code: 9ferno

Download patch

ref: 5c30140aa4d842dbb700cd6c8b9d7296fd91da84
parent: 72db5b394c55a4fecc11f7af3faad04b5bc755ba
author: joe9 <joe9mail@gmail.com>
date: Fri Jul 16 19:27:44 EDT 2021

moving inferno os/boot away

diff: cannot open a/os/boot/arm1110//null: file does not exist: 'a/os/boot/arm1110//null' diff: cannot open a/os/boot/libflate//null: file does not exist: 'a/os/boot/libflate//null' diff: cannot open a/os/boot/mpc//null: file does not exist: 'a/os/boot/mpc//null' diff: cannot open a/os/boot/pc//null: file does not exist: 'a/os/boot/pc//null' diff: cannot open a/os/boot/puma//null: file does not exist: 'a/os/boot/puma//null' diff: cannot open a/os/boot/rpcg//null: file does not exist: 'a/os/boot/rpcg//null' diff: cannot open a/os/boot//null: file does not exist: 'a/os/boot//null' diff: cannot open b/os/boot.original/arm1110//null: file does not exist: 'b/os/boot.original/arm1110//null' diff: cannot open b/os/boot.original/libflate//null: file does not exist: 'b/os/boot.original/libflate//null' diff: cannot open b/os/boot.original/mpc//null: file does not exist: 'b/os/boot.original/mpc//null' diff: cannot open b/os/boot.original/pc//null: file does not exist: 'b/os/boot.original/pc//null' diff: cannot open b/os/boot.original/puma//null: file does not exist: 'b/os/boot.original/puma//null' diff: cannot open b/os/boot.original/rpcg//null: file does not exist: 'b/os/boot.original/rpcg//null' diff: cannot open b/os/boot.original//null: file does not exist: 'b/os/boot.original//null'
--- a/os/boot/README
+++ /dev/null
@@ -1,33 +1,0 @@
-Often the devices we use now come with some
-form of bootstrap (often annoyingly complicated,
-which gets in the way).  Older boards were sometimes
-bare, and we had to provide something (often annoyingly
-complicated...).  On the PC it's currently helpful to
-have something that can boot from disc or ether;
-since it's a thankless task to write such a thing, we
-use Plan 9's, and thank its authors.
-
-The current scheme on newer devices is to have a simple
-program that can put a stripped-down Inferno kernel into
-flash, and use that to boot from other devices (including over the net)
-as required during development.
-
-There are two distinct models for bootstrap in this directory.
-
-	Model I
-
-Each member of the first model is represented by a self-contained directory.
-They are derived from various ages of Plan 9's /sys/src/boot/pc.
-
-arm1110	arm	a prefix to a gzip'd kernel to decompress it (runs after basic bootloader)
-pc	386	pc-specific bootstrap essentially identical to current Plan 9
-		and covered by the Lucent Public License; it uses
-libflate	-	zlib-style inflate/deflate library
-mpc	power	PowerPC bootstrap for FADS board derived from an older version
-		of Plan 9 but covered by our Inferno licence (because it came with Inferno)
-puma	arm	SA110 bootstrap for Teralogics Puma, also covered by the Inferno licence
-
-	Model II
-omap	purpose-built bootstrap for the OMAP processor
-
-Not all of these are being distributed.
--- a/os/boot/arm1110/Mk
+++ /dev/null
@@ -1,8 +1,0 @@
-#!/bin/rc
-rfork ne
-ROOT=/usr/inferno
-fn cd
-NPROC=3
-path=(/usr/inferno/Plan9/$cputype/bin $path)
-#bind /usr/inferno/mkconfig.dist /usr/inferno/mkconfig
-exec mk $*
--- a/os/boot/arm1110/dat.h
+++ /dev/null
@@ -1,1 +1,0 @@
-/* deliberately empty */
--- a/os/boot/arm1110/donprint.c
+++ /dev/null
@@ -1,332 +1,0 @@
-#include	"u.h"
-#include	"lib.h"
-
-#define	PTR	sizeof(char*)
-#define	SHORT	sizeof(int)
-#define	INT	sizeof(int)
-#define	LONG	sizeof(long)
-#define	IDIGIT	30
-#define	MAXCON	30
-
-#define	FLONG	(1<<0)
-#define	FSHORT	(1<<1)
-#define	FUNSIGN	(1<<2)
-
-typedef struct Op	Op;
-struct Op
-{
-	char	*p;
-	char	*ep;
-	void	*argp;
-	int	f1;
-	int	f2;
-	int	f3;
-};
-
-static	int	noconv(Op*);
-static	int	cconv(Op*);
-static	int	dconv(Op*);
-static	int	hconv(Op*);
-static	int	lconv(Op*);
-static	int	oconv(Op*);
-static	int	sconv(Op*);
-static	int	uconv(Op*);
-static	int	xconv(Op*);
-static	int	Xconv(Op*);
-static	int	percent(Op*);
-
-static
-int	(*fmtconv[MAXCON])(Op*) =
-{
-	noconv,
-	cconv, dconv, hconv, lconv,
-	oconv, sconv, uconv, xconv,
-	Xconv, percent,
-};
-static
-char	fmtindex[128] =
-{
-	['c'] 1,
-	['d'] 2,
-	['h'] 3,
-	['l'] 4,
-	['o'] 5,
-	['s'] 6,
-	['u'] 7,
-	['x'] 8,
-	['X'] 9,
-	['%'] 10,
-};
-
-static	int	convcount  = { 11 };
-static	int	ucase;
-
-static void
-PUT(Op *o, int c)
-{
-	static int pos;
-	int opos;
-
-	if(c == '\t'){
-		opos = pos;
-		pos = (opos+8) & ~7;
-		while(opos++ < pos && o->p < o->ep)
-			*o->p++ = ' ';
-		return;
-	}
-	if(o->p < o->ep){
-		*o->p++ = c;
-		pos++;
-	}
-	if(c == '\n')
-		pos = 0;
-}
-
-int
-fmtinstall(char c, int (*f)(Op*))
-{
-
-	c &= 0177;
-	if(fmtindex[c] == 0) {
-		if(convcount >= MAXCON)
-			return 1;
-		fmtindex[c] = convcount++;
-	}
-	fmtconv[fmtindex[c]] = f;
-	return 0;
-}
-
-char*
-donprint(char *p, char *ep, char *fmt, void *argp)
-{
-	int sf1, c;
-	Op o;
-
-	o.p = p;
-	o.ep = ep;
-	o.argp = argp;
-
-loop:
-	c = *fmt++;
-	if(c != '%') {
-		if(c == 0) {
-			if(o.p < o.ep)
-				*o.p = 0;
-			return o.p;
-		}
-		PUT(&o, c);
-		goto loop;
-	}
-	o.f1 = 0;
-	o.f2 = -1;
-	o.f3 = 0;
-	c = *fmt++;
-	sf1 = 0;
-	if(c == '-') {
-		sf1 = 1;
-		c = *fmt++;
-	}
-	while(c >= '0' && c <= '9') {
-		o.f1 = o.f1*10 + c-'0';
-		c = *fmt++;
-	}
-	if(sf1)
-		o.f1 = -o.f1;
-	if(c != '.')
-		goto l1;
-	c = *fmt++;
-	while(c >= '0' && c <= '9') {
-		if(o.f2 < 0)
-			o.f2 = 0;
-		o.f2 = o.f2*10 + c-'0';
-		c = *fmt++;
-	}
-l1:
-	if(c == 0)
-		fmt--;
-	c = (*fmtconv[fmtindex[c&0177]])(&o);
-	if(c < 0) {
-		o.f3 |= -c;
-		c = *fmt++;
-		goto l1;
-	}
-	o.argp = (char*)o.argp + c;
-	goto loop;
-}
-
-void
-strconv(char *o, Op *op, int f1, int f2)
-{
-	int n, c;
-	char *p;
-
-	n = strlen(o);
-	if(f1 >= 0)
-		while(n < f1) {
-			PUT(op, ' ');
-			n++;
-		}
-	for(p=o; c = *p++;)
-		if(f2 != 0) {
-			PUT(op, c);
-			f2--;
-		}
-	if(f1 < 0) {
-		f1 = -f1;
-		while(n < f1) {
-			PUT(op, ' ');
-			n++;
-		}
-	}
-}
-
-int
-numbconv(Op *op, int base)
-{
-	char b[IDIGIT];
-	int i, f, n, r;
-	long v;
-	short h;
-
-	f = 0;
-	switch(op->f3 & (FLONG|FSHORT|FUNSIGN)) {
-	case FLONG:
-		v = *(long*)op->argp;
-		r = LONG;
-		break;
-
-	case FUNSIGN|FLONG:
-		v = *(ulong*)op->argp;
-		r = LONG;
-		break;
-
-	case FSHORT:
-		h = *(int*)op->argp;
-		v = h;
-		r = SHORT;
-		break;
-
-	case FUNSIGN|FSHORT:
-		h = *(int*)op->argp;
-		v = (ushort)h;
-		r = SHORT;
-		break;
-
-	default:
-		v = *(int*)op->argp;
-		r = INT;
-		break;
-
-	case FUNSIGN:
-		v = *(unsigned*)op->argp;
-		r = INT;
-		break;
-	}
-	if(!(op->f3 & FUNSIGN) && v < 0) {
-		v = -v;
-		f = 1;
-	}
-	b[IDIGIT-1] = 0;
-	for(i = IDIGIT-2;; i--) {
-		n = (ulong)v % base;
-		n += '0';
-		if(n > '9'){
-			n += 'a' - ('9'+1);
-			if(ucase)
-				n += 'A'-'a';
-		}
-		b[i] = n;
-		if(i < 2)
-			break;
-		v = (ulong)v / base;
-		if(op->f2 >= 0 && i >= IDIGIT-op->f2)
-			continue;
-		if(v <= 0)
-			break;
-	}
-	if(f)
-		b[--i] = '-';
-	strconv(b+i, op, op->f1, -1);
-	return r;
-}
-
-static	int
-noconv(Op *op)
-{
-
-	strconv("***", op, 0, -1);
-	return 0;
-}
-
-static	int
-cconv(Op *op)
-{
-	char b[2];
-
-	b[0] = *(int*)op->argp;
-	b[1] = 0;
-	strconv(b, op, op->f1, -1);
-	return INT;
-}
-
-static	int
-dconv(Op *op)
-{
-	return numbconv(op, 10);
-}
-
-static	int
-hconv(Op*)
-{
-	return -FSHORT;
-}
-
-static	int
-lconv(Op*)
-{
-	return -FLONG;
-}
-
-static	int
-oconv(Op *op)
-{
-	return numbconv(op, 8);
-}
-
-static	int
-sconv(Op *op)
-{
-	strconv(*(char**)op->argp, op, op->f1, op->f2);
-	return PTR;
-}
-
-static	int
-uconv(Op*)
-{
-	return -FUNSIGN;
-}
-
-static	int
-xconv(Op *op)
-{
-	return numbconv(op, 16);
-}
-
-static	int
-Xconv(Op *op)
-{
-	int r;
-
-	ucase = 1;
-	r = numbconv(op, 16);
-	ucase = 0;
-	return r;
-}
-
-static	int
-percent(Op *op)
-{
-
-	PUT(op, '%');
-	return 0;
-}
--- a/os/boot/arm1110/fns.h
+++ /dev/null
@@ -1,7 +1,0 @@
-/*
- *  functions defined locally
- */
-extern int	gunzip(uchar *out, int outn, uchar *in, int inn);
-extern void	delay(int ms);
-extern void	serialputs(char *str, int n);
-extern void	draincache(void);
--- a/os/boot/arm1110/il.s
+++ /dev/null
@@ -1,99 +1,0 @@
-#include "mem.h"
-/*
- *  Entered here from Compaq's bootldr.  First relocate to
- *  the location we're linked for and then copy back the
- *  decompressed kernel.
- *
- *  All 
- */
-TEXT _start(SB), $-4
-	MOVW	$setR12(SB), R12		/* load the SB */
-	MOVW	$1, R0		/* dance to make 5l think that the magic */
-	MOVW	$1, R1		/* numbers in WORDs below are being used */
-	CMP.S	R0, R1		/* and to align them to where bootldr wants */
-	BEQ	_start2
-	WORD	$0x016f2818	/* magic number to say we are a kernel */
-	WORD	$0xc0008000	/* entry point address */
-	WORD	$0		/* size?, or end of data? */
-
-_start2:
-
-	/* SVC mode, interrupts disabled */
-	MOVW	$(PsrDirq|PsrDfiq|PsrMsvc), R1
-	MOVW	R1, CPSR
-
-	/* disable the MMU */
-	MOVW	$0x130, R1
-	MCR     CpMMU, 0, R1, C(CpControl), C(0x0)
-
-	/* enable caches */
-	MRC	CpMMU, 0, R0, C(CpControl), C(0x0)
-	ORR	$(CpCdcache|CpCicache|CpCwb), R0
-	MCR     CpMMU, 0, R0, C(CpControl), C(0x0)
-
-	/* flush caches */
-	MCR	CpMMU, 0, R0, C(CpCacheFlush), C(0x7), 0
-	/* drain prefetch */
-	MOVW	R0,R0						
-	MOVW	R0,R0
-	MOVW	R0,R0
-	MOVW	R0,R0
-
-	/* drain write buffer */
-	MCR	CpMMU, 0, R0, C(CpCacheFlush), C(0xa), 4
-
-	/* relocate to where we expect to be */
-	MOVW	$(FLATESIZE),R3
-	MOVW	$0xC0008000,R1
-	MOVW	$0xC0200000,R2
-	ADD	R1,R3
-_relloop:
-	MOVW	(R1),R0
-	MOVW	R0,(R2)
-	ADD	$4,R1
-	ADD	$4,R2
-	CMP.S	R1,R3
-	BNE	_relloop
-
-	MOVW	$(MACHADDR+BY2PG), R13		/* stack */
-	SUB	$4, R13				/* link */
-
-	/* jump to where we've been relocated */
-	MOVW	$_relocated(SB),R15
-
-TEXT _relocated(SB),$-4
-	BL	main(SB)
-	BL	exit(SB)
-	/* we shouldn't get here */
-_mainloop:
-	B	_mainloop
-	BL	_div(SB)			/* hack to get _div etc loaded */
-
-TEXT mypc(SB),$-4
-	MOVW	R14,R0
-	RET
-
-TEXT draincache(SB),$-4
-	/* write back any dirty data */
-	MOVW	$0xe0000000,R0
-	ADD	$(8*1024),R0,R1
-_cfloop:
-	MOVW.P	32(R0),R2
-	CMP.S	R0,R1
-	BNE	_cfloop
-	
-	/* drain write buffer and invalidate i&d cache contents */
-	MCR	CpMMU, 0, R0, C(CpCacheFlush), C(0xa), 4
-	MCR	CpMMU, 0, R0, C(CpCacheFlush), C(0x7), 0
-
-	/* drain prefetch */
-	MOVW	R0,R0						
-	MOVW	R0,R0
-	MOVW	R0,R0
-	MOVW	R0,R0
-
-	/* disable caches */
-	MRC	CpMMU, 0, R0, C(CpControl), C(0x0)
-	BIC	$(CpCdcache|CpCicache|CpCwb), R0
-	MCR     CpMMU, 0, R0, C(CpControl), C(0x0)
-	RET
--- a/os/boot/arm1110/imain.c
+++ /dev/null
@@ -1,48 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "fns.h"
-#include "dat.h"
-#include "mem.h"
-
-void
-main(void)
-{
-	void (*f)(void);
-	ulong *kernel;
-
-	print("inflating kernel\n");
-
-	kernel = (ulong*)(0xc0200000+20*1024);
-	if(gunzip((uchar*)0xc0008000, 2*1024*1024, (uchar*)kernel, FLATESIZE) > 0){
-		f = (void (*)(void))0xc0008010;
-		draincache();
-	} else {
-		print("inflation failed\n");
-		f = nil;
-	}
-	(*f)();
-}
-
-void
-exit(void)
-{
-
-	void (*f)(void);
-
-	delay(1000);
-
-	print("it's a wonderful day to die\n");
-	f = nil;
-	(*f)();
-}
-
-void
-delay(int ms)
-{
-	int i;
-
-	while(ms-- > 0){
-		for(i = 0; i < 1000; i++)
-			;
-	}
-}
--- a/os/boot/arm1110/inflate.c
+++ /dev/null
@@ -1,208 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-#include <flate.h>
-
-typedef struct Biobuf	Biobuf;
-
-struct Biobuf
-{
-	uchar *bp;
-	uchar *p;
-	uchar *ep;
-};
-
-static int	header(Biobuf*);
-static int	trailer(Biobuf*, Biobuf*);
-static int	getc(void*);
-static ulong	offset(Biobuf*);
-static int	crcwrite(void *out, void *buf, int n);
-static ulong	get4(Biobuf *b);
-static ulong	Boffset(Biobuf *bp);
-
-/* GZIP flags */
-enum {
-	Ftext=		(1<<0),
-	Fhcrc=		(1<<1),
-	Fextra=		(1<<2),
-	Fname=		(1<<3),
-	Fcomment=	(1<<4),
-
-	GZCRCPOLY	= 0xedb88320UL,
-};
-
-static ulong	*crctab;
-static ulong	crc;
-
-int
-gunzip(uchar *out, int outn, uchar *in, int inn)
-{
-	Biobuf bin, bout;
-	int err;
-
-	crc = 0;
-	crctab = mkcrctab(GZCRCPOLY);
-	err = inflateinit();
-	if(err != FlateOk)
-		print("inflateinit failed: %s\n", flateerr(err));
-
-	bin.bp = bin.p = in;
-	bin.ep = in+inn;
-	bout.bp = bout.p = out;
-	bout.ep = out+outn;
-
-	err = header(&bin);
-	if(err != FlateOk)
-		return err;
-
-	err = inflate(&bout, crcwrite, &bin, getc);
-	if(err != FlateOk)
-		print("inflate failed: %s\n", flateerr(err));
-
-	err = trailer(&bout, &bin);
-	if(err != FlateOk)
-		return err;
-
-	return Boffset(&bout);
-}
-
-static int
-header(Biobuf *bin)
-{
-	int i, flag;
-
-	if(getc(bin) != 0x1f || getc(bin) != 0x8b){
-		print("bad magic\n");
-		return FlateCorrupted;
-	}
-	if(getc(bin) != 8){
-		print("unknown compression type\n");
-		return FlateCorrupted;
-	}
-	
-	flag = getc(bin);
-	
-	/* mod time */
-	get4(bin);
-	
-	/* extra flags */
-	getc(bin);
-	
-	/* OS type */
-	getc(bin);
-
-	if(flag & Fextra)
-		for(i=getc(bin); i>0; i--)
-			getc(bin);
-	
-	/* name */
-	if(flag&Fname)
-		while(getc(bin) != 0)
-			;
-
-	/* comment */
-	if(flag&Fcomment)
-		while(getc(bin) != 0)
-			;
-
-	/* crc16 */
-	if(flag&Fhcrc) {
-		getc(bin);
-		getc(bin);
-	}
-		
-	return FlateOk;
-}
-
-static int
-trailer(Biobuf *bout, Biobuf *bin)
-{
-	/* crc32 */
-	ulong x;
-
-	x = get4(bin);
-	if(crc != x){
-		print("crc mismatch %lux %lux\n", crc, x);
-		return FlateCorrupted;
-	}
-
-	/* length */
-	if(get4(bin) != Boffset(bout)){
-		print("bad output len\n");
-		return FlateCorrupted;
-	}
-	return FlateOk;
-}
-
-static ulong
-get4(Biobuf *b)
-{
-	ulong v;
-	int i, c;
-
-	v = 0;
-	for(i = 0; i < 4; i++){
-		c = getc(b);
-		v |= c << (i * 8);
-	}
-	return v;
-}
-
-static int
-getc(void *in)
-{
-	Biobuf *bp = in;
-
-	if((bp->p - bp->bp) % 10000 == 0)
-		print(".");
-	if(bp->p >= bp->ep)
-		return -1;
-	return *bp->p++;
-}
-
-static ulong
-Boffset(Biobuf *bp)
-{
-	return bp->p - bp->bp;
-}
-
-static int
-crcwrite(void *out, void *buf, int n)
-{
-	Biobuf *bp;
-
-	crc = blockcrc(crctab, crc, buf, n);
-	bp = out;
-	if(n > bp->ep-bp->p)
-		n = bp->ep-bp->p;
-	memmove(bp->p, buf, n);
-	bp->p += n;
-	return n;
-}
-
-#undef malloc
-#undef free
-
-static ulong ibrkp = ~0;
-
-void *
-malloc(ulong n)
-{
-	ulong rv;
-
-	if(ibrkp == ~0)
-		ibrkp = ((ulong)end)+1024*1024;
-	n = (n+3)>>2;
-	n <<= 2;
-	rv = ibrkp;
-	ibrkp += n;
-	return (void*)rv;
-}
-
-void
-free(void *)
-{
-}
--- a/os/boot/arm1110/io.h
+++ /dev/null
@@ -1,261 +1,0 @@
-/*
- *  Definitions for IO devices.  Used only in C.
- */
-
-enum
-{
-	/* hardware counter frequency */
-	ClockFreq=	3686400,
-};
-
-/*
- *  IRQ's defined by SA1100
- */
-enum
-{
-	IRQgpio0=	0,
-	IRQgpio1=	1,
-	IRQgpio2=	2,
-	IRQgpio3=	3,
-	IRQgpio4=	4,
-	IRQgpio5=	5,
-	IRQgpio6=	6,
-	IRQgpio7=	7,
-	IRQgpio8=	8,
-	IRQgpio9=	9,
-	IRQgpio10=	10,
-	IRQgpiohi=	11,
-	IRQlcd=		12,
-	IRQudc=		13,
-	IRQuart1b=	15,
-	IRQuart2=	16,
-	IRQuart3=	17,
-	IRQmcp=		18,
-	IRQssp=		19,
-	IRQdma0=	20,
-	IRQdma1=	21,
-	IRQdma2=	22,
-	IRQdma3=	23,
-	IRQdma4=	24,
-	IRQdma5=	25,
-	IRQtimer0=	26,
-	IRQtimer1=	27,
-	IRQtimer2=	28,
-	IRQtimer3=	29,
-	IRQsecond=	30,
-	IRQrtc=		31,
-};
-
-/*
- *  GPIO lines (signal names from compaq document).  _i indicates input
- *  and _o output.
- */
-enum
-{
-	GPIO_PWR_ON_i=		1<<0,	/* power button */
-	GPIO_UP_IRQ_i=		1<<1,	/* microcontroller interrupts */
-	GPIO_LDD8_o=		1<<2,	/* LCD data 8-15 */
-	GPIO_LDD9_o=		1<<3,
-	GPIO_LDD10_o=		1<<4,
-	GPIO_LDD11_o=		1<<5,
-	GPIO_LDD12_o=		1<<6,
-	GPIO_LDD13_o=		1<<7,
-	GPIO_LDD14_o=		1<<8,
-	GPIO_LDD15_o=		1<<9,
-	GPIO_CARD_IND1_i=	1<<10,	/* card inserted in PCMCIA socket 1 */
-	GPIO_CARD_IRQ1_i=	1<<11,	/* PCMCIA socket 1 interrupt */
-	GPIO_CLK_SET0_o=	1<<12,	/* clock selects for audio codec */
-	GPIO_CLK_SET1_o=	1<<13,
-	GPIO_L3_SDA_io=		1<<14,	/* UDA1341 interface */
-	GPIO_L3_MODE_o=		1<<15,
-	GPIO_L3_SCLK_o=		1<<16,
-	GPIO_CARD_IND0_i=	1<<17,	/* card inserted in PCMCIA socket 0 */
-	GPIO_KEY_ACT_i=		1<<18,	/* hot key from cradle */
-	GPIO_SYS_CLK_i=		1<<19,	/* clock from codec */
-	GPIO_BAT_FAULT_i=	1<<20,	/* battery fault */
-	GPIO_CARD_IRQ0_i=	1<<21,	/* PCMCIA socket 0 interrupt */
-	GPIO_LOCK_i=		1<<22,	/* expansion pack lock/unlock */
-	GPIO_COM_DCD_i=		1<<23,	/* DCD from UART3 */
-	GPIO_OPT_IRQ_i=		1<<24,	/* expansion pack IRQ */
-	GPIO_COM_CTS_i=		1<<25,	/* CTS from UART3 */
-	GPIO_COM_RTS_o=		1<<26,	/* RTS to UART3 */
-	GPIO_OPT_IND_i=		1<<27,	/* expansion pack inserted */
-
-/* Peripheral Unit GPIO pin assignments: alternate functions */
-	GPIO_SSP_TXD_o=		1<<10,	/* SSP Transmit Data */
-	GPIO_SSP_RXD_i=		1<<11,	/* SSP Receive Data */
-	GPIO_SSP_SCLK_o=	1<<12,	/* SSP Sample CLocK */
-	GPIO_SSP_SFRM_o=	1<<13,	/* SSP Sample FRaMe */
-	/* ser. port 1: */
-	GPIO_UART_TXD_o=	1<<14,	/* UART Transmit Data */
-	GPIO_UART_RXD_i=	1<<15,	/* UART Receive Data */
-	GPIO_SDLC_SCLK_io=	1<<16,	/* SDLC Sample CLocK (I/O) */
-	GPIO_SDLC_AAF_o=	1<<17,	/* SDLC Abort After Frame */
-	GPIO_UART_SCLK1_i=	1<<18,	/* UART Sample CLocK 1 */
-	/* ser. port 4: */
-	GPIO_SSP_CLK_i=		1<<19,	/* SSP external CLocK */
-	/* ser. port 3: */
-	GPIO_UART_SCLK3_i=	1<<20,	/* UART Sample CLocK 3 */
-	/* ser. port 4: */
-	GPIO_MCP_CLK_i=		1<<21,	/* MCP CLocK */
-	/* test controller: */
-	GPIO_TIC_ACK_o=		1<<21,	/* TIC ACKnowledge */
-	GPIO_MBGNT_o=		1<<21,	/* Memory Bus GraNT */
-	GPIO_TREQA_i=		1<<22,	/* TIC REQuest A */
-	GPIO_MBREQ_i=		1<<22,	/* Memory Bus REQuest */
-	GPIO_TREQB_i=		1<<23,	/* TIC REQuest B */
-	GPIO_1Hz_o=			1<<25,	/* 1 Hz clock */
-	GPIO_RCLK_o=		1<<26,	/* internal (R) CLocK (O, fcpu/2) */
-	GPIO_32_768kHz_o=	1<<27,	/* 32.768 kHz clock (O, RTC) */
-};
-
-/*
- *  types of interrupts
- */
-enum
-{
-	GPIOrising,
-	GPIOfalling,
-	GPIOboth,
-	IRQ,
-};
-
-/* hardware registers */
-typedef struct Uartregs Uartregs;
-struct Uartregs
-{
-	ulong	ctl[4];
-	ulong	dummya;
-	ulong	data;
-	ulong	dummyb;
-	ulong	status[2];
-};
-Uartregs *uart3regs;
-
-/* general purpose I/O lines control registers */
-typedef struct GPIOregs GPIOregs;
-struct GPIOregs
-{
-	ulong	level;		/* 1 == high */
-	ulong	direction;	/* 1 == output */
-	ulong	set;		/* a 1 sets the bit, 0 leaves it alone */
-	ulong	clear;		/* a 1 clears the bit, 0 leaves it alone */
-	ulong	rising;		/* rising edge detect enable */
-	ulong	falling;	/* falling edge detect enable */
-	ulong	edgestatus;	/* writing a 1 bit clears */
-	ulong	altfunc;	/* turn on alternate function for any set bits */
-};
-
-extern GPIOregs *gpioregs;
-
-/* extra general purpose I/O bits, output only */
-enum
-{
-	EGPIO_prog_flash=	1<<0,
-	EGPIO_pcmcia_reset=	1<<1,
-	EGPIO_exppack_reset=	1<<2,
-	EGPIO_codec_reset=	1<<3,
-	EGPIO_exp_nvram_power=	1<<4,
-	EGPIO_exp_full_power=	1<<5,
-	EGPIO_lcd_3v=		1<<6,
-	EGPIO_rs232_power=	1<<7,
-	EGPIO_lcd_ic_power=	1<<8,
-	EGPIO_ir_power=		1<<9,
-	EGPIO_audio_power=	1<<10,
-	EGPIO_audio_ic_power=	1<<11,
-	EGPIO_audio_mute=	1<<12,
-	EGPIO_fir=		1<<13,	/* not set is sir */
-	EGPIO_lcd_5v=		1<<14,
-	EGPIO_lcd_9v=		1<<15,
-};
-extern ulong *egpioreg;
-
-/* Peripheral pin controller registers */
-typedef struct PPCregs PPCregs;
-struct PPCregs {
-	ulong	direction;
-	ulong	state;
-	ulong	assignment;
-	ulong	sleepdir;
-	ulong	flags;
-};
-extern PPCregs *ppcregs;
-
-/* Synchronous Serial Port controller registers */
-typedef struct SSPregs SSPregs;
-struct SSPregs {
-	ulong	control0;
-	ulong	control1;
-	ulong	dummy0;
-	ulong	data;
-	ulong	dummy1;
-	ulong	status;
-};
-extern SSPregs *sspregs;
-
-/* Multimedia Communications Port controller registers */
-typedef struct MCPregs MCPregs;
-struct MCPregs {
-	ulong	control0;
-	ulong	reserved0;
-	ulong	data0;
-	ulong	data1;
-	ulong	data2;
-	ulong	reserved1;
-	ulong	status;
-	ulong	reserved[11];
-	ulong	control1;
-};
-extern MCPregs *mcpregs;
-
-/*
- *  memory configuration
- */
-enum
-{
-	/* bit shifts for pcmcia access time counters */
-	MECR_io0=	0,
-	MECR_attr0=	5,
-	MECR_mem0=	10,
-	MECR_fast0=	11,
-	MECR_io1=	MECR_io0+16,
-	MECR_attr1=	MECR_attr0+16,
-	MECR_mem1=	MECR_mem0+16,
-	MECR_fast1=	MECR_fast0+16,
-};
-
-typedef struct MemConfRegs MemConfRegs;
-struct MemConfRegs
-{
-	ulong	mdcnfg;		/* dram */
-	ulong	mdcas00;	/* dram banks 0/1 */
-	ulong	mdcas01;
-	ulong	mdcas02;
-	ulong	msc0;		/* static */
-	ulong	msc1;
-	ulong	mecr;		/* pcmcia */
-	ulong	mdrefr;		/* dram refresh */
-	ulong	mdcas20;	/* dram banks 2/3 */
-	ulong	mdcas21;
-	ulong	mdcas22;
-	ulong	msc2;		/* static */
-	ulong	smcnfg;		/* SMROM config */
-};
-extern MemConfRegs *memconfregs;
-
-/*
- *  power management
- */
-typedef struct PowerRegs PowerRegs;
-struct PowerRegs
-{
-	ulong	pmcr;	/* Power manager control register */
-	ulong	pssr;	/* Power manager sleep status register */
-	ulong	pspr;	/* Power manager scratch pad register */
-	ulong	pwer;	/* Power manager wakeup enable register */
-	ulong	pcfr;	/* Power manager general configuration register */
-	ulong	ppcr;	/* Power manager PPL configuration register */
-	ulong	pgsr;	/* Power manager GPIO sleep state register */
-	ulong	posr;	/* Power manager oscillator status register */
-};
-extern PowerRegs *powerregs;
--- a/os/boot/arm1110/l.s
+++ /dev/null
@@ -1,454 +1,0 @@
-#include "mem.h"
-
-/*
- * Entered here from Compaq's bootldr with MMU disabled.
- */
-TEXT _start(SB), $-4
-	MOVW	$setR12(SB), R12		/* load the SB */
-_main:
-	/* SVC mode, interrupts disabled */
-	MOVW	$(PsrDirq|PsrDfiq|PsrMsvc), R1
-	MOVW	R1, CPSR
-
-	/* disable the MMU */
-	MOVW	$0x130, R1
-	MCR     CpMMU, 0, R1, C(CpControl), C(0x0)
-
-	/* flush caches */
-	MCR	CpMMU, 0, R0, C(CpCacheFlush), C(0x7), 0
-	/* drain prefetch */
-	MOVW	R0,R0						
-	MOVW	R0,R0
-	MOVW	R0,R0
-	MOVW	R0,R0
-
-	/* drain write buffer */
-	MCR	CpMMU, 0, R0, C(CpCacheFlush), C(0xa), 4
-
-	MOVW	$(MACHADDR+BY2PG), R13		/* stack */
-	SUB	$4, R13				/* link */
-	BL	main(SB)
-	BL	exit(SB)
-	/* we shouldn't get here */
-_mainloop:
-	B	_mainloop
-	BL	_div(SB)			/* hack to get _div etc loaded */
-
-/* flush tlb's */
-TEXT mmuinvalidate(SB), $-4
-	MCR	CpMMU, 0, R0, C(CpTLBFlush), C(0x7)
-	RET
-
-/* flush tlb's */
-TEXT mmuinvalidateaddr(SB), $-4
-	MCR	CpMMU, 0, R0, C(CpTLBFlush), C(0x6), 1
-	RET
-
-/* write back and invalidate i and d caches */
-TEXT cacheflush(SB), $-4
-	/* write back any dirty data */
-	MOVW	$0xe0000000,R0
-	ADD	$(8*1024),R0,R1
-_cfloop:
-	MOVW.P	32(R0),R2
-	CMP.S	R0,R1
-	BNE	_cfloop
-	
-	/* drain write buffer and invalidate i&d cache contents */
-	MCR	CpMMU, 0, R0, C(CpCacheFlush), C(0xa), 4
-	MCR	CpMMU, 0, R0, C(CpCacheFlush), C(0x7), 0
-
-	/* drain prefetch */
-	MOVW	R0,R0						
-	MOVW	R0,R0
-	MOVW	R0,R0
-	MOVW	R0,R0
-	RET
-
-/* write back d cache */
-TEXT cachewb(SB), $-4
-	/* write back any dirty data */
-_cachewb:
-	MOVW	$0xe0000000,R0
-	ADD	$(8*1024),R0,R1
-_cwbloop:
-	MOVW.P	32(R0),R2
-	CMP.S	R0,R1
-	BNE	_cwbloop
-	
-	/* drain write buffer */
-	MCR	CpMMU, 0, R0, C(CpCacheFlush), C(0xa), 4
-	RET
-
-/* write back a single cache line */
-TEXT cachewbaddr(SB), $-4
-	BIC	$31,R0
-	MCR	CpMMU, 0, R0, C(CpCacheFlush), C(0xa), 1
-	B	_wbflush
-
-/* write back a region of cache lines */
-TEXT cachewbregion(SB), $-4
-	MOVW	4(FP),R1
-	CMP.S	$(4*1024),R1
-	BGT	_cachewb
-	ADD	R0,R1
-	BIC	$31,R0
-_cwbrloop:
-	MCR	CpMMU, 0, R0, C(CpCacheFlush), C(0xa), 1
-	ADD	$32,R0
-	CMP.S	R0,R1
-	BGT	_cwbrloop
-	B	_wbflush
-
-/* invalidate the dcache */
-TEXT dcacheinvalidate(SB), $-4
-	MCR	CpMMU, 0, R0, C(CpCacheFlush), C(0x6)
-	RET
-
-/* invalidate the icache */
-TEXT icacheinvalidate(SB), $-4
-	MCR	CpMMU, 0, R0, C(CpCacheFlush), C(0x9)
-	RET
-
-/* drain write buffer */
-TEXT wbflush(SB), $-4
-_wbflush:
-	MCR	CpMMU, 0, R0, C(CpCacheFlush), C(0xa), 4
-	RET
-
-/* return cpu id */
-TEXT getcpuid(SB), $-4
-	MRC	CpMMU, 0, R0, C(CpCPUID), C(0x0)
-	RET
-
-/* return fault status */
-TEXT getfsr(SB), $-4
-	MRC	CpMMU, 0, R0, C(CpFSR), C(0x0)
-	RET
-
-/* return fault address */
-TEXT getfar(SB), $-4
-	MRC	CpMMU, 0, R0, C(CpFAR), C(0x0)
-	RET
-
-/* return fault address */
-TEXT putfar(SB), $-4
-	MRC	CpMMU, 0, R0, C(CpFAR), C(0x0)
-	RET
-
-/* set the translation table base */
-TEXT putttb(SB), $-4
-	MCR	CpMMU, 0, R0, C(CpTTB), C(0x0)
-	RET
-
-/*
- *  enable mmu, i and d caches
- */
-TEXT mmuenable(SB), $-4
-	MRC	CpMMU, 0, R0, C(CpControl), C(0x0)
-	ORR	$(CpCmmuena|CpCdcache|CpCicache|CpCwb), R0
-	MCR     CpMMU, 0, R0, C(CpControl), C(0x0)
-	RET
-
-TEXT mmudisable(SB), $-4
-	MRC	CpMMU, 0, R0, C(CpControl), C(0x0)
-	BIC	$(CpCmmuena|CpCdcache|CpCicache|CpCwb|CpCvivec), R0
-	MCR     CpMMU, 0, R0, C(CpControl), C(0x0)
-	RET
-
-/*
- *  use exception vectors at 0xffff0000
- */
-TEXT mappedIvecEnable(SB), $-4
-	MRC	CpMMU, 0, R0, C(CpControl), C(0x0)
-	ORR	$(CpCvivec), R0
-	MCR     CpMMU, 0, R0, C(CpControl), C(0x0)
-	RET
-TEXT mappedIvecDisable(SB), $-4
-	MRC	CpMMU, 0, R0, C(CpControl), C(0x0)
-	BIC	$(CpCvivec), R0
-	MCR     CpMMU, 0, R0, C(CpControl), C(0x0)
-	RET
-
-/* set the translation table base */
-TEXT putdac(SB), $-4
-	MCR	CpMMU, 0, R0, C(CpDAC), C(0x0)
-	RET
-
-/* set address translation pid */
-TEXT putpid(SB), $-4
-	MCR	CpMMU, 0, R0, C(CpPID), C(0x0)
-	RET
-
-/*
- *  set the stack value for the mode passed in R0
- */
-TEXT setr13(SB), $-4
-	MOVW	4(FP), R1
-
-	MOVW	CPSR, R2
-	BIC	$PsrMask, R2, R3
-	ORR	R0, R3
-	MOVW	R3, CPSR
-
-	MOVW	R13, R0
-	MOVW	R1, R13
-
-	MOVW	R2, CPSR
-	RET
-
-/*
- *  exception vectors, copied by trapinit() to somewhere useful
- */
-
-TEXT vectors(SB), $-4
-	MOVW	0x18(R15), R15			/* reset */
-	MOVW	0x18(R15), R15			/* undefined */
-	MOVW	0x18(R15), R15			/* SWI */
-	MOVW	0x18(R15), R15			/* prefetch abort */
-	MOVW	0x18(R15), R15			/* data abort */
-	MOVW	0x18(R15), R15			/* reserved */
-	MOVW	0x18(R15), R15			/* IRQ */
-	MOVW	0x18(R15), R15			/* FIQ */
-
-TEXT vtable(SB), $-4
-	WORD	$_vsvc(SB)			/* reset, in svc mode already */
-	WORD	$_vund(SB)			/* undefined, switch to svc mode */
-	WORD	$_vsvc(SB)			/* swi, in svc mode already */
-	WORD	$_vpabt(SB)			/* prefetch abort, switch to svc mode */
-	WORD	$_vdabt(SB)			/* data abort, switch to svc mode */
-	WORD	$_vsvc(SB)			/* reserved */
-	WORD	$_virq(SB)			/* IRQ, switch to svc mode */
-	WORD	$_vfiq(SB)			/* FIQ, switch to svc mode */
-
-TEXT _vrst(SB), $-4
-	BL	resettrap(SB)
-
-TEXT _vsvc(SB), $-4			/* SWI */
-	MOVW.W	R14, -4(R13)		/* ureg->pc = interupted PC */
-	MOVW	SPSR, R14		/* ureg->psr = SPSR */
-	MOVW.W	R14, -4(R13)		/* ... */
-	MOVW	$PsrMsvc, R14		/* ureg->type = PsrMsvc */
-	MOVW.W	R14, -4(R13)		/* ... */
-	MOVM.DB.W.S [R0-R14], (R13)	/* save user level registers, at end r13 points to ureg */
-	MOVW	$setR12(SB), R12	/* Make sure we've got the kernel's SB loaded */
-	MOVW	R13, R0			/* first arg is pointer to ureg */
-	SUB	$8, R13			/* space for argument+link */
-
-	BL	syscall(SB)
-
-	ADD	$(8+4*15), R13		/* make r13 point to ureg->type */
-	MOVW	8(R13), R14		/* restore link */
-	MOVW	4(R13), R0		/* restore SPSR */
-	MOVW	R0, SPSR		/* ... */
-	MOVM.DB.S (R13), [R0-R14]	/* restore registers */
-	ADD	$8, R13			/* pop past ureg->{type+psr} */
-	RFE				/* MOVM.IA.S.W (R13), [R15] */
-
-TEXT _vund(SB), $-4			/* undefined */
-	MOVM.IA	[R0-R4], (R13)		/* free some working space */
-	MOVW	$PsrMund, R0
-	B	_vswitch
-
-TEXT _vpabt(SB), $-4			/* prefetch abort */
-	MOVM.IA	[R0-R4], (R13)		/* free some working space */
-	MOVW	$PsrMabt, R0		/* r0 = type */
-	B	_vswitch
-
-TEXT _vdabt(SB), $-4			/* prefetch abort */
-	MOVM.IA	[R0-R4], (R13)		/* free some working space */
-	MOVW	$(PsrMabt+1), R0		/* r0 = type */
-	B	_vswitch
-
-TEXT _virq(SB), $-4			/* IRQ */
-	MOVM.IA	[R0-R4], (R13)		/* free some working space */
-	MOVW	$PsrMirq, R0		/* r0 = type */
-	B	_vswitch
-
-	/*
-	 *  come here with type in R0 and R13 pointing above saved [r0-r4]
-	 *  and type in r0.  we'll switch to SVC mode and then call trap.
-	 */
-_vswitch:
-	MOVW	SPSR, R1		/* save SPSR for ureg */
-	MOVW	R14, R2			/* save interrupted pc for ureg */
-	MOVW	R13, R3			/* save pointer to where the original [R0-R3] are */
-
-	/* switch to svc mode */
-	MOVW	CPSR, R14
-	BIC	$PsrMask, R14
-	ORR	$(PsrDirq|PsrDfiq|PsrMsvc), R14
-	MOVW	R14, CPSR
-
-	/* interupted code kernel or user? */
-	AND.S	$0xf, R1, R4
-	BEQ	_userexcep
-
-	/* here for trap from SVC mode */
-	MOVM.DB.W [R0-R2], (R13)	/* set ureg->{type, psr, pc}; r13 points to ureg->type  */
-	MOVM.IA	  (R3), [R0-R4]		/* restore [R0-R4] from previous mode's stack */
-	MOVM.DB.W [R0-R14], (R13)	/* save kernel level registers, at end r13 points to ureg */
-	MOVW	$setR12(SB), R12	/* Make sure we've got the kernel's SB loaded */
-	MOVW	R13, R0			/* first arg is pointer to ureg */
-	SUB	$8, R13			/* space for argument+link (for debugger) */
-	MOVW	$0xdeaddead,R11		/* marker */
-
-	BL	trap(SB)
-
-	ADD	$(8+4*15), R13		/* make r13 point to ureg->type */
-	MOVW	8(R13), R14		/* restore link */
-	MOVW	4(R13), R0		/* restore SPSR */
-	MOVW	R0, SPSR		/* ... */
-	MOVM.DB (R13), [R0-R14]	/* restore registers */
-	ADD	$8, R13			/* pop past ureg->{type+psr} */
-	RFE				/* MOVM.IA.S.W (R13), [R15] */
-
-	/* here for trap from USER mode */
-_userexcep:
-	MOVM.DB.W [R0-R2], (R13)	/* set ureg->{type, psr, pc}; r13 points to ureg->type  */
-	MOVM.IA	  (R3), [R0-R4]		/* restore [R0-R4] from previous mode's stack */
-	MOVM.DB.W.S [R0-R14], (R13)	/* save kernel level registers, at end r13 points to ureg */
-	MOVW	$setR12(SB), R12	/* Make sure we've got the kernel's SB loaded */
-	MOVW	R13, R0			/* first arg is pointer to ureg */
-	SUB	$8, R13			/* space for argument+link (for debugger) */
-
-	BL	trap(SB)
-
-	ADD	$(8+4*15), R13		/* make r13 point to ureg->type */
-	MOVW	8(R13), R14		/* restore link */
-	MOVW	4(R13), R0		/* restore SPSR */
-	MOVW	R0, SPSR		/* ... */
-	MOVM.DB.S (R13), [R0-R14]	/* restore registers */
-	ADD	$8, R13			/* pop past ureg->{type+psr} */
-	RFE				/* MOVM.IA.S.W (R13), [R15] */
-
-TEXT _vfiq(SB), $-4			/* FIQ */
-	RFE				/* FIQ is special, ignore it for now */
-
-/*
- *  This is the first jump from kernel to user mode.
- *  Fake a return from interrupt.
- *
- *  Enter with R0 containing the user stack pointer.
- *  UTZERO + 0x20 is always the entry point.
- *  
- */
-TEXT touser(SB),$-4
-	/* store the user stack pointer into the USR_r13 */
-	MOVM.DB.W [R0], (R13)
-	MOVM.S.IA.W (R13),[R13]
-
-	/* set up a PSR for user level */
-	MOVW	$(PsrMusr), R0
-	MOVW	R0,SPSR
-
-	/* save the PC on the stack */
-	MOVW	$(UTZERO+0x20), R0
-	MOVM.DB.W [R0],(R13)
-
-	/* return from interrupt */
-	RFE				/* MOVM.IA.S.W (R13), [R15] */
-	
-/*
- *  here to jump to a newly forked process
- */
-TEXT forkret(SB),$-4
-	ADD	$(4*15), R13		/* make r13 point to ureg->type */
-	MOVW	8(R13), R14		/* restore link */
-	MOVW	4(R13), R0		/* restore SPSR */
-	MOVW	R0, SPSR		/* ... */
-	MOVM.DB.S (R13), [R0-R14]	/* restore registers */
-	ADD	$8, R13			/* pop past ureg->{type+psr} */
-	RFE				/* MOVM.IA.S.W (R13), [R15] */
-
-TEXT splhi(SB), $-4
-	/* save caller pc in Mach */
-	MOVW	$(MACHADDR+0x04),R2
-	MOVW	R14,0(R2)
-	/* turn off interrupts */
-	MOVW	CPSR, R0
-	ORR	$(PsrDfiq|PsrDirq), R0, R1
-	MOVW	R1, CPSR
-	RET
-
-TEXT spllo(SB), $-4
-	MOVW	CPSR, R0
-	BIC	$(PsrDfiq|PsrDirq), R0, R1
-	MOVW	R1, CPSR
-	RET
-
-TEXT splx(SB), $-4
-	/* save caller pc in Mach */
-	MOVW	$(MACHADDR+0x04),R2
-	MOVW	R14,0(R2)
-	/* reset interrupt level */
-	MOVW	R0, R1
-	MOVW	CPSR, R0
-	MOVW	R1, CPSR
-	RET
-
-TEXT splxpc(SB), $-4				/* for iunlock */
-	MOVW	R0, R1
-	MOVW	CPSR, R0
-	MOVW	R1, CPSR
-	RET
-
-TEXT spldone(SB), $0
-	RET
-
-TEXT islo(SB), $-4
-	MOVW	CPSR, R0
-	AND	$(PsrDfiq|PsrDirq), R0
-	EOR	$(PsrDfiq|PsrDirq), R0
-	RET
-
-TEXT cpsrr(SB), $-4
-	MOVW	CPSR, R0
-	RET
-
-TEXT spsrr(SB), $-4
-	MOVW	SPSR, R0
-	RET
-
-TEXT getcallerpc(SB), $-4
-	MOVW	0(R13), R0
-	RET
-
-TEXT tas(SB), $-4
-	MOVW	R0, R1
-	MOVW	$0xDEADDEAD, R2
-	SWPW	R2, (R1), R0
-	RET
-
-TEXT setlabel(SB), $-4
-	MOVW	R13, 0(R0)			/* sp */
-	MOVW	R14, 4(R0)			/* pc */
-	MOVW	$0, R0
-	RET
-
-TEXT gotolabel(SB), $-4
-	MOVW	0(R0), R13			/* sp */
-	MOVW	4(R0), R14			/* pc */
-	MOVW	$1, R0
-	RET
-
-
-/* The first MCR instruction of this function needs to be on a cache-line
- * boundary; to make this happen, it will be copied (in trap.c).
- *
- * Doze puts the machine into idle mode.  Any interrupt will get it out
- * at the next instruction (the RET, to be precise).
- */
-TEXT _doze(SB), $-4
-	MOVW	$UCDRAMZERO, R1
-	MOVW	R0,R0
-	MOVW	R0,R0
-	MOVW	R0,R0
-	MOVW	R0,R0
-	MOVW	R0,R0
-	MOVW	R0,R0
-	MOVW	R0,R0
-	MCR     CpPWR, 0, R0, C(CpTest), C(0x2), 2
-	MOVW	(R1), R0
-	MCR     CpPWR, 0, R0, C(CpTest), C(0x8), 2
-	RET
--- a/os/boot/arm1110/lib.h
+++ /dev/null
@@ -1,143 +1,0 @@
-/*
- * functions (possibly) linked in, complete, from libc.
- */
-
-/*
- * mem routines
- */
-extern	void	*memccpy(void*, void*, int, long);
-extern	void	*memset(void*, int, long);
-extern	int	memcmp(void*, void*, long);
-extern	void	*memmove(void*, void*, long);
-extern	void	*memchr(void*, int, long);
-
-/*
- * string routines
- */
-extern	char	*strcat(char*, char*);
-extern	char	*strchr(char*, char);
-extern	char	*strrchr(char*, char);
-extern	int	strcmp(char*, char*);
-extern	char	*strcpy(char*, char*);
-extern	char	*strncat(char*, char*, long);
-extern	char	*strncpy(char*, char*, long);
-extern	int	strncmp(char*, char*, long);
-extern	long	strlen(char*);
-extern	char*	strstr(char*, char*);
-extern	int	atoi(char*);
-
-enum
-{
-	UTFmax		= 3,	/* maximum bytes per rune */
-	Runesync	= 0x80,	/* cannot represent part of a UTF sequence */
-	Runeself	= 0x80,	/* rune and UTF sequences are the same (<) */
-	Runeerror	= 0x80,	/* decoding error in UTF */
-};
-
-/*
- * rune routines
- */
-extern	int	runetochar(char*, Rune*);
-extern	int	chartorune(Rune*, char*);
-extern	char*	utfrune(char*, long);
-extern	int	utflen(char*);
-extern	int	runelen(long);
-
-extern	int	abs(int);
-
-/*
- * print routines
- */
-typedef struct Cconv Fconv;
-extern	char*	donprint(char*, char*, char*, void*);
-extern	int	sprint(char*, char*, ...);
-extern	char*	seprint(char*, char*, char*, ...);
-extern	int	snprint(char*, int, char*, ...);
-extern	int	print(char*, ...);
-
-/*
- * one-of-a-kind
- */
-extern	char*	cleanname(char*);
-extern	ulong	getcallerpc(void*);
-extern	long	strtol(char*, char**, int);
-extern	ulong	strtoul(char*, char**, int);
-extern	vlong	strtoll(char*, char**, int);
-extern	uvlong	strtoull(char*, char**, int);
-extern	char	etext[];
-extern	char	edata[];
-extern	char	end[];
-extern	int	getfields(char*, char**, int, int, char*);
-
-/*
- * Syscall data structures
- */
-#define	MORDER	0x0003	/* mask for bits defining order of mounting */
-#define	MREPL	0x0000	/* mount replaces object */
-#define	MBEFORE	0x0001	/* mount goes before others in union directory */
-#define	MAFTER	0x0002	/* mount goes after others in union directory */
-#define	MCREATE	0x0004	/* permit creation in mounted directory */
-#define	MCACHE	0x0010	/* cache some data */
-#define	MMASK	0x001F	/* all bits on */
-
-#define	OREAD	0	/* open for read */
-#define	OWRITE	1	/* write */
-#define	ORDWR	2	/* read and write */
-#define	OEXEC	3	/* execute, == read but check execute permission */
-#define	OTRUNC	16	/* or'ed in (except for exec), truncate file first */
-#define	OCEXEC	32	/* or'ed in, close on exec */
-#define	ORCLOSE	64	/* or'ed in, remove on close */
-
-#define	NCONT	0	/* continue after note */
-#define	NDFLT	1	/* terminate after note */
-#define	NSAVE	2	/* clear note but hold state */
-#define	NRSTR	3	/* restore saved state */
-
-typedef struct Qid	Qid;
-typedef struct Dir	Dir;
-typedef struct Waitmsg	Waitmsg;
-
-#define	ERRLEN		64
-#define	DIRLEN		116
-#define	NAMELEN		28
-
-struct Qid
-{
-	ulong	path;
-	ulong	vers;
-};
-
-struct Dir
-{
-	char	name[NAMELEN];
-	char	uid[NAMELEN];
-	char	gid[NAMELEN];
-	Qid	qid;
-	ulong	mode;
-	long	atime;
-	long	mtime;
-	vlong	length;
-	short	type;
-	short	dev;
-};
-
-struct Waitmsg
-{
-	char	pid[12];	/* of loved one */
-	char	time[3*12];	/* of loved one and descendants */
-	char	msg[ERRLEN];
-};
-
-/*
- *  locks
- */
-typedef
-struct Lock {
-	int	val;
-} Lock;
-
-extern int	_tas(int*);
-
-extern	void	lock(Lock*);
-extern	void	unlock(Lock*);
-extern	int	canlock(Lock*);
--- a/os/boot/arm1110/map
+++ /dev/null
@@ -1,10 +1,0 @@
-defn acidmap()
-{
-	local dfoffset;
-
-	dfoffset = map()[1][3];
-	map({"text", _start, etext, 0x20});
-	map({"data", etext+1, edata, dfoffset});
-	print("Set map for plan 9 kernel image\n");
-	print("btext ", _start, " etext ", etext, "\n");
-}
--- a/os/boot/arm1110/mem.h
+++ /dev/null
@@ -1,215 +1,0 @@
-/*
- * Memory and machine-specific definitions.  Used in C and assembler.
- */
-
-/*
- * Sizes
- */
-#define	BI2BY		8			/* bits per byte */
-#define BI2WD		32			/* bits per word */
-#define	BY2WD		4			/* bytes per word */
-#define	BY2V		8			/* bytes per double word */
-#define	BY2PG		4096			/* bytes per page */
-#define	WD2PG		(BY2PG/BY2WD)		/* words per page */
-#define	PGSHIFT		12			/* log(BY2PG) */
-#define ROUND(s, sz)	(((s)+(sz-1))&~(sz-1))
-#define PGROUND(s)	ROUND(s, BY2PG)
-#define	BLOCKALIGN	8
-
-#define	MAXMACH		1			/* max # cpus system can run */
-
-/*
- * Time
- */
-#define	HZ		(20)				/* clock frequency */
-#define	MS2HZ		(1000/HZ)			/* millisec per clock tick */
-#define	TK2SEC(t)	((t)/HZ)			/* ticks to seconds */
-#define	TK2MS(t)	((((ulong)(t))*1000)/HZ)	/* ticks to milliseconds */
-#define	MS2TK(t)	((((ulong)(t))*HZ)/1000)	/* milliseconds to ticks */
-
-/*
- *  Virtual addresses:
- *
- *  We direct map all discovered DRAM and the area twixt 0xe0000000 and
- *  0xe8000000 used to provide zeros for cache flushing.
- *
- *  Flash is mapped to 0xb0000000 and special registers are mapped
- *  on demand to areas starting at 0xa0000000.
- *
- *  The direct mapping is convenient but not necessary.  It means
- *  that we don't have to turn on the MMU till well into the
- *  kernel.  This can be changed by providing a mapping in l.s
- *  before calling main.
- */
-#define	UZERO		0			/* base of user address space */
-#define	UTZERO		(UZERO+BY2PG)		/* first address in user text */
-#define	KZERO		0xC0000000		/* base of kernel address space */
-#define	KTZERO		0xC0008000		/* first address in kernel text */
-#define	EMEMZERO	0x90000000		/* 256 meg for add on memory */
-#define	EMEMTOP		0xA0000000		/* ... */
-#define	REGZERO		0xA0000000		/* 128 meg for mapspecial regs */
-#define	REGTOP		0xA8000000		/* ... */
-#define	FLASHZERO	0xB0000000		/* 128 meg for flash */
-#define	FLASHTOP	0xB8000000		/* ... */
-#define	DRAMZERO	0xC0000000		/* 128 meg for dram */
-#define DRAMTOP		0xC8000000		/* ... */
-#define	UCDRAMZERO	0xC8000000		/* 128 meg for dram (uncached/unbuffered) */
-#define UCDRAMTOP	0xD0000000		/* ... */
-#define	NULLZERO	0xE0000000		/* 128 meg for cache flush zeroes */
-#define NULLTOP		0xE8000000		/* ... */
-#define	USTKTOP		0x2000000		/* byte just beyond user stack */
-#define	USTKSIZE	(8*1024*1024)		/* size of user stack */
-#define	TSTKTOP		(USTKTOP-USTKSIZE)	/* end of new stack in sysexec */
-#define TSTKSIZ 	100
-#define MACHADDR	(KZERO+0x00001000)
-#define	EVECTORS	0xFFFF0000		/* virt base of exception vectors */
-
-#define KSTACK		(16*1024)		/* Size of kernel stack */
-
-#define	FLATESIZE	(700*1024)		/* maximum size of compressed image */
-
-/*
- *  Offsets into flash
- */
-#define Flash_bootldr	(FLASHZERO+0x0)		/* boot loader */
-#define Flash_kernel	(FLASHZERO+0x10000)	/* boot kernel */
-#define	Flash_tar	(FLASHZERO+0x100000)	/* tar file containing fs.sac */
-
-/*
- *  virtual MMU
- */
-#define PTEMAPMEM	(1024*1024)	
-#define	PTEPERTAB	(PTEMAPMEM/BY2PG)
-#define SEGMAPSIZE	1984
-#define SSEGMAPSIZE	16
-#define PPN(x)		((x)&~(BY2PG-1))
-
-/*
- *  SA1110 definitions
- */
-
-/*
- *  memory physical addresses
- */
-#define PHYSFLASH0	0x00000000
-#define PHYSDRAM0	0xC0000000
-#define	PHYSNULL0	0xE0000000
-
-/*
- *  peripheral control module physical addresses
- */
-#define USBREGS		0x80000000	/* serial port 0 - USB */
-#define UART1REGS	0x80010000	/* serial port 1 - UART */
-#define GPCLKREGS	0x80020060	/* serial port 1 - general purpose clock */
-#define UART2REGS	0x80030000	/* serial port 2 - low speed IR */
-#define HSSPREGS	0x80040060	/* serial port 2 - high speed IR */
-#define UART3REGS	0x80050000	/* serial port 3 - RS232 UART */
-#define MCPREGS		0x80060000	/* serial port 4 - multimedia comm port */
-#define SSPREGS		0x80070060	/* serial port 4 - synchronous serial port */
-#define OSTIMERREGS	0x90000000	/* operating system timer registers */
-#define POWERREGS	0x90020000	/* power management */
-#define GPIOREGS	0x90040000	/* 28 general purpose IO pins */
-#define INTRREGS	0x90050000	/* interrupt registers */
-#define PPCREGS		0x90060000	/* peripheral pin controller */
-#define MEMCONFREGS	0xA0000000	/* memory configuration */
-#define LCDREGS		0xB0100000	/* display */
-
-/*
- *  PCMCIA addresses
- */
-#define PHYSPCM0REGS	0x20000000
-#define PYHSPCM0ATTR	0x28000000
-#define PYHSPCM0MEM	0x2C000000
-#define PHYSPCM1REGS	0x30000000
-#define PYHSPCM1ATTR	0x38000000
-#define PYHSPCM1MEM	0x3C000000
-
-/*
- *  Program Status Registers
- */
-#define PsrMusr		0x00000010	/* mode */
-#define PsrMfiq		0x00000011
-#define PsrMirq		0x00000012
-#define PsrMsvc		0x00000013
-#define PsrMabt		0x00000017
-#define PsrMund		0x0000001B
-#define PsrMask		0x0000001F
-
-#define PsrDfiq		0x00000040	/* disable FIQ interrupts */
-#define PsrDirq		0x00000080	/* disable IRQ interrupts */
-
-#define PsrV		0x10000000	/* overflow */
-#define PsrC		0x20000000	/* carry/borrow/extend */
-#define PsrZ		0x40000000	/* zero */
-#define PsrN		0x80000000	/* negative/less than */
-
-/*
- *  Coprocessors
- */
-#define CpMMU		15
-#define CpPWR		15
-
-/*
- *  Internal MMU coprocessor registers
- */
-#define CpCPUID		0		/* R: */
-#define CpControl	1		/* R: */
-#define CpTTB		2		/* RW: translation table base */
-#define CpDAC		3		/* RW: domain access control */
-#define CpFSR		5		/* RW: fault status */
-#define CpFAR		6		/* RW: fault address */
-#define CpCacheFlush	7		/* W: cache flushing, wb draining*/
-#define CpTLBFlush	8		/* W: TLB flushing */
-#define CpRBFlush	9		/* W: Read Buffer ops */
-#define CpPID		13		/* RW: PID for virtual mapping */
-#define	CpBpt		14		/* W: Breakpoint register */
-#define CpTest		15		/* W: Test, Clock and Idle Control */
-
-/*
- *  CpControl
- */
-#define CpCmmuena	0x00000001	/* M: MMU enable */
-#define CpCalign	0x00000002	/* A: alignment fault enable */
-#define CpCdcache	0x00000004	/* C: data cache on */
-#define CpCwb		0x00000008	/* W: write buffer turned on */
-#define CpCi32		0x00000010	/* P: 32-bit program space */
-#define CpCd32		0x00000020	/* D: 32-bit data space */
-#define CpCbe		0x00000080	/* B: big-endian operation */
-#define CpCsystem	0x00000100	/* S: system permission */
-#define CpCrom		0x00000200	/* R: ROM permission */
-#define CpCicache	0x00001000	/* I: instruction cache on */
-#define CpCvivec	0x00002000	/* X: virtual interrupt vector adjust */
-
-/*
- *  fault codes
- */
-#define	FCterm		0x2	/* terminal */
-#define	FCvec		0x0	/* vector */
-#define	FCalignf	0x1	/* unaligned full word data access */
-#define	FCalignh	0x3	/* unaligned half word data access */
-#define	FCl1abort	0xc	/* level 1 external abort on translation */
-#define	FCl2abort	0xe	/* level 2 external abort on translation */
-#define	FCtransSec	0x5	/* section translation */
-#define	FCtransPage	0x7	/* page translation */
-#define	FCdomainSec	0x9	/* section domain  */
-#define	FCdomainPage	0x11	/* page domain */
-#define	FCpermSec	0x9	/* section permissions  */
-#define	FCpermPage	0x11	/* page permissions */
-#define	FCabortLFSec	0x4	/* external abort on linefetch for section */
-#define	FCabortLFPage	0x6	/* external abort on linefetch for page */
-#define	FCabortNLFSec	0x8	/* external abort on non-linefetch for section */
-#define	FCabortNLFPage	0xa	/* external abort on non-linefetch for page */
-
-/*
- *  PTE bits used by fault.h.  mmu.c translates them to real values.
- */
-#define	PTEVALID	(1<<0)
-#define	PTERONLY	0	/* this is implied by the absence of PTEWRITE */
-#define	PTEWRITE	(1<<1)
-#define	PTEUNCACHED	(1<<2)
-#define PTEKERNEL	(1<<3)	/* no user access */
-
-/*
- *  H3650 specific definitions
- */
-#define EGPIOREGS	0x49000000	/* Additional GPIO register */
--- a/os/boot/arm1110/mkfile
+++ /dev/null
@@ -1,86 +1,0 @@
-<../../../mkconfig
-objtype=arm
-SYSTARG=$OSTARG
-OBJTYPE=arm
-BIN=$ROOT/Inferno/$OBJTYPE
-LIBDIR=$ROOT/Inferno/$OBJTYPE/lib
-LIBDIRS=../libflate $ROOT/libkern
-LIBS=\
-	libflate\
-	libkern\
-
-LIBFILES=${LIBS:%=$LIBDIR/%.a}
-<$ROOT/mkfiles/mkfile-$SYSTARG-$OBJTYPE
-
-BIN=$ROOT/Inferno/$OBJTYPE
-
-TARG=\
-	inflate\
-
-INFLATE=\
-	il.$O\
-	imain.$O\
-
-CORE=\
-	uart.$O\
-	inflate.$O\
-	donprint.$O\
-	print.$O\
-
-HFILES=\
-	mem.h\
-
-CFLAGS=-FVw -I.  -I$ROOT/Inferno/$OBJTYPE/include -I$ROOT/include
-
-all:V:	$TARG
-
-install:V:	$BIN/$TARG
-
-$BIN/%:	%
-	cp $stem $BIN/$stem
-
-inflate: $INFLATE $CORE $LIBFILES
-	$LD -o s$target -R4 -T0xC0200010 -l $prereq
-	$LD -o _$target -H5 -R4 -T0xC0200010 -l $prereq
-	dd -conv sync -ibs 20k -if _$target -of $target
-
-%.$O:	%.s
-	$AS $stem.s
-
-%.$O:	%.c
-	$CC $CFLAGS $stem.c
-
-%.$O:	$HFILES
-
-clean:
-	rm -f *.[$OS] [$OS].out y.tab.? y.debug y.output $TARG _$TARG s$TARG
-
-
-# added to cause libflate to be made automatically:
-
-$ROOT/Inferno/$OBJTYPE/lib/lib%.a:Q:	all-$SHELLTYPE
-	#
-
-rc-lib%.a nt-lib%.a:VQ:
-	echo '@{builtin cd ' $ROOT/lib$stem ';mk SHELLTYPE=$SHELLTYPE SYSTARG=$SYSTARG OBJTYPE=$OBJTYPE install}'
-	@{builtin cd  $ROOT/lib$stem ;mk 'SHELLTYPE='$SHELLTYPE 'SYSTARG='$SYSTARG 'OBJTYPE='$OBJTYPE install}
-
-sh-lib%.a:VQ:
-	echo "(cd $ROOT/lib$stem ; mk SHELLTYPE=$SHELLTYPE SYSTARG=$SYSTARG OBJTYPE=$OBJTYPE install)"
-	(cd $ROOT/lib$stem ; mk SHELLTYPE=$SHELLTYPE SYSTARG=$SYSTARG OBJTYPE=$OBJTYPE install)
-
-%-sh:QV:
-		for i in $LIBDIRS
-		do
-			echo "(cd $i ; mk SHELLTYPE=$SHELLTYPE SYSTARG=$SYSTARG OBJTYPE=$OBJTYPE $stem)"
-			(cd $i; mk 'SHELLTYPE='$SHELLTYPE 'SYSTARG='$SYSTARG 'OBJTYPE='$OBJTYPE $stem)
-		done
-
-%-rc %-nt:QV:
-		for (i in $LIBDIRS)
-		{
-			echo '@{cd $i ; mk SHELLTYPE=$SHELLTYPE SYSTARG=$SYSTARG OBJTYPE=$OBJTYPE $stem}'
-			@{cd $i; mk 'SHELLTYPE='$SHELLTYPE 'SYSTARG='$SYSTARG 'OBJTYPE='$OBJTYPE $stem}
-		}
-
-nuke:V:		clean nuke-$SHELLTYPE
--- a/os/boot/arm1110/print.c
+++ /dev/null
@@ -1,56 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "fns.h"
-#include "dat.h"
-
-
-#define	SIZE	1024
-
-int
-print(char *fmt, ...)
-{
-	char buf[SIZE], *out;
-	va_list arg;
-
-	va_start(arg, fmt);
-	out = donprint(buf, buf+SIZE, fmt, arg);
-	va_end(arg);
-	serialputs(buf, out-buf);
-	return out-buf;
-}
-
-int
-sprint(char *buf, char *fmt, ...)
-{
-	char *out;
-	va_list arg;
-
-	va_start(arg, fmt);
-	out = donprint(buf, buf+SIZE, fmt, arg);
-	va_end(arg);
-	return out-buf;
-}
-
-int
-snprint(char *buf, int len, char *fmt, ...)
-{
-	char *out;
-	va_list arg;
-
-	va_start(arg, fmt);
-	out = donprint(buf, buf+len, fmt, arg);
-	va_end(arg);
-	return out-buf;
-}
-
-char*
-seprint(char *buf, char *e, char *fmt, ...)
-{
-	char *out;
-	va_list arg;
-
-	va_start(arg, fmt);
-	out = donprint(buf, e, fmt, arg);
-	va_end(arg);
-	return out;
-}
--- a/os/boot/arm1110/uart.c
+++ /dev/null
@@ -1,69 +1,0 @@
-#include	"u.h"
-#include	"lib.h"
-#include	"mem.h"
-#include	"dat.h"
-#include	"fns.h"
-#include	"io.h"
-
-enum
-{
-	/* ctl[0] bits */
-	Parity=		1<<0,
-	Even=		1<<1,
-	Stop2=		1<<2,
-	Bits8=		1<<3,
-	SCE=		1<<4,	/* synchronous clock enable */
-	RCE=		1<<5,	/* rx on falling edge of clock */
-	TCE=		1<<6,	/* tx on falling edge of clock */
-
-	/* ctl[3] bits */
-	Rena=		1<<0,	/* receiver enable */
-	Tena=		1<<1,	/* transmitter enable */
-	Break=		1<<2,	/* force TXD3 low */
-	Rintena=	1<<3,	/* enable receive interrupt */
-	Tintena=	1<<4,	/* enable transmitter interrupt */
-	Loopback=	1<<5,	/* loop back data */
-
-	/* data bits */
-	DEparity=	1<<8,	/* parity error */
-	DEframe=	1<<9,	/* framing error */
-	DEoverrun=	1<<10,	/* overrun error */
-
-	/* status[0] bits */
-	Tint=		1<<0,	/* transmit fifo half full interrupt */
-	Rint0=		1<<1,	/* receiver fifo 1/3-2/3 full */
-	Rint1=		1<<2,	/* receiver fifo not empty and receiver idle */
-	Breakstart=	1<<3,
-	Breakend=	1<<4,
-	Fifoerror=	1<<5,	/* fifo error */
-
-	/* status[1] bits */
-	Tbusy=		1<<0,	/* transmitting */
-	Rnotempty=	1<<1,	/* receive fifo not empty */
-	Tnotfull=	1<<2,	/* transmit fifo not full */
-	ParityError=	1<<3,
-	FrameError=	1<<4,
-	Overrun=	1<<5,
-};
-
-Uartregs *uart3regs = UART3REGS;
-
-
-/*
- *  for iprint, just write it
- */
-void
-serialputs(char *str, int n)
-{
-	Uartregs *ur;
-
-	ur = uart3regs;
-	while(n-- > 0){
-		/* wait for output ready */
-		while((ur->status[1] & Tnotfull) == 0)
-			;
-		ur->data = *str++;
-	}
-	while((ur->status[1] & Tbusy))
-		;
-}
--- a/os/boot/libflate/LICENCE
+++ /dev/null
@@ -1,237 +1,0 @@
-Lucent Public License Version 1.02
-
-THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS PUBLIC
-LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE
-PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT.
-
-1. DEFINITIONS
-
-"Contribution" means:
-
-  a. in the case of Lucent Technologies Inc. ("LUCENT"), the Original
-     Program, and
-  b. in the case of each Contributor,
-
-     i. changes to the Program, and
-    ii. additions to the Program;
-
-    where such changes and/or additions to the Program were added to the
-    Program by such Contributor itself or anyone acting on such
-    Contributor's behalf, and the Contributor explicitly consents, in
-    accordance with Section 3C, to characterization of the changes and/or
-    additions as Contributions.
-
-"Contributor" means LUCENT and any other entity that has Contributed a
-Contribution to the Program.
-
-"Distributor" means a Recipient that distributes the Program,
-modifications to the Program, or any part thereof.
-
-"Licensed Patents" mean patent claims licensable by a Contributor
-which are necessarily infringed by the use or sale of its Contribution
-alone or when combined with the Program.
-
-"Original Program" means the original version of the software
-accompanying this Agreement as released by LUCENT, including source
-code, object code and documentation, if any.
-
-"Program" means the Original Program and Contributions or any part
-thereof
-
-"Recipient" means anyone who receives the Program under this
-Agreement, including all Contributors.
-
-2. GRANT OF RIGHTS
-
- a. Subject to the terms of this Agreement, each Contributor hereby
-    grants Recipient a non-exclusive, worldwide, royalty-free copyright
-    license to reproduce, prepare derivative works of, publicly display,
-    publicly perform, distribute and sublicense the Contribution of such
-    Contributor, if any, and such derivative works, in source code and
-    object code form.
-    
- b. Subject to the terms of this Agreement, each Contributor hereby
-    grants Recipient a non-exclusive, worldwide, royalty-free patent
-    license under Licensed Patents to make, use, sell, offer to sell,
-    import and otherwise transfer the Contribution of such Contributor, if
-    any, in source code and object code form. The patent license granted
-    by a Contributor shall also apply to the combination of the
-    Contribution of that Contributor and the Program if, at the time the
-    Contribution is added by the Contributor, such addition of the
-    Contribution causes such combination to be covered by the Licensed
-    Patents. The patent license granted by a Contributor shall not apply
-    to (i) any other combinations which include the Contribution, nor to
-    (ii) Contributions of other Contributors. No hardware per se is
-    licensed hereunder.
-    
- c. Recipient understands that although each Contributor grants the
-    licenses to its Contributions set forth herein, no assurances are
-    provided by any Contributor that the Program does not infringe the
-    patent or other intellectual property rights of any other entity. Each
-    Contributor disclaims any liability to Recipient for claims brought by
-    any other entity based on infringement of intellectual property rights
-    or otherwise. As a condition to exercising the rights and licenses
-    granted hereunder, each Recipient hereby assumes sole responsibility
-    to secure any other intellectual property rights needed, if any. For
-    example, if a third party patent license is required to allow
-    Recipient to distribute the Program, it is Recipient's responsibility
-    to acquire that license before distributing the Program.
-
- d. Each Contributor represents that to its knowledge it has sufficient
-    copyright rights in its Contribution, if any, to grant the copyright
-    license set forth in this Agreement.
-
-3. REQUIREMENTS
-
-A. Distributor may choose to distribute the Program in any form under
-this Agreement or under its own license agreement, provided that:
-
- a. it complies with the terms and conditions of this Agreement;
-
- b. if the Program is distributed in source code or other tangible
-    form, a copy of this Agreement or Distributor's own license agreement
-    is included with each copy of the Program; and
-
- c. if distributed under Distributor's own license agreement, such
-    license agreement:
-
-      i. effectively disclaims on behalf of all Contributors all warranties
-         and conditions, express and implied, including warranties or
-         conditions of title and non-infringement, and implied warranties or
-         conditions of merchantability and fitness for a particular purpose;
-     ii. effectively excludes on behalf of all Contributors all liability
-         for damages, including direct, indirect, special, incidental and
-         consequential damages, such as lost profits; and
-    iii. states that any provisions which differ from this Agreement are
-         offered by that Contributor alone and not by any other party.
-
-B. Each Distributor must include the following in a conspicuous
-   location in the Program:
-
-   Copyright (C) 2003, Lucent Technologies Inc. and others. All Rights
-   Reserved.
-
-C. In addition, each Contributor must identify itself as the
-originator of its Contribution in a manner that reasonably allows
-subsequent Recipients to identify the originator of the Contribution.
-Also, each Contributor must agree that the additions and/or changes
-are intended to be a Contribution. Once a Contribution is contributed,
-it may not thereafter be revoked.
-
-4. COMMERCIAL DISTRIBUTION
-
-Commercial distributors of software may accept certain
-responsibilities with respect to end users, business partners and the
-like. While this license is intended to facilitate the commercial use
-of the Program, the Distributor who includes the Program in a
-commercial product offering should do so in a manner which does not
-create potential liability for Contributors. Therefore, if a
-Distributor includes the Program in a commercial product offering,
-such Distributor ("Commercial Distributor") hereby agrees to defend
-and indemnify every Contributor ("Indemnified Contributor") against
-any losses, damages and costs (collectively"Losses") arising from
-claims, lawsuits and other legal actions brought by a third party
-against the Indemnified Contributor to the extent caused by the acts
-or omissions of such Commercial Distributor in connection with its
-distribution of the Program in a commercial product offering. The
-obligations in this section do not apply to any claims or Losses
-relating to any actual or alleged intellectual property infringement.
-In order to qualify, an Indemnified Contributor must: a) promptly
-notify the Commercial Distributor in writing of such claim, and b)
-allow the Commercial Distributor to control, and cooperate with the
-Commercial Distributor in, the defense and any related settlement
-negotiations. The Indemnified Contributor may participate in any such
-claim at its own expense.
-
-For example, a Distributor might include the Program in a commercial
-product offering, Product X. That Distributor is then a Commercial
-Distributor. If that Commercial Distributor then makes performance
-claims, or offers warranties related to Product X, those performance
-claims and warranties are such Commercial Distributor's responsibility
-alone. Under this section, the Commercial Distributor would have to
-defend claims against the Contributors related to those performance
-claims and warranties, and if a court requires any Contributor to pay
-any damages as a result, the Commercial Distributor must pay those
-damages.
-
-5. NO WARRANTY
-
-EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS
-PROVIDED ON AN"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY
-WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY
-OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely
-responsible for determining the appropriateness of using and
-distributing the Program and assumes all risks associated with its
-exercise of rights under this Agreement, including but not limited to
-the risks and costs of program errors, compliance with applicable
-laws, damage to or loss of data, programs or equipment, and
-unavailability or interruption of operations.
-
-6. DISCLAIMER OF LIABILITY
-
-EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR
-ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT,
-INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING
-WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF
-LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR
-DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
-HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
-
-7. EXPORT CONTROL
-
-Recipient agrees that Recipient alone is responsible for compliance
-with the United States export administration regulations (and the
-export control laws and regulation of any other countries).
-
-8. GENERAL
-
-If any provision of this Agreement is invalid or unenforceable under
-applicable law, it shall not affect the validity or enforceability of
-the remainder of the terms of this Agreement, and without further
-action by the parties hereto, such provision shall be reformed to the
-minimum extent necessary to make such provision valid and enforceable.
-
-If Recipient institutes patent litigation against a Contributor with
-respect to a patent applicable to software (including a cross-claim or
-counterclaim in a lawsuit), then any patent licenses granted by that
-Contributor to such Recipient under this Agreement shall terminate as
-of the date such litigation is filed. In addition, if Recipient
-institutes patent litigation against any entity (including a
-cross-claim or counterclaim in a lawsuit) alleging that the Program
-itself (excluding combinations of the Program with other software or
-hardware) infringes such Recipient's patent(s), then such Recipient's
-rights granted under Section 2(b) shall terminate as of the date such
-litigation is filed.
-
-All Recipient's rights under this Agreement shall terminate if it
-fails to comply with any of the material terms or conditions of this
-Agreement and does not cure such failure in a reasonable period of
-time after becoming aware of such noncompliance. If all Recipient's
-rights under this Agreement terminate, Recipient agrees to cease use
-and distribution of the Program as soon as reasonably practicable.
-However, Recipient's obligations under this Agreement and any licenses
-granted by Recipient relating to the Program shall continue and
-survive.
-
-LUCENT may publish new versions (including revisions) of this
-Agreement from time to time. Each new version of the Agreement will be
-given a distinguishing version number. The Program (including
-Contributions) may always be distributed subject to the version of the
-Agreement under which it was received. In addition, after a new
-version of the Agreement is published, Contributor may elect to
-distribute the Program (including its Contributions) under the new
-version. No one other than LUCENT has the right to modify this
-Agreement. Except as expressly stated in Sections 2(a) and 2(b) above,
-Recipient receives no rights or licenses to the intellectual property
-of any Contributor under this Agreement, whether expressly, by
-implication, estoppel or otherwise. All rights in the Program not
-expressly granted under this Agreement are reserved.
-
-This Agreement is governed by the laws of the State of New York and
-the intellectual property laws of the United States of America. No
-party to this Agreement will bring a legal action under this Agreement
-more than one year after the cause of action arose. Each party waives
-its rights to a jury trial in any resulting litigation.
-
--- a/os/boot/libflate/NOTICE
+++ /dev/null
@@ -1,8 +1,0 @@
-Copyright © 2002 Lucent Technologies Inc.
-All Rights Reserved
-
-This software was originally developed for Plan 9.
-It is provided under the terms of the Lucent Public License, Version 1.02.
-
-Trivial modifications have been made to make it compile for Inferno.
-	Vita Nuova Holdings Limited.
--- a/os/boot/libflate/adler.c
+++ /dev/null
@@ -1,71 +1,0 @@
-#include "lib9.h"
-#include <flate.h>
-
-enum
-{
-	ADLERITERS	= 5552,	/* max iters before can overflow 32 bits */
-	ADLERBASE	= 65521 /* largest prime smaller than 65536 */
-};
-
-ulong
-adler32(ulong adler, void *vbuf, int n)
-{
-	ulong s1, s2;
-	uchar *buf, *ebuf;
-	int m;
-
-	buf = vbuf;
-	s1 = adler & 0xffff;
-	s2 = (adler >> 16) & 0xffff;
-	for(; n >= 16; n -= m){
-		m = n;
-		if(m > ADLERITERS)
-			m = ADLERITERS;
-		m &= ~15;
-		for(ebuf = buf + m; buf < ebuf; buf += 16){
-			s1 += buf[0];
-			s2 += s1;
-			s1 += buf[1];
-			s2 += s1;
-			s1 += buf[2];
-			s2 += s1;
-			s1 += buf[3];
-			s2 += s1;
-			s1 += buf[4];
-			s2 += s1;
-			s1 += buf[5];
-			s2 += s1;
-			s1 += buf[6];
-			s2 += s1;
-			s1 += buf[7];
-			s2 += s1;
-			s1 += buf[8];
-			s2 += s1;
-			s1 += buf[9];
-			s2 += s1;
-			s1 += buf[10];
-			s2 += s1;
-			s1 += buf[11];
-			s2 += s1;
-			s1 += buf[12];
-			s2 += s1;
-			s1 += buf[13];
-			s2 += s1;
-			s1 += buf[14];
-			s2 += s1;
-			s1 += buf[15];
-			s2 += s1;
-		}
-		s1 %= ADLERBASE;
-		s2 %= ADLERBASE;
-	}
-	if(n){
-		for(ebuf = buf + n; buf < ebuf; buf++){
-			s1 += buf[0];
-			s2 += s1;
-		}
-		s1 %= ADLERBASE;
-		s2 %= ADLERBASE;
-	}
-	return (s2 << 16) + s1;
-}
--- a/os/boot/libflate/crc.c
+++ /dev/null
@@ -1,39 +1,0 @@
-#include "lib9.h"
-#include <flate.h>
-
-ulong*
-mkcrctab(ulong poly)
-{
-	ulong *crctab;
-	ulong crc;
-	int i, j;
-
-	crctab = malloc(256 * sizeof(ulong));
-	if(crctab == nil)
-		return nil;
-
-	for(i = 0; i < 256; i++){
-		crc = i;
-		for(j = 0; j < 8; j++){
-			if(crc & 1)
-				crc = (crc >> 1) ^ poly;
-			else
-				crc >>= 1;
-		}
-		crctab[i] = crc;
-	}
-	return crctab;
-}
-
-ulong
-blockcrc(ulong *crctab, ulong crc, void *vbuf, int n)
-{
-	uchar *buf, *ebuf;
-
-	crc ^= 0xffffffff;
-	buf = vbuf;
-	ebuf = buf + n;
-	while(buf < ebuf)
-		crc = crctab[(crc & 0xff) ^ *buf++] ^ (crc >> 8);
-	return crc ^ 0xffffffff;
-}
--- a/os/boot/libflate/deflate.c
+++ /dev/null
@@ -1,1358 +1,0 @@
-#include "lib9.h"
-#include <flate.h>
-
-typedef struct Chain	Chain;
-typedef struct Chains	Chains;
-typedef struct Dyncode	Dyncode;
-typedef struct Huff	Huff;
-typedef struct LZblock	LZblock;
-typedef struct LZstate	LZstate;
-
-enum
-{
-	/*
-	 * deflate format paramaters
-	 */
-	DeflateUnc	= 0,			/* uncompressed block */
-	DeflateFix	= 1,			/* fixed huffman codes */
-	DeflateDyn	= 2,			/* dynamic huffman codes */
-
-	DeflateEob	= 256,			/* end of block code in lit/len book */
-	DeflateMaxBlock	= 64*1024-1,		/* maximum size of uncompressed block */
-
-	DeflateMaxExp	= 10,			/* maximum expansion for a block */
-
-	LenStart	= 257,			/* start of length codes in litlen */
-	Nlitlen		= 288,			/* number of litlen codes */
-	Noff		= 30,			/* number of offset codes */
-	Nclen		= 19,			/* number of codelen codes */
-
-	MaxOff		= 32*1024,
-	MinMatch	= 3,			/* shortest match possible */
-	MaxMatch	= 258,			/* longest match possible */
-
-	/*
-	 * huffman code paramaters
-	 */
-	MaxLeaf		= Nlitlen,
-	MaxHuffBits	= 16,			/* max bits in a huffman code */
-	ChainMem	= 2 * (MaxHuffBits - 1) * MaxHuffBits,
-
-	/*
-	 * coding of the lz parse
-	 */
-	LenFlag		= 1 << 3,
-	LenShift	= 4,			/* leaves enough space for MinMatchMaxOff */
-	MaxLitRun	= LenFlag - 1,
-
-	/*
-	 * internal lz paramaters
-	 */
-	DeflateOut	= 4096,			/* output buffer size */
-	BlockSize	= 8192,			/* attempted input read quanta */
-	DeflateBlock	= DeflateMaxBlock & ~(BlockSize - 1),
-	MinMatchMaxOff	= 4096,			/* max profitable offset for small match;
-						 * assumes 8 bits for len, 5+10 for offset
-						 * DONT CHANGE WITHOUT CHANGING LZPARSE CONSTANTS
-						 */
-	HistSlop	= 512,			/* must be at lead MaxMatch */
-	HistBlock	= 64*1024,
-	HistSize	= HistBlock + HistSlop,
-
-	HashLog		= 13,
-	HashSize	= 1<<HashLog,
-
-	MaxOffCode	= 256,			/* biggest offset looked up in direct table */
-
-	EstLitBits	= 8,
-	EstLenBits	= 4,
-	EstOffBits	= 5,
-};
-
-/*
- * knuth vol. 3 multiplicative hashing
- * each byte x chosen according to rules
- * 1/4 < x < 3/10, 1/3 x < < 3/7, 4/7 < x < 2/3, 7/10 < x < 3/4
- * with reasonable spread between the bytes & their complements
- *
- * the 3 byte value appears to be as almost good as the 4 byte value,
- * and might be faster on some machines
- */
-/*
-#define hashit(c)	(((ulong)(c) * 0x6b43a9) >> (24 - HashLog))
-*/
-#define hashit(c)	((((ulong)(c) & 0xffffff) * 0x6b43a9b5) >> (32 - HashLog))
-
-/*
- * lempel-ziv style compression state
- */
-struct LZstate
-{
-	uchar	hist[HistSize];
-	ulong	pos;				/* current location in history buffer */
-	ulong	avail;				/* data available after pos */
-	int	eof;
-	ushort	hash[HashSize];			/* hash chains */
-	ushort	nexts[MaxOff];
-	int	now;				/* pos in hash chains */
-	int	dot;				/* dawn of time in history */
-	int	prevlen;			/* lazy matching state */
-	int	prevoff;
-	int	maxcheck;			/* compressor tuning */
-
-	uchar	obuf[DeflateOut];
-	uchar	*out;				/* current position in the output buffer */
-	uchar	*eout;
-	ulong	bits;				/* bit shift register */
-	int	nbits;
-	int	rbad;				/* got an error reading the buffer */
-	int	wbad;				/* got an error writing the buffer */
-	int	(*w)(void*, void*, int);
-	void	*wr;
-
-	ulong	totr;				/* total input size */
-	ulong	totw;				/* total output size */
-	int	debug;
-};
-
-struct LZblock
-{
-	ushort	parse[DeflateMaxBlock / 2 + 1];
-	int	lastv;				/* value being constucted for parse */
-	ulong	litlencount[Nlitlen];
-	ulong	offcount[Noff];
-	ushort	*eparse;			/* limit for parse table */
-	int	bytes;				/* consumed from the input */
-	int	excost;				/* cost of encoding extra len & off bits */
-};
-
-/*
- * huffman code table
- */
-struct Huff
-{
-	short	bits;				/* length of the code */
-	ushort	encode;				/* the code */
-};
-
-/*
- * encoding of dynamic huffman trees
- */
-struct Dyncode
-{
-	int	nlit;
-	int	noff;
-	int	nclen;
-	int	ncode;
-	Huff	codetab[Nclen];
-	uchar	codes[Nlitlen+Noff];
-	uchar	codeaux[Nlitlen+Noff];
-};
-
-static	int	deflateb(LZstate *lz, LZblock *lzb, void *rr, int (*r)(void*, void*, int));
-static	int	lzcomp(LZstate*, LZblock*, uchar*, ushort*, int finish);
-static	void	wrblock(LZstate*, int, ushort*, ushort*, Huff*, Huff*);
-static	int	bitcost(Huff*, ulong*, int);
-static	int	huffcodes(Dyncode*, Huff*, Huff*);
-static	void	wrdyncode(LZstate*, Dyncode*);
-static	void	lzput(LZstate*, ulong bits, int nbits);
-static	void	lzflushbits(LZstate*);
-static	void	lzflush(LZstate *lz);
-static	void	lzwrite(LZstate *lz, void *buf, int n);
-
-static	int	hufftabinit(Huff*, int, ulong*, int);
-static	int	mkgzprecode(Huff*, ulong *, int, int);
-
-static	int	mkprecode(Huff*, ulong *, int, int, ulong*);
-static	void	nextchain(Chains*, int);
-static	void	leafsort(ulong*, ushort*, int, int);
-
-/* conversion from len to code word */
-static int lencode[MaxMatch];
-
-/*
- * conversion from off to code word
- * off <= MaxOffCode ? offcode[off] : bigoffcode[off >> 7]
-*/
-static int offcode[MaxOffCode];
-static int bigoffcode[256];
-
-/* litlen code words LenStart-285 extra bits */
-static int litlenbase[Nlitlen-LenStart];
-static int litlenextra[Nlitlen-LenStart] =
-{
-/* 257 */	0, 0, 0,
-/* 260 */	0, 0, 0, 0, 0, 1, 1, 1, 1, 2,
-/* 270 */	2, 2, 2, 3, 3, 3, 3, 4, 4, 4,
-/* 280 */	4, 5, 5, 5, 5, 0, 0, 0
-};
-
-/* offset code word extra bits */
-static int offbase[Noff];
-static int offextra[] =
-{
-	0,  0,  0,  0,  1,  1,  2,  2,  3,  3,
-	4,  4,  5,  5,  6,  6,  7,  7,  8,  8,
-	9,  9,  10, 10, 11, 11, 12, 12, 13, 13,
-	0,  0,
-};
-
-/* order code lengths */
-static int clenorder[Nclen] =
-{
-        16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
-};
-
-/* static huffman tables */
-static	Huff	litlentab[Nlitlen];
-static	Huff	offtab[Noff];
-static	Huff	hofftab[Noff];
-
-/* bit reversal for brain dead endian swap in huffman codes */
-static	uchar	revtab[256];
-static	ulong	nlits;
-static	ulong	nmatches;
-
-int
-deflateinit(void)
-{
-	ulong bitcount[MaxHuffBits];
-	int i, j, ci, n;
-
-	/* byte reverse table */
-	for(i=0; i<256; i++)
-		for(j=0; j<8; j++)
-			if(i & (1<<j))
-				revtab[i] |= 0x80 >> j;
-
-	/* static Litlen bit lengths */
-	for(i=0; i<144; i++)
-		litlentab[i].bits = 8;
-	for(i=144; i<256; i++)
-		litlentab[i].bits = 9;
-	for(i=256; i<280; i++)
-		litlentab[i].bits = 7;
-	for(i=280; i<Nlitlen; i++)
-		litlentab[i].bits = 8;
-
-	memset(bitcount, 0, sizeof(bitcount));
-	bitcount[8] += 144 - 0;
-	bitcount[9] += 256 - 144;
-	bitcount[7] += 280 - 256;
-	bitcount[8] += Nlitlen - 280;
-
-	if(!hufftabinit(litlentab, Nlitlen, bitcount, 9))
-		return FlateInternal;
-
-	/* static offset bit lengths */
-	for(i = 0; i < Noff; i++)
-		offtab[i].bits = 5;
-
-	memset(bitcount, 0, sizeof(bitcount));
-	bitcount[5] = Noff;
-
-	if(!hufftabinit(offtab, Noff, bitcount, 5))
-		return FlateInternal;
-
-	bitcount[0] = 0;
-	bitcount[1] = 0;
-	if(!mkgzprecode(hofftab, bitcount, 2, MaxHuffBits))
-		return FlateInternal;
-
-	/* conversion tables for lens & offs to codes */
-	ci = 0;
-	for(i = LenStart; i < 286; i++){
-		n = ci + (1 << litlenextra[i - LenStart]);
-		litlenbase[i - LenStart] = ci;
-		for(; ci < n; ci++)
-			lencode[ci] = i;
-	}
-	/* patch up special case for len MaxMatch */
-	lencode[MaxMatch-MinMatch] = 285;
-	litlenbase[285-LenStart] = MaxMatch-MinMatch;
-
-	ci = 0;
-	for(i = 0; i < 16; i++){
-		n = ci + (1 << offextra[i]);
-		offbase[i] = ci;
-		for(; ci < n; ci++)
-			offcode[ci] = i;
-	}
-
-	ci = ci >> 7;
-	for(; i < 30; i++){
-		n = ci + (1 << (offextra[i] - 7));
-		offbase[i] = ci << 7;
-		for(; ci < n; ci++)
-			bigoffcode[ci] = i;
-	}
-	return FlateOk;
-}
-
-static void
-deflatereset(LZstate *lz, int level, int debug)
-{
-	memset(lz->nexts, 0, sizeof lz->nexts);
-	memset(lz->hash, 0, sizeof lz->hash);
-	lz->totr = 0;
-	lz->totw = 0;
-	lz->pos = 0;
-	lz->avail = 0;
-	lz->out = lz->obuf;
-	lz->eout = &lz->obuf[DeflateOut];
-	lz->prevlen = MinMatch - 1;
-	lz->prevoff = 0;
-	lz->now = MaxOff + 1;
-	lz->dot = lz->now;
-	lz->bits = 0;
-	lz->nbits = 0;
-	lz->maxcheck = (1 << level);
-	lz->maxcheck -= lz->maxcheck >> 2;
-	if(lz->maxcheck < 2)
-		lz->maxcheck = 2;
-	else if(lz->maxcheck > 1024)
-		lz->maxcheck = 1024;
-
-	lz->debug = debug;
-}
-
-int
-deflate(void *wr, int (*w)(void*, void*, int), void *rr, int (*r)(void*, void*, int), int level, int debug)
-{
-	LZstate *lz;
-	LZblock *lzb;
-	int ok;
-
-	lz = malloc(sizeof *lz + sizeof *lzb);
-	if(lz == nil)
-		return FlateNoMem;
-	lzb = (LZblock*)&lz[1];
-
-	deflatereset(lz, level, debug);
-	lz->w = w;
-	lz->wr = wr;
-	lz->wbad = 0;
-	lz->rbad = 0;
-	lz->eof = 0;
-	ok = FlateOk;
-	while(!lz->eof || lz->avail){
-		ok = deflateb(lz, lzb, rr, r);
-		if(ok != FlateOk)
-			break;
-	}
-	if(ok == FlateOk && lz->rbad)
-		ok = FlateInputFail;
-	if(ok == FlateOk && lz->wbad)
-		ok = FlateOutputFail;
-	free(lz);
-	return ok;
-}
-
-static int
-deflateb(LZstate *lz, LZblock *lzb, void *rr, int (*r)(void*, void*, int))
-{
-	Dyncode dyncode, hdyncode;
-	Huff dlitlentab[Nlitlen], dofftab[Noff], hlitlentab[Nlitlen];
-	ulong litcount[Nlitlen];
-	long nunc, ndyn, nfix, nhuff;
-	uchar *slop, *hslop;
-	ulong ep;
-	int i, n, m, mm, nslop;
-
-	memset(lzb->litlencount, 0, sizeof lzb->litlencount);
-	memset(lzb->offcount, 0, sizeof lzb->offcount);
-	lzb->litlencount[DeflateEob]++;
-
-	lzb->bytes = 0;
-	lzb->eparse = lzb->parse;
-	lzb->lastv = 0;
-	lzb->excost = 0;
-
-	slop = &lz->hist[lz->pos];
-	n = lz->avail;
-	while(n < DeflateBlock && (!lz->eof || lz->avail)){
-		/*
-		 * fill the buffer as much as possible,
-		 * while leaving room for MaxOff history behind lz->pos,
-		 * and not reading more than we can handle.
-		 *
-		 * make sure we read at least HistSlop bytes.
-		 */
-		if(!lz->eof){
-			ep = lz->pos + lz->avail;
-			if(ep >= HistBlock)
-				ep -= HistBlock;
-			m = HistBlock - MaxOff - lz->avail;
-			if(m > HistBlock - n)
-				m = HistBlock - n;
-			if(m > (HistBlock + HistSlop) - ep)
-				m = (HistBlock + HistSlop) - ep;
-			if(m & ~(BlockSize - 1))
-				m &= ~(BlockSize - 1);
-
-			/*
-			 * be nice to the caller: stop reads that are too small.
-			 * can only get here when we've already filled the buffer some
-			 */
-			if(m < HistSlop){
-				if(!m || !lzb->bytes)
-					return FlateInternal;
-				break;
-			}
-
-			mm = (*r)(rr, &lz->hist[ep], m);
-			if(mm > 0){
-				/*
-				 * wrap data to end if we're read it from the beginning
-				 * this way, we don't have to wrap searches.
-				 *
-				 * wrap reads past the end to the beginning.
-				 * this way, we can guarantee minimum size reads.
-				 */
-				if(ep < HistSlop)
-					memmove(&lz->hist[ep + HistBlock], &lz->hist[ep], HistSlop - ep);
-				else if(ep + mm > HistBlock)
-					memmove(&lz->hist[0], &lz->hist[HistBlock], ep + mm - HistBlock);
-
-				lz->totr += mm;
-				n += mm;
-				lz->avail += mm;
-			}else{
-				if(mm < 0)
-					lz->rbad = 1;
-				lz->eof = 1;
-			}
-		}
-		ep = lz->pos + lz->avail;
-		if(ep > HistSize)
-			ep = HistSize;
-		if(lzb->bytes + ep - lz->pos > DeflateMaxBlock)
-			ep = lz->pos + DeflateMaxBlock - lzb->bytes;
-		m = lzcomp(lz, lzb, &lz->hist[ep], lzb->eparse, lz->eof);
-		lzb->bytes += m;
-		lz->pos = (lz->pos + m) & (HistBlock - 1);
-		lz->avail -= m;
-	}
-	if(lzb->lastv)
-		*lzb->eparse++ = lzb->lastv;
-	if(lzb->eparse > lzb->parse + nelem(lzb->parse))
-		return FlateInternal;
-	nunc = lzb->bytes;
-
-	if(!mkgzprecode(dlitlentab, lzb->litlencount, Nlitlen, MaxHuffBits)
-	|| !mkgzprecode(dofftab, lzb->offcount, Noff, MaxHuffBits))
-		return FlateInternal;
-
-	ndyn = huffcodes(&dyncode, dlitlentab, dofftab);
-	if(ndyn < 0)
-		return FlateInternal;
-	ndyn += bitcost(dlitlentab, lzb->litlencount, Nlitlen)
-		+ bitcost(dofftab, lzb->offcount, Noff)
-		+ lzb->excost;
-
-	memset(litcount, 0, sizeof litcount);
-
-	nslop = nunc;
-	if(nslop > &lz->hist[HistSize] - slop)
-		nslop = &lz->hist[HistSize] - slop;
-
-	for(i = 0; i < nslop; i++)
-		litcount[slop[i]]++;
-	hslop = &lz->hist[HistSlop - nslop];
-	for(; i < nunc; i++)
-		litcount[hslop[i]]++;
-	litcount[DeflateEob]++;
-
-	if(!mkgzprecode(hlitlentab, litcount, Nlitlen, MaxHuffBits))
-		return FlateInternal;
-	nhuff = huffcodes(&hdyncode, hlitlentab, hofftab);
-	if(nhuff < 0)
-		return FlateInternal;
-	nhuff += bitcost(hlitlentab, litcount, Nlitlen);
-
-	nfix = bitcost(litlentab, lzb->litlencount, Nlitlen)
-		+ bitcost(offtab, lzb->offcount, Noff)
-		+ lzb->excost;
-
-	lzput(lz, lz->eof && !lz->avail, 1);
-
-	if(lz->debug){
-		fprint(2, "block: bytes=%lud entries=%ld extra bits=%d\n\tuncompressed=%lud fixed=%lud dynamic=%lud huffman=%lud\n",
-			nunc, lzb->eparse - lzb->parse, lzb->excost, (nunc + 4) * 8, nfix, ndyn, nhuff);
-		fprint(2, "\tnlit=%lud matches=%lud eof=%d\n", nlits, nmatches, lz->eof && !lz->avail);
-	}
-
-	if((nunc + 4) * 8 < ndyn && (nunc + 4) * 8 < nfix && (nunc + 4) * 8 < nhuff){
-		lzput(lz, DeflateUnc, 2);
-		lzflushbits(lz);
-
-		lzput(lz, nunc & 0xff, 8);
-		lzput(lz, (nunc >> 8) & 0xff, 8);
-		lzput(lz, ~nunc & 0xff, 8);
-		lzput(lz, (~nunc >> 8) & 0xff, 8);
-		lzflush(lz);
-
-		lzwrite(lz, slop, nslop);
-		lzwrite(lz, &lz->hist[HistSlop], nunc - nslop);
-	}else if(ndyn < nfix && ndyn < nhuff){
-		lzput(lz, DeflateDyn, 2);
-
-		wrdyncode(lz, &dyncode);
-		wrblock(lz, slop - lz->hist, lzb->parse, lzb->eparse, dlitlentab, dofftab);
-		lzput(lz, dlitlentab[DeflateEob].encode, dlitlentab[DeflateEob].bits);
-	}else if(nhuff < nfix){
-		lzput(lz, DeflateDyn, 2);
-
-		wrdyncode(lz, &hdyncode);
-
-		m = 0;
-		for(i = nunc; i > MaxLitRun; i -= MaxLitRun)
-			lzb->parse[m++] = MaxLitRun;
-		lzb->parse[m++] = i;
-
-		wrblock(lz, slop - lz->hist, lzb->parse, lzb->parse + m, hlitlentab, hofftab);
-		lzput(lz, hlitlentab[DeflateEob].encode, hlitlentab[DeflateEob].bits);
-	}else{
-		lzput(lz, DeflateFix, 2);
-
-		wrblock(lz, slop - lz->hist, lzb->parse, lzb->eparse, litlentab, offtab);
-		lzput(lz, litlentab[DeflateEob].encode, litlentab[DeflateEob].bits);
-	}
-
-	if(lz->eof && !lz->avail){
-		lzflushbits(lz);
-		lzflush(lz);
-	}
-	return FlateOk;
-}
-
-static void
-lzwrite(LZstate *lz, void *buf, int n)
-{
-	int nw;
-
-	if(n && lz->w){
-		nw = (*lz->w)(lz->wr, buf, n);
-		if(nw != n){
-			lz->w = nil;
-			lz->wbad = 1;
-		}else
-			lz->totw += n;
-	}
-}
-
-static void
-lzflush(LZstate *lz)
-{
-	lzwrite(lz, lz->obuf, lz->out - lz->obuf);
-	lz->out = lz->obuf;
-}
-
-static void
-lzput(LZstate *lz, ulong bits, int nbits)
-{
-	bits = (bits << lz->nbits) | lz->bits;
-	for(nbits += lz->nbits; nbits >= 8; nbits -= 8){
-		*lz->out++ = bits;
-		if(lz->out == lz->eout)
-			lzflush(lz);
-		bits >>= 8;
-	}
-	lz->bits = bits;
-	lz->nbits = nbits;
-}
-
-static void
-lzflushbits(LZstate *lz)
-{
-	if(lz->nbits)
-		lzput(lz, 0, 8 - (lz->nbits & 7));
-}
-
-/*
- * write out a block of n samples,
- * given lz encoding and counts for huffman tables
- */
-static void
-wrblock(LZstate *out, int litoff, ushort *soff, ushort *eoff, Huff *litlentab, Huff *offtab)
-{
-	ushort *off;
-	int i, run, offset, lit, len, c;
-
-	if(out->debug > 2){
-		for(off = soff; off < eoff; ){
-			offset = *off++;
-			run = offset & MaxLitRun;
-			if(run){
-				for(i = 0; i < run; i++){
-					lit = out->hist[litoff & (HistBlock - 1)];
-					litoff++;
-					fprint(2, "\tlit %.2ux %c\n", lit, lit);
-				}
-				if(!(offset & LenFlag))
-					continue;
-				len = offset >> LenShift;
-				offset = *off++;
-			}else if(offset & LenFlag){
-				len = offset >> LenShift;
-				offset = *off++;
-			}else{
-				len = 0;
-				offset >>= LenShift;
-			}
-			litoff += len + MinMatch;
-			fprint(2, "\t<%d, %d>\n", offset + 1, len + MinMatch);
-		}
-	}
-
-	for(off = soff; off < eoff; ){
-		offset = *off++;
-		run = offset & MaxLitRun;
-		if(run){
-			for(i = 0; i < run; i++){
-				lit = out->hist[litoff & (HistBlock - 1)];
-				litoff++;
-				lzput(out, litlentab[lit].encode, litlentab[lit].bits);
-			}
-			if(!(offset & LenFlag))
-				continue;
-			len = offset >> LenShift;
-			offset = *off++;
-		}else if(offset & LenFlag){
-			len = offset >> LenShift;
-			offset = *off++;
-		}else{
-			len = 0;
-			offset >>= LenShift;
-		}
-		litoff += len + MinMatch;
-		c = lencode[len];
-		lzput(out, litlentab[c].encode, litlentab[c].bits);
-		c -= LenStart;
-		if(litlenextra[c])
-			lzput(out, len - litlenbase[c], litlenextra[c]);
-
-		if(offset < MaxOffCode)
-			c = offcode[offset];
-		else
-			c = bigoffcode[offset >> 7];
-		lzput(out, offtab[c].encode, offtab[c].bits);
-		if(offextra[c])
-			lzput(out, offset - offbase[c], offextra[c]);
-	}
-}
-
-/*
- * look for the longest, closest string which matches
- * the next prefix.  the clever part here is looking for
- * a string 1 longer than the previous best match.
- *
- * follows the recommendation of limiting number of chains
- * which are checked.  this appears to be the best heuristic.
- */
-static int
-lzmatch(int now, int then, uchar *p, uchar *es, ushort *nexts, uchar *hist, int runlen, int check, int *m)
-{
-	uchar *s, *t;
-	int ml, off, last;
-
-	ml = check;
-	if(runlen >= 8)
-		check >>= 2;
-	*m = 0;
-	if(p + runlen >= es)
-		return runlen;
-	last = 0;
-	for(; check-- > 0; then = nexts[then & (MaxOff-1)]){
-		off = (ushort)(now - then);
-		if(off <= last || off > MaxOff)
-			break;
-		s = p + runlen;
-		t = hist + (((p - hist) - off) & (HistBlock-1));
-		t += runlen;
-		for(; s >= p; s--){
-			if(*s != *t)
-				goto matchloop;
-			t--;
-		}
-
-		/*
-		 * we have a new best match.
-		 * extend it to it's maximum length
-		 */
-		t += runlen + 2;
-		s += runlen + 2;
-		for(; s < es; s++){
-			if(*s != *t)
-				break;
-			t++;
-		}
-		runlen = s - p;
-		*m = off - 1;
-		if(s == es || runlen > ml)
-			break;
-matchloop:;
-		last = off;
-	}
-	return runlen;
-}
-
-static int
-lzcomp(LZstate *lz, LZblock *lzb, uchar *ep, ushort *parse, int finish)
-{
-	ulong cont, excost, *litlencount, *offcount;
-	uchar *p, *q, *s, *es;
-	ushort *nexts, *hash;
-	int v, i, h, runlen, n, now, then, m, prevlen, prevoff, maxdefer;
-
-	litlencount = lzb->litlencount;
-	offcount = lzb->offcount;
-	nexts = lz->nexts;
-	hash = lz->hash;
-	now = lz->now;
-
-	p = &lz->hist[lz->pos];
-	if(lz->prevlen != MinMatch - 1)
-		p++;
-
-	/*
-	 * hash in the links for any hanging link positions,
-	 * and calculate the hash for the current position.
-	 */
-	n = MinMatch;
-	if(n > ep - p)
-		n = ep - p;
-	cont = 0;
-	for(i = 0; i < n - 1; i++){
-		m = now - ((MinMatch-1) - i);
-		if(m < lz->dot)
-			continue;
-		s = lz->hist + (((p - lz->hist) - (now - m)) & (HistBlock-1));
-
-		cont = (s[0] << 16) | (s[1] << 8) | s[2];
-		h = hashit(cont);
-		prevoff = 0;
-		for(then = hash[h]; ; then = nexts[then & (MaxOff-1)]){
-			v = (ushort)(now - then);
-			if(v <= prevoff || v >= (MinMatch-1) - i)
-				break;
-			prevoff = v;
-		}
-		if(then == (ushort)m)
-			continue;
-		nexts[m & (MaxOff-1)] = hash[h];
-		hash[h] = m;
-	}
-	for(i = 0; i < n; i++)
-		cont = (cont << 8) | p[i];
-
-	/*
-	 * now must point to the index in the nexts array
-	 * corresponding to p's position in the history
-	 */
-	prevlen = lz->prevlen;
-	prevoff = lz->prevoff;
-	maxdefer = lz->maxcheck >> 2;
-	excost = 0;
-	v = lzb->lastv;
-	for(;;){
-		es = p + MaxMatch;
-		if(es > ep){
-			if(!finish || p >= ep)
-				break;
-			es = ep;
-		}
-
-		h = hashit(cont);
-		runlen = lzmatch(now, hash[h], p, es, nexts, lz->hist, prevlen, lz->maxcheck, &m);
-
-		/*
-		 * back out of small matches too far in the past
-		 */
-		if(runlen == MinMatch && m >= MinMatchMaxOff){
-			runlen = MinMatch - 1;
-			m = 0;
-		}
-
-		/*
-		 * record the encoding and increment counts for huffman trees
-		 * if we get a match, defer selecting it until we check for
-		 * a longer match at the next position.
-		 */
-		if(prevlen >= runlen && prevlen != MinMatch - 1){
-			/*
-			 * old match at least as good; use that one
-			 */
-			n = prevlen - MinMatch;
-			if(v || n){
-				*parse++ = v | LenFlag | (n << LenShift);
-				*parse++ = prevoff;
-			}else
-				*parse++ = prevoff << LenShift;
-			v = 0;
-
-			n = lencode[n];
-			litlencount[n]++;
-			excost += litlenextra[n - LenStart];
-
-			if(prevoff < MaxOffCode)
-				n = offcode[prevoff];
-			else
-				n = bigoffcode[prevoff >> 7];
-			offcount[n]++;
-			excost += offextra[n];
-
-			runlen = prevlen - 1;
-			prevlen = MinMatch - 1;
-			nmatches++;
-		}else if(runlen == MinMatch - 1){
-			/*
-			 * no match; just put out the literal
-			 */
-			if(++v == MaxLitRun){
-				*parse++ = v;
-				v = 0;
-			}
-			litlencount[*p]++;
-			nlits++;
-			runlen = 1;
-		}else{
-			if(prevlen != MinMatch - 1){
-				/*
-				 * longer match now. output previous literal,
-				 * update current match, and try again
-				 */
-				if(++v == MaxLitRun){
-					*parse++ = v;
-					v = 0;
-				}
-				litlencount[p[-1]]++;
-				nlits++;
-			}
-
-			prevoff = m;
-
-			if(runlen < maxdefer){
-				prevlen = runlen;
-				runlen = 1;
-			}else{
-				n = runlen - MinMatch;
-				if(v || n){
-					*parse++ = v | LenFlag | (n << LenShift);
-					*parse++ = prevoff;
-				}else
-					*parse++ = prevoff << LenShift;
-				v = 0;
-
-				n = lencode[n];
-				litlencount[n]++;
-				excost += litlenextra[n - LenStart];
-
-				if(prevoff < MaxOffCode)
-					n = offcode[prevoff];
-				else
-					n = bigoffcode[prevoff >> 7];
-				offcount[n]++;
-				excost += offextra[n];
-
-				prevlen = MinMatch - 1;
-				nmatches++;
-			}
-		}
-
-		/*
-		 * update the hash for the newly matched data
-		 * this is constructed so the link for the old
-		 * match in this position must be at the end of a chain,
-		 * and will expire when this match is added, ie it will
-		 * never be examined by the match loop.
-		 * add to the hash chain only if we have the real hash data.
-		 */
-		for(q = p + runlen; p != q; p++){
-			if(p + MinMatch <= ep){
-				h = hashit(cont);
-				nexts[now & (MaxOff-1)] = hash[h];
-				hash[h] = now;
-				if(p + MinMatch < ep)
-					cont = (cont << 8) | p[MinMatch];
-			}
-			now++;
-		}
-	}
-
-	/*
-	 * we can just store away the lazy state and
-	 * pick it up next time.  the last block will have finish set
-	 * so we won't have any pending matches
-	 * however, we need to correct for how much we've encoded
-	 */
-	if(prevlen != MinMatch - 1)
-		p--;
-
-	lzb->excost += excost;
-	lzb->eparse = parse;
-	lzb->lastv = v;
-
-	lz->now = now;
-	lz->prevlen = prevlen;
-	lz->prevoff = prevoff;
-
-	return p - &lz->hist[lz->pos];
-}
-
-/*
- * make up the dynamic code tables, and return the number of bits
- * needed to transmit them.
- */
-static int
-huffcodes(Dyncode *dc, Huff *littab, Huff *offtab)
-{
-	Huff *codetab;
-	uchar *codes, *codeaux;
-	ulong codecount[Nclen], excost;
-	int i, n, m, v, c, nlit, noff, ncode, nclen;
-
-	codetab = dc->codetab;
-	codes = dc->codes;
-	codeaux = dc->codeaux;
-
-	/*
-	 * trim the sizes of the tables
-	 */
-	for(nlit = Nlitlen; nlit > 257 && littab[nlit-1].bits == 0; nlit--)
-		;
-	for(noff = Noff; noff > 1 && offtab[noff-1].bits == 0; noff--)
-		;
-
-	/*
-	 * make the code-length code
-	 */
-	for(i = 0; i < nlit; i++)
-		codes[i] = littab[i].bits;
-	for(i = 0; i < noff; i++)
-		codes[i + nlit] = offtab[i].bits;
-
-	/*
-	 * run-length compress the code-length code
-	 */
-	excost = 0;
-	c = 0;
-	ncode = nlit+noff;
-	for(i = 0; i < ncode; ){
-		n = i + 1;
-		v = codes[i];
-		while(n < ncode && v == codes[n])
-			n++;
-		n -= i;
-		i += n;
-		if(v == 0){
-			while(n >= 11){
-				m = n;
-				if(m > 138)
-					m = 138;
-				codes[c] = 18;
-				codeaux[c++] = m - 11;
-				n -= m;
-				excost += 7;
-			}
-			if(n >= 3){
-				codes[c] = 17;
-				codeaux[c++] = n - 3;
-				n = 0;
-				excost += 3;
-			}
-		}
-		while(n--){
-			codes[c++] = v;
-			while(n >= 3){
-				m = n;
-				if(m > 6)
-					m = 6;
-				codes[c] = 16;
-				codeaux[c++] = m - 3;
-				n -= m;
-				excost += 3;
-			}
-		}
-	}
-
-	memset(codecount, 0, sizeof codecount);
-	for(i = 0; i < c; i++)
-		codecount[codes[i]]++;
-	if(!mkgzprecode(codetab, codecount, Nclen, 8))
-		return -1;
-
-	for(nclen = Nclen; nclen > 4 && codetab[clenorder[nclen-1]].bits == 0; nclen--)
-		;
-
-	dc->nlit = nlit;
-	dc->noff = noff;
-	dc->nclen = nclen;
-	dc->ncode = c;
-
-	return 5 + 5 + 4 + nclen * 3 + bitcost(codetab, codecount, Nclen) + excost;
-}
-
-static void
-wrdyncode(LZstate *out, Dyncode *dc)
-{
-	Huff *codetab;
-	uchar *codes, *codeaux;
-	int i, v, c;
-
-	/*
-	 * write out header, then code length code lengths,
-	 * and code lengths
-	 */
-	lzput(out, dc->nlit-257, 5);
-	lzput(out, dc->noff-1, 5);
-	lzput(out, dc->nclen-4, 4);
-
-	codetab = dc->codetab;
-	for(i = 0; i < dc->nclen; i++)
-		lzput(out, codetab[clenorder[i]].bits, 3);
-
-	codes = dc->codes;
-	codeaux = dc->codeaux;
-	c = dc->ncode;
-	for(i = 0; i < c; i++){
-		v = codes[i];
-		lzput(out, codetab[v].encode, codetab[v].bits);
-		if(v >= 16){
-			if(v == 16)
-				lzput(out, codeaux[i], 2);
-			else if(v == 17)
-				lzput(out, codeaux[i], 3);
-			else /* v == 18 */
-				lzput(out, codeaux[i], 7);
-		}
-	}
-}
-
-static int
-bitcost(Huff *tab, ulong *count, int n)
-{
-	ulong tot;
-	int i;
-
-	tot = 0;
-	for(i = 0; i < n; i++)
-		tot += count[i] * tab[i].bits;
-	return tot;
-}
-
-static int
-mkgzprecode(Huff *tab, ulong *count, int n, int maxbits)
-{
-	ulong bitcount[MaxHuffBits];
-	int i, nbits;
-
-	nbits = mkprecode(tab, count, n, maxbits, bitcount);
-	for(i = 0; i < n; i++){
-		if(tab[i].bits == -1)
-			tab[i].bits = 0;
-		else if(tab[i].bits == 0){
-			if(nbits != 0 || bitcount[0] != 1)
-				return 0;
-			bitcount[1] = 1;
-			bitcount[0] = 0;
-			nbits = 1;
-			tab[i].bits = 1;
-		}
-	}
-	if(bitcount[0] != 0)
-		return 0;
-	return hufftabinit(tab, n, bitcount, nbits);
-}
-
-static int
-hufftabinit(Huff *tab, int n, ulong *bitcount, int nbits)
-{
-	ulong code, nc[MaxHuffBits];
-	int i, bits;
-
-	code = 0;
-	for(bits = 1; bits <= nbits; bits++){
-		code = (code + bitcount[bits-1]) << 1;
-		nc[bits] = code;
-	}
-
-	for(i = 0; i < n; i++){
-		bits = tab[i].bits;
-		if(bits){
-			code = nc[bits]++ << (16 - bits);
-			if(code & ~0xffff)
-				return 0;
-			tab[i].encode = revtab[code >> 8] | (revtab[code & 0xff] << 8);
-		}
-	}
-	return 1;
-}
-
-
-/*
- * this should be in a library
- */
-struct Chain
-{
-	ulong	count;				/* occurances of everything in the chain */
-	ushort	leaf;				/* leaves to the left of chain, or leaf value */
-	char	col;				/* ref count for collecting unused chains */
-	char	gen;				/* need to generate chains for next lower level */
-	Chain	*up;				/* Chain up in the lists */
-};
-
-struct Chains
-{
-	Chain	*lists[(MaxHuffBits - 1) * 2];
-	ulong	leafcount[MaxLeaf];		/* sorted list of leaf counts */
-	ushort	leafmap[MaxLeaf];		/* map to actual leaf number */
-	int	nleaf;				/* number of leaves */
-	Chain	chains[ChainMem];
-	Chain	*echains;
-	Chain	*free;
-	char	col;
-	int	nlists;
-};
-
-/*
- * fast, low space overhead algorithm for max depth huffman type codes
- *
- * J. Katajainen, A. Moffat and A. Turpin, "A fast and space-economical
- * algorithm for length-limited coding," Proc. Intl. Symp. on Algorithms
- * and Computation, Cairns, Australia, Dec. 1995, Lecture Notes in Computer
- * Science, Vol 1004, J. Staples, P. Eades, N. Katoh, and A. Moffat, eds.,
- * pp 12-21, Springer Verlag, New York, 1995.
- */
-static int
-mkprecode(Huff *tab, ulong *count, int n, int maxbits, ulong *bitcount)
-{
-	Chains cs;
-	Chain *c;
-	int i, m, em, bits;
-
-	/*
-	 * set up the sorted list of leaves
-	 */
-	m = 0;
-	for(i = 0; i < n; i++){
-		tab[i].bits = -1;
-		tab[i].encode = 0;
-		if(count[i] != 0){
-			cs.leafcount[m] = count[i];
-			cs.leafmap[m] = i;
-			m++;
-		}
-	}
-	if(m < 2){
-		if(m != 0){
-			tab[cs.leafmap[0]].bits = 0;
-			bitcount[0] = 1;
-		}else
-			bitcount[0] = 0;
-		return 0;
-	}
-	cs.nleaf = m;
-	leafsort(cs.leafcount, cs.leafmap, 0, m);
-
-	for(i = 0; i < m; i++)
-		cs.leafcount[i] = count[cs.leafmap[i]];
-
-	/*
-	 * set up free list
-	 */
-	cs.free = &cs.chains[2];
-	cs.echains = &cs.chains[ChainMem];
-	cs.col = 1;
-
-	/*
-	 * initialize chains for each list
-	 */
-	c = &cs.chains[0];
-	c->count = cs.leafcount[0];
-	c->leaf = 1;
-	c->col = cs.col;
-	c->up = nil;
-	c->gen = 0;
-	cs.chains[1] = cs.chains[0];
-	cs.chains[1].leaf = 2;
-	cs.chains[1].count = cs.leafcount[1];
-	for(i = 0; i < maxbits-1; i++){
-		cs.lists[i * 2] = &cs.chains[0];
-		cs.lists[i * 2 + 1] = &cs.chains[1];
-	}
-
-	cs.nlists = 2 * (maxbits - 1);
-	m = 2 * m - 2;
-	for(i = 2; i < m; i++)
-		nextchain(&cs, cs.nlists - 2);
-
-	bits = 0;
-	bitcount[0] = cs.nleaf;
-	for(c = cs.lists[cs.nlists - 1]; c != nil; c = c->up){
-		m = c->leaf;
-		bitcount[bits++] -= m;
-		bitcount[bits] = m;
-	}
-	m = 0;
-	for(i = bits; i >= 0; i--)
-		for(em = m + bitcount[i]; m < em; m++)
-			tab[cs.leafmap[m]].bits = i;
-
-	return bits;
-}
-
-/*
- * calculate the next chain on the list
- * we can always toss out the old chain
- */
-static void
-nextchain(Chains *cs, int list)
-{
-	Chain *c, *oc;
-	int i, nleaf, sumc;
-
-	oc = cs->lists[list + 1];
-	cs->lists[list] = oc;
-	if(oc == nil)
-		return;
-
-	/*
-	 * make sure we have all chains needed to make sumc
-	 * note it is possible to generate only one of these,
-	 * use twice that value for sumc, and then generate
-	 * the second if that preliminary sumc would be chosen.
-	 * however, this appears to be slower on current tests
-	 */
-	if(oc->gen){
-		nextchain(cs, list - 2);
-		nextchain(cs, list - 2);
-		oc->gen = 0;
-	}
-
-	/*
-	 * pick up the chain we're going to add;
-	 * collect unused chains no free ones are left
-	 */
-	for(c = cs->free; ; c++){
-		if(c >= cs->echains){
-			cs->col++;
-			for(i = 0; i < cs->nlists; i++)
-				for(c = cs->lists[i]; c != nil; c = c->up)
-					c->col = cs->col;
-			c = cs->chains;
-		}
-		if(c->col != cs->col)
-			break;
-	}
-
-	/*
-	 * pick the cheapest of
-	 * 1) the next package from the previous list
-	 * 2) the next leaf
-	 */
-	nleaf = oc->leaf;
-	sumc = 0;
-	if(list > 0 && cs->lists[list-1] != nil)
-		sumc = cs->lists[list-2]->count + cs->lists[list-1]->count;
-	if(sumc != 0 && (nleaf >= cs->nleaf || cs->leafcount[nleaf] > sumc)){
-		c->count = sumc;
-		c->leaf = oc->leaf;
-		c->up = cs->lists[list-1];
-		c->gen = 1;
-	}else if(nleaf >= cs->nleaf){
-		cs->lists[list + 1] = nil;
-		return;
-	}else{
-		c->leaf = nleaf + 1;
-		c->count = cs->leafcount[nleaf];
-		c->up = oc->up;
-		c->gen = 0;
-	}
-	cs->free = c + 1;
-
-	cs->lists[list + 1] = c;
-	c->col = cs->col;
-}
-
-static int
-pivot(ulong *c, int a, int n)
-{
-	int j, pi, pj, pk;
-
-	j = n/6;
-	pi = a + j;	/* 1/6 */
-	j += j;
-	pj = pi + j;	/* 1/2 */
-	pk = pj + j;	/* 5/6 */
-	if(c[pi] < c[pj]){
-		if(c[pi] < c[pk]){
-			if(c[pj] < c[pk])
-				return pj;
-			return pk;
-		}
-		return pi;
-	}
-	if(c[pj] < c[pk]){
-		if(c[pi] < c[pk])
-			return pi;
-		return pk;
-	}
-	return pj;
-}
-
-static	void
-leafsort(ulong *leafcount, ushort *leafmap, int a, int n)
-{
-	ulong t;
-	int j, pi, pj, pn;
-
-	while(n > 1){
-		if(n > 10){
-			pi = pivot(leafcount, a, n);
-		}else
-			pi = a + (n>>1);
-
-		t = leafcount[pi];
-		leafcount[pi] = leafcount[a];
-		leafcount[a] = t;
-		t = leafmap[pi];
-		leafmap[pi] = leafmap[a];
-		leafmap[a] = t;
-		pi = a;
-		pn = a + n;
-		pj = pn;
-		for(;;){
-			do
-				pi++;
-			while(pi < pn && (leafcount[pi] < leafcount[a] || leafcount[pi] == leafcount[a] && leafmap[pi] > leafmap[a]));
-			do
-				pj--;
-			while(pj > a && (leafcount[pj] > leafcount[a] || leafcount[pj] == leafcount[a] && leafmap[pj] < leafmap[a]));
-			if(pj < pi)
-				break;
-			t = leafcount[pi];
-			leafcount[pi] = leafcount[pj];
-			leafcount[pj] = t;
-			t = leafmap[pi];
-			leafmap[pi] = leafmap[pj];
-			leafmap[pj] = t;
-		}
-		t = leafcount[a];
-		leafcount[a] = leafcount[pj];
-		leafcount[pj] = t;
-		t = leafmap[a];
-		leafmap[a] = leafmap[pj];
-		leafmap[pj] = t;
-		j = pj - a;
-
-		n = n-j-1;
-		if(j >= n){
-			leafsort(leafcount, leafmap, a, j);
-			a += j+1;
-		}else{
-			leafsort(leafcount, leafmap, a + (j+1), n);
-			n = j;
-		}
-	}
-}
--- a/os/boot/libflate/deflateblock.c
+++ /dev/null
@@ -1,55 +1,0 @@
-#include "lib9.h"
-#include <flate.h>
-
-typedef struct Block	Block;
-
-struct Block
-{
-	uchar	*pos;
-	uchar	*limit;
-};
-
-static int
-blread(void *vb, void *buf, int n)
-{
-	Block *b;
-
-	b = vb;
-	if(n > b->limit - b->pos)
-		n = b->limit - b->pos;
-	memmove(buf, b->pos, n);
-	b->pos += n;
-	return n;
-}
-
-static int
-blwrite(void *vb, void *buf, int n)
-{
-	Block *b;
-
-	b = vb;
-
-	if(n > b->limit - b->pos)
-		n = b->limit - b->pos;
-	memmove(b->pos, buf, n);
-	b->pos += n;
-	return n;
-}
-
-int
-deflateblock(uchar *dst, int dsize, uchar *src, int ssize, int level, int debug)
-{
-	Block bd, bs;
-	int ok;
-
-	bs.pos = src;
-	bs.limit = src + ssize;
-
-	bd.pos = dst;
-	bd.limit = dst + dsize;
-
-	ok = deflate(&bd, blwrite, &bs, blread, level, debug);
-	if(ok != FlateOk)
-		return ok;
-	return bd.pos - dst;
-}
--- a/os/boot/libflate/deflatezlib.c
+++ /dev/null
@@ -1,59 +1,0 @@
-#include "lib9.h"
-#include <flate.h>
-#include "zlib.h"
-
-typedef struct ZRead	ZRead;
-
-struct ZRead
-{
-	ulong	adler;
-	void	*rr;
-	int	(*r)(void*, void*, int);
-};
-
-static int
-zlread(void *vzr, void *buf, int n)
-{
-	ZRead *zr;
-
-	zr = vzr;
-	n = (*zr->r)(zr->rr, buf, n);
-	if(n <= 0)
-		return n;
-	zr->adler = adler32(zr->adler, buf, n);
-	return n;
-}
-
-int
-deflatezlib(void *wr, int (*w)(void*, void*, int), void *rr, int (*r)(void*, void*, int), int level, int debug)
-{
-	ZRead zr;
-	uchar buf[4];
-	int ok;
-
-	buf[0] = ZlibDeflate | ZlibWin32k;
-
-	/* bogus zlib encoding of compression level */
-	buf[1] = ((level > 2) + (level > 5) + (level > 8)) << 6;
-
-	/* header check field */
-	buf[1] |= 31 - ((buf[0] << 8) | buf[1]) % 31;
-	if((*w)(wr, buf, 2) != 2)
-		return FlateOutputFail;
-
-	zr.rr = rr;
-	zr.r = r;
-	zr.adler = 1;
-	ok = deflate(wr, w, &zr, zlread, level, debug);
-	if(ok != FlateOk)
-		return ok;
-
-	buf[0] = zr.adler >> 24;
-	buf[1] = zr.adler >> 16;
-	buf[2] = zr.adler >> 8;
-	buf[3] = zr.adler;
-	if((*w)(wr, buf, 4) != 4)
-		return FlateOutputFail;
-
-	return FlateOk;
-}
--- a/os/boot/libflate/deflatezlibblock.c
+++ /dev/null
@@ -1,33 +1,0 @@
-#include "lib9.h"
-#include <flate.h>
-#include "zlib.h"
-
-int
-deflatezlibblock(uchar *dst, int dsize, uchar *src, int ssize, int level, int debug)
-{
-	ulong adler;
-	int n;
-
-	if(dsize < 6)
-		return FlateOutputFail;
-
-	n = deflateblock(dst + 2, dsize - 6, src, ssize, level, debug);
-	if(n < 0)
-		return n;
-
-	dst[0] = ZlibDeflate | ZlibWin32k;
-
-	/* bogus zlib encoding of compression level */
-	dst[1] = ((level > 2) + (level > 5) + (level > 8)) << 6;
-
-	/* header check field */
-	dst[1] |= 31 - ((dst[0] << 8) | dst[1]) % 31;
-
-	adler = adler32(1, src, ssize);
-	dst[n + 2] = adler >> 24;
-	dst[n + 3] = adler >> 16;
-	dst[n + 4] = adler >> 8;
-	dst[n + 5] = adler;
-
-	return n + 6;
-}
--- a/os/boot/libflate/flateerr.c
+++ /dev/null
@@ -1,22 +1,0 @@
-#include "lib9.h"
-#include <flate.h>
-
-char *
-flateerr(int err)
-{
-	switch(err){
-	case FlateOk:
-		return "no error";
-	case FlateNoMem:
-		return "out of memory";
-	case FlateInputFail:
-		return "input error";
-	case FlateOutputFail:
-		return "output error";
-	case FlateCorrupted:
-		return "corrupted data";
-	case FlateInternal:
-		return "internal error";
-	}
-	return "unknown error";
-}
--- a/os/boot/libflate/inflate.c
+++ /dev/null
@@ -1,692 +1,0 @@
-#include "lib9.h"
-#include <flate.h>
-
-enum {
-	HistorySize=	32*1024,
-	BufSize=	4*1024,
-	MaxHuffBits=	17,	/* maximum bits in a encoded code */
-	Nlitlen=	288,	/* number of litlen codes */
-	Noff=		32,	/* number of offset codes */
-	Nclen=		19,	/* number of codelen codes */
-	LenShift=	10,	/* code = len<<LenShift|code */
-	LitlenBits=	7,	/* number of bits in litlen decode table */
-	OffBits=	6,	/* number of bits in offset decode table */
-	ClenBits=	6,	/* number of bits in code len decode table */
-	MaxFlatBits=	LitlenBits,
-	MaxLeaf=	Nlitlen
-};
-
-typedef struct Input	Input;
-typedef struct History	History;
-typedef struct Huff	Huff;
-
-struct Input
-{
-	int	error;		/* first error encountered, or FlateOk */
-	void	*wr;
-	int	(*w)(void*, void*, int);
-	void	*getr;
-	int	(*get)(void*);
-	ulong	sreg;
-	int	nbits;
-};
-
-struct History
-{
-	uchar	his[HistorySize];
-	uchar	*cp;		/* current pointer in history */
-	int	full;		/* his has been filled up at least once */
-};
-
-struct Huff
-{
-	int	maxbits;	/* max bits for any code */
-	int	minbits;	/* min bits to get before looking in flat */
-	int	flatmask;	/* bits used in "flat" fast decoding table */
-	ulong	flat[1<<MaxFlatBits];
-	ulong	maxcode[MaxHuffBits];
-	ulong	last[MaxHuffBits];
-	ulong	decode[MaxLeaf];
-};
-
-/* litlen code words 257-285 extra bits */
-static int litlenextra[Nlitlen-257] =
-{
-/* 257 */	0, 0, 0,
-/* 260 */	0, 0, 0, 0, 0, 1, 1, 1, 1, 2,
-/* 270 */	2, 2, 2, 3, 3, 3, 3, 4, 4, 4,
-/* 280 */	4, 5, 5, 5, 5, 0, 0, 0
-};
-
-static int litlenbase[Nlitlen-257];
-
-/* offset code word extra bits */
-static int offextra[Noff] =
-{
-	0,  0,  0,  0,  1,  1,  2,  2,  3,  3,
-	4,  4,  5,  5,  6,  6,  7,  7,  8,  8,
-	9,  9,  10, 10, 11, 11, 12, 12, 13, 13,
-	0,  0,
-};
-static int offbase[Noff];
-
-/* order code lengths */
-static int clenorder[Nclen] =
-{
-        16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
-};
-
-/* for static huffman tables */
-static	Huff	litlentab;
-static	Huff	offtab;
-static	uchar	revtab[256];
-
-static int	uncblock(Input *in, History*);
-static int	fixedblock(Input *in, History*);
-static int	dynamicblock(Input *in, History*);
-static int	sregfill(Input *in, int n);
-static int	sregunget(Input *in);
-static int	decode(Input*, History*, Huff*, Huff*);
-static int	hufftab(Huff*, char*, int, int);
-static int	hdecsym(Input *in, Huff *h, int b);
-
-int
-inflateinit(void)
-{
-	char *len;
-	int i, j, base;
-
-	/* byte reverse table */
-	for(i=0; i<256; i++)
-		for(j=0; j<8; j++)
-			if(i & (1<<j))
-				revtab[i] |= 0x80 >> j;
-
-	for(i=257,base=3; i<Nlitlen; i++) {
-		litlenbase[i-257] = base;
-		base += 1<<litlenextra[i-257];
-	}
-	/* strange table entry in spec... */
-	litlenbase[285-257]--;
-
-	for(i=0,base=1; i<Noff; i++) {
-		offbase[i] = base;
-		base += 1<<offextra[i];
-	}
-
-	len = malloc(MaxLeaf);
-	if(len == nil)
-		return FlateNoMem;
-
-	/* static Litlen bit lengths */
-	for(i=0; i<144; i++)
-		len[i] = 8;
-	for(i=144; i<256; i++)
-		len[i] = 9;
-	for(i=256; i<280; i++)
-		len[i] = 7;
-	for(i=280; i<Nlitlen; i++)
-		len[i] = 8;
-
-	if(!hufftab(&litlentab, len, Nlitlen, MaxFlatBits))
-		return FlateInternal;
-
-	/* static Offset bit lengths */
-	for(i=0; i<Noff; i++)
-		len[i] = 5;
-
-	if(!hufftab(&offtab, len, Noff, MaxFlatBits))
-		return FlateInternal;
-	free(len);
-
-	return FlateOk;
-}
-
-int
-inflate(void *wr, int (*w)(void*, void*, int), void *getr, int (*get)(void*))
-{
-	History *his;
-	Input in;
-	int final, type;
-
-	his = malloc(sizeof(History));
-	if(his == nil)
-		return FlateNoMem;
-	his->cp = his->his;
-	his->full = 0;
-	in.getr = getr;
-	in.get = get;
-	in.wr = wr;
-	in.w = w;
-	in.nbits = 0;
-	in.sreg = 0;
-	in.error = FlateOk;
-
-	do {
-		if(!sregfill(&in, 3))
-			goto bad;
-		final = in.sreg & 0x1;
-		type = (in.sreg>>1) & 0x3;
-		in.sreg >>= 3;
-		in.nbits -= 3;
-		switch(type) {
-		default:
-			in.error = FlateCorrupted;
-			goto bad;
-		case 0:
-			/* uncompressed */
-			if(!uncblock(&in, his))
-				goto bad;
-			break;
-		case 1:
-			/* fixed huffman */
-			if(!fixedblock(&in, his))
-				goto bad;
-			break;
-		case 2:
-			/* dynamic huffman */
-			if(!dynamicblock(&in, his))
-				goto bad;
-			break;
-		}
-	} while(!final);
-
-	if(his->cp != his->his && (*w)(wr, his->his, his->cp - his->his) != his->cp - his->his) {
-		in.error = FlateOutputFail;
-		goto bad;
-	}
-
-	if(!sregunget(&in))
-		goto bad;
-
-	free(his);
-	if(in.error != FlateOk)
-		return FlateInternal;
-	return FlateOk;
-
-bad:
-	free(his);
-	if(in.error == FlateOk)
-		return FlateInternal;
-	return in.error;
-}
-
-static int
-uncblock(Input *in, History *his)
-{
-	int len, nlen, c;
-	uchar *hs, *hp, *he;
-
-	if(!sregunget(in))
-		return 0;
-	len = (*in->get)(in->getr);
-	len |= (*in->get)(in->getr)<<8;
-	nlen = (*in->get)(in->getr);
-	nlen |= (*in->get)(in->getr)<<8;
-	if(len != (~nlen&0xffff)) {
-		in->error = FlateCorrupted;
-		return 0;
-	}
-
-	hp = his->cp;
-	hs = his->his;
-	he = hs + HistorySize;
-
-	while(len > 0) {
-		c = (*in->get)(in->getr);
-		if(c < 0)
-			return 0;
-		*hp++ = c;
-		if(hp == he) {
-			his->full = 1;
-			if((*in->w)(in->wr, hs, HistorySize) != HistorySize) {
-				in->error = FlateOutputFail;
-				return 0;
-			}
-			hp = hs;
-		}
-		len--;
-	}
-
-	his->cp = hp;
-
-	return 1;
-}
-
-static int
-fixedblock(Input *in, History *his)
-{
-	return decode(in, his, &litlentab, &offtab);
-}
-
-static int
-dynamicblock(Input *in, History *his)
-{
-	Huff *lentab, *offtab;
-	char *len;
-	int i, j, n, c, nlit, ndist, nclen, res, nb;
-
-	if(!sregfill(in, 14))
-		return 0;
-	nlit = (in->sreg&0x1f) + 257;
-	ndist = ((in->sreg>>5) & 0x1f) + 1;
-	nclen = ((in->sreg>>10) & 0xf) + 4;
-	in->sreg >>= 14;
-	in->nbits -= 14;
-
-	if(nlit > Nlitlen || ndist > Noff || nlit < 257) {
-		in->error = FlateCorrupted;
-		return 0;
-	}
-
-	/* huff table header */
-	len = malloc(Nlitlen+Noff);
-	lentab = malloc(sizeof(Huff));
-	offtab = malloc(sizeof(Huff));
-	if(len == nil || lentab == nil || offtab == nil){
-		in->error = FlateNoMem;
-		goto bad;
-	}
-	for(i=0; i < Nclen; i++)
-		len[i] = 0;
-	for(i=0; i<nclen; i++) {
-		if(!sregfill(in, 3))
-			goto bad;
-		len[clenorder[i]] = in->sreg & 0x7;
-		in->sreg >>= 3;
-		in->nbits -= 3;
-	}
-
-	if(!hufftab(lentab, len, Nclen, ClenBits)){
-		in->error = FlateCorrupted;
-		goto bad;
-	}
-
-	n = nlit+ndist;
-	for(i=0; i<n;) {
-		nb = lentab->minbits;
-		for(;;){
-			if(in->nbits<nb && !sregfill(in, nb))
-				goto bad;
-			c = lentab->flat[in->sreg & lentab->flatmask];
-			nb = c & 0xff;
-			if(nb > in->nbits){
-				if(nb != 0xff)
-					continue;
-				c = hdecsym(in, lentab, c);
-				if(c < 0)
-					goto bad;
-			}else{
-				c >>= 8;
-				in->sreg >>= nb;
-				in->nbits -= nb;
-			}
-			break;
-		}
-
-		if(c < 16) {
-			j = 1;
-		} else if(c == 16) {
-			if(in->nbits<2 && !sregfill(in, 2))
-				goto bad;
-			j = (in->sreg&0x3)+3;
-			in->sreg >>= 2;
-			in->nbits -= 2;
-			if(i == 0) {
-				in->error = FlateCorrupted;
-				goto bad;
-			}
-			c = len[i-1];
-		} else if(c == 17) {
-			if(in->nbits<3 && !sregfill(in, 3))
-				goto bad;
-			j = (in->sreg&0x7)+3;
-			in->sreg >>= 3;
-			in->nbits -= 3;
-			c = 0;
-		} else if(c == 18) {
-			if(in->nbits<7 && !sregfill(in, 7))
-				goto bad;
-			j = (in->sreg&0x7f)+11;
-			in->sreg >>= 7;
-			in->nbits -= 7;
-			c = 0;
-		} else {
-			in->error = FlateCorrupted;
-			goto bad;
-		}
-
-		if(i+j > n) {
-			in->error = FlateCorrupted;
-			goto bad;
-		}
-
-		while(j) {
-			len[i] = c;
-			i++;
-			j--;
-		}
-	}
-
-	if(!hufftab(lentab, len, nlit, LitlenBits)
-	|| !hufftab(offtab, &len[nlit], ndist, OffBits)){
-		in->error = FlateCorrupted;
-		goto bad;
-	}
-
-	res = decode(in, his, lentab, offtab);
-
-	free(len);
-	free(lentab);
-	free(offtab);
-
-	return res;
-
-bad:
-	free(len);
-	free(lentab);
-	free(offtab);
-	return 0;
-}
-
-static int
-decode(Input *in, History *his, Huff *litlentab, Huff *offtab)
-{
-	int len, off;
-	uchar *hs, *hp, *hq, *he;
-	int c;
-	int nb;
-
-	hs = his->his;
-	he = hs + HistorySize;
-	hp = his->cp;
-
-	for(;;) {
-		nb = litlentab->minbits;
-		for(;;){
-			if(in->nbits<nb && !sregfill(in, nb))
-				return 0;
-			c = litlentab->flat[in->sreg & litlentab->flatmask];
-			nb = c & 0xff;
-			if(nb > in->nbits){
-				if(nb != 0xff)
-					continue;
-				c = hdecsym(in, litlentab, c);
-				if(c < 0)
-					return 0;
-			}else{
-				c >>= 8;
-				in->sreg >>= nb;
-				in->nbits -= nb;
-			}
-			break;
-		}
-
-		if(c < 256) {
-			/* literal */
-			*hp++ = c;
-			if(hp == he) {
-				his->full = 1;
-				if((*in->w)(in->wr, hs, HistorySize) != HistorySize) {
-					in->error = FlateOutputFail;
-					return 0;
-				}
-				hp = hs;
-			}
-			continue;
-		}
-
-		if(c == 256)
-			break;
-
-		if(c > 285) {
-			in->error = FlateCorrupted;
-			return 0;
-		}
-
-		c -= 257;
-		nb = litlenextra[c];
-		if(in->nbits < nb && !sregfill(in, nb))
-			return 0;
-		len = litlenbase[c] + (in->sreg & ((1<<nb)-1));
-		in->sreg >>= nb;
-		in->nbits -= nb;
-
-		/* get offset */
-		nb = offtab->minbits;
-		for(;;){
-			if(in->nbits<nb && !sregfill(in, nb))
-				return 0;
-			c = offtab->flat[in->sreg & offtab->flatmask];
-			nb = c & 0xff;
-			if(nb > in->nbits){
-				if(nb != 0xff)
-					continue;
-				c = hdecsym(in, offtab, c);
-				if(c < 0)
-					return 0;
-			}else{
-				c >>= 8;
-				in->sreg >>= nb;
-				in->nbits -= nb;
-			}
-			break;
-		}
-
-		if(c > 29) {
-			in->error = FlateCorrupted;
-			return 0;
-		}
-
-		nb = offextra[c];
-		if(in->nbits < nb && !sregfill(in, nb))
-			return 0;
-
-		off = offbase[c] + (in->sreg & ((1<<nb)-1));
-		in->sreg >>= nb;
-		in->nbits -= nb;
-
-		hq = hp - off;
-		if(hq < hs) {
-			if(!his->full) {
-				in->error = FlateCorrupted;
-				return 0;
-			}
-			hq += HistorySize;
-		}
-
-		/* slow but correct */
-		while(len) {
-			*hp = *hq;
-			hq++;
-			hp++;
-			if(hq >= he)
-				hq = hs;
-			if(hp == he) {
-				his->full = 1;
-				if((*in->w)(in->wr, hs, HistorySize) != HistorySize) {
-					in->error = FlateOutputFail;
-					return 0;
-				}
-				hp = hs;
-			}
-			len--;
-		}
-
-	}
-
-	his->cp = hp;
-
-	return 1;
-}
-
-static int
-revcode(int c, int b)
-{
-	/* shift encode up so it starts on bit 15 then reverse */
-	c <<= (16-b);
-	c = revtab[c>>8] | (revtab[c&0xff]<<8);
-	return c;
-}
-
-/*
- * construct the huffman decoding arrays and a fast lookup table.
- * the fast lookup is a table indexed by the next flatbits bits,
- * which returns the symbol matched and the number of bits consumed,
- * or the minimum number of bits needed and 0xff if more than flatbits
- * bits are needed.
- *
- * flatbits can be longer than the smallest huffman code,
- * because shorter codes are assigned smaller lexical prefixes.
- * this means assuming zeros for the next few bits will give a
- * conservative answer, in the sense that it will either give the
- * correct answer, or return the minimum number of bits which
- * are needed for an answer.
- */
-static int
-hufftab(Huff *h, char *hb, int maxleaf, int flatbits)
-{
-	ulong bitcount[MaxHuffBits];
-	ulong c, fc, ec, mincode, code, nc[MaxHuffBits];
-	int i, b, minbits, maxbits;
-
-	for(i = 0; i < MaxHuffBits; i++)
-		bitcount[i] = 0;
-	maxbits = -1;
-	minbits = MaxHuffBits + 1;
-	for(i=0; i < maxleaf; i++){
-		b = hb[i];
-		if(b){
-			bitcount[b]++;
-			if(b < minbits)
-				minbits = b;
-			if(b > maxbits)
-				maxbits = b;
-		}
-	}
-
-	h->maxbits = maxbits;
-	if(maxbits <= 0){
-		h->maxbits = 0;
-		h->minbits = 0;
-		h->flatmask = 0;
-		return 1;
-	}
-	code = 0;
-	c = 0;
-	for(b = 0; b <= maxbits; b++){
-		h->last[b] = c;
-		c += bitcount[b];
-		mincode = code << 1;
-		nc[b] = mincode;
-		code = mincode + bitcount[b];
-		if(code > (1 << b))
-			return 0;
-		h->maxcode[b] = code - 1;
-		h->last[b] += code - 1;
-	}
-
-	if(flatbits > maxbits)
-		flatbits = maxbits;
-	h->flatmask = (1 << flatbits) - 1;
-	if(minbits > flatbits)
-		minbits = flatbits;
-	h->minbits = minbits;
-
-	b = 1 << flatbits;
-	for(i = 0; i < b; i++)
-		h->flat[i] = ~0;
-
-	/*
-	 * initialize the flat table to include the minimum possible
-	 * bit length for each code prefix
-	 */
-	for(b = maxbits; b > flatbits; b--){
-		code = h->maxcode[b];
-		if(code == -1)
-			break;
-		mincode = code + 1 - bitcount[b];
-		mincode >>= b - flatbits;
-		code >>= b - flatbits;
-		for(; mincode <= code; mincode++)
-			h->flat[revcode(mincode, flatbits)] = (b << 8) | 0xff;
-	}
-
-	for(i = 0; i < maxleaf; i++){
-		b = hb[i];
-		if(b <= 0)
-			continue;
-		c = nc[b]++;
-		if(b <= flatbits){
-			code = (i << 8) | b;
-			ec = (c + 1) << (flatbits - b);
-			if(ec > (1<<flatbits))
-				return 0;	/* this is actually an internal error */
-			for(fc = c << (flatbits - b); fc < ec; fc++)
-				h->flat[revcode(fc, flatbits)] = code;
-		}
-		if(b > minbits){
-			c = h->last[b] - c;
-			if(c >= maxleaf)
-				return 0;
-			h->decode[c] = i;
-		}
-	}
-	return 1;
-}
-
-static int
-hdecsym(Input *in, Huff *h, int nb)
-{
-	long c;
-
-	if((nb & 0xff) == 0xff)
-		nb = nb >> 8;
-	else
-		nb = nb & 0xff;
-	for(; nb <= h->maxbits; nb++){
-		if(in->nbits<nb && !sregfill(in, nb))
-			return -1;
-		c = revtab[in->sreg&0xff]<<8;
-		c |= revtab[(in->sreg>>8)&0xff];
-		c >>= (16-nb);
-		if(c <= h->maxcode[nb]){
-			in->sreg >>= nb;
-			in->nbits -= nb;
-			return h->decode[h->last[nb] - c];
-		}
-	}
-	in->error = FlateCorrupted;
-	return -1;
-}
-
-static int
-sregfill(Input *in, int n)
-{
-	int c;
-
-	while(n > in->nbits) {
-		c = (*in->get)(in->getr);
-		if(c < 0){
-			in->error = FlateInputFail;
-			return 0;
-		}
-		in->sreg |= c<<in->nbits;
-		in->nbits += 8;
-	}
-	return 1;
-}
-
-static int
-sregunget(Input *in)
-{
-	if(in->nbits >= 8) {
-		in->error = FlateInternal;
-		return 0;
-	}
-
-	/* throw other bits on the floor */
-	in->nbits = 0;
-	in->sreg = 0;
-	return 1;
-}
--- a/os/boot/libflate/inflateblock.c
+++ /dev/null
@@ -1,53 +1,0 @@
-#include "lib9.h"
-#include <flate.h>
-
-typedef struct Block	Block;
-
-struct Block
-{
-	uchar	*pos;
-	uchar	*limit;
-};
-
-static int
-blgetc(void *vb)
-{
-	Block *b;
-
-	b = vb;
-	if(b->pos >= b->limit)
-		return -1;
-	return *b->pos++;
-}
-
-static int
-blwrite(void *vb, void *buf, int n)
-{
-	Block *b;
-
-	b = vb;
-
-	if(n > b->limit - b->pos)
-		n = b->limit - b->pos;
-	memmove(b->pos, buf, n);
-	b->pos += n;
-	return n;
-}
-
-int
-inflateblock(uchar *dst, int dsize, uchar *src, int ssize)
-{
-	Block bd, bs;
-	int ok;
-
-	bs.pos = src;
-	bs.limit = src + ssize;
-
-	bd.pos = dst;
-	bd.limit = dst + dsize;
-
-	ok = inflate(&bd, blwrite, &bs, blgetc);
-	if(ok != FlateOk)
-		return ok;
-	return bd.pos - dst;
-}
--- a/os/boot/libflate/inflatezlib.c
+++ /dev/null
@@ -1,65 +1,0 @@
-#include "lib9.h"
-#include <flate.h>
-#include "zlib.h"
-
-typedef struct ZWrite	ZWrite;
-
-struct ZWrite
-{
-	ulong	adler;
-	void	*wr;
-	int	(*w)(void*, void*, int);
-};
-
-static int
-zlwrite(void *vzw, void *buf, int n)
-{
-	ZWrite *zw;
-
-	zw = vzw;
-	zw->adler = adler32(zw->adler, buf, n);
-	n = (*zw->w)(zw->wr, buf, n);
-	if(n <= 0)
-		return n;
-	return n;
-}
-
-int
-inflatezlib(void *wr, int (*w)(void*, void*, int), void *getr, int (*get)(void*))
-{
-	ZWrite zw;
-	ulong v;
-	int c, i;
-
-	c = (*get)(getr);
-	if(c < 0)
-		return FlateInputFail;
-	i = (*get)(getr);
-	if(i < 0)
-		return FlateInputFail;
-
-	if(((c << 8) | i) % 31)
-		return FlateCorrupted;
-	if((c & ZlibMeth) != ZlibDeflate
-	|| (c & ZlibCInfo) > ZlibWin32k)
-		return FlateCorrupted;
-
-	zw.wr = wr;
-	zw.w = w;
-	zw.adler = 1;
-	i = inflate(&zw, zlwrite, getr, get);
-	if(i != FlateOk)
-		return i;
-
-	v = 0;
-	for(i = 0; i < 4; i++){
-		c = (*get)(getr);
-		if(c < 0)
-			return FlateInputFail;
-		v = (v << 8) | c;
-	}
-	if(zw.adler != v)
-		return FlateCorrupted;
-
-	return FlateOk;
-}
--- a/os/boot/libflate/inflatezlibblock.c
+++ /dev/null
@@ -1,67 +1,0 @@
-#include "lib9.h"
-#include <flate.h>
-#include "zlib.h"
-
-typedef struct Block	Block;
-
-struct Block
-{
-	uchar	*pos;
-	uchar	*limit;
-};
-
-static int
-blgetc(void *vb)
-{
-	Block *b;
-
-	b = vb;
-	if(b->pos >= b->limit)
-		return -1;
-	return *b->pos++;
-}
-
-static int
-blwrite(void *vb, void *buf, int n)
-{
-	Block *b;
-
-	b = vb;
-
-	if(n > b->limit - b->pos)
-		n = b->limit - b->pos;
-	memmove(b->pos, buf, n);
-	b->pos += n;
-	return n;
-}
-
-int
-inflatezlibblock(uchar *dst, int dsize, uchar *src, int ssize)
-{
-	Block bd, bs;
-	int ok;
-
-	if(ssize < 6)
-		return FlateInputFail;
-
-	if(((src[0] << 8) | src[1]) % 31)
-		return FlateCorrupted;
-	if((src[0] & ZlibMeth) != ZlibDeflate
-	|| (src[0] & ZlibCInfo) > ZlibWin32k)
-		return FlateCorrupted;
-
-	bs.pos = src + 2;
-	bs.limit = src + ssize - 6;
-
-	bd.pos = dst;
-	bd.limit = dst + dsize;
-
-	ok = inflate(&bd, blwrite, &bs, blgetc);
-	if(ok != FlateOk)
-		return ok;
-
-	if(adler32(1, dst, bs.pos - dst) != ((bs.pos[0] << 24) | (bs.pos[1] << 16) | (bs.pos[2] << 8) | bs.pos[3]))
-		return FlateCorrupted;
-
-	return bd.pos - dst;
-}
--- a/os/boot/libflate/mkfile
+++ /dev/null
@@ -1,21 +1,0 @@
-<../../../mkconfig
-
-LIB=libflate.a
-OFILES=\
-	deflate.$O\
-	deflatezlib.$O\
-	deflateblock.$O\
-	deflatezlibblock.$O\
-	inflate.$O\
-	inflatezlib.$O\
-	inflateblock.$O\
-	inflatezlibblock.$O\
-	flateerr.$O\
-	crc.$O\
-	adler.$O\
-
-HFILES=\
-	$ROOT/include/flate.h\
-	zlib.h\
-
-<$ROOT/mkfiles/mksyslib-$SHELLTYPE
--- a/os/boot/libflate/zlib.h
+++ /dev/null
@@ -1,11 +1,0 @@
-/*
- * zlib header fields
- */
-enum
-{
-	ZlibMeth	= 0x0f,			/* mask of compression methods */
-	ZlibDeflate	= 0x08,
-
-	ZlibCInfo	= 0xf0,			/* mask of compression aux. info */
-	ZlibWin32k	= 0x70,			/* 32k history window */
-};
--- a/os/boot/mpc/NOTICE
+++ /dev/null
@@ -1,3 +1,0 @@
-Inferno® Copyright © 1996-1999 Lucent Technologies Inc.  All rights reserved.
-PowerPC support Copyright © 1995-1997 C H Forsyth (forsyth@caldo.demon.co.uk).  All rights reserved.
-MPC8xx Inferno PowerPC port Copyright © 1998-2003 Vita Nuova Holdings Limited.  All rights reserved.
--- a/os/boot/mpc/alarm.c
+++ /dev/null
@@ -1,123 +1,0 @@
-#include	"u.h"
-#include	"lib.h"
-#include	"mem.h"
-#include	"dat.h"
-#include	"fns.h"
-#include	"io.h"
-#define	MAXALARM	10
-
-Alarm	alarmtab[MAXALARM];
-
-/*
- * Insert new into list after where
- */
-void
-insert(List **head, List *where, List *new)
-{
-	if(where == 0){
-		new->next = *head;
-		*head = new;
-	}else{
-		new->next = where->next;
-		where->next = new;
-	}
-		
-}
-
-/*
- * Delete old from list.  where->next is known to be old.
- */
-void
-delete(List **head, List *where, List *old)
-{
-	if(where == 0){
-		*head = old->next;
-		return;
-	}
-	where->next = old->next;
-}
-
-Alarm*
-newalarm(void)
-{
-	int i;
-	Alarm *a;
-
-	for(i=0,a=alarmtab; i < nelem(alarmtab); i++,a++)
-		if(a->busy==0 && a->f==0){
-			a->f = 0;
-			a->arg = 0;
-			a->busy = 1;
-			return a;
-		}
-	panic("newalarm");
-	return 0;	/* not reached */
-}
-
-Alarm*
-alarm(int ms, void (*f)(Alarm*), void *arg)
-{
-	Alarm *a, *w, *pw;
-	ulong s;
-
-	if(ms < 0)
-		ms = 0;
-	s = splhi();
-	a = newalarm();
-	a->dt = MS2TK(ms);
-	a->f = f;
-	a->arg = arg;
-	pw = 0;
-	for(w=m->alarm; w; pw=w, w=w->next){
-		if(w->dt <= a->dt){
-			a->dt -= w->dt;
-			continue;
-		}
-		w->dt -= a->dt;
-		break;
-	}
-	insert(&m->alarm, pw, a);
-	splx(s);
-	return a;
-}
-
-void
-cancel(Alarm *a)
-{
-	a->f = 0;
-}
-
-void
-alarminit(void)
-{
-}
-
-#define NA 10		/* alarms per clock tick */
-void
-checkalarms(void)
-{
-	int i, n, s;
-	Alarm *a;
-	void (*f)(Alarm*);
-	Alarm *alist[NA];
-
-	s = splhi();
-	a = m->alarm;
-	if(a){
-		for(n=0; a && a->dt<=0 && n<NA; n++){
-			alist[n] = a;
-			delete(&m->alarm, 0, a);
-			a = m->alarm;
-		}
-		if(a)
-			a->dt--;
-
-		for(i = 0; i < n; i++){
-			f = alist[i]->f;	/* avoid race with cancel */
-			if(f)
-				(*f)(alist[i]);
-			alist[i]->busy = 0;
-		}
-	}
-	splx(s);
-}
--- a/os/boot/mpc/all.h
+++ /dev/null
@@ -1,6 +1,0 @@
-#include	"u.h"
-#include	"lib.h"
-#include	"dat.h"
-#include	"fns.h"
-#include	"mem.h"
-#include	"io.h"
--- a/os/boot/mpc/archfads.c
+++ /dev/null
@@ -1,355 +1,0 @@
-#include	"u.h"
-#include	"lib.h"
-#include	"mem.h"
-#include	"dat.h"
-#include	"fns.h"
-#include	"io.h"
-#include	"archfads.h"
-
-/*
- * board-specific support for the 8xxFADS (including 860/21 development system)
- */
-
-enum {
-	USESDRAM = 0,	/* set to 1 if kernel is to use SDRAM as well as DRAM */
-
-	/* sccr */
-	RTSEL = IBIT(8),	/* =0, select main oscillator (OSCM); =1, select external crystal (EXTCLK) */
-	RTDIV = IBIT(7),	/* =0, divide by 4; =1, divide by 512 */
-	CRQEN = IBIT(9),	/* =1, switch to high frequency when CPM active */
-	PRQEN = IBIT(10),	/* =1, switch to high frequency when interrupt pending */
-
-	/* plprcr */
-	CSRC = IBIT(21),	/* =0, clock is DFNH; =1, clock is DFNL */
-};
-
-/*
- * called early in main.c, after machinit:
- * using board and architecture specific registers, initialise
- * 8xx registers that need it and complete initialisation of the Mach structure.
- */
-void
-archinit(void)
-{
-	IMM *io;
-	int mf, isfads, sysmhz, t;
-	ulong v;
-
-	v = getimmr() & 0xFFFF;
-	isfads = 0;		/* assume it's the 860/821 board */
-	sysmhz = 40;
-	switch(v>>8){
-	case 0x00:	t = 0x86000; break;
-	case 0x20:	t = 0x82300; isfads = 1; break;
-	case 0x21:	t = 0x823a0; isfads = 1; break;
-	default:	t = 0; break;
-	}
-	m->cputype = t;
-	m->bcsr = KADDR(BCSRMEM);
-	m->bcsr[1] |= DisableRS232a | DisableIR | DisableEther | DisablePCMCIA | DisableRS232b;
-	m->bcsr[1] &= ~(DisableDRAM|DisableFlash);
-	if(isfads){
-		sysmhz = 50;
-		m->bcsr[1] &= ~EnableSDRAM;
-		m->bcsr[4] &= ~(EnableVideoClock|EnableVideoPort);
-		m->bcsr[4] |= DisableVideoLamp;
-	}
-	io = m->iomem;
-	if(1 || io->sccr & IBIT(7)){	/* RTDIV=1 */
-		/* oscillator frequency can't be determined independently: check a switch */
-		if((m->bcsr[2]>>19)&(1<<2))
-			m->clockgen = 5*MHz;
-		else
-			m->clockgen = 4*MHz;
-	} else
-		m->clockgen = 32768;
-	mf = (sysmhz*MHz)/m->clockgen;
-	m->cpuhz = m->clockgen*mf;
-	io->plprcrk = KEEP_ALIVE_KEY;
-	io->plprcr &= ~IBIT(21);	/* general system clock is DFNH */
-	io->plprcr = (io->plprcr & ((1<<20)-1)) | ((mf-1)<<20);
-	io->mptpr = 0x0400;	/* memory prescaler = 16 for refresh */
-	io->plprcrk = ~KEEP_ALIVE_KEY;
-	if(isfads){
-		m->bcsr[1] |= EnableSDRAM;
-		sdraminit(SDRAMMEM);
-		if(!USESDRAM)
-			m->bcsr[1] &= ~EnableSDRAM;	/* tells kernel not to map it */
-	}
-}
-
-static void
-archidprint(void)
-{
-	int f, i;
-	ulong v;
-
-	/* 8xx and FADS specific */
-	print("IMMR: ");
-	v = getimmr() & 0xFFFF;
-	switch(v>>8){
-	case 0x00:	print("MPC860/821"); break;
-	case 0x20:	print("MPC823"); break;
-	case 0x21:	print("MPC823A"); break;
-	default:	print("Type #%lux", v>>8); break;
-	}
-	print(", mask #%lux\n", v&0xFF);
-	v = m->bcsr[3]>>16;
-	print("MPC8xxFADS rev %lud, DB: ", ((v>>4)&8)|((v>>1)&4)|(v&3));
-	f = (v>>8)&0x3F;
-	switch(f){
-	default:	print("ID#%x", f); break;
-	case 0x00:	print("MPC860/821"); break;
-	case 0x01:	print("MPC813"); break;
-	case 0x02:	print("MPC821"); break;
-	case 0x03:	print("MPC823"); break;
-	case 0x20:	print("MPC801"); break;
-	case 0x21:	print("MPC850"); break;
-	case 0x22:	print("MPC860"); break;
-	case 0x23:	print("MPC860SAR"); break;
-	case 0x24:	print("MPC860T"); break;
-	}
-	print("ADS, rev #%lux\n", (m->bcsr[2]>>16)&7);
-	for(i=0; i<=4; i++)
-		print("BCSR%d: %8.8lux\n", i, m->bcsr[i]);
-	v = m->bcsr[2];
-	f = (v>>28)&0xF;
-	switch(f){
-	default:	print("Unknown"); break;
-	case 4:	print("SM732A2000/SM73228 - 8M SIMM"); break;
-	case 5:	print("SM732A1000A/SM73218 - 4M SIMM"); break;
-	case 6:	print("MCM29080 - 8M SIMM"); break;
-	case 7:	print("MCM29040 - 4M SIMM"); break;
-	case 8:	print("MCM29020 - 2M SIMM"); break;
-	}
-	switch((m->bcsr[3]>>20)&7){
-	default:	i = 0; break;
-	case 1:	i = 150; break;
-	case 2:	i = 120; break;
-	case 3:	i = 90; break;
-	}
-	print(" flash, %dns\n", i);
-	f = (v>>23)&0xF;
-	switch(f&3){
-	case 0:	i = 4; break;
-	case 1:	i = 32; break;
-	case 2:	i = 16; break;
-	case 3:	i = 8; break;
-	}
-	print("%dM SIMM, ", i);
-	switch(f>>2){
-	default: 	i = 0; break;
-	case 2:	i = 70; break;
-	case 3:	i = 60; break;
-	}
-	print("%dns\n", i);
-	print("options: #%lux\n", (m->bcsr[2]>>19)&0xF);
-	print("plprcr=%8.8lux sccr=%8.8lux\n", m->iomem->plprcr, m->iomem->sccr);
-}
-
-void
-cpuidprint(void)
-{
-	int t;
-
-	print("PVR: ");
-	t = getpvr()>>16;
-	switch(t){
-	case 0x01:	print("MPC601"); break;
-	case 0x03:	print("MPC603"); break;
-	case 0x04:	print("MPC604"); break;
-	case 0x06:	print("MPC603e"); break;
-	case 0x07:	print("MPC603e-v7"); break;
-	case 0x50:	print("MPC8xx"); break;
-	default:	print("PowerPC version #%x", t); break;
-	}
-	print(", revision #%lux\n", getpvr()&0xffff);
-	archidprint();
-	print("%lud MHz system\n", m->cpuhz/MHz);
-	print("\n");
-}
-
-static	char*	defplan9ini[2] = {
-	/* 860/821 */
-	"ether0=type=SCC port=1 ea=00108bf12900\r\n"
-	"vgasize=640x480x8\r\n"
-	"kernelpercent=40\r\n"
-	"console=0 lcd\r\nbaud=9600\r\n",
-
-	/* 823 */
-	"ether0=type=SCC port=2 ea=00108bf12900\r\n"
-	"vgasize=640x480x8\r\n"
-	"kernelpercent=40\r\n"
-	"console=0 lcd\r\nbaud=9600\r\n",
-};
-
-char *
-archconfig(void)
-{
-	print("Using default configuration\n");
-	return defplan9ini[MPCMODEL(m->cputype) == 0x823];
-}
-
-/*
- * provide value for #r/switch (devrtc.c)
- */
-int
-archoptionsw(void)
-{
-	return (m->bcsr[2]>>19)&0xF;	/* value of switch DS1 */
-}
-
-/*
- * invoked by clock.c:/^clockintr
- */
-static void
-twinkle(void)
-{
-	if(m->ticks%MS2TK(1000) == 0)
-		m->bcsr[4] ^= DisableLamp;
-}
-
-void	(*archclocktick)(void) = twinkle;
-
-/*
- * for flash.c:/^flashreset
- * retrieve flash type, virtual base and length and return 0;
- * return -1 on error (no flash)
- */
-int
-archflashreset(char *type, void **addr, long *length)
-{
-	char *t;
-	int mbyte;
-
-	if((m->iomem->memc[0].base & 1) == 0)
-		return -1;		/* shouldn't happen */
-	switch((m->bcsr[2]>>28)&0xF){
-	default:	return -1;	/* unknown or not there */
-	case 4:	mbyte=8; t = "SM732x8"; break;
-	case 5:	mbyte=4; t = "SM732x8"; break;
-	case 6:	mbyte=8; t = "AMD29F0x0"; break;
-	case 7:	mbyte=4; t = "AMD29F0x0"; break;
-	case 8:	mbyte=2; t = "AMD29F0x0"; break;
-	}
-	strcpy(type, t);
-	*addr = KADDR(FLASHMEM);
-	*length = mbyte*1024*1024;
-	return 0;
-}
-
-/*
- * enable the clocks for the given SCC ether and reveal them to the caller.
- * do anything else required to prepare the transceiver (eg, set full-duplex, reset loopback).
- */
-int
-archetherenable(int cpmid, int *rcs, int *tcs)
-{
-	IMM *io;
-
-	switch(cpmid){
-	default:
-		/* no other SCCs are wired on the FADS board */
-		return -1;
-
-	case SCC2ID:	/* assume 8xxFADS board with 823DABS */
-		io = ioplock();
-		m->bcsr[1] |= DisableIR|DisableRS232b;
-		m->bcsr[1] &= ~DisableEther;
-		io->papar |= SIBIT(6)|SIBIT(5);	/* enable CLK2 and CLK3 */
-		io->padir &= ~(SIBIT(6)|SIBIT(5));
-
-		/* ETHLOOP etc set in BCSR elsewhere */
-		*rcs = CLK2;
-		*tcs = CLK3;
-		iopunlock();
-		break;
-
-	case SCC1ID:	/* assume 860/21 development board */
-		io = ioplock();
-		m->bcsr[1] |= DisableIR|DisableRS232b;	/* TO DO: might not be shared with RS232b */
-		m->bcsr[1] &= ~DisableEther;
-		io->papar |= SIBIT(6)|SIBIT(7);	/* enable CLK2 and CLK1 */
-		io->padir &= ~(SIBIT(6)|SIBIT(7));
-
-		/* settings peculiar to 860/821 development board */
-		io->pcpar &= ~(SIBIT(4)|SIBIT(5)|SIBIT(6));	/* ETHLOOP, TPFULDL~, TPSQEL~ */
-		io->pcdir |= SIBIT(4)|SIBIT(5)|SIBIT(6);
-		io->pcdat &= ~SIBIT(4);
-		io->pcdat |= SIBIT(5)|SIBIT(6);
-		*rcs = CLK2;
-		*tcs = CLK1;
-		iopunlock();
-		break;
-	}
-	return 0;
-}
-
-void
-archetherdisable(int id)
-{
-	USED(id);
-	m->bcsr[1] |= DisableEther|DisableIR|DisableRS232b;
-}
-
-/*
- * do anything extra required to enable the UART on the given CPM port
- */
-void
-archenableuart(int id, int irda)
-{
-	switch(id){
-	case SMC1ID:
-		m->bcsr[1] &= ~DisableRS232a;
-		break;
-	case SCC2ID:
-		m->bcsr[1] |= DisableEther|DisableIR|DisableRS232b;
-		if(irda)
-			m->bcsr[1] &= ~DisableIR;
-		else
-			m->bcsr[1] &= ~DisableRS232b;
-		break;
-	default:
-		/* nothing special */
-		break;
-	}
-}
-
-/*
- * do anything extra required to disable the UART on the given CPM port
- */
-void
-archdisableuart(int id)
-{
-	switch(id){
-	case SMC1ID:
-		m->bcsr[1] |= DisableRS232a;
-		break;
-	case SCC2ID:
-		m->bcsr[1] |= DisableIR|DisableRS232b;
-		break;
-	default:
-		/* nothing special */
-		break;
-	}
-}
-
-/*
- * enable/disable the LCD panel's backlight via
- * York touch panel interface (does no harm without it)
- */
-void
-archbacklight(int on)
-{
-	IMM *io;
-
-	delay(2);
-	io = ioplock();
-	io->papar &= ~SIBIT(4);
-	io->padir |= SIBIT(4);
-	if(on)
-		io->padat |= SIBIT(4);
-	else
-		io->padat &= ~SIBIT(4);
-	iopunlock();
-}
--- a/os/boot/mpc/archfads.h
+++ /dev/null
@@ -1,42 +1,0 @@
-
-enum {
-	/* BCSR1 bits */
-	DisableFlash=	IBIT(0),
-	DisableDRAM=	IBIT(1),
-	DisableEther=	IBIT(2),
-	DisableIR=	IBIT(3),
-	DisableRS232a=	IBIT(7),
-	DisablePCMCIA=	IBIT(8),
-	PCCVCCMask=	IBIT(9)|IBIT(15),
-	PCCVPPMask=	IBIT(10)|IBIT(11),
-	DisableRS232b=	IBIT(13),
-	EnableSDRAM=	IBIT(14),
-
-	PCCVCC0V=	IBIT(15)|IBIT(9),
-	PCCVCC5V=	IBIT(9),	/* active low */
-	PCCVCC3V=	IBIT(15),	/* active low */
-	PCCVPP0V=	IBIT(10)|IBIT(11),	/* active low */
-	PCCVPP5V=	IBIT(10),	/* active low */
-	PCCVPP12V=	IBIT(11),	/* active low */
-	PCCVPPHiZ=	IBIT(10)|IBIT(11),
-
-	/* BCSR4 bits */
-	DisableTPDuplex=	IBIT(1),
-	DisableLamp=	IBIT(3),
-	DisableUSB=	IBIT(4),
-	USBFullSpeed=	IBIT(5),
-	DisableUSBVcc=	IBIT(6),
-	DisableVideoLamp=	IBIT(8),
-	EnableVideoClock=	IBIT(9),
-	EnableVideoPort=	IBIT(10),
-	DisableModem=	IBIT(11),
-};
-
-enum {
-	/* memory controller CS assignment on FADS boards */
-	BOOTCS = 0,
-	BCSRCS = 1,
-	DRAM1 = 2,
-	DRAM2 = 3,
-	SDRAM = 4,
-};
--- a/os/boot/mpc/archpaq.c
+++ /dev/null
@@ -1,240 +1,0 @@
-#include	"u.h"
-#include	"lib.h"
-#include	"mem.h"
-#include	"dat.h"
-#include	"fns.h"
-#include	"io.h"
-
-#include	"archpaq.h"
-
-/*
- * board-specific support for the 82x PowerPAQ
- */
-
-enum {
-	SYSMHZ = 50,	/* desired system clock in MHz */
-
-	/* sccr */
-	RTSEL = IBIT(8),	/* =0, select main oscillator (OSCM); =1, select external crystal (EXTCLK) */
-	RTDIV = IBIT(7),	/* =0, divide by 4; =1, divide by 512 */
-	CRQEN = IBIT(9),	/* =1, switch to high frequency when CPM active */
-	PRQEN = IBIT(10),	/* =1, switch to high frequency when interrupt pending */
-
-	/* plprcr */
-	CSRC = IBIT(21),	/* =0, clock is DFNH; =1, clock is DFNL */
-};
-
-/*
- * called early in main.c, after machinit:
- * using board and architecture specific registers, initialise
- * 8xx registers that need it and complete initialisation of the Mach structure.
- */
-void
-archinit(void)
-{
-	IMM *io;
-	int mf, t;
-
-	switch((getimmr()>>8)&0xFF){
-	case 0x00:	t = 0x86000; break;	/* also 821 */
-	case 0x20:	t = 0x82300; break;
-	case 0x21:	t = 0x823a0; break;
-	default:	t = 0; break;
-	}
-	m->cputype = t;
-	m->bcsr = nil;	/* there isn't one */
-	m->clockgen = 32*1024;	/* crystal frequency */
-	io = m->iomem;
-	io->sccrk = KEEP_ALIVE_KEY;
-	io->sccr &= ~RTDIV;	/* divide 32k by 4 */
-	io->sccr |= RTSEL;
-	io->sccrk = ~KEEP_ALIVE_KEY;
-	mf = (SYSMHZ*MHz)/m->clockgen;
-	m->cpuhz = m->clockgen*mf;
-	io->plprcrk = KEEP_ALIVE_KEY;
-	io->plprcr &= ~IBIT(21);	/* general system clock is DFNH */
-	io->plprcr = (io->plprcr & ((1<<20)-1)) | ((mf-1)<<20);
-	io->mptpr = 0x0400;	/* memory prescaler = 16 for refresh */
-	io->plprcrk = ~KEEP_ALIVE_KEY;
-}
-
-void
-cpuidprint(void)
-{
-	int t, v;
-
-	print("PVR: ");
-	t = getpvr()>>16;
-	switch(t){
-	case 0x01:	print("MPC601"); break;
-	case 0x03:	print("MPC603"); break;
-	case 0x04:	print("MPC604"); break;
-	case 0x06:	print("MPC603e"); break;
-	case 0x07:	print("MPC603e-v7"); break;
-	case 0x50:	print("MPC8xx"); break;
-	default:	print("PowerPC version #%x", t); break;
-	}
-	print(", revision #%lux\n", getpvr()&0xffff);
-	print("IMMR: ");
-	v = getimmr() & 0xFFFF;
-	switch(v>>8){
-	case 0x00:	print("MPC860/821"); break;
-	case 0x20:	print("MPC823"); break;
-	case 0x21:	print("MPC823A"); break;
-	default:	print("Type #%lux", v>>8); break;
-	}
-	print(", mask #%lux\n", v&0xFF);
-	print("plprcr=%8.8lux sccr=%8.8lux\n", m->iomem->plprcr, m->iomem->sccr);
-	print("%lud MHz system\n", m->cpuhz/MHz);
-	print("\n");
-}
-
-static	char*	defplan9ini[2] = {
-	/* 860/821 */
-	"ether0=type=SCC port=1 ea=00108bf12900\r\n"
-	"vgasize=640x480x8\r\n"
-	"kernelpercent=40\r\n"
-	"console=0 lcd\r\nbaud=19200\r\n",
-
-	/* 823 */
-	"ether0=type=SCC port=2 ea=00108bf12900\r\n"
-	"vgasize=640x480x8\r\n"
-	"kernelpercent=40\r\n"
-	"console=0 lcd\r\nbaud=19200\r\n",
-};
-
-char *
-archconfig(void)
-{
-	print("Using default configuration\n");
-	return defplan9ini[MPCMODEL(m->cputype) == 0x823];
-}
-
-/*
- * provide value for #r/switch (devrtc.c)
- */
-int
-archoptionsw(void)
-{
-	return 0;
-}
-
-/*
- * invoked by clock.c:/^clockintr
- */
-static void
-twinkle(void)
-{
-	/* no easy-to-use LED on PAQ (they use i2c) */
-}
-
-void	(*archclocktick)(void) = twinkle;
-
-/*
- * for flash.c:/^flashinit
- * retrieve flash type, virtual base and length and return 0;
- * return -1 on error (no flash)
- */
-int
-archflashreset(char *type, void **addr, long *length)
-{
-	strcpy(type, "AMD29F0x0");
-	*addr = KADDR(FLASHMEM);
-	*length = 8*1024*1024;	/* 8mbytes on some models */
-	return 0;
-}
-
-/*
- * enable the clocks for the given SCC ether and reveal them to the caller.
- * do anything else required to prepare the transceiver (eg, set full-duplex, reset loopback).
- */
-int
-archetherenable(int cpmid, int *rcs, int *tcs)
-{
-	USED(cpmid, rcs, tcs);
-	return -1;	/* there isn't an ether on the PAQs */
-}
-
-void
-archetherdisable(int id)
-{
-	USED(id);
-}
-
-/*
- * do anything extra required to enable the UART on the given CPM port
- */
-void
-archenableuart(int id, int irda)
-{
-	IMM *io;
-
-	USED(irda);
-	switch(id){
-	case SMC1ID:
-		io = ioplock();
-		io->pbodr &= ~0xc0;
-		io->pbdat |= 0xc0;
-		io->pcdat |= 0x400;
-		io->pcpar &= ~0x400;
-		io->pcdir |= 0x400;
-		io->pcdat &= ~0x400;	/* enable SMC RS232 buffer */
-		iopunlock();
-		break;
-	case SCC2ID:
-		/* TO DO */
-		break;
-	default:
-		/* nothing special */
-		break;
-	}
-}
-
-/*
- * do anything extra required to disable the UART on the given CPM port
- */
-void
-archdisableuart(int id)
-{
-	switch(id){
-	case SMC1ID:
-		/* TO DO */
-		break;
-	case SCC2ID:
-		/* TO DO */
-		break;
-	default:
-		/* nothing special */
-		break;
-	}
-}
-
-/*
- * enable/disable the LCD panel's backlight via i2c
- */
-void
-archbacklight(int on)
-{
-	uchar msg;
-	IMM *io;
-
-	i2csetup();
-	msg = ~7;
-	i2csend(LEDRegI2C, &msg, 1);
-	io = ioplock();
-	io->pbpar &= ~EnableLCD;
-	io->pbodr &= ~EnableLCD;
-	io->pbdir |= EnableLCD;
-	if(on)
-		io->pbdat |= EnableLCD;
-	else
-		io->pbdat &= ~EnableLCD;
-	iopunlock();
-	if(on){
-		msg = ~(DisablePanelVCC5|DisableTFT);
-		i2csend(PanelI2C, &msg, 1);
-	}else{
-		msg = ~0;
-		i2csend(PanelI2C, &msg, 1);
-	}
-}
--- a/os/boot/mpc/archpaq.h
+++ /dev/null
@@ -1,29 +1,0 @@
-enum {
-	/* memory controller CS assignment on PowerPAQ */
-	BOOTCS = 0,
-	DRAM1 = 1,	/* UPMB */
-	DRAM2 = 2,	/* UPMB */
-	/* CS3 also connected to DRAM */
-	/* CS4 128mbyte 8-bit gpcm, trlx, 15 wait; it's DAC */
-	/* CS5 is external*/
-};
-
-enum {
-	/* I2C addresses */
-	PanelI2C = 0x21<<1,
-	  /* the control bits are active low enables, or high disables */
-	  DisableVGA = ~0xFD,	/* disable VGA signals */
-	  DisableTFT = ~0xFB,	/* disable TFT panel signals */
-	  DisableSPIBus = ~0xF7,	/* disable SPI/I2C to panel */
-	  DisablePanelVCC5 = ~0xEF,	/* disable +5V to panel(s) */
-	  DisablePanelVCC3 = ~0xDF,	/* disable +3.3V to panel(s) */
-	  DisableMonoPanel = ~0xBF,	/* disable mono panel signals */
-	  DisableSPISelect = ~0x7F,	/* disable SPI chip select to LVDS panel */
-	ContrastI2C = 0x2E<<1,
-	LEDRegI2C = 0x20<<1,
-	  DisableGreenLED = ~0xFE,
-	  DisableYellowLED = ~0xFD,
-	  DisableRedLED = ~0xFB,
-
-	EnableLCD = IBIT(23),	/* LCD enable bit in i/o port B */
-};
--- a/os/boot/mpc/boot.h
+++ /dev/null
@@ -1,8 +1,0 @@
-#include <u.h>
-#include "lib.h"
-
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-#include "ureg.h"
--- a/os/boot/mpc/bootp.c
+++ /dev/null
@@ -1,507 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-#include "ip.h"
-
-enum {
-	CHECKSUM = 1,	/* set zero if trouble booting from Linux */
-};
-
-uchar broadcast[Eaddrlen] = {
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-};
-
-static ushort tftpport = 5000;
-static int Id = 1;
-static Netaddr myaddr;
-static Netaddr server;
-
-typedef struct {
-	uchar	header[4];
-	uchar	data[Segsize];
-} Tftp;
-static Tftp tftpb;
-
-static void
-hnputs(uchar *ptr, ushort val)
-{
-	ptr[0] = val>>8;
-	ptr[1] = val;
-}
-
-static void
-hnputl(uchar *ptr, ulong val)
-{
-	ptr[0] = val>>24;
-	ptr[1] = val>>16;
-	ptr[2] = val>>8;
-	ptr[3] = val;
-}
-
-static ulong
-nhgetl(uchar *ptr)
-{
-	return ((ptr[0]<<24) | (ptr[1]<<16) | (ptr[2]<<8) | ptr[3]);
-}
-
-static ushort
-nhgets(uchar *ptr)
-{
-	return ((ptr[0]<<8) | ptr[1]);
-}
-
-static	short	endian	= 1;
-static	char*	aendian	= (char*)&endian;
-#define	LITTLE	*aendian
-
-static ushort
-ptcl_csum(void *a, int len)
-{
-	uchar *addr;
-	ulong t1, t2;
-	ulong losum, hisum, mdsum, x;
-
-	addr = a;
-	losum = 0;
-	hisum = 0;
-	mdsum = 0;
-
-	x = 0;
-	if((ulong)addr & 1) {
-		if(len) {
-			hisum += addr[0];
-			len--;
-			addr++;
-		}
-		x = 1;
-	}
-	while(len >= 16) {
-		t1 = *(ushort*)(addr+0);
-		t2 = *(ushort*)(addr+2);	mdsum += t1;
-		t1 = *(ushort*)(addr+4);	mdsum += t2;
-		t2 = *(ushort*)(addr+6);	mdsum += t1;
-		t1 = *(ushort*)(addr+8);	mdsum += t2;
-		t2 = *(ushort*)(addr+10);	mdsum += t1;
-		t1 = *(ushort*)(addr+12);	mdsum += t2;
-		t2 = *(ushort*)(addr+14);	mdsum += t1;
-		mdsum += t2;
-		len -= 16;
-		addr += 16;
-	}
-	while(len >= 2) {
-		mdsum += *(ushort*)addr;
-		len -= 2;
-		addr += 2;
-	}
-	if(x) {
-		if(len)
-			losum += addr[0];
-		if(LITTLE)
-			losum += mdsum;
-		else
-			hisum += mdsum;
-	} else {
-		if(len)
-			hisum += addr[0];
-		if(LITTLE)
-			hisum += mdsum;
-		else
-			losum += mdsum;
-	}
-
-	losum += hisum >> 8;
-	losum += (hisum & 0xff) << 8;
-	while(hisum = losum>>16)
-		losum = hisum + (losum & 0xffff);
-
-	return ~losum;
-}
-
-static ushort
-ip_csum(uchar *addr)
-{
-	int len;
-	ulong sum = 0;
-
-	len = (addr[0]&0xf)<<2;
-
-	while(len > 0) {
-		sum += addr[0]<<8 | addr[1] ;
-		len -= 2;
-		addr += 2;
-	}
-
-	sum = (sum & 0xffff) + (sum >> 16);
-	sum = (sum & 0xffff) + (sum >> 16);
-	return (sum^0xffff);
-}
-
-static void
-udpsend(int ctlrno, Netaddr *a, void *data, int dlen)
-{
-	Udphdr *uh;
-	Etherhdr *ip;
-	static Etherpkt pkt;
-	int len, ptcllen;
-
-
-	uh = (Udphdr*)&pkt;
-
-	memset(uh, 0, sizeof(Etherpkt));
-	memmove(uh->udpcksum+sizeof(uh->udpcksum), data, dlen);
-
-	/*
-	 * UDP portion
-	 */
-	ptcllen = dlen + (UDP_HDRSIZE-UDP_PHDRSIZE);
-	uh->ttl = 0;
-	uh->udpproto = IP_UDPPROTO;
-	uh->frag[0] = 0;
-	uh->frag[1] = 0;
-	hnputs(uh->udpplen, ptcllen);
-	hnputl(uh->udpsrc, myaddr.ip);
-	hnputs(uh->udpsport, myaddr.port);
-	hnputl(uh->udpdst, a->ip);
-	hnputs(uh->udpdport, a->port);
-	hnputs(uh->udplen, ptcllen);
-	uh->udpcksum[0] = 0;
-	uh->udpcksum[1] = 0;
-	/*dlen = (dlen+1)&~1; */
-	hnputs(uh->udpcksum, ptcl_csum(&uh->ttl, dlen+UDP_HDRSIZE));
-
-	/*
-	 * IP portion
-	 */
-	ip = (Etherhdr*)&pkt;
-	len = sizeof(Udphdr)+dlen;
-	ip->vihl = IP_VER|IP_HLEN;
-	ip->tos = 0;
-	ip->ttl = 255;
-	hnputs(ip->length, len-ETHER_HDR);
-	hnputs(ip->id, Id++);
-	ip->frag[0] = 0;
-	ip->frag[1] = 0;
-	ip->cksum[0] = 0;
-	ip->cksum[1] = 0;
-	hnputs(ip->cksum, ip_csum(&ip->vihl));
-
-	/*
-	 * Ethernet MAC portion
-	 */
-	hnputs(ip->type, ET_IP);
-	memmove(ip->d, a->ea, sizeof(ip->d));
-
-	ethertxpkt(ctlrno, &pkt, len, Timeout);
-}
-
-static void
-nak(int ctlrno, Netaddr *a, int code, char *msg, int report)
-{
-	int n;
-	char buf[128];
-
-	buf[0] = 0;
-	buf[1] = Tftp_ERROR;
-	buf[2] = 0;
-	buf[3] = code;
-	strcpy(buf+4, msg);
-	n = strlen(msg) + 4 + 1;
-	udpsend(ctlrno, a, buf, n);
-	if(report)
-		print("\ntftp: error(%d): %s\n", code, msg);
-}
-
-static int
-udprecv(int ctlrno, Netaddr *a, void *data, int dlen)
-{
-	int n, len;
-	ushort csm;
-	Udphdr *h;
-	ulong addr, timo;
-	static Etherpkt pkt;
-	static int rxactive;
-
-	if(rxactive == 0)
-		timo = 1000;
-	else
-		timo = Timeout;
-	timo += TK2MS(m->ticks);
-	while(timo > TK2MS(m->ticks)){
-		n = etherrxpkt(ctlrno, &pkt, timo-TK2MS(m->ticks));
-		if(n <= 0)
-			continue;
-
-		h = (Udphdr*)&pkt;
-		if(nhgets(h->type) != ET_IP)
-			continue;
-
-		if(ip_csum(&h->vihl)) {
-			print("ip chksum error\n");
-			continue;
-		}
-		if(h->vihl != (IP_VER|IP_HLEN)) {
-			print("ip bad vers/hlen\n");
-			continue;
-		}
-
-		if(h->udpproto != IP_UDPPROTO)
-			continue;
-
-		h->ttl = 0;
-		len = nhgets(h->udplen);
-		hnputs(h->udpplen, len);
-
-		if(CHECKSUM && nhgets(h->udpcksum)) {
-			csm = ptcl_csum(&h->ttl, len+UDP_PHDRSIZE);
-			if(csm != 0) {
-				print("udp chksum error csum #%4lux len %d\n", csm, n);
-				break;
-			}
-		}
-
-		if(a->port != 0 && nhgets(h->udpsport) != a->port)
-			continue;
-
-		addr = nhgetl(h->udpsrc);
-		if(a->ip != Bcastip && addr != a->ip)
-			continue;
-
-		len -= UDP_HDRSIZE-UDP_PHDRSIZE;
-		if(len > dlen) {
-			print("udp: packet too big\n");
-			continue;
-		}
-
-		memmove(data, h->udpcksum+sizeof(h->udpcksum), len);
-		a->ip = addr;
-		a->port = nhgets(h->udpsport);
-		memmove(a->ea, pkt.s, sizeof(a->ea));
-
-		rxactive = 1;
-		return len;
-	}
-
-	return 0;
-}
-
-static int tftpblockno;
-
-static int
-tftpopen(int ctlrno, Netaddr *a, char *name, Tftp *tftp)
-{
-	int i, len, rlen, oport;
-	char buf[Segsize+2];
-
-	buf[0] = 0;
-	buf[1] = Tftp_READ;
-	len = sprint(buf+2, "%s", name) + 2;
-	len += sprint(buf+len+1, "octet") + 2;
-
-	oport = a->port;
-	for(i = 0; i < 5; i++){
-		a->port = oport;
-		udpsend(ctlrno, a, buf, len);
-		a->port = 0;
-		if((rlen = udprecv(ctlrno, a, tftp, sizeof(Tftp))) < sizeof(tftp->header))
-			continue;
-
-		switch((tftp->header[0]<<8)|tftp->header[1]){
-
-		case Tftp_ERROR:
-			print("tftpopen: error (%d): %s\n",
-				(tftp->header[2]<<8)|tftp->header[3], tftp->data);
-			return -1;
-
-		case Tftp_DATA:
-			tftpblockno = 1;
-			len = (tftp->header[2]<<8)|tftp->header[3];
-			if(len != tftpblockno){
-				print("tftpopen: block error: %d\n", len);
-				nak(ctlrno, a, 1, "block error", 0);
-				return -1;
-			}
-			return rlen-sizeof(tftp->header);
-		}
-	}
-
-	print("tftpopen: failed to connect to server\n");
-	return -1;
-}
-
-static int
-tftpread(int ctlrno, Netaddr *a, Tftp *tftp, int dlen)
-{
-	int blockno, len, retry;
-	uchar buf[4];
-
-	buf[0] = 0;
-	buf[1] = Tftp_ACK;
-	buf[2] = tftpblockno>>8;
-	buf[3] = tftpblockno;
-	tftpblockno++;
-
-	dlen += sizeof(tftp->header);
-
-	retry = 0;
-buggery:
-	udpsend(ctlrno, a, buf, sizeof(buf));
-
-	if((len = udprecv(ctlrno, a, tftp, dlen)) < dlen){
-		print("tftpread: %d != %d\n", len, dlen);
-		nak(ctlrno, a, 2, "short read", 0);
-		if(retry++ < 5)
-			goto buggery;
-		return -1;
-	}
-
-	blockno = (tftp->header[2]<<8)|tftp->header[3];
-	if(blockno != tftpblockno){
-		print("?");
-
-		if(blockno == tftpblockno-1 && retry++ < 8)
-			goto buggery;
-		print("tftpread: block error: %d, expected %d\n", blockno, tftpblockno);
-		nak(ctlrno, a, 1, "block error", 0);
-
-		return -1;
-	}
-
-	return len-sizeof(tftp->header);
-}
-
-int
-bootp(int ctlrno, char *file)
-{
-	Bootp req, rep;
-	int i, dlen, segsize, text, data, bss, total;
-	uchar *ea, *addr, *p;
-	ulong entry;
-	Exec *exec;
-	char name[128], *filename, *sysname;
-
-	if((ea = etheraddr(ctlrno)) == 0){
-		print("invalid ctlrno %d\n", ctlrno);
-		return -1;
-	}
-
-	filename = 0;
-	sysname = 0;
-	if(file && *file){
-		strcpy(name, file);
-		if(filename = strchr(name, ':')){
-			if(filename != name && *(filename-1) != '\\'){
-				sysname = name;
-				*filename++ = 0;
-			}
-		}
-		else
-			filename = name;
-	}
-		
-
-	memset(&req, 0, sizeof(req));
-	req.op = Bootrequest;
-	req.htype = 1;			/* ethernet */
-	req.hlen = Eaddrlen;		/* ethernet */
-	memmove(req.chaddr, ea, Eaddrlen);
-
-	myaddr.ip = 0;
-	myaddr.port = BPportsrc;
-	memmove(myaddr.ea, ea, Eaddrlen);
-
-	for(i = 0; i < 10; i++) {
-		server.ip = Bcastip;
-		server.port = BPportdst;
-		memmove(server.ea, broadcast, sizeof(server.ea));
-		udpsend(ctlrno, &server, &req, sizeof(req));
-		if(udprecv(ctlrno, &server, &rep, sizeof(rep)) <= 0)
-			continue;
-		if(memcmp(req.chaddr, rep.chaddr, Eaddrlen))
-			continue;
-		if(rep.htype != 1 || rep.hlen != Eaddrlen)
-			continue;
-		if(sysname == 0 || strcmp(sysname, rep.sname) == 0)
-			break;
-	}
-	if(i >= 10) {
-		print("bootp timed out\n");
-		return -1;
-	}
-
-	if(filename == 0 || *filename == 0)
-		filename = rep.file;
-
-	if(rep.sname[0] != '\0')
-		 print("%s ", rep.sname);
-	print("(%d.%d.%d.%d!%d): %s\n",
-		rep.siaddr[0],
-		rep.siaddr[1],
-		rep.siaddr[2],
-		rep.siaddr[3],
-		server.port,
-		filename);uartwait();
-
-	myaddr.ip = nhgetl(rep.yiaddr);
-	myaddr.port = tftpport++;
-	server.ip = nhgetl(rep.siaddr);
-	server.port = TFTPport;
-
-	if((dlen = tftpopen(ctlrno, &server, filename, &tftpb)) < 0)
-		return -1;
-	exec = (Exec*)(tftpb.data);
-	if(dlen < sizeof(Exec) || GLLONG(exec->magic) != Q_MAGIC){
-		nak(ctlrno, &server, 0, "bad magic number", 1);
-		return -1;
-	}
-	text = GLLONG(exec->text);
-	data = GLLONG(exec->data);
-	bss = GLLONG(exec->bss);
-	total = text+data+bss;
-	entry = GLLONG(exec->entry);
-print("load@%8.8lux: ", PADDR(entry));uartwait();
-	print("%d", text);
-
-	addr = (uchar*)PADDR(entry);
-	p = tftpb.data+sizeof(Exec);
-	dlen -= sizeof(Exec);
-	segsize = text;
-	for(;;){
-		if(dlen == 0){
-			if((dlen = tftpread(ctlrno, &server, &tftpb, sizeof(tftpb.data))) < 0)
-				return -1;
-			p = tftpb.data;
-		}
-		if(segsize <= dlen)
-			i = segsize;
-		else
-			i = dlen;
-		memmove(addr, p, i);
-
-		addr += i;
-		p += i;
-		segsize -= i;
-		dlen -= i;
-
-		if(segsize <= 0){
-			if(data == 0)
-				break;
-			print("+%d", data);
-			segsize = data;
-			data = 0;
-			addr = (uchar*)PGROUND((ulong)addr);
-		}
-	}
-	nak(ctlrno, &server, 3, "ok", 0);		/* tftpclose */
-	print("+%d=%d\n", bss, total);
-	print("entry: 0x%lux\n", entry);
-	uartwait();
-	scc2stop();
-	splhi();
-	(*(void(*)(void))(PADDR(entry)))();
-	
-	return 0;
-}
--- a/os/boot/mpc/clock.c
+++ /dev/null
@@ -1,71 +1,0 @@
-#include	"u.h"
-#include	"lib.h"
-#include	"mem.h"
-#include	"dat.h"
-#include	"fns.h"
-#include	"io.h"
-#include	"ureg.h"
-
-enum {
-	Timebase = 4,	/* system clock cycles per time base cycle */
-};
-
-void	(*archclocktick)(void);	/* set by arch*.c when desired */
-
-static	ulong	clkreload;
-
-void
-delay(int l)
-{
-	ulong i, j;
-
-	j = m->delayloop;
-	while(l-- > 0)
-		for(i=0; i < j; i++)
-			;
-}
-
-void
-microdelay(int l)
-{
-	ulong i;
-
-	l *= m->delayloop;
-	l /= 1000;
-	if(l <= 0)
-		l = 1;
-	for(i = 0; i < l; i++)
-		;
-}
-
-void
-clockintr(Ureg*, void*)
-{
-	putdec(clkreload);
-	m->ticks++;
-	checkalarms();
-	if(archclocktick != nil)
-		archclocktick();
-}
-
-void
-clockinit(void)
-{
-	long x;
-
-	m->delayloop = m->cpuhz/1000;	/* initial estimate */
-	do {
-		x = gettbl();
-		delay(10);
-		x = gettbl() - x;
-	} while(x < 0);
-
-	/*
-	 *  fix count
-	 */
-	m->delayloop = ((vlong)m->delayloop*(10*m->clockgen/1000))/(x*Timebase);
-	if(m->delayloop == 0)
-		m->delayloop = 1;
-	clkreload = (m->clockgen/Timebase)/HZ-1;
-	putdec(clkreload);
-}
--- a/os/boot/mpc/conf.c
+++ /dev/null
@@ -1,173 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-#include "dosfs.h"
-
-static char *confname[MAXCONF];
-static char *confval[MAXCONF];
-static int nconf;
-
-extern char **ini;
-
-char*
-getconf(char *name)
-{
-	int i;
-
-	for(i = 0; i < nconf; i++)
-		if(strcmp(confname[i], name) == 0)
-			return confval[i];
-	return 0;
-}
-
-/*
- *  read configuration file
- */
-int
-plan9ini(Dos *dos, char *val)
-{
-	Dosfile rc;
-	int i, n;
-	char *cp, *p, *q, *line[MAXCONF];
-
-	cp = BOOTARGS;
-	if(dos) {
-		if(dosstat(dos, *ini, &rc) <= 0)
-			return -1;
-
-		*cp = 0;
-		n = dosread(&rc, cp, BOOTARGSLEN-1);
-		if(n <= 0)
-			return -1;
-		cp[n] = 0;
-	} else if(val != nil){
-		if(memchr(val, 0, BOOTARGSLEN-1) == nil)
-			return -1;
-		print("Using flash configuration\n");
-		strcpy(cp, val);
-		n = strlen(cp);
-	}else{
-		strcpy(cp, archconfig());
-		n = strlen(cp);
-	}
-
-	/*
-	 * Make a working copy.
-	 * We could change this to pass the parsed strings
-	 * to the booted programme instead of the raw
-	 * string, then it only gets done once.
-	 */
-	memmove(cp+BOOTARGSLEN, cp, n+1);
-	cp += BOOTARGSLEN;
-
-	/*
-	 * Strip out '\r', change '\t' -> ' '.
-	 */
-	p = cp;
-	for(q = cp; *q; q++){
-		if(*q == '\r')
-			continue;
-		if(*q == '\t')
-			*q = ' ';
-		*p++ = *q;
-	}
-	*p = 0;
-	n = getcfields(cp, line, MAXCONF, "\n");
-	for(i = 0; i < n; i++){
-		cp = strchr(line[i], '=');
-		if(cp == 0)
-			continue;
-		*cp++ = 0;
-		if(cp - line[i] >= NAMELEN+1)
-			*(line[i]+NAMELEN-1) = 0;
-		confname[nconf] = line[i];
-		confval[nconf] = cp;
-		nconf++;
-	}
-	return 0;
-}
-
-int
-parseether(uchar *to, char *from)
-{
-	char nip[4];
-	char *p;
-	int i;
-
-	p = from;
-	while(*p == ' ')
-		++p;
-	for(i = 0; i < 6; i++){
-		if(*p == 0)
-			return -1;
-		nip[0] = *p++;
-		if(*p == 0)
-			return -1;
-		nip[1] = *p++;
-		nip[2] = 0;
-		to[i] = strtoul(nip, 0, 16);
-		if(*p == ':')
-			p++;
-	}
-	return 0;
-}
-
-int
-isaconfig(char *class, int ctlrno, ISAConf *isa)
-{
-	char cc[NAMELEN], *p, *q, *r;
-	int n;
-
-	sprint(cc, "%s%d", class, ctlrno);
-	for(n = 0; n < nconf; n++){
-		if(strncmp(confname[n], cc, NAMELEN))
-			continue;
-		isa->nopt = 0;
-		p = confval[n];
-		while(*p){
-			while(*p == ' ' || *p == '\t')
-				p++;
-			if(*p == '\0')
-				break;
-			if(strncmp(p, "type=", 5) == 0){
-				p += 5;
-				for(q = isa->type; q < &isa->type[NAMELEN-1]; q++){
-					if(*p == '\0' || *p == ' ' || *p == '\t')
-						break;
-					*q = *p++;
-				}
-				*q = '\0';
-			}
-			else if(strncmp(p, "port=", 5) == 0)
-				isa->port = strtoul(p+5, &p, 0);
-			else if(strncmp(p, "irq=", 4) == 0)
-				isa->irq = strtoul(p+4, &p, 0);
-			else if(strncmp(p, "mem=", 4) == 0)
-				isa->mem = strtoul(p+4, &p, 0);
-			else if(strncmp(p, "size=", 5) == 0)
-				isa->size = strtoul(p+5, &p, 0);
-			else if(strncmp(p, "ea=", 3) == 0){
-				if(parseether(isa->ea, p+3) == -1)
-					memset(isa->ea, 0, 6);
-			}
-			else if(isa->nopt < NISAOPT){
-				r = isa->opt[isa->nopt];
-				while(*p && *p != ' ' && *p != '\t'){
-					*r++ = *p++;
-					if(r-isa->opt[isa->nopt] >= ISAOPTLEN-1)
-						break;
-				}
-				*r = '\0';
-				isa->nopt++;
-			}
-			while(*p && *p != ' ' && *p != '\t')
-				p++;
-		}
-		return 1;
-	}
-	return 0;
-}
--- a/os/boot/mpc/console.c
+++ /dev/null
@@ -1,173 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-static Queue*	consiq;
-static Queue*	consoq;
-
-void
-bothputs(char *s, int n)
-{
-	uartputs(s, n);
-	screenputs(s, n);
-}
-
-static void (*consputs)(char*, int) = bothputs;	/* or screenputs */
-
-void
-consinit(void)
-{
-	char *p;
-	int baud, port;
-	static int cgadone;
-
-	p = getconf("console");
-	if(0)
-	if(p == 0 || strcmp(p, "lcd") == 0 || strcmp(p, "screen") == 0){
-		consiq = qopen(4*1024, 0, 0, 0);
-		consoq = qopen(8*1024, 0, 0, 0);
-		consputs = screenputs;
-		return;
-	}
-	if(p!=0 && strstr(p, "lcd") == 0)
-		consputs = bothputs;
-	else
-		consputs = uartputs;
-//consputs = screenputs;
-	port = 0;
-	if(p)
-		port = strtoul(p, 0, 0);
-	baud = 0;
-	if(p = getconf("baud"))
-		baud = strtoul(p, 0, 0);
-	if(baud == 0)
-		baud = 9600;
-	uartspecial(port, baud, &consiq, &consoq, kbdchar);
-}
-
-void
-kbdchar(Queue *q, int c)
-{
-	c &= 0x7F;
-	if(c == 0x10)
-		panic("^p");
-	qbputc(q, c);
-}
-
-static int
-getline(char *buf, int size, int dotimeout)
-{
-	int c, i=0;
-	ulong start;
-	char echo;
-
-	for (;;) {
-		start = m->ticks;
-		do{
-			if(dotimeout && ((m->ticks - start) > 5*HZ))
-				return -2;
-			c = qbgetc(consiq);
-		}while(c == -1);
-		if(c == '\r')
-			c = '\n'; 		/* turn carriage return into newline */
-		if(c == '\177')
-			c = '\010';		/* turn delete into backspace */
-		if(c == '\025')
-			echo = '\n';		/* echo ^U as a newline */
-		else
-			echo = c;
-		(*consputs)(&echo, 1);
-
-		if(c == '\010'){
-			if(i > 0)
-				i--; /* bs deletes last character */
-			continue;
-		}
-		/* a newline ends a line */
-		if (c == '\n')
-			break;
-		/* ^U wipes out the line */
-		if (c =='\025')
-			return -1;
-		if(i == size)
-			return size;
-		buf[i++] = c;
-	}
-	buf[i] = 0;
-	return i;
-}
-
-int
-getstr(char *prompt, char *buf, int size, char *def)
-{
-	int len, isdefault;
-
-	buf[0] = 0;
-	isdefault = (def && *def);
-	for (;;) {
-		if(isdefault)
-			print("%s[default==%s]: ", prompt, def);
-		else
-			print("%s: ", prompt);
-		len = getline(buf, size, isdefault);
-		switch(len){
-		case -1:
-			/* ^U typed */
-			continue;
-		case -2:
-			/* timeout, use default */
-			(*consputs)("\n", 1);
-			len = 0;
-			break;
-		default:
-			break;
-		}
-		if(len >= size){
-			print("line too long\n");
-			continue;
-		}
-		break;
-	}
-	if(len == 0 && isdefault)
-		strcpy(buf, def);
-	return 0;
-}
-
-int
-sprint(char *s, char *fmt, ...)
-{
-	return donprint(s, s+PRINTSIZE, fmt, (&fmt+1)) - s;
-}
-
-int
-print(char *fmt, ...)
-{
-	char buf[PRINTSIZE];
-	int n;
-
-	if(consputs == 0)
-		return 0;
-	n = donprint(buf, buf+sizeof(buf), fmt, (&fmt+1)) - buf;
-	(*consputs)(buf, n);
-	return n;
-}
-
-void
-panic(char *fmt, ...)
-{
-	char buf[PRINTSIZE];
-	int n;
-
-	if(consputs){
-		(*consputs)("panic: ", 7);
-		n = donprint(buf, buf+sizeof(buf), fmt, (&fmt+1)) - buf;
-		(*consputs)(buf, n);
-		(*consputs)("\n", 1);
-	}
-	spllo();
-	for(;;)
-		idle();
-}
--- a/os/boot/mpc/cpm.c
+++ /dev/null
@@ -1,162 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-enum {
-	BDSIZE=	1024,	/* TO DO: check this */
-};
-
-static	Map	bdmapv[BDSIZE/sizeof(BD)];
-static	RMap	bdmap = {"buffer descriptors"};
-
-void
-cpminit(void)
-{
-	IMM *io;
-
-	io = m->iomem;
-	io->sdcr = 1;
-	io->lccr &= ~1;	/* disable LCD */
-	io->pcint = 0;	/* disable all port C interrupts */
-	io->pcso = 0;
-	io->pcdir =0;
-	io->pcpar = 0;
-	io->pcdat = 0;
-	io->papar = 0;
-	io->padir = 0;
-	io->paodr = 0;
-	io->padat = 0;
-	io->pbpar = 0;
-	io->pbdir = 0;
-	io->pbodr = 0;
-	io->pbdat = 0;
-	eieio();
-
-	for(io->cpcr = 0x8001; io->cpcr & 1;)	/* reset all CPM channels */
-		eieio();
-
-	mapinit(&bdmap, bdmapv, sizeof(bdmapv));
-	mapfree(&bdmap, DPBASE, BDSIZE);
-}
-
-void
-cpmop(int op, int cno, int param)
-{
-	IMM *io;
-	int s;
-
-	s = splhi();
-	io = m->iomem;
-	eieio();
-	while(io->cpcr & 1)
-		eieio();
-	io->cpcr = (op<<8)|(cno<<4)|(param<<1)|1;
-	eieio();
-	while(io->cpcr & 1)
-		eieio();
-	splx(s);
-}
-
-/*
- * connect SCCx clocks in NSMI mode (x=1 for USB)
- */
-void
-sccnmsi(int x, int rcs, int tcs)
-{
-	IMM *io;
-	ulong v;
-	int sh;
-
-	sh = (x-1)*8;	/* each SCCx field in sicr is 8 bits */
-	v = (((rcs&7)<<3) | (tcs&7)) << sh;
-	io = ioplock();
-	io->sicr = (io->sicr & ~(0xFF<<sh)) | v;
-	iopunlock();
-}
-
-void
-scc2stop(void)
-{
-	SCC *scc;
-
-	scc = IOREGS(0xA20, SCC);
-	if(scc->gsmrl & (3<<4)){
-		cpmop(GracefulStopTx, SCC2ID, 0);
-		cpmop(CloseRxBD, SCC2ID, 0);
-		delay(1);
-		scc->gsmrl &= ~(3<<4);	/* disable current use */
-		archetherdisable(SCC2ID);
-	}
-}
-
-BD *
-bdalloc(int n)
-{
-	ulong a;
-
-	a = mapalloc(&bdmap, 0, n*sizeof(BD), 0);
-	if(a == 0)
-		panic("bdalloc");
-	return KADDR(a);
-}
-
-void
-bdfree(BD *b, int n)
-{
-	if(b){
-		eieio();
-		mapfree(&bdmap, PADDR(b), n*sizeof(BD));
-	}
-}
-
-/*
- * initialise receive and transmit buffer rings.
- */
-int
-ioringinit(Ring* r, int nrdre, int ntdre, int bufsize)
-{
-	int i, x;
-
-	/* the ring entries must be aligned on sizeof(BD) boundaries */
-	r->nrdre = nrdre;
-	if(r->rdr == nil)
-		r->rdr = bdalloc(nrdre);
-	/* the buffer size must align with cache lines since the cache doesn't snoop */
-	bufsize = (bufsize+CACHELINESZ-1)&~(CACHELINESZ-1);
-	if(r->rrb == nil)
-		r->rrb = malloc(nrdre*bufsize);
-	if(r->rdr == nil || r->rrb == nil)
-		return -1;
-	dcflush(r->rrb, nrdre*bufsize);
-	x = PADDR(r->rrb);
-	for(i = 0; i < nrdre; i++){
-		r->rdr[i].length = 0;
-		r->rdr[i].addr = x;
-		r->rdr[i].status = BDEmpty|BDInt;
-		x += bufsize;
-	}
-	r->rdr[i-1].status |= BDWrap;
-	r->rdrx = 0;
-
-	r->ntdre = ntdre;
-	if(r->tdr == nil)
-		r->tdr = bdalloc(ntdre);
-	if(r->txb == nil)
-		r->txb = malloc(ntdre*sizeof(Block*));
-	if(r->tdr == nil || r->txb == nil)
-		return -1;
-	for(i = 0; i < ntdre; i++){
-		r->txb[i] = nil;
-		r->tdr[i].addr = 0;
-		r->tdr[i].length = 0;
-		r->tdr[i].status = 0;
-	}
-	r->tdr[i-1].status |= BDWrap;
-	r->tdrh = 0;
-	r->tdri = 0;
-	r->ntq = 0;
-	return 0;
-}
--- a/os/boot/mpc/crc32.c
+++ /dev/null
@@ -1,42 +1,0 @@
-#include "boot.h"
-
-/*
- * from Rob Warnock
- */
-static	ulong	crc32tab[256];	/* initialised on first call to crc32 */
-
-enum {
-	CRC32POLY = 0x04c11db7     /* AUTODIN II, Ethernet, & FDDI */
-};
-
-/*
- * Build auxiliary table for parallel byte-at-a-time CRC-32.
- */
-static void
-initcrc32(void)
-{
-	int i, j;
-	ulong c;
-
-	for(i = 0; i < 256; i++) {
-		for(c = i << 24, j = 8; j > 0; j--)
-			if(c & (1<<31))
-				c = (c<<1) ^ CRC32POLY;
-			else
-				c <<= 1;
-		crc32tab[i] = c;
-	}
-}
-
-ulong
-crc32(void *buf, int n, ulong crc)
-{
-	uchar *p;
-
-	if(crc32tab[1] == 0)
-		initcrc32();
-	crc = ~crc;
-	for(p = buf; --n >= 0;)
-		crc = (crc << 8) ^ crc32tab[(crc >> 24) ^ *p++];
-	return ~crc;
-}
--- a/os/boot/mpc/dat.h
+++ /dev/null
@@ -1,217 +1,0 @@
-typedef struct Alarm Alarm;
-typedef struct Block Block;
-typedef struct IMM IMM;
-typedef struct Queue Queue;
-
-typedef struct List {
-	void	*next;
-} List;
-
-typedef struct {
-	int	fake;
-	int	pri;
-} Lock;
-#define	lock(x)
-#define	unlock(x)
-
-struct Alarm {
-	List;
-	int	busy;
-	long	dt;
-	void	(*f)(Alarm*);
-	void	*arg;
-};
-
-enum {
-	Eaddrlen	= 6,
-	ETHERMINTU	= 60,		/* minimum transmit size */
-	ETHERMAXTU	= 1514,		/* maximum transmit size */
-	ETHERHDRSIZE	= 14,		/* size of an ethernet header */
-
-	MaxEther	= 4,
-};
-
-typedef struct {
-	uchar	d[Eaddrlen];
-	uchar	s[Eaddrlen];
-	uchar	type[2];
-	uchar	data[1500];
-	uchar	crc[4];
-} Etherpkt;
-
-extern uchar broadcast[Eaddrlen];
-
-enum {
-	Npart		= 20+2,		/* 8 sub partitions, disk, and partition */
-	Maxxfer		= 16*1024,	/* maximum transfer size/cmd */
-};
-
-typedef struct {
-	ulong	start;
-	ulong	end;
-	char	name[NAMELEN+1];
-} Partition;
-
-typedef struct {
-	int	online;
-	int	npart;		/* number of real partitions */
-	Partition p[Npart];
-	ulong	offset;
-	Partition *current;	/* current partition */
-
-	ulong	cap;		/* total bytes */
-	int	bytes;		/* bytes/sector */
-	int	sectors;	/* sectors/track */
-	int	heads;		/* heads/cyl */
-	long	cyl;		/* cylinders/drive */
-
-	char	lba;		/* true if drive has logical block addressing */
-	char	multi;		/* non-zero if drive does multiple block xfers */
-} Disc;
-
-enum {
-	ScsiTestunit	= 0x00,
-	ScsiExtsens	= 0x03,
-	ScsiInquiry	= 0x12,
-	ScsiModesense	= 0x1a,
-	ScsiStartunit	= 0x1B,
-	ScsiStopunit	= 0x1B,
-	ScsiGetcap	= 0x25,
-	ScsiRead	= 0x08,
-	ScsiWrite	= 0x0a,
-	ScsiExtread	= 0x28,
-	ScsiExtwrite	= 0x2a,
-
-	/* data direction */
-	ScsiIn		= 1,
-	ScsiOut		= 0,
-};
-
-typedef struct Scsibuf Scsibuf;
-typedef struct Scsibuf {
-	void*		virt;
-	void*		phys;
-	Scsibuf*	next;
-};
-
-typedef struct Scsidata {
-	uchar*		base;
-	uchar*		lim;
-	uchar*		ptr;
-} Scsidata;
-
-typedef struct Ureg Ureg;
-
-typedef struct Scsi {
-	ulong		pid;
-	ushort		target;
-	ushort		lun;
-	ushort		rflag;
-	ushort		status;
-	Scsidata 	cmd;
-	Scsidata 	data;
-	Scsibuf*	b;
-	uchar*		save;
-	uchar		cmdblk[16];
-} Scsi;
-
-typedef struct Segdesc {
-	ulong	d0;
-	ulong	d1;
-} Segdesc;
-
-typedef struct Mach {
-	ulong	ticks;			/* of the clock since boot time */
-	ulong	delayloop;
-	long	cpuhz;	/* general system clock (cycles) */
-	long	clockgen;	/* clock generator frequency (cycles) */
-	ulong	cpupvr;	/* cpu type in processor version register */
-	ulong	cputype;	/* cpu variant in BCD (eg, 0x823xx) */
-	void*	alarm;			/* alarms bound to this clock */
-	ulong*	bcsr;
-	IMM*	iomem;
-} Mach;
-
-/* Mach.cputype */
-#define MPCREV(x)	((x) & 0xFF)
-#define MPCMODEL(x)	(((x)>>8) & 0xFFF)
-#define MPCFAMILY(x)	(((x)>>24) & 0x0F)
-
-
-extern Mach *m;
-
-#define Q_MAGIC		((((4*21)+0)*21)+7)
-
-typedef struct Exec Exec;
-struct	Exec
-{
-	uchar	magic[4];		/* magic number */
-	uchar	text[4];	 	/* size of text segment */
-	uchar	data[4];	 	/* size of initialized data */
-	uchar	bss[4];	  		/* size of uninitialized data */
-	uchar	syms[4];	 	/* size of symbol table */
-	uchar	entry[4];	 	/* entry point */
-	uchar	spsz[4];		/* size of sp/pc offset table */
-	uchar	pcsz[4];		/* size of pc/line number table */
-};
-
-/*
- *  bootline passed by boot program
- */
-#define BOOTLINE ((char *)0x200000-150)
-
-/*
- * Where we leave configuration info.
- */
-#define BOOTARGS	((char*)(0x200000))
-#define	BOOTARGSLEN	1024
-#define	MAXCONF		32
-
-/*
- *  a parsed plan9.ini line
- */
-#define ISAOPTLEN	16
-#define NISAOPT		8
-
-typedef struct  ISAConf {
-	char	type[NAMELEN];
-	ulong	port;
-	ulong	irq;
-	ulong	mem;
-	ulong	size;
-	uchar	ea[6];
-
-	int	nopt;
-	char	opt[NISAOPT][ISAOPTLEN];
-} ISAConf;
-
-typedef struct {
-	int	size;
-	ulong	addr;
-} Map;
-
-typedef struct {
-	char*	name;
-	Map*	map;
-	Map*	mapend;
-
-	Lock;
-} RMap;
-
-typedef struct PCIcfg PCIcfg;
-
-extern	uchar*	vgamem;
-
-struct Block {
-	uchar	*rp;
-	uchar	*wp;
-	uchar	*lim;
-	uchar	*data;
-	Block*	next;
-	ulong	magic;
-};
-#define	BLEN(b)	((b)->wp-(b)->rp)
-
-typedef struct QLock {
-	int	dummy;
-} QLock;
--- a/os/boot/mpc/defont0.c
+++ /dev/null
@@ -1,216 +1,0 @@
-#include <u.h>
-#include <libc.h>
-#include <libg.h>
-#include <gnot.h>
-
-
-
-static ulong bits0[] = {
- 0x907070f0,  0xf0f07000,  0xf0888888,  0xf8707070,  0xe0e0e0e0,  0xe09070f0,  0x70f870f0,  0xf870f088, 
- 0x00000000,  0x00000000,  0x00000000,  0x00000000,  0x00000000,  0x00000000,  0x00000000,  0x00000000, 
- 0x00000000,  0x00000000,  0x00000000,  0x00000000,  0x00000000,  0x00000000,  0x00000000,  0x00000000, 
- 0x00000000,  0x00000000,  0x00000000,  0x00000000,  0x00000000,  0x00000000,  0x00000000,  0x000000e0, 
- 0xd0808080,  0x80808800,  0x8888c888,  0x80888888,  0x90909090,  0x90d08080,  0x80808080,  0x80888888, 
- 0x00000000,  0x08000000,  0x0c300000,  0x00000006,  0x00000000,  0x00000000,  0x00000000,  0x00000000, 
- 0x00000000,  0x00000000,  0x00000000,  0x00000000,  0x00000000,  0x00000000,  0x0000003c,  0xc03c0000, 
- 0x00006000,  0x06001e00,  0x60181860,  0x78000000,  0x00000000,  0x00000000,  0x0000001c,  0x18380090, 
- 0xb06060e0,  0xe0e0f800,  0xf088a888,  0x80808080,  0x90909090,  0x90b060e0,  0x808060e0,  0x80808888, 
- 0x00182428,  0x3e707018,  0x18180000,  0x00000006,  0x3c183c3c,  0x1c3e3c7e,  0x3c3c0000,  0x0200403c, 
- 0x3c187c1e,  0x787e7e1e,  0x663c7c66,  0x6066623c,  0x7c3c7c3c,  0x7e6266c2,  0x66667e30,  0xc00c1000, 
- 0x08006000,  0x06003000,  0x60181860,  0x18000000,  0x00000000,  0x10000000,  0x00000030,  0x180c0090, 
- 0x90101080,  0x80808818,  0x88f8a888,  0xe0807070,  0xe0e0e0e0,  0xe0901080,  0x70e01080,  0xe098f088, 
- 0x00182428,  0x6adad818,  0x18181000,  0x0000000c,  0x66386666,  0x2c3e667e,  0x66660000,  0x06006066, 
- 0x42186632,  0x6c606032,  0x66181864,  0x60667224,  0x66246666,  0x186262da,  0x62620630,  0x600c3800, 
- 0x10006000,  0x06003000,  0x60000060,  0x18000000,  0x00000000,  0x30000000,  0x00000030,  0x180c00e0, 
- 0x00e0e0f0,  0xf0f00018,  0x88889850,  0x80880808,  0x201c1c1c,  0x1c00e0f0,  0x0080e0f0,  0x80888888, 
- 0x00182428,  0x68dad808,  0x300c5418,  0x0000000c,  0x66580606,  0x2c206002,  0x66661818,  0x0cfe3006, 
- 0x9e2c6660,  0x66606060,  0x6618186c,  0x60667266,  0x66666660,  0x186262da,  0x36660c30,  0x600c2800, 
- 0x103c6c3c,  0x3e3c7e3e,  0x6c787866,  0x18d46c3c,  0x6c3e763c,  0x7e6666c2,  0x66667e18,  0x18180000, 
- 0x44180000,  0x18241c24,  0xf0888820,  0x8070f0f0,  0x20202020,  0x201c243e,  0x1cf8241c,  0x80708870, 
- 0x0018247c,  0x78745008,  0x300c3818,  0x00000018,  0x66180606,  0x4c206006,  0x76661818,  0x18fe180c, 
- 0xb62c6660,  0x66606060,  0x66181868,  0x607e5a66,  0x66666470,  0x186266da,  0x34340c30,  0x300c6c00, 
- 0x18667666,  0x66663066,  0x76181864,  0x18fe7666,  0x76663666,  0x306662da,  0x62620608,  0x1810323c, 
- 0x44247c7c,  0x24342042,  0x00000000,  0x00000000,  0x20202020,  0x20222408,  0x22002420,  0x00000000, 
- 0x00180028,  0x3c287610,  0x300cee7e,  0x00fe0018,  0x66180c18,  0x4c3c7c0c,  0x3c3e0000,  0x30000c18, 
- 0xb62c7c60,  0x667c7c6e,  0x7e181878,  0x605a5a66,  0x6466783c,  0x186234da,  0x18341830,  0x300c4400, 
- 0x18066660,  0x66663066,  0x66181868,  0x18d66666,  0x66663860,  0x306662da,  0x34620c30,  0x180c5a20, 
- 0x44241010,  0x242c2042,  0x0e3e103e,  0x3e3c1c3e,  0x3c1c1c1c,  0x1c3e1c08,  0x3e222418,  0x0e0e0e0e, 
- 0x0008007c,  0x1e5cdc00,  0x300c387e,  0x00fe0030,  0x66181806,  0x7e066618,  0x6e060000,  0x18001818, 
- 0xb67e6660,  0x66606066,  0x6618186c,  0x605a4e66,  0x78666c0e,  0x1862346c,  0x2c183030,  0x180c4400, 
- 0x003e6660,  0x667e3066,  0x66181878,  0x18d66666,  0x6666303c,  0x306634da,  0x18341808,  0x18104c38, 
- 0x3c181010,  0x18241c42,  0x11081008,  0x20222208,  0x00000000,  0x00220408,  0x22361804,  0x11111111, 
- 0x00000028,  0x16b6cc00,  0x300c5418,  0x00000030,  0x66183006,  0x7e066618,  0x66060000,  0x0cfe3000, 
- 0x9a466660,  0x66606066,  0x6618186c,  0x605a4e66,  0x60666606,  0x1862346c,  0x6c183030,  0x180c0000, 
- 0x00666660,  0x66603066,  0x6618186c,  0x18d66666,  0x66663006,  0x3066346c,  0x2c343018,  0x18180020, 
- 0x00091010,  0x000e0942,  0x10081008,  0x20222208,  0x0f06060f,  0x0a09041e,  0x002a0e38,  0x10101010, 
- 0x00180028,  0x56b6cc00,  0x300c1018,  0x18001860,  0x66187e66,  0x0c666630,  0x66661818,  0x06fe6018, 
- 0x40466632,  0x6c606036,  0x66181866,  0x605a4624,  0x60246666,  0x1834186c,  0x46186030,  0x0c0c0000, 
- 0x006e6666,  0x6e66306e,  0x66181866,  0x18d66666,  0x666e3066,  0x306e186c,  0x46186030,  0x180c003c, 
- 0x08090909,  0x1f110aff,  0x0e081008,  0x382c2208,  0x08020901,  0x0a0a0911,  0x09220907,  0x0e0e0e0e, 
- 0x00180028,  0x7c1c7600,  0x18180000,  0x18001860,  0x3c7e7e3c,  0x0c3c3c30,  0x3c3c1818,  0x02004018, 
- 0x3e467c1e,  0x787e601e,  0x663c1866,  0x7e42463c,  0x603c663c,  0x1818186c,  0x66187e30,  0x0c0c0000, 
- 0x00367c3c,  0x363c7c36,  0x667e1866,  0x7ed6663c,  0x7c367c3c,  0x1e36186c,  0x66187e30,  0x180c0008, 
- 0x080f0606,  0x04110c18,  0x01081008,  0x20222208,  0x0e020203,  0x0a0c0d1e,  0x0d220e08,  0x01010101, 
- 0x00000000,  0x10000000,  0x18180000,  0x080000c0,  0x00000000,  0x00000000,  0x00000008,  0x00000000, 
- 0x00000000,  0x00000000,  0x00001800,  0x00000000,  0x000c0000,  0x00000000,  0x00000030,  0x060c00fe, 
- 0x00000000,  0x00000006,  0x00001800,  0x00000000,  0x60060000,  0x00000000,  0x0010001c,  0x18380008, 
- 0x08090606,  0x040e0a18,  0x11081f08,  0x20221c3e,  0x08020401,  0x0f0a0b11,  0x0b220908,  0x11111111, 
- 0x00000000,  0x00000000,  0x0c300000,  0x080000c0,  0x00000000,  0x00000000,  0x00000008,  0x00000000, 
- 0x00000000,  0x00000000,  0x00007000,  0x00000000,  0x00060000,  0x00000000,  0x0000003c,  0x063c0000, 
- 0x00000000,  0x00000066,  0x00001800,  0x00000000,  0x60060000,  0x00000000,  0x00300000,  0x00000008, 
- 0x0f090909,  0x04030900,  0x0e000000,  0x00000000,  0x0f0f0f0f,  0x0209091e,  0x09000f07,  0x0e0e0e0e, 
- 0x00000000,  0x00000000,  0x00000000,  0x10000000,  0x00000000,  0x00000000,  0x00000010,  0x00000000, 
- 0x00000000,  0x00000000,  0x00000000,  0x00000000,  0x00000000,  0x00000000,  0x00000000,  0x00000000, 
- 0x00000000,  0x0000003c,  0x00007000,  0x00000000,  0x60060000,  0x00000000,  0x00600000,  0x0000000f, 
-
-};
-
-static GBitmap strike0 = {
-	bits0,
-	0,
-	32,
-	0,
-	{0, 0, 1024, 14},
-	{0, 0, 1024, 14},
-};
-
-static Fontchar info0[] = {
-	{ 0, 0, 14, 0, 8 },
-	{ 8, 0, 14, 0, 8 },
-	{ 16, 0, 14, 0, 8 },
-	{ 24, 0, 14, 0, 8 },
-	{ 32, 0, 14, 0, 8 },
-	{ 40, 0, 14, 0, 8 },
-	{ 48, 0, 14, 0, 8 },
-	{ 56, 0, 14, 0, 8 },
-	{ 64, 0, 14, 0, 8 },
-	{ 72, 0, 14, 0, 8 },
-	{ 80, 0, 14, 0, 8 },
-	{ 88, 0, 14, 0, 8 },
-	{ 96, 0, 14, 0, 8 },
-	{ 104, 0, 14, 0, 8 },
-	{ 112, 0, 14, 0, 8 },
-	{ 120, 0, 14, 0, 8 },
-	{ 128, 0, 14, 0, 8 },
-	{ 136, 0, 14, 0, 8 },
-	{ 144, 0, 14, 0, 8 },
-	{ 152, 0, 14, 0, 8 },
-	{ 160, 0, 14, 0, 8 },
-	{ 168, 0, 14, 0, 8 },
-	{ 176, 0, 14, 0, 8 },
-	{ 184, 0, 14, 0, 8 },
-	{ 192, 0, 14, 0, 8 },
-	{ 200, 0, 14, 0, 8 },
-	{ 208, 0, 14, 0, 8 },
-	{ 216, 0, 14, 0, 8 },
-	{ 224, 0, 14, 0, 8 },
-	{ 232, 0, 14, 0, 8 },
-	{ 240, 0, 14, 0, 8 },
-	{ 248, 0, 14, 0, 8 },
-	{ 256, 0, 0, 0, 8 },
-	{ 264, 2, 11, 0, 8 },
-	{ 272, 2, 6, 0, 8 },
-	{ 280, 2, 11, 0, 8 },
-	{ 288, 1, 12, 0, 8 },
-	{ 296, 2, 11, 0, 8 },
-	{ 304, 2, 11, 0, 8 },
-	{ 312, 2, 7, 0, 8 },
-	{ 320, 1, 13, 0, 8 },
-	{ 328, 1, 13, 0, 8 },
-	{ 336, 3, 10, 0, 8 },
-	{ 344, 4, 10, 0, 8 },
-	{ 352, 9, 14, 0, 8 },
-	{ 360, 6, 8, 0, 8 },
-	{ 368, 9, 11, 0, 8 },
-	{ 376, 1, 13, 0, 8 },
-	{ 384, 2, 11, 0, 8 },
-	{ 392, 2, 11, 0, 8 },
-	{ 400, 2, 11, 0, 8 },
-	{ 408, 2, 11, 0, 8 },
-	{ 416, 2, 11, 0, 8 },
-	{ 424, 2, 11, 0, 8 },
-	{ 432, 2, 11, 0, 8 },
-	{ 440, 2, 11, 0, 8 },
-	{ 448, 2, 11, 0, 8 },
-	{ 456, 2, 11, 0, 8 },
-	{ 464, 4, 11, 0, 8 },
-	{ 472, 4, 14, 0, 8 },
-	{ 480, 2, 11, 0, 8 },
-	{ 488, 4, 10, 0, 8 },
-	{ 496, 2, 11, 0, 8 },
-	{ 504, 2, 11, 0, 8 },
-	{ 512, 2, 11, 0, 8 },
-	{ 520, 2, 11, 0, 8 },
-	{ 528, 2, 11, 0, 8 },
-	{ 536, 2, 11, 0, 8 },
-	{ 544, 2, 11, 0, 8 },
-	{ 552, 2, 11, 0, 8 },
-	{ 560, 2, 11, 0, 8 },
-	{ 568, 2, 11, 0, 8 },
-	{ 576, 2, 11, 0, 8 },
-	{ 584, 2, 11, 0, 8 },
-	{ 592, 2, 13, 0, 8 },
-	{ 600, 2, 11, 0, 8 },
-	{ 608, 2, 11, 0, 8 },
-	{ 616, 2, 11, 0, 8 },
-	{ 624, 2, 11, 0, 8 },
-	{ 632, 2, 11, 0, 8 },
-	{ 640, 2, 11, 0, 8 },
-	{ 648, 2, 13, 0, 8 },
-	{ 656, 2, 11, 0, 8 },
-	{ 664, 2, 11, 0, 8 },
-	{ 672, 2, 11, 0, 8 },
-	{ 680, 2, 11, 0, 8 },
-	{ 688, 2, 11, 0, 8 },
-	{ 696, 2, 11, 0, 8 },
-	{ 704, 2, 11, 0, 8 },
-	{ 712, 2, 11, 0, 8 },
-	{ 720, 2, 11, 0, 8 },
-	{ 728, 1, 13, 0, 8 },
-	{ 736, 1, 13, 0, 8 },
-	{ 744, 1, 13, 0, 8 },
-	{ 752, 2, 8, 0, 8 },
-	{ 760, 11, 12, 0, 8 },
-	{ 768, 2, 7, 0, 8 },
-	{ 776, 4, 11, 0, 8 },
-	{ 784, 1, 11, 0, 8 },
-	{ 792, 4, 11, 0, 8 },
-	{ 800, 1, 11, 0, 8 },
-	{ 808, 4, 11, 0, 8 },
-	{ 816, 1, 11, 0, 8 },
-	{ 824, 4, 14, 0, 8 },
-	{ 832, 1, 11, 0, 8 },
-	{ 840, 1, 11, 0, 8 },
-	{ 848, 1, 14, 0, 8 },
-	{ 856, 1, 11, 0, 8 },
-	{ 864, 1, 11, 0, 8 },
-	{ 872, 4, 11, 0, 8 },
-	{ 880, 4, 11, 0, 8 },
-	{ 888, 4, 11, 0, 8 },
-	{ 896, 4, 14, 0, 8 },
-	{ 904, 4, 14, 0, 8 },
-	{ 912, 4, 11, 0, 8 },
-	{ 920, 4, 11, 0, 8 },
-	{ 928, 2, 11, 0, 8 },
-	{ 936, 4, 11, 0, 8 },
-	{ 944, 4, 11, 0, 8 },
-	{ 952, 4, 11, 0, 8 },
-	{ 960, 4, 11, 0, 8 },
-	{ 968, 4, 14, 0, 8 },
-	{ 976, 4, 11, 0, 8 },
-	{ 984, 1, 12, 0, 8 },
-	{ 992, 1, 12, 0, 8 },
-	{ 1000, 1, 12, 0, 8 },
-	{ 1008, 5, 8, 0, 8 },
-	{ 1016, 0, 14, 0, 8 },
-	{ 1024, 0, 14, 0, 8 },
-	{ 0, 0, 0, 0, 0 }
-};
-
-GSubfont defont0 = {
-	129,
-	14,
-	2,
-	info0,
-	&strike0,
-};
--- a/os/boot/mpc/devether.c
+++ /dev/null
@@ -1,157 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-#include "etherif.h"
-
-static Ctlr ether[MaxEther];
-
-static struct {
-	char	*type;
-	int	(*reset)(Ctlr*);
-} cards[] = {
-	{ "SCC", sccethreset, },
-	{ "SCC2", sccethreset, },
-	{ 0, }
-};
-
-int
-etherinit(void)
-{
-	Ctlr *ctlr;
-	int ctlrno, i, mask, n;
-
-	mask = 0;
-	for(ctlrno = 0; ctlrno < MaxEther; ctlrno++){
-		ctlr = &ether[ctlrno];
-		memset(ctlr, 0, sizeof(Ctlr));
-		if(isaconfig("ether", ctlrno, &ctlr->card) == 0)
-			continue;
-		for(n = 0; cards[n].type; n++){
-			if(strcmp(cards[n].type, ctlr->card.type))
-				continue;
-			ctlr->ctlrno = ctlrno;
-			if((*cards[n].reset)(ctlr))
-				break;
-
-			ctlr->iq = qopen(16*1024, 1, 0, 0);
-			ctlr->oq = qopen(16*1024, 1, 0, 0);
-
-			ctlr->present = 1;
-			mask |= 1<<ctlrno;
-
-			print("ether%d: %s: port 0x%luX irq %d",
-				ctlr->ctlrno, ctlr->card.type, ctlr->card.port, ctlr->card.irq);
-			if(ctlr->card.mem)
-				print(" addr 0x%luX", PADDR(ctlr->card.mem));
-			if(ctlr->card.size)
-				print(" size 0x%luX", ctlr->card.size);
-			print(":");
-			for(i = 0; i < sizeof(ctlr->card.ea); i++)
-				print(" %2.2uX", ctlr->card.ea[i]);
-			print("\n"); uartwait();
-			setvec(VectorPIC + ctlr->card.irq, ctlr->card.intr, ctlr);
-			break;
-		}
-	}
-
-	return mask;
-}
-
-static Ctlr*
-attach(int ctlrno)
-{
-	Ctlr *ctlr;
-
-	if(ctlrno >= MaxEther || ether[ctlrno].present == 0)
-		return 0;
-
-	ctlr = &ether[ctlrno];
-	if(ctlr->present == 1){
-		ctlr->present = 2;
-		(*ctlr->card.attach)(ctlr);
-	}
-
-	return ctlr;
-}
-
-uchar*
-etheraddr(int ctlrno)
-{
-	Ctlr *ctlr;
-
-	if((ctlr = attach(ctlrno)) == 0)
-		return 0;
-
-	return ctlr->card.ea;
-}
-
-int
-etherrxpkt(int ctlrno, Etherpkt *pkt, int timo)
-{
-	int n;
-	Ctlr *ctlr;
-	Block *b;
-	ulong start;
-
-	if((ctlr = attach(ctlrno)) == 0)
-		return 0;
-
-	start = m->ticks;
-	while((b = qget(ctlr->iq)) == 0){
-		if(TK2MS(m->ticks - start) >= timo){
-			/*
-			print("ether%d: rx timeout\n", ctlrno);
-			 */
-			return 0;
-		}
-	}
-
-	n = BLEN(b);
-	memmove(pkt, b->rp, n);
-	freeb(b);
-
-	return n;
-}
-
-int
-etheriq(Ctlr *ctlr, Block *b, int freebp)
-{
-	if(memcmp(((Etherpkt*)b->rp)->d, ctlr->card.ea, Eaddrlen) != 0 &&
-	   memcmp(((Etherpkt*)b->rp)->d, broadcast, Eaddrlen) != 0){
-		if(freebp)
-			freeb(b);
-		return 0;
-	}
-	qbwrite(ctlr->iq, b);
-	return 1;
-}
-
-int
-ethertxpkt(int ctlrno, Etherpkt *pkt, int len, int)
-{
-	Ctlr *ctlr;
-	Block *b;
-	int s;
-
-	if((ctlr = attach(ctlrno)) == 0)
-		return 0;
-
-	if(qlen(ctlr->oq) > 16*1024){
-		print("ether%d: tx queue full\n", ctlrno);
-		return 0;
-	}
-	b = iallocb(sizeof(Etherpkt));
-	memmove(b->wp, pkt, len);
-	memmove(((Etherpkt*)b->wp)->s, ctlr->card.ea, Eaddrlen);
-	b->wp += len;
-	qbwrite(ctlr->oq, b);
-	s = splhi();
-	(*ctlr->card.transmit)(ctlr);
-	splx(s);
-
-	return 1;
-}
--- a/os/boot/mpc/devuart.c
+++ /dev/null
@@ -1,230 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-/*
- *  SMC1 in UART mode
- */
-
-typedef struct Uartsmc Uartsmc;
-struct Uartsmc {
-	IOCparam;
-	ushort	maxidl;
-	ushort	idlc;
-	ushort	brkln;
-	ushort	brkec;
-	ushort	brkcr;
-	ushort	rmask;
-};
-
-typedef struct Uart	Uart;
-struct Uart
-{
-	int	port;
-	int	setup;
-	uchar	txbusy;
-
-	Queue*	iq;
-	Queue*	oq;
-	void	(*rx)(Queue*, int);
-	void	(*boot)(uchar*, int);
-
-	ulong	frame;
-	ulong	overrun;
-	uchar	rxbuf[128];
-	char	txbuf[16];
-	BD*	rxb;
-	BD*	txb;
-};
-
-Uart	uart[1];
-int	predawn = 1;
-
-static	void	uartintr(Ureg*, void*);
-static	void	uartkick(void*);
-
-static int
-baudgen(int baud)
-{
-	int d;
-
-	d = ((m->cpuhz/baud)+8)>>4;
-	if(d >= (1<<12))
-		return ((d+15)>>3)|1;
-	return d<<1;
-}
-
-static void
-smcsetup(Uart *up, int baud)
-{
-	IMM *io;
-	Uartsmc *p;
-	BD *bd;
-	SMC *smc;
-
-	archenableuart(SMC1ID, 0);
-	io = m->iomem;
-	io->pbpar |= IBIT(24)|IBIT(25);	/* enable SMC1 TX/RX */
-	io->pbdir &= ~(IBIT(24)|IBIT(25));
-	io->brgc1 = baudgen(baud) | BaudEnable;
-	io->simode &= ~0xF000;	/* SMC1 to NMSI mode, Tx/Rx clocks are BRG1 */
-
-	bd = bdalloc(1);
-	p = (Uartsmc*)KADDR(SMC1P);
-	p->rbase = (ushort)bd;
-	up->rxb = bd;
-	bd->status = BDEmpty|BDWrap|BDInt;
-	bd->length = 0;
-	bd->addr = PADDR(up->rxbuf);
-	bd = bdalloc(1);
-	p->tbase = (ushort)bd;
-	up->txb = bd;
-	bd->status = BDWrap|BDInt;
-	bd->length = 0;
-	bd->addr = PADDR(up->txbuf);
-
-	cpmop(InitRxTx, SMC1ID, 0);
-
-	/* protocol parameters */
-	p->rfcr = 0x18;
-	p->tfcr = 0x18;
-	p->mrblr = 1;
-	p->maxidl = 1;
-	p->brkln = 0;
-	p->brkec = 0;
-	p->brkcr = 1;
-	smc = IOREGS(0xA80, SMC);
-	smc->smce = 0xff;	/* clear events */
-	smc->smcm = 0x17;	/* enable all possible interrupts */
-	setvec(VectorCPIC+4, uartintr, up);
-	smc->smcmr = 0x4820;	/* 8-bit mode, no parity, 1 stop bit, UART mode, ... */
-	smc->smcmr |= 3;	/* enable rx/tx */
-}
-
-static void
-uartintr(Ureg*, void *arg)
-{
-	Uart *up;
-	int ch, i;
-	BD *bd;
-	SMC *smc;
-	Block *b;
-
-	up = arg;
-	smc = IOREGS(0xA80, SMC);
-	smc->smce = 0xff;	/* clear all events */
-	if((bd = up->rxb) != nil && (bd->status & BDEmpty) == 0){
-		if(up->iq != nil && bd->length > 0){
-			if(up->boot != nil){
-				up->boot(up->rxbuf, bd->length);
-			}else if(up->rx != nil){
-				for(i=0; i<bd->length; i++){
-					ch = up->rxbuf[i];
-					up->rx(up->iq, ch);
-				}
-			}else{
-				b = iallocb(bd->length);
-				memmove(b->wp, up->rxbuf, bd->length);
-				b->wp += bd->length;
-				qbwrite(up->iq, b);
-			}
-		}
-		bd->status |= BDEmpty|BDInt;
-	} else if((bd = up->txb) != nil && (bd->status & BDReady) == 0){
-		ch = -1;
-		if(up->oq)
-			ch = qbgetc(up->oq);
-		if(ch != -1){
-			up->txbuf[0] = ch;
-			bd->length = 1;
-			bd->status |= BDReady;
-		}else
-			up->txbusy = 0;
-	}
-	/* TO DO: modem status, errors, etc */
-}
-
-static void
-uartkick(void *arg)
-{
-	Uart *up = arg;
-	int s, c, i;
-
-	s = splhi();
-	while(up->txbusy == 0 && (c = qbgetc(up->oq)) != -1){
-		if(predawn){
-			while(up->txb->status & BDReady)
-				;
-		} else {
-			for(i = 0; i < 100; i++){
-				if((up->txb->status & BDReady) == 0)
-					break;
-				delay(1);
-			}
-		}
-		up->txbuf[0] = c;
-		up->txb->length = 1;
-		up->txb->status |= BDReady;
-		up->txbusy = !predawn;
-	}
-	splx(s);
-}
-
-void
-uartspecial(int port, int baud, Queue **iq, Queue **oq, void (*rx)(Queue*,int))
-{
-	Uart *up = &uart[0];
-
-	if(up->setup)
-		return;
-	up->setup = 1;
-
-	*iq = up->iq = qopen(4*1024, 0, 0, 0);
-	*oq = up->oq = qopen(16*1024, 0, uartkick, up);
-	up->rx = rx;
-	USED(port);
-	up->port = SMC1ID;
-	if(baud == 0)
-		baud = 9600;
-	smcsetup(up, baud);
-	/* if using SCCn's UART, would also set DTR and RTS, but SMC doesn't use them */
-}
-
-void
-uartsetboot(void (*f)(uchar*, int))
-{
-	uart[0].boot = f;
-}
-
-void
-uartputs(char *s, int n)
-{
-	Uart *up = &uart[0];
-	Block *b;
-	int nl;
-	char *p;
-
-	nl = 0;
-	for(p = s; p < s+n; p++)
-		if(*p == '\n')
-			nl++;
-	b = iallocb(n+nl);
-	while(n--){
-		if(*s == '\n')
-			*b->wp++ = '\r';
-		*b->wp++ = *s++;
-	}
-	qbwrite(up->oq, b);
-}
-
-void
-uartwait(void)
-{
-	Uart *up = &uart[0];
-
-	while(up->txbusy)
-		;
-}
--- a/os/boot/mpc/dload.c
+++ /dev/null
@@ -1,103 +1,0 @@
-#include <u.h>
-#include <libc.h>
-#include <bio.h>
-#include <mach.h>
-
-static	char	*kernelfile = "/power/ipaq";
-ulong	crc32(void *buf, int n, ulong crc);
-
-void
-main(int argc, char **argv)
-{
-	int ifd, n;
-	char buf[64], reply[1];
-	int i, execsize;
-	Fhdr f;
-	ulong csum;
-
-	ARGBEGIN{
-	}ARGEND
-	ifd = open(kernelfile, OREAD);
-	if(ifd < 0){
-		fprint(2, "dload: can't open %s: %r\n", kernelfile);
-		exits("open");
-	}
-	i = 0;
-	if(crackhdr(ifd, &f) == 0){
-		fprint(2, "dload: not an executable file: %r\n");
-		exits("format");
-	}
-	if(f.magic != Q_MAGIC){
-		fprint(2, "dload: not a powerpc executable\n");
-		exits("format");
-	}
-	execsize = f.txtsz + f.datsz + f.txtoff;
-	seek(ifd, 0, 0);
-	csum = ~0;
-	while(execsize > 0 && (n = read(ifd, buf, sizeof(buf))) > 0){
-		if(n > execsize)
-			n = execsize;
-		for(;;){
-			if(write(1, buf, sizeof(buf)) != sizeof(buf)){	/* always writes full buffer */
-				fprint(2, "dload: write error: %r\n");
-				exits("write");
-			}
-			if(read(0, reply, 1) != 1){
-				fprint(2, "dload: bad reply\n");
-				exits("read");
-			}
-			if(reply[0] != 'n')
-				break;
-			fprint(2, "!");
-		}
-		if(reply[0] != 'y'){
-			fprint(2, "dload: bad ack: %c\n", reply[0]);
-			exits("reply");
-		}
-		if(++i%10 == 0)
-			fprint(2, ".");
-		execsize -= n;
-	}
-	exits(0);
-}
-
-/*
- * from Rob Warnock
- */
-static	ulong	crc32tab[256];	/* initialised on first call to crc32 */
-
-enum {
-	CRC32POLY = 0x04c11db7     /* AUTODIN II, Ethernet, & FDDI */
-};
-
-/*
- * Build auxiliary table for parallel byte-at-a-time CRC-32.
- */
-static void
-initcrc32(void)
-{
-	int i, j;
-	ulong c;
-
-	for(i = 0; i < 256; i++) {
-		for(c = i << 24, j = 8; j > 0; j--)
-			if(c & (1<<31))
-				c = (c<<1) ^ CRC32POLY;
-			else
-				c <<= 1;
-		crc32tab[i] = c;
-	}
-}
-
-ulong
-crc32(void *buf, int n, ulong crc)
-{
-	uchar *p;
-
-	if(crc32tab[1] == 0)
-		initcrc32();
-	crc = ~crc;
-	for(p = buf; --n >= 0;)
-		crc = (crc << 8) ^ crc32tab[(crc >> 24) ^ *p++];
-	return ~crc;
-}
--- a/os/boot/mpc/donprint.c
+++ /dev/null
@@ -1,332 +1,0 @@
-#include	"u.h"
-#include	"lib.h"
-
-#define	PTR	sizeof(char*)
-#define	SHORT	sizeof(int)
-#define	INT	sizeof(int)
-#define	LONG	sizeof(long)
-#define	IDIGIT	30
-#define	MAXCON	30
-
-#define	FLONG	(1<<0)
-#define	FSHORT	(1<<1)
-#define	FUNSIGN	(1<<2)
-
-typedef struct Op	Op;
-struct Op
-{
-	char	*p;
-	char	*ep;
-	void	*argp;
-	int	f1;
-	int	f2;
-	int	f3;
-};
-
-static	int	noconv(Op*);
-static	int	cconv(Op*);
-static	int	dconv(Op*);
-static	int	hconv(Op*);
-static	int	lconv(Op*);
-static	int	oconv(Op*);
-static	int	sconv(Op*);
-static	int	uconv(Op*);
-static	int	xconv(Op*);
-static	int	Xconv(Op*);
-static	int	percent(Op*);
-
-static
-int	(*fmtconv[MAXCON])(Op*) =
-{
-	noconv,
-	cconv, dconv, hconv, lconv,
-	oconv, sconv, uconv, xconv,
-	Xconv, percent,
-};
-static
-char	fmtindex[128] =
-{
-	['c'] 1,
-	['d'] 2,
-	['h'] 3,
-	['l'] 4,
-	['o'] 5,
-	['s'] 6,
-	['u'] 7,
-	['x'] 8,
-	['X'] 9,
-	['%'] 10,
-};
-
-static	int	convcount  = { 11 };
-static	int	ucase;
-
-static void
-PUT(Op *o, int c)
-{
-	static int pos;
-	int opos;
-
-	if(c == '\t'){
-		opos = pos;
-		pos = (opos+8) & ~7;
-		while(opos++ < pos && o->p < o->ep)
-			*o->p++ = ' ';
-		return;
-	}
-	if(o->p < o->ep){
-		*o->p++ = c;
-		pos++;
-	}
-	if(c == '\n')
-		pos = 0;
-}
-
-int
-fmtinstall(char c, int (*f)(Op*))
-{
-
-	c &= 0177;
-	if(fmtindex[c] == 0) {
-		if(convcount >= MAXCON)
-			return 1;
-		fmtindex[c] = convcount++;
-	}
-	fmtconv[fmtindex[c]] = f;
-	return 0;
-}
-
-char*
-donprint(char *p, char *ep, char *fmt, void *argp)
-{
-	int sf1, c;
-	Op o;
-
-	o.p = p;
-	o.ep = ep;
-	o.argp = argp;
-
-loop:
-	c = *fmt++;
-	if(c != '%') {
-		if(c == 0) {
-			if(o.p < o.ep)
-				*o.p = 0;
-			return o.p;
-		}
-		PUT(&o, c);
-		goto loop;
-	}
-	o.f1 = 0;
-	o.f2 = -1;
-	o.f3 = 0;
-	c = *fmt++;
-	sf1 = 0;
-	if(c == '-') {
-		sf1 = 1;
-		c = *fmt++;
-	}
-	while(c >= '0' && c <= '9') {
-		o.f1 = o.f1*10 + c-'0';
-		c = *fmt++;
-	}
-	if(sf1)
-		o.f1 = -o.f1;
-	if(c != '.')
-		goto l1;
-	c = *fmt++;
-	while(c >= '0' && c <= '9') {
-		if(o.f2 < 0)
-			o.f2 = 0;
-		o.f2 = o.f2*10 + c-'0';
-		c = *fmt++;
-	}
-l1:
-	if(c == 0)
-		fmt--;
-	c = (*fmtconv[fmtindex[c&0177]])(&o);
-	if(c < 0) {
-		o.f3 |= -c;
-		c = *fmt++;
-		goto l1;
-	}
-	o.argp = (char*)o.argp + c;
-	goto loop;
-}
-
-void
-strconv(char *o, Op *op, int f1, int f2)
-{
-	int n, c;
-	char *p;
-
-	n = strlen(o);
-	if(f1 >= 0)
-		while(n < f1) {
-			PUT(op, ' ');
-			n++;
-		}
-	for(p=o; c = *p++;)
-		if(f2 != 0) {
-			PUT(op, c);
-			f2--;
-		}
-	if(f1 < 0) {
-		f1 = -f1;
-		while(n < f1) {
-			PUT(op, ' ');
-			n++;
-		}
-	}
-}
-
-int
-numbconv(Op *op, int base)
-{
-	char b[IDIGIT];
-	int i, f, n, r;
-	long v;
-	short h;
-
-	f = 0;
-	switch(op->f3 & (FLONG|FSHORT|FUNSIGN)) {
-	case FLONG:
-		v = *(long*)op->argp;
-		r = LONG;
-		break;
-
-	case FUNSIGN|FLONG:
-		v = *(ulong*)op->argp;
-		r = LONG;
-		break;
-
-	case FSHORT:
-		h = *(int*)op->argp;
-		v = h;
-		r = SHORT;
-		break;
-
-	case FUNSIGN|FSHORT:
-		h = *(int*)op->argp;
-		v = (ushort)h;
-		r = SHORT;
-		break;
-
-	default:
-		v = *(int*)op->argp;
-		r = INT;
-		break;
-
-	case FUNSIGN:
-		v = *(unsigned*)op->argp;
-		r = INT;
-		break;
-	}
-	if(!(op->f3 & FUNSIGN) && v < 0) {
-		v = -v;
-		f = 1;
-	}
-	b[IDIGIT-1] = 0;
-	for(i = IDIGIT-2;; i--) {
-		n = (ulong)v % base;
-		n += '0';
-		if(n > '9'){
-			n += 'a' - ('9'+1);
-			if(ucase)
-				n += 'A'-'a';
-		}
-		b[i] = n;
-		if(i < 2)
-			break;
-		v = (ulong)v / base;
-		if(op->f2 >= 0 && i >= IDIGIT-op->f2)
-			continue;
-		if(v <= 0)
-			break;
-	}
-	if(f)
-		b[--i] = '-';
-	strconv(b+i, op, op->f1, -1);
-	return r;
-}
-
-static	int
-noconv(Op *op)
-{
-
-	strconv("***", op, 0, -1);
-	return 0;
-}
-
-static	int
-cconv(Op *op)
-{
-	char b[2];
-
-	b[0] = *(int*)op->argp;
-	b[1] = 0;
-	strconv(b, op, op->f1, -1);
-	return INT;
-}
-
-static	int
-dconv(Op *op)
-{
-	return numbconv(op, 10);
-}
-
-static	int
-hconv(Op*)
-{
-	return -FSHORT;
-}
-
-static	int
-lconv(Op*)
-{
-	return -FLONG;
-}
-
-static	int
-oconv(Op *op)
-{
-	return numbconv(op, 8);
-}
-
-static	int
-sconv(Op *op)
-{
-	strconv(*(char**)op->argp, op, op->f1, op->f2);
-	return PTR;
-}
-
-static	int
-uconv(Op*)
-{
-	return -FUNSIGN;
-}
-
-static	int
-xconv(Op *op)
-{
-	return numbconv(op, 16);
-}
-
-static	int
-Xconv(Op *op)
-{
-	int r;
-
-	ucase = 1;
-	r = numbconv(op, 16);
-	ucase = 0;
-	return r;
-}
-
-static	int
-percent(Op *op)
-{
-
-	PUT(op, '%');
-	return 0;
-}
--- a/os/boot/mpc/dosboot.c
+++ /dev/null
@@ -1,614 +1,0 @@
-#include	"u.h"
-#include	"lib.h"
-#include	"mem.h"
-#include	"dat.h"
-#include	"fns.h"
-#include	"dosfs.h"
-
-extern char *premature;
-
-/*
- *  predeclared
- */
-static void	bootdump(Dosboot*);
-static void	setname(Dosfile*, char*);
-long		dosreadseg(Dosfile*, long, long);
-
-/*
- *  debugging
- */
-#define chatty	1
-#define chat	if(chatty)print
-
-/*
- *  block io buffers
- */
-enum
-{
-	Nbio=	16,
-};
-typedef struct	Clustbuf	Clustbuf;
-struct Clustbuf
-{
-	int	age;
-	long	sector;
-	uchar	*iobuf;
-	Dos	*dos;
-	int	size;
-};
-Clustbuf	bio[Nbio];
-
-/*
- *  get an io block from an io buffer
- */
-Clustbuf*
-getclust(Dos *dos, long sector)
-{
-	Clustbuf *p, *oldest;
-	int size;
-
-	chat("getclust @ %d\n", sector);
-
-	/*
-	 *  if we have it, just return it
-	 */
-	for(p = bio; p < &bio[Nbio]; p++){
-		if(sector == p->sector && dos == p->dos){
-			p->age = m->ticks;
-			chat("getclust %d in cache\n", sector);
-			return p;
-		}
-	}
-
-	/*
-	 *  otherwise, reuse the oldest entry
-	 */
-	oldest = bio;
-	for(p = &bio[1]; p < &bio[Nbio]; p++){
-		if(p->age <= oldest->age)
-			oldest = p;
-	}
-	p = oldest;
-
-	/*
-	 *  make sure the buffer is big enough
-	 */
-	size = dos->clustsize*dos->sectsize;
-	if(p->iobuf==0 || p->size < size)
-		p->iobuf = ialloc(size, 0);
-	p->size = size;
-
-	/*
-	 *  read in the cluster
-	 */
-	chat("getclust addr %d\n", (sector+dos->start)*dos->sectsize);
-	if((*dos->seek)(dos->dev, (sector+dos->start)*dos->sectsize) < 0){
-		chat("can't seek block\n");
-		return 0;
-	}
-	if((*dos->read)(dos->dev, p->iobuf, size) != size){
-		chat("can't read block\n");
-		return 0;
-	}
-
-	p->age = m->ticks;
-	p->dos = dos;
-	p->sector = sector;
-	chat("getclust %d read\n", sector);
-	return p;
-}
-
-/*
- *  walk the fat one level ( n is a current cluster number ).
- *  return the new cluster number or -1 if no more.
- */
-static long
-fatwalk(Dos *dos, int n)
-{
-	ulong k, sect;
-	Clustbuf *p;
-	int o;
-
-	chat("fatwalk %d\n", n);
-
-	if(n < 2 || n >= dos->fatclusters)
-		return -1;
-
-	switch(dos->fatbits){
-	case 12:
-		k = (3*n)/2; break;
-	case 16:
-		k = 2*n; break;
-	default:
-		return -1;
-	}
-	if(k >= dos->fatsize*dos->sectsize)
-		panic("getfat");
-
-	sect = (k/(dos->sectsize*dos->clustsize))*dos->clustsize + dos->fataddr;
-	o = k%(dos->sectsize*dos->clustsize);
-	p = getclust(dos, sect);
-	k = p->iobuf[o++];
-	if(o >= dos->sectsize*dos->clustsize){
-		p = getclust(dos, sect+dos->clustsize);
-		o = 0;
-	}
-	k |= p->iobuf[o]<<8;
-	if(dos->fatbits == 12){
-		if(n&1)
-			k >>= 4;
-		else
-			k &= 0xfff;
-		if(k >= 0xff8)
-			k |= 0xf000;
-	}
-	k = k < 0xfff8 ? k : -1;
-	chat("fatwalk %d -> %d\n", n, k);
-	return k;
-}
-
-/*
- *  map a file's logical cluster address to a physical sector address
- */
-static long
-fileaddr(Dosfile *fp, long ltarget)
-{
-	Dos *dos = fp->dos;
-	long l;
-	long p;
-
-	chat("fileaddr %8.8s %d\n", fp->name, ltarget);
-	/*
-	 *  root directory is contiguous and easy
-	 */
-	if(fp->pstart == 0){
-		if(ltarget*dos->sectsize*dos->clustsize >= dos->rootsize*sizeof(Dosdir))
-			return -1;
-		l = dos->rootaddr + ltarget*dos->clustsize;
-		chat("fileaddr %d -> %d\n", ltarget, l);
-		return l;
-	}
-
-	/*
-	 *  anything else requires a walk through the fat
-	 */
-	if(ltarget >= fp->lcurrent && fp->pcurrent){
-		/* start at the currrent point */
-		l = fp->lcurrent;
-		p = fp->pcurrent;
-	} else {
-		/* go back to the beginning */
-		l = 0;
-		p = fp->pstart;
-	}
-	while(l != ltarget){
-		/* walk the fat */
-		p = fatwalk(dos, p);
-		if(p < 0)
-			return -1;
-		l++;
-	}
-	fp->lcurrent = l;
-	fp->pcurrent = p;
-
-	/*
-	 *  clusters start at 2 instead of 0 (why? - presotto)
-	 */
-	l =  dos->dataaddr + (p-2)*dos->clustsize;
-	chat("fileaddr %d -> %d\n", ltarget, l);
-	return l;
-}
-
-/*
- *  read from a dos file
- */
-long
-dosread(Dosfile *fp, void *a, long n)
-{
-	long addr;
-	long rv;
-	int i;
-	int off;
-	Clustbuf *p;
-	uchar *from, *to;
-
-	if((fp->attr & DDIR) == 0){
-		if(fp->offset >= fp->length)
-			return 0;
-		if(fp->offset+n > fp->length)
-			n = fp->length - fp->offset;
-	}
-
-	to = a;
-	for(rv = 0; rv < n; rv+=i){
-		/*
-		 *  read the cluster
-		 */
-		addr = fileaddr(fp, fp->offset/fp->dos->clustbytes);
-		if(addr < 0)
-			return -1;
-		p = getclust(fp->dos, addr);
-		if(p == 0)
-			return -1;
-
-		/*
-		 *  copy the bytes we need
-		 */
-		off = fp->offset % fp->dos->clustbytes;
-		from = &p->iobuf[off];
-		i = n - rv;
-		if(i > fp->dos->clustbytes - off)
-			i = fp->dos->clustbytes - off;
-		memmove(to, from, i);
-		to += i;
-		fp->offset += i;
-	}
-
-	return rv;
-}
-
-/*
- *  walk a directory returns
- * 	-1 if something went wrong
- *	 0 if not found
- *	 1 if found
- */
-int
-doswalk(Dosfile *file, char *name)
-{
-	Dosdir d;
-	long n;
-
-	if((file->attr & DDIR) == 0){
-		chat("walking non-directory!\n");
-		return -1;
-	}
-
-	setname(file, name);
-
-	file->offset = 0;	/* start at the beginning */
-	while((n = dosread(file, &d, sizeof(d))) == sizeof(d)){
-		chat("comparing to %8.8s.%3.3s\n", d.name, d.ext);
-		if(memcmp(file->name, d.name, sizeof(d.name)) != 0)
-			continue;
-		if(memcmp(file->ext, d.ext, sizeof(d.ext)) != 0)
-			continue;
-		if(d.attr & DVLABEL){
-			chat("%8.8s.%3.3s is a LABEL\n", d.name, d.ext);
-			continue;
-		}
-		file->attr = d.attr;
-		file->pstart = GSHORT(d.start);
-		file->length = GLONG(d.length);
-		file->pcurrent = 0;
-		file->lcurrent = 0;
-		file->offset = 0;
-		return 1;
-	}
-	return n >= 0 ? 0 : -1;
-}
-
-
-/*
- *  instructions that boot blocks can start with
- */
-#define	JMPSHORT	0xeb
-#define JMPNEAR		0xe9
-
-/*
- *  read dos file system properties
- */
-int
-dosinit(Dos *dos, int start, int ishard)
-{
-	Dosboot *b;
-	int i;
-	Clustbuf *p;
-	Dospart *dp;
-	ulong mbroffset, offset;
-
-	/* defaults till we know better */
-	dos->start = start;
-	dos->sectsize = 512;
-	dos->clustsize = 1;
-	mbroffset = 0;
-
-dmddo:
-	/* get first sector */
-	p = getclust(dos, mbroffset);
-	if(p == 0){
-		chat("can't read boot block\n");
-		return -1;
-	}
-
-	/*
-	 * If it's a hard disc then look for an MBR and pick either an
-	 * active partition or the FAT with the lowest starting LBA.
-	 * Things are tricky because we could be pointing to, amongst others:
-	 *	1) a floppy BPB;
-	 *	2) a hard disc MBR;
-	 *	3) a hard disc extended partition table;
-	 *	4) a logical drive on a hard disc;
-	 *	5) a disc-manager boot block.
-	 * They all have the same magic at the end of the block.
-	 */
-	if(p->iobuf[0x1FE] != 0x55 || p->iobuf[0x1FF] != 0xAA) {
-		chat("not DOS\n");
-		return -1;
-	}
-	p->dos = 0;
-	b = (Dosboot *)p->iobuf;
-	if(ishard && b->mediadesc != 0xF8){
-		dp = (Dospart*)&p->iobuf[0x1BE];
-		offset = 0xFFFFFFFF;
-		for(i = 0; i < 4; i++, dp++){
-			if(dp->type == DMDDO){
-				mbroffset = 63;
-				goto dmddo;
-			}
-			if(dp->type != FAT12 && dp->type != FAT16 && dp->type != FATHUGE)
-				continue;
-			if(dp->flag & 0x80){
-				offset = GLONG(dp->start);
-				break;
-			}
-			if(GLONG(dp->start) < offset)
-				offset = GLONG(dp->start);
-		}
-		if(i != 4 || offset != 0xFFFFFFFF){
-			dos->start = mbroffset+offset;
-			p = getclust(dos, 0);
-			if(p == 0 || p->iobuf[0x1FE] != 0x55 || p->iobuf[0x1FF] != 0xAA)
-				return -1;
-		}
-		p->dos = 0;
-	}
-
-	b = (Dosboot *)p->iobuf;
-	if(b->magic[0] != JMPNEAR && (b->magic[0] != JMPSHORT || b->magic[2] != 0x90)){
-		chat("no dos file system\n");
-		return -1;
-	}
-
-	if(chatty)
-		bootdump(b);
-
-	/*
-	 *  determine the systems' wondersous properties
-	 */
-	dos->sectsize = GSHORT(b->sectsize);
-	dos->clustsize = b->clustsize;
-	dos->clustbytes = dos->sectsize*dos->clustsize;
-	dos->nresrv = GSHORT(b->nresrv);
-	dos->nfats = b->nfats;
-	dos->rootsize = GSHORT(b->rootsize);
-	dos->volsize = GSHORT(b->volsize);
-	if(dos->volsize == 0)
-		dos->volsize = GLONG(b->bigvolsize);
-	dos->mediadesc = b->mediadesc;
-	dos->fatsize = GSHORT(b->fatsize);
-	dos->fataddr = dos->nresrv;
-	dos->rootaddr = dos->fataddr + dos->nfats*dos->fatsize;
-	i = dos->rootsize*sizeof(Dosdir) + dos->sectsize - 1;
-	i = i/dos->sectsize;
-	dos->dataaddr = dos->rootaddr + i;
-	dos->fatclusters = 2+(dos->volsize - dos->dataaddr)/dos->clustsize;
-	if(dos->fatclusters < 4087)
-		dos->fatbits = 12;
-	else
-		dos->fatbits = 16;
-	dos->freeptr = 2;
-
-	/*
-	 *  set up the root
-	 */
-	dos->root.dos = dos;
-	dos->root.pstart = 0;
-	dos->root.pcurrent = dos->root.lcurrent = 0;
-	dos->root.offset = 0;
-	dos->root.attr = DDIR;
-	dos->root.length = dos->rootsize*sizeof(Dosdir);
-
-	return 0;
-}
-
-static void
-bootdump(Dosboot *b)
-{
-	if(chatty == 0)
-		return;
-	print("magic: 0x%2.2x 0x%2.2x 0x%2.2x\n",
-		b->magic[0], b->magic[1], b->magic[2]);
-	print("version: \"%8.8s\"\n", b->version);
-	print("sectsize: %d\n", GSHORT(b->sectsize));
-	print("allocsize: %d\n", b->clustsize);
-	print("nresrv: %d\n", GSHORT(b->nresrv));
-	print("nfats: %d\n", b->nfats);
-	print("rootsize: %d\n", GSHORT(b->rootsize));
-	print("volsize: %d\n", GSHORT(b->volsize));
-	print("mediadesc: 0x%2.2x\n", b->mediadesc);
-	print("fatsize: %d\n", GSHORT(b->fatsize));
-	print("trksize: %d\n", GSHORT(b->trksize));
-	print("nheads: %d\n", GSHORT(b->nheads));
-	print("nhidden: %d\n", GLONG(b->nhidden));
-	print("bigvolsize: %d\n", GLONG(b->bigvolsize));
-	print("driveno: %d\n", b->driveno);
-	print("reserved0: 0x%2.2x\n", b->reserved0);
-	print("bootsig: 0x%2.2x\n", b->bootsig);
-	print("volid: 0x%8.8x\n", GLONG(b->volid));
-	print("label: \"%11.11s\"\n", b->label);
-}
-
-/*
- *  grab next element from a path, return the pointer to unprocessed portion of
- *  path.
- */
-static char *
-nextelem(char *path, char *elem)
-{
-	int i;
-
-	while(*path == '/')
-		path++;
-	if(*path==0 || *path==' ')
-		return 0;
-	for(i=0; *path!='\0' && *path!='/' && *path!=' '; i++){
-		if(i==28){
-			print("name component too long\n");
-			return 0;
-		}
-		*elem++ = *path++;
-	}
-	*elem = '\0';
-	return path;
-}
-
-int
-dosstat(Dos *dos, char *path, Dosfile *f)
-{
-	char element[NAMELEN];
-
-	*f = dos->root;
-	while(path = nextelem(path, element)){
-		switch(doswalk(f, element)){
-		case -1:
-			return -1;
-		case 0:
-			return 0;
-		}
-	}
-	return 1;
-}
-
-/*
- *  boot
- */
-int
-dosboot(Dos *dos, char *path)
-{
-	Dosfile file;
-	long n;
-	long addr;
-	Exec *ep;
-	void (*b)(void);
-
-	switch(dosstat(dos, path, &file)){
-
-	case -1:
-		print("error walking to %s\n", path);
-		return -1;
-	case 0:
-		print("%s not found\n", path);
-		return -1;
-	case 1:
-		print("found %8.8s.%3.3s attr 0x%ux start 0x%lux len %d\n", file.name,
-			file.ext, file.attr, file.pstart, file.length);
-		break;
-	}
-
-	/*
-	 *  read header
-	 */
-	ep = (Exec*)ialloc(sizeof(Exec), 0);
-	n = sizeof(Exec);
-	if(dosreadseg(&file, n, (ulong) ep) != n){
-		print(premature);
-		return -1;
-	}
-	if(GLLONG(ep->magic) != Q_MAGIC){
-		print("bad magic 0x%lux not a plan 9 executable!\n", GLLONG(ep->magic));
-		return -1;
-	}
-
-	/*
-	 *  read text
-	 */
-	addr = PADDR(GLLONG(ep->entry));
-	n = GLLONG(ep->text);
-	print("+%d", n);
-	if(dosreadseg(&file, n, addr) != n){
-		print(premature);
-		return -1;
-	}
-
-	/*
-	 *  read data (starts at first page after kernel)
-	 */
-	addr = PGROUND(addr+n);
-	n = GLLONG(ep->data);
-	print("+%d", n);
-	if(dosreadseg(&file, n, addr) != n){
-		print(premature);
-		return -1;
-	}
-
-	/*
-	 *  bss and entry point
-	 */
-	print("+%d\nstart at 0x%lux\n", GLLONG(ep->bss), GLLONG(ep->entry));
-
-	/*
-	 *  Go to new code. It's up to the program to get its PC relocated to
-	 *  the right place.
-	 */
-	b = (void (*)(void))(PADDR(GLLONG(ep->entry)));
-	(*b)();
-	return 0;
-}
-
-/*
- *  read in a segment
- */
-long
-dosreadseg(Dosfile *fp, long len, long addr)
-{
-	char *a;
-	long n, sofar;
-
-	a = (char *)addr;
-	for(sofar = 0; sofar < len; sofar += n){
-		n = 8*1024;
-		if(len - sofar < n)
-			n = len - sofar;
-		n = dosread(fp, a + sofar, n);
-		if(n <= 0)
-			break;
-		print(".");
-	}
-	return sofar;
-}
-
-/*
- *  set up a dos file name
- */
-static void
-setname(Dosfile *fp, char *from)
-{
-	char *to;
-
-	to = fp->name;
-	for(; *from && to-fp->name < 8; from++, to++){
-		if(*from == '.'){
-			from++;
-			break;
-		}
-		if(*from >= 'a' && *from <= 'z')
-			*to = *from + 'A' - 'a';
-		else
-			*to = *from;
-	}
-	while(to - fp->name < 8)
-		*to++ = ' ';
-	
-	to = fp->ext;
-	for(; *from && to-fp->ext < 3; from++, to++){
-		if(*from >= 'a' && *from <= 'z')
-			*to = *from + 'A' - 'a';
-		else
-			*to = *from;
-	}
-	while(to-fp->ext < 3)
-		*to++ = ' ';
-
-	chat("name is %8.8s %3.3s\n", fp->name, fp->ext);
-}
--- a/os/boot/mpc/dosfs.h
+++ /dev/null
@@ -1,110 +1,0 @@
-typedef struct Dosboot	Dosboot;
-typedef struct Dos	Dos;
-typedef struct Dosdir	Dosdir;
-typedef struct Dosfile	Dosfile;
-typedef struct Dospart	Dospart;
-
-struct Dospart
-{
-	uchar flag;		/* active flag */
-	uchar shead;		/* starting head */
-	uchar scs[2];		/* starting cylinder/sector */
-	uchar type;		/* partition type */
-	uchar ehead;		/* ending head */
-	uchar ecs[2];		/* ending cylinder/sector */
-	uchar start[4];		/* starting sector */
-	uchar len[4];		/* length in sectors */
-};
-
-#define FAT12	0x01
-#define FAT16	0x04
-#define FATHUGE	0x06
-#define DMDDO	0x54
-
-struct Dosboot{
-	uchar	magic[3];
-	uchar	version[8];
-	uchar	sectsize[2];
-	uchar	clustsize;
-	uchar	nresrv[2];
-	uchar	nfats;
-	uchar	rootsize[2];
-	uchar	volsize[2];
-	uchar	mediadesc;
-	uchar	fatsize[2];
-	uchar	trksize[2];
-	uchar	nheads[2];
-	uchar	nhidden[4];
-	uchar	bigvolsize[4];
-	uchar	driveno;
-	uchar	reserved0;
-	uchar	bootsig;
-	uchar	volid[4];
-	uchar	label[11];
-	uchar	reserved1[8];
-};
-
-struct Dosfile{
-	Dos	*dos;		/* owning dos file system */
-	char	name[8];
-	char	ext[3];
-	uchar	attr;
-	long	length;
-	long	pstart;		/* physical start cluster address */
-	long	pcurrent;	/* physical current cluster address */
-	long	lcurrent;	/* logical current cluster address */
-	long	offset;
-};
-
-struct Dos{
-	int	dev;				/* device id */
-	long	(*read)(int, void*, long);	/* read routine */
-	long	(*seek)(int, long);		/* seek routine */
-
-	int	start;		/* start of file system */
-	int	sectsize;	/* in bytes */
-	int	clustsize;	/* in sectors */
-	int	clustbytes;	/* in bytes */
-	int	nresrv;		/* sectors */
-	int	nfats;		/* usually 2 */
-	int	rootsize;	/* number of entries */
-	int	volsize;	/* in sectors */
-	int	mediadesc;
-	int	fatsize;	/* in sectors */
-	int	fatclusters;
-	int	fatbits;	/* 12 or 16 */
-	long	fataddr;	/* sector number */
-	long	rootaddr;
-	long	dataaddr;
-	long	freeptr;
-
-	Dosfile	root;
-};
-
-struct Dosdir{
-	uchar	name[8];
-	uchar	ext[3];
-	uchar	attr;
-	uchar	reserved[10];
-	uchar	time[2];
-	uchar	date[2];
-	uchar	start[2];
-	uchar	length[4];
-};
-
-#define	DRONLY	0x01
-#define	DHIDDEN	0x02
-#define	DSYSTEM	0x04
-#define	DVLABEL	0x08
-#define	DDIR	0x10
-#define	DARCH	0x20
-
-extern int chatty;
-
-extern int dosboot(Dos*, char*);
-extern int dosinit(Dos*, int, int);
-extern long dosread(Dosfile*, void*, long);
-extern int dosstat(Dos*, char*, Dosfile*);
-extern int doswalk(Dosfile*, char*);
-
-extern int plan9ini(Dos*, char*);
--- a/os/boot/mpc/etherif.h
+++ /dev/null
@@ -1,59 +1,0 @@
-/*
- * All the goo for PC ethernet cards.
- */
-typedef struct Card Card;
-typedef struct Type Type;
-typedef struct Ctlr Ctlr;
-
-/*
- * Hardware interface.
- */
-struct Card {
-	ISAConf;
-
-	int	(*reset)(Ctlr*);
-	void	(*attach)(Ctlr*);
-
-	void	*(*read)(Ctlr*, void*, ulong, ulong);
-	void	*(*write)(Ctlr*, ulong, void*, ulong);
-
-	void	(*receive)(Ctlr*);
-	void	(*transmit)(Ctlr*);
-	void	(*intr)(Ureg*, void*);
-	void	(*overflow)(Ctlr*);
-
-	uchar	bit16;			/* true if a 16 bit interface */
-	uchar	ram;			/* true if card has shared memory */
-
-	ulong	dp8390;			/* I/O address of 8390 (if any) */
-	ulong	data;			/* I/O data port if no shared memory */
-	uchar	nxtpkt;			/* software bndry */
-	uchar	tstart;			/* 8390 ring addresses */
-	uchar	pstart;
-	uchar	pstop;
-
-	uchar	dummyrr;		/* do dummy remote read */
-};
-
-/*
- * Software controller.
- */
-struct Ctlr {
-	Card	card;			/* hardware info */
-	int	ctlrno;
-	int	present;
-
-	Queue*	iq;
-	Queue*	oq;
-
-	int	inpackets;
-	int	outpackets;
-	int	crcs;			/* input crc errors */
-	int	oerrs;			/* output errors */
-	int	frames;			/* framing errors */
-	int	overflows;		/* packet overflows */
-	int	buffs;			/* buffering errors */
-};
-
-extern int sccethreset(Ctlr*);
-extern int	etheriq(Ctlr*, Block*, int);
--- a/os/boot/mpc/etherscc.c
+++ /dev/null
@@ -1,411 +1,0 @@
-/*
- * SCCn ethernet
- */
-
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-#include "etherif.h"
-
-enum {
-	Nrdre		= 32,	/* receive descriptor ring entries */
-	Ntdre		= 4,	/* transmit descriptor ring entries */
-
-	Rbsize		= ETHERMAXTU+4,		/* ring buffer size (+4 for CRC) */
-	Bufsize		= (Rbsize+7)&~7,	/* aligned */
-};
-
-enum {
-	/* ether-specific Rx BD bits */
-	RxMiss=		1<<8,
-	RxeLG=		1<<5,
-	RxeNO=		1<<4,
-	RxeSH=		1<<3,
-	RxeCR=		1<<2,
-	RxeOV=		1<<1,
-	RxeCL=		1<<0,
-	RxError=		(RxeLG|RxeNO|RxeSH|RxeCR|RxeOV|RxeCL),	/* various error flags */
-
-	/* ether-specific Tx BD bits */
-	TxPad=		1<<14,	/* pad short frames */
-	TxTC=		1<<10,	/* transmit CRC */
-	TxeDEF=		1<<9,
-	TxeHB=		1<<8,
-	TxeLC=		1<<7,
-	TxeRL=		1<<6,
-	TxeUN=		1<<1,
-	TxeCSL=		1<<0,
-
-	/* scce */
-	RXB=	1<<0,
-	TXB=	1<<1,
-	BSY=		1<<2,
-	RXF=		1<<3,
-	TXE=		1<<4,
-
-	/* gsmrl */
-	ENR=	1<<5,
-	ENT=	1<<4,
-
-	/* port A */
-	RXD1=	SIBIT(15),
-	TXD1=	SIBIT(14),
-
-	/* port B */
-	RTS1=	IBIT(19),
-
-	/* port C */
-	CTS1=	SIBIT(11),
-	CD1=	SIBIT(10),
-};
-
-typedef struct Etherparam Etherparam;
-struct Etherparam {
-	SCCparam;
-	ulong	c_pres;		/* preset CRC */
-	ulong	c_mask;		/* constant mask for CRC */
-	ulong	crcec;		/* CRC error counter */
-	ulong	alec;		/* alighnment error counter */
-	ulong	disfc;		/* discard frame counter */
-	ushort	pads;		/* short frame PAD characters */
-	ushort	ret_lim;	/* retry limit threshold */
-	ushort	ret_cnt;	/* retry limit counter */
-	ushort	mflr;		/* maximum frame length reg */
-	ushort	minflr;		/* minimum frame length reg */
-	ushort	maxd1;		/* maximum DMA1 length reg */
-	ushort	maxd2;		/* maximum DMA2 length reg */
-	ushort	maxd;		/* rx max DMA */
-	ushort	dma_cnt;	/* rx dma counter */
-	ushort	max_b;		/* max bd byte count */
-	ushort	gaddr[4];		/* group address filter */
-	ulong	tbuf0_data0;	/* save area 0 - current frm */
-	ulong	tbuf0_data1;	/* save area 1 - current frm */
-	ulong	tbuf0_rba0;
-	ulong	tbuf0_crc;
-	ushort	tbuf0_bcnt;
-	ushort	paddr[3];	/* physical address LSB to MSB increasing */
-	ushort	p_per;		/* persistence */
-	ushort	rfbd_ptr;	/* rx first bd pointer */
-	ushort	tfbd_ptr;	/* tx first bd pointer */
-	ushort	tlbd_ptr;	/* tx last bd pointer */
-	ulong	tbuf1_data0;	/* save area 0 - next frame */
-	ulong	tbuf1_data1;	/* save area 1 - next frame */
-	ulong	tbuf1_rba0;
-	ulong	tbuf1_crc;
-	ushort	tbuf1_bcnt;
-	ushort	tx_len;		/* tx frame length counter */
-	ushort	iaddr[4];		/* individual address filter*/
-	ushort	boff_cnt;	/* back-off counter */
-	ushort	taddr[3];	/* temp address */
-};
-
-typedef struct {
-	SCC*	scc;
-	int	port;
-	int	cpm;
-
-	BD*	rdr;				/* receive descriptor ring */
-	void*	rrb;				/* receive ring buffers */
-	int	rdrx;				/* index into rdr */
-
-	BD*	tdr;				/* transmit descriptor ring */
-	void*	trb;				/* transmit ring buffers */
-	int	tdrx;				/* index into tdr */
-} Mot;
-static Mot mot[MaxEther];
-
-static	int	sccid[] = {-1, SCC1ID, SCC2ID, SCC3ID, SCC4ID};
-static	int	sccparam[] = {-1, SCC1P, SCC2P, SCC3P, SCC4P};
-static	int	sccreg[] = {-1, 0xA00, 0xA20, 0xA40, 0xA60};
-static	int	sccirq[] = {-1, 0x1E, 0x1D, 0x1C, 0x1B};
-
-static void
-attach(Ctlr *ctlr)
-{
-	mot[ctlr->ctlrno].scc->gsmrl |= ENR|ENT;
-	eieio();
-}
-
-static void
-transmit(Ctlr *ctlr)
-{
-	int len;
-	Mot *motp;
-	Block *b;
-	BD *tdre;
-
-	motp = &mot[ctlr->ctlrno];
-	while(((tdre = &motp->tdr[motp->tdrx])->status & BDReady) == 0){
-		b = qget(ctlr->oq);
-		if(b == 0)
-			break;
-
-		/*
-		 * Copy the packet to the transmit buffer.
-		 */
-		len = BLEN(b);
-		memmove(KADDR(tdre->addr), b->rp, len);
-	
-		/*
-		 * Give ownership of the descriptor to the chip, increment the
-		 * software ring descriptor pointer and tell the chip to poll.
-		 */
-		tdre->length = len;
-		eieio();
-		tdre->status = (tdre->status & BDWrap) | BDReady|TxPad|BDInt|BDLast|TxTC;
-		eieio();
-		motp->scc->todr = 1<<15;	/* transmit now */
-		eieio();
-		motp->tdrx = NEXT(motp->tdrx, Ntdre);
-
-		freeb(b);
-	
-	}
-}
-
-static void
-interrupt(Ureg*, void *ap)
-{
-	int len, events, status;
-	Mot *motp;
-	BD *rdre;
-	Block *b;
-	Ctlr *ctlr;
-
-	ctlr = ap;
-	motp = &mot[ctlr->ctlrno];
-
-	/*
-	 * Acknowledge all interrupts and whine about those that shouldn't
-	 * happen.
-	 */
-	events = motp->scc->scce;
-	eieio();
-	motp->scc->scce = events;
-	eieio();
-	if(events & (TXE|BSY|RXB))
-		print("ETHER.SCC#%d: scce = 0x%uX\n", ctlr->ctlrno, events);
-	//print(" %ux|", events);
-	/*
-	 * Receiver interrupt: run round the descriptor ring logging
-	 * errors and passing valid receive data up to the higher levels
-	 * until we encounter a descriptor still owned by the chip.
-	 */
-	if(events & (RXF|RXB) || 1){
-		rdre = &motp->rdr[motp->rdrx];
-		while(((status = rdre->status) & BDEmpty) == 0){
-			if(status & RxError || (status & (BDFirst|BDLast)) != (BDFirst|BDLast)){
-				//if(status & RxBuff)
-				//	ctlr->buffs++;
-				if(status & (1<<2))
-					ctlr->crcs++;
-				if(status & (1<<1))
-					ctlr->overflows++;
-				//print("eth rx: %ux\n", status);
-				if(status & RxError)
-					print("~");
-				else if((status & BDLast) == 0)
-					print("@");
-			}
-			else{
-				/*
-				 * We have a packet. Read it into the next
-				 * free ring buffer, if any.
-				 */
-				len = rdre->length-4;
-				if((b = iallocb(len)) != 0){
-					memmove(b->wp, KADDR(rdre->addr), len);
-					b->wp += len;
-					etheriq(ctlr, b, 1);
-				}
-			}
-
-			/*
-			 * Finished with this descriptor, reinitialise it,
-			 * give it back to the chip, then on to the next...
-			 */
-			rdre->length = 0;
-			rdre->status = (rdre->status & BDWrap) | BDEmpty | BDInt;
-			eieio();
-
-			motp->rdrx = NEXT(motp->rdrx, Nrdre);
-			rdre = &motp->rdr[motp->rdrx];
-		}
-	}
-
-	/*
-	 * Transmitter interrupt: handle anything queued for a free descriptor.
-	 */
-	if(events & TXB)
-		transmit(ctlr);
-	if(events & TXE)
-		cpmop(RestartTx, motp->cpm, 0);
-}
-
-static void
-ringinit(Mot* motp)
-{
-	int i, x;
-
-	/*
-	 * Initialise the receive and transmit buffer rings. The ring
-	 * entries must be aligned on 16-byte boundaries.
-	 */
-	if(motp->rdr == 0)
-		motp->rdr = bdalloc(Nrdre);
-	if(motp->rrb == 0)
-		motp->rrb = ialloc(Nrdre*Bufsize, 0);
-	x = PADDR(motp->rrb);
-	for(i = 0; i < Nrdre; i++){
-		motp->rdr[i].length = 0;
-		motp->rdr[i].addr = x;
-		motp->rdr[i].status = BDEmpty|BDInt;
-		x += Bufsize;
-	}
-	motp->rdr[i-1].status |= BDWrap;
-	motp->rdrx = 0;
-
-	if(motp->tdr == 0)
-		motp->tdr = bdalloc(Ntdre);
-	if(motp->trb == 0)
-		motp->trb = ialloc(Ntdre*Bufsize, 0);
-	x = PADDR(motp->trb);
-	for(i = 0; i < Ntdre; i++){
-		motp->tdr[i].addr = x;
-		motp->tdr[i].length = 0;
-		motp->tdr[i].status = TxPad|BDInt|BDLast|TxTC;
-		x += Bufsize;
-	}
-	motp->tdr[i-1].status |= BDWrap;
-	motp->tdrx = 0;
-}
-
-/*
- * This follows the MPC823 user guide: section16.9.23.7's initialisation sequence,
- * except that it sets the right bits for the MPC823ADS board when SCC2 is used,
- * and those for the 860/821 development board for SCC1.
- */
-static void
-sccsetup(Mot *ctlr, SCC *scc, uchar *ea)
-{
-	int i, rcs, tcs, w;
-	Etherparam *p;
-	IMM *io;
-
-
-	i = 2*(ctlr->port-1);
-	io = ioplock();
-	w = (TXD1|RXD1)<<i;	/* TXDn and RXDn in port A */
-	io->papar |= w;	/* enable TXDn and RXDn pins */
-	io->padir &= ~w;
-	io->paodr &= ~w;	/* not open drain */
-
-	w = (CD1|CTS1)<<i;	/* CLSN and RENA: CDn and CTSn in port C */
-	io->pcpar &= ~w;	/* enable CLSN (CTSn) and RENA (CDn) */
-	io->pcdir &= ~w;
-	io->pcso |= w;
-	iopunlock();
-
-	/* clocks and transceiver control: details depend on the board's wiring */
-	archetherenable(ctlr->cpm, &rcs, &tcs);
-
-	sccnmsi(ctlr->port, rcs, tcs);	/* connect the clocks */
-
-	p = (Etherparam*)KADDR(sccparam[ctlr->port]);
-	memset(p, 0, sizeof(*p));
-	p->rfcr = 0x18;
-	p->tfcr = 0x18;
-	p->mrblr = Bufsize;
-	p->rbase = PADDR(ctlr->rdr);
-	p->tbase = PADDR(ctlr->tdr);
-
-	cpmop(InitRxTx, ctlr->cpm, 0);
-
-	p->c_pres = ~0;
-	p->c_mask = 0xDEBB20E3;
-	p->crcec = 0;
-	p->alec = 0;
-	p->disfc = 0;
-	p->pads = 0x8888;
-	p->ret_lim = 0xF;
-	p->mflr = Rbsize;
-	p->minflr = ETHERMINTU+4;
-	p->maxd1 = Bufsize;
-	p->maxd2 = Bufsize;
-	p->p_per = 0;	/* only moderate aggression */
-
-	for(i=0; i<Eaddrlen; i+=2)
-		p->paddr[2-i/2] = (ea[i+1]<<8)|ea[i];	/* it's not the obvious byte order */
-
-	scc->psmr = (2<<10)|(5<<1);	/* 32-bit CRC, ignore 22 bits before SFD */
-	scc->dsr = 0xd555;
-	scc->gsmrh = 0;	/* normal operation */
-	scc->gsmrl = (1<<28)|(4<<21)|(1<<19)|0xC;	/* transmit clock invert, 48 bit preamble, repetitive 10 preamble, ethernet */
-	eieio();
-	scc->scce = ~0;	/* clear all events */
-	eieio();
-	scc->sccm = TXE | RXF | TXB;	/* enable interrupts */
-	eieio();
-
-	io = ioplock();
-	w = RTS1<<(ctlr->port-1);	/* enable TENA pin (RTSn) */
-	io->pbpar |= w;
-	io->pbdir |= w;
-	iopunlock();
-
-	/* gsmrl enable is deferred until attach */
-}
-
-/*
- * Prepare the SCCx ethernet for booting.
- */
-int
-sccethreset(Ctlr* ctlr)
-{
-	uchar ea[Eaddrlen];
-	Mot *motp;
-	SCC *scc;
-	char line[50], def[50];
-
-	/*
-	 * Since there's no EPROM, insist that the configuration entry
-	 * (see conf.c and flash.c) holds the Ethernet address.
-	 */
-	memset(ea, 0, Eaddrlen);
-	if(memcmp(ea, ctlr->card.ea, Eaddrlen) == 0){
-		print("no preset Ether address\n");
-		for(;;){
-			strcpy(def, "00108bf12900");	/* valid MAC address to be used only for initial configuration */
-			if(getstr("ether MAC address", line, sizeof(line), def) < 0)
-				return -1;
-			if(parseether(ctlr->card.ea, line) >= 0 || ctlr->card.ea[0] == 0xFF)
-				break;
-			print("invalid MAC address\n");
-		}
-	}
-
-	scc = IOREGS(sccreg[ctlr->card.port], SCC);
-	ctlr->card.irq = VectorCPIC+sccirq[ctlr->card.port];
-
-	motp = &mot[ctlr->ctlrno];
-	motp->scc = scc;
-	motp->port = ctlr->card.port;
-	motp->cpm = sccid[ctlr->card.port];
-
-	ringinit(motp);
-
-	sccsetup(motp, scc, ctlr->card.ea);
-
-	/* enable is deferred until attach */
-
-	ctlr->card.reset = sccethreset;
-	ctlr->card.attach = attach;
-	ctlr->card.transmit = transmit;
-	ctlr->card.intr = interrupt;
-
-	return 0;
-}
--- a/os/boot/mpc/fblt.c
+++ /dev/null
@@ -1,531 +1,0 @@
-#include <u.h>
-#include <libc.h>
-#include <libg.h>
-#include <gnot.h>
-
-/*
- * bitblt operates a 'word' at a time.
- * WBITS is the number of bits in a word
- * LWBITS=log2(WBITS),
- * W2L is the number of words in a long
- * WMASK has bits set for the low order word of a long
- * WType is a pointer to a word
- */
-#ifndef WBITS
-#define WBITS	32
-#define LWBITS	5
-#define	W2L	1
-#define WMASK	~0UL
-typedef ulong	*WType;
-#endif
-
-#define DEBUG 
-
-#ifdef TEST
-/*
- * globals used for testing
- */
-int	FORCEFORW;
-int	FORCEBAKW;
-GBitmap	*curdm, *cursm;
-Point	curpt;
-Rectangle curr;
-Fcode	curf;
-void	*mem;
-#endif
-
-static void
-gbitexplode(ulong sw, ulong *buf, int sdep, int x)
-{
-	int j, o, q, n, nw, inc, qinc;
-	ulong s, dw, pix;
-
-	inc = 1 << sdep;
-	pix = (1 << inc) - 1;
-	nw = 1 << x;
-	n = 32 >> x;
-	qinc = (nw << sdep) - inc;
-	for(o = 32 - n; o >= 0; o -= n){
-		dw = 0;
-		s = sw >> o;
-		q = 0;
-		for(j = 0; j < n; j += inc){
-			dw |= (s & (pix << j)) << q;
-			q += qinc;
-		}
-		for(j = 0; j < x; j++)
-			dw |= dw << (inc << j);
-		*buf++ = dw;
-	}
-}
-
-/*
-void
-main(void)
-{
-	ulong buf[128];
-
-	gbitexplode(0x7777, buf, 0, 3);
-	exits(0);
-}
-*/
-
-void
-gbitblt(GBitmap *dm, Point pt, GBitmap *sm, Rectangle r, Fcode fcode)
-{
-	int	width;		/* width in bits of dst */
-	int	wwidth;		/* floor width in words */
-	int	height;		/* height in pixels minus 1 */
-	int	sdep;		/* src ldepth */
-	int 	ddep;		/* dst ldepth */
-	int	deltadep;	/* diff between ldepths */
-	int	sspan;		/* words between scanlines in src */
-	int	dspan;		/* words between scanlines in dst */
-	int	soff;		/* bit offset of src start point */
-	int	sdest;		/* bit offset of src start point that matches doff when expanded */
-	int	doff;		/* bit offset of dst start point */
-	int	delta;		/* amount to shift src by */
-	int	sign;		/* of delta */
-	ulong	*saddr;
-	ulong	*daddr;
-	ulong	*s;
-	ulong	*d;
-	ulong	mask;
-	ulong	tmp;		/* temp storage source word */
-	ulong	sw;		/* source word constructed */
-	ulong	dw;		/* dest word fetched */
-	ulong	lmask;		/* affected pixels in leftmost dst word */
-	ulong	rmask;		/* affected pixels in rightmost dst word */
-	int	i;
-	int	j;
-	ulong	buf[32];	/* for expanding a source */
-	ulong	*p;		/* pointer into buf */
-	int	spare;		/* number of words already converted */
-
-
-#ifdef TEST
-	curdm = dm;
-	cursm = sm;
-	curpt = pt;
-	curr = r;
-	curf = fcode;
-#endif
-
-	gbitbltclip(&dm);
-
-	width = r.max.x - r.min.x;
-	if(width <= 0)
-		return;
-	height = r.max.y - r.min.y - 1;
-	if(height < 0)
-		return;
-
-	ddep = dm->ldepth;
-	pt.x <<= ddep;
-	width <<= ddep;
-
-	sdep = sm->ldepth;
-	r.min.x <<= sdep;
-	r.max.x <<= sdep;
-
-	dspan = dm->width * W2L;
-	sspan = sm->width * W2L;
-
-	daddr = (ulong*)((WType)dm->base
-			+ dm->zero*W2L + pt.y*dspan
-			+ (pt.x >> LWBITS));
-	saddr = (ulong*)((WType)sm->base
-			+ sm->zero*W2L + r.min.y*sspan
-			+ (r.min.x >> LWBITS));
-
-	doff = pt.x & (WBITS - 1);
-	lmask = WMASK >> doff;
-	rmask = (WMASK << (WBITS - ((doff+width) & (WBITS-1))))&WMASK;
-	if(!rmask)
-		rmask = WMASK;
-	soff = r.min.x & (WBITS-1);
-	wwidth = ((pt.x+width-1)>>LWBITS) - (pt.x>>LWBITS);
-
-	if(sm == dm){
-#ifdef TEST
-		if(!FORCEBAKW &&
-		   (FORCEFORW || sm != dm || saddr > daddr ||
-		    (saddr == daddr && soff > doff)))
-			;
-		else{
-			daddr += height * dspan;
-			saddr += height * sspan;
-			sspan -= 2 * W2L * sm->width;
-			dspan -= 2 * W2L * dm->width;
-		}
-#else
-		if(r.min.y < pt.y){	/* bottom to top */
-			daddr += height * dspan;
-			saddr += height * sspan;
-			sspan -= 2 * W2L * sm->width;
-			dspan -= 2 * W2L * dm->width;
-		}else if(r.min.y == pt.y && r.min.x < pt.x)
-			abort()/*goto right*/;
-#endif
-	}
-	if(wwidth == 0)		/* collapse masks for narrow cases */
-		lmask &= rmask;
-	fcode &= F;
-
-	deltadep = ddep - sdep;
-	sdest = doff >> deltadep;
-	delta = soff - sdest;
-	sign = 0;
-	if(delta < 0){
-		sign = 1;
-		delta = -delta;
-	}
-
-	p = 0;
-	for(j = 0; j <= height; j++){
-		d = daddr;
-		s = saddr;
-		mask = lmask;
-		tmp = 0;
-		if(!sign)
-			tmp = *s++;
-		spare = 0;
-		for(i = wwidth; i >= 0; i--){
-			if(spare)
-				sw = *p++;
-			else{
-				if(sign){
-					sw = tmp << (WBITS-delta);
-					tmp = *s++;
-					sw |= tmp >> delta;
-				}else{
-					sw = tmp << delta;
-					tmp = *s++;
-					if(delta)
-						sw |= tmp >> (WBITS-delta);
-				}
-				spare = 1 << deltadep;
-				if(deltadep >= 1){
-					gbitexplode(sw, buf, sdep, deltadep);
-					p = buf;
-					sw = *p++;
-				}
-			}
-
-			dw = *d;
-			switch(fcode){		/* ltor bit aligned */
-			case Zero:	*d = dw & ~mask;		break;
-			case DnorS:	*d = dw ^ ((~sw | dw) & mask);	break;
-			case DandnotS:	*d = dw ^ ((sw & dw) & mask);	break;
-			case notS:	*d = dw ^ ((~sw ^ dw) & mask);	break;
-			case notDandS:	*d = dw ^ ((sw | dw) & mask);	break;
-			case notD:	*d = dw ^ mask;			break;
-			case DxorS:	*d = dw ^ (sw & mask);		break;
-			case DnandS:	*d = dw ^ ((sw | ~dw) & mask);	break;
-			case DandS:	*d = dw ^ ((~sw & dw) & mask);	break;
-			case DxnorS:	*d = dw ^ (~sw & mask);		break;
-			case D:						break;
-			case DornotS:	*d = dw | (~sw & mask);		break;
-			case S:		*d = dw ^ ((sw ^ dw) & mask);	break;
-			case notDorS:	*d = dw ^ (~(sw & dw) & mask);	break;
-			case DorS:	*d = dw | (sw & mask);		break;
-			case F:		*d = dw | mask;			break;
-			}
-			d++;
-
-			mask = WMASK;
-			if(i == 1)
-				mask = rmask;
-			spare--;
-		}
-		saddr += sspan;
-		daddr += dspan;
-	}
-}
-
-#ifdef TEST
-void	prprog(void);
-GBitmap *bb1, *bb2;
-ulong	*src, *dst, *xdst, *xans;
-int	swds, dwds;
-long	ticks;
-int	timeit;
-
-long
-func(int f, long s, int sld, long d, int dld)
-{
-	long a;
-	int sh, i, db, sb;
-
-	db = 1 << dld;
-	sb = 1 << sld;
-	sh = db - sb;
-	if(sh > 0) {
-		a = s;
-		for(i = sb; i<db; i += sb){
-			a <<= sb;
-			s |= a;
-		}
-	} else if(sh < 0)
-		s >>= -sh;
-
-	switch(f){
-	case Zero:	d = 0;			break;
-	case DnorS:	d = ~(d|s);		break;
-	case DandnotS:	d = d & ~s;		break;
-	case notS:	d = ~s;			break;
-	case notDandS:	d = ~d & s;		break;
-	case notD:	d = ~d;			break;
-	case DxorS:	d = d ^ s;		break;
-	case DnandS:	d = ~(d&s);		break;
-	case DandS:	d = d & s;		break;
-	case DxnorS:	d = ~(d^s);		break;
-	case S:		d = s;			break;
-	case DornotS:	d = d | ~s;		break;
-	case D:		d = d;			break;
-	case notDorS:	d = ~d | s;		break;
-	case DorS:	d = d | s;		break;
-	case F:		d = ~0;			break;
-	}
-
-	d &= ((1<<db)-1);
-	return d;
-}
-
-void
-run(int fr, int to, int w, int op)
-{
-	int i, j, f, t, fy, ty;
-	extern long *_clock;
-
-	fr += bb2->r.min.x;
-	to += bb1->r.min.x;
-	fy = bb2->r.min.y + 1;
-	ty = bb1->r.min.y + 1;
-	if(timeit) {
-		memcpy(dst, xdst, dwds * sizeof(long));
-		ticks -= *_clock;
-		gbitblt(bb1, Pt(to,ty), bb2, Rect(fr,fy,fr+w,fy+2), op);
-		ticks += *_clock;
-		return;
-	}
-	f = fr;
-	t = to;
-	memcpy(dst, xdst, dwds * sizeof(long));
-	for(i=0; i<w; i++) {
-		gbitblt(bb1, Pt(t,ty), bb2, Rect(f,fy,f+1,fy+1), op);
-		gbitblt(bb1, Pt(t,ty+1), bb2, Rect(f,fy+1,f+1,fy+2), op);
-		f++;
-		t++;
-	}
-	memcpy(xans, dst, dwds * sizeof(long));
-
-	memcpy(dst, xdst, dwds * sizeof(long));
-	gbitblt(bb1, Pt(to,ty), bb2, Rect(fr,fy,fr+w,fy+2), op);
-
-	if(memcmp(xans, dst, dwds * sizeof(long))) {
-		/*
-		 * print src and dst row offset, width in bits, and forw/back
-		 * then print for each of the four rows: the source (s),
-		 * the dest (d), the good value of the answer (g),
-		 * and the actual bad value of the answer (b)
-		 */
-		print("fr=%d to=%d w=%d fb=%d%d\n",
-			fr, to, w, FORCEFORW, FORCEBAKW);
-		print("dst bitmap b %#lux, z %d, w %d, ld %d, r [%d,%d][%d,%d]\n",
-			bb1->base, bb1->zero, bb1->width, bb1->ldepth,
-			bb1->r.min.x, bb1->r.min.y, bb1->r.max.x, bb1->r.max.y);
-		print("src bitmap b %#lux, z %d, w %d, ld %d, r [%d,%d][%d,%d]\n",
-			bb2->base, bb2->zero, bb2->width, bb2->ldepth,
-			bb2->r.min.x, bb2->r.min.y, bb2->r.max.x, bb2->r.max.y);
-		for(j=0; 7*j < dwds; j++) {
-			print("\ns");
-			for(i=0; i<7 && 7*j+i < dwds; i++)
-				print(" %.8lux", src[7*j + i]);
-			print("\nd");
-			for(i=0; i<7 && 7*j+i < dwds; i++)
-				print(" %.8lux", xdst[7*j + i]);
-			print("\ng");
-			for(i=0; i<7 && 7*j+i < dwds; i++)
-				print(" %.8lux", xans[7*j + i]);
-			print("\nb");
-			for(i=0; i<7 && 7*j+i < dwds; i++)
-				print(" %.8lux", dst[7*j + i]);
-			print("\n");
-		}
-		prprog();
-	}
-}
-
-void
-prprog(void)
-{
-	exits(0);
-}
-
-int
-main(int argc, char *argv[])
-{
-	int f, t, w, i, sld, dld, op, iters, simple;
-	ulong s, d, spix, dpix, apix, fpix, m, *ps, *pd;
-	Point sorg, dorg;
-	GBitmap *bs, *bd;
-	long seed;
-	char *ct;
-
-	sld = 0;
-	dld = 0;
-	timeit = 0;
-	iters = 200;
-	simple = 0;
-	ARGBEGIN {
-	case 'i':
-		iters = atoi(ARGF());
-		break;
-	case 's':
-		simple = 1;
-		break;
-	case 't':
-		timeit = 1;
-		ct = ARGF();
-		if(ct)
-			iters = atoi(ct);
-		break;
-	} ARGEND
-	if(argc > 0)
-		sld = atoi(argv[0]);
-	if(argc > 1)
-		dld = atoi(argv[1]);
-	if(!timeit && !simple) {
-		seed = time(0);
-		print("seed %lux\n", seed); srand(seed);	/**/
-	}
-
-	print("sld %d dld %d\n", sld, dld);
-	op = 1;
-
-	/* bitmaps for 1-bit tests */
-	bd = gballoc(Rect(0,0,32,1), dld);
-	bs = gballoc(Rect(0,0,32,1), sld);
-	for(i=0; i<bs->width; i++)
-		bs->base[i] = lrand();
-
-	/* bitmaps for rect tests */
-	if(simple) {
-		dorg = Pt(0,0);
-		sorg = Pt(0,0);
-	} else {
-		dorg = Pt(nrand(63)-31,nrand(63)-31);
-		sorg = Pt(nrand(63)-31,nrand(63)-31);
-	}
-	bb1 = gballoc(Rpt(dorg,add(dorg,Pt(200,4))), dld);
-	bb2 = gballoc(Rpt(sorg,add(sorg,Pt(200,4))), sld);
-	dwds = bb1->width * Dy(bb1->r);
-	swds = bb2->width * Dy(bb2->r);
-	dst = bb1->base;
-	src = bb2->base;
-	xdst = malloc(dwds * sizeof(long));
-	xans =  malloc(dwds * sizeof(long));
-	for(i=0; i<swds; i++)
-		src[i] = lrand();
-	for(i=0; i<dwds; i++)
-		xdst[i] = lrand();
-
-loop:
-	print("Op %d\n", op);
-	if(!timeit) {
-		print("one pixel\n");
-		ps = bs->base;
-		pd = bd->base;
-		FORCEFORW = 1;
-		FORCEBAKW = 0;
-		for(i=0; i<1000; i++, FORCEFORW = !FORCEFORW, FORCEBAKW = !FORCEBAKW) {
-			f = nrand(32 >> sld);
-			t = nrand(32 >> dld);
-			s = lrand();
-			d = lrand();
-			ps[0] = s;
-			pd[0] = d;
-#ifdef T386
-			spix = (byterev(s) >> (32 - ((f+1)<<sld))) & ((1 << (1<<sld)) - 1);
-			dpix = (byterev(d) >> (32 - ((t+1)<<dld))) & ((1 << (1<<dld)) - 1);
-#else
-			spix = (s >> (32 - ((f+1)<<sld))) & ((1 << (1<<sld)) - 1);
-			dpix = (d >> (32 - ((t+1)<<dld))) & ((1 << (1<<dld)) - 1);
-#endif
-#ifdef T386
-			apix = byterev(func(op, spix, sld, dpix, dld) << (32 - ((t+1)<<dld)));
-#else
-			apix = func(op, spix, sld, dpix, dld) << (32 - ((t+1)<<dld));
-#endif
-			gbitblt(bd, Pt(t,0), bs, Rect(f,0,f+1,1), op);
-			if(ps[0] != s) {
-				print("bb src %.8lux %.8lux %d %d\n", ps[0], s, f, t);
-				exits("error");
-			}
-			m = ((1 << (1<<dld)) - 1) << (32 - ((t+1)<<dld));
-#ifdef T386
-			m = byterev(m);
-#endif
-			if((pd[0] & ~m) != (d & ~m)) {
-					print("bb dst1 %.8lux %.8lux\n",
-						s, d);
-					print("bb      %.8lux %.8lux %d %d\n",
-						ps[0], pd[0], f, t);
-					prprog();
-					exits("error");
-			}
-			if((pd[0] & m) != apix) {
-				spix <<= 32 - ((f+1)<<sld);
-				dpix <<= 32 - ((t+1)<<dld);
-#ifdef T386
-				spix = byterev(spix);
-				dpix = byterev(dpix);
-#endif
-				print("bb dst2 %.8lux %.8lux\n",
-					s, d);
-				print("bb      %.8lux %.8lux %d %d\n",
-					ps[0], pd[0], f, t);
-				print("bb      %.8lux %.8lux %.8lux %.8lux\n",
-					spix, dpix, apix, pd[0] & m);
-				prprog();
-				exits("error");
-			}
-		}
-	}
-
-	print("for\n");
-	FORCEFORW = 1;
-	FORCEBAKW = 0;
-
-	for(i=0; i<iters; i++) {
-		f = nrand(64);
-		t = nrand(64);
-		w = nrand(130);
-		run(f, t, w, op);
-	}
-
-	if(sld == dld) {
-		print("bak\n");
-		FORCEFORW = 0;
-		FORCEBAKW = 1;
-	
-		for(i=0; i<iters; i++) {
-			f = nrand(64);
-			t = nrand(64);
-			w = nrand(130);
-			run(f, t, w, op);
-		}
-	}
-
-	if(op < F) {
-		op++;
-		goto loop;
-	}
-	if(timeit)
-		print("time: %d ticks\n", ticks);
-	exits(0);
-}
-
-
-#endif
--- a/os/boot/mpc/flash.c
+++ /dev/null
@@ -1,212 +1,0 @@
-#include "boot.h"
-
-typedef struct Flashdev Flashdev;
-struct Flashdev {
-	uchar*	base;
-	int	size;
-	uchar*	exec;
-	char*	config;
-	int	conflen;
-};
-
-enum {
-	FLASHSEG = 256*1024,
-	CONFIGLIM = FLASHSEG,
-	BOOTOFF = FLASHSEG,
-	BOOTLEN = 3*FLASHSEG,	/* third segment might be filsys */
-	/* rest of flash is free */
-};
-
-static Flashdev flash;
-
-/*
- * configuration data is written between the bootstrap and
- * the end of region 0. the region ends with allocation descriptors
- * of the following form:
- *
- * byte order is big endian
- *
- * the last valid region found that starts with the string "#plan9.ini\n" is plan9.ini
- */
-typedef struct Flalloc Flalloc;
-struct Flalloc {
-	ulong	check;	/* checksum of data, or ~0 */
-	ulong	base;	/* base of region; ~0 if unallocated, 0 if deleted */
-	uchar	len[3];
-	uchar	tag;		/* see below */
-	uchar	sig[4];
-};
-
-enum {
-	/* tags */
-	Tdead=	0,
-	Tboot=	0x01,	/* space reserved for boot */
-	Tconf=	0x02,	/* configuration data */
-	Tnone=	0xFF,
-
-	Noval=	~0,
-};
-
-static char flashsig[] = {0xF1, 0xA5, 0x5A, 0x1F};
-static char conftag[] = "#plan9.ini\n";
-
-static ulong
-checksum(uchar* p, int n)
-{
-	ulong s;
-
-	for(s=0; --n >= 0;)
-		s += *p++;
-	return s;
-}
-
-static int
-validptr(Flalloc *ap, uchar *p)
-{
-	return p > (uchar*)&end && p < (uchar*)ap;
-}
-
-static int
-flashcheck(Flalloc *ap, char **val, int *len)
-{
-	uchar *base;
-	int n;
-
-	if(ap->base == Noval || ap->base >= FLASHSEG || ap->tag == Tnone)
-		return 0;
-	base = flash.base+ap->base;
-	if(!validptr(ap, base))
-		return 0;
-	n = (((ap->len[0]<<8)|ap->len[1])<<8)|ap->len[2];
-	if(n == 0xFFFFFF)
-		n = 0;
-	if(n < 0)
-		return 0;
-	if(n > 0 && !validptr(ap, base+n-1))
-		return 0;
-	if(ap->check != Noval && checksum(base, n) != ap->check){
-		print("flash: bad checksum\n");
-		return 0;
-	}
-	*val = (char*)base;
-	*len = n;
-	return 1;
-}
-
-int
-flashinit(void)
-{
-	int len;
-	char *val;
-	Flalloc *ap;
-	void *addr;
-	long mbytes;
-	char type[20];
-
-	flash.base = 0;
-	flash.exec = 0;
-	flash.size = 0;
-	if(archflashreset(type, &addr, &mbytes) < 0){
-		print("flash: flash not present or not enabled\n");	/* shouldn't happen */
-		return 0;
-	}
-	flash.size = mbytes;
-	flash.base = addr;
-	flash.exec = flash.base + BOOTOFF;
-	flash.config = nil;
-	flash.conflen = 0;
-
-	for(ap = (Flalloc*)(flash.base+CONFIGLIM)-1; memcmp(ap->sig, flashsig, 4) == 0; ap--){
-		if(0)
-			print("conf #%8.8lux: #%x #%6.6lux\n", ap, ap->tag, ap->base);
-		if(ap->tag == Tconf &&
-		   flashcheck(ap, &val, &len) &&
-		   len >= sizeof(conftag)-1 &&
-		   memcmp(val, conftag, sizeof(conftag)-1) == 0){
-			flash.config = val;
-			flash.conflen = len;
-			if(0)
-				print("flash: found config %8.8lux(%d):\n%s\n", val, len, val);
-		}
-	}
-	if(flash.config == nil)
-		print("flash: no config\n");
-	else
-		print("flash config %8.8lux(%d):\n%s\n", flash.config, flash.conflen, flash.config);
-	if(issqueezed(flash.exec) == Q_MAGIC){
-		print("flash: squeezed powerpc kernel installed\n");
-		return 1<<0;
-	}
-	if(GLLONG(flash.exec) == Q_MAGIC){
-		print("flash: unsqueezed powerpc kernel installed\n");
-		return 1<<0;
-	}
-	flash.exec = 0;
-	print("flash: no powerpc kernel in Flash\n");
-	return 0;
-}
-
-char*
-flashconfig(int)
-{
-	return flash.config;
-}
-
-int
-flashbootable(int)
-{
-	return flash.exec != nil && (issqueezed(flash.exec) || GLLONG(flash.exec) == Q_MAGIC);
-}
-
-int
-flashboot(int)
-{
-	ulong entry, addr;
-	void (*b)(void);
-	Exec *ep;
-	Block in;
-	long n;
-	uchar *p;
-
-	if(flash.exec == 0)
-		return -1;
-	p = flash.exec;
-	if(GLLONG(p) == Q_MAGIC){
-		/* unsqueezed: copy data and perhaps text, then jump to it */
-		ep = (Exec*)p;
-		entry = PADDR(GLLONG(ep->entry));
-		p += sizeof(Exec);
-		addr = entry;
-		n = GLLONG(ep->text);
-		if(addr != (ulong)p){
-			memmove((void*)addr, p, n);
-			print("text: %8.8lux <- %8.8lux [%ld]\n", addr, p, n);
-		}
-		p += n;
-		if(entry >= FLASHMEM)
-			addr = 3*BY2PG;	/* kernel text is in Flash, data in RAM */
-		else
-			addr = PGROUND(addr+n);
-		n = GLLONG(ep->data);
-		memmove((void*)addr, p, n);
-		print("data: %8.8lux <- %8.8lux [%ld]\n", addr, p, n);
-	}else{
-		in.data = p;
-		in.rp = in.data;
-		in.lim = p+BOOTLEN;
-		in.wp = in.lim;
-		n = unsqueezef(&in, &entry);
-		if(n < 0)
-			return -1;
-	}
-	print("entry=0x%lux\n", entry);
-	uartwait();
-	scc2stop();
-	/*
-	 *  Go to new code. It's up to the program to get its PC relocated to
-	 *  the right place.
-	 */
-	b = (void (*)(void))KADDR(PADDR(entry));
-	(*b)();
-	return -1;
-}
--- a/os/boot/mpc/fns.h
+++ /dev/null
@@ -1,117 +1,0 @@
-Alarm*	alarm(int, void (*)(Alarm*), void*);
-void	alarminit(void);
-void	archbacklight(int);
-char*	archconfig(void);
-void	archdisableuart(int);
-void	archenableuart(int, int);
-void	archenableusb(int);
-void	archetherdisable(int);
-int	archetherenable(int, int*, int*);
-int	archflashreset(char*, void**, long*);
-void	archinit(void);
-int	archoptionsw(void);
-int	bootp(int, char*);
-void	cancel(Alarm*);
-void	checkalarms(void);
-void	clockinit(void);
-void	clockintr(Ureg*, void*);
-void	consinit(void);
-void	cpminit(void);
-void	cpuidprint(void);
-#define	dcflush(a,b)
-void	delay(int);
-void	eieio(void);
-uchar*	etheraddr(int);
-int	etherinit(void);
-int	etherrxpkt(int, Etherpkt*, int);
-int	ethertxpkt(int, Etherpkt*, int, int);
-void	exception(void);
-int	flashboot(int);
-int	flashbootable(int);
-char*	flashconfig(int);
-int	flashinit(void);
-void	free(void*);
-void	freeb(Block*);
-int	getcfields(char*, char**, int, char*);
-char*	getconf(char*);
-ulong	getdec(void);
-ulong	gethid0(void);
-ulong	getimmr(void);
-ulong	getmsr(void);
-ulong	getpvr(void);
-int	getstr(char*, char*, int, char*);
-ulong	gettbl(void);
-ulong	gettbu(void);
-int	hardinit(void);
-long	hardread(int, void*, long);
-long	hardseek(int, long);
-long	hardwrite(int, void*, long);
-long	i2csend(int, void*, long);
-void	i2csetup(void);
-void*	ialloc(ulong, int);
-Block*	iallocb(int);
-void	idle(void);
-int	isaconfig(char*, int, ISAConf*);
-int	issqueezed(uchar*);
-void	kbdchar(Queue*, int);
-void	kbdinit(void);
-void	kbdreset(void);
-void	machinit(void);
-void*	malloc(ulong);
-ulong	mapalloc(RMap*, ulong, int, int);
-void	mapfree(RMap*, ulong, int);
-void	mapinit(RMap*, Map*, int);
-void	meminit(void);
-void	microdelay(int);
-void	mmuinit(void);
-int	optionsw(void);
-void	panic(char*, ...);
-int	parseether(uchar*, char*);
-int	plan9boot(int, long (*)(int, long), long (*)(int, void*, long));
-void	putdec(ulong);
-void	puthid0(ulong);
-void	putmsr(ulong);
-int	qbgetc(Queue*);
-void	qbputc(Queue*, int);
-void	qbwrite(Queue*, Block*);
-Block*	qget(Queue*);
-long	qlen(Queue*);
-Queue*	qopen(int, int, void (*)(void*), void*);
-#define	qpass	qbwrite
-void	scc2stop(void);
-void	sccnmsi(int, int, int);
-void	sched(void);
-void	screeninit(void);
-void	screenputs(char*, int);
-void	sdraminit(ulong);
-Partition*	sethardpart(int, char*);
-Partition*	setscsipart(int, char*);
-void	setvec(int, void (*)(Ureg*, void*), void*);
-int	splhi(void);
-int	spllo(void);
-void	splx(int);
-void	trapinit(void);
-void	uartputs(char*, int);
-void	uartsetboot(void (*f)(uchar*, int));
-void	uartspecial(int, int, Queue**, Queue**, void(*)(Queue*,int));
-void	uartwait(void);
-long	unsqueezef(Block*, ulong*);
-
-#define	GSHORT(p)	(((p)[1]<<8)|(p)[0])
-#define	GLONG(p)	((GSHORT(p+2)<<16)|GSHORT(p))
-#define	GLSHORT(p)	(((p)[0]<<8)|(p)[1])
-#define	GLLONG(p)	((GLSHORT(p)<<16)|GLSHORT(p+2))
-
-#define KADDR(a)	((void*)((ulong)(a)|KZERO))
-#define PADDR(a)	((ulong)(a)&~KSEGM)
-
-/* IBM bit field order */
-#define	IBIT(b)	((ulong)1<<(31-(b)))
-#define	SIBIT(n)	((ushort)1<<(15-(n)))
-
-#define IOREGS(x, T)	((T*)((char*)m->iomem+(x)))
-
-int	uartinit(void);
-Partition*	setuartpart(int, char*);
-long	uartread(int, void*, long);
-long	uartseek(int, long);
--- a/os/boot/mpc/gbitbltclip.c
+++ /dev/null
@@ -1,52 +1,0 @@
-#include <u.h>
-#include <libc.h>
-#include <libg.h>
-#include <gnot.h>
-
-void
-gbitbltclip(void *vp)
-{
-	int dx, dy;
-	int i;
-	struct{
-		GBitmap *dm;
-		Point p;
-		GBitmap *sm;
-		Rectangle r;
-		Fcode f;
-	}*bp;
-
-	bp = vp;
-	dx = Dx(bp->r);
-	dy = Dy(bp->r);
-	if(bp->p.x < bp->dm->clipr.min.x){
-		i = bp->dm->clipr.min.x-bp->p.x;
-		bp->r.min.x += i;
-		bp->p.x += i;
-		dx -= i;
-	}
-	if(bp->p.y < bp->dm->clipr.min.y){
-		i = bp->dm->clipr.min.y-bp->p.y;
-		bp->r.min.y += i;
-		bp->p.y += i;
-		dy -= i;
-	}
-	if(bp->p.x+dx > bp->dm->clipr.max.x)
-		bp->r.max.x -= bp->p.x+dx-bp->dm->clipr.max.x;
-	if(bp->p.y+dy > bp->dm->clipr.max.y)
-		bp->r.max.y -= bp->p.y+dy-bp->dm->clipr.max.y;
-	if(bp->r.min.x < bp->sm->clipr.min.x){
-		i = bp->sm->clipr.min.x-bp->r.min.x;
-		bp->p.x += i;
-		bp->r.min.x += i;
-	}
-	if(bp->r.min.y < bp->sm->clipr.min.y){
-		i = bp->sm->clipr.min.y-bp->r.min.y;
-		bp->p.y += i;
-		bp->r.min.y += i;
-	}
-	if(bp->r.max.x > bp->sm->clipr.max.x)
-		bp->r.max.x = bp->sm->clipr.max.x;
-	if(bp->r.max.y > bp->sm->clipr.max.y)
-		bp->r.max.y = bp->sm->clipr.max.y;
-}
--- a/os/boot/mpc/gnot.h
+++ /dev/null
@@ -1,71 +1,0 @@
-
-extern void	*bbmalloc(int);
-extern void	bbfree(void *, int);
-extern int	bbonstack(void);
-extern void	bbexec(void(*)(void), int, int);
-
-/*
- * Graphics types
- */
-
-typedef	struct	GBitmap		GBitmap;
-typedef struct	GFont		GFont;
-typedef struct	GSubfont	GSubfont;
-typedef struct	GCacheinfo	GCacheinfo;
-
-struct	GBitmap
-{
-	ulong	*base;		/* pointer to start of data */
-	long	zero;		/* base+zero=&word containing (0,0) */
-	ulong	width;		/* width in 32 bit words of total data area */
-	int	ldepth;		/* log base 2 of number of bits per pixel */
-	Rectangle r;		/* rectangle in data area, local coords */
-	Rectangle clipr;	/* clipping region */
-	GBitmap	*cache;		/* zero; distinguishes bitmap from layer */
-};
-
-
-/*
- * GFont etc. are not used in the library, only in devbit.c.
- * GSubfont is only barely used.
- */
-struct	GSubfont
-{
-	short	n;		/* number of chars in font */
-	char	height;		/* height of bitmap */
-	char	ascent;		/* top of bitmap to baseline */
-	Fontchar *info;		/* n+1 character descriptors */
-	GBitmap	*bits;		/* where the characters are */
-};
-struct GCacheinfo
-{
-	ulong		xright;	/* right edge of bits */
-	Fontchar;
-};
-
-struct GFont
-{
-	uchar		height;	/* max height of bitmap, interline spacing */
-	char		ascent;	/* top of bitmap to baseline */
-	char		width;	/* widest so far; used in caching only */	
-	char		ldepth;	/* of images */
-	short		id;	/* of font */
-	int		ncache;	/* number of entries in cache */
-	GCacheinfo	*cache;	/* cached characters */
-	GBitmap		*b;	/* cached images */
-};
-
-extern ulong	 *gaddr(GBitmap*, Point);
-extern uchar	 *gbaddr(GBitmap*, Point);
-extern void	 gbitblt(GBitmap*, Point, GBitmap*, Rectangle, Fcode);
-extern void	 gbitbltclip(void*);
-extern void	 gtexture(GBitmap*, Rectangle, GBitmap*, Fcode);
-extern Point	 gsubfstrsize(GSubfont*, char*);
-extern int	 gsubfstrwidth(GSubfont*, char*);
-extern Point	 gsubfstring(GBitmap*, Point, GSubfont*, char*, Fcode);
-extern Point	 gbitbltstring(GBitmap*, Point, GSubfont*, char*, Fcode);
-extern void	 gsegment(GBitmap*, Point, Point, int, Fcode);
-extern void	 gpoint(GBitmap*, Point, int, Fcode);
-extern void	 gflushcpucache(void);
-extern GBitmap*	 gballoc(Rectangle, int);
-extern void	 gbfree(GBitmap*);
--- a/os/boot/mpc/i2c.c
+++ /dev/null
@@ -1,351 +1,0 @@
-#include "boot.h"
-
-/*
- * basic read/write interface to mpc8xx I2C bus (master mode)
- */
-
-typedef struct I2C I2C;
-
-struct I2C {
-	uchar	i2mod;
-	uchar	rsv12a[3];
-	uchar	i2add;
-	uchar	rsv12b[3];
-	uchar	i2brg;
-	uchar	rsv12c[3];
-	uchar	i2com;
-	uchar	rsv12d[3];
-	uchar	i2cer;
-	uchar	rsv12e[3];
-	uchar	i2cmr;
-};
-
-enum {
-	/* i2c-specific BD flags */
-	RxeOV=		1<<1,	/* overrun */
-	TxS=			1<<10,	/* transmit start condition */
-	TxeNAK=		1<<2,	/* last transmitted byte not acknowledged */
-	TxeUN=		1<<1,	/* underflow */
-	TxeCL=		1<<0,	/* collision */
-	TxERR=		(TxeNAK|TxeUN|TxeCL),
-
-	/* i2cmod */
-	REVD=	1<<5,	/* =1, LSB first */
-	GCD=	1<<4,	/* =1, general call address disabled */
-	FLT=		1<<3,	/* =0, not filtered; =1, filtered */
-	PDIV=	3<<1,	/* predivisor field */
-	EN=		1<<0,	/* enable */
-
-	/* i2com */
-	STR=		1<<7,	/* start transmit */
-	I2CM=	1<<0,	/* master */
-	I2CS=	0<<0,	/* slave */
-
-	/* i2cer */
-	TXE =	1<<4,
-	BSY =	1<<2,
-	TXB =	1<<1,
-	RXB =	1<<0,
-
-	/* port B bits */
-	I2CSDA =	IBIT(27),
-	I2CSCL = IBIT(26),
-
-	Rbit =	1<<0,	/* bit in address byte denoting read */
-
-	/* maximum I2C I/O (can change) */
-	Bufsize =	64,
-	Tbuflen=	Bufsize+4,	/* extra address bytes and alignment */
-	Freq =	100000,
-	I2CTimeout = 250,	/* msec */
-};
-
-/* data cache needn't be flushed if buffers allocated in uncached INTMEM */
-#define	DCFLUSH(a,n)
-
-/*
- * I2C software structures
- */
-
-struct Ctlr {
-	Lock;
-	QLock	io;
-	int	init;
-	I2C*	i2c;
-	IOCparam*	sp;
-
-	BD*	rd;
-	BD*	td;
-	int	phase;
-	char*	addr;
-	char*	txbuf;
-	char*	rxbuf;
-};
-typedef struct Ctlr Ctlr;
-
-static	Ctlr	i2ctlr[1];
-extern	int	predawn;
-
-static	void	interrupt(Ureg*, void*);
-
-static void
-enable(void)
-{
-	I2C *i2c;
-
-	i2c = i2ctlr->i2c;
-	i2c->i2cer = ~0;	/* clear events */
-	eieio();
-	i2c->i2mod |= EN;
-	eieio();
-	i2c->i2cmr = TXE|BSY|TXB|RXB;	/* enable all interrupts */
-	eieio();
-}
-
-static void
-disable(void)
-{
-	I2C *i2c;
-
-	i2c = i2ctlr->i2c;
-	i2c->i2cmr = 0;	/* mask all interrupts */
-	i2c->i2mod &= ~EN;
-}
-
-/*
- * called by the reset routine of any driver using the I2C
- */
-void
-i2csetup(void)
-{
-	IMM *io;
-	I2C *i2c;
-	IOCparam *sp;
-	Ctlr *ctlr;
-	long f, e, emin;
-	int p, d, dmax;
-
-	ctlr = i2ctlr;
-	if(ctlr->init)
-		return;
-	print("i2c setup...\n");
-	ctlr->init = 1;
-	i2c = KADDR(INTMEM+0x860);
-	ctlr->i2c = i2c;
-	sp = KADDR(INTMEM+0x3c80);
-	ctlr->sp = sp;
-	disable();
-
-	if(ctlr->txbuf == nil){
-		ctlr->txbuf = ialloc(Tbuflen, 2);
-		ctlr->addr = ctlr->txbuf+Bufsize;
-	}
-	if(ctlr->rxbuf == nil)
-		ctlr->rxbuf = ialloc(Bufsize, 2);
-	if(ctlr->rd == nil){
-		ctlr->rd = bdalloc(1);
-		ctlr->rd->addr = PADDR(ctlr->rxbuf);
-		ctlr->rd->length = 0;
-		ctlr->rd->status = BDWrap;
-	}
-	if(ctlr->td == nil){
-		ctlr->td = bdalloc(2);
-		ctlr->td->addr = PADDR(ctlr->txbuf);
-		ctlr->td->length = 0;
-		ctlr->td->status = BDWrap|BDLast;
-	}
-
-	/* select port pins */
-	io = ioplock();
-	io->pbdir |= I2CSDA | I2CSCL;
-	io->pbodr |= I2CSDA | I2CSCL;
-	io->pbpar |= I2CSDA | I2CSCL;
-	iopunlock();
-
-	/* explicitly initialise parameters, because InitRxTx can't be used (see i2c/spi relocation errata) */
-	sp = ctlr->sp;
-	sp->rbase = PADDR(ctlr->rd);
-	sp->tbase = PADDR(ctlr->td);
-	sp->rfcr = 0x18;
-	sp->tfcr = 0x18;
-	sp->mrblr = Bufsize;
-	sp->rstate = 0;
-	sp->rptr = 0;
-	sp->rbptr = sp->rbase;
-	sp->rcnt = 0;
-	sp->tstate = 0;
-	sp->tbptr = sp->tbase;
-	sp->tptr = 0;
-	sp->tcnt = 0;
-	eieio();
-
-	i2c->i2com = I2CM;
-	i2c->i2mod = 0;	/* normal mode */
-	i2c->i2add = 0;
-
-	emin = Freq;
-	dmax = (m->cpuhz/Freq)/2-3;
-	for(d=0; d < dmax; d++){
-		for(p=3; p>=0; p--){
-			f = (m->cpuhz>>(p+2))/(2*(d+3));
-			e = Freq - f;
-			if(e < 0)
-				e = -e;
-			if(e < emin){
-				emin = e;
-				i2c->i2brg = d;
-				i2c->i2mod = (i2c->i2mod&~PDIV)|((3-p)<<1); /* set PDIV */
-			}
-		}
-	}
-	//print("i2brg=%d i2mod=#%2.2ux\n", i2c->i2brg, i2c->i2mod);
-	setvec(VectorCPIC+0x10, interrupt, i2ctlr);
-}
-
-enum {
-	Idling,
-	Done,
-	Busy,
-		Sending,
-		Recving,
-};
-
-static void
-interrupt(Ureg*, void *arg)
-{
-	int events;
-	Ctlr *ctlr;
-	I2C *i2c;
-
-	ctlr = arg;
-	i2c = ctlr->i2c;
-	events = i2c->i2cer;
-	eieio();
-	i2c->i2cer = events;
-	if(events & (BSY|TXE)){
-		//print("I2C#%x\n", events);
-		if(ctlr->phase != Idling){
-			ctlr->phase = Idling;
-		}
-	}else{
-		if(events & TXB){
-			//print("i2c: xmt %d %4.4ux %4.4ux\n", ctlr->phase, ctlr->td->status, ctlr->td[1].status);
-			if(ctlr->phase == Sending){
-				ctlr->phase = Done;
-			}
-		}
-		if(events & RXB){
-			//print("i2c: rcv %d %4.4ux %d\n", ctlr->phase, ctlr->rd->status, ctlr->rd->length);
-			if(ctlr->phase == Recving){
-				ctlr->phase = Done;
-			}
-		}
-	}
-}
-
-static int
-done(void *a)
-{
-	return ((Ctlr*)a)->phase < Busy;
-}
-
-static void
-i2cwait(Ctlr *ctlr)
-{
-	/* TO DO: timeout */
-	while(!done(ctlr)){
-		if(predawn)
-			interrupt(nil, ctlr);
-	}
-}
-
-long
-i2csend(int addr, void *buf, long n)
-{
-	Ctlr *ctlr;
-	int i, p, s;
-
-	ctlr = i2ctlr;
-	if(n > Bufsize)
-		return -1;
-	i = 1;
-	ctlr->txbuf[0] = addr & ~1;
-	if(addr & 1){
-		ctlr->txbuf[1] = addr>>8;
-		i++;
-	}
-	memmove(ctlr->txbuf+i, buf, n);
-	DCFLUSH(ctlr->txbuf, Tbuflen);
-	ctlr->phase = Sending;
-	ctlr->rd->status = BDEmpty|BDWrap|BDInt;
-	ctlr->td->addr = PADDR(ctlr->txbuf);
-	ctlr->td->length = n+i;
-	ctlr->td->status = BDReady|BDWrap|BDLast|BDInt;
-	enable();
-	ctlr->i2c->i2com = STR|I2CM;
-	eieio();
-	i2cwait(ctlr);
-	disable();
-	p = ctlr->phase;
-	s = ctlr->td->status;
-	if(s & BDReady || s & TxERR || p != Done)
-		return -1;
-	return n;
-}
-
-long
-i2crecv(int addr, void *buf, long n)
-{
-	Ctlr *ctlr;
-	int p, s, flag;
-	BD *td;
-	long nr;
-
-	ctlr = i2ctlr;
-	if(n > Bufsize)
-		return -1;
-	ctlr->txbuf[0] = addr|Rbit;
-	if(addr & 1){	/* special select sequence */
-		ctlr->addr[0] = addr &~ 1;
-		ctlr->addr[1] = addr>>8;
-	}
-	DCFLUSH(ctlr->txbuf, Tbuflen);
-	DCFLUSH(ctlr->rxbuf, Bufsize);
-	ctlr->phase = Recving;
-	ctlr->rd->addr = PADDR(ctlr->rxbuf);
-	ctlr->rd->status = BDEmpty|BDWrap|BDInt;
-	flag = 0;
-	td = ctlr->td;
-	td[1].status = 0;
-	if(addr & 1){
-		/* special select sequence */
-		td->addr = PADDR(ctlr->addr);
-		td->length = 2;
-		/* td->status made BDReady below */
-		td++;
-		flag = TxS;
-	}
-	td->addr = PADDR(ctlr->txbuf);
-	td->length = n+1;
-	td->status = BDReady|BDWrap|BDLast | flag;	/* not BDInt: leave that to receive */
-	if(flag)
-		ctlr->td->status = BDReady;
-	enable();
-	ctlr->i2c->i2com = STR|I2CM;
-	eieio();
-	i2cwait(ctlr);
-	disable();
-	p = ctlr->phase;
-	s = ctlr->td->status;
-	if(flag)
-		s |= ctlr->td[1].status;
-	nr = ctlr->rd->length;
-	if(nr > n)
-		nr = n;	/* shouldn't happen */
-	if(s & TxERR || s & BDReady || ctlr->rd->status & BDEmpty)
-		return -1;
-	if(p != Done)
-		return -1;
-	memmove(buf, ctlr->rxbuf, nr);
-	return nr;
-}
--- a/os/boot/mpc/initfads.c
+++ /dev/null
@@ -1,187 +1,0 @@
-/*
- * Called from l.s in EPROM to set up a minimal working environment.
- * Since there is no DRAM yet, and therefore no stack, no function
- * calls may be made from sysinit0, and values can't be stored,
- * except to INTMEM.  Global values are accessed by offset from SB,
- * which has been set by l.s to point into EPROM.
- *
- * This is FADS-specific in CS assignment and access of the FADS BCSR
- * to discover memory size and speed.
- */
-
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-#include "archfads.h"
-
-#define	MB	(1024*1024)
-
-enum {
-	UPMSIZE = 64,	/* memory controller instruction RAM */
-	SPEED = 50,	/* maximum memory clock in MHz */
-	SDRAMSIZE = 4*MB,
-
-	/* mcr */
-	WriteRAM = 0<<30,
-	ReadRAM = 1<<30,
-	ExecRAM = 2<<30,
-
-	SelUPMA = 0<<23,
-	SelUPMB = 1<<23,
-
-	Once = 1<<8,
-};
-
-/*
- * mpc8bug uses the following for 60ns EDO DRAMs 32-50MHz
- */
-static ulong upma50[UPMSIZE] = {
-	0x8FFFEC24,	0xFFFEC04,	0xCFFEC04,	0xFFEC04,       
-	0xFFEC00,	0x37FFEC47,	0xFFFFFFFF,	0xFFFFFFFF,
-	0x8FFFEC24,	0xFFFEC04,	0x8FFEC04,	0xFFEC0C,
-	0x3FFEC00,	0xFFEC44,	0xFFCC08,	0xCFFCC44,
-	0xFFEC0C,	0x3FFEC00,	0xFFEC44,	0xFFCC00,
-	0x3FFFC847,	0x3FFFEC47,	0xFFFFFFFF,	0xFFFFFFFF,
-	0x8FAFCC24,	0xFAFCC04,	0xCAFCC00,	0x11BFCC47,
-	0xC0FFCC84,	0xFFFFFFFF,	0xFFFFFFFF,	0xFFFFFFFF,
-	0x8FAFCC24,	0xFAFCC04,	0xCAFCC00,	0x3AFCC4C,
-	0xCAFCC00,	0x3AFCC4C,	0xCAFCC00,	0x3AFCC4C,
-	0xCAFCC00,	0x33BFCC4F,	0xFFFFFFFF,	0xFFFFFFFF,
-	0xFFFFFFFF,	0xFFFFFFFF,	0xFFFFFFFF,	0xFFFFFFFF,
-	0xC0FFCC84,	0xFFCC04,	0x7FFCC04,	0x3FFFCC06,
-	0xFFFFCC85,	0xFFFFCC05,	0xFFFFCC05,	0xFFFFFFFF,
-	0xFFFFFFFF,	0xFFFFFFFF,	0xFFFFFFFF,	0xFFFFFFFF,
-	0x33FFCC07,	0xFFFFFFFF,	0xFFFFFFFF,	0xFFFFFFFF,
-};
-
-/*
- * the FADS manual table 3-7 suggests the following for 60ns EDO DRAMs at 20MHz
- */
-static ulong upma20[UPMSIZE] = {
-	0x8FFFCC04, 0x08FFCC00, 0x33FFCC47, ~0, ~0, ~0, ~0, ~0,
-	[0x08]	0x8FFFCC04, 0x08FFCC08, 0x08FFCC08, 0x08FFCC08, 0x08FFCC00, 0x3FFFCC47, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0,
-	[0x18]	0x8FEFCC00, 0x39BFCC47, ~0, ~0, ~0, ~0, ~0, ~0,
-	[0x20]	0x8FEFCC00, 0x09AFCC48, 0x09AFCC48, 0x08AFCC48, 0x39BFCC47, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0,
-	[0x30]	0x80FFCC84, 0x17FFCC04, 0xFFFFCC86, 0xFFFFCC05, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0,
-	[0x3C]	0x33FFCC07, ~0, ~0, ~0,
-};
-
-void
-sysinit0(int inrom)
-{
-	ulong *upm, *bcsr;
-	IMM *io;
-	int i, mb;
-
-	io = (IMM*)INTMEM;		/* running before maps, no KADDR */
-
-	/* system interface unit initialisation, FADS manual table 3-2, except as noted */
-	io->siumcr = 0x01012440;
-	io->sypcr = 0xFFFFFF88;
-	io->tbscrk = KEEP_ALIVE_KEY;
-	io->tbscr = 0xC3;	/* time base enabled */
-	io->rtcsck = KEEP_ALIVE_KEY;
-	io->rtcsc = 0xC1;	/* don't FRZ, real-time clock enabled */
-	io->rtcsck = ~KEEP_ALIVE_KEY;
-	io->piscrk = KEEP_ALIVE_KEY;
-	io->piscr = 0x82;
-
-	io->memc[BCSRCS].option = 0xFFFF8110;	/* 32k block, all types access, CS early negate, 1 ws */
-	io->memc[BCSRCS].base = BCSRMEM | 1;	/* base, 32-bit port, no parity, GPCM */
-
-	io->memc[BOOTCS].base = FLASHMEM | 1;
-	io->memc[BOOTCS].option = 0xFF800D54;
-
-	if(!inrom)
-		return;	/* can't initialise DRAM controller from DRAM */
-
-	bcsr = (ulong*)BCSRMEM;
-//	bcsr[1] &= ~DisableDRAM;
-	/* could check DRAM speed here; assume 60ns */
-	switch((bcsr[2]>>23)&3){
-	default:	return;	/* can't happen; for the compiler */
-	case 0:	mb = 4; break;
-	case 1:	mb = 32; break;
-	case 2:	mb = 16; break;
-	case 3:	mb = 8; break;
-	}
-
-	upm = upma50;
-	for(i=0; i<UPMSIZE; i++){
-		io->mdr = upm[i];
-		io->mcr = WriteRAM | SelUPMA | i;
-	}
-	io->mptpr = 0x0400;
-	if(SPEED >= 32)
-		io->mamr = (0x9C<<24) | 0xA21114;	/* 50MHz BRGCLK; FADS manual says 0xC0, mpc8bug sets 0x9C */
-	else if(SPEED >= 20)
-		io->mamr = (0x60<<24) | 0xA21114;	/* 25MHz BRGCLK */
-	else
-		io->mamr = (0x40<<24) | 0xA21114;	/* 16.67MHz BRGCLK */
-	io->memc[DRAM1].option = ~((mb<<20)-1)|0x0800;	/* address mask, SAM=1 */
-	io->memc[DRAM1].base = 0 | 0x81;	/* base at 0, 32-bit port size, no parity, UPMA */
-}
-
-/*
- * the FADS manual table 3-9's suggestion for MB811171622A-100 32+MHz-50MHz
- */
-static ulong upmb50[UPMSIZE] = {
-	[0x00]	0x1F07FC04, 0xEEAEFC04, 0x11ADFC04, 0xEFBBBC00, 0x1FF77C47,
-	[0x05]	0x1FF77C34, 0xEFEABC34, 0x1FB57C35,
-	[0x08]	0x1F07FC04, 0xEEAEFC04, 0x10ADFC04, 0xF0AFFC00, 0xF0AFFC00, 0xF1AFFC00, 0xEFBBBC00, 0x1FF77C47, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0,
-	[0x18]	0x1F27FC04, 0xEEAEBC00, 0x01B93C04, 0x1FF77C47, ~0, ~0, ~0, ~0,
-	[0x20]	0x1F07FC04, 0xEEAEBC00, 0x10AD7C00, 0xF0AFFC00, 0xF0AFFC00, 0xE1BBBC04, 0x1FF77C47, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0,
-	[0x30] 	0x1FF5FC84, 0xFFFFFC04, 0xFFFFFC04, 0xFFFFFC04, 0xFFFFFC84, 0xFFFFFC07, ~0, ~0, ~0, ~0, ~0, ~0,
-	[0x3C]	0x7FFFFC07, ~0, ~0, ~0,
-};
-
-/*
- * the FADS manual table 3-8's suggestion for MB811171622A-100 up to 32MHz
- */
-static	ulong	upmb32[UPMSIZE] = {
-	[0x00]	0x126CC04, 0xFB98C00, 0x1FF74C45, ~0, ~0,
-	[0x05]	0x1FE77C34, 0xEFAABC34, 0x1FA57C35,
-	[0x08]	0x0026FC04, 0x10ADFC00, 0xF0AFFC00, 0xF1AFFC00, 0xEFBBBC00, 0x1FF77C45, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0,
-	[0x18]	0x0E26BC04, 0x01B93C00, 0x1FF77C45, ~0, ~0, ~0, ~0, ~0,
-	[0x20]	0x0E26BC00, 0x10AD7C00, 0xF0AFFC00, 0xF0AFFC00, 0xE1BBBC04, 0x1FF77C45, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0,
-	[0x30]	0x1FF5FC84, 0xFFFFFC04, 0xFFFFFC84, 0xFFFFFC05, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0,
-	[0x3C]	0x7FFFFC07, ~0, ~0, ~0,
-};
-
-/*
- * optionally called by archfads.c:/^archinit to initialise access to SDRAM
- */
-void
-sdraminit(ulong base)
-{
-	ulong *upm;
-	IMM *io;
-	int i;
-
-	io = (IMM*)INTMEM;		/* running before maps, no KADDR */
-	if(SPEED > 32)
-		upm = upmb50;
-	else
-		upm = upmb32;
-	for(i=0; i<UPMSIZE; i++){
-		io->mdr = upm[i];
-		io->mcr = WriteRAM | SelUPMB | i;
-	}
-	io->memc[SDRAM].option = ~(SDRAMSIZE-1)|0x0A00;	/* address mask, SAM=1, G5LS=1 */
-	io->memc[SDRAM].base = base | 0xC1;
-	if(SPEED > 32){
-		io->mbmr = 0xD0802114;	/* 50MHz BRGCLK */
-		io->mar = 0x88;
-	}else{
-		io->mbmr = 0x80802114;	/* 32MHz BRGCLK */
-		io->mar = 0x48;
-	}
-	io->mcr = ExecRAM | SelUPMB | (SDRAM<<13) | Once | 5;	/* run MRS command in locations 5-8 of UPMB */
-	io->mbmr = (io->mbmr & ~0xF) | 8;
-	io->mcr = ExecRAM | SelUPMB | (SDRAM<<13) | Once | 0x30;	/* run refresh sequence */
-	io->mbmr = (io->mbmr & ~0xF) | 4;	/* 4-beat refresh bursts */
-}
--- a/os/boot/mpc/initpaq.c
+++ /dev/null
@@ -1,101 +1,0 @@
-/*
- * Called from l.s in EPROM to set up a minimal working environment.
- * Since there is no DRAM yet, and therefore no stack, no function
- * calls may be made from sysinit0, and values can't be stored,
- * except to INTMEM.  Global values are accessed by offset from SB,
- * which has been set by l.s to point into EPROM.
- *
- * This is PowerPAQ-specific:
- *	- assumes 8mbytes
- *	- powerpaq CS assignment
- */
-
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-#include "archpaq.h"
-
-#define	MB	(1024*1024)
-
-enum {
-	DRAMSIZE = 8*MB,
-	FLASHSIZE = 8*MB,
-
-	UPMSIZE = 64,	/* memory controller instruction RAM */
-	SPEED = 50,	/* maximum memory clock in MHz */
-
-	/* mcr */
-	WriteRAM = 0<<30,
-	ReadRAM = 1<<30,
-	ExecRAM = 2<<30,
-
-	SelUPMA = 0<<23,
-	SelUPMB = 1<<23,
-
-	Once = 1<<8,
-};
-
-/*
- * mpc8bug uses the following for 60ns EDO DRAMs 32-50MHz
- */
-static ulong upmb50[UPMSIZE] = {
-	0x8FFFEC24,	0xFFFEC04,	0xCFFEC04,	0xFFEC04,       
-	0xFFEC00,	0x37FFEC47,	0xFFFFFFFF,	0xFFFFFFFF,
-	0x8FFFEC24,	0xFFFEC04,	0x8FFEC04,	0xFFEC0C,
-	0x3FFEC00,	0xFFEC44,	0xFFCC08,	0xCFFCC44,
-	0xFFEC0C,	0x3FFEC00,	0xFFEC44,	0xFFCC00,
-	0x3FFFC847,	0x3FFFEC47,	0xFFFFFFFF,	0xFFFFFFFF,
-	0x8FAFCC24,	0xFAFCC04,	0xCAFCC00,	0x11BFCC47,
-	0xC0FFCC84,	0xFFFFFFFF,	0xFFFFFFFF,	0xFFFFFFFF,
-	0x8FAFCC24,	0xFAFCC04,	0xCAFCC00,	0x3AFCC4C,
-	0xCAFCC00,	0x3AFCC4C,	0xCAFCC00,	0x3AFCC4C,
-	0xCAFCC00,	0x33BFCC4F,	0xFFFFFFFF,	0xFFFFFFFF,
-	0xFFFFFFFF,	0xFFFFFFFF,	0xFFFFFFFF,	0xFFFFFFFF,
-	0xC0FFCC84,	0xFFCC04,	0x7FFCC04,	0x3FFFCC06,
-	0xFFFFCC85,	0xFFFFCC05,	0xFFFFCC05,	0xFFFFFFFF,
-	0xFFFFFFFF,	0xFFFFFFFF,	0xFFFFFFFF,	0xFFFFFFFF,
-	0x33FFCC07,	0xFFFFFFFF,	0xFFFFFFFF,	0xFFFFFFFF,
-};
-
-void
-sysinit0(int inrom)
-{
-	ulong *upm;
-	IMM *io;
-	int i;
-
-	io = (IMM*)INTMEM;		/* running before maps, no KADDR */
-
-	/* system interface unit initialisation, FADS manual table 3-2, except as noted */
-	io->siumcr = 0x01012440;
-	io->sypcr = 0xFFFFFF88;
-	io->tbscrk = KEEP_ALIVE_KEY;
-	io->tbscr = 0xC3;	/* time base enabled */
-	io->rtcsck = KEEP_ALIVE_KEY;
-	io->rtcsc = 0xC1;	/* don't FRZ, real-time clock enabled */
-	io->rtcsck = ~KEEP_ALIVE_KEY;
-	io->piscrk = KEEP_ALIVE_KEY;
-	io->piscr = 0x82;
-
-	io->memc[BOOTCS].base = FLASHMEM | 1;
-	io->memc[BOOTCS].option = ~(FLASHSIZE-1)|(1<<8)|(2<<4);	/* mask, BIH, 2 wait states */
-
-	if(!inrom)
-		return;	/* can't initialise DRAM controller from DRAM */
-
-	/* could check DRAM speed here; assume 60ns */
-	/* could probe DRAM for size here; assume DRAMSIZE */
-	io->mptpr = 0x400;	/* powerpaq flash has 0x1000 */
-	io->mbmr = (0xC0<<24) | 0xA21114;	/* 50MHz BRGCLK */
-	upm = upmb50;
-	for(i=0; i<UPMSIZE; i++){
-		io->mdr = upm[i];
-		io->mcr = WriteRAM | SelUPMB | i;
-	}
-	io->memc[DRAM1].option = ~(DRAMSIZE-1)|0x0800;	/* address mask, SAM=1 */
-	io->memc[DRAM1].base = 0 | 0xC1;	/* base at 0, 32-bit port size, no parity, UPMB */
-}
--- a/os/boot/mpc/initrpcg.c
+++ /dev/null
@@ -1,91 +1,0 @@
-
-/*
- * Called from l.s in EPROM to set up a minimal working environment.
- * Since there is no DRAM yet, and therefore no stack, no function
- * calls may be made from sysinit, and values can't be stored,
- * except to INTMEM.  Global values are accessed by offset from SB,
- * which has been set by l.s to point into EPROM.
- */
-
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-#include	"archrpcg.h"
-
-#define	MB	(1024*1024)
-
-enum {
-	UPMSIZE = 64,	/* memory controller instruction RAM */
-	DRAMSIZE = 16*MB,
-	FLASHSIZE = 4*MB,
-
-	WriteRAM = 0<<30,
-	ReadRAM = 1<<30,
-	ExecRAM = 2<<30,
-
-	SelUPMA = 0<<23,
-	SelUPMB = 1<<23,
-};
-/* RPCG values for RPXLite AW */
-static	ulong	upma50[UPMSIZE] = {
-	0xCFFFCC24,	0x0FFFCC04,	0x0CAFCC04,	0x03AFCC08,       
-	0x3FBFCC27,	0xFFFFCC25,	0xFFFFCC25,	0xFFFFCC25,
-	0xCFFFCC24,	0x0FFFCC04,	0x0CAFCC84,	0x03AFCC88,
-	0x3FBFCC27,	0xFFFFCC25,	0xFFFFCC25,	0xFFFFCC25,
-	0xFFFFCC25,	0xFFFFCC25,	0xFFFFCC25,	0xFFFFCC25,
-	0xFFFFCC25,	0xFFFFCC25,	0xFFFFCC25,	0xFFFFCC25,
-	0xCFFFCC24,	0x0FFFCC04,	0x0CFFCC04,	0x03FFCC00,
-	0x3FFFCC27,	0xFFFFCC25,	0xFFFFCC25,	0xFFFFCC25,
-	0xCFFFCC24,	0x0FFFCC04,	0x0CFFCC84,	0x03FFCC84,
-	0x0CFFCC00,	0x33FFCC27,	0xFFFFCC25,	0xFFFFCC25,
-	0xFFFFCC25,	0xFFFFCC25,	0xFFFFCC25,	0xFFFFCC25,
-	0xFFFFCC25,	0xFFFFCC25,	0xFFFFCC25,	0xFFFFCC25,
-	0xC0FFCC24,	0x03FFCC24,	0x0FFFCC24,	0x0FFFCC24,
-	0x3FFFCC27,	0xFFFFCC25,	0xFFFFCC25,	0xFFFFCC25,
-	0xFFFFCC25,	0xFFFFCC25,	0xFFFFCC25,	0xFFFFCC25,
-	0xFFFFCC25,	0xFFFFCC25,	0xFFFFCC25,	0xFFFFCC25,
-};
-
-void
-sysinit0(int inrom)
-{
-	ulong *upm;
-	IMM *io;
-	int i;
-
-	io = (IMM*)INTMEM;		/* running before maps, no KADDR */
-	io->siumcr = 0x01012440;
-	io->sypcr = 0xFFFFFF88;
-	io->tbscrk = KEEP_ALIVE_KEY;
-	io->tbscr = 0xC3;
-	io->rtcsck = KEEP_ALIVE_KEY;
-	io->rtcsc = 0xC1;
-	io->rtcsck = ~KEEP_ALIVE_KEY;
-	io->piscrk = KEEP_ALIVE_KEY;
-	io->piscr = 0x82;
-return;
-	io->memc[BCSRCS].option = 0xFFFF8910;	/* 32k block, all types access, CSNT, CS early negate, burst inhibit, 1 ws */
-	io->memc[BCSRCS].base = BCSRMEM | 1;	/* base, 32-bit port, no parity, GPCM */
-
-	io->memc[BOOTCS].base = FLASHMEM | 0x801; /* base, 16 bit port */
-	io->memc[BOOTCS].option = ~(FLASHSIZE-1)|(1<<8)|(4<<4);	/* mask, BIH, 4 wait states */
-
-	if(1||!inrom)
-		return;	/* can't initialise DRAM controller from DRAM */
-
-	/* TO DO: could check DRAM size and speed now */
-
-	upm = upma50;
-	for(i=0; i<nelem(upma50); i++){
-		io->mdr = upm[i];
-		io->mcr = WriteRAM | SelUPMA | i;
-	}
-	io->mptpr = 0x0800;	/* divide by 8 */
-	io->mamr = (0x58<<24) | 0xA01430;	/* 40MHz BRGCLK */
-	io->memc[DRAM1].option = ~(DRAMSIZE-1)|0x0E00;	/* address mask, SAM=1, G5LA/S=3 */
-	io->memc[DRAM1].base = 0 | 0x81;	/* base at 0, 32-bit port size, no parity, UPMA */
-}
--- a/os/boot/mpc/io.h
+++ /dev/null
@@ -1,463 +1,0 @@
-enum
-{
-	/* software interrupt vectors (SIU and CPM) */
-	VectorPIC= 0,	/* level 0 to level 7, assigned by software */
-		CPIClevel=	4,
-	VectorIRQ=	VectorPIC+8,	/* IRQ0 to IRQ7 */
-	VectorCPIC=	VectorIRQ+8,	/* 32 CPM interrupts: 0 (error) to 0x1F (PC15) */
-};
-
-enum
-{
-	BUSUNKNOWN = 0,
-};
-
-/*
- * Buffer Descriptors and IO Rings
- */
-
-typedef struct BD BD;
-struct BD {
-	ushort	status;
-	ushort	length;
-	ulong	addr;
-};
-
-BD*	bdalloc(int);
-void	bdfree(BD*, int);
-
-enum {
-	/* Rx BDs, bits common to all protocols */
-	BDEmpty=	1<<15,
-	BDWrap=		1<<13,
-	BDInt=		1<<12,
-	BDLast=		1<<11,
-	BDFirst=		1<<10,
-
-	/* Tx BDs */
-	BDReady=		1<<15,
-	/* BDWrap, BDInt, BDLast */
-};
-
-typedef struct Ring Ring;
-struct Ring {
-	BD*	rdr;				/* receive descriptor ring */
-	void*	rrb;				/* receive ring buffers */
-	int	rdrx;				/* index into rdr */
-	int	nrdre;			/* length of rdr */
-
-	BD*	tdr;				/* transmit descriptor ring */
-	Block**	txb;				/* corresponding transmit ring buffers */
-	int	tdrh;				/* host index into tdr */
-	int	tdri;				/* interface index into tdr */
-	int	ntdre;			/* length of tdr */
-	int	ntq;				/* pending transmit requests */
-};
-
-#define NEXT(x, l)	(((x)+1)%(l))
-#define PREV(x, l)	(((x) == 0) ? (l)-1: (x)-1)
-#define	HOWMANY(x, y)	(((x)+((y)-1))/(y))
-#define ROUNDUP(x, y)	(HOWMANY((x), (y))*(y))
-
-int	ioringinit(Ring*, int, int, int);
-
-/*
- * CPM
- */
-enum {
-	/* commands */
-	InitRxTx =	0,
-	InitRx =		1,
-	InitTx =		2,
-	EnterHunt=	3,
-	StopTx=		4,
-	GracefulStopTx = 5,
-	InitIDMA =	5,
-	RestartTx =	6,
-	CloseRxBD =	7,
-	SetGroupAddr = 8,
-	SetTimer =	8,
-	GCITimeout =	9,
-	GCIAbort =	10,
-	StopIDMA =	11,
-	StartDSP = 	12,
-	ArmIDMA =	13,
-	InitDSP =		13,
-	USBCmd =	15,
-
-	/* channel IDs */
-	SCC1ID=	0,
-	USBID=	0,
-	I2CID=	1,
-	IDMA1ID= 1,
-	SCC2ID=	4,
-	SPIID=	5,
-	IDMA2ID= 5,
-	TIMERID=	5,
-	SCC3ID=	8,
-	SMC1ID=	9,
-	DSP1ID=9,
-	SCC4ID=	12,
-	SMC2ID=	13,
-	DSP2ID=	13,
-
-	BaudEnable = 1<<16,
-
-	/* sicr */
-	CLK1 = 4,		/* SCC1,2 */
-	CLK2 = 5,
-	CLK3 = 6,
-	CLK4 = 7,
-	CLK5 = CLK1,	/* SCC3,4 */
-	CLK6 = CLK2,
-	CLK7 = CLK3,
-	CLK8 = CLK4,
-};
-
-void	cpmop(int, int, int);
-#define	ioplock()	(m->iomem)
-#define	iopunlock()
-
-/*
- * the structures below follow hardware/firmware layouts in the 8xx manuals:
- * mind the data types, offsets and alignment
- */
-
-/*
- * basic IO controller parameters (SMC and SCC)
- */
-typedef struct IOCparam IOCparam;
-struct IOCparam {
-	ushort	rbase;
-	ushort	tbase;
-	uchar	rfcr;
-	uchar	tfcr;
-	ushort	mrblr;
-	ulong	rstate;
-	ulong	rptr;
-	ushort	rbptr;
-	ushort	rcnt;
-	ulong	rtmp;
-	ulong	tstate;
-	ulong	tptr;
-	ushort	tbptr;
-	ushort	tcnt;
-	ulong	ttmp;
-};
-
-typedef struct SCCparam SCCparam;
-struct SCCparam {
-	IOCparam;
-	ulong	rcrc;
-	ulong	tcrc;
-};
-
-typedef struct SCC SCC;
-struct SCC {
-	ulong	gsmrl;
-	ulong	gsmrh;
-	ushort	psmr;
-	uchar	rsvscc0[2];
-	ushort	todr;
-	ushort	dsr;
-	ushort	scce;
-	uchar	rsvscc1[2];
-	ushort	sccm;
-	uchar	rsvscc3;
-	uchar	sccs;
-	ushort	irmode;
-	ushort	irsip;
-};
-
-typedef struct SMC SMC;
-struct SMC {
-	uchar	pad1[2];
-	ushort	smcmr;
-	uchar	pad2[2];
-	uchar	smce;
-	uchar	pad3[3];
-	uchar	smcm;
-	uchar	pad4[5];
-};
-
-typedef struct SPI SPI;
-struct SPI {
-	ushort	spmode;
-	uchar	res1[4];
-	uchar	spie;
-	uchar	res2[3];
-	uchar	spim;
-	uchar	res3[2];
-	uchar	spcom;
-	uchar	res4[10];
-};
-
-typedef struct USB USB;
-struct USB {	/* 823 only */
-	uchar	usmod;
-	uchar	usadr;
-	uchar	uscom;
-	uchar	rsvu1;
-	ushort	usep[4];
-	uchar	rsvu2[4];
-	ushort	usber;
-	uchar	rsvu3[2];
-	ushort	usbmr;
-	uchar	rsvu4;
-	uchar	usbs;
-	uchar	rsvu5[8];
-};
-
-typedef struct IMM IMM;
-struct IMM {
-	struct {	/* general SIU */
-		ulong	siumcr;
-		ulong	sypcr;
-		uchar	rsv0[0xE-0x8];
-		ushort	swsr;
-		ulong	sipend;
-		ulong	simask;
-		ulong	siel;
-		uchar	sivec;
-		uchar	padv[3];
-		ulong	tesr;
-		uchar	rsv1[0x30-0x24];
-		ulong	sdcr;
-		uchar	rsv2[0x80-0x34];
-	};
-	struct {	/* PCMCIA */
-		struct {
-			ulong	base;
-			ulong	option;
-		} pcmr[8];
-		uchar	rsv3[0xe0-0xc0];
-		ulong	pgcra;
-		ulong	pgcrb;
-		ulong	pscr;
-		uchar	rsv4[0xf0-0xec];
-		ulong	pipr;
-		uchar	rsv5[4];
-		ulong	per;
-		uchar	rsv6[4];
-	};
-	struct {	/* MEMC */
-		struct {
-			ulong	base;
-			ulong	option;
-		} memc[8];
-		uchar	rsv7a[0x24];
-		ulong	mar;
-		ulong	mcr;
-		uchar	rsv7b[4];
-		ulong	mamr;
-		ulong	mbmr;
-		ushort	mstat;
-		ushort	mptpr;
-		ulong	mdr;
-		uchar	rsv7c[0x80];
-	};
-	struct {	/* system integration timers */
-		ushort	tbscr;
-		uchar	rsv8a[2];
-		ulong	tbrefu;
-		ulong	tbrefl;
-		uchar	rsv8b[0x14];
-		ushort	rtcsc;
-		uchar	rsv8c[2];
-		ulong	rtc;
-		ulong	rtsec;
-		ulong	rtcal;
-		uchar	rsv8d[0x10];
-		ushort	piscr;
-		ushort	rsv8e;
-		ulong	pitc;
-		ulong	pitr;
-		uchar	rsv8f[0x34];
-	};
-	struct {	/* 280: clocks and resets */
-		ulong	sccr;
-		ulong	plprcr;
-		ulong	rsr;
-		uchar	rsv9[0x300-0x28c];
-	};
-	struct {	/* 300: system integration timers keys */
-		ulong	tbscrk;
-		ulong	tbrefuk;
-		ulong	tbreflk;
-		ulong	tbk;
-		uchar	rsv10a[0x10];
-		ulong	rtcsck;
-		ulong	rtck;
-		ulong	rtseck;
-		ulong	rtcalk;
-		uchar	rsv10b[0x10];
-		ulong	piscrk;
-		ulong	pitck;
-		uchar	rsv10c[0x38];
-	};
-	struct {	/* 380: clocks and resets keys */
-		ulong	sccrk;
-		ulong	plprcrk;
-		ulong	rsrk;
-		uchar	rsv11[0x800-0x38C];
-	};
-	struct {	/* 800: video controller */
-		ushort	vccr;
-		ushort	pad11a;
-		uchar	vsr;
-		uchar	pad11b;
-		uchar	vcmr;
-		uchar	pad11c;
-		ulong	vbcb;
-		ulong	pad11d;
-		ulong	vfcr0;
-		ulong	vfaa0;
-		ulong	vfba0;
-		ulong	vfcr1;
-		ulong	vfaa1;
-		ulong	vfba1;
-		uchar	rsv11a[0x840-0x828];
-	};
-	struct {	/* 840: LCD */
-		ulong	lccr;
-		ulong	lchcr;
-		ulong	lcvcr;
-		ulong	rsv11b;
-		ulong	lcfaa;
-		ulong	lcfba;
-		uchar	lcsr;
-		uchar	rsv11c[0x860-0x859];
-	};
-	struct {	/* 860: I2C */
-		uchar	i2mod;
-		uchar	rsv12a[3];
-		uchar	i2add;
-		uchar	rsv12b[3];
-		uchar	i2brg;
-		uchar	rsv12c[3];
-		uchar	i2com;
-		uchar	rsv12d[3];
-		uchar	i2cer;
-		uchar	rsv12e[3];
-		uchar	i2cmr;
-		uchar	rsv12[0x900-0x875];
-	};
-	struct {	/* 900: DMA */
-		uchar	rsv13[4];
-		ulong	sdar;
-		uchar	sdsr;
-		uchar	pad1[3];
-		uchar	sdmr;
-		uchar	pad2[3];
-		uchar	idsr1;
-		uchar	pad3[3];
-		uchar	idmr1;
-		uchar	pad4[3];
-		uchar	idsr2;
-		uchar	pad5[3];
-		uchar	idmr2;
-		uchar	pad6[0x930-0x91D];
-	};
-	struct {	/* CPM interrupt control */
-		ushort	civr;
-		uchar	pad7[0x940-0x932];
-		ulong	cicr;
-		ulong	cipr;
-		ulong	cimr;
-		ulong	cisr;
-	};
-	struct {	/* input/output port */
-		ushort	padir;
-		ushort	papar;
-		ushort	paodr;
-		ushort	padat;
-		uchar	pad8[8];
-		ushort	pcdir;
-		ushort	pcpar;
-		ushort	pcso;
-		ushort	pcdat;
-		ushort	pcint;
-		uchar	pad9[6];
-		ushort	pddir;
-		ushort	pdpar;
-		ushort	rsv14a;
-		ushort	pddat;
-		uchar	rsv14[0x980-0x978];
-	};
-	struct {	/* CPM timers */
-		ushort	tgcr;
-		uchar	rsv15a[0x990-0x982];
-		ushort	tmr1;
-		ushort	tmr2;
-		ushort	trr1;
-		ushort	trr2;
-		ushort	tcr1;
-		ushort	tcr2;
-		ushort	tcn1;
-		ushort	tcn2;
-		ushort	tmr3;
-		ushort	tmr4;
-		ushort	trr3;
-		ushort	trr4;
-		ushort	tcr3;
-		ushort	tcr4;
-		ushort	tcn3;
-		ushort	tcn4;
-		ushort	ter1;
-		ushort	ter2;
-		ushort	ter3;
-		ushort	ter4;
-		uchar	rsv15[0x9C0-0x9B8];
-	};
-	struct {	/* CPM */
-		ushort	cpcr;
-		uchar	res0[2];
-		ushort	rccr;
-		uchar	res1;
-		uchar	rmds;
-		uchar	res2a[4];
-		ushort	rctr1;
-		ushort	rctr2;
-		ushort	rctr3;
-		ushort	rctr4;
-		uchar	res2[2];
-		ushort	rter;
-		uchar	res3[2];
-		ushort	rtmr;
-		uchar	rsv16[0x9F0-0x9DC];
-	};
-	union {	/* BRG */
-		struct {
-			ulong	brgc1;
-			ulong	brgc2;
-			ulong	brgc3;
-			ulong	brgc4;
-		};
-		ulong	brgc[4];
-	};
-	uchar	skip0[0xAB2-0xA00];	/* USB, SCC, SMC, SPI: address using cpmdev(CP...)->regs */
-	struct {	/* PIP */
-		ushort	pipc;		/* not 823 */
-		ushort	ptpr;		/* not 823 */
-		ulong	pbdir;
-		ulong	pbpar;
-		uchar	pad10[2];
-		ushort	pbodr;
-		ulong	pbdat;
-		uchar	pad11[0xAE0-0xAC8];
-	};
-	struct {	/* SI */
-		ulong	simode;
-		uchar	sigmr;
-		uchar	pad12;
-		uchar	sistr;
-		uchar	sicmr;
-		uchar	pad13[4];
-		ulong	sicr;
-		ulong	sirp;
-		uchar	pad14[0xB00-0xAF4];
-	};
-	ulong	vcram[64];
-	ushort	siram[256];
-	ushort	lcdmap[256];
-};
--- a/os/boot/mpc/ip.h
+++ /dev/null
@@ -1,98 +1,0 @@
-typedef struct Udphdr Udphdr;
-struct Udphdr
-{
-	uchar	d[6];		/* Ethernet destination */
-	uchar	s[6];		/* Ethernet source */
-	uchar	type[2];	/* Ethernet packet type */
-
-	uchar	vihl;		/* Version and header length */
-	uchar	tos;		/* Type of service */
-	uchar	length[2];	/* packet length */
-	uchar	id[2];		/* Identification */
-	uchar	frag[2];	/* Fragment information */
-
-	/* Udp pseudo ip really starts here */
-	uchar	ttl;	
-	uchar	udpproto;	/* Protocol */
-	uchar	udpplen[2];	/* Header plus data length */
-	uchar	udpsrc[4];	/* Ip source */
-	uchar	udpdst[4];	/* Ip destination */
-	uchar	udpsport[2];	/* Source port */
-	uchar	udpdport[2];	/* Destination port */
-	uchar	udplen[2];	/* data length */
-	uchar	udpcksum[2];	/* Checksum */
-};
-
-typedef struct Etherhdr Etherhdr;
-struct Etherhdr
-{
-	uchar	d[6];
-	uchar	s[6];
-	uchar	type[2];
-
-	/* Now we have the ip fields */
-	uchar	vihl;		/* Version and header length */
-	uchar	tos;		/* Type of service */
-	uchar	length[2];	/* packet length */
-	uchar	id[2];		/* Identification */
-	uchar	frag[2];	/* Fragment information */
-	uchar	ttl;		/* Time to live */
-	uchar	proto;		/* Protocol */
-	uchar	cksum[2];	/* Header checksum */
-	uchar	src[4];		/* Ip source */
-	uchar	dst[4];		/* Ip destination */
-};
-
-enum
-{
-	IP_VER		= 0x40,
-	IP_HLEN		= 0x05,			
- 	UDP_EHSIZE	= 22,
-	UDP_PHDRSIZE	= 12,
-	UDP_HDRSIZE	= 20,
-	ETHER_HDR	= 14,
-	IP_UDPPROTO	= 17,
-	ET_IP		= 0x800,
-	Bcastip		= 0xffffffff,
-	BPportsrc	= 68,
-	BPportdst	= 67,
-	TFTPport	= 69,
-	Timeout		= 5000,	/* milliseconds */
-	Bootrequest 	= 1,
-	Bootreply   	= 2,
-	Tftp_READ	= 1,
-	Tftp_WRITE	= 2,
-	Tftp_DATA	= 3,
-	Tftp_ACK	= 4,
-	Tftp_ERROR	= 5,
-	Segsize		= 512,
-	TFTPSZ		= Segsize+10,
-};
-
-typedef struct Bootp Bootp;
-struct Bootp
-{
-	uchar	op;		/* opcode */
-	uchar	htype;		/* hardware type */
-	uchar	hlen;		/* hardware address len */
-	uchar	hops;		/* hops */
-	uchar	xid[4];		/* a random number */
-	uchar	secs[2];	/* elapsed snce client started booting */
-	uchar	pad[2];
-	uchar	ciaddr[4];	/* client IP address (client tells server) */
-	uchar	yiaddr[4];	/* client IP address (server tells client) */
-	uchar	siaddr[4];	/* server IP address */
-	uchar	giaddr[4];	/* gateway IP address */
-	uchar	chaddr[16];	/* client hardware address */
-	char	sname[64];	/* server host name (optional) */
-	char	file[128];	/* boot file name */
-	char	vend[128];	/* vendor-specific goo */
-};
-
-typedef struct Netaddr Netaddr;
-struct Netaddr
-{
-	ulong	ip;
-	ushort	port;
-	char	ea[Eaddrlen];
-};
--- a/os/boot/mpc/l.s
+++ /dev/null
@@ -1,370 +1,0 @@
-#include "mem.h"
-
-/* special instruction definitions */
-#define	BDNE	BC	0,2,
-#define	BDNZ	BC	16,0,
-#define	NOOP	OR	R0,R0,R0
-
-/*
- * common ppc special purpose registers
- */
-#define DSISR	18
-#define DAR	19	/* Data Address Register */
-#define DEC	22	/* Decrementer */
-#define SRR0	26	/* Saved Registers (exception) */
-#define SRR1	27
-#define SPRG0	272	/* Supervisor Private Registers */
-#define SPRG1	273
-#define SPRG2	274
-#define SPRG3	275
-#define TBRU	269	/* Time base Upper/Lower (Reading) */
-#define TBRL	268
-#define TBWU	285	/* Time base Upper/Lower (Writing) */
-#define TBWL	284
-#define PVR	287	/* Processor Version */
-
-/*
- * mpc82x-specific special purpose registers of interest here
- */
-#define EIE	80
-#define EID	81
-#define NRI	82
-#define IMMR	638
-#define IC_CST	560
-#define IC_ADR	561
-#define IC_DAT	562
-#define DC_CST	568
-#define DC_ADR	569
-#define DC_DAT	570
-#define MI_CTR	784
-#define MI_AP	786
-#define MI_EPN	787
-#define MI_TWC	789
-#define MI_RPN	790
-#define MI_DBCAM	816
-#define MI_DBRAM0	817
-#define MI_DBRAM1	818
-#define MD_CTR	792
-#define M_CASID	793
-#define MD_AP	794
-#define MD_EPN	795
-#define M_TWB	796
-#define MD_TWC	797
-#define MD_RPN	798
-#define	M_TW	799
-#define	MD_DBCAM	824
-#define	MD_DBRAM0	825
-#define	MD_DBRAM1	826
-
-/* as on 603e, apparently mtmsr needs help in some chip revisions */
-#define	WAITMSR	SYNC; ISYNC
-
-/* use of SPRG registers in save/restore */
-#define	SAVER0	SPRG0
-#define	SAVER1	SPRG1
-#define	SAVELR	SPRG2
-#define	SAVECR	SPRG3
-
-#define	UREGSIZE	((8+32)*4)
-#define	UREGSPACE	(UREGSIZE+8)	/* allow for arg to trap, and align */
-
-/*
- * This code is loaded by the ROM loader at location 0x3000,
- * or lives in flash memory at 0x2800100.
- * Move it to high memory so that it can load the kernel at 0x0000.
- */
-
-#define LOADCODEBASE	0x3000	/* when downloaded in S records */
-#define FLASHCODEBASE	(FLASHMEM+0x100)	/* when in flash */
-
-	TEXT	start(SB), $-4
-	MOVW	MSR, R3
-	MOVW	$(EE|IP|RI), R4
-	ANDN	R4, R3
-	OR	$ME, R3
-	SYNC
-	MOVW	R3, MSR	/* turn off interrupts but enable traps */
-	WAITMSR
-
-/*
- * reset the caches and disable them for now
- */
-	MOVW	SPR(IC_CST), R4	/* read and clear */
-	MOVW	$(5<<25), R4
-	MOVW	R4, SPR(IC_CST)	/* unlock all */
-	ISYNC
-	MOVW	$(6<<25), R4
-	MOVW	R4, SPR(IC_CST)	/* invalidate all */
-	ISYNC
-	MOVW	$(2<<25), R4
-	MOVW	R4, SPR(IC_CST)	/* disable i-cache */
-	ISYNC
-
-	SYNC
-	MOVW	SPR(DC_CST), R4	/* read and clear */
-	MOVW	$(10<<24), R4
-	MOVW	R4, SPR(DC_CST)	/* unlock all */
-	ISYNC
-	MOVW	$(12<<24), R4
-	MOVW	R4, SPR(DC_CST)	/* invalidate all */
-	ISYNC
-	MOVW	$(4<<24), R4
-	MOVW	R4, SPR(DC_CST)	/* disable i-cache */
-	ISYNC
-
-	MOVW	$7, R4
-ANDN R4, R4, R4
-	MOVW	R4, SPR(158)		/* cancel `show cycle' for normal instruction execution */
-
-/*
- * set other system configuration values
- */
-	MOVW	SPR(IMMR), R5		/* save initial space pointer */
-	MOVW	$INTMEM, R4
-	MOVW	R4, SPR(IMMR)		/* set internal memory base */
-	MOVW	$0xFFFFFF88, R3
-	MOVW	R3, 4(R4)	/* disable watchdog in sypcr */
-	MOVW	$0x01012440, R3
-	MOVW	R3, 0(R4)	/* siumcr */
-
-/*
- * system initialisation (init and map DRAM)
- */
-	MOVW	$0, R0
-	MOVW	$setSB(SB), R2
-	MOVW	$(0xF000<<16), R3
-/*MOVW R0, R3*/
-	ANDCC	R5, R3	/* initial space is high? */
-	BEQ	notrom
-	MOVW	$FLASHCODEBASE, R5	/* where $start(SB) actually is now */
-	MOVW	$start(SB), R4	/* logical start address */
-	SUB	R4, R5, R6	/* text relocation value */
-	MOVW	$etext(SB), R7
-	SUB	R4, R7
-	ADD	R5, R7	/* data address in ROM */
-	MOVW	$bdata(SB), R8
-	SUB	R8, R2
-	ADD	R7, R2	/* relocate SB: SB' = romdata+(SB-bdata) */
-	MOVW	$sysinit0(SB), R4
-	ADD	R6, R4	/* relocate sysinit0's address */
-	MOVW	R4, CTR
-	MOVW	$inmem(SB), R4
-	ADD	R6, R4
-	MOVW	R4, LR	/* and the return address */
-	BR	(CTR)	/* call sysinit0 */
-	TEXT	inmem(SB), $-4
-	MOVW	$FLASHCODEBASE, R3
-	BR	cpu0
-notrom:
-	MOVW	$start(SB), R6
-	SUB	R6, R2
-	ADD	$LOADCODEBASE, R2
-	BL	sysinit0(SB)
-	MOVW	$LOADCODEBASE, R3
-
-/*
- * cpu 0
- *	relocate bootstrap to our link addresses for text and data
- *	set new PC
- */
-cpu0:
-	MOVW	$setSB(SB), R2	/* set correct static base register */
-	MOVW	$start(SB), R4
-	MOVW	$etext(SB), R5
-	SUB	R4, R5
-	CMP	R4, R3	/* already there? */
-	BNE	copytext
-	ADD	R5, R3	/* start of data image */
-	BR	copydata
-
-copytext:
-	ADD	$3, R5
-	SRAW	$2, R5
-	MOVW	R5, CTR
-	SUB	$4, R4
-	SUB	$4, R3
-copyt:			/* copy text */
-	MOVWU	4(R3), R5
-	MOVWU	R5, 4(R4)
-	BDNZ	copyt
-	ADD	$4, R3
-
-copydata:
-	/* copy data */
-	MOVW	$bdata(SB), R4
-	CMP	R4, R3	/* already there? */
-	BEQ	loadkpc
-	MOVW	$edata(SB), R5
-	SUB	R4, R5
-	ADD	$3, R5
-	SRAW	$2, R5
-	MOVW	R5, CTR
-	SUB	$4, R4
-	SUB	$4, R3
-copyd:
-	MOVWU	4(R3), R5
-	MOVWU	R5, 4(R4)
-	BDNZ	copyd
-
-	/* load correct PC */
-loadkpc:
-	MOVW	$start1(SB), R3
-	MOVW	R3, LR
-	BR	(LR)
-TEXT start1(SB), $-4
-	MOVW	$edata(SB), R3
-	MOVW	$end(SB), R4
-	SUBCC	R3, R4
-	BLE	skipz
-	SRAW	$2, R4
-	MOVW	R4, CTR
-	SUB	$4, R3
-	MOVW	$0, R0
-zero:
-	MOVWU	R0, 4(R3)
-	BDNZ	zero
-skipz:
-	MOVW	$mach0(SB), R1
-	MOVW	R1, m(SB)
-	ADD	$(MACHSIZE-8), R1
-	MOVW	$0, R0
-	BL	main(SB)
-	BR	0(PC)
-
-TEXT	getmsr(SB), $0
-	MOVW	MSR, R3
-	RETURN
-
-TEXT	putmsr(SB), $0
-	SYNC
-	MOVW	R3, MSR
-	WAITMSR
-	RETURN
-
-TEXT	eieio(SB), $0
-	EIEIO
-	RETURN
-
-TEXT	idle(SB), $0
-	RETURN
-
-TEXT	spllo(SB), $0
-	MOVW	MSR, R3
-	OR	$EE, R3, R4
-	SYNC
-	MOVW	R4, MSR
-	WAITMSR
-	RETURN
-
-TEXT	splhi(SB), $0
-	MOVW	MSR, R3
-	RLWNM	$0, R3, $~EE, R4
-	SYNC
-	MOVW	R4, MSR
-	WAITMSR
-	RETURN
-
-TEXT	splx(SB), $0
-	MOVW	MSR, R4
-	RLWMI	$0, R3, $EE, R4
-	SYNC
-	MOVW	R4, MSR
-	WAITMSR
-	RETURN
-
-TEXT	gettbl(SB), $0
-/*	MOVW	SPR(TBRL), R3	*/
-	WORD	$0x7c6c42e6	/* mftbl on 8xx series */
-	RETURN
-
-TEXT	getpvr(SB), $0
-	MOVW	SPR(PVR), R3
-	RETURN
-
-TEXT	getimmr(SB), $0
-	MOVW	SPR(IMMR), R3
-	RETURN
-
-TEXT	getdec(SB), $0
-	MOVW	SPR(DEC), R3
-	RETURN
-
-TEXT	putdec(SB), $0
-	MOVW	R3, SPR(DEC)
-	RETURN
-
-/*
- * save state in Ureg on kernel stack.
- * enter with R0 giving the PC from the call to `exception' from the vector.
- * on return, SB (R2) has been set, and R3 has the Ureg*
- */
-TEXT saveureg(SB), $-4
-	SUB	$UREGSPACE, R1
-	MOVMW	R2, 48(R1)	/* r2:r31 */
-	MOVW	$setSB(SB), R2
-	MOVW	SPR(SAVER1), R4
-	MOVW	R4, 44(R1)
-	MOVW	SPR(SAVER0), R5
-	MOVW	R5, 40(R1)
-	MOVW	CTR, R6
-	MOVW	R6, 36(R1)
-	MOVW	XER, R4
-	MOVW	R4, 32(R1)
-	MOVW	SPR(SAVECR), R5	/* CR */
-	MOVW	R5, 28(R1)
-	MOVW	SPR(SAVELR), R6	/* LR */
-	MOVW	R6, 24(R1)
-	/* pad at 20(R1) */
-	MOVW	SPR(SRR0), R4
-	MOVW	R4, 16(R1)	/* old PC */
-	MOVW	SPR(SRR1), R5
-	MOVW	R5, 12(R1)
-	MOVW	R0, 8(R1)	/* cause/vector, encoded in LR from vector */
-	ADD	$8, R1, R3	/* Ureg* */
-	STWCCC	R3, (R1)	/* break any pending reservations */
-	MOVW	$0, R0	/* R0ISZERO */
-	BR	(LR)
-
-/*
- * restore state from Ureg
- * SB (R2) is unusable on return
- */
-TEXT restoreureg(SB), $-4
-	MOVMW	48(R1), R2	/* r2:r31 */
-	/* defer R1 */
-	MOVW	40(R1), R0
-	MOVW	R0, SPR(SAVER0)
-	MOVW	36(R1), R0
-	MOVW	R0, CTR
-	MOVW	32(R1), R0
-	MOVW	R0, XER
-	MOVW	28(R1), R0
-	MOVW	R0, CR	/* CR */
-	MOVW	24(R1), R0
-	MOVW	R0, SPR(SAVELR)	/* LR */
-	/* pad, skip */
-	MOVW	16(R1), R0
-	MOVW	R0, SPR(SRR0)	/* old PC */
-	MOVW	12(R1), R0
-	MOVW	R0, SPR(SRR1)	/* old MSR */
-	/* cause, skip */
-	MOVW	44(R1), R1	/* old SP */
-	BR	(LR)
-
-TEXT	exception(SB), $-4
-	MOVW	R1, SPR(SAVER1)
-	MOVW	CR, R0
-	MOVW	R0, SPR(SAVECR)
-	MOVW	LR, R0
-	BL	saveureg(SB)
-	MOVW	$0, R0
-	BL	trap(SB)
-	BL	restoreureg(SB)
-	MOVW	SPR(SAVELR), R0
-	MOVW	R0, LR
-	MOVW	SPR(SAVER0), R0
-	ISYNC
-	RFI
-
-GLOBL	mach0+0(SB), $MACHSIZE
-GLOBL	m(SB), $4
--- a/os/boot/mpc/lib.h
+++ /dev/null
@@ -1,106 +1,0 @@
-/*
- * functions (possibly) linked in, complete, from libc.
- */
-
-/*
- * mem routines
- */
-extern	void*	memccpy(void*, void*, int, long);
-extern	void*	memset(void*, int, long);
-extern	int	memcmp(void*, void*, long);
-extern	void*	memmove(void*, void*, long);
-extern	void*	memchr(void*, int, long);
-
-/*
- * string routines
- */
-extern	char*	strcat(char*, char*);
-extern	char*	strchr(char*, char);
-extern	int	strcmp(char*, char*);
-extern	char*	strcpy(char*, char*);
-extern	char*	strncat(char*, char*, long);
-extern	char*	strncpy(char*, char*, long);
-extern	int	strncmp(char*, char*, long);
-extern	long	strlen(char*);
-extern	char*	strrchr(char*, char);
-extern	char*	strstr(char*, char*);
-
-/*
- * print routines
- * 	Fconv isn't used but is defined to satisfy prototypes in libg.h
- *	that are never called.
- */
-typedef	struct Fconv Fconv;
-
-extern	char*	donprint(char*, char*, char*, void*);
-extern	int	sprint(char*, char*, ...);
-extern	int	print(char*, ...);
-
-#define	PRINTSIZE	256
-
-/*
- * one-of-a-kind
- */
-extern	int	atoi(char*);
-extern	long	strtol(char*, char**, int);
-extern	ulong	strtoul(char*, char**, int);
-extern	long	end;
-
-/*
- * Syscall data structures
- */
-
-#define	MORDER	0x0003	/* mask for bits defining order of mounting */
-#define	MREPL	0x0000	/* mount replaces object */
-#define	MBEFORE	0x0001	/* mount goes before others in union directory */
-#define	MAFTER	0x0002	/* mount goes after others in union directory */
-#define	MCREATE	0x0004	/* permit creation in mounted directory */
-#define	MMASK	0x0007	/* all bits on */
-
-#define	OREAD	0	/* open for read */
-#define	OWRITE	1	/* write */
-#define	ORDWR	2	/* read and write */
-#define	OEXEC	3	/* execute, == read but check execute permission */
-#define	OTRUNC	16	/* or'ed in (except for exec), truncate file first */
-#define	OCEXEC	32	/* or'ed in, close on exec */
-#define	ORCLOSE	64	/* or'ed in, remove on close */
-
-#define	NCONT	0	/* continue after note */
-#define	NDFLT	1	/* terminate after note */
-
-typedef struct Qid	Qid;
-typedef struct Dir	Dir;
-typedef struct Waitmsg	Waitmsg;
-
-#define	ERRLEN	64
-#define	DIRLEN	116
-#define	NAMELEN	28
-
-struct Qid
-{
-	ulong	path;
-	ulong	vers;
-};
-
-struct Dir
-{
-	char	name[NAMELEN];
-	char	uid[NAMELEN];
-	char	gid[NAMELEN];
-	Qid	qid;
-	ulong	mode;
-	long	atime;
-	long	mtime;
-	vlong	length;
-	short	type;
-	short	dev;
-};
-
-struct Waitmsg
-{
-	int	pid;		/* of loved one */
-	int	status;		/* unused; a placeholder */
-	ulong	time[3];	/* of loved one */
-	char	msg[ERRLEN];
-};
-#define	nelem(x)	(sizeof(x)/sizeof((x)[0]))
--- a/os/boot/mpc/main.c
+++ /dev/null
@@ -1,524 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-#include "dosfs.h"
-
-typedef struct Type Type;
-typedef struct Medium Medium;
-typedef struct Mode Mode;
-
-enum {
-	Dany		= -1,
-	Nmedia		= 16,
-
-	/* DS1 switch options */
-	Sflashfs		= 1<<0,	/* take local fs from flash */
-	Snotflash		= 1<<1,	/* don't boot from flash */
-};
-
-enum {					/* type */
-	Tflash,
-	Tuart,
-	Tether,
-	Thard,
-
-	Tany		= -1,
-};
-
-enum {					/* flag and name */
-	Fnone		= 0x00,
-
-	Fdos		= 0x01,
-	Ndos		= 0x00,
-	Fboot		= 0x02,
-	Nboot		= 0x01,
-	Fbootp		= 0x04,
-	Nbootp		= 0x02,
-	Fflash		= 0x08,
-	Fuart		= 0x10,
-	NName		= 0x03,
-
-	Fany		= Fbootp|Fboot|Fdos|Fflash|Fuart,
-
-	Fini		= 0x10,
-	Fprobe		= 0x80,
-};
-
-enum {					/* mode */
-	Mauto		= 0x00,
-	Mlocal		= 0x01,
-	Manual		= 0x02,
-	NMode		= 0x03,
-};
-
-typedef struct Type {
-	int	type;
-	char	*cname;
-	int	flag;
-	int	(*init)(void);
-	long	(*read)(int, void*, long);
-	long	(*seek)(int, long);
-	Partition* (*setpart)(int, char*);
-	char*	name[NName];
-
-	int	mask;
-	Medium*	media;
-} Type;
-
-typedef struct Medium {
-	Type*	type;
-	int	flag;
-	Partition* partition;
-	Dos;
-
-	Medium*	next;
-} Medium;
-
-typedef struct Mode {
-	char*	name;
-	int	mode;
-} Mode;
-
-static Type types[] = {
-	{	Tflash, "flash",
-		Fflash,
-		flashinit, 0, 0, 0,
-		{ 0, "F", 0, }
-	},
-/*
-	{	Tuart, "uart",
-		Fuart|Fboot,
-		uartinit, uartread, uartseek, setuartpart,
-		{ 0, "u", 0, }
-	},
-*/
-	{	Tether, "ether",
-		Fbootp,
-		etherinit, 0, 0, 0,
-		{ 0, 0, "e", },
-	},
-	{	Thard, "ata",
-		Fini|Fboot|Fdos,
-		0, 0, 0, 0,		/* not used now, will be later with PCMCIA */
-		{ "hd", "h", 0, },
-	},
-	{-1},
-};
-
-static Medium media[Nmedia];
-static Medium *curmedium = media;
-
-static Mode modes[NMode+1] = {
-	[Mauto]		{ "auto",   Mauto,  },
-	[Mlocal]	{ "local",  Mlocal, },
-	[Manual]	{ "manual", Manual, },
-};
-
-static char *inis[] = {
-	"inferno/inferno.ini",
-	"inferno.ini",
-	"plan9/plan9.ini",
-	"plan9.ini",
-	0,
-};
-char **ini;
-int	predawn;
-
-static int
-parse(char *line, int *type, int *flag, int *dev, char *file)
-{
-	Type *tp;
-	char buf[2*NAMELEN], *v[4], *p;
-	int i;
-
-	strcpy(buf, line);
-	switch(getcfields(buf, v, 4, "!")){
-
-	case 3:
-		break;
-
-	case 2:
-		v[2] = "";
-		break;
-
-	default:
-		return 0;
-	}
-
-	*flag = 0;
-	for(tp = types; tp->cname; tp++){
-		for(i = 0; i < NName; i++){
-
-			if(tp->name[i] == 0 || strcmp(v[0], tp->name[i]))
-				continue;
-			*type = tp->type;
-			*flag |= 1<<i;
-
-			if((*dev = strtoul(v[1], &p, 0)) == 0 && p == v[1])
-				return 0;
-		
-			strcpy(file, v[2]);
-		
-			return 1;
-		}
-	}
-
-	return 0;
-
-}
-
-static int
-boot(Medium *mp, int flag, char *file)
-{
-	Dosfile df;
-	char ixdos[128], *p;
-	int r;
-
-	uartsetboot(0);
-	if(flag & Fbootp){
-		sprint(BOOTLINE, "%s!%d", mp->type->name[Nbootp], mp->dev);
-		return bootp(mp->dev, file);
-	}
-
-	if(flag & Fflash){
-		if(mp->flag & Fflash && flashbootable(0))
-			flashboot(mp->dev);
-	}
-
-	if(flag & Fboot){
-
-		if(mp->flag & Fini){
-			(*mp->type->setpart)(mp->dev, "disk");
-			plan9ini(mp, nil);
-		}
-		if(file == 0 || *file == 0)
-			file = mp->partition->name;
-		(*mp->type->setpart)(mp->dev, file);
-		sprint(BOOTLINE, "%s!%d!%s", mp->type->name[Nboot], mp->dev, file);
-		r = plan9boot(mp->dev, mp->seek, mp->read);
-		uartsetboot(0);
-		return r;
-	}
-
-	if(flag & Fdos){
-		if(mp->type->setpart)
-			(*mp->type->setpart)(mp->dev, "disk");
-		if(mp->flag & Fini)
-			plan9ini(mp, nil);
-		if(file == 0 || *file == 0){
-			strcpy(ixdos, *ini);
-			if(p = strrchr(ixdos, '/'))
-				p++;
-			else
-				p = ixdos;
-			strcpy(p, "impc");
-			if(dosstat(mp, ixdos, &df) <= 0)
-				return -1;
-		}
-		else
-			strcpy(ixdos, file);
-		sprint(BOOTLINE, "%s!%d!%s", mp->type->name[Ndos], mp->dev, ixdos);
-		return dosboot(mp, ixdos);
-	}
-
-	return -1;
-}
-
-static Medium*
-allocm(Type *tp)
-{
-	Medium **l;
-
-	if(curmedium >= &media[Nmedia])
-		return 0;
-
-	for(l = &tp->media; *l; l = &(*l)->next)
-		;
-	*l = curmedium++;
-	return *l;
-}
-
-Medium*
-probe(int type, int flag, int dev)
-{
-	Type *tp;
-	int dombr, i, start;
-	Medium *mp;
-	Dosfile df;
-	Partition *pp;
-
-	for(tp = types; tp->cname; tp++){
-		if(type != Tany && type != tp->type || tp->init == 0)
-			continue;
-
-		if(flag != Fnone){
-			for(mp = tp->media; mp; mp = mp->next){
-				if((flag & mp->flag) && (dev == Dany || dev == mp->dev))
-					return mp;
-			}
-		}
-		if((tp->flag & Fprobe) == 0){
-			tp->flag |= Fprobe;
-			tp->mask = (*tp->init)();
-		}
-
-		for(i = 0; tp->mask; i++){
-			if((tp->mask & (1<<i)) == 0)
-				continue;
-			tp->mask &= ~(1<<i);
-
-			if((mp = allocm(tp)) == 0)
-				continue;
-
-			mp->dev = i;
-			mp->flag = tp->flag;
-			mp->seek = tp->seek;
-			mp->read = tp->read;
-			mp->type = tp;
-
-			if(mp->flag & Fboot){
-				if((mp->partition = (*tp->setpart)(i, "boot")) == 0)
-					mp->flag &= ~Fboot;
-				if((mp->flag & (Fflash|Fuart)) == 0)
-					(*tp->setpart)(i, "disk");
-			}
-
-			if(mp->flag & Fdos){
-				start = 0;
-				dombr = 1;
-				if(mp->type->setpart){
-					if(pp = (*mp->type->setpart)(i, "dos")){
-						if(start = pp->start)
-							dombr = 0;
-					}
-					(*tp->setpart)(i, "disk");
-				}
-				if(dosinit(mp, start, dombr) < 0)
-					mp->flag &= ~(Fini|Fdos);
-				else
-					print("dos init failed\n");
-			}
-
-			if(mp->flag & Fini){
-				mp->flag &= ~Fini;
-				for(ini = inis; *ini; ini++){
-					if(dosstat(mp, *ini, &df) <= 0)
-						continue;
-					mp->flag |= Fini;
-					break;
-				}
-			}
-
-			if((flag & mp->flag) && (dev == Dany || dev == i))
-				return mp;
-		}
-	}
-
-	return 0;
-}
-
-void
-main(void)
-{
-	Medium *mp;
-	int dev, flag, i, mode, tried, type, options;
-	char def[2*NAMELEN], file[2*NAMELEN], line[80], *p;
-	Type *tp;
-
-	machinit();
-	archinit();
-	meminit();
-	cpminit();
-	trapinit();
-	consinit();	/* screen and keyboard initially */
-	screeninit();
-	cpuidprint();
-	alarminit();
-	clockinit();
-	predawn = 0;
-	spllo();
-	options = archoptionsw();
-
-	mp = 0;
-	for(tp = types; tp->cname; tp++){
-		if(tp->type == Tether)
-			continue;
-		if((mp = probe(tp->type, Fini, Dany)) && (mp->flag & Fini)){
-			plan9ini(mp, nil);
-			break;
-		}
-	}
-
-	if(mp == 0 || (mp->flag & Fini) == 0)
-		plan9ini(nil, flashconfig(0));
-
-	//consinit();	/* establish new console location */
-
-	if((options & Snotflash) == 0 && flashbootable(0)){
-		print("Flash boot\n");
-		flashboot(0);
-	}
-
-	tried = 0;
-	mode = Mauto;
-	p = getconf("bootfile");
-	flag = 0;
-
-	if(p != 0) {
-		mode = Manual;
-		for(i = 0; i < NMode; i++){
-			if(strcmp(p, modes[i].name) == 0){
-				mode = modes[i].mode;
-				goto done;
-			}
-		}
-		if(parse(p, &type, &flag, &dev, file) == 0) {
-			print("Bad bootfile syntax: %s\n", p);
-			goto done;
-		}
-		mp = probe(type, flag, dev);
-		if(mp == 0) {
-			print("Cannot access device: %s\n", p);
-			goto done;
-		}
-		tried = boot(mp, flag, file);
-	}
-done:
-	if(tried == 0 && mode != Manual){
-		flag = Fany;
-		if(mode == Mlocal)
-			flag &= ~Fbootp;
-		if(options & Snotflash)
-			flag &= ~Fflash;
-		if((mp = probe(Tany, flag, Dany)) != 0)
-			boot(mp, flag & mp->flag, 0);
-	}
-
-	def[0] = 0;
-	probe(Tany, Fnone, Dany);
-
-	flag = 0;
-	for(tp = types; tp->cname; tp++){
-		for(mp = tp->media; mp; mp = mp->next){
-			if(flag == 0){
-				flag = 1;
-				print("Boot devices:");
-			}
-
-			if(mp->flag & Fbootp)
-				print(" %s!%d", mp->type->name[Nbootp], mp->dev);
-			if(mp->flag & Fdos)
-				print(" %s!%d", mp->type->name[Ndos], mp->dev);
-			if(mp->flag & (Fflash|Fuart) || mp->flag & Fboot)
-				print(" %s!%d", mp->type->name[Nboot], mp->dev);
-		}
-	}
-	if(flag)
-		print("\n");
-
-	for(;;){
-		if(getstr("boot from", line, sizeof(line), def) >= 0){
-			if(parse(line, &type, &flag, &dev, file)){
-				if(mp = probe(type, flag, dev))
-					boot(mp, flag, file);
-			}
-		}
-		def[0] = 0;
-	}
-}
-
-void
-machinit(void)
-{
-	memset(m, 0, sizeof(*m));
-	m->delayloop = 20000;
-	m->cpupvr = getpvr();
-	m->iomem = KADDR(INTMEM);
-}
-
-int
-getcfields(char* lp, char** fields, int n, char* sep)
-{
-	int i;
-
-	for(i = 0; lp && *lp && i < n; i++){
-		while(*lp && strchr(sep, *lp) != 0)
-			*lp++ = 0;
-		if(*lp == 0)
-			break;
-		fields[i] = lp;
-		while(*lp && strchr(sep, *lp) == 0){
-			if(*lp == '\\' && *(lp+1) == '\n')
-				*lp++ = ' ';
-			lp++;
-		}
-	}
-
-	return i;
-}
-
-static	Map	memv[512];
-static	RMap	rammap = {"physical memory"};
-
-void
-meminit(void)
-{
-	ulong e;
-
-	mapinit(&rammap, memv, sizeof(memv));
-	e = PADDR(&end);
-	mapfree(&rammap, e, 4*1024*1024-e);	/* fixed 4Mbytes is plenty for bootstrap */
-}
-
-void*
-ialloc(ulong n, int align)
-{
-	ulong a;
-	int s;
-
-	if(align <= 0)
-		align = 4;
-	s = splhi();
-	a = mapalloc(&rammap, 0, n, align);
-	splx(s);
-	if(a == 0)
-		panic("ialloc");
-	return memset(KADDR(a), 0, n);
-}
-
-void*
-malloc(ulong n)
-{
-	ulong *p;
-
-	n = ((n+sizeof(int)-1)&~(sizeof(int)-1))+2*sizeof(int);
-	p = ialloc(n, sizeof(int));
-	*p++ = 0xcafebeef;
-	*p++ = n;
-	return p;
-}
-
-void
-free(void *ap)
-{
-	int s;
-	ulong *p;
-
-	p = ap;
-	if(p){
-		if(*(p -= 2) != 0xcafebeef)
-			panic("free");
-		s = splhi();
-		mapfree(&rammap, (ulong)p, p[1]);
-		splx(s);
-	}
-}
-
-void
-sched(void)
-{
-}
--- a/os/boot/mpc/mem.h
+++ /dev/null
@@ -1,95 +1,0 @@
-/*
- * Memory and machine-specific definitions.  Used in C and assembler.
- */
-
-/*
- * Sizes
- */
-#define	BI2BY		8			/* bits per byte */
-#define BI2WD		32			/* bits per word */
-#define	BY2WD		4			/* bytes per word */
-#define	BY2PG		4096			/* bytes per page */
-#define	WD2PG		(BY2PG/BY2WD)		/* words per page */
-#define	PGSHIFT		12			/* log(BY2PG) */
-#define PGROUND(s)	(((s)+(BY2PG-1))&~(BY2PG-1))
-
-#define	MAXMACH		1			/* max # cpus system can run */
-#define	CACHELINELOG	4
-#define CACHELINESZ	(1<<CACHELINELOG)
-
-/*
- * Time
- */
-#define	HZ		(50)				/* clock frequency */
-#define	MS2HZ		(1000/HZ)			/* millisec per clock tick */
-#define	TK2SEC(t)	((t)/HZ)			/* ticks to seconds */
-#define	TK2MS(t)	((((ulong)(t))*1000)/HZ)	/* ticks to milliseconds */
-#define	MS2TK(t)	((((ulong)(t))*HZ)/1000)	/* milliseconds to ticks */
-#define	MHz	1000000
-
-/*
- * Fundamental values
- */
-
-#define	KZERO	0	/* bootstrap runs in real mode */
-#define	MACHSIZE	4096
-
-/*
- *  physical MMU
- */
-#define KSEG0	0x20000000
-#define	KSEGM	0xE0000000	/* mask to check which seg */
-
-/*
- * MSR bits
- */
-
-#define	POW	0x40000	/* enable power mgmt */
-#define	TGPR	0x20000	/* GPR0-3 remapped; 603/603e specific */
-#define	ILE	0x10000	/* interrupts little endian */
-#define	EE	0x08000	/* enable external/decrementer interrupts */
-#define	PR	0x04000	/* =1, user mode */
-#define	FPE	0x02000	/* enable floating point */
-#define	ME	0x01000	/* enable machine check exceptions */
-#define	FE0	0x00800
-#define	SE	0x00400	/* single-step trace */
-#define	BE	0x00200	/* branch trace */
-#define	FE1	0x00100
-#define	IP	0x00040	/* =0, vector to nnnnn; =1, vector to FFFnnnnn */
-#define	IR	0x00020	/* enable instruction address translation */
-#define	DR	0x00010	/* enable data address translation */
-#define	RI	0x00002	/* exception is recoverable */
-#define	LE	0x00001	/* little endian mode */
-
-#define	KMSR	(ME|FE0|FE1|FPE)
-#define	UMSR	(KMSR|PR|EE|IR|DR)
-
-/*
- * MPC82x addresses; mpc8bug is happy with these
- */
-#define	BCSRMEM	0x02100000
-#define	INTMEM	0x02200000
-#define	FLASHMEM	0x02800000
-#define	SDRAMMEM	0x03000000
-
-#define	DPRAM	(INTMEM+0x2000)
-#define	DPLEN1	0x400
-#define	DPLEN2	0x200
-#define	DPLEN3	0x100
-#define	DPBASE	(DPRAM+DPLEN1)
-
-#define	SCC1P	(INTMEM+0x3C00)
-#define	I2CP	(INTMEM+0x3C80)
-#define	MISCP	(INTMEM+0x3CB0)
-#define	IDMA1P	(INTMEM+0x3CC0)
-#define	SCC2P	(INTMEM+0x3D00)
-#define	SCC3P	(INTMEM+0x3E00)
-#define	SCC4P	(INTMEM+0x3F00)
-#define	SPIP	(INTMEM+0x3D80)
-#define	TIMERP	(INTMEM+0x3DB0)
-#define	SMC1P	(INTMEM+0x3E80)
-#define	DSP1P	(INTMEM+0x3EC0)
-#define	SMC2P	(INTMEM+0x3F80)
-#define	DSP2P	(INTMEM+0x3FC0)
-
-#define KEEP_ALIVE_KEY 0x55ccaa33	/* clock and rtc register key */
--- a/os/boot/mpc/mkfile
+++ /dev/null
@@ -1,116 +1,0 @@
-objtype=power
-OBJTYPE=power	# always
-<../../../mkconfig
-SYSTARG=$OSTARG	# always
-<$ROOT/mkfiles/mkfile-$SYSTARG-$OBJTYPE
-INSTALLDIR=$ROOT/Inferno/$OBJTYPE/bin	#path of directory where kernel is installed
-ARCH=fads	# selects board dependent code
-TARG=qb$ARCH
-OFILES=\
-	l.$O\
-	arch$ARCH.$O\
-	devuart.$O\
-	uartboot.$O\
-	alarm.$O\
-	bootp.$O\
-	clock.$O\
-	conf.$O\
-	console.$O\
-	cpm.$O\
-	defont0.$O\
-	donprint.$O\
-	dosboot.$O\
-	devether.$O\
-	etherscc.$O\
-	fblt.$O\
-	gbitbltclip.$O\
-	flash.$O\
-	main.$O\
-	plan9boot.$O\
-	qio.$O\
-	rmap.$O\
-	screen.$O\
-	init$ARCH.$O\
-	trap.$O\
-	zqs.$O\
-
-HFILES=\
-	boot.h\
-	dat.h\
-	fns.h\
-	io.h\
-	lib.h\
-	mem.h\
-	squeeze.h\
-	gnot.h\
-	arch$ARCH.h\
-
-LIBS=\
-	kern\
-
-LIBDIRS=$LIBS
-LIBNAMES=${LIBS:%=lib%.a}
-LIBFILES=${LIBS:%=$ROOT/$TARGMODEL/$OBJTYPE/lib/lib%.a}
-
-#all:NV:	$TARG k.mx f.mx
-all:NV:	$TARG
-install:V: 	$INSTALLDIR/$TARG
-installall:V: 	$INSTALLDIR/$TARG
-
-$INSTALLDIR/%: %
-	rm -f $INSTALLDIR/$stem && cp $stem $INSTALLDIR/$stem
-
-$TARG: $OFILES $LIBNAMES
-	$LD -o $target -l  -T0x140000 -R4 $OFILES $LIBFILES
-	ls -l $target
-
-qbrom$ARCH:	$OFILES $LIBNAMES
-	$LD -o $target -l -T0x02800100 -R0 -D0x140000 $OFILES $LIBFILES
-
-k.mx:	$TARG
-	ms2 -S 0x100 -a 0x100 -p 4 $TARG >k.mx
-
-f.mx:	qbrom$ARCH
-	ms2 -S 0x100 -a 0x2800100 -p 4 $prereq >f.mx
-
-%.$O:	%.s
-	$AS $stem.s
-
-%.$O:	%.c
-	$CC $CFLAGS $stem.c
-
-%.$O:	$HFILES
-
-lib%.a:V:	$SHELLTYPE-lib%.a
-
-rc-lib%.a nt-lib%.a:VQ:
-	echo '@{builtin cd ' $ROOT/lib$stem ';mk SHELLTYPE=$SHELLTYPE SYSTARG=$SYSTARG OBJTYPE=$OBJTYPE install}'
-	@{builtin cd  $ROOT/lib$stem ;mk 'SHELLTYPE='$SHELLTYPE 'SYSTARG='$SYSTARG 'OBJTYPE='$OBJTYPE install}
-
-sh-lib%.a:VQ:
-	echo "(cd $ROOT/lib$stem ; mk SHELLTYPE=$SHELLTYPE SYSTARG=$SYSTARG OBJTYPE=$OBJTYPE install)"
-	(cd $ROOT/lib$stem ; mk SHELLTYPE=$SHELLTYPE SYSTARG=$SYSTARG OBJTYPE=$OBJTYPE install)
-
-clock.$O floppy.$O trap.$O:	ureg.h
-conf.$O dosboot.$O main.$O:	dosfs.h
-ether.$O etherscc.$O:	etherif.h
-bootp.$O:	ip.h
-
-clean:V:
-	rm -f *.[$OS] [$OS].out y.tab.? y.debug y.output $TARG qboot k.mx f.mx romboot
-
-nuke-sh:QV:
-		for i in $LIBDIRS
-		do
-			echo "(cd $ROOT/lib$i ; mk SHELLTYPE=$SHELLTYPE SYSTARG=$SYSTARG OBJTYPE=$OBJTYPE nuke)"
-			(cd $ROOT/lib$i; mk 'SHELLTYPE='$SHELLTYPE 'SYSTARG='$SYSTARG 'OBJTYPE='$OBJTYPE nuke)
-		done
-
-nuke-rc nuke-nt:QV:
-		for (i in $LIBDIRS)
-		{
-			echo '@{cd $ROOT/lib$i ; mk SHELLTYPE=$SHELLTYPE SYSTARG=$SYSTARG OBJTYPE=$OBJTYPE nuke}'
-			@{cd $ROOT/lib$i; mk 'SHELLTYPE='$SHELLTYPE 'SYSTARG='$SYSTARG 'OBJTYPE='$OBJTYPE nuke}
-		}
-
-nuke:V:		clean nuke-$SHELLTYPE
--- a/os/boot/mpc/ms2.c
+++ /dev/null
@@ -1,179 +1,0 @@
-#include <u.h>
-#include <libc.h>
-#include <bio.h>
-#include <mach.h>
-
-void	record(uchar*, int);
-void	usage(void);
-void	dosegment(long, int);
-void trailer(ulong);
-
-enum
-{
-	Recordsize = 32,
-};
-
-int	dsegonly;
-int	supressend;
-int	binary;
-int	addr4;
-ulong	addr;
-ulong 	psize = 4096;
-ulong	startaddr = 0x030000;
-Biobuf 	stdout;
-Biobuf	bio;
-
-void
-main(int argc, char **argv)
-{
-	Dir dir;
-	Fhdr f;
-	int fd;
-
-	ARGBEGIN{
-	case 'd':
-		dsegonly++;
-		break;
-	case 's':
-		supressend++;
-		break;
-	case 'a':
-		addr = strtoul(ARGF(), 0, 0);
-		break;
-	case 'p':
-		psize = strtoul(ARGF(), 0, 0);
-		break;
-	case 'b':
-		binary++;
-		break;
-	case 'S':
-		startaddr = strtoul(ARGF(), 0, 0);
-		break;
-	case '4':
-		addr4++;
-		break;
-	default:
-		usage();
-	}ARGEND
-
-	if(argc != 1)
-		usage();
-
-	Binit(&stdout, 1, OWRITE);
-
-	fd = open(argv[0], OREAD);
-	if(fd < 0) {
-		fprint(2, "ms2: open %s: %r\n", argv[0]);
-		exits("open");
-	}
-
-	if(binary) {
-		if(dirfstat(fd, &dir) < 0) {
-			fprint(2, "ms2: stat failed %r");
-			exits("dirfstat");
-		}
-		Binit(&bio, fd, OREAD);
-		dosegment(0, dir.length);
-		if(supressend == 0)
-			trailer(startaddr);
-		Bterm(&stdout);
-		Bterm(&bio);
-		exits(0);
-	}
-
-	if(crackhdr(fd, &f) == 0){
-		fprint(2, "ms2: bad magic: %r\n");
-		exits("magic");
-	}
-	seek(fd, 0, 0);
-
-	Binit(&bio, fd, OREAD);
-
-	if(dsegonly)
-		dosegment(f.datoff, f.datsz);
-	else {
-		dosegment(f.txtoff, f.txtsz);
-		addr = (addr+(psize-1))&~(psize-1);
-		dosegment(f.datoff, f.datsz);
-	}
-
-	if(supressend == 0)
-		trailer(startaddr);
-
-	Bterm(&stdout);
-	Bterm(&bio);
-	exits(0);
-}
-
-void
-dosegment(long foff, int len)
-{
-	int l, n;
-	uchar buf[2*Recordsize];
-
-	Bseek(&bio, foff, 0);
-	for(;;) {
-		l = len;
-		if(l > Recordsize)
-			l = Recordsize;
-		n = Bread(&bio, buf, l);
-		if(n == 0)
-			break;
-		if(n < 0) {
-			fprint(2, "ms2: read error: %r\n");
-			exits("read");
-		}
-		record(buf, l);
-		len -= l;
-	}
-}
-
-void
-record(uchar *s, int l)
-{
-	int i;
-	ulong cksum;
-
-	if(addr4 || addr & (0xFF<<24)){
-		Bprint(&stdout, "S3%.2X%.8luX", l+5, addr);
-		cksum = l+5;
-		cksum += (addr>>24)&0xff;
-	}else{
-		Bprint(&stdout, "S2%.2X%.6X", l+4, addr);
-		cksum = l+4;
-	}
-	cksum += addr&0xff;
-	cksum += (addr>>8)&0xff;
-	cksum += (addr>>16)&0xff;
-
-	for(i = 0; i < l; i++) {
-		cksum += *s;
-		Bprint(&stdout, "%.2X", *s++);
-	}
-	Bprint(&stdout, "%.2X\n", (~cksum)&0xff);
-	addr += l;
-}
-
-void
-trailer(ulong a)
-{
-	ulong cksum;
-
-	cksum = 0;
-	if(addr4 || a & (0xFF<<24)){
-		Bprint(&stdout, "S7%.8luX", a);
-		cksum += (a>>24)&0xff;
-	}else
-		Bprint(&stdout, "S9%.6X", a);
-	cksum += a&0xff;
-	cksum += (a>>8)&0xff;
-	cksum += (a>>16)&0xff;
-	Bprint(&stdout, "%.2X\n", (~cksum)&0xff);
-}
-
-void
-usage(void)
-{
-	fprint(2, "usage: ms2 [-ds] [-a address] [-p pagesize] ?.out\n");
-	exits("usage");
-}
--- a/os/boot/mpc/plan9boot.c
+++ /dev/null
@@ -1,96 +1,0 @@
-#include	"u.h"
-#include	"lib.h"
-#include	"mem.h"
-#include	"dat.h"
-#include	"fns.h"
-
-char *premature = "premature EOF\n";
-
-/*
- *  read in a segment
- */
-static long
-readseg(int dev, long (*read)(int, void*, long), long len, long addr)
-{
-	char *a;
-	long n, sofar;
-
-	a = (char *)addr;
-	for(sofar = 0; sofar < len; sofar += n){
-		n = 8*1024;
-		if(len - sofar < n)
-			n = len - sofar;
-		n = (*read)(dev, a + sofar, n);
-		if(n <= 0)
-			break;
-		print(".");
-	}
-	return sofar;
-}
-
-/*
- *  boot
- */
-int
-plan9boot(int dev, long (*seek)(int, long), long (*read)(int, void*, long))
-{
-	long n;
-	long addr;
-	void (*b)(void);
-	Exec *ep;
-
-	if((*seek)(dev, 0) < 0)
-		return -1;
-
-	/*
-	 *  read header
-	 */
-	ep = (Exec *) ialloc(sizeof(Exec), 0);
-	n = sizeof(Exec);
-	if(readseg(dev, read, n, (long) ep) != n){
-		print(premature);
-		return -1;
-	}
-	if(GLLONG(ep->magic) != Q_MAGIC){
-		print("bad magic 0x%lux not a plan 9 executable!\n", GLLONG(ep->magic));
-		return -1;
-	}
-
-	/*
-	 *  read text
-	 */
-	addr = PADDR(GLLONG(ep->entry));
-	n = GLLONG(ep->text);
-	print("%d", n);
-	if(readseg(dev, read, n, addr) != n){
-		print(premature);
-		return -1;
-	}
-
-	/*
-	 *  read data (starts at first page after kernel)
-	 */
-	addr = PGROUND(addr+n);
-	n = GLLONG(ep->data);
-	print("+%d@%8.8lux", n, addr);
-	if(readseg(dev, read, n, addr) != n){
-		print(premature);
-		return -1;
-	}
-
-	/*
-	 *  bss and entry point
-	 */
-	print("+%d\nstart at 0x%lux\n", GLLONG(ep->bss), GLLONG(ep->entry));
-	uartwait();
-	scc2stop();
-	splhi();
-
-	/*
-	 *  Go to new code. It's up to the program to get its PC relocated to
-	 *  the right place.
-	 */
-	b = (void (*)(void))(PADDR(GLLONG(ep->entry)));
-	(*b)();
-	return 0;
-}
--- a/os/boot/mpc/qio.c
+++ /dev/null
@@ -1,128 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-struct Queue {
-	Block*	first;
-	Block*	last;
-	void	(*kick)(void*);
-	void*	arg;
-	long	len;
-};
-
-Block *
-iallocb(int n)
-{
-	Block *b;
-
-	b = (Block*)malloc(sizeof(Block)+n);
-	b->data = (uchar*)b + sizeof(Block);
-	b->rp = b->wp = b->data;
-	b->lim = b->data + n;
-	b->next = 0;
-	b->magic = 0xcafebee0;
-	return b;
-}
-
-void
-freeb(Block *b)
-{
-	if(b){
-		if(b->magic != 0xcafebee0)
-			panic("freeb");
-		b->magic = 0;
-		b->next = (Block*)0xdeadbabe;
-		free(b);
-	}
-}
-
-Queue *
-qopen(int limit, int msg, void (*kick)(void*), void *arg)
-{
-	Queue *q;
-
-	USED(limit, msg);
-	q = (Queue*)malloc(sizeof(Queue));
-	q->first = q->last = 0;
-	q->kick = kick;
-	q->arg = arg;
-	q->len = 0;
-	return q;
-}
-
-Block *
-qget(Queue *q)
-{
-	int s;
-	Block *b;
-
-	s = splhi();
-	if((b = q->first) != 0){
-		q->first = b->next;
-		b->next = 0;
-		q->len -= BLEN(b);
-		if(q->len < 0)
-			panic("qget");
-	}
-	splx(s);
-	return b;
-}
-
-void
-qbwrite(Queue *q, Block *b)
-{
-	int s;
-
-	s = splhi();
-	b->next = 0;
-	if(q->first == 0)
-		q->first = b;
-	else
-		q->last->next = b;
-	q->last = b;
-	q->len += BLEN(b);
-	splx(s);
-	if(q->kick)
-		q->kick(q->arg);
-}
-
-long
-qlen(Queue *q)
-{
-	return q->len;
-}
-
-int
-qbgetc(Queue *q)
-{
-	Block *b;
-	int s, c;
-
-	c = -1;
-	s = splhi();
-	while(c < 0 && (b = q->first) != nil){
-		if(b->rp < b->wp){
-			c = *b->rp++;
-			q->len--;
-		}
-		if(b->rp >= b->wp){
-			q->first = b->next;
-			b->next = nil;
-		}
-	}
-	splx(s);
-	return c;
-}
-
-void
-qbputc(Queue *q, int c)
-{
-	Block *b;
-
-	b = iallocb(1);
-	*b->wp++ = c;
-	qbwrite(q, b);
-}
--- a/os/boot/mpc/rmap.c
+++ /dev/null
@@ -1,104 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-
-void
-mapinit(RMap *rmap, Map *map, int size)
-{
-	lock(rmap);
-	rmap->map = map;
-	rmap->mapend = map+(size/sizeof(Map));
-	unlock(rmap);
-}
-
-void
-mapfree(RMap* rmap, ulong addr, int size)
-{
-	Map *mp;
-	ulong t;
-
-	if(size <= 0)
-		return;
-
-	lock(rmap);
-	for(mp = rmap->map; mp->addr <= addr && mp->size; mp++)
-		;
-
-	if(mp > rmap->map && (mp-1)->addr+(mp-1)->size == addr){
-		(mp-1)->size += size;
-		if(addr+size == mp->addr){
-			(mp-1)->size += mp->size;
-			while(mp->size){
-				mp++;
-				(mp-1)->addr = mp->addr;
-				(mp-1)->size = mp->size;
-			}
-		}
-	}
-	else{
-		if(addr+size == mp->addr && mp->size){
-			mp->addr -= size;
-			mp->size += size;
-		}
-		else do{
-			if(mp >= rmap->mapend){
-				print("mapfree: %s: losing 0x%uX, %d\n",
-					rmap->name, addr, size);
-				break;
-			}
-			t = mp->addr;
-			mp->addr = addr;
-			addr = t;
-			t = mp->size;
-			mp->size = size;
-			mp++;
-		}while(size = t);
-	}
-	unlock(rmap);
-}
-
-ulong
-mapalloc(RMap* rmap, ulong addr, int size, int align)
-{
-	Map *mp;
-	ulong maddr, oaddr;
-
-	lock(rmap);
-	for(mp = rmap->map; mp->size; mp++){
-		maddr = mp->addr;
-
-		if(addr){
-			if(maddr > addr)
-				continue;
-			if(addr+size > maddr+mp->size)
-				break;
-			maddr = addr;
-		}
-
-		if(align > 0)
-			maddr = ((maddr+align-1)/align)*align;
-		if(mp->addr+mp->size-maddr < size)
-			continue;
-
-		oaddr = mp->addr;
-		mp->addr = maddr+size;
-		mp->size -= maddr-oaddr+size;
-		if(mp->size == 0){
-			do{
-				mp++;
-				(mp-1)->addr = mp->addr;
-			}while((mp-1)->size = mp->size);
-		}
-
-		unlock(rmap);
-		if(oaddr != maddr)
-			mapfree(rmap, oaddr, maddr-oaddr);
-
-		return maddr;
-	}
-	unlock(rmap);
-
-	return 0;
-}
--- a/os/boot/mpc/screen.c
+++ /dev/null
@@ -1,242 +1,0 @@
-#include	"all.h"
-#include	<libg.h>
-#include	<gnot.h>
-
-enum {
-	Colldepth		= 3,
-	Colmaxx		= 640,
-	Colmaxxvis	= 640,
-	Colmaxy		= 480,
-};
-
-#define	MINX	8
-
-extern	GSubfont	defont0;
-
-struct{
-	Point	pos;
-	int	bwid;
-}out;
-
-typedef struct Mode Mode;
-struct Mode {
-	int	x;
-	int	y;
-	int	d;
-	char*	aperture;
-	int	apsize;
-};
-
-GBitmap	gscreen;
-Point	gchar(GBitmap*, Point, GFont*, int, Fcode);
-int	setcolor(ulong, ulong, ulong, ulong);
-static	void	lcdinit(Mode*);
-
-void
-screeninit(void)
-{
-	Mode m;
-
-	m.x = Colmaxx;
-	m.y = Colmaxy;
-	m.d = Colldepth;
-	m.aperture = 0;
-	lcdinit(&m);
-	if(m.aperture == 0)
-		return;
-	gscreen.ldepth = 3;
-	gscreen.base = (ulong*)m.aperture;
-	gscreen.width = Colmaxx/BY2WD;
-	gscreen.r = Rect(0, 0, Colmaxxvis, Colmaxy);
-	gscreen.clipr = gscreen.r;
-	/*
-	 * For now, just use a fixed colormap:
-	 * 0 == white and 255 == black
-	 */
-	setcolor(0, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF);
-	setcolor(255, 0x00000000, 0x00000000, 0x00000000);
-
-	gbitblt(&gscreen, Pt(0, 0), &gscreen, gscreen.r, Zero);
-	out.pos.x = MINX;
-	out.pos.y = 0;
-	out.bwid = defont0.info[' '].width;
-}
-
-void
-screenputc(int c)
-{
-	Fontchar *i;
-	Point p;
-
-	if(gscreen.base == nil)
-		return;
-	switch(c){
-	case '\n':
-		out.pos.x = MINX;
-		out.pos.y += defont0.height;
-		if(out.pos.y > gscreen.r.max.y-defont0.height)
-			out.pos.y = gscreen.r.min.y;
-		gbitblt(&gscreen, Pt(0, out.pos.y), &gscreen,
-		  Rect(0, out.pos.y, gscreen.r.max.x, out.pos.y+2*defont0.height),
-		  Zero);
-		break;
-	case '\t':
-		out.pos.x += (8-((out.pos.x-MINX)/out.bwid&7))*out.bwid;
-		if(out.pos.x >= gscreen.r.max.x)
-			screenputc('\n');
-		break;
-	case '\b':
-		if(out.pos.x >= out.bwid+MINX){
-			out.pos.x -= out.bwid;
-			screenputc(' ');
-			out.pos.x -= out.bwid;
-		}
-		break;
-	default:
-		if(out.pos.x >= gscreen.r.max.x-out.bwid)
-			screenputc('\n');
-		c &= 0x7f;
-		if(c <= 0 || c >= defont0.n)
-			break;
-		i = defont0.info + c;
-		p = out.pos;
-		gbitblt(&gscreen, Pt(p.x+i->left, p.y), defont0.bits,
-			Rect(i[0].x, 0, i[1].x, defont0.height),
-			S);
-		out.pos.x = p.x + i->width;
-		break;
-	}
-}
-
-void
-screenputs(char *s, int n)
-{
-	while(n-- > 0)
-		screenputc(*s++);
-}
-
-/*
- * See section 5.2.1 (page 5-6) of the MPC823 manual
- */
-static uchar lcdclock[17] = {	/* (a<<2)|b => divisor of (1<<a)*((b<<1)+1) */
-	0, 0, (1<<2), 1,
-	(2<<2), 2, (1<<2)|1, 3,
-	(3<<2), (1<<2)|2, (1<<2)|2, (2<<2)|1,
-	(2<<2)|1, (1<<2)|3, (1<<2)|3, (4<<2),
-	(4<<2)
-};
-	
-/*
- * support for the Sharp LQ64D341 TFT colour display
- */
-
-enum {
-	COLS = 640,
-	ROWS = 480,
-	LDEPTH = 3,	/* screen depth */
-	LCDFREQ = 25000000,
-
-	/* lccr */
-	ClockLow = 1<<11,
-	OELow = 1<<10,
-	HsyncLow = 1<<9,
-	VsyncLow = 1<<8,
-	DataLow = 1<<7,
-	Passive8 = 1<<4,
-	DualScan = 1<<3,
-	IsColour = 1<<2,
-	IsTFT = 1<<1,
-	Enable = 1<<0,
-
-	/* lchcr */
-	BigEndian = 1<<24,
-	AT7 = 7<<21,	/* access type */
-
-	/* sdcr */
-	LAM = 1<<6,	/* ``LCD aggressive mode'' */
-};
-
-/*
- * TO DO: most of the data could come from a table
- */
-static void
-lcdinit(Mode *mode)
-{
-	IMM *io;
-	int i, d;
-	long hz;
-
-	io = m->iomem;
-	mode->y = ROWS;
-	mode->x = COLS;
-	mode->d = LDEPTH;
-	mode->aperture = ialloc(mode->x*mode->y, 16);
-	mode->apsize = mode->x*mode->y;
-
-	io->sdcr &= ~LAM;	/* MPC823 errata: turn off LAM before disabling controller */
-	io->lcfaa = PADDR(mode->aperture);
-	io->lccr = (((mode->x*mode->y*(1<<LDEPTH)+127)/128) << 17) | (LDEPTH << 5) | IsColour | IsTFT | OELow | VsyncLow | ClockLow;
-
-	switch(LDEPTH){
-	default:
-	case 0:
-		/* monochrome/greyscale identity map */
-		for(i=0; i<16; i++)
-			io->lcdmap[i] = i;
-		break;
-	case 2:
-		/* 4-bit grey scale map */
-		for(i=0; i<16; i++)
-			io->lcdmap[0] = (i<<8)|(i<<4)|i;
-		break;
-	case 3:
-		/* 8-bit linear map */
-		for(i=0; i<256; i++)
-			io->lcdmap[i] = (i<<8)|(i<<4)|i;
-		break;
-	}
-
-	io->lcvcr = (mode->y << 11) | (1<<28) | 33;	/* 2 line vsync pulse, 34 line wait between frames */
-	io->lchcr = (mode->x<<10) | BigEndian | 228;	/* clock cycles between lines */
-
-	hz = m->cpuhz;
-	d = hz/LCDFREQ;
-	if(hz/d > LCDFREQ)
-		d++;
-	if(d >= 16)
-		d = 16;
-
-	/*
-	 * enable LCD outputs
-	 */
-	io->pddat = 0;
-	io->pdpar = 0x1fff;
-io->pdpar &= ~SIBIT(6);	/* 823 bug fix? */
-	io->pddir = 0x1fff;
-	io->pbpar |= IBIT(31) | IBIT(19) | IBIT(17);
-	io->pbdir |= IBIT(31) | IBIT(19) | IBIT(17);
-	io->pbodr &= ~(IBIT(31) | IBIT(19) | IBIT(17));
-
-	eieio();
-	io->sccrk = KEEP_ALIVE_KEY;
-	eieio();
-	io->sccr  = (io->sccr & ~0x1F) | lcdclock[d];
-	eieio();
-	io->sccrk = ~KEEP_ALIVE_KEY;
-	eieio();
-	gscreen.width = gscreen.width;	/* access external memory before enabling (mpc823 errata) */
-	io->lcsr = 7;	/* clear status */
-	eieio();
-	io->lccr |= Enable;
-	archbacklight(1);
-}
-
-int
-setcolor(ulong p, ulong r, ulong g, ulong b)
-{
-	r >>= 28;
-	g >>= 28;
-	b >>= 28;
-	m->iomem->lcdmap[~p&0xFF] = (r<<8) | (g<<4) | b;	/* TO DO: it's a function of the ldepth */
-	return 1;
-}
--- a/os/boot/mpc/sload.c
+++ /dev/null
@@ -1,71 +1,0 @@
-/*
- * send S records to rpcg
- */
-
-#include <u.h>
-#include <libc.h>
-#include <bio.h>
-
-static	int	dbg;
-static	char	buf[2048];
-static	int	run=1;
-static	void	stuffbym(char*, int, int);
-static	void	getdot(void);
-
-void
-main(int argc, char **argv)
-{
-	int n;
-	char *l;
-	Biobuf *f;
-	static int p;
-
-	ARGBEGIN{
-	case 'd': dbg++; break;
-	case 'n': run=0; break;
-	}ARGEND
-
-	f = Bopen(*argv? *argv: "k.mx", OREAD);
-	if(f == 0) {
-		fprint(2, "sload: cannot open k.mx: %r\n");
-		exits("sload");
-	}
-	getdot();
-	while((l = Brdline(f, '\n')) != 0) {
-		l[Blinelen(f)-1] = '\r';
-		stuffbym(l, Blinelen(f), 16);
-		getdot();
-		if(++p % 25 == 0)
-			write(2, ".", 1);
-	}
-	exits(0);
-}
-
-static void
-stuffbym(char *l, int n, int m)
-{
-	int nr, ns;
-
-	while(n > 0) {
-		ns = n;
-		if(ns > m)
-			ns = m;
-		write(1, l, ns);
-		l += ns;
-		n -= ns;
-	}
-}
-
-static void
-getdot(void)
-{
-	char c;
-
-	for(;;){
-		if(read(0, &c, 1) != 1)
-			exits("bang");
-		write(2, &c, 1);
-		if(c == '.')
-			break;
-	}
-}
--- a/os/boot/mpc/squeeze.h
+++ /dev/null
@@ -1,34 +1,0 @@
-
-/*
- * squeezed file format:
- *	Sqhdr
- *	original Exec header
- *	two Squeeze tables
- *	squeezed segment
- *	unsqueezed segment, if any
- */
-#define	SQMAGIC	(ulong)0xFEEF0F1E
-
-typedef struct Sqhdr Sqhdr;
-struct Sqhdr {
-	uchar	magic[4];	/* SQMAGIC */
-	uchar	text[4];	/* squeezed length of text (excluding tables) */
-	uchar	data[4];	/* squeezed length of data (excluding tables) */
-	uchar	asis[4];	/* length of unsqueezed segment */
-	uchar	toptxt[4];	/* value for 0 encoding in text */
-	uchar	topdat[4];	/* value for 0 encoding in data */
-	uchar	sum[4];	/* simple checksum of unsqueezed data */
-	uchar	flags[4];
-};
-#define	SQHDRLEN	(8*4)
-
-/*
- * certain power instruction types are rearranged by sqz
- * so as to move the variable part of the instruction word to the
- * low order bits.  note that the mapping is its own inverse.
- */
-#define	QREMAP(X)\
-	switch((X)>>26){\
-	case 19: case 31: case 59: case 63:\
-		(X) = (((X) & 0xFC00F801) | (((X)>>15)&0x7FE) | (((X)&0x7FE)<<15));\
-	}
--- a/os/boot/mpc/trap.c
+++ /dev/null
@@ -1,233 +1,0 @@
-#include "boot.h"
-
-enum 
-{
-	Maxhandler=	32+16,		/* max number of interrupt handlers */
-};
-
-typedef struct Handler	Handler;
-struct Handler
-{
-	void	(*r)(Ureg*, void*);
-	void	*arg;
-	Handler	*next;
-	int	edge;
-};
-
-struct
-{
-	Handler	*ivec[128];
-	Handler	h[Maxhandler];
-	int	free;
-} halloc;
-
-char	*excname[] = {
-	"reserved 0",
-	"system reset",
-	"machine check",
-	"data access",
-	"instruction access",
-	"external interrupt",
-	"alignment",
-	"program exception",
-	"floating-point unavailable",
-	"decrementer",
-	"reserved A",
-	"reserved B",
-	"system call",
-	"trace trap",
-	"floating point assist",
-	"reserved F",
-	"software emulation",
-	"ITLB miss",
-	"DTLB miss",
-	"ITLB error",
-	"DTLB error",
-};
-
-char *regname[]={
-	"CAUSE",	"SRR1",
-	"PC",		"GOK",
-	"LR",		"CR",
-	"XER",	"CTR",
-	"R0",		"R1",
-	"R2",		"R3",
-	"R4",		"R5",
-	"R6",		"R7",
-	"R8",		"R9",
-	"R10",	"R11",
-	"R12",	"R13",
-	"R14",	"R15",
-	"R16",	"R17",
-	"R18",	"R19",
-	"R20",	"R21",
-	"R22",	"R23",
-	"R24",	"R25",
-	"R26",	"R27",
-	"R28",	"R29",
-	"R30",	"R31",
-};
-
-static	void	intr(Ureg*);
-
-void
-sethvec(int v, void (*r)(void))
-{
-	ulong *vp, pa, o;
-
-	if((ulong)r & 3)
-		panic("sethvec");
-	vp = (ulong*)KADDR(v);
-	vp[0] = 0x7c1043a6;	/* MOVW R0, SPR(SPRG0) */
-	vp[1] = 0x7c0802a6;	/* MOVW LR, R0 */
-	vp[2] = 0x7c1243a6;	/* MOVW R0, SPR(SPRG2) */
-	pa = PADDR(r);
-	o = pa >> 25;
-	if(o != 0 && o != 0x7F){
-		/* a branch too far: running from ROM */
-		vp[3] = (15<<26)|(pa>>16);	/* MOVW $r&~0xFFFF, R0 */
-		vp[4] = (24<<26)|(pa&0xFFFF);	/* OR $r&0xFFFF, R0 */
-		vp[5] = 0x7c0803a6;	/* MOVW	R0, LR */
-		vp[6] = 0x4e800021;	/* BL (LR) */
-	}else
-		vp[3] = (18<<26)|(pa&0x3FFFFFC)|3;	/* bla */
-}
-
-#define	LEV(n)	(((n)<<1)|1)
-#define	IRQ(n)	(((n)<<1)|0)
-
-void
-setvec(int v, void (*r)(Ureg*, void*), void *arg)
-{
-	Handler *h;
-	IMM *io;
-
-	if(halloc.free >= Maxhandler)
-		panic("out of interrupt handlers");
-	v -= VectorPIC;
-	h = &halloc.h[halloc.free++];
-	h->next = halloc.ivec[v];
-	h->r = r;
-	h->arg = arg;
-	halloc.ivec[v] = h;
-
-	/*
-	 * enable corresponding interrupt in SIU/CPM
-	 */
-
-	io = m->iomem;
-	if(v >= VectorCPIC){
-		v -= VectorCPIC;
-		io->cimr |= 1<<(v&0x1F);
-	}
-	else if(v >= VectorIRQ)
-		io->simask |= 1<<(31-IRQ(v&7));
-	else
-		io->simask |= 1<<(31-LEV(v));
-}
-
-void
-trapinit(void)
-{
-	int i;
-	IMM *io;
-
-	io = m->iomem;
-	io->sypcr &= ~(3<<2);	/* disable watchdog (821/823) */
-	io->simask = 0;	/* mask all */
-	io->siel = ~0;	/* edge sensitive, wake on all */
-	io->cicr = 0;	/* disable CPM interrupts */
-	io->cipr = ~0;	/* clear all interrupts */
-	io->cimr = 0;	/* mask all events */
-	io->cicr = (0xE1<<16)|(CPIClevel<<13)|(0x1F<<8);
-	io->cicr |= 1 << 7;	/* enable */
-	io->tbscrk = KEEP_ALIVE_KEY;
-	io->tbscr = 1;	/* TBE */
-	io->simask |= 1<<(31-LEV(CPIClevel));	/* CPM's level */
-	io->tbk = KEEP_ALIVE_KEY;
-	eieio();
-	putdec(~0);
-
-	/*
-	 * set all exceptions to trap
-	 */
-	for(i = 0x0; i < 0x3000; i += 0x100)
-		sethvec(i, exception);
-}
-
-void
-dumpregs(Ureg *ur)
-{
-	int i;
-	ulong *l;
-	l = &ur->cause;
-	for(i=0; i<sizeof regname/sizeof(char*); i+=2, l+=2)
-		print("%s\t%.8lux\t%s\t%.8lux\n", regname[i], l[0], regname[i+1], l[1]);
-}
-
-void
-trap(Ureg *ur)
-{
-	int c;
-
-	c = ur->cause >> 8;
-	switch(c){
-	default:
-		{extern int predawn; predawn = 1;}
-		if(c < 0 || c >= nelem(excname))
-			print("exception/interrupt #%x\n", c);
-		else
-			print("exception %s\n", excname[c]);
-		dumpregs(ur);
-		/* spllo(); */
-		print("^P to reset\n");
-		for(;;)
-			;
-
-	case 0x09:	/* decrementer */
-		clockintr(ur, 0);
-		return;
-
-	case 0x05:	/* external interrupt */
-		intr(ur);
-		break;
-	}
-}
-
-static void
-intr(Ureg *ur)
-{
-	int b, v;
-	Handler *h;
-	IMM *io;
-
-	io = m->iomem;
-	b = io->sivec>>2;
-	v = b>>1;
-	if(b & 1) {
-		if(v == CPIClevel){
-			io->civr = 1;
-			eieio();
-			v = VectorCPIC+(io->civr>>11);
-		}
-	}else
-		v += VectorIRQ;
-	h = halloc.ivec[v];
-	if(h == nil){
-		for(;;)
-			;
-		//print("unknown interrupt %d pc=0x%lux\n", v, ur->pc);
-		return;
-	}
-	if(h->edge)
-		io->sipend |= 1<<(31-b);
-	/*
-	 *  call the interrupt handlers
-	 */
-	do {
-		(*h->r)(ur, h->arg);
-		h = h->next;
-	} while(h != nil);
-	if(v >= VectorCPIC)
-		io->cisr |= 1<<(v-VectorCPIC);
-}
--- a/os/boot/mpc/uartboot.c
+++ /dev/null
@@ -1,189 +1,0 @@
-#include "boot.h"
-
-/*
- * this doesn't yet use the crc
- */
-
-typedef struct Uboot Uboot;
-struct Uboot {
-	Queue*	iq;
-	Block*	partial;
-	ulong	csum;
-	long	bno;
-	uchar	buf[64];
-	int	nleft;
-	int	ntimeout;
-};
-
-static	Uboot	uboot;
-ulong	crc32(void *buf, int n, ulong crc);
-
-static void
-uartbrecv(uchar *p, int n)
-{
-	Uboot *ub;
-	Block *b;
-
-	ub = &uboot;
-	if(n > 0 && ub->iq != nil){
-		b = iallocb(n);
-		memmove(b->wp, p, n);
-		b->wp += n;
-		qbwrite(ub->iq, b);
-	}
-}
-
-int
-uartinit(void)
-{
-	return 1<<0;
-}
-
-Partition*
-setuartpart(int, char *s)
-{
-	static Partition pp[1];
-
-	if(strcmp(s, "boot") != 0 && strcmp(s, "disk") != 0)
-		return 0;
-	pp[0].start = 0;
-	pp[0].end = 2*1024*1024;
-	strcpy(pp[0].name, "boot");
-	return pp;
-}
-
-long
-uartseek(int, long)
-{
-	/* start the boot */
-	if(uboot.iq == nil)
-		uboot.iq = qopen(64*1024, 0, 0, 0);
-	if(uboot.partial){
-		freeb(uboot.partial);
-		uboot.partial = 0;
-	}
-	print("uart: start transmission\n");
-	uartsetboot(uartbrecv);
-	uboot.csum = ~0;
-	uboot.bno = 0;
-	uboot.nleft = 0;
-	uboot.ntimeout = 0;
-	return 0;
-}
-
-static long
-uartreadn(void *buf, int nb)
-{
-	ulong start;
-	Uboot *ub;
-	int l;
-	Block *b;
-	uchar *p;
-
-	p = buf;
-	ub = &uboot;
-	start = m->ticks;
-	while(nb > 0){
-		b = ub->partial;
-		ub->partial = nil;
-		if(b == nil){
-			ub->ntimeout = 0;
-			while((b = qget(ub->iq)) == 0){
-				if(TK2MS(m->ticks - start) >= 15*1000){
-					if(++ub->ntimeout >= 3){
-						print("uart: timeout\n");
-						return 0;
-					}
-					uartputs("n", 1);
-				}
-			}
-		}
-		l = BLEN(b);
-		if(l > nb)
-			l = nb;
-		memmove(p, b->rp, l);
-		b->rp += l;
-		if(b->rp >= b->wp)
-			freeb(b);
-		else
-			ub->partial = b;
-		nb -= l;
-		p += l;
-	}
-	return p-(uchar*)buf;
-}
-
-long
-uartread(int, void *buf, long n)
-{
-	uchar *p;
-	int l;
-	static uchar lbuf[64];
-
-	p = buf;
-	if((l = uboot.nleft) > 0){
-		if(l > n)
-			l = n;
-		uboot.nleft -= l;
-		memmove(p, uboot.buf, l);
-		p += l;
-		n -= l;
-	}
-	while(n > 0){
-		l = uartreadn(lbuf, sizeof(lbuf));
-		if(l < sizeof(lbuf))
-			return 0;
-		if(l > n){
-			uboot.nleft = l-n;
-			memmove(uboot.buf, lbuf+n, uboot.nleft);
-			l = n;
-		}
-		memmove(p, lbuf, l);
-		n -= l;
-		p += l;
-		uboot.bno++;
-		uartputs("y", 1);
-	}
-	return p-(uchar*)buf;
-}
-
-/*
- * from Rob Warnock
- */
-static	ulong	crc32tab[256];	/* initialised on first call to crc32 */
-
-enum {
-	CRC32POLY = 0x04c11db7     /* AUTODIN II, Ethernet, & FDDI */
-};
-
-/*
- * Build auxiliary table for parallel byte-at-a-time CRC-32.
- */
-static void
-initcrc32(void)
-{
-	int i, j;
-	ulong c;
-
-	for(i = 0; i < 256; i++) {
-		for(c = i << 24, j = 8; j > 0; j--)
-			if(c & (1<<31))
-				c = (c<<1) ^ CRC32POLY;
-			else
-				c <<= 1;
-		crc32tab[i] = c;
-	}
-}
-
-ulong
-crc32(void *buf, int n, ulong crc)
-{
-	uchar *p;
-
-	if(crc32tab[1] == 0)
-		initcrc32();
-	crc = ~crc;
-	for(p = buf; --n >= 0;)
-		crc = (crc << 8) ^ crc32tab[(crc >> 24) ^ *p++];
-	return ~crc;
-}
--- a/os/boot/mpc/ureg.h
+++ /dev/null
@@ -1,43 +1,0 @@
-struct Ureg
-{
-	ulong	cause;
-	union { ulong	srr1; ulong status;};
-	ulong	pc;	/* SRR0 */
-	ulong	pad;
-	ulong	lr;
-	ulong	cr;
-	ulong	xer;
-	ulong	ctr;
-	ulong	r0;
-	union{ ulong r1;	ulong	sp;	ulong	usp; };
-	ulong	r2;
-	ulong	r3;
-	ulong	r4;
-	ulong	r5;
-	ulong	r6;
-	ulong	r7;
-	ulong	r8;
-	ulong	r9;
-	ulong	r10;
-	ulong	r11;
-	ulong	r12;
-	ulong	r13;
-	ulong	r14;
-	ulong	r15;
-	ulong	r16;
-	ulong	r17;
-	ulong	r18;
-	ulong	r19;
-	ulong	r20;
-	ulong	r21;
-	ulong	r22;
-	ulong	r23;
-	ulong	r24;
-	ulong	r25;
-	ulong	r26;
-	ulong	r27;
-	ulong	r28;
-	ulong	r29;
-	ulong	r30;
-	ulong	r31;
-};
--- a/os/boot/mpc/zqs.c
+++ /dev/null
@@ -1,234 +1,0 @@
-#include "boot.h"
-#include "squeeze.h"
-
-/*
- * for details of `unsqueeze' see:
- *
- * %A Mark Taunton
- * %T Compressed Executables: An Exercise in Thinking Small
- * %P 385-404
- * %I USENIX
- * %B USENIX Conference Proceedings
- * %D Summer 1991
- * %C Nashville, TN
- *
- * several of the unimplemented improvements described in the paper
- * have been implemented here
- *
- * there is a further transformation on the powerpc (QFLAG!=0) to shuffle bits
- * in certain instructions so as to push the fixed bits to the top of the word.
- */
-
-#define	EXECHDRLEN	(8*4)
-
-typedef struct Squeeze Squeeze;
-struct Squeeze {
-	int	n;
-	ulong	tab[7*256];
-};
-
-#define	GET4(p)	(((((((p)[0]<<8)|(p)[1])<<8)|(p)[2])<<8)|(p)[3])
-
-/*
- * for speed of unsqueezing from Flash, certain checks are
- * not done inside the loop (as they would be in the unsqueeze program zqs),
- * but instead the checksum is expected to catch corrupted files.
- * in fact the Squeeze array bounds can't be exceeded in practice
- * because the tables are always full for a squeezed kernel.
- */
-enum {
-	QFLAG = 1,	/* invert powerpc-specific code transformation */
-	CHECK = 0,	/* check precise bounds in Squeeze array (otherwise checksum detects error) */
-};
-
-static	ulong	chksum;
-static	int	rdtab(Block*, Squeeze*, int);
-static	ulong*	unsqueeze(ulong*, uchar*, uchar*, Squeeze*, Squeeze*, ulong);
-static	uchar*	unsqzseg(uchar*, Block*, long, long, char*);
-static	Alarm*	unsqzal;
-
-int
-issqueezed(uchar *b)
-{
-	return GET4(b) == SQMAGIC? GET4(b+SQHDRLEN): 0;
-}
-
-static void
-unsqzdot(Alarm*)
-{
-	unsqzal = alarm(500, unsqzdot, nil);
-	print(".");
-}
-
-long
-unsqueezef(Block *b, ulong *entryp)
-{
-	uchar *loada, *wp;
-	ulong toptxt, topdat, oldsum;
-	long asis, nst, nsd;
-	Sqhdr *sqh;
-	Exec *ex;
-
-	if(BLEN(b) < SQHDRLEN+EXECHDRLEN)
-		return -1;
-	sqh = (Sqhdr*)b->rp;
-	if(GET4(sqh->magic) != SQMAGIC)
-		return -1;
-	chksum = 0;
-	toptxt = GET4(sqh->toptxt);
-	topdat = GET4(sqh->topdat);
-	oldsum = GET4(sqh->sum);
-	asis = GET4(sqh->asis);
-	nst = GET4(sqh->text);
-	nsd = GET4(sqh->data);
-	b->rp += SQHDRLEN;
-	ex = (Exec*)b->rp;
-	if(GET4(ex->magic) != Q_MAGIC){
-		print("zqs: not powerPC executable\n");
-		return -1;
-	}
-	*entryp = GET4(ex->entry);
-	b->rp += EXECHDRLEN;
-	loada = KADDR(PADDR(*entryp));
-	wp = unsqzseg(loada, b, nst, toptxt, "text");
-	if(wp == nil){
-		print("zqs: format error\n");
-		return -1;
-	}
-	if(nsd){
-		wp = (uchar*)PGROUND((ulong)wp);
-		wp = unsqzseg(wp, b, nsd, topdat, "data");
-		if(wp == nil){
-			print("zqs: format error\n");
-			return -1;
-		}
-	}
-	if(asis){
-		memmove(wp, b->rp, asis);
-		wp += asis;
-		b->rp += asis;
-	}
-	if(chksum != oldsum){
-		print("\nsqueezed kernel: checksum error: %8.8lux need %8.8lux\n", chksum, oldsum);
-		return -1;
-	}
-	return wp-loada;
-}
-
-static uchar *
-unsqzseg(uchar *wp, Block *b, long ns, long top, char *what)
-{
-	static Squeeze sq3, sq4;
-
-	print("unpack %s %8.8lux %lud:", what, wp, ns);
-	if(ns == 0)
-		return wp;
-	if(rdtab(b, &sq3, 0) < 0)
-		return nil;
-	if(rdtab(b, &sq4, 8) < 0)
-		return nil;
-	if(BLEN(b) < ns){
-		print(" **size error\n");
-		return nil;
-	}
-	unsqzal = alarm(500, unsqzdot, nil);
-	wp = (uchar*)unsqueeze((ulong*)wp, b->rp, b->rp+ns, &sq3, &sq4, top);
-	cancel(unsqzal);
-	unsqzal = nil;
-	print("\n");
-	if(wp == nil){
-		print("zqs: corrupt squeezed data stream\n");
-		return nil;
-	}
-	b->rp += ns;
-	return wp;
-}
-
-static ulong*
-unsqueeze(ulong *wp, uchar *rp, uchar *ep, Squeeze *sq3, Squeeze *sq4, ulong top)
-{
-	ulong nx, csum;
-	int code, n;
-
-	if(QFLAG){
-		QREMAP(top);	/* adjust top just once, outside the loop */
-	}
-	csum = chksum;
-	while(rp < ep){
-		/* no function calls within this loop for speed */
-		code = *rp;
-		rp++;
-		n = 0;
-		nx = code>>4;
-		do{
-			if(nx == 0){
-				nx = top;
-			}else{
-				if(nx==1){
-					nx = (((((rp[3]<<8)|rp[2])<<8)|rp[1])<<8)|rp[0];
-					rp += 4;
-				}else if(nx <= 8){	/* 2 to 8 */
-					nx = ((nx-2)<<8) | rp[0];
-					if(CHECK && nx >= sq4->n)
-						return nil;	/* corrupted file */
-					nx = sq4->tab[nx] | rp[1];
-					rp += 2;
-				}else{	/* 9 to 15 */
-					nx = ((nx-9)<<8) | rp[0];
-					if(CHECK && nx >= sq3->n)
-						return nil;	/* corrupted file */
-					nx = sq3->tab[nx];
-					rp++;
-				}
-				if(rp > ep)
-					return nil;	/* corrupted file */
-				if(QFLAG){
-					QREMAP(nx);
-				}
-			}
-			*wp = nx;
-			wp++;
-			csum += nx;
-			nx = code & 0xF;
-		}while(++n == 1);
-	}
-	chksum = csum;
-	return wp;
-}
-
-static int
-rdtab(Block *b, Squeeze *sq, int shift)
-{
-	uchar *p, *ep;
-	ulong v, w;
-	int i;
-
-	if(BLEN(b) < 2)
-		return -1;
-	i = (b->rp[0]<<8) | b->rp[1];
-	if(1)
-		print(" T%d", i);
-	b->rp += 2;
-	if((i -= 2) > 0){
-		if(BLEN(b) < i)
-			return -1;
-	}
-	sq->n = 0;
-	p = b->rp;
-	ep = b->rp+i;
-	b->rp += i;
-	v = 0;
-	while(p < ep){
-		w = 0;
-		do{
-			if(p >= ep)
-				return -1;
-			w = (w<<7) | (*p & 0x7F);
-		}while(*p++ & 0x80);
-		v += w;
-		if(0)
-			print("%d %8.8lux %8.8lux\n", sq->n, v, w);
-		sq->tab[sq->n++] = v<<shift;
-	}
-	return 0;
-}
--- a/os/boot/pc/8250.c
+++ /dev/null
@@ -1,308 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-/*
- *  INS8250 uart
- */
-enum
-{
-	/*
-	 *  register numbers
-	 */
-	Data=	0,		/* xmit/rcv buffer */
-	Iena=	1,		/* interrupt enable */
-	 Ircv=	(1<<0),		/*  for char rcv'd */
-	 Ixmt=	(1<<1),		/*  for xmit buffer empty */
-	 Irstat=(1<<2),		/*  for change in rcv'er status */
-	 Imstat=(1<<3),		/*  for change in modem status */
-	Istat=	2,		/* interrupt flag (read) */
-	Tctl=	2,		/* test control (write) */
-	Format=	3,		/* byte format */
-	 Bits8=	(3<<0),		/*  8 bits/byte */
-	 Stop2=	(1<<2),		/*  2 stop bits */
-	 Pena=	(1<<3),		/*  generate parity */
-	 Peven=	(1<<4),		/*  even parity */
-	 Pforce=(1<<5),		/*  force parity */
-	 Break=	(1<<6),		/*  generate a break */
-	 Dra=	(1<<7),		/*  address the divisor */
-	Mctl=	4,		/* modem control */
-	 Dtr=	(1<<0),		/*  data terminal ready */
-	 Rts=	(1<<1),		/*  request to send */
-	 Ri=	(1<<2),		/*  ring */
-	 Inton=	(1<<3),		/*  turn on interrupts */
-	 Loop=	(1<<4),		/*  loop back */
-	Lstat=	5,		/* line status */
-	 Inready=(1<<0),	/*  receive buffer full */
-	 Oerror=(1<<1),		/*  receiver overrun */
-	 Perror=(1<<2),		/*  receiver parity error */
-	 Ferror=(1<<3),		/*  rcv framing error */
-	 Outready=(1<<5),	/*  output buffer empty */
-	Mstat=	6,		/* modem status */
-	 Ctsc=	(1<<0),		/*  clear to send changed */
-	 Dsrc=	(1<<1),		/*  data set ready changed */
-	 Rire=	(1<<2),		/*  rising edge of ring indicator */
-	 Dcdc=	(1<<3),		/*  data carrier detect changed */
-	 Cts=	(1<<4),		/*  complement of clear to send line */
-	 Dsr=	(1<<5),		/*  complement of data set ready line */
-	 Ring=	(1<<6),		/*  complement of ring indicator line */
-	 Dcd=	(1<<7),		/*  complement of data carrier detect line */
-	Scratch=7,		/* scratchpad */
-	Dlsb=	0,		/* divisor lsb */
-	Dmsb=	1,		/* divisor msb */
-
-	Serial=	0,
-	Modem=	1,
-};
-
-typedef struct Uart	Uart;
-struct Uart
-{
-	int	port;
-	uchar	sticky[8];	/* sticky write register values */
-	uchar	txbusy;
-
-	void	(*rx)(int);	/* routine to take a received character */
-	int	(*tx)(void);	/* routine to get a character to transmit */
-
-	ulong	frame;
-	ulong	overrun;
-};
-
-static Uart com[2];
-static Uart* uart;
-
-#define UartFREQ 1843200
-
-#define uartwrreg(u,r,v)	outb((u)->port + r, (u)->sticky[r] | (v))
-#define uartrdreg(u,r)		inb((u)->port + r)
-
-/*
- *  set the baud rate by calculating and setting the baudrate
- *  generator constant.  This will work with fairly non-standard
- *  baud rates.
- */
-static void
-uartsetbaud(Uart *up, int rate)
-{
-	ulong brconst;
-
-	brconst = (UartFREQ+8*rate-1)/(16*rate);
-
-	uartwrreg(up, Format, Dra);
-	outb(up->port+Dmsb, (brconst>>8) & 0xff);
-	outb(up->port+Dlsb, brconst & 0xff);
-	uartwrreg(up, Format, 0);
-}
-
-/*
- *  toggle DTR
- */
-static void
-uartdtr(Uart *up, int n)
-{
-	if(n)
-		up->sticky[Mctl] |= Dtr;
-	else
-		up->sticky[Mctl] &= ~Dtr;
-	uartwrreg(up, Mctl, 0);
-}
-
-/*
- *  toggle RTS
- */
-static void
-uartrts(Uart *up, int n)
-{
-	if(n)
-		up->sticky[Mctl] |= Rts;
-	else
-		up->sticky[Mctl] &= ~Rts;
-	uartwrreg(up, Mctl, 0);
-}
-
-static void
-uartintr(Ureg*, void *arg)
-{
-	Uart *up;
-	int ch;
-	int s, l, loops;
-
-	up = arg;
-	for(loops = 0; loops < 1024; loops++){
-		s = uartrdreg(up, Istat);
-		switch(s & 0x3F){
-		case 6:	/* receiver line status */
-			l = uartrdreg(up, Lstat);
-			if(l & Ferror)
-				up->frame++;
-			if(l & Oerror)
-				up->overrun++;
-			break;
-	
-		case 4:	/* received data available */
-		case 12:
-			ch = inb(up->port+Data);
-			if(up->rx)
-				(*up->rx)(ch);
-			break;
-	
-		case 2:	/* transmitter empty */
-			ch = -1;
-			if(up->tx)
-				ch = (*up->tx)();
-			if(ch != -1)
-				outb(up->port+Data, ch);
-			else
-				up->txbusy = 0;
-			break;
-	
-		case 0:	/* modem status */
-			uartrdreg(up, Mstat);
-			break;
-	
-		default:
-			if(s&1)
-				return;
-			print("weird modem interrupt #%2.2ux\n", s);
-			break;
-		}
-	}
-	panic("uartintr: 0x%2.2ux\n", uartrdreg(up, Istat));
-}
-
-/*
- *  turn on a port's interrupts.  set DTR and RTS
- */
-static void
-uartenable(Uart *up)
-{
-	/*
- 	 *  turn on interrupts
-	 */
-	up->sticky[Iena] = 0;
-	if(up->tx)
-		up->sticky[Iena] |= Ixmt;
-	if(up->rx)
-		up->sticky[Iena] |= Ircv|Irstat;
-	uartwrreg(up, Iena, 0);
-
-	/*
-	 *  turn on DTR and RTS
-	 */
-	uartdtr(up, 1);
-	uartrts(up, 1);
-}
-
-static void
-uartdisable(Uart* up)
-{
-	/*
- 	 * Disable interrupts.
-	 */
-	up->sticky[Iena] = 0;
-	uartwrreg(up, Iena, 0);
-	uartdtr(up, 0);
-	uartrts(up, 0);
-}
-
-void
-uartspecial(int port, void (*rx)(int), int (*tx)(void), int baud)
-{
-	Uart *up;
-	int vector;
-
-	switch(port){
-	case 0:
-		port = 0x3F8;
-		vector = VectorUART0;
-		up = &com[0];
-		break;
-	case 1:
-		port = 0x2F8;
-		vector = VectorUART1;
-		up = &com[1];
-		break;
-	default:
-		return;
-	}
-
-	if(uart != nil && uart != up)
-		uartdisable(uart);
-	uart = up;
-
-	if(up->port == 0){
-		up->port = port;
-		setvec(vector, uartintr, up);
-	}
-
-	/*
-	 *  set rate to 9600 baud.
-	 *  8 bits/character.
-	 *  1 stop bit.
-	 *  interrupts enabled.
-	 */
-	uartsetbaud(up, 9600);
-	up->sticky[Format] = Bits8;
-	uartwrreg(up, Format, 0);
-	up->sticky[Mctl] |= Inton;
-	uartwrreg(up, Mctl, 0x0);
-
-	up->rx = rx;
-	up->tx = tx;
-	uartenable(up);
-	if(baud)
-		uartsetbaud(up, baud);
-}
-
-void
-uartputc(int c)
-{
-	int i;
-	Uart *up;
-
-	if((up = uart) == nil)
-		return;
-	for(i = 0; i < 100; i++){
-		if(uartrdreg(up, Lstat) & Outready)
-			break;
-		delay(1);
-	}
-	outb(up->port+Data, c);
-}
-
-void
-uartputs(IOQ *q, char *s, int n)
-{
-	Uart *up;
-	int c, x;
-
-	if((up = uart) == nil)
-		return;
-	while(n--){
-		if(*s == '\n')
-			q->putc(q, '\r');
-		q->putc(q, *s++);
-	}
-	x = splhi();
-	if(up->txbusy == 0 && (c = q->getc(q)) != -1){
-		uartputc(c & 0xFF);
-		up->txbusy = 1;
-	}
-	splx(x);
-}
-
-void
-uartdrain(void)
-{
-	Uart *up;
-	int timeo;
-
-	if((up = uart) == nil)
-		return;
-	for(timeo = 0; timeo < 10000 && up->txbusy; timeo++)
-		delay(1);
-}
--- a/os/boot/pc/LICENCE
+++ /dev/null
@@ -1,237 +1,0 @@
-Lucent Public License Version 1.02
-
-THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS PUBLIC
-LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE
-PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT.
-
-1. DEFINITIONS
-
-"Contribution" means:
-
-  a. in the case of Lucent Technologies Inc. ("LUCENT"), the Original
-     Program, and
-  b. in the case of each Contributor,
-
-     i. changes to the Program, and
-    ii. additions to the Program;
-
-    where such changes and/or additions to the Program were added to the
-    Program by such Contributor itself or anyone acting on such
-    Contributor's behalf, and the Contributor explicitly consents, in
-    accordance with Section 3C, to characterization of the changes and/or
-    additions as Contributions.
-
-"Contributor" means LUCENT and any other entity that has Contributed a
-Contribution to the Program.
-
-"Distributor" means a Recipient that distributes the Program,
-modifications to the Program, or any part thereof.
-
-"Licensed Patents" mean patent claims licensable by a Contributor
-which are necessarily infringed by the use or sale of its Contribution
-alone or when combined with the Program.
-
-"Original Program" means the original version of the software
-accompanying this Agreement as released by LUCENT, including source
-code, object code and documentation, if any.
-
-"Program" means the Original Program and Contributions or any part
-thereof
-
-"Recipient" means anyone who receives the Program under this
-Agreement, including all Contributors.
-
-2. GRANT OF RIGHTS
-
- a. Subject to the terms of this Agreement, each Contributor hereby
-    grants Recipient a non-exclusive, worldwide, royalty-free copyright
-    license to reproduce, prepare derivative works of, publicly display,
-    publicly perform, distribute and sublicense the Contribution of such
-    Contributor, if any, and such derivative works, in source code and
-    object code form.
-    
- b. Subject to the terms of this Agreement, each Contributor hereby
-    grants Recipient a non-exclusive, worldwide, royalty-free patent
-    license under Licensed Patents to make, use, sell, offer to sell,
-    import and otherwise transfer the Contribution of such Contributor, if
-    any, in source code and object code form. The patent license granted
-    by a Contributor shall also apply to the combination of the
-    Contribution of that Contributor and the Program if, at the time the
-    Contribution is added by the Contributor, such addition of the
-    Contribution causes such combination to be covered by the Licensed
-    Patents. The patent license granted by a Contributor shall not apply
-    to (i) any other combinations which include the Contribution, nor to
-    (ii) Contributions of other Contributors. No hardware per se is
-    licensed hereunder.
-    
- c. Recipient understands that although each Contributor grants the
-    licenses to its Contributions set forth herein, no assurances are
-    provided by any Contributor that the Program does not infringe the
-    patent or other intellectual property rights of any other entity. Each
-    Contributor disclaims any liability to Recipient for claims brought by
-    any other entity based on infringement of intellectual property rights
-    or otherwise. As a condition to exercising the rights and licenses
-    granted hereunder, each Recipient hereby assumes sole responsibility
-    to secure any other intellectual property rights needed, if any. For
-    example, if a third party patent license is required to allow
-    Recipient to distribute the Program, it is Recipient's responsibility
-    to acquire that license before distributing the Program.
-
- d. Each Contributor represents that to its knowledge it has sufficient
-    copyright rights in its Contribution, if any, to grant the copyright
-    license set forth in this Agreement.
-
-3. REQUIREMENTS
-
-A. Distributor may choose to distribute the Program in any form under
-this Agreement or under its own license agreement, provided that:
-
- a. it complies with the terms and conditions of this Agreement;
-
- b. if the Program is distributed in source code or other tangible
-    form, a copy of this Agreement or Distributor's own license agreement
-    is included with each copy of the Program; and
-
- c. if distributed under Distributor's own license agreement, such
-    license agreement:
-
-      i. effectively disclaims on behalf of all Contributors all warranties
-         and conditions, express and implied, including warranties or
-         conditions of title and non-infringement, and implied warranties or
-         conditions of merchantability and fitness for a particular purpose;
-     ii. effectively excludes on behalf of all Contributors all liability
-         for damages, including direct, indirect, special, incidental and
-         consequential damages, such as lost profits; and
-    iii. states that any provisions which differ from this Agreement are
-         offered by that Contributor alone and not by any other party.
-
-B. Each Distributor must include the following in a conspicuous
-   location in the Program:
-
-   Copyright (C) 2003, Lucent Technologies Inc. and others. All Rights
-   Reserved.
-
-C. In addition, each Contributor must identify itself as the
-originator of its Contribution in a manner that reasonably allows
-subsequent Recipients to identify the originator of the Contribution.
-Also, each Contributor must agree that the additions and/or changes
-are intended to be a Contribution. Once a Contribution is contributed,
-it may not thereafter be revoked.
-
-4. COMMERCIAL DISTRIBUTION
-
-Commercial distributors of software may accept certain
-responsibilities with respect to end users, business partners and the
-like. While this license is intended to facilitate the commercial use
-of the Program, the Distributor who includes the Program in a
-commercial product offering should do so in a manner which does not
-create potential liability for Contributors. Therefore, if a
-Distributor includes the Program in a commercial product offering,
-such Distributor ("Commercial Distributor") hereby agrees to defend
-and indemnify every Contributor ("Indemnified Contributor") against
-any losses, damages and costs (collectively"Losses") arising from
-claims, lawsuits and other legal actions brought by a third party
-against the Indemnified Contributor to the extent caused by the acts
-or omissions of such Commercial Distributor in connection with its
-distribution of the Program in a commercial product offering. The
-obligations in this section do not apply to any claims or Losses
-relating to any actual or alleged intellectual property infringement.
-In order to qualify, an Indemnified Contributor must: a) promptly
-notify the Commercial Distributor in writing of such claim, and b)
-allow the Commercial Distributor to control, and cooperate with the
-Commercial Distributor in, the defense and any related settlement
-negotiations. The Indemnified Contributor may participate in any such
-claim at its own expense.
-
-For example, a Distributor might include the Program in a commercial
-product offering, Product X. That Distributor is then a Commercial
-Distributor. If that Commercial Distributor then makes performance
-claims, or offers warranties related to Product X, those performance
-claims and warranties are such Commercial Distributor's responsibility
-alone. Under this section, the Commercial Distributor would have to
-defend claims against the Contributors related to those performance
-claims and warranties, and if a court requires any Contributor to pay
-any damages as a result, the Commercial Distributor must pay those
-damages.
-
-5. NO WARRANTY
-
-EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS
-PROVIDED ON AN"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY
-WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY
-OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely
-responsible for determining the appropriateness of using and
-distributing the Program and assumes all risks associated with its
-exercise of rights under this Agreement, including but not limited to
-the risks and costs of program errors, compliance with applicable
-laws, damage to or loss of data, programs or equipment, and
-unavailability or interruption of operations.
-
-6. DISCLAIMER OF LIABILITY
-
-EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR
-ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT,
-INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING
-WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF
-LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR
-DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
-HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
-
-7. EXPORT CONTROL
-
-Recipient agrees that Recipient alone is responsible for compliance
-with the United States export administration regulations (and the
-export control laws and regulation of any other countries).
-
-8. GENERAL
-
-If any provision of this Agreement is invalid or unenforceable under
-applicable law, it shall not affect the validity or enforceability of
-the remainder of the terms of this Agreement, and without further
-action by the parties hereto, such provision shall be reformed to the
-minimum extent necessary to make such provision valid and enforceable.
-
-If Recipient institutes patent litigation against a Contributor with
-respect to a patent applicable to software (including a cross-claim or
-counterclaim in a lawsuit), then any patent licenses granted by that
-Contributor to such Recipient under this Agreement shall terminate as
-of the date such litigation is filed. In addition, if Recipient
-institutes patent litigation against any entity (including a
-cross-claim or counterclaim in a lawsuit) alleging that the Program
-itself (excluding combinations of the Program with other software or
-hardware) infringes such Recipient's patent(s), then such Recipient's
-rights granted under Section 2(b) shall terminate as of the date such
-litigation is filed.
-
-All Recipient's rights under this Agreement shall terminate if it
-fails to comply with any of the material terms or conditions of this
-Agreement and does not cure such failure in a reasonable period of
-time after becoming aware of such noncompliance. If all Recipient's
-rights under this Agreement terminate, Recipient agrees to cease use
-and distribution of the Program as soon as reasonably practicable.
-However, Recipient's obligations under this Agreement and any licenses
-granted by Recipient relating to the Program shall continue and
-survive.
-
-LUCENT may publish new versions (including revisions) of this
-Agreement from time to time. Each new version of the Agreement will be
-given a distinguishing version number. The Program (including
-Contributions) may always be distributed subject to the version of the
-Agreement under which it was received. In addition, after a new
-version of the Agreement is published, Contributor may elect to
-distribute the Program (including its Contributions) under the new
-version. No one other than LUCENT has the right to modify this
-Agreement. Except as expressly stated in Sections 2(a) and 2(b) above,
-Recipient receives no rights or licenses to the intellectual property
-of any Contributor under this Agreement, whether expressly, by
-implication, estoppel or otherwise. All rights in the Program not
-expressly granted under this Agreement are reserved.
-
-This Agreement is governed by the laws of the State of New York and
-the intellectual property laws of the United States of America. No
-party to this Agreement will bring a legal action under this Agreement
-more than one year after the cause of action arose. Each party waives
-its rights to a jury trial in any resulting litigation.
-
--- a/os/boot/pc/NOTICE
+++ /dev/null
@@ -1,4 +1,0 @@
-Copyright © 1995-2007 Lucent Technologies Inc. and others.  All rights reserved.
-Revisions for use with Inferno © 2003-2007 Vita Nuova Holdings Limited.
-
-This software is provided under the terms of the Lucent Public License, Version 1.02.
--- a/os/boot/pc/ahci.h
+++ /dev/null
@@ -1,275 +1,0 @@
-/*
- * advanced host controller interface (sata)
- * © 2007  coraid, inc
- */
-
-/* ata errors */
-enum {
-	Emed	= 1<<0,		/* media error */
-	Enm	= 1<<1,		/* no media */
-	Eabrt	= 1<<2,		/* abort */
-	Emcr	= 1<<3,		/* media change request */
-	Eidnf	= 1<<4,		/* no user-accessible address */
-	Emc	= 1<<5,		/* media change */
-	Eunc	= 1<<6,		/* data error */
-	Ewp	= 1<<6,		/* write protect */
-	Eicrc	= 1<<7,		/* interface crc error */
-
-	Efatal	= Eidnf|Eicrc,	/* must sw reset */
-};
-
-/* ata status */
-enum {
-	ASerr	= 1<<0,		/* error */
-	ASdrq	= 1<<3,		/* request */
-	ASdf	= 1<<5,		/* fault */
-	ASdrdy	= 1<<6,		/* ready */
-	ASbsy	= 1<<7,		/* busy */
-
-	ASobs	= 1<<1|1<<2|1<<4,
-};
-
-/* pci configuration */
-enum {
-	Abar	= 5,
-};
-
-/*
- * ahci memory configuration
- *
- * 0000-0023	generic host control
- * 0024-009f	reserved
- * 00a0-00ff	vendor specific.
- * 0100-017f	port 0
- * ...
- * 1080-1100	port 31
- */
-
-/* cap bits: supported features */
-enum {
-	Hs64a	= 1<<31,	/* 64-bit addressing */
-	Hsncq	= 1<<30,	/* ncq */
-	Hssntf	= 1<<29,	/* snotification reg. */
-	Hsmps	= 1<<28,	/* mech pres switch */
-	Hsss	= 1<<27,	/* staggered spinup */
-	Hsalp	= 1<<26,	/* aggressive link pm */
-	Hsal	= 1<<25,	/* activity led */
-	Hsclo	= 1<<24,	/* command-list override */
-	Hiss	= 1<<20,	/* for interface speed */
-//	Hsnzo	= 1<<19,
-	Hsam	= 1<<18,	/* ahci-mode only */
-	Hspm	= 1<<17,	/* port multiplier */
-//	Hfbss	= 1<<16,
-	Hpmb	= 1<<15,	/* multiple-block pio */
-	Hssc	= 1<<14,	/* slumber state */
-	Hpsc	= 1<<13,	/* partial-slumber state */
-	Hncs	= 1<<8,		/* n command slots */
-	Hcccs	= 1<<7,		/* coal */
-	Hems	= 1<<6,		/* enclosure mgmt. */
-	Hsxs	= 1<<5,		/* external sata */
-	Hnp	= 1<<0,		/* n ports */
-};
-
-/* ghc bits */
-enum {
-	Hae	= 1<<31,	/* enable ahci */
-	Hie	= 1<<1,		/* " interrupts */
-	Hhr	= 1<<0,		/* hba reset */
-};
-
-typedef struct {
-	ulong	cap;
-	ulong	ghc;
-	ulong	isr;
-	ulong	pi;		/* ports implemented */
-	ulong	ver;
-	ulong	ccc;		/* coaleasing control */
-	ulong	cccports;
-	ulong	emloc;
-	ulong	emctl;
-} Ahba;
-
-enum {
-	Acpds	= 1<<31,	/* cold port detect status */
-	Atfes	= 1<<30,	/* task file error status */
-	Ahbfs	= 1<<29,	/* hba fatal */
-	Ahbds	= 1<<28,	/* hba error (parity error) */
-	Aifs	= 1<<27,	/* interface fatal  §6.1.2 */
-	Ainfs	= 1<<26,	/* interface error (recovered) */
-	Aofs	= 1<<24,	/* too many bytes from disk */
-	Aipms	= 1<<23,	/* incorrect prt mul status */
-	Aprcs	= 1<<22,	/* PhyRdy change status Pxserr.diag.n */
-	Adpms	= 1<<7,		/* mechanical presence status */
-	Apcs 	= 1<<6,		/* port connect  diag.x */
-	Adps 	= 1<<5,		/* descriptor processed */
-	Aufs 	= 1<<4,		/* unknown fis diag.f */
-	Asdbs	= 1<<3,		/* set device bits fis received w/ i bit set */
-	Adss	= 1<<2,		/* dma setup */
-	Apio	= 1<<1,		/* pio setup fis */
-	Adhrs	= 1<<0,		/* device to host register fis */
-
-	IEM	= Acpds|Atfes|Ahbds|Ahbfs|Ahbds|Aifs|Ainfs|Aprcs|Apcs|Adps|
-			Aufs|Asdbs|Adss|Adhrs,
-	Ifatal	= Atfes|Ahbfs|Ahbds|Aifs,
-};
-
-/* serror bits */
-enum {
-	SerrX	= 1<<26,	/* exchanged */
-	SerrF	= 1<<25,	/* unknown fis */
-	SerrT	= 1<<24,	/* transition error */
-	SerrS	= 1<<23,	/* link sequence */
-	SerrH	= 1<<22,	/* handshake */
-	SerrC	= 1<<21,	/* crc */
-	SerrD	= 1<<20,	/* not used by ahci */
-	SerrB	= 1<<19,	/* 10-tp-8 decode */
-	SerrW	= 1<<18,	/* comm wake */
-	SerrI	= 1<<17,	/* phy internal */
-	SerrN	= 1<<16,	/* phyrdy change */
-
-	ErrE	= 1<<11,	/* internal */
-	ErrP	= 1<<10,	/* ata protocol violation */
-	ErrC	= 1<<9,		/* communication */
-	ErrT	= 1<<8,		/* transient */
-	ErrM	= 1<<1,		/* recoverd comm */
-	ErrI	= 1<<0,		/* recovered data integrety */
-
-	ErrAll	= ErrE|ErrP|ErrC|ErrT|ErrM|ErrI,
-	SerrAll	= SerrX|SerrF|SerrT|SerrS|SerrH|SerrC|SerrD|SerrB|SerrW|
-			SerrI|SerrN|ErrAll,
-	SerrBad	= 0x7f<<19,
-};
-
-/* cmd register bits */
-enum {
-	Aicc	= 1<<28,	/* interface communcations control. 4 bits */
-	Aasp	= 1<<27,	/* agressive slumber & partial sleep */
-	Aalpe 	= 1<<26,	/* agressive link pm enable */
-	Adlae	= 1<<25,	/* drive led on atapi */
-	Aatapi	= 1<<24,	/* device is atapi */
-	Aesp	= 1<<21,	/* external sata port */
-	Acpd	= 1<<20,	/* cold presence detect */
-	Ampsp	= 1<<19,	/* mechanical pres. */
-	Ahpcp	= 1<<18,	/* hot plug capable */
-	Apma	= 1<<17,	/* pm attached */
-	Acps	= 1<<16,	/* cold presence state */
-	Acr	= 1<<15,	/* cmdlist running */
-	Afr	= 1<<14,	/* fis running */
-	Ampss	= 1<<13,	/* mechanical presence switch state */
-	Accs	= 1<<8,		/* current command slot 12:08 */
-	Afre	= 1<<4,		/* fis enable receive */
-	Aclo	= 1<<3,		/* command list override */
-	Apod	= 1<<2,		/* power on dev (requires cold-pres. detect) */
-	Asud	= 1<<1,		/* spin-up device;  requires ss capability */
-	Ast	= 1<<0,		/* start */
-
-	Arun	= Ast|Acr|Afre|Afr,
-};
-
-/* ctl register bits */
-enum {
-	Aipm	= 1<<8,		/* interface power mgmt. 3=off */
-	Aspd	= 1<<4,
-	Adet	= 1<<0,		/* device detection */
-};
-
-#define	sstatus	scr0
-#define	sctl	scr2
-#define	serror	scr1
-#define	sactive	scr3
-
-typedef struct {
-	ulong	list;		/* PxCLB must be 1kb aligned. */
-	ulong	listhi;
-	ulong	fis;		/* 256-byte aligned */
-	ulong	fishi;
-	ulong	isr;
-	ulong	ie;		/* interrupt enable */
-	ulong	cmd;
-	ulong	res1;
-	ulong	task;
-	ulong	sig;
-	ulong	scr0;
-	ulong	scr2;
-	ulong	scr1;
-	ulong	scr3;
-	ulong	ci;		/* command issue */
-	ulong	ntf;
-	uchar	res2[8];
-	ulong	vendor;
-} Aport;
-
-/* in host's memory; not memory mapped */
-typedef struct {
-	uchar	*base;
-	uchar	*d;
-	uchar	*p;
-	uchar	*r;
-	uchar	*u;
-	ulong	*devicebits;
-} Afis;
-
-enum {
-	Lprdtl	= 1<<16,	/* physical region descriptor table len */
-	Lpmp	= 1<<12,	/* port multiplier port */
-	Lclear	= 1<<10,	/* clear busy on R_OK */
-	Lbist	= 1<<9,
-	Lreset	= 1<<8,
-	Lpref	= 1<<7,		/* prefetchable */
-	Lwrite	= 1<<6,
-	Latapi	= 1<<5,
-	Lcfl	= 1<<0,		/* command fis length in double words */
-};
-
-/* in hosts memory; memory mapped */
-typedef struct {
-	ulong	flags;
-	ulong	len;
-	ulong	ctab;
-	ulong	ctabhi;
-	uchar	reserved[16];
-} Alist;
-
-typedef struct {
-	ulong	dba;
-	ulong	dbahi;
-	ulong	pad;
-	ulong	count;
-} Aprdt;
-
-typedef struct {
-	uchar	cfis[0x40];
-	uchar	atapi[0x10];
-	uchar	pad[0x30];
-	Aprdt	prdt;
-} Actab;
-
-enum {
-	Ferror	= 1,
-	Fdone	= 2,
-};
-
-enum {
-	Dllba 	= 1,
-	Dsmart	= 1<<1,
-	Dpower	= 1<<2,
-	Dnop	= 1<<3,
-	Datapi	= 1<<4,
-	Datapi16= 1<<5,
-};
-
-typedef struct {
-//	QLock;
-//	Rendez;
-	uchar	flag;
-	uchar	feat;
-	uchar	smart;
-	Afis	fis;
-	Alist	*list;
-	Actab	*ctab;
-} Aportm;
-
-typedef struct {
-	Aport	*p;
-	Aportm	*m;
-} Aportc;
--- a/os/boot/pc/alarm.c
+++ /dev/null
@@ -1,123 +1,0 @@
-#include	"u.h"
-#include	"lib.h"
-#include	"mem.h"
-#include	"dat.h"
-#include	"fns.h"
-#include	"io.h"
-#define	MAXALARM	10
-
-Alarm	alarmtab[MAXALARM];
-
-/*
- * Insert new into list after where
- */
-void
-insert(List **head, List *where, List *new)
-{
-	if(where == 0){
-		new->next = *head;
-		*head = new;
-	}else{
-		new->next = where->next;
-		where->next = new;
-	}
-		
-}
-
-/*
- * Delete old from list.  where->next is known to be old.
- */
-void
-delete(List **head, List *where, List *old)
-{
-	if(where == 0){
-		*head = old->next;
-		return;
-	}
-	where->next = old->next;
-}
-
-Alarm*
-newalarm(void)
-{
-	int i;
-	Alarm *a;
-
-	for(i=0,a=alarmtab; i < nelem(alarmtab); i++,a++)
-		if(a->busy==0 && a->f==0){
-			a->f = 0;
-			a->arg = 0;
-			a->busy = 1;
-			return a;
-		}
-	panic("newalarm");
-	return 0;	/* not reached */
-}
-
-Alarm*
-alarm(int ms, void (*f)(Alarm*), void *arg)
-{
-	Alarm *a, *w, *pw;
-	ulong s;
-
-	if(ms < 0)
-		ms = 0;
-	s = splhi();
-	a = newalarm();
-	a->dt = MS2TK(ms);
-	a->f = f;
-	a->arg = arg;
-	pw = 0;
-	for(w=m->alarm; w; pw=w, w=w->next){
-		if(w->dt <= a->dt){
-			a->dt -= w->dt;
-			continue;
-		}
-		w->dt -= a->dt;
-		break;
-	}
-	insert(&m->alarm, pw, a);
-	splx(s);
-	return a;
-}
-
-void
-cancel(Alarm *a)
-{
-	a->f = 0;
-}
-
-void
-alarminit(void)
-{
-}
-
-#define NA 10		/* alarms per clock tick */
-void
-checkalarms(void)
-{
-	int i, n, s;
-	Alarm *a;
-	void (*f)(Alarm*);
-	Alarm *alist[NA];
-
-	s = splhi();
-	a = m->alarm;
-	if(a){
-		for(n=0; a && a->dt<=0 && n<NA; n++){
-			alist[n] = a;
-			delete(&m->alarm, 0, a);
-			a = m->alarm;
-		}
-		if(a)
-			a->dt--;
-
-		for(i = 0; i < n; i++){
-			f = alist[i]->f;	/* avoid race with cancel */
-			if(f)
-				(*f)(alist[i]);
-			alist[i]->busy = 0;
-		}
-	}
-	splx(s);
-}
--- a/os/boot/pc/aoe.h
+++ /dev/null
@@ -1,76 +1,0 @@
-/*
- * ATA-over-Ethernet
- */
-enum {
-	ACata,
-	ACconfig,
-};
-
-enum {
-	AQCread,
-	AQCtest,
-	AQCprefix,
-	AQCset,
-	AQCfset,
-};
-
-enum {
-	AEcmd	= 1,
-	AEarg,
-	AEdev,
-	AEcfg,
-	AEver,
-};
-
-enum {
-	Aoetype	= 0x88a2,
-	Aoever	= 1,
-
-	AFerr	= 1<<2,
-	AFrsp	= 1<<3,
-
-	AAFwrite= 1,
-	AAFext	= 1<<6,
-};
-
-enum {
-	Crd	= 0x20,
-	Crdext	= 0x24,
-	Cwr	= 0x30,
-	Cwrext	= 0x34,
-	Cid	= 0xec,
-};
-
-typedef struct {
-	uchar	dst[Eaddrlen];
-	uchar	src[Eaddrlen];
-	uchar	type[2];
-	uchar	verflag;
-	uchar	error;
-	uchar	major[2];
-	uchar	minor;
-	uchar	cmd;
-	uchar	tag[4];
-} Aoehdr;
-
-typedef struct {
-	Aoehdr;
-	uchar	aflag;
-	uchar	errfeat;
-	uchar	scnt;
-	uchar	cmdstat;
-	uchar	lba[6];
-	uchar	res[2];
-} Aoeata;
-
-typedef struct {
-	Aoehdr;
-	uchar	bufcnt[2];
-	uchar	fwver[2];
-	uchar	scnt;
-	uchar	verccmd;
-	uchar	cslen[2];
-} Aoeqc;
-
-extern char Echange[];
-extern char Enotup[];
--- a/os/boot/pc/apm.c
+++ /dev/null
@@ -1,16 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-Apminfo apm;
-
-void
-apminit(void)
-{
-	if(getconf("apm0") && apm.haveinfo)
-		changeconf("apm0=ax=%x ebx=%x cx=%x dx=%x di=%x esi=%x\n",
-			apm.ax, apm.ebx, apm.cx, apm.dx, apm.di, apm.esi);
-}
--- a/os/boot/pc/bcom.c
+++ /dev/null
@@ -1,463 +1,0 @@
-/*
- * ld - DOS boot loader of Plan 9
- */
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-#include "fs.h"
-
-Type types[] = {
-	{	Tfloppy,
-		Fini|Ffs,
-		floppyinit, floppyinitdev,
-		floppygetfspart, 0, floppyboot,
-	},
-	{	Tsd,
-		Fini|Ffs,
-		sdinit, sdinitdev,
-		sdgetfspart, sdaddconf, sdboot,
-	},
-	{	Tnil,
-		0,
-		0, 0,
-		0, 0, 0,
-	},
-};
-
-#include "sd.h"
-
-extern SDifc sdataifc;
-extern SDifc sdmylexifc;
-extern SDifc sd53c8xxifc;
-SDifc* sdifc[] = {
-	&sdataifc,
-//	&sdmylexifc,
-//	&sd53c8xxifc,
-	nil,
-};
-
-typedef struct Mode Mode;
-
-enum {
-	Maxdev		= 7,
-	Dany		= -1,
-	Nmedia		= 16,
-	Nini		= 10,
-};
-
-enum {					/* mode */
-	Mauto		= 0x00,
-	Mlocal		= 0x01,
-	Manual		= 0x02,
-	NMode		= 0x03,
-};
-
-typedef struct Medium Medium;
-struct Medium {
-	Type*	type;
-	int	flag;
-	int	dev;
-	char name[NAMELEN];
-	Fs*	inifs;
-
-	Medium*	next;
-};
-
-typedef struct Mode {
-	char*	name;
-	int	mode;
-} Mode;
-
-static Medium media[Nmedia];
-static Medium *curmedium = media;
-
-static Mode modes[NMode+1] = {
-	[Mauto]		{ "auto",   Mauto,  },
-	[Mlocal]	{ "local",  Mlocal, },
-	[Manual]	{ "manual", Manual, },
-};
-
-char *defaultpartition = "new";
-
-static Medium*
-parse(char *line, char **file)
-{
-	char *p;
-	Type *tp;
-	Medium *mp;
-
-	if(p = strchr(line, '!')) {
-		*p++ = 0;
-		*file = p;
-	} else
-		*file = "";
-
-	for(tp = types; tp->type != Tnil; tp++)
-		for(mp = tp->media; mp; mp = mp->next)
-			if(strcmp(mp->name, line) == 0)
-				return mp;
-	return nil;
-}
-
-static int
-boot(Medium *mp, char *file)
-{
-	static Boot b;
-
-	memset(&b, 0, sizeof b);
-	b.state = INIT9LOAD;
-
-//	sprint(BOOTLINE, "%s!%s", mp->name, file);
-	return (*mp->type->boot)(mp->dev, file, &b);
-}
-
-static Medium*
-allocm(Type *tp)
-{
-	Medium **l;
-
-	if(curmedium >= &media[Nmedia])
-		return 0;
-
-	for(l = &tp->media; *l; l = &(*l)->next)
-		;
-	*l = curmedium++;
-	return *l;
-}
-
-char *parts[] = { "dos", "9fat", "fs", 0 };
-
-Medium*
-probe(int type, int flag, int dev)
-{
-	Type *tp;
-	int i;
-	Medium *mp;
-
-	for(tp = types; tp->type != Tnil; tp++){
-		if(type != Tany && type != tp->type)
-			continue;
-
-		if(flag != Fnone){
-			for(mp = tp->media; mp; mp = mp->next){
-				if((flag & mp->flag) && (dev == Dany || dev == mp->dev))
-					return mp;
-			}
-		}
-
-		if((tp->flag & Fprobe) == 0){
-			tp->flag |= Fprobe;
-			tp->mask = (*tp->init)();
-		}
-
-		for(i = 0; tp->mask; i++){
-			if((tp->mask & (1<<i)) == 0)
-				continue;
-			tp->mask &= ~(1<<i);
-
-			if((mp = allocm(tp)) == 0)
-				continue;
-
-			mp->dev = i;
-			mp->flag = tp->flag;
-			mp->type = tp;
-			(*tp->initdev)(i, mp->name);
-
-			if((flag & mp->flag) && (dev == Dany || dev == i))
-				return mp;
-		}
-	}
-
-	return 0;
-}
-
-extern int loopconst;
-void
-main(void)
-{
-	Medium *mp;
-	int flag;
-	char def[2*NAMELEN], line[80], *p, *file;
-	Type *tp;
-
-	i8042a20();
-	memset(m, 0, sizeof(Mach));
-	trapinit();
-	clockinit();
-	alarminit();
-	spllo();
-
-	kbdinit();
-	
-	if((ulong)&end > (KZERO|(640*1024)))
-		panic("i'm too big");
-
-	/*
-	 * If there were any arguments, MS-DOS leaves a character
-	 * count followed by the arguments in the runtime header.
-	 * Step over the leading space.
-	 */
-	p = (char*)0x80080080;
-	if(p[0]){
-		p[p[0]+1] = 0;
-		p += 2;
-	}
-	else
-		p = 0;
-
-	/*
-	 * Advance command line to first option, if any
-	 */
-	if(p) {
-		while(*p==' ' || *p=='\t')
-			p++;
-		if(*p == 0)
-			p = nil;
-	}
-
-	/*
- 	 * Probe everything, to collect device names.
-	 */
-	probe(Tany, Fnone, Dany);
-
-	if(p != 0) {
-		if((mp = parse(p, &file)) == nil) {
-			print("bad loadfile syntax: %s\n", p);
-			goto done;
-		}
-		boot(mp, file);
-	}
-
-done:
-	flag = 0;
-	for(tp = types; tp->type != Tnil; tp++){
-		for(mp = tp->media; mp; mp = mp->next){
-			if(flag == 0){
-				flag = 1;
-				print("Load devices:");
-			}
-			print(" %s", mp->name);
-		}
-	}
-	if(flag)
-		print("\n");
-
-	for(;;){
-		if(getstr("load from", line, sizeof(line), nil, 0) >= 0)
-			if(mp = parse(line, &file))
-				boot(mp, file);
-		def[0] = 0;
-	}
-}
-
-int
-getfields(char *lp, char **fields, int n, char sep)
-{
-	int i;
-
-	for(i = 0; lp && *lp && i < n; i++){
-		while(*lp == sep)
-			*lp++ = 0;
-		if(*lp == 0)
-			break;
-		fields[i] = lp;
-		while(*lp && *lp != sep){
-			if(*lp == '\\' && *(lp+1) == '\n')
-				*lp++ = ' ';
-			lp++;
-		}
-	}
-	return i;
-}
-
-int
-cistrcmp(char *a, char *b)
-{
-	int ac, bc;
-
-	for(;;){
-		ac = *a++;
-		bc = *b++;
-	
-		if(ac >= 'A' && ac <= 'Z')
-			ac = 'a' + (ac - 'A');
-		if(bc >= 'A' && bc <= 'Z')
-			bc = 'a' + (bc - 'A');
-		ac -= bc;
-		if(ac)
-			return ac;
-		if(bc == 0)
-			break;
-	}
-	return 0;
-}
-
-int
-cistrncmp(char *a, char *b, int n)
-{
-	unsigned ac, bc;
-
-	while(n > 0){
-		ac = *a++;
-		bc = *b++;
-		n--;
-
-		if(ac >= 'A' && ac <= 'Z')
-			ac = 'a' + (ac - 'A');
-		if(bc >= 'A' && bc <= 'Z')
-			bc = 'a' + (bc - 'A');
-
-		ac -= bc;
-		if(ac)
-			return ac;
-		if(bc == 0)
-			break;
-	}
-
-	return 0;
-}
-
-void*
-ialloc(ulong n, int align)
-{
-
-	static ulong palloc;
-	ulong p;
-	int a;
-
-	if(palloc == 0)
-		palloc = 3*1024*1024;
-
-	p = palloc;
-	if(align <= 0)
-		align = 4;
-	if(a = n % align)
-		n += align - a;
-	if(a = p % align)
-		p += align - a;
-
-	palloc = p+n;
-
-	return memset((void*)(p|KZERO), 0, n);
-}
-
-void*
-xspanalloc(ulong size, int align, ulong span)
-{
-	ulong a, v;
-
-	a = (ulong)ialloc(size+align+span, 0);
-
-	if(span > 2)
-		v = (a + span) & ~(span-1);
-	else
-		v = a;
-
-	if(align > 1)
-		v = (v + align) & ~(align-1);
-
-	return (void*)v;
-}
-
-static Block *allocbp;
-
-Block*
-allocb(int size)
-{
-	Block *bp, **lbp;
-	ulong addr;
-
-	lbp = &allocbp;
-	for(bp = *lbp; bp; bp = bp->next){
-		if((bp->lim - bp->base) >= size){
-			*lbp = bp->next;
-			break;
-		}
-		lbp = &bp->next;
-	}
-	if(bp == 0){
-		bp = ialloc(sizeof(Block)+size+64, 0);
-		addr = (ulong)bp;
-		addr = ROUNDUP(addr + sizeof(Block), 8);
-		bp->base = (uchar*)addr;
-		bp->lim = ((uchar*)bp) + sizeof(Block)+size+64;
-	}
-
-	if(bp->flag)
-		panic("allocb reuse\n");
-
-	bp->rp = bp->base;
-	bp->wp = bp->rp;
-	bp->next = 0;
-	bp->flag = 1;
-
-	return bp;
-}
-
-void
-freeb(Block* bp)
-{
-	bp->next = allocbp;
-	allocbp = bp;
-
-	bp->flag = 0;
-}
-
-enum {
-	Paddr=		0x70,	/* address port */
-	Pdata=		0x71,	/* data port */
-};
-
-uchar
-nvramread(int offset)
-{
-	outb(Paddr, offset);
-	return inb(Pdata);
-}
-
-void (*etherdetach)(void);
-void (*floppydetach)(void);
-void (*sddetach)(void);
-
-void
-warp9(ulong entry)
-{
-	if(etherdetach)
-		etherdetach();
-	consdrain();
-	(*(void(*)(void))(PADDR(entry)))();
-}
-
-char*
-getconf(char*)
-{
-	return nil;
-}
-
-void
-addconf(char*, ...)
-{
-}
-
-void
-uartspecial(int, void(*)(int), int(*)(void), int)
-{
-}
-
-void
-uartputs(IOQ*, char*, int)
-{
-}
-
-void
-uartputc(int)
-{}
-
-void
-uartdrain(void)
-{
-}
--- a/os/boot/pc/boot.c
+++ /dev/null
@@ -1,451 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-#include "../../../utils/libmach/elf.h"
-
-static uchar elfident[7] = {
-	'\177', 'E', 'L', 'F', '\1', '\1', '\1'
-};
-static Ehdr ehdr, rehdr;
-static Phdr *phdr;
-static int curphdr;
-static ulong curoff;
-static ulong elftotal;
-static long (*swal)(long);
-static ushort (*swab)(ushort);
-
-/*
- * big-endian short
- */
-ushort
-beswab(ushort s)
-{
-	uchar *p;
-
-	p = (uchar*)&s;
-	return (p[0]<<8) | p[1];
-}
-
-/*
- * big-endian long
- */
-long
-beswal(long l)
-{
-	uchar *p;
-
-	p = (uchar*)&l;
-	return (p[0]<<24) | (p[1]<<16) | (p[2]<<8) | p[3];
-}
-
-/*
- * little-endian short
- */
-ushort
-leswab(ushort s)
-{
-	uchar *p;
-
-	p = (uchar*)&s;
-	return (p[1]<<8) | p[0];
-}
-
-/*
- * little-endian long
- */
-long
-leswal(long l)
-{
-	uchar *p;
-
-	p = (uchar*)&l;
-	return (p[3]<<24) | (p[2]<<16) | (p[1]<<8) | p[0];
-}
-
-/*
- * Convert header to canonical form
- */
-static void
-hswal(long *lp, int n, long (*swap) (long))
-{
-	while (n--) {
-		*lp = (*swap) (*lp);
-		lp++;
-	}
-}
-
-static int
-readehdr(Boot *b)
-{
-	int i;
-
-	/* bitswap the header according to the DATA format */
-	if(ehdr.ident[CLASS] != ELFCLASS32) {
-		print("bad ELF class - not 32 bit\n");
-		return 0;
-	}
-	if(ehdr.ident[DATA] == ELFDATA2LSB) {
-		swab = leswab;
-		swal = leswal;
-	} else if(ehdr.ident[DATA] == ELFDATA2MSB) {
-		swab = beswab;
-		swal = beswal;
-	} else {
-		print("bad ELF encoding - not big or little endian\n");
-		return 0;
-	}
-	memmove(&rehdr, &ehdr, sizeof(Ehdr));
-
-	ehdr.type = swab(ehdr.type);
-	ehdr.machine = swab(ehdr.machine);
-	ehdr.version = swal(ehdr.version);
-	ehdr.elfentry = swal(ehdr.elfentry);
-	ehdr.phoff = swal(ehdr.phoff);
-	ehdr.shoff = swal(ehdr.shoff);
-	ehdr.flags = swal(ehdr.flags);
-	ehdr.ehsize = swab(ehdr.ehsize);
-	ehdr.phentsize = swab(ehdr.phentsize);
-	ehdr.phnum = swab(ehdr.phnum);
-	ehdr.shentsize = swab(ehdr.shentsize);
-	ehdr.shnum = swab(ehdr.shnum);
-	ehdr.shstrndx = swab(ehdr.shstrndx);
-	if(ehdr.type != EXEC || ehdr.version != CURRENT)
-		return 0;
-	if(ehdr.phentsize != sizeof(Phdr))
-		return 0;
-
-	if(debug)
-		print("readehdr OK entry 0x%lux\n", ehdr.elfentry);
-
-	curoff = sizeof(Ehdr);
-	i = ehdr.phoff+ehdr.phentsize*ehdr.phnum - curoff;
-	b->state = READPHDR;
-	b->bp = (char*)malloc(i);
-	b->wp = b->bp;
-	b->ep = b->wp + i;
-	phdr = (Phdr*)(b->bp + ehdr.phoff-sizeof(Ehdr));
-	if(debug)
-		print("phdr...");
-
-	return 1;
-}
-
-static int
-nextphdr(Boot *b)
-{
-	Phdr *php;
-	ulong entry, offset;
-	char *paddr;
-
-	if(debug)
-		print("readedata %d\n", curphdr);
-
-	for(; curphdr < ehdr.phnum; curphdr++){
-		php = phdr+curphdr;
-		if(php->type != LOAD)
-			continue;
-		offset = php->offset;
-		paddr = (char*)PADDR(php->paddr);
-		if(offset < curoff){
-			/*
-			 * Can't (be bothered to) rewind the
-			 * input, it might be from tftp. If we
-			 * did then we could boot FreeBSD kernels
-			 * too maybe.
-			 */
-			return 0;
-		}
-		if(php->offset > curoff){
-			b->state = READEPAD;
-			b->bp = (char*)malloc(offset - curoff);
-			b->wp = b->bp;
-			b->ep = b->wp + offset - curoff;
-			if(debug)
-				print("nextphdr %lud...\n", offset - curoff);
-			return 1;
-		}
-		b->state = READEDATA;
-		b->bp = paddr;
-		b->wp = b->bp;
-		b->ep = b->wp+php->filesz;
-		print("%ud+", php->filesz);
-		elftotal += php->filesz;
-		if(debug)
-			print("nextphdr %ud@0x%p\n", php->filesz, paddr);
-
-		return 1;
-	}
-
-	if(curphdr != 0){
-		print("=%lud\n", elftotal);
-		b->state = TRYBOOT;
-		entry = ehdr.elfentry & ~0xF0000000;
-		PLLONG(b->exec.entry, entry);
-		return 1;
-	}
-
-	return 0;
-}
-
-static int
-readepad(Boot *b)
-{
-	Phdr *php;
-
-	php = phdr+curphdr;
-	if(debug)
-		print("readepad %d\n", curphdr);
-	curoff = php->offset;
-
-	return nextphdr(b);
-}
-
-static int
-readedata(Boot *b)
-{
-	Phdr *php;
-
-	php = phdr+curphdr;
-	if(debug)
-		print("readedata %d\n", curphdr);
-	if(php->filesz < php->memsz){
-		print("%lud",  php->memsz-php->filesz);
-		elftotal += php->memsz-php->filesz;
-		memset((char*)(PADDR(php->paddr)+php->filesz), 0, php->memsz-php->filesz);
-	}
-	curoff = php->offset+php->filesz;
-	curphdr++;
-
-	return nextphdr(b);
-}
-
-static int
-readphdr(Boot *b)
-{
-	Phdr *php;
-
-	php = phdr;
-	hswal((long*)php, ehdr.phentsize*ehdr.phnum/sizeof(long), swal);
-	if(debug)
-		print("phdr curoff %lud vaddr 0x%lux paddr 0x%lux\n",
-			curoff, php->vaddr, php->paddr);
-
-	curoff = ehdr.phoff+ehdr.phentsize*ehdr.phnum;
-	curphdr = 0;
-
-	return nextphdr(b);
-}
-
-static int
-addbytes(char **dbuf, char *edbuf, char **sbuf, char *esbuf)
-{
-	int n;
-
-	n = edbuf - *dbuf;
-	if(n <= 0)
-		return 0;
-	if(n > esbuf - *sbuf)
-		n = esbuf - *sbuf;
-	if(n <= 0)
-		return -1;
-
-	memmove(*dbuf, *sbuf, n);
-	*sbuf += n;
-	*dbuf += n;
-	return edbuf - *dbuf;
-}
-
-int
-bootpass(Boot *b, void *vbuf, int nbuf)
-{
-	char *buf, *ebuf;
-	Exec *ep;
-	ulong entry, data, text, bss;
-
-	if(b->state == FAILED)
-		return FAIL;
-
-	if(nbuf == 0)
-		goto Endofinput;
-
-	buf = vbuf;
-	ebuf = buf+nbuf;
-	while(addbytes(&b->wp, b->ep, &buf, ebuf) == 0) {
-		switch(b->state) {
-		case INITKERNEL:
-			b->state = READEXEC;
-			b->bp = (char*)&b->exec;
-			b->wp = b->bp;
-			b->ep = b->bp+sizeof(Exec);
-			break;
-		case READEXEC:
-			ep = &b->exec;
-			if(GLLONG(ep->magic) == I_MAGIC) {
-				b->state = READ9TEXT;
-				b->bp = (char*)PADDR(GLLONG(ep->entry));
-				b->wp = b->bp;
-				b->ep = b->wp+GLLONG(ep->text);
-				print("%lud", GLLONG(ep->text));
-				break;
-			}
-
-			/* check for gzipped kernel */
-			if(b->bp[0] == 0x1F && (uchar)b->bp[1] == 0x8B && b->bp[2] == 0x08) {
-				b->state = READGZIP;
-				b->bp = (char*)malloc(1440*1024);
-				b->wp = b->bp;
-				b->ep = b->wp + 1440*1024;
-				memmove(b->bp, &b->exec, sizeof(Exec));
-				b->wp += sizeof(Exec);
-				print("gz...");
-				break;
-			}
-
-			/*
-			 * Check for ELF.
-			 */
-			if(memcmp(b->bp, elfident, 4) == 0){
-				b->state = READEHDR;
-				b->bp = (char*)&ehdr;
-				b->wp = b->bp;
-				b->ep = b->wp + sizeof(Ehdr);
-				memmove(b->bp, &b->exec, sizeof(Exec));
-				b->wp += sizeof(Exec);
-				print("elf...");
-				break;
-			}
-
-			print("bad kernel format\n");
-			b->state = FAILED;
-			return FAIL;
-
-		case READ9TEXT:
-			ep = &b->exec;
-			b->state = READ9DATA;
-			b->bp = (char*)PGROUND(PADDR(GLLONG(ep->entry))+GLLONG(ep->text));
-			b->wp = b->bp;
-			b->ep = b->wp + GLLONG(ep->data);
-			print("+%ld", GLLONG(ep->data));
-			break;
-	
-		case READ9DATA:
-			ep = &b->exec;
-			bss = GLLONG(ep->bss);
-			print("+%ld=%ld\n",
-				bss, GLLONG(ep->text)+GLLONG(ep->data)+bss);
-			b->state = TRYBOOT;
-			return ENOUGH;
-
-		case READEHDR:
-			if(!readehdr(b)){
-				print("readehdr failed\n");
-				b->state = FAILED;
-				return FAIL;
-			}
-			break;
-
-		case READPHDR:
-			if(!readphdr(b)){
-				b->state = FAILED;
-				return FAIL;
-			}
-			break;
-
-		case READEPAD:
-			if(!readepad(b)){
-				b->state = FAILED;
-				return FAIL;
-			}
-			break;
-
-		case READEDATA:
-			if(!readedata(b)){
-				b->state = FAILED;
-				return FAIL;
-			}
-			if(b->state == TRYBOOT)
-				return ENOUGH;
-			break;
-
-		case TRYBOOT:
-		case READGZIP:
-			return ENOUGH;
-
-		case READ9LOAD:
-		case INIT9LOAD:
-			panic("9load");
-
-		default:
-			panic("bootstate");
-		}
-	}
-	return MORE;
-
-
-Endofinput:
-	/* end of input */
-	switch(b->state) {
-	case INITKERNEL:
-	case READEXEC:
-	case READ9TEXT:
-	case READ9DATA:
-	case READEHDR:
-	case READPHDR:
-	case READEPAD:
-	case READEDATA:
-		print("premature EOF\n");
-		b->state = FAILED;
-		return FAIL;
-	
-	case TRYBOOT:
-		entry = GLLONG(b->exec.entry);
-		print("entry: 0x%lux\n", entry);
-		warp9(PADDR(entry));
-		b->state = FAILED;
-		return FAIL;
-
-	case READGZIP:
-		ep = &b->exec;
-		if(b->bp[0] != 0x1F || (uchar)b->bp[1] != 0x8B || b->bp[2] != 0x08)
-			print("lost magic\n");
-
-		print("%ld => ", b->wp - b->bp);
-		if(gunzip((uchar*)ep, sizeof(*ep), (uchar*)b->bp, b->wp - b->bp) < sizeof(*ep)) {
-			print("badly compressed kernel\n");
-			return FAIL;
-		}
-
-		entry = GLLONG(ep->entry);
-		text = GLLONG(ep->text);
-		data = GLLONG(ep->data);
-		bss = GLLONG(ep->bss);
-		print("%lud+%lud+%lud=%lud\n", text, data, bss, text+data+bss);
-
-		if(gunzip((uchar*)PADDR(entry)-sizeof(Exec), sizeof(Exec)+text+data, 
-		     (uchar*)b->bp, b->wp-b->bp) < sizeof(Exec)+text+data) {
-			print("error uncompressing kernel\n");
-			return FAIL;
-		}
-
-		/* relocate data to start at page boundary */
-		memmove((void*)PGROUND(PADDR(entry+text)), (void*)(PADDR(entry+text)), data);
-
-		print("entry: %lux\n", entry);
-		warp9(PADDR(entry));
-		b->state = FAILED;
-		return FAIL;
-
-	case INIT9LOAD:
-	case READ9LOAD:
-		panic("end 9load");
-
-	default:
-		panic("bootdone");
-	}
-	b->state = FAILED;
-	return FAIL;
-}
--- a/os/boot/pc/bootld.c
+++ /dev/null
@@ -1,108 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-static int
-addbytes(char **dbuf, char *edbuf, char **sbuf, char *esbuf)
-{
-	int n;
-
-	n = edbuf - *dbuf;
-	if(n <= 0)
-		return 0;
-	if(n > esbuf - *sbuf)
-		n = esbuf - *sbuf;
-	if(n <= 0)
-		return -1;
-
-	memmove(*dbuf, *sbuf, n);
-	*sbuf += n;
-	*dbuf += n;
-	return edbuf - *dbuf;
-}
-
-extern void origin(void);
-
-int
-bootpass(Boot *b, void *vbuf, int nbuf)
-{
-	char *buf, *ebuf, *p, *q;
-	ulong size;
-
-	if(b->state == FAILED)
-		return FAIL;
-
-	if(nbuf == 0)
-		goto Endofinput;
-
-	buf = vbuf;
-	ebuf = buf+nbuf;
-	while(addbytes(&b->wp, b->ep, &buf, ebuf) == 0) {
-		switch(b->state) {
-		case INIT9LOAD:
-			b->state = READ9LOAD;
-			b->bp = (char*)0x10000;
-			b->wp = b->bp;
-			b->ep = b->bp + 256*1024;
-			break;
-
-		case READ9LOAD:
-			return ENOUGH;
-
-		default:
-			panic("bootstate");
-		}
-	}
-	return MORE;
-
-
-Endofinput:
-	/* end of input */
-	print("\n");
-	switch(b->state) {
-	case INIT9LOAD:
-		print("premature EOF\n");
-		b->state = FAILED;
-		return FAIL;
-	
-	case READ9LOAD:
-		size = b->wp - b->bp;
-		if(memcmp(b->bp, origin, 16) != 0) {
-			print("beginning of file does not look right\n");
-			b->state = FAILED;
-			return FAIL;
-		}
-		if(size < 32*1024 || size > 256*1024) {
-			print("got %lud byte loader; not likely\n", size);
-			b->state = FAILED;
-			return FAIL;
-		}
-
-		p = b->bp;
-		q = b->wp;
-		if(q - p > 10000)	/* don't search much past l.s */
-			q = p+10000;
-
-		/*
-		 * The string `JUMP' appears right before
-		 * tokzero, which is where we want to jump.
-		 */
-		for(; p<q; p++) {
-			if(strncmp(p, "JUMP", 4) == 0) {
-				p += 4;
-				warp9((ulong)p);
-			}
-		}
-		print("could not find jump destination\n");
-		b->state = FAILED;
-		return FAIL;
-
-	default:
-		panic("bootdone");
-	}
-	b->state = FAILED;
-	return FAIL;
-}
--- a/os/boot/pc/bootp.c
+++ /dev/null
@@ -1,659 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-#include "ip.h"
-
-extern int debugload;
-
-uchar broadcast[Eaddrlen] = {
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-};
-
-static ushort tftpport = 5000;
-static int Id = 1;
-static Netaddr myaddr;
-static Netaddr server;
-
-typedef struct {
-	uchar	header[4];
-	uchar	data[Segsize];
-} Tftp;
-static Tftp tftpb;
-
-static void
-hnputs(uchar *ptr, ushort val)
-{
-	ptr[0] = val>>8;
-	ptr[1] = val;
-}
-
-static void
-hnputl(uchar *ptr, ulong val)
-{
-	ptr[0] = val>>24;
-	ptr[1] = val>>16;
-	ptr[2] = val>>8;
-	ptr[3] = val;
-}
-
-static ulong
-nhgetl(uchar *ptr)
-{
-	return ((ptr[0]<<24) | (ptr[1]<<16) | (ptr[2]<<8) | ptr[3]);
-}
-
-static ushort
-nhgets(uchar *ptr)
-{
-	return ((ptr[0]<<8) | ptr[1]);
-}
-
-static	short	endian	= 1;
-static	char*	aendian	= (char*)&endian;
-#define	LITTLE	*aendian
-
-static ushort
-ptcl_csum(void *a, int len)
-{
-	uchar *addr;
-	ulong t1, t2;
-	ulong losum, hisum, mdsum, x;
-
-	addr = a;
-	losum = 0;
-	hisum = 0;
-	mdsum = 0;
-
-	x = 0;
-	if((ulong)addr & 1) {
-		if(len) {
-			hisum += addr[0];
-			len--;
-			addr++;
-		}
-		x = 1;
-	}
-	while(len >= 16) {
-		t1 = *(ushort*)(addr+0);
-		t2 = *(ushort*)(addr+2);	mdsum += t1;
-		t1 = *(ushort*)(addr+4);	mdsum += t2;
-		t2 = *(ushort*)(addr+6);	mdsum += t1;
-		t1 = *(ushort*)(addr+8);	mdsum += t2;
-		t2 = *(ushort*)(addr+10);	mdsum += t1;
-		t1 = *(ushort*)(addr+12);	mdsum += t2;
-		t2 = *(ushort*)(addr+14);	mdsum += t1;
-		mdsum += t2;
-		len -= 16;
-		addr += 16;
-	}
-	while(len >= 2) {
-		mdsum += *(ushort*)addr;
-		len -= 2;
-		addr += 2;
-	}
-	if(x) {
-		if(len)
-			losum += addr[0];
-		if(LITTLE)
-			losum += mdsum;
-		else
-			hisum += mdsum;
-	} else {
-		if(len)
-			hisum += addr[0];
-		if(LITTLE)
-			hisum += mdsum;
-		else
-			losum += mdsum;
-	}
-
-	losum += hisum >> 8;
-	losum += (hisum & 0xff) << 8;
-	while(hisum = losum>>16)
-		losum = hisum + (losum & 0xffff);
-
-	return ~losum;
-}
-
-static ushort
-ip_csum(uchar *addr)
-{
-	int len;
-	ulong sum = 0;
-
-	len = (addr[0]&0xf)<<2;
-
-	while(len > 0) {
-		sum += addr[0]<<8 | addr[1] ;
-		len -= 2;
-		addr += 2;
-	}
-
-	sum = (sum & 0xffff) + (sum >> 16);
-	sum = (sum & 0xffff) + (sum >> 16);
-	return (sum^0xffff);
-}
-
-enum {
-	/* this is only true of IPv4, but we're not doing v6 yet */
-	Min_udp_payload = ETHERMINTU - ETHERHDRSIZE - UDP_HDRSIZE,
-};
-
-static void
-udpsend(int ctlrno, Netaddr *a, void *data, int dlen)
-{
-	char payload[ETHERMAXTU];
-	Udphdr *uh;
-	Etherhdr *ip;
-	Etherpkt pkt;
-	int len, ptcllen;
-
-	/*
-	 * if packet is too short, make it longer rather than relying
-	 * on ethernet interface or lower layers to pad it.
-	 */
-	if (dlen < Min_udp_payload) {
-		memmove(payload, data, dlen);
-		data = payload;
-		dlen = Min_udp_payload;
-	}
-
-	uh = (Udphdr*)&pkt;
-
-	memset(uh, 0, sizeof(Etherpkt));
-	memmove(uh->udpcksum+sizeof(uh->udpcksum), data, dlen);
-
-	/*
-	 * UDP portion
-	 */
-	ptcllen = dlen + (UDP_HDRSIZE-UDP_PHDRSIZE);
-	uh->ttl = 0;
-	uh->udpproto = IP_UDPPROTO;
-	uh->frag[0] = 0;
-	uh->frag[1] = 0;
-	hnputs(uh->udpplen, ptcllen);
-	hnputl(uh->udpsrc, myaddr.ip);
-	hnputs(uh->udpsport, myaddr.port);
-	hnputl(uh->udpdst, a->ip);
-	hnputs(uh->udpdport, a->port);
-	hnputs(uh->udplen, ptcllen);
-	uh->udpcksum[0] = 0;
-	uh->udpcksum[1] = 0;
-	dlen = (dlen+1)&~1;
-	hnputs(uh->udpcksum, ptcl_csum(&uh->ttl, dlen+UDP_HDRSIZE));
-
-	/*
-	 * IP portion
-	 */
-	ip = (Etherhdr*)&pkt;
-	len = UDP_EHSIZE+UDP_HDRSIZE+dlen;		/* non-descriptive names */
-	ip->vihl = IP_VER|IP_HLEN;
-	ip->tos = 0;
-	ip->ttl = 255;
-	hnputs(ip->length, len-ETHER_HDR);
-	hnputs(ip->id, Id++);
-	ip->frag[0] = 0;
-	ip->frag[1] = 0;
-	ip->cksum[0] = 0;
-	ip->cksum[1] = 0;
-	hnputs(ip->cksum, ip_csum(&ip->vihl));
-
-	/*
-	 * Ethernet MAC portion
-	 */
-	hnputs(ip->type, ET_IP);
-	memmove(ip->d, a->ea, sizeof(ip->d));
-
-if(debug) {
-	print("udpsend ");
-}
-	ethertxpkt(ctlrno, &pkt, len, Timeout);
-}
-
-static void
-nak(int ctlrno, Netaddr *a, int code, char *msg, int report)
-{
-	int n;
-	char buf[128];
-
-	buf[0] = 0;
-	buf[1] = Tftp_ERROR;
-	buf[2] = 0;
-	buf[3] = code;
-	strcpy(buf+4, msg);
-	n = strlen(msg) + 4 + 1;
-	udpsend(ctlrno, a, buf, n);
-	if(report)
-		print("\ntftp: error(%d): %s\n", code, msg);
-}
-
-static int
-udprecv(int ctlrno, Netaddr *a, void *data, int dlen)
-{
-	int n, len;
-	ushort csm;
-	Udphdr *h;
-	ulong addr, timo;
-	Etherpkt pkt;
-	static int rxactive;
-
-	if(rxactive == 0)
-		timo = 1000;
-	else
-		timo = Timeout;
-	timo += TK2MS(m->ticks);
-	while(timo > TK2MS(m->ticks)){
-		n = etherrxpkt(ctlrno, &pkt, timo-TK2MS(m->ticks));
-		if(n <= 0)
-			continue;
-
-		h = (Udphdr*)&pkt;
-		if(debug)
-			print("udprecv %E to %E...\n", h->s, h->d);
-
-		if(nhgets(h->type) != ET_IP) {
-			if(debug)
-				print("not ip...");
-			continue;
-		}
-
-		if(ip_csum(&h->vihl)) {
-			print("ip chksum error\n");
-			continue;
-		}
-		if(h->vihl != (IP_VER|IP_HLEN)) {
-			print("ip bad vers/hlen\n");
-			continue;
-		}
-
-		if(h->udpproto != IP_UDPPROTO) {
-			if(debug)
-				print("not udp (%d)...", h->udpproto);
-			continue;
-		}
-
-		if(debug)
-			print("okay udp...");
-
-		h->ttl = 0;
-		len = nhgets(h->udplen);
-		hnputs(h->udpplen, len);
-
-		if(nhgets(h->udpcksum)) {
-			csm = ptcl_csum(&h->ttl, len+UDP_PHDRSIZE);
-			if(csm != 0) {
-				print("udp chksum error csum #%4ux len %d\n",
-					csm, n);
-				break;
-			}
-		}
-
-		if(a->port != 0 && nhgets(h->udpsport) != a->port) {
-			if(debug)
-				print("udpport %ux not %ux\n",
-					nhgets(h->udpsport), a->port);
-			continue;
-		}
-
-		addr = nhgetl(h->udpsrc);
-		if(a->ip != Bcastip && a->ip != addr) {
-			if(debug)
-				print("bad ip %lux not %lux\n", addr, a->ip);
-			continue;
-		}
-
-		len -= UDP_HDRSIZE-UDP_PHDRSIZE;
-		if(len > dlen) {
-			print("udp: packet too big: %d > %d; from addr %E\n",
-				len, dlen, h->udpsrc);
-			continue;
-		}
-
-		memmove(data, h->udpcksum+sizeof(h->udpcksum), len);
-		a->ip = addr;
-		a->port = nhgets(h->udpsport);
-		memmove(a->ea, pkt.s, sizeof(a->ea));
-
-		rxactive = 1;
-		return len;
-	}
-
-	return 0;
-}
-
-static int tftpblockno;
-
-/*
- * format of a request packet, from the RFC:
- *
-            2 bytes     string    1 byte     string   1 byte
-            ------------------------------------------------
-           | Opcode |  Filename  |   0  |    Mode    |   0  |
-            ------------------------------------------------
- */
-static int
-tftpopen(int ctlrno, Netaddr *a, char *name, Tftp *tftp)
-{
-	int i, len, rlen, oport;
-	char buf[Segsize+2];
-
-	buf[0] = 0;
-	buf[1] = Tftp_READ;
-	len = 2 + sprint(buf+2, "%s", name) + 1;
-	len += sprint(buf+len, "octet") + 1;
-
-	oport = a->port;
-	for(i = 0; i < 5; i++){
-		a->port = oport;
-		udpsend(ctlrno, a, buf, len);
-		a->port = 0;
-		if((rlen = udprecv(ctlrno, a, tftp, sizeof(Tftp))) < sizeof(tftp->header))
-			continue;
-
-		switch((tftp->header[0]<<8)|tftp->header[1]){
-
-		case Tftp_ERROR:
-			print("tftpopen: error (%d): %s\n",
-				(tftp->header[2]<<8)|tftp->header[3], (char*)tftp->data);
-			return -1;
-
-		case Tftp_DATA:
-			tftpblockno = 1;
-			len = (tftp->header[2]<<8)|tftp->header[3];
-			if(len != tftpblockno){
-				print("tftpopen: block error: %d\n", len);
-				nak(ctlrno, a, 1, "block error", 0);
-				return -1;
-			}
-			rlen -= sizeof(tftp->header);
-			if(rlen < Segsize){
-				/* ACK now, in case we don't later */
-				buf[0] = 0;
-				buf[1] = Tftp_ACK;
-				buf[2] = tftpblockno>>8;
-				buf[3] = tftpblockno;
-				udpsend(ctlrno, a, buf, sizeof(tftp->header));
-			}
-			return rlen;
-		}
-	}
-
-	print("tftpopen: failed to connect to server\n");
-	return -1;
-}
-
-static int
-tftpread(int ctlrno, Netaddr *a, Tftp *tftp, int dlen)
-{
-	uchar buf[4];
-	int try, blockno, len;
-
-	dlen += sizeof(tftp->header);
-
-	for(try = 0; try < 10; try++) {
-		buf[0] = 0;
-		buf[1] = Tftp_ACK;
-		buf[2] = tftpblockno>>8;
-		buf[3] = tftpblockno;
-
-		udpsend(ctlrno, a, buf, sizeof(buf));
-		len = udprecv(ctlrno, a, tftp, dlen);
-		if(len <= sizeof(tftp->header)){
-			if(debug)
-				print("tftpread: too short %d <= %d\n",
-					len, sizeof(tftp->header));
-			continue;
-		}
-		blockno = (tftp->header[2]<<8)|tftp->header[3];
-		if(blockno <= tftpblockno){
-			if(debug)
-				print("tftpread: blkno %d <= %d\n",
-					blockno, tftpblockno);
-			continue;
-		}
-
-		if(blockno == tftpblockno+1) {
-			tftpblockno++;
-			if(len < dlen) {	/* last packet; send final ack */
-				tftpblockno++;
-				buf[0] = 0;
-				buf[1] = Tftp_ACK;
-				buf[2] = tftpblockno>>8;
-				buf[3] = tftpblockno;
-				udpsend(ctlrno, a, buf, sizeof(buf));
-			}
-			return len-sizeof(tftp->header);
-		}
-		print("tftpread: block error: %d, expected %d\n",
-			blockno, tftpblockno+1);
-	}
-
-	return -1;
-}
-
-static int
-bootpopen(int ctlrno, char *file, Bootp *rep, int dotftpopen)
-{
-	Bootp req;
-	int i, n;
-	uchar *ea;
-	char name[128], *filename, *sysname;
-
-	if (debugload)
-		print("bootpopen: ether%d!%s...", ctlrno, file);
-	if((ea = etheraddr(ctlrno)) == 0){
-		print("invalid ctlrno %d\n", ctlrno);
-		return -1;
-	}
-
-	filename = 0;
-	sysname = 0;
-	if(file && *file){
-		strcpy(name, file);
-		if(filename = strchr(name, '!')){
-			sysname = name;
-			*filename++ = 0;
-		}
-		else
-			filename = name;
-	}
-
-	memset(&req, 0, sizeof(req));
-	req.op = Bootrequest;
-	req.htype = 1;			/* ethernet */
-	req.hlen = Eaddrlen;		/* ethernet */
-	memmove(req.chaddr, ea, Eaddrlen);
-	if(filename != nil)
-		strncpy(req.file, filename, sizeof(req.file));
-	if(sysname != nil)
-		strncpy(req.sname, sysname, sizeof(req.sname));
-
-	myaddr.ip = 0;
-	myaddr.port = BPportsrc;
-	memmove(myaddr.ea, ea, Eaddrlen);
-
-	etherrxflush(ctlrno);
-	for(i = 0; i < 10; i++) {
-		server.ip = Bcastip;
-		server.port = BPportdst;
-		memmove(server.ea, broadcast, sizeof(server.ea));
-		udpsend(ctlrno, &server, &req, sizeof(req));
-		if(udprecv(ctlrno, &server, rep, sizeof(*rep)) <= 0)
-			continue;
-		if(memcmp(req.chaddr, rep->chaddr, Eaddrlen))
-			continue;
-		if(rep->htype != 1 || rep->hlen != Eaddrlen)
-			continue;
-		if(sysname == 0 || strcmp(sysname, rep->sname) == 0)
-			break;
-	}
-	if(i >= 10) {
-		print("bootp timed out\n");
-		return -1;
-	}
-
-	if(!dotftpopen)
-		return 0;
-
-	if(filename == 0 || *filename == 0){
-		if(strcmp(rep->file, "/386/9pxeload") == 0)
-			return -1;
-		filename = rep->file;
-	}
-
-	if(rep->sname[0] != '\0')
-		 print("%s ", rep->sname);
-	print("(%d.%d.%d.%d!%d): %s\n",
-		rep->siaddr[0],
-		rep->siaddr[1],
-		rep->siaddr[2],
-		rep->siaddr[3],
-		server.port,
-		filename);
-
-	myaddr.ip = nhgetl(rep->yiaddr);
-	myaddr.port = tftpport++;
-	server.ip = nhgetl(rep->siaddr);
-	server.port = TFTPport;
-
-	if((n = tftpopen(ctlrno, &server, filename, &tftpb)) < 0)
-		return -1;
-
-	return n;
-}
-
-int
-bootpboot(int ctlrno, char *file, Boot *b)
-{
-	int n;
-	Bootp rep;
-
-	if((n = bootpopen(ctlrno, file, &rep, 1)) < 0)
-		return -1;
-
-	while(bootpass(b, tftpb.data, n) == MORE){
-		n = tftpread(ctlrno, &server, &tftpb, sizeof(tftpb.data));
-		if(n < sizeof(tftpb.data))
-			break;
-	}
-
-	if(0 < n && n < sizeof(tftpb.data))	/* got to end of file */
-		bootpass(b, tftpb.data, n);
-	else
-		nak(ctlrno, &server, 3, "ok", 0);	/* tftpclose to abort transfer */
-	bootpass(b, nil, 0);	/* boot if possible */
-	return -1;
-}
-
-#include "fs.h"
-
-#define INIPATHLEN	64
-
-static struct {
-	Fs	fs;
-	char	ini[INIPATHLEN];
-} pxether[MaxEther];
-
-static vlong
-pxediskseek(Fs*, vlong)
-{
-	return -1LL;
-}
-
-static long
-pxediskread(Fs*, void*, long)
-{
-	return -1;
-}
-
-static long
-pxeread(File* f, void* va, long len)
-{
-	int n;
-	Bootp rep;
-	char *p, *v;
-
-	if((n = bootpopen(f->fs->dev, pxether[f->fs->dev].ini, &rep, 1)) < 0)
-		return -1;
-
-	p = v = va;
-	while(n > 0) {
-		if((p-v)+n > len)
-			n = len - (p-v);
-		memmove(p, tftpb.data, n);
-		p += n;
-		if(n != Segsize)
-			break;
-		if((n = tftpread(f->fs->dev, &server, &tftpb, sizeof(tftpb.data))) < 0)
-			return -1;
-	}
-	return p-v;
-}
-
-static int
-pxewalk(File* f, char* name)
-{
-	Bootp rep;
-	char *ini;
-
-	switch(f->walked){
-	default:
-		return -1;
-	case 0:
-		if(strcmp(name, "cfg") == 0){
-			f->walked = 1;
-			return 1;
-		}
-		break;
-	case 1:
-		if(strcmp(name, "pxe") == 0){
-			f->walked = 2;
-			return 1;
-		}
-		break;
-	case 2:
-		if(strcmp(name, "%E") != 0)
-			break;
-		f->walked = 3;
-
-		if(bootpopen(f->fs->dev, nil, &rep, 0) < 0)
-			return 0;
-
-		ini = pxether[f->fs->dev].ini;
-		/* use our mac address instead of relying on a bootp answer */
-		snprint(ini, INIPATHLEN, "/cfg/pxe/%E", (uchar *)myaddr.ea);
-		f->path = ini;
-
-		return 1;
-	}
-	return 0;
-}
-
-void*
-pxegetfspart(int ctlrno, char* part, int)
-{
-	if(!pxe)
-		return nil;
-	if(strcmp(part, "*") != 0)
-		return nil;
-	if(ctlrno >= MaxEther)
-		return nil;
-	if(iniread && getconf("*pxeini") != nil)
-		return nil;
-
-	pxether[ctlrno].fs.dev = ctlrno;
-	pxether[ctlrno].fs.diskread = pxediskread;
-	pxether[ctlrno].fs.diskseek = pxediskseek;
-
-	pxether[ctlrno].fs.read = pxeread;
-	pxether[ctlrno].fs.walk = pxewalk;
-
-	pxether[ctlrno].fs.root.fs = &pxether[ctlrno].fs;
-	pxether[ctlrno].fs.root.walked = 0;
-
-	return &pxether[ctlrno].fs;
-}
--- a/os/boot/pc/cga.c
+++ /dev/null
@@ -1,91 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-
-enum {
-	Width		= 160,
-	Height		= 25,
-
-	Attr		= 7,		/* white on black */
-};
-
-#define CGASCREENBASE	((uchar*)KADDR(0xB8000))
-
-static int pos;
-static int screeninitdone;
-
-static uchar
-cgaregr(int index)
-{
-	outb(0x3D4, index);
-	return inb(0x3D4+1) & 0xFF;
-}
-
-static void
-cgaregw(int index, int data)
-{
-	outb(0x3D4, index);
-	outb(0x3D4+1, data);
-}
-
-static void
-movecursor(void)
-{
-	cgaregw(0x0E, (pos/2>>8) & 0xFF);
-	cgaregw(0x0F, pos/2 & 0xFF);
-	CGASCREENBASE[pos+1] = Attr;
-}
-
-static void
-cgascreenputc(int c)
-{
-	int i;
-
-	if(c == '\n'){
-		pos = pos/Width;
-		pos = (pos+1)*Width;
-	}
-	else if(c == '\t'){
-		i = 8 - ((pos/2)&7);
-		while(i-->0)
-			cgascreenputc(' ');
-	}
-	else if(c == '\b'){
-		if(pos >= 2)
-			pos -= 2;
-		cgascreenputc(' ');
-		pos -= 2;
-	}
-	else{
-		CGASCREENBASE[pos++] = c;
-		CGASCREENBASE[pos++] = Attr;
-	}
-	if(pos >= Width*Height){
-		memmove(CGASCREENBASE, &CGASCREENBASE[Width], Width*(Height-1));
-		memset(&CGASCREENBASE[Width*(Height-1)], 0, Width);
-		pos = Width*(Height-1);
-	}
-	movecursor();
-}
-
-static void
-screeninit(void)
-{
-	if(screeninitdone == 0){
-		pos = cgaregr(0x0E)<<8;
-		pos |= cgaregr(0x0F);
-		pos *= 2;
-		screeninitdone = 1;
-	}
-}
-
-void
-cgascreenputs(char* s, int n)
-{
-	if(screeninitdone == 0)
-		screeninit();
-	while(n-- > 0)
-		cgascreenputc(*s++);
-}
--- a/os/boot/pc/cis.c
+++ /dev/null
@@ -1,539 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "error.h"
-#include "io.h"
-
-enum{
-	Linktarget = 0x13,
-};
-	
-/*
- *  read and crack the card information structure enough to set
- *  important parameters like power
- */
-/* cis memory walking */
-typedef struct Cisdat {
-	uchar	*cisbase;
-	int	cispos;
-	int	cisskip;
-	int	cislen;
-} Cisdat;
-
-static void	tcfig(PCMslot*, Cisdat*, int);
-static void	tentry(PCMslot*, Cisdat*, int);
-static void	tvers1(PCMslot*, Cisdat*, int);
-static void	tlonglnkmfc(PCMslot*, Cisdat*, int);
-
-static int
-readc(Cisdat *cis, uchar *x)
-{
-	if(cis->cispos >= cis->cislen)
-		return 0;
-	*x = cis->cisbase[cis->cisskip*cis->cispos];
-	cis->cispos++;
-	return 1;
-}
-
-static int
-xcistuple(int slotno, int tuple, int subtuple, void *v, int nv, int attr)
-{
-	PCMmap *m;
-	Cisdat cis;
-	int i, l;
-	uchar *p;
-	uchar type, link, n, c;
-	int this, subtype;
-
-	m = pcmmap(slotno, 0, 0, attr);
-	if(m == 0)
-		return -1;
-
-	cis.cisbase = KADDR(m->isa);
-	cis.cispos = 0;
-	cis.cisskip = attr ? 2 : 1;
-	cis.cislen = m->len;
-
-	/* loop through all the tuples */
-	for(i = 0; i < 1000; i++){
-		this = cis.cispos;
-		if(readc(&cis, &type) != 1)
-			break;
-		if(type == 0xFF)
-			break;
-		if(readc(&cis, &link) != 1)
-			break;
-		if(link == 0xFF)
-			break;
-
-		n = link;
-		if(link > 1 && subtuple != -1){
-			if(readc(&cis, &c) != 1)
-				break;
-			subtype = c;
-			n--;
-		}else
-			subtype = -1;
-
-		if(type == tuple && subtype == subtuple){
-			p = v;
-			for(l=0; l<nv && l<n; l++)
-				if(readc(&cis, p++) != 1)
-					break;
-			pcmunmap(slotno, m);
-			return nv;
-		}
-		cis.cispos = this + (2+link);
-	}
-	pcmunmap(slotno, m);
-	return -1;
-}
-
-int
-pcmcistuple(int slotno, int tuple, int subtuple, void *v, int nv)
-{
-	int n;
-
-	/* try attribute space, then memory */
-	if((n = xcistuple(slotno, tuple, subtuple, v, nv, 1)) >= 0)
-		return n;
-	return xcistuple(slotno, tuple, subtuple, v, nv, 0);
-}
-
-void
-pcmcisread(PCMslot *pp)
-{
-	int this;
-	Cisdat cis;
-	PCMmap *m;
-	uchar type, link;
-
-	memset(pp->ctab, 0, sizeof(pp->ctab));
-	pp->ncfg = 0;
-	memset(pp->cfg, 0, sizeof(pp->cfg));
-	pp->configed = 0;
-	pp->nctab = 0;
-	pp->verstr[0] = 0;
-
-	/*
-	 * Read all tuples in attribute space.
-	 */
-	m = pcmmap(pp->slotno, 0, 0, 1);
-	if(m == 0)
-		return;
-
-	cis.cisbase = KADDR(m->isa);
-	cis.cispos = 0;
-	cis.cisskip = 2;
-	cis.cislen = m->len;
-
-	/* loop through all the tuples */
-	for(;;){
-		this = cis.cispos;
-		if(readc(&cis, &type) != 1)
-			break;
-		if(type == 0xFF)
-			break;
-		if(readc(&cis, &link) != 1)
-			break;
-
-		switch(type){
-		default:
-			break;
-		case 6:
-			tlonglnkmfc(pp, &cis, type);
-			break;
-		case 0x15:
-			tvers1(pp, &cis, type);
-			break;
-		case 0x1A:
-			tcfig(pp, &cis, type);
-			break;
-		case 0x1B:
-			tentry(pp, &cis, type);
-			break;
-		}
-
-		if(link == 0xFF)
-			break;
-		cis.cispos = this + (2+link);
-	}
-	pcmunmap(pp->slotno, m);
-}
-
-static ulong
-getlong(Cisdat *cis, int size)
-{
-	uchar c;
-	int i;
-	ulong x;
-
-	x = 0;
-	for(i = 0; i < size; i++){
-		if(readc(cis, &c) != 1)
-			break;
-		x |= c<<(i*8);
-	}
-	return x;
-}
-
-static void
-tcfig(PCMslot *pp, Cisdat *cis, int )
-{
-	uchar size, rasize, rmsize;
-	uchar last;
-
-	if(readc(cis, &size) != 1)
-		return;
-	rasize = (size&0x3) + 1;
-	rmsize = ((size>>2)&0xf) + 1;
-	if(readc(cis, &last) != 1)
-		return;
-
-	if(pp->ncfg >= 8){
-		print("tcfig: too many configuration registers\n");
-		return;
-	}
-	
-	pp->cfg[pp->ncfg].caddr = getlong(cis, rasize);
-	pp->cfg[pp->ncfg].cpresent = getlong(cis, rmsize);
-	pp->ncfg++;
-}
-
-static ulong vexp[8] =
-{
-	1, 10, 100, 1000, 10000, 100000, 1000000, 10000000
-};
-static ulong vmant[16] =
-{
-	10, 12, 13, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 70, 80, 90,
-};
-
-static ulong
-microvolt(Cisdat *cis)
-{
-	uchar c;
-	ulong microvolts;
-	ulong exp;
-
-	if(readc(cis, &c) != 1)
-		return 0;
-	exp = vexp[c&0x7];
-	microvolts = vmant[(c>>3)&0xf]*exp;
-	while(c & 0x80){
-		if(readc(cis, &c) != 1)
-			return 0;
-		switch(c){
-		case 0x7d:
-			break;		/* high impedence when sleeping */
-		case 0x7e:
-		case 0x7f:
-			microvolts = 0;	/* no connection */
-			break;
-		default:
-			exp /= 10;
-			microvolts += exp*(c&0x7f);
-		}
-	}
-	return microvolts;
-}
-
-static ulong
-nanoamps(Cisdat *cis)
-{
-	uchar c;
-	ulong nanoamps;
-
-	if(readc(cis, &c) != 1)
-		return 0;
-	nanoamps = vexp[c&0x7]*vmant[(c>>3)&0xf];
-	while(c & 0x80){
-		if(readc(cis, &c) != 1)
-			return 0;
-		if(c == 0x7d || c == 0x7e || c == 0x7f)
-			nanoamps = 0;
-	}
-	return nanoamps;
-}
-
-/*
- * only nominal voltage (feature 1) is important for config,
- * other features must read card to stay in sync.
- */
-static ulong
-power(Cisdat *cis)
-{
-	uchar feature;
-	ulong mv;
-
-	mv = 0;
-	if(readc(cis, &feature) != 1)
-		return 0;
-	if(feature & 1)
-		mv = microvolt(cis);
-	if(feature & 2)
-		microvolt(cis);
-	if(feature & 4)
-		microvolt(cis);
-	if(feature & 8)
-		nanoamps(cis);
-	if(feature & 0x10)
-		nanoamps(cis);
-	if(feature & 0x20)
-		nanoamps(cis);
-	if(feature & 0x40)
-		nanoamps(cis);
-	return mv/1000000;
-}
-
-static ulong mantissa[16] =
-{ 0, 10, 12, 13, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 70, 80, };
-
-static ulong exponent[8] =
-{ 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, };
-
-static ulong
-ttiming(Cisdat *cis, int scale)
-{
-	uchar unscaled;
-	ulong nanosecs;
-
-	if(readc(cis, &unscaled) != 1)
-		return 0;
-	nanosecs = (mantissa[(unscaled>>3)&0xf]*exponent[unscaled&7])/10;
-	nanosecs = nanosecs * vexp[scale];
-	return nanosecs;
-}
-
-static void
-timing(Cisdat *cis, PCMconftab *ct)
-{
-	uchar c, i;
-
-	if(readc(cis, &c) != 1)
-		return;
-	i = c&0x3;
-	if(i != 3)
-		ct->maxwait = ttiming(cis, i);		/* max wait */
-	i = (c>>2)&0x7;
-	if(i != 7)
-		ct->readywait = ttiming(cis, i);		/* max ready/busy wait */
-	i = (c>>5)&0x7;
-	if(i != 7)
-		ct->otherwait = ttiming(cis, i);		/* reserved wait */
-}
-
-static void
-iospaces(Cisdat *cis, PCMconftab *ct)
-{
-	uchar c;
-	int i, nio;
-
-	ct->nio = 0;
-	if(readc(cis, &c) != 1)
-		return;
-
-	ct->bit16 = ((c>>5)&3) >= 2;
-	if(!(c & 0x80)){
-		ct->io[0].start = 0;
-		ct->io[0].len = 1<<(c&0x1f);
-		ct->nio = 1;
-		return;
-	}
-
-	if(readc(cis, &c) != 1)
-		return;
-
-	/*
-	 * For each of the range descriptions read the
-	 * start address and the length (value is length-1).
-	 */
-	nio = (c&0xf)+1;
-	for(i = 0; i < nio; i++){
-		ct->io[i].start = getlong(cis, (c>>4)&0x3);
-		ct->io[i].len = getlong(cis, (c>>6)&0x3)+1;
-	}
-	ct->nio = nio;
-}
-
-static void
-irq(Cisdat *cis, PCMconftab *ct)
-{
-	uchar c;
-
-	if(readc(cis, &c) != 1)
-		return;
-	ct->irqtype = c & 0xe0;
-	if(c & 0x10)
-		ct->irqs = getlong(cis, 2);
-	else
-		ct->irqs = 1<<(c&0xf);
-	ct->irqs &= 0xDEB8;		/* levels available to card */
-}
-
-static void
-memspace(Cisdat *cis, int asize, int lsize, int host)
-{
-	ulong haddress, address, len;
-
-	len = getlong(cis, lsize)*256;
-	address = getlong(cis, asize)*256;
-	USED(len, address);
-	if(host){
-		haddress = getlong(cis, asize)*256;
-		USED(haddress);
-	}
-}
-
-static void
-tentry(PCMslot *pp, Cisdat *cis, int )
-{
-	uchar c, i, feature;
-	PCMconftab *ct;
-
-	if(pp->nctab >= nelem(pp->ctab))
-		return;
-	if(readc(cis, &c) != 1)
-		return;
-	ct = &pp->ctab[pp->nctab++];
-
-	/* copy from last default config */
-	if(pp->def)
-		*ct = *pp->def;
-
-	ct->index = c & 0x3f;
-
-	/* is this the new default? */
-	if(c & 0x40)
-		pp->def = ct;
-
-	/* memory wait specified? */
-	if(c & 0x80){
-		if(readc(cis, &i) != 1)
-			return;
-		if(i&0x80)
-			ct->memwait = 1;
-	}
-
-	if(readc(cis, &feature) != 1)
-		return;
-	switch(feature&0x3){
-	case 1:
-		ct->vpp1 = ct->vpp2 = power(cis);
-		break;
-	case 2:
-		power(cis);
-		ct->vpp1 = ct->vpp2 = power(cis);
-		break;
-	case 3:
-		power(cis);
-		ct->vpp1 = power(cis);
-		ct->vpp2 = power(cis);
-		break;
-	default:
-		break;
-	}
-	if(feature&0x4)
-		timing(cis, ct);
-	if(feature&0x8)
-		iospaces(cis, ct);
-	if(feature&0x10)
-		irq(cis, ct);
-	switch((feature>>5)&0x3){
-	case 1:
-		memspace(cis, 0, 2, 0);
-		break;
-	case 2:
-		memspace(cis, 2, 2, 0);
-		break;
-	case 3:
-		if(readc(cis, &c) != 1)
-			return;
-		for(i = 0; i <= (c&0x7); i++)
-			memspace(cis, (c>>5)&0x3, (c>>3)&0x3, c&0x80);
-		break;
-	}
-	pp->configed++;
-}
-
-static void
-tvers1(PCMslot *pp, Cisdat *cis, int )
-{
-	uchar c, major, minor, last;
-	int  i;
-
-	if(readc(cis, &major) != 1)
-		return;
-	if(readc(cis, &minor) != 1)
-		return;
-	last = 0;
-	for(i = 0; i < sizeof(pp->verstr)-1; i++){
-		if(readc(cis, &c) != 1)
-			return;
-		if(c == 0)
-			c = ';';
-		if(c == '\n')
-			c = ';';
-		if(c == 0xff)
-			break;
-		if(c == ';' && last == ';')
-			continue;
-		pp->verstr[i] = c;
-		last = c;
-	}
-	pp->verstr[i] = 0;
-}
-
-static void
-tlonglnkmfc(PCMslot *pp, Cisdat *cis, int)
-{
-	int i, npos, opos;
-	uchar nfn, space, expect, type, this, link;
-
-	readc(cis, &nfn);
-	for(i = 0; i < nfn; i++){
-		readc(cis, &space);
-		npos        = getlong(cis, 4);
-		opos        = cis->cispos;
-		cis->cispos = npos;
-		expect      = Linktarget;
-
-		while(1){
-			this = cis->cispos;
-			if(readc(cis, &type) != 1)
-				break;
-			if(type == 0xFF)
-				break;
-			if(readc(cis, &link) != 1)
-				break;
-
-			if(expect && expect != type){
-				print("tlonglnkmfc: expected %X found %X\n",
-					expect, type);
-				break;
-			}
-			expect = 0;
-
-			switch(type){
-			default:
-				break;
-			case 0x15:
-				tvers1(pp, cis, type);
-				break;
-			case 0x1A:
-				tcfig(pp, cis, type);
-				break;
-			case 0x1B:
-				tentry(pp, cis, type);
-				break;
-			}
-
-			if(link == 0xFF)
-				break;
-			cis->cispos = this + (2+link);
-		}
-		cis->cispos = opos;
-	}
-}
--- a/os/boot/pc/clock.c
+++ /dev/null
@@ -1,309 +1,0 @@
-#include	"u.h"
-#include	"lib.h"
-#include	"mem.h"
-#include	"dat.h"
-#include	"fns.h"
-#include	"io.h"
-#include	"ureg.h"
-
-/*
- *  8253 timer
- */
-enum
-{
-	T0cntr=	0x40,		/* counter ports */
-	T1cntr=	0x41,		/* ... */
-	T2cntr=	0x42,		/* ... */
-	Tmode=	0x43,		/* mode port */
-
-	/* commands */
-	Latch0=	0x00,		/* latch counter 0's value */
-	Load0=	0x30,		/* load counter 0 with 2 bytes */
-
-	/* modes */
-	Square=	0x36,		/* perioic square wave */
-
-	Freq=	1193182,	/* Real clock frequency */
-};
-
-static uvlong cpuhz = 66000000;
-static int cpumhz = 66;
-static int loopconst = 100;
-int cpuidax, cpuiddx;
-int havetsc;
-
-extern void _cycles(uvlong*);		/* in l.s */
-extern void wrmsr(int, vlong);
-
-static void
-clockintr(Ureg*, void*)
-{
-	m->ticks++;
-	checkalarms();
-}
-
-#define STEPPING(x)	((x)&0xf)
-#define X86MODEL(x)	(((x)>>4)&0xf)
-#define X86FAMILY(x)	(((x)>>8)&0xf)
-
-enum
-{
-	/* flags */
-	CpuidFPU	= 0x001,	/* on-chip floating point unit */
-	CpuidMCE	= 0x080,	/* machine check exception */
-	CpuidCX8	= 0x100,	/* CMPXCHG8B instruction */
-};
-
-typedef struct
-{
-	int family;
-	int model;
-	int aalcycles;
-	char *name;
-} X86type;
-
-X86type x86intel[] =
-{
-	{ 4,	0,	22,	"486DX", },	/* known chips */
-	{ 4,	1,	22,	"486DX50", },
-	{ 4,	2,	22,	"486SX", },
-	{ 4,	3,	22,	"486DX2", },
-	{ 4,	4,	22,	"486SL", },
-	{ 4,	5,	22,	"486SX2", },
-	{ 4,	7,	22,	"DX2WB", },	/* P24D */
-	{ 4,	8,	22,	"DX4", },	/* P24C */
-	{ 4,	9,	22,	"DX4WB", },	/* P24CT */
-	{ 5,	0,	23,	"P5", },
-	{ 5,	1,	23,	"P5", },
-	{ 5,	2,	23,	"P54C", },
-	{ 5,	3,	23,	"P24T", },
-	{ 5,	4,	23,	"P55C MMX", },
-	{ 5,	7,	23,	"P54C VRT", },
-	{ 6,	1,	16,	"PentiumPro", },/* trial and error */
-	{ 6,	3,	16,	"PentiumII", },
-	{ 6,	5,	16,	"PentiumII/Xeon", },
-	{ 6,	6,	16,	"Celeron", },
-	{ 6,	7,	16,	"PentiumIII/Xeon", },
-	{ 6,	8,	16,	"PentiumIII/Xeon", },
-	{ 6,	0xB,	16,	"PentiumIII/Xeon", },
-	{ 0xF,	1,	16,	"P4", },	/* P4 */
-	{ 0xF,	2,	16,	"PentiumIV/Xeon", },
-
-	{ 3,	-1,	32,	"386", },	/* family defaults */
-	{ 4,	-1,	22,	"486", },
-	{ 5,	-1,	23,	"P5", },
-	{ 6,	-1,	16,	"P6", },
-	{ 0xF,	-1,	16,	"P4", },	/* P4 */
-
-	{ -1,	-1,	16,	"unknown", },	/* total default */
-};
-
-
-/*
- * The AMD processors all implement the CPUID instruction.
- * The later ones also return the processor name via functions
- * 0x80000002, 0x80000003 and 0x80000004 in registers AX, BX, CX
- * and DX:
- *	K5	"AMD-K5(tm) Processor"
- *	K6	"AMD-K6tm w/ multimedia extensions"
- *	K6 3D	"AMD-K6(tm) 3D processor"
- *	K6 3D+	?
- */
-static X86type x86amd[] =
-{
-	{ 5,	0,	23,	"AMD-K5", },	/* guesswork */
-	{ 5,	1,	23,	"AMD-K5", },	/* guesswork */
-	{ 5,	2,	23,	"AMD-K5", },	/* guesswork */
-	{ 5,	3,	23,	"AMD-K5", },	/* guesswork */
-	{ 5,	4,	23,	"AMD Geode GX1", },	/* guesswork */
-	{ 5,	5,	23,	"AMD Geode GX2", },	/* guesswork */
-	{ 5,	6,	11,	"AMD-K6", },	/* trial and error */
-	{ 5,	7,	11,	"AMD-K6", },	/* trial and error */
-	{ 5,	8,	11,	"AMD-K6-2", },	/* trial and error */
-	{ 5,	9,	11,	"AMD-K6-III", },/* trial and error */
-	{ 5,	0xa,	23,	"AMD Geode LX", },	/* guesswork */
-
-	{ 6,	1,	11,	"AMD-Athlon", },/* trial and error */
-	{ 6,	2,	11,	"AMD-Athlon", },/* trial and error */
-
-	{ 4,	-1,	22,	"Am486", },	/* guesswork */
-	{ 5,	-1,	23,	"AMD-K5/K6", },	/* guesswork */
-	{ 6,	-1,	11,	"AMD-Athlon", },/* guesswork */
-	{ 0xF,	-1,	11,	"AMD64", },	/* guesswork */
-
-	{ -1,	-1,	11,	"unknown", },	/* total default */
-};
-
-static X86type	*cputype;
-
-
-void
-delay(int millisecs)
-{
-	millisecs *= loopconst;
-	if(millisecs <= 0)
-		millisecs = 1;
-	aamloop(millisecs);
-}
-
-void
-microdelay(int microsecs)
-{
-	microsecs *= loopconst;
-	microsecs /= 1000;
-	if(microsecs <= 0)
-		microsecs = 1;
-	aamloop(microsecs);
-}
-
-extern void cpuid(char*, int*, int*);
-
-X86type*
-cpuidentify(void)
-{
-	int family, model;
-	X86type *t;
-	char cpuidid[16];
-	int cpuidax, cpuiddx;
-
-	cpuid(cpuidid, &cpuidax, &cpuiddx);
-	if(strncmp(cpuidid, "AuthenticAMD", 12) == 0 ||
-	   strncmp(cpuidid, "Geode by NSC", 12) == 0)
-		t = x86amd;
-	else
-		t = x86intel;
-	family = X86FAMILY(cpuidax);
-	model = X86MODEL(cpuidax);
-	if (0)
-		print("cpuidentify: cpuidax 0x%ux cpuiddx 0x%ux\n",
-			cpuidax, cpuiddx);
-	while(t->name){
-		if((t->family == family && t->model == model)
-		|| (t->family == family && t->model == -1)
-		|| (t->family == -1))
-			break;
-		t++;
-	}
-	if(t->name == nil)
-		panic("cpuidentify");
-
-	if(cpuiddx & 0x10){
-		havetsc = 1;
-		if(cpuiddx & 0x20)
-			wrmsr(0x10, 0);
-	}
-
-	return t;
-}
-
-void
-clockinit(void)
-{
-	uvlong a, b, cpufreq;
-	int loops, incr, x, y;
-	X86type *t;
-
-	/*
-	 *  set vector for clock interrupts
-	 */
-	setvec(VectorCLOCK, clockintr, 0);
-
-	t = cpuidentify();
-
-	/*
-	 *  set clock for 1/HZ seconds
-	 */
-	outb(Tmode, Load0|Square);
-	outb(T0cntr, (Freq/HZ));	/* low byte */
-	outb(T0cntr, (Freq/HZ)>>8);	/* high byte */
-
-	/*
-	 * Introduce a little delay to make sure the count is
-	 * latched and the timer is counting down; with a fast
-	 * enough processor this may not be the case.
-	 * The i8254 (which this probably is) has a read-back
-	 * command which can be used to make sure the counting
-	 * register has been written into the counting element.
-	 */
-	x = (Freq/HZ);
-	for(loops = 0; loops < 100000 && x >= (Freq/HZ); loops++){
-		outb(Tmode, Latch0);
-		x = inb(T0cntr);
-		x |= inb(T0cntr)<<8;
-	}
-
-	/* find biggest loop that doesn't wrap */
-	incr = 16000000/(t->aalcycles*HZ*2);
-	x = 2000;
-	for(loops = incr; loops < 64*1024; loops += incr) {
-	
-		/*
-		 *  measure time for the loop
-		 *
-		 *			MOVL	loops,CX
-		 *	aaml1:	 	AAM
-		 *			LOOP	aaml1
-		 *
-		 *  the time for the loop should be independent of external
-		 *  cache and memory system since it fits in the execution
-		 *  prefetch buffer.
-		 *
-		 */
-		outb(Tmode, Latch0);
-		if(havetsc)
-			_cycles(&a);
-		x = inb(T0cntr);
-		x |= inb(T0cntr)<<8;
-		aamloop(loops);
-		outb(Tmode, Latch0);
-		if(havetsc)
-			_cycles(&b);
-		y = inb(T0cntr);
-		y |= inb(T0cntr)<<8;
-		x -= y;
-	
-		if(x < 0)
-			x += Freq/HZ;
-
-		if(x > Freq/(3*HZ))
-			break;
-	}
-
-	/*
- 	 *  figure out clock frequency and a loop multiplier for delay().
-	 *  counter  goes at twice the frequency, once per transition,
-	 *  i.e., twice per square wave
-	 */
-	cpufreq = (vlong)loops*((t->aalcycles*2*Freq)/x);
-	loopconst = (cpufreq/1000)/t->aalcycles;	/* AAM+LOOP's for 1 ms */
-
-	if(havetsc){
-		/* counter goes up by 2*Freq */
-		b = (b-a)<<1;
-		b *= Freq;
-		b /= x;
-
-		/*
-		 *  round to the nearest megahz
-		 */
-		cpumhz = (b+500000)/1000000L;
-		cpuhz = b;
-	}
-	else{
-		/*
-		 *  add in possible .5% error and convert to MHz
-		 */
-		cpumhz = (cpufreq + cpufreq/200)/1000000;
-		cpuhz = cpufreq;
-	}
-
-	if(debug){
-		int timeo;
-
-		print("%dMHz %s loop %d\n", cpumhz, t->name, loopconst);
-		print("tick...");
-		for(timeo = 0; timeo < 10; timeo++)
-			delay(1000);
-		print("tock...\n");
-	}
-}
--- a/os/boot/pc/conf.c
+++ /dev/null
@@ -1,537 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-#include "fs.h"
-
-/*
- * Where configuration info is left for the loaded programme.
- * This will turn into a structure as more is done by the boot loader
- * (e.g. why parse the .ini file twice?).
- * There are 3584 bytes available at CONFADDR.
- *
- * The low-level boot routines in l.s leave data for us at CONFADDR,
- * which we pick up before reading the plan9.ini file.
- */
-#define BOOTLINELEN	64
-#define BOOTARGS	((char*)(CONFADDR+BOOTLINELEN))
-#define	BOOTARGSLEN	(3584-0x200-BOOTLINELEN)
-#define	MAXCONF		100
-
-static char *confname[MAXCONF];
-static char *confval[MAXCONF];
-static int nconf;
-
-extern char **ini;
-
-typedef struct {
-	char*	name;
-	int	start;
-	int	end;
-} Mblock;
-
-typedef struct {
-	char*	tag;
-	Mblock*	mb;
-} Mitem;
-
-static Mblock mblock[MAXCONF];
-static int nmblock;
-static Mitem mitem[MAXCONF];
-static int nmitem;
-static char* mdefault;
-static char mdefaultbuf[10];
-static int mtimeout;
-
-static char*
-comma(char* line, char** residue)
-{
-	char *q, *r;
-
-	if((q = strchr(line, ',')) != nil){
-		*q++ = 0;
-		if(*q == ' ')
-			q++;
-	}
-	*residue = q;
-
-	if((r = strchr(line, ' ')) != nil)
-		*r = 0;
-
-	if(*line == ' ')
-		line++;
-	return line;
-}
-
-static Mblock*
-findblock(char* name, char** residue)
-{
-	int i;
-	char *p;
-
-	p = comma(name, residue);
-	for(i = 0; i < nmblock; i++){
-		if(strcmp(p, mblock[i].name) == 0)
-			return &mblock[i];
-	}
-	return nil;
-}
-
-static Mitem*
-finditem(char* name, char** residue)
-{
-	int i;
-	char *p;
-
-	p = comma(name, residue);
-	for(i = 0; i < nmitem; i++){
-		if(strcmp(p, mitem[i].mb->name) == 0)
-			return &mitem[i];
-	}
-	return nil;
-}
-
-static void
-parsemenu(char* str, char* scratch, int len)
-{
-	Mitem *mi;
-	Mblock *mb, *menu;
-	char buf[20], *p, *q, *line[MAXCONF];
-	int i, inblock, n, show;
-
-	inblock = 0;
-	menu = nil;
-	memmove(scratch, str, len);
-	n = getfields(scratch, line, MAXCONF, '\n');
-	if(n >= MAXCONF)
-		print("warning: possibly too many lines in plan9.ini\n");
-	for(i = 0; i < n; i++){
-		p = line[i];
-		if(inblock && *p == '['){
-			mblock[nmblock].end = i;
-			if(strcmp(mblock[nmblock].name, "menu") == 0)
-				menu = &mblock[nmblock];
-			nmblock++;
-			inblock = 0;
-		}
-		if(*p == '['){
-			if(nmblock == 0 && i != 0){
-				mblock[nmblock].name = "common";
-				mblock[nmblock].start = 0;
-				mblock[nmblock].end = i;
-				nmblock++;
-			}
-			q = strchr(p+1, ']');
-			if(q == nil || *(q+1) != 0){
-				print("malformed menu block header - %s\n", p);
-				return;
-			}
-			*q = 0;
-			mblock[nmblock].name = p+1;
-			mblock[nmblock].start = i+1;
-			inblock = 1;
-		}
-	}
-
-	if(inblock){
-		mblock[nmblock].end = i;
-		nmblock++;
-	}
-	if(menu == nil)
-		return;
-	if(nmblock < 2){
-		print("incomplete menu specification\n");
-		return;
-	}
-
-	for(i = menu->start; i < menu->end; i++){
-		p = line[i];
-		if(cistrncmp(p, "menuitem=", 9) == 0){
-			p += 9;
-			if((mb = findblock(p, &q)) == nil){
-				print("no block for menuitem %s\n", p);
-				return;
-			}
-			if(q != nil)
-				mitem[nmitem].tag = q;
-			else
-				mitem[nmitem].tag = mb->name;
-			mitem[nmitem].mb = mb;
-			nmitem++;
-		}
-		else if(cistrncmp(p, "menudefault=", 12) == 0){
-			p += 12;
-			if((mi = finditem(p, &q)) == nil){
-				print("no item for menudefault %s\n", p);
-				return;
-			}
-			if(q != nil)
-				mtimeout = strtol(q, 0, 0);
-			sprint(mdefaultbuf, "%ld", mi-mitem+1);
-			mdefault = mdefaultbuf;
-		}
-		else if(cistrncmp(p, "menuconsole=", 12) == 0){
-			p += 12;
-			p = comma(p, &q);
-			consinit(p, q);
-		}
-		else{
-			print("invalid line in [menu] block - %s\n", p);
-			return;
-		}
-	}
-
-again:
-	print("\nPlan 9 Startup Menu:\n====================\n");
-	for(i = 0; i < nmitem; i++)
-		print("    %d. %s\n", i+1, mitem[i].tag);
-	for(;;){
-		getstr("Selection", buf, sizeof(buf), mdefault, mtimeout);
-		mtimeout = 0;
-		i = strtol(buf, &p, 0)-1;
-		if(i < 0 || i >= nmitem)
-			goto again;
-		switch(*p){
-		case 'p':
-		case 'P':
-			show = 1;
-			print("\n");
-			break;
-		case 0:
-			show = 0;
-			break;
-		default:
-			continue;
-			
-		}
-		mi = &mitem[i];
-	
-		p = str;
-		p += sprint(p, "menuitem=%s\n", mi->mb->name);
-		for(i = 0; i < nmblock; i++){
-			mb = &mblock[i];
-			if(mi->mb != mb && cistrcmp(mb->name, "common") != 0)
-				continue;
-			for(n = mb->start; n < mb->end; n++)
-				p += sprint(p, "%s\n", line[n]);
-		}
-
-		if(show){
-			for(q = str; q < p; q += i){
-				if((i = print(q)) <= 0)
-					break;
-			}
-			goto again;
-		}
-		break;
-	}
-	print("\n");
-}
-
-/*
-static void
-msleep(int msec)
-{
-	ulong start;
-
-	for(start = m->ticks; TK2MS(m->ticks - start) < msec; )
-		;
-}
-*/
-
-void
-readlsconf(void)
-{
-	uchar *p;
-
-	p = (uchar*)CONFADDR;
-	for(;;) {
-		if(strcmp((char*)p, "APM") == 0){
-			apm.haveinfo = 1;
-			apm.ax = *(ushort*)(p+4);
-			apm.cx = *(ushort*)(p+6);
-			apm.dx = *(ushort*)(p+8);
-			apm.di = *(ushort*)(p+10);
-			apm.ebx = *(ulong*)(p+12);
-			apm.esi = *(ulong*)(p+16);
-			print("apm ax=%x cx=%x dx=%x di=%x ebx=%x esi=%x\n",
-				apm.ax, apm.cx, apm.dx, apm.di, apm.ebx, apm.esi);
-			p += 20;
-			continue;
-		}
-		break;
-	}
-}
-
-char*
-getconf(char *name)
-{
-	int i, n, nmatch;
-	char buf[20];
-
-	nmatch = 0;
-	for(i = 0; i < nconf; i++)
-		if(cistrcmp(confname[i], name) == 0)
-			nmatch++;
-
-	switch(nmatch) {
-	default:
-		print("\n");
-		nmatch = 0;
-		for(i = 0; i < nconf; i++)
-			if(cistrcmp(confname[i], name) == 0)
-				print("%d. %s\n", ++nmatch, confval[i]);
-		print("%d. none of the above\n", ++nmatch);
-		do {
-			getstr(name, buf, sizeof(buf), nil, 0);
-			n = atoi(buf);
-		} while(n < 1 || n > nmatch);
-
-		for(i = 0; i < nconf; i++)
-			if(cistrcmp(confname[i], name) == 0)
-				if(--n == 0)
-					return confval[i];
-		break;
-
-	case 1:
-		for(i = 0; i < nconf; i++)
-			if(cistrcmp(confname[i], name) == 0)
-				return confval[i];
-		break;
-
-	case 0:
-		break;
-	}
-	return nil;
-}
-
-void
-addconf(char *fmt, ...)
-{
-	va_list arg;
-
-	va_start(arg, fmt);
-	vseprint(BOOTARGS+strlen(BOOTARGS), BOOTARGS+BOOTARGSLEN, fmt, arg);
-	va_end(arg);
-}
-
-void
-changeconf(char *fmt, ...)
-{
-	va_list arg;
-	char *p, *q, pref[20], buf[128];
-
-	va_start(arg, fmt);
-	vseprint(buf, buf+sizeof buf, fmt, arg);
-	va_end(arg);
-	strncpy(pref+1, buf, 19);
-	pref[19] = '\0';
-	if(p = strchr(pref, '='))
-		*(p+1) = '\0';
-	else
-		print("warning: did not change %s in plan9.ini\n", buf);
-
-	/* find old line by looking for \nwhat= */
-	pref[0] = '\n';
-	if(strncmp(BOOTARGS, pref+1, strlen(pref+1)) == 0)
-		p = BOOTARGS;
-	else if(p = strstr(BOOTARGS, pref))
-		p++;
-	else
-		p = nil;
-
-	/* move rest of args up, deleting what= line. */
-	if(p != nil && (q = strchr(p, '\n')) != nil)
-		memmove(p, q+1, strlen(q+1)+1);
-
-	/* add replacement to end */
-	addconf("%s", buf);
-}
-
-/*
- *  read configuration file
- */
-static char inibuf[BOOTARGSLEN];
-static char id[8] = "ZORT 0\r\n";
-
-int
-dotini(Fs *fs)
-{
-	File rc;
-	int blankline, i, incomment, inspace, n;
-	char *cp, *p, *q, *line[MAXCONF];
-
-	if(fswalk(fs, *ini, &rc) <= 0)
-		return -1;
-
-	cp = inibuf;
-	*cp = 0;
-	n = fsread(&rc, cp, BOOTARGSLEN-1);
-	if(n <= 0)
-		return -1;
-
-	cp[n] = 0;
-
-	/*
-	 * Strip out '\r', change '\t' -> ' '.
-	 * Change runs of spaces into single spaces.
-	 * Strip out trailing spaces, blank lines.
-	 *
-	 * We do this before we make the copy so that if we 
-	 * need to change the copy, it is already fairly clean.
-	 * The main need is in the case when plan9.ini has been
-	 * padded with lots of trailing spaces, as is the case 
-	 * for those created during a distribution install.
-	 */
-	p = cp;
-	blankline = 1;
-	incomment = inspace = 0;
-	for(q = cp; *q; q++){
-		if(*q == '\r')
-			continue;
-		if(*q == '\t')
-			*q = ' ';
-		if(*q == ' '){
-			inspace = 1;
-			continue;
-		}
-		if(*q == '\n'){
-			if(!blankline){
-				if(!incomment)
-					*p++ = '\n';
-				blankline = 1;
-			}
-			incomment = inspace = 0;
-			continue;
-		}
-		if(inspace){
-			if(!blankline && !incomment)
-				*p++ = ' ';
-			inspace = 0;
-		}
-		if(blankline && *q == '#')
-			incomment = 1;
-		blankline = 0;
-		if(!incomment)
-			*p++ = *q;	
-	}
-	if(p > cp && p[-1] != '\n')
-		*p++ = '\n';
-	*p++ = 0;
-	n = p-cp;
-
-	parsemenu(cp, BOOTARGS, n);
-
-	/*
-	 * Keep a copy.
-	 * We could change this to pass the parsed strings
-	 * to the booted programme instead of the raw
-	 * string, then it only gets done once.
-	 */
-	if(strncmp(cp, id, sizeof(id))){
-		memmove(BOOTARGS, id, sizeof(id));
-		if(n+1+sizeof(id) >= BOOTARGSLEN)
-			n -= sizeof(id);
-		memmove(BOOTARGS+sizeof(id), cp, n+1);
-	}
-	else
-		memmove(BOOTARGS, cp, n+1);
-
-	n = getfields(cp, line, MAXCONF, '\n');
-	for(i = 0; i < n; i++){
-		cp = strchr(line[i], '=');
-		if(cp == 0)
-			continue;
-		*cp++ = 0;
-		if(cp - line[i] >= NAMELEN+1)
-			*(line[i]+NAMELEN-1) = 0;
-		confname[nconf] = line[i];
-		confval[nconf] = cp;
-		nconf++;
-	}
-	return 0;
-}
-
-static int
-parseether(uchar *to, char *from)
-{
-	char nip[4];
-	char *p;
-	int i;
-
-	p = from;
-	while(*p == ' ')
-		++p;
-	for(i = 0; i < 6; i++){
-		if(*p == 0)
-			return -1;
-		nip[0] = *p++;
-		if(*p == 0)
-			return -1;
-		nip[1] = *p++;
-		nip[2] = 0;
-		to[i] = strtoul(nip, 0, 16);
-		if(*p == ':')
-			p++;
-	}
-	return 0;
-}
-
-int
-isaconfig(char *class, int ctlrno, ISAConf *isa)
-{
-	char cc[NAMELEN], *p, *q, *r;
-	int n;
-
-	sprint(cc, "%s%d", class, ctlrno);
-	for(n = 0; n < nconf; n++){
-		if(cistrncmp(confname[n], cc, NAMELEN))
-			continue;
-		isa->nopt = 0;
-		p = confval[n];
-		while(*p){
-			while(*p == ' ' || *p == '\t')
-				p++;
-			if(*p == '\0')
-				break;
-			if(cistrncmp(p, "type=", 5) == 0){
-				p += 5;
-				for(q = isa->type; q < &isa->type[NAMELEN-1]; q++){
-					if(*p == '\0' || *p == ' ' || *p == '\t')
-						break;
-					*q = *p++;
-				}
-				*q = '\0';
-			}
-			else if(cistrncmp(p, "port=", 5) == 0)
-				isa->port = strtoul(p+5, &p, 0);
-			else if(cistrncmp(p, "irq=", 4) == 0)
-				isa->irq = strtoul(p+4, &p, 0);
-			else if(cistrncmp(p, "mem=", 4) == 0)
-				isa->mem = strtoul(p+4, &p, 0);
-			else if(cistrncmp(p, "size=", 5) == 0)
-				isa->size = strtoul(p+5, &p, 0);
-			else if(cistrncmp(p, "ea=", 3) == 0){
-				if(parseether(isa->ea, p+3) == -1)
-					memset(isa->ea, 0, 6);
-			}
-			else if(isa->nopt < NISAOPT){
-				r = isa->opt[isa->nopt];
-				while(*p && *p != ' ' && *p != '\t'){
-					*r++ = *p++;
-					if(r-isa->opt[isa->nopt] >= ISAOPTLEN-1)
-						break;
-				}
-				*r = '\0';
-				isa->nopt++;
-			}
-			while(*p && *p != ' ' && *p != '\t')
-				p++;
-		}
-		return 1;
-	}
-	return 0;
-}
--- a/os/boot/pc/console.c
+++ /dev/null
@@ -1,236 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-IOQ consiq;
-IOQ consoq;
-
-static int useuart;
-
-int	debug = 0;
-
-void
-kbdchar(int c)
-{
-	c &= 0x7F;
-	if(c == 0x10)
-		warp86("\n^P\n", 0);
-	if(c == 0x12)
-		debug = !debug;
-	consiq.putc(&consiq, c);
-}
-
-static int
-consputc(void)
-{
-	return consoq.getc(&consoq);
-}
-
-void
-kbdinit(void)
-{
-	i8042init();
-	qinit(&consiq);
-}
-
-void
-consinit(char* name, char* speed)
-{
-	int baud, port;
-
-	if(name == nil || cistrcmp(name, "cga") == 0)
-		return;
-	port = strtoul(name, 0, 0);
-	if(port < 0 || port > 1)
-		return;
-	if(speed == nil || (baud = strtoul(speed, 0, 0)) == 0)
-		baud = 9600;
-
-	qinit(&consoq);
-
-	uartspecial(port, kbdchar, consputc, baud);
-	useuart = 1;
-	uartputs(&consoq, "\n", 1);
-}
-
-void
-consdrain(void)
-{
-	if(useuart)
-		uartdrain();
-}
-
-void
-consputs(char* s, int n)
-{
-	cgascreenputs(s, n);
-	if(useuart)
-		uartputs(&consoq, s, n);
-}
-
-void
-warp86(char* s, ulong)
-{
-	if(s != nil)
-		print(s);
-	spllo();
-	consdrain();
-
-	i8042reset();
-	print("Takes a licking and keeps on ticking...\n");
-	for(;;)
-		idle();
-}
-
-static int
-getline(char *buf, int size, int timeout)
-{
-	int c, i=0;
-	ulong start;
-	char echo;
-
-	for (;;) {
-		start = m->ticks;
-		do{
-			/* timeout seconds to first char */
-			if(timeout && ((m->ticks - start) > timeout*HZ))
-				return -2;
-			c = consiq.getc(&consiq);
-		}while(c == -1);
-		timeout = 0;
-
-		if(c == '\r')
-			c = '\n'; 		/* turn carriage return into newline */
-		if(c == '\177')
-			c = '\010';		/* turn delete into backspace */
-		if(c == '\025')
-			echo = '\n';		/* echo ^U as a newline */
-		else
-			echo = c;
-		consputs(&echo, 1);
-
-		if(c == '\010'){
-			if(i > 0)
-				i--; /* bs deletes last character */
-			continue;
-		}
-		/* a newline ends a line */
-		if (c == '\n')
-			break;
-		/* ^U wipes out the line */
-		if (c =='\025')
-			return -1;
-		if(i == size)
-			return size;
-		buf[i++] = c;
-	}
-	buf[i] = 0;
-	return i;
-}
-
-int
-getstr(char *prompt, char *buf, int size, char *def, int timeout)
-{
-	int len, isdefault;
-	char pbuf[PRINTSIZE];
-
-	buf[0] = 0;
-	isdefault = (def && *def);
-	if(isdefault == 0){
-		timeout = 0;
-		sprint(pbuf, "%s: ", prompt);
-	}
-	else if(timeout)
-		sprint(pbuf, "%s[default==%s (%ds timeout)]: ", prompt, def, timeout);
-	else
-		sprint(pbuf, "%s[default==%s]: ", prompt, def);
-	for (;;) {
-		print(pbuf);
-		len = getline(buf, size, timeout);
-		switch(len){
-		case 0:
-			/* RETURN */
-			if(isdefault)
-				break;
-			continue;
-		case -1:
-			/* ^U typed */
-			continue;
-		case -2:
-			/* timeout, use default */
-			consputs("\n", 1);
-			len = 0;
-			break;
-		default:
-			break;
-		}
-		if(len >= size){
-			print("line too long\n");
-			continue;
-		}
-		break;
-	}
-	if(len == 0 && isdefault)
-		strcpy(buf, def);
-	return 0;
-}
-
-int
-print(char *fmt, ...)
-{
-	int n;
-	va_list arg;
-	char buf[PRINTSIZE];
-
-	va_start(arg, fmt);
-	n = vseprint(buf, buf+sizeof(buf), fmt, arg) - buf;
-	va_end(arg);
-	consputs(buf, n);
-
-	return n;
-}
-
-int
-sprint(char *s, char *fmt, ...)
-{
-	int n;
-	va_list arg;
-
-	va_start(arg, fmt);
-	n = vseprint(s, s+PRINTSIZE, fmt, arg) - s;
-	va_end(arg);
-
-	return n;
-}
-
-void
-panic(char *fmt, ...)
-{
-	int n;
-	va_list arg;
-	char buf[PRINTSIZE];
-
-	strcpy(buf, "panic: ");
-	va_start(arg, fmt);
-	n = vseprint(buf+7, buf+sizeof(buf), fmt, arg) - buf;
-	va_end(arg);
-	buf[n] = '\n';
-	consputs(buf, n+1);
-
-//floppymemwrite();
-//splhi(); for(;;);
-	if(etherdetach)
-		etherdetach();
-	if(sddetach)
-		sddetach();
-
-	consputs("\nPress almost any key to reset...", 32);
-	spllo();
-	while(consiq.getc(&consiq) == -1)
-		;
-
-	warp86(nil, 0);
-}
--- a/os/boot/pc/dat.h
+++ /dev/null
@@ -1,215 +1,0 @@
-typedef struct List {
-	void	*next;
-} List;
-
-typedef struct Alarm Alarm;
-typedef struct Alarm {
-	List;
-	int	busy;
-	long	dt;
-	void	(*f)(Alarm*);
-	void	*arg;
-} Alarm;
-
-typedef struct Apminfo {
-	int haveinfo;
-	int ax;
-	int cx;
-	int dx;
-	int di;
-	int ebx;
-	int esi;
-} Apminfo;
-
-typedef struct Block Block;
-struct Block {
-	Block*	next;
-	uchar*	rp;			/* first unconsumed byte */
-	uchar*	wp;			/* first empty byte */
-	uchar*	lim;			/* 1 past the end of the buffer */
-	uchar*	base;			/* start of the buffer */
-	ulong	flag;
-};
-#define BLEN(s)	((s)->wp - (s)->rp)
-
-typedef struct IOQ IOQ;
-typedef struct IOQ {
-	uchar	buf[4096];
-	uchar	*in;
-	uchar	*out;
-	int	state;
-	int	(*getc)(IOQ*);
-	int	(*putc)(IOQ*, int);
-	void	*ptr;
-};
-
-enum {
-	Eaddrlen	= 6,
-	/* next two exclude 4-byte ether CRC */
-	ETHERMINTU	= 60,		/* minimum transmit size */
-	ETHERMAXTU	= 1514,		/* maximum transmit size */
-	ETHERHDRSIZE	= 14,		/* size of an ethernet header */
-
-	MaxEther	= 6,
-};
-
-typedef struct {
-	uchar	d[Eaddrlen];
-	uchar	s[Eaddrlen];
-	uchar	type[2];
-	uchar	data[1500];
-	uchar	crc[4];
-} Etherpkt;
-
-extern uchar broadcast[Eaddrlen];
-
-typedef struct Ureg Ureg;
-#pragma incomplete Ureg
-
-typedef struct Segdesc {
-	ulong	d0;
-	ulong	d1;
-} Segdesc;
-
-typedef struct Mach {
-	ulong	ticks;			/* of the clock since boot time */
-	void	*alarm;			/* alarms bound to this clock */
-} Mach;
-
-extern Mach *m;
-
-#define I_MAGIC		((((4*11)+0)*11)+7)
-
-typedef struct Exec Exec;
-struct	Exec
-{
-	uchar	magic[4];		/* magic number */
-	uchar	text[4];	 	/* size of text segment */
-	uchar	data[4];	 	/* size of initialized data */
-	uchar	bss[4];	  		/* size of uninitialized data */
-	uchar	syms[4];	 	/* size of symbol table */
-	uchar	entry[4];	 	/* entry point */
-	uchar	spsz[4];		/* size of sp/pc offset table */
-	uchar	pcsz[4];		/* size of pc/line number table */
-};
-
-/*
- *  a parsed .ini line
- */
-#define ISAOPTLEN	32
-#define NISAOPT		8
-
-typedef struct  ISAConf {
-	char	type[NAMELEN];
-	ulong	port;
-	ulong	irq;
-	ulong	mem;
-	ulong	size;
-	uchar	ea[6];
-
-	int	nopt;
-	char	opt[NISAOPT][ISAOPTLEN];
-} ISAConf;
-
-typedef struct Pcidev Pcidev;
-typedef struct PCMmap PCMmap;
-typedef struct PCMslot PCMslot;
-
-#define BOOTLINE	((char*)CONFADDR)
-
-enum {
-	MB =		(1024*1024),
-};
-#define ROUND(s, sz)	(((s)+((sz)-1))&~((sz)-1))
-
-
-typedef struct Type Type;
-typedef struct Medium Medium;
-typedef struct Boot Boot;
-
-enum {					/* type */
-	Tnil		= 0x00,
-
-	Tfloppy		= 0x01,
-	Tsd		= 0x02,
-	Tether		= 0x03,
-	Tcd		= 0x04,
-	Tbios		= 0x05,
-
-	Tany		= -1,
-};
-
-enum {					/* name and flag */
-	Fnone		= 0x00,
-
-	Nfs		= 0x00,
-	Ffs		= (1<<Nfs),
-	Nboot		= 0x01,
-	Fboot		= (1<<Nboot),
-	Nbootp		= 0x02,
-	Fbootp		= (1<<Nbootp),
-	NName		= 3,
-
-	Fany		= Fbootp|Fboot|Ffs,
-
-	Fini		= 0x10,
-	Fprobe		= 0x80,
-};
-
-typedef struct Type {
-	int	type;
-	int	flag;
-	int	(*init)(void);
-	void	(*initdev)(int, char*);
-	void*	(*getfspart)(int, char*, int);	/* actually returns Dos* */
-	void	(*addconf)(int);
-	int	(*boot)(int, char*, Boot*);
-	void	(*printdevs)(int);
-	char**	parts;
-	char**	inis;
-	int	mask;
-	Medium*	media;
-} Type;
-
-extern void (*etherdetach)(void);
-extern void (*floppydetach)(void);
-extern void (*sddetach)(void);
-
-typedef struct Lock {	/* for ilock, iunlock */
-	int locked;
-	int spl;
-} Lock;
-
-enum {	/* returned by bootpass */
-	MORE, ENOUGH, FAIL
-};
-enum {
-	INITKERNEL,
-	READEXEC,
-	READ9TEXT,
-	READ9DATA,
-	READGZIP,
-	READEHDR,
-	READPHDR,
-	READEPAD,
-	READEDATA,
-	TRYBOOT,
-	INIT9LOAD,
-	READ9LOAD,
-	FAILED
-};
-
-struct Boot {
-	int state;
-
-	Exec exec;
-	char *bp;	/* base ptr */
-	char *wp;	/* write ptr */
-	char *ep;	/* end ptr */
-};
-
-extern int	debug;
-extern Apminfo	apm;
-extern char	*defaultpartition;
-extern int	iniread;
-extern int	pxe;
--- a/os/boot/pc/devbios.c
+++ /dev/null
@@ -1,428 +1,0 @@
-/*
- * boot driver for BIOS devices
- */
-#include <u.h>
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-#include "ureg.h"
-#include "fs.h"
-
-typedef uvlong Devbytes, Devsects;
-
-typedef struct Biosdrive Biosdrive;	/* 1 drive -> ndevs */
-typedef struct Biosdev Biosdev;
-
-enum {
-	Debug = 0,
-	Maxdevs = 4,
-
-	CF = 1,
-	Flopid = 0,			/* first floppy */
-	Baseid = 0x80,			/* first disk */
-
-	/* bios calls: int 13 disk services */
-	Biosinit	= 0,		/* initialise disk & floppy ctlrs */
-	Biosdrvsts,
-	Bioschsrdsects,
-	Biosdrvparam	= 8,
-	Biosctlrinit,
-	Biosreset	=  0xd,		/* reset disk */
-	Biosdrvrdy	= 0x10,
-	Biosdrvtype	= 0x15,
-	Biosckext	= 0x41,
-	Biosrdsect,
-	Biosedrvparam	= 0x48,
-
-	/* disk types */
-	Typenone = 0,
-	Typedisk = 3,
-};
-
-struct Biosdrive {
-	int	ndevs;
-};
-struct Biosdev {
-	Devbytes size;
-	Devbytes offset;
-	uchar	id;			/* drive number; e.g., 0x80 */
-	char	type;
-	ushort	sectsz;
-};
-
-typedef struct Extread {
-	uchar	size;
-	uchar	unused1;
-	uchar	nsects;
-	uchar	unused2;
-	ulong	addr;		/* segment:offset */
-	uvlong	stsect;		/* starting sector */
-} Extread;
-typedef struct Edrvparam {
-	/* from edd 1.1 spec */
-	ushort	size;			/* max. buffer size */
-	ushort	flags;
-	ulong	physcyls;
-	ulong	physheads;
-	ulong	phystracksects;
-	uvlong	physsects;
-	ushort	sectsz;
-	void	*dpte;			/* ~0ull: invalid */
-
-	/* remainder from edd 3.0 spec */
-	ushort	key;			/* 0xbedd if present */
-	uchar	dpilen;
-	uchar	unused1;
-	ushort	unused2;
-	char	bustype[4];		/* "PCI" or "ISA" */
-	char	ifctype[8]; /* "ATA", "ATAPI", "SCSI", "USB", "1394", "FIBRE" */
-	uvlong	ifcpath;
-	uvlong	devpath;
-	uchar	unused3;
-	uchar	dpicksum;
-} Edrvparam;
-
-void	realmode(int intr, Ureg *ureg);		/* from trap.c */
-
-int onlybios0;
-int biosinited;
-
-static Biosdev bdev[Maxdevs];
-static Biosdrive bdrive;
-static Ureg regs;
-
-static int	dreset(uchar drive);
-static Devbytes	extgetsize(Biosdev *);
-static Devsects	getsize(uchar drive, char *type);
-static int	islba(uchar drive);
-
-static int
-biosdiskcall(Ureg *rp, uchar op, ulong bx, ulong dx, ulong si)
-{
-	memset(rp, 0, sizeof *rp);
-	rp->ax = op << 8;
-	rp->bx = bx;
-	rp->dx = dx;			/* often drive id */
-	rp->si = si;
-	/* pass command in *rp, get results from there */
-	realmode(0x13, rp);
-	if (rp->flags & CF) {
-//		print("biosdiskcall: int 13 op 0x%ux drive 0x%lux failed, "
-//			"ah error code 0x%ux\n", op, dx, (uchar)(rp->ax >> 8));
-		return -1;
-	}
-	return 0;
-}
-
-/*
- * Find out what the bios knows about devices.
- * our boot device could be usb; ghod only knows where it will appear.
- */
-int
-biosinit(void)
-{
-	int devid, lba, mask, lastbit;
-	Devbytes size;
-	char type;
-	Biosdev *bdp;
-	static int beenhere;
-
-	mask = lastbit = 0;
-	if (beenhere)
-		return mask;
-	beenhere = 1;
-	/* 9pxeload can't use bios int 13 calls; they wedge the machine */
-	if (pxe || getconf("*nobiosload") != nil || onlybios0 || !biosinited)
-		return mask;
-	for (devid = 0; devid < (1 << 8) && bdrive.ndevs < Maxdevs; devid++) {
-		lba = islba(devid);
-		if(!lba /* || devid != Baseid && dreset(devid) < 0 */ )
-			continue;
-		type = Typedisk;		/* HACK */
-		if (getsize(devid, &type) == 0) { /* no device, end of range */
-			devid &= ~0xf;
-			devid += 0x10;
-			devid--;
-			continue;
-		}
-		lastbit = 1 << bdrive.ndevs;
-		mask |= lastbit;
-		bdp = &bdev[bdrive.ndevs];
-		bdp->id = devid;
-		bdp->type = type;
-		size = extgetsize(bdp);
-		bdp->size = size;
-		print("bios%d: drive 0x%ux: %llud bytes, type %d\n",
-			bdrive.ndevs, devid, size, type);
-		bdrive.ndevs++;
-	}
-	/*
-	 * bioses seem to only be able to read from drive number 0x80
-	 * and certainly can't read from the highest drive number when we
-	 * call them, even if there is only one.  attempting to read from
-	 * the last drive number yields a hung machine or a two-minute pause.
-	 */
-	if (bdrive.ndevs > 0) {
-		if (bdrive.ndevs == 1) {
-			print("biosinit: sorry, only one bios drive; "
-				"can't read last one\n");
-			onlybios0 = 1;
-		} else
-			biosinited = 1;
-		bdrive.ndevs--;	/* omit last drive number; it can't be read */
-		mask &= ~lastbit;
-	}
-	return mask;
-}
-
-void
-biosinitdev(int i, char *name)
-{
-	if(i >= bdrive.ndevs)
-		panic("biosinitdev");
-	sprint(name, "bios%d", i);
-}
-
-void
-biosprintdevs(int i)
-{
-	if(i >= bdrive.ndevs){
-		print("got a print for %d, only got %d\n", i, bdrive.ndevs);
-		panic("biosprintdevs");
-	}
-	print(" bios%d", i);
-}
-
-int
-biosboot(int dev, char *file, Boot *b)
-{
-	Fs *fs;
-
-	if(strncmp(file, "dos!", 4) == 0)
-		file += 4;
-	if(strchr(file, '!') != nil || strcmp(file, "") == 0) {
-		print("syntax is bios0!file\n");
-		return -1;
-	}
-
-	fs = biosgetfspart(dev, "9fat", 1);
-	if(fs == nil)
-		return -1;
-	return fsboot(fs, file, b);
-}
-
-/* read n bytes at sector offset into a from drive id */
-long
-sectread(Biosdev *bdp, void *a, long n, Devsects offset)
-{
-	uchar *biosparam, *cp;
-	Extread *erp;
-
-	if(n < 0 || n > bdp->sectsz)
-		return -1;
-	if(Debug)
-		memset((uchar *)BIOSXCHG, 'r', bdp->sectsz); /* preclean the buffer. */
-
-	biosdiskcall(&regs, Biosdrvrdy, 0, bdp->id, 0);
-
-	/* space for a BIG sector, just in case... */
-	biosparam = (uchar *)BIOSXCHG + 2*1024;
-
-	/* read into BIOSXCHG */
-	erp = (Extread *)biosparam;
-	memset(erp, 0, sizeof *erp);
-	erp->size = sizeof *erp;
-	erp->nsects = 1;
-	erp->addr = PADDR(BIOSXCHG);
-	erp->stsect = offset;
-	if (biosdiskcall(&regs, Biosrdsect, 0, bdp->id, PADDR(erp)) < 0) {
-		print("sectread: bios failed to read %ld @ sector %lld of 0x%ux\n",
-			n, offset, bdp->id);
-		return -1;
-	}
-
-	/* copy into caller's buffer */
-	memmove(a, (char *)BIOSXCHG, n);
-	if(Debug){
-		cp = (uchar *)BIOSXCHG;
-		print("-%ux %ux %ux %ux--%16.16s-\n",
-			cp[0], cp[1], cp[2], cp[3], (char *)cp + 480);
-	}
-	return n;
-}
-
-/* not tested yet. */
-static int
-dreset(uchar drive)
-{
-if (0) {
-print("devbios: resetting disk controllers...");
-	biosdiskcall(&regs, Biosinit, 0, drive, 0);
-print("\n");
-}
-	return regs.ax? -1: 0;		/* ax!=0 on error */
-}
-
-static int
-islba(uchar drive)
-{
-	if (biosdiskcall(&regs, Biosckext, 0x55aa, drive, 0) < 0)
-		return 0;
-	if(regs.bx != 0xaa55){
-		print("islba: buggy bios\n");
-		return 0;
-	}
-	if (Debug)
-		print("islba: drive 0x%ux extensions version %d.%d cx 0x%lux\n",
-			drive, (uchar)(regs.ax >> 8),
-			(uchar)regs.ax, regs.cx); /* cx: 4=edd, 1=use dap */
-	return regs.cx & 1;		/* dap bit */
-}
-
-/*
- * works so so... some floppies are 0x80+x when they shouldn't be,
- * and report lba even if they cannot...
- */
-static Devsects
-getsize(uchar id, char *typep)
-{
-	int dtype;
-
-	if (biosdiskcall(&regs, Biosdrvtype, 0x55aa, id, 0) < 0)
-		return 0;
-
-	dtype = (ushort)regs.ax >> 8;
-	if(dtype == Typenone){
-		print("no such device 0x%ux of type %d\n", id, dtype);
-		return 0;
-	}
-	if(dtype != Typedisk){
-		print("non-disk device 0x%ux of type %d\n", id, dtype);
-		return 0;
-	}
-	*typep = dtype;
-	return (ushort)regs.cx | regs.dx << 16;
-}
-
-/* extended get size */
-static Devbytes
-extgetsize(Biosdev *bdp)
-{
-	Edrvparam *edp;
-
-	edp = (Edrvparam *)BIOSXCHG;
-	memset(edp, 0, sizeof *edp);
-	edp->size = sizeof *edp;
-	edp->dpilen = 36;
-	if (biosdiskcall(&regs, Biosedrvparam, 0, bdp->id, PADDR(edp)) < 0)
-		return 0;
-	if(Debug) {
-		print("extgetsize: drive 0x%ux info flags 0x%ux",
-			bdp->id, edp->flags);
-		if (edp->key == 0xbedd)
-			print(" %s %s", edp->bustype, edp->ifctype);
-		print("\n");
-	}
-	if (edp->sectsz <= 0) {
-		print("extgetsize: drive 0x%ux: non-positive sector size\n",
-			bdp->id);
-		edp->sectsz = 1;		/* don't divide by zero */
-	}
-	bdp->sectsz = edp->sectsz;
-	return edp->physsects * edp->sectsz;
-}
-
-long
-biosread(Fs *fs, void *a, long n)
-{
-	int want, got, part;
-	long totnr, stuck;
-	Devbytes offset;
-	Biosdev *bdp;
-
-	if(fs->dev > bdrive.ndevs)
-		return -1;
-	if (n <= 0)
-		return n;
-	bdp = &bdev[fs->dev];
-	offset = bdp->offset;
-	stuck = 0;
-	for (totnr = 0; totnr < n && stuck < 4; totnr += got) {
-		want = bdp->sectsz;
-		if (totnr + want > n)
-			want = n - totnr;
-		if(Debug)
-			print("bios%d, read: %ld @ off %lld, want: %d, id: 0x%ux\n",
-				fs->dev, n, offset, want, bdp->id);
-		part = offset % bdp->sectsz;
-		if (part != 0) {	/* back up to start of sector */
-			offset -= part;
-			totnr  -= part;
-			if (totnr < 0) {
-				print("biosread: negative count %ld\n", totnr);
-				return -1;
-			}
-		}
-		if ((vlong)offset < 0) {
-			print("biosread: negative offset %lld\n", offset);
-			return -1;
-		}
-		got = sectread(bdp, (char *)a + totnr, want, offset/bdp->sectsz);
-		if(got <= 0){
-//			print("biosread: failed to read %ld @ off %lld of 0x%ux, "
-//				"want %d got %d\n",
-//				n, offset, bdp->id, want, got);
-			return -1;
-		}
-		offset += got;
-		bdp->offset = offset;
-		if (got < bdp->sectsz)
-			stuck++;	/* we'll have to re-read this sector */
-		else
-			stuck = 0;
-	}
-	return totnr;
-}
-
-vlong
-biosseek(Fs *fs, vlong off)
-{
-	if (off < 0) {
-		print("biosseek(fs, %lld) is illegal\n", off);
-		return -1;
-	}
-	if(fs->dev > bdrive.ndevs) {
-		print("biosseek: fs->dev %d > bdrive.ndevs %d\n",
-			fs->dev, bdrive.ndevs);
-		return -1;
-	}
-	bdev[fs->dev].offset = off;	/* do not know size... (yet) */
-	return off;
-}
-
-void *
-biosgetfspart(int i, char *name, int chatty)
-{
-	static Fs fs;
-
-	if(strcmp(name, "9fat") != 0){
-		if(chatty)
-			print("unknown partition bios%d!%s (use bios%d!9fat)\n",
-				i, name, i);
-		return nil;
-	}
-
-	fs.dev = i;
-	fs.diskread = biosread;
-	fs.diskseek = biosseek;
-
-	if(dosinit(&fs) < 0){
-		if(chatty)
-			print("bios%d!%s does not contain a FAT file system\n",
-				i, name);
-		return nil;
-	}
-	return &fs;
-}
--- a/os/boot/pc/devbios.h
+++ /dev/null
@@ -1,22 +1,0 @@
-typedef uvlong Devbytes, Devsects;
-
-typedef struct Biosdrive Biosdrive;	/* 1 drive -> ndevs */
-typedef struct Biosdev Biosdev;
-
-struct Biosdrive {
-	int	ndevs;
-};
-struct Biosdev {
-	Devbytes size;
-	Devbytes offset;
-	uchar	id;
-	char	type;
-};
-
-int	biosboot(int dev, char *file, Boot *b);
-void*	biosgetfspart(int i, char *name, int chatty);
-void	biosinitdev(int i, char *name);
-int	biosinit(void);
-void	biosprintbootdevs(int dev);
-void	biosprintdevs(int i);
-long	biosread(Fs *fs, void *a, long n);
--- a/os/boot/pc/devfloppy.c
+++ /dev/null
@@ -1,853 +1,0 @@
-#include <u.h>
-
-#include	"lib.h"
-#include	"mem.h"
-#include	"dat.h"
-#include	"fns.h"
-#include	"io.h"
-#include	"ureg.h"
-
-#include	"fs.h"
-#include	"devfloppy.h"
-
-
-/* Intel 82077A (8272A compatible) floppy controller */
-
-/* This module expects the following functions to be defined
- * elsewhere: 
- * 
- * inb()
- * outb()
- * floppyexec()
- * floppyeject() 
- * floppysetup0()
- * floppysetup1()
- * dmainit()
- * dmasetup()
- * dmaend()
- * 
- * On DMA systems, floppyexec() should be an empty function; 
- * on non-DMA systems, dmaend() should be an empty function; 
- * dmasetup() may enforce maximum transfer sizes. 
- */
-
-enum {
-	/* file types */
-	Qdir=		0, 
-	Qdata=		(1<<2),
-	Qctl=		(2<<2),
-	Qmask=		(3<<2),
-
-	DMAchan=	2,	/* floppy dma channel */
-};
-
-#define DPRINT if(0)print
-
-FType floppytype[] =
-{
- { "3½HD",	T1440kb, 512, 18, 2, 1, 80, 0x1B, 0x54,	0, },
- { "3½DD",	T1440kb, 512,  9, 2, 1, 80, 0x1B, 0x54, 2, },
- { "3½DD",	T720kb,  512,  9, 2, 1, 80, 0x1B, 0x54, 2, },
- { "5¼HD",	T1200kb, 512, 15, 2, 1, 80, 0x2A, 0x50, 0, },
- { "5¼DD",	T1200kb, 512,  9, 2, 2, 40, 0x2A, 0x50, 1, },
- { "ATT3B1",	T1200kb, 512,  8, 2, 2, 48, 0x2A, 0x50, 1, },
- { "5¼DD",	T360kb,  512,  9, 2, 1, 40, 0x2A, 0x50, 2, },
-};
-
-/*
- *  bytes per sector encoding for the controller.
- *  - index for b2c is is (bytes per sector/128).
- *  - index for c2b is code from b2c
- */
-static int b2c[] =
-{
-[1]	0,
-[2]	1,
-[4]	2,
-[8]	3,
-};
-static int c2b[] =
-{
-	128,
-	256,
-	512,
-	1024,
-};
-
-FController	fl;
-
-#define MOTORBIT(i)	(1<<((i)+4))
-
-/*
- *  predeclared
- */
-static int	cmddone(void*);
-static void	floppyformat(FDrive*, char*);
-static void	floppykproc(void*);
-static void	floppypos(FDrive*,long);
-static int	floppyrecal(FDrive*);
-static int	floppyresult(void);
-static void	floppyrevive(void);
-static vlong	pcfloppyseek(FDrive*, vlong);
-static int	floppysense(void);
-static void	floppywait(int);
-static long	floppyxfer(FDrive*, int, void*, long, long);
-
-static void
-fldump(void)
-{
-	DPRINT("sra %ux srb %ux dor %ux msr %ux dir %ux\n", inb(Psra), inb(Psrb),
-		inb(Pdor), inb(Pmsr), inb(Pdir));
-}
-
-static void
-floppyalarm(Alarm* a)
-{
-	FDrive *dp;
-
-	for(dp = fl.d; dp < &fl.d[fl.ndrive]; dp++){
-		if((fl.motor&MOTORBIT(dp->dev)) && TK2SEC(m->ticks - dp->lasttouched) > 5)
-			floppyoff(dp);
-	}
-
-	alarm(5*1000, floppyalarm, 0);
-	cancel(a);
-}
-
-/*
- *  set floppy drive to its default type
- */
-static void
-floppysetdef(FDrive *dp)
-{
-	FType *t;
-
-	for(t = floppytype; t < &floppytype[nelem(floppytype)]; t++)
-		if(dp->dt == t->dt){
-			dp->t = t;
-			break;
-		}
-}
-
-static void
-_floppydetach(void)
-{
-	/*
-	 *  stop the motors
-	 */
-	fl.motor = 0;
-	delay(10);
-	outb(Pdor, fl.motor | Fintena | Fena);
-	delay(10);
-}
-
-int
-floppyinit(void)
-{
-	FDrive *dp;
-	FType *t;
-	ulong maxtsize;
-	int mask;
-
-	dmainit(DMAchan);
-
-	floppysetup0(&fl);
-
-	/*
-	 *  init dependent parameters
-	 */
-	maxtsize = 0;
-	for(t = floppytype; t < &floppytype[nelem(floppytype)]; t++){
-		t->cap = t->bytes * t->heads * t->sectors * t->tracks;
-		t->bcode = b2c[t->bytes/128];
-		t->tsize = t->bytes * t->sectors;
-		if(maxtsize < t->tsize)
-			maxtsize = t->tsize;
-	}
-
-	fl.selected = fl.d;
-
-	floppydetach = _floppydetach;
-	floppydetach();
-
-	/*
-	 *  init drives
-	 */
-	mask = 0;
-	for(dp = fl.d; dp < &fl.d[fl.ndrive]; dp++){
-		dp->dev = dp - fl.d;
-		if(dp->dt == Tnone)
-			continue;
-		mask |= 1<<dp->dev;
-		floppysetdef(dp);
-		dp->cyl = -1;			/* because we don't know */
-		dp->cache = (uchar*)xspanalloc(maxtsize, BY2PG, 64*1024);
-		dp->ccyl = -1;
-		dp->vers = 0;
-		dp->maxtries = 5;
-	}
-
-	/*
-	 *  first operation will recalibrate
-	 */
-	fl.confused = 1;
-
-	floppysetup1(&fl);
-
-	/* to turn the motor off when inactive */
-	alarm(5*1000, floppyalarm, 0);
-
-	return mask;
-}
-
-void
-floppyinitdev(int i, char *name)
-{
-	if(i >= fl.ndrive)
-		panic("floppyinitdev");
-	sprint(name, "fd%d", i);
-}
-
-void
-floppyprintdevs(int i)
-{
-	if(i >= fl.ndrive)
-		panic("floppyprintdevs");
-	print(" fd%d", i);
-}
-
-int
-floppyboot(int dev, char *file, Boot *b)
-{
-	Fs *fs;
-
-	if(strncmp(file, "dos!", 4) == 0)
-		file += 4;
-	else if(strchr(file, '!') || strcmp(file, "")==0) {
-		print("syntax is fd0!file\n");
-		return -1;
-	}
-
-	fs = floppygetfspart(dev, "dos", 1);
-	if(fs == nil)
-		return -1;
-
-	return fsboot(fs, file, b);
-}
-
-void
-floppyprintbootdevs(int dev)
-{
-	print(" fd%d", dev);
-}
-
-/*
- *  check if the floppy has been replaced under foot.  cause
- *  an error if it has.
- *
- *  a seek and a read clears the condition.  this was determined
- *  experimentally, there has to be a better way.
- *
- *  if the read fails, cycle through the possible floppy
- *  density till one works or we've cycled through all
- *  possibilities for this drive.
- */
-static int
-changed(FDrive *dp)
-{
-	FType *start;
-
-	/*
-	 *  if floppy has changed or first time through
-	 */
-	if((inb(Pdir)&Fchange) || dp->vers == 0){
-		DPRINT("changed\n");
-		fldump();
-		dp->vers++;
-		floppysetdef(dp);
-		dp->maxtries = 3;
-		start = dp->t;
-
-		/* flopppyon fails if there's no drive */
-		dp->confused = 1;	/* make floppyon recal */
-		if(floppyon(dp) < 0)
-			return -1;
-
-		pcfloppyseek(dp, dp->t->heads*dp->t->tsize);
-
-		while(floppyxfer(dp, Fread, dp->cache, 0, dp->t->tsize) <= 0){
-
-			/*
-			 *  if the xfer attempt doesn't clear the changed bit,
-			 *  there's no floppy in the drive
-			 */
-			if(inb(Pdir)&Fchange)
-				return -1;
-
-			while(++dp->t){
-				if(dp->t == &floppytype[nelem(floppytype)])
-					dp->t = floppytype;
-				if(dp->dt == dp->t->dt)
-					break;
-			}
-
-			/* flopppyon fails if there's no drive */
-			if(floppyon(dp) < 0)
-				return -1;
-
-			DPRINT("changed: trying %s\n", dp->t->name);
-			fldump();
-			if(dp->t == start)
-				return -1;
-		}
-	}
-
-	return 0;
-}
-
-static int
-readtrack(FDrive *dp, int cyl, int head)
-{
-	int i, nn, sofar;
-	ulong pos;
-
-	nn = dp->t->tsize;
-	if(dp->ccyl==cyl && dp->chead==head)
-		return nn;
-	pos = (cyl*dp->t->heads+head) * nn;
-	for(sofar = 0; sofar < nn; sofar += i){
-		dp->ccyl = -1;
-		i = floppyxfer(dp, Fread, dp->cache + sofar, pos + sofar, nn - sofar);
-		if(i <= 0)
-			return -1;
-	}
-	dp->ccyl = cyl;
-	dp->chead = head;
-	return nn;
-}
-
-long
-floppyread(Fs *fs, void *a, long n)
-{
-	FDrive *dp;
-	long rv, offset;
-	int sec, head, cyl;
-	long len;
-	uchar *aa;
-
-	aa = a;
-	dp = &fl.d[fs->dev];
-
-	offset = dp->offset;
-	floppyon(dp);
-	if(changed(dp))
-		return -1;
-
-	for(rv = 0; rv < n; rv += len){
-		/*
-		 *  all xfers come out of the track cache
-		 */
-		dp->len = n - rv;
-		floppypos(dp, offset+rv);
-		cyl = dp->tcyl;
-		head = dp->thead;
-		len = dp->len;
-		sec = dp->tsec;
-		if(readtrack(dp, cyl, head) < 0)
-			break;
-		memmove(aa+rv, dp->cache + (sec-1)*dp->t->bytes, len);
-	}
-	dp->offset = offset+rv;
-
-	return rv;
-}
-
-void*
-floppygetfspart(int i, char *name, int chatty)
-{
-	static Fs fs;
-
-	if(strcmp(name, "dos") != 0){
-		if(chatty)
-			print("unknown partition fd%d!%s (use fd%d!dos)\n", i, name, i);
-		return nil;
-	}
-
-	fs.dev = i;
-	fs.diskread = floppyread;
-	fs.diskseek = floppyseek;
-
-	/* sometimes we get spurious errors and doing it again works */
-	if(dosinit(&fs) < 0 && dosinit(&fs) < 0){
-		if(chatty)
-			print("fd%d!%s does not contain a FAT file system\n", i, name);
-		return nil;
-	}
-	return &fs;
-}
-
-static int
-return0(void*)
-{
-	return 0;
-}
-
-static void
-timedsleep(int (*f)(void*), void* arg, int ms)
-{
-	int s;
-	ulong end;
-
-	end = m->ticks + 1 + MS2TK(ms);
-	while(m->ticks < end && !(*f)(arg)){
-		s = spllo();
-		delay(10);
-		splx(s);
-	}
-}
-
-/*
- *  start a floppy drive's motor.
- */
-static int
-floppyon(FDrive *dp)
-{
-	int alreadyon;
-	int tries;
-
-	if(fl.confused)
-		floppyrevive();
-
-	/* start motor and select drive */
-	dp->lasttouched = m->ticks;
-	alreadyon = fl.motor & MOTORBIT(dp->dev);
-	if(!alreadyon){
-		fl.motor |= MOTORBIT(dp->dev);
-		outb(Pdor, fl.motor | Fintena | Fena | dp->dev);
-		/* wait for drive to spin up */
-		timedsleep(return0, 0, 750);
-
-		/* clear any pending interrupts */
-		floppysense();
-	}
-
-	/* set transfer rate */
-	if(fl.rate != dp->t->rate){
-		fl.rate = dp->t->rate;
-		outb(Pdsr, fl.rate);
-	}
-
-	/* get drive to a known cylinder */
-	if(dp->confused)
-		for(tries = 0; tries < 4; tries++)
-			if(floppyrecal(dp) >= 0)
-				break;
-	dp->lasttouched = m->ticks;
-	fl.selected = dp;
-	if(dp->confused)
-		return -1;
-	return 0;
-}
-
-/*
- *  stop the floppy if it hasn't been used in 5 seconds
- */
-static void
-floppyoff(FDrive *dp)
-{
-	fl.motor &= ~MOTORBIT(dp->dev);
-	outb(Pdor, fl.motor | Fintena | Fena | dp->dev);
-}
-
-/*
- *  send a command to the floppy
- */
-static int
-floppycmd(void)
-{
-	int i;
-	int tries;
-
-	fl.nstat = 0;
-	for(i = 0; i < fl.ncmd; i++){
-		for(tries = 0; ; tries++){
-			if((inb(Pmsr)&(Ffrom|Fready)) == Fready)
-				break;
-			if(tries > 1000){
-				DPRINT("cmd %ux can't be sent (%d)\n", fl.cmd[0], i);
-				fldump();
-
-				/* empty fifo, might have been a bad command */
-				floppyresult();
-				return -1;
-			}
-			microdelay(1);
-		}
-		outb(Pfdata, fl.cmd[i]);
-	}
-	return 0;
-}
-
-/*
- *  get a command result from the floppy
- *
- *  when the controller goes ready waiting for a command
- *  (instead of sending results), we're done
- * 
- */
-static int
-floppyresult(void)
-{
-	int i, s;
-	int tries;
-
-	/* get the result of the operation */
-	for(i = 0; i < sizeof(fl.stat); i++){
-		/* wait for status byte */
-		for(tries = 0; ; tries++){
-			s = inb(Pmsr)&(Ffrom|Fready);
-			if(s == Fready){
-				fl.nstat = i;
-				return fl.nstat;
-			}
-			if(s == (Ffrom|Fready))
-				break;
-			if(tries > 1000){
-				DPRINT("floppyresult: %d stats\n", i);
-				fldump();
-				fl.confused = 1;
-				return -1;
-			}
-			microdelay(1);
-		}
-		fl.stat[i] = inb(Pfdata);
-	}
-	fl.nstat = sizeof(fl.stat);
-	return fl.nstat;
-}
-
-/*
- *  calculate physical address of a logical byte offset into the disk
- *
- *  truncate dp->length if it crosses a track boundary
- */
-static void
-floppypos(FDrive *dp, long off)
-{
-	int lsec;
-	int ltrack;
-	int end;
-
-	lsec = off/dp->t->bytes;
-	ltrack = lsec/dp->t->sectors;
-	dp->tcyl = ltrack/dp->t->heads;
-	dp->tsec = (lsec % dp->t->sectors) + 1;
-	dp->thead = (lsec/dp->t->sectors) % dp->t->heads;
-
-	/*
-	 *  can't read across track boundaries.
-	 *  if so, decrement the bytes to be read.
-	 */
-	end = (ltrack+1)*dp->t->sectors*dp->t->bytes;
-	if(off+dp->len > end)
-		dp->len = end - off;
-}
-
-/*
- *  get the interrupt cause from the floppy.
- */
-static int
-floppysense(void)
-{
-	fl.ncmd = 0;
-	fl.cmd[fl.ncmd++] = Fsense;
-	if(floppycmd() < 0)
-		return -1;
-	if(floppyresult() < 2){
-		DPRINT("can't read sense response\n");
-		fldump();
-		fl.confused = 1;
-		return -1;
-	}
-	return 0;
-}
-
-static int
-cmddone(void *a)
-{
-	USED(a);
-	return fl.ncmd == 0;
-}
-
-/*
- *  Wait for a floppy interrupt.  If none occurs in 5 seconds, we
- *  may have missed one.  This only happens on some portables which
- *  do power management behind our backs.  Call the interrupt
- *  routine to try to clear any conditions.
- */
-static void
-floppywait(int slow)
-{
-	timedsleep(cmddone, 0, slow ? 5000 : 1000);
-	if(!cmddone(0)){
-		floppyintr(0);
-		fl.confused = 1;
-	}
-}
-
-/*
- *  we've lost the floppy position, go to cylinder 0.
- */
-static int
-floppyrecal(FDrive *dp)
-{
-	dp->ccyl = -1;
-	dp->cyl = -1;
-
-	fl.ncmd = 0;
-	fl.cmd[fl.ncmd++] = Frecal;
-	fl.cmd[fl.ncmd++] = dp->dev;
-	if(floppycmd() < 0)
-		return -1;
-	floppywait(1);
-	if(fl.nstat < 2){
-		DPRINT("recalibrate: confused %ux\n", inb(Pmsr));
-		fl.confused = 1;
-		return -1;
-	}
-	if((fl.stat[0] & (Codemask|Seekend)) != Seekend){
-		DPRINT("recalibrate: failed\n");
-		dp->confused = 1;
-		return -1;
-	}
-	dp->cyl = fl.stat[1];
-	if(dp->cyl != 0){
-		DPRINT("recalibrate: wrong cylinder %d\n", dp->cyl);
-		dp->cyl = -1;
-		dp->confused = 1;
-		return -1;
-	}
-
-	dp->confused = 0;
-	return 0;
-}
-
-/*
- *  if the controller or a specific drive is in a confused state,
- *  reset it and get back to a kown state
- */
-static void
-floppyrevive(void)
-{
-	FDrive *dp;
-
-	/*
-	 *  reset the controller if it's confused
-	 */
-	if(fl.confused){
-		DPRINT("floppyrevive in\n");
-		fldump();
-
-		/* reset controller and turn all motors off */
-		splhi();
-		fl.ncmd = 1;
-		fl.cmd[0] = 0;
-		outb(Pdor, 0);
-		delay(10);
-		outb(Pdor, Fintena|Fena);
-		delay(10);
-		spllo();
-		fl.motor = 0;
-		fl.confused = 0;
-		floppywait(0);
-
-		/* mark all drives in an unknown state */
-		for(dp = fl.d; dp < &fl.d[fl.ndrive]; dp++)
-			dp->confused = 1;
-
-		/* set rate to a known value */
-		outb(Pdsr, 0);
-		fl.rate = 0;
-
-		DPRINT("floppyrevive out\n");
-		fldump();
-	}
-}
-
-/*
- *  seek to the target cylinder
- *
- *	interrupt, no results
- */
-static vlong
-pcfloppyseek(FDrive *dp, vlong off)
-{
-	floppypos(dp, off);
-	if(dp->cyl == dp->tcyl){
-		dp->offset = off;
-		return off;
-	}
-	dp->cyl = -1;
-
-	fl.ncmd = 0;
-	fl.cmd[fl.ncmd++] = Fseek;
-	fl.cmd[fl.ncmd++] = (dp->thead<<2) | dp->dev;
-	fl.cmd[fl.ncmd++] = dp->tcyl * dp->t->steps;
-	if(floppycmd() < 0)
-		return -1;
-	floppywait(1);
-	if(fl.nstat < 2){
-		DPRINT("seek: confused\n");
-		fl.confused = 1;
-		return -1;
-	}
-	if((fl.stat[0] & (Codemask|Seekend)) != Seekend){
-		DPRINT("seek: failed\n");
-		dp->confused = 1;
-		return -1;
-	}
-
-	dp->cyl = dp->tcyl;
-	dp->offset = off;
-	DPRINT("seek to %d succeeded\n", dp->offset);
-
-	return dp->offset;
-}
-
-/*
- *  read or write to floppy.  try up to three times.
- */
-static long
-floppyxfer(FDrive *dp, int cmd, void *a, long off, long n)
-{
-	long offset;
-	int tries;
-
-	if(off >= dp->t->cap)
-		return 0;
-	if(off + n > dp->t->cap)
-		n = dp->t->cap - off;
-
-	/* retry on error (until it gets ridiculous) */
-	for(tries = 0; tries < dp->maxtries; tries++){
-
-		dp->len = n;
-		if(pcfloppyseek(dp, off) < 0){
-			DPRINT("xfer: seek failed\n");
-			dp->confused = 1;
-			continue;
-		}
-
-		/*
-		 *  set up the dma (dp->len may be trimmed)
-		 */
-		dp->len = dmasetup(DMAchan, a, dp->len, cmd==Fread);
-		if(dp->len < 0){
-	buggery:
-			dmaend(DMAchan);
-			continue;
-		}
-	
-		/*
-		 *  start operation
-		 */
-		fl.ncmd = 0;
-		fl.cmd[fl.ncmd++] = cmd | (dp->t->heads > 1 ? Fmulti : 0);
-		fl.cmd[fl.ncmd++] = (dp->thead<<2) | dp->dev;
-		fl.cmd[fl.ncmd++] = dp->tcyl;
-		fl.cmd[fl.ncmd++] = dp->thead;
-		fl.cmd[fl.ncmd++] = dp->tsec;
-		fl.cmd[fl.ncmd++] = dp->t->bcode;
-		fl.cmd[fl.ncmd++] = dp->t->sectors;
-		fl.cmd[fl.ncmd++] = dp->t->gpl;
-		fl.cmd[fl.ncmd++] = 0xFF;
-		if(floppycmd() < 0)
-			goto buggery;
-
-		/*
-		 *  give bus to DMA, floppyintr() will read result
-		 */
-		floppywait(0);
-		dmaend(DMAchan);
-
-		/*
-		 *  check for errors
-		 */
-		if(fl.nstat < 7){
-			DPRINT("xfer: confused\n");
-			fl.confused = 1;
-			continue;
-		}
-		if((fl.stat[0] & Codemask)!=0 || fl.stat[1] || fl.stat[2]){
-			DPRINT("xfer: failed %ux %ux %ux\n", fl.stat[0],
-				fl.stat[1], fl.stat[2]);
-			DPRINT("offset %lud len %ld\n", off, dp->len);
-			if((fl.stat[0]&Codemask)==Cmdexec && fl.stat[1]==Overrun){
-				DPRINT("DMA overrun: retry\n");
-			} else
-				dp->confused = 1;
-			continue;
-		}
-
-		/*
-		 *  check for correct cylinder
-		 */
-		offset = fl.stat[3] * dp->t->heads + fl.stat[4];
-		offset = offset*dp->t->sectors + fl.stat[5] - 1;
-		offset = offset * c2b[fl.stat[6]];
-		if(offset != off+dp->len){
-			DPRINT("xfer: ends on wrong cyl\n");
-			dp->confused = 1;
-			continue;
-		}
-	
-		dp->lasttouched = m->ticks;
-		dp->maxtries = 20;
-		return dp->len;
-	}
-
-	return -1;
-}
-
-/*
-void
-floppymemwrite(void)
-{
-	int i;
-	int n;
-	uchar *a;
-	FDrive *dp;
-
-	dp = &fl.d[0];
-	a = (uchar*)0x80000000;
-	n = 0;
-	while(n < 1440*1024){
-		i = floppyxfer(dp, Fwrite, a+n, n, 1440*1024-n);
-		if(i <= 0)
-			break;
-		n += i;
-	}
-	print("floppymemwrite wrote %d bytes\n", n);
-splhi(); for(;;);
-}
-*/
-
-static void
-floppyintr(Ureg *ur)
-{
-	USED(ur);
-	switch(fl.cmd[0]&~Fmulti){
-	case Fread:
-	case Fwrite:
-	case Fformat:
-	case Fdumpreg: 
-		floppyresult();
-		break;
-	case Fseek:
-	case Frecal:
-	default:
-		floppysense();	/* to clear interrupt */
-		break;
-	}
-	fl.ncmd = 0;
-}
--- a/os/boot/pc/devfloppy.h
+++ /dev/null
@@ -1,196 +1,0 @@
-typedef	struct FController FController;
-typedef	struct FDrive FDrive;
-typedef struct FType FType;
-
-static void floppyintr(Ureg*);
-static int floppyon(FDrive*);
-static void floppyoff(FDrive*);
-static void floppysetdef(FDrive*);
-
-/*
- *  a floppy drive
- */
-struct FDrive
-{
-	FType	*t;		/* floppy type */
-	int	dt;		/* drive type */
-	int	dev;
-
-	ulong	lasttouched;	/* time last touched */
-	int	cyl;		/* current arm position */
-	int	confused;	/* needs to be recalibrated */
-	int	offset;		/* current offset */
-	int	vers;
-	int	maxtries;
-
-	int	tcyl;		/* target cylinder */
-	int	thead;		/* target head */
-	int	tsec;		/* target sector */
-	long	len;		/* size of xfer */
-
-	uchar	*cache;		/* track cache */
-	int	ccyl;
-	int	chead;
-
-//	Rendez	r;		/* waiting here for motor to spin up */
-	void	*aux;
-};
-
-/*
- *  controller for 4 floppys
- */
-struct FController
-{
-//	QLock;			/* exclusive access to the contoller */
-
-	int	ndrive;
-	FDrive	*d;		/* the floppy drives */
-	FDrive	*selected;
-	int	rate;		/* current rate selected */
-	uchar	cmd[14];	/* command */
-	int	ncmd;		/* # command bytes */
-	uchar	stat[14];	/* command status */
-	int	nstat;		/* # status bytes */
-	int	confused;	/* controler needs to be reset */
-//	Rendez	r;		/* wait here for command termination */
-	int	motor;		/* bit mask of spinning disks */
-//	Rendez	kr;		/* for motor watcher */
-};
-
-/*
- *  floppy types (all MFM encoding)
- */
-struct FType
-{
-	char	*name;
-	int	dt;		/* compatible drive type */
-	int	bytes;		/* bytes/sector */
-	int	sectors;	/* sectors/track */
-	int	heads;		/* number of heads */
-	int	steps;		/* steps per cylinder */
-	int	tracks;		/* tracks/disk */
-	int	gpl;		/* intersector gap length for read/write */	
-	int	fgpl;		/* intersector gap length for format */
-	int	rate;		/* rate code */
-
-	/*
-	 *  these depend on previous entries and are set filled in
-	 *  by floppyinit
-	 */
-	int	bcode;		/* coded version of bytes for the controller */
-	long	cap;		/* drive capacity in bytes */
-	long	tsize;		/* track size in bytes */
-};
-/* bits in the registers */
-enum
-{
-	/* status registers a & b */
-	Psra=		0x3f0,
-	Psrb=		0x3f1,
-
-	/* digital output register */
-	Pdor=		0x3f2,
-	Fintena=	0x8,	/* enable floppy interrupt */
-	Fena=		0x4,	/* 0 == reset controller */
-
-	/* main status register */
-	Pmsr=		0x3f4,
-	Fready=		0x80,	/* ready to be touched */
-	Ffrom=		0x40,	/* data from controller */
-	Ffloppybusy=	0x10,	/* operation not over */
-
-	/* data register */
-	Pfdata=		0x3f5,
-	Frecal=		0x07,	/* recalibrate cmd */
-	Fseek=		0x0f,	/* seek cmd */
-	Fsense=		0x08,	/* sense cmd */
-	Fread=		0x66,	/* read cmd */
-	Freadid=	0x4a,	/* read track id */
-	Fspec=		0x03,	/* set hold times */
-	Fwrite=		0x45,	/* write cmd */
-	Fformat=	0x4d,	/* format cmd */
-	Fmulti=		0x80,	/* or'd with Fread or Fwrite for multi-head */
-	Fdumpreg=	0x0e,	/* dump internal registers */
-
-	/* digital input register */
-	Pdir=		0x3F7,	/* disk changed port (read only) */
-	Pdsr=		0x3F7,	/* data rate select port (write only) */
-	Fchange=	0x80,	/* disk has changed */
-
-	/* status 0 byte */
-	Drivemask=	3<<0,
-	Seekend=	1<<5,
-	Codemask=	(3<<6)|(3<<3),
-	Cmdexec=	1<<6,
-
-	/* status 1 byte */
-	Overrun=	0x10,
-};
-
-/*
- *  types of drive (from PC equipment byte)
- */
-enum
-{
-	Tnone=		0,
-	T360kb=		1,
-	T1200kb=	2,
-	T720kb=		3,
-	T1440kb=	4,
-};
-
-static void
-pcfloppyintr(Ureg *ur, void *a)
-{
-	USED(a);
-
-	floppyintr(ur);
-}
-
-void
-floppysetup0(FController *fl)
-{
-	uchar equip;
-
-	/*
-	 * Read nvram for types of floppies 0 & 1.
-	 * Always try floppy 0.
-	 */
-	equip = nvramread(0x10);
-	fl->ndrive = 1;
-
-	if(equip & 0xf)
-		fl->ndrive++;
-
-	/*
-	 * Allocate the drive storage.
-	 * There's always one.
-	 */
-	fl->d = xalloc(fl->ndrive*sizeof(FDrive));
-	fl->d[0].dt = (equip >> 4) & 0xf;
-	if(fl->d[0].dt == Tnone)
-		fl->d[0].dt = T1440kb;
-
-	if(fl->ndrive == 2)
-		fl->d[1].dt = equip & 0xf;
-}
-
-void
-floppysetup1(FController*)
-{
-//	intrenable(VectorFLOPPY, pcfloppyintr, fl, BUSUNKNOWN);
-	setvec(VectorFLOPPY, pcfloppyintr, 0);
-}
-
-
-static vlong pcfloppyseek(FDrive*, vlong);
-FController	fl;
-
-vlong
-floppyseek(Fs *fs, vlong off)
-{
-	FDrive *dp;
-
-	dp = &fl.d[fs->dev];
-	return pcfloppyseek(dp, off);
-}
--- a/os/boot/pc/devi82365.c
+++ /dev/null
@@ -1,742 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "error.h"
-#include "io.h"
-
-/*
- *  Intel 82365SL PCIC controller and compatibles.
- */
-enum
-{
-	/*
-	 *  registers indices
-	 */
-	Rid=		0x0,		/* identification and revision */
-	Ris=		0x1,		/* interface status */
-	Rpc=	 	0x2,		/* power control */
-	 Foutena=	 (1<<7),	/*  output enable */
-	 Fautopower=	 (1<<5),	/*  automatic power switching */
-	 Fcardena=	 (1<<4),	/*  PC card enable */
-	Rigc= 		0x3,		/* interrupt and general control */
-	 Fiocard=	 (1<<5),	/*  I/O card (vs memory) */
-	 Fnotreset=	 (1<<6),	/*  reset if not set */	
-	 FSMIena=	 (1<<4),	/*  enable change interrupt on SMI */ 
-	Rcsc= 		0x4,		/* card status change */
-	Rcscic= 	0x5,		/* card status change interrupt config */
-	 Fchangeena=	 (1<<3),	/*  card changed */
-	 Fbwarnena=	 (1<<1),	/*  card battery warning */
-	 Fbdeadena=	 (1<<0),	/*  card battery dead */
-	Rwe= 		0x6,		/* address window enable */
-	 Fmem16=	 (1<<5),	/*  use A23-A12 to decode address */
-	Rio= 		0x7,		/* I/O control */
-	 Fwidth16=	 (1<<0),	/*  16 bit data width */
-	 Fiocs16=	 (1<<1),	/*  IOCS16 determines data width */
-	 Fzerows=	 (1<<2),	/*  zero wait state */
-	 Ftiming=	 (1<<3),	/*  timing register to use */
-	Riobtm0lo=	0x8,		/* I/O address 0 start low byte */
-	Riobtm0hi=	0x9,		/* I/O address 0 start high byte */
-	Riotop0lo=	0xa,		/* I/O address 0 stop low byte */
-	Riotop0hi=	0xb,		/* I/O address 0 stop high byte */
-	Riobtm1lo=	0xc,		/* I/O address 1 start low byte */
-	Riobtm1hi=	0xd,		/* I/O address 1 start high byte */
-	Riotop1lo=	0xe,		/* I/O address 1 stop low byte */
-	Riotop1hi=	0xf,		/* I/O address 1 stop high byte */
-	Rmap=		0x10,		/* map 0 */
-
-	/*
-	 *  CL-PD67xx extension registers
-	 */
-	Rmisc1=		0x16,		/* misc control 1 */
-	 F5Vdetect=	 (1<<0),
-	 Fvcc3V=	 (1<<1),
-	 Fpmint=	 (1<<2),
-	 Fpsirq=	 (1<<3),
-	 Fspeaker=	 (1<<4),
-	 Finpack=	 (1<<7),
-	Rfifo=		0x17,		/* fifo control */
-	 Fflush=	 (1<<7),	/*  flush fifo */
-	Rmisc2=		0x1E,		/* misc control 2 */
-	 Flowpow=	 (1<<1),	/*  low power mode */
-	Rchipinfo=	0x1F,		/* chip information */
-	Ratactl=	0x26,		/* ATA control */
-
-	/*
-	 *  offsets into the system memory address maps
-	 */
-	Mbtmlo=		0x0,		/* System mem addr mapping start low byte */
-	Mbtmhi=		0x1,		/* System mem addr mapping start high byte */
-	 F16bit=	 (1<<7),	/*  16-bit wide data path */
-	Mtoplo=		0x2,		/* System mem addr mapping stop low byte */
-	Mtophi=		0x3,		/* System mem addr mapping stop high byte */
-	 Ftimer1=	 (1<<6),	/*  timer set 1 */
-	Mofflo=		0x4,		/* Card memory offset address low byte */
-	Moffhi=		0x5,		/* Card memory offset address high byte */
-	 Fregactive=	 (1<<6),	/*  attribute memory */
-
-	/*
-	 *  configuration registers - they start at an offset in attribute
-	 *  memory found in the CIS.
-	 */
-	Rconfig=	0,
-	 Creset=	 (1<<7),	/*  reset device */
-	 Clevel=	 (1<<6),	/*  level sensitive interrupt line */
-	 Cirq=		 (1<<2),	/*  IRQ enable */
-	 Cdecode=	 (1<<1),	/*  address decode */
-	 Cfunc=		 (1<<0),	/*  function enable */
-	Riobase0=	5,
-	Riobase1=	6,
-	Riosize=	9,
-};
-
-static int pcmcia_pcmspecial(char *, ISAConf *);
-static void pcmcia_pcmspecialclose(int);
-
-#define MAP(x,o)	(Rmap + (x)*0x8 + o)
-
-typedef struct I82365	I82365;
-
-/* a controller */
-enum
-{
-	Ti82365,
-	Tpd6710,
-	Tpd6720,
-	Tvg46x,
-};
-struct I82365
-{
-	int	type;
-	int	dev;
-	int	nslot;
-	int	xreg;		/* index register address */
-	int	dreg;		/* data register address */
-	int	irq;
-};
-static I82365 *controller[4];
-static int ncontroller;
-static PCMslot	*slot;
-static PCMslot	*lastslot;
-static nslot;
-
-static void	i82365intr(Ureg*, void*);
-static void	i82365reset(void);
-static int	pcmio(int, ISAConf*);
-
-static void i82365dump(PCMslot*);
-
-void
-devi82365link(void)
-{
-	static int already;
-	char *p;
-
-	if(already)
-		return;
-	already = 1;
-
-	if((p=getconf("pcmcia0")) && strncmp(p, "disabled", 8)==0)
-		return;
-
-	if (_pcmspecial)
-		return;
-	
-	_pcmspecial = pcmcia_pcmspecial;
-	_pcmspecialclose = pcmcia_pcmspecialclose;
-}
-
-/*
- *  reading and writing card registers
- */
-static uchar
-rdreg(PCMslot *pp, int index)
-{
-	outb(((I82365*)pp->cp)->xreg, pp->base + index);
-	return inb(((I82365*)pp->cp)->dreg);
-}
-static void
-wrreg(PCMslot *pp, int index, uchar val)
-{
-	outb(((I82365*)pp->cp)->xreg, pp->base + index);
-	outb(((I82365*)pp->cp)->dreg, val);
-}
-
-/*
- *  get info about card
- */
-static void
-slotinfo(PCMslot *pp)
-{
-	uchar isr;
-
-	isr = rdreg(pp, Ris);
-	pp->occupied = (isr & (3<<2)) == (3<<2);
-	pp->powered = isr & (1<<6);
-	pp->battery = (isr & 3) == 3;
-	pp->wrprot = isr & (1<<4);
-	pp->busy = isr & (1<<5);
-	//pp->msec = TK2MS(MACHP(0)->ticks);
-}
-
-static int
-vcode(int volt)
-{
-	switch(volt){
-	case 5:
-		return 1;
-	case 12:
-		return 2;
-	default:
-		return 0;
-	}
-}
-
-/*
- *  enable the slot card
- */
-static void
-slotena(PCMslot *pp)
-{
-	if(pp->enabled)
-		return;
-
-	/* power up and unreset, wait's are empirical (???) */
-	wrreg(pp, Rpc, Fautopower|Foutena|Fcardena);
-	delay(300);
-	wrreg(pp, Rigc, 0);
-	delay(100);
-	wrreg(pp, Rigc, Fnotreset);
-	delay(500);
-
-	/* get configuration */
-	slotinfo(pp);
-	if(pp->occupied){
-		pcmcisread(pp);
-		pp->enabled = 1;
-	} else
-		wrreg(pp, Rpc, Fautopower);
-}
-
-/*
- *  disable the slot card
- */
-static void
-slotdis(PCMslot *pp)
-{
-	wrreg(pp, Rpc, 0);	/* turn off card power */
-	wrreg(pp, Rwe, 0);	/* no windows */
-	pp->enabled = 0;
-}
-
-/*
- *  status change interrupt
- */
-static void
-i82365intr(Ureg *, void *)
-{
-	uchar csc, was;
-	PCMslot *pp;
-
-	if(slot == 0)
-		return;
-
-	for(pp = slot; pp < lastslot; pp++){
-		csc = rdreg(pp, Rcsc);
-		was = pp->occupied;
-		slotinfo(pp);
-		if(csc & (1<<3) && was != pp->occupied){
-			if(!pp->occupied)
-				slotdis(pp);
-		}
-	}
-}
-
-enum
-{
-	Mshift=	12,
-	Mgran=	(1<<Mshift),	/* granularity of maps */
-	Mmask=	~(Mgran-1),	/* mask for address bits important to the chip */
-};
-
-/*
- *  get a map for pc card region, return corrected len
- */
-PCMmap*
-pcmmap(int slotno, ulong offset, int len, int attr)
-{
-	PCMslot *pp;
-	uchar we, bit;
-	PCMmap *m, *nm;
-	int i;
-	ulong e;
-
-	pp = slot + slotno;
-	lock(&pp->mlock);
-
-	/* convert offset to granularity */
-	if(len <= 0)
-		len = 1;
-	e = ROUND(offset+len, Mgran);
-	offset &= Mmask;
-	len = e - offset;
-
-	/* look for a map that covers the right area */
-	we = rdreg(pp, Rwe);
-	bit = 1;
-	nm = 0;
-	for(m = pp->mmap; m < &pp->mmap[nelem(pp->mmap)]; m++){
-		if((we & bit))
-		if(m->attr == attr)
-		if(offset >= m->ca && e <= m->cea){
-
-			m->ref++;
-			unlock(&pp->mlock);
-			return m;
-		}
-		bit <<= 1;
-		if(nm == 0 && m->ref == 0)
-			nm = m;
-	}
-	m = nm;
-	if(m == 0){
-		unlock(&pp->mlock);
-		return 0;
-	}
-
-	/* if isa space isn't big enough, free it and get more */
-	if(m->len < len){
-		if(m->isa){
-			umbfree(m->isa, m->len);
-			m->len = 0;
-		}
-		m->isa = PADDR(umbmalloc(0, len, Mgran));
-		if(m->isa == 0){
-			print("pcmmap %d: out of isa space\n", len);
-			unlock(&pp->mlock);
-			return 0;
-		}
-		m->len = len;
-	}
-
-	/* set up new map */
-	m->ca = offset;
-	m->cea = m->ca + m->len;
-	m->attr = attr;
-	i = m-pp->mmap;
-	bit = 1<<i;
-	wrreg(pp, Rwe, we & ~bit);		/* disable map before changing it */
-	wrreg(pp, MAP(i, Mbtmlo), m->isa>>Mshift);
-	wrreg(pp, MAP(i, Mbtmhi), (m->isa>>(Mshift+8)) | F16bit);
-	wrreg(pp, MAP(i, Mtoplo), (m->isa+m->len-1)>>Mshift);
-	wrreg(pp, MAP(i, Mtophi), ((m->isa+m->len-1)>>(Mshift+8)));
-	offset -= m->isa;
-	offset &= (1<<25)-1;
-	offset >>= Mshift;
-	wrreg(pp, MAP(i, Mofflo), offset);
-	wrreg(pp, MAP(i, Moffhi), (offset>>8) | (attr ? Fregactive : 0));
-	wrreg(pp, Rwe, we | bit);		/* enable map */
-	m->ref = 1;
-
-	unlock(&pp->mlock);
-	return m;
-}
-
-void
-pcmunmap(int slotno, PCMmap* m)
-{
-	PCMslot *pp;
-
-	pp = slot + slotno;
-	lock(&pp->mlock);
-	m->ref--;
-	unlock(&pp->mlock);
-}
-
-static void
-increfp(PCMslot *pp)
-{
-	lock(pp);
-	if(pp->ref++ == 0)
-		slotena(pp);
-	unlock(pp);
-}
-
-static void
-decrefp(PCMslot *pp)
-{
-	lock(pp);
-	if(pp->ref-- == 1)
-		slotdis(pp);
-	unlock(pp);
-}
-
-/*
- *  look for a card whose version contains 'idstr'
- */
-static int
-pcmcia_pcmspecial(char *idstr, ISAConf *isa)
-{
-	PCMslot *pp;
-	extern char *strstr(char*, char*);
-	int enabled;
-
-	i82365reset();
-	for(pp = slot; pp < lastslot; pp++){
-		if(pp->special)
-			continue;	/* already taken */
-		enabled = 0;
-		/* make sure we don't power on cards when we already know what's
-		 * in them.  We'll reread every two minutes if necessary
-		 */
-		if (pp->verstr[0] == '\0') {
-			increfp(pp);
-			enabled++;
-		}
-
-		if(pp->occupied) {
-			if(strstr(pp->verstr, idstr)){
-				if (!enabled){
-					enabled = 1;
-					increfp(pp);
-				}
-				if(isa == 0 || pcmio(pp->slotno, isa) == 0){
-					pp->special = 1;
-					return pp->slotno;
-				}
-			}
-		} else
-			pp->special = 1;
-		if (enabled)
-			decrefp(pp);
-	}
-	return -1;
-}
-
-static void
-pcmcia_pcmspecialclose(int slotno)
-{
-	PCMslot *pp;
-
-	print("pcmspecialclose called\n");
-	if(slotno >= nslot)
-		panic("pcmspecialclose");
-	pp = slot + slotno;
-	pp->special = 0;
-	decrefp(pp);
-}
-
-static char *chipname[] =
-{
-[Ti82365]	"Intel 82365SL",
-[Tpd6710]	"Cirrus Logic PD6710",
-[Tpd6720]	"Cirrus Logic PD6720",
-[Tvg46x]	"Vadem VG-46x",
-};
-
-static I82365*
-i82365probe(int x, int d, int dev)
-{
-	uchar c, id;
-	I82365 *cp;
-	ISAConf isa;
-	int i, nslot;
-
-	outb(x, Rid + (dev<<7));
-	id = inb(d);
-	if((id & 0xf0) != 0x80)
-		return 0;		/* not a memory & I/O card */
-	if((id & 0x0f) == 0x00)
-		return 0;		/* no revision number, not possible */
-
-	cp = xalloc(sizeof(I82365));
-	cp->xreg = x;
-	cp->dreg = d;
-	cp->dev = dev;
-	cp->type = Ti82365;
-	cp->nslot = 2;
-
-	switch(id){
-	case 0x82:
-	case 0x83:
-	case 0x84:
-		/* could be a cirrus */
-		outb(x, Rchipinfo + (dev<<7));
-		outb(d, 0);
-		c = inb(d);
-		if((c & 0xc0) != 0xc0)
-			break;
-		c = inb(d);
-		if((c & 0xc0) != 0x00)
-			break;
-		if(c & 0x20){
-			cp->type = Tpd6720;
-		} else {
-			cp->type = Tpd6710;
-			cp->nslot = 1;
-		}
-
-		/* low power mode */
-		outb(x, Rmisc2 + (dev<<7));
-		c = inb(d);
-		outb(d, c & ~Flowpow);
-		break;
-	}
-
-	/* if it's not a Cirrus, it could be a Vadem... */
-	if(cp->type == Ti82365){
-		/* unlock the Vadem extended regs */
-		outb(x, 0x0E + (dev<<7));
-		outb(x, 0x37 + (dev<<7));
-
-		/* make the id register show the Vadem id */
-		outb(x, 0x3A + (dev<<7));
-		c = inb(d);
-		outb(d, c|0xC0);
-		outb(x, Rid + (dev<<7));
-		c = inb(d);
-		if(c & 0x08)
-			cp->type = Tvg46x;
-
-		/* go back to Intel compatible id */
-		outb(x, 0x3A + (dev<<7));
-		c = inb(d);
-		outb(d, c & ~0xC0);
-	}
-
-	memset(&isa, 0, sizeof(ISAConf));
-	if(isaconfig("pcmcia", ncontroller, &isa) && isa.irq)
-		cp->irq = isa.irq;
-	else
-		cp->irq = VectorPCMCIA - VectorPIC;
-
-	for(i = 0; i < isa.nopt; i++){
-		if(cistrncmp(isa.opt[i], "nslot=", 6))
-			continue;
-		nslot = strtol(&isa.opt[i][6], nil, 0);
-		if(nslot > 0 && nslot <= 2)
-			cp->nslot = nslot;
-	}
-
-	controller[ncontroller++] = cp;
-	return cp;
-}
-
-static void
-i82365dump(PCMslot *pp)
-{
-	int i;
-
-	for(i = 0; i < 0x40; i++){
-		if((i&0x0F) == 0)
-			print("\n%2.2uX:	", i);
-		if(((i+1) & 0x0F) == 0x08)
-			print(" - ");
-		print("%2.2uX ", rdreg(pp, i));
-	}
-	print("\n");
-}
-
-/*
- *  set up for slot cards
- */
-static void
-i82365reset(void)
-{
-	static int already;
-	int i, j;
-	I82365 *cp;
-	PCMslot *pp;
-
-	if(already)
-		return;
-	already = 1;
-
-
-	/* look for controllers */
-	i82365probe(0x3E0, 0x3E1, 0);
-	i82365probe(0x3E0, 0x3E1, 1);
-	i82365probe(0x3E2, 0x3E3, 0);
-	i82365probe(0x3E2, 0x3E3, 1);
-
-	for(i = 0; i < ncontroller; i++)
-		nslot += controller[i]->nslot;
-	slot = xalloc(nslot * sizeof(PCMslot));
-
-	lastslot = slot;
-	for(i = 0; i < ncontroller; i++){
-		cp = controller[i];
-		print("#y%d: %d slot %s: port 0x%uX irq %d\n",
-			i, cp->nslot, chipname[cp->type], cp->xreg, cp->irq);
-		for(j = 0; j < cp->nslot; j++){
-			pp = lastslot++;
-			pp->slotno = pp - slot;
-			pp->memlen = 64*MB;
-			pp->base = (cp->dev<<7) | (j<<6);
-			pp->cp = cp;
-			pp->msec = ~0;
-			pp->verstr[0] = 0;
-			slotdis(pp);
-
-			/* interrupt on status change */
-			wrreg(pp, Rcscic, (cp->irq<<4) | Fchangeena);
-			rdreg(pp, Rcsc);
-		}
-
-		/* for card management interrupts */
-		setvec(cp->irq+VectorPIC, i82365intr, 0);
-	}
-}
-
-/*
- *  configure the PCMslot for IO.  We assume very heavily that we can read
- *  configuration info from the CIS.  If not, we won't set up correctly.
- */
-static int
-pcmio(int slotno, ISAConf *isa)
-{
-	uchar we, x, *p;
-	PCMslot *pp;
-	PCMconftab *ct, *et, *t;
-	PCMmap *m;
-	int i, index, irq;
-	char *cp;
-
-	irq = isa->irq;
-	if(irq == 2)
-		irq = 9;
-
-	if(slotno > nslot)
-		return -1;
-	pp = slot + slotno;
-
-	if(!pp->occupied)
-		return -1;
-
-	et = &pp->ctab[pp->nctab];
-
-	ct = 0;
-	for(i = 0; i < isa->nopt; i++){
-		if(strncmp(isa->opt[i], "index=", 6))
-			continue;
-		index = strtol(&isa->opt[i][6], &cp, 0);
-		if(cp == &isa->opt[i][6] || index >= pp->nctab)
-			return -1;
-		ct = &pp->ctab[index];
-	}
-
-	if(ct == 0){
-	
-		/* assume default is right */
-		if(pp->def)
-			ct = pp->def;
-		else
-			ct = pp->ctab;
-	
-		/* try for best match */
-		if(ct->nio == 0
-		|| ct->io[0].start != isa->port || ((1<<irq) & ct->irqs) == 0){
-			for(t = pp->ctab; t < et; t++)
-				if(t->nio
-				&& t->io[0].start == isa->port
-				&& ((1<<irq) & t->irqs)){
-					ct = t;
-					break;
-				}
-		}
-		if(ct->nio == 0 || ((1<<irq) & ct->irqs) == 0){
-			for(t = pp->ctab; t < et; t++)
-				if(t->nio && ((1<<irq) & t->irqs)){
-					ct = t;
-					break;
-				}
-		}
-		if(ct->nio == 0){
-			for(t = pp->ctab; t < et; t++)
-				if(t->nio){
-					ct = t;
-					break;
-				}
-		}
-	}
-
-	if(ct == et || ct->nio == 0)
-		return -1;
-	if(isa->port == 0 && ct->io[0].start == 0)
-		return -1;
-
-	/* route interrupts */
-	isa->irq = irq;
-	wrreg(pp, Rigc, irq | Fnotreset | Fiocard);
-	
-	/* set power and enable device */
-	x = vcode(ct->vpp1);
-	wrreg(pp, Rpc, x|Fautopower|Foutena|Fcardena);
-
-	/* 16-bit data path */
-	if(ct->bit16)
-		x = Ftiming|Fiocs16|Fwidth16;
-	else
-		x = Ftiming;
-	if(ct->nio == 2 && ct->io[1].start)
-		x |= x<<4;
-	wrreg(pp, Rio, x);
-
-	/*
-	 * enable io port map 0
-	 * the 'top' register value includes the last valid address
-	 */
-	if(isa->port == 0)
-		isa->port = ct->io[0].start;
-	we = rdreg(pp, Rwe);
-	wrreg(pp, Riobtm0lo, isa->port);
-	wrreg(pp, Riobtm0hi, isa->port>>8);
-	i = isa->port+ct->io[0].len-1;
-	wrreg(pp, Riotop0lo, i);
-	wrreg(pp, Riotop0hi, i>>8);
-	we |= 1<<6;
-	if(ct->nio >= 2 && ct->io[1].start){
-		wrreg(pp, Riobtm1lo, ct->io[1].start);
-		wrreg(pp, Riobtm1hi, ct->io[1].start>>8);
-		i = ct->io[1].start+ct->io[1].len-1;
-		wrreg(pp, Riotop1lo, i);
-		wrreg(pp, Riotop1hi, i>>8);
-		we |= 1<<7;
-	}
-	wrreg(pp, Rwe, we);
-
-	/* only touch Rconfig if it is present */
-	m = pcmmap(slotno, pp->cfg[0].caddr + Rconfig, 0x20, 1);
-	p = KADDR(m->isa + pp->cfg[0].caddr - m->ca);
-	if(pp->cfg[0].cpresent & (1<<Rconfig)){
-		/*  Reset adapter */
-
-		/*  set configuration and interrupt type.
-		 *  if level is possible on the card, use it.
-		 */
-		x = ct->index;
-		if(ct->irqtype & 0x20)
-			x |= Clevel;
-
-		/*  enable the device, enable address decode and
-		 *  irq enable.
-		 */
-		x |= Cfunc|Cdecode|Cirq;
-
-		p[0] = x;
-		//delay(5);
-		microdelay(40);
-	}
-
-	if(pp->cfg[0].cpresent & (1<<Riobase0)){
-		/* set up the iobase 0 */
-		p[Riobase0 << 1] = isa->port;
-		p[Riobase1 << 1] = isa->port >> 8;
-	}
-
-	if(pp->cfg[0].cpresent & (1<<Riosize))
-		p[Riosize << 1] = ct->io[0].len;
-	pcmunmap(slotno, m);
-	return 0;
-}
--- a/os/boot/pc/devpccard.c
+++ /dev/null
@@ -1,1606 +1,0 @@
-/*
-     cardbus and pcmcia (grmph) support.
-*/
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "error.h"
-#include "io.h"
-
-extern int pciscan(int, Pcidev **);
-
-int (*_pcmspecial)(char *, ISAConf *);
-void (*_pcmspecialclose)(int);
-
-int
-pcmspecial(char *idstr, ISAConf *isa)
-{
-	return (_pcmspecial  != nil)? _pcmspecial(idstr, isa): -1;
-}
-
-void
-pcmspecialclose(int a)
-{
-	if (_pcmspecialclose != nil)
-		_pcmspecialclose(a);
-}
-
-static ulong
-ioreserve(ulong, int size, int align, char *)
-{
-	static ulong isaend = 0x400; /*0xfd00*/
-	ulong ioaddr;
-
-	if (align)
-		isaend = ((isaend + align - 1) / align) * align;
-	ioaddr = isaend;
-	isaend += size;
-	return ioaddr;
-}
-
-#define MAP(x,o)	(Rmap + (x)*0x8 + o)
-
-enum {
-	TI_vid = 0x104c,
-	TI_1131_did = 0xAC15,
-	TI_1250_did = 0xAC16,
-	TI_1450_did = 0xAC1B,
-	TI_1251A_did = 0xAC1D,
-	TI_1420_did = 0xAC51,
-
-	Ricoh_vid = 0x1180,
-	Ricoh_475_did = 0x0475,
-	Ricoh_476_did = 0x0476,
-	Ricoh_478_did = 0x0478,
-
-	O2_vid = 0x1217,
-	O2_OZ711M3_did = 0x7134,
-
-	Nslots = 4,		/* Maximum number of CardBus slots to use */
-
-	K = 1024,
-	M = K * K,
-
-	LegacyAddr = 0x3e0,
-	NUMEVENTS = 10,
-
-	TI1131xSC = 0x80,		// system control
-		TI122X_SC_INTRTIE	= 1 << 29,
-	TI12xxIM = 0x8c,		// 
-	TI1131xCC = 0x91,		// card control
-		TI113X_CC_RIENB = 1 << 7,
-		TI113X_CC_ZVENABLE = 1 << 6,
-		TI113X_CC_PCI_IRQ_ENA = 1 << 5,
-		TI113X_CC_PCI_IREQ = 1 << 4,
-		TI113X_CC_PCI_CSC = 1 << 3,
-		TI113X_CC_SPKROUTEN = 1 << 1,
-		TI113X_CC_IFG = 1 << 0,
-	TI1131xDC = 0x92,		// device control
-};
-
-typedef struct Variant Variant;
-struct Variant {
-	ushort	vid;
-	ushort	did;
-	char	*name;
-};
-
-static Variant variant[] = {
-{	Ricoh_vid,	Ricoh_475_did,	"Ricoh 475 PCI/Cardbus bridge",	},
-{	Ricoh_vid,	Ricoh_476_did,	"Ricoh 476 PCI/Cardbus bridge",	},
-{	Ricoh_vid,	Ricoh_478_did,	"Ricoh 478 PCI/Cardbus bridge",	},
-{	TI_vid,		TI_1131_did,	"TI PCI-1131 Cardbus Controller", },
-{	TI_vid,		TI_1250_did,	"TI PCI-1250 Cardbus Controller", },
-{	TI_vid,		TI_1450_did,	"TI PCI-1450 Cardbus Controller", },
-{	TI_vid,		TI_1251A_did,	"TI PCI-1251A Cardbus Controller", },
-{	TI_vid,		TI_1420_did,	"TI PCI-1420 Cardbus Controller", },
-{	O2_vid,		O2_OZ711M3_did,	"O2Micro OZ711M3 MemoryCardBus", },
-};
-
-/* Cardbus registers */
-enum {
-	SocketEvent = 0,
-		SE_CCD = 3 << 1,
-		SE_POWER = 1 << 3,
-	SocketMask = 1,
-	SocketState = 2,
-		SS_CCD = 3 << 1,
-		SS_POWER = 1 << 3,
-		SS_PC16 = 1 << 4,
-		SS_CBC = 1 << 5,
-		SS_NOTCARD = 1 << 7,
-		SS_BADVCC = 1 << 9,
-		SS_5V = 1 << 10,
-		SS_3V = 1 << 11,
-	SocketForce = 3,
-	SocketControl = 4,
-		SC_5V = 0x22,
-		SC_3V = 0x33,
-};
-
-enum {
-	PciPCR_IO = 1 << 0,
-	PciPCR_MEM = 1 << 1,
-	PciPCR_Master = 1 << 2,
-
-	PciPMC = 0xa4,
-
-	Nbars = 6,
-	Ncmd = 10,
-	CBIRQ = 9,
-
-	PC16,
-	PC32,
-};
-
-enum {
-	Ti82365,
-	Tpd6710,
-	Tpd6720,
-	Tvg46x,
-};
-
-/*
- *  Intel 82365SL PCIC controller for the PCMCIA or
- *  Cirrus Logic PD6710/PD6720 which is mostly register compatible
- */
-enum
-{
-	/*
-	 *  registers indices
-	 */
-	Rid=		0x0,		/* identification and revision */
-	Ris=		0x1,		/* interface status */
-	Rpc=	 	0x2,		/* power control */
-	 Foutena=	 (1<<7),	/*  output enable */
-	 Fautopower=	 (1<<5),	/*  automatic power switching */
-	 Fcardena=	 (1<<4),	/*  PC card enable */
-	Rigc= 		0x3,		/* interrupt and general control */
-	 Fiocard=	 (1<<5),	/*  I/O card (vs memory) */
-	 Fnotreset=	 (1<<6),	/*  reset if not set */	
-	 FSMIena=	 (1<<4),	/*  enable change interrupt on SMI */ 
-	Rcsc= 		0x4,		/* card status change */
-	Rcscic= 	0x5,		/* card status change interrupt config */
-	 Fchangeena=	 (1<<3),	/*  card changed */
-	 Fbwarnena=	 (1<<1),	/*  card battery warning */
-	 Fbdeadena=	 (1<<0),	/*  card battery dead */
-	Rwe= 		0x6,		/* address window enable */
-	 Fmem16=	 (1<<5),	/*  use A23-A12 to decode address */
-	Rio= 		0x7,		/* I/O control */
-	 Fwidth16=	 (1<<0),	/*  16 bit data width */
-	 Fiocs16=	 (1<<1),	/*  IOCS16 determines data width */
-	 Fzerows=	 (1<<2),	/*  zero wait state */
-	 Ftiming=	 (1<<3),	/*  timing register to use */
-	Riobtm0lo=	0x8,		/* I/O address 0 start low byte */
-	Riobtm0hi=	0x9,		/* I/O address 0 start high byte */
-	Riotop0lo=	0xa,		/* I/O address 0 stop low byte */
-	Riotop0hi=	0xb,		/* I/O address 0 stop high byte */
-	Riobtm1lo=	0xc,		/* I/O address 1 start low byte */
-	Riobtm1hi=	0xd,		/* I/O address 1 start high byte */
-	Riotop1lo=	0xe,		/* I/O address 1 stop low byte */
-	Riotop1hi=	0xf,		/* I/O address 1 stop high byte */
-	Rmap=		0x10,		/* map 0 */
-
-	/*
-	 *  CL-PD67xx extension registers
-	 */
-	Rmisc1=		0x16,		/* misc control 1 */
-	 F5Vdetect=	 (1<<0),
-	 Fvcc3V=	 (1<<1),
-	 Fpmint=	 (1<<2),
-	 Fpsirq=	 (1<<3),
-	 Fspeaker=	 (1<<4),
-	 Finpack=	 (1<<7),
-	Rfifo=		0x17,		/* fifo control */
-	 Fflush=	 (1<<7),	/*  flush fifo */
-	Rmisc2=		0x1E,		/* misc control 2 */
-	 Flowpow=	 (1<<1),	/*  low power mode */
-	Rchipinfo=	0x1F,		/* chip information */
-	Ratactl=	0x26,		/* ATA control */
-
-	/*
-	 *  offsets into the system memory address maps
-	 */
-	Mbtmlo=		0x0,		/* System mem addr mapping start low byte */
-	Mbtmhi=		0x1,		/* System mem addr mapping start high byte */
-	 F16bit=	 (1<<7),	/*  16-bit wide data path */
-	Mtoplo=		0x2,		/* System mem addr mapping stop low byte */
-	Mtophi=		0x3,		/* System mem addr mapping stop high byte */
-	 Ftimer1=	 (1<<6),	/*  timer set 1 */
-	Mofflo=		0x4,		/* Card memory offset address low byte */
-	Moffhi=		0x5,		/* Card memory offset address high byte */
-	 Fregactive=	 (1<<6),	/*  attribute memory */
-
-	/*
-	 *  configuration registers - they start at an offset in attribute
-	 *  memory found in the CIS.
-	 */
-	Rconfig=	0,
-	 Creset=	 (1<<7),	/*  reset device */
-	 Clevel=	 (1<<6),	/*  level sensitive interrupt line */
-};
-
-/*
- *  read and crack the card information structure enough to set
- *  important parameters like power
- */
-/* cis memory walking */
-typedef struct Cisdat Cisdat;
-struct Cisdat {
-	uchar		*cisbase;
-	int		cispos;
-	int		cisskip;
-	int		cislen;
-};
-
-typedef struct Pcminfo Pcminfo;
-struct Pcminfo {
-	char		verstr[512];		/* Version string */
-	PCMmap		mmap[4];		/* maps, last is always for the kernel */
-	ulong		conf_addr;		/* Config address */
-	uchar		conf_present;		/* Config register present */
-	int		nctab;			/* In use configuration tables */
-	PCMconftab	ctab[8];		/* Configuration tables */
-	PCMconftab	*defctab;		/* Default conftab */
-
-	int		port;			/* Actual port usage */
-	int		irq;			/* Actual IRQ usage */
-};
-
-typedef struct Cardbus Cardbus;
-struct Cardbus {
-	Lock;
-	Variant		*variant;		/* Which CardBus chipset */
-	Pcidev		*pci;			/* The bridge itself */
-	ulong		*regs;			/* Cardbus registers */
-	int		ltype;			/* Legacy type */
-	int		lindex;			/* Legacy port index address */
-	int		ldata;			/* Legacy port data address */
-	int		lbase;			/* Base register for this socket */
-
-	int		state;			/* Current state of card */
-	int		type;			/* Type of card */
-	Pcminfo		linfo;			/* PCMCIA slot info */
-
-	int		special;		/* card is allocated to a driver */
-
-	int		refs;			/* Number of refs to slot */
-	Lock		refslock;		/* inc/dev ref lock */
-};
-
-enum {
-	Mshift=	12,
-	Mgran=	(1<<Mshift),	/* granularity of maps */
-	Mmask=	~(Mgran-1),	/* mask for address bits important to the chip */
-};
-
-static Cardbus cbslots[Nslots];
-static int nslots;
-
-static ulong exponent[8] = { 
-	1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 
-};
-
-static ulong vmant[16] = {
-	10, 12, 13, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 70, 80, 90,
-};
-
-static ulong mantissa[16] = { 
-	0, 10, 12, 13, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 70, 80, 
-};
-
-static void cbint(Ureg *, void *);
-static int powerup(Cardbus *);
-static void configure(Cardbus *);
-static void managecard(Cardbus *);
-static void cardmanager(void *);
-static void eject(Cardbus *);
-static void interrupt(Ureg *, void *);
-static void powerdown(Cardbus *cb);
-static void unconfigure(Cardbus *cb);
-
-static void i82365probe(Cardbus *cb, int lindex, int ldata);
-static void i82365configure(Cardbus *cb);
-static PCMmap *isamap(Cardbus *cb, ulong offset, int len, int attr);
-static void isaunmap(PCMmap* m);
-static uchar rdreg(Cardbus *cb, int index);
-static void wrreg(Cardbus *cb, int index, uchar val);
-static int readc(Cisdat *cis, uchar *x);
-static void tvers1(Cardbus *cb, Cisdat *cis, int );
-static void tcfig(Cardbus *cb, Cisdat *cis, int );
-static void tentry(Cardbus *cb, Cisdat *cis, int );
-static int vcode(int volt);
-static int pccard_pcmspecial(char *idstr, ISAConf *isa);
-static void pccard_pcmspecialclose(int slotno);
-
-enum {
-	CardDetected,
-	CardPowered,
-	CardEjected,
-	CardConfigured,
-};
-
-static char *messages[] = {
-[CardDetected]		"CardDetected",
-[CardPowered]		"CardPowered",
-[CardEjected]		"CardEjected",
-[CardConfigured]	"CardConfigured",
-};
-
-enum {
-	SlotEmpty,
-	SlotFull,
-	SlotPowered,
-	SlotConfigured,
-};
-
-static char *states[] = {
-[SlotEmpty]		"SlotEmpty",
-[SlotFull]		"SlotFull",
-[SlotPowered]		"SlotPowered",
-[SlotConfigured]	"SlotConfigured",
-};
-
-static void
-engine(Cardbus *cb, int message)
-{
-	// print("engine(%d): %s(%s)\n", 
-	//	 (int)(cb - cbslots), states[cb->state], messages[message]);
-	switch (cb->state) {
-	case SlotEmpty:
-
-		switch (message) {
-		case CardDetected:
-			cb->state = SlotFull;
-			powerup(cb);
-			break;
-		case CardEjected:
-			break;
-		default:
-			//print("#Y%d: Invalid message %s in SlotEmpty state\n",
-			//	(int)(cb - cbslots), messages[message]);
-			break;
-		}
-		break;
-
-	case SlotFull:
-
-		switch (message) {
-		case CardPowered:
-			cb->state = SlotPowered;
-			configure(cb);
-			break;
-		case CardEjected:
-			cb->state = SlotEmpty;
-			powerdown(cb);
-			break;
-		default:
-			//print("#Y%d: Invalid message %s in SlotFull state\n",
-			//	(int)(cb - cbslots), messages[message]);
-			break;
-		}
-		break;
-
-	case SlotPowered:
-
-		switch (message) {
-		case CardConfigured:
-			cb->state = SlotConfigured;
-			break;
-		case CardEjected:
-			cb->state = SlotEmpty;
-			unconfigure(cb);
-			powerdown(cb);
-			break;
-		default:
-			print("#Y%d: Invalid message %s in SlotPowered state\n",
-				(int)(cb - cbslots), messages[message]);
-			break;
-		}
-		break;
-
-	case SlotConfigured:
-
-		switch (message) {
-		case CardEjected:
-			cb->state = SlotEmpty;
-			unconfigure(cb);
-			powerdown(cb);
-			break;
-		default:
-			//print("#Y%d: Invalid message %s in SlotConfigured state\n",
-			//	(int)(cb - cbslots), messages[message]);
-			break;
-		}
-		break;
-	}
-}
-
-void
-devpccardlink(void)
-{
-	static int initialized;
-	Pcidev *pci;
-	int i;
-	char *p;
-
-	if (initialized) 
-		return;
-	initialized = 1;
-
-	if((p=getconf("pccard0")) && strncmp(p, "disabled", 8)==0)
-		return;
-
-	if(_pcmspecial)
-		return;
-
-
-	/* Allocate legacy space */
-	if (ioalloc(LegacyAddr, 2, 0, "i82365.0") < 0)
-		print("#Y: WARNING: Cannot allocate legacy ports\n");
-
-	/* Find all CardBus controllers */
-	pci = nil;
-	while ((pci = pcimatch(pci, 0, 0)) != nil) {
-		ulong baddr;
-		uchar pin;
-		Cardbus *cb;
-		int slot;
-
-		if(pci->ccrb != 6 || pci->ccru != 7)
-			continue;
-		for (i = 0; i != nelem(variant); i++)
-			if (pci->vid == variant[i].vid && pci->did == variant[i].did)
-				break;
-		if (i == nelem(variant))
-			continue;
-
-		/* initialize this slot */
-		slot = nslots++;
-		cb = &cbslots[slot];
-
-		cb->pci = pci;
-		cb->variant = &variant[i];
-
-		// Set up PCI bus numbers if needed.
-		if (pcicfgr8(pci, PciSBN) == 0) {
-			static int busbase = 0x20;
-
-			pcicfgw8(pci, PciSBN, busbase);
-			pcicfgw8(pci, PciUBN, busbase + 2);
-			busbase += 3;
-		}
-
-		// Patch up intl if needed.
-		if ((pin = pcicfgr8(pci, PciINTP)) != 0 && 
-		    (pci->intl == 0xff || pci->intl == 0)) {
-			pci->intl = pciipin(nil, pin);
-			pcicfgw8(pci, PciINTL, pci->intl);
-
-			if (pci->intl == 0xff || pci->intl == 0)
-				print("#Y%d: No interrupt?\n", (int)(cb - cbslots));
-		}
-		
-		// Don't you love standards!
-		if (pci->vid == TI_vid) {
-			if (pci->did <= TI_1131_did) {
-				uchar cc;
-
-				cc = pcicfgr8(pci, TI1131xCC);
-				cc &= ~(TI113X_CC_PCI_IRQ_ENA |
-						TI113X_CC_PCI_IREQ | 
-						TI113X_CC_PCI_CSC |
-						TI113X_CC_ZVENABLE);
-				cc |= TI113X_CC_PCI_IRQ_ENA | 
-						TI113X_CC_PCI_IREQ | 
-						TI113X_CC_SPKROUTEN;
-				pcicfgw8(pci, TI1131xCC, cc);
-
-				// PCI interrupts only
-				pcicfgw8(pci, TI1131xDC, 
-						pcicfgr8(pci, TI1131xDC) & ~6);
-
-				// CSC ints to PCI bus.
-				wrreg(cb, Rigc, rdreg(cb, Rigc) | 0x10);
-			}
-			else if (pci->did == TI_1250_did) {
-				print("No support yet for the TI_1250_did, prod pb\n");
-			}
-			else if (pci->did == TI_1420_did) {
-				// Disable Vcc protection
-				pcicfgw32(cb->pci, 0x80, 
-					pcicfgr32(cb->pci, 0x80) | (1 << 21));
-			}
-			
-			pcicfgw16(cb->pci, PciPMC, pcicfgr16(cb->pci, PciPMC) & ~3);
-		}
-	
-		if ((baddr = pcicfgr32(cb->pci, PciBAR0)) == 0) {
-			int size = (pci->did == Ricoh_478_did)? 0x10000: 0x1000;
-
-			baddr = upamalloc(baddr, size, size);
-			pcicfgw32(cb->pci, PciBAR0, baddr);
-			cb->regs = (ulong *)KADDR(baddr);
-		}
-		else
-			cb->regs = (ulong *)KADDR(upamalloc(baddr, 4096, 0));
-		cb->state = SlotEmpty;
-
-		/* Don't really know what to do with this... */
-		i82365probe(cb, LegacyAddr, LegacyAddr + 1);
-
-		print("#Y%ld: %s, %.8ulX intl %d\n", cb - cbslots, 
-			 variant[i].name, baddr, pci->intl);
-	}
-
-	if (nslots == 0)
-		return;
-
-	_pcmspecial = pccard_pcmspecial;
-	_pcmspecialclose = pccard_pcmspecialclose;
-
-	for (i = 0; i != nslots; i++) {
-		Cardbus *cb = &cbslots[i];
-
-		if ((cb->regs[SocketState] & SE_CCD) == 0)
-			engine(cb, CardDetected);
-	}
-
-	delay(500);			/* Allow time for power up */
-
-	for (i = 0; i != nslots; i++) {
-		Cardbus *cb = &cbslots[i];
-
-		if (cb->regs[SocketState] & SE_POWER)
-			engine(cb, CardPowered);
-
-		/* Ack and enable interrupts on all events */
-		//cb->regs[SocketEvent] = cb->regs[SocketEvent];
-		//cb->regs[SocketMask] |= 0xF;	
-		//wrreg(cb, Rcscic, 0xC);
-	}
-}
-
-static int
-powerup(Cardbus *cb)
-{
-	ulong state;
-	ushort bcr;
-
-	state = cb->regs[SocketState];
-	if (state & SS_PC16) {
-	
-		// print("#Y%ld: Probed a PC16 card, powering up card\n", cb - cbslots);
-		cb->type = PC16;
-		memset(&cb->linfo, 0, sizeof(Pcminfo));
-
-		/* power up and unreset, wait's are empirical (???) */
-		wrreg(cb, Rpc, Fautopower|Foutena|Fcardena);
-		delay(300);
-		wrreg(cb, Rigc, 0);
-		delay(100);
-		wrreg(cb, Rigc, Fnotreset);
-		delay(500);
-
-		return 1;
-	}
-
-	if (state & SS_CCD)
-		return 0;
-
-	if (state & SS_NOTCARD) {
-		print("#Y%ld: No card inserted\n", cb - cbslots);
-		return 0;
-	}
-
-	if (state & SS_BADVCC) {
-		print("#Y%ld: Bad VCC request to card, powering down card!\n", 
-			 cb - cbslots);
-		cb->regs[SocketControl] = 0;
-		return 0;
-	}
-
-	if ((state & SS_3V) == 0 && (state & SS_5V) == 0) {
-		print("#Y%ld: Unsupported voltage, powering down card!\n", 
-			cb - cbslots);
-		cb->regs[SocketControl] = 0;
-		return 0;
-	}
-
-	//print("#Y%ld: card %spowered at %d volt\n", cb - cbslots, 
-	//	(state & SS_POWER)? "": "not ", 
-	//	(state & SS_3V)? 3: (state & SS_5V)? 5: -1);
-
-	/* Power up the card
-	 * and make sure the secondary bus is not in reset.
-	 */
-	cb->regs[SocketControl] = (state & SS_5V)? SC_5V: SC_3V;
-	delay(50);
-	bcr = pcicfgr16(cb->pci, PciBCR);
-	bcr &= ~0x40;
-	pcicfgw16(cb->pci, PciBCR, bcr);
-	delay(100);
-
-	cb->type = PC32;
-
-	return 1;
-}
-
-static void
-powerdown(Cardbus *cb)
-{
-	ushort bcr;
-
-	if (cb->type == PC16) {
-
-		wrreg(cb, Rpc, 0);	/* turn off card power */
-		wrreg(cb, Rwe, 0);	/* no windows */
-
-		cb->type = -1;
-		return;
-	}
-
-	bcr = pcicfgr16(cb->pci, PciBCR);
-	bcr |= 0x40;
-	pcicfgw16(cb->pci, PciBCR, bcr);
-	cb->regs[SocketControl] = 0;
-	cb->type = -1;
-}
-
-static void
-configure(Cardbus *cb)
-{
-	Pcidev *pci;
-	ulong size, bar;
-	int i, ioindex, memindex, r;
-
-	//print("configuring slot %d (%s)\n", (int)(cb - cbslots), states[cb->state]);
-	if (cb->state == SlotConfigured)
-		return;
-	engine(cb, CardConfigured);
-
-	delay(50);					/* Emperically established */
-
-	if (cb->type == PC16) {
-		i82365configure(cb);
-		return;
-	}
-
-	/* Scan the CardBus for new PCI devices */
-	pciscan(pcicfgr8(cb->pci, PciSBN), &cb->pci->bridge);
-	pci = cb->pci->bridge;
-	while (pci) {
-		r = pcicfgr16(pci, PciPCR);
-		r &= ~(PciPCR_IO|PciPCR_MEM);
-		pcicfgw16(pci, PciPCR, r);
-
-		/*
-		 * Treat the found device as an ordinary PCI card.
-		 * It seems that the CIS is not always present in
-		 * CardBus cards.
-		 * XXX, need to support multifunction cards
-		 */
-		memindex = ioindex = 0;
-		for (i = 0; i != Nbars; i++) {
-
-			if (pci->mem[i].size == 0)
-				continue;
-			if (pci->mem[i].bar & 1) {
-
-				// Allocate I/O space
-				if (ioindex > 1) {
-					print("#Y%ld: WARNING: Can only configure 2 I/O slots\n", cb - cbslots);
-					continue;
-				}
-				bar = ioreserve(-1, pci->mem[i].size, 0, "cardbus");
-				pci->mem[i].bar = bar | 1;
-				pcicfgw32(pci, PciBAR0 + i * sizeof(ulong), 
-					          pci->mem[i].bar);
-				pcicfgw16(cb->pci, PciCBIBR0 + ioindex * 8, bar);
-				pcicfgw16(cb->pci, PciCBILR0 + ioindex * 8, 
-						 bar + pci->mem[i].size - 1);
-				//print("ioindex[%d] %.8uX (%d)\n", 
-				//	ioindex, bar, pci->mem[i].size);
-				ioindex++;
-				continue;
-			}
-
-			// Allocating memory space
-			if (memindex > 1) {
-				print("#Y%ld: WARNING: Can only configure 2 memory slots\n", cb - cbslots);
-				continue;
-			}
-
-			bar = upamalloc(0, pci->mem[i].size, BY2PG);
-			pci->mem[i].bar = bar | (pci->mem[i].bar & 0x80);
-			pcicfgw32(pci, PciBAR0 + i * sizeof(ulong), pci->mem[i].bar);
-			pcicfgw32(cb->pci, PciCBMBR0 + memindex * 8, bar);
-			pcicfgw32(cb->pci, PciCBMLR0 + memindex * 8, 
-					  bar + pci->mem[i].size - 1);
-
-			if (pci->mem[i].bar & 0x80) {
-				/* Enable prefetch */
-				r = pcicfgr16(cb->pci, PciBCR);
-				r |= 1 << (8 + memindex);
-				pcicfgw16(cb->pci, PciBCR, r);
-			}
-
-			//print("memindex[%d] %.8uX (%d)\n", 
-			//	  memindex, bar, pci->mem[i].size);
-			memindex++;
-		}
-
-		if ((size = pcibarsize(pci, PciEBAR0)) > 0) {
-
-			if (memindex > 1)
-				print("#Y%ld: WARNING: Too many memory spaces, not mapping ROM space\n",
-					cb - cbslots);
-			else {
-				pci->rom.bar = upamalloc(0, size, BY2PG);
-				pci->rom.size = size;
-
-				pcicfgw32(pci, PciEBAR0, pci->rom.bar);
-				pcicfgw32(cb->pci, PciCBMBR0 + memindex * 8,
-						 pci->rom.bar);
-				pcicfgw32(cb->pci, PciCBMLR0 + memindex * 8, 
-						 pci->rom.bar + pci->rom.size - 1);
-			}
-		}
-
-		/* Set the basic PCI registers for the device */
-		pci->pcr = pcicfgr16(pci, PciPCR);
-		pci->pcr |= PciPCR_IO|PciPCR_MEM|PciPCR_Master;
-		pci->cls = 8;
-		pci->ltr = 64;
-		pcicfgw16(pci, PciPCR, pci->pcr);
-		pcicfgw8(pci, PciCLS, pci->cls);
-		pcicfgw8(pci, PciLTR, pci->ltr);
-
-		if (pcicfgr8(pci, PciINTP)) {
-			pci->intl = pcicfgr8(cb->pci, PciINTL);
-			pcicfgw8(pci, PciINTL, pci->intl);
-
-			/* Route interrupts to INTA#/B# */
-			pcicfgw16(cb->pci, PciBCR, 
-					  pcicfgr16(cb->pci, PciBCR) & ~(1 << 7));
-		}
-			
-		pci = pci->list;
-	}
-}
-
-static void
-unconfigure(Cardbus *cb)
-{
-	Pcidev *pci;
-	int i, ioindex, memindex, r;
-
-	if (cb->type == PC16) {
-		print("#Y%d: Don't know how to unconfigure a PC16 card\n",
-			 (int)(cb - cbslots));
-
-		memset(&cb->linfo, 0, sizeof(Pcminfo));
-		return;
-	}
-
-	pci = cb->pci->bridge;
-	if (pci == nil) 
-		return;		/* Not configured */
-	cb->pci->bridge = nil;		
-
-	memindex = ioindex = 0;
-	while (pci) {
-		Pcidev *_pci;
-
-		for (i = 0; i != Nbars; i++) {
-			if (pci->mem[i].size == 0)
-				continue;
-			if (pci->mem[i].bar & 1) {
-				iofree(pci->mem[i].bar & ~1);
-				pcicfgw16(cb->pci, PciCBIBR0 + ioindex * 8, 
-						 (ushort)-1);
-				pcicfgw16(cb->pci, PciCBILR0 + ioindex * 8, 0);
-				ioindex++;
-				continue;
-			}
-
-			upafree(pci->mem[i].bar & ~0xF, pci->mem[i].size);
-			pcicfgw32(cb->pci, PciCBMBR0 + memindex * 8, (ulong)-1);
-			pcicfgw32(cb->pci, PciCBMLR0 + memindex * 8, 0);
-			r = pcicfgr16(cb->pci, PciBCR);
-			r &= ~(1 << (8 + memindex));
-			pcicfgw16(cb->pci, PciBCR, r);
-			memindex++;
-		}
-
-		if (pci->rom.bar && memindex < 2) {
-			upafree(pci->rom.bar & ~0xF, pci->rom.size);
-			pcicfgw32(cb->pci, PciCBMBR0 + memindex * 8, (ulong)-1);
-			pcicfgw32(cb->pci, PciCBMLR0 + memindex * 8, 0);
-			memindex++;
-		}
-
-		_pci = pci->list;
-		free(_pci);
-		pci = _pci;
-	}
-}
-
-static void
-i82365configure(Cardbus *cb)
-{
-	int this;
-	Cisdat cis;
-	PCMmap *m;
-	uchar type, link;
-
-	/*
-	 * Read all tuples in attribute space.
-	 */
-	m = isamap(cb, 0, 0, 1);
-	if(m == 0)
-		return;
-
-	cis.cisbase = KADDR(m->isa);
-	cis.cispos = 0;
-	cis.cisskip = 2;
-	cis.cislen = m->len;
-
-	/* loop through all the tuples */
-	for(;;){
-		this = cis.cispos;
-		if(readc(&cis, &type) != 1)
-			break;
-		if(type == 0xFF)
-			break;
-		if(readc(&cis, &link) != 1)
-			break;
-
-		switch(type){
-		default:
-			break;
-		case 0x15:
-			tvers1(cb, &cis, type);
-			break;
-		case 0x1A:
-			tcfig(cb, &cis, type);
-			break;
-		case 0x1B:
-			tentry(cb, &cis, type);
-			break;
-		}
-
-		if(link == 0xFF)
-			break;
-		cis.cispos = this + (2+link);
-	}
-	isaunmap(m);
-}
-
-/*
- *  look for a card whose version contains 'idstr'
- */
-static int
-pccard_pcmspecial(char *idstr, ISAConf *isa)
-{
-	int i, irq;
-	PCMconftab *ct, *et;
-	Pcminfo *pi;
-	Cardbus *cb;
-	uchar x, we, *p;
-
-	cb = nil;
-	for (i = 0; i != nslots; i++) {
-		cb = &cbslots[i];
-
-		lock(cb);
-		if (cb->state == SlotConfigured &&
-		    cb->type == PC16 && 
-		    !cb->special &&
-		    strstr(cb->linfo.verstr, idstr)) 
-			break;
-		unlock(cb);
-	}
-
-	if (i == nslots) {
-		// print("#Y: %s not found\n", idstr);
-		return -1;
-	}
-
-	pi = &cb->linfo;
-
-	/*
- 	  *  configure the PCMslot for IO.  We assume very heavily that we can read
- 	  *  configuration info from the CIS.  If not, we won't set up correctly.
- 	  */
-	irq = isa->irq;
-	if(irq == 2)
-		irq = 9;
-
-	et = &pi->ctab[pi->nctab];
-	ct = nil;
-	for(i = 0; i < isa->nopt; i++){
-		int index;
-		char *cp;
-
-		if(strncmp(isa->opt[i], "index=", 6))
-			continue;
-		index = strtol(&isa->opt[i][6], &cp, 0);
-		if(cp == &isa->opt[i][6] || index >= pi->nctab) {
-			unlock(cb);
-			print("#Y%d: Cannot find index %d in conf table\n", 
-				 (int)(cb - cbslots), index);
-			return -1;
-		}
-		ct = &pi->ctab[index];
-	}
-
-	if(ct == nil){
-		PCMconftab *t;
-
-		/* assume default is right */
-		if(pi->defctab)
-			ct = pi->defctab;
-		else
-			ct = pi->ctab;
-	
-		/* try for best match */
-		if(ct->nio == 0
-		|| ct->io[0].start != isa->port || ((1<<irq) & ct->irqs) == 0){
-			for(t = pi->ctab; t < et; t++)
-				if(t->nio
-				&& t->io[0].start == isa->port
-				&& ((1<<irq) & t->irqs)){
-					ct = t;
-					break;
-				}
-		}
-		if(ct->nio == 0 || ((1<<irq) & ct->irqs) == 0){
-			for(t = pi->ctab; t < et; t++)
-				if(t->nio && ((1<<irq) & t->irqs)){
-					ct = t;
-					break;
-				}
-		}
-		if(ct->nio == 0){
-			for(t = pi->ctab; t < et; t++)
-				if(t->nio){
-					ct = t;
-					break;
-				}
-		}
-	}
-
-	if(ct == et || ct->nio == 0) {
-		unlock(cb);
-		print("#Y%d: No configuration?\n", (int)(cb - cbslots));
-		return -1;
-	}
-	if(isa->port == 0 && ct->io[0].start == 0) {
-		unlock(cb);
-		print("#Y%d: No part or start address\n", (int)(cb - cbslots));
-		return -1;
-	}
-
-	cb->special = 1;	/* taken */
-
-	/* route interrupts */
-	isa->irq = irq;
-	wrreg(cb, Rigc, irq | Fnotreset | Fiocard);
-
-	/* set power and enable device */
-	x = vcode(ct->vpp1);
-	wrreg(cb, Rpc, x|Fautopower|Foutena|Fcardena);
-
-	/* 16-bit data path */
-	if(ct->bit16)
-		x = Ftiming|Fiocs16|Fwidth16;
-	else
-		x = Ftiming;
-	if(ct->nio == 2 && ct->io[1].start)
-		x |= x<<4;
-	wrreg(cb, Rio, x);
-
-	/*
-	 * enable io port map 0
-	 * the 'top' register value includes the last valid address
-	 */
-	if(isa->port == 0)
-		isa->port = ct->io[0].start;
-	we = rdreg(cb, Rwe);
-	wrreg(cb, Riobtm0lo, isa->port);
-	wrreg(cb, Riobtm0hi, isa->port>>8);
-	i = isa->port+ct->io[0].len-1;
-	wrreg(cb, Riotop0lo, i);
-	wrreg(cb, Riotop0hi, i>>8);
-	we |= 1<<6;
-	if(ct->nio == 2 && ct->io[1].start){
-		wrreg(cb, Riobtm1lo, ct->io[1].start);
-		wrreg(cb, Riobtm1hi, ct->io[1].start>>8);
-		i = ct->io[1].start+ct->io[1].len-1;
-		wrreg(cb, Riotop1lo, i);
-		wrreg(cb, Riotop1hi, i>>8);
-		we |= 1<<7;
-	}
-	wrreg(cb, Rwe, we);
-
-	/* only touch Rconfig if it is present */
-	if(pi->conf_present & (1<<Rconfig)){
-		PCMmap *m;
-
-		/*  Reset adapter */
-		m = isamap(cb, pi->conf_addr + Rconfig, 1, 1);
-		p = KADDR(m->isa + pi->conf_addr + Rconfig - m->ca);
-
-		/* set configuration and interrupt type */
-		x = ct->index;
-		if((ct->irqtype & 0x20)/* && ((ct->irqtype & 0x40)==0 || isa->irq>7)*/)
-			x |= Clevel;
-		*p = x;
-		delay(5);
-
-		isaunmap(m);
-	}
-
-	pi->port = isa->port;
-	pi->irq = isa->irq;
-	unlock(cb);
-
-	print("#Y%d: %s irq %ld, port %lX\n", (int)(cb - cbslots), pi->verstr, isa->irq, isa->port);
-	return (int)(cb - cbslots);
-}
-
-static void
-pccard_pcmspecialclose(int slotno)
-{
-	Cardbus *cb = &cbslots[slotno];
-
-	wrreg(cb, Rwe, 0);	/* no windows */
-	cb->special = 0;
-}
-
-static int
-xcistuple(int slotno, int tuple, int subtuple, void *v, int nv, int attr)
-{
-	PCMmap *m;
-	Cisdat cis;
-	int i, l;
-	uchar *p;
-	uchar type, link, n, c;
-	int this, subtype;
-	Cardbus *cb = &cbslots[slotno];
-
-	m = isamap(cb, 0, 0, attr);
-	if(m == 0)
-		return -1;
-
-	cis.cisbase = KADDR(m->isa);
-	cis.cispos = 0;
-	cis.cisskip = attr ? 2 : 1;
-	cis.cislen = m->len;
-
-	/* loop through all the tuples */
-	for(i = 0; i < 1000; i++){
-		this = cis.cispos;
-		if(readc(&cis, &type) != 1)
-			break;
-		if(type == 0xFF)
-			break;
-		if(readc(&cis, &link) != 1)
-			break;
-		if(link == 0xFF)
-			break;
-
-		n = link;
-		if (link > 1 && subtuple != -1) {
-			if (readc(&cis, &c) != 1)
-				break;
-			subtype = c;
-			n--;
-		} else
-			subtype = -1;
-
-		if(type == tuple && subtype == subtuple) {
-			p = v;
-			for(l=0; l<nv && l<n; l++)
-				if(readc(&cis, p++) != 1)
-					break;
-			isaunmap(m);
-			return nv;
-		}
-		cis.cispos = this + (2+link);
-	}
-	isaunmap(m);
-	return -1;
-}
-
-static PCMmap *
-isamap(Cardbus *cb, ulong offset, int len, int attr)
-{
-	uchar we, bit;
-	PCMmap *m, *nm;
-	Pcminfo *pi;
-	int i;
-	ulong e;
-
-	pi = &cb->linfo;
-
-	/* convert offset to granularity */
-	if(len <= 0)
-		len = 1;
-	e = ROUND(offset+len, Mgran);
-	offset &= Mmask;
-	len = e - offset;
-
-	/* look for a map that covers the right area */
-	we = rdreg(cb, Rwe);
-	bit = 1;
-	nm = 0;
-	for(m = pi->mmap; m < &pi->mmap[nelem(pi->mmap)]; m++){
-		if((we & bit))
-		if(m->attr == attr)
-		if(offset >= m->ca && e <= m->cea){
-
-			m->ref++;
-			return m;
-		}
-		bit <<= 1;
-		if(nm == 0 && m->ref == 0)
-			nm = m;
-	}
-	m = nm;
-	if(m == 0)
-		return 0;
-
-	/* if isa space isn't big enough, free it and get more */
-	if(m->len < len){
-		if(m->isa){
-			umbfree(m->isa, m->len);
-			m->len = 0;
-		}
-		m->isa = PADDR(umbmalloc(0, len, Mgran));
-		if(m->isa == 0){
-			print("isamap: out of isa space\n");
-			return 0;
-		}
-		m->len = len;
-	}
-
-	/* set up new map */
-	m->ca = offset;
-	m->cea = m->ca + m->len;
-	m->attr = attr;
-	i = m - pi->mmap;
-	bit = 1<<i;
-	wrreg(cb, Rwe, we & ~bit);		/* disable map before changing it */
-	wrreg(cb, MAP(i, Mbtmlo), m->isa>>Mshift);
-	wrreg(cb, MAP(i, Mbtmhi), (m->isa>>(Mshift+8)) | F16bit);
-	wrreg(cb, MAP(i, Mtoplo), (m->isa+m->len-1)>>Mshift);
-	wrreg(cb, MAP(i, Mtophi), ((m->isa+m->len-1)>>(Mshift+8)));
-	offset -= m->isa;
-	offset &= (1<<25)-1;
-	offset >>= Mshift;
-	wrreg(cb, MAP(i, Mofflo), offset);
-	wrreg(cb, MAP(i, Moffhi), (offset>>8) | (attr ? Fregactive : 0));
-	wrreg(cb, Rwe, we | bit);		/* enable map */
-	m->ref = 1;
-
-	return m;
-}
-
-static void
-isaunmap(PCMmap* m)
-{
-	m->ref--;
-}
-
-/*
- *  reading and writing card registers
- */
-static uchar
-rdreg(Cardbus *cb, int index)
-{
-	outb(cb->lindex, cb->lbase + index);
-	return inb(cb->ldata);
-}
-
-static void
-wrreg(Cardbus *cb, int index, uchar val)
-{
-	outb(cb->lindex, cb->lbase + index);
-	outb(cb->ldata, val);
-}
-
-static int
-readc(Cisdat *cis, uchar *x)
-{
-	if(cis->cispos >= cis->cislen)
-		return 0;
-	*x = cis->cisbase[cis->cisskip*cis->cispos];
-	cis->cispos++;
-	return 1;
-}
-
-static ulong
-getlong(Cisdat *cis, int size)
-{
-	uchar c;
-	int i;
-	ulong x;
-
-	x = 0;
-	for(i = 0; i < size; i++){
-		if(readc(cis, &c) != 1)
-			break;
-		x |= c<<(i*8);
-	}
-	return x;
-}
-
-static void
-tcfig(Cardbus *cb, Cisdat *cis, int )
-{
-	uchar size, rasize, rmsize;
-	uchar last;
-	Pcminfo *pi;
-
-	if(readc(cis, &size) != 1)
-		return;
-	rasize = (size&0x3) + 1;
-	rmsize = ((size>>2)&0xf) + 1;
-	if(readc(cis, &last) != 1)
-		return;
-
-	pi = &cb->linfo;
-	pi->conf_addr = getlong(cis, rasize);
-	pi->conf_present = getlong(cis, rmsize);
-}
-
-static void
-tvers1(Cardbus *cb, Cisdat *cis, int )
-{
-	uchar c, major, minor, last;
-	int  i;
-	Pcminfo *pi;
-
-	pi = &cb->linfo;
-	if(readc(cis, &major) != 1)
-		return;
-	if(readc(cis, &minor) != 1)
-		return;
-	last = 0;
-	for(i = 0; i < sizeof(pi->verstr) - 1; i++){
-		if(readc(cis, &c) != 1)
-			return;
-		if(c == 0)
-			c = ';';
-		if(c == '\n')
-			c = ';';
-		if(c == 0xff)
-			break;
-		if(c == ';' && last == ';')
-			continue;
-		pi->verstr[i] = c;
-		last = c;
-	}
-	pi->verstr[i] = 0;
-}
-
-static ulong
-microvolt(Cisdat *cis)
-{
-	uchar c;
-	ulong microvolts;
-	ulong exp;
-
-	if(readc(cis, &c) != 1)
-		return 0;
-	exp = exponent[c&0x7];
-	microvolts = vmant[(c>>3)&0xf]*exp;
-	while(c & 0x80){
-		if(readc(cis, &c) != 1)
-			return 0;
-		switch(c){
-		case 0x7d:
-			break;		/* high impedence when sleeping */
-		case 0x7e:
-		case 0x7f:
-			microvolts = 0;	/* no connection */
-			break;
-		default:
-			exp /= 10;
-			microvolts += exp*(c&0x7f);
-		}
-	}
-	return microvolts;
-}
-
-static ulong
-nanoamps(Cisdat *cis)
-{
-	uchar c;
-	ulong nanoamps;
-
-	if(readc(cis, &c) != 1)
-		return 0;
-	nanoamps = exponent[c&0x7]*vmant[(c>>3)&0xf];
-	while(c & 0x80){
-		if(readc(cis, &c) != 1)
-			return 0;
-		if(c == 0x7d || c == 0x7e || c == 0x7f)
-			nanoamps = 0;
-	}
-	return nanoamps;
-}
-
-/*
- * only nominal voltage (feature 1) is important for config,
- * other features must read card to stay in sync.
- */
-static ulong
-power(Cisdat *cis)
-{
-	uchar feature;
-	ulong mv;
-
-	mv = 0;
-	if(readc(cis, &feature) != 1)
-		return 0;
-	if(feature & 1)
-		mv = microvolt(cis);
-	if(feature & 2)
-		microvolt(cis);
-	if(feature & 4)
-		microvolt(cis);
-	if(feature & 8)
-		nanoamps(cis);
-	if(feature & 0x10)
-		nanoamps(cis);
-	if(feature & 0x20)
-		nanoamps(cis);
-	if(feature & 0x40)
-		nanoamps(cis);
-	return mv/1000000;
-}
-
-static ulong
-ttiming(Cisdat *cis, int scale)
-{
-	uchar unscaled;
-	ulong nanosecs;
-
-	if(readc(cis, &unscaled) != 1)
-		return 0;
-	nanosecs = (mantissa[(unscaled>>3)&0xf]*exponent[unscaled&7])/10;
-	nanosecs = nanosecs * exponent[scale];
-	return nanosecs;
-}
-
-static void
-timing(Cisdat *cis, PCMconftab *ct)
-{
-	uchar c, i;
-
-	if(readc(cis, &c) != 1)
-		return;
-	i = c&0x3;
-	if(i != 3)
-		ct->maxwait = ttiming(cis, i);		/* max wait */
-	i = (c>>2)&0x7;
-	if(i != 7)
-		ct->readywait = ttiming(cis, i);	/* max ready/busy wait */
-	i = (c>>5)&0x7;
-	if(i != 7)
-		ct->otherwait = ttiming(cis, i);	/* reserved wait */
-}
-
-static void
-iospaces(Cisdat *cis, PCMconftab *ct)
-{
-	uchar c;
-	int i, nio;
-
-	ct->nio = 0;
-	if(readc(cis, &c) != 1)
-		return;
-
-	ct->bit16 = ((c>>5)&3) >= 2;
-	if(!(c & 0x80)){
-		ct->io[0].start = 0;
-		ct->io[0].len = 1<<(c&0x1f);
-		ct->nio = 1;
-		return;
-	}
-
-	if(readc(cis, &c) != 1)
-		return;
-
-	/*
-	 * For each of the range descriptions read the
-	 * start address and the length (value is length-1).
-	 */
-	nio = (c&0xf)+1;
-	for(i = 0; i < nio; i++){
-		ct->io[i].start = getlong(cis, (c>>4)&0x3);
-		ct->io[i].len = getlong(cis, (c>>6)&0x3)+1;
-	}
-	ct->nio = nio;
-}
-
-static void
-irq(Cisdat *cis, PCMconftab *ct)
-{
-	uchar c;
-
-	if(readc(cis, &c) != 1)
-		return;
-	ct->irqtype = c & 0xe0;
-	if(c & 0x10)
-		ct->irqs = getlong(cis, 2);
-	else
-		ct->irqs = 1<<(c&0xf);
-	ct->irqs &= 0xDEB8;		/* levels available to card */
-}
-
-static void
-memspace(Cisdat *cis, int asize, int lsize, int host)
-{
-	ulong haddress, address, len;
-
-	len = getlong(cis, lsize)*256;
-	address = getlong(cis, asize)*256;
-	USED(len, address);
-	if(host){
-		haddress = getlong(cis, asize)*256;
-		USED(haddress);
-	}
-}
-
-static void
-tentry(Cardbus *cb, Cisdat *cis, int )
-{
-	uchar c, i, feature;
-	PCMconftab *ct;
-	Pcminfo *pi;
-
-	pi = &cb->linfo;
-	if(pi->nctab >= nelem(pi->ctab))
-		return;
-	if(readc(cis, &c) != 1)
-		return;
-	ct = &pi->ctab[pi->nctab++];
-
-	/* copy from last default config */
-	if(pi->defctab)
-		*ct = *pi->defctab;
-
-	ct->index = c & 0x3f;
-
-	/* is this the new default? */
-	if(c & 0x40)
-		pi->defctab = ct;
-
-	/* memory wait specified? */
-	if(c & 0x80){
-		if(readc(cis, &i) != 1)
-			return;
-		if(i&0x80)
-			ct->memwait = 1;
-	}
-
-	if(readc(cis, &feature) != 1)
-		return;
-	switch(feature&0x3){
-	case 1:
-		ct->vpp1 = ct->vpp2 = power(cis);
-		break;
-	case 2:
-		power(cis);
-		ct->vpp1 = ct->vpp2 = power(cis);
-		break;
-	case 3:
-		power(cis);
-		ct->vpp1 = power(cis);
-		ct->vpp2 = power(cis);
-		break;
-	default:
-		break;
-	}
-	if(feature&0x4)
-		timing(cis, ct);
-	if(feature&0x8)
-		iospaces(cis, ct);
-	if(feature&0x10)
-		irq(cis, ct);
-	switch((feature>>5)&0x3){
-	case 1:
-		memspace(cis, 0, 2, 0);
-		break;
-	case 2:
-		memspace(cis, 2, 2, 0);
-		break;
-	case 3:
-		if(readc(cis, &c) != 1)
-			return;
-		for(i = 0; i <= (c&0x7); i++)
-			memspace(cis, (c>>5)&0x3, (c>>3)&0x3, c&0x80);
-		break;
-	}
-}
-
-static void
-i82365probe(Cardbus *cb, int lindex, int ldata)
-{
-	uchar c, id;
-	int dev = 0;	/* According to the Ricoh spec 00->3F _and_ 80->BF seem
-				     to be the same socket A (ditto for B). */
-
-	outb(lindex, Rid + (dev<<7));
-	id = inb(ldata);
-	if((id & 0xf0) != 0x80)
-		return;		/* not a memory & I/O card */
-	if((id & 0x0f) == 0x00)
-		return;		/* no revision number, not possible */
-
-	cb->lindex = lindex;
-	cb->ldata = ldata;
-	cb->ltype = Ti82365;
-	cb->lbase = (int)(cb - cbslots) * 0x40;
-
-	switch(id){
-	case 0x82:
-	case 0x83:
-	case 0x84:
-		/* could be a cirrus */
-		outb(cb->lindex, Rchipinfo + (dev<<7));
-		outb(cb->ldata, 0);
-		c = inb(cb->ldata);
-		if((c & 0xc0) != 0xc0)
-			break;
-		c = inb(cb->ldata);
-		if((c & 0xc0) != 0x00)
-			break;
-		if(c & 0x20){
-			cb->ltype = Tpd6720;
-		} else {
-			cb->ltype = Tpd6710;
-		}
-		break;
-	}
-
-	/* if it's not a Cirrus, it could be a Vadem... */
-	if(cb->ltype == Ti82365){
-		/* unlock the Vadem extended regs */
-		outb(cb->lindex, 0x0E + (dev<<7));
-		outb(cb->lindex, 0x37 + (dev<<7));
-
-		/* make the id register show the Vadem id */
-		outb(cb->lindex, 0x3A + (dev<<7));
-		c = inb(cb->ldata);
-		outb(cb->ldata, c|0xC0);
-		outb(cb->lindex, Rid + (dev<<7));
-		c = inb(cb->ldata);
-		if(c & 0x08)
-			cb->ltype = Tvg46x;
-
-		/* go back to Intel compatible id */
-		outb(cb->lindex, 0x3A + (dev<<7));
-		c = inb(cb->ldata);
-		outb(cb->ldata, c & ~0xC0);
-	}
-}
-
-static int
-vcode(int volt)
-{
-	switch(volt){
-	case 5:
-		return 1;
-	case 12:
-		return 2;
-	default:
-		return 0;
-	}
-}
--- a/os/boot/pc/devsd.c
+++ /dev/null
@@ -1,631 +1,0 @@
-/*
- * Storage Device.
- */
-#include "u.h"
-#include "mem.h"
-#include "lib.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-#include "ureg.h"
-#include "error.h"
-
-#include "sd.h"
-#include "fs.h"
-
-#define parttrace 0
-
-
-extern SDifc* sdifc[];
-
-static SDev* sdlist;
-static SDunit** sdunit;
-static int sdnunit;
-static int _sdmask;
-static int cdmask;
-static int sdmask;
-
-enum {
-	Rawcmd,
-	Rawdata,
-	Rawstatus,
-};
-
-void
-sdaddpart(SDunit* unit, char* name, uvlong start, uvlong end)
-{
-	SDpart *pp;
-	int i, partno;
-
-	if(parttrace)
-		print("add %d %s %s %lld %lld\n", unit->npart, unit->name, name, start, end);
-	/*
-	 * Check name not already used
-	 * and look for a free slot.
-	 */
-	if(unit->part != nil){
-		partno = -1;
-		for(i = 0; i < SDnpart; i++){
-			pp = &unit->part[i];
-			if(!pp->valid){
-				if(partno == -1)
-					partno = i;
-				break;
-			}
-			if(strcmp(name, pp->name) == 0){
-				if(pp->start == start && pp->end == end){
-					if(parttrace)
-						print("already present\n");
-					return;
-				}
-			}
-		}
-	}else{
-		if((unit->part = malloc(sizeof(SDpart)*SDnpart)) == nil){
-			if(parttrace)
-				print("malloc failed\n");
-			return;
-		}
-		partno = 0;
-	}
-
-	/*
-	 * Check there is a free slot and size and extent are valid.
-	 */
-	if(partno == -1 || start > end || end > unit->sectors){
-		print("cannot add %s!%s [%llud,%llud) to disk [0,%llud): %s\n",
-			unit->name, name, start, end, unit->sectors, 
-			partno==-1 ? "no free partitions" : "partition boundaries out of range");
-		return;
-	}
-	pp = &unit->part[partno];
-	pp->start = start;
-	pp->end = end;
-	strncpy(pp->name, name, NAMELEN);
-	pp->valid = 1;
-	unit->npart++;
-}
-
-void
-sddelpart(SDunit* unit,  char* name)
-{
-	int i;
-	SDpart *pp;
-
-	if(parttrace)
-		print("del %d %s %s\n", unit->npart, unit->name, name);
-	/*
-	 * Look for the partition to delete.
-	 * Can't delete if someone still has it open.
-	 * If it's the last valid partition zap the
-	 * whole table.
-	 */
-	pp = unit->part;
-	for(i = 0; i < SDnpart; i++){
-		if(strncmp(name, pp->name, NAMELEN) == 0)
-			break;
-		pp++;
-	}
-	if(i >= SDnpart)
-		return;
-	pp->valid = 0;
-
-	unit->npart--;
-	if(unit->npart == 0){
-		free(unit->part);
-		unit->part = nil;
-	}
-}
-
-static int
-sdinitpart(SDunit* unit)
-{
-	unit->sectors = unit->secsize = 0;
-	unit->npart = 0;
-	if(unit->part){
-		free(unit->part);
-		unit->part = nil;
-	}
-
-	if(unit->inquiry[0] & 0xC0)
-		return 0;
-	switch(unit->inquiry[0] & 0x1F){
-	case 0x00:			/* DA */
-	case 0x04:			/* WORM */
-	case 0x05:			/* CD-ROM */
-	case 0x07:			/* MO */
-		break;
-	default:
-		return 0;
-	}
-
-	if(unit->dev->ifc->online == nil || unit->dev->ifc->online(unit) == 0)
-		return 0;
-	sdaddpart(unit, "data", 0, unit->sectors);
-	return 1;
-}
-
-static SDunit*
-sdgetunit(SDev* sdev, int subno)
-{
-	int index;
-	SDunit *unit;
-
-	/*
-	 * Associate a unit with a given device and sub-unit
-	 * number on that device.
-	 * The device will be probed if it has not already been
-	 * successfully accessed.
-	 */
-	qlock(&sdqlock);
-	index = sdev->index+subno;
-	unit = sdunit[index];
-	if(unit == nil){
-		if((unit = malloc(sizeof(SDunit))) == nil){
-			qunlock(&sdqlock);
-			return nil;
-		}
-
-		if(sdev->enabled == 0 && sdev->ifc->enable)
-			sdev->ifc->enable(sdev);
-		sdev->enabled = 1;
-
-		snprint(unit->name, NAMELEN, "sd%c%d", sdev->idno, subno);
-		unit->subno = subno;
-		unit->dev = sdev;
-
-		/*
-		 * No need to lock anything here as this is only
-		 * called before the unit is made available in the
-		 * sdunit[] array.
-		 */
-		if(unit->dev->ifc->verify(unit) == 0){
-			qunlock(&sdqlock);
-			free(unit);
-			return nil;
-		}
-		sdunit[index] = unit;
-	}
-	qunlock(&sdqlock);
-
-	return unit;
-}
-
-static SDunit*
-sdindex2unit(int index)
-{
-	SDev *sdev;
-
-	/*
-	 * Associate a unit with a given index into the top-level
-	 * device directory.
-	 * The device will be probed if it has not already been
-	 * successfully accessed.
-	 */
-	for(sdev = sdlist; sdev != nil; sdev = sdev->next){
-		if(index >= sdev->index && index < sdev->index+sdev->nunit)
-			return sdgetunit(sdev, index-sdev->index);
-	}
-
-	return nil;
-}
-
-static void
-_sddetach(void)
-{
-	SDev *sdev;
-
-	for(sdev = sdlist; sdev != nil; sdev = sdev->next){
-		if(sdev->enabled == 0)
-			continue;
-		if(sdev->ifc->disable)
-			sdev->ifc->disable(sdev);
-		sdev->enabled = 0;
-	}
-}
-
-static void
-sddump(void)
-{
-	SDev *sdev;
-
-	print("sdevs:\n");
-	for(sdev = sdlist; sdev != nil; sdev = sdev->next){
-		print("sdev %c index %d nunit %d: ",
-			sdev->idno, sdev->index, sdev->nunit);
-		print("\n");
-	}
-}
-
-static int
-_sdinit(void)
-{
-	ulong m;
-	int i;
-	SDev *sdev, *tail;
-	SDunit *unit;
-
-	/*
-	 * Probe all configured controllers and make a list
-	 * of devices found, accumulating a possible maximum number
-	 * of units attached and marking each device with an index
-	 * into the linear top-level directory array of units.
-	 */
-	tail = nil;
-	for(i = 0; sdifc[i] != nil; i++){
-		if((sdev = sdifc[i]->pnp()) == nil)
-			continue;
-		if(sdlist != nil)
-			tail->next = sdev;
-		else
-			sdlist = sdev;
-		for(tail = sdev; tail->next != nil; tail = tail->next){
-			tail->index = sdnunit;
-			sdnunit += tail->nunit;
-		}
-		tail->index = sdnunit;
-		sdnunit += tail->nunit;
-	}
-	/*
-	 * Legacy and option code goes here. This will be hard...
-	 */
-
-	/*
-	 * The maximum number of possible units is known, allocate
-	 * placeholders for their datastructures; the units will be
-	 * probed and structures allocated when attached.
-	 * Allocate controller names for the different types.
-	 */
-	if(sdnunit == 0)
-		return 0;
-	if((sdunit = malloc(sdnunit*sizeof(SDunit*))) == nil)
-		return 0;
-	sddetach = _sddetach;
-
-	for(i = 0; sdifc[i] != nil; i++){
-		if(sdifc[i]->id)
-			sdifc[i]->id(sdlist);
-	}
-	if (0)
-		sddump();
-
-	m = 0;
-	cdmask = sdmask = 0;
-	for(i=0; i<sdnunit && i < 32; i++) {
-		unit = sdindex2unit(i);
-		if(unit == nil)
-			continue;
-		sdinitpart(unit);
-		partition(unit);
-		if(unit->npart > 0){	/* BUG */
-			if((unit->inquiry[0] & 0x1F) == 0x05)
-				cdmask |= (1<<i);
-			else
-				sdmask |= (1<<i);
-			m |= (1<<i);
-		}
-	}
-
-//notesdinfo();
-	_sdmask = m;
-	return m;
-}
-
-int
-cdinit(void)
-{
-	if(sdnunit == 0)
-		_sdinit();
-	return cdmask;
-}
-
-int
-sdinit(void)
-{
-	if(sdnunit == 0)
-		_sdinit();
-	return sdmask;
-}
-
-void
-sdinitdev(int i, char *s)
-{
-	SDunit *unit;
-
-	unit = sdindex2unit(i);
-	strcpy(s, unit->name);
-}
-
-void
-sdprintdevs(int i)
-{
-	char *s;
-	SDunit *unit;
-
-	unit = sdindex2unit(i);
-	for(i=0; i<unit->npart; i++){
-		s = unit->part[i].name;
-		if(strncmp(s, "dos", 3) == 0
-		|| strncmp(s, "9fat", 4) == 0
-		|| strncmp(s, "fs", 2) == 0)
-			print(" %s!%s", unit->name, s);
-	}
-}
-
-SDpart*
-sdfindpart(SDunit *unit, char *name)
-{
-	int i;
-
-	if(parttrace)
-		print("findpart %d %s %s\t\n", unit->npart, unit->name, name);
-	for(i=0; i<unit->npart; i++) {
-		if(parttrace)
-			print("%s...", unit->part[i].name);
-		if(strcmp(unit->part[i].name, name) == 0){
-			if(parttrace)
-				print("\n");
-			return &unit->part[i];
-		}
-	}
-	if(parttrace)
-		print("not found\n");
-	return nil;
-}
-
-typedef struct Scsicrud Scsicrud;
-struct Scsicrud {
-	Fs fs;
-	vlong offset;
-	SDunit *unit;
-	SDpart *part;
-};
-
-long
-sdread(Fs *vcrud, void *v, long n)
-{
-	Scsicrud *crud;
-	long x;
-
-	crud = (Scsicrud*)vcrud;
-	x = sdbio(crud->unit, crud->part, v, n, crud->offset);
-	if(x > 0)
-		crud->offset += x;
-	return x;
-}
-
-vlong
-sdseek(Fs *vcrud, vlong seek)
-{
-	((Scsicrud*)vcrud)->offset = seek;
-	return seek;
-}
-
-void*
-sdgetfspart(int i, char *s, int chatty)
-{
-	SDunit *unit;
-	SDpart *p;
-	Scsicrud *crud;
-
-	if(cdmask&(1<<i)){
-		if(strcmp(s, "cdboot") != 0)
-			return nil;
-	}else if(sdmask&(1<<i)){
-		if(strcmp(s, "cdboot") == 0)
-			return nil;
-	}
-
-	unit = sdindex2unit(i);
-	if((p = sdfindpart(unit, s)) == nil){
-		if(chatty)
-			print("unknown partition %s!%s\n", unit->name, s);
-		return nil;
-	}
-	if(p->crud == nil) {
-		crud = malloc(sizeof(Scsicrud));
-		crud->fs.dev = i;
-		crud->fs.diskread = sdread;
-		crud->fs.diskseek = sdseek;
-	//	crud->start = 0;
-		crud->unit = unit;
-		crud->part = p;
-		if(dosinit(&crud->fs) < 0 && dosinit(&crud->fs) < 0 && kfsinit(&crud->fs) < 0){
-			if(chatty)
-				print("partition %s!%s does not contain a DOS or KFS file system\n",
-					unit->name, s);
-			return nil;
-		}
-		p->crud = crud;
-	}
-	return p->crud;
-}
-
-/*
- * Leave partitions around for devsd to pick up.
- * (Needed by boot process; more extensive 
- * partitioning is done by termrc or cpurc).
- */
-void
-sdaddconf(int i)
-{
-	SDunit *unit;
-	SDpart *pp;
-
-	unit = sdindex2unit(i);
-	
-	/*
-	 * If there were no partitions (just data and partition), don't bother.
-	 */
-	if(unit->npart<= 1 || (unit->npart==2 && strcmp(unit->part[1].name, "partition")==0))
-		return;
-
-	addconf("%spart=", unit->name);
-	for(i=1, pp=&unit->part[i]; i<unit->npart; i++, pp++)	/* skip 0, which is "data" */
-		addconf("%s%s %lld %lld", i==1 ? "" : "/", pp->name,
-			pp->start, pp->end);
-	addconf("\n");
-}
-
-int
-sdboot(int dev, char *pname, Boot *b)
-{
-	char *file;
-	Fs *fs;
-
-	if((file = strchr(pname, '!')) == nil) {
-		print("syntax is sdC0!partition!file\n");
-		return -1;
-	}
-	*file++ = '\0';
-
-	fs = sdgetfspart(dev, pname, 1);
-	if(fs == nil)
-		return -1;
-
-	return fsboot(fs, file, b);
-}
-
-long
-sdbio(SDunit *unit, SDpart *pp, void* va, long len, vlong off)
-{
-	long l;
-	ulong bno, max, nb, offset;
-	static uchar *b;
-	char *a;
-	static ulong bsz;
-
-	a = va;
-memset(a, 0xDA, len);
-	qlock(&unit->ctl);
-	if(unit->changed){
-		qunlock(&unit->ctl);
-		return 0;
-	}
-
-	/*
-	 * Check the request is within bounds.
-	 * Removeable drives are locked throughout the I/O
-	 * in case the media changes unexpectedly.
-	 * Non-removeable drives are not locked during the I/O
-	 * to allow the hardware to optimise if it can; this is
-	 * a little fast and loose.
-	 * It's assumed that non-removable media parameters
-	 * (sectors, secsize) can't change once the drive has
-	 * been brought online.
-	 */
-	bno = (off/unit->secsize) + pp->start;
-	nb = ((off+len+unit->secsize-1)/unit->secsize) + pp->start - bno;
-	max = SDmaxio/unit->secsize;
-	if(nb > max)
-		nb = max;
-	if(bno+nb > pp->end)
-		nb = pp->end - bno;
-	if(bno >= pp->end || nb == 0){
-		qunlock(&unit->ctl);
-		return 0;
-	}
-	if(!(unit->inquiry[1] & 0x80))
-		qunlock(&unit->ctl);
-
-	if(bsz < nb*unit->secsize){
-		b = malloc(nb*unit->secsize);
-		bsz = nb*unit->secsize;
-	}
-//	b = sdmalloc(nb*unit->secsize);
-//	if(b == nil)
-//		return 0;
-
-	offset = off%unit->secsize;
-	if((l = unit->dev->ifc->bio(unit, 0, 0, b, nb, bno)) < 0) {
-//		sdfree(b);
-		return 0;
-	}
-
-	if(l < offset)
-		len = 0;
-	else if(len > l - offset)
-		len = l - offset;
-	if(len)
-		memmove(a, b+offset, len);
-//	sdfree(b);
-
-	if(unit->inquiry[1] & 0x80)
-		qunlock(&unit->ctl);
-
-	return len;
-}
-
-#ifdef DMA
-long
-sdrio(SDreq *r, void* a, long n)
-{
-	if(n >= SDmaxio || n < 0)
-		return 0;
-
-	r->data = nil;
-	if(n){
-		if((r->data = malloc(n)) == nil)
-			return 0;
-		if(r->write)
-			memmove(r->data, a, n);
-	}
-	r->dlen = n;
-
-	if(r->unit->dev->ifc->rio(r) != SDok){
-// cgascreenputs("1", 1);
-		if(r->data != nil){
-			sdfree(r->data);
-			r->data = nil;
-		}
-		return 0;
-	}
-// cgascreenputs("2", 1);
-
-	if(!r->write && r->rlen > 0)
-		memmove(a, r->data, r->rlen);
-// cgascreenputs("3", 1);
-	if(r->data != nil){
-		sdfree(r->data);
-		r->data = nil;
-	}
-
-// cgascreenputs("4", 1);
-	return r->rlen;
-}
-#endif /* DMA */
-
-void
-sleep(void*, int (*fn)(void*), void *v)
-{
-	int x;
-	x = spllo();
-	while(!fn(v))
-		;
-	splx(x);
-	return;
-}
-
-void
-tsleep(void*, int (*fn)(void*), void *v, int msec)
-{
-	int x;
-	ulong start;
-
-	x = spllo();
-	for(start = m->ticks; TK2MS(m->ticks - start) < msec
-		&& !fn(v); )
-		;
-	splx(x);
-	return;
-}
-
-void*
-sdmalloc(void *p, ulong sz)
-{
-	if(p != nil) {
-		memset(p, 0, sz);
-		return p;
-	}
-	return malloc(sz);
-}
--- a/os/boot/pc/dma.c
+++ /dev/null
@@ -1,245 +1,0 @@
-#include	"u.h"
-#include	"lib.h"
-#include	"mem.h"
-#include	"dat.h"
-#include	"fns.h"
-
-typedef struct DMAport	DMAport;
-typedef struct DMA	DMA;
-typedef struct DMAxfer	DMAxfer;
-
-enum
-{
-	/*
-	 *  the byte registers for DMA0 are all one byte apart
-	 */
-	Dma0=		0x00,
-	Dma0status=	Dma0+0x8,	/* status port */
-	Dma0reset=	Dma0+0xD,	/* reset port */
-
-	/*
-	 *  the byte registers for DMA1 are all two bytes apart (why?)
-	 */
-	Dma1=		0xC0,
-	Dma1status=	Dma1+2*0x8,	/* status port */
-	Dma1reset=	Dma1+2*0xD,	/* reset port */
-};
-
-/*
- *  state of a dma transfer
- */
-struct DMAxfer
-{
-	ulong	bpa;		/* bounce buffer physical address */
-	void*	bva;		/* bounce buffer virtual address */
-	void*	va;		/* virtual address destination/src */
-	long	len;		/* bytes to be transferred */
-	int	isread;
-};
-
-/*
- *  the dma controllers.  the first half of this structure specifies
- *  the I/O ports used by the DMA controllers.
- */
-struct DMAport
-{
-	uchar	addr[4];	/* current address (4 channels) */
-	uchar	count[4];	/* current count (4 channels) */
-	uchar	page[4];	/* page registers (4 channels) */
-	uchar	cmd;		/* command status register */
-	uchar	req;		/* request registers */
-	uchar	sbm;		/* single bit mask register */
-	uchar	mode;		/* mode register */
-	uchar	cbp;		/* clear byte pointer */
-	uchar	mc;		/* master clear */
-	uchar	cmask;		/* clear mask register */
-	uchar	wam;		/* write all mask register bit */
-};
-
-struct DMA
-{
-	DMAport;
-	int	shift;
-	Lock;
-	DMAxfer	x[4];
-};
-
-DMA dma[2] = {
-	{ 0x00, 0x02, 0x04, 0x06,
-	  0x01, 0x03, 0x05, 0x07,
-	  0x87, 0x83, 0x81, 0x82,
-	  0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
-	 0 },
-
-	{ 0xc0, 0xc4, 0xc8, 0xcc,
-	  0xc2, 0xc6, 0xca, 0xce,
-	  0x8f, 0x8b, 0x89, 0x8a,
-	  0xd0, 0xd2, 0xd4, 0xd6, 0xd8, 0xda, 0xdc, 0xde,
-	 1 },
-};
-
-/*
- *  DMA must be in the first 16MB.  This gets called early by the
- *  initialisation routines of any devices which require DMA to ensure
- *  the allocated bounce buffers are below the 16MB limit.
- */
-void
-dmainit(int chan)
-{
-	DMA *dp;
-	DMAxfer *xp;
-	ulong v;
-	static int once;
-
-	if(once == 0){
-//		if(ioalloc(0x00, 0x10, 0, "dma") < 0
-//		|| ioalloc(0x80, 0x10, 0, "dma") < 0
-//		|| ioalloc(0xd0, 0x10, 0, "dma") < 0)
-//			panic("dmainit");
-		outb(dma[0].mc, 0);
-		outb(dma[1].mc, 0);
-		outb(dma[0].cmask, 0);
-		outb(dma[1].cmask, 0);
-		outb(dma[1].mode, 0xC0);
-		once = 1;
-	}
-
-	dp = &dma[(chan>>2)&1];
-	chan = chan & 3;
-	xp = &dp->x[chan];
-	if(xp->bva != nil)
-		return;
-
-	v = (ulong)xalloc(BY2PG+BY2PG);
-	if(v == 0 || PADDR(v) >= 16*MB){
-		print("dmainit: chan %d: 0x%luX out of range\n", chan, v);
-		xfree((void*)v);
-		v = 0;
-	}
-	xp->bva = (void*)ROUND(v, BY2PG);
-	xp->bpa = PADDR(xp->bva);
-	xp->len = 0;
-	xp->isread = 0;
-}
-
-/*
- *  setup a dma transfer.  if the destination is not in kernel
- *  memory, allocate a page for the transfer.
- *
- *  we assume BIOS has set up the command register before we
- *  are booted.
- *
- *  return the updated transfer length (we can't transfer across 64k
- *  boundaries)
- */
-long
-dmasetup(int chan, void *va, long len, int isread)
-{
-	DMA *dp;
-	ulong pa;
-	uchar mode;
-	DMAxfer *xp;
-
-	dp = &dma[(chan>>2)&1];
-	chan = chan & 3;
-	xp = &dp->x[chan];
-
-	/*
-	 *  if this isn't kernel memory or crossing 64k boundary or above 16 meg
-	 *  use the allocated low memory page.
-	 */
-	pa = PADDR(va);
-	if((((ulong)va)&0xF0000000) != KZERO
-	|| (pa&0xFFFF0000) != ((pa+len)&0xFFFF0000)
-	|| pa > 16*MB) {
-		if(xp->bva == nil)
-			return -1;
-		if(len > BY2PG)
-			len = BY2PG;
-		if(!isread)
-			memmove(xp->bva, va, len);
-		xp->va = va;
-		xp->len = len;
-		xp->isread = isread;
-		pa = xp->bpa;
-	}
-	else
-		xp->len = 0;
-
-	/*
-	 * this setup must be atomic
-	 */
-	ilock(dp);
-	mode = (isread ? 0x44 : 0x48) | chan;
-	outb(dp->mode, mode);	/* single mode dma (give CPU a chance at mem) */
-	outb(dp->page[chan], pa>>16);
-	outb(dp->cbp, 0);		/* set count & address to their first byte */
-	outb(dp->addr[chan], pa>>dp->shift);		/* set address */
-	outb(dp->addr[chan], pa>>(8+dp->shift));
-	outb(dp->count[chan], (len>>dp->shift)-1);		/* set count */
-	outb(dp->count[chan], ((len>>dp->shift)-1)>>8);
-	outb(dp->sbm, chan);		/* enable the channel */
-	iunlock(dp);
-
-	return len;
-}
-
-int
-dmadone(int chan)
-{
-	DMA *dp;
-
-	dp = &dma[(chan>>2)&1];
-	chan = chan & 3;
-
-	return inb(dp->cmd) & (1<<chan);
-}
-
-/*
- *  this must be called after a dma has been completed.
- *
- *  if a page has been allocated for the dma,
- *  copy the data into the actual destination
- *  and free the page.
- */
-void
-dmaend(int chan)
-{
-	DMA *dp;
-	DMAxfer *xp;
-
-	dp = &dma[(chan>>2)&1];
-	chan = chan & 3;
-
-	/*
-	 *  disable the channel
-	 */
-	ilock(dp);
-	outb(dp->sbm, 4|chan);
-	iunlock(dp);
-
-	xp = &dp->x[chan];
-	if(xp->len == 0 || !xp->isread)
-		return;
-
-	/*
-	 *  copy out of temporary page
-	 */
-	memmove(xp->va, xp->bva, xp->len);
-	xp->len = 0;
-}
-
-/*
-int
-dmacount(int chan)
-{
-	int     retval;
-	DMA     *dp;
- 
-	dp = &dma[(chan>>2)&1];
-	outb(dp->cbp, 0);
-	retval = inb(dp->count[chan]);
-	retval |= inb(dp->count[chan]) << 8;
-	return((retval<<dp->shift)+1);
-}
- */
--- a/os/boot/pc/dosboot.c
+++ /dev/null
@@ -1,582 +1,0 @@
-#include	"u.h"
-#include	"lib.h"
-#include	"mem.h"
-#include	"dat.h"
-#include	"fns.h"
-#include	"fs.h"
-
-struct Dosboot{
-	uchar	magic[3];
-	uchar	version[8];
-	uchar	sectsize[2];
-	uchar	clustsize;
-	uchar	nresrv[2];
-	uchar	nfats;
-	uchar	rootsize[2];
-	uchar	volsize[2];
-	uchar	mediadesc;
-	uchar	fatsize[2];
-	uchar	trksize[2];
-	uchar	nheads[2];
-	uchar	nhidden[4];
-	uchar	bigvolsize[4];
-/* fat 32 */
-	uchar	bigfatsize[4];
-	uchar	extflags[2];
-	uchar	fsversion[2];
-	uchar	rootdirstartclust[4];
-	uchar	fsinfosect[2];
-	uchar	backupbootsect[2];
-/* ???
-	uchar	driveno;
-	uchar	reserved0;
-	uchar	bootsig;
-	uchar	volid[4];
-	uchar	label[11];
-	uchar	reserved1[8];
-*/
-};
-
-struct Dosdir{
-	uchar	name[8];
-	uchar	ext[3];
-	uchar	attr;
-	uchar	lowercase;
-	uchar	hundredth;
-	uchar	ctime[2];
-	uchar	cdate[2];
-	uchar	adate[2];
-	uchar	highstart[2];
-	uchar	mtime[2];
-	uchar	mdate[2];
-	uchar	start[2];
-	uchar	length[4];
-};
-
-#define	DOSRONLY	0x01
-#define	DOSHIDDEN	0x02
-#define	DOSSYSTEM	0x04
-#define	DOSVLABEL	0x08
-#define	DOSDIR	0x10
-#define	DOSARCH	0x20
-
-/*
- *  predeclared
- */
-static void	bootdump(Dosboot*);
-static void	setname(Dosfile*, char*);
-
-/*
- *  debugging
- */
-#define chatty	0
-#define chat	if(chatty)print
-
-/*
- *  block io buffers
- */
-enum
-{
-	Nbio=	16,
-};
-typedef struct	Clustbuf	Clustbuf;
-struct Clustbuf
-{
-	int	age;
-	long	sector;
-	uchar	*iobuf;
-	Dos	*dos;
-	int	size;
-};
-Clustbuf	bio[Nbio];
-
-/*
- *  get an io block from an io buffer
- */
-Clustbuf*
-getclust(Dos *dos, long sector)
-{
-	Fs *fs;
-	Clustbuf *p, *oldest;
-	int size;
-
-	chat("getclust @ %ld\n", sector);
-
-	/*
-	 *  if we have it, just return it
-	 */
-	for(p = bio; p < &bio[Nbio]; p++){
-		if(sector == p->sector && dos == p->dos){
-			p->age = m->ticks;
-			chat("getclust %ld in cache\n", sector);
-			return p;
-		}
-	}
-
-	/*
-	 *  otherwise, reuse the oldest entry
-	 */
-	oldest = bio;
-	for(p = &bio[1]; p < &bio[Nbio]; p++){
-		if(p->age <= oldest->age)
-			oldest = p;
-	}
-	p = oldest;
-
-	/*
-	 *  make sure the buffer is big enough
-	 */
-	size = dos->clustsize*dos->sectsize;
-	if(p->iobuf==0 || p->size < size)
-		p->iobuf = ialloc(size, 0);
-	p->size = size;
-
-	/*
-	 *  read in the cluster
-	 */
-	fs = (Fs*)dos;
-	chat("getclust addr %lud %p %p %p\n", (ulong)((sector+dos->start)*(vlong)dos->sectsize),
-		fs, fs->diskseek, fs->diskread);
-	if(fs->diskseek(fs, (sector+dos->start)*(vlong)dos->sectsize) < 0){
-		chat("can't seek block\n");
-		return 0;
-	}
-	if(fs->diskread(fs, p->iobuf, size) != size){
-		chat("can't read block\n");
-		return 0;
-	}
-
-	p->age = m->ticks;
-	p->dos = dos;
-	p->sector = sector;
-	chat("getclust %ld read\n", sector);
-	return p;
-}
-
-/*
- *  walk the fat one level ( n is a current cluster number ).
- *  return the new cluster number or -1 if no more.
- */
-static long
-fatwalk(Dos *dos, int n)
-{
-	ulong k, sect;
-	Clustbuf *p;
-	int o;
-
-	chat("fatwalk %d\n", n);
-
-	if(n < 2 || n >= dos->fatclusters)
-		return -1;
-
-	switch(dos->fatbits){
-	case 12:
-		k = (3*n)/2; break;
-	case 16:
-		k = 2*n; break;
-	case 32:
-		k = 4*n; break;
-	default:
-		return -1;
-	}
-	if(k >= dos->fatsize*dos->sectsize)
-		panic("getfat");
-
-	sect = (k/(dos->sectsize*dos->clustsize))*dos->clustsize + dos->fataddr;
-	o = k%(dos->sectsize*dos->clustsize);
-	p = getclust(dos, sect);
-	k = p->iobuf[o++];
-	if(o >= dos->sectsize*dos->clustsize){
-		p = getclust(dos, sect+dos->clustsize);
-		o = 0;
-	}
-	k |= p->iobuf[o++]<<8;
-	if(dos->fatbits == 12){
-		if(n&1)
-			k >>= 4;
-		else
-			k &= 0xfff;
-		if(k >= 0xff8)
-			k = -1;
-	}
-	else if (dos->fatbits == 32){
-		if(o >= dos->sectsize*dos->clustsize){
-			p = getclust(dos, sect+dos->clustsize);
-			o = 0;
-		}
-		k |= p->iobuf[o++]<<16;
-		k |= p->iobuf[o]<<24;
-		if (k >= 0xfffffff8)
-			k = -1;
-	}
-	else
-		k = k < 0xfff8 ? k : -1;
-	chat("fatwalk %d -> %lud\n", n, k);
-	return k;
-}
-
-/*
- *  map a file's logical cluster address to a physical sector address
- */
-static long
-fileaddr(Dosfile *fp, long ltarget)
-{
-	Dos *dos = fp->dos;
-	long l;
-	long p;
-
-	chat("fileaddr %8.8s %ld\n", fp->name, ltarget);
-	/*
-	 *  root directory is contiguous and easy (unless FAT32)
-	 */
-	if(fp->pstart == 0 && dos->rootsize != 0) {
-		if(ltarget*dos->sectsize*dos->clustsize >= dos->rootsize*sizeof(Dosdir))
-			return -1;
-		l = dos->rootaddr + ltarget*dos->clustsize;
-		chat("fileaddr %ld -> %ld\n", ltarget, l);
-		return l;
-	}
-
-	/*
-	 *  anything else requires a walk through the fat
-	 */
-	if(ltarget >= fp->lcurrent && fp->pcurrent){
-		/* start at the currrent point */
-		l = fp->lcurrent;
-		p = fp->pcurrent;
-	} else {
-		/* go back to the beginning */
-		l = 0;
-		p = fp->pstart;
-	}
-	while(l != ltarget){
-		/* walk the fat */
-		p = fatwalk(dos, p);
-		if(p < 0)
-			return -1;
-		l++;
-	}
-	fp->lcurrent = l;
-	fp->pcurrent = p;
-
-	/*
-	 *  clusters start at 2 instead of 0 (why? - presotto)
-	 */
-	l =  dos->dataaddr + (p-2)*dos->clustsize;
-	chat("fileaddr %ld -> %ld\n", ltarget, l);
-	return l;
-}
-
-/*
- *  read from a dos file
- */
-long
-dosread(Dosfile *fp, void *a, long n)
-{
-	long addr;
-	long rv;
-	int i;
-	int off;
-	Clustbuf *p;
-	uchar *from, *to;
-
-	if((fp->attr & DOSDIR) == 0){
-		if(fp->offset >= fp->length)
-			return 0;
-		if(fp->offset+n > fp->length)
-			n = fp->length - fp->offset;
-	}
-
-	to = a;
-	for(rv = 0; rv < n; rv+=i){
-		/*
-		 *  read the cluster
-		 */
-		addr = fileaddr(fp, fp->offset/fp->dos->clustbytes);
-		if(addr < 0)
-			return -1;
-		p = getclust(fp->dos, addr);
-		if(p == 0)
-			return -1;
-
-		/*
-		 *  copy the bytes we need
-		 */
-		off = fp->offset % fp->dos->clustbytes;
-		from = &p->iobuf[off];
-		i = n - rv;
-		if(i > fp->dos->clustbytes - off)
-			i = fp->dos->clustbytes - off;
-		memmove(to, from, i);
-		to += i;
-		fp->offset += i;
-	}
-
-	return rv;
-}
-
-/*
- *  walk a directory returns
- * 	-1 if something went wrong
- *	 0 if not found
- *	 1 if found
- */
-int
-doswalk(File *f, char *name)
-{
-	Dosdir d;
-	long n;
-	Dosfile *file;
-
-	chat("doswalk %s\n", name);
-
-	file = &f->dos;
-
-	if((file->attr & DOSDIR) == 0){
-		chat("walking non-directory!\n");
-		return -1;
-	}
-
-	setname(file, name);
-
-	file->offset = 0;	/* start at the beginning */
-	while((n = dosread(file, &d, sizeof(d))) == sizeof(d)){
-		chat("comparing to %8.8s.%3.3s\n", (char*)d.name, (char*)d.ext);
-		if(memcmp(file->name, d.name, sizeof(d.name)) != 0)
-			continue;
-		if(memcmp(file->ext, d.ext, sizeof(d.ext)) != 0)
-			continue;
-		if(d.attr & DOSVLABEL){
-			chat("%8.8s.%3.3s is a LABEL\n", (char*)d.name, (char*)d.ext);
-			continue;
-		}
-		file->attr = d.attr;
-		file->pstart = GSHORT(d.start);
-		if (file->dos->fatbits == 32)
-			file->pstart |= GSHORT(d.highstart) << 16;
-		file->length = GLONG(d.length);
-		file->pcurrent = 0;
-		file->lcurrent = 0;
-		file->offset = 0;
-		return 1;
-	}
-	return n >= 0 ? 0 : -1;
-}
-
-/*
- *  instructions that boot blocks can start with
- */
-#define	JMPSHORT	0xeb
-#define JMPNEAR		0xe9
-
-/*
- *  read in a segment
- */
-long
-dosreadseg(File *f, void *va, long len)
-{
-	char *a;
-	long n, sofar;
-	Dosfile *fp;
-
-	fp = &f->dos;
-	a = va;
-	for(sofar = 0; sofar < len; sofar += n){
-		n = 8*1024;
-		if(len - sofar < n)
-			n = len - sofar;
-		n = dosread(fp, a + sofar, n);
-		if(n <= 0)
-			break;
-		print(".");
-	}
-	return sofar;
-}
-
-int
-dosinit(Fs *fs)
-{
-	Clustbuf *p;
-	Dosboot *b;
-	int i;
-	Dos *dos;
-	Dosfile *root;
-
-chat("dosinit0 %p %p %p\n", fs, fs->diskseek, fs->diskread);
-
-	dos = &fs->dos;
-	/* defaults till we know better */
-	dos->sectsize = 512;
-	dos->clustsize = 1;
-
-	/* get first sector */
-	p = getclust(dos, 0);
-	if(p == 0){
-		chat("can't read boot block\n");
-		return -1;
-	}
-
-chat("dosinit0a\n");
-
-	p->dos = 0;
-	b = (Dosboot *)p->iobuf;
-	if(b->magic[0] != JMPNEAR && (b->magic[0] != JMPSHORT || b->magic[2] != 0x90)){
-		chat("no dos file system %x %x %x %x\n",
-			b->magic[0], b->magic[1], b->magic[2], b->magic[3]);
-		return -1;
-	}
-
-	if(chatty)
-		bootdump(b);
-
-	if(b->clustsize == 0) {
-unreasonable:
-		if(chatty){
-			print("unreasonable FAT BPB: ");
-			for(i=0; i<3+8+2+1; i++)
-				print(" %.2ux", p->iobuf[i]);
-			print("\n");
-		}
-		return -1;
-	}
-
-chat("dosinit1\n");
-
-	/*
-	 * Determine the systems' wondrous properties.
-	 * There are heuristics here, but there's no real way
-	 * of knowing if this is a reasonable FAT.
-	 */
-	dos->fatbits = 0;
-	dos->sectsize = GSHORT(b->sectsize);
-	if(dos->sectsize & 0xFF)
-		goto unreasonable;
-	dos->clustsize = b->clustsize;
-	dos->clustbytes = dos->sectsize*dos->clustsize;
-	dos->nresrv = GSHORT(b->nresrv);
-	dos->nfats = b->nfats;
-	dos->fatsize = GSHORT(b->fatsize);
-	dos->rootsize = GSHORT(b->rootsize);
-	dos->volsize = GSHORT(b->volsize);
-	if(dos->volsize == 0)
-		dos->volsize = GLONG(b->bigvolsize);
-	dos->mediadesc = b->mediadesc;
-	if(dos->fatsize == 0) {
-		chat("fat32\n");
-		dos->rootsize = 0;
-		dos->fatsize = GLONG(b->bigfatsize);
-		dos->fatbits = 32;
-	}
-	dos->fataddr = dos->nresrv;
-	if (dos->rootsize == 0) {
-		dos->rootaddr = 0;
-		dos->rootclust = GLONG(b->rootdirstartclust);
-		dos->dataaddr = dos->fataddr + dos->nfats*dos->fatsize;
-	} else {
-		dos->rootaddr = dos->fataddr + dos->nfats*dos->fatsize;
-		i = dos->rootsize*sizeof(Dosdir) + dos->sectsize - 1;
-		i = i/dos->sectsize;
-		dos->dataaddr = dos->rootaddr + i;
-	}
-	dos->fatclusters = 2+(dos->volsize - dos->dataaddr)/dos->clustsize;
-	if(dos->fatbits != 32) {
-		if(dos->fatclusters < 4087)
-			dos->fatbits = 12;
-		else
-			dos->fatbits = 16;
-	}
-	dos->freeptr = 2;
-
-	if(dos->clustbytes < 512 || dos->clustbytes > 64*1024)
-		goto unreasonable;
-
-chat("dosinit2\n");
-
-	/*
-	 *  set up the root
-	 */
-
-	fs->root.fs = fs;
-	root = &fs->root.dos;
-	root->dos = dos;
-	root->pstart = dos->rootsize == 0 ? dos->rootclust : 0;
-	root->pcurrent = root->lcurrent = 0;
-	root->offset = 0;
-	root->attr = DOSDIR;
-	root->length = dos->rootsize*sizeof(Dosdir);
-
-chat("dosinit3\n");
-
-	fs->read = dosreadseg;
-	fs->walk = doswalk;
-	return 0;
-}
-
-static void
-bootdump(Dosboot *b)
-{
-	if(chatty == 0)
-		return;
-	print("magic: 0x%2.2x 0x%2.2x 0x%2.2x ",
-		b->magic[0], b->magic[1], b->magic[2]);
-	print("version: \"%8.8s\"\n", (char*)b->version);
-	print("sectsize: %d ", GSHORT(b->sectsize));
-	print("allocsize: %d ", b->clustsize);
-	print("nresrv: %d ", GSHORT(b->nresrv));
-	print("nfats: %d\n", b->nfats);
-	print("rootsize: %d ", GSHORT(b->rootsize));
-	print("volsize: %d ", GSHORT(b->volsize));
-	print("mediadesc: 0x%2.2x\n", b->mediadesc);
-	print("fatsize: %d ", GSHORT(b->fatsize));
-	print("trksize: %d ", GSHORT(b->trksize));
-	print("nheads: %d ", GSHORT(b->nheads));
-	print("nhidden: %d ", GLONG(b->nhidden));
-	print("bigvolsize: %d\n", GLONG(b->bigvolsize));
-/*
-	print("driveno: %d\n", b->driveno);
-	print("reserved0: 0x%2.2x\n", b->reserved0);
-	print("bootsig: 0x%2.2x\n", b->bootsig);
-	print("volid: 0x%8.8x\n", GLONG(b->volid));
-	print("label: \"%11.11s\"\n", b->label);
-*/
-}
-
-
-/*
- *  set up a dos file name
- */
-static void
-setname(Dosfile *fp, char *from)
-{
-	char *to;
-
-	to = fp->name;
-	for(; *from && to-fp->name < 8; from++, to++){
-		if(*from == '.'){
-			from++;
-			break;
-		}
-		if(*from >= 'a' && *from <= 'z')
-			*to = *from + 'A' - 'a';
-		else
-			*to = *from;
-	}
-	while(to - fp->name < 8)
-		*to++ = ' ';
-	
-	/* from might be 12345678.123: don't save the '.' in ext */
-	if(*from == '.')
-		from++;
-
-	to = fp->ext;
-	for(; *from && to-fp->ext < 3; from++, to++){
-		if(*from >= 'a' && *from <= 'z')
-			*to = *from + 'A' - 'a';
-		else
-			*to = *from;
-	}
-	while(to-fp->ext < 3)
-		*to++ = ' ';
-
-	chat("name is %8.8s.%3.3s\n", fp->name, fp->ext);
-}
--- a/os/boot/pc/dosfs.h
+++ /dev/null
@@ -1,62 +1,0 @@
-typedef struct Dosboot	Dosboot;
-typedef struct Dos	Dos;
-typedef struct Dosdir	Dosdir;
-typedef struct Dosfile	Dosfile;
-typedef struct Dospart	Dospart;
-
-struct Dospart
-{
-	uchar flag;		/* active flag */
-	uchar shead;		/* starting head */
-	uchar scs[2];		/* starting cylinder/sector */
-	uchar type;		/* partition type */
-	uchar ehead;		/* ending head */
-	uchar ecs[2];		/* ending cylinder/sector */
-	uchar start[4];		/* starting sector */
-	uchar len[4];		/* length in sectors */
-};
-
-#define FAT12	0x01
-#define FAT16	0x04
-#define EXTEND	0x05
-#define FATHUGE	0x06
-#define FAT32	0x0b
-#define FAT32X	0x0c
-#define EXTHUGE	0x0f
-#define DMDDO	0x54
-#define PLAN9	0x39
-#define LEXTEND 0x85
-
-struct Dosfile{
-	Dos	*dos;		/* owning dos file system */
-	char	name[8];
-	char	ext[3];
-	uchar	attr;
-	long	length;
-	long	pstart;		/* physical start cluster address */
-	long	pcurrent;	/* physical current cluster address */
-	long	lcurrent;	/* logical current cluster address */
-	long	offset;
-};
-
-struct Dos{
-	long	start;		/* start of file system */
-	int	sectsize;	/* in bytes */
-	int	clustsize;	/* in sectors */
-	int	clustbytes;	/* in bytes */
-	int	nresrv;		/* sectors */
-	int	nfats;		/* usually 2 */
-	int	rootsize;	/* number of entries */
-	int	volsize;	/* in sectors */
-	int	mediadesc;
-	int	fatsize;	/* in sectors */
-	int	fatclusters;
-	int	fatbits;	/* 12 or 16 */
-	long	fataddr;	/* sector number */
-	long	rootaddr;
-	long	rootclust;
-	long	dataaddr;
-	long	freeptr;
-};
-
-extern int	dosinit(Fs*);
--- a/os/boot/pc/eipfmt.c
+++ /dev/null
@@ -1,145 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "ip.h"
-
-
-enum 
-{
-	IPaddrlen=	16,
-	IPv4addrlen=	4,
-	IPv4off=	12,
-	IPllen=		4,
-};
-extern	int	fmtstrcpy(Fmt*, char*);
-
-
-/*
- *  prefix of all v4 addresses
- */
-uchar v4prefix[IPaddrlen] = {
-	0, 0, 0, 0,
-	0, 0, 0, 0,
-	0, 0, 0xff, 0xff,
-	0, 0, 0, 0
-};
-
-enum
-{
-	Isprefix= 16,
-};
-
-uchar prefixvals[256] =
-{
-[0x00] 0 | Isprefix,
-[0x80] 1 | Isprefix,
-[0xC0] 2 | Isprefix,
-[0xE0] 3 | Isprefix,
-[0xF0] 4 | Isprefix,
-[0xF8] 5 | Isprefix,
-[0xFC] 6 | Isprefix,
-[0xFE] 7 | Isprefix,
-[0xFF] 8 | Isprefix,
-};
-
-void
-hnputl(void *p, uint v)
-{
-	uchar *a;
-
-	a = p;
-	a[0] = v>>24;
-	a[1] = v>>16;
-	a[2] = v>>8;
-	a[3] = v;
-}
-
-int
-eipfmt(Fmt *f)
-{
-	char buf[5*8];
-	static char *efmt = "%.2lux%.2lux%.2lux%.2lux%.2lux%.2lux";
-	static char *ifmt = "%d.%d.%d.%d";
-	uchar *p, ip[16];
-	ulong *lp;
-	ushort s;
-	int i, j, n, eln, eli;
-
-	switch(f->r) {
-	case 'E':		/* Ethernet address */
-		p = va_arg(f->args, uchar*);
-		snprint(buf, sizeof buf, efmt, p[0], p[1], p[2], p[3], p[4], p[5]);
-		return fmtstrcpy(f, buf);
-
-	case 'I':		/* Ip address */
-		p = va_arg(f->args, uchar*);
-common:
-		if(memcmp(p, v4prefix, 12) == 0){
-			snprint(buf, sizeof buf, ifmt, p[12], p[13], p[14], p[15]);
-			return fmtstrcpy(f, buf);
-		}
-
-		/* find longest elision */
-		eln = eli = -1;
-		for(i = 0; i < 16; i += 2){
-			for(j = i; j < 16; j += 2)
-				if(p[j] != 0 || p[j+1] != 0)
-					break;
-			if(j > i && j - i > eln){
-				eli = i;
-				eln = j - i;
-			}
-		}
-
-		/* print with possible elision */
-		n = 0;
-		for(i = 0; i < 16; i += 2){
-			if(i == eli){
-				n += sprint(buf+n, "::");
-				i += eln;
-				if(i >= 16)
-					break;
-			} else if(i != 0)
-				n += sprint(buf+n, ":");
-			s = (p[i]<<8) + p[i+1];
-			n += sprint(buf+n, "%ux", s);
-		}
-		return fmtstrcpy(f, buf);
-
-	case 'i':		/* v6 address as 4 longs */
-		lp = va_arg(f->args, ulong*);
-		for(i = 0; i < 4; i++)
-			hnputl(ip+4*i, *lp++);
-		p = ip;
-		goto common;
-
-	case 'V':		/* v4 ip address */
-		p = va_arg(f->args, uchar*);
-		snprint(buf, sizeof buf, ifmt, p[0], p[1], p[2], p[3]);
-		return fmtstrcpy(f, buf);
-
-	case 'M':		/* ip mask */
-		p = va_arg(f->args, uchar*);
-
-		/* look for a prefix mask */
-		for(i = 0; i < 16; i++)
-			if(p[i] != 0xff)
-				break;
-		if(i < 16){
-			if((prefixvals[p[i]] & Isprefix) == 0)
-				goto common;
-			for(j = i+1; j < 16; j++)
-				if(p[j] != 0)
-					goto common;
-			n = 8*i + (prefixvals[p[i]] & ~Isprefix);
-		} else
-			n = 8*16;
-
-		/* got one, use /xx format */
-		snprint(buf, sizeof buf, "/%d", n);
-		return fmtstrcpy(f, buf);
-	}
-	return fmtstrcpy(f, "(eipfmt)");
-}
--- a/os/boot/pc/error.h
+++ /dev/null
@@ -1,58 +1,0 @@
-extern char Enoerror[];		/* no error */
-extern char Emount[];		/* inconsistent mount */
-extern char Eunmount[];		/* not mounted */
-extern char Eunion[];		/* not in union */
-extern char Emountrpc[];	/* mount rpc error */
-extern char Eshutdown[];	/* mounted device shut down */
-extern char Enocreate[];	/* mounted directory forbids creation */
-extern char Enonexist[];	/* file does not exist */
-extern char Eexist[];		/* file already exists */
-extern char Ebadsharp[];	/* unknown device in # filename */
-extern char Enotdir[];		/* not a directory */
-extern char Eisdir[];		/* file is a directory */
-extern char Ebadchar[];		/* bad character in file name */
-extern char Efilename[];	/* file name syntax */
-extern char Eperm[];		/* permission denied */
-extern char Ebadusefd[];	/* inappropriate use of fd */
-extern char Ebadarg[];		/* bad arg in system call */
-extern char Einuse[];		/* device or object already in use */
-extern char Eio[];		/* i/o error */
-extern char Etoobig[];		/* read or write too large */
-extern char Etoosmall[];	/* read or write too small */
-extern char Enetaddr[];		/* bad network address */
-extern char Emsgsize[];		/* message is too big for protocol */
-extern char Enetbusy[];		/* network device is busy or allocated */
-extern char Enoproto[];		/* network protocol not supported */
-extern char Enoport[];		/* network port not available */
-extern char Enoifc[];		/* bad interface or no free interface slots */
-extern char Enolisten[];	/* not announced */
-extern char Ehungup[];		/* write to hungup channel */
-extern char Ebadctl[];		/* bad process or channel control request */
-extern char Enodev[];		/* no free devices */
-extern char Enoenv[];		/* no free environment resources */
-extern char Emuxshutdown[];	/* mux server shut down */
-extern char Emuxbusy[];		/* all mux channels busy */
-extern char Emuxmsg[];		/* bad mux message format or mismatch */
-extern char Eprocdied[];	/* process exited */
-extern char Enochild[];		/* no living children */
-extern char Eioload[];		/* i/o error in demand load */
-extern char Enovmem[];		/* virtual memory allocation failed */
-extern char Ebadld[];		/* illegal line discipline */
-extern char Ebadfd[];		/* fd out of range or not open */
-extern char Eisstream[];	/* seek on a stream */
-extern char Ebadexec[];		/* exec header invalid */
-extern char Etimedout[];	/* connection timed out */
-extern char Econrefused[];	/* connection refused */
-extern char Enetunreach[];	/* network unreachable */
-extern char Eintr[];		/* interrupted */
-extern char Eneedservice[];	/* service required for tcp/udp/il calls */
-extern char Enomem[];		/* kernel allocate failed */
-extern char Enoswap[];		/* swap space full */
-extern char Esfnotcached[];	/* subfont not cached */
-extern char Esoverlap[];	/* segments overlap */
-extern char Emouseset[];	/* mouse type already set */
-extern char Erecover[];		/* failed to recover fd */
-extern char Eshort[];		/* i/o count too small */
-extern char Egreg[];		/* ken scheduled it */
-extern char Ebadspec[];		/* bad attach specifier */
-extern char Enoreg[];		/* process has no saved registers */
--- a/os/boot/pc/ether.c
+++ /dev/null
@@ -1,291 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-#include "ip.h"
-
-#include "etherif.h"
-
-static Ether ether[MaxEther];
-
-extern int ether2114xreset(Ether*);
-extern int elnk3reset(Ether*);
-extern int i82557reset(Ether*);
-extern int igbepnp(Ether *);
-extern int i82563pnp(Ether *);
-extern int elnk3reset(Ether*);
-extern int ether589reset(Ether*);
-extern int ne2000reset(Ether*);
-extern int wd8003reset(Ether*);
-extern int ec2treset(Ether*);
-extern int amd79c970reset(Ether*);
-extern int rtl8139pnp(Ether*);
-extern int rtl8169pnp(Ether*);
-extern int ether83815reset(Ether*);
-extern int rhinepnp(Ether*);
-extern int ga620pnp(Ether*);
-extern int dp83820pnp(Ether*);
-
-struct {
-	char	*type;
-	int	(*reset)(Ether*);
-	int	noprobe;
-} ethercards[] = {
-	{ "21140", ether2114xreset, 0, },
-	{ "2114x", ether2114xreset, 0, },
-	{ "i82557", i82557reset, 0, },
-	{ "igbe",  igbepnp, 0, },
-	{ "i82563",i82563pnp, 0, },
-	{ "igbepcie",i82563pnp, 0, },
-	{ "elnk3", elnk3reset, 0, },
-	{ "3C509", elnk3reset, 0, },
-	{ "3C575", elnk3reset, 0, },
-	{ "3C589", ether589reset, 1, },
-	{ "3C562", ether589reset, 1, },
-	{ "589E", ether589reset, 1, },
-	{ "NE2000", ne2000reset, 0, },
-	{ "WD8003", wd8003reset, 1, },
-	{ "EC2T", ec2treset, 0, },
-	{ "AMD79C970", amd79c970reset, 0, },
-	{ "RTL8139", rtl8139pnp, 0, },
-	{ "RTL8169", rtl8169pnp, 0, },
-	{ "83815", ether83815reset, 0, },
-	{ "rhine", rhinepnp, 0, },
-	{ "vt6102", rhinepnp, 0, },
-	{ "GA620", ga620pnp, 0, },
-	{ "83820",   dp83820pnp, 0, },
-	{ "dp83820", dp83820pnp, 0, },
-
-	{ 0, }
-};
-
-static void xetherdetach(void);
-
-int
-etherinit(void)
-{
-	Ether *ctlr;
-	int ctlrno, i, mask, n, x;
-
-	fmtinstall('E', eipfmt);
-
-	etherdetach = xetherdetach;
-	mask = 0;
-	for(ctlrno = 0; ctlrno < MaxEther; ctlrno++){
-		ctlr = &ether[ctlrno];
-		memset(ctlr, 0, sizeof(Ether));
-		if(iniread && isaconfig("ether", ctlrno, ctlr) == 0)
-			continue;
-
-		for(n = 0; ethercards[n].type; n++){
-			if(!iniread){
-				if(ethercards[n].noprobe)
-					continue;
-				memset(ctlr, 0, sizeof(Ether));
-				strcpy(ctlr->type, ethercards[n].type);
-			}
-			else if(cistrcmp(ethercards[n].type, ctlr->type))
-				continue;
-			ctlr->ctlrno = ctlrno;
-
-			x = splhi();
-			if((*ethercards[n].reset)(ctlr)){
-				splx(x);
-				if(iniread)
-					break;
-				else
-					continue;
-			}
-
-			ctlr->state = 1;		/* card found */
-			mask |= 1<<ctlrno;
-			if(ctlr->irq == 2)
-				ctlr->irq = 9;
-			setvec(VectorPIC + ctlr->irq, ctlr->interrupt, ctlr);
-
-			print("ether#%d: %s: port 0x%luX irq %lud",
-				ctlr->ctlrno, ctlr->type, ctlr->port, ctlr->irq);
-			if(ctlr->mem)
-				print(" addr 0x%luX", ctlr->mem & ~KZERO);
-			if(ctlr->size)
-				print(" size 0x%luX", ctlr->size);
-			print(": %E\n", ctlr->ea);
-		
-			if(ctlr->nrb == 0)
-				ctlr->nrb = Nrb;
-			ctlr->rb = ialloc(sizeof(RingBuf)*ctlr->nrb, 0);
-			if(ctlr->ntb == 0)
-				ctlr->ntb = Ntb;
-			ctlr->tb = ialloc(sizeof(RingBuf)*ctlr->ntb, 0);
-
-			ctlr->rh = 0;
-			ctlr->ri = 0;
-			for(i = 0; i < ctlr->nrb; i++)
-				ctlr->rb[i].owner = Interface;
-		
-			ctlr->th = 0;
-			ctlr->ti = 0;
-			for(i = 0; i < ctlr->ntb; i++)
-				ctlr->tb[i].owner = Host;
-
-			splx(x);
-			break;
-		}
-	}
-
-	return mask;
-}
-
-void
-etherinitdev(int i, char *s)
-{
-	sprint(s, "ether%d", i);
-}
-
-void
-etherprintdevs(int i)
-{
-	print(" ether%d", i);
-}
-
-static Ether*
-attach(int ctlrno)
-{
-	Ether *ctlr;
-
-	if(ctlrno >= MaxEther || ether[ctlrno].state == 0)
-		return 0;
-
-	ctlr = &ether[ctlrno];
-	if(ctlr->state == 1){		/* card found? */
-		ctlr->state = 2;	/* attaching */
-		(*ctlr->attach)(ctlr);
-	}
-
-	return ctlr;
-}
-
-static void
-xetherdetach(void)
-{
-	Ether *ctlr;
-	int ctlrno, x;
-
-	x = splhi();
-	for(ctlrno = 0; ctlrno < MaxEther; ctlrno++){
-		ctlr = &ether[ctlrno];
-		if(ctlr->detach && ctlr->state != 0)	/* found | attaching? */
-			ctlr->detach(ctlr);
-	}
-	splx(x);
-}
-
-uchar*
-etheraddr(int ctlrno)
-{
-	Ether *ctlr;
-
-	if((ctlr = attach(ctlrno)) == 0)
-		return 0;
-
-	return ctlr->ea;
-}
-
-static int
-wait(RingBuf* ring, uchar owner, int timo)
-{
-	ulong start;
-
-	start = m->ticks;
-	while(TK2MS(m->ticks - start) < timo){
-		if(ring->owner != owner)
-			return 1;
-	}
-
-	return 0;
-}
-
-int
-etherrxpkt(int ctlrno, Etherpkt* pkt, int timo)
-{
-	int n;
-	Ether *ctlr;
-	RingBuf *ring;
-
-	if((ctlr = attach(ctlrno)) == 0)
-		return 0;
-
-	ring = &ctlr->rb[ctlr->rh];
-	if(wait(ring, Interface, timo) == 0){
-		if(debug)
-			print("ether%d: rx timeout\n", ctlrno);
-		return 0;
-	}
-
-	n = ring->len;
-	memmove(pkt, ring->pkt, n);
-	ring->owner = Interface;
-	ctlr->rh = NEXT(ctlr->rh, ctlr->nrb);
-
-	return n;
-}
-
-int
-etherrxflush(int ctlrno)
-{
-	int n;
-	Ether *ctlr;
-	RingBuf *ring;
-
-	if((ctlr = attach(ctlrno)) == 0)
-		return 0;
-
-	n = 0;
-	for(;;){
-		ring = &ctlr->rb[ctlr->rh];
-		if(wait(ring, Interface, 100) == 0)
-			break;
-
-		ring->owner = Interface;
-		ctlr->rh = NEXT(ctlr->rh, ctlr->nrb);
-		n++;
-	}
-
-	return n;
-}
-
-int
-ethertxpkt(int ctlrno, Etherpkt* pkt, int len, int)
-{
-	Ether *ctlr;
-	RingBuf *ring;
-	int s;
-
-	if((ctlr = attach(ctlrno)) == 0)
-		return 0;
-
-	ring = &ctlr->tb[ctlr->th];
-	if(wait(ring, Interface, 1000) == 0){
-		print("ether%d: tx buffer timeout\n", ctlrno);
-		return 0;
-	}
-
-	memmove(pkt->s, ctlr->ea, Eaddrlen);
-	if(debug)
-		print("%E to %E...\n", pkt->s, pkt->d);
-	memmove(ring->pkt, pkt, len);
-	if(len < ETHERMINTU){
-		memset(ring->pkt+len, 0, ETHERMINTU-len);
-		len = ETHERMINTU;
-	}
-	ring->len = len;
-	ring->owner = Interface;
-	ctlr->th = NEXT(ctlr->th, ctlr->ntb);
-	s = splhi();
-	(*ctlr->transmit)(ctlr);
-	splx(s);
-
-	return 1;
-}
--- a/os/boot/pc/ether2000.c
+++ /dev/null
@@ -1,110 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-#include "etherif.h"
-#include "ether8390.h"
-
-/*
- * Driver written for the 'Notebook Computer Ethernet LAN Adapter',
- * a plug-in to the bus-slot on the rear of the Gateway NOMAD 425DXL
- * laptop. The manual says NE2000 compatible.
- * The interface appears to be pretty well described in the National
- * Semiconductor Local Area Network Databook (1992) as one of the
- * AT evaluation cards.
- *
- * The NE2000 is really just a DP8390[12] plus a data port
- * and a reset port.
- */
-enum {
-	Data		= 0x10,		/* offset from I/O base of data port */
-	Reset		= 0x1F,		/* offset from I/O base of reset port */
-};
-
-int
-ne2000reset(Ether* ether)
-{
-	ushort buf[16];
-	ulong port;
-	Dp8390 *ctlr;
-	int i;
-	uchar ea[Eaddrlen];
-
-	/*
-	 * Set up the software configuration.
-	 * Use defaults for port, irq, mem and size
-	 * if not specified.
-	 */
-	if(ether->port == 0)
-		ether->port = 0x300;
-	if(ether->irq == 0)
-		ether->irq = 2;
-	if(ether->mem == 0)
-		ether->mem = 0x4000;
-	if(ether->size == 0)
-		ether->size = 16*1024;
-	port = ether->port;
-
-	ether->ctlr = malloc(sizeof(Dp8390));
-	ctlr = ether->ctlr;
-	ctlr->width = 2;
-	ctlr->ram = 0;
-
-	ctlr->port = port;
-	ctlr->data = port+Data;
-
-	ctlr->tstart = HOWMANY(ether->mem, Dp8390BufSz);
-	ctlr->pstart = ctlr->tstart + HOWMANY(sizeof(Etherpkt), Dp8390BufSz);
-	ctlr->pstop = ctlr->tstart + HOWMANY(ether->size, Dp8390BufSz);
-
-	ctlr->dummyrr = 1;
-	for(i = 0; i < ether->nopt; i++){
-		if(strcmp(ether->opt[i], "nodummyrr"))
-			continue;
-		ctlr->dummyrr = 0;
-		break;
-	}
-
-	/*
-	 * Reset the board. This is done by doing a read
-	 * followed by a write to the Reset address.
-	 */
-	buf[0] = inb(port+Reset);
-	delay(2);
-	outb(port+Reset, buf[0]);
-	delay(2);
-	
-	/*
-	 * Init the (possible) chip, then use the (possible)
-	 * chip to read the (possible) PROM for ethernet address
-	 * and a marker byte.
-	 * Could just look at the DP8390 command register after
-	 * initialisation has been tried, but that wouldn't be
-	 * enough, there are other ethernet boards which could
-	 * match.
-	 */
-	dp8390reset(ether);
-	memset(buf, 0, sizeof(buf));
-	dp8390read(ctlr, buf, 0, sizeof(buf));
-	if((buf[0x0E] & 0xFF) != 0x57 || (buf[0x0F] & 0xFF) != 0x57){
-		free(ether->ctlr);
-		return -1;
-	}
-
-	/*
-	 * Stupid machine. Shorts were asked for,
-	 * shorts were delivered, although the PROM is a byte array.
-	 * Set the ethernet address.
-	 */
-	memset(ea, 0, Eaddrlen);
-	if(memcmp(ea, ether->ea, Eaddrlen) == 0){
-		for(i = 0; i < sizeof(ether->ea); i++)
-			ether->ea[i] = buf[i];
-	}
-	dp8390setea(ether);
-
-	return 0;
-}
--- a/os/boot/pc/ether2114x.c
+++ /dev/null
@@ -1,1652 +1,0 @@
-/*
- * Digital Semiconductor DECchip 21140 PCI Fast Ethernet LAN Controller
- * as found on the Digital Fast EtherWORKS PCI 10/100 adapter (DE-500-X).
- * To do:
- *	thresholds;
- *	ring sizing;
- *	handle more error conditions;
- *	all the rest of it...
- */
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-#include "etherif.h"
-
-#define DEBUG		(0)
-#define debug		if(DEBUG)print
-
-enum {
-	Nrde		= 32,
-	Ntde		= 4,
-};
-
-#define Rbsz		ROUNDUP(sizeof(Etherpkt)+4, 4)
-
-enum {					/* CRS0 - Bus Mode */
-	Swr		= 0x00000001,	/* Software Reset */
-	Bar		= 0x00000002,	/* Bus Arbitration */
-	Dsl		= 0x0000007C,	/* Descriptor Skip Length (field) */
-	Ble		= 0x00000080,	/* Big/Little Endian */
-	Pbl		= 0x00003F00,	/* Programmable Burst Length (field) */
-	Cal		= 0x0000C000,	/* Cache Alignment (field) */
-	Cal8		= 0x00004000,	/* 8 longword boundary alignment */
-	Cal16		= 0x00008000,	/* 16 longword boundary alignment */
-	Cal32		= 0x0000C000,	/* 32 longword boundary alignment */
-	Tap		= 0x000E0000,	/* Transmit Automatic Polling (field) */
-	Dbo		= 0x00100000,	/* Descriptor Byte Ordering Mode */
-	Rml		= 0x00200000,	/* Read Multiple */
-}; 
-
-enum {					/* CSR[57] - Status and Interrupt Enable */
-	Ti		= 0x00000001,	/* Transmit Interrupt */
-	Tps		= 0x00000002,	/* Transmit Process Stopped */
-	Tu		= 0x00000004,	/* Transmit buffer Unavailable */
-	Tjt		= 0x00000008,	/* Transmit Jabber Timeout */
-	Unf		= 0x00000020,	/* transmit UNderFlow */
-	Ri		= 0x00000040,	/* Receive Interrupt */
-	Ru		= 0x00000080,	/* Receive buffer Unavailable */
-	Rps		= 0x00000100,	/* Receive Process Stopped */
-	Rwt		= 0x00000200,	/* Receive Watchdog Timeout */
-	Eti		= 0x00000400,	/* Early Transmit Interrupt */
-	Gte		= 0x00000800,	/* General purpose Timer Expired */
-	Fbe		= 0x00002000,	/* Fatal Bit Error */
-	Ais		= 0x00008000,	/* Abnormal Interrupt Summary */
-	Nis		= 0x00010000,	/* Normal Interrupt Summary */
-	Rs		= 0x000E0000,	/* Receive process State (field) */
-	Ts		= 0x00700000,	/* Transmit process State (field) */
-	Eb		= 0x03800000,	/* Error bits */
-};
-
-enum {					/* CSR6 - Operating Mode */
-	Hp		= 0x00000001,	/* Hash/Perfect receive filtering mode */
-	Sr		= 0x00000002,	/* Start/stop Receive */
-	Ho		= 0x00000004,	/* Hash-Only filtering mode */
-	Pb		= 0x00000008,	/* Pass Bad frames */
-	If		= 0x00000010,	/* Inverse Filtering */
-	Sb		= 0x00000020,	/* Start/stop Backoff counter */
-	Pr		= 0x00000040,	/* Promiscuous Mode */
-	Pm		= 0x00000080,	/* Pass all Multicast */
-	Fd		= 0x00000200,	/* Full Duplex mode */
-	Om		= 0x00000C00,	/* Operating Mode (field) */
-	Fc		= 0x00001000,	/* Force Collision */
-	St		= 0x00002000,	/* Start/stop Transmission Command */
-	Tr		= 0x0000C000,	/* ThReshold control bits (field) */
-	Tr128		= 0x00000000,
-	Tr256		= 0x00004000,
-	Tr512		= 0x00008000,
-	Tr1024		= 0x0000C000,
-	Ca		= 0x00020000,	/* CApture effect enable */
-	Ps		= 0x00040000,	/* Port Select */
-	Hbd		= 0x00080000,	/* HeartBeat Disable */
-	Imm		= 0x00100000,	/* IMMediate mode */
-	Sf		= 0x00200000,	/* Store and Forward */
-	Ttm		= 0x00400000,	/* Transmit Threshold Mode */
-	Pcs		= 0x00800000,	/* PCS function */
-	Scr		= 0x01000000,	/* SCRambler mode */
-	Mbo		= 0x02000000,	/* Must Be One */
-	Ra		= 0x40000000,	/* Receive All */
-	Sc		= 0x80000000,	/* Special Capture effect enable */
-
-	TrMODE		= Tr512,	/* default transmission threshold */
-};
-
-enum {					/* CSR9 - ROM and MII Management */
-	Scs		= 0x00000001,	/* serial ROM chip select */
-	Sclk		= 0x00000002,	/* serial ROM clock */
-	Sdi		= 0x00000004,	/* serial ROM data in */
-	Sdo		= 0x00000008,	/* serial ROM data out */
-	Ss		= 0x00000800,	/* serial ROM select */
-	Wr		= 0x00002000,	/* write */
-	Rd		= 0x00004000,	/* read */
-
-	Mdc		= 0x00010000,	/* MII management clock */
-	Mdo		= 0x00020000,	/* MII management write data */
-	Mii		= 0x00040000,	/* MII management operation mode (W) */
-	Mdi		= 0x00080000,	/* MII management data in */
-};
-
-enum {					/* CSR12 - General-Purpose Port */
-	Gpc		= 0x00000100,	/* General Purpose Control */
-};
-
-typedef struct Des {
-	int	status;
-	int	control;
-	ulong	addr;
-	void*	bp;
-} Des;
-
-enum {					/* status */
-	Of		= 0x00000001,	/* Rx: OverFlow */
-	Ce		= 0x00000002,	/* Rx: CRC Error */
-	Db		= 0x00000004,	/* Rx: Dribbling Bit */
-	Re		= 0x00000008,	/* Rx: Report on MII Error */
-	Rw		= 0x00000010,	/* Rx: Receive Watchdog */
-	Ft		= 0x00000020,	/* Rx: Frame Type */
-	Cs		= 0x00000040,	/* Rx: Collision Seen */
-	Tl		= 0x00000080,	/* Rx: Frame too Long */
-	Ls		= 0x00000100,	/* Rx: Last deScriptor */
-	Fs		= 0x00000200,	/* Rx: First deScriptor */
-	Mf		= 0x00000400,	/* Rx: Multicast Frame */
-	Rf		= 0x00000800,	/* Rx: Runt Frame */
-	Dt		= 0x00003000,	/* Rx: Data Type (field) */
-	De		= 0x00004000,	/* Rx: Descriptor Error */
-	Fl		= 0x3FFF0000,	/* Rx: Frame Length (field) */
-	Ff		= 0x40000000,	/* Rx: Filtering Fail */
-
-	Def		= 0x00000001,	/* Tx: DEFerred */
-	Uf		= 0x00000002,	/* Tx: UnderFlow error */
-	Lf		= 0x00000004,	/* Tx: Link Fail report */
-	Cc		= 0x00000078,	/* Tx: Collision Count (field) */
-	Hf		= 0x00000080,	/* Tx: Heartbeat Fail */
-	Ec		= 0x00000100,	/* Tx: Excessive Collisions */
-	Lc		= 0x00000200,	/* Tx: Late Collision */
-	Nc		= 0x00000400,	/* Tx: No Carrier */
-	Lo		= 0x00000800,	/* Tx: LOss of carrier */
-	To		= 0x00004000,	/* Tx: Transmission jabber timeOut */
-
-	Es		= 0x00008000,	/* [RT]x: Error Summary */
-	Own		= 0x80000000,	/* [RT]x: OWN bit */
-};
-
-enum {					/* control */
-	Bs1		= 0x000007FF,	/* [RT]x: Buffer 1 Size */
-	Bs2		= 0x003FF800,	/* [RT]x: Buffer 2 Size */
-
-	Ch		= 0x01000000,	/* [RT]x: second address CHained */
-	Er		= 0x02000000,	/* [RT]x: End of Ring */
-
-	Ft0		= 0x00400000,	/* Tx: Filtering Type 0 */
-	Dpd		= 0x00800000,	/* Tx: Disabled PaDding */
-	Ac		= 0x04000000,	/* Tx: Add CRC disable */
-	Set		= 0x08000000,	/* Tx: SETup packet */
-	Ft1		= 0x10000000,	/* Tx: Filtering Type 1 */
-	Fseg		= 0x20000000,	/* Tx: First SEGment */
-	Lseg		= 0x40000000,	/* Tx: Last SEGment */
-	Ic		= 0x80000000,	/* Tx: Interrupt on Completion */
-};
-
-enum {					/* PHY registers */
-	Bmcr		= 0,		/* Basic Mode Control */
-	Bmsr		= 1,		/* Basic Mode Status */
-	Phyidr1		= 2,		/* PHY Identifier #1 */
-	Phyidr2		= 3,		/* PHY Identifier #2 */
-	Anar		= 4,		/* Auto-Negotiation Advertisment */
-	Anlpar		= 5,		/* Auto-Negotiation Link Partner Ability */
-	Aner		= 6,		/* Auto-Negotiation Expansion */
-};
-
-enum {					/* Variants */
-	Tulip0		= (0x0009<<16)|0x1011,
-	Tulip1		= (0x0014<<16)|0x1011,
-	Tulip3		= (0x0019<<16)|0x1011,
-	Pnic		= (0x0002<<16)|0x11AD,
-	Pnic2		= (0xC115<<16)|0x11AD,
-};
-
-typedef struct Ctlr Ctlr;
-typedef struct Ctlr {
-	int	port;
-	Pcidev*	pcidev;
-	Ctlr*	next;
-	int	active;
-	int	id;			/* (pcidev->did<<16)|pcidev->vid */
-
-	uchar	*srom;
-	int	sromsz;
-	uchar*	sromea;			/* MAC address */
-	uchar*	leaf;
-	int	sct;			/* selected connection type */
-	int	k;			/* info block count */
-	uchar*	infoblock[16];
-	int	sctk;			/* sct block index */
-	int	curk;			/* current block index */
-	uchar*	type5block;
-
-	int	phy[32];		/* logical to physical map */
-	int	phyreset;		/* reset bitmap */
-	int	curphyad;
-	int	fdx;
-	int	ttm;
-
-	uchar	fd;			/* option */
-	int	medium;			/* option */
-
-	int	csr6;			/* CSR6 - operating mode */
-	int	mask;			/* CSR[57] - interrupt mask */
-	int	mbps;
-
-	Des*	rdr;			/* receive descriptor ring */
-	int	nrdr;			/* size of rdr */
-	int	rdrx;			/* index into rdr */
-
-	Des*	tdr;			/* transmit descriptor ring */
-	int	ntdr;			/* size of tdr */
-	int	tdrh;			/* host index into tdr */
-	int	tdri;			/* interface index into tdr */
-	int	ntq;			/* descriptors active */
-	Block*	setupbp;
-
-	ulong	of;			/* receive statistics */
-	ulong	ce;
-	ulong	cs;
-	ulong	tl;
-	ulong	rf;
-	ulong	de;
-
-	ulong	uf;			/* transmit statistics */
-	ulong	ec;
-	ulong	lc;
-	ulong	nc;
-	ulong	lo;
-	ulong	to;
-
-} Ctlr;
-
-static Ctlr* ctlrhead;
-static Ctlr* ctlrtail;
-
-#define csr32r(c, r)	(inl((c)->port+((r)*8)))
-#define csr32w(c, r, l)	(outl((c)->port+((r)*8), (ulong)(l)))
-
-static void
-attach(Ether* ether)
-{
-	Ctlr *ctlr;
-
-	ctlr = ether->ctlr;
-	if(!(ctlr->csr6 & Sr)){
-		ctlr->csr6 |= Sr;
-		csr32w(ctlr, 6, ctlr->csr6);
-	}
-}
-
-static void
-transmit(Ether* ether)
-{
-	Ctlr *ctlr;
-	Block *bp;
-	Des *des;
-	int control;
-	RingBuf *tb;
-
-	ctlr = ether->ctlr;
-	while(ctlr->ntq < (ctlr->ntdr-1)){
-		if(ctlr->setupbp){
-			bp = ctlr->setupbp;
-			ctlr->setupbp = 0;
-			control = Ic|Set|BLEN(bp);
-		}
-		else{
-			if(ether->ntb == 0)
-				break;
-			tb = &ether->tb[ether->ti];
-			if(tb->owner != Interface)
-				break;
-			bp = allocb(tb->len);
-			memmove(bp->wp, tb->pkt, tb->len);
-			memmove(bp->wp+Eaddrlen, ether->ea, Eaddrlen);
-			bp->wp += tb->len;
-
-			tb->owner = Host;
-			ether->ti = NEXT(ether->ti, ether->ntb);
-
-			control = Ic|Lseg|Fseg|BLEN(bp);
-		}
-
-		ctlr->tdr[PREV(ctlr->tdrh, ctlr->ntdr)].control &= ~Ic;
-		des = &ctlr->tdr[ctlr->tdrh];
-		des->bp = bp;
-		des->addr = PADDR(bp->rp);
-		des->control |= control;
-		ctlr->ntq++;
-		//coherence();
-		des->status = Own;
-		csr32w(ctlr, 1, 0);
-		ctlr->tdrh = NEXT(ctlr->tdrh, ctlr->ntdr);
-	}
-}
-
-static void
-interrupt(Ureg*, void* arg)
-{
-	Ctlr *ctlr;
-	Ether *ether;
-	int len, status;
-	Des *des;
-	RingBuf *ring;
-
-	ether = arg;
-	ctlr = ether->ctlr;
-
-	while((status = csr32r(ctlr, 5)) & (Nis|Ais)){
-		/*
-		 * Acknowledge the interrupts and mask-out
-		 * the ones that are implicitly handled.
-		 */
-		csr32w(ctlr, 5, status);
-		status &= (ctlr->mask & ~(Nis|Ais|Ti));
-
-		/*
-		 * Received packets.
-		 */
-		if(status & Ri){
-			des = &ctlr->rdr[ctlr->rdrx];
-			while((des->status & Own) == 0){
-				len = ((des->status & Fl)>>16)-4;
-				if(des->status & Es){
-					if(des->status & Of)
-						ctlr->of++;
-					if(des->status & Ce)
-						ctlr->ce++;
-					if(des->status & Cs)
-						ctlr->cs++;
-					if(des->status & Tl)
-						ctlr->tl++;
-					if(des->status & Rf)
-						ctlr->rf++;
-					if(des->status & De)
-						ctlr->de++;
-				}
-				else{
-					ring = &ether->rb[ether->ri];
-					if(ring->owner == Interface){
-						ring->owner = Host;
-						ring->len = len;
-						memmove(ring->pkt, des->bp, len);
-						ether->ri = NEXT(ether->ri, ether->nrb);
-					}
-				}
-
-				des->control &= Er;
-				des->control |= Rbsz;
-				des->status = Own;
-
-				ctlr->rdrx = NEXT(ctlr->rdrx, ctlr->nrdr);
-				des = &ctlr->rdr[ctlr->rdrx];
-			}
-			status &= ~Ri;
-		}
-
-		/*
-		 * Check the transmit side:
-		 *	check for Transmit Underflow and Adjust
-		 *	the threshold upwards;
-		 *	free any transmitted buffers and try to
-		 *	top-up the ring.
-		 */
-		if(status & Unf){
-			csr32w(ctlr, 6, ctlr->csr6 & ~St);
-			switch(ctlr->csr6 & Tr){
-			case Tr128:
-				len = Tr256;
-				break;
-			case Tr256:
-				len = Tr512;
-				break;
-			case Tr512:
-				len = Tr1024;
-				break;
-			default:
-			case Tr1024:
-				len = Sf;
-				break;
-			}
-			ctlr->csr6 = (ctlr->csr6 & ~Tr)|len;
-			csr32w(ctlr, 6, ctlr->csr6);
-			csr32w(ctlr, 5, Tps);
-			status &= ~(Unf|Tps);
-		}
-
-		while(ctlr->ntq){
-			des = &ctlr->tdr[ctlr->tdri];
-			if(des->status & Own)
-				break;
-
-			if(des->status & Es){
-				if(des->status & Uf)
-					ctlr->uf++;
-				if(des->status & Ec)
-					ctlr->ec++;
-				if(des->status & Lc)
-					ctlr->lc++;
-				if(des->status & Nc)
-					ctlr->nc++;
-				if(des->status & Lo)
-					ctlr->lo++;
-				if(des->status & To)
-					ctlr->to++;
-			}
-
-			freeb(des->bp);
-			des->control &= Er;
-
-			ctlr->ntq--;
-			ctlr->tdri = NEXT(ctlr->tdri, ctlr->ntdr);
-		}
-		transmit(ether);
-
-		/*
-		 * Anything left not catered for?
-		 */
-		if(status)
-			panic("#l%d: status %8.8uX\n", ether->ctlrno, status);
-	}
-}
-
-static void
-ctlrinit(Ether* ether)
-{
-	Ctlr *ctlr;
-	Des *des;
-	Block *bp;
-	int i;
-	uchar bi[Eaddrlen*2];
-
-	ctlr = ether->ctlr;
-
-	/*
-	 * Allocate and initialise the receive ring;
-	 * allocate and initialise the transmit ring;
-	 * unmask interrupts and start the transmit side;
-	 * create and post a setup packet to initialise
-	 * the physical ethernet address.
-	 */
-	ctlr->rdr = malloc(ctlr->nrdr*sizeof(Des));
-	for(des = ctlr->rdr; des < &ctlr->rdr[ctlr->nrdr]; des++){
-		des->bp = malloc(Rbsz);
-		des->status = Own;
-		des->control = Rbsz;
-		des->addr = PADDR(des->bp);
-	}
-	ctlr->rdr[ctlr->nrdr-1].control |= Er;
-	ctlr->rdrx = 0;
-	csr32w(ctlr, 3, PADDR(ctlr->rdr));
-
-	ctlr->tdr = ialloc(ctlr->ntdr*sizeof(Des), 32);
-	ctlr->tdr[ctlr->ntdr-1].control |= Er;
-	ctlr->tdrh = 0;
-	ctlr->tdri = 0;
-	csr32w(ctlr, 4, PADDR(ctlr->tdr));
-
-	/*
-	 * Clear any bits in the Status Register (CSR5) as
-	 * the PNIC has a different reset value from a true 2114x.
-	 */
-	ctlr->mask = Nis|Ais|Fbe|Rwt|Rps|Ru|Ri|Unf|Tjt|Tps|Ti;
-	csr32w(ctlr, 5, ctlr->mask);
-	csr32w(ctlr, 7, ctlr->mask);
-	ctlr->csr6 |= St;
-	csr32w(ctlr, 6, ctlr->csr6);
-
-	for(i = 0; i < Eaddrlen/2; i++){
-		bi[i*4] = ether->ea[i*2];
-		bi[i*4+1] = ether->ea[i*2+1];
-		bi[i*4+2] = ether->ea[i*2+1];
-		bi[i*4+3] = ether->ea[i*2];
-	}
-	bp = allocb(Eaddrlen*2*16);
-	memset(bp->rp, 0xFF, sizeof(bi));
-	for(i = sizeof(bi); i < sizeof(bi)*16; i += sizeof(bi))
-		memmove(bp->rp+i, bi, sizeof(bi));
-	bp->wp += sizeof(bi)*16;
-
-	ctlr->setupbp = bp;
-	transmit(ether);
-}
-
-static void
-csr9w(Ctlr* ctlr, int data)
-{
-	csr32w(ctlr, 9, data);
-	microdelay(1);
-}
-
-static int
-miimdi(Ctlr* ctlr, int n)
-{
-	int data, i;
-
-	/*
-	 * Read n bits from the MII Management Register.
-	 */
-	data = 0;
-	for(i = n-1; i >= 0; i--){
-		if(csr32r(ctlr, 9) & Mdi)
-			data |= (1<<i);
-		csr9w(ctlr, Mii|Mdc);
-		csr9w(ctlr, Mii);
-	}
-	csr9w(ctlr, 0);
-
-	return data;
-}
-
-static void
-miimdo(Ctlr* ctlr, int bits, int n)
-{
-	int i, mdo;
-
-	/*
-	 * Write n bits to the MII Management Register.
-	 */
-	for(i = n-1; i >= 0; i--){
-		if(bits & (1<<i))
-			mdo = Mdo;
-		else
-			mdo = 0;
-		csr9w(ctlr, mdo);
-		csr9w(ctlr, mdo|Mdc);
-		csr9w(ctlr, mdo);
-	}
-}
-
-static int
-miir(Ctlr* ctlr, int phyad, int regad)
-{
-	int data, i;
-
-	if(ctlr->id == Pnic){
-		i = 1000;
-		csr32w(ctlr, 20, 0x60020000|(phyad<<23)|(regad<<18));
-		do{
-			microdelay(1);
-			data = csr32r(ctlr, 20);
-		}while((data & 0x80000000) && --i);
-
-		if(i == 0)
-			return -1;
-		return data & 0xFFFF;
-	}
-
-	/*
-	 * Preamble;
-	 * ST+OP+PHYAD+REGAD;
-	 * TA + 16 data bits.
-	 */
-	miimdo(ctlr, 0xFFFFFFFF, 32);
-	miimdo(ctlr, 0x1800|(phyad<<5)|regad, 14);
-	data = miimdi(ctlr, 18);
-
-	if(data & 0x10000)
-		return -1;
-
-	return data & 0xFFFF;
-}
-
-static void
-miiw(Ctlr* ctlr, int phyad, int regad, int data)
-{
-	/*
-	 * Preamble;
-	 * ST+OP+PHYAD+REGAD+TA + 16 data bits;
-	 * Z.
-	 */
-	miimdo(ctlr, 0xFFFFFFFF, 32);
-	data &= 0xFFFF;
-	data |= (0x05<<(5+5+2+16))|(phyad<<(5+2+16))|(regad<<(2+16))|(0x02<<16);
-	miimdo(ctlr, data, 32);
-	csr9w(ctlr, Mdc);
-	csr9w(ctlr, 0);
-}
-
-static int
-sromr(Ctlr* ctlr, int r)
-{
-	int i, op, data, size;
-
-	if(ctlr->id == Pnic){
-		i = 1000;
-		csr32w(ctlr, 19, 0x600|r);
-		do{
-			microdelay(1);
-			data = csr32r(ctlr, 19);
-		}while((data & 0x80000000) && --i);
-
-		if(ctlr->sromsz == 0)
-			ctlr->sromsz = 6;
-
-		return csr32r(ctlr, 9) & 0xFFFF;
-	}
-
-	/*
-	 * This sequence for reading a 16-bit register 'r'
-	 * in the EEPROM is taken (pretty much) straight from Section
-	 * 7.4 of the 21140 Hardware Reference Manual.
-	 */
-reread:
-	csr9w(ctlr, Rd|Ss);
-	csr9w(ctlr, Rd|Ss|Scs);
-	csr9w(ctlr, Rd|Ss|Sclk|Scs);
-	csr9w(ctlr, Rd|Ss);
-
-	op = 0x06;
-	for(i = 3-1; i >= 0; i--){
-		data = Rd|Ss|(((op>>i) & 0x01)<<2)|Scs;
-		csr9w(ctlr, data);
-		csr9w(ctlr, data|Sclk);
-		csr9w(ctlr, data);
-	}
-
-	/*
-	 * First time through must work out the EEPROM size.
-	 * This doesn't seem to work on the 21041 as implemented
-	 * in Virtual PC for the Mac, so wire any 21041 to 6,
-	 * it's the only 21041 this code will ever likely see.
-	 */
-	if((size = ctlr->sromsz) == 0){
-		if(ctlr->id == Tulip1)
-			ctlr->sromsz = size = 6;
-		else
-			size = 8;
-	}
-
-	for(size = size-1; size >= 0; size--){
-		data = Rd|Ss|(((r>>size) & 0x01)<<2)|Scs;
-		csr9w(ctlr, data);
-		csr9w(ctlr, data|Sclk);
-		csr9w(ctlr, data);
-		microdelay(1);
-		if(ctlr->sromsz == 0 && !(csr32r(ctlr, 9) & Sdo))
-			break;
-	}
-
-	data = 0;
-	for(i = 16-1; i >= 0; i--){
-		csr9w(ctlr, Rd|Ss|Sclk|Scs);
-		if(csr32r(ctlr, 9) & Sdo)
-			data |= (1<<i);
-		csr9w(ctlr, Rd|Ss|Scs);
-	}
-
-	csr9w(ctlr, 0);
-
-	if(ctlr->sromsz == 0){
-		ctlr->sromsz = 8-size;
-		goto reread;
-	}
-
-	return data & 0xFFFF;
-}
-
-static void
-softreset(Ctlr* ctlr)
-{
-	/*
-	 * Soft-reset the controller and initialise bus mode.
-	 * Delay should be >= 50 PCI cycles (2×S @ 25MHz).
-	 */
-	csr32w(ctlr, 0, Swr);
-	microdelay(10);
-	csr32w(ctlr, 0, Rml|Cal16);
-	delay(1);
-}
-
-static int
-type5block(Ctlr* ctlr, uchar* block)
-{
-	int csr15, i, len;
-
-	/*
-	 * Reset or GPR sequence. Reset should be once only,
-	 * before the GPR sequence.
-	 * Note 'block' is not a pointer to the block head but
-	 * a pointer to the data in the block starting at the
-	 * reset length value so type5block can be used for the
-	 * sequences contained in type 1 and type 3 blocks.
-	 * The SROM docs state the 21140 type 5 block is the
-	 * same as that for the 21143, but the two controllers
-	 * use different registers and sequence-element lengths
-	 * so the 21140 code here is a guess for a real type 5
-	 * sequence.
-	 */
-	len = *block++;
-	if(ctlr->id != Tulip3){
-		for(i = 0; i < len; i++){
-			csr32w(ctlr, 12, *block);
-			block++;
-		}
-		return len;
-	}
-
-	for(i = 0; i < len; i++){
-		csr15 = *block++<<16;
-		csr15 |= *block++<<24;
-		csr32w(ctlr, 15, csr15);
-		debug("%8.8uX ", csr15);
-	}
-	return 2*len;
-}
-
-static int
-typephylink(Ctlr* ctlr, uchar*)
-{
-	int an, bmcr, bmsr, csr6, x;
-
-	/*
-	 * Fail if
-	 *	auto-negotiataion enabled but not complete;
-	 *	no valid link established.
-	 */
-	bmcr = miir(ctlr, ctlr->curphyad, Bmcr);
-	miir(ctlr, ctlr->curphyad, Bmsr);
-	bmsr = miir(ctlr, ctlr->curphyad, Bmsr);
-	debug("bmcr 0x%2.2uX bmsr 0x%2.2uX\n", bmcr, bmsr);
-	if(((bmcr & 0x1000) && !(bmsr & 0x0020)) || !(bmsr & 0x0004))
-		return 0;
-
-	if(bmcr & 0x1000){
-		an = miir(ctlr, ctlr->curphyad, Anar);
-		an &= miir(ctlr, ctlr->curphyad, Anlpar) & 0x3E0;
-		debug("an 0x%2.uX 0x%2.2uX 0x%2.2uX\n",
-	    		miir(ctlr, ctlr->curphyad, Anar),
-			miir(ctlr, ctlr->curphyad, Anlpar),
-			an);
-	
-		if(an & 0x0100)
-			x = 0x4000;
-		else if(an & 0x0080)
-			x = 0x2000;
-		else if(an & 0x0040)
-			x = 0x1000;
-		else if(an & 0x0020)
-			x = 0x0800;
-		else
-			x = 0;
-	}
-	else if((bmcr & 0x2100) == 0x2100)
-		x = 0x4000;
-	else if(bmcr & 0x2000){
-		/*
-		 * If FD capable, force it if necessary.
-		 */
-		if((bmsr & 0x4000) && ctlr->fd){
-			miiw(ctlr, ctlr->curphyad, Bmcr, 0x2100);
-			x = 0x4000;
-		}
-		else
-			x = 0x2000;
-	}
-	else if(bmcr & 0x0100)
-		x = 0x1000;
-	else
-		x = 0x0800;
-
-	csr6 = Sc|Mbo|Hbd|Ps|Ca|TrMODE|Sb;
-	if(ctlr->fdx & x)
-		csr6 |= Fd;
-	if(ctlr->ttm & x)
-		csr6 |= Ttm;
-	debug("csr6 0x%8.8uX 0x%8.8uX 0x%8.8luX\n",
-		csr6, ctlr->csr6, csr32r(ctlr, 6));
-	if(csr6 != ctlr->csr6){
-		ctlr->csr6 = csr6;
-		csr32w(ctlr, 6, csr6);
-	}
-
-	return 1;
-}
-
-static int
-typephymode(Ctlr* ctlr, uchar* block, int wait)
-{
-	uchar *p;
-	int len, mc, nway, phyx, timeo;
-
-	if(DEBUG){
-		int i;
-
-		len = (block[0] & ~0x80)+1;
-		for(i = 0; i < len; i++)
-			debug("%2.2uX ", block[i]);
-		debug("\n");
-	}
-
-	if(block[1] == 1)
-		len = 1;
-	else if(block[1] == 3)
-		len = 2;
-	else
-		return -1;
-
-	/*
-	 * Snarf the media capabilities, nway advertisment,
-	 * FDX and TTM bitmaps.
-	 */
-	p = &block[5+len*block[3]+len*block[4+len*block[3]]];
-	mc = *p++;
-	mc |= *p++<<8;
-	nway = *p++;
-	nway |= *p++<<8;
-	ctlr->fdx = *p++;
-	ctlr->fdx |= *p++<<8;
-	ctlr->ttm = *p++;
-	ctlr->ttm |= *p<<8;
-	debug("mc %4.4uX nway %4.4uX fdx %4.4uX ttm %4.4uX\n",
-		mc, nway, ctlr->fdx, ctlr->ttm);
-	USED(mc);
-
-	phyx = block[2];
-	ctlr->curphyad = ctlr->phy[phyx];
-
-	ctlr->csr6 = 0;//Sc|Mbo|Hbd|Ps|Ca|TrMODE|Sb;
-	//csr32w(ctlr, 6, ctlr->csr6);
-	if(typephylink(ctlr, block))
-		return 0;
-
-	if(!(ctlr->phyreset & (1<<phyx))){
-		debug("reset seq: len %d: ", block[3]);
-		if(ctlr->type5block)
-			type5block(ctlr, &ctlr->type5block[2]);
-		else
-			type5block(ctlr, &block[4+len*block[3]]);
-		debug("\n");
-		ctlr->phyreset |= (1<<phyx);
-	}
-
-	/*
-	 * GPR sequence.
-	 */
-	debug("gpr seq: len %d: ", block[3]);
-	type5block(ctlr, &block[3]);
-	debug("\n");
-
-	ctlr->csr6 = 0;//Sc|Mbo|Hbd|Ps|Ca|TrMODE|Sb;
-	//csr32w(ctlr, 6, ctlr->csr6);
-	if(typephylink(ctlr, block))
-		return 0;
-
-	/*
-	 * Turn off auto-negotiation, set the auto-negotiation
-	 * advertisment register then start the auto-negotiation
-	 * process again.
-	 */
-	miiw(ctlr, ctlr->curphyad, Bmcr, 0);
-	miiw(ctlr, ctlr->curphyad, Anar, nway|1);
-	miiw(ctlr, ctlr->curphyad, Bmcr, 0x1000);
-
-	if(!wait)
-		return 0;
-
-	for(timeo = 0; timeo < 30; timeo++){
-		if(typephylink(ctlr, block))
-			return 0;
-		delay(100);
-	}
-
-	return -1;
-}
-
-static int
-typesymmode(Ctlr *ctlr, uchar *block, int wait)
-{
-	uint gpmode, gpdata, command;
-
-	USED(wait);
-	gpmode = block[3] | ((uint) block[4] << 8);
-	gpdata = block[5] | ((uint) block[6] << 8);
-	command = (block[7] | ((uint) block[8] << 8)) & 0x71;
-	if (command & 0x8000) {
-		print("ether2114x.c: FIXME: handle type 4 mode blocks where cmd.active_invalid != 0\n");
-		return -1;
-	}
-	csr32w(ctlr, 15, gpmode);
-	csr32w(ctlr, 15, gpdata);
-	ctlr->csr6 = (command & 0x71) << 18;
-	csr32w(ctlr, 6, ctlr->csr6);
-	return 0;
-}
-
-static int
-type2mode(Ctlr* ctlr, uchar* block, int)
-{
-	uchar *p;
-	int csr6, csr13, csr14, csr15, gpc, gpd;
-
-	csr6 = Sc|Mbo|Ca|TrMODE|Sb;
-	debug("type2mode: medium 0x%2.2uX\n", block[2]);
-
-	/*
-	 * Don't attempt full-duplex
-	 * unless explicitly requested.
-	 */
-	if((block[2] & 0x3F) == 0x04){	/* 10BASE-TFD */
-		if(!ctlr->fd)
-			return -1;
-		csr6 |= Fd;
-	}
-
-	/*
-	 * Operating mode programming values from the datasheet
-	 * unless media specific data is explicitly given.
-	 */
-	p = &block[3];
-	if(block[2] & 0x40){
-		csr13 = (block[4]<<8)|block[3];
-		csr14 = (block[6]<<8)|block[5];
-		csr15 = (block[8]<<8)|block[7];
-		p += 6;
-	}
-	else switch(block[2] & 0x3F){
-	default:
-		return -1;
-	case 0x00:			/* 10BASE-T */
-		csr13 = 0x00000001;
-		csr14 = 0x00007F3F;
-		csr15 = 0x00000008;
-		break;
-	case 0x01:			/* 10BASE-2 */
-		csr13 = 0x00000009;
-		csr14 = 0x00000705;
-		csr15 = 0x00000006;
-		break;
-	case 0x02:			/* 10BASE-5 (AUI) */
-		csr13 = 0x00000009;
-		csr14 = 0x00000705;
-		csr15 = 0x0000000E;
-		break;
-	case 0x04:			/* 10BASE-TFD */
-		csr13 = 0x00000001;
-		csr14 = 0x00007F3D;
-		csr15 = 0x00000008;
-		break;
-	}
-	gpc = *p++<<16;
-	gpc |= *p++<<24;
-	gpd = *p++<<16;
-	gpd |= *p<<24;
-
-	csr32w(ctlr, 13, 0);
-	csr32w(ctlr, 14, csr14);
-	csr32w(ctlr, 15, gpc|csr15);
-	delay(10);
-	csr32w(ctlr, 15, gpd|csr15);
-	csr32w(ctlr, 13, csr13);
-
-	ctlr->csr6 = csr6;
-	csr32w(ctlr, 6, ctlr->csr6);
-
-	debug("type2mode: csr13 %8.8uX csr14 %8.8uX csr15 %8.8uX\n",
-		csr13, csr14, csr15);
-	debug("type2mode: gpc %8.8uX gpd %8.8uX csr6 %8.8uX\n",
-		gpc, gpd, csr6);
-
-	return 0;
-}
-
-static int
-type0link(Ctlr* ctlr, uchar* block)
-{
-	int m, polarity, sense;
-
-	m = (block[3]<<8)|block[2];
-	sense = 1<<((m & 0x000E)>>1);
-	if(m & 0x0080)
-		polarity = sense;
-	else
-		polarity = 0;
-
-	return (csr32r(ctlr, 12) & sense)^polarity;
-}
-
-static int
-type0mode(Ctlr* ctlr, uchar* block, int wait)
-{
-	int csr6, m, timeo;
-
-	csr6 = Sc|Mbo|Hbd|Ca|TrMODE|Sb;
-debug("type0: medium 0x%uX, fd %d: 0x%2.2uX 0x%2.2uX 0x%2.2uX 0x%2.2uX\n",
-    ctlr->medium, ctlr->fd, block[0], block[1], block[2], block[3]); 
-	switch(block[0]){
-	default:
-		break;
-
-	case 0x04:			/* 10BASE-TFD */
-	case 0x05:			/* 100BASE-TXFD */
-	case 0x08:			/* 100BASE-FXFD */
-		/*
-		 * Don't attempt full-duplex
-		 * unless explicitly requested.
-		 */
-		if(!ctlr->fd)
-			return -1;
-		csr6 |= Fd;
-		break;
-	}
-
-	m = (block[3]<<8)|block[2];
-	if(m & 0x0001)
-		csr6 |= Ps;
-	if(m & 0x0010)
-		csr6 |= Ttm;
-	if(m & 0x0020)
-		csr6 |= Pcs;
-	if(m & 0x0040)
-		csr6 |= Scr;
-
-	csr32w(ctlr, 12, block[1]);
-	microdelay(10);
-	csr32w(ctlr, 6, csr6);
-	ctlr->csr6 = csr6;
-
-	if(!wait)
-		return 0;
-
-	for(timeo = 0; timeo < 30; timeo++){
-		if(type0link(ctlr, block))
-			return 0;
-		delay(100);
-	}
-
-	return -1;
-}
-
-static int
-media21041(Ether* ether, int wait)
-{
-	Ctlr* ctlr;
-	uchar *block;
-	int csr6, csr13, csr14, csr15, medium, timeo;
-
-	ctlr = ether->ctlr;
-	block = ctlr->infoblock[ctlr->curk];
-	debug("media21041: block[0] %2.2uX, medium %4.4uX sct %4.4uX\n",
-		block[0], ctlr->medium, ctlr->sct);
-
-	medium = block[0] & 0x3F;
-	if(ctlr->medium >= 0 && medium != ctlr->medium)
-		return 0;
-	if(ctlr->sct != 0x0800 && (ctlr->sct & 0x3F) != medium)
-		return 0;
-
-	csr6 = Sc|Mbo|Ca|TrMODE|Sb;
-	if(block[0] & 0x40){
-		csr13 = (block[2]<<8)|block[1];
-		csr14 = (block[4]<<8)|block[3];
-		csr15 = (block[6]<<8)|block[5];
-	}
-	else switch(medium){
-	default:
-		return -1;
-	case 0x00:		/* 10BASE-T */
-		csr13 = 0xEF01;
-		csr14 = 0xFF3F;
-		csr15 = 0x0008;
-		break;
-	case 0x01:		/* 10BASE-2 */
-		csr13 = 0xEF09;
-		csr14 = 0xF73D;
-		csr15 = 0x0006;
-		break;
-	case 0x02:		/* 10BASE-5 */
-		csr13 = 0xEF09;
-		csr14 = 0xF73D;
-		csr15 = 0x000E;
-		break;
-	case 0x04:		/* 10BASE-TFD */
-		csr13 = 0xEF01;
-		csr14 = 0xFF3D;
-		csr15 = 0x0008;
-		break;
-	}
-
-	csr32w(ctlr, 13, 0);
-	csr32w(ctlr, 14, csr14);
-	csr32w(ctlr, 15, csr15);
-	csr32w(ctlr, 13, csr13);
-	delay(10);
-
-	if(medium == 0x04)
-		csr6 |= Fd;
-	ctlr->csr6 = csr6;
-	csr32w(ctlr, 6, ctlr->csr6);
-
-	debug("media21041: csr6 %8.8uX csr13 %4.4uX csr14 %4.4uX csr15 %4.4uX\n",
-		csr6, csr13, csr14, csr15);
-
-	if(!wait)
-		return 0;
-
-	for(timeo = 0; timeo < 30; timeo++){
-		if(!(csr32r(ctlr, 12) & 0x0002)){
-			debug("media21041: ok: csr12 %4.4luX timeo %d\n",
-				csr32r(ctlr, 12), timeo);
-			return 10;
-		}
-		delay(100);
-	}
-	debug("media21041: !ok: csr12 %4.4luX\n", csr32r(ctlr, 12));
-
-	return -1;
-}
-
-static int
-mediaxx(Ether* ether, int wait)
-{
-	Ctlr* ctlr;
-	uchar *block;
-
-	ctlr = ether->ctlr;
-	block = ctlr->infoblock[ctlr->curk];
-	if(block[0] & 0x80){
-		switch(block[1]){
-		default:
-			return -1;
-		case 0:
-			if(ctlr->medium >= 0 && block[2] != ctlr->medium)
-				return 0;
-/* need this test? */	if(ctlr->sct != 0x0800 && (ctlr->sct & 0x3F) != block[2])
-				return 0;
-			if(type0mode(ctlr, block+2, wait))
-				return 0;
-			break;
-		case 1:
-			if(typephymode(ctlr, block, wait))
-				return 0;
-			break;
-		case 2:
-			debug("type2: medium %d block[2] %d\n",
-				ctlr->medium, block[2]);
-			if(ctlr->medium >= 0 && ((block[2] & 0x3F) != ctlr->medium))
-				return 0;
-			if(type2mode(ctlr, block, wait))
-				return 0;
-			break;
-		case 3:
-			if(typephymode(ctlr, block, wait))
-				return 0;
-			break;
-		case 4:
-			debug("type4: medium %d block[2] %d\n",
-				ctlr->medium, block[2]);
-			if(ctlr->medium >= 0 && ((block[2] & 0x3F) != ctlr->medium))
-				return 0;
-			if(typesymmode(ctlr, block, wait))
-				return 0;
-			break;
-		}
-	}
-	else{
-		if(ctlr->medium >= 0 && block[0] != ctlr->medium)
-			return 0;
-/* need this test? */if(ctlr->sct != 0x0800 && (ctlr->sct & 0x3F) != block[0])
-			return 0;
-		if(type0mode(ctlr, block, wait))
-			return 0;
-	}
-
-	if(ctlr->csr6){
-		if(!(ctlr->csr6 & Ps) || (ctlr->csr6 & Ttm))
-			return 10;
-		return 100;
-	}
-
-	return 0;
-}
-
-static int
-media(Ether* ether, int wait)
-{
-	Ctlr* ctlr;
-	int k, mbps;
-
-	ctlr = ether->ctlr;
-	for(k = 0; k < ctlr->k; k++){
-		switch(ctlr->id){
-		default:
-			mbps = mediaxx(ether, wait);
-			break;
-		case Tulip1:			/* 21041 */
-			mbps = media21041(ether, wait);
-			break;
-		}
-		if(mbps > 0)
-			return mbps;
-		if(ctlr->curk == 0)
-			ctlr->curk = ctlr->k-1;
-		else
-			ctlr->curk--;
-	}
-
-	return 0;
-}
-
-static char* mediatable[9] = {
-	"10BASE-T",			/* TP */
-	"10BASE-2",			/* BNC */
-	"10BASE-5",			/* AUI */
-	"100BASE-TX",
-	"10BASE-TFD",
-	"100BASE-TXFD",
-	"100BASE-T4",
-	"100BASE-FX",
-	"100BASE-FXFD",
-};
-
-static uchar en1207[] = {		/* Accton EN1207-COMBO */
-	0x00, 0x00, 0xE8,		/* [0]  vendor ethernet code */
-	0x00,				/* [3]  spare */
-
-	0x00, 0x08,			/* [4]  connection (LSB+MSB = 0x0800) */
-	0x1F,				/* [6]  general purpose control */
-	2,				/* [7]  block count */
-
-	0x00,				/* [8]  media code (10BASE-TX) */
-	0x0B,				/* [9]  general purpose port data */
-	0x9E, 0x00,			/* [10] command (LSB+MSB = 0x009E) */
-
-	0x03,				/* [8]  media code (100BASE-TX) */
-	0x1B,				/* [9]  general purpose port data */
-	0x6D, 0x00,			/* [10] command (LSB+MSB = 0x006D) */
-
-					/* There is 10BASE-2 as well, but... */
-};
-
-static uchar ana6910fx[] = {		/* Adaptec (Cogent) ANA-6910FX */
-	0x00, 0x00, 0x92,		/* [0]  vendor ethernet code */
-	0x00,				/* [3]  spare */
-
-	0x00, 0x08,			/* [4]  connection (LSB+MSB = 0x0800) */
-	0x3F,				/* [6]  general purpose control */
-	1,				/* [7]  block count */
-
-	0x07,				/* [8]  media code (100BASE-FX) */
-	0x03,				/* [9]  general purpose port data */
-	0x2D, 0x00			/* [10] command (LSB+MSB = 0x000D) */
-};
-
-static uchar smc9332[] = {		/* SMC 9332 */
-	0x00, 0x00, 0xC0,		/* [0]  vendor ethernet code */
-	0x00,				/* [3]  spare */
-
-	0x00, 0x08,			/* [4]  connection (LSB+MSB = 0x0800) */
-	0x1F,				/* [6]  general purpose control */
-	2,				/* [7]  block count */
-
-	0x00,				/* [8]  media code (10BASE-TX) */
-	0x00,				/* [9]  general purpose port data */
-	0x9E, 0x00,			/* [10] command (LSB+MSB = 0x009E) */
-
-	0x03,				/* [8]  media code (100BASE-TX) */
-	0x09,				/* [9]  general purpose port data */
-	0x6D, 0x00,			/* [10] command (LSB+MSB = 0x006D) */
-};
-
-static uchar* leaf21140[] = {
-	en1207,				/* Accton EN1207-COMBO */
-	ana6910fx,			/* Adaptec (Cogent) ANA-6910FX */
-	smc9332,			/* SMC 9332 */
-	0,
-};
-
-/*
- * Copied to ctlr->srom at offset 20.
- */
-static uchar leafpnic[] = {
-	0x00, 0x00, 0x00, 0x00,		/* MAC address */
-	0x00, 0x00,
-	0x00,				/* controller 0 device number */
-	0x1E, 0x00,			/* controller 0 info leaf offset */
-	0x00,				/* reserved */
-	0x00, 0x08,			/* selected connection type */
-	0x00,				/* general purpose control */
-	0x01,				/* block count */
-
-	0x8C,				/* format indicator and count */
-	0x01,				/* block type */
-	0x00,				/* PHY number */
-	0x00,				/* GPR sequence length */
-	0x00,				/* reset sequence length */
-	0x00, 0x78,			/* media capabilities */
-	0xE0, 0x01,			/* Nway advertisment */
-	0x00, 0x50,			/* FDX bitmap */
-	0x00, 0x18,			/* TTM bitmap */
-};
-
-static int
-srom(Ctlr* ctlr)
-{
-	int i, k, oui, phy, x;
-	uchar *p;
-
-	/*
-	 * This is a partial decoding of the SROM format described in
-	 * 'Digital Semiconductor 21X4 Serial ROM Format, Version 4.05,
-	 * 2-Mar-98'. Only the 2114[03] are handled, support for other
-	 * controllers can be added as needed.
-	 */
-	sromr(ctlr, 0);
-	if(ctlr->srom == nil)
-		ctlr->srom = malloc((1<<ctlr->sromsz)*sizeof(ushort));
-	for(i = 0; i < (1<<ctlr->sromsz); i++){
-		x = sromr(ctlr, i);
-		ctlr->srom[2*i] = x;
-		ctlr->srom[2*i+1] = x>>8;
-	}
-
-	if(DEBUG){
-		print("srom:");
-		for(i = 0; i < ((1<<ctlr->sromsz)*sizeof(ushort)); i++){
-			if(i && ((i & 0x0F) == 0))
-				print("\n     ");
-			print(" %2.2uX", ctlr->srom[i]);
-		}
-		print("\n");
-	}
-
-	/*
-	 * There are 2 SROM layouts:
-	 *	e.g. Digital EtherWORKS	station address at offset 20;
-	 *				this complies with the 21140A SROM
-	 *				application note from Digital;
-	 * 	e.g. SMC9332		station address at offset 0 followed by
-	 *				2 additional bytes, repeated at offset
-	 *				6; the 8 bytes are also repeated in
-	 *				reverse order at offset 8.
-	 * To check which it is, read the SROM and check for the repeating
-	 * patterns of the non-compliant cards; if that fails use the one at
-	 * offset 20.
-	 */
-	ctlr->sromea = ctlr->srom;
-	for(i = 0; i < 8; i++){
-		x = ctlr->srom[i];
-		if(x != ctlr->srom[15-i] || x != ctlr->srom[16+i]){
-			ctlr->sromea = &ctlr->srom[20];
-			break;
-		}
-	}
-
-	/*
-	 * Fake up the SROM for the PNIC.
-	 * It looks like a 21140 with a PHY.
-	 * The MAC address is byte-swapped in the orginal SROM data.
-	 */
-	if(ctlr->id == Pnic){
-		memmove(&ctlr->srom[20], leafpnic, sizeof(leafpnic));
-		for(i = 0; i < Eaddrlen; i += 2){
-			ctlr->srom[20+i] = ctlr->srom[i+1];
-			ctlr->srom[20+i+1] = ctlr->srom[i];
-		}
-	}
-
-	/*
-	 * Next, try to find the info leaf in the SROM for media detection.
-	 * If it's a non-conforming card try to match the vendor ethernet code
-	 * and point p at a fake info leaf with compact 21140 entries.
-	 */
-	if(ctlr->sromea == ctlr->srom){
-		p = nil;
-		for(i = 0; leaf21140[i] != nil; i++){
-			if(memcmp(leaf21140[i], ctlr->sromea, 3) == 0){
-				p = &leaf21140[i][4];
-				break;
-			}
-		}
-		if(p == nil)
-			return -1;
-	}
-	else
-		p = &ctlr->srom[(ctlr->srom[28]<<8)|ctlr->srom[27]];
-
-	/*
-	 * Set up the info needed for later media detection.
-	 * For the 21140, set the general-purpose mask in CSR12.
-	 * The info block entries are stored in order of increasing
-	 * precedence, so detection will work backwards through the
-	 * stored indexes into ctlr->srom.
-	 * If an entry is found which matches the selected connection
-	 * type, save the index. Otherwise, start at the last entry.
-	 * If any MII entries are found (type 1 and 3 blocks), scan
-	 * for PHYs.
-	 */
-	ctlr->leaf = p;
-	ctlr->sct = *p++;
-	ctlr->sct |= *p++<<8;
-	if(ctlr->id != Tulip3 && ctlr->id != Tulip1){
-		csr32w(ctlr, 12, Gpc|*p++);
-		delay(200);
-	}
-	ctlr->k = *p++;
-	if(ctlr->k >= nelem(ctlr->infoblock))
-		ctlr->k = nelem(ctlr->infoblock)-1;
-	ctlr->sctk = ctlr->k-1;
-	phy = 0;
-	for(k = 0; k < ctlr->k; k++){
-		ctlr->infoblock[k] = p;
-		if(ctlr->id == Tulip1){
-			debug("type21041: 0x%2.2uX\n", p[0]); 
-			if(ctlr->sct != 0x0800 && *p == (ctlr->sct & 0xFF))
-				ctlr->sctk = k;
-			if(*p & 0x40)
-				p += 7;
-			else
-				p += 1;
-		}
-		/*
-		 * The RAMIX PMC665 has a badly-coded SROM,
-		 * hence the test for 21143 and type 3.
-		 */
-		else if((*p & 0x80) || (ctlr->id == Tulip3 && *(p+1) == 3)){
-			*p |= 0x80;
-			if(*(p+1) == 1 || *(p+1) == 3)
-				phy = 1;
-			if(*(p+1) == 5)
-				ctlr->type5block = p;
-			p += (*p & ~0x80)+1;
-		}
-		else{
-			debug("type0: 0x%2.2uX 0x%2.2uX 0x%2.2uX 0x%2.2uX\n",
-				p[0], p[1], p[2], p[3]); 
-			if(ctlr->sct != 0x0800 && *p == (ctlr->sct & 0xFF))
-				ctlr->sctk = k;
-			p += 4;
-		}
-	}
-	ctlr->curk = ctlr->sctk;
-	debug("sct 0x%uX medium 0x%uX k %d curk %d phy %d\n",
-		ctlr->sct, ctlr->medium, ctlr->k, ctlr->curk, phy);
-
-	if(phy){
-		x = 0;
-		for(k = 0; k < nelem(ctlr->phy); k++){
-			if((oui = miir(ctlr, k, 2)) == -1 || oui == 0)
-				continue;
-			if(DEBUG){
-				oui = (oui & 0x3FF)<<6;
-				oui |= miir(ctlr, k, 3)>>10;
-				miir(ctlr, k, 1);
-				debug("phy%d: index %d oui %uX reg1 %uX\n",
-					x, k, oui, miir(ctlr, k, 1));
-				USED(oui);
-			}
-			ctlr->phy[x] = k;
-		}
-	}
-
-	ctlr->fd = 0;
-	ctlr->medium = -1;
-
-	return 0;
-}
-
-static void
-dec2114xpci(void)
-{
-	Ctlr *ctlr;
-	Pcidev *p;
-	int x;
-
-	p = nil;
-	while(p = pcimatch(p, 0, 0)){
-		if(p->ccrb != 0x02 || p->ccru != 0)
-			continue;
-		switch((p->did<<16)|p->vid){
-		default:
-			continue;
-
-		case Tulip3:			/* 21143 */
-			/*
-			 * Exit sleep mode.
-			 */
-			x = pcicfgr32(p, 0x40);
-			x &= ~0xC0000000;
-			pcicfgw32(p, 0x40, x);
-			/*FALLTHROUGH*/
-
-		case Pnic:			/* PNIC */
-		case Pnic2:			/* PNIC-II */
-		case Tulip0:			/* 21140 */
-		case Tulip1:			/* 21041 */
-			break;
-		}
-
-		/*
-		 * bar[0] is the I/O port register address and
-		 * bar[1] is the memory-mapped register address.
-		 */
-		ctlr = malloc(sizeof(Ctlr));
-		ctlr->port = p->mem[0].bar & ~0x01;
-		ctlr->pcidev = p;
-		ctlr->id = (p->did<<16)|p->vid;
-		debug("2114x: type 0x%8.8uX rev 0x%4.4uX at port 0x%4.4uX\n",
-			ctlr->id, p->rid, ctlr->port);
-
-		/*
-		 * Some cards (e.g. ANA-6910FX) seem to need the Ps bit
-		 * set or they don't always work right after a hardware
-		 * reset.
-		 */
-		csr32w(ctlr, 6, Mbo|Ps);
-		softreset(ctlr);
-
-		if(srom(ctlr)){
-			free(ctlr);
-			break;
-		}
-
-		switch(ctlr->id){
-		default:
-			break;
-
-		case Pnic:			/* PNIC */
-			/*
-			 * Turn off the jabber timer.
-			 */
-			csr32w(ctlr, 15, 0x00000001);
-			break;
-		}
-
-		if(ctlrhead != nil)
-			ctlrtail->next = ctlr;
-		else
-			ctlrhead = ctlr;
-		ctlrtail = ctlr;
-	}
-}
-
-static void
-detach(Ether* ether)
-{
-	softreset(ether->ctlr);
-}
-
-int
-ether2114xreset(Ether* ether)
-{
-	Ctlr *ctlr;
-	int i, x;
-	uchar ea[Eaddrlen];
-	static int scandone;
-
-	if(scandone == 0){
-		dec2114xpci();
-		scandone = 1;
-	}
-
-	/*
-	 * Any adapter matches if no ether->port is supplied,
-	 * otherwise the ports must match.
-	 */
-	for(ctlr = ctlrhead; ctlr != nil; ctlr = ctlr->next){
-		if(ctlr->active)
-			continue;
-		if(ether->port == 0 || ether->port == ctlr->port){
-			ctlr->active = 1;
-			break;
-		}
-	}
-	if(ctlr == nil)
-		return -1;
-
-	ether->ctlr = ctlr;
-	ether->port = ctlr->port;
-	ether->irq = ctlr->pcidev->intl;
-	ether->tbdf = ctlr->pcidev->tbdf;
-
-	/*
-	 * Check if the adapter's station address is to be overridden.
-	 * If not, read it from the EEPROM and set in ether->ea prior to
-	 * loading the station address in the hardware.
-	 */
-	memset(ea, 0, Eaddrlen);
-	if(memcmp(ea, ether->ea, Eaddrlen) == 0)
-		memmove(ether->ea, ctlr->sromea, Eaddrlen);
-
-	/*
-	 * Look for a medium override in case there's no autonegotiation
-	 * (no MII) or the autonegotiation fails.
-	 */
-	for(i = 0; i < ether->nopt; i++){
-		if(cistrcmp(ether->opt[i], "FD") == 0){
-			ctlr->fd = 1;
-			continue;
-		}
-		for(x = 0; x < nelem(mediatable); x++){
-			debug("compare <%s> <%s>\n", mediatable[x],
-				ether->opt[i]);
-			if(cistrcmp(mediatable[x], ether->opt[i]))
-				continue;
-			ctlr->medium = x;
-	
-			switch(ctlr->medium){
-			default:
-				ctlr->fd = 0;
-				break;
-	
-			case 0x04:		/* 10BASE-TFD */
-			case 0x05:		/* 100BASE-TXFD */
-			case 0x08:		/* 100BASE-FXFD */
-				ctlr->fd = 1;
-				break;
-			}
-			break;
-		}
-	}
-
-	/*
-	 * Determine media.
-	 */
-	ctlr->mbps = media(ether, 1);
-
-	/*
-	 * Initialise descriptor rings, ethernet address.
-	 */
-	ctlr->nrdr = Nrde;
-	ctlr->ntdr = Ntde;
-	pcisetbme(ctlr->pcidev);
-	ctlrinit(ether);
-
-	/*
-	 * Linkage to the generic ethernet driver.
-	 */
-	ether->attach = attach;
-	ether->transmit = transmit;
-	ether->interrupt = interrupt;
-	ether->detach = detach;
-
-	return 0;
-}
--- a/os/boot/pc/ether589.c
+++ /dev/null
@@ -1,211 +1,0 @@
-/*
- * 3C589 and 3C562.
- * To do:
- *	check xcvr10Base2 still works (is GlobalReset necessary?).
- */
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-#include "error.h"
-
-#include "etherif.h"
-
-enum {						/* all windows */
-	CommandR		= 0x000E,
-	IntStatusR		= 0x000E,
-};
-
-enum {						/* Commands */
-	GlobalReset		= 0x0000,
-	SelectRegisterWindow	= 0x0001,
-	RxReset			= 0x0005,
-	TxReset			= 0x000B,
-	AcknowledgeInterrupt	= 0x000D,
-};
-
-enum {						/* IntStatus bits */
-	commandInProgress	= 0x1000,
-};
-
-#define COMMAND(port, cmd, a)	outs((port)+CommandR, ((cmd)<<11)|(a))
-#define STATUS(port)		ins((port)+IntStatusR)
-
-enum {						/* Window 0 - setup */
-	Wsetup			= 0x0000,
-						/* registers */
-	ManufacturerID		= 0x0000,	/* 3C5[08]*, 3C59[27] */
-	ProductID		= 0x0002,	/* 3C5[08]*, 3C59[27] */
-	ConfigControl		= 0x0004,	/* 3C5[08]*, 3C59[27] */
-	AddressConfig		= 0x0006,	/* 3C5[08]*, 3C59[27] */
-	ResourceConfig		= 0x0008,	/* 3C5[08]*, 3C59[27] */
-	EepromCommand		= 0x000A,
-	EepromData		= 0x000C,
-						/* AddressConfig Bits */
-	autoSelect9		= 0x0080,
-	xcvrMask9		= 0xC000,
-						/* ConfigControl bits */
-	Ena			= 0x0001,
-	base10TAvailable9	= 0x0200,
-	coaxAvailable9		= 0x1000,
-	auiAvailable9		= 0x2000,
-						/* EepromCommand bits */
-	EepromReadRegister	= 0x0080,
-	EepromBusy		= 0x8000,
-};
-
-enum {						/* Window 1 - operating set */
-	Wop			= 0x0001,
-};
-
-enum {						/* Window 3 - FIFO management */
-	Wfifo			= 0x0003,
-						/* registers */
-	InternalConfig		= 0x0000,	/* 3C509B, 3C589, 3C59[0257] */
-						/* InternalConfig bits */
-	xcvr10BaseT		= 0x00000000,
-	xcvr10Base2		= 0x00300000,
-};
-
-enum {						/* Window 4 - diagnostic */
-	Wdiagnostic		= 0x0004,
-						/* registers */
-	MediaStatus		= 0x000A,
-						/* MediaStatus bits */
-	linkBeatDetect		= 0x0800,
-};
-
-extern int elnk3reset(Ether*);
-
-static char *tcmpcmcia[] = {
-	"3C589",			/* 3COM 589[ABCD] */
-	"3C562",			/* 3COM 562 */
-	"589E",				/* 3COM Megahertz 589E */
-	nil,
-};
-
-static int
-configASIC(Ether* ether, int port, int xcvr)
-{
-	int x;
-
-	/* set Window 0 configuration registers */
-	COMMAND(port, SelectRegisterWindow, Wsetup);
-	outs(port+ConfigControl, Ena);
-
-	/* IRQ must be 3 on 3C589/3C562 */
-	outs(port + ResourceConfig, 0x3F00);
-
-	x = ins(port+AddressConfig) & ~xcvrMask9;
-	x |= (xcvr>>20)<<14;
-	outs(port+AddressConfig, x);
-
-	COMMAND(port, TxReset, 0);
-	while(STATUS(port) & commandInProgress)
-		;
-	COMMAND(port, RxReset, 0);
-	while(STATUS(port) & commandInProgress)
-		;
-
-	return elnk3reset(ether);
-}
-
-int
-ether589reset(Ether* ether)
-{
-	int i, t, slot;
-	char *type;
-	int port;
-	enum { WantAny, Want10BT, Want10B2 };
-	int want;
-	uchar ea[6];
-	char *p;
-
-	if(ether->irq == 0)
-		ether->irq = 10;
-	if(ether->port == 0)
-		ether->port = 0x240;
-	port = ether->port;
-
-//	if(ioalloc(port, 0x10, 0, "3C589") < 0)
-//		return -1;
-
-	type = nil;
-	slot = -1;
-	for(i = 0; tcmpcmcia[i] != nil; i++){
-		type = tcmpcmcia[i];
-if(debug) print("try %s...", type);
-		if((slot = pcmspecial(type, ether)) >= 0)
-			break;
-	}
-	if(slot < 0){
-if(debug) print("none found\n");
-//		iofree(port);
-		return -1;
-	}
-
-	/*
-	 * Read Ethernet address from card memory
-	 * on 3C562, but only if the user has not 
-	 * overridden it.
-	 */
-	memset(ea, 0, sizeof ea);
-	if(memcmp(ea, ether->ea, 6) == 0 && strcmp(type, "3C562") == 0) {
-		if(debug)
-			print("read 562...");
-		if(pcmcistuple(slot, 0x88, -1, ea, 6) == 6) {
-			for(i = 0; i < 6; i += 2){
-				t = ea[i];
-				ea[i] = ea[i+1];
-				ea[i+1] = t;
-			}
-			memmove(ether->ea, ea, 6);
-			if(debug)
-				print("ea %E", ea);
-		}
-	}
-	/*
-	 * Allow user to specify desired media in plan9.ini
-	 */
-	want = WantAny;
-	for(i = 0; i < ether->nopt; i++){
-		if(cistrncmp(ether->opt[i], "media=", 6) != 0)
-			continue;
-		p = ether->opt[i]+6;
-		if(cistrcmp(p, "10base2") == 0)
-			want = Want10B2;
-		else if(cistrcmp(p, "10baseT") == 0)
-			want = Want10BT;
-	}
-	
-	/* try configuring as a 10BaseT */
-	if(want==WantAny || want==Want10BT){
-		if(configASIC(ether, port, xcvr10BaseT) < 0){
-			pcmspecialclose(slot);
-//			iofree(port);
-			return -1;
-		}
-		delay(100);
-		COMMAND(port, SelectRegisterWindow, Wdiagnostic);
-		if((ins(port+MediaStatus)&linkBeatDetect) || want==Want10BT){
-			COMMAND(port, SelectRegisterWindow, Wop);
-			print("#l%d: xcvr10BaseT %s\n", ether->ctlrno, type);
-			return 0;
-		}
-	}
-
-	/* try configuring as a 10base2 */
-	if(want==WantAny || want==Want10B2){
-		COMMAND(port, GlobalReset, 0);
-		if(configASIC(ether, port, xcvr10Base2) < 0){
-			pcmspecialclose(slot);
-//			iofree(port);
-			return -1;
-		}
-		print("#l%d: xcvr10Base2 %s\n", ether->ctlrno, type);
-		return 0;
-	}
-	return -1;		/* not reached */
-}
--- a/os/boot/pc/ether79c970.c
+++ /dev/null
@@ -1,539 +1,0 @@
-/*
- * AMD79C970
- * PCnet-PCI Single-Chip Ethernet Controller for PCI Local Bus
- * To do:
- *	finish this rewrite
- */
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-#include "etherif.h"
-
-enum {
-	Lognrdre	= 6,
-	Nrdre		= (1<<Lognrdre),/* receive descriptor ring entries */
-	Logntdre	= 4,
-	Ntdre		= (1<<Logntdre),/* transmit descriptor ring entries */
-
-	Rbsize		= ETHERMAXTU+4,	/* ring buffer size (+4 for CRC) */
-};
-
-enum {					/* DWIO I/O resource map */
-	Aprom		= 0x0000,	/* physical address */
-	Rdp		= 0x0010,	/* register data port */
-	Rap		= 0x0014,	/* register address port */
-	Sreset		= 0x0018,	/* software reset */
-	Bdp		= 0x001C,	/* bus configuration register data port */
-};
-
-enum {					/* CSR0 */
-	Init		= 0x0001,	/* begin initialisation */
-	Strt		= 0x0002,	/* enable chip */
-	Stop		= 0x0004,	/* disable chip */
-	Tdmd		= 0x0008,	/* transmit demand */
-	Txon		= 0x0010,	/* transmitter on */
-	Rxon		= 0x0020,	/* receiver on */
-	Iena		= 0x0040,	/* interrupt enable */
-	Intr		= 0x0080,	/* interrupt flag */
-	Idon		= 0x0100,	/* initialisation done */
-	Tint		= 0x0200,	/* transmit interrupt */
-	Rint		= 0x0400,	/* receive interrupt */
-	Merr		= 0x0800,	/* memory error */
-	Miss		= 0x1000,	/* missed frame */
-	Cerr		= 0x2000,	/* collision */
-	Babl		= 0x4000,	/* transmitter timeout */
-	Err		= 0x8000,	/* Babl|Cerr|Miss|Merr */
-};
-	
-enum {					/* CSR3 */
-	Bswp		= 0x0004,	/* byte swap */
-	Emba		= 0x0008,	/* enable modified back-off algorithm */
-	Dxmt2pd		= 0x0010,	/* disable transmit two part deferral */
-	Lappen		= 0x0020,	/* look-ahead packet processing enable */
-};
-
-enum {					/* CSR4 */
-	ApadXmt		= 0x0800,	/* auto pad transmit */
-};
-
-enum {					/* CSR15 */
-	Prom		= 0x8000,	/* promiscuous mode */
-};
-
-typedef struct {			/* Initialisation Block */
-	ushort	mode;
-	uchar	rlen;			/* upper 4 bits */
-	uchar	tlen;			/* upper 4 bits */
-	uchar	padr[6];
-	uchar	res[2];
-	uchar	ladr[8];
-	ulong	rdra;
-	ulong	tdra;
-} Iblock;
-
-typedef struct {			/* descriptor ring entry */
-	ulong	addr;
-	ulong	md1;			/* status|bcnt */
-	ulong	md2;			/* rcc|rpc|mcnt */
-	void*	data;
-} Dre;
-
-enum {					/* md1 */
-	Enp		= 0x01000000,	/* end of packet */
-	Stp		= 0x02000000,	/* start of packet */
-	RxBuff		= 0x04000000,	/* buffer error */
-	Def		= 0x04000000,	/* deferred */
-	Crc		= 0x08000000,	/* CRC error */
-	One		= 0x08000000,	/* one retry needed */
-	Oflo		= 0x10000000,	/* overflow error */
-	More		= 0x10000000,	/* more than one retry needed */
-	Fram		= 0x20000000,	/* framing error */
-	RxErr		= 0x40000000,	/* Fram|Oflo|Crc|RxBuff */
-	TxErr		= 0x40000000,	/* Uflo|Lcol|Lcar|Rtry */
-	Own		= 0x80000000,
-};
-
-enum {					/* md2 */
-	Rtry		= 0x04000000,	/* failed after repeated retries */
-	Lcar		= 0x08000000,	/* loss of carrier */
-	Lcol		= 0x10000000,	/* late collision */
-	Uflo		= 0x40000000,	/* underflow error */
-	TxBuff		= 0x80000000,	/* buffer error */
-};
-
-typedef struct Ctlr Ctlr;
-struct Ctlr {
-	Lock;
-	int	port;
-	Pcidev*	pcidev;
-	Ctlr*	next;
-	int	active;
-
-	int	init;			/* initialisation in progress */
-	Iblock	iblock;
-
-	Dre*	rdr;			/* receive descriptor ring */
-	int	rdrx;
-
-	Dre*	tdr;			/* transmit descriptor ring */
-	int	tdrh;			/* host index into tdr */
-	int	tdri;			/* interface index into tdr */
-	int	ntq;			/* descriptors active */
-
-	ulong	rxbuff;			/* receive statistics */
-	ulong	crc;
-	ulong	oflo;
-	ulong	fram;
-
-	ulong	rtry;			/* transmit statistics */
-	ulong	lcar;
-	ulong	lcol;
-	ulong	uflo;
-	ulong	txbuff;
-
-	ulong	merr;			/* bobf is such a whiner */
-	ulong	miss;
-	ulong	babl;
-
-	int		(*ior)(Ctlr*, int);
-	void		(*iow)(Ctlr*, int, int);
-};
-
-static Ctlr* ctlrhead;
-static Ctlr* ctlrtail;
-
-/*
- * The Rdp, Rap, Sreset, Bdp ports are 32-bit port offset in the enumeration above.
- * To get to 16-bit offsets, scale down with 0x10 staying the same.
- */
-static int
-io16r(Ctlr* c, int r)
-{
-	if(r >= Rdp)
-		r = (r-Rdp)/2+Rdp;
-	return ins(c->port+r);
-}
-
-static void
-io16w(Ctlr* c, int r, int v)
-{
-	if(r >= Rdp)
-		r = (r-Rdp)/2+Rdp;
-	outs(c->port+r, v);
-}
-
-static int
-io32r(Ctlr* c, int r)
-{
-	return inl(c->port+r);
-}
-
-static void
-io32w(Ctlr* c, int r, int v)
-{
-	outl(c->port+r, v);
-}
-
-static void
-attach(Ether*)
-{
-}
-
-static void
-detach(Ether* ether)
-{
-	Ctlr *ctlr;
-
-	ctlr = ether->ctlr;
-	ctlr->iow(ctlr, Rdp, Iena|Stop);
-}
-
-static void
-ringinit(Ctlr* ctlr)
-{
-	Dre *dre;
-
-	/*
-	 * Initialise the receive and transmit buffer rings.
-	 * The ring entries must be aligned on 16-byte boundaries.
-	 *
-	 * This routine is protected by ctlr->init.
-	 */
-	if(ctlr->rdr == 0){
-		ctlr->rdr = ialloc(Nrdre*sizeof(Dre), 0x10);
-		for(dre = ctlr->rdr; dre < &ctlr->rdr[Nrdre]; dre++){
-			dre->data = malloc(Rbsize);
-			dre->addr = PADDR(dre->data);
-			dre->md2 = 0;
-			dre->md1 = Own|(-Rbsize & 0xFFFF);
-		}
-	}
-	ctlr->rdrx = 0;
-
-	if(ctlr->tdr == 0)
-		ctlr->tdr = ialloc(Ntdre*sizeof(Dre), 0x10);
-	memset(ctlr->tdr, 0, Ntdre*sizeof(Dre));
-	ctlr->tdrh = ctlr->tdri = 0;
-}
-
-static void
-transmit(Ether* ether)
-{
-	Ctlr *ctlr;
-	Block *bp;
-	Dre *dre;
-	RingBuf *tb;
-
-	ctlr = ether->ctlr;
-
-	if(ctlr->init)
-		return;
-
-	while(ctlr->ntq < (Ntdre-1)){
-		tb = &ether->tb[ether->ti];
-		if(tb->owner != Interface)
-			break;
-
-		bp = allocb(tb->len);
-		memmove(bp->wp, tb->pkt, tb->len);
-		memmove(bp->wp+Eaddrlen, ether->ea, Eaddrlen);
-		bp->wp += tb->len;
-
-		/*
-		 * Give ownership of the descriptor to the chip,
-		 * increment the software ring descriptor pointer
-		 * and tell the chip to poll.
-		 * There's no need to pad to ETHERMINTU
-		 * here as ApadXmt is set in CSR4.
-		 */
-		dre = &ctlr->tdr[ctlr->tdrh];
-		dre->data = bp;
-		dre->addr = PADDR(bp->rp);
-		dre->md2 = 0;
-		dre->md1 = Own|Stp|Enp|Oflo|(-BLEN(bp) & 0xFFFF);
-		ctlr->ntq++;
-		ctlr->iow(ctlr, Rap, 0);
-		ctlr->iow(ctlr, Rdp, Iena|Tdmd);
-		ctlr->tdrh = NEXT(ctlr->tdrh, Ntdre);
-
-		tb->owner = Host;
-		ether->ti = NEXT(ether->ti, ether->ntb);
-	}
-}
-
-static void
-interrupt(Ureg*, void* arg)
-{
-	Ctlr *ctlr;
-	Ether *ether;
-	int csr0;
-	Dre *dre;
-	RingBuf *rb;
-
-	ether = arg;
-	ctlr = ether->ctlr;
-
-	/*
-	 * Acknowledge all interrupts and whine about those that shouldn't
-	 * happen.
-	 */
-intrloop:
-	csr0 = ctlr->ior(ctlr, Rdp) & 0xFFFF;
-	ctlr->iow(ctlr, Rdp, Babl|Cerr|Miss|Merr|Rint|Tint|Iena);
-	if(csr0 & Merr)
-		ctlr->merr++;
-	if(csr0 & Miss)
-		ctlr->miss++;
-	if(csr0 & Babl)
-		ctlr->babl++;
-	//if(csr0 & (Babl|Miss|Merr))
-	//	print("#l%d: csr0 = 0x%uX\n", ether->ctlrno, csr0);
-	if(!(csr0 & (Rint|Tint)))
-		return;
-
-	/*
-	 * Receiver interrupt: run round the descriptor ring logging
-	 * errors and passing valid receive data up to the higher levels
-	 * until a descriptor is encountered still owned by the chip.
-	 */
-	if(csr0 & Rint){
-		dre = &ctlr->rdr[ctlr->rdrx];
-		while(!(dre->md1 & Own)){
-			rb = &ether->rb[ether->ri];
-			if(dre->md1 & RxErr){
-				if(dre->md1 & RxBuff)
-					ctlr->rxbuff++;
-				if(dre->md1 & Crc)
-					ctlr->crc++;
-				if(dre->md1 & Oflo)
-					ctlr->oflo++;
-				if(dre->md1 & Fram)
-					ctlr->fram++;
-			}
-			else if(rb->owner == Interface){
-				rb->owner = Host;
-				rb->len = (dre->md2 & 0x0FFF)-4;
-				memmove(rb->pkt, dre->data, rb->len);
-				ether->ri = NEXT(ether->ri, ether->nrb);
-			}
-
-			/*
-			 * Finished with this descriptor, reinitialise it,
-			 * give it back to the chip, then on to the next...
-			 */
-			dre->md2 = 0;
-			dre->md1 = Own|(-Rbsize & 0xFFFF);
-
-			ctlr->rdrx = NEXT(ctlr->rdrx, Nrdre);
-			dre = &ctlr->rdr[ctlr->rdrx];
-		}
-	}
-
-	/*
-	 * Transmitter interrupt: wakeup anyone waiting for a free descriptor.
-	 */
-	if(csr0 & Tint){
-		lock(ctlr);
-		while(ctlr->ntq){
-			dre = &ctlr->tdr[ctlr->tdri];
-			if(dre->md1 & Own)
-				break;
-	
-			if(dre->md1 & TxErr){
-				if(dre->md2 & Rtry)
-					ctlr->rtry++;
-				if(dre->md2 & Lcar)
-					ctlr->lcar++;
-				if(dre->md2 & Lcol)
-					ctlr->lcol++;
-				if(dre->md2 & Uflo)
-					ctlr->uflo++;
-				if(dre->md2 & TxBuff)
-					ctlr->txbuff++;
-			}
-	
-			freeb(dre->data);
-	
-			ctlr->ntq--;
-			ctlr->tdri = NEXT(ctlr->tdri, Ntdre);
-		}
-		transmit(ether);
-		unlock(ctlr);
-	}
-	goto intrloop;
-}
-
-static void
-amd79c970pci(void)
-{
-	Ctlr *ctlr;
-	Pcidev *p;
-
-	p = nil;
-	while(p = pcimatch(p, 0x1022, 0x2000)){
-		ctlr = malloc(sizeof(Ctlr));
-		ctlr->port = p->mem[0].bar & ~0x01;
-		ctlr->pcidev = p;
-
-		if(ctlrhead != nil)
-			ctlrtail->next = ctlr;
-		else
-			ctlrhead = ctlr;
-		ctlrtail = ctlr;
-	}
-}
-
-int
-amd79c970reset(Ether* ether)
-{
-	int x;
-	uchar ea[Eaddrlen];
-	Ctlr *ctlr;
-
-	if(ctlrhead == nil)
-		amd79c970pci();
-
-	/*
-	 * Any adapter matches if no port is supplied,
-	 * otherwise the ports must match.
-	 */
-	for(ctlr = ctlrhead; ctlr != nil; ctlr = ctlr->next){
-		if(ctlr->active)
-			continue;
-		if(ether->port == 0 || ether->port == ctlr->port){
-			ctlr->active = 1;
-			break;
-		}
-	}
-	if(ctlr == nil)
-		return -1;
-
-	/*
-	 * Allocate a controller structure and start to initialise it.
-	 */
-	ether->ctlr = ctlr;
-	ether->port = ctlr->port;
-	ether->irq = ctlr->pcidev->intl;
-	ether->tbdf = ctlr->pcidev->tbdf;
-	pcisetbme(ctlr->pcidev);
-	ilock(ctlr);
-	ctlr->init = 1;
-
-	io32r(ctlr, Sreset);
-	io16r(ctlr, Sreset);
-
-	if(io16w(ctlr, Rap, 0), io16r(ctlr, Rdp) == 4){
-		ctlr->ior = io16r;
-		ctlr->iow = io16w;
-	}else if(io32w(ctlr, Rap, 0), io32r(ctlr, Rdp) == 4){
-		ctlr->ior = io32r;
-		ctlr->iow = io32w;
-	}else{
-		print("#l%d: card doesn't talk right\n", ether->ctlrno);
-		iunlock(ctlr);
-		return -1;
-	}
-
-	ctlr->iow(ctlr, Rap, 88);
-	x = ctlr->ior(ctlr, Rdp);
-	ctlr->iow(ctlr, Rap, 89);
-	x |= ctlr->ior(ctlr, Rdp)<<16;
-
-	switch(x&0xFFFFFFF){
-	case 0x2420003:	/* PCnet/PCI 79C970 */
-	case 0x2621003:	/* PCnet/PCI II 79C970A */
-		break;
-	default:
-		print("unknown PCnet card version %.7ux\n", x&0xFFFFFFF);
-		iunlock(ctlr);
-		return -1;
-	}
-
-	/*
-	 * Set the software style in BCR20 to be PCnet-PCI to ensure 32-bit access.
-	 * Set the auto pad transmit in CSR4.
-	 */
-	ctlr->iow(ctlr, Rap, 20);
-	ctlr->iow(ctlr, Bdp, 0x0002);
-
-	ctlr->iow(ctlr, Rap, 4);
-	x = ctlr->ior(ctlr, Rdp) & 0xFFFF;
-	ctlr->iow(ctlr, Rdp, ApadXmt|x);
-
-	ctlr->iow(ctlr, Rap, 0);
-
-	/*
-	 * Check if the adapter's station address is to be overridden.
-	 * If not, read it from the I/O-space and set in ether->ea prior to
-	 * loading the station address in the initialisation block.
-	 */
-	memset(ea, 0, Eaddrlen);
-	if(!memcmp(ea, ether->ea, Eaddrlen)){
-		x = ctlr->ior(ctlr, Aprom);
-		ether->ea[0] = x;
-		ether->ea[1] = x>>8;
-		if(ctlr->ior == io16r)
-			x = ctlr->ior(ctlr, Aprom+2);
-		else
-			x >>= 16;
-		ether->ea[2] = x;
-		ether->ea[3] = x>>8;
-		x = ctlr->ior(ctlr, Aprom+4);
-		ether->ea[4] = x;
-		ether->ea[5] = x>>8;
-	}
-
-	/*
-	 * Start to fill in the initialisation block
-	 * (must be DWORD aligned).
-	 */
-	ctlr->iblock.rlen = Lognrdre<<4;
-	ctlr->iblock.tlen = Logntdre<<4;
-	memmove(ctlr->iblock.padr, ether->ea, sizeof(ctlr->iblock.padr));
-
-	ringinit(ctlr);
-	ctlr->iblock.rdra = PADDR(ctlr->rdr);
-	ctlr->iblock.tdra = PADDR(ctlr->tdr);
-
-	/*
-	 * Point the chip at the initialisation block and tell it to go.
-	 * Mask the Idon interrupt and poll for completion. Strt and interrupt
-	 * enables will be set later when attaching to the network.
-	 */
-	x = PADDR(&ctlr->iblock);
-	ctlr->iow(ctlr, Rap, 1);
-	ctlr->iow(ctlr, Rdp, x & 0xFFFF);
-	ctlr->iow(ctlr, Rap, 2);
-	ctlr->iow(ctlr, Rdp, (x>>16) & 0xFFFF);
-	ctlr->iow(ctlr, Rap, 3);
-	ctlr->iow(ctlr, Rdp, Idon);
-	ctlr->iow(ctlr, Rap, 0);
-	ctlr->iow(ctlr, Rdp, Init);
-
-	while(!(ctlr->ior(ctlr, Rdp) & Idon))
-		;
-
-	/*
-	 * We used to set CSR0 to Idon|Stop here, and then
-	 * in attach change it to Iena|Strt.  Apparently the simulated
-	 * 79C970 in VMware never enables after a write of Idon|Stop,
-	 * so we enable the device here now.
-	 */
-	ctlr->iow(ctlr, Rdp, Iena|Strt);
-	ctlr->init = 0;
-	iunlock(ctlr);
-
-	/*
-	 * Linkage to the generic ethernet driver.
-	 */
-	ether->attach = attach;
-	ether->transmit = transmit;
-	ether->interrupt = interrupt;
-	ether->detach = detach;
-
-	return 0;
-}
--- a/os/boot/pc/ether8003.c
+++ /dev/null
@@ -1,258 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-#include "etherif.h"
-#include "ether8390.h"
-
-/*
- * Western Digital/Standard Microsystems Corporation cards (WD80[01]3).
- * Also handles 8216 cards (Elite Ultra).
- * Configuration code based on that provided by SMC a long time ago.
- */
-enum {					/* 83C584 Bus Interface Controller */
-	Msr		= 0x00,		/* Memory Select Register */
-	Icr		= 0x01,		/* Interface Configuration Register */
-	Iar		= 0x02,		/* I/O Address Register */
-	Bio		= 0x03,		/* BIOS ROM Address Register */
-	Ear		= 0x03,		/* EEROM Address Register (shared with Bio) */
-	Irr		= 0x04,		/* Interrupt Request Register */
-	Hcr		= 0x04,		/* 8216 hardware control */
-	Laar		= 0x05,		/* LA Address Register */
-	Ijr		= 0x06,		/* Initialisation Jumpers */
-	Gp2		= 0x07,		/* General Purpose Data Register */
-	Lar		= 0x08,		/* LAN Address Registers */
-	Id		= 0x0E,		/* Card ID byte */
-	Cksum		= 0x0F,		/* Checksum */
-};
-
-enum {					/* Msr */
-	Rst		= 0x80,		/* software reset */
-	Menb		= 0x40,		/* memory enable */
-};
-
-enum {					/* Icr */
-	Bit16		= 0x01,		/* 16-bit bus */
-	Other		= 0x02,		/* other register access */
-	Ir2		= 0x04,		/* IR2 */
-	Msz		= 0x08,		/* SRAM size */
-	Rla		= 0x10,		/* recall LAN address */
-	Rx7		= 0x20,		/* recall all but I/O and LAN address */
-	Rio		= 0x40,		/* recall I/O address from EEROM */
-	Sto		= 0x80,		/* non-volatile EEROM store */
-};
-
-enum {					/* Laar */
-	ZeroWS16	= 0x20,		/* zero wait states for 16-bit ops */
-	L16en		= 0x40,		/* enable 16-bit LAN operation */
-	M16en		= 0x80,		/* enable 16-bit memory access */
-};
-
-enum {					/* Ijr */
-	Ienable		= 0x01,		/* 8216 interrupt enable */
-};
-
-/*
- * Mapping from configuration bits to interrupt level.
- */
-static int irq8003[8] = {
-	9, 3, 5, 7, 10, 11, 15, 4,
-};
-
-static int irq8216[8] = {
-	0, 9, 3, 5, 7, 10, 11, 15,
-};
-
-static void
-reset8003(Ether* ether, uchar ea[Eaddrlen], uchar ic[8])
-{
-	Dp8390 *ctlr;
-	ulong port;
-
-	ctlr = ether->ctlr;
-	port = ether->port;
-
-	/*
-	 * Check for old, dumb 8003E, which doesn't have an interface
-	 * chip. Only Msr exists out of the 1st eight registers, reads
-	 * of the others just alias the 2nd eight registers, the LAN
-	 * address ROM. Can check Icr, Irr and Laar against the ethernet
-	 * address read above and if they match it's an 8003E (or an
-	 * 8003EBT, 8003S, 8003SH or 8003WT, doesn't matter), in which
-	 * case the default irq gets used.
-	 */
-	if(memcmp(&ea[1], &ic[1], 5) == 0){
-		memset(ic, 0, sizeof(ic));
-		ic[Msr] = (((ulong)ether->mem)>>13) & 0x3F;
-	}
-	else{
-		/*
-		 * As a final sanity check for the 8013EBT, which doesn't have
-		 * the 83C584 interface chip, but has 2 real registers, write Gp2
-		 * and if it reads back the same, it's not an 8013EBT.
-		 */
-		outb(port+Gp2, 0xAA);
-		inb(port+Msr);				/* wiggle bus */
-		if(inb(port+Gp2) != 0xAA){
-			memset(ic, 0, sizeof(ic));
-			ic[Msr] = (((ulong)ether->mem)>>13) & 0x3F;
-		}
-		else
-			ether->irq = irq8003[((ic[Irr]>>5) & 0x3)|(ic[Icr] & 0x4)];
-
-		/*
-		 * Check if 16-bit card.
-		 * If Bit16 is read/write, then it's an 8-bit card.
-		 * If Bit16 is set, it's in a 16-bit slot.
-		 */
-		outb(port+Icr, ic[Icr]^Bit16);
-		inb(port+Msr);				/* wiggle bus */
-		if((inb(port+Icr) & Bit16) == (ic[Icr] & Bit16)){
-			ctlr->width = 2;
-			ic[Icr] &= ~Bit16;
-		}
-		outb(port+Icr, ic[Icr]);
-
-		if(ctlr->width == 2 && (inb(port+Icr) & Bit16) == 0)
-			ctlr->width = 1;
-	}
-
-	ether->mem = (ulong)KADDR((ic[Msr] & 0x3F)<<13);
-	if(ctlr->width == 2)
-		ether->mem |= (ic[Laar] & 0x1F)<<19;
-	else
-		ether->mem |= 0x80000;
-
-	if(ic[Icr] & (1<<3))
-		ether->size = 32*1024;
-	if(ctlr->width == 2)
-		ether->size <<= 1;
-
-	/*
-	 * Enable interface RAM, set interface width.
-	 */
-	outb(port+Msr, ic[Msr]|Menb);
-	if(ctlr->width == 2)
-		outb(port+Laar, ic[Laar]|L16en|M16en|ZeroWS16);
-}
-
-static void
-reset8216(Ether* ether, uchar[8])
-{
-	uchar hcr, irq, x;
-	ulong addr, port;
-	Dp8390 *ctlr;
-
-	ctlr = ether->ctlr;
-	port = ether->port;
-
-	ctlr->width = 2;
-
-	/*
-	 * Switch to the alternate register set and retrieve the memory
-	 * and irq information.
-	 */
-	hcr = inb(port+Hcr);
-	outb(port+Hcr, 0x80|hcr);
-	addr = inb(port+0x0B) & 0xFF;
-	irq = inb(port+0x0D);
-	outb(port+Hcr, hcr);
-
-	ether->mem = (ulong)KADDR(0xC0000+((((addr>>2) & 0x30)|(addr & 0x0F))<<13));
-	ether->size = 8192*(1<<((addr>>4) & 0x03));
-	ether->irq = irq8216[((irq>>4) & 0x04)|((irq>>2) & 0x03)];
-
-	/*
-	 * Enable interface RAM, set interface width, and enable interrupts.
-	 */
-	x = inb(port+Msr) & ~Rst;
-	outb(port+Msr, Menb|x);
-	x = inb(port+Laar);
-	outb(port+Laar, M16en|x);
-	outb(port+Ijr, Ienable);
-}
-
-/*
- * Get configuration parameters, enable memory.
- * There are opportunities here for buckets of code, try to resist.
- */
-int
-wd8003reset(Ether* ether)
-{
-	int i;
-	uchar ea[Eaddrlen], ic[8], id, nullea[Eaddrlen], sum;
-	ulong port;
-	Dp8390 *ctlr;
-
-	/*
-	 * Set up the software configuration.
-	 * Use defaults for port, irq, mem and size if not specified.
-	 * Defaults are set for the dumb 8003E which can't be
-	 * autoconfigured.
-	 */
-	if(ether->port == 0)
-		ether->port = 0x280;
-	if(ether->irq == 0)
-		ether->irq = 3;
-	if(ether->mem == 0)
-		ether->mem = 0xD0000;
-	if(ether->size == 0)
-		ether->size = 8*1024;
-
-	/*
-	 * Look for the interface. Read the LAN address ROM
-	 * and validate the checksum - the sum of all 8 bytes
-	 * should be 0xFF.
-	 * At the same time, get the (possible) interface chip
-	 * registers, they'll be used later to check for aliasing.
-	 */
-	port = ether->port;
-	sum = 0;
-	for(i = 0; i < sizeof(ea); i++){
-		ea[i] = inb(port+Lar+i);
-		sum += ea[i];
-		ic[i] = inb(port+i);
-	}
-	id = inb(port+Id);
-	sum += id;
-	sum += inb(port+Cksum);
-	if(sum != 0xFF)
-		return -1;
-
-	ether->ctlr = malloc(sizeof(Dp8390));
-	ctlr = ether->ctlr;
-	ctlr->ram = 1;
-
-	if((id & 0xFE) == 0x2A)
-		reset8216(ether, ic);
-	else
-		reset8003(ether, ea, ic);
-
-	/*
-	 * Set the DP8390 ring addresses.
-	 */
-	ctlr->port = port+0x10;
-	ctlr->tstart = 0;
-	ctlr->pstart = HOWMANY(sizeof(Etherpkt), Dp8390BufSz);
-	ctlr->pstop = HOWMANY(ether->size, Dp8390BufSz);
-
-	/*
-	 * Finally, init the 8390, set the ethernet address
-	 * and claim the memory used.
-	 */
-	dp8390reset(ether);
-	memset(nullea, 0, Eaddrlen);
-	if(memcmp(nullea, ether->ea, Eaddrlen) == 0){
-		for(i = 0; i < sizeof(ether->ea); i++)
-			ether->ea[i] = ea[i];
-	}
-	dp8390setea(ether);
-
-	if(umbrwmalloc(PADDR(ether->mem), ether->size, 0) == 0)
-		print("ether8003: warning - 0x%luX unavailable", PADDR(ether->mem));
-
-	return 0;
-}
--- a/os/boot/pc/ether8139.c
+++ /dev/null
@@ -1,614 +1,0 @@
-/*
- * Realtek 8139 (but not the 8129).
- * Error recovery for the various over/under -flow conditions
- * may need work.
- */
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-#include "etherif.h"
-
-enum {					/* registers */
-	Idr0		= 0x0000,	/* MAC address */
-	Mar0		= 0x0008,	/* Multicast address */
-	Tsd0		= 0x0010,	/* Transmit Status Descriptor0 */
-	Tsad0		= 0x0020,	/* Transmit Start Address Descriptor0 */
-	Rbstart		= 0x0030,	/* Receive Buffer Start Address */
-	Erbcr		= 0x0034,	/* Early Receive Byte Count */
-	Ersr		= 0x0036,	/* Early Receive Status */
-	Cr		= 0x0037,	/* Command Register */
-	Capr		= 0x0038,	/* Current Address of Packet Read */
-	Cbr		= 0x003A,	/* Current Buffer Address */
-	Imr		= 0x003C,	/* Interrupt Mask */
-	Isr		= 0x003E,	/* Interrupt Status */
-	Tcr		= 0x0040,	/* Transmit Configuration */
-	Rcr		= 0x0044,	/* Receive Configuration */
-	Tctr		= 0x0048,	/* Timer Count */
-	Mpc		= 0x004C,	/* Missed Packet Counter */
-	Cr9346		= 0x0050,	/* 9346 Command Register */
-	Config0		= 0x0051,	/* Configuration Register 0 */
-	Config1		= 0x0052,	/* Configuration Register 1 */
-	TimerInt	= 0x0054,	/* Timer Interrupt */
-	Msr		= 0x0058,	/* Media Status */
-	Config3		= 0x0059,	/* Configuration Register 3 */
-	Config4		= 0x005A,	/* Configuration Register 4 */
-	Mulint		= 0x005C,	/* Multiple Interrupt Select */
-	RerID		= 0x005E,	/* PCI Revision ID */
-	Tsad		= 0x0060,	/* Transmit Status of all Descriptors */
-
-	Bmcr		= 0x0062,	/* Basic Mode Control */
-	Bmsr		= 0x0064,	/* Basic Mode Status */
-	Anar		= 0x0066,	/* Auto-Negotiation Advertisment */
-	Anlpar		= 0x0068,	/* Auto-Negotiation Link Partner */
-	Aner		= 0x006A,	/* Auto-Negotiation Expansion */
-	Dis		= 0x006C,	/* Disconnect Counter */
-	Fcsc		= 0x006E,	/* False Carrier Sense Counter */
-	Nwaytr		= 0x0070,	/* N-way Test */
-	Rec		= 0x0072,	/* RX_ER Counter */
-	Cscr		= 0x0074,	/* CS Configuration */
-	Phy1parm	= 0x0078,	/* PHY Parameter 1 */
-	Twparm		= 0x007C,	/* Twister Parameter */
-	Phy2parm	= 0x0080,	/* PHY Parameter 2 */
-};
-
-enum {					/* Cr */
-	Bufe		= 0x01,		/* Rx Buffer Empty */
-	Te		= 0x04,		/* Transmitter Enable */
-	Re		= 0x08,		/* Receiver Enable */
-	Rst		= 0x10,		/* Software Reset */
-};
-
-enum {					/* Imr/Isr */
-	Rok		= 0x0001,	/* Receive OK */
-	Rer		= 0x0002,	/* Receive Error */
-	Tok		= 0x0004,	/* Transmit OK */
-	Ter		= 0x0008,	/* Transmit Error */
-	Rxovw		= 0x0010,	/* Receive Buffer Overflow */
-	PunLc		= 0x0020,	/* Packet Underrun or Link Change */
-	Fovw		= 0x0040,	/* Receive FIFO Overflow */
-	Clc		= 0x2000,	/* Cable Length Change */
-	Timer		= 0x4000,	/* Timer */
-	Serr		= 0x8000,	/* System Error */
-};
-
-enum {					/* Tcr */
-	Clrabt		= 0x00000001,	/* Clear Abort */
-	TxrrSHIFT	= 4,		/* Transmit Retry Count */
-	TxrrMASK	= 0x000000F0,
-	MtxdmaSHIFT	= 8,		/* Max. DMA Burst Size */
-	MtxdmaMASK	= 0x00000700,
-	Mtxdma2048	= 0x00000700,
-	Acrc		= 0x00010000,	/* Append CRC (not) */
-	LbkSHIFT	= 17,		/* Loopback Test */
-	LbkMASK		= 0x00060000,
-	IfgSHIFT	= 24,		/* Interframe Gap */
-	IfgMASK		= 0x03000000,
-	HwveridSHIFT	= 22,		/* Hardware Version ID */
-	HwveridMASK	= 0x7CC00000,
-};
-
-enum {					/* Rcr */
-	Aap		= 0x00000001,	/* Accept All Packets */
-	Apm		= 0x00000002,	/* Accept Physical Match */
-	Am		= 0x00000004,	/* Accept Multicast */
-	Ab		= 0x00000008,	/* Accept Broadcast */
-	Ar		= 0x00000010,	/* Accept Runt */
-	Aer		= 0x00000020,	/* Accept Error */
-	Sel9356		= 0x00000040,	/* 9356 EEPROM used */
-	Wrap		= 0x00000080,	/* Rx Buffer Wrap Control */
-	MrxdmaSHIFT	= 8,		/* Max. DMA Burst Size */
-	MrxdmaMASK	= 0x00000700,
-	Mrxdmaunlimited	= 0x00000700,
-	RblenSHIFT	= 11,		/* Receive Buffer Length */
-	RblenMASK	= 0x00001800,
-	Rblen8K		= 0x00000000,	/* 8KB+16 */
-	Rblen16K	= 0x00000800,	/* 16KB+16 */
-	Rblen32K	= 0x00001000,	/* 32KB+16 */
-	Rblen64K	= 0x00001800,	/* 64KB+16 */
-	RxfthSHIFT	= 13,		/* Receive Buffer Length */
-	RxfthMASK	= 0x0000E000,
-	Rxfth256	= 0x00008000,
-	Rxfthnone	= 0x0000E000,
-	Rer8		= 0x00010000,	/* Accept Error Packets > 8 bytes */
-	MulERINT	= 0x00020000,	/* Multiple Early Interrupt Select */
-	ErxthSHIFT	= 24,		/* Early Rx Threshold */
-	ErxthMASK	= 0x0F000000,
-	Erxthnone	= 0x00000000,
-};
-
-enum {					/* Received Packet Status */
-	Rcok		= 0x0001,	/* Receive Completed OK */
-	Fae		= 0x0002,	/* Frame Alignment Error */
-	Crc		= 0x0004,	/* CRC Error */
-	Long		= 0x0008,	/* Long Packet */
-	Runt		= 0x0010,	/* Runt Packet Received */
-	Ise		= 0x0020,	/* Invalid Symbol Error */
-	Bar		= 0x2000,	/* Broadcast Address Received */
-	Pam		= 0x4000,	/* Physical Address Matched */
-	Mar		= 0x8000,	/* Multicast Address Received */
-};
-
-enum {					/* Media Status Register */
-	Rxpf		= 0x01,		/* Pause Flag */
-	Txpf		= 0x02,		/* Pause Flag */
-	Linkb		= 0x04,		/* Inverse of Link Status */
-	Speed10		= 0x08,		/* 10Mbps */
-	Auxstatus	= 0x10,		/* Aux. Power Present Status */
-	Rxfce		= 0x40,		/* Receive Flow Control Enable */
-	Txfce		= 0x80,		/* Transmit Flow Control Enable */
-};
-
-typedef struct {			/* Soft Transmit Descriptor */
-	int	tsd;
-	int	tsad;
-	uchar*	data;
-} Td;
-
-enum {					/* Tsd0 */
-	SizeSHIFT	= 0,		/* Descriptor Size */
-	SizeMASK	= 0x00001FFF,
-	Own		= 0x00002000,
-	Tun		= 0x00004000,	/* Transmit FIFO Underrun */
-	Tcok		= 0x00008000,	/* Transmit COmpleted OK */
-	EtxthSHIFT	= 16,		/* Early Tx Threshold */
-	EtxthMASK	= 0x001F0000,
-	NccSHIFT	= 24,		/* Number of Collisions Count */
-	NccMASK		= 0x0F000000,
-	Cdh		= 0x10000000,	/* CD Heartbeat */
-	Owc		= 0x20000000,	/* Out of Window Collision */
-	Tabt		= 0x40000000,	/* Transmit Abort */
-	Crs		= 0x80000000,	/* Carrier Sense Lost */
-};
-
-enum {
-	Rblen		= Rblen64K,	/* Receive Buffer Length */
-	Ntd		= 4,		/* Number of Transmit Descriptors */
-	Tdbsz		= ROUNDUP(sizeof(Etherpkt), 4),
-};
-
-typedef struct Ctlr Ctlr;
-typedef struct Ctlr {
-	int	port;
-	Pcidev*	pcidev;
-	Ctlr*	next;
-	int	active;
-	int	id;
-
-	Lock	ilock;			/* init */
-	void*	alloc;			/* base of per-Ctlr allocated data */
-
-	int	rcr;			/* receive configuration register */
-	uchar*	rbstart;		/* receive buffer */
-	int	rblen;			/* receive buffer length */
-	int	ierrs;			/* receive errors */
-
-	Lock	tlock;			/* transmit */
-	Td	td[Ntd];
-	int	ntd;			/* descriptors active */
-	int	tdh;			/* host index into td */
-	int	tdi;			/* interface index into td */
-	int	etxth;			/* early transmit threshold */
-	int	taligned;		/* packet required no alignment */
-	int	tunaligned;		/* packet required alignment */
-
-	int	dis;			/* disconnect counter */
-	int	fcsc;			/* false carrier sense counter */
-	int	rec;			/* RX_ER counter */
-} Ctlr;
-
-static Ctlr* ctlrhead;
-static Ctlr* ctlrtail;
-
-#define csr8r(c, r)	(inb((c)->port+(r)))
-#define csr16r(c, r)	(ins((c)->port+(r)))
-#define csr32r(c, r)	(inl((c)->port+(r)))
-#define csr8w(c, r, b)	(outb((c)->port+(r), (int)(b)))
-#define csr16w(c, r, w)	(outs((c)->port+(r), (ushort)(w)))
-#define csr32w(c, r, l)	(outl((c)->port+(r), (ulong)(l)))
-
-static int
-rtl8139reset(Ctlr* ctlr)
-{
-	/*
-	 * Soft reset the controller.
-	 */
-	csr8w(ctlr, Cr, Rst);
-	while(csr8r(ctlr, Cr) & Rst)
-		;
-
-	return 0;
-}
-
-static void
-rtl8139detach(Ether* edev)
-{
-	rtl8139reset(edev->ctlr);
-}
-
-static void
-rtl8139halt(Ctlr* ctlr)
-{
-	csr8w(ctlr, Cr, 0);
-	csr16w(ctlr, Imr, 0);
-	csr16w(ctlr, Isr, ~0);
-}
-
-static void
-rtl8139init(Ether* edev)
-{
-	int i;
-	ulong r;
-	Ctlr *ctlr;
-	uchar *alloc;
-
-	ctlr = edev->ctlr;
-	ilock(&ctlr->ilock);
-
-	rtl8139halt(ctlr);
-
-	/*
-	 * MAC Address.
-	 */
-	r = (edev->ea[3]<<24)|(edev->ea[2]<<16)|(edev->ea[1]<<8)|edev->ea[0];
-	csr32w(ctlr, Idr0, r);
-	r = (edev->ea[5]<<8)|edev->ea[4];
-	csr32w(ctlr, Idr0+4, r);
-
-	/*
-	 * Receiver
-	 */
-	alloc = (uchar*)ROUNDUP((ulong)ctlr->alloc, 32);
-	ctlr->rbstart = alloc;
-	alloc += ctlr->rblen+16;
-	memset(ctlr->rbstart, 0, ctlr->rblen+16);
-	csr32w(ctlr, Rbstart, PADDR(ctlr->rbstart));
-	ctlr->rcr = Rxfth256|Rblen|Mrxdmaunlimited|Ab|Apm;
-
-	/*
-	 * Transmitter.
-	 */
-	for(i = 0; i < Ntd; i++){
-		ctlr->td[i].tsd = Tsd0+i*4;
-		ctlr->td[i].tsad = Tsad0+i*4;
-		ctlr->td[i].data = alloc;
-		alloc += Tdbsz;
-	}
-	ctlr->ntd = ctlr->tdh = ctlr->tdi = 0;
-	ctlr->etxth = 128/32;
-
-	/*
-	 * Interrupts.
-	 */
-	csr32w(ctlr, TimerInt, 0);
-	csr16w(ctlr, Imr, Serr|Timer|Fovw|PunLc|Rxovw|Ter|Tok|Rer|Rok);
-	csr32w(ctlr, Mpc, 0);
-
-	/*
-	 * Enable receiver/transmitter.
-	 * Need to enable before writing the Rcr or it won't take.
-	 */
-	csr8w(ctlr, Cr, Te|Re);
-	csr32w(ctlr, Tcr, Mtxdma2048);
-	csr32w(ctlr, Rcr, ctlr->rcr);
-
-	iunlock(&ctlr->ilock);
-}
-
-static void
-rtl8139attach(Ether* edev)
-{
-	Ctlr *ctlr;
-
-	ctlr = edev->ctlr;
-	if(ctlr->alloc == nil){
-		ctlr->rblen = 1<<((Rblen>>RblenSHIFT)+13);
-		ctlr->alloc = mallocz(ctlr->rblen+16 + Ntd*Tdbsz + 32, 0);
-		rtl8139init(edev);
-	}
-}
-
-static void
-rtl8139txstart(Ether* edev)
-{
-	Td *td;
-	Ctlr *ctlr;
-	RingBuf *tb;
-
-	ctlr = edev->ctlr;
-	while(ctlr->ntd < Ntd){
-		tb = &edev->tb[edev->ti];
-		if(tb->owner != Interface)
-			break;
-
-		td = &ctlr->td[ctlr->tdh];
-		memmove(td->data, tb->pkt, tb->len);
-		csr32w(ctlr, td->tsad, PADDR(tb->pkt));
-		csr32w(ctlr, td->tsd, (ctlr->etxth<<EtxthSHIFT)|tb->len);
-
-		ctlr->ntd++;
-		ctlr->tdh = NEXT(ctlr->tdh, Ntd);
-		tb->owner = Host;
-		edev->ti = NEXT(edev->ti, edev->ntb);
-	}
-}
-
-static void
-rtl8139transmit(Ether* edev)
-{
-	Ctlr *ctlr;
-
-	ctlr = edev->ctlr;
-	ilock(&ctlr->tlock);
-	rtl8139txstart(edev);
-	iunlock(&ctlr->tlock);
-}
-
-static void
-rtl8139receive(Ether* edev)
-{
-	Ctlr *ctlr;
-	RingBuf *rb;
-	ushort capr;
-	uchar cr, *p;
-	int l, length, status;
-
-	ctlr = edev->ctlr;
-
-	/*
-	 * Capr is where the host is reading from,
-	 * Cbr is where the NIC is currently writing.
-	 */
-	capr = (csr16r(ctlr, Capr)+16) % ctlr->rblen;
-	while(!(csr8r(ctlr, Cr) & Bufe)){
-		p = ctlr->rbstart+capr;
-
-		/*
-		 * Apparently the packet length may be 0xFFF0 if
-		 * the NIC is still copying the packet into memory.
-		 */
-		length = (*(p+3)<<8)|*(p+2);
-		if(length == 0xFFF0)
-			break;
-		status = (*(p+1)<<8)|*p;
-
-		if(!(status & Rcok)){
-			/*
-			 * Reset the receiver.
-			 * Also may have to restore the multicast list
-			 * here too if it ever gets used.
-			 */
-			cr = csr8r(ctlr, Cr);
-			csr8w(ctlr, Cr, cr & ~Re);
-			csr32w(ctlr, Rbstart, PADDR(ctlr->rbstart));
-			csr8w(ctlr, Cr, cr);
-			csr32w(ctlr, Rcr, ctlr->rcr);
-
-			continue;
-		}
-
-		/*
-		 * Receive Completed OK.
-		 * Very simplistic; there are ways this could be done
-		 * without copying, but the juice probably isn't worth
-		 * the squeeze.
-		 * The packet length includes a 4 byte CRC on the end.
-		 */
-		capr = (capr+4) % ctlr->rblen;
-		p = ctlr->rbstart+capr;
-		capr = (capr+length) % ctlr->rblen;
-
-		rb = &edev->rb[edev->ri];
-		l = 0;
-		if(p+length >= ctlr->rbstart+ctlr->rblen){
-			l = ctlr->rbstart+ctlr->rblen - p;
-			if(rb->owner == Interface)
-				memmove(rb->pkt, p, l);
-			length -= l;
-			p = ctlr->rbstart;
-		}
-		if(length > 0 && rb->owner == Interface){
-			memmove(rb->pkt+l, p, length);
-			l += length;
-		}
-		if(rb->owner == Interface){
-			rb->owner = Host;
-			rb->len = l-4;
-			edev->ri = NEXT(edev->ri, edev->nrb);
-		}
-
-		capr = ROUNDUP(capr, 4);
-		csr16w(ctlr, Capr, capr-16);
-	}
-}
-
-static void
-rtl8139interrupt(Ureg*, void* arg)
-{
-	Td *td;
-	Ctlr *ctlr;
-	Ether *edev;
-	int isr, tsd;
-
-	edev = arg;
-	ctlr = edev->ctlr;
-
-	while((isr = csr16r(ctlr, Isr)) != 0){
-		csr16w(ctlr, Isr, isr);
-		if(isr & (Fovw|PunLc|Rxovw|Rer|Rok)){
-			rtl8139receive(edev);
-			if(!(isr & Rok))
-				ctlr->ierrs++;
-			isr &= ~(Fovw|Rxovw|Rer|Rok);
-		}
-
-		if(isr & (Ter|Tok)){
-			ilock(&ctlr->tlock);
-			while(ctlr->ntd){
-				td = &ctlr->td[ctlr->tdi];
-				tsd = csr32r(ctlr, td->tsd);
-				if(!(tsd & (Tabt|Tun|Tcok)))
-					break;
-
-				if(!(tsd & Tcok)){
-					if(tsd & Tun){
-						if(ctlr->etxth < ETHERMAXTU/32)
-							ctlr->etxth++;
-					}
-				}
-
-				ctlr->ntd--;
-				ctlr->tdi = NEXT(ctlr->tdi, Ntd);
-			}
-			rtl8139txstart(edev);
-			iunlock(&ctlr->tlock);
-			isr &= ~(Ter|Tok);
-		}
-
-		if(isr & PunLc)
-			isr &= ~(Clc|PunLc);
-
-		/*
-		 * Only Serr|Timer should be left by now.
-		 * Should anything be done to tidy up? TimerInt isn't
-		 * used so that can be cleared. A PCI bus error is indicated
-		 * by Serr, that's pretty serious; is there anyhing to do
-		 * other than try to reinitialise the chip?
-		 */
-		if((isr & (Serr|Timer)) != 0){
-			print("rtl8139interrupt: imr %4.4uX isr %4.4uX\n",
-				csr16r(ctlr, Imr), isr);
-			if(isr & Timer)
-				csr32w(ctlr, TimerInt, 0);
-			if(isr & Serr)
-				rtl8139init(edev);
-		}
-	}
-}
-
-static Ctlr*
-rtl8139match(Ether* edev, int id)
-{
-	int port;
-	Pcidev *p;
-	Ctlr *ctlr;
-
-	/*
-	 * Any adapter matches if no edev->port is supplied,
-	 * otherwise the ports must match.
-	 */
-	for(ctlr = ctlrhead; ctlr != nil; ctlr = ctlr->next){
-		if(ctlr->active)
-			continue;
-		p = ctlr->pcidev;
-		if(((p->did<<16)|p->vid) != id)
-			continue;
-		port = p->mem[0].bar & ~0x01;
-		if(edev->port != 0 && edev->port != port)
-			continue;
-
-		ctlr->port = port;
-		if(rtl8139reset(ctlr))
-			continue;
-		pcisetbme(p);
-
-		ctlr->active = 1;
-		return ctlr;
-	}
-	return nil;
-}
-
-static struct {
-	char*	name;
-	int	id;
-} rtl8139pci[] = {
-	{ "rtl8139",	(0x8139<<16)|0x10EC, },	/* generic */
-	{ "smc1211",	(0x1211<<16)|0x1113, },	/* SMC EZ-Card */
-	{ "dfe-538tx",	(0x1300<<16)|0x1186, }, /* D-Link DFE-538TX */
-	{ "dfe-560txd",	(0x1340<<16)|0x1186, }, /* D-Link DFE-560TXD */
-	{ nil },
-};
-
-int
-rtl8139pnp(Ether* edev)
-{
-	int i, id;
-	Pcidev *p;
-	Ctlr *ctlr;
-	uchar ea[Eaddrlen];
-
-	/*
-	 * Make a list of all ethernet controllers
-	 * if not already done.
-	 */
-	if(ctlrhead == nil){
-		p = nil;
-		while(p = pcimatch(p, 0, 0)){
-			if(p->ccrb != 0x02 || p->ccru != 0)
-				continue;
-			ctlr = malloc(sizeof(Ctlr));
-			ctlr->pcidev = p;
-			ctlr->id = (p->did<<16)|p->vid;
-
-			if(ctlrhead != nil)
-				ctlrtail->next = ctlr;
-			else
-				ctlrhead = ctlr;
-			ctlrtail = ctlr;
-		}
-	}
-
-	/*
-	 * Is it an RTL8139 under a different name?
-	 * Normally a search is made through all the found controllers
-	 * for one which matches any of the known vid+did pairs.
-	 * If a vid+did pair is specified a search is made for that
-	 * specific controller only.
-	 */
-	id = 0;
-	for(i = 0; i < edev->nopt; i++){
-		if(cistrncmp(edev->opt[i], "id=", 3) == 0)
-			id = strtol(&edev->opt[i][3], nil, 0);
-	}
-
-	ctlr = nil;
-	if(id != 0)
-		ctlr = rtl8139match(edev, id);
-	else for(i = 0; rtl8139pci[i].name; i++){
-		if((ctlr = rtl8139match(edev, rtl8139pci[i].id)) != nil)
-			break;
-	}
-	if(ctlr == nil)
-		return -1;
-
-	edev->ctlr = ctlr;
-	edev->port = ctlr->port;
-	edev->irq = ctlr->pcidev->intl;
-	edev->tbdf = ctlr->pcidev->tbdf;
-
-	/*
-	 * Check if the adapter's station address is to be overridden.
-	 * If not, read it from the device and set in edev->ea.
-	 */
-	memset(ea, 0, Eaddrlen);
-	if(memcmp(ea, edev->ea, Eaddrlen) == 0){
-		i = csr32r(ctlr, Idr0);
-		edev->ea[0] = i;
-		edev->ea[1] = i>>8;
-		edev->ea[2] = i>>16;
-		edev->ea[3] = i>>24;
-		i = csr32r(ctlr, Idr0+4);
-		edev->ea[4] = i;
-		edev->ea[5] = i>>8;
-	}
-
-	edev->attach = rtl8139attach;
-	edev->transmit = rtl8139transmit;
-	edev->interrupt = rtl8139interrupt;
-	edev->detach = rtl8139detach;
-
-	return 0;
-}
--- a/os/boot/pc/ether8169.c
+++ /dev/null
@@ -1,958 +1,0 @@
-/*
- * Realtek RTL8110S/8169S.
- * Mostly there. There are some magic register values used
- * which are not described in any datasheet or driver but seem
- * to be necessary.
- * Why is the Fovf descriptor bit set for every received packet?
- * Occasionally the hardware indicates an input TCP checksum error
- * although the higher-level software seems to check the packet OK?
- * No tuning has been done. Only tested on an RTL8110S, there
- * are slight differences between the chips in the series so some
- * tweaks may be needed.
- */
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-typedef struct QLock { int r; } QLock;
-#define qlock(i)	while(0)
-#define qunlock(i)	while(0)
-#define iallocb		allocb
-#define iprint		print
-#define mallocalign(n, a, o, s)	ialloc((n), (a))
-
-#include "etherif.h"
-#include "ethermii.h"
-
-enum {					/* registers */
-	Idr0		= 0x00,		/* MAC address */
-	Mar0		= 0x08,		/* Multicast address */
-	Dtccr		= 0x10,		/* Dump Tally Counter Command */
-	Tnpds		= 0x20,		/* Transmit Normal Priority Descriptors */
-	Thpds		= 0x28,		/* Transmit High Priority Descriptors */
-	Flash		= 0x30,		/* Flash Memory Read/Write */
-	Erbcr		= 0x34,		/* Early Receive Byte Count */
-	Ersr		= 0x36,		/* Early Receive Status */
-	Cr		= 0x37,		/* Command Register */
-	Tppoll		= 0x38,		/* Transmit Priority Polling */
-	Imr		= 0x3C,		/* Interrupt Mask */
-	Isr		= 0x3E,		/* Interrupt Status */
-	Tcr		= 0x40,		/* Transmit Configuration */
-	Rcr		= 0x44,		/* Receive Configuration */
-	Tctr		= 0x48,		/* Timer Count */
-	Mpc		= 0x4C,		/* Missed Packet Counter */
-	Cr9346		= 0x50,		/* 9346 Command Register */
-	Config0		= 0x51,		/* Configuration Register 0 */
-	Config1		= 0x52,		/* Configuration Register 1 */
-	Config2		= 0x53,		/* Configuration Register 2 */
-	Config3		= 0x54,		/* Configuration Register 3 */
-	Config4		= 0x55,		/* Configuration Register 4 */
-	Config5		= 0x56,		/* Configuration Register 5 */
-	Timerint	= 0x58,		/* Timer Interrupt */
-	Mulint		= 0x5C,		/* Multiple Interrupt Select */
-	Phyar		= 0x60,		/* PHY Access */
-	Tbicsr0		= 0x64,		/* TBI Control and Status */
-	Tbianar		= 0x68,		/* TBI Auto-Negotiation Advertisment */
-	Tbilpar		= 0x6A,		/* TBI Auto-Negotiation Link Partner */
-	Phystatus	= 0x6C,		/* PHY Status */
-
-	Rms		= 0xDA,		/* Receive Packet Maximum Size */
-	Cplusc		= 0xE0,		/* C+ Command */
-	Rdsar		= 0xE4,		/* Receive Descriptor Start Address */
-	Mtps		= 0xEC,		/* Max. Transmit Packet Size */
-};
-
-enum {					/* Dtccr */
-	Cmd		= 0x00000008,	/* Command */
-};
-
-enum {					/* Cr */
-	Te		= 0x04,		/* Transmitter Enable */
-	Re		= 0x08,		/* Receiver Enable */
-	Rst		= 0x10,		/* Software Reset */
-};
-
-enum {					/* Tppoll */
-	Fswint		= 0x01,		/* Forced Software Interrupt */
-	Npq		= 0x40,		/* Normal Priority Queue polling */
-	Hpq		= 0x80,		/* High Priority Queue polling */
-};
-
-enum {					/* Imr/Isr */
-	Rok		= 0x0001,	/* Receive OK */
-	Rer		= 0x0002,	/* Receive Error */
-	Tok		= 0x0004,	/* Transmit OK */
-	Ter		= 0x0008,	/* Transmit Error */
-	Rdu		= 0x0010,	/* Receive Descriptor Unavailable */
-	Punlc		= 0x0020,	/* Packet Underrun or Link Change */
-	Fovw		= 0x0040,	/* Receive FIFO Overflow */
-	Tdu		= 0x0080,	/* Transmit Descriptor Unavailable */
-	Swint		= 0x0100,	/* Software Interrupt */
-	Timeout		= 0x4000,	/* Timer */
-	Serr		= 0x8000,	/* System Error */
-};
-
-enum {					/* Tcr */
-	MtxdmaSHIFT	= 8,		/* Max. DMA Burst Size */
-	MtxdmaMASK	= 0x00000700,
-	Mtxdmaunlimited	= 0x00000700,
-	Acrc		= 0x00010000,	/* Append CRC (not) */
-	Lbk0		= 0x00020000,	/* Loopback Test 0 */
-	Lbk1		= 0x00040000,	/* Loopback Test 1 */
-	Ifg2		= 0x00080000,	/* Interframe Gap 2 */
-	HwveridSHIFT	= 23,		/* Hardware Version ID */
-	HwveridMASK	= 0x7C800000,
-	Macv01		= 0x00000000,	/* RTL8169 */
-	Macv02		= 0x00800000,	/* RTL8169S/8110S */
-	Macv03		= 0x04000000,	/* RTL8169S/8110S */
-	Macv04		= 0x10000000,	/* RTL8169SB/8110SB */
-	Macv05		= 0x18000000,	/* RTL8169SC/8110SC */
-	Macv11		= 0x30000000,	/* RTL8168B/8111B */
-	Macv12		= 0x38000000,	/* RTL8169B/8111B */
-	Macv13		= 0x34000000,	/* RTL8101E */
-	Macv14		= 0x30800000,	/* RTL8100E */
-	Macv15		= 0x38800000,	/* RTL8100E */
-	Ifg0		= 0x01000000,	/* Interframe Gap 0 */
-	Ifg1		= 0x02000000,	/* Interframe Gap 1 */
-};
-
-enum {					/* Rcr */
-	Aap		= 0x00000001,	/* Accept All Packets */
-	Apm		= 0x00000002,	/* Accept Physical Match */
-	Am		= 0x00000004,	/* Accept Multicast */
-	Ab		= 0x00000008,	/* Accept Broadcast */
-	Ar		= 0x00000010,	/* Accept Runt */
-	Aer		= 0x00000020,	/* Accept Error */
-	Sel9356		= 0x00000040,	/* 9356 EEPROM used */
-	MrxdmaSHIFT	= 8,		/* Max. DMA Burst Size */
-	MrxdmaMASK	= 0x00000700,
-	Mrxdmaunlimited	= 0x00000700,
-	RxfthSHIFT	= 13,		/* Receive Buffer Length */
-	RxfthMASK	= 0x0000E000,
-	Rxfth256	= 0x00008000,
-	Rxfthnone	= 0x0000E000,
-	Rer8		= 0x00010000,	/* Accept Error Packets > 8 bytes */
-	MulERINT	= 0x01000000,	/* Multiple Early Interrupt Select */
-};
-
-enum {					/* Cr9346 */
-	Eedo		= 0x01,		/* */
-	Eedi		= 0x02,		/* */
-	Eesk		= 0x04,		/* */
-	Eecs		= 0x08,		/* */
-	Eem0		= 0x40,		/* Operating Mode */
-	Eem1		= 0x80,
-};
-
-enum {					/* Phyar */
-	DataMASK	= 0x0000FFFF,	/* 16-bit GMII/MII Register Data */
-	DataSHIFT	= 0,
-	RegaddrMASK	= 0x001F0000,	/* 5-bit GMII/MII Register Address */
-	RegaddrSHIFT	= 16,
-	Flag		= 0x80000000,	/* */
-};
-
-enum {					/* Phystatus */
-	Fd		= 0x01,		/* Full Duplex */
-	Linksts		= 0x02,		/* Link Status */
-	Speed10		= 0x04,		/* */
-	Speed100	= 0x08,		/* */
-	Speed1000	= 0x10,		/* */
-	Rxflow		= 0x20,		/* */
-	Txflow		= 0x40,		/* */
-	Entbi		= 0x80,		/* */
-};
-
-enum {					/* Cplusc */
-	Mulrw		= 0x0008,	/* PCI Multiple R/W Enable */
-	Dac		= 0x0010,	/* PCI Dual Address Cycle Enable */
-	Rxchksum	= 0x0020,	/* Receive Checksum Offload Enable */
-	Rxvlan		= 0x0040,	/* Receive VLAN De-tagging Enable */
-	Endian		= 0x0200,	/* Endian Mode */
-};
-
-typedef struct D D;			/* Transmit/Receive Descriptor */
-struct D {
-	u32	control;
-	u32	vlan;
-	u32	addrlo;
-	u32	addrhi;
-};
-
-enum {					/* Transmit Descriptor control */
-	TxflMASK	= 0x0000FFFF,	/* Transmit Frame Length */
-	TxflSHIFT	= 0,
-	Tcps		= 0x00010000,	/* TCP Checksum Offload */
-	Udpcs		= 0x00020000,	/* UDP Checksum Offload */
-	Ipcs		= 0x00040000,	/* IP Checksum Offload */
-	Lgsen		= 0x08000000,	/* Large Send */
-};
-
-enum {					/* Receive Descriptor control */
-	RxflMASK	= 0x00003FFF,	/* Receive Frame Length */
-	RxflSHIFT	= 0,
-	Tcpf		= 0x00004000,	/* TCP Checksum Failure */
-	Udpf		= 0x00008000,	/* UDP Checksum Failure */
-	Ipf		= 0x00010000,	/* IP Checksum Failure */
-	Pid0		= 0x00020000,	/* Protocol ID0 */
-	Pid1		= 0x00040000,	/* Protocol ID1 */
-	Crce		= 0x00080000,	/* CRC Error */
-	Runt		= 0x00100000,	/* Runt Packet */
-	Res		= 0x00200000,	/* Receive Error Summary */
-	Rwt		= 0x00400000,	/* Receive Watchdog Timer Expired */
-	Fovf		= 0x00800000,	/* FIFO Overflow */
-	Bovf		= 0x01000000,	/* Buffer Overflow */
-	Bar		= 0x02000000,	/* Broadcast Address Received */
-	Pam		= 0x04000000,	/* Physical Address Matched */
-	Mar		= 0x08000000,	/* Multicast Address Received */
-};
-
-enum {					/* General Descriptor control */
-	Ls		= 0x10000000,	/* Last Segment Descriptor */
-	Fs		= 0x20000000,	/* First Segment Descriptor */
-	Eor		= 0x40000000,	/* End of Descriptor Ring */
-	Own		= 0x80000000,	/* Ownership */
-};
-
-/*
- */
-enum {					/* Ring sizes  (<= 1024) */
-	Ntd		= 8,		/* Transmit Ring */
-	Nrd		= 32,		/* Receive Ring */
-
-	Mps		= ROUNDUP(ETHERMAXTU+4, 128),
-};
-
-typedef struct Dtcc Dtcc;
-struct Dtcc {
-	u64int	txok;
-	u64int	rxok;
-	u64int	txer;
-	u32	rxer;
-	u16int	misspkt;
-	u16int	fae;
-	u32	tx1col;
-	u32	txmcol;
-	u64int	rxokph;
-	u64int	rxokbrd;
-	u32	rxokmu;
-	u16int	txabt;
-	u16int	txundrn;
-};
-
-enum {						/* Variants */
-	Rtl8100e	= (0x8136<<16)|0x10EC,	/* RTL810[01]E ? */
-	Rtl8169c		= (0x0116<<16)|0x16EC,	/* RTL8169C+ (USR997902) */
-	Rtl8169sc	= (0x8167<<16)|0x10EC,	/* RTL8169SC */
-	Rtl8168b	= (0x8168<<16)|0x10EC,	/* RTL8168B */
-	Rtl8169		= (0x8169<<16)|0x10EC,	/* RTL8169 */
-};
-
-typedef struct Ctlr Ctlr;
-typedef struct Ctlr {
-	int	port;
-	Pcidev*	pcidev;
-	Ctlr*	next;
-	int	active;
-
-	void*	nic;
-
-	QLock	alock;			/* attach */
-	Lock	ilock;			/* init */
-	int	init;			/*  */
-
-	int	pciv;			/*  */
-	int	macv;			/* MAC version */
-	int	phyv;			/* PHY version */
-
-	Mii*	mii;
-
-	Lock	tlock;			/* transmit */
-	D*	td;			/* descriptor ring */
-	Block**	tb;			/* transmit buffers */
-	int	ntd;
-
-	int	tdh;			/* head - producer index (host) */
-	int	tdt;			/* tail - consumer index (NIC) */
-	int	ntdfree;
-	int	ntq;
-
-	int	mtps;			/* Max. Transmit Packet Size */
-
-	Lock	rlock;			/* receive */
-	D*	rd;			/* descriptor ring */
-	void**	rb;			/* receive buffers */
-	int	nrd;
-
-	int	rdh;			/* head - producer index (NIC) */
-	int	rdt;			/* tail - consumer index (host) */
-	int	nrdfree;
-
-	int	rcr;			/* receive configuration register */
-
-	QLock	slock;			/* statistics */
-	Dtcc*	dtcc;
-	uint	txdu;
-	uint	tcpf;
-	uint	udpf;
-	uint	ipf;
-	uint	fovf;
-	uint	ierrs;
-	uint	rer;
-	uint	rdu;
-	uint	punlc;
-	uint	fovw;
-} Ctlr;
-
-static Ctlr* rtl8169ctlrhead;
-static Ctlr* rtl8169ctlrtail;
-
-#define csr8r(c, r)	(inb((c)->port+(r)))
-#define csr16r(c, r)	(ins((c)->port+(r)))
-#define csr32r(c, r)	(inl((c)->port+(r)))
-#define csr8w(c, r, b)	(outb((c)->port+(r), (int)(b)))
-#define csr16w(c, r, w)	(outs((c)->port+(r), (ushort)(w)))
-#define csr32w(c, r, l)	(outl((c)->port+(r), (ulong)(l)))
-
-static int
-rtl8169miimir(Mii* mii, int pa, int ra)
-{
-	uint r;
-	int timeo;
-	Ctlr *ctlr;
-
-	if(pa != 1)
-		return -1;
-	ctlr = mii->ctlr;
-
-	r = (ra<<16) & RegaddrMASK;
-	csr32w(ctlr, Phyar, r);
-	delay(1);
-	for(timeo = 0; timeo < 2000; timeo++){
-		if((r = csr32r(ctlr, Phyar)) & Flag)
-			break;
-		microdelay(100);
-	}
-	if(!(r & Flag))
-		return -1;
-
-	return (r & DataMASK)>>DataSHIFT;
-}
-
-static int
-rtl8169miimiw(Mii* mii, int pa, int ra, int data)
-{
-	uint r;
-	int timeo;
-	Ctlr *ctlr;
-
-	if(pa != 1)
-		return -1;
-	ctlr = mii->ctlr;
-
-	r = Flag|((ra<<16) & RegaddrMASK)|((data<<DataSHIFT) & DataMASK);
-	csr32w(ctlr, Phyar, r);
-	delay(1);
-	for(timeo = 0; timeo < 2000; timeo++){
-		if(!((r = csr32r(ctlr, Phyar)) & Flag))
-			break;
-		microdelay(100);
-	}
-	if(r & Flag)
-		return -1;
-
-	return 0;
-}
-
-static int
-rtl8169mii(Ctlr* ctlr)
-{
-	MiiPhy *phy;
-
-	/*
-	 * Link management.
-	 */
-	if((ctlr->mii = malloc(sizeof(Mii))) == nil)
-		return -1;
-	ctlr->mii->mir = rtl8169miimir;
-	ctlr->mii->miw = rtl8169miimiw;
-	ctlr->mii->ctlr = ctlr;
-
-	/*
-	 * Get rev number out of Phyidr2 so can config properly.
-	 * There's probably more special stuff for Macv0[234] needed here.
-	 */
-	ctlr->phyv = rtl8169miimir(ctlr->mii, 1, Phyidr2) & 0x0F;
-	if(ctlr->macv == Macv02){
-		csr8w(ctlr, 0x82, 1);				/* magic */
-		rtl8169miimiw(ctlr->mii, 1, 0x0B, 0x0000);	/* magic */
-	}
-
-	if(mii(ctlr->mii, (1<<1)) == 0 || (phy = ctlr->mii->curphy) == nil){
-		free(ctlr->mii);
-		ctlr->mii = nil;
-		return -1;
-	}
-	print("oui %#ux phyno %d, macv = %#8.8ux phyv = %#4.4ux\n",
-		phy->oui, phy->phyno, ctlr->macv, ctlr->phyv);
-
-	miiane(ctlr->mii, ~0, ~0, ~0);
-
-	return 0;
-}
-
-static void
-rtl8169halt(Ctlr* ctlr)
-{
-	csr8w(ctlr, Cr, 0);
-	csr16w(ctlr, Imr, 0);
-	csr16w(ctlr, Isr, ~0);
-}
-
-static int
-rtl8169reset(Ctlr* ctlr)
-{
-	u32 r;
-	int timeo;
-
-	/*
-	 * Soft reset the controller.
-	 */
-	csr8w(ctlr, Cr, Rst);
-	for(r = timeo = 0; timeo < 1000; timeo++){
-		r = csr8r(ctlr, Cr);
-		if(!(r & Rst))
-			break;
-		delay(1);
-	}
-	rtl8169halt(ctlr);
-
-	if(r & Rst)
-		return -1;
-	return 0;
-}
-
-static void
-rtl8169detach(Ether* edev)
-{
-	rtl8169reset(edev->ctlr);
-}
-
-static void
-rtl8169replenish(Ctlr* ctlr)
-{
-	D *d;
-	int rdt;
-	void *bp;
-
-	rdt = ctlr->rdt;
-	while(NEXT(rdt, ctlr->nrd) != ctlr->rdh){
-		d = &ctlr->rd[rdt];
-		if(ctlr->rb[rdt] == nil){
-			/*
-			 * simple allocation for now
-			 */
-			bp = mallocalign(Mps, 8, 0, 0);
-			ctlr->rb[rdt] = bp;
-			d->addrlo = PCIWADDR(bp);
-			d->addrhi = 0;
-		}
-		coherence();
-		d->control |= Own|Mps;
-		rdt = NEXT(rdt, ctlr->nrd);
-		ctlr->nrdfree++;
-	}
-	ctlr->rdt = rdt;
-}
-
-static int
-rtl8169init(Ether* edev)
-{
-	u32 r;
-	Ctlr *ctlr;
-	u8int cplusc;
-
-	ctlr = edev->ctlr;
-	ilock(&ctlr->ilock);
-
-	rtl8169halt(ctlr);
-
-	/*
-	 * MAC Address.
-	 * Must put chip into config register write enable mode.
-	 */
-	csr8w(ctlr, Cr9346, Eem1|Eem0);
-	r = (edev->ea[3]<<24)|(edev->ea[2]<<16)|(edev->ea[1]<<8)|edev->ea[0];
-	csr32w(ctlr, Idr0, r);
-	r = (edev->ea[5]<<8)|edev->ea[4];
-	csr32w(ctlr, Idr0+4, r);
-
-	/*
-	 * Transmitter.
-	 */
-	memset(ctlr->td, 0, sizeof(D)*ctlr->ntd);
-	ctlr->tdh = ctlr->tdt = 0;
-	ctlr->td[ctlr->ntd-1].control = Eor;
-
-	/*
-	 * Receiver.
-	 * Need to do something here about the multicast filter.
-	 */
-	memset(ctlr->rd, 0, sizeof(D)*ctlr->nrd);
-	ctlr->rdh = ctlr->rdt = 0;
-	ctlr->rd[ctlr->nrd-1].control = Eor;
-	rtl8169replenish(ctlr);
-	ctlr->rcr = Rxfthnone|Mrxdmaunlimited|Ab|Apm;
-
-	/*
-	 * Mtps is in units of 128 except for the RTL8169
-	 * where is is 32. If using jumbo frames should be
-	 * set to 0x3F.
-	 * Setting Mulrw in Cplusc disables the Tx/Rx DMA burst
-	 * settings in Tcr/Rcr; the (1<<14) is magic.
-	 */
-	ctlr->mtps = HOWMANY(Mps, 128);
-	cplusc = csr16r(ctlr, Cplusc) & ~(1<<14);
-	cplusc |= Rxchksum|Mulrw;
-	switch(ctlr->macv){
-	default:
-		return -1;
-	case Macv01:
-		ctlr->mtps = HOWMANY(Mps, 32);
-		break;
-	case Macv02:
-	case Macv03:
-		cplusc |= (1<<14);			/* magic */
-		break;
-	case Macv05:
-		/*
-		 * This is interpreted from clearly bogus code
-		 * in the manufacturer-supplied driver, it could
-		 * be wrong. Untested.
-		 */
-		r = csr8r(ctlr, Config2) & 0x07;
-		if(r == 0x01)				/* 66MHz PCI */
-			csr32w(ctlr, 0x7C, 0x0007FFFF);	/* magic */
-		else
-			csr32w(ctlr, 0x7C, 0x0007FF00);	/* magic */
-		pciclrmwi(ctlr->pcidev);
-		break;
-	case Macv13:
-		/*
-		 * This is interpreted from clearly bogus code
-		 * in the manufacturer-supplied driver, it could
-		 * be wrong. Untested.
-		 */
-		pcicfgw8(ctlr->pcidev, 0x68, 0x00);	/* magic */
-		pcicfgw8(ctlr->pcidev, 0x69, 0x08);	/* magic */
-		break;
-	case Macv04:
-	case Macv11:
-	case Macv12:
-	case Macv14:
-	case Macv15:
-		break;
-	}
-
-	/*
-	 * Enable receiver/transmitter.
-	 * Need to do this first or some of the settings below
-	 * won't take.
-	 */
-	switch(ctlr->pciv){
-	default:
-		csr8w(ctlr, Cr, Te|Re);
-		csr32w(ctlr, Tcr, Ifg1|Ifg0|Mtxdmaunlimited);
-		csr32w(ctlr, Rcr, ctlr->rcr);
-	case Rtl8169sc:
-	case Rtl8168b:
-		break;
-	}
-
-	/*
-	 * Interrupts.
-	 * Disable Tdu|Tok for now, the transmit routine will tidy.
-	 * Tdu means the NIC ran out of descriptors to send, so it
-	 * doesn't really need to ever be on.
-	 */
-	csr32w(ctlr, Timerint, 0);
-	csr16w(ctlr, Imr, Serr|Timeout|Fovw|Punlc|Rdu|Ter|Rer|Rok);
-
-	/*
-	 * Clear missed-packet counter;
-	 * initial early transmit threshold value;
-	 * set the descriptor ring base addresses;
-	 * set the maximum receive packet size;
-	 * no early-receive interrupts.
-	 */
-	csr32w(ctlr, Mpc, 0);
-	csr8w(ctlr, Mtps, ctlr->mtps);
-	csr32w(ctlr, Tnpds+4, 0);
-	csr32w(ctlr, Tnpds, PCIWADDR(ctlr->td));
-	csr32w(ctlr, Rdsar+4, 0);
-	csr32w(ctlr, Rdsar, PCIWADDR(ctlr->rd));
-	csr16w(ctlr, Rms, Mps);
-	r = csr16r(ctlr, Mulint) & 0xF000;
-	csr16w(ctlr, Mulint, r);
-	csr16w(ctlr, Cplusc, cplusc);
-
-	/*
-	 * Set configuration.
-	 */
-	switch(ctlr->pciv){
-	default:
-		break;
-	case Rtl8169sc:
-		csr16w(ctlr, 0xE2, 0);			/* magic */
-		csr8w(ctlr, Cr, Te|Re);
-		csr32w(ctlr, Tcr, Ifg1|Ifg0|Mtxdmaunlimited);
-		csr32w(ctlr, Rcr, ctlr->rcr);
-		break;
-	case Rtl8168b:
-	case Rtl8169c:
-		csr16w(ctlr, 0xE2, 0);			/* magic */
-		csr16w(ctlr, Cplusc, 0x2000);		/* magic */
-		csr8w(ctlr, Cr, Te|Re);
-		csr32w(ctlr, Tcr, Ifg1|Ifg0|Mtxdmaunlimited);
-		csr32w(ctlr, Rcr, ctlr->rcr);
-		csr16w(ctlr, Rms, 0x0800);
-		csr8w(ctlr, Mtps, 0x3F);
-		break;
-	}
-
-	csr8w(ctlr, Cr9346, 0);
-
-	iunlock(&ctlr->ilock);
-
-//	rtl8169mii(ctlr);
-
-	return 0;
-}
-
-static void
-rtl8169attach(Ether* edev)
-{
-	int timeo;
-	Ctlr *ctlr;
-
-	ctlr = edev->ctlr;
-	qlock(&ctlr->alock);
-	if(ctlr->init == 0){
-		/*
-		 * Handle allocation/init errors here.
-		 */
-		ctlr->td = xspanalloc(sizeof(D)*Ntd, 256, 0);
-		ctlr->tb = malloc(Ntd*sizeof(Block*));
-		ctlr->ntd = Ntd;
-		ctlr->rd = xspanalloc(sizeof(D)*Nrd, 256, 0);
-		ctlr->rb = malloc(Nrd*sizeof(Block*));
-		ctlr->nrd = Nrd;
-		ctlr->dtcc = xspanalloc(sizeof(Dtcc), 64, 0);
-		rtl8169init(edev);
-		ctlr->init = 1;
-	}
-	qunlock(&ctlr->alock);
-
-	for(timeo = 0; timeo < 3500; timeo++){
-		if(miistatus(ctlr->mii) == 0)
-			break;
-		delay(10);
-	}
-}
-
-static void
-rtl8169transmit(Ether* edev)
-{
-	D *d;
-	Block *bp;
-	Ctlr *ctlr;
-	int control, x;
-	RingBuf *tb;
-
-	ctlr = edev->ctlr;
-
-	ilock(&ctlr->tlock);
-	for(x = ctlr->tdh; ctlr->ntq > 0; x = NEXT(x, ctlr->ntd)){
-		d = &ctlr->td[x];
-		if((control = d->control) & Own)
-			break;
-
-		/*
-		 * Check errors and log here.
-		 */
-		USED(control);
-
-		/*
-		 * Free it up.
-		 * Need to clean the descriptor here? Not really.
-		 * Simple freeb for now (no chain and freeblist).
-		 * Use ntq count for now.
-		 */
-		freeb(ctlr->tb[x]);
-		ctlr->tb[x] = nil;
-		d->control &= Eor;
-
-		ctlr->ntq--;
-	}
-	ctlr->tdh = x;
-
-	x = ctlr->tdt;
-	while(ctlr->ntq < (ctlr->ntd-1)){
-		tb = &edev->tb[edev->ti];
-		if(tb->owner != Interface)
-			break;
-
-		bp = allocb(tb->len);
-		memmove(bp->wp, tb->pkt, tb->len);
-		memmove(bp->wp+Eaddrlen, edev->ea, Eaddrlen);
-		bp->wp += tb->len;
-
-		tb->owner = Host;
-		edev->ti = NEXT(edev->ti, edev->ntb);
-
-		d = &ctlr->td[x];
-		d->addrlo = PCIWADDR(bp->rp);
-		d->addrhi = 0;
-		ctlr->tb[x] = bp;
-		coherence();
-		d->control |= Own|Fs|Ls|((BLEN(bp)<<TxflSHIFT) & TxflMASK);
-
-		x = NEXT(x, ctlr->ntd);
-		ctlr->ntq++;
-	}
-	if(x != ctlr->tdt){
-		ctlr->tdt = x;
-		csr8w(ctlr, Tppoll, Npq);
-	}
-	else if(ctlr->ntq >= (ctlr->ntd-1))
-		ctlr->txdu++;
-
-	iunlock(&ctlr->tlock);
-}
-
-static void
-rtl8169receive(Ether* edev)
-{
-	D *d;
-	int len, rdh;
-	Ctlr *ctlr;
-	u32 control;
-	RingBuf *ring;
-
-	ctlr = edev->ctlr;
-
-	rdh = ctlr->rdh;
-	for(;;){
-		d = &ctlr->rd[rdh];
-	
-		if(d->control & Own)
-			break;
-
-		control = d->control;
-		if((control & (Fs|Ls|Res)) == (Fs|Ls)){
-			len = ((control & RxflMASK)>>RxflSHIFT) - 4;
-
-			ring = &edev->rb[edev->ri];
-			if(ring->owner == Interface){
-				ring->owner = Host;
-				ring->len = len;
-				memmove(ring->pkt, ctlr->rb[rdh], len);
-				edev->ri = NEXT(edev->ri, edev->nrb);
-			}
-		}
-		else{
-			/*
-			 * Error stuff here.
-			print("control %#8.8ux\n", control);
-			 */
-		}
-		d->control &= Eor;
-		ctlr->nrdfree--;
-		rdh = NEXT(rdh, ctlr->nrd);
-	}
-	ctlr->rdh = rdh;
-	
-	if(ctlr->nrdfree < ctlr->nrd/2)
-		rtl8169replenish(ctlr);
-}
-
-static void
-rtl8169interrupt(Ureg*, void* arg)
-{
-	Ctlr *ctlr;
-	Ether *edev;
-	u32 isr;
-
-	edev = arg;
-	ctlr = edev->ctlr;
-
-	while((isr = csr16r(ctlr, Isr)) != 0 && isr != 0xFFFF){
-		csr16w(ctlr, Isr, isr);
-		if(isr & (Fovw|Punlc|Rdu|Rer|Rok)){
-			rtl8169receive(edev);
-			if(!(isr & (Punlc|Rok)))
-				ctlr->ierrs++;
-			if(isr & Rer)
-				ctlr->rer++;
-			if(isr & Rdu)
-				ctlr->rdu++;
-			if(isr & Punlc)
-				ctlr->punlc++;
-			if(isr & Fovw)
-				ctlr->fovw++;
-			isr &= ~(Fovw|Rdu|Rer|Rok);
-		}
-
-		if(isr & (Tdu|Ter|Tok)){
-			rtl8169transmit(edev);
-			isr &= ~(Tdu|Ter|Tok);
-		}
-
-		if(isr & Punlc){
-//			rtl8169link(edev);
-			isr &= ~Punlc;
-		}
-
-		/*
-		 * Some of the reserved bits get set sometimes...
-		 */
-		if(isr & (Serr|Timeout|Tdu|Fovw|Punlc|Rdu|Ter|Tok|Rer|Rok))
-			panic("rtl8169interrupt: imr %#4.4ux isr %#4.4ux\n",
-				csr16r(ctlr, Imr), isr);
-	}
-}
-
-static void
-rtl8169pci(void)
-{
-	Pcidev *p;
-	Ctlr *ctlr;
-	int i, port;
-	u32 bar;
-
-	p = nil;
-	while(p = pcimatch(p, 0, 0)){
-		if(p->ccrb != 0x02 || p->ccru != 0)
-			continue;
-
-		switch(i = ((p->did<<16)|p->vid)){
-		default:
-			continue;
-		case Rtl8100e:			/* RTL810[01]E ? */
-		case Rtl8169c:			/* RTL8169C */
-		case Rtl8169sc:			/* RTL8169SC */
-		case Rtl8168b:			/* RTL8168B */
-		case Rtl8169:			/* RTL8169 */
-			break;
-		case (0xC107<<16)|0x1259:	/* Corega CG-LAPCIGT */
-			i = Rtl8169;
-			break;
-		}
-
-		bar = p->mem[0].bar;
-		port = bar & ~0x01;
-		if(ioalloc(port, p->mem[0].size, 0, "rtl8169") < 0){
-			print("rtl8169: port %#ux in use\n", port);
-			continue;
-		}
-		ctlr = malloc(sizeof(Ctlr));
-		ctlr->port = port;
-		ctlr->pcidev = p;
-		ctlr->pciv = i;
-
-		if(pcigetpms(p) > 0){
-			pcisetpms(p, 0);
-	
-			for(i = 0; i < 6; i++)
-				pcicfgw32(p, PciBAR0+i*4, p->mem[i].bar);
-			pcicfgw8(p, PciINTL, p->intl);
-			pcicfgw8(p, PciLTR, p->ltr);
-			pcicfgw8(p, PciCLS, p->cls);
-			pcicfgw16(p, PciPCR, p->pcr);
-		}
-
-		if(rtl8169reset(ctlr)){
-			iofree(port);
-			free(ctlr);
-			continue;
-		}
-
-		/*
-		 * Extract the chip hardware version,
-		 * needed to configure each properly.
-		 */
-		ctlr->macv = csr32r(ctlr, Tcr) & HwveridMASK;
-
-		rtl8169mii(ctlr);
-
-		pcisetbme(p);
-
-		if(rtl8169ctlrhead != nil)
-			rtl8169ctlrtail->next = ctlr;
-		else
-			rtl8169ctlrhead = ctlr;
-		rtl8169ctlrtail = ctlr;
-	}
-}
-
-int
-rtl8169pnp(Ether* edev)
-{
-	u32 r;
-	Ctlr *ctlr;
-
-	if(rtl8169ctlrhead == nil)
-		rtl8169pci();
-
-	/*
-	 * Any adapter matches if no edev->port is supplied,
-	 * otherwise the ports must match.
-	 */
-	for(ctlr = rtl8169ctlrhead; ctlr != nil; ctlr = ctlr->next){
-		if(ctlr->active)
-			continue;
-		if(edev->port == 0 || edev->port == ctlr->port){
-			ctlr->active = 1;
-			break;
-		}
-	}
-	if(ctlr == nil)
-		return -1;
-
-	edev->ctlr = ctlr;
-	edev->port = ctlr->port;
-	edev->irq = ctlr->pcidev->intl;
-	edev->tbdf = ctlr->pcidev->tbdf;
-//	edev->mbps = 100;
-
-	/*
-	 * Pull the MAC address out of the chip.
-	 */
-	r = csr32r(ctlr, Idr0);
-	edev->ea[0] = r;
-	edev->ea[1] = r>>8;
-	edev->ea[2] = r>>16;
-	edev->ea[3] = r>>24;
-	r = csr32r(ctlr, Idr0+4);
-	edev->ea[4] = r;
-	edev->ea[5] = r>>8;
-
-	/*
-	 * Linkage to the generic ethernet driver.
-	 */
-	edev->attach = rtl8169attach;
-	edev->transmit = rtl8169transmit;
-	edev->interrupt = rtl8169interrupt;
-	edev->detach = rtl8169detach;
-//	edev->ifstat = rtl8169ifstat;
-//	edev->ctl = nil;
-//
-//	edev->arg = edev;
-//	edev->promiscuous = rtl8169promiscuous;
-//	edev->multicast = rtl8169multicast;
-
-	return 0;
-}
--- a/os/boot/pc/ether82557.c
+++ /dev/null
@@ -1,882 +1,0 @@
-/*
- * Intel 82557 Fast Ethernet PCI Bus LAN Controller
- * as found on the Intel EtherExpress PRO/100B. This chip is full
- * of smarts, unfortunately none of them are in the right place.
- * To do:
- *	the PCI scanning code could be made common to other adapters;
- *	PCI code needs rewritten to handle byte, word, dword accesses
- *	  and using the devno as a bus+dev+function triplet.
- */
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-#include "etherif.h"
-
-enum {
-	Nrfd		= 4,		/* receive frame area */
-
-	NullPointer	= 0xFFFFFFFF,	/* 82557 NULL pointer */
-};
-
-enum {					/* CSR */
-	Status		= 0x00,		/* byte or word (word includes Ack) */
-	Ack		= 0x01,		/* byte */
-	CommandR	= 0x02,		/* byte or word (word includes Interrupt) */
-	Interrupt	= 0x03,		/* byte */
-	Pointer		= 0x04,		/* dword */
-	Port		= 0x08,		/* dword */
-	Fcr		= 0x0C,		/* Flash control register */
-	Ecr		= 0x0E,		/* EEPROM control register */
-	Mcr		= 0x10,		/* MDI control register */
-};
-
-enum {					/* Status */
-	RUidle		= 0x0000,
-	RUsuspended	= 0x0004,
-	RUnoresources	= 0x0008,
-	RUready		= 0x0010,
-	RUrbd		= 0x0020,	/* bit */
-	RUstatus	= 0x003F,	/* mask */
-
-	CUidle		= 0x0000,
-	CUsuspended	= 0x0040,
-	CUactive	= 0x0080,
-	CUstatus	= 0x00C0,	/* mask */
-
-	StatSWI		= 0x0400,	/* SoftWare generated Interrupt */
-	StatMDI		= 0x0800,	/* MDI r/w done */
-	StatRNR		= 0x1000,	/* Receive unit Not Ready */
-	StatCNA		= 0x2000,	/* Command unit Not Active (Active->Idle) */
-	StatFR		= 0x4000,	/* Finished Receiving */
-	StatCX		= 0x8000,	/* Command eXecuted */
-	StatTNO		= 0x8000,	/* Transmit NOT OK */
-};
-
-enum {					/* Command (byte) */
-	CUnop		= 0x00,
-	CUstart		= 0x10,
-	CUresume	= 0x20,
-	LoadDCA		= 0x40,		/* Load Dump Counters Address */
-	DumpSC		= 0x50,		/* Dump Statistical Counters */
-	LoadCUB		= 0x60,		/* Load CU Base */
-	ResetSA		= 0x70,		/* Dump and Reset Statistical Counters */
-
-	RUstart		= 0x01,
-	RUresume	= 0x02,
-	RUabort		= 0x04,
-	LoadHDS		= 0x05,		/* Load Header Data Size */
-	LoadRUB		= 0x06,		/* Load RU Base */
-	RBDresume	= 0x07,		/* Resume frame reception */
-};
-
-enum {					/* Interrupt (byte) */
-	InterruptM	= 0x01,		/* interrupt Mask */
-	InterruptSI	= 0x02,		/* Software generated Interrupt */
-};
-
-enum {					/* Ecr */
-	EEsk		= 0x01,		/* serial clock */
-	EEcs		= 0x02,		/* chip select */
-	EEdi		= 0x04,		/* serial data in */
-	EEdo		= 0x08,		/* serial data out */
-
-	EEstart		= 0x04,		/* start bit */
-	EEread		= 0x02,		/* read opcode */
-};
-
-enum {					/* Mcr */
-	MDIread		= 0x08000000,	/* read opcode */
-	MDIwrite	= 0x04000000,	/* write opcode */
-	MDIready	= 0x10000000,	/* ready bit */
-	MDIie		= 0x20000000,	/* interrupt enable */
-};
-
-typedef struct Rfd {
-	int	field;
-	ulong	link;
-	ulong	rbd;
-	ushort	count;
-	ushort	size;
-
-	Etherpkt;
-} Rfd;
-
-enum {					/* field */
-	RfdCollision	= 0x00000001,
-	RfdIA		= 0x00000002,	/* IA match */
-	RfdRxerr	= 0x00000010,	/* PHY character error */
-	RfdType		= 0x00000020,	/* Type frame */
-	RfdRunt		= 0x00000080,
-	RfdOverrun	= 0x00000100,
-	RfdBuffer	= 0x00000200,
-	RfdAlignment	= 0x00000400,
-	RfdCRC		= 0x00000800,
-
-	RfdOK		= 0x00002000,	/* frame received OK */
-	RfdC		= 0x00008000,	/* reception Complete */
-	RfdSF		= 0x00080000,	/* Simplified or Flexible (1) Rfd */
-	RfdH		= 0x00100000,	/* Header RFD */
-
-	RfdI		= 0x20000000,	/* Interrupt after completion */
-	RfdS		= 0x40000000,	/* Suspend after completion */
-	RfdEL		= 0x80000000,	/* End of List */
-};
-
-enum {					/* count */
-	RfdF		= 0x00004000,
-	RfdEOF		= 0x00008000,
-};
-
-typedef struct Cb {
-	int	command;
-	ulong	link;
-	uchar	data[24];	/* CbIAS + CbConfigure */
-} Cb;
-
-typedef struct TxCB {
-	int	command;
-	ulong	link;
-	ulong	tbd;
-	ushort	count;
-	uchar	threshold;
-	uchar	number;
-} TxCB;
-
-enum {					/* action command */
-	CbOK		= 0x00002000,	/* DMA completed OK */
-	CbC		= 0x00008000,	/* execution Complete */
-
-	CbNOP		= 0x00000000,
-	CbIAS		= 0x00010000,	/* Indvidual Address Setup */
-	CbConfigure	= 0x00020000,
-	CbMAS		= 0x00030000,	/* Multicast Address Setup */
-	CbTransmit	= 0x00040000,
-	CbDump		= 0x00060000,
-	CbDiagnose	= 0x00070000,
-	CbCommand	= 0x00070000,	/* mask */
-
-	CbSF		= 0x00080000,	/* CbTransmit */
-
-	CbI		= 0x20000000,	/* Interrupt after completion */
-	CbS		= 0x40000000,	/* Suspend after completion */
-	CbEL		= 0x80000000,	/* End of List */
-};
-
-enum {					/* CbTransmit count */
-	CbEOF		= 0x00008000,
-};
-
-typedef struct Ctlr Ctlr;
-typedef struct Ctlr {
-	int	port;
-	Pcidev*	pcidev;
-	Ctlr*	next;
-	int	active;
-
-	int	eepromsz;		/* address size in bits */
-	ushort*	eeprom;
-
-	int	ctlrno;
-	char*	type;
-
-	uchar	configdata[24];
-
-	Rfd	rfd[Nrfd];
-	int	rfdl;
-	int	rfdx;
-
-	Block*	cbqhead;
-	Block*	cbqtail;
-	int	cbqbusy;
-} Ctlr;
-
-static Ctlr* ctlrhead;
-static Ctlr* ctlrtail;
-
-static uchar configdata[24] = {
-	0x16,				/* byte count */
-	0x44,				/* Rx/Tx FIFO limit */
-	0x00,				/* adaptive IFS */
-	0x00,	
-	0x04,				/* Rx DMA maximum byte count */
-	0x84,				/* Tx DMA maximum byte count */
-	0x33,				/* late SCB, CNA interrupts */
-	0x01,				/* discard short Rx frames */
-	0x00,				/* 503/MII */
-
-	0x00,	
-	0x2E,				/* normal operation, NSAI */
-	0x00,				/* linear priority */
-	0x60,				/* inter-frame spacing */
-	0x00,	
-	0xF2,	
-	0x48,				/* promiscuous mode off */
-	0x00,	
-	0x40,	
-	0xF2,				/* transmit padding enable */
-	0x80,				/* full duplex pin enable */
-	0x3F,				/* no Multi IA */
-	0x05,				/* no Multi Cast ALL */
-};
-
-#define csr8r(c, r)	(inb((c)->port+(r)))
-#define csr16r(c, r)	(ins((c)->port+(r)))
-#define csr32r(c, r)	(inl((c)->port+(r)))
-#define csr8w(c, r, b)	(outb((c)->port+(r), (int)(b)))
-#define csr16w(c, r, w)	(outs((c)->port+(r), (ushort)(w)))
-#define csr32w(c, r, l)	(outl((c)->port+(r), (ulong)(l)))
-
-static void
-custart(Ctlr* ctlr)
-{
-	if(ctlr->cbqhead == 0){
-		ctlr->cbqbusy = 0;
-		return;
-	}
-	ctlr->cbqbusy = 1;
-
-	csr32w(ctlr, Pointer, PADDR(ctlr->cbqhead->rp));
-	while(csr8r(ctlr, CommandR))
-		;
-	csr8w(ctlr, CommandR, CUstart);
-}
-
-static void
-action(Ctlr* ctlr, Block* bp)
-{
-	Cb *cb;
-
-	cb = (Cb*)bp->rp;
-	cb->command |= CbEL;
-
-	if(ctlr->cbqhead){
-		ctlr->cbqtail->next = bp;
-		cb = (Cb*)ctlr->cbqtail->rp;
-		cb->link = PADDR(bp->rp);
-		cb->command &= ~CbEL;
-	}
-	else
-		ctlr->cbqhead = bp;
-	ctlr->cbqtail = bp;
-
-	if(ctlr->cbqbusy == 0)
-		custart(ctlr);
-}
-
-static void
-attach(Ether* ether)
-{
-	int status;
-	Ctlr *ctlr;
-
-	ctlr = ether->ctlr;
-	status = csr16r(ctlr, Status);
-	if((status & RUstatus) == RUidle){
-		csr32w(ctlr, Pointer, PADDR(&ctlr->rfd[ctlr->rfdx]));
-		while(csr8r(ctlr, CommandR))
-			;
-		csr8w(ctlr, CommandR, RUstart);
-	}
-}
-
-static void
-configure(void* arg, int promiscuous)
-{
-	Ctlr *ctlr;
-	Block *bp;
-	Cb *cb;
-
-	ctlr = ((Ether*)arg)->ctlr;
-
-	bp = allocb(sizeof(Cb));
-	cb = (Cb*)bp->rp;
-	bp->wp += sizeof(Cb);
-
-	cb->command = CbConfigure;
-	cb->link = NullPointer;
-	memmove(cb->data, ctlr->configdata, sizeof(ctlr->configdata));
-	if(promiscuous)
-		cb->data[15] |= 0x01;
-	action(ctlr, bp);
-}
-
-static void
-transmit(Ether* ether)
-{
-	Block *bp;
-	TxCB *txcb;
-	RingBuf *tb;
-
-	for(tb = &ether->tb[ether->ti]; tb->owner == Interface; tb = &ether->tb[ether->ti]){
-		bp = allocb(tb->len+sizeof(TxCB));
-		txcb = (TxCB*)bp->wp;
-		bp->wp += sizeof(TxCB);
-
-		txcb->command = CbTransmit;
-		txcb->link = NullPointer;
-		txcb->tbd = NullPointer;
-		txcb->count = CbEOF|tb->len;
-		txcb->threshold = 2;
-		txcb->number = 0;
-
-		memmove(bp->wp, tb->pkt, tb->len);
-		memmove(bp->wp+Eaddrlen, ether->ea, Eaddrlen);
-		bp->wp += tb->len;
-
-		action(ether->ctlr, bp);
-
-		tb->owner = Host;
-		ether->ti = NEXT(ether->ti, ether->ntb);
-	}
-}
-
-static void
-interrupt(Ureg*, void* arg)
-{
-	Rfd *rfd;
-	Block *bp;
-	Ctlr *ctlr;
-	Ether *ether;
-	int status;
-	RingBuf *rb;
-
-	ether = arg;
-	ctlr = ether->ctlr;
-
-	for(;;){
-		status = csr16r(ctlr, Status);
-		csr8w(ctlr, Ack, (status>>8) & 0xFF);
-
-		if((status & (StatCX|StatFR|StatCNA|StatRNR)) == 0)
-			return;
-
-		if(status & StatFR){
-			rfd = &ctlr->rfd[ctlr->rfdx];
-			while(rfd->field & RfdC){
-				rb = &ether->rb[ether->ri];
-				if(rb->owner == Interface){
-					rb->owner = Host;
-					rb->len = rfd->count & 0x3FFF;
-					memmove(rb->pkt, rfd->d, rfd->count & 0x3FFF);
-					ether->ri = NEXT(ether->ri, ether->nrb);
-				}
-
-				/*
-				 * Reinitialise the frame for reception and bump
-				 * the receive frame processing index;
-				 * bump the sentinel index, mark the new sentinel
-				 * and clear the old sentinel suspend bit;
-				 * set bp and rfd for the next receive frame to
-				 * process.
-				 */
-				rfd->field = 0;
-				rfd->count = 0;
-				ctlr->rfdx = NEXT(ctlr->rfdx, Nrfd);
-
-				rfd = &ctlr->rfd[ctlr->rfdl];
-				ctlr->rfdl = NEXT(ctlr->rfdl, Nrfd);
-				ctlr->rfd[ctlr->rfdl].field |= RfdS;
-				rfd->field &= ~RfdS;
-
-				rfd = &ctlr->rfd[ctlr->rfdx];
-			}
-			status &= ~StatFR;
-		}
-
-		if(status & StatRNR){
-			while(csr8r(ctlr, CommandR))
-				;
-			csr8w(ctlr, CommandR, RUresume);
-
-			status &= ~StatRNR;
-		}
-
-		if(status & StatCNA){
-			while(bp = ctlr->cbqhead){
-				if((((Cb*)bp->rp)->command & CbC) == 0)
-					break;
-				ctlr->cbqhead = bp->next;
-				freeb(bp);
-			}
-			custart(ctlr);
-
-			status &= ~StatCNA;
-		}
-
-		if(status & (StatCX|StatFR|StatCNA|StatRNR|StatMDI|StatSWI))
-			panic("%s#%d: status %uX\n", ctlr->type,  ctlr->ctlrno, status);
-	}
-}
-
-static void
-ctlrinit(Ctlr* ctlr)
-{
-	int i;
-	Rfd *rfd;
-	ulong link;
-
-	link = NullPointer;
-	for(i = Nrfd-1; i >= 0; i--){
-		rfd = &ctlr->rfd[i];
-
-		rfd->field = 0;
-		rfd->link = link;
-		link = PADDR(rfd);
-		rfd->rbd = NullPointer;
-		rfd->count = 0;
-		rfd->size = sizeof(Etherpkt);
-	}
-	ctlr->rfd[Nrfd-1].link = PADDR(&ctlr->rfd[0]);
-
-	ctlr->rfdl = 0;
-	ctlr->rfd[0].field |= RfdS;
-	ctlr->rfdx = 2;
-
-	memmove(ctlr->configdata, configdata, sizeof(configdata));
-}
-
-static int
-miir(Ctlr* ctlr, int phyadd, int regadd)
-{
-	int mcr, timo;
-
-	csr32w(ctlr, Mcr, MDIread|(phyadd<<21)|(regadd<<16));
-	mcr = 0;
-	for(timo = 64; timo; timo--){
-		mcr = csr32r(ctlr, Mcr);
-		if(mcr & MDIready)
-			break;
-		microdelay(1);
-	}
-
-	if(mcr & MDIready)
-		return mcr & 0xFFFF;
-
-	return -1;
-}
-
-static int
-miiw(Ctlr* ctlr, int phyadd, int regadd, int data)
-{
-	int mcr, timo;
-
-	csr32w(ctlr, Mcr, MDIwrite|(phyadd<<21)|(regadd<<16)|(data & 0xFFFF));
-	mcr = 0;
-	for(timo = 64; timo; timo--){
-		mcr = csr32r(ctlr, Mcr);
-		if(mcr & MDIready)
-			break;
-		microdelay(1);
-	}
-
-	if(mcr & MDIready)
-		return 0;
-
-	return -1;
-}
-
-static int
-hy93c46r(Ctlr* ctlr, int r)
-{
-	int data, i, op, size;
-
-	/*
-	 * Hyundai HY93C46 or equivalent serial EEPROM.
-	 * This sequence for reading a 16-bit register 'r'
-	 * in the EEPROM is taken straight from Section
-	 * 3.3.4.2 of the Intel 82557 User's Guide.
-	 */
-reread:
-	csr16w(ctlr, Ecr, EEcs);
-	op = EEstart|EEread;
-	for(i = 2; i >= 0; i--){
-		data = (((op>>i) & 0x01)<<2)|EEcs;
-		csr16w(ctlr, Ecr, data);
-		csr16w(ctlr, Ecr, data|EEsk);
-		microdelay(1);
-		csr16w(ctlr, Ecr, data);
-		microdelay(1);
-	}
-
-	/*
-	 * First time through must work out the EEPROM size.
-	 */
-	if((size = ctlr->eepromsz) == 0)
-		size = 8;
-
-	for(size = size-1; size >= 0; size--){
-		data = (((r>>size) & 0x01)<<2)|EEcs;
-		csr16w(ctlr, Ecr, data);
-		csr16w(ctlr, Ecr, data|EEsk);
-		delay(1);
-		csr16w(ctlr, Ecr, data);
-		microdelay(1);
-		if(!(csr16r(ctlr, Ecr) & EEdo))
-			break;
-	}
-
-	data = 0;
-	for(i = 15; i >= 0; i--){
-		csr16w(ctlr, Ecr, EEcs|EEsk);
-		microdelay(1);
-		if(csr16r(ctlr, Ecr) & EEdo)
-			data |= (1<<i);
-		csr16w(ctlr, Ecr, EEcs);
-		microdelay(1);
-	}
-
-	csr16w(ctlr, Ecr, 0);
-
-	if(ctlr->eepromsz == 0){
-		ctlr->eepromsz = 8-size;
-		ctlr->eeprom = malloc((1<<ctlr->eepromsz)*sizeof(ushort));
-		goto reread;
-	}
-
-	return data;
-}
-
-static void
-i82557pci(void)
-{
-	Pcidev *p;
-	Ctlr *ctlr;
-
-	p = nil;
-	while(p = pcimatch(p, 0x8086, 0)){
-		switch(p->did){
-		default:
-			continue;
-		case 0x1031:		/* Intel 82562EM */
-		case 0x1050:		/* Intel 82562EZ */
-		case 0x1039:		/* Intel 82801BD PRO/100 VE */
-		case 0x103A:		/* Intel 82562 PRO/100 VE */
-		case 0x1064:		/* Intel 82562 PRO/100 VE */
-		case 0x2449:		/* Intel 82562ET */
-		case 0x1209:		/* Intel 82559ER */
-		case 0x1229:		/* Intel 8255[789] */
-		case 0x1030:		/* Intel 82559 InBusiness 10/100  */
-			break;
-		}
-
-		/*
-		 * bar[0] is the memory-mapped register address (4KB),
-		 * bar[1] is the I/O port register address (32 bytes) and
-		 * bar[2] is for the flash ROM (1MB).
-		 */
-		ctlr = malloc(sizeof(Ctlr));
-		ctlr->port = p->mem[1].bar & ~0x01;
-		ctlr->pcidev = p;
-
-		if(ctlrhead != nil)
-			ctlrtail->next = ctlr;
-		else
-			ctlrhead = ctlr;
-		ctlrtail = ctlr;
-
-		pcisetbme(p);
-	}
-}
-
-static void
-detach(Ether* ether)
-{
-	Ctlr *ctlr;
-
-	ctlr = ether->ctlr;
-
-	csr32w(ctlr, Port, 0);
-	delay(1);
-
-	while(csr8r(ctlr, CommandR))
-		;
-}
-
-static int
-scanphy(Ctlr* ctlr)
-{
-	int i, oui, x;
-
-	for(i = 0; i < 32; i++){
-		if((oui = miir(ctlr, i, 2)) == -1 || oui == 0 || oui == 0xFFFF)
-			continue;
-		oui <<= 6;
-		x = miir(ctlr, i, 3);
-		oui |= x>>10;
-		//print("phy%d: oui %uX reg1 %uX\n", i, oui, miir(ctlr, i, 1));
-
-		if(oui == 0xAA00)
-			ctlr->eeprom[6] = 0x07<<8;
-		else if(oui == 0x80017){
-			if(x & 0x01)
-				ctlr->eeprom[6] = 0x0A<<8;
-			else
-				ctlr->eeprom[6] = 0x04<<8;
-		}
-		return i;
-	}
-	return -1;
-}
-
-int
-i82557reset(Ether* ether)
-{
-	int anar, anlpar, bmcr, bmsr, force, i, phyaddr, x;
-	unsigned short sum;
-	Block *bp;
-	uchar ea[Eaddrlen];
-	Ctlr *ctlr;
-	Cb *cb;
-
-
-	if(ctlrhead == nil)
-		i82557pci();
-
-	/*
-	 * Any adapter matches if no ether->port is supplied,
-	 * otherwise the ports must match.
-	 */
-	for(ctlr = ctlrhead; ctlr != nil; ctlr = ctlr->next){
-		if(ctlr->active)
-			continue;
-		if(ether->port == 0 || ether->port == ctlr->port){
-			ctlr->active = 1;
-			break;
-		}
-	}
-	if(ctlr == nil)
-		return -1;
-
-	/*
-	 * Initialise the Ctlr structure.
-	 * Perform a software reset after which need to ensure busmastering
-	 * is still enabled. The EtherExpress PRO/100B appears to leave
-	 * the PCI configuration alone (see the 'To do' list above) so punt
-	 * for now.
-	 * Load the RUB and CUB registers for linear addressing (0).
-	 */
-	ether->ctlr = ctlr;
-	ether->port = ctlr->port;
-	ether->irq = ctlr->pcidev->intl;
-	ether->tbdf = ctlr->pcidev->tbdf;
-	ctlr->ctlrno = ether->ctlrno;
-	ctlr->type = ether->type;
-
-	csr32w(ctlr, Port, 0);
-	delay(1);
-
-	while(csr8r(ctlr, CommandR))
-		;
-	csr32w(ctlr, Pointer, 0);
-	csr8w(ctlr, CommandR, LoadRUB);
-	while(csr8r(ctlr, CommandR))
-		;
-	csr8w(ctlr, CommandR, LoadCUB);
-
-	/*
-	 * Initialise the action and receive frame areas.
-	 */
-	ctlrinit(ctlr);
-
-	/*
-	 * Read the EEPROM.
-	 * Do a dummy read first to get the size
-	 * and allocate ctlr->eeprom.
-	 */
-	hy93c46r(ctlr, 0);
-	sum = 0;
-	for(i = 0; i < (1<<ctlr->eepromsz); i++){
-		x = hy93c46r(ctlr, i);
-		ctlr->eeprom[i] = x;
-		sum += x;
-	}
-	if(sum != 0xBABA)
-		print("#l%d: EEPROM checksum - 0x%4.4uX\n", ether->ctlrno, sum);
-
-	/*
-	 * Eeprom[6] indicates whether there is a PHY and whether
-	 * it's not 10Mb-only, in which case use the given PHY address
-	 * to set any PHY specific options and determine the speed.
-	 * Unfortunately, sometimes the EEPROM is blank except for
-	 * the ether address and checksum; in this case look at the
-	 * controller type and if it's am 82558 or 82559 it has an
-	 * embedded PHY so scan for that.
-	 * If no PHY, assume 82503 (serial) operation.
-	 */
-	if((ctlr->eeprom[6] & 0x1F00) && !(ctlr->eeprom[6] & 0x8000))
-		phyaddr = ctlr->eeprom[6] & 0x00FF;
-	else
-	switch(ctlr->pcidev->rid){
-	case 0x01:			/* 82557 A-step */
-	case 0x02:			/* 82557 B-step */
-	case 0x03:			/* 82557 C-step */
-	default:
-		phyaddr = -1;
-		break;
-	case 0x04:			/* 82558 A-step */
-	case 0x05:			/* 82558 B-step */
-	case 0x06:			/* 82559 A-step */
-	case 0x07:			/* 82559 B-step */
-	case 0x08:			/* 82559 C-step */
-	case 0x09:			/* 82559ER A-step */
-		phyaddr = scanphy(ctlr);
-		break;
-	}
-	if(phyaddr >= 0){
-		/*
-		 * Resolve the highest common ability of the two
-		 * link partners. In descending order:
-		 *	0x0100		100BASE-TX Full Duplex
-		 *	0x0200		100BASE-T4
-		 *	0x0080		100BASE-TX
-		 *	0x0040		10BASE-T Full Duplex
-		 *	0x0020		10BASE-T
-		 */
-		anar = miir(ctlr, phyaddr, 0x04);
-		anlpar = miir(ctlr, phyaddr, 0x05) & 0x03E0;
-		anar &= anlpar;
-		bmcr = 0;
-		if(anar & 0x380)
-			bmcr = 0x2000;
-		if(anar & 0x0140)
-			bmcr |= 0x0100;
-
-		switch((ctlr->eeprom[6]>>8) & 0x001F){
-
-		case 0x04:				/* DP83840 */
-		case 0x0A:				/* DP83840A */
-			/*
-			 * The DP83840[A] requires some tweaking for
-			 * reliable operation.
-			 * The manual says bit 10 should be unconditionally
-			 * set although it supposedly only affects full-duplex
-			 * operation (an & 0x0140).
-			 */
-			x = miir(ctlr, phyaddr, 0x17) & ~0x0520;
-			x |= 0x0420;
-			for(i = 0; i < ether->nopt; i++){
-				if(cistrcmp(ether->opt[i], "congestioncontrol"))
-					continue;
-				x |= 0x0100;
-				break;
-			}
-			miiw(ctlr, phyaddr, 0x17, x);
-
-			/*
-			 * If the link partner can't autonegotiate, determine
-			 * the speed from elsewhere.
-			 */
-			if(anlpar == 0){
-				miir(ctlr, phyaddr, 0x01);
-				bmsr = miir(ctlr, phyaddr, 0x01);
-				x = miir(ctlr, phyaddr, 0x19);
-				if((bmsr & 0x0004) && !(x & 0x0040))
-					bmcr = 0x2000;
-			}
-			break;
-
-		case 0x07:				/* Intel 82555 */
-			/*
-			 * Auto-negotiation may fail if the other end is
-			 * a DP83840A and the cable is short.
-			 */
-			bmsr = miir(ctlr, phyaddr, 0x01);
-			if((miir(ctlr, phyaddr, 0) & 0x1000) && !(bmsr & 0x0020)){
-				miiw(ctlr, phyaddr, 0x1A, 0x2010);
-				x = miir(ctlr, phyaddr, 0);
-				miiw(ctlr, phyaddr, 0, 0x0200|x);
-				for(i = 0; i < 3000; i++){
-					delay(1);
-					if(miir(ctlr, phyaddr, 0x01) & 0x0020)
-						break;
-				}
-				miiw(ctlr, phyaddr, 0x1A, 0x2000);
-					
-				anar = miir(ctlr, phyaddr, 0x04);
-				anlpar = miir(ctlr, phyaddr, 0x05) & 0x03E0;
-				anar &= anlpar;
-				bmcr = 0;
-				if(anar & 0x380)
-					bmcr = 0x2000;
-				if(anar & 0x0140)
-					bmcr |= 0x0100;
-			}
-			break;
-		}
-
-		/*
-		 * Force speed and duplex if no auto-negotiation.
-		 */
-		if(anlpar == 0){
-			force = 0;
-			for(i = 0; i < ether->nopt; i++){
-				if(cistrcmp(ether->opt[i], "fullduplex") == 0){
-					force = 1;
-					bmcr |= 0x0100;
-					ctlr->configdata[19] |= 0x40;
-				}
-				else if(cistrcmp(ether->opt[i], "speed") == 0){
-					force = 1;
-					x = strtol(&ether->opt[i][6], 0, 0);
-					if(x == 10)
-						bmcr &= ~0x2000;
-					else if(x == 100)
-						bmcr |= 0x2000;
-					else
-						force = 0;
-				}
-			}
-			if(force)
-				miiw(ctlr, phyaddr, 0x00, bmcr);
-		}
-
-		ctlr->configdata[8] = 1;
-		ctlr->configdata[15] &= ~0x80;
-	}
-	else{
-		ctlr->configdata[8] = 0;
-		ctlr->configdata[15] |= 0x80;
-	}
-
-	/*
-	 * Load the chip configuration
-	 */
-	configure(ether, 0);
-
-	/*
-	 * Check if the adapter's station address is to be overridden.
-	 * If not, read it from the EEPROM and set in ether->ea prior to loading
-	 * the station address with the Individual Address Setup command.
-	 */
-	memset(ea, 0, Eaddrlen);
-	if(memcmp(ea, ether->ea, Eaddrlen) == 0){
-		for(i = 0; i < Eaddrlen/2; i++){
-			x = ctlr->eeprom[i];
-			ether->ea[2*i] = x & 0xFF;
-			ether->ea[2*i+1] = (x>>8) & 0xFF;
-		}
-	}
-
-	bp = allocb(sizeof(Cb));
-	cb = (Cb*)bp->rp;
-	bp->wp += sizeof(Cb);
-
-	cb->command = CbIAS;
-	cb->link = NullPointer;
-	memmove(cb->data, ether->ea, Eaddrlen);
-	action(ctlr, bp);
-
-	/*
-	 * Linkage to the generic ethernet driver.
-	 */
-	ether->attach = attach;
-	ether->transmit = transmit;
-	ether->interrupt = interrupt;
-	ether->detach = detach;
-
-	return 0;
-}
--- a/os/boot/pc/ether82563.c
+++ /dev/null
@@ -1,977 +1,0 @@
-/*
- * bootstrap driver for
- * Intel 82563, 82571, 82573 Gigabit Ethernet PCI-Express Controllers
- */
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-#include "etherif.h"
-
-/* compatibility with cpu kernels */
-#define iallocb allocb
-#ifndef CACHELINESZ
-#define CACHELINESZ	32		/* pentium & later */
-#endif
-
-/* from pci.c */
-enum
-{					/* command register pcidev->pcr */
-	IOen		= 1<<0,
-	MEMen		= 1<<1,
-	MASen		= 1<<2,
-	MemWrInv	= 1<<4,
-	PErrEn		= 1<<6,
-	SErrEn		= 1<<8,
-};
-
-/*
- * these are in the order they appear in the manual, not numeric order.
- * It was too hard to find them in the book. Ref 21489, rev 2.6
- */
-
-enum {
-	/* General */
-
-	Ctrl		= 0x00000000,	/* Device Control */
-	Status		= 0x00000008,	/* Device Status */
-	Eec		= 0x00000010,	/* EEPROM/Flash Control/Data */
-	Eerd		= 0x00000014,	/* EEPROM Read */
-	Ctrlext		= 0x00000018,	/* Extended Device Control */
-	Fla		= 0x0000001c,	/* Flash Access */
-	Mdic		= 0x00000020,	/* MDI Control */
-	Seresctl	= 0x00000024,	/* Serdes ana */
-	Fcal		= 0x00000028,	/* Flow Control Address Low */
-	Fcah		= 0x0000002C,	/* Flow Control Address High */
-	Fct		= 0x00000030,	/* Flow Control Type */
-	Kumctrlsta	= 0x00000034,	/* Kumeran Controll and Status Register */
-	Vet		= 0x00000038,	/* VLAN EtherType */
-	Fcttv		= 0x00000170,	/* Flow Control Transmit Timer Value */
-	Txcw		= 0x00000178,	/* Transmit Configuration Word */
-	Rxcw		= 0x00000180,	/* Receive Configuration Word */
-	Ledctl		= 0x00000E00,	/* LED control */
-	Pba		= 0x00001000,	/* Packet Buffer Allocation */
-
-	/* Interrupt */
-
-	Icr		= 0x000000C0,	/* Interrupt Cause Read */
-	Ics		= 0x000000C8,	/* Interrupt Cause Set */
-	Ims		= 0x000000D0,	/* Interrupt Mask Set/Read */
-	Imc		= 0x000000D8,	/* Interrupt mask Clear */
-	Iam		= 0x000000E0,	/* Interrupt acknowledge Auto Mask */
-
-	/* Receive */
-
-	Rctl		= 0x00000100,	/* Receive Control */
-	Ert		= 0x00002008,	/* Early Receive Threshold (573[EVL] only) */
-	Fcrtl		= 0x00002160,	/* Flow Control RX Threshold Low */
-	Fcrth		= 0x00002168,	/* Flow Control Rx Threshold High */
-	Psrctl		= 0x00002170,	/* Packet Split Receive Control */
-	Rdbal		= 0x00002800,	/* Rdesc Base Address Low Queue 0 */
-	Rdbah		= 0x00002804,	/* Rdesc Base Address High Queue 0 */
-	Rdlen		= 0x00002808,	/* Receive Descriptor Length Queue 0 */
-	Rdh		= 0x00002810,	/* Receive Descriptor Head Queue 0 */
-	Rdt		= 0x00002818,	/* Receive Descriptor Tail Queue 0 */
-	Rdtr		= 0x00002820,	/* Receive Descriptor Timer Ring */
-	Rxdctl		= 0x00002828,	/* Receive Descriptor Control */
-	Radv		= 0x0000282C,	/* Receive Interrupt Absolute Delay Timer */
-	Rdbal1		= 0x00002900,	/* Rdesc Base Address Low Queue 1 */
-	Rdbah1		= 0x00002804,	/* Rdesc Base Address High Queue 1 */
-	Rdlen1		= 0x00002908,	/* Receive Descriptor Length Queue 1 */
-	Rdh1		= 0x00002910,	/* Receive Descriptor Head Queue 1 */
-	Rdt1		= 0x00002918,	/* Receive Descriptor Tail Queue 1 */
-	Rxdctl1		= 0x00002928,	/* Receive Descriptor Control Queue 1 */
-	Rsrpd		= 0x00002c00,	/* Receive Small Packet Detect */
-	Raid		= 0x00002c08,	/* Receive ACK interrupt delay */
-	Cpuvec		= 0x00002c10,	/* CPU Vector */
-	Rxcsum		= 0x00005000,	/* Receive Checksum Control */
-	Rfctl		= 0x00005008,	/* Receive Filter Control */
-	Mta		= 0x00005200,	/* Multicast Table Array */
-	Ral		= 0x00005400,	/* Receive Address Low */
-	Rah		= 0x00005404,	/* Receive Address High */
-	Vfta		= 0x00005600,	/* VLAN Filter Table Array */
-	Mrqc		= 0x00005818,	/* Multiple Receive Queues Command */
-	Rssim		= 0x00005864,	/* RSS Interrupt Mask */
-	Rssir		= 0x00005868,	/* RSS Interrupt Request */
-	Reta		= 0x00005c00,	/* Redirection Table */
-	Rssrk		= 0x00005c80,	/* RSS Random Key */
-
-	/* Transmit */
-
-	Tctl		= 0x00000400,	/* Transmit Control */
-	Tipg		= 0x00000410,	/* Transmit IPG */
-	Tdbal		= 0x00003800,	/* Tdesc Base Address Low */
-	Tdbah		= 0x00003804,	/* Tdesc Base Address High */
-	Tdlen		= 0x00003808,	/* Transmit Descriptor Length */
-	Tdh		= 0x00003810,	/* Transmit Descriptor Head */
-	Tdt		= 0x00003818,	/* Transmit Descriptor Tail */
-	Tidv		= 0x00003820,	/* Transmit Interrupt Delay Value */
-	Txdctl		= 0x00003828,	/* Transmit Descriptor Control */
-	Tadv		= 0x0000382C,	/* Transmit Interrupt Absolute Delay Timer */
-	Tarc0		= 0x00003840,	/* Transmit Arbitration Counter Queue 0 */
-	Tdbal1		= 0x00003900,	/* Transmit Descriptor Base Low Queue 1 */
-	Tdbah1		= 0x00003904,	/* Transmit Descriptor Base High Queue 1 */
-	Tdlen1		= 0x00003908,	/* Transmit Descriptor Length Queue 1 */
-	Tdh1		= 0x00003910,	/* Transmit Descriptor Head Queue 1 */
-	Tdt1		= 0x00003918,	/* Transmit Descriptor Tail Queue 1 */
-	Txdctl1		= 0x00003928,	/* Transmit Descriptor Control 1 */
-	Tarc1		= 0x00003940,	/* Transmit Arbitration Counter Queue 1 */
-
-	/* Statistics */
-
-	Statistics	= 0x00004000,	/* Start of Statistics Area */
-	Gorcl		= 0x88/4,	/* Good Octets Received Count */
-	Gotcl		= 0x90/4,	/* Good Octets Transmitted Count */
-	Torl		= 0xC0/4,	/* Total Octets Received */
-	Totl		= 0xC8/4,	/* Total Octets Transmitted */
-	Nstatistics	= 64,
-
-};
-
-enum {					/* Ctrl */
-	GIOmd		= 1<<2,		/* BIO master disable */
-	Lrst		= 1<<3,		/* link reset */
-	Slu		= 1<<6,		/* Set Link Up */
-	SspeedMASK	= 3<<8,		/* Speed Selection */
-	SspeedSHIFT	= 8,
-	Sspeed10	= 0x00000000,	/* 10Mb/s */
-	Sspeed100	= 0x00000100,	/* 100Mb/s */
-	Sspeed1000	= 0x00000200,	/* 1000Mb/s */
-	Frcspd		= 1<<11,	/* Force Speed */
-	Frcdplx		= 1<<12,	/* Force Duplex */
-	SwdpinsloMASK	= 0x003C0000,	/* Software Defined Pins - lo nibble */
-	SwdpinsloSHIFT	= 18,
-	SwdpioloMASK	= 0x03C00000,	/* Software Defined Pins - I or O */
-	SwdpioloSHIFT	= 22,
-	Devrst		= 1<<26,	/* Device Reset */
-	Rfce		= 1<<27,	/* Receive Flow Control Enable */
-	Tfce		= 1<<28,	/* Transmit Flow Control Enable */
-	Vme		= 1<<30,	/* VLAN Mode Enable */
-	Phy_rst		= 1<<31,	/* Phy Reset */
-};
-
-enum {					/* Status */
-	Lu		= 1<<1,		/* Link Up */
-	Lanid		= 3<<2,		/* mask for Lan ID. */
-	Txoff		= 1<<4,		/* Transmission Paused */
-	Tbimode		= 1<<5,		/* TBI Mode Indication */
-	SpeedMASK	= 0x000000C0,
-	Speed10		= 0x00000000,	/* 10Mb/s */
-	Speed100	= 0x00000040,	/* 100Mb/s */
-	Speed1000	= 0x00000080,	/* 1000Mb/s */
-	Phyra		= 1<<10,	/* PHY Reset Asserted */
-	GIOme		= 1<<19,	/* GIO Master Enable Status */
-};
-
-enum {					/* Ctrl and Status */
-	Fd		= 0x00000001,	/* Full-Duplex */
-	AsdvMASK	= 0x00000300,
-	Asdv10		= 0x00000000,	/* 10Mb/s */
-	Asdv100		= 0x00000100,	/* 100Mb/s */
-	Asdv1000	= 0x00000200,	/* 1000Mb/s */
-};
-
-enum {					/* Eec */
-	Sk		= 1<<0,		/* Clock input to the EEPROM */
-	Cs		= 1<<1,		/* Chip Select */
-	Di		= 1<<2,		/* Data Input to the EEPROM */
-	Do		= 1<<3,		/* Data Output from the EEPROM */
-	Areq		= 1<<6,		/* EEPROM Access Request */
-	Agnt		= 1<<7,		/* EEPROM Access Grant */
-};
-
-enum {					/* Eerd */
-	ee_start	= 1<<0,		/* Start Read */
-	ee_done		= 1<<1,		/* Read done */
-	ee_addr		= 0xfff8<<2,	/* Read address [15:2] */
-	ee_data		= 0xffff<<16,	/* Read Data; Data returned from eeprom/nvm */
-};
-
-enum {					/* Ctrlext */
-	Asdchk		= 1<<12,	/* ASD Check */
-	Eerst		= 1<<13,	/* EEPROM Reset */
-	Spdbyps		= 1<<15,	/* Speed Select Bypass */
-};
-
-enum {					/* EEPROM content offsets */
-	Ea		= 0x00,		/* Ethernet Address */
-	Cf		= 0x03,		/* Compatibility Field */
-	Icw1		= 0x0A,		/* Initialization Control Word 1 */
-	Sid		= 0x0B,		/* Subsystem ID */
-	Svid		= 0x0C,		/* Subsystem Vendor ID */
-	Did		= 0x0D,		/* Device ID */
-	Vid		= 0x0E,		/* Vendor ID */
-	Icw2		= 0x0F,		/* Initialization Control Word 2 */
-};
-
-enum {					/* Mdic */
-	MDIdMASK	= 0x0000FFFF,	/* Data */
-	MDIdSHIFT	= 0,
-	MDIrMASK	= 0x001F0000,	/* PHY Register Address */
-	MDIrSHIFT	= 16,
-	MDIpMASK	= 0x03E00000,	/* PHY Address */
-	MDIpSHIFT	= 21,
-	MDIwop		= 0x04000000,	/* Write Operation */
-	MDIrop		= 0x08000000,	/* Read Operation */
-	MDIready	= 0x10000000,	/* End of Transaction */
-	MDIie		= 0x20000000,	/* Interrupt Enable */
-	MDIe		= 0x40000000,	/* Error */
-};
-
-enum {					/* Icr, Ics, Ims, Imc */
-	Txdw		= 0x00000001,	/* Transmit Descriptor Written Back */
-	Txqe		= 0x00000002,	/* Transmit Queue Empty */
-	Lsc		= 0x00000004,	/* Link Status Change */
-	Rxseq		= 0x00000008,	/* Receive Sequence Error */
-	Rxdmt0		= 0x00000010,	/* Rdesc Minimum Threshold Reached */
-	Rxo		= 0x00000040,	/* Receiver Overrun */
-	Rxt0		= 0x00000080,	/* Receiver Timer Interrupt */
-	Mdac		= 0x00000200,	/* MDIO Access Completed */
-	Rxcfg		= 0x00000400,	/* Receiving /C/ ordered sets */
-	Gpi0		= 0x00000800,	/* General Purpose Interrupts */
-	Gpi1		= 0x00001000,
-	Gpi2		= 0x00002000,
-	Gpi3		= 0x00004000,
-	Ack		= 0x00020000,	/* receive ACK frame */
-};
-
-enum {					/* Txcw */
-	TxcwFd		= 0x00000020,	/* Full Duplex */
-	TxcwHd		= 0x00000040,	/* Half Duplex */
-	TxcwPauseMASK	= 0x00000180,	/* Pause */
-	TxcwPauseSHIFT	= 7,
-	TxcwPs		= 1<<TxcwPauseSHIFT,	/* Pause Supported */
-	TxcwAs		= 2<<TxcwPauseSHIFT,	/* Asymmetric FC desired */
-	TxcwRfiMASK	= 0x00003000,	/* Remote Fault Indication */
-	TxcwRfiSHIFT	= 12,
-	TxcwNpr		= 0x00008000,	/* Next Page Request */
-	TxcwConfig	= 0x40000000,	/* Transmit COnfig Control */
-	TxcwAne		= 0x80000000,	/* Auto-Negotiation Enable */
-};
-
-enum {					/* Rctl */
-	Rrst		= 0x00000001,	/* Receiver Software Reset */
-	Ren		= 0x00000002,	/* Receiver Enable */
-	Sbp		= 0x00000004,	/* Store Bad Packets */
-	Upe		= 0x00000008,	/* Unicast Promiscuous Enable */
-	Mpe		= 0x00000010,	/* Multicast Promiscuous Enable */
-	Lpe		= 0x00000020,	/* Long Packet Reception Enable */
-	LbmMASK		= 0x000000C0,	/* Loopback Mode */
-	LbmOFF		= 0x00000000,	/* No Loopback */
-	LbmTBI		= 0x00000040,	/* TBI Loopback */
-	LbmMII		= 0x00000080,	/* GMII/MII Loopback */
-	LbmXCVR		= 0x000000C0,	/* Transceiver Loopback */
-	RdtmsMASK	= 0x00000300,	/* Rdesc Minimum Threshold Size */
-	RdtmsHALF	= 0x00000000,	/* Threshold is 1/2 Rdlen */
-	RdtmsQUARTER	= 0x00000100,	/* Threshold is 1/4 Rdlen */
-	RdtmsEIGHTH	= 0x00000200,	/* Threshold is 1/8 Rdlen */
-	MoMASK		= 0x00003000,	/* Multicast Offset */
-	Bam		= 0x00008000,	/* Broadcast Accept Mode */
-	BsizeMASK	= 0x00030000,	/* Receive Buffer Size */
-	Bsize2048	= 0x00000000,
-	Bsize1024	= 0x00010000,
-	Bsize512	= 0x00020000,
-	Bsize256	= 0x00030000,
-	Vfe		= 0x00040000,	/* VLAN Filter Enable */
-	Cfien		= 0x00080000,	/* Canonical Form Indicator Enable */
-	Cfi		= 0x00100000,	/* Canonical Form Indicator value */
-	Dpf		= 0x00400000,	/* Discard Pause Frames */
-	Pmcf		= 0x00800000,	/* Pass MAC Control Frames */
-	Bsex		= 0x02000000,	/* Buffer Size Extension */
-	Secrc		= 0x04000000,	/* Strip CRC from incoming packet */
-};
-
-enum {					/* Tctl */
-	Trst		= 0x00000001,	/* Transmitter Software Reset */
-	Ten		= 0x00000002,	/* Transmit Enable */
-	Psp		= 0x00000008,	/* Pad Short Packets */
-	Mulr		= 0x10000000,	/* Allow multiple concurrent requests */
-	CtMASK		= 0x00000FF0,	/* Collision Threshold */
-	CtSHIFT		= 4,
-	ColdMASK	= 0x003FF000,	/* Collision Distance */
-	ColdSHIFT	= 12,
-	Swxoff		= 0x00400000,	/* Sofware XOFF Transmission */
-	Pbe		= 0x00800000,	/* Packet Burst Enable */
-	Rtlc		= 0x01000000,	/* Re-transmit on Late Collision */
-	Nrtu		= 0x02000000,	/* No Re-transmit on Underrrun */
-};
-
-enum {					/* [RT]xdctl */
-	PthreshMASK	= 0x0000003F,	/* Prefetch Threshold */
-	PthreshSHIFT	= 0,
-	HthreshMASK	= 0x00003F00,	/* Host Threshold */
-	HthreshSHIFT	= 8,
-	WthreshMASK	= 0x003F0000,	/* Writebacj Threshold */
-	WthreshSHIFT	= 16,
-	Gran		= 0x01000000,	/* Granularity */
-};
-
-enum {					/* Rxcsum */
-	PcssMASK	= 0x000000FF,	/* Packet Checksum Start */
-	PcssSHIFT	= 0,
-	Ipofl		= 0x00000100,	/* IP Checksum Off-load Enable */
-	Tuofl		= 0x00000200,	/* TCP/UDP Checksum Off-load Enable */
-};
-
-typedef struct Rdesc {			/* Receive Descriptor */
-	uint	addr[2];
-	ushort	length;
-	ushort	checksum;
-	uchar	status;
-	uchar	errors;
-	ushort	special;
-} Rdesc;
-
-enum {					/* Rdesc status */
-	Rdd		= 0x01,		/* Descriptor Done */
-	Reop		= 0x02,		/* End of Packet */
-	Ixsm		= 0x04,		/* Ignore Checksum Indication */
-	Vp		= 0x08,		/* Packet is 802.1Q (matched VET) */
-	Tcpcs		= 0x20,		/* TCP Checksum Calculated on Packet */
-	Ipcs		= 0x40,		/* IP Checksum Calculated on Packet */
-	Pif		= 0x80,		/* Passed in-exact filter */
-};
-
-enum {					/* Rdesc errors */
-	Ce		= 0x01,		/* CRC Error or Alignment Error */
-	Se		= 0x02,		/* Symbol Error */
-	Seq		= 0x04,		/* Sequence Error */
-	Cxe		= 0x10,		/* Carrier Extension Error */
-	Tcpe		= 0x20,		/* TCP/UDP Checksum Error */
-	Ipe		= 0x40,		/* IP Checksum Error */
-	Rxe		= 0x80,		/* RX Data Error */
-};
-
-typedef struct Tdesc {			/* Legacy+Normal Transmit Descriptor */
-	uint	addr[2];
-	uint	control;		/* varies with descriptor type */
-	uint	status;			/* varies with descriptor type */
-} Tdesc;
-
-enum {					/* Tdesc control */
-	LenMASK		= 0x000FFFFF,	/* Data/Packet Length Field */
-	LenSHIFT	= 0,
-	DtypeCD		= 0x00000000,	/* Data Type 'Context Descriptor' */
-	DtypeDD		= 0x00100000,	/* Data Type 'Data Descriptor' */
-	PtypeTCP	= 0x01000000,	/* TCP/UDP Packet Type (CD) */
-	Teop		= 0x01000000,	/* End of Packet (DD) */
-	PtypeIP		= 0x02000000,	/* IP Packet Type (CD) */
-	Ifcs		= 0x02000000,	/* Insert FCS (DD) */
-	Tse		= 0x04000000,	/* TCP Segmentation Enable */
-	Rs		= 0x08000000,	/* Report Status */
-	Rps		= 0x10000000,	/* Report Status Sent */
-	Dext		= 0x20000000,	/* Descriptor Extension */
-	Vle		= 0x40000000,	/* VLAN Packet Enable */
-	Ide		= 0x80000000,	/* Interrupt Delay Enable */
-};
-
-enum {					/* Tdesc status */
-	Tdd		= 0x00000001,	/* Descriptor Done */
-	Ec		= 0x00000002,	/* Excess Collisions */
-	Lc		= 0x00000004,	/* Late Collision */
-	Tu		= 0x00000008,	/* Transmit Underrun */
-	CssMASK		= 0x0000FF00,	/* Checksum Start Field */
-	CssSHIFT	= 8,
-};
-
-enum {
-	Nrdesc		= 128,		/* multiple of 8 */
-	Ntdesc		= 128,		/* multiple of 8 */
-};
-
-enum {
-	i82563,
-	i82571,
-	i82573,
-};
-
-static char *tname[] = {
-	"i82563",
-	"i82571",
-	"i82573",
-};
-
-#define Type	tname[ctlr->type]
-
-typedef struct Ctlr Ctlr;
-struct Ctlr {
-	int	port;
-	Pcidev	*pcidev;
-	Ctlr	*next;
-	int	active;
-	int	cls;
-	ushort	eeprom[0x40];
-	uchar	ra[Eaddrlen];		/* receive address */
-	int	type;
-
-	int*	nic;
-	Lock	imlock;
-	int	im;			/* interrupt mask */
-
-	Lock	slock;
-	uint	statistics[Nstatistics];
-
-	Rdesc	*rdba;			/* receive descriptor base address */
-	Block	**rb;			/* receive buffers */
-	int	rdh;			/* receive descriptor head */
-	int	rdt;			/* receive descriptor tail */
-
-	Tdesc	*tdba;			/* transmit descriptor base address */
-	Lock	tdlock;
-	Block	**tb;			/* transmit buffers */
-	int	tdh;			/* transmit descriptor head */
-	int	tdt;			/* transmit descriptor tail */
-
-	int	txcw;
-	int	fcrtl;
-	int	fcrth;
-
-	/* bootstrap goo */
-	Block	*bqhead;		/* transmission queue */
-	Block	*bqtail;
-};
-
-static Ctlr	*ctlrhead;
-static Ctlr	*ctlrtail;
-
-#define csr32r(c, r)	(*((c)->nic+((r)/4)))
-#define csr32w(c, r, v)	(*((c)->nic+((r)/4)) = (v))
-
-static void
-i82563im(Ctlr* ctlr, int im)
-{
-	ilock(&ctlr->imlock);
-	ctlr->im |= im;
-	csr32w(ctlr, Ims, ctlr->im);
-	iunlock(&ctlr->imlock);
-}
-
-static void
-i82563attach(Ether* edev)
-{
-	int ctl;
-	Ctlr *ctlr;
-
-	ctlr = edev->ctlr;
-	i82563im(ctlr, 0);
-	ctl = csr32r(ctlr, Rctl)|Ren;
-	csr32w(ctlr, Rctl, ctl);
-	ctl = csr32r(ctlr, Tctl)|Ten;
-	csr32w(ctlr, Tctl, ctl);
-}
-
-
-static void
-txstart(Ether *edev)
-{
-	int tdh, tdt;
-	Ctlr *ctlr = edev->ctlr;
-	Block *bp;
-	Tdesc *tdesc;
-
-	/*
-	 * Try to fill the ring back up, moving buffers from the transmit q.
-	 */
-	tdh = PREV(ctlr->tdh, Ntdesc);
-	for(tdt = ctlr->tdt; tdt != tdh; tdt = NEXT(tdt, Ntdesc)){
-		/* pull off the head of the transmission queue */
-		if((bp = ctlr->bqhead) == nil)	/* was qget(edev->oq) */
-			break;
-		ctlr->bqhead = bp->next;
-		if (ctlr->bqtail == bp)
-			ctlr->bqtail = nil;
-
-		/* set up a descriptor for it */
-		tdesc = &ctlr->tdba[tdt];
-		tdesc->addr[0] = PCIWADDR(bp->rp);
-		tdesc->addr[1] = 0;
-		tdesc->control = /* Ide | */ Rs | Ifcs | Teop | BLEN(bp);
-
-		ctlr->tb[tdt] = bp;
-	}
-	ctlr->tdt = tdt;
-	csr32w(ctlr, Tdt, tdt);
-	i82563im(ctlr, Txdw);
-}
-
-static Block *
-fromringbuf(Ether *ether)
-{
-	RingBuf *tb = &ether->tb[ether->ti];
-	Block *bp = allocb(tb->len);
-
-	memmove(bp->wp, tb->pkt, tb->len);
-	memmove(bp->wp+Eaddrlen, ether->ea, Eaddrlen);
-	bp->wp += tb->len;
-	return bp;
-}
-
-static void
-i82563transmit(Ether* edev)
-{
-	Block *bp;
-	Ctlr *ctlr;
-	Tdesc *tdesc;
-	RingBuf *tb;
-	int tdh;
-
-	ctlr = edev->ctlr;
-	ilock(&ctlr->tdlock);
-
-	/*
-	 * Free any completed packets
-	 * - try to get the soft tdh to catch the tdt;
-	 * - if the packet had an underrun bump the threshold
-	 *   - the Tu bit doesn't seem to ever be set, perhaps
-	 *     because Rs mode is used?
-	 */
-	tdh = ctlr->tdh;
-	for(;;){
-		tdesc = &ctlr->tdba[tdh];
-		if(!(tdesc->status & Tdd))
-			break;
-		if(ctlr->tb[tdh] != nil){
-			freeb(ctlr->tb[tdh]);
-			ctlr->tb[tdh] = nil;
-		}
-		tdesc->status = 0;
-		tdh = NEXT(tdh, Ntdesc);
-	}
-	ctlr->tdh = tdh;
-
-	/* copy packets from the software RingBuf to the transmission q */
-	while((tb = &edev->tb[edev->ti])->owner == Interface){
-		bp = fromringbuf(edev);
-//		print("#l%d: tx %d %E %E\n", edev->ctlrno, edev->ti, bp->rp,
-//			bp->rp+6);
-
-		if(ctlr->bqhead)
-			ctlr->bqtail->next = bp;
-		else
-			ctlr->bqhead = bp;
-		ctlr->bqtail = bp;
-
-		txstart(edev);		/* kick transmitter */
-		tb->owner = Host;	/* give descriptor back */
-		edev->ti = NEXT(edev->ti, edev->ntb);
-	}
-	iunlock(&ctlr->tdlock);
-}
-
-static void
-i82563replenish(Ctlr* ctlr)
-{
-	int rdt;
-	Block *bp;
-	Rdesc *rdesc;
-
-	rdt = ctlr->rdt;
-	while(NEXT(rdt, Nrdesc) != ctlr->rdh){
-		rdesc = &ctlr->rdba[rdt];
-		if(ctlr->rb[rdt] != nil){
-			/* nothing to do */
-		}
-		else if((bp = iallocb(2048)) != nil){
-			ctlr->rb[rdt] = bp;
-			rdesc->addr[0] = PCIWADDR(bp->rp);
-			rdesc->addr[1] = 0;
-		}
-		else
-			break;
-		rdesc->status = 0;
-
-		rdt = NEXT(rdt, Nrdesc);
-	}
-	ctlr->rdt = rdt;
-	csr32w(ctlr, Rdt, rdt);
-}
-
-static void
-toringbuf(Ether *ether, Block *bp)
-{
-	RingBuf *rb = &ether->rb[ether->ri];
-
-	if (rb->owner == Interface) {
-		rb->len = BLEN(bp);
-		memmove(rb->pkt, bp->rp, rb->len);
-		rb->owner = Host;
-		ether->ri = NEXT(ether->ri, ether->nrb);
-	} else if (debug)
-		print("#l%d: toringbuf: dropping packets @ ri %d\n",
-			ether->ctlrno, ether->ri);
-}
-
-static void
-i82563interrupt(Ureg*, void* arg)
-{
-	int icr, im, rdh, txdw = 0;
-	Block *bp;
-	Ctlr *ctlr;
-	Ether *edev;
-	Rdesc *rdesc;
-
-	edev = arg;
-	ctlr = edev->ctlr;
-
-	ilock(&ctlr->imlock);
-	csr32w(ctlr, Imc, ~0);
-	im = ctlr->im;
-
-	for(icr = csr32r(ctlr, Icr); icr & ctlr->im; icr = csr32r(ctlr, Icr)){
-		if(icr & (Rxseq|Lsc)){
-			/* should be more here */
-		}
-
-		rdh = ctlr->rdh;
-		for (;;) {
-			rdesc = &ctlr->rdba[rdh];
-			if(!(rdesc->status & Rdd))
-				break;
-			if ((rdesc->status & Reop) && rdesc->errors == 0) {
-				bp = ctlr->rb[rdh];
-				if(0 && memcmp(bp->rp, broadcast, 6) != 0)
-					print("#l%d: rx %d %E %E %d\n",
-						edev->ctlrno, rdh, bp->rp,
-						bp->rp+6, rdesc->length);
-				ctlr->rb[rdh] = nil;
-				bp->wp += rdesc->length;
-				toringbuf(edev, bp);
-				freeb(bp);
-			} else if (rdesc->status & Reop && rdesc->errors)
-				print("%s: input packet error 0x%ux\n",
-					Type, rdesc->errors);
-			rdesc->status = 0;
-			rdh = NEXT(rdh, Nrdesc);
-		}
-		ctlr->rdh = rdh;
-		if(icr & Rxdmt0)
-			i82563replenish(ctlr);
-		if(icr & Txdw){
-			im &= ~Txdw;
-			txdw++;
-		}
-	}
-	ctlr->im = im;
-	csr32w(ctlr, Ims, im);
-	iunlock(&ctlr->imlock);
-	if(txdw)
-		i82563transmit(edev);
-}
-
-static void
-i82563init(Ether* edev)
-{
-	int csr, i, r;
-	Ctlr *ctlr;
-
-	ctlr = edev->ctlr;
-	csr = edev->ea[3]<<24 | edev->ea[2]<<16 | edev->ea[1]<<8 | edev->ea[0];
-	csr32w(ctlr, Ral, csr);
-	csr = 0x80000000 | edev->ea[5]<<8 | edev->ea[4];
-	csr32w(ctlr, Rah, csr);
-	for (i = 1; i < 16; i++) {
-		csr32w(ctlr, Ral+i*8, 0);
-		csr32w(ctlr, Rah+i*8, 0);
-	}
-	for(i = 0; i < 128; i++)
-		csr32w(ctlr, Mta+i*4, 0);
-	csr32w(ctlr, Rctl, 0);
-	ctlr->rdba = xspanalloc(Nrdesc*sizeof(Rdesc), 256, 0);
-	csr32w(ctlr, Rdbal, PCIWADDR(ctlr->rdba));
-	csr32w(ctlr, Rdbah, 0);
-	csr32w(ctlr, Rdlen, Nrdesc*sizeof(Rdesc));
-	ctlr->rdh = 0;
-	csr32w(ctlr, Rdh, ctlr->rdh);
-	ctlr->rdt = 0;
-	csr32w(ctlr, Rdt, ctlr->rdt);
-	ctlr->rb = malloc(sizeof(Block*)*Nrdesc);
-	i82563replenish(ctlr);
-	csr32w(ctlr, Rdtr, 0);
-	csr32w(ctlr, Rctl, Dpf | Bsize2048 | Bam | RdtmsHALF);
-	i82563im(ctlr, Rxt0 | Rxo | Rxdmt0 | Rxseq | Ack);
-
-	csr32w(ctlr, Tctl, 0x0F<<CtSHIFT | Psp | 0x3f<<ColdSHIFT | Mulr);
-	csr32w(ctlr, Tipg, 6<<20 | 8<<10 | 8);
-	csr32w(ctlr, Tidv, 1);
-
-	ctlr->tdba = xspanalloc(Ntdesc*sizeof(Tdesc), 256, 0);
-	memset(ctlr->tdba, 0, Ntdesc*sizeof(Tdesc));
-	csr32w(ctlr, Tdbal, PCIWADDR(ctlr->tdba));
-
-	csr32w(ctlr, Tdbah, 0);
-	csr32w(ctlr, Tdlen, Ntdesc*sizeof(Tdesc));
-	ctlr->tdh = 0;
-	csr32w(ctlr, Tdh, ctlr->tdh);
-	ctlr->tdt = 0;
-	csr32w(ctlr, Tdt, ctlr->tdt);
-	ctlr->tb = malloc(sizeof(Block*)*Ntdesc);
-
-//	r = 4<<WthreshSHIFT | 4<<HthreshSHIFT | 8<<PthreshSHIFT;
-//	csr32w(ctlr, Txdctl, r);
-	csr32w(ctlr, Rxcsum, Tuofl | Ipofl | ETHERHDRSIZE<<PcssSHIFT);
-	r = csr32r(ctlr, Tctl);
-	r |= Ten;
-	csr32w(ctlr, Tctl, r);
-}
-
-
-static ushort
-eeread(Ctlr* ctlr, int adr)
-{
-	csr32w(ctlr, Eerd, ee_start | adr << 2);
-	while ((csr32r(ctlr, Eerd) & ee_done) == 0)
-		;
-	return csr32r(ctlr, Eerd) >> 16;
-}
-
-static int
-eeload(Ctlr* ctlr)
-{
-	ushort sum;
-	int data, adr;
-
-	sum = 0;
-	for (adr = 0; adr < 0x40; adr++) {
-		data = eeread(ctlr, adr);
-		ctlr->eeprom[adr] = data;
-		sum += data;
-	}
-	return sum;
-}
-
-
-static void
-detach(Ctlr *ctlr)
-{
-	int r;
-
-	csr32w(ctlr, Imc, ~0);
-	csr32w(ctlr, Rctl, 0);
-	csr32w(ctlr, Tctl, 0);
-
-	delay(10);
-
-	r = csr32r(ctlr, Ctrl);
-	csr32w(ctlr, Ctrl, Devrst | r);
-	/* apparently needed on multi-GHz processors to avoid infinite loops */
-	delay(1);
-	while(csr32r(ctlr, Ctrl) & Devrst)
-		;
-
-	if(1 || ctlr->type != i82563){
-		r = csr32r(ctlr, Ctrl);
-		csr32w(ctlr, Ctrl, Slu | r);
-	}
-
-	csr32w(ctlr, Ctrlext, Eerst | csr32r(ctlr, Ctrlext));
-	delay(1);
-	while(csr32r(ctlr, Ctrlext) & Eerst)
-		;
-
-	csr32w(ctlr, Imc, ~0);
-	delay(1);
-	while(csr32r(ctlr, Icr))
-		;
-}
-
-static void
-i82563detach(Ether *edev)
-{
-	detach(edev->ctlr);
-}
-
-static void
-i82563shutdown(Ether* ether)
-{
-	i82563detach(ether);
-}
-
-static int
-i82563reset(Ctlr* ctlr)
-{
-	int i, r;
-
-	detach(ctlr);
-
-	r = eeload(ctlr);
-	if (r != 0 && r != 0xBABA){
-		print("%s: bad EEPROM checksum - 0x%4.4ux\n", Type, r);
-		return -1;
-	}
-
-	for(i = Ea; i < Eaddrlen/2; i++){
-		ctlr->ra[2*i]   = ctlr->eeprom[i];
-		ctlr->ra[2*i+1] = ctlr->eeprom[i]>>8;
-	}
-	r = (csr32r(ctlr, Status) & Lanid) >> 2;
-	ctlr->ra[5] += r;		/* ea ctlr[1] = ea ctlr[0]+1 */
-
-	r = ctlr->ra[3]<<24 | ctlr->ra[2]<<16 | ctlr->ra[1]<<8 | ctlr->ra[0];
-	csr32w(ctlr, Ral, r);
-	r = 0x80000000 | ctlr->ra[5]<<8 | ctlr->ra[4];
-	csr32w(ctlr, Rah, r);
-	for(i = 1; i < 16; i++){
-		csr32w(ctlr, Ral+i*8, 0);
-		csr32w(ctlr, Rah+i*8, 0);
-	}
-
-	for(i = 0; i < 128; i++)
-		csr32w(ctlr, Mta+i*4, 0);
-
-	csr32w(ctlr, Fcal, 0x00C28001);
-	csr32w(ctlr, Fcah, 0x00000100);
-	csr32w(ctlr, Fct,  0x00008808);
-	csr32w(ctlr, Fcttv, 0x00000100);
-
-	csr32w(ctlr, Fcrtl, ctlr->fcrtl);
-	csr32w(ctlr, Fcrth, ctlr->fcrth);
-
-	ilock(&ctlr->imlock);
-	csr32w(ctlr, Imc, ~0);
-	ctlr->im = 0;		/* was = Lsc, which hangs some controllers */
-	csr32w(ctlr, Ims, ctlr->im);
-	iunlock(&ctlr->imlock);
-
-	return 0;
-}
-
-static void
-i82563pci(void)
-{
-	int port, type, cls;
-	Pcidev *p;
-	Ctlr *ctlr;
-	static int first = 1;
-
-	if (first)
-		first = 0;
-	else
-		return;
-
-	p = nil;
-	while(p = pcimatch(p, 0x8086, 0)){
-		switch(p->did){
-		case 0x1096:
-		case 0x10ba:
-			type = i82563;
-			break;
-		case 0x108b:		/*  e */
-		case 0x108c:		/*  e (iamt) */
-		case 0x109a:		/*  l */
-			type = i82573;
-			break;
-		default:
-			continue;
-		}
-
-		port = upamalloc(p->mem[0].bar & ~0x0F, p->mem[0].size, 0);
-		if(port == 0){
-			print("%s: can't map %d @ 0x%8.8lux\n", tname[type],
-				p->mem[0].size, p->mem[0].bar);
-			continue;
-		}
-
-		if(p->pcr & MemWrInv){
-			cls = pcicfgr8(p, PciCLS) * 4;
-			if(cls != CACHELINESZ)
-				pcicfgw8(p, PciCLS, CACHELINESZ/4);
-		}
-
-		cls = pcicfgr8(p, PciCLS);
-		switch(cls){
-		default:
-			print("%s: unexpected CLS - %d bytes\n",
-				tname[type], cls*sizeof(long));
-			break;
-		case 0x00:
-		case 0xFF:
-			/* alphapc 164lx returns 0 */
-			print("%s: unusable PciCLS: %d, using %d longs\n",
-				tname[type], cls, CACHELINESZ/sizeof(long));
-			cls = CACHELINESZ/sizeof(long);
-			pcicfgw8(p, PciCLS, cls);
-			break;
-		case 0x08:
-		case 0x10:
-			break;
-		}
-
-		ctlr = malloc(sizeof(Ctlr));
-		ctlr->port = port;
-		ctlr->pcidev = p;
-		ctlr->cls = cls*4;
-		ctlr->type = type;
-		ctlr->nic = KADDR(ctlr->port);
-		if(i82563reset(ctlr)){
-			free(ctlr);
-			continue;
-		}
-		pcisetbme(p);
-
-		if(ctlrhead != nil)
-			ctlrtail->next = ctlr;
-		else
-			ctlrhead = ctlr;
-		ctlrtail = ctlr;
-	}
-}
-
-static uchar nilea[Eaddrlen];
-
-int
-i82563pnp(Ether* edev)
-{
-	Ctlr *ctlr;
-
-	if(ctlrhead == nil)
-		i82563pci();
-
-	/*
-	 * Any adapter matches if no edev->port is supplied,
-	 * otherwise the ports must match.
-	 */
-	for(ctlr = ctlrhead; ctlr != nil; ctlr = ctlr->next){
-		if(ctlr->active)
-			continue;
-		if(edev->port == 0 || edev->port == ctlr->port){
-			ctlr->active = 1;
-			break;
-		}
-	}
-	if(ctlr == nil)
-		return -1;
-
-	edev->ctlr = ctlr;
-	edev->port = ctlr->port;
-	edev->irq = ctlr->pcidev->intl;
-	edev->tbdf = ctlr->pcidev->tbdf;
-//	edev->mbps = 1000;
-
-	if(memcmp(edev->ea, nilea, Eaddrlen) == 0)
-		memmove(edev->ea, ctlr->ra, Eaddrlen);
-	i82563init(edev);
-
-	/*
-	 * Linkage to the generic ethernet driver.
-	 */
-	edev->attach = i82563attach;
-	edev->transmit = i82563transmit;
-	edev->interrupt = i82563interrupt;
-	edev->detach = i82563detach;
-
-	/*
-	 * with the current structure, there is no right place for this.
-	 * ideally, we recognize the interface, note it's down and move on.
-	 * currently either we can skip the interface or note it is down,
-	 * but not both.
-	 */
-	if((csr32r(ctlr, Status)&Lu) == 0){
-		print("ether#%d: 82563 (%s): link down\n", edev->ctlrno, Type);
-		return -1;
-	}
-
-	return 0;
-}
--- a/os/boot/pc/ether83815.c
+++ /dev/null
@@ -1,820 +1,0 @@
-/*
- * National Semiconductor DP83815
- *
- * Supports only internal PHY and has been tested on:
- *	Netgear FA311TX (using Netgear DS108 10/100 hub)
- * To do:
- *	check Ethernet address;
- *	test autonegotiation on 10 Mbit, and 100 Mbit full duplex;
- *	external PHY via MII (should be common code for MII);
- *	thresholds;
- *	ring sizing;
- *	physical link changes/disconnect;
- *	push initialisation back to attach.
- *
- * C H Forsyth, forsyth@vitanuova.com, 18th June 2001.
- */
-
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-#include "etherif.h"
-
-#define DEBUG		(1)
-#define debug		if(DEBUG)print
-
-enum {
-	Nrde		= 8,
-	Ntde		= 8,
-};
-
-#define Rbsz		ROUNDUP(sizeof(Etherpkt)+4, 4)
-
-typedef struct Des {
-	ulong	next;
-	int	cmdsts;
-	ulong	addr;
-	Block*	bp;
-} Des;
-
-enum {	/* cmdsts */
-	Own		= 1<<31,	/* set by data producer to hand to consumer */
-	More	= 1<<30,	/* more of packet in next descriptor */
-	Intr		= 1<<29,	/* interrupt when device is done with it */
-	Supcrc	= 1<<28,	/* suppress crc on transmit */
-	Inccrc	= 1<<28,	/* crc included on receive (always) */
-	Ok		= 1<<27,	/* packet ok */
-	Size		= 0xFFF,	/* packet size in bytes */
-
-	/* transmit */
-	Txa	= 1<<26,	/* transmission aborted */
-	Tfu	= 1<<25,	/* transmit fifo underrun */
-	Crs	= 1<<24,	/* carrier sense lost */
-	Td	= 1<<23,	/* transmission deferred */
-	Ed	= 1<<22,	/* excessive deferral */
-	Owc	= 1<<21,	/* out of window collision */
-	Ec	= 1<<20,	/* excessive collisions */
-	/* 19-16 collision count */
-
-	/* receive */
-	Rxa	= 1<<26,	/* receive aborted (same as Rxo) */
-	Rxo	= 1<<25,	/* receive overrun */
-	Dest	= 3<<23,	/* destination class */
-	  Drej=	0<<23,		/* packet was rejected */
-	  Duni=	1<<23,		/* unicast */
-	  Dmulti=	2<<23,		/* multicast */
-	  Dbroad=	3<<23,		/* broadcast */
-	Long = 1<<22,	/* too long packet received */
-	Runt =  1<<21,	/* packet less than 64 bytes */
-	Ise =	1<<20,	/* invalid symbol */
-	Crce =	1<<19,	/* invalid crc */
-	Fae =	1<<18,	/* frame alignment error */
-	Lbp =	1<<17,	/* loopback packet */
-	Col =	1<<16,	/* collision during receive */
-};
-
-enum {					/* Variants */
-	Nat83815		= (0x0020<<16)|0x100B,
-};
-
-typedef struct Ctlr Ctlr;
-typedef struct Ctlr {
-	int	port;
-	Pcidev*	pcidev;
-	Ctlr*	next;
-	int	active;
-	int	id;			/* (pcidev->did<<16)|pcidev->vid */
-
-	ushort	srom[0xB+1];
-	uchar	sromea[Eaddrlen];			/* MAC address */
-
-	uchar	fd;			/* option or auto negotiation */
-
-	int	mbps;
-
-	Lock	ilock;
-
-	Des*	rdr;			/* receive descriptor ring */
-	int	nrdr;			/* size of rdr */
-	int	rdrx;			/* index into rdr */
-
-	Lock	tlock;
-	Des*	tdr;			/* transmit descriptor ring */
-	int	ntdr;			/* size of tdr */
-	int	tdrh;			/* host index into tdr */
-	int	tdri;			/* interface index into tdr */
-	int	ntq;			/* descriptors active */
-	int	ntqmax;
-	Block*	bqhead;	/* transmission queue */
-	Block*	bqtail;
-
-	ulong	rxa;			/* receive statistics */
-	ulong	rxo;
-	ulong	rlong;
-	ulong	runt;
-	ulong	ise;
-	ulong	crce;
-	ulong	fae;
-	ulong	lbp;
-	ulong	col;
-	ulong	rxsovr;
-	ulong	rxorn;
-
-	ulong	txa;			/* transmit statistics */
-	ulong	tfu;
-	ulong	crs;
-	ulong	td;
-	ulong	ed;
-	ulong	owc;
-	ulong	ec;
-	ulong	txurn;
-
-	ulong	dperr;		/* system errors */
-	ulong	rmabt;
-	ulong	rtabt;
-	ulong	sserr;
-	ulong	rxsover;
-} Ctlr;
-
-static Ctlr* ctlrhead;
-static Ctlr* ctlrtail;
-
-enum {
-	/* registers (could memory map) */
-	Rcr=		0x00,	/* command register */
-	  Rst=		1<<8,
-	  Rxr=		1<<5,	/* receiver reset */
-	  Txr=		1<<4,	/* transmitter reset */
-	  Rxd=		1<<3,	/* receiver disable */
-	  Rxe=		1<<2,	/* receiver enable */
-	  Txd=		1<<1,	/* transmitter disable */
-	  Txe=		1<<0,	/* transmitter enable */
-	Rcfg=	0x04,	/* configuration */
-	  Lnksts=		1<<31,	/* link good */
-	  Speed100=	1<<30,	/* 100 Mb/s link */
-	  Fdup=		1<<29,	/* full duplex */
-	  Pol=		1<<28,	/* polarity reversal (10baseT) */
-	  Aneg_dn=	1<<27,	/* autonegotiation done */
-	  Pint_acen=	1<<17,	/* PHY interrupt auto clear enable */
-	  Pause_adv=	1<<16,	/* advertise pause during auto neg */
-	  Paneg_ena=	1<<13,	/* auto negotiation enable */
-	  Paneg_all=	7<<13,	/* auto negotiation enable 10/100 half & full */
-	  Ext_phy=	1<<12,	/* enable MII for external PHY */
-	  Phy_rst=		1<<10,	/* reset internal PHY */
-	  Phy_dis=		1<<9,	/* disable internal PHY (eg, low power) */
-	  Req_alg=	1<<7,	/* PCI bus request: set means less aggressive */
-	  Sb=			1<<6,	/* single slot back-off not random */
-	  Pow=		1<<5,	/* out of window timer selection */
-	  Exd=		1<<4,	/* disable excessive deferral timer */
-	  Pesel=		1<<3,	/* parity error algorithm selection */
-	  Brom_dis=	1<<2,	/* disable boot rom interface */
-	  Bem=		1<<0,	/* big-endian mode */
-	Rmear=	0x08,	/* eeprom access */
-	  Mdc=		1<<6,	/* MII mangement check */
-	  Mddir=		1<<5,	/* MII management direction */
-	  Mdio=		1<<4,	/* MII mangement data */
-	  Eesel=		1<<3,	/* EEPROM chip select */
-	  Eeclk=		1<<2,	/* EEPROM clock */
-	  Eedo=		1<<1,	/* EEPROM data out (from chip) */
-	  Eedi=		1<<0,	/* EEPROM data in (to chip) */
-	Rptscr=	0x0C,	/* pci test control */
-	Risr=		0x10,	/* interrupt status */
-	  Txrcmp=	1<<25,	/* transmit reset complete */
-	  Rxrcmp=	1<<24,	/* receiver reset complete */
-	  Dperr=		1<<23,	/* detected parity error */
-	  Sserr=		1<<22,	/* signalled system error */
-	  Rmabt=		1<<21,	/* received master abort */
-	  Rtabt=		1<<20,	/* received target abort */
-	  Rxsovr=		1<<16,	/* RX status FIFO overrun */
-	  Hiberr=		1<<15,	/* high bits error set (OR of 25-16) */
-	  Phy=		1<<14,	/* PHY interrupt */
-	  Pme=		1<<13,	/* power management event (wake online) */
-	  Swi=		1<<12,	/* software interrupt */
-	  Mib=		1<<11,	/* MIB service */
-	  Txurn=		1<<10,	/* TX underrun */
-	  Txidle=		1<<9,	/* TX idle */
-	  Txerr=		1<<8,	/* TX packet error */
-	  Txdesc=		1<<7,	/* TX descriptor (with Intr bit done) */
-	  Txok=		1<<6,	/* TX ok */
-	  Rxorn=		1<<5,	/* RX overrun */
-	  Rxidle=		1<<4,	/* RX idle */
-	  Rxearly=		1<<3,	/* RX early threshold */
-	  Rxerr=		1<<2,	/* RX packet error */
-	  Rxdesc=		1<<1,	/* RX descriptor (with Intr bit done) */
-	  Rxok=		1<<0,	/* RX ok */
-	Rimr=	0x14,	/* interrupt mask */
-	Rier=	0x18,	/* interrupt enable */
-	  Ie=			1<<0,	/* interrupt enable */
-	Rtxdp=	0x20,	/* transmit descriptor pointer */
-	Rtxcfg=	0x24,	/* transmit configuration */
-	  Csi=		1<<31,	/* carrier sense ignore (needed for full duplex) */
-	  Hbi=		1<<30,	/* heartbeat ignore (needed for full duplex) */
-	  Atp=		1<<28,	/* automatic padding of runt packets */
-	  Mxdma=		7<<20,	/* maximum dma transfer field */
-	  Mxdma32=	4<<20,	/* 4x32-bit words (32 bytes) */
-	  Mxdma64=	5<<20,	/* 8x32-bit words (64 bytes) */
-	  Flth=		0x3F<<8,	/* Tx fill threshold, units of 32 bytes (must be > Mxdma) */
-	  Drth=		0x3F<<0,	/* Tx drain threshold (units of 32 bytes) */
-	  Flth128=		4<<8,	/* fill at 128 bytes */
-	  Drth512=	16<<0,	/* drain at 512 bytes */
-	Rrxdp=	0x30,	/* receive descriptor pointer */
-	Rrxcfg=	0x34,	/* receive configuration */
-	  Atx=		1<<28,	/* accept transmit packets (needed for full duplex) */
-	  Rdrth=		0x1F<<1,	/* Rx drain threshold (units of 32 bytes) */
-	  Rdrth64=	2<<1,	/* drain at 64 bytes */
-	Rccsr=	0x3C,	/* CLKRUN control/status */
-	  Pmests=		1<<15,	/* PME status */
-	Rwcsr=	0x40,	/* wake on lan control/status */
-	Rpcr=	0x44,	/* pause control/status */
-	Rrfcr=	0x48,	/* receive filter/match control */
-	  Rfen=		1<<31,	/* receive filter enable */
-	  Aab=		1<<30,	/* accept all broadcast */
-	  Aam=		1<<29,	/* accept all multicast */
-	  Aau=		1<<28,	/* accept all unicast */
-	  Apm=		1<<27,	/* accept on perfect match */
-	  Apat=		0xF<<23,	/* accept on pattern match */
-	  Aarp=		1<<22,	/* accept ARP */
-	  Mhen=		1<<21,	/* multicast hash enable */
-	  Uhen=		1<<20,	/* unicast hash enable */
-	  Ulm=		1<<19,	/* U/L bit mask */
-						/* bits 0-9 are rfaddr */
-	Rrfdr=	0x4C,	/* receive filter/match data */
-	Rbrar=	0x50,	/* boot rom address */
-	Rbrdr=	0x54,	/* boot rom data */
-	Rsrr=	0x58,	/* silicon revision */
-	Rmibc=	0x5C,	/* MIB control */
-					/* 60-78 MIB data */
-
-	/* PHY registers */
-	Rbmcr=	0x80,	/* basic mode configuration */
-	  Reset=		1<<15,
-	  Sel100=		1<<13,	/* select 100Mb/sec if no auto neg */
-	  Anena=		1<<12,	/* auto negotiation enable */
-	  Anrestart=	1<<9,	/* restart auto negotiation */
-	  Selfdx=		1<<8,	/* select full duplex if no auto neg */
-	Rbmsr=	0x84,	/* basic mode status */
-	  Ancomp=	1<<5,	/* autonegotiation complete */
-	Rphyidr1= 0x88,
-	Rphyidr2= 0x8C,
-	Ranar=	0x90,	/* autonegotiation advertisement */
-	Ranlpar=	0x94,	/* autonegotiation link partner ability */
-	Raner=	0x98,	/* autonegotiation expansion */
-	Rannptr=	0x9C,	/* autonegotiation next page TX */
-	Rphysts=	0xC0,	/* PHY status */
-	Rmicr=	0xC4,	/* MII control */
-	  Inten=		1<<1,	/* PHY interrupt enable */
-	Rmisr=	0xC8,	/* MII status */
-	Rfcscr=	0xD0,	/* false carrier sense counter */
-	Rrecr=	0xD4,	/* receive error counter */
-	Rpcsr=	0xD8,	/* 100Mb config/status */
-	Rphycr=	0xE4,	/* PHY control */
-	Rtbscr=	0xE8,	/* 10BaseT status/control */
-};
-
-/*
- * eeprom addresses
- * 	7 to 9 (16 bit words): mac address, shifted and reversed
- */
-
-#define csr32r(c, r)	(inl((c)->port+(r)))
-#define csr32w(c, r, l)	(outl((c)->port+(r), (ulong)(l)))
-#define csr16r(c, r)	(ins((c)->port+(r)))
-#define csr16w(c, r, l)	(outs((c)->port+(r), (ulong)(l)))
-
-static void
-dumpcregs(Ctlr *ctlr)
-{
-	int i;
-
-	for(i=0; i<=0x5C; i+=4)
-		print("%2.2ux %8.8lux\n", i, csr32r(ctlr, i));
-}
-
-static void
-attach(Ether* ether)
-{
-	Ctlr *ctlr;
-
-	ctlr = ether->ctlr;
-	ilock(&ctlr->ilock);
-	if(0)
-		dumpcregs(ctlr);
-	csr32w(ctlr, Rcr, Rxe);
-	iunlock(&ctlr->ilock);
-}
-
-static void
-detach(Ether* ether)
-{
-	Ctlr *ctlr;
-
-	ctlr = ether->ctlr;
-	csr32w(ctlr, Rcr, 0);
-	delay(1);
-}
-
-static void
-txstart(Ether* ether)
-{
-	Ctlr *ctlr;
-	Block *bp;
-	Des *des;
-	int started;
-
-	ctlr = ether->ctlr;
-	started = 0;
-	while(ctlr->ntq < ctlr->ntdr-1){
-		bp = ctlr->bqhead;
-		if(bp == nil)
-			break;
-		ctlr->bqhead = bp->next;
-		des = &ctlr->tdr[ctlr->tdrh];
-		des->bp = bp;
-		des->addr = PADDR(bp->rp);
-		ctlr->ntq++;
-		coherence();
-		des->cmdsts = Own | BLEN(bp);
-		ctlr->tdrh = NEXT(ctlr->tdrh, ctlr->ntdr);
-		started = 1;
-	}
-	if(started){
-		coherence();
-		csr32w(ctlr, Rcr, Txe);	/* prompt */
-	}
-
-	if(ctlr->ntq > ctlr->ntqmax)
-		ctlr->ntqmax = ctlr->ntq;
-}
-
-static void
-transmit(Ether* ether)
-{
-	Ctlr *ctlr;
-	Block *bp;
-	RingBuf *tb;
-
-	ctlr = ether->ctlr;
-	ilock(&ctlr->tlock);
-	while((tb = &ether->tb[ether->ti])->owner == Interface){
-		bp = allocb(tb->len);
-		memmove(bp->wp, tb->pkt, tb->len);
-		memmove(bp->wp+Eaddrlen, ether->ea, Eaddrlen);
-		bp->wp += tb->len;
-		if(ctlr->bqhead)
-			ctlr->bqtail->next = bp;
-		else
-			ctlr->bqhead = bp;
-		ctlr->bqtail = bp;
-		txstart(ether);
-		tb->owner = Host;
-		ether->ti = NEXT(ether->ti, ether->ntb);
-	}
-	iunlock(&ctlr->tlock);
-}
-
-static void
-txrxcfg(Ctlr *ctlr, int txdrth)
-{
-	ulong rx, tx;
-
-	rx = csr32r(ctlr, Rrxcfg);
-	tx = csr32r(ctlr, Rtxcfg);
-	if(ctlr->fd){
-		rx |= Atx;
-		tx |= Csi | Hbi;
-	}else{
-		rx &= ~Atx;
-		tx &= ~(Csi | Hbi);
-	}
-	tx &= ~(Mxdma|Drth|Flth);
-	tx |= Mxdma64 | Flth128 | txdrth;
-	csr32w(ctlr, Rtxcfg, tx);
-	rx &= ~(Mxdma|Rdrth);
-	rx |= Mxdma64 | Rdrth64;
-	csr32w(ctlr, Rrxcfg, rx);
-}
-
-static void
-interrupt(Ureg*, void* arg)
-{
-	Ctlr *ctlr;
-	Ether *ether;
-	int status, cmdsts;
-	Des *des;
-	RingBuf *rb;
-
-	ether = arg;
-	ctlr = ether->ctlr;
-
-	while((status = csr32r(ctlr, Risr)) != 0){
-
-		status &= ~(Pme|Mib);
-		status &= ~(Hiberr|Txrcmp|Rxrcmp|Rxsovr|Dperr|Sserr|Rmabt|Rtabt);
-
-		/*
-		 * Received packets.
-		 */
-		if(status & (Rxdesc|Rxok|Rxerr|Rxearly|Rxorn)){
-			des = &ctlr->rdr[ctlr->rdrx];
-			while((cmdsts = des->cmdsts) & Own){
-				rb = &ether->rb[ether->ri];
-				if(rb->owner == Interface && (cmdsts&Ok)){
-					rb->len = (cmdsts&Size)-4;
-					memmove(rb->pkt, des->bp->rp, rb->len);
-					rb->owner = Host;
-					ether->ri = NEXT(ether->ri, ether->nrb);
-				}
-
-				des->cmdsts = Rbsz;
-				coherence();
-
-				ctlr->rdrx = NEXT(ctlr->rdrx, ctlr->nrdr);
-				des = &ctlr->rdr[ctlr->rdrx];
-			}
-			status &= ~(Rxdesc|Rxok|Rxerr|Rxearly|Rxorn);
-		}
-
-		/*
-		 * Check the transmit side:
-		 *	check for Transmit Underflow and Adjust
-		 *	the threshold upwards;
-		 *	free any transmitted buffers and try to
-		 *	top-up the ring.
-		 */
-		if(status & Txurn){
-			ctlr->txurn++;
-			ilock(&ctlr->ilock);
-			/* change threshold */
-			iunlock(&ctlr->ilock);
-			status &= ~(Txurn);
-		}
-
-		ilock(&ctlr->tlock);
-		while(ctlr->ntq){
-			des = &ctlr->tdr[ctlr->tdri];
-			cmdsts = des->cmdsts;
-			if(cmdsts & Own)
-				break;
-
-			freeb(des->bp);
-			des->bp = nil;
-			des->cmdsts = 0;
-
-			ctlr->ntq--;
-			ctlr->tdri = NEXT(ctlr->tdri, ctlr->ntdr);
-		}
-		txstart(ether);
-		iunlock(&ctlr->tlock);
-
-		status &= ~(Txurn|Txidle|Txerr|Txdesc|Txok);
-
-		/*
-		 * Anything left not catered for?
-		 */
-		if(status)
-			print("#l%d: status %8.8uX\n", ether->ctlrno, status);
-	}
-}
-
-static void
-ctlrinit(Ether* ether)
-{
-	Ctlr *ctlr;
-	Des *des, *last;
-
-	ctlr = ether->ctlr;
-
-	/*
-	 * Allocate and initialise the receive ring;
-	 * allocate and initialise the transmit ring;
-	 * unmask interrupts and start the transmit side
-	 */
-	ctlr->rdr = malloc(ctlr->nrdr*sizeof(Des));
-	last = nil;
-	for(des = ctlr->rdr; des < &ctlr->rdr[ctlr->nrdr]; des++){
-		des->bp = allocb(Rbsz);
-		des->cmdsts = Rbsz;
-		des->addr = PADDR(des->bp->rp);
-		if(last != nil)
-			last->next = PADDR(des);
-		last = des;
-	}
-	ctlr->rdr[ctlr->nrdr-1].next = PADDR(ctlr->rdr);
-	ctlr->rdrx = 0;
-	csr32w(ctlr, Rrxdp, PADDR(ctlr->rdr));
-
-	ctlr->tdr = xspanalloc(ctlr->ntdr*sizeof(Des), 8*sizeof(ulong), 0);
-	last = nil;
-	for(des = ctlr->tdr; des < &ctlr->tdr[ctlr->ntdr]; des++){
-		des->cmdsts = 0;
-		des->bp = nil;
-		des->addr = ~0;
-		if(last != nil)
-			last->next = PADDR(des);
-		last = des;
-	}
-	ctlr->tdr[ctlr->ntdr-1].next = PADDR(ctlr->tdr);
-	ctlr->tdrh = 0;
-	ctlr->tdri = 0;
-	csr32w(ctlr, Rtxdp, PADDR(ctlr->tdr));
-
-	txrxcfg(ctlr, Drth512);
-
-	csr32w(ctlr, Rimr, Dperr|Sserr|Rmabt|Rtabt|Rxsovr|Hiberr|Txurn|Txerr|Txdesc|Txok|Rxorn|Rxerr|Rxdesc|Rxok);	/* Phy|Pme|Mib */
-	csr32r(ctlr, Risr);	/* clear status */
-	csr32w(ctlr, Rier, Ie);
-}
-
-static void
-eeclk(Ctlr *ctlr, int clk)
-{
-	csr32w(ctlr, Rmear, Eesel | clk);
-	microdelay(2);
-}
-
-static void
-eeidle(Ctlr *ctlr)
-{
-	int i;
-
-	eeclk(ctlr, 0);
-	eeclk(ctlr, Eeclk);
-	for(i=0; i<25; i++){
-		eeclk(ctlr, 0);
-		eeclk(ctlr, Eeclk);
-	}
-	eeclk(ctlr, 0);
-	csr32w(ctlr, Rmear, 0);
-	microdelay(2);
-}
-
-static int
-eegetw(Ctlr *ctlr, int a)
-{
-	int d, i, w, v;
-
-	eeidle(ctlr);
-	eeclk(ctlr, 0);
-	eeclk(ctlr, Eeclk);
-	d = 0x180 | a;
-	for(i=0x400; i; i>>=1){
-		v = (d & i) ? Eedi : 0;
-		eeclk(ctlr, v);
-		eeclk(ctlr, Eeclk|v);
-	}
-	eeclk(ctlr, 0);
-
-	w = 0;
-	for(i=0x8000; i; i >>= 1){
-		eeclk(ctlr, Eeclk);
-		if(csr32r(ctlr, Rmear) & Eedo)
-			w |= i;
-		microdelay(2);
-		eeclk(ctlr, 0);
-	}
-	eeidle(ctlr);
-	return w;
-}
-
-static void
-softreset(Ctlr* ctlr, int resetphys)
-{
-	int i, w;
-
-	/*
-	 * Soft-reset the controller
-	 */
-	csr32w(ctlr, Rcr, Rst);
-	for(i=0;; i++){
-		if(i > 100)
-			panic("ns83815: soft reset did not complete");
-		microdelay(250);
-		if((csr32r(ctlr, Rcr) & Rst) == 0)
-			break;
-		delay(1);
-	}
-
-	csr32w(ctlr, Rccsr, Pmests);
-	csr32w(ctlr, Rccsr, 0);
-	csr32w(ctlr, Rcfg, csr32r(ctlr, Rcfg) | Pint_acen);
-
-	if(resetphys){
-		/*
-		 * Soft-reset the PHY
-		 */
-		csr32w(ctlr, Rbmcr, Reset);
-		for(i=0;; i++){
-			if(i > 100)
-				panic("ns83815: PHY soft reset time out");
-			if((csr32r(ctlr, Rbmcr) & Reset) == 0)
-				break;
-			delay(1);
-		}
-	}
-
-	/*
-	 * Initialisation values, in sequence (see 4.4 Recommended Registers Configuration)
-	 */
-	csr16w(ctlr, 0xCC, 0x0001);	/* PGSEL */
-	csr16w(ctlr, 0xE4, 0x189C);	/* PMCCSR */
-	csr16w(ctlr, 0xFC, 0x0000);	/* TSTDAT */
-	csr16w(ctlr, 0xF4, 0x5040);	/* DSPCFG */
-	csr16w(ctlr, 0xF8, 0x008C);	/* SDCFG */
-
-	/*
-	 * Auto negotiate
-	 */
-	w = csr16r(ctlr, Rbmsr);	/* clear latched bits */
-	debug("anar: %4.4ux\n", csr16r(ctlr, Ranar));
-	csr16w(ctlr, Rbmcr, Anena);
-	if(csr16r(ctlr, Ranar) == 0 || (csr32r(ctlr, Rcfg) & Aneg_dn) == 0){
-		csr16w(ctlr, Rbmcr, Anena|Anrestart);
-		for(i=0;; i++){
-			if(i > 6000){
-				print("ns83815: auto neg timed out\n");
-				break;
-			}
-			if((w = csr16r(ctlr, Rbmsr)) & Ancomp)
-				break;
-			delay(1);
-		}
-		debug("%d ms\n", i);
-		w &= 0xFFFF;
-		debug("bmsr: %4.4ux\n", w);
-	}
-	debug("anar: %4.4ux\n", csr16r(ctlr, Ranar));
-	debug("anlpar: %4.4ux\n", csr16r(ctlr, Ranlpar));
-	debug("aner: %4.4ux\n", csr16r(ctlr, Raner));
-	debug("physts: %4.4ux\n", csr16r(ctlr, Rphysts));
-	debug("tbscr: %4.4ux\n", csr16r(ctlr, Rtbscr));
-}
-
-static char* mediatable[9] = {
-	"10BASE-T",				/* TP */
-	"10BASE-2",				/* BNC */
-	"10BASE-5",				/* AUI */
-	"100BASE-TX",
-	"10BASE-TFD",
-	"100BASE-TXFD",
-	"100BASE-T4",
-	"100BASE-FX",
-	"100BASE-FXFD",
-};
-
-static void
-srom(Ctlr* ctlr)
-{
-	int i, j;
-
-	for(i = 0; i < nelem(ctlr->srom); i++)
-		ctlr->srom[i] = eegetw(ctlr, i);
-
-	/*
-	 * the MAC address is reversed, straddling word boundaries
-	 */
-	memset(ctlr->sromea, 0, sizeof(ctlr->sromea));
-	j = 6*16 + 15;
-	for(i=0; i<48; i++){
-		ctlr->sromea[i>>3] |= ((ctlr->srom[j>>4] >> (15-(j&0xF))) & 1) << (i&7);
-		j++;
-	}
-}
-
-static void
-scanpci83815(void)
-{
-	Ctlr *ctlr;
-	Pcidev *p;
-
-	p = nil;
-	while(p = pcimatch(p, 0, 0)){
-		if(p->ccrb != 0x02 || p->ccru != 0)
-			continue;
-		switch((p->did<<16)|p->vid){
-		default:
-			continue;
-
-		case Nat83815:
-			break;
-		}
-
-		/*
-		 * bar[0] is the I/O port register address and
-		 * bar[1] is the memory-mapped register address.
-		 */
-		ctlr = malloc(sizeof(Ctlr));
-		ctlr->port = p->mem[0].bar & ~0x01;
-		ctlr->pcidev = p;
-		ctlr->id = (p->did<<16)|p->vid;
-
-		softreset(ctlr, 0);
-		srom(ctlr);
-
-		if(ctlrhead != nil)
-			ctlrtail->next = ctlr;
-		else
-			ctlrhead = ctlr;
-		ctlrtail = ctlr;
-	}
-}
-
-int
-ether83815reset(Ether* ether)
-{
-	Ctlr *ctlr;
-	int i, x;
-	uchar ea[Eaddrlen];
-	static int scandone;
-
-	if(scandone == 0){
-		scanpci83815();
-		scandone = 1;
-	}
-
-	/*
-	 * Any adapter matches if no ether->port is supplied,
-	 * otherwise the ports must match.
-	 */
-	for(ctlr = ctlrhead; ctlr != nil; ctlr = ctlr->next){
-		if(ctlr->active)
-			continue;
-		if(ether->port == 0 || ether->port == ctlr->port){
-			ctlr->active = 1;
-			break;
-		}
-	}
-	if(ctlr == nil)
-		return -1;
-
-	ether->ctlr = ctlr;
-	ether->port = ctlr->port;
-	ether->irq = ctlr->pcidev->intl;
-	ether->tbdf = ctlr->pcidev->tbdf;
-
-	/*
-	 * Check if the adapter's station address is to be overridden.
-	 * If not, read it from the EEPROM and set in ether->ea prior to
-	 * loading the station address in the hardware.
-	 */
-	memset(ea, 0, Eaddrlen);
-	if(memcmp(ea, ether->ea, Eaddrlen) == 0)
-		memmove(ether->ea, ctlr->sromea, Eaddrlen);
-	for(i=0; i<Eaddrlen; i+=2){
-		x = ether->ea[i] | (ether->ea[i+1]<<8);
-		csr32w(ctlr, Rrfcr, i);
-		csr32w(ctlr, Rrfdr, x);
-	}
-	csr32w(ctlr, Rrfcr, Rfen|Apm|Aab|Aam);
-
-	/*
-	 * Look for a medium override in case there's no autonegotiation
-	 * the autonegotiation fails.
-	 */
-
-	for(i = 0; i < ether->nopt; i++){
-		if(cistrcmp(ether->opt[i], "FD") == 0){
-			ctlr->fd = 1;
-			continue;
-		}
-		for(x = 0; x < nelem(mediatable); x++){
-			debug("compare <%s> <%s>\n", mediatable[x],
-				ether->opt[i]);
-			if(cistrcmp(mediatable[x], ether->opt[i]) == 0){
-				switch(x){
-				default:
-					ctlr->fd = 0;
-					break;
-
-				case 0x04:		/* 10BASE-TFD */
-				case 0x05:		/* 100BASE-TXFD */
-				case 0x08:		/* 100BASE-FXFD */
-					ctlr->fd = 1;
-					break;
-				}
-				break;
-			}
-		}
-	}
-
-	/*
-	 * Initialise descriptor rings, ethernet address.
-	 */
-	ctlr->nrdr = Nrde;
-	ctlr->ntdr = Ntde;
-	pcisetbme(ctlr->pcidev);
-	ctlrinit(ether);
-
-	/*
-	 * Linkage to the generic ethernet driver.
-	 */
-	ether->attach = attach;
-	ether->transmit = transmit;
-	ether->interrupt = interrupt;
-	ether->detach = detach;
-
-	return 0;
-}
--- a/os/boot/pc/ether8390.c
+++ /dev/null
@@ -1,715 +1,0 @@
-/*
- * National Semiconductor DP8390 and clone
- * Network Interface Controller.
- */
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-#include "etherif.h"
-#include "ether8390.h"
-
-enum {					/* NIC core registers */
-	Cr		= 0x00,		/* command register, all pages */
-
-					/* Page 0, read */
-	Clda0		= 0x01,		/* current local DMA address 0 */
-	Clda1		= 0x02,		/* current local DMA address 1 */
-	Bnry		= 0x03,		/* boundary pointer (R/W) */
-	Tsr		= 0x04,		/* transmit status register */
-	Ncr		= 0x05,		/* number of collisions register */
-	Fifo		= 0x06,		/* FIFO */
-	Isr		= 0x07,		/* interrupt status register (R/W) */
-	Crda0		= 0x08,		/* current remote DMA address 0 */
-	Crda1		= 0x09,		/* current remote DMA address 1 */
-	Rsr		= 0x0C,		/* receive status register */
-	Cntr0		= 0x0D,		/* frame alignment errors */
-	Cntr1		= 0x0E,		/* CRC errors */
-	Cntr2		= 0x0F,		/* missed packet errors */
-
-					/* Page 0, write */
-	Pstart		= 0x01,		/* page start register */
-	Pstop		= 0x02,		/* page stop register */
-	Tpsr		= 0x04,		/* transmit page start address */
-	Tbcr0		= 0x05,		/* transmit byte count register 0 */
-	Tbcr1		= 0x06,		/* transmit byte count register 1 */
-	Rsar0		= 0x08,		/* remote start address register 0 */
-	Rsar1		= 0x09,		/* remote start address register 1 */
-	Rbcr0		= 0x0A,		/* remote byte count register 0 */
-	Rbcr1		= 0x0B,		/* remote byte count register 1 */
-	Rcr		= 0x0C,		/* receive configuration register */
-	Tcr		= 0x0D,		/* transmit configuration register */
-	Dcr		= 0x0E,		/* data configuration register */
-	Imr		= 0x0F,		/* interrupt mask */
-
-					/* Page 1, read/write */
-	Par0		= 0x01,		/* physical address register 0 */
-	Curr		= 0x07,		/* current page register */
-	Mar0		= 0x08,		/* multicast address register 0 */
-};
-
-enum {					/* Cr */
-	Stp		= 0x01,		/* stop */
-	Sta		= 0x02,		/* start */
-	Txp		= 0x04,		/* transmit packet */
-	Rd0		= 0x08,		/* remote DMA command */
-	Rd1		= 0x10,	
-	Rd2		= 0x20,
-	RdREAD		= Rd0,		/* remote read */
-	RdWRITE		= Rd1,		/* remote write */
-	RdSEND		= Rd1|Rd0,	/* send packet */
-	RdABORT		= Rd2,		/* abort/complete remote DMA */
-	Ps0		= 0x40,		/* page select */
-	Ps1		= 0x80,
-	Page0		= 0x00,
-	Page1		= Ps0,
-	Page2		= Ps1,
-};
-
-enum {					/* Isr/Imr */
-	Prx		= 0x01,		/* packet received */
-	Ptx		= 0x02,		/* packet transmitted */
-	Rxe		= 0x04,		/* receive error */
-	Txe		= 0x08,		/* transmit error */
-	Ovw		= 0x10,		/* overwrite warning */
-	Cnt		= 0x20,		/* counter overflow */
-	Rdc		= 0x40,		/* remote DMA complete */
-	Rst		= 0x80,		/* reset status */
-};
-
-enum {					/* Dcr */
-	Wts		= 0x01,		/* word transfer select */
-	Bos		= 0x02,		/* byte order select */
-	Las		= 0x04,		/* long address select */
-	Ls		= 0x08,		/* loopback select */
-	Arm		= 0x10,		/* auto-initialise remote */
-	Ft0		= 0x20,		/* FIFO threshold select */
-	Ft1		= 0x40,
-	Ft1WORD		= 0x00,
-	Ft2WORD		= Ft0,
-	Ft4WORD		= Ft1,
-	Ft6WORD		= Ft1|Ft0,
-};
-
-enum {					/* Tcr */
-	Crc		= 0x01,		/* inhibit CRC */
-	Lb0		= 0x02,		/* encoded loopback control */
-	Lb1		= 0x04,
-	LpbkNORMAL	= 0x00,		/* normal operation */
-	LpbkNIC		= Lb0,		/* internal NIC module loopback */
-	LpbkENDEC	= Lb1,		/* internal ENDEC module loopback */
-	LpbkEXTERNAL	= Lb1|Lb0,	/* external loopback */
-	Atd		= 0x08,		/* auto transmit disable */
-	Ofst		= 0x10,		/* collision offset enable */
-};
-
-enum {					/* Tsr */
-	Ptxok		= 0x01,		/* packet transmitted */
-	Col		= 0x04,		/* transmit collided */
-	Abt		= 0x08,		/* tranmit aborted */
-	Crs		= 0x10,		/* carrier sense lost */
-	Fu		= 0x20,		/* FIFO underrun */
-	Cdh		= 0x40,		/* CD heartbeat */
-	Owc		= 0x80,		/* out of window collision */
-};
-
-enum {					/* Rcr */
-	Sep		= 0x01,		/* save errored packets */
-	Ar		= 0x02,		/* accept runt packets */
-	Ab		= 0x04,		/* accept broadcast */
-	Am		= 0x08,		/* accept multicast */
-	Pro		= 0x10,		/* promiscuous physical */
-	Mon		= 0x20,		/* monitor mode */
-};
-
-enum {					/* Rsr */
-	Prxok		= 0x01,		/* packet received intact */
-	Crce		= 0x02,		/* CRC error */
-	Fae		= 0x04,		/* frame alignment error */
-	Fo		= 0x08,		/* FIFO overrun */
-	Mpa		= 0x10,		/* missed packet */
-	Phy		= 0x20,		/* physical/multicast address */
-	Dis		= 0x40,		/* receiver disabled */
-	Dfr		= 0x80,		/* deferring */
-};
-
-typedef struct {
-	uchar	status;
-	uchar	next;
-	uchar	len0;
-	uchar	len1;
-} Hdr;
-
-void
-dp8390getea(Ether* ether, uchar* ea)
-{
-	Dp8390 *ctlr;
-	uchar cr;
-	int i;
-
-	ctlr = ether->ctlr;
-
-	/*
-	 * Get the ethernet address from the chip.
-	 * Take care to restore the command register
-	 * afterwards.
-	 */
-	ilock(ctlr);
-	cr = regr(ctlr, Cr) & ~Txp;
-	regw(ctlr, Cr, Page1|(~(Ps1|Ps0) & cr));
-	for(i = 0; i < Eaddrlen; i++)
-		ea[i] = regr(ctlr, Par0+i);
-	regw(ctlr, Cr, cr);
-	iunlock(ctlr);
-}
-
-void
-dp8390setea(Ether* ether)
-{
-	int i;
-	uchar cr;
-	Dp8390 *ctlr;
-
-	ctlr = ether->ctlr;
-
-	/*
-	 * Set the ethernet address into the chip.
-	 * Take care to restore the command register
-	 * afterwards. Don't care about multicast
-	 * addresses as multicast is never enabled
-	 * (currently).
-	 */
-	ilock(ctlr);
-	cr = regr(ctlr, Cr) & ~Txp;
-	regw(ctlr, Cr, Page1|(~(Ps1|Ps0) & cr));
-	for(i = 0; i < Eaddrlen; i++)
-		regw(ctlr, Par0+i, ether->ea[i]);
-	regw(ctlr, Cr, cr);
-	iunlock(ctlr);
-}
-
-static void*
-_dp8390read(Dp8390* ctlr, void* to, ulong from, ulong len)
-{
-	uchar cr;
-	int timo;
-
-	/*
-	 * Read some data at offset 'from' in the card's memory
-	 * using the DP8390 remote DMA facility, and place it at
-	 * 'to' in main memory, via the I/O data port.
-	 */
-	cr = regr(ctlr, Cr) & ~Txp;
-	regw(ctlr, Cr, Page0|RdABORT|Sta);
-	regw(ctlr, Isr, Rdc);
-
-	/*
-	 * Set up the remote DMA address and count.
-	 */
-	len = ROUNDUP(len, ctlr->width);
-	regw(ctlr, Rbcr0, len & 0xFF);
-	regw(ctlr, Rbcr1, (len>>8) & 0xFF);
-	regw(ctlr, Rsar0, from & 0xFF);
-	regw(ctlr, Rsar1, (from>>8) & 0xFF);
-
-	/*
-	 * Start the remote DMA read and suck the data
-	 * out of the I/O port.
-	 */
-	regw(ctlr, Cr, Page0|RdREAD|Sta);
-	rdread(ctlr, to, len);
-
-	/*
-	 * Wait for the remote DMA to complete. The timeout
-	 * is necessary because this routine may be called on
-	 * a non-existent chip during initialisation and, due
-	 * to the miracles of the bus, it's possible to get this
-	 * far and still be talking to a slot full of nothing.
-	 */
-	for(timo = 10000; (regr(ctlr, Isr) & Rdc) == 0 && timo; timo--)
-			;
-
-	regw(ctlr, Isr, Rdc);
-	regw(ctlr, Cr, cr);
-
-	return to;
-}
-
-void*
-dp8390read(Dp8390* ctlr, void* to, ulong from, ulong len)
-{
-	void *v;
-
-	ilock(ctlr);
-	v = _dp8390read(ctlr, to, from, len);
-	iunlock(ctlr);
-
-	return v;
-}
-
-static void*
-dp8390write(Dp8390* ctlr, ulong to, void* from, ulong len)
-{
-	ulong crda;
-	uchar cr;
-	int timo, width;
-
-top:
-	/*
-	 * Write some data to offset 'to' in the card's memory
-	 * using the DP8390 remote DMA facility, reading it at
-	 * 'from' in main memory, via the I/O data port.
-	 */
-	cr = regr(ctlr, Cr) & ~Txp;
-	regw(ctlr, Cr, Page0|RdABORT|Sta);
-	regw(ctlr, Isr, Rdc);
-
-	len = ROUNDUP(len, ctlr->width);
-
-	/*
-	 * Set up the remote DMA address and count.
-	 * This is straight from the DP8390[12D] datasheet,
-	 * hence the initial set up for read.
-	 * Assumption here that the A7000 EtherV card will
-	 * never need a dummyrr.
-	 */
-	if(ctlr->dummyrr && (ctlr->width == 1 || ctlr->width == 2)){
-		if(ctlr->width == 2)
-			width = 1;
-		else
-			width = 0;
-		crda = to-1-width;
-		regw(ctlr, Rbcr0, (len+1+width) & 0xFF);
-		regw(ctlr, Rbcr1, ((len+1+width)>>8) & 0xFF);
-		regw(ctlr, Rsar0, crda & 0xFF);
-		regw(ctlr, Rsar1, (crda>>8) & 0xFF);
-		regw(ctlr, Cr, Page0|RdREAD|Sta);
-	
-		for(timo=0;; timo++){
-			if(timo > 10000){
-				print("ether8390: dummyrr timeout; assuming nodummyrr\n");
-				ctlr->dummyrr = 0;
-				goto top;
-			}
-			crda = regr(ctlr, Crda0);
-			crda |= regr(ctlr, Crda1)<<8;
-			if(crda == to){
-				/*
-				 * Start the remote DMA write and make sure
-				 * the registers are correct.
-				 */
-				regw(ctlr, Cr, Page0|RdWRITE|Sta);
-	
-				crda = regr(ctlr, Crda0);
-				crda |= regr(ctlr, Crda1)<<8;
-				if(crda != to)
-					panic("crda write %d to %d\n", crda, to);
-	
-				break;
-			}
-		}
-	}
-	else{
-		regw(ctlr, Rsar0, to & 0xFF);
-		regw(ctlr, Rsar1, (to>>8) & 0xFF);
-		regw(ctlr, Rbcr0, len & 0xFF);
-		regw(ctlr, Rbcr1, (len>>8) & 0xFF);
-		regw(ctlr, Cr, Page0|RdWRITE|Sta);
-	}
-
-	/*
-	 * Pump the data into the I/O port
-	 * then wait for the remote DMA to finish.
-	 */
-	rdwrite(ctlr, from, len);
-	for(timo = 10000; (regr(ctlr, Isr) & Rdc) == 0 && timo; timo--)
-			;
-
-	regw(ctlr, Isr, Rdc);
-	regw(ctlr, Cr, cr);
-
-	return (void*)to;
-}
-
-static void
-ringinit(Dp8390* ctlr)
-{
-	regw(ctlr, Pstart, ctlr->pstart);
-	regw(ctlr, Pstop, ctlr->pstop);
-	regw(ctlr, Bnry, ctlr->pstop-1);
-
-	regw(ctlr, Cr, Page1|RdABORT|Stp);
-	regw(ctlr, Curr, ctlr->pstart);
-	regw(ctlr, Cr, Page0|RdABORT|Stp);
-
-	ctlr->nxtpkt = ctlr->pstart;
-}
-
-static uchar
-getcurr(Dp8390* ctlr)
-{
-	uchar cr, curr;
-
-	cr = regr(ctlr, Cr) & ~Txp;
-	regw(ctlr, Cr, Page1|(~(Ps1|Ps0) & cr));
-	curr = regr(ctlr, Curr);
-	regw(ctlr, Cr, cr);
-
-	return curr;
-}
-
-static void
-receive(Ether* ether)
-{
-	Dp8390 *ctlr;
-	uchar curr, *p;
-	Hdr hdr;
-	ulong count, data, len;
-	RingBuf *ring;
-
-	ctlr = ether->ctlr;
-	for(curr = getcurr(ctlr); ctlr->nxtpkt != curr; curr = getcurr(ctlr)){
-		data = ctlr->nxtpkt*Dp8390BufSz;
-		if(ctlr->ram)
-			memmove(&hdr, (void*)(ether->mem+data), sizeof(Hdr));
-		else
-			_dp8390read(ctlr, &hdr, data, sizeof(Hdr));
-
-		/*
-		 * Don't believe the upper byte count, work it
-		 * out from the software next-page pointer and
-		 * the current next-page pointer.
-		 */
-		if(hdr.next > ctlr->nxtpkt)
-			len = hdr.next - ctlr->nxtpkt - 1;
-		else
-			len = (ctlr->pstop-ctlr->nxtpkt) + (hdr.next-ctlr->pstart) - 1;
-		if(hdr.len0 > (Dp8390BufSz-sizeof(Hdr)))
-			len--;
-
-		len = ((len<<8)|hdr.len0)-4;
-
-		/*
-		 * Chip is badly scrogged, reinitialise the ring.
-		 */
-		if(hdr.next < ctlr->pstart || hdr.next >= ctlr->pstop
-		  || len < 60 || len > sizeof(Etherpkt)){
-			print("dp8390: H#%2.2ux#%2.2ux#%2.2ux#%2.2ux,%lud\n",
-				hdr.status, hdr.next, hdr.len0, hdr.len1, len);
-			regw(ctlr, Cr, Page0|RdABORT|Stp);
-			ringinit(ctlr);
-			regw(ctlr, Cr, Page0|RdABORT|Sta);
-
-			return;
-		}
-
-		/*
-		 * If it's a good packet read it in to the software buffer.
-		 * If the packet wraps round the hardware ring, read it in
-		 * two pieces.
-		 */
-		ring = &ether->rb[ether->ri];
-		if((hdr.status & (Fo|Fae|Crce|Prxok)) == Prxok && ring->owner == Interface){
-			p = ring->pkt;
-			ring->len = len;
-			data += sizeof(Hdr);
-
-			if((data+len) >= ctlr->pstop*Dp8390BufSz){
-				count = ctlr->pstop*Dp8390BufSz - data;
-				if(ctlr->ram)
-					memmove(p, (void*)(ether->mem+data), count);
-				else
-					_dp8390read(ctlr, p, data, count);
-				p += count;
-				data = ctlr->pstart*Dp8390BufSz;
-				len -= count;
-			}
-			if(len){
-				if(ctlr->ram)
-					memmove(p, (void*)(ether->mem+data), len);
-				else
-					_dp8390read(ctlr, p, data, len);
-			}
-
-			/*
-			 * Copy the packet to whoever wants it.
-			 */
-			ring->owner = Host;
-			ether->ri = NEXT(ether->ri, ether->nrb);
-		}
-
-		/*
-		 * Finished with this packet, update the
-		 * hardware and software ring pointers.
-		 */
-		ctlr->nxtpkt = hdr.next;
-
-		hdr.next--;
-		if(hdr.next < ctlr->pstart)
-			hdr.next = ctlr->pstop-1;
-		regw(ctlr, Bnry, hdr.next);
-	}
-}
-
-static void
-txstart(Ether* ether)
-{
-	int len;
-	Dp8390 *ctlr;
-	RingBuf *ring;
-	uchar minpkt[ETHERMINTU], *rp;
-
-	ctlr = ether->ctlr;
-
-	/*
-	 * This routine is called both from the top level and from interrupt
-	 * level and expects to be called with ctlr already locked.
-	 */
-	if(ether->tbusy)
-		return;
-	ring = &ether->tb[ether->ti];
-	if(ring->owner != Interface)
-		return;
-
-	/*
-	 * Make sure the packet is of minimum length;
-	 * copy it to the card's memory by the appropriate means;
-	 * start the transmission.
-	 */
-	len = ring->len;
-	rp = ring->pkt;
-	if(len < ETHERMINTU){
-		rp = minpkt;
-		memmove(rp, ring->pkt, len);
-		memset(rp+len, 0, ETHERMINTU-len);
-		len = ETHERMINTU;
-	}
-
-	if(ctlr->ram)
-		memmove((void*)(ether->mem+ctlr->tstart*Dp8390BufSz), rp, len);
-	else
-		dp8390write(ctlr, ctlr->tstart*Dp8390BufSz, rp, len);
-
-	regw(ctlr, Tbcr0, len & 0xFF);
-	regw(ctlr, Tbcr1, (len>>8) & 0xFF);
-	regw(ctlr, Cr, Page0|RdABORT|Txp|Sta);
-
-	ether->tbusy = 1;
-}
-
-static void
-transmit(Ether* ether)
-{
-	Dp8390 *ctlr;
-
-	ctlr = ether->ctlr;
-
-	ilock(ctlr);
-	txstart(ether);
-	iunlock(ctlr);
-}
-
-static void
-overflow(Ether *ether)
-{
-	Dp8390 *ctlr;
-	uchar txp;
-	int resend;
-
-	ctlr = ether->ctlr;
-
-	/*
-	 * The following procedure is taken from the DP8390[12D] datasheet,
-	 * it seems pretty adamant that this is what has to be done.
-	 */
-	txp = regr(ctlr, Cr) & Txp;
-	regw(ctlr, Cr, Page0|RdABORT|Stp);
-	delay(2);
-	regw(ctlr, Rbcr0, 0);
-	regw(ctlr, Rbcr1, 0);
-
-	resend = 0;
-	if(txp && (regr(ctlr, Isr) & (Txe|Ptx)) == 0)
-		resend = 1;
-
-	regw(ctlr, Tcr, LpbkNIC);
-	regw(ctlr, Cr, Page0|RdABORT|Sta);
-	receive(ether);
-	regw(ctlr, Isr, Ovw);
-	regw(ctlr, Tcr, LpbkNORMAL);
-
-	if(resend)
-		regw(ctlr, Cr, Page0|RdABORT|Txp|Sta);
-}
-
-static void
-interrupt(Ureg*, void* arg)
-{
-	Ether *ether;
-	Dp8390 *ctlr;
-	RingBuf *ring;
-	uchar isr, r;
-
-	ether = arg;
-	ctlr = ether->ctlr;
-
-	/*
-	 * While there is something of interest,
-	 * clear all the interrupts and process.
-	 */
-	ilock(ctlr);
-	regw(ctlr, Imr, 0x00);
-	while(isr = (regr(ctlr, Isr) & (Cnt|Ovw|Txe|Rxe|Ptx|Prx))){
-		if(isr & Ovw){
-			overflow(ether);
-			regw(ctlr, Isr, Ovw);
-		}
-
-		/*
-		 * Packets have been received.
-		 * Take a spin round the ring.
-		 */
-		if(isr & (Rxe|Prx)){
-			receive(ether);
-			regw(ctlr, Isr, Rxe|Prx);
-		}
-
-		/*
-		 * A packet completed transmission, successfully or
-		 * not. Start transmission on the next buffered packet,
-		 * and wake the output routine.
-		 */
-		if(isr & (Txe|Ptx)){
-			r = regr(ctlr, Tsr);
-			if((isr & Txe) && (r & (Cdh|Fu|Crs|Abt))){
-				print("dp8390: Tsr#%2.2ux|", r);
-			}
-
-			regw(ctlr, Isr, Txe|Ptx);
-
-			ring = &ether->tb[ether->ti];
-			ring->owner = Host;
-			ether->ti = NEXT(ether->ti, ether->ntb);
-			ether->tbusy = 0;
-			txstart(ether);
-		}
-
-		if(isr & Cnt){
-			regr(ctlr, Cntr0);
-			regr(ctlr, Cntr1);
-			regr(ctlr, Cntr2);
-			regw(ctlr, Isr, Cnt);
-		}
-	}
-	regw(ctlr, Imr, Cnt|Ovw|Txe|Rxe|Ptx|Prx);
-	iunlock(ctlr);
-}
-
-static void
-attach(Ether* ether)
-{
-	Dp8390 *ctlr;
-	uchar r;
-
-	ctlr = ether->ctlr;
-
-	/*
-	 * Enable the chip for transmit/receive.
-	 * The init routine leaves the chip in monitor
-	 * mode. Clear the missed-packet counter, it
-	 * increments while in monitor mode.
-	 * Sometimes there's an interrupt pending at this
-	 * point but there's nothing in the Isr, so
-	 * any pending interrupts are cleared and the
-	 * mask of acceptable interrupts is enabled here.
-	 */
-	r = Ab;
-	ilock(ctlr);
-	regw(ctlr, Isr, 0xFF);
-	regw(ctlr, Imr, Cnt|Ovw|Txe|Rxe|Ptx|Prx);
-	regw(ctlr, Rcr, r);
-	r = regr(ctlr, Cntr2);
-	regw(ctlr, Tcr, LpbkNORMAL);
-	iunlock(ctlr);
-	USED(r);
-}
-
-static void
-detach(Ether* ether)
-{
-	int timo;
-	Dp8390 *ctlr;
-
-	/*
-	 * Stop the chip. Set the Stp bit and wait for the chip
-	 * to finish whatever was on its tiny mind before it sets
-	 * the Rst bit.
-	 * The timeout is needed because there may not be a real
-	 * chip there if this is called when probing for a device
-	 * at boot.
-	 */
-	ctlr = ether->ctlr;
-	regw(ctlr, Cr, Page0|RdABORT|Stp);
-	regw(ctlr, Rbcr0, 0);
-	regw(ctlr, Rbcr1, 0);
-	for(timo = 10000; (regr(ctlr, Isr) & Rst) == 0 && timo; timo--)
-			;
-}
-
-int
-dp8390reset(Ether* ether)
-{
-	Dp8390 *ctlr;
-
-	ctlr = ether->ctlr;
-
-	/*
-	 * This is the initialisation procedure described
-	 * as 'mandatory' in the datasheet, with references
-	 * to the 3C503 technical reference manual.
-	 */ 
-	detach(ether);
-	if(ctlr->width != 1)
-		regw(ctlr, Dcr, Ft4WORD|Ls|Wts);
-	else
-		regw(ctlr, Dcr, Ft4WORD|Ls);
-
-	regw(ctlr, Rbcr0, 0);
-	regw(ctlr, Rbcr1, 0);
-
-	regw(ctlr, Tcr, LpbkNIC);
-	regw(ctlr, Rcr, Mon);
-
-	/*
-	 * Init the ring hardware and software ring pointers.
-	 * Can't initialise ethernet address as it may not be
-	 * known yet.
-	 */
-	ringinit(ctlr);
-	regw(ctlr, Tpsr, ctlr->tstart);
-
-	/*
-	 * Clear any pending interrupts and mask then all off.
-	 */
-	regw(ctlr, Isr, 0xFF);
-	regw(ctlr, Imr, 0);
-
-	/*
-	 * Leave the chip initialised,
-	 * but in monitor mode.
-	 */
-	regw(ctlr, Cr, Page0|RdABORT|Sta);
-
-	/*
-	 * Set up the software configuration.
-	 */
-	ether->attach = attach;
-	ether->transmit = transmit;
-	ether->interrupt = interrupt;
-	ether->detach = detach;
-
-	return 0;
-}
--- a/os/boot/pc/ether8390.h
+++ /dev/null
@@ -1,71 +1,0 @@
-/*
- * Ctlr for the boards using the National Semiconductor DP8390
- * and SMC 83C90 Network Interface Controller.
- * Common code is in ether8390.c.
- */
-typedef struct {
-	Lock;
-
-	ulong	port;			/* I/O address of 8390 */
-	ulong	data;			/* I/O data port if no shared memory */
-
-	uchar	width;			/* data transfer width in bytes */
-	uchar	ram;			/* true if card has shared memory */
-	uchar	dummyrr;		/* do dummy remote read */
-
-	uchar	nxtpkt;			/* receive: software bndry */
-	uchar	pstart;
-	uchar	pstop;
-
-	int	txbusy;			/* transmit */
-	uchar	tstart;			/* 8390 ring addresses */
-} Dp8390;
-
-#define Dp8390BufSz	256
-
-extern int dp8390reset(Ether*);
-extern void *dp8390read(Dp8390*, void*, ulong, ulong);
-extern void dp8390getea(Ether*, uchar*);
-extern void dp8390setea(Ether*);
-
-/*
- * x86-specific code.
- */
-#define regr(c, r)	inb((c)->port+(r))
-#define regw(c, r, v)	outb((c)->port+(r), (v))
-
-static void
-rdread(Dp8390* ctlr, void* to, int len)
-{
-	switch(ctlr->width){
-	default:
-		panic("dp8390 rdread: width %d\n", ctlr->width);
-		break;
-
-	case 2:
-		inss(ctlr->data, to, len/2);
-		break;
-
-	case 1:
-		insb(ctlr->data, to, len);
-		break;
-	}
-}
-
-static void
-rdwrite(Dp8390* ctlr, void* from, int len)
-{
-	switch(ctlr->width){
-	default:
-		panic("dp8390 rdwrite: width %d\n", ctlr->width);
-		break;
-
-	case 2:
-		outss(ctlr->data, from, len/2);
-		break;
-
-	case 1:
-		outsb(ctlr->data, from, len);
-		break;
-	}
-}
--- a/os/boot/pc/etherdp83820.c
+++ /dev/null
@@ -1,1222 +1,0 @@
-/*
- * boot driver for
- * National Semiconductor DP83820
- * 10/100/1000 Mb/s Ethernet Network Interface Controller
- * (Gig-NIC).
- * Driver assumes little-endian and 32-bit host throughout.
- */
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-#include "etherif.h"
-#include "ethermii.h"
-
-#define iprint print
-#define waserror()	(0)
-#define poperror()
-
-enum {					/* Registers */
-	Cr		= 0x00,		/* Command */
-	Cfg		= 0x04,		/* Configuration and Media Status */
-	Mear		= 0x08,		/* MII/EEPROM Access */
-	Ptscr		= 0x0C,		/* PCI Test Control */
-	Isr		= 0x10,		/* Interrupt Status */
-	Imr		= 0x14,		/* Interrupt Mask */
-	Ier		= 0x18,		/* Interrupt Enable */
-	Ihr		= 0x1C,		/* Interrupt Holdoff */
-	Txdp		= 0x20,		/* Transmit Descriptor Pointer */
-	Txdphi		= 0x24,		/* Transmit Descriptor Pointer Hi */
-	Txcfg		= 0x28,		/* Transmit Configuration */
-	Gpior		= 0x2C,		/* General Purpose I/O Control */
-	Rxdp		= 0x30,		/* Receive Descriptor Pointer */
-	Rxdphi		= 0x34,		/* Receive Descriptor Pointer Hi */
-	Rxcfg		= 0x38,		/* Receive Configuration */
-	Pqcr		= 0x3C,		/* Priority Queueing Control */
-	Wcsr		= 0x40,		/* Wake on LAN Control/Status */
-	Pcr		= 0x44,		/* Pause Control/Status */
-	Rfcr		= 0x48,		/* Receive Filter/Match Control */
-	Rfdr		= 0x4C,		/* Receive Filter/Match Data */
-	Brar		= 0x50,		/* Boot ROM Address */
-	Brdr		= 0x54,		/* Boot ROM Data */
-	Srr		= 0x58,		/* Silicon Revision */
-	Mibc		= 0x5C,		/* MIB Control */
-	Mibd		= 0x60,		/* MIB Data */
-	Txdp1		= 0xA0,		/* Txdp Priority 1 */
-	Txdp2		= 0xA4,		/* Txdp Priority 2 */
-	Txdp3		= 0xA8,		/* Txdp Priority 3 */
-	Rxdp1		= 0xB0,		/* Rxdp Priority 1 */
-	Rxdp2		= 0xB4,		/* Rxdp Priority 2 */
-	Rxdp3		= 0xB8,		/* Rxdp Priority 3 */
-	Vrcr		= 0xBC,		/* VLAN/IP Receive Control */
-	Vtcr		= 0xC0,		/* VLAN/IP Transmit Control */
-	Vdr		= 0xC4,		/* VLAN Data */
-	Ccsr		= 0xCC,		/* Clockrun Control/Status */
-	Tbicr		= 0xE0,		/* TBI Control */
-	Tbisr		= 0xE4,		/* TBI Status */
-	Tanar		= 0xE8,		/* TBI ANAR */
-	Tanlpar		= 0xEC,		/* TBI ANLPAR */
-	Taner		= 0xF0,		/* TBI ANER */
-	Tesr		= 0xF4,		/* TBI ESR */
-};
-
-enum {					/* Cr */
-	Txe		= 0x00000001,	/* Transmit Enable */
-	Txd		= 0x00000002,	/* Transmit Disable */
-	Rxe		= 0x00000004,	/* Receiver Enable */
-	Rxd		= 0x00000008,	/* Receiver Disable */
-	Txr		= 0x00000010,	/* Transmitter Reset */
-	Rxr		= 0x00000020,	/* Receiver Reset */
-	Swien		= 0x00000080,	/* Software Interrupt Enable */
-	Rst		= 0x00000100,	/* Reset */
-	TxpriSHFT	= 9,		/* Tx Priority Queue Select */
-	TxpriMASK	= 0x00001E00,
-	RxpriSHFT	= 13,		/* Rx Priority Queue Select */
-	RxpriMASK	= 0x0001E000,
-};
-
-enum {					/* Configuration and Media Status */
-	Bem		= 0x00000001,	/* Big Endian Mode */
-	Ext125		= 0x00000002,	/* External 125MHz reference Select */
-	Bromdis		= 0x00000004,	/* Disable Boot ROM interface */
-	Pesel		= 0x00000008,	/* Parity Error Detection Action */
-	Exd		= 0x00000010,	/* Excessive Deferral Abort */
-	Pow		= 0x00000020,	/* Program Out of Window Timer */
-	Sb		= 0x00000040,	/* Single Back-off */
-	Reqalg		= 0x00000080,	/* PCI Bus Request Algorithm */
-	Extstsen	= 0x00000100,	/* Extended Status Enable */
-	Phydis		= 0x00000200,	/* Disable PHY */
-	Phyrst		= 0x00000400,	/* Reset PHY */
-	M64addren	= 0x00000800,	/* Master 64-bit Addressing Enable */
-	Data64en	= 0x00001000,	/* 64-bit Data Enable */
-	Pci64det	= 0x00002000,	/* PCI 64-bit Bus Detected */
-	T64addren	= 0x00004000,	/* Target 64-bit Addressing Enable */
-	Mwidis		= 0x00008000,	/* MWI Disable */
-	Mrmdis		= 0x00010000,	/* MRM Disable */
-	Tmrtest		= 0x00020000,	/* Timer Test Mode */
-	Spdstsien	= 0x00040000,	/* PHY Spdsts Interrupt Enable */
-	Lnkstsien	= 0x00080000,	/* PHY Lnksts Interrupt Enable */
-	Dupstsien	= 0x00100000,	/* PHY Dupsts Interrupt Enable */
-	Mode1000	= 0x00400000,	/* 1000Mb/s Mode Control */
-	Tbien		= 0x01000000,	/* Ten-Bit Interface Enable */
-	Dupsts		= 0x10000000,	/* Full Duplex Status */
-	Spdsts100	= 0x20000000,	/* SPEED100 Input Pin Status */
-	Spdsts1000	= 0x40000000,	/* SPEED1000 Input Pin Status */
-	Lnksts		= 0x80000000,	/* Link Status */
-};
-
-enum {					/* MII/EEPROM Access */
-	Eedi		= 0x00000001,	/* EEPROM Data In */
-	Eedo		= 0x00000002,	/* EEPROM Data Out */
-	Eeclk		= 0x00000004,	/* EEPROM Serial Clock */
-	Eesel		= 0x00000008,	/* EEPROM Chip Select */
-	Mdio		= 0x00000010,	/* MII Management Data */
-	Mddir		= 0x00000020,	/* MII Management Direction */
-	Mdc		= 0x00000040,	/* MII Management Clock */
-};
-
-enum {					/* Interrupts */
-	Rxok		= 0x00000001,	/* Rx OK */
-	Rxdesc		= 0x00000002,	/* Rx Descriptor */
-	Rxerr		= 0x00000004,	/* Rx Packet Error */
-	Rxearly		= 0x00000008,	/* Rx Early Threshold */
-	Rxidle		= 0x00000010,	/* Rx Idle */
-	Rxorn		= 0x00000020,	/* Rx Overrun */
-	Txok		= 0x00000040,	/* Tx Packet OK */
-	Txdesc		= 0x00000080,	/* Tx Descriptor */
-	Txerr		= 0x00000100,	/* Tx Packet Error */
-	Txidle		= 0x00000200,	/* Tx Idle */
-	Txurn		= 0x00000400,	/* Tx Underrun */
-	Mib		= 0x00000800,	/* MIB Service */
-	Swi		= 0x00001000,	/* Software Interrupt */
-	Pme		= 0x00002000,	/* Power Management Event */
-	Phy		= 0x00004000,	/* PHY Interrupt */
-	Hibint		= 0x00008000,	/* High Bits Interrupt Set */
-	Rxsovr		= 0x00010000,	/* Rx Status FIFO Overrun */
-	Rtabt		= 0x00020000,	/* Received Target Abort */
-	Rmabt		= 0x00040000,	/* Received Master Abort */
-	Sserr		= 0x00080000,	/* Signalled System Error */
-	Dperr		= 0x00100000,	/* Detected Parity Error */
-	Rxrcmp		= 0x00200000,	/* Receive Reset Complete */
-	Txrcmp		= 0x00400000,	/* Transmit Reset Complete */
-	Rxdesc0		= 0x00800000,	/* Rx Descriptor for Priority Queue 0 */
-	Rxdesc1		= 0x01000000,	/* Rx Descriptor for Priority Queue 1 */
-	Rxdesc2		= 0x02000000,	/* Rx Descriptor for Priority Queue 2 */
-	Rxdesc3		= 0x04000000,	/* Rx Descriptor for Priority Queue 3 */
-	Txdesc0		= 0x08000000,	/* Tx Descriptor for Priority Queue 0 */
-	Txdesc1		= 0x10000000,	/* Tx Descriptor for Priority Queue 1 */
-	Txdesc2		= 0x20000000,	/* Tx Descriptor for Priority Queue 2 */
-	Txdesc3		= 0x40000000,	/* Tx Descriptor for Priority Queue 3 */
-};
-
-enum {					/* Interrupt Enable */
-	Ien		= 0x00000001,	/* Interrupt Enable */
-};
-
-enum {					/* Interrupt Holdoff */
-	IhSHFT		= 0,		/* Interrupt Holdoff */
-	IhMASK		= 0x000000FF,
-	Ihctl		= 0x00000100,	/* Interrupt Holdoff Control */
-};
-
-enum {					/* Transmit Configuration */
-	TxdrthSHFT	= 0,		/* Tx Drain Threshold */
-	TxdrthMASK	= 0x000000FF,
-	FlthSHFT	= 16,		/* Tx Fill Threshold */
-	FlthMASK	= 0x0000FF00,
-	Brstdis		= 0x00080000,	/* 1000Mb/s Burst Disable */
-	MxdmaSHFT	= 20,		/* Max Size per Tx DMA Burst */
-	MxdmaMASK	= 0x00700000,
-	Ecretryen	= 0x00800000,	/* Excessive Collision Retry Enable */
-	Atp		= 0x10000000,	/* Automatic Transmit Padding */
-	Mlb		= 0x20000000,	/* MAC Loopback */
-	Hbi		= 0x40000000,	/* Heartbeat Ignore */
-	Csi		= 0x80000000,	/* Carrier Sense Ignore */
-};
-
-enum {					/* Receive Configuration */
-	RxdrthSHFT	= 1,		/* Rx Drain Threshold */
-	RxdrthMASK	= 0x0000003E,
-	Airl		= 0x04000000,	/* Accept In-Range Length Errored */
-	Alp		= 0x08000000,	/* Accept Long Packets */
-	Rxfd		= 0x10000000,	/* Receive Full Duplex */
-	Stripcrc	= 0x20000000,	/* Strip CRC */
-	Arp		= 0x40000000,	/* Accept Runt Packets */
-	Aep		= 0x80000000,	/* Accept Errored Packets */
-};
-
-enum {					/* Priority Queueing Control */
-	Txpqen		= 0x00000001,	/* Transmit Priority Queuing Enable */
-	Txfairen	= 0x00000002,	/* Transmit Fairness Enable */
-	RxpqenSHFT	= 2,		/* Receive Priority Queue Enable */
-	RxpqenMASK	= 0x0000000C,
-};
-
-enum {					/* Pause Control/Status */
-	PscntSHFT	= 0,		/* Pause Counter Value */
-	PscntMASK	= 0x0000FFFF,
-	Pstx		= 0x00020000,	/* Transmit Pause Frame */
-	PsffloSHFT	= 18,		/* Rx Data FIFO Lo Threshold */
-	PsffloMASK	= 0x000C0000,
-	PsffhiSHFT	= 20,		/* Rx Data FIFO Hi Threshold */
-	PsffhiMASK	= 0x00300000,
-	PsstloSHFT	= 22,		/* Rx Stat FIFO Hi Threshold */
-	PsstloMASK	= 0x00C00000,
-	PssthiSHFT	= 24,		/* Rx Stat FIFO Hi Threshold */
-	PssthiMASK	= 0x03000000,
-	Psrcvd		= 0x08000000,	/* Pause Frame Received */
-	Psact		= 0x10000000,	/* Pause Active */
-	Psda		= 0x20000000,	/* Pause on Destination Address */
-	Psmcast		= 0x40000000,	/* Pause on Multicast */
-	Psen		= 0x80000000,	/* Pause Enable */
-};
-
-enum {					/* Receive Filter/Match Control */
-	RfaddrSHFT	= 0,		/* Extended Register Address */
-	RfaddrMASK	= 0x000003FF,
-	Ulm		= 0x00080000,	/* U/L bit mask */
-	Uhen		= 0x00100000,	/* Unicast Hash Enable */
-	Mhen		= 0x00200000,	/* Multicast Hash Enable */
-	Aarp		= 0x00400000,	/* Accept ARP Packets */
-	ApatSHFT	= 23,		/* Accept on Pattern Match */
-	ApatMASK	= 0x07800000,
-	Apm		= 0x08000000,	/* Accept on Perfect Match */
-	Aau		= 0x10000000,	/* Accept All Unicast */
-	Aam		= 0x20000000,	/* Accept All Multicast */
-	Aab		= 0x40000000,	/* Accept All Broadcast */
-	Rfen		= 0x80000000,	/* Rx Filter Enable */
-};
-
-enum {					/* Receive Filter/Match Data */
-	RfdataSHFT	= 0,		/* Receive Filter Data */
-	RfdataMASK	= 0x0000FFFF,
-	BmaskSHFT	= 16,		/* Byte Mask */
-	BmaskMASK	= 0x00030000,
-};
-
-enum {					/* MIB Control */
-	Wrn		= 0x00000001,	/* Warning Test Indicator */
-	Frz		= 0x00000002,	/* Freeze All Counters */
-	Aclr		= 0x00000004,	/* Clear All Counters */
-	Mibs		= 0x00000008,	/* MIB Counter Strobe */
-};
-
-enum {					/* MIB Data */
-	Nmibd		= 11,		/* Number of MIB Data Registers */
-};
-
-enum {					/* VLAN/IP Receive Control */
-	Vtden		= 0x00000001,	/* VLAN Tag Detection Enable */
-	Vtren		= 0x00000002,	/* VLAN Tag Removal Enable */
-	Dvtf		= 0x00000004,	/* Discard VLAN Tagged Frames */
-	Dutf		= 0x00000008,	/* Discard Untagged Frames */
-	Ipen		= 0x00000010,	/* IP Checksum Enable */
-	Ripe		= 0x00000020,	/* Reject IP Checksum Errors */
-	Rtcpe		= 0x00000040,	/* Reject TCP Checksum Errors */
-	Rudpe		= 0x00000080,	/* Reject UDP Checksum Errors */
-};
-
-enum {					/* VLAN/IP Transmit Control */
-	Vgti		= 0x00000001,	/* VLAN Global Tag Insertion */
-	Vppti		= 0x00000002,	/* VLAN Per-Packet Tag Insertion */
-	Gchk		= 0x00000004,	/* Global Checksum Generation */
-	Ppchk		= 0x00000008,	/* Per-Packet Checksum Generation */
-};
-
-enum {					/* VLAN Data */
-	VtypeSHFT	= 0,		/* VLAN Type Field */
-	VtypeMASK	= 0x0000FFFF,
-	VtciSHFT	= 16,		/* VLAN Tag Control Information */
-	VtciMASK	= 0xFFFF0000,
-};
-
-enum {					/* Clockrun Control/Status */
-	Clkrunen	= 0x00000001,	/* CLKRUN Enable */
-	Pmeen		= 0x00000100,	/* PME Enable */
-	Pmests		= 0x00008000,	/* PME Status */
-};
-
-typedef struct {
-	u32	link;			/* Link to the next descriptor */
-	u32	bufptr;			/* pointer to data Buffer */
-	int	cmdsts;			/* Command/Status */
-	int	extsts;			/* optional Extended Status */
-
-	Block*	bp;			/* Block containing bufptr */
-	u32	unused;			/* pad to 64-bit */
-} Desc;
-
-enum {					/* Common cmdsts bits */
-	SizeMASK	= 0x0000FFFF,	/* Descriptor Byte Count */
-	SizeSHFT	= 0,
-	Ok		= 0x08000000,	/* Packet OK */
-	Crc		= 0x10000000,	/* Suppress/Include CRC */
-	Intr		= 0x20000000,	/* Interrupt on ownership transfer */
-	More		= 0x40000000,	/* not last descriptor in a packet */
-	Own		= 0x80000000,	/* Descriptor Ownership */
-};
-
-enum {					/* Transmit cmdsts bits */
-	CcntMASK	= 0x000F0000,	/* Collision Count */
-	CcntSHFT	= 16,
-	Ec		= 0x00100000,	/* Excessive Collisions */
-	Owc		= 0x00200000,	/* Out of Window Collision */
-	Ed		= 0x00400000,	/* Excessive Deferral */
-	Td		= 0x00800000,	/* Transmit Deferred */
-	Crs		= 0x01000000,	/* Carrier Sense Lost */
-	Tfu		= 0x02000000,	/* Transmit FIFO Underrun */
-	Txa		= 0x04000000,	/* Transmit Abort */
-};
-
-enum {					/* Receive cmdsts bits */
-	Irl		= 0x00010000,	/* In-Range Length Error */
-	Lbp		= 0x00020000,	/* Loopback Packet */
-	Fae		= 0x00040000,	/* Frame Alignment Error */
-	Crce		= 0x00080000,	/* CRC Error */
-	Ise		= 0x00100000,	/* Invalid Symbol Error */
-	Runt		= 0x00200000,	/* Runt Packet Received */
-	Long		= 0x00400000,	/* Too Long Packet Received */
-	DestMASK	= 0x01800000,	/* Destination Class */
-	DestSHFT	= 23,
-	Rxo		= 0x02000000,	/* Receive Overrun */
-	Rxa		= 0x04000000,	/* Receive Aborted */
-};
-
-enum {					/* extsts bits */
-	EvtciMASK	= 0x0000FFFF,	/* VLAN Tag Control Information */
-	EvtciSHFT	= 0,
-	Vpkt		= 0x00010000,	/* VLAN Packet */
-	Ippkt		= 0x00020000,	/* IP Packet */
-	Iperr		= 0x00040000,	/* IP Checksum Error */
-	Tcppkt		= 0x00080000,	/* TCP Packet */
-	Tcperr		= 0x00100000,	/* TCP Checksum Error */
-	Udppkt		= 0x00200000,	/* UDP Packet */
-	Udperr		= 0x00400000,	/* UDP Checksum Error */
-};
-
-enum {
-	Nrd		= 32,		/* was 256 */
-	Nrbf		= 4*Nrd,
-	Rbsz		= ROUNDUP(sizeof(Etherpkt)+8, 8),
-	Ntd		= 8,		/* was 128 */
-};
-
-typedef struct Ctlr Ctlr;
-struct Ctlr {
-	int	port;
-	Pcidev*	pcidev;
-	Ctlr*	next;
-	int	active;
-	int	id;
-
-	int	eepromsz;		/* address size in bits */
-	ushort*	eeprom;
-
-	int*	nic;
-	int	cfg;
-	int	imr;
-
-	Lock	alock;			/* attach */
-	Lock	ilock;			/* init */
-	void*	alloc;			/* base of per-Ctlr allocated data */
-
-	Mii*	mii;
-
-	Lock	rdlock;			/* receive */
-	Desc*	rd;
-	int	nrd;
-	int	nrb;
-	int	rdx;
-	int	rxcfg;
-
-	Lock	tlock;			/* transmit */
-	Desc*	td;
-	int	ntd;
-	int	tdh;
-	int	tdt;
-	int	ntq;
-	int	txcfg;
-
-	int	rxidle;
-
-	uint	mibd[Nmibd];
-
-	int	ec;
-	int	owc;
-	int	ed;
-	int	crs;
-	int	tfu;
-	int	txa;
-};
-
-#define csr32r(c, r)	(*((c)->nic+((r)/4)))
-#define csr32w(c, r, v)	(*((c)->nic+((r)/4)) = (v))
-
-static Ctlr* dp83820ctlrhead;
-static Ctlr* dp83820ctlrtail;
-
-static Lock dp83820rblock;		/* free receive Blocks */
-static Block* dp83820rbpool;
-
-static char* dp83820mibs[Nmibd] = {
-	"RXErroredPkts",
-	"RXFCSErrors",
-	"RXMsdPktErrors",
-	"RXFAErrors",
-	"RXSymbolErrors",
-	"RXFrameToLong",
-	"RXIRLErrors",
-	"RXBadOpcodes",
-	"RXPauseFrames",
-	"TXPauseFrames",
-	"TXSQEErrors",
-};
-
-static int
-mdior(Ctlr* ctlr, int n)
-{
-	int data, i, mear, r;
-
-	mear = csr32r(ctlr, Mear);
-	r = ~(Mdc|Mddir) & mear;
-	data = 0;
-	for(i = n-1; i >= 0; i--){
-		if(csr32r(ctlr, Mear) & Mdio)
-			data |= (1<<i);
-		csr32w(ctlr, Mear, Mdc|r);
-		csr32w(ctlr, Mear, r);
-	}
-	csr32w(ctlr, Mear, mear);
-
-	return data;
-}
-
-static void
-mdiow(Ctlr* ctlr, int bits, int n)
-{
-	int i, mear, r;
-
-	mear = csr32r(ctlr, Mear);
-	r = Mddir|(~Mdc & mear);
-	for(i = n-1; i >= 0; i--){
-		if(bits & (1<<i))
-			r |= Mdio;
-		else
-			r &= ~Mdio;
-		csr32w(ctlr, Mear, r);
-		csr32w(ctlr, Mear, Mdc|r);
-	}
-	csr32w(ctlr, Mear, mear);
-}
-
-static int
-dp83820miimir(Mii* mii, int pa, int ra)
-{
-	int data;
-	Ctlr *ctlr;
-
-	ctlr = mii->ctlr;
-
-	/*
-	 * MII Management Interface Read.
-	 *
-	 * Preamble;
-	 * ST+OP+PA+RA;
-	 * LT + 16 data bits.
-	 */
-	mdiow(ctlr, 0xFFFFFFFF, 32);
-	mdiow(ctlr, 0x1800|(pa<<5)|ra, 14);
-	data = mdior(ctlr, 18);
-
-	if(data & 0x10000)
-		return -1;
-
-	return data & 0xFFFF;
-}
-
-static int
-dp83820miimiw(Mii* mii, int pa, int ra, int data)
-{
-	Ctlr *ctlr;
-
-	ctlr = mii->ctlr;
-
-	/*
-	 * MII Management Interface Write.
-	 *
-	 * Preamble;
-	 * ST+OP+PA+RA+LT + 16 data bits;
-	 * Z.
-	 */
-	mdiow(ctlr, 0xFFFFFFFF, 32);
-	data &= 0xFFFF;
-	data |= (0x05<<(5+5+2+16))|(pa<<(5+2+16))|(ra<<(2+16))|(0x02<<16);
-	mdiow(ctlr, data, 32);
-
-	return 0;
-}
-
-static Block *
-dp83820rballoc(Desc* desc)
-{
-	Block *bp;
-
-	if(desc->bp == nil){
-		ilock(&dp83820rblock);
-		if((bp = dp83820rbpool) == nil){
-			iunlock(&dp83820rblock);
-			desc->bp = nil;
-			desc->cmdsts = Own;
-			return nil;
-		}
-		dp83820rbpool = bp->next;
-		bp->next = nil;
-		iunlock(&dp83820rblock);
-	
-		desc->bufptr = PCIWADDR(bp->rp);
-		desc->bp = bp;
-	}
-	else{
-		bp = desc->bp;
-		bp->rp = bp->lim - Rbsz;
-		bp->wp = bp->rp;
-	}
-
-	coherence();
-	desc->cmdsts = Intr|Rbsz;
-
-	return bp;
-}
-
-static void
-dp83820rbfree(Block *bp)
-{
-	bp->rp = bp->lim - Rbsz;
-	bp->wp = bp->rp;
-
-	ilock(&dp83820rblock);
-	bp->next = dp83820rbpool;
-	dp83820rbpool = bp;
-	iunlock(&dp83820rblock);
-}
-
-static void
-dp83820halt(Ctlr* ctlr)
-{
-	int i, timeo;
-
-	ilock(&ctlr->ilock);
-	csr32w(ctlr, Imr, 0);
-	csr32w(ctlr, Ier, 0);
-	csr32w(ctlr, Cr, Rxd|Txd);
-	for(timeo = 0; timeo < 1000; timeo++){
-		if(!(csr32r(ctlr, Cr) & (Rxe|Txe)))
-			break;
-		microdelay(1);
-	}
-	csr32w(ctlr, Mibc, Frz);
-	iunlock(&ctlr->ilock);
-
-	if(ctlr->rd != nil){
-		for(i = 0; i < ctlr->nrd; i++){
-			if(ctlr->rd[i].bp == nil)
-				continue;
-			freeb(ctlr->rd[i].bp);
-			ctlr->rd[i].bp = nil;
-		}
-	}
-	if(ctlr->td != nil){
-		for(i = 0; i < ctlr->ntd; i++){
-			if(ctlr->td[i].bp == nil)
-				continue;
-			freeb(ctlr->td[i].bp);
-			ctlr->td[i].bp = nil;
-		}
-	}
-}
-
-static void
-dp83820cfg(Ctlr* ctlr)
-{
-	int cfg;
-
-	/*
-	 * Don't know how to deal with a TBI yet.
-	 */
-	if(ctlr->mii == nil)
-		return;
-
-	/*
-	 * The polarity of these bits is at the mercy
-	 * of the board designer.
-	 * The correct answer for all speed and duplex questions
-	 * should be to query the phy.
-	 */
-	cfg = csr32r(ctlr, Cfg);
-	if(!(cfg & Dupsts)){
-		ctlr->rxcfg |= Rxfd;
-		ctlr->txcfg |= Csi|Hbi;
-		iprint("83820: full duplex, ");
-	}
-	else{
-		ctlr->rxcfg &= ~Rxfd;
-		ctlr->txcfg &= ~(Csi|Hbi);
-		iprint("83820: half duplex, ");
-	}
-	csr32w(ctlr, Rxcfg, ctlr->rxcfg);
-	csr32w(ctlr, Txcfg, ctlr->txcfg);
-
-	switch(cfg & (Spdsts1000|Spdsts100)){
-	case Spdsts1000:		/* 100Mbps */
-	default:			/* 10Mbps */
-		ctlr->cfg &= ~Mode1000;
-		if((cfg & (Spdsts1000|Spdsts100)) == Spdsts1000)
-			iprint("100Mb/s\n");
-		else
-			iprint("10Mb/s\n");
-		break;
-	case Spdsts100:			/* 1Gbps */
-		ctlr->cfg |= Mode1000;
-		iprint("1Gb/s\n");
-		break;
-	}
-	csr32w(ctlr, Cfg, ctlr->cfg);
-}
-
-static void
-dp83820init(Ether* edev)
-{
-	int i;
-	Ctlr *ctlr;
-	Desc *desc;
-	uchar *alloc;
-
-	ctlr = edev->ctlr;
-
-	dp83820halt(ctlr);
-
-	/*
-	 * Receiver
-	 */
-	alloc = (uchar*)ROUNDUP((ulong)ctlr->alloc, 8);
-	ctlr->rd = (Desc*)alloc;
-	alloc += ctlr->nrd*sizeof(Desc);
-	memset(ctlr->rd, 0, ctlr->nrd*sizeof(Desc));
-	ctlr->rdx = 0;
-	for(i = 0; i < ctlr->nrd; i++){
-		desc = &ctlr->rd[i];
-		desc->link = PCIWADDR(&ctlr->rd[NEXT(i, ctlr->nrd)]);
-		if(dp83820rballoc(desc) == nil)
-			continue;
-	}
-	csr32w(ctlr, Rxdphi, 0);
-	csr32w(ctlr, Rxdp, PCIWADDR(ctlr->rd));
-
-	for(i = 0; i < Eaddrlen; i += 2){
-		csr32w(ctlr, Rfcr, i);
-		csr32w(ctlr, Rfdr, (edev->ea[i+1]<<8)|edev->ea[i]);
-	}
-	csr32w(ctlr, Rfcr, Rfen|Aab|Aam|Apm);
-
-	ctlr->rxcfg = Stripcrc|(((2*(ETHERMINTU+4))/8)<<RxdrthSHFT);
-	ctlr->imr |= Rxorn|Rxidle|Rxearly|Rxdesc|Rxok;
-
-	/*
-	 * Transmitter.
-	 */
-	ctlr->td = (Desc*)alloc;
-	memset(ctlr->td, 0, ctlr->ntd*sizeof(Desc));
-	ctlr->tdh = ctlr->tdt = ctlr->ntq = 0;
-	for(i = 0; i < ctlr->ntd; i++){
-		desc = &ctlr->td[i];
-		desc->link = PCIWADDR(&ctlr->td[NEXT(i, ctlr->ntd)]);
-	}
-	csr32w(ctlr, Txdphi, 0);
-	csr32w(ctlr, Txdp, PCIWADDR(ctlr->td));
-
-	ctlr->txcfg = Atp|(((2*(ETHERMINTU+4))/32)<<FlthSHFT)|((4096/32)<<TxdrthSHFT);
-	ctlr->imr |= Txurn|Txidle|Txdesc|Txok;
-
-	ilock(&ctlr->ilock);
-
-	dp83820cfg(ctlr);
-
-	csr32w(ctlr, Mibc, Aclr);
-	ctlr->imr |= Mib;
-
-	csr32w(ctlr, Imr, ctlr->imr);
-
-	/* try coalescing adjacent interrupts; use hold-off interval of 100µs */
-	csr32w(ctlr, Ihr, Ihctl|(1<<IhSHFT));
-
-	csr32w(ctlr, Ier, Ien);
-	csr32w(ctlr, Cr, Rxe|Txe);
-
-	iunlock(&ctlr->ilock);
-}
-
-static void
-dp83820attach(Ether* edev)
-{
-	Block *bp;
-	Ctlr *ctlr;
-
-	ctlr = edev->ctlr;
-	lock(&ctlr->alock);
-	if(ctlr->alloc != nil){
-		unlock(&ctlr->alock);
-		return;
-	}
-
-	if(waserror()){
-err:
-		if(ctlr->mii != nil){
-			free(ctlr->mii);
-			ctlr->mii = nil;
-		}
-		if(ctlr->alloc != nil){
-			free(ctlr->alloc);
-			ctlr->alloc = nil;
-		}
-		unlock(&ctlr->alock);
-		return;
-	}
-
-	if(!(ctlr->cfg & Tbien)){
-		if((ctlr->mii = malloc(sizeof(Mii))) == nil)
-			goto err;
-		ctlr->mii->ctlr = ctlr;
-		ctlr->mii->mir = dp83820miimir;
-		ctlr->mii->miw = dp83820miimiw;
-		if(mii(ctlr->mii, ~0) == 0)
-			goto err;
-		ctlr->cfg |= Dupstsien|Lnkstsien|Spdstsien;
-		ctlr->imr |= Phy;
-	}
-
-	ctlr->nrd = Nrd;
-	ctlr->nrb = Nrbf;
-	ctlr->ntd = Ntd;
-	ctlr->alloc = mallocz((ctlr->nrd+ctlr->ntd)*sizeof(Desc) + 7, 0);
-	if(ctlr->alloc == nil)
-		goto err;
-
-	/*
-	 * the Bill Paul bsd drivers claim that receive buffers must be aligned
-	 * on 8-byte boundaries.
-	 */
-	for(ctlr->nrb = 0; ctlr->nrb < Nrbf; ctlr->nrb++){
-		if((bp = allocb(Rbsz+8-1)) == nil)
-			break;
-		bp->rp += 8 - (uintptr)bp->rp % 8;
-		bp->wp = bp->rp;
-//		bp->free = dp83820rbfree;	/* TODO: fix */
-		dp83820rbfree(bp);
-	}
-
-	dp83820init(edev);
-
-	unlock(&ctlr->alock);
-	poperror();
-}
-
-/*
- *  free a list of blocks
- */
-static void
-freeblist(Block *b)
-{
-	Block *next;
-
-	for(; b != 0; b = next){
-		next = b->next;
-		b->next = 0;
-		freeb(b);
-	}
-}
-
-static void
-toringbuf(Ether *ether, Block *bp)
-{
-	RingBuf *rb = &ether->rb[ether->ri];
-
-	if (rb->owner == Interface) {
-		rb->len = BLEN(bp);
-		memmove(rb->pkt, bp->rp, rb->len);
-		rb->owner = Host;
-		ether->ri = NEXT(ether->ri, ether->nrb);
-	}
-	/* else no one is expecting packets from the network */
-}
-
-static Block *
-fromringbuf(Ether *ether)
-{
-	RingBuf *tb = &ether->tb[ether->ti];
-	Block *bp = allocb(tb->len);
-
-	memmove(bp->wp, tb->pkt, tb->len);
-	memmove(bp->wp+Eaddrlen, ether->ea, Eaddrlen);
-	bp->wp += tb->len;
-	return bp;
-}
-
-static void
-dp83820transmit(Ether* edev)
-{
-	Block *bp;
-	Ctlr *ctlr;
-	Desc *desc;
-	RingBuf *tb;
-	int cmdsts, r, x;
-
-	ctlr = edev->ctlr;
-
-	ilock(&ctlr->tlock);
-
-	bp = nil;
-	for(x = ctlr->tdh; ctlr->ntq; x = NEXT(x, ctlr->ntd)){
-		desc = &ctlr->td[x];
-		if((cmdsts = desc->cmdsts) & Own)
-			break;
-		if(!(cmdsts & Ok)){
-			if(cmdsts & Ec)
-				ctlr->ec++;
-			if(cmdsts & Owc)
-				ctlr->owc++;
-			if(cmdsts & Ed)
-				ctlr->ed++;
-			if(cmdsts & Crs)
-				ctlr->crs++;
-			if(cmdsts & Tfu)
-				ctlr->tfu++;
-			if(cmdsts & Txa)
-				ctlr->txa++;
-		}
-		desc->bp->next = bp;
-		bp = desc->bp;
-		desc->bp = nil;
-
-		ctlr->ntq--;
-	}
-	ctlr->tdh = x;
-	if(bp != nil)
-		freeblist(bp);
-
-	x = ctlr->tdt;
-//	tb = &edev->tb[edev->ti];
-	while(ctlr->ntq < ctlr->ntd - 1 /* && tb->owner == Interface */ ){
-		bp = fromringbuf(edev);
-		if (bp == nil)
-			break;
-
-		/* transmit packet from bp */
-		desc = &ctlr->td[x];
-		desc->bufptr = PCIWADDR(bp->rp);
-		desc->bp = bp;
-		ctlr->ntq++;
-		coherence();
-		desc->cmdsts = Own|Intr|BLEN(bp);	/* kick transmitter */
-//print("t");
-		tb = &edev->tb[edev->ti];
-		tb->owner = Host;		/* give descriptor back */
-		edev->ti = NEXT(edev->ti, edev->ntb);
-
-		x = NEXT(x, ctlr->ntd);
-	}
-	if(x != ctlr->tdt){
-		ctlr->tdt = x;
-		r = csr32r(ctlr, Cr);
-		csr32w(ctlr, Cr, Txe|r);
-	}
-
-	iunlock(&ctlr->tlock);
-}
-
-static void
-dp83820interrupt(Ureg*, void* arg)
-{
-	Block *bp;
-	Ctlr *ctlr;
-	Desc *desc;
-	Ether *edev;
-	int cmdsts, i, isr, r, x;
-
-	edev = arg;
-	ctlr = edev->ctlr;
-
-	for(isr = csr32r(ctlr, Isr); isr & ctlr->imr; isr = csr32r(ctlr, Isr)){
-		if(isr & (Rxorn|Rxidle|Rxearly|Rxerr|Rxdesc|Rxok)){
-			x = ctlr->rdx;
-			desc = &ctlr->rd[x];
-			while((cmdsts = desc->cmdsts) & Own){
-				if((cmdsts & Ok) && desc->bp != nil){
-					/* receive a packet into desc->bp */
-					bp = desc->bp;
-					desc->bp = nil;
-					// bp->rp = desc->bufptr;
-					bp->wp += cmdsts & SizeMASK;
-
-					toringbuf(edev, bp);
-//print("r");
-				}
-				dp83820rballoc(desc);
-
-				x = NEXT(x, ctlr->nrd);
-				desc = &ctlr->rd[x];
-			}
-			ctlr->rdx = x;
-
-			if(isr & Rxidle){
-				r = csr32r(ctlr, Cr);
-				csr32w(ctlr, Cr, Rxe|r);
-				ctlr->rxidle++;
-			}
-
-			isr &= ~(Rxorn|Rxidle|Rxearly|Rxerr|Rxdesc|Rxok);
-		}
-
-		if(isr & Txurn){
-			x = (ctlr->txcfg & TxdrthMASK)>>TxdrthSHFT;
-			r = (ctlr->txcfg & FlthMASK)>>FlthSHFT;
-			if(x < ((TxdrthMASK)>>TxdrthSHFT)
-			&& x < (2048/32 - r)){
-				ctlr->txcfg &= ~TxdrthMASK;
-				x++;
-				ctlr->txcfg |= x<<TxdrthSHFT;
-				csr32w(ctlr, Txcfg, ctlr->txcfg);
-			}
-		}
-
-		if(isr & (Txurn|Txidle|Txdesc|Txok)){
-			dp83820transmit(edev);
-			isr &= ~(Txurn|Txidle|Txdesc|Txok);
-		}
-
-		if(isr & Mib){
-			for(i = 0; i < Nmibd; i++){
-				r = csr32r(ctlr, Mibd+(i*sizeof(int)));
-				ctlr->mibd[i] += r & 0xFFFF;
-			}
-			isr &= ~Mib;
-		}
-
-		if((isr & Phy) && ctlr->mii != nil){
-			ctlr->mii->mir(ctlr->mii, 1, Bmsr);
-			print("phy: cfg %8.8uX bmsr %4.4uX\n",
-				csr32r(ctlr, Cfg),
-				ctlr->mii->mir(ctlr->mii, 1, Bmsr));
-			dp83820cfg(ctlr);
-			isr &= ~Phy;
-		}
-// TODO fix	if(isr)
-// TODO fix		iprint("dp83820: isr %8.8uX\n", isr);
-		USED(isr);
-	}
-}
-
-static int
-dp83820detach(Ctlr* ctlr)
-{
-	/*
-	 * Soft reset the controller.
-	 */
-	csr32w(ctlr, Cr, Rst);
-	delay(1);
-	while(csr32r(ctlr, Cr) & Rst)
-		delay(1);
-	return 0;
-}
-
-static void
-dp83820shutdown(Ether* ether)
-{
-print("dp83820shutdown\n");
-	dp83820detach(ether->ctlr);
-}
-
-static int
-atc93c46r(Ctlr* ctlr, int address)
-{
-	int data, i, mear, r, size;
-
-	/*
-	 * Analog Technology, Inc. ATC93C46
-	 * or equivalent serial EEPROM.
-	 */
-	mear = csr32r(ctlr, Mear);
-	mear &= ~(Eesel|Eeclk|Eedo|Eedi);
-	r = Eesel|mear;
-
-reread:
-	csr32w(ctlr, Mear, r);
-	data = 0x06;
-	for(i = 3-1; i >= 0; i--){
-		if(data & (1<<i))
-			r |= Eedi;
-		else
-			r &= ~Eedi;
-		csr32w(ctlr, Mear, r);
-		csr32w(ctlr, Mear, Eeclk|r);
-		microdelay(1);
-		csr32w(ctlr, Mear, r);
-		microdelay(1);
-	}
-
-	/*
-	 * First time through must work out the EEPROM size.
-	 */
-	if((size = ctlr->eepromsz) == 0)
-		size = 8;
-
-	for(size = size-1; size >= 0; size--){
-		if(address & (1<<size))
-			r |= Eedi;
-		else
-			r &= ~Eedi;
-		csr32w(ctlr, Mear, r);
-		microdelay(1);
-		csr32w(ctlr, Mear, Eeclk|r);
-		microdelay(1);
-		csr32w(ctlr, Mear, r);
-		microdelay(1);
-		if(!(csr32r(ctlr, Mear) & Eedo))
-			break;
-	}
-	r &= ~Eedi;
-
-	data = 0;
-	for(i = 16-1; i >= 0; i--){
-		csr32w(ctlr, Mear, Eeclk|r);
-		microdelay(1);
-		if(csr32r(ctlr, Mear) & Eedo)
-			data |= (1<<i);
-		csr32w(ctlr, Mear, r);
-		microdelay(1);
-	}
-
-	csr32w(ctlr, Mear, mear);
-
-	if(ctlr->eepromsz == 0){
-		ctlr->eepromsz = 8-size;
-		ctlr->eeprom = malloc((1<<ctlr->eepromsz)*sizeof(ushort));
-		goto reread;
-	}
-
-	return data;
-}
-
-static int
-dp83820reset(Ctlr* ctlr)
-{
-	int i, r;
-	unsigned char sum;
-
-	/*
-	 * Soft reset the controller;
-	 * read the EEPROM to get the initial settings
-	 * of the Cfg and Gpior bits which should be cleared by
-	 * the reset.
-	 */
-	csr32w(ctlr, Cr, Rst);
-	delay(1);
-	while(csr32r(ctlr, Cr) & Rst)
-		delay(1);
-
-	atc93c46r(ctlr, 0);
-	if(ctlr->eeprom == nil) {
-		print("dp83820reset: no eeprom\n");
-		return -1;
-	}
-	sum = 0;
-	for(i = 0; i < 0x0E; i++){
-		r = atc93c46r(ctlr, i);
-		ctlr->eeprom[i] = r;
-		sum += r;
-		sum += r>>8;
-	}
-
-	if(sum != 0){
-		print("dp83820reset: bad EEPROM checksum\n");
-		return -1;
-	}
-
-#ifdef notdef
-	csr32w(ctlr, Gpior, ctlr->eeprom[4]);
-
-	cfg = Extstsen|Exd;
-	r = csr32r(ctlr, Cfg);
-	if(ctlr->eeprom[5] & 0x0001)
-		cfg |= Ext125;
-	if(ctlr->eeprom[5] & 0x0002)
-		cfg |= M64addren;
-	if((ctlr->eeprom[5] & 0x0004) && (r & Pci64det))
-		cfg |= Data64en;
-	if(ctlr->eeprom[5] & 0x0008)
-		cfg |= T64addren;
-	if(!(pcicfgr16(ctlr->pcidev, PciPCR) & 0x10))
-		cfg |= Mwidis;
-	if(ctlr->eeprom[5] & 0x0020)
-		cfg |= Mrmdis;
-	if(ctlr->eeprom[5] & 0x0080)
-		cfg |= Mode1000;
-	if(ctlr->eeprom[5] & 0x0200)
-		cfg |= Tbien|Mode1000;
-	/*
-	 * What about RO bits we might have destroyed with Rst?
-	 * What about Exd, Tmrtest, Extstsen, Pintctl?
-	 * Why does it think it has detected a 64-bit bus when
-	 * it hasn't?
-	 */
-#else
-	//r = csr32r(ctlr, Cfg);
-	//r &= ~(Mode1000|T64addren|Data64en|M64addren);
-	//csr32w(ctlr, Cfg, r);
-	//csr32w(ctlr, Cfg, 0x2000);
-#endif /* notdef */
-	ctlr->cfg = csr32r(ctlr, Cfg);
-print("cfg %8.8uX pcicfg %8.8uX\n", ctlr->cfg, pcicfgr32(ctlr->pcidev, PciPCR));
-	ctlr->cfg &= ~(T64addren|Data64en|M64addren);
-	csr32w(ctlr, Cfg, ctlr->cfg);
-	csr32w(ctlr, Mibc, Aclr|Frz);
-
-	return 0;
-}
-
-static void
-dp83820pci(void)
-{
-	int port;
-	Pcidev *p;
-	Ctlr *ctlr;
-
-	p = nil;
-	while(p = pcimatch(p, 0, 0)){
-		if(p->ccrb != 0x02 || p->ccru != 0)
-			continue;
-
-		switch((p->did<<16)|p->vid){
-		default:
-			continue;
-		case (0x0022<<16)|0x100B:	/* DP83820 (Gig-NIC) */
-			break;
-		}
-
-		port = upamalloc(p->mem[1].bar & ~0x0F, p->mem[1].size, 0);
-		if(port == 0){
-			print("dp83820: can't map %d @ 0x%8.8luX\n",
-				p->mem[1].size, p->mem[1].bar);
-			continue;
-		}
-
-		ctlr = malloc(sizeof(Ctlr));
-		ctlr->port = port;
-		ctlr->pcidev = p;
-		ctlr->id = p->did<<16 | p->vid;
-
-		ctlr->nic = KADDR(ctlr->port);
-		if(dp83820reset(ctlr)){
-			free(ctlr);
-			continue;
-		}
-		pcisetbme(p);
-
-		if(dp83820ctlrhead != nil)
-			dp83820ctlrtail->next = ctlr;
-		else
-			dp83820ctlrhead = ctlr;
-		dp83820ctlrtail = ctlr;
-	}
-}
-
-int
-dp83820pnp(Ether* edev)
-{
-	int i;
-	Ctlr *ctlr;
-	uchar ea[Eaddrlen];
-
-	if(dp83820ctlrhead == nil)
-		dp83820pci();
-
-	/*
-	 * Any adapter matches if no edev->port is supplied,
-	 * otherwise the ports must match.
-	 */
-	for(ctlr = dp83820ctlrhead; ctlr != nil; ctlr = ctlr->next){
-		if(ctlr->active)
-			continue;
-		if(edev->port == 0 || edev->port == ctlr->port){
-			ctlr->active = 1;
-			break;
-		}
-	}
-	if(ctlr == nil)
-		return -1;
-
-	edev->ctlr = ctlr;
-	edev->port = ctlr->port;
-	edev->irq = ctlr->pcidev->intl;
-	edev->tbdf = ctlr->pcidev->tbdf;
-
-	/*
-	 * Check if the adapter's station address is to be overridden.
-	 * If not, read it from the EEPROM and set in ether->ea prior to
-	 * loading the station address in the hardware.
-	 */
-	memset(ea, 0, Eaddrlen);
-	if(memcmp(ea, edev->ea, Eaddrlen) == 0)
-		for(i = 0; i < Eaddrlen/2; i++){
-			edev->ea[2*i] = ctlr->eeprom[0x0C-i];
-			edev->ea[2*i+1] = ctlr->eeprom[0x0C-i]>>8;
-		}
-
-	edev->attach = dp83820attach;
-	edev->transmit = dp83820transmit;
-	edev->interrupt = dp83820interrupt;
-	edev->detach = dp83820shutdown;
-	return 0;
-}
--- a/os/boot/pc/etherec2t.c
+++ /dev/null
@@ -1,155 +1,0 @@
-/*
- * Supposed NE2000 PCMCIA clones, see the comments in ether2000.c
- */
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-#include "etherif.h"
-#include "ether8390.h"
-
-enum {
-	Data		= 0x10,		/* offset from I/O base of data port */
-	Reset		= 0x1F,		/* offset from I/O base of reset port */
-};
-
-static char* ec2tpcmcia[] = {
-	"EC2T",				/* Linksys Combo PCMCIA EthernetCard */
-	"PCMPC100",			/* EtherFast 10/100 PC Card */
-	"EN2216",			/* Accton EtherPair-PCMCIA */
-	"FA410TX",			/* Netgear FA410TX */
-	"Network Everywhere",		/* Linksys NP10T 10BaseT Card */
-	nil,
-};
-
-int
-ec2treset(Ether* ether)
-{
-	ushort buf[16];
-	ulong port;
-	Dp8390 *ctlr;
-	int i, slot;
-	uchar ea[Eaddrlen], sum, x;
-	char *type;
-
-	/*
-	 * Set up the software configuration.
-	 * Use defaults for port, irq, mem and size
-	 * if not specified.
-	 * The manual says 16KB memory, the box
-	 * says 32KB. The manual seems to be correct.
-	 */
-	if(ether->port == 0)
-		ether->port = 0x300;
-	if(ether->irq == 0)
-		ether->irq = 9;
-	if(ether->mem == 0)
-		ether->mem = 0x4000;
-	if(ether->size == 0)
-		ether->size = 16*1024;
-	port = ether->port;
-
-	//if(ioalloc(ether->port, 0x20, 0, "ec2t") < 0)
-	//	return -1;
-	slot = -1;
-	type = nil;
-	for(i = 0; ec2tpcmcia[i] != nil; i++){
-		type = ec2tpcmcia[i];
-		if((slot = pcmspecial(type, ether)) >= 0)
-			break;
-	}
-	if(ec2tpcmcia[i] == nil){
-		for(i = 0; i < ether->nopt; i++){
-			if(cistrncmp(ether->opt[i], "id=", 3))
-				continue;
-			type = &ether->opt[i][3];
-			if((slot = pcmspecial(type, ether)) >= 0)
-				break;
-		}
-	}
-	if(slot < 0){
-	//	iofree(port);
-		return -1;
-	}
-
-	ether->ctlr = malloc(sizeof(Dp8390));
-	ctlr = ether->ctlr;
-	ctlr->width = 2;
-	ctlr->ram = 0;
-
-	ctlr->port = port;
-	ctlr->data = port+Data;
-
-	ctlr->tstart = HOWMANY(ether->mem, Dp8390BufSz);
-	ctlr->pstart = ctlr->tstart + HOWMANY(sizeof(Etherpkt), Dp8390BufSz);
-	ctlr->pstop = ctlr->tstart + HOWMANY(ether->size, Dp8390BufSz);
-
-	ctlr->dummyrr = 0;
-	for(i = 0; i < ether->nopt; i++){
-		if(cistrcmp(ether->opt[i], "nodummyrr") == 0)
-			ctlr->dummyrr = 0;
-		else if(cistrncmp(ether->opt[i], "dummyrr=", 8) == 0)
-			ctlr->dummyrr = strtol(&ether->opt[i][8], nil, 0);
-	}
-
-	/*
-	 * Reset the board. This is done by doing a read
-	 * followed by a write to the Reset address.
-	 */
-	buf[0] = inb(port+Reset);
-	delay(2);
-	outb(port+Reset, buf[0]);
-	delay(2);
-
-	/*
-	 * Init the (possible) chip, then use the (possible)
-	 * chip to read the (possible) PROM for ethernet address
-	 * and a marker byte.
-	 * Could just look at the DP8390 command register after
-	 * initialisation has been tried, but that wouldn't be
-	 * enough, there are other ethernet boards which could
-	 * match.
-	 */
-	dp8390reset(ether);
-	sum = 0;
-	if(cistrcmp(type, "PCMPC100") == 0 || cistrcmp(type, "FA410TX") == 0){
-		/*
-		 * The PCMPC100 has the ethernet address in I/O space.
-		 * There's a checksum over 8 bytes which sums to 0xFF.
-		 */
-		for(i = 0; i < 8; i++){
-			x = inb(port+0x14+i);
-			sum += x;
-			buf[i] = (x<<8)|x;
-		}
-	}
-	else{
-		memset(buf, 0, sizeof(buf));
-		dp8390read(ctlr, buf, 0, sizeof(buf));
-		if((buf[0x0E] & 0xFF) == 0x57 && (buf[0x0F] & 0xFF) == 0x57)
-			sum = 0xFF;
-	}
-	if(sum != 0xFF){
-		pcmspecialclose(slot);
-		//iofree(ether->port);
-		free(ether->ctlr);
-		return -1;
-	}
-
-	/*
-	 * Stupid machine. Shorts were asked for,
-	 * shorts were delivered, although the PROM is a byte array.
-	 * Set the ethernet address.
-	 */
-	memset(ea, 0, Eaddrlen);
-	if(memcmp(ea, ether->ea, Eaddrlen) == 0){
-		for(i = 0; i < sizeof(ether->ea); i++)
-			ether->ea[i] = buf[i];
-	}
-	dp8390setea(ether);
-
-	return 0;
-}
--- a/os/boot/pc/etherelnk3.c
+++ /dev/null
@@ -1,1897 +1,0 @@
-/*
- * Etherlink III, Fast EtherLink and Fast EtherLink XL adapters.
- * To do:
- *	check robustness in the face of errors (e.g. busmaster & rxUnderrun);
- *	RxEarly and busmaster;
- *	autoSelect;
- *	PCI latency timer and master enable;
- *	errata list;
- *	rewrite all initialisation.
- *
- * Product ID:
- *	9150 ISA	3C509[B]
- *	9050 ISA	3C509[B]-TP
- *	9450 ISA	3C509[B]-COMBO
- *	9550 ISA	3C509[B]-TPO
- *
- *	9350 EISA	3C579
- *	9250 EISA	3C579-TP
- *
- *	5920 EISA	3C592-[TP|COMBO|TPO]
- *	5970 EISA	3C597-TX	Fast Etherlink 10BASE-T/100BASE-TX
- *	5971 EISA	3C597-T4	Fast Etherlink 10BASE-T/100BASE-T4
- *	5972 EISA	3C597-MII	Fast Etherlink 10BASE-T/MII
- *
- *	5900 PCI	3C590-[TP|COMBO|TPO]
- *	5950 PCI	3C595-TX	Fast Etherlink Shared 10BASE-T/100BASE-TX
- *	5951 PCI	3C595-T4	Fast Etherlink Shared 10BASE-T/100BASE-T4
- *	5952 PCI	3C595-MII	Fast Etherlink 10BASE-T/MII
- *
- *	9000 PCI	3C900-TPO	Etherlink III XL PCI 10BASE-T
- *	9001 PCI	3C900-COMBO	Etherlink III XL PCI 10BASE-T/10BASE-2/AUI
- *	9005 PCI	3C900B-COMBO	Etherlink III XL PCI 10BASE-T/10BASE-2/AUI
- *	9050 PCI	3C905-TX	Fast Etherlink XL Shared 10BASE-T/100BASE-TX
- *	9051 PCI	3C905-T4	Fast Etherlink Shared 10BASE-T/100BASE-T4
- *	9055 PCI	3C905B-TX	Fast Etherlink Shared 10BASE-T/100BASE-TX
- *	9200 PCI	3C905C-TX	Fast Etherlink Shared 10BASE-T/100BASE-TX
- *
- *	9058 PCMCIA	3C589[B]-[TP|COMBO]
- *
- *	627C MCA	3C529
- *	627D MCA	3C529-TP
- */
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-#include "etherif.h"
-
-#define XCVRDEBUG		if(0)print
-
-enum {
-	IDport			= 0x0110,	/* anywhere between 0x0100 and 0x01F0 */
-};
-
-enum {						/* all windows */
-	CommandR		= 0x000E,
-	IntStatusR		= 0x000E,
-};
-
-enum {						/* Commands */
-	GlobalReset		= 0x0000,
-	SelectRegisterWindow	= 0x0001,
-	EnableDcConverter	= 0x0002,
-	RxDisable		= 0x0003,
-	RxEnable		= 0x0004,
-	RxReset			= 0x0005,
-	Stall			= 0x0006,	/* 3C90x */
-	TxDone			= 0x0007,
-	RxDiscard		= 0x0008,
-	TxEnable		= 0x0009,
-	TxDisable		= 0x000A,
-	TxReset			= 0x000B,
-	RequestInterrupt	= 0x000C,
-	AcknowledgeInterrupt	= 0x000D,
-	SetInterruptEnable	= 0x000E,
-	SetIndicationEnable	= 0x000F,	/* SetReadZeroMask */
-	SetRxFilter		= 0x0010,
-	SetRxEarlyThresh	= 0x0011,
-	SetTxAvailableThresh	= 0x0012,
-	SetTxStartThresh	= 0x0013,
-	StartDma		= 0x0014,	/* initiate busmaster operation */
-	StatisticsEnable	= 0x0015,
-	StatisticsDisable	= 0x0016,
-	DisableDcConverter	= 0x0017,
-	SetTxReclaimThresh	= 0x0018,	/* PIO-only adapters */
-	PowerUp			= 0x001B,	/* not all adapters */
-	PowerDownFull		= 0x001C,	/* not all adapters */
-	PowerAuto		= 0x001D,	/* not all adapters */
-};
-
-enum {						/* (Global|Rx|Tx)Reset command bits */
-	tpAuiReset		= 0x0001,	/* 10BaseT and AUI transceivers */
-	endecReset		= 0x0002,	/* internal Ethernet encoder/decoder */
-	networkReset		= 0x0004,	/* network interface logic */
-	fifoReset		= 0x0008,	/* FIFO control logic */
-	aismReset		= 0x0010,	/* autoinitialise state-machine logic */
-	hostReset		= 0x0020,	/* bus interface logic */
-	dmaReset		= 0x0040,	/* bus master logic */
-	vcoReset		= 0x0080,	/* on-board 10Mbps VCO */
-	updnReset		= 0x0100,	/* upload/download (Rx/TX) logic */
-
-	resetMask		= 0x01FF,
-};
-
-enum {						/* Stall command bits */
-	upStall			= 0x0000,
-	upUnStall		= 0x0001,
-	dnStall			= 0x0002,
-	dnUnStall		= 0x0003,
-};
-
-enum {						/* SetRxFilter command bits */
-	receiveIndividual	= 0x0001,	/* match station address */
-	receiveMulticast	= 0x0002,
-	receiveBroadcast	= 0x0004,
-	receiveAllFrames	= 0x0008,	/* promiscuous */
-};
-
-enum {						/* StartDma command bits */
-	Upload			= 0x0000,	/* transfer data from adapter to memory */
-	Download		= 0x0001,	/* transfer data from memory to adapter */
-};
-
-enum {						/* IntStatus bits */
-	interruptLatch		= 0x0001,
-	hostError		= 0x0002,	/* Adapter Failure */
-	txComplete		= 0x0004,
-	txAvailable		= 0x0008,
-	rxComplete		= 0x0010,
-	rxEarly			= 0x0020,
-	intRequested		= 0x0040,
-	updateStats		= 0x0080,
-	transferInt		= 0x0100,	/* Bus Master Transfer Complete */
-	dnComplete		= 0x0200,
-	upComplete		= 0x0400,
-	busMasterInProgress	= 0x0800,
-	commandInProgress	= 0x1000,
-
-	interruptMask		= 0x07FE,
-};
-
-#define COMMAND(port, cmd, a)	outs((port)+CommandR, ((cmd)<<11)|(a))
-#define STATUS(port)		ins((port)+IntStatusR)
-
-enum {						/* Window 0 - setup */
-	Wsetup			= 0x0000,
-						/* registers */
-	ManufacturerID		= 0x0000,	/* 3C5[08]*, 3C59[27] */
-	ProductID		= 0x0002,	/* 3C5[08]*, 3C59[27] */
-	ConfigControl		= 0x0004,	/* 3C5[08]*, 3C59[27] */
-	AddressConfig		= 0x0006,	/* 3C5[08]*, 3C59[27] */
-	ResourceConfig		= 0x0008,	/* 3C5[08]*, 3C59[27] */
-	EepromCommand		= 0x000A,
-	EepromData		= 0x000C,
-						/* AddressConfig Bits */
-	autoSelect9		= 0x0080,
-	xcvrMask9		= 0xC000,
-						/* ConfigControl bits */
-	Ena			= 0x0001,
-	base10TAvailable9	= 0x0200,
-	coaxAvailable9		= 0x1000,
-	auiAvailable9		= 0x2000,
-						/* EepromCommand bits */
-	_EepromReadRegister	= 0x0080,
-	_EepromRead8bRegister	= 0x0230,
-	EepromBusy		= 0x8000,
-};
-
-static int EepromReadRegister = _EepromReadRegister;
-
-#define EEPROMCMD(port, cmd, a)	outs((port)+EepromCommand, (cmd)|(a))
-#define EEPROMBUSY(port)	(ins((port)+EepromCommand) & EepromBusy)
-#define EEPROMDATA(port)	ins((port)+EepromData)
-
-enum {						/* Window 1 - operating set */
-	Wop			= 0x0001,
-						/* registers */
-	Fifo			= 0x0000,
-	RxError			= 0x0004,	/* 3C59[0257] only */
-	RxStatus		= 0x0008,
-	Timer			= 0x000A,
-	TxStatus		= 0x000B,
-	TxFree			= 0x000C,
-						/* RxError bits */
-	rxOverrun		= 0x0001,
-	runtFrame		= 0x0002,
-	alignmentError		= 0x0004,	/* Framing */
-	crcError		= 0x0008,
-	oversizedFrame		= 0x0010,
-	dribbleBits		= 0x0080,
-						/* RxStatus bits */
-	rxBytes			= 0x1FFF,	/* 3C59[0257] mask */
-	rxBytes9		= 0x07FF,	/* 3C5[078]9 mask */
-	rxError9		= 0x3800,	/* 3C5[078]9 error mask */
-	rxOverrun9		= 0x0000,
-	oversizedFrame9		= 0x0800,
-	dribbleBits9		= 0x1000,
-	runtFrame9		= 0x1800,
-	alignmentError9		= 0x2000,	/* Framing */
-	crcError9		= 0x2800,
-	rxError			= 0x4000,
-	rxIncomplete		= 0x8000,
-						/* TxStatus Bits */
-	txStatusOverflow	= 0x0004,
-	maxCollisions		= 0x0008,
-	txUnderrun		= 0x0010,
-	txJabber		= 0x0020,
-	interruptRequested	= 0x0040,
-	txStatusComplete	= 0x0080,
-};
-
-enum {						/* Window 2 - station address */
-	Wstation		= 0x0002,
-
-	ResetOp905B		= 0x000C,
-};
-
-enum {						/* Window 3 - FIFO management */
-	Wfifo			= 0x0003,
-						/* registers */
-	InternalConfig		= 0x0000,	/* 3C509B, 3C589, 3C59[0257] */
-	OtherInt		= 0x0004,	/* 3C59[0257] */
-	RomControl		= 0x0006,	/* 3C509B, 3C59[27] */
-	MacControl		= 0x0006,	/* 3C59[0257] */
-	ResetOptions		= 0x0008,	/* 3C59[0257] */
-	MediaOptions		= 0x0008,	/* 3C905B */
-	RxFree			= 0x000A,
-						/* InternalConfig bits */
-	disableBadSsdDetect	= 0x00000100,
-	ramLocation		= 0x00000200,	/* 0 external, 1 internal */
-	ramPartition5to3	= 0x00000000,
-	ramPartition3to1	= 0x00010000,
-	ramPartition1to1	= 0x00020000,
-	ramPartition3to5	= 0x00030000,
-	ramPartitionMask	= 0x00030000,
-	xcvr10BaseT		= 0x00000000,
-	xcvrAui			= 0x00100000,	/* 10BASE5 */
-	xcvr10Base2		= 0x00300000,
-	xcvr100BaseTX		= 0x00400000,
-	xcvr100BaseFX		= 0x00500000,
-	xcvrMii			= 0x00600000,
-	xcvrMask		= 0x00700000,
-	autoSelect		= 0x01000000,
-						/* MacControl bits */
-	deferExtendEnable	= 0x0001,
-	deferTimerSelect	= 0x001E,	/* mask */
-	fullDuplexEnable	= 0x0020,
-	allowLargePackets	= 0x0040,
-	extendAfterCollision	= 0x0080,	/* 3C90xB */
-	flowControlEnable	= 0x0100,	/* 3C90xB */
-	vltEnable		= 0x0200,	/* 3C90xB */
-						/* ResetOptions bits */
-	baseT4Available		= 0x0001,
-	baseTXAvailable		= 0x0002,
-	baseFXAvailable		= 0x0004,
-	base10TAvailable	= 0x0008,
-	coaxAvailable		= 0x0010,
-	auiAvailable		= 0x0020,
-	miiConnector		= 0x0040,
-};
-
-enum {						/* Window 4 - diagnostic */
-	Wdiagnostic		= 0x0004,
-						/* registers */
-	VcoDiagnostic		= 0x0002,
-	FifoDiagnostic		= 0x0004,
-	NetworkDiagnostic	= 0x0006,
-	PhysicalMgmt		= 0x0008,
-	MediaStatus		= 0x000A,
-	BadSSD			= 0x000C,
-	UpperBytesOk		= 0x000D,
-						/* FifoDiagnostic bits */
-	txOverrun		= 0x0400,
-	rxUnderrun		= 0x2000,
-	receiving		= 0x8000,
-						/* PhysicalMgmt bits */
-	mgmtClk			= 0x0001,
-	mgmtData		= 0x0002,
-	mgmtDir			= 0x0004,
-	cat5LinkTestDefeat	= 0x8000,
-						/* MediaStatus bits */
-	dataRate100		= 0x0002,
-	crcStripDisable		= 0x0004,
-	enableSqeStats		= 0x0008,
-	collisionDetect		= 0x0010,
-	carrierSense		= 0x0020,
-	jabberGuardEnable	= 0x0040,
-	linkBeatEnable		= 0x0080,
-	jabberDetect		= 0x0200,
-	polarityReversed	= 0x0400,
-	linkBeatDetect		= 0x0800,
-	txInProg		= 0x1000,
-	dcConverterEnabled	= 0x4000,
-	auiDisable		= 0x8000,	/* 10BaseT transceiver selected */
-};
-
-enum {						/* Window 5 - internal state */
-	Wstate			= 0x0005,
-						/* registers */
-	TxStartThresh		= 0x0000,
-	TxAvailableThresh	= 0x0002,
-	RxEarlyThresh		= 0x0006,
-	RxFilter		= 0x0008,
-	InterruptEnable		= 0x000A,
-	IndicationEnable	= 0x000C,
-};
-
-enum {						/* Window 6 - statistics */
-	Wstatistics		= 0x0006,
-						/* registers */
-	CarrierLost		= 0x0000,
-	SqeErrors		= 0x0001,
-	MultipleColls		= 0x0002,
-	SingleCollFrames	= 0x0003,
-	LateCollisions		= 0x0004,
-	RxOverruns		= 0x0005,
-	FramesXmittedOk		= 0x0006,
-	FramesRcvdOk		= 0x0007,
-	FramesDeferred		= 0x0008,
-	UpperFramesOk		= 0x0009,
-	BytesRcvdOk		= 0x000A,
-	BytesXmittedOk		= 0x000C,
-};
-
-enum {						/* Window 7 - bus master operations */
-	Wmaster			= 0x0007,
-						/* registers */
-	MasterAddress		= 0x0000,
-	MasterLen		= 0x0006,
-	MasterStatus		= 0x000C,
-						/* MasterStatus bits */
-	masterAbort		= 0x0001,
-	targetAbort		= 0x0002,
-	targetRetry		= 0x0004,
-	targetDisc		= 0x0008,
-	masterDownload		= 0x1000,
-	masterUpload		= 0x4000,
-	masterInProgress	= 0x8000,
-
-	masterMask		= 0xD00F,
-};
-
-enum {						/* 3C90x extended register set */
-	Timer905		= 0x001A,	/* 8-bits */
-	TxStatus905		= 0x001B,	/* 8-bits */
-	PktStatus		= 0x0020,	/* 32-bits */
-	DnListPtr		= 0x0024,	/* 32-bits, 8-byte aligned */
-	FragAddr		= 0x0028,	/* 32-bits */
-	FragLen			= 0x002C,	/* 16-bits */
-	ListOffset		= 0x002E,	/* 8-bits */
-	TxFreeThresh		= 0x002F,	/* 8-bits */
-	UpPktStatus		= 0x0030,	/* 32-bits */
-	FreeTimer		= 0x0034,	/* 16-bits */
-	UpListPtr		= 0x0038,	/* 32-bits, 8-byte aligned */
-
-						/* PktStatus bits */
-	fragLast		= 0x00000001,
-	dnCmplReq		= 0x00000002,
-	dnStalled		= 0x00000004,
-	upCompleteX		= 0x00000008,
-	dnCompleteX		= 0x00000010,
-	upRxEarlyEnable		= 0x00000020,
-	armCountdown		= 0x00000040,
-	dnInProg		= 0x00000080,
-	counterSpeed		= 0x00000010,	/* 0 3.2uS, 1 320nS */
-	countdownMode		= 0x00000020,
-						/* UpPktStatus bits (dpd->control) */
-	upPktLenMask		= 0x00001FFF,
-	upStalled		= 0x00002000,
-	upError			= 0x00004000,
-	upPktComplete		= 0x00008000,
-	upOverrun		= 0x00010000,	/* RxError<<16 */
-	upRuntFrame		= 0x00020000,
-	upAlignmentError	= 0x00040000,
-	upCRCError		= 0x00080000,
-	upOversizedFrame	= 0x00100000,
-	upDribbleBits		= 0x00800000,
-	upOverflow		= 0x01000000,
-
-	dnIndicate		= 0x80000000,	/* FrameStartHeader (dpd->control) */
-
-	updnLastFrag		= 0x80000000,	/* (dpd->len) */
-
-	Nup			= 32,
-	Ndn			= 64,
-};
-
-/*
- * Up/Dn Packet Descriptors.
- * The hardware info (np, control, addr, len) must be 8-byte aligned
- * and this structure size must be a multiple of 8.
- */
-typedef struct Pd Pd;
-typedef struct Pd {
-	ulong	np;				/* next pointer */
-	ulong	control;			/* FSH or UpPktStatus */
-	ulong	addr;
-	ulong	len;
-
-	Pd*	next;
-	void *vaddr;
-} Pd;
-
-typedef struct {
-	Lock	wlock;				/* window access */
-
-	int	attached;
-	int	busmaster;
-	Block*	rbp;				/* receive buffer */
-
-	Block*	txbp;				/* FIFO -based transmission */
-	int	txthreshold;
-	int	txbusy;
-
-	int	nup;				/* full-busmaster -based reception */
-	void*	upbase;
-	Pd*	upr;
-	Pd*	uphead;
-
-	int	ndn;				/* full-busmaster -based transmission */
-	void*	dnbase;
-	Pd*	dnr;
-	Pd*	dnhead;
-	Pd*	dntail;
-	int	dnq;
-
-	long	interrupts;			/* statistics */
-	long	timer[2];
-	long	stats[BytesRcvdOk+3];
-
-	int	upqmax;
-	int	upqmaxhw;
-	ulong	upinterrupts;
-	ulong	upqueued;
-	ulong	upstalls;
-	int	dnqmax;
-	int	dnqmaxhw;
-	ulong	dninterrupts;
-	ulong	dnqueued;
-
-	int	xcvr;				/* transceiver type */
-	int	rxstatus9;			/* old-style RxStatus register */
-	int	rxearly;			/* RxEarlyThreshold */
-	int	ts;				/* threshold shift */
-	int	upenabled;
-	int	dnenabled;
-} Ctlr;
-
-static void
-init905(Ctlr* ctlr)
-{
-	Pd *pd, *prev;
-	uchar *vaddr;
-
-	/*
-	 * Create rings for the receive and transmit sides.
-	 * Take care with alignment:
-	 *	make sure ring base is 8-byte aligned;
-	 *	make sure each entry is 8-byte aligned.
-	 */
-	ctlr->upbase = malloc((ctlr->nup+1)*sizeof(Pd));
-	ctlr->upr = (Pd*)ROUNDUP((ulong)ctlr->upbase, 8);
-	vaddr = ialloc((ctlr->nup+1)*ROUNDUP(sizeof(Etherpkt)+4, 8), 8);
-
-	prev = ctlr->upr;
-	for(pd = &ctlr->upr[ctlr->nup-1]; pd >= ctlr->upr; pd--){
-		pd->np = PADDR(&prev->np);
-		pd->control = 0;
-		pd->vaddr = vaddr;
-		pd->addr = PADDR(vaddr);
-		vaddr += ROUNDUP(sizeof(Etherpkt)+4, 8);
-		pd->len = updnLastFrag|sizeof(Etherpkt);
-
-		pd->next = prev;
-		prev = pd;
-	}
-	ctlr->uphead = ctlr->upr;
-
-	ctlr->dnbase = malloc((ctlr->ndn+1)*sizeof(Pd));
-	ctlr->dnr = (Pd*)ROUNDUP((ulong)ctlr->dnbase, 8);
-	vaddr = ialloc((ctlr->ndn+1)*ROUNDUP(sizeof(Etherpkt)+4, 8), 8); 
-
-	prev = ctlr->dnr;
-	for(pd = &ctlr->dnr[ctlr->ndn-1]; pd >= ctlr->dnr; pd--){
-		pd->next = prev;
-		pd->vaddr = vaddr;								
-		pd->addr = PADDR(vaddr);						
-		vaddr += ROUNDUP(sizeof(Etherpkt)+4, 8);		
-		prev = pd;
-	}
-	ctlr->dnhead = ctlr->dnr;
-	ctlr->dntail = ctlr->dnr;
-	ctlr->dnq = 0;
-}
-
-static Block*
-rbpalloc(Block* (*f)(int))
-{
-	Block *bp;
-	ulong addr;
-
-	/*
-	 * The receive buffers must be on a 32-byte
-	 * boundary for EISA busmastering.
-	 */
-	if(bp = f(ROUNDUP(sizeof(Etherpkt), 4) + 31)){
-		addr = (ulong)bp->base;
-		addr = ROUNDUP(addr, 32);
-		bp->rp = (uchar*)addr;
-	}
-
-	return bp;
-}
-
-static uchar*
-startdma(Ether* ether, ulong address)
-{
-	int port, status, w;
-	uchar *wp;
-
-	port = ether->port;
-
-	w = (STATUS(port)>>13) & 0x07;
-	COMMAND(port, SelectRegisterWindow, Wmaster);
-
-	wp = KADDR(inl(port+MasterAddress));
-	status = ins(port+MasterStatus);
-	if(status & (masterInProgress|targetAbort|masterAbort))
-		print("#l%d: BM status 0x%uX\n", ether->ctlrno, status);
-	outs(port+MasterStatus, masterMask);
-	outl(port+MasterAddress, address);
-	outs(port+MasterLen, sizeof(Etherpkt));
-	COMMAND(port, StartDma, Upload);
-
-	COMMAND(port, SelectRegisterWindow, w);
-	return wp;
-}
-
-/* On the 575B and C, interrupts need to be acknowledged in CardBus memory space */
-static void
-intrack3c575(ulong *cbfns)
-{
-	cbfns[1] = 0x8000;
-}
-
-static void
-attach(Ether* ether)
-{
-	int port, x;
-	Ctlr *ctlr;
-
-	ctlr = ether->ctlr;
-	ilock(&ctlr->wlock);
-	if(ctlr->attached){
-		iunlock(&ctlr->wlock);
-		return;
-	}
-
-	port = ether->port;
-
-	COMMAND(port, SetRxFilter, receiveIndividual|receiveBroadcast);
-	x = interruptMask;
-	if(ctlr->busmaster == 1)
-		x &= ~(rxEarly|rxComplete);
-	else{
-		if(ctlr->dnenabled)
-			x &= ~transferInt;
-		if(ctlr->upenabled)
-			x &= ~(rxEarly|rxComplete);
-	}
-	COMMAND(port, SetIndicationEnable, x);
-	COMMAND(port, SetInterruptEnable, x);
-	COMMAND(port, RxEnable, 0);
-	COMMAND(port, TxEnable, 0);
-
-	if (ether->mem)
-		/* This must be a cardbus card.  Acknowledge the interrupt */
-		intrack3c575(KADDR(ether->mem));
-		
-	/*
-	 * Prime the busmaster channel for receiving directly into a
-	 * receive packet buffer if necessary.
-	 */
-	if(ctlr->busmaster == 1)
-		startdma(ether, PADDR(ctlr->rbp->rp));
-	else{
-		if(ctlr->upenabled)
-			outl(port+UpListPtr, PADDR(&ctlr->uphead->np));
-	}
-
-	ctlr->attached = 1;
-	iunlock(&ctlr->wlock);
-
-}
-
-static void
-statistics(Ether* ether)
-{
-	int port, i, u, w;
-	Ctlr *ctlr;
-
-	port = ether->port;
-	ctlr = ether->ctlr;
-
-	/*
-	 * 3C59[27] require a read between a PIO write and
-	 * reading a statistics register.
-	 */
-	w = (STATUS(port)>>13) & 0x07;
-	COMMAND(port, SelectRegisterWindow, Wstatistics);
-	STATUS(port);
-
-	for(i = 0; i < UpperFramesOk; i++)
-		ctlr->stats[i] += inb(port+i) & 0xFF;
-	u = inb(port+UpperFramesOk) & 0xFF;
-	ctlr->stats[FramesXmittedOk] += (u & 0x30)<<4;
-	ctlr->stats[FramesRcvdOk] += (u & 0x03)<<8;
-	ctlr->stats[BytesRcvdOk] += ins(port+BytesRcvdOk) & 0xFFFF;
-	ctlr->stats[BytesRcvdOk+1] += ins(port+BytesXmittedOk) & 0xFFFF;
-
-	switch(ctlr->xcvr){
-
-	case xcvrMii:
-	case xcvr100BaseTX:
-	case xcvr100BaseFX:
-		COMMAND(port, SelectRegisterWindow, Wdiagnostic);
-		STATUS(port);
-		ctlr->stats[BytesRcvdOk+2] += inb(port+BadSSD);
-		break;
-	}
-
-	COMMAND(port, SelectRegisterWindow, w);
-}
-
-static void
-txstart(Ether* ether)
-{
-	int port, len;
-	Ctlr *ctlr;
-	RingBuf *tb;
-
-	port = ether->port;
-	ctlr = ether->ctlr;
-
-	/*
-	 * Attempt to top-up the transmit FIFO. If there's room simply
-	 * stuff in the packet length (unpadded to a dword boundary), the
-	 * packet data (padded) and remove the packet from the queue.
-	 * If there's no room post an interrupt for when there is.
-	 * This routine is called both from the top level and from interrupt
-	 * level and expects to be called with ctlr->wlock already locked
-	 * and the correct register window (Wop) in place.
-	 */
-	for(tb = &ether->tb[ether->ti]; tb->owner == Interface; tb = &ether->tb[ether->ti]){
-		len = ROUNDUP(tb->len, 4);
-		if(len+4 <= ins(port+TxFree)){
-			outl(port+Fifo, tb->len);
-			outsl(port+Fifo, tb->pkt, len/4);
-			tb->owner = Host;
-			ether->ti = NEXT(ether->ti, ether->ntb);
-		}
-		else{
-			if(ctlr->txbusy == 0){
-				ctlr->txbusy = 1;
-				COMMAND(port, SetTxAvailableThresh, len>>ctlr->ts);
-			}
-			break;
-		}
-	}
-}
-
-static void
-txstart905(Ether* ether)
-{
-	Ctlr *ctlr;
-	int port, stalled, timeo;
-	RingBuf *tb;
-	Pd *pd;
-
-	ctlr = ether->ctlr;
-	port = ether->port;
-
-	/*
-	 * Free any completed packets.
-	 */
-	pd = ctlr->dntail;
-	while(ctlr->dnq){
-		if(PADDR(&pd->np) == inl(port+DnListPtr))
-			break;
-		ctlr->dnq--;
-		pd = pd->next;
-	}
-	ctlr->dntail = pd;
-
-	stalled = 0;
-	while(ctlr->dnq < (ctlr->ndn-1)){
-		tb = &ether->tb[ether->ti];
-		if(tb->owner != Interface)
-			break;
-
-		pd = ctlr->dnhead->next;
-		pd->np = 0;
-		pd->control = dnIndicate|tb->len;
-		memmove(pd->vaddr, tb->pkt, tb->len);
-		pd->len = updnLastFrag|tb->len;
-
-		tb->owner = Host;
-		ether->ti = NEXT(ether->ti, ether->ntb);
-
-		if(stalled == 0 && ctlr->dnq && inl(port+DnListPtr)){
-			COMMAND(port, Stall, dnStall);
-			for(timeo = 100; (STATUS(port) & commandInProgress) && timeo; timeo--)
-				;
-			if(timeo == 0)
-				print("#l%d: dnstall %d\n", ether->ctlrno, timeo);
-			stalled = 1;
-		}
-
-		coherence();
-		ctlr->dnhead->np = PADDR(&pd->np);
-		ctlr->dnhead->control &= ~dnIndicate;
-		ctlr->dnhead = pd;
-		if(ctlr->dnq == 0)
-			ctlr->dntail = pd;
-		ctlr->dnq++;
-
-		ctlr->dnqueued++;
-	}
-
-	if(ctlr->dnq > ctlr->dnqmax)
-		ctlr->dnqmax = ctlr->dnq;
-
-	/*
-	 * If the adapter is not currently processing anything
-	 * and there is something on the queue, start it processing.
-	 */
-	if(inl(port+DnListPtr) == 0 && ctlr->dnq)
-		outl(port+DnListPtr, PADDR(&ctlr->dnhead->np));
-	if(stalled)
-		COMMAND(port, Stall, dnUnStall);
-}
-
-static void
-transmit(Ether* ether)
-{
-	Ctlr *ctlr;
-	int port, w;
-
-	port = ether->port;
-	ctlr = ether->ctlr;
-
-	ilock(&ctlr->wlock);
-	if(ctlr->dnenabled)
-		txstart905(ether);
-	else{
-		w = (STATUS(port)>>13) & 0x07;
-		COMMAND(port, SelectRegisterWindow, Wop);
-		txstart(ether);
-		COMMAND(port, SelectRegisterWindow, w);
-	}
-	iunlock(&ctlr->wlock);
-}
-
-static void
-receive905(Ether* ether)
-{
-	Ctlr *ctlr;
-	int len, port, q;
-	Pd *pd;
-	RingBuf *rb;
-
-	ctlr = ether->ctlr;
-	port = ether->port;
-
-	if(inl(port+UpPktStatus) & upStalled)
-		ctlr->upstalls++;
-	q = 0;
-	for(pd = ctlr->uphead; pd->control & upPktComplete; pd = pd->next){
-		if(!(pd->control & upError)){
-			rb = &ether->rb[ether->ri];
-			if (rb->owner == Interface) {
-				len = pd->control & rxBytes;
-				rb->len = len;
-				memmove(rb->pkt, pd->vaddr, len);
-				rb->owner = Host;
-				ether->ri = NEXT(ether->ri, ether->nrb);
-			}
-		}
-
-		pd->control = 0;
-		COMMAND(port, Stall, upUnStall);
-
-		q++;
-	}
-	ctlr->uphead = pd;
-
-	ctlr->upqueued += q;
-	if(q > ctlr->upqmax)
-		ctlr->upqmax = q;
-}
-
-static void
-receive(Ether* ether)
-{
-	int len, port, rxstatus;
-	RingBuf *rb;
-	Ctlr *ctlr;
-
-	port = ether->port;
-	ctlr = ether->ctlr;
-
-	while(((rxstatus = ins(port+RxStatus)) & rxIncomplete) == 0){
-		if(ctlr->busmaster == 1 && (STATUS(port) & busMasterInProgress))
-			break;
-
-		/*
-		 * If there was an error, log it and continue.
-		 * Unfortunately the 3C5[078]9 has the error info in the status register
-		 * and the 3C59[0257] implement a separate RxError register.
-		 */
-		if((rxstatus & rxError) == 0){
-			/*
-			 * Packet received. Read it into the next free
-			 * ring buffer, if any. Must read len bytes padded
-			 * to a doubleword, can be picked out 32-bits at
-			 * a time. The CRC is already stripped off.
-			 */
-			rb = &ether->rb[ether->ri];
-			if(rb->owner == Interface){
-				len = (rxstatus & rxBytes9);
-				rb->len = len;
-				insl(port+Fifo, rb->pkt, HOWMANY(len, 4));
-
-				rb->owner = Host;
-				ether->ri = NEXT(ether->ri, ether->nrb);
-			}else
-if(debug) print("toss...");
-		}
-else
-if(debug) print("error...");
-
-		/*
-		 * All done, discard the packet.
-		 */
-		COMMAND(port, RxDiscard, 0);
-		while(STATUS(port) & commandInProgress)
-			;
-	}
-}
-
-static void
-interrupt(Ureg*, void* arg)
-{
-	Ether *ether;
-	int port, status, s, txstatus, w, x;
-	Ctlr *ctlr;
-
-	ether = arg;
-	port = ether->port;
-	ctlr = ether->ctlr;
-
-	ilock(&ctlr->wlock);
-	status = STATUS(port);
-	if(!(status & (interruptMask|interruptLatch))){
-		iunlock(&ctlr->wlock);
-		return;
-	}
-	w = (status>>13) & 0x07;
-	COMMAND(port, SelectRegisterWindow, Wop);
-
-	ctlr->interrupts++;
-	if(ctlr->busmaster == 2)
-		ctlr->timer[0] += inb(port+Timer905) & 0xFF;
-	else
-		ctlr->timer[0] += inb(port+Timer) & 0xFF;
-
-	do{
-		if(status & hostError){
-			/*
-			 * Adapter failure, try to find out why, reset if
-			 * necessary. What happens if Tx is active and a reset
-			 * occurs, need to retransmit? This probably isn't right.
-			 */
-			COMMAND(port, SelectRegisterWindow, Wdiagnostic);
-			x = ins(port+FifoDiagnostic);
-			COMMAND(port, SelectRegisterWindow, Wop);
-			print("#l%d: status 0x%uX, diag 0x%uX\n",
-			    ether->ctlrno, status, x);
-
-			if(x & txOverrun){
-				if(ctlr->busmaster == 0)
-					COMMAND(port, TxReset, 0);
-				else
-					COMMAND(port, TxReset, (updnReset|dmaReset));
-				COMMAND(port, TxEnable, 0);
-			}
-
-			if(x & rxUnderrun){
-				/*
-				 * This shouldn't happen...
-				 * Reset the receiver and restore the filter and RxEarly
-				 * threshold before re-enabling.
-				 * Need to restart any busmastering?
-				 */
-				COMMAND(port, SelectRegisterWindow, Wstate);
-				s = (port+RxFilter) & 0x000F;
-				COMMAND(port, SelectRegisterWindow, Wop);
-				COMMAND(port, RxReset, 0);
-				while(STATUS(port) & commandInProgress)
-					;
-				COMMAND(port, SetRxFilter, s);
-				COMMAND(port, SetRxEarlyThresh, ctlr->rxearly>>ctlr->ts);
-				COMMAND(port, RxEnable, 0);
-			}
-
-			status &= ~hostError;
-		}
-
-		if(status & (transferInt|rxComplete)){
-			receive(ether);
-			status &= ~(transferInt|rxComplete);
-		}
-
-		if(status & (upComplete)){
-			COMMAND(port, AcknowledgeInterrupt, upComplete);
-			receive905(ether);
-			status &= ~upComplete;
-			ctlr->upinterrupts++;
-		}
-
-		if(status & txComplete){
-			/*
-			 * Pop the TxStatus stack, accumulating errors.
-			 * Adjust the TX start threshold if there was an underrun.
-			 * If there was a Jabber or Underrun error, reset
-			 * the transmitter, taking care not to reset the dma logic
-			 * as a busmaster receive may be in progress.
-			 * For all conditions enable the transmitter.
-			 */
-			if(ctlr->busmaster == 2)
-				txstatus = port+TxStatus905;
-			else
-				txstatus = port+TxStatus;
-			s = 0;
-			do{
-				if(x = inb(txstatus))
-					outb(txstatus, 0);
-				s |= x;
-			}while(STATUS(port) & txComplete);
-
-			if(s & txUnderrun){
-				if(ctlr->dnenabled){
-					while(inl(port+PktStatus) & dnInProg)
-						;
-				}
-				COMMAND(port, SelectRegisterWindow, Wdiagnostic);
-				while(ins(port+MediaStatus) & txInProg)
-					;
-				COMMAND(port, SelectRegisterWindow, Wop);
-				if(ctlr->txthreshold < ETHERMAXTU)
-					ctlr->txthreshold += ETHERMINTU;
-			}
-
-			/*
-			 * According to the manual, maxCollisions does not require
-			 * a TxReset, merely a TxEnable. However, evidence points to
-			 * it being necessary on the 3C905. The jury is still out.
-			 * On busy or badly configured networks maxCollisions can
-			 * happen frequently enough for messages to be annoying so
-			 * keep quiet about them by popular request.
-			 */
-			if(s & (txJabber|txUnderrun|maxCollisions)){
-				if(ctlr->busmaster == 0)
-					COMMAND(port, TxReset, 0);
-				else
-					COMMAND(port, TxReset, (updnReset|dmaReset));
-				while(STATUS(port) & commandInProgress)
-					;
-				COMMAND(port, SetTxStartThresh, ctlr->txthreshold>>ctlr->ts);
-				if(ctlr->busmaster == 2)
-					outl(port+TxFreeThresh, HOWMANY(ETHERMAXTU, 256));
-				if(ctlr->dnenabled)
-					status |= dnComplete;
-			}
-
-			if(s & ~(txStatusComplete|maxCollisions))
-				print("#l%d: txstatus 0x%uX, threshold %d\n",
-			    		ether->ctlrno, s, ctlr->txthreshold);
-			COMMAND(port, TxEnable, 0);
-			status &= ~txComplete;
-			status |= txAvailable;
-		}
-
-		if(status & txAvailable){
-			COMMAND(port, AcknowledgeInterrupt, txAvailable);
-			ctlr->txbusy = 0;
-			txstart(ether);
-			status &= ~txAvailable;
-		}
-
-		if(status & dnComplete){
-			COMMAND(port, AcknowledgeInterrupt, dnComplete);
-			txstart905(ether);
-			status &= ~dnComplete;
-			ctlr->dninterrupts++;
-		}
-
-		if(status & updateStats){
-			statistics(ether);
-			status &= ~updateStats;
-		}
-
-		/*
-		 * Currently, this shouldn't happen.
-		 */
-		if(status & rxEarly){
-			COMMAND(port, AcknowledgeInterrupt, rxEarly);
-			status &= ~rxEarly;
-		}
-
-		/*
-		 * Panic if there are any interrupts not dealt with.
-		 */
-		if(status & interruptMask)
-			panic("#l%d: interrupt mask 0x%uX\n", ether->ctlrno, status);
-
-		COMMAND(port, AcknowledgeInterrupt, interruptLatch);
-		if (ether->mem) 
-			intrack3c575((ulong *)KADDR(ether->mem));
-
-	}while((status = STATUS(port)) & (interruptMask|interruptLatch));
-
-	if(ctlr->busmaster == 2)
-		ctlr->timer[1] += inb(port+Timer905) & 0xFF;
-	else
-		ctlr->timer[1] += inb(port+Timer) & 0xFF;
-
-	COMMAND(port, SelectRegisterWindow, w);
-	iunlock(&ctlr->wlock);
-}
-
-static void
-txrxreset(int port)
-{
-	COMMAND(port, TxReset, 0);
-	while(STATUS(port) & commandInProgress)
-		;
-	COMMAND(port, RxReset, 0);
-	while(STATUS(port) & commandInProgress)
-		;
-}
-
-typedef struct Adapter {
-	int		port;
-	int		irq;
-	int		tbdf;
-	ulong	cbfns;
-} Adapter;
-static Block* adapter;
-
-static void
-tcmadapter(int port, int irq, int tbdf, ulong cbfns)
-{
-	Block *bp;
-	Adapter *ap;
-
-	bp = allocb(sizeof(Adapter));
-	ap = (Adapter*)bp->rp;
-	ap->port = port;
-	ap->irq = irq;
-	ap->tbdf = tbdf;
-	ap->cbfns = cbfns;
-
-	bp->next = adapter;
-	adapter = bp;
-}
-
-/*
- * Write two 0 bytes to identify the IDport and then reset the
- * ID sequence. Then send the ID sequence to the card to get
- * the card into command state.
- */
-static void
-idseq(void)
-{
-	int i;
-	uchar al;
-	static int reset, untag;
-
-	/*
-	 * One time only:
-	 *	reset any adapters listening
-	 */
-	if(reset == 0){
-		outb(IDport, 0);
-		outb(IDport, 0);
-		outb(IDport, 0xC0);
-		delay(20);
-		reset = 1;
-	}
-
-	outb(IDport, 0);
-	outb(IDport, 0);
-	for(al = 0xFF, i = 0; i < 255; i++){
-		outb(IDport, al);
-		if(al & 0x80){
-			al <<= 1;
-			al ^= 0xCF;
-		}
-		else
-			al <<= 1;
-	}
-
-	/*
-	 * One time only:
-	 *	write ID sequence to get the attention of all adapters;
-	 *	untag all adapters.
-	 * If a global reset is done here on all adapters it will confuse
-	 * any ISA cards configured for EISA mode.
-	 */
-	if(untag == 0){
-		outb(IDport, 0xD0);
-		untag = 1;
-	}
-}
-
-static ulong
-activate(void)
-{
-	int i;
-	ushort x, acr;
-
-	/*
-	 * Do the little configuration dance:
-	 *
-	 * 2. write the ID sequence to get to command state.
-	 */
-	idseq();
-
-	/*
-	 * 3. Read the Manufacturer ID from the EEPROM.
-	 *    This is done by writing the IDPort with 0x87 (0x80
-	 *    is the 'read EEPROM' command, 0x07 is the offset of
-	 *    the Manufacturer ID field in the EEPROM).
-	 *    The data comes back 1 bit at a time.
-	 *    A delay seems necessary between reading the bits.
-	 *
-	 * If the ID doesn't match, there are no more adapters.
-	 */
-	outb(IDport, 0x87);
-	delay(20);
-	for(x = 0, i = 0; i < 16; i++){
-		delay(20);
-		x <<= 1;
-		x |= inb(IDport) & 0x01;
-	}
-	if(x != 0x6D50)
-		return 0;
-
-	/*
-	 * 3. Read the Address Configuration from the EEPROM.
-	 *    The Address Configuration field is at offset 0x08 in the EEPROM).
-	 */
-	outb(IDport, 0x88);
-	for(acr = 0, i = 0; i < 16; i++){
-		delay(20);
-		acr <<= 1;
-		acr |= inb(IDport) & 0x01;
-	}
-
-	return (acr & 0x1F)*0x10 + 0x200;
-}
-
-static void
-tcm509isa(void)
-{
-	int irq, port;
-
-	/*
-	 * Attempt to activate all adapters. If adapter is set for
-	 * EISA mode (0x3F0), tag it and ignore. Otherwise, activate
-	 * it fully.
-	 */
-	while(port = activate()){
-		/*
-		 * 6. Tag the adapter so it won't respond in future.
-		 */
-		outb(IDport, 0xD1);
-		if(port == 0x3F0)
-			continue;
-
-		/*
-		 * 6. Activate the adapter by writing the Activate command
-		 *    (0xFF).
-		 */
-		outb(IDport, 0xFF);
-		delay(20);
-
-		/*
-		 * 8. Can now talk to the adapter's I/O base addresses.
-		 *    Use the I/O base address from the acr just read.
-		 *
-		 *    Enable the adapter and clear out any lingering status
-		 *    and interrupts.
-		 */
-		while(STATUS(port) & commandInProgress)
-			;
-		COMMAND(port, SelectRegisterWindow, Wsetup);
-		outs(port+ConfigControl, Ena);
-
-		txrxreset(port);
-		COMMAND(port, AcknowledgeInterrupt, 0xFF);
-
-		irq = (ins(port+ResourceConfig)>>12) & 0x0F;
-		tcmadapter(port, irq, BUSUNKNOWN, 0);
-	}
-}
-
-static void
-tcm5XXeisa(void)
-{
-	ushort x;
-	int irq, port, slot;
-
-	/*
-	 * Check if this is an EISA machine.
-	 * If not, nothing to do.
-	 */
-	if(strncmp((char*)KADDR(0xFFFD9), "EISA", 4))
-		return;
-
-	/*
-	 * Continue through the EISA slots looking for a match on both
-	 * 3COM as the manufacturer and 3C579-* or 3C59[27]-* as the product.
-	 * If an adapter is found, select window 0, enable it and clear
-	 * out any lingering status and interrupts.
-	 */
-	for(slot = 1; slot < MaxEISA; slot++){
-		port = slot*0x1000;
-		if(ins(port+0xC80+ManufacturerID) != 0x6D50)
-			continue;
-		x = ins(port+0xC80+ProductID);
-		if((x & 0xF0FF) != 0x9050 && (x & 0xFF00) != 0x5900)
-			continue;
-
-		COMMAND(port, SelectRegisterWindow, Wsetup);
-		outs(port+ConfigControl, Ena);
-
-		txrxreset(port);
-		COMMAND(port, AcknowledgeInterrupt, 0xFF);
-
-		irq = (ins(port+ResourceConfig)>>12) & 0x0F;
-		tcmadapter(port, irq, BUSUNKNOWN, 0);
-	}
-}
-
-static void
-tcm59Xpci(Ether *ether)
-{
-	Pcidev *p;
-	int irq, port;
-	ulong bar;
-
-	p = nil;
-	while(p = pcimatch(p, 0x10B7, 0)){
-		if (p->did == 0x5157) {
-			EepromReadRegister = _EepromRead8bRegister;
-			
-			/* Map the CardBus functions */
-			bar = pcicfgr32(p, PciBAR2);
-			print("ether#%d: CardBus functions at %.8luX\n", ether->ctlrno, bar & ~KZERO);
-		}
-		else
-			bar = 0;
-
-		/*
-		 * Not prepared to deal with memory-mapped
-		 * devices yet.
-		 */
-		if(!(p->mem[0].bar & 0x01))
-			continue;
-		port = p->mem[0].bar & ~0x01;
-		irq = p->intl;
-		COMMAND(port, GlobalReset, 0);
-		while(STATUS(port) & commandInProgress)
-			;
-
-		tcmadapter(port, irq, p->tbdf, bar);
-		pcisetbme(p);
-	}
-}
-
-static char* tcmpcmcia[] = {
-	"3C589",			/* 3COM 589[ABCD] */
-	"3C562",			/* 3COM 562 */
-	"589E",				/* 3COM Megahertz 589E */
-	nil,
-};
-
-static int
-tcm5XXpcmcia(Ether* ether)
-{
-	int i;
-
-	for(i = 0; tcmpcmcia[i] != nil; i++){
-		if(!cistrcmp(ether->type, tcmpcmcia[i])){
-			/*
-			 * No need for an ioalloc here, the 589 reset
-			 * code deals with it.
-			if(ioalloc(ether->port, 0x10, 0, "tcm5XXpcmcia") < 0)
-				return 0;
-			 */
-			return ether->port;
-		}
-	}
-
-	return 0;
-}
-
-static void
-setxcvr(int port, int xcvr, int is9)
-{
-	int x;
-
-	if(is9){
-		COMMAND(port, SelectRegisterWindow, Wsetup);
-		x = ins(port+AddressConfig) & ~xcvrMask9;
-		x |= (xcvr>>20)<<14;
-		outs(port+AddressConfig, x);
-	}
-	else{
-		COMMAND(port, SelectRegisterWindow, Wfifo);
-		x = inl(port+InternalConfig) & ~xcvrMask;
-		x |= xcvr;
-		outl(port+InternalConfig, x);
-	}
-
-	txrxreset(port);
-}
-
-static void
-setfullduplex(int port)
-{
-	int x;
-
-	COMMAND(port, SelectRegisterWindow, Wfifo);
-	x = ins(port+MacControl);
-	outs(port+MacControl, fullDuplexEnable|x);
-
-	txrxreset(port);
-}
-
-static int
-miimdi(int port, int n)
-{
-	int data, i;
-
-	/*
-	 * Read n bits from the MII Management Register.
-	 */
-	data = 0;
-	for(i = n-1; i >= 0; i--){
-		if(ins(port) & mgmtData)
-			data |= (1<<i);
-		microdelay(1);
-		outs(port, mgmtClk);
-		microdelay(1);
-		outs(port, 0);
-		microdelay(1);
-	}
-
-	return data;
-}
-
-static void
-miimdo(int port, int bits, int n)
-{
-	int i, mdo;
-
-	/*
-	 * Write n bits to the MII Management Register.
-	 */
-	for(i = n-1; i >= 0; i--){
-		if(bits & (1<<i))
-			mdo = mgmtDir|mgmtData;
-		else
-			mdo = mgmtDir;
-		outs(port, mdo);
-		microdelay(1);
-		outs(port, mdo|mgmtClk);
-		microdelay(1);
-		outs(port, mdo);
-		microdelay(1);
-	}
-}
-
-static int
-miir(int port, int phyad, int regad)
-{
-	int data, w;
-
-	w = (STATUS(port)>>13) & 0x07;
-	COMMAND(port, SelectRegisterWindow, Wdiagnostic);
-	port += PhysicalMgmt;
-
-	/*
-	 * Preamble;
-	 * ST+OP+PHYAD+REGAD;
-	 * TA + 16 data bits.
-	 */
-	miimdo(port, 0xFFFFFFFF, 32);
-	miimdo(port, 0x1800|(phyad<<5)|regad, 14);
-	data = miimdi(port, 18);
-
-	port -= PhysicalMgmt;
-	COMMAND(port, SelectRegisterWindow, w);
-
-	if(data & 0x10000)
-		return -1;
-
-	return data & 0xFFFF;
-}
-
-static void
-scanphy(int port)
-{
-	int i, x;
-
-	for(i = 0; i < 32; i++){
-		if((x = miir(port, i, 2)) == -1 || x == 0)
-			continue;
-		x <<= 6;
-		x |= miir(port, i, 3)>>10;
-		XCVRDEBUG("phy%d: oui %uX reg1 %uX\n", i, x, miir(port, i, 1));
-		USED(x);
-	}
-}
-
-#ifdef notdef
-static struct xxx {
-	int	available;
-	int	next;
-} xxx[8] = {
-	{ base10TAvailable,	1, },		/* xcvr10BaseT	-> xcvrAui */
-	{ auiAvailable,		3, },		/* xcvrAui	-> xcvr10Base2 */
-	{ 0, -1, },
-	{ coaxAvailable,	-1, },		/* xcvr10Base2	-> nowhere */
-	{ baseTXAvailable,	5, },		/* xcvr100BaseTX-> xcvr100BaseFX */
-	{ baseFXAvailable,	-1, },		/* xcvr100BaseFX-> nowhere */
-	{ miiConnector,		-1, },		/* xcvrMii	-> nowhere */
-	{ 0, -1, },
-};
-#endif /* notdef */
-
-static struct {
-	char *name;
-	int avail;
-	int xcvr;
-} media[] = {
-	"10BaseT",	base10TAvailable,	xcvr10BaseT,
-	"10Base2",	coaxAvailable,		xcvr10Base2,
-	"100BaseTX",	baseTXAvailable,	xcvr100BaseTX,
-	"100BaseFX",	baseFXAvailable,	xcvr100BaseFX,
-	"aui",		auiAvailable,		xcvrAui,
-	"mii",		miiConnector,		xcvrMii
-};
-
-static int
-autoselect(int port, int xcvr, int is9)
-{
-	int media, x;
-	USED(xcvr);
-
-	/*
-	 * Pathetic attempt at automatic media selection.
-	 * Really just to get the Fast Etherlink 10BASE-T/100BASE-TX
-	 * cards operational.
-	 * It's a bonus if it works for anything else.
-	 */
-	if(is9){
-		COMMAND(port, SelectRegisterWindow, Wsetup);
-		x = ins(port+ConfigControl);
-		media = 0;
-		if(x & base10TAvailable9)
-			media |= base10TAvailable;
-		if(x & coaxAvailable9)
-			media |= coaxAvailable;
-		if(x & auiAvailable9)
-			media |= auiAvailable;
-	}
-	else{
-		COMMAND(port, SelectRegisterWindow, Wfifo);
-		media = ins(port+ResetOptions);
-	}
-	XCVRDEBUG("autoselect: media %uX\n", media);
-
-	if(media & miiConnector)
-		return xcvrMii;
-
-	COMMAND(port, SelectRegisterWindow, Wdiagnostic);
-	XCVRDEBUG("autoselect: media status %uX\n", ins(port+MediaStatus));
-
-	if(media & baseTXAvailable){
-		/*
-		 * Must have InternalConfig register.
-		 */
-		setxcvr(port, xcvr100BaseTX, is9);
-
-		COMMAND(port, SelectRegisterWindow, Wdiagnostic);
-		x = ins(port+MediaStatus) & ~(dcConverterEnabled|jabberGuardEnable);
-		outs(port+MediaStatus, linkBeatEnable|x);
-		delay(10);
-
-		if(ins(port+MediaStatus) & linkBeatDetect)
-			return xcvr100BaseTX;
-		outs(port+MediaStatus, x);
-	}
-
-	if(media & base10TAvailable){
-		setxcvr(port, xcvr10BaseT, is9);
-
-		COMMAND(port, SelectRegisterWindow, Wdiagnostic);
-		x = ins(port+MediaStatus) & ~dcConverterEnabled;
-		outs(port+MediaStatus, linkBeatEnable|jabberGuardEnable|x);
-		delay(100);
-
-		XCVRDEBUG("autoselect: 10BaseT media status %uX\n", ins(port+MediaStatus));
-		if(ins(port+MediaStatus) & linkBeatDetect)
-			return xcvr10BaseT;
-		outs(port+MediaStatus, x);
-	}
-
-	/*
-	 * Botch.
-	 */
-	return autoSelect;
-}
-
-static int
-eepromdata(int port, int offset)
-{
-	COMMAND(port, SelectRegisterWindow, Wsetup);
-	while(EEPROMBUSY(port))
-		;
-	EEPROMCMD(port, EepromReadRegister, offset);
-	while(EEPROMBUSY(port))
-		;
-	return EEPROMDATA(port);
-}
-
-int
-elnk3reset(Ether* ether)
-{
-	int anar, anlpar, phyaddr, phystat, timeo, xcvr;
-	int busmaster, did, i, j, port, rxearly, rxstatus9, x;
-	Block *bp, **bpp;
-	Adapter *ap;
-	uchar ea[Eaddrlen];
-	Ctlr *ctlr;
-	static int scandone;
-	char *p;
-
-	/*
-	 * Scan for adapter on PCI, EISA and finally
-	 * using the little ISA configuration dance.
-	 */
-	if(scandone == 0){
-		tcm59Xpci(ether);
-		tcm5XXeisa();
-		tcm509isa();
-		scandone = 1;
-	}
-
-	/*
-	 * Any adapter matches if no ether->port is supplied,
-	 * otherwise the ports must match.
-	 */
-	port = 0;
-	bpp = &adapter;
-	for(bp = *bpp; bp; bp = bp->next){
-		ap = (Adapter*)bp->rp;
-		if(ether->port == 0 || ether->port == ap->port){
-			port = ap->port;
-			ether->irq = ap->irq;
-			ether->tbdf = ap->tbdf;
-			ether->mem = ap->cbfns;	/* Misuse the mem ref for the cardbus functions */
-			*bpp = bp->next;
-			freeb(bp);
-			break;
-		}
-		bpp = &bp->next;
-	}
-	if(port == 0 && (port = tcm5XXpcmcia(ether)) == 0)
-		return -1;
-
-	/*
-	 * Read the DeviceID from the EEPROM, it's at offset 0x03,
-	 * and do something depending on capabilities.
-	 */
-	switch(did = eepromdata(port, 0x03)){
-
-	case 0x5157:		/* 3C575 Cyclone */
-	case 0x4500:		/* 3C450 HomePNA Tornado */
-	case 0x6056:
-	case 0x7646:		/* 3CSOHO100-TX */
-	case 0x9055:		/* 3C905B-TX */
-	case 0x9200:		/* 3C905C-TX */
-		/*FALLTHROUGH*/
-	case 0x9000:		/* 3C900-TPO */
-	case 0x9001:		/* 3C900-COMBO */
-	case 0x9005:		/* 3C900B-COMBO */
-	case 0x9050:		/* 3C905-TX */
-	case 0x9051:		/* 3C905-T4 */
-		if(BUSTYPE(ether->tbdf) != BusPCI)
-			goto buggery;
-		busmaster = 2;
-		goto vortex;
-
-	case 0x5900:		/* 3C590-[TP|COMBO|TPO] */
-	case 0x5920:		/* 3C592-[TP|COMBO|TPO] */
-	case 0x5950:		/* 3C595-TX */
-	case 0x5951:		/* 3C595-T4 */
-	case 0x5952:		/* 3C595-MII */
-	case 0x5970:		/* 3C597-TX */
-	case 0x5971:		/* 3C597-T4 */
-	case 0x5972:		/* 3C597-MII */
-		busmaster = 1;
-	vortex:
-		COMMAND(port, SelectRegisterWindow, Wfifo);
-		xcvr = inl(port+InternalConfig) & (autoSelect|xcvrMask);
-		rxearly = 8188;
-		rxstatus9 = 0;
-		break;
-
-	buggery:
-	default:
-		busmaster = 0;
-		COMMAND(port, SelectRegisterWindow, Wsetup);
-		x = ins(port+AddressConfig);
-		xcvr = ((x & xcvrMask9)>>14)<<20;
-		if(x & autoSelect9)
-			xcvr |= autoSelect;
-		rxearly = 2044;
-		rxstatus9 = 1;
-		break;
-	}
-
-	/*
-	 * Check if the adapter's station address is to be overridden.
-	 * If not, read it from the EEPROM and set in ether->ea prior to
-	 * loading the station address in Wstation.
-	 * The EEPROM returns 16-bits at a time.
-	 */
-	memset(ea, 0, Eaddrlen);
-	if(memcmp(ea, ether->ea, Eaddrlen) == 0){
-		for(i = 0; i < Eaddrlen/2; i++){
-			x = eepromdata(port, i);
-			ether->ea[2*i] = x>>8;
-			ether->ea[2*i+1] = x;
-		}
-	}
-
-	COMMAND(port, SelectRegisterWindow, Wstation);
-	for(i = 0; i < Eaddrlen; i++)
-		outb(port+i, ether->ea[i]);
-
-	/*
-	 * Enable the transceiver if necessary and determine whether
-	 * busmastering can be used. Due to bugs in the first revision
-	 * of the 3C59[05], don't use busmastering at 10Mbps.
-	 */
-	XCVRDEBUG("reset: xcvr %uX\n", xcvr);
-
-	/*
-	 * Allow user to specify desired media in plan9.ini
-	 */
-	for(i = 0; i < ether->nopt; i++){
-		if(cistrncmp(ether->opt[i], "media=", 6) != 0)
-			continue;
-		p = ether->opt[i]+6;
-		for(j = 0; j < nelem(media); j++)
-			if(cistrcmp(p, media[j].name) == 0)
-				xcvr = media[j].xcvr;
-	}
-	
-	/*
-	 * forgive me, but i am weak
-	 */
-	switch(did){
-	default:
-		if(xcvr & autoSelect)
-			xcvr = autoselect(port, xcvr, rxstatus9);
-		break;
-	case 0x4500:
-	case 0x5157:
-	case 0x6056:
-	case 0x7646:
-	case 0x9055:
-	case 0x9200:
-		xcvr = xcvrMii;
-		txrxreset(port);
-		XCVRDEBUG("905[BC] reset ops 0x%uX\n", ins(port+ResetOp905B));
-
-		if (did == 0x5157) {
-			ushort reset_opts;
-
-			COMMAND(port, SelectRegisterWindow, Wstation);
-			reset_opts = ins(port + ResetOp905B);
-			reset_opts |= 0x0010;		/* Invert LED */
-			outs(port + ResetOp905B, reset_opts);
-		}
-		break;
-	}
-	XCVRDEBUG("autoselect returns: xcvr %uX, did 0x%uX\n", xcvr, did);
-
-	switch(xcvr){
-
-	case xcvrMii:
-		/*
-		 * Quick hack.
-		scanphy(port);
-		 */
-		phyaddr = (did == 0x5157)? 0: 24;
-		for(i = 0; i < 7; i++)
-			XCVRDEBUG(" %2.2uX", miir(port, phyaddr, i));
-			XCVRDEBUG("\n");
-
-		for(timeo = 0; timeo < 30; timeo++){
-			phystat = miir(port, phyaddr, 0x01);
-			if(phystat & 0x20)
-				break;
-			XCVRDEBUG(" %2.2uX", phystat);
-			delay(100);
-		}
-		XCVRDEBUG(" %2.2uX", miir(port, phyaddr, 0x01));
-		XCVRDEBUG("\n");
-
-		anar = miir(port, phyaddr, 0x04);
-		anlpar = miir(port, phyaddr, 0x05) & 0x03E0;
-		anar &= anlpar;
-		miir(port, phyaddr, 0x00);
-		XCVRDEBUG("mii an: %uX anlp: %uX r0:%uX r1:%uX\n",
-			anar, anlpar, miir(port, phyaddr, 0x00),
-			miir(port, phyaddr, 0x01));
-		for(i = 0; i < ether->nopt; i++){
-			if(cistrcmp(ether->opt[i], "fullduplex") == 0)
-				anar |= 0x0100;
-			else if(cistrcmp(ether->opt[i], "100BASE-TXFD") == 0)
-				anar |= 0x0100;
-			else if(cistrcmp(ether->opt[i], "force100") == 0)
-				anar |= 0x0080;
-		}
-		XCVRDEBUG("mii anar: %uX\n", anar);
-		if(anar & 0x0100){		/* 100BASE-TXFD */
-			setfullduplex(port);
-		}
-		else if(anar & 0x0200){		/* 100BASE-T4 */
-			/* nothing to do */
-		}
-		else if(anar & 0x0080){		/* 100BASE-TX */
-			/* nothing to do */;
-		}
-		else if(anar & 0x0040)		/* 10BASE-TFD */
-			setfullduplex(port);
-		else{				/* 10BASE-T */
-			/* nothing to do */;
-		}
-		break;
-
-	case xcvr100BaseTX:
-	case xcvr100BaseFX:
-		COMMAND(port, SelectRegisterWindow, Wfifo);
-		x = inl(port+InternalConfig) & ~ramPartitionMask;
-		outl(port+InternalConfig, x|ramPartition1to1);
-
-		COMMAND(port, SelectRegisterWindow, Wdiagnostic);
-		x = ins(port+MediaStatus) & ~(dcConverterEnabled|jabberGuardEnable);
-		x |= linkBeatEnable;
-		outs(port+MediaStatus, x);
-		break;
-
-	case xcvr10BaseT:
-		/*
-		 * Enable Link Beat and Jabber to start the
-		 * transceiver.
-		 */
-		COMMAND(port, SelectRegisterWindow, Wdiagnostic);
-		x = ins(port+MediaStatus) & ~dcConverterEnabled;
-		x |= linkBeatEnable|jabberGuardEnable;
-		outs(port+MediaStatus, x);
-
-		if((did & 0xFF00) == 0x5900)
-			busmaster = 0;
-		break;
-
-	case xcvr10Base2:
-		COMMAND(port, SelectRegisterWindow, Wdiagnostic);
-		x = ins(port+MediaStatus) & ~(linkBeatEnable|jabberGuardEnable);
-		outs(port+MediaStatus, x);
-
-		/*
-		 * Start the DC-DC converter.
-		 * Wait > 800 microseconds.
-		 */
-		COMMAND(port, EnableDcConverter, 0);
-		delay(1);
-		break;
-	}
-
-	/*
-	 * Wop is the normal operating register set.
-	 * The 3C59[0257] adapters allow access to more than one register window
-	 * at a time, but there are situations where switching still needs to be
-	 * done, so just do it.
-	 * Clear out any lingering Tx status.
-	 */
-	COMMAND(port, SelectRegisterWindow, Wop);
-	if(busmaster == 2)
-		x = port+TxStatus905;
-	else
-		x = port+TxStatus;
-	while(inb(x))
-		outb(x, 0);
-
-	/*
-	 * Allocate a controller structure, clear out the
-	 * adapter statistics, clear the statistics logged into ctlr
-	 * and enable statistics collection. Xcvr is needed in order
-	 * to collect the BadSSD statistics.
-	 */
-	ether->ctlr = malloc(sizeof(Ctlr));
-	ctlr = ether->ctlr;
-
-	ilock(&ctlr->wlock);
-	ctlr->xcvr = xcvr;
-	statistics(ether);
-	memset(ctlr->stats, 0, sizeof(ctlr->stats));
-
-	ctlr->busmaster = busmaster;
-	ctlr->xcvr = xcvr;
-	ctlr->rxstatus9 = rxstatus9;
-	ctlr->rxearly = rxearly;
-	if(rxearly >= 2048)
-		ctlr->ts = 2;
-
-	COMMAND(port, StatisticsEnable, 0);
-
-	/*
-	 * Allocate any receive buffers.
-	 */
-	if (ctlr->busmaster == 2) {
-		ctlr->dnenabled = 1;
-
-		/*
-		 * 10MUpldBug.
-		 * Disabling is too severe, can use receive busmastering at
-		 * 100Mbps OK, but how to tell which rate is actually being used -
-		 * the 3c905 always seems to have dataRate100 set?
-		 * Believe the bug doesn't apply if upRxEarlyEnable is set
-		 * and the threshold is set such that uploads won't start
-		 * until the whole packet has been received.
-		 */
-		ctlr->upenabled = 1;
-		x = eepromdata(port, 0x0F);
-		if(!(x & 0x01))
-			outl(port+PktStatus, upRxEarlyEnable);
-
-		ctlr->nup = Nup;
-		ctlr->ndn = Ndn;
-		init905(ctlr);
-		outl(port+TxFreeThresh, HOWMANY(ETHERMAXTU, 256));
-	}
-
-	/*
-	 * Set a base TxStartThresh which will be incremented
-	 * if any txUnderrun errors occur and ensure no RxEarly
-	 * interrupts happen.
-	 */
-	ctlr->txthreshold = ETHERMAXTU/2;
-	COMMAND(port, SetTxStartThresh, ctlr->txthreshold>>ctlr->ts);
-	COMMAND(port, SetRxEarlyThresh, rxearly>>ctlr->ts);
-
-	iunlock(&ctlr->wlock);
-
-	/*
-	 * Linkage to the generic ethernet driver.
-	 */
-	ether->port = port;
-	ether->attach = attach;
-	ether->transmit = transmit;
-	ether->interrupt = interrupt;
-
-	return 0;
-}
--- a/os/boot/pc/etherelnk3x.c
+++ /dev/null
@@ -1,1074 +1,0 @@
-/*
- * Etherlink III and Fast EtherLink adapters.
- * To do:
- *	autoSelect;
- *	busmaster channel;
- *	PCMCIA;
- *	PCI latency timer and master enable;
- *	errata list.
- *
- * Product ID:
- *	9150 ISA	3C509[B]
- *	9050 ISA	3C509[B]-TP
- *	9450 ISA	3C509[B]-COMBO
- *	9550 ISA	3C509[B]-TPO
- *
- *	9350 EISA	3C579
- *	9250 EISA	3C579-TP
- *
- *	5920 EISA	3C592-[TP|COMBO|TPO]
- *	5970 EISA	3C597-TX	Fast Etherlink 10BASE-T/100BASE-TX
- *	5971 EISA	3C597-T4	Fast Etherlink 10BASE-T/100BASE-T4
- *	5972 EISA	3C597-MII	Fast Etherlink 10BASE-T/MII
- *
- *	5900 PCI	3C590-[TP|COMBO|TPO]
- *	5950 PCI	3C595-TX	Fast Etherlink Shared 10BASE-T/100BASE-TX
- *	5951 PCI	3C595-T4	Fast Etherlink Shared 10BASE-T/100BASE-T4
- *	5952 PCI	3C595-MII	Fast Etherlink 10BASE-T/MII
- *
- *	9058 PCMCIA	3C589[B]-[TP|COMBO]
- *
- *	627C MCA	3C529
- *	627D MCA	3C529-TP
- */
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-#include "etherif.h"
-
-enum {
-	IDport			= 0x0110,	/* anywhere between 0x0100 and 0x01F0 */
-};
-
-enum {						/* all windows */
-	Command			= 0x000E,
-	IntStatus		= 0x000E,
-};
-
-enum {						/* Commands */
-	GlobalReset		= 0x0000,
-	SelectRegisterWindow	= 0x0001,	
-	EnableDcConverter	= 0x0002,
-	RxDisable		= 0x0003,
-	RxEnable		= 0x0004,
-	RxReset			= 0x0005,
-	TxDone			= 0x0007,	
-	RxDiscard		= 0x0008,
-	TxEnable		= 0x0009,
-	TxDisable		= 0x000A,
-	TxReset			= 0x000B,
-	RequestInterrupt	= 0x000C,
-	AcknowledgeInterrupt	= 0x000D,
-	SetInterruptEnable	= 0x000E,
-	SetIndicationEnable	= 0x000F,	/* SetReadZeroMask */
-	SetRxFilter		= 0x0010,
-	SetRxEarlyThresh	= 0x0011,
-	SetTxAvailableThresh	= 0x0012,
-	SetTxStartThresh	= 0x0013,
-	StartDma		= 0x0014,	/* initiate busmaster operation */
-	StatisticsEnable	= 0x0015,
-	StatisticsDisable	= 0x0016,
-	DisableDcConverter	= 0x0017,
-	SetTxReclaimThresh	= 0x0018,	/* PIO-only adapters */
-	PowerUp			= 0x001B,	/* not all adapters */
-	PowerDownFull		= 0x001C,	/* not all adapters */
-	PowerAuto		= 0x001D,	/* not all adapters */
-};
-
-enum {						/* (Global|Rx|Tx)Reset command bits */
-	tpAuiReset		= 0x0001,	/* 10BaseT and AUI transceivers */
-	endecReset		= 0x0002,	/* internal Ethernet encoder/decoder */
-	networkReset		= 0x0004,	/* network interface logic */
-	fifoReset		= 0x0008,	/* FIFO control logic */
-	aismReset		= 0x0010,	/* autoinitialise state-machine logic */
-	hostReset		= 0x0020,	/* bus interface logic */
-	dmaReset		= 0x0040,	/* bus master logic */
-	vcoReset		= 0x0080,	/* on-board 10Mbps VCO */
-
-	resetMask		= 0x00FF,
-};
-
-enum {						/* SetRxFilter command bits */
-	receiveIndividual	= 0x0001,	/* match station address */
-	receiveMulticast	= 0x0002,
-	receiveBroadcast	= 0x0004,
-	receiveAllFrames	= 0x0008,	/* promiscuous */
-};
-
-enum {						/* StartDma command bits */
-	Upload			= 0x0000,	/* transfer data from adapter to memory */
-	Download		= 0x0001,	/* transfer data from memory to adapter */
-};
-
-enum {						/* IntStatus bits */
-	interruptLatch		= 0x0001,
-	hostError		= 0x0002,	/* Adapter Failure */
-	txComplete		= 0x0004,
-	txAvailable		= 0x0008,
-	rxComplete		= 0x0010,
-	rxEarly			= 0x0020,
-	intRequested		= 0x0040,
-	updateStats		= 0x0080,
-	transferInt		= 0x0100,	/* Bus Master Transfer Complete */
-	busMasterInProgress	= 0x0800,
-	commandInProgress	= 0x1000,
-
-	interruptMask		= 0x01FE,
-};
-
-#define COMMAND(port, cmd, a)	outs((port)+Command, ((cmd)<<11)|(a))
-#define STATUS(port)		ins((port)+IntStatus)
-
-enum {						/* Window 0 - setup */
-	Wsetup			= 0x0000,
-						/* registers */
-	ManufacturerID		= 0x0000,	/* 3C5[08]*, 3C59[27] */
-	ProductID		= 0x0002,	/* 3C5[08]*, 3C59[27] */
-	ConfigControl		= 0x0004,	/* 3C5[08]*, 3C59[27] */
-	AddressConfig		= 0x0006,	/* 3C5[08]*, 3C59[27] */
-	ResourceConfig		= 0x0008,	/* 3C5[08]*, 3C59[27] */
-	EepromCommand		= 0x000A,
-	EepromData		= 0x000C,
-						/* AddressConfig Bits */
-	autoSelect9		= 0x0080,
-	xcvrMask9		= 0xC000,
-						/* ConfigControl bits */
-	Ena			= 0x0001,
-						/* EepromCommand bits */
-	EepromReadRegister	= 0x0080,
-	EepromBusy		= 0x8000,
-};
-
-#define EEPROMCMD(port, cmd, a)	outs((port)+EepromCommand, (cmd)|(a))
-#define EEPROMBUSY(port)	(ins((port)+EepromCommand) & EepromBusy)
-#define EEPROMDATA(port)	ins((port)+EepromData)
-
-enum {						/* Window 1 - operating set */
-	Wop			= 0x0001,
-						/* registers */
-	Fifo			= 0x0000,
-	RxError			= 0x0004,	/* 3C59[0257] only */
-	RxStatus		= 0x0008,
-	Timer			= 0x000A,
-	TxStatus		= 0x000B,
-	TxFree			= 0x000C,
-						/* RxError bits */
-	rxOverrun		= 0x0001,
-	runtFrame		= 0x0002,
-	alignmentError		= 0x0004,	/* Framing */
-	crcError		= 0x0008,
-	oversizedFrame		= 0x0010,
-	dribbleBits		= 0x0080,
-						/* RxStatus bits */
-	rxBytes			= 0x1FFF,	/* 3C59[0257] mask */
-	rxBytes9		= 0x07FF,	/* 3C5[078]9 mask */
-	rxError9		= 0x3800,	/* 3C5[078]9 error mask */
-	rxOverrun9		= 0x0000,
-	oversizedFrame9		= 0x0800,
-	dribbleBits9		= 0x1000,
-	runtFrame9		= 0x1800,
-	alignmentError9		= 0x2000,	/* Framing */
-	crcError9		= 0x2800,
-	rxError			= 0x4000,
-	rxIncomplete		= 0x8000,
-						/* TxStatus Bits */
-	txStatusOverflow	= 0x0004,
-	maxCollisions		= 0x0008,
-	txUnderrun		= 0x0010,
-	txJabber		= 0x0020,
-	interruptRequested	= 0x0040,
-	txStatusComplete	= 0x0080,
-};
-
-enum {						/* Window 2 - station address */
-	Wstation		= 0x0002,
-};
-
-enum {						/* Window 3 - FIFO management */
-	Wfifo			= 0x0003,
-						/* registers */
-	InternalConfig		= 0x0000,	/* 3C509B, 3C589, 3C59[0257] */
-	OtherInt		= 0x0004,	/* 3C59[0257] */
-	RomControl		= 0x0006,	/* 3C509B, 3C59[27] */
-	MacControl		= 0x0006,	/* 3C59[0257] */
-	ResetOptions		= 0x0008,	/* 3C59[0257] */
-	RxFree			= 0x000A,
-						/* InternalConfig bits */
-	disableBadSsdDetect	= 0x00000100,
-	ramLocation		= 0x00000200,	/* 0 external, 1 internal */
-	ramPartition5to3	= 0x00000000,
-	ramPartition3to1	= 0x00010000,
-	ramPartition1to1	= 0x00020000,
-	ramPartition3to5	= 0x00030000,
-	ramPartitionMask	= 0x00030000,
-	xcvr10BaseT		= 0x00000000,
-	xcvrAui			= 0x00100000,	/* 10BASE5 */
-	xcvr10Base2		= 0x00300000,
-	xcvr100BaseTX		= 0x00400000,
-	xcvr100BaseFX		= 0x00500000,
-	xcvrMii			= 0x00600000,
-	xcvrMask		= 0x00700000,
-	autoSelect		= 0x01000000,
-						/* MacControl bits */
-	deferExtendEnable	= 0x0001,
-	deferTimerSelect	= 0x001E,	/* mask */
-	fullDuplexEnable	= 0x0020,
-	allowLargePackets	= 0x0040,
-						/* ResetOptions bits */
-	baseT4Available		= 0x0001,
-	baseTXAvailable		= 0x0002,
-	baseFXAvailable		= 0x0004,
-	base10TAvailable	= 0x0008,
-	coaxAvailable		= 0x0010,
-	auiAvailable		= 0x0020,
-	miiConnector		= 0x0040,
-};
-
-enum {						/* Window 4 - diagnostic */
-	Wdiagnostic		= 0x0004,
-						/* registers */
-	VcoDiagnostic		= 0x0002,
-	FifoDiagnostic		= 0x0004,
-	NetworkDiagnostic	= 0x0006,
-	PhysicalMgmt		= 0x0008,
-	MediaStatus		= 0x000A,
-	BadSSD			= 0x000C,
-						/* FifoDiagnostic bits */
-	txOverrun		= 0x0400,
-	rxUnderrun		= 0x2000,
-	receiving		= 0x8000,
-						/* MediaStatus bits */
-	dataRate100		= 0x0002,
-	crcStripDisable		= 0x0004,
-	enableSqeStats		= 0x0008,
-	collisionDetect		= 0x0010,
-	carrierSense		= 0x0020,
-	jabberGuardEnable	= 0x0040,
-	linkBeatEnable		= 0x0080,
-	jabberDetect		= 0x0200,
-	polarityReversed	= 0x0400,
-	linkBeatDetect		= 0x0800,
-	txInProg		= 0x1000,
-	dcConverterEnabled	= 0x4000,
-	auiDisable		= 0x8000,
-};
-
-enum {						/* Window 5 - internal state */
-	Wstate			= 0x0005,
-						/* registers */
-	TxStartThresh		= 0x0000,
-	TxAvalableThresh	= 0x0002,
-	RxEarlyThresh		= 0x0006,
-	RxFilter		= 0x0008,
-	InterruptEnable		= 0x000A,
-	IndicationEnable	= 0x000C,
-};
-
-enum {						/* Window 6 - statistics */
-	Wstatistics		= 0x0006,
-						/* registers */
-	CarrierLost		= 0x0000,
-	SqeErrors		= 0x0001,
-	MultipleColls		= 0x0002,
-	SingleCollFrames	= 0x0003,
-	LateCollisions		= 0x0004,
-	RxOverruns		= 0x0005,
-	FramesXmittedOk		= 0x0006,
-	FramesRcvdOk		= 0x0007,
-	FramesDeferred		= 0x0008,
-	UpperFramesOk		= 0x0009,
-	BytesRcvdOk		= 0x000A,
-	BytesXmittedOk		= 0x000C,
-};
-
-enum {						/* Window 7 - bus master operations */
-	Wmaster			= 0x0007,
-						/* registers */
-	MasterAddress		= 0x0000,
-	MasterLen		= 0x0006,
-	MasterStatus		= 0x000C,
-						/* MasterStatus bits */
-	masterAbort		= 0x0001,
-	targetAbort		= 0x0002,
-	targetRetry		= 0x0004,
-	targetDisc		= 0x0008,
-	masterDownload		= 0x1000,
-	masterUpload		= 0x4000,
-	masterInProgress	= 0x8000,
-
-	masterMask		= 0xD00F,
-};	
-
-typedef struct {
-	int	txthreshold;
-} Ctlr;
-
-static void
-attach(Ether* ether)
-{
-	int port, x;
-
-	port = ether->port;
-
-	/*
-	 * Set the receiver packet filter for this and broadcast addresses,
-	 * set the interrupt masks for all interrupts, enable the receiver
-	 * and transmitter.
-	 */
-	x = receiveBroadcast|receiveIndividual;
-	COMMAND(port, SetRxFilter, x);
-
-	x = interruptMask|interruptLatch;
-	COMMAND(port, SetIndicationEnable, x);
-	COMMAND(port, SetInterruptEnable, x);
-
-	COMMAND(port, RxEnable, 0);
-	COMMAND(port, TxEnable, 0);
-}
-
-static void
-transmit(Ether* ether)
-{
-	int port, len;
-	RingBuf *tb;
-
-	/*
-	 * Attempt to top-up the transmit FIFO. If there's room simply
-	 * stuff in the packet length (unpadded to a dword boundary), the
-	 * packet data (padded) and remove the packet from the queue.
-	 * If there's no room post an interrupt for when there is.
-	 * This routine is called both from the top level and from interrupt
-	 * level.
-	 */
-	port = ether->port;
-	for(tb = &ether->tb[ether->ti]; tb->owner == Interface; tb = &ether->tb[ether->ti]){
-		len = ROUNDUP(tb->len, 4);
-		if(len+4 <= ins(port+TxFree)){
-			outl(port+Fifo, tb->len);
-			outsl(port+Fifo, tb->pkt, len/4);
-			tb->owner = Host;
-			ether->ti = NEXT(ether->ti, ether->ntb);
-		}
-		else{
-			COMMAND(port, SetTxAvailableThresh, len);
-			break;
-		}
-	}
-}
-
-static void
-receive(Ether* ether)
-{
-	int len, port, rxstatus;
-	RingBuf *rb;
-
-	port = ether->port;
-
-	while(((rxstatus = ins(port+RxStatus)) & rxIncomplete) == 0){
-		/*
-		 * If there was an error, throw it away and continue.
-		 * The 3C5[078]9 has the error info in the status register
-		 * and the 3C59[0257] implement a separate RxError register.
-		 */
-		if((rxstatus & rxError) == 0){
-			/*
-			 * Packet received. Read it into the next free
-			 * ring buffer, if any. Must read len bytes padded
-			 * to a doubleword, can be picked out 32-bits at
-			 * a time. The CRC is already stripped off.
-			 */
-			rb = &ether->rb[ether->ri];
-			if(rb->owner == Interface){
-				len = (rxstatus & rxBytes9);
-				rb->len = len;
-				insl(port+Fifo, rb->pkt, HOWMANY(len, 4));
-
-				rb->owner = Host;
-				ether->ri = NEXT(ether->ri, ether->nrb);
-			}
-		}
-
-		/*
-		 * All done, discard the packet.
-		 */
-		COMMAND(port, RxDiscard, 0);
-		while(STATUS(port) & commandInProgress)
-			;
-	}
-}
-
-static void
-statistics(Ether* ether)
-{
-	int i, port, w;
-
-	port = ether->port;
-	w = (STATUS(port)>>13) & 0x07;
-	COMMAND(port, SelectRegisterWindow, Wop);
-	COMMAND(port, SelectRegisterWindow, Wstatistics);
-
-	for(i = 0; i < 0x0A; i++)
-		inb(port+i);
-	ins(port+BytesRcvdOk);
-	ins(port+BytesXmittedOk);
-
-	COMMAND(port, SelectRegisterWindow, w);
-}
-
-static void
-interrupt(Ureg*, void* arg)
-{
-	Ether *ether;
-	int port, status, txstatus, w, x;
-	Ctlr *ctlr;
-
-	ether = arg;
-	port = ether->port;
-	ctlr = ether->ctlr;
-
-	w = (STATUS(port)>>13) & 0x07;
-	COMMAND(port, SelectRegisterWindow, Wop);
-
-	for(;;){
-		/*
-		 * Clear the interrupt latch.
-		 * It's possible to receive a packet and for another
-		 * to become complete before exiting the interrupt
-		 * handler so this must be done first to ensure another
-		 * interrupt will occur.
-		 */
-		COMMAND(port, AcknowledgeInterrupt, interruptLatch);
-		status = STATUS(port);
-		if((status & interruptMask) == 0)
-			break;
-
-		if(status & hostError){
-			/*
-			 * Adapter failure, try to find out why, reset if
-			 * necessary. What happens if Tx is active and a reset
-			 * occurs, need to retransmit? This probably isn't right.
-			 */
-			COMMAND(port, SelectRegisterWindow, Wdiagnostic);
-			x = ins(port+FifoDiagnostic);
-			COMMAND(port, SelectRegisterWindow, Wop);
-			print("elnk3#%d: status 0x%uX, diag 0x%uX\n",
-			    ether->ctlrno, status, x);
-
-			if(x & txOverrun){
-				COMMAND(port, TxReset, 0);
-				COMMAND(port, TxEnable, 0);
-			}
-
-			if(x & rxUnderrun){
-				/*
-				 * This shouldn't happen...
-				 * Need to restart any busmastering?
-				 */
-				COMMAND(port, RxReset, 0);
-				while(STATUS(port) & commandInProgress)
-					;
-				COMMAND(port, RxEnable, 0);
-			}
-
-			status &= ~hostError;
-		}
-
-		if(status & (transferInt|rxComplete)){
-			receive(ether);
-			status &= ~(transferInt|rxComplete);
-		}
-
-		if(status & txComplete){
-			/*
-			 * Pop the TxStatus stack, accumulating errors.
-			 * Adjust the TX start threshold if there was an underrun.
-			 * If there was a Jabber or Underrun error, reset
-			 * the transmitter.
-			 * For all conditions enable the transmitter.
-			 */
-			txstatus = 0;
-			do{
-				if(x = inb(port+TxStatus))
-					outb(port+TxStatus, 0);
-				txstatus |= x;
-			}while(STATUS(port) & txComplete);
-
-			if(txstatus & txUnderrun){
-				COMMAND(port, SelectRegisterWindow, Wdiagnostic);
-				while(ins(port+MediaStatus) & txInProg)
-					;
-				COMMAND(port, SelectRegisterWindow, Wop);
-				if(ctlr->txthreshold < ETHERMAXTU)
-					ctlr->txthreshold += ETHERMINTU;
-			}
-
-			if(txstatus & (txJabber|txUnderrun)){
-				COMMAND(port, TxReset, 0);
-				while(STATUS(port) & commandInProgress)
-					;
-				COMMAND(port, SetTxStartThresh, ctlr->txthreshold);
-			}
-			COMMAND(port, TxEnable, 0);
-			status &= ~txComplete;
-			status |= txAvailable;
-		}
-
-		if(status & txAvailable){
-			COMMAND(port, AcknowledgeInterrupt, txAvailable);
-			transmit(ether);
-			status &= ~txAvailable;
-		}
-
-		if(status & updateStats){
-			statistics(ether);
-			status &= ~updateStats;
-		}
-
-		/*
-		 * Panic if there are any interrupts not dealt with.
-		 */
-		if(status & interruptMask)
-			panic("elnk3#%d: interrupt mask 0x%uX\n", ether->ctlrno, status);
-	}
-
-	COMMAND(port, SelectRegisterWindow, w);
-}
-
-typedef struct Adapter {
-	int	port;
-	int	irq;
-	int	tbdf;
-} Adapter;
-static Block* adapter;
-
-static void
-tcmadapter(int port, int irq, int tbdf)
-{
-	Block *bp;
-	Adapter *ap;
-
-	bp = allocb(sizeof(Adapter));
-	ap = (Adapter*)bp->rp;
-	ap->port = port;
-	ap->irq = irq;
-	ap->tbdf = tbdf;
-
-	bp->next = adapter;
-	adapter = bp;
-}
-
-/*
- * Write two 0 bytes to identify the IDport and then reset the
- * ID sequence. Then send the ID sequence to the card to get
- * the card into command state.
- */
-static void
-idseq(void)
-{
-	int i;
-	uchar al;
-	static int reset, untag;
-
-	/*
-	 * One time only:
-	 *	reset any adapters listening
-	 */
-	if(reset == 0){
-		outb(IDport, 0);
-		outb(IDport, 0);
-		outb(IDport, 0xC0);
-		delay(20);
-		reset = 1;
-	}
-
-	outb(IDport, 0);
-	outb(IDport, 0);
-	for(al = 0xFF, i = 0; i < 255; i++){
-		outb(IDport, al);
-		if(al & 0x80){
-			al <<= 1;
-			al ^= 0xCF;
-		}
-		else
-			al <<= 1;
-	}
-
-	/*
-	 * One time only:
-	 *	write ID sequence to get the attention of all adapters;
-	 *	untag all adapters.
-	 * If we do a global reset here on all adapters we'll confuse any
-	 * ISA cards configured for EISA mode.
-	 */
-	if(untag == 0){
-		outb(IDport, 0xD0);
-		untag = 1;
-	}
-}
-
-static ulong
-activate(void)
-{
-	int i;
-	ushort x, acr;
-
-	/*
-	 * Do the little configuration dance:
-	 *
-	 * 2. write the ID sequence to get to command state.
-	 */
-	idseq();
-
-	/*
-	 * 3. Read the Manufacturer ID from the EEPROM.
-	 *    This is done by writing the IDPort with 0x87 (0x80
-	 *    is the 'read EEPROM' command, 0x07 is the offset of
-	 *    the Manufacturer ID field in the EEPROM).
-	 *    The data comes back 1 bit at a time.
-	 *    We seem to need a delay here between reading the bits.
-	 *
-	 * If the ID doesn't match, there are no more adapters.
-	 */
-	outb(IDport, 0x87);
-	delay(20);
-	for(x = 0, i = 0; i < 16; i++){
-		delay(20);
-		x <<= 1;
-		x |= inb(IDport) & 0x01;
-	}
-	if(x != 0x6D50)
-		return 0;
-
-	/*
-	 * 3. Read the Address Configuration from the EEPROM.
-	 *    The Address Configuration field is at offset 0x08 in the EEPROM).
-	 */
-	outb(IDport, 0x88);
-	for(acr = 0, i = 0; i < 16; i++){
-		delay(20);
-		acr <<= 1;
-		acr |= inb(IDport) & 0x01;
-	}
-
-	return (acr & 0x1F)*0x10 + 0x200;
-}
-
-#ifdef notjustpcmcia
-static void
-tcm509isa(void)
-{
-	int irq, port;
-
-	/*
-	 * Attempt to activate all adapters. If adapter is set for
-	 * EISA mode (0x3F0), tag it and ignore. Otherwise, activate
-	 * it fully.
-	 */
-	while(port = activate()){
-		/*
-		 * 6. Tag the adapter so it won't respond in future.
-		 */
-		outb(IDport, 0xD1);
-		if(port == 0x3F0)
-			continue;
-
-		/*
-		 * 6. Activate the adapter by writing the Activate command
-		 *    (0xFF).
-		 */
-		outb(IDport, 0xFF);
-		delay(20);
-
-		/*
-		 * 8. Can now talk to the adapter's I/O base addresses.
-		 *    Use the I/O base address from the acr just read.
-		 *
-		 *    Enable the adapter and clear out any lingering status
-		 *    and interrupts.
-		 */
-		while(STATUS(port) & commandInProgress)
-			;
-		COMMAND(port, SelectRegisterWindow, Wsetup);
-		outs(port+ConfigControl, Ena);
-
-		COMMAND(port, TxReset, 0);
-		COMMAND(port, RxReset, 0);
-		COMMAND(port, AcknowledgeInterrupt, 0xFF);
-
-		irq = (ins(port+ResourceConfig)>>12) & 0x0F;
-		tcmadapter(port, irq, BUSUNKNOWN);
-	}
-}
-
-static void
-tcm5XXeisa(void)
-{
-	ushort x;
-	int irq, port, slot;
-
-	/*
-	 * Check if this is an EISA machine.
-	 * If not, nothing to do.
-	 */
-	if(strncmp((char*)(KZERO|0xFFFD9), "EISA", 4))
-		return;
-
-	/*
-	 * Continue through the EISA slots looking for a match on both
-	 * 3COM as the manufacturer and 3C579-* or 3C59[27]-* as the product.
-	 * If an adapter is found, select window 0, enable it and clear
-	 * out any lingering status and interrupts.
-	 */
-	for(slot = 1; slot < MaxEISA; slot++){
-		port = slot*0x1000;
-		if(ins(port+0xC80+ManufacturerID) != 0x6D50)
-			continue;
-		x = ins(port+0xC80+ProductID);
-		if((x & 0xF0FF) != 0x9050 && (x & 0xFF00) != 0x5900)
-			continue;
-
-		COMMAND(port, SelectRegisterWindow, Wsetup);
-		outs(port+ConfigControl, Ena);
-
-		COMMAND(port, TxReset, 0);
-		COMMAND(port, RxReset, 0);
-		COMMAND(port, AcknowledgeInterrupt, 0xFF);
-
-		irq = (ins(port+ResourceConfig)>>12) & 0x0F;
-		tcmadapter(port, irq, BUSUNKNOWN);
-	}
-}
-
-static void
-tcm59Xpci(void)
-{
-	Pcidev *p;
-	int irq, port;
-
-	p = nil;
-	while(p = pcimatch(p, 0x10B7, 0)){
-		port = p->mem[0].bar & ~0x01;
-		irq = p->intl;
-		COMMAND(port, GlobalReset, 0);
-		while(STATUS(port) & commandInProgress)
-			;
-
-		tcmadapter(port, irq, p->tbdf);
-	}
-}
-#endif /* notjustpcmcia */
-
-static char* tcmpcmcia[] = {
-	"3C589",			/* 3COM 589[ABCD] */
-	"3C562",			/* 3COM 562 */
-	"589E",				/* 3COM Megahertz 589E */
-	nil,
-};
-
-static int
-tcm5XXpcmcia(Ether* ether)
-{
-	int i;
-
-	for(i = 0; tcmpcmcia[i] != nil; i++){
-		if(!cistrcmp(ether->type, tcmpcmcia[i]))
-			return ether->port;
-	}
-
-	return 0;
-}
-
-static int
-autoselect(int port, int rxstatus9)
-{
-	int media, x;
-
-	/*
-	 * Pathetic attempt at automatic media selection.
-	 * Really just to get the Fast Etherlink 10BASE-T/100BASE-TX
-	 * cards operational.
-	 */
-	media = auiAvailable|coaxAvailable|base10TAvailable;
-	if(rxstatus9 == 0){
-		COMMAND(port, SelectRegisterWindow, Wfifo);
-		media = ins(port+ResetOptions);
-	}
-
-	if(media & miiConnector)
-		return xcvrMii;
-
-	if(media & baseTXAvailable){
-		/*
-		 * Must have InternalConfig register.
-		 */
-		COMMAND(port, SelectRegisterWindow, Wfifo);
-		x = inl(port+InternalConfig) & ~xcvrMask;
-		x |= xcvr100BaseTX;
-		outl(port+InternalConfig, x);
-		COMMAND(port, TxReset, 0);
-		while(STATUS(port) & commandInProgress)
-			;
-		COMMAND(port, RxReset, 0);
-		while(STATUS(port) & commandInProgress)
-			;
-
-		COMMAND(port, SelectRegisterWindow, Wdiagnostic);
-		x = ins(port+MediaStatus) & ~(dcConverterEnabled|jabberGuardEnable);
-		outs(port+MediaStatus, linkBeatEnable|x);
-		delay(10);
-
-{ int i, v;
-  for(i = 0; i < 10000; i++){
-	v = ins(port+MediaStatus);
-	if(v & linkBeatDetect){
-		print("count %d v %uX\n", i, v);
-		return xcvr100BaseTX;
-	}
-	delay(1);
-  }
-print("count %d v %uX\n", i, ins(port+MediaStatus));
-}
-		if(ins(port+MediaStatus) & linkBeatDetect)
-			return xcvr100BaseTX;
-		outs(port+MediaStatus, x);
-	}
-
-	if(media & base10TAvailable){
-		if(rxstatus9 == 0){
-			COMMAND(port, SelectRegisterWindow, Wfifo);
-			x = inl(port+InternalConfig) & ~xcvrMask;
-			x |= xcvr10BaseT;
-			outl(port+InternalConfig, x);
-		}
-		else{
-			COMMAND(port, SelectRegisterWindow, Wsetup);
-			x = ins(port+AddressConfig) & ~xcvrMask9;
-			x |= (xcvr10BaseT>>20)<<14;
-			outs(port+AddressConfig, x);
-		}
-		COMMAND(port, TxReset, 0);
-		while(STATUS(port) & commandInProgress)
-			;
-		COMMAND(port, RxReset, 0);
-		while(STATUS(port) & commandInProgress)
-			;
-
-		COMMAND(port, SelectRegisterWindow, Wdiagnostic);
-		x = ins(port+MediaStatus) & ~dcConverterEnabled;
-		outs(port+MediaStatus, linkBeatEnable|jabberGuardEnable|x);
-		delay(10);
-
-		if(ins(port+MediaStatus) & linkBeatDetect)
-			return xcvr10BaseT;
-		outs(port+MediaStatus, x);
-	}
-
-	/*
-	 * Botch.
-	 */
-	return autoSelect;
-}
-
-static int
-eepromdata(int port, int offset)
-{
-	COMMAND(port, SelectRegisterWindow, Wsetup);
-	while(EEPROMBUSY(port))
-		;
-	EEPROMCMD(port, EepromReadRegister, offset);
-	while(EEPROMBUSY(port))
-		;
-	return EEPROMDATA(port);
-}
-
-int
-elnk3reset(Ether* ether)
-{
-	int did, i, port, rxstatus9, x, xcvr;
-	Block *bp, **bpp;
-	Adapter *ap;
-	uchar ea[Eaddrlen];
-	Ctlr *ctlr;
-#ifdef notjustpcmcia
-	static int scandone;
-
-	/*
-	 * Scan for adapter on PCI, EISA and finally
-	 * using the little ISA configuration dance.
-	 */
-	if(scandone == 0){
-		tcm59Xpci();
-		tcm5XXeisa();
-		tcm509isa();
-		scandone = 1;
-	}
-#endif /* notjustpcmcia */
-
-	/*
-	 * Any adapter matches if no ether->port is supplied,
-	 * otherwise the ports must match.
-	 */
-	port = 0;
-	bpp = &adapter;
-	for(bp = *bpp; bp; bp = bp->next){
-		ap = (Adapter*)bp->rp;
-		if(ether->port == 0 || ether->port == ap->port){
-			port = ap->port;
-			ether->irq = ap->irq;
-			ether->tbdf = ap->tbdf;
-			*bpp = bp->next;
-			freeb(bp);
-			break;
-		}
-		bpp = &bp->next;
-	}
-	if(port == 0 && (port = tcm5XXpcmcia(ether)) == 0)
-		return -1;
-
-	/*
-	 * Read the DeviceID from the EEPROM, it's at offset 0x03,
-	 * and do something depending on capabilities.
-	 */
-	switch(did = eepromdata(port, 0x03)){
-
-	case 0x9000:
-	case 0x9001:
-	case 0x9050:
-	case 0x9051:
-		if(BUSTYPE(ether->tbdf) != BusPCI)
-			goto buggery;
-		goto vortex;
-
-	case 0x5900:
-	case 0x5920:
-	case 0x5950:
-	case 0x5951:
-	case 0x5952:
-	case 0x5970:
-	case 0x5971:
-	case 0x5972:
-	vortex:
-		COMMAND(port, SelectRegisterWindow, Wfifo);
-		xcvr = inl(port+InternalConfig) & (autoSelect|xcvrMask);
-		rxstatus9 = 0;
-		break;
-
-	buggery:
-	default:
-		COMMAND(port, SelectRegisterWindow, Wsetup);
-		x = ins(port+AddressConfig);
-		xcvr = ((x & xcvrMask9)>>14)<<20;
-		if(x & autoSelect9)
-			xcvr |= autoSelect;
-		rxstatus9 = 1;
-		break;
-	}
-	USED(did);
-
-	/*
-	 * Check if the adapter's station address is to be overridden.
-	 * If not, read it from the EEPROM and set in ether->ea prior to loading the
-	 * station address in Wstation. The EEPROM returns 16-bits at a time.
-	 */
-	memset(ea, 0, Eaddrlen);
-	if(memcmp(ea, ether->ea, Eaddrlen) == 0){
-		for(i = 0; i < Eaddrlen/2; i++){
-			x = eepromdata(port, i);
-			ether->ea[2*i] = x>>8;
-			ether->ea[2*i+1] = x;
-		}
-	}
-
-	COMMAND(port, SelectRegisterWindow, Wstation);
-	for(i = 0; i < Eaddrlen; i++)
-		outb(port+i, ether->ea[i]);
-
-	/*
-	 * Enable the transceiver if necessary.
-	 */
-	if(xcvr & autoSelect)
-		xcvr = autoselect(port, rxstatus9);
-	switch(xcvr){
-
-	case xcvrMii:
-		break;
-
-	case xcvr100BaseTX:
-	case xcvr100BaseFX:
-		COMMAND(port, SelectRegisterWindow, Wfifo);
-		x = inl(port+InternalConfig) & ~ramPartitionMask;
-		outl(port+InternalConfig, x|ramPartition1to1);
-
-		COMMAND(port, SelectRegisterWindow, Wdiagnostic);
-		x = ins(port+MediaStatus) & ~(dcConverterEnabled|jabberGuardEnable);
-		x |= linkBeatEnable;
-		outs(port+MediaStatus, x);
-		break;
-
-	case xcvr10BaseT:
-		/*
-		 * Enable Link Beat and Jabber to start the
-		 * transceiver.
-		 */
-		COMMAND(port, SelectRegisterWindow, Wdiagnostic);
-		x = ins(port+MediaStatus) & ~dcConverterEnabled;
-		x |= linkBeatEnable|jabberGuardEnable;
-		outs(port+MediaStatus, x);
-		break;
-
-	case xcvr10Base2:
-		COMMAND(port, SelectRegisterWindow, Wdiagnostic);
-		x = ins(port+MediaStatus) & ~(linkBeatEnable|jabberGuardEnable);
-		outs(port+MediaStatus, x);
-
-		/*
-		 * Start the DC-DC converter.
-		 * Wait > 800 microseconds.
-		 */
-		COMMAND(port, EnableDcConverter, 0);
-		delay(1);
-		break;
-	}
-
-	/*
-	 * Wop is the normal operating register set.
-	 * The 3C59[0257] adapters allow access to more than one register window
-	 * at a time, but there are situations where switching still needs to be
-	 * done, so just do it.
-	 * Clear out any lingering Tx status.
-	 */
-	COMMAND(port, SelectRegisterWindow, Wop);
-	while(inb(port+TxStatus))
-		outb(port+TxStatus, 0);
-
-	/*
-	 * Allocate a controller structure and start
-	 * to initialise it.
-	 */
-	ether->ctlr = malloc(sizeof(Ctlr));
-	ctlr = ether->ctlr;
-	memset(ctlr, 0, sizeof(Ctlr));
-
-	/*
-	 * Set a base TxStartThresh which will be incremented
-	 * if any txUnderrun errors occur and ensure no RxEarly
-	 * interrupts happen.
-	 */
-	ctlr->txthreshold = ETHERMINTU;
-	COMMAND(port, SetTxStartThresh, ETHERMINTU);
-	COMMAND(port, SetRxEarlyThresh, ETHERMAXTU);
-
-	/*
-	 * Set up the software configuration.
-	 */
-	ether->port = port;
-	ether->attach = attach;
-	ether->transmit = transmit;
-	ether->interrupt = interrupt;
-
-	return 0;
-}
--- a/os/boot/pc/etherga620.c
+++ /dev/null
@@ -1,1147 +1,0 @@
-/*
- * bootstrap driver for
- * Netgear GA620 Gigabit Ethernet Card.
- * Specific for the Alteon Tigon 2 and Intel Pentium or later.
- * To Do:
- *	cache alignment for PCI Write-and-Invalidate
- *	mini ring (what size)?
- *	tune coalescing values
- *	statistics formatting
- *	don't update Spi if nothing to send
- *	receive ring alignment
- *	watchdog for link management?
- */
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-#define malign(n)	xspanalloc((n), 32, 0)
-
-#include "etherif.h"
-#include "etherga620fw.h"
-
-enum {
-	Mhc		= 0x0040,	/* Miscellaneous Host Control */
-	Mlc		= 0x0044,	/* Miscellaneous Local Control */
-	Mc		= 0x0050,	/* Miscellaneous Configuration */
-	Ps		= 0x005C,	/* PCI State */
-	Wba		= 0x0068,	/* Window Base Address */
-	Wd		= 0x006C,	/* Window Data */
-
-	DMAas		= 0x011C,	/* DMA Assist State */
-
-	CPUAstate	= 0x0140,	/* CPU A State */
-	CPUApc		= 0x0144,	/* CPU A Programme Counter */
-
-	CPUBstate	= 0x0240,	/* CPU B State */
-
-	Hi		= 0x0504,	/* Host In Interrupt Handler */
-	Cpi		= 0x050C,	/* Command Producer Index */
-	Spi		= 0x0514,	/* Send Producer Index */
-	Rspi		= 0x051C,	/* Receive Standard Producer Index */
-	Rjpi		= 0x0524,	/* Receive Jumbo Producer Index */
-	Rmpi		= 0x052C,	/* Receive Mini Producer Index */
-
-	Mac		= 0x0600,	/* MAC Address */
-	Gip		= 0x0608,	/* General Information Pointer */
-	Om		= 0x0618,	/* Operating Mode */
-	DMArc		= 0x061C,	/* DMA Read Configuration */
-	DMAwc		= 0x0620,	/* DMA Write Configuration */
-	Tbr		= 0x0624,	/* Transmit Buffer Ratio */
-	Eci		= 0x0628,	/* Event Consumer Index */
-	Cci		= 0x062C,	/* Command Consumer Index */
-
-	Rct		= 0x0630,	/* Receive Coalesced Ticks */
-	Sct		= 0x0634,	/* Send Coalesced Ticks */
-	St		= 0x0638,	/* Stat Ticks */
-	SmcBD		= 0x063C,	/* Send Max. Coalesced BDs */
-	RmcBD		= 0x0640,	/* Receive Max. Coalesced BDs */
-	Nt		= 0x0644,	/* NIC Tracing */
-	Gln		= 0x0648,	/* Gigabit Link Negotiation */
-	Fln		= 0x064C,	/* 10/100 Link Negotiation */
-	Ifx		= 0x065C,	/* Interface Index */
-	IfMTU		= 0x0660,	/* Interface MTU */
-	Mi		= 0x0664,	/* Mask Interrupts */
-	Gls		= 0x0668,	/* Gigabit Link State */
-	Fls		= 0x066C,	/* 10/100 Link State */
-
-	Cr		= 0x0700,	/* Command Ring */
-
-	Lmw		= 0x0800,	/* Local Memory Window */
-};
-
-enum {					/* Mhc */
-	Is		= 0x00000001,	/* Interrupt State */
-	Ci		= 0x00000002,	/* Clear Interrupt */
-	Hr		= 0x00000008,	/* Hard Reset */
-	Eebs		= 0x00000010,	/* Enable Endian Byte Swap */
-	Eews		= 0x00000020,	/* Enable Endian Word (64-bit) swap */
-	Mpio		= 0x00000040,	/* Mask PCI Interrupt Output */
-};
-
-enum {					/* Mlc */
-	SRAM512		= 0x00000200,	/* SRAM Bank Size of 512KB */
-	SRAMmask	= 0x00000300,
-	EEclk		= 0x00100000,	/* Serial EEPROM Clock Output */
-	EEdoe		= 0x00200000,	/* Serial EEPROM Data Out Enable */
-	EEdo		= 0x00400000,	/* Serial EEPROM Data Out Value */
-	EEdi		= 0x00800000,	/* Serial EEPROM Data Input */
-};
-
-enum {					/* Mc */
-	SyncSRAM	= 0x00100000,	/* Set Synchronous SRAM Timing */
-};
-
-enum {					/* Ps */
-	PCIwm32		= 0x000000C0,	/* Write Max DMA 32 */
-	PCImrm		= 0x00020000,	/* Use Memory Read Multiple Command */
-	PCI66		= 0x00080000,
-	PCI32		= 0x00100000,
-	PCIrcmd		= 0x06000000,	/* PCI Read Command */
-	PCIwcmd		= 0x70000000,	/* PCI Write Command */
-};
-
-enum {					/* CPUAstate */
-	CPUrf		= 0x00000010,	/* ROM Fail */
-	CPUhalt		= 0x00010000,	/* Halt the internal CPU */
-	CPUhie		= 0x00040000,	/* HALT instruction executed */
-};
-
-enum {					/* Om */
-	BswapBD		= 0x00000002,	/* Byte Swap Buffer Descriptors */
-	WswapBD		= 0x00000004,	/* Word Swap Buffer Descriptors */
-	Warn		= 0x00000008,
-	BswapDMA	= 0x00000010,	/* Byte Swap DMA Data */
-	Only1DMA	= 0x00000040,	/* Only One DMA Active at a time */
-	NoJFrag		= 0x00000200,	/* Don't Fragment Jumbo Frames */
-	Fatal		= 0x40000000,
-};
-
-enum {					/* Lmw */
-	Lmwsz		= 2*1024,	/* Local Memory Window Size */
-
-	/*
-	 * legal values are 0x3800 iff Nsr is 128, 0x3000 iff Nsr is 256,
-	 * or 0x2000 iff Nsr is 512.
-	 */
-	Sr		= 0x3800,	/* Send Ring (accessed via Lmw) */
-};
-
-enum {					/* Link */
-	Lpref		= 0x00008000,	/* Preferred Link */
-	L10MB		= 0x00010000,
-	L100MB		= 0x00020000,
-	L1000MB		= 0x00040000,
-	Lfd		= 0x00080000,	/* Full Duplex */
-	Lhd		= 0x00100000,	/* Half Duplex */
-	Lefc		= 0x00200000,	/* Emit Flow Control Packets */
-	Lofc		= 0x00800000,	/* Obey Flow Control Packets */
-	Lean		= 0x20000000,	/* Enable Autonegotiation/Sensing */
-	Le		= 0x40000000,	/* Link Enable */
-};
-
-typedef struct Host64 {
-	uint	hi;
-	uint	lo;
-} Host64;
-
-typedef struct Ere {			/* Event Ring Element */
-	int	event;			/* event<<24 | code<<12 | index */
-	int	unused;
-} Ere;
-
-typedef int Cmd;			/* cmd<<24 | flags<<12 | index */
-
-typedef struct Rbd {			/* Receive Buffer Descriptor */
-	Host64	addr;
-	int	indexlen;		/* ring-index<<16 | buffer-length */
-	int	flags;			/* only lower 16-bits */
-	int	checksum;		/* ip<<16 |tcp/udp */
-	int	error;			/* only upper 16-bits */
-	int	reserved;
-	void*	opaque;			/* passed to receive return ring */
-} Rbd;
-
-typedef struct Sbd {			/* Send Buffer Descriptor */
-	Host64	addr;
-	int	lenflags;		/* len<<16 |flags */
-	int	reserved;
-} Sbd;
-
-enum {					/* Buffer Descriptor Flags */
-	Fend		= 0x00000004,	/* Frame Ends in this Buffer */
-	Frjr		= 0x00000010,	/* Receive Jumbo Ring Buffer */
-	Funicast	= 0x00000020,	/* Unicast packet (2-bit field) */
-	Fmulticast	= 0x00000040,	/* Multicast packet */
-	Fbroadcast	= 0x00000060,	/* Broadcast packet */
-	Ferror		= 0x00000400,	/* Frame Has Error */
-	Frmr		= 0x00001000,	/* Receive Mini Ring Buffer */
-};
-
-enum {					/* Buffer Error Flags */
-	Ecrc		= 0x00010000,	/* bad CRC */
-	Ecollision	= 0x00020000,	/* collision */
-	Elink		= 0x00040000,	/* link lost */
-	Ephy		= 0x00080000,	/* unspecified PHY frame decode error */
-	Eodd		= 0x00100000,	/* odd number of nibbles */
-	Emac		= 0x00200000,	/* unspecified MAC abort */
-	Elen64		= 0x00400000,	/* short packet */
-	Eresources	= 0x00800000,	/* MAC out of internal resources */
-	Egiant		= 0x01000000,	/* packet too big */
-};
-
-typedef struct Rcb {			/* Ring Control Block */
-	Host64	addr;			/* points to the Rbd ring */
-	int	control;		/* max_len<<16 |flags */
-	int	unused;
-} Rcb;
-
-enum {
-	TcpUdpCksum	= 0x0001,	/* Perform TCP or UDP checksum */
-	IpCksum		= 0x0002,	/* Perform IP checksum */
-	NoPseudoHdrCksum= 0x0008,	/* Don't include the pseudo header */
-	VlanAssist	= 0x0010,	/* Enable VLAN tagging */
-	CoalUpdateOnly	= 0x0020,	/* Coalesce transmit interrupts */
-	HostRing	= 0x0040,	/* Sr in host memory */
-	SnapCksum	= 0x0080,	/* Parse + offload 802.3 SNAP frames */
-	UseExtRxBd	= 0x0100,	/* Extended Rbd for Jumbo frames */
-	RingDisabled	= 0x0200,	/* Jumbo or Mini RCB only */
-};
-
-typedef struct Gib {			/* General Information Block */
-	int	statistics[256];	/* Statistics */
-	Rcb	ercb;			/* Event Ring */
-	Rcb	crcb;			/* Command Ring */
-	Rcb	srcb;			/* Send Ring */
-	Rcb	rsrcb;			/* Receive Standard Ring */
-	Rcb	rjrcb;			/* Receive Jumbo Ring */
-	Rcb	rmrcb;			/* Receive Mini Ring */
-	Rcb	rrrcb;			/* Receive Return Ring */
-	Host64	epp;			/* Event Producer */
-	Host64	rrrpp;			/* Receive Return Ring Producer */
-	Host64	scp;			/* Send Consumer */
-	Host64	rsp;			/* Refresh Stats */
-} Gib;
-
-/*
- * these sizes are all fixed in the card,
- * except for Nsr, which has only 3 valid sizes.
- */
-enum {					/* Host/NIC Interface ring sizes */
-	Ner		= 256,		/* event ring */
-	Ncr		= 64,		/* command ring */
-	Nsr		= 128,		/* send ring: 128, 256 or 512 */
-	Nrsr		= 512,		/* receive standard ring */
-	Nrjr		= 256,		/* receive jumbo ring */
-	Nrmr		= 1024,		/* receive mini ring, optional */
-	Nrrr		= 2048,		/* receive return ring */
-};
-
-enum {
-	NrsrHI		= 72,		/* Fill-level of Rsr (m.b. < Nrsr) */
-	NrsrLO		= 54,		/* Level at which to top-up ring */
-	NrjrHI		= 0,		/* Fill-level of Rjr (m.b. < Nrjr) */
-	NrjrLO		= 0,		/* Level at which to top-up ring */
-	NrmrHI		= 0,		/* Fill-level of Rmr (m.b. < Nrmr) */
-	NrmrLO		= 0,		/* Level at which to top-up ring */
-};
-
-typedef struct Ctlr Ctlr;
-struct Ctlr {
-	int	port;
-	Pcidev*	pcidev;
-	Ctlr*	next;
-	int	active;
-	int	id;
-
-	uchar	ea[Eaddrlen];
-
-	int*	nic;
-	Gib*	gib;
-
-	Ere*	er;
-
-	Lock	srlock;
-	Sbd*	sr;
-	Block**	srb;
-	int	nsr;			/* currently in send ring */
-
-	Rbd*	rsr;
-	int	nrsr;			/* currently in Receive Standard Ring */
-	Rbd*	rjr;
-	int	nrjr;			/* currently in Receive Jumbo Ring */
-	Rbd*	rmr;
-	int	nrmr;			/* currently in Receive Mini Ring */
-	Rbd*	rrr;
-	int	rrrci;			/* Receive Return Ring Consumer Index */
-
-	int	epi[2];			/* Event Producer Index */
-	int	rrrpi[2];		/* Receive Return Ring Producer Index */
-	int	sci[3];			/* Send Consumer Index ([2] is host) */
-
-	int	interrupts;		/* statistics */
-	int	mi;
-	uvlong	ticks;
-
-	int	coalupdateonly;		/* tuning */
-	int	hardwarecksum;
-	int	rct;			/* Receive Coalesce Ticks */
-	int	sct;			/* Send Coalesce Ticks */
-	int	st;			/* Stat Ticks */
-	int	smcbd;			/* Send Max. Coalesced BDs */
-	int	rmcbd;			/* Receive Max. Coalesced BDs */
-};
-
-static Ctlr* ctlrhead;
-static Ctlr* ctlrtail;
-
-#define csr32r(c, r)	(*((c)->nic+((r)/4)))
-#define csr32w(c, r, v)	(*((c)->nic+((r)/4)) = (v))
-
-static void
-sethost64(Host64* host64, void* addr)
-{
-	uvlong uvl;
-
-	uvl = PCIWADDR(addr);
-	host64->hi = uvl>>32;
-	host64->lo = uvl & 0xFFFFFFFFL;
-}
-
-static void
-ga620command(Ctlr* ctlr, int cmd, int flags, int index)
-{
-	int cpi;
-
-	cpi = csr32r(ctlr, Cpi);
-	csr32w(ctlr, Cr+(cpi*4), cmd<<24 | flags<<12 | index);
-	cpi = NEXT(cpi, Ncr);
-	csr32w(ctlr, Cpi, cpi);
-}
-
-static void
-ga620attach(Ether* )
-{
-}
-
-static void
-waitforlink(Ether *edev)
-{
-	int i;
-
-	if (edev->mbps == 0) {
-		print("#l%d: ga620: waiting for link", edev->ctlrno);
-		/* usually takes about 10 seconds */
-		for (i = 0; i < 20 && edev->mbps == 0; i++) {
-			print(".");
-			delay(1000);
-		}
-		print("\n");
-		if (i == 20 && edev->mbps == 0)
-			edev->mbps = 1;			/* buggered */
-	}
-}
-
-static void
-toringbuf(Ether *ether, Block *bp)
-{
-	RingBuf *rb = &ether->rb[ether->ri];
-
-	if (rb->owner == Interface) {
-		rb->len = BLEN(bp);
-		memmove(rb->pkt, bp->rp, rb->len);
-		rb->owner = Host;
-		ether->ri = NEXT(ether->ri, ether->nrb);
-	}
-	/* else no one is expecting packets from the network */
-}
-
-static Block *
-fromringbuf(Ether *ether)
-{
-	RingBuf *tb = &ether->tb[ether->ti];
-	Block *bp = allocb(tb->len);
-
-	if (bp == nil)
-		panic("fromringbuf: nil allocb return");
-	if (bp->wp == nil)
-		panic("fromringbuf: nil bp->wb");
-	memmove(bp->wp, tb->pkt, tb->len);
-	memmove(bp->wp+Eaddrlen, ether->ea, Eaddrlen);
-	bp->wp += tb->len;
-	return bp;
-}
-
-static int
-_ga620transmit(Ether* edev)
-{
-	Sbd *sbd;
-	Block *bp;
-	Ctlr *ctlr;
-	RingBuf *tb;
-	int sci, spi, work;
-
-	/*
-	 * For now there are no smarts here, just empty the
-	 * ring and try to fill it back up. Tuning comes later.
-	 */
-	ctlr = edev->ctlr;
-	waitforlink(edev);
-	ilock(&ctlr->srlock);
-
-	/*
-	 * Free any completed packets.
-	 * Ctlr->sci[0] is where the NIC has got to consuming the ring.
-	 * Ctlr->sci[2] is where the host has got to tidying up after the
-	 * NIC has done with the packets.
-	 */
-	work = 0;
-	for(sci = ctlr->sci[2]; sci != ctlr->sci[0]; sci = NEXT(sci, Nsr)){
-		if(ctlr->srb[sci] == nil)
-			continue;
-		freeb(ctlr->srb[sci]);
-		ctlr->srb[sci] = nil;
-		work++;
-	}
-	ctlr->sci[2] = sci;
-
-	sci = PREV(sci, Nsr);
-
-	tb = &edev->tb[edev->ti];
-	for(spi = csr32r(ctlr, Spi); spi != sci && tb->owner == Interface;
-	    spi = NEXT(spi, Nsr)){
-		bp = fromringbuf(edev);
-
-		sbd = &ctlr->sr[spi];
-		sethost64(&sbd->addr, bp->rp);
-		sbd->lenflags = BLEN(bp)<<16 |Fend;
-
-		ctlr->srb[spi] = bp;
-		work++;
-
-		tb->owner = Host;
-		edev->ti = NEXT(edev->ti, edev->ntb);
-		tb = &edev->tb[edev->ti];
-	}
-	csr32w(ctlr, Spi, spi);
-
-	iunlock(&ctlr->srlock);
-
-	return work;
-}
-
-static void
-ga620transmit(Ether* edev)
-{
-	_ga620transmit(edev);
-}
-
-static void
-ga620replenish(Ctlr* ctlr)
-{
-	Rbd *rbd;
-	int rspi;
-	Block *bp;
-
-	rspi = csr32r(ctlr, Rspi);
-	while(ctlr->nrsr < NrsrHI){
-		if((bp = allocb(ETHERMAXTU+4)) == nil)
-			break;
-		rbd = &ctlr->rsr[rspi];
-		sethost64(&rbd->addr, bp->rp);
-		rbd->indexlen = rspi<<16 | (ETHERMAXTU+4);
-		rbd->flags = 0;
-		rbd->opaque = bp;
-
-		rspi = NEXT(rspi, Nrsr);
-		ctlr->nrsr++;
-	}
-	csr32w(ctlr, Rspi, rspi);
-}
-
-static void
-ga620event(Ether *edev, int eci, int epi)
-{
-	unsigned event, code;
-	Ctlr *ctlr;
-
-	ctlr = edev->ctlr;
-	while(eci != epi){
-		event = ctlr->er[eci].event;
-		code = (event >> 12) & ((1<<12)-1);
-		switch(event>>24){
-		case 0x01:		/* firmware operational */
-			/* host stack (us) is up.  3rd arg of 2 means down. */
-			ga620command(ctlr, 0x01, 0x01, 0x00);
-			/*
-			 * link negotiation: any speed is okay.
-			 * 3rd arg of 1 selects gigabit only; 2 10/100 only.
-			 */
-			ga620command(ctlr, 0x0B, 0x00, 0x00);
-			print("#l%d: ga620: port %8.8uX: firmware is up\n",
-				edev->ctlrno, ctlr->port);
-			break;
-		case 0x04:		/* statistics updated */
-			break;
-		case 0x06:		/* link state changed */
-			switch (code) {
-			case 1:
-				edev->mbps = 1000;
-				break;
-			case 2:
-				print("#l%d: link down\n", edev->ctlrno);
-				break;
-			case 3:
-				edev->mbps = 100;	/* it's 10 or 100 */
-				break;
-			}
-			if (code != 2)
-				print("#l%d: %dMbps link up\n",
-					edev->ctlrno, edev->mbps);
-			break;
-		case 0x07:		/* event error */
-		default:
-			print("#l%d: ga620: er[%d] = %8.8uX\n", edev->ctlrno,
-				eci, event);
-			break;
-		}
-		eci = NEXT(eci, Ner);
-	}
-	csr32w(ctlr, Eci, eci);
-}
-
-static void
-ga620receive(Ether* edev)
-{
-	int len;
-	Rbd *rbd;
-	Block *bp;
-	Ctlr* ctlr;
-
-	ctlr = edev->ctlr;
-	while(ctlr->rrrci != ctlr->rrrpi[0]){
-		rbd = &ctlr->rrr[ctlr->rrrci];
-		/*
-		 * Errors are collected in the statistics block so
-		 * no need to tally them here, let ifstat do the work.
-		 */
-		len = rbd->indexlen & 0xFFFF;
-		if(!(rbd->flags & Ferror) && len != 0){
-			bp = rbd->opaque;
-			bp->wp = bp->rp+len;
-
-			toringbuf(edev, bp);
-		} else
-			freeb(rbd->opaque);
-		rbd->opaque = nil;
-
-		if(rbd->flags & Frjr)
-			ctlr->nrjr--;
-		else if(rbd->flags & Frmr)
-			ctlr->nrmr--;
-		else
-			ctlr->nrsr--;
-
-		ctlr->rrrci = NEXT(ctlr->rrrci, Nrrr);
-	}
-}
-
-static void
-ga620interrupt(Ureg*, void* arg)
-{
-	int csr, ie, work;
-	Ctlr *ctlr;
-	Ether *edev;
-
-	edev = arg;
-	ctlr = edev->ctlr;
-
-	if(!(csr32r(ctlr, Mhc) & Is))
-		return;
-
-	ctlr->interrupts++;
-	csr32w(ctlr, Hi, 1);
-
-	ie = 0;
-	work = 0;
-	while(ie < 2){
-		if(ctlr->rrrci != ctlr->rrrpi[0]){
-			ga620receive(edev);
-			work = 1;
-		}
-
-		if(_ga620transmit(edev) != 0)
-			work = 1;
-
-		csr = csr32r(ctlr, Eci);
-		if(csr != ctlr->epi[0]){
-			ga620event(edev, csr, ctlr->epi[0]);
-			work = 1;
-		}
-
-		if(ctlr->nrsr <= NrsrLO)
-			ga620replenish(ctlr);
-		if(work == 0){
-			if(ie == 0)
-				csr32w(ctlr, Hi, 0);
-			ie++;
-		}
-		work = 0;
-	}
-}
-
-static void
-ga620lmw(Ctlr* ctlr, int addr, int* data, int len)
-{
-	int i, l, lmw, v;
-
-	/*
-	 * Write to or clear ('data' == nil) 'len' bytes of the NIC
-	 * local memory at address 'addr'.
-	 * The destination address and count should be 32-bit aligned.
-	 */
-	v = 0;
-	while(len > 0){
-		/*
-		 * 1) Set the window. The (Lmwsz-1) bits are ignored
-		 *    in Wba when accessing through the local memory window;
-		 * 2) Find the minimum of how many bytes still to
-		 *    transfer and how many left in this window;
-		 * 3) Create the offset into the local memory window in the
-		 *    shared memory space then copy (or zero) the data;
-		 * 4) Bump the counts.
-		 */
-		csr32w(ctlr, Wba, addr);
-
-		l = ROUNDUP(addr+1, Lmwsz) - addr;
-		if(l > len)
-			l = len;
-
-		lmw = Lmw + (addr & (Lmwsz-1));
-		for(i = 0; i < l; i += 4){
-			if(data != nil)
-				v = *data++;
-			csr32w(ctlr, lmw+i, v);
-		}
-
-		len -= l;
-		addr += l;
-	}
-}
-
-static int
-ga620init(Ether* edev)
-{
-	Ctlr *ctlr;
-	Host64 host64;
-	int csr, ea, i, flags;
-
-	ctlr = edev->ctlr;
-
-	/*
-	 * Load the MAC address.
-	 */
-	ea = edev->ea[0]<<8 | edev->ea[1];
-	csr32w(ctlr, Mac, ea);
-	ea = edev->ea[2]<<24 | edev->ea[3]<<16 | edev->ea[4]<<8 | edev->ea[5];
-	csr32w(ctlr, Mac+4, ea);
-
-	/*
-	 * General Information Block.
-	 */
-	ctlr->gib = malloc(sizeof(Gib));
-	sethost64(&host64, ctlr->gib);
-	csr32w(ctlr, Gip, host64.hi);
-	csr32w(ctlr, Gip+4, host64.lo);
-
-	/*
-	 * Event Ring.
-	 * This is located in host memory. Allocate the ring,
-	 * tell the NIC where it is and initialise the indices.
-	 */
-	ctlr->er = malign(sizeof(Ere)*Ner);
-	sethost64(&ctlr->gib->ercb.addr, ctlr->er);
-	sethost64(&ctlr->gib->epp, ctlr->epi);
-	csr32w(ctlr, Eci, 0);
-
-	/*
-	 * Command Ring.
-	 * This is located in the General Communications Region
-	 * and so the value placed in the Rcb is unused, the NIC
-	 * knows where it is. Stick in the value according to
-	 * the datasheet anyway.
-	 * Initialise the ring and indices.
-	 */
-	ctlr->gib->crcb.addr.lo = Cr - 0x400;
-	for(i = 0; i < Ncr*4; i += 4)
-		csr32w(ctlr, Cr+i, 0);
-	csr32w(ctlr, Cpi, 0);
-	csr32w(ctlr, Cci, 0);
-
-	/*
-	 * Send Ring.
-	 * This ring is either in NIC memory at a fixed location depending
-	 * on how big the ring is or it is in host memory. If in NIC
-	 * memory it is accessed via the Local Memory Window; with a send
-	 * ring size of 128 the window covers the whole ring and then need
-	 * only be set once:
-	 *	ctlr->sr = (uchar*)ctlr->nic+Lmw;
-	 *	ga620lmw(ctlr, Sr, nil, sizeof(Sbd)*Nsr);
-	 *	ctlr->gib->srcb.addr.lo = Sr;
-	 * There is nowhere in the Sbd to hold the Block* associated
-	 * with this entry so an external array must be kept.
-	 */
-	ctlr->sr = malign(sizeof(Sbd)*Nsr);
-	sethost64(&ctlr->gib->srcb.addr, ctlr->sr);
-	if(ctlr->hardwarecksum)
-		flags = TcpUdpCksum|NoPseudoHdrCksum|HostRing;
-	else 
-		flags = HostRing;
-	if(ctlr->coalupdateonly) 
-		flags |= CoalUpdateOnly;
-	ctlr->gib->srcb.control = Nsr<<16 | flags;
-	sethost64(&ctlr->gib->scp, ctlr->sci);
-	csr32w(ctlr, Spi, 0);
-	ctlr->srb = malloc(sizeof(Block*)*Nsr);
-
-	/*
-	 * Receive Standard Ring.
-	 */
-	ctlr->rsr = malign(sizeof(Rbd)*Nrsr);
-	sethost64(&ctlr->gib->rsrcb.addr, ctlr->rsr);
-	if(ctlr->hardwarecksum)
-		flags = TcpUdpCksum|NoPseudoHdrCksum;
-	else
-		flags = 0;
-	ctlr->gib->rsrcb.control = (ETHERMAXTU+4)<<16 | flags;
-	csr32w(ctlr, Rspi, 0);
-
-	/*
-	 * Jumbo and Mini Rings. Unused for now.
-	 */
-	ctlr->gib->rjrcb.control = RingDisabled;
-	ctlr->gib->rmrcb.control = RingDisabled;
-
-	/*
-	 * Receive Return Ring.
-	 * This is located in host memory. Allocate the ring,
-	 * tell the NIC where it is and initialise the indices.
-	 */
-	ctlr->rrr = malign(sizeof(Rbd)*Nrrr);
-	sethost64(&ctlr->gib->rrrcb.addr, ctlr->rrr);
-	ctlr->gib->rrrcb.control = Nrrr<<16 | 0;
-	sethost64(&ctlr->gib->rrrpp, ctlr->rrrpi);
-	ctlr->rrrci = 0;
-
-	/*
-	 * Refresh Stats Pointer.
-	 * For now just point it at the existing statistics block.
-	 */
-	sethost64(&ctlr->gib->rsp, ctlr->gib->statistics);
-
-	/*
-	 * DMA configuration.
-	 * Use the recommended values.
-	 */
-	csr32w(ctlr, DMArc, 0x80);
-	csr32w(ctlr, DMAwc, 0x80);
-
-	/*
-	 * Transmit Buffer Ratio.
-	 * Set to 1/3 of available buffer space (units are 1/64ths)
-	 * if using Jumbo packets, ~64KB otherwise (assume 1MB on NIC).
-	 */
-	if(NrjrHI > 0 || Nsr > 128)
-		csr32w(ctlr, Tbr, 64/3);
-	else
-		csr32w(ctlr, Tbr, 4);
-
-	/*
-	 * Tuneable parameters.
-	 * These defaults are based on the tuning hints in the Alteon
-	 * Host/NIC Software Interface Definition and example software.
-	 */
-	ctlr->rct = 1 /*100*/;
-	csr32w(ctlr, Rct, ctlr->rct);
-	ctlr->sct = 0;
-	csr32w(ctlr, Sct, ctlr->sct);
-	ctlr->st = 1000000;
-	csr32w(ctlr, St, ctlr->st);
-	ctlr->smcbd = Nsr/4;
-	csr32w(ctlr, SmcBD, ctlr->smcbd);
-	ctlr->rmcbd = 4 /*6*/;
-	csr32w(ctlr, RmcBD, ctlr->rmcbd);
-
-	/*
-	 * Enable DMA Assist Logic.
-	 */
-	csr = csr32r(ctlr, DMAas) & ~0x03;
-	csr32w(ctlr, DMAas, csr|0x01);
-
-	/*
-	 * Link negotiation.
-	 * The bits are set here but the NIC must be given a command
-	 * once it is running to set negotiation in motion.
-	 */
-	csr32w(ctlr, Gln, Le|Lean|Lofc|Lfd|L1000MB|Lpref);
-	csr32w(ctlr, Fln, Le|Lean|Lhd|Lfd|L100MB|L10MB);
-
-	/*
-	 * A unique index for this controller and the maximum packet
-	 * length expected.
-	 * For now only standard packets are expected.
-	 */
-	csr32w(ctlr, Ifx, 1);
-	csr32w(ctlr, IfMTU, ETHERMAXTU+4);
-
-	/*
-	 * Enable Interrupts.
-	 * There are 3 ways to mask interrupts - a bit in the Mhc (which
-	 * is already cleared), the Mi register and the Hi mailbox.
-	 * Writing to the Hi mailbox has the side-effect of clearing the
-	 * PCI interrupt.
-	 */
-	csr32w(ctlr, Mi, 0);
-	csr32w(ctlr, Hi, 0);
-
-	/*
-	 * Start the firmware.
-	 */
-	csr32w(ctlr, CPUApc, tigon2FwStartAddr);
-	csr = csr32r(ctlr, CPUAstate) & ~CPUhalt;
-	csr32w(ctlr, CPUAstate, csr);
-
-	return 0;
-}
-
-static int
-at24c32io(Ctlr* ctlr, char* op, int data)
-{
-	char *lp, *p;
-	int i, loop, mlc, r;
-
-	mlc = csr32r(ctlr, Mlc);
-
-	r = 0;
-	loop = -1;
-	lp = nil;
-	for(p = op; *p != '\0'; p++){
-		switch(*p){
-		default:
-			return -1;
-		case ' ':
-			continue;
-		case ':':			/* start of 8-bit loop */
-			if(lp != nil)
-				return -1;
-			lp = p;
-			loop = 7;
-			continue;
-		case ';':			/* end of 8-bit loop */
-			if(lp == nil)
-				return -1;
-			loop--;
-			if(loop >= 0)
-				p = lp;
-			else
-				lp = nil;
-			continue;
-		case 'C':			/* assert clock */
-			mlc |= EEclk;
-			break;
-		case 'c':			/* deassert clock */
-			mlc &= ~EEclk;
-			break;
-		case 'D':			/* next bit in 'data' byte */
-			if(loop < 0)
-				return -1;
-			if(data & (1<<loop))
-				mlc |= EEdo;
-			else
-				mlc &= ~EEdo;
-			break;
-		case 'E':			/* enable data output */
-			mlc |= EEdoe;
-			break;
-		case 'e':			/* disable data output */
-			mlc &= ~EEdoe;
-			break;
-		case 'I':			/* input bit */
-			i = (csr32r(ctlr, Mlc) & EEdi) != 0;
-			if(loop >= 0)
-				r |= (i<<loop);
-			else
-				r = i;
-			continue;
-		case 'O':			/* assert data output */
-			mlc |= EEdo;
-			break;
-		case 'o':			/* deassert data output */
-			mlc &= ~EEdo;
-			break;
-		}
-		csr32w(ctlr, Mlc, mlc);
-		microdelay(1);
-	}
-	if(loop >= 0)
-		return -1;
-	return r;
-}
-
-static int
-at24c32r(Ctlr* ctlr, int addr)
-{
-	int data;
-
-	/*
-	 * Read a byte at address 'addr' from the Atmel AT24C32
-	 * Serial EEPROM. The 2-wire EEPROM access is controlled
-	 * by 4 bits in Mlc. See the AT24C32 datasheet for
-	 * protocol details.
-	 */
-	/*
-	 * Start condition - a high to low transition of data
-	 * with the clock high must precede any other command.
-	 */
-	at24c32io(ctlr, "OECoc", 0);
-
-	/*
-	 * Perform a random read at 'addr'. A dummy byte
-	 * write sequence is performed to clock in the device
-	 * and data word addresses (0 and 'addr' respectively).
-	 */
-	data = -1;
-	if(at24c32io(ctlr, "oE :DCc; oeCIc", 0xA0) != 0)
-		goto stop;
-	if(at24c32io(ctlr, "oE :DCc; oeCIc", addr>>8) != 0)
-		goto stop;
-	if(at24c32io(ctlr, "oE :DCc; oeCIc", addr) != 0)
-		goto stop;
-
-	/*
-	 * Now send another start condition followed by a
-	 * request to read the device. The EEPROM responds
-	 * by clocking out the data.
-	 */
-	at24c32io(ctlr, "OECoc", 0);
-	if(at24c32io(ctlr, "oE :DCc; oeCIc", 0xA1) != 0)
-		goto stop;
-	data = at24c32io(ctlr, ":CIc;", 0xA1);
-
-stop:
-	/*
-	 * Stop condition - a low to high transition of data
-	 * with the clock high is a stop condition. After a read
-	 * sequence, the stop command will place the EEPROM in
-	 * a standby power mode.
-	 */
-	at24c32io(ctlr, "oECOc", 0);
-
-	return data;
-}
-
-static int
-ga620detach(Ctlr* ctlr)
-{
-	int timeo;
-
-	/*
-	 * Hard reset (don't know which endian so catch both);
-	 * enable for little-endian mode;
-	 * wait for code to be loaded from serial EEPROM or flash;
-	 * make sure CPU A is halted.
-	 */
-	csr32w(ctlr, Mhc, Hr<<24 | Hr);
-	csr32w(ctlr, Mhc, (Eews|Ci)<<24 | Eews|Ci);
-
-	microdelay(1);
-	for(timeo = 0; timeo < 500000; timeo++){
-		if((csr32r(ctlr, CPUAstate) & (CPUhie|CPUrf)) == CPUhie)
-			break;
-		microdelay(1);
-	}
-	if((csr32r(ctlr, CPUAstate) & (CPUhie|CPUrf)) != CPUhie)
-		return -1;
-	csr32w(ctlr, CPUAstate, CPUhalt);
-
-	/*
-	 * After reset, CPU B seems to be stuck in 'CPUrf'.
-	 * Worry about it later.
-	 */
-	csr32w(ctlr, CPUBstate, CPUhalt);
-
-	return 0;
-}
-
-static void
-ga620shutdown(Ether* ether)
-{
-print("ga620shutdown\n");
-	ga620detach(ether->ctlr);
-}
-
-static int
-ga620reset(Ctlr* ctlr)
-{
-	int cls, csr, i, r;
-
-	if(ga620detach(ctlr) < 0)
-		return -1;
-
-	/*
-	 * Tigon 2 PCI NICs have 512KB SRAM per bank.
-	 * Clear out any lingering serial EEPROM state
-	 * bits.
-	 */
-	csr = csr32r(ctlr, Mlc) & ~(EEdi|EEdo|EEdoe|EEclk|SRAMmask);
-	csr32w(ctlr, Mlc, SRAM512|csr);
-	csr = csr32r(ctlr, Mc);
-	csr32w(ctlr, Mc, SyncSRAM|csr);
-
-	/*
-	 * Initialise PCI State register.
-	 * If PCI Write-and-Invalidate is enabled set the max write DMA
-	 * value to the host cache-line size (32 on Pentium or later).
-	 */
-	csr = csr32r(ctlr, Ps) & (PCI32|PCI66);
-	csr |= PCIwcmd|PCIrcmd|PCImrm;
-	if(ctlr->pcidev->pcr & 0x0010){
-		cls = pcicfgr8(ctlr->pcidev, PciCLS) * 4;
-		if(cls != 32)
-			pcicfgw8(ctlr->pcidev, PciCLS, 32/4);
-		csr |= PCIwm32;
-	}
-	csr32w(ctlr, Ps, csr);
-
-	/*
-	 * Operating Mode.
-	 */
-	csr32w(ctlr, Om, Fatal|NoJFrag|BswapDMA|WswapBD);
-
-	/*
-	 * Snarf the MAC address from the serial EEPROM.
-	 */
-	for(i = 0; i < Eaddrlen; i++){
-		if((r = at24c32r(ctlr, 0x8E+i)) == -1)
-			return -1;
-		ctlr->ea[i] = r;
-	}
-
-	/*
-	 * Load the firmware.
-	 */
-	ga620lmw(ctlr, tigon2FwTextAddr, tigon2FwText, tigon2FwTextLen);
-	ga620lmw(ctlr, tigon2FwRodataAddr, tigon2FwRodata, tigon2FwRodataLen);
-	ga620lmw(ctlr, tigon2FwDataAddr, tigon2FwData, tigon2FwDataLen);
-	ga620lmw(ctlr, tigon2FwSbssAddr, nil, tigon2FwSbssLen);
-	ga620lmw(ctlr, tigon2FwBssAddr, nil, tigon2FwBssLen);
-
-	/*
-	 * we will eventually get events telling us that the firmware is
-	 * up and that the link is up.
-	 */
-	return 0;
-}
-
-static void
-ga620pci(void)
-{
-	int port;
-	Pcidev *p;
-	Ctlr *ctlr;
-
-	p = nil;
-	while(p = pcimatch(p, 0, 0)){
-		if(p->ccrb != 0x02 || p->ccru != 0)
-			continue;
-
-		switch(p->did<<16 | p->vid){
-		default:
-			continue;
-		case 0x620A<<16 | 0x1385:	/* Netgear GA620 fiber */
-		case 0x630A<<16 | 0x1385:	/* Netgear GA620T copper */
-		case 0x0001<<16 | 0x12AE:	/* Alteon Acenic fiber
-						 * and DEC DEGPA-SA */
-		case 0x0002<<16 | 0x12AE:	/* Alteon Acenic copper */
-		case 0x0009<<16 | 0x10A9:	/* SGI Acenic */
-			break;
-		}
-
-		port = upamalloc(p->mem[0].bar & ~0x0F, p->mem[0].size, 0);
-		if(port == 0){
-			print("ga620: can't map %d @ 0x%8.8luX\n",
-				p->mem[0].size, p->mem[0].bar);
-			continue;
-		}
-
-		ctlr = malloc(sizeof(Ctlr));
-		ctlr->port = port;
-		ctlr->pcidev = p;
-		ctlr->id = p->did<<16 | p->vid;
-
-		ctlr->nic = KADDR(ctlr->port);
-		if(ga620reset(ctlr)){
-			free(ctlr);
-			continue;
-		}
-
-		if(ctlrhead != nil)
-			ctlrtail->next = ctlr;
-		else
-			ctlrhead = ctlr;
-		ctlrtail = ctlr;
-	}
-}
-
-int
-ga620pnp(Ether* edev)
-{
-	Ctlr *ctlr;
-	uchar ea[Eaddrlen];
-
-	if(ctlrhead == nil)
-		ga620pci();
-
-	/*
-	 * Any adapter matches if no edev->port is supplied,
-	 * otherwise the ports must match.
-	 */
-	for(ctlr = ctlrhead; ctlr != nil; ctlr = ctlr->next){
-		if(ctlr->active)
-			continue;
-		if(edev->port == 0 || edev->port == ctlr->port){
-			ctlr->active = 1;
-			break;
-		}
-	}
-	if(ctlr == nil)
-		return -1;
-
-	edev->ctlr = ctlr;
-	edev->port = ctlr->port;
-	edev->irq = ctlr->pcidev->intl;
-	edev->tbdf = ctlr->pcidev->tbdf;
-
-	/*
-	 * Check if the adapter's station address is to be overridden.
-	 * If not, read it from the EEPROM and set in ether->ea prior to
-	 * loading the station address in the hardware.
-	 */
-	memset(ea, 0, Eaddrlen);
-	if(memcmp(ea, edev->ea, Eaddrlen) == 0)
-		memmove(edev->ea, ctlr->ea, Eaddrlen);
-
-	ga620init(edev);		/* enables interrupts */
-
-	/*
-	 * Linkage to the generic ethernet driver.
-	 */
-	edev->attach = ga620attach;
-	edev->transmit = ga620transmit;
-	edev->interrupt = ga620interrupt;
-	edev->detach = ga620shutdown;
-	return 0;
-}
--- a/os/boot/pc/etherga620fw.h
+++ /dev/null
@@ -1,4858 +1,0 @@
-/* Generated by genfw.c */
-#define tigon2FwReleaseMajor 0xc
-#define tigon2FwReleaseMinor 0x4
-#define tigon2FwReleaseFix 0xb
-#define tigon2FwStartAddr 0x00004000
-#define tigon2FwTextAddr 0x00004000
-#define tigon2FwTextLen 0x11bc0
-#define tigon2FwRodataAddr 0x00015bc0
-#define tigon2FwRodataLen 0x10d0
-#define tigon2FwDataAddr 0x00016cc0
-#define tigon2FwDataLen 0x1c0
-#define tigon2FwSbssAddr 0x00016e80
-#define tigon2FwSbssLen 0xcc
-#define tigon2FwBssAddr 0x00016f50
-#define tigon2FwBssLen 0x20c0
-static int tigon2FwText[/*(MAX_TEXT_LEN/4) + 1*/] = {
-0x0, 
-0x10000003, 0x0, 0xd, 0xd, 
-0x3c1d0001, 0x8fbd6d20, 0x3a0f021, 0x3c100000, 
-0x26104000, 0xc0010c0, 0x0, 0xd, 
-0x3c1d0001, 0x8fbd6d24, 0x3a0f021, 0x3c100000, 
-0x26104000, 0xc0017e0, 0x0, 0xd, 
-0x0, 0x0, 0x0, 0x0, 
-0x0, 0x0, 0x0, 0x0, 
-0x0, 0x0, 0x0, 0x0, 
-0x0, 0x0, 0x0, 0x0, 
-0x0, 0x0, 0x0, 0x0, 
-0x0, 0x0, 0x0, 0x0, 
-0x0, 0x0, 0x0, 0x0, 
-0x0, 0x0, 0x0, 0x0, 
-0x0, 0x0, 0x0, 0x0, 
-0x0, 0x0, 0x0, 0x0, 
-0x0, 0x0, 0x0, 0x2000008, 
-0x0, 0x800172f, 0x3c0a0001, 0x800172f, 
-0x3c0a0002, 0x800172f, 0x0, 0x8002cac, 
-0x0, 0x8002c4f, 0x0, 0x800172f, 
-0x3c0a0004, 0x800328a, 0x0, 0x8001a52, 
-0x0, 0x800394d, 0x0, 0x80038f4, 
-0x0, 0x800172f, 0x3c0a0006, 0x80039bb, 
-0x3c0a0007, 0x800172f, 0x3c0a0008, 0x800172f, 
-0x3c0a0009, 0x8003a13, 0x0, 0x8002ea6, 
-0x0, 0x800172f, 0x3c0a000b, 0x800172f, 
-0x3c0a000c, 0x800172f, 0x3c0a000d, 0x80028fb, 
-0x0, 0x8002890, 0x0, 0x800172f, 
-0x3c0a000e, 0x800208c, 0x0, 0x8001964, 
-0x0, 0x8001a04, 0x0, 0x8003ca6, 
-0x0, 0x8003c94, 0x0, 0x800172f, 
-0x0, 0x800191a, 0x0, 0x800172f, 
-0x0, 0x800172f, 0x3c0a0013, 0x800172f, 
-0x3c0a0014, 0x0, 0x0, 0x0, 
-0x0, 0x0, 0x0, 0x0, 
-0x0, 0x0, 0x0, 0x0, 
-0x0, 0x0, 0x0, 0x0, 
-0x0, 0x0, 0x0, 0x0, 
-0x0, 0x0, 0x0, 0x0, 
-0x0, 0x0, 0x0, 0x0, 
-0x0, 0x0, 0x0, 0x0, 
-0x0, 0x0, 0x0, 0x0, 
-0x0, 0x0, 0x0, 0x0, 
-0x0, 0x0, 0x0, 0x0, 
-0x0, 0x0, 0x0, 0x0, 
-0x0, 0x0, 0x0, 0x0, 
-0x0, 0x0, 0x0, 0x0, 
-0x0, 0x0, 0x0, 0x0, 
-0x0, 0x0, 0x0, 0x27bdffe0, 
-0x3c1cc000, 0xafbf001c, 0xafb00018, 0x8f820140, 
-0x24030003, 0xaf8300ec, 0x34420004, 0xc002b20, 
-0xaf820140, 0x3c0100c0, 0xc001763, 0xac203ffc, 
-0x401821, 0x3c020010, 0x3c010001, 0xac236e9c, 
-0x10620011, 0x43102b, 0x14400002, 0x3c020020, 
-0x3c020008, 0x1062000c, 0x24050100, 0x3c060001, 
-0x8cc66e9c, 0x3c040001, 0x24845c74, 0x3821, 
-0xafa00010, 0xc002b3b, 0xafa00014, 0x3c020020, 
-0x3c010001, 0xac226e9c, 0x24020008, 0x3c010001, 
-0xac226eb4, 0x2402001f, 0x3c010001, 0xac226ec4, 
-0x24020016, 0x3c010001, 0xac226e98, 0x3c05fffe, 
-0x34a56f08, 0x3c020001, 0x8c426e9c, 0x3c030002, 
-0x24639010, 0x3c040001, 0x8c846cc4, 0x431023, 
-0x14800002, 0x458021, 0x2610fa38, 0x2402f000, 
-0x2028024, 0xc001785, 0x2002021, 0x2022823, 
-0x3c040020, 0x821823, 0x651823, 0x247bb000, 
-0x3c03fffe, 0x3463bf08, 0x363b821, 0x3c0600bf, 
-0x34c6f000, 0x3c070001, 0x8ce76cc0, 0x3c0300bf, 
-0x3463e000, 0x852023, 0x3c010001, 0xac246ea8, 
-0x822023, 0x3c010001, 0xac256e90, 0x52842, 
-0x3c010001, 0xac226e84, 0x27620ffc, 0x3c010001, 
-0xac226d20, 0x27621ffc, 0xdb3023, 0x7b1823, 
-0x3c010001, 0xac246e88, 0x3c010001, 0xac256eac, 
-0x3c010001, 0xac226d24, 0xaf860150, 0x10e00011, 
-0xaf830250, 0x3c1d0001, 0x8fbd6ccc, 0x3a0f021, 
-0xc001749, 0x0, 0x3c020001, 0x8c426cd0, 
-0x3c030001, 0x8c636cd4, 0x2442fe00, 0x24630200, 
-0x3c010001, 0xac226cd0, 0x3c010001, 0x10000004, 
-0xac236cd4, 0x3c1d0001, 0x8fbd6d20, 0x3a0f021, 
-0x3c020001, 0x8c426cc4, 0x1040000d, 0x26fafa38, 
-0x3c020001, 0x8c426cd0, 0x3c030001, 0x8c636cd4, 
-0x3c1a0001, 0x8f5a6cd4, 0x2442fa38, 0x246305c8, 
-0x3c010001, 0xac226cd0, 0x3c010001, 0xac236cd4, 
-0x3c020001, 0x8c426cc8, 0x14400003, 0x0, 
-0x3c010001, 0xac206cd0, 0xc001151, 0x0, 
-0x8fbf001c, 0x8fb00018, 0x3e00008, 0x27bd0020, 
-0x3c020001, 0x8c426cd0, 0x3c030001, 0x8c636cd4, 
-0x27bdff98, 0xafb00048, 0x3c100001, 0x8e1066b8, 
-0xafb20050, 0x3c120000, 0x26524100, 0xafbf0060, 
-0xafbe005c, 0xafb50058, 0xafb30054, 0xafb1004c, 
-0xafa20034, 0xafa30030, 0xafa00010, 0xafa00014, 
-0x8f860040, 0x3c040001, 0x24845c80, 0x24050200, 
-0x3c010001, 0xac326e80, 0xc002b3b, 0x2003821, 
-0x8f830040, 0x3c02f000, 0x621824, 0x3c026000, 
-0x1062000b, 0xa3a0003f, 0x240e0001, 0x3c040001, 
-0x24845c88, 0xa3ae003f, 0xafa00010, 0xafa00014, 
-0x8f860040, 0x24050300, 0xc002b3b, 0x2003821, 
-0x8f820240, 0x3c030001, 0x431025, 0xaf820240, 
-0xaf800048, 0x8f820048, 0x14400005, 0x0, 
-0xaf800048, 0x8f820048, 0x10400004, 0x0, 
-0xaf800048, 0x10000003, 0x2e02021, 0xaf80004c, 
-0x2e02021, 0x3c050001, 0xc002ba8, 0x34a540f8, 
-0x3402021, 0xc002ba8, 0x240505c8, 0x3c020001, 
-0x8c426ea8, 0x3c0d0001, 0x8dad6e88, 0x3c030001, 
-0x8c636e84, 0x3c080001, 0x8d086e90, 0x3c090001, 
-0x8d296eac, 0x3c0a0001, 0x8d4a6eb4, 0x3c0b0001, 
-0x8d6b6ec4, 0x3c0c0001, 0x8d8c6e98, 0x3c040001, 
-0x24845c94, 0x24050400, 0xaf42013c, 0x8f42013c, 
-0x24060001, 0x24070001, 0xaf400000, 0xaf4d0138, 
-0xaf430144, 0xaf480148, 0xaf49014c, 0xaf4a0150, 
-0xaf4b0154, 0xaf4c0158, 0x2442ff80, 0xaf420140, 
-0x24020001, 0xafa20010, 0xc002b3b, 0xafa00014, 
-0x8f420138, 0xafa20010, 0x8f42013c, 0xafa20014, 
-0x8f460144, 0x8f470148, 0x3c040001, 0x24845ca0, 
-0xc002b3b, 0x24050500, 0xafb70010, 0xafba0014, 
-0x8f46014c, 0x8f470150, 0x3c040001, 0x24845cac, 
-0xc002b3b, 0x24050600, 0x3c020001, 0x8c426e9c, 
-0x3603821, 0x3c060002, 0x24c69010, 0x2448ffff, 
-0x1061824, 0xe81024, 0x43102b, 0x10400006, 
-0x24050900, 0x3c040001, 0x24845cb8, 0xafa80010, 
-0xc002b3b, 0xafa00014, 0x8f82000c, 0xafa20010, 
-0x8f82003c, 0xafa20014, 0x8f860000, 0x8f870004, 
-0x3c040001, 0x24845cc4, 0xc002b3b, 0x24051000, 
-0x8c020220, 0x8c030224, 0x8c060218, 0x8c07021c, 
-0x3c040001, 0x24845ccc, 0x24051100, 0xafa20010, 
-0xc002b3b, 0xafa30014, 0xaf800054, 0xaf80011c, 
-0x8c020218, 0x30420002, 0x10400009, 0x0, 
-0x8c020220, 0x3c030002, 0x34630004, 0x431025, 
-0xaf42000c, 0x8c02021c, 0x10000008, 0x34420004, 
-0x8c020220, 0x3c030002, 0x34630006, 0x431025, 
-0xaf42000c, 0x8c02021c, 0x34420006, 0xaf420014, 
-0x8c020218, 0x30420010, 0x1040000a, 0x0, 
-0x8c02021c, 0x34420004, 0xaf420010, 0x8c020220, 
-0x3c03000a, 0x34630004, 0x431025, 0x10000009, 
-0xaf420008, 0x8c020220, 0x3c03000a, 0x34630006, 
-0x431025, 0xaf420008, 0x8c02021c, 0x34420006, 
-0xaf420010, 0x24020001, 0xaf8200a0, 0xaf8200b0, 
-0x8f830054, 0x8f820054, 0xaf8000d0, 0xaf8000c0, 
-0x10000002, 0x24630064, 0x8f820054, 0x621023, 
-0x2c420065, 0x1440fffc, 0x0, 0x8c040208, 
-0x8c05020c, 0x26e20028, 0xaee20020, 0x24020490, 
-0xaee20010, 0xaee40008, 0xaee5000c, 0x26e40008, 
-0x8c820000, 0x8c830004, 0xaf820090, 0xaf830094, 
-0x8c820018, 0xaf8200b4, 0x9482000a, 0xaf82009c, 
-0x8f420014, 0xaf8200b0, 0x8f8200b0, 0x30420004, 
-0x1440fffd, 0x0, 0x8f8200b0, 0x3c03ef00, 
-0x431024, 0x10400021, 0x0, 0x8f8200b4, 
-0xafa20010, 0x8f820090, 0x8f830094, 0x3c040001, 
-0x24845cd4, 0xafa30014, 0x8f8600b0, 0x8f87009c, 
-0x3c050001, 0xc002b3b, 0x34a5200d, 0x3c040001, 
-0x24845ce0, 0x240203c0, 0xafa20010, 0xafa00014, 
-0x8f860144, 0x3c070001, 0x24e75ce8, 0xc002b3b, 
-0x3405dead, 0x8f82011c, 0x34420002, 0xaf82011c, 
-0x8f820220, 0x34420004, 0xaf820220, 0x8f820140, 
-0x3c030001, 0x431025, 0xaf820140, 0x96e20472, 
-0x96e60452, 0x96e70462, 0xafa20010, 0x96e20482, 
-0x3c040001, 0x24845d14, 0x24051200, 0xc002b3b, 
-0xafa20014, 0x96f00452, 0x32020001, 0x10400002, 
-0xb021, 0x24160001, 0x32020002, 0x54400001, 
-0x36d60002, 0x32020008, 0x54400001, 0x36d60004, 
-0x32020010, 0x54400001, 0x36d60008, 0x32020020, 
-0x54400001, 0x36d60010, 0x32020040, 0x54400001, 
-0x36d60020, 0x32020080, 0x54400001, 0x36d60040, 
-0x96e60482, 0x30c20200, 0x54400001, 0x36d64000, 
-0x96e30472, 0x30620200, 0x10400003, 0x30620100, 
-0x10000003, 0x36d62000, 0x54400001, 0x36d61000, 
-0x96f00462, 0x32c24000, 0x14400004, 0x3207009b, 
-0x30c2009b, 0x14e20007, 0x240e0001, 0x32c22000, 
-0x1440000d, 0x32020001, 0x3062009b, 0x10e20009, 
-0x240e0001, 0x3c040001, 0x24845d20, 0x24051300, 
-0x2003821, 0xa3ae003f, 0xafa30010, 0xc002b3b, 
-0xafa00014, 0x32020001, 0x54400001, 0x36d60080, 
-0x32020002, 0x54400001, 0x36d60100, 0x32020008, 
-0x54400001, 0x36d60200, 0x32020010, 0x54400001, 
-0x36d60400, 0x32020080, 0x54400001, 0x36d60800, 
-0x8c020218, 0x30420200, 0x10400002, 0x3c020008, 
-0x2c2b025, 0x8c020218, 0x30420800, 0x10400002, 
-0x3c020080, 0x2c2b025, 0x8c020218, 0x30420400, 
-0x10400002, 0x3c020100, 0x2c2b025, 0x8c020218, 
-0x30420100, 0x10400002, 0x3c020200, 0x2c2b025, 
-0x8c020218, 0x30420080, 0x10400002, 0x3c020400, 
-0x2c2b025, 0x8c020218, 0x30422000, 0x10400002, 
-0x3c020010, 0x2c2b025, 0x8c020218, 0x30424000, 
-0x10400002, 0x3c020020, 0x2c2b025, 0x8c020218, 
-0x30421000, 0x10400002, 0x3c020040, 0x2c2b025, 
-0x8ee20498, 0x8ee3049c, 0xaf420160, 0xaf430164, 
-0x8ee204a0, 0x8ee304a4, 0xaf420168, 0xaf43016c, 
-0x8ee204a8, 0x8ee304ac, 0xaf420170, 0xaf430174, 
-0x8ee20428, 0x8ee3042c, 0xaf420178, 0xaf43017c, 
-0x8ee20448, 0x8ee3044c, 0xaf420180, 0xaf430184, 
-0x8ee20458, 0x8ee3045c, 0xaf420188, 0xaf43018c, 
-0x8ee20468, 0x8ee3046c, 0xaf420190, 0xaf430194, 
-0x8ee20478, 0x8ee3047c, 0xaf420198, 0xaf43019c, 
-0x8ee20488, 0x8ee3048c, 0xaf4201a0, 0xaf4301a4, 
-0x8ee204b0, 0x8ee304b4, 0x24040080, 0xaf4201a8, 
-0xaf4301ac, 0xc002ba8, 0x24050080, 0x8c02025c, 
-0x27440224, 0xaf4201f0, 0x8c020260, 0x24050200, 
-0x24060008, 0xc002bbf, 0xaf4201f8, 0x3c043b9a, 
-0x3484ca00, 0x3821, 0x24020006, 0x24030002, 
-0xaf4201f4, 0x240203e8, 0xaf430204, 0xaf430200, 
-0xaf4401fc, 0xaf420294, 0x24020001, 0xaf430290, 
-0xaf42029c, 0x3c030001, 0x671821, 0x90636cd8, 
-0x3471021, 0x24e70001, 0xa043022c, 0x2ce2000f, 
-0x1440fff8, 0x3471821, 0x24e70001, 0x3c080001, 
-0x350840f8, 0x8f820040, 0x3c040001, 0x24845d2c, 
-0x24051400, 0x21702, 0x24420030, 0xa062022c, 
-0x3471021, 0xa040022c, 0x8c070218, 0x2c03021, 
-0x240205c8, 0xafa20010, 0xc002b3b, 0xafa80014, 
-0x3c040001, 0x24845d38, 0x3c050000, 0x24a55c80, 
-0x24060010, 0x27b10030, 0x2203821, 0x27b30034, 
-0xc0017a3, 0xafb30010, 0x3c030001, 0x8c636cc8, 
-0x1060000a, 0x408021, 0x8fa30030, 0x2405ff00, 
-0x8fa20034, 0x246400ff, 0x852024, 0x831823, 
-0x431023, 0xafa20034, 0xafa40030, 0x3c040001, 
-0x24845d44, 0x3c050000, 0x24a54100, 0x24060108, 
-0x2203821, 0xc0017a3, 0xafb30010, 0x409021, 
-0x32c20003, 0x3c010001, 0xac326e80, 0x10400045, 
-0x2203821, 0x8f820050, 0x3c030010, 0x431024, 
-0x10400016, 0x0, 0x8c020218, 0x30420040, 
-0x1040000f, 0x24020001, 0x8f820050, 0x8c030218, 
-0x240e0001, 0x3c040001, 0x24845d50, 0xa3ae003f, 
-0xafa20010, 0xafa30014, 0x8f870040, 0x24051500, 
-0xc002b3b, 0x2c03021, 0x10000004, 0x0, 
-0x3c010001, 0x370821, 0xa02240f4, 0x3c040001, 
-0x24845d5c, 0x3c050001, 0x24a55b40, 0x3c060001, 
-0x24c65bac, 0xc53023, 0x8f420010, 0x27b30030, 
-0x2603821, 0x27b10034, 0x34420a00, 0xaf420010, 
-0xc0017a3, 0xafb10010, 0x3c040001, 0x24845d70, 
-0x3c050001, 0x24a5b714, 0x3c060001, 0x24c6ba90, 
-0xc53023, 0x2603821, 0xaf420108, 0xc0017a3, 
-0xafb10010, 0x3c040001, 0x24845d8c, 0x3c050001, 
-0x24a5be58, 0x3c060001, 0x24c6c900, 0xc53023, 
-0x2603821, 0x3c010001, 0xac226ef4, 0xc0017a3, 
-0xafb10010, 0x3c040001, 0x24845da4, 0x10000024, 
-0x24051600, 0x3c040001, 0x24845dac, 0x3c050001, 
-0x24a5a10c, 0x3c060001, 0x24c6a238, 0xc53023, 
-0xc0017a3, 0xafb30010, 0x3c040001, 0x24845dbc, 
-0x3c050001, 0x24a5b2b0, 0x3c060001, 0x24c6b70c, 
-0xc53023, 0x2203821, 0xaf420108, 0xc0017a3, 
-0xafb30010, 0x3c040001, 0x24845dd0, 0x3c050001, 
-0x24a5ba98, 0x3c060001, 0x24c6be50, 0xc53023, 
-0x2203821, 0x3c010001, 0xac226ef4, 0xc0017a3, 
-0xafb30010, 0x3c040001, 0x24845de4, 0x24051650, 
-0x2c03021, 0x3821, 0x3c010001, 0xac226ef8, 
-0xafa00010, 0xc002b3b, 0xafa00014, 0x32c20020, 
-0x10400021, 0x27a70030, 0x3c040001, 0x24845df0, 
-0x3c050001, 0x24a5b13c, 0x3c060001, 0x24c6b2a8, 
-0xc53023, 0x24022000, 0xaf42001c, 0x27a20034, 
-0xc0017a3, 0xafa20010, 0x21900, 0x31982, 
-0x3c040800, 0x641825, 0xae430028, 0x24030010, 
-0xaf43003c, 0x96e30450, 0xaf430040, 0x8f430040, 
-0x3c040001, 0x24845e04, 0xafa00014, 0xafa30010, 
-0x8f47001c, 0x24051660, 0x3c010001, 0xac226ef0, 
-0x10000025, 0x32c60020, 0x8ee20448, 0x8ee3044c, 
-0xaf43001c, 0x8f42001c, 0x2442e000, 0x2c422001, 
-0x1440000a, 0x240e0001, 0x3c040001, 0x24845e10, 
-0xa3ae003f, 0xafa00010, 0xafa00014, 0x8f46001c, 
-0x24051700, 0xc002b3b, 0x3821, 0x3c020000, 
-0x24425cbc, 0x21100, 0x21182, 0x3c030800, 
-0x431025, 0xae420028, 0x24020008, 0xaf42003c, 
-0x96e20450, 0xaf420040, 0x8f420040, 0x3c040001, 
-0x24845e1c, 0xafa00014, 0xafa20010, 0x8f47001c, 
-0x24051800, 0x32c60020, 0xc002b3b, 0x0, 
-0x3c050fff, 0x3c030001, 0x8c636ef4, 0x34a5ffff, 
-0x2403021, 0x3c020001, 0x8c426ef8, 0x3c040800, 
-0x651824, 0x31882, 0x641825, 0x451024, 
-0x21082, 0x441025, 0xacc20080, 0x32c20180, 
-0x10400056, 0xacc30020, 0x8f82005c, 0x3c030080, 
-0x431024, 0x1040000d, 0x0, 0x8f820050, 
-0xafa20010, 0x8f82005c, 0x240e0001, 0x3c040001, 
-0x24845e28, 0xa3ae003f, 0xafa20014, 0x8f870040, 
-0x24051900, 0xc002b3b, 0x2c03021, 0x8f820050, 
-0x3c030010, 0x431024, 0x10400016, 0x0, 
-0x8c020218, 0x30420040, 0x1040000f, 0x24020001, 
-0x8f820050, 0x8c030218, 0x240e0001, 0x3c040001, 
-0x24845d50, 0xa3ae003f, 0xafa20010, 0xafa30014, 
-0x8f870040, 0x24052000, 0xc002b3b, 0x2c03021, 
-0x10000004, 0x0, 0x3c010001, 0x370821, 
-0xa02240f4, 0x3c040001, 0x24845e34, 0x3c050001, 
-0x24a55ac0, 0x3c060001, 0x24c65b38, 0xc53023, 
-0x8f420008, 0x27b30030, 0x2603821, 0x27b10034, 
-0x34420e00, 0xaf420008, 0xc0017a3, 0xafb10010, 
-0x3c040001, 0x24845e4c, 0x3c050001, 0x24a5d8b4, 
-0x3c060001, 0x24c6e3c8, 0xc53023, 0x2603821, 
-0xaf42010c, 0xc0017a3, 0xafb10010, 0x3c040001, 
-0x24845e64, 0x3c050001, 0x24a5e9ac, 0x3c060001, 
-0x24c6f0f0, 0xc53023, 0x2603821, 0x3c010001, 
-0xac226f04, 0xc0017a3, 0xafb10010, 0x3c040001, 
-0x24845e7c, 0x10000027, 0x24052100, 0x3c040001, 
-0x24845e84, 0x3c050001, 0x24a59fc8, 0x3c060001, 
-0x24c6a104, 0xc53023, 0x27b10030, 0x2203821, 
-0x27b30034, 0xc0017a3, 0xafb30010, 0x3c040001, 
-0x24845e94, 0x3c050001, 0x24a5cad4, 0x3c060001, 
-0x24c6d8ac, 0xc53023, 0x2203821, 0xaf42010c, 
-0xc0017a3, 0xafb30010, 0x3c040001, 0x24845ea4, 
-0x3c050001, 0x24a5e84c, 0x3c060001, 0x24c6e9a4, 
-0xc53023, 0x2203821, 0x3c010001, 0xac226f04, 
-0xc0017a3, 0xafb30010, 0x3c040001, 0x24845eb8, 
-0x24052150, 0x2c03021, 0x3821, 0x3c010001, 
-0xac226f10, 0xafa00010, 0xc002b3b, 0xafa00014, 
-0x3c110fff, 0x3c030001, 0x8c636f04, 0x3631ffff, 
-0x2409821, 0x3c020001, 0x8c426f10, 0x3c0e0800, 
-0x711824, 0x31882, 0x6e1825, 0x511024, 
-0x21082, 0x4e1025, 0xae630038, 0xae620078, 
-0x8c020218, 0x30420040, 0x14400004, 0x24020001, 
-0x3c010001, 0x370821, 0xa02240f4, 0x3c040001, 
-0x24845ec4, 0x3c050001, 0x24a5e3d0, 0x3c060001, 
-0x24c6e52c, 0xc53023, 0x27be0030, 0x3c03821, 
-0x27b50034, 0xc0017a3, 0xafb50010, 0x3c010001, 
-0xac226efc, 0x511024, 0x21082, 0x3c0e0800, 
-0x4e1025, 0xae620050, 0x32c22000, 0x10400006, 
-0x3c03821, 0x3c020000, 0x24425cbc, 0x2221024, 
-0x1000000f, 0x21082, 0x3c040001, 0x24845ed8, 
-0x3c050001, 0x24a5e534, 0x3c060001, 0x24c6e6e4, 
-0xc53023, 0xc0017a3, 0xafb50010, 0x3c010001, 
-0xac226f14, 0x511024, 0x21082, 0x3c0e0800, 
-0x4e1025, 0xae620048, 0x32c24000, 0x10400005, 
-0x27a70030, 0x3c020000, 0x24425cbc, 0x1000000e, 
-0x21100, 0x3c040001, 0x24845ef0, 0x3c050001, 
-0x24a5e6ec, 0x3c060001, 0x24c6e844, 0xc53023, 
-0x27a20034, 0xc0017a3, 0xafa20010, 0x3c010001, 
-0xac226f08, 0x21100, 0x21182, 0x3c030800, 
-0x431025, 0xae420060, 0x3c040001, 0x24845f08, 
-0x3c050001, 0x24a58230, 0x3c060001, 0x24c68650, 
-0xc53023, 0x27b10030, 0x2203821, 0x27b30034, 
-0xc0017a3, 0xafb30010, 0x3c0e0fff, 0x35ceffff, 
-0x3c040001, 0x24845f14, 0x3c050000, 0x24a56468, 
-0x3c060000, 0x24c66588, 0xc53023, 0x2203821, 
-0x240f021, 0x3c010001, 0xac226edc, 0x4e1024, 
-0x21082, 0x3c150800, 0x551025, 0xafae0044, 
-0xafc200b8, 0xc0017a3, 0xafb30010, 0x3c040001, 
-0x24845f20, 0x3c050000, 0x24a56590, 0x3c060000, 
-0x24c66808, 0x8fae0044, 0xc53023, 0x2203821, 
-0x3c010001, 0xac226ed0, 0x4e1024, 0x21082, 
-0x551025, 0xafc200e8, 0xc0017a3, 0xafb30010, 
-0x3c040001, 0x24845f38, 0x3c050000, 0x24a56810, 
-0x3c060000, 0x24c66940, 0x8fae0044, 0xc53023, 
-0x2203821, 0x3c010001, 0xac226ec8, 0x4e1024, 
-0x21082, 0x551025, 0xafc200c0, 0xc0017a3, 
-0xafb30010, 0x3c040001, 0x24845f50, 0x3c050001, 
-0x24a5fad0, 0x3c060001, 0x24c6fba8, 0x8fae0044, 
-0xc53023, 0x2203821, 0x3c010001, 0xac226ed4, 
-0x4e1024, 0x21082, 0x551025, 0xafc200c8, 
-0xc0017a3, 0xafb30010, 0x3c040001, 0x24845f5c, 
-0x3c050001, 0x24a5c93c, 0x3c060001, 0x24c6ca20, 
-0xc53023, 0x2203821, 0xaf420110, 0xc0017a3, 
-0xafb30010, 0x3c040001, 0x24845f6c, 0x3c050001, 
-0x24a5c910, 0x3c060001, 0x24c6c934, 0xc53023, 
-0x2203821, 0xaf420124, 0xc0017a3, 0xafb30010, 
-0x3c040001, 0x24845f7c, 0x3c050001, 0x24a55a80, 
-0x3c060001, 0x24c65aac, 0xc53023, 0x2203821, 
-0xaf420120, 0xaf420114, 0xc0017a3, 0xafb30010, 
-0x3c040001, 0x24845f88, 0x3c050001, 0x24a5f298, 
-0x3c060001, 0x24c6f6b4, 0xc53023, 0x2203821, 
-0xaf420118, 0xc0017a3, 0xafb30010, 0x8fae0044, 
-0x3c010001, 0xac226f18, 0x4e1024, 0x21082, 
-0x551025, 0xc003fc3, 0xafc200d0, 0xc003c40, 
-0x0, 0xc0027a8, 0x0, 0xac000228, 
-0xac00022c, 0x96e20450, 0x2442ffff, 0xaf420038, 
-0x96e20460, 0xaf420080, 0x32c24000, 0x14400003, 
-0x0, 0x96e20480, 0xaf420084, 0x96e70490, 
-0x50e00001, 0x24070800, 0x24e2ffff, 0xaf420088, 
-0xaf42007c, 0x24020800, 0x10e2000f, 0x32c24000, 
-0x10400003, 0x24020400, 0x10e2000b, 0x0, 
-0x240e0001, 0x3c040001, 0x24845f98, 0xa3ae003f, 
-0x96e60490, 0x24052170, 0x2c03821, 0xafa00010, 
-0xc002b3b, 0xafa00014, 0x8f430138, 0x8f440138, 
-0x24020001, 0xa34205c2, 0xaf430094, 0xaf440098, 
-0xafa00010, 0xafa00014, 0x8f460080, 0x8f470084, 
-0x3c040001, 0x24845fa4, 0xc002b3b, 0x24052200, 
-0xc0024a4, 0x3c110800, 0x3c1433d8, 0x3694cb58, 
-0x3c020800, 0x34420080, 0x3c040001, 0x24845fb0, 
-0x3c050000, 0x24a55d00, 0x3c060000, 0x24c65d1c, 
-0xc53023, 0x27a70030, 0xaf820060, 0x2402ffff, 
-0xaf820064, 0x27a20034, 0xc0017a3, 0xafa20010, 
-0x3c010001, 0xac226eb8, 0x21100, 0x21182, 
-0x511025, 0xc0018fc, 0xae420000, 0x8f820240, 
-0x3c030001, 0x431025, 0xaf820240, 0x3c020000, 
-0x24424034, 0xaf820244, 0xaf800240, 0x8f820060, 
-0x511024, 0x14400005, 0x3c030800, 0x8f820060, 
-0x431024, 0x1040fffd, 0x0, 0xc003c4d, 
-0x8821, 0x3c020100, 0xafa20020, 0x8f530018, 
-0x240200ff, 0x56620001, 0x26710001, 0x8c020228, 
-0x1622000e, 0x1330c0, 0x8f42033c, 0x24420001, 
-0xaf42033c, 0x8f42033c, 0x8c020228, 0x3c040001, 
-0x24845c24, 0x3c050009, 0xafa00014, 0xafa20010, 
-0x8fa60020, 0x1000003f, 0x34a50100, 0xd71021, 
-0x8fa30020, 0x8fa40024, 0xac4304c0, 0xac4404c4, 
-0xc01821, 0x8f440178, 0x8f45017c, 0x1021, 
-0x24070004, 0xafa70010, 0xafb10014, 0x8f48000c, 
-0x24c604c0, 0x2e63021, 0xafa80018, 0x8f48010c, 
-0x24070008, 0xa32821, 0xa3482b, 0x822021, 
-0x100f809, 0x892021, 0x1440000b, 0x24070008, 
-0x8f820120, 0xafa20010, 0x8f820124, 0x3c040001, 
-0x24845c2c, 0x3c050009, 0xafa20014, 0x8fa60020, 
-0x1000001c, 0x34a50200, 0x8f440160, 0x8f450164, 
-0x8f43000c, 0xaf510018, 0x8f860120, 0x24020010, 
-0xafa20010, 0xafb10014, 0xafa30018, 0x8f42010c, 
-0x40f809, 0x24c6001c, 0x14400010, 0x0, 
-0x8f420340, 0x24420001, 0xaf420340, 0x8f420340, 
-0x8f820120, 0xafa20010, 0x8f820124, 0x3c040001, 
-0x24845c34, 0x3c050009, 0xafa20014, 0x8fa60020, 
-0x34a50300, 0xc002b3b, 0x2603821, 0x8f4202e4, 
-0x24420001, 0xaf4202e4, 0x8f4202e4, 0x93a2003f, 
-0x10400069, 0x3c020700, 0x34423000, 0xafa20028, 
-0x8f530018, 0x240200ff, 0x12620002, 0x8821, 
-0x26710001, 0x8c020228, 0x1622000e, 0x1330c0, 
-0x8f42033c, 0x24420001, 0xaf42033c, 0x8f42033c, 
-0x8c020228, 0x3c040001, 0x24845c24, 0x3c050009, 
-0xafa00014, 0xafa20010, 0x8fa60028, 0x1000003f, 
-0x34a50100, 0xd71021, 0x8fa30028, 0x8fa4002c, 
-0xac4304c0, 0xac4404c4, 0xc01821, 0x8f440178, 
-0x8f45017c, 0x1021, 0x24070004, 0xafa70010, 
-0xafb10014, 0x8f48000c, 0x24c604c0, 0x2e63021, 
-0xafa80018, 0x8f48010c, 0x24070008, 0xa32821, 
-0xa3482b, 0x822021, 0x100f809, 0x892021, 
-0x1440000b, 0x24070008, 0x8f820120, 0xafa20010, 
-0x8f820124, 0x3c040001, 0x24845c2c, 0x3c050009, 
-0xafa20014, 0x8fa60028, 0x1000001c, 0x34a50200, 
-0x8f440160, 0x8f450164, 0x8f43000c, 0xaf510018, 
-0x8f860120, 0x24020010, 0xafa20010, 0xafb10014, 
-0xafa30018, 0x8f42010c, 0x40f809, 0x24c6001c, 
-0x14400010, 0x0, 0x8f420340, 0x24420001, 
-0xaf420340, 0x8f420340, 0x8f820120, 0xafa20010, 
-0x8f820124, 0x3c040001, 0x24845c34, 0x3c050009, 
-0xafa20014, 0x8fa60028, 0x34a50300, 0xc002b3b, 
-0x2603821, 0x8f4202f0, 0x24420001, 0xaf4202f0, 
-0x8f4202f0, 0x3c040001, 0x24845fc0, 0xafa00010, 
-0xafa00014, 0x8fa60028, 0x24052300, 0xc002b3b, 
-0x3821, 0x10000004, 0x0, 0x8c020264, 
-0x10400005, 0x0, 0x8f8200a0, 0x30420004, 
-0x1440fffa, 0x0, 0x8f820044, 0x34420004, 
-0xaf820044, 0x8f420308, 0x24420001, 0xaf420308, 
-0x8f420308, 0x8f8200d8, 0x8f8300d4, 0x431023, 
-0x2442ff80, 0xaf420090, 0x8f420090, 0x2842ff81, 
-0x10400006, 0x24020001, 0x8f420090, 0x8f430144, 
-0x431021, 0xaf420090, 0x24020001, 0xaf42008c, 
-0x32c20008, 0x10400006, 0x0, 0x8f820214, 
-0x3c038100, 0x3042ffff, 0x431025, 0xaf820214, 
-0x3c030001, 0x8c636d94, 0x30620002, 0x10400009, 
-0x30620001, 0x3c040001, 0x24845fcc, 0x3c050000, 
-0x24a56d50, 0x3c060000, 0x24c671c8, 0x10000012, 
-0xc53023, 0x10400009, 0x0, 0x3c040001, 
-0x24845fdc, 0x3c050000, 0x24a571d0, 0x3c060000, 
-0x24c67678, 0x10000008, 0xc53023, 0x3c040001, 
-0x24845fec, 0x3c050000, 0x24a56948, 0x3c060000, 
-0x24c66d48, 0xc53023, 0x27a70030, 0x27a20034, 
-0xc0017a3, 0xafa20010, 0x3c010001, 0xac226ecc, 
-0x3c020001, 0x8c426ecc, 0x3c030800, 0x21100, 
-0x21182, 0x431025, 0xae420040, 0x8f8200a0, 
-0xafa20010, 0x8f8200b0, 0xafa20014, 0x8f86005c, 
-0x8f87011c, 0x3c040001, 0x24845ffc, 0x3c010001, 
-0xac366ea4, 0x3c010001, 0xac206e94, 0x3c010001, 
-0xac3c6e8c, 0x3c010001, 0xac3b6ebc, 0x3c010001, 
-0xac376ec0, 0x3c010001, 0xac3a6ea0, 0xc002b3b, 
-0x24052400, 0x8f820200, 0xafa20010, 0x8f820220, 
-0xafa20014, 0x8f860044, 0x8f870050, 0x3c040001, 
-0x24846008, 0xc002b3b, 0x24052500, 0x8f830060, 
-0x74100b, 0x242000a, 0x200f821, 0x0, 
-0xd, 0x8fbf0060, 0x8fbe005c, 0x8fb50058, 
-0x8fb30054, 0x8fb20050, 0x8fb1004c, 0x8fb00048, 
-0x3e00008, 0x27bd0068, 0x27bdffe0, 0x3c040001, 
-0x24846014, 0x24052600, 0x3021, 0x3821, 
-0xafbf0018, 0xafa00010, 0xc002b3b, 0xafa00014, 
-0x8fbf0018, 0x3e00008, 0x27bd0020, 0x3e00008, 
-0x0, 0x3e00008, 0x0, 0x0, 
-0x0, 0x0, 0x0, 0x0, 
-0x3e00008, 0x0, 0x3e00008, 0x0, 
-0x27bdfde0, 0x27a50018, 0x3c04dead, 0x3484beef, 
-0xafbf0218, 0x8f820150, 0x3c03001f, 0x3463ffff, 
-0xafa40018, 0xa22823, 0xa32824, 0x8ca20000, 
-0x1044000a, 0x0, 0xafa50010, 0x8ca20000, 
-0xafa20014, 0x8f860150, 0x8f870250, 0x3c040001, 
-0x2484601c, 0xc002b3b, 0x24052700, 0x8fbf0218, 
-0x3e00008, 0x27bd0220, 0x27bdffe0, 0x3c06abba, 
-0x34c6babe, 0xafb00018, 0x3c100004, 0x3c07007f, 
-0x34e7ffff, 0xafbf001c, 0x102840, 0x8e040000, 
-0x8ca30000, 0xaca00000, 0xae060000, 0x8ca20000, 
-0xaca30000, 0x10460005, 0xae040000, 0xa08021, 
-0xf0102b, 0x1040fff5, 0x102840, 0x3c040001, 
-0x24846028, 0x24052800, 0x2003021, 0x3821, 
-0xafa00010, 0xc002b3b, 0xafa00014, 0x2001021, 
-0x8fbf001c, 0x8fb00018, 0x3e00008, 0x27bd0020, 
-0x8c020224, 0x3047003f, 0x10e00010, 0x803021, 
-0x2821, 0x24030020, 0xe31024, 0x10400002, 
-0x63042, 0xa62821, 0x31842, 0x1460fffb, 
-0xe31024, 0x2402f000, 0xa22824, 0x3402ffff, 
-0x45102b, 0x14400003, 0x3c020001, 0x10000008, 
-0x3c020001, 0x3442ffff, 0x851823, 0x43102b, 
-0x14400003, 0xa01021, 0x3c02fffe, 0x821021, 
-0x3e00008, 0x0, 0x27bdffd0, 0xafb50028, 
-0x8fb50040, 0xafb20020, 0xa09021, 0xafb1001c, 
-0x24c60003, 0xafbf002c, 0xafb30024, 0xafb00018, 
-0x8ea20000, 0x2403fffc, 0xc38024, 0x50102b, 
-0x1440001b, 0xe08821, 0x8e330000, 0xafb00010, 
-0x8ea20000, 0xafa20014, 0x8e270000, 0x24053000, 
-0xc002b3b, 0x2403021, 0x8e230000, 0x702021, 
-0x64102b, 0x10400007, 0x2402821, 0x8ca20000, 
-0xac620000, 0x24630004, 0x64102b, 0x1440fffb, 
-0x24a50004, 0x8ea20000, 0x501023, 0xaea20000, 
-0x8e220000, 0x501021, 0x1000000b, 0xae220000, 
-0x2402002d, 0xa0820000, 0xafb00010, 0x8ea20000, 
-0x2409821, 0xafa20014, 0x8e270000, 0x24053100, 
-0xc002b3b, 0x2603021, 0x2601021, 0x8fbf002c, 
-0x8fb50028, 0x8fb30024, 0x8fb20020, 0x8fb1001c, 
-0x8fb00018, 0x3e00008, 0x27bd0030, 0x27bdffe8, 
-0x3c1cc000, 0x3c05fffe, 0x3c030001, 0x8c636e84, 
-0x3c040001, 0x8c846e90, 0x34a5bf08, 0x24021ffc, 
-0x3c010001, 0xac226cd0, 0x3c0200c0, 0x3c010001, 
-0xac226cd4, 0x3c020020, 0xafbf0010, 0x3c0100c0, 
-0xac201ffc, 0x431023, 0x441023, 0x245bb000, 
-0x365b821, 0x3c1d0001, 0x8fbd6ccc, 0x3a0f021, 
-0x3c0400c0, 0x34840200, 0x3c1a00c0, 0x3c0300c0, 
-0x346307c8, 0x24021dfc, 0x3c010001, 0xac226cd0, 
-0x24021834, 0x3c010001, 0xac246cd4, 0x3c010001, 
-0xac226cd0, 0x3c010001, 0xac236cd4, 0xc00180d, 
-0x375a0200, 0x8fbf0010, 0x3e00008, 0x27bd0018, 
-0x27bdffc8, 0x3c040001, 0x24846034, 0x24053200, 
-0x3c020001, 0x8c426cd0, 0x3c030001, 0x8c636cd4, 
-0x3021, 0x3603821, 0xafbf0030, 0xafb3002c, 
-0xafb20028, 0xafb10024, 0xafb00020, 0xafa2001c, 
-0xafa30018, 0xafb70010, 0xc002b3b, 0xafba0014, 
-0xc001916, 0x0, 0x8f820240, 0x34420004, 
-0xaf820240, 0x24020001, 0xaf420000, 0x3c020001, 
-0x571021, 0x904240f4, 0x10400092, 0x2403fffc, 
-0x3c100001, 0x2610ac73, 0x3c120001, 0x2652a84c, 
-0x2121023, 0x438024, 0x8fa3001c, 0x3c040001, 
-0x24846040, 0x70102b, 0x1440001a, 0x27b30018, 
-0x8fb10018, 0x24053000, 0x2403021, 0xafb00010, 
-0xafa30014, 0xc002b3b, 0x2203821, 0x8fa30018, 
-0x702021, 0x64102b, 0x10400007, 0x2403021, 
-0x8cc20000, 0xac620000, 0x24630004, 0x64102b, 
-0x1440fffb, 0x24c60004, 0x8fa2001c, 0x501023, 
-0xafa2001c, 0x8e620000, 0x501021, 0x1000000a, 
-0xae620000, 0x2408821, 0x24053100, 0xafb00010, 
-0xafa30014, 0x8fa70018, 0x2203021, 0x2402002d, 
-0xc002b3b, 0xa0820000, 0x24070020, 0x8fa3001c, 
-0x3c040001, 0x2484605c, 0x24120020, 0x3c010001, 
-0xac316eb0, 0x2c620020, 0x1440001d, 0x27b10018, 
-0x8fb00018, 0x24053000, 0x3c060001, 0x24c66f50, 
-0xafa70010, 0xafa30014, 0xc002b3b, 0x2003821, 
-0x8fa30018, 0x3c040001, 0x24846f50, 0x24650020, 
-0x65102b, 0x10400007, 0x0, 0x8c820000, 
-0xac620000, 0x24630004, 0x65102b, 0x1440fffb, 
-0x24840004, 0x8fa2001c, 0x521023, 0xafa2001c, 
-0x8e220000, 0x521021, 0x1000000b, 0xae220000, 
-0x3c100001, 0x26106f50, 0x24053100, 0xafa70010, 
-0xafa30014, 0x8fa70018, 0x2003021, 0x2402002d, 
-0xc002b3b, 0xa0820000, 0x24070020, 0x3c040001, 
-0x24846070, 0x8fa3001c, 0x24120020, 0x3c010001, 
-0xac306ee4, 0x2c620020, 0x1440001d, 0x27b10018, 
-0x8fb00018, 0x24053000, 0x3c060001, 0x24c66f70, 
-0xafa70010, 0xafa30014, 0xc002b3b, 0x2003821, 
-0x8fa30018, 0x3c040001, 0x24846f70, 0x24650020, 
-0x65102b, 0x10400007, 0x0, 0x8c820000, 
-0xac620000, 0x24630004, 0x65102b, 0x1440fffb, 
-0x24840004, 0x8fa2001c, 0x521023, 0xafa2001c, 
-0x8e220000, 0x521021, 0x1000000b, 0xae220000, 
-0x3c100001, 0x26106f70, 0x24053100, 0xafa70010, 
-0xafa30014, 0x8fa70018, 0x2003021, 0x2402002d, 
-0xc002b3b, 0xa0820000, 0x3c010001, 0x10000031, 
-0xac306ee0, 0x3c100001, 0x2610821f, 0x3c120001, 
-0x2652809c, 0x2121023, 0x438024, 0x8fa3001c, 
-0x3c040001, 0x24846084, 0x70102b, 0x1440001a, 
-0x27b30018, 0x8fb10018, 0x24053000, 0x2403021, 
-0xafb00010, 0xafa30014, 0xc002b3b, 0x2203821, 
-0x8fa30018, 0x702021, 0x64102b, 0x10400007, 
-0x2403021, 0x8cc20000, 0xac620000, 0x24630004, 
-0x64102b, 0x1440fffb, 0x24c60004, 0x8fa2001c, 
-0x501023, 0xafa2001c, 0x8e620000, 0x501021, 
-0x1000000a, 0xae620000, 0x2408821, 0x24053100, 
-0xafb00010, 0xafa30014, 0x8fa70018, 0x2203021, 
-0x2402002d, 0xc002b3b, 0xa0820000, 0x3c010001, 
-0xac316eb0, 0x3c030001, 0x8c636eb0, 0x24020400, 
-0x60f809, 0xaf820070, 0x8fbf0030, 0x8fb3002c, 
-0x8fb20028, 0x8fb10024, 0x8fb00020, 0x3e00008, 
-0x27bd0038, 0x0, 0x0, 0x8f820040, 
-0x3c03f000, 0x431024, 0x3c036000, 0x14430006, 
-0x0, 0x8f820050, 0x2403ff80, 0x431024, 
-0x34420055, 0xaf820050, 0x8f820054, 0x244203e8, 
-0xaf820058, 0x240201f4, 0xaf4200e0, 0x24020004, 
-0xaf4200e8, 0x24020002, 0xaf4001b0, 0xaf4000e4, 
-0xaf4200dc, 0xaf4000d8, 0xaf4000d4, 0x3e00008, 
-0xaf4000d0, 0x8f820054, 0x24420005, 0x3e00008, 
-0xaf820078, 0x27bdffe8, 0xafbf0010, 0x8f820054, 
-0x244203e8, 0xaf820058, 0x3c020800, 0x2c21024, 
-0x10400004, 0x3c02f7ff, 0x3442ffff, 0x2c2b024, 
-0x36940040, 0x3c020001, 0x8c426da8, 0x10400017, 
-0x3c020200, 0x3c030001, 0x8c636f1c, 0x10600016, 
-0x282a025, 0x3c020001, 0x8c426e44, 0x14400012, 
-0x3c020200, 0x3c020001, 0x8c426d94, 0x30420003, 
-0x1440000d, 0x3c020200, 0x8f830224, 0x3c020002, 
-0x8c428fec, 0x10620008, 0x3c020200, 0xc003daf, 
-0x0, 0x10000004, 0x3c020200, 0xc004196, 
-0x0, 0x3c020200, 0x2c21024, 0x10400003, 
-0x0, 0xc001f4b, 0x0, 0x8f4200d8, 
-0x8f4300dc, 0x24420001, 0xaf4200d8, 0x43102b, 
-0x14400003, 0x0, 0xaf4000d8, 0x36940080, 
-0x8c030238, 0x1060000c, 0x0, 0x8f4201b0, 
-0x244203e8, 0xaf4201b0, 0x43102b, 0x14400006, 
-0x0, 0x934205c5, 0x14400003, 0x0, 
-0xc001da0, 0x0, 0x8fbf0010, 0x3e00008, 
-0x27bd0018, 0x3e00008, 0x0, 0x27bdffd8, 
-0xafbf0020, 0x8f43002c, 0x8f420038, 0x10620059, 
-0x0, 0x3c020001, 0x571021, 0x904240f0, 
-0x10400026, 0x24070008, 0x8f440170, 0x8f450174, 
-0x8f48000c, 0x8f860120, 0x24020020, 0xafa20010, 
-0xafa30014, 0xafa80018, 0x8f42010c, 0x40f809, 
-0x24c6001c, 0x14400011, 0x24020001, 0x3c010001, 
-0x370821, 0xa02240f0, 0x8f820124, 0xafa20010, 
-0x8f820128, 0x3c040001, 0x24846128, 0xafa20014, 
-0x8f46002c, 0x8f870120, 0x3c050009, 0xc002b3b, 
-0x34a50900, 0x1000005c, 0x0, 0x8f420300, 
-0x24420001, 0xaf420300, 0x8f420300, 0x8f42002c, 
-0xa34005c1, 0x10000027, 0xaf420038, 0x8f440170, 
-0x8f450174, 0x8f43002c, 0x8f48000c, 0x8f860120, 
-0x24020080, 0xafa20010, 0xafa30014, 0xafa80018, 
-0x8f42010c, 0x40f809, 0x24c6001c, 0x14400011, 
-0x24020001, 0x3c010001, 0x370821, 0xa02240f1, 
-0x8f820124, 0xafa20010, 0x8f820128, 0x3c040001, 
-0x24846134, 0xafa20014, 0x8f46002c, 0x8f870120, 
-0x3c050009, 0xc002b3b, 0x34a51100, 0x10000036, 
-0x0, 0x8f420300, 0x8f43002c, 0x24420001, 
-0xaf420300, 0x8f420300, 0x24020001, 0xa34205c1, 
-0xaf430038, 0x3c010001, 0x370821, 0xa02040f1, 
-0x3c010001, 0x370821, 0xa02040f0, 0x10000026, 
-0xaf400034, 0x934205c1, 0x1040001d, 0x0, 
-0xa34005c1, 0x8f820040, 0x30420001, 0x14400008, 
-0x2021, 0x8c030104, 0x24020001, 0x50620005, 
-0x24040001, 0x8c020264, 0x10400003, 0x801021, 
-0x24040001, 0x801021, 0x10400006, 0x0, 
-0x8f42030c, 0x24420001, 0xaf42030c, 0x10000008, 
-0x8f42030c, 0x8f820044, 0x34420004, 0xaf820044, 
-0x8f420308, 0x24420001, 0xaf420308, 0x8f420308, 
-0x3c010001, 0x370821, 0xa02040f0, 0x3c010001, 
-0x370821, 0xa02040f1, 0x8f420000, 0x10400007, 
-0x0, 0xaf80004c, 0x8f82004c, 0x1040fffd, 
-0x0, 0x10000005, 0x0, 0xaf800048, 
-0x8f820048, 0x1040fffd, 0x0, 0x8f820060, 
-0x3c03ff7f, 0x3463ffff, 0x431024, 0xaf820060, 
-0x8f420000, 0x10400003, 0x0, 0x10000002, 
-0xaf80004c, 0xaf800048, 0x8fbf0020, 0x3e00008, 
-0x27bd0028, 0x3e00008, 0x0, 0x27bdffd8, 
-0xafbf0020, 0x8f430044, 0x8f42007c, 0x10620029, 
-0x24070008, 0x8f440168, 0x8f45016c, 0x8f48000c, 
-0x8f860120, 0x24020040, 0xafa20010, 0xafa30014, 
-0xafa80018, 0x8f42010c, 0x40f809, 0x24c6001c, 
-0x14400011, 0x24020001, 0x3c010001, 0x370821, 
-0xa02240f2, 0x8f820124, 0xafa20010, 0x8f820128, 
-0x3c040001, 0x2484613c, 0xafa20014, 0x8f460044, 
-0x8f870120, 0x3c050009, 0xc002b3b, 0x34a51300, 
-0x1000000f, 0x0, 0x8f420304, 0x24420001, 
-0xaf420304, 0x8f420304, 0x8f420044, 0xaf42007c, 
-0x3c010001, 0x370821, 0xa02040f2, 0x10000004, 
-0xaf400078, 0x3c010001, 0x370821, 0xa02040f2, 
-0x8f420000, 0x10400007, 0x0, 0xaf80004c, 
-0x8f82004c, 0x1040fffd, 0x0, 0x10000005, 
-0x0, 0xaf800048, 0x8f820048, 0x1040fffd, 
-0x0, 0x8f820060, 0x3c03feff, 0x3463ffff, 
-0x431024, 0xaf820060, 0x8f420000, 0x10400003, 
-0x0, 0x10000002, 0xaf80004c, 0xaf800048, 
-0x8fbf0020, 0x3e00008, 0x27bd0028, 0x3e00008, 
-0x0, 0x3c020001, 0x8c426da8, 0x27bdffa8, 
-0xafbf0050, 0xafbe004c, 0xafb50048, 0xafb30044, 
-0xafb20040, 0xafb1003c, 0xafb00038, 0x104000d5, 
-0x8f900044, 0x8f4200d0, 0x24430001, 0x2842000b, 
-0x144000e4, 0xaf4300d0, 0x8f420004, 0x30420002, 
-0x1440009c, 0xaf4000d0, 0x8f420004, 0x3c030001, 
-0x8c636d98, 0x34420002, 0xaf420004, 0x24020001, 
-0x14620003, 0x3c020600, 0x10000002, 0x34423000, 
-0x34421000, 0xafa20020, 0x8f4a0018, 0xafaa0034, 
-0x27aa0020, 0xafaa002c, 0x8faa0034, 0x240200ff, 
-0x11420002, 0x1821, 0x25430001, 0x8c020228, 
-0x609821, 0x1662000e, 0x3c050009, 0x8f42033c, 
-0x24420001, 0xaf42033c, 0x8f42033c, 0x8c020228, 
-0x8fa70034, 0x3c040001, 0x2484610c, 0xafa00014, 
-0xafa20010, 0x8fa60020, 0x10000070, 0x34a50500, 
-0x8faa0034, 0xa38c0, 0xf71021, 0x8fa30020, 
-0x8fa40024, 0xac4304c0, 0xac4404c4, 0x8f830054, 
-0x8f820054, 0x247103e8, 0x2221023, 0x2c4203e9, 
-0x1040001b, 0xa821, 0xe09021, 0x265e04c0, 
-0x8f440178, 0x8f45017c, 0x2401821, 0x240a0004, 
-0xafaa0010, 0xafb30014, 0x8f48000c, 0x1021, 
-0x2fe3021, 0xafa80018, 0x8f48010c, 0x24070008, 
-0xa32821, 0xa3482b, 0x822021, 0x100f809, 
-0x892021, 0x54400006, 0x24150001, 0x8f820054, 
-0x2221023, 0x2c4203e9, 0x1440ffe9, 0x0, 
-0x32a200ff, 0x54400018, 0xaf530018, 0x8f420378, 
-0x24420001, 0xaf420378, 0x8f420378, 0x8f820120, 
-0x8faa002c, 0x8fa70034, 0xafa20010, 0x8f820124, 
-0x3c040001, 0x24846118, 0xafa20014, 0x8d460000, 
-0x3c050009, 0x10000035, 0x34a50600, 0x8f420308, 
-0x24150001, 0x24420001, 0xaf420308, 0x8f420308, 
-0x1000001e, 0x32a200ff, 0x8f830054, 0x8f820054, 
-0x247103e8, 0x2221023, 0x2c4203e9, 0x10400016, 
-0xa821, 0x3c1e0020, 0x24120010, 0x8f42000c, 
-0x8f440160, 0x8f450164, 0x8f860120, 0xafb20010, 
-0xafb30014, 0x5e1025, 0xafa20018, 0x8f42010c, 
-0x24070008, 0x40f809, 0x24c6001c, 0x1440ffe3, 
-0x0, 0x8f820054, 0x2221023, 0x2c4203e9, 
-0x1440ffee, 0x0, 0x32a200ff, 0x14400011, 
-0x3c050009, 0x8f420378, 0x24420001, 0xaf420378, 
-0x8f420378, 0x8f820120, 0x8faa002c, 0x8fa70034, 
-0xafa20010, 0x8f820124, 0x3c040001, 0x24846120, 
-0xafa20014, 0x8d460000, 0x34a50700, 0xc002b3b, 
-0x0, 0x8f4202ec, 0x24420001, 0xaf4202ec, 
-0x8f4202ec, 0x8f420004, 0x30420001, 0x50400029, 
-0x36100040, 0x3c020400, 0x2c21024, 0x10400013, 
-0x2404ffdf, 0x8f420250, 0x8f430254, 0x8f4401b4, 
-0x14640006, 0x36100040, 0x8f420270, 0x8f430274, 
-0x8f4401b8, 0x10640007, 0x2402ffdf, 0x8f420250, 
-0x8f430254, 0x8f440270, 0x8f450274, 0x10000012, 
-0x3a100020, 0x1000002b, 0x2028024, 0x8f420250, 
-0x8f430254, 0x8f4501b4, 0x14650006, 0x2048024, 
-0x8f420270, 0x8f430274, 0x8f4401b8, 0x50640021, 
-0x36100040, 0x8f420250, 0x8f430254, 0x8f440270, 
-0x8f450274, 0x3a100040, 0xaf4301b4, 0x10000019, 
-0xaf4501b8, 0x8f4200d4, 0x24430001, 0x10000011, 
-0x28420033, 0x8f420004, 0x30420001, 0x10400009, 
-0x3c020400, 0x2c21024, 0x10400004, 0x2402ffdf, 
-0x2028024, 0x1000000b, 0x36100040, 0x10000009, 
-0x36100060, 0x8f4200d4, 0x36100040, 0x24430001, 
-0x284201f5, 0x14400003, 0xaf4300d4, 0xaf4000d4, 
-0x3a100020, 0xaf900044, 0x2402ff7f, 0x282a024, 
-0x8fbf0050, 0x8fbe004c, 0x8fb50048, 0x8fb30044, 
-0x8fb20040, 0x8fb1003c, 0x8fb00038, 0x3e00008, 
-0x27bd0058, 0x3e00008, 0x0, 0x3c020001, 
-0x8c426da8, 0x27bdffb0, 0xafbf0048, 0xafbe0044, 
-0xafb50040, 0xafb3003c, 0xafb20038, 0xafb10034, 
-0x104000c7, 0xafb00030, 0x8f4200d0, 0x24430001, 
-0x2842000b, 0x144000da, 0xaf4300d0, 0x8f420004, 
-0x30420002, 0x14400097, 0xaf4000d0, 0x8f420004, 
-0x3c030001, 0x8c636d98, 0x34420002, 0xaf420004, 
-0x24020001, 0x14620003, 0x3c020600, 0x10000002, 
-0x34423000, 0x34421000, 0xafa20020, 0x1821, 
-0x8f5e0018, 0x27aa0020, 0x240200ff, 0x13c20002, 
-0xafaa002c, 0x27c30001, 0x8c020228, 0x609021, 
-0x1642000e, 0x1e38c0, 0x8f42033c, 0x24420001, 
-0xaf42033c, 0x8f42033c, 0x8c020228, 0x3c040001, 
-0x2484610c, 0x3c050009, 0xafa00014, 0xafa20010, 
-0x8fa60020, 0x1000006d, 0x34a50500, 0xf71021, 
-0x8fa30020, 0x8fa40024, 0xac4304c0, 0xac4404c4, 
-0x8f830054, 0x8f820054, 0x247003e8, 0x2021023, 
-0x2c4203e9, 0x1040001b, 0x9821, 0xe08821, 
-0x263504c0, 0x8f440178, 0x8f45017c, 0x2201821, 
-0x240a0004, 0xafaa0010, 0xafb20014, 0x8f48000c, 
-0x1021, 0x2f53021, 0xafa80018, 0x8f48010c, 
-0x24070008, 0xa32821, 0xa3482b, 0x822021, 
-0x100f809, 0x892021, 0x54400006, 0x24130001, 
-0x8f820054, 0x2021023, 0x2c4203e9, 0x1440ffe9, 
-0x0, 0x326200ff, 0x54400017, 0xaf520018, 
-0x8f420378, 0x24420001, 0xaf420378, 0x8f420378, 
-0x8f820120, 0x8faa002c, 0xafa20010, 0x8f820124, 
-0x3c040001, 0x24846118, 0x3c050009, 0xafa20014, 
-0x8d460000, 0x10000035, 0x34a50600, 0x8f420308, 
-0x24130001, 0x24420001, 0xaf420308, 0x8f420308, 
-0x1000001e, 0x326200ff, 0x8f830054, 0x8f820054, 
-0x247003e8, 0x2021023, 0x2c4203e9, 0x10400016, 
-0x9821, 0x3c150020, 0x24110010, 0x8f42000c, 
-0x8f440160, 0x8f450164, 0x8f860120, 0xafb10010, 
-0xafb20014, 0x551025, 0xafa20018, 0x8f42010c, 
-0x24070008, 0x40f809, 0x24c6001c, 0x1440ffe3, 
-0x0, 0x8f820054, 0x2021023, 0x2c4203e9, 
-0x1440ffee, 0x0, 0x326200ff, 0x14400011, 
-0x0, 0x8f420378, 0x24420001, 0xaf420378, 
-0x8f420378, 0x8f820120, 0x8faa002c, 0xafa20010, 
-0x8f820124, 0x3c040001, 0x24846120, 0x3c050009, 
-0xafa20014, 0x8d460000, 0x34a50700, 0xc002b3b, 
-0x3c03821, 0x8f4202ec, 0x24420001, 0xaf4202ec, 
-0x8f4202ec, 0x8f420004, 0x30420001, 0x10400018, 
-0x24040001, 0x8f420250, 0x8f430254, 0x8f4501b4, 
-0x3c010001, 0x14650006, 0xa0246cf1, 0x8f420270, 
-0x8f430274, 0x8f4401b8, 0x10640021, 0x0, 
-0x8f420250, 0x8f430254, 0x3c040001, 0x90846cf0, 
-0x8f460270, 0x8f470274, 0x38840001, 0xaf4301b4, 
-0xaf4701b8, 0x3c010001, 0x10000025, 0xa0246cf0, 
-0x8f4200d4, 0x3c010001, 0xa0206cf0, 0x24430001, 
-0x28420033, 0x1440001e, 0xaf4300d4, 0x3c020001, 
-0x90426cf1, 0xaf4000d4, 0x10000017, 0x38420001, 
-0x8f420004, 0x30420001, 0x10400008, 0x0, 
-0xc00565a, 0x2021, 0x3c010001, 0xa0206cf1, 
-0x3c010001, 0x1000000e, 0xa0206cf0, 0x8f4200d4, 
-0x3c010001, 0xa0206cf0, 0x24430001, 0x284201f5, 
-0x14400007, 0xaf4300d4, 0x3c020001, 0x90426cf1, 
-0xaf4000d4, 0x421026, 0x3c010001, 0xa0226cf1, 
-0x3c030001, 0x8c636d98, 0x24020002, 0x1462000c, 
-0x3c030002, 0x3c030001, 0x90636cf1, 0x24020001, 
-0x5462001f, 0x2021, 0x3c020001, 0x90426cf0, 
-0x1443001b, 0x24040005, 0x10000019, 0x24040006, 
-0x3c020002, 0x8c428ff4, 0x431024, 0x1040000b, 
-0x24020001, 0x3c030001, 0x90636cf1, 0x54620010, 
-0x2021, 0x3c020001, 0x90426cf0, 0x1443000c, 
-0x24040003, 0x1000000a, 0x24040004, 0x3c030001, 
-0x90636cf1, 0x14620006, 0x2021, 0x3c020001, 
-0x90426cf0, 0x24040001, 0x50440001, 0x24040002, 
-0xc00565a, 0x0, 0x2402ff7f, 0x282a024, 
-0x8fbf0048, 0x8fbe0044, 0x8fb50040, 0x8fb3003c, 
-0x8fb20038, 0x8fb10034, 0x8fb00030, 0x3e00008, 
-0x27bd0050, 0x3e00008, 0x0, 0x3c020001, 
-0x8c426da8, 0x27bdffb0, 0xafbf0048, 0xafbe0044, 
-0xafb50040, 0xafb3003c, 0xafb20038, 0xafb10034, 
-0x104000de, 0xafb00030, 0x8f4200d0, 0x3c040001, 
-0x8c846d98, 0x24430001, 0x2842000b, 0xaf4400e8, 
-0x144000fe, 0xaf4300d0, 0x8f420004, 0x30420002, 
-0x14400095, 0xaf4000d0, 0x8f420004, 0x34420002, 
-0xaf420004, 0x24020001, 0x14820003, 0x3c020600, 
-0x10000002, 0x34423000, 0x34421000, 0xafa20020, 
-0x1821, 0x8f5e0018, 0x27aa0020, 0x240200ff, 
-0x13c20002, 0xafaa002c, 0x27c30001, 0x8c020228, 
-0x609021, 0x1642000e, 0x1e38c0, 0x8f42033c, 
-0x24420001, 0xaf42033c, 0x8f42033c, 0x8c020228, 
-0x3c040001, 0x2484610c, 0x3c050009, 0xafa00014, 
-0xafa20010, 0x8fa60020, 0x1000006d, 0x34a50500, 
-0xf71021, 0x8fa30020, 0x8fa40024, 0xac4304c0, 
-0xac4404c4, 0x8f830054, 0x8f820054, 0x247003e8, 
-0x2021023, 0x2c4203e9, 0x1040001b, 0x9821, 
-0xe08821, 0x263504c0, 0x8f440178, 0x8f45017c, 
-0x2201821, 0x240a0004, 0xafaa0010, 0xafb20014, 
-0x8f48000c, 0x1021, 0x2f53021, 0xafa80018, 
-0x8f48010c, 0x24070008, 0xa32821, 0xa3482b, 
-0x822021, 0x100f809, 0x892021, 0x54400006, 
-0x24130001, 0x8f820054, 0x2021023, 0x2c4203e9, 
-0x1440ffe9, 0x0, 0x326200ff, 0x54400017, 
-0xaf520018, 0x8f420378, 0x24420001, 0xaf420378, 
-0x8f420378, 0x8f820120, 0x8faa002c, 0xafa20010, 
-0x8f820124, 0x3c040001, 0x24846118, 0x3c050009, 
-0xafa20014, 0x8d460000, 0x10000035, 0x34a50600, 
-0x8f420308, 0x24130001, 0x24420001, 0xaf420308, 
-0x8f420308, 0x1000001e, 0x326200ff, 0x8f830054, 
-0x8f820054, 0x247003e8, 0x2021023, 0x2c4203e9, 
-0x10400016, 0x9821, 0x3c150020, 0x24110010, 
-0x8f42000c, 0x8f440160, 0x8f450164, 0x8f860120, 
-0xafb10010, 0xafb20014, 0x551025, 0xafa20018, 
-0x8f42010c, 0x24070008, 0x40f809, 0x24c6001c, 
-0x1440ffe3, 0x0, 0x8f820054, 0x2021023, 
-0x2c4203e9, 0x1440ffee, 0x0, 0x326200ff, 
-0x14400011, 0x0, 0x8f420378, 0x24420001, 
-0xaf420378, 0x8f420378, 0x8f820120, 0x8faa002c, 
-0xafa20010, 0x8f820124, 0x3c040001, 0x24846120, 
-0x3c050009, 0xafa20014, 0x8d460000, 0x34a50700, 
-0xc002b3b, 0x3c03821, 0x8f4202ec, 0x24420001, 
-0xaf4202ec, 0x8f4202ec, 0x8f420004, 0x30420001, 
-0x10400033, 0x3c020400, 0x2c21024, 0x10400017, 
-0x0, 0x934205c0, 0x8f440250, 0x8f450254, 
-0x8f4301b4, 0x34420020, 0x14a30006, 0xa34205c0, 
-0x8f420270, 0x8f430274, 0x8f4401b8, 0x10640008, 
-0x0, 0x8f420250, 0x8f430254, 0x934405c0, 
-0x8f460270, 0x8f470274, 0x10000016, 0x38840040, 
-0x934205c0, 0x10000048, 0x304200bf, 0x934205c0, 
-0x8f440250, 0x8f450254, 0x8f4301b4, 0x304200bf, 
-0x14a30006, 0xa34205c0, 0x8f420270, 0x8f430274, 
-0x8f4401b8, 0x1064000b, 0x0, 0x8f420250, 
-0x8f430254, 0x934405c0, 0x8f460270, 0x8f470274, 
-0x38840020, 0xaf4301b4, 0xaf4701b8, 0x10000033, 
-0xa34405c0, 0x934205c0, 0x1000002f, 0x34420020, 
-0x934205c0, 0x8f4300d4, 0x34420020, 0xa34205c0, 
-0x24620001, 0x10000023, 0x28630033, 0x8f4200e4, 
-0x8f4300e0, 0x24420001, 0xaf4200e4, 0x43102a, 
-0x14400006, 0x24030001, 0x8f4200e8, 0x14430002, 
-0xaf4000e4, 0x24030004, 0xaf4300e8, 0x8f420004, 
-0x30420001, 0x1040000d, 0x3c020400, 0x2c21024, 
-0x10400007, 0x0, 0x934205c0, 0x34420040, 
-0xa34205c0, 0x934205c0, 0x1000000f, 0x304200df, 
-0x934205c0, 0x1000000c, 0x34420060, 0x934205c0, 
-0x8f4300d4, 0x34420020, 0xa34205c0, 0x24620001, 
-0x286300fb, 0x14600005, 0xaf4200d4, 0x934205c0, 
-0xaf4000d4, 0x38420040, 0xa34205c0, 0x934205c0, 
-0x8f4300e8, 0x3042007f, 0xa34205c0, 0x24020001, 
-0x14620005, 0x0, 0x934405c0, 0x42102, 
-0x10000003, 0x348400f0, 0x934405c0, 0x3484000f, 
-0xc005640, 0x0, 0x2402ff7f, 0x282a024, 
-0x8fbf0048, 0x8fbe0044, 0x8fb50040, 0x8fb3003c, 
-0x8fb20038, 0x8fb10034, 0x8fb00030, 0x3e00008, 
-0x27bd0050, 0x3e00008, 0x0, 0x27bdffb0, 
-0x274401c0, 0x26e30028, 0x24650400, 0x65102b, 
-0xafbf0048, 0xafbe0044, 0xafb50040, 0xafb3003c, 
-0xafb20038, 0xafb10034, 0x10400007, 0xafb00030, 
-0x8c820000, 0xac620000, 0x24630004, 0x65102b, 
-0x1440fffb, 0x24840004, 0x8c020080, 0xaee20044, 
-0x8c0200c0, 0xaee20040, 0x8c020084, 0xaee20030, 
-0x8c020084, 0xaee2023c, 0x8c020088, 0xaee20240, 
-0x8c02008c, 0xaee20244, 0x8c020090, 0xaee20248, 
-0x8c020094, 0xaee2024c, 0x8c020098, 0xaee20250, 
-0x8c02009c, 0xaee20254, 0x8c0200a0, 0xaee20258, 
-0x8c0200a4, 0xaee2025c, 0x8c0200a8, 0xaee20260, 
-0x8c0200ac, 0xaee20264, 0x8c0200b0, 0xaee20268, 
-0x8c0200b4, 0xaee2026c, 0x8c0200b8, 0xaee20270, 
-0x8c0200bc, 0x24040001, 0xaee20274, 0xaee00034, 
-0x41080, 0x571021, 0x8ee30034, 0x8c42023c, 
-0x24840001, 0x621821, 0x2c82000f, 0xaee30034, 
-0x1440fff8, 0x41080, 0x8c0200cc, 0xaee20048, 
-0x8c0200d0, 0xaee2004c, 0x8c0200e0, 0xaee201f8, 
-0x8c0200e4, 0xaee201fc, 0x8c0200e8, 0xaee20200, 
-0x8c0200ec, 0xaee20204, 0x8c0200f0, 0xaee20208, 
-0x8ee400c0, 0x8ee500c4, 0x8c0200fc, 0x45102b, 
-0x1040000b, 0x0, 0x8ee200c0, 0x8ee300c4, 
-0x24040001, 0x24050000, 0x651821, 0x65302b, 
-0x441021, 0x461021, 0xaee200c0, 0xaee300c4, 
-0x8c0200fc, 0x8ee400c0, 0x8ee500c4, 0x2408ffff, 
-0x24090000, 0x401821, 0x1021, 0x882024, 
-0xa92824, 0x822025, 0xa32825, 0xaee400c0, 
-0xaee500c4, 0x8ee400d0, 0x8ee500d4, 0x8c0200f4, 
-0x45102b, 0x1040000b, 0x0, 0x8ee200d0, 
-0x8ee300d4, 0x24040001, 0x24050000, 0x651821, 
-0x65302b, 0x441021, 0x461021, 0xaee200d0, 
-0xaee300d4, 0x8c0200f4, 0x8ee400d0, 0x8ee500d4, 
-0x401821, 0x1021, 0x882024, 0xa92824, 
-0x822025, 0xa32825, 0xaee400d0, 0xaee500d4, 
-0x8ee400c8, 0x8ee500cc, 0x8c0200f8, 0x45102b, 
-0x1040000b, 0x0, 0x8ee200c8, 0x8ee300cc, 
-0x24040001, 0x24050000, 0x651821, 0x65302b, 
-0x441021, 0x461021, 0xaee200c8, 0xaee300cc, 
-0x8c0200f8, 0x8ee400c8, 0x8ee500cc, 0x401821, 
-0x1021, 0x882024, 0xa92824, 0x822025, 
-0xa32825, 0x24020008, 0xaee400c8, 0xaee500cc, 
-0xafa20010, 0xafa00014, 0x8f42000c, 0x8c040208, 
-0x8c05020c, 0xafa20018, 0x8f42010c, 0x26e60028, 
-0x40f809, 0x24070400, 0x104000f0, 0x3c020400, 
-0xafa20020, 0x934205c6, 0x10400089, 0x1821, 
-0x8f5e0018, 0x27aa0020, 0x240200ff, 0x13c20002, 
-0xafaa002c, 0x27c30001, 0x8c020228, 0x609021, 
-0x1642000e, 0x1e38c0, 0x8f42033c, 0x24420001, 
-0xaf42033c, 0x8f42033c, 0x8c020228, 0x3c040001, 
-0x2484610c, 0x3c050009, 0xafa00014, 0xafa20010, 
-0x8fa60020, 0x1000006b, 0x34a50500, 0xf71021, 
-0x8fa30020, 0x8fa40024, 0xac4304c0, 0xac4404c4, 
-0x8f830054, 0x8f820054, 0x247003e8, 0x2021023, 
-0x2c4203e9, 0x1040001b, 0x9821, 0xe08821, 
-0x263504c0, 0x8f440178, 0x8f45017c, 0x2201821, 
-0x240a0004, 0xafaa0010, 0xafb20014, 0x8f48000c, 
-0x1021, 0x2f53021, 0xafa80018, 0x8f48010c, 
-0x24070008, 0xa32821, 0xa3482b, 0x822021, 
-0x100f809, 0x892021, 0x54400006, 0x24130001, 
-0x8f820054, 0x2021023, 0x2c4203e9, 0x1440ffe9, 
-0x0, 0x326200ff, 0x54400017, 0xaf520018, 
-0x8f420378, 0x24420001, 0xaf420378, 0x8f420378, 
-0x8f820120, 0x8faa002c, 0xafa20010, 0x8f820124, 
-0x3c040001, 0x24846118, 0x3c050009, 0xafa20014, 
-0x8d460000, 0x10000033, 0x34a50600, 0x8f420308, 
-0x24130001, 0x24420001, 0xaf420308, 0x8f420308, 
-0x1000001c, 0x326200ff, 0x8f830054, 0x8f820054, 
-0x247003e8, 0x2021023, 0x2c4203e9, 0x10400014, 
-0x9821, 0x24110010, 0x8f42000c, 0x8f440160, 
-0x8f450164, 0x8f860120, 0xafb10010, 0xafb20014, 
-0xafa20018, 0x8f42010c, 0x24070008, 0x40f809, 
-0x24c6001c, 0x1440ffe5, 0x0, 0x8f820054, 
-0x2021023, 0x2c4203e9, 0x1440ffef, 0x0, 
-0x326200ff, 0x54400012, 0x24020001, 0x8f420378, 
-0x24420001, 0xaf420378, 0x8f420378, 0x8f820120, 
-0x8faa002c, 0xafa20010, 0x8f820124, 0x3c040001, 
-0x24846120, 0x3c050009, 0xafa20014, 0x8d460000, 
-0x34a50700, 0xc002b3b, 0x3c03821, 0x1021, 
-0x1440005b, 0x24020001, 0x10000065, 0x0, 
-0x8f510018, 0x240200ff, 0x12220002, 0x8021, 
-0x26300001, 0x8c020228, 0x1602000e, 0x1130c0, 
-0x8f42033c, 0x24420001, 0xaf42033c, 0x8f42033c, 
-0x8c020228, 0x3c040001, 0x248460f4, 0x3c050009, 
-0xafa00014, 0xafa20010, 0x8fa60020, 0x1000003f, 
-0x34a50100, 0xd71021, 0x8fa30020, 0x8fa40024, 
-0xac4304c0, 0xac4404c4, 0xc01821, 0x8f440178, 
-0x8f45017c, 0x1021, 0x24070004, 0xafa70010, 
-0xafb00014, 0x8f48000c, 0x24c604c0, 0x2e63021, 
-0xafa80018, 0x8f48010c, 0x24070008, 0xa32821, 
-0xa3482b, 0x822021, 0x100f809, 0x892021, 
-0x1440000b, 0x24070008, 0x8f820120, 0xafa20010, 
-0x8f820124, 0x3c040001, 0x248460fc, 0x3c050009, 
-0xafa20014, 0x8fa60020, 0x1000001c, 0x34a50200, 
-0x8f440160, 0x8f450164, 0x8f43000c, 0xaf500018, 
-0x8f860120, 0x24020010, 0xafa20010, 0xafb00014, 
-0xafa30018, 0x8f42010c, 0x40f809, 0x24c6001c, 
-0x54400011, 0x24020001, 0x8f420340, 0x24420001, 
-0xaf420340, 0x8f420340, 0x8f820120, 0xafa20010, 
-0x8f820124, 0x3c040001, 0x24846104, 0x3c050009, 
-0xafa20014, 0x8fa60020, 0x34a50300, 0xc002b3b, 
-0x2203821, 0x1021, 0x1040000d, 0x24020001, 
-0x8f4202e8, 0xa34005c6, 0xaf4001b0, 0x24420001, 
-0xaf4202e8, 0x8f4202e8, 0x8ee20150, 0x24420001, 
-0xaee20150, 0x10000003, 0x8ee20150, 0x24020001, 
-0xa34205c6, 0x8fbf0048, 0x8fbe0044, 0x8fb50040, 
-0x8fb3003c, 0x8fb20038, 0x8fb10034, 0x8fb00030, 
-0x3e00008, 0x27bd0050, 0x27bdffd8, 0xafbf0020, 
-0x8f8200b0, 0x30420004, 0x10400068, 0x0, 
-0x8f430128, 0x8f820104, 0x14620005, 0x0, 
-0x8f430130, 0x8f8200b4, 0x10620006, 0x0, 
-0x8f820104, 0xaf420128, 0x8f8200b4, 0x1000005b, 
-0xaf420130, 0x8f8200b0, 0x3c030080, 0x431024, 
-0x1040000d, 0x0, 0x8f82011c, 0x34420002, 
-0xaf82011c, 0x8f8200b0, 0x2403fffb, 0x431024, 
-0xaf8200b0, 0x8f82011c, 0x2403fffd, 0x431024, 
-0x1000004a, 0xaf82011c, 0x8f430128, 0x8f820104, 
-0x14620005, 0x0, 0x8f430130, 0x8f8200b4, 
-0x10620010, 0x0, 0x8f820104, 0xaf420128, 
-0x8f8200b4, 0x8f430128, 0xaf420130, 0xafa30010, 
-0x8f420130, 0x3c040001, 0x24846144, 0xafa20014, 
-0x8f86011c, 0x8f8700b0, 0x3c050005, 0x10000031, 
-0x34a50900, 0x8f420128, 0xafa20010, 0x8f420130, 
-0x3c040001, 0x24846150, 0xafa20014, 0x8f86011c, 
-0x8f8700b0, 0x3c050005, 0xc002b3b, 0x34a51000, 
-0x8f82011c, 0x34420002, 0xaf82011c, 0x8f830104, 
-0x8f8200b0, 0x34420001, 0xaf8200b0, 0x24020008, 
-0xaf830104, 0xafa20010, 0xafa00014, 0x8f42000c, 
-0x8c040208, 0x8c05020c, 0xafa20018, 0x8f42010c, 
-0x26e60028, 0x40f809, 0x24070400, 0x8f82011c, 
-0x2403fffd, 0x431024, 0xaf82011c, 0x8ee201dc, 
-0x24420001, 0xaee201dc, 0x8ee201dc, 0x8f420128, 
-0xafa20010, 0x8f420130, 0x3c040001, 0x2484615c, 
-0xafa20014, 0x8f86011c, 0x8f8700b0, 0x3c050005, 
-0x34a51100, 0xc002b3b, 0x0, 0x8f8200a0, 
-0x30420004, 0x10400069, 0x0, 0x8f43012c, 
-0x8f820124, 0x14620005, 0x0, 0x8f430134, 
-0x8f8200a4, 0x10620006, 0x0, 0x8f820124, 
-0xaf42012c, 0x8f8200a4, 0x1000005c, 0xaf420134, 
-0x8f8200a0, 0x3c030080, 0x431024, 0x1040000d, 
-0x0, 0x8f82011c, 0x34420002, 0xaf82011c, 
-0x8f8200a0, 0x2403fffb, 0x431024, 0xaf8200a0, 
-0x8f82011c, 0x2403fffd, 0x431024, 0x1000004b, 
-0xaf82011c, 0x8f43012c, 0x8f820124, 0x14620005, 
-0x0, 0x8f430134, 0x8f8200a4, 0x10620010, 
-0x0, 0x8f820124, 0xaf42012c, 0x8f8200a4, 
-0x8f43012c, 0xaf420134, 0xafa30010, 0x8f420134, 
-0x3c040001, 0x24846168, 0xafa20014, 0x8f86011c, 
-0x8f8700a0, 0x3c050005, 0x10000032, 0x34a51200, 
-0x8f42012c, 0xafa20010, 0x8f420134, 0x3c040001, 
-0x24846174, 0xafa20014, 0x8f86011c, 0x8f8700a0, 
-0x3c050005, 0xc002b3b, 0x34a51300, 0x8f82011c, 
-0x34420002, 0xaf82011c, 0x8f830124, 0x8f8200a0, 
-0x34420001, 0xaf8200a0, 0x24020080, 0xaf830124, 
-0xafa20010, 0xafa00014, 0x8f420014, 0x8c040208, 
-0x8c05020c, 0xafa20018, 0x8f420108, 0x3c060001, 
-0x24c66ed8, 0x40f809, 0x24070004, 0x8f82011c, 
-0x2403fffd, 0x431024, 0xaf82011c, 0x8ee201dc, 
-0x24420001, 0xaee201dc, 0x8ee201dc, 0x8f42012c, 
-0xafa20010, 0x8f420134, 0x3c040001, 0x24846180, 
-0xafa20014, 0x8f86011c, 0x8f8700a0, 0x3c050005, 
-0x34a51400, 0xc002b3b, 0x0, 0x8fbf0020, 
-0x3e00008, 0x27bd0028, 0x3c081000, 0x24070001, 
-0x3c060080, 0x3c050100, 0x8f820070, 0x481024, 
-0x1040fffd, 0x0, 0x8f820054, 0x24420005, 
-0xaf820078, 0x8c040234, 0x10800016, 0x1821, 
-0x3c020001, 0x571021, 0x8c4240e8, 0x24420005, 
-0x3c010001, 0x370821, 0xac2240e8, 0x3c020001, 
-0x571021, 0x8c4240e8, 0x44102b, 0x14400009, 
-0x0, 0x3c030080, 0x3c010001, 0x370821, 
-0xac2040e8, 0x3c010001, 0x370821, 0x1000000b, 
-0xa02740f0, 0x3c020001, 0x571021, 0x904240f0, 
-0x54400006, 0x661825, 0x3c020001, 0x571021, 
-0x904240f1, 0x54400001, 0x661825, 0x8c040230, 
-0x10800013, 0x0, 0x3c020001, 0x571021, 
-0x8c4240ec, 0x24420005, 0x3c010001, 0x370821, 
-0xac2240ec, 0x3c020001, 0x571021, 0x8c4240ec, 
-0x44102b, 0x14400006, 0x0, 0x3c010001, 
-0x370821, 0xac2040ec, 0x10000006, 0x651825, 
-0x3c020001, 0x571021, 0x904240f2, 0x54400001, 
-0x651825, 0x1060ffbc, 0x0, 0x8f420000, 
-0x10400007, 0x0, 0xaf80004c, 0x8f82004c, 
-0x1040fffd, 0x0, 0x10000005, 0x0, 
-0xaf800048, 0x8f820048, 0x1040fffd, 0x0, 
-0x8f820060, 0x431025, 0xaf820060, 0x8f420000, 
-0x10400003, 0x0, 0x1000ffa7, 0xaf80004c, 
-0x1000ffa5, 0xaf800048, 0x3e00008, 0x0, 
-0x0, 0x0, 0x0, 0x27bdffe0, 
-0xafbf0018, 0x8f860064, 0x30c20004, 0x10400025, 
-0x24040004, 0x8c020114, 0xaf420020, 0xaf840064, 
-0x8f4202fc, 0x24420001, 0xaf4202fc, 0x8f4202fc, 
-0x8f820064, 0x30420004, 0x14400005, 0x0, 
-0x8c030114, 0x8f420020, 0x1462fff2, 0x0, 
-0x8f420000, 0x10400007, 0x8f43003c, 0xaf80004c, 
-0x8f82004c, 0x1040fffd, 0x0, 0x10000005, 
-0x0, 0xaf800048, 0x8f820048, 0x1040fffd, 
-0x0, 0x8f820060, 0x431025, 0xaf820060, 
-0x8f420000, 0x10400073, 0x0, 0x1000006f, 
-0x0, 0x30c20008, 0x10400020, 0x24040008, 
-0x8c02011c, 0xaf420048, 0xaf840064, 0x8f4202a8, 
-0x24420001, 0xaf4202a8, 0x8f4202a8, 0x8f820064, 
-0x30420008, 0x14400005, 0x0, 0x8c03011c, 
-0x8f420048, 0x1462fff2, 0x0, 0x8f420000, 
-0x10400007, 0x0, 0xaf80004c, 0x8f82004c, 
-0x1040fffd, 0x0, 0x10000005, 0x0, 
-0xaf800048, 0x8f820048, 0x1040fffd, 0x0, 
-0x8f820060, 0x1000ffd9, 0x34420200, 0x30c20020, 
-0x10400023, 0x24040020, 0x8c02012c, 0xaf420068, 
-0xaf840064, 0x8f4202d8, 0x24420001, 0xaf4202d8, 
-0x8f4202d8, 0x8f820064, 0x30420020, 0x14400005, 
-0x32c24000, 0x8c03012c, 0x8f420068, 0x1462fff2, 
-0x32c24000, 0x14400002, 0x3c020001, 0x2c2b025, 
-0x8f420000, 0x10400007, 0x0, 0xaf80004c, 
-0x8f82004c, 0x1040fffd, 0x0, 0x10000005, 
-0x0, 0xaf800048, 0x8f820048, 0x1040fffd, 
-0x0, 0x8f820060, 0x1000ffb4, 0x34420800, 
-0x30c20010, 0x10400029, 0x24040010, 0x8c020124, 
-0xaf420058, 0xaf840064, 0x8f4202d4, 0x24420001, 
-0xaf4202d4, 0x8f4202d4, 0x8f820064, 0x30420010, 
-0x14400005, 0x32c22000, 0x8c030124, 0x8f420058, 
-0x1462fff2, 0x32c22000, 0x50400001, 0x36d68000, 
-0x8f420000, 0x10400007, 0x0, 0xaf80004c, 
-0x8f82004c, 0x1040fffd, 0x0, 0x10000005, 
-0x0, 0xaf800048, 0x8f820048, 0x1040fffd, 
-0x0, 0x8f820060, 0x34420100, 0xaf820060, 
-0x8f420000, 0x10400003, 0x0, 0x1000006c, 
-0xaf80004c, 0x1000006a, 0xaf800048, 0x30c20001, 
-0x10400004, 0x24020001, 0xaf820064, 0x10000064, 
-0x0, 0x30c20002, 0x1440000b, 0x3c050003, 
-0x3c040001, 0x24846244, 0x34a50500, 0x3821, 
-0xafa00010, 0xc002b3b, 0xafa00014, 0x2402ffc0, 
-0x10000057, 0xaf820064, 0x8c05022c, 0x8c02010c, 
-0x10a20048, 0x51080, 0x8c460300, 0x24a20001, 
-0x3045003f, 0x24020003, 0xac05022c, 0x61e02, 
-0x10620005, 0x24020010, 0x1062001d, 0x30c20fff, 
-0x10000039, 0x0, 0x8f4302a8, 0x8f440000, 
-0x30c20fff, 0xaf420048, 0x24630001, 0xaf4302a8, 
-0x10800007, 0x8f4202a8, 0xaf80004c, 0x8f82004c, 
-0x1040fffd, 0x0, 0x10000005, 0x0, 
-0xaf800048, 0x8f820048, 0x1040fffd, 0x0, 
-0x8f820060, 0x34420200, 0xaf820060, 0x8f420000, 
-0x1040001f, 0x0, 0x1000001b, 0x0, 
-0xaf420058, 0x32c22000, 0x50400001, 0x36d68000, 
-0x8f4202d4, 0x8f430000, 0x24420001, 0xaf4202d4, 
-0x10600007, 0x8f4202d4, 0xaf80004c, 0x8f82004c, 
-0x1040fffd, 0x0, 0x10000005, 0x0, 
-0xaf800048, 0x8f820048, 0x1040fffd, 0x0, 
-0x8f820060, 0x34420100, 0xaf820060, 0x8f420000, 
-0x10400003, 0x0, 0x10000006, 0xaf80004c, 
-0x10000004, 0xaf800048, 0xc002196, 0xc02021, 
-0x402821, 0x8c02010c, 0x14a20002, 0x24020002, 
-0xaf820064, 0x8f820064, 0x30420002, 0x14400004, 
-0x0, 0x8c02010c, 0x14a2ffac, 0x0, 
-0x8fbf0018, 0x3e00008, 0x27bd0020, 0x3e00008, 
-0x0, 0x27bdffa0, 0xafb00040, 0x808021, 
-0x101602, 0x2442ffff, 0x304300ff, 0x2c620013, 
-0xafbf0058, 0xafbe0054, 0xafb50050, 0xafb3004c, 
-0xafb20048, 0xafb10044, 0x104001f3, 0xafa50034, 
-0x31080, 0x3c010001, 0x220821, 0x8c226288, 
-0x400008, 0x0, 0x101302, 0x30440fff, 
-0x24020001, 0x10820005, 0x24020002, 0x1082000c, 
-0x2402fffe, 0x10000024, 0x3c050003, 0x8f430004, 
-0x3c020001, 0x8c426f04, 0xaf440200, 0xaf440204, 
-0x3c040001, 0x8c846e80, 0x10000009, 0x34630001, 
-0x8f430004, 0xaf440200, 0xaf440204, 0x3c040001, 
-0x8c846e80, 0x621824, 0x3c020001, 0x2442ca28, 
-0x21100, 0x21182, 0xaf430004, 0x3c030800, 
-0x431025, 0xac820038, 0x8f840054, 0x41442, 
-0x41c82, 0x431021, 0x41cc2, 0x431023, 
-0x41d02, 0x431021, 0x41d42, 0x431023, 
-0x10000009, 0xaf420208, 0x3c040001, 0x24846250, 
-0x34a51000, 0x2003021, 0x3821, 0xafa00010, 
-0xc002b3b, 0xafa00014, 0x8f4202a0, 0x24420001, 
-0xaf4202a0, 0x1000021f, 0x8f4202a0, 0x27b00028, 
-0x2002021, 0x24050210, 0xc002bbf, 0x24060008, 
-0xc002518, 0x2002021, 0x10000216, 0x0, 
-0x8faa0034, 0x27a40028, 0xa1880, 0x25420001, 
-0x3042003f, 0xafa20034, 0x8c650300, 0x8faa0034, 
-0x21080, 0x8c430300, 0x25420001, 0x3042003f, 
-0xafa20034, 0xac02022c, 0xafa50028, 0xc002518, 
-0xafa3002c, 0x10000203, 0x0, 0x27b00028, 
-0x2002021, 0x24050210, 0xc002bbf, 0x24060008, 
-0xc002657, 0x2002021, 0x100001fa, 0x0, 
-0x8faa0034, 0x27a40028, 0xa1880, 0x25420001, 
-0x3042003f, 0xafa20034, 0x8c650300, 0x8faa0034, 
-0x21080, 0x8c430300, 0x25420001, 0x3042003f, 
-0xafa20034, 0xac02022c, 0xafa50028, 0xc002657, 
-0xafa3002c, 0x100001e7, 0x0, 0x101302, 
-0x30430fff, 0x24020001, 0x10620005, 0x24020002, 
-0x1062001e, 0x3c020002, 0x10000033, 0x3c050003, 
-0x3c030002, 0x2c31024, 0x54400037, 0x2c3b025, 
-0x8f820228, 0x3c010001, 0x370821, 0xac2238d8, 
-0x8f82022c, 0x3c010001, 0x370821, 0xac2238dc, 
-0x8f820230, 0x3c010001, 0x370821, 0xac2238e0, 
-0x8f820234, 0x3c010001, 0x370821, 0xac2238e4, 
-0x2402ffff, 0xaf820228, 0xaf82022c, 0xaf820230, 
-0xaf820234, 0x10000020, 0x2c3b025, 0x2c21024, 
-0x10400012, 0x3c02fffd, 0x3c020001, 0x571021, 
-0x8c4238d8, 0xaf820228, 0x3c020001, 0x571021, 
-0x8c4238dc, 0xaf82022c, 0x3c020001, 0x571021, 
-0x8c4238e0, 0xaf820230, 0x3c020001, 0x571021, 
-0x8c4238e4, 0xaf820234, 0x3c02fffd, 0x3442ffff, 
-0x10000009, 0x2c2b024, 0x3c040001, 0x2484625c, 
-0x34a51100, 0x2003021, 0x3821, 0xafa00010, 
-0xc002b3b, 0xafa00014, 0x8f4202cc, 0x24420001, 
-0xaf4202cc, 0x1000019f, 0x8f4202cc, 0x101302, 
-0x30450fff, 0x24020001, 0x10a20005, 0x24020002, 
-0x10a2000d, 0x3c0408ff, 0x10000014, 0x3c050003, 
-0x3c0208ff, 0x3442ffff, 0x8f830220, 0x3c040004, 
-0x2c4b025, 0x621824, 0x34630008, 0xaf830220, 
-0x10000012, 0xaf450298, 0x3484fff7, 0x3c03fffb, 
-0x8f820220, 0x3463ffff, 0x2c3b024, 0x441024, 
-0xaf820220, 0x10000009, 0xaf450298, 0x3c040001, 
-0x24846268, 0x34a51200, 0x2003021, 0x3821, 
-0xafa00010, 0xc002b3b, 0xafa00014, 0x8f4202bc, 
-0x24420001, 0xaf4202bc, 0x10000176, 0x8f4202bc, 
-0x27840208, 0x24050200, 0xc002bbf, 0x24060008, 
-0x27440224, 0x24050200, 0xc002bbf, 0x24060008, 
-0x8f4202c4, 0x24420001, 0xaf4202c4, 0x10000169, 
-0x8f4202c4, 0x101302, 0x30430fff, 0x24020001, 
-0x10620011, 0x28620002, 0x50400005, 0x24020002, 
-0x10600007, 0x0, 0x10000017, 0x0, 
-0x1062000f, 0x0, 0x10000013, 0x0, 
-0x8c060248, 0x2021, 0xc005104, 0x24050004, 
-0x10000007, 0x0, 0x8c060248, 0x2021, 
-0xc005104, 0x24050004, 0x10000010, 0x0, 
-0x8c06024c, 0x2021, 0xc005104, 0x24050001, 
-0x1000000a, 0x0, 0x3c040001, 0x24846274, 
-0x3c050003, 0x34a51300, 0x2003021, 0x3821, 
-0xafa00010, 0xc002b3b, 0xafa00014, 0x8f4202c0, 
-0x24420001, 0xaf4202c0, 0x1000013a, 0x8f4202c0, 
-0xc002426, 0x0, 0x10000136, 0x0, 
-0x24020001, 0xa34205c5, 0x24100100, 0x8f4401a8, 
-0x8f4501ac, 0xafb00010, 0xafa00014, 0x8f420014, 
-0xafa20018, 0x8f420108, 0x26e60028, 0x40f809, 
-0x24070400, 0x1040fff5, 0x0, 0x10000125, 
-0x0, 0x3c03ffff, 0x34637fff, 0x8f420368, 
-0x8f440360, 0x2c3b024, 0x1821, 0xaf400058, 
-0xaf40005c, 0xaf400060, 0xaf400064, 0x441023, 
-0xaf420368, 0x3c020900, 0xaf400360, 0xafa20020, 
-0x8f5e0018, 0x27aa0020, 0x240200ff, 0x13c20002, 
-0xafaa003c, 0x27c30001, 0x8c020228, 0x609021, 
-0x1642000e, 0x1e38c0, 0x8f42033c, 0x24420001, 
-0xaf42033c, 0x8f42033c, 0x8c020228, 0x3c040001, 
-0x2484620c, 0x3c050009, 0xafa00014, 0xafa20010, 
-0x8fa60020, 0x1000006b, 0x34a50500, 0xf71021, 
-0x8fa30020, 0x8fa40024, 0xac4304c0, 0xac4404c4, 
-0x8f830054, 0x8f820054, 0x247003e8, 0x2021023, 
-0x2c4203e9, 0x1040001b, 0x9821, 0xe08821, 
-0x263504c0, 0x8f440178, 0x8f45017c, 0x2201821, 
-0x240a0004, 0xafaa0010, 0xafb20014, 0x8f48000c, 
-0x1021, 0x2f53021, 0xafa80018, 0x8f48010c, 
-0x24070008, 0xa32821, 0xa3482b, 0x822021, 
-0x100f809, 0x892021, 0x54400006, 0x24130001, 
-0x8f820054, 0x2021023, 0x2c4203e9, 0x1440ffe9, 
-0x0, 0x326200ff, 0x54400017, 0xaf520018, 
-0x8f420378, 0x24420001, 0xaf420378, 0x8f420378, 
-0x8f820120, 0x8faa003c, 0xafa20010, 0x8f820124, 
-0x3c040001, 0x24846218, 0x3c050009, 0xafa20014, 
-0x8d460000, 0x10000033, 0x34a50600, 0x8f420308, 
-0x24130001, 0x24420001, 0xaf420308, 0x8f420308, 
-0x1000001c, 0x326200ff, 0x8f830054, 0x8f820054, 
-0x247003e8, 0x2021023, 0x2c4203e9, 0x10400014, 
-0x9821, 0x24110010, 0x8f42000c, 0x8f440160, 
-0x8f450164, 0x8f860120, 0xafb10010, 0xafb20014, 
-0xafa20018, 0x8f42010c, 0x24070008, 0x40f809, 
-0x24c6001c, 0x1440ffe5, 0x0, 0x8f820054, 
-0x2021023, 0x2c4203e9, 0x1440ffef, 0x0, 
-0x326200ff, 0x14400011, 0x0, 0x8f420378, 
-0x24420001, 0xaf420378, 0x8f420378, 0x8f820120, 
-0x8faa003c, 0xafa20010, 0x8f820124, 0x3c040001, 
-0x24846220, 0x3c050009, 0xafa20014, 0x8d460000, 
-0x34a50700, 0xc002b3b, 0x3c03821, 0x8f4202b0, 
-0x24420001, 0xaf4202b0, 0x8f4202b0, 0x8f4202f8, 
-0x24420001, 0xaf4202f8, 0x1000008a, 0x8f4202f8, 
-0x8c02025c, 0x27440224, 0xaf4201f0, 0x8c020260, 
-0x24050200, 0x24060008, 0xc002bbf, 0xaf4201f8, 
-0x8f820220, 0x30420008, 0x14400002, 0x24020001, 
-0x24020002, 0xaf420298, 0x8f4202ac, 0x24420001, 
-0xaf4202ac, 0x10000077, 0x8f4202ac, 0x3c0200ff, 
-0x3442ffff, 0x2021824, 0x32c20180, 0x14400006, 
-0x3402fffb, 0x43102b, 0x14400003, 0x0, 
-0x1000006c, 0xaf4300bc, 0x3c040001, 0x24846280, 
-0x3c050003, 0x34a51500, 0x2003021, 0x3821, 
-0xafa00010, 0xc002b3b, 0xafa00014, 0x3c020700, 
-0x34421000, 0x101e02, 0x621825, 0xafa30020, 
-0x8f510018, 0x240200ff, 0x12220002, 0x8021, 
-0x26300001, 0x8c020228, 0x1602000e, 0x1130c0, 
-0x8f42033c, 0x24420001, 0xaf42033c, 0x8f42033c, 
-0x8c020228, 0x3c040001, 0x248461f4, 0x3c050009, 
-0xafa00014, 0xafa20010, 0x8fa60020, 0x1000003f, 
-0x34a50100, 0xd71021, 0x8fa30020, 0x8fa40024, 
-0xac4304c0, 0xac4404c4, 0xc01821, 0x8f440178, 
-0x8f45017c, 0x1021, 0x24070004, 0xafa70010, 
-0xafb00014, 0x8f48000c, 0x24c604c0, 0x2e63021, 
-0xafa80018, 0x8f48010c, 0x24070008, 0xa32821, 
-0xa3482b, 0x822021, 0x100f809, 0x892021, 
-0x1440000b, 0x24070008, 0x8f820120, 0xafa20010, 
-0x8f820124, 0x3c040001, 0x248461fc, 0x3c050009, 
-0xafa20014, 0x8fa60020, 0x1000001c, 0x34a50200, 
-0x8f440160, 0x8f450164, 0x8f43000c, 0xaf500018, 
-0x8f860120, 0x24020010, 0xafa20010, 0xafb00014, 
-0xafa30018, 0x8f42010c, 0x40f809, 0x24c6001c, 
-0x14400010, 0x0, 0x8f420340, 0x24420001, 
-0xaf420340, 0x8f420340, 0x8f820120, 0xafa20010, 
-0x8f820124, 0x3c040001, 0x24846204, 0x3c050009, 
-0xafa20014, 0x8fa60020, 0x34a50300, 0xc002b3b, 
-0x2203821, 0x8f4202e0, 0x24420001, 0xaf4202e0, 
-0x8f4202e0, 0x8f4202f0, 0x24420001, 0xaf4202f0, 
-0x8f4202f0, 0x8fa20034, 0x8fbf0058, 0x8fbe0054, 
-0x8fb50050, 0x8fb3004c, 0x8fb20048, 0x8fb10044, 
-0x8fb00040, 0x3e00008, 0x27bd0060, 0x27bdfff8, 
-0x2408ffff, 0x10a00014, 0x4821, 0x3c0aedb8, 
-0x354a8320, 0x90870000, 0x24840001, 0x3021, 
-0x1071026, 0x30420001, 0x10400002, 0x81842, 
-0x6a1826, 0x604021, 0x24c60001, 0x2cc20008, 
-0x1440fff7, 0x73842, 0x25290001, 0x125102b, 
-0x1440fff0, 0x0, 0x1001021, 0x3e00008, 
-0x27bd0008, 0x27bdffb0, 0xafbf0048, 0xafbe0044, 
-0xafb50040, 0xafb3003c, 0xafb20038, 0xafb10034, 
-0xafb00030, 0x8f870220, 0xafa70024, 0x8f870200, 
-0xafa7002c, 0x8f820220, 0x3c0308ff, 0x3463ffff, 
-0x431024, 0x34420004, 0xaf820220, 0x8f820200, 
-0x3c03c0ff, 0x3463ffff, 0x431024, 0x34420004, 
-0xaf820200, 0x8f530358, 0x8f55035c, 0x8f5e0360, 
-0x8f470364, 0xafa70014, 0x8f470368, 0xafa7001c, 
-0x8f4202d0, 0x274401c0, 0x24420001, 0xaf4202d0, 
-0x8f5002d0, 0x8f510204, 0x8f520200, 0xc002ba8, 
-0x24050400, 0xaf530358, 0xaf55035c, 0xaf5e0360, 
-0x8fa70014, 0xaf470364, 0x8fa7001c, 0xaf470368, 
-0xaf5002d0, 0xaf510204, 0xaf520200, 0x8c02025c, 
-0x27440224, 0xaf4201f0, 0x8c020260, 0x24050200, 
-0x24060008, 0xaf4201f8, 0x24020006, 0xc002bbf, 
-0xaf4201f4, 0x3c023b9a, 0x3442ca00, 0xaf4201fc, 
-0x240203e8, 0x24040002, 0x24030001, 0xaf420294, 
-0xaf440290, 0xaf43029c, 0x8f820220, 0x30420008, 
-0x10400004, 0x0, 0xaf430298, 0x10000003, 
-0x3021, 0xaf440298, 0x3021, 0x3c030001, 
-0x661821, 0x90636d00, 0x3461021, 0x24c60001, 
-0xa043022c, 0x2cc2000f, 0x1440fff8, 0x3461821, 
-0x24c60001, 0x8f820040, 0x24040080, 0x24050080, 
-0x21702, 0x24420030, 0xa062022c, 0x3461021, 
-0xc002ba8, 0xa040022c, 0x8fa70024, 0x30e20004, 
-0x14400006, 0x0, 0x8f820220, 0x3c0308ff, 
-0x3463fffb, 0x431024, 0xaf820220, 0x8fa7002c, 
-0x30e20004, 0x14400006, 0x0, 0x8f820200, 
-0x3c03c0ff, 0x3463fffb, 0x431024, 0xaf820200, 
-0x8fbf0048, 0x8fbe0044, 0x8fb50040, 0x8fb3003c, 
-0x8fb20038, 0x8fb10034, 0x8fb00030, 0x3e00008, 
-0x27bd0050, 0x0, 0x0, 0xaf400104, 
-0x24040001, 0x410c0, 0x2e21821, 0x24820001, 
-0x3c010001, 0x230821, 0xa42234d0, 0x402021, 
-0x2c820080, 0x1440fff8, 0x410c0, 0x24020001, 
-0x3c010001, 0x370821, 0xa42038d0, 0xaf420100, 
-0xaf800228, 0xaf80022c, 0xaf800230, 0xaf800234, 
-0x3e00008, 0x0, 0x27bdffe8, 0xafbf0014, 
-0xafb00010, 0x8f420104, 0x28420005, 0x10400026, 
-0x808021, 0x3c020001, 0x8f430104, 0x344230d0, 
-0x2e22021, 0x318c0, 0x621821, 0x2e31821, 
-0x83102b, 0x10400015, 0x1021, 0x96070000, 
-0x24840006, 0x24660006, 0x9482fffc, 0x14470009, 
-0x2821, 0x9483fffe, 0x96020002, 0x14620006, 
-0xa01021, 0x94820000, 0x96030004, 0x431026, 
-0x2c450001, 0xa01021, 0x14400009, 0x24840008, 
-0x86102b, 0x1440fff0, 0x1021, 0x304200ff, 
-0x14400030, 0x24020001, 0x1000002e, 0x1021, 
-0x1000fffa, 0x24020001, 0x2002021, 0xc00240c, 
-0x24050006, 0x3042007f, 0x218c0, 0x2e31021, 
-0x3c010001, 0x220821, 0x942230d0, 0x1040fff2, 
-0x2e31021, 0x3c060001, 0xc23021, 0x94c630d0, 
-0x10c0ffed, 0x3c080001, 0x350834d2, 0x96070000, 
-0x610c0, 0x572021, 0x882021, 0x94820000, 
-0x14470009, 0x2821, 0x94830002, 0x96020002, 
-0x14620006, 0xa01021, 0x94820004, 0x96030004, 
-0x431026, 0x2c450001, 0xa01021, 0x14400007, 
-0x610c0, 0x2e21021, 0x3c060001, 0xc23021, 
-0x94c634d0, 0x14c0ffeb, 0x610c0, 0x10c0ffd2, 
-0x24020001, 0x8fbf0014, 0x8fb00010, 0x3e00008, 
-0x27bd0018, 0x3e00008, 0x0, 0x27bdffb0, 
-0x801021, 0xafb00030, 0x24500002, 0x2002021, 
-0x24050006, 0xafb10034, 0x408821, 0xafbf0048, 
-0xafbe0044, 0xafb50040, 0xafb3003c, 0xc00240c, 
-0xafb20038, 0x3047007f, 0x710c0, 0x2e21021, 
-0x3c050001, 0xa22821, 0x94a530d0, 0x50a0001c, 
-0xa03021, 0x3c090001, 0x352934d2, 0x96280002, 
-0x510c0, 0x572021, 0x892021, 0x94820000, 
-0x14480009, 0x3021, 0x94830002, 0x96020002, 
-0x14620006, 0xc01021, 0x94820004, 0x96030004, 
-0x431026, 0x2c460001, 0xc01021, 0x14400007, 
-0x510c0, 0x2e21021, 0x3c050001, 0xa22821, 
-0x94a534d0, 0x14a0ffeb, 0x510c0, 0xa03021, 
-0x10c00014, 0x610c0, 0x571821, 0x3c010001, 
-0x230821, 0x8c2334d0, 0x571021, 0xafa30010, 
-0x3c010001, 0x220821, 0x8c2234d4, 0x3c040001, 
-0x24846394, 0xafa20014, 0x8e260000, 0x8e270004, 
-0x3c050004, 0xc002b3b, 0x34a50400, 0x10000063, 
-0x3c020800, 0x8f450100, 0x10a00006, 0x510c0, 
-0x2e21021, 0x3c010001, 0x220821, 0x942234d0, 
-0xaf420100, 0xa03021, 0x14c00011, 0x628c0, 
-0x710c0, 0x2e21021, 0xafa70010, 0x3c010001, 
-0x220821, 0x942230d0, 0x3c040001, 0x248463a0, 
-0xafa20014, 0x8e260000, 0x8e270004, 0x3c050004, 
-0xc002b3b, 0x34a50500, 0x10000048, 0x3c020800, 
-0xb71821, 0x3c020001, 0x96040000, 0x344234d2, 
-0x621821, 0xa4640000, 0x8e020002, 0x720c0, 
-0xac620002, 0x2e41021, 0x3c030001, 0x621821, 
-0x946330d0, 0x2e51021, 0x3c010001, 0x220821, 
-0xa42334d0, 0x2e41021, 0x3c010001, 0x220821, 
-0xa42630d0, 0x8f420104, 0x24420001, 0x28420080, 
-0x1040000f, 0x3c020002, 0x8f420104, 0x3c040001, 
-0x348430d2, 0x96030000, 0x210c0, 0x571021, 
-0x441021, 0xa4430000, 0x8e030002, 0xac430002, 
-0x8f420104, 0x24420001, 0xaf420104, 0x3c020002, 
-0x2c21024, 0x10400011, 0x72142, 0x3c030001, 
-0x346338d8, 0x24020003, 0x441023, 0x21080, 
-0x572021, 0x832021, 0x571021, 0x431021, 
-0x30e5001f, 0x8c430000, 0x24020001, 0xa21004, 
-0x621825, 0x1000000c, 0xac830000, 0x24020003, 
-0x441023, 0x21080, 0x5c2821, 0x5c1021, 
-0x30e4001f, 0x8c430228, 0x24020001, 0x821004, 
-0x621825, 0xaca30228, 0x3c020800, 0x34421000, 
-0x1821, 0xafa20020, 0x8f5e0018, 0x27aa0020, 
-0x240200ff, 0x13c20002, 0xafaa002c, 0x27c30001, 
-0x8c020228, 0x609021, 0x1642000e, 0x1e38c0, 
-0x8f42033c, 0x24420001, 0xaf42033c, 0x8f42033c, 
-0x8c020228, 0x3c040001, 0x2484635c, 0x3c050009, 
-0xafa00014, 0xafa20010, 0x8fa60020, 0x1000006b, 
-0x34a50500, 0xf71021, 0x8fa30020, 0x8fa40024, 
-0xac4304c0, 0xac4404c4, 0x8f830054, 0x8f820054, 
-0x247003e8, 0x2021023, 0x2c4203e9, 0x1040001b, 
-0x9821, 0xe08821, 0x263504c0, 0x8f440178, 
-0x8f45017c, 0x2201821, 0x240a0004, 0xafaa0010, 
-0xafb20014, 0x8f48000c, 0x1021, 0x2f53021, 
-0xafa80018, 0x8f48010c, 0x24070008, 0xa32821, 
-0xa3482b, 0x822021, 0x100f809, 0x892021, 
-0x54400006, 0x24130001, 0x8f820054, 0x2021023, 
-0x2c4203e9, 0x1440ffe9, 0x0, 0x326200ff, 
-0x54400017, 0xaf520018, 0x8f420378, 0x24420001, 
-0xaf420378, 0x8f420378, 0x8f820120, 0x8faa002c, 
-0xafa20010, 0x8f820124, 0x3c040001, 0x24846368, 
-0x3c050009, 0xafa20014, 0x8d460000, 0x10000033, 
-0x34a50600, 0x8f420308, 0x24130001, 0x24420001, 
-0xaf420308, 0x8f420308, 0x1000001c, 0x326200ff, 
-0x8f830054, 0x8f820054, 0x247003e8, 0x2021023, 
-0x2c4203e9, 0x10400014, 0x9821, 0x24110010, 
-0x8f42000c, 0x8f440160, 0x8f450164, 0x8f860120, 
-0xafb10010, 0xafb20014, 0xafa20018, 0x8f42010c, 
-0x24070008, 0x40f809, 0x24c6001c, 0x1440ffe5, 
-0x0, 0x8f820054, 0x2021023, 0x2c4203e9, 
-0x1440ffef, 0x0, 0x326200ff, 0x14400011, 
-0x0, 0x8f420378, 0x24420001, 0xaf420378, 
-0x8f420378, 0x8f820120, 0x8faa002c, 0xafa20010, 
-0x8f820124, 0x3c040001, 0x24846370, 0x3c050009, 
-0xafa20014, 0x8d460000, 0x34a50700, 0xc002b3b, 
-0x3c03821, 0x8f4202b4, 0x24420001, 0xaf4202b4, 
-0x8f4202b4, 0x8f4202f4, 0x24420001, 0xaf4202f4, 
-0x8f4202f4, 0x8fbf0048, 0x8fbe0044, 0x8fb50040, 
-0x8fb3003c, 0x8fb20038, 0x8fb10034, 0x8fb00030, 
-0x3e00008, 0x27bd0050, 0x27bdffa0, 0x801021, 
-0xafb00040, 0x24500002, 0x2002021, 0x24050006, 
-0xafb10044, 0x408821, 0xafbf0058, 0xafbe0054, 
-0xafb50050, 0xafb3004c, 0xc00240c, 0xafb20048, 
-0x3048007f, 0x810c0, 0x2e21021, 0x3c060001, 
-0xc23021, 0x94c630d0, 0x10c0001c, 0x3821, 
-0x3c0a0001, 0x354a34d2, 0x96290002, 0x610c0, 
-0x572021, 0x8a2021, 0x94820000, 0x14490009, 
-0x2821, 0x94830002, 0x96020002, 0x14620006, 
-0xa01021, 0x94820004, 0x96030004, 0x431026, 
-0x2c450001, 0xa01021, 0x14400008, 0x610c0, 
-0xc03821, 0x2e21021, 0x3c060001, 0xc23021, 
-0x94c634d0, 0x14c0ffea, 0x610c0, 0x14c00011, 
-0xafa70028, 0x810c0, 0x2e21021, 0xafa80010, 
-0x3c010001, 0x220821, 0x942230d0, 0x3c040001, 
-0x248463ac, 0xafa20014, 0x8e260000, 0x8e270004, 
-0x3c050004, 0xc002b3b, 0x34a50900, 0x10000075, 
-0x3c020800, 0x10e0000c, 0x610c0, 0x2e21021, 
-0x3c030001, 0x621821, 0x946334d0, 0x710c0, 
-0x2e21021, 0x3c010001, 0x220821, 0xa42334d0, 
-0x1000000b, 0x3c040001, 0x2e21021, 0x3c030001, 
-0x621821, 0x946334d0, 0x810c0, 0x2e21021, 
-0x3c010001, 0x220821, 0xa42330d0, 0x3c040001, 
-0x348430d0, 0x8f430100, 0x610c0, 0x2e21021, 
-0x3c010001, 0x220821, 0xa42334d0, 0x8f420104, 
-0x2e43821, 0x2821, 0x18400029, 0xaf460100, 
-0x24e60006, 0x94c3fffc, 0x96020000, 0x14620009, 
-0x2021, 0x94c3fffe, 0x96020002, 0x14620006, 
-0x801021, 0x94c20000, 0x96030004, 0x431026, 
-0x2c440001, 0x801021, 0x50400014, 0x24a50001, 
-0x8f420104, 0x2442ffff, 0xa2102a, 0x1040000b, 
-0x24e40004, 0x94820006, 0x8c830008, 0xa482fffe, 
-0xac830000, 0x8f420104, 0x24a50001, 0x2442ffff, 
-0xa2102a, 0x1440fff7, 0x24840008, 0x8f420104, 
-0x2442ffff, 0x10000006, 0xaf420104, 0x8f420104, 
-0x24c60008, 0xa2102a, 0x1440ffda, 0x24e70008, 
-0x810c0, 0x2e21021, 0x3c010001, 0x220821, 
-0x942230d0, 0x14400023, 0x3c020800, 0x3c020002, 
-0x2c21024, 0x10400012, 0x82142, 0x3c030001, 
-0x346338d8, 0x24020003, 0x441023, 0x21080, 
-0x572021, 0x832021, 0x571021, 0x431021, 
-0x3105001f, 0x24030001, 0x8c420000, 0xa31804, 
-0x31827, 0x431024, 0x1000000d, 0xac820000, 
-0x24020003, 0x441023, 0x21080, 0x5c2821, 
-0x5c1021, 0x3104001f, 0x24030001, 0x8c420228, 
-0x831804, 0x31827, 0x431024, 0xaca20228, 
-0x3c020800, 0x34422000, 0x1821, 0xafa20020, 
-0x8f5e0018, 0x27ab0020, 0x240200ff, 0x13c20002, 
-0xafab0034, 0x27c30001, 0x8c020228, 0x609021, 
-0x1642000e, 0x1e38c0, 0x8f42033c, 0x24420001, 
-0xaf42033c, 0x8f42033c, 0x8c020228, 0x3c040001, 
-0x2484635c, 0x3c050009, 0xafa00014, 0xafa20010, 
-0x8fa60020, 0x1000006b, 0x34a50500, 0xf71021, 
-0x8fa30020, 0x8fa40024, 0xac4304c0, 0xac4404c4, 
-0x8f830054, 0x8f820054, 0x247003e8, 0x2021023, 
-0x2c4203e9, 0x1040001b, 0x9821, 0xe08821, 
-0x263504c0, 0x8f440178, 0x8f45017c, 0x2201821, 
-0x240b0004, 0xafab0010, 0xafb20014, 0x8f48000c, 
-0x1021, 0x2f53021, 0xafa80018, 0x8f48010c, 
-0x24070008, 0xa32821, 0xa3482b, 0x822021, 
-0x100f809, 0x892021, 0x54400006, 0x24130001, 
-0x8f820054, 0x2021023, 0x2c4203e9, 0x1440ffe9, 
-0x0, 0x326200ff, 0x54400017, 0xaf520018, 
-0x8f420378, 0x24420001, 0xaf420378, 0x8f420378, 
-0x8f820120, 0x8fab0034, 0xafa20010, 0x8f820124, 
-0x3c040001, 0x24846368, 0x3c050009, 0xafa20014, 
-0x8d660000, 0x10000033, 0x34a50600, 0x8f420308, 
-0x24130001, 0x24420001, 0xaf420308, 0x8f420308, 
-0x1000001c, 0x326200ff, 0x8f830054, 0x8f820054, 
-0x247003e8, 0x2021023, 0x2c4203e9, 0x10400014, 
-0x9821, 0x24110010, 0x8f42000c, 0x8f440160, 
-0x8f450164, 0x8f860120, 0xafb10010, 0xafb20014, 
-0xafa20018, 0x8f42010c, 0x24070008, 0x40f809, 
-0x24c6001c, 0x1440ffe5, 0x0, 0x8f820054, 
-0x2021023, 0x2c4203e9, 0x1440ffef, 0x0, 
-0x326200ff, 0x14400011, 0x0, 0x8f420378, 
-0x24420001, 0xaf420378, 0x8f420378, 0x8f820120, 
-0x8fab0034, 0xafa20010, 0x8f820124, 0x3c040001, 
-0x24846370, 0x3c050009, 0xafa20014, 0x8d660000, 
-0x34a50700, 0xc002b3b, 0x3c03821, 0x8f4202b8, 
-0x24420001, 0xaf4202b8, 0x8f4202b8, 0x8f4202f4, 
-0x24420001, 0xaf4202f4, 0x8f4202f4, 0x8fbf0058, 
-0x8fbe0054, 0x8fb50050, 0x8fb3004c, 0x8fb20048, 
-0x8fb10044, 0x8fb00040, 0x3e00008, 0x27bd0060, 
-0x0, 0x0, 0x0, 0x27bdffe0, 
-0x27644000, 0xafbf0018, 0xc002ba8, 0x24051000, 
-0x3c030001, 0x34632cc0, 0x3c040001, 0x34842ec8, 
-0x24020020, 0xaf82011c, 0x2e31021, 0xaf800100, 
-0xaf800104, 0xaf800108, 0xaf800110, 0xaf800114, 
-0xaf800118, 0xaf800120, 0xaf800124, 0xaf800128, 
-0xaf800130, 0xaf800134, 0xaf800138, 0xaf4200ec, 
-0x2e31021, 0xaf4200f0, 0x2e41021, 0xaf4200f4, 
-0x2e41021, 0xaf4200f8, 0x3c020001, 0x571021, 
-0x904240f4, 0x1440001c, 0x3c050001, 0x8f82011c, 
-0x3c040001, 0x24846470, 0x3c050001, 0x34420001, 
-0xaf82011c, 0xafa00010, 0xafa00014, 0x8f86011c, 
-0x34a50100, 0xc002b3b, 0x3821, 0x8c020218, 
-0x30420040, 0x10400014, 0x0, 0x8f82011c, 
-0x3c040001, 0x2484647c, 0x3c050001, 0x34420004, 
-0xaf82011c, 0xafa00010, 0xafa00014, 0x8f86011c, 
-0x10000007, 0x34a50200, 0x3c040001, 0x24846484, 
-0xafa00010, 0xafa00014, 0x8f86011c, 0x34a50300, 
-0xc002b3b, 0x3821, 0x8fbf0018, 0x3e00008, 
-0x27bd0020, 0x8fa90010, 0x8f83012c, 0x8faa0014, 
-0x8fab0018, 0x1060000a, 0x27624fe0, 0x14620002, 
-0x24680020, 0x27684800, 0x8f820128, 0x11020004, 
-0x0, 0x8f820124, 0x15020007, 0x0, 
-0x8f430334, 0x1021, 0x24630001, 0xaf430334, 
-0x10000039, 0x8f430334, 0xac640000, 0xac650004, 
-0xac660008, 0xa467000e, 0xac690018, 0xac6a001c, 
-0xac6b0010, 0xac620014, 0xaf880120, 0x8f4200fc, 
-0x8f4400f4, 0x2442ffff, 0xaf4200fc, 0x8c820000, 
-0x10490005, 0x3042ff8f, 0x10400019, 0x3122ff8f, 
-0x10400018, 0x3c020001, 0x8c830004, 0x2c620010, 
-0x10400013, 0x3c020001, 0x24630001, 0xac830004, 
-0x8f4300f8, 0x344230c8, 0x2e21021, 0x54620004, 
-0x24620008, 0x3c020001, 0x34422ec8, 0x2e21021, 
-0x14440015, 0x24020001, 0x8f820128, 0x24420020, 
-0xaf820128, 0x8f820128, 0x1000000f, 0x24020001, 
-0x3c020001, 0x344230c8, 0x2e21021, 0x54820004, 
-0x24820008, 0x3c020001, 0x34422ec8, 0x2e21021, 
-0x402021, 0x24020001, 0xaf4400f4, 0xac890000, 
-0xac820004, 0x24020001, 0x3e00008, 0x0, 
-0x3e00008, 0x0, 0x8fa90010, 0x8f83010c, 
-0x8faa0014, 0x8fab0018, 0x1060000a, 0x276247e0, 
-0x14620002, 0x24680020, 0x27684000, 0x8f820108, 
-0x11020004, 0x0, 0x8f820104, 0x15020007, 
-0x0, 0x8f430338, 0x1021, 0x24630001, 
-0xaf430338, 0x10000035, 0x8f430338, 0xac640000, 
-0xac650004, 0xac660008, 0xa467000e, 0xac690018, 
-0xac6a001c, 0xac6b0010, 0xac620014, 0xaf880100, 
-0x8f4400ec, 0x8c820000, 0x30420006, 0x10400019, 
-0x31220006, 0x10400018, 0x3c020001, 0x8c830004, 
-0x2c620010, 0x10400013, 0x3c020001, 0x24630001, 
-0xac830004, 0x8f4300f0, 0x34422ec0, 0x2e21021, 
-0x54620004, 0x24620008, 0x3c020001, 0x34422cc0, 
-0x2e21021, 0x14440015, 0x24020001, 0x8f820108, 
-0x24420020, 0xaf820108, 0x8f820108, 0x1000000f, 
-0x24020001, 0x3c020001, 0x34422ec0, 0x2e21021, 
-0x54820004, 0x24820008, 0x3c020001, 0x34422cc0, 
-0x2e21021, 0x402021, 0x24020001, 0xaf4400ec, 
-0xac890000, 0xac820004, 0x24020001, 0x3e00008, 
-0x0, 0x3e00008, 0x0, 0x27bdffd8, 
-0x3c040001, 0x2484648c, 0x3c050001, 0xafbf0024, 
-0xafb20020, 0xafb1001c, 0xafb00018, 0x8f900104, 
-0x8f9100b0, 0x8f92011c, 0x34a52500, 0x8f820100, 
-0x2403021, 0x2203821, 0xafa20010, 0xc002b3b, 
-0xafb00014, 0x8e020008, 0xafa20010, 0x8e02000c, 
-0x3c040001, 0x24846498, 0xafa20014, 0x8e060000, 
-0x8e070004, 0x3c050001, 0xc002b3b, 0x34a52510, 
-0x8e020018, 0xafa20010, 0x8e02001c, 0x3c040001, 
-0x248464a4, 0xafa20014, 0x8e060010, 0x8e070014, 
-0x3c050001, 0xc002b3b, 0x34a52520, 0x3c027f00, 
-0x2221024, 0x3c030800, 0x54430016, 0x3c030200, 
-0x8f82009c, 0x3042ffff, 0x14400012, 0x3c030200, 
-0x3c040001, 0x248464b0, 0x3c050002, 0x34a5f030, 
-0x3021, 0x3821, 0x36420002, 0xaf82011c, 
-0x36220001, 0xaf8200b0, 0xaf900104, 0xaf92011c, 
-0xafa00010, 0xc002b3b, 0xafa00014, 0x10000024, 
-0x0, 0x2c31024, 0x1040000d, 0x2231024, 
-0x1040000b, 0x36420002, 0xaf82011c, 0x36220001, 
-0xaf8200b0, 0xaf900104, 0xaf92011c, 0x8f420330, 
-0x24420001, 0xaf420330, 0x10000015, 0x8f420330, 
-0x3c040001, 0x248464b8, 0x240202a9, 0xafa20010, 
-0xafa00014, 0x8f860144, 0x3c070001, 0x24e764c0, 
-0xc002b3b, 0x3405dead, 0x8f82011c, 0x34420002, 
-0xaf82011c, 0x8f820220, 0x34420004, 0xaf820220, 
-0x8f820140, 0x3c030001, 0x431025, 0xaf820140, 
-0x8fbf0024, 0x8fb20020, 0x8fb1001c, 0x8fb00018, 
-0x3e00008, 0x27bd0028, 0x27bdffd8, 0x3c040001, 
-0x248464e8, 0x3c050001, 0xafbf0024, 0xafb20020, 
-0xafb1001c, 0xafb00018, 0x8f900124, 0x8f9100a0, 
-0x8f92011c, 0x34a52600, 0x8f820120, 0x2403021, 
-0x2203821, 0xafa20010, 0xc002b3b, 0xafb00014, 
-0x8e020008, 0xafa20010, 0x8e02000c, 0x3c040001, 
-0x248464f4, 0xafa20014, 0x8e060000, 0x8e070004, 
-0x3c050001, 0xc002b3b, 0x34a52610, 0x8e020018, 
-0xafa20010, 0x8e02001c, 0x3c040001, 0x24846500, 
-0xafa20014, 0x8e060010, 0x8e070014, 0x3c050001, 
-0xc002b3b, 0x34a52620, 0x3c027f00, 0x2221024, 
-0x3c030800, 0x54430016, 0x3c030200, 0x8f8200ac, 
-0x3042ffff, 0x14400012, 0x3c030200, 0x3c040001, 
-0x2484650c, 0x3c050001, 0x34a5f030, 0x3021, 
-0x3821, 0x36420002, 0xaf82011c, 0x36220001, 
-0xaf8200a0, 0xaf900124, 0xaf92011c, 0xafa00010, 
-0xc002b3b, 0xafa00014, 0x10000024, 0x0, 
-0x2c31024, 0x1040000d, 0x2231024, 0x1040000b, 
-0x36420002, 0xaf82011c, 0x36220001, 0xaf8200a0, 
-0xaf900124, 0xaf92011c, 0x8f42032c, 0x24420001, 
-0xaf42032c, 0x10000015, 0x8f42032c, 0x3c040001, 
-0x248464b8, 0x240202e2, 0xafa20010, 0xafa00014, 
-0x8f860144, 0x3c070001, 0x24e764c0, 0xc002b3b, 
-0x3405dead, 0x8f82011c, 0x34420002, 0xaf82011c, 
-0x8f820220, 0x34420004, 0xaf820220, 0x8f820140, 
-0x3c030001, 0x431025, 0xaf820140, 0x8fbf0024, 
-0x8fb20020, 0x8fb1001c, 0x8fb00018, 0x3e00008, 
-0x27bd0028, 0x6021, 0x5021, 0x3021, 
-0x2821, 0x6821, 0x4821, 0x7821, 
-0x7021, 0x8f880124, 0x8f870104, 0x1580002e, 
-0x8f8b011c, 0x11a00014, 0x31620800, 0x8f820120, 
-0x10460029, 0x0, 0x3c040001, 0x8c846ee4, 
-0x8cc20000, 0x8cc30004, 0xac820000, 0xac830004, 
-0x8cc20008, 0xac820008, 0x94c2000e, 0xa482000e, 
-0x8cc20010, 0x240c0001, 0xac820010, 0x8cc20014, 
-0x10000012, 0x24c60020, 0x10400017, 0x0, 
-0x3c040001, 0x8c846ee4, 0x8d020000, 0x8d030004, 
-0xac820000, 0xac830004, 0x8d020008, 0xac820008, 
-0x9502000e, 0xa482000e, 0x8d020010, 0x25060020, 
-0xac820010, 0x8d020014, 0x240c0001, 0xc01821, 
-0xac820014, 0x27624fe0, 0x43102b, 0x54400001, 
-0x27634800, 0x603021, 0x1540002f, 0x31620100, 
-0x11200014, 0x31628000, 0x8f820100, 0x1045002a, 
-0x31620100, 0x3c040001, 0x8c846ee0, 0x8ca20000, 
-0x8ca30004, 0xac820000, 0xac830004, 0x8ca20008, 
-0xac820008, 0x94a2000e, 0xa482000e, 0x8ca20010, 
-0x240a0001, 0xac820010, 0x8ca20014, 0x10000012, 
-0x24a50020, 0x10400018, 0x31620100, 0x3c040001, 
-0x8c846ee0, 0x8ce20000, 0x8ce30004, 0xac820000, 
-0xac830004, 0x8ce20008, 0xac820008, 0x94e2000e, 
-0xa482000e, 0x8ce20010, 0x24e50020, 0xac820010, 
-0x8ce20014, 0x240a0001, 0xa01821, 0xac820014, 
-0x276247e0, 0x43102b, 0x54400001, 0x27634000, 
-0x602821, 0x31620100, 0x5440001d, 0x31621000, 
-0x11a00009, 0x31a20800, 0x10400004, 0x25020020, 
-0x8f8200a8, 0xa5e20000, 0x25020020, 0xaf820124, 
-0x8f880124, 0x6821, 0x11800011, 0x31621000, 
-0x3c040001, 0x8c846ee4, 0x8c820000, 0x8c830004, 
-0xaf820080, 0xaf830084, 0x8c820008, 0xaf8200a4, 
-0x9482000e, 0xaf8200ac, 0x8c820010, 0x6021, 
-0xaf8200a0, 0x8c8d0010, 0x8c8f0014, 0x31621000, 
-0x1440ff82, 0x0, 0x1120000f, 0x31220800, 
-0x10400004, 0x3c020002, 0x8f8200b8, 0xa5c20000, 
-0x3c020002, 0x1221024, 0x10400004, 0x24e20020, 
-0x8f8200b4, 0xaf8200d4, 0x24e20020, 0xaf820104, 
-0x8f870104, 0x4821, 0x1140ff70, 0x0, 
-0x3c040001, 0x8c846ee0, 0x8c820000, 0x8c830004, 
-0xaf820090, 0xaf830094, 0x8c820008, 0xaf8200b4, 
-0x9482000e, 0xaf82009c, 0x8c820010, 0x5021, 
-0xaf8200b0, 0x8c890010, 0x1000ff60, 0x8c8e0014, 
-0x3e00008, 0x0, 0x6021, 0x5821, 
-0x3021, 0x2821, 0x6821, 0x5021, 
-0x7821, 0x7021, 0x8f880124, 0x8f870104, 
-0x3c180100, 0x1580002e, 0x8f89011c, 0x11a00014, 
-0x31220800, 0x8f820120, 0x10460029, 0x0, 
-0x3c040001, 0x8c846ee4, 0x8cc20000, 0x8cc30004, 
-0xac820000, 0xac830004, 0x8cc20008, 0xac820008, 
-0x94c2000e, 0xa482000e, 0x8cc20010, 0x240c0001, 
-0xac820010, 0x8cc20014, 0x10000012, 0x24c60020, 
-0x10400017, 0x0, 0x3c040001, 0x8c846ee4, 
-0x8d020000, 0x8d030004, 0xac820000, 0xac830004, 
-0x8d020008, 0xac820008, 0x9502000e, 0xa482000e, 
-0x8d020010, 0x25060020, 0xac820010, 0x8d020014, 
-0x240c0001, 0xc01821, 0xac820014, 0x27624fe0, 
-0x43102b, 0x54400001, 0x27634800, 0x603021, 
-0x1560002f, 0x31220100, 0x11400014, 0x31228000, 
-0x8f820100, 0x1045002a, 0x31220100, 0x3c040001, 
-0x8c846ee0, 0x8ca20000, 0x8ca30004, 0xac820000, 
-0xac830004, 0x8ca20008, 0xac820008, 0x94a2000e, 
-0xa482000e, 0x8ca20010, 0x240b0001, 0xac820010, 
-0x8ca20014, 0x10000012, 0x24a50020, 0x10400018, 
-0x31220100, 0x3c040001, 0x8c846ee0, 0x8ce20000, 
-0x8ce30004, 0xac820000, 0xac830004, 0x8ce20008, 
-0xac820008, 0x94e2000e, 0xa482000e, 0x8ce20010, 
-0x24e50020, 0xac820010, 0x8ce20014, 0x240b0001, 
-0xa01821, 0xac820014, 0x276247e0, 0x43102b, 
-0x54400001, 0x27634000, 0x602821, 0x31220100, 
-0x5440001d, 0x31221000, 0x11a00009, 0x31a20800, 
-0x10400004, 0x25020020, 0x8f8200a8, 0xa5e20000, 
-0x25020020, 0xaf820124, 0x8f880124, 0x6821, 
-0x11800011, 0x31221000, 0x3c040001, 0x8c846ee4, 
-0x8c820000, 0x8c830004, 0xaf820080, 0xaf830084, 
-0x8c820008, 0xaf8200a4, 0x9482000e, 0xaf8200ac, 
-0x8c820010, 0x6021, 0xaf8200a0, 0x8c8d0010, 
-0x8c8f0014, 0x31221000, 0x14400022, 0x0, 
-0x1140000f, 0x31420800, 0x10400004, 0x3c020002, 
-0x8f8200b8, 0xa5c20000, 0x3c020002, 0x1421024, 
-0x10400004, 0x24e20020, 0x8f8200b4, 0xaf8200d4, 
-0x24e20020, 0xaf820104, 0x8f870104, 0x5021, 
-0x11600010, 0x0, 0x3c040001, 0x8c846ee0, 
-0x8c820000, 0x8c830004, 0xaf820090, 0xaf830094, 
-0x8c820008, 0xaf8200b4, 0x9482000e, 0xaf82009c, 
-0x8c820010, 0x5821, 0xaf8200b0, 0x8c8a0010, 
-0x8c8e0014, 0x8f820070, 0x3c031000, 0x431024, 
-0x1040ff5c, 0x0, 0x8f820054, 0x24420005, 
-0xaf820078, 0x8c040234, 0x10800016, 0x1821, 
-0x3c020001, 0x571021, 0x8c4240e8, 0x24420005, 
-0x3c010001, 0x370821, 0xac2240e8, 0x3c020001, 
-0x571021, 0x8c4240e8, 0x44102b, 0x14400009, 
-0x24020001, 0x3c030080, 0x3c010001, 0x370821, 
-0xac2040e8, 0x3c010001, 0x370821, 0x1000000c, 
-0xa02240f0, 0x3c020001, 0x571021, 0x904240f0, 
-0x14400006, 0x3c020080, 0x3c020001, 0x571021, 
-0x904240f1, 0x10400002, 0x3c020080, 0x621825, 
-0x8c040230, 0x10800013, 0x0, 0x3c020001, 
-0x571021, 0x8c4240ec, 0x24420005, 0x3c010001, 
-0x370821, 0xac2240ec, 0x3c020001, 0x571021, 
-0x8c4240ec, 0x44102b, 0x14400006, 0x0, 
-0x3c010001, 0x370821, 0xac2040ec, 0x10000006, 
-0x781825, 0x3c020001, 0x571021, 0x904240f2, 
-0x54400001, 0x781825, 0x1060ff1a, 0x0, 
-0x8f420000, 0x10400007, 0x0, 0xaf80004c, 
-0x8f82004c, 0x1040fffd, 0x0, 0x10000005, 
-0x0, 0xaf800048, 0x8f820048, 0x1040fffd, 
-0x0, 0x8f820060, 0x431025, 0xaf820060, 
-0x8f420000, 0x10400003, 0x0, 0x1000ff05, 
-0xaf80004c, 0x1000ff03, 0xaf800048, 0x3e00008, 
-0x0, 0x0, 0x0, 0x3c020001, 
-0x8c426d28, 0x27bdffe8, 0xafbf0014, 0x14400012, 
-0xafb00010, 0x3c100001, 0x26106f90, 0x2002021, 
-0xc002ba8, 0x24052000, 0x26021fe0, 0x3c010001, 
-0xac226eec, 0x3c010001, 0xac226ee8, 0xac020250, 
-0x24022000, 0xac100254, 0xac020258, 0x24020001, 
-0x3c010001, 0xac226d28, 0x8fbf0014, 0x8fb00010, 
-0x3e00008, 0x27bd0018, 0x3c090001, 0x8d296eec, 
-0x8c820000, 0x8fa30010, 0x8fa80014, 0xad220000, 
-0x8c820004, 0xad250008, 0xad220004, 0x8f820054, 
-0xad260010, 0xad270014, 0xad230018, 0xad28001c, 
-0xad22000c, 0x2529ffe0, 0x3c020001, 0x24426f90, 
-0x122102b, 0x10400003, 0x0, 0x3c090001, 
-0x8d296ee8, 0x3c020001, 0x8c426d10, 0xad220000, 
-0x3c020001, 0x8c426d10, 0x3c010001, 0xac296eec, 
-0xad220004, 0xac090250, 0x3e00008, 0x0, 
-0x27bdffd0, 0xafb00010, 0x3c100001, 0x8e106eec, 
-0x3c020001, 0x8c426d10, 0xafb10014, 0x808821, 
-0xafbe0024, 0x8fbe0040, 0x8fa40048, 0xafb20018, 
-0xa09021, 0xafbf0028, 0xafb50020, 0xafb3001c, 
-0xae020000, 0x3c020001, 0x8c426d10, 0xc09821, 
-0xe0a821, 0x10800006, 0xae020004, 0x26050008, 
-0xc002bb3, 0x24060018, 0x10000005, 0x2610ffe0, 
-0x26040008, 0xc002ba8, 0x24050018, 0x2610ffe0, 
-0x3c030001, 0x24636f90, 0x203102b, 0x10400003, 
-0x0, 0x3c100001, 0x8e106ee8, 0x8e220000, 
-0xae020000, 0x8e220004, 0xae120008, 0xae020004, 
-0x8f820054, 0xae130010, 0xae150014, 0xae1e0018, 
-0x8fa80044, 0xae08001c, 0xae02000c, 0x2610ffe0, 
-0x203102b, 0x10400003, 0x0, 0x3c100001, 
-0x8e106ee8, 0x3c020001, 0x8c426d10, 0xae020000, 
-0x3c020001, 0x8c426d10, 0x3c010001, 0xac306eec, 
-0xae020004, 0xac100250, 0x8fbf0028, 0x8fbe0024, 
-0x8fb50020, 0x8fb3001c, 0x8fb20018, 0x8fb10014, 
-0x8fb00010, 0x3e00008, 0x27bd0030, 0x851821, 
-0x83102b, 0x10400006, 0x0, 0xac800000, 
-0x24840004, 0x83102b, 0x5440fffd, 0xac800000, 
-0x3e00008, 0x0, 0xa61821, 0xa3102b, 
-0x10400007, 0x0, 0x8c820000, 0xaca20000, 
-0x24a50004, 0xa3102b, 0x1440fffb, 0x24840004, 
-0x3e00008, 0x0, 0x861821, 0x83102b, 
-0x10400007, 0x0, 0x8ca20000, 0xac820000, 
-0x24840004, 0x83102b, 0x1440fffb, 0x24a50004, 
-0x3e00008, 0x0, 0x63080, 0x861821, 
-0x83102b, 0x10400006, 0x0, 0xac850000, 
-0x24840004, 0x83102b, 0x5440fffd, 0xac850000, 
-0x3e00008, 0x0, 0x0, 0x26e50028, 
-0xa03021, 0x274301c0, 0x8f4d0358, 0x8f47035c, 
-0x8f480360, 0x8f490364, 0x8f4a0368, 0x8f4b0204, 
-0x8f4c0200, 0x24640400, 0x64102b, 0x10400008, 
-0x3c0208ff, 0x8cc20000, 0xac620000, 0x24630004, 
-0x64102b, 0x1440fffb, 0x24c60004, 0x3c0208ff, 
-0x3442ffff, 0x3c03c0ff, 0xaf4d0358, 0xaf47035c, 
-0xaf480360, 0xaf490364, 0xaf4a0368, 0xaf4b0204, 
-0xaf4c0200, 0x8f840220, 0x3463ffff, 0x8f860200, 
-0x821024, 0x34420004, 0xc31824, 0x34630004, 
-0xaf820220, 0xaf830200, 0x8ca20214, 0xac020084, 
-0x8ca20218, 0xac020088, 0x8ca2021c, 0xac02008c, 
-0x8ca20220, 0xac020090, 0x8ca20224, 0xac020094, 
-0x8ca20228, 0xac020098, 0x8ca2022c, 0xac02009c, 
-0x8ca20230, 0xac0200a0, 0x8ca20234, 0xac0200a4, 
-0x8ca20238, 0xac0200a8, 0x8ca2023c, 0xac0200ac, 
-0x8ca20240, 0xac0200b0, 0x8ca20244, 0xac0200b4, 
-0x8ca20248, 0xac0200b8, 0x8ca2024c, 0xac0200bc, 
-0x8ca2001c, 0xac020080, 0x8ca20018, 0xac0200c0, 
-0x8ca20020, 0xac0200cc, 0x8ca20024, 0xac0200d0, 
-0x8ca201d0, 0xac0200e0, 0x8ca201d4, 0xac0200e4, 
-0x8ca201d8, 0xac0200e8, 0x8ca201dc, 0xac0200ec, 
-0x8ca201e0, 0xac0200f0, 0x8ca20098, 0x8ca3009c, 
-0xac0300fc, 0x8ca200a8, 0x8ca300ac, 0xac0300f4, 
-0x8ca200a0, 0x8ca300a4, 0x30840004, 0xac0300f8, 
-0x14800007, 0x30c20004, 0x8f820220, 0x3c0308ff, 
-0x3463fffb, 0x431024, 0xaf820220, 0x30c20004, 
-0x14400006, 0x0, 0x8f820200, 0x3c03c0ff, 
-0x3463fffb, 0x431024, 0xaf820200, 0x8f4202dc, 
-0xa34005c5, 0x24420001, 0xaf4202dc, 0x8f4202dc, 
-0x3e00008, 0x0, 0x27bdffd8, 0xafbf0024, 
-0xafb00020, 0x8f430024, 0x8f420020, 0x10620038, 
-0x0, 0x8f430020, 0x8f420024, 0x622023, 
-0x4810003, 0x0, 0x8f420040, 0x822021, 
-0x8f430030, 0x8f420024, 0x43102b, 0x14400005, 
-0x0, 0x8f430040, 0x8f420024, 0x10000005, 
-0x621023, 0x8f420030, 0x8f430024, 0x431023, 
-0x2442ffff, 0x406021, 0x8c102a, 0x54400001, 
-0x806021, 0x8f4a0024, 0x8f490040, 0x8f480024, 
-0x8f440180, 0x8f450184, 0x8f460024, 0x8f4b001c, 
-0x24070001, 0xafa70010, 0x84100, 0x1001821, 
-0x14c5021, 0x2529ffff, 0x1498024, 0xafb00014, 
-0x8f470014, 0x1021, 0x63100, 0xafa70018, 
-0xa32821, 0xa3382b, 0x822021, 0x872021, 
-0x8f420108, 0x1663021, 0x40f809, 0xc3900, 
-0x54400001, 0xaf500024, 0x8f430024, 0x8f420020, 
-0x14620018, 0x0, 0x8f420000, 0x10400007, 
-0x0, 0xaf80004c, 0x8f82004c, 0x1040fffd, 
-0x0, 0x10000005, 0x0, 0xaf800048, 
-0x8f820048, 0x1040fffd, 0x0, 0x8f820060, 
-0x2403ffef, 0x431024, 0xaf820060, 0x8f420000, 
-0x10400003, 0x0, 0x10000002, 0xaf80004c, 
-0xaf800048, 0x8fbf0024, 0x8fb00020, 0x3e00008, 
-0x27bd0028, 0x3e00008, 0x0, 0x27bdffc0, 
-0x32c20020, 0xafbf0038, 0xafb30034, 0xafb20030, 
-0xafb1002c, 0x10400004, 0xafb00028, 0x8f530028, 
-0x10000002, 0x0, 0x8f530020, 0x8f420030, 
-0x105300eb, 0x21100, 0x8f43001c, 0x628021, 
-0x8e040000, 0x8e050004, 0x96120008, 0x8f420090, 
-0x9611000a, 0x3246ffff, 0x46102a, 0x10400017, 
-0x0, 0x8f8200d8, 0x8f430098, 0x431023, 
-0x2442dcbe, 0xaf420090, 0x8f420090, 0x2842dcbf, 
-0x10400005, 0x0, 0x8f420090, 0x8f430144, 
-0x431021, 0xaf420090, 0x8f420090, 0x46102a, 
-0x10400006, 0x0, 0x8f420348, 0x24420001, 
-0xaf420348, 0x100000e1, 0x8f420348, 0x8f8200fc, 
-0x14400006, 0x0, 0x8f420344, 0x24420001, 
-0xaf420344, 0x100000d9, 0x8f420344, 0x934205c2, 
-0x1040000b, 0x32c20008, 0x10400008, 0x32220200, 
-0x10400006, 0x3c034000, 0x9602000e, 0xaf4300ac, 
-0x21400, 0x10000002, 0xaf4200b0, 0xaf4000ac, 
-0x32220004, 0x1040007f, 0x32220800, 0x10400003, 
-0x3247ffff, 0x10000002, 0x24020020, 0x24020004, 
-0xafa20010, 0x8f420030, 0xafa20014, 0x8f420010, 
-0x3c030002, 0x431025, 0xafa20018, 0x8f460098, 
-0x8f420108, 0x40f809, 0x0, 0x104000b7, 
-0x0, 0x8f42009c, 0x8f430094, 0x2421021, 
-0xaf42009c, 0xae03000c, 0x8f4200ac, 0x10400008, 
-0x3c034000, 0x8f420094, 0x431025, 0xafa20020, 
-0x8f42009c, 0x8f4300b0, 0x10000004, 0x431025, 
-0x8f420094, 0xafa20020, 0x8f42009c, 0xafa20024, 
-0x8f8200fc, 0x8fa30020, 0x8fa40024, 0xac430000, 
-0xac440004, 0x24420008, 0xaf8200f0, 0x8f42009c, 
-0x8f440270, 0x8f450274, 0x401821, 0x1021, 
-0xa32821, 0xa3302b, 0x822021, 0x862021, 
-0x32230060, 0x24020040, 0xaf440270, 0xaf450274, 
-0x10620017, 0x2c620041, 0x10400005, 0x24020020, 
-0x10620008, 0x24020001, 0x10000026, 0x0, 
-0x24020060, 0x10620019, 0x24020001, 0x10000021, 
-0x0, 0x8f420278, 0x8f43027c, 0x24630001, 
-0x2c640001, 0x441021, 0xaf420278, 0xaf43027c, 
-0x8f420278, 0x8f43027c, 0x10000016, 0x24020001, 
-0x8f420280, 0x8f430284, 0x24630001, 0x2c640001, 
-0x441021, 0xaf420280, 0xaf430284, 0x8f420280, 
-0x8f430284, 0x1000000b, 0x24020001, 0x8f420288, 
-0x8f43028c, 0x24630001, 0x2c640001, 0x441021, 
-0xaf420288, 0xaf43028c, 0x8f420288, 0x8f43028c, 
-0x24020001, 0xa34205c2, 0x8f420098, 0x3244ffff, 
-0x2406fff8, 0x8f45013c, 0x441021, 0x24420007, 
-0x461024, 0x24840007, 0xaf420094, 0x8f420090, 
-0x8f430094, 0x862024, 0x441023, 0x65182b, 
-0x14600005, 0xaf420090, 0x8f420094, 0x8f430144, 
-0x431023, 0xaf420094, 0x8f420094, 0x10000023, 
-0xaf40009c, 0x3247ffff, 0x50e00022, 0x32c20020, 
-0x14400002, 0x24020010, 0x24020002, 0xafa20010, 
-0x8f420030, 0xafa20014, 0x8f420010, 0xafa20018, 
-0x8f460098, 0x8f420108, 0x40f809, 0x0, 
-0x1040003a, 0x3245ffff, 0x8f420098, 0x8f430090, 
-0x8f46013c, 0x451021, 0xaf420098, 0x8f42009c, 
-0x8f440098, 0xa34005c2, 0x651823, 0xaf430090, 
-0x451021, 0x86202b, 0x14800005, 0xaf42009c, 
-0x8f420098, 0x8f430144, 0x431023, 0xaf420098, 
-0x32c20020, 0x10400005, 0x0, 0x8f420358, 
-0x2442ffff, 0xaf420358, 0x8f420358, 0x8f420030, 
-0x8f430040, 0x24420001, 0x2463ffff, 0x431024, 
-0xaf420030, 0x8f420030, 0x14530018, 0x0, 
-0x8f420000, 0x10400007, 0x0, 0xaf80004c, 
-0x8f82004c, 0x1040fffd, 0x0, 0x10000005, 
-0x0, 0xaf800048, 0x8f820048, 0x1040fffd, 
-0x0, 0x8f820060, 0x2403fff7, 0x431024, 
-0xaf820060, 0x8f420000, 0x10400003, 0x0, 
-0x10000002, 0xaf80004c, 0xaf800048, 0x8fbf0038, 
-0x8fb30034, 0x8fb20030, 0x8fb1002c, 0x8fb00028, 
-0x3e00008, 0x27bd0040, 0x3e00008, 0x0, 
-0x27bdffd0, 0x32c20020, 0xafbf002c, 0xafb20028, 
-0xafb10024, 0x10400004, 0xafb00020, 0x8f520028, 
-0x10000002, 0x0, 0x8f520020, 0x8f420030, 
-0x105200b5, 0x21100, 0x8f43001c, 0x628021, 
-0x8e040000, 0x8e050004, 0x96110008, 0x8f420090, 
-0x9607000a, 0x3226ffff, 0x46102a, 0x10400017, 
-0x0, 0x8f8200d8, 0x8f430098, 0x431023, 
-0x2442dc46, 0xaf420090, 0x8f420090, 0x2842dc47, 
-0x10400005, 0x0, 0x8f420090, 0x8f430144, 
-0x431021, 0xaf420090, 0x8f420090, 0x46102a, 
-0x10400006, 0x0, 0x8f420348, 0x24420001, 
-0xaf420348, 0x100000ab, 0x8f420348, 0x8f8600fc, 
-0x10c0000c, 0x0, 0x8f8200f4, 0x2403fff8, 
-0x431024, 0x461023, 0x218c3, 0x58600001, 
-0x24630100, 0x8f42008c, 0x43102b, 0x14400006, 
-0x712c2, 0x8f420344, 0x24420001, 0xaf420344, 
-0x10000098, 0x8f420344, 0x934305c2, 0x1060000f, 
-0x30460001, 0x8f420010, 0x34480400, 0x32c20008, 
-0x10400008, 0x30e20200, 0x10400006, 0x3c034000, 
-0x9602000e, 0xaf4300ac, 0x21400, 0x10000004, 
-0xaf4200b0, 0x10000002, 0xaf4000ac, 0x8f480010, 
-0x30e20004, 0x10400045, 0x3227ffff, 0x8f4900ac, 
-0x11200005, 0x30c200ff, 0x14400006, 0x24020040, 
-0x10000004, 0x24020008, 0x14400002, 0x24020020, 
-0x24020004, 0xafa20010, 0x8f430030, 0x11200004, 
-0xafa30014, 0x8f4200b0, 0x621025, 0xafa20014, 
-0x3c020002, 0x1021025, 0xafa20018, 0x8f460098, 
-0x8f420108, 0x40f809, 0x0, 0x10400069, 
-0x3224ffff, 0x8f42008c, 0x8f430094, 0x24420001, 
-0xaf42008c, 0x24020001, 0xae03000c, 0xa34205c2, 
-0x8f420098, 0x2406fff8, 0x8f45013c, 0x441021, 
-0x24420007, 0x461024, 0x24840007, 0xaf420094, 
-0x8f420090, 0x8f430094, 0x862024, 0x441023, 
-0x65182b, 0x14600005, 0xaf420090, 0x8f420094, 
-0x8f430144, 0x431023, 0xaf420094, 0x8f430094, 
-0x8f420140, 0x43102b, 0x10400009, 0x0, 
-0x8f43013c, 0x8f440094, 0x8f420090, 0x8f450138, 
-0x641823, 0x431023, 0xaf420090, 0xaf450094, 
-0x8f420094, 0x1000001f, 0xaf420098, 0x10e0001d, 
-0x30c200ff, 0x14400002, 0x24020010, 0x24020002, 
-0xafa20010, 0x8f420030, 0xafa80018, 0xafa20014, 
-0x8f460098, 0x8f420108, 0x40f809, 0x0, 
-0x10400030, 0x3225ffff, 0x8f420098, 0x8f44013c, 
-0x451021, 0xaf420098, 0x8f420090, 0x8f430098, 
-0xa34005c2, 0x451023, 0x64182b, 0x14600005, 
-0xaf420090, 0x8f420098, 0x8f430144, 0x431023, 
-0xaf420098, 0x8f420030, 0x8f430040, 0x24420001, 
-0x2463ffff, 0x431024, 0xaf420030, 0x8f420030, 
-0x14520018, 0x0, 0x8f420000, 0x10400007, 
-0x0, 0xaf80004c, 0x8f82004c, 0x1040fffd, 
-0x0, 0x10000005, 0x0, 0xaf800048, 
-0x8f820048, 0x1040fffd, 0x0, 0x8f820060, 
-0x2403fff7, 0x431024, 0xaf820060, 0x8f420000, 
-0x10400003, 0x0, 0x10000002, 0xaf80004c, 
-0xaf800048, 0x8fbf002c, 0x8fb20028, 0x8fb10024, 
-0x8fb00020, 0x3e00008, 0x27bd0030, 0x3e00008, 
-0x0, 0x27bdffd8, 0x3c020001, 0x34422ec0, 
-0xafbf0020, 0x8f4300f0, 0x8f840108, 0x2e21021, 
-0x54620004, 0x24620008, 0x3c020001, 0x34422cc0, 
-0x2e21021, 0x401821, 0xaf4300f0, 0xac600000, 
-0x8f4200ec, 0x8c660004, 0x14620004, 0x3c020001, 
-0x24820020, 0x1000000f, 0xaf820108, 0x8f4300f0, 
-0x34422ec0, 0x2e21021, 0x54620004, 0x24620008, 
-0x3c020001, 0x34422cc0, 0x2e21021, 0x401821, 
-0x8c620004, 0x21140, 0x821021, 0xaf820108, 
-0xac600000, 0x8c850018, 0x30a20036, 0x1040006c, 
-0x30a20001, 0x8c82001c, 0x8f430040, 0x8f440034, 
-0x24420001, 0x2463ffff, 0x431024, 0x862021, 
-0xaf42002c, 0x30a20030, 0x14400006, 0xaf440034, 
-0x8f420034, 0x8c03023c, 0x43102b, 0x144000b4, 
-0x0, 0x32c20010, 0x10400028, 0x24070008, 
-0x8f440170, 0x8f450174, 0x8f43002c, 0x8f48000c, 
-0x8f860120, 0x24020080, 0xafa20010, 0xafa30014, 
-0xafa80018, 0x8f42010c, 0x40f809, 0x24c6001c, 
-0x14400011, 0x24020001, 0x3c010001, 0x370821, 
-0xa02240f1, 0x8f820124, 0xafa20010, 0x8f820128, 
-0x3c040001, 0x248467c4, 0xafa20014, 0x8f46002c, 
-0x8f870120, 0x3c050009, 0xc002b3b, 0x34a51100, 
-0x10000036, 0x0, 0x8f420300, 0x8f43002c, 
-0x24420001, 0xaf420300, 0x8f420300, 0x24020001, 
-0xa34205c1, 0x10000026, 0xaf430038, 0x8f440170, 
-0x8f450174, 0x8f43002c, 0x8f48000c, 0x8f860120, 
-0x24020020, 0xafa20010, 0xafa30014, 0xafa80018, 
-0x8f42010c, 0x40f809, 0x24c6001c, 0x14400011, 
-0x24020001, 0x3c010001, 0x370821, 0xa02240f0, 
-0x8f820124, 0xafa20010, 0x8f820128, 0x3c040001, 
-0x248467b8, 0xafa20014, 0x8f46002c, 0x8f870120, 
-0x3c050009, 0xc002b3b, 0x34a50900, 0x1000000f, 
-0x0, 0x8f420300, 0x24420001, 0xaf420300, 
-0x8f420300, 0x8f42002c, 0xa34005c1, 0xaf420038, 
-0x3c010001, 0x370821, 0xa02040f1, 0x3c010001, 
-0x370821, 0xa02040f0, 0xaf400034, 0x8f420314, 
-0x24420001, 0xaf420314, 0x10000059, 0x8f420314, 
-0x10400022, 0x30a27000, 0x8c85001c, 0x8f420028, 
-0xa22023, 0x4810003, 0x0, 0x8f420040, 
-0x822021, 0x8f420358, 0x8f430000, 0xaf450028, 
-0x441021, 0x10600007, 0xaf420358, 0xaf80004c, 
-0x8f82004c, 0x1040fffd, 0x0, 0x10000005, 
-0x0, 0xaf800048, 0x8f820048, 0x1040fffd, 
-0x0, 0x8f820060, 0x34420008, 0xaf820060, 
-0x8f420000, 0x10400003, 0x0, 0x10000038, 
-0xaf80004c, 0x10000036, 0xaf800048, 0x1040002f, 
-0x30a21000, 0x1040000c, 0x30a24000, 0x8c83001c, 
-0x8f420050, 0x622023, 0x4820001, 0x24840200, 
-0x8f42035c, 0x441021, 0xaf42035c, 0x8f420368, 
-0x1000001a, 0xaf430050, 0x1040000c, 0x32c28000, 
-0x8c83001c, 0x8f420070, 0x622023, 0x4820001, 
-0x24840400, 0x8f420364, 0x441021, 0xaf420364, 
-0x8f420368, 0x1000000d, 0xaf430070, 0x1040000e, 
-0x3c020800, 0x8c83001c, 0x8f420060, 0x622023, 
-0x4820001, 0x24840100, 0x8f420360, 0x441021, 
-0xaf420360, 0x8f420368, 0xaf430060, 0x441021, 
-0xaf420368, 0x3c020800, 0x2c21024, 0x50400008, 
-0x36940040, 0x10000006, 0x0, 0x30a20100, 
-0x10400003, 0x0, 0xc002bd8, 0x0, 
-0x8fbf0020, 0x3e00008, 0x27bd0028, 0x3e00008, 
-0x0, 0x27bdffa8, 0xafbf0050, 0xafbe004c, 
-0xafb50048, 0xafb30044, 0xafb20040, 0xafb1003c, 
-0xafb00038, 0x8f910108, 0x26220020, 0xaf820108, 
-0x8e320018, 0xa821, 0x32420024, 0x104001ba, 
-0xf021, 0x8e26001c, 0x8f43001c, 0x61100, 
-0x621821, 0x8c70000c, 0x9604000c, 0x962d0016, 
-0x9473000a, 0x2c8305dd, 0x38828870, 0x2c420001, 
-0x621825, 0x10600015, 0x2821, 0x32c20040, 
-0x10400015, 0x24020800, 0x96030014, 0x14620012, 
-0x3402aaaa, 0x9603000e, 0x14620007, 0x2021, 
-0x96030010, 0x24020300, 0x14620004, 0x801021, 
-0x96020012, 0x2c440001, 0x801021, 0x54400006, 
-0x24050016, 0x10000004, 0x0, 0x24020800, 
-0x50820001, 0x2405000e, 0x934205c3, 0x14400008, 
-0x5821, 0x240b0001, 0x32620180, 0xaf4500a8, 
-0xaf5000a0, 0x10400002, 0xaf4600a4, 0xa34b05c3, 
-0x10a00085, 0x2054021, 0x91020000, 0x3821, 
-0x3042000f, 0x25080, 0x32c20002, 0x10400012, 
-0x10a1821, 0x32620002, 0x10400010, 0x32c20001, 
-0x1002021, 0x94820000, 0x24840002, 0xe23821, 
-0x83102b, 0x1440fffb, 0x30e2ffff, 0x71c02, 
-0x623821, 0x71c02, 0x30e2ffff, 0x623821, 
-0x71027, 0xa502000a, 0x32c20001, 0x1040006a, 
-0x32620001, 0x10400068, 0x0, 0x8f4200a8, 
-0x10400065, 0x0, 0x8f4200a0, 0x8f4300a8, 
-0x431021, 0x904c0009, 0x318900ff, 0x39230006, 
-0x3182b, 0x39220011, 0x2102b, 0x621824, 
-0x1060000c, 0x3c050006, 0x8f4200a4, 0x3c040001, 
-0x248467d4, 0xafa20010, 0x8f4200a0, 0x34a54600, 
-0x1203821, 0xc002b3b, 0xafa20014, 0x1000004e, 
-0x0, 0x32c20004, 0x14400013, 0x2821, 
-0x316200ff, 0x14400004, 0x0, 0x95020002, 
-0x1000000d, 0x4a2823, 0x9505000c, 0x9502000e, 
-0x95030010, 0xa22821, 0xa32821, 0x95030012, 
-0x91040009, 0x95020002, 0xa32821, 0xa42821, 
-0x4a1023, 0xa22821, 0x2002021, 0x94820000, 
-0x24840002, 0xe23821, 0x88102b, 0x1440fffb, 
-0x71c02, 0x30e2ffff, 0x623821, 0x71c02, 
-0x30e2ffff, 0x623821, 0x1a52821, 0x51c02, 
-0x30a2ffff, 0x622821, 0x51c02, 0x30a2ffff, 
-0x622821, 0xa72823, 0x51402, 0xa22821, 
-0x30a5ffff, 0x50a00001, 0x3405ffff, 0x316200ff, 
-0x14400008, 0x318300ff, 0x8f4300a0, 0x8f4200a8, 
-0x624021, 0x91020000, 0x3042000f, 0x25080, 
-0x318300ff, 0x24020006, 0x14620003, 0x10a1021, 
-0x10000002, 0x24440010, 0x24440006, 0x316200ff, 
-0x14400006, 0x0, 0x94820000, 0xa22821, 
-0x51c02, 0x30a2ffff, 0x622821, 0x934205c3, 
-0x10400003, 0x32620100, 0x50400003, 0xa4850000, 
-0x52827, 0xa4850000, 0x9622000e, 0x8f43009c, 
-0x621821, 0x32a200ff, 0x10400007, 0xaf43009c, 
-0x3c024000, 0x2021025, 0xafa20020, 0x8f42009c, 
-0x10000003, 0x5e1025, 0xafb00020, 0x8f42009c, 
-0xafa20024, 0x32620080, 0x10400010, 0x32620100, 
-0x8f4200b4, 0x24430001, 0x210c0, 0x571021, 
-0xaf4300b4, 0x8fa30020, 0x8fa40024, 0x3c010001, 
-0x220821, 0xac2338e8, 0x3c010001, 0x220821, 
-0xac2438ec, 0x100000a5, 0x32c20020, 0x10400064, 
-0x0, 0x8f4200b4, 0x24430001, 0x210c0, 
-0x571021, 0xaf4300b4, 0x8fa30020, 0x8fa40024, 
-0x3c010001, 0x220821, 0xac2338e8, 0x3c010001, 
-0x220821, 0xac2438ec, 0x8f4200b4, 0x10400051, 
-0x3821, 0x3c090001, 0x352938e8, 0x3c08001f, 
-0x3508ffff, 0x240bffff, 0x340affff, 0x710c0, 
-0x571021, 0x491021, 0x8c430000, 0x8c440004, 
-0xafa30028, 0xafa4002c, 0x8f8200fc, 0x8fa30028, 
-0x8fa4002c, 0xac430000, 0xac440004, 0x24420008, 
-0xaf8200f0, 0x8f42008c, 0x2442ffff, 0xaf42008c, 
-0x97a2002e, 0x8f440270, 0x8f450274, 0x401821, 
-0x1021, 0xa32821, 0xa3302b, 0x822021, 
-0x862021, 0xaf440270, 0xaf450274, 0x8fa20028, 
-0x481024, 0x90430000, 0x30630001, 0x1460000b, 
-0x402021, 0x8f420278, 0x8f43027c, 0x24630001, 
-0x2c640001, 0x441021, 0xaf420278, 0xaf43027c, 
-0x8f420278, 0x1000001a, 0x8f43027c, 0x8c820000, 
-0x144b000e, 0x0, 0x94820004, 0x144a000b, 
-0x0, 0x8f420288, 0x8f43028c, 0x24630001, 
-0x2c640001, 0x441021, 0xaf420288, 0xaf43028c, 
-0x8f420288, 0x1000000a, 0x8f43028c, 0x8f420280, 
-0x8f430284, 0x24630001, 0x2c640001, 0x441021, 
-0xaf420280, 0xaf430284, 0x8f420280, 0x8f430284, 
-0x8f4200b4, 0x24e70001, 0xe2102b, 0x1440ffb8, 
-0x710c0, 0xa34005c3, 0x1000003f, 0xaf4000b4, 
-0x8f8200fc, 0x8fa30020, 0x8fa40024, 0xac430000, 
-0xac440004, 0x24420008, 0xaf8200f0, 0x8f42009c, 
-0x8f46008c, 0x8f440270, 0x8f450274, 0x401821, 
-0x1021, 0x24c6ffff, 0xaf46008c, 0xa32821, 
-0xa3302b, 0x822021, 0x862021, 0xaf440270, 
-0xaf450274, 0x92020000, 0x30420001, 0x1440000c, 
-0x2402ffff, 0x8f420278, 0x8f43027c, 0x24630001, 
-0x2c640001, 0x441021, 0xaf420278, 0xaf43027c, 
-0x8f420278, 0x8f43027c, 0x1000001c, 0x32c20020, 
-0x8e030000, 0x1462000f, 0x3402ffff, 0x96030004, 
-0x1462000c, 0x0, 0x8f420288, 0x8f43028c, 
-0x24630001, 0x2c640001, 0x441021, 0xaf420288, 
-0xaf43028c, 0x8f420288, 0x8f43028c, 0x1000000b, 
-0x32c20020, 0x8f420280, 0x8f430284, 0x24630001, 
-0x2c640001, 0x441021, 0xaf420280, 0xaf430284, 
-0x8f420280, 0x8f430284, 0x32c20020, 0x10400005, 
-0xaf40009c, 0x8f420358, 0x2442ffff, 0xaf420358, 
-0x8f420358, 0x8e22001c, 0x8f430040, 0x24420001, 
-0x2463ffff, 0x431024, 0xaf42002c, 0x32420060, 
-0x14400008, 0x32c20010, 0x8f420034, 0x24420001, 
-0xaf420034, 0x8c03023c, 0x43102b, 0x14400102, 
-0x32c20010, 0x10400018, 0x24070008, 0x8f440170, 
-0x8f450174, 0x8f43002c, 0x8f48000c, 0x8f860120, 
-0x24020080, 0xafa20010, 0xafa30014, 0xafa80018, 
-0x8f42010c, 0x40f809, 0x24c6001c, 0x10400047, 
-0x24020001, 0x8f420300, 0x8f43002c, 0x24420001, 
-0xaf420300, 0x8f420300, 0x24020001, 0xa34205c1, 
-0x1000007c, 0xaf430038, 0x8f440170, 0x8f450174, 
-0x8f43002c, 0x8f48000c, 0x8f860120, 0x24020020, 
-0xafa20010, 0xafa30014, 0xafa80018, 0x8f42010c, 
-0x40f809, 0x24c6001c, 0x10400057, 0x24020001, 
-0x10000065, 0x0, 0x32420012, 0x10400075, 
-0x32420001, 0x9622000e, 0x8f43009c, 0x621821, 
-0x32c20020, 0x10400005, 0xaf43009c, 0x8f420358, 
-0x2442ffff, 0xaf420358, 0x8f420358, 0x8e22001c, 
-0x8f430040, 0x24420001, 0x2463ffff, 0x431024, 
-0xaf42002c, 0x32420010, 0x14400008, 0x32c20010, 
-0x8f420034, 0x24420001, 0xaf420034, 0x8c03023c, 
-0x43102b, 0x144000bc, 0x32c20010, 0x10400028, 
-0x24070008, 0x8f440170, 0x8f450174, 0x8f43002c, 
-0x8f48000c, 0x8f860120, 0x24020080, 0xafa20010, 
-0xafa30014, 0xafa80018, 0x8f42010c, 0x40f809, 
-0x24c6001c, 0x14400011, 0x24020001, 0x3c010001, 
-0x370821, 0xa02240f1, 0x8f820124, 0xafa20010, 
-0x8f820128, 0x3c040001, 0x248467c4, 0xafa20014, 
-0x8f46002c, 0x8f870120, 0x3c050009, 0xc002b3b, 
-0x34a51100, 0x10000036, 0x0, 0x8f420300, 
-0x8f43002c, 0x24420001, 0xaf420300, 0x8f420300, 
-0x24020001, 0xa34205c1, 0x10000026, 0xaf430038, 
-0x8f440170, 0x8f450174, 0x8f43002c, 0x8f48000c, 
-0x8f860120, 0x24020020, 0xafa20010, 0xafa30014, 
-0xafa80018, 0x8f42010c, 0x40f809, 0x24c6001c, 
-0x14400011, 0x24020001, 0x3c010001, 0x370821, 
-0xa02240f0, 0x8f820124, 0xafa20010, 0x8f820128, 
-0x3c040001, 0x248467b8, 0xafa20014, 0x8f46002c, 
-0x8f870120, 0x3c050009, 0xc002b3b, 0x34a50900, 
-0x1000000f, 0x0, 0x8f420300, 0x24420001, 
-0xaf420300, 0x8f420300, 0x8f42002c, 0xa34005c1, 
-0xaf420038, 0x3c010001, 0x370821, 0xa02040f1, 
-0x3c010001, 0x370821, 0xa02040f0, 0xaf400034, 
-0x8f420314, 0x24420001, 0xaf420314, 0x10000062, 
-0x8f420314, 0x10400022, 0x32427000, 0x8e25001c, 
-0x8f420028, 0xa22023, 0x4810003, 0x0, 
-0x8f420040, 0x822021, 0x8f420358, 0x8f430000, 
-0xaf450028, 0x441021, 0x10600007, 0xaf420358, 
-0xaf80004c, 0x8f82004c, 0x1040fffd, 0x0, 
-0x10000005, 0x0, 0xaf800048, 0x8f820048, 
-0x1040fffd, 0x0, 0x8f820060, 0x34420008, 
-0xaf820060, 0x8f420000, 0x10400003, 0x0, 
-0x10000041, 0xaf80004c, 0x1000003f, 0xaf800048, 
-0x1040002f, 0x32421000, 0x1040000c, 0x32424000, 
-0x8e23001c, 0x8f420050, 0x622023, 0x4820001, 
-0x24840200, 0x8f42035c, 0x441021, 0xaf42035c, 
-0x8f420368, 0x1000001a, 0xaf430050, 0x1040000c, 
-0x32c28000, 0x8e23001c, 0x8f420070, 0x622023, 
-0x4820001, 0x24840400, 0x8f420364, 0x441021, 
-0xaf420364, 0x8f420368, 0x1000000d, 0xaf430070, 
-0x1040000e, 0x3c020800, 0x8e23001c, 0x8f420060, 
-0x622023, 0x4820001, 0x24840100, 0x8f420360, 
-0x441021, 0xaf420360, 0x8f420368, 0xaf430060, 
-0x441021, 0xaf420368, 0x3c020800, 0x2c21024, 
-0x50400011, 0x36940040, 0x1000000f, 0x0, 
-0x32420048, 0x10400007, 0x24150001, 0x8e22001c, 
-0x3c03ffff, 0x43f024, 0x3042ffff, 0x1000fd75, 
-0xae22001c, 0x32420100, 0x10400003, 0x0, 
-0xc002bd8, 0x0, 0x8fbf0050, 0x8fbe004c, 
-0x8fb50048, 0x8fb30044, 0x8fb20040, 0x8fb1003c, 
-0x8fb00038, 0x3e00008, 0x27bd0058, 0x3e00008, 
-0x0, 0x0, 0x0, 0x8f8300e4, 
-0x8f8200e0, 0x2404fff8, 0x441024, 0x621026, 
-0x2102b, 0x21023, 0x3e00008, 0x621024, 
-0x3e00008, 0x0, 0x27bdffe0, 0xafbf001c, 
-0xafb00018, 0x8f8600c4, 0x8f8400e0, 0x8f8500e4, 
-0x2402fff8, 0x821824, 0x10a30009, 0x27623ff8, 
-0x14a20002, 0x24a20008, 0x27623000, 0x408021, 
-0x16030005, 0x30820004, 0x10400004, 0xc02021, 
-0x10000022, 0x1021, 0x8e040000, 0x8f42011c, 
-0x14a20003, 0x0, 0x8f420120, 0xaf420114, 
-0x8ca30000, 0x8f420148, 0x831823, 0x43102b, 
-0x10400003, 0x0, 0x8f420148, 0x621821, 
-0x94a20006, 0x24420050, 0x62102b, 0x1440000f, 
-0xa01021, 0xafa40010, 0xafa30014, 0x8ca60000, 
-0x8ca70004, 0x3c040001, 0xc002b3b, 0x24846894, 
-0x8f42020c, 0x24420001, 0xaf42020c, 0x8f42020c, 
-0x1021, 0xaf9000e8, 0xaf9000e4, 0x8fbf001c, 
-0x8fb00018, 0x3e00008, 0x27bd0020, 0x3e00008, 
-0x0, 0x8f8400e0, 0x8f8800c4, 0x8f8300e8, 
-0x2402fff8, 0x823824, 0xe32023, 0x2c821000, 
-0x50400001, 0x24841000, 0x420c2, 0x801821, 
-0x8f440258, 0x8f45025c, 0x1021, 0xa32821, 
-0xa3302b, 0x822021, 0x862021, 0xaf440258, 
-0xaf45025c, 0x8f8300c8, 0x8f420148, 0x1032023, 
-0x82102b, 0x14400004, 0x801821, 0x8f420148, 
-0x822021, 0x801821, 0x8f440250, 0x8f450254, 
-0x1021, 0xa32821, 0xa3302b, 0x822021, 
-0x862021, 0xaf440250, 0xaf450254, 0xaf8800c8, 
-0xaf8700e4, 0xaf8700e8, 0x3e00008, 0x0, 
-0x27bdff30, 0x240a0001, 0xafbf00c8, 0xafbe00c4, 
-0xafb500c0, 0xafb300bc, 0xafb200b8, 0xafb100b4, 
-0xafb000b0, 0xa3a00097, 0xafa00044, 0xafaa005c, 
-0x934205c4, 0xa7a0008e, 0x1040000a, 0xa7a00086, 
-0x8f4b00c4, 0xafab0064, 0x8f4a00c0, 0xafaa006c, 
-0x8f4b00cc, 0xafab0074, 0x8f4a00c8, 0x10000129, 
-0xafaa007c, 0x8f420114, 0x40f809, 0x0, 
-0x403021, 0x10c0034f, 0x0, 0x8cc20000, 
-0x8cc30004, 0xafa20020, 0xafa30024, 0x8fab0024, 
-0x8faa0020, 0x3162ffff, 0x2442fffc, 0xafa2006c, 
-0x3c020006, 0x2c21024, 0xafab007c, 0x14400015, 
-0xafaa0064, 0x91420000, 0x30420001, 0x10400011, 
-0x2402ffff, 0x8d430000, 0x14620004, 0x3402ffff, 
-0x95430004, 0x1062000b, 0x0, 0xc0024bb, 
-0x8fa40064, 0x304200ff, 0x14400006, 0x0, 
-0x8f420118, 0x40f809, 0x0, 0x1000032d, 
-0x0, 0x8fa20024, 0x3c03ffbf, 0x3463ffff, 
-0x431024, 0x3c03ffff, 0x431824, 0x14600003, 
-0xafa20024, 0x10000040, 0x1821, 0x3c020080, 
-0x621024, 0x10400007, 0x0, 0x8f42038c, 
-0x24420001, 0xaf42038c, 0x8f42038c, 0x10000036, 
-0x24030001, 0x8f420210, 0x24420001, 0xaf420210, 
-0x8f420210, 0x3c020001, 0x621024, 0x10400006, 
-0x3c020002, 0x8f4201c4, 0x24420001, 0xaf4201c4, 
-0x8f4201c4, 0x3c020002, 0x621024, 0x10400006, 
-0x3c020004, 0x8f42037c, 0x24420001, 0xaf42037c, 
-0x8f42037c, 0x3c020004, 0x621024, 0x10400006, 
-0x3c020008, 0x8f420380, 0x24420001, 0xaf420380, 
-0x8f420380, 0x3c020008, 0x621024, 0x10400006, 
-0x3c020010, 0x8f420384, 0x24420001, 0xaf420384, 
-0x8f420384, 0x3c020010, 0x621024, 0x10400006, 
-0x3c020020, 0x8f4201c0, 0x24420001, 0xaf4201c0, 
-0x8f4201c0, 0x3c020020, 0x621024, 0x10400006, 
-0x24030001, 0x8f420388, 0x24420001, 0xaf420388, 
-0x8f420388, 0x24030001, 0x8c020260, 0x8fab006c, 
-0x4b102b, 0x10400014, 0x307000ff, 0x8f4201e8, 
-0x24420001, 0xaf4201e8, 0x8f4201e8, 0x8faa007c, 
-0x8f8200e0, 0x354a0100, 0xafaa007c, 0xafa20010, 
-0x8f8200e4, 0x24100001, 0x3c040001, 0x248468a0, 
-0xafa20014, 0x8fa60020, 0x8fa70024, 0x3c050007, 
-0xc002b3b, 0x34a50800, 0x12000010, 0x3c020080, 
-0x2c21024, 0x1440000e, 0x32c20400, 0x8fab007c, 
-0x3c020080, 0x34420100, 0x1621024, 0x10400005, 
-0x0, 0x8f42020c, 0x24420001, 0xaf42020c, 
-0x8f42020c, 0x100002b0, 0x8fa3006c, 0x32c20400, 
-0x10400015, 0x34028100, 0x8faa0064, 0x9543000c, 
-0x14620012, 0x3c020100, 0x240b0200, 0xa7ab008e, 
-0x9542000e, 0x8d430008, 0x8d440004, 0x8d450000, 
-0x8faa006c, 0x8fab0064, 0x254afffc, 0xafaa006c, 
-0xa7a20086, 0xad63000c, 0xad640008, 0xad650004, 
-0x256b0004, 0xafab0064, 0x3c020100, 0x2c21024, 
-0x10400004, 0x0, 0x8faa006c, 0x254a0004, 
-0xafaa006c, 0x8f4200bc, 0x5040000a, 0xafa00074, 
-0x8fab006c, 0x4b102b, 0x50400006, 0xafa00074, 
-0x8f4200bc, 0x1621023, 0xafa20074, 0x8f4a00bc, 
-0xafaa006c, 0x8f420080, 0x8fab006c, 0x4b102b, 
-0x10400056, 0x32c28000, 0x1040005e, 0x240a0003, 
-0x32c21000, 0x1040005b, 0xafaa005c, 0x10000058, 
-0x240b0004, 0x8f420350, 0x2403ffbf, 0x283a024, 
-0x24420001, 0xaf420350, 0x1000024f, 0x8f420350, 
-0x2c2b025, 0x2402ffbf, 0x282a024, 0x8f830128, 
-0x3c040001, 0x248468d0, 0x26620001, 0xafa20014, 
-0xafa30010, 0x8f860120, 0x8f870124, 0x3c050007, 
-0xc002b3b, 0x34a52250, 0x1000023f, 0x0, 
-0x2c2b025, 0x2402ffbf, 0x282a024, 0x8f830128, 
-0x3c040001, 0x248468d0, 0x24020002, 0xafa20014, 
-0xafa30010, 0x8f860120, 0x8f870124, 0x3c050007, 
-0xc002b3b, 0x34a52450, 0x1000022f, 0x0, 
-0x8ea20000, 0x8ea30004, 0x3c040001, 0x248468e8, 
-0xafb00010, 0xafbe0014, 0x8ea70018, 0x34a52800, 
-0xc002b3b, 0x603021, 0x10000223, 0x0, 
-0xa6b1000a, 0x8f820124, 0x3c040001, 0x248468f0, 
-0xafbe0014, 0xafa20010, 0x8f460044, 0x8f870120, 
-0x3c050007, 0xc002b3b, 0x34a53000, 0x10000216, 
-0x0, 0xa6b1000a, 0xa6b2000e, 0x8f820124, 
-0x3c040001, 0x248468fc, 0xafbe0014, 0xafa20010, 
-0x8f460044, 0x8f870120, 0x3c050007, 0xc002b3b, 
-0x34a53200, 0x10000208, 0x0, 0x8f420084, 
-0x8faa006c, 0x4a102b, 0x14400007, 0x3c020001, 
-0x2c21024, 0x10400004, 0x0, 0x240b0002, 
-0xafab005c, 0x8faa006c, 0x1140021b, 0x27ab0020, 
-0xafab00a4, 0x3c0a001f, 0x354affff, 0xafaa009c, 
-0x8fab005c, 0x240a0001, 0x556a0021, 0x240a0002, 
-0x8f430054, 0x8f420050, 0x1062000b, 0x274b0054, 
-0x8f5e0054, 0x3403ecc0, 0xafab004c, 0x27c20001, 
-0x304201ff, 0xafa20054, 0x1e1140, 0x431021, 
-0x1000006b, 0x2e2a821, 0x8f420044, 0x8faa006c, 
-0x3c040001, 0x248468ac, 0xafaa0014, 0xafa20010, 
-0x8f460054, 0x8f470050, 0x3c050007, 0xc002b3b, 
-0x34a51300, 0x8f430350, 0x2402ffbf, 0x282a024, 
-0x24630001, 0xaf430350, 0x100001d3, 0x8f420350, 
-0x156a001d, 0x0, 0x8f430074, 0x8f420070, 
-0x1062000a, 0x274b0074, 0x8f5e0074, 0xafab004c, 
-0x27c20001, 0x304203ff, 0xafa20054, 0x1e1140, 
-0x24426cc0, 0x1000004a, 0x2e2a821, 0x8f420044, 
-0x8faa006c, 0x3c040001, 0x248468b8, 0x3c050007, 
-0xafaa0014, 0xafa20010, 0x8f460074, 0x8f470070, 
-0x34a51500, 0x240b0001, 0xc002b3b, 0xafab005c, 
-0x1000ffc3, 0x0, 0x8f430064, 0x8f420060, 
-0x1062001a, 0x274a0064, 0x8f5e0064, 0x8fab005c, 
-0xafaa004c, 0x27c20001, 0x304200ff, 0xafa20054, 
-0x24020004, 0x1562000e, 0x1e1140, 0x1e1180, 
-0x24420cc0, 0x2e21021, 0xafa20044, 0x9442002a, 
-0x8faa0044, 0x8fab006c, 0x4b102b, 0x10400024, 
-0x25550020, 0x240a0001, 0x10000021, 0xa3aa0097, 
-0x24424cc0, 0x1000001e, 0x2e2a821, 0x8f420044, 
-0x8fab006c, 0x3c040001, 0x248468c4, 0xafab0014, 
-0xafa20010, 0x8f460064, 0x8f470060, 0x3c050007, 
-0xc002b3b, 0x34a51800, 0x3c020008, 0x2c21024, 
-0x1440ff34, 0x0, 0x8f420370, 0x240a0001, 
-0xafaa005c, 0x24420001, 0xaf420370, 0x1000ff90, 
-0x8f420370, 0x27a30036, 0x131040, 0x621821, 
-0x94620000, 0x441021, 0x10000020, 0xa4620000, 
-0x8fab0064, 0xaeab0018, 0x93a20097, 0x10400072, 
-0x9821, 0x8faa0044, 0x8fa4006c, 0x8fa300a4, 
-0x25420020, 0xafa20028, 0x25420008, 0xafa20030, 
-0x25420010, 0xafaa002c, 0xafa20034, 0x9542002a, 
-0xa7a20038, 0x95420018, 0xa7a2003a, 0x9542001a, 
-0xa7a2003c, 0x9542001c, 0xa7a2003e, 0x94620018, 
-0x24630002, 0x822023, 0x1880ffde, 0x26730001, 
-0x2e620004, 0x1440fff9, 0x0, 0x8f4200fc, 
-0x26650001, 0xa2102a, 0x1440002b, 0x24030001, 
-0x8f83012c, 0x10600023, 0x0, 0x8f820124, 
-0x431023, 0x22143, 0x58800001, 0x24840040, 
-0x8f820128, 0x431023, 0x21943, 0x58600001, 
-0x24630040, 0x64102a, 0x54400001, 0x602021, 
-0xaf4400fc, 0x8f4200fc, 0xa2102a, 0x10400011, 
-0x24030001, 0x10000015, 0x306200ff, 0x8fab0064, 
-0x96070018, 0xafab0010, 0x8e220008, 0x3c040001, 
-0x248468dc, 0x8c430004, 0x8c420000, 0x34a52400, 
-0x2403021, 0xc002b3b, 0xafa30014, 0x1000002b, 
-0x0, 0x8f420334, 0x1821, 0x24420001, 
-0xaf420334, 0x8f420334, 0x306200ff, 0x5040fedc, 
-0x3c020800, 0x12600021, 0x9021, 0x8fb100a4, 
-0x2208021, 0x8e220008, 0x96070018, 0x8fa60064, 
-0x8c440000, 0x8c450004, 0x240a0001, 0xafaa0010, 
-0xafbe0014, 0x8f420008, 0xafa20018, 0x8f42010c, 
-0x40f809, 0x0, 0x1040ffd8, 0x3c050007, 
-0x96020018, 0x8fab0064, 0x8faa009c, 0x1625821, 
-0x14b102b, 0x10400004, 0xafab0064, 0x8f420148, 
-0x1625823, 0xafab0064, 0x26100002, 0x26520001, 
-0x253102b, 0x1440ffe3, 0x26310004, 0x8fb0006c, 
-0x10000036, 0x97b10038, 0x8f4200fc, 0x24050002, 
-0xa2102a, 0x1440001b, 0x24030001, 0x8f83012c, 
-0x10600013, 0x0, 0x8f820124, 0x431023, 
-0x22143, 0x58800001, 0x24840040, 0x8f820128, 
-0x431023, 0x21943, 0x58600001, 0x24630040, 
-0x64102a, 0x54400001, 0x602021, 0xaf4400fc, 
-0x8f4200fc, 0xa2102a, 0x14400006, 0x24030001, 
-0x8f420334, 0x1821, 0x24420001, 0xaf420334, 
-0x8f420334, 0x306200ff, 0x1040fea5, 0x3c020800, 
-0x96b1000a, 0x8fb0006c, 0x3223ffff, 0x70102b, 
-0x54400001, 0x608021, 0x8ea40000, 0x8ea50004, 
-0x240b0001, 0xafab0010, 0xafbe0014, 0x8f420008, 
-0x8fa60064, 0xafa20018, 0x8f42010c, 0x40f809, 
-0x2003821, 0x1040fea2, 0x3c050007, 0x96a3000e, 
-0x97aa008e, 0x11400007, 0x609021, 0x934205c4, 
-0x14400004, 0x0, 0x97ab0086, 0x6a1825, 
-0xa6ab0016, 0x8faa007c, 0x3c02ffff, 0x1421024, 
-0x10400003, 0xa1402, 0x34630400, 0xa6a20014, 
-0x8fab006c, 0x560b0072, 0xa6a3000e, 0x34620004, 
-0xa6a2000e, 0x8faa0074, 0x16a1021, 0xa6a2000a, 
-0x8f430044, 0x8f4401a0, 0x8f4501a4, 0x34028000, 
-0xafa20010, 0x8f420044, 0x2a03021, 0x24070020, 
-0xafa20014, 0x8f42000c, 0x31940, 0x604821, 
-0xafa20018, 0x8f42010c, 0x4021, 0xa92821, 
-0xa9182b, 0x882021, 0x40f809, 0x832021, 
-0x5040fe7f, 0xa6b2000e, 0x8f420368, 0xafa0006c, 
-0xa34005c4, 0x2442ffff, 0xaf420368, 0x8fab005c, 
-0x240a0001, 0x8f420368, 0x156a0006, 0x240a0002, 
-0x8f42035c, 0x2442ffff, 0xaf42035c, 0x1000000c, 
-0x8f42035c, 0x156a0006, 0x0, 0x8f420364, 
-0x2442ffff, 0xaf420364, 0x10000005, 0x8f420364, 
-0x8f420360, 0x2442ffff, 0xaf420360, 0x8f420360, 
-0x8faa0054, 0x8fab004c, 0xad6a0000, 0x8f420044, 
-0x8f440088, 0x8f430078, 0x24420001, 0x441024, 
-0x24630001, 0xaf420044, 0xaf430078, 0x8c020240, 
-0x62182b, 0x14600075, 0x24070008, 0x8f440168, 
-0x8f45016c, 0x8f430044, 0x8f48000c, 0x8f860120, 
-0x24020040, 0xafa20010, 0xafa30014, 0xafa80018, 
-0x8f42010c, 0x40f809, 0x24c6001c, 0x14400011, 
-0x240b0001, 0x3c010001, 0x370821, 0xa02b40f2, 
-0x8f820124, 0xafa20010, 0x8f820128, 0x3c040001, 
-0x2484688c, 0xafa20014, 0x8f460044, 0x8f870120, 
-0x3c050009, 0xc002b3b, 0x34a51300, 0x1000000b, 
-0x0, 0x8f420304, 0x24420001, 0xaf420304, 
-0x8f420304, 0x8f420044, 0xaf42007c, 0x3c010001, 
-0x370821, 0xa02040f2, 0xaf400078, 0x8f420318, 
-0x24420001, 0xaf420318, 0x10000048, 0x8f420318, 
-0xa6b0000a, 0x8f430044, 0x8f4401a0, 0x8f4501a4, 
-0x34028000, 0xafa20010, 0x8f420044, 0x2a03021, 
-0x24070020, 0xafa20014, 0x8f42000c, 0x31940, 
-0x604821, 0xafa20018, 0x8f42010c, 0x4021, 
-0xa92821, 0xa9182b, 0x882021, 0x40f809, 
-0x832021, 0x1040fe1f, 0x240a0001, 0xa34a05c4, 
-0x8fab006c, 0x8faa0064, 0x1705823, 0xafab006c, 
-0x8fab009c, 0x1505021, 0x16a102b, 0x10400004, 
-0xafaa0064, 0x8f420148, 0x1425023, 0xafaa0064, 
-0x8f420368, 0x2442ffff, 0xaf420368, 0x8faa005c, 
-0x240b0001, 0x8f420368, 0x154b0006, 0x240b0002, 
-0x8f42035c, 0x2442ffff, 0xaf42035c, 0x1000000c, 
-0x8f42035c, 0x114b0006, 0x0, 0x8f420360, 
-0x2442ffff, 0xaf420360, 0x10000005, 0x8f420360, 
-0x8f420364, 0x2442ffff, 0xaf420364, 0x8f420364, 
-0x8fab0054, 0x8faa004c, 0xad4b0000, 0x8f420044, 
-0x8f440088, 0x8f430078, 0x24420001, 0x441024, 
-0x24630001, 0xaf420044, 0xaf430078, 0x8faa006c, 
-0x1540fe0b, 0x0, 0x8fab006c, 0x1160001e, 
-0x0, 0x934205c4, 0x10400009, 0x0, 
-0x8faa0064, 0xaf4a00c4, 0xaf4b00c0, 0x8fab007c, 
-0xaf4b00c8, 0x8faa0074, 0x1000000e, 0xaf4a00cc, 
-0x97ab008e, 0x1160000b, 0x34038100, 0x8fa20020, 
-0x8c46000c, 0xa443000c, 0x97aa0086, 0x8c440004, 
-0x8c450008, 0xa44a000e, 0xac440000, 0xac450004, 
-0xac460008, 0x8f42034c, 0x24420001, 0xaf42034c, 
-0x10000010, 0x8f42034c, 0x8fab007c, 0x3164ffff, 
-0x2484fffc, 0x801821, 0x8f440250, 0x8f450254, 
-0x8f460118, 0x1021, 0xa32821, 0xa3382b, 
-0x822021, 0x872021, 0xaf440250, 0xc0f809, 
-0xaf450254, 0x8fbf00c8, 0x8fbe00c4, 0x8fb500c0, 
-0x8fb300bc, 0x8fb200b8, 0x8fb100b4, 0x8fb000b0, 
-0x3e00008, 0x27bd00d0, 0x3e00008, 0x0, 
-0x27bdff38, 0x240b0001, 0xafbf00c0, 0xafbe00bc, 
-0xafb500b8, 0xafb300b4, 0xafb200b0, 0xafb100ac, 
-0xafb000a8, 0xa3a00087, 0xafa00044, 0xafab005c, 
-0x934205c4, 0xa7a00076, 0x10400007, 0xa7a0007e, 
-0x8f4c00c0, 0xafac0064, 0x8f4b00c8, 0x8f5e00c4, 
-0x10000130, 0xafab006c, 0x8f420114, 0x40f809, 
-0x0, 0x403021, 0x10c002a1, 0x0, 
-0x8cc20000, 0x8cc30004, 0xafa20020, 0xafa30024, 
-0x8fac0024, 0x8fbe0020, 0x3182ffff, 0x2442fffc, 
-0xafa20064, 0x3c020006, 0x2c21024, 0x14400015, 
-0xafac006c, 0x93c20000, 0x30420001, 0x10400011, 
-0x2402ffff, 0x8fc30000, 0x14620004, 0x3402ffff, 
-0x97c30004, 0x1062000b, 0x0, 0xc0024bb, 
-0x3c02021, 0x304200ff, 0x14400006, 0x0, 
-0x8f420118, 0x40f809, 0x0, 0x10000280, 
-0x0, 0x8fa20024, 0x3c03ffbf, 0x3463ffff, 
-0x431024, 0x3c03ffff, 0x431824, 0x14600003, 
-0xafa20024, 0x10000040, 0x8021, 0x3c020080, 
-0x621024, 0x10400007, 0x0, 0x8f42038c, 
-0x24420001, 0xaf42038c, 0x8f42038c, 0x10000036, 
-0x24100001, 0x8f420210, 0x24420001, 0xaf420210, 
-0x8f420210, 0x3c020001, 0x621024, 0x10400006, 
-0x3c020002, 0x8f4201c4, 0x24420001, 0xaf4201c4, 
-0x8f4201c4, 0x3c020002, 0x621024, 0x10400006, 
-0x3c020004, 0x8f42037c, 0x24420001, 0xaf42037c, 
-0x8f42037c, 0x3c020004, 0x621024, 0x10400006, 
-0x3c020008, 0x8f420380, 0x24420001, 0xaf420380, 
-0x8f420380, 0x3c020008, 0x621024, 0x10400006, 
-0x3c020010, 0x8f420384, 0x24420001, 0xaf420384, 
-0x8f420384, 0x3c020010, 0x621024, 0x10400006, 
-0x3c020020, 0x8f4201c0, 0x24420001, 0xaf4201c0, 
-0x8f4201c0, 0x3c020020, 0x621024, 0x10400006, 
-0x24100001, 0x8f420388, 0x24420001, 0xaf420388, 
-0x8f420388, 0x24100001, 0x8c020260, 0x8fab0064, 
-0x4b102b, 0x10400015, 0x320200ff, 0x8f4201e8, 
-0x24420001, 0xaf4201e8, 0x8f4201e8, 0x8fac006c, 
-0x8f8200e0, 0x358c0100, 0xafac006c, 0xafa20010, 
-0x8f8200e4, 0x24100001, 0x3c040001, 0x248468a0, 
-0xafa20014, 0x8fa60020, 0x8fa70024, 0x3c050007, 
-0xc002b3b, 0x34a53600, 0x320200ff, 0x10400010, 
-0x3c020080, 0x2c21024, 0x1440000e, 0x32c20400, 
-0x8fab006c, 0x3c020080, 0x34420100, 0x1621024, 
-0x10400005, 0x0, 0x8f42020c, 0x24420001, 
-0xaf42020c, 0x8f42020c, 0x10000202, 0x8fa30064, 
-0x32c20400, 0x10400012, 0x34028100, 0x97c3000c, 
-0x1462000f, 0x0, 0x240c0200, 0xa7ac0076, 
-0x97c2000e, 0x8fc30008, 0x8fc40004, 0x8fab0064, 
-0x8fc50000, 0x256bfffc, 0xafab0064, 0xa7a2007e, 
-0xafc3000c, 0xafc40008, 0xafc50004, 0x27de0004, 
-0x8fa70064, 0x320200ff, 0x14400034, 0x3c020100, 
-0x97c4000c, 0x2c8305dd, 0x38828870, 0x2c420001, 
-0x621825, 0x10600015, 0x2821, 0x32c20800, 
-0x10400015, 0x24020800, 0x97c30014, 0x14620012, 
-0x3402aaaa, 0x97c3000e, 0x14620007, 0x2021, 
-0x97c30010, 0x24020300, 0x14620004, 0x801021, 
-0x97c20012, 0x2c440001, 0x801021, 0x54400006, 
-0x24050016, 0x10000004, 0x0, 0x24020800, 
-0x50820001, 0x2405000e, 0x10a00013, 0x3c52021, 
-0x24830009, 0x3c02001f, 0x3442ffff, 0x43102b, 
-0x10400003, 0x0, 0x8f420148, 0x621823, 
-0x90620000, 0x38430006, 0x2c630001, 0x38420011, 
-0x2c420001, 0x621825, 0x10600004, 0x3c020100, 
-0x94820002, 0x453821, 0x3c020100, 0x2c21024, 
-0x5040000e, 0xafa70064, 0x8fac0064, 0x10ec0008, 
-0x3c050007, 0x3c040001, 0x24846908, 0x8fa60064, 
-0x34a54000, 0xafa00010, 0xc002b3b, 0xafa00014, 
-0x8fab0064, 0x256b0004, 0xafab0064, 0x8f420080, 
-0x8fac0064, 0x4c102b, 0x1040002c, 0x32c28000, 
-0x10400034, 0x240b0003, 0x32c21000, 0x10400031, 
-0xafab005c, 0x1000002e, 0x240c0004, 0x8f420350, 
-0x2403ffbf, 0x283a024, 0x24420001, 0xaf420350, 
-0x10000173, 0x8f420350, 0x3c020800, 0x2c2b025, 
-0x2402ffbf, 0x282a024, 0x8f830128, 0x3c040001, 
-0x248468d0, 0x26620001, 0xafa20014, 0xafa30010, 
-0x8f860120, 0x8f870124, 0x3c050007, 0xc002b3b, 
-0x34a55300, 0x10000162, 0x0, 0x8ea20000, 
-0x8ea30004, 0x3c040001, 0x248468e8, 0xafb00010, 
-0xafb10014, 0x8ea70018, 0x34a55900, 0xc002b3b, 
-0x603021, 0x10000156, 0x0, 0x8f420084, 
-0x8fab0064, 0x4b102b, 0x14400007, 0x3c020001, 
-0x2c21024, 0x10400004, 0x0, 0x240c0002, 
-0xafac005c, 0x8fab0064, 0x11600166, 0x27ac0020, 
-0xafac008c, 0x8fab005c, 0x240c0001, 0x556c0021, 
-0x240c0002, 0x8f430054, 0x8f420050, 0x1062000b, 
-0x274b0054, 0x8f510054, 0x3403ecc0, 0xafab004c, 
-0x26220001, 0x304201ff, 0xafa20054, 0x111140, 
-0x431021, 0x1000006b, 0x2e2a821, 0x8f420044, 
-0x8fac0064, 0x3c040001, 0x248468ac, 0xafac0014, 
-0xafa20010, 0x8f460054, 0x8f470050, 0x3c050007, 
-0xc002b3b, 0x34a54300, 0x8f430350, 0x2402ffbf, 
-0x282a024, 0x24630001, 0xaf430350, 0x10000124, 
-0x8f420350, 0x156c001d, 0x0, 0x8f430074, 
-0x8f420070, 0x1062000a, 0x274b0074, 0x8f510074, 
-0xafab004c, 0x26220001, 0x304203ff, 0xafa20054, 
-0x111140, 0x24426cc0, 0x1000004a, 0x2e2a821, 
-0x8f420044, 0x8fac0064, 0x3c040001, 0x248468b8, 
-0x3c050007, 0xafac0014, 0xafa20010, 0x8f460074, 
-0x8f470070, 0x34a54500, 0x240b0001, 0xc002b3b, 
-0xafab005c, 0x1000ffc3, 0x0, 0x8f430064, 
-0x8f420060, 0x1062001a, 0x274c0064, 0x8f510064, 
-0x8fab005c, 0xafac004c, 0x26220001, 0x304200ff, 
-0xafa20054, 0x24020004, 0x1562000e, 0x111140, 
-0x111180, 0x24420cc0, 0x2e21021, 0xafa20044, 
-0x9442002a, 0x8fac0044, 0x8fab0064, 0x4b102b, 
-0x10400024, 0x25950020, 0x240c0001, 0x10000021, 
-0xa3ac0087, 0x24424cc0, 0x1000001e, 0x2e2a821, 
-0x8f420044, 0x8fab0064, 0x3c040001, 0x248468c4, 
-0xafab0014, 0xafa20010, 0x8f460064, 0x8f470060, 
-0x3c050007, 0xc002b3b, 0x34a54800, 0x3c020008, 
-0x2c21024, 0x1440ff61, 0x0, 0x8f420370, 
-0x240c0001, 0xafac005c, 0x24420001, 0xaf420370, 
-0x1000ff90, 0x8f420370, 0x27a30036, 0x131040, 
-0x621821, 0x94620000, 0x441021, 0x1000001f, 
-0xa4620000, 0xaebe0018, 0x93a20087, 0x10400084, 
-0x9821, 0x8fab0044, 0x8fa40064, 0x8fa3008c, 
-0x25620020, 0xafa20028, 0x25620008, 0xafa20030, 
-0x25620010, 0xafab002c, 0xafa20034, 0x9562002a, 
-0xa7a20038, 0x95620018, 0xa7a2003a, 0x9562001a, 
-0xa7a2003c, 0x9562001c, 0xa7a2003e, 0x94620018, 
-0x24630002, 0x822023, 0x1880ffdf, 0x26730001, 
-0x2e620004, 0x1440fff9, 0x0, 0x8f4200fc, 
-0x262102a, 0x14400030, 0x24030001, 0x8f83012c, 
-0x10600028, 0x0, 0x8f820124, 0x431023, 
-0x22143, 0x58800001, 0x24840040, 0x8f820128, 
-0x431023, 0x21943, 0x58600001, 0x24630040, 
-0x64102a, 0x54400001, 0x602021, 0xaf4400fc, 
-0x8f4200fc, 0x262102a, 0x10400016, 0x24030001, 
-0x1000001a, 0x306200ff, 0x8fac008c, 0x101040, 
-0x4c1021, 0x94470018, 0x101080, 0x4c1021, 
-0xafbe0010, 0x8c420008, 0x3c040001, 0x248468dc, 
-0x3c050007, 0x8c430004, 0x8c420000, 0x34a55500, 
-0x2003021, 0xc002b3b, 0xafa30014, 0x10000039, 
-0x0, 0x8f420334, 0x1821, 0x24420001, 
-0xaf420334, 0x8f420334, 0x306200ff, 0x1040ff06, 
-0x8021, 0x8f430008, 0x2402fbff, 0x1260002d, 
-0x625024, 0x3c0b4000, 0x22b4025, 0x8fb1008c, 
-0x2669ffff, 0x2209021, 0x8e420008, 0x96270018, 
-0x8c440000, 0x8c450004, 0x56090004, 0x240b0001, 
-0x240c0002, 0x10000002, 0xafac0010, 0xafab0010, 
-0x16000004, 0xafa80014, 0x8f420008, 0x10000002, 
-0xafa20018, 0xafaa0018, 0x8f42010c, 0x3c03021, 
-0xafa80098, 0xafa9009c, 0x40f809, 0xafaa00a0, 
-0x8fa80098, 0x8fa9009c, 0x8faa00a0, 0x1040ffc2, 
-0x3c02001f, 0x96230018, 0x3442ffff, 0x3c3f021, 
-0x5e102b, 0x10400003, 0x26310002, 0x8f420148, 
-0x3c2f023, 0x26100001, 0x213102b, 0x1440ffda, 
-0x26520004, 0x8fb00064, 0x1000001a, 0x0, 
-0x96a3000a, 0x8fb00064, 0x70102b, 0x54400001, 
-0x608021, 0x8ea40000, 0x8ea50004, 0x8fab005c, 
-0x240c0002, 0xafac0010, 0x934305c4, 0xb1700, 
-0x10600003, 0x2223025, 0x3c020800, 0xc23025, 
-0xafa60014, 0x8f420008, 0xafa20018, 0x8f42010c, 
-0x3c03021, 0x40f809, 0x2003821, 0x1040fecb, 
-0x3c050007, 0x97ac0076, 0x11800007, 0x96a3000e, 
-0x934205c4, 0x14400004, 0x0, 0x97ab007e, 
-0x6c1825, 0xa6ab0016, 0x8fac006c, 0x3c02ffff, 
-0x1821024, 0x10400003, 0xc1402, 0x34630400, 
-0xa6a20014, 0xa6b0000a, 0x8fab0064, 0x560b0006, 
-0x3d0f021, 0x34620004, 0xafa00064, 0xa6a2000e, 
-0x1000000d, 0xa34005c4, 0x8fac0064, 0x3c02001f, 
-0x3442ffff, 0x5e102b, 0x1906023, 0xafac0064, 
-0xa6a3000e, 0x240b0001, 0x10400003, 0xa34b05c4, 
-0x8f420148, 0x3c2f023, 0x8fab0054, 0x8fac004c, 
-0xad8b0000, 0x8fac0064, 0x1580feba, 0x0, 
-0x8fab0064, 0x1160001b, 0x0, 0x934205c4, 
-0x10400006, 0x0, 0xaf5e00c4, 0xaf4b00c0, 
-0x8fac006c, 0x1000000e, 0xaf4c00c8, 0x97ab0076, 
-0x1160000b, 0x34038100, 0x8fa20020, 0x8c46000c, 
-0xa443000c, 0x97ac007e, 0x8c440004, 0x8c450008, 
-0xa44c000e, 0xac440000, 0xac450004, 0xac460008, 
-0x8f42034c, 0x24420001, 0xaf42034c, 0x10000010, 
-0x8f42034c, 0x8fab006c, 0x3164ffff, 0x2484fffc, 
-0x801821, 0x8f440250, 0x8f450254, 0x8f460118, 
-0x1021, 0xa32821, 0xa3382b, 0x822021, 
-0x872021, 0xaf440250, 0xc0f809, 0xaf450254, 
-0x8fbf00c0, 0x8fbe00bc, 0x8fb500b8, 0x8fb300b4, 
-0x8fb200b0, 0x8fb100ac, 0x8fb000a8, 0x3e00008, 
-0x27bd00c8, 0x3e00008, 0x0, 0x27bdffd8, 
-0xafbf0024, 0xafb00020, 0x8f43004c, 0x8f420048, 
-0x10620034, 0x0, 0x8f430048, 0x8f42004c, 
-0x622023, 0x4820001, 0x24840200, 0x8f430054, 
-0x8f42004c, 0x43102b, 0x14400004, 0x24020200, 
-0x8f43004c, 0x10000005, 0x431023, 0x8f420054, 
-0x8f43004c, 0x431023, 0x2442ffff, 0x405021, 
-0x8a102a, 0x54400001, 0x805021, 0x8f49004c, 
-0x8f48004c, 0x8f440188, 0x8f45018c, 0x8f46004c, 
-0x24071000, 0xafa70010, 0x84140, 0x1001821, 
-0x12a4821, 0x313001ff, 0xafb00014, 0x8f470014, 
-0x1021, 0x63140, 0xafa70018, 0xa32821, 
-0xa3382b, 0x822021, 0x872021, 0x3402ecc0, 
-0xc23021, 0x8f420108, 0x2e63021, 0x40f809, 
-0xa3940, 0x54400001, 0xaf50004c, 0x8f43004c, 
-0x8f420048, 0x14620018, 0x0, 0x8f420000, 
-0x10400007, 0x0, 0xaf80004c, 0x8f82004c, 
-0x1040fffd, 0x0, 0x10000005, 0x0, 
-0xaf800048, 0x8f820048, 0x1040fffd, 0x0, 
-0x8f820060, 0x2403fdff, 0x431024, 0xaf820060, 
-0x8f420000, 0x10400003, 0x0, 0x10000002, 
-0xaf80004c, 0xaf800048, 0x8fbf0024, 0x8fb00020, 
-0x3e00008, 0x27bd0028, 0x3e00008, 0x0, 
-0x27bdffd8, 0xafbf0024, 0xafb00020, 0x8f43005c, 
-0x8f420058, 0x10620049, 0x0, 0x8f430058, 
-0x8f42005c, 0x622023, 0x4820001, 0x24840100, 
-0x8f430064, 0x8f42005c, 0x43102b, 0x14400004, 
-0x24020100, 0x8f43005c, 0x10000005, 0x431023, 
-0x8f420064, 0x8f43005c, 0x431023, 0x2442ffff, 
-0x403821, 0x87102a, 0x54400001, 0x803821, 
-0x8f42005c, 0x471021, 0x305000ff, 0x32c21000, 
-0x10400015, 0x24082000, 0x8f49005c, 0x8f440190, 
-0x8f450194, 0x8f46005c, 0x73980, 0xafa80010, 
-0xafb00014, 0x8f480014, 0x94980, 0x1201821, 
-0x1021, 0xa32821, 0xa3482b, 0x822021, 
-0x892021, 0x63180, 0xafa80018, 0x8f420108, 
-0x10000014, 0x24c60cc0, 0x8f49005c, 0x8f440190, 
-0x8f450194, 0x8f46005c, 0x73940, 0xafa80010, 
-0xafb00014, 0x8f480014, 0x94940, 0x1201821, 
-0x1021, 0xa32821, 0xa3482b, 0x822021, 
-0x892021, 0x63140, 0xafa80018, 0x8f420108, 
-0x24c64cc0, 0x40f809, 0x2e63021, 0x54400001, 
-0xaf50005c, 0x8f43005c, 0x8f420058, 0x14620018, 
-0x0, 0x8f420000, 0x10400007, 0x0, 
-0xaf80004c, 0x8f82004c, 0x1040fffd, 0x0, 
-0x10000005, 0x0, 0xaf800048, 0x8f820048, 
-0x1040fffd, 0x0, 0x8f820060, 0x2403feff, 
-0x431024, 0xaf820060, 0x8f420000, 0x10400003, 
-0x0, 0x10000002, 0xaf80004c, 0xaf800048, 
-0x8fbf0024, 0x8fb00020, 0x3e00008, 0x27bd0028, 
-0x3e00008, 0x0, 0x27bdffd8, 0xafbf0024, 
-0xafb00020, 0x8f43006c, 0x8f420068, 0x10620033, 
-0x0, 0x8f430068, 0x8f42006c, 0x622023, 
-0x4820001, 0x24840400, 0x8f430074, 0x8f42006c, 
-0x43102b, 0x14400004, 0x24020400, 0x8f43006c, 
-0x10000005, 0x431023, 0x8f420074, 0x8f43006c, 
-0x431023, 0x2442ffff, 0x405021, 0x8a102a, 
-0x54400001, 0x805021, 0x8f49006c, 0x8f48006c, 
-0x8f440198, 0x8f45019c, 0x8f46006c, 0x24074000, 
-0xafa70010, 0x84140, 0x1001821, 0x12a4821, 
-0x313003ff, 0xafb00014, 0x8f470014, 0x1021, 
-0x63140, 0x24c66cc0, 0xafa70018, 0xa32821, 
-0xa3382b, 0x822021, 0x872021, 0x8f420108, 
-0x2e63021, 0x40f809, 0xa3940, 0x54400001, 
-0xaf50006c, 0x8f43006c, 0x8f420068, 0x14620018, 
-0x0, 0x8f420000, 0x10400007, 0x0, 
-0xaf80004c, 0x8f82004c, 0x1040fffd, 0x0, 
-0x10000005, 0x0, 0xaf800048, 0x8f820048, 
-0x1040fffd, 0x0, 0x8f820060, 0x2403f7ff, 
-0x431024, 0xaf820060, 0x8f420000, 0x10400003, 
-0x0, 0x10000002, 0xaf80004c, 0xaf800048, 
-0x8fbf0024, 0x8fb00020, 0x3e00008, 0x27bd0028, 
-0x3e00008, 0x0, 0x8f4200fc, 0x3c030001, 
-0x8f4400f8, 0x346330c8, 0x24420001, 0xaf4200fc, 
-0x8f850128, 0x2e31021, 0x54820004, 0x24820008, 
-0x3c020001, 0x34422ec8, 0x2e21021, 0x401821, 
-0xaf4300f8, 0xac600000, 0x8f4200f4, 0x14620004, 
-0x3c020001, 0x24a20020, 0x1000000f, 0xaf820128, 
-0x8f4300f8, 0x344230c8, 0x2e21021, 0x54620004, 
-0x24620008, 0x3c020001, 0x34422ec8, 0x2e21021, 
-0x401821, 0x8c620004, 0x21140, 0xa21021, 
-0xaf820128, 0xac600000, 0x8ca30018, 0x30620070, 
-0x1040002d, 0x30620020, 0x10400004, 0x3c020010, 
-0x2c21024, 0x1040000d, 0x0, 0x30620040, 
-0x10400004, 0x3c020020, 0x2c21024, 0x10400007, 
-0x0, 0x30620010, 0x1040001f, 0x3c020040, 
-0x2c21024, 0x1440001c, 0x0, 0x8f820040, 
-0x30420001, 0x14400008, 0x2021, 0x8c030104, 
-0x24020001, 0x50620005, 0x24040001, 0x8c020264, 
-0x10400003, 0x801021, 0x24040001, 0x801021, 
-0x10400006, 0x0, 0x8f42030c, 0x24420001, 
-0xaf42030c, 0x10000008, 0x8f42030c, 0x8f820044, 
-0x34420004, 0xaf820044, 0x8f420308, 0x24420001, 
-0xaf420308, 0x8f420308, 0x3e00008, 0x0, 
-0x3e00008, 0x0, 0x27bdff98, 0xafbf0060, 
-0xafbe005c, 0xafb50058, 0xafb30054, 0xafb20050, 
-0xafb1004c, 0xafb00048, 0x8f4200fc, 0x24420001, 
-0xaf4200fc, 0x8f880128, 0x25020020, 0xaf820128, 
-0x8d030018, 0x30620070, 0x1040002e, 0x30620020, 
-0x10400004, 0x3c020010, 0x2c21024, 0x1040000d, 
-0x0, 0x30620040, 0x10400004, 0x3c020020, 
-0x2c21024, 0x10400007, 0x0, 0x30620010, 
-0x104001a9, 0x3c020040, 0x2c21024, 0x144001a6, 
-0x0, 0x8f820040, 0x30420001, 0x14400008, 
-0x2021, 0x8c030104, 0x24020001, 0x50620005, 
-0x24040001, 0x8c020264, 0x10400003, 0x801021, 
-0x24040001, 0x801021, 0x10400006, 0x0, 
-0x8f42030c, 0x24420001, 0xaf42030c, 0x10000192, 
-0x8f42030c, 0x8f820044, 0x34420004, 0xaf820044, 
-0x8f420308, 0x24420001, 0xaf420308, 0x1000018a, 
-0x8f420308, 0x30620002, 0x1040014b, 0x3c020800, 
-0x8d1e001c, 0x1e5702, 0xafaa0034, 0x950a0016, 
-0x3c22024, 0xafaa0024, 0x8faa0034, 0x24020001, 
-0x15420006, 0x33deffff, 0x1e1140, 0x3403ecc0, 
-0x431021, 0x10000010, 0x2e2a821, 0x24020002, 
-0x15420005, 0x24020003, 0x1e1140, 0x24426cc0, 
-0x10000009, 0x2e2a821, 0x15420005, 0x1e1180, 
-0x1e1140, 0x24424cc0, 0x10000003, 0x2e2a821, 
-0x571021, 0x24550ce0, 0x96a2000e, 0x304afffc, 
-0x30420400, 0x10400003, 0xafaa002c, 0x100000e1, 
-0x8821, 0x10800004, 0x8821, 0x97b10026, 
-0x100000dd, 0xa6b10012, 0x8eb30018, 0x966a000c, 
-0xa7aa003e, 0x97a5003e, 0x2ca305dd, 0x38a28870, 
-0x2c420001, 0x621825, 0x10600015, 0x2021, 
-0x32c20800, 0x10400015, 0x24020800, 0x96630014, 
-0x14620012, 0x3402aaaa, 0x9663000e, 0x14620007, 
-0x2821, 0x96630010, 0x24020300, 0x14620004, 
-0xa01021, 0x96620012, 0x2c450001, 0xa01021, 
-0x54400006, 0x24040016, 0x10000004, 0x0, 
-0x24020800, 0x50a20001, 0x2404000e, 0x108000b9, 
-0x2649021, 0x92420000, 0x3042000f, 0x28080, 
-0x32c20100, 0x10400020, 0x2501821, 0x3c020020, 
-0x43102b, 0x1440000e, 0x2402021, 0x2821, 
-0x94820000, 0x24840002, 0xa22821, 0x83102b, 
-0x1440fffb, 0x30a2ffff, 0x51c02, 0x622821, 
-0x51c02, 0x30a2ffff, 0x10000009, 0x622821, 
-0x8f470148, 0x8f420110, 0x102842, 0x3c060020, 
-0x40f809, 0xafa80040, 0x3045ffff, 0x8fa80040, 
-0x50a00001, 0x3405ffff, 0x8faa002c, 0x354a0002, 
-0x10000002, 0xafaa002c, 0x2821, 0x32c20080, 
-0x10400090, 0xa6a50010, 0x26430009, 0x3c02001f, 
-0x3442ffff, 0x43102b, 0x10400003, 0x0, 
-0x8f420148, 0x621823, 0x90660000, 0x30c200ff, 
-0x38430006, 0x2c630001, 0x38420011, 0x2c420001, 
-0x621825, 0x1060007f, 0x24020800, 0x8821, 
-0x97a3003e, 0x1462000f, 0x2602021, 0x96710000, 
-0x96620002, 0x96630004, 0x96640006, 0x2228821, 
-0x2238821, 0x2248821, 0x96620008, 0x9663000a, 
-0x9664000c, 0x2228821, 0x2238821, 0x10000007, 
-0x2248821, 0x94820000, 0x24840002, 0x2228821, 
-0x92102b, 0x1440fffb, 0x0, 0x111c02, 
-0x3222ffff, 0x628821, 0x111c02, 0x3222ffff, 
-0x628821, 0x32c20200, 0x10400003, 0x26440006, 
-0x1000003e, 0x8021, 0x3c05001f, 0x34a5ffff, 
-0xa4102b, 0x10400003, 0x0, 0x8f420148, 
-0x822023, 0x94820000, 0x30421fff, 0x10400004, 
-0x2644000c, 0x96420002, 0x10000030, 0x508023, 
-0x96420002, 0x26430014, 0x508023, 0x3c020020, 
-0x43102b, 0x1440000a, 0xd08021, 0x9642000c, 
-0x2028021, 0x9642000e, 0x96430010, 0x96440012, 
-0x2028021, 0x2038021, 0x10000020, 0x2048021, 
-0xa4102b, 0x10400003, 0x0, 0x8f420148, 
-0x822023, 0x94820000, 0x24840002, 0x2028021, 
-0xa4102b, 0x10400003, 0x0, 0x8f420148, 
-0x822023, 0x94820000, 0x24840002, 0x2028021, 
-0xa4102b, 0x10400003, 0x0, 0x8f420148, 
-0x822023, 0x94820000, 0x24840002, 0x2028021, 
-0xa4102b, 0x10400003, 0x0, 0x8f420148, 
-0x822023, 0x94820000, 0x2028021, 0x3c020100, 
-0x2c21024, 0x1040000e, 0x0, 0x8faa002c, 
-0x31420004, 0x1040000a, 0x0, 0x9504000e, 
-0x2642021, 0xc003eec, 0x2484fffc, 0x3042ffff, 
-0x2228821, 0x111c02, 0x3222ffff, 0x628821, 
-0x8faa0024, 0x1518823, 0x111402, 0x2228821, 
-0x2308821, 0x111402, 0x2228821, 0x3231ffff, 
-0x52200001, 0x3411ffff, 0x8faa002c, 0x354a0001, 
-0xafaa002c, 0xa6b10012, 0x97aa002e, 0xa6aa000e, 
-0x8faa002c, 0x31420004, 0x10400002, 0x24091000, 
-0x34098000, 0x8f480044, 0x8f4401a0, 0x8f4501a4, 
-0xafa90010, 0x8f490044, 0x84140, 0x1001821, 
-0xafa90014, 0x8f48000c, 0x2a03021, 0x24070020, 
-0xafa80018, 0x8f48010c, 0x1021, 0xa32821, 
-0xa3482b, 0x822021, 0x100f809, 0x892021, 
-0x1440000b, 0x0, 0x8f820128, 0x3c040001, 
-0x24846914, 0xafbe0014, 0xafa20010, 0x8f860124, 
-0x8f870120, 0x3c050007, 0xc002b3b, 0x34a59920, 
-0x8f420368, 0x2442ffff, 0xaf420368, 0x8f420044, 
-0x8f430088, 0x24420001, 0x431024, 0xaf420044, 
-0x8faa0034, 0x8f440368, 0x24020001, 0x15420006, 
-0x24020002, 0x8f42035c, 0x2442ffff, 0xaf42035c, 
-0x10000049, 0x8f42035c, 0x15420006, 0x0, 
-0x8f420364, 0x2442ffff, 0xaf420364, 0x10000042, 
-0x8f420364, 0x8f420360, 0x2442ffff, 0xaf420360, 
-0x1000003d, 0x8f420360, 0x30621000, 0x10400005, 
-0x30628000, 0x8f420078, 0x24420001, 0x10000036, 
-0xaf420078, 0x10400034, 0x0, 0x8f420078, 
-0x24420001, 0xaf420078, 0x8c030240, 0x43102b, 
-0x1440002d, 0x24070008, 0x8f440168, 0x8f45016c, 
-0x8f430044, 0x8f48000c, 0x8f860120, 0x24020040, 
-0xafa20010, 0xafa30014, 0xafa80018, 0x8f42010c, 
-0x40f809, 0x24c6001c, 0x14400011, 0x24020001, 
-0x3c010001, 0x370821, 0xa02240f2, 0x8f820124, 
-0xafa20010, 0x8f820128, 0x3c040001, 0x2484688c, 
-0xafa20014, 0x8f460044, 0x8f870120, 0x3c050009, 
-0xc002b3b, 0x34a51300, 0x1000000b, 0x0, 
-0x8f420304, 0x24420001, 0xaf420304, 0x8f420304, 
-0x8f420044, 0xaf42007c, 0x3c010001, 0x370821, 
-0xa02040f2, 0xaf400078, 0x8f420318, 0x24420001, 
-0xaf420318, 0x8f420318, 0x8fbf0060, 0x8fbe005c, 
-0x8fb50058, 0x8fb30054, 0x8fb20050, 0x8fb1004c, 
-0x8fb00048, 0x3e00008, 0x27bd0068, 0x3e00008, 
-0x0, 0x0, 0x0, 0x8f42013c, 
-0xaf8200c0, 0x8f42013c, 0xaf8200c4, 0x8f42013c, 
-0xaf8200c8, 0x8f420138, 0xaf8200d0, 0x8f420138, 
-0xaf8200d4, 0x8f420138, 0x3e00008, 0xaf8200d8, 
-0x27bdffe0, 0x27840208, 0x24050200, 0xafbf0018, 
-0xc002bbf, 0x24060008, 0x8c020204, 0xc004012, 
-0xaf820210, 0x3c020001, 0x8c426d94, 0x30420002, 
-0x1040000e, 0x2021, 0x8c060248, 0x24020002, 
-0x3c010001, 0xac226d98, 0xc005104, 0x24050002, 
-0x2021, 0x8c060248, 0x24020001, 0x3c010001, 
-0xac226d98, 0x10000011, 0x24050001, 0x8c060248, 
-0x24020004, 0x3c010001, 0xac226d98, 0xc005104, 
-0x24050004, 0x3c020001, 0x8c426d94, 0x30420001, 
-0x10400008, 0x24020001, 0x3c010001, 0xac226d98, 
-0x2021, 0x24050001, 0x3c06601b, 0xc005104, 
-0x0, 0x3c040001, 0x248469d0, 0x8f420150, 
-0x8f430154, 0x3c050008, 0x8f460158, 0x21640, 
-0x31940, 0x34630403, 0x431025, 0x633c0, 
-0x461025, 0xaf82021c, 0xafa00010, 0xafa00014, 
-0x8f86021c, 0x34a50200, 0xc002b3b, 0x3821, 
-0x3c010001, 0xac206d90, 0x3c010001, 0xac206da8, 
-0x8fbf0018, 0x3e00008, 0x27bd0020, 0x27bdffe0, 
-0x3c050008, 0x34a50300, 0xafbf0018, 0xafa00010, 
-0xafa00014, 0x8f860200, 0x3c040001, 0x248469dc, 
-0xc002b3b, 0x3821, 0x8f420410, 0x24420001, 
-0xaf420410, 0x8f420410, 0x8fbf0018, 0x3e00008, 
-0x27bd0020, 0x27bdffd8, 0xafbf0020, 0xafb1001c, 
-0xafb00018, 0x8f4203a4, 0x24420001, 0xaf4203a4, 
-0x8f4203a4, 0x8f900220, 0x8f8200e0, 0xafa20010, 
-0x8f8200e4, 0xafa20014, 0x8f8600c4, 0x8f8700c8, 
-0x3c040001, 0x248469e8, 0xc002b3b, 0x2002821, 
-0x3c044000, 0x2041024, 0x504000b4, 0x3c040100, 
-0x8f4203bc, 0x24420001, 0xaf4203bc, 0x8f4203bc, 
-0x8f8700c4, 0x8f8300c8, 0x8f420148, 0x671823, 
-0x43102b, 0x10400003, 0x0, 0x8f420148, 
-0x621821, 0x10600005, 0x0, 0x8f42014c, 
-0x43102b, 0x1040000b, 0x0, 0x8f8200e0, 
-0x8f430124, 0xaf42011c, 0xaf430114, 0x8f820220, 
-0x3c0308ff, 0x3463fffb, 0x431024, 0x100000ce, 
-0x441025, 0x8f820220, 0x3c0308ff, 0x3463ffff, 
-0x431024, 0x34420004, 0xaf820220, 0x8f8200e0, 
-0x8f430124, 0xaf42011c, 0xaf430114, 0x8f8600c8, 
-0x8f840120, 0x8f830124, 0x10000005, 0x2821, 
-0x14620002, 0x24620020, 0x27624800, 0x401821, 
-0x1064000c, 0x30a200ff, 0x8c620018, 0x30420003, 
-0x1040fff7, 0x27624fe0, 0x8f4203d0, 0x24050001, 
-0x24420001, 0xaf4203d0, 0x8f4203d0, 0x8c660008, 
-0x30a200ff, 0x14400058, 0x0, 0x934205c4, 
-0x14400055, 0x0, 0x8f8700c4, 0x8f8800e0, 
-0x8f8400e4, 0x2402fff8, 0x1024024, 0x1041023, 
-0x218c3, 0x4620001, 0x24630200, 0x10600005, 
-0x24020001, 0x10620009, 0x0, 0x1000001f, 
-0x0, 0x8f4203c0, 0xe03021, 0x24420001, 
-0xaf4203c0, 0x10000040, 0x8f4203c0, 0x8f4203c4, 
-0x24420001, 0xaf4203c4, 0x8c860000, 0x8f420148, 
-0x8f4303c4, 0xe61823, 0x43102b, 0x10400004, 
-0x2c62233f, 0x8f420148, 0x621821, 0x2c62233f, 
-0x14400031, 0x0, 0x8f42020c, 0x24420001, 
-0xaf42020c, 0x8f42020c, 0xe03021, 0x24820008, 
-0xaf8200e4, 0x10000028, 0xaf8200e8, 0x8f4203c8, 
-0x24420001, 0xaf4203c8, 0x8f4203c8, 0x8c850000, 
-0x8f420148, 0xa71823, 0x43102b, 0x10400003, 
-0x0, 0x8f420148, 0x621821, 0x8f42014c, 
-0x43102b, 0x5440000a, 0xa03021, 0x8f42020c, 
-0x24420001, 0xaf42020c, 0x8f42020c, 0x24820008, 
-0xaf8200e4, 0x8f8400e4, 0x1488ffec, 0xaf8400e8, 
-0x1488000d, 0x27623000, 0x14820002, 0x2482fff8, 
-0x27623ff8, 0x94430006, 0x3c02001f, 0x3442ffff, 
-0xc33021, 0x46102b, 0x10400003, 0x0, 
-0x8f420148, 0xc23023, 0xaf8600c8, 0x8f8300c4, 
-0x8f420148, 0xc31823, 0x43102b, 0x10400003, 
-0x0, 0x8f420148, 0x621821, 0x10600005, 
-0x0, 0x8f42014c, 0x43102b, 0x50400008, 
-0x3c02fdff, 0x8f820220, 0x3c0308ff, 0x3463fffb, 
-0x431024, 0x3c034000, 0x1000003f, 0x431025, 
-0x8f4303cc, 0x3442ffff, 0x282a024, 0x24630001, 
-0xaf4303cc, 0x10000039, 0x8f4203cc, 0x2041024, 
-0x1040000e, 0x3c110200, 0x8f4203a8, 0x24420001, 
-0xaf4203a8, 0x8f4203a8, 0x8f820220, 0x3c0308ff, 
-0x3463ffff, 0x431024, 0x441025, 0xc003daf, 
-0xaf820220, 0x10000029, 0x0, 0x2111024, 
-0x50400008, 0x3c110400, 0x8f4203ac, 0x24420001, 
-0xaf4203ac, 0xc003daf, 0x8f4203ac, 0x10000019, 
-0x0, 0x2111024, 0x1040001c, 0x0, 
-0x8f830224, 0x24021402, 0x14620009, 0x3c050008, 
-0x3c040001, 0x248469f4, 0xafa00010, 0xafa00014, 
-0x8f860224, 0x34a50500, 0xc002b3b, 0x3821, 
-0x8f4203b0, 0x24420001, 0xaf4203b0, 0x8f4203b0, 
-0x8f820220, 0x2002021, 0x34420002, 0xc004e9c, 
-0xaf820220, 0x8f820220, 0x3c0308ff, 0x3463ffff, 
-0x431024, 0x511025, 0xaf820220, 0x8fbf0020, 
-0x8fb1001c, 0x8fb00018, 0x3e00008, 0x27bd0028, 
-0x3e00008, 0x0, 0x3c020001, 0x8c426da8, 
-0x27bdffb0, 0xafbf0048, 0xafbe0044, 0xafb50040, 
-0xafb3003c, 0xafb20038, 0xafb10034, 0x1040000f, 
-0xafb00030, 0x3c040001, 0x24846a00, 0x3c050008, 
-0xafa00010, 0xafa00014, 0x8f860220, 0x34a50600, 
-0x24020001, 0x3c010001, 0xac206da8, 0x3c010001, 
-0xac226d9c, 0xc002b3b, 0x3821, 0x3c037fff, 
-0x8c020268, 0x3463ffff, 0x3c04fdff, 0x431024, 
-0xac020268, 0x8f420004, 0x3484ffff, 0x30420002, 
-0x10400092, 0x284a024, 0x3c040600, 0x34842000, 
-0x8f420004, 0x2821, 0x2403fffd, 0x431024, 
-0xaf420004, 0xafa40020, 0x8f5e0018, 0x27aa0020, 
-0x240200ff, 0x13c20002, 0xafaa002c, 0x27c50001, 
-0x8c020228, 0xa09021, 0x1642000e, 0x1e38c0, 
-0x8f42033c, 0x24420001, 0xaf42033c, 0x8f42033c, 
-0x8c020228, 0x3c040001, 0x24846998, 0x3c050009, 
-0xafa00014, 0xafa20010, 0x8fa60020, 0x1000006d, 
-0x34a50500, 0xf71021, 0x8fa30020, 0x8fa40024, 
-0xac4304c0, 0xac4404c4, 0x8f830054, 0x8f820054, 
-0x247003e8, 0x2021023, 0x2c4203e9, 0x1040001b, 
-0x9821, 0xe08821, 0x263504c0, 0x8f440178, 
-0x8f45017c, 0x2201821, 0x240a0004, 0xafaa0010, 
-0xafb20014, 0x8f48000c, 0x1021, 0x2f53021, 
-0xafa80018, 0x8f48010c, 0x24070008, 0xa32821, 
-0xa3482b, 0x822021, 0x100f809, 0x892021, 
-0x54400006, 0x24130001, 0x8f820054, 0x2021023, 
-0x2c4203e9, 0x1440ffe9, 0x0, 0x326200ff, 
-0x54400017, 0xaf520018, 0x8f420378, 0x24420001, 
-0xaf420378, 0x8f420378, 0x8f820120, 0x8faa002c, 
-0xafa20010, 0x8f820124, 0x3c040001, 0x248469a4, 
-0x3c050009, 0xafa20014, 0x8d460000, 0x10000035, 
-0x34a50600, 0x8f420308, 0x24130001, 0x24420001, 
-0xaf420308, 0x8f420308, 0x1000001e, 0x326200ff, 
-0x8f830054, 0x8f820054, 0x247003e8, 0x2021023, 
-0x2c4203e9, 0x10400016, 0x9821, 0x3c150020, 
-0x24110010, 0x8f42000c, 0x8f440160, 0x8f450164, 
-0x8f860120, 0xafb10010, 0xafb20014, 0x551025, 
-0xafa20018, 0x8f42010c, 0x24070008, 0x40f809, 
-0x24c6001c, 0x1440ffe3, 0x0, 0x8f820054, 
-0x2021023, 0x2c4203e9, 0x1440ffee, 0x0, 
-0x326200ff, 0x14400011, 0x0, 0x8f420378, 
-0x24420001, 0xaf420378, 0x8f420378, 0x8f820120, 
-0x8faa002c, 0xafa20010, 0x8f820124, 0x3c040001, 
-0x248469ac, 0x3c050009, 0xafa20014, 0x8d460000, 
-0x34a50700, 0xc002b3b, 0x3c03821, 0x8f4202ec, 
-0x24420001, 0xaf4202ec, 0x8f4202ec, 0x8fbf0048, 
-0x8fbe0044, 0x8fb50040, 0x8fb3003c, 0x8fb20038, 
-0x8fb10034, 0x8fb00030, 0x3e00008, 0x27bd0050, 
-0x3c020001, 0x8c426da8, 0x27bdffe0, 0x1440000d, 
-0xafbf0018, 0x3c040001, 0x24846a0c, 0x3c050008, 
-0xafa00010, 0xafa00014, 0x8f860220, 0x34a50700, 
-0x24020001, 0x3c010001, 0xac226da8, 0xc002b3b, 
-0x3821, 0x3c020004, 0x2c21024, 0x10400007, 
-0x0, 0x8f820220, 0x3c0308ff, 0x3463ffff, 
-0x431024, 0x34420008, 0xaf820220, 0x3c050001, 
-0x8ca56d98, 0x24020001, 0x14a20007, 0x2021, 
-0xc00529b, 0x24050001, 0xac02026c, 0x8c03026c, 
-0x10000006, 0x3c020007, 0xc00529b, 0x2021, 
-0xac020268, 0x8c030268, 0x3c020007, 0x621824, 
-0x3c020002, 0x5062000d, 0x3c0205f5, 0x43102b, 
-0x14400006, 0x3c020004, 0x3c020001, 0x10620009, 
-0x3c020098, 0x1000000b, 0x0, 0x14620009, 
-0x3c023b9a, 0x10000004, 0x3442ca00, 0x10000002, 
-0x3442e100, 0x34429680, 0xaf4201fc, 0x8f4201fc, 
-0xaee20064, 0x8fbf0018, 0x3e00008, 0x27bd0020, 
-0x0, 0x0, 0x0, 0x86102b, 
-0x50400001, 0x872023, 0xc41023, 0x24843, 
-0x125102b, 0x1040001b, 0x91040, 0x824021, 
-0x88102b, 0x10400007, 0x1821, 0x94820000, 
-0x24840002, 0x621821, 0x88102b, 0x1440fffb, 
-0x0, 0x602021, 0xc73023, 0xa91023, 
-0x21040, 0xc22821, 0xc5102b, 0x10400007, 
-0x1821, 0x94c20000, 0x24c60002, 0x621821, 
-0xc5102b, 0x1440fffb, 0x0, 0x1000000d, 
-0x832021, 0x51040, 0x822821, 0x85102b, 
-0x10400007, 0x1821, 0x94820000, 0x24840002, 
-0x621821, 0x85102b, 0x1440fffb, 0x0, 
-0x602021, 0x41c02, 0x3082ffff, 0x622021, 
-0x41c02, 0x3082ffff, 0x622021, 0x3e00008, 
-0x3082ffff, 0x3e00008, 0x0, 0x802821, 
-0x30a20001, 0x1040002b, 0x3c03001f, 0x3463ffff, 
-0x24a20004, 0x62102b, 0x54400007, 0x65102b, 
-0x90a20001, 0x90a40003, 0x90a30000, 0x90a50002, 
-0x1000002a, 0x441021, 0x10400003, 0x0, 
-0x8f420148, 0xa22823, 0x90a40000, 0x24a50001, 
-0x65102b, 0x10400003, 0x0, 0x8f420148, 
-0xa22823, 0x90a20000, 0x24a50001, 0x21200, 
-0x822021, 0x65102b, 0x10400003, 0x0, 
-0x8f420148, 0xa22823, 0x90a20000, 0x24a50001, 
-0x822021, 0x65102b, 0x10400003, 0x0, 
-0x8f420148, 0xa22823, 0x90a20000, 0x1000002d, 
-0x21200, 0x3463ffff, 0x24a20004, 0x62102b, 
-0x5440000a, 0x65102b, 0x90a20000, 0x90a40002, 
-0x90a30001, 0x90a50003, 0x441021, 0x21200, 
-0x651821, 0x10000020, 0x432021, 0x10400003, 
-0x0, 0x8f420148, 0xa22823, 0x90a20000, 
-0x24a50001, 0x22200, 0x65102b, 0x10400003, 
-0x0, 0x8f420148, 0xa22823, 0x90a20000, 
-0x24a50001, 0x822021, 0x65102b, 0x10400003, 
-0x0, 0x8f420148, 0xa22823, 0x90a20000, 
-0x24a50001, 0x21200, 0x822021, 0x65102b, 
-0x10400003, 0x0, 0x8f420148, 0xa22823, 
-0x90a20000, 0x822021, 0x41c02, 0x3082ffff, 
-0x622021, 0x41c02, 0x3082ffff, 0x622021, 
-0x3e00008, 0x3082ffff, 0x0, 0x8f820220, 
-0x34420002, 0xaf820220, 0x3c020002, 0x8c428ff8, 
-0x30424000, 0x10400054, 0x24040001, 0x8f820200, 
-0x24067fff, 0x8f830200, 0x30450002, 0x2402fffd, 
-0x621824, 0xaf830200, 0xaf840204, 0x8f830054, 
-0x8f820054, 0x10000002, 0x24630001, 0x8f820054, 
-0x621023, 0x2c420002, 0x1440fffc, 0x0, 
-0x8f820224, 0x1444004d, 0x42040, 0xc4102b, 
-0x1040fff1, 0x0, 0x8f820200, 0x451025, 
-0xaf820200, 0x8f820220, 0x34428000, 0xaf820220, 
-0x8f830054, 0x8f820054, 0x10000002, 0x24630001, 
-0x8f820054, 0x621023, 0x2c420002, 0x1440fffc, 
-0x0, 0x8f820220, 0x3c030004, 0x431024, 
-0x1440000f, 0x0, 0x8f820220, 0x3c03ffff, 
-0x34637fff, 0x431024, 0xaf820220, 0x8f830054, 
-0x8f820054, 0x10000002, 0x24630001, 0x8f820054, 
-0x621023, 0x2c420002, 0x1440fffc, 0x0, 
-0x8f820220, 0x3c030004, 0x431024, 0x1440000d, 
-0x0, 0x8f820220, 0x34428000, 0xaf820220, 
-0x8f830054, 0x8f820054, 0x10000002, 0x24630001, 
-0x8f820054, 0x621023, 0x2c420002, 0x1440fffc, 
-0x0, 0x8f820220, 0x3c030004, 0x431024, 
-0x1040001b, 0x1021, 0x8f830220, 0x24020001, 
-0x10000015, 0x3c04f700, 0x8f820220, 0x3c04f700, 
-0x441025, 0xaf820220, 0x8f820220, 0x2403fffd, 
-0x431024, 0xaf820220, 0x8f820220, 0x3c030300, 
-0x431024, 0x14400003, 0x0, 0x10000008, 
-0x1021, 0x8f820220, 0x34420002, 0xaf820220, 
-0x8f830220, 0x24020001, 0x641825, 0xaf830220, 
-0x3e00008, 0x0, 0x2021, 0x3c050100, 
-0x24020001, 0xaf80021c, 0xaf820200, 0xaf820220, 
-0x27625000, 0xaf8200c0, 0x27625000, 0xaf8200c4, 
-0x27625000, 0xaf8200c8, 0x27625000, 0xaf8200d0, 
-0x27625000, 0xaf8200d4, 0x27625000, 0xaf8200d8, 
-0x27623000, 0xaf8200e0, 0x27623000, 0xaf8200e4, 
-0x27623000, 0xaf8200e8, 0x27622800, 0xaf8200f0, 
-0x27622800, 0xaf8200f4, 0x27622800, 0xaf8200f8, 
-0x418c0, 0x24840001, 0x3631021, 0xac453004, 
-0x3631021, 0xac403000, 0x28820200, 0x1440fff9, 
-0x418c0, 0x2021, 0x418c0, 0x24840001, 
-0x3631021, 0xac402804, 0x3631021, 0xac402800, 
-0x28820100, 0x1440fff9, 0x418c0, 0xaf80023c, 
-0x24030080, 0x24040100, 0xac600000, 0x24630004, 
-0x64102b, 0x5440fffd, 0xac600000, 0x8f830040, 
-0x3c02f000, 0x621824, 0x3c025000, 0x1062000c, 
-0x43102b, 0x14400006, 0x3c026000, 0x3c024000, 
-0x10620008, 0x24020800, 0x10000008, 0x0, 
-0x10620004, 0x24020800, 0x10000004, 0x0, 
-0x24020700, 0x3c010001, 0xac226dac, 0x3e00008, 
-0x0, 0x3c020001, 0x8c426dbc, 0x27bdffd0, 
-0xafbf002c, 0xafb20028, 0xafb10024, 0xafb00020, 
-0x3c010001, 0x10400005, 0xac206d94, 0xc004d9e, 
-0x0, 0x3c010001, 0xac206dbc, 0x8f830054, 
-0x8f820054, 0x10000002, 0x24630064, 0x8f820054, 
-0x621023, 0x2c420065, 0x1440fffc, 0x0, 
-0xc004db9, 0x0, 0x24040001, 0x2821, 
-0x27a60018, 0x34028000, 0xc0045be, 0xa7a20018, 
-0x8f830054, 0x8f820054, 0x10000002, 0x24630064, 
-0x8f820054, 0x621023, 0x2c420065, 0x1440fffc, 
-0x24040001, 0x24050001, 0xc00457c, 0x27a60018, 
-0x8f830054, 0x8f820054, 0x10000002, 0x24630064, 
-0x8f820054, 0x621023, 0x2c420065, 0x1440fffc, 
-0x24040001, 0x24050001, 0xc00457c, 0x27a60018, 
-0x8f830054, 0x8f820054, 0x10000002, 0x24630064, 
-0x8f820054, 0x621023, 0x2c420065, 0x1440fffc, 
-0x24040001, 0x3c060001, 0x24c66f24, 0xc00457c, 
-0x24050002, 0x8f830054, 0x8f820054, 0x10000002, 
-0x24630064, 0x8f820054, 0x621023, 0x2c420065, 
-0x1440fffc, 0x24040001, 0x24050003, 0x3c100001, 
-0x26106f26, 0xc00457c, 0x2003021, 0x97a60018, 
-0x3c070001, 0x94e76f24, 0x3c040001, 0x24846ae0, 
-0xafa00014, 0x96020000, 0x3c05000d, 0x34a50100, 
-0xc002b3b, 0xafa20010, 0x97a20018, 0x1040004d, 
-0x24036040, 0x96020000, 0x3042fff0, 0x1443000c, 
-0x24020020, 0x3c030001, 0x94636f24, 0x1462000b, 
-0x24027830, 0x24020003, 0x3c010001, 0xac226d94, 
-0x24020005, 0x3c010001, 0x1000003f, 0xac226f34, 
-0x3c030001, 0x94636f24, 0x24027830, 0x1462000c, 
-0x24030010, 0x3c020001, 0x94426f26, 0x3042fff0, 
-0x14430007, 0x24020003, 0x3c010001, 0xac226d94, 
-0x24020006, 0x3c010001, 0x1000002f, 0xac226f34, 
-0x3c020001, 0x8c426d94, 0x3c030001, 0x94636f24, 
-0x34420001, 0x3c010001, 0xac226d94, 0x24020015, 
-0x1462000b, 0x0, 0x3c020001, 0x94426f26, 
-0x3042fff0, 0x3843f420, 0x2c630001, 0x3842f430, 
-0x2c420001, 0x621825, 0x1460001b, 0x24020003, 
-0x3c030001, 0x94636f24, 0x24027810, 0x14620016, 
-0x24020002, 0x3c020001, 0x94426f26, 0x3042fff0, 
-0x14400011, 0x24020002, 0x1000000f, 0x24020004, 
-0x3c020001, 0x8c426d94, 0x34420008, 0x3c010001, 
-0xac226d94, 0x1000005e, 0x24020004, 0x3c020001, 
-0x8c426d94, 0x34420004, 0x3c010001, 0x100000af, 
-0xac226d94, 0x24020001, 0x3c010001, 0xac226f40, 
-0x3c020001, 0x8c426d94, 0x30420002, 0x144000b2, 
-0x3c09fff0, 0x24020e00, 0xaf820238, 0x8f840054, 
-0x8f820054, 0x24030008, 0x3c010001, 0xac236d98, 
-0x10000002, 0x248401f4, 0x8f820054, 0x821023, 
-0x2c4201f5, 0x1440fffc, 0x3c0200c8, 0x344201fb, 
-0xaf820238, 0x8f830054, 0x8f820054, 0x10000002, 
-0x246301f4, 0x8f820054, 0x621023, 0x2c4201f5, 
-0x1440fffc, 0x8021, 0x24120001, 0x24110009, 
-0xc004482, 0x0, 0x3c010001, 0xac326db4, 
-0xc004547, 0x0, 0x3c020001, 0x8c426db4, 
-0x1451fffb, 0x3c0200c8, 0x344201f6, 0xaf820238, 
-0x8f830054, 0x8f820054, 0x10000002, 0x2463000a, 
-0x8f820054, 0x621023, 0x2c42000b, 0x1440fffc, 
-0x0, 0x8f820220, 0x24040001, 0x34420002, 
-0xaf820220, 0x8f830200, 0x24057fff, 0x2402fffd, 
-0x621824, 0xaf830200, 0xaf840204, 0x8f830054, 
-0x8f820054, 0x10000002, 0x24630001, 0x8f820054, 
-0x621023, 0x2c420002, 0x1440fffc, 0x0, 
-0x8f820224, 0x14440005, 0x34028000, 0x42040, 
-0xa4102b, 0x1040fff0, 0x34028000, 0x1082ffa0, 
-0x26100001, 0x2e020014, 0x1440ffcd, 0x24020004, 
-0x3c010001, 0xac226d98, 0x8021, 0x24120009, 
-0x3c11ffff, 0x36313f7f, 0xc004482, 0x0, 
-0x24020001, 0x3c010001, 0xac226db4, 0xc004547, 
-0x0, 0x3c020001, 0x8c426db4, 0x1452fffb, 
-0x0, 0x8f820044, 0x511024, 0x34425080, 
-0xaf820044, 0x8f830054, 0x8f820054, 0x10000002, 
-0x2463000a, 0x8f820054, 0x621023, 0x2c42000b, 
-0x1440fffc, 0x0, 0x8f820044, 0x511024, 
-0x3442f080, 0xaf820044, 0x8f830054, 0x8f820054, 
-0x10000002, 0x2463000a, 0x8f820054, 0x621023, 
-0x2c42000b, 0x1440fffc, 0x0, 0x8f820220, 
-0x3c03f700, 0x431025, 0xaf820220, 0x8f830054, 
-0x8f820054, 0x10000002, 0x24630064, 0x8f820054, 
-0x621023, 0x2c420065, 0x1440fffc, 0x0, 
-0x8f820220, 0x24040001, 0x34420002, 0xaf820220, 
-0x8f830200, 0x24057fff, 0x2402fffd, 0x621824, 
-0xaf830200, 0xaf840204, 0x8f830054, 0x8f820054, 
-0x10000002, 0x24630001, 0x8f820054, 0x621023, 
-0x2c420002, 0x1440fffc, 0x0, 0x8f820224, 
-0x14440005, 0x34028000, 0x42040, 0xa4102b, 
-0x1040fff0, 0x34028000, 0x1082ff50, 0x26100001, 
-0x2e020064, 0x1440ffb0, 0x0, 0x3c020001, 
-0x8c426d94, 0x30420004, 0x14400007, 0x3c09fff0, 
-0x8f820044, 0x3c03ffff, 0x34633f7f, 0x431024, 
-0xaf820044, 0x3c09fff0, 0x3529bdc0, 0x3c060001, 
-0x8cc66d94, 0x3c040001, 0x24846ae0, 0x24020001, 
-0x3c010001, 0xac226d9c, 0x8f820054, 0x3c070001, 
-0x8ce76f40, 0x3c030001, 0x94636f24, 0x3c080001, 
-0x95086f26, 0x3c05000d, 0x34a50100, 0x3c010001, 
-0xac206d98, 0x491021, 0x3c010001, 0xac226f30, 
-0xafa30010, 0xc002b3b, 0xafa80014, 0x8fbf002c, 
-0x8fb20028, 0x8fb10024, 0x8fb00020, 0x3e00008, 
-0x27bd0030, 0x27bdffe8, 0x3c050001, 0x8ca56d98, 
-0x24060004, 0x24020001, 0x14a20014, 0xafbf0010, 
-0x3c020002, 0x8c428ffc, 0x30428000, 0x10400005, 
-0x3c04000f, 0x3c030001, 0x8c636f40, 0x10000005, 
-0x34844240, 0x3c040004, 0x3c030001, 0x8c636f40, 
-0x348493e0, 0x24020005, 0x14620016, 0x0, 
-0x3c04003d, 0x10000013, 0x34840900, 0x3c020002, 
-0x8c428ff8, 0x30428000, 0x10400005, 0x3c04001e, 
-0x3c030001, 0x8c636f40, 0x10000005, 0x34848480, 
-0x3c04000f, 0x3c030001, 0x8c636f40, 0x34844240, 
-0x24020005, 0x14620003, 0x0, 0x3c04007a, 
-0x34841200, 0x3c020001, 0x8c426f30, 0x8f830054, 
-0x441021, 0x431023, 0x44102b, 0x1440004c, 
-0x0, 0x3c020001, 0x8c426da0, 0x14400048, 
-0x0, 0x3c010001, 0x10c00025, 0xac206db0, 
-0x3c090001, 0x8d296d94, 0x24070001, 0x3c044000, 
-0x3c080002, 0x25088ffc, 0x250afffc, 0x52842, 
-0x14a00002, 0x24c6ffff, 0x24050008, 0xa91024, 
-0x10400010, 0x0, 0x14a70008, 0x0, 
-0x8d020000, 0x441024, 0x1040000a, 0x0, 
-0x3c010001, 0x10000007, 0xac256db0, 0x8d420000, 
-0x441024, 0x10400003, 0x0, 0x3c010001, 
-0xac276db0, 0x3c020001, 0x8c426db0, 0x6182b, 
-0x2c420001, 0x431024, 0x5440ffe5, 0x52842, 
-0x8f820054, 0x3c030001, 0x8c636db0, 0x3c010001, 
-0xac226f30, 0x1060003b, 0x24020005, 0x3c030001, 
-0x8c636f40, 0x3c010001, 0xac256d98, 0x14620012, 
-0x24020001, 0x3c020002, 0x8c428ff8, 0x3c032000, 
-0x34635000, 0x431024, 0x14400006, 0x24020001, 
-0x3c010001, 0xac206f1c, 0x3c010001, 0xac226d98, 
-0x24020001, 0x3c010001, 0xac226e24, 0x3c010001, 
-0xac226da4, 0x24020001, 0x3c010001, 0xac226d9c, 
-0x3c020001, 0x8c426db0, 0x1040001e, 0x0, 
-0x3c020001, 0x8c426d9c, 0x10400008, 0x24020001, 
-0x3c010001, 0xac206d9c, 0xaee204b8, 0x3c010001, 
-0xac206e1c, 0x3c010001, 0xac226dd4, 0x8ee304b8, 
-0x24020008, 0x10620005, 0x24020001, 0xc004239, 
-0x0, 0x1000000b, 0x0, 0x3c030001, 
-0x8c636d98, 0x10620007, 0x2402000e, 0x3c030002, 
-0x8c638f90, 0x10620003, 0x0, 0xc004e9c, 
-0x8f840220, 0x8fbf0010, 0x3e00008, 0x27bd0018, 
-0x27bdffe0, 0x3c03fdff, 0x3c040001, 0x8c846d98, 
-0x3c020001, 0x8c426dc0, 0x3463ffff, 0x283a024, 
-0x14820006, 0xafbf0018, 0x8ee304b8, 0x3c020001, 
-0x8c426dc4, 0x10620006, 0x0, 0x8ee204b8, 
-0x3c010001, 0xac246dc0, 0x3c010001, 0xac226dc4, 
-0x3c030001, 0x8c636d98, 0x24020002, 0x1062019c, 
-0x2c620003, 0x10400005, 0x24020001, 0x1062000a, 
-0x0, 0x10000226, 0x0, 0x24020004, 
-0x106200b6, 0x24020008, 0x1062010a, 0x24020001, 
-0x1000021f, 0x0, 0x8ee204b8, 0x2443ffff, 
-0x2c620008, 0x1040021c, 0x31080, 0x3c010001, 
-0x220821, 0x8c226af8, 0x400008, 0x0, 
-0x3c030001, 0x8c636f40, 0x24020005, 0x14620010, 
-0x0, 0x3c020001, 0x8c426da4, 0x10400008, 
-0x24020003, 0xc004482, 0x0, 0x24020002, 
-0xaee204b8, 0x3c010001, 0x10000002, 0xac206da4, 
-0xaee204b8, 0x3c010001, 0x10000203, 0xac206d30, 
-0xc004482, 0x0, 0x3c020001, 0x8c426da4, 
-0x3c010001, 0xac206d30, 0x1440017a, 0x24020002, 
-0x1000019d, 0x24020007, 0x3c030001, 0x8c636f40, 
-0x24020005, 0x14620003, 0x24020001, 0x3c010001, 
-0xac226dd0, 0xc0045ff, 0x0, 0x3c030001, 
-0x8c636dd0, 0x10000174, 0x24020011, 0x3c050001, 
-0x8ca56d98, 0x3c060002, 0x8cc68ffc, 0xc005104, 
-0x2021, 0x24020005, 0x3c010001, 0xac206da4, 
-0x100001e1, 0xaee204b8, 0x3c040001, 0x24846aec, 
-0x3c05000f, 0x34a50100, 0x3021, 0x3821, 
-0xafa00010, 0xc002b3b, 0xafa00014, 0x100001d6, 
-0x0, 0x8f820220, 0x3c030004, 0x431024, 
-0x14400175, 0x24020007, 0x8f830054, 0x3c020001, 
-0x8c426f28, 0x2463d8f0, 0x431023, 0x2c422710, 
-0x14400003, 0x24020001, 0x3c010001, 0xac226d9c, 
-0x3c020002, 0x8c428ffc, 0x30425000, 0x104001c2, 
-0x0, 0x8f820220, 0x30428000, 0x1040017d, 
-0x0, 0x10000175, 0x0, 0x3c050001, 
-0x8ca56d98, 0xc00529b, 0x2021, 0xc00551b, 
-0x2021, 0x3c030002, 0x8c638ff4, 0x46101b0, 
-0x24020001, 0x3c020008, 0x621024, 0x10400006, 
-0x0, 0x8f820214, 0x3c03ffff, 0x431024, 
-0x10000005, 0x3442251f, 0x8f820214, 0x3c03ffff, 
-0x431024, 0x3442241f, 0xaf820214, 0x8f820220, 
-0x3c030200, 0x34420002, 0xaf820220, 0x24020008, 
-0xaee204b8, 0x8f820220, 0x283a025, 0x3c030004, 
-0x431024, 0x14400016, 0x0, 0x3c020002, 
-0x8c428ffc, 0x30425000, 0x1040000d, 0x0, 
-0x8f820220, 0x30428000, 0x10400006, 0x0, 
-0x8f820220, 0x3c03ffff, 0x34637fff, 0x10000003, 
-0x431024, 0x8f820220, 0x34428000, 0xaf820220, 
-0x8f820220, 0x3c03f700, 0x431025, 0xaf820220, 
-0x3c030001, 0x8c636f40, 0x24020005, 0x1462000a, 
-0x0, 0x3c020001, 0x94426f26, 0x24429fbc, 
-0x2c420004, 0x10400004, 0x24040018, 0x24050002, 
-0xc004ddb, 0x24060020, 0xc003e6d, 0x0, 
-0x3c010001, 0x10000170, 0xac206e20, 0x8ee204b8, 
-0x2443ffff, 0x2c620008, 0x1040016b, 0x31080, 
-0x3c010001, 0x220821, 0x8c226b18, 0x400008, 
-0x0, 0xc004547, 0x0, 0x3c030001, 
-0x8c636db4, 0x100000e8, 0x24020009, 0x3c020002, 
-0x8c428ff8, 0x30424000, 0x10400004, 0x0, 
-0x8f820044, 0x10000006, 0x3442f080, 0x8f820044, 
-0x3c03ffff, 0x34633f7f, 0x431024, 0x3442a080, 
-0xaf820044, 0x8f830054, 0x100000ea, 0x24020004, 
-0x8f830054, 0x3c020001, 0x8c426f28, 0x2463d8f0, 
-0x431023, 0x2c422710, 0x14400147, 0x24020005, 
-0x100000d8, 0x0, 0x8f820220, 0x3c03f700, 
-0x431025, 0xaf820220, 0xaf800204, 0x3c010002, 
-0x100000d6, 0xac208fe0, 0x8f830054, 0x3c020001, 
-0x8c426f28, 0x2463fff6, 0x431023, 0x2c42000a, 
-0x14400135, 0x24020007, 0x100000d7, 0x0, 
-0xc003f50, 0x0, 0x1040012d, 0x24020001, 
-0x8f820214, 0x3c03ffff, 0x3c040001, 0x8c846f1c, 
-0x431024, 0x3442251f, 0xaf820214, 0x24020008, 
-0x10800005, 0xaee204b8, 0x3c020001, 0x8c426e44, 
-0x10400064, 0x24020001, 0x8f820220, 0x3c030008, 
-0x431024, 0x1040006a, 0x3c020200, 0x10000078, 
-0x0, 0x8ee204b8, 0x2443ffff, 0x2c620007, 
-0x10400115, 0x31080, 0x3c010001, 0x220821, 
-0x8c226b38, 0x400008, 0x0, 0xc003daf, 
-0x0, 0x3c010001, 0xac206d9c, 0xaf800204, 
-0x3c010002, 0xc004482, 0xac208fe0, 0x24020001, 
-0x3c010001, 0xac226db4, 0x24020002, 0x10000102, 
-0xaee204b8, 0xc004547, 0x0, 0x3c030001, 
-0x8c636db4, 0x10000084, 0x24020009, 0x3c020002, 
-0x8c428ff8, 0x30424000, 0x10400003, 0x3c0200c8, 
-0x10000002, 0x344201f6, 0x344201fe, 0xaf820238, 
-0x8f830054, 0x1000008b, 0x24020004, 0x8f830054, 
-0x3c020001, 0x8c426f28, 0x2463d8f0, 0x431023, 
-0x2c422710, 0x144000e8, 0x24020005, 0x10000079, 
-0x0, 0x8f820220, 0x3c03f700, 0x431025, 
-0xaf820220, 0xaf800204, 0x3c010002, 0x10000077, 
-0xac208fe0, 0x8f830054, 0x3c020001, 0x8c426f28, 
-0x2463fff6, 0x431023, 0x2c42000a, 0x144000d6, 
-0x24020007, 0x10000078, 0x0, 0xc003f50, 
-0x0, 0x104000ce, 0x24020001, 0x8f820214, 
-0x3c03ffff, 0x3c040001, 0x8c846f1c, 0x431024, 
-0x3442251f, 0xaf820214, 0x24020008, 0x1080000f, 
-0xaee204b8, 0x3c020001, 0x8c426e44, 0x1440000b, 
-0x0, 0x8f820220, 0x34420002, 0xaf820220, 
-0x24020001, 0x3c010002, 0xac228f90, 0xc004e9c, 
-0x8f840220, 0x10000016, 0x0, 0x8f820220, 
-0x3c030008, 0x431024, 0x14400011, 0x3c020200, 
-0x282a025, 0x2402000e, 0x3c010002, 0xac228f90, 
-0xc00551b, 0x2021, 0x8f820220, 0x34420002, 
-0xc003e6d, 0xaf820220, 0x3c050001, 0x8ca56d98, 
-0xc00529b, 0x2021, 0x100000a3, 0x0, 
-0x3c020001, 0x8c426e44, 0x1040009f, 0x0, 
-0x3c020001, 0x8c426e40, 0x2442ffff, 0x3c010001, 
-0xac226e40, 0x14400098, 0x24020002, 0x3c010001, 
-0xac206e44, 0x3c010001, 0x10000093, 0xac226e40, 
-0x8ee204b8, 0x2443ffff, 0x2c620007, 0x1040008e, 
-0x31080, 0x3c010001, 0x220821, 0x8c226b58, 
-0x400008, 0x0, 0x3c020001, 0x8c426da4, 
-0x10400018, 0x24020005, 0xc004482, 0x0, 
-0x24020002, 0xaee204b8, 0x3c010001, 0x1000007e, 
-0xac206da4, 0xc004963, 0x0, 0x3c030001, 
-0x8c636dd4, 0x24020006, 0x14620077, 0x24020003, 
-0x10000075, 0xaee204b8, 0x3c050001, 0x8ca56d98, 
-0x3c060002, 0x8cc68ff8, 0xc005104, 0x2021, 
-0x24020005, 0x1000006c, 0xaee204b8, 0x8f820220, 
-0x3c03f700, 0x431025, 0xaf820220, 0x8f830054, 
-0x24020006, 0xaee204b8, 0x3c010001, 0x10000062, 
-0xac236f28, 0x8f820220, 0x3c030004, 0x431024, 
-0x10400003, 0x24020007, 0x1000005b, 0xaee204b8, 
-0x8f830054, 0x3c020001, 0x8c426f28, 0x2463d8f0, 
-0x431023, 0x2c422710, 0x14400003, 0x24020001, 
-0x3c010001, 0xac226d9c, 0x3c020002, 0x8c428ff8, 
-0x30425000, 0x1040004c, 0x0, 0x8f820220, 
-0x30428000, 0x10400007, 0x0, 0x8f820220, 
-0x3c03ffff, 0x34637fff, 0x431024, 0x10000042, 
-0xaf820220, 0x8f820220, 0x34428000, 0x1000003e, 
-0xaf820220, 0x3c050001, 0x8ca56d98, 0xc00529b, 
-0x2021, 0xc00551b, 0x2021, 0x3c020002, 
-0x8c428ff0, 0x4410032, 0x24020001, 0x8f820214, 
-0x3c03ffff, 0x431024, 0x3442251f, 0xaf820214, 
-0x24020008, 0xaee204b8, 0x8f820220, 0x34420002, 
-0xaf820220, 0x8f820220, 0x3c030004, 0x431024, 
-0x14400016, 0x0, 0x3c020002, 0x8c428ff8, 
-0x30425000, 0x1040000d, 0x0, 0x8f820220, 
-0x30428000, 0x10400006, 0x0, 0x8f820220, 
-0x3c03ffff, 0x34637fff, 0x10000003, 0x431024, 
-0x8f820220, 0x34428000, 0xaf820220, 0x8f820220, 
-0x3c03f700, 0x431025, 0xaf820220, 0x3c020001, 
-0x94426f26, 0x24429fbc, 0x2c420004, 0x10400004, 
-0x24040018, 0x24050002, 0xc004ddb, 0x24060020, 
-0xc003e6d, 0x0, 0x10000003, 0x0, 
-0x3c010001, 0xac226d9c, 0x8fbf0018, 0x3e00008, 
-0x27bd0020, 0x8f820200, 0x8f820220, 0x8f820220, 
-0x34420004, 0xaf820220, 0x8f820200, 0x3c050001, 
-0x8ca56d98, 0x34420004, 0xaf820200, 0x24020002, 
-0x10a2004b, 0x2ca20003, 0x10400005, 0x24020001, 
-0x10a2000a, 0x0, 0x100000b1, 0x0, 
-0x24020004, 0x10a20072, 0x24020008, 0x10a20085, 
-0x3c02f0ff, 0x100000aa, 0x0, 0x8f830050, 
-0x3c02f0ff, 0x3442ffff, 0x3c040001, 0x8c846f40, 
-0x621824, 0x3c020700, 0x621825, 0x24020e00, 
-0x2484fffb, 0x2c840002, 0xaf830050, 0xaf850200, 
-0xaf850220, 0x14800006, 0xaf820238, 0x8f820044, 
-0x3c03ffff, 0x34633f7f, 0x431024, 0xaf820044, 
-0x3c030001, 0x8c636f40, 0x24020005, 0x14620004, 
-0x0, 0x8f820044, 0x34425000, 0xaf820044, 
-0x3c020001, 0x8c426d88, 0x3c030001, 0x8c636f40, 
-0x34420022, 0x2463fffc, 0x2c630002, 0x1460000c, 
-0xaf820200, 0x3c020001, 0x8c426dac, 0x3c030001, 
-0x8c636d90, 0x3c040001, 0x8c846d8c, 0x34428000, 
-0x621825, 0x641825, 0x1000000a, 0x34620002, 
-0x3c020001, 0x8c426d90, 0x3c030001, 0x8c636dac, 
-0x3c040001, 0x8c846d8c, 0x431025, 0x441025, 
-0x34420002, 0xaf820220, 0x1000002f, 0x24020001, 
-0x24020e01, 0xaf820238, 0x8f830050, 0x3c02f0ff, 
-0x3442ffff, 0x3c040001, 0x8c846f1c, 0x621824, 
-0x3c020d00, 0x621825, 0x24020001, 0xaf830050, 
-0xaf820200, 0xaf820220, 0x10800005, 0x3c033f00, 
-0x3c020001, 0x8c426d80, 0x10000004, 0x34630070, 
-0x3c020001, 0x8c426d80, 0x34630072, 0x431025, 
-0xaf820200, 0x3c030001, 0x8c636d84, 0x3c02f700, 
-0x621825, 0x3c020001, 0x8c426d90, 0x3c040001, 
-0x8c846dac, 0x3c050001, 0x8ca56f40, 0x431025, 
-0x441025, 0xaf820220, 0x24020005, 0x14a20006, 
-0x24020001, 0x8f820044, 0x2403afff, 0x431024, 
-0xaf820044, 0x24020001, 0x1000003d, 0xaf820238, 
-0x8f830050, 0x3c02f0ff, 0x3442ffff, 0x3c040001, 
-0x8c846f1c, 0x621824, 0x3c020a00, 0x621825, 
-0x24020001, 0xaf830050, 0xaf820200, 0x1080001e, 
-0xaf820220, 0x3c020001, 0x8c426e44, 0x1440001a, 
-0x3c033f00, 0x3c020001, 0x8c426d80, 0x1000001a, 
-0x346300e0, 0x8f830050, 0x3c040001, 0x8c846f1c, 
-0x3442ffff, 0x621824, 0x1080000f, 0xaf830050, 
-0x3c020001, 0x8c426e44, 0x1440000b, 0x3c043f00, 
-0x3c030001, 0x8c636d80, 0x348400e0, 0x24020001, 
-0xaf820200, 0xaf820220, 0x641825, 0xaf830200, 
-0x10000008, 0x3c05f700, 0x3c020001, 0x8c426d80, 
-0x3c033f00, 0x346300e2, 0x431025, 0xaf820200, 
-0x3c05f700, 0x34a58000, 0x3c030001, 0x8c636d84, 
-0x3c020001, 0x8c426d90, 0x3c040001, 0x8c846dac, 
-0x651825, 0x431025, 0x441025, 0xaf820220, 
-0x3e00008, 0x0, 0x3c030001, 0x8c636db4, 
-0x3c020001, 0x8c426db8, 0x10620003, 0x24020002, 
-0x3c010001, 0xac236db8, 0x1062001d, 0x2c620003, 
-0x10400025, 0x24020001, 0x14620023, 0x24020004, 
-0x3c030001, 0x8c636d98, 0x10620006, 0x24020008, 
-0x1462000c, 0x3c0200c8, 0x344201fb, 0x10000009, 
-0xaf820238, 0x24020e01, 0xaf820238, 0x8f820044, 
-0x3c03ffff, 0x34633f7f, 0x431024, 0x34420080, 
-0xaf820044, 0x8f830054, 0x24020002, 0x3c010001, 
-0xac226db4, 0x3c010001, 0x1000000b, 0xac236f2c, 
-0x8f830054, 0x3c020001, 0x8c426f2c, 0x2463d8f0, 
-0x431023, 0x2c422710, 0x14400003, 0x24020009, 
-0x3c010001, 0xac226db4, 0x3e00008, 0x0, 
-0x0, 0x0, 0x0, 0x27bdffd8, 
-0xafb20018, 0x809021, 0xafb3001c, 0xa09821, 
-0xafb10014, 0xc08821, 0xafb00010, 0x8021, 
-0xafbf0020, 0xa6200000, 0xc004d78, 0x24040001, 
-0x26100001, 0x2e020020, 0x1440fffb, 0x0, 
-0xc004d78, 0x2021, 0xc004d78, 0x24040001, 
-0xc004d78, 0x24040001, 0xc004d78, 0x2021, 
-0x24100010, 0x2501024, 0x10400002, 0x2021, 
-0x24040001, 0xc004d78, 0x108042, 0x1600fffa, 
-0x2501024, 0x24100010, 0x2701024, 0x10400002, 
-0x2021, 0x24040001, 0xc004d78, 0x108042, 
-0x1600fffa, 0x2701024, 0xc004db9, 0x34108000, 
-0xc004db9, 0x0, 0xc004d58, 0x0, 
-0x50400005, 0x108042, 0x96220000, 0x501025, 
-0xa6220000, 0x108042, 0x1600fff7, 0x0, 
-0xc004db9, 0x0, 0x8fbf0020, 0x8fb3001c, 
-0x8fb20018, 0x8fb10014, 0x8fb00010, 0x3e00008, 
-0x27bd0028, 0x27bdffd8, 0xafb10014, 0x808821, 
-0xafb20018, 0xa09021, 0xafb3001c, 0xc09821, 
-0xafb00010, 0x8021, 0xafbf0020, 0xc004d78, 
-0x24040001, 0x26100001, 0x2e020020, 0x1440fffb, 
-0x0, 0xc004d78, 0x2021, 0xc004d78, 
-0x24040001, 0xc004d78, 0x2021, 0xc004d78, 
-0x24040001, 0x24100010, 0x2301024, 0x10400002, 
-0x2021, 0x24040001, 0xc004d78, 0x108042, 
-0x1600fffa, 0x2301024, 0x24100010, 0x2501024, 
-0x10400002, 0x2021, 0x24040001, 0xc004d78, 
-0x108042, 0x1600fffa, 0x2501024, 0xc004d78, 
-0x24040001, 0xc004d78, 0x2021, 0x34108000, 
-0x96620000, 0x501024, 0x10400002, 0x2021, 
-0x24040001, 0xc004d78, 0x108042, 0x1600fff8, 
-0x0, 0xc004db9, 0x0, 0x8fbf0020, 
-0x8fb3001c, 0x8fb20018, 0x8fb10014, 0x8fb00010, 
-0x3e00008, 0x27bd0028, 0x3c040001, 0x8c846dd0, 
-0x3c020001, 0x8c426e18, 0x27bdffd8, 0xafbf0020, 
-0xafb1001c, 0x10820003, 0xafb00018, 0x3c010001, 
-0xac246e18, 0x3c030001, 0x8c636f40, 0x24020005, 
-0x14620005, 0x2483ffff, 0xc004963, 0x0, 
-0x1000034c, 0x0, 0x2c620013, 0x10400349, 
-0x31080, 0x3c010001, 0x220821, 0x8c226b80, 
-0x400008, 0x0, 0xc004db9, 0x8021, 
-0x34028000, 0xa7a20010, 0x27b10010, 0xc004d78, 
-0x24040001, 0x26100001, 0x2e020020, 0x1440fffb, 
-0x0, 0xc004d78, 0x2021, 0xc004d78, 
-0x24040001, 0xc004d78, 0x2021, 0xc004d78, 
-0x24040001, 0x24100010, 0x32020001, 0x10400002, 
-0x2021, 0x24040001, 0xc004d78, 0x108042, 
-0x1600fffa, 0x32020001, 0x24100010, 0xc004d78, 
-0x2021, 0x108042, 0x1600fffc, 0x0, 
-0xc004d78, 0x24040001, 0xc004d78, 0x2021, 
-0x34108000, 0x96220000, 0x501024, 0x10400002, 
-0x2021, 0x24040001, 0xc004d78, 0x108042, 
-0x1600fff8, 0x0, 0xc004db9, 0x0, 
-0x1000030e, 0x24020002, 0x27b10010, 0xa7a00010, 
-0x8021, 0xc004d78, 0x24040001, 0x26100001, 
-0x2e020020, 0x1440fffb, 0x0, 0xc004d78, 
-0x2021, 0xc004d78, 0x24040001, 0xc004d78, 
-0x24040001, 0xc004d78, 0x2021, 0x24100010, 
-0x32020001, 0x10400002, 0x2021, 0x24040001, 
-0xc004d78, 0x108042, 0x1600fffa, 0x32020001, 
-0x24100010, 0xc004d78, 0x2021, 0x108042, 
-0x1600fffc, 0x0, 0xc004db9, 0x34108000, 
-0xc004db9, 0x0, 0xc004d58, 0x0, 
-0x50400005, 0x108042, 0x96220000, 0x501025, 
-0xa6220000, 0x108042, 0x1600fff7, 0x0, 
-0xc004db9, 0x0, 0x97a20010, 0x30428000, 
-0x144002dc, 0x24020003, 0x100002d8, 0x0, 
-0x24021200, 0xa7a20010, 0x27b10010, 0x8021, 
-0xc004d78, 0x24040001, 0x26100001, 0x2e020020, 
-0x1440fffb, 0x0, 0xc004d78, 0x2021, 
-0xc004d78, 0x24040001, 0xc004d78, 0x2021, 
-0xc004d78, 0x24040001, 0x24100010, 0x32020001, 
-0x10400002, 0x2021, 0x24040001, 0xc004d78, 
-0x108042, 0x1600fffa, 0x32020001, 0x24100010, 
-0xc004d78, 0x2021, 0x108042, 0x1600fffc, 
-0x0, 0xc004d78, 0x24040001, 0xc004d78, 
-0x2021, 0x34108000, 0x96220000, 0x501024, 
-0x10400002, 0x2021, 0x24040001, 0xc004d78, 
-0x108042, 0x1600fff8, 0x0, 0xc004db9, 
-0x0, 0x8f830054, 0x10000296, 0x24020004, 
-0x8f830054, 0x3c020001, 0x8c426f3c, 0x2463ff9c, 
-0x431023, 0x2c420064, 0x1440029e, 0x24020002, 
-0x3c030001, 0x8c636f40, 0x10620297, 0x2c620003, 
-0x14400296, 0x24020011, 0x24020003, 0x10620005, 
-0x24020004, 0x10620291, 0x2402000f, 0x1000028f, 
-0x24020011, 0x1000028d, 0x24020005, 0x24020014, 
-0xa7a20010, 0x27b10010, 0x8021, 0xc004d78, 
-0x24040001, 0x26100001, 0x2e020020, 0x1440fffb, 
-0x0, 0xc004d78, 0x2021, 0xc004d78, 
-0x24040001, 0xc004d78, 0x2021, 0xc004d78, 
-0x24040001, 0x24100010, 0x32020001, 0x10400002, 
-0x2021, 0x24040001, 0xc004d78, 0x108042, 
-0x1600fffa, 0x32020001, 0x24100010, 0x32020012, 
-0x10400002, 0x2021, 0x24040001, 0xc004d78, 
-0x108042, 0x1600fffa, 0x32020012, 0xc004d78, 
-0x24040001, 0xc004d78, 0x2021, 0x34108000, 
-0x96220000, 0x501024, 0x10400002, 0x2021, 
-0x24040001, 0xc004d78, 0x108042, 0x1600fff8, 
-0x0, 0xc004db9, 0x0, 0x8f830054, 
-0x10000248, 0x24020006, 0x8f830054, 0x3c020001, 
-0x8c426f3c, 0x2463ff9c, 0x431023, 0x2c420064, 
-0x14400250, 0x24020007, 0x1000024c, 0x0, 
-0x24020006, 0xa7a20010, 0x27b10010, 0x8021, 
-0xc004d78, 0x24040001, 0x26100001, 0x2e020020, 
-0x1440fffb, 0x0, 0xc004d78, 0x2021, 
-0xc004d78, 0x24040001, 0xc004d78, 0x2021, 
-0xc004d78, 0x24040001, 0x24100010, 0x32020001, 
-0x10400002, 0x2021, 0x24040001, 0xc004d78, 
-0x108042, 0x1600fffa, 0x32020001, 0x24100010, 
-0x32020013, 0x10400002, 0x2021, 0x24040001, 
-0xc004d78, 0x108042, 0x1600fffa, 0x32020013, 
-0xc004d78, 0x24040001, 0xc004d78, 0x2021, 
-0x34108000, 0x96220000, 0x501024, 0x10400002, 
-0x2021, 0x24040001, 0xc004d78, 0x108042, 
-0x1600fff8, 0x0, 0xc004db9, 0x0, 
-0x8f830054, 0x10000207, 0x24020008, 0x8f830054, 
-0x3c020001, 0x8c426f3c, 0x2463ff9c, 0x431023, 
-0x2c420064, 0x1440020f, 0x24020009, 0x1000020b, 
-0x0, 0x27b10010, 0xa7a00010, 0x8021, 
-0xc004d78, 0x24040001, 0x26100001, 0x2e020020, 
-0x1440fffb, 0x0, 0xc004d78, 0x2021, 
-0xc004d78, 0x24040001, 0xc004d78, 0x24040001, 
-0xc004d78, 0x2021, 0x24100010, 0x32020001, 
-0x10400002, 0x2021, 0x24040001, 0xc004d78, 
-0x108042, 0x1600fffa, 0x32020001, 0x24100010, 
-0x32020018, 0x10400002, 0x2021, 0x24040001, 
-0xc004d78, 0x108042, 0x1600fffa, 0x32020018, 
-0xc004db9, 0x34108000, 0xc004db9, 0x0, 
-0xc004d58, 0x0, 0x50400005, 0x108042, 
-0x96220000, 0x501025, 0xa6220000, 0x108042, 
-0x1600fff7, 0x0, 0xc004db9, 0x8021, 
-0x97a20010, 0x27b10010, 0x34420001, 0xa7a20010, 
-0xc004d78, 0x24040001, 0x26100001, 0x2e020020, 
-0x1440fffb, 0x0, 0xc004d78, 0x2021, 
-0xc004d78, 0x24040001, 0xc004d78, 0x2021, 
-0xc004d78, 0x24040001, 0x24100010, 0x32020001, 
-0x10400002, 0x2021, 0x24040001, 0xc004d78, 
-0x108042, 0x1600fffa, 0x32020001, 0x24100010, 
-0x32020018, 0x10400002, 0x2021, 0x24040001, 
-0xc004d78, 0x108042, 0x1600fffa, 0x32020018, 
-0xc004d78, 0x24040001, 0xc004d78, 0x2021, 
-0x34108000, 0x96220000, 0x501024, 0x10400002, 
-0x2021, 0x24040001, 0xc004d78, 0x108042, 
-0x1600fff8, 0x0, 0xc004db9, 0x0, 
-0x8f830054, 0x10000193, 0x2402000a, 0x8f830054, 
-0x3c020001, 0x8c426f3c, 0x2463ff9c, 0x431023, 
-0x2c420064, 0x1440019b, 0x2402000b, 0x10000197, 
-0x0, 0x27b10010, 0xa7a00010, 0x8021, 
-0xc004d78, 0x24040001, 0x26100001, 0x2e020020, 
-0x1440fffb, 0x0, 0xc004d78, 0x2021, 
-0xc004d78, 0x24040001, 0xc004d78, 0x24040001, 
-0xc004d78, 0x2021, 0x24100010, 0x32020001, 
-0x10400002, 0x2021, 0x24040001, 0xc004d78, 
-0x108042, 0x1600fffa, 0x32020001, 0x24100010, 
-0x32020017, 0x10400002, 0x2021, 0x24040001, 
-0xc004d78, 0x108042, 0x1600fffa, 0x32020017, 
-0xc004db9, 0x34108000, 0xc004db9, 0x0, 
-0xc004d58, 0x0, 0x50400005, 0x108042, 
-0x96220000, 0x501025, 0xa6220000, 0x108042, 
-0x1600fff7, 0x0, 0xc004db9, 0x8021, 
-0x97a20010, 0x27b10010, 0x34420700, 0xa7a20010, 
-0xc004d78, 0x24040001, 0x26100001, 0x2e020020, 
-0x1440fffb, 0x0, 0xc004d78, 0x2021, 
-0xc004d78, 0x24040001, 0xc004d78, 0x2021, 
-0xc004d78, 0x24040001, 0x24100010, 0x32020001, 
-0x10400002, 0x2021, 0x24040001, 0xc004d78, 
-0x108042, 0x1600fffa, 0x32020001, 0x24100010, 
-0x32020017, 0x10400002, 0x2021, 0x24040001, 
-0xc004d78, 0x108042, 0x1600fffa, 0x32020017, 
-0xc004d78, 0x24040001, 0xc004d78, 0x2021, 
-0x34108000, 0x96220000, 0x501024, 0x10400002, 
-0x2021, 0x24040001, 0xc004d78, 0x108042, 
-0x1600fff8, 0x0, 0xc004db9, 0x0, 
-0x8f830054, 0x1000011f, 0x2402000c, 0x8f830054, 
-0x3c020001, 0x8c426f3c, 0x2463ff9c, 0x431023, 
-0x2c420064, 0x14400127, 0x24020012, 0x10000123, 
-0x0, 0x27b10010, 0xa7a00010, 0x8021, 
-0xc004d78, 0x24040001, 0x26100001, 0x2e020020, 
-0x1440fffb, 0x0, 0xc004d78, 0x2021, 
-0xc004d78, 0x24040001, 0xc004d78, 0x24040001, 
-0xc004d78, 0x2021, 0x24100010, 0x32020001, 
-0x10400002, 0x2021, 0x24040001, 0xc004d78, 
-0x108042, 0x1600fffa, 0x32020001, 0x24100010, 
-0x32020014, 0x10400002, 0x2021, 0x24040001, 
-0xc004d78, 0x108042, 0x1600fffa, 0x32020014, 
-0xc004db9, 0x34108000, 0xc004db9, 0x0, 
-0xc004d58, 0x0, 0x50400005, 0x108042, 
-0x96220000, 0x501025, 0xa6220000, 0x108042, 
-0x1600fff7, 0x0, 0xc004db9, 0x8021, 
-0x97a20010, 0x27b10010, 0x34420010, 0xa7a20010, 
-0xc004d78, 0x24040001, 0x26100001, 0x2e020020, 
-0x1440fffb, 0x0, 0xc004d78, 0x2021, 
-0xc004d78, 0x24040001, 0xc004d78, 0x2021, 
-0xc004d78, 0x24040001, 0x24100010, 0x32020001, 
-0x10400002, 0x2021, 0x24040001, 0xc004d78, 
-0x108042, 0x1600fffa, 0x32020001, 0x24100010, 
-0x32020014, 0x10400002, 0x2021, 0x24040001, 
-0xc004d78, 0x108042, 0x1600fffa, 0x32020014, 
-0xc004d78, 0x24040001, 0xc004d78, 0x2021, 
-0x34108000, 0x96220000, 0x501024, 0x10400002, 
-0x2021, 0x24040001, 0xc004d78, 0x108042, 
-0x1600fff8, 0x0, 0xc004db9, 0x0, 
-0x8f830054, 0x100000ab, 0x24020013, 0x8f830054, 
-0x3c020001, 0x8c426f3c, 0x2463ff9c, 0x431023, 
-0x2c420064, 0x144000b3, 0x2402000d, 0x100000af, 
-0x0, 0x27b10010, 0xa7a00010, 0x8021, 
-0xc004d78, 0x24040001, 0x26100001, 0x2e020020, 
-0x1440fffb, 0x0, 0xc004d78, 0x2021, 
-0xc004d78, 0x24040001, 0xc004d78, 0x24040001, 
-0xc004d78, 0x2021, 0x24100010, 0x32020001, 
-0x10400002, 0x2021, 0x24040001, 0xc004d78, 
-0x108042, 0x1600fffa, 0x32020001, 0x24100010, 
-0x32020018, 0x10400002, 0x2021, 0x24040001, 
-0xc004d78, 0x108042, 0x1600fffa, 0x32020018, 
-0xc004db9, 0x34108000, 0xc004db9, 0x0, 
-0xc004d58, 0x0, 0x50400005, 0x108042, 
-0x96220000, 0x501025, 0xa6220000, 0x108042, 
-0x1600fff7, 0x0, 0xc004db9, 0x8021, 
-0x97a20010, 0x27b10010, 0x3042fffe, 0xa7a20010, 
-0xc004d78, 0x24040001, 0x26100001, 0x2e020020, 
-0x1440fffb, 0x0, 0xc004d78, 0x2021, 
-0xc004d78, 0x24040001, 0xc004d78, 0x2021, 
-0xc004d78, 0x24040001, 0x24100010, 0x32020001, 
-0x10400002, 0x2021, 0x24040001, 0xc004d78, 
-0x108042, 0x1600fffa, 0x32020001, 0x24100010, 
-0x32020018, 0x10400002, 0x2021, 0x24040001, 
-0xc004d78, 0x108042, 0x1600fffa, 0x32020018, 
-0xc004d78, 0x24040001, 0xc004d78, 0x2021, 
-0x34108000, 0x96220000, 0x501024, 0x10400002, 
-0x2021, 0x24040001, 0xc004d78, 0x108042, 
-0x1600fff8, 0x0, 0xc004db9, 0x0, 
-0x8f830054, 0x10000037, 0x2402000e, 0x24020840, 
-0xa7a20010, 0x27b10010, 0x8021, 0xc004d78, 
-0x24040001, 0x26100001, 0x2e020020, 0x1440fffb, 
-0x0, 0xc004d78, 0x2021, 0xc004d78, 
-0x24040001, 0xc004d78, 0x2021, 0xc004d78, 
-0x24040001, 0x24100010, 0x32020001, 0x10400002, 
-0x2021, 0x24040001, 0xc004d78, 0x108042, 
-0x1600fffa, 0x32020001, 0x24100010, 0x32020013, 
-0x10400002, 0x2021, 0x24040001, 0xc004d78, 
-0x108042, 0x1600fffa, 0x32020013, 0xc004d78, 
-0x24040001, 0xc004d78, 0x2021, 0x34108000, 
-0x96220000, 0x501024, 0x10400002, 0x2021, 
-0x24040001, 0xc004d78, 0x108042, 0x1600fff8, 
-0x0, 0xc004db9, 0x0, 0x8f830054, 
-0x24020010, 0x3c010001, 0xac226dd0, 0x3c010001, 
-0x1000000c, 0xac236f3c, 0x8f830054, 0x3c020001, 
-0x8c426f3c, 0x2463ff9c, 0x431023, 0x2c420064, 
-0x14400004, 0x0, 0x24020011, 0x3c010001, 
-0xac226dd0, 0x8fbf0020, 0x8fb1001c, 0x8fb00018, 
-0x3e00008, 0x27bd0028, 0x3c030001, 0x8c636d98, 
-0x27bdffc8, 0x24020002, 0xafbf0034, 0xafb20030, 
-0xafb1002c, 0x14620004, 0xafb00028, 0x3c120002, 
-0x10000003, 0x8e528ff8, 0x3c120002, 0x8e528ffc, 
-0x3c030001, 0x8c636dd4, 0x3c020001, 0x8c426e1c, 
-0x50620004, 0x2463ffff, 0x3c010001, 0xac236e1c, 
-0x2463ffff, 0x2c620006, 0x10400377, 0x31080, 
-0x3c010001, 0x220821, 0x8c226bd8, 0x400008, 
-0x0, 0x2021, 0x2821, 0xc004ddb, 
-0x34068000, 0x24040010, 0x24050002, 0x24060002, 
-0x24020002, 0xc004ddb, 0xa7a20018, 0x24020002, 
-0x3c010001, 0x10000364, 0xac226dd4, 0x27b10018, 
-0xa7a00018, 0x8021, 0xc004d78, 0x24040001, 
-0x26100001, 0x2e020020, 0x1440fffb, 0x0, 
-0xc004d78, 0x2021, 0xc004d78, 0x24040001, 
-0xc004d78, 0x24040001, 0xc004d78, 0x2021, 
-0x24100010, 0x32020001, 0x10400002, 0x2021, 
-0x24040001, 0xc004d78, 0x108042, 0x1600fffa, 
-0x32020001, 0x24100010, 0xc004d78, 0x2021, 
-0x108042, 0x1600fffc, 0x0, 0xc004db9, 
-0x34108000, 0xc004db9, 0x0, 0xc004d58, 
-0x0, 0x50400005, 0x108042, 0x96220000, 
-0x501025, 0xa6220000, 0x108042, 0x1600fff7, 
-0x0, 0xc004db9, 0x0, 0x97a20018, 
-0x30428000, 0x14400004, 0x24020003, 0x3c010001, 
-0xac226dd4, 0x24020003, 0x3c010001, 0x1000032a, 
-0xac226dd4, 0x24040010, 0x24050002, 0x24060002, 
-0x24020002, 0xc004ddb, 0xa7a20018, 0x3c030001, 
-0x8c636e20, 0x24020001, 0x146201e1, 0x8021, 
-0x27b10018, 0xa7a00018, 0xc004d78, 0x24040001, 
-0x26100001, 0x2e020020, 0x1440fffb, 0x0, 
-0xc004d78, 0x2021, 0xc004d78, 0x24040001, 
-0xc004d78, 0x24040001, 0xc004d78, 0x2021, 
-0x24100010, 0x32020001, 0x10400002, 0x2021, 
-0x24040001, 0xc004d78, 0x108042, 0x1600fffa, 
-0x32020001, 0x24100010, 0x32020018, 0x10400002, 
-0x2021, 0x24040001, 0xc004d78, 0x108042, 
-0x1600fffa, 0x32020018, 0xc004db9, 0x34108000, 
-0xc004db9, 0x0, 0xc004d58, 0x0, 
-0x50400005, 0x108042, 0x96220000, 0x501025, 
-0xa6220000, 0x108042, 0x1600fff7, 0x0, 
-0xc004db9, 0x8021, 0x27b10018, 0xa7a00018, 
-0xc004d78, 0x24040001, 0x26100001, 0x2e020020, 
-0x1440fffb, 0x0, 0xc004d78, 0x2021, 
-0xc004d78, 0x24040001, 0xc004d78, 0x24040001, 
-0xc004d78, 0x2021, 0x24100010, 0x32020001, 
-0x10400002, 0x2021, 0x24040001, 0xc004d78, 
-0x108042, 0x1600fffa, 0x32020001, 0x24100010, 
-0x32020018, 0x10400002, 0x2021, 0x24040001, 
-0xc004d78, 0x108042, 0x1600fffa, 0x32020018, 
-0xc004db9, 0x34108000, 0xc004db9, 0x0, 
-0xc004d58, 0x0, 0x50400005, 0x108042, 
-0x96220000, 0x501025, 0xa6220000, 0x108042, 
-0x1600fff7, 0x0, 0xc004db9, 0x8021, 
-0x24040018, 0x2821, 0xc004ddb, 0x24060404, 
-0xa7a0001a, 0xc004d78, 0x24040001, 0x26100001, 
-0x2e020020, 0x1440fffb, 0x0, 0xc004d78, 
-0x2021, 0xc004d78, 0x24040001, 0xc004d78, 
-0x24040001, 0xc004d78, 0x2021, 0x24100010, 
-0x32020001, 0x10400002, 0x2021, 0x24040001, 
-0xc004d78, 0x108042, 0x1600fffa, 0x32020001, 
-0x24100010, 0x32020018, 0x10400002, 0x2021, 
-0x24040001, 0xc004d78, 0x108042, 0x1600fffa, 
-0x32020018, 0xc004db9, 0x34108000, 0xc004db9, 
-0x0, 0xc004d58, 0x0, 0x50400005, 
-0x108042, 0x97a2001a, 0x501025, 0xa7a2001a, 
-0x108042, 0x1600fff7, 0x0, 0xc004db9, 
-0x8021, 0xa7a0001a, 0xc004d78, 0x24040001, 
-0x26100001, 0x2e020020, 0x1440fffb, 0x0, 
-0xc004d78, 0x2021, 0xc004d78, 0x24040001, 
-0xc004d78, 0x24040001, 0xc004d78, 0x2021, 
-0x24100010, 0x32020001, 0x10400002, 0x2021, 
-0x24040001, 0xc004d78, 0x108042, 0x1600fffa, 
-0x32020001, 0x24100010, 0x32020018, 0x10400002, 
-0x2021, 0x24040001, 0xc004d78, 0x108042, 
-0x1600fffa, 0x32020018, 0xc004db9, 0x34108000, 
-0xc004db9, 0x0, 0xc004d58, 0x0, 
-0x50400005, 0x108042, 0x97a2001a, 0x501025, 
-0xa7a2001a, 0x108042, 0x1600fff7, 0x0, 
-0xc004db9, 0x8021, 0xa7a0001c, 0xc004d78, 
-0x24040001, 0x26100001, 0x2e020020, 0x1440fffb, 
-0x0, 0xc004d78, 0x2021, 0xc004d78, 
-0x24040001, 0xc004d78, 0x24040001, 0xc004d78, 
-0x2021, 0x24100010, 0xc004d78, 0x2021, 
-0x108042, 0x1600fffc, 0x0, 0x24100010, 
-0x3202001e, 0x10400002, 0x2021, 0x24040001, 
-0xc004d78, 0x108042, 0x1600fffa, 0x3202001e, 
-0xc004db9, 0x34108000, 0xc004db9, 0x0, 
-0xc004d58, 0x0, 0x50400005, 0x108042, 
-0x97a2001c, 0x501025, 0xa7a2001c, 0x108042, 
-0x1600fff7, 0x0, 0xc004db9, 0x8021, 
-0xa7a0001c, 0xc004d78, 0x24040001, 0x26100001, 
-0x2e020020, 0x1440fffb, 0x0, 0xc004d78, 
-0x2021, 0xc004d78, 0x24040001, 0xc004d78, 
-0x24040001, 0xc004d78, 0x2021, 0x24100010, 
-0xc004d78, 0x2021, 0x108042, 0x1600fffc, 
-0x0, 0x24100010, 0x3202001e, 0x10400002, 
-0x2021, 0x24040001, 0xc004d78, 0x108042, 
-0x1600fffa, 0x3202001e, 0xc004db9, 0x34108000, 
-0xc004db9, 0x0, 0xc004d58, 0x0, 
-0x50400005, 0x108042, 0x97a2001c, 0x501025, 
-0xa7a2001c, 0x108042, 0x1600fff7, 0x0, 
-0xc004db9, 0x8021, 0x24020002, 0xa7a2001e, 
-0xc004d78, 0x24040001, 0x26100001, 0x2e020020, 
-0x1440fffb, 0x0, 0xc004d78, 0x2021, 
-0xc004d78, 0x24040001, 0xc004d78, 0x2021, 
-0xc004d78, 0x24040001, 0x24100010, 0xc004d78, 
-0x2021, 0x108042, 0x1600fffc, 0x0, 
-0x24100010, 0x3202001e, 0x10400002, 0x2021, 
-0x24040001, 0xc004d78, 0x108042, 0x1600fffa, 
-0x3202001e, 0xc004d78, 0x24040001, 0xc004d78, 
-0x2021, 0x34108000, 0x97a2001e, 0x501024, 
-0x10400002, 0x2021, 0x24040001, 0xc004d78, 
-0x108042, 0x1600fff8, 0x0, 0xc004db9, 
-0x8021, 0xa7a00020, 0xc004d78, 0x24040001, 
-0x26100001, 0x2e020020, 0x1440fffb, 0x0, 
-0xc004d78, 0x2021, 0xc004d78, 0x24040001, 
-0xc004d78, 0x24040001, 0xc004d78, 0x2021, 
-0x24100010, 0xc004d78, 0x2021, 0x108042, 
-0x1600fffc, 0x0, 0x24100010, 0x3202001e, 
-0x10400002, 0x2021, 0x24040001, 0xc004d78, 
-0x108042, 0x1600fffa, 0x3202001e, 0xc004db9, 
-0x34108000, 0xc004db9, 0x0, 0xc004d58, 
-0x0, 0x50400005, 0x108042, 0x97a20020, 
-0x501025, 0xa7a20020, 0x108042, 0x1600fff7, 
-0x0, 0xc004db9, 0x8021, 0xa7a00020, 
-0xc004d78, 0x24040001, 0x26100001, 0x2e020020, 
-0x1440fffb, 0x0, 0xc004d78, 0x2021, 
-0xc004d78, 0x24040001, 0xc004d78, 0x24040001, 
-0xc004d78, 0x2021, 0x24100010, 0xc004d78, 
-0x2021, 0x108042, 0x1600fffc, 0x0, 
-0x24100010, 0x3202001e, 0x10400002, 0x2021, 
-0x24040001, 0xc004d78, 0x108042, 0x1600fffa, 
-0x3202001e, 0xc004db9, 0x34108000, 0xc004db9, 
-0x0, 0xc004d58, 0x0, 0x50400005, 
-0x108042, 0x97a20020, 0x501025, 0xa7a20020, 
-0x108042, 0x1600fff7, 0x0, 0xc004db9, 
-0x8021, 0xa7a00022, 0xc004d78, 0x24040001, 
-0x26100001, 0x2e020020, 0x1440fffb, 0x0, 
-0xc004d78, 0x2021, 0xc004d78, 0x24040001, 
-0xc004d78, 0x2021, 0xc004d78, 0x24040001, 
-0x24100010, 0xc004d78, 0x2021, 0x108042, 
-0x1600fffc, 0x0, 0x24100010, 0xc004d78, 
-0x2021, 0x108042, 0x1600fffc, 0x0, 
-0xc004d78, 0x24040001, 0xc004d78, 0x2021, 
-0x34108000, 0x97a20022, 0x501024, 0x10400002, 
-0x2021, 0x24040001, 0xc004d78, 0x108042, 
-0x1600fff8, 0x0, 0xc004db9, 0x0, 
-0x24040018, 0x24050002, 0xc004ddb, 0x24060004, 
-0x3c100001, 0x8e106e24, 0x24020001, 0x1602011d, 
-0x0, 0x3c020001, 0x94426f26, 0x3c010001, 
-0xac206e24, 0x24429fbc, 0x2c420004, 0x1040000c, 
-0x24040009, 0x24050001, 0xc004ddb, 0x24060400, 
-0x24040018, 0x24050001, 0xc004ddb, 0x24060020, 
-0x24040018, 0x24050001, 0xc004ddb, 0x24062000, 
-0x3c024000, 0x2421024, 0x10400123, 0x3c022000, 
-0x2421024, 0x10400004, 0x0, 0x3c010001, 
-0x10000003, 0xac306f1c, 0x3c010001, 0xac206f1c, 
-0x3c030001, 0x8c636f34, 0x24020005, 0x146200f9, 
-0x0, 0x3c020001, 0x8c426f1c, 0x10400067, 
-0x3c020004, 0x2421024, 0x10400011, 0xa7a00018, 
-0x3c020008, 0x2421024, 0x10400002, 0x24020200, 
-0xa7a20018, 0x3c020010, 0x2421024, 0x10400004, 
-0x0, 0x97a20018, 0x34420100, 0xa7a20018, 
-0x97a60018, 0x24040009, 0x10000004, 0x2821, 
-0x24040009, 0x2821, 0x3021, 0xc004ddb, 
-0x0, 0x24020001, 0xa7a2001a, 0x3c020008, 
-0x2421024, 0x1040000c, 0x3c020002, 0x2421024, 
-0x10400002, 0x24020101, 0xa7a2001a, 0x3c020001, 
-0x2421024, 0x10400005, 0x3c020010, 0x97a2001a, 
-0x34420040, 0xa7a2001a, 0x3c020010, 0x2421024, 
-0x1040000e, 0x3c020002, 0x2421024, 0x10400005, 
-0x3c020001, 0x97a2001a, 0x34420080, 0xa7a2001a, 
-0x3c020001, 0x2421024, 0x10400005, 0x3c0300a0, 
-0x97a2001a, 0x34420020, 0xa7a2001a, 0x3c0300a0, 
-0x2431024, 0x54430004, 0x3c020020, 0x97a2001a, 
-0x1000000c, 0x34420400, 0x2421024, 0x50400004, 
-0x3c020080, 0x97a2001a, 0x10000006, 0x34420800, 
-0x2421024, 0x10400004, 0x0, 0x97a2001a, 
-0x34420c00, 0xa7a2001a, 0x97a6001a, 0x24040004, 
-0xc004ddb, 0x2821, 0x3c020004, 0x2421024, 
-0x10400004, 0xa7a0001c, 0x32425000, 0x14400004, 
-0x0, 0x32424000, 0x10400005, 0x2021, 
-0xc004cf9, 0x2402021, 0x10000096, 0x0, 
-0x97a6001c, 0x2821, 0x34c61200, 0xc004ddb, 
-0xa7a6001c, 0x1000008f, 0x0, 0x2421024, 
-0x10400004, 0xa7a00018, 0x32425000, 0x14400004, 
-0x0, 0x32424000, 0x10400005, 0x3c020010, 
-0xc004cf9, 0x2402021, 0x10000019, 0xa7a0001a, 
-0x2421024, 0x10400004, 0x0, 0x97a20018, 
-0x10000004, 0xa7a20018, 0x97a20018, 0x34420100, 
-0xa7a20018, 0x3c020001, 0x2421024, 0x10400004, 
-0x0, 0x97a20018, 0x10000004, 0xa7a20018, 
-0x97a20018, 0x34422000, 0xa7a20018, 0x97a60018, 
-0x2021, 0xc004ddb, 0x2821, 0xa7a0001a, 
-0x8021, 0xc004d78, 0x24040001, 0x26100001, 
-0x2e020020, 0x1440fffb, 0x0, 0xc004d78, 
-0x2021, 0xc004d78, 0x24040001, 0xc004d78, 
-0x24040001, 0xc004d78, 0x2021, 0x24100010, 
-0x32020001, 0x10400002, 0x2021, 0x24040001, 
-0xc004d78, 0x108042, 0x1600fffa, 0x32020001, 
-0x24100010, 0xc004d78, 0x2021, 0x108042, 
-0x1600fffc, 0x0, 0xc004db9, 0x34108000, 
-0xc004db9, 0x0, 0xc004d58, 0x0, 
-0x50400005, 0x108042, 0x97a2001a, 0x501025, 
-0xa7a2001a, 0x108042, 0x1600fff7, 0x0, 
-0xc004db9, 0x8021, 0xa7a0001a, 0xc004d78, 
-0x24040001, 0x26100001, 0x2e020020, 0x1440fffb, 
-0x0, 0xc004d78, 0x2021, 0xc004d78, 
-0x24040001, 0xc004d78, 0x24040001, 0xc004d78, 
-0x2021, 0x24100010, 0x32020001, 0x10400002, 
-0x2021, 0x24040001, 0xc004d78, 0x108042, 
-0x1600fffa, 0x32020001, 0x24100010, 0xc004d78, 
-0x2021, 0x108042, 0x1600fffc, 0x0, 
-0xc004db9, 0x34108000, 0xc004db9, 0x0, 
-0xc004d58, 0x0, 0x50400005, 0x108042, 
-0x97a2001a, 0x501025, 0xa7a2001a, 0x108042, 
-0x1600fff7, 0x0, 0xc004db9, 0x0, 
-0x3c040001, 0x24846bcc, 0x97a60018, 0x97a7001a, 
-0x3c020001, 0x8c426d98, 0x3c030001, 0x8c636f1c, 
-0x3c05000d, 0x34a50205, 0xafa20010, 0xc002b3b, 
-0xafa30014, 0x8f830054, 0x24020004, 0x3c010001, 
-0xac226dd4, 0x3c010001, 0x10000017, 0xac236f38, 
-0x8f830054, 0x3c020001, 0x8c426f38, 0x2463ff9c, 
-0x431023, 0x2c420064, 0x1440000f, 0x0, 
-0x8f820220, 0x24030005, 0x3c010001, 0xac236dd4, 
-0x3c03f700, 0x431025, 0x10000007, 0xaf820220, 
-0x24020006, 0x3c010001, 0xac226dd4, 0x24020011, 
-0x3c010001, 0xac226dd0, 0x8fbf0034, 0x8fb20030, 
-0x8fb1002c, 0x8fb00028, 0x3e00008, 0x27bd0038, 
-0x27bdffd8, 0xafb00018, 0x808021, 0xafb1001c, 
-0x8821, 0x32024000, 0x10400013, 0xafbf0020, 
-0x3c020010, 0x2021024, 0x2c420001, 0x21023, 
-0x30434100, 0x3c020001, 0x2021024, 0x14400006, 
-0x34714000, 0x3c020002, 0x2021024, 0x14400002, 
-0x34716000, 0x34714040, 0x2021, 0x2821, 
-0x10000036, 0x2203021, 0x32021000, 0x10400035, 
-0x2021, 0x2821, 0xc004ddb, 0x24060040, 
-0x24040018, 0x2821, 0xc004ddb, 0x24060c00, 
-0x24040017, 0x2821, 0xc004ddb, 0x24060400, 
-0x24040016, 0x2821, 0xc004ddb, 0x24060006, 
-0x24040017, 0x2821, 0xc004ddb, 0x24062500, 
-0x24040016, 0x2821, 0xc004ddb, 0x24060006, 
-0x24040017, 0x2821, 0xc004ddb, 0x24064600, 
-0x24040016, 0x2821, 0xc004ddb, 0x24060006, 
-0x24040017, 0x2821, 0xc004ddb, 0x24066700, 
-0x24040016, 0x2821, 0xc004ddb, 0x24060006, 
-0x2404001f, 0x2821, 0xc004ddb, 0x24060010, 
-0x24040009, 0x2821, 0xc004ddb, 0x24061500, 
-0x24040009, 0x2821, 0x24061d00, 0xc004ddb, 
-0x0, 0x3c040001, 0x24846bf0, 0x3c05000e, 
-0x34a50100, 0x2003021, 0x2203821, 0xafa00010, 
-0xc002b3b, 0xafa00014, 0x8fbf0020, 0x8fb1001c, 
-0x8fb00018, 0x3e00008, 0x27bd0028, 0x8f850044, 
-0x8f820044, 0x3c030001, 0x431025, 0x3c030008, 
-0xaf820044, 0x8f840054, 0x8f820054, 0xa32824, 
-0x10000002, 0x24840001, 0x8f820054, 0x821023, 
-0x2c420002, 0x1440fffc, 0x0, 0x8f820044, 
-0x3c03fffe, 0x3463ffff, 0x431024, 0xaf820044, 
-0x8f830054, 0x8f820054, 0x10000002, 0x24630001, 
-0x8f820054, 0x621023, 0x2c420002, 0x1440fffc, 
-0x0, 0x3e00008, 0xa01021, 0x8f830044, 
-0x3c02fff0, 0x3442ffff, 0x42480, 0x621824, 
-0x3c020002, 0x822025, 0x641825, 0xaf830044, 
-0x8f820044, 0x3c03fffe, 0x3463ffff, 0x431024, 
-0xaf820044, 0x8f830054, 0x8f820054, 0x10000002, 
-0x24630001, 0x8f820054, 0x621023, 0x2c420002, 
-0x1440fffc, 0x0, 0x8f820044, 0x3c030001, 
-0x431025, 0xaf820044, 0x8f830054, 0x8f820054, 
-0x10000002, 0x24630001, 0x8f820054, 0x621023, 
-0x2c420002, 0x1440fffc, 0x0, 0x3e00008, 
-0x0, 0x8f820044, 0x2403ff7f, 0x431024, 
-0xaf820044, 0x8f830054, 0x8f820054, 0x10000002, 
-0x24630001, 0x8f820054, 0x621023, 0x2c420002, 
-0x1440fffc, 0x0, 0x8f820044, 0x34420080, 
-0xaf820044, 0x8f830054, 0x8f820054, 0x10000002, 
-0x24630001, 0x8f820054, 0x621023, 0x2c420002, 
-0x1440fffc, 0x0, 0x3e00008, 0x0, 
-0x8f820044, 0x3c03fff0, 0x3463ffff, 0x431024, 
-0xaf820044, 0x8f820044, 0x3c030001, 0x431025, 
-0xaf820044, 0x8f830054, 0x8f820054, 0x10000002, 
-0x24630001, 0x8f820054, 0x621023, 0x2c420002, 
-0x1440fffc, 0x0, 0x8f820044, 0x3c03fffe, 
-0x3463ffff, 0x431024, 0xaf820044, 0x8f830054, 
-0x8f820054, 0x10000002, 0x24630001, 0x8f820054, 
-0x621023, 0x2c420002, 0x1440fffc, 0x0, 
-0x3e00008, 0x0, 0x27bdffc8, 0xafb30024, 
-0x809821, 0xafbe002c, 0xa0f021, 0xafb20020, 
-0xc09021, 0x33c2ffff, 0xafbf0030, 0xafb50028, 
-0xafb1001c, 0xafb00018, 0x14400034, 0xa7b20010, 
-0x3271ffff, 0x27b20010, 0x8021, 0xc004d78, 
-0x24040001, 0x26100001, 0x2e020020, 0x1440fffb, 
-0x0, 0xc004d78, 0x2021, 0xc004d78, 
-0x24040001, 0xc004d78, 0x2021, 0xc004d78, 
-0x24040001, 0x24100010, 0x32020001, 0x10400002, 
-0x2021, 0x24040001, 0xc004d78, 0x108042, 
-0x1600fffa, 0x32020001, 0x24100010, 0x2301024, 
-0x10400002, 0x2021, 0x24040001, 0xc004d78, 
-0x108042, 0x1600fffa, 0x2301024, 0xc004d78, 
-0x24040001, 0xc004d78, 0x2021, 0x34108000, 
-0x96420000, 0x501024, 0x10400002, 0x2021, 
-0x24040001, 0xc004d78, 0x108042, 0x12000075, 
-0x0, 0x1000fff6, 0x0, 0x3275ffff, 
-0x27b10010, 0xa7a00010, 0x8021, 0xc004d78, 
-0x24040001, 0x26100001, 0x2e020020, 0x1440fffb, 
-0x0, 0xc004d78, 0x2021, 0xc004d78, 
-0x24040001, 0xc004d78, 0x24040001, 0xc004d78, 
-0x2021, 0x24100010, 0x32020001, 0x10400002, 
-0x2021, 0x24040001, 0xc004d78, 0x108042, 
-0x1600fffa, 0x32020001, 0x24100010, 0x2b01024, 
-0x10400002, 0x2021, 0x24040001, 0xc004d78, 
-0x108042, 0x1600fffa, 0x2b01024, 0xc004db9, 
-0x34108000, 0xc004db9, 0x0, 0xc004d58, 
-0x0, 0x50400005, 0x108042, 0x96220000, 
-0x501025, 0xa6220000, 0x108042, 0x1600fff7, 
-0x0, 0xc004db9, 0x0, 0x33c5ffff, 
-0x24020001, 0x54a20004, 0x24020002, 0x97a20010, 
-0x10000006, 0x521025, 0x14a20006, 0x3271ffff, 
-0x97a20010, 0x121827, 0x431024, 0xa7a20010, 
-0x3271ffff, 0x27b20010, 0x8021, 0xc004d78, 
-0x24040001, 0x26100001, 0x2e020020, 0x1440fffb, 
-0x0, 0xc004d78, 0x2021, 0xc004d78, 
-0x24040001, 0xc004d78, 0x2021, 0xc004d78, 
-0x24040001, 0x24100010, 0x32020001, 0x10400002, 
-0x2021, 0x24040001, 0xc004d78, 0x108042, 
-0x1600fffa, 0x32020001, 0x24100010, 0x2301024, 
-0x10400002, 0x2021, 0x24040001, 0xc004d78, 
-0x108042, 0x1600fffa, 0x2301024, 0xc004d78, 
-0x24040001, 0xc004d78, 0x2021, 0x34108000, 
-0x96420000, 0x501024, 0x10400002, 0x2021, 
-0x24040001, 0xc004d78, 0x108042, 0x1600fff8, 
-0x0, 0xc004db9, 0x0, 0x8fbf0030, 
-0x8fbe002c, 0x8fb50028, 0x8fb30024, 0x8fb20020, 
-0x8fb1001c, 0x8fb00018, 0x3e00008, 0x27bd0038, 
-0x0, 0x0, 0x0, 0x27bdffe8, 
-0xafbf0010, 0x8ee304b8, 0x24020008, 0x146201e0, 
-0x0, 0x3c020001, 0x8c426f1c, 0x14400005, 
-0x0, 0xc003daf, 0x8f840224, 0x100001d8, 
-0x0, 0x8f820220, 0x3c030008, 0x431024, 
-0x10400026, 0x24020001, 0x8f840224, 0x8f820220, 
-0x3c030400, 0x431024, 0x10400006, 0x0, 
-0x3c010002, 0xac208fa0, 0x3c010002, 0x1000000b, 
-0xac208fc0, 0x3c030002, 0x24638fa0, 0x8c620000, 
-0x24420001, 0xac620000, 0x2c420002, 0x14400003, 
-0x24020001, 0x3c010002, 0xac228fc0, 0x3c020002, 
-0x8c428fc0, 0x10400006, 0x30820040, 0x10400004, 
-0x24020001, 0x3c010002, 0x10000003, 0xac228fc4, 
-0x3c010002, 0xac208fc4, 0x3c010002, 0xac248f9c, 
-0x3c010002, 0x1000000b, 0xac208fd0, 0x3c010002, 
-0xac228fd0, 0x3c010002, 0xac208fc0, 0x3c010002, 
-0xac208fa0, 0x3c010002, 0xac208fc4, 0x3c010002, 
-0xac208f9c, 0x3c030002, 0x8c638f90, 0x3c020002, 
-0x8c428f94, 0x50620004, 0x2463ffff, 0x3c010002, 
-0xac238f94, 0x2463ffff, 0x2c62000e, 0x10400194, 
-0x31080, 0x3c010001, 0x220821, 0x8c226c00, 
-0x400008, 0x0, 0x24020002, 0x3c010002, 
-0xac208fc0, 0x3c010002, 0xac208fa0, 0x3c010002, 
-0xac208f9c, 0x3c010002, 0xac208fc4, 0x3c010002, 
-0xac208fb8, 0x3c010002, 0xac208fb0, 0xaf800224, 
-0x3c010002, 0xac228f90, 0x3c020002, 0x8c428fd0, 
-0x1440004f, 0x3c02fdff, 0x3442ffff, 0xc003daf, 
-0x282a024, 0xaf800204, 0x8f820200, 0x2403fffd, 
-0x431024, 0xaf820200, 0x3c010002, 0xac208fe0, 
-0x8f830054, 0x3c020002, 0x8c428fb8, 0x24040001, 
-0x3c010002, 0xac248fcc, 0x24420001, 0x3c010002, 
-0xac228fb8, 0x2c420004, 0x3c010002, 0xac238fb4, 
-0x14400006, 0x24020003, 0x3c010001, 0xac246d9c, 
-0x3c010002, 0x1000015e, 0xac208fb8, 0x3c010002, 
-0x1000015b, 0xac228f90, 0x8f830054, 0x3c020002, 
-0x8c428fb4, 0x2463d8f0, 0x431023, 0x2c422710, 
-0x14400003, 0x24020004, 0x3c010002, 0xac228f90, 
-0x3c020002, 0x8c428fd0, 0x14400021, 0x3c02fdff, 
-0x3442ffff, 0x1000014a, 0x282a024, 0x3c040001, 
-0x8c846f20, 0x3c010002, 0xc005084, 0xac208fa8, 
-0x3c020002, 0x8c428fdc, 0xaf820204, 0x3c020002, 
-0x8c428fd0, 0x14400012, 0x3c03fdff, 0x8f820204, 
-0x3463ffff, 0x30420030, 0x1440012f, 0x283a024, 
-0x3c030002, 0x8c638fdc, 0x24020005, 0x3c010002, 
-0xac228f90, 0x3c010002, 0x10000131, 0xac238fe0, 
-0x3c020002, 0x8c428fd0, 0x10400010, 0x3c02fdff, 
-0x3c020001, 0x8c426e3c, 0x24420001, 0x3c010001, 
-0xac226e3c, 0x2c420002, 0x14400125, 0x24020001, 
-0x3c010001, 0xac226e44, 0x3c010001, 0xac206e3c, 
-0x3c010001, 0x1000011e, 0xac226d9c, 0x3c030002, 
-0x8c638fc0, 0x3442ffff, 0x10600119, 0x282a024, 
-0x3c020002, 0x8c428f9c, 0x10400115, 0x0, 
-0x3c010002, 0xac228fc8, 0x24020003, 0x3c010002, 
-0xac228fa0, 0x100000b8, 0x24020006, 0x3c010002, 
-0xac208fa8, 0x8f820204, 0x34420040, 0xaf820204, 
-0x3c020002, 0x8c428fe0, 0x24030007, 0x3c010002, 
-0xac238f90, 0x34420040, 0x3c010002, 0xac228fe0, 
-0x3c020002, 0x8c428fc0, 0x10400005, 0x0, 
-0x3c020002, 0x8c428f9c, 0x104000f0, 0x24020002, 
-0x3c050002, 0x24a58fa0, 0x8ca20000, 0x2c424e21, 
-0x104000ea, 0x24020002, 0x3c020002, 0x8c428fc4, 
-0x104000ef, 0x2404ffbf, 0x3c020002, 0x8c428f9c, 
-0x3c030002, 0x8c638fc8, 0x441024, 0x641824, 
-0x10430004, 0x24020001, 0x3c010002, 0x100000e4, 
-0xac228f90, 0x24020003, 0xaca20000, 0x24020008, 
-0x3c010002, 0xac228f90, 0x3c020002, 0x8c428fcc, 
-0x1040000c, 0x24020001, 0x3c040002, 0xc005091, 
-0x8c848f9c, 0x3c020002, 0x8c428fe8, 0x14400005, 
-0x24020001, 0x3c020002, 0x8c428fe4, 0x10400006, 
-0x24020001, 0x3c010001, 0xac226d9c, 0x3c010002, 
-0x100000cb, 0xac208fb8, 0x3c020002, 0x8c428fb0, 
-0x3c030002, 0x8c638f9c, 0x2c420001, 0x210c0, 
-0x30630008, 0x3c010002, 0xac228fb0, 0x3c010002, 
-0xac238fac, 0x8f830054, 0x24020009, 0x3c010002, 
-0xac228f90, 0x3c010002, 0x100000b9, 0xac238fb4, 
-0x8f830054, 0x3c020002, 0x8c428fb4, 0x2463d8f0, 
-0x431023, 0x2c422710, 0x1440009f, 0x0, 
-0x3c020002, 0x8c428fc0, 0x10400005, 0x0, 
-0x3c020002, 0x8c428f9c, 0x104000a0, 0x24020002, 
-0x3c030002, 0x24638fa0, 0x8c620000, 0x2c424e21, 
-0x1040009a, 0x24020002, 0x3c020002, 0x8c428fcc, 
-0x1040000e, 0x0, 0x3c020002, 0x8c428f9c, 
-0x3c010002, 0xac208fcc, 0x30420080, 0x1040002f, 
-0x2402000c, 0x8f820204, 0x30420080, 0x1440000c, 
-0x24020003, 0x10000029, 0x2402000c, 0x3c020002, 
-0x8c428f9c, 0x30420080, 0x14400005, 0x24020003, 
-0x8f820204, 0x30420080, 0x1040001f, 0x24020003, 
-0xac620000, 0x2402000a, 0x3c010002, 0xac228f90, 
-0x3c040002, 0x24848fd8, 0x8c820000, 0x3c030002, 
-0x8c638fb0, 0x431025, 0xaf820204, 0x8c830000, 
-0x3c040002, 0x8c848fb0, 0x2402000b, 0x3c010002, 
-0xac228f90, 0x641825, 0x3c010002, 0xac238fe0, 
-0x3c050002, 0x24a58fa0, 0x8ca20000, 0x2c424e21, 
-0x10400066, 0x24020002, 0x3c020002, 0x8c428fd0, 
-0x10400005, 0x0, 0x2402000c, 0x3c010002, 
-0x10000067, 0xac228f90, 0x3c020002, 0x8c428fc0, 
-0x10400063, 0x0, 0x3c040002, 0x8c848f9c, 
-0x10800055, 0x30820008, 0x3c030002, 0x8c638fac, 
-0x1062005b, 0x24020003, 0x3c010002, 0xac248fc8, 
-0xaca20000, 0x24020006, 0x3c010002, 0x10000054, 
-0xac228f90, 0x8f820200, 0x34420002, 0xaf820200, 
-0x8f830054, 0x2402000d, 0x3c010002, 0xac228f90, 
-0x3c010002, 0xac238fb4, 0x8f830054, 0x3c020002, 
-0x8c428fb4, 0x2463d8f0, 0x431023, 0x2c422710, 
-0x14400031, 0x0, 0x3c020002, 0x8c428fd0, 
-0x10400020, 0x2402000e, 0x3c030002, 0x8c638fe4, 
-0x3c010002, 0x14600015, 0xac228f90, 0xc003e6d, 
-0x0, 0x3c050001, 0x8ca56d98, 0xc00529b, 
-0x2021, 0x3c030001, 0x8c636d98, 0x24020004, 
-0x14620005, 0x2403fffb, 0x3c020001, 0x8c426d94, 
-0x10000003, 0x2403fff7, 0x3c020001, 0x8c426d94, 
-0x431024, 0x3c010001, 0xac226d94, 0x8f830224, 
-0x3c020200, 0x3c010002, 0xac238fec, 0x10000020, 
-0x282a025, 0x3c020002, 0x8c428fc0, 0x10400005, 
-0x0, 0x3c020002, 0x8c428f9c, 0x1040000f, 
-0x24020002, 0x3c020002, 0x8c428fa0, 0x2c424e21, 
-0x1040000a, 0x24020002, 0x3c020002, 0x8c428fc0, 
-0x1040000f, 0x0, 0x3c020002, 0x8c428f9c, 
-0x1440000b, 0x0, 0x24020002, 0x3c010002, 
-0x10000007, 0xac228f90, 0x3c020002, 0x8c428fc0, 
-0x10400003, 0x0, 0xc003daf, 0x0, 
-0x8f820220, 0x3c03f700, 0x431025, 0xaf820220, 
-0x8fbf0010, 0x3e00008, 0x27bd0018, 0x3c030002, 
-0x24638fe8, 0x8c620000, 0x10400005, 0x34422000, 
-0x3c010002, 0xac228fdc, 0x10000003, 0xac600000, 
-0x3c010002, 0xac248fdc, 0x3e00008, 0x0, 
-0x27bdffe0, 0x30820030, 0xafbf0018, 0x3c010002, 
-0xac228fe4, 0x14400067, 0x3c02ffff, 0x34421f0e, 
-0x821024, 0x14400061, 0x24020030, 0x30822000, 
-0x1040005d, 0x30838000, 0x31a02, 0x30820001, 
-0x21200, 0x3c040001, 0x8c846f20, 0x621825, 
-0x331c2, 0x3c030001, 0x24636e48, 0x30828000, 
-0x21202, 0x30840001, 0x42200, 0x441025, 
-0x239c2, 0x61080, 0x431021, 0x471021, 
-0x90430000, 0x24020001, 0x10620025, 0x0, 
-0x10600007, 0x24020002, 0x10620013, 0x24020003, 
-0x1062002c, 0x3c05000f, 0x10000037, 0x0, 
-0x8f820200, 0x2403feff, 0x431024, 0xaf820200, 
-0x8f820220, 0x3c03fffe, 0x3463ffff, 0x431024, 
-0xaf820220, 0x3c010002, 0xac209004, 0x3c010002, 
-0x10000034, 0xac20900c, 0x8f820200, 0x34420100, 
-0xaf820200, 0x8f820220, 0x3c03fffe, 0x3463ffff, 
-0x431024, 0xaf820220, 0x24020100, 0x3c010002, 
-0xac229004, 0x3c010002, 0x10000026, 0xac20900c, 
-0x8f820200, 0x2403feff, 0x431024, 0xaf820200, 
-0x8f820220, 0x3c030001, 0x431025, 0xaf820220, 
-0x3c010002, 0xac209004, 0x3c010002, 0x10000019, 
-0xac23900c, 0x8f820200, 0x34420100, 0xaf820200, 
-0x8f820220, 0x3c030001, 0x431025, 0xaf820220, 
-0x24020100, 0x3c010002, 0xac229004, 0x3c010002, 
-0x1000000c, 0xac23900c, 0x34a5ffff, 0x3c040001, 
-0x24846c38, 0xafa30010, 0xc002b3b, 0xafa00014, 
-0x10000004, 0x0, 0x24020030, 0x3c010002, 
-0xac228fe8, 0x8fbf0018, 0x3e00008, 0x27bd0020, 
-0x0, 0x0, 0x0, 0x27bdffc8, 
-0xafb20028, 0x809021, 0xafb3002c, 0xa09821, 
-0xafb00020, 0xc08021, 0x3c040001, 0x24846c50, 
-0x3c050009, 0x3c020001, 0x8c426d98, 0x34a59001, 
-0x2403021, 0x2603821, 0xafbf0030, 0xafb10024, 
-0xa7a0001a, 0xafb00014, 0xc002b3b, 0xafa20010, 
-0x24020002, 0x12620083, 0x2e620003, 0x10400005, 
-0x24020001, 0x1262000a, 0x0, 0x10000173, 
-0x0, 0x24020004, 0x126200f8, 0x24020008, 
-0x126200f7, 0x3c02ffec, 0x1000016c, 0x0, 
-0x3c020001, 0x8c426d94, 0x30420002, 0x14400004, 
-0x128940, 0x3c02fffb, 0x3442ffff, 0x2028024, 
-0x3c010002, 0x310821, 0xac308ffc, 0x3c024000, 
-0x2021024, 0x1040004e, 0x1023c2, 0x30840030, 
-0x101382, 0x3042001c, 0x3c030001, 0x24636dd8, 
-0x431021, 0x823821, 0x3c020020, 0x2021024, 
-0x10400006, 0x24020100, 0x3c010002, 0x310821, 
-0xac229000, 0x10000005, 0x3c020080, 0x3c010002, 
-0x310821, 0xac209000, 0x3c020080, 0x2021024, 
-0x10400006, 0x121940, 0x3c020001, 0x3c010002, 
-0x230821, 0x10000005, 0xac229008, 0x121140, 
-0x3c010002, 0x220821, 0xac209008, 0x94e40000, 
-0x3c030001, 0x8c636f40, 0x24020005, 0x10620010, 
-0xa7a40018, 0x32024000, 0x10400002, 0x34824000, 
-0xa7a20018, 0x24040001, 0x94e20002, 0x24050004, 
-0x24e60002, 0x34420001, 0xc0045be, 0xa4e20002, 
-0x24040001, 0x2821, 0xc0045be, 0x27a60018, 
-0x3c020001, 0x8c426d98, 0x24110001, 0x3c010001, 
-0xac316da4, 0x14530004, 0x32028000, 0xc003daf, 
-0x0, 0x32028000, 0x1040011c, 0x0, 
-0xc003daf, 0x0, 0x3c030001, 0x8c636f40, 
-0x24020005, 0x10620115, 0x24020002, 0x3c010001, 
-0xac316d9c, 0x3c010001, 0x10000110, 0xac226d98, 
-0x24040001, 0x24050004, 0x27b0001a, 0xc0045be, 
-0x2003021, 0x24040001, 0x2821, 0xc0045be, 
-0x2003021, 0x3c020002, 0x511021, 0x8c428ff4, 
-0x3c040001, 0x8c846d98, 0x3c03bfff, 0x3463ffff, 
-0x3c010001, 0xac336da4, 0x431024, 0x3c010002, 
-0x310821, 0x109300f7, 0xac228ff4, 0x100000f7, 
-0x0, 0x3c022000, 0x2021024, 0x10400005, 
-0x24020001, 0x3c010001, 0xac226f1c, 0x10000004, 
-0x128940, 0x3c010001, 0xac206f1c, 0x128940, 
-0x3c010002, 0x310821, 0xac308ff8, 0x3c024000, 
-0x2021024, 0x14400014, 0x0, 0x3c020001, 
-0x8c426f1c, 0x10400006, 0x24040004, 0x24050001, 
-0xc004ddb, 0x24062000, 0x24020001, 0xaee204b8, 
-0x3c020002, 0x511021, 0x8c428ff0, 0x3c03bfff, 
-0x3463ffff, 0x431024, 0x3c010002, 0x310821, 
-0x100000d0, 0xac228ff0, 0x3c020001, 0x8c426f1c, 
-0x10400028, 0x3c0300a0, 0x2031024, 0x5443000d, 
-0x3c020020, 0x3c020001, 0x8c426f20, 0x24030100, 
-0x3c010002, 0x310821, 0xac239004, 0x3c030001, 
-0x3c010002, 0x310821, 0xac23900c, 0x10000015, 
-0x34420400, 0x2021024, 0x10400008, 0x24030100, 
-0x3c020001, 0x8c426f20, 0x3c010002, 0x310821, 
-0xac239004, 0x1000000b, 0x34420800, 0x3c020080, 
-0x2021024, 0x1040002e, 0x3c030001, 0x3c020001, 
-0x8c426f20, 0x3c010002, 0x310821, 0xac23900c, 
-0x34420c00, 0x3c010001, 0xac226f20, 0x10000025, 
-0x24040001, 0x3c020020, 0x2021024, 0x10400006, 
-0x24020100, 0x3c010002, 0x310821, 0xac229004, 
-0x10000005, 0x3c020080, 0x3c010002, 0x310821, 
-0xac209004, 0x3c020080, 0x2021024, 0x10400007, 
-0x121940, 0x3c020001, 0x3c010002, 0x230821, 
-0xac22900c, 0x10000006, 0x24040001, 0x121140, 
-0x3c010002, 0x220821, 0xac20900c, 0x24040001, 
-0x2821, 0x27b0001e, 0xc00457c, 0x2003021, 
-0x24040001, 0x2821, 0xc00457c, 0x2003021, 
-0x24040001, 0x24050001, 0x27b0001c, 0xc00457c, 
-0x2003021, 0x24040001, 0x24050001, 0xc00457c, 
-0x2003021, 0x10000077, 0x0, 0x3c02ffec, 
-0x3442ffff, 0x2028024, 0x3c020008, 0x2028025, 
-0x121140, 0x3c010002, 0x220821, 0xac308ff8, 
-0x3c022000, 0x2021024, 0x10400009, 0x0, 
-0x3c020001, 0x8c426e44, 0x14400005, 0x24020001, 
-0x3c010001, 0xac226f1c, 0x10000004, 0x3c024000, 
-0x3c010001, 0xac206f1c, 0x3c024000, 0x2021024, 
-0x1440001d, 0x24020e01, 0x3c030001, 0x8c636f1c, 
-0xaf820238, 0x3c010001, 0xac206db0, 0x10600005, 
-0x24022020, 0x3c010001, 0xac226f20, 0x24020001, 
-0xaee204b8, 0x3c04bfff, 0x121940, 0x3c020002, 
-0x431021, 0x8c428ff0, 0x3c050001, 0x8ca56d98, 
-0x3484ffff, 0x441024, 0x3c010002, 0x230821, 
-0xac228ff0, 0x24020001, 0x10a20044, 0x0, 
-0x10000040, 0x0, 0x3c020001, 0x8c426f1c, 
-0x1040001c, 0x24022000, 0x3c010001, 0xac226f20, 
-0x3c0300a0, 0x2031024, 0x14430005, 0x121140, 
-0x3402a000, 0x3c010001, 0x1000002d, 0xac226f20, 
-0x3c030002, 0x621821, 0x8c638ff8, 0x3c020020, 
-0x621024, 0x10400004, 0x24022001, 0x3c010001, 
-0x10000023, 0xac226f20, 0x3c020080, 0x621024, 
-0x1040001f, 0x3402a001, 0x3c010001, 0x1000001c, 
-0xac226f20, 0x3c020020, 0x2021024, 0x10400007, 
-0x121940, 0x24020100, 0x3c010002, 0x230821, 
-0xac229004, 0x10000006, 0x3c020080, 0x121140, 
-0x3c010002, 0x220821, 0xac209004, 0x3c020080, 
-0x2021024, 0x10400006, 0x121940, 0x3c020001, 
-0x3c010002, 0x230821, 0x10000005, 0xac22900c, 
-0x121140, 0x3c010002, 0x220821, 0xac20900c, 
-0x3c030001, 0x8c636d98, 0x24020001, 0x10620003, 
-0x0, 0xc003daf, 0x0, 0x8fbf0030, 
-0x8fb3002c, 0x8fb20028, 0x8fb10024, 0x8fb00020, 
-0x3e00008, 0x27bd0038, 0x27bdffb0, 0xafb3003c, 
-0x9821, 0xafb50040, 0xa821, 0xafb10034, 
-0x8821, 0x24020002, 0xafbf0048, 0xafbe0044, 
-0xafb20038, 0xafb00030, 0xafa4002c, 0xa7a0001a, 
-0xa7a00018, 0xa7a00020, 0xa7a0001e, 0xa7a00022, 
-0x10a20130, 0xa7a0001c, 0x2ca20003, 0x10400005, 
-0x24020001, 0x10a2000a, 0x3c024000, 0x1000025d, 
-0x2201021, 0x24020004, 0x10a2020a, 0x24020008, 
-0x10a20208, 0x2201021, 0x10000256, 0x0, 
-0x8fa8002c, 0x88140, 0x3c030002, 0x701821, 
-0x8c638ffc, 0x621024, 0x14400009, 0x24040001, 
-0x3c027fff, 0x3442ffff, 0x628824, 0x3c010002, 
-0x300821, 0xac318ff4, 0x10000246, 0x2201021, 
-0x24050001, 0xc00457c, 0x27a60018, 0x24040001, 
-0x24050001, 0xc00457c, 0x27a60018, 0x97a20018, 
-0x30420004, 0x104000d9, 0x3c114000, 0x3c020001, 
-0x8c426f40, 0x2443ffff, 0x2c620006, 0x104000d9, 
-0x31080, 0x3c010001, 0x220821, 0x8c226c68, 
-0x400008, 0x0, 0x24040001, 0x24050011, 
-0x27b0001a, 0xc00457c, 0x2003021, 0x24040001, 
-0x24050011, 0xc00457c, 0x2003021, 0x97a3001a, 
-0x30624000, 0x10400002, 0x3c150010, 0x3c150008, 
-0x30628000, 0x104000aa, 0x3c130001, 0x100000a8, 
-0x3c130002, 0x24040001, 0x24050014, 0x27b0001a, 
-0xc00457c, 0x2003021, 0x24040001, 0x24050014, 
-0xc00457c, 0x2003021, 0x97a3001a, 0x30621000, 
-0x10400002, 0x3c150010, 0x3c150008, 0x30620800, 
-0x10400097, 0x3c130001, 0x10000095, 0x3c130002, 
-0x24040001, 0x24050019, 0x27b0001c, 0xc00457c, 
-0x2003021, 0x24040001, 0x24050019, 0xc00457c, 
-0x2003021, 0x97a2001c, 0x30430700, 0x24020400, 
-0x10620027, 0x28620401, 0x1040000e, 0x24020200, 
-0x1062001f, 0x28620201, 0x10400005, 0x24020100, 
-0x5062001e, 0x3c130001, 0x1000001e, 0x24040001, 
-0x24020300, 0x50620019, 0x3c130002, 0x10000019, 
-0x24040001, 0x24020600, 0x1062000d, 0x28620601, 
-0x10400005, 0x24020500, 0x5062000b, 0x3c130002, 
-0x10000010, 0x24040001, 0x24020700, 0x1462000d, 
-0x24040001, 0x3c130004, 0x1000000a, 0x3c150008, 
-0x10000006, 0x3c130004, 0x10000005, 0x3c150008, 
-0x3c130001, 0x10000002, 0x3c150008, 0x3c150010, 
-0x24040001, 0x24050018, 0x27b0001e, 0xc00457c, 
-0x2003021, 0x24040001, 0x24050018, 0xc00457c, 
-0x2003021, 0x8fa8002c, 0x97a7001e, 0x81140, 
-0x3c060002, 0xc23021, 0x8cc68ff4, 0x97a20022, 
-0x3c100001, 0x26106c5c, 0x2002021, 0xafa20010, 
-0x97a2001c, 0x3c05000c, 0x34a50303, 0xc002b3b, 
-0xafa20014, 0x3c020004, 0x16620010, 0x3c020001, 
-0x8f840054, 0x24030001, 0x24020002, 0x3c010001, 
-0xac236d9c, 0x3c010001, 0xac226d98, 0x3c010001, 
-0xac236da4, 0x3c010001, 0xac236e24, 0x3c010001, 
-0xac246f30, 0x1000004f, 0x2b38825, 0x16620039, 
-0x3c028000, 0x3c020001, 0x8c426e20, 0x1440001e, 
-0x24040018, 0x2021, 0x2821, 0xc004ddb, 
-0x34068000, 0x8f830054, 0x8f820054, 0x2b38825, 
-0x10000002, 0x24630032, 0x8f820054, 0x621023, 
-0x2c420033, 0x1440fffc, 0x0, 0x8f830054, 
-0x24020001, 0x3c010001, 0xac226e20, 0x3c010001, 
-0xac226d9c, 0x3c010001, 0xac226d98, 0x3c010001, 
-0xac226da4, 0x3c010001, 0xac226e24, 0x3c010001, 
-0x1000002c, 0xac236f30, 0x2821, 0xc004ddb, 
-0x24060404, 0x2021, 0x2405001e, 0x27a60018, 
-0x24020002, 0xc0045be, 0xa7a20018, 0x2021, 
-0x2821, 0x27a60018, 0xc0045be, 0xa7a00018, 
-0x24040018, 0x24050002, 0xc004ddb, 0x24060004, 
-0x3c028000, 0x2221025, 0x2b31825, 0x10000015, 
-0x438825, 0x2221025, 0x2751825, 0x438825, 
-0x2002021, 0x97a6001c, 0x3c070001, 0x8ce76d98, 
-0x3c05000c, 0x34a50326, 0xafb30010, 0xc002b3b, 
-0xafb10014, 0x10000007, 0x0, 0x3c110002, 
-0x2308821, 0x8e318ffc, 0x3c027fff, 0x3442ffff, 
-0x2228824, 0x3c020001, 0x8c426da8, 0x1040001e, 
-0x0, 0x3c020001, 0x8c426f1c, 0x10400002, 
-0x3c022000, 0x2228825, 0x8fa8002c, 0x81140, 
-0x3c010002, 0x220821, 0x8c229000, 0x10400003, 
-0x3c020020, 0x10000005, 0x2228825, 0x3c02ffdf, 
-0x3442ffff, 0x2228824, 0x8fa8002c, 0x81140, 
-0x3c010002, 0x220821, 0x8c229008, 0x10400003, 
-0x3c020080, 0x10000004, 0x2228825, 0x3c02ff7f, 
-0x3442ffff, 0x2228824, 0x8fa8002c, 0x81140, 
-0x3c010002, 0x220821, 0xac318ff4, 0x10000135, 
-0x2201021, 0x8fa8002c, 0x8f140, 0x3c030002, 
-0x7e1821, 0x8c638ff8, 0x3c024000, 0x621024, 
-0x14400009, 0x24040001, 0x3c027fff, 0x3442ffff, 
-0x628824, 0x3c010002, 0x3e0821, 0xac318ff0, 
-0x10000124, 0x2201021, 0x2821, 0xc00457c, 
-0x27a60018, 0x24040001, 0x2821, 0xc00457c, 
-0x27a60018, 0x24040001, 0x24050001, 0x27b20020, 
-0xc00457c, 0x2403021, 0x24040001, 0x24050001, 
-0xc00457c, 0x2403021, 0x24040001, 0x24050004, 
-0x27b1001e, 0xc00457c, 0x2203021, 0x24040001, 
-0x24050004, 0xc00457c, 0x2203021, 0x24040001, 
-0x24050005, 0x27b00022, 0xc00457c, 0x2003021, 
-0x24040001, 0x24050005, 0xc00457c, 0x2003021, 
-0x24040001, 0x24050010, 0xc00457c, 0x27a60018, 
-0x24040001, 0x24050010, 0xc00457c, 0x27a60018, 
-0x24040001, 0x2405000a, 0xc00457c, 0x2403021, 
-0x24040001, 0x2405000a, 0xc00457c, 0x2403021, 
-0x24040001, 0x24050018, 0xc00457c, 0x2203021, 
-0x24040001, 0x24050018, 0xc00457c, 0x2203021, 
-0x24040001, 0x24050001, 0xc00457c, 0x27a60018, 
-0x24040001, 0x24050001, 0xc00457c, 0x27a60018, 
-0x97a20018, 0x30420004, 0x10400066, 0x3c114000, 
-0x3c030001, 0x8c636f34, 0x24020005, 0x14620067, 
-0x24040001, 0x24050019, 0x27b0001c, 0xc00457c, 
-0x2003021, 0x24040001, 0x24050019, 0xc00457c, 
-0x2003021, 0x97a2001c, 0x30430700, 0x24020400, 
-0x10620027, 0x28620401, 0x1040000e, 0x24020200, 
-0x1062001f, 0x28620201, 0x10400005, 0x24020100, 
-0x5062001e, 0x3c130001, 0x1000001e, 0x3c020004, 
-0x24020300, 0x50620019, 0x3c130002, 0x10000019, 
-0x3c020004, 0x24020600, 0x1062000d, 0x28620601, 
-0x10400005, 0x24020500, 0x5062000b, 0x3c130002, 
-0x10000010, 0x3c020004, 0x24020700, 0x1462000d, 
-0x3c020004, 0x3c130004, 0x1000000a, 0x3c150008, 
-0x10000006, 0x3c130004, 0x10000005, 0x3c150008, 
-0x3c130001, 0x10000002, 0x3c150008, 0x3c150010, 
-0x3c020004, 0x12620017, 0x3c028000, 0x8f820054, 
-0x24100001, 0x3c010001, 0xac306d9c, 0x3c010001, 
-0xac306d98, 0x3c010001, 0xac306da4, 0x3c010001, 
-0xac306e24, 0x3c010001, 0xac226f30, 0x3c020001, 
-0x16620022, 0x2758825, 0x2021, 0x2821, 
-0xc004ddb, 0x34068000, 0x3c010001, 0x1000001b, 
-0xac306e20, 0x2221025, 0x2b31825, 0x438825, 
-0x97a6001c, 0x3c020001, 0x8c426f1c, 0x3c070001, 
-0x8ce76d98, 0x3c040001, 0x24846c5c, 0xafa20010, 
-0x97a2001e, 0x3c05000c, 0x34a50323, 0x3c010001, 
-0xac206e20, 0xc002b3b, 0xafa20014, 0x10000007, 
-0x0, 0x3c110002, 0x23e8821, 0x8e318ff0, 
-0x3c027fff, 0x3442ffff, 0x2228824, 0x3c020001, 
-0x8c426da8, 0x10400069, 0x0, 0x3c020001, 
-0x8c426f1c, 0x10400002, 0x3c022000, 0x2228825, 
-0x8fa8002c, 0x81140, 0x3c010002, 0x220821, 
-0x8c229004, 0x10400003, 0x3c020020, 0x10000005, 
-0x2228825, 0x3c02ffdf, 0x3442ffff, 0x2228824, 
-0x8fa8002c, 0x81140, 0x3c010002, 0x220821, 
-0x8c22900c, 0x10400003, 0x3c020080, 0x1000004f, 
-0x2228825, 0x3c02ff7f, 0x3442ffff, 0x1000004b, 
-0x2228824, 0x8fa8002c, 0x82940, 0x3c030002, 
-0x651821, 0x8c638ff8, 0x3c024000, 0x621024, 
-0x14400008, 0x3c027fff, 0x3442ffff, 0x628824, 
-0x3c010002, 0x250821, 0xac318ff0, 0x10000041, 
-0x2201021, 0x3c020001, 0x8c426da8, 0x10400034, 
-0x3c11c00c, 0x3c020001, 0x8c426e44, 0x3c04c00c, 
-0x34842000, 0x3c030001, 0x8c636f1c, 0x2102b, 
-0x21023, 0x441024, 0x10600003, 0x518825, 
-0x3c022000, 0x2228825, 0x3c020002, 0x451021, 
-0x8c429004, 0x10400003, 0x3c020020, 0x10000004, 
-0x2228825, 0x3c02ffdf, 0x3442ffff, 0x2228824, 
-0x8fa8002c, 0x81140, 0x3c010002, 0x220821, 
-0x8c22900c, 0x10400003, 0x3c020080, 0x10000004, 
-0x2228825, 0x3c02ff7f, 0x3442ffff, 0x2228824, 
-0x3c020001, 0x8c426e30, 0x10400002, 0x3c020800, 
-0x2228825, 0x3c020001, 0x8c426e34, 0x10400002, 
-0x3c020400, 0x2228825, 0x3c020001, 0x8c426e38, 
-0x10400006, 0x3c020100, 0x10000004, 0x2228825, 
-0x3c027fff, 0x3442ffff, 0x628824, 0x8fa8002c, 
-0x81140, 0x3c010002, 0x220821, 0xac318ff0, 
-0x2201021, 0x8fbf0048, 0x8fbe0044, 0x8fb50040, 
-0x8fb3003c, 0x8fb20038, 0x8fb10034, 0x8fb00030, 
-0x3e00008, 0x27bd0050, 0x27bdffd0, 0xafb20028, 
-0x809021, 0xafbf002c, 0xafb10024, 0xafb00020, 
-0x8f840200, 0x3c100001, 0x8e106d98, 0x8f860220, 
-0x24020002, 0x1202005c, 0x2e020003, 0x10400005, 
-0x24020001, 0x1202000a, 0x121940, 0x1000010c, 
-0x0, 0x24020004, 0x120200bf, 0x24020008, 
-0x120200be, 0x128940, 0x10000105, 0x0, 
-0x3c050002, 0xa32821, 0x8ca58ffc, 0x3c100002, 
-0x2038021, 0x8e108ff4, 0x3c024000, 0xa21024, 
-0x10400038, 0x3c020008, 0x2021024, 0x10400020, 
-0x34840002, 0x3c020002, 0x431021, 0x8c429000, 
-0x10400005, 0x34840020, 0x34840100, 0x3c020020, 
-0x10000006, 0x2028025, 0x2402feff, 0x822024, 
-0x3c02ffdf, 0x3442ffff, 0x2028024, 0x121140, 
-0x3c010002, 0x220821, 0x8c229008, 0x10400005, 
-0x3c020001, 0xc23025, 0x3c020080, 0x10000016, 
-0x2028025, 0x3c02fffe, 0x3442ffff, 0xc23024, 
-0x3c02ff7f, 0x3442ffff, 0x1000000f, 0x2028024, 
-0x2402fedf, 0x822024, 0x3c02fffe, 0x3442ffff, 
-0xc23024, 0x3c02ff5f, 0x3442ffff, 0x2028024, 
-0x3c010002, 0x230821, 0xac209000, 0x3c010002, 
-0x230821, 0xac209008, 0xaf840200, 0xaf860220, 
-0x8f820220, 0x34420002, 0xaf820220, 0x1000000a, 
-0x121140, 0x3c02bfff, 0x3442ffff, 0x8f830200, 
-0x2028024, 0x2402fffd, 0x621824, 0xc003daf, 
-0xaf830200, 0x121140, 0x3c010002, 0x220821, 
-0x100000b7, 0xac308ff4, 0x3c020001, 0x8c426f1c, 
-0x10400069, 0x24050004, 0x24040001, 0xc00457c, 
-0x27a60018, 0x24040001, 0x24050005, 0xc00457c, 
-0x27a6001a, 0x97a30018, 0x97a2001a, 0x3c040001, 
-0x24846e48, 0x30630c00, 0x31a82, 0x30420c00, 
-0x21282, 0xa7a2001a, 0x21080, 0x441021, 
-0x431021, 0xa7a30018, 0x90480000, 0x24020001, 
-0x3103ffff, 0x10620029, 0x28620002, 0x10400005, 
-0x0, 0x10600009, 0x0, 0x1000003d, 
-0x0, 0x10700013, 0x24020003, 0x1062002c, 
-0x0, 0x10000037, 0x0, 0x8f820200, 
-0x2403feff, 0x431024, 0xaf820200, 0x8f820220, 
-0x3c03fffe, 0x3463ffff, 0x431024, 0xaf820220, 
-0x3c010002, 0xac209004, 0x3c010002, 0x10000032, 
-0xac20900c, 0x8f820200, 0x34420100, 0xaf820200, 
-0x8f820220, 0x3c03fffe, 0x3463ffff, 0x431024, 
-0xaf820220, 0x24020100, 0x3c010002, 0xac229004, 
-0x3c010002, 0x10000024, 0xac20900c, 0x8f820200, 
-0x2403feff, 0x431024, 0xaf820200, 0x8f820220, 
-0x3c030001, 0x431025, 0xaf820220, 0x3c010002, 
-0xac209004, 0x3c010002, 0x10000017, 0xac23900c, 
-0x8f820200, 0x34420100, 0xaf820200, 0x8f820220, 
-0x3c030001, 0x431025, 0xaf820220, 0x24020100, 
-0x3c010002, 0xac229004, 0x3c010002, 0x1000000a, 
-0xac23900c, 0x3c040001, 0x24846c80, 0x97a6001a, 
-0x97a70018, 0x3c050001, 0x34a5ffff, 0xafa80010, 
-0xc002b3b, 0xafa00014, 0x8f820200, 0x34420002, 
-0x1000004b, 0xaf820200, 0x128940, 0x3c050002, 
-0xb12821, 0x8ca58ff8, 0x3c100002, 0x2118021, 
-0x8e108ff0, 0x3c024000, 0xa21024, 0x14400010, 
-0x0, 0x3c020001, 0x8c426f1c, 0x14400005, 
-0x3c02bfff, 0x8f820200, 0x34420002, 0xaf820200, 
-0x3c02bfff, 0x3442ffff, 0xc003daf, 0x2028024, 
-0x3c010002, 0x310821, 0x10000031, 0xac308ff0, 
-0x3c020001, 0x8c426f1c, 0x10400005, 0x3c020020, 
-0x3c020001, 0x8c426e44, 0x10400025, 0x3c020020, 
-0xa21024, 0x10400007, 0x34840020, 0x24020100, 
-0x3c010002, 0x310821, 0xac229004, 0x10000006, 
-0x34840100, 0x3c010002, 0x310821, 0xac209004, 
-0x2402feff, 0x822024, 0x3c020080, 0xa21024, 
-0x10400007, 0x121940, 0x3c020001, 0x3c010002, 
-0x230821, 0xac22900c, 0x10000008, 0xc23025, 
-0x121140, 0x3c010002, 0x220821, 0xac20900c, 
-0x3c02fffe, 0x3442ffff, 0xc23024, 0xaf840200, 
-0xaf860220, 0x8f820220, 0x34420002, 0xaf820220, 
-0x121140, 0x3c010002, 0x220821, 0xac308ff0, 
-0x8fbf002c, 0x8fb20028, 0x8fb10024, 0x8fb00020, 
-0x3e00008, 0x27bd0030, 0x0, 0x1821, 
-0x308400ff, 0x2405ffdf, 0x2406ffbf, 0x641007, 
-0x30420001, 0x10400004, 0x0, 0x8f820044, 
-0x10000003, 0x34420040, 0x8f820044, 0x461024, 
-0xaf820044, 0x8f820044, 0x34420020, 0xaf820044, 
-0x8f820044, 0x451024, 0xaf820044, 0x24630001, 
-0x28620008, 0x5440ffee, 0x641007, 0x3e00008, 
-0x0, 0x2c820008, 0x1040001b, 0x0, 
-0x2405ffdf, 0x2406ffbf, 0x41880, 0x3c020001, 
-0x24426e60, 0x621821, 0x24640004, 0x90620000, 
-0x10400004, 0x0, 0x8f820044, 0x10000003, 
-0x34420040, 0x8f820044, 0x461024, 0xaf820044, 
-0x8f820044, 0x34420020, 0xaf820044, 0x8f820044, 
-0x451024, 0xaf820044, 0x24630001, 0x64102b, 
-0x1440ffee, 0x0, 0x3e00008, 0x0, 
-0x0, 0x0, 0x0, 0x8f8400c4, 
-0x8f8600e0, 0x8f8700e4, 0x2402fff8, 0xc22824, 
-0x10e5001a, 0x27623ff8, 0x14e20002, 0x24e80008, 
-0x27683000, 0x55050004, 0x8d0a0000, 0x30c20004, 
-0x14400012, 0x805021, 0x8ce90000, 0x8f42013c, 
-0x1494823, 0x49182b, 0x94eb0006, 0x10600002, 
-0x25630050, 0x494821, 0x123182b, 0x50400003, 
-0x8f4201fc, 0x3e00008, 0xe01021, 0xaf8800e8, 
-0x24420001, 0xaf4201fc, 0xaf8800e4, 0x3e00008, 
-0x1021, 0x3e00008, 0x0, 0x8f8300e4, 
-0x27623ff8, 0x10620004, 0x24620008, 0xaf8200e8, 
-0x3e00008, 0xaf8200e4, 0x27623000, 0xaf8200e8, 
-0x3e00008, 0xaf8200e4, 0x3e00008, 0x0, 
-0x0, 0x0, 0x0, 0x8f880120, 
-0x27624fe0, 0x8f830128, 0x15020002, 0x25090020, 
-0x27694800, 0x11230012, 0x8fa20010, 0xad040000, 
-0xad050004, 0xad060008, 0xa507000e, 0x8fa30014, 
-0xad020018, 0x8fa20018, 0xad03001c, 0x25030016, 
-0xad020010, 0xad030014, 0xaf890120, 0x8f4300fc, 
-0x24020001, 0x2463ffff, 0x3e00008, 0xaf4300fc, 
-0x8f430324, 0x1021, 0x24630001, 0x3e00008, 
-0xaf430324, 0x3e00008, 0x0, 0x8f880100, 
-0x276247e0, 0x8f830108, 0x15020002, 0x25090020, 
-0x27694000, 0x1123000f, 0x8fa20010, 0xad040000, 
-0xad050004, 0xad060008, 0xa507000e, 0x8fa30014, 
-0xad020018, 0x8fa20018, 0xad03001c, 0x25030016, 
-0xad020010, 0xad030014, 0xaf890100, 0x3e00008, 
-0x24020001, 0x8f430328, 0x1021, 0x24630001, 
-0x3e00008, 0xaf430328, 0x3e00008, 0x0, 
-0x0, 0x0, 0x0, 0x0 };
-static int tigon2FwRodata[/*(MAX_RODATA_LEN/4) + 1*/] = {
-0x24486561, 0x6465723a, 0x202f7072, 
-0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765, 
-0x2f2e2f6e, 0x69632f66, 0x77322f63, 0x6f6d6d6f, 
-0x6e2f6677, 0x6d61696e, 0x2e632c76, 0x20312e31, 
-0x2e322e34, 0x35203139, 0x39392f30, 0x312f3234, 
-0x2030303a, 0x31303a35, 0x35207368, 0x75616e67, 
-0x20457870, 0x20240000, 0x65767452, 0x6e674600, 
-0x51657674, 0x46000000, 0x51657674, 0x505f4600, 
-0x4d657674, 0x526e6746, 0x0, 0x4d516576, 
-0x74460000, 0x4d516576, 0x505f4600, 0x5173436f, 
-0x6e495f46, 0x0, 0x5173436f, 0x6e734600, 
-0x51725072, 0x6f644600, 0x6261644d, 0x656d537a, 
-0x0, 0x68775665, 0x72000000, 0x62616448, 
-0x77566572, 0x0, 0x2a2a4441, 0x574e5f41, 
-0x0, 0x74785278, 0x4266537a, 0x0, 
-0x62664174, 0x6e4d726b, 0x0, 0x7265645a, 
-0x6f6e6531, 0x0, 0x70636943, 0x6f6e6600, 
-0x67656e43, 0x6f6e6600, 0x2a646d61, 0x5244666c, 
-0x0, 0x2a50414e, 0x49432a00, 0x2e2e2f2e, 
-0x2e2f2e2e, 0x2f2e2e2f, 0x2e2e2f73, 0x72632f6e, 
-0x69632f66, 0x77322f63, 0x6f6d6d6f, 0x6e2f6677, 
-0x6d61696e, 0x2e630000, 0x72636246, 0x6c616773, 
-0x0, 0x62616452, 0x78526362, 0x0, 
-0x676c6f62, 0x466c6773, 0x0, 0x2b5f6469, 
-0x73705f6c, 0x6f6f7000, 0x2b65765f, 0x68616e64, 
-0x6c657200, 0x63616e74, 0x31446d61, 0x0, 
-0x2b715f64, 0x6d615f74, 0x6f5f6e69, 0x635f636b, 
-0x73756d00, 0x2b685f73, 0x656e645f, 0x64617461, 
-0x5f726561, 0x64795f63, 0x6b73756d, 0x0, 
-0x2b685f64, 0x6d615f72, 0x645f6173, 0x73697374, 
-0x5f636b73, 0x756d0000, 0x74436b73, 0x6d4f6e00, 
-0x2b715f64, 0x6d615f74, 0x6f5f6e69, 0x63000000, 
-0x2b685f73, 0x656e645f, 0x64617461, 0x5f726561, 
-0x64790000, 0x2b685f64, 0x6d615f72, 0x645f6173, 
-0x73697374, 0x0, 0x74436b73, 0x6d4f6666, 
-0x0, 0x2b685f73, 0x656e645f, 0x62645f72, 
-0x65616479, 0x0, 0x68737453, 0x52696e67, 
-0x0, 0x62616453, 0x52696e67, 0x0, 
-0x6e696353, 0x52696e67, 0x0, 0x77446d61, 
-0x416c6c41, 0x0, 0x2b715f64, 0x6d615f74, 
-0x6f5f686f, 0x73745f63, 0x6b73756d, 0x0, 
-0x2b685f6d, 0x61635f72, 0x785f636f, 0x6d705f63, 
-0x6b73756d, 0x0, 0x2b685f64, 0x6d615f77, 
-0x725f6173, 0x73697374, 0x5f636b73, 0x756d0000, 
-0x72436b73, 0x6d4f6e00, 0x2b715f64, 0x6d615f74, 
-0x6f5f686f, 0x73740000, 0x2b685f6d, 0x61635f72, 
-0x785f636f, 0x6d700000, 0x2b685f64, 0x6d615f77, 
-0x725f6173, 0x73697374, 0x0, 0x72436b73, 
-0x6d4f6666, 0x0, 0x2b685f72, 0x6563765f, 
-0x62645f72, 0x65616479, 0x0, 0x2b685f72, 
-0x6563765f, 0x6a756d62, 0x6f5f6264, 0x5f726561, 
-0x64790000, 0x2b685f72, 0x6563765f, 0x6d696e69, 
-0x5f62645f, 0x72656164, 0x79000000, 0x2b6d685f, 
-0x636f6d6d, 0x616e6400, 0x2b685f74, 0x696d6572, 
-0x0, 0x2b685f64, 0x6f5f7570, 0x64617465, 
-0x5f74785f, 0x636f6e73, 0x0, 0x2b685f64, 
-0x6f5f7570, 0x64617465, 0x5f72785f, 0x70726f64, 
-0x0, 0x2b636b73, 0x756d3136, 0x0, 
-0x2b706565, 0x6b5f6d61, 0x635f7278, 0x5f776100, 
-0x2b706565, 0x6b5f6d61, 0x635f7278, 0x0, 
-0x2b646571, 0x5f6d6163, 0x5f727800, 0x2b685f6d, 
-0x61635f72, 0x785f6174, 0x746e0000, 0x62616452, 
-0x6574537a, 0x0, 0x72784264, 0x4266537a, 
-0x0, 0x2b6e756c, 0x6c5f6861, 0x6e646c65, 
-0x72000000, 0x66774f70, 0x4661696c, 0x0, 
-0x2b685f75, 0x70646174, 0x655f6c65, 0x64340000, 
-0x2b685f75, 0x70646174, 0x655f6c65, 0x64360000, 
-0x2b685f75, 0x70646174, 0x655f6c65, 0x64320000, 
-0x696e7453, 0x74617465, 0x0, 0x2a2a696e, 
-0x69744370, 0x0, 0x23736372, 0x65616d00, 
-0x69537461, 0x636b4572, 0x0, 0x70726f62, 
-0x654d656d, 0x0, 0x2a2a4441, 0x574e5f42, 
-0x0, 0x2b73775f, 0x646d615f, 0x61737369, 
-0x73745f70, 0x6c75735f, 0x74696d65, 0x72000000, 
-0x2b267072, 0x656c6f61, 0x645f7772, 0x5f646573, 
-0x63720000, 0x2b267072, 0x656c6f61, 0x645f7264, 
-0x5f646573, 0x63720000, 0x2b685f68, 0x665f7469, 
-0x6d657200, 0x24486561, 0x6465723a, 0x202f7072, 
-0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765, 
-0x2f2e2f6e, 0x69632f66, 0x77322f63, 0x6f6d6d6f, 
-0x6e2f7469, 0x6d65722e, 0x632c7620, 0x312e312e, 
-0x322e3335, 0x20313939, 0x392f3031, 0x2f323720, 
-0x31393a30, 0x393a3530, 0x20686179, 0x65732045, 
-0x78702024, 0x0, 0x65767452, 0x6e674600, 
-0x51657674, 0x46000000, 0x51657674, 0x505f4600, 
-0x4d657674, 0x526e6746, 0x0, 0x4d516576, 
-0x74460000, 0x4d516576, 0x505f4600, 0x5173436f, 
-0x6e495f46, 0x0, 0x5173436f, 0x6e734600, 
-0x51725072, 0x6f644600, 0x542d446d, 0x61526432, 
-0x0, 0x542d446d, 0x61526431, 0x0, 
-0x542d446d, 0x61526442, 0x0, 0x542d446d, 
-0x61577232, 0x0, 0x542d446d, 0x61577231, 
-0x0, 0x542d446d, 0x61577242, 0x0, 
-0x0, 0x24486561, 0x6465723a, 0x202f7072, 
-0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765, 
-0x2f2e2f6e, 0x69632f66, 0x77322f63, 0x6f6d6d6f, 
-0x6e2f636f, 0x6d6d616e, 0x642e632c, 0x7620312e, 
-0x312e322e, 0x32382031, 0x3939392f, 0x30312f32, 
-0x30203139, 0x3a34393a, 0x34392073, 0x6875616e, 
-0x67204578, 0x70202400, 0x65767452, 0x6e674600, 
-0x51657674, 0x46000000, 0x51657674, 0x505f4600, 
-0x4d657674, 0x526e6746, 0x0, 0x4d516576, 
-0x74460000, 0x4d516576, 0x505f4600, 0x5173436f, 
-0x6e495f46, 0x0, 0x5173436f, 0x6e734600, 
-0x51725072, 0x6f644600, 0x3f48636d, 0x644d6278, 
-0x0, 0x3f636d64, 0x48737453, 0x0, 
-0x3f636d64, 0x4d634d64, 0x0, 0x3f636d64, 
-0x50726f6d, 0x0, 0x3f636d64, 0x4c696e6b, 
-0x0, 0x3f636d64, 0x45727200, 0x86ac, 
-0x8e5c, 0x8e5c, 0x8de4, 0x8b78, 
-0x8e30, 0x8e5c, 0x8790, 0x8800, 
-0x8990, 0x8a68, 0x8a34, 0x8e5c, 
-0x8870, 0x8b24, 0x8e5c, 0x8b34, 
-0x87b4, 0x8824, 0x0, 0x0, 
-0x0, 0x24486561, 0x6465723a, 0x202f7072, 
-0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765, 
-0x2f2e2f6e, 0x69632f66, 0x77322f63, 0x6f6d6d6f, 
-0x6e2f6d63, 0x6173742e, 0x632c7620, 0x312e312e, 
-0x322e3820, 0x31393938, 0x2f31322f, 0x30382030, 
-0x323a3336, 0x3a333620, 0x73687561, 0x6e672045, 
-0x78702024, 0x0, 0x65767452, 0x6e674600, 
-0x51657674, 0x46000000, 0x51657674, 0x505f4600, 
-0x4d657674, 0x526e6746, 0x0, 0x4d516576, 
-0x74460000, 0x4d516576, 0x505f4600, 0x5173436f, 
-0x6e495f46, 0x0, 0x5173436f, 0x6e734600, 
-0x51725072, 0x6f644600, 0x6164644d, 0x63447570, 
-0x0, 0x6164644d, 0x6346756c, 0x0, 
-0x64656c4d, 0x634e6f45, 0x0, 0x0, 
-0x0, 0x24486561, 0x6465723a, 0x202f7072, 
-0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765, 
-0x2f2e2f6e, 0x69632f66, 0x77322f63, 0x6f6d6d6f, 
-0x6e2f646d, 0x612e632c, 0x7620312e, 0x312e322e, 
-0x32342031, 0x3939382f, 0x31322f32, 0x31203030, 
-0x3a33333a, 0x30392073, 0x6875616e, 0x67204578, 
-0x70202400, 0x65767452, 0x6e674600, 0x51657674, 
-0x46000000, 0x51657674, 0x505f4600, 0x4d657674, 
-0x526e6746, 0x0, 0x4d516576, 0x74460000, 
-0x4d516576, 0x505f4600, 0x5173436f, 0x6e495f46, 
-0x0, 0x5173436f, 0x6e734600, 0x51725072, 
-0x6f644600, 0x7377446d, 0x614f6666, 0x0, 
-0x31446d61, 0x4f6e0000, 0x7377446d, 0x614f6e00, 
-0x2372446d, 0x6141544e, 0x0, 0x72446d61, 
-0x41544e30, 0x0, 0x72446d61, 0x41544e31, 
-0x0, 0x72446d61, 0x34476200, 0x2a50414e, 
-0x49432a00, 0x2e2e2f2e, 0x2e2f2e2e, 0x2f2e2e2f, 
-0x2e2e2f73, 0x72632f6e, 0x69632f66, 0x77322f63, 
-0x6f6d6d6f, 0x6e2f646d, 0x612e6300, 0x2377446d, 
-0x6141544e, 0x0, 0x77446d61, 0x41544e30, 
-0x0, 0x77446d61, 0x41544e31, 0x0, 
-0x77446d61, 0x34476200, 0x0, 0x0, 
-0x0, 0x24486561, 0x6465723a, 0x202f7072, 
-0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765, 
-0x2f2e2f6e, 0x69632f66, 0x77322f63, 0x6f6d6d6f, 
-0x6e2f7472, 0x6163652e, 0x632c7620, 0x312e312e, 
-0x322e3520, 0x31393938, 0x2f30392f, 0x33302031, 
-0x383a3530, 0x3a323820, 0x73687561, 0x6e672045, 
-0x78702024, 0x0, 0x0, 0x0, 
-0x0, 0x24486561, 0x6465723a, 0x202f7072, 
-0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765, 
-0x2f2e2f6e, 0x69632f66, 0x77322f63, 0x6f6d6d6f, 
-0x6e2f6461, 0x74612e63, 0x2c762031, 0x2e312e32, 
-0x2e313220, 0x31393939, 0x2f30312f, 0x32302031, 
-0x393a3439, 0x3a353120, 0x73687561, 0x6e672045, 
-0x78702024, 0x0, 0x46575f56, 0x45525349, 
-0x4f4e3a20, 0x23312046, 0x72692041, 0x70722037, 
-0x2031373a, 0x35373a35, 0x32205044, 0x54203230, 
-0x30300000, 0x46575f43, 0x4f4d5049, 0x4c455f54, 
-0x494d453a, 0x2031373a, 0x35373a35, 0x32000000, 
-0x46575f43, 0x4f4d5049, 0x4c455f42, 0x593a2064, 
-0x65767263, 0x73000000, 0x46575f43, 0x4f4d5049, 
-0x4c455f48, 0x4f53543a, 0x20636f6d, 0x70757465, 
-0x0, 0x46575f43, 0x4f4d5049, 0x4c455f44, 
-0x4f4d4149, 0x4e3a2065, 0x6e672e61, 0x6374656f, 
-0x6e2e636f, 0x6d000000, 0x46575f43, 0x4f4d5049, 
-0x4c45523a, 0x20676363, 0x20766572, 0x73696f6e, 
-0x20322e37, 0x2e320000, 0x0, 0x12041100, 
-0x0, 0x24486561, 0x6465723a, 0x202f7072, 
-0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765, 
-0x2f2e2f6e, 0x69632f66, 0x77322f63, 0x6f6d6d6f, 
-0x6e2f6d65, 0x6d2e632c, 0x7620312e, 0x312e322e, 
-0x35203139, 0x39382f30, 0x392f3330, 0x2031383a, 
-0x35303a30, 0x38207368, 0x75616e67, 0x20457870, 
-0x20240000, 0x24486561, 0x6465723a, 0x202f7072, 
-0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765, 
-0x2f2e2f6e, 0x69632f66, 0x77322f63, 0x6f6d6d6f, 
-0x6e2f7365, 0x6e642e63, 0x2c762031, 0x2e312e32, 
-0x2e343420, 0x31393938, 0x2f31322f, 0x32312030, 
-0x303a3333, 0x3a313820, 0x73687561, 0x6e672045, 
-0x78702024, 0x0, 0x65767452, 0x6e674600, 
-0x51657674, 0x46000000, 0x51657674, 0x505f4600, 
-0x4d657674, 0x526e6746, 0x0, 0x4d516576, 
-0x74460000, 0x4d516576, 0x505f4600, 0x5173436f, 
-0x6e495f46, 0x0, 0x5173436f, 0x6e734600, 
-0x51725072, 0x6f644600, 0x69736e74, 0x54637055, 
-0x0, 0x24486561, 0x6465723a, 0x202f7072, 
-0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765, 
-0x2f2e2f6e, 0x69632f66, 0x77322f63, 0x6f6d6d6f, 
-0x6e2f7265, 0x63762e63, 0x2c762031, 0x2e312e32, 
-0x2e353320, 0x31393939, 0x2f30312f, 0x31362030, 
-0x323a3535, 0x3a343320, 0x73687561, 0x6e672045, 
-0x78702024, 0x0, 0x65767452, 0x6e674600, 
-0x51657674, 0x46000000, 0x51657674, 0x505f4600, 
-0x4d657674, 0x526e6746, 0x0, 0x4d516576, 
-0x74460000, 0x4d516576, 0x505f4600, 0x5173436f, 
-0x6e495f46, 0x0, 0x5173436f, 0x6e734600, 
-0x51725072, 0x6f644600, 0x724d6163, 0x43686b30, 
-0x0, 0x72784672, 0x6d324c67, 0x0, 
-0x72784e6f, 0x53744264, 0x0, 0x72784e6f, 
-0x4d694264, 0x0, 0x72784e6f, 0x4a6d4264, 
-0x0, 0x7278436b, 0x446d6146, 0x0, 
-0x72785144, 0x6d457846, 0x0, 0x72785144, 
-0x6d614600, 0x72785144, 0x4c426446, 0x0, 
-0x72785144, 0x6d426446, 0x0, 0x72784372, 
-0x63506164, 0x0, 0x72536d51, 0x446d6146, 
-0x0, 0x24486561, 0x6465723a, 0x202f7072, 
-0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765, 
-0x2f2e2f6e, 0x69632f66, 0x77322f63, 0x6f6d6d6f, 
-0x6e2f6d61, 0x632e632c, 0x7620312e, 0x312e322e, 
-0x32322031, 0x3939382f, 0x31322f30, 0x38203032, 
-0x3a33363a, 0x33302073, 0x6875616e, 0x67204578, 
-0x70202400, 0x65767452, 0x6e674600, 0x51657674, 
-0x46000000, 0x51657674, 0x505f4600, 0x4d657674, 
-0x526e6746, 0x0, 0x4d516576, 0x74460000, 
-0x4d516576, 0x505f4600, 0x5173436f, 0x6e495f46, 
-0x0, 0x5173436f, 0x6e734600, 0x51725072, 
-0x6f644600, 0x6d616354, 0x68726573, 0x0, 
-0x23744d61, 0x6341544e, 0x0, 0x23724d61, 
-0x6341544e, 0x0, 0x72656d41, 0x73737274, 
-0x0, 0x6c696e6b, 0x444f574e, 0x0, 
-0x6c696e6b, 0x55500000, 0x0, 0x0, 
-0x0, 0x24486561, 0x6465723a, 0x202f7072, 
-0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765, 
-0x2f2e2f6e, 0x69632f66, 0x77322f63, 0x6f6d6d6f, 
-0x6e2f636b, 0x73756d2e, 0x632c7620, 0x312e312e, 
-0x322e3920, 0x31393939, 0x2f30312f, 0x31342030, 
-0x303a3033, 0x3a343820, 0x73687561, 0x6e672045, 
-0x78702024, 0x0, 0x65767452, 0x6e674600, 
-0x51657674, 0x46000000, 0x51657674, 0x505f4600, 
-0x4d657674, 0x526e6746, 0x0, 0x4d516576, 
-0x74460000, 0x4d516576, 0x505f4600, 0x5173436f, 
-0x6e495f46, 0x0, 0x5173436f, 0x6e734600, 
-0x51725072, 0x6f644600, 0x0, 0x0, 
-0x0, 0x50726f62, 0x65506879, 0x0, 
-0x6c6e6b41, 0x53535254, 0x0, 0x109a4, 
-0x10a1c, 0x10a50, 0x10a7c, 0x11050, 
-0x10aa8, 0x10b10, 0x111fc, 0x10dc0, 
-0x10c68, 0x10c80, 0x10cc4, 0x10cec, 
-0x10d0c, 0x10d34, 0x111fc, 0x10dc0, 
-0x10df8, 0x10e10, 0x10e40, 0x10e68, 
-0x10e88, 0x10eb0, 0x0, 0x10fdc, 
-0x11008, 0x1102c, 0x111fc, 0x11050, 
-0x11078, 0x11108, 0x0, 0x0, 
-0x0, 0x1186c, 0x1193c, 0x11a14, 
-0x11ae4, 0x11b40, 0x11c1c, 0x11c44, 
-0x11d20, 0x11d48, 0x11ef0, 0x11f18, 
-0x120c0, 0x122b8, 0x1254c, 0x12460, 
-0x1254c, 0x12578, 0x120e8, 0x12290, 
-0x7273745f, 0x676d6969, 0x0, 0x12608, 
-0x12640, 0x12728, 0x13374, 0x133b4, 
-0x133cc, 0x7365746c, 0x6f6f7000, 0x0, 
-0x0, 0x13bbc, 0x13bfc, 0x13c8c, 
-0x13cd0, 0x13d34, 0x13dc0, 0x13df4, 
-0x13e7c, 0x13f14, 0x13fe4, 0x14024, 
-0x140a8, 0x140cc, 0x141dc, 0x646f4261, 
-0x73655067, 0x0, 0x0, 0x0, 
-0x0, 0x73746d61, 0x634c4e4b, 0x0, 
-0x6765746d, 0x636c6e6b, 0x0, 0x14ed8, 
-0x14ed8, 0x14b8c, 0x14bd8, 0x14c24, 
-0x14ed8, 0x7365746d, 0x61636163, 0x74000000, 
-0x0, 0x0 };
-static int tigon2FwData[/*(MAX_DATA_LEN/4) + 1*/] = {
-0x1, 
-0x1, 0x1, 0xc001fc, 0x3ffc, 
-0xc00000, 0x416c7465, 0x6f6e2041, 0x63654e49, 
-0x43205600, 0x0, 0x0, 0x0, 
-0x0, 0x0, 0x0, 0x416c7465, 
-0x6f6e2041, 0x63654e49, 0x43205600, 0x42424242, 
-0x0, 0x0, 0x0, 0x1ffffc, 
-0x1fff7c, 0x0, 0x0, 0x0, 
-0x0, 0x0, 0x0, 0x60cf00, 
-0x60, 0xcf000000, 0x0, 0x0, 
-0x0, 0x0, 0x0, 0x0, 
-0x0, 0x0, 0x0, 0x0, 
-0x0, 0x0, 0x0, 0x0, 
-0x0, 0x0, 0x0, 0x0, 
-0x0, 0x0, 0x3, 0x0, 
-0x1, 0x0, 0x0, 0x0, 
-0x1, 0x0, 0x1, 0x0, 
-0x0, 0x0, 0x0, 0x1, 
-0x1, 0x0, 0x0, 0x0, 
-0x0, 0x0, 0x1000000, 0x21000000, 
-0x12000140, 0x0, 0x0, 0x20000000, 
-0x120000a0, 0x0, 0x12000060, 0x12000180, 
-0x120001e0, 0x0, 0x0, 0x0, 
-0x1, 0x0, 0x0, 0x0, 
-0x0, 0x0, 0x0, 0x2, 
-0x0, 0x0, 0x30001, 0x1, 
-0x30201, 0x0, 0x0, 0x1010101, 
-0x1010100, 0x10100, 0x1010001, 0x10001, 
-0x1000101, 0x101, 0x0, 0x0 };
--- a/os/boot/pc/etherif.h
+++ /dev/null
@@ -1,47 +1,0 @@
-typedef struct RingBuf {
-	uchar	owner;
-	uchar	unused;
-	ushort	len;
-	uchar	pkt[sizeof(Etherpkt)];
-} RingBuf;
-
-enum {
-	Host		= 0,		/* buffer owned by host */
-	Interface	= 1,		/* buffer owned by card */
-
-	Nrb		= 32,		/* default number of receive buffers */
-	Ntb		= 8,		/* default number of transmit buffers */
-};
-
-typedef struct Ether Ether;
-struct Ether {
-	ISAConf;			/* hardware info */
-	int	ctlrno;
-	int	state;			/* 0: unfound, 1: found, 2: attaching */
-	int	tbdf;
-
-	void	(*attach)(Ether*);	/* filled in by reset routine */
-	void	(*transmit)(Ether*);
-	void	(*interrupt)(Ureg*, void*);
-	void	(*detach)(Ether*);
-	void	*ctlr;
-
-	ushort	nrb;			/* number of software receive buffers */
-	ushort	ntb;			/* number of software transmit buffers */
-	RingBuf *rb;			/* software receive buffers */
-	RingBuf *tb;			/* software transmit buffers */
-
-	ushort	rh;			/* first receive buffer belonging to host */
-	ushort	ri;			/* first receive buffer belonging to card */	
-
-	ushort	th;			/* first transmit buffer belonging to host */	
-	ushort	ti;			/* first transmit buffer belonging to card */
-	int	tbusy;			/* transmitter is busy */
-	int	mbps;			/* zero means link down */	
-};
-
-extern void etherrloop(Ether*, Etherpkt*, long);
-extern void addethercard(char*, int(*)(Ether*));
-
-#define NEXT(x, l)	(((x)+1)%(l))
-#define PREV(x, l)	(((x) == 0) ? (l)-1: (x)-1)
--- a/os/boot/pc/etherigbe.c
+++ /dev/null
@@ -1,1741 +1,0 @@
-/*
- * bootstrap driver for
- * Intel RS-82543GC Gigabit Ethernet PCI Controllers
- * as found on the Intel PRO/1000[FT] Server Adapter.
- * The older non-[FT] cards use the 82542 (LSI L2A1157) chip; no attempt
- * is made to handle the older chip although it should be possible.
- *
- * updated just enough to cope with the
- * Intel 8254[0347]NN Gigabit Ethernet Controller
- * as found on the Intel PRO/1000 series of adapters:
- *	82540EM Intel PRO/1000 MT
- *	82543GC	Intel PRO/1000 T
- *	82544EI Intel PRO/1000 XT
- *	82547EI built-in
- *
- * The datasheet is not very clear about running on a big-endian system
- * and this driver assumes little-endian throughout.
- * To do:
- *	GMII/MII
- *	check recovery from receive no buffers condition
- *	automatic ett adjustment
- */
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-#include "etherif.h"
-#include "ethermii.h"
-
-enum {
-	Debug = 0,		/* mostly for X60 debugging */
-};
-enum {
-	i82542     = (0x1000<<16)|0x8086,
-	i82543gc   = (0x1004<<16)|0x8086,
-	i82544ei   = (0x1008<<16)|0x8086,
-	i82540em   = (0x100E<<16)|0x8086,
-	i82546eb   = (0x1010<<16)|0x8086,
-	i82547ei   = (0x1019<<16)|0x8086,
-	i82540eplp = (0x101E<<16)|0x8086,
-	i82547gi   = (0x1075<<16)|0x8086,
-	i82541gi   = (0x1076<<16)|0x8086,
-	i82541gi2  = (0x1077<<16)|0x8086,
-	i82546gb   = (0x1079<<16)|0x8086,
-	i82541pi   = (0x107c<<16)|0x8086,
-};
-
-/* compatibility with cpu kernels */
-#define iallocb allocb
-#ifndef CACHELINESZ
-#define CACHELINESZ	32		/* pentium & later */
-#endif
-
-/* from pci.c */
-enum
-{					/* command register (pcidev->pcr) */
-	IOen		= (1<<0),
-	MEMen		= (1<<1),
-	MASen		= (1<<2),
-	MemWrInv	= (1<<4),
-	PErrEn		= (1<<6),
-	SErrEn		= (1<<8),
-};
-enum {
-	Ctrl		= 0x00000000,	/* Device Control */
-	Status		= 0x00000008,	/* Device Status */
-	Eecd		= 0x00000010,	/* EEPROM/Flash Control/Data */
-	Ctrlext		= 0x00000018,	/* Extended Device Control */
-	Mdic		= 0x00000020,	/* MDI Control */
-	Fcal		= 0x00000028,	/* Flow Control Address Low */
-	Fcah		= 0x0000002C,	/* Flow Control Address High */
-	Fct		= 0x00000030,	/* Flow Control Type */
-	Icr		= 0x000000C0,	/* Interrupt Cause Read */
-	Ics		= 0x000000C8,	/* Interrupt Cause Set */
-	Ims		= 0x000000D0,	/* Interrupt Mask Set/Read */
-	Imc		= 0x000000D8,	/* Interrupt mask Clear */
-	Rctl		= 0x00000100,	/* Receive Control */
-	Fcttv		= 0x00000170,	/* Flow Control Transmit Timer Value */
-	Txcw		= 0x00000178,	/* Transmit Configuration Word */
-	Tctl		= 0x00000400,	/* Transmit Control */
-	Tipg		= 0x00000410,	/* Transmit IPG */
-	Tbt		= 0x00000448,	/* Transmit Burst Timer */
-	Ait		= 0x00000458,	/* Adaptive IFS Throttle */
-	Fcrtl		= 0x00002160,	/* Flow Control RX Threshold Low */
-	Fcrth		= 0x00002168,	/* Flow Control Rx Threshold High */
-	Rdbal		= 0x00002800,	/* Rdesc Base Address Low */
-	Rdbah		= 0x00002804,	/* Rdesc Base Address High */
-	Rdlen		= 0x00002808,	/* Receive Descriptor Length */
-	Rdh		= 0x00002810,	/* Receive Descriptor Head */
-	Rdt		= 0x00002818,	/* Receive Descriptor Tail */
-	Rdtr		= 0x00002820,	/* Receive Descriptor Timer Ring */
-	Rxdctl		= 0x00002828,	/* Receive Descriptor Control */
-	Radv		= 0x0000282C,	/* Receive Interrupt Absolute Delay Timer */
-	Txdmac		= 0x00003000,	/* Transfer DMA Control */
-	Ett		= 0x00003008,	/* Early Transmit Control */
-	Tdbal		= 0x00003800,	/* Tdesc Base Address Low */
-	Tdbah		= 0x00003804,	/* Tdesc Base Address High */
-	Tdlen		= 0x00003808,	/* Transmit Descriptor Length */
-	Tdh		= 0x00003810,	/* Transmit Descriptor Head */
-	Tdt		= 0x00003818,	/* Transmit Descriptor Tail */
-	Tidv		= 0x00003820,	/* Transmit Interrupt Delay Value */
-	Txdctl		= 0x00003828,	/* Transmit Descriptor Control */
-	Tadv		= 0x0000382C,	/* Transmit Interrupt Absolute Delay Timer */
-
-	Statistics	= 0x00004000,	/* Start of Statistics Area */
-	Gorcl		= 0x88/4,	/* Good Octets Received Count */
-	Gotcl		= 0x90/4,	/* Good Octets Transmitted Count */
-	Torl		= 0xC0/4,	/* Total Octets Received */
-	Totl		= 0xC8/4,	/* Total Octets Transmitted */
-	Nstatistics	= 64,
-
-	Rxcsum		= 0x00005000,	/* Receive Checksum Control */
-	Mta		= 0x00005200,	/* Multicast Table Array */
-	Ral		= 0x00005400,	/* Receive Address Low */
-	Rah		= 0x00005404,	/* Receive Address High */
-	Manc		= 0x00005820,	/* Management Control */
-};
-
-enum {					/* Ctrl */
-	Bem		= 0x00000002,	/* Big Endian Mode */
-	Prior		= 0x00000004,	/* Priority on the PCI bus */
-	Lrst		= 0x00000008,	/* Link Reset */
-	Asde		= 0x00000020,	/* Auto-Speed Detection Enable */
-	Slu		= 0x00000040,	/* Set Link Up */
-	Ilos		= 0x00000080,	/* Invert Loss of Signal (LOS) */
-	SspeedMASK	= 0x00000300,	/* Speed Selection */
-	SspeedSHIFT	= 8,
-	Sspeed10	= 0x00000000,	/* 10Mb/s */
-	Sspeed100	= 0x00000100,	/* 100Mb/s */
-	Sspeed1000	= 0x00000200,	/* 1000Mb/s */
-	Frcspd		= 0x00000800,	/* Force Speed */
-	Frcdplx		= 0x00001000,	/* Force Duplex */
-	SwdpinsloMASK	= 0x003C0000,	/* Software Defined Pins - lo nibble */
-	SwdpinsloSHIFT	= 18,
-	SwdpioloMASK	= 0x03C00000,	/* Software Defined Pins - I or O */
-	SwdpioloSHIFT	= 22,
-	Devrst		= 0x04000000,	/* Device Reset */
-	Rfce		= 0x08000000,	/* Receive Flow Control Enable */
-	Tfce		= 0x10000000,	/* Transmit Flow Control Enable */
-	Vme		= 0x40000000,	/* VLAN Mode Enable */
-};
-
-/*
- * can't find Tckok nor Rbcok in any Intel docs,
- * but even 82543gc docs define Lanid.
- */
-enum {					/* Status */
-	Lu		= 0x00000002,	/* Link Up */
-	Lanid		= 0x0000000C,	/* mask for Lan ID. (function id) */
-//	Tckok		= 0x00000004,	/* Transmit clock is running */
-//	Rbcok		= 0x00000008,	/* Receive clock is running */
-	Txoff		= 0x00000010,	/* Transmission Paused */
-	Tbimode		= 0x00000020,	/* TBI Mode Indication */
-	SpeedMASK	= 0x000000C0,
-	Speed10		= 0x00000000,	/* 10Mb/s */
-	Speed100	= 0x00000040,	/* 100Mb/s */
-	Speed1000	= 0x00000080,	/* 1000Mb/s */
-	Mtxckok		= 0x00000400,	/* MTX clock is running */
-	Pci66		= 0x00000800,	/* PCI Bus speed indication */
-	Bus64		= 0x00001000,	/* PCI Bus width indication */
-};
-
-enum {					/* Ctrl and Status */
-	Fd		= 0x00000001,	/* Full-Duplex */
-	AsdvMASK	= 0x00000300,
-	Asdv10		= 0x00000000,	/* 10Mb/s */
-	Asdv100		= 0x00000100,	/* 100Mb/s */
-	Asdv1000	= 0x00000200,	/* 1000Mb/s */
-};
-
-enum {					/* Eecd */
-	Sk		= 0x00000001,	/* Clock input to the EEPROM */
-	Cs		= 0x00000002,	/* Chip Select */
-	Di		= 0x00000004,	/* Data Input to the EEPROM */
-	Do		= 0x00000008,	/* Data Output from the EEPROM */
-	Areq		= 0x00000040,	/* EEPROM Access Request */
-	Agnt		= 0x00000080,	/* EEPROM Access Grant */
-	Eepresent	= 0x00000100,	/* EEPROM Present */
-	Eesz256		= 0x00000200,	/* EEPROM is 256 words not 64 */
-	Eeszaddr	= 0x00000400,	/* EEPROM size for 8254[17] */
-	Spi		= 0x00002000,	/* EEPROM is SPI not Microwire */
-};
-
-enum {					/* Ctrlext */
-	Gpien		= 0x0000000F,	/* General Purpose Interrupt Enables */
-	SwdpinshiMASK	= 0x000000F0,	/* Software Defined Pins - hi nibble */
-	SwdpinshiSHIFT	= 4,
-	SwdpiohiMASK	= 0x00000F00,	/* Software Defined Pins - I or O */
-	SwdpiohiSHIFT	= 8,
-	Asdchk		= 0x00001000,	/* ASD Check */
-	Eerst		= 0x00002000,	/* EEPROM Reset */
-	Ips		= 0x00004000,	/* Invert Power State */
-	Spdbyps		= 0x00008000,	/* Speed Select Bypass */
-};
-
-enum {					/* EEPROM content offsets */
-	Ea		= 0x00,		/* Ethernet Address */
-	Cf		= 0x03,		/* Compatibility Field */
-	Pba		= 0x08,		/* Printed Board Assembly number */
-	Icw1		= 0x0A,		/* Initialization Control Word 1 */
-	Sid		= 0x0B,		/* Subsystem ID */
-	Svid		= 0x0C,		/* Subsystem Vendor ID */
-	Did		= 0x0D,		/* Device ID */
-	Vid		= 0x0E,		/* Vendor ID */
-	Icw2		= 0x0F,		/* Initialization Control Word 2 */
-};
-
-enum {					/* Mdic */
-	MDIdMASK	= 0x0000FFFF,	/* Data */
-	MDIdSHIFT	= 0,
-	MDIrMASK	= 0x001F0000,	/* PHY Register Address */
-	MDIrSHIFT	= 16,
-	MDIpMASK	= 0x03E00000,	/* PHY Address */
-	MDIpSHIFT	= 21,
-	MDIwop		= 0x04000000,	/* Write Operation */
-	MDIrop		= 0x08000000,	/* Read Operation */
-	MDIready	= 0x10000000,	/* End of Transaction */
-	MDIie		= 0x20000000,	/* Interrupt Enable */
-	MDIe		= 0x40000000,	/* Error */
-};
-
-enum {					/* Icr, Ics, Ims, Imc */
-	Txdw		= 0x00000001,	/* Transmit Descriptor Written Back */
-	Txqe		= 0x00000002,	/* Transmit Queue Empty */
-	Lsc		= 0x00000004,	/* Link Status Change */
-	Rxseq		= 0x00000008,	/* Receive Sequence Error */
-	Rxdmt0		= 0x00000010,	/* Rdesc Minimum Threshold Reached */
-	Rxo		= 0x00000040,	/* Receiver Overrun */
-	Rxt0		= 0x00000080,	/* Receiver Timer Interrupt */
-	Mdac		= 0x00000200,	/* MDIO Access Completed */
-	Rxcfg		= 0x00000400,	/* Receiving /C/ ordered sets */
-	Gpi0		= 0x00000800,	/* General Purpose Interrupts */
-	Gpi1		= 0x00001000,
-	Gpi2		= 0x00002000,
-	Gpi3		= 0x00004000,
-};
-
-/*
- * The Mdic register isn't implemented on the 82543GC,
- * the software defined pins are used instead.
- * These definitions work for the Intel PRO/1000 T Server Adapter.
- * The direction pin bits are read from the EEPROM.
- */
-enum {
-	Mdd		= ((1<<2)<<SwdpinsloSHIFT),	/* data */
-	Mddo		= ((1<<2)<<SwdpioloSHIFT),	/* pin direction */
-	Mdc		= ((1<<3)<<SwdpinsloSHIFT),	/* clock */
-	Mdco		= ((1<<3)<<SwdpioloSHIFT),	/* pin direction */
-	Mdr		= ((1<<0)<<SwdpinshiSHIFT),	/* reset */
-	Mdro		= ((1<<0)<<SwdpiohiSHIFT),	/* pin direction */
-};
-
-enum {					/* Txcw */
-	TxcwFd		= 0x00000020,	/* Full Duplex */
-	TxcwHd		= 0x00000040,	/* Half Duplex */
-	TxcwPauseMASK	= 0x00000180,	/* Pause */
-	TxcwPauseSHIFT	= 7,
-	TxcwPs		= (1<<TxcwPauseSHIFT),	/* Pause Supported */
-	TxcwAs		= (2<<TxcwPauseSHIFT),	/* Asymmetric FC desired */
-	TxcwRfiMASK	= 0x00003000,	/* Remote Fault Indication */
-	TxcwRfiSHIFT	= 12,
-	TxcwNpr		= 0x00008000,	/* Next Page Request */
-	TxcwConfig	= 0x40000000,	/* Transmit COnfig Control */
-	TxcwAne		= 0x80000000,	/* Auto-Negotiation Enable */
-};
-
-enum {					/* Rctl */
-	Rrst		= 0x00000001,	/* Receiver Software Reset */
-	Ren		= 0x00000002,	/* Receiver Enable */
-	Sbp		= 0x00000004,	/* Store Bad Packets */
-	Upe		= 0x00000008,	/* Unicast Promiscuous Enable */
-	Mpe		= 0x00000010,	/* Multicast Promiscuous Enable */
-	Lpe		= 0x00000020,	/* Long Packet Reception Enable */
-	LbmMASK		= 0x000000C0,	/* Loopback Mode */
-	LbmOFF		= 0x00000000,	/* No Loopback */
-	LbmTBI		= 0x00000040,	/* TBI Loopback */
-	LbmMII		= 0x00000080,	/* GMII/MII Loopback */
-	LbmXCVR		= 0x000000C0,	/* Transceiver Loopback */
-	RdtmsMASK	= 0x00000300,	/* Rdesc Minimum Threshold Size */
-	RdtmsHALF	= 0x00000000,	/* Threshold is 1/2 Rdlen */
-	RdtmsQUARTER	= 0x00000100,	/* Threshold is 1/4 Rdlen */
-	RdtmsEIGHTH	= 0x00000200,	/* Threshold is 1/8 Rdlen */
-	MoMASK		= 0x00003000,	/* Multicast Offset */
-	Bam		= 0x00008000,	/* Broadcast Accept Mode */
-	BsizeMASK	= 0x00030000,	/* Receive Buffer Size */
-	Bsize2048	= 0x00000000,
-	Bsize1024	= 0x00010000,
-	Bsize512	= 0x00020000,
-	Bsize256	= 0x00030000,
-	Vfe		= 0x00040000,	/* VLAN Filter Enable */
-	Cfien		= 0x00080000,	/* Canonical Form Indicator Enable */
-	Cfi		= 0x00100000,	/* Canonical Form Indicator value */
-	Dpf		= 0x00400000,	/* Discard Pause Frames */
-	Pmcf		= 0x00800000,	/* Pass MAC Control Frames */
-	Bsex		= 0x02000000,	/* Buffer Size Extension */
-	Secrc		= 0x04000000,	/* Strip CRC from incoming packet */
-};
-
-enum {					/* Tctl */
-	Trst		= 0x00000001,	/* Transmitter Software Reset */
-	Ten		= 0x00000002,	/* Transmit Enable */
-	Psp		= 0x00000008,	/* Pad Short Packets */
-	CtMASK		= 0x00000FF0,	/* Collision Threshold */
-	CtSHIFT		= 4,
-	ColdMASK	= 0x003FF000,	/* Collision Distance */
-	ColdSHIFT	= 12,
-	Swxoff		= 0x00400000,	/* Sofware XOFF Transmission */
-	Pbe		= 0x00800000,	/* Packet Burst Enable */
-	Rtlc		= 0x01000000,	/* Re-transmit on Late Collision */
-	Nrtu		= 0x02000000,	/* No Re-transmit on Underrrun */
-};
-
-enum {					/* [RT]xdctl */
-	PthreshMASK	= 0x0000003F,	/* Prefetch Threshold */
-	PthreshSHIFT	= 0,
-	HthreshMASK	= 0x00003F00,	/* Host Threshold */
-	HthreshSHIFT	= 8,
-	WthreshMASK	= 0x003F0000,	/* Writebacj Threshold */
-	WthreshSHIFT	= 16,
-	Gran		= 0x01000000,	/* Granularity */
-};
-
-enum {					/* Rxcsum */
-	PcssMASK	= 0x000000FF,	/* Packet Checksum Start */
-	PcssSHIFT	= 0,
-	Ipofl		= 0x00000100,	/* IP Checksum Off-load Enable */
-	Tuofl		= 0x00000200,	/* TCP/UDP Checksum Off-load Enable */
-};
-
-enum {					/* Manc */
-	Arpen		= 0x00002000,	/* Enable ARP Request Filtering */
-};
-
-typedef struct Rdesc {			/* Receive Descriptor */
-	uint	addr[2];
-	ushort	length;
-	ushort	checksum;
-	uchar	status;
-	uchar	errors;
-	ushort	special;
-} Rdesc;
-
-enum {					/* Rdesc status */
-	Rdd		= 0x01,		/* Descriptor Done */
-	Reop		= 0x02,		/* End of Packet */
-	Ixsm		= 0x04,		/* Ignore Checksum Indication */
-	Vp		= 0x08,		/* Packet is 802.1Q (matched VET) */
-	Tcpcs		= 0x20,		/* TCP Checksum Calculated on Packet */
-	Ipcs		= 0x40,		/* IP Checksum Calculated on Packet */
-	Pif		= 0x80,		/* Passed in-exact filter */
-};
-
-enum {					/* Rdesc errors */
-	Ce		= 0x01,		/* CRC Error or Alignment Error */
-	Se		= 0x02,		/* Symbol Error */
-	Seq		= 0x04,		/* Sequence Error */
-	Cxe		= 0x10,		/* Carrier Extension Error */
-	Tcpe		= 0x20,		/* TCP/UDP Checksum Error */
-	Ipe		= 0x40,		/* IP Checksum Error */
-	Rxe		= 0x80,		/* RX Data Error */
-};
-
-typedef struct Tdesc {			/* Legacy+Normal Transmit Descriptor */
-	uint	addr[2];
-	uint	control;		/* varies with descriptor type */
-	uint	status;			/* varies with descriptor type */
-} Tdesc;
-
-enum {					/* Tdesc control */
-	LenMASK		= 0x000FFFFF,	/* Data/Packet Length Field */
-	LenSHIFT	= 0,
-	DtypeCD		= 0x00000000,	/* Data Type 'Context Descriptor' */
-	DtypeDD		= 0x00100000,	/* Data Type 'Data Descriptor' */
-	PtypeTCP	= 0x01000000,	/* TCP/UDP Packet Type (CD) */
-	Teop		= 0x01000000,	/* End of Packet (DD) */
-	PtypeIP		= 0x02000000,	/* IP Packet Type (CD) */
-	Ifcs		= 0x02000000,	/* Insert FCS (DD) */
-	Tse		= 0x04000000,	/* TCP Segmentation Enable */
-	Rs		= 0x08000000,	/* Report Status */
-	Rps		= 0x10000000,	/* Report Status Sent */
-	Dext		= 0x20000000,	/* Descriptor Extension */
-	Vle		= 0x40000000,	/* VLAN Packet Enable */
-	Ide		= 0x80000000,	/* Interrupt Delay Enable */
-};
-
-enum {					/* Tdesc status */
-	Tdd		= 0x00000001,	/* Descriptor Done */
-	Ec		= 0x00000002,	/* Excess Collisions */
-	Lc		= 0x00000004,	/* Late Collision */
-	Tu		= 0x00000008,	/* Transmit Underrun */
-	CssMASK		= 0x0000FF00,	/* Checksum Start Field */
-	CssSHIFT	= 8,
-};
-
-enum {
-	Nrdesc		= 32,		/* multiple of 8 */
-	Ntdesc		= 8,		/* multiple of 8 */
-};
-
-typedef struct Ctlr Ctlr;
-typedef struct Ctlr {
-	int	port;
-	Pcidev*	pcidev;
-	Ctlr*	next;
-	int	active;
-	int	id;
-	int	cls;
-	ushort	eeprom[0x40];
-
-	int*	nic;
-	Lock	imlock;
-	int	im;			/* interrupt mask */
-
-	Mii*	mii;
-
-	Lock	slock;
-	uint	statistics[Nstatistics];
-
-	uchar	ra[Eaddrlen];		/* receive address */
-	ulong	mta[128];		/* multicast table array */
-
-	Rdesc*	rdba;			/* receive descriptor base address */
-	Block**	rb;			/* receive buffers */
-	int	rdh;			/* receive descriptor head */
-	int	rdt;			/* receive descriptor tail */
-
-	Tdesc*	tdba;			/* transmit descriptor base address */
-	Lock	tdlock;
-	Block**	tb;			/* transmit buffers */
-	int	tdh;			/* transmit descriptor head */
-	int	tdt;			/* transmit descriptor tail */
-	int	ett;			/* early transmit threshold */
-
-	int	txcw;
-	int	fcrtl;
-	int	fcrth;
-
-	/* bootstrap goo */
-	Block*	bqhead;	/* transmission queue */
-	Block*	bqtail;
-} Ctlr;
-
-static Ctlr* ctlrhead;
-static Ctlr* ctlrtail;
-
-#define csr32r(c, r)	(*((c)->nic+((r)/4)))
-#define csr32w(c, r, v)	(*((c)->nic+((r)/4)) = (v))
-
-static void
-igbeim(Ctlr* ctlr, int im)
-{
-	ilock(&ctlr->imlock);
-	ctlr->im |= im;
-	csr32w(ctlr, Ims, ctlr->im);
-	iunlock(&ctlr->imlock);
-}
-
-static void
-igbeattach(Ether* edev)
-{
-	int ctl;
-	Ctlr *ctlr;
-
-	/*
-	 * To do here:
-	 *	one-time stuff;
-	 *	start off a kproc for link status change:
-	 *		adjust queue length depending on speed;
-	 *		flow control.
-	 *	more needed here...
-	 */
-	ctlr = edev->ctlr;
-	igbeim(ctlr, 0);
-	ctl = csr32r(ctlr, Rctl)|Ren;
-	csr32w(ctlr, Rctl, ctl);
-	ctl = csr32r(ctlr, Tctl)|Ten;
-	csr32w(ctlr, Tctl, ctl);
-}
-
-static char* statistics[Nstatistics] = {
-	"CRC Error",
-	"Alignment Error",
-	"Symbol Error",
-	"RX Error",
-	"Missed Packets",
-	"Single Collision",
-	"Excessive Collisions",
-	"Multiple Collision",
-	"Late Collisions",
-	nil,
-	"Collision",
-	"Transmit Underrun",
-	"Defer",
-	"Transmit - No CRS",
-	"Sequence Error",
-	"Carrier Extension Error",
-	"Receive Error Length",
-	nil,
-	"XON Received",
-	"XON Transmitted",
-	"XOFF Received",
-	"XOFF Transmitted",
-	"FC Received Unsupported",
-	"Packets Received (64 Bytes)",
-	"Packets Received (65-127 Bytes)",
-	"Packets Received (128-255 Bytes)",
-	"Packets Received (256-511 Bytes)",
-	"Packets Received (512-1023 Bytes)",
-	"Packets Received (1024-1522 Bytes)",
-	"Good Packets Received",
-	"Broadcast Packets Received",
-	"Multicast Packets Received",
-	"Good Packets Transmitted",
-	nil,
-	"Good Octets Received",
-	nil,
-	"Good Octets Transmitted",
-	nil,
-	nil,
-	nil,
-	"Receive No Buffers",
-	"Receive Undersize",
-	"Receive Fragment",
-	"Receive Oversize",
-	"Receive Jabber",
-	nil,
-	nil,
-	nil,
-	"Total Octets Received",
-	nil,
-	"Total Octets Transmitted",
-	nil,
-	"Total Packets Received",
-	"Total Packets Transmitted",
-	"Packets Transmitted (64 Bytes)",
-	"Packets Transmitted (65-127 Bytes)",
-	"Packets Transmitted (128-255 Bytes)",
-	"Packets Transmitted (256-511 Bytes)",
-	"Packets Transmitted (512-1023 Bytes)",
-	"Packets Transmitted (1024-1522 Bytes)",
-	"Multicast Packets Transmitted",
-	"Broadcast Packets Transmitted",
-	"TCP Segmentation Context Transmitted",
-	"TCP Segmentation Context Fail",
-};
-
-static void
-txstart(Ether *edev)
-{
-	int tdh, tdt, len, olen;
-	Ctlr *ctlr = edev->ctlr;
-	Block *bp;
-	Tdesc *tdesc;
-
-	/*
-	 * Try to fill the ring back up, moving buffers from the transmit q.
-	 */
-	tdh = PREV(ctlr->tdh, Ntdesc);
-	for(tdt = ctlr->tdt; tdt != tdh; tdt = NEXT(tdt, Ntdesc)){
-		/* pull off the head of the transmission queue */
-		if((bp = ctlr->bqhead) == nil)		/* was qget(edev->oq) */
-			break;
-		ctlr->bqhead = bp->next;
-		if (ctlr->bqtail == bp)
-			ctlr->bqtail = nil;
-		len = olen = BLEN(bp);
-
-		/*
-		 * if packet is too short, make it longer rather than relying
-		 * on ethernet interface to pad it and complain so the caller
-		 * will get fixed.  I don't think Psp is working right, or it's
-		 * getting cleared.
-		 */
-		if (len < ETHERMINTU) {
-			if (bp->rp + ETHERMINTU <= bp->lim)
-				bp->wp = bp->rp + ETHERMINTU;
-			else
-				bp->wp = bp->lim;
-			len = BLEN(bp);
-			print("txstart: extended short pkt %d -> %d bytes\n",
-				olen, len);
-		}
-
-		/* set up a descriptor for it */
-		tdesc = &ctlr->tdba[tdt];
-		tdesc->addr[0] = PCIWADDR(bp->rp);
-		tdesc->addr[1] = 0;
-		tdesc->control = /* Ide| */ Rs|Dext|Ifcs|Teop|DtypeDD|len;
-		tdesc->status = 0;
-
-		ctlr->tb[tdt] = bp;
-	}
-	ctlr->tdt = tdt;
-	csr32w(ctlr, Tdt, tdt);
-	igbeim(ctlr, Txdw);
-}
-
-static Block *
-fromringbuf(Ether *ether)
-{
-	RingBuf *tb = &ether->tb[ether->ti];
-	Block *bp = allocb(tb->len);
-
-	memmove(bp->wp, tb->pkt, tb->len);
-	memmove(bp->wp+Eaddrlen, ether->ea, Eaddrlen);
-	bp->wp += tb->len;
-	return bp;
-}
-
-static void
-igbetransmit(Ether* edev)
-{
-	Block *bp;
-	Ctlr *ctlr;
-	Tdesc *tdesc;
-	RingBuf *tb;
-	int tdh;
-
-	/*
-	 * For now there are no smarts here. Tuning comes later.
-	 */
-	ctlr = edev->ctlr;
-	ilock(&ctlr->tdlock);
-
-	/*
-	 * Free any completed packets
-	 * - try to get the soft tdh to catch the tdt;
-	 * - if the packet had an underrun bump the threshold
-	 *   - the Tu bit doesn't seem to ever be set, perhaps
-	 *     because Rs mode is used?
-	 */
-	tdh = ctlr->tdh;
-	for(;;){
-		tdesc = &ctlr->tdba[tdh];
-		if(!(tdesc->status & Tdd))
-			break;
-		if(tdesc->status & Tu){
-			ctlr->ett++;
-			csr32w(ctlr, Ett, ctlr->ett);
-		}
-		tdesc->status = 0;
-		if(ctlr->tb[tdh] != nil){
-			freeb(ctlr->tb[tdh]);
-			ctlr->tb[tdh] = nil;
-		}
-		tdh = NEXT(tdh, Ntdesc);
-	}
-	ctlr->tdh = tdh;
-
-	/* copy packets from the software RingBuf to the transmission q */
-	/* from boot ether83815.c */
-	while((tb = &edev->tb[edev->ti])->owner == Interface){
-		bp = fromringbuf(edev);
-
-		/* put the buffer on the transmit queue */
-		if(ctlr->bqhead)
-			ctlr->bqtail->next = bp;
-		else
-			ctlr->bqhead = bp;
-		ctlr->bqtail = bp;
-
-		txstart(edev);		/* kick transmitter */
-		tb->owner = Host;	/* give descriptor back */
-
-		edev->ti = NEXT(edev->ti, edev->ntb);
-	}
-
-	iunlock(&ctlr->tdlock);
-}
-
-static void
-igbereplenish(Ctlr* ctlr)
-{
-	int rdt;
-	Block *bp;
-	Rdesc *rdesc;
-
-	rdt = ctlr->rdt;
-	while(NEXT(rdt, Nrdesc) != ctlr->rdh){
-		rdesc = &ctlr->rdba[rdt];
-		if(ctlr->rb[rdt] != nil){
-			/* nothing to do */
-		}
-		else if((bp = iallocb(2048)) != nil){
-			ctlr->rb[rdt] = bp;
-			rdesc->addr[0] = PCIWADDR(bp->rp);
-			rdesc->addr[1] = 0;
-		}
-		else
-			break;
-		rdesc->status = 0;
-
-		rdt = NEXT(rdt, Nrdesc);
-	}
-	ctlr->rdt = rdt;
-	csr32w(ctlr, Rdt, rdt);
-}
-
-static void
-toringbuf(Ether *ether, Block *bp)
-{
-	RingBuf *rb = &ether->rb[ether->ri];
-
-	if (rb->owner == Interface) {
-		rb->len = BLEN(bp);
-		memmove(rb->pkt, bp->rp, rb->len);
-		rb->owner = Host;
-		ether->ri = NEXT(ether->ri, ether->nrb);
-	}
-	/* else no one is expecting packets from the network */
-}
-
-static void
-igbeinterrupt(Ureg*, void* arg)
-{
-	Block *bp;
-	Ctlr *ctlr;
-	Ether *edev;
-	Rdesc *rdesc;
-	int icr, im, rdh, txdw = 0;
-
-	edev = arg;
-	ctlr = edev->ctlr;
-
-	ilock(&ctlr->imlock);
-	csr32w(ctlr, Imc, ~0);
-	im = ctlr->im;
-
-	for(icr = csr32r(ctlr, Icr); icr & ctlr->im; icr = csr32r(ctlr, Icr)){
-		/*
-		 * Link status changed.
-		 */
-		if(icr & (Rxseq|Lsc)){
-			/*
-			 * should be more here...
-			 */
-		}
-
-		/*
-		 * Process any received packets.
-		 */
-		rdh = ctlr->rdh;
-		for(;;){
-			rdesc = &ctlr->rdba[rdh];
-			if(!(rdesc->status & Rdd))
-				break;
-			if ((rdesc->status & Reop) && rdesc->errors == 0) {
-				bp = ctlr->rb[rdh];
-				ctlr->rb[rdh] = nil;
-				/*
-				 * it appears that the original 82543 needed
-				 * to have the Ethernet CRC excluded, but that
-				 * the newer chips do not?
-				 */
-				bp->wp += rdesc->length /* -4 */;
-				toringbuf(edev, bp);
-				freeb(bp);
-			} else if ((rdesc->status & Reop) && rdesc->errors)
-				print("igbe: input packet error 0x%ux\n",
-					rdesc->errors);
-			rdesc->status = 0;
-			rdh = NEXT(rdh, Nrdesc);
-		}
-		ctlr->rdh = rdh;
-
-		if(icr & Rxdmt0)
-			igbereplenish(ctlr);
-		if(icr & Txdw){
-			im &= ~Txdw;
-			txdw++;
-		}
-	}
-
-	ctlr->im = im;
-	csr32w(ctlr, Ims, im);
-	iunlock(&ctlr->imlock);
-
-	if(txdw)
-		igbetransmit(edev);
-}
-
-static int
-igbeinit(Ether* edev)
-{
-	int csr, i, r, ctrl;
-	MiiPhy *phy;
-	Ctlr *ctlr;
-
-	ctlr = edev->ctlr;
-
-	/*
-	 * Set up the receive addresses.
-	 * There are 16 addresses. The first should be the MAC address.
-	 * The others are cleared and not marked valid (MS bit of Rah).
-	 */
-	csr = (edev->ea[3]<<24)|(edev->ea[2]<<16)|(edev->ea[1]<<8)|edev->ea[0];
-	csr32w(ctlr, Ral, csr);
-	csr = 0x80000000|(edev->ea[5]<<8)|edev->ea[4];
-	csr32w(ctlr, Rah, csr);
-	for(i = 1; i < 16; i++){
-		csr32w(ctlr, Ral+i*8, 0);
-		csr32w(ctlr, Rah+i*8, 0);
-	}
-
-	/*
-	 * Clear the Multicast Table Array.
-	 * It's a 4096 bit vector accessed as 128 32-bit registers.
-	 */
-	for(i = 0; i < 128; i++)
-		csr32w(ctlr, Mta+i*4, 0);
-
-	/*
-	 * Receive initialisation.
-	 * Mostly defaults from the datasheet, will
-	 * need some tuning for performance:
-	 *	Rctl	descriptor mimimum threshold size
-	 *		discard pause frames
-	 *		strip CRC
-	 * 	Rdtr	interrupt delay
-	 * 	Rxdctl	all the thresholds
-	 */
-	csr32w(ctlr, Rctl, 0);
-
-	/*
-	 * Allocate the descriptor ring and load its
-	 * address and length into the NIC.
-	 */
-	ctlr->rdba = xspanalloc(Nrdesc*sizeof(Rdesc), 128 /* was 16 */, 0);
-	csr32w(ctlr, Rdbal, PCIWADDR(ctlr->rdba));
-	csr32w(ctlr, Rdbah, 0);
-	csr32w(ctlr, Rdlen, Nrdesc*sizeof(Rdesc));
-
-	/*
-	 * Initialise the ring head and tail pointers and
-	 * populate the ring with Blocks.
-	 * The datasheet says the tail pointer is set to beyond the last
-	 * descriptor hardware can process, which implies the initial
-	 * condition is Rdh == Rdt. However, experience shows Rdt must
-	 * always be 'behind' Rdh; the replenish routine ensures this.
-	 */
-	ctlr->rdh = 0;
-	csr32w(ctlr, Rdh, ctlr->rdh);
-	ctlr->rdt = 0;
-	csr32w(ctlr, Rdt, ctlr->rdt);
-	ctlr->rb = malloc(sizeof(Block*)*Nrdesc);
-	igbereplenish(ctlr);
-
-	/*
-	 * Set up Rctl but don't enable receiver (yet).
-	 */
-	csr32w(ctlr, Rdtr, 0);
-	switch(ctlr->id){
-	case i82540em:
-	case i82540eplp:
-	case i82541gi:
-	case i82541gi2:
-	case i82541pi:
-	case i82546gb:
-	case i82546eb:
-	case i82547gi:
-		csr32w(ctlr, Radv, 64);
-		break;
-	}
-	csr32w(ctlr, Rxdctl, (8<<WthreshSHIFT)|(8<<HthreshSHIFT)|4);
-	/*
-	 * Enable checksum offload.
-	 */
-	csr32w(ctlr, Rxcsum, Tuofl|Ipofl|(ETHERHDRSIZE<<PcssSHIFT));
-
-	csr32w(ctlr, Rctl, Dpf|Bsize2048|Bam|RdtmsHALF);
-	igbeim(ctlr, Rxt0|Rxo|Rxdmt0|Rxseq);
-
-	/*
-	 * Transmit initialisation.
-	 * Mostly defaults from the datasheet, will
-	 * need some tuning for performance. The normal mode will
-	 * be full-duplex and things to tune for half-duplex are
-	 *	Tctl	re-transmit on late collision
-	 *	Tipg	all IPG times
-	 *	Tbt	burst timer
-	 *	Ait	adaptive IFS throttle
-	 * and in general
-	 *	Txdmac	packet prefetching
-	 *	Ett	transmit early threshold
-	 *	Tidv	interrupt delay value
-	 *	Txdctl	all the thresholds
-	 */
-	csr32w(ctlr, Tctl, (0x0F<<CtSHIFT)|Psp|(66<<ColdSHIFT));	/* Fd */
-	switch(ctlr->id){
-	default:
-		r = 6;
-		break;
-	case i82543gc:
-	case i82544ei:
-	case i82547ei:
-	case i82540em:
-	case i82540eplp:
-	case i82541gi:
-	case i82541gi2:
-	case i82541pi:
-	case i82546gb:
-	case i82546eb:
-	case i82547gi:
-		r = 8;
-		break;
-	}
-	csr32w(ctlr, Tipg, (6<<20)|(8<<10)|r);
-	csr32w(ctlr, Ait, 0);
-	csr32w(ctlr, Txdmac, 0);
-	csr32w(ctlr, Tidv, 128);
-
-	/*
-	 * Allocate the descriptor ring and load its
-	 * address and length into the NIC.
-	 */
-	ctlr->tdba = xspanalloc(Ntdesc*sizeof(Tdesc), 128 /* was 16 */, 0);
-	csr32w(ctlr, Tdbal, PCIWADDR(ctlr->tdba));
-	csr32w(ctlr, Tdbah, 0);
-	csr32w(ctlr, Tdlen, Ntdesc*sizeof(Tdesc));
-
-	/*
-	 * Initialise the ring head and tail pointers.
-	 */
-	ctlr->tdh = 0;
-	csr32w(ctlr, Tdh, ctlr->tdh);
-	ctlr->tdt = 0;
-	csr32w(ctlr, Tdt, ctlr->tdt);
-	ctlr->tb = malloc(sizeof(Block*)*Ntdesc);
-//	ctlr->im |= Txqe|Txdw;
-
-	r = (4<<WthreshSHIFT)|(4<<HthreshSHIFT)|(8<<PthreshSHIFT);
-	switch(ctlr->id){
-	default:
-		break;
-	case i82540em:
-	case i82540eplp:
-	case i82547gi:
-	case i82541pi:
-	case i82546gb:
-	case i82546eb:
-	case i82541gi:
-	case i82541gi2:
-		r = csr32r(ctlr, Txdctl);
-		r &= ~WthreshMASK;
-		r |= Gran|(4<<WthreshSHIFT);
-
-		csr32w(ctlr, Tadv, 64);
-		break;
-	}
-	csr32w(ctlr, Txdctl, r);
-
-	r = csr32r(ctlr, Tctl);
-	r |= Ten;
-	csr32w(ctlr, Tctl, r);
-
-	if(ctlr->mii == nil || ctlr->mii->curphy == nil) {
-		print("igbe: no mii (yet)\n");
-		return 0;
-	}
-	/* wait for the link to come up */
-	if (miistatus(ctlr->mii) < 0)
-		return -1;
-	print("igbe: phy: ");
-	phy = ctlr->mii->curphy;
-	if (phy->fd)
-		print("full duplex");
-	else
-		print("half duplex");
-	print(", %d Mb/s\n", phy->speed);
-
-	/*
-	 * Flow control.
-	 */
-	ctrl = csr32r(ctlr, Ctrl);
-	if(phy->rfc)
-		ctrl |= Rfce;
-	if(phy->tfc)
-		ctrl |= Tfce;
-	csr32w(ctlr, Ctrl, ctrl);
-
-	return 0;
-}
-
-static int
-i82543mdior(Ctlr* ctlr, int n)
-{
-	int ctrl, data, i, r;
-
-	/*
-	 * Read n bits from the Management Data I/O Interface.
-	 */
-	ctrl = csr32r(ctlr, Ctrl);
-	r = (ctrl & ~Mddo)|Mdco;
-	data = 0;
-	for(i = n-1; i >= 0; i--){
-		if(csr32r(ctlr, Ctrl) & Mdd)
-			data |= (1<<i);
-		csr32w(ctlr, Ctrl, Mdc|r);
-		csr32w(ctlr, Ctrl, r);
-	}
-	csr32w(ctlr, Ctrl, ctrl);
-
-	return data;
-}
-
-static int
-i82543mdiow(Ctlr* ctlr, int bits, int n)
-{
-	int ctrl, i, r;
-
-	/*
-	 * Write n bits to the Management Data I/O Interface.
-	 */
-	ctrl = csr32r(ctlr, Ctrl);
-	r = Mdco|Mddo|ctrl;
-	for(i = n-1; i >= 0; i--){
-		if(bits & (1<<i))
-			r |= Mdd;
-		else
-			r &= ~Mdd;
-		csr32w(ctlr, Ctrl, Mdc|r);
-		csr32w(ctlr, Ctrl, r);
-	}
-	csr32w(ctlr, Ctrl, ctrl);
-
-	return 0;
-}
-
-static int
-i82543miimir(Mii* mii, int pa, int ra)
-{
-	int data;
-	Ctlr *ctlr;
-
-	ctlr = mii->ctlr;
-
-	/*
-	 * MII Management Interface Read.
-	 *
-	 * Preamble;
-	 * ST+OP+PHYAD+REGAD;
-	 * TA + 16 data bits.
-	 */
-	i82543mdiow(ctlr, 0xFFFFFFFF, 32);
-	i82543mdiow(ctlr, 0x1800|(pa<<5)|ra, 14);
-	data = i82543mdior(ctlr, 18);
-
-	if(data & 0x10000)
-		return -1;
-
-	return data & 0xFFFF;
-}
-
-static int
-i82543miimiw(Mii* mii, int pa, int ra, int data)
-{
-	Ctlr *ctlr;
-
-	ctlr = mii->ctlr;
-
-	/*
-	 * MII Management Interface Write.
-	 *
-	 * Preamble;
-	 * ST+OP+PHYAD+REGAD+TA + 16 data bits;
-	 * Z.
-	 */
-	i82543mdiow(ctlr, 0xFFFFFFFF, 32);
-	data &= 0xFFFF;
-	data |= (0x05<<(5+5+2+16))|(pa<<(5+2+16))|(ra<<(2+16))|(0x02<<16);
-	i82543mdiow(ctlr, data, 32);
-
-	return 0;
-}
-
-static int
-igbemiimir(Mii* mii, int pa, int ra)
-{
-	Ctlr *ctlr;
-	int mdic, timo;
-
-	ctlr = mii->ctlr;
-
-	csr32w(ctlr, Mdic, MDIrop|(pa<<MDIpSHIFT)|(ra<<MDIrSHIFT));
-	mdic = 0;
-	for(timo = 64; timo; timo--){
-		mdic = csr32r(ctlr, Mdic);
-		if(mdic & (MDIe|MDIready))
-			break;
-		microdelay(1);
-	}
-
-	if((mdic & (MDIe|MDIready)) == MDIready)
-		return mdic & 0xFFFF;
-	return -1;
-}
-
-static int
-igbemiimiw(Mii* mii, int pa, int ra, int data)
-{
-	Ctlr *ctlr;
-	int mdic, timo;
-
-	ctlr = mii->ctlr;
-
-	data &= MDIdMASK;
-	csr32w(ctlr, Mdic, MDIwop|(pa<<MDIpSHIFT)|(ra<<MDIrSHIFT)|data);
-	mdic = 0;
-	for(timo = 64; timo; timo--){
-		mdic = csr32r(ctlr, Mdic);
-		if(mdic & (MDIe|MDIready))
-			break;
-		microdelay(1);
-	}
-	if((mdic & (MDIe|MDIready)) == MDIready)
-		return 0;
-	return -1;
-}
-
-static int
-igbemii(Ctlr* ctlr)
-{
-	MiiPhy *phy = (MiiPhy *)1;
-	int ctrl, p, r;
-
-	USED(phy);
-	r = csr32r(ctlr, Status);
-	if(r & Tbimode)
-		return -1;
-	if((ctlr->mii = malloc(sizeof(Mii))) == nil)
-		return -1;
-	ctlr->mii->ctlr = ctlr;
-
-	ctrl = csr32r(ctlr, Ctrl);
-	ctrl |= Slu;
-
-	switch(ctlr->id){
-	case i82543gc:
-		ctrl |= Frcdplx|Frcspd;
-		csr32w(ctlr, Ctrl, ctrl);
-
-		/*
-		 * The reset pin direction (Mdro) should already
-		 * be set from the EEPROM load.
-		 * If it's not set this configuration is unexpected
-		 * so bail.
-		 */
-		r = csr32r(ctlr, Ctrlext);
-		if(!(r & Mdro))
-			return -1;
-		csr32w(ctlr, Ctrlext, r);
-		delay(20);
-		r = csr32r(ctlr, Ctrlext);
-		r &= ~Mdr;
-		csr32w(ctlr, Ctrlext, r);
-		delay(20);
-		r = csr32r(ctlr, Ctrlext);
-		r |= Mdr;
-		csr32w(ctlr, Ctrlext, r);
-		delay(20);
-
-		ctlr->mii->mir = i82543miimir;
-		ctlr->mii->miw = i82543miimiw;
-		break;
-	case i82544ei:
-	case i82547ei:
-	case i82540em:
-	case i82540eplp:
-	case i82547gi:
-	case i82541gi:
-	case i82541gi2:
-	case i82541pi:
-	case i82546gb:
-	case i82546eb:
-		ctrl &= ~(Frcdplx|Frcspd);
-		csr32w(ctlr, Ctrl, ctrl);
-		ctlr->mii->mir = igbemiimir;
-		ctlr->mii->miw = igbemiimiw;
-		break;
-	default:
-		free(ctlr->mii);
-		ctlr->mii = nil;
-		return -1;
-	}
-
-	if(mii(ctlr->mii, ~0) == 0 || (phy = ctlr->mii->curphy) == nil){
-		if (0)
-			print("phy trouble: phy = 0x%lux\n", (ulong)phy);
-		free(ctlr->mii);
-		ctlr->mii = nil;
-		return -1;
-	}
-	if (Debug)
-		print("oui %X phyno %d\n", phy->oui, phy->phyno);
-	else
-		USED(phy);
-
-	/*
-	 * 8254X-specific PHY registers not in 802.3:
-	 *	0x10	PHY specific control
-	 *	0x14	extended PHY specific control
-	 * Set appropriate values then reset the PHY to have
-	 * changes noted.
-	 */
-	switch(ctlr->id){
-	case i82547gi:
-	case i82541gi:
-	case i82541gi2:
-	case i82541pi:
-	case i82546gb:
-	case i82546eb:
-		break;
-	default:
-		r = miimir(ctlr->mii, 16);
-		r |= 0x0800;			/* assert CRS on Tx */
-		r |= 0x0060;			/* auto-crossover all speeds */
-		r |= 0x0002;			/* polarity reversal enabled */
-		miimiw(ctlr->mii, 16, r);
-
-		r = miimir(ctlr->mii, 20);
-		r |= 0x0070;			/* +25MHz clock */
-		r &= ~0x0F00;
-		r |= 0x0100;			/* 1x downshift */
-		miimiw(ctlr->mii, 20, r);
-
-		miireset(ctlr->mii);
-		break;
-	}
-	p = 0;
-	if(ctlr->txcw & TxcwPs)
-		p |= AnaP;
-	if(ctlr->txcw & TxcwAs)
-		p |= AnaAP;
-	miiane(ctlr->mii, ~0, p, ~0);
-
-	return 0;
-}
-
-static int
-at93c46io(Ctlr* ctlr, char* op, int data)
-{
-	char *lp, *p;
-	int i, loop, eecd, r;
-
-	eecd = csr32r(ctlr, Eecd);
-
-	r = 0;
-	loop = -1;
-	lp = nil;
-	for(p = op; *p != '\0'; p++){
-		switch(*p){
-		default:
-			return -1;
-		case ' ':
-			continue;
-		case ':':			/* start of loop */
-			loop = strtol(p+1, &lp, 0)-1;
-			lp--;
-			if(p == lp)
-				loop = 7;
-			p = lp;
-			continue;
-		case ';':			/* end of loop */
-			if(lp == nil)
-				return -1;
-			loop--;
-			if(loop >= 0)
-				p = lp;
-			else
-				lp = nil;
-			continue;
-		case 'C':			/* assert clock */
-			eecd |= Sk;
-			break;
-		case 'c':			/* deassert clock */
-			eecd &= ~Sk;
-			break;
-		case 'D':			/* next bit in 'data' byte */
-			if(loop < 0)
-				return -1;
-			if(data & (1<<loop))
-				eecd |= Di;
-			else
-				eecd &= ~Di;
-			break;
-		case 'O':			/* collect data output */
-			i = (csr32r(ctlr, Eecd) & Do) != 0;
-			if(loop >= 0)
-				r |= (i<<loop);
-			else
-				r = i;
-			continue;
-		case 'I':			/* assert data input */
-			eecd |= Di;
-			break;
-		case 'i':			/* deassert data input */
-			eecd &= ~Di;
-			break;
-		case 'S':			/* enable chip select */
-			eecd |= Cs;
-			break;
-		case 's':			/* disable chip select */
-			eecd &= ~Cs;
-			break;
-		}
-		csr32w(ctlr, Eecd, eecd);
-		microdelay(50);
-	}
-	if(loop >= 0)
-		return -1;
-	return r;
-}
-
-static int
-at93c46r(Ctlr* ctlr)
-{
-	ushort sum;
-	char rop[20];
-	int addr, areq, bits, data, eecd, i;
-
-	eecd = csr32r(ctlr, Eecd);
-	if(eecd & Spi){
-		print("igbe: SPI EEPROM access not implemented\n");
-		return 0;
-	}
-	if(eecd & (Eeszaddr|Eesz256))
-		bits = 8;
-	else
-		bits = 6;
-	sum = 0;
-
-	switch(ctlr->id){
-	default:
-		areq = 0;
-		break;
-	case i82540em:
-	case i82540eplp:
-	case i82541gi:
-	case i82541gi2:
-	case i82541pi:
-	case i82547gi:
-	case i82546gb:
-	case i82546eb:
-		areq = 1;
-		csr32w(ctlr, Eecd, eecd|Areq);
-		for(i = 0; i < 1000; i++){
-			if((eecd = csr32r(ctlr, Eecd)) & Agnt)
-				break;
-			microdelay(5);
-		}
-		if(!(eecd & Agnt)){
-			print("igbe: not granted EEPROM access\n");
-			goto release;
-		}
-		break;
-	}
-	snprint(rop, sizeof(rop), "S :%dDCc;", bits+3);
-
-	for(addr = 0; addr < 0x40; addr++){
-		/*
-		 * Read a word at address 'addr' from the Atmel AT93C46
-		 * 3-Wire Serial EEPROM or compatible. The EEPROM access is
-		 * controlled by 4 bits in Eecd. See the AT93C46 datasheet
-		 * for protocol details.
-		 */
-		if(at93c46io(ctlr, rop, (0x06<<bits)|addr) != 0){
-			print("igbe: can't set EEPROM address 0x%2.2X\n", addr);
-			goto release;
-		}
-		data = at93c46io(ctlr, ":16COc;", 0);
-		at93c46io(ctlr, "sic", 0);
-		ctlr->eeprom[addr] = data;
-		sum += data;
-		if (Debug) {
-			if(addr && ((addr & 0x07) == 0))
-				print("\n");
-			print(" %4.4ux", data);
-		}
-	}
-	if (Debug)
-		print("\n");
-release:
-	if(areq)
-		csr32w(ctlr, Eecd, eecd & ~Areq);
-	return sum;
-}
-
-static void
-detach(Ctlr *ctlr)
-{
-	int r;
-
-	/*
-	 * Perform a device reset to get the chip back to the
-	 * power-on state, followed by an EEPROM reset to read
-	 * the defaults for some internal registers.
-	 */
-	csr32w(ctlr, Imc, ~0);
-	csr32w(ctlr, Rctl, 0);
-	csr32w(ctlr, Tctl, 0);
-
-	delay(20);
-
-	csr32w(ctlr, Ctrl, Devrst);
-	/* apparently needed on multi-GHz processors to avoid infinite loops */
-	delay(1);
-	while(csr32r(ctlr, Ctrl) & Devrst)
-		;
-
-	csr32w(ctlr, Ctrlext, Eerst | csr32r(ctlr, Ctrlext));
-	delay(1);
-	while(csr32r(ctlr, Ctrlext) & Eerst)
-		;
-
-	switch(ctlr->id){
-	default:
-		break;
-	case i82540em:
-	case i82540eplp:
-	case i82541gi:
-	case i82541gi2:
-	case i82541pi:
-	case i82547gi:
-	case i82546gb:
-	case i82546eb:
-		r = csr32r(ctlr, Manc);
-		r &= ~Arpen;
-		csr32w(ctlr, Manc, r);
-		break;
-	}
-
-	csr32w(ctlr, Imc, ~0);
-	delay(1);
-	while(csr32r(ctlr, Icr))
-		;
-}
-
-static void
-igbedetach(Ether *edev)
-{
-	detach(edev->ctlr);
-}
-
-static void
-igbeshutdown(Ether* ether)
-{
-print("igbeshutdown\n");
-	igbedetach(ether);
-}
-
-static int
-igbereset(Ctlr* ctlr)
-{
-	int ctrl, i, pause, r, swdpio, txcw;
-
-	detach(ctlr);
-
-	/*
-	 * Read the EEPROM, validate the checksum
-	 * then get the device back to a power-on state.
-	 */
-	r = at93c46r(ctlr);
-	/* zero return means no SPI EEPROM access */
-	if (r != 0 && r != 0xBABA){
-		print("igbe: bad EEPROM checksum - 0x%4.4uX\n", r);
-		return -1;
-	}
-
-	/*
-	 * Snarf and set up the receive addresses.
-	 * There are 16 addresses. The first should be the MAC address.
-	 * The others are cleared and not marked valid (MS bit of Rah).
-	 */
-	if ((ctlr->id == i82546gb || ctlr->id == i82546eb) &&
-	    BUSFNO(ctlr->pcidev->tbdf) == 1)
-		ctlr->eeprom[Ea+2] += 0x100;		/* second interface */
-	for(i = Ea; i < Eaddrlen/2; i++){
-		ctlr->ra[2*i]   = ctlr->eeprom[i];
-		ctlr->ra[2*i+1] = ctlr->eeprom[i]>>8;
-	}
-	/* lan id seems to vary on 82543gc; don't use it */
-	if (ctlr->id != i82543gc) {
-		r = (csr32r(ctlr, Status) & Lanid) >> 2;
-		ctlr->ra[5] += r;		/* ea ctlr[1] = ea ctlr[0]+1 */
-	}
-	r = (ctlr->ra[3]<<24)|(ctlr->ra[2]<<16)|(ctlr->ra[1]<<8)|ctlr->ra[0];
-	csr32w(ctlr, Ral, r);
-	r = 0x80000000|(ctlr->ra[5]<<8)|ctlr->ra[4];
-	csr32w(ctlr, Rah, r);
-	for(i = 1; i < 16; i++){
-		csr32w(ctlr, Ral+i*8, 0);
-		csr32w(ctlr, Rah+i*8, 0);
-	}
-
-	/*
-	 * Clear the Multicast Table Array.
-	 * It's a 4096 bit vector accessed as 128 32-bit registers.
-	 */
-	memset(ctlr->mta, 0, sizeof(ctlr->mta));
-	for(i = 0; i < 128; i++)
-		csr32w(ctlr, Mta+i*4, 0);
-
-	/*
-	 * Just in case the Eerst didn't load the defaults
-	 * (doesn't appear to fully on the 8243GC), do it manually.
-	 */
-	if (ctlr->id == i82543gc) {
-		txcw = csr32r(ctlr, Txcw);
-		txcw &= ~(TxcwAne|TxcwPauseMASK|TxcwFd);
-		ctrl = csr32r(ctlr, Ctrl);
-		ctrl &= ~(SwdpioloMASK|Frcspd|Ilos|Lrst|Fd);
-
-		if(ctlr->eeprom[Icw1] & 0x0400){
-			ctrl |= Fd;
-			txcw |= TxcwFd;
-		}
-		if(ctlr->eeprom[Icw1] & 0x0200)
-			ctrl |= Lrst;
-		if(ctlr->eeprom[Icw1] & 0x0010)
-			ctrl |= Ilos;
-		if(ctlr->eeprom[Icw1] & 0x0800)
-			ctrl |= Frcspd;
-		swdpio = (ctlr->eeprom[Icw1] & 0x01E0)>>5;
-		ctrl |= swdpio<<SwdpioloSHIFT;
-		csr32w(ctlr, Ctrl, ctrl);
-
-		ctrl = csr32r(ctlr, Ctrlext);
-		ctrl &= ~(Ips|SwdpiohiMASK);
-		swdpio = (ctlr->eeprom[Icw2] & 0x00F0)>>4;
-		if(ctlr->eeprom[Icw1] & 0x1000)
-			ctrl |= Ips;
-		ctrl |= swdpio<<SwdpiohiSHIFT;
-		csr32w(ctlr, Ctrlext, ctrl);
-
-		if(ctlr->eeprom[Icw2] & 0x0800)
-			txcw |= TxcwAne;
-		pause = (ctlr->eeprom[Icw2] & 0x3000)>>12;
-		txcw |= pause<<TxcwPauseSHIFT;
-		switch(pause){
-		default:
-			ctlr->fcrtl = 0x00002000;
-			ctlr->fcrth = 0x00004000;
-			txcw |= TxcwAs|TxcwPs;
-			break;
-		case 0:
-			ctlr->fcrtl = 0x00002000;
-			ctlr->fcrth = 0x00004000;
-			break;
-		case 2:
-			ctlr->fcrtl = 0;
-			ctlr->fcrth = 0;
-			txcw |= TxcwAs;
-			break;
-		}
-		ctlr->txcw = txcw;
-		csr32w(ctlr, Txcw, txcw);
-	}
-	/*
-	 * Flow control - values from the datasheet.
-	 */
-	csr32w(ctlr, Fcal, 0x00C28001);
-	csr32w(ctlr, Fcah, 0x00000100);
-	csr32w(ctlr, Fct, 0x00008808);
-	csr32w(ctlr, Fcttv, 0x00000100);
-
-	csr32w(ctlr, Fcrtl, ctlr->fcrtl);
-	csr32w(ctlr, Fcrth, ctlr->fcrth);
-
-	ilock(&ctlr->imlock);
-	csr32w(ctlr, Imc, ~0);
-	ctlr->im = 0;		/* was = Lsc, which hangs some controllers */
-	csr32w(ctlr, Ims, ctlr->im);
-	iunlock(&ctlr->imlock);
-
-	if(!(csr32r(ctlr, Status) & Tbimode) && igbemii(ctlr) < 0) {
-		print("igbe: igbemii failed\n");
-		return -1;
-	}
-
-	return 0;
-}
-
-static void
-igbepci(void)
-{
-	int port, cls;
-	Pcidev *p;
-	Ctlr *ctlr;
-	static int first = 1;
-
-	if (first)
-		first = 0;
-	else
-		return;
-
-	p = nil;
-	while(p = pcimatch(p, 0, 0)){
-		if(p->ccrb != 0x02 || p->ccru != 0)
-			continue;
-
-		switch((p->did<<16)|p->vid){
-		case i82542:
-		default:
-			continue;
-
-		case (0x1001<<16)|0x8086:	/* Intel PRO/1000 F */
-			break;
-		case i82543gc:
-		case i82544ei:
-		case i82547ei:
-		case i82540em:
-		case i82540eplp:
-		case i82547gi:
-		case i82541gi:
-		case i82541gi2:
-		case i82541pi:
-		case i82546gb:
-		case i82546eb:
-			break;
-		}
-
-		/* the 82547EI is on the CSA bus, whatever that is */
-		port = upamalloc(p->mem[0].bar & ~0x0F, p->mem[0].size, 0);
-		if(port == 0){
-			print("igbe: can't map %d @ 0x%8.8luX\n",
-				p->mem[0].size, p->mem[0].bar);
-			continue;
-		}
-
-		/*
-		 * from etherga620.c:
-		 * If PCI Write-and-Invalidate is enabled set the max write DMA
-		 * value to the host cache-line size (32 on Pentium or later).
-		 */
-		if(p->pcr & MemWrInv){
-			cls = pcicfgr8(p, PciCLS) * 4;
-			if(cls != CACHELINESZ)
-				pcicfgw8(p, PciCLS, CACHELINESZ/4);
-		}
-
-		cls = pcicfgr8(p, PciCLS);
-		switch(cls){
-			default:
-				print("igbe: unexpected CLS - %d bytes\n",
-					cls*sizeof(long));
-				break;
-			case 0x00:
-			case 0xFF:
-				/* alphapc 164lx returns 0 */
-				print("igbe: unusable PciCLS: %d, using %d longs\n",
-					cls, CACHELINESZ/sizeof(long));
-				cls = CACHELINESZ/sizeof(long);
-				pcicfgw8(p, PciCLS, cls);
-				break;
-			case 0x08:
-			case 0x10:
-				break;
-		}
-
-		ctlr = malloc(sizeof(Ctlr));
-		ctlr->port = port;
-		ctlr->pcidev = p;
-		ctlr->id = (p->did<<16)|p->vid;
-		ctlr->cls = cls*4;
-		ctlr->nic = KADDR(ctlr->port);
-		if (Debug)
-			print("status0 %8.8uX\n", csr32r(ctlr, Status));
-		if(igbereset(ctlr)){
-			free(ctlr);
-			continue;
-		}
-		if (Debug)
-			print("status1 %8.8uX\n", csr32r(ctlr, Status));
-		pcisetbme(p);
-
-		if(ctlrhead != nil)
-			ctlrtail->next = ctlr;
-		else
-			ctlrhead = ctlr;
-		ctlrtail = ctlr;
-	}
-}
-
-int
-igbepnp(Ether* edev)
-{
-	int i;
-	Ctlr *ctlr;
-	uchar ea[Eaddrlen];
-
-	if(ctlrhead == nil)
-		igbepci();
-
-	/*
-	 * Any adapter matches if no edev->port is supplied,
-	 * otherwise the ports must match.
-	 */
-	for(ctlr = ctlrhead; ctlr != nil; ctlr = ctlr->next){
-		if(ctlr->active)
-			continue;
-		if(edev->port == 0 || edev->port == ctlr->port){
-			ctlr->active = 1;
-			break;
-		}
-	}
-	if(ctlr == nil)
-		return -1;
-
-	edev->ctlr = ctlr;
-	edev->port = ctlr->port;
-	edev->irq = ctlr->pcidev->intl;
-	edev->tbdf = ctlr->pcidev->tbdf;
-//	edev->mbps = 1000;
-
-	/*
-	 * Check if the adapter's station address is to be overridden.
-	 * If not, read it from the EEPROM and set in ether->ea prior to
-	 * loading the station address in the hardware.
-	 */
-	memset(ea, 0, Eaddrlen);
-	if(memcmp(ea, edev->ea, Eaddrlen) == 0){
-		for(i = 0; i < Eaddrlen/2; i++){
-			edev->ea[2*i] = ctlr->eeprom[i];
-			edev->ea[2*i+1] = ctlr->eeprom[i]>>8;
-		}
-	}
-	igbeinit(edev);
-
-	/*
-	 * Linkage to the generic ethernet driver.
-	 */
-	edev->attach = igbeattach;
-	edev->transmit = igbetransmit;
-	edev->interrupt = igbeinterrupt;
-	edev->detach = igbedetach;
-
-	return 0;
-}
--- a/os/boot/pc/ethermii.c
+++ /dev/null
@@ -1,224 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-#include "etherif.h"
-#include "ethermii.h"
-
-int
-mii(Mii* mii, int mask)
-{
-	MiiPhy *miiphy;
-	int bit, phyno, r, rmask;
-
-	/*
-	 * Probe through mii for PHYs in mask;
-	 * return the mask of those found in the current probe.
-	 * If the PHY has not already been probed, update
-	 * the Mii information.
-	 */
-	rmask = 0;
-	for(phyno = 0; phyno < NMiiPhy; phyno++){
-		bit = 1<<phyno;
-		if(!(mask & bit))
-			continue;
-		if(mii->mask & bit){
-			rmask |= bit;
-			continue;
-		}
-		if(mii->mir(mii, phyno, Bmsr) == -1)
-			continue;
-		if((miiphy = malloc(sizeof(MiiPhy))) == nil)
-			continue;
-
-		miiphy->mii = mii;
-		r = mii->mir(mii, phyno, Phyidr1);
-		miiphy->oui = (r & 0x3FFF)<<6;
-		r = mii->mir(mii, phyno, Phyidr2);
-		miiphy->oui |= r>>10;
-		miiphy->phyno = phyno;
-
-		miiphy->anar = ~0;
-		miiphy->fc = ~0;
-		miiphy->mscr = ~0;
-
-		mii->phy[phyno] = miiphy;
-		if(mii->curphy == nil)
-			mii->curphy = miiphy;
-		mii->mask |= bit;
-		mii->nphy++;
-
-		rmask |= bit;
-	}
-	return rmask;
-}
-
-int
-miimir(Mii* mii, int r)
-{
-	if(mii == nil || mii->ctlr == nil || mii->curphy == nil)
-		return -1;
-	return mii->mir(mii, mii->curphy->phyno, r);
-}
-
-int
-miimiw(Mii* mii, int r, int data)
-{
-	if(mii == nil || mii->ctlr == nil || mii->curphy == nil)
-		return -1;
-	return mii->miw(mii, mii->curphy->phyno, r, data);
-}
-
-int
-miireset(Mii* mii)
-{
-	int bmcr;
-
-	if(mii == nil || mii->ctlr == nil || mii->curphy == nil)
-		return -1;
-	bmcr = mii->mir(mii, mii->curphy->phyno, Bmcr);
-	bmcr |= BmcrR;
-	mii->miw(mii, mii->curphy->phyno, Bmcr, bmcr);
-	microdelay(1);
-
-	return 0;
-}
-
-int
-miiane(Mii* mii, int a, int p, int e)
-{
-	int anar, bmsr, mscr, r, phyno;
-
-	if(mii == nil || mii->ctlr == nil || mii->curphy == nil)
-		return -1;
-	phyno = mii->curphy->phyno;
-
-	bmsr = mii->mir(mii, phyno, Bmsr);
-	if(!(bmsr & BmsrAna))
-		return -1;
-
-	if(a != ~0)
-		anar = (AnaTXFD|AnaTXHD|Ana10FD|Ana10HD) & a;
-	else if(mii->curphy->anar != ~0)
-		anar = mii->curphy->anar;
-	else{
-		anar = mii->mir(mii, phyno, Anar);
-		anar &= ~(AnaAP|AnaP|AnaT4|AnaTXFD|AnaTXHD|Ana10FD|Ana10HD);
-		if(bmsr & Bmsr10THD)
-			anar |= Ana10HD;
-		if(bmsr & Bmsr10TFD)
-			anar |= Ana10FD;
-		if(bmsr & Bmsr100TXHD)
-			anar |= AnaTXHD;
-		if(bmsr & Bmsr100TXFD)
-			anar |= AnaTXFD;
-	}
-	mii->curphy->anar = anar;
-
-	if(p != ~0)
-		anar |= (AnaAP|AnaP) & p;
-	else if(mii->curphy->fc != ~0)
-		anar |= mii->curphy->fc;
-	mii->curphy->fc = (AnaAP|AnaP) & anar;
-
-	if(bmsr & BmsrEs){
-		mscr = mii->mir(mii, phyno, Mscr);
-		mscr &= ~(Mscr1000TFD|Mscr1000THD);
-		if(e != ~0)
-			mscr |= (Mscr1000TFD|Mscr1000THD) & e;
-		else if(mii->curphy->mscr != ~0)
-			mscr = mii->curphy->mscr;
-		else{
-			r = mii->mir(mii, phyno, Esr);
-			if(r & Esr1000THD)
-				mscr |= Mscr1000THD;
-			if(r & Esr1000TFD)
-				mscr |= Mscr1000TFD;
-		}
-		mii->curphy->mscr = mscr;
-		mii->miw(mii, phyno, Mscr, mscr);
-	}
-	mii->miw(mii, phyno, Anar, anar);
-
-	r = mii->mir(mii, phyno, Bmcr);
-	if(!(r & BmcrR)){
-		r |= BmcrAne|BmcrRan;
-		mii->miw(mii, phyno, Bmcr, r);
-	}
-
-	return 0;
-}
-
-int
-miistatus(Mii* mii)
-{
-	MiiPhy *phy;
-	int anlpar, bmsr, p, r, phyno;
-
-	if(mii == nil || mii->ctlr == nil || mii->curphy == nil)
-		return -1;
-	phy = mii->curphy;
-	phyno = phy->phyno;
-
-	/*
-	 * Check Auto-Negotiation is complete and link is up.
-	 * (Read status twice as the Ls bit is sticky).
-	 */
-	bmsr = mii->mir(mii, phyno, Bmsr);
-	if(!(bmsr & (BmsrAnc|BmsrAna)))
-		return -1;
-
-	bmsr = mii->mir(mii, phyno, Bmsr);
-	if(!(bmsr & BmsrLs)){
-		phy->link = 0;
-		return -1;
-	}
-
-	phy->speed = phy->fd = phy->rfc = phy->tfc = 0;
-	if(phy->mscr){
-		r = mii->mir(mii, phyno, Mssr);
-		if((phy->mscr & Mscr1000TFD) && (r & Mssr1000TFD)){
-			phy->speed = 1000;
-			phy->fd = 1;
-		}
-		else if((phy->mscr & Mscr1000THD) && (r & Mssr1000THD))
-			phy->speed = 1000;
-	}
-
-	anlpar = mii->mir(mii, phyno, Anlpar);
-	if(phy->speed == 0){
-		r = phy->anar & anlpar;
-		if(r & AnaTXFD){
-			phy->speed = 100;
-			phy->fd = 1;
-		}
-		else if(r & AnaTXHD)
-			phy->speed = 100;
-		else if(r & Ana10FD){
-			phy->speed = 10;
-			phy->fd = 1;
-		}
-		else if(r & Ana10HD)
-			phy->speed = 10;
-	}
-	if(phy->speed == 0)
-		return -1;
-
-	if(phy->fd){
-		p = phy->fc;
-		r = anlpar & (AnaAP|AnaP);
-		if(p == AnaAP && r == (AnaAP|AnaP))
-			phy->tfc = 1;
-		else if(p == (AnaAP|AnaP) && r == AnaAP)
-			phy->rfc = 1;
-		else if((p & AnaP) && (r & AnaP))
-			phy->rfc = phy->tfc = 1;
-	}
-
-	phy->link = 1;
-
-	return 0;
-}
--- a/os/boot/pc/ethermii.h
+++ /dev/null
@@ -1,116 +1,0 @@
-typedef struct Mii Mii;
-typedef struct MiiPhy MiiPhy;
-
-enum {					/* registers */
-	Bmcr		= 0x00,		/* Basic Mode Control */
-	Bmsr		= 0x01,		/* Basic Mode Status */
-	Phyidr1		= 0x02,		/* PHY Identifier #1 */
-	Phyidr2		= 0x03,		/* PHY Identifier #2 */
-	Anar		= 0x04,		/* Auto-Negotiation Advertisement */
-	Anlpar		= 0x05,		/* AN Link Partner Ability */
-	Aner		= 0x06,		/* AN Expansion */
-	Annptr		= 0x07,		/* AN Next Page TX */
-	Annprr		= 0x08,		/* AN Next Page RX */
-	Mscr		= 0x09,		/* MASTER-SLAVE Control */
-	Mssr		= 0x0A,		/* MASTER-SLAVE Status */
-	Esr		= 0x0F,		/* Extended Status */
-
-	NMiiPhyr	= 32,
-	NMiiPhy		= 32,
-};
-
-enum {					/* Bmcr */
-	BmcrSs1		= 0x0040,	/* Speed Select[1] */
-	BmcrCte		= 0x0080,	/* Collision Test Enable */
-	BmcrDm		= 0x0100,	/* Duplex Mode */
-	BmcrRan		= 0x0200,	/* Restart Auto-Negotiation */
-	BmcrI		= 0x0400,	/* Isolate */
-	BmcrPd		= 0x0800,	/* Power Down */
-	BmcrAne		= 0x1000,	/* Auto-Negotiation Enable */
-	BmcrSs0		= 0x2000,	/* Speed Select[0] */
-	BmcrLe		= 0x4000,	/* Loopback Enable */
-	BmcrR		= 0x8000,	/* Reset */
-};
-
-enum {					/* Bmsr */
-	BmsrEc		= 0x0001,	/* Extended Capability */
-	BmsrJd		= 0x0002,	/* Jabber Detect */
-	BmsrLs		= 0x0004,	/* Link Status */
-	BmsrAna		= 0x0008,	/* Auto-Negotiation Ability */
-	BmsrRf		= 0x0010,	/* Remote Fault */
-	BmsrAnc		= 0x0020,	/* Auto-Negotiation Complete */
-	BmsrPs		= 0x0040,	/* Preamble Suppression Capable */
-	BmsrEs		= 0x0100,	/* Extended Status */
-	Bmsr100T2HD	= 0x0200,	/* 100BASE-T2 HD Capable */
-	Bmsr100T2FD	= 0x0400,	/* 100BASE-T2 FD Capable */
-	Bmsr10THD	= 0x0800,	/* 100BASE-T HD Capable */
-	Bmsr10TFD	= 0x1000,	/* 10BASE-T FD Capable */
-	Bmsr100TXHD	= 0x2000,	/* 100BASE-TX HD Capable */
-	Bmsr100TXFD	= 0x4000,	/* 100BASE-TX FD Capable */
-	Bmsr100T4	= 0x8000,	/* 100BASE-T4 Capable */
-};
-
-enum {					/* Anar/Anlpar */
-	Ana10HD		= 0x0020,	/* Advertise 10BASE-T */
-	Ana10FD		= 0x0040,	/* Advertise 10BASE-T FD */
-	AnaTXHD		= 0x0080,	/* Advertise 100BASE-TX */
-	AnaTXFD		= 0x0100,	/* Advertise 100BASE-TX FD */
-	AnaT4		= 0x0200,	/* Advertise 100BASE-T4 */
-	AnaP		= 0x0400,	/* Pause */
-	AnaAP		= 0x0800,	/* Asymmetrical Pause */
-	AnaRf		= 0x2000,	/* Remote Fault */
-	AnaAck		= 0x4000,	/* Acknowledge */
-	AnaNp		= 0x8000,	/* Next Page Indication */
-};
-
-enum {					/* Mscr */
-	Mscr1000THD	= 0x0100,	/* Advertise 1000BASE-T HD */
-	Mscr1000TFD	= 0x0200,	/* Advertise 1000BASE-T FD */
-};
-
-enum {					/* Mssr */
-	Mssr1000THD	= 0x0400,	/* Link Partner 1000BASE-T HD able */
-	Mssr1000TFD	= 0x0800,	/* Link Partner 1000BASE-T FD able */
-};
-
-enum {					/* Esr */
-	Esr1000THD	= 0x1000,	/* 1000BASE-T HD Capable */
-	Esr1000TFD	= 0x2000,	/* 1000BASE-T FD Capable */
-	Esr1000XHD	= 0x4000,	/* 1000BASE-X HD Capable */
-	Esr1000XFD	= 0x8000,	/* 1000BASE-X FD Capable */
-};
-
-typedef struct Mii {
-	Lock;
-	int	nphy;
-	int	mask;
-	MiiPhy*	phy[NMiiPhy];
-	MiiPhy*	curphy;
-
-	void*	ctlr;
-	int	(*mir)(Mii*, int, int);
-	int	(*miw)(Mii*, int, int, int);
-} Mii;
-
-typedef struct MiiPhy {
-	Mii*	mii;
-	int	oui;
-	int	phyno;
-
-	int	anar;
-	int	fc;
-	int	mscr;
-
-	int	link;
-	int	speed;
-	int	fd;
-	int	rfc;
-	int	tfc;
-};
-
-extern int mii(Mii*, int);
-extern int miiane(Mii*, int, int, int);
-extern int miimir(Mii*, int);
-extern int miimiw(Mii*, int, int);
-extern int miireset(Mii*);
-extern int miistatus(Mii*);
--- a/os/boot/pc/etherrhine.c
+++ /dev/null
@@ -1,657 +1,0 @@
-/*
-	Via Rhine driver, written for VT6102.
-	Uses the ethermii to control PHY.
-
-	Currently always copies on both, tx and rx.
-	rx side could be copy-free, and tx-side might be made
-	(almost) copy-free by using (possibly) two descriptors (if it allows
-	arbitrary tx lengths, which it should..): first for alignment and
-	second for rest of the frame. Rx-part should be worth doing.
- */
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-typedef struct QLock { int r; } QLock;
-#define qlock(i)	while(0)
-#define qunlock(i)	while(0)
-#define iprint		print
-
-#include "etherif.h"
-#include "ethermii.h"
-
-enum {
-	Ntxd = 4,
-	Nrxd = 4,
-	Nwait = 50,
-	BIGSTR = 8192,
-};
-
-typedef struct Desc Desc;
-typedef struct Ctlr Ctlr;
-
-struct Desc {
-	ulong	stat;
-	ulong	size;
-	ulong	addr;
-	ulong	next;
-	char	*buf;
-	ulong	pad[3];
-};
-
-struct Ctlr {
-	Pcidev	*pci;
-	int	attached;
-	int	txused;
-	int	txhead;
-	int	txtail;
-	int	rxtail;
-	ulong	port;
-
-	Mii	mii;
-
-	Desc	*txd;		/* wants to be aligned on 16-byte boundary */
-	Desc	*rxd;
-
-	QLock	attachlck;
-	Lock	tlock;
-};
-
-#define ior8(c, r)	(inb((c)->port+(r)))
-#define iow8(c, r, b)	(outb((c)->port+(r), (int)(b)))
-#define ior16(c, r)	(ins((c)->port+(r)))
-#define ior32(c, r)	(inl((c)->port+(r)))
-#define iow16(c, r, w)	(outs((c)->port+(r), (ushort)(w)))
-#define iow32(c, r, l)	(outl((c)->port+(r), (ulong)(l)))
-
-/* names used everywhere else */
-#define csr8r ior8
-#define csr8w iow8
-#define csr16r ior16
-#define csr16w iow16
-#define csr32r ior32
-#define csr32w iow32
-
-enum Regs {
-	Eaddr		= 0x0,
-	Rcr		= 0x6,
-	Tcr		= 0x7,
-	Cr		= 0x8,
-	Isr		= 0xc,
-	Imr		= 0xe,
-	McastAddr	= 0x10,
-	RxdAddr		= 0x18,
-	TxdAddr		= 0x1C,
-	Bcr0		= 0x6E,		/* Bus Control */
-	Bcr1		= 0x6F,
-	RhineMiiPhy	= 0x6C,
-	RhineMiiSr	= 0x6D,
-	RhineMiiCr	= 0x70,
-	RhineMiiAddr	= 0x71,
-	RhineMiiData	= 0x72,
-	Eecsr		= 0x74,
-	ConfigB		= 0x79,
-	ConfigD		= 0x7B,
-	MiscCr		= 0x80,
-	HwSticky	= 0x83,
-	MiscIsr		= 0x84,
-	MiscImr		= 0x86,
-	WolCrSet	= 0xA0,
-	WolCfgSet	= 0xA1,
-	WolCgSet	= 0xA3,
-	WolCrClr	= 0xA4,
-	PwrCfgClr	= 0xA5,
-	WolCgClr	= 0xA7,
-};
-
-enum {					/* Rcr */
-	Sep		= 0x01,		/* Accept Error Packets */
-	Ar		= 0x02,		/* Accept Small Packets */
-	Am		= 0x04,		/* Accept Multicast */
-	Ab		= 0x08,		/* Accept Broadcast */
-	RxBcast		= Ab,
-	Prom		= 0x10,		/* Accept Physical Address Packets */
-	RxProm		= Prom,
-	RrftMASK	= 0xE0,		/* Receive FIFO Threshold */
-	RrftSHIFT	= 5,
-	Rrft64		= 0<<RrftSHIFT,
-	Rrft32		= 1<<RrftSHIFT,
-	Rrft128		= 2<<RrftSHIFT,
-	Rrft256		= 3<<RrftSHIFT,
-	Rrft512		= 4<<RrftSHIFT,
-	Rrft768		= 5<<RrftSHIFT,
-	Rrft1024	= 6<<RrftSHIFT,
-	RrftSAF		= 7<<RrftSHIFT,
-};
-
-enum {					/* Tcr */
-	Lb0		= 0x02,		/* Loopback Mode */
-	Lb1		= 0x04,
-	Ofset		= 0x08,		/* Back-off Priority Selection */
-	RtsfMASK	= 0xE0,		/* Transmit FIFO Threshold */
-	RtsfSHIFT	= 5,
-	Rtsf128		= 0<<RtsfSHIFT,
-	Rtsf256		= 1<<RtsfSHIFT,
-	Rtsf512		= 2<<RtsfSHIFT,
-	Rtsf1024	= 3<<RtsfSHIFT,
-	RtsfSAF		= 7<<RtsfSHIFT,
-};
-
-enum Crbits {
-	Init		= 1<<0,
-	Start		= 1<<1,
-	Stop		= 1<<2,
-	RxOn		= 1<<3,
-	TxOn		= 1<<4,
-	Tdmd		= 1<<5,
-	Rdmd		= 1<<6,
-	EarlyRx		= 1<<8,
-	Reserved0	= 1<<9,
-	FullDuplex	= 1<<10,
-	NoAutoPoll	= 1<<11,
-	Reserved1	= 1<<12,
-	Tdmd1		= 1<<13,
-	Rdmd1		= 1<<14,
-	Reset		= 1<<15,
-};
-
-enum Isrbits {
-	RxOk		= 1<<0,
-	TxOk		= 1<<1,
-	RxErr		= 1<<2,
-	TxErr		= 1<<3,
-	TxBufUdf	= 1<<4,
-	RxBufLinkErr	= 1<<5,
-	BusErr		= 1<<6,
-	CrcOvf		= 1<<7,
-	EarlyRxInt	= 1<<8,
-	TxFifoUdf	= 1<<9,
-	RxFifoOvf	= 1<<10,
-	TxPktRace	= 1<<11,
-	NoRxbuf		= 1<<12,
-	TxCollision	= 1<<13,
-	PortCh		= 1<<14,
-	GPInt		= 1<<15,
-};
-
-enum {					/* Bcr0 */
-	DmaMASK		= 0x07,		/* DMA Length */
-	DmaSHIFT	= 0,
-	Dma32		= 0<<DmaSHIFT,
-	Dma64		= 1<<DmaSHIFT,
-	Dma128		= 2<<DmaSHIFT,
-	Dma256		= 3<<DmaSHIFT,
-	Dma512		= 4<<DmaSHIFT,
-	Dma1024		= 5<<DmaSHIFT,
-	DmaSAF		= 7<<DmaSHIFT,
-	CrftMASK	= 0x38,		/* Rx FIFO Threshold */
-	CrftSHIFT	= 3,
-	Crft64		= 1<<CrftSHIFT,
-	Crft128		= 2<<CrftSHIFT,
-	Crft256		= 3<<CrftSHIFT,
-	Crft512		= 4<<CrftSHIFT,
-	Crft1024	= 5<<CrftSHIFT,
-	CrftSAF		= 7<<CrftSHIFT,
-	Extled		= 0x40,		/* Extra LED Support Control */
-	Med2		= 0x80,		/* Medium Select Control */
-};
-
-enum {					/* Bcr1 */
-	PotMASK		= 0x07,		/* Polling Timer Interval */
-	PotSHIFT	= 0,
-	CtftMASK	= 0x38,		/* Tx FIFO Threshold */
-	CtftSHIFT	= 3,
-	Ctft64		= 1<<CtftSHIFT,
-	Ctft128		= 2<<CtftSHIFT,
-	Ctft256		= 3<<CtftSHIFT,
-	Ctft512		= 4<<CtftSHIFT,
-	Ctft1024	= 5<<CtftSHIFT,
-	CtftSAF		= 7<<CtftSHIFT,
-};
-
-
-enum Eecsrbits {
-	EeAutoLoad	= 1<<5,
-};
-
-enum Descbits {
-	OwnNic		= 1<<31,	/* stat */
-	TxAbort		= 1<<8,		/* stat */
-	TxError		= 1<<15,	/* stat */
-	RxChainbuf	= 1<<10,	/* stat */
-	RxChainStart	= 1<<9,		/* stat */
-	RxChainEnd	= 1<<8,		/* stat */
-	Chainbuf	= 1<<15,	/* size rx & tx*/
-	TxDisableCrc	= 1<<16,	/* size */
-	TxChainStart	= 1<<21,	/* size */
-	TxChainEnd	= 1<<22,	/* size */
-	TxInt		= 1<<23,	/* size */
-};
-
-enum RhineMiiCrbits {
-	Mdc	= 1<<0,
-	Mdi	= 1<<1,
-	Mdo	= 1<<2,
-	Mdout	= 1<<3,
-	Mdpm	= 1<<4,
-	Wcmd	= 1<<5,
-	Rcmd	= 1<<6,
-	Mauto	= 1<<7,
-};
-
-static void
-attach(Ether *edev)
-{
-	Ctlr *ctlr;
-	Desc *txd, *rxd, *td, *rd;
-	Mii *mi;
-	MiiPhy *phy;
-	int i, s;
-
-	ctlr = edev->ctlr;
-	qlock(&ctlr->attachlck);
-	if (ctlr->attached == 0) {
-		txd = ctlr->txd;
-		rxd = ctlr->rxd;
-		for (i = 0; i < Ntxd; ++i) {
-			td = &txd[i];
-			td->next = PCIWADDR(&txd[(i+1) % Ntxd]);
-			td->buf = xspanalloc(sizeof(Etherpkt)+4, 4, 0);
-			td->addr = PCIWADDR(td->buf);
-			td->size = 0;
-			coherence();
-			td->stat = 0;
-		}
-		for (i = 0; i < Nrxd; ++i) {
-			rd = &rxd[i];
-			rd->next = PCIWADDR(&rxd[(i+1) % Nrxd]);
-			rd->buf = xspanalloc(sizeof(Etherpkt)+4, 4, 0);
-			rd->addr = PCIWADDR(rd->buf);
-			rd->size = sizeof(Etherpkt)+4;
-			coherence();
-			rd->stat = OwnNic;
-		}
-
-		ctlr->txhead = ctlr->txtail = ctlr->rxtail = 0;
-		mi = &ctlr->mii;
-		miistatus(mi);
-		phy = mi->curphy;
-		s = splhi();
-		iow32(ctlr, TxdAddr, PCIWADDR(&txd[0]));
-		iow32(ctlr, RxdAddr, PCIWADDR(&rxd[0]));
-		iow16(ctlr, Cr, (phy->fd? FullDuplex: 0) | NoAutoPoll | TxOn |
-			RxOn | Start | Rdmd);
-		iow16(ctlr, Isr, 0xFFFF);
-		iow16(ctlr, Imr, 0xFFFF);
-		iow8(ctlr, MiscIsr, 0xFF);
-		iow8(ctlr, MiscImr, ~(3<<5));
-		splx(s);
-		ctlr->attached = 1;
-	}
-	qunlock(&ctlr->attachlck);
-}
-
-static void
-txstart(Ether *edev)
-{
-	Ctlr *ctlr;
-	Desc *txd, *td;
-	int i, txused, n;
-	RingBuf *tb;
-
-	ctlr = edev->ctlr;
-	txd = ctlr->txd;
-	i = ctlr->txhead;
-	n = 0;
-	for (txused = ctlr->txused; txused < Ntxd; txused++) {
-		tb = &edev->tb[edev->ti];
-		if(tb->owner != Interface)
-			break;
-
-		td = &txd[i];
-		memmove(td->buf, tb->pkt, tb->len);
-		/* could reduce number of intrs here */
-		td->size = tb->len | TxChainStart | TxChainEnd | TxInt;
-		coherence();
-		td->stat = OwnNic;
-		i = (i + 1) % Ntxd;
-		n++;
-
-		tb->owner = Host;
-		edev->ti = NEXT(edev->ti, edev->ntb);
-	}
-	if (n)
-		iow16(ctlr, Cr, ior16(ctlr, Cr) | Tdmd);
-
-	ctlr->txhead = i;
-	ctlr->txused = txused;
-}
-
-static void
-transmit(Ether *edev)
-{
-	Ctlr *ctlr;
-
-	ctlr = edev->ctlr;
-	ilock(&ctlr->tlock);
-	txstart(edev);
-	iunlock(&ctlr->tlock);
-}
-
-static void
-txcomplete(Ether *edev)
-{
-	Ctlr *ctlr;
-	Desc *txd, *td;
-	int i, txused;
-	ulong stat;
-
-	ctlr = edev->ctlr;
- 	txd = ctlr->txd;
-	i = ctlr->txtail;
-	for (txused = ctlr->txused; txused > 0; txused--) {
-		td = &txd[i];
-		stat = td->stat;
-		if (stat & OwnNic)
-			break;
-		i = (i + 1) % Ntxd;
-	}
-	ctlr->txused = txused;
-	ctlr->txtail = i;
-
-	if (txused <= Ntxd/2)
-		txstart(edev);
-}
-
-static void
-interrupt(Ureg *, void *arg)
-{
-	Ether *edev;
-	Ctlr *ctlr;
-	RingBuf *rb;
-	ushort  isr, misr;
-	ulong stat;
-	Desc *rxd, *rd;
-	int i, n, size;
-
-	edev = (Ether*)arg;
-	ctlr = edev->ctlr;
-	iow16(ctlr, Imr, 0);
-	isr = ior16(ctlr, Isr);
-	iow16(ctlr, Isr, 0xFFFF);
-	/* don't care about used defined intrs */
-	misr = ior16(ctlr, MiscIsr) & ~(3<<5);
-
-	if (isr & RxOk) {
-		rxd = ctlr->rxd;
-		i = ctlr->rxtail;
-
-		n = 0;
-		while ((rxd[i].stat & OwnNic) == 0) {
-			rd = &rxd[i];
-			stat = rd->stat;
-			if (stat & 0xFF)
-				iprint("rx: %lux\n", stat & 0xFF);
-			size = ((rd->stat>>16) & (2048-1)) - 4;
-
-			rb = &edev->rb[edev->ri];
-			if(rb->owner == Interface){
-				rb->owner = Host;
-				rb->len = size;
-				memmove(rb->pkt, rd->buf, size);
-				edev->ri = NEXT(edev->ri, edev->nrb);
-			}
-
-			rd->size = sizeof(Etherpkt)+4;
-			coherence();
-			rd->stat = OwnNic;
-			i = (i + 1) % Nrxd;
-			n++;
-		}
-		if (n)
-			iow16(ctlr, Cr, ior16(ctlr, Cr) | Rdmd);
-		ctlr->rxtail = i;
-		isr &= ~RxOk;
-	}
-	if (isr & TxOk) {
-		txcomplete(edev);
-		isr &= ~TxOk;
-	}
-	if (isr | misr)
-		iprint("etherrhine: unhandled irq(s). isr:%x misr:%x\n",
-			isr, misr);
-	iow16(ctlr, Imr, 0xFFFF);
-}
-
-static int
-miiread(Mii *mii, int phy, int reg)
-{
-	Ctlr *ctlr;
-	int n;
-
-	ctlr = mii->ctlr;
-
-	n = Nwait;
-	while (n-- && ior8(ctlr, RhineMiiCr) & (Rcmd | Wcmd))
-		microdelay(1);
-	if (n == Nwait)
-		iprint("etherrhine: miiread: timeout\n");
-
-	iow8(ctlr, RhineMiiCr, 0);
-	iow8(ctlr, RhineMiiPhy, phy);
-	iow8(ctlr, RhineMiiAddr, reg);
-	iow8(ctlr, RhineMiiCr, Rcmd);
-
-	n = Nwait;
-	while (n-- && ior8(ctlr, RhineMiiCr) & Rcmd)
-		microdelay(1);
-	if (n == Nwait)
-		iprint("etherrhine: miiread: timeout\n");
-
-	return ior16(ctlr, RhineMiiData);
-}
-
-static int
-miiwrite(Mii *mii, int phy, int reg, int data)
-{
-	int n;
-	Ctlr *ctlr;
-
-	ctlr = mii->ctlr;
-
-	n = Nwait;
-	while (n-- && ior8(ctlr, RhineMiiCr) & (Rcmd | Wcmd))
-		microdelay(1);
-	if (n == Nwait)
-		iprint("etherrhine: miiwrite: timeout\n");
-
-	iow8(ctlr, RhineMiiCr, 0);
-	iow8(ctlr, RhineMiiPhy, phy);
-	iow8(ctlr, RhineMiiAddr, reg);
-	iow16(ctlr, RhineMiiData, data);
-	iow8(ctlr, RhineMiiCr, Wcmd);
-
-	n = Nwait;
-	while (n-- && ior8(ctlr, RhineMiiCr) & Wcmd)
-		microdelay(1);
-	if (n == Nwait)
-		iprint("etherrhine: miiwrite: timeout\n");
-
-	return 0;
-}
-
-static void
-reset(Ctlr* ctlr)
-{
-	int r, timeo;
-
-	/*
-	 * Soft reset the controller.
-	 */
-	csr16w(ctlr, Cr, Stop);
-	csr16w(ctlr, Cr, Stop|Reset);
-	for(timeo = 0; timeo < 10000; timeo++){
-		if(!(csr16r(ctlr, Cr) & Reset))
-			break;
-		microdelay(1);
-	}
-	if(timeo >= 1000)
-		return;
-
-	/*
-	 * Load the MAC address into the PAR[01]
-	 * registers.
-	 */
-	r = csr8r(ctlr, Eecsr);
-	csr8w(ctlr, Eecsr, EeAutoLoad|r);
-	for(timeo = 0; timeo < 100; timeo++){
-		if(!(csr8r(ctlr, Cr) & EeAutoLoad))
-			break;
-		microdelay(1);
-	}
-	if(timeo >= 100)
-		return;
-
-	/*
-	 * Configure DMA and Rx/Tx thresholds.
-	 * If the Rx/Tx threshold bits in Bcr[01] are 0 then
-	 * the thresholds are determined by Rcr/Tcr.
-	 */
-	r = csr8r(ctlr, Bcr0) & ~(CrftMASK|DmaMASK);
-	csr8w(ctlr, Bcr0, r|Crft64|Dma64);
-	r = csr8r(ctlr, Bcr1) & ~CtftMASK;
-	csr8w(ctlr, Bcr1, r|Ctft64);
-
-	r = csr8r(ctlr, Rcr) & ~(RrftMASK|Prom|Ar|Sep);
-	csr8w(ctlr, Rcr, r|Ab|Am);
-
-	r = csr8r(ctlr, Tcr) & ~(RtsfMASK|Ofset|Lb1|Lb0);
-	csr8w(ctlr, Tcr, r);
-}
-
-static void
-detach(Ether* edev)
-{
-	reset(edev->ctlr);
-}
-
-static void
-init(Ether *edev)
-{
-	Ctlr *ctlr;
-	int i;
-
-	ctlr = edev->ctlr;
-	ilock(&ctlr->tlock);
-
-	pcisetbme(ctlr->pci);
-	reset(ctlr);
-
-	iow8(ctlr, Eecsr, ior8(ctlr, Eecsr) | EeAutoLoad);
-	for (i = 0; i < Nwait; ++i) {
-		if ((ior8(ctlr, Eecsr) & EeAutoLoad) == 0)
-			break;
-		delay(5);
-	}
-	if (i >= Nwait)
-		iprint("etherrhine: eeprom autoload timeout\n");
-
-	for (i = 0; i < Eaddrlen; ++i)
-		edev->ea[i] = ior8(ctlr, Eaddr + i);
-
-	ctlr->mii.mir = miiread;
-	ctlr->mii.miw = miiwrite;
-	ctlr->mii.ctlr = ctlr;
-
-	if(mii(&ctlr->mii, ~0) == 0 || ctlr->mii.curphy == nil){
-		iunlock(&ctlr->tlock);
-		iprint("etherrhine: init mii failure\n");
-		return;
-	}
-	for (i = 0; i < NMiiPhy; ++i)
-		if (ctlr->mii.phy[i])
-			if (ctlr->mii.phy[i]->oui != 0xFFFFF)
-				ctlr->mii.curphy = ctlr->mii.phy[i];
-	miistatus(&ctlr->mii);
-
-	iow16(ctlr, Imr, 0);
-	iow16(ctlr, Cr, ior16(ctlr, Cr) | Stop);
-
-	iunlock(&ctlr->tlock);
-}
-
-static Pcidev *
-rhinematch(ulong)
-{
-	static int nrhines = 0;
-	int nfound = 0;
-	Pcidev *p = nil;
-
-	while(p = pcimatch(p, 0x1106, 0)){
-		if(p->ccrb != Pcibcnet || p->ccru != Pciscether)
-			continue;
-		switch((p->did<<16)|p->vid){
-		default:
-			continue;
-		case (0x3053<<16)|0x1106:	/* Rhine III vt6105m (Soekris) */
-		case (0x3065<<16)|0x1106:	/* Rhine II */
-		case (0x3106<<16)|0x1106:	/* Rhine III */
-			if (++nfound > nrhines) {
-				nrhines++;
-				return p;
-			}
-			break;
-		}
-	}
-	return p;
-}
-
-int
-rhinepnp(Ether *edev)
-{
-	Pcidev *p;
-	Ctlr *ctlr;
-	ulong port;
-
-	if (edev->attach)
-		return 0;
-	p = rhinematch(edev->port);
-	if (p == nil)
-		return -1;
-
-	port = p->mem[0].bar & ~1;
-
-	if ((ctlr = malloc(sizeof(Ctlr))) == nil) {
-		print("etherrhine: couldn't allocate memory for ctlr\n");
-		return -1;
-	}
-	memset(ctlr, 0, sizeof(Ctlr));
-	ctlr->txd = xspanalloc(sizeof(Desc) * Ntxd, 16, 0);
-	ctlr->rxd = xspanalloc(sizeof(Desc) * Nrxd, 16, 0);
-
-	ctlr->pci = p;
-	ctlr->port = port;
-
-	edev->ctlr = ctlr;
-	edev->port = ctlr->port;
-	edev->irq = p->intl;
-	edev->tbdf = p->tbdf;
-
-	init(edev);
-
-	edev->attach = attach;
-	edev->transmit = transmit;
-	edev->interrupt = interrupt;
-	edev->detach = detach;
-
-	return 0;
-}
-
-int
-vt6102pnp(Ether *edev)
-{
-	return rhinepnp(edev);
-}
--- a/os/boot/pc/fns.h
+++ /dev/null
@@ -1,175 +1,0 @@
-void	aamloop(int);
-void	addconf(char*, ...);
-Alarm*	alarm(int, void (*)(Alarm*), void*);
-void	alarminit(void);
-Block*	allocb(int);
-void	apminit(void);
-int	biosboot(int dev, char *file, Boot *b);
-void*	biosgetfspart(int i, char *name, int chatty);
-void	biosinitdev(int i, char *name);
-int	biosinit(void);
-void	biosprintbootdevs(int dev);
-void	biosprintdevs(int i);
-int	bootpboot(int, char*, Boot*);
-int	bootpass(Boot*, void*, int);
-void	cancel(Alarm*);
-int	cdinit(void);
-void	check(char*);
-void	cgascreenputs(char*, int);
-int	cistrcmp(char*, char*);
-int	cistrncmp(char*, char*, int);
-void	changeconf(char*, ...);
-void	checkalarms(void);
-void	clockinit(void);
-#define coherence()	mb386()
-void	consdrain(void);
-void	consinit(char*, char*);
-void	consputs(char*, int);
-void	delay(int);
-uchar*	etheraddr(int);
-int	etherinit(void);
-void	etherinitdev(int, char*);
-void	etherprintdevs(int);
-int	etherrxflush(int);
-int	etherrxpkt(int, Etherpkt*, int);
-int	ethertxpkt(int, Etherpkt*, int, int);
-#define	evenaddr(x)		/* 386 doesn't care */
-int	floppyboot(int, char*, Boot*);
-int	floppyinit(void);
-void	floppyinitdev(int, char*);
-void	floppyprintdevs(int);
-void*	floppygetfspart(int, char*, int);
-void	freeb(Block*);
-char*	getconf(char*);
-ulong	getcr0(void);
-ulong	getcr2(void);
-ulong	getcr3(void);
-ulong	getcr4(void);
-int	getfields(char*, char**, int, char);
-int	getstr(char*, char*, int, char*, int);
-int	gunzip(uchar*, int, uchar*, int);
-void	i8042a20(void);
-void	i8042init(void);
-void	i8042reset(void);
-void*	ialloc(ulong, int);
-void	idle(void);
-void	ilock(Lock*);
-int	inb(int);
-ushort	ins(int);
-ulong	inl(int);
-void	insb(int, void*, int);
-void	inss(int, void*, int);
-void	insl(int, void*, int);
-#define ioalloc(addr, len, align, name)	(addr)
-#define iofree(addr)
-void	iunlock(Lock*);
-int	isaconfig(char*, int, ISAConf*);
-void	kbdinit(void);
-void	kbdchar(int);
-void	machinit(void);
-void	mb386(void);
-void	meminit(ulong);
-void	microdelay(int);
-void	mmuinit(void);
-#define	nelem(x)	(sizeof(x)/sizeof(x[0]))
-char*	nextelem(char*, char*);
-uchar	nvramread(int);
-void	outb(int, int);
-void	outs(int, ushort);
-void	outl(int, ulong);
-void	outsb(int, void*, int);
-void	outss(int, void*, int);
-void	outsl(int, void*, int);
-void	panic(char*, ...);
-ulong	pcibarsize(Pcidev*, int);
-int	pcicfgr8(Pcidev*, int);
-int	pcicfgr16(Pcidev*, int);
-int	pcicfgr32(Pcidev*, int);
-void	pcicfgw8(Pcidev*, int, int);
-void	pcicfgw16(Pcidev*, int, int);
-void	pcicfgw32(Pcidev*, int, int);
-void	pciclrbme(Pcidev*);
-void	pciclrioe(Pcidev*);
-void	pciclrmwi(Pcidev*);
-int	pcigetpms(Pcidev*);
-void	pcihinv(Pcidev*);
-Pcidev*	pcimatch(Pcidev*, int, int);
-uchar	pciintl(Pcidev *);
-uchar	pciipin(Pcidev *, uchar);
-void	pcireset(void);
-void	pcisetbme(Pcidev*);
-void	pcisetioe(Pcidev*);
-void	pcisetmwi(Pcidev*);
-int	pcisetpms(Pcidev*, int);
-void	pcmcisread(PCMslot*);
-int	pcmcistuple(int, int, int, void*, int);
-PCMmap*	pcmmap(int, ulong, int, int);
-int	pcmspecial(char*, ISAConf*);
-void	pcmspecialclose(int);
-void	pcmunmap(int, PCMmap*);
-void	ptcheck(char*);
-void	putcr3(ulong);
-void	putidt(Segdesc*, int);
-void*	pxegetfspart(int, char*, int);
-void	qinit(IOQ*);
-void	readlsconf(void);
-void	sdaddconf(int);
-int	sdboot(int, char*, Boot*);
-void	sdcheck(char*);
-void*	sdgetfspart(int, char*, int);
-int	sdinit(void);
-void	sdinitdev(int, char*);
-void	sdprintdevs(int);
-int	sdsetpart(int, char*);
-void	setvec(int, void (*)(Ureg*, void*), void*);
-int	splhi(void);
-int	spllo(void);
-void	splx(int);
-void	trapinit(void);
-void	trapdisable(void);
-void	trapenable(void);
-void	uartdrain(void);
-void	uartspecial(int, void (*)(int), int (*)(void), int);
-void	uartputs(IOQ*, char*, int);
-ulong	umbmalloc(ulong, int, int);
-void	umbfree(ulong, int);
-ulong	umbrwmalloc(ulong, int, int);
-void	upafree(ulong, int);
-ulong	upamalloc(ulong, int, int);
-void	warp86(char*, ulong);
-void	warp9(ulong);
-int	x86cpuid(int*, int*);
-void*	xspanalloc(ulong, int, ulong);
-
-#define malloc(n)	ialloc(n, 0)
-#define mallocz(n, c)	ialloc(n, 0)
-#define free(v)		while(0)
-
-#define	GSHORT(p)	(((p)[1]<<8)|(p)[0])
-#define	GLONG(p)	((GSHORT(p+2)<<16)|GSHORT(p))
-#define	GLSHORT(p)	(((p)[0]<<8)|(p)[1])
-#define	GLLONG(p)	(((ulong)GLSHORT(p)<<16)|GLSHORT(p+2))
-#define	PLLONG(p,v)	(p)[3]=(v);(p)[2]=(v)>>8;(p)[1]=(v)>>16;(p)[0]=(v)>>24
-
-#define KADDR(a)	((void*)((ulong)(a)|KZERO))
-#define PADDR(a)	((ulong)(a)&~0xF0000000)
-
-#define	HOWMANY(x, y)	(((x)+((y)-1))/(y))
-#define ROUNDUP(x, y)	(HOWMANY((x), (y))*(y))
-
-
-#define xalloc(n)	ialloc(n, 0)
-#define xfree(v)	while(0)
-#define lock(l)		if(l){/* nothing to do */;}else{/* nothing to do */;}
-#define unlock(l)	if(l){/* nothing to do */;}else{/* nothing to do */;}
-
-int	dmacount(int);
-int	dmadone(int);
-void	dmaend(int);
-void	dmainit(int);
-long	dmasetup(int, void*, long, int);
-
-extern int (*_pcmspecial)(char *, ISAConf *);
-extern void (*_pcmspecialclose)(int);
-extern void devi82365link(void);
-extern void devpccardlink(void);
--- a/os/boot/pc/fs.c
+++ /dev/null
@@ -1,94 +1,0 @@
-#include	"u.h"
-#include	"lib.h"
-#include	"mem.h"
-#include	"dat.h"
-#include	"fns.h"
-#include	"io.h"
-
-#include	"fs.h"
-
-/*
- *  grab next element from a path, return the pointer to unprocessed portion of
- *  path.
- */
-char *
-nextelem(char *path, char *elem)
-{
-	int i;
-
-	while(*path == '/')
-		path++;
-	if(*path==0 || *path==' ')
-		return 0;
-	for(i=0; *path!='\0' && *path!='/' && *path!=' '; i++){
-		if(i==NAMELEN){
-			print("name component too long\n");
-			return 0;
-		}
-		*elem++ = *path++;
-	}
-	*elem = '\0';
-	return path;
-}
-
-int
-fswalk(Fs *fs, char *path, File *f)
-{
-	char element[NAMELEN];
-
-	*f = fs->root;
-	if(BADPTR(fs->walk))
-		panic("fswalk bad pointer fs->walk");
-
-	f->path = path;
-	while(path = nextelem(path, element)){
-		switch(fs->walk(f, element)){
-		case -1:
-			return -1;
-		case 0:
-			return 0;
-		}
-	}
-	return 1;
-}
-
-/*
- *  boot
- */
-int
-fsboot(Fs *fs, char *path, Boot *b)
-{
-	File file;
-	long n;
-	static char buf[8192];
-
-	switch(fswalk(fs, path, &file)){
-	case -1:
-		print("error walking to %s\n", path);
-		return -1;
-	case 0:
-		print("%s not found\n", path);
-		return -1;
-	case 1:
-		print("found %s\n", path);
-		break;
-	}
-
-	while((n = fsread(&file, buf, sizeof buf)) > 0) {
-		if(bootpass(b, buf, n) != MORE)
-			break;
-	}
-
-	bootpass(b, nil, 0);	/* tries boot */
-	return -1;
-}
-
-int
-fsread(File *file, void *a, long n)
-{
-	if(BADPTR(file->fs))
-		panic("bad pointer file->fs in fsread");
-	if(BADPTR(file->fs->read))
-		panic("bad pointer file->fs->read in fsread");
-	return file->fs->read(file, a, n);
-}
--- a/os/boot/pc/fs.h
+++ /dev/null
@@ -1,36 +1,0 @@
-typedef struct File File;
-typedef struct Fs Fs;
-
-#include "dosfs.h"
-#include "kfs.h"
-
-struct File{
-	union{
-		Dosfile	dos;
-		Kfsfile	kfs;
-		int walked;
-	};
-	Fs	*fs;
-	char	*path;
-};
-
-struct Fs{
-	union {
-		Dos dos;
-		Kfs kfs;
-	};
-	int	dev;				/* device id */
-	long	(*diskread)(Fs*, void*, long);	/* disk read routine */
-	vlong	(*diskseek)(Fs*, vlong);	/* disk seek routine */
-	long	(*read)(File*, void*, long);
-	int	(*walk)(File*, char*);
-	File	root;
-};
-
-extern int chatty;
-extern int dotini(Fs*);
-extern int fswalk(Fs*, char*, File*);
-extern int fsread(File*, void*, long);
-extern int fsboot(Fs*, char*, Boot*);
-
-#define BADPTR(x) ((ulong)x < 0x80000000)
--- a/os/boot/pc/getcallerpc.c
+++ /dev/null
@@ -1,8 +1,0 @@
-#include "u.h"
-#include "lib.h"
-
-ulong
-getcallerpc(void *x)
-{
-	return (((ulong*)(x))[-1]);
-}
--- a/os/boot/pc/ilock.c
+++ /dev/null
@@ -1,24 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-void
-ilock(Lock *lk)
-{
-	if(lk->locked != 0)
-		panic("ilock");
-	lk->spl = splhi();
-	lk->locked = 1;
-}
-
-void
-iunlock(Lock *lk)
-{
-	if(lk->locked != 1)
-		panic("iunlock");
-	lk->locked = 0;
-	splx(lk->spl);
-}
--- a/os/boot/pc/inflate.c
+++ /dev/null
@@ -1,199 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-#include <flate.h>
-
-typedef struct Biobuf	Biobuf;
-
-struct Biobuf
-{
-	uchar *bp;
-	uchar *p;
-	uchar *ep;
-};
-
-static int	header(Biobuf*);
-static int	trailer(Biobuf*, Biobuf*);
-static int	getc(void*);
-static ulong	offset(Biobuf*);
-static int	crcwrite(void *out, void *buf, int n);
-static ulong	get4(Biobuf *b);
-static ulong	Boffset(Biobuf *bp);
-
-/* GZIP flags */
-enum {
-	Ftext=		(1<<0),
-	Fhcrc=		(1<<1),
-	Fextra=		(1<<2),
-	Fname=		(1<<3),
-	Fcomment=	(1<<4),
-
-	GZCRCPOLY	= 0xedb88320UL,
-};
-
-static ulong	*crctab;
-static ulong	crc;
-
-extern void diff(char*);	//XXX
-int
-gunzip(uchar *out, int outn, uchar *in, int inn)
-{
-	Biobuf bin, bout;
-	int err;
-
-	crc = 0;
-	crctab = mkcrctab(GZCRCPOLY);
-	err = inflateinit();
-	if(err != FlateOk)
-		print("inflateinit failed: %s\n", flateerr(err));
-
-	bin.bp = bin.p = in;
-	bin.ep = in+inn;
-	bout.bp = bout.p = out;
-	bout.ep = out+outn;
-
-	err = header(&bin);
-	if(err != FlateOk)
-		return err;
-
-	err = inflate(&bout, crcwrite, &bin, getc);
-	if(err != FlateOk)
-		print("inflate failed: %s\n", flateerr(err));
-
-	err = trailer(&bout, &bin);
-	if(err != FlateOk)
-		return err;
-
-	return Boffset(&bout);
-}
-
-static int
-header(Biobuf *bin)
-{
-	int i, flag;
-
-	if(getc(bin) != 0x1f || getc(bin) != 0x8b){
-		print("bad magic\n");
-		return FlateCorrupted;
-	}
-	if(getc(bin) != 8){
-		print("unknown compression type\n");
-		return FlateCorrupted;
-	}
-	
-	flag = getc(bin);
-	
-	/* mod time */
-	get4(bin);
-	
-	/* extra flags */
-	getc(bin);
-	
-	/* OS type */
-	getc(bin);
-
-	if(flag & Fextra)
-		for(i=getc(bin); i>0; i--)
-			getc(bin);
-	
-	/* name */
-	if(flag&Fname)
-		while(getc(bin) != 0)
-			;
-
-	/* comment */
-	if(flag&Fcomment)
-		while(getc(bin) != 0)
-			;
-
-	/* crc16 */
-	if(flag&Fhcrc) {
-		getc(bin);
-		getc(bin);
-	}
-		
-	return FlateOk;
-}
-
-static int
-trailer(Biobuf *bout, Biobuf *bin)
-{
-	/* crc32 */
-	if(crc != get4(bin)){
-		print("crc mismatch\n");
-		return FlateCorrupted;
-	}
-
-	/* length */
-	if(get4(bin) != Boffset(bout)){
-		print("bad output len\n");
-		return FlateCorrupted;
-	}
-	return FlateOk;
-}
-
-static ulong
-get4(Biobuf *b)
-{
-	ulong v;
-	int i, c;
-
-	v = 0;
-	for(i = 0; i < 4; i++){
-		c = getc(b);
-		v |= c << (i * 8);
-	}
-	return v;
-}
-
-static int
-getc(void *in)
-{
-	Biobuf *bp = in;
-
-//	if((bp->p - bp->bp) % 10000 == 0)
-//		print(".");
-	if(bp->p >= bp->ep)
-		return -1;
-	return *bp->p++;
-}
-
-static ulong
-Boffset(Biobuf *bp)
-{
-	return bp->p - bp->bp;
-}
-
-static int
-crcwrite(void *out, void *buf, int n)
-{
-	Biobuf *bp;
-	int nn;
-
-	crc = blockcrc(crctab, crc, buf, n);
-	bp = out;
-	nn = n;
-	if(nn > bp->ep-bp->p)
-		nn = bp->ep-bp->p;
-	if(nn > 0)
-		memmove(bp->p, buf, nn);
-	bp->p += n;
-	return n;
-}
-
-#undef malloc
-#undef free
-
-void *
-malloc(ulong n)
-{
-	return ialloc(n, 8);
-}
-
-void
-free(void *)
-{
-}
--- a/os/boot/pc/io.h
+++ /dev/null
@@ -1,317 +1,0 @@
-/*
- *  programmable interrupt vectors (for the 8259's)
- */
-enum
-{
-	Bptvec=		3,		/* breakpoints */
-	Mathemuvec=	7,		/* math coprocessor emulation interrupt */
-	Mathovervec=	9,		/* math coprocessor overrun interrupt */
-	Matherr1vec=	16,		/* math coprocessor error interrupt */
-	Faultvec=	14,		/* page fault */
-
-	Syscallvec=	64,
-
-	VectorPIC	= 24,		/* external [A]PIC interrupts */
-	VectorCLOCK	= VectorPIC+0,
-	VectorKBD	= VectorPIC+1,
-	VectorUART1	= VectorPIC+3,
-	VectorUART0	= VectorPIC+4,
-	VectorPCMCIA	= VectorPIC+5,
-	VectorFLOPPY	= VectorPIC+6,
-	VectorLPT	= VectorPIC+7,
-	VectorIRQ7	= VectorPIC+7,
-	VectorAUX	= VectorPIC+12,	/* PS/2 port */
-	VectorIRQ13	= VectorPIC+13,	/* coprocessor on x386 */
-	VectorATA0	= VectorPIC+14,
-	VectorATA1	= VectorPIC+15,
-	MaxVectorPIC	= VectorPIC+15,
-};
-
-enum {
-	BusCBUS		= 0,		/* Corollary CBUS */
-	BusCBUSII,			/* Corollary CBUS II */
-	BusEISA,			/* Extended ISA */
-	BusFUTURE,			/* IEEE Futurebus */
-	BusINTERN,			/* Internal bus */
-	BusISA,				/* Industry Standard Architecture */
-	BusMBI,				/* Multibus I */
-	BusMBII,			/* Multibus II */
-	BusMCA,				/* Micro Channel Architecture */
-	BusMPI,				/* MPI */
-	BusMPSA,			/* MPSA */
-	BusNUBUS,			/* Apple Macintosh NuBus */
-	BusPCI,				/* Peripheral Component Interconnect */
-	BusPCMCIA,			/* PC Memory Card International Association */
-	BusTC,				/* DEC TurboChannel */
-	BusVL,				/* VESA Local bus */
-	BusVME,				/* VMEbus */
-	BusXPRESS,			/* Express System Bus */
-};
-
-#define MKBUS(t,b,d,f)	(((t)<<24)|(((b)&0xFF)<<16)|(((d)&0x1F)<<11)|(((f)&0x07)<<8))
-#define BUSFNO(tbdf)	(((tbdf)>>8)&0x07)
-#define BUSDNO(tbdf)	(((tbdf)>>11)&0x1F)
-#define BUSBNO(tbdf)	(((tbdf)>>16)&0xFF)
-#define BUSTYPE(tbdf)	((tbdf)>>24)
-#define BUSBDF(tbdf)	((tbdf)&0x00FFFF00)
-#define BUSUNKNOWN	(-1)
-
-enum {
-	MaxEISA		= 16,
-	CfgEISA		= 0xC80,
-};
-
-/*
- * PCI support code.
- */
-enum {					/* type 0 and type 1 pre-defined header */
-	PciVID		= 0x00,		/* vendor ID */
-	PciDID		= 0x02,		/* device ID */
-	PciPCR		= 0x04,		/* command */
-	PciPSR		= 0x06,		/* status */
-	PciRID		= 0x08,		/* revision ID */
-	PciCCRp		= 0x09,		/* programming interface class code */
-	PciCCRu		= 0x0A,		/* sub-class code */
-	PciCCRb		= 0x0B,		/* base class code */
-	PciCLS		= 0x0C,		/* cache line size */
-	PciLTR		= 0x0D,		/* latency timer */
-	PciHDT		= 0x0E,		/* header type */
-	PciBST		= 0x0F,		/* BIST */
-
-	PciBAR0		= 0x10,		/* base address */
-	PciBAR1		= 0x14,
-
-	PciINTL		= 0x3C,		/* interrupt line */
-	PciINTP		= 0x3D,		/* interrupt pin */
-};
-
-/* ccrb (base class code) values; controller types */
-enum {
-	Pcibcpci1	= 0,		/* pci 1.0; no class codes defined */
-	Pcibcstore	= 1,		/* mass storage */
-	Pcibcnet	= 2,		/* network */
-	Pcibcdisp	= 3,		/* display */
-	Pcibcmmedia	= 4,		/* multimedia */
-	Pcibcmem	= 5,		/* memory */
-	Pcibcbridge	= 6,		/* bridge */
-	Pcibccomm	= 7,		/* simple comms (e.g., serial) */
-	Pcibcbasesys	= 8,		/* base system */
-	Pcibcinput	= 9,		/* input */
-	Pcibcdock	= 0xa,		/* docking stations */
-	Pcibcproc	= 0xb,		/* processors */
-	Pcibcserial	= 0xc,		/* serial bus (e.g., USB) */
-	Pcibcwireless	= 0xd,		/* wireless */
-	Pcibcintell	= 0xe,		/* intelligent i/o */
-	Pcibcsatcom	= 0xf,		/* satellite comms */
-	Pcibccrypto	= 0x10,		/* encryption/decryption */
-	Pcibcdacq	= 0x11,		/* data acquisition & signal proc. */
-};
-
-/* ccru (sub-class code) values; common cases only */
-enum {
-	/* mass storage */
-	Pciscscsi	= 0,		/* SCSI */
-	Pciscide	= 1,		/* IDE (ATA) */
-
-	/* network */
-	Pciscether	= 0,		/* Ethernet */
-
-	/* display */
-	Pciscvga	= 0,		/* VGA */
-	Pciscxga	= 1,		/* XGA */
-	Pcisc3d		= 2,		/* 3D */
-
-	/* bridges */
-	Pcischostpci	= 0,		/* host/pci */
-	Pciscpcicpci	= 1,		/* pci/pci */
-
-	/* simple comms */
-	Pciscserial	= 0,		/* 16450, etc. */
-	Pciscmultiser	= 1,		/* multiport serial */
-
-	/* serial bus */
-	Pciscusb	= 3,		/* USB */
-};
-
-enum {					/* type 0 pre-defined header */
-	PciBAR2		= 0x18,
-	PciBAR3		= 0x1C,
-	PciBAR4		= 0x20,
-	PciBAR5		= 0x24,
-	PciCIS		= 0x28,		/* cardbus CIS pointer */
-	PciSVID		= 0x2C,		/* subsystem vendor ID */
-	PciSID		= 0x2E,		/* cardbus CIS pointer */
-	PciEBAR0	= 0x30,		/* expansion ROM base address */
-	PciMGNT		= 0x3E,		/* burst period length */
-	PciMLT		= 0x3F,		/* maximum latency between bursts */
-};
-
-enum {					/* type 1 pre-defined header */
-	PciPBN		= 0x18,		/* primary bus number */
-	PciSBN		= 0x19,		/* secondary bus number */
-	PciUBN		= 0x1A,		/* subordinate bus number */
-	PciSLTR		= 0x1B,		/* secondary latency timer */
-	PciIBR		= 0x1C,		/* I/O base */
-	PciILR		= 0x1D,		/* I/O limit */
-	PciSPSR		= 0x1E,		/* secondary status */
-	PciMBR		= 0x20,		/* memory base */
-	PciMLR		= 0x22,		/* memory limit */
-	PciPMBR		= 0x24,		/* prefetchable memory base */
-	PciPMLR		= 0x26,		/* prefetchable memory limit */
-	PciPUBR		= 0x28,		/* prefetchable base upper 32 bits */
-	PciPULR		= 0x2C,		/* prefetchable limit upper 32 bits */
-	PciIUBR		= 0x30,		/* I/O base upper 16 bits */
-	PciIULR		= 0x32,		/* I/O limit upper 16 bits */
-	PciEBAR1	= 0x28,		/* expansion ROM base address */
-	PciBCR		= 0x3E,		/* bridge control register */
-};
-
-enum {					/* type 2 pre-defined header */
-	PciCBExCA	= 0x10,
-	PciCBSPSR	= 0x16,
-	PciCBPBN	= 0x18,		/* primary bus number */
-	PciCBSBN	= 0x19,		/* secondary bus number */
-	PciCBUBN	= 0x1A,		/* subordinate bus number */
-	PciCBSLTR	= 0x1B,		/* secondary latency timer */
-	PciCBMBR0	= 0x1C,
-	PciCBMLR0	= 0x20,
-	PciCBMBR1	= 0x24,
-	PciCBMLR1	= 0x28,
-	PciCBIBR0	= 0x2C,		/* I/O base */
-	PciCBILR0	= 0x30,		/* I/O limit */
-	PciCBIBR1	= 0x34,		/* I/O base */
-	PciCBILR1	= 0x38,		/* I/O limit */
-	PciCBBCTL	= 0x3E,		/* Bridge control */
-	PciCBSVID	= 0x40,		/* subsystem vendor ID */
-	PciCBSID	= 0x42,		/* subsystem ID */
-	PciCBLMBAR	= 0x44,		/* legacy mode base address */
-};
-
-typedef struct Pcisiz Pcisiz;
-struct Pcisiz
-{
-	Pcidev*	dev;
-	int	siz;
-	int	bar;
-};
-
-typedef struct Pcidev Pcidev;
-typedef struct Pcidev {
-	int	tbdf;			/* type+bus+device+function */
-	ushort	vid;			/* vendor ID */
-	ushort	did;			/* device ID */
-
-	ushort	pcr;
-
-	uchar	rid;
-	uchar	ccrp;
-	uchar	ccru;
-	uchar	ccrb;
-	uchar	cls;
-	uchar	ltr;
-
-	struct {
-		ulong	bar;		/* base address */
-		int	size;
-	} mem[6];
-
-	struct {
-		ulong	bar;
-		int	size;
-	} rom;
-	uchar	intl;			/* interrupt line */
-
-	Pcidev*	list;
-	Pcidev*	link;			/* next device on this bno */
-
-	Pcidev*	bridge;			/* down a bus */
-	struct {
-		ulong	bar;
-		int	size;
-	} ioa, mema;
-
-	int	pmrb;			/* power management register block */
-};
-
-#define PCIWINDOW	0
-#define PCIWADDR(va)	(PADDR(va)+PCIWINDOW)
-#define ISAWINDOW	0
-#define ISAWADDR(va)	(PADDR(va)+ISAWINDOW)
-
-/*
- * PCMCIA support code.
- */
-typedef struct PCMslot		PCMslot;
-typedef struct PCMconftab	PCMconftab;
-
-/*
- * Map between ISA memory space and PCMCIA card memory space.
- */
-struct PCMmap {
-	ulong	ca;			/* card address */
-	ulong	cea;			/* card end address */
-	ulong	isa;			/* ISA address */
-	int	len;			/* length of the ISA area */
-	int	attr;			/* attribute memory */
-	int	ref;
-};
-
-/* configuration table entry */
-struct PCMconftab
-{
-	int	index;
-	ushort	irqs;		/* legal irqs */
-	uchar	irqtype;
-	uchar	bit16;		/* true for 16 bit access */
-	struct {
-		ulong	start;
-		ulong	len;
-	} io[16];
-	int	nio;
-	uchar	vpp1;
-	uchar	vpp2;
-	uchar	memwait;
-	ulong	maxwait;
-	ulong	readywait;
-	ulong	otherwait;
-};
-
-/* a card slot */
-struct PCMslot
-{
-	Lock;
-	int	ref;
-
-	void	*cp;		/* controller for this slot */
-	long	memlen;		/* memory length */
-	uchar	base;		/* index register base */
-	uchar	slotno;		/* slot number */
-
-	/* status */
-	uchar	special;	/* in use for a special device */
-	uchar	already;	/* already inited */
-	uchar	occupied;
-	uchar	battery;
-	uchar	wrprot;
-	uchar	powered;
-	uchar	configed;
-	uchar	enabled;
-	uchar	busy;
-
-	/* cis info */
-	ulong	msec;		/* time of last slotinfo call */
-	char	verstr[512];	/* version string */
-	int	ncfg;		/* number of configurations */
-	struct {
-		ushort	cpresent;	/* config registers present */
-		ulong	caddr;		/* relative address of config registers */
-	} cfg[8];
-	int	nctab;		/* number of config table entries */
-	PCMconftab	ctab[8];
-	PCMconftab	*def;	/* default conftab */
-
-	/* memory maps */
-	Lock	mlock;		/* lock down the maps */
-	int	time;
-	PCMmap	mmap[4];	/* maps, last is always for the kernel */
-};
--- a/os/boot/pc/ip.h
+++ /dev/null
@@ -1,100 +1,0 @@
-typedef struct Udphdr Udphdr;
-struct Udphdr
-{
-	uchar	d[6];		/* Ethernet destination */
-	uchar	s[6];		/* Ethernet source */
-	uchar	type[2];	/* Ethernet packet type */
-
-	uchar	vihl;		/* Version and header length */
-	uchar	tos;		/* Type of service */
-	uchar	length[2];	/* packet length */
-	uchar	id[2];		/* Identification */
-	uchar	frag[2];	/* Fragment information */
-
-	/* Udp pseudo ip really starts here */
-	uchar	ttl;	
-	uchar	udpproto;	/* Protocol */
-	uchar	udpplen[2];	/* Header plus data length */
-	uchar	udpsrc[4];	/* Ip source */
-	uchar	udpdst[4];	/* Ip destination */
-	uchar	udpsport[2];	/* Source port */
-	uchar	udpdport[2];	/* Destination port */
-	uchar	udplen[2];	/* data length */
-	uchar	udpcksum[2];	/* Checksum */
-};
-
-typedef struct Etherhdr Etherhdr;
-struct Etherhdr
-{
-	uchar	d[6];
-	uchar	s[6];
-	uchar	type[2];
-
-	/* Now we have the ip fields */
-	uchar	vihl;		/* Version and header length */
-	uchar	tos;		/* Type of service */
-	uchar	length[2];	/* packet length */
-	uchar	id[2];		/* Identification */
-	uchar	frag[2];	/* Fragment information */
-	uchar	ttl;		/* Time to live */
-	uchar	proto;		/* Protocol */
-	uchar	cksum[2];	/* Header checksum */
-	uchar	src[4];		/* Ip source */
-	uchar	dst[4];		/* Ip destination */
-};
-
-enum
-{
-	IP_VER		= 0x40,
-	IP_HLEN		= 0x05,			
- 	UDP_EHSIZE	= 22,
-	UDP_PHDRSIZE	= 12,
-	UDP_HDRSIZE	= 20,
-	ETHER_HDR	= 14,
-	IP_UDPPROTO	= 17,
-	ET_IP		= 0x800,
-	Bcastip		= 0xffffffff,
-	BPportsrc	= 68,
-	BPportdst	= 67,
-	TFTPport	= 69,
-	Timeout		= 5000,	/* milliseconds */
-	Bootrequest 	= 1,
-	Bootreply   	= 2,
-	Tftp_READ	= 1,
-	Tftp_WRITE	= 2,
-	Tftp_DATA	= 3,
-	Tftp_ACK	= 4,
-	Tftp_ERROR	= 5,
-	Segsize		= 512,
-	TFTPSZ		= Segsize+10,
-};
-
-typedef struct Bootp Bootp;
-struct Bootp
-{
-	uchar	op;		/* opcode */
-	uchar	htype;		/* hardware type */
-	uchar	hlen;		/* hardware address len */
-	uchar	hops;		/* hops */
-	uchar	xid[4];		/* a random number */
-	uchar	secs[2];	/* elapsed since client started booting */
-	uchar	pad[2];
-	uchar	ciaddr[4];	/* client IP address (client tells server) */
-	uchar	yiaddr[4];	/* client IP address (server tells client) */
-	uchar	siaddr[4];	/* server IP address */
-	uchar	giaddr[4];	/* gateway IP address */
-	uchar	chaddr[16];	/* client hardware address */
-	char	sname[64];	/* server host name (optional) */
-	char	file[128];	/* boot file name */
-	char	vend[128];	/* vendor-specific goo */
-};
-
-typedef struct Netaddr Netaddr;
-struct Netaddr
-{
-	ulong	ip;
-	ushort	port;
-	char	ea[Eaddrlen];
-};
-
-extern int	eipfmt(Fmt*);
--- a/os/boot/pc/kbd.c
+++ /dev/null
@@ -1,489 +1,0 @@
-#include	"u.h"
-#include	"lib.h"
-#include	"mem.h"
-#include	"dat.h"
-#include	"fns.h"
-#include	"io.h"
-
-enum {
-	Data=		0x60,	/* data port */
-
-	Status=		0x64,	/* status port */
-	 Inready=	0x01,	/*  input character ready */
-	 Outbusy=	0x02,	/*  output busy */
-	 Sysflag=	0x04,	/*  system flag */
-	 Cmddata=	0x08,	/*  cmd==0, data==1 */
-	 Inhibit=	0x10,	/*  keyboard/mouse inhibited */
-	 Minready=	0x20,	/*  mouse character ready */
-	 Rtimeout=	0x40,	/*  general timeout */
-	 Parity=	0x80,
-
-	Cmd=		0x64,	/* command port (write only) */
- 
-	Spec=	0x80,
-
-	PF=	Spec|0x20,	/* num pad function key */
-	View=	Spec|0x00,	/* view (shift window up) */
-	KF=	Spec|0x40,	/* function key */
-	Shift=	Spec|0x60,
-	Break=	Spec|0x61,
-	Ctrl=	Spec|0x62,
-	Latin=	Spec|0x63,
-	Caps=	Spec|0x64,
-	Num=	Spec|0x65,
-	No=	Spec|0x7F,	/* no mapping */
-
-	Home=	KF|13,
-	Up=	KF|14,
-	Pgup=	KF|15,
-	Print=	KF|16,
-	Left=	View,
-	Right=	View,
-	End=	'\r',
-	Down=	View,
-	Pgdown=	View,
-	Ins=	KF|20,
-	Del=	0x7F,
-};
-
-uchar kbtab[] = 
-{
-[0x00]	No,	0x1b,	'1',	'2',	'3',	'4',	'5',	'6',
-[0x08]	'7',	'8',	'9',	'0',	'-',	'=',	'\b',	'\t',
-[0x10]	'q',	'w',	'e',	'r',	't',	'y',	'u',	'i',
-[0x18]	'o',	'p',	'[',	']',	'\n',	Ctrl,	'a',	's',
-[0x20]	'd',	'f',	'g',	'h',	'j',	'k',	'l',	';',
-[0x28]	'\'',	'`',	Shift,	'\\',	'z',	'x',	'c',	'v',
-[0x30]	'b',	'n',	'm',	',',	'.',	'/',	Shift,	No,
-[0x38]	Latin,	' ',	Caps,	KF|1,	KF|2,	KF|3,	KF|4,	KF|5,
-[0x40]	KF|6,	KF|7,	KF|8,	KF|9,	KF|10,	Num,	KF|12,	Home,
-[0x48]	No,	No,	No,	No,	No,	No,	No,	No,
-[0x50]	No,	No,	No,	No,	No,	No,	No,	KF|11,
-[0x58]	KF|12,	No,	No,	No,	No,	No,	No,	No,
-};
-
-uchar kbtabshift[] =
-{
-[0x00]	No,	0x1b,	'!',	'@',	'#',	'$',	'%',	'^',
-[0x08]	'&',	'*',	'(',	')',	'_',	'+',	'\b',	'\t',
-[0x10]	'Q',	'W',	'E',	'R',	'T',	'Y',	'U',	'I',
-[0x18]	'O',	'P',	'{',	'}',	'\n',	Ctrl,	'A',	'S',
-[0x20]	'D',	'F',	'G',	'H',	'J',	'K',	'L',	':',
-[0x28]	'"',	'~',	Shift,	'|',	'Z',	'X',	'C',	'V',
-[0x30]	'B',	'N',	'M',	'<',	'>',	'?',	Shift,	No,
-[0x38]	Latin,	' ',	Caps,	KF|1,	KF|2,	KF|3,	KF|4,	KF|5,
-[0x40]	KF|6,	KF|7,	KF|8,	KF|9,	KF|10,	Num,	KF|12,	Home,
-[0x48]	No,	No,	No,	No,	No,	No,	No,	No,
-[0x50]	No,	No,	No,	No,	No,	No,	No,	KF|11,
-[0x58]	KF|12,	No,	No,	No,	No,	No,	No,	No,
-};
-
-uchar kbtabesc1[] =
-{
-[0x00]	No,	No,	No,	No,	No,	No,	No,	No,
-[0x08]	No,	No,	No,	No,	No,	No,	No,	No,
-[0x10]	No,	No,	No,	No,	No,	No,	No,	No,
-[0x18]	No,	No,	No,	No,	No,	Ctrl,	No,	No,
-[0x20]	No,	No,	No,	No,	No,	No,	No,	No,
-[0x28]	No,	No,	No,	No,	No,	No,	No,	No,
-[0x30]	No,	No,	No,	No,	No,	No,	No,	Print,
-[0x38]	Latin,	No,	No,	No,	No,	No,	No,	No,
-[0x40]	No,	No,	No,	No,	No,	No,	Break,	Home,
-[0x48]	Up,	Pgup,	No,	Down,	No,	Right,	No,	End,
-[0x50]	Left,	Pgdown,	Ins,	Del,	No,	No,	No,	No,
-[0x58]	No,	No,	No,	No,	No,	No,	No,	No,
-};
-
-struct latin
-{
-	uchar	l;
-	char	c[2];
-}latintab[] = {
-	L'¡',	"!!",	/* spanish initial ! */
-	L'¢',	"c|",	/* cent */
-	L'¢',	"c$",	/* cent */
-	L'£',	"l$",	/* pound sterling */
-	L'¤',	"g$",	/* general currency */
-	L'¥',	"y$",	/* yen */
-	L'¥',	"j$",	/* yen */
-	L'¦',	"||",	/* broken vertical bar */
-	L'§',	"SS",	/* section symbol */
-	L'¨',	"\"\"",	/* dieresis */
-	L'©',	"cr",	/* copyright */
-	L'©',	"cO",	/* copyright */
-	L'ª',	"sa",	/* super a, feminine ordinal */
-	L'«',	"<<",	/* left angle quotation */
-	L'¬',	"no",	/* not sign, hooked overbar */
-	L'­',	"--",	/* soft hyphen */
-	L'®',	"rg",	/* registered trademark */
-	L'¯',	"__",	/* macron */
-	L'°',	"s0",	/* degree (sup o) */
-	L'±',	"+-",	/* plus-minus */
-	L'²',	"s2",	/* sup 2 */
-	L'³',	"s3",	/* sup 3 */
-	L'´',	"''",	/* grave accent */
-	L'µ',	"mu",	/* mu */
-	L'¶',	"pg",	/* paragraph (pilcrow) */
-	L'·',	"..",	/* centered . */
-	L'¸',	",,",	/* cedilla */
-	L'¹',	"s1",	/* sup 1 */
-	L'º',	"so",	/* sup o */
-	L'»',	">>",	/* right angle quotation */
-	L'¼',	"14",	/* 1/4 */
-	L'½',	"12",	/* 1/2 */
-	L'¾',	"34",	/* 3/4 */
-	L'¿',	"??",	/* spanish initial ? */
-	L'À',	"A`",	/* A grave */
-	L'Á',	"A'",	/* A acute */
-	L'Â',	"A^",	/* A circumflex */
-	L'Ã',	"A~",	/* A tilde */
-	L'Ä',	"A\"",	/* A dieresis */
-	L'Ä',	"A:",	/* A dieresis */
-	L'Å',	"Ao",	/* A circle */
-	L'Å',	"AO",	/* A circle */
-	L'Æ',	"Ae",	/* AE ligature */
-	L'Æ',	"AE",	/* AE ligature */
-	L'Ç',	"C,",	/* C cedilla */
-	L'È',	"E`",	/* E grave */
-	L'É',	"E'",	/* E acute */
-	L'Ê',	"E^",	/* E circumflex */
-	L'Ë',	"E\"",	/* E dieresis */
-	L'Ë',	"E:",	/* E dieresis */
-	L'Ì',	"I`",	/* I grave */
-	L'Í',	"I'",	/* I acute */
-	L'Î',	"I^",	/* I circumflex */
-	L'Ï',	"I\"",	/* I dieresis */
-	L'Ï',	"I:",	/* I dieresis */
-	L'Ð',	"D-",	/* Eth */
-	L'Ñ',	"N~",	/* N tilde */
-	L'Ò',	"O`",	/* O grave */
-	L'Ó',	"O'",	/* O acute */
-	L'Ô',	"O^",	/* O circumflex */
-	L'Õ',	"O~",	/* O tilde */
-	L'Ö',	"O\"",	/* O dieresis */
-	L'Ö',	"O:",	/* O dieresis */
-	L'Ö',	"OE",	/* O dieresis */
-	L'Ö',	"Oe",	/* O dieresis */
-	L'×',	"xx",	/* times sign */
-	L'Ø',	"O/",	/* O slash */
-	L'Ù',	"U`",	/* U grave */
-	L'Ú',	"U'",	/* U acute */
-	L'Û',	"U^",	/* U circumflex */
-	L'Ü',	"U\"",	/* U dieresis */
-	L'Ü',	"U:",	/* U dieresis */
-	L'Ü',	"UE",	/* U dieresis */
-	L'Ü',	"Ue",	/* U dieresis */
-	L'Ý',	"Y'",	/* Y acute */
-	L'Þ',	"P|",	/* Thorn */
-	L'Þ',	"Th",	/* Thorn */
-	L'Þ',	"TH",	/* Thorn */
-	L'ß',	"ss",	/* sharp s */
-	L'à',	"a`",	/* a grave */
-	L'á',	"a'",	/* a acute */
-	L'â',	"a^",	/* a circumflex */
-	L'ã',	"a~",	/* a tilde */
-	L'ä',	"a\"",	/* a dieresis */
-	L'ä',	"a:",	/* a dieresis */
-	L'å',	"ao",	/* a circle */
-	L'æ',	"ae",	/* ae ligature */
-	L'ç',	"c,",	/* c cedilla */
-	L'è',	"e`",	/* e grave */
-	L'é',	"e'",	/* e acute */
-	L'ê',	"e^",	/* e circumflex */
-	L'ë',	"e\"",	/* e dieresis */
-	L'ë',	"e:",	/* e dieresis */
-	L'ì',	"i`",	/* i grave */
-	L'í',	"i'",	/* i acute */
-	L'î',	"i^",	/* i circumflex */
-	L'ï',	"i\"",	/* i dieresis */
-	L'ï',	"i:",	/* i dieresis */
-	L'ð',	"d-",	/* eth */
-	L'ñ',	"n~",	/* n tilde */
-	L'ò',	"o`",	/* o grave */
-	L'ó',	"o'",	/* o acute */
-	L'ô',	"o^",	/* o circumflex */
-	L'õ',	"o~",	/* o tilde */
-	L'ö',	"o\"",	/* o dieresis */
-	L'ö',	"o:",	/* o dieresis */
-	L'ö',	"oe",	/* o dieresis */
-	L'÷',	"-:",	/* divide sign */
-	L'ø',	"o/",	/* o slash */
-	L'ù',	"u`",	/* u grave */
-	L'ú',	"u'",	/* u acute */
-	L'û',	"u^",	/* u circumflex */
-	L'ü',	"u\"",	/* u dieresis */
-	L'ü',	"u:",	/* u dieresis */
-	L'ü',	"ue",	/* u dieresis */
-	L'ý',	"y'",	/* y acute */
-	L'þ',	"th",	/* thorn */
-	L'þ',	"p|",	/* thorn */
-	L'ÿ',	"y\"",	/* y dieresis */
-	L'ÿ',	"y:",	/* y dieresis */
-	0,	0,
-};
-
-enum
-{
-	/* controller command byte */
-	Cscs1=		(1<<6),		/* scan code set 1 */
-	Cmousedis=	(1<<5),		/* mouse disable */
-	Ckbddis=	(1<<4),		/* kbd disable */
-	Csf=		(1<<2),		/* system flag */
-	Cmouseint=	(1<<1),		/* mouse interrupt enable */
-	Ckbdint=	(1<<0),		/* kbd interrupt enable */
-};
-
-static uchar ccc;
-
-int
-latin1(int k1, int k2)
-{
-	struct latin *l;
-
-	for(l=latintab; l->l; l++)
-		if(k1==l->c[0] && k2==l->c[1])
-			return l->l;
-	return 0;
-}
-
-/*
- *  wait for output no longer busy
- */
-static int
-outready(void)
-{
-	int tries;
-
-	for(tries = 0; (inb(Status) & Outbusy); tries++){
-		if(tries > 500)
-			return -1;
-		delay(2);
-	}
-	return 0;
-}
-
-/*
- *  wait for input
- */
-static int
-inready(void)
-{
-	int tries;
-
-	for(tries = 0; !(inb(Status) & Inready); tries++){
-		if(tries > 500)
-			return -1;
-		delay(2);
-	}
-	return 0;
-}
-
-/*
- *  ask 8042 to enable the use of address bit 20
- */
-void
-i8042a20(void)
-{
-	outready();
-	outb(Cmd, 0xD1);
-	outready();
-	outb(Data, 0xDF);
-	outready();
-}
-
-/*
- *  ask 8042 to reset the machine
- */
-void
-i8042reset(void)
-{
-	int i, x;
-#ifdef notdef
-	ushort *s = (ushort*)(KZERO|0x472);
-
-	*s = 0x1234;		/* BIOS warm-boot flag */
-#endif /* notdef */
-
-	outready();
-	outb(Cmd, 0xFE);	/* pulse reset line (means resend on AT&T machines) */
-	outready();
-
-	/*
-	 *  Pulse it by hand (old somewhat reliable)
-	 */
-	x = 0xDF;
-	for(i = 0; i < 5; i++){
-		x ^= 1;
-		outready();
-		outb(Cmd, 0xD1);
-		outready();
-		outb(Data, x);	/* toggle reset */
-		delay(100);
-	}
-}
-
-/*
- *  keyboard interrupt
- */
-static void
-i8042intr(Ureg*, void*)
-{
-	int s, c;
-	static int esc1, esc2;
-	static int alt, caps, ctl, num, shift;
-	static int lstate, k1, k2;
-	int keyup;
-
-	/*
-	 *  get status
-	 */
-	s = inb(Status);
-	if(!(s&Inready))
-		return;
-
-	/*
-	 *  get the character
-	 */
-	c = inb(Data);
-
-	/*
-	 *  if it's the aux port...
-	 */
-	if(s & Minready)
-		return;
-
-	/*
-	 *  e0's is the first of a 2 character sequence
-	 */
-	if(c == 0xe0){
-		esc1 = 1;
-		return;
-	} else if(c == 0xe1){
-		esc2 = 2;
-		return;
-	}
-
-	keyup = c&0x80;
-	c &= 0x7f;
-	if(c > sizeof kbtab){
-		c |= keyup;
-		if(c != 0xFF)	/* these come fairly often: CAPSLOCK U Y */
-			print("unknown key %ux\n", c);
-		return;
-	}
-
-	if(esc1){
-		c = kbtabesc1[c];
-		esc1 = 0;
-	} else if(esc2){
-		esc2--;
-		return;
-	} else if(shift)
-		c = kbtabshift[c];
-	else
-		c = kbtab[c];
-
-	if(caps && c<='z' && c>='a')
-		c += 'A' - 'a';
-
-	/*
-	 *  keyup only important for shifts
-	 */
-	if(keyup){
-		switch(c){
-		case Latin:
-			alt = 0;
-			break;
-		case Shift:
-			shift = 0;
-			break;
-		case Ctrl:
-			ctl = 0;
-			break;
-		}
-		return;
-	}
-
-	/*
- 	 *  normal character
-	 */
-	if(!(c & Spec)){
-		if(ctl){
-			if(alt && c == Del)
-				warp86("\nCtrl-Alt-Del\n", 0);
-			c &= 0x1f;
-		}
-		switch(lstate){
-		case 1:
-			k1 = c;
-			lstate = 2;
-			return;
-		case 2:
-			k2 = c;
-			lstate = 0;
-			c = latin1(k1, k2);
-			if(c == 0){
-				kbdchar(k1);
-				c = k2;
-			}
-			/* fall through */
-		default:
-			break;
-		}
-	} else {
-		switch(c){
-		case Caps:
-			caps ^= 1;
-			return;
-		case Num:
-			num ^= 1;
-			return;
-		case Shift:
-			shift = 1;
-			return;
-		case Latin:
-			alt = 1;
-			lstate = 1;
-			return;
-		case Ctrl:
-			ctl = 1;
-			return;
-		}
-	}
-	kbdchar(c);
-}
-
-static char *initfailed = "kbd init failed\n";
-
-void
-i8042init(void)
-{
-	int c;
-
-	/* wait for a quiescent controller */
-	while((c = inb(Status)) & (Outbusy | Inready))
-		if(c & Inready)
-			inb(Data);
-
-	/* get current controller command byte */
-	outb(Cmd, 0x20);
-	if(inready() < 0){
-		print("kbdinit: can't read ccc\n");
-		ccc = 0;
-	} else
-		ccc = inb(Data);
-
-	/* enable kbd xfers and interrupts */
-	ccc &= ~Ckbddis;
-	ccc |= Csf | Ckbdint | Cscs1;
-	if(outready() < 0)
-		print(initfailed);
-	outb(Cmd, 0x60);
-	if(outready() < 0)
-		print(initfailed);
-	outb(Data, ccc);
-	if(outready() < 0)
-		print(initfailed);
-
-	setvec(VectorKBD, i8042intr, 0);
-}
--- a/os/boot/pc/kfs.h
+++ /dev/null
@@ -1,57 +1,0 @@
-typedef struct Qid9p1 Qid9p1;
-typedef struct Dentry Dentry;
-typedef struct Kfsfile Kfsfile;
-typedef struct Kfs Kfs;
-
-/* DONT TOUCH, this is the disk structure */
-struct	Qid9p1
-{
-	long	path;
-	long	version;
-};
-
-//#define	NAMELEN		28		/* size of names */
-#define	NDBLOCK		6		/* number of direct blocks in Dentry */
-
-/* DONT TOUCH, this is the disk structure */
-struct	Dentry
-{
-	char	name[NAMELEN];
-	short	uid;
-	short	gid;
-	ushort	mode;
-/*
-		#define	DALLOC	0x8000
-		#define	DDIR	0x4000
-		#define	DAPND	0x2000
-		#define	DLOCK	0x1000
-		#define	DREAD	0x4
-		#define	DWRITE	0x2
-		#define	DEXEC	0x1
-*/
-	Qid9p1	qid;
-	long	size;
-	long	dblock[NDBLOCK];
-	long	iblock;
-	long	diblock;
-	long	atime;
-	long	mtime;
-};
-
-struct Kfsfile
-{
-	Dentry;
-	long off;
-};
-
-struct Kfs
-{
-	int	RBUFSIZE;
-	int	BUFSIZE;
-	int	DIRPERBUF;
-	int	INDPERBUF;
-	int	INDPERBUF2;
-};
-
-extern int kfsinit(Fs*);
-
--- a/os/boot/pc/kfsboot.c
+++ /dev/null
@@ -1,256 +1,0 @@
-#include	"u.h"
-#include	"lib.h"
-#include	"mem.h"
-#include	"dat.h"
-#include	"fns.h"
-#include	"fs.h"
-
-typedef struct Tag Tag;
-
-/*
- * tags on block
- */
-enum
-{
-	Tnone		= 0,
-	Tsuper,			/* the super block */
-	Tdir,			/* directory contents */
-	Tind1,			/* points to blocks */
-	Tind2,			/* points to Tind1 */
-	Tfile,			/* file contents */
-	Tfree,			/* in free list */
-	Tbuck,			/* cache fs bucket */
-	Tvirgo,			/* fake worm virgin bits */
-	Tcache,			/* cw cache things */
-	MAXTAG
-};
-
-#define	QPDIR	0x80000000L
-#define	QPNONE	0
-#define	QPROOT	1
-#define	QPSUPER	2
-
-/* DONT TOUCH, this is the disk structure */
-struct	Tag
-{
-	short	pad;
-	short	tag;
-	long	path;
-};
-
-static int thisblock = -1;
-static Fs *thisfs;
-static uchar *block;
-
-/*
- * we end up reading 2x or 3x the number of blocks we need to read.
- * this is okay because we need to read so few.  if it wasn't okay, we could
- * have getblock return a pointer to a block, and keep a cache of the last
- * three read blocks.  that would get us down to the minimum.
- * but this is fine.
- */
-static int
-getblock(Fs *fs, ulong n)
-{
-	if(!block)
-		block = malloc(16384);
-
-	if(thisblock == n && thisfs == fs)
-		return 0;
-	thisblock = -1;
-	if(fs->diskseek(fs, (vlong)n*fs->kfs.RBUFSIZE) < 0)
-		return -1;
-	if(fs->diskread(fs, block, fs->kfs.RBUFSIZE) != fs->kfs.RBUFSIZE)
-		return -1;
-	thisblock = n;
-	thisfs = fs;
-
-	return 1;
-}
-
-static int
-checktag(Fs *fs, uchar *block, int tag, long qpath)
-{
-	Tag *t;
-
-	t = (Tag*)(block+fs->kfs.BUFSIZE);
-	if(t->tag != tag)
-		return -1;
-	if(qpath != QPNONE && (qpath&~QPDIR) != t->path)
-		return -1;
-	return 1;
-}
-
-static int
-getblocktag(Fs *fs, ulong n, int tag, long qpath)
-{
-	if(getblock(fs, n) < 0 || checktag(fs, block, tag, qpath) < 0)
-		return -1;
-	return 1;
-}
-
-static int
-readinfo(Fs *fs)
-{
-	fs->kfs.RBUFSIZE = 512;
-	if(getblock(fs, 0) < 0)
-		return -1;
-
-	if(memcmp(block+256, "kfs wren device\n", 16) != 0)
-		return -1;
-
-	fs->kfs.RBUFSIZE = atoi((char*)block+256+16);
-	if(!fs->kfs.RBUFSIZE || (fs->kfs.RBUFSIZE&(fs->kfs.RBUFSIZE-1)))
-		return -1;
-
-	fs->kfs.BUFSIZE = fs->kfs.RBUFSIZE - sizeof(Tag);
-	fs->kfs.DIRPERBUF = fs->kfs.BUFSIZE / sizeof(Dentry);
-	fs->kfs.INDPERBUF = fs->kfs.BUFSIZE / sizeof(long);
-	fs->kfs.INDPERBUF2 = fs->kfs.INDPERBUF * fs->kfs.INDPERBUF;
-
-	return 1;
-}
-
-static int
-readroot(Fs *fs, Dentry *d)
-{
-	Dentry *d2;
-
-	if(getblocktag(fs, 2, Tdir, QPROOT) < 0)
-		return -1;
-	d2 = (Dentry*)block;
-	if(strcmp(d2->name, "/") != 0)
-		return -1;
-	*d = *(Dentry*)block;
-	return 1;
-}
-
-static long
-indfetch(Fs *fs, long addr, long off, int tag, long path)
-{
-	if(getblocktag(fs, addr, tag, path) < 0)
-		return -1;
-	return ((long*)block)[off];
-}
-
-static long
-rel2abs(Fs *fs, Dentry *d, long a)
-{
-	long addr;
-
-	if(a < NDBLOCK)
-		return d->dblock[a];
-	a -= NDBLOCK;
-	if(a < fs->kfs.INDPERBUF){
-		if(d->iblock == 0)
-			return 0;
-		addr = indfetch(fs, d->iblock, a, Tind1, d->qid.path);
-		if(addr == 0)
-			print("rel2abs indfetch 0 %s %ld\n", d->name, a);
-		return addr;
-	}
-	a -= fs->kfs.INDPERBUF;
-	if(a < fs->kfs.INDPERBUF2){
-		if(d->diblock == 0)
-			return 0;
-		addr = indfetch(fs, d->diblock, a/fs->kfs.INDPERBUF, Tind2, d->qid.path);
-		if(addr == 0){
-			print("rel2abs indfetch 0 %s %ld\n", d->name, a/fs->kfs.INDPERBUF);
-			return 0;
-		}
-		addr = indfetch(fs, addr, a%fs->kfs.INDPERBUF, Tind1, d->qid.path);
-		return addr;
-	}
-	print("rel2abs trip ind %s %ld\n", d->name, a);
-	return -1;
-}
-
-static int
-readdentry(Fs *fs, Dentry *d, int n, Dentry *e)
-{
-	long addr, m;
-
-	m = n/fs->kfs.DIRPERBUF;
-	if((addr = rel2abs(fs, d, m)) <= 0)
-		return addr;
-	if(getblocktag(fs, addr, Tdir, d->qid.path) < 0)
-		return -1;
-	*e = *(Dentry*)(block+(n%fs->kfs.DIRPERBUF)*sizeof(Dentry));
-	return 1;
-}
-
-static int
-getdatablock(Fs *fs, Dentry *d, long a)
-{
-	long addr;
-
-	if((addr = rel2abs(fs, d, a)) == 0)
-		return -1;
-	return getblocktag(fs, addr, Tfile, QPNONE);
-}
-
-static int
-walk(Fs *fs, Dentry *d, char *name, Dentry *e)
-{
-	int i, n;
-	Dentry x;
-
-	for(i=0;; i++){
-		if((n=readdentry(fs, d, i, &x)) <= 0)
-			return n;
-		if(strcmp(x.name, name) == 0){
-			*e = x;
-			return 1;
-		}
-	}
-}
-
-static long
-kfsread(File *f, void *va, long len)
-{
-	uchar *a;
-	long tot, off, o, n;
-	Fs *fs;
-
-	a = va;
-	fs = f->fs;
-	off = f->kfs.off;
-	tot = 0;
-	while(tot < len){
-		if(getdatablock(fs, &f->kfs, off/fs->kfs.BUFSIZE) < 0)
-			return -1;
-		o = off%fs->kfs.BUFSIZE;
-		n = fs->kfs.BUFSIZE - o;
-		if(n > len-tot)
-			n = len-tot;
-		memmove(a+tot, block+o, n);
-		off += n;
-		tot += n;
-	}
-	f->kfs.off = off;
-	return tot;
-}
-
-static int
-kfswalk(File *f, char *name)
-{
-	int n;
-
-	n = walk(f->fs, &f->kfs, name, &f->kfs);
-	if(n < 0)
-		return -1;
-	f->kfs.off = 0;
-	return 1;
-}
-
-int
-kfsinit(Fs *fs)
-{
-	if(readinfo(fs) < 0 || readroot(fs, &fs->root.kfs) < 0)
-		return -1;
-
-	fs->root.fs = fs;
-	fs->read = kfsread;
-	fs->walk = kfswalk;
-	return 0;
-}
--- a/os/boot/pc/l.s
+++ /dev/null
@@ -1,1084 +1,0 @@
-#include "x16.h"
-#include "mem.h"
-
-#define WRMSR		BYTE $0x0F; BYTE $0x30	/* WRMSR, argument in AX/DX (lo/hi) */
-#define RDTSC 		BYTE $0x0F; BYTE $0x31	/* RDTSC, result in AX/DX (lo/hi) */
-#define RDMSR		BYTE $0x0F; BYTE $0x32	/* RDMSR, result in AX/DX (lo/hi) */
-
-#ifdef PXE
-#define PDB		0x90000		/* temporary page tables (24KB) */
-#else
-#define PDB		0x08000
-#endif PXE
-
-#define NoScreenBlank	1
-/*#define ResetDiscs	1*/
-
-TEXT origin(SB), $0
-	/*
-	 * This part of l.s is used only in the boot kernel.
-	 * It assumes that we are in real address mode, i.e.,
-	 * that we look like an 8086.
-	 *
-	 * Make sure the segments are reasonable.
-	 * If we were started directly from the BIOS
-	 * (i.e. no MS-DOS) then DS may not be
-	 * right.
-	 */
-	MOVW	CS, AX
-	MOVW	AX, DS
-
-#ifdef NoScreenBlank
-	/*
-	 * Get the current video mode. If it isn't mode 3,
-	 * set text mode 3.
-	 * Well, no. Windows95 won't co-operate here so we have
-	 * to explicitly set mode 3.
-	 */
-	XORL	AX, AX
-	MOVB	$0x0F, AH
-	INT	$0x10			/* get current video mode in AL */
-	CMPB	AL, $03
-	JEQ	sayhello
-#endif /* NoScreenBlank */
-	XORL	AX, AX
-	MOVB	$0x03, AL
-	INT	$0x10			/* set video mode in AL */
-
-sayhello:
-	LWI(hello(SB), rSI)
-	CALL16(biosputs(SB))
-
-#ifdef ResetDiscs
-	XORL	AX, AX			/* reset disc system */
-	XORL	DX, DX
-	MOVB	$0x80, DL
-	INT	$0x13
-#endif /* ResetDiscs */
-
-#ifdef DOTCOM
-/*
- *	relocate everything to a half meg and jump there
- *	- looks weird because it is being assembled by a 32 bit
- *	  assembler for a 16 bit world
- *
- *	only b.com does this - not 9load
- */
-	MOVL	$0,BX
-	INCL	BX
-	SHLL	$15,BX
-	MOVL	BX,CX
-	MOVW	BX,ES
-	MOVL	$0,SI
-	MOVL	SI,DI
-	CLD
-	REP
-	MOVSL
-
-	/*
-	 * Jump to the copied image;
-	 * fix up the DS for the new location.
-	 */
-	FARJUMP16(0x8000, _start8000(SB))
-
-TEXT _start8000(SB), $0
-	MFSR(rCS, rAX)			/* fix up DS, ES (0x8000) */
-	MTSR(rAX, rDS)
-	MTSR(rAX, rES)
-
-	/*
-	 * If we are already in protected mode, have to get back
-	 * to real mode before trying any privileged operations
-	 * (like going into protected mode...).
-	 * Try to reset with a restart vector.
-	 */
-	MFCR(rCR0, rAX)			/* are we in protected mode? */
-	ANDI(0x0001, rAX)
-	JEQ	_real
-
-	CLR(rBX)
-	MTSR(rBX, rES)
-
-	LWI(0x0467, rBX)		/* reset entry point */
-	LWI(_start8000(SB), rAX)	/* offset within segment */
-	BYTE	$0x26
-	BYTE	$0x89
-	BYTE	$0x07			/* MOVW	AX, ES:[BX] */
-	LBI(0x69, rBL)
-	MFSR(rCS, rAX)			/* segment */
-	BYTE	$0x26
-	BYTE	$0x89
-	BYTE	$0x07			/* MOVW	AX, ES:[BX] */
-
-	CLR(rDX)
-	OUTPORTB(0x70, 0x8F)
-	OUTPORTB(0x71, 0x0A)
-
-	FARJUMP16(0xFFFF, 0x0000)		/* reset */
-#endif /* DOTCOM */
-
-_real:
-
-/*
- *	do things that need to be done in real mode.
- *	the results get written to CONFADDR (0x1200)
- *	in a series of <4-byte-magic-number><block-of-data>
- *	the data length is dependent on the magic number.
- *
- *	this gets parsed by conf.c:/^readlsconf
- *
- *	N.B. CALL16 kills rDI, so we can't call anything.
- */
-	LWI(0x0000, rAX)
-	MTSR(rAX, rES)
-	LWI(0x1200, rDI)
-
-/*
- *	turn off interrupts
- */
-	CLI
-
-/*
- *	detect APM1.2 bios support
- */
-	/* save DI */
-	SW(rDI, rock(SB))
-
-	/* disconnect anyone else */
-	LWI(0x5304, rAX)
-	LWI(0x0000, rBX)
-	INT $0x15
-
-	/* connect */
-	CLC
-	LWI(0x5303, rAX)
-	LWI(0x0000, rBX)
-	INT $0x15
-	CLI	/* apm put interrupts back? */
-
-	JC noapm
-
-	OPSIZE; PUSHR(rSI)
-	OPSIZE; PUSHR(rBX)
-	PUSHR(rDI)
-	PUSHR(rDX)
-	PUSHR(rCX)
-	PUSHR(rAX)
-
-	/* put DI, ES back */
-	LW(rock(SB), rDI)
-	LWI(0x0000, rAX)
-	MTSR(rAX, rES)
-
-	/*
-	 * write APM data.  first four bytes are APM\0.
-	 */
-	LWI(0x5041, rAX)
-	STOSW
-
-	LWI(0x004d, rAX)
-	STOSW
-
-	LWI(8, rCX)
-apmmove:
-	POPR(rAX)
-	STOSW
-	LOOP apmmove
-
-noapm:
-
-/*
- *	end of real mode hacks: write terminator, put ES back.
- */
-	LWI(0x0000, rAX)
-	STOSW
-	STOSW
-
-	MFSR(rCS, rAX)			/* fix up ES (0x8000) */
-	MTSR(rAX, rES)
-
-/*
- * 	goto protected mode
- */
-/*	MOVL	tgdtptr(SB),GDTR /**/
-	 BYTE	$0x0f
-	 BYTE	$0x01
-	 BYTE	$0x16
-	 WORD	$tgdtptr(SB)
-
-	LWI(1, rAX)
-	/* MOV AX,MSW */
-	BYTE $0x0F; BYTE $0x01; BYTE $0xF0
-
-/*
- *	clear prefetch queue (weird code to avoid optimizations)
- */
-	/* JMP .+2 */
-	BYTE $0xEB
-	BYTE $0x00
-
-/*
- *	set all segs
- */
-/*	MOVW	$SELECTOR(1, SELGDT, 0),AX	/**/
-	 BYTE	$0xc7
-	 BYTE	$0xc0
-	 WORD	$SELECTOR(1, SELGDT, 0)
-	MOVW	AX,DS
-	MOVW	AX,SS
-	MOVW	AX,ES
-	MOVW	AX,FS
-	MOVW	AX,GS
-
-/*	JMPFAR	SELECTOR(2, SELGDT, 0):$mode32bit(SB) /**/
-	 BYTE	$0x66
-	 BYTE	$0xEA
-	 LONG	$mode32bit-KZERO(SB)
-	 WORD	$SELECTOR(2, SELGDT, 0)
-
-TEXT	mode32bit(SB),$0
-	/*
-	 *  make a bottom level page table page that maps the first
-	 *  16 meg of physical memory
-	 */
-	MOVL	$PDB, DI			/* clear 6 pages for the tables etc. */
-	XORL	AX, AX
-	MOVL	$(6*BY2PG), CX
-	SHRL	$2, CX
-
-	CLD
-	REP;	STOSL
-
-	MOVL	$PDB, AX		/* phys addr of temporary page table */
-	MOVL	$(4*1024),CX		/* pte's per page */
-	MOVL	$((((4*1024)-1)<<PGSHIFT)|PTEVALID|PTEKERNEL|PTEWRITE),BX
-setpte:
-	MOVL	BX,-4(AX)(CX*4)
-	SUBL	$(1<<PGSHIFT),BX
-	LOOP	setpte
-
-	/*
-	 *  make a top level page table page that maps the first
-	 *  16 meg of memory to 0 thru 16meg and to KZERO thru KZERO+16meg
-	 */
-	MOVL	AX,BX
-	ADDL	$(4*BY2PG),AX
-	ADDL	$(PTEVALID|PTEKERNEL|PTEWRITE),BX
-	MOVL	BX,0(AX)
-	MOVL	BX,((((KZERO>>1)&0x7FFFFFFF)>>(2*PGSHIFT-1-4))+0)(AX)
-	ADDL	$BY2PG,BX
-	MOVL	BX,4(AX)
-	MOVL	BX,((((KZERO>>1)&0x7FFFFFFF)>>(2*PGSHIFT-1-4))+4)(AX)
-	ADDL	$BY2PG,BX
-	MOVL	BX,8(AX)
-	MOVL	BX,((((KZERO>>1)&0x7FFFFFFF)>>(2*PGSHIFT-1-4))+8)(AX)
-	ADDL	$BY2PG,BX
-	MOVL	BX,12(AX)
-	MOVL	BX,((((KZERO>>1)&0x7FFFFFFF)>>(2*PGSHIFT-1-4))+12)(AX)
-
-	/*
-	 *  point processor to top level page & turn on paging
-	 *
-	 *  this produces the apparently harmless "VMX|F(125):468 Dis 0x0:0x0"
-	 *  message in the VMware log.
-	 */
-	MOVL	AX,CR3
-	MOVL	CR0,AX
-	ORL	$0X80000000,AX
-	MOVL	AX,CR0
-
-	/*
-	 *  use a jump to an absolute location to get the PC into
-	 *  KZERO.
-	 */
-	LEAL	tokzero(SB),AX
-	JMP*	AX
-
-/*
- * When we load 9load from DOS, the bootstrap jumps
- * to the instruction right after `JUMP', which gets
- * us into kzero.
- *
- * The name prevents it from being optimized away.
- */
-TEXT jumplabel(SB), $0
-	BYTE $'J'; BYTE $'U'; BYTE $'M'; BYTE $'P'
-
-	LEAL	tokzero(SB),AX
-	JMP*	AX
-
-TEXT	tokzero(SB),$0
-	/*
-	 * Clear BSS
-	 */
-	LEAL	edata(SB),SI
-	MOVL	SI,DI
-	ADDL	$4,DI
-	MOVL	$0,AX
-	MOVL	AX,(SI)
-	LEAL	end(SB),CX
-	SUBL	DI,CX
-	SHRL	$2,CX
-	CLD
-	REP
-	MOVSL
-
-	/*
-	 *  stack and mach
-	 */
-	MOVL	$mach0(SB),SP
-	MOVL	SP,m(SB)
-	MOVL	$0,0(SP)
-	ADDL	$(MACHSIZE-4),SP	/* start stack above machine struct */
-
-	CALL	main(SB)
-
-loop:
-	JMP	loop
-
-GLOBL	mach0+0(SB), $MACHSIZE
-GLOBL	m(SB), $4
-
-/*
- *  gdt to get us to 32-bit/segmented/unpaged mode
- */
-TEXT	tgdt(SB),$0
-
-	/* null descriptor */
-	LONG	$0
-	LONG	$0
-
-	/* data segment descriptor for 4 gigabytes (PL 0) */
-	LONG	$(0xFFFF)
-	LONG	$(SEGG|SEGB|(0xF<<16)|SEGP|SEGPL(0)|SEGDATA|SEGW)
-
-	/* exec segment descriptor for 4 gigabytes (PL 0) */
-	LONG	$(0xFFFF)
-	LONG	$(SEGG|SEGD|(0xF<<16)|SEGP|SEGPL(0)|SEGEXEC|SEGR)
-
-	/* exec segment descriptor for 4 gigabytes (PL 0) 16-bit */
-	LONG	$(0xFFFF)
-	LONG	$(SEGG|(0xF<<16)|SEGP|SEGPL(0)|SEGEXEC|SEGR)
-
-/*
- *  pointer to initial gdt
- */
-TEXT	tgdtptr(SB),$0
-	WORD	$(4*8)
-	LONG	$tgdt-KZERO(SB)
-
-/*
- * Output a string to the display.
- * String argument is in rSI.
- */
-TEXT biosputs(SB), $0
-	PUSHA
-	CLR(rBX)
-_BIOSputs:
-	LODSB
-	ORB(rAL, rAL)
-	JEQ _BIOSputsret
-
-	LBI(0x0E, rAH)
-	BIOSCALL(0x10)
-	JMP _BIOSputs
-
-_BIOSputsret:
-	POPA
-	RET
-
-/*
- *  input a byte
- */
-TEXT	inb(SB),$0
-
-	MOVL	p+0(FP),DX
-	XORL	AX,AX
-	INB
-	RET
-
-/*
- * input a short from a port
- */
-TEXT	ins(SB), $0
-
-	MOVL	p+0(FP), DX
-	XORL	AX, AX
-	OPSIZE; INL
-	RET
-
-/*
- * input a long from a port
- */
-TEXT	inl(SB), $0
-
-	MOVL	p+0(FP), DX
-	XORL	AX, AX
-	INL
-	RET
-
-/*
- *  output a byte
- */
-TEXT	outb(SB),$0
-
-	MOVL	p+0(FP),DX
-	MOVL	b+4(FP),AX
-	OUTB
-	RET
-
-/*
- * output a short to a port
- */
-TEXT	outs(SB), $0
-	MOVL	p+0(FP), DX
-	MOVL	s+4(FP), AX
-	OPSIZE; OUTL
-	RET
-
-/*
- * output a long to a port
- */
-TEXT	outl(SB), $0
-	MOVL	p+0(FP), DX
-	MOVL	s+4(FP), AX
-	OUTL
-	RET
-
-/*
- *  input a string of bytes from a port
- */
-TEXT	insb(SB),$0
-
-	MOVL	p+0(FP),DX
-	MOVL	a+4(FP),DI
-	MOVL	c+8(FP),CX
-	CLD; REP; INSB
-	RET
-
-/*
- *  input a string of shorts from a port
- */
-TEXT	inss(SB),$0
-	MOVL	p+0(FP),DX
-	MOVL	a+4(FP),DI
-	MOVL	c+8(FP),CX
-	CLD
-	REP; OPSIZE; INSL
-	RET
-
-/*
- *  output a string of bytes to a port
- */
-TEXT	outsb(SB),$0
-
-	MOVL	p+0(FP),DX
-	MOVL	a+4(FP),SI
-	MOVL	c+8(FP),CX
-	CLD; REP; OUTSB
-	RET
-
-/*
- *  output a string of shorts to a port
- */
-TEXT	outss(SB),$0
-	MOVL	p+0(FP),DX
-	MOVL	a+4(FP),SI
-	MOVL	c+8(FP),CX
-	CLD
-	REP; OPSIZE; OUTSL
-	RET
-
-/*
- *  input a string of longs from a port
- */
-TEXT	insl(SB),$0
-
-	MOVL	p+0(FP),DX
-	MOVL	a+4(FP),DI
-	MOVL	c+8(FP),CX
-	CLD; REP; INSL
-	RET
-
-/*
- *  output a string of longs to a port
- */
-TEXT	outsl(SB),$0
-
-	MOVL	p+0(FP),DX
-	MOVL	a+4(FP),SI
-	MOVL	c+8(FP),CX
-	CLD; REP; OUTSL
-	RET
-
-/*
- *  routines to load/read various system registers
- */
-GLOBL	idtptr(SB),$6
-TEXT	putidt(SB),$0		/* interrupt descriptor table */
-	MOVL	t+0(FP),AX
-	MOVL	AX,idtptr+2(SB)
-	MOVL	l+4(FP),AX
-	MOVW	AX,idtptr(SB)
-	MOVL	idtptr(SB),IDTR
-	RET
-
-TEXT	putcr3(SB),$0		/* top level page table pointer */
-	MOVL	t+0(FP),AX
-	MOVL	AX,CR3
-	RET
-
-TEXT	getcr0(SB),$0		/* coprocessor bits */
-	MOVL	CR0,AX
-	RET
-
-TEXT	getcr2(SB),$0		/* fault address */
-	MOVL	CR2,AX
-	RET
-
-TEXT	getcr3(SB),$0		/* page directory base */
-	MOVL	CR3,AX
-	RET
-
-TEXT	getcr4(SB), $0		/* CR4 - extensions */
-	MOVL	CR4, AX
-	RET
-
-TEXT _cycles(SB), $0				/* time stamp counter */
-	RDTSC
-	MOVL	vlong+0(FP), CX			/* &vlong */
-	MOVL	AX, 0(CX)			/* lo */
-	MOVL	DX, 4(CX)			/* hi */
-	RET
-
-TEXT rdmsr(SB), $0				/* model-specific register */
-	MOVL	index+0(FP), CX
-	RDMSR
-	MOVL	vlong+4(FP), CX			/* &vlong */
-	MOVL	AX, 0(CX)			/* lo */
-	MOVL	DX, 4(CX)			/* hi */
-	RET
-	
-TEXT wrmsr(SB), $0
-	MOVL	index+0(FP), CX
-	MOVL	lo+4(FP), AX
-	MOVL	hi+8(FP), DX
-	WRMSR
-	RET
-
-TEXT mb386(SB), $0
-	POPL	AX				/* return PC */
-	PUSHFL
-	PUSHL	CS
-	PUSHL	AX
-	IRETL
-
-/*
- *  special traps
- */
-TEXT	intr0(SB),$0
-	PUSHL	$0
-	PUSHL	$0
-	JMP	intrcommon
-TEXT	intr1(SB),$0
-	PUSHL	$0
-	PUSHL	$1
-	JMP	intrcommon
-TEXT	intr2(SB),$0
-	PUSHL	$0
-	PUSHL	$2
-	JMP	intrcommon
-TEXT	intr3(SB),$0
-	PUSHL	$0
-	PUSHL	$3
-	JMP	intrcommon
-TEXT	intr4(SB),$0
-	PUSHL	$0
-	PUSHL	$4
-	JMP	intrcommon
-TEXT	intr5(SB),$0
-	PUSHL	$0
-	PUSHL	$5
-	JMP	intrcommon
-TEXT	intr6(SB),$0
-	PUSHL	$0
-	PUSHL	$6
-	JMP	intrcommon
-TEXT	intr7(SB),$0
-	PUSHL	$0
-	PUSHL	$7
-	JMP	intrcommon
-TEXT	intr8(SB),$0
-	PUSHL	$8
-	JMP	intrcommon
-TEXT	intr9(SB),$0
-	PUSHL	$0
-	PUSHL	$9
-	JMP	intrcommon
-TEXT	intr10(SB),$0
-	PUSHL	$10
-	JMP	intrcommon
-TEXT	intr11(SB),$0
-	PUSHL	$11
-	JMP	intrcommon
-TEXT	intr12(SB),$0
-	PUSHL	$12
-	JMP	intrcommon
-TEXT	intr13(SB),$0
-	PUSHL	$13
-	JMP	intrcommon
-TEXT	intr14(SB),$0
-	PUSHL	$14
-	JMP	intrcommon
-TEXT	intr15(SB),$0
-	PUSHL	$0
-	PUSHL	$15
-	JMP	intrcommon
-TEXT	intr16(SB),$0
-	PUSHL	$0
-	PUSHL	$16
-	JMP	intrcommon
-TEXT	intr24(SB),$0
-	PUSHL	$0
-	PUSHL	$24
-	JMP	intrcommon
-TEXT	intr25(SB),$0
-	PUSHL	$0
-	PUSHL	$25
-	JMP	intrcommon
-TEXT	intr26(SB),$0
-	PUSHL	$0
-	PUSHL	$26
-	JMP	intrcommon
-TEXT	intr27(SB),$0
-	PUSHL	$0
-	PUSHL	$27
-	JMP	intrcommon
-TEXT	intr28(SB),$0
-	PUSHL	$0
-	PUSHL	$28
-	JMP	intrcommon
-TEXT	intr29(SB),$0
-	PUSHL	$0
-	PUSHL	$29
-	JMP	intrcommon
-TEXT	intr30(SB),$0
-	PUSHL	$0
-	PUSHL	$30
-	JMP	intrcommon
-TEXT	intr31(SB),$0
-	PUSHL	$0
-	PUSHL	$31
-	JMP	intrcommon
-TEXT	intr32(SB),$0
-	PUSHL	$0
-	PUSHL	$32
-	JMP	intrcommon
-TEXT	intr33(SB),$0
-	PUSHL	$0
-	PUSHL	$33
-	JMP	intrcommon
-TEXT	intr34(SB),$0
-	PUSHL	$0
-	PUSHL	$34
-	JMP	intrcommon
-TEXT	intr35(SB),$0
-	PUSHL	$0
-	PUSHL	$35
-	JMP	intrcommon
-TEXT	intr36(SB),$0
-	PUSHL	$0
-	PUSHL	$36
-	JMP	intrcommon
-TEXT	intr37(SB),$0
-	PUSHL	$0
-	PUSHL	$37
-	JMP	intrcommon
-TEXT	intr38(SB),$0
-	PUSHL	$0
-	PUSHL	$38
-	JMP	intrcommon
-TEXT	intr39(SB),$0
-	PUSHL	$0
-	PUSHL	$39
-	JMP	intrcommon
-TEXT	intr64(SB),$0
-	PUSHL	$0
-	PUSHL	$64
-	JMP	intrcommon
-TEXT	intrbad(SB),$0
-	PUSHL	$0
-	PUSHL	$0x1ff
-	JMP	intrcommon
-
-intrcommon:
-	PUSHL	DS
-	PUSHL	ES
-	PUSHL	FS
-	PUSHL	GS
-	PUSHAL
-	MOVL	$(KDSEL),AX
-	MOVW	AX,DS
-	MOVW	AX,ES
-	LEAL	0(SP),AX
-	PUSHL	AX
-	CALL	trap(SB)
-	POPL	AX
-	POPAL
-	POPL	GS
-	POPL	FS
-	POPL	ES
-	POPL	DS
-	ADDL	$8,SP	/* error code and trap type */
-	IRETL
-
-
-/*
- *  interrupt level is interrupts on or off
- */
-TEXT	spllo(SB),$0
-	PUSHFL
-	POPL	AX
-	STI
-	RET
-
-TEXT	splhi(SB),$0
-	PUSHFL
-	POPL	AX
-	CLI
-	RET
-
-TEXT	splx(SB),$0
-	MOVL	s+0(FP),AX
-	PUSHL	AX
-	POPFL
-	RET
-
-/*
- *  do nothing whatsoever till interrupt happens
- */
-TEXT	idle(SB),$0
-	HLT
-	RET
-
-/*
- * Try to determine the CPU type which requires fiddling with EFLAGS.
- * If the Id bit can be toggled then the CPUID instruciton can be used
- * to determine CPU identity and features. First have to check if it's
- * a 386 (Ac bit can't be set). If it's not a 386 and the Id bit can't be
- * toggled then it's an older 486 of some kind.
- *
- *	cpuid(id[], &ax, &dx);
- */
-#define CPUID		BYTE $0x0F; BYTE $0xA2	/* CPUID, argument in AX */
-TEXT cpuid(SB), $0
-	MOVL	$0x240000, AX
-	PUSHL	AX
-	POPFL					/* set Id|Ac */
-
-	PUSHFL
-	POPL	BX				/* retrieve value */
-
-	MOVL	$0, AX
-	PUSHL	AX
-	POPFL					/* clear Id|Ac, EFLAGS initialised */
-
-	PUSHFL
-	POPL	AX				/* retrieve value */
-	XORL	BX, AX
-	TESTL	$0x040000, AX			/* Ac */
-	JZ	_cpu386				/* can't set this bit on 386 */
-	TESTL	$0x200000, AX			/* Id */
-	JZ	_cpu486				/* can't toggle this bit on some 486 */
-
-	MOVL	$0, AX
-	CPUID
-	MOVL	id+0(FP), BP
-	MOVL	BX, 0(BP)			/* "Genu" "Auth" "Cyri" */
-	MOVL	DX, 4(BP)			/* "ineI" "enti" "xIns" */
-	MOVL	CX, 8(BP)			/* "ntel" "cAMD" "tead" */
-
-	MOVL	$1, AX
-	CPUID
-	JMP	_cpuid
-
-_cpu486:
-	MOVL	$0x400, AX
-	MOVL	$0, DX
-	JMP	_cpuid
-
-_cpu386:
-	MOVL	$0x300, AX
-	MOVL	$0, DX
-
-_cpuid:
-	MOVL	ax+4(FP), BP
-	MOVL	AX, 0(BP)
-	MOVL	dx+8(FP), BP
-	MOVL	DX, 0(BP)
-	RET
-
-
-/*
- *  basic timing loop to determine CPU frequency
- */
-TEXT	aamloop(SB),$0
-
-	MOVL	c+0(FP),CX
-aaml1:
-	AAM
-	LOOP	aaml1
-	RET
-
-TEXT hello(SB), $0
-	BYTE $'P'; BYTE $'l'; BYTE $'a'; BYTE $'n';
-	BYTE $' '; BYTE $'9'; BYTE $' '; BYTE $'f';
-	BYTE $'r'; BYTE $'o'; BYTE $'m'; BYTE $' ';
-	BYTE $'B'; BYTE $'e'; BYTE $'l'; BYTE $'l';
-	BYTE $' '; BYTE $'L'; BYTE $'a'; BYTE $'b';
-	BYTE $'s'; 
-#ifdef PXE
-	BYTE $' '; BYTE $'b'; BYTE $'y'; BYTE $' ';
-	BYTE $'P'; BYTE $'X'; BYTE $'E';
-#endif
-	BYTE $'\r';
-	BYTE $'\n';
-	BYTE $'\z';
-
-TEXT rock(SB), $0
-	BYTE $0; BYTE $0; BYTE $0; BYTE $0;
-
-GLOBL pxe(SB), $4
-#ifdef PXE
-DATA	pxe+0(SB)/4, $1
-#else
-DATA	pxe+0(SB)/4, $0
-#endif /* PXE */
-
-/*
- * Save registers.
- */
-TEXT saveregs(SB), $0
-	/* appease 8l */
-	SUBL $32, SP
-	POPL AX
-	POPL AX
-	POPL AX
-	POPL AX
-	POPL AX
-	POPL AX
-	POPL AX
-	POPL AX
-	
-	PUSHL	AX
-	PUSHL	BX
-	PUSHL	CX
-	PUSHL	DX
-	PUSHL	BP
-	PUSHL	DI
-	PUSHL	SI
-	PUSHFL
-
-	XCHGL	32(SP), AX	/* swap return PC and saved flags */
-	XCHGL	0(SP), AX
-	XCHGL	32(SP), AX
-	RET
-
-TEXT restoreregs(SB), $0
-	/* appease 8l */
-	PUSHL	AX
-	PUSHL	AX
-	PUSHL	AX
-	PUSHL	AX
-	PUSHL	AX
-	PUSHL	AX
-	PUSHL	AX
-	PUSHL	AX
-	ADDL	$32, SP
-	
-	XCHGL	32(SP), AX	/* swap return PC and saved flags */
-	XCHGL	0(SP), AX
-	XCHGL	32(SP), AX
-
-	POPFL
-	POPL	SI
-	POPL	DI
-	POPL	BP
-	POPL	DX
-	POPL	CX
-	POPL	BX
-	POPL	AX
-	RET
-
-/*
- * Assumed to be in protected mode at time of call.
- * Switch to real mode, execute an interrupt, and
- * then switch back to protected mode.  
- *
- * Assumes:
- *
- *	- no device interrupts are going to come in
- *	- 0-16MB is identity mapped in page tables
- *	- can use code segment 0x1000 in real mode
- *		to get at l.s code
- */
-TEXT realmodeidtptr(SB), $0
-	WORD	$(4*256-1)
-	LONG	$0
-
-TEXT realmode0(SB), $0
-	CALL	saveregs(SB)
-
-	/* switch to low code address */
-	LEAL	physcode-KZERO(SB), AX
-	JMP *AX
-
-TEXT physcode(SB), $0
-
-	/* switch to low stack */
-	MOVL	SP, AX
-	MOVL	$0x7C00, SP
-	PUSHL	AX
-
-	/* load IDT with real-mode version; GDT already fine */
-	MOVL	realmodeidtptr(SB), IDTR
-
-	/* edit INT $0x00 instruction below */
-	MOVL	realmodeintr(SB), AX
-	MOVB	AX, realmodeintrinst+1(SB)
-
-	/* disable paging */
-	MOVL	CR0, AX
-	ANDL	$0x7FFFFFFF, AX
-	MOVL	AX, CR0
-	/* JMP .+2 to clear prefetch queue*/
-	BYTE $0xEB; BYTE $0x00
-
-	/* jump to 16-bit code segment */
-/*	JMPFAR	SELECTOR(3, SELGDT, 0):$again16bit(SB) /**/
-	 BYTE	$0xEA
-	 LONG	$again16bit-KZERO(SB)
-	 WORD	$SELECTOR(3, SELGDT, 0)
-
-TEXT again16bit(SB), $0
-	/*
-	 * Now in 16-bit compatibility mode.
-	 * These are 32-bit instructions being interpreted
-	 * as 16-bit instructions.  I'm being lazy and
-	 * not using the macros because I know when
-	 * the 16- and 32-bit instructions look the same
-	 * or close enough.
-	 */
-
-	/* disable protected mode and jump to real mode cs */
-	OPSIZE; MOVL CR0, AX
-	OPSIZE; XORL BX, BX
-	OPSIZE; INCL BX
-	OPSIZE; XORL BX, AX
-	OPSIZE; MOVL AX, CR0
-
-	/* JMPFAR 0x1000:now16real */
-	 BYTE $0xEA
-	 WORD	$now16real-KZERO(SB)
-	 WORD	$0x1000
-
-TEXT now16real(SB), $0
-	/* copy the registers for the bios call */
-	LWI(0x1000, rAX)
-	MOVW	AX,SS
-	LWI(realmoderegs(SB), rBP)
-	
-	/* offsets are in Ureg */
-	LXW(44, xBP, rAX)
-	MOVW	AX, DS
-	LXW(40, xBP, rAX)
-	MOVW	AX, ES
-
-	OPSIZE; LXW(0, xBP, rDI)
-	OPSIZE; LXW(4, xBP, rSI)
-	OPSIZE; LXW(16, xBP, rBX)
-	OPSIZE; LXW(20, xBP, rDX)
-	OPSIZE; LXW(24, xBP, rCX)
-	OPSIZE; LXW(28, xBP, rAX)
-
-	CLC
-
-TEXT realmodeintrinst(SB), $0
-	INT $0x00
-
-
-	/* save the registers after the call */
-
-	LWI(0x7bfc, rSP)
-	OPSIZE; PUSHFL
-	OPSIZE; PUSHL AX
-
-	LWI(0x1000, rAX)
-	MOVW	AX,SS
-	LWI(realmoderegs(SB), rBP)
-	
-	OPSIZE; SXW(rDI, 0, xBP)
-	OPSIZE; SXW(rSI, 4, xBP)
-	OPSIZE; SXW(rBX, 16, xBP)
-	OPSIZE; SXW(rDX, 20, xBP)
-	OPSIZE; SXW(rCX, 24, xBP)
-	OPSIZE; POPL AX
-	OPSIZE; SXW(rAX, 28, xBP)
-
-	MOVW	DS, AX
-	OPSIZE; SXW(rAX, 44, xBP)
-	MOVW	ES, AX
-	OPSIZE; SXW(rAX, 40, xBP)
-
-	OPSIZE; POPL AX
-	OPSIZE; SXW(rAX, 64, xBP)	/* flags */
-
-	/* re-enter protected mode and jump to 32-bit code */
-	OPSIZE; MOVL $1, AX
-	OPSIZE; MOVL AX, CR0
-	
-/*	JMPFAR	SELECTOR(2, SELGDT, 0):$again32bit(SB) /**/
-	 OPSIZE
-	 BYTE $0xEA
-	 LONG	$again32bit-KZERO(SB)
-	 WORD	$SELECTOR(2, SELGDT, 0)
-
-TEXT again32bit(SB), $0
-	MOVW	$SELECTOR(1, SELGDT, 0),AX
-	MOVW	AX,DS
-	MOVW	AX,SS
-	MOVW	AX,ES
-	MOVW	AX,FS
-	MOVW	AX,GS
-
-	/* enable paging and jump to kzero-address code */
-	MOVL	CR0, AX
-	ORL	$0x80000000, AX
-	MOVL	AX, CR0
-	LEAL	again32kzero(SB), AX
-	JMP*	AX
-
-TEXT again32kzero(SB), $0
-	/* breathe a sigh of relief - back in 32-bit protected mode */
-
-	/* switch to old stack */	
-	PUSHL	AX	/* match popl below for 8l */
-	MOVL	$0x7BFC, SP
-	POPL	SP
-
-	/* restore idt */
-	MOVL	idtptr(SB),IDTR
-
-	CALL	restoreregs(SB)
-	RET
-
-TEXT realmoderegs(SB), $0
-	LONG $0; LONG $0; LONG $0; LONG $0
-	LONG $0; LONG $0; LONG $0; LONG $0
-	LONG $0; LONG $0; LONG $0; LONG $0
-	LONG $0; LONG $0; LONG $0; LONG $0
-	LONG $0; LONG $0; LONG $0; LONG $0
-
-TEXT realmodeintr(SB), $0
-	LONG $0
-
--- a/os/boot/pc/lib.h
+++ /dev/null
@@ -1,106 +1,0 @@
-#define	offsetof(s, m)	(ulong)(&(((s*)0)->m))
-
-/*
- * functions (possibly) linked in, complete, from libc.
- */
-
-/*
- * mem routines
- */
-extern	void*	memccpy(void*, void*, int, ulong);
-extern	void*	memset(void*, int, ulong);
-extern	int	memcmp(void*, void*, ulong);
-extern	void*	memmove(void*, void*, ulong);
-extern	void*	memchr(void*, int, ulong);
-
-/*
- * string routines
- */
-extern	char*	strcat(char*, char*);
-extern	char*	strchr(char*, int);
-extern	int	strcmp(char*, char*);
-extern	char*	strcpy(char*, char*);
-extern	char*	strncat(char*, char*, long);
-extern	char*	strncpy(char*, char*, long);
-extern	int	strncmp(char*, char*, long);
-extern	long	strlen(char*);
-extern	char*	strrchr(char*, char);
-extern	char*	strstr(char*, char*);
-
-
-/*
- * print routines
- */
-typedef struct Fmt	Fmt;
-typedef int (*Fmts)(Fmt*);
-struct Fmt{
-	uchar	runes;			/* output buffer is runes or chars? */
-	void	*start;			/* of buffer */
-	void	*to;			/* current place in the buffer */
-	void	*stop;			/* end of the buffer; overwritten if flush fails */
-	int	(*flush)(Fmt *);	/* called when to == stop */
-	void	*farg;			/* to make flush a closure */
-	int	nfmt;			/* num chars formatted so far */
-	va_list	args;			/* args passed to dofmt */
-	int	r;			/* % format Rune */
-	int	width;
-	int	prec;
-	ulong	flags;
-};
-extern	int	print(char*, ...);
-extern	char*	vseprint(char*, char*, char*, va_list);
-extern	int	sprint(char*, char*, ...);
-extern 	int	snprint(char*, int, char*, ...);
-extern	int	fmtinstall(int, int (*)(Fmt*));
-
-#pragma varargck	argpos	addconf 1
-#pragma	varargck	argpos	fmtprint	2
-#pragma	varargck	argpos	print		1
-#pragma	varargck	argpos	seprint		3
-#pragma	varargck	argpos	snprint		3
-#pragma	varargck	argpos	sprint		2
-#pragma varargck	type	"H" void*
-
-#pragma	varargck	type	"lld"	vlong
-#pragma	varargck	type	"llx"	vlong
-#pragma	varargck	type	"lld"	uvlong
-#pragma	varargck	type	"llx"	uvlong
-#pragma	varargck	type	"ld"	long
-#pragma	varargck	type	"lx"	long
-#pragma	varargck	type	"ld"	ulong
-#pragma	varargck	type	"lx"	ulong
-#pragma	varargck	type	"d"	int
-#pragma	varargck	type	"x"	int
-#pragma	varargck	type	"c"	int
-#pragma	varargck	type	"C"	int
-#pragma	varargck	type	"d"	uint
-#pragma	varargck	type	"x"	uint
-#pragma	varargck	type	"c"	uint
-#pragma	varargck	type	"C"	uint
-#pragma	varargck	type	"f"	double
-#pragma	varargck	type	"e"	double
-#pragma	varargck	type	"g"	double
-#pragma	varargck	type	"s"	char*
-#pragma	varargck	type	"q"	char*
-#pragma	varargck	type	"S"	Rune*
-#pragma	varargck	type	"Q"	Rune*
-#pragma	varargck	type	"r"	void
-#pragma	varargck	type	"%"	void
-#pragma	varargck	type	"|"	int
-#pragma	varargck	type	"p"	void*
-#pragma varargck	type	"lux"	void*
-#pragma	varargck	type	"E"	uchar*
-
-#define PRINTSIZE	256
-
-/*
- * one-of-a-kind
- */
-extern	int	atoi(char*);
-extern	uintptr	getcallerpc(void*);
-extern	long	strtol(char*, char**, int);
-extern	ulong	strtoul(char*, char**, int);
-extern	uvlong	strtoull(char*, char**, int);
-extern	long	end;
-
-#define	NAMELEN	28
--- a/os/boot/pc/load.c
+++ /dev/null
@@ -1,627 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-#include "sd.h"
-#include "fs.h"
-
-#ifndef VERBOSE
-#define VERBOSE 0
-#endif
-
-/*
- * "cache" must be in this list so that 9load will pass the definition of
- * the cache partition into the kernel so that the disk named by the `cfs'
- * variable in plan9.ini can be seen in all circumstances before termrc
- * sets up all the disk partitions.  In particular, if it's on an odd-ball
- * disk like sd10 rather than sdC0, this is needed.
- */
-static char *diskparts[] = {
-	"dos", "9fat", "fs", "data", "cdboot", "cache", 0
-};
-static char *etherparts[] = { "*", 0 };
-
-static char *diskinis[] = {
-	"plan9/plan9.ini",
-	"plan9.ini",
-	0
-};
-static char *etherinis[] = {
-	"/cfg/pxe/%E",
-	0
-};
-
-/* ordering: devbios must be called before devsd calls sdbios */
-Type types[] = {
-	{	Tfloppy,
-		Fini|Ffs,
-		floppyinit, floppyinitdev,
-		floppygetfspart, 0, floppyboot,
-		floppyprintdevs,
-		diskparts,
-		diskinis,
-	},
-	{	Tether,
-		Fini|Fbootp,
-		etherinit, etherinitdev,
-		pxegetfspart, 0, bootpboot,
-		etherprintdevs,
-		etherparts,
-		etherinis,
-	},
-	{	Tbios,
-		Fini|Ffs,
-		biosinit, biosinitdev,
-		biosgetfspart, nil, biosboot,
-		biosprintdevs,
-		diskparts,
-		diskinis,
-	},
-	{	Tcd,
-		Fini|Ffs,
-		cdinit, sdinitdev,
-		sdgetfspart, sdaddconf, sdboot,
-		sdprintdevs,
-		diskparts,
-		diskinis,
-	},
-	{	Tsd,
-		Fini|Ffs,
-		sdinit, sdinitdev,
-		sdgetfspart, sdaddconf, sdboot,
-		sdprintdevs,
-		diskparts,
-		diskinis,
-	},
-	{	Tnil,
-		0,
-		nil, nil, nil, nil, nil, nil,
-		nil,
-		nil,
-		0,
-		nil,
-	},
-};
-
-static char *typenm[] = {
-	[Tnil]		"nil",
-	[Tfloppy]	"floppy",
-	[Tsd]		"sd",
-	[Tether]	"ether",
-	[Tcd]		"cd",
-	[Tbios]		"bios",
-};
-
-static char *
-typename(int type)
-{
-	if (type < 0 || type >= nelem(typenm) || typenm[type] == nil)
-		return "**gok**";
-	return typenm[type];
-}
-
-extern SDifc sdataifc;
-extern SDifc sdiahciifc;
-extern SDifc sdaoeifc;
-extern SDifc sdbiosifc;
-
-#ifdef NOSCSI
-
-SDifc* sdifc[] = {
-	&sdataifc,
-	&sdiahciifc,
-	&sdbiosifc,
-	&sdaoeifc,
-	nil,
-};
-
-#else
-
-extern SDifc sdmylexifc;
-extern SDifc sd53c8xxifc;
-
-SDifc* sdifc[] = {
-	&sdataifc,
-	&sdiahciifc,
-	&sdmylexifc,
-	&sd53c8xxifc,
-	&sdbiosifc,
-	&sdaoeifc,
-	nil,
-};
-
-#endif NOSCSI
-
-typedef struct Mode Mode;
-
-enum {
-	Maxdev		= 7,
-	Dany		= -1,
-	Nmedia		= 16,
-	Nini		= 10,
-};
-
-enum {					/* mode */
-	Mauto		= 0x00,
-	Mlocal		= 0x01,
-	Manual		= 0x02,
-	NMode		= 0x03,
-};
-
-typedef struct Medium Medium;
-struct Medium {
-	Type*	type;
-	int	flag;
-	int	dev;
-	char name[NAMELEN];
-
-	Fs *inifs;
-	char *part;
-	char *ini;
-
-	Medium*	next;
-};
-
-typedef struct Mode {
-	char*	name;
-	int	mode;
-} Mode;
-
-static Medium media[Nmedia];
-static Medium *curmedium = media;
-
-static Mode modes[NMode+1] = {
-	[Mauto]		{ "auto",   Mauto,  },
-	[Mlocal]	{ "local",  Mlocal, },
-	[Manual]	{ "manual", Manual, },
-};
-
-char **ini;
-
-int scsi0port;
-char *defaultpartition;
-int iniread;
-
-int debugload;
-
-static Medium*
-parse(char *line, char **file)
-{
-	char *p;
-	Type *tp;
-	Medium *mp;
-
-	if(p = strchr(line, '!')) {
-		*p++ = 0;
-		*file = p;
-	} else
-		*file = "";
-
-	for(tp = types; tp->type != Tnil; tp++)
-		for(mp = tp->media; mp; mp = mp->next)
-			if(strcmp(mp->name, line) == 0)
-				return mp;
-	if(p)
-		*--p = '!';
-	return nil;
-}
-
-static int
-boot(Medium *mp, char *file)
-{
-	Type *tp;
-	Medium *xmp;
-	static int didaddconf;
-	Boot b;
-
-	memset(&b, 0, sizeof b);
-	b.state = INITKERNEL;
-
-	if(didaddconf == 0) {
-		didaddconf = 1;
-		for(tp = types; tp->type != Tnil; tp++)
-			if(tp->addconf)
-				for(xmp = tp->media; xmp; xmp = xmp->next)
-					(*tp->addconf)(xmp->dev);
-	}
-
-	sprint(BOOTLINE, "%s!%s", mp->name, file);
-	print("booting %s!%s\n", mp->name, file);
-	return (*mp->type->boot)(mp->dev, file, &b);
-}
-
-static Medium*
-allocm(Type *tp)
-{
-	Medium **l;
-
-	if(curmedium >= &media[Nmedia])
-		return 0;
-
-	for(l = &tp->media; *l; l = &(*l)->next)
-		;
-	*l = curmedium++;
-	return *l;
-}
-
-Medium*
-probe(int type, int flag, int dev)
-{
-	Type *tp;
-	int i;
-	Medium *mp;
-	File f;
-	Fs *fs;
-	char **partp;
-
-	for(tp = types; tp->type != Tnil; tp++){
-		if(type != Tany && type != tp->type)
-			continue;
-
-		if(flag != Fnone){
-			for(mp = tp->media; mp; mp = mp->next){
-				if((flag & mp->flag) && (dev == Dany || dev == mp->dev))
-					return mp;
-			}
-		}
-		if (debugload)
-			print("probing %s...", typename(tp->type));
-		if((tp->flag & Fprobe) == 0){
-			tp->flag |= Fprobe;
-			tp->mask = (*tp->init)();
-		}
-
-		for(i = 0; tp->mask; i++){
-			if((tp->mask & (1<<i)) == 0)
-				continue;
-			tp->mask &= ~(1<<i);
-
-			if((mp = allocm(tp)) == 0)
-				continue;
-
-			mp->dev = i;
-			mp->flag = tp->flag;
-			mp->type = tp;
-			(*tp->initdev)(i, mp->name);
-
-			if(mp->flag & Fini){
-				mp->flag &= ~Fini;
-				for(partp = tp->parts; *partp; partp++){
-					if((fs = (*tp->getfspart)(i, *partp, 0)) == nil)
-						continue;
-
-					for(ini = tp->inis; *ini; ini++){
-						if(fswalk(fs, *ini, &f) > 0){
-							mp->inifs = fs;
-							mp->part = *partp;
-							mp->ini = f.path;
-							mp->flag |= Fini;
-							goto Break2;
-						}
-					}
-				}
-			}
-		Break2:
-			if((flag & mp->flag) && (dev == Dany || dev == i))
-				return mp;
-		}
-	}
-
-	return 0;
-}
-
-void
-main(void)
-{
-	Medium *mp;
-	int flag, i, mode, tried;
-	char def[2*NAMELEN], line[80], *p, *file;
-	Type *tp;
-
-	i8042a20();
-	memset(m, 0, sizeof(Mach));
-	trapinit();
-	clockinit();
-	alarminit();
-	meminit(0);
-	spllo();
-	consinit("0", "9600");
-	kbdinit();
-	if((ulong)&end > (KZERO|(640*1024)))
-		panic("i'm too big\n");
-
-	readlsconf();
-	print("initial probe, to find plan9.ini...");
-	/* find and read plan9.ini, setting configuration variables */
-	for(tp = types; tp->type != Tnil; tp++){
-		/* skip bios until we have read plan9.ini */
-		if(!pxe && tp->type == Tether || tp->type == Tbios)
-			continue;
-		if (VERBOSE)
-			print("probing %s...", typename(tp->type));
-		if((mp = probe(tp->type, Fini, Dany)) && (mp->flag & Fini)){
-			print("using %s!%s!%s\n", mp->name, mp->part, mp->ini);
-			iniread = !dotini(mp->inifs);
-			break;
-		}
-	}
-	print("\n");
-	apminit();
-
-	debugload = getconf("*debugload") != nil;
-	if((p = getconf("console")) != nil)
-		consinit(p, getconf("baud"));
-
-	devpccardlink();
-	devi82365link();
-
-	/*
- 	 * Even after we find the ini file, we keep probing disks,
-	 * because we have to collect the partition tables and
-	 * have boot devices for parse.
-	 */
-	probe(Tany, Fnone, Dany);
-	if (debugload)
-		print("end disk probe\n");
-	tried = 0;
-	mode = Mauto;
-
-	p = getconf("bootfile");
-
-	if(p != 0) {
-		mode = Manual;
-		for(i = 0; i < NMode; i++){
-			if(strcmp(p, modes[i].name) == 0){
-				mode = modes[i].mode;
-				goto done;
-			}
-		}
-		if((mp = parse(p, &file)) == nil) {
-			print("Unknown boot device: %s\n", p);
-			goto done;
-		}
-		tried = boot(mp, file);
-	}
-done:
-	if(tried == 0 && mode != Manual){
-		flag = Fany;
-		if(mode == Mlocal)
-			flag &= ~Fbootp;
-		if((mp = probe(Tany, flag, Dany)) && mp->type->type != Tfloppy)
-			boot(mp, "");
-		if (debugload)
-			print("end auto probe\n");
-	}
-
-	def[0] = 0;
-	probe(Tany, Fnone, Dany);
-	if (debugload)
-		print("end final probe\n");
-	if(p = getconf("bootdef"))
-		strcpy(def, p);
-
-	flag = 0;
-	for(tp = types; tp->type != Tnil; tp++){
-		for(mp = tp->media; mp; mp = mp->next){
-			if(flag == 0){
-				flag = 1;
-				print("Boot devices:");
-			}
-			(*tp->printdevs)(mp->dev);
-		}
-	}
-	if(flag)
-		print("\n");
-
-	for(;;){
-		if(getstr("boot from", line, sizeof(line), def, (mode != Manual)*15) >= 0)
-			if(mp = parse(line, &file))
-				boot(mp, file);
-		def[0] = 0;
-	}
-}
-
-int
-getfields(char *lp, char **fields, int n, char sep)
-{
-	int i;
-
-	for(i = 0; lp && *lp && i < n; i++){
-		while(*lp == sep)
-			*lp++ = 0;
-		if(*lp == 0)
-			break;
-		fields[i] = lp;
-		while(*lp && *lp != sep){
-			if(*lp == '\\' && *(lp+1) == '\n')
-				*lp++ = ' ';
-			lp++;
-		}
-	}
-	return i;
-}
-
-int
-cistrcmp(char *a, char *b)
-{
-	int ac, bc;
-
-	for(;;){
-		ac = *a++;
-		bc = *b++;
-
-		if(ac >= 'A' && ac <= 'Z')
-			ac = 'a' + (ac - 'A');
-		if(bc >= 'A' && bc <= 'Z')
-			bc = 'a' + (bc - 'A');
-		ac -= bc;
-		if(ac)
-			return ac;
-		if(bc == 0)
-			break;
-	}
-	return 0;
-}
-
-int
-cistrncmp(char *a, char *b, int n)
-{
-	unsigned ac, bc;
-
-	while(n > 0){
-		ac = *a++;
-		bc = *b++;
-		n--;
-
-		if(ac >= 'A' && ac <= 'Z')
-			ac = 'a' + (ac - 'A');
-		if(bc >= 'A' && bc <= 'Z')
-			bc = 'a' + (bc - 'A');
-
-		ac -= bc;
-		if(ac)
-			return ac;
-		if(bc == 0)
-			break;
-	}
-
-	return 0;
-}
-
-#define PSTART		( 8*1024*1024)
-#define PEND		(16*1024*1024)
-
-ulong palloc = PSTART;
-
-void*
-ialloc(ulong n, int align)
-{
-	ulong p;
-	int a;
-
-	p = palloc;
-	if(align <= 0)
-		align = 4;
-	if(a = n % align)
-		n += align - a;
-	if(a = p % align)
-		p += align - a;
-
-
-	palloc = p+n;
-	if(palloc > PEND)
-		panic("ialloc(%lud, %d) called from %#p\n",
-			n, align, getcallerpc(&n));
-	return memset((void*)(p|KZERO), 0, n);
-}
-
-void*
-xspanalloc(ulong size, int align, ulong span)
-{
-	ulong a, v;
-
-	if((palloc + (size+align+span)) > PEND)
-		panic("xspanalloc(%lud, %d, 0x%lux) called from %#p\n",
-			size, align, span, getcallerpc(&size));
-
-	a = (ulong)ialloc(size+align+span, 0);
-
-	if(span > 2)
-		v = (a + span) & ~(span-1);
-	else
-		v = a;
-
-	if(align > 1)
-		v = (v + align) & ~(align-1);
-
-	return (void*)v;
-}
-
-static Block *allocbp;
-
-Block*
-allocb(int size)
-{
-	Block *bp, **lbp;
-	ulong addr;
-
-	lbp = &allocbp;
-	for(bp = *lbp; bp; bp = bp->next){
-		if((bp->lim - bp->base) >= size){
-			*lbp = bp->next;
-			break;
-		}
-		lbp = &bp->next;
-	}
-	if(bp == 0){
-		if((palloc + (sizeof(Block)+size+64)) > PEND)
-			panic("allocb(%d) called from %#p\n",
-				size, getcallerpc(&size));
-		bp = ialloc(sizeof(Block)+size+64, 0);
-		addr = (ulong)bp;
-		addr = ROUNDUP(addr + sizeof(Block), 8);
-		bp->base = (uchar*)addr;
-		bp->lim = ((uchar*)bp) + sizeof(Block)+size+64;
-	}
-
-	if(bp->flag)
-		panic("allocb reuse\n");
-
-	bp->rp = bp->base;
-	bp->wp = bp->rp;
-	bp->next = 0;
-	bp->flag = 1;
-
-	return bp;
-}
-
-void
-freeb(Block* bp)
-{
-	bp->next = allocbp;
-	allocbp = bp;
-
-	bp->flag = 0;
-}
-
-enum {
-	Paddr=		0x70,	/* address port */
-	Pdata=		0x71,	/* data port */
-};
-
-uchar
-nvramread(int offset)
-{
-	outb(Paddr, offset);
-	return inb(Pdata);
-}
-
-void (*etherdetach)(void);
-void (*floppydetach)(void);
-void (*sddetach)(void);
-
-void
-warp9(ulong entry)
-{
-	if(etherdetach)
-		etherdetach();
-	if(floppydetach)
-		floppydetach();
-	if(sddetach)
-		sddetach();
-	consdrain();
-
-	splhi();
-	trapdisable();
-
-	/*
-	 * This is where to push things on the stack to
-	 * boot *BSD systems, e.g.
-	(*(void(*)(void*, void*, void*, void*, ulong, ulong))(PADDR(entry)))(0, 0, 0, 0, 8196, 640);
-	 * will enable NetBSD boot (the real memory size needs to
-	 * go in the 5th argument).
-	 */
-	(*(void(*)(void))(PADDR(entry)))();
-}
--- a/os/boot/pc/mbr.s
+++ /dev/null
@@ -1,259 +1,0 @@
-/*
- * Hard disc boot block. Loaded at 0x7C00, relocates to 0x0600:
- *	8a mbr.s; 8l -o mbr -l -H3 -T0x0600 mbr.8
- */
-#include "x16.h"
-#include "mem.h"
-
-/*#define FLOPPY	1		/* test on a floppy */
-#define TRACE(C)	PUSHA;\
-			CLR(rBX);\
-			MOVB $C, AL;\
-			LBI(0x0E, rAH);\
-			BIOSCALL(0x10);\
-			POPA
-
-/*
- * We keep data on the stack, indexed by BP.
- */
-#define Xdap		0x00		/* disc address packet */
-#define Xtable		0x10		/* partition table entry */
-#define Xdrive		0x12		/* starting disc */
-#define Xtotal		0x14		/* sum of allocated data above */
-
-/*
- * Start: loaded at 0000:7C00, relocate to 0000:0600.
- * Boot drive is in rDL.
- */
-TEXT _start(SB), $0
-	CLI
-	CLR(rAX)
-	MTSR(rAX, rSS)			/* 0000 -> rSS */
-	LWI((0x7C00-Xtotal), rSP)	/* 7Bxx -> rSP */
-	MW(rSP, rBP)			/* set the indexed-data pointer */
-
-	MTSR(rAX, rDS)			/* 0000 -> rDS, source segment */
-	LWI(0x7C00, rSI)		/* 7C00 -> rSI, source offset */
-	MTSR(rAX, rES)			/* 0000 -> rES, destination segment */
-	LWI(0x600, rDI)			/* 0600 -> rDI, destination offset */
-	LWI(0x100, rCX)			/* 0100 -> rCX, loop count (words) */
-
-	CLD
-	REP; MOVSL			/* MOV DS:[(E)SI] -> ES:[(E)DI] */
-
-	FARJUMP16(0x0000, _start0600(SB))
-
-TEXT _start0600(SB), $0
-#ifdef FLOPPY
-	LBI(0x80, rDL)
-#else
-	CLRB(rAL)			/* some systems pass 0 */
-	CMPBR(rAL, rDL)
-	JNE _save
-	LBI(0x80, rDL)
-#endif /* FLOPPY */
-_save:
-	SXB(rDL, Xdrive, xBP)		/* save disc */
-
-	LWI(confidence(SB), rSI)	/* for that warm, fuzzy feeling */
-	CALL16(BIOSputs(SB))
-
-	LWI(_start+0x01BE(SB), rSI)	/* address of partition table */
-	LWI(0x04, rCX)			/* 4 entries in table */
-	LBI(0x80, rAH)			/* active entry value */
-	CLRB(rAL)			/* inactive entry value */
-
-_activeloop0:
-	LXB(0x00, xSI, rBL)		/* get active entry from table */
-	CMPBR(rBL, rAH)			/* is this an active entry? */
-	JEQ _active
-
-	CMPBR(rBL, rAL)			/* if not active it should be 0 */
-	JNE _invalidMBR
-
-	ADDI(0x10, rSI)			/* next table entry */
-	DEC(rCX)
-	JNE _activeloop0
-
-	LWI(noentry(SB), rSI)
-	CALL16(buggery(SB))
-
-_active:
-	MW(rSI, rDI)			/* save table address */
-
-_activeloop1:
-	ADDI(0x10, rSI)			/* next table entry */
-	DEC(rCX)
-	JEQ _readsector
-
-	LXB(0x00, xSI, rBL)		/* get active entry from table */
-	CMPBR(rBL, rAH)			/* is this an active entry? */
-	JNE _activeloop1		/* should only be one active */
-
-_invalidMBR:
-	LWI(invalidMBR(SB), rSI)
-	CALL16(buggery(SB))
-
-_readsector:
-	LBI(0x41, rAH)			/* check extensions present */
-	LWI(0x55AA, rBX)
-	LXB(Xdrive, xBP, rDL)		/* drive */
-	BIOSCALL(0x13)			/* CF set on failure */
-	JCS _readsector2
-	CMPI(0xAA55, rBX)
-	JNE _readsector2
-	ANDI(0x0001, rCX)
-	JEQ _readsector2
-
-_readsector42:
-	SBPBI(0x10, Xdap+0)		/* packet size */
-	SBPBI(0x00, Xdap+1)		/* reserved */
-	SBPBI(0x01, Xdap+2)		/* number of blocks to transfer */
-	SBPBI(0x00, Xdap+3)		/* reserved */
-	SBPWI(0x7C00, Xdap+4)		/* transfer buffer :offset */
-	SBPWI(0x0000, Xdap+6)		/* transfer buffer seg: */
-	LXW(0x08, xDI, rAX)		/* LBA (64-bits) */
-	SBPW(rAX, Xdap+8)
-	LXW(0x0A, xDI, rAX)
-	SBPW(rAX, Xdap+10)
-	SBPWI(0x0000, Xdap+12)
-	SBPWI(0x0000, Xdap+14)
-
-	MW(rBP, rSI)			/* disk address packet */
-	LBI(0x42, rAH)			/* extended read */
-	BIOSCALL(0x13)			/* CF set on failure */
-	JCC _readsectorok
-
-	LWI(ioerror(SB), rSI)
-	CALL16(buggery(SB))
-
-/*
- * Read a sector from a disc using the traditional BIOS call.
- * For BIOSCALL(0x13/AH=0x02):
- *   rAH	0x02
- *   rAL	number of sectors to read (1)
- *   rCH	low 8 bits of cylinder
- *   rCL	high 2 bits of cylinder (7-6), sector (5-0)
- *   rDH	head
- *   rDL	drive
- *   rES:rBX	buffer address
- */
-_readsector2:
-	LXB(0x01, xDI, rDH)		/* head */
-	LXW(0x02, xDI, rCX)		/* save active cylinder/sector */
-
-	LWI(0x0201, rAX)		/* read one sector */
-	LXB(Xdrive, xBP, rDL)		/* drive */
-	LWI(0x7C00, rBX)		/* buffer address (rES already OK) */
-	BIOSCALL(0x13)			/* CF set on failure */
-	JCC _readsectorok
-
-	LWI(ioerror(SB), rSI)
-	CALL16(buggery(SB))
-
-_readsectorok:
-	LWI(0x7C00, rBX)		/* buffer address (rES already OK) */
-	LXW(0x1FE, xBX, rAX)
-	CMPI(0xAA55, rAX)
-	JNE _bbnotok
-
-	/*
-	 * Jump to the loaded PBS.
-	 * rDL and rSI should still contain the drive
-	 * and partition table pointer respectively.
-	 */
-	MW(rDI, rSI)
-	FARJUMP16(0x0000, 0x7C00)
-
-_bbnotok:
-	LWI(invalidPBS(SB), rSI)
-
-TEXT buggery(SB), $0
-	CALL16(BIOSputs(SB))
-	LWI(reboot(SB), rSI)
-	CALL16(BIOSputs(SB))
-
-_wait:
-	CLR(rAX)			/* wait for any key */
-	BIOSCALL(0x16)
-
-_reset:
-	CLR(rBX)			/* set ES segment for BIOS area */
-	MTSR(rBX, rES)
-
-	LWI(0x0472, rBX)		/* warm-start code address */
-	LWI(0x1234, rAX)		/* warm-start code */
-	POKEW				/* MOVW	AX, ES:[BX] */
-
-	FARJUMP16(0xFFFF, 0x0000)	/* reset */
-
-/*
- * Output a string to the display.
- * String argument is in rSI.
- */
-TEXT BIOSputs(SB), $0
-	PUSHA
-	CLR(rBX)
-_BIOSputs:
-	LODSB
-	ORB(rAL, rAL)
-	JEQ _BIOSputsret
-
-	LBI(0x0E, rAH)
-	BIOSCALL(0x10)
-	JMP _BIOSputs
-
-_BIOSputsret:
-	POPA
-	RET
-
-/* "No active entry in MBR" */
-TEXT noentry(SB), $0
-	BYTE $'N'; BYTE $'o'; BYTE $' '; BYTE $'a';
-	BYTE $'c'; BYTE $'t'; BYTE $'i'; BYTE $'v';
-	BYTE $'e'; BYTE $' '; BYTE $'e'; BYTE $'n';
-	BYTE $'t'; BYTE $'r'; BYTE $'y'; BYTE $' ';
-	BYTE $'i'; BYTE $'n'; BYTE $' '; BYTE $'M';
-	BYTE $'B'; BYTE $'R';
-	BYTE $'\z';
-
-/* "Invalid MBR" */
-TEXT invalidMBR(SB), $0
-	BYTE $'I'; BYTE $'n'; BYTE $'v'; BYTE $'a';
-	BYTE $'l'; BYTE $'i'; BYTE $'d'; BYTE $' ';
-	BYTE $'M'; BYTE $'B'; BYTE $'R';
-	BYTE $'\z';
-
-/* "I/O error" */
-TEXT ioerror(SB), $0
-	BYTE $'I'; BYTE $'/'; BYTE $'O'; BYTE $' ';
-	BYTE $'e'; BYTE $'r'; BYTE $'r'; BYTE $'o';
-	BYTE $'r';
-	BYTE $'\z';
-
-/* "Invalid PBS" */
-TEXT invalidPBS(SB), $0
-	BYTE $'I'; BYTE $'n'; BYTE $'v'; BYTE $'a';
-	BYTE $'l'; BYTE $'i'; BYTE $'d'; BYTE $' ';
-	BYTE $'P'; BYTE $'B'; BYTE $'S';
-	BYTE $'\z';
-
-/* "\r\nPress almost any key to reboot..." */
-TEXT reboot(SB), $0
-	BYTE $'\r';BYTE $'\n';
-	BYTE $'P'; BYTE $'r'; BYTE $'e'; BYTE $'s';
-	BYTE $'s'; BYTE $' '; BYTE $'a'; BYTE $'l'; 
-	BYTE $'m'; BYTE $'o'; BYTE $'s'; BYTE $'t';
-	BYTE $' '; BYTE $'a'; BYTE $'n'; BYTE $'y';
-	BYTE $' '; BYTE $'k'; BYTE $'e'; BYTE $'y';
-	BYTE $' '; BYTE $'t'; BYTE $'o'; BYTE $' ';
-	BYTE $'r'; BYTE $'e'; BYTE $'b'; BYTE $'o';
-	BYTE $'o'; BYTE $'t'; BYTE $'.'; BYTE $'.';
-	BYTE $'.';
-	BYTE $'\z';
-
-/* "MBR..." */
-TEXT confidence(SB), $0
-	BYTE $'M'; BYTE $'B'; BYTE $'R'; BYTE $'.';
-	BYTE $'.'; BYTE $'.';
-	BYTE $'\z';
--- a/os/boot/pc/mem.h
+++ /dev/null
@@ -1,114 +1,0 @@
-/*
- * Memory and machine-specific definitions.  Used in C and assembler.
- */
-
-/*
- * Sizes
- */
-#define	BI2BY		8			/* bits per byte */
-#define	BI2WD		32			/* bits per word */
-#define	BY2WD		4			/* bytes per word */
-#define	BY2PG		4096			/* bytes per page */
-#define	WD2PG		(BY2PG/BY2WD)		/* words per page */
-#define	PGSHIFT		12			/* log(BY2PG) */
-#define	PGROUND(s)	(((s)+(BY2PG-1))&~(BY2PG-1))
-
-#define	MAXMACH		1			/* max # cpus system can run */
-
-/*
- * Time
- */
-#define	HZ		(100)				/* clock frequency */
-#define	MS2HZ		(1000/HZ)			/* millisec per clock tick */
-#define	TK2SEC(t)	((t)/HZ)			/* ticks to seconds */
-#define	TK2MS(x)	((x)*(1000/HZ))
-#define	MS2TK(t)	((((ulong)(t))*HZ)/1000)	/* milliseconds to ticks */
-
-/*
- * Fundamental addresses
- */
-#define IDTADDR		0x80000800		/* idt */
-#define APBOOTSTRAP	0x80001000		/* AP bootstrap code */
-#define CONFADDR	0x80001200		/* info passed from boot loader */
-#define CPU0PDB		0x80002000		/* bootstrap processor PDB */
-#define CPU0PTE		0x80003000		/* bootstrap processor PTE's for 0-4MB */
-#define MACHADDR	0x80004000		/* as seen by current processor */
-#define CPU0MACH	0x80005000		/* Mach for bootstrap processor */
-#define BIOSXCHG	0x80006000		/* To exchange data with the BIOS */
-#define	MACHSIZE	(BY2PG*8)		/* stack size */
-
-/*
- *  Address spaces
- *
- *  Kernel is at 2GB-4GB
- */
-#define	KZERO		0x80000000		/* base of kernel address space */
-#define	KTZERO		KZERO			/* first address in kernel text */
-#define ROMBIOS		(KZERO|0xF0000)
-
-/*
- *  known 80386 segments (in GDT) and their selectors
- */
-#define	NULLSEG	0	/* null segment */
-#define	KDSEG	1	/* kernel data/stack */
-#define	KESEG	2	/* kernel executable */	
-#define	UDSEG	3	/* user data/stack */
-#define	UESEG	4	/* user executable */
-#define	SYSGATE	5	/* system call gate */
-#define TSSSEG	6	/* task segment */
-
-#define SELGDT	(0<<3)	/* selector is in gdt */
-#define	SELLDT	(1<<3)	/* selector is in ldt */
-
-#define SELECTOR(i, t, p)	(((i)<<3) | (t) | (p))
-
-#define NULLSEL	SELECTOR(NULLSEG, SELGDT, 0)
-#define KESEL	SELECTOR(KESEG, SELGDT, 0)
-#define KDSEL	SELECTOR(KDSEG, SELGDT, 0)
-#define UESEL	SELECTOR(UESEG, SELGDT, 3)
-#define UDSEL	SELECTOR(UDSEG, SELGDT, 3)
-#define TSSSEL	SELECTOR(TSSSEG, SELGDT, 0)
-
-/*
- *  fields in segment descriptors
- */
-#define SEGDATA	(0x10<<8)	/* data/stack segment */
-#define SEGEXEC	(0x18<<8)	/* executable segment */
-#define	SEGTSS	(0x9<<8)	/* TSS segment */
-#define SEGCG	(0x0C<<8)	/* call gate */
-#define	SEGIG	(0x0E<<8)	/* interrupt gate */
-#define SEGTG	(0x0F<<8)	/* task gate */
-#define SEGTYPE	(0x1F<<8)
-
-#define SEGP	(1<<15)		/* segment present */
-#define SEGPL(x) ((x)<<13)	/* priority level */
-#define SEGB	(1<<22)		/* granularity 1==4k (for expand-down) */
-#define SEGG	(1<<23)		/* granularity 1==4k (for other) */
-#define SEGE	(1<<10)		/* expand down */
-#define SEGW	(1<<9)		/* writable (for data/stack) */
-#define	SEGR	(1<<9)		/* readable (for code) */
-#define SEGD	(1<<22)		/* default 1==32bit (for code) */
-
-/*
- *  virtual MMU
- */
-#define PTEMAPMEM	(1024*1024)	/* ??? */	
-#define SEGMAPSIZE	16		/* ??? */
-#define	PTEPERTAB	(PTEMAPMEM/BY2PG)	/* ??? */
-#define PPN(x)		((x)&~(BY2PG-1))
-
-/*
- *  physical MMU
- */
-#define	PTEVALID	(1<<0)
-#define	PTEUNCACHED	0		/* everything is uncached */
-#define	PTEWRITE	(1<<1)
-#define	PTERONLY	(0<<1)
-#define	PTEKERNEL	(0<<2)
-#define	PTEUSER		(1<<2)
-#define	PTESIZE		(1<<7)
-
-/*
- *  flag register bits that we care about
- */
-#define IFLAG	0x200
--- a/os/boot/pc/memory.c
+++ /dev/null
@@ -1,504 +1,0 @@
-/*
- * Size memory and create the kernel page-tables on the fly while doing so.
- * Called from main(), this code should only be run by the bootstrap processor.
- */
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-#define MEMDEBUG	0
-
-#define PDX(va)		((((ulong)(va))>>22) & 0x03FF)
-#define PTX(va)		((((ulong)(va))>>12) & 0x03FF)
-
-enum {
-	MemUPA		= 0,		/* unbacked physical address */
-	MemRAM		= 1,		/* physical memory */
-	MemUMB		= 2,		/* upper memory block (<16MB) */
-	NMemType	= 3,
-
-	KB		= 1024,
-
-	MemMinMB	= 4,		/* minimum physical memory (<=4MB) */
-	MemMaxMB	= 768,		/* maximum physical memory to check */
-
-	NMemBase	= 10,
-};
-
-typedef struct {
-	int	size;
-	ulong	addr;
-} Map;
-
-typedef struct {
-	char*	name;
-	Map*	map;
-	Map*	mapend;
-
-	Lock;
-} RMap;
-
-static Map mapupa[8];
-static RMap rmapupa = {
-	"unallocated unbacked physical memory",
-	mapupa,
-	&mapupa[7],
-};
-
-static Map xmapupa[8];
-static RMap xrmapupa = {
-	"unbacked physical memory",
-	xmapupa,
-	&xmapupa[7],
-};
-
-static Map mapram[8];
-static RMap rmapram = {
-	"physical memory",
-	mapram,
-	&mapram[7],
-};
-
-static Map mapumb[64];
-static RMap rmapumb = {
-	"upper memory block",
-	mapumb,
-	&mapumb[63],
-};
-
-static Map mapumbrw[8];
-static RMap rmapumbrw = {
-	"UMB device memory",
-	mapumbrw,
-	&mapumbrw[7],
-};
-
-void
-memdebug(void)
-{
-	Map *mp;
-	ulong maxpa, maxpa1, maxpa2;
-
-	if(MEMDEBUG == 0)
-		return;
-
-	maxpa = (nvramread(0x18)<<8)|nvramread(0x17);
-	maxpa1 = (nvramread(0x31)<<8)|nvramread(0x30);
-	maxpa2 = (nvramread(0x16)<<8)|nvramread(0x15);
-	print("maxpa = %luX -> %luX, maxpa1 = %luX maxpa2 = %luX\n",
-		maxpa, MB+maxpa*KB, maxpa1, maxpa2);
-
-	for(mp = rmapram.map; mp->size; mp++)
-		print("%8.8luX %8.8luX %8.8luX\n", mp->addr, (ulong)mp->size, mp->addr+mp->size);
-	for(mp = rmapumb.map; mp->size; mp++)
-		print("%8.8luX %8.8luX %8.8luX\n", mp->addr, (ulong)mp->size, mp->addr+mp->size);
-	for(mp = rmapumbrw.map; mp->size; mp++)
-		print("%8.8luX %8.8luX %8.8luX\n", mp->addr, (ulong)mp->size, mp->addr+mp->size);
-	for(mp = rmapupa.map; mp->size; mp++)
-		print("%8.8luX %8.8luX %8.8luX\n", mp->addr, (ulong)mp->size, mp->addr+mp->size);
-}
-
-void
-mapfree(RMap* rmap, ulong addr, ulong size)
-{
-	Map *mp;
-	ulong t;
-
-	if(size == 0)
-		return;
-
-	lock(rmap);
-	for(mp = rmap->map; mp->addr <= addr && mp->size; mp++)
-		;
-
-	if(mp > rmap->map && (mp-1)->addr+(mp-1)->size == addr){
-		(mp-1)->size += size;
-		if(addr+size == mp->addr){
-			(mp-1)->size += mp->size;
-			while(mp->size){
-				mp++;
-				(mp-1)->addr = mp->addr;
-				(mp-1)->size = mp->size;
-			}
-		}
-	}
-	else{
-		if(addr+size == mp->addr && mp->size){
-			mp->addr -= size;
-			mp->size += size;
-		}
-		else do{
-			if(mp >= rmap->mapend){
-				print("mapfree: %s: losing 0x%luX, %lud\n",
-					rmap->name, addr, size);
-				break;
-			}
-			t = mp->addr;
-			mp->addr = addr;
-			addr = t;
-			t = mp->size;
-			mp->size = size;
-			mp++;
-		}while(size = t);
-	}
-	unlock(rmap);
-}
-
-ulong
-mapalloc(RMap* rmap, ulong addr, int size, int align)
-{
-	Map *mp;
-	ulong maddr, oaddr;
-
-	lock(rmap);
-	for(mp = rmap->map; mp->size; mp++){
-		maddr = mp->addr;
-
-		if(addr){
-			/*
-			 * A specific address range has been given:
-			 *   if the current map entry is greater then
-			 *   the address is not in the map;
-			 *   if the current map entry does not overlap
-			 *   the beginning of the requested range then
-			 *   continue on to the next map entry;
-			 *   if the current map entry does not entirely
-			 *   contain the requested range then the range
-			 *   is not in the map.
-			 */
-			if(maddr > addr)
-				break;
-			if(mp->size < addr - maddr)	/* maddr+mp->size < addr, but no overflow */
-				continue;
-			if(addr - maddr > mp->size - size)	/* addr+size > maddr+mp->size, but no overflow */
-				break;
-			maddr = addr;
-		}
-
-		if(align > 0)
-			maddr = ((maddr+align-1)/align)*align;
-		if(mp->addr+mp->size-maddr < size)
-			continue;
-
-		oaddr = mp->addr;
-		mp->addr = maddr+size;
-		mp->size -= maddr-oaddr+size;
-		if(mp->size == 0){
-			do{
-				mp++;
-				(mp-1)->addr = mp->addr;
-			}while((mp-1)->size = mp->size);
-		}
-
-		unlock(rmap);
-		if(oaddr != maddr)
-			mapfree(rmap, oaddr, maddr-oaddr);
-
-		return maddr;
-	}
-	unlock(rmap);
-
-	return 0;
-}
-
-static void
-umbscan(void)
-{
-	uchar *p;
-
-	/*
-	 * Scan the Upper Memory Blocks (0xA0000->0xF0000) for pieces
-	 * which aren't used; they can be used later for devices which
-	 * want to allocate some virtual address space.
-	 * Check for two things:
-	 * 1) device BIOS ROM. This should start with a two-byte header
-	 *    of 0x55 0xAA, followed by a byte giving the size of the ROM
-	 *    in 512-byte chunks. These ROM's must start on a 2KB boundary.
-	 * 2) device memory. This is read-write.
-	 * There are some assumptions: there's VGA memory at 0xA0000 and
-	 * the VGA BIOS ROM is at 0xC0000. Also, if there's no ROM signature
-	 * at 0xE0000 then the whole 64KB up to 0xF0000 is theoretically up
-	 * for grabs; check anyway.
-	 */
-	p = KADDR(0xD0000);	/*RSC: changed from 0xC0000 */
-	while(p < (uchar*)KADDR(0xE0000)){
-		if (p[0] == 0x55 && p[1] == 0xAA) {
-			/* Skip p[2] chunks of 512 bytes.  Test for 0x55 AA before
-			     poking obtrusively, or else the Thinkpad X20 dies when
-			     setting up the cardbus (PB) */
-			p += p[2] * 512;
-			continue;
-		}
-
-		p[0] = 0xCC;
-		p[2*KB-1] = 0xCC;
-		if(p[0] != 0xCC || p[2*KB-1] != 0xCC){
-			p[0] = 0x55;
-			p[1] = 0xAA;
-			p[2] = 4;
-			if(p[0] == 0x55 && p[1] == 0xAA){
-				p += p[2]*512;
-				continue;
-			}
-			if(p[0] == 0xFF && p[1] == 0xFF)
-				mapfree(&rmapumb, PADDR(p), 2*KB);
-		}
-		else
-			mapfree(&rmapumbrw, PADDR(p), 2*KB);
-		p += 2*KB;
-	}
-
-	p = KADDR(0xE0000);
-	if(p[0] != 0x55 || p[1] != 0xAA){
-		p[0] = 0xCC;
-		p[64*KB-1] = 0xCC;
-		if(p[0] != 0xCC && p[64*KB-1] != 0xCC)
-			mapfree(&rmapumb, PADDR(p), 64*KB);
-	}
-}
-
-
-void
-meminit(ulong)
-{
-	/* A hack to initialize unbacked physical memory.  It's assumed PCI space is assigned by 
-	     the BIOS in the 0xF0000000 range and 9load never needs more than 0x2000... to run. These
-	     values leave ample space for memory allocations for uninitialized PCI cards (e.g. cardbus 
-	     cards).  (pb) */
-	ulong maxmem = 0x40000000;
-
-	umbscan();
-	mapfree(&rmapupa, maxmem, 0x00000000-maxmem);
-	if(MEMDEBUG)
-		memdebug();
-}
-
-ulong
-umbmalloc(ulong addr, int size, int align)
-{
-	ulong a;
-
-	if(a = mapalloc(&rmapumb, addr, size, align))
-		return (ulong)KADDR(a);
-
-	return 0;
-}
-
-void
-umbfree(ulong addr, int size)
-{
-	mapfree(&rmapumb, PADDR(addr), size);
-}
-
-ulong
-umbrwmalloc(ulong addr, int size, int align)
-{
-	ulong a;
-	uchar *p;
-
-	if(a = mapalloc(&rmapumbrw, addr, size, align))
-		return(ulong)KADDR(a);
-
-	/*
-	 * Perhaps the memory wasn't visible before
-	 * the interface is initialised, so try again.
-	 */
-	if((a = umbmalloc(addr, size, align)) == 0)
-		return 0;
-	p = (uchar*)a;
-	p[0] = 0xCC;
-	p[size-1] = 0xCC;
-	if(p[0] == 0xCC && p[size-1] == 0xCC)
-		return a;
-	umbfree(a, size);
-
-	return 0;
-}
-
-void
-umbrwfree(ulong addr, int size)
-{
-	mapfree(&rmapumbrw, PADDR(addr), size);
-}
-
-ulong*
-mmuwalk(ulong* pdb, ulong va, int level, int create)
-{
-	ulong pa, *table;
-
-	/*
-	 * Walk the page-table pointed to by pdb and return a pointer
-	 * to the entry for virtual address va at the requested level.
-	 * If the entry is invalid and create isn't requested then bail
-	 * out early. Otherwise, for the 2nd level walk, allocate a new
-	 * page-table page and register it in the 1st level.
-	 */
-	table = &pdb[PDX(va)];
-	if(!(*table & PTEVALID) && create == 0)
-		return 0;
-
-	switch(level){
-
-	default:
-		return 0;
-
-	case 1:
-		return table;
-
-	case 2:
-		if(*table & PTESIZE)
-			panic("mmuwalk2: va 0x%ux entry 0x%ux\n", va, *table);
-		if(!(*table & PTEVALID)){
-			pa = PADDR(ialloc(BY2PG, BY2PG));
-			*table = pa|PTEWRITE|PTEVALID;
-		}
-		table = KADDR(PPN(*table));
-
-		return &table[PTX(va)];
-	}
-}
-
-static Lock mmukmaplock;
-
-ulong
-mmukmap(ulong pa, ulong va, int size)
-{
-	ulong pae, *table, *pdb, pgsz, *pte, x;
-	int pse, sync;
-	extern int cpuidax, cpuiddx;
-
-	pdb = KADDR(getcr3());
-	if((cpuiddx & 0x08) && (getcr4() & 0x10))
-		pse = 1;
-	else
-		pse = 0;
-	sync = 0;
-
-	pa = PPN(pa);
-	if(va == 0)
-		va = (ulong)KADDR(pa);
-	else
-		va = PPN(va);
-
-	pae = pa + size;
-	lock(&mmukmaplock);
-	while(pa < pae){
-		table = &pdb[PDX(va)];
-		/*
-		 * Possibly already mapped.
-		 */
-		if(*table & PTEVALID){
-			if(*table & PTESIZE){
-				/*
-				 * Big page. Does it fit within?
-				 * If it does, adjust pgsz so the correct end can be
-				 * returned and get out.
-				 * If not, adjust pgsz up to the next 4MB boundary
-				 * and continue.
-				 */
-				x = PPN(*table);
-				if(x != pa)
-					panic("mmukmap1: pa 0x%ux  entry 0x%ux\n",
-						pa, *table);
-				x += 4*MB;
-				if(pae <= x){
-					pa = pae;
-					break;
-				}
-				pgsz = x - pa;
-				pa += pgsz;
-				va += pgsz;
-
-				continue;
-			}
-			else{
-				/*
-				 * Little page. Walk to the entry.
-				 * If the entry is valid, set pgsz and continue.
-				 * If not, make it so, set pgsz, sync and continue.
-				 */
-				pte = mmuwalk(pdb, va, 2, 0);
-				if(pte && *pte & PTEVALID){
-					x = PPN(*pte);
-					if(x != pa)
-						panic("mmukmap2: pa 0x%ux entry 0x%ux\n",
-							pa, *pte);
-					pgsz = BY2PG;
-					pa += pgsz;
-					va += pgsz;
-					sync++;
-
-					continue;
-				}
-			}
-		}
-
-		/*
-		 * Not mapped. Check if it can be mapped using a big page -
-		 * starts on a 4MB boundary, size >= 4MB and processor can do it.
-		 * If not a big page, walk the walk, talk the talk.
-		 * Sync is set.
-		 */
-		if(pse && (pa % (4*MB)) == 0 && (pae >= pa+4*MB)){
-			*table = pa|PTESIZE|PTEWRITE|PTEUNCACHED|PTEVALID;
-			pgsz = 4*MB;
-		}
-		else{
-			pte = mmuwalk(pdb, va, 2, 1);
-			*pte = pa|PTEWRITE|PTEUNCACHED|PTEVALID;
-			pgsz = BY2PG;
-		}
-		pa += pgsz;
-		va += pgsz;
-		sync++;
-	}
-	unlock(&mmukmaplock);
-
-	/*
-	 * If something was added
-	 * then need to sync up.
-	 */
-	if(sync)
-		putcr3(PADDR(pdb));
-
-	return pa;
-}
-
-ulong
-upamalloc(ulong addr, int size, int align)
-{
-	ulong ae, a;
-
-	USED(align);
-
-	if((a = mapalloc(&rmapupa, addr, size, align)) == 0){
-		memdebug();
-		return 0;
-	}
-
-	/*
-	 * This is a travesty, but they all are.
-	 */
-	ae = mmukmap(a, 0, size);
-
-	/*
-	 * Should check here that it was all delivered
-	 * and put it back and barf if not.
-	 */
-	USED(ae);
-
-	/*
-	 * Be very careful this returns a PHYSICAL address.
-	 */
-	return a;
-}
-
-void
-upafree(ulong pa, int size)
-{
-	USED(pa, size);
-}
-
--- a/os/boot/pc/mkfile
+++ /dev/null
@@ -1,250 +1,0 @@
-<../../../mkconfig
-objtype=386
-SYSTARG=$OSTARG
-OBJTYPE=386
-BIN=$ROOT/Inferno/$OBJTYPE
-LIBDIR=$ROOT/Inferno/$OBJTYPE/lib
-LIBDIRS=../libflate $ROOT/libkern
-LIBS=\
-	libflate\
-	libkern\
-
-LIBFILES=${LIBS:%=$LIBDIR/%.a}
-<$ROOT/mkfiles/mkfile-$SYSTARG-$OBJTYPE
-
-BIN=$ROOT/Inferno/$OBJTYPE
-
-TARG=\
-	9load\
-	9pxeload\
-	9loadlite\
-	9loaddebug\
-	9loadlitedebug\
-	ld.com\
-	mbr\
-	pbs\
-	pbslba\
-
-CORE=\
-	alarm.$O\
-	cga.$O\
-	clock.$O\
-	console.$O\
-	dosboot.$O\
-	devfloppy.$O\
-	dma.$O\
-	fs.$O\
-	ilock.$O\
-	kbd.$O\
-	kfsboot.$O\
-	print.$O\
-	queue.$O\
-	trap.$O\
-	getcallerpc.$O\
-
-LOAD=\
-	8250.$O\
-	apm.$O\
-	boot.$O\
-	cis.$O\
-	conf.$O\
-	devbios.$O\
-	devi82365.$O\
-	devpccard.$O\
-	devsd.$O\
-	inflate.$O\
-	load.$O\
-	memory.$O\
-	part.$O\
-	pci.$O\
-	sdata.$O\
-	sdmylex.$O\
-	sd53c8xx.$O\
-	sdiahci.$O\
-	sdscsi.$O\
-	sdaoe.$O\
-	sdbios.$O\
-
-ETHER=\
-	bootp.$O\
-	eipfmt.$O\
-	ether.$O\
-	ether2114x.$O\
-	ether2000.$O\
-	ether589.$O\
-	ether79c970.$O\
-	ether8003.$O\
-	ether8139.$O\
-	ether8169.$O\
-	ether82563.$O\
-	ether82557.$O\
-	ether83815.$O\
-	ether8390.$O\
-	etherec2t.$O\
-	etherelnk3.$O\
-	etherga620.$O\
-	etherigbe.$O\
-	ethermii.$O\
-	etherrhine.$O\
-	etherdp83820.$O\
-
-BCOM=\
-	bcom.$O\
-	bootld.$O\
-	devsd.$O\
-	memory.$O\
-	part.$O\
-	pci.$O\
-	sdata.$O\
-	sdscsi.$O\
-
-HFILES=\
-	lib.h\
-	mem.h\
-	dat.h\
-	fns.h\
-	io.h\
-	aoe.h\
-
-CFLAGS=-FVTw -I. -I$ROOT/Inferno/$OBJTYPE/include -I$ROOT/include
-
-all:V:	$TARG
-
-9load:	l.$O $CORE $LOAD $ETHER $LIBFILES
-	$LD -o $target -H3 -T0x80010000 -l $prereq
-	ls -l $target
-
-9pxeload:	l.$O $CORE $LOAD $ETHER $LIBFILES
-	$LD -o $target -H3 -T0x80007C00 -l $prereq
-	ls -l $target
-
-9loaddebug:	l.$O $CORE $LOAD $ETHER $LIBFILES
-	$LD -o $target -T0x80010000 -l $prereq
-	ls -l $target
-	# acid $target
-	# map({"text", 0x80010000, 0x80090000, 0x00000020})
-
-9loadlite:	l.$O $CORE $LOAD noether.$O $LIBFILES
-	$LD -o $target -H3 -T0x80010000 -l $prereq
-	ls -l $target
-
-9loadlitedebug:	l.$O $CORE $LOAD noether.$O $LIBFILES
-	$LD -o $target -T0x80010000 -l $prereq
-	ls -l $target
-	# acid $target
-	# map({"text", 0x80010000, 0x80090000, 0x00000020})
-
-ld.com:	ld.$O $CORE $BCOM $LIBFILES
-	$LD -o $target -H3 -T0x80080100 -l $prereq
-	ls -l $target
-
-lddebug:	ld.$O $CORE $BCOM $LIBFILES
-	$LD -o $target -T0x80080100 -l $prereq
-	ls -l $target
-	# acid $target
-	# map({"text", 0x80080100, 0x800B0000, 0x00000020})
-
-ld.$O:	l.s
-	$AS -DDOTCOM -o $target l.s
-
-lpxe.$O:	l.s
-	$AS -DPXE -o $target l.s
-
-%.$O:	%.s
-	$AS $stem.s
-
-%.$O:	%.c
-	$CC $CFLAGS $stem.c
-
-%.$O:	$HFILES
-
-l.$O pbs.$O pbslba.$O mbr.$O:	x16.h
-
-clock.$O floppy.$O trap.$O:	ureg.h
-bcom.$O conf.$O devfloppy.$O devsd.$O dosboot.$O fs.$O \
-	kfsboot.$O load.$O part.$O:	dosfs.h fs.h kfs.h
-ether.$O etherelnk3.$O:	etherif.h
-devsd.$O part.$O sdata.$O sdscsi.$O: sd.h
-bootp.$O:	ip.h
-
-mbr:	mbr.$O
-	$LD -o $target -H3 -T0x0600 -l $prereq
-	ls -l $target
-
-pbs&:	pbs%.$O
-	$LD -o $target -H3 -T0x7C00 -l $prereq
-	ls -l $target
-
-pbs&.debug:	pbs%.$O
-	$LD -o $target -T0x7C00 -l $prereq
-	ls -l $target
-	# acid $target
-	# map({"text", 0x7C00, 0x7E00, 0x00000020})
-	
-# added to cause libflate to be made automatically:
-
-$ROOT/Inferno/$OBJTYPE/lib/lib%.a:Q:	all-$SHELLTYPE
-	#
-
-rc-lib%.a nt-lib%.a:VQ:
-	echo '@{builtin cd ' $ROOT/lib$stem ';mk SHELLTYPE=$SHELLTYPE SYSTARG=$SYSTARG OBJTYPE=$OBJTYPE install}'
-	@{builtin cd  $ROOT/lib$stem ;mk 'SHELLTYPE='$SHELLTYPE 'SYSTARG='$SYSTARG 'OBJTYPE='$OBJTYPE install}
-
-sh-lib%.a:VQ:
-	echo "(cd $ROOT/lib$stem ; mk SHELLTYPE=$SHELLTYPE SYSTARG=$SYSTARG OBJTYPE=$OBJTYPE install)"
-	(cd $ROOT/lib$stem ; mk SHELLTYPE=$SHELLTYPE SYSTARG=$SYSTARG OBJTYPE=$OBJTYPE install)
-
-clean:
-	rm -f *.[$OS] [$OS].out y.tab.? y.debug y.output $TARG 9loaddebug lddebug
-
-install:V:
-	for (i in $TARG)
-		mk $MKFLAGS $i.install
-
-%.install:V:	$BIN/%
-
-$BIN/%:	%
-	cp $stem $BIN/$stem
-
-UPDATE=\
-	mkfile\
-	${CORE:%.$O=%.c}\
-	${LOAD:%.$O=%.c}\
-	${BCOM:%.$O=%.c}\
-	${ETHER:%.$O=%.c}\
-	$HFILES\
-	l.s\
-	noether.c\
-	pbs.s\
-	pbslba.s\
-	mbr.s\
-	x16.h\
-	ureg.h\
-	dosfs.h\
-	fs.h\
-	kfs.h\
-	etherif.h\
-	sd.h\
-	ip.h\
-	devfloppy.h\
-	${TARG:%=/386/%}\
-
-update:V:
-	update $UPDATEFLAGS $UPDATE
-
-
-%-sh:QV:
-		for i in $LIBDIRS
-		do
-			echo "(cd $i ; mk SHELLTYPE=$SHELLTYPE SYSTARG=$SYSTARG OBJTYPE=$OBJTYPE $stem)"
-			(cd $i; mk 'SHELLTYPE='$SHELLTYPE 'SYSTARG='$SYSTARG 'OBJTYPE='$OBJTYPE $stem)
-		done
-
-%-rc %-nt:QV:
-		for (i in $LIBDIRS)
-		{
-			echo '@{cd $i ; mk SHELLTYPE=$SHELLTYPE SYSTARG=$SYSTARG OBJTYPE=$OBJTYPE $stem}'
-			@{cd $i; mk 'SHELLTYPE='$SHELLTYPE 'SYSTARG='$SYSTARG 'OBJTYPE='$OBJTYPE $stem}
-		}
-
-nuke:V:		clean nuke-$SHELLTYPE
--- a/os/boot/pc/noether.c
+++ /dev/null
@@ -1,46 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-int
-etherinit(void)
-{
-	return -1;
-}
-
-void
-etherinitdev(int, char*)
-{
-}
-
-void
-etherprintdevs(int)
-{
-}
-
-int
-etherrxpkt(int, Etherpkt*, int)
-{
-	return -1;
-}
-
-int
-ethertxpkt(int, Etherpkt*, int, int)
-{
-	return -1;
-}
-
-int
-bootpboot(int, char*, Boot*)
-{
-	return -1;
-}
-
-void*
-pxegetfspart(int, char*, int)
-{
-	return nil;
-}
--- a/os/boot/pc/part.c
+++ /dev/null
@@ -1,344 +1,0 @@
-#include	"u.h"
-#include	"lib.h"
-#include	"mem.h"
-#include	"dat.h"
-#include	"fns.h"
-
-#include	"sd.h"
-#include	"fs.h"
-
-enum {
-	Npart = 32
-};
-
-uchar *mbrbuf, *partbuf;
-int nbuf;
-#define trace 0
-
-int
-tsdbio(SDunit *unit, SDpart *part, void *a, vlong off, int mbr)
-{
-	uchar *b;
-
-	if(sdbio(unit, part, a, unit->secsize, off) != unit->secsize){
-		if(trace)
-			print("%s: read %lud at %lld failed\n", unit->name,
-				unit->secsize, (vlong)part->start*unit->secsize+off);
-		return -1;
-	}
-	b = a;
-	if(mbr && (b[0x1FE] != 0x55 || b[0x1FF] != 0xAA)){
-		if(trace)
-			print("%s: bad magic %.2ux %.2ux at %lld\n",
-				unit->name, b[0x1FE], b[0x1FF],
-				(vlong)part->start*unit->secsize+off);
-		return -1;
-	}
-	return 0;
-}
-
-/*
- *  read partition table.  The partition table is just ascii strings.
- */
-#define MAGIC "plan9 partitions"
-static void
-oldp9part(SDunit *unit)
-{
-	SDpart *pp;
-	char *field[3], *line[Npart+1];
-	ulong n, start, end;
-	int i;
-
-	/*
-	 *  We have some partitions already.
-	 */
-	pp = &unit->part[unit->npart];
-
-	/*
-	 * We prefer partition tables on the second to last sector,
-	 * but some old disks use the last sector instead.
-	 */
-	strcpy(pp->name, "partition");
-	pp->start = unit->sectors - 2;
-	pp->end = unit->sectors - 1;
-
-	if(tsdbio(unit, pp, partbuf, 0, 0) < 0)
-		return;
-
-	if(strncmp((char*)partbuf, MAGIC, sizeof(MAGIC)-1) != 0) {
-		/* not found on 2nd last sector; look on last sector */
-		pp->start++;
-		pp->end++;
-		if(tsdbio(unit, pp, partbuf, 0, 0) < 0)
-			return;
-		if(strncmp((char*)partbuf, MAGIC, sizeof(MAGIC)-1) != 0)
-			return;
-		print("%s: using old plan9 partition table on last sector\n", unit->name);
-	}else
-		print("%s: using old plan9 partition table on 2nd-to-last sector\n", unit->name);
-
-	/* we found a partition table, so add a partition partition */
-	unit->npart++;
-	partbuf[unit->secsize-1] = '\0';
-
-	/*
-	 * parse partition table
-	 */
-	n = getfields((char*)partbuf, line, Npart+1, '\n');
-	if(n && strncmp(line[0], MAGIC, sizeof(MAGIC)-1) == 0){
-		for(i = 1; i < n && unit->npart < SDnpart; i++){
-			if(getfields(line[i], field, 3, ' ') != 3)
-				break;
-			start = strtoull(field[1], 0, 0);
-			end = strtoull(field[2], 0, 0);
-			if(start >= end || end > unit->sectors)
-				break;
-			sdaddpart(unit, field[0], start, end);
-		}
-	}	
-}
-
-static void
-p9part(SDunit *unit, char *name)
-{
-	SDpart *p;
-	char *field[4], *line[Npart+1];
-	uvlong start, end;
-	int i, n;
-	
-	p = sdfindpart(unit, name);
-	if(p == nil)
-		return;
-
-	if(tsdbio(unit, p, partbuf, unit->secsize, 0) < 0)
-		return;
-	partbuf[unit->secsize-1] = '\0';
-
-	if(strncmp((char*)partbuf, "part ", 5) != 0)
-		return;
-
-	n = getfields((char*)partbuf, line, Npart+1, '\n');
-	if(n == 0)
-		return;
-	for(i = 0; i < n && unit->npart < SDnpart; i++){
-		if(strncmp(line[i], "part ", 5) != 0)
-			break;
-		if(getfields(line[i], field, 4, ' ') != 4)
-			break;
-		start = strtoull(field[2], 0, 0);
-		end = strtoull(field[3], 0, 0);
-		if(start >= end || end > unit->sectors)
-			break;
-		sdaddpart(unit, field[1], p->start+start, p->start+end);
-	}
-}
-
-int
-isdos(int t)
-{
-	return t==FAT12 || t==FAT16 || t==FATHUGE || t==FAT32 || t==FAT32X;
-}
-
-int
-isextend(int t)
-{
-	return t==EXTEND || t==EXTHUGE || t==LEXTEND;
-}
-
-/* 
- * Fetch the first dos and all plan9 partitions out of the MBR partition table.
- * We return -1 if we did not find a plan9 partition.
- */
-static int
-mbrpart(SDunit *unit)
-{
-	Dospart *dp;
-	ulong taboffset, start, end;
-	ulong firstxpart, nxtxpart;
-	int havedos, i, nplan9;
-	char name[10];
-
-	taboffset = 0;
-	dp = (Dospart*)&mbrbuf[0x1BE];
-	if(1) {
-		/* get the MBR (allowing for DMDDO) */
-		if(tsdbio(unit, &unit->part[0], mbrbuf, (vlong)taboffset*unit->secsize, 1) < 0)
-			return -1;
-		for(i=0; i<4; i++)
-			if(dp[i].type == DMDDO) {
-				if(trace)
-					print("DMDDO partition found\n");
-				taboffset = 63;
-				if(tsdbio(unit, &unit->part[0], mbrbuf, (vlong)taboffset*unit->secsize, 1) < 0)
-					return -1;
-				i = -1;	/* start over */
-			}
-	}
-
-	/*
-	 * Read the partitions, first from the MBR and then
-	 * from successive extended partition tables.
-	 */
-	nplan9 = 0;
-	havedos = 0;
-	firstxpart = 0;
-	for(;;) {
-		if(tsdbio(unit, &unit->part[0], mbrbuf, (vlong)taboffset*unit->secsize, 1) < 0)
-			return -1;
-		if(trace) {
-			if(firstxpart)
-				print("%s ext %lud ", unit->name, taboffset);
-			else
-				print("%s mbr ", unit->name);
-		}
-		nxtxpart = 0;
-		for(i=0; i<4; i++) {
-			if(trace)
-				print("dp %d...", dp[i].type);
-			start = taboffset+GLONG(dp[i].start);
-			end = start+GLONG(dp[i].len);
-
-			if(dp[i].type == PLAN9) {
-				if(nplan9 == 0)
-					strcpy(name, "plan9");
-				else
-					sprint(name, "plan9.%d", nplan9);
-				sdaddpart(unit, name, start, end);
-				p9part(unit, name);
-				nplan9++;
-			}
-
-			/*
-			 * We used to take the active partition (and then the first
-			 * when none are active).  We have to take the first here,
-			 * so that the partition we call ``dos'' agrees with the
-			 * partition disk/fdisk calls ``dos''. 
-			 */
-			if(havedos==0 && isdos(dp[i].type)){
-				havedos = 1;
-				sdaddpart(unit, "dos", start, end);
-			}
-
-			/* nxtxpart is relative to firstxpart (or 0), not taboffset */
-			if(isextend(dp[i].type)){
-				nxtxpart = start-taboffset+firstxpart;
-				if(trace)
-					print("link %lud...", nxtxpart);
-			}
-		}
-		if(trace)
-			print("\n");
-
-		if(!nxtxpart)
-			break;
-		if(!firstxpart)
-			firstxpart = nxtxpart;
-		taboffset = nxtxpart;
-	}	
-	return nplan9 ? 0 : -1;
-}
-
-/*
- * To facilitate booting from CDs, we create a partition for
- * the boot floppy image embedded in a bootable CD.
- */
-static int
-part9660(SDunit *unit)
-{
-	uchar buf[2048];
-	ulong a, n;
-	uchar *p;
-
-	if(unit->secsize != 2048)
-		return -1;
-
-	if(sdbio(unit, &unit->part[0], buf, 2048, 17*2048) < 0)
-		return -1;
-
-	if(buf[0] || strcmp((char*)buf+1, "CD001\x01EL TORITO SPECIFICATION") != 0)
-		return -1;
-
-	
-	p = buf+0x47;
-	a = p[0] | (p[1]<<8) | (p[2]<<16) | (p[3]<<24);
-
-	if(sdbio(unit, &unit->part[0], buf, 2048, a*2048) < 0)
-		return -1;
-
-	if(memcmp(buf, "\x01\x00\x00\x00", 4) != 0
-	|| memcmp(buf+30, "\x55\xAA", 2) != 0
-	|| buf[0x20] != 0x88)
-		return -1;
-
-	p = buf+0x28;
-	a = p[0] | (p[1]<<8) | (p[2]<<16) | (p[3]<<24);
-
-	switch(buf[0x21]){
-	case 0x01:
-		n = 1200*1024;
-		break;
-	case 0x02:
-		n = 1440*1024;
-		break;
-	case 0x03:
-		n = 2880*1024;
-		break;
-	default:
-		return -1;
-	}
-	n /= 2048;
-
-	print("found partition %s!cdboot; %lud+%lud\n", unit->name, a, n);
-	sdaddpart(unit, "cdboot", a, a+n);
-	return 0;
-}
-
-enum {
-	NEW = 1<<0,
-	OLD = 1<<1
-};
-
-void
-partition(SDunit *unit)
-{
-	int type;
-	char *p;
-
-	if(unit->part == 0)
-		return;
-
-	if(part9660(unit) == 0)
-		return;
-
-	p = getconf("partition");
-	if(p == nil)
-		p = defaultpartition;
-
-	if(p != nil && strncmp(p, "new", 3) == 0)
-		type = NEW;
-	else if(p != nil && strncmp(p, "old", 3) == 0)
-		type = OLD;
-	else
-		type = NEW|OLD;
-
-	if(nbuf < unit->secsize) {
-		free(mbrbuf);
-		free(partbuf);
-		mbrbuf = malloc(unit->secsize);
-		partbuf = malloc(unit->secsize);
-		if(mbrbuf==nil || partbuf==nil) {
-			free(mbrbuf);
-			free(partbuf);
-			partbuf = mbrbuf = nil;
-			nbuf = 0;
-			return;
-		}
-		nbuf = unit->secsize;
-	}
-
-	if((type & NEW) && mbrpart(unit) >= 0){
-		/* nothing to do */;
-	}
-	else if(type & OLD)
-		oldp9part(unit);
-}
--- a/os/boot/pc/pbs.s
+++ /dev/null
@@ -1,372 +1,0 @@
-/*
- * FAT Partition Boot Sector. Loaded at 0x7C00:
- *	8a pbs.s; 8l -o pbs -l -H3 -T0x7C00 pbs.8
- * Will load the target at LOADSEG*16+LOADOFF, so the target
- * should be probably be loaded with LOADOFF added to the
- * -Taddress.
- * If LOADSEG is a multiple of 64KB and LOADOFF is 0 then
- * targets larger than 64KB can be loaded.
- *
- * This code uses the traditional INT13 BIOS interface and can
- * therefore only access the first 8.4GB of the disc.
- *
- * It relies on the _volid field in the FAT header containing
- * the LBA of the root directory.
- */
-#include "x16.h"
-#include "mem.h"
-
-#define LOADSEG		(0x10000/16)	/* where to load code (64KB) */
-#define LOADOFF		0
-#define DIROFF		0x0200		/* where to read the root directory */
-
-/*
- * FAT directory entry.
- */
-#define Dname		0x00
-#define Dext		0x08
-#define Dattr		0x0B
-#define Dtime		0x16
-#define Ddate		0x18
-#define Dstart		0x1A
-#define Dlengthlo	0x1C
-#define Dlengthhi	0x1E
-
-#define Dirsz		0x20
-
-/*
- * Data is kept on the stack, indexed by rBP.
- */
-#define Xdap		0x00		/* disc address packet */
-#define Xrootsz		0x10		/* file data area */
-#define Xdrive		0x12		/* boot drive, passed by BIOS or MBR */
-#define Xtotal		0x14		/* sum of allocated data above */
-
-TEXT _magic(SB), $0
-	BYTE $0xEB; BYTE $0x3C;		/* jmp .+ 0x3C  (_start0x3E) */
-	BYTE $0x90			/* nop */
-TEXT _version(SB), $0
-	BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
-	BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00
-TEXT _sectsize(SB), $0
-	BYTE $0x00; BYTE $0x00
-TEXT _clustsize(SB), $0
-	BYTE $0x00
-TEXT _nresrv(SB), $0
-	BYTE $0x00; BYTE $0x00
-TEXT _nfats(SB), $0
-	BYTE $0x00
-TEXT _rootsize(SB), $0
-	BYTE $0x00; BYTE $0x00
-TEXT _volsize(SB), $0
-	BYTE $0x00; BYTE $0x00
-TEXT _mediadesc(SB), $0
-	BYTE $0x00
-TEXT _fatsize(SB), $0
-	BYTE $0x00; BYTE $0x00
-TEXT _trksize(SB), $0
-	BYTE $0x00; BYTE $0x00
-TEXT _nheads(SB), $0
-	BYTE $0x00; BYTE $0x00
-TEXT _nhiddenlo(SB), $0
-	BYTE $0x00; BYTE $0x00
-TEXT _nhiddenhi(SB), $0
-	BYTE $0x00; BYTE $0x00;
-TEXT _bigvolsize(SB), $0
-	BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
-TEXT _driveno(SB), $0
-	BYTE $0x00
-TEXT _reserved0(SB), $0
-	BYTE $0x00
-TEXT _bootsig(SB), $0
-	BYTE $0x00
-TEXT _volid(SB), $0
-	BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
-TEXT _label(SB), $0
-	BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
-	BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00
-	BYTE $0x00; BYTE $0x00; BYTE $0x00
-TEXT _type(SB), $0
-	BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
-	BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
-
-_start0x3E:
-	CLI
-	CLR(rAX)
-	MTSR(rAX, rSS)			/* 0000 -> rSS */
-	MTSR(rAX, rDS)			/* 0000 -> rDS, source segment */
-	MTSR(rAX, rES)
-	LWI(_magic-Xtotal(SB), rSP)
-	MW(rSP, rBP)			/* set the indexed-data pointer */
-
-	SBPB(rDL, Xdrive)		/* save the boot drive */
-
-	/* booting from a CD starts us at 7C0:0.  Move to 0:7C00 */
-	PUSHR(rAX)
-	LWI(_nxt(SB), rAX)
-	PUSHR(rAX)
-	BYTE $0xCB	/* FAR RET */
-
-TEXT _nxt(SB), $0
-	STI
-
-	LWI(confidence(SB), rSI)	/* for that warm, fuzzy feeling */
-	CALL16(BIOSputs(SB))
-
-	CALL16(dreset(SB))
-
-_jmp00:
-	LW(_volid(SB), rAX)		/* Xrootlo */
-	LW(_volid+2(SB), rDX)		/* Xroothi */
-
-	LWI(_magic+DIROFF(SB), rBX)
-	CALL16(BIOSread(SB))		/* read the root directory */
-
-	LWI((512/Dirsz), rBX)
-
-	LWI(_magic+DIROFF(SB), rDI)	/* compare first directory entry */
-
-_cmp00:
-	PUSHR(rDI)			/* save for later if it matches */
-	LWI(bootfile(SB), rSI)
-	LWI(Dattr, rCX)
-	REP
-	CMPSB
-	POPR(rDI)
-	JEQ _jmp02
-
-	DEC(rBX)
-	JEQ _jmp01
-
-	ADDI(Dirsz, rDI)
-	JMP _cmp00
-_jmp01:
-	CALL16(buggery(SB))
-
-_jmp02:
-	CLR(rBX)			/* a handy value */
-	LW(_rootsize(SB), rAX)		/* calculate and save Xrootsz */
-	LWI(Dirsz, rCX)
-	MUL(rCX)
-	LW(_sectsize(SB), rCX)
-	PUSHR(rCX)
-	DEC(rCX)
-	ADD(rCX, rAX)
-	ADC(rBX, rDX)
-	POPR(rCX)			/* _sectsize(SB) */
-	DIV(rCX)
-	PUSHR(rAX)			/* Xrootsz */
-
-	/*
-	 * rDI points to the matching directory entry.
-	 */
-	LXW(Dstart, xDI, rAX)		/* starting sector address */
-	DEC(rAX)			/* that's just the way it is */
-	DEC(rAX)
-	LB(_clustsize(SB), rCL)
-	CLRB(rCH)
-	MUL(rCX)
-	LW(_volid(SB), rCX)		/* Xrootlo */
-	ADD(rCX, rAX)
-	LW(_volid+2(SB), rCX)		/* Xroothi */
-	ADC(rCX, rDX)
-	POPR(rCX)			/* Xrootsz */
-	ADD(rCX, rAX)
-	ADC(rBX, rDX)
-
-	PUSHR(rAX)			/* calculate how many sectors to read */
-	PUSHR(rDX)
-	LXW(Dlengthlo, xDI, rAX)
-	LXW(Dlengthhi, xDI, rDX)
-	LW(_sectsize(SB), rCX)
-	PUSHR(rCX)
-	DEC(rCX)
-	ADD(rCX, rAX)
-	ADC(rBX, rDX)
-	POPR(rCX)			/* _sectsize(SB) */
-	DIV(rCX)
-	MW(rAX, rCX)
-	POPR(rDX)
-	POPR(rAX)
-
-	LWI(LOADSEG, rBX)		/* address to load into (seg+offset) */
-	MTSR(rBX, rES)			/*  seg */
-	LWI(LOADOFF, rBX)		/*  offset */
-
-_readboot:
-	CALL16(BIOSread(SB))		/* read the sector */
-
-	LW(_sectsize(SB), rDI)		/* bump addresses/counts */
-	ADD(rDI, rBX)
-	JCC _incsecno
-
-	MFSR(rES, rDI)			/* next 64KB segment */
-	ADDI(0x1000, rDI)
-	MTSR(rDI, rES)
-
-_incsecno:
-	CLR(rDI)
-	INC(rAX)
-	ADC(rDI, rDX)
-	LOOP _readboot
-
-	LWI(LOADSEG, rDI)		/* set rDS for loaded code */
-	MTSR(rDI, rDS)
-	FARJUMP16(LOADSEG, LOADOFF)	/* no deposit, no return */
-
-TEXT buggery(SB), $0
-	LWI(error(SB), rSI)
-	CALL16(BIOSputs(SB))
-
-_wait:
-	CLR(rAX)			/* wait for almost any key */
-	BIOSCALL(0x16)
-
-_reset:
-	CLR(rBX)			/* set ES segment for BIOS area */
-	MTSR(rBX, rES)
-
-	LWI(0x0472, rBX)		/* warm-start code address */
-	LWI(0x1234, rAX)		/* warm-start code */
-	POKEW				/* MOVW	AX, ES:[BX] */
-
-	FARJUMP16(0xFFFF, 0x0000)	/* reset */
-
-/*
- * Read a sector from a disc. On entry:
- *   rDX:rAX	sector number
- *   rES:rBX	buffer address
- * For BIOSCALL(0x13):
- *   rAH	0x02
- *   rAL	number of sectors to read (1)
- *   rCH	low 8 bits of cylinder
- *   rCL	high 2 bits of cylinder (7-6), sector (5-0)
- *   rDH	head
- *   rDL	drive
- *   rES:rBX	buffer address
- */
-TEXT BIOSread(SB), $0
-	LWI(5, rDI)			/* retry count (ATAPI ZIPs suck) */
-_retry:
-	PUSHA				/* may be trashed by BIOSCALL */
-	PUSHR(rBX)
-
-	LW(_trksize(SB), rBX)
-	LW(_nheads(SB), rDI)
-	IMUL(rDI, rBX)
-	OR(rBX, rBX)
-	JZ _ioerror
-
-_okay:
-	DIV(rBX)			/* cylinder -> rAX, track,sector -> rDX */
-
-	MW(rAX, rCX)			/* save cylinder */
-	ROLI(0x08, rCX)			/* swap rC[HL] */
-	SHLBI(0x06, rCL)		/* move high bits up */
-
-	MW(rDX, rAX)
-	CLR(rDX)
-	LW(_trksize(SB), rBX)
-
-	DIV(rBX)			/* head -> rAX, sector -> rDX */
-
-	INC(rDX)			/* sector numbers are 1-based */
-	ANDI(0x003F, rDX)		/* should not be necessary */
-	OR(rDX, rCX)
-
-	MW(rAX, rDX)
-	SHLI(0x08, rDX)			/* form head */
-	LBPB(Xdrive, rDL)		/* form drive */
-
-	POPR(rBX)
-	LWI(0x0201, rAX)		/* form command and sectors */
-	BIOSCALL(0x13)			/* CF set on failure */
-	JCC _BIOSreadret
-
-	POPA
-	DEC(rDI)			/* too many retries? */
-	JEQ _ioerror
-
-	CALL16(dreset(SB))
-	JMP _retry
-
-_ioerror:
-	LWI(ioerror(SB), rSI)
-	CALL16(BIOSputs(SB))
-	JMP _wait
-
-_BIOSreadret:
-	POPA
-	RET
-
-TEXT dreset(SB), $0
-	PUSHA
-	CLR(rAX)			/* rAH == 0 == reset disc system */
-	LBPB(Xdrive, rDL)
-	BIOSCALL(0x13)
-	ORB(rAH, rAH)			/* status (0 == success) */
-	POPA
-	JNE _ioerror
-	RET
-
-/*
- * Output a string to the display.
- * String argument is in rSI.
- */
-TEXT BIOSputs(SB), $0
-	PUSHA
-	CLR(rBX)
-_BIOSputs:
-	LODSB
-	ORB(rAL, rAL)
-	JEQ _BIOSputsret
-
-	LBI(0x0E, rAH)
-	BIOSCALL(0x10)
-	JMP _BIOSputs
-
-_BIOSputsret:
-	POPA
-	RET
-
-/* "Bad format or I/O error\r\nPress almost any key to reboot..."*/
-TEXT error(SB), $0
-	BYTE $'B'; BYTE $'a'; BYTE $'d'; BYTE $' ';
-	BYTE $'f'; BYTE $'o'; BYTE $'r'; BYTE $'m';
-	BYTE $'a'; BYTE $'t'; BYTE $' '; BYTE $'o';
-	BYTE $'r'; BYTE $' ';
-/* "I/O error\r\nPress almost any key to reboot..." */
-TEXT ioerror(SB), $0
-	BYTE $'I'; BYTE $'/'; BYTE $'O'; BYTE $' ';
-	BYTE $'e'; BYTE $'r'; BYTE $'r'; BYTE $'o';
-	BYTE $'r'; BYTE $'\r';BYTE $'\n';
-	BYTE $'P'; BYTE $'r'; BYTE $'e'; BYTE $'s';
-	BYTE $'s'; BYTE $' '; BYTE $'a'; BYTE $' ';
-	BYTE $'k'; BYTE $'e'; BYTE $'y';
-	BYTE $' '; BYTE $'t'; BYTE $'o'; BYTE $' ';
-	BYTE $'r'; BYTE $'e'; BYTE $'b'; BYTE $'o';
-	BYTE $'o'; BYTE $'t';
-	BYTE $'.'; BYTE $'.'; BYTE $'.';
-	BYTE $'\z';
-
-#ifdef USEBCOM
-/* "B       COM" */
-TEXT bootfile(SB), $0
-	BYTE $'B'; BYTE $' '; BYTE $' '; BYTE $' ';
-	BYTE $' '; BYTE $' '; BYTE $' '; BYTE $' ';
-	BYTE $'C'; BYTE $'O'; BYTE $'M';
-	BYTE $'\z';
-#else
-/* "9LOAD      " */
-TEXT bootfile(SB), $0
-	BYTE $'9'; BYTE $'L'; BYTE $'O'; BYTE $'A';
-	BYTE $'D'; BYTE $' '; BYTE $' '; BYTE $' ';
-	BYTE $' '; BYTE $' '; BYTE $' ';
-	BYTE $'\z';
-#endif /* USEBCOM */
-
-/* "PBS..." */
-TEXT confidence(SB), $0
-	BYTE $'P'; BYTE $'B'; BYTE $'S'; BYTE $'1'; 
-	BYTE $'.'; BYTE $'.'; BYTE $'.';
-	BYTE $'\z';
binary files a/os/boot/pc/pbsdisk /dev/null differ
--- a/os/boot/pc/pbsdisk.s
+++ /dev/null
@@ -1,344 +1,0 @@
-/*
- * Debugging boot sector.  Reads the first directory
- * sector from disk and displays it.
- *
- * It relies on the _volid field in the FAT header containing
- * the LBA of the root directory.
- */
-#include "x16.h"
-
-#define DIROFF		0x00200		/* where to read the root directory (offset) */
-#define LOADSEG		(0x10000/16)	/* where to load code (64KB) */
-#define LOADOFF		0
-
-/*
- * FAT directory entry.
- */
-#define Dname		0x00
-#define Dext		0x08
-#define Dattr		0x0B
-#define Dtime		0x16
-#define Ddate		0x18
-#define Dstart		0x1A
-#define Dlengthlo	0x1C
-#define Dlengthhi	0x1E
-
-#define Dirsz		0x20
-
-/*
- * We keep data on the stack, indexed by rBP.
- */
-#define Xdrive		0x00		/* boot drive, passed by BIOS in rDL */
-#define Xrootlo		0x02		/* offset of root directory */
-#define Xroothi		0x04
-#define Xrootsz		0x06		/* file data area */
-#define Xtotal		0x08		/* sum of allocated data above */
-#define Xdap		0x00		/* disc address packet */
-
-TEXT _magic(SB), $0
-	BYTE $0xEB; BYTE $0x3C;		/* jmp .+ 0x3C  (_start0x3E) */
-	BYTE $0x90			/* nop */
-TEXT _version(SB), $0
-	BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
-	BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00
-TEXT _sectsize(SB), $0
-	BYTE $0x00; BYTE $0x00
-TEXT _clustsize(SB), $0
-	BYTE $0x00
-TEXT _nresrv(SB), $0
-	BYTE $0x00; BYTE $0x00
-TEXT _nfats(SB), $0
-	BYTE $0x00
-TEXT _rootsize(SB), $0
-	BYTE $0x00; BYTE $0x00
-TEXT _volsize(SB), $0
-	BYTE $0x00; BYTE $0x00
-TEXT _mediadesc(SB), $0
-	BYTE $0x00
-TEXT _fatsize(SB), $0
-	BYTE $0x00; BYTE $0x00
-TEXT _trksize(SB), $0
-	BYTE $0x00; BYTE $0x00
-TEXT _nheads(SB), $0
-	BYTE $0x00; BYTE $0x00
-TEXT _nhiddenlo(SB), $0
-	BYTE $0x00; BYTE $0x00
-TEXT _nhiddenhi(SB), $0
-	BYTE $0x00; BYTE $0x00;
-TEXT _bigvolsize(SB), $0
-	BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
-TEXT _driveno(SB), $0
-	BYTE $0x00
-TEXT _reserved0(SB), $0
-	BYTE $0x00
-TEXT _bootsig(SB), $0
-	BYTE $0x00
-TEXT _volid(SB), $0
-	BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
-TEXT _label(SB), $0
-	BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
-	BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00
-	BYTE $0x00; BYTE $0x00; BYTE $0x00
-TEXT _type(SB), $0
-	BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
-	BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
-
-_start0x3E:
-	CLI
-	CLR(rAX)
-	MTSR(rAX, rSS)			/* 0000 -> rSS */
-	MTSR(rAX, rDS)			/* 0000 -> rDS, source segment */
-	MTSR(rAX, rES)
-	LWI(_magic-Xtotal(SB), rSP)
-	MW(rSP, rBP)			/* set the indexed-data pointer */
-	SBPB(rDL, Xdrive)		/* save the boot drive */
-
-	/* VMware starts us at 7C0:0.  Move to 0:7C00 */
-	PUSHR(rAX)
-	LWI(_nxt(SB), rAX)
-	PUSHR(rAX)
-	BYTE $0xCB	/* FAR RET */
-
-TEXT _nxt(SB), $0
-	STI
-	LWI(confidence(SB), rSI)	/* for that warm, fuzzy feeling */
-	CALL16(BIOSputs(SB))
-
-	CALL16(dreset(SB))
-
-_jmp00:
-	LW(_volid(SB), rAX)		/* Xrootlo */
-	LW(_volid+2(SB), rDX)		/* Xroothi */
-
-	LWI(_magic+DIROFF(SB), rBX)
-	CALL16(BIOSread(SB))		/* read the root directory */
-
-	CALL16(printnl(SB))
-	LWI(_magic+DIROFF(SB), rBX)
-	LWI((512/2), rCX)
-	CALL16(printbuf(SB))
-
-xloop:
-	JMP xloop
-
-
-TEXT buggery(SB), $0
-	LWI(error(SB), rSI)
-	CALL16(BIOSputs(SB))
-
-TEXT quietbuggery(SB), $0
-xbuggery:
-	JMP xbuggery
-
-/*
- * Read a sector from a disc. On entry:
- *   rDX:rAX	sector number
- *   rES:rBX	buffer address
- * For BIOSCALL(0x13):
- *   rAH	0x02
- *   rAL	number of sectors to read (1)
- *   rCH	low 8 bits of cylinder
- *   rCL	high 2 bits of cylinder (7-6), sector (5-0)
- *   rDH	head
- *   rDL	drive
- *   rES:rBX	buffer address
- */
-TEXT BIOSread(SB), $0
-	LWI(5, rDI)			/* retry count (ATAPI ZIPs suck) */
-_retry:
-	PUSHA				/* may be trashed by BIOSCALL */
-	PUSHR(rBX)
-
-	LW(_trksize(SB), rBX)
-	LW(_nheads(SB), rDI)
-	IMUL(rDI, rBX)
-	OR(rBX, rBX)
-	JZ _ioerror
-
-_okay:
-	DIV(rBX)			/* cylinder -> rAX, track,sector -> rDX */
-
-	MW(rAX, rCX)			/* save cylinder */
-	ROLI(0x08, rCX)			/* swap rC[HL] */
-	SHLBI(0x06, rCL)		/* move high bits up */
-
-	MW(rDX, rAX)
-	CLR(rDX)
-	LW(_trksize(SB), rBX)
-
-	DIV(rBX)			/* head -> rAX, sector -> rDX */
-
-	INC(rDX)			/* sector numbers are 1-based */
-	ANDI(0x003F, rDX)		/* should not be necessary */
-	OR(rDX, rCX)
-
-	MW(rAX, rDX)
-	SHLI(0x08, rDX)			/* form head */
-	LBPB(Xdrive, rDL)		/* form drive */
-
-	POPR(rBX)
-	LWI(0x0201, rAX)		/* form command and sectors */
-	BIOSCALL(0x13)			/* CF set on failure */
-	JCC _BIOSreadret
-
-	POPA
-	DEC(rDI)			/* too many retries? */
-	JEQ _ioerror
-
-	CALL16(dreset(SB))
-	JMP _retry
-
-_ioerror:
-	LWI(ioerror(SB), rSI)
-	CALL16(BIOSputs(SB))
-	JMP xbuggery
-
-_BIOSreadret:
-	POPA
-	RET
-
-TEXT dreset(SB), $0
-	PUSHA
-	CLR(rAX)			/* rAH == 0 == reset disc system */
-	LBPB(Xdrive, rDL)
-	BIOSCALL(0x13)
-	ORB(rAH, rAH)			/* status (0 == success) */
-	POPA
-	JNE _ioerror
-	RET
-
-TEXT printsharp(SB), $0
-	LWI(sharp(SB), rSI)
-_doprint:
-	CALL16(BIOSputs(SB))
-	RET
-
-TEXT printspace(SB), $0
-	LWI(space(SB), rSI)
-	JMP _doprint
-
-TEXT printnl(SB), $0
-	LWI(nl(SB), rSI)
-	JMP _doprint
-
-/*
- * Output a string to the display.
- * String argument is in rSI.
- */
-TEXT BIOSputs(SB), $0
-	PUSHA
-	CLR(rBX)
-_BIOSputs:
-	LODSB
-	ORB(rAL, rAL)
-	JEQ _BIOSputsret
-
-	LBI(0x0E, rAH)
-	BIOSCALL(0x10)
-	JMP _BIOSputs
-
-_BIOSputsret:
-	POPA
-	RET
-
-/*
- * Output a register to the display.
- */
-TEXT printAX(SB), $0
-	PUSHW(rAX)
-	PUSHW(rBX)
-	PUSHW(rCX)
-	PUSHW(rDI)
-
-	LWI(4, rCX)
-	LWI(numbuf+4(SB), rSI)
-
-_nextchar:
-	DEC(rSI)
-	MW(rAX, rBX)
-	ANDI(0x000F, rBX)
-	ADDI(0x30, rBX)	/* 0x30 = '0' */
-	CMPI(0x39, rBX)	/* 0x39 = '9' */
-	JLE _dowrite
-	ADDI(0x07, rBX)	/* 0x07 = 'A'-(1+'9')*/
-
-_dowrite:
-	SXB(rBL, 0, xSI)
-	SHRI(4, rAX)
-
-	DEC(rCX)
-	JNE _nextchar
-
-	LWI(numbuf(SB), rSI)
-	CALL16(BIOSputs(SB))
-
-	POPW(rDI)
-	POPW(rCX)
-	POPW(rBX)
-	POPW(rAX)
-
-	CALL16(printspace(SB))
-	RET
-
-TEXT printDXAX(SB), $0
-	PUSHW(rAX)
-	MW(rDX, rAX)
-	CALL16(printAX(SB))
-	POPW(rAX)
-	CALL16(printAX(SB))
-	RET
-
-TEXT printBX(SB), $0
-	PUSHW(rAX)
-	MW(rBX, rAX)
-	CALL16(printAX(SB))
-	POPW(rAX)
-	RET
-
-/*
- * Output some number of words to the display
- * rDS:rDI - buffer
- * rCX: number of words
- */
-TEXT printbuf(SB), $0
-	PUSHW(rAX)
-	PUSHW(rBX)
-	PUSHW(rCX)
-
-_nextword:
-	LXW(0, xBX, rAX)
-	CALL16(printAX(SB))
-	INC(rBX)
-	INC(rBX)
-	DEC(rCX)
-	JNE _nextword
-
-	POPW(rCX)
-	POPW(rBX)
-	POPW(rAX)
-	RET
-
-TEXT error(SB), $0
-	BYTE $'E'; 
-
-TEXT ioerror(SB), $0
-	BYTE $'I'; 
-
-TEXT nl(SB), $0
-	BYTE $'\r';
-	BYTE $'\n';
-	BYTE $'\z';
-
-TEXT numbuf(SB), $0
-	BYTE $'X'; BYTE $'X'; BYTE $'X'; BYTE $'X';
-	BYTE $'\z';
-
-TEXT space(SB), $0
-	BYTE $' ';
-	BYTE $'\z';
-
-TEXT sharp(SB), $0
-	BYTE $'#'; BYTE $'\z';
-
-TEXT confidence(SB), $0
-	BYTE $'P'; BYTE $'\z'
binary files a/os/boot/pc/pbsdisklba /dev/null differ
--- a/os/boot/pc/pbsdisklba.s
+++ /dev/null
@@ -1,327 +1,0 @@
-/*
- * Debugging boot sector.  Reads the first directory
- * sector from disk and displays it.
- *
- * It relies on the _volid field in the FAT header containing
- * the LBA of the root directory.
- */
-#include "x16.h"
-
-#define DIROFF		0x00200		/* where to read the root directory (offset) */
-#define LOADSEG		(0x10000/16)	/* where to load code (64KB) */
-#define LOADOFF		0
-
-/*
- * FAT directory entry.
- */
-#define Dname		0x00
-#define Dext		0x08
-#define Dattr		0x0B
-#define Dtime		0x16
-#define Ddate		0x18
-#define Dstart		0x1A
-#define Dlengthlo	0x1C
-#define Dlengthhi	0x1E
-
-#define Dirsz		0x20
-
-/*
- * We keep data on the stack, indexed by rBP.
- */
-#define Xdrive		0x00		/* boot drive, passed by BIOS in rDL */
-#define Xrootlo		0x02		/* offset of root directory */
-#define Xroothi		0x04
-#define Xrootsz		0x06		/* file data area */
-#define Xtotal		0x08		/* sum of allocated data above */
-#define Xdap		0x00		/* disc address packet */
-
-TEXT _magic(SB), $0
-	BYTE $0xEB; BYTE $0x3C;		/* jmp .+ 0x3C  (_start0x3E) */
-	BYTE $0x90			/* nop */
-TEXT _version(SB), $0
-	BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
-	BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00
-TEXT _sectsize(SB), $0
-	BYTE $0x00; BYTE $0x00
-TEXT _clustsize(SB), $0
-	BYTE $0x00
-TEXT _nresrv(SB), $0
-	BYTE $0x00; BYTE $0x00
-TEXT _nfats(SB), $0
-	BYTE $0x00
-TEXT _rootsize(SB), $0
-	BYTE $0x00; BYTE $0x00
-TEXT _volsize(SB), $0
-	BYTE $0x00; BYTE $0x00
-TEXT _mediadesc(SB), $0
-	BYTE $0x00
-TEXT _fatsize(SB), $0
-	BYTE $0x00; BYTE $0x00
-TEXT _trksize(SB), $0
-	BYTE $0x00; BYTE $0x00
-TEXT _nheads(SB), $0
-	BYTE $0x00; BYTE $0x00
-TEXT _nhiddenlo(SB), $0
-	BYTE $0x00; BYTE $0x00
-TEXT _nhiddenhi(SB), $0
-	BYTE $0x00; BYTE $0x00;
-TEXT _bigvolsize(SB), $0
-	BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
-TEXT _driveno(SB), $0
-	BYTE $0x00
-TEXT _reserved0(SB), $0
-	BYTE $0x00
-TEXT _bootsig(SB), $0
-	BYTE $0x00
-TEXT _volid(SB), $0
-	BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
-TEXT _label(SB), $0
-	BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
-	BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00
-	BYTE $0x00; BYTE $0x00; BYTE $0x00
-TEXT _type(SB), $0
-	BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
-	BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
-
-_start0x3E:
-	CLI
-	CLR(rAX)
-	MTSR(rAX, rSS)			/* 0000 -> rSS */
-	MTSR(rAX, rDS)			/* 0000 -> rDS, source segment */
-	MTSR(rAX, rES)
-	LWI(_magic-Xtotal(SB), rSP)
-	MW(rSP, rBP)			/* set the indexed-data pointer */
-
-	SBPB(rDL, Xdrive)		/* save the boot drive */
-
-	STI
-
-	LWI(confidence(SB), rSI)	/* for that warm, fuzzy feeling */
-	CALL(BIOSputs(SB))
-
-	LBI(0x41, rAH)			/* check extensions present */
-	LWI(0x55AA, rBX)
-	LXB(Xdrive, xBP, rDL)		/* drive */
-	SYSCALL(0x13)			/* CF set on failure */
-	JCS _jmp01
-	CMPI(0xAA55, rBX)
-	JNE _jmp01
-	ANDI(0x0001, rCX)
-	JEQ _jmp01
-
-					/* rCX contains 0x0001 */
-	SBPWI(0x0010, Xdap+0)		/* reserved + packet size */
-	SBPW(rCX, Xdap+2)		/* reserved + # of blocks to transfer */
-
-	DEC(rCX)
-	SBPW(rCX, Xdap+12)
-	SBPW(rCX, Xdap+14)
-
-/* BIOSread will do this 	CALL(dreset(SB)) */
-
-_jmp00:
-	LW(_volid(SB), rAX)		/* Xrootlo */
-	LW(_volid+2(SB), rDX)		/* Xroothi */
-
-	LWI(_magic+DIROFF(SB), rBX)
-	CALL(BIOSread(SB))		/* read the root directory */
-
-	CALL(printnl(SB))
-	LWI(_magic+DIROFF(SB), rBX)
-	LWI((512/2), rCX)
-	CALL(printbuf(SB))
-
-xloop:
-	JMP xloop
-
-
-_jmp01:
-
-TEXT buggery(SB), $0
-	LWI(error(SB), rSI)
-	CALL(BIOSputs(SB))
-
-xbuggery:
-	JMP xbuggery
-
-/*
- * Read a sector from a disc. On entry:
- *   rDX:rAX	sector number
- *   rES:rBX	buffer address
- */
-TEXT BIOSread(SB), $0
-	LWI(5, rDI)			/* retry count (ATAPI ZIPs suck) */
-_retry:
-	PUSHA				/* may be trashed by SYSCALL */
-
-	SBPW(rBX, Xdap+4)		/* transfer buffer :offset */
-	MFSR(rES, rDI)			/* transfer buffer seg: */
-	SBPW(rDI, Xdap+6)
-	SBPW(rAX, Xdap+8)		/* LBA (64-bits) */
-	SBPW(rDX, Xdap+10)
-
-	MW(rBP, rSI)			/* disk address packet */
-	LBI(0x42, rAH)			/* extended read */
-	LBPB(Xdrive, rDL)		/* form drive */
-	SYSCALL(0x13)			/* CF set on failure */
-	JCC _BIOSreadret
-
-	POPA
-	DEC(rDI)			/* too many retries? */
-	JEQ _ioerror
-
-	CALL(dreset(SB))
-	JMP _retry
-
-_ioerror:
-	LWI(ioerror(SB), rSI)
-	CALL(BIOSputs(SB))
-	JMP xbuggery
-
-_BIOSreadret:
-	POPA
-	RET
-
-TEXT dreset(SB), $0
-	PUSHA
-	CLR(rAX)			/* rAH == 0 == reset disc system */
-	LBPB(Xdrive, rDL)
-	SYSCALL(0x13)
-	ORB(rAH, rAH)			/* status (0 == success) */
-	POPA
-	JNE _ioerror
-	RET
-
-
-TEXT printsharp(SB), $0
-	LWI(sharp(SB), rSI)
-_doprint:
-	CALL(BIOSputs(SB))
-	RET
-
-TEXT printspace(SB), $0
-	LWI(space(SB), rSI)
-	JMP _doprint
-
-TEXT printnl(SB), $0
-	LWI(nl(SB), rSI)
-	JMP _doprint
-
-/*
- * Output a string to the display.
- * String argument is in rSI.
- */
-TEXT BIOSputs(SB), $0
-	PUSHA
-	CLR(rBX)
-_BIOSputs:
-	LODSB
-	ORB(rAL, rAL)
-	JEQ _BIOSputsret
-
-	LBI(0x0E, rAH)
-	SYSCALL(0x10)
-	JMP _BIOSputs
-
-_BIOSputsret:
-	POPA
-	RET
-
-/*
- * Output a register to the display.
- */
-TEXT printAX(SB), $0
-	PUSHW(rAX)
-	PUSHW(rBX)
-	PUSHW(rCX)
-	PUSHW(rDI)
-
-	LWI(4, rCX)
-	LWI(numbuf+4(SB), rSI)
-
-_nextchar:
-	DEC(rSI)
-	MW(rAX, rBX)
-	ANDI(0x000F, rBX)
-	ADDI(0x30, rBX)	/* 0x30 = '0' */
-	CMPI(0x39, rBX)	/* 0x39 = '9' */
-	JLE _dowrite
-	ADDI(0x07, rBX)	/* 0x07 = 'A'-(1+'9')*/
-
-_dowrite:
-	SXB(rBL, 0, xSI)
-	SHRI(4, rAX)
-
-	DEC(rCX)
-	JNE _nextchar
-
-	LWI(numbuf(SB), rSI)
-	CALL(BIOSputs(SB))
-
-	POPW(rDI)
-	POPW(rCX)
-	POPW(rBX)
-	POPW(rAX)
-
-	CALL(printspace(SB))
-	RET
-
-TEXT printDXAX(SB), $0
-	PUSHW(rAX)
-	MW(rDX, rAX)
-	CALL(printAX(SB))
-	POPW(rAX)
-	CALL(printAX(SB))
-	RET
-
-TEXT printBX(SB), $0
-	PUSHW(rAX)
-	MW(rBX, rAX)
-	CALL(printAX(SB))
-	POPW(rAX)
-	RET
-
-/*
- * Output some number of words to the display
- * rDS:rDI - buffer
- * rCX: number of words
- */
-TEXT printbuf(SB), $0
-	PUSHW(rAX)
-	PUSHW(rBX)
-	PUSHW(rCX)
-
-_nextword:
-	LXW(0, xBX, rAX)
-	CALL(printAX(SB))
-	INC(rBX)
-	INC(rBX)
-	DEC(rCX)
-	JNE _nextword
-
-	POPW(rCX)
-	POPW(rBX)
-	POPW(rAX)
-	RET
-
-TEXT error(SB), $0
-	BYTE $'E'; 
-
-TEXT ioerror(SB), $0
-	BYTE $'I'; 
-
-TEXT nl(SB), $0
-	BYTE $'\r';
-	BYTE $'\n';
-	BYTE $'\z';
-
-TEXT numbuf(SB), $0
-	BYTE $'X'; BYTE $'X'; BYTE $'X'; BYTE $'X';
-	BYTE $'\z';
-
-TEXT space(SB), $0
-	BYTE $' ';
-	BYTE $'\z';
-
-TEXT sharp(SB), $0
-	BYTE $'#'; BYTE $'\z';
--- a/os/boot/pc/pbslba.s
+++ /dev/null
@@ -1,363 +1,0 @@
-/*
- * FAT Partition Boot Sector. Loaded at 0x7C00:
- *	8a pbslba.s; 8l -o pbslba -l -H3 -T0x7C00 pbslba.8
- * Will load the target at LOADSEG*16+LOADOFF, so the target
- * should be probably be loaded with LOADOFF added to the
- * -Taddress.
- * If LOADSEG is a multiple of 64KB and LOADOFF is 0 then
- * targets larger than 64KB can be loaded.
- *
- * This code is uses Enhanced BIOS Services for Disc Drives and
- * can be used with discs up to 137GB in capacity.
- *
- * It relies on the _volid field in the FAT header containing
- * the LBA of the root directory.
- */
-#include "x16.h"
-#include "mem.h"
-
-#define LOADSEG		(0x10000/16)	/* where to load code (64KB) */
-#define LOADOFF		0
-#define DIROFF		0x0200		/* where to read the root directory */
-
-/*
- * FAT directory entry.
- */
-#define Dname		0x00
-#define Dnamesz	0x0B
-#define Dext		0x08
-#define Dattr		0x0B
-#define Dtime		0x16
-#define Ddate		0x18
-#define Dstart		0x1A
-#define Dlengthlo	0x1C
-#define Dlengthhi	0x1E
-
-#define Dirsz		0x20
-
-/*
- * Data is kept on the stack, indexed by rBP.
- */
-#define Xdap		0x00		/* disc address packet */
-#define Xrootsz		0x10		/* file data area */
-#define Xdrive		0x12		/* boot drive, passed by BIOS or MBR */
-#define Xtotal		0x14		/* sum of allocated data above */
-
-TEXT _magic(SB), $0
-	BYTE $0xEB; BYTE $0x3C;		/* jmp .+ 0x3C  (_start0x3E) */
-	BYTE $0x90			/* nop */
-TEXT _version(SB), $0
-	BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
-	BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00
-TEXT _sectsize(SB), $0
-	BYTE $0x00; BYTE $0x00
-TEXT _clustsize(SB), $0
-	BYTE $0x00
-TEXT _nresrv(SB), $0
-	BYTE $0x00; BYTE $0x00
-TEXT _nfats(SB), $0
-	BYTE $0x00
-TEXT _rootsize(SB), $0
-	BYTE $0x00; BYTE $0x00
-TEXT _volsize(SB), $0
-	BYTE $0x00; BYTE $0x00
-TEXT _mediadesc(SB), $0
-	BYTE $0x00
-TEXT _fatsize(SB), $0
-	BYTE $0x00; BYTE $0x00
-TEXT _trksize(SB), $0
-	BYTE $0x00; BYTE $0x00
-TEXT _nheads(SB), $0
-	BYTE $0x00; BYTE $0x00
-TEXT _nhiddenlo(SB), $0
-	BYTE $0x00; BYTE $0x00
-TEXT _nhiddenhi(SB), $0
-	BYTE $0x00; BYTE $0x00;
-TEXT _bigvolsize(SB), $0
-	BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
-TEXT _driveno(SB), $0
-	BYTE $0x00
-TEXT _reserved0(SB), $0
-	BYTE $0x00
-TEXT _bootsig(SB), $0
-	BYTE $0x00
-TEXT _volid(SB), $0
-	BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
-TEXT _label(SB), $0
-	BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
-	BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00
-	BYTE $0x00; BYTE $0x00; BYTE $0x00
-TEXT _type(SB), $0
-	BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
-	BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
-
-_start0x3E:
-	CLI
-	CLR(rAX)
-	MTSR(rAX, rSS)			/* 0000 -> rSS */
-	MTSR(rAX, rDS)			/* 0000 -> rDS, source segment */
-	MTSR(rAX, rES)
-	LWI(_magic-Xtotal(SB), rSP)
-	MW(rSP, rBP)			/* set the indexed-data pointer */
-
-	SBPB(rDL, Xdrive)		/* save the boot drive */
-
-	/* booting from a CD starts us at 7C0:0.  Move to 0:7C00 */
-	PUSHR(rAX)
-	LWI(_nxt(SB), rAX)
-	PUSHR(rAX)
-	BYTE $0xCB	/* FAR RET */
-
-TEXT _nxt(SB), $0
-	STI
-
-	LWI(confidence(SB), rSI)	/* for that warm, fuzzy feeling */
-	CALL16(BIOSputs(SB))
-
-	LBI(0x41, rAH)			/* check extensions present */
-	LWI(0x55AA, rBX)
-	LXB(Xdrive, xBP, rDL)		/* drive */
-	BIOSCALL(0x13)			/* CF set on failure */
-	JCS _jmp01
-	CMPI(0xAA55, rBX)
-	JNE _jmp01
-	ANDI(0x0001, rCX)
-	JEQ _jmp01
-
-					/* rCX contains 0x0001 */
-	SBPWI(0x0010, Xdap+0)		/* reserved + packet size */
-	SBPW(rCX, Xdap+2)		/* reserved + # of blocks to transfer */
-
-	DEC(rCX)
-	SBPW(rCX, Xdap+12)
-	SBPW(rCX, Xdap+14)
-
-	CALL16(dreset(SB))
-
-_jmp00:
-	LW(_volid(SB), rAX)		/* Xrootlo */
-	LW(_volid+2(SB), rDX)		/* Xroothi */
-
-	LWI(_magic+DIROFF(SB), rBX)
-	CALL16(BIOSread(SB))		/* read the root directory */
-
-	LWI((512/Dirsz), rBX)
-
-	LWI(_magic+DIROFF(SB), rDI)	/* compare first directory entry */
-
-_cmp00:
-	PUSHR(rDI)			/* save for later if it matches */
-	LWI(bootfile(SB), rSI)
-	LWI(Dnamesz, rCX)
-	REP
-	CMPSB
-	POPR(rDI)
-	JEQ _jmp02
-
-	DEC(rBX)
-	JEQ _jmp01
-
-	ADDI(Dirsz, rDI)
-	JMP _cmp00
-_jmp01:
-	CALL16(buggery(SB))
-
-_jmp02:
-	CLR(rBX)			/* a handy value */
-	LW(_rootsize(SB), rAX)		/* calculate and save Xrootsz */
-	LWI(Dirsz, rCX)
-	MUL(rCX)
-	LW(_sectsize(SB), rCX)
-	PUSHR(rCX)
-	DEC(rCX)
-	ADD(rCX, rAX)
-	ADC(rBX, rDX)
-	POPR(rCX)			/* _sectsize(SB) */
-	DIV(rCX)
-	PUSHR(rAX)			/* Xrootsz */
-
-	/*
-	 * rDI points to the matching directory entry.
-	 */
-	LXW(Dstart, xDI, rAX)		/* starting sector address */
-	DEC(rAX)			/* that's just the way it is */
-	DEC(rAX)
-	LB(_clustsize(SB), rCL)
-	CLRB(rCH)
-	MUL(rCX)
-	LW(_volid(SB), rCX)		/* Xrootlo */
-	ADD(rCX, rAX)
-	LW(_volid+2(SB), rCX)		/* Xroothi */
-	ADC(rCX, rDX)
-	POPR(rCX)			/* Xrootsz */
-	ADD(rCX, rAX)
-	ADC(rBX, rDX)
-
-	PUSHR(rAX)			/* calculate how many sectors to read */
-	PUSHR(rDX)
-	LXW(Dlengthlo, xDI, rAX)
-	LXW(Dlengthhi, xDI, rDX)
-	LW(_sectsize(SB), rCX)
-	PUSHR(rCX)
-	DEC(rCX)
-	ADD(rCX, rAX)
-	ADC(rBX, rDX)
-	POPR(rCX)			/* _sectsize(SB) */
-	DIV(rCX)
-	MW(rAX, rCX)
-	POPR(rDX)
-	POPR(rAX)
-
-	LWI(LOADSEG, rBX)		/* address to load into (seg+offset) */
-	MTSR(rBX, rES)			/*  seg */
-	LWI(LOADOFF, rBX)		/*  offset */
-
-_readboot:
-	CALL16(BIOSread(SB))		/* read the sector */
-
-	LW(_sectsize(SB), rDI)		/* bump addresses/counts */
-	ADD(rDI, rBX)
-	JCC _incsecno
-
-	MFSR(rES, rDI)			/* next 64KB segment */
-	ADDI(0x1000, rDI)
-	MTSR(rDI, rES)
-
-_incsecno:
-	CLR(rDI)
-	INC(rAX)
-	ADC(rDI, rDX)
-	LOOP _readboot
-
-	LWI(LOADSEG, rDI)		/* set rDS for loaded code */
-	MTSR(rDI, rDS)
-	FARJUMP16(LOADSEG, LOADOFF)	/* no deposit, no return */
-
-TEXT buggery(SB), $0
-	LWI(error(SB), rSI)
-	CALL16(BIOSputs(SB))
-
-_wait:
-	CLR(rAX)			/* wait for almost any key */
-	BIOSCALL(0x16)
-
-_reset:
-	CLR(rBX)			/* set ES segment for BIOS area */
-	MTSR(rBX, rES)
-
-	LWI(0x0472, rBX)		/* warm-start code address */
-	LWI(0x1234, rAX)		/* warm-start code */
-	POKEW				/* MOVW	AX, ES:[BX] */
-
-	FARJUMP16(0xFFFF, 0x0000)	/* reset */
-
-
-/*
- * Read a sector from a disc. On entry:
- *   rDX:rAX	sector number
- *   rES:rBX	buffer address
- */
-TEXT BIOSread(SB), $0
-	LWI(5, rDI)			/* retry count (ATAPI ZIPs suck) */
-_retry:
-	PUSHA				/* may be trashed by BIOSCALL */
-
-	SBPW(rBX, Xdap+4)		/* transfer buffer :offset */
-	MFSR(rES, rDI)			/* transfer buffer seg: */
-	SBPW(rDI, Xdap+6)
-	SBPW(rAX, Xdap+8)		/* LBA (64-bits) */
-	SBPW(rDX, Xdap+10)
-
-	MW(rBP, rSI)			/* disk address packet */
-	LBI(0x42, rAH)			/* extended read */
-	LBPB(Xdrive, rDL)		/* form drive */
-	BIOSCALL(0x13)			/* CF set on failure */
-	JCC _BIOSreadret
-
-	POPA
-	DEC(rDI)			/* too many retries? */
-	JEQ _ioerror
-
-	CALL16(dreset(SB))
-	JMP _retry
-
-_ioerror:
-	LWI(ioerror(SB), rSI)
-	CALL16(BIOSputs(SB))
-	JMP _wait
-
-_BIOSreadret:
-	POPA
-	RET
-
-TEXT dreset(SB), $0
-	PUSHA
-	CLR(rAX)			/* rAH == 0 == reset disc system */
-	LBPB(Xdrive, rDL)
-	BIOSCALL(0x13)
-	ORB(rAH, rAH)			/* status (0 == success) */
-	POPA
-	JNE _ioerror
-	RET
-
-/*
- * Output a string to the display.
- * String argument is in rSI.
- */
-TEXT BIOSputs(SB), $0
-	PUSHA
-	CLR(rBX)
-_BIOSputs:
-	LODSB
-	ORB(rAL, rAL)
-	JEQ _BIOSputsret
-
-	LBI(0x0E, rAH)
-	BIOSCALL(0x10)
-	JMP _BIOSputs
-
-_BIOSputsret:
-	POPA
-	RET
-
-/* "Bad format or I/O error\r\nPress almost any key to reboot..." */
-TEXT error(SB), $0
-	BYTE $'B'; BYTE $'a'; BYTE $'d'; BYTE $' ';
-	BYTE $'f'; BYTE $'o'; BYTE $'r'; BYTE $'m';
-	BYTE $'a'; BYTE $'t'; BYTE $' '; BYTE $'o';
-	BYTE $'r'; BYTE $' ';
-/* "I/O error\r\nPress almost any key to reboot..." */
-TEXT ioerror(SB), $0
-	BYTE $'I'; BYTE $'/'; BYTE $'O'; BYTE $' ';
-	BYTE $'e'; BYTE $'r'; BYTE $'r'; BYTE $'o';
-	BYTE $'r'; BYTE $'\r';BYTE $'\n';
-	BYTE $'P'; BYTE $'r'; BYTE $'e'; BYTE $'s';
-	BYTE $'s'; BYTE $' '; BYTE $'a'; BYTE $' ';
-	BYTE $'k'; BYTE $'e'; BYTE $'y';
-	BYTE $' '; BYTE $'t'; BYTE $'o'; BYTE $' ';
-	BYTE $'r'; BYTE $'e'; BYTE $'b'; BYTE $'o';
-	BYTE $'o'; BYTE $'t';
-	BYTE $'.'; BYTE $'.'; BYTE $'.';
-	BYTE $'\z';
-
-#ifdef USEBCOM
-/* "B       COM" */
-TEXT bootfile(SB), $0
-	BYTE $'B'; BYTE $' '; BYTE $' '; BYTE $' ';
-	BYTE $' '; BYTE $' '; BYTE $' '; BYTE $' ';
-	BYTE $'C'; BYTE $'O'; BYTE $'M';
-	BYTE $'\z';
-#else
-/* "9LOAD      " */
-TEXT bootfile(SB), $0
-	BYTE $'9'; BYTE $'L'; BYTE $'O'; BYTE $'A';
-	BYTE $'D'; BYTE $' '; BYTE $' '; BYTE $' ';
-	BYTE $' '; BYTE $' '; BYTE $' ';
-	BYTE $'\z';
-#endif /* USEBCOM */
-
-/* "PBS..." */
-TEXT confidence(SB), $0
-	BYTE $'P'; BYTE $'B'; BYTE $'S'; BYTE $'2';
-	BYTE $'.'; BYTE $'.'; BYTE $'.';
-	BYTE $'\z';
--- a/os/boot/pc/pci.c
+++ /dev/null
@@ -1,1002 +1,0 @@
-/*
- * PCI support code.
- * To do:
- *	initialise bridge mappings if the PCI BIOS didn't.
- */
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-#include "error.h"
-
-enum {					/* configuration mechanism #1 */
-	PciADDR		= 0xCF8,	/* CONFIG_ADDRESS */
-	PciDATA		= 0xCFC,	/* CONFIG_DATA */
-
-					/* configuration mechanism #2 */
-	PciCSE		= 0xCF8,	/* configuration space enable */
-	PciFORWARD	= 0xCFA,	/* which bus */
-
-	MaxFNO		= 7,
-	MaxUBN		= 255,
-};
-
-enum
-{					/* command register */
-	IOen		= (1<<0),
-	MEMen		= (1<<1),
-	MASen		= (1<<2),
-	MemWrInv	= (1<<4),
-	PErrEn		= (1<<6),
-	SErrEn		= (1<<8),
-};
-
-static Lock pcicfglock;
-static Lock pcicfginitlock;
-static int pcicfgmode = -1;
-static int pcimaxbno = 7;
-static int pcimaxdno;
-static Pcidev* pciroot;
-static Pcidev* pcilist;
-static Pcidev* pcitail;
-
-static int pcicfgrw32(int, int, int, int);
-static int pcicfgrw8(int, int, int, int);
-
-ulong
-pcibarsize(Pcidev *p, int rno)
-{
-	ulong v, size;
-
-	v = pcicfgrw32(p->tbdf, rno, 0, 1);
-	pcicfgrw32(p->tbdf, rno, 0xFFFFFFF0, 0);
-	size = pcicfgrw32(p->tbdf, rno, 0, 1);
-	if(v & 1)
-		size |= 0xFFFF0000;
-	pcicfgrw32(p->tbdf, rno, v, 0);
-
-	return -(size & ~0x0F);
-}
-
-int
-pciscan(int bno, Pcidev** list)
-{
-	Pcidev *p, *head, *tail;
-	int dno, fno, i, hdt, l, maxfno, maxubn, rno, sbn, tbdf, ubn;
-
-	maxubn = bno;
-	head = nil;
-	tail = nil;
-	for(dno = 0; dno <= pcimaxdno; dno++){
-		maxfno = 0;
-		for(fno = 0; fno <= maxfno; fno++){
-			/*
-			 * For this possible device, form the
-			 * bus+device+function triplet needed to address it
-			 * and try to read the vendor and device ID.
-			 * If successful, allocate a device struct and
-			 * start to fill it in with some useful information
-			 * from the device's configuration space.
-			 */
-			tbdf = MKBUS(BusPCI, bno, dno, fno);
-			l = pcicfgrw32(tbdf, PciVID, 0, 1);
-			if(l == 0xFFFFFFFF || l == 0)
-				continue;
-			p = malloc(sizeof(*p));
-			p->tbdf = tbdf;
-			p->vid = l;
-			p->did = l>>16;
-
-			if(pcilist != nil)
-				pcitail->list = p;
-			else
-				pcilist = p;
-			pcitail = p;
-
-			p->rid = pcicfgr8(p, PciRID);
-			p->ccrp = pcicfgr8(p, PciCCRp);
-			p->ccru = pcicfgr8(p, PciCCRu);
-			p->ccrb = pcicfgr8(p, PciCCRb);
-			p->pcr = pcicfgr32(p, PciPCR);
-
-			p->intl = pcicfgr8(p, PciINTL);
-
-			/*
-			 * If the device is a multi-function device adjust the
-			 * loop count so all possible functions are checked.
-			 */
-			hdt = pcicfgr8(p, PciHDT);
-			if(hdt & 0x80)
-				maxfno = MaxFNO;
-
-			/*
-			 * If appropriate, read the base address registers
-			 * and work out the sizes.
-			 */
-			switch(p->ccrb){
-
-			case 0x01:		/* mass storage controller */
-			case 0x02:		/* network controller */
-			case 0x03:		/* display controller */
-			case 0x04:		/* multimedia device */
-			case 0x07:		/* simple comm. controllers */
-			case 0x08:		/* base system peripherals */
-			case 0x09:		/* input devices */
-			case 0x0A:		/* docking stations */
-			case 0x0B:		/* processors */
-			case 0x0C:		/* serial bus controllers */
-				if((hdt & 0x7F) != 0)
-					break;
-				rno = PciBAR0 - 4;
-				for(i = 0; i < nelem(p->mem); i++){
-					rno += 4;
-					p->mem[i].bar = pcicfgr32(p, rno);
-					p->mem[i].size = pcibarsize(p, rno);
-				}
-				break;
-
-			case 0x00:
-			case 0x05:		/* memory controller */
-			case 0x06:		/* bridge device */
-			default:
-				break;
-			}
-
-			if(head != nil)
-				tail->link = p;
-			else
-				head = p;
-			tail = p;
-		}
-	}
-
-	*list = head;
-	for(p = head; p != nil; p = p->link){
-		/*
-		 * Find PCI-PCI and PCI-Cardbus bridges
-		 * and recursively descend the tree.
-		 */
-		if(p->ccrb != 0x06 || p->ccru != 0x04)
-			continue;
-
-		/*
-		 * If the secondary or subordinate bus number is not
-		 * initialised try to do what the PCI BIOS should have
-		 * done and fill in the numbers as the tree is descended.
-		 * On the way down the subordinate bus number is set to
-		 * the maximum as it's not known how many buses are behind
-		 * this one; the final value is set on the way back up.
-		 */
-		ubn = pcicfgr8(p, PciUBN);
-		sbn = pcicfgr8(p, PciSBN);
-
-		if(sbn == 0 || ubn == 0){
-			sbn = maxubn+1;
-			/*
-			 * Make sure memory, I/O and master enables are
-			 * off, set the primary, secondary and subordinate
-			 * bus numbers and clear the secondary status before
-			 * attempting to scan the secondary bus.
-			 *
-			 * Initialisation of the bridge should be done here.
-			 */
-			pcicfgw32(p, PciPCR, 0xFFFF0000);
-			l = (MaxUBN<<16)|(sbn<<8)|bno;
-			pcicfgw32(p, PciPBN, l);
-			pcicfgw16(p, PciSPSR, 0xFFFF);
-			maxubn = pciscan(sbn, &p->bridge);
-			l = (maxubn<<16)|(sbn<<8)|bno;
-
-			pcicfgw32(p, PciPBN, l);
-		}
-		else{
-			/*
-			 * You can't go back.
-			 * This shouldn't be possible, but the
-			 * Iwill DK8-HTX seems to have subordinate
-			 * bus numbers which get smaller on the
-			 * way down. Need to look more closely at
-			 * this.
-			 */
-			if(ubn > maxubn)
-				maxubn = ubn;
-			pciscan(sbn, &p->bridge);
-		}
-	}
-
-	return maxubn;
-}
-
-static uchar
-null_link(Pcidev *, uchar )
-{
-	return 0;
-}
-
-static void
-null_init(Pcidev *, uchar , uchar )
-{
-}
-
-static uchar
-pIIx_link(Pcidev *router, uchar link)
-{
-	uchar pirq;
-
-	/* link should be 0x60, 0x61, 0x62, 0x63 */
-	pirq = pcicfgr8(router, link);
-	return (pirq < 16)? pirq: 0;
-}
-
-static void
-pIIx_init(Pcidev *router, uchar link, uchar irq)
-{
-	pcicfgw8(router, link, irq);
-}
-
-static uchar
-via_link(Pcidev *router, uchar link)
-{
-	uchar pirq;
-
-	/* link should be 1, 2, 3, 5 */
-	pirq = (link < 6)? pcicfgr8(router, 0x55 + (link>>1)): 0;
-
-	return (link & 1)? (pirq >> 4): (pirq & 15);
-}
-
-static void
-via_init(Pcidev *router, uchar link, uchar irq)
-{
-	uchar pirq;
-
-	pirq = pcicfgr8(router, 0x55 + (link >> 1));
-	pirq &= (link & 1)? 0x0f: 0xf0;
-	pirq |= (link & 1)? (irq << 4): (irq & 15);
-	pcicfgw8(router, 0x55 + (link>>1), pirq);
-}
-
-static uchar
-opti_link(Pcidev *router, uchar link)
-{
-	uchar pirq = 0;
-
-	/* link should be 0x02, 0x12, 0x22, 0x32 */
-	if ((link & 0xcf) == 0x02)
-		pirq = pcicfgr8(router, 0xb8 + (link >> 5));
-	return (link & 0x10)? (pirq >> 4): (pirq & 15);
-}
-
-static void
-opti_init(Pcidev *router, uchar link, uchar irq)
-{
-	uchar pirq;
-
-	pirq = pcicfgr8(router, 0xb8 + (link >> 5));
-    	pirq &= (link & 0x10)? 0x0f : 0xf0;
-    	pirq |= (link & 0x10)? (irq << 4): (irq & 15);
-	pcicfgw8(router, 0xb8 + (link >> 5), pirq);
-}
-
-static uchar
-ali_link(Pcidev *router, uchar link)
-{
-	/* No, you're not dreaming */
-	static const uchar map[] = { 0, 9, 3, 10, 4, 5, 7, 6, 1, 11, 0, 12, 0, 14, 0, 15 };
-	uchar pirq;
-
-	/* link should be 0x01..0x08 */
-	pirq = pcicfgr8(router, 0x48 + ((link-1)>>1));
-	return (link & 1)? map[pirq&15]: map[pirq>>4];
-}
-
-static void
-ali_init(Pcidev *router, uchar link, uchar irq)
-{
-	/* Inverse of map in ali_link */
-	static const uchar map[] = { 0, 8, 0, 2, 4, 5, 7, 6, 0, 1, 3, 9, 11, 0, 13, 15 };
-	uchar pirq;
-
-	pirq = pcicfgr8(router, 0x48 + ((link-1)>>1));
-	pirq &= (link & 1)? 0x0f: 0xf0;
-	pirq |= (link & 1)? (map[irq] << 4): (map[irq] & 15);
-	pcicfgw8(router, 0x48 + ((link-1)>>1), pirq);
-}
-
-static uchar
-cyrix_link(Pcidev *router, uchar link)
-{
-	uchar pirq;
-
-	/* link should be 1, 2, 3, 4 */
-	pirq = pcicfgr8(router, 0x5c + ((link-1)>>1));
-	return ((link & 1)? pirq >> 4: pirq & 15);
-}
-
-static void
-cyrix_init(Pcidev *router, uchar link, uchar irq)
-{
-	uchar pirq;
-
-	pirq = pcicfgr8(router, 0x5c + (link>>1));
-	pirq &= (link & 1)? 0x0f: 0xf0;
-	pirq |= (link & 1)? (irq << 4): (irq & 15);
-	pcicfgw8(router, 0x5c + (link>>1), pirq);
-}
-
-typedef struct {
-	ushort	sb_vid, sb_did;
-	uchar	(*sb_translate)(Pcidev *, uchar);
-	void	(*sb_initialize)(Pcidev *, uchar, uchar);
-} bridge_t;
-
-static bridge_t southbridges[] = {
-	{ 0x8086, 0x122e, pIIx_link, pIIx_init },	// Intel 82371FB
-	{ 0x8086, 0x1234, pIIx_link, pIIx_init },	// Intel 82371MX
-	{ 0x8086, 0x7000, pIIx_link, pIIx_init },	// Intel 82371SB
-	{ 0x8086, 0x7110, pIIx_link, pIIx_init },	// Intel 82371AB
-	{ 0x8086, 0x7198, pIIx_link, pIIx_init },	// Intel 82443MX (fn 1)
-	{ 0x8086, 0x2410, pIIx_link, pIIx_init },	// Intel 82801AA
-	{ 0x8086, 0x2420, pIIx_link, pIIx_init },	// Intel 82801AB
-	{ 0x8086, 0x2440, pIIx_link, pIIx_init },	// Intel 82801BA
-	{ 0x8086, 0x244c, pIIx_link, pIIx_init },	// Intel 82801BAM
-	{ 0x8086, 0x2480, pIIx_link, pIIx_init },	// Intel 82801CA
-	{ 0x8086, 0x248c, pIIx_link, pIIx_init },	// Intel 82801CAM
-	{ 0x8086, 0x24c0, pIIx_link, pIIx_init },	// Intel 82801DBL
-	{ 0x8086, 0x24cc, pIIx_link, pIIx_init },	// Intel 82801DBM
-	{ 0x8086, 0x24d0, pIIx_link, pIIx_init },	// Intel 82801EB
-	{ 0x8086, 0x2640, pIIx_link, pIIx_init },	// Intel 82801FB
-	{ 0x8086, 0x27b8, pIIx_link, pIIx_init },	// Intel 82801GB
-	{ 0x8086, 0x27b9, pIIx_link, pIIx_init },	// Intel 82801GBM
-	{ 0x1106, 0x0586, via_link, via_init },		// Viatech 82C586
-	{ 0x1106, 0x0596, via_link, via_init },		// Viatech 82C596
-	{ 0x1106, 0x0686, via_link, via_init },		// Viatech 82C686
-	{ 0x1106, 0x3227, via_link, via_init },		// Viatech VT8237
-	{ 0x1045, 0xc700, opti_link, opti_init },	// Opti 82C700
-	{ 0x10b9, 0x1533, ali_link, ali_init },		// Al M1533
-	{ 0x1039, 0x0008, pIIx_link, pIIx_init },	// SI 503
-	{ 0x1039, 0x0496, pIIx_link, pIIx_init },	// SI 496
-	{ 0x1078, 0x0100, cyrix_link, cyrix_init },	// Cyrix 5530 Legacy
-
-	{ 0x1002, 0x4377, nil, nil },		// ATI Radeon Xpress 200M
-	{ 0x1002, 0x4372, nil, nil },		// ATI SB400
-	{ 0x1022, 0x746B, nil, nil },		// AMD 8111
-	{ 0x10DE, 0x00D1, nil, nil },		// NVIDIA nForce 3
-	{ 0x10DE, 0x00E0, nil, nil },		// NVIDIA nForce 3 250 Series
-	{ 0x1166, 0x0200, nil, nil },		// ServerWorks ServerSet III LE
-};
-
-typedef struct {
-	uchar	e_bus;			// Pci bus number
-	uchar	e_dev;			// Pci device number
-	uchar	e_maps[12];		// Avoid structs!  Link and mask.
-	uchar	e_slot;			// Add-in/built-in slot
-	uchar	e_reserved;
-} slot_t;
-
-typedef struct {
-	uchar	rt_signature[4];	// Routing table signature
-	uchar	rt_version[2];		// Version number
-	uchar	rt_size[2];			// Total table size
-	uchar	rt_bus;			// Interrupt router bus number
-	uchar	rt_devfn;			// Router's devfunc
-	uchar	rt_pciirqs[2];		// Exclusive PCI irqs
-	uchar	rt_compat[4];		// Compatible PCI interrupt router
-	uchar	rt_miniport[4];		// Miniport data
-	uchar	rt_reserved[11];
-	uchar	rt_checksum;
-} router_t;
-
-static ushort pciirqs;			// Exclusive PCI irqs
-static bridge_t *southbridge;	// Which southbridge to use.
-
-static void
-pcirouting(void)
-{
-	uchar *p, pin, irq;
-	ulong tbdf, vdid;
-	ushort vid, did;
-	router_t *r;
-	slot_t *e;
-	int size, i, fn;
-	Pcidev *sbpci, *pci;
-
-	// Peek in the BIOS
-	for (p = (uchar *)KADDR(0xf0000); p < (uchar *)KADDR(0xfffff); p += 16)
-		if (p[0] == '$' && p[1] == 'P' && p[2] == 'I' && p[3] == 'R')
-			break;
-
-	if (p >= (uchar *)KADDR(0xfffff))
-		return;
-
-	r = (router_t *)p;
-
-	// print("PCI interrupt routing table version %d.%d at %.6uX\n",
-	// 	r->rt_version[0], r->rt_version[1], (ulong)r & 0xfffff);
-
-	tbdf = (BusPCI << 24)|(r->rt_bus << 16)|(r->rt_devfn << 8);
-	vdid = pcicfgrw32(tbdf, PciVID, 0, 1);
-	vid = vdid;
-	did = vdid >> 16;
-
-	for (i = 0; i != nelem(southbridges); i++)
-		if (vid == southbridges[i].sb_vid && did == southbridges[i].sb_did)
-			break;
-
-	if (i == nelem(southbridges)) {
-		print("pcirouting: South bridge %.4uX, %.4uX not found\n", vid, did);
-		return;
-	}
-	southbridge = &southbridges[i];
-
-	if ((sbpci = pcimatch(nil, vid, did)) == nil) {
-		print("pcirouting: Cannot match south bridge %.4uX, %.4uX\n",
-			  vid, did);
-		return;
-	}
-
-	pciirqs = (r->rt_pciirqs[1] << 8)|r->rt_pciirqs[0];
-
-	size = (r->rt_size[1] << 8)|r->rt_size[0];
-	for (e = (slot_t *)&r[1]; (uchar *)e < p + size; e++) {
-		// print("%.2uX/%.2uX %.2uX: ", e->e_bus, e->e_dev, e->e_slot);
-		// for (i = 0; i != 4; i++) {
-		// 	uchar *m = &e->e_maps[i * 3];
-		// 	print("[%d] %.2uX %.4uX ",
-		// 		i, m[0], (m[2] << 8)|m[1]);
-		// }
-		// print("\n");
-
-		for (fn = 0; fn != 8; fn++) {
-			uchar *m;
-
-			// Retrieve the did and vid through the devfn before
-			// obtaining the Pcidev structure.
-			tbdf = (BusPCI << 24)|(e->e_bus << 16)|((e->e_dev | fn) << 8);
-			vdid = pcicfgrw32(tbdf, PciVID, 0, 1);
-			if (vdid == 0xFFFFFFFF || vdid == 0)
-				continue;
-
-			vid = vdid;
-			did = vdid >> 16;
-
-			pci = nil;
-			while ((pci = pcimatch(pci, vid, did)) != nil) {
-
-				if (pci->intl != 0 && pci->intl != 0xFF)
-					continue;
-
-				pin = pcicfgr8(pci, PciINTP);
-				if (pin == 0 || pin == 0xff)
-					continue;
-
-				m = &e->e_maps[(pin - 1) * 3];
-				irq = southbridge->sb_translate(sbpci, m[0]);
-				if (irq) {
-					print("pcirouting: %.4uX/%.4uX at pin %d irq %d\n",
-						  vid, did, pin, irq);
-					pcicfgw8(pci, PciINTL, irq);
-					pci->intl = irq;
-				}
-			}
-		}
-	}
-}
-
-static void
-pcicfginit(void)
-{
-	char *p;
-	int bno, n;
-	Pcidev **list;
-
-	lock(&pcicfginitlock);
-	if(pcicfgmode != -1)
-		goto out;
-
-	/*
-	 * Try to determine which PCI configuration mode is implemented.
-	 * Mode2 uses a byte at 0xCF8 and another at 0xCFA; Mode1 uses
-	 * a DWORD at 0xCF8 and another at 0xCFC and will pass through
-	 * any non-DWORD accesses as normal I/O cycles. There shouldn't be
-	 * a device behind these addresses so if Mode1 accesses fail try
-	 * for Mode2 (Mode2 is deprecated).
-	 */
-
-	/*
-	 * Bits [30:24] of PciADDR must be 0,
-	 * according to the spec.
-	 */
-	n = inl(PciADDR);
-	if(!(n & 0x7FF00000)){
-		outl(PciADDR, 0x80000000);
-		outb(PciADDR+3, 0);
-		if(inl(PciADDR) & 0x80000000){
-			pcicfgmode = 1;
-			pcimaxdno = 31;
-		}
-	}
-	outl(PciADDR, n);
-
-	if(pcicfgmode < 0){
-		/*
-		 * The 'key' part of PciCSE should be 0.
-		 */
-		n = inb(PciCSE);
-		if(!(n & 0xF0)){
-			outb(PciCSE, 0x0E);
-			if(inb(PciCSE) == 0x0E){
-				pcicfgmode = 2;
-				pcimaxdno = 15;
-			}
-		}
-		outb(PciCSE, n);
-	}
-
-	if(pcicfgmode < 0)
-		goto out;
-
-
-	if(p = getconf("*pcimaxbno"))
-		pcimaxbno = strtoul(p, 0, 0);
-	if(p = getconf("*pcimaxdno"))
-		pcimaxdno = strtoul(p, 0, 0);
-
-	list = &pciroot;
-	for(bno = 0; bno <= pcimaxbno; bno++) {
-		bno = pciscan(bno, list);
-		while(*list)
-			list = &(*list)->link;
-	}
-
-	pcirouting();
-
-out:
-	unlock(&pcicfginitlock);
-
-	if(getconf("*pcihinv"))
-		pcihinv(nil);
-}
-
-
-static int
-pcicfgrw8(int tbdf, int rno, int data, int read)
-{
-	int o, type, x;
-
-	if(pcicfgmode == -1)
-		pcicfginit();
-
-	if(BUSBNO(tbdf))
-		type = 0x01;
-	else
-		type = 0x00;
-	x = -1;
-	if(BUSDNO(tbdf) > pcimaxdno)
-		return x;
-
-	lock(&pcicfglock);
-	switch(pcicfgmode){
-
-	case 1:
-		o = rno & 0x03;
-		rno &= ~0x03;
-		outl(PciADDR, 0x80000000|BUSBDF(tbdf)|rno|type);
-		if(read)
-			x = inb(PciDATA+o);
-		else
-			outb(PciDATA+o, data);
-		outl(PciADDR, 0);
-		break;
-
-	case 2:
-		outb(PciCSE, 0x80|(BUSFNO(tbdf)<<1));
-		outb(PciFORWARD, BUSBNO(tbdf));
-		if(read)
-			x = inb((0xC000|(BUSDNO(tbdf)<<8)) + rno);
-		else
-			outb((0xC000|(BUSDNO(tbdf)<<8)) + rno, data);
-		outb(PciCSE, 0);
-		break;
-	}
-	unlock(&pcicfglock);
-
-	return x;
-}
-
-int
-pcicfgr8(Pcidev* pcidev, int rno)
-{
-	return pcicfgrw8(pcidev->tbdf, rno, 0, 1);
-}
-
-void
-pcicfgw8(Pcidev* pcidev, int rno, int data)
-{
-	pcicfgrw8(pcidev->tbdf, rno, data, 0);
-}
-
-static int
-pcicfgrw16(int tbdf, int rno, int data, int read)
-{
-	int o, type, x;
-
-	if(pcicfgmode == -1)
-		pcicfginit();
-
-	if(BUSBNO(tbdf))
-		type = 0x01;
-	else
-		type = 0x00;
-	x = -1;
-	if(BUSDNO(tbdf) > pcimaxdno)
-		return x;
-
-	lock(&pcicfglock);
-	switch(pcicfgmode){
-
-	case 1:
-		o = rno & 0x02;
-		rno &= ~0x03;
-		outl(PciADDR, 0x80000000|BUSBDF(tbdf)|rno|type);
-		if(read)
-			x = ins(PciDATA+o);
-		else
-			outs(PciDATA+o, data);
-		outl(PciADDR, 0);
-		break;
-
-	case 2:
-		outb(PciCSE, 0x80|(BUSFNO(tbdf)<<1));
-		outb(PciFORWARD, BUSBNO(tbdf));
-		if(read)
-			x = ins((0xC000|(BUSDNO(tbdf)<<8)) + rno);
-		else
-			outs((0xC000|(BUSDNO(tbdf)<<8)) + rno, data);
-		outb(PciCSE, 0);
-		break;
-	}
-	unlock(&pcicfglock);
-
-	return x;
-}
-
-int
-pcicfgr16(Pcidev* pcidev, int rno)
-{
-	return pcicfgrw16(pcidev->tbdf, rno, 0, 1);
-}
-
-void
-pcicfgw16(Pcidev* pcidev, int rno, int data)
-{
-	pcicfgrw16(pcidev->tbdf, rno, data, 0);
-}
-
-static int
-pcicfgrw32(int tbdf, int rno, int data, int read)
-{
-	int type, x;
-
-	if(pcicfgmode == -1)
-		pcicfginit();
-
-	if(BUSBNO(tbdf))
-		type = 0x01;
-	else
-		type = 0x00;
-	x = -1;
-	if(BUSDNO(tbdf) > pcimaxdno)
-		return x;
-
-	lock(&pcicfglock);
-	switch(pcicfgmode){
-
-	case 1:
-		rno &= ~0x03;
-		outl(PciADDR, 0x80000000|BUSBDF(tbdf)|rno|type);
-		if(read)
-			x = inl(PciDATA);
-		else
-			outl(PciDATA, data);
-		outl(PciADDR, 0);
-		break;
-
-	case 2:
-		outb(PciCSE, 0x80|(BUSFNO(tbdf)<<1));
-		outb(PciFORWARD, BUSBNO(tbdf));
-		if(read)
-			x = inl((0xC000|(BUSDNO(tbdf)<<8)) + rno);
-		else
-			outl((0xC000|(BUSDNO(tbdf)<<8)) + rno, data);
-		outb(PciCSE, 0);
-		break;
-	}
-	unlock(&pcicfglock);
-
-	return x;
-}
-
-int
-pcicfgr32(Pcidev* pcidev, int rno)
-{
-	return pcicfgrw32(pcidev->tbdf, rno, 0, 1);
-}
-
-void
-pcicfgw32(Pcidev* pcidev, int rno, int data)
-{
-	pcicfgrw32(pcidev->tbdf, rno, data, 0);
-}
-
-Pcidev*
-pcimatch(Pcidev* prev, int vid, int did)
-{
-	if(pcicfgmode == -1)
-		pcicfginit();
-
-	if(prev == nil)
-		prev = pcilist;
-	else
-		prev = prev->list;
-
-	while(prev != nil) {
-		if((vid == 0 || prev->vid == vid)
-		&& (did == 0 || prev->did == did))
-			break;
-		prev = prev->list;
-	}
-	return prev;
-}
-
-uchar
-pciipin(Pcidev *pci, uchar pin)
-{
-	if (pci == nil)
-		pci = pcilist;
-
-	while (pci) {
-		uchar intl;
-
-		if (pcicfgr8(pci, PciINTP) == pin && pci->intl != 0 && pci->intl != 0xff)
-			return pci->intl;
-
-		if (pci->bridge && (intl = pciipin(pci->bridge, pin)) != 0)
-			return intl;
-
-		pci = pci->list;
-	}
-	return 0;
-}
-
-static ushort
-pciimask(Pcidev *pci)
-{
-	ushort imask;
-
-	imask = 0;
-	while (pci) {
-		if (pcicfgr8(pci, PciINTP) && pci->intl < 16)
-			imask |= 1 << pci->intl;
-
-		if (pci->bridge)
-			imask |= pciimask(pci->bridge);
-
-		pci = pci->list;
-	}
-	return imask;
-}
-
-uchar
-pciintl(Pcidev *pci)
-{
-	ushort imask;
-	int i;
-
-	if (pci == nil)
-		pci = pcilist;
-
-	imask = pciimask(pci) | 1;
-	for (i = 0; i != 16; i++)
-		if ((imask & (1 << i)) == 0)
-			return i;
-	return 0;
-}
-
-void
-pcihinv(Pcidev* p)
-{
-	int i;
-	Pcidev *t;
-
-	if(pcicfgmode == -1)
-		pcicfginit();
-
-	if(p == nil) {
-		p = pciroot;
-		print("bus dev type vid  did intl memory\n");
-	}
-	for(t = p; t != nil; t = t->link) {
-		print("%d  %2d/%d %.2ux %.2ux %.2ux %.4ux %.4ux %3d  ",
-			BUSBNO(t->tbdf), BUSDNO(t->tbdf), BUSFNO(t->tbdf),
-			t->ccrb, t->ccru, t->ccrp, t->vid, t->did, t->intl);
-
-		for(i = 0; i < nelem(p->mem); i++) {
-			if(t->mem[i].size == 0)
-				continue;
-			print("%d:%.8lux %d ", i,
-				t->mem[i].bar, t->mem[i].size);
-		}
-		print("\n");
-	}
-	while(p != nil) {
-		if(p->bridge != nil)
-			pcihinv(p->bridge);
-		p = p->link;
-	}
-}
-
-void
-pcireset(void)
-{
-	Pcidev *p;
-	int pcr;
-
-	if(pcicfgmode == -1)
-		pcicfginit();
-
-	for(p = pcilist; p != nil; p = p->list){
-		pcr = pcicfgr16(p, PciPSR);
-		pcicfgw16(p, PciPSR, pcr & ~0x04);
-	}
-}
-
-void
-pcisetioe(Pcidev* p)
-{
-	p->pcr |= IOen;
-	pcicfgw16(p, PciPCR, p->pcr);
-}
-
-void
-pciclrioe(Pcidev* p)
-{
-	p->pcr &= ~IOen;
-	pcicfgw16(p, PciPCR, p->pcr);
-}
-
-void
-pcisetbme(Pcidev* p)
-{
-	p->pcr |= MASen;
-	pcicfgw16(p, PciPCR, p->pcr);
-}
-
-void
-pciclrbme(Pcidev* p)
-{
-	p->pcr &= ~MASen;
-	pcicfgw16(p, PciPCR, p->pcr);
-}
-
-void
-pcisetmwi(Pcidev* p)
-{
-	p->pcr |= MemWrInv;
-	pcicfgw16(p, PciPCR, p->pcr);
-}
-
-void
-pciclrmwi(Pcidev* p)
-{
-	p->pcr &= ~MemWrInv;
-	pcicfgw16(p, PciPCR, p->pcr);
-}
-
-static int
-pcigetpmrb(Pcidev* p)
-{
-	int ptr;
-
-	if(p->pmrb != 0)
-		return p->pmrb;
-	p->pmrb = -1;
-
-	/*
-	 * If there are no extended capabilities implemented,
-	 * (bit 4 in the status register) assume there's no standard
-	 * power management method.
-	 * Find the capabilities pointer based on PCI header type.
-	 */
-	if(!(pcicfgr16(p, PciPSR) & 0x0010))
-		return -1;
-	switch(pcicfgr8(p, PciHDT)){
-	default:
-		return -1;
-	case 0:					/* all other */
-	case 1:					/* PCI to PCI bridge */
-		ptr = 0x34;
-		break;
-	case 2:					/* CardBus bridge */
-		ptr = 0x14;
-		break;
-	}
-	ptr = pcicfgr32(p, ptr);
-
-	while(ptr != 0){
-		/*
-		 * Check for validity.
-		 * Can't be in standard header and must be double
-		 * word aligned.
-		 */
-		if(ptr < 0x40 || (ptr & ~0xFC))
-			return -1;
-		if(pcicfgr8(p, ptr) == 0x01){
-			p->pmrb = ptr;
-			return ptr;
-		}
-
-		ptr = pcicfgr8(p, ptr+1);
-	}
-
-	return -1;
-}
-
-int
-pcigetpms(Pcidev* p)
-{
-	int pmcsr, ptr;
-
-	if((ptr = pcigetpmrb(p)) == -1)
-		return -1;
-
-	/*
-	 * Power Management Register Block:
-	 *  offset 0:	Capability ID
-	 *	   1:	next item pointer
-	 *	   2:	capabilities
-	 *	   4:	control/status
-	 *	   6:	bridge support extensions
-	 *	   7:	data
-	 */
-	pmcsr = pcicfgr16(p, ptr+4);
-
-	return pmcsr & 0x0003;
-}
-
-int
-pcisetpms(Pcidev* p, int state)
-{
-	int ostate, pmc, pmcsr, ptr;
-
-	if((ptr = pcigetpmrb(p)) == -1)
-		return -1;
-
-	pmc = pcicfgr16(p, ptr+2);
-	pmcsr = pcicfgr16(p, ptr+4);
-	ostate = pmcsr & 0x0003;
-	pmcsr &= ~0x0003;
-
-	switch(state){
-	default:
-		return -1;
-	case 0:
-		break;
-	case 1:
-		if(!(pmc & 0x0200))
-			return -1;
-		break;
-	case 2:
-		if(!(pmc & 0x0400))
-			return -1;
-		break;
-	case 3:
-		break;
-	}
-	pmcsr |= state;
-	pcicfgw16(p, ptr+4, pmcsr);
-
-	return ostate;
-}
--- a/os/boot/pc/print.c
+++ /dev/null
@@ -1,31 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-
-static Lock fmtl;
-
-void
-_fmtlock(void)
-{
-	lock(&fmtl);
-}
-
-void
-_fmtunlock(void)
-{
-	unlock(&fmtl);
-}
-
-int
-_efgfmt(Fmt*)
-{
-	return -1;
-}
-
-int
-errfmt(Fmt*)
-{
-	return -1;
-}
--- a/os/boot/pc/queue.c
+++ /dev/null
@@ -1,44 +1,0 @@
-#include	"u.h"
-#include	"lib.h"
-#include	"mem.h"
-#include	"dat.h"
-#include	"fns.h"
-#include	"io.h"
-
-int
-qgetc(IOQ *q)
-{
-	int c;
-
-	if(q->in == q->out)
-		return -1;
-	c = *q->out;
-	if(q->out == q->buf+sizeof(q->buf)-1)
-		q->out = q->buf;
-	else
-		q->out++;
-	return c;
-}
-
-static int
-qputc(IOQ *q, int c)
-{
-	uchar *nextin;
-	if(q->in >= &q->buf[sizeof(q->buf)-1])
-		nextin = q->buf;
-	else
-		nextin = q->in+1;
-	if(nextin == q->out)
-		return -1;
-	*q->in = c;
-	q->in = nextin;
-	return 0;
-}
-
-void
-qinit(IOQ *q)
-{
-	q->in = q->out = q->buf;
-	q->getc = qgetc;
-	q->putc = qputc;
-}
--- a/os/boot/pc/sd.h
+++ /dev/null
@@ -1,126 +1,0 @@
-/*
- * Storage Device.
- */
-typedef struct SDev SDev;
-typedef struct SDifc SDifc;
-typedef struct SDpart SDpart;
-typedef struct SDreq SDreq;
-typedef struct SDunit SDunit;
-
-typedef struct SDpart {
-	uvlong	start;
-	uvlong	end;
-	char	name[NAMELEN];
-	char	user[NAMELEN];
-	ulong	perm;
-	int	valid;
-	void *crud;
-} SDpart;
-
-typedef struct SDunit {
-	SDev*	dev;
-	int	subno;
-	uchar	inquiry[256];		/* format follows SCSI spec */
-	char	name[NAMELEN];
-//	Rendez	rendez;
-
-//	QLock	ctl;
-	uvlong	sectors;
-	ulong	secsize;
-	SDpart*	part;
-	int	npart;			/* of valid partitions */
-	int	changed;
-
-//	QLock	raw;
-	int	state;
-	ulong	pid;
-	SDreq*	req;
-} SDunit;
-
-typedef struct SDev {
-	SDifc*	ifc;			/* pnp/legacy */
-	void	*ctlr;
-	int	idno;
-	int	index;			/* into unit space */
-	int	nunit;
-	SDev*	next;
-
-//	QLock;				/* enable/disable */
-	int	enabled;
-} SDev;
-
-typedef struct SDifc {
-	char*	name;
-
-	SDev*	(*pnp)(void);
-	SDev*	(*legacy)(int, int);
-	SDev*	(*id)(SDev*);
-	int	(*enable)(SDev*);
-	int	(*disable)(SDev*);
-
-	int	(*verify)(SDunit*);
-	int	(*online)(SDunit*);
-	int	(*rio)(SDreq*);
-	int	(*rctl)(SDunit*, char*, int);
-	int	(*wctl)(SDunit*, void*);
-
-	long	(*bio)(SDunit*, int, int, void*, long, long);
-} SDifc;
-
-typedef struct SDreq {
-	SDunit*	unit;
-	int	lun;
-	int	write;
-	uchar	cmd[16];
-	int	clen;
-	void*	data;
-	int	dlen;
-
-	int	flags;
-
-	int	status;
-	long	rlen;
-	uchar	sense[256];
-} SDreq;
-
-enum {
-	SDnosense	= 0x00000001,
-	SDvalidsense	= 0x00010000,
-};
-
-enum {
-	SDmalloc	= -4,
-	SDeio		= -3,
-	SDtimeout	= -2,
-	SDnostatus	= -1,
-
-	SDok		= 0,
-
-	SDcheck		= 0x02,		/* check condition */
-	SDbusy		= 0x08,		/* busy */
-
-	SDmaxio		= 2048*1024,
-	SDnpart		= 16,
-};
-
-/* sdscsi.c */
-extern int scsiverify(SDunit*);
-extern int scsionline(SDunit*);
-extern long scsibio(SDunit*, int, int, void*, long, long);
-extern SDev* scsiid(SDev*, SDifc*);
-
-#define IrqATA0 14
-#define IrqATA1 15
-#define qlock(i)	while(0)
-#define qunlock(i)	while(0)
-
-#define putstrn consputs
-
-void sleep(void*, int(*)(void*), void*);
-void tsleep(void*, int(*)(void*), void*, int);
-#define wakeup(x) while(0)
-extern long sdbio(SDunit *unit, SDpart *pp, void *a, long len, vlong off);
-void	partition(SDunit*);
-SDpart* sdfindpart(SDunit*, char*);
-void	sdaddpart(SDunit*, char*, uvlong, uvlong);
-void*	sdmalloc(void*, ulong);
--- a/os/boot/pc/sd53c8xx.c
+++ /dev/null
@@ -1,2124 +1,0 @@
-/*
- * NCR 53c8xx driver for Plan 9
- * Nigel Roles (ngr@cotswold.demon.co.uk)
- *
- * 08/07/99	Ultra2 fixed. Brazil #ifdefs added. Fixed script error 6 diagnostics.
- *
- * 09/06/99	Enhancements to support 895 and 896 correctly. Attempt at Ultra 2 negotiation,
- *		though no device to test with yet.
- *		Variant now contains the number of valid chip registers to assist
- *		dumpncrregs() 
- *
- * 06/10/98	Various bug fixes and Brazil compiler inspired changes from jmk
- *
- * 05/10/98	Small fix to handle command length being greater than expected by device
- *
- * 04/08/98     Added missing locks to interrupt handler. Marked places where 
- *		multiple controller extensions could go
- *
- * 18/05/97	Fixed overestimate in size of local SCRIPT RAM
- *
- * 17/05/97	Bug fix to return status
- *
- * 06/10/96	Enhanced list of chip IDs. 875 revision 1 has no clock doubler, so assume it
- *		is shipped with 80MHz crystal. Use bit 3 of the GPREG to recognise differential
- *		boards. This is Symbios specific, but since they are about the only suppliers of
- *		differential cards.
- *
- * 23/9/96	Wide and Ultra supported. 825A and 860 added to variants. Dual compiling
- *		version for fileserver and cpu. 80MHz default clock for 860
- *		
- * 5/8/96	Waits for an Inquiry message before initiating synchronous negotiation
- *		in case capabilities byte [7] indicates device does not support it. Devices
- *		which do target initiated negotiation will typically get in first; a few
- *		bugs in handling this have been fixed
- *
- * 3/8/96	Added differential support (put scsi0=diff in plan9.ini)
- *		Split exec() into exec() and io(). Exec() is small, and Io() does not
- *		use any Plan 9 specific data structures, so alternate exec() functions
- *		may be done for other environments, such as the fileserver
- *
- * GENERAL
- *
- * Works on 810 and 875
- * Should work on 815, 825, 810A, 825A, 860A
- * Uses local RAM, large FIFO, prefetch, burst opcode fetch, and 16 byte synch. offset
- * where applicable
- * Supports multi-target, wide, Ultra
- * Differential mode can be enabled by putting scsi0=diff in plan9.ini
- * NO SUPPORT FOR tagged queuing (yet)
- *
- * Known problems
- */
-
-#define MAXTARGET	16		/* can be 8 or 16 */
-
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-#include "ureg.h"
-#include "error.h"
-
-#include "sd.h"
-extern SDifc sd53c8xxifc;
-
-#define waserror()	(0)
-#define poperror()
-typedef struct QLock{ int r; } QLock;
-typedef struct Rendez{ int r; } Rendez;
-#define	intrenable(irq, f, c, tbdf, name)	setvec(VectorPIC+(irq), f, c);
-
-/**********************************/
-/* Portable configuration macros  */
-/**********************************/
-
-//#define BOOTDEBUG
-//#define ASYNC_ONLY
-//#define	INTERNAL_SCLK
-//#define ALWAYS_DO_WDTR
-#define WMR_DEBUG
-
-/**********************************/
-/* CPU specific macros            */
-/**********************************/
-
-#ifdef BOOTDEBUG
-
-#define KPRINT oprint
-#define IPRINT intrprint
-#define DEBUG(n) 0
-#define IFLUSH() iflush()
-
-#else
-
-#define KPRINT	if(0)print
-#define IPRINT	if(0)print
-#define DEBUG(n)	(0)
-#define IFLUSH()
-
-#endif /* BOOTDEBUG */
-
-/*******************************/
-/* General                     */
-/*******************************/
-
-#ifndef DMASEG
-#define DMASEG(x) PADDR(x)
-#define legetl(x) (*(ulong*)(x))
-#define lesetl(x,v) (*(ulong*)(x) = (v))
-#define swabl(a,b,c)
-#else
-#endif /*DMASEG */
-#define DMASEG_TO_KADDR(x) KADDR(PADDR(x))
-#define KPTR(x) ((x) == 0 ? 0 : DMASEG_TO_KADDR(x))
-
-#define MEGA 1000000L
-#ifdef INTERNAL_SCLK
-#define	SCLK (33 * MEGA)
-#else
-#define SCLK (40 * MEGA)
-#endif /* INTERNAL_SCLK */
-#define ULTRA_NOCLOCKDOUBLE_SCLK (80 * MEGA)
-
-#define MAXSYNCSCSIRATE (5 * MEGA)
-#define MAXFASTSYNCSCSIRATE (10 * MEGA)
-#define MAXULTRASYNCSCSIRATE (20 * MEGA)
-#define MAXULTRA2SYNCSCSIRATE (40 * MEGA)
-#define MAXASYNCCORERATE (25 * MEGA)
-#define MAXSYNCCORERATE (25 * MEGA)
-#define MAXFASTSYNCCORERATE (50 * MEGA)
-#define MAXULTRASYNCCORERATE (80 * MEGA)
-#define MAXULTRA2SYNCCORERATE (160 * MEGA)
-
-
-#define X_MSG	1
-#define X_MSG_SDTR 1
-#define X_MSG_WDTR 3
-
-struct na_patch {
-	unsigned lwoff;
-	unsigned char type;
-};
-
-typedef struct Ncr {
-	uchar scntl0;	/* 00 */
-	uchar scntl1;
-	uchar scntl2;
-	uchar scntl3;
-
-	uchar scid;	/* 04 */
-	uchar sxfer;
-	uchar sdid;
-	uchar gpreg;
-
-	uchar sfbr;	/* 08 */
-	uchar socl;
-	uchar ssid;
-	uchar sbcl;
-
-	uchar dstat;	/* 0c */
-	uchar sstat0;
-	uchar sstat1;
-	uchar sstat2;
-
-	uchar dsa[4];	/* 10 */
-
-	uchar istat;	/* 14 */
-	uchar istatpad[3];
-
-	uchar ctest0;	/* 18 */
-	uchar ctest1;
-	uchar ctest2;
-	uchar ctest3;
-
-	uchar temp[4];	/* 1c */
-
-	uchar dfifo;	/* 20 */
-	uchar ctest4;
-	uchar ctest5;
-	uchar ctest6;
-
-	uchar dbc[3];	/* 24 */
-	uchar dcmd;	/* 27 */
-
-	uchar dnad[4];	/* 28 */
-	uchar dsp[4];	/* 2c */
-	uchar dsps[4];	/* 30 */
-
-	uchar scratcha[4];	/* 34 */
-
-	uchar dmode;	/* 38 */
-	uchar dien;
-	uchar dwt;
-	uchar dcntl;
-
-	uchar adder[4];	/* 3c */
-
-	uchar sien0;	/* 40 */
-	uchar sien1;
-	uchar sist0;
-	uchar sist1;
-
-	uchar slpar;	/* 44 */
-	uchar slparpad0;
-	uchar macntl;
-	uchar gpcntl;
-
-	uchar stime0;	/* 48 */
-	uchar stime1;
-	uchar respid;
-	uchar respidpad0;
-
-	uchar stest0;	/* 4c */
-	uchar stest1;
-	uchar stest2;
-	uchar stest3;
-
-	uchar sidl;	/* 50 */
-	uchar sidlpad[3];
-
-	uchar sodl;	/* 54 */
-	uchar sodlpad[3];
-
-	uchar sbdl;	/* 58 */
-	uchar sbdlpad[3];
-
-	uchar scratchb[4];	/* 5c */
-} Ncr;
-
-typedef struct Movedata {
-	uchar dbc[4];
-	uchar pa[4];
-} Movedata;
-
-typedef enum NegoState {
-	NeitherDone, WideInit, WideResponse, WideDone,
-	SyncInit, SyncResponse, BothDone
-} NegoState;
-
-typedef enum State {
-	Allocated, Queued, Active, Done
-} State;
-
-typedef struct Dsa {
-	union {
-		uchar state[4];
-		struct {
-			uchar stateb;
-			uchar result;
-			uchar dmablks;
-			uchar flag;	/* setbyte(state,3,...) */
-		};
-	};
-
-	union {
-		ulong dmancr;		/* For block transfer: NCR order (little-endian) */
-		uchar dmaaddr[4];
-	};
-
-	uchar target;			/* Target */
-	uchar pad0[3];
-
-	uchar lun;			/* Logical Unit Number */
-	uchar pad1[3];
-
-	uchar scntl3;
-	uchar sxfer;
-	uchar pad2[2];
-
-	uchar next[4];			/* chaining for SCRIPT (NCR byte order) */
-	struct Dsa *freechain;		/* chaining for freelist */
-	Rendez;
-	uchar scsi_id_buf[4];
-	Movedata msg_out_buf;
-	Movedata cmd_buf;
-	Movedata data_buf;
-	Movedata status_buf;
-	uchar msg_out[10];		/* enough to include SDTR */
-	uchar status;
-	int p9status;
-	uchar parityerror;
-} Dsa;
-
-typedef enum Feature {
-	BigFifo = 1,			/* 536 byte fifo */
-	BurstOpCodeFetch = 2,		/* burst fetch opcodes */
-	Prefetch = 4,			/* prefetch 8 longwords */
-	LocalRAM = 8,			/* 4K longwords of local RAM */
-	Differential = 16,		/* Differential support */
-	Wide = 32,			/* Wide capable */
-	Ultra = 64,			/* Ultra capable */
-	ClockDouble = 128,		/* Has clock doubler */
-	ClockQuad = 256,		/* Has clock quadrupler (same as Ultra2) */
-	Ultra2 = 256,
-} Feature;
-
-typedef enum Burst {
-	Burst2 = 0,
-	Burst4 = 1,
-	Burst8 = 2,
-	Burst16 = 3,
-	Burst32 = 4,
-	Burst64 = 5,
-	Burst128 = 6
-} Burst;
-
-typedef struct Variant {
-	ushort did;
-	uchar maxrid;			/* maximum allowed revision ID */
-	char *name;
-	Burst burst;			/* codings for max burst */
-	uchar maxsyncoff;		/* max synchronous offset */
-	uchar registers;		/* number of 32 bit registers */
-	unsigned feature;
-} Variant;
-
-static unsigned char cf2[] = { 6, 2, 3, 4, 6, 8, 12, 16 };
-#define NULTRA2SCF (sizeof(cf2)/sizeof(cf2[0]))
-#define NULTRASCF (NULTRA2SCF - 2)
-#define NSCF (NULTRASCF - 1)
-
-typedef struct Controller {
-	Lock;
-	struct {
-		uchar scntl3;
-		uchar stest2;
-	} bios;
-	uchar synctab[NULTRA2SCF - 1][8];/* table of legal tpfs */
-	NegoState s[MAXTARGET];
-	uchar scntl3[MAXTARGET];
-	uchar sxfer[MAXTARGET];
-	uchar cap[MAXTARGET];		/* capabilities byte from Identify */
-	ushort capvalid;		/* bit per target for validity of cap[] */
-	ushort wide;			/* bit per target set if wide negotiated */
-	ulong sclk;			/* clock speed of controller */
-	uchar clockmult;		/* set by synctabinit */
-	uchar ccf;			/* CCF bits */
-	uchar tpf;			/* best tpf value for this controller */
-	uchar feature;			/* requested features */
-	int running;			/* is the script processor running? */
-	int ssm;			/* single step mode */
-	Ncr *n;				/* pointer to registers */
-	Variant *v;			/* pointer to variant type */
-	ulong *script;			/* where the real script is */
-	ulong scriptpa;			/* where the real script is */
-	Pcidev* pcidev;
-	SDev*	sdev;
-
-	struct {
-		Lock;
-		uchar head[4];		/* head of free list (NCR byte order) */
-		Dsa	*tail;
-		Dsa	*freechain;
-	} dsalist;
-
-	QLock q[MAXTARGET];		/* queues for each target */
-} Controller;
-
-static Controller controller;
-
-/* ISTAT */
-enum { Abrt = 0x80, Srst = 0x40, Sigp = 0x20, Sem = 0x10, Con = 0x08, Intf = 0x04, Sip = 0x02, Dip = 0x01 };
-
-/* DSTAT */
-enum { Dfe = 0x80, Mdpe = 0x40, Bf = 0x20, Abrted = 0x10, Ssi = 0x08, Sir = 0x04, Iid = 0x01 };
-
-/* SSTAT */
-enum { DataOut, DataIn, Cmd, Status, ReservedOut, ReservedIn, MessageOut, MessageIn };
-
-static void setmovedata(Movedata*, ulong, ulong);
-static void advancedata(Movedata*, long);
-static int bios_set_differential(Controller *c);
-
-static char *phase[] = {
-	"data out", "data in", "command", "status",
-	"reserved out", "reserved in", "message out", "message in"
-};
-
-#ifdef BOOTDEBUG
-#define DEBUGSIZE 10240
-char debugbuf[DEBUGSIZE];
-char *debuglast;
-
-static void
-intrprint(char *format, ...)
-{
-	if (debuglast == 0)
-		debuglast = debugbuf;
-	debuglast = doprint(debuglast, debugbuf + (DEBUGSIZE - 1), format, (&format + 1));
-}
-
-static void
-iflush()
-{
-	int s;
-	char *endp;
-	s = splhi();
-	if (debuglast == 0)
-		debuglast = debugbuf;
-	if (debuglast == debugbuf) {
-		splx(s);
-		return;
-	}
-	endp = debuglast;
-	splx(s);
-	screenputs(debugbuf, endp - debugbuf);
-	s = splhi();
-	memmove(debugbuf, endp, debuglast - endp);
-	debuglast -= endp - debugbuf;
-	splx(s);
-}
-
-static void
-oprint(char *format, ...)
-{
-	int s;
-
-	iflush();
-	s = splhi();
-	if (debuglast == 0)
-		debuglast = debugbuf;
-	debuglast = doprint(debuglast, debugbuf + (DEBUGSIZE - 1), format, (&format + 1));
-	splx(s);
-	iflush();	
-}
-#endif
-
-#include "sd53c8xx.i"
-
-static Dsa *
-dsaalloc(Controller *c, int target, int lun)
-{
-	Dsa *d;
-
-	ilock(&c->dsalist);
-	if ((d = c->dsalist.freechain) == 0) {
-		d = xalloc(sizeof(*d));
-		if (DEBUG(1))
-			KPRINT("sd53c8xx: %d/%d: allocated new dsa %lux\n", target, lun, d);
-		lesetl(d->next, 0);
-		lesetl(d->state, A_STATE_ALLOCATED);
-		if (legetl(c->dsalist.head) == 0)
-			lesetl(c->dsalist.head, DMASEG(d));	/* ATOMIC?!? */
-		else
-			lesetl(c->dsalist.tail->next, DMASEG(d));	/* ATOMIC?!? */
-		c->dsalist.tail = d;
-	}
-	else {
-		if (DEBUG(1))
-			KPRINT("sd53c8xx: %d/%d: reused dsa %lux\n", target, lun, d);
-		c->dsalist.freechain = d->freechain;
-		lesetl(d->state, A_STATE_ALLOCATED);
-	}
-	iunlock(&c->dsalist);
-	d->target = target;
-	d->lun = lun;
-	return d;
-}
-
-static void
-dsafree(Controller *c, Dsa *d)
-{
-	ilock(&c->dsalist);
-	d->freechain = c->dsalist.freechain;
-	c->dsalist.freechain = d;
-	lesetl(d->state, A_STATE_FREE);
-	iunlock(&c->dsalist);
-}
-
-static Dsa *
-dsafind(Controller *c, uchar target, uchar lun, uchar state)
-{
-	Dsa *d;
-	for (d = KPTR(legetl(c->dsalist.head)); d; d = KPTR(legetl(d->next))) {
-		if (d->target != 0xff && d->target != target)
-			continue;
-		if (lun != 0xff && d->lun != lun)
-			continue;
-		if (state != 0xff && d->stateb != state)
-			continue;
-		break;
-	}
-	return d;
-}
-
-static void
-dumpncrregs(Controller *c, int intr)
-{
-	int i;
-	Ncr *n = c->n;
-	int depth = c->v->registers / 4;
-
-	KPRINT("sa = %.8lux\n", c->scriptpa);
-	for (i = 0; i < depth; i++) {
-		int j;
-		for (j = 0; j < 4; j++) {
-			int k = j * depth + i;
-			uchar *p;
-
-			/* display little-endian to make 32-bit values readable */
-			p = (uchar*)n+k*4;
-			if (intr)
-				IPRINT(" %.2x%.2x%.2x%.2x %.2x %.2x", p[3], p[2], p[1], p[0], k * 4, (k * 4) + 0x80);
-			else
-				KPRINT(" %.2x%.2x%.2x%.2x %.2x %.2x", p[3], p[2], p[1], p[0], k * 4, (k * 4) + 0x80);
-			USED(p);
-		}
-		if (intr)
-			IPRINT("\n");
-		else
-			KPRINT("\n");
-	}
-}	
-
-static int
-chooserate(Controller *c, int tpf, int *scfp, int *xferpp)
-{
-	/* find lowest entry >= tpf */
-	int besttpf = 1000;
-	int bestscfi = 0;
-	int bestxferp = 0;
-	int scf, xferp;
-	int maxscf;
-
-	if (c->v->feature & Ultra2)
-		maxscf = NULTRA2SCF;
-	else if (c->v->feature & Ultra)
-		maxscf = NULTRASCF;
-	else
-		maxscf = NSCF;
-
-	/*
-	 * search large clock factors first since this should
-	 * result in more reliable transfers
-	 */
-	for (scf = maxscf; scf >= 1; scf--) {
-		for (xferp = 0; xferp < 8; xferp++) {
-			unsigned char v = c->synctab[scf - 1][xferp];
-			if (v == 0)
-				continue;
-			if (v >= tpf && v < besttpf) {
-				besttpf = v;
-				bestscfi = scf;
-				bestxferp = xferp;
-			}
-		}
-	}
-	if (besttpf == 1000)
-		return 0;
-	if (scfp)
-		*scfp = bestscfi;
-	if (xferpp)
-		*xferpp = bestxferp;
-	return besttpf;
-}
-
-static void
-synctabinit(Controller *c)
-{
-	int scf;
-	unsigned long scsilimit;
-	int xferp;
-	unsigned long cr, sr;
-	int tpf;
-	int fast;
-	int maxscf;
-
-	if (c->v->feature & Ultra2)
-		maxscf = NULTRA2SCF;
-	else if (c->v->feature & Ultra)
-		maxscf = NULTRASCF;
-	else
-		maxscf = NSCF;
-
-	/*
-	 * for chips with no clock doubler, but Ultra capable (e.g. 860, or interestingly the
-	 * first spin of the 875), assume 80MHz
-	 * otherwise use the internal (33 Mhz) or external (40MHz) default
-	 */
-
-	if ((c->v->feature & Ultra) != 0 && (c->v->feature & (ClockDouble | ClockQuad)) == 0)
-		c->sclk = ULTRA_NOCLOCKDOUBLE_SCLK;
-	else
-		c->sclk = SCLK;
-
-	/*
-	 * otherwise, if the chip is Ultra capable, but has a slow(ish) clock,
-	 * invoke the doubler
-	 */
-
-	if (SCLK <= 40000000) {
-		if (c->v->feature & ClockDouble) {
-			c->sclk *= 2;
-			c->clockmult = 1;
-		}
-		else if (c->v->feature & ClockQuad) {
-			c->sclk *= 4;
-			c->clockmult = 1;
-		}
-		else
-			c->clockmult = 0;
-	}
-	else
-		c->clockmult = 0;
-
-	/* derive CCF from sclk */
-	/* woebetide anyone with SCLK < 16.7 or > 80MHz */
-	if (c->sclk <= 25 * MEGA)
-		c->ccf = 1;
-	else if (c->sclk <= 3750000)
-		c->ccf = 2;
-	else if (c->sclk <= 50 * MEGA)
-		c->ccf = 3;
-	else if (c->sclk <= 75 * MEGA)
-		c->ccf = 4;
-	else if ((c->v->feature & ClockDouble) && c->sclk <= 80 * MEGA)
-		c->ccf = 5;
-	else if ((c->v->feature & ClockQuad) && c->sclk <= 120 * MEGA)
-		c->ccf = 6;
-	else if ((c->v->feature & ClockQuad) && c->sclk <= 160 * MEGA)
-		c->ccf = 7;
-
-	for (scf = 1; scf < maxscf; scf++) {
-		/* check for legal core rate */
-		/* round up so we run slower for safety */
-	   	cr = (c->sclk * 2 + cf2[scf] - 1) / cf2[scf];
-		if (cr <= MAXSYNCCORERATE) {
-			scsilimit = MAXSYNCSCSIRATE;
-			fast = 0;
-		}
-		else if (cr <= MAXFASTSYNCCORERATE) {
-			scsilimit = MAXFASTSYNCSCSIRATE;
-			fast = 1;
-		}
-		else if ((c->v->feature & Ultra) && cr <= MAXULTRASYNCCORERATE) {
-			scsilimit = MAXULTRASYNCSCSIRATE;
-			fast = 2;
-		}
-		else if ((c->v->feature & Ultra2) && cr <= MAXULTRA2SYNCCORERATE) {
-			scsilimit = MAXULTRA2SYNCSCSIRATE;
-			fast = 3;
-		}
-		else
-			continue;
-		for (xferp = 11; xferp >= 4; xferp--) {
-			int ok;
-			int tp;
-			/* calculate scsi rate - round up again */
-			/* start from sclk for accuracy */
-			int totaldivide = xferp * cf2[scf];
-			sr = (c->sclk * 2 + totaldivide - 1) / totaldivide;
-			if (sr > scsilimit)
-				break;
-			/*
-			 * now work out transfer period
-			 * round down now so that period is pessimistic
-			 */
-			tp = (MEGA * 1000) / sr;
-			/*
-			 * bounds check it
-			 */
-			if (tp < 25 || tp > 255 * 4)
-				continue;
-			/*
-			 * spot stupid special case for Ultra or Ultra2
-			 * while working out factor
-			 */
-			if (tp == 25)
-				tpf = 10;
-			else if (tp == 50)
-				tpf = 12;
-			else if (tp < 52)
-				continue;
-			else
-				tpf = tp / 4;
-			/*
-			 * now check tpf looks sensible
-			 * given core rate
-			 */
-			switch (fast) {
-			case 0:
-				/* scf must be ccf for SCSI 1 */
-				ok = tpf >= 50 && scf == c->ccf;
-				break;
-			case 1:
-				ok = tpf >= 25 && tpf < 50;
-				break;
-			case 2:
-				/*
-				 * must use xferp of 4, or 5 at a pinch
-				 * for an Ultra transfer
-				 */
-				ok = xferp <= 5 && tpf >= 12 && tpf < 25;
-				break;
-			case 3:
-				ok = xferp == 4 && (tpf == 10 || tpf == 11);
-				break;
-			default:
-				ok = 0;
-			}
-			if (!ok)
-				continue;
-			c->synctab[scf - 1][xferp - 4] = tpf;
-		}
-	}
-
-#ifndef NO_ULTRA2
-	if (c->v->feature & Ultra2)
-		tpf = 10;
-	else
-#endif
-	if (c->v->feature & Ultra)
-		tpf = 12;
-	else
-		tpf = 25;
-	for (; tpf < 256; tpf++) {
-		if (chooserate(c, tpf, &scf, &xferp) == tpf) {
-			unsigned tp = tpf == 10 ? 25 : (tpf == 12 ? 50 : tpf * 4);
-			unsigned long khz = (MEGA + tp - 1) / (tp);
-			KPRINT("sd53c8xx: tpf=%d scf=%d.%.1d xferp=%d mhz=%ld.%.3ld\n",
-			    tpf, cf2[scf] / 2, (cf2[scf] & 1) ? 5 : 0,
-			    xferp + 4, khz / 1000, khz % 1000);
-			USED(khz);
-			if (c->tpf == 0)
-				c->tpf = tpf;	/* note lowest value for controller */
-		}
-	}
-}
-
-static void
-synctodsa(Dsa *dsa, Controller *c)
-{
-/*
-	KPRINT("synctodsa(dsa=%lux, target=%d, scntl3=%.2lx sxfer=%.2x)\n",
-	    dsa, dsa->target, c->scntl3[dsa->target], c->sxfer[dsa->target]);
-*/
-	dsa->scntl3 = c->scntl3[dsa->target];
-	dsa->sxfer = c->sxfer[dsa->target];
-}
-
-static void
-setsync(Dsa *dsa, Controller *c, int target, uchar ultra, uchar scf, uchar xferp, uchar reqack)
-{
-	c->scntl3[target] =
-	    (c->scntl3[target] & 0x08) | (((scf << 4) | c->ccf | (ultra << 7)) & ~0x08);
-	c->sxfer[target] = (xferp << 5) | reqack;
-	c->s[target] = BothDone;
-	if (dsa) {
-		synctodsa(dsa, c);
-		c->n->scntl3 = c->scntl3[target];
-		c->n->sxfer = c->sxfer[target];
-	}
-}
-
-static void
-setasync(Dsa *dsa, Controller *c, int target)
-{
-	setsync(dsa, c, target, 0, c->ccf, 0, 0);
-}
-
-static void
-setwide(Dsa *dsa, Controller *c, int target, uchar wide)
-{
-	c->scntl3[target] = wide ? (1 << 3) : 0;
-	setasync(dsa, c, target);
-	c->s[target] = WideDone;
-}
-
-static int
-buildsdtrmsg(uchar *buf, uchar tpf, uchar offset)
-{
-	*buf++ = X_MSG;
-	*buf++ = 3;
-	*buf++ = X_MSG_SDTR;
-	*buf++ = tpf;
-	*buf = offset;
-	return 5;
-}
-
-static int
-buildwdtrmsg(uchar *buf, uchar expo)
-{
-	*buf++ = X_MSG;
-	*buf++ = 2;
-	*buf++ = X_MSG_WDTR;
-	*buf = expo;
-	return 4;
-}
-
-static void
-start(Controller *c, long entry)
-{
-	ulong p;
-
-	if (c->running)
-		panic("sd53c8xx: start called while running");
-	c->running = 1;
-	p = c->scriptpa + entry;
-	lesetl(c->n->dsp, p);
-	if (c->ssm)
-		c->n->dcntl |= 0x4;		/* start DMA in SSI mode */
-}
-
-static void
-ncrcontinue(Controller *c)
-{
-	if (c->running)
-		panic("sd53c8xx: ncrcontinue called while running");
-	/* set the start DMA bit to continue execution */
-	c->running = 1;
-	c->n->dcntl |= 0x4;
-}
-
-static void
-softreset(Controller *c)
-{
-	Ncr *n = c->n;
-
-	n->istat = Srst;		/* software reset */
-	n->istat = 0;
-	/* general initialisation */
-	n->scid = (1 << 6) | 7;		/* respond to reselect, ID 7 */
-	n->respid = 1 << 7;		/* response ID = 7 */
-
-#ifdef INTERNAL_SCLK
-	n->stest1 = 0x80;		/* disable external scsi clock */
-#else
-	n->stest1 = 0x00;
-#endif
-
-	n->stime0 = 0xdd;		/* about 0.5 second timeout on each device */
-	n->scntl0 |= 0x8;		/* Enable parity checking */
-
-	/* continued setup */
-	n->sien0 = 0x8f;
-	n->sien1 = 0x04;
-	n->dien = 0x7d;
-	n->stest3 = 0x80;		/* TolerANT enable */
-	c->running = 0;
-
-	if (c->v->feature & BigFifo)
-		n->ctest5 = (1 << 5);
-	n->dmode = c->v->burst << 6;	/* set burst length bits */
-	if (c->v->burst & 4)
-		n->ctest5 |= (1 << 2);	/* including overflow into ctest5 bit 2 */
-	if (c->v->feature & Prefetch)
-		n->dcntl |= (1 << 5);	/* prefetch enable */
-	else if (c->v->feature & BurstOpCodeFetch)
-		n->dmode |= (1 << 1);	/* burst opcode fetch */
-	if (c->v->feature & Differential) {
-		/* chip capable */
-		if ((c->feature & Differential) || bios_set_differential(c)) {
-			/* user enabled, or some evidence bios set differential */
-			if (n->sstat2 & (1 << 2))
-				print("sd53c8xx: can't go differential; wrong cable\n");
-			else {
-				n->stest2 = (1 << 5);
-				print("sd53c8xx: differential mode set\n");
-			}
-		}
-	}
-	if (c->clockmult) {
-		n->stest1 |= (1 << 3);	/* power up doubler */
-		delay(2);
-		n->stest3 |= (1 << 5);	/* stop clock */
-		n->stest1 |= (1 << 2);	/* enable doubler */
-		n->stest3 &= ~(1 << 5);	/* start clock */
-		/* pray */
-	}
-}
-
-static void
-msgsm(Dsa *dsa, Controller *c, int msg, int *cont, int *wakeme)
-{
-	uchar histpf, hisreqack;
-	int tpf;
-	int scf, xferp;
-	int len;
-
-	Ncr *n = c->n;
-
-	switch (c->s[dsa->target]) {
-	case SyncInit:
-		switch (msg) {
-		case A_SIR_MSG_SDTR:
-			/* reply to my SDTR */
-			histpf = n->scratcha[2];
-			hisreqack = n->scratcha[3];
-			KPRINT("sd53c8xx: %d: SDTN response %d %d\n",
-			    dsa->target, histpf, hisreqack);
-
-			if (hisreqack == 0)
-				setasync(dsa, c, dsa->target);
-			else {
-				/* hisreqack should be <= c->v->maxsyncoff */
-				tpf = chooserate(c, histpf, &scf, &xferp);
-				KPRINT("sd53c8xx: %d: SDTN: using %d %d\n",
-				    dsa->target, tpf, hisreqack);
-				setsync(dsa, c, dsa->target, tpf < 25, scf, xferp, hisreqack);
-			}
-			*cont = -2;
-			return;
-		case A_SIR_EV_PHASE_SWITCH_AFTER_ID:
-			/* target ignored ATN for message after IDENTIFY - not SCSI-II */
-			KPRINT("sd53c8xx: %d: illegal phase switch after ID message - SCSI-1 device?\n", dsa->target);
-			KPRINT("sd53c8xx: %d: SDTN: async\n", dsa->target);
-			setasync(dsa, c, dsa->target);
-			*cont = E_to_decisions;
-			return;
-		case A_SIR_MSG_REJECT:
-			/* rejection of my SDTR */
-			KPRINT("sd53c8xx: %d: SDTN: rejected SDTR\n", dsa->target);
-		//async:
-			KPRINT("sd53c8xx: %d: SDTN: async\n", dsa->target);
-			setasync(dsa, c, dsa->target);
-			*cont = -2;
-			return;
-		}
-		break;
-	case WideInit:
-		switch (msg) {
-		case A_SIR_MSG_WDTR:
-			/* reply to my WDTR */
-			KPRINT("sd53c8xx: %d: WDTN: response %d\n",
-			    dsa->target, n->scratcha[2]);
-			setwide(dsa, c, dsa->target, n->scratcha[2]);
-			*cont = -2;
-			return;
-		case A_SIR_EV_PHASE_SWITCH_AFTER_ID:
-			/* target ignored ATN for message after IDENTIFY - not SCSI-II */
-			KPRINT("sd53c8xx: %d: illegal phase switch after ID message - SCSI-1 device?\n", dsa->target);
-			setwide(dsa, c, dsa->target, 0);
-			*cont = E_to_decisions;
-			return;
-		case A_SIR_MSG_REJECT:
-			/* rejection of my SDTR */
-			KPRINT("sd53c8xx: %d: WDTN: rejected WDTR\n", dsa->target);
-			setwide(dsa, c, dsa->target, 0);
-			*cont = -2;
-			return;
-		}
-		break;
-
-	case NeitherDone:
-	case WideDone:
-	case BothDone:
-		switch (msg) {
-		case A_SIR_MSG_WDTR: {
-			uchar hiswide, mywide;
-			hiswide = n->scratcha[2];
-			mywide = (c->v->feature & Wide) != 0;
-			KPRINT("sd53c8xx: %d: WDTN: target init %d\n",
-			    dsa->target, hiswide);
-			if (hiswide < mywide)
-				mywide = hiswide;
-			KPRINT("sd53c8xx: %d: WDTN: responding %d\n",
-			    dsa->target, mywide);
-			setwide(dsa, c, dsa->target, mywide);
-			len = buildwdtrmsg(dsa->msg_out, mywide);
-			setmovedata(&dsa->msg_out_buf, DMASEG(dsa->msg_out), len);
-			*cont = E_response;
-			c->s[dsa->target] = WideResponse;
-			return;
-		}
-		case A_SIR_MSG_SDTR:
-#ifdef ASYNC_ONLY
-			*cont = E_reject;
-			return;
-#else
-			/* target decides to renegotiate */
-			histpf = n->scratcha[2];
-			hisreqack = n->scratcha[3];
-			KPRINT("sd53c8xx: %d: SDTN: target init %d %d\n",
-			    dsa->target, histpf, hisreqack);
-			if (hisreqack == 0) {
-				/* he wants asynchronous */
-				setasync(dsa, c, dsa->target);
-				tpf = 0;
-			}
-			else {
-				/* he wants synchronous */
-				tpf = chooserate(c, histpf, &scf, &xferp);
-				if (hisreqack > c->v->maxsyncoff)
-					hisreqack = c->v->maxsyncoff;
-				KPRINT("sd53c8xx: %d: using %d %d\n",
-				    dsa->target, tpf, hisreqack);
-				setsync(dsa, c, dsa->target, tpf < 25, scf, xferp, hisreqack);
-			}
-			/* build my SDTR message */
-			len = buildsdtrmsg(dsa->msg_out, tpf, hisreqack);
-			setmovedata(&dsa->msg_out_buf, DMASEG(dsa->msg_out), len);
-			*cont = E_response;
-			c->s[dsa->target] = SyncResponse;
-			return;
-#endif
-		}
-		break;
-	case WideResponse:
-		switch (msg) {
-		case A_SIR_EV_RESPONSE_OK:
-			c->s[dsa->target] = WideDone;
-			KPRINT("sd53c8xx: %d: WDTN: response accepted\n", dsa->target);
-			*cont = -2;
-			return;
-		case A_SIR_MSG_REJECT:
-			setwide(dsa, c, dsa->target, 0);
-			KPRINT("sd53c8xx: %d: WDTN: response REJECTed\n", dsa->target);
-			*cont = -2;
-			return;
-		}
-		break;
-	case SyncResponse:
-		switch (msg) {
-		case A_SIR_EV_RESPONSE_OK:
-			c->s[dsa->target] = BothDone;
-			KPRINT("sd53c8xx: %d: SDTN: response accepted (%s)\n",
-			    dsa->target, phase[n->sstat1 & 7]);
-			*cont = -2;
-			return;	/* chf */
-		case A_SIR_MSG_REJECT:
-			setasync(dsa, c, dsa->target);
-			KPRINT("sd53c8xx: %d: SDTN: response REJECTed\n", dsa->target);
-			*cont = -2;
-			return;
-		}
-		break;
-	}
-	KPRINT("sd53c8xx: %d: msgsm: state %d msg %d\n",
-	    dsa->target, c->s[dsa->target], msg);
-	*wakeme = 1;
-	return;
-}
-
-static void
-calcblockdma(Dsa *d, ulong base, ulong count)
-{
-	ulong blocks;
-	if (DEBUG(3))
-		blocks = 0;
-	else {
-		blocks = count / A_BSIZE;
-		if (blocks > 255)
-			blocks = 255;
-	}
-	d->dmablks = blocks;
-	d->dmaaddr[0] = base;
-	d->dmaaddr[1] = base >> 8;
-	d->dmaaddr[2] = base >> 16;
-	d->dmaaddr[3] = base >> 24;
-	setmovedata(&d->data_buf, base + blocks * A_BSIZE, count - blocks * A_BSIZE);
-	if (legetl(d->data_buf.dbc) == 0)
-		d->flag = 1;
-}
-
-static ulong
-read_mismatch_recover(Controller *c, Ncr *n, Dsa *dsa)
-{
-	ulong dbc;
-	uchar dfifo = n->dfifo;
-	int inchip;
-
-	dbc = (n->dbc[2]<<16)|(n->dbc[1]<<8)|n->dbc[0];
-	if (n->ctest5 & (1 << 5))
-		inchip = ((dfifo | ((n->ctest5 & 3) << 8)) - (dbc & 0x3ff)) & 0x3ff;
-	else
-		inchip = ((dfifo & 0x7f) - (dbc & 0x7f)) & 0x7f;
-	if (inchip) {
-		IPRINT("sd53c8xx: %d/%d: read_mismatch_recover: DMA FIFO = %d\n",
-		    dsa->target, dsa->lun, inchip);
-	}
-	if (n->sxfer & 0xf) {
-		/* SCSI FIFO */
-		uchar fifo = n->sstat1 >> 4;
-		if (c->v->maxsyncoff > 8)
-			fifo |= (n->sstat2 & (1 << 4));
-		if (fifo) {
-			inchip += fifo;
-			IPRINT("sd53c8xx: %d/%d: read_mismatch_recover: SCSI FIFO = %d\n",
-			    dsa->target, dsa->lun, fifo);
-		}
-	}
-	else {
-		if (n->sstat0 & (1 << 7)) {
-			inchip++;
-			IPRINT("sd53c8xx: %d/%d: read_mismatch_recover: SIDL full\n",
-			    dsa->target, dsa->lun);
-		}
-		if (n->sstat2 & (1 << 7)) {
-			inchip++;
-			IPRINT("sd53c8xx: %d/%d: read_mismatch_recover: SIDL msb full\n",
-			    dsa->target, dsa->lun);
-		}
-	}
-	USED(inchip);
-	return dbc;
-}
-
-static ulong
-write_mismatch_recover(Ncr *n, Dsa *dsa)
-{
-	ulong dbc;
-	uchar dfifo = n->dfifo;
-	int inchip;
-
-	dbc = (n->dbc[2]<<16)|(n->dbc[1]<<8)|n->dbc[0];
-	USED(dsa);
-	if (n->ctest5 & (1 << 5))
-		inchip = ((dfifo | ((n->ctest5 & 3) << 8)) - (dbc & 0x3ff)) & 0x3ff;
-	else
-		inchip = ((dfifo & 0x7f) - (dbc & 0x7f)) & 0x7f;
-#ifdef WMR_DEBUG
-	if (inchip) {
-		IPRINT("sd53c8xx: %d/%d: write_mismatch_recover: DMA FIFO = %d\n",
-		    dsa->target, dsa->lun, inchip);
-	}
-#endif
-	if (n->sstat0 & (1 << 5)) {
-		inchip++;
-#ifdef WMR_DEBUG
-		IPRINT("sd53c8xx: %d/%d: write_mismatch_recover: SODL full\n", dsa->target, dsa->lun);
-#endif
-	}
-	if (n->sstat2 & (1 << 5)) {
-		inchip++;
-#ifdef WMR_DEBUG
-		IPRINT("sd53c8xx: %d/%d: write_mismatch_recover: SODL msb full\n", dsa->target, dsa->lun);
-#endif
-	}
-	if (n->sxfer & 0xf) {
-		/* synchronous SODR */
-		if (n->sstat0 & (1 << 6)) {
-			inchip++;
-#ifdef WMR_DEBUG
-			IPRINT("sd53c8xx: %d/%d: write_mismatch_recover: SODR full\n",
-			    dsa->target, dsa->lun);
-#endif
-		}
-		if (n->sstat2 & (1 << 6)) {
-			inchip++;
-#ifdef WMR_DEBUG
-			IPRINT("sd53c8xx: %d/%d: write_mismatch_recover: SODR msb full\n",
-			    dsa->target, dsa->lun);
-#endif
-		}
-	}
-	/* clear the dma fifo */
-	n->ctest3 |= (1 << 2);
-	/* wait till done */
-	while ((n->dstat & Dfe) == 0)
-		;
-	return dbc + inchip;
-}
-
-static void
-interrupt(Ureg *ur, void *a)
-{
-	uchar istat;
-	ushort sist;
-	uchar dstat;
-	int wakeme = 0;
-	int cont = -1;
-	Dsa *dsa;
-	Controller *c = a;
-	Ncr *n = c->n;
-
-	USED(ur);
-	if (DEBUG(1))
-		IPRINT("sd53c8xx: int\n");
-	ilock(c);
-	istat = n->istat;
-	if (istat & Intf) {
-		Dsa *d;
-		int wokesomething = 0;
-		if (DEBUG(1))
-			IPRINT("sd53c8xx: Intfly\n");
-		n->istat = Intf;
-		/* search for structures in A_STATE_DONE */
-		for (d = KPTR(legetl(c->dsalist.head)); d; d = KPTR(legetl(d->next))) {
-			if (d->stateb == A_STATE_DONE) {
-				d->p9status = d->status;
-				if (DEBUG(1))
-					IPRINT("sd53c8xx: waking up dsa %lux\n", d);
-				wakeup(d);
-				wokesomething = 1;
-			}
-		}
-		if (!wokesomething)
-			IPRINT("sd53c8xx: nothing to wake up\n");
-	}
-
-	if ((istat & (Sip | Dip)) == 0) {
-		if (DEBUG(1))
-			IPRINT("sd53c8xx: int end %x\n", istat);
-		iunlock(c);
-		return;
-	}
-
-	sist = (n->sist1<<8)|n->sist0;	/* BUG? can two-byte read be inconsistent? */
-	dstat = n->dstat;
-	dsa = (Dsa *)DMASEG_TO_KADDR(legetl(n->dsa));
-	c->running = 0;
-	if (istat & Sip) {
-		if (DEBUG(1))
-			IPRINT("sist = %.4x\n", sist);
-		if (sist & 0x80) {
-			ulong addr;
-			ulong sa;
-			ulong dbc;
-			ulong tbc;
-			int dmablks;
-			ulong dmaaddr;
-
-			addr = legetl(n->dsp);
-			sa = addr - c->scriptpa;
-			if (DEBUG(1) || DEBUG(2))
-				IPRINT("sd53c8xx: %d/%d: Phase Mismatch sa=%.8lux\n",
-				    dsa->target, dsa->lun, sa);
-			/*
-			 * now recover
-			 */
-			if (sa == E_data_in_mismatch) {
-				dbc = read_mismatch_recover(c, n, dsa);
-				tbc = legetl(dsa->data_buf.dbc) - dbc;
-				advancedata(&dsa->data_buf, tbc);
-				if (DEBUG(1) || DEBUG(2))
-					IPRINT("sd53c8xx: %d/%d: transferred = %ld residue = %ld\n",
-					    dsa->target, dsa->lun, tbc, legetl(dsa->data_buf.dbc));
-				cont = E_to_decisions;
-			}
-			else if (sa == E_data_in_block_mismatch) {
-				dbc = read_mismatch_recover(c, n, dsa);
-				tbc = A_BSIZE - dbc;
-				/* recover current state from registers */
-				dmablks = n->scratcha[2];
-				dmaaddr = legetl(n->scratchb);
-				/* we have got to dmaaddr + tbc */
-				/* we have dmablks * A_BSIZE - tbc + residue left to do */
-				/* so remaining transfer is */
-				IPRINT("in_block_mismatch: dmaaddr = 0x%lux tbc=%lud dmablks=%d\n",
-				    dmaaddr, tbc, dmablks);
-				calcblockdma(dsa, dmaaddr + tbc,
-				    dmablks * A_BSIZE - tbc + legetl(dsa->data_buf.dbc));
-				/* copy changes into scratch registers */
-				IPRINT("recalc: dmablks %d dmaaddr 0x%lx pa 0x%lx dbc %ld\n",
-				    dsa->dmablks, legetl(dsa->dmaaddr),
-				    legetl(dsa->data_buf.pa), legetl(dsa->data_buf.dbc));
-				n->scratcha[2] = dsa->dmablks;
-				lesetl(n->scratchb, dsa->dmancr);
-				cont = E_data_block_mismatch_recover;
-			}
-			else if (sa == E_data_out_mismatch) {
-				dbc = write_mismatch_recover(n, dsa);
-				tbc = legetl(dsa->data_buf.dbc) - dbc;
-				advancedata(&dsa->data_buf, tbc);
-				if (DEBUG(1) || DEBUG(2))
-					IPRINT("sd53c8xx: %d/%d: transferred = %ld residue = %ld\n",
-					    dsa->target, dsa->lun, tbc, legetl(dsa->data_buf.dbc));
-				cont = E_to_decisions;
-			}
-			else if (sa == E_data_out_block_mismatch) {
-				dbc = write_mismatch_recover(n, dsa);
-				tbc = legetl(dsa->data_buf.dbc) - dbc;
-				/* recover current state from registers */
-				dmablks = n->scratcha[2];
-				dmaaddr = legetl(n->scratchb);
-				/* we have got to dmaaddr + tbc */
-				/* we have dmablks blocks - tbc + residue left to do */
-				/* so remaining transfer is */
-				IPRINT("out_block_mismatch: dmaaddr = %lux tbc=%lud dmablks=%d\n",
-				    dmaaddr, tbc, dmablks);
-				calcblockdma(dsa, dmaaddr + tbc,
-				    dmablks * A_BSIZE - tbc + legetl(dsa->data_buf.dbc));
-				/* copy changes into scratch registers */
-				n->scratcha[2] = dsa->dmablks;
-				lesetl(n->scratchb, dsa->dmancr);
-				cont = E_data_block_mismatch_recover;
-			}
-			else if (sa == E_id_out_mismatch) {
-				/*
-				 * target switched phases while attention held during
-				 * message out. The possibilities are:
-				 * 1. It didn't like the last message. This is indicated
-				 *    by the new phase being message_in. Use script to recover
-				 *
-				 * 2. It's not SCSI-II compliant. The new phase will be other
-				 *    than message_in. We should also indicate that the device
-				 *    is asynchronous, if it's the SDTR that got ignored
-				 * 
-				 * For now, if the phase switch is not to message_in, and
-				 * and it happens after IDENTIFY and before SDTR, we
-				 * notify the negotiation state machine.
-				 */
-				ulong lim = legetl(dsa->msg_out_buf.dbc);
-				uchar p = n->sstat1 & 7;
-				dbc = write_mismatch_recover(n, dsa);
-				tbc = lim - dbc;
-				IPRINT("sd53c8xx: %d/%d: msg_out_mismatch: %lud/%lud sent, phase %s\n",
-				    dsa->target, dsa->lun, tbc, lim, phase[p]);
-				if (p != MessageIn && tbc == 1) {
-					msgsm(dsa, c, A_SIR_EV_PHASE_SWITCH_AFTER_ID, &cont, &wakeme);
-				}
-				else
-					cont = E_id_out_mismatch_recover;
-			}
-			else if (sa == E_cmd_out_mismatch) {
-				/*
-				 * probably the command count is longer than the device wants ...
-				 */
-				ulong lim = legetl(dsa->cmd_buf.dbc);
-				uchar p = n->sstat1 & 7;
-				dbc = write_mismatch_recover(n, dsa);
-				tbc = lim - dbc;
-				IPRINT("sd53c8xx: %d/%d: cmd_out_mismatch: %lud/%lud sent, phase %s\n",
-				    dsa->target, dsa->lun, tbc, lim, phase[p]);
-				USED(p, tbc);
-				cont = E_to_decisions;
-			}
-			else {
-				IPRINT("sd53c8xx: %d/%d: ma sa=%.8lux wanted=%s got=%s\n",
-				    dsa->target, dsa->lun, sa,
-				    phase[n->dcmd & 7],
-				    phase[n->sstat1 & 7]);
-				dumpncrregs(c, 1);
-				dsa->p9status = SDeio;	/* chf */
-				wakeme = 1;
-			}
-		}
-		/*else*/ if (sist & 0x400) {
-			if (DEBUG(0))
-				IPRINT("sd53c8xx: %d/%d Sto\n", dsa->target, dsa->lun);
-			dsa->p9status = SDtimeout;
-			dsa->stateb = A_STATE_DONE;
-			softreset(c);
-			cont = E_issue_check;
-			wakeme = 1;
-		}
-		if (sist & 0x1) {
-			IPRINT("sd53c8xx: %d/%d: parity error\n", dsa->target, dsa->lun);
-			dsa->parityerror = 1;
-		}
-		if (sist & 0x4) {
-			IPRINT("sd53c8xx: %d/%d: unexpected disconnect\n",
-			    dsa->target, dsa->lun);
-			dumpncrregs(c, 1);
-			//wakeme = 1;
-			dsa->p9status = SDeio;
-		}
-	}
-	if (istat & Dip) {
-		if (DEBUG(1))
-			IPRINT("dstat = %.2x\n", dstat);
-		/*else*/ if (dstat & Ssi) {
-			ulong *p = DMASEG_TO_KADDR(legetl(n->dsp));
-			ulong w = (uchar *)p - (uchar *)c->script;
-			IPRINT("[%lux]", w);
-			USED(w);
-			cont = -2;	/* restart */
-		}
-		if (dstat & Sir) {
-			switch (legetl(n->dsps)) {
-			case A_SIR_MSG_IO_COMPLETE:
-				dsa->p9status = dsa->status;
-				wakeme = 1;
-				break;
-			case A_SIR_MSG_SDTR:
-			case A_SIR_MSG_WDTR:
-			case A_SIR_MSG_REJECT:
-			case A_SIR_EV_RESPONSE_OK:
-				msgsm(dsa, c, legetl(n->dsps), &cont, &wakeme);
-				break;
-			case A_SIR_MSG_IGNORE_WIDE_RESIDUE:
-				/* back up one in the data transfer */
-				IPRINT("sd53c8xx: %d/%d: ignore wide residue %d, WSR = %d\n",
-				    dsa->target, dsa->lun, n->scratcha[1], n->scntl2 & 1);
-				if (dsa->dmablks == 0 && dsa->flag)
-					IPRINT("sd53c8xx: %d/%d: transfer over; residue ignored\n",
-					    dsa->target, dsa->lun);
-				else
-					calcblockdma(dsa, legetl(dsa->dmaaddr) - 1,
-					    dsa->dmablks * A_BSIZE + legetl(dsa->data_buf.dbc) + 1);
-				cont = -2;
-				break;
-			case A_SIR_ERROR_NOT_MSG_IN_AFTER_RESELECT:
-				IPRINT("sd53c8xx: %d: not msg_in after reselect (%s)",
-				    n->ssid & 7, phase[n->sstat1 & 7]);
-				dsa = dsafind(c, n->ssid & 7, -1, A_STATE_DISCONNECTED);
-				dumpncrregs(c, 1);
-				wakeme = 1;
-				break;
-			case A_SIR_NOTIFY_MSG_IN:
-				IPRINT("sd53c8xx: %d/%d: msg_in %d\n",
-				    dsa->target, dsa->lun, n->sfbr);
-				cont = -2;
-				break;
-			case A_SIR_NOTIFY_DISC:
-				IPRINT("sd53c8xx: %d/%d: disconnect:", dsa->target, dsa->lun);
-				goto dsadump;
-			case A_SIR_NOTIFY_STATUS:
-				IPRINT("sd53c8xx: %d/%d: status\n", dsa->target, dsa->lun);
-				cont = -2;
-				break;
-			case A_SIR_NOTIFY_COMMAND:
-				IPRINT("sd53c8xx: %d/%d: commands\n", dsa->target, dsa->lun);
-				cont = -2;
-				break;
-			case A_SIR_NOTIFY_DATA_IN:
-				IPRINT("sd53c8xx: %d/%d: data in a %lx b %lx\n",
-				    dsa->target, dsa->lun, legetl(n->scratcha), legetl(n->scratchb));
-				cont = -2;
-				break;
-			case A_SIR_NOTIFY_BLOCK_DATA_IN:
-				IPRINT("sd53c8xx: %d/%d: block data in: a2 %x b %lx\n",
-				    dsa->target, dsa->lun, n->scratcha[2], legetl(n->scratchb));
-				cont = -2;
-				break;
-			case A_SIR_NOTIFY_DATA_OUT:
-				IPRINT("sd53c8xx: %d/%d: data out\n", dsa->target, dsa->lun);
-				cont = -2;
-				break;
-			case A_SIR_NOTIFY_DUMP:
-				IPRINT("sd53c8xx: %d/%d: dump\n", dsa->target, dsa->lun);
-				dumpncrregs(c, 1);
-				cont = -2;
-				break;
-			case A_SIR_NOTIFY_DUMP2:
-				IPRINT("sd53c8xx: %d/%d: dump2:", dsa->target, dsa->lun);
-				IPRINT(" sa %lux", legetl(n->dsp) - c->scriptpa);
-				IPRINT(" dsa %lux", legetl(n->dsa));
-				IPRINT(" sfbr %ux", n->sfbr);
-				IPRINT(" a %lux", n->scratcha);
-				IPRINT(" b %lux", legetl(n->scratchb));
-				IPRINT(" ssid %ux", n->ssid);
-				IPRINT("\n");
-				cont = -2;
-				break;
-			case A_SIR_NOTIFY_WAIT_RESELECT:
-				IPRINT("sd53c8xx: wait reselect\n");
-				cont = -2;
-				break;
-			case A_SIR_NOTIFY_RESELECT:
-				IPRINT("sd53c8xx: reselect: ssid %.2x sfbr %.2x at %ld\n",
-				    n->ssid, n->sfbr, TK2MS(m->ticks));
-				cont = -2;
-				break;
-			case A_SIR_NOTIFY_ISSUE:
-				IPRINT("sd53c8xx: %d/%d: issue:", dsa->target, dsa->lun);
-			dsadump:
-				IPRINT(" tgt=%d", dsa->target);
-				IPRINT(" time=%ld", TK2MS(m->ticks));
-				IPRINT("\n");
-				cont = -2;
-				break;
-			case A_SIR_NOTIFY_ISSUE_CHECK:
-				IPRINT("sd53c8xx: issue check\n");
-				cont = -2;
-				break;
-			case A_SIR_NOTIFY_SIGP:
-				IPRINT("sd53c8xx: responded to SIGP\n");
-				cont = -2;
-				break;
-			case A_SIR_NOTIFY_DUMP_NEXT_CODE: {
-				ulong *dsp = DMASEG_TO_KADDR(legetl(n->dsp));
-				int x;
-				IPRINT("sd53c8xx: code at %lux", dsp - c->script);
-				for (x = 0; x < 6; x++)
-					IPRINT(" %.8lux", dsp[x]);
-				IPRINT("\n");
-				USED(dsp);
-				cont = -2;
-				break;
-			}
-			case A_SIR_NOTIFY_WSR:
-				IPRINT("sd53c8xx: %d/%d: WSR set\n", dsa->target, dsa->lun);
-				cont = -2;
-				break;
-			case A_SIR_NOTIFY_LOAD_SYNC:
-				IPRINT("sd53c8xx: %d/%d: scntl=%.2x sxfer=%.2x\n",
-				    dsa->target, dsa->lun, n->scntl3, n->sxfer);
-				cont = -2;
-				break;
-			case A_SIR_NOTIFY_RESELECTED_ON_SELECT:
-				IPRINT("sd53c8xx: %d/%d: reselected during select\n",
-				    dsa->target, dsa->lun);
-				cont = -2;
-				break;
-			default:
-				IPRINT("sd53c8xx: %d/%d: script error %ld\n",
-					dsa->target, dsa->lun, legetl(n->dsps));
-				dumpncrregs(c, 1);
-				wakeme = 1;
-			}
-		}
-		/*else*/ if (dstat & Iid) {
-			ulong addr = legetl(n->dsp);
-			ulong dbc = (n->dbc[2]<<16)|(n->dbc[1]<<8)|n->dbc[0];
-			IPRINT("sd53c8xx: %d/%d: Iid pa=%.8lux sa=%.8lux dbc=%lux\n",
-			    dsa->target, dsa->lun,
-			    addr, addr - c->scriptpa, dbc);
-			addr = (ulong)DMASEG_TO_KADDR(addr);
-			IPRINT("%.8lux %.8lux %.8lux\n",
-			    *(ulong *)(addr - 12), *(ulong *)(addr - 8), *(ulong *)(addr - 4));
-			USED(addr, dbc);
-			dsa->p9status = SDeio;
-			wakeme = 1;
-		}
-		/*else*/ if (dstat & Bf) {
-			IPRINT("sd53c8xx: %d/%d: Bus Fault\n", dsa->target, dsa->lun);
-			dumpncrregs(c, 1);
-			dsa->p9status = SDeio;
-			wakeme = 1;
-		}
-	}
-	if (cont == -2)
-		ncrcontinue(c);
-	else if (cont >= 0)
-		start(c, cont);
-	if (wakeme){
-		if(dsa->p9status == SDnostatus)
-			dsa->p9status = SDeio;
-		wakeup(dsa);
-	}
-	iunlock(c);
-	if (DEBUG(1)) {
-		IPRINT("sd53c8xx: int end 1\n");
-	}
-}
-
-static int
-done(void *arg)
-{
-	return ((Dsa *)arg)->p9status != SDnostatus;
-}
-
-static void
-setmovedata(Movedata *d, ulong pa, ulong bc)
-{
-	d->pa[0] = pa;
-	d->pa[1] = pa>>8;
-	d->pa[2] = pa>>16;
-	d->pa[3] = pa>>24;
-	d->dbc[0] = bc;
-	d->dbc[1] = bc>>8;
-	d->dbc[2] = bc>>16;
-	d->dbc[3] = bc>>24;
-}
-
-static void
-advancedata(Movedata *d, long v)
-{
-	lesetl(d->pa, legetl(d->pa) + v);
-	lesetl(d->dbc, legetl(d->dbc) - v);
-}
-
-static void
-dumpwritedata(uchar *data, int datalen)
-{
-	int i;
-	uchar *bp;
-	if (!DEBUG(0)){
-		USED(data, datalen);
-		return;
-	}
-
-	if (datalen) {
-		KPRINT("sd53c8xx:write:");
-		for (i = 0, bp = data; i < 50 && i < datalen; i++, bp++)
-			KPRINT("%.2ux", *bp);
-		if (i < datalen) {
-			KPRINT("...");
-		}
-		KPRINT("\n");
-	}
-}
-
-static void
-dumpreaddata(uchar *data, int datalen)
-{
-	int i;
-	uchar *bp;
-	if (!DEBUG(0)){
-		USED(data, datalen);
-		return;
-	}
-
-	if (datalen) {
-		KPRINT("sd53c8xx:read:");
-		for (i = 0, bp = data; i < 50 && i < datalen; i++, bp++)
-			KPRINT("%.2ux", *bp);
-		if (i < datalen) {
-			KPRINT("...");
-		}
-		KPRINT("\n");
-	}
-}
-
-static void
-busreset(Controller *c)
-{
-	int x, ntarget;
-
-	/* bus reset */
-	c->n->scntl1 |= (1 << 3);
-	delay(500);
-	c->n->scntl1 &= ~(1 << 3);
-	if(!(c->v->feature & Wide))
-		ntarget = 8;
-	else
-		ntarget = MAXTARGET;
-	for (x = 0; x < ntarget; x++) {
-		setwide(0, c, x, 0);
-#ifndef ASYNC_ONLY
-		c->s[x] = NeitherDone;
-#endif
-	}
-	c->capvalid = 0;
-}
-
-static void
-reset(Controller *c)
-{
-	/* should wakeup all pending tasks */
-	softreset(c);
-	busreset(c);
-}
-
-static int
-symrio(SDreq* r)
-{
-	Dsa *d;
-	uchar *bp;
-	Controller *c;
-	uchar target_expo, my_expo;
-	int bc, check, status, target;
-
-	if((target = r->unit->subno) == 0x07)
-		return r->status = SDtimeout;	/* assign */
-	c = r->unit->dev->ctlr;
-
-	check = 0;
-	d = dsaalloc(c, target, r->lun);
-
-	qlock(&c->q[target]);			/* obtain access to target */
-docheck:
-	/* load the transfer control stuff */
-	d->scsi_id_buf[0] = 0;
-	d->scsi_id_buf[1] = c->sxfer[target];
-	d->scsi_id_buf[2] = target;
-	d->scsi_id_buf[3] = c->scntl3[target];
-	synctodsa(d, c);
-
-	bc = 0;
-
-	d->msg_out[bc] = 0x80 | r->lun;
-
-#ifndef NO_DISCONNECT
-	d->msg_out[bc] |= (1 << 6);
-#endif
-	bc++;
-
-	/* work out what to do about negotiation */
-	switch (c->s[target]) {
-	default:
-		KPRINT("sd53c8xx: %d: strange nego state %d\n", target, c->s[target]);
-		c->s[target] = NeitherDone;
-		/* fall through */
-	case NeitherDone:
-		if ((c->capvalid & (1 << target)) == 0)
-			break;
-		target_expo = (c->cap[target] >> 5) & 3;
-		my_expo = (c->v->feature & Wide) != 0;
-		if (target_expo < my_expo)
-			my_expo = target_expo;
-#ifdef ALWAYS_DO_WDTR
-		bc += buildwdtrmsg(d->msg_out + bc, my_expo);
-		KPRINT("sd53c8xx: %d: WDTN: initiating expo %d\n", target, my_expo);
-		c->s[target] = WideInit;
-		break;
-#else
-		if (my_expo) {
-			bc += buildwdtrmsg(d->msg_out + bc, (c->v->feature & Wide) ? 1 : 0);
-			KPRINT("sd53c8xx: %d: WDTN: initiating expo %d\n", target, my_expo);
-			c->s[target] = WideInit;
-			break;
-		}
-		KPRINT("sd53c8xx: %d: WDTN: narrow\n", target);
-		/* fall through */
-#endif
-	case WideDone:
-		if (c->cap[target] & (1 << 4)) {
-			KPRINT("sd53c8xx: %d: SDTN: initiating %d %d\n", target, c->tpf, c->v->maxsyncoff);
-			bc += buildsdtrmsg(d->msg_out + bc, c->tpf, c->v->maxsyncoff);
-			c->s[target] = SyncInit;
-			break;
-		}
-		KPRINT("sd53c8xx: %d: SDTN: async only\n", target);
-		c->s[target] = BothDone;
-		break;
-
-	case BothDone:
-		break;
-	}
-
-	setmovedata(&d->msg_out_buf, DMASEG(d->msg_out), bc);
-	setmovedata(&d->cmd_buf, DMASEG(r->cmd), r->clen);
-	calcblockdma(d, DMASEG(r->data), r->dlen);
-
-	if (DEBUG(0)) {
-		KPRINT("sd53c8xx: %d/%d: exec: ", target, r->lun);
-		for (bp = r->cmd; bp < &r->cmd[r->clen]; bp++)
-			KPRINT("%.2ux", *bp);
-		KPRINT("\n");
-		if (!r->write)
-			KPRINT("sd53c8xx: %d/%d: exec: limit=(%d)%ld\n",
-			  target, r->lun, d->dmablks, legetl(d->data_buf.dbc));
-		else
-			dumpwritedata(r->data, r->dlen);
-	}
-
-	setmovedata(&d->status_buf, DMASEG(&d->status), 1);	
-
-	d->p9status = SDnostatus;
-	d->parityerror = 0;
-
-	d->stateb = A_STATE_ISSUE;		/* start operation */
-
-	ilock(c);
-	if (c->ssm)
-		c->n->dcntl |= 0x10;		/* SSI */
-	if (c->running) {
-		c->n->istat |= Sigp;
-	}
-	else {
-		start(c, E_issue_check);
-	}
-	iunlock(c);
-
-	while(waserror())
-		;
-	tsleep(d, done, d, 30 * 1000);
-	poperror();
-
-	if (!done(d)) {
-		KPRINT("sd53c8xx: %d/%d: exec: Timed out\n", target, r->lun);
-		dumpncrregs(c, 0);
-		dsafree(c, d);
-		reset(c);
-		qunlock(&c->q[target]);
-		r->status = SDtimeout;
-		return r->status = SDtimeout;	/* assign */
-	}
-
-	if((status = d->p9status) == SDeio)
-		c->s[target] = NeitherDone;
-	if (d->parityerror) {
-		status = SDeio;
-	}
-
-	/*
-	 * adjust datalen
-	 */
-	r->rlen = r->dlen;
-	if (d->dmablks > 0)
-		r->rlen -= d->dmablks * A_BSIZE;
-	else if (d->flag == 0)
-		r->rlen -= legetl(d->data_buf.dbc);
-	if(!r->write)
-		dumpreaddata(r->data, r->rlen);
-	if (DEBUG(0))
-		KPRINT("53c8xx: %d/%d: exec: p9status=%d status %d rlen %ld\n",
-		    target, r->lun, d->p9status, status, r->rlen);
-	/*
-	 * spot the identify
-	 */
-	if ((c->capvalid & (1 << target)) == 0
-	 && (status == SDok || status == SDcheck)
-	 && r->cmd[0] == 0x12 && r->dlen >= 8) {
-		c->capvalid |= 1 << target;
-		bp = r->data;
-		c->cap[target] = bp[7];
-		KPRINT("sd53c8xx: %d: capabilities %.2x\n", target, bp[7]);
-	}
-	if(!check && status == SDcheck && !(r->flags & SDnosense)){
-		check = 1;
-		r->write = 0;
-		memset(r->cmd, 0, sizeof(r->cmd));
-		r->cmd[0] = 0x03;
-		r->cmd[1] = r->lun<<5;
-		r->cmd[4] = sizeof(r->sense)-1;
-		r->clen = 6;
-		r->data = r->sense;
-		r->dlen = sizeof(r->sense)-1;
-		/*
-		 * Clear out the microcode state
-		 * so the Dsa can be re-used.
-		 */
-		lesetl(d->state, A_STATE_ALLOCATED);
-		goto docheck;
-	}
-	qunlock(&c->q[target]);
-	dsafree(c, d);
-
-	if(status == SDok && check){
-		status = SDcheck;
-		r->flags |= SDvalidsense;
-	}
-	KPRINT("sd53c8xx: %d: r flags %8.8uX status %d rlen %ld\n",
-		target, r->flags, status, r->rlen);
-	return r->status = status;
-}
-
-static void
-cribbios(Controller *c)
-{
-	c->bios.scntl3 = c->n->scntl3;
-	c->bios.stest2 = c->n->stest2;
-	print("sd53c8xx: bios scntl3(%.2x) stest2(%.2x)\n", c->bios.scntl3, c->bios.stest2);
-}
-
-static int
-bios_set_differential(Controller *c)
-{
-	/* Concept lifted from FreeBSD - thanks Gerard */
-	/* basically, if clock conversion factors are set, then there is
- 	 * evidence the bios had a go at the chip, and if so, it would
-	 * have set the differential enable bit in stest2
-	 */
-	return (c->bios.scntl3 & 7) != 0 && (c->bios.stest2 & 0x20) != 0;
-}
-
-#define NCR_VID 	0x1000
-#define NCR_810_DID 	0x0001
-#define NCR_820_DID	0x0002	/* don't know enough about this one to support it */
-#define NCR_825_DID	0x0003
-#define NCR_815_DID	0x0004
-#define SYM_810AP_DID	0x0005
-#define SYM_860_DID	0x0006
-#define SYM_896_DID	0x000b
-#define SYM_895_DID	0x000c
-#define SYM_885_DID	0x000d	/* ditto */
-#define SYM_875_DID	0x000f	/* ditto */
-#define SYM_1010_DID	0x0020
-#define SYM_1011_DID	0x0021
-#define SYM_875J_DID	0x008f
-
-static Variant variant[] = {
-{ NCR_810_DID,   0x0f, "NCR53C810",	Burst16,   8, 24, 0 },
-{ NCR_810_DID,   0x1f, "SYM53C810ALV",	Burst16,   8, 24, Prefetch },
-{ NCR_810_DID,   0xff, "SYM53C810A",	Burst16,   8, 24, Prefetch },
-{ SYM_810AP_DID, 0xff, "SYM53C810AP",	Burst16,   8, 24, Prefetch },
-{ NCR_815_DID,   0xff, "NCR53C815",	Burst16,   8, 24, BurstOpCodeFetch },
-{ NCR_825_DID,   0x0f, "NCR53C825",	Burst16,   8, 24, Wide|BurstOpCodeFetch|Differential },
-{ NCR_825_DID,   0xff, "SYM53C825A",	Burst128, 16, 24, Prefetch|LocalRAM|BigFifo|Differential|Wide },
-{ SYM_860_DID,   0x0f, "SYM53C860",	Burst16,   8, 24, Prefetch|Ultra },
-{ SYM_860_DID,   0xff, "SYM53C860LV",	Burst16,   8, 24, Prefetch|Ultra },
-{ SYM_875_DID,   0x01, "SYM53C875r1",	Burst128, 16, 24, Prefetch|LocalRAM|BigFifo|Differential|Wide|Ultra },
-{ SYM_875_DID,   0xff, "SYM53C875",	Burst128, 16, 24, Prefetch|LocalRAM|BigFifo|Differential|Wide|Ultra|ClockDouble },
-{ SYM_875J_DID,   0xff, "SYM53C875j",	Burst128, 16, 24, Prefetch|LocalRAM|BigFifo|Differential|Wide|Ultra|ClockDouble },
-{ SYM_885_DID,   0xff, "SYM53C885",	Burst128, 16, 24, Prefetch|LocalRAM|BigFifo|Wide|Ultra|ClockDouble },
-{ SYM_895_DID,   0xff, "SYM53C895",	Burst128, 16, 24, Prefetch|LocalRAM|BigFifo|Wide|Ultra|Ultra2 },
-{ SYM_896_DID,   0xff, "SYM53C896",	Burst128, 16, 64, Prefetch|LocalRAM|BigFifo|Wide|Ultra|Ultra2 },
-{ SYM_1010_DID,   0xff, "SYM53C1010",	Burst128, 16, 64, Prefetch|LocalRAM|BigFifo|Wide|Ultra|Ultra2 },
-{ SYM_1011_DID,   0xff, "SYM53C1010",	Burst128, 16, 64, Prefetch|LocalRAM|BigFifo|Wide|Ultra|Ultra2 },
-};
-
-
-static int
-xfunc(Controller *c, enum na_external x, unsigned long *v)
-{
-	switch (x) {
-	default:
-		print("xfunc: can't find external %d\n", x);
-		return 0;
-	case X_scsi_id_buf:
-		*v = offsetof(Dsa, scsi_id_buf[0]);
-		break;
-	case X_msg_out_buf:
-		*v = offsetof(Dsa, msg_out_buf);
-		break;
-	case X_cmd_buf:
-		*v = offsetof(Dsa, cmd_buf);
-		break;
-	case X_data_buf:
-		*v = offsetof(Dsa, data_buf);
-		break;
-	case X_status_buf:
-		*v = offsetof(Dsa, status_buf);
-		break;
-	case X_dsa_head:
-		*v = DMASEG(&c->dsalist.head[0]);
-		break;
-	}
-	return 1;
-}
-
-static int
-na_fixup(Controller *c, ulong pa_reg,
-    struct na_patch *patch, int patches,
-    int (*externval)(Controller*, int, ulong*))
-{
-	int p;
-	int v;
-	ulong *script, pa_script;
-	unsigned long lw, lv;
-
-	script = c->script;
-	pa_script = c->scriptpa;
-	for (p = 0; p < patches; p++) {
-		switch (patch[p].type) {
-		case 1:
-			/* script relative */
-			script[patch[p].lwoff] += pa_script;
-			break;
-		case 2:
-			/* register i/o relative */
-			script[patch[p].lwoff] += pa_reg;
-			break;
-		case 3:
-			/* data external */
-			lw = script[patch[p].lwoff];
-			v = (lw >> 8) & 0xff;
-			if (!(*externval)(c, v, &lv))
-				return 0;
-			v = lv & 0xff;
-			script[patch[p].lwoff] = (lw & 0xffff00ffL) | (v << 8);
-			break;
-		case 4:
-			/* 32 bit external */
-			lw = script[patch[p].lwoff];
-			if (!(*externval)(c, lw, &lv))
-				return 0;
-			script[patch[p].lwoff] = lv;
-			break;
-		case 5:
-			/* 24 bit external */
-			lw = script[patch[p].lwoff];
-			if (!(*externval)(c, lw & 0xffffff, &lv))
-				return 0;
-			script[patch[p].lwoff] = (lw & 0xff000000L) | (lv & 0xffffffL);
-			break;
-		}
-	}
-	return 1;
-}
-
-static SDev*
-sympnp(void)
-{
-	int ba;
-	Pcidev *p;
-	Variant *v;
-	void *scriptma;
-	Controller *ctlr;
-	SDev *sdev, *head, *tail;
-	ulong regpa, *script, scriptpa;
-
-	p = nil;
-	head = tail = nil;
-	while(p = pcimatch(p, NCR_VID, 0)){
-		for(v = variant; v < &variant[nelem(variant)]; v++){
-			if(p->did == v->did && p->rid <= v->maxrid)
-				break;
-		}
-		if(v >= &variant[nelem(variant)])
-			continue;
-		print("sd53c8xx: %s rev. 0x%2.2x intr=%d command=%4.4uX\n",
-			v->name, p->rid, p->intl, p->pcr);
-
-		regpa = p->mem[1].bar;
-		ba = 2;
-		if(regpa & 0x04){
-			if(p->mem[2].bar)
-				continue;
-			ba++;
-		}
-		regpa = upamalloc(regpa & ~0x0F, p->mem[1].size, 0);
-		if(regpa == 0)
-			continue;
-
-		script = nil;
-		scriptpa = 0;
-		scriptma = nil;
-		if((v->feature & LocalRAM) && sizeof(na_script) <= 4096){
-			scriptpa = p->mem[ba].bar;
-			if((scriptpa & 0x04) && p->mem[ba+1].bar){
-				upafree(regpa, p->mem[1].size);
-				continue;
-			}
-			scriptpa = upamalloc(scriptpa & ~0x0F,
-					p->mem[ba].size, 0);
-			if(scriptpa)
-				script = KADDR(scriptpa);
-		}
-		if(scriptpa == 0){
-			/*
-			 * Either the map failed, or this chip does not have
-			 * local RAM. It will need a copy of the microcode.
-			 */
-			scriptma = malloc(sizeof(na_script));
-			if(scriptma == nil){
-				upafree(regpa, p->mem[1].size);
-				continue;
-			}
-			scriptpa = DMASEG(scriptma);
-			script = scriptma;
-		}
-
-		ctlr = malloc(sizeof(Controller));
-		sdev = malloc(sizeof(SDev));
-		if(ctlr == nil || sdev == nil){
-buggery:
-			if(ctlr)
-				free(ctlr);
-			if(sdev)
-				free(sdev);
-			if(scriptma)
-				free(scriptma);
-			else
-				upafree(scriptpa, p->mem[ba].size);
-			upafree(regpa, p->mem[1].size);
-			continue;
-		}
-
-		ctlr->n = KADDR(regpa);
-		ctlr->v = v;
-		ctlr->script = script;
-		memmove(ctlr->script, na_script, sizeof(na_script));
-		ctlr->scriptpa = scriptpa;
-		if(!na_fixup(ctlr, regpa, na_patches, NA_PATCHES, xfunc)){
-			print("script fixup failed\n");
-			goto buggery;
-		}
-		swabl(ctlr->script, ctlr->script, sizeof(na_script));
-
-		ctlr->dsalist.freechain = 0;
-		lesetl(ctlr->dsalist.head, 0);
-
-		ctlr->pcidev = p;
-
-		sdev->ifc = &sd53c8xxifc;
-		sdev->ctlr = ctlr;
-		if(!(v->feature & Wide))
-			sdev->nunit = 8;
-		else
-			sdev->nunit = MAXTARGET;
-		ctlr->sdev = sdev;
-
-		if(head != nil)
-			tail->next = sdev;
-		else
-			head = sdev;
-		tail = sdev;
-	}
-
-	return head;
-}
-
-static SDev*
-symid(SDev* sdev)
-{
-	return scsiid(sdev, &sd53c8xxifc);
-}
-
-static int
-symenable(SDev* sdev)
-{
-	Pcidev *pcidev;
-	Controller *ctlr;
-	//char name[NAMELEN];
-
-	ctlr = sdev->ctlr;
-	pcidev = ctlr->pcidev;
-
-	pcisetbme(pcidev);
-	//snprint(name, NAMELEN, "%s (%s)", sdev->name, sdev->ifc->name);
-	intrenable(pcidev->intl, interrupt, ctlr, pcidev->tbdf, name);
-
-	ilock(ctlr);
-	synctabinit(ctlr);
-	cribbios(ctlr);
-	reset(ctlr);
-	iunlock(ctlr);
-
-	return 1;
-}
-
-static int
-symdisable(SDev* sdev)
-{
-	Ncr *n;
-	Controller *ctlr;
-
-	ctlr = sdev->ctlr;
-	n = ctlr->n;
-
-	n->istat = Srst;		/* software reset */
-	microdelay(1);
-	n->istat = 0;
-
-	n->scntl1 |= (1 << 3);		/* bus reset */
-	delay(500);
-	n->scntl1 &= ~(1 << 3);
-
-	return 1;
-}
-
-SDifc sd53c8xxifc = {
-	"53c8xx",			/* name */
-
-	sympnp,				/* pnp */
-	nil,				/* legacy */
-	symid,				/* id */
-	symenable,			/* enable */
-	symdisable,			/* disable */
-
-	scsiverify,			/* verify */
-	scsionline,			/* online */
-	symrio,				/* rio */
-	nil,				/* rctl */
-	nil,				/* wctl */
-
-	scsibio,			/* bio */
-};
--- a/os/boot/pc/sd53c8xx.i
+++ /dev/null
@@ -1,769 +1,0 @@
-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 */
-			/*	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 */ 0x78370100L, /*		move	1 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 */ 0x78370100L, /*		move	1 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 */ 0x740a0f00L, /*		move	ssid & 15 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 */
-	{ 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 79
-
-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,
-};
-
-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_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
--- a/os/boot/pc/sdaoe.c
+++ /dev/null
@@ -1,733 +1,0 @@
-/*
- * aoe sd bootstrap driver, copyright © 2007 coraid
- */
-
-#include "u.h"
-#include "mem.h"
-#include "lib.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-#include "sd.h"
-#include "aoe.h"
-
-
-enum {
-	Nctlr	= 4,
-};
-
-enum {
-	/* sync with ahci.h */
-	Dllba 	= 1<<0,
-	Dsmart	= 1<<1,
-	Dpower	= 1<<2,
-	Dnop	= 1<<3,
-	Datapi	= 1<<4,
-	Datapi16= 1<<5,
-};
-
-enum {
-	Tfree	= -1,
-	Tmgmt,
-};
-
-typedef struct Ctlr Ctlr;
-struct Ctlr{
-	Ctlr	*next;
-	SDunit	*unit;
-
-	int	ctlrno;
-	int	major;
-	int	minor;
-	uchar	ea[Eaddrlen];
-	ushort	lasttag;
-
-	ulong	vers;
-	uchar	mediachange;
-	uchar	flag;
-	uchar	smart;
-	uchar	smartrs;
-	uchar	feat;
-
-	uvlong	sectors;
-	char	serial[20+1];
-	char	firmware[8+1];
-	char	model[40+1];
-	char	ident[0x100];
-};
-
-static	Ctlr	*head;
-static	Ctlr	*tail;
-
-static	int	aoeether[10];
-
-SDifc sdaoeifc;
-
-static void
-hnputs(uchar *p, ushort i)
-{
-	p[0] = i >> 8;
-	p[1] = i;
-}
-
-static void
-hnputl(uchar *p, ulong i)
-{
-	p[0] = i >> 24;
-	p[1] = i >> 16;
-	p[2] = i >> 8;
-	p[3] = i;
-}
-
-static ushort
-nhgets(uchar *p)
-{
-	return *p<<8 | p[1];
-}
-
-static ulong
-nhgetl(uchar *p)
-{
-	return p[0]<<24 | p[1]<<16 | p[2]<<8 | p[3];
-}
-
-static int
-newtag(Ctlr *d)
-{
-	int t;
-
-	for(;;){
-		t = ++d->lasttag << 16;
-		t |= m->ticks & 0xffff;
-		switch(t) {
-		case Tfree:
-		case Tmgmt:
-			break;
-		default:
-			return t;
-		}
-	}
-}
-
-static int
-hset(Ctlr *d, Aoehdr *h, int cmd)
-{
-	int tag;
-
-	memmove(h->dst, d->ea, Eaddrlen);
-	hnputs(h->type, Aoetype);
-	h->verflag = Aoever << 4;
-	hnputs(h->major, d->major);
-	h->minor = d->minor;
-	h->cmd = cmd;
-	hnputl(h->tag, tag = newtag(d));
-	return tag;
-}
-
-static void
-idmove(char *p, ushort *a, int n)
-{
-	int i;
-	char *op, *e;
-
-	op = p;
-	for(i = 0; i < n / 2; i++){
-		*p++ = a[i] >> 8;
-		*p++ = a[i];
-	}
-	*p = 0;
-	while(p > op && *--p == ' ')
-		*p = 0;
-	e = p;
-	p = op;
-	while(*p == ' ')
-		p++;
-	memmove(op, p, n - (e - p));
-}
-
-static ushort
-gbit16(void *a)
-{
-	uchar *i;
-
-	i = a;
-	return i[1]<<8 | i[0];
-}
-
-static ulong
-gbit32(void *a)
-{
-	uchar *i;
-	ulong j;
-
-	i = a;
-	j  = i[3] << 24;
-	j |= i[2] << 16;
-	j |= i[1] << 8;
-	j |= i[0];
-	return j;
-}
-
-static uvlong
-gbit64(void *a)
-{
-	uchar *i;
-
-	i = a;
-	return (uvlong)gbit32(i+4) << 32 | gbit32(a);
-}
-
-static int
-ataidentify(Ctlr *c, ushort *id)
-{
-	vlong s;
-	int i;
-
-	i = gbit16(id+83) | gbit16(id+86);
-	if(i & (1 << 10)){
-		c->feat |= Dllba;
-		s = gbit64(id+100);
-	}else
-		s = gbit32(id+60);
-
-	idmove(c->serial, id+10, 20);
-	idmove(c->firmware, id+23, 8);
-	idmove(c->model, id+27, 40);
-
-print("aoe discovers %d.%d: %s %s\n", c->major, c->minor, c->model, c->serial);
-
-	c->sectors = s;
-	c->mediachange = 1;
-	return 0;
-}
-
-static void
-identifydump(Aoeata *a)
-{
-	print("%E %E type=%.4ux verflag=%x error=%x %d.%d cmd=%d tag=%.8lux\n",
-		a->dst, a->src, nhgets(a->type), a->verflag, a->error,
-		nhgets(a->major), a->minor, a->cmd, nhgetl(a->tag));
-	print("   aflag=%x errfeat=%ux scnt=%d cmdstat=%ux, lba=%d? res=%.4ux\n",
-		a->aflag, a->errfeat, a->scnt, a->cmdstat, 0, nhgets(a->res));
-}
-
-static int
-idpkt(Ctlr *c, Aoeata *a)
-{
-	memset(a, 0, sizeof *a);
-	a->cmdstat = Cid;
-	a->scnt = 1;
-	a->lba[3] = 0xa0;
-	return hset(c, a, ACata);
-}
-
-static int
-chktag(int *out, int nout, int tag)
-{
-	int j;
-
-	for(j = 0; j <= nout; j++)
-		if(out[j] == tag)
-			return 0;
-print("wrong tag\n");
-	for(j = 0; j <= nout; j++)
-		print("%.8ux != %.8ux\n", out[j], tag);
-	return -1;
-}
-
-/*
- * ignore the tag for identify.  better than ignoring
- * a response to the wrong identify request
- */
-static int
-identify(Ctlr *c)
-{
-	int tag[5], i, n;
-	Aoeata *a;
-	Etherpkt p;
-
-	memset(&p, 0, sizeof p);
-	a = (Aoeata*)&p;
-	i = 0;
-	do {
-		if(i == 5){
-			print("aoe: identify timeout\n");
-			return -1;
-		}
-		tag[i] = idpkt(c, a);
-		ethertxpkt(c->ctlrno, &p, sizeof *a, 0);
-		memset(&p, 0, sizeof p);
-next:
-		n = etherrxpkt(c->ctlrno, &p, 125);
-		if(n == 0){
-			i++;
-			continue;
-		}
-		if(nhgets(a->type) != Aoetype)
-			goto next;
-		if(nhgets(a->major) != c->major || a->minor != c->minor){
-			print("wrong device %d.%d want %d.%d; %d\n",
-				nhgets(a->major), a->minor,
-				c->major, c->minor, n);
-			goto next;
-		}
-		if(chktag(tag, i, nhgetl(a->tag)) == -1)
-			goto next;
-		if(a->cmdstat & 0xa9){
-			print("aoe: ata error on identify: %2ux\n", a->cmdstat);
-			return -1;
-		}
-	} while (a->scnt != 1);
-
-	c->feat = 0;
-	ataidentify(c, (ushort*)(a+1));
-	return 0;
-}
-
-static Ctlr*
-ctlrlookup(int major, int minor)
-{
-	Ctlr *c;
-
-	for(c = head; c; c = c->next)
-		if(c->major == major && c->minor == minor)
-			break;
-	return c;
-}
-
-static Ctlr*
-newctlr(Etherpkt *p)
-{
-	int major, minor;
-	Aoeqc *q;
-	Ctlr *c;
-
-	q = (Aoeqc*)p;
-	if(nhgets(q->type) != Aoetype)
-		return 0;
-	major = nhgets(q->major);
-	minor = q->minor;
-
-	if(major == 0xffff || minor == 0xff)
-		return 0;
-
-	if(ctlrlookup(major, minor)){
-		print("duplicate shelf.slot\n");
-		return 0;
-	}
-
-	if((c = malloc(sizeof *c)) == 0)
-		return 0;
-	c->major = major;
-	c->minor = minor;
-	memmove(c->ea, q->src, Eaddrlen);
-
-	if(head != 0)
-		tail->next = c;
-	else
-		head = c;
-	tail = c;
-	return c;
-}
-
-static void
-discover(int major, int minor)
-{
-	int i;
-	Aoehdr *h;
-	Etherpkt p;
-
-	for(i = 0; i < nelem(aoeether); i++){
-		if(aoeether[i] == 0)
-			continue;
-		memset(&p, 0, ETHERMINTU);
-		h = (Aoehdr*)&p;
-		memset(h->dst, 0xff, sizeof h->dst);
-		hnputs(h->type, Aoetype);
-		h->verflag = Aoever << 4;
-		hnputs(h->major, major);
-		h->minor = minor;
-		h->cmd = ACconfig;
-		ethertxpkt(i, &p, ETHERMINTU, 0);
-	}
-}
-
-static int
-rxany(Etherpkt *p, int t)
-{
-	int i, n;
-
-	for(i = 0; i < nelem(aoeether); i++){
-		if(aoeether[i] == 0)
-			continue;
-		while ((n = etherrxpkt(i, p, t)) != 0)
-			if(nhgets(p->type) == Aoetype)
-				return n;
-	}
-	return 0;
-}
-
-static int
-aoeprobe(int major, int minor, SDev *s)
-{
-	Ctlr *ctlr;
-	Etherpkt p;
-	int n, i;
-
-	for(i = 0;; i += 200){
-		if(i > 8000)
-			return -1;
-		discover(major, minor);
-again:
-		n = rxany(&p, 100);
-		if(n > 0 && (ctlr = newctlr(&p)))
-			break;
-		if(n > 0)
-			goto again;
-	}
-
-	s->ctlr = ctlr;
-	s->ifc = &sdaoeifc;
-	s->nunit = 1;
-	return 0;
-}
-
-static char 	*probef[32];
-static int 	nprobe;
-
-int
-pnpprobeid(char *s)
-{
-	int id;
-
-	if(strlen(s) < 2)
-		return 0;
-	id = 'e';
-	if(s[1] == '!')
-		id = s[0];
-	return id;
-}
-
-int
-tokenize(char *s, char **args, int maxargs)
-{
-	int nargs;
-
-	for(nargs = 0; nargs < maxargs; nargs++){
-		while(*s != '\0' && strchr("\t\n ", *s) != nil)
-			s++;
-		if(*s == '\0')
-			break;
-		args[nargs] = s;
-		while(*s != '\0' && strchr("\t\n ", *s) == nil)
-			s++;
-		if(*s != '\0')
-			*s++ = 0;
-	}
-	return nargs;
-}
-
-int
-aoepnp0(void)
-{
-	int i;
-	char *p, c;
-
-	if((p = getconf("aoeif")) == nil)
-		return 0;
-print("aoeif = %s\n", p);
-	nprobe = tokenize(p, probef, nelem(probef));
-	for(i = 0; i < nprobe; i++){
-		if(strncmp(probef[i], "ether", 5) != 0)
-			continue;
-		c = probef[i][5];
-		if(c > '9' || c < '0')
-			continue;
-		aoeether[c - '0'] = 1;
-	}
-
-	if((p = getconf("aoedev")) == nil)
-		return 0;
-	return nprobe = tokenize(p, probef, nelem(probef));
-}
-
-int
-probeshelf(char *s, int *shelf, int *slot)
-{
-	int a, b;
-	char *r;
-
-	for(r = s + strlen(s) - 1; r > s; r--)
-		if((*r < '0' || *r > '9') && *r != '.'){
-			r++;
-			break;
-		}
-	a = strtoul(r, &r, 10);
-	if(*r++ != '.')
-		return -1;
-	b = strtoul(r, 0, 10);
-
-	*shelf = a;
-	*slot = b;
-print("  shelf=%d.%d\n", a, b);
-	return 0;
-}
-
-Ctlr*
-pnpprobe(SDev *sd)
-{
-	int shelf, slot;
-	char *p;
-	static int i;
-
-	if(i >= nprobe)
-		return 0;
-	p = probef[i++];
-	if(strlen(p) < 2)
-		return 0;
-	if(p[1] == '!'){
-		sd->idno = p[0];
-		p += 2;
-	}
-	if(probeshelf(p, &shelf, &slot) == -1 ||
-	    aoeprobe(shelf, slot, sd) == -1 ||
-	    identify(sd->ctlr) == -1)
-		return 0;
-	return sd->ctlr;
-}
-
-/*
- * we may need to pretend we found something
- */
-
-SDev*
-aoepnp(void)
-{
-	int n, i, id;
-	char *p;
-	SDev *h, *t, *s;
-
-	p = getconf("aoeif");
-	if (p)
-		print("aoepnp: aoeif=%s\n", p);
-
-	if((n = aoepnp0()) == 0)
-		n = 2;
-	t = h = 0;
-	for(i = 0; i < n; i++){
-		id = 'e';
-		s = malloc(sizeof *s);
-		if(s == 0)
-			break;
-		s->ctlr = 0;
-		s->idno = id;
-		s->ifc = &sdaoeifc;
-		s->nunit = 1;
-		pnpprobe(s);
-
-		if(h)
-			t->next = s;
-		else
-			h = s;
-		t = s;
-	}
-	return h;
-}
-
-static int
-aoeverify(SDunit *u)
-{
-	Ctlr *c;
-	SDev *s;
-
-	s = u->dev;
-	c = s->ctlr;
-	if(c == 0){
-		aoepnp0();
-		if((s->ctlr = c = pnpprobe(s)) == nil)
-			return 0;
-	}
-	c->mediachange = 1;
-	return 1;
-}
-
-static int
-aoeonline(SDunit *u)
-{
-	int r;
-	Ctlr *c;
-
-	c = u->dev->ctlr;
-	if(c->mediachange){
-		r = 2;
-		c->mediachange = 0;
-		u->sectors = c->sectors;
-		u->secsize = 512;
-	} else
-		r = 1;
-	return r;
-}
-
-static int
-rio(Ctlr *c, Aoeata *a, int n, int scnt)
-{
-	int i, tag, cmd;
-
-	for(i = 0; i < 5; i++){
-		tag = hset(c, a, ACata);
-		cmd = a->cmdstat;
-		ethertxpkt(c->ctlrno, (Etherpkt*)a, n, 0);
-		memset(a, 0, sizeof *a);
-again:
-		n = etherrxpkt(c->ctlrno, (Etherpkt*)a, 125);
-		if(n == 0)
-			continue;
-		if(nhgets(a->type) != Aoetype || nhgetl(a->tag) != tag ||
-		    nhgets(a->major) != c->major || a->minor != c->minor)
-			goto again;
-		if(a->cmdstat & 0xa9){
-			print("aoe: ata rio error: %2ux\n", a->cmdstat);
-			return 0;
-		}
-		switch(cmd){
-		case Crd:
-		case Crdext:
-			if(n - sizeof *a < scnt * 512){
-				print("aoe: runt expect %d got %d\n",
-					scnt*512 + sizeof *a, n);
-				return 0;
-			}
-			return n - sizeof *a;
-		case Cwr:
-		case Cwrext:
-			return scnt * 512;
-		default:
-print("unknown cmd %ux\n", cmd);
-			break;
-		}
-	}
-	print("aoe: rio timeout\n");
-	return 0;
-}
-
-static void
-putlba(Aoeata *a, vlong lba)
-{
-	uchar *c;
-
-	c = a->lba;
-	c[0] = lba;
-	c[1] = lba >> 8;
-	c[2] = lba >> 16;
-	c[3] = lba >> 24;
-	c[4] = lba >> 32;
-	c[5] = lba >> 40;
-}
-
-/*
- * you'll need to loop if you want to read more than 2 sectors.  for now
- * i'm cheeting and not bothering with a loop.
- */
-static uchar pktbuf[1024 + sizeof(Aoeata)];
-
-static int
-aoebuild(Ctlr *c, uchar *cmd, char *data, vlong lba, int scnt)
-{
-	int n;
-	Aoeata *a;
-
-	memset(pktbuf, 0, sizeof pktbuf);
-	a = (Aoeata*)pktbuf;
-	hset(c, a, ACata);
-	putlba(a, lba);
-
-	a->cmdstat = 0x20;
-	if(c->flag & Dllba){
-		a->aflag |= AAFext;
-		a->cmdstat |= 4;
-	}else{
-		a->lba[3] &= 0xf;
-		a->lba[3] |= 0xe0;		/* LBA bit+obsolete 0xa0 */
-	}
-
-	n = scnt;
-	if(n > 2)
-		n = 2;
-	a->scnt = n;
-
-	switch(*cmd){
-	case 0x2a:
-		a->aflag |= AAFwrite;
-		a->cmdstat |= 10;
-		memmove(a+1, data, n*512);
-		n = sizeof *a + n*512;
-		break;
-	case 0x28:
-		n = sizeof *a;
-		break;
-	default:
-		print("aoe: bad cmd 0x%.2ux\n", cmd[0]);
-		return -1;
-	}
-	return n;
-}
-
-static int
-aoerio(SDreq *r)
-{
-	int size, nsec, n;
-	vlong lba;
-	char *data;
-	uchar *cmd;
-	Aoeata *a;
-	Ctlr *c;
-	SDunit *unit;
-
-	unit = r->unit;
-	c = unit->dev->ctlr;
-	if(r->data == nil)
-		return SDok;
-	cmd = r->cmd;
-
-	lba = cmd[2]<<24 | cmd[3]<<16 | cmd[4]<<8 | cmd[5];	/* sic. */
-	nsec = cmd[7]<<8 | cmd[8];
-	a = (Aoeata*)pktbuf;
-	data = r->data;
-	r->rlen = 0;
-
-	for(; nsec > 0; nsec -= n){
-//		print("aoebuild(%2x, %p, %lld, %d)\n", *cmd, data, lba, nsec);
-		size = aoebuild(c, cmd, data, lba, nsec);
-		if(size < 0){
-			r->status = SDcheck;
-			return SDcheck;
-		}
-		n = a->scnt;
-		r->rlen += rio(c, a, size, n);
-		if(*cmd == 0x28)
-			memmove(r->data, a + 1, n * 512);
-		data += n * 512;
-		lba += n;
-	}
-
-	r->status = SDok;
-	return SDok;
-}
-
-SDifc sdaoeifc = {
-	"aoe",
-
-	aoepnp,
-	nil,		/* legacy */
-	nil,		/* id */
-	nil,		/* enable */
-	nil,		/* disable */
-
-	aoeverify,
-	aoeonline,
-	aoerio,
-	nil,
-	nil,
-
-	scsibio,
-};
--- a/os/boot/pc/sdata.c
+++ /dev/null
@@ -1,1652 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-#include "ureg.h"
-#include "error.h"
-
-#include "sd.h"
-
-extern SDifc sdataifc;
-
-enum {
-	DbgCONFIG	= 0x0001,	/* detected drive config info */
-	DbgIDENTIFY	= 0x0002,	/* detected drive identify info */
-	DbgSTATE	= 0x0004,	/* dump state on panic */
-	DbgPROBE	= 0x0008,	/* trace device probing */
-	DbgDEBUG	= 0x0080,	/* the current problem... */
-	DbgINL		= 0x0100,	/* That Inil20+ message we hate */
-	Dbg48BIT	= 0x0200,	/* 48-bit LBA */
-	DbgBsy		= 0x0400,	/* interrupt but Bsy (shared IRQ) */
-};
-#define DEBUG		(DbgDEBUG|DbgCONFIG)
-
-enum {					/* I/O ports */
-	Data		= 0,
-	Error		= 1,		/* (read) */
-	Features	= 1,		/* (write) */
-	Count		= 2,		/* sector count<7-0>, sector count<15-8> */
-	Ir		= 2,		/* interrupt reason (PACKET) */
-	Sector		= 3,		/* sector number */
-	Lbalo		= 3,		/* LBA<7-0>, LBA<31-24> */
-	Cyllo		= 4,		/* cylinder low */
-	Bytelo		= 4,		/* byte count low (PACKET) */
-	Lbamid		= 4,		/* LBA<15-8>, LBA<39-32> */
-	Cylhi		= 5,		/* cylinder high */
-	Bytehi		= 5,		/* byte count hi (PACKET) */
-	Lbahi		= 5,		/* LBA<23-16>, LBA<47-40> */
-	Dh		= 6,		/* Device/Head, LBA<32-14> */
-	Status		= 7,		/* (read) */
-	Command		= 7,		/* (write) */
-
-	As		= 2,		/* Alternate Status (read) */
-	Dc		= 2,		/* Device Control (write) */
-};
-
-enum {					/* Error */
-	Med		= 0x01,		/* Media error */
-	Ili		= 0x01,		/* command set specific (PACKET) */
-	Nm		= 0x02,		/* No Media */
-	Eom		= 0x02,		/* command set specific (PACKET) */
-	Abrt		= 0x04,		/* Aborted command */
-	Mcr		= 0x08,		/* Media Change Request */
-	Idnf		= 0x10,		/* no user-accessible address */
-	Mc		= 0x20,		/* Media Change */
-	Unc		= 0x40,		/* Uncorrectable data error */
-	Wp		= 0x40,		/* Write Protect */
-	Icrc		= 0x80,		/* Interface CRC error */
-};
-
-enum {					/* Features */
-	Dma		= 0x01,		/* data transfer via DMA (PACKET) */
-	Ovl		= 0x02,		/* command overlapped (PACKET) */
-};
-
-enum {					/* Interrupt Reason */
-	Cd		= 0x01,		/* Command/Data */
-	Io		= 0x02,		/* I/O direction */
-	Rel		= 0x04,		/* Bus Release */
-};
-
-enum {					/* Device/Head */
-	Dev0		= 0xA0,		/* Master */
-	Dev1		= 0xB0,		/* Slave */
-	Lba		= 0x40,		/* LBA mode */
-};
-
-enum {					/* Status, Alternate Status */
-	Err		= 0x01,		/* Error */
-	Chk		= 0x01,		/* Check error (PACKET) */
-	Drq		= 0x08,		/* Data Request */
-	Dsc		= 0x10,		/* Device Seek Complete */
-	Serv		= 0x10,		/* Service */
-	Df		= 0x20,		/* Device Fault */
-	Dmrd		= 0x20,		/* DMA ready (PACKET) */
-	Drdy		= 0x40,		/* Device Ready */
-	Bsy		= 0x80,		/* Busy */
-};
-
-enum {					/* Command */
-	Cnop		= 0x00,		/* NOP */
-	Cdr		= 0x08,		/* Device Reset */
-	Crs		= 0x20,		/* Read Sectors */
-	Crs48		= 0x24,		/* Read Sectors Ext */
-	Crd48		= 0x25,		/* Read w/ DMA Ext */
-	Crdq48		= 0x26,		/* Read w/ DMA Queued Ext */
-	Crsm48		= 0x29,		/* Read Multiple Ext */
-	Cws		= 0x30,		/* Write Sectors */
-	Cws48		= 0x34,		/* Write Sectors Ext */
-	Cwd48		= 0x35,		/* Write w/ DMA Ext */
-	Cwdq48		= 0x36,		/* Write w/ DMA Queued Ext */
-	Cwsm48		= 0x39,		/* Write Multiple Ext */
-	Cedd		= 0x90,		/* Execute Device Diagnostics */
-	Cpkt		= 0xA0,		/* Packet */
-	Cidpkt		= 0xA1,		/* Identify Packet Device */
-	Crsm		= 0xC4,		/* Read Multiple */
-	Cwsm		= 0xC5,		/* Write Multiple */
-	Csm		= 0xC6,		/* Set Multiple */
-	Crdq		= 0xC7,		/* Read DMA queued */
-	Crd		= 0xC8,		/* Read DMA */
-	Cwd		= 0xCA,		/* Write DMA */
-	Cwdq		= 0xCC,		/* Write DMA queued */
-	Cstandby	= 0xE2,		/* Standby */
-	Cid		= 0xEC,		/* Identify Device */
-	Csf		= 0xEF,		/* Set Features */
-};
-
-enum {					/* Device Control */
-	Nien		= 0x02,		/* (not) Interrupt Enable */
-	Srst		= 0x04,		/* Software Reset */
-};
-
-enum {					/* PCI Configuration Registers */
-	Bmiba		= 0x20,		/* Bus Master Interface Base Address */
-	Idetim		= 0x40,		/* IE Timing */
-	Sidetim		= 0x44,		/* Slave IE Timing */
-	Udmactl		= 0x48,		/* Ultra DMA/33 Control */
-	Udmatim		= 0x4A,		/* Ultra DMA/33 Timing */
-};
-
-enum {					/* Bus Master IDE I/O Ports */
-	Bmicx		= 0,		/* Command */
-	Bmisx		= 2,		/* Status */
-	Bmidtpx		= 4,		/* Descriptor Table Pointer */
-};
-
-enum {					/* Bmicx */
-	Ssbm		= 0x01,		/* Start/Stop Bus Master */
-	Rwcon		= 0x08,		/* Read/Write Control */
-};
-
-enum {					/* Bmisx */
-	Bmidea		= 0x01,		/* Bus Master IDE Active */
-	Idedmae		= 0x02,		/* IDE DMA Error  (R/WC) */
-	Ideints		= 0x04,		/* IDE Interrupt Status (R/WC) */
-	Dma0cap		= 0x20,		/* Drive 0 DMA Capable */
-	Dma1cap		= 0x40,		/* Drive 0 DMA Capable */
-};
-enum {					/* Physical Region Descriptor */
-	PrdEOT		= 0x80000000,	/* Bus Master IDE Active */
-};
-
-enum {					/* offsets into the identify info. */
-	Iconfig		= 0,		/* general configuration */
-	Ilcyl		= 1,		/* logical cylinders */
-	Ilhead		= 3,		/* logical heads */
-	Ilsec		= 6,		/* logical sectors per logical track */
-	Iserial		= 10,		/* serial number */
-	Ifirmware	= 23,		/* firmware revision */
-	Imodel		= 27,		/* model number */
-	Imaxrwm		= 47,		/* max. read/write multiple sectors */
-	Icapabilities	= 49,		/* capabilities */
-	Istandby	= 50,		/* device specific standby timer */
-	Ipiomode	= 51,		/* PIO data transfer mode number */
-	Ivalid		= 53,
-	Iccyl		= 54,		/* cylinders if (valid&0x01) */
-	Ichead		= 55,		/* heads if (valid&0x01) */
-	Icsec		= 56,		/* sectors if (valid&0x01) */
-	Iccap		= 57,		/* capacity if (valid&0x01) */
-	Irwm		= 59,		/* read/write multiple */
-	Ilba		= 60,		/* LBA size */
-	Imwdma		= 63,		/* multiword DMA mode */
-	Iapiomode	= 64,		/* advanced PIO modes supported */
-	Iminmwdma	= 65,		/* min. multiword DMA cycle time */
-	Irecmwdma	= 66,		/* rec. multiword DMA cycle time */
-	Iminpio		= 67,		/* min. PIO cycle w/o flow control */
-	Iminiordy	= 68,		/* min. PIO cycle with IORDY */
-	Ipcktbr		= 71,		/* time from PACKET to bus release */
-	Iserbsy		= 72,		/* time from SERVICE to !Bsy */
-	Iqdepth		= 75,		/* max. queue depth */
-	Imajor		= 80,		/* major version number */
-	Iminor		= 81,		/* minor version number */
-	Icsfs		= 82,		/* command set/feature supported */
-	Icsfe		= 85,		/* command set/feature enabled */
-	Iudma		= 88,		/* ultra DMA mode */
-	Ierase		= 89,		/* time for security erase */
-	Ieerase		= 90,		/* time for enhanced security erase */
-	Ipower		= 91,		/* current advanced power management */
-	Ilba48		= 100,		/* 48-bit LBA size (64 bits in 100-103) */
-	Irmsn		= 127,		/* removable status notification */
-	Isecstat	= 128,		/* security status */
-};
-
-typedef struct Ctlr Ctlr;
-typedef struct Drive Drive;
-
-typedef struct Prd {
-	ulong	pa;			/* Physical Base Address */
-	int	count;
-} Prd;
-
-enum {
-	Nprd		= SDmaxio/(64*1024)+2,
-};
-
-typedef struct Ctlr {
-	int	cmdport;
-	int	ctlport;
-	int	irq;
-	int	tbdf;
-
-	Pcidev*	pcidev;
-	void	(*ienable)(Ctlr*);
-	SDev*	sdev;
-
-	Drive*	drive[2];
-
-	Prd*	prdt;			/* physical region descriptor table */
-
-//	QLock;				/* current command */
-	Drive*	curdrive;
-	int	command;		/* last command issued (debugging) */
-//	Rendez;
-	int	done;
-
-	Lock;				/* register access */
-} Ctlr;
-
-typedef struct Drive {
-	Ctlr*	ctlr;
-
-	int	dev;
-	ushort	info[256];
-	int	c;			/* cylinder */
-	int	h;			/* head */
-	int	s;			/* sector */
-	vlong	sectors;		/* total */
-	int	secsize;		/* sector size */
-
-//	int	dma;			/* DMA R/W possible */
-//	int	dmactl;
-//	int	rwm;			/* read/write multiple possible */
-//	int	rwmctl;
-
-	int	pkt;			/* PACKET device, length of pktcmd */
-	uchar	pktcmd[16];
-//	int	pktdma;			/* this PACKET command using dma */
-
-	uchar	sense[18];
-	uchar	inquiry[48];
-
-//	QLock;				/* drive access */
-	int	command;		/* current command */
-	int	write;
-	uchar*	data;
-	int	dlen;
-	uchar*	limit;
-	int	count;			/* sectors */
-	int	block;			/* R/W bytes per block */
-	int	status;
-	int	error;
-	int	flags;			/* internal flags */
-} Drive;
-
-enum {					/* internal flags */
-	Lba48		= 0x1,		/* LBA48 mode */
-	Lba48always	= 0x2,		/* ... */
-};
-
-static void
-pc87415ienable(Ctlr* ctlr)
-{
-	Pcidev *p;
-	int x;
-
-	p = ctlr->pcidev;
-	if(p == nil)
-		return;
-
-	x = pcicfgr32(p, 0x40);
-	if(ctlr->cmdport == p->mem[0].bar)
-		x &= ~0x00000100;
-	else
-		x &= ~0x00000200;
-	pcicfgw32(p, 0x40, x);
-}
-
-static int
-atadebug(int cmdport, int ctlport, char* fmt, ...)
-{
-	int i, n;
-	va_list arg;
-	char buf[PRINTSIZE];
-
-	if(!(DEBUG & DbgPROBE)){
-		USED(cmdport, ctlport, fmt);
-		return 0;
-	}
-
-	va_start(arg, fmt);
-	n = vseprint(buf, buf+sizeof(buf), fmt, arg) - buf;
-	va_end(arg);
-
-	if(cmdport){
-		if(buf[n-1] == '\n')
-			n--;
-		n += snprint(buf+n, PRINTSIZE-n, " ataregs 0x%uX:",
-			cmdport);
-		for(i = Features; i < Command; i++)
-			n += snprint(buf+n, PRINTSIZE-n, " 0x%2.2uX",
-				inb(cmdport+i));
-		if(ctlport)
-			n += snprint(buf+n, PRINTSIZE-n, " 0x%2.2uX",
-				inb(ctlport+As));
-		n += snprint(buf+n, PRINTSIZE-n, "\n");
-	}
-	putstrn(buf, n);
-
-	return n;
-}
-
-static int
-ataready(int cmdport, int ctlport, int dev, int reset, int ready, int micro)
-{
-	int as;
-
-	atadebug(cmdport, ctlport, "ataready: dev %uX reset %uX ready %uX",
-		dev, reset, ready);
-
-	for(;;){
-		/*
-		 * Wait for the controller to become not busy and
-		 * possibly for a status bit to become true (usually
-		 * Drdy). Must change to the appropriate device
-		 * register set if necessary before testing for ready.
-		 * Always run through the loop at least once so it
-		 * can be used as a test for !Bsy.
-		 */
-		as = inb(ctlport+As);
-		if(as & reset){
-			/* nothing to do */;
-		}
-		else if(dev){
-			outb(cmdport+Dh, dev);
-			dev = 0;
-		}
-		else if(ready == 0 || (as & ready)){
-			atadebug(0, 0, "ataready: %d 0x%2.2uX\n", micro, as);
-			return as;
-		}
-
-		if(micro-- <= 0){
-			atadebug(0, 0, "ataready: %d 0x%2.2uX\n", micro, as);
-			break;
-		}
-		microdelay(1);
-	}
-	atadebug(cmdport, ctlport, "ataready: timeout");
-
-	return -1;
-}
-
-static int
-atacsfenabled(Drive* drive, vlong csf)
-{
-	int cmdset, i, x;
-
-	for(i = 0; i < 3; i++){
-		x = (csf>>(16*i)) & 0xFFFF;
-		if(x == 0)
-			continue;
-		cmdset = drive->info[Icsfe+i];
-		if(cmdset == 0 || cmdset == 0xFFFF)
-			return 0;
-		return cmdset & x;
-	}
-
-	return 0;
-}
-
-/*
-static int
-atasf(int cmdport, int ctlport, int dev, uchar* command)
-{
-	int as, i;
-
-	if(ataready(cmdport, ctlport, dev, Bsy|Drq, Drdy, 108*1000) < 0)
-		return -1;
-
-	for(i = Features; i < Dh; i++)
-		outb(cmdport+i, command[i]);
-	outb(cmdport+Command, Csf);
-	microdelay(100);
-	as = ataready(cmdport, ctlport, 0, Bsy, Drdy|Df|Err, 109*1000);
-	if(as < 0 || (as & (Df|Err)))
-		return -1;
-	return 0;
-}
- */
-
-static int
-ataidentify(int cmdport, int ctlport, int dev, int pkt, void* info)
-{
-	int as, command, drdy;
-
-	if(pkt){
-		command = Cidpkt;
-		drdy = 0;
-	}
-	else{
-		command = Cid;
-		drdy = Drdy;
-	}
-	as = ataready(cmdport, ctlport, dev, Bsy|Drq, drdy, 103*1000);
-	if(as < 0)
-		return as;
-	outb(cmdport+Command, command);
-	microdelay(1);
-
-	as = ataready(cmdport, ctlport, 0, Bsy, Drq|Err, 400*1000);
-	if(as < 0)
-		return -1;
-	if(as & Err)
-		return as;
-
-	memset(info, 0, 512);
-	inss(cmdport+Data, info, 256);
-	inb(cmdport+Status);
-
-	if(DEBUG & DbgIDENTIFY){
-		int i;
-		ushort *sp;
-
-		sp = (ushort*)info;
-		for(i = 0; i < 256; i++){
-			if(i && (i%16) == 0)
-				print("\n");
-			print(" %4.4uX ", *sp);
-			sp++;
-		}
-		print("\n");
-	}
-
-	return 0;
-}
-
-static Drive*
-atadrive(int cmdport, int ctlport, int dev)
-{
-	Drive *drive;
-	int as, i, pkt;
-	uchar buf[512], *p;
-	ushort iconfig, *sp;
-
-	atadebug(0, 0, "identify: port 0x%uX dev 0x%2.2uX\n", cmdport, dev);
-	pkt = 1;
-retry:
-	as = ataidentify(cmdport, ctlport, dev, pkt, buf);
-	if(as < 0)
-		return nil;
-	if(as & Err){
-		if(pkt == 0)
-			return nil;
-		pkt = 0;
-		goto retry;
-	}
-
-	if((drive = malloc(sizeof(Drive))) == nil)
-		return nil;
-	drive->dev = dev;
-	memmove(drive->info, buf, sizeof(drive->info));
-	drive->sense[0] = 0x70;
-	drive->sense[7] = sizeof(drive->sense)-7;
-
-	drive->inquiry[2] = 2;
-	drive->inquiry[3] = 2;
-	drive->inquiry[4] = sizeof(drive->inquiry)-4;
-	p = &drive->inquiry[8];
-	sp = &drive->info[Imodel];
-	for(i = 0; i < 20; i++){
-		*p++ = *sp>>8;
-		*p++ = *sp++;
-	}
-
-	drive->secsize = 512;
-
-	/*
-	 * Beware the CompactFlash Association feature set.
-	 * Now, why this value in Iconfig just walks all over the bit
-	 * definitions used in the other parts of the ATA/ATAPI standards
-	 * is a mystery and a sign of true stupidity on someone's part.
-	 * Anyway, the standard says if this value is 0x848A then it's
-	 * CompactFlash and it's NOT a packet device.
-	 */
-	iconfig = drive->info[Iconfig];
-	if(iconfig != 0x848A && (iconfig & 0xC000) == 0x8000){
-		if(iconfig & 0x01)
-			drive->pkt = 16;
-		else
-			drive->pkt = 12;
-	}
-	else{
-		if(drive->info[Ivalid] & 0x0001){
-			drive->c = drive->info[Iccyl];
-			drive->h = drive->info[Ichead];
-			drive->s = drive->info[Icsec];
-		}
-		else{
-			drive->c = drive->info[Ilcyl];
-			drive->h = drive->info[Ilhead];
-			drive->s = drive->info[Ilsec];
-		}
-		if(drive->info[Icapabilities] & 0x0200){
-			if(drive->info[Icsfs+1] & 0x0400){
-				drive->sectors = drive->info[Ilba48]
-					|(drive->info[Ilba48+1]<<16)
-					|((vlong)drive->info[Ilba48+2]<<32);
-				drive->flags |= Lba48;
-			}
-			else{
-				drive->sectors = (drive->info[Ilba+1]<<16)
-					 |drive->info[Ilba];
-			}
-			drive->dev |= Lba;
-		}
-		else
-			drive->sectors = drive->c*drive->h*drive->s;
-	//	atarwmmode(drive, cmdport, ctlport, dev);
-	}
-//	atadmamode(drive);	
-
-	if(DEBUG & DbgCONFIG){
-		print("dev %2.2uX port %uX config %4.4uX capabilities %4.4uX",
-			dev, cmdport, iconfig, drive->info[Icapabilities]);
-		print(" mwdma %4.4uX", drive->info[Imwdma]);
-		if(drive->info[Ivalid] & 0x04)
-			print(" udma %4.4uX", drive->info[Iudma]);
-//		print(" dma %8.8uX rwm %ud", drive->dma, drive->rwm);
-		if(drive->flags&Lba48)
-			print("\tLLBA sectors %lld", drive->sectors);
-		print("\n");
-	}
-
-	return drive;
-}
-
-static void
-atasrst(int ctlport)
-{
-	/*
-	 * Srst is a big stick and may cause problems if further
-	 * commands are tried before the drives become ready again.
-	 * Also, there will be problems here if overlapped commands
-	 * are ever supported.
-	 */
-	microdelay(5);
-	outb(ctlport+Dc, Srst);
-	microdelay(5);
-	outb(ctlport+Dc, 0);
-	microdelay(2*1000);
-}
-
-static SDev*
-ataprobe(int cmdport, int ctlport, int irq)
-{
-	Ctlr* ctlr;
-	SDev *sdev;
-	Drive *drive;
-	int dev, error, rhi, rlo;
-
-//	if(ioalloc(cmdport, 8, 0, "atacmd") < 0)
-//		return nil;
-//	if(ioalloc(ctlport+As, 1, 0, "atactl") < 0){
-//		iofree(cmdport);
-//		return nil;
-//	}
-
-	/*
-	 * Try to detect a floating bus.
-	 * Bsy should be cleared. If not, see if the cylinder registers
-	 * are read/write capable.
-	 * If the master fails, try the slave to catch slave-only
-	 * configurations.
-	 * There's no need to restore the tested registers as they will
-	 * be reset on any detected drives by the Cedd command.
-	 * All this indicates is that there is at least one drive on the
-	 * controller; when the non-existent drive is selected in a
-	 * single-drive configuration the registers of the existing drive
-	 * are often seen, only command execution fails.
-	 */
-	dev = Dev0;
-	if(inb(ctlport+As) & Bsy){
-		outb(cmdport+Dh, dev);
-		microdelay(1);
-trydev1:
-		atadebug(cmdport, ctlport, "ataprobe bsy");
-		outb(cmdport+Cyllo, 0xAA);
-		outb(cmdport+Cylhi, 0x55);
-		outb(cmdport+Sector, 0xFF);
-		rlo = inb(cmdport+Cyllo);
-		rhi = inb(cmdport+Cylhi);
-		if(rlo != 0xAA && (rlo == 0xFF || rhi != 0x55)){
-			if(dev == Dev1){
-release:
-			//	iofree(cmdport);
-			//	iofree(ctlport+As);
-				return nil;
-			}
-			dev = Dev1;
-			if(ataready(cmdport, ctlport, dev, Bsy, 0, 20*1000) < 0)
-				goto trydev1;
-		}
-	}
-
-	/*
-	 * Disable interrupts on any detected controllers.
-	 */
-	outb(ctlport+Dc, Nien);
-tryedd1:
-	if(ataready(cmdport, ctlport, dev, Bsy|Drq, 0, 105*1000) < 0){
-		/*
-		 * There's something there, but it didn't come up clean,
-		 * so try hitting it with a big stick. The timing here is
-		 * wrong but this is a last-ditch effort and it sometimes
-		 * gets some marginal hardware back online.
-		 */
-		atasrst(ctlport);
-		if(ataready(cmdport, ctlport, dev, Bsy|Drq, 0, 106*1000) < 0)
-			goto release;
-	}
-
-	/*
-	 * Can only get here if controller is not busy.
-	 * If there are drives Bsy will be set within 400nS,
-	 * must wait 2mS before testing Status.
-	 * Wait for the command to complete (6 seconds max).
-	 */
-	outb(cmdport+Command, Cedd);
-	delay(2);
-	if(ataready(cmdport, ctlport, dev, Bsy|Drq, 0, 6*1000*1000) < 0)
-		goto release;
-
-	/*
-	 * If bit 0 of the error register is set then the selected drive
-	 * exists. This is enough to detect single-drive configurations.
-	 * However, if the master exists there is no way short of executing
-	 * a command to determine if a slave is present.
-	 * It appears possible to get here testing Dev0 although it doesn't
-	 * exist and the EDD won't take, so try again with Dev1.
-	 */
-	error = inb(cmdport+Error);
-	atadebug(cmdport, ctlport, "ataprobe: dev %uX", dev);
-	if((error & ~0x80) != 0x01){
-		if(dev == Dev1)
-			goto release;
-		dev = Dev1;
-		goto tryedd1;
-	}
-
-	/*
-	 * At least one drive is known to exist, try to
-	 * identify it. If that fails, don't bother checking
-	 * any further.
-	 * If the one drive found is Dev0 and the EDD command
-	 * didn't indicate Dev1 doesn't exist, check for it.
-	 */
-	if((drive = atadrive(cmdport, ctlport, dev)) == nil)
-		goto release;
-	if((ctlr = malloc(sizeof(Ctlr))) == nil){
-		free(drive);
-		goto release;
-	}
-	if((sdev = malloc(sizeof(SDev))) == nil){
-		free(ctlr);
-		free(drive);
-		goto release;
-	}
-	drive->ctlr = ctlr;
-	if(dev == Dev0){
-		ctlr->drive[0] = drive;
-		if(!(error & 0x80)){
-			/*
-			 * Always leave Dh pointing to a valid drive,
-			 * otherwise a subsequent call to ataready on
-			 * this controller may try to test a bogus Status.
-			 * Ataprobe is the only place possibly invalid
-			 * drives should be selected.
-			 */
-			drive = atadrive(cmdport, ctlport, Dev1);
-			if(drive != nil){
-				drive->ctlr = ctlr;
-				ctlr->drive[1] = drive;
-			}
-			else{
-				outb(cmdport+Dh, Dev0);
-				microdelay(1);
-			}
-		}
-	}
-	else
-		ctlr->drive[1] = drive;
-
-	ctlr->cmdport = cmdport;
-	ctlr->ctlport = ctlport;
-	ctlr->irq = irq;
-	ctlr->tbdf = BUSUNKNOWN;
-	ctlr->command = Cedd;		/* debugging */
-
-	sdev->ifc = &sdataifc;
-	sdev->ctlr = ctlr;
-	sdev->nunit = 2;
-	ctlr->sdev = sdev;
-
-	return sdev;
-}
-
-static int
-atasetsense(Drive* drive, int status, int key, int asc, int ascq)
-{
-	drive->sense[2] = key;
-	drive->sense[12] = asc;
-	drive->sense[13] = ascq;
-
-	return status;
-}
-
-static int
-atamodesense(Drive* drive, uchar* cmd)
-{
-	int len;
-
-	/*
-	 * Fake a vendor-specific request with page code 0,
-	 * return the drive info.
-	 */
-	if((cmd[2] & 0x3F) != 0 && (cmd[2] & 0x3F) != 0x3F)
-		return atasetsense(drive, SDcheck, 0x05, 0x24, 0);
-	len = (cmd[7]<<8)|cmd[8];
-	if(len == 0)
-		return SDok;
-	if(len < 8+sizeof(drive->info))
-		return atasetsense(drive, SDcheck, 0x05, 0x1A, 0);
-	if(drive->data == nil || drive->dlen < len)
-		return atasetsense(drive, SDcheck, 0x05, 0x20, 1);
-	memset(drive->data, 0, 8);
-	drive->data[0] = sizeof(drive->info)>>8;
-	drive->data[1] = sizeof(drive->info);
-	memmove(drive->data+8, drive->info, sizeof(drive->info));
-	drive->data += 8+sizeof(drive->info);
-
-	return SDok;
-}
-
-static void
-atanop(Drive* drive, int subcommand)
-{
-	Ctlr* ctlr;
-	int as, cmdport, ctlport, timeo;
-
-	/*
-	 * Attempt to abort a command by using NOP.
-	 * In response, the drive is supposed to set Abrt
-	 * in the Error register, set (Drdy|Err) in Status
-	 * and clear Bsy when done. However, some drives
-	 * (e.g. ATAPI Zip) just go Bsy then clear Status
-	 * when done, hence the timeout loop only on Bsy
-	 * and the forced setting of drive->error.
-	 */
-	ctlr = drive->ctlr;
-	cmdport = ctlr->cmdport;
-	outb(cmdport+Features, subcommand);
-	outb(cmdport+Dh, drive->dev);
-	ctlr->command = Cnop;		/* debugging */
-	outb(cmdport+Command, Cnop);
-
-	microdelay(1);
-	ctlport = ctlr->ctlport;
-	for(timeo = 0; timeo < 1000; timeo++){
-		as = inb(ctlport+As);
-		if(!(as & Bsy))
-			break;
-		microdelay(1);
-	}
-	drive->error |= Abrt;
-}
-
-static void
-ataabort(Drive* drive, int dolock)
-{
-	/*
-	 * If NOP is available (packet commands) use it otherwise
-	 * must try a software reset.
-	 */
-	if(dolock)
-		ilock(drive->ctlr);
-	if(atacsfenabled(drive, 0x0000000000004000LL))
-		atanop(drive, 0);
-	else{
-		atasrst(drive->ctlr->ctlport);
-		drive->error |= Abrt;
-	}
-	if(dolock)
-		iunlock(drive->ctlr);
-}
-
-static int
-atapktiodone(void* arg)
-{
-	return ((Ctlr*)arg)->done;
-}
-
-static void
-atapktinterrupt(Drive* drive)
-{
-	Ctlr* ctlr;
-	int cmdport, len;
-
-	ctlr = drive->ctlr;
-	cmdport = ctlr->cmdport;
-	switch(inb(cmdport+Ir) & (/*Rel|*/Io|Cd)){
-	case Cd:
-		outss(cmdport+Data, drive->pktcmd, drive->pkt/2);
-		break;
-
-	case 0:
-		len = (inb(cmdport+Bytehi)<<8)|inb(cmdport+Bytelo);
-		if(drive->data+len > drive->limit){
-			atanop(drive, 0);
-			break;
-		}
-		outss(cmdport+Data, drive->data, len/2);
-		drive->data += len;
-		break;
-
-	case Io:
-		len = (inb(cmdport+Bytehi)<<8)|inb(cmdport+Bytelo);
-		if(drive->data+len > drive->limit){
-			atanop(drive, 0);
-			break;
-		}
-		inss(cmdport+Data, drive->data, len/2);
-		drive->data += len;
-		break;
-
-	case Io|Cd:
-	//	if(drive->pktdma)
-	//		atadmainterrupt(drive, drive->dlen);
-	//	else
-			ctlr->done = 1;
-		break;
-	}
-}
-
-static int
-atapktio(Drive* drive, uchar* cmd, int clen)
-{
-	Ctlr *ctlr;
-	int as, cmdport, ctlport, len, r;
-
-	if(cmd[0] == 0x5A && (cmd[2] & 0x3F) == 0)
-		return atamodesense(drive, cmd);
-
-	r = SDok;
-
-	drive->command = Cpkt;
-	memmove(drive->pktcmd, cmd, clen);
-	memset(drive->pktcmd+clen, 0, drive->pkt-clen);
-	drive->limit = drive->data+drive->dlen;
-
-	ctlr = drive->ctlr;
-	cmdport = ctlr->cmdport;
-	ctlport = ctlr->ctlport;
-
-	qlock(ctlr);
-
-	as = ataready(cmdport, ctlport, drive->dev, Bsy|Drq, 0, 107*1000);
-	if(as < 0 || (as&Chk)){
-		qunlock(ctlr);
-		return -1;
-	}
-
-	ilock(ctlr);
-//	if(drive->dlen && drive->dmactl && !atadmasetup(drive, drive->dlen))
-//		drive->pktdma = Dma;
-//	else
-//		drive->pktdma = 0;
-
-	outb(cmdport+Features, 0/*drive->pktdma*/);
-	outb(cmdport+Count, 0);
-	outb(cmdport+Sector, 0);
-	len = 16*drive->secsize;
-	outb(cmdport+Bytelo, len);
-	outb(cmdport+Bytehi, len>>8);
-	outb(cmdport+Dh, drive->dev);
-	ctlr->done = 0;
-	ctlr->curdrive = drive;
-	ctlr->command = Cpkt;		/* debugging */
-//	if(drive->pktdma)
-//		atadmastart(ctlr, drive->write);
-	outb(cmdport+Command, Cpkt);
-
-	if((drive->info[Iconfig] & 0x0060) != 0x0020){
-		microdelay(1);
-		as = ataready(cmdport, ctlport, 0, Bsy, Drq|Chk, 4*1000);
-		if(as < 0 || (as & (Bsy|Chk))){
-			drive->status = as<0 ? 0 : as;
-			ctlr->curdrive = nil;
-			ctlr->done = 1;
-			r = SDtimeout;
-		}else
-			atapktinterrupt(drive);
-	}
-	iunlock(ctlr);
-
-	sleep(ctlr, atapktiodone, ctlr);
-
-	qunlock(ctlr);
-
-	if(drive->status & Chk)
-		r = SDcheck;
-
-	return r;
-}
-
-static int
-atageniodone(void* arg)
-{
-	return ((Ctlr*)arg)->done;
-}
-
-static uchar cmd48[256] = {
-	[Crs]	Crs48,
-	[Crd]	Crd48,
-	[Crdq]	Crdq48,
-	[Crsm]	Crsm48,
-	[Cws]	Cws48,
-	[Cwd]	Cwd48,
-	[Cwdq]	Cwdq48,
-	[Cwsm]	Cwsm48,
-};
-
-static int
-atageniostart(Drive* drive, vlong lba)
-{
-	Ctlr *ctlr;
-	uchar cmd;
-	int as, c, cmdport, ctlport, h, len, s, use48;
-
-	use48 = 0;
-	if((drive->flags&Lba48always) || (lba>>28) || drive->count > 256){
-		if(!(drive->flags & Lba48))
-			return -1;
-		use48 = 1;
-		c = h = s = 0;
-	}else if(drive->dev & Lba){
-		c = (lba>>8) & 0xFFFF;
-		h = (lba>>24) & 0x0F;
-		s = lba & 0xFF;
-	}
-	else{
-		c = lba/(drive->s*drive->h);
-		h = ((lba/drive->s) % drive->h);
-		s = (lba % drive->s) + 1;
-	}
-
-	ctlr = drive->ctlr;
-	cmdport = ctlr->cmdport;
-	ctlport = ctlr->ctlport;
-	if(ataready(cmdport, ctlport, drive->dev, Bsy|Drq, 0, 101*1000) < 0)
-		return -1;
-
-	ilock(ctlr);
-
-	drive->block = drive->secsize;
-	if(drive->write)
-		drive->command = Cws;
-	else
-		drive->command = Crs;
-
-	drive->limit = drive->data + drive->count*drive->secsize;
-	cmd = drive->command;
-	if(use48){
-		outb(cmdport+Count, (drive->count>>8) & 0xFF);
-		outb(cmdport+Count, drive->count & 0XFF);
-		outb(cmdport+Lbalo, (lba>>24) & 0xFF);
-		outb(cmdport+Lbalo, lba & 0xFF);
-		outb(cmdport+Lbamid, (lba>>32) & 0xFF);
-		outb(cmdport+Lbamid, (lba>>8) & 0xFF);
-		outb(cmdport+Lbahi, (lba>>40) & 0xFF);
-		outb(cmdport+Lbahi, (lba>>16) & 0xFF);
-		outb(cmdport+Dh, drive->dev|Lba);
-		cmd = cmd48[cmd];
-
-		if(DEBUG & Dbg48BIT)
-			print("using 48-bit commands\n");
-	}else{
-		outb(cmdport+Count, drive->count);
-		outb(cmdport+Sector, s);
-		outb(cmdport+Cyllo, c);
-		outb(cmdport+Cylhi, c>>8);
-		outb(cmdport+Dh, drive->dev|h);
-	}
-	ctlr->done = 0;
-	ctlr->curdrive = drive;
-	ctlr->command = drive->command;	/* debugging */
-	outb(cmdport+Command, cmd);
-
-	switch(drive->command){
-	case Cws:
-	case Cwsm:
-		microdelay(1);
-		as = ataready(cmdport, ctlport, 0, Bsy, Drq|Err, 1000);
-		if(as < 0 || (as & Err)){
-			iunlock(ctlr);
-			return -1;
-		}
-		len = drive->block;
-		if(drive->data+len > drive->limit)
-			len = drive->limit-drive->data;
-		outss(cmdport+Data, drive->data, len/2);
-		break;
-
-	case Crd:
-	case Cwd:
-	//	atadmastart(ctlr, drive->write);
-		break;
-	}
-	iunlock(ctlr);
-
-	return 0;
-}
-
-static int
-atagenioretry(Drive* drive)
-{
-	return atasetsense(drive, SDcheck, 4, 8, drive->error);
-}
-
-static int
-atagenio(Drive* drive, uchar* cmd, int)
-{
-	uchar *p;
-	Ctlr *ctlr;
-	int count, max;
-	vlong lba, len;
-
-	/*
-	 * Map SCSI commands into ATA commands for discs.
-	 * Fail any command with a LUN except INQUIRY which
-	 * will return 'logical unit not supported'.
-	 */
-	if((cmd[1]>>5) && cmd[0] != 0x12)
-		return atasetsense(drive, SDcheck, 0x05, 0x25, 0);
-
-	switch(cmd[0]){
-	default:
-		return atasetsense(drive, SDcheck, 0x05, 0x20, 0);
-
-	case 0x00:			/* test unit ready */
-		return SDok;
-
-	case 0x03:			/* request sense */
-		if(cmd[4] < sizeof(drive->sense))
-			len = cmd[4];
-		else
-			len = sizeof(drive->sense);
-		if(drive->data && drive->dlen >= len){
-			memmove(drive->data, drive->sense, len);
-			drive->data += len;
-		}
-		return SDok;
-
-	case 0x12:			/* inquiry */
-		if(cmd[4] < sizeof(drive->inquiry))
-			len = cmd[4];
-		else
-			len = sizeof(drive->inquiry);
-		if(drive->data && drive->dlen >= len){
-			memmove(drive->data, drive->inquiry, len);
-			drive->data += len;
-		}
-		return SDok;
-
-	case 0x1B:			/* start/stop unit */
-		/*
-		 * NOP for now, can use the power management feature
-		 * set later.
-		 */
-		return SDok;
-
-	case 0x25:			/* read capacity */
-		if((cmd[1] & 0x01) || cmd[2] || cmd[3])
-			return atasetsense(drive, SDcheck, 0x05, 0x24, 0);
-		if(drive->data == nil || drive->dlen < 8)
-			return atasetsense(drive, SDcheck, 0x05, 0x20, 1);
-		/*
-		 * Read capacity returns the LBA of the last sector.
-		 */
-		len = drive->sectors-1;
-		p = drive->data;
-		*p++ = len>>24;
-		*p++ = len>>16;
-		*p++ = len>>8;
-		*p++ = len;
-		len = drive->secsize;
-		*p++ = len>>24;
-		*p++ = len>>16;
-		*p++ = len>>8;
-		*p = len;
-		drive->data += 8;
-		return SDok;
-
-	case 0x9E:			/* long read capacity */
-		if((cmd[1] & 0x01) || cmd[2] || cmd[3])
-			return atasetsense(drive, SDcheck, 0x05, 0x24, 0);
-		if(drive->data == nil || drive->dlen < 8)
-			return atasetsense(drive, SDcheck, 0x05, 0x20, 1);
-		/*
-		 * Read capacity returns the LBA of the last sector.
-		 */
-		len = drive->sectors-1;
-		p = drive->data;
-		*p++ = len>>56;
-		*p++ = len>>48;
-		*p++ = len>>40;
-		*p++ = len>>32;
-		*p++ = len>>24;
-		*p++ = len>>16;
-		*p++ = len>>8;
-		*p++ = len;
-		len = drive->secsize;
-		*p++ = len>>24;
-		*p++ = len>>16;
-		*p++ = len>>8;
-		*p = len;
-		drive->data += 8;
-		return SDok;
-
-	case 0x28:			/* read */
-	case 0x2A:			/* write */
-		break;
-
-	case 0x5A:
-		return atamodesense(drive, cmd);
-	}
-
-	ctlr = drive->ctlr;
-	lba = (cmd[2]<<24)|(cmd[3]<<16)|(cmd[4]<<8)|cmd[5];
-	count = (cmd[7]<<8)|cmd[8];
-	if(drive->data == nil)
-		return SDok;
-	if(drive->dlen < count*drive->secsize)
-		count = drive->dlen/drive->secsize;
-	qlock(ctlr);
-	while(count){
-		max = (drive->flags&Lba48) ? 65536 : 256;
-		if(count > max)
-			drive->count = max;
-		else
-			drive->count = count;
-		if(atageniostart(drive, lba)){
-			ilock(ctlr);
-			atanop(drive, 0);
-			iunlock(ctlr);
-			qunlock(ctlr);
-			return atagenioretry(drive);
-		}
-
-		tsleep(ctlr, atageniodone, ctlr, 10*1000);
-		if(!ctlr->done){
-			/*
-			 * What should the above timeout be? In
-			 * standby and sleep modes it could take as
-			 * long as 30 seconds for a drive to respond.
-			 * Very hard to get out of this cleanly.
-			 */
-		//	atadumpstate(drive, cmd, lba, count);
-			ataabort(drive, 1);
-			return atagenioretry(drive);
-		}
-
-		if(drive->status & Err){
-			qunlock(ctlr);
-			return atasetsense(drive, SDcheck, 4, 8, drive->error);
-		}
-		count -= drive->count;
-		lba += drive->count;
-	}
-	qunlock(ctlr);
-
-	return SDok;
-}
-
-static int
-atario(SDreq* r)
-{
-	Ctlr *ctlr;
-	Drive *drive;
-	SDunit *unit;
-	uchar cmd10[10], *cmdp, *p;
-	int clen, reqstatus, status;
-
-	unit = r->unit;
-	if((ctlr = unit->dev->ctlr) == nil || ctlr->drive[unit->subno] == nil){
-		r->status = SDtimeout;
-		return SDtimeout;
-	}
-	drive = ctlr->drive[unit->subno];
-
-	/*
-	 * Most SCSI commands can be passed unchanged except for
-	 * the padding on the end. The few which require munging
-	 * are not used internally. Mode select/sense(6) could be
-	 * converted to the 10-byte form but it's not worth the
-	 * effort. Read/write(6) are easy.
-	 */
-	switch(r->cmd[0]){
-	case 0x08:			/* read */
-	case 0x0A:			/* write */
-		cmdp = cmd10;
-		memset(cmdp, 0, sizeof(cmd10));
-		cmdp[0] = r->cmd[0]|0x20;
-		cmdp[1] = r->cmd[1] & 0xE0;
-		cmdp[5] = r->cmd[3];
-		cmdp[4] = r->cmd[2];
-		cmdp[3] = r->cmd[1] & 0x0F;
-		cmdp[8] = r->cmd[4];
-		clen = sizeof(cmd10);
-		break;
-
-	default:
-		cmdp = r->cmd;
-		clen = r->clen;
-		break;
-	}
-
-	qlock(drive);
-	drive->write = r->write;
-	drive->data = r->data;
-	drive->dlen = r->dlen;
-
-	drive->status = 0;
-	drive->error = 0;
-	if(drive->pkt)
-		status = atapktio(drive, cmdp, clen);
-	else
-		status = atagenio(drive, cmdp, clen);
-	if(status == SDok){
-		atasetsense(drive, SDok, 0, 0, 0);
-		if(drive->data){
-			p = r->data;
-			r->rlen = drive->data - p;
-		}
-		else
-			r->rlen = 0;
-	}
-	else if(status == SDcheck && !(r->flags & SDnosense)){
-		drive->write = 0;
-		memset(cmd10, 0, sizeof(cmd10));
-		cmd10[0] = 0x03;
-		cmd10[1] = r->lun<<5;
-		cmd10[4] = sizeof(r->sense)-1;
-		drive->data = r->sense;
-		drive->dlen = sizeof(r->sense)-1;
-		drive->status = 0;
-		drive->error = 0;
-		if(drive->pkt)
-			reqstatus = atapktio(drive, cmd10, 6);
-		else
-			reqstatus = atagenio(drive, cmd10, 6);
-		if(reqstatus == SDok){
-			r->flags |= SDvalidsense;
-			atasetsense(drive, SDok, 0, 0, 0);
-		}
-	}
-	qunlock(drive);
-	r->status = status;
-	if(status != SDok)
-		return status;
-
-	/*
-	 * Fix up any results.
-	 * Many ATAPI CD-ROMs ignore the LUN field completely and
-	 * return valid INQUIRY data. Patch the response to indicate
-	 * 'logical unit not supported' if the LUN is non-zero.
-	 */
-	switch(cmdp[0]){
-	case 0x12:			/* inquiry */
-		if((p = r->data) == nil)
-			break;
-		if((cmdp[1]>>5) && (!drive->pkt || (p[0] & 0x1F) == 0x05))
-			p[0] = 0x7F;
-		/*FALLTHROUGH*/
-	default:
-		break;
-	}
-
-	return SDok;
-}
-
-static void
-atainterrupt(Ureg*, void* arg)
-{
-	Ctlr *ctlr;
-	Drive *drive;
-	int cmdport, len, status;
-
-	ctlr = arg;
-
-	ilock(ctlr);
-	if(inb(ctlr->ctlport+As) & Bsy){
-		iunlock(ctlr);
-		if(DEBUG & DbgBsy)
-			print("IBsy+");
-		return;
-	}
-	cmdport = ctlr->cmdport;
-	status = inb(cmdport+Status);
-	if((drive = ctlr->curdrive) == nil){
-		iunlock(ctlr);
-		if((DEBUG & DbgINL) && ctlr->command != Cedd)
-			print("Inil%2.2uX+", ctlr->command);
-		return;
-	}
-
-	if(status & Err)
-		drive->error = inb(cmdport+Error);
-	else switch(drive->command){
-	default:
-		drive->error = Abrt;
-		break;
-
-	case Crs:
-	case Crsm:
-		if(!(status & Drq)){
-			drive->error = Abrt;
-			break;
-		}
-		len = drive->block;
-		if(drive->data+len > drive->limit)
-			len = drive->limit-drive->data;
-		inss(cmdport+Data, drive->data, len/2);
-		drive->data += len;
-		if(drive->data >= drive->limit)
-			ctlr->done = 1;
-		break;
-
-	case Cws:
-	case Cwsm:
-		len = drive->block;
-		if(drive->data+len > drive->limit)
-			len = drive->limit-drive->data;
-		drive->data += len;
-		if(drive->data >= drive->limit){
-			ctlr->done = 1;
-			break;
-		}
-		if(!(status & Drq)){
-			drive->error = Abrt;
-			break;
-		}
-		len = drive->block;
-		if(drive->data+len > drive->limit)
-			len = drive->limit-drive->data;
-		outss(cmdport+Data, drive->data, len/2);
-		break;
-
-	case Cpkt:
-		atapktinterrupt(drive);
-		break;
-
-	case Crd:
-	case Cwd:
-	//	atadmainterrupt(drive, drive->count*drive->secsize);
-		break;
-	}
-	iunlock(ctlr);
-
-	if(drive->error){
-		status |= Err;
-		ctlr->done = 1;
-	}
-
-	if(ctlr->done){
-		ctlr->curdrive = nil;
-		drive->status = status;
-		wakeup(ctlr);
-	}
-}
-
-static SDev*
-atapnp(void)
-{
-	Ctlr *ctlr;
-	Pcidev *p;
-	int channel, ispc87415, pi, r;
-	SDev *legacy[2], *sdev, *head, *tail;
-
-	legacy[0] = legacy[1] = head = tail = nil;
-	if(sdev = ataprobe(0x1F0, 0x3F4, IrqATA0)){
-		head = tail = sdev;
-		legacy[0] = sdev;
-	}
-	if(sdev = ataprobe(0x170, 0x374, IrqATA1)){
-		if(head != nil)
-			tail->next = sdev;
-		else
-			head = sdev;
-		tail = sdev;
-		legacy[1] = sdev;
-	}
-
-	p = nil;
-	while(p = pcimatch(p, 0, 0)){
-		/*
-		 * Look for devices with the correct class and sub-class
-		 * code and known device and vendor ID; add native-mode
-		 * channels to the list to be probed, save info for the
-		 * compatibility mode channels.
-		 * Note that the legacy devices should not be considered
-		 * PCI devices by the interrupt controller.
-		 * For both native and legacy, save info for busmastering
-		 * if capable.
-		 * Promise Ultra ATA/66 (PDC20262) appears to
-		 * 1) give a sub-class of 'other mass storage controller'
-		 *    instead of 'IDE controller', regardless of whether it's
-		 *    the only controller or not;
-		 * 2) put 0 in the programming interface byte (probably
-		 *    as a consequence of 1) above).
-		 * Sub-class code 0x04 is 'RAID controller', e.g. VIA VT8237.
-		 */
-		if(p->ccrb != 0x01)
-			continue;
-		if(p->ccru != 0x01 && p->ccru != 0x04 && p->ccru != 0x80)
-			continue;
-		pi = p->ccrp;
-		ispc87415 = 0;
-
-		switch((p->did<<16)|p->vid){
-		default:
-			continue;
-
-		case (0x0002<<16)|0x100B:	/* NS PC87415 */
-			/*
-			 * Disable interrupts on both channels until
-			 * after they are probed for drives.
-			 * This must be called before interrupts are
-			 * enabled because the IRQ may be shared.
-			 */
-			ispc87415 = 1;
-			pcicfgw32(p, 0x40, 0x00000300);
-			break;
-		case (0x1000<<16)|0x1042:	/* PC-Tech RZ1000 */
-			/*
-			 * Turn off prefetch. Overkill, but cheap.
-			 */
-			r = pcicfgr32(p, 0x40);
-			r &= ~0x2000;
-			pcicfgw32(p, 0x40, r);
-			break;
-		case (0x4D38<<16)|0x105A:	/* Promise PDC20262 */
-		case (0x4D30<<16)|0x105A:	/* Promise PDC202xx */
-		case (0x4D68<<16)|0x105A:	/* Promise PDC20268 */
-		case (0x4D69<<16)|0x105A:	/* Promise Ultra/133 TX2 */
-		case (0x3373<<16)|0x105A:	/* Promise 20378 RAID */
-		case (0x3149<<16)|0x1106:	/* VIA VT8237 SATA/RAID */
-		case (0x4379<<16)|0x1002:	/* ATI 4379 SATA*/
-		case (0x3112<<16)|0x1095:	/* SiL 3112 SATA (DMA busted?) */
-		case (0x3114<<16)|0x1095:	/* SiL 3114 SATA/RAID */
-			pi = 0x85;
-			break;
-		case (0x0004<<16)|0x1103:	/* HighPoint HPT-370 */
-			pi = 0x85;
-			/*
-			 * Turn off fast interrupt prediction.
-			 */
-			if((r = pcicfgr8(p, 0x51)) & 0x80)
-				pcicfgw8(p, 0x51, r & ~0x80);
-			if((r = pcicfgr8(p, 0x55)) & 0x80)
-				pcicfgw8(p, 0x55, r & ~0x80);
-			break;
-		case (0x0640<<16)|0x1095:	/* CMD 640B */
-			/*
-			 * Bugfix code here...
-			 */
-			break;
-		case (0x7441<<16)|0x1022:	/* AMD 768 */
-			/*
-			 * Set:
-			 *	0x41	prefetch, postwrite;
-			 *	0x43	FIFO configuration 1/2 and 1/2;
-			 *	0x44	status register read retry;
-			 *	0x46	DMA read and end of sector flush.
-			 */
-			r = pcicfgr8(p, 0x41);
-			pcicfgw8(p, 0x41, r|0xF0);
-			r = pcicfgr8(p, 0x43);
-			pcicfgw8(p, 0x43, (r & 0x90)|0x2A);
-			r = pcicfgr8(p, 0x44);
-			pcicfgw8(p, 0x44, r|0x08);
-			r = pcicfgr8(p, 0x46);
-			pcicfgw8(p, 0x46, (r & 0x0C)|0xF0);
-			/*FALLTHROUGH*/
-		case (0x7469<<16)|0x1022:	/* AMD 3111 */
-			/*
-			 * This can probably be lumped in with the 768 above.
-			 */
-			/*FALLTHROUGH*/
-		case (0x209A<<16)|0x1022:	/* AMD CS5536 */
-		case (0x01BC<<16)|0x10DE:	/* nVidia nForce1 */
-		case (0x0065<<16)|0x10DE:	/* nVidia nForce2 */
-		case (0x0085<<16)|0x10DE:	/* nVidia nForce2 MCP */
-		case (0x00D5<<16)|0x10DE:	/* nVidia nForce3 */
-		case (0x00E5<<16)|0x10DE:	/* nVidia nForce3 Pro */
-		case (0x0035<<16)|0x10DE:	/* nVidia nForce3 MCP */
-		case (0x0053<<16)|0x10DE:	/* nVidia nForce4 */
-		case (0x0054<<16)|0x10DE:	/* nVidia nForce4 SATA */
-		case (0x0055<<16)|0x10DE:	/* nVidia nForce4 SATA */
-			/*
-			 * Ditto, although it may have a different base
-			 * address for the registers (0x50?).
-			 */
-			break;
-		case (0x0646<<16)|0x1095:	/* CMD 646 */
-		case (0x0571<<16)|0x1106:	/* VIA 82C686 */
-		case (0x0211<<16)|0x1166:	/* ServerWorks IB6566 */
-		case (0x1230<<16)|0x8086:	/* 82371FB (PIIX) */
-		case (0x7010<<16)|0x8086:	/* 82371SB (PIIX3) */
-		case (0x7111<<16)|0x8086:	/* 82371[AE]B (PIIX4[E]) */
-		case (0x2411<<16)|0x8086:	/* 82801AA (ICH) */
-		case (0x2421<<16)|0x8086:	/* 82801AB (ICH0) */
-		case (0x244A<<16)|0x8086:	/* 82801BA (ICH2, Mobile) */
-		case (0x244B<<16)|0x8086:	/* 82801BA (ICH2, High-End) */
-		case (0x248A<<16)|0x8086:	/* 82801CA (ICH3, Mobile) */
-		case (0x248B<<16)|0x8086:	/* 82801CA (ICH3, High-End) */
-		case (0x24CA<<16)|0x8086:	/* 82801DBM (ICH4, Mobile) */
-		case (0x24CB<<16)|0x8086:	/* 82801DB (ICH4, High-End) */
-		case (0x24DB<<16)|0x8086:	/* 82801EB (ICH5) */
-		case (0x266F<<16)|0x8086:	/* 82801FB (ICH6) */
-		case (0x27C4<<16)|0x8086:	/* 82801GBM SATA (ICH7) */
-		case (0x27C5<<16)|0x8086:	/* 82801GBM SATA AHCI (ICH7) */
-			break;
-		}
-
-		for(channel = 0; channel < 2; channel++){
-			if(pi & (1<<(2*channel))){
-				sdev = ataprobe(p->mem[0+2*channel].bar & ~0x01,
-						p->mem[1+2*channel].bar & ~0x01,
-						p->intl);
-				if(sdev == nil)
-					continue;
-
-				ctlr = sdev->ctlr;
-				if(ispc87415)
-					ctlr->ienable = pc87415ienable;
-
-				if(head != nil)
-					tail->next = sdev;
-				else
-					head = sdev;
-				tail = sdev;
-				ctlr->tbdf = p->tbdf;
-			}
-			else if((sdev = legacy[channel]) == nil)
-				continue;
-			else
-				ctlr = sdev->ctlr;
-
-			ctlr->pcidev = p;
-		}
-	}
-
-	return head;
-}
-
-static SDev*
-atalegacy(int port, int irq)
-{
-	return ataprobe(port, port+0x204, irq);
-}
-
-static SDev*
-ataid(SDev* sdev)
-{
-	int i;
-	Ctlr *ctlr;
-
-	/*
-	 * Legacy controllers are always 'C' and 'D' and if
-	 * they exist and have drives will be first in the list.
-	 * If there are no active legacy controllers, native
-	 * controllers start at 'C'.
-	 */
-	if(sdev == nil)
-		return nil;
-	ctlr = sdev->ctlr;
-	if(ctlr->cmdport == 0x1F0 || ctlr->cmdport == 0x170)
-		i = 2;
-	else
-		i = 0;
-	while(sdev){
-		if(sdev->ifc == &sdataifc){
-			ctlr = sdev->ctlr;
-			if(ctlr->cmdport == 0x1F0)
-				sdev->idno = 'C';
-			else if(ctlr->cmdport == 0x170)
-				sdev->idno = 'D';
-			else{
-				sdev->idno = 'C'+i;
-				i++;
-			}
-		//	snprint(sdev->name, NAMELEN, "sd%c", sdev->idno);
-		}
-		sdev = sdev->next;
-	}
-
-	return nil;
-}
-
-static int
-ataenable(SDev* sdev)
-{
-	Ctlr *ctlr;
-
-	ctlr = sdev->ctlr;
-
-	setvec(ctlr->irq+VectorPIC, atainterrupt, ctlr);
-	outb(ctlr->ctlport+Dc, 0);
-	if(ctlr->ienable)
-		ctlr->ienable(ctlr);
-
-	return 1;
-}
-
-SDifc sdataifc = {
-	"ata",				/* name */
-
-	atapnp,				/* pnp */
-	atalegacy,			/* legacy */
-	ataid,				/* id */
-	ataenable,			/* enable */
-	nil,				/* disable */
-
-	scsiverify,			/* verify */
-	scsionline,			/* online */
-	atario,				/* rio */
-	nil,			/* rctl */
-	nil,			/* wctl */
-
-	scsibio,			/* bio */
-};
--- a/os/boot/pc/sdbios.c
+++ /dev/null
@@ -1,165 +1,0 @@
-/*
- * boot driver for BIOS devices with partitions
- * devbios must be called first
- */
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-#include "ureg.h"
-#include "error.h"
-
-#include "sd.h"
-#include "fs.h"
-
-long	biosread(Fs *, void *, long);
-vlong	biosseek(Fs *fs, vlong off);
-
-extern SDifc sdbiosifc;
-extern int onlybios0, biosinited;
-
-int
-biosverify(SDunit* )
-{
-	if (onlybios0 || !biosinited)
-		return 0;
-	return 1;
-}
-
-int
-biosonline(SDunit* unit)
-{
-	if (onlybios0 || !biosinited || !unit)
-		return 0;
-	unit->sectors = 1UL << 30;	/* a bunch */
-	unit->secsize = 512;		/* conventional */
-	return 1;
-}
-
-static int
-biosrio(SDreq* r)
-{
-	int nb;
-	long got;
-	vlong len, off;
-	uchar *p;
-	Fs fs;			/* just for fs->dev, which is zero */
-
-	if (onlybios0 || !biosinited)
-		return SDeio;
-	/*
-	 * Most SCSI commands can be passed unchanged except for
-	 * the padding on the end. The few which require munging
-	 * are not used internally. Mode select/sense(6) could be
-	 * converted to the 10-byte form but it's not worth the
-	 * effort. Read/write(6) are easy.
-	 */
-	r->rlen = 0;
-	r->status = SDok;
-	switch(r->cmd[0]){
-	case 0x08:			/* read */
-	case 0x28:			/* read */
-		if (r->cmd[0] == 0x08)
-			panic("biosrio: 0x08 read op\n");
-		off = r->cmd[2]<<24 | r->cmd[3]<<16 | r->cmd[4]<<8 | r->cmd[5];
-		nb = r->cmd[7]<<8 | r->cmd[8];	/* often 4 */
-		USED(nb);		/* is nb*512 == r->dlen? */
-		memset(&fs, 0, sizeof fs);
-		biosseek(&fs, off*512);
-		got = biosread(&fs, r->data, r->dlen);
-		if (got < 0)
-			r->status = SDeio;
-		else
-			r->rlen = got;
-		break;
-	case 0x0A:			/* write */
-	case 0x2A:			/* write */
-		r->status = SDeio;	/* boot programs don't write */
-		break;
-	case 0x25:			/* read capacity */
-		/*
-		 * Read capacity returns the LBA of the last sector.
-		 */
-		len = r->unit->sectors - 1;
-		p = r->data;
-		*p++ = len>>24;
-		*p++ = len>>16;
-		*p++ = len>>8;
-		*p++ = len;
-		len = r->unit->secsize;
-		*p++ = len>>24;
-		*p++ = len>>16;
-		*p++ = len>>8;
-		*p = len;
-		r->data = (char *)r->data + 8;
-		return SDok;
-	case 0x9E:			/* long read capacity */
-		/*
-		 * Read capacity returns the LBA of the last sector.
-		 */
-		len = r->unit->sectors - 1;
-		p = r->data;
-		*p++ = len>>56;
-		*p++ = len>>48;
-		*p++ = len>>40;
-		*p++ = len>>32;
-		*p++ = len>>24;
-		*p++ = len>>16;
-		*p++ = len>>8;
-		*p++ = len;
-		len = r->unit->secsize;
-		*p++ = len>>24;
-		*p++ = len>>16;
-		*p++ = len>>8;
-		*p = len;
-		r->data = (char *)r->data + 8;
-		return SDok;
-	/* ignore others */
-	}
-	return r->status;
-}
-
-SDev*
-biosid(SDev* sdev)
-{
-	for (; sdev; sdev = sdev->next)
-		if (sdev->ifc == &sdbiosifc)
-			sdev->idno = 'B';
-	return sdev;
-}
-
-static SDev*
-biospnp(void)
-{
-	SDev *sdev;
-
-	/* 9pxeload can't use bios int 13 calls; they wedge the machine */
-	if (pxe || getconf("*nobiosload") != nil || onlybios0 || !biosinited)
-		return nil;
-	if((sdev = malloc(sizeof(SDev))) != nil) {
-		sdev->ifc = &sdbiosifc;
-		sdev->index = -1;
-		sdev->nunit = 1;
-	}
-	return sdev;
-}
-
-SDifc sdbiosifc = {
-	"bios",				/* name */
-
-	biospnp,			/* pnp */
-	nil,				/* legacy */
-	biosid,				/* id */
-	nil,				/* enable */
-	nil,				/* disable */
-
-	biosverify,			/* verify */
-	biosonline,			/* online */
-	biosrio,			/* rio */
-	nil,				/* rctl */
-	nil,				/* wctl */
-
-	scsibio,			/* bio */
-};
--- a/os/boot/pc/sdiahci.c
+++ /dev/null
@@ -1,1668 +1,0 @@
-/*
- * intel/amd ahci (advanced host controller interface) sata controller
- * bootstrap driver
- * copyright © 2007, 2008 coraid, inc.
- */
-
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-#include "error.h"
-#include "sd.h"
-#include "ahci.h"
-
-#define	dprint	if(debug==0){}else print
-#define	idprint	if(prid==0){}else print
-#define	aprint	if(datapi==0){}else print
-
-enum {
-	NCtlr	= 2,
-	NCtlrdrv= 8,
-	NDrive	= NCtlr*NCtlrdrv,
-
-	Read	= 0,
-	Write
-};
-
-/* pci space configurtion */
-enum {
-	Pmap	= 0x90,
-	Ppcs	= 0x91,
-	Prev	= 0xa8,
-};
-
-enum {
-	Tesb,
-	Tich,
-	Tsb600,
-};
-
-#define Intel(x)	((x) == Tesb  || (x) == Tich)
-
-static char *tname[] = {
-	"63xxesb",
-	"ich",
-	"sb600",
-};
-
-enum {
-	Dnull,
-	Dmissing,
-	Dnew,
-	Dready,
-	Derror,
-	Dreset,
-	Doffline,
-	Dportreset,
-	Dlast
-};
-
-static char *diskstates[Dlast] = {
-	"null",
-	"missing",
-	"new",
-	"ready",
-	"error",
-	"reset",
-	"offline",
-	"portreset",
-};
-
-extern SDifc sdiahciifc;
-typedef struct Ctlr Ctlr;
-
-enum {
-	DMautoneg,
-	DMsatai,
-	DMsataii,
-};
-
-static char *modename[] = {
-	"auto",
-	"satai",
-	"sataii",
-};
-
-typedef struct {
-	Lock;
-
-	Ctlr	*ctlr;
-	SDunit	*unit;
-	char	name[10];
-	Aport	*port;
-	Aportm	portm;
-	Aportc	portc;		/* redundant ptr to port and portm. */
-
-	uchar	mediachange;
-	uchar	state;
-	uchar	smartrs;
-
-	uvlong	sectors;
-	ulong	intick;
-	int	wait;
-	uchar	mode;		/* DMautoneg, satai or sataii. */
-	uchar	active;
-
-	char	serial[20+1];
-	char	firmware[8+1];
-	char	model[40+1];
-
-	ushort	info[0x200];
-
-	int	driveno;	/* ctlr*NCtlrdrv + unit */
-	int	portno;	/* ctlr port # != drive # when not all ports enabled. */
-} Drive;
-
-struct Ctlr {
-	Lock;
-
-	int	type;
-	int	enabled;
-	SDev	*sdev;
-	Pcidev	*pci;
-
-	uchar	*mmio;
-	ulong	*lmmio;
-	Ahba	*hba;
-
-	Drive	rawdrive[NCtlrdrv];
-	Drive*	drive[NCtlrdrv];
-	int	ndrive;
-};
-
-static	Ctlr	iactlr[NCtlr];
-static	SDev	sdevs[NCtlr];
-static	int	niactlr;
-
-static	int	prid = 0;
-static	int	datapi = 0;
-
-static char stab[] = {
-[0]	'i', 'm',
-[8]	't', 'c', 'p', 'e',
-[16]	'N', 'I', 'W', 'B', 'D', 'C', 'H', 'S', 'T', 'F', 'X'
-};
-
-static void
-serrstr(ulong r, char *s, char *e)
-{
-	int i;
-
-	e -= 3;
-	for(i = 0; i < nelem(stab) && s < e; i++)
-		if((r & (1<<i)) && stab[i]){
-			*s++ = stab[i];
-			if(SerrBad & (1<<i))
-				*s++ = '*';
-		}
-	*s = 0;
-}
-
-static char ntab[] = "0123456789abcdef";
-
-static void
-preg(uchar *reg, int n)
-{
-	int i;
-	char buf[25*3+1], *e;
-
-	e = buf;
-	for(i = 0; i < n; i++){
-		*e++ = ntab[reg[i] >> 4];
-		*e++ = ntab[reg[i] & 0xf];
-		*e++ = ' ';
-	}
-	*e++ = '\n';
-	*e = 0;
-	dprint(buf);
-}
-
-static void
-dreg(char *s, Aport *p)
-{
-	dprint("%stask=%lux; cmd=%lux; ci=%lux; is=%lux\n",
-		s, p->task, p->cmd, p->ci, p->isr);
-}
-
-static void
-esleep(int ms)
-{
-	delay(ms);
-}
-
-typedef struct {
-	Aport	*p;
-	int	i;
-} Asleep;
-
-static int
-ahciclear(void *v)
-{
-	Asleep *s;
-
-	s = v;
-	return (s->p->ci & s->i) == 0;
-}
-
-static void
-aesleep(Aportm *, Asleep *a, int ms)
-{
-	ulong start;
-
-	start = m->ticks;
-	while((a->p->ci & a->i) != 0)
-		if(TK2MS(m->ticks-start) >= ms)
-			break;
-}
-
-static int
-ahciwait(Aportc *c, int ms)
-{
-	Aport *p;
-	Asleep as;
-
-	p = c->p;
-	p->ci = 1;
-	as.p = p;
-	as.i = 1;
-	aesleep(c->m, &as, ms);
-	if((p->task & 1) == 0 && p->ci == 0)
-		return 0;
-	dreg("ahciwait timeout ", c->p);
-	return -1;
-}
-
-static int
-setfeatures(Aportc *pc, uchar f)
-{
-	uchar *c;
-	Actab *t;
-	Alist *l;
-
-	t = pc->m->ctab;
-	c = t->cfis;
-
-	memset(c, 0, 0x20);
-	c[0] = 0x27;
-	c[1] = 0x80;
-	c[2] = 0xef;
-	c[3] = f;
-	c[7] = 0xa0;		/* obsolete device bits */
-
-	l = pc->m->list;
-	l->flags = Lwrite|0x5;
-	l->len = 0;
-	l->ctab = PCIWADDR(t);
-	l->ctabhi = 0;
-
-	return ahciwait(pc, 3*1000);
-}
-
-static int
-setudmamode(Aportc *pc, uchar f)
-{
-	uchar *c;
-	Actab *t;
-	Alist *l;
-
-	t = pc->m->ctab;
-	c = t->cfis;
-
-	memset(c, 0, 0x20);
-	c[0] = 0x27;
-	c[1] = 0x80;
-	c[2] = 0xef;
-	c[3] = 3;		/* set transfer mode */
-	c[7] = 0xa0;		/* obsolete device bits */
-	c[12] = 0x40 | f;	/* sector count */
-
-	l = pc->m->list;
-	l->flags = Lwrite | 0x5;
-	l->len = 0;
-	l->ctab = PCIWADDR(t);
-	l->ctabhi = 0;
-
-	return ahciwait(pc, 3*1000);
-}
-
-static void
-asleep(int ms)
-{
-	delay(ms);
-}
-
-static int
-ahciportreset(Aportc *c)
-{
-	ulong *cmd, i;
-	Aport *p;
-
-	p = c->p;
-	cmd = &p->cmd;
-	*cmd &= ~(Afre|Ast);
-	for(i = 0; i < 500; i += 25){
-		if((*cmd & Acr) == 0)
-			break;
-		asleep(25);
-	}
-	p->sctl = 1 | (p->sctl & ~7);
-	delay(1);
-	p->sctl &= ~7;
-	return 0;
-}
-
-static ushort
-gbit16(void *a)
-{
-	uchar *i;
-
-	i = a;
-	return i[1]<<8 | i[0];
-}
-
-static ulong
-gbit32(void *a)
-{
-	ulong j;
-	uchar *i;
-
-	i = a;
-	j  = i[3] << 24;
-	j |= i[2] << 16;
-	j |= i[1] << 8;
-	j |= i[0];
-	return j;
-}
-
-static uvlong
-gbit64(void *a)
-{
-	uchar *i;
-
-	i = a;
-	return (uvlong) gbit32(i+4)<<32 | gbit32(a);
-}
-
-static int
-ahciidentify0(Aportc *pc, void *id, int atapi)
-{
-	uchar *c;
-	Actab *t;
-	Alist *l;
-	Aprdt *p;
-	static uchar tab[] = { 0xec, 0xa1 };
-
-	t = pc->m->ctab;
-	c = t->cfis;
-
-	memset(c, 0, 0x20);
-	c[0] = 0x27;
-	c[1] = 0x80;
-	c[2] = tab[atapi];
-	c[7] = 0xa0;		/* obsolete device bits */
-
-	l = pc->m->list;
-	l->flags = 1<<16 | 0x5;
-	l->len = 0;
-	l->ctab = PCIWADDR(t);
-	l->ctabhi = 0;
-
-	memset(id, 0, 0x100);
-	p = &t->prdt;
-	p->dba = PCIWADDR(id);
-	p->dbahi = 0;
-	p->count = 1<<31 | (0x200-2) | 1;
-
-	return ahciwait(pc, 3*1000);
-}
-
-static vlong
-ahciidentify(Aportc *pc, ushort *id)
-{
-	int i, sig;
-	vlong s;
-	Aportm *m;
-
-	m = pc->m;
-	m->feat = 0;
-	m->smart = 0;
-	i = 0;
-	sig = pc->p->sig >> 16;
-	if(sig == 0xeb14){
-		m->feat |= Datapi;
-		i = 1;
-	}
-	if(ahciidentify0(pc, id, i) == -1)
-		return -1;
-
-	i = gbit16(id+83) | gbit16(id+86);
-	if(i & (1<<10)){
-		m->feat |= Dllba;
-		s = gbit64(id+100);
-	}else
-		s = gbit32(id+60);
-
-	if(m->feat & Datapi){
-		i = gbit16(id+0);
-		if(i & 1)
-			m->feat |= Datapi16;
-	}
-
-	i = gbit16(id+83);
-	if((i>>14) != 1)
-		return s;
-	if(i & (1<<3))
-		m->feat |= Dpower;
-	i = gbit16(id+82);
-	if(i & 1)
-		m->feat |= Dsmart;
-	if(i & (1<<14))
-		m->feat |= Dnop;
-	return s;
-}
-
-static int
-ahciquiet(Aport *a)
-{
-	ulong *p, i;
-
-	p = &a->cmd;
-	*p &= ~Ast;
-	for(i = 0; i < 500; i += 50){
-		if((*p & Acr) == 0)
-			goto stop;
-		asleep(50);
-	}
-	return -1;
-stop:
-	if((a->task & (ASdrq|ASbsy)) == 0){
-		*p |= Ast;
-		return 0;
-	}
-
-	*p |= Aclo;
-	for(i = 0; i < 500; i += 50){
-		if((*p & Aclo) == 0)
-			goto stop1;
-		asleep(50);
-	}
-	return -1;
-stop1:
-	/* extra check */
-	dprint("clo clear %lx\n", a->task);
-	if(a->task & ASbsy)
-		return -1;
-	*p |= Ast;
-	return 0;
-}
-
-static int
-ahciidle(Aport *port)
-{
-	ulong *p, i, r;
-
-	p = &port->cmd;
-	if((*p & Arun) == 0)
-		return 0;
-	*p &= ~Ast;
-	r = 0;
-	for(i = 0; i < 500; i += 25){
-		if((*p & Acr) == 0)
-			goto stop;
-		asleep(25);
-	}
-	r = -1;
-stop:
-	if((*p & Afre) == 0)
-		return r;
-	*p &= ~Afre;
-	for(i = 0; i < 500; i += 25){
-		if((*p & Afre) == 0)
-			return 0;
-		asleep(25);
-	}
-	return -1;
-}
-
-/*
- * §6.2.2.1  first part; comreset handled by reset disk.
- *	- remainder is handled by configdisk.
- *	- ahcirecover is a quick recovery from a failed command.
- */
-int
-ahciswreset(Aportc *pc)
-{
-	int i;
-
-	i = ahciidle(pc->p);
-	pc->p->cmd |= Afre;
-	if(i == -1)
-		return -1;
-	if(pc->p->task & (ASdrq|ASbsy))
-		return -1;
-	return 0;
-}
-
-int
-ahcirecover(Aportc *pc)
-{
-	ahciswreset(pc);
-	pc->p->cmd |= Ast;
-	if(setudmamode(pc, 5) == -1)
-		return -1;
-	return 0;
-}
-
-static void*
-malign(int size, int align)
-{
-	void *v;
-
-	v = xspanalloc(size, align, 0);
-	memset(v, 0, size);
-	return v;
-}
-
-static void
-setupfis(Afis *f)
-{
-	f->base = malign(0x100, 0x100);
-	f->d = f->base + 0;
-	f->p = f->base + 0x20;
-	f->r = f->base + 0x40;
-	f->u = f->base + 0x60;
-	f->devicebits = (ulong*)(f->base + 0x58);
-}
-
-static void
-ahciwakeup(Aport *p)
-{
-	ushort s;
-
-	s = p->sstatus;
-	if((s & 0x700) != 0x600)
-		return;
-	if((s & 7) != 1){
-		print("ahci: slumbering drive unwakeable %ux\n", s);
-		return;
-	}
-	p->sctl = 3*Aipm | 0*Aspd | Adet;
-	delay(1);
-	p->sctl &= ~7;
-//	iprint("ahci: wake %ux -> %ux\n", s, p->sstatus);
-}
-
-static int
-ahciconfigdrive(Ahba *h, Aportc *c, int mode)
-{
-	Aportm *m;
-	Aport *p;
-
-	p = c->p;
-	m = c->m;
-
-	if(m->list == 0){
-		setupfis(&m->fis);
-		m->list = malign(sizeof *m->list, 1024);
-		m->ctab = malign(sizeof *m->ctab, 128);
-	}
-
-	if(p->sstatus & 3 && h->cap & Hsss){
-		dprint("configdrive:  spinning up ... [%lux]\n", p->sstatus);
-		p->cmd |= Apod|Asud;
-		asleep(1400);
-	}
-
-	p->serror = SerrAll;
-
-	p->list = PCIWADDR(m->list);
-	p->listhi = 0;
-	p->fis = PCIWADDR(m->fis.base);
-	p->fishi = 0;
-	p->cmd |= Afre | Ast;
-
-	if((p->sstatus & 0x707) == 0x601) /* drive coming up in slumbering? */
-		ahciwakeup(p);
-
-	/* disable power managment sequence from book. */
-	p->sctl = (3*Aipm) | (mode*Aspd) | (0*Adet);
-	p->cmd &= ~Aalpe;
-
-	p->ie = IEM;
-
-	return 0;
-}
-
-static int
-ahcienable(Ahba *h)
-{
-	h->ghc |= Hie;
-	return 0;
-}
-
-static int
-ahcidisable(Ahba *h)
-{
-	h->ghc &= ~Hie;
-	return 0;
-}
-
-static int
-countbits(ulong u)
-{
-	int i, n;
-
-	n = 0;
-	for(i = 0; i < 32; i++)
-		if(u & (1<<i))
-			n++;
-	return n;
-}
-
-static int
-ahciconf(Ctlr *c)
-{
-	ulong u;
-	Ahba *h;
-	static int count;
-
-	h = c->hba = (Ahba*)c->mmio;
-	u = h->cap;
-
-	if((u & Hsam) == 0)
-		h->ghc |= Hae;
-
-	print("ahci%d port %#p: hba sss %ld; ncs %ld; coal %ld; mports %ld; "
-		"led %ld; clo %ld; ems %ld;\n", count++, h,
-		(u>>27) & 1, (u>>8) & 0x1f, (u>>7) & 1,	u & 0x1f, (u>>25) & 1,
-		(u>>24) & 1, (u>>6) & 1);
-	return countbits(h->pi);
-}
-
-static int
-ahcihbareset(Ahba *h)
-{
-	int wait;
-
-	h->ghc |= 1;
-	for(wait = 0; wait < 1000; wait += 100){
-		if(h->ghc == 0)
-			return 0;
-		delay(100);
-	}
-	return -1;
-}
-
-static void
-idmove(char *p, ushort *a, int n)
-{
-	int i;
-	char *op, *e;
-
-	op = p;
-	for(i = 0; i < n/2; i++){
-		*p++ = a[i] >> 8;
-		*p++ = a[i];
-	}
-	*p = 0;
-	while(p > op && *--p == ' ')
-		*p = 0;
-	e = p;
-	for (p = op; *p == ' '; p++)
-		;
-	memmove(op, p, n - (e - p));
-}
-
-static int
-identify(Drive *d)
-{
-	ushort *id;
-	vlong osectors, s;
-	uchar oserial[21];
-	SDunit *u;
-
-	id = d->info;
-	s = ahciidentify(&d->portc, id);
-	if(s == -1){
-		d->state = Derror;
-		return -1;
-	}
-	osectors = d->sectors;
-	memmove(oserial, d->serial, sizeof d->serial);
-
-	d->sectors = s;
-	d->smartrs = 0;
-
-	idmove(d->serial, id+10, 20);
-	idmove(d->firmware, id+23, 8);
-	idmove(d->model, id+27, 40);
-
-	u = d->unit;
-	memset(u->inquiry, 0, sizeof u->inquiry);
-	u->inquiry[2] = 2;
-	u->inquiry[3] = 2;
-	u->inquiry[4] = sizeof u->inquiry - 4;
-	memmove(u->inquiry+8, d->model, 40);
-
-	if((osectors == 0 || osectors != s) &&
-	    memcmp(oserial, d->serial, sizeof oserial) != 0){
-		d->mediachange = 1;
-		u->sectors = 0;
-	}
-
-	return 0;
-}
-
-static void
-clearci(Aport *p)
-{
-	if((p->cmd & Ast) == 0)
-		return;
-	p->cmd &= ~Ast;
-	p->cmd |= Ast;
-}
-
-static void
-updatedrive(Drive *d)
-{
-	ulong cause, serr, s0, pr, ewake;
-	char *name;
-	Aport *p;
-	static ulong last;
-
-	pr = 1;
-	ewake = 0;
-	p = d->port;
-	cause = p->isr;
-	serr = p->serror;
-	p->isr = cause;
-	name = "??";
-	if(d->unit && d->unit->name)
-		name = d->unit->name;
-
-	if(p->ci == 0){
-		d->portm.flag |= Fdone;
-		pr = 0;
-	}else if(cause & Adps)
-		pr = 0;
-	if(cause&Ifatal){
-		ewake = 1;
-		dprint("Fatal\n");
-	}
-	if(cause & Adhrs){
-		if(p->task & (32|1)){
-			dprint("Adhrs cause = %lux; serr = %lux; task=%lux\n",
-				cause, serr, p->task);
-			d->portm.flag |= Ferror;
-			ewake = 1;
-		}
-		pr = 0;
-	}
-
-	if(pr)
-		dprint("%s: upd %lux ta %lux\n", name, cause, p->task);
-	if(cause & (Aprcs|Aifs)){
-		s0 = d->state;
-		switch(p->sstatus & 7){
-		case 0:
-			d->state = Dmissing;
-			break;
-		case 1:
-			if((p->sstatus & 0x700) == 0x600)
-				d->state = Dnew;
-			else
-				d->state = Derror;
-			break;
-		case 3:
-			/* power mgnt crap for surprise removal */
-			p->ie |= Aprcs | Apcs;	/* is this required? */
-			d->state = Dreset;
-			break;
-		case 4:
-			d->state = Doffline;
-			break;
-		}
-		dprint("%s: %s → %s [Apcrs] %lux\n", name, diskstates[s0],
-			diskstates[d->state], p->sstatus);
-		if(s0 == Dready && d->state != Dready)
-			idprint("%s: pulled\n", name);
-		if(d->state != Dready)
-			d->portm.flag |= Ferror;
-		ewake = 1;
-	}
-	p->serror = serr;
-	if(ewake)
-		clearci(p);
-	last = cause;
-}
-
-static void
-pstatus(Drive *d, ulong s)
-{
-	/*
-	 * bogus code because the first interrupt is currently dropped.
-	 * likely my fault.  serror may be cleared at the wrong time.
-	 */
-	switch(s){
-	case 0:
-		d->state = Dmissing;
-		break;
-	case 2:			/* should this be missing?  need testcase. */
-		dprint("pstatus 2\n");
-	case 3:
-		d->wait = 0;
-		d->state = Dnew;
-		break;
-	case 4:
-		d->state = Doffline;
-		break;
-	case 6:
-		d->state = Dnew;
-		break;
-	}
-}
-
-static int
-configdrive(Drive *d)
-{
-	if(ahciconfigdrive(d->ctlr->hba, &d->portc, d->mode) == -1)
-		return -1;
-	ilock(d);
-	pstatus(d, d->port->sstatus & 7);
-	iunlock(d);
-	return 0;
-}
-
-static void
-resetdisk(Drive *d)
-{
-	uint state, det, stat;
-	Aport *p;
-
-	p = d->port;
-	det = p->sctl & 7;
-	stat = p->sstatus & 7;
-	state = (p->cmd>>28) & 0xf;
-	dprint("resetdisk: icc %ux  det %d sdet %d\n", state, det, stat);
-	if(stat != 3){
-		ilock(d);
-		d->state = Dportreset;
-		iunlock(d);
-		return;
-	}
-	ilock(d);
-	state = d->state;
-	if(d->state != Dready || d->state != Dnew)
-		d->portm.flag |= Ferror;
-	clearci(p);			/* satisfy sleep condition. */
-	iunlock(d);
-
-	qlock(&d->portm);
-
-	if(p->cmd & Ast && ahciswreset(&d->portc) == -1){
-		ilock(d);
-		d->state = Dportreset;	/* get a bigger stick. */
-		iunlock(d);
-	} else {
-		ilock(d);
-		d->state = Dmissing;
-		iunlock(d);
-
-		configdrive(d);
-	}
-	dprint("resetdisk: %s → %s\n", diskstates[state], diskstates[d->state]);
-	qunlock(&d->portm);
-}
-
-static int
-newdrive(Drive *d)
-{
-	char *name, *s;
-	Aportc *c;
-	Aportm *m;
-
-	c = &d->portc;
-	m = &d->portm;
-
-	name = d->unit->name;
-	if(name == 0)
-		name = "??";
-
-	if(d->port->task == 0x80)
-		return -1;
-	qlock(c->m);
-	if(setudmamode(c, 5) == -1){
-		dprint("%s: can't set udma mode\n", name);
-		goto lose;
-	}
-	if(identify(d) == -1){
-		dprint("%s: identify failure\n", name);
-		goto lose;
-	}
-	if(m->feat & Dpower && setfeatures(c, 0x85) == -1){
-		m->feat &= ~Dpower;
-		if(ahcirecover(c) == -1) {
-			dprint("%s: ahcirecover failed\n", name);
-			goto lose;
-		}
-	}
-
-	ilock(d);
-	d->state = Dready;
-	iunlock(d);
-
-	qunlock(c->m);
-
-	s = "";
-	if(m->feat & Dllba)
-		s = "L";
-	idprint("%s: %sLBA %lld sectors\n", d->unit->name, s, d->sectors);
-	idprint("  %s %s %s %s\n", d->model, d->firmware, d->serial,
-		d->mediachange? "[mediachange]": "");
-
-	return 0;
-
-lose:
-	qunlock(&d->portm);
-	return -1;
-}
-
-enum {
-	Nms		= 256,
-	Mphywait	=  2*1024/Nms - 1,
-	Midwait		= 16*1024/Nms - 1,
-	Mcomrwait	= 64*1024/Nms - 1,
-};
-
-static void
-westerndigitalhung(Drive *d)
-{
-	if((d->portm.feat & Datapi) == 0 && d->active &&
-	    TK2MS(m->ticks - d->intick) > 5000){
-		dprint("%s: drive hung; resetting [%lux] ci=%lx\n",
-			d->unit->name, d->port->task, d->port->ci);
-		d->state = Dreset;
-	}
-}
-
-static ushort olds[NCtlr*NCtlrdrv];
-
-static int
-doportreset(Drive *d)
-{
-	int i;
-
-	i = -1;
-	qlock(&d->portm);
-	if(ahciportreset(&d->portc) == -1)
-		dprint("ahciportreset fails\n");
-	else
-		i = 0;
-	qunlock(&d->portm);
-	dprint("portreset → %s  [task %lux]\n", diskstates[d->state],
-		d->port->task);
-	return i;
-}
-
-static void
-checkdrive(Drive *d, int i)
-{
-	ushort s;
-	char *name;
-
-	ilock(d);
-	name = d->unit->name;
-	s = d->port->sstatus;
-	if(s != olds[i]){
-		dprint("%s: status: %#ux -> %#ux: %s\n", name, olds[i],
-			s, diskstates[d->state]);
-		olds[i] = s;
-		d->wait = 0;
-	}
-	westerndigitalhung(d);
-	switch(d->state){
-	case Dnull:
-		break;
-	case Dmissing:
-	case Dnew:
-		switch(s & 0x107){
-		case 1:
-			ahciwakeup(d->port);
-		case 0:
-			break;
-		default:
-			dprint("%s: unknown status %04ux\n", name, s);
-		case 0x100:
-			if(++d->wait&Mphywait)
-				break;
-reset:
-			if(++d->mode > DMsataii)
-				d->mode = 0;
-			if(d->mode == DMsatai){	/* we tried everything */
-				d->state = Dportreset;
-				goto portreset;
-			}
-			dprint("%s: reset; new mode %s\n", name,
-				modename[d->mode]);
-			iunlock(d);
-			resetdisk(d);
-			ilock(d);
-			break;
-		case 0x103:
-			if((++d->wait&Midwait) == 0){
-				dprint("%s: slow reset %#ux task=%#lux; %d\n",
-					name, s, d->port->task, d->wait);
-				goto reset;
-			}
-			s = d->port->task&0xff;
-			if(s == 0x7f || ((d->port->sig>>16) != 0xeb14 &&
-			    (s & ~0x17) != (1<<6)))
-				break;
-			iunlock(d);
-			newdrive(d);
-			ilock(d);
-			break;
-		}
-		break;
-	case Doffline:
-		if(d->wait++ & Mcomrwait)
-			break;
-	case Derror:
-	case Dreset:
-		dprint("%s: reset [%s]: mode %d; status %#ux\n",
-			name, diskstates[d->state], d->mode, s);
-		iunlock(d);
-		resetdisk(d);
-		ilock(d);
-		break;
-	case Dportreset:
-portreset:
-		if(d->wait++ & 0xff && (s & 0x100) == 0)
-			break;
-		dprint("%s: portreset [%s]: mode %d; status %04ux\n",
-			name, diskstates[d->state], d->mode, s);
-		d->portm.flag |= Ferror;
-		clearci(d->port);
-		if((s & 7) == 0){
-			d->state = Dmissing;
-			break;
-		}
-		iunlock(d);
-		doportreset(d);
-		ilock(d);
-		break;
-	}
-	iunlock(d);
-}
-
-static void
-iainterrupt(Ureg*, void *a)
-{
-	int i;
-	ulong cause, m;
-	Ctlr *c;
-	Drive *d;
-
-	c = a;
-	ilock(c);
-	/* check drive here! */
-	cause = c->hba->isr;
-	for(i = 0; i < c->ndrive; i++){
-		m = 1 << i;
-		if((cause & m) == 0)
-			continue;
-		d = c->rawdrive + i;
-		ilock(d);
-		if(d->port->isr && c->hba->pi & m)
-			updatedrive(d);
-		c->hba->isr = m;
-		iunlock(d);
-	}
-	iunlock(c);
-}
-
-static int
-iaverify(SDunit *u)
-{
-	int i;
-	Ctlr *c;
-	Drive *d;
-
-	c = u->dev->ctlr;
-	d = c->drive[u->subno];
-	ilock(c);
-	ilock(d);
-	d->unit = u;
-	iunlock(d);
-	iunlock(c);
-	for(i = 0; i < 10; i++){
-		checkdrive(d, d->driveno);
-		switch(d->state){
-		case Dmissing:
-			if(i < 4 || d->port->sstatus & 0x733)
-				break;
-			/* fall through */
-		case Dnull:
-		case Dready:
-		case Doffline:
-			print("sdiahci: drive %d in state %s after %d resets\n",
-				d->driveno, diskstates[d->state], i);
-			return 1;
-		}
-		delay(100);
-	}
-	print("sdiahci: drive %d won't come up; in state %s after %d resets\n",
-		d->driveno, diskstates[d->state], i);
-	return 1;
-}
-
-static int
-iaenable(SDev *s)
-{
-	Ctlr *c;
-
-	c = s->ctlr;
-	ilock(c);
-	if(!c->enabled) {
-		if(c->ndrive == 0)
-			panic("iaenable: zero s->ctlr->ndrive");
-		pcisetbme(c->pci);
-		setvec(c->pci->intl+VectorPIC, iainterrupt, c);
-		/* supposed to squelch leftover interrupts here. */
-		ahcienable(c->hba);
-		c->enabled = 1;
-	}
-	iunlock(c);
-	return 1;
-}
-
-static int
-iadisable(SDev *s)
-{
-	Ctlr *c;
-
-	c = s->ctlr;
-	ilock(c);
-	ahcidisable(c->hba);
-//	intrdisable(c->irq, iainterrupt, c, c->tbdf, name);
-	c->enabled = 0;
-	iunlock(c);
-	return 1;
-}
-
-static int
-iaonline(SDunit *unit)
-{
-	int r;
-	Ctlr *c;
-	Drive *d;
-
-	c = unit->dev->ctlr;
-	d = c->drive[unit->subno];
-	r = 0;
-
-	if(d->portm.feat & Datapi && d->mediachange){
-		r = scsionline(unit);
-		if(r > 0)
-			d->mediachange = 0;
-		return r;
-	}
-
-	ilock(d);
-	if(d->mediachange){
-		r = 2;
-		d->mediachange = 0;
-		/* devsd resets this after online is called; why? */
-		unit->sectors = d->sectors;
-		unit->secsize = 512;
-	} else if(d->state == Dready)
-		r = 1;
-	iunlock(d);
-	return r;
-}
-
-/* returns locked list! */
-static Alist*
-ahcibuild(Aportm *m, uchar *cmd, void *data, int n, vlong lba)
-{
-	uchar *c, acmd, dir, llba;
-	Alist *l;
-	Actab *t;
-	Aprdt *p;
-	static uchar tab[2][2] = { 0xc8, 0x25, 0xca, 0x35 };
-
-	dir = *cmd != 0x28;
-	llba = m->feat & Dllba? 1: 0;
-	acmd = tab[dir][llba];
-	qlock(m);
-	l = m->list;
-	t = m->ctab;
-	c = t->cfis;
-
-	c[0] = 0x27;
-	c[1] = 0x80;
-	c[2] = acmd;
-	c[3] = 0;
-
-	c[4] = lba;		/* sector	lba low	7:0 */
-	c[5] = lba >> 8;	/* cylinder low	lba mid	15:8 */
-	c[6] = lba >> 16;	/* cylinder hi	lba hi	23:16 */
-	c[7] = 0xa0 | 0x40;	/* obsolete device bits + lba */
-	if(llba == 0)
-		c[7] |= (lba>>24) & 7;
-
-	c[8] = lba >> 24;	/* sector (exp)		lba 	31:24 */
-	c[9] = lba >> 32;	/* cylinder low (exp)	lba	39:32	 */
-	c[10] = lba >> 48;	/* cylinder hi (exp)	lba	48:40 */
-	c[11] = 0;		/* features (exp); */
-
-	c[12] = n;		/* sector count */
-	c[13] = n >> 8;		/* sector count (exp) */
-	c[14] = 0;		/* r */
-	c[15] = 0;		/* control */
-
-	*(ulong*)(c+16) = 0;
-
-	l->flags = 1<<16 | Lpref | 0x5;	/* Lpref ?? */
-	if(dir == Write)
-		l->flags |= Lwrite;
-	l->len = 0;
-	l->ctab = PCIWADDR(t);
-	l->ctabhi = 0;
-
-	p = &t->prdt;
-	p->dba = PCIWADDR(data);
-	p->dbahi = 0;
-	p->count = 1<<31 | (512*n - 2) | 1;
-
-	return l;
-}
-
-static Alist*
-ahcibuildpkt(Aportm *m, SDreq *r, void *data, int n)
-{
-	int fill, len;
-	uchar *c;
-	Actab *t;
-	Alist *l;
-	Aprdt *p;
-
-	qlock(m);
-	l = m->list;
-	t = m->ctab;
-	c = t->cfis;
-
-	fill = m->feat & Datapi16? 16: 12;
-	if((len = r->clen) > fill)
-		len = fill;
-	memmove(t->atapi, r->cmd, len);
-	memset(t->atapi + len, 0, fill - len);
-
-	c[0] = 0x27;
-	c[1] = 0x80;
-	c[2] = 0xa0;
-	if(n != 0)
-		c[3] = 1;	/* dma */
-	else
-		c[3] = 0;	/* features (exp); */
-
-	c[4] = 0;		/* sector	lba low	7:0 */
-	c[5] = n;		/* cylinder low	lba mid	15:8 */
-	c[6] = n >> 8;		/* cylinder hi	lba hi	23:16 */
-	c[7] = 0xa0;		/* obsolete device bits */
-
-	*(ulong*)(c+8) = 0;
-	*(ulong*)(c+12) = 0;
-	*(ulong*)(c+16) = 0;
-
-	l->flags = 1<<16 | Lpref | Latapi | 0x5;
-	if(r->write != 0 && data)
-		l->flags |= Lwrite;
-	l->len = 0;
-	l->ctab = PCIWADDR(t);
-	l->ctabhi = 0;
-
-	if(data == 0)
-		return l;
-
-	p = &t->prdt;
-	p->dba = PCIWADDR(data);
-	p->dbahi = 0;
-	p->count = 1<<31 | (n - 2) | 1;
-
-	return l;
-}
-
-static int
-waitready(Drive *d)
-{
-	ulong s, t, i;
-
-	for(i = 0; i < 120; i++){
-		ilock(d);
-		s = d->port->sstatus;
-		t = d->port->task;
-		iunlock(d);
-		if((s & 0x100) == 0)
-			return -1;
-		if(d->state == Dready && (s & 7) == 3)
-			return 0;
-		if((i + 1) % 30 == 0)
-			print("%s: waitready: [%s] task=%lux sstat=%lux\n",
-				d->unit->name, diskstates[d->state], t, s);
-		esleep(1000);
-	}
-	print("%s: not responding; offline\n", d->unit->name);
-	ilock(d);
-	d->state = Doffline;
-	iunlock(d);
-	return -1;
-}
-
-static int
-iariopkt(SDreq *r, Drive *d)
-{
-	int n, count, try, max, flag, task;
-	char *name;
-	uchar *cmd, *data;
-	Aport *p;
-	Asleep as;
-
-	cmd = r->cmd;
-	name = d->unit->name;
-	p = d->port;
-
-	aprint("%02ux %02ux %c %d %p\n", cmd[0], cmd[2], "rw"[r->write],
-		r->dlen, r->data);
-//	if(cmd[0] == 0x5a && (cmd[2] & 0x3f) == 0x3f)
-//		return sdmodesense(r, cmd, d->info, sizeof d->info);
-	r->rlen = 0;
-	count = r->dlen;
-	max = 65536;
-
-	try = 0;
-retry:
-	if(waitready(d) == -1)
-		return SDeio;
-	data = r->data;
-	n = count;
-	if(n > max)
-		n = max;
-	d->active++;
-	ahcibuildpkt(&d->portm, r, data, n);
-	ilock(d);
-	d->portm.flag = 0;
-	iunlock(d);
-	p->ci = 1;
-
-	as.p = p;
-	as.i = 1;
-	d->intick = m->ticks;
-
-	while(ahciclear(&as) == 0)
-		;
-
-	ilock(d);
-	flag = d->portm.flag;
-	task = d->port->task;
-	iunlock(d);
-
-	if(task & (Efatal<<8) || task & (ASbsy|ASdrq) && d->state == Dready){
-		d->port->ci = 0;		/* @? */
-		ahcirecover(&d->portc);
-		task = d->port->task;
-	}
-	d->active--;
-	qunlock(&d->portm);
-	if(flag == 0){
-		if(++try == 10){
-			print("%s: bad disk\n", name);
-			r->status = SDcheck;
-			return SDcheck;
-		}
-		print("%s: retry\n", name);
-		esleep(1000);
-		goto retry;
-	}
-	if(flag & Ferror){
-		if((task & Eidnf) == 0)
-			print("%s: i/o error %ux\n", name, task);
-		r->status = SDcheck;
-		return SDcheck;
-	}
-
-	data += n;
-
-	r->rlen = data - (uchar*)r->data;
-	r->status = SDok;
-	return SDok;
-}
-
-static int
-iario(SDreq *r)
-{
-	int n, count, max, flag, task;
-	vlong lba;
-	char *name;
-	uchar *cmd, *data;
-	Aport *p;
-	Asleep as;
-	Ctlr *c;
-	Drive *d;
-	SDunit *unit;
-
-	unit = r->unit;
-	c = unit->dev->ctlr;
-	d = c->drive[unit->subno];
-	if(d->portm.feat & Datapi)
-		return iariopkt(r, d);
-	cmd = r->cmd;
-	name = d->unit->name;
-	p = d->port;
-
-//	if((i = sdfakescsi(r, d->info, sizeof d->info)) != SDnostatus){
-//		r->status = i;
-//		return i;
-//	}
-
-	if(*cmd != 0x28 && *cmd != 0x2a){
-		print("%s: bad cmd 0x%.2ux\n", name, cmd[0]);
-		r->status = SDcheck;
-		return SDcheck;
-	}
-
-	lba   = cmd[2]<<24 | cmd[3]<<16 | cmd[4]<<8 | cmd[5];
-	count = cmd[7]<<8  | cmd[8];
-	if(r->data == nil)
-		return SDok;
-	if(r->dlen < count * unit->secsize)
-		count = r->dlen / unit->secsize;
-	max = 128;
-
-	if(waitready(d) == -1)
-		return SDeio;
-	data = r->data;
-	while(count > 0){
-		n = count;
-		if(n > max)
-			n = max;
-		d->active++;
-		ahcibuild(&d->portm, cmd, data, n, lba);
-		ilock(d);
-		d->portm.flag = 0;
-		iunlock(d);
-		p->ci = 1;
-
-		as.p = p;
-		as.i = 1;
-		d->intick = m->ticks;
-
-		while(ahciclear(&as) == 0)
-			;
-
-		ilock(d);
-		flag = d->portm.flag;
-		task = d->port->task;
-		iunlock(d);
-
-		if(task & (Efatal<<8) ||
-		    task & (ASbsy|ASdrq) && d->state == Dready){
-			d->port->ci = 0;		/* @? */
-			ahcirecover(&d->portc);
-			task = d->port->task;
-		}
-		d->active--;
-		qunlock(&d->portm);
-		if(flag == 0 || flag & Ferror){
-			print("%s: i/o error %ux @%lld\n", name, task, lba);
-			r->status = SDeio;
-			return SDeio;
-		}
-
-		count -= n;
-		lba += n;
-		data += n * unit->secsize;
-	}
-	r->rlen = data - (uchar*)r->data;
-	r->status = SDok;
-	return SDok;
-}
-
-/*
- * configure drives 0-5 as ahci sata  (c.f. errata)
- */
-static int
-iaahcimode(Pcidev *p)
-{
-	dprint("iaahcimode %ux %ux %ux\n", pcicfgr8(p, 0x91),
-		pcicfgr8(p, 92), pcicfgr8(p, 93));
-	pcicfgw16(p, 0x92, pcicfgr32(p, 0x92) | 0xf);	/* ports 0-3 */
-//	pcicfgw8(p, 0x93, pcicfgr32(p, 9x93) | 3);	/* ports 4-5 */
-	return 0;
-}
-
-static void
-iasetupahci(Ctlr *c)
-{
-	/* disable cmd block decoding. */
-	pcicfgw16(c->pci, 0x40, pcicfgr16(c->pci, 0x40) & ~(1<<15));
-	pcicfgw16(c->pci, 0x42, pcicfgr16(c->pci, 0x42) & ~(1<<15));
-
-	c->lmmio[0x4/4] |= 1 << 31;	/* enable ahci mode (ghc register) */
-	c->lmmio[0xc/4] = (1<<6) - 1;	/* five ports (supposedly ro pi reg) */
-
-	/* enable ahci mode; from ich9 datasheet */
-	pcicfgw8(c->pci, 0x90, 1<<6 | 1<<5);
-}
-
-static SDev*
-iapnp(void)
-{
-	int i, n, nunit, type;
-	ulong io;
-	Ctlr *c;
-	Drive *d;
-	Pcidev *p;
-	SDev *head, *tail, *s;
-	static int done;
-
-	if (done || getconf("*noahciload") != nil)
-		return nil;
-	done = 1;
-	p = nil;
-	head = tail = nil;
-loop:
-	while((p = pcimatch(p, 0, 0)) != nil){
-		if(p->vid == 0x8086 && (p->did & 0xfffc) == 0x2680)
-			type = Tesb;
-		else if(p->vid == 0x8086 && p->did == 0x27c5)
-			type = Tich;	/* 82801g[bh]m; compat mode fails */
-		else if(p->vid == 0x8086 && (p->did & 0xfeff) == 0x2829)
-			type = Tich;		/* ich8 */
-		else if(p->vid == 0x8086 && (p->did & 0xfffe) == 0x2922)
-			type = Tich;		/* ich8 */
-		else if(p->vid == 0x1002 && p->did == 0x4380)
-			type = Tsb600;
-		else
-			continue;
-		if(niactlr == NCtlr){
-			print("iapnp: %s: too many controllers\n", tname[type]);
-			break;
-		}
-		c = iactlr + niactlr;
-		s = sdevs  + niactlr;
-		memset(c, 0, sizeof *c);
-		memset(s, 0, sizeof *s);
-		c->pci = p;
-		c->type = type;
-		io = p->mem[Abar].bar & ~0xf;
-		io = upamalloc(io, p->mem[Abar].size, 0);
-		if(io == 0){
-			print("%s: address %#lux in use, did %#ux\n",
-				tname[c->type], io, p->did);
-			continue;
-		}
-		/* ugly hack: get this in compatibility mode; see memory.c:271 */
-		if(io == 0x40000000) {
-			print("%s: did %#ux is in non-sata mode.  bar %#lux\n",
-				tname[c->type], p->did, p->mem[Abar].bar);
-			continue;
-		}
-		c->mmio = KADDR(io);
-		c->lmmio = (ulong*)c->mmio;
-		if(Intel(c->type) && p->did != 0x2681)
-			iasetupahci(c);
-		nunit = ahciconf(c);
-//		ahcihbareset((Ahba*)c->mmio);
-		if(Intel(c->type) && iaahcimode(p) == -1)
-			break;
-		if(nunit < 1){
-//			vunmap(c->mmio, p->mem[Abar].size);
-			continue;
-		}
-		niactlr++;
-		i = (c->hba->cap>>21) & 1;
-		print("%s: sata-%s with %d ports\n", tname[c->type],
-			"I\0II"+i*2, nunit);
-		s->ifc = &sdiahciifc;
-		s->ctlr = c;
-		s->nunit = nunit;
-		s->idno = 'E';
-		c->sdev = s;
-		c->ndrive = nunit;
-
-		/* map the drives -- they don't all need to be enabled. */
-		memset(c->rawdrive, 0, sizeof c->rawdrive);
-		n = 0;
-		for(i = 0; i < NCtlrdrv; i++) {
-			d = c->rawdrive+i;
-			d->portno = i;
-			d->driveno = -1;
-			d->sectors = 0;
-			d->ctlr = c;
-			if((c->hba->pi & (1<<i)) == 0)
-				continue;
-//			d->state = Dnew;
-			d->port = (Aport*)(c->mmio + 0x80*i + 0x100);
-			d->portc.p = d->port;
-			d->portc.m = &d->portm;
-			d->driveno = n++;
-			c->drive[d->driveno] = d;
-		}
-		for(i = 0; i < n; i++)
-			if(ahciidle(c->drive[i]->port) == -1){
-				print("%s: port %d wedged; abort\n",
-					tname[c->type], i);
-				goto loop;
-			}
-		for(i = 0; i < n; i++){
-			c->drive[i]->mode = DMsatai;
-			configdrive(c->drive[i]);
-		}
-
-		if(head)
-			tail->next = s;
-		else
-			head = s;
-		tail = s;
-	}
-	return head;
-}
-
-static SDev*
-iaid(SDev* sdev)
-{
-	int i;
-	Ctlr *c;
-
-	for(; sdev; sdev = sdev->next){
-		if(sdev->ifc != &sdiahciifc)
-			continue;
-		c = sdev->ctlr;
-		for(i = 0; i < NCtlr; i++)
-			if(c == iactlr + i)
-				sdev->idno = 'E' + i;
-	}
-	return nil;
-}
-
-SDifc sdiahciifc = {
-	"iahci",
-
-	iapnp,
-	nil,			/* legacy */
-	iaid,
-	iaenable,
-	iadisable,
-
-	iaverify,
-	iaonline,
-	iario,
-	nil,
-	nil,
-
-	scsibio,
-};
--- a/os/boot/pc/sdmylex.c
+++ /dev/null
@@ -1,1292 +1,0 @@
-/*
- * Mylex MultiMaster (Buslogic BT-*) SCSI Host Adapter
- * in both 24-bit and 32-bit mode.
- * 24-bit mode works for Adaptec AHA-154xx series too.
- *
- * To do:
- *	allocate more Ccb's as needed, up to NMbox-1;
- *	add nmbox and nccb to Ctlr struct for the above;
- *	64-bit LUN/explicit wide support necessary?
- *
- */
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-#include "ureg.h"
-#include "error.h"
-
-#include "sd.h"
-
-#define waserror()	(0)
-#define poperror()
-typedef struct QLock{ int r; } QLock;
-typedef struct Rendez{ int r; } Rendez;
-#define	intrenable(irq, f, c, tbdf, name)	setvec(VectorPIC+(irq), f, c);\
-						USED(tbdf);
-
-#define K2BPA(va, tbdf)	PADDR(va)
-#define BPA2K(pa, tbdf)	KADDR(pa)
-
-extern SDifc sdmylexifc;
-
-enum {					/* registers */
-	Rcontrol	= 0x00,		/* WO: control register */
-	Rstatus		= 0x00,		/* RO: status register */
-	Rcpr		= 0x01,		/* WO: command/parameter register */
-	Rdatain		= 0x01,		/* RO: data-in register */
-	Rinterrupt	= 0x02,		/* RO: interrupt register */
-};
-
-enum {					/* Rcontrol */
-	Rsbus		= 0x10,		/* SCSI Bus Reset */
-	Rint		= 0x20,		/* Interrupt Reset */
-	Rsoft		= 0x40,		/* Soft Reset */
-	Rhard		= 0x80,		/* Hard Reset */
-};
-
-enum {					/* Rstatus */
-	Cmdinv		= 0x01,		/* Command Invalid */
-	Dirrdy		= 0x04,		/* Data In Register Ready */
-	Cprbsy		= 0x08,		/* Command/Parameter Register Busy */
-	Hardy		= 0x10,		/* Host Adapter Ready */
-	Inreq		= 0x20,		/* Initialisation Required */
-	Dfail		= 0x40,		/* Diagnostic Failure */
-	Dact		= 0x80,		/* Diagnostic Active */
-};
-
-enum {					/* Rcpr */
-	Cinitialise	= 0x01,		/* Initialise Mailbox */
-	Cstart		= 0x02,		/* Start Mailbox Command */
-	Cinquiry	= 0x04,		/* Adapter Inquiry */
-	Ceombri		= 0x05,		/* Enable OMBR Interrupt */
-	Cinquire	= 0x0B,		/* Inquire Configuration */
-	Cextbios	= 0x28,		/* AHA-1542: extended BIOS info. */
-	Cmbienable	= 0x29,		/* AHA-1542: Mailbox interface enable */
-	Ciem		= 0x81,		/* Initialise Extended Mailbox */
-	Ciesi		= 0x8D,		/* Inquire Extended Setup Information */
-	Cerrm		= 0x8F,		/* Enable strict round-robin mode */
-	Cwide		= 0x96,		/* Wide CCB */
-};
-
-enum {					/* Rinterrupt */
-	Imbl		= 0x01,		/* Incoming Mailbox Loaded */
-	Mbor		= 0x02,		/* Mailbox Out Ready */
-	Cmdc		= 0x04,		/* Command Complete */
-	Rsts		= 0x08,		/* SCSI Reset State */
-	Intv		= 0x80,		/* Interrupt Valid */
-};
-
-typedef struct {
-	uchar	code;			/* action/completion code */
-	uchar	ccb[3];			/* CCB pointer (MSB, ..., LSB) */
-} Mbox24;
-
-typedef struct {
-	uchar	ccb[4];			/* CCB pointer (LSB, ..., MSB) */
-	uchar	btstat;			/* BT-7[45]7[SD] status */
-	uchar	sdstat;			/* SCSI device status */
-	uchar	pad;
-	uchar	code;			/* action/completion code */
-} Mbox32;
-
-enum {					/* mailbox commands */
-	Mbfree		= 0x00,		/* Mailbox not in use */
-
-	Mbostart	= 0x01,		/* Start a mailbox command */
-	Mboabort	= 0x02,		/* Abort a mailbox command */
-
-	Mbiok		= 0x01,		/* CCB completed without error */
-	Mbiabort	= 0x02,		/* CCB aborted at request of host */
-	Mbinx		= 0x03,		/* Aborted CCB not found */
-	Mbierror	= 0x04,		/* CCB completed with error */
-};
-
-typedef struct Ccb24 Ccb24;
-typedef struct Ccb32 Ccb32;
-typedef union Ccb Ccb;
-
-typedef struct Ccb24 {
-	uchar	opcode;			/* Operation code */
-	uchar	datadir;		/* Data direction control */
-	uchar	cdblen;			/* Length of CDB */
-	uchar	senselen;		/* Length of sense area */
-	uchar	datalen[3];		/* Data length (MSB, ..., LSB) */
-	uchar	dataptr[3];		/* Data pointer (MSB, ..., LSB) */
-	uchar	linkptr[3];		/* Link pointer (MSB, ..., LSB) */
-	uchar	linkid;			/* command linking identifier */
-	uchar	btstat;			/* BT-* adapter status */
-	uchar	sdstat;			/* SCSI device status */
-	uchar	reserved[2];		/* */
-	uchar	cs[12+0xFF];		/* Command descriptor block + Sense */
-
-	void*	data;			/* buffer if address > 24-bits */
-
-	Rendez;
-	int	done;			/* command completed */
-
-	Ccb*	ccb;			/* link on free list */
-} Ccb24;
-
-
-typedef struct Ccb32 {
-	uchar	opcode;			/* Operation code */
-	uchar	datadir;		/* Data direction control */
-	uchar	cdblen;			/* Length of CDB */
-	uchar	senselen;		/* Length of sense area */
-	uchar	datalen[4];		/* Data length (LSB, ..., MSB) */
-	uchar	dataptr[4];		/* Data pointer (LSB, ..., MSB) */
-	uchar	reserved[2];
-	uchar	btstat;			/* BT-* adapter status */
-	uchar	sdstat;			/* SCSI device status */
-	uchar	targetid;		/* Target ID */
-	uchar	luntag;			/* LUN & tag */
-	uchar	cdb[12];		/* Command descriptor block */
-	uchar	ccbctl;			/* CCB control */
-	uchar	linkid;			/* command linking identifier */
-	uchar	linkptr[4];		/* Link pointer (LSB, ..., MSB) */
-	uchar	senseptr[4];		/* Sense pointer (LSB, ..., MSB) */
-	uchar	sense[0xFF];		/* Sense bytes */
-
-	Rendez;
-	int	done;			/* command completed */
-
-	Ccb*	ccb;			/* link on free list */
-} Ccb32;
-
-typedef union Ccb {
-	Ccb24;
-	Ccb32;
-} Ccb;
-
-enum {					/* opcode */
-	OInitiator	= 0x00,		/* initiator CCB */
-	Ordl		= 0x03,		/* initiator CCB with
-					 * residual data length returned
-					 */
-};
-
-enum {					/* datadir */
-	CCBdatain	= 0x08,		/* inbound, length is checked */
-	CCBdataout	= 0x10,		/* outbound, length is checked */
-};
-
-enum {					/* btstat */
-	Eok		= 0x00,		/* normal completion with no errors */
-};
-
-enum {					/* luntag */
-	TagEnable	= 0x20,		/* Tag enable */
-	SQTag		= 0x00,		/* Simple Queue Tag */
-	HQTag		= 0x40,		/* Head of Queue Tag */
-	OQTag		= 0x80,		/* Ordered Queue Tag */
-};
-
-enum {					/* CCB control */
-	NoDisc		= 0x08,		/* No disconnect */
-	NoUnd		= 0x10,		/* No underrrun error report */
-	NoData		= 0x20,		/* No data transfer */
-	NoStat		= 0x40,		/* No CCB status if zero */
-	NoIntr		= 0x80,		/* No Interrupts */
-};
-
-typedef struct {
-	int	port;			/* I/O port */
-	int	id;			/* adapter SCSI id */
-	int	bus;			/* 24 or 32 -bit */
-	int	irq;
-	int	wide;
-	Pcidev*	pcidev;
-	SDev*	sdev;
-	int	spurious;
-
-	Lock	issuelock;
-
-	Lock	ccblock;
-	QLock	ccbq;
-	Rendez	ccbr;
-
-	Lock	mboxlock;
-	void*	mb;			/* mailbox out + mailbox in */
-	int	mbox;			/* current mailbox out index into mb */
-	int	mbix;			/* current mailbox in index into mb */
-
-	Lock	cachelock;
-	Ccb*	ccb;			/* list of free Ccb's */
-	Ccb**	cache;			/* last completed Ccb */
-} Ctlr;
-
-/*
- * The number of mailboxes should be a multiple of 8 (4 for Mbox32)
- * to ensure the boundary between the out and in mailboxes doesn't
- * straddle a cache-line boundary.
- * The number of Ccb's should be less than the number of mailboxes to
- * ensure no queueing is necessary on mailbox allocation.
- */
-enum {
-	NMbox		= 8*8,		/* number of Mbox's */
-	NCcb		= NMbox-1,	/* number of Ccb's */
-};
-
-#define PADDR24(a, n)	((PADDR(a)+(n)) <= (1<<24))
-
-static void
-ccbfree(Ctlr* ctlr, Ccb* ccb)
-{
-	lock(&ctlr->ccblock);
-	if(ctlr->bus == 24)
-		((Ccb24*)ccb)->ccb = ctlr->ccb;
-	else
-		((Ccb32*)ccb)->ccb = ctlr->ccb;
-	if(ctlr->ccb == nil)
-		wakeup(&ctlr->ccbr);
-	ctlr->ccb = ccb;
-	unlock(&ctlr->ccblock);
-}
-
-static int
-ccbavailable(void* a)
-{
-	return ((Ctlr*)a)->ccb != nil;
-}
-
-static Ccb*
-ccballoc(Ctlr* ctlr)
-{
-	Ccb *ccb;
-
-	for(;;){
-		lock(&ctlr->ccblock);
-		if((ccb = ctlr->ccb) != nil){
-			if(ctlr->bus == 24)
-				 ctlr->ccb = ((Ccb24*)ccb)->ccb;
-			else
-				 ctlr->ccb = ((Ccb32*)ccb)->ccb;
-			unlock(&ctlr->ccblock);
-			break;
-		}
-
-		unlock(&ctlr->ccblock);
-		qlock(&ctlr->ccbq);
-		if(waserror()){
-			qunlock(&ctlr->ccbq);
-			continue;
-		}
-		sleep(&ctlr->ccbr, ccbavailable, ctlr);
-		qunlock(&ctlr->ccbq);
-		poperror();
-	}
-
-	return ccb;
-}
-
-static int
-done24(void* arg)
-{
-	return ((Ccb24*)arg)->done;
-}
-
-static int
-mylex24rio(SDreq* r)
-{
-	ulong p;
-	Ctlr *ctlr;
-	Ccb24 *ccb;
-	Mbox24 *mb;
-	uchar *data, lun, *sense;
-	int d, n, btstat, sdstat, target;
-
-	ctlr = r->unit->dev->ctlr;
-	target = r->unit->subno;
-	lun = (r->cmd[1]>>5) & 0x07;
-
-	/*
-	 * Ctlr->cache holds the last completed Ccb for this target if it
-	 * returned 'check condition'.
-	 * If this command is a request-sense and there is valid sense data
-	 * from the last completed Ccb, return it immediately.
-	 */
-	lock(&ctlr->cachelock);
-	if((ccb = ctlr->cache[target]) != nil){
-		ctlr->cache[target] = nil;
-		if(r->cmd[0] == 0x03
-		&& ccb->sdstat == SDcheck && lun == ((ccb->cs[1]>>5) & 0x07)){
-			unlock(&ctlr->cachelock);
-			if(r->dlen){
-				sense = &ccb->cs[ccb->cdblen];
-				n = 8+sense[7];
-				if(n > r->dlen)
-					n = r->dlen;
-				memmove(r->data, sense, n);
-				r->rlen = n;
-			}
-			ccbfree(ctlr, (Ccb*)ccb);
-			return SDok;
-		}
-	}
-	unlock(&ctlr->cachelock);
-	if(ccb == nil)
-		ccb = ccballoc(ctlr);
-
-	/*
-	 * Check if the transfer is to memory above the 24-bit limit the
-	 * controller can address. If it is, try to allocate a temporary
-	 * buffer as a staging area.
-	 */
-	n = r->dlen;
-	if(n && !PADDR24(r->data, n)){
-		data = mallocz(n, 0);
-		if(data == nil || !PADDR24(data, n)){
-			if(data != nil){
-				free(data);
-				ccb->data = nil;
-			}
-			ccbfree(ctlr, (Ccb*)ccb);
-			return SDmalloc;
-		}
-		if(r->write)
-			memmove(data, r->data, n);
-		ccb->data = r->data;
-	}
-	else
-		data = r->data;
-
-	/*
-	 * Fill in the ccb.
-	 */
-	ccb->opcode = Ordl;
-
-	ccb->datadir = (target<<5)|lun;
-	if(n == 0)
-		ccb->datadir |= CCBdataout|CCBdatain;
-	else if(!r->write)
-		ccb->datadir |= CCBdatain;
-	else
-		ccb->datadir |= CCBdataout;
-
-	ccb->cdblen = r->clen;
-	ccb->senselen = 0xFF;
-
-	ccb->datalen[0] = n>>16;
-	ccb->datalen[1] = n>>8;
-	ccb->datalen[2] = n;
-	p = PADDR(data);
-	ccb->dataptr[0] = p>>16;
-	ccb->dataptr[1] = p>>8;
-	ccb->dataptr[2] = p;
-
-	ccb->linkptr[0] = ccb->linkptr[1] = ccb->linkptr[2] = 0;
-	ccb->linkid = 0;
-	ccb->btstat = ccb->sdstat = 0;
-	ccb->reserved[0] = ccb->reserved[1] = 0;
-
-	memmove(ccb->cs, r->cmd, r->clen);
-
-	/*
-	 * There's one more mbox than there there is
-	 * ccb so there is always one free.
-	 */
-	lock(&ctlr->mboxlock);
-	mb = ctlr->mb;
-	mb += ctlr->mbox;
-	p = PADDR(ccb);
-	mb->ccb[0] = p>>16;
-	mb->ccb[1] = p>>8;
-	mb->ccb[2] = p;
-	mb->code = Mbostart;
-	ctlr->mbox++;
-	if(ctlr->mbox >= NMbox)
-		ctlr->mbox = 0;
-
-	/*
-	 * This command does not require Hardy
-	 * and doesn't generate a Cmdc interrupt.
-	 */
-	ccb->done = 0;
-	outb(ctlr->port+Rcpr, Cstart);
-	unlock(&ctlr->mboxlock);
-
-	/*
-	 * Wait for the request to complete and return the status.
-	 * Since the buffer is not reference counted cannot return
-	 * until the DMA is done writing into the buffer so the caller
-	 * cannot free the buffer prematurely.
-	 */
-	while(waserror())
-		;
-	tsleep(ccb, done24, ccb, 30*1000);
-	poperror();
-
-	if(!done24(ccb)){
-		print("%s: %d/%d: sd24rio timeout\n",
-			"sdmylex"/*ctlr->sdev->name*/, target, r->lun);
-		if(ccb->data != nil){
-			free(data);
-			ccb->data = nil;
-		}
-		ccbfree(ctlr, (Ccb*)ccb);
-
-		return SDtimeout;
-	}
-
-	/*
-	 * Save the status and patch up the number of
-	 * bytes actually transferred.
-	 * There's a firmware bug on some 956C controllers
-	 * which causes the return count from a successful
-	 * READ CAPACITY not be updated, so fix it here.
-	 */
-	sdstat = ccb->sdstat;
-	btstat = ccb->btstat;
-
-	d = ccb->datalen[0]<<16;
-	d |= ccb->datalen[1]<<8;
-	d |= ccb->datalen[2];
-	if(ccb->cs[0] == 0x25 && sdstat == SDok)
-		d = 0;
-	n -= d;
-	r->rlen = n;
-
-	/*
-	 * Tidy things up if a staging area was used for the data,
-	 */
-	if(ccb->data != nil){
-		if(sdstat == SDok && btstat == 0 && !r->write)
-			memmove(ccb->data, data, n);
-		free(data);
-		ccb->data = nil;
-	}
-
-	/*
-	 * If there was a check-condition, save the
-	 * ccb for a possible request-sense command.
-	 */
-	if(sdstat == SDcheck){
-		if(r->flags & SDnosense){
-			lock(&ctlr->cachelock);
-			if(ctlr->cache[target])
-				ccbfree(ctlr, ctlr->cache[target]);
-			ctlr->cache[target] = (Ccb*)ccb;
-			unlock(&ctlr->cachelock);
-			return SDcheck;
-		}
-		sense = &ccb->cs[ccb->cdblen];
-		n = 8+sense[7];
-		if(n > sizeof(r->sense)-1)
-			n = sizeof(r->sense)-1;
-		memmove(r->sense, sense, n);
-		r->flags |= SDvalidsense;
-	}
-	ccbfree(ctlr, (Ccb*)ccb);
-
-	if(btstat){
-		if(btstat == 0x11)
-			return SDtimeout;
-		return SDeio;
-	}
-	return sdstat;
-}
-
-static void
-mylex24interrupt(Ureg*, void* arg)
-{
-	ulong pa;
-	Ctlr *ctlr;
-	Ccb24 *ccb;
-	Mbox24 *mb, *mbox;
-	int port, rinterrupt, rstatus;
-
-	ctlr = arg;
-	port = ctlr->port;
-
-	/*
-	 * Save and clear the interrupt(s). The only
-	 * interrupts expected are Cmdc, which is ignored,
-	 * and Imbl which means something completed.
-	 * There's one spurious interrupt left over from
-	 * initialisation, ignore it.
-	 */
-	rinterrupt = inb(port+Rinterrupt);
-	rstatus = inb(port+Rstatus);
-	outb(port+Rcontrol, Rint);
-	if((rinterrupt & ~(Cmdc|Imbl)) != Intv && ctlr->spurious++)
-		print("%s: interrupt 0x%2.2ux\n",
-			"sdmylex"/*ctlr->sdev->name*/, rinterrupt);
-	if((rinterrupt & Cmdc) && (rstatus & Cmdinv))
-		print("%s: command invalid\n", "sdmylex"/*ctlr->sdev->name*/);
-
-	/*
-	 * Look for something in the mail.
-	 * If there is, save the status, free the mailbox
-	 * and wakeup whoever.
-	 */
-	mb = ctlr->mb;
-	for(mbox = &mb[ctlr->mbix]; mbox->code; mbox = &mb[ctlr->mbix]){
-		pa = (mbox->ccb[0]<<16)|(mbox->ccb[1]<<8)|mbox->ccb[2];
-		ccb = BPA2K(pa, BUSUNKNOWN);
-		mbox->code = 0;
-		ccb->done = 1;
-		wakeup(ccb);
-
-		ctlr->mbix++;
-		if(ctlr->mbix >= NMbox+NMbox)
-			ctlr->mbix = NMbox;
-	}
-}
-
-static int
-done32(void* arg)
-{
-	return ((Ccb32*)arg)->done;
-}
-
-static int
-mylex32rio(SDreq* r)
-{
-	ulong p;
-	uchar lun;
-	Ctlr *ctlr;
-	Ccb32 *ccb;
-	Mbox32 *mb;
-	int d, n, btstat, sdstat, target;
-
-	ctlr = r->unit->dev->ctlr;
-	target = r->unit->subno;
-	lun = (r->cmd[1]>>5) & 0x07;
-
-	/*
-	 * Ctlr->cache holds the last completed Ccb for this target if it
-	 * returned 'check condition'.
-	 * If this command is a request-sense and there is valid sense data
-	 * from the last completed Ccb, return it immediately.
-	 */
-	lock(&ctlr->cachelock);
-	if((ccb = ctlr->cache[target]) != nil){
-		ctlr->cache[target] = nil;
-		if(r->cmd[0] == 0x03
-		&& ccb->sdstat == SDcheck && lun == (ccb->luntag & 0x07)){
-			unlock(&ctlr->cachelock);
-			if(r->dlen){
-				n = 8+ccb->sense[7];
-				if(n > r->dlen)
-					n = r->dlen;
-				memmove(r->data, ccb->sense, n);
-				r->rlen = n;
-			}
-			ccbfree(ctlr, (Ccb*)ccb);
-			return SDok;
-		}
-	}
-	unlock(&ctlr->cachelock);
-	if(ccb == nil)
-		ccb = ccballoc(ctlr);
-
-	/*
-	 * Fill in the ccb.
-	 */
-	ccb->opcode = Ordl;
-
-	n = r->dlen;
-	if(n == 0)
-		ccb->datadir = CCBdataout|CCBdatain;
-	else if(!r->write)
-		ccb->datadir = CCBdatain;
-	else
-		ccb->datadir = CCBdataout;
-
-	ccb->cdblen = r->clen;
-
-	ccb->datalen[0] = n;
-	ccb->datalen[1] = n>>8;
-	ccb->datalen[2] = n>>16;
-	ccb->datalen[3] = n>>24;
-	p = PADDR(r->data);
-	ccb->dataptr[0] = p;
-	ccb->dataptr[1] = p>>8;
-	ccb->dataptr[2] = p>>16;
-	ccb->dataptr[3] = p>>24;
-
-	ccb->targetid = target;
-	ccb->luntag = lun;
-	if(r->unit->inquiry[7] & 0x02)
-		ccb->luntag |= SQTag|TagEnable;
-	memmove(ccb->cdb, r->cmd, r->clen);
-	ccb->btstat = ccb->sdstat = 0;
-	ccb->ccbctl = 0;
-
-	/*
-	 * There's one more mbox than there there is
-	 * ccb so there is always one free.
-	 */
-	lock(&ctlr->mboxlock);
-	mb = ctlr->mb;
-	mb += ctlr->mbox;
-	p = PADDR(ccb);
-	mb->ccb[0] = p;
-	mb->ccb[1] = p>>8;
-	mb->ccb[2] = p>>16;
-	mb->ccb[3] = p>>24;
-	mb->code = Mbostart;
-	ctlr->mbox++;
-	if(ctlr->mbox >= NMbox)
-		ctlr->mbox = 0;
-
-	/*
-	 * This command does not require Hardy
-	 * and doesn't generate a Cmdc interrupt.
-	 */
-	ccb->done = 0;
-	outb(ctlr->port+Rcpr, Cstart);
-	unlock(&ctlr->mboxlock);
-
-	/*
-	 * Wait for the request to complete and return the status.
-	 * Since the buffer is not reference counted cannot return
-	 * until the DMA is done writing into the buffer so the caller
-	 * cannot free the buffer prematurely.
-	 */
-	while(waserror())
-		;
-	tsleep(ccb, done32, ccb, 30*1000);
-	poperror();
-
-	if(!done32(ccb)){
-		print("%s: %d/%d: sd32rio timeout\n",
-			"sdmylex"/*ctlr->sdev->name*/, target, r->lun);
-		ccbfree(ctlr, (Ccb*)ccb);
-
-		return SDtimeout;
-	}
-
-	/*
-	 * Save the status and patch up the number of
-	 * bytes actually transferred.
-	 * There's a firmware bug on some 956C controllers
-	 * which causes the return count from a successful
-	 * READ CAPACITY not to be updated, so fix it here.
-	 */
-	sdstat = ccb->sdstat;
-	btstat = ccb->btstat;
-
-	d = ccb->datalen[0];
-	d |= (ccb->datalen[1]<<8);
-	d |= (ccb->datalen[2]<<16);
-	d |= (ccb->datalen[3]<<24);
-	if(ccb->cdb[0] == 0x25 && sdstat == SDok)
-		d = 0;
-	n -= d;
-	r->rlen = n;
-
-	/*
-	 * If there was a check-condition, save the
-	 * ccb for a possible request-sense command.
-	 */
-	if(sdstat == SDcheck){
-		if(r->flags & SDnosense){
-			lock(&ctlr->cachelock);
-			if(ctlr->cache[target])
-				ccbfree(ctlr, ctlr->cache[target]);
-			ctlr->cache[target] = (Ccb*)ccb;
-			unlock(&ctlr->cachelock);
-			return SDcheck;
-		}
-		n = 8+ccb->sense[7];
-		if(n > sizeof(r->sense)-1)
-			n = sizeof(r->sense)-1;
-		memmove(r->sense, ccb->sense, n);
-		r->flags |= SDvalidsense;
-	}
-	ccbfree(ctlr, (Ccb*)ccb);
-
-	if(btstat){
-		if(btstat == 0x11)
-			return SDtimeout;
-		return SDeio;
-	}
-	return sdstat;
-}
-
-static void
-mylex32interrupt(Ureg*, void* arg)
-{
-	ulong pa;
-	Ctlr *ctlr;
-	Ccb32 *ccb;
-	Mbox32 *mb, *mbox;
-	int port, rinterrupt, rstatus;
-
-	ctlr = arg;
-	port = ctlr->port;
-
-	/*
-	 * Save and clear the interrupt(s). The only
-	 * interrupts expected are Cmdc, which is ignored,
-	 * and Imbl which means something completed.
-	 * There's one spurious interrupt left over from
-	 * initialisation, ignore it.
-	 */
-	rinterrupt = inb(port+Rinterrupt);
-	rstatus = inb(port+Rstatus);
-	outb(port+Rcontrol, Rint);
-	if((rinterrupt & ~(Cmdc|Imbl)) != Intv && ctlr->spurious++)
-		print("%s: interrupt 0x%2.2ux\n",
-			"sdmylex"/*ctlr->sdev->name*/, rinterrupt);
-	if((rinterrupt & Cmdc) && (rstatus & Cmdinv))
-		print("%s: command invalid\n", "sdmylex"/*ctlr->sdev->name*/);
-
-	/*
-	 * Look for something in the mail.
-	 * If there is, free the mailbox and wakeup whoever.
-	 */
-	mb = ctlr->mb;
-	for(mbox = &mb[ctlr->mbix]; mbox->code; mbox = &mb[ctlr->mbix]){
-		pa = (mbox->ccb[3]<<24)
-		    |(mbox->ccb[2]<<16)
-		    |(mbox->ccb[1]<<8)
-		    |mbox->ccb[0];
-		if(ctlr->pcidev)
-			ccb = BPA2K(pa, ctlr->pcidev->tbdf);
-		else
-			ccb = BPA2K(pa, BUSUNKNOWN);
-		mbox->code = 0;
-		ccb->done = 1;
-		wakeup(ccb);
-
-		ctlr->mbix++;
-		if(ctlr->mbix >= NMbox+NMbox)
-			ctlr->mbix = NMbox;
-	}
-}
-
-static int
-mylexrio(SDreq* r)
-{
-	int subno;
-	Ctlr *ctlr;
-
-	subno = r->unit->subno;
-	ctlr = r->unit->dev->ctlr;
-	if(subno == ctlr->id || (!ctlr->wide && subno >= 8))
-		r->status = SDtimeout;
-	else if(ctlr->bus == 24)
-		r->status = mylex24rio(r);
-	else
-		r->status = mylex32rio(r);
-	return r->status;
-}
-
-/*
- * Issue a command to a controller. The command and its length is
- * contained in cmd and cmdlen. If any data is to be
- * returned, datalen should be non-zero, and the returned data
- * will be placed in data.
- * If Cmdc is set, bail out, the invalid command will be handled
- * when the interrupt is processed.
- */
-static void
-issueio(int port, uchar* cmd, int cmdlen, uchar* data, int datalen)
-{
-	int len;
-
-	if(cmd[0] != Cstart && cmd[0] != Ceombri){
-		while(!(inb(port+Rstatus) & Hardy))
-			;
-	}
-	outb(port+Rcpr, cmd[0]);
-
-	len = 1;
-	while(len < cmdlen){
-		if(!(inb(port+Rstatus) & Cprbsy)){
-			outb(port+Rcpr, cmd[len]);
-			len++;
-		}
-		if(inb(port+Rinterrupt) & Cmdc)
-			return;
-	}
-
-	if(datalen){
-		len = 0;
-		while(len < datalen){
-			if(inb(port+Rstatus) & Dirrdy){
-				data[len] = inb(port+Rdatain);
-				len++;
-			}
-			if(inb(port+Rinterrupt) & Cmdc)
-				return;
-		}
-	}
-}
-
-/*
- * Issue a command to a controller, wait for it to complete then
- * try to reset the interrupt. Should only be called at initialisation.
- */
-static int
-issue(Ctlr* ctlr, uchar* cmd, int cmdlen, uchar* data, int datalen)
-{
-	int port;
-	uchar rinterrupt, rstatus;
-	static Lock mylexissuelock;
-
-	port = ctlr->port;
-
-	ilock(&ctlr->issuelock);
-	issueio(port, cmd, cmdlen, data, datalen);
-
-	while(!((rinterrupt = inb(port+Rinterrupt)) & Cmdc))
-		;
-
-	rstatus = inb(port+Rstatus);
-	outb(port+Rcontrol, Rint);
-	iunlock(&ctlr->issuelock);
-
-	if((rinterrupt & Cmdc) && (rstatus & Cmdinv))
-		return 0;
-	return 1;
-}
-
-static SDev*
-mylexprobe(int port, int irq)
-{
-	SDev *sdev;
-	Ctlr *ctlr;
-	uchar cmd[6], data[256];
-	int clen, dlen, timeo;
-
-	if(ioalloc(port, 0x3, 0, "mylex") < 0)
-		return nil;
-	ctlr = nil;
-
-	/*
-	 * Attempt to hard-reset the board and reset
-	 * the SCSI bus. If the board state doesn't settle to
-	 * idle with mailbox initialisation required, either
-	 * it isn't a compatible board or it's broken.
-	 * If the controller has SCAM set this can take a while.
-	 */
-	if(getconf("*noscsireset") != nil)
-		outb(port+Rcontrol, Rhard);
-	else
-		outb(port+Rcontrol, Rhard|Rsbus);
-	for(timeo = 0; timeo < 100; timeo++){
-		if(inb(port+Rstatus) == (Inreq|Hardy))
-			break;
-		delay(100);
-	}
-	if(inb(port+Rstatus) != (Inreq|Hardy)){
-buggery:
-		if(ctlr != nil)
-			free(ctlr);
-		iofree(port);
-		return nil;
-	}
-
-	if((ctlr = malloc(sizeof(Ctlr))) == nil)
-		goto buggery;
-	ctlr->port = port;
-	ctlr->irq = irq;
-	ctlr->bus = 24;
-	ctlr->wide = 0;
-
-	/*
-	 * Try to determine if this is a 32-bit MultiMaster controller
-	 * by attempting to obtain the extended inquiry information;
-	 * this command is not implemented on Adaptec 154xx
-	 * controllers. If successful, the first byte of the returned
-	 * data is the host adapter bus type, 'E' for 32-bit EISA,
-	 * PCI and VLB buses.
-	 */
-	cmd[0] = Ciesi;
-	cmd[1] = 14;
-	clen = 2;
-	dlen = 256;
-	if(issue(ctlr, cmd, clen, data, dlen)){
-		if(data[0] == 'E')
-			ctlr->bus = 32;
-		ctlr->wide = data[0x0D] & 0x01;
-	}
-	else{
-		/*
-		 * Inconceivable though it may seem, a hard controller reset
-		 * is necessary here to clear out the command queue. Every
-		 * board seems to lock-up in a different way if you give an
-		 * invalid command and then try to clear out the
-		 * command/parameter and/or data-in register.
-		 * Soft reset doesn't do the job either. Fortunately no
-		 * serious initialisation has been done yet so there's nothing
-		 * to tidy up.
-		 */
-		outb(port+Rcontrol, Rhard);
-		for(timeo = 0; timeo < 100; timeo++){
-			if(inb(port+Rstatus) == (Inreq|Hardy))
-				break;
-			delay(100);
-		}
-		if(inb(port+Rstatus) != (Inreq|Hardy))
-			goto buggery;
-	}
-
-	/*
-	 * If the BIOS is enabled on the AHA-1542C/CF and BIOS options for
-	 * support of drives > 1Gb, dynamic scanning of the SCSI bus or more
-	 * than 2 drives under DOS 5.0 are enabled, the BIOS disables
-	 * accepting Cmbinit to protect against running with drivers which
-	 * don't support those options. In order to unlock the interface it
-	 * is necessary to read a lock-code using Cextbios and write it back
-	 * using Cmbienable; the lock-code is non-zero.
-	 */
-	cmd[0] = Cinquiry;
-	clen = 1;
-	dlen = 4;
-	if(issue(ctlr, cmd, clen, data, dlen) == 0)
-		goto buggery;
-	if(data[0] >= 0x43){
-		cmd[0] = Cextbios;
-		clen = 1;
-		dlen = 2;
-		if(issue(ctlr, cmd, clen, data, dlen) == 0)
-			goto buggery;
-
-		/*
-		 * Lock-code returned in data[1]. If it's non-zero write
-		 * it back along with bit 0 of byte 0 cleared to enable
-		 * mailbox initialisation.
-		 */
-		if(data[1]){
-			cmd[0] = Cmbienable;
-			cmd[1] = 0;
-			cmd[2] = data[1];
-			clen = 3;
-			if(issue(ctlr, cmd, clen, 0, 0) == 0)
-				goto buggery;
-		}
-	}
-
-	/*
-	 * Get the id, DMA and IRQ info from the board. This will
-	 * cause an interrupt which will hopefully not cause any
-	 * trouble because the interrupt number isn't known yet.
-	 * This is necessary as the DMA won't be set up if the
-	 * board has the BIOS disabled.
-	 *
-	 * If the IRQ is already known, this must be a 32-bit PCI
-	 * or EISA card, in which case the returned DMA and IRQ can
-	 * be ignored.
-	 */
-	cmd[0] = Cinquire;
-	clen = 1;
-	dlen = 3;
-	if(issue(ctlr, cmd, clen, data, dlen) == 0)
-		goto buggery;
-
-	ctlr->id = data[2] & 0x07;
-	if(ctlr->irq < 0){
-		switch(data[0]){		/* DMA Arbitration Priority */
-		case 0x80:			/* Channel 7 */
-			outb(0xD6, 0xC3);
-			outb(0xD4, 0x03);
-			break;
-		case 0x40:			/* Channel 6 */
-			outb(0xD6, 0xC2);
-			outb(0xD4, 0x02);
-			break;
-		case 0x20:			/* Channel 5 */
-			outb(0xD6, 0xC1);
-			outb(0xD4, 0x01);
-			break;
-		case 0x01:			/* Channel 0 */
-			outb(0x0B, 0xC0);
-			outb(0x0A, 0x00);
-			break;
-		default:
-			if(ctlr->bus == 24)
-				goto buggery;
-			break;
-		}
-	
-		switch(data[1]){		/* Interrupt Channel */
-		case 0x40:
-			ctlr->irq = 15;
-			break;
-		case 0x20:
-			ctlr->irq = 14;
-			break;
-		case 0x08:
-			ctlr->irq = 12;
-			break;
-		case 0x04:
-			ctlr->irq = 11;
-			break;
-		case 0x02:
-			ctlr->irq = 10;
-			break;
-		case 0x01:
-			ctlr->irq = 9;
-			break;
-		default:
-			goto buggery;
-		}
-	}
-
-	if((sdev = malloc(sizeof(SDev))) == nil)
-		goto buggery;
-	sdev->ifc = &sdmylexifc;
-	sdev->ctlr = ctlr;
-	ctlr->sdev = sdev;
-	if(!ctlr->wide)
-		sdev->nunit = 8;
-	else
-		sdev->nunit = 16;
-
-	return sdev;
-}
-
-static int mylexport[8] = {
-	0x330, 0x334, 0x230, 0x234, 0x130, 0x134, 0x000, 0x000,
-};
-
-static SDev*
-mylexpnp(void)
-{
-	Pcidev *p;
-	Ctlr *ctlr;
-	ISAConf isa;
-	int cfg, ctlrno, i, x;
-	SDev *sdev, *head, *tail;
-
-	p = nil;
-	head = tail = nil;
-	while(p = pcimatch(p, 0x104B, 0)){
-		if((sdev = mylexprobe(p->mem[0].bar & ~0x01, p->intl)) == nil)
-			continue;
-
-		ctlr = sdev->ctlr;
-		ctlr->pcidev = p;
-
-		if(head != nil)
-			tail->next = sdev;
-		else
-			head = sdev;
-		tail = sdev;
-	}
-
-	if(strncmp(KADDR(0xFFFD9), "EISA", 4) == 0){
-		for(cfg = 0x1000; cfg < MaxEISA*0x1000; cfg += 0x1000){
-			x = 0;
-			for(i = 0; i < 4; i++)
-				x |= inb(cfg+CfgEISA+i)<<(i*8);
-			if(x != 0x0142B30A && x != 0x0242B30A)
-				continue;
-	
-			x = inb(cfg+0xC8C);
-			if((sdev = mylexprobe(mylexport[x & 0x07], -1)) == nil)
-				continue;
-	
-			if(head != nil)
-				tail->next = sdev;
-			else
-				head = sdev;
-			tail = sdev;
-		}
-	}
-
-	for(ctlrno = 0; ctlrno < 4; ctlrno++){
-		memset(&isa, 0, sizeof(isa));
-		if(!isaconfig("scsi", ctlrno, &isa))
-			continue;
-		if(strcmp(isa.type, "aha1542"))
-			continue;
-		if((sdev = mylexprobe(isa.port, -1)) == nil)
-			continue;
-
-		if(head != nil)
-			tail->next = sdev;
-		else
-			head = sdev;
-		tail = sdev;
-	}
-
-	return head;
-}
-
-static SDev*
-mylexid(SDev* sdev)
-{
-	return scsiid(sdev, &sdmylexifc);
-}
-
-static int
-mylex24enable(Ctlr* ctlr)
-{
-	ulong p;
-	Ccb24 *ccb, *ccbp;
-	uchar cmd[6], *v;
-	int len;
-
-	len = (sizeof(Mbox24)*NMbox*2)+(sizeof(Ccb24)*NCcb);
-	v = xspanalloc(len, 32, 0);
-
-	if(!PADDR24(ctlr, sizeof(Ctlr)) || !PADDR24(v, len))
-		return 0;
-
-	ctlr->mb = v;
-	v += sizeof(Mbox24)*NMbox*2;
-
-	ccb = (Ccb24*)v;
-	for(ccbp = ccb; ccbp < &ccb[NCcb]; ccbp++){
-		ccbp->ccb = ctlr->ccb;
-		ctlr->ccb = (Ccb*)ccbp;
-	}
-
-	/*
-	 * Initialise the software controller and
-	 * set the board scanning the mailboxes.
-	 */
-	ctlr->mbix = NMbox;
-
-	cmd[0] = Cinitialise;
-	cmd[1] = NMbox;
-	p = K2BPA(ctlr->mb, BUSUNKNOWN);
-	cmd[2] = p>>16;
-	cmd[3] = p>>8;
-	cmd[4] = p;
-
-	return issue(ctlr, cmd, 5, 0, 0);
-}
-
-static int
-mylex32enable(Ctlr* ctlr)
-{
-	ulong p;
-	Ccb32 *ccb, *ccbp;
-	uchar cmd[6], *v;
-
-	v = xspanalloc((sizeof(Mbox32)*NMbox*2)+(sizeof(Ccb32)*NCcb), 32, 0);
-
-	ctlr->mb = v;
-	v += sizeof(Mbox32)*NMbox*2;
-
-	ccb = (Ccb32*)v;
-	for(ccbp = ccb; ccbp < &ccb[NCcb]; ccbp++){
-		/*
-		 * Fill in some stuff that doesn't change.
-		 */
-		ccbp->senselen = sizeof(ccbp->sense);
-		p = PADDR(ccbp->sense);
-		ccbp->senseptr[0] = p;
-		ccbp->senseptr[1] = p>>8;
-		ccbp->senseptr[2] = p>>16;
-		ccbp->senseptr[3] = p>>24;
-
-		ccbp->ccb = ctlr->ccb;
-		ctlr->ccb = (Ccb*)ccbp;
-	}
-
-	/*
-	 * Attempt wide mode setup.
-	 */
-	if(ctlr->wide){
-		cmd[0] = Cwide;
-		cmd[1] = 1;
-		if(!issue(ctlr, cmd, 2, 0, 0))
-			ctlr->wide = 0;
-	}
-
-	/*
-	 * Initialise the software controller and
-	 * set the board scanning the mailboxes.
-	 */
-	ctlr->mbix = NMbox;
-
-	cmd[0] = Ciem;
-	cmd[1] = NMbox;
-	if(ctlr->pcidev)
-		p = K2BPA(ctlr->mb, ctlr->tbdf);
-	else
-		p = K2BPA(ctlr->mb, BUSUNKNOWN);
-	cmd[2] = p;
-	cmd[3] = p>>8;
-	cmd[4] = p>>16;
-	cmd[5] = p>>24;
-
-	return issue(ctlr, cmd, 6, 0, 0);
-}
-
-static int
-mylexenable(SDev* sdev)
-{
-	int tbdf;
-	Ctlr *ctlr;
-	void (*interrupt)(Ureg*, void*);
-	char name[NAMELEN];
-
-	ctlr = sdev->ctlr;
-	if(ctlr->cache == nil){
-		if((ctlr->cache = malloc(sdev->nunit*sizeof(Ccb*))) == nil)
-			return 0;
-	}
-
-	tbdf = BUSUNKNOWN;
-	if(ctlr->bus == 32){
-		if(ctlr->pcidev){
-			tbdf = ctlr->pcidev->tbdf;
-			pcisetbme(ctlr->pcidev);
-		}
-		if(!mylex32enable(ctlr))
-			return 0;
-		interrupt = mylex32interrupt;
-	}
-	else if(mylex24enable(ctlr))
-		interrupt = mylex24interrupt;
-	else
-		return 0;
-
-	snprint(name, NAMELEN, "sd%c (%s)", sdev->idno, sdev->ifc->name);
-	intrenable(ctlr->irq, interrupt, ctlr, tbdf, name);
-
-	return 1;
-}
-
-static int
-mylexdisable(SDev* sdev)
-{
-	Ctlr *ctlr;
-	int port, timeo;
-
-	ctlr = sdev->ctlr;
-	port = ctlr->port;
-
-	if(getconf("*noscsireset") != nil)
-		outb(port+Rcontrol, Rhard);
-	else
-		outb(port+Rcontrol, Rhard|Rsbus);
-	for(timeo = 0; timeo < 100; timeo++){
-		if(inb(port+Rstatus) == (Inreq|Hardy))
-			break;
-		delay(100);
-	}
-	if(inb(port+Rstatus) != (Inreq|Hardy))
-		return 0;
-
-	return 1;
-}
-
-SDifc sdmylexifc = {
-	"mylex",			/* name */
-
-	mylexpnp,			/* pnp */
-	nil,				/* legacy */
-	mylexid,			/* id */
-	mylexenable,			/* enable */
-	mylexdisable,			/* disable */
-
-	scsiverify,			/* verify */
-	scsionline,			/* online */
-	mylexrio,			/* rio */
-	nil,				/* rctl */
-	nil,				/* wctl */
-
-	scsibio,			/* bio */
-};
--- a/os/boot/pc/sdscsi.c
+++ /dev/null
@@ -1,376 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-#include "ureg.h"
-#include "error.h"
-
-#include "sd.h"
-
-static int
-scsitest(SDreq* r)
-{
-	r->write = 0;
-	memset(r->cmd, 0, sizeof(r->cmd));
-	r->cmd[1] = r->lun<<5;
-	r->clen = 6;
-	r->data = nil;
-	r->dlen = 0;
-	r->flags = 0;
-
-	r->status = ~0;
-
-// cgascreenputs("A", 1);
-	return r->unit->dev->ifc->rio(r);
-}
-
-int
-scsiverify(SDunit* unit)
-{
-	static SDreq *r;
-	int i, status;
-	static uchar *inquiry;
-
-	if((r = sdmalloc(r, sizeof(SDreq))) == nil)
-		return 0;
-
-	if((inquiry = sdmalloc(inquiry, sizeof(unit->inquiry))) == nil)
-		return 0;
-
-	r->unit = unit;
-	r->lun = 0;		/* ??? */
-
-	memset(unit->inquiry, 0, sizeof(unit->inquiry));
-	r->write = 0;
-	r->cmd[0] = 0x12;
-	r->cmd[1] = r->lun<<5;
-	r->cmd[4] = sizeof(unit->inquiry)-1;
-	r->clen = 6;
-	r->data = inquiry;
-	r->dlen = sizeof(unit->inquiry)-1;
-	r->flags = 0;
-
-	r->status = ~0;
-// cgascreenputs("B", 1);
-	if(unit->dev->ifc->rio(r) != SDok){
-		return 0;
-	}
-	memmove(unit->inquiry, inquiry, r->dlen);
-
-	SET(status);
-	for(i = 0; i < 3; i++){
-		while((status = scsitest(r)) == SDbusy)
-			;
-		if(status == SDok || status != SDcheck)
-			break;
-		if(!(r->flags & SDvalidsense))
-			break;
-		if((r->sense[2] & 0x0F) != 0x02)
-			continue;
-
-		/*
-		 * Unit is 'not ready'.
-		 * If it is in the process of becoming ready or needs
-		 * an initialising command, set status so it will be spun-up
-		 * below.
-		 * If there's no medium, that's OK too, but don't
-		 * try to spin it up.
-		 */
-		if(r->sense[12] == 0x04){
-			if(r->sense[13] == 0x02 || r->sense[13] == 0x01){
-				status = SDok;
-				break;
-			}
-		}
-		if(r->sense[12] == 0x3A)
-			break;
-	}
-
-	if(status == SDok){
-		/*
-		 * Try to ensure a direct-access device is spinning.
-		 * Ignore the result.
-		 */
-		if((unit->inquiry[0] & 0x1F) == 0){
-			memset(r->cmd, 0, sizeof(r->cmd));
-			r->write = 0;
-			r->cmd[0] = 0x1B;
-			r->cmd[1] = r->lun<<5;
-			r->cmd[4] = 1;
-			r->clen = 6;
-			r->data = nil;
-			r->dlen = 0;
-			r->flags = 0;
-
-			r->status = ~0;
-			unit->dev->ifc->rio(r);
-		}
-		return 1;
-	}
-	return 0;
-}
-
-int
-return0(void*)
-{
-	return 0;
-}
-
-static int
-scsirio(SDreq* r)
-{
-	/*
-	 * Perform an I/O request, returning
-	 *	-1	failure
-	 *	 0	ok
-	 *	 2	retry
-	 * The contents of r may be altered so the
-	 * caller should re-initialise if necesary.
-	 */
-	r->status = ~0;
-// cgascreenputs("C", 1);
-	switch(r->unit->dev->ifc->rio(r)){
-	default:
-		break;
-	case SDcheck:
-		if(!(r->flags & SDvalidsense))
-			return -1;
-		switch(r->sense[2] & 0x0F){
-		case 0x00:		/* no sense */
-		case 0x01:		/* recovered error */
-			return 2;
-		case 0x06:		/* check condition */
-			/*
-			 * 0x28 - not ready to ready transition,
-			 *	  medium may have changed.
-			 * 0x29 - power on or some type of reset.
-			 */
-			if(r->sense[12] == 0x28 && r->sense[13] == 0)
-				return 2;
-			if(r->sense[12] == 0x29)
-				return 2;
-			break;
-		case 0x02:		/* not ready */
-			/*
-			 * If no medium present, bail out.
-			 * If unit is becoming ready, rather than not
-			 * not ready, wait a little then poke it again. 							 */
-			if(r->sense[12] == 0x3A)
-				return -1;
-			if(r->sense[12] != 0x04 || r->sense[13] != 0x01)
-				return -1;
-
-			tsleep(nil, return0, 0, 500);
-			scsitest(r);
-			return 2;
-		default:
-			break;
-		}
-		break;
-	case SDok:
-		return 0;
-	}
-	return -1;
-}
-
-int
-scsionline(SDunit* unit)
-{
-	int ok;
-	static SDreq *r;
-	static uchar *p;
-
-	if((r = sdmalloc(r, sizeof(SDreq))) == nil)
-		return 0;
-
-	if((p = sdmalloc(p, 8)) == nil)
-		return 0;
-
-	ok = 0;
-
-	r->unit = unit;
-	r->lun = 0;				/* ??? */
-	for(;;){
-		/*
-		 * Read-capacity is mandatory for DA, WORM, CD-ROM and
-		 * MO. It may return 'not ready' if type DA is not
-		 * spun up, type MO or type CD-ROM are not loaded or just
-		 * plain slow getting their act together after a reset.
-		 */
-		r->write = 0;
-		memset(r->cmd, 0, sizeof(r->cmd));
-		r->cmd[0] = 0x25;
-		r->cmd[1] = r->lun<<5;
-		r->clen = 10;
-		r->data = p;
-		r->dlen = 8;
-		r->flags = 0;
-	
-		r->status = ~0;
-// cgascreenputs("F", 1);
-		switch(scsirio(r)){
-		default:
-			break;
-		case 0:
-			unit->sectors = (p[0]<<24)|(p[1]<<16)|(p[2]<<8)|p[3];
-			/*
-			 * Read-capacity returns the LBA of the last sector,
-			 * therefore the number of sectors must be incremented.
-			 */
-			unit->sectors++;
-			unit->secsize = (p[4]<<24)|(p[5]<<16)|(p[6]<<8)|p[7];
-			ok = 1;
-			break;
-		case 2:
-			continue;
-		}
-		break;
-	}
-
-	return ok;
-}
-
-int
-scsiexec(SDunit* unit, int write, uchar* cmd, int clen, void* data, int* dlen)
-{
-	static SDreq *r;
-	int status;
-
-	if((r = sdmalloc(r, sizeof(SDreq))) == nil)
-		return SDmalloc;
-
-	r->unit = unit;
-	r->lun = cmd[1]>>5;		/* ??? */
-	r->write = write;
-	memmove(r->cmd, cmd, clen);
-	r->clen = clen;
-	r->data = data;
-	if(dlen)
-		r->dlen = *dlen;
-	r->flags = 0;
-
-	r->status = ~0;
-
-	/*
-	 * Call the device-specific I/O routine.
-	 * There should be no calls to 'error()' below this
-	 * which percolate back up.
-	 */
-// cgascreenputs("D", 1);
-	switch(status = unit->dev->ifc->rio(r)){
-	case SDok:
-		if(dlen)
-			*dlen = r->rlen;
-		/*FALLTHROUGH*/
-	case SDcheck:
-		/*FALLTHROUGH*/
-	default:
-		/*
-		 * It's more complicated than this. There are conditions
-		 * which are 'ok' but for which the returned status code
-		 * is not 'SDok'.
-		 * Also, not all conditions require a reqsense, might
-		 * need to do a reqsense here and make it available to the
-		 * caller somehow.
-		 *
-		 * Mañana.
-		 */
-		break;
-	}
-
-	return status;
-}
-
-long
-scsibio(SDunit* unit, int lun, int write, void* data, long nb, long bno)
-{
-	static SDreq *r;
-	long rlen;
-
-	if((r = sdmalloc(r, sizeof(SDreq))) == nil)
-		return SDmalloc;
-
-	r->unit = unit;
-	r->lun = lun;
-again:
-	r->write = write;
-	if(write == 0)
-		r->cmd[0] = 0x28;
-	else
-		r->cmd[0] = 0x2A;
-	r->cmd[1] = (lun<<5);
-	r->cmd[2] = bno>>24;
-	r->cmd[3] = bno>>16;
-	r->cmd[4] = bno>>8;
-	r->cmd[5] = bno;
-	r->cmd[6] = 0;
-	r->cmd[7] = nb>>8;
-	r->cmd[8] = nb;
-	r->cmd[9] = 0;
-	r->clen = 10;
-	r->data = data;
-	r->dlen = nb*unit->secsize;
-	r->flags = 0;
-
-	r->status = ~0;
-// cgascreenputs("E", 1);
-	switch(scsirio(r)){
-	default:
-		rlen = -1;
-		break;
-	case 0:
-		rlen = r->rlen;
-		break;
-	case 2:
-		rlen = -1;
-		if(!(r->flags & SDvalidsense))
-			break;
-		switch(r->sense[2] & 0x0F){
-		default:
-			break;
-		case 0x06:		/* check condition */
-			/*
-			 * Check for a removeable media change.
-			 * If so, mark it and zap the geometry info
-			 * to force an online request.
-			 */
-			if(r->sense[12] != 0x28 || r->sense[13] != 0)
-				break;
-			if(unit->inquiry[1] & 0x80){
-				unit->sectors = 0;
-			}
-			break;
-		case 0x02:		/* not ready */
-			/*
-			 * If unit is becoming ready,
-			 * rather than not not ready, try again.
-			 */
-			if(r->sense[12] == 0x04 && r->sense[13] == 0x01)
-				goto again;
-			break;
-		}
-		break;
-	}
-
-	return rlen;
-}
-
-SDev*
-scsiid(SDev* sdev, SDifc* ifc)
-{
-	static char idno[16] = "0123456789abcdef";
-	static char *p = idno;
-
-	while(sdev){
-		if(sdev->ifc == ifc){
-			sdev->idno = *p++;
-			if(p >= &idno[sizeof(idno)])
-				break;
-		}
-		sdev = sdev->next;
-	}
-
-	return nil;
-}
--- a/os/boot/pc/trap.c
+++ /dev/null
@@ -1,332 +1,0 @@
-#include	"u.h"
-#include	"lib.h"
-#include	"mem.h"
-#include	"dat.h"
-#include	"fns.h"
-#include	"io.h"
-#include	"ureg.h"
-
-void	intr0(void), intr1(void), intr2(void), intr3(void);
-void	intr4(void), intr5(void), intr6(void), intr7(void);
-void	intr8(void), intr9(void), intr10(void), intr11(void);
-void	intr12(void), intr13(void), intr14(void), intr15(void);
-void	intr16(void);
-void	intr24(void), intr25(void), intr26(void), intr27(void);
-void	intr28(void), intr29(void), intr30(void), intr31(void);
-void	intr32(void), intr33(void), intr34(void), intr35(void);
-void	intr36(void), intr37(void), intr38(void), intr39(void);
-void	intr64(void);
-void	intrbad(void);
-
-/*
- *  8259 interrupt controllers
- */
-enum
-{
-	Int0ctl=	0x20,		/* control port (ICW1, OCW2, OCW3) */
-	Int0aux=	0x21,		/* everything else (ICW2, ICW3, ICW4, OCW1) */
-	Int1ctl=	0xA0,		/* control port */
-	Int1aux=	0xA1,		/* everything else (ICW2, ICW3, ICW4, OCW1) */
-
-	Icw1=		0x10,		/* select bit in ctl register */
-	Ocw2=		0x00,
-	Ocw3=		0x08,
-
-	EOI=		0x20,		/* non-specific end of interrupt */
-
-	Elcr1=		0x4D0,		/* Edge/Level Triggered Register */
-	Elcr2=		0x4D1,
-};
-
-int	int0mask = 0xff;	/* interrupts enabled for first 8259 */
-int	int1mask = 0xff;	/* interrupts enabled for second 8259 */
-int i8259elcr;				/* mask of level-triggered interrupts */
-
-/*
- *  trap/interrupt gates
- */
-Segdesc ilt[256];
-
-enum 
-{
-	Maxhandler=	32,		/* max number of interrupt handlers */
-};
-
-typedef struct Handler	Handler;
-struct Handler
-{
-	void	(*r)(Ureg*, void*);
-	void	*arg;
-	Handler	*next;
-};
-
-struct
-{
-	Handler	*ivec[256];
-	Handler	h[Maxhandler];
-	int	nextfree;
-} halloc;
-
-void
-sethvec(int v, void (*r)(void), int type, int pri)
-{
-	ilt[v].d0 = ((ulong)r)&0xFFFF|(KESEL<<16);
-	ilt[v].d1 = ((ulong)r)&0xFFFF0000|SEGP|SEGPL(pri)|type;
-}
-
-void
-setvec(int v, void (*r)(Ureg*, void*), void *arg)
-{
-	Handler *h;
-
-	if(halloc.nextfree >= Maxhandler)
-		panic("out of interrupt handlers");
-	h = &halloc.h[halloc.nextfree++];
-	h->next = halloc.ivec[v];
-	h->r = r;
-	h->arg = arg;
-	halloc.ivec[v] = h;
-
-	/*
-	 *  enable corresponding interrupt in 8259
-	 */
-	if((v&~0x7) == VectorPIC){
-		int0mask &= ~(1<<(v&7));
-		outb(Int0aux, int0mask);
-	} else if((v&~0x7) == VectorPIC+8){
-		int1mask &= ~(1<<(v&7));
-		outb(Int1aux, int1mask);
-	}
-}
-
-void
-trapdisable(void)
-{
-	outb(Int0aux, 0xFF);
-	outb(Int1aux, 0xFF);
-}
-
-void
-trapenable(void)
-{
-	outb(Int0aux, int0mask);
-	outb(Int1aux, int1mask);
-}
-
-
-/*
- *  set up the interrupt/trap gates
- */
-void
-trapinit(void)
-{
-	int i, x;
-
-	/*
-	 *  set all interrupts to panics
-	 */
-	for(i = 0; i < 256; i++)
-		sethvec(i, intrbad, SEGTG, 0);
-
-	/*
-	 *  80386 processor (and coprocessor) traps
-	 */
-	sethvec(0, intr0, SEGTG, 0);
-	sethvec(1, intr1, SEGTG, 0);
-	sethvec(2, intr2, SEGTG, 0);
-	sethvec(3, intr3, SEGTG, 0);
-	sethvec(4, intr4, SEGTG, 0);
-	sethvec(5, intr5, SEGTG, 0);
-	sethvec(6, intr6, SEGTG, 0);
-	sethvec(7, intr7, SEGTG, 0);
-	sethvec(8, intr8, SEGTG, 0);
-	sethvec(9, intr9, SEGTG, 0);
-	sethvec(10, intr10, SEGTG, 0);
-	sethvec(11, intr11, SEGTG, 0);
-	sethvec(12, intr12, SEGTG, 0);
-	sethvec(13, intr13, SEGTG, 0);
-	sethvec(14, intr14, SEGTG, 0);
-	sethvec(15, intr15, SEGTG, 0);
-	sethvec(16, intr16, SEGTG, 0);
-
-	/*
-	 *  device interrupts
-	 */
-	sethvec(24, intr24, SEGIG, 0);
-	sethvec(25, intr25, SEGIG, 0);
-	sethvec(26, intr26, SEGIG, 0);
-	sethvec(27, intr27, SEGIG, 0);
-	sethvec(28, intr28, SEGIG, 0);
-	sethvec(29, intr29, SEGIG, 0);
-	sethvec(30, intr30, SEGIG, 0);
-	sethvec(31, intr31, SEGIG, 0);
-	sethvec(32, intr32, SEGIG, 0);
-	sethvec(33, intr33, SEGIG, 0);
-	sethvec(34, intr34, SEGIG, 0);
-	sethvec(35, intr35, SEGIG, 0);
-	sethvec(36, intr36, SEGIG, 0);
-	sethvec(37, intr37, SEGIG, 0);
-	sethvec(38, intr38, SEGIG, 0);
-	sethvec(39, intr39, SEGIG, 0);
-
-	/*
-	 *  tell the hardware where the table is (and how long)
-	 */
-	putidt(ilt, sizeof(ilt)-1);
-
-	/*
-	 *  Set up the first 8259 interrupt processor.
-	 *  Make 8259 interrupts start at CPU vector VectorPIC.
-	 *  Set the 8259 as master with edge triggered
-	 *  input with fully nested interrupts.
-	 */
-	outb(Int0ctl, Icw1|0x01);	/* ICW1 - edge triggered, master,
-					   ICW4 will be sent */
-	outb(Int0aux, VectorPIC);	/* ICW2 - interrupt vector offset */
-	outb(Int0aux, 0x04);		/* ICW3 - have slave on level 2 */
-	outb(Int0aux, 0x01);		/* ICW4 - 8086 mode, not buffered */
-
-	/*
-	 *  Set up the second 8259 interrupt processor.
-	 *  Make 8259 interrupts start at CPU vector VectorPIC+8.
-	 *  Set the 8259 as master with edge triggered
-	 *  input with fully nested interrupts.
-	 */
-	outb(Int1ctl, Icw1|0x01);	/* ICW1 - edge triggered, master,
-					   ICW4 will be sent */
-	outb(Int1aux, VectorPIC+8);	/* ICW2 - interrupt vector offset */
-	outb(Int1aux, 0x02);		/* ICW3 - I am a slave on level 2 */
-	outb(Int1aux, 0x01);		/* ICW4 - 8086 mode, not buffered */
-	outb(Int1aux, int1mask);
-
-	/*
-	 *  pass #2 8259 interrupts to #1
-	 */
-	int0mask &= ~0x04;
-	outb(Int0aux, int0mask);
-
-	/*
-	 * Set Ocw3 to return the ISR when ctl read.
-	 */
-	outb(Int0ctl, Ocw3|0x03);
-	outb(Int1ctl, Ocw3|0x03);
-
-	/*
-	 * Check for Edge/Level register.
-	 * This check may not work for all chipsets.
-	 * First try a non-intrusive test - the bits for
-	 * IRQs 13, 8, 2, 1 and 0 must be edge (0). If
-	 * that's OK try a R/W test.
-	 */
-	x = (inb(Elcr2)<<8)|inb(Elcr1);
-	if(!(x & 0x2107)){
-		outb(Elcr1, 0);
-		if(inb(Elcr1) == 0){
-			outb(Elcr1, 0x20);
-			if(inb(Elcr1) == 0x20)
-				i8259elcr = x;
-			outb(Elcr1, x & 0xFF);
-			print("ELCR: %4.4uX\n", i8259elcr);
-		}
-	}
-}
-
-/*
- *  dump registers
- */
-static void
-dumpregs(Ureg *ur)
-{
-	print("FLAGS=%lux TRAP=%lux ECODE=%lux PC=%lux\n",
-		ur->flags, ur->trap, ur->ecode, ur->pc);
-	print("  AX %8.8lux  BX %8.8lux  CX %8.8lux  DX %8.8lux\n",
-		ur->ax, ur->bx, ur->cx, ur->dx);
-	print("  SI %8.8lux  DI %8.8lux  BP %8.8lux\n",
-		ur->si, ur->di, ur->bp);
-	print("  CS %4.4lux DS %4.4lux  ES %4.4lux  FS %4.4lux  GS %4.4lux\n",
-		ur->cs & 0xFF, ur->ds & 0xFFFF, ur->es & 0xFFFF, ur->fs & 0xFFFF, ur->gs & 0xFFFF);
-	print("  CR0 %8.8lux CR2 %8.8lux CR3 %8.8lux\n",
-		getcr0(), getcr2(), getcr3());
-}
-
-/*
- *  All traps
- */
-void
-trap(Ureg *ur)
-{
-	int v;
-	int c;
-	Handler *h;
-	ushort isr;
-
-	v = ur->trap;
-	/*
-	 *  tell the 8259 that we're done with the
-	 *  highest level interrupt (interrupts are still
-	 *  off at this point)
-	 */
-	c = v&~0x7;
-	isr = 0;
-	if(c==VectorPIC || c==VectorPIC+8){
-		isr = inb(Int0ctl);
-		outb(Int0ctl, EOI);
-		if(c == VectorPIC+8){
-			isr |= inb(Int1ctl)<<8;
-			outb(Int1ctl, EOI);
-		}
-	}
-
-	if(v>=256 || (h = halloc.ivec[v]) == 0){
-		if(v >= VectorPIC && v < VectorPIC+16){
-			v -= VectorPIC;
-			/*
-			 * Check for a default IRQ7. This can happen when
-			 * the IRQ input goes away before the acknowledge.
-			 * In this case, a 'default IRQ7' is generated, but
-			 * the corresponding bit in the ISR isn't set.
-			 * In fact, just ignore all such interrupts.
-			 */
-			if(isr & (1<<v))
-				print("unknown interrupt %d pc=0x%lux\n", v, ur->pc);
-			return;
-		}
-
-		switch(v){
-
-		case 0x02:				/* NMI */
-			print("NMI: nmisc=0x%2.2ux, nmiertc=0x%2.2ux, nmiesc=0x%2.2ux\n",
-				inb(0x61), inb(0x70), inb(0x461));
-			return;
-
-		default:
-			dumpregs(ur);
-			panic("exception/interrupt %d", v);
-			return;
-		}
-	}
-
-	/*
-	 *  call the trap routines
-	 */
-	do {
-		(*h->r)(ur, h->arg);
-		h = h->next;
-	} while(h);
-}
-
-extern void realmode0(void);	/* in l.s */
-
-extern int realmodeintr;
-extern Ureg realmoderegs;
-
-void
-realmode(int intr, Ureg *ureg)
-{
-	realmoderegs = *ureg;
-	realmodeintr = intr;
-	trapdisable();
-	realmode0();
-	trapenable();
-	*ureg = realmoderegs;
-}
--- a/os/boot/pc/ureg.h
+++ /dev/null
@@ -1,27 +1,0 @@
-typedef struct Ureg	Ureg;
-
-struct Ureg
-{
-	ulong	di;		/* general registers */
-	ulong	si;		/* ... */
-	ulong	bp;		/* ... */
-	ulong	nsp;
-	ulong	bx;		/* ... */
-	ulong	dx;		/* ... */
-	ulong	cx;		/* ... */
-	ulong	ax;		/* ... */
-	ulong	gs;		/* data segments */
-	ulong	fs;		/* ... */
-	ulong	es;		/* ... */
-	ulong	ds;		/* ... */
-	ulong	trap;		/* trap type */
-	ulong	ecode;		/* error code (or zero) */
-	ulong	pc;		/* pc */
-	ulong	cs;		/* old context */
-	ulong	flags;		/* old flags */
-	union {
-		ulong	usp;
-		ulong	sp;
-	};
-	ulong	ss;		/* old stack segment */
-};
--- a/os/boot/pc/x16.h
+++ /dev/null
@@ -1,159 +1,0 @@
-/*
- * Can't write 16-bit code for 8a without getting into
- * lots of bother, so define some simple commands and
- * output the code directly.
- * 
- * N.B. CALL16(x) kills DI, so don't expect it to be
- * saved across calls.
- */
-#define rAX		0		/* rX  */
-#define rCX		1
-#define rDX		2
-#define rBX		3
-#define rSP		4		/* SP */
-#define rBP		5		/* BP */
-#define rSI		6		/* SI */
-#define rDI		7		/* DI */
-
-#define rAL		0		/* rL  */
-#define rCL		1
-#define rDL		2
-#define rBL		3
-#define rAH		4		/* rH */
-#define rCH		5
-#define rDH		6
-#define rBH		7
-
-#define rES		0		/* rS */
-#define rCS		1
-#define rSS		2
-#define rDS		3
-#define rFS		4
-#define rGS		5
-
-#define xSI		4		/* rI (index) */
-#define xDI		5
-#define xBP		6
-#define xBX		7
-
-#define rCR0		0		/* rC */
-#define rCR2		2
-#define rCR3		3
-#define rCR4		4
-
-#define OP(o, m, ro, rm)	BYTE $o;	/* op + modr/m byte */	\
-			BYTE $(((m)<<6)|((ro)<<3)|(rm))
-#define OPrm(o, r, m)	OP(o, 0x00, r, 0x06);	/* general r <-> m */	\
-			WORD $m;
-#define OPrr(o, r0, r1)	OP(o, 0x03, r0, r1);	/* general r -> r */
-
-#define LW(m, rX)	OPrm(0x8B, rX, m)	/* m -> rX */
-#define LXW(x, rI, r)	OP(0x8B, 0x02, r, rI);	/* x(rI) -> r */	\
-			WORD $x
-#define LBPW(x, r)	OP(0x8B, 0x02, r, xBP);	/* x(rBP) -> r */	\
-			WORD $x
-#define LB(m, rB)	OPrm(0x8A, rB, m)	/* m -> r[HL] */
-#define LXB(x, rI, r)	OP(0x8A, 0x01, r, rI);	/* x(rI) -> r */	\
-			BYTE $x
-#define LBPB(x, r)	OP(0x8A, 0x01, r, xBP);	/* x(rBP) -> r */	\
-			BYTE $x
-#define SW(rX, m)	OPrm(0x89, rX, m)	/* rX -> m */
-#define SXW(r, x, rI)	OP(0x89, 0x02, r, rI);	/* r -> x(rI) */	\
-			WORD $x
-#define SBPW(r, x)	OP(0x89, 0x02, r, xBP);	/* r -> x(rBP) */	\
-			WORD $(x)
-#define SBPWI(i, x)	OP(0xC7, 0x01, 0, xBP);	/* i -> x(rBP) */	\
-			BYTE $(x); WORD $(i)
-#define STB(rB, m)	OPrm(0x88, rB, m)	/* rB -> m */
-#define SXB(r, x, rI)	OP(0x88, 0x01, r, rI);	/* rB -> x(rI) */	\
-			BYTE $x
-#define SBPB(r, x)	OP(0x88, 0x01, r, xBP);	/* r -> x(rBP) */	\
-			BYTE $x
-#define SBPBI(i, x)	OP(0xC6, 0x01, 0, xBP);	/* i -> x(rBP) */	\
-			BYTE $(x); BYTE $(i)
-#define LWI(i, rX)	BYTE $(0xB8+rX);	/* i -> rX */		\
-			WORD $i;
-#define LBI(i, rB)	BYTE $(0xB0+rB);	/* i -> r[HL] */	\
-			BYTE $i
-
-#define MW(r0, r1)	OPrr(0x89, r0, r1)	/* r0 -> r1 */
-#define MFSR(rS, rX)	OPrr(0x8C, rS, rX)	/* rS -> rX */
-#define MTSR(rX, rS)	OPrr(0x8E, rS, rX)	/* rX -> rS */
-#define MFCR(rC, rX)	BYTE $0x0F;		/* rC -> rX */		\
-			OP(0x20, 0x03, rC, rX)
-#define MTCR(rX, rC)	BYTE $0x0F;		/* rX -> rC */		\
-			OP(0x22, 0x03, rC, rX)
-
-#define ADC(r0, r1)	OPrr(0x11, r0, r1)	/* r0 + r1 -> r1 */
-#define ADD(r0, r1)	OPrr(0x01, r0, r1)	/* r0 + r1 -> r1 */
-#define ADDI(i, r)	OP(0x81, 0x03, 0x00, r);/* i+r -> r */		\
-			WORD $i;
-#define AND(r0, r1)	OPrr(0x21, r0, r1)	/* r0&r1 -> r1 */
-#define ANDI(i, r)	OP(0x81, 0x03, 0x04, r);/* i&r -> r */		\
-			WORD $i;
-#define CLR(r)		OPrr(0x31, r, r)	/* r^r -> r */
-#define CLRB(r)		OPrr(0x30, r, r)	/* r^r -> r */
-#define CMP(r0, r1)	OPrr(0x39, r0, r1)	/* r1-r0 -> flags */
-#define CMPI(i, r)	OP(0x81, 0x03, 0x07, r);/* r-i -> flags */	\
-			WORD $i;
-#define CMPBR(r0, r1)	OPrr(0x38, r0, r1)	/* r1-r0 -> flags */
-#define DEC(r)		BYTE $(0x48|r)		/* r-1 -> r */
-#define DIV(r)		OPrr(0xF7, 0x06, r)	/* rDX:rAX/r -> rAX, rDX:rAX%r -> rDX */
-#define INC(r)		BYTE $(0x40|r)		/* r+1 -> r */
-#define MUL(r)		OPrr(0xF7, 0x04, r)	/* r*rAX -> rDX:rAX */
-#define IMUL(r0, r1)	BYTE $0x0F;		/* r0*r1 -> r1 */	\
-			OPrr(0xAF, r1, r0)	/* (signed) */
-#define OR(r0, r1)	OPrr(0x09, r0, r1)	/* r0|r1 -> r1 */
-#define ORB(r0, r1)	OPrr(0x08, r0, r1)	/* r0|r1 -> r1 */
-#define ORI(i, r)	OP(0x81, 0x03, 0x01, r);/* i|r -> r */		\
-			WORD $i;
-#define ROLI(i, r)	OPrr(0xC1, 0x00, r);	/* r<<>>i -> r */	\
-			BYTE $i;
-#define SHLI(i, r)	OPrr(0xC1, 0x04, r);	/* r<<i -> r */		\
-			BYTE $i;
-#define SHLBI(i, r)	OPrr(0xC0, 0x04, r);	/* r<<i -> r */		\
-			BYTE $i;
-#define SHRI(i, r)	OPrr(0xC1, 0x05, r);	/* r>>i -> r */		\
-			BYTE $i;
-#define SHRBI(i, r)	OPrr(0xC0, 0x05, r);	/* r>>i -> r */		\
-			BYTE $i;
-#define SUB(r0, r1)	OPrr(0x29, r0, r1)	/* r1-r0 -> r1 */
-#define SUBI(i, r)	OP(0x81, 0x03, 0x05, r);/* r-i -> r */		\
-			WORD $i;
-
-#define STOSW		STOSL
-
-#define CALL16(f)	LWI(f, rDI);		/* &f -> rDI */		\
-			BYTE $0xFF;		/* (*rDI) */		\
-			BYTE $0xD7;
-#define FARJUMP16(s, o)	BYTE $0xEA;		/* jump to ptr16:16 */	\
-			WORD $o; WORD $s
-#define FARJUMP32(s, o)	BYTE $0x66;		/* jump to ptr32:16 */	\
-			BYTE $0xEA; LONG $o; WORD $s
-#define	DELAY		BYTE $0xEB;		/* jmp .+2 */		\
-			BYTE $0x00
-#define BIOSCALL(b)	INT $b			/* INT $b */
-
-#define PEEKW		BYTE $0x26;		/* MOVW	rES:[rBX], rAX  */	\
-			BYTE $0x8B; BYTE $0x07
-#define POKEW		BYTE $0x26;		/* MOVW	rAX, rES:[rBX] */	\
-			BYTE $0x89; BYTE $0x07
-#define OUTPORTB(p, d)	LBI(d, rAL);		/* d -> I/O port p */	\
-			BYTE $0xE6;					\
-			BYTE $p; DELAY
-#define PUSHA		BYTE $0x60
-#define PUSHR(r)	BYTE $(0x50|r)		/* r  -> (--rSP) */
-#define PUSHS(rS)	BYTE $(0x06|((rS)<<3))	/* rS  -> (--rSP) */
-#define PUSHI(i)	BYTE $0x68; WORD $i;	/* i -> --(rSP) */
-#define POPA		BYTE $0x61
-#define POPR(r)		BYTE $(0x58|r)		/* (rSP++) -> r */
-#define POPS(rS)	BYTE $(0x07|((rS)<<3))	/* (rSP++) -> r */
-#define NOP		BYTE $0x90		/* nop */
-
-#define LGDT(gdtptr)	BYTE $0x0F;		/* LGDT */			\
-			BYTE $0x01; BYTE $0x16;					\
-			WORD $gdtptr
-
-/* operand size switch. */
-#define OPSIZE		BYTE $0x66
-
--- a/os/boot/puma/8250.c
+++ /dev/null
@@ -1,312 +1,0 @@
-#include "boot.h"
-
-/*
- *  INS8250 uart
- */
-enum
-{
-	/*
-	 *  register numbers
-	 */
-	Data=	0,		/* xmit/rcv buffer */
-	Iena=	1,		/* interrupt enable */
-	 Ircv=	(1<<0),		/*  for char rcv'd */
-	 Ixmt=	(1<<1),		/*  for xmit buffer empty */
-	 Irstat=(1<<2),		/*  for change in rcv'er status */
-	 Imstat=(1<<3),		/*  for change in modem status */
-	Istat=	2,		/* interrupt flag (read) */
-	Tctl=	2,		/* test control (write) */
-	Format=	3,		/* byte format */
-	 Bits8=	(3<<0),		/*  8 bits/byte */
-	 Stop2=	(1<<2),		/*  2 stop bits */
-	 Pena=	(1<<3),		/*  generate parity */
-	 Peven=	(1<<4),		/*  even parity */
-	 Pforce=(1<<5),		/*  force parity */
-	 Break=	(1<<6),		/*  generate a break */
-	 Dra=	(1<<7),		/*  address the divisor */
-	Mctl=	4,		/* modem control */
-	 Dtr=	(1<<0),		/*  data terminal ready */
-	 Rts=	(1<<1),		/*  request to send */
-	 Ri=	(1<<2),		/*  ring */
-	 Inton=	(1<<3),		/*  turn on interrupts */
-	 Loop=	(1<<4),		/*  loop back */
-	Lstat=	5,		/* line status */
-	 Inready=(1<<0),	/*  receive buffer full */
-	 Oerror=(1<<1),		/*  receiver overrun */
-	 Perror=(1<<2),		/*  receiver parity error */
-	 Ferror=(1<<3),		/*  rcv framing error */
-	 Outready=(1<<5),	/*  output buffer empty */
-	Mstat=	6,		/* modem status */
-	 Ctsc=	(1<<0),		/*  clear to send changed */
-	 Dsrc=	(1<<1),		/*  data set ready changed */
-	 Rire=	(1<<2),		/*  rising edge of ring indicator */
-	 Dcdc=	(1<<3),		/*  data carrier detect changed */
-	 Cts=	(1<<4),		/*  complement of clear to send line */
-	 Dsr=	(1<<5),		/*  complement of data set ready line */
-	 Ring=	(1<<6),		/*  complement of ring indicator line */
-	 Dcd=	(1<<7),		/*  complement of data carrier detect line */
-	Scratch=7,		/* scratchpad */
-	Dlsb=	0,		/* divisor lsb */
-	Dmsb=	1,		/* divisor msb */
-
-	Serial=	0,
-	Modem=	1,
-};
-
-typedef struct Uart	Uart;
-struct Uart
-{
-	int	port;
-	int	setup;
-	uchar	sticky[8];	/* sticky write register values */
-	uchar	txbusy;
-
-	Queue	*iq;
-	Queue	*oq;
-	void	(*rx)(Queue *, int);
-
-	ulong	frame;
-	ulong	overrun;
-};
-
-Uart	uart[1];
-
-static	void	uartkick(void*);
-
-
-#define UartFREQ 1843200
-
-#define uartwrreg(u,r,v)	outb((u)->port + r, (u)->sticky[r] | (v))
-#define uartrdreg(u,r)		inb((u)->port + r)
-
-/*
- *  set the baud rate by calculating and setting the baudrate
- *  generator constant.  This will work with fairly non-standard
- *  baud rates.
- */
-static void
-uartsetbaud(Uart *up, int rate)
-{
-	ulong brconst;
-
-	brconst = (UartFREQ+8*rate-1)/(16*rate);
-
-	uartwrreg(up, Format, Dra);
-	outb(up->port+Dmsb, (brconst>>8) & 0xff);
-	outb(up->port+Dlsb, brconst & 0xff);
-	uartwrreg(up, Format, 0);
-}
-
-/*
- *  toggle DTR
- */
-static void
-uartdtr(Uart *up, int n)
-{
-	if(n)
-		up->sticky[Mctl] |= Dtr;
-	else
-		up->sticky[Mctl] &= ~Dtr;
-	uartwrreg(up, Mctl, 0);
-}
-
-/*
- *  toggle RTS
- */
-static void
-uartrts(Uart *up, int n)
-{
-	if(n)
-		up->sticky[Mctl] |= Rts;
-	else
-		up->sticky[Mctl] &= ~Rts;
-	uartwrreg(up, Mctl, 0);
-}
-
-static void
-uartintr(Ureg*, void *arg)
-{
-	Uart *up;
-	int ch;
-	int s, l, loops;
-
-	up = arg;
-	for(loops = 0; loops < 1024; loops++){
-		s = uartrdreg(up, Istat);
-		switch(s){
-		case 6:	/* receiver line status */
-			l = uartrdreg(up, Lstat);
-			if(l & Ferror)
-				up->frame++;
-			if(l & Oerror)
-				up->overrun++;
-			break;
-	
-		case 4:	/* received data available */
-		case 12:
-			ch = inb(up->port+Data);
-			if(up->iq)
-				if(up->rx)
-					(*up->rx)(up->iq, ch);
-				else
-					qbputc(up->iq, ch);
-			break;
-	
-		case 2:	/* transmitter empty */
-			ch = -1;
-			if(up->oq)
-				ch = qbgetc(up->oq);
-			if(ch != -1)
-				outb(up->port+Data, ch);
-			else
-				up->txbusy = 0;
-			break;
-	
-		case 0:	/* modem status */
-			uartrdreg(up, Mstat);
-			break;
-	
-		default:
-			if(s&1)
-				return;
-			print("weird modem interrupt #%2.2ux\n", s);
-			break;
-		}
-	}
-	panic("uartintr: 0x%2.2ux\n", uartrdreg(up, Istat));
-}
-
-/*
- *  turn on a port's interrupts.  set DTR and RTS
- */
-static void
-uartenable(Uart *up)
-{
-	/*
- 	 *  turn on interrupts
-	 */
-	up->sticky[Iena] = 0;
-	if(up->oq)
-		up->sticky[Iena] |= Ixmt;
-	if(up->iq)
-		up->sticky[Iena] |= Ircv|Irstat;
-	uartwrreg(up, Iena, 0);
-
-	/*
-	 *  turn on DTR and RTS
-	 */
-	uartdtr(up, 1);
-	uartrts(up, 1);
-}
-
-void
-uartspecial(int port, int baud, Queue **iq, Queue **oq, void (*rx)(Queue *, int))
-{
-	Uart *up = &uart[0];
-
-	if(up->setup)
-		return;
-	up->setup = 1;
-
-	*iq = up->iq = qopen(4*1024, 0, 0, 0);
-	*oq = up->oq = qopen(16*1024, 0, uartkick, up);
-	switch(port){
-
-	case 0:
-		up->port = 0x3F8;
-		setvec(V_COM1, uartintr, up);
-		break;
-
-	case 1:
-		up->port = 0x2F8;
-		setvec(V_COM2, uartintr, up);
-		break;
-
-	default:
-		return;
-	}
-
-	/*
-	 *  set rate to 9600 baud.
-	 *  8 bits/character.
-	 *  1 stop bit.
-	 *  interrupts enabled.
-	 */
-	uartsetbaud(up, 9600);
-	up->sticky[Format] = Bits8;
-	uartwrreg(up, Format, 0);
-	up->sticky[Mctl] |= Inton;
-	uartwrreg(up, Mctl, 0x0);
-
-	up->rx = rx;
-	uartenable(up);
-	if(baud)
-		uartsetbaud(up, baud);
-}
-
-static void
-uartputc(int c)
-{
-	Uart *up = &uart[0];
-	int i;
-
-	for(i = 0; i < 100; i++){
-		if(uartrdreg(up, Lstat) & Outready)
-			break;
-		delay(1);
-	}
-	outb(up->port+Data, c);
-}
-
-void
-uartputs(char *s, int n)
-{
-	Uart *up = &uart[0];
-	Block *b;
-	int nl;
-	char *p;
-
-	nl = 0;
-	for(p = s; p < s+n; p++)
-		if(*p == '\n')
-			nl++;
-	b = iallocb(n+nl);
-	while(n--){
-		if(*s == '\n')
-			*b->wp++ = '\r';
-		*b->wp++ = *s++;
-	}
-	qbwrite(up->oq, b);
-}
-
-/*
- *  (re)start output
- */
-static void
-uartkick(void *arg)
-{
-	Uart *up = arg;
-	int x, n, c;
-
-	x = splhi();
-	while(up->txbusy == 0 && (c = qbgetc(up->oq)) != -1) {
-		n = 0;
-		while((uartrdreg(up, Lstat) & Outready) == 0){
-			if(++n > 100000){
-				print("stuck serial line\n");
-				break;
-			}
-		}
-			outb(up->port + Data, c);
-	}
-	splx(x);
-}
-
-void
-uartwait(void)
-{
-	Uart *up = &uart[0];
-
-	while(up->txbusy)
-		;
-}
--- a/os/boot/puma/alarm.c
+++ /dev/null
@@ -1,123 +1,0 @@
-#include	"u.h"
-#include	"lib.h"
-#include	"mem.h"
-#include	"dat.h"
-#include	"fns.h"
-#include	"io.h"
-#define	MAXALARM	10
-
-Alarm	alarmtab[MAXALARM];
-
-/*
- * Insert new into list after where
- */
-void
-insert(List **head, List *where, List *new)
-{
-	if(where == 0){
-		new->next = *head;
-		*head = new;
-	}else{
-		new->next = where->next;
-		where->next = new;
-	}
-		
-}
-
-/*
- * Delete old from list.  where->next is known to be old.
- */
-void
-delete(List **head, List *where, List *old)
-{
-	if(where == 0){
-		*head = old->next;
-		return;
-	}
-	where->next = old->next;
-}
-
-Alarm*
-newalarm(void)
-{
-	int i;
-	Alarm *a;
-
-	for(i=0,a=alarmtab; i < nelem(alarmtab); i++,a++)
-		if(a->busy==0 && a->f==0){
-			a->f = 0;
-			a->arg = 0;
-			a->busy = 1;
-			return a;
-		}
-	panic("newalarm");
-	return 0;	/* not reached */
-}
-
-Alarm*
-alarm(int ms, void (*f)(Alarm*), void *arg)
-{
-	Alarm *a, *w, *pw;
-	ulong s;
-
-	if(ms < 0)
-		ms = 0;
-	s = splhi();
-	a = newalarm();
-	a->dt = MS2TK(ms);
-	a->f = f;
-	a->arg = arg;
-	pw = 0;
-	for(w=m->alarm; w; pw=w, w=w->next){
-		if(w->dt <= a->dt){
-			a->dt -= w->dt;
-			continue;
-		}
-		w->dt -= a->dt;
-		break;
-	}
-	insert(&m->alarm, pw, a);
-	splx(s);
-	return a;
-}
-
-void
-cancel(Alarm *a)
-{
-	a->f = 0;
-}
-
-void
-alarminit(void)
-{
-}
-
-#define NA 10		/* alarms per clock tick */
-void
-checkalarms(void)
-{
-	int i, n, s;
-	Alarm *a;
-	void (*f)(void*);
-	Alarm *alist[NA];
-
-	s = splhi();
-	a = m->alarm;
-	if(a){
-		for(n=0; a && a->dt<=0 && n<NA; n++){
-			alist[n] = a;
-			delete(&m->alarm, 0, a);
-			a = m->alarm;
-		}
-		if(a)
-			a->dt--;
-
-		for(i = 0; i < n; i++){
-			f = alist[i]->f;	/* avoid race with cancel */
-			if(f)
-				(*f)(alist[i]);
-			alist[i]->busy = 0;
-		}
-	}
-	splx(s);
-}
--- a/os/boot/puma/armv4.h
+++ /dev/null
@@ -1,99 +1,0 @@
-/*
- * PSR
- */
-#define PsrMusr		0x10 	/* mode */
-#define PsrMfiq		0x11 
-#define PsrMirq		0x12
-#define PsrMsvc		0x13
-#define PsrMabt		0x17
-#define PsrMund		0x1B
-#define PsrMsys		0x1F
-#define PsrMask		0x1F
-
-#define PsrDfiq		0x00000040	/* disable FIQ interrupts */
-#define PsrDirq		0x00000080	/* disable IRQ interrupts */
-
-#define PsrV		0x10000000	/* overflow */
-#define PsrC		0x20000000	/* carry/borrow/extend */
-#define PsrZ		0x40000000	/* zero */
-#define PsrN		0x80000000	/* negative/less than */
-
-/*
- * Internal MMU coprocessor registers
- */
-#define CpCPUID		0		/* R: */
-#define CpControl	1		/* R: */
-#define CpTTB		2		/* W: translation table base */
-#define CpDAC		3		/* W: domain access control */
-#define CpFSR		5		/* R: fault status */
-#define CpTLBflush	5		/* W: */
-#define CpFAR		6		/* R: fault address */
-#define CpTLBpurge	6		/* W: */
-#define CpCacheCtl	7		/* W: */
-
-#define CpDebug		14		/* R/W: debug registers */
-/*
- * Coprocessors
- */
-#define CpMMU		15
-
-/*
- * Internal MMU coprocessor registers
- */
-#define CpCmmu		0x00000001	/* M: MMU enable */
-#define CpCalign	0x00000002	/* A: alignment fault enable */
-#define CpCDcache	0x00000004	/* C: instruction/data cache on */
-#define CpCwb		0x00000008	/* W: write buffer turned on */
-#define CpCi32		0x00000010	/* P: 32-bit programme space */
-#define CpCd32		0x00000020	/* D: 32-bit data space */
-#define CpCbe		0x00000080	/* B: big-endian operation */
-#define CpCsystem	0x00000100	/* S: system permission */
-#define CpCrom		0x00000200	/* R: ROM permission */
-#define CpCIcache	0x00001000	/* C: Instruction Cache on */
-
-/*
- * Debug support internal registers
- */
-#define CpDBAR	0
-#define CpDBVR	1
-#define CpDBMR	2
-#define CpDBCR	3
-#define CpIBCR	8
-/*
- * MMU
- */
-/*
- * Small pages:
- *	L1: 12-bit index -> 4096 descriptors -> 16Kb
- *	L2:  8-bit index ->  256 descriptors ->  1Kb
- * Each L2 descriptor has access permissions for 4 1Kb sub-pages.
- *
- *	TTB + L1Tx gives address of L1 descriptor
- *	L1 descriptor gives PTBA
- *	PTBA + L2Tx gives address of L2 descriptor
- *	L2 descriptor gives PBA
- */
-#define MmuTTB(pa)	((pa) & ~0x3FFF)	/* translation table base */
-#define MmuL1x(pa)	(((pa)>>20) & 0xFFF)	/* L1 table index */
-#define MmuPTBA(pa)	((pa) & ~0x3FF)		/* page table base address */
-#define MmuL2x(pa)	(((pa)>>12) & 0xFF)	/* L2 table index */
-#define MmuPBA(pa)	((pa) & ~0xFFF)		/* page base address */
-#define MmuSBA(pa)	((pa) & ~0xFFFFF)	/* section base address */
-
-#define MmuL1page	0x011			/* descriptor is for L2 pages */
-#define MmuL1section	0x012			/* descriptor is for section */
-
-#define MmuL2invalid	0x000
-#define MmuL2large	0x001			/* large */
-#define MmuL2small	0x002			/* small */
-#define MmuWB		0x004			/* data goes through write buffer */
-#define MmuIDC		0x008			/* data placed in cache */
-
-#define MmuDAC(d)	(((d) & 0xF)<<5)	/* L1 domain */
-#define MmuAP(i, v)	((v)<<(((i)*2)+4))	/* access permissions */
-#define MmuL1AP(v)	MmuAP(3, (v))
-#define MmuL2AP(v)	MmuAP(3, (v))|MmuAP(2, (v))|MmuAP(1, (v))|MmuAP(0, (v))
-#define MmuAPsro	0			/* supervisor rw */
-#define MmuAPsrw	1			/* supervisor rw */
-#define MmuAPuro	2			/* supervisor rw + user ro */
-#define MmuAPurw	3			/* supervisor rw + user rw */
--- a/os/boot/puma/boot.h
+++ /dev/null
@@ -1,12 +1,0 @@
-#include <u.h>
-#include "lib.h"
-
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-#include "ureg.h"
-
-#include "armv4.h"
-#include "puma.h"
-
--- a/os/boot/puma/bootp.c
+++ /dev/null
@@ -1,502 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-#include "ip.h"
-
-uchar broadcast[Eaddrlen] = {
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-};
-
-static ushort tftpport = 5000;
-static int Id = 1;
-static Netaddr myaddr;
-static Netaddr server;
-
-typedef struct {
-	uchar	header[4];
-	uchar	data[Segsize];
-} Tftp;
-static Tftp tftpb;
-
-static void
-hnputs(uchar *ptr, ushort val)
-{
-	ptr[0] = val>>8;
-	ptr[1] = val;
-}
-
-static void
-hnputl(uchar *ptr, ulong val)
-{
-	ptr[0] = val>>24;
-	ptr[1] = val>>16;
-	ptr[2] = val>>8;
-	ptr[3] = val;
-}
-
-static ulong
-nhgetl(uchar *ptr)
-{
-	return ((ptr[0]<<24) | (ptr[1]<<16) | (ptr[2]<<8) | ptr[3]);
-}
-
-static ushort
-nhgets(uchar *ptr)
-{
-	return ((ptr[0]<<8) | ptr[1]);
-}
-
-static	short	endian	= 1;
-static	char*	aendian	= (char*)&endian;
-#define	LITTLE	*aendian
-
-static ushort
-ptcl_csum(void *a, int len)
-{
-	uchar *addr;
-	ulong t1, t2;
-	ulong losum, hisum, mdsum, x;
-
-	addr = a;
-	losum = 0;
-	hisum = 0;
-	mdsum = 0;
-
-	x = 0;
-	if((ulong)addr & 1) {
-		if(len) {
-			hisum += addr[0];
-			len--;
-			addr++;
-		}
-		x = 1;
-	}
-	while(len >= 16) {
-		t1 = *(ushort*)(addr+0);
-		t2 = *(ushort*)(addr+2);	mdsum += t1;
-		t1 = *(ushort*)(addr+4);	mdsum += t2;
-		t2 = *(ushort*)(addr+6);	mdsum += t1;
-		t1 = *(ushort*)(addr+8);	mdsum += t2;
-		t2 = *(ushort*)(addr+10);	mdsum += t1;
-		t1 = *(ushort*)(addr+12);	mdsum += t2;
-		t2 = *(ushort*)(addr+14);	mdsum += t1;
-		mdsum += t2;
-		len -= 16;
-		addr += 16;
-	}
-	while(len >= 2) {
-		mdsum += *(ushort*)addr;
-		len -= 2;
-		addr += 2;
-	}
-	if(x) {
-		if(len)
-			losum += addr[0];
-		if(LITTLE)
-			losum += mdsum;
-		else
-			hisum += mdsum;
-	} else {
-		if(len)
-			hisum += addr[0];
-		if(LITTLE)
-			hisum += mdsum;
-		else
-			losum += mdsum;
-	}
-
-	losum += hisum >> 8;
-	losum += (hisum & 0xff) << 8;
-	while(hisum = losum>>16)
-		losum = hisum + (losum & 0xffff);
-
-	return ~losum;
-}
-
-static ushort
-ip_csum(uchar *addr)
-{
-	int len;
-	ulong sum = 0;
-
-	len = (addr[0]&0xf)<<2;
-
-	while(len > 0) {
-		sum += addr[0]<<8 | addr[1] ;
-		len -= 2;
-		addr += 2;
-	}
-
-	sum = (sum & 0xffff) + (sum >> 16);
-	sum = (sum & 0xffff) + (sum >> 16);
-	return (sum^0xffff);
-}
-
-static void
-udpsend(int ctlrno, Netaddr *a, void *data, int dlen)
-{
-	Udphdr *uh;
-	Etherhdr *ip;
-	Etherpkt pkt;
-	int len, ptcllen;
-
-
-	uh = (Udphdr*)&pkt;
-
-	memset(uh, 0, sizeof(Etherpkt));
-	memmove(uh->udpcksum+sizeof(uh->udpcksum), data, dlen);
-
-	/*
-	 * UDP portion
-	 */
-	ptcllen = dlen + (UDP_HDRSIZE-UDP_PHDRSIZE);
-	uh->ttl = 0;
-	uh->udpproto = IP_UDPPROTO;
-	uh->frag[0] = 0;
-	uh->frag[1] = 0;
-	hnputs(uh->udpplen, ptcllen);
-	hnputl(uh->udpsrc, myaddr.ip);
-	hnputs(uh->udpsport, myaddr.port);
-	hnputl(uh->udpdst, a->ip);
-	hnputs(uh->udpdport, a->port);
-	hnputs(uh->udplen, ptcllen);
-	uh->udpcksum[0] = 0;
-	uh->udpcksum[1] = 0;
-	dlen = (dlen+1)&~1;
-	hnputs(uh->udpcksum, ptcl_csum(&uh->ttl, dlen+UDP_HDRSIZE));
-
-	/*
-	 * IP portion
-	 */
-	ip = (Etherhdr*)&pkt;
-	len = sizeof(Udphdr)+dlen;
-	ip->vihl = IP_VER|IP_HLEN;
-	ip->tos = 0;
-	ip->ttl = 255;
-	hnputs(ip->length, len-ETHER_HDR);
-	hnputs(ip->id, Id++);
-	ip->frag[0] = 0;
-	ip->frag[1] = 0;
-	ip->cksum[0] = 0;
-	ip->cksum[1] = 0;
-	hnputs(ip->cksum, ip_csum(&ip->vihl));
-
-	/*
-	 * Ethernet MAC portion
-	 */
-	hnputs(ip->type, ET_IP);
-	memmove(ip->d, a->ea, sizeof(ip->d));
-
-	ethertxpkt(ctlrno, &pkt, len, Timeout);
-}
-
-static void
-nak(int ctlrno, Netaddr *a, int code, char *msg, int report)
-{
-	int n;
-	char buf[128];
-
-	buf[0] = 0;
-	buf[1] = Tftp_ERROR;
-	buf[2] = 0;
-	buf[3] = code;
-	strcpy(buf+4, msg);
-	n = strlen(msg) + 4 + 1;
-	udpsend(ctlrno, a, buf, n);
-	if(report)
-		print("\ntftp: error(%d): %s\n", code, msg);
-}
-
-static int
-udprecv(int ctlrno, Netaddr *a, void *data, int dlen)
-{
-	int n, len;
-	ushort csm;
-	Udphdr *h;
-	ulong addr, timo;
-	Etherpkt pkt;
-	static int rxactive;
-
-	if(rxactive == 0)
-		timo = 1000;
-	else
-		timo = Timeout;
-	timo += TK2MS(m->ticks);
-	while(timo > TK2MS(m->ticks)){
-		n = etherrxpkt(ctlrno, &pkt, timo-TK2MS(m->ticks));
-
-		if(n <= 0)
-			continue;
-
-		h = (Udphdr*)&pkt;
-		if(nhgets(h->type) != ET_IP)
-			continue;
-
-		if(ip_csum(&h->vihl)) {
-			print("ip chksum error\n");
-			continue;
-		}
-		if(h->vihl != (IP_VER|IP_HLEN)) {
-			print("ip bad vers/hlen\n");
-			continue;
-		}
-
-		if(h->udpproto != IP_UDPPROTO)
-			continue;
-
-		h->ttl = 0;
-		len = nhgets(h->udplen);
-		hnputs(h->udpplen, len);
-
-		if(nhgets(h->udpcksum)) {
-			csm = ptcl_csum(&h->ttl, len+UDP_PHDRSIZE);
-			if(csm != 0) {
-				print("udp chksum error csum #%4lux len %d\n", csm, n);
-				break;
-			}
-		}
-
-		if(a->port != 0 && nhgets(h->udpsport) != a->port)
-			continue;
-
-		addr = nhgetl(h->udpsrc);
-		if(a->ip != Bcastip && addr != a->ip)
-			continue;
-
-		len -= UDP_HDRSIZE-UDP_PHDRSIZE;
-		if(len > dlen) {
-			print("udp: packet too big\n");
-			continue;
-		}
-
-		memmove(data, h->udpcksum+sizeof(h->udpcksum), len);
-		a->ip = addr;
-		a->port = nhgets(h->udpsport);
-		memmove(a->ea, pkt.s, sizeof(a->ea));
-
-		rxactive = 1;
-		return len;
-	}
-
-	return 0;
-}
-
-static int tftpblockno;
-
-static int
-tftpopen(int ctlrno, Netaddr *a, char *name, Tftp *tftp)
-{
-	int i, len, rlen, oport;
-	char buf[Segsize+2];
-
-	buf[0] = 0;
-	buf[1] = Tftp_READ;
-	len = sprint(buf+2, "%s", name) + 2;
-	len += sprint(buf+len+1, "octet") + 2;
-
-	oport = a->port;
-	for(i = 0; i < 5; i++){
-		a->port = oport;
-		udpsend(ctlrno, a, buf, len);
-		a->port = 0;
-		if((rlen = udprecv(ctlrno, a, tftp, sizeof(Tftp))) < sizeof(tftp->header))
-			continue;
-
-		switch((tftp->header[0]<<8)|tftp->header[1]){
-
-		case Tftp_ERROR:
-			print("tftpopen: error (%d): %s\n",
-				(tftp->header[2]<<8)|tftp->header[3], tftp->data);
-			return -1;
-
-		case Tftp_DATA:
-			tftpblockno = 1;
-			len = (tftp->header[2]<<8)|tftp->header[3];
-			if(len != tftpblockno){
-				print("tftpopen: block error: %d\n", len);
-				nak(ctlrno, a, 1, "block error", 0);
-				return -1;
-			}
-			return rlen-sizeof(tftp->header);
-		}
-	}
-
-	print("tftpopen: failed to connect to server\n");
-	return -1;
-}
-
-static int
-tftpread(int ctlrno, Netaddr *a, Tftp *tftp, int dlen)
-{
-	int blockno, len, retry;
-	uchar buf[4];
-
-	buf[0] = 0;
-	buf[1] = Tftp_ACK;
-	buf[2] = tftpblockno>>8;
-	buf[3] = tftpblockno;
-	tftpblockno++;
-
-	dlen += sizeof(tftp->header);
-
-	retry = 0;
-buggery:
-	udpsend(ctlrno, a, buf, sizeof(buf));
-
-	if((len = udprecv(ctlrno, a, tftp, dlen)) != dlen){
-		print("tftpread: %d != %d\n", len, dlen);
-		nak(ctlrno, a, 2, "short read", 0);
-		if(retry++ < 5)
-			goto buggery;
-		return -1;
-	}
-
-	blockno = (tftp->header[2]<<8)|tftp->header[3];
-	if(blockno != tftpblockno){
-		print("tftpread: block error: %d, expected %d\n", blockno, tftpblockno);
-
-		if(blockno == tftpblockno-1 && retry++ < 5)
-			goto buggery;
-		nak(ctlrno, a, 1, "block error", 0);
-
-		return -1;
-	}
-
-	return len-sizeof(tftp->header);
-}
-
-int
-bootp(int ctlrno, char *file)
-{
-	Bootp req, rep;
-	int i, dlen, segsize, text, data, bss, total;
-	uchar *ea, *addr, *p;
-	ulong entry;
-	Exec *exec;
-	char name[128], *filename, *sysname;
-
-	if((ea = etheraddr(ctlrno)) == 0){
-		print("invalid ctlrno %d\n", ctlrno);
-		return -1;
-	}
-
-	filename = 0;
-	sysname = 0;
-	if(file && *file){
-		strcpy(name, file);
-		if(filename = strchr(name, ':')){
-			if(filename != name && *(filename-1) != '\\'){
-				sysname = name;
-				*filename++ = 0;
-			}
-		}
-		else
-			filename = name;
-	}
-		
-
-	memset(&req, 0, sizeof(req));
-	req.op = Bootrequest;
-	req.htype = 1;			/* ethernet */
-	req.hlen = Eaddrlen;		/* ethernet */
-	memmove(req.chaddr, ea, Eaddrlen);
-
-	myaddr.ip = 0;
-	myaddr.port = BPportsrc;
-	memmove(myaddr.ea, ea, Eaddrlen);
-
-	for(i = 0; i < 10; i++) {
-		server.ip = Bcastip;
-		server.port = BPportdst;
-		memmove(server.ea, broadcast, sizeof(server.ea));
-		udpsend(ctlrno, &server, &req, sizeof(req));
-		if(udprecv(ctlrno, &server, &rep, sizeof(rep)) <= 0)
-			continue;
-		if(memcmp(req.chaddr, rep.chaddr, Eaddrlen))
-			continue;
-		if(rep.htype != 1 || rep.hlen != Eaddrlen)
-			continue;
-		if(sysname == 0 || strcmp(sysname, rep.sname) == 0)
-			break;
-	}
-	if(i >= 10) {
-		print("bootp timed out\n");
-		return -1;
-	}
-
-	if(filename == 0 || *filename == 0)
-		filename = rep.file;
-
-	if(rep.sname[0] != '\0')
-		 print("%s ", rep.sname);
-	print("(%d.%d.%d.%d!%d): %s\n",
-		rep.siaddr[0],
-		rep.siaddr[1],
-		rep.siaddr[2],
-		rep.siaddr[3],
-		server.port,
-		filename);
-
-	myaddr.ip = nhgetl(rep.yiaddr);
-	myaddr.port = tftpport++;
-	server.ip = nhgetl(rep.siaddr);
-	server.port = TFTPport;
-
-	if((dlen = tftpopen(ctlrno, &server, filename, &tftpb)) < 0)
-		return -1;
-
-	exec = (Exec*)(tftpb.data);
-	if(dlen < sizeof(Exec) || GLLONG(exec->magic) != E_MAGIC){
-		nak(ctlrno, &server, 0, "bad magic number", 1);
-		return -1;
-	}
-	text = GLLONG(exec->text);
-	data = GLLONG(exec->data);
-	bss = GLLONG(exec->bss);
-	total = text+data+bss;
-	entry = GLLONG(exec->entry);
-print("load@%8.8lux: ", PADDR(entry));
-	print("%d", text);
-
-	addr = (uchar*)PADDR(entry);
-	p = tftpb.data+sizeof(Exec);
-	dlen -= sizeof(Exec);
-	segsize = text;
-	for(;;){
-		if(dlen == 0){
-			if((dlen = tftpread(ctlrno, &server, &tftpb, sizeof(tftpb.data))) < 0)
-				return -1;
-			p = tftpb.data;
-		}
-		if(segsize <= dlen)
-			i = segsize;
-		else
-			i = dlen;
-		memmove(addr, p, i);
-
-		addr += i;
-		p += i;
-		segsize -= i;
-		dlen -= i;
-
-		if(segsize <= 0){
-			if(data == 0)
-				break;
-			print("+%d", data);
-			segsize = data;
-			data = 0;
-			addr = (uchar*)PGROUND((ulong)addr);
-		}
-	}
-	nak(ctlrno, &server, 3, "ok", 0);		/* tftpclose */
-	print("+%d=%d\n", bss, total);
-	print("entry: 0x%lux\n", entry);
-
-	(*(void(*)(void))(PADDR(entry)))();
-	
-	return 0;
-}
--- a/os/boot/puma/cga.c
+++ /dev/null
@@ -1,92 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "io.h"
-#include "fns.h"
-
-enum {
-	Width		= 160,
-	Height		= 25,
-
-	Attr		= 7,		/* white on black */
-};
-
-#define CGASCREENBASE	((uchar*)KADDR(0xB8000))
-
-static int pos;
-static int screeninitdone;
-
-static uchar
-cgaregr(int index)
-{
-	outb(0x3D4, index);
-	return inb(0x3D4+1) & 0xFF;
-}
-
-static void
-cgaregw(int index, int data)
-{
-	outb(0x3D4, index);
-	outb(0x3D4+1, data);
-}
-
-static void
-movecursor(void)
-{
-	cgaregw(0x0E, (pos/2>>8) & 0xFF);
-	cgaregw(0x0F, pos/2 & 0xFF);
-	CGASCREENBASE[pos+1] = Attr;
-}
-
-static void
-cgascreenputc(int c)
-{
-	int i;
-
-	if(c == '\n'){
-		pos = pos/Width;
-		pos = (pos+1)*Width;
-	}
-	else if(c == '\t'){
-		i = 8 - ((pos/2)&7);
-		while(i-->0)
-			cgascreenputc(' ');
-	}
-	else if(c == '\b'){
-		if(pos >= 2)
-			pos -= 2;
-		cgascreenputc(' ');
-		pos -= 2;
-	}
-	else{
-		CGASCREENBASE[pos++] = c;
-		CGASCREENBASE[pos++] = Attr;
-	}
-	if(pos >= Width*Height){
-		memmove(CGASCREENBASE, &CGASCREENBASE[Width], Width*(Height-1));
-		memset(&CGASCREENBASE[Width*(Height-1)], 0, Width);
-		pos = Width*(Height-1);
-	}
-	movecursor();
-}
-
-void
-screeninit(void)
-{
-	if(screeninitdone == 0){
-		pos = cgaregr(0x0E)<<8;
-		pos |= cgaregr(0x0F);
-		pos *= 2;
-		screeninitdone = 1;
-	}
-}
-
-void
-cgascreenputs(char* s, int n)
-{
-	if(screeninitdone == 0)
-		screeninit();
-	while(n-- > 0)
-		cgascreenputc(*s++);
-}
--- a/os/boot/puma/clock.c
+++ /dev/null
@@ -1,154 +1,0 @@
-#include "boot.h"
-
- /*
- * Control Word Read/Write Counter (mode 0)  LSB, MSB
- */
-#define PIT_RW_COUNTER0  0x30
-#define PIT_RW_COUNTER1  0x70
-#define PIT_RW_COUNTER2  0xB0
-#define PIT_COUNTERLATCH0	0x00
-#define PIT_COUNTERLATCH1	0x40
-#define PIT_COUNTERLATCH2	0x80
-
-#define PIT_MODE_0	0	/* Interrupt on Terminal Count */
-#define PIT_MODE_1	2	/* Hardware Retriggeable One-shot */
-#define PIT_MODE_2	4	/* Rate Generator */
-#define PIT_MODE_3	6	/* Square Wave Mode */
-#define PIT_MODE_4	8	/* Software Triggered Mode */
-#define PIT_MODE_5	10	/* Hardware Triggered Mode (Retriggeable) */
-
-/*
- * Harris 82C54 Programmable Interval Timer
- * On the Puma board the PIT is memory mapped
- * starting at 0xf2000000 and with each of the 8-bit
- * registers addressed on a consecutive 4-byte boundary.
- */
-#undef inb
-#undef outb
-#define 	inb(port)			((*(uchar *)(port))&0xff)
-#define 	outb(port, data)	(*(uchar *)(port) = (data))
-enum
-{
-	Cnt0=	0xf2000000,		/* counter locations */
-	Cnt1=	0xf2000004,		/* ... */
-	Cnt2=	0xf2000008,		/* ... */
-	Ctlw=	0xf200000c,		/* control word register*/
-
-	/* commands */
-	Latch0=	0x00,		/* latch counter 0's value */
-	Load0=	0x30,		/* load counter 0 with 2 bytes */
-	Latch1=	0x40,		/* latch counter 1's value */
-	Load1=	0x70,		/* load counter 1 with 2 bytes */
-
-	/* modes */
-	Square=	0x06,		/* periodic square wave */
-	RateGen=	0x04,		/* rate generator */
-
-	Freq=	3686400,	/* Real clock frequency */
-};
-
-static int cpufreq = 233000000;
-static int aalcycles = 14;
-
-static void
-clockintr(Ureg*, void*)
-{
-	m->ticks++;
-	checkalarms();
-}
-
-/*
- *  delay for l milliseconds more or less.  delayloop is set by
- *  clockinit() to match the actual CPU speed.
- */
-void
-delay(int l)
-{
-	l *= m->delayloop;
-	if(l <= 0)
-		l = 1;
-	aamloop(l);
-}
-
-void
-microdelay(int l)
-{
-	l *= m->delayloop;
-	l /= 1000;
-	if(l <= 0)
-		l = 1;
-	aamloop(l);
-}
-
-void
-clockinit(void)
-{
-	int x, y;	/* change in counter */
-	int loops, incr;
-
-	/*
-	 *  set vector for clock interrupts
-	 */
-	setvec(V_TIMER0, clockintr, 0);
-
-	/*
-	 *  set clock for 1/HZ seconds
-	 */
-	outb(Ctlw, Load0|Square);
-	outb(Cnt0, (Freq/HZ));	/* low byte */
-	outb(Cnt0, (Freq/HZ)>>8);	/* high byte */
-
-	/* find biggest loop that doesn't wrap */
-	incr = 16000000/(aalcycles*HZ*2);
-	x = 2000;
-	for(loops = incr; loops < 64*1024; loops += incr) {
-		/*
-		 *  measure time for the loop
-		 *	TEXT aamloop(SB), $-4
-		 *	_aamloop:
-		 *		MOVW	R0, R0
-		 *		MOVW	R0, R0
-		 *		MOVW	R0, R0
-		 *		SUB		$1, R0
-		 *		CMP		$0, R0
-		 *		BNE		_aamloop
-		 *		RET
-		 *
-		 *  the time for the loop should be independent of external
-		 *  cache and memory system since it fits in the execution
-		 *  prefetch buffer.
-		 *
-		 */
-		outb(Ctlw, Latch0);
-		x = inb(Cnt0);
-		x |= inb(Cnt0)<<8;
-		aamloop(loops);
-		outb(Ctlw, Latch0);
-		y = inb(Cnt0);
-		y |= inb(Cnt0)<<8;
-		x -= y;
-	
-		if(x < 0)
-			x += Freq/HZ;
-
-		if(x > Freq/(3*HZ))
-			break;
-	}
-
-	/*
-	 *  counter  goes at twice the frequency, once per transition,
-	 *  i.e., twice per square wave
-	 */
-	x >>= 1;
-
-	/*
- 	 *  figure out clock frequency and a loop multiplier for delay().
-	 */
-	cpufreq = loops*((aalcycles*Freq)/x);
-	m->delayloop = (cpufreq/1000)/aalcycles;	/* AAMLOOPs for 1 ms */
-
-	/*
-	 *  add in possible .2% error and convert to MHz
-	 */
-	m->speed = (cpufreq + cpufreq/500)/1000000;
-}
--- a/os/boot/puma/conf.c
+++ /dev/null
@@ -1,181 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-#include "dosfs.h"
-
-static char *confname[MAXCONF];
-static char *confval[MAXCONF];
-static int nconf;
-
-static	char*	defplan9ini =
-	"ether0=type=CS8900\r\n"
-	"vgasize=640x480x8\r\n"
-	"kernelpercent=40\r\n"
-	"console=1\r\nbaud=9600\r\n"
-;
-
-extern char **ini;
-
-char*
-getconf(char *name)
-{
-	int i;
-
-	for(i = 0; i < nconf; i++)
-		if(strcmp(confname[i], name) == 0)
-			return confval[i];
-	return 0;
-}
-
-/*
- *  read configuration file
- */
-int
-plan9ini(Dos *dos, char *val)
-{
-	Dosfile rc;
-	int i, n;
-	char *cp, *p, *q, *line[MAXCONF];
-
-	cp = BOOTARGS;
-	if(dos) {
-		if(dosstat(dos, *ini, &rc) <= 0)
-			return -1;
-
-		*cp = 0;
-		n = dosread(&rc, cp, BOOTARGSLEN-1);
-		if(n <= 0)
-			return -1;
-		cp[n] = 0;
-	} else if(val != nil){
-		if(memchr(val, 0, BOOTARGSLEN-1) == nil)
-			return -1;
-		print("Using flash configuration\n");
-		strcpy(cp, val);
-		n = strlen(cp);
-	}else{
-		print("Using default configuration\n");
-		strcpy(cp, defplan9ini);
-		n = strlen(cp);
-	}
-
-	/*
-	 * Make a working copy.
-	 * We could change this to pass the parsed strings
-	 * to the booted programme instead of the raw
-	 * string, then it only gets done once.
-	 */
-	memmove(cp+BOOTARGSLEN, cp, n+1);
-	cp += BOOTARGSLEN;
-
-	/*
-	 * Strip out '\r', change '\t' -> ' '.
-	 */
-	p = cp;
-	for(q = cp; *q; q++){
-		if(*q == '\r')
-			continue;
-		if(*q == '\t')
-			*q = ' ';
-		*p++ = *q;
-	}
-	*p = 0;
-	n = getcfields(cp, line, MAXCONF, "\n");
-	for(i = 0; i < n; i++){
-		cp = strchr(line[i], '=');
-		if(cp == 0)
-			continue;
-		*cp++ = 0;
-		if(cp - line[i] >= NAMELEN+1)
-			*(line[i]+NAMELEN-1) = 0;
-		confname[nconf] = line[i];
-		confval[nconf] = cp;
-		nconf++;
-	}
-	return 0;
-}
-
-static int
-parseether(uchar *to, char *from)
-{
-	char nip[4];
-	char *p;
-	int i;
-
-	p = from;
-	while(*p == ' ')
-		++p;
-	for(i = 0; i < 6; i++){
-		if(*p == 0)
-			return -1;
-		nip[0] = *p++;
-		if(*p == 0)
-			return -1;
-		nip[1] = *p++;
-		nip[2] = 0;
-		to[i] = strtoul(nip, 0, 16);
-		if(*p == ':')
-			p++;
-	}
-	return 0;
-}
-
-int
-isaconfig(char *class, int ctlrno, ISAConf *isa)
-{
-	char cc[NAMELEN], *p, *q, *r;
-	int n;
-
-	sprint(cc, "%s%d", class, ctlrno);
-	for(n = 0; n < nconf; n++){
-		if(strncmp(confname[n], cc, NAMELEN))
-			continue;
-		isa->nopt = 0;
-		p = confval[n];
-		while(*p){
-			while(*p == ' ' || *p == '\t')
-				p++;
-			if(*p == '\0')
-				break;
-			if(strncmp(p, "type=", 5) == 0){
-				p += 5;
-				for(q = isa->type; q < &isa->type[NAMELEN-1]; q++){
-					if(*p == '\0' || *p == ' ' || *p == '\t')
-						break;
-					*q = *p++;
-				}
-				*q = '\0';
-			}
-			else if(strncmp(p, "port=", 5) == 0)
-				isa->port = strtoul(p+5, &p, 0);
-			else if(strncmp(p, "irq=", 4) == 0)
-				isa->irq = strtoul(p+4, &p, 0);
-			else if(strncmp(p, "mem=", 4) == 0)
-				isa->mem = strtoul(p+4, &p, 0);
-			else if(strncmp(p, "size=", 5) == 0)
-				isa->size = strtoul(p+5, &p, 0);
-			else if(strncmp(p, "ea=", 3) == 0){
-				if(parseether(isa->ea, p+3) == -1)
-					memset(isa->ea, 0, 6);
-			}
-			else if(isa->nopt < NISAOPT){
-				r = isa->opt[isa->nopt];
-				while(*p && *p != ' ' && *p != '\t'){
-					*r++ = *p++;
-					if(r-isa->opt[isa->nopt] >= ISAOPTLEN-1)
-						break;
-				}
-				*r = '\0';
-				isa->nopt++;
-			}
-			while(*p && *p != ' ' && *p != '\t')
-				p++;
-		}
-		return 1;
-	}
-	return 0;
-}
--- a/os/boot/puma/console.c
+++ /dev/null
@@ -1,181 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-static Queue*	consiq;
-static Queue*	consoq;
-
-void
-bothputs(char *s, int n)
-{
-	uartputs(s, n);
-//	cgascreenputs(s, n);
-}
-
-static void (*consputs)(char*, int) =  0;
-
-void
-consinit(void)
-{
-	char *p;
-	int baud, port;
-	static int cgadone;
-
-	if((p = getconf("console")) == 0 || strcmp(p, "lcd") == 0 || strcmp(p, "screen") == 0){
-		consiq = qopen(4*1024, 0, 0, 0);
-		consoq = qopen(8*1024, 0, 0, 0);
-		consputs = uartputs;
-		if(!cgadone) {
-			cgadone = 1;
-			//screeninit();
-			//kbdinit();
-		port = 1;
-		baud = 9600;
-		uartspecial(port, baud, &consiq, &consoq, kbdchar);
-		}
-		return;
-	}
-	if(0 || strstr(p, "lcd") == 0)
-		consputs = bothputs;
-	else
-		consputs = uartputs;
-
-	port = strtoul(p, 0, 0);
-	baud = 0;
-	if(p = getconf("baud"))
-		baud = strtoul(p, 0, 0);
-	if(baud == 0)
-		baud = 9600;
-	uartspecial(port, baud, &consiq, &consoq, kbdchar);
-}
-
-void
-kbdchar(Queue *q, int c)
-{
-	c &= 0x7F;
-	if(c == 0x10)
-		panic("^p");
-	if(q == 0) {
-		if(consiq != 0)
-			qbputc(consiq, c);
-	} else
-		qbputc(q, c);
-}
-
-static int
-getline(char *buf, int size, int dotimeout)
-{
-	int c, i=0;
-	ulong start;
-	char echo;
-
-	for (;;) {
-		start = m->ticks;
-		do{
-			if(dotimeout && ((m->ticks - start) > 5*HZ))
-				return -2;
-			c = qbgetc(consiq);
-		}while(c == -1);
-		if(c == '\r')
-			c = '\n'; 		/* turn carriage return into newline */
-		if(c == '\177')
-			c = '\010';		/* turn delete into backspace */
-		if(c == '\025')
-			echo = '\n';		/* echo ^U as a newline */
-		else
-			echo = c;
-		(*consputs)(&echo, 1);
-
-		if(c == '\010'){
-			if(i > 0)
-				i--; /* bs deletes last character */
-			continue;
-		}
-		/* a newline ends a line */
-		if (c == '\n')
-			break;
-		/* ^U wipes out the line */
-		if (c =='\025')
-			return -1;
-		if(i == size)
-			return size;
-		buf[i++] = c;
-	}
-	buf[i] = 0;
-	return i;
-}
-
-int
-getstr(char *prompt, char *buf, int size, char *def)
-{
-	int len, isdefault;
-
-	buf[0] = 0;
-	isdefault = (def && *def);
-	for (;;) {
-		if(isdefault)
-			print("%s[default==%s]: ", prompt, def);
-		else
-			print("%s: ", prompt);
-		len = getline(buf, size, isdefault);
-		switch(len){
-		case -1:
-			/* ^U typed */
-			continue;
-		case -2:
-			/* timeout, use default */
-			(*consputs)("\n", 1);
-			len = 0;
-			break;
-		default:
-			break;
-		}
-		if(len >= size){
-			print("line too long\n");
-			continue;
-		}
-		break;
-	}
-	if(len == 0 && isdefault)
-		strcpy(buf, def);
-	return 0;
-}
-
-int
-sprint(char *s, char *fmt, ...)
-{
-	return donprint(s, s+PRINTSIZE, fmt, (&fmt+1)) - s;
-}
-
-int
-print(char *fmt, ...)
-{
-	char buf[PRINTSIZE];
-	int n;
-
-	if(consputs == 0)
-		return 0;
-	n = donprint(buf, buf+sizeof(buf), fmt, (&fmt+1)) - buf;
-	(*consputs)(buf, n);
-	return n;
-}
-
-void
-panic(char *fmt, ...)
-{
-	char buf[PRINTSIZE];
-	int n;
-
-	if(consputs){
-		(*consputs)("panic: ", 7);
-		n = donprint(buf, buf+sizeof(buf), fmt, (&fmt+1)) - buf;
-		(*consputs)(buf, n);
-		(*consputs)("\n", 1);
-	}
-	spllo();
-	for(;;)
-		idle();
-}
--- a/os/boot/puma/dat.h
+++ /dev/null
@@ -1,205 +1,0 @@
-typedef struct Block Block;
-typedef struct Queue Queue;
-
-typedef struct List {
-	void	*next;
-} List;
-
-typedef struct {
-	int	fake;
-	int	pri;
-} Lock;
-#define	lock(x)
-#define	unlock(x)
-
-typedef struct Alarm {
-	List;
-	int	busy;
-	long	dt;
-	void	(*f)(void*);
-	void	*arg;
-} Alarm;
-
-enum {
-	Eaddrlen	= 6,
-	ETHERMINTU	= 60,		/* minimum transmit size */
-	ETHERMAXTU	= 1514,		/* maximum transmit size */
-	ETHERHDRSIZE	= 14,		/* size of an ethernet header */
-
-	MaxEther	= 2,
-};
-
-typedef struct {
-	uchar	d[Eaddrlen];
-	uchar	s[Eaddrlen];
-	uchar	type[2];
-	uchar	data[1500];
-	uchar	crc[4];
-} Etherpkt;
-
-extern uchar broadcast[Eaddrlen];
-
-enum {
-	Npart		= 20+2,		/* 8 sub partitions, disk, and partition */
-	Maxxfer		= 16*1024,	/* maximum transfer size/cmd */
-};
-
-typedef struct {
-	ulong	start;
-	ulong	end;
-	char	name[NAMELEN+1];
-} Partition;
-
-typedef struct {
-	int	online;
-	int	npart;		/* number of real partitions */
-	Partition p[Npart];
-	ulong	offset;
-	Partition *current;	/* current partition */
-
-	ulong	cap;		/* total bytes */
-	int	bytes;		/* bytes/sector */
-	int	sectors;		/* sectors/track */
-	int	heads;		/* heads/cyl */
-	long	cyl;			/* cylinders/drive */
-
-	char	lba;			/* true if drive has logical block addressing */
-	char	multi;		/* non-zero if drive does multiple block xfers */
-} Disc;
-
-enum {
-	ScsiTestunit	= 0x00,
-	ScsiExtsens	= 0x03,
-	ScsiInquiry	= 0x12,
-	ScsiModesense	= 0x1a,
-	ScsiStartunit	= 0x1B,
-	ScsiStopunit	= 0x1B,
-	ScsiGetcap	= 0x25,
-	ScsiRead	= 0x08,
-	ScsiWrite	= 0x0a,
-	ScsiExtread	= 0x28,
-	ScsiExtwrite	= 0x2a,
-
-	/* data direction */
-	ScsiIn		= 1,
-	ScsiOut		= 0,
-};
-
-typedef struct Scsibuf Scsibuf;
-typedef struct Scsibuf {
-	void*		virt;
-	void*		phys;
-	Scsibuf*	next;
-};
-
-typedef struct Scsidata {
-	uchar*		base;
-	uchar*		lim;
-	uchar*		ptr;
-} Scsidata;
-
-typedef struct Ureg Ureg;
-
-typedef struct Scsi {
-	ulong		pid;
-	ushort		target;
-	ushort		lun;
-	ushort		rflag;
-	ushort		status;
-	Scsidata 	cmd;
-	Scsidata 	data;
-	Scsibuf*	b;
-	uchar*		save;
-	uchar		cmdblk[16];
-} Scsi;
-
-typedef struct Segdesc {
-	ulong	d0;
-	ulong	d1;
-} Segdesc;
-
-typedef struct Mach {
-	ulong	ticks;		/* of the clock since boot time */
-	ulong	delayloop;
-	int		speed;		/* general system clock in MHz */
-	int		oscclk;		/* oscillator frequency in MHz */
-	void*	alarm;		/* alarms bound to this clock */
-} Mach;
-
-extern Mach *m;
-
-#define E_MAGIC		((((4*20)+0)*20)+7)
-
-typedef struct Exec Exec;
-struct	Exec
-{
-	uchar	magic[4];		/* magic number */
-	uchar	text[4];	 	/* size of text segment */
-	uchar	data[4];	 	/* size of initialized data */
-	uchar	bss[4];	  		/* size of uninitialized data */
-	uchar	syms[4];	 	/* size of symbol table */
-	uchar	entry[4];	 	/* entry point */
-	uchar	spsz[4];		/* size of sp/pc offset table */
-	uchar	pcsz[4];		/* size of pc/line number table */
-};
-
-/*
- *  bootline passed by boot program
- */
-#define BOOTLINE ((char *)0x18000-150)
-
-/*
- * Where we leave configuration info.
- */
-#define BOOTARGS	((char*)(0x18000))
-#define	BOOTARGSLEN	1024
-#define	MAXCONF		32
-
-/*
- *  a parsed plan9.ini line
- */
-#define ISAOPTLEN	16
-#define NISAOPT		8
-
-typedef struct  ISAConf {
-	char	type[NAMELEN];
-	ulong	port;
-	ulong	irq;
-	ulong	mem;
-	ulong	size;
-	uchar	ea[6];
-
-	int	nopt;
-	char	opt[NISAOPT][ISAOPTLEN];
-} ISAConf;
-
-typedef struct {
-	int	size;
-	ulong	addr;
-} Map;
-
-typedef struct {
-	char*	name;
-	Map*	map;
-	Map*	mapend;
-
-	Lock;
-} RMap;
-
-typedef struct PCIcfg PCIcfg;
-
-extern	uchar*	vgamem;
-
-struct Block {
-	uchar	*rp;
-	uchar	*wp;
-	uchar	*lim;
-	uchar	*data;
-	Block*	next;
-	ulong	magic;
-};
-#define	BLEN(b)	((b)->wp-(b)->rp)
-
-typedef struct QLock {
-	int	dummy;
-} QLock;
--- a/os/boot/puma/div.s
+++ /dev/null
@@ -1,122 +1,0 @@
-/*
- * Div/Mod taken from the Inferno 2.0 ebsit code
- */
-
-Q	= 0
-N	= 1
-D	= 2
-CC	= 3
-TMP	= 11
-
-TEXT	save<>(SB), 1, $0
-	MOVW	R(Q), 0(FP)
-	MOVW	R(N), 4(FP)
-	MOVW	R(D), 8(FP)
-	MOVW	R(CC), 12(FP)
-
-	MOVW	R(TMP), R(Q)		/* numerator */
-	MOVW	20(FP), R(D)		/* denominator */
-	CMP	$0, R(D)
-	BNE	s1
-	MOVW	-1(R(D)), R(TMP)	/* divide by zero fault */
-s1:	RET
-
-TEXT	rest<>(SB), 1, $0
-	MOVW	0(FP), R(Q)
-	MOVW	4(FP), R(N)
-	MOVW	8(FP), R(D)
-	MOVW	12(FP), R(CC)
-/*
- * return to caller
- * of rest<>
- */
-	MOVW	0(R13), R14
-	ADD	$20, R13
-	B	(R14)
-
-TEXT	div<>(SB), 1, $0
-	MOVW	$32, R(CC)
-/*
- * skip zeros 8-at-a-time
- */
-e1:
-	AND.S	$(0xff<<24),R(Q), R(N)
-	BNE	e2
-	SLL	$8, R(Q)
-	SUB.S	$8, R(CC)
-	BNE	e1
-	RET
-e2:
-	MOVW	$0, R(N)
-
-loop:
-/*
- * shift R(N||Q) left one
- */
-	SLL	$1, R(N)
-	CMP	$0, R(Q)
-	ORR.LT	$1, R(N)
-	SLL	$1, R(Q)
-
-/*
- * compare numerator to denominator
- * if less, subtract and set quotent bit
- */
-	CMP	R(D), R(N)
-	ORR.HS	$1, R(Q)
-	SUB.HS	R(D), R(N)
-	SUB.S	$1, R(CC)
-	BNE	loop
-	RET
-
-TEXT	_div(SB), 1, $16
-	BL	save<>(SB)
-	CMP	$0, R(Q)
-	BGE	d1
-	RSB	$0, R(Q), R(Q)
-	CMP	$0, R(D)
-	BGE	d2
-	RSB	$0, R(D), R(D)
-d0:
-	BL	div<>(SB)		/* none/both neg */
-	MOVW	R(Q), R(TMP)
-	B	out
-d1:
-	CMP	$0, R(D)
-	BGE	d0
-	RSB	$0, R(D), R(D)
-d2:
-	BL	div<>(SB)		/* one neg */
-	RSB	$0, R(Q), R(TMP)
-	B	out
-
-TEXT	_mod(SB), 1, $16
-	BL	save<>(SB)
-	CMP	$0, R(D)
-	RSB.LT	$0, R(D), R(D)
-	CMP	$0, R(Q)
-	BGE	m1
-	RSB	$0, R(Q), R(Q)
-	BL	div<>(SB)		/* neg numerator */
-	RSB	$0, R(N), R(TMP)
-	B	out
-m1:
-	BL	div<>(SB)		/* pos numerator */
-	MOVW	R(N), R(TMP)
-	B	out
-
-TEXT	_divu(SB), 1, $16
-	BL	save<>(SB)
-	BL	div<>(SB)
-	MOVW	R(Q), R(TMP)
-	B	out
-
-TEXT	_modu(SB), 1, $16
-	BL	save<>(SB)
-	BL	div<>(SB)
-	MOVW	R(N), R(TMP)
-	B	out
-
-out:
-	BL	rest<>(SB)
-	B	out
--- a/os/boot/puma/donprint.c
+++ /dev/null
@@ -1,332 +1,0 @@
-#include	"u.h"
-#include	"lib.h"
-
-#define	PTR	sizeof(char*)
-#define	SHORT	sizeof(int)
-#define	INT	sizeof(int)
-#define	LONG	sizeof(long)
-#define	IDIGIT	30
-#define	MAXCON	30
-
-#define	FLONG	(1<<0)
-#define	FSHORT	(1<<1)
-#define	FUNSIGN	(1<<2)
-
-typedef struct Op	Op;
-struct Op
-{
-	char	*p;
-	char	*ep;
-	void	*argp;
-	int	f1;
-	int	f2;
-	int	f3;
-};
-
-static	int	noconv(Op*);
-static	int	cconv(Op*);
-static	int	dconv(Op*);
-static	int	hconv(Op*);
-static	int	lconv(Op*);
-static	int	oconv(Op*);
-static	int	sconv(Op*);
-static	int	uconv(Op*);
-static	int	xconv(Op*);
-static	int	Xconv(Op*);
-static	int	percent(Op*);
-
-static
-int	(*fmtconv[MAXCON])(Op*) =
-{
-	noconv,
-	cconv, dconv, hconv, lconv,
-	oconv, sconv, uconv, xconv,
-	Xconv, percent,
-};
-static
-char	fmtindex[128] =
-{
-	['c'] 1,
-	['d'] 2,
-	['h'] 3,
-	['l'] 4,
-	['o'] 5,
-	['s'] 6,
-	['u'] 7,
-	['x'] 8,
-	['X'] 9,
-	['%'] 10,
-};
-
-static	int	convcount  = { 11 };
-static	int	ucase;
-
-static void
-PUT(Op *o, int c)
-{
-	static int pos;
-	int opos;
-
-	if(c == '\t'){
-		opos = pos;
-		pos = (opos+8) & ~7;
-		while(opos++ < pos && o->p < o->ep)
-			*o->p++ = ' ';
-		return;
-	}
-	if(o->p < o->ep){
-		*o->p++ = c;
-		pos++;
-	}
-	if(c == '\n')
-		pos = 0;
-}
-
-int
-fmtinstall(char c, int (*f)(Op*))
-{
-
-	c &= 0177;
-	if(fmtindex[c] == 0) {
-		if(convcount >= MAXCON)
-			return 1;
-		fmtindex[c] = convcount++;
-	}
-	fmtconv[fmtindex[c]] = f;
-	return 0;
-}
-
-char*
-donprint(char *p, char *ep, char *fmt, void *argp)
-{
-	int sf1, c;
-	Op o;
-
-	o.p = p;
-	o.ep = ep;
-	o.argp = argp;
-
-loop:
-	c = *fmt++;
-	if(c != '%') {
-		if(c == 0) {
-			if(o.p < o.ep)
-				*o.p = 0;
-			return o.p;
-		}
-		PUT(&o, c);
-		goto loop;
-	}
-	o.f1 = 0;
-	o.f2 = -1;
-	o.f3 = 0;
-	c = *fmt++;
-	sf1 = 0;
-	if(c == '-') {
-		sf1 = 1;
-		c = *fmt++;
-	}
-	while(c >= '0' && c <= '9') {
-		o.f1 = o.f1*10 + c-'0';
-		c = *fmt++;
-	}
-	if(sf1)
-		o.f1 = -o.f1;
-	if(c != '.')
-		goto l1;
-	c = *fmt++;
-	while(c >= '0' && c <= '9') {
-		if(o.f2 < 0)
-			o.f2 = 0;
-		o.f2 = o.f2*10 + c-'0';
-		c = *fmt++;
-	}
-l1:
-	if(c == 0)
-		fmt--;
-	c = (*fmtconv[fmtindex[c&0177]])(&o);
-	if(c < 0) {
-		o.f3 |= -c;
-		c = *fmt++;
-		goto l1;
-	}
-	o.argp = (char*)o.argp + c;
-	goto loop;
-}
-
-void
-strconv(char *o, Op *op, int f1, int f2)
-{
-	int n, c;
-	char *p;
-
-	n = strlen(o);
-	if(f1 >= 0)
-		while(n < f1) {
-			PUT(op, ' ');
-			n++;
-		}
-	for(p=o; c = *p++;)
-		if(f2 != 0) {
-			PUT(op, c);
-			f2--;
-		}
-	if(f1 < 0) {
-		f1 = -f1;
-		while(n < f1) {
-			PUT(op, ' ');
-			n++;
-		}
-	}
-}
-
-int
-numbconv(Op *op, int base)
-{
-	char b[IDIGIT];
-	int i, f, n, r;
-	long v;
-	short h;
-
-	f = 0;
-	switch(op->f3 & (FLONG|FSHORT|FUNSIGN)) {
-	case FLONG:
-		v = *(long*)op->argp;
-		r = LONG;
-		break;
-
-	case FUNSIGN|FLONG:
-		v = *(ulong*)op->argp;
-		r = LONG;
-		break;
-
-	case FSHORT:
-		h = *(int*)op->argp;
-		v = h;
-		r = SHORT;
-		break;
-
-	case FUNSIGN|FSHORT:
-		h = *(int*)op->argp;
-		v = (ushort)h;
-		r = SHORT;
-		break;
-
-	default:
-		v = *(int*)op->argp;
-		r = INT;
-		break;
-
-	case FUNSIGN:
-		v = *(unsigned*)op->argp;
-		r = INT;
-		break;
-	}
-	if(!(op->f3 & FUNSIGN) && v < 0) {
-		v = -v;
-		f = 1;
-	}
-	b[IDIGIT-1] = 0;
-	for(i = IDIGIT-2;; i--) {
-		n = (ulong)v % base;
-		n += '0';
-		if(n > '9'){
-			n += 'a' - ('9'+1);
-			if(ucase)
-				n += 'A'-'a';
-		}
-		b[i] = n;
-		if(i < 2)
-			break;
-		v = (ulong)v / base;
-		if(op->f2 >= 0 && i >= IDIGIT-op->f2)
-			continue;
-		if(v <= 0)
-			break;
-	}
-	if(f)
-		b[--i] = '-';
-	strconv(b+i, op, op->f1, -1);
-	return r;
-}
-
-static	int
-noconv(Op *op)
-{
-
-	strconv("***", op, 0, -1);
-	return 0;
-}
-
-static	int
-cconv(Op *op)
-{
-	char b[2];
-
-	b[0] = *(int*)op->argp;
-	b[1] = 0;
-	strconv(b, op, op->f1, -1);
-	return INT;
-}
-
-static	int
-dconv(Op *op)
-{
-	return numbconv(op, 10);
-}
-
-static	int
-hconv(Op*)
-{
-	return -FSHORT;
-}
-
-static	int
-lconv(Op*)
-{
-	return -FLONG;
-}
-
-static	int
-oconv(Op *op)
-{
-	return numbconv(op, 8);
-}
-
-static	int
-sconv(Op *op)
-{
-	strconv(*(char**)op->argp, op, op->f1, op->f2);
-	return PTR;
-}
-
-static	int
-uconv(Op*)
-{
-	return -FUNSIGN;
-}
-
-static	int
-xconv(Op *op)
-{
-	return numbconv(op, 16);
-}
-
-static	int
-Xconv(Op *op)
-{
-	int r;
-
-	ucase = 1;
-	r = numbconv(op, 16);
-	ucase = 0;
-	return r;
-}
-
-static	int
-percent(Op *op)
-{
-
-	PUT(op, '%');
-	return 0;
-}
--- a/os/boot/puma/dosboot.c
+++ /dev/null
@@ -1,614 +1,0 @@
-#include	"u.h"
-#include	"lib.h"
-#include	"mem.h"
-#include	"dat.h"
-#include	"fns.h"
-#include	"dosfs.h"
-
-extern char *premature;
-
-/*
- *  predeclared
- */
-static void	bootdump(Dosboot*);
-static void	setname(Dosfile*, char*);
-long		dosreadseg(Dosfile*, long, long);
-
-/*
- *  debugging
- */
-#define chatty	1
-#define chat	if(chatty)print
-
-/*
- *  block io buffers
- */
-enum
-{
-	Nbio=	16,
-};
-typedef struct	Clustbuf	Clustbuf;
-struct Clustbuf
-{
-	int	age;
-	long	sector;
-	uchar	*iobuf;
-	Dos	*dos;
-	int	size;
-};
-Clustbuf	bio[Nbio];
-
-/*
- *  get an io block from an io buffer
- */
-Clustbuf*
-getclust(Dos *dos, long sector)
-{
-	Clustbuf *p, *oldest;
-	int size;
-
-	chat("getclust @ %d\n", sector);
-
-	/*
-	 *  if we have it, just return it
-	 */
-	for(p = bio; p < &bio[Nbio]; p++){
-		if(sector == p->sector && dos == p->dos){
-			p->age = m->ticks;
-			chat("getclust %d in cache\n", sector);
-			return p;
-		}
-	}
-
-	/*
-	 *  otherwise, reuse the oldest entry
-	 */
-	oldest = bio;
-	for(p = &bio[1]; p < &bio[Nbio]; p++){
-		if(p->age <= oldest->age)
-			oldest = p;
-	}
-	p = oldest;
-
-	/*
-	 *  make sure the buffer is big enough
-	 */
-	size = dos->clustsize*dos->sectsize;
-	if(p->iobuf==0 || p->size < size)
-		p->iobuf = ialloc(size, 0);
-	p->size = size;
-
-	/*
-	 *  read in the cluster
-	 */
-	chat("getclust addr %d\n", (sector+dos->start)*dos->sectsize);
-	if((*dos->seek)(dos->dev, (sector+dos->start)*dos->sectsize) < 0){
-		chat("can't seek block\n");
-		return 0;
-	}
-	if((*dos->read)(dos->dev, p->iobuf, size) != size){
-		chat("can't read block\n");
-		return 0;
-	}
-
-	p->age = m->ticks;
-	p->dos = dos;
-	p->sector = sector;
-	chat("getclust %d read\n", sector);
-	return p;
-}
-
-/*
- *  walk the fat one level ( n is a current cluster number ).
- *  return the new cluster number or -1 if no more.
- */
-static long
-fatwalk(Dos *dos, int n)
-{
-	ulong k, sect;
-	Clustbuf *p;
-	int o;
-
-	chat("fatwalk %d\n", n);
-
-	if(n < 2 || n >= dos->fatclusters)
-		return -1;
-
-	switch(dos->fatbits){
-	case 12:
-		k = (3*n)/2; break;
-	case 16:
-		k = 2*n; break;
-	default:
-		return -1;
-	}
-	if(k >= dos->fatsize*dos->sectsize)
-		panic("getfat");
-
-	sect = (k/(dos->sectsize*dos->clustsize))*dos->clustsize + dos->fataddr;
-	o = k%(dos->sectsize*dos->clustsize);
-	p = getclust(dos, sect);
-	k = p->iobuf[o++];
-	if(o >= dos->sectsize*dos->clustsize){
-		p = getclust(dos, sect+dos->clustsize);
-		o = 0;
-	}
-	k |= p->iobuf[o]<<8;
-	if(dos->fatbits == 12){
-		if(n&1)
-			k >>= 4;
-		else
-			k &= 0xfff;
-		if(k >= 0xff8)
-			k |= 0xf000;
-	}
-	k = k < 0xfff8 ? k : -1;
-	chat("fatwalk %d -> %d\n", n, k);
-	return k;
-}
-
-/*
- *  map a file's logical cluster address to a physical sector address
- */
-static long
-fileaddr(Dosfile *fp, long ltarget)
-{
-	Dos *dos = fp->dos;
-	long l;
-	long p;
-
-	chat("fileaddr %8.8s %d\n", fp->name, ltarget);
-	/*
-	 *  root directory is contiguous and easy
-	 */
-	if(fp->pstart == 0){
-		if(ltarget*dos->sectsize*dos->clustsize >= dos->rootsize*sizeof(Dosdir))
-			return -1;
-		l = dos->rootaddr + ltarget*dos->clustsize;
-		chat("fileaddr %d -> %d\n", ltarget, l);
-		return l;
-	}
-
-	/*
-	 *  anything else requires a walk through the fat
-	 */
-	if(ltarget >= fp->lcurrent && fp->pcurrent){
-		/* start at the currrent point */
-		l = fp->lcurrent;
-		p = fp->pcurrent;
-	} else {
-		/* go back to the beginning */
-		l = 0;
-		p = fp->pstart;
-	}
-	while(l != ltarget){
-		/* walk the fat */
-		p = fatwalk(dos, p);
-		if(p < 0)
-			return -1;
-		l++;
-	}
-	fp->lcurrent = l;
-	fp->pcurrent = p;
-
-	/*
-	 *  clusters start at 2 instead of 0 (why? - presotto)
-	 */
-	l =  dos->dataaddr + (p-2)*dos->clustsize;
-	chat("fileaddr %d -> %d\n", ltarget, l);
-	return l;
-}
-
-/*
- *  read from a dos file
- */
-long
-dosread(Dosfile *fp, void *a, long n)
-{
-	long addr;
-	long rv;
-	int i;
-	int off;
-	Clustbuf *p;
-	uchar *from, *to;
-
-	if((fp->attr & DDIR) == 0){
-		if(fp->offset >= fp->length)
-			return 0;
-		if(fp->offset+n > fp->length)
-			n = fp->length - fp->offset;
-	}
-
-	to = a;
-	for(rv = 0; rv < n; rv+=i){
-		/*
-		 *  read the cluster
-		 */
-		addr = fileaddr(fp, fp->offset/fp->dos->clustbytes);
-		if(addr < 0)
-			return -1;
-		p = getclust(fp->dos, addr);
-		if(p == 0)
-			return -1;
-
-		/*
-		 *  copy the bytes we need
-		 */
-		off = fp->offset % fp->dos->clustbytes;
-		from = &p->iobuf[off];
-		i = n - rv;
-		if(i > fp->dos->clustbytes - off)
-			i = fp->dos->clustbytes - off;
-		memmove(to, from, i);
-		to += i;
-		fp->offset += i;
-	}
-
-	return rv;
-}
-
-/*
- *  walk a directory returns
- * 	-1 if something went wrong
- *	 0 if not found
- *	 1 if found
- */
-int
-doswalk(Dosfile *file, char *name)
-{
-	Dosdir d;
-	long n;
-
-	if((file->attr & DDIR) == 0){
-		chat("walking non-directory!\n");
-		return -1;
-	}
-
-	setname(file, name);
-
-	file->offset = 0;	/* start at the beginning */
-	while((n = dosread(file, &d, sizeof(d))) == sizeof(d)){
-		chat("comparing to %8.8s.%3.3s\n", d.name, d.ext);
-		if(memcmp(file->name, d.name, sizeof(d.name)) != 0)
-			continue;
-		if(memcmp(file->ext, d.ext, sizeof(d.ext)) != 0)
-			continue;
-		if(d.attr & DVLABEL){
-			chat("%8.8s.%3.3s is a LABEL\n", d.name, d.ext);
-			continue;
-		}
-		file->attr = d.attr;
-		file->pstart = GSHORT(d.start);
-		file->length = GLONG(d.length);
-		file->pcurrent = 0;
-		file->lcurrent = 0;
-		file->offset = 0;
-		return 1;
-	}
-	return n >= 0 ? 0 : -1;
-}
-
-
-/*
- *  instructions that boot blocks can start with
- */
-#define	JMPSHORT	0xeb
-#define JMPNEAR		0xe9
-
-/*
- *  read dos file system properties
- */
-int
-dosinit(Dos *dos, int start, int ishard)
-{
-	Dosboot *b;
-	int i;
-	Clustbuf *p;
-	Dospart *dp;
-	ulong mbroffset, offset;
-
-	/* defaults till we know better */
-	dos->start = start;
-	dos->sectsize = 512;
-	dos->clustsize = 1;
-	mbroffset = 0;
-
-dmddo:
-	/* get first sector */
-	p = getclust(dos, mbroffset);
-	if(p == 0){
-		chat("can't read boot block\n");
-		return -1;
-	}
-
-	/*
-	 * If it's a hard disc then look for an MBR and pick either an
-	 * active partition or the FAT with the lowest starting LBA.
-	 * Things are tricky because we could be pointing to, amongst others:
-	 *	1) a floppy BPB;
-	 *	2) a hard disc MBR;
-	 *	3) a hard disc extended partition table;
-	 *	4) a logical drive on a hard disc;
-	 *	5) a disc-manager boot block.
-	 * They all have the same magic at the end of the block.
-	 */
-	if(p->iobuf[0x1FE] != 0x55 || p->iobuf[0x1FF] != 0xAA) {
-		chat("not DOS\n");
-		return -1;
-	}
-	p->dos = 0;
-	b = (Dosboot *)p->iobuf;
-	if(ishard && b->mediadesc != 0xF8){
-		dp = (Dospart*)&p->iobuf[0x1BE];
-		offset = 0xFFFFFFFF;
-		for(i = 0; i < 4; i++, dp++){
-			if(dp->type == DMDDO){
-				mbroffset = 63;
-				goto dmddo;
-			}
-			if(dp->type != FAT12 && dp->type != FAT16 && dp->type != FATHUGE)
-				continue;
-			if(dp->flag & 0x80){
-				offset = GLONG(dp->start);
-				break;
-			}
-			if(GLONG(dp->start) < offset)
-				offset = GLONG(dp->start);
-		}
-		if(i != 4 || offset != 0xFFFFFFFF){
-			dos->start = mbroffset+offset;
-			p = getclust(dos, 0);
-			if(p == 0 || p->iobuf[0x1FE] != 0x55 || p->iobuf[0x1FF] != 0xAA)
-				return -1;
-		}
-		p->dos = 0;
-	}
-
-	b = (Dosboot *)p->iobuf;
-	if(b->magic[0] != JMPNEAR && (b->magic[0] != JMPSHORT || b->magic[2] != 0x90)){
-		chat("no dos file system\n");
-		return -1;
-	}
-
-	if(chatty)
-		bootdump(b);
-
-	/*
-	 *  determine the systems' wondersous properties
-	 */
-	dos->sectsize = GSHORT(b->sectsize);
-	dos->clustsize = b->clustsize;
-	dos->clustbytes = dos->sectsize*dos->clustsize;
-	dos->nresrv = GSHORT(b->nresrv);
-	dos->nfats = b->nfats;
-	dos->rootsize = GSHORT(b->rootsize);
-	dos->volsize = GSHORT(b->volsize);
-	if(dos->volsize == 0)
-		dos->volsize = GLONG(b->bigvolsize);
-	dos->mediadesc = b->mediadesc;
-	dos->fatsize = GSHORT(b->fatsize);
-	dos->fataddr = dos->nresrv;
-	dos->rootaddr = dos->fataddr + dos->nfats*dos->fatsize;
-	i = dos->rootsize*sizeof(Dosdir) + dos->sectsize - 1;
-	i = i/dos->sectsize;
-	dos->dataaddr = dos->rootaddr + i;
-	dos->fatclusters = 2+(dos->volsize - dos->dataaddr)/dos->clustsize;
-	if(dos->fatclusters < 4087)
-		dos->fatbits = 12;
-	else
-		dos->fatbits = 16;
-	dos->freeptr = 2;
-
-	/*
-	 *  set up the root
-	 */
-	dos->root.dos = dos;
-	dos->root.pstart = 0;
-	dos->root.pcurrent = dos->root.lcurrent = 0;
-	dos->root.offset = 0;
-	dos->root.attr = DDIR;
-	dos->root.length = dos->rootsize*sizeof(Dosdir);
-
-	return 0;
-}
-
-static void
-bootdump(Dosboot *b)
-{
-	if(chatty == 0)
-		return;
-	print("magic: 0x%2.2x 0x%2.2x 0x%2.2x\n",
-		b->magic[0], b->magic[1], b->magic[2]);
-	print("version: \"%8.8s\"\n", b->version);
-	print("sectsize: %d\n", GSHORT(b->sectsize));
-	print("allocsize: %d\n", b->clustsize);
-	print("nresrv: %d\n", GSHORT(b->nresrv));
-	print("nfats: %d\n", b->nfats);
-	print("rootsize: %d\n", GSHORT(b->rootsize));
-	print("volsize: %d\n", GSHORT(b->volsize));
-	print("mediadesc: 0x%2.2x\n", b->mediadesc);
-	print("fatsize: %d\n", GSHORT(b->fatsize));
-	print("trksize: %d\n", GSHORT(b->trksize));
-	print("nheads: %d\n", GSHORT(b->nheads));
-	print("nhidden: %d\n", GLONG(b->nhidden));
-	print("bigvolsize: %d\n", GLONG(b->bigvolsize));
-	print("driveno: %d\n", b->driveno);
-	print("reserved0: 0x%2.2x\n", b->reserved0);
-	print("bootsig: 0x%2.2x\n", b->bootsig);
-	print("volid: 0x%8.8x\n", GLONG(b->volid));
-	print("label: \"%11.11s\"\n", b->label);
-}
-
-/*
- *  grab next element from a path, return the pointer to unprocessed portion of
- *  path.
- */
-static char *
-nextelem(char *path, char *elem)
-{
-	int i;
-
-	while(*path == '/')
-		path++;
-	if(*path==0 || *path==' ')
-		return 0;
-	for(i=0; *path!='\0' && *path!='/' && *path!=' '; i++){
-		if(i==28){
-			print("name component too long\n");
-			return 0;
-		}
-		*elem++ = *path++;
-	}
-	*elem = '\0';
-	return path;
-}
-
-int
-dosstat(Dos *dos, char *path, Dosfile *f)
-{
-	char element[NAMELEN];
-
-	*f = dos->root;
-	while(path = nextelem(path, element)){
-		switch(doswalk(f, element)){
-		case -1:
-			return -1;
-		case 0:
-			return 0;
-		}
-	}
-	return 1;
-}
-
-/*
- *  boot
- */
-int
-dosboot(Dos *dos, char *path)
-{
-	Dosfile file;
-	long n;
-	long addr;
-	Exec *ep;
-	void (*b)(void);
-
-	switch(dosstat(dos, path, &file)){
-
-	case -1:
-		print("error walking to %s\n", path);
-		return -1;
-	case 0:
-		print("%s not found\n", path);
-		return -1;
-	case 1:
-		print("found %8.8s.%3.3s attr 0x%ux start 0x%lux len %d\n", file.name,
-			file.ext, file.attr, file.pstart, file.length);
-		break;
-	}
-
-	/*
-	 *  read header
-	 */
-	ep = (Exec*)ialloc(sizeof(Exec), 0);
-	n = sizeof(Exec);
-	if(dosreadseg(&file, n, (ulong) ep) != n){
-		print(premature);
-		return -1;
-	}
-	if(GLLONG(ep->magic) != E_MAGIC){
-		print("bad magic 0x%lux not a plan 9 executable!\n", GLLONG(ep->magic));
-		return -1;
-	}
-
-	/*
-	 *  read text
-	 */
-	addr = PADDR(GLLONG(ep->entry));
-	n = GLLONG(ep->text);
-	print("+%d", n);
-	if(dosreadseg(&file, n, addr) != n){
-		print(premature);
-		return -1;
-	}
-
-	/*
-	 *  read data (starts at first page after kernel)
-	 */
-	addr = PGROUND(addr+n);
-	n = GLLONG(ep->data);
-	print("+%d", n);
-	if(dosreadseg(&file, n, addr) != n){
-		print(premature);
-		return -1;
-	}
-
-	/*
-	 *  bss and entry point
-	 */
-	print("+%d\nstart at 0x%lux\n", GLLONG(ep->bss), GLLONG(ep->entry));
-
-	/*
-	 *  Go to new code. It's up to the program to get its PC relocated to
-	 *  the right place.
-	 */
-	b = (void (*)(void))(PADDR(GLLONG(ep->entry)));
-	(*b)();
-	return 0;
-}
-
-/*
- *  read in a segment
- */
-long
-dosreadseg(Dosfile *fp, long len, long addr)
-{
-	char *a;
-	long n, sofar;
-
-	a = (char *)addr;
-	for(sofar = 0; sofar < len; sofar += n){
-		n = 8*1024;
-		if(len - sofar < n)
-			n = len - sofar;
-		n = dosread(fp, a + sofar, n);
-		if(n <= 0)
-			break;
-		print(".");
-	}
-	return sofar;
-}
-
-/*
- *  set up a dos file name
- */
-static void
-setname(Dosfile *fp, char *from)
-{
-	char *to;
-
-	to = fp->name;
-	for(; *from && to-fp->name < 8; from++, to++){
-		if(*from == '.'){
-			from++;
-			break;
-		}
-		if(*from >= 'a' && *from <= 'z')
-			*to = *from + 'A' - 'a';
-		else
-			*to = *from;
-	}
-	while(to - fp->name < 8)
-		*to++ = ' ';
-	
-	to = fp->ext;
-	for(; *from && to-fp->ext < 3; from++, to++){
-		if(*from >= 'a' && *from <= 'z')
-			*to = *from + 'A' - 'a';
-		else
-			*to = *from;
-	}
-	while(to-fp->ext < 3)
-		*to++ = ' ';
-
-	chat("name is %8.8s %3.3s\n", fp->name, fp->ext);
-}
--- a/os/boot/puma/dosfs.h
+++ /dev/null
@@ -1,110 +1,0 @@
-typedef struct Dosboot	Dosboot;
-typedef struct Dos	Dos;
-typedef struct Dosdir	Dosdir;
-typedef struct Dosfile	Dosfile;
-typedef struct Dospart	Dospart;
-
-struct Dospart
-{
-	uchar flag;		/* active flag */
-	uchar shead;		/* starting head */
-	uchar scs[2];		/* starting cylinder/sector */
-	uchar type;		/* partition type */
-	uchar ehead;		/* ending head */
-	uchar ecs[2];		/* ending cylinder/sector */
-	uchar start[4];		/* starting sector */
-	uchar len[4];		/* length in sectors */
-};
-
-#define FAT12	0x01
-#define FAT16	0x04
-#define FATHUGE	0x06
-#define DMDDO	0x54
-
-struct Dosboot{
-	uchar	magic[3];
-	uchar	version[8];
-	uchar	sectsize[2];
-	uchar	clustsize;
-	uchar	nresrv[2];
-	uchar	nfats;
-	uchar	rootsize[2];
-	uchar	volsize[2];
-	uchar	mediadesc;
-	uchar	fatsize[2];
-	uchar	trksize[2];
-	uchar	nheads[2];
-	uchar	nhidden[4];
-	uchar	bigvolsize[4];
-	uchar	driveno;
-	uchar	reserved0;
-	uchar	bootsig;
-	uchar	volid[4];
-	uchar	label[11];
-	uchar	reserved1[8];
-};
-
-struct Dosfile{
-	Dos	*dos;		/* owning dos file system */
-	char	name[8];
-	char	ext[3];
-	uchar	attr;
-	long	length;
-	long	pstart;		/* physical start cluster address */
-	long	pcurrent;	/* physical current cluster address */
-	long	lcurrent;	/* logical current cluster address */
-	long	offset;
-};
-
-struct Dos{
-	int	dev;				/* device id */
-	long	(*read)(int, void*, long);	/* read routine */
-	long	(*seek)(int, long);		/* seek routine */
-
-	int	start;		/* start of file system */
-	int	sectsize;	/* in bytes */
-	int	clustsize;	/* in sectors */
-	int	clustbytes;	/* in bytes */
-	int	nresrv;		/* sectors */
-	int	nfats;		/* usually 2 */
-	int	rootsize;	/* number of entries */
-	int	volsize;	/* in sectors */
-	int	mediadesc;
-	int	fatsize;	/* in sectors */
-	int	fatclusters;
-	int	fatbits;	/* 12 or 16 */
-	long	fataddr;	/* sector number */
-	long	rootaddr;
-	long	dataaddr;
-	long	freeptr;
-
-	Dosfile	root;
-};
-
-struct Dosdir{
-	uchar	name[8];
-	uchar	ext[3];
-	uchar	attr;
-	uchar	reserved[10];
-	uchar	time[2];
-	uchar	date[2];
-	uchar	start[2];
-	uchar	length[4];
-};
-
-#define	DRONLY	0x01
-#define	DHIDDEN	0x02
-#define	DSYSTEM	0x04
-#define	DVLABEL	0x08
-#define	DDIR	0x10
-#define	DARCH	0x20
-
-extern int chatty;
-
-extern int dosboot(Dos*, char*);
-extern int dosinit(Dos*, int, int);
-extern long dosread(Dosfile*, void*, long);
-extern int dosstat(Dos*, char*, Dosfile*);
-extern int doswalk(Dosfile*, char*);
-
-extern int plan9ini(Dos*, char*);
--- a/os/boot/puma/ebsit.trap.c
+++ /dev/null
@@ -1,206 +1,0 @@
-#include "u.h"
-#include "../port/lib.h"
-#include "mem.h"
-#include "ebsit.h"
-#include "dat.h"
-#include "fns.h"
-
-#include "ureg.h"
-
-int inpanic;
-
-#define CSR ((ushort *) 0x2000000)
- 
-
-typedef struct Irqctlr {
-	uint	addr;
-  	uint	enabled;
-	struct {
-		void	(*r)(Ureg*, void*);
-		void 	*a;
-	} h[16];
-} Irqctlr;
-
-static Irqctlr irqctlr;  
-
-void 
-csrset( int bit )
-{
-static ushort *csr_val = 0x8c;
-
-	*csr_val ^= (1 << bit);
-	putcsr(*csr_val);
-}
-
-void
-intrinit( void )
-{
-int offset;
-ulong op;
-
-
-	irqctlr.addr = 1;
-	irqctlr.enabled = 0;
- 
-	/* Reset Exception */
-	offset = ((((ulong) _vsvccall) - 0x0)-8) >> 2;
-	op = ( 0xea << 24 ) | offset;
-	*((ulong *) 0x0) = op;
-
-	/* Undefined Instruction Exception */
-	offset = ((((ulong) _vundcall) - 0x4)-8) >> 2;
-	op = ( 0xea << 24 ) | offset;
-	*((ulong *) 0x4) = op;
-
-	/* SWI Exception */
-	offset = ((((ulong) _vsvccall) - 0x8)-8) >> 2;
-	op = ( 0xea << 24 ) | offset;
-	*((ulong *) 0x8) = op;
-
-	/* Prefetch Abort Exception */
-	offset = ((((ulong) _vpabcall) - 0xc)-8) >> 2;
-	op = ( 0xea << 24 ) | offset;
-	*((ulong *) 0xc) = op;
-
-	/* Data Abort Exception */
-	offset = ((((ulong) _vdabcall) - 0x10)-8) >> 2;
-	op = ( 0xea << 24 ) | offset;
-	*((ulong *) 0x10) = op;
-
-	/* IRQ Exception */
-	offset = ((((ulong) _virqcall) - 0x18)-8) >> 2;
-	op = ( 0xea << 24 ) | offset;
-	*((ulong *) 0x18) = op;
-
-
-}
-
-void
-intrenable(uint addr, int bit, void (*r)(Ureg*, void*), void* a)
-{
-	int i;
-	USED(addr);
-	for(i = 0; i < 16; i++)
-		{
-		if((bit & (1<<i)) == 0)
-			continue;
-		irqctlr.h[i].r = r;
-		irqctlr.h[i].a = a;
-		irqctlr.enabled |= (1<<i); 
-		if (i < 7) 
-			csrset(i);
-		}
-	return;
-}
-
-int lucifer;					/* Global to store the last CSR (eric) */
-
-static void
-interrupt(Ureg* ureg)
-{
-	int i, mask;
-
- 		mask = *CSR;
-		lucifer = mask;			/* eric */
-		if(irqctlr.enabled == 0){
-		
-			return;
- 			}
-		for(i = 0; i < 16; i++)
-			{
-
-			if((irqctlr.enabled & (1<<i)) == 0)
-				continue;
-			if(( mask & (1 << i)) == 0)
-				continue;
-			if (!irqctlr.h[i].r)
-				continue;
-			(irqctlr.h[i].r)(ureg, irqctlr.h[i].a);
-			mask &= ~(1 << i);
-			}
-
-		if ((mask) && (mask < 0x90))		/* ignore non-maskable interrupts */
-			{
-			print("unknown or unhandled interrupt\n");
-			panic("unknown or unhandled interrupt: mask=%ux",mask);
-			}
-	
-}
-
-static void
-dumpregs(Ureg* ureg)
-{
-	print("PSR %8.8uX type %2.2uX PC %8.8uX LINK %8.8uX\n",
-		ureg->psr, ureg->type, ureg->pc, ureg->link);
-	print("R14 %8.8uX R13 %8.8uX R12 %8.8uX R11 %8.8uX R10 %8.8uX\n",
-		ureg->r14, ureg->r13, ureg->r12, ureg->r11, ureg->r10);
-	print("R9  %8.8uX R8  %8.8uX R7  %8.8uX R6  %8.8uX R5  %8.8uX\n",
-		ureg->r9, ureg->r8, ureg->r7, ureg->r6, ureg->r5);
-	print("R4  %8.8uX R3  %8.8uX R2  %8.8uX R1  %8.8uX R0  %8.8uX\n",
-		ureg->r4, ureg->r3, ureg->r2, ureg->r1, ureg->r0);
-	print("Last Interrupt's CSR: %8.8uX\n",lucifer);
-	print("CPSR %8.8uX SPSR %8.8uX\n", cpsrr(), spsrr());
-}
-
-void
-dumpstack(void)
-{
-}
-
-void
-exception(Ureg* ureg)
-{
-	static Ureg old_ureg;
-	uint far =0;
-	uint fsr =0;
-
-	static lasttype = 0;
-
-	LOWBAT;	
-	
-	USED(far, fsr);
-
-	lasttype = ureg->type;
-
-	/*
-	 * All interrupts/exceptions should be resumed at ureg->pc-4,
-	 * except for Data Abort which resumes at ureg->pc-8.
-	 */
-
-	if(ureg->type == (PsrMabt+1))
-		ureg->pc -= 8;
-	else
-		ureg->pc -= 4;
-
-	switch(ureg->type){
-
-	case PsrMfiq:				/* (Fast) */
-		print("Fast\n");
-		print("We should never be here\n");
-		while(1);
-
-	case PsrMirq:				/* Interrupt Request */
-		interrupt(ureg);
-		break;
-
-	case PsrMund:				/* Undefined instruction */
-		print("Undefined instruction\n");
-	case PsrMsvc:				/* Jump through 0, SWI or reserved trap */
-		print("SWI/SVC trap\n");
-	case PsrMabt:				/* Prefetch abort */
-		print("Prefetch Abort\n");
-	case PsrMabt+1:				/* Data abort */
-		print("Data Abort\n");
-
-
-	default:
-		dumpregs(ureg);
-		/* panic("exception %uX\n", ureg->type); */
-		break;
-	}
-
-	LOWBAT;				/* Low bat off after interrupt */
-
-	splhi();
-
-}
--- a/os/boot/puma/ether.c
+++ /dev/null
@@ -1,156 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-#include "ether.h"
-
-static Ctlr ether[MaxEther];
-
-static struct {
-	char	*type;
-	int	(*reset)(Ctlr*);
-} cards[] = {
-	{ "CS8900", cs8900reset, },
-	{ 0, }
-};
-
-int
-etherinit(void)
-{
-	Ctlr *ctlr;
-	int ctlrno, i, mask, n;
-
-	mask = 0;
-	for(ctlrno = 0; ctlrno < MaxEther; ctlrno++){
-		ctlr = &ether[ctlrno];
-		memset(ctlr, 0, sizeof(Ctlr));
-		if(isaconfig("ether", ctlrno, &ctlr->card) == 0)
-			continue;
-		for(n = 0; cards[n].type; n++){
-			if(strcmp(cards[n].type, ctlr->card.type))
-				continue;
-			ctlr->ctlrno = ctlrno;
-			if((*cards[n].reset)(ctlr))
-				break;
-
-			ctlr->iq = qopen(16*1024, 1, 0, 0);
-			ctlr->oq = qopen(16*1024, 1, 0, 0);
-
-			ctlr->present = 1;
-			mask |= 1<<ctlrno;
-
-			print("ether%d: %s: port 0x%luX irq %d",
-				ctlr->ctlrno, ctlr->card.type, ctlr->card.port, ctlr->card.irq);
-			if(ctlr->card.mem)
-				print(" addr 0x%luX", ctlr->card.mem & ~KZERO);
-			if(ctlr->card.size)
-				print(" size 0x%luX", ctlr->card.size);
-			print(":");
-			for(i = 0; i < sizeof(ctlr->card.ea); i++)
-				print(" %2.2uX", ctlr->card.ea[i]);
-			print("\n"); uartwait();
-			setvec(ctlr->card.irq, ctlr->card.intr, ctlr);
-			break;
-		}
-	}
-
-	return mask;
-}
-
-static Ctlr*
-attach(int ctlrno)
-{
-	Ctlr *ctlr;
-
-	if(ctlrno >= MaxEther || ether[ctlrno].present == 0)
-		return 0;
-
-	ctlr = &ether[ctlrno];
-	if(ctlr->present == 1){
-		ctlr->present = 2;
-		(*ctlr->card.attach)(ctlr);
-	}
-
-	return ctlr;
-}
-
-uchar*
-etheraddr(int ctlrno)
-{
-	Ctlr *ctlr;
-
-	if((ctlr = attach(ctlrno)) == 0)
-		return 0;
-
-	return ctlr->card.ea;
-}
-
-int
-etherrxpkt(int ctlrno, Etherpkt *pkt, int timo)
-{
-	int n;
-	Ctlr *ctlr;
-	Block *b;
-	ulong start;
-
-	if((ctlr = attach(ctlrno)) == 0)
-		return 0;
-
-	start = m->ticks;
-	while((b = qget(ctlr->iq)) == 0){
-		if(TK2MS(m->ticks - start) >= timo){
-			/*
-			print("ether%d: rx timeout\n", ctlrno);
-			 */
-			return 0;
-		}
-		//delay(1);
-	}
-
-	n = BLEN(b);
-	memmove(pkt, b->rp, n);
-	freeb(b);
-
-	return n;
-}
-
-int
-etheriq(Ctlr *ctlr, Block *b, int freebp)
-{
-	if(memcmp(((Etherpkt*)b->rp)->d, ctlr->card.ea, Eaddrlen) != 0){
-		if(freebp)
-			freeb(b);
-		return 0;
-	}
-	qbwrite(ctlr->iq, b);
-	return 1;
-}
-
-int
-ethertxpkt(int ctlrno, Etherpkt *pkt, int len, int)
-{
-	Ctlr *ctlr;
-	Block *b;
-	int s;
-
-	if((ctlr = attach(ctlrno)) == 0)
-		return 0;
-
-	if(qlen(ctlr->oq) > 16*1024){
-		print("ether%d: tx queue full\n", ctlrno);
-		return 0;
-	}
-	b = iallocb(sizeof(Etherpkt));
-	memmove(b->wp, pkt, len);
-	memmove(((Etherpkt*)b->wp)->s, ctlr->card.ea, Eaddrlen);
-	b->wp += len;
-	qbwrite(ctlr->oq, b);
-	s = splhi();
-	(*ctlr->card.transmit)(ctlr);
-	splx(s);
-
-	return 1;
-}
--- a/os/boot/puma/ether.h
+++ /dev/null
@@ -1,82 +1,0 @@
-/*
- * All the goo for PC ethernet cards.
- */
-typedef struct Card Card;
-typedef struct RingBuf RingBuf;
-typedef struct Type Type;
-typedef struct Ctlr Ctlr;
-
-/*
- * Hardware interface.
- */
-struct Card {
-	ISAConf;
-
-	int	(*reset)(Ctlr*);
-	void	(*attach)(Ctlr*);
-
-	void	*(*read)(Ctlr*, void*, ulong, ulong);
-	void	*(*write)(Ctlr*, ulong, void*, ulong);
-
-	void	(*receive)(Ctlr*);
-	void	(*transmit)(Ctlr*);
-	void	(*intr)(Ureg*, Ctlr*);
-	void	(*overflow)(Ctlr*);
-
-	uchar	bit16;			/* true if a 16 bit interface */
-	uchar	ram;			/* true if card has shared memory */
-
-	ulong	dp8390;			/* I/O address of 8390 (if any) */
-	ulong	data;			/* I/O data port if no shared memory */
-	uchar	nxtpkt;			/* software bndry */
-	uchar	tstart;			/* 8390 ring addresses */
-	uchar	pstart;
-	uchar	pstop;
-
-	uchar	dummyrr;		/* do dummy remote read */
-};
-
-/*
- * Software ring buffer.
- */
-struct RingBuf {
-	uchar	owner;
-	uchar	busy;			/* unused */
-	ushort	len;
-	uchar	pkt[sizeof(Etherpkt)];
-};
-
-enum {
-	Host		= 0,		/* buffer owned by host */
-	Interface	= 1,		/* buffer owned by card */
-
-	Nrb		= 16,		/* default number of receive buffers */
-	Ntb		= 2,		/* default number of transmit buffers */
-};
-
-/*
- * Software controller.
- */
-struct Ctlr {
-	Card	card;			/* hardware info */
-	int	ctlrno;
-	int	present;
-
-	Queue*	iq;
-	Queue*	oq;
-
-	int	inpackets;
-	int	outpackets;
-	int	crcs;			/* input crc errors */
-	int	oerrs;			/* output errors */
-	int	frames;			/* framing errors */
-	int	overflows;		/* packet overflows */
-	int	buffs;			/* buffering errors */
-};
-
-#define NEXT(x, l)	(((x)+1)%(l))
-#define	HOWMANY(x, y)	(((x)+((y)-1))/(y))
-#define ROUNDUP(x, y)	(HOWMANY((x), (y))*(y))
-
-extern int cs8900reset(Ctlr*);
-extern int	etheriq(Ctlr*, Block*, int);
--- a/os/boot/puma/ether8900.c
+++ /dev/null
@@ -1,555 +1,0 @@
-/*
- * Crystal CS8900 ethernet controller
- * Specifically for the Teralogic Puma architecture
- */
-
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-#include "ether.h"
-#include "puma.h"
-
-/*
- * On the Puma board the CS8900 can be addressed from either 
- * ISA I/O space or ISA memory space at the following locations.
- * The cs8900 address pins are shifted by 1 relative to the CPU.
- */
-enum {
-	IsaIOBase		= 0xf0000000,
-	IsaMemBase	= 0xe0000000,
-
-	IOBase		= 0x300,
-	MemBase		= 0xc0000,
-};
-
-/* I/O accesses */
-#define	out16(port, val)	(*((ushort *)IsaIOBase + IOBase + (port)) = (val))
-#define	in16(port)			*((ushort *)IsaIOBase + IOBase + (port))
-#define	in8(port)			*((uchar *)IsaIOBase + ((IOBase+(port))<<1))
-#define	regIOw(reg, val)	 do {out16(PpPtr, (reg)|0x3000); out16(PpData, val);} while(0)
-#define	regIOr(reg)		(out16(PpPtr, (reg)|0x3000), in16(PpData))
-#define	regIOr1(reg)		(out16(PpPtr, (reg)|0x3000), in16(PpData1))
-
-/* Memory accesses */
-#define	regw(reg, val)		*((ushort *)IsaMemBase + MemBase + (reg)) = (val)
-#define	regr(reg)			*((ushort *)IsaMemBase + MemBase + (reg))
-
-/* Puma frame copying */
-#define	copyout(src, len)	{ \
-						int _len = (len); \
-						ushort *_src = (ushort *)(src); \
-						ushort *_dst = (ushort *)IsaMemBase + MemBase + TxFrame; \
-						while(_len > 0) { \
-							*_dst++ = *_src++; \
-							_dst++; \
-							_len -= 2; \
-						} \
-					}
-#define	copyoutIO(src, len)	{ \
-						int _len = (len); \
-						ushort *_src = (ushort *)(src); \
-						while(_len > 0) { \
-							out16(RxTxData, *_src); \
-							_src++; \
-							_len -= 2; \
-						} \
-					}
-#define	copyin(dst, len)	{ \
-						int _len = (len), _len2 = (len)&~1; \
-						ushort *_src = (ushort *)IsaMemBase + MemBase + RxFrame; \
-						ushort *_dst = (ushort *)(dst); \
-						while(_len2 > 0) { \
-							*_dst++ = *_src++; \
-							_src++; \
-							_len2 -= 2; \
-						} \
-						if(_len&1) \
-							*(uchar*)_dst = (*_src)&0xff; \
-					}
-#define	copyinIO(dst, len)	{ \
-						int _i, _len = (len), _len2 = (len)&~1; \
-						ushort *_dst = (ushort *)(dst); \
-						_i = in16(RxTxData); USED(_i); /* RxStatus */ \
-						_i = in16(RxTxData); USED(_i); /* RxLen */ \
-						while(_len2 > 0) { \
-							*_dst++ = in16(RxTxData); \
-							_len2 -= 2; \
-						} \
-						if(_len&1) \
-							*(uchar*)_dst = (in16(RxTxData))&0xff; \
-					}
-						
-	
-
-enum {					/* I/O Mode Register Offsets */
-	RxTxData	= 0x00,		/* receive/transmit data - port 0 */
-	TxCmdIO = 0x04,		/* transmit command */
-	TxLenIO	= 0x06,		/* transmit length */
-	IsqIO	= 0x08,		/* Interrupt status queue */
-	PpPtr	= 0x0a,		/* packet page pointer */
-	PpData	= 0x0c,		/* packet page data */
-	PpData1	= 0x0e,		/* packet page data - port 1*/
-};
-
-enum {					/* Memory Mode Register Offsets */
-	/* Bus Interface Registers */
-	Ern		= 0x0000,		/* EISA registration numberion */
-	Pic		= 0x0002,		/* Product identification code */
-	Iob		= 0x0020,		/* I/O base address */
-	Intr		= 0x0022,		/* interrupt number */
-	Mba		= 0x002c,		/* memory base address */
-	
-	Ecr		= 0x0040,		/* EEPROM command register */
-	Edw		= 0x0042,		/* EEPROM data word */
-	Rbc		= 0x0050,		/* receive frame byte counter */
-
-	/* Status and Control Registers */
-	RxCfg	= 0x0102,
-	RxCtl	= 0x0104,
-	TxCfg	= 0x0106,
-	BufCfg	= 0x010a,
-	LineCtl	= 0x0112,
-	SelfCtl	= 0x0114,
-	BusCtl	= 0x0116,
-	TestCtl	= 0x0118,
-	Isq		= 0x0120,
-	RxEvent	= 0x0124,
-	TxEvent	= 0x0128,
-	BufEvent	= 0x012c,
-	RxMISS	= 0x0130,
-	TxCol	= 0x0132,
-	LineSt	= 0x0134,
-	SelfSt	= 0x0136,
-	BusSt	= 0x0138,
-	Tdr		= 0x013c,
-
-	/* Initiate Transmit Registers */
-	TxCmd	= 0x0144,		/* transmit command */
-	TxLen	= 0x0146,		/* transmit length */
-
-	/* Address Filter Registers */
-	IndAddr	= 0x0158,		/* individual address registers */
-
-	/* Frame Location */
-	RxStatus	= 0x0400,		/* receive status */
-	RxLen	= 0x0402,		/* receive length */
-	RxFrame	= 0x0404,		/* receive frame location */
-	TxFrame	= 0x0a00,		/* transmit frame location */
-};
-
-enum {					/* Ecr */
-	Addr			= 0x00ff,		/* EEPROM word address (field) */
-	Opcode		= 0x0300,		/* command opcode (field) */
-};
-
-enum {					/* Isq */
-	Regnum		= 0x003f,		/* register number held by Isq (field) */
-		IsqRxEvent	= 0x04,
-		IsqTxEvent	= 0x08,
-		IsqBufEvent	= 0x0c,
-		IsqRxMiss		= 0x10,
-		IsqTxCol		= 0x12,
-	RegContent 	= 0xffc0,		/* register data contents (field) */
-};
-
-enum {					/* RxCfg */
-	Skip_1		= 0x0040,
-	StreamE		= 0x0080,
-	RxOKiE		= 0x0100,
-	RxDMAonly	= 0x0200,
-	AutoRxDMAE	= 0x0400,
-	BufferCRC		= 0x0800,
-	CRCerroriE	= 0x1000,
-	RuntiE		= 0x2000,
-	ExtradataiE	= 0x4000,
-};
-
-enum {					/* RxEvent */
-	IAHash		= 0x0040,
-	Dribblebits	= 0x0080,
-	RxOK		= 0x0100,
-	Hashed		= 0x0200,
-	IndividualAdr	= 0x0400,
-	Broadcast		= 0x0800,
-	CRCerror		= 0x1000,
-	Runt			= 0x2000,
-	Extradata		= 0x4000,
-};
-
-enum {					/* RxCtl */
-	IAHashA		= 0x0040,
-	PromiscuousA	= 0x0080,
-	RxOKA		= 0x0100,
-	MulticastA	= 0x0200,
-	IndividualA	= 0x0400,
-	BroadcastA	= 0x0800,
-	CRCerrorA	= 0x1000,
-	RuntA		= 0x2000,
-	ExtradataA	= 0x4000,
-};
-
-enum {					/* TxCfg */
-	LossofCRSiE	= 0x0040,
-	SQEerroriE	= 0x0080,
-	TxOKiE		= 0x0100,
-	OutofWindowiE	= 0x0200,
-	JabberiE		= 0x0400,
-	AnycolliE		= 0x0800,
-	Coll16iE		= 0x8000,
-};
-
-enum {					/* TxEvent */
-	LossofCRS	= 0x0040,
-	SQEerror		= 0x0080,
-	TxOK		= 0x0100,
-	OutofWindow	= 0x0200,
-	Jabber		= 0x0400,
-	NTxCols		= 0x7800,		/* number of Tx collisions (field) */
-	coll16		= 0x8000,
-};
-
-enum {					/* BufCfg */
-	SWintX		= 0x0040,
-	RxDMAiE		= 0x0080,
-	Rdy4TxiE		= 0x0100,
-	TxUnderruniE	= 0x0200,
-	RxMissiE		= 0x0400,
-	Rx128iE		= 0x0800,
-	TxColOvfiE	= 0x1000,
-	MissOvfloiE	= 0x2000,
-	RxDestiE		= 0x8000,
-};
-
-enum {					/* BufEvent */
-	SWint		= 0x0040,
-	RxDMAFrame	= 0x0080,
-	Rdy4Tx		= 0x0100,
-	TxUnderrun	= 0x0200,
-	RxMiss		= 0x0400,
-	Rx128		= 0x0800,
-	RxDest		= 0x8000,
-};
-
-enum {					/* RxMiss */
-	MissCount	= 0xffc0,
-};
-
-enum {					/* TxCol */
-	ColCount	= 0xffc0,
-};
-
-enum {					/* LineCtl */
-	SerRxOn		= 0x0040,
-	SerTxOn		= 0x0080,
-	Iface			= 0x0300,		/* (field) 01 - AUI, 00 - 10BASE-T, 10 - Auto select */
-	ModBackoffE	= 0x0800,
-	PolarityDis	= 0x1000,
-	DefDis		= 0x2000,
-	LoRxSquelch	= 0x4000,
-};
-
-enum {					/* LineSt */
-	LinkOK		= 0x0080,
-	AUI			= 0x0100,
-	TenBT		= 0x0200,
-	PolarityOK	= 0x1000,
-	CRS			= 0x4000,
-};
-
-enum {					/* SelfCtl */
-	RESET		= 0x0040,
-	SWSuspend	= 0x0100,
-	HWSleepE		= 0x0200,
-	HWStandbyE	= 0x0400,
-};
-
-enum {					/* SelfSt */
-	INITD		= 0x0080,
-	SIBUSY		= 0x0100,
-	EepromPresent	= 0x0200,
-	EepromOK	= 0x0400,
-	ElPresent		= 0x0800,
-	EeSize		= 0x1000,
-};
-
-enum {					/* BusCtl */
-	ResetRxDMA	= 0x0040,
-	UseSA		= 0x0200,
-	MemoryE		= 0x0400,
-	DMABurst		= 0x0800,
-	EnableIRQ		= 0x8000,
-};
-
-enum {					/* BusST */
-	TxBidErr		= 0x0080,
-	Rdy4TxNOW	= 0x0100,
-};
-
-enum {					/* TestCtl */
-	FDX			= 0x4000,		/* full duplex */
-};
-
-enum {					/* TxCmd */
-	TxStart		= 0x00c0,		/* bytes before transmit starts (field) */
-		TxSt5	= 0x0000,		/* start after 5 bytes */
-		TxSt381	= 0x0040,		/* start after 381 bytes */
-		TxSt1021	= 0x0080,		/* start after 1021 bytes */
-		TxStAll	= 0x00c0,		/* start after the entire frame is in the cs8900 */
-	Force		= 0x0100,
-	Onecoll		= 0x0200,
-	InhibitCRC	= 0x1000,
-	TxPadDis		= 0x2000,
-};
-
-static Queue *pendingTx[MaxEther];
-
-static void
-attach(Ctlr *ctlr)
-{
-	int reg;
-
-	USED(ctlr);
-	/* enable transmit and receive */
-	reg = regr(BusCtl);
-	regw(BusCtl, reg|EnableIRQ);
-	reg = regr(LineCtl);
-	regw(LineCtl, reg|SerRxOn|SerTxOn);
-}
-
-static char pbuf[200];
-int
-sprintx(void *f, char *to, int count)
-{
-	int i, printable;
-	char *start = to;
-	uchar *from = f;
-
-	if(count < 0) {
-		print("BAD DATA COUNT %d\n", count);
-		return 0;
-	}
-	printable = 1;
-	if(count > 40)
-		count = 40;
-	for(i=0; i<count && printable; i++)
-		if((from[i]<32 && from[i] !='\n' && from[i] !='\r' && from[i] !='\b' && from[i] !='\t') || from[i]>127)
-			printable = 0;
-	*to++ = '\'';
-	if(printable){
-		memmove(to, from, count);
-		to += count;
-	}else{
-		for(i=0; i<count; i++){
-			if(i>0 && i%4==0)
-				*to++ = ' ';
-			sprint(to, "%2.2ux", from[i]);
-			to += 2;
-		}
-	}
-	*to++ = '\'';
-	*to = 0;
-	return to - start;
-}
-
-static void
-transmit(Ctlr *ctlr)
-{
-	int len, status;
-	Block *b;
-
-	for(;;){
-		/* is TxCmd pending ? - check */
-		if(qlen(pendingTx[ctlr->ctlrno]) > 0)
-			break;
-		b = qget(ctlr->oq);
-		if(b == 0)
-			break;
-		len = BLEN(b);
-		regw(TxCmd, TxSt381);
-		regw(TxLen, len);
-		status = regr(BusSt);
-		if((status & Rdy4TxNOW) == 0) {
-			qbwrite(pendingTx[ctlr->ctlrno], b);
-			break;
-		}
-		/*
-		 * Copy the packet to the transmit buffer.
-		 */
-		copyout(b->rp, len);
-		freeb(b);
-	}
-}
-
-static void
-interrupt(Ureg*, Ctlr *ctlr)
-{
-	int len, events, status;
-	Block *b;
-	Queue *q;
-
-	while((events = regr(Isq)) != 0) {
-		status = events&RegContent;
-	
-		switch(events&Regnum) {
-
-		case IsqBufEvent:
-			if(status&Rdy4Tx) {
-				if(qlen(pendingTx[ctlr->ctlrno]) > 0)
-					q = pendingTx[ctlr->ctlrno];
-				else
-					q = ctlr->oq;
-				b = qget(q);
-				if(b == 0)
-					break;
-				len = BLEN(b);
-				copyout(b->rp, len);
-				freeb(b);
-			} else
-			if(status&TxUnderrun) {
-				print("TxUnderrun\n");
-			} else
-			if(status&RxMiss) {
-				print("RxMiss\n");
-			} else {
-				print("IsqBufEvent status = %ux\n", status);
-			}
-			break;
-
-		case IsqRxEvent:
-			if(status&RxOK) {
-				len = regr(RxLen);
-				if((b = iallocb(len)) != 0) {
-					copyin(b->wp, len);
-					b->wp += len;
-					etheriq(ctlr, b, 1);
-				}
-			} else {
-				print("IsqRxEvent status = %ux\n", status);
-			}
-			break;
-
-		case IsqTxEvent:
-			if(status&TxOK) {
-				if(qlen(pendingTx[ctlr->ctlrno]) > 0)
-					q = pendingTx[ctlr->ctlrno];
-				else
-					q = ctlr->oq;
-				b = qget(q);
-				if(b == 0)
-					break;
-				len = BLEN(b);
-				regw(TxCmd, TxSt381);
-				regw(TxLen, len);
-if((regr(BusSt) & Rdy4TxNOW) == 0) {
-	print("IsqTxEvent and Rdy4TxNow == 0\n");
-}
-				copyout(b->rp, len);
-				freeb(b);
-			} else {
-				print("IsqTxEvent status = %ux\n", status);
-			}
-			break;
-		case IsqRxMiss:
-			break;
-		case IsqTxCol:
-			break;
-		}
-	}
-}
-
-int
-cs8900reset(Ctlr* ctlr)
-{
-	int i, reg;
-	uchar ea[Eaddrlen];
-
-	ctlr->card.irq = V_ETHERNET;
-	pendingTx[ctlr->ctlrno] = qopen(16*1024, 1, 0, 0);
-
-	/*
-	 * If the Ethernet address is not set in the plan9.ini file
-	 * a) try reading from the Puma board ROM. The ether address is found in
-	 * 	bytes 4-9 of the ROM. The Teralogic Organizational Unique Id (OUI) 
-	 *	is in bytes 4-6 and should be 00 10 8a.
-	 */
-	memset(ea, 0, Eaddrlen);
-	if(memcmp(ea, ctlr->card.ea, Eaddrlen) == 0) {
-		uchar *rom = (uchar *)EPROM_BASE;
-		if(rom[4] != 0x00 || rom[5] != 0x10 || rom[6] != 0x8a)
-			panic("no ether address");
-		memmove(ea, &rom[4], Eaddrlen);
-	}
-	memmove(ctlr->card.ea, ea, Eaddrlen);
-
-	/* 
-	 * Identify the chip by reading the Pic register.
-	 * The EISA registration number is in the low word
-	 * and the product identification code in the high code.
-	 * The ERN for Crystal Semiconductor is 0x630e.
-	 * Bits 0-7 and 13-15 of the Pic should be zero for a CS8900.
-	 */
-	if(regIOr(Ern) != 0x630e || (regIOr(Pic) & 0xe0ff) != 0)
-		panic("no cs8900 found");
-
-	/*
-	 * Reset the chip and ensure 16-bit mode operation
-	 */
-	regIOw(SelfCtl, RESET);
-	delay(10);
-	i=in8(PpPtr); 	USED(i);
-	i=in8(PpPtr+1); USED(i);
-	i=in8(PpPtr); 	USED(i);
-	i=in8(PpPtr+1);	USED(i);
-
-	/*
-	 * Wait for initialisation and EEPROM reads to complete
-	 */
-	i=0;
-	for(;;) {
-		short st = regIOr(SelfSt);
-		if((st&SIBUSY) == 0 && st&INITD)
-			break;
-		if(i++ > 1000000)
-			panic("cs8900: initialisation failed");
-	}
-
-	/*
-	 * Enable memory mode operation.
-	 */
-	regIOw(Mba, MemBase & 0xffff);
-	regIOw(Mba+2, MemBase >> 16);
-	regIOw(BusCtl, MemoryE|UseSA);
-
-	/*
-	 * Enable 10BASE-T half duplex, transmit in interrupt mode
-	 */
-	reg = regr(LineCtl);
-	regw(LineCtl, reg&~Iface);
-	reg = regr(TestCtl);
-	regw(TestCtl, reg&~FDX);
-	regw(BufCfg, Rdy4TxiE|TxUnderruniE|RxMissiE);
-	regw(TxCfg, TxOKiE|JabberiE|Coll16iE);
-	regw(RxCfg, RxOKiE);
-	regw(RxCtl, RxOKA|IndividualA|BroadcastA);
-
-	for(i=0; i<Eaddrlen; i+=2)
-		regw(IndAddr+i, ea[i] | (ea[i+1] << 8));
-
-	/* Puma IRQ tied to INTRQ0 */
-	regw(Intr, 0);
-
-	ctlr->card.reset = cs8900reset;
-	ctlr->card.port = 0x300;
-	ctlr->card.attach = attach;
-	ctlr->card.transmit = transmit;
-	ctlr->card.intr = interrupt;
-
-	print("Ether reset...\n");uartwait();
-
-	return 0;
-}
-
--- a/os/boot/puma/flash.c
+++ /dev/null
@@ -1,226 +1,0 @@
-#include "boot.h"
-
-typedef struct Flashdev Flashdev;
-struct Flashdev {
-	uchar*	base;
-	int	size;
-	uchar*	exec;
-	char*	type;
-	char*	config;
-	int	conflen;
-};
-
-enum {
-	FLASHSEG = 256*1024,
-	CONFIGLIM = FLASHSEG,
-	BOOTOFF = FLASHSEG,
-	BOOTLEN = 3*FLASHSEG,	/* third segment might be filsys */
-	/* rest of flash is free */
-};
-
-static Flashdev flash;
-
-/*
- * configuration data is written between the bootstrap and
- * the end of region 0. the region ends with allocation descriptors
- * of the following form:
- *
- * byte order is big endian
- *
- * the last valid region found that starts with the string "#plan9.ini\n" is plan9.ini
- */
-typedef struct Flalloc Flalloc;
-struct Flalloc {
-	ulong	check;	/* checksum of data, or ~0 */
-	ulong	base;	/* base of region; ~0 if unallocated, 0 if deleted */
-	uchar	len[3];
-	uchar	tag;		/* see below */
-	uchar	sig[4];
-};
-
-enum {
-	/* tags */
-	Tdead=	0,
-	Tboot=	0x01,	/* space reserved for boot */
-	Tconf=	0x02,	/* configuration data */
-	Tnone=	0xFF,
-
-	Noval=	~0,
-};
-
-static char flashsig[] = {0xF1, 0xA5, 0x5A, 0x1F};
-static char conftag[] = "#plan9.ini\n";
-
-static ulong
-checksum(uchar* p, int n)
-{
-	ulong s;
-
-	for(s=0; --n >= 0;)
-		s += *p++;
-	return s;
-}
-
-static int
-validptr(Flalloc *ap, uchar *p)
-{
-	return p > (uchar*)end && p < (uchar*)ap;
-}
-
-static int
-flashcheck(Flalloc *ap, char **val, int *len)
-{
-	uchar *base;
-	int n;
-
-	if(ap->base == Noval || ap->base >= FLASHSEG || ap->tag == Tnone)
-		return 0;
-	base = flash.base+ap->base;
-	if(!validptr(ap, base))
-		return 0;
-	n = (((ap->len[0]<<8)|ap->len[1])<<8)|ap->len[2];
-	if(n == 0xFFFFFF)
-		n = 0;
-	if(n < 0)
-		return 0;
-	if(n > 0 && !validptr(ap, base+n-1))
-		return 0;
-	if(ap->check != Noval && checksum(base, n) != ap->check){
-		print("flash: bad checksum\n");
-		return 0;
-	}
-	*val = (char*)base;
-	*len = n;
-	return 1;
-}
-
-int
-flashinit(void)
-{
-	int f, n, len;
-	char *type, *val;
-	Flalloc *ap;
-
-	flash.base = 0;
-	flash.exec = 0;
-	flash.type = 0;
-	/* TODO - check for presence and type */
-/*
- *	if((m->iomem->memc[0].base & 1) == 0){
- *		print("flash: flash not present or not enabled\n");
- *		return 0;
- *	}
- *	f = (m->bcsr[2]>>28)&0xF;
- */
-f = 0;
-	switch(f){
-	default:
-			print("flash boot: unknown or no flash\n");
-			return 0;
-	case 4:	n=8; type = "SM732x8"; break;
-	case 5:	n=4; type = "SM732x8"; break;
-	case 6:	n=8; type = "AMD29F0x0"; break;
-	case 7:	n=4; type = "AMD29F0x0"; break;
-	case 8:	n=2; type = "AMD29F0x0"; break;
-	}
-	flash.type = type;
-	flash.size = n*1024*1024;
-	flash.base = KADDR(FLASH_BASE);
-	flash.exec = flash.base + BOOTOFF;
-	flash.config = nil;
-	flash.conflen = 0;
-
-	for(ap = (Flalloc*)(flash.base+CONFIGLIM)-1; memcmp(ap->sig, flashsig, 4) == 0; ap--){
-		if(1)
-			print("conf #%8.8lux: #%x #%6.6lux\n", ap, ap->tag, ap->base);
-		if(ap->tag == Tconf &&
-		   flashcheck(ap, &val, &len) &&
-		   len >= sizeof(conftag)-1 &&
-		   memcmp(val, conftag, sizeof(conftag)-1) == 0){
-			flash.config = val;
-			flash.conflen = len;
-			print("flash: found config %8.8lux(%d):\n%s\n", val, len, val);
-		}
-	}
-	if(flash.config){
-		print("flash config %8.8lux(%d):\n%s\n", flash.config, flash.conflen, flash.config);
-		flash.config = nil;	/* not that daring yet */
-	}else
-		print("flash: no config\n");
-	if(issqueezed(flash.exec) == E_MAGIC){
-		print("flash: squeezed StrongARM kernel installed\n");
-		return 1<<0;
-	}
-	if(GLLONG(flash.exec) == E_MAGIC){
-		print("flash: unsqueezed stringARM kernel installed\n");
-		return 1<<0;
-	}
-	flash.exec = 0;
-	print("flash: no StrongARM kernel in Flash\n");
-	return 0;
-}
-
-char*
-flashconfig(int)
-{
-	return flash.config;
-}
-
-int
-flashbootable(int)
-{
-	return flash.exec != nil && (issqueezed(flash.exec) || GLLONG(flash.exec) == E_MAGIC);
-}
-
-int
-flashboot(int)
-{
-	ulong entry, addr;
-	void (*b)(void);
-	Exec *ep;
-	Block in;
-	long n;
-	uchar *p;
-
-	if(flash.exec == 0)
-		return -1;
-	p = flash.exec;
-	if(GLLONG(p) == E_MAGIC){
-		/* unsqueezed: copy data and perhaps text, then jump to it */
-		ep = (Exec*)p;
-		entry = PADDR(GLLONG(ep->entry));
-		p += sizeof(Exec);
-		addr = entry;
-		n = GLLONG(ep->text);
-		if(addr != (ulong)p){
-			memmove((void*)addr, p, n);
-			print("text: %8.8lux <- %8.8lux [%ld]\n", addr, p, n);
-		}
-		p += n;
-		if(entry >= FLASH_BASE)
-			addr = 3*BY2PG;	/* kernel text is in Flash, data in RAM */
-		else
-			addr = PGROUND(addr+n);
-		n = GLLONG(ep->data);
-		memmove((void*)addr, p, n);
-		print("data: %8.8lux <- %8.8lux [%ld]\n", addr, p, n);
-	}else{
-		in.data = p;
-		in.rp = in.data;
-		in.lim = p+BOOTLEN;
-		in.wp = in.lim;
-		n = unsqueezef(&in, &entry);
-		if(n < 0)
-			return -1;
-	}
-	print("entry=0x%lux\n", entry);
-	uartwait();
-	/* scc2stop(); */
-	/*
-	 *  Go to new code. It's up to the program to get its PC relocated to
-	 *  the right place.
-	 */
-	b = (void (*)(void))KADDR(PADDR(entry));
-	(*b)();
-	return -1;
-}
--- a/os/boot/puma/fns.h
+++ /dev/null
@@ -1,111 +1,0 @@
-void	aamloop(int);
-Alarm*	alarm(int, void (*)(Alarm*), void*);
-void	alarminit(void);
-int	bootp(int, char*);
-void	cancel(Alarm*);
-void	checkalarms(void);
-void	clockinit(void);
-void	consinit(void);
-void	delay(int);
-uchar*	etheraddr(int);
-int	etherinit(void);
-int	etherrxpkt(int, Etherpkt*, int);
-int	ethertxpkt(int, Etherpkt*, int, int);
-int	flashboot(int);
-int	flashbootable(int);
-char*	flashconfig(int);
-int	flashinit(void);
-char*	getconf(char*);
-int	getcfields(char*, char**, int, char*);
-int	getstr(char*, char*, int, char*);
-int	hardinit(void);
-long	hardread(int, void*, long);
-long	hardseek(int, long);
-long	hardwrite(int, void*, long);
-void*	ialloc(ulong, int);
-void	idle(void);
-int	isaconfig(char*, int, ISAConf*);
-int	isgzipped(uchar*);
-int	issqueezed(uchar*);
-void	kbdinit(void);
-void	kbdchar(Queue*, int);
-void	machinit(void);
-void	meminit(void);
-void	microdelay(int);
-void	mmuinit(void);
-uchar	nvramread(int);
-void	outb(int, int);
-void	outs(int, ushort);
-void	outl(int, ulong);
-void	outsb(int, void*, int);
-void	outss(int, void*, int);
-void	outsl(int, void*, int);
-void	panic(char*, ...);
-int	optionsw(void);
-int	plan9boot(int, long (*)(int, long), long (*)(int, void*, long));
-Partition*	setflashpart(int, char*);
-Partition* sethardpart(int, char*);
-Partition* setscsipart(int, char*);
-void	setvec(int, void (*)(Ureg*, void*), void*);
-void	screeninit(void);
-void	screenputs(char*, int);
-void setr13(int, void*);
-int	splhi(void);
-int	spllo(void);
-void	splx(int);
-void	trapinit(void);
-void	uartspecial(int, int, Queue**, Queue**, void(*)(Queue*,int));
-void	uartputs(char*, int);
-void	uartwait(void);
-long	unsqueezef(Block*, ulong*);
-
-#define	GSHORT(p)	(((p)[1]<<8)|(p)[0])
-#define	GLONG(p)	((GSHORT(p+2)<<16)|GSHORT(p))
-#define	GLSHORT(p)	(((p)[0]<<8)|(p)[1])
-#define	GLLONG(p)	((GLSHORT(p)<<16)|GLSHORT(p+2))
-
-#define KADDR(a)	((void*)((ulong)(a)|KZERO))
-#define PADDR(a)	((ulong)(a)&~KZERO)
-
-
-void	mapinit(RMap*, Map*, int);
-void	mapfree(RMap*, ulong, int);
-ulong	mapalloc(RMap*, ulong, int, int);
-
-/* IBM bit field order */
-#define	IBFEXT(v,a,b) (((ulong)(v)>>(32-(b)-1)) & ~(~0L<<(((b)-(a)+1))))
-#define	IBIT(b)	((ulong)1<<(31-(b)))
-
-#define	SIBIT(n)	((ushort)1<<(15-(n)))
-
-void*	malloc(ulong);
-void	free(void*);
-
-extern Block*	iallocb(int);
-extern void	freeb(Block*);
-extern Queue*	qopen(int, int, void (*)(void*), void*);
-extern Block*	qget(Queue*);
-extern void	qbwrite(Queue*, Block*);
-extern long	qlen(Queue*);
-#define	qpass	qbwrite
-extern void	qbputc(Queue*, int);
-extern int	qbgetc(Queue*);
-
-int	sio_inb(int);
-void	sio_outb(int, int);
-void	led(int);
-
-extern void _virqcall(void);
-extern void _vfiqcall(void);
-extern void _vundcall(void);
-extern void _vsvccall(void);
-extern void _vpabcall(void);
-extern void _vdabcall(void);
-
-void flushIcache(void);
-void writeBackDC(void);
-void flushDcache(void);
-void flushIcache(void);
-void drainWBuffer(void);
-
-void pumainit(void);
--- a/os/boot/puma/hard.c
+++ /dev/null
@@ -1,773 +1,0 @@
-#include	"u.h"
-#include	"lib.h"
-#include	"mem.h"
-#include	"dat.h"
-#include	"fns.h"
-#include	"io.h"
-
-#define DPRINT if(0)print
-
-typedef	struct Drive		Drive;
-typedef	struct Ident		Ident;
-typedef	struct Controller	Controller;
-
-enum
-{
-	/* ports */
-	Pbase0=		0x1F0,	/* primary */
-	Pbase1=		0x170,	/* secondary */
-	Pbase2=		0x1E8,	/* tertiary */
-	Pbase3=		0x168,	/* quaternary */
-	Pdata=		0,	/* data port (16 bits) */
-	Perror=		1,	/* error port (read) */
-	Pprecomp=	1,	/* buffer mode port (write) */
-	Pcount=		2,	/* sector count port */
-	Psector=	3,	/* sector number port */
-	Pcyllsb=	4,	/* least significant byte cylinder # */
-	Pcylmsb=	5,	/* most significant byte cylinder # */
-	Pdh=		6,	/* drive/head port */
-	 DHmagic=	0xA0,
-	 DHslave=	0x10,
-	Pstatus=	7,	/* status port (read) */
-	 Sbusy=		 (1<<7),
-	 Sready=	 (1<<6),
-	 Sdrq=		 (1<<3),
-	 Serr=		 (1<<0),
-	Pcmd=		7,	/* cmd port (write) */
-
-	/* commands */
-	Crecal=		0x10,
-	Cread=		0x20,
-	Cwrite=		0x30,
-	Cident=		0xEC,
-	Cident2=	0xFF,	/* pseudo command for post Cident interrupt */
-	Csetbuf=	0xEF,
-
-	/* file types */
-	Qdir=		0,
-
-	Timeout=	5,		/* seconds to wait for things to complete */
-
-	NCtlr=		4,
-	NDrive=		NCtlr*2,
-};
-
-/*
- *  ident sector from drive.  this is from ANSI X3.221-1994
- */
-struct Ident
-{
-	ushort	config;		/* general configuration info */
-	ushort	cyls;		/* # of cylinders (default) */
-	ushort	reserved0;
-	ushort	heads;		/* # of heads (default) */
-	ushort	b2t;		/* unformatted bytes/track */
-	ushort	b2s;		/* unformated bytes/sector */
-	ushort	s2t;		/* sectors/track (default) */
-	ushort	reserved1[3];
-/* 10 */
-	ushort	serial[10];	/* serial number */
-	ushort	type;		/* buffer type */
-	ushort	bsize;		/* buffer size/512 */
-	ushort	ecc;		/* ecc bytes returned by read long */
-	ushort	firm[4];	/* firmware revision */
-	ushort	model[20];	/* model number */
-/* 47 */
-	ushort	s2i;		/* number of sectors/interrupt */
-	ushort	dwtf;		/* double word transfer flag */
-	ushort	capabilities;
-	ushort	reserved2;
-	ushort	piomode;
-	ushort	dmamode;
-	ushort	cvalid;		/* (cvald&1) if next 4 words are valid */
-	ushort	ccyls;		/* current # cylinders */
-	ushort	cheads;		/* current # heads */
-	ushort	cs2t;		/* current sectors/track */
-	ushort	ccap[2];	/* current capacity in sectors */
-	ushort	cs2i;		/* current number of sectors/interrupt */
-/* 60 */
-	ushort	lbasecs[2];	/* # LBA user addressable sectors */
-	ushort	dmasingle;
-	ushort	dmadouble;
-/* 64 */
-	ushort	reserved3[64];
-	ushort	vendor[32];	/* vendor specific */
-	ushort	reserved4[96];
-};
-
-/*
- *  a hard drive
- */
-struct Drive
-{
-	Controller *cp;
-	uchar	driveno;
-	uchar	dh;
-
-	Disc;
-};
-
-/*
- *  a controller for 2 drives
- */
-struct Controller
-{
-	int	pbase;		/* base port */
-	uchar	ctlrno;
-
-	/*
-	 *  current operation
-	 */
-	int	cmd;		/* current command */
-	char	*buf;		/* xfer buffer */
-	int	tcyl;		/* target cylinder */
-	int	thead;		/* target head */
-	int	tsec;		/* target sector */
-	int	tbyte;		/* target byte */
-	int	nsecs;		/* length of transfer (sectors) */
-	int	sofar;		/* bytes transferred so far */
-	int	status;
-	int	error;
-	Drive	*dp;		/* drive being accessed */
-};
-
-static int atactlrmask;
-static Controller *atactlr[NCtlr];
-static int atadrivemask;
-static Drive *atadrive[NDrive];
-static int pbase[NCtlr] = {
-	Pbase0, Pbase1, Pbase2, Pbase3,
-};
-
-static void	hardintr(Ureg*, void*);
-static long	hardxfer(Drive*, Partition*, int, ulong, long);
-static int	hardident(Drive*);
-static void	hardsetbuf(Drive*, int);
-static void	hardpart(Drive*);
-static int	hardparams(Drive*);
-static void	hardrecal(Drive*);
-static int	hardprobe(Drive*, int, int, int);
-
-static void
-atactlrprobe(int ctlrno, int irq)
-{
-	Controller *ctlr;
-	Drive *drive;
-	int driveno, port;
-
-	if(atactlrmask & (1<<ctlrno))
-		return;
-	atactlrmask |= 1<<ctlrno;
-
-	port = pbase[ctlrno];
-	outb(port+Pdh, DHmagic);
-	delay(1);
-	if((inb(port+Pdh) & 0xFF) != DHmagic){
-		DPRINT("ata%d: DHmagic not ok\n", ctlrno);
-		return;
-	}
-	DPRINT("ata%d: DHmagic ok\n", ctlrno);
-
-	atactlr[ctlrno] = ialloc(sizeof(Controller), 0);
-	ctlr = atactlr[ctlrno];
-	ctlr->pbase = port;
-	ctlr->ctlrno = ctlrno;
-	ctlr->buf = ialloc(Maxxfer, 0);
-	inb(ctlr->pbase+Pstatus);
-	setvec(irq, hardintr, ctlr);
-
-	driveno = ctlrno*2;
-	atadrive[driveno] = ialloc(sizeof(Drive), 0);
-	drive = atadrive[driveno];
-	drive->cp = ctlr;
-	drive->driveno = driveno;
-	drive->dh = DHmagic;
-
-	driveno++;
-	atadrive[driveno] = ialloc(sizeof(Drive), 0);
-	drive = atadrive[driveno];
-	drive->cp = ctlr;
-	drive->driveno = driveno;
-	drive->dh = DHmagic|DHslave;
-}
-
-static Drive*
-atadriveprobe(int driveno)
-{
-	Drive *drive;
-	int ctlrno;
-	ISAConf isa;
-
-	ctlrno = driveno/2;
-	if(atactlr[ctlrno] == 0){
-		if(atactlrmask & (1<<ctlrno))
-			return 0;
-		memset(&isa, 0, sizeof(ISAConf));
-		if(isaconfig("ata", ctlrno, &isa) == 0)
-			return 0;
-		if(ctlrno && isa.irq)
-			atactlrprobe(ctlrno, Int0vec+isa.irq);
-		if(atactlr[ctlrno] == 0)
-			return 0;
-	}
-
-	drive = atadrive[driveno];
-	if(drive->online == 0){
-		if(atadrivemask & (1<<driveno))
-			return 0;
-		atadrivemask |= 1<<driveno;
-		if(hardparams(drive))
-			return 0;
-		if(drive->lba)
-			print("hd%d: LBA %d sectors, %ud bytes\n",
-				drive->driveno, drive->sectors, drive->cap);
-		else
-			print("hd%d: CHS %d/%d/%d %d bytes\n",
-				drive->driveno, drive->cyl, drive->heads,
-				drive->sectors, drive->cap);
-		drive->online = 1;
-		hardpart(drive);
-		hardsetbuf(drive, 1);
-	}
-
-	return drive;
-}
-
-int
-hardinit(void)
-{
-	atactlrprobe(0, ATAvec0);
-	return 0xFF;
-}
-
-long
-hardseek(int driveno, long offset)
-{
-	Drive *drive;
-
-	if((drive = atadriveprobe(driveno)) == 0)
-		return -1;
-	drive->offset = offset;
-	return offset;
-}
-
-/*
- *  did an interrupt happen?
- */
-static void
-hardwait(Controller *cp)
-{
-	ulong start;
-	int x;
-
-	x = spllo();
-	for(start = m->ticks; TK2SEC(m->ticks - start) < Timeout && cp->cmd;)
-		if(cp->cmd == Cident2 && TK2SEC(m->ticks - start) >= 1)
-			break;
-	if(TK2SEC(m->ticks - start) >= Timeout){
-		DPRINT("hardwait timed out %ux\n", inb(cp->pbase+Pstatus));
-		hardintr(0, cp);
-	}
-	splx(x);
-}
-
-Partition*
-sethardpart(int driveno, char *p)
-{
-	Partition *pp;
-	Drive *dp;
-
-	if((dp = atadriveprobe(driveno)) == 0)
-		return 0;
-
-	for(pp = dp->p; pp < &dp->p[dp->npart]; pp++)
-		if(strcmp(pp->name, p) == 0){
-			dp->current = pp;
-			return pp;
-		}
-	return 0;
-}
-
-long
-hardread(int driveno, void *a, long n)
-{
-	Drive *dp;
-	long rv, i;
-	int skip;
-	uchar *aa = a;
-	Partition *pp;
-	Controller *cp;
-
-	if((dp = atadriveprobe(driveno)) == 0)
-		return 0;
-
-	pp = dp->current;
-	if(pp == 0)
-		return -1;
-	cp = dp->cp;
-
-	skip = dp->offset % dp->bytes;
-	for(rv = 0; rv < n; rv += i){
-		i = hardxfer(dp, pp, Cread, dp->offset+rv-skip, n-rv+skip);
-		if(i == 0)
-			break;
-		if(i < 0)
-			return -1;
-		i -= skip;
-		if(i > n - rv)
-			i = n - rv;
-		memmove(aa+rv, cp->buf + skip, i);
-		skip = 0;
-	}
-	dp->offset += rv;
-
-	return rv;
-}
-
-/*
- *  wait for the controller to be ready to accept a command
- */
-static int
-cmdreadywait(Drive *drive)
-{
-	ulong end;
-	uchar dh, status;
-	Controller *ctlr;
-
-	ctlr = drive->cp;
-	end = m->ticks+MS2TK(10)+1;
-	dh = (inb(ctlr->pbase+Pdh) & DHslave)^(drive->dh & DHslave);
-	
-	status = 0;
-	while(m->ticks < end){
-		status = inb(ctlr->pbase+Pstatus);
-		if(status & Sbusy)
-			continue;
-		if(dh){
-			outb(ctlr->pbase+Pdh, drive->dh);
-			dh = 0;
-			continue;
-		}
-		if(status & Sready)
-			return 0;
-	}
-	USED(status);
-
-	DPRINT("hd%d: cmdreadywait failed %uX\n", drive->driveno, status);
-	outb(ctlr->pbase+Pdh, DHmagic);
-	return -1;
-}
-
-/*
- *  transfer a number of sectors.  hardintr will perform all the iterative
- *  parts.
- */
-static long
-hardxfer(Drive *dp, Partition *pp, int cmd, ulong start, long len)
-{
-	Controller *cp;
-	long lsec;
-
-	if(dp->online == 0){
-		DPRINT("disk not on line\n");
-		return -1;
-	}
-
-	if(cmd == Cwrite)
-		return -1;
-
-	/*
-	 *  cut transfer size down to disk buffer size
-	 */
-	start = start / dp->bytes;
-	if(len > Maxxfer)
-		len = Maxxfer;
-	len = (len + dp->bytes - 1) / dp->bytes;
-
-	/*
-	 *  calculate physical address
-	 */
-	cp = dp->cp;
-	lsec = start + pp->start;
-	if(lsec >= pp->end){
-		DPRINT("read past end of partition\n");
-		return 0;
-	}
-	if(dp->lba){
-		cp->tsec = lsec & 0xff;
-		cp->tcyl = (lsec>>8) & 0xffff;
-		cp->thead = (lsec>>24) & 0xf;
-	} else {
-		cp->tcyl = lsec/(dp->sectors*dp->heads);
-		cp->tsec = (lsec % dp->sectors) + 1;
-		cp->thead = (lsec/dp->sectors) % dp->heads;
-	}
-
-	/*
-	 *  can't xfer past end of disk
-	 */
-	if(lsec+len > pp->end)
-		len = pp->end - lsec;
-	cp->nsecs = len;
-
-	if(cmdreadywait(dp) < 0)
-		return -1;
-
-	/*
-	 *  start the transfer
-	 */
-	cp->cmd = cmd;
-	cp->dp = dp;
-	cp->sofar = 0;
-	cp->status = 0;
-	DPRINT("xfer:\ttcyl %d, tsec %d, thead %d\n", cp->tcyl, cp->tsec, cp->thead);
-	DPRINT("\tnsecs %d, sofar %d\n", cp->nsecs, cp->sofar);
-	outb(cp->pbase+Pcount, cp->nsecs);
-	outb(cp->pbase+Psector, cp->tsec);
-	outb(cp->pbase+Pdh, dp->dh | (dp->lba<<6) | cp->thead);
-	outb(cp->pbase+Pcyllsb, cp->tcyl);
-	outb(cp->pbase+Pcylmsb, cp->tcyl>>8);
-	outb(cp->pbase+Pcmd, cmd);
-
-	hardwait(cp);
-
-	if(cp->status & Serr){
-		DPRINT("hd%d err: status %lux, err %lux\n",
-			dp->driveno, cp->status, cp->error);
-		DPRINT("\ttcyl %d, tsec %d, thead %d\n",
-			cp->tcyl, cp->tsec, cp->thead);
-		DPRINT("\tnsecs %d, sofar %d\n", cp->nsecs, cp->sofar);
-		return -1;
-	}
-
-	return cp->nsecs*dp->bytes;
-}
-
-/*
- *  set read ahead mode (1 == on, 0 == off)
- */
-static void
-hardsetbuf(Drive *dp, int on)
-{
-	Controller *cp = dp->cp;
-
-	if(cmdreadywait(dp) < 0)
-		return;
-
-	cp->cmd = Csetbuf;
-	/* BUG: precomp varies by hard drive...this is safari-specific? */
-	outb(cp->pbase+Pprecomp, on ? 0xAA : 0x55);
-	outb(cp->pbase+Pdh, dp->dh);
-	outb(cp->pbase+Pcmd, Csetbuf);
-
-	hardwait(cp);
-}
-
-static int
-isatapi(Drive *drive)
-{
-	Controller *cp;
-
-	cp = drive->cp;
-	outb(cp->pbase+Pdh, drive->dh);
-	microdelay(1);
-	if(inb(cp->pbase+Pstatus))
-		return 0;
-	if(inb(cp->pbase+Pcylmsb) != 0xEB || inb(cp->pbase+Pcyllsb) != 0x14)
-		return 0;
-	return 1;
-}
-
-/*
- *  get parameters from the drive
- */
-static int
-hardident(Drive *dp)
-{
-	Controller *cp;
-	Ident *ip;
-
-	dp->bytes = 512;
-	cp = dp->cp;
-
-	if(isatapi(dp) || cmdreadywait(dp) < 0)
-		return -1;
-
-	cp->nsecs = 1;
-	cp->sofar = 0;
-	cp->cmd = Cident;
-	cp->dp = dp;
-	outb(cp->pbase+Pdh, dp->dh);
-	outb(cp->pbase+Pcmd, Cident);
-
-	hardwait(cp);
-
-	if(cp->status & Serr)
-		return -1;
-	
-	hardwait(cp);
-
-	ip = (Ident*)cp->buf;
-	DPRINT("LBA%d: %lud\n",
-		ip->capabilities & (1<<9) == 1, (ip->lbasecs[0]) | (ip->lbasecs[1]<<16));
-	DPRINT("DEF: %ud/%ud/%ud\nMAP %ud/%ud/%ud\n",
-		ip->cyls, ip->heads, ip->s2t,
-		ip->ccyls, ip->cheads, ip->cs2t);
-	if(ip->capabilities & (1<<9)){
-		dp->lba = 1;
-		dp->sectors = (ip->lbasecs[0]) | (ip->lbasecs[1]<<16);
-		dp->cap = dp->bytes * dp->sectors;
-/*print("\nata%d model %s with %d lba sectors\n", dp->driveno, id, dp->sectors);/**/
-	} else {
-		dp->lba = 0;
-
-		/* use default (unformatted) settings */
-		dp->cyl = ip->cyls;
-		dp->heads = ip->heads;
-		dp->sectors = ip->s2t;
-/*print("\nata%d model %s with default %d cyl %d head %d sec\n", dp->driveno,
-			id, dp->cyl, dp->heads, dp->sectors);/**/
-
-		if(ip->cvalid&(1<<0)){
-			/* use current settings */
-			dp->cyl = ip->ccyls;
-			dp->heads = ip->cheads;
-			dp->sectors = ip->cs2t;
-/*print("\tchanged to %d cyl %d head %d sec\n", dp->cyl, dp->heads, dp->sectors);/**/
-		}
-		dp->cap = dp->bytes * dp->cyl * dp->heads * dp->sectors;
-	}
-
-	return 0;
-}
-
-/*
- *  probe the given sector to see if it exists
- */
-static int
-hardprobe(Drive *dp, int cyl, int sec, int head)
-{
-	Controller *cp;
-
-	cp = dp->cp;
-	if(cmdreadywait(dp) < 0)
-		return -1;
-
-	/*
-	 *  start the transfer
-	 */
-	cp->cmd = Cread;
-	cp->dp = dp;
-	cp->sofar = 0;
-	cp->nsecs = 1;
-	cp->status = 0;
-	outb(cp->pbase+Pcount, 1);
-	outb(cp->pbase+Psector, sec+1);
-	outb(cp->pbase+Pdh, dp->dh | (dp->lba<<6) | head);
-	outb(cp->pbase+Pcyllsb, cyl);
-	outb(cp->pbase+Pcylmsb, cyl>>8);
-	outb(cp->pbase+Pcmd, Cread);
-
-	hardwait(cp);
-
-	if(cp->status & Serr)
-		return -1;
-
-	return 0;
-}
-
-/*
- *  figure out the drive parameters
- */
-static int
-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;
-	if(hardident(dp) < 0)
-		return -1;
-	if(dp->lba){
-		i = dp->sectors - 1;
-		if(hardprobe(dp, (i>>8)&0xffff, (i&0xff)-1, (i>>24)&0xf) == 0)
-			return 0;
-	} else {
-		if(hardprobe(dp, dp->cyl-1, dp->sectors-1, dp->heads-1) == 0)
-			return 0;
-	}
-
-	DPRINT("hardparam: cyl %d sectors %d heads %d\n", dp->cyl, dp->sectors, dp->heads);
-	/*
-	 *  the drive lied, determine parameters by seeing which ones
-	 *  work to read sectors.
-	 */
-	dp->lba = 0;
-	for(i = 0; i < 16; i++)
-		if(hardprobe(dp, 0, 0, i) < 0)
-			break;
-	dp->heads = i;
-	for(i = 0; i < 64; 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;
-
-	if(dp->cyl == 0 || dp->heads == 0 || dp->sectors == 0 || dp->cap == 0)
-		return -1;
-
-	return 0;
-}
-
-/*
- *  read partition table.  The partition table is just ascii strings.
- */
-#define MAGIC "plan9 partitions"
-static void
-hardpart(Drive *dp)
-{
-	Partition *pp;
-	Controller *cp;
-	char *field[3], *line[Npart+1], *p, buf[NAMELEN];
-	ulong n;
-	int i;
-
-	cp = dp->cp;
-
-	/*
-	 *  we always have a partition for the whole disk
-	 *  and one for the partition table
-	 */
-	pp = &dp->p[0];
-	strcpy(pp->name, "disk");
-	pp->start = 0;
-	pp->end = dp->cap / dp->bytes;
-	pp++;
-	strcpy(pp->name, "partition");
-	pp->start = dp->p[0].end - 1;
-	pp->end = dp->p[0].end;
-	dp->npart = 2;
-
-	/*
-	 * Check if the partitions are described in plan9.ini.
-	 * If not, read the disc.
-	 */
-	sprint(buf, "hd%dpartition", dp->driveno);
-	if((p = getconf(buf)) == 0){	
-		/*
-		 *  read last sector from disk, null terminate.  This used
-		 *  to be the sector we used for the partition tables.
-		 *  However, this sector is special on some PC's so we've
-		 *  started to use the second last sector as the partition
-		 *  table instead.  To avoid reconfiguring all our old systems
-		 *  we first look to see if there is a valid partition
-		 *  table in the last sector.  If so, we use it.  Otherwise
-		 *  we switch to the second last.
-		 */
-		hardxfer(dp, pp, Cread, 0, dp->bytes);
-		cp->buf[dp->bytes-1] = 0;
-		n = getcfields(cp->buf, line, Npart+1, "\n");
-		if(n == 0 || strncmp(line[0], MAGIC, sizeof(MAGIC)-1)){
-			dp->p[0].end--;
-			dp->p[1].start--;
-			dp->p[1].end--;
-			hardxfer(dp, pp, Cread, 0, dp->bytes);
-			cp->buf[dp->bytes-1] = 0;
-			n = getcfields(cp->buf, line, Npart+1, "\n");
-		}
-	}
-	else{
-		strcpy(cp->buf, p);
-		n = getcfields(cp->buf, line, Npart+1, "\n");
-	}
-
-	/*
-	 *  parse partition table.
-	 */
-	if(n && strncmp(line[0], MAGIC, sizeof(MAGIC)-1) == 0){
-		for(i = 1; i < n; i++){
-			pp++;
-			if(getcfields(line[i], field, 3, " ") != 3)
-				break;
-			strncpy(pp->name, field[0], NAMELEN);
-			pp->start = strtoul(field[1], 0, 0);
-			pp->end = strtoul(field[2], 0, 0);
-			if(pp->start > pp->end || pp->start >= dp->p[0].end)
-				break;
-			dp->npart++;
-		}
-	}
-	return;
-}
-
-/*
- *  we get an interrupt for every sector transferred
- */
-static void
-hardintr(Ureg*, void *arg)
-{
-	Controller *cp;
-	Drive *dp;
-	long loop;
-
-	cp = arg;
-	dp = cp->dp;
-
-	loop = 0;
-	while((cp->status = inb(cp->pbase+Pstatus)) & Sbusy)
-		if(++loop > 100000){
-			print("hardintr 0x%lux\n", cp->status);
-			break;
-		}
-	switch(cp->cmd){
-	case Cread:
-	case Cident:
-		if(cp->status & Serr){
-			cp->cmd = 0;
-			cp->error = inb(cp->pbase+Perror);
-			return;
-		}
-		loop = 0;
-		while((inb(cp->pbase+Pstatus) & Sdrq) == 0)
-			if(++loop > 100000){
-				print("hardintr 2 cmd %ux status %ux",
-					cp->cmd, inb(cp->pbase+Pstatus));
-				cp->cmd = 0;
-				return;
-			}
-		inss(cp->pbase+Pdata, &cp->buf[cp->sofar*dp->bytes],
-			dp->bytes/2);
-		cp->sofar++;
-		if(cp->sofar >= cp->nsecs){
-			if(cp->cmd == Cident && (cp->status & Sready) == 0)
-				cp->cmd = Cident2; /* sometimes we get a second intr */
-			else
-				cp->cmd = 0;
-			inb(cp->pbase+Pstatus);
-		}
-		break;
-	case Csetbuf:
-	case Cident2:
-		cp->cmd = 0;
-		break;
-	default:
-		cp->cmd = 0;
-		break;
-	}
-}
--- a/os/boot/puma/io.h
+++ /dev/null
@@ -1,3 +1,0 @@
-#define 	inb(port)			sio_inb(port)
-#define 	outb(port, data)	sio_outb(port, data)
-
--- a/os/boot/puma/ip.h
+++ /dev/null
@@ -1,98 +1,0 @@
-typedef struct Udphdr Udphdr;
-struct Udphdr
-{
-	uchar	d[6];		/* Ethernet destination */
-	uchar	s[6];		/* Ethernet source */
-	uchar	type[2];	/* Ethernet packet type */
-
-	uchar	vihl;		/* Version and header length */
-	uchar	tos;		/* Type of service */
-	uchar	length[2];	/* packet length */
-	uchar	id[2];		/* Identification */
-	uchar	frag[2];	/* Fragment information */
-
-	/* Udp pseudo ip really starts here */
-	uchar	ttl;	
-	uchar	udpproto;	/* Protocol */
-	uchar	udpplen[2];	/* Header plus data length */
-	uchar	udpsrc[4];	/* Ip source */
-	uchar	udpdst[4];	/* Ip destination */
-	uchar	udpsport[2];	/* Source port */
-	uchar	udpdport[2];	/* Destination port */
-	uchar	udplen[2];	/* data length */
-	uchar	udpcksum[2];	/* Checksum */
-};
-
-typedef struct Etherhdr Etherhdr;
-struct Etherhdr
-{
-	uchar	d[6];
-	uchar	s[6];
-	uchar	type[2];
-
-	/* Now we have the ip fields */
-	uchar	vihl;		/* Version and header length */
-	uchar	tos;		/* Type of service */
-	uchar	length[2];	/* packet length */
-	uchar	id[2];		/* Identification */
-	uchar	frag[2];	/* Fragment information */
-	uchar	ttl;		/* Time to live */
-	uchar	proto;		/* Protocol */
-	uchar	cksum[2];	/* Header checksum */
-	uchar	src[4];		/* Ip source */
-	uchar	dst[4];		/* Ip destination */
-};
-
-enum
-{
-	IP_VER		= 0x40,
-	IP_HLEN		= 0x05,			
- 	UDP_EHSIZE	= 22,
-	UDP_PHDRSIZE	= 12,
-	UDP_HDRSIZE	= 20,
-	ETHER_HDR	= 14,
-	IP_UDPPROTO	= 17,
-	ET_IP		= 0x800,
-	Bcastip		= 0xffffffff,
-	BPportsrc	= 68,
-	BPportdst	= 67,
-	TFTPport	= 69,
-	Timeout		= 5000,	/* milliseconds */
-	Bootrequest 	= 1,
-	Bootreply   	= 2,
-	Tftp_READ	= 1,
-	Tftp_WRITE	= 2,
-	Tftp_DATA	= 3,
-	Tftp_ACK	= 4,
-	Tftp_ERROR	= 5,
-	Segsize		= 512,
-	TFTPSZ		= Segsize+10,
-};
-
-typedef struct Bootp Bootp;
-struct Bootp
-{
-	uchar	op;		/* opcode */
-	uchar	htype;		/* hardware type */
-	uchar	hlen;		/* hardware address len */
-	uchar	hops;		/* hops */
-	uchar	xid[4];		/* a random number */
-	uchar	secs[2];	/* elapsed snce client started booting */
-	uchar	pad[2];
-	uchar	ciaddr[4];	/* client IP address (client tells server) */
-	uchar	yiaddr[4];	/* client IP address (server tells client) */
-	uchar	siaddr[4];	/* server IP address */
-	uchar	giaddr[4];	/* gateway IP address */
-	uchar	chaddr[16];	/* client hardware address */
-	char	sname[64];	/* server host name (optional) */
-	char	file[128];	/* boot file name */
-	char	vend[128];	/* vendor-specific goo */
-};
-
-typedef struct Netaddr Netaddr;
-struct Netaddr
-{
-	ulong	ip;
-	ushort	port;
-	char	ea[Eaddrlen];
-};
--- a/os/boot/puma/kbd.c
+++ /dev/null
@@ -1,482 +1,0 @@
-#include "boot.h"
-
-
-enum {
-	Data=		0x60,	/* data port */
-
-	Status=		0x64,	/* status port */
-	 Inready=	0x01,	/*  input character ready */
-	 Outbusy=	0x02,	/*  output busy */
-	 Sysflag=	0x04,	/*  system flag */
-	 Cmddata=	0x08,	/*  cmd==0, data==1 */
-	 Inhibit=	0x10,	/*  keyboard/mouse inhibited */
-	 Minready=	0x20,	/*  mouse character ready */
-	 Rtimeout=	0x40,	/*  general timeout */
-	 Parity=	0x80,
-
-	Cmd=		0x64,	/* command port (write only) */
- 
-	Spec=	0x80,
-
-	PF=	Spec|0x20,	/* num pad function key */
-	View=	Spec|0x00,	/* view (shift window up) */
-	KF=	Spec|0x40,	/* function key */
-	Shift=	Spec|0x60,
-	Break=	Spec|0x61,
-	Ctrl=	Spec|0x62,
-	Latin=	Spec|0x63,
-	Caps=	Spec|0x64,
-	Num=	Spec|0x65,
-	No=	Spec|0x7F,	/* no mapping */
-
-	Home=	KF|13,
-	Up=	KF|14,
-	Pgup=	KF|15,
-	Print=	KF|16,
-	Left=	View,
-	Right=	View,
-	End=	'\r',
-	Down=	View,
-	Pgdown=	View,
-	Ins=	KF|20,
-	Del=	0x7F,
-};
-
-uchar kbtab[] = 
-{
-[0x00]	No,	0x1b,	'1',	'2',	'3',	'4',	'5',	'6',
-[0x08]	'7',	'8',	'9',	'0',	'-',	'=',	'\b',	'\t',
-[0x10]	'q',	'w',	'e',	'r',	't',	'y',	'u',	'i',
-[0x18]	'o',	'p',	'[',	']',	'\n',	Ctrl,	'a',	's',
-[0x20]	'd',	'f',	'g',	'h',	'j',	'k',	'l',	';',
-[0x28]	'\'',	'`',	Shift,	'\\',	'z',	'x',	'c',	'v',
-[0x30]	'b',	'n',	'm',	',',	'.',	'/',	Shift,	No,
-[0x38]	Latin,	' ',	Caps,	KF|1,	KF|2,	KF|3,	KF|4,	KF|5,
-[0x40]	KF|6,	KF|7,	KF|8,	KF|9,	KF|10,	Num,	KF|12,	Home,
-[0x48]	No,	No,	No,	No,	No,	No,	No,	No,
-[0x50]	No,	No,	No,	No,	No,	No,	No,	KF|11,
-[0x58]	KF|12,	No,	No,	No,	No,	No,	No,	No,
-};
-
-uchar kbtabshift[] =
-{
-[0x00]	No,	0x1b,	'!',	'@',	'#',	'$',	'%',	'^',
-[0x08]	'&',	'*',	'(',	')',	'_',	'+',	'\b',	'\t',
-[0x10]	'Q',	'W',	'E',	'R',	'T',	'Y',	'U',	'I',
-[0x18]	'O',	'P',	'{',	'}',	'\n',	Ctrl,	'A',	'S',
-[0x20]	'D',	'F',	'G',	'H',	'J',	'K',	'L',	':',
-[0x28]	'"',	'~',	Shift,	'|',	'Z',	'X',	'C',	'V',
-[0x30]	'B',	'N',	'M',	'<',	'>',	'?',	Shift,	No,
-[0x38]	Latin,	' ',	Caps,	KF|1,	KF|2,	KF|3,	KF|4,	KF|5,
-[0x40]	KF|6,	KF|7,	KF|8,	KF|9,	KF|10,	Num,	KF|12,	Home,
-[0x48]	No,	No,	No,	No,	No,	No,	No,	No,
-[0x50]	No,	No,	No,	No,	No,	No,	No,	KF|11,
-[0x58]	KF|12,	No,	No,	No,	No,	No,	No,	No,
-};
-
-uchar kbtabesc1[] =
-{
-[0x00]	No,	No,	No,	No,	No,	No,	No,	No,
-[0x08]	No,	No,	No,	No,	No,	No,	No,	No,
-[0x10]	No,	No,	No,	No,	No,	No,	No,	No,
-[0x18]	No,	No,	No,	No,	No,	Ctrl,	No,	No,
-[0x20]	No,	No,	No,	No,	No,	No,	No,	No,
-[0x28]	No,	No,	No,	No,	No,	No,	No,	No,
-[0x30]	No,	No,	No,	No,	No,	No,	No,	Print,
-[0x38]	Latin,	No,	No,	No,	No,	No,	No,	No,
-[0x40]	No,	No,	No,	No,	No,	No,	Break,	Home,
-[0x48]	Up,	Pgup,	No,	Down,	No,	Right,	No,	End,
-[0x50]	Left,	Pgdown,	Ins,	Del,	No,	No,	No,	No,
-[0x58]	No,	No,	No,	No,	No,	No,	No,	No,
-};
-
-struct latin
-{
-	uchar	l;
-	char	c[2];
-}latintab[] = {
-	L'¡',	"!!",	/* spanish initial ! */
-	L'¢',	"c|",	/* cent */
-	L'¢',	"c$",	/* cent */
-	L'£',	"l$",	/* pound sterling */
-	L'¤',	"g$",	/* general currency */
-	L'¥',	"y$",	/* yen */
-	L'¥',	"j$",	/* yen */
-	L'¦',	"||",	/* broken vertical bar */
-	L'§',	"SS",	/* section symbol */
-	L'¨',	"\"\"",	/* dieresis */
-	L'©',	"cr",	/* copyright */
-	L'©',	"cO",	/* copyright */
-	L'ª',	"sa",	/* super a, feminine ordinal */
-	L'«',	"<<",	/* left angle quotation */
-	L'¬',	"no",	/* not sign, hooked overbar */
-	L'­',	"--",	/* soft hyphen */
-	L'®',	"rg",	/* registered trademark */
-	L'¯',	"__",	/* macron */
-	L'°',	"s0",	/* degree (sup o) */
-	L'±',	"+-",	/* plus-minus */
-	L'²',	"s2",	/* sup 2 */
-	L'³',	"s3",	/* sup 3 */
-	L'´',	"''",	/* grave accent */
-	L'µ',	"mu",	/* mu */
-	L'¶',	"pg",	/* paragraph (pilcrow) */
-	L'·',	"..",	/* centered . */
-	L'¸',	",,",	/* cedilla */
-	L'¹',	"s1",	/* sup 1 */
-	L'º',	"so",	/* sup o */
-	L'»',	">>",	/* right angle quotation */
-	L'¼',	"14",	/* 1/4 */
-	L'½',	"12",	/* 1/2 */
-	L'¾',	"34",	/* 3/4 */
-	L'¿',	"??",	/* spanish initial ? */
-	L'À',	"A`",	/* A grave */
-	L'Á',	"A'",	/* A acute */
-	L'Â',	"A^",	/* A circumflex */
-	L'Ã',	"A~",	/* A tilde */
-	L'Ä',	"A\"",	/* A dieresis */
-	L'Ä',	"A:",	/* A dieresis */
-	L'Å',	"Ao",	/* A circle */
-	L'Å',	"AO",	/* A circle */
-	L'Æ',	"Ae",	/* AE ligature */
-	L'Æ',	"AE",	/* AE ligature */
-	L'Ç',	"C,",	/* C cedilla */
-	L'È',	"E`",	/* E grave */
-	L'É',	"E'",	/* E acute */
-	L'Ê',	"E^",	/* E circumflex */
-	L'Ë',	"E\"",	/* E dieresis */
-	L'Ë',	"E:",	/* E dieresis */
-	L'Ì',	"I`",	/* I grave */
-	L'Í',	"I'",	/* I acute */
-	L'Î',	"I^",	/* I circumflex */
-	L'Ï',	"I\"",	/* I dieresis */
-	L'Ï',	"I:",	/* I dieresis */
-	L'Ð',	"D-",	/* Eth */
-	L'Ñ',	"N~",	/* N tilde */
-	L'Ò',	"O`",	/* O grave */
-	L'Ó',	"O'",	/* O acute */
-	L'Ô',	"O^",	/* O circumflex */
-	L'Õ',	"O~",	/* O tilde */
-	L'Ö',	"O\"",	/* O dieresis */
-	L'Ö',	"O:",	/* O dieresis */
-	L'Ö',	"OE",	/* O dieresis */
-	L'Ö',	"Oe",	/* O dieresis */
-	L'×',	"xx",	/* times sign */
-	L'Ø',	"O/",	/* O slash */
-	L'Ù',	"U`",	/* U grave */
-	L'Ú',	"U'",	/* U acute */
-	L'Û',	"U^",	/* U circumflex */
-	L'Ü',	"U\"",	/* U dieresis */
-	L'Ü',	"U:",	/* U dieresis */
-	L'Ü',	"UE",	/* U dieresis */
-	L'Ü',	"Ue",	/* U dieresis */
-	L'Ý',	"Y'",	/* Y acute */
-	L'Þ',	"P|",	/* Thorn */
-	L'Þ',	"Th",	/* Thorn */
-	L'Þ',	"TH",	/* Thorn */
-	L'ß',	"ss",	/* sharp s */
-	L'à',	"a`",	/* a grave */
-	L'á',	"a'",	/* a acute */
-	L'â',	"a^",	/* a circumflex */
-	L'ã',	"a~",	/* a tilde */
-	L'ä',	"a\"",	/* a dieresis */
-	L'ä',	"a:",	/* a dieresis */
-	L'å',	"ao",	/* a circle */
-	L'æ',	"ae",	/* ae ligature */
-	L'ç',	"c,",	/* c cedilla */
-	L'è',	"e`",	/* e grave */
-	L'é',	"e'",	/* e acute */
-	L'ê',	"e^",	/* e circumflex */
-	L'ë',	"e\"",	/* e dieresis */
-	L'ë',	"e:",	/* e dieresis */
-	L'ì',	"i`",	/* i grave */
-	L'í',	"i'",	/* i acute */
-	L'î',	"i^",	/* i circumflex */
-	L'ï',	"i\"",	/* i dieresis */
-	L'ï',	"i:",	/* i dieresis */
-	L'ð',	"d-",	/* eth */
-	L'ñ',	"n~",	/* n tilde */
-	L'ò',	"o`",	/* o grave */
-	L'ó',	"o'",	/* o acute */
-	L'ô',	"o^",	/* o circumflex */
-	L'õ',	"o~",	/* o tilde */
-	L'ö',	"o\"",	/* o dieresis */
-	L'ö',	"o:",	/* o dieresis */
-	L'ö',	"oe",	/* o dieresis */
-	L'÷',	"-:",	/* divide sign */
-	L'ø',	"o/",	/* o slash */
-	L'ù',	"u`",	/* u grave */
-	L'ú',	"u'",	/* u acute */
-	L'û',	"u^",	/* u circumflex */
-	L'ü',	"u\"",	/* u dieresis */
-	L'ü',	"u:",	/* u dieresis */
-	L'ü',	"ue",	/* u dieresis */
-	L'ý',	"y'",	/* y acute */
-	L'þ',	"th",	/* thorn */
-	L'þ',	"p|",	/* thorn */
-	L'ÿ',	"y\"",	/* y dieresis */
-	L'ÿ',	"y:",	/* y dieresis */
-	0,	0,
-};
-
-enum
-{
-	/* controller command byte */
-	Cscs1=		(1<<6),		/* scan code set 1 */
-	Cmousedis=	(1<<5),		/* mouse disable */
-	Ckbddis=	(1<<4),		/* kbd disable */
-	Csf=		(1<<2),		/* system flag */
-	Cmouseint=	(1<<1),		/* mouse interrupt enable */
-	Ckbdint=	(1<<0),		/* kbd interrupt enable */
-};
-
-static uchar ccc;
-
-int
-latin1(int k1, int k2)
-{
-	struct latin *l;
-
-	for(l=latintab; l->l; l++)
-		if(k1==l->c[0] && k2==l->c[1])
-			return l->l;
-	return 0;
-}
-
-/*
- *  wait for output no longer busy
- */
-static int
-outready(void)
-{
-	int tries;
-
-	for(tries = 0; (inb(Status) & Outbusy); tries++){
-		if(tries > 500)
-			return -1;
-		delay(2);
-	}
-	return 0;
-}
-
-/*
- *  wait for input
- */
-static int
-inready(void)
-{
-	int tries;
-
-	for(tries = 0; !(inb(Status) & Inready); tries++){
-		if(tries > 500)
-			return -1;
-		delay(2);
-	}
-	return 0;
-}
-
-/*
- *  ask 8042 to enable the use of address bit 20
- */
-void
-i8042a20(void)
-{
-	outready();
-	outb(Cmd, 0xD1);
-	outready();
-	outb(Data, 0xDF);
-	outready();
-}
-
-/*
- *  ask 8042 to reset the machine
- */
-void
-i8042reset(void)
-{
-	ushort *s = (ushort*)(KZERO|0x472);
-	int i, x;
-
-	*s = 0x1234;		/* BIOS warm-boot flag */
-
-	outready();
-	outb(Cmd, 0xFE);	/* pulse reset line (means resend on AT&T machines) */
-	outready();
-
-	/*
-	 *  Pulse it by hand (old somewhat reliable)
-	 */
-	x = 0xDF;
-	for(i = 0; i < 5; i++){
-		x ^= 1;
-		outready();
-		outb(Cmd, 0xD1);
-		outready();
-		outb(Data, x);	/* toggle reset */
-		delay(100);
-	}
-}
-
-/*
- *  keyboard interrupt
- */
-int
-kbdintr0(void)
-{
-	int s, c;
-	static int esc1, esc2;
-	static int shift;
-	static int caps;
-	static int ctl;
-	static int num;
-	static int lstate, k1, k2;
-	int keyup;
-
-	/*
-	 *  get status
-	 */
-	s = inb(Status);
-	if(!(s&Inready))
-		return -1;
-
-	/*
-	 *  get the character
-	 */
-	c = inb(Data);
-
-	/*
-	 *  e0's is the first of a 2 character sequence
-	 */
-	if(c == 0xe0){
-		esc1 = 1;
-		return 0;
-	} else if(c == 0xe1){
-		esc2 = 2;
-		return 0;
-	}
-
-	keyup = c&0x80;
-	c &= 0x7f;
-	if(c > sizeof kbtab){
-		print("unknown key %ux\n", c|keyup);
-		kbdchar(0, k1);
-		return 0;
-	}
-
-	if(esc1){
-		c = kbtabesc1[c];
-		esc1 = 0;
-		kbdchar(0, c);
-		return 0;
-	} else if(esc2){
-		esc2--;
-		return 0;
-	} else if(shift)
-		c = kbtabshift[c];
-	else
-		c = kbtab[c];
-
-	if(caps && c<='z' && c>='a')
-		c += 'A' - 'a';
-
-	/*
-	 *  keyup only important for shifts
-	 */
-	if(keyup){
-		switch(c){
-		case Shift:
-			shift = 0;
-			break;
-		case Ctrl:
-			ctl = 0;
-			break;
-		}
-		return 0;
-	}
-
-	/*
- 	 *  normal character
-	 */
-	if(!(c & Spec)){
-		if(ctl)
-			c &= 0x1f;
-		switch(lstate){
-		case 1:
-			k1 = c;
-			lstate = 2;
-			return 0;
-		case 2:
-			k2 = c;
-			lstate = 0;
-			c = latin1(k1, k2);
-			if(c == 0){
-				kbdchar(0, k1);
-				c = k2;
-			}
-			/* fall through */
-		default:
-			break;
-		}
-	} else {
-		switch(c){
-		case Caps:
-			caps ^= 1;
-			return 0;
-		case Num:
-			num ^= 1;
-			return 0;
-		case Shift:
-			shift = 1;
-			return 0;
-		case Latin:
-			lstate = 1;
-			return 0;
-		case Ctrl:
-			ctl = 1;
-			return 0;
-		}
-	}
-	kbdchar(0, c);
-	return 0;
-}
-
-static void
-kbdintr(Ureg*, void*)
-{
-	while(kbdintr0() == 0)
-		;
-}
-
-static char *initfailed = "kbd init failed\n";
-
-void
-kbdinit(void)
-{
-	int c;
-
-	/* wait for a quiescent controller */
-	while((c = inb(Status)) & (Outbusy | Inready))
-		if(c & Inready)
-			inb(Data);
-
-	/* get current controller command byte */
-	outb(Cmd, 0x20);
-	if(inready() < 0){
-		print("kbdinit: can't read ccc\n");
-		ccc = 0;
-	} else
-		ccc = inb(Data);
-
-	/* enable kbd xfers and interrupts */
-	ccc &= ~Ckbddis;
-	ccc |= Csf | Ckbdint | Cscs1;
-	if(outready() < 0)
-		print(initfailed);
-	outb(Cmd, 0x60);
-	if(outready() < 0)
-		print(initfailed);
-	outb(Data, ccc);
-	if(outready() < 0)
-		print(initfailed);
-
-	setvec(V_KEYBOARD, kbdintr, 0);
-}
--- a/os/boot/puma/l.s
+++ /dev/null
@@ -1,427 +1,0 @@
-/*
- *	File: 		l.s
- *	Purpose:
- *  	Puma Board StrongARM 110 Architecture Specific Assembly
- *	
- */
-
-#include "mem.h"
-#include "armv4.h"
-#include "puma.h"
-
-#define	DRAMWAIT	100000		/* 3.125μsec per iteration */
-#define	TL750R(r)	(TL750_BASE+(r)*4)
-
-#define	BOOTBASE	0x00200000
-
-TEXT		_main(SB),1,$-4
-	MOVW	R15, R7	/* save PC on entry */
-
-/*
- * initialise DRAM controller on the TL750 (SDRAM mode)
- */
-	MOVW	$DRAMWAIT, R0	/* wait 312 ms after reset before touching DRAM */
-dram1:
-	SUB.S	$1, R0
-	BNE	dram1
-
-	MOVW	$TL750R(0x103), R0	/* DMC_DELAY */
-	MOVW	$0x03333333, R1	/* DRAM timing parameters */
-	MOVW	R1, (R0)
-
-	MOVW	$TL750R(0x101), R0	/* DMC_SDRAM */
-	MOVW	$0x03133011, R1	/* SDRAM parameters for Puma */
-	MOVW	R1, (R0)
-
-	MOVW	$DRAMWAIT, R0	/* wait 312 ms for initialisation */
-dram2:
-	SUB.S	$1, R0
-	BNE	dram2
-
-	MOVW		$setR12(SB),R12
-
-/*
- * copy bootstrap to final location in DRAM
- */
-	MOVW	R7, baddr(SB)
-	MOVW	$(BOOTBASE+8), R0
-	CMP	R0, R7
-	BEQ	inplace
-	MOVW	$((128*1024)/4), R6
-copyboot:
-	MOVW.P	4(R7), R5
-	MOVW.P	R5, 4(R0)
-	SUB.S	$1, R6
-	BNE	copyboot
-	MOVW	$bootrel(SB), R7
-	MOVW	R7, R15
-
-TEXT	bootrel(SB), $-4
-
-/*
- * set C environment and invoke main
- */
-inplace:
-	MOVW		$mach0(SB),R13
-	MOVW		R13,m(SB)
-	ADD			$(MACHSIZE-12),R13
-
-	/* disable MMU activity */
-	BL			mmuctlregr(SB)
-	BIC			$(CpCmmu|CpCDcache|CpCwb|CpCIcache), R0
-	BL			mmuctlregw(SB)
-		
-	BL			main(SB)
-loop:
-	B			loop
-
-TEXT		idle(SB),$0
-	RET
-
-/*
- *  basic timing loop to determine CPU frequency
- */
-TEXT aamloop(SB), $-4				/* 3 */
-_aamloop:
-	MOVW		R0, R0			/* 1 */
-	MOVW		R0, R0			/* 1 */
-	MOVW		R0, R0			/* 1 */
-	SUB			$1, R0			/* 1 */
-	CMP			$0, R0			/* 1 */
-	BNE			_aamloop			/* 3 */
-	RET							/* 3 */
-
-/*
- * Function: setr13( mode, pointer )
- * Purpose:
- *		Sets the stack pointer for a particular mode
- */
-
-TEXT setr13(SB), $-4
-	MOVW		4(FP), R1
-
-	MOVW		CPSR, R2
-	BIC			$PsrMask, R2, R3
-	ORR			R0, R3
-	MOVW		R3, CPSR
-
-	MOVW		R13, R0
-	MOVW		R1, R13
-
-	MOVW		R2, CPSR
-
-	RET
-
-/*
- * Function: _vundcall
- * Purpose:
- *		Undefined Instruction Trap Handler
- *
- */
-
-TEXT _vundcall(SB), $-4			
-_vund:
-	MOVM.DB		[R0-R3], (R13)
-	MOVW		$PsrMund, R0
-	B			_vswitch
-
-/*
- * Function: _vsvccall
- * Purpose:
- *		Reset or SWI Handler
- *
- */
-
-TEXT _vsvccall(SB), $-4				
-_vsvc:
-	SUB			$12, R13
-	MOVW		R14, 8(R13)
-	MOVW		CPSR, R14
-	MOVW		R14, 4(R13)
-	MOVW		$PsrMsvc, R14
-	MOVW		R14, (R13)
-	B			_vsaveu
-
-/*
- * Function: _pabcall
- * Purpose:
- *		Prefetch Abort Trap Handler
- *
- */
-
-TEXT _vpabcall(SB), $-4			
-_vpab:
-	MOVM.DB		[R0-R3], (R13)
-	MOVW		$PsrMabt, R0
-	B			_vswitch
-
-/*
- * Function: _vdabcall
- * Purpose:
- *		Data Abort Trap Handler
- *
- */
-
-TEXT _vdabcall(SB), $-4	
-_vdab:
-	MOVM.DB		[R0-R3], (R13)
-	MOVW		$(PsrMabt+1), R0
-	B			_vswitch
-
-/*
- * Function: _virqcall
- * Purpose:
- *		IRQ Trap Handler 
- *
- */
-
-TEXT _virqcall(SB), $-4				/* IRQ */
-_virq:
-	MOVM.DB		[R0-R3], (R13)
-	MOVW		$PsrMirq, R0
-	B			_vswitch
-
-/*
- * Function: _vfiqcall
- * Purpose:
- *		FIQ Trap Handler 
- *
- */
-
-TEXT _vfiqcall(SB), $-4				/* FIQ */
-_vfiq:
-	MOVM.DB		[R0-R3], (R13)
-	MOVW		$PsrMfiq, R0
-	/* FALLTHROUGH */
-
-_vswitch:					/* switch to svc mode */
-	MOVW		SPSR, R1
-	MOVW		R14, R2
-	MOVW		R13, R3
-
-	MOVW		CPSR, R14
-	BIC			$PsrMask, R14
-	ORR			$(PsrDirq|PsrDfiq|PsrMsvc), R14
-	MOVW		R14, CPSR
-
-	MOVM.DB.W 	[R0-R2], (R13)
-	MOVM.DB	  	(R3), [R0-R3]
-
-_vsaveu:						/* Save Registers */
-	SUB			$4, R13		/* save link */
-	MOVW		R14, (R13)	/* MOVW.W R14,4(R13)*/
-
-	SUB			$8, R13
-
-	MOVW		R13, R14	/* ur->sp */
-	ADD			$(6*4), R14
-	MOVW		R14, 0(R13)
-
-	MOVW		8(SP), R14			/* ur->link */
-	MOVW		R14, 4(SP)
-
-	MOVM.DB.W 	[R0-R12], (R13)	
-	MOVW		R0, R0				/* gratuitous noop */
-
-	MOVW		$setR12(SB), R12		/* static base (SB) */
-	MOVW		R13, R0				/* argument is ureg */
-	SUB			$8, R13				/* space for arg+lnk*/
-	BL			trap(SB)
-
-
-_vrfe:							/* Restore Regs */
-	MOVW		CPSR, R0			/* splhi on return */
-	ORR			$(PsrDirq|PsrDfiq), R0, R1
-	MOVW		R1, CPSR
-	ADD			$(8+4*15), R13		/* [r0-R14]+argument+link */
-	MOVW		(R13), R14			/* restore link */
-	MOVW		8(R13), R0
-	MOVW		R0, SPSR
-	MOVM.DB.S 	(R13), [R0-R14]		/* restore user registers */
-	MOVW		R0, R0				/* gratuitous nop */
-	ADD			$12, R13		/* skip saved link+type+SPSR*/
-	RFE					/* MOVM.IA.S.W (R13), [R15] */
-
-
-/*
- * Function: splhi
- * Purpose:
- *		Disable Interrupts
- * Returns:
- *		Previous interrupt state
- */
-	
-TEXT splhi(SB), $-4					
-	MOVW		CPSR, R0
-	ORR			$(PsrDirq|PsrDfiq), R0, R1
-	MOVW		R1, CPSR
-	RET
-
-/*
- * Function: spllo
- * Purpose:
- *		Enable Interrupts
- * Returns:
- *		Previous interrupt state
- */
-
-TEXT spllo(SB), $-4
-	MOVW		CPSR, R0
-	BIC			$(PsrDirq), R0, R1
-	MOVW		R1, CPSR
-	RET
-
-/*
- * Function: splx(level)
- * Purpose:
- *		Restore interrupt level
- */
-
-TEXT splx(SB), $-4
-	MOVW		R0, R1
-	MOVW		CPSR, R0
-	MOVW		R1, CPSR
-	RET
-
-/*
- * Function: islo
- * Purpose:
- *		Check if interrupts are enabled
- *
- */
-
-TEXT islo(SB), $-4
-	MOVW		CPSR, R0
-	AND			$(PsrDirq), R0
-	EOR			$(PsrDirq), R0
-	RET
-
-/*
- * Function: cpsrr
- * Purpose:
- *		Returns current program status register
- *
- */
-
-TEXT cpsrr(SB), $-4
-	MOVW		CPSR, R0
-	RET
-
-/*
- * Function: spsrr
- * Purpose:
- *		Returns saved program status register
- *
- */
-
-TEXT spsrr(SB), $-4
-	MOVW		SPSR, R0
-	RET
-
-/*
- * MMU Operations
- */
-TEXT mmuctlregr(SB), $-4
-	MRC		CpMMU, 0, R0, C(CpControl), C(0)
-	RET	
-
-TEXT mmuctlregw(SB), $-4
-	MCR		CpMMU, 0, R0, C(CpControl), C(0)
-	MOVW		R0, R0
-	MOVW		R0, R0
-	RET	
-
-/*
- * Cache Routines
- */
-
-/*
- * Function: flushIcache
- * Purpose:
- *		Flushes the *WHOLE* instruction cache
- */
-
-TEXT flushIcache(SB), $-4
-	MCR	 	CpMMU, 0, R0, C(CpCacheCtl), C(5), 0	
-	MOVW		R0,R0							
-	MOVW		R0,R0
-	MOVW		R0,R0
-	MOVW		R0,R0
-	RET
-
-
-
-/*
- * Function: flushDentry
- * Purpose:
- *		Flushes an entry of the data cache
- */
-
-TEXT flushDentry(SB), $-4
-	MCR		CpMMU, 0, R0, C(CpCacheCtl), C(6), 1
-	RET
-
-/*
- * Function: drainWBuffer
- * Purpose:
- *		Drains the Write Buffer
- */
-
-TEXT drainWBuffer(SB), $-4
-	MCR		CpMMU, 0, R0, C(CpCacheCtl), C(10), 4	
-	RET
-
-/*
- * Function: writeBackDC
- * Purpose:
- *		Drains the dcache prior to flush
- */
-
-TEXT writeBackDC(SB), $-4
-	MOVW		$0xE0000000, R0
-	MOVW		$8192, R1
-	ADD		R0, R1
-
-wbflush:
-	MOVW		(R0), R2
-	ADD		$32, R0
-	CMP		R1,R0
-	BNE		wbflush
-	RET
-
-/*
- * Function: flushDcache(SB)
- * Purpose:
- *		Flush the dcache 
- */
-
-TEXT flushDcache(SB), $-4
-	MCR		CpMMU, 0, R0, C(CpCacheCtl), C(6), 0	
-	RET
-
-/*
- * Function: writeBackBDC(SB)
- * Purpose:
- *		Write back the Baby D-Cache
- */
-
-TEXT writeBackBDC(SB), $-4		
-	MOVW		$0xE4000000, R0
-	MOVW		$0x200, R1
-	ADD		R0, R1
-
-wbbflush:
-	MOVW		(R0), R2
-	ADD		$32, R0
-	CMP		R1,R0
-	BNE		wbbflush
-	MCR		CpMMU, 0, R0, C(CpCacheCtl), C(10), 4	
-	MOVW		R0,R0								
-	MOVW		R0,R0
-	MOVW		R0,R0
-	MOVW		R0,R0
-	RET
-
-GLOBL	mach0+0(SB), $MACHSIZE
-GLOBL	m(SB), $4
-GLOBL	baddr(SB), $4
--- a/os/boot/puma/lib.h
+++ /dev/null
@@ -1,107 +1,0 @@
-/*
- * functions (possibly) linked in, complete, from libc.
- */
-
-/*
- * mem routines
- */
-extern	void*	memccpy(void*, void*, int, long);
-extern	void*	memset(void*, int, long);
-extern	int	memcmp(void*, void*, long);
-extern	void*	memmove(void*, void*, long);
-extern	void*	memchr(void*, int, long);
-
-/*
- * string routines
- */
-extern	char*	strcat(char*, char*);
-extern	char*	strchr(char*, char);
-extern	int	strcmp(char*, char*);
-extern	char*	strcpy(char*, char*);
-extern	char*	strncat(char*, char*, long);
-extern	char*	strncpy(char*, char*, long);
-extern	int	strncmp(char*, char*, long);
-extern	long	strlen(char*);
-extern	char*	strrchr(char*, char);
-extern	char*	strstr(char*, char*);
-
-/*
- * print routines
- * 	Fconv isn't used but is defined to satisfy prototypes in libg.h
- *	that are never called.
- */
-typedef	struct Fconv Fconv;
-
-extern	char*	donprint(char*, char*, char*, void*);
-extern	int	sprint(char*, char*, ...);
-extern	int	print(char*, ...);
-
-#define	PRINTSIZE	256
-
-/*
- * one-of-a-kind
- */
-extern	int	atoi(char*);
-extern	long	strtol(char*, char**, int);
-extern	ulong	strtoul(char*, char**, int);
-extern	char	end[];
-extern 	char edata[];
-
-/*
- * Syscall data structures
- */
-
-#define	MORDER	0x0003	/* mask for bits defining order of mounting */
-#define	MREPL	0x0000	/* mount replaces object */
-#define	MBEFORE	0x0001	/* mount goes before others in union directory */
-#define	MAFTER	0x0002	/* mount goes after others in union directory */
-#define	MCREATE	0x0004	/* permit creation in mounted directory */
-#define	MMASK	0x0007	/* all bits on */
-
-#define	OREAD	0	/* open for read */
-#define	OWRITE	1	/* write */
-#define	ORDWR	2	/* read and write */
-#define	OEXEC	3	/* execute, == read but check execute permission */
-#define	OTRUNC	16	/* or'ed in (except for exec), truncate file first */
-#define	OCEXEC	32	/* or'ed in, close on exec */
-#define	ORCLOSE	64	/* or'ed in, remove on close */
-
-#define	NCONT	0	/* continue after note */
-#define	NDFLT	1	/* terminate after note */
-
-typedef struct Qid	Qid;
-typedef struct Dir	Dir;
-typedef struct Waitmsg	Waitmsg;
-
-#define	ERRLEN	64
-#define	DIRLEN	116
-#define	NAMELEN	28
-
-struct Qid
-{
-	ulong	path;
-	ulong	vers;
-};
-
-struct Dir
-{
-	char	name[NAMELEN];
-	char	uid[NAMELEN];
-	char	gid[NAMELEN];
-	Qid	qid;
-	ulong	mode;
-	long	atime;
-	long	mtime;
-	ulong	length;
-	short	type;
-	short	dev;
-};
-
-struct Waitmsg
-{
-	int	pid;		/* of loved one */
-	int	status;		/* unused; a placeholder */
-	ulong	time[3];	/* of loved one */
-	char	msg[ERRLEN];
-};
-#define	nelem(x)	(sizeof(x)/sizeof((x)[0]))
--- a/os/boot/puma/main.c
+++ /dev/null
@@ -1,552 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-#include "dosfs.h"
-
-typedef struct Type Type;
-typedef struct Medium Medium;
-typedef struct Mode Mode;
-
-enum {
-	Dany		= -1,
-	Nmedia		= 16,
-
-	/* DS1 switch options */
-	Sflashfs		= 1<<0,	/* take local fs from flash */
-	Snotflash		= 1<<1,	/* don't boot from flash */
-};
-
-enum {					/* type */
-	Tflash,
-	Tether,
-	Thard,
-
-	Tany		= -1,
-};
-
-enum {					/* flag and name */
-	Fnone		= 0x00,
-
-	Fdos		= 0x01,
-	Ndos		= 0x00,
-	Fboot		= 0x02,
-	Nboot		= 0x01,
-	Fbootp		= 0x04,
-	Nbootp		= 0x02,
-	Fflash		= 0x08,
-	NName		= 0x03,
-
-	Fany		= Fbootp|Fboot|Fdos|Fflash,
-
-	Fini		= 0x10,
-	Fprobe		= 0x80,
-};
-
-enum {					/* mode */
-	Mauto		= 0x00,
-	Mlocal		= 0x01,
-	Manual		= 0x02,
-	NMode		= 0x03,
-};
-
-typedef struct Type {
-	int	type;
-	char	*cname;
-	int	flag;
-	int	(*init)(void);
-	long	(*read)(int, void*, long);
-	long	(*seek)(int, long);
-	Partition* (*setpart)(int, char*);
-	char*	name[NName];
-
-	int	mask;
-	Medium*	media;
-} Type;
-
-typedef struct Medium {
-	Type*	type;
-	int	flag;
-	Partition* partition;
-	Dos;
-
-	Medium*	next;
-} Medium;
-
-typedef struct Mode {
-	char*	name;
-	int	mode;
-} Mode;
-
-static Type types[] = {
-	{	Tflash, "flash",
-		Fflash,
-		flashinit, 0, 0, 0,
-		{ 0, "F", 0, }
-	},
-	{	Tether, "ether",
-		Fbootp,
-		etherinit, 0, 0, 0,
-		{ 0, 0, "e", },
-	},
-	{	Thard, "ata",
-		Fini|Fboot|Fdos,
-		0, 0, 0, 0,		/* not used now, will be later with PCMCIA */
-		{ "hd", "h", 0, },
-	},
-	{-1},
-};
-
-static Medium media[Nmedia];
-static Medium *curmedium = media;
-
-static Mode modes[NMode+1] = {
-	[Mauto]		{ "auto",   Mauto,  },
-	[Mlocal]	{ "local",  Mlocal, },
-	[Manual]	{ "manual", Manual, },
-};
-
-static char *inis[] = {
-	"inferno/inferno.ini",
-	"inferno.ini",
-	"plan9/plan9.ini",
-	"plan9.ini",
-	0,
-};
-char **ini;
-void	printversion(void);
-
-static int
-parse(char *line, int *type, int *flag, int *dev, char *file)
-{
-	Type *tp;
-	char buf[2*NAMELEN], *v[4], *p;
-	int i;
-
-	strcpy(buf, line);
-	switch(getcfields(buf, v, 4, "!")){
-
-	case 3:
-		break;
-
-	case 2:
-		v[2] = "";
-		break;
-
-	default:
-		return 0;
-	}
-
-	*flag = 0;
-	for(tp = types; tp->cname; tp++){
-		for(i = 0; i < NName; i++){
-
-			if(tp->name[i] == 0 || strcmp(v[0], tp->name[i]))
-				continue;
-			*type = tp->type;
-			*flag |= 1<<i;
-
-			if((*dev = strtoul(v[1], &p, 0)) == 0 && p == v[1])
-				return 0;
-		
-			strcpy(file, v[2]);
-		
-			return 1;
-		}
-	}
-
-	return 0;
-
-}
-
-static int
-boot(Medium *mp, int flag, char *file)
-{
-	Dosfile df;
-	char ixdos[128], *p;
-
-	if(flag & Fbootp){
-		sprint(BOOTLINE, "%s!%d", mp->type->name[Nbootp], mp->dev);
-		return bootp(mp->dev, file);
-	}
-
-	if(flag & Fflash){
-		if(mp->flag & Fflash && flashbootable(0))
-			flashboot(mp->dev);
-	}
-
-	if(flag & Fboot){
-
-		if(mp->flag & Fini){
-			(*mp->type->setpart)(mp->dev, "disk");
-			plan9ini(mp, nil);
-		}
-		if(file == 0 || *file == 0)
-			file = mp->partition->name;
-		(*mp->type->setpart)(mp->dev, file);
-		sprint(BOOTLINE, "%s!%d!%s", mp->type->name[Nboot], mp->dev, file);
-		return plan9boot(mp->dev, mp->seek, mp->read);
-	}
-
-	if(flag & Fdos){
-		if(mp->type->setpart)
-			(*mp->type->setpart)(mp->dev, "disk");
-		if(mp->flag & Fini)
-			plan9ini(mp, nil);
-		if(file == 0 || *file == 0){
-			strcpy(ixdos, *ini);
-			if(p = strrchr(ixdos, '/'))
-				p++;
-			else
-				p = ixdos;
-			strcpy(p, "infernopuma");
-			if(dosstat(mp, ixdos, &df) <= 0)
-				return -1;
-		}
-		else
-			strcpy(ixdos, file);
-		sprint(BOOTLINE, "%s!%d!%s", mp->type->name[Ndos], mp->dev, ixdos);
-		return dosboot(mp, ixdos);
-	}
-
-	return -1;
-}
-
-static Medium*
-allocm(Type *tp)
-{
-	Medium **l;
-
-	if(curmedium >= &media[Nmedia])
-		return 0;
-
-	for(l = &tp->media; *l; l = &(*l)->next)
-		;
-	*l = curmedium++;
-	return *l;
-}
-
-Medium*
-probe(int type, int flag, int dev)
-{
-	Type *tp;
-	int dombr, i, start;
-	Medium *mp;
-	Dosfile df;
-	Partition *pp;
-
-	for(tp = types; tp->cname; tp++){
-		if(type != Tany && type != tp->type || tp->init == 0)
-			continue;
-
-		if(flag != Fnone){
-			for(mp = tp->media; mp; mp = mp->next){
-				if((flag & mp->flag) && (dev == Dany || dev == mp->dev))
-					return mp;
-			}
-		}
-		if((tp->flag & Fprobe) == 0){
-			tp->flag |= Fprobe;
-			tp->mask = (*tp->init)();
-		}
-
-		for(i = 0; tp->mask; i++){
-			if((tp->mask & (1<<i)) == 0)
-				continue;
-			tp->mask &= ~(1<<i);
-
-			if((mp = allocm(tp)) == 0)
-				continue;
-
-			mp->dev = i;
-			mp->flag = tp->flag;
-			mp->seek = tp->seek;
-			mp->read = tp->read;
-			mp->type = tp;
-
-			if(mp->flag & Fboot){
-				if((mp->partition = (*tp->setpart)(i, "boot")) == 0)
-					mp->flag &= ~Fboot;
-				if((mp->flag & Fflash) == 0)
-					(*tp->setpart)(i, "disk");
-			}
-
-			if(mp->flag & Fdos){
-				start = 0;
-				dombr = 1;
-				if(mp->type->setpart){
-					if(pp = (*mp->type->setpart)(i, "dos")){
-						if(start = pp->start)
-							dombr = 0;
-					}
-					(*tp->setpart)(i, "disk");
-				}
-				if(dosinit(mp, start, dombr) < 0)
-					mp->flag &= ~(Fini|Fdos);
-				else
-					print("dos init failed\n");
-			}
-
-			if(mp->flag & Fini){
-				mp->flag &= ~Fini;
-				for(ini = inis; *ini; ini++){
-					if(dosstat(mp, *ini, &df) <= 0)
-						continue;
-					mp->flag |= Fini;
-					break;
-				}
-			}
-
-			if((flag & mp->flag) && (dev == Dany || dev == i))
-				return mp;
-		}
-	}
-
-	return 0;
-}
-
-static void
-pause(void)
-{
-	long d;
-	for(d=0; d<10000000; d++)
-		;
-	USED(d);
-}
-
-static void
-flash(int n)
-{
-	int i;
-
-	if(n <= 0)
-		return;
-	for(i=0; i<n-1; i++) {
-		led(1);
-		pause();
-		led(0);
-		pause();
-	}
-	led(1);
-	pause();pause();pause();
-	led(0);
-	pause();pause();pause();
-}
-
-void
-main(void)
-{
-	Medium *mp;
-	int dev, flag, i, mode, tried, type, options;
-	char def[2*NAMELEN], file[2*NAMELEN], line[80], *p;
-	Type *tp;
-
-	memset(edata, 0, end-edata );			/* clear the BSS */		
-	pumainit();
-
-	machinit();
-	meminit();
-	trapinit();
-	consinit();	/* screen and keyboard initially */
-//	screeninit();
-	alarminit();
-	clockinit();
-	printversion();
-
-	spllo();
-	options = optionsw();
-
-
-	mp = 0;
-	for(tp = types; tp->cname; tp++){
-		if(tp->type == Tether)
-			continue;
-		if((mp = probe(tp->type, Fini, Dany)) && (mp->flag & Fini)){
-			plan9ini(mp, nil);
-			break;
-		}
-	}
-
-	if(mp == 0 || (mp->flag & Fini) == 0)
-		plan9ini(nil, flashconfig(0));
-
-	//consinit();	/* establish new console location */
-
-	if((options & Snotflash) == 0 && flashbootable(0)){
-		print("Flash boot\n");
-		flashboot(0);
-	}
-
-	tried = 0;
-	mode = Mauto;
-	p = getconf("bootfile");
-	flag = 0;
-
-	if(p != 0) {
-		mode = Manual;
-		for(i = 0; i < NMode; i++){
-			if(strcmp(p, modes[i].name) == 0){
-				mode = modes[i].mode;
-				goto done;
-			}
-		}
-		if(parse(p, &type, &flag, &dev, file) == 0) {
-			print("Bad bootfile syntax: %s\n", p);
-			goto done;
-		}
-		mp = probe(type, flag, dev);
-		if(mp == 0) {
-			print("Cannot access device: %s\n", p);
-			goto done;
-		}
-		tried = boot(mp, flag, file);
-	}
-done:
-	if(tried == 0 && mode != Manual){
-		flag = Fany;
-		if(mode == Mlocal)
-			flag &= ~Fbootp;
-		if(options & Snotflash)
-			flag &= ~Fflash;
-		if((mp = probe(Tany, flag, Dany)) != 0)
-			boot(mp, flag & mp->flag, 0);
-	}
-
-	def[0] = 0;
-	probe(Tany, Fnone, Dany);
-
-	flag = 0;
-	for(tp = types; tp->cname; tp++){
-		for(mp = tp->media; mp; mp = mp->next){
-			if(flag == 0){
-				flag = 1;
-				print("Boot devices:");
-			}
-
-			if(mp->flag & Fbootp)
-				print(" %s!%d", mp->type->name[Nbootp], mp->dev);
-			if(mp->flag & Fdos)
-				print(" %s!%d", mp->type->name[Ndos], mp->dev);
-			if(mp->flag & Fflash || mp->flag & Fboot)
-				print(" %s!%d", mp->type->name[Nboot], mp->dev);
-		}
-	}
-	if(flag)
-		print("\n");
-
-	for(;;){
-		if(getstr("boot from", line, sizeof(line), def) >= 0){
-			if(parse(line, &type, &flag, &dev, file)){
-				if(mp = probe(type, flag, dev))
-					boot(mp, flag, file);
-			}
-		}
-		def[0] = 0;
-	}
-}
-
-void
-machinit(void)
-{
-	memset(m, 0, sizeof(*m));
-	m->delayloop = 20000;
-}
-
-void
-printversion(void)
-{
-	print("StrongARM SA-110 ");
-	print("%d MHz system\n", m->speed);
-	print("\n");
-{extern long baddr; print("%8.8lux\n", baddr);}
-}
-
-int
-optionsw()
-{
-	return 0;
-}
-
-int
-getcfields(char* lp, char** fields, int n, char* sep)
-{
-	int i;
-
-	for(i = 0; lp && *lp && i < n; i++){
-		while(*lp && strchr(sep, *lp) != 0)
-			*lp++ = 0;
-		if(*lp == 0)
-			break;
-		fields[i] = lp;
-		while(*lp && strchr(sep, *lp) == 0){
-			if(*lp == '\\' && *(lp+1) == '\n')
-				*lp++ = ' ';
-			lp++;
-		}
-	}
-
-	return i;
-}
-
-static	Map	memv[512];
-static	RMap	rammap = {"physical memory"};
-
-void
-meminit(void)
-{
-	ulong e;
-
-	mapinit(&rammap, memv, sizeof(memv));
-	e = PADDR(end);
-	mapfree(&rammap, e, 4*1024*1024-e);
-}
-
-void*
-ialloc(ulong n, int align)
-{
-	ulong a;
-	int s;
-
-	if(align <= 0)
-		align = 4;
-	s = splhi();
-	a = mapalloc(&rammap, 0, n, align);
-	splx(s);
-	if(a == 0)
-		panic("ialloc");
-	return memset(KADDR(a), 0, n);
-}
-
-void*
-malloc(ulong n)
-{
-	ulong *p;
-
-	n = ((n+sizeof(int)-1)&~(sizeof(int)-1))+2*sizeof(int);
-	p = ialloc(n, sizeof(int));
-	*p++ = 0xcafebeef;
-	*p++ = n;
-	return p;
-}
-
-void
-free(ulong *p)
-{
-	int s;
-
-	if(p){
-		if(*(p -= 2) != 0xcafebeef)
-			panic("free");
-		s = splhi();
-		mapfree(&rammap, (ulong)p, p[1]);
-		splx(s);
-	}
-}
-
-void
-sched(void)
-{
-}
--- a/os/boot/puma/mem.h
+++ /dev/null
@@ -1,38 +1,0 @@
-/*
- * Memory and machine-specific definitions.  Used in C and assembler.
- */
-
-/*
- * Sizes
- */
-#define	BI2BY		8			/* bits per byte */
-#define	BI2WD		32			/* bits per word */
-#define	BY2WD		4			/* bytes per word */
-#define	BY2PG		4096			/* bytes per page */
-#define	WD2PG		(BY2PG/BY2WD)		/* words per page */
-#define	PGSHIFT		12			/* log(BY2PG) */
-#define	PGROUND(s)	(((s)+(BY2PG-1))&~(BY2PG-1))
-
-#define	MAXMACH		1			/* max # cpus system can run */
-
-/*
- * Time
- */
-#define	HZ		(20)				/* clock frequency */
-#define	MS2HZ		(1000/HZ)			/* millisec per clock tick */
-#define	TK2SEC(t)	((t)/HZ)			/* ticks to seconds */
-#define	TK2MS(t)	((((ulong)(t))*1000)/HZ)	/* ticks to milliseconds */
-#define	MS2TK(t)	((((ulong)(t))*HZ)/1000)	/* milliseconds to ticks */
-
-/*
- * Fundamental addresses
- */
-
-/*
- *  Address spaces
- *
- *  Kernel is at 0x00008000
- */
-#define	KZERO		0x00000000		/* base of kernel address space */
-#define	KTZERO		KZERO			/* first address in kernel text */
-#define	MACHSIZE	4096
--- a/os/boot/puma/mkfile
+++ /dev/null
@@ -1,71 +1,0 @@
-<../../../mkconfig
-
-SYSTARG=Inferno
-OBJTYPE=arm
-<$ROOT/mkfiles/mkfile-$SYSTARG-$OBJTYPE	#set vars based on target system
-
-TARGET=${O}boot
-OBJ=\
-	l.$O\
-	div.$O\
-	8250.$O\
-	alarm.$O\
-	bootp.$O\
-	clock.$O\
-	console.$O\
-	conf.$O\
-	dosboot.$O\
-	donprint.$O\
-	ether.$O\
-	ether8900.$O\
-	flash.$O\
-	kbd.$O\
-	main.$O\
-	plan9boot.$O\
-	puma.$O\
-	qio.$O\
-	rmap.$O\
-	trap.$O\
-	zqs.$O
-
-HFILES=\
-	lib.h\
-	mem.h\
-	dat.h\
-	fns.h\
-	io.h\
-	boot.h\
-	armv4.h\
-	puma.h\
-
-CFLAGS=-w -I.
-LFLAGS=-H1 -R4 -T0x00200000 -E_main #-a
-#LFLAGS=-H1 -R4 -T0x00008080 -E_main #-a
-#LFLAGS = -H1 -R4 -T0xa00000c0 -E_main #-a
-
-all:V:	$TARGET
-
-$TARGET:	$OBJ
-	$LD -o $target $LFLAGS -l $prereq -lc
-	ls -l $target
-
-installall:V:	install
-install:V:	bb $TARGET
-	cp $TARGET /arm
-
-%.$O:	%.s
-	$AS $stem.s
-
-%.$O:	%.c
-	$CC $CFLAGS $stem.c
-
-%.$O:	$HFILES
-
-clock.$O floppy.$O trap.$O:	ureg.h
-conf.$O dosboot.$O main.$O:	dosfs.h
-ether.$O ether2000.$O ether509.$O ether8003.$O ether8390.$O:	ether.h
-bootp.$O:	ip.h
-
-clean:
-	rm -f *.[$OS] [$OS].out y.tab.? y.debug y.output $TARGET
-
--- a/os/boot/puma/outb.c
+++ /dev/null
@@ -1,20 +1,0 @@
-typedef	unsigned short	ushort;
-typedef	unsigned char	uchar;
-
-enum {
-	IsaIOBase		= 0xf0000000,
-	IsaMemBase	= 0xe0000000,
-
-	IOBase		= 0x300,
-	MemBase		= 0xc0000,
-
-	TxFrame		= 0x0a00,
-};
-
-#define	regw(reg, val)		*((ushort *)IsaMemBase + MemBase + (reg)) = (val)
-
-void
-main(void)
-{
-	regw(TxFrame, 0x1234);
-}
--- a/os/boot/puma/plan9boot.c
+++ /dev/null
@@ -1,93 +1,0 @@
-#include	"u.h"
-#include	"lib.h"
-#include	"mem.h"
-#include	"dat.h"
-#include	"fns.h"
-
-char *premature = "premature EOF\n";
-
-/*
- *  read in a segment
- */
-static long
-readseg(int dev, long (*read)(int, void*, long), long len, long addr)
-{
-	char *a;
-	long n, sofar;
-
-	a = (char *)addr;
-	for(sofar = 0; sofar < len; sofar += n){
-		n = 8*1024;
-		if(len - sofar < n)
-			n = len - sofar;
-		n = (*read)(dev, a + sofar, n);
-		if(n <= 0)
-			break;
-		print(".");
-	}
-	return sofar;
-}
-
-/*
- *  boot
- */
-int
-plan9boot(int dev, long (*seek)(int, long), long (*read)(int, void*, long))
-{
-	long n;
-	long addr;
-	void (*b)(void);
-	Exec *ep;
-
-	if((*seek)(dev, 0) < 0)
-		return -1;
-
-	/*
-	 *  read header
-	 */
-	ep = (Exec *) ialloc(sizeof(Exec), 0);
-	n = sizeof(Exec);
-	if(readseg(dev, read, n, (ulong) ep) != n){
-		print(premature);
-		return -1;
-	}
-	if(GLLONG(ep->magic) != E_MAGIC){
-		print("bad magic 0x%lux not a plan 9 executable!\n", GLLONG(ep->magic));
-		return -1;
-	}
-
-	/*
-	 *  read text
-	 */
-	addr = PADDR(GLLONG(ep->entry));
-	n = GLLONG(ep->text);
-	print("%d", n);
-	if(readseg(dev, read, n, addr) != n){
-		print(premature);
-		return -1;
-	}
-
-	/*
-	 *  read data (starts at first page after kernel)
-	 */
-	addr = PGROUND(addr+n);
-	n = GLLONG(ep->data);
-	print("+%d", n);
-	if(readseg(dev, read, n, addr) != n){
-		print(premature);
-		return -1;
-	}
-
-	/*
-	 *  bss and entry point
-	 */
-	print("+%d\nstart at 0x%lux\n", GLLONG(ep->bss), GLLONG(ep->entry)); uartwait();
-
-	/*
-	 *  Go to new code. It's up to the program to get its PC relocated to
-	 *  the right place.
-	 */
-	b = (void (*)(void))(PADDR(GLLONG(ep->entry)));
-	(*b)();
-	return 0;
-}
--- a/os/boot/puma/puma.c
+++ /dev/null
@@ -1,123 +1,0 @@
-#include "boot.h"
-
-//#define GPIO1_PORT		0x0078
-//#define GPIO2_PORT		0x0079
-
-#define GPIO2_N_LED1_DIAG	0x10	/* diagnostic led mask */
-
-#define	HARI2_N_LED1		0x01
-#define	HARI2_N_LED2		0x02
-#define	HARI2_N_LED3		0x04
-#define	HARI2_N_LED4		0x08
-
-/*
- * National Semiconductor PC87306 Super I/O
- */
-enum {
-	Index=		0x398,	/* sio configuration index register */
-	Data=		0x399,	/* sio configuration data register */
-};
-
-
-// byte flip table for Puma SuperIO port permuted as 76543210 -> 01234567
-unsigned char
-byteflip[] = {
-	0x00,0x80,0x40,0xC0,0x20,0xA0,0x60,0xE0,0x10,0x90,0x50,0xD0,0x30,0xB0,0x70,0xF0,
-	0x08,0x88,0x48,0xC8,0x28,0xA8,0x68,0xE8,0x18,0x98,0x58,0xD8,0x38,0xB8,0x78,0xF8,
-	0x04,0x84,0x44,0xC4,0x24,0xA4,0x64,0xE4,0x14,0x94,0x54,0xD4,0x34,0xB4,0x74,0xF4,
-	0x0C,0x8C,0x4C,0xCC,0x2C,0xAC,0x6C,0xEC,0x1C,0x9C,0x5C,0xDC,0x3C,0xBC,0x7C,0xFC,
-	0x02,0x82,0x42,0xC2,0x22,0xA2,0x62,0xE2,0x12,0x92,0x52,0xD2,0x32,0xB2,0x72,0xF2,
-	0x0A,0x8A,0x4A,0xCA,0x2A,0xAA,0x6A,0xEA,0x1A,0x9A,0x5A,0xDA,0x3A,0xBA,0x7A,0xFA,
-	0x06,0x86,0x46,0xC6,0x26,0xA6,0x66,0xE6,0x16,0x96,0x56,0xD6,0x36,0xB6,0x76,0xF6,
-	0x0E,0x8E,0x4E,0xCE,0x2E,0xAE,0x6E,0xEE,0x1E,0x9E,0x5E,0xDE,0x3E,0xBE,0x7E,0xFE,
-	0x01,0x81,0x41,0xC1,0x21,0xA1,0x61,0xE1,0x11,0x91,0x51,0xD1,0x31,0xB1,0x71,0xF1,
-	0x09,0x89,0x49,0xC9,0x29,0xA9,0x69,0xE9,0x19,0x99,0x59,0xD9,0x39,0xB9,0x79,0xF9,
-	0x05,0x85,0x45,0xC5,0x25,0xA5,0x65,0xE5,0x15,0x95,0x55,0xD5,0x35,0xB5,0x75,0xF5,
-	0x0D,0x8D,0x4D,0xCD,0x2D,0xAD,0x6D,0xED,0x1D,0x9D,0x5D,0xDD,0x3D,0xBD,0x7D,0xFD,
-	0x03,0x83,0x43,0xC3,0x23,0xA3,0x63,0xE3,0x13,0x93,0x53,0xD3,0x33,0xB3,0x73,0xF3,
-	0x0B,0x8B,0x4B,0xCB,0x2B,0xAB,0x6B,0xEB,0x1B,0x9B,0x5B,0xDB,0x3B,0xBB,0x7B,0xFB,
-	0x07,0x87,0x47,0xC7,0x27,0xA7,0x67,0xE7,0x17,0x97,0x57,0xD7,0x37,0xB7,0x77,0xF7,
-	0x0F,0x8F,0x4F,0xCF,0x2F,0xAF,0x6F,0xEF,0x1F,0x9F,0x5F,0xDF,0x3F,0xBF,0x7F,0xFF
-};
-
-int
-sio_inb(int port)
-{
-	unsigned char b = *(uchar *)IOBADDR(port);
-//	b = byteflip[b];
-	return b&0xff;
-}
-
-void
-sio_outb(int port, int data)
-{
-//	data = byteflip[data];
-	*(uchar *)IOBADDR(port) = data;
-}
-
-static void
-siocfg(int r, int v, int rsv)
-{
-	sio_outb(Index, r);
-	if(rsv)
-		v = (sio_inb(Data)&rsv) | (v&~rsv);
-	sio_outb(Data, v);
-	sio_outb(Data, v);	/* ``write data twice'' */
-}
-
-void
-sioinit(void)
-{
-	/* determine which byte flip is required ... */
-
-	siocfg(SIO_CONFIG_FAR, FAR_LPT_LPTA | FAR_UART1_COM1 | FAR_UART2_COM2, 0);
-	siocfg(SIO_CONFIG_FER,	FER_LPT_ENABLE | FER_UART1_ENABLE | FER_UART2_ENABLE | FER_IDE_ENABLE, 0);
-	siocfg(SIO_CONFIG_KRR,	KRR_KBC_ENABLE | KRR_KBC_MUST_BE_1 | KRR_RTC_ENABLE, 0x50);
-	siocfg(SIO_CONFIG_SCF0,SCF0_GPIO_PORT1_ENABLE | SCF0_GPIO_PORT2_ENABLE, 0xC0);
-
-	/* force UART interrupt pins low, not tristate by setting ienable in MCR (!) */
-	sio_outb(COM1_PORT+UART_MCR, sio_inb(COM1_PORT+UART_MCR)|(1<<3));
-	sio_outb(COM2_PORT+UART_MCR, sio_inb(COM2_PORT+UART_MCR)|(1<<3));
-}
-
-void
-led(int on)
-{
-	int gpio, hari, hbits;
-	int s;
-
-	s = splhi();
-
-	gpio = sio_inb(GPIO2_PORT);
-	if (on)
-		gpio &= ~GPIO2_N_LED1_DIAG;
-	else
-		gpio |= GPIO2_N_LED1_DIAG;
-	sio_outb(GPIO2_PORT, gpio);
-
-	hari = HARI2_INIT;
-	hbits = HARI2_N_LED1|HARI2_N_LED2|HARI2_N_LED3|HARI2_N_LED4;
-	if (on)
-		hari &= ~hbits;
-	else
-		hari |= hbits;
-	*(uchar *)HARI2 = hari;
-
-	
-	splx(s);
-
-}
-
-void
-pumainit(void)
-{
-	/*
-	 * Initialise HARI2 for:
-	 * a) Leds off
-	 * b) No Timer2 aborts
-	 * c) Ethernet on IRQ
-	 */
-	*(uchar *)HARI2 = HARI2_INIT|HARI2_N_LED1|HARI2_N_LED2|HARI2_N_LED3|HARI2_N_LED4;
-	sioinit();
-}
-
--- a/os/boot/puma/puma.h
+++ /dev/null
@@ -1,435 +1,0 @@
-/*
- * Teralogic TL750 - Puma Evaluation Board
- */
- 
-/*
- * Puma addresses
- */
-#define EPROM_BASE	0x80000000	/* EPROM */
-#define FLASH_BASE	0xa0000000	/* Flash */
-#define TL750_BASE	0xc0000000	/* TL750 registers */
-#define ISAMEM_BASE	0xe0000000	/* ISA memory space */
-#define ISAIO_BASE		0xf0000000	/* ISA I/O space */
-
-#define ISAIO_SHIFT	2
-#define IOBADDR(io_port) (ISAIO_BASE + (io_port << ISAIO_SHIFT))
-
-/* Hardware address register for interrupts (HARI) */
-#define HARI1			0xE2000000 /* Interrupt status on read, User interrupt on write */
-#define HARI2			0xE3000000 /* More interrupt status on read, LEDs on write */	
-#define HARI1_FIQ_MASK	0x92	/* FIQ indicator bits in HARI1, others are IRQ */
-#define HARI2_INIT			0x20	/* No timer2 aborts, Ethernet on IRQ */			
-
-
-
-/*
- * Interrupt Vectors
- * corresponding to the HARIx_xxx_IRQ/FIQ bits above. 
- *
- * HARI1 interrupts 
- */
-#define V_LPT				0		/* Parallel port interrupt */
-#define V_NM0			1		/* MPEG Decode Interrupt */
-#define V_NM1			2		/* MPEG Decode Interrupt */
-#define V_COM2			3		/* Serial Port 2 Interrupt */
-#define V_COM1			4       	/* Serial Port 1 Interrupt */
-#define V_MOUSE			5		/* Mouse Interrupt */
-#define V_KEYBOARD		6		/* Keyboard Interrupt */
-#define V_ETHERNET		7		/* Ethernet Interrupt */
-/* 
- * HARI2 interrupts 
- */
-#define V_TIMER0			8		/* 82C54 Timer 0 Interrupt */
-#define V_TIMER1			9		/* 82C54 Timer 1 Interrupt */
-#define V_TIMER2			10		/* 82C54 Timer 2 Interrupt */
-#define V_SOFTWARE		11		/* Software Interrupt */
-#define V_IDE				12		/* IDE Hard Drive Interrupt */
-#define V_SMARTCARD		13		/* Smart Card Interrupt */
-#define V_TL750			14		/* TL750 Interrupt */
-								/* Nothing in vector 15 for now */
-#define V_MAXNUM     		15
-
-/*
- * Definitions for National Semiconductor PC87306 SuperIO configuration
- */
-#define SIO_CONFIG_INDEX		0x398	/* SuperIO configuration index register */
-#define SIO_CONFIG_DATA			0x399	/* SuperIO configuration data register */
-
-#define SIO_CONFIG_RESET_VAL		0x88	/* Value read from first read of sio_config_index reg after reset */
-/*
- * PC87306 Configuration Registers (The value listed is the configuration space
- * index.)
- */
-#define SIO_CONFIG_FER			0x00	/* Function Enable Register */
-
-#define     FER_LPT_ENABLE				0x01	/* Enable Parallel Port */
-#define     FER_UART1_ENABLE				0x02	/* Enable Serial Port 1 */
-#define     FER_UART2_ENABLE				0x04	/* Enable Serial Port 2 */
-#define     FER_FDC_ENABLE				0x08	/* Enable Floppy Controller */
-#define     FER_FDC_4DRIVE_ENCODING			0x10	/* Select Floppy 4 Drive Encoding */
-#define     FER_FDC_ADDR_ENABLE				0x20	/* Select Floppy Secondary Address */
-								/* 0: [0x3F0..0x3F7] */
-								/* 1: [0x370..0x377] */
-#define     FER_IDE_ENABLE				0x40	/* Enable IDE Controller */
-#define     FER_IDE_ADDR_SELECT				0x80	/* Select IDE Secondary Address */
-								/* 0: [0x1F0..0x1F7,0x3F6,0x3F7] */
-								/* 1: [0x170..0x177,0x376,0x377] */
-
-#define SIO_CONFIG_FAR			0x01	/* Function Address Register */
-
-#define     FAR_LPT_ADDR_MASK				0x03	/* Select LPT Address */
-								/* If (PNP0[4] == 0) then: */
-								/*     0: LPTB [0x378..0x37F] IRQ5/7 */
-								/*     1: LPTA [0x3BC..0x3BE] IRQ7 */
-								/*     2: LPTC [0x278..0x27F] IRQ5 */
-								/*     3: Reserved */
-								/* Else ignored. */
-#define	FAR_LPT_LPTB	0	/* 0: LPTB 0x378 irq5/7 */
-#define	FAR_LPT_LPTA	1	/* 1: LPTA 0x3BC irq 7 */
-#define	FAR_LPT_LPTC	2	/* 2: LPTC 0x278 irq5 */
-
-#define     FAR_UART1_ADDR_MASK				0x0C	/* Select Serial Port 1 Address */
-								/* 0: COM1 [0x3F8..0x3FF] */
-								/* 1: COM2 [0x2F8..0x2FF] */
-								/* 2: COM3 (See FAR[7:6]) */
-								/* 3: COM4 (See FAR[7:6]) */
-#define	FAR_UART1_COM1		0x00 
-#define     FAR_UART2_ADDR_MASK				0x30	/* Select Serial Port 2 Address */
-								/* 0: COM1 [0x3F8..0x3FF] */
-								/* 1: COM2 [0x2F8..0x2FF] */
-								/* 2: COM3 (See FAR[7:6]) */
-								/* 3: COM4 (See FAR[7:6]) */
-#define	FAR_UART2_COM2		0x10
-#define     FAR_EXTENDED_UART_ADDR_SELECT		0xC0	/* Extended Address Selects */
-								/*    COM3@IRQ4,  COM4@IRQ3 */
-								/* 0: COM3@0x3E8, COM4@0x2E8 */
-								/* 1: COM3@0x338, COM4@0x238 */
-								/* 2: COM3@0x2E8, COM4@0x2E0 */
-								/* 3: COM3@0x220, COM4@0x228 */
-
-#define SIO_CONFIG_PTR			0x02	/* Power & Test Register */
-
-#define     PTR_POWER_DOWN				0x01	/* Power down all enabled functions */
-#define     PTR_LPT_IRQ_SELECT				0x08	/* Select LPT IRQ if (FAR[1:0] == 0) */
-								/* 0: IRQ5 */
-								/* 1: IRQ7 */
-#define     PTR_UART1_TEST_MODE				0x10	/* Set serial port 1 test mode */
-#define     PTR_UART2_TEST_MODE				0x20	/* Set serial port 2 test mode */
-#define     PTR_LOCK_CONFIGURATION			0x40	/* Prevent all further config writes */
-								/* Only a RESET will reenable writes */
-#define     PTR_LPT_EXTENDED_MODE_SELECT		0x80	/* Select Mode if not EPP/ECP */
-								/* 0: Compatible Mode */
-								/* 1: Extended Mode */
-
-#define SIO_CONFIG_FCR			0x03	/* Function Control Register */
-							/* WARNING: The FCR register must be written */
-							/* using read-modify-write! */
-#define     FCR_TDR_MODE_SELECT				0x01	/* ? (floppy/tape) */
-#define     FCR_IDE_DMA_ENABLE				0x02	/* Enable IDE DMA mode */
-#define     FCR_EPP_ZERO_WAIT_STATE			0x40	/* Enable EPP zero wait state */
-
-#define SIO_CONFIG_PCR			0x04	/* Printer Control Register */
-
-#define     PCR_EPP_ENABLE				0x01	/* Enable parallel port EPP mode */
-#define     PCR_EPP_VERSION_SELECT			0x02	/* Select version of EPP mode */
-								/* 0: Version 1.7 */
-								/* 1: Version 1.9 (IEEE 1284) */
-#define     PCR_ECP_ENABLE				0x04	/* Enable parallel port ECP mode */
-#define     PCR_ECP_POWER_DOWN_CLOCK_ENABLE		0x08	/* Enable clock in power-down state */
-								/* 0: Freeze ECP clock */
-								/* 1: Run ECP clock */
-#define     PCR_ECP_INT_POLARITY_CONTROL		0x20	/* Interrupt polarity control */
-								/* 0: Level high or negative pulse */
-								/* 1: Level low or positive pulse */
-#define     PCR_ECP_INT_IO_CONTROL			0x40	/* Interrupt I/O control */
-								/* WARNING: Slightly safer to choose */
-								/* open drain if you don't know the */
-								/* exact requirements of the circuit */
-								/* 0: Totem-pole output */
-								/* 1: Open drain output */
-#define     PCR_RTC_RAM_WRITE_DISABLE			0x80	/* Disable writes to RTC RAM */
-								/* 0: Enable writes */
-								/* 1: Disable writes */
-
-#define SIO_CONFIG_KRR			0x05	/* Keyboard & RTC Control Register */
-							/* WARNING: The KRR register must be written */
-							/* with a 1 in bit 2, else the KBC will not */
-							/* work! */
-#define     KRR_KBC_ENABLE				0x01	/* Enable keyboard controller */
-#define     KRR_KBC_SPEED_CONTROL			0x02	/* Select clock divisor if !KRR[7] */
-								/* 0: Divide by 3 */
-								/* 1: Divide by 2 */
-#define	    KRR_KBC_MUST_BE_1				0x04	/* Reserved: This bit must be 1! */
-#define     KRR_RTC_ENABLE				0x08	/* Enable real time clock */
-#define     KRR_RTC_RAMSEL				0x20	/* Select RTC RAM bank */
-#define     KRR_KBC_CLOCK_SOURCE_SELECT			0x80	/* Select clock source */
-								/* 0: Use X1 clock source */
-								/* 1: Use SYSCLK clock source */
-
-#define SIO_CONFIG_PMC			0x06	/* Power Management Control Register */
-
-#define     PMC_IDE_TRISTATE_CONTROL			0x01	/* ? (power management) */
-#define     PMC_FDC_TRISTATE_CONTROL			0x02	/* ? (power management) */
-#define     PMC_UART1_TRISTATE_CONTROL			0x04	/* ? (power management) */
-#define     PMC_SELECTIVE_LOCK				0x20	/* ? (power management) */
-#define     PMC_LPT_TRISTATE_CONTROL			0x40	/* ? (power management) */
-
-#define SIO_CONFIG_TUP			0x07	/* Tape, UARTS & Parallel Port Register */
-
-#define     TUP_EPP_TIMEOUT_INT_ENABLE			0x04	/* Enable EPP timeout interrupts */
-
-#define SIO_CONFIG_SID			0x08	/* Super I/O Identification Register */
-
-#define     SID_ID_MASK					0xF8	/* Super I/O ID field */
-#define         SID_ID_PC87306					0x70	/* PC87306 ID value */
-
-#define SIO_CONFIG_ASC			0x09	/* Advanced Super I/O Config Register */
-							/* WARNING: The ASC register must be written */
-							/* with a 0 in bit 3! */
-							/* WARNING: The ASC register resets to 1 in */
-							/* bit 7 (PC/AT mode)! */
-#define     ASC_VLD_MASK				0x03	/* ? (floppy/tape) */
-#define     ASC_ENHANCED_TDR_SUPPORT			0x04	/* ? (floppy/tape) */
-#define     ASC_MUST_BE_0				0x08	/* Reserved: Must be 0 */
-#define     ASC_ECP_CNFGA				0x20	/* ? */
-#define     ASC_DENSEL_POLARITY_BIT			0x40	/* ? (floppy/tape) */
-#define     ASC_SYSTEM_OPERATION_MODE			0x80	/* Select system operation mode */
-								/* 0: PS/2 mode */
-								/* 1: PC/AT mode */
-
-#define SIO_CONFIG_CS0LA			0x0A	/* Chip Select 0 Low Address Register */
-
-#define SIO_CONFIG_CS0CF			0x0B	/* Chip Select 0 Configuration Register */
-							/* WARNING: The CS0CF register must be */
-							/* written with a 1 in bit 7! */
-#define     CS0CF_CS0_DECODE				0x08	/* Select CS0 decode sensitivity */
-								/* 0: Decode full 16-bit address */
-								/* 1: Decode only bits 15 thru 12 */
-#define     CS0CF_CS0_WRITE_ENABLE			0x10	/* Enable CS0 on write cycles */
-#define     CS0CF_CS0_READ_ENABLE			0x20	/* Enable CS0 on read cycles */
-#define     CS0CF_CS0_MUST_BE_1				0x80	/* Reserved: Must be 1 */
-
-#define SIO_CONFIG_CS1LA			0x0C	/* Chip Select 1 Low Address Register */
-
-#define SIO_CONFIG_CS1CF			0x0D	/* Chip Select 1 Configuration Register */
-
-#define     CS1CF_CS1_DECODE				0x08	/* Select CS1 decode sensitivity */
-								/* 0: Decode full 16-bit address */
-								/* 1: Decode only bits 15 thru 12 */
-#define     CS1CF_CS1_WRITE_ENABLE			0x10	/* Enable CS1 on write cycles */
-#define     CS1CF_CS1_READ_ENABLE			0x20	/* Enable CS1 on read cycles */
-
-#define SIO_CONFIG_IRC			0x0E	/* Infrared Configuration Register */
-
-#define     IRC_UART2_INTERFACE_MODE			0x01	/* Select UART2 interface mode */
-								/* 0: Normal (modem) mode */
-								/* 1: IR mode */
-#define     IRC_IR_FULL_DUPLEX				0x02	/* Select IR duplex mode */
-								/* 0: Full duplex mode */
-								/* 1: Half duplex mode */
-#define     IRC_ENCODED_IR_TRANSMITTER_DRIVE		0x10	/* IR transmitter drive control */
-								/* 0: IRTX active for 1.6usec */
-								/* 1: IRTX active for 3/16 baud */
-#define     IRC_ENCODED_IR_MODE				0x20	/* IR encode mode */
-								/* 0: Encoded mode */
-								/* 1: Non-encoded mode */
-
-#define SIO_CONFIG_GPBA			0x0F	/* GP I/O Port Base Address Config Register */
-
-#define SIO_CONFIG_CS0HA			0x10	/* Chip Select 0 High Address Register */
-
-#define SIO_CONFIG_CS1HA			0x11	/* Chip Select 1 High Address Register */
-
-#define SIO_CONFIG_SCF0			0x12	/* Super I/O Configuration Register 0 */
-
-#define     SCF0_RTC_RAM_LOCK				0x01	/* Lock (1) will prevent all further */
-								/* accesses to RTC RAM.  Only RESET */
-								/* return this bit to a 0. */
-#define     SCF0_IRQ1_12_LATCH_ENABLE			0x02	/* Enable IRQ1/IRQ12 latching */
-#define     SCF0_IRQ12_TRISTATE				0x04	/* IRQ12 tri-state control */
-								/* 0: Use quasi-bidirectional buffer */
-								/* 1: Tri-state IRQ12 */
-#define     SCF0_UART2_TRISTATE				0x08	/* Force UART2/IR outputs to */
-								/* tri-state when disabled */
-#define     SCF0_GPIO_PORT1_ENABLE			0x10	/* Enable GPIO port 1 */
-#define     SCF0_GPIO_PORT2_ENABLE			0x20	/* Enable GPIO port 2 */
-
-#define SIO_CONFIG_SCF1			0x18	/* Super I/O Configuration Register 1 */
-
-#define     SCF1_REPORTED_ECP_DMA			0x06	/* Reported ECP DMA number */
-								/* 0: Jumpered 8-bit DMA */
-								/* 1: DMA channel 1 */
-								/* 2: DMA channel 2 */
-								/* 3: DMA channel 3 */
-#define     SCF1_SELECTED_ECP_DMA			0x08	/* Selected ECP DMA pins */
-								/* 0: PDRQ0 & PDACK0 */
-								/* 1: PDRQ1 & PDACK1 */
-#define     SCF1_SCRATCH_BITS				0xC0	/* ? */
-
-#define SIO_CONFIG_LPTBA			0x19	/* LPT Base Address */
-
-#define SIO_CONFIG_PNP0			0x1B	/* Plug & Play Configuration Register 0 */
-
-#define     PNP0_LPT_INT_SELECT_CONTROL			0x10	/* LPT IRQ select control */
-								/* 0: IRQ selected by FAR[1:0] */
-								/* 1: IRQ selected by PNP0[5] */
-#define     PNP0_LPT_INT_MAPPING			0x20	/* LPT IRQ mapping */
-								/* 0: IRQ5 */
-								/* 1: IRQ7 */
-#define     PNP0_LPTA_BASE_ADDR_SELECT			0x40	/* LPTA base address */
-								/* 0: Always 0x3BC */
-								/* 1: Selected by LPTBA[7:0] */
-
-#define SIO_CONFIG_PNP1			0x1C	/* Plug & Play Configuration Register 1 */
-
-#define     PNP1_UARTS_INT_SELECT_CONTROL		0x01	/* UART interrupt select control */
-								/* 0: Use FAR[3:2] & FAR[5:4] */
-								/* 1: Use PNP1[2] & PNP1[6] */
-#define     PNP1_UART1_INT_MAPPING			0x04	/* UART1 interrupt mapping */
-								/* 0: IRQ3 */
-								/* 1: IRQ4 */
-#define     PNP1_UART2_INT_MAPPING			0x40	/* UART2 interrupt mapping */
-								/* 0: IRQ3 */
-								/* 1: IRQ4 */
-/*---------------------------------------------------------------------------*/
-
-/*
- * Definitions for the SuperIO UART.
- */
-#define COM1_PORT       0x3f8   
-#define COM2_PORT       0x2f8
-
-/*
- * Register offsets.
- */
-#define UART_RX    		0      /* Receive port, read only */
-#define UART_TX         0      /* transmit port, write only */
-#define UART_IER        1      /* Interrupt enable, read/write */
-#define UART_IIR        2      /* Interrupt id, read only */
-#define UART_FIFO_CONTROL 2    /* FIFO control, write only */
-#define UART_LCR        3      /* Line control register */
-#define UART_MCR      	4      /* Modem control register */
-#define UART_LSR        5      /* Line Status register */
-#define UART_MSR        6      /* Modem Status register */
-
-/* with the DLAB bit set, the first two registers contain the baud rate */
-#define UART_DLLSB      0
-#define UART_DLMSB      1
-
-/*
- * Line control register 
- */
-#define LCR_DB          3      /* Data bits in transmission (0 = 5, 1 = 6, 2 = 7, 3 = 8) */
-#define LCR_SB          4      /* Stop bit */
-#define LCR_PE          8      /* Parity enable */
-#define LCR_EP          16     /* Even parity */
-#define LCR_SP          32     /* Stick parity */
-#define LCR_BC          64     /* break control */
-#define LCR_DLAB        128    /* Divisor latch access bit */
-
-
-/*
- *  Modem Control register
- */
-#define MCR_DTR			1	/* Data Terminal Ready */
-#define MCR_RTS			2	/* Request To Send */
-#define MCR_OUT1		4	/* Out1 (not used) */
-#define MCR_IRQ_ENABLE  8	/* Enable IRQ */
-#define MCR_LOOP		16	/* Loopback mode */
-
-/*
- * Line status bits.
- */
-#define    LSR_DR     0x01        /* Data ready                         */
-#define    LSR_OE     0x02        /* Overrun error                      */
-#define    LSR_PE     0x04        /* Parity error                       */
-#define    LSR_FE     0x08        /* Framing error                      */
-#define    LSR_BI     0x10        /* Break interrupt                    */
-#define    LSR_THRE   0x20        /* Transmitter holding register empty */
-#define    LSR_TEMT   0x40        /* Transmitter empty                  */
-#define    LSR_FFE    0x80        /* Receiver FIFO error                */
-
-#define LSR_ERROR       (LSR_OE | LSR_PE | LSR_FE) 
-
-/*
- * Interrupt Identification register (IIR)
- */
-#define IIR_IP          1     /* No Interrupt pending */
-#define IIR_RECEIVE_LINE_STATUS	6 /* Overrun, Parity, Framing erros, Break */
-#define IIR_RDA			4     /* Receive data available */
-#define IIR_FIFO_FLAG	8     /* FIFO flag */
-#define IIR_FIFO_TIMEOUT (IIR_RDA+IIR_FIFO_FLAG)  /* Got data some time ago, but FIFO time out */
-#define IIR_THRE		2     /* Transmitter holding register empty. */
-#define IIR_MS			0     /* CTS, DSR, RING, DCD changed */
-#define IIR_HPIP        6     /* Highest priority interrupt pending */
-
-/*
- * Interrupt enable register (IER)
- */
-#define IER_RDA         1     /* Received data available */
-#define IER_THRE        2     /* Transmitter holding register empty */
-#define IER_RLS         4     /* Receiver line status */
-#define IER_MS          8     /* Modem status */
-
-/*
- * PC87306 Parallel I/O Port
- */
-#define LPT1_PORT		0x03BC
-
-/*
- * PC87306 General Purpose I/O Ports
- */
-#define GPIO1_PORT		0x0078
-#define GPIO2_PORT		0x0079
-
-/*
- * PC87306 IDE Port
- */
-#define IDE_PORT_1		0x01F0
-#define IDE_PORT_2		0x03F6
-#define IDE_PORT_3		0x03F7
-
-/*
- * PC87306 Floppy Port
- */
-#define FDC_PORT		0x03F0
-
-/*
- * PC87306 Real Time Clock/battery backed up RAM port
- */
-#define RTC_INDEX_PORT		0x0070
-#define RTC_DATA_PORT		0x0071
-
-/*
- * Offsets in RTC memory (RAMSEL = 0)
- */
-#define RTC_SECONDS			0
-#define	RTC_SECONDS_ALARM	1
-#define RTC_MINUTES			2
-#define RTC_MINUTES_ALARM	3
-#define RTC_HOURS			4
-#define RTC_HOURS_ALARM		5
-#define RTC_DAY_OF_WEEK		6
-#define RTC_DAY_OF_MONTH	7
-#define RTC_MONTH			8
-#define RTC_YEAR			9
-#define RTC_CONTROL_A		0xA
-#define RTC_CONTROL_B		0xB
-#define RTC_CONTROL_C		0xC
-#define RTC_CONTROL_D		0xD
-
-#define RTC_NVRAM0_START	0xE
-#define RTC_NVRAM0_SIZE		114
-#define RTC_NVRAM1_START	0
-#define RTC_NVRAM1_SIZE		128
-#define	RTC_NVRAM_SIZE		(RTC_NVRAM0_SIZE+RTC_NVRAM1_SIZE)
-
-#define RTC_PWNVRAM_START	0x38	/* Start of protected NVRAM */
-#define RTC_PWNVRAM_SIZE	8		/* Size of protected NVRAM */
-
-
-/*
- * PC87306 Keyboard controller ports
- */
-#define KEYBD_DATA_PORT		0x0060
-#define KEYBD_CTRL_PORT 	0x0064
--- a/os/boot/puma/qio.c
+++ /dev/null
@@ -1,128 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-struct Queue {
-	Block*	first;
-	Block*	last;
-	void	(*kick)(void*);
-	void*	arg;
-	long	len;
-};
-
-Block *
-iallocb(int n)
-{
-	Block *b;
-
-	b = (Block*)malloc(sizeof(Block)+n);
-	b->data = (uchar*)b + sizeof(Block);
-	b->rp = b->wp = b->data;
-	b->lim = b->data + n;
-	b->next = 0;
-	b->magic = 0xcafebee0;
-	return b;
-}
-
-void
-freeb(Block *b)
-{
-	if(b){
-		if(b->magic != 0xcafebee0)
-			panic("freeb");
-		b->magic = 0;
-		b->next = (Block*)0xdeadbabe;
-		free(b);
-	}
-}
-
-Queue *
-qopen(int limit, int msg, void (*kick)(void*), void *arg)
-{
-	Queue *q;
-
-	USED(limit, msg);
-	q = (Queue*)malloc(sizeof(Queue));
-	q->first = q->last = 0;
-	q->kick = kick;
-	q->arg = arg;
-	q->len = 0;
-	return q;
-}
-
-Block *
-qget(Queue *q)
-{
-	int s;
-	Block *b;
-
-	s = splhi();
-	if((b = q->first) != 0){
-		q->first = b->next;
-		b->next = 0;
-		q->len -= BLEN(b);
-		if(q->len < 0)
-			panic("qget");
-	}
-	splx(s);
-	return b;
-}
-
-void
-qbwrite(Queue *q, Block *b)
-{
-	int s;
-
-	s = splhi();
-	b->next = 0;
-	if(q->first == 0)
-		q->first = b;
-	else
-		q->last->next = b;
-	q->last = b;
-	q->len += BLEN(b);
-	splx(s);
-	if(q->kick)
-		q->kick(q->arg);
-}
-
-long
-qlen(Queue *q)
-{
-	return q->len;
-}
-
-int
-qbgetc(Queue *q)
-{
-	Block *b;
-	int s, c;
-
-	c = -1;
-	s = splhi();
-	while(c < 0 && (b = q->first) != nil){
-		if(b->rp < b->wp){
-			c = *b->rp++;
-			q->len--;
-		}
-		if(b->rp >= b->wp){
-			q->first = b->next;
-			b->next = nil;
-		}
-	}
-	splx(s);
-	return c;
-}
-
-void
-qbputc(Queue *q, int c)
-{
-	Block *b;
-
-	b = iallocb(1);
-	*b->wp++ = c;
-	qbwrite(q, b);
-}
--- a/os/boot/puma/rmap.c
+++ /dev/null
@@ -1,104 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-
-void
-mapinit(RMap *rmap, Map *map, int size)
-{
-	lock(rmap);
-	rmap->map = map;
-	rmap->mapend = map+(size/sizeof(Map));
-	unlock(rmap);
-}
-
-void
-mapfree(RMap* rmap, ulong addr, int size)
-{
-	Map *mp;
-	ulong t;
-
-	if(size <= 0)
-		return;
-
-	lock(rmap);
-	for(mp = rmap->map; mp->addr <= addr && mp->size; mp++)
-		;
-
-	if(mp > rmap->map && (mp-1)->addr+(mp-1)->size == addr){
-		(mp-1)->size += size;
-		if(addr+size == mp->addr){
-			(mp-1)->size += mp->size;
-			while(mp->size){
-				mp++;
-				(mp-1)->addr = mp->addr;
-				(mp-1)->size = mp->size;
-			}
-		}
-	}
-	else{
-		if(addr+size == mp->addr && mp->size){
-			mp->addr -= size;
-			mp->size += size;
-		}
-		else do{
-			if(mp >= rmap->mapend){
-				print("mapfree: %s: losing 0x%uX, %d\n",
-					rmap->name, addr, size);
-				break;
-			}
-			t = mp->addr;
-			mp->addr = addr;
-			addr = t;
-			t = mp->size;
-			mp->size = size;
-			mp++;
-		}while(size = t);
-	}
-	unlock(rmap);
-}
-
-ulong
-mapalloc(RMap* rmap, ulong addr, int size, int align)
-{
-	Map *mp;
-	ulong maddr, oaddr;
-
-	lock(rmap);
-	for(mp = rmap->map; mp->size; mp++){
-		maddr = mp->addr;
-
-		if(addr){
-			if(maddr > addr)
-				continue;
-			if(addr+size > maddr+mp->size)
-				break;
-			maddr = addr;
-		}
-
-		if(align > 0)
-			maddr = ((maddr+align-1)/align)*align;
-		if(mp->addr+mp->size-maddr < size)
-			continue;
-
-		oaddr = mp->addr;
-		mp->addr = maddr+size;
-		mp->size -= maddr-oaddr+size;
-		if(mp->size == 0){
-			do{
-				mp++;
-				(mp-1)->addr = mp->addr;
-			}while((mp-1)->size = mp->size);
-		}
-
-		unlock(rmap);
-		if(oaddr != maddr)
-			mapfree(rmap, oaddr, maddr-oaddr);
-
-		return maddr;
-	}
-	unlock(rmap);
-
-	return 0;
-}
--- a/os/boot/puma/squeeze.h
+++ /dev/null
@@ -1,34 +1,0 @@
-
-/*
- * squeezed file format:
- *	Sqhdr
- *	original Exec header
- *	two Squeeze tables
- *	squeezed segment
- *	unsqueezed segment, if any
- */
-#define	SQMAGIC	(ulong)0xFEEF0F1E
-
-typedef struct Sqhdr Sqhdr;
-struct Sqhdr {
-	uchar	magic[4];	/* SQMAGIC */
-	uchar	text[4];	/* squeezed length of text (excluding tables) */
-	uchar	data[4];	/* squeezed length of data (excluding tables) */
-	uchar	asis[4];	/* length of unsqueezed segment */
-	uchar	toptxt[4];	/* value for 0 encoding in text */
-	uchar	topdat[4];	/* value for 0 encoding in data */
-	uchar	sum[4];	/* simple checksum of unsqueezed data */
-	uchar	flags[4];
-};
-#define	SQHDRLEN	(8*4)
-
-/*
- * certain power instruction types are rearranged by sqz
- * so as to move the variable part of the instruction word to the
- * low order bits.  note that the mapping is its own inverse.
- */
-#define	QREMAP(X)\
-	switch((X)>>26){\
-	case 19: case 31: case 59: case 63:\
-		(X) = (((X) & 0xFC00F801) | (((X)>>15)&0x7FE) | (((X)&0x7FE)<<15));\
-	}
--- a/os/boot/puma/sum.c
+++ /dev/null
@@ -1,13 +1,0 @@
-int
-sum(int a, int b, int c)
-{
-	return a+b+c;
-}
-
-void
-main(void)
-{
-	int s;
-
-	s = sum(1, 2, 3);
-}
--- a/os/boot/puma/trap.c
+++ /dev/null
@@ -1,190 +1,0 @@
-#include "boot.h"
-
-typedef struct IrqEntry {
-		void	(*r)(Ureg*, void*);
-		void 	*a;				
-} IrqEntry;
-
-IrqEntry Irq[V_MAXNUM+1];
-
-static void dumpstk(ulong *);
-void dumpregs(Ureg* ureg);
-
-void
-setvec(int v, void (*f)(Ureg*, void*), void* a)
-{
-	if(v < 0 || v >= V_MAXNUM)
-		panic("setvec: interrupt source %d out of range\n", v);
-	Irq[v].r = f;
-	Irq[v].a = a;
-}
-
-ulong irqstack[64];
-ulong fiqstack[64];
-ulong abtstack[64];
-ulong undstack[64];
-
-static void
-safeintr(Ureg*, void *a)
-{
-	int v = (int)a;
-//	print("spurious interrupt %d\n", v);
-	USED(v);
-}
-
-void
-trapinit(void)
-{
-	int offset;
-	ulong op;
-	int v;
-	int s;
-
-	s = splhi();
-
-	/* set up stacks for various exceptions */ 
-	setr13(PsrMirq, irqstack+nelem(irqstack)-1);
-	setr13(PsrMfiq, fiqstack+nelem(fiqstack)-1);
-	setr13(PsrMabt, abtstack+nelem(abtstack)-1);
-	setr13(PsrMund, undstack+nelem(undstack)-1);
-
-	for(v = 0; v <= V_MAXNUM; v++) {
-		Irq[v].r = safeintr;
-		Irq[v].a = (void *)v;
-	}
-
-	/* Reset Exception */
-	offset = ((((ulong) _vsvccall) - 0x0)-8) >> 2;
-	op = ( 0xea << 24 ) | offset;
-	*((ulong *) 0x0) = op; 
-
-	/* Undefined Instruction Exception */
-	offset = ((((ulong) _vundcall) - 0x4)-8) >> 2;
-	op = ( 0xea << 24 ) | offset;
-	*((ulong *) 0x4) = op;
-
-	/* SWI Exception */
-	offset = ((((ulong) _vsvccall) - 0x8)-8) >> 2;
-	op = ( 0xea << 24 ) | offset;
-	*((ulong *) 0x8) = op;
-
-	/* Prefetch Abort Exception */
-	offset = ((((ulong) _vpabcall) - 0xc)-8) >> 2;
-	op = ( 0xea << 24 ) | offset;
-	*((ulong *) 0xc) = op;
-
-	/* Data Abort Exception */
-	offset = ((((ulong) _vdabcall) - 0x10)-8) >> 2;
-	op = ( 0xea << 24 ) | offset;
-	*((ulong *) 0x10) = op;
-
-	/* IRQ Exception */
- 	offset = ((((ulong) _virqcall) - 0x18)-8) >> 2;
-	op = ( 0xea << 24 ) | offset;
-	*((ulong *) 0x18) = op;
-
-	/* FIQ Exception */
- 	offset = ((((ulong) _vfiqcall) - 0x1c)-8) >> 2;
-	op = ( 0xea << 24 ) | offset;
-	*((ulong *) 0x1c) = op;
-
-
-	flushIcache();
-	writeBackDC();
-	flushDcache();
-	flushIcache();
-	drainWBuffer();
-
-	splx(s);
-}
-
-/*
- *  trap is called splhi().
- */
-
-void
-trap(Ureg* ureg)
-{
-	ushort mask;
-	IrqEntry *ip;
-
-	/*
-	 * All interrupts/exceptions should be resumed at ureg->pc-4,
-	 * except for Data Abort which resumes at ureg->pc-8.
-	 */
-	ureg->pc -= 4;
-
-	switch(ureg->type) {
-	case PsrMirq:				/* Interrupt Request */
-		mask = *(uchar*)HARI1 | ((*(uchar*)HARI2) << 8);
-		ip = Irq;
-		while (mask != 0) {
-			if(mask&1)
-				ip->r(ureg, ip->a);
-			ip++;
-			mask >>= 1;
-		}
-		break;
-
-	case PsrMfiq:					/* FIQ */
-		mask = *(uchar*)HARI1 & HARI1_FIQ_MASK;
-		ip = Irq;
-		while (mask != 0) {
-			if(mask&1)
-				ip->r(ureg, ip->a);
-			ip++;
-			mask >>= 1;
-		}
-		break;
-
-	case PsrMund:			/* Undefined instruction */
-		dumpregs(ureg);
-		panic("Undefined Instruction Exception\n");
-		break;
-
-	case PsrMsvc:				/* Jump through 0 or SWI  */
-		dumpregs(ureg);
-		panic("SVC/SWI Exception\n");
-		break;
-
-	case PsrMabt:					/* Prefetch abort */
-		ureg->pc -= 4;
-		/* FALLTHROUGH */
-
-	case PsrMabt+1:	{				/* Data abort */
-		uint far =0;
-		uint fsr =0;
-
-		USED(far,fsr);
-		fsr = 0;	/*mmuregr(CpFSR);*/
-		far = 0;	/*mmuregr(CpFAR);	*/
-		if (ureg->type == PsrMabt)
-			print("Prefetch Abort/");
-		print("Data Abort\n");
-		
-		print("Data Abort: FSR %8.8uX FAR %8.8uX\n", fsr, far);
-		/* FALLTHROUGH */
-	}
-	default:
-		dumpregs(ureg);
-		panic("exception %uX\n", ureg->type);
-		break;
-	}
-
-	splhi();
-}
-
-void
-dumpregs(Ureg* ureg)
-{
-	print("PSR %8.8uX type %2.2uX PC %8.8uX LINK %8.8uX\n",
-		ureg->psr, ureg->type, ureg->pc, ureg->link);
-	print("R14 %8.8uX R13 %8.8uX R12 %8.8uX R11 %8.8uX R10 %8.8uX\n",
-		ureg->r14, ureg->r13, ureg->r12, ureg->r11, ureg->r10);
-	print("R9  %8.8uX R8  %8.8uX R7  %8.8uX R6  %8.8uX R5  %8.8uX\n",
-		ureg->r9, ureg->r8, ureg->r7, ureg->r6, ureg->r5);
-	print("R4  %8.8uX R3  %8.8uX R2  %8.8uX R1  %8.8uX R0  %8.8uX\n",
-		ureg->r4, ureg->r3, ureg->r2, ureg->r1, ureg->r0);
-	print("Stack is at: %8.8uX\n", ureg);
-/*	print("CPSR %8.8uX SPSR %8.8uX\n", cpsrr(), spsrr());*/
-}
--- a/os/boot/puma/ureg.h
+++ /dev/null
@@ -1,22 +1,0 @@
-typedef struct Ureg {
-	uint	r0;
-	uint	r1;
-	uint	r2;
-	uint	r3;
-	uint	r4;
-	uint	r5;
-	uint	r6;
-	uint	r7;
-	uint	r8;
-	uint	r9;
-	uint	r10;
-	uint	r11;
-	uint	r12;
-	uint	r13;
-	uint	r14;
-	uint	link;
-	uint	type;
-	uint	psr;
-//	uint	sp;
-	uint	pc;
-} Ureg;
--- a/os/boot/puma/zqs.c
+++ /dev/null
@@ -1,216 +1,0 @@
-#include "boot.h"
-#include "squeeze.h"
-
-#define	EXECHDRLEN	(8*4)
-
-typedef struct Squeeze Squeeze;
-struct Squeeze {
-	int	n;
-	ulong	tab[7*256];
-};
-
-#define	GET4(p)	(((((((p)[0]<<8)|(p)[1])<<8)|(p)[2])<<8)|(p)[3])
-
-/*
- * for speed of unsqueezing from Flash, certain checks are
- * not done inside the loop (as they would be in the unsqueeze program zqs),
- * but instead the checksum is expected to catch corrupted files.
- * in fact the Squeeze array bounds can't be exceeded in practice
- * because the tables are always full for a squeezed kernel.
- */
-enum {
-	QFLAG = 1,	/* invert powerpc-specific code transformation */
-	CHECK = 0,	/* check precise bounds in Squeeze array (otherwise checksum detects error) */
-};
-
-static	ulong	chksum;
-static	int	rdtab(Block*, Squeeze*, int);
-static	ulong*	unsqueeze(ulong*, uchar*, uchar*, Squeeze*, Squeeze*, ulong);
-static	uchar*	unsqzseg(uchar*, Block*, long, long, char*);
-static	Alarm*	unsqzal;
-
-int
-issqueezed(uchar *b)
-{
-	return GET4(b) == SQMAGIC? GET4(b+SQHDRLEN): 0;
-}
-
-static void
-unsqzdot(void*)
-{
-	unsqzal = alarm(500, unsqzdot, nil);
-	print(".");
-}
-
-long
-unsqueezef(Block *b, ulong *entryp)
-{
-	uchar *loada, *wp;
-	ulong toptxt, topdat, oldsum;
-	long asis, nst, nsd;
-	Sqhdr *sqh;
-	Exec *ex;
-
-	if(BLEN(b) < SQHDRLEN+EXECHDRLEN)
-		return -1;
-	sqh = (Sqhdr*)b->rp;
-	if(GET4(sqh->magic) != SQMAGIC)
-		return -1;
-	chksum = 0;
-	toptxt = GET4(sqh->toptxt);
-	topdat = GET4(sqh->topdat);
-	oldsum = GET4(sqh->sum);
-	asis = GET4(sqh->asis);
-	nst = GET4(sqh->text);
-	nsd = GET4(sqh->data);
-	b->rp += SQHDRLEN;
-	ex = (Exec*)b->rp;
-	if(GET4(ex->magic) != E_MAGIC){
-		print("zqs: not StrongARM executable\n");
-		return -1;
-	}
-	*entryp = GET4(ex->entry);
-	b->rp += EXECHDRLEN;
-	loada = KADDR(PADDR(*entryp));
-	wp = unsqzseg(loada, b, nst, toptxt, "text");
-	if(wp == nil){
-		print("zqs: format error\n");
-		return -1;
-	}
-	if(nsd){
-		wp = (uchar*)PGROUND((ulong)wp);
-		wp = unsqzseg(wp, b, nsd, topdat, "data");
-		if(wp == nil){
-			print("zqs: format error\n");
-			return -1;
-		}
-	}
-	if(asis){
-		memmove(wp, b->rp, asis);
-		wp += asis;
-		b->rp += asis;
-	}
-	if(chksum != oldsum){
-		print("\nsqueezed kernel: checksum error: %8.8lux need %8.8lux\n", chksum, oldsum);
-		return -1;
-	}
-	return wp-loada;
-}
-
-static uchar *
-unsqzseg(uchar *wp, Block *b, long ns, long top, char *what)
-{
-	static Squeeze sq3, sq4;
-
-	print("unpack %s %8.8lux %lud:", what, wp, ns);
-	if(ns == 0)
-		return wp;
-	if(rdtab(b, &sq3, 0) < 0)
-		return nil;
-	if(rdtab(b, &sq4, 8) < 0)
-		return nil;
-	if(BLEN(b) < ns){
-		print(" **size error\n");
-		return nil;
-	}
-	unsqzal = alarm(500, unsqzdot, nil);
-	wp = (uchar*)unsqueeze((ulong*)wp, b->rp, b->rp+ns, &sq3, &sq4, top);
-	cancel(unsqzal);
-	unsqzal = nil;
-	print("\n");
-	if(wp == nil){
-		print("zqs: corrupt squeezed data stream\n");
-		return nil;
-	}
-	b->rp += ns;
-	return wp;
-}
-
-static ulong*
-unsqueeze(ulong *wp, uchar *rp, uchar *ep, Squeeze *sq3, Squeeze *sq4, ulong top)
-{
-	ulong nx, csum;
-	int code, n;
-
-	if(QFLAG){
-		QREMAP(top);	/* adjust top just once, outside the loop */
-	}
-	csum = chksum;
-	while(rp < ep){
-		/* no function calls within this loop for speed */
-		code = *rp;
-		rp++;
-		n = 0;
-		nx = code>>4;
-		do{
-			if(nx == 0){
-				nx = top;
-			}else{
-				if(nx==1){
-					nx = (((((rp[3]<<8)|rp[2])<<8)|rp[1])<<8)|rp[0];
-					rp += 4;
-				}else if(nx <= 8){	/* 2 to 8 */
-					nx = ((nx-2)<<8) | rp[0];
-					if(CHECK && nx >= sq4->n)
-						return nil;	/* corrupted file */
-					nx = sq4->tab[nx] | rp[1];
-					rp += 2;
-				}else{	/* 9 to 15 */
-					nx = ((nx-9)<<8) | rp[0];
-					if(CHECK && nx >= sq3->n)
-						return nil;	/* corrupted file */
-					nx = sq3->tab[nx];
-					rp++;
-				}
-				if(rp > ep)
-					return nil;	/* corrupted file */
-				if(QFLAG){
-					QREMAP(nx);
-				}
-			}
-			*wp = nx;
-			wp++;
-			csum += nx;
-			nx = code & 0xF;
-		}while(++n == 1);
-	}
-	chksum = csum;
-	return wp;
-}
-
-static int
-rdtab(Block *b, Squeeze *sq, int shift)
-{
-	uchar *p, *ep;
-	ulong v, w;
-	int i;
-
-	if(BLEN(b) < 2)
-		return -1;
-	i = (b->rp[0]<<8) | b->rp[1];
-	if(1)
-		print(" T%d", i);
-	b->rp += 2;
-	if((i -= 2) > 0){
-		if(BLEN(b) < i)
-			return -1;
-	}
-	sq->n = 0;
-	p = b->rp;
-	ep = b->rp+i;
-	b->rp += i;
-	v = 0;
-	while(p < ep){
-		w = 0;
-		do{
-			if(p >= ep)
-				return -1;
-			w = (w<<7) | (*p & 0x7F);
-		}while(*p++ & 0x80);
-		v += w;
-		if(0)
-			print("%d %8.8lux %8.8lux\n", sq->n, v, w);
-		sq->tab[sq->n++] = v<<shift;
-	}
-	return 0;
-}
--- a/os/boot/rpcg/NOTICE
+++ /dev/null
@@ -1,3 +1,0 @@
-Inferno® Copyright © 1996-1999 Lucent Technologies Inc.  All rights reserved.
-PowerPC support Copyright © 1995-1997 C H Forsyth (forsyth@caldo.demon.co.uk).  All rights reserved.
-MPC8xx Inferno PowerPC port Copyright © 1998-2003 Vita Nuova Holdings Limited.  All rights reserved.
--- a/os/boot/rpcg/alarm.c
+++ /dev/null
@@ -1,123 +1,0 @@
-#include	"u.h"
-#include	"lib.h"
-#include	"mem.h"
-#include	"dat.h"
-#include	"fns.h"
-#include	"io.h"
-#define	MAXALARM	10
-
-Alarm	alarmtab[MAXALARM];
-
-/*
- * Insert new into list after where
- */
-void
-insert(List **head, List *where, List *new)
-{
-	if(where == 0){
-		new->next = *head;
-		*head = new;
-	}else{
-		new->next = where->next;
-		where->next = new;
-	}
-		
-}
-
-/*
- * Delete old from list.  where->next is known to be old.
- */
-void
-delete(List **head, List *where, List *old)
-{
-	if(where == 0){
-		*head = old->next;
-		return;
-	}
-	where->next = old->next;
-}
-
-Alarm*
-newalarm(void)
-{
-	int i;
-	Alarm *a;
-
-	for(i=0,a=alarmtab; i < nelem(alarmtab); i++,a++)
-		if(a->busy==0 && a->f==0){
-			a->f = 0;
-			a->arg = 0;
-			a->busy = 1;
-			return a;
-		}
-	panic("newalarm");
-	return 0;	/* not reached */
-}
-
-Alarm*
-alarm(int ms, void (*f)(Alarm*), void *arg)
-{
-	Alarm *a, *w, *pw;
-	ulong s;
-
-	if(ms < 0)
-		ms = 0;
-	s = splhi();
-	a = newalarm();
-	a->dt = MS2TK(ms);
-	a->f = f;
-	a->arg = arg;
-	pw = 0;
-	for(w=m->alarm; w; pw=w, w=w->next){
-		if(w->dt <= a->dt){
-			a->dt -= w->dt;
-			continue;
-		}
-		w->dt -= a->dt;
-		break;
-	}
-	insert(&m->alarm, pw, a);
-	splx(s);
-	return a;
-}
-
-void
-cancel(Alarm *a)
-{
-	a->f = 0;
-}
-
-void
-alarminit(void)
-{
-}
-
-#define NA 10		/* alarms per clock tick */
-void
-checkalarms(void)
-{
-	int i, n, s;
-	Alarm *a;
-	void (*f)(Alarm*);
-	Alarm *alist[NA];
-
-	s = splhi();
-	a = m->alarm;
-	if(a){
-		for(n=0; a && a->dt<=0 && n<NA; n++){
-			alist[n] = a;
-			delete(&m->alarm, 0, a);
-			a = m->alarm;
-		}
-		if(a)
-			a->dt--;
-
-		for(i = 0; i < n; i++){
-			f = alist[i]->f;	/* avoid race with cancel */
-			if(f)
-				(*f)(alist[i]);
-			alist[i]->busy = 0;
-		}
-	}
-	splx(s);
-}
--- a/os/boot/rpcg/all.h
+++ /dev/null
@@ -1,6 +1,0 @@
-#include	"u.h"
-#include	"lib.h"
-#include	"dat.h"
-#include	"fns.h"
-#include	"mem.h"
-#include	"io.h"
--- a/os/boot/rpcg/archrpcg.c
+++ /dev/null
@@ -1,279 +1,0 @@
-#include	"u.h"
-#include	"lib.h"
-#include	"mem.h"
-#include	"dat.h"
-#include	"fns.h"
-#include	"io.h"
-
-#include	"archrpcg.h"
-#include "etherif.h"
-
-/*
- * board-specific support for the RPCG RXLite
- */
-
-enum {
-	SYSMHZ =	66,	/* target frequency */
-
-	/* sccr */
-	RTSEL = IBIT(8),	/* =0, select main oscillator (OSCM); =1, select external crystal (EXTCLK) */
-	RTDIV = IBIT(7),	/* =0, divide by 4; =1, divide by 512 */
-	CRQEN = IBIT(9),	/* =1, switch to high frequency when CPM active */
-	PRQEN = IBIT(10),	/* =1, switch to high frequency when interrupt pending */
-
-	/* plprcr */
-	CSRC = IBIT(21),	/* =0, clock is DFNH; =1, clock is DFNL */
-};
-
-static	char	flashsig[] = "RPXsignature=1.0\nNAME=qbrpcg\nSTART=FFC20100\nVERSION=1.1\n";
-static	char*	geteeprom(char*);
-
-/*
- * called early in main.c, after machinit:
- * using board and architecture specific registers, initialise
- * 8xx registers that need it and complete initialisation of the Mach structure.
- */
-void
-archinit(void)
-{
-	IMM *io;
-	int mf, t;
-	ulong v;
-
-	v = getimmr() & 0xFFFF;
-	switch(v>>8){
-	case 0x00:	t = 0x86000; break;
-	case 0x20:	t = 0x82300; break;
-	case 0x21:	t = 0x823a0; break;
-	default:	t = 0; break;
-	}
-	m->cputype = t;
-	m->bcsr = KADDR(BCSRMEM);
-	io = m->iomem;
-	m->clockgen = 8*MHz;
-	mf = (io->plprcr >> 20)+1;	/* use timing set by bootstrap */
-	m->cpuhz = m->clockgen*mf;
-	m->bcsr[0] = DisableColTest | DisableFullDplx | DisableUSB | HighSpdUSB | LedOff;	/* first write enables bcsr regs */
-return;
-	io->plprcrk = KEEP_ALIVE_KEY;
-	io->plprcr &= ~CSRC;	/* general system clock is DFNH */
-/*	io->mptpr = 0x0800;	/* memory prescaler = 8 for refresh */
-	/* use memory refresh time set by RPXLite monitor */
-	io->plprcrk = ~KEEP_ALIVE_KEY;
-}
-
-void
-cpuidprint(void)
-{
-	int t, v;
-
-	print("Inferno bootstrap\n");
-	print("PVR: ");
-	t = getpvr()>>16;
-	switch(t){
-	case 0x01:	print("MPC601"); break;
-	case 0x03:	print("MPC603"); break;
-	case 0x04:	print("MPC604"); break;
-	case 0x06:	print("MPC603e"); break;
-	case 0x07:	print("MPC603e-v7"); break;
-	case 0x50:	print("MPC8xx"); break;
-	default:	print("PowerPC version #%x", t); break;
-	}
-	print(", revision #%lux\n", getpvr()&0xffff);
-	print("IMMR: ");
-	v = getimmr() & 0xFFFF;
-	switch(v>>8){
-	case 0x00:	print("MPC860/821"); break;
-	case 0x20:	print("MPC823"); break;
-	case 0x21:	print("MPC823A"); break;
-	default:	print("Type #%lux", v>>8); break;
-	}
-	print(", mask #%lux\n", v&0xFF);
-	print("options: #%lux\n", archoptionsw());
-	print("bcsr: %8.8lux\n", m->bcsr[0]);
-	print("PLPRCR=%8.8lux SCCR=%8.8lux\n", m->iomem->plprcr, m->iomem->sccr);
-	print("%lud MHz system\n", m->cpuhz/MHz);
-	print("\n");
-//print("%s\n", geteeprom("EA"));
-print("BR0=%8.8lux OR0=%8.8lux\n", m->iomem->memc[0].base, m->iomem->memc[0].option);
-print("MPTPR=%8.8lux\n", m->iomem->mptpr);
-}
-
-static	char*	defplan9ini[2] = {
-	/* 860/821 */
-	"ether0=type=SCC port=1 ea=0010ec000051\r\n"
-	"vgasize=640x480x8\r\n"
-	"kernelpercent=40\r\n"
-	"console=0\r\nbaud=9600\r\n",
-
-	/* 823 */
-	"ether0=type=SCC port=2 ea=0010ec000051\r\n"
-	"vgasize=640x480x8\r\n"
-	"kernelpercent=40\r\n"
-	"console=0\r\nbaud=9600\r\n",
-};
-
-char *
-archconfig(void)
-{
-	print("Using default configuration\n");
-	return defplan9ini[MPCMODEL(m->cputype) == 0x823];
-}
-
-/*
- * provide value for #r/switch (devrtc.c)
- */
-int
-archoptionsw(void)
-{
-	return (m->bcsr[0]&DipSwitchMask)>>4;
-}
-
-/*
- * invoked by clock.c:/^clockintr
- */
-static void
-twinkle(void)
-{
-	if(m->ticks%MS2TK(1000) == 0)
-		m->bcsr[0] ^= LedOff;
-}
-
-void	(*archclocktick)(void) = twinkle;
-
-/*
- * for flash.c:/^flashreset
- * retrieve flash type, virtual base and length and return 0;
- * return -1 on error (no flash)
- */
-int
-archflashreset(char *type, void **addr, long *length)
-{
-	if((m->iomem->memc[BOOTCS].base & 1) == 0)
-		return -1;		/* shouldn't happen */
-	strcpy(type, "AMD29F0x0");
-	*addr = KADDR(FLASHMEM);
-	*length = 4*1024*1024;
-	return 0;
-}
-
-int
-archether(int ctlrno, Card *ether)
-{
-	char *ea;
-
-	if(ctlrno > 0)
-		return -1;
-	strcpy(ether->type, "SCC");
-	ether->port = 2;
-	ea = geteeprom("EA");
-	if(ea != nil)
-		parseether(ether->ea, ea);
-	return 1;
-}
-
-/*
- * enable the clocks for the given SCC ether and reveal them to the caller.
- * do anything else required to prepare the transceiver (eg, set full-duplex, reset loopback).
- */
-int
-archetherenable(int cpmid, int *rcs, int *tcs)
-{
-	IMM *io;
-
-	switch(cpmid){
-	default:
-		/* no other SCCs are wired for ether on RPXLite*/
-		return -1;
-
-	case SCC2ID:
-		io = ioplock();
-		m->bcsr[0] |= EnableEnet;
-		io->papar |= SIBIT(6)|SIBIT(4);	/* enable CLK2 and CLK4 */
-		io->padir &= ~(SIBIT(6)|SIBIT(4));
-		*rcs = CLK4;
-		*tcs = CLK2;
-		iopunlock();
-		break;
-	}
-	return 0;
-}
-
-void
-archetherdisable(int id)
-{
-	USED(id);
-	m->bcsr[0] &= ~EnableEnet;
-}
-
-/*
- * do anything extra required to enable the UART on the given CPM port
- */
-void
-archenableuart(int id, int irda)
-{
-	USED(id, irda);
-}
-
-/*
- * do anything extra required to disable the UART on the given CPM port
- */
-void
-archdisableuart(int id)
-{
-	USED(id);
-}
-
-/*
- * enable/disable the LCD panel's backlight
- */
-void
-archbacklight(int on)
-{
-	USED(on);
-}
-
-static char*
-geteeprom(char *s)
-{
-	static int init;
-	static char res[64];
-	static uchar eeprom[257];
-	uchar *l, *p;
-	int i, j;
-
-	if(!init){
-		i2csetup();
-		if(i2crecv(0xa8|1|(0<<8), eeprom, 128) < 0 ||
-		   i2crecv(0xa8|1|(128<<8), eeprom+128, 128) < 0){
-			print("i2c failed\n");
-			return nil;
-		}
-		if(0){
-			print("eeprom:\n");
-			for(i=0; i<16; i++){for(j=0; j<16; j++)print(" %2.2ux[%c]", eeprom[i*16+j], eeprom[i*16+j]); print("\n");}
-		}
-		eeprom[256] = 0xFF;
-		init = 1;
-	}
-	for(l = eeprom; *l != 0xFF && *l != '\n';){
-		p = l;
-		while(*l != '\n' && *l != 0xFF && *l != '=')
-			l++;
-		if(*l == '='){
-			if(l-p == strlen(s) && strncmp(s, (char*)p, strlen(s)) == 0){
-				p = l+1;
-				while(*l != '\n' && *l != 0xFF)
-					l++;
-				memmove(res, p, l-p);
-				res[l-p] = 0;
-				return res;
-			}
-		}
-		while(*l != '\n' && *l != 0xFF)
-			l++;
-		if(*l == '\n')
-			l++;
-	}
-	return nil;
-}
--- a/os/boot/rpcg/archrpcg.h
+++ /dev/null
@@ -1,48 +1,0 @@
-/*
- * values for RPXLite AW
- */
-enum {
-	/* CS assignment */
-	BOOTCS = 0,
-	DRAM1 = 1,
-	/* CS2 is routed to expansion header */
-	BCSRCS = 3,
-	NVRAMCS = 4,
-	/* CS5 is routed to expansion header */
-	PCMCIA0CS = 6,	/* select even bytes */
-	PCMCIA1CS = 7,	/* select odd bytes */
-};
-
-/*
- * BCSR bits (there are 4 8-bit registers that we access as ulong)
- */
-enum {
-	EnableEnet =	IBIT(0),
-	EnableXcrLB=	IBIT(1),
-	DisableColTest=	IBIT(2),
-	DisableFullDplx=IBIT(3),
-	LedOff=		IBIT(4),
-	DisableUSB=	IBIT(5),
-	HighSpdUSB=	IBIT(6),
-	EnableUSBPwr=	IBIT(7),
-	/* 8,9,10 unused */
-	PCCVCCMask=	IBIT(12)|IBIT(13),
-	PCCVPPMask=	IBIT(14)|IBIT(15),
-	PCCVCC0V=	0,
-	PCCVCC5V=	IBIT(13),
-	PCCVCC3V=	IBIT(12),
-	PCCVPP0V=	0,
-	PCCVPP5V=	IBIT(14),
-	PCCVPP12V=	IBIT(15),
-	PCCVPPHiZ=	IBIT(14)|IBIT(15),
-	/* 16-23 NYI */
-	DipSwitchMask=	IBIT(24)|IBIT(25)|IBIT(26)|IBIT(27),
-	DipSwitch0=	IBIT(24),
-	DipSwitch1=	IBIT(25),
-	DipSwitch2=	IBIT(26),
-	DipSwitch3=	IBIT(27),
-	/* bit 28 RESERVED */
-	FlashComplete=	IBIT(29),
-	NVRAMBattGood=	IBIT(30),
-	RTCBattGood=	IBIT(31),
-};
--- a/os/boot/rpcg/boot.h
+++ /dev/null
@@ -1,8 +1,0 @@
-#include <u.h>
-#include "lib.h"
-
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-#include "ureg.h"
--- a/os/boot/rpcg/bootp.c
+++ /dev/null
@@ -1,509 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-#include "ip.h"
-
-#define	XPADDR(a)	((ulong)(a) & ~KSEGM)
-
-enum {
-	CHECKSUM = 1,	/* set zero if trouble booting from Linux */
-};
-
-uchar broadcast[Eaddrlen] = {
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-};
-
-static ushort tftpport = 5000;
-static int Id = 1;
-static Netaddr myaddr;
-static Netaddr server;
-
-typedef struct {
-	uchar	header[4];
-	uchar	data[Segsize];
-} Tftp;
-static Tftp tftpb;
-
-static void
-hnputs(uchar *ptr, ushort val)
-{
-	ptr[0] = val>>8;
-	ptr[1] = val;
-}
-
-static void
-hnputl(uchar *ptr, ulong val)
-{
-	ptr[0] = val>>24;
-	ptr[1] = val>>16;
-	ptr[2] = val>>8;
-	ptr[3] = val;
-}
-
-static ulong
-nhgetl(uchar *ptr)
-{
-	return ((ptr[0]<<24) | (ptr[1]<<16) | (ptr[2]<<8) | ptr[3]);
-}
-
-static ushort
-nhgets(uchar *ptr)
-{
-	return ((ptr[0]<<8) | ptr[1]);
-}
-
-static	short	endian	= 1;
-static	char*	aendian	= (char*)&endian;
-#define	LITTLE	*aendian
-
-static ushort
-ptcl_csum(void *a, int len)
-{
-	uchar *addr;
-	ulong t1, t2;
-	ulong losum, hisum, mdsum, x;
-
-	addr = a;
-	losum = 0;
-	hisum = 0;
-	mdsum = 0;
-
-	x = 0;
-	if((ulong)addr & 1) {
-		if(len) {
-			hisum += addr[0];
-			len--;
-			addr++;
-		}
-		x = 1;
-	}
-	while(len >= 16) {
-		t1 = *(ushort*)(addr+0);
-		t2 = *(ushort*)(addr+2);	mdsum += t1;
-		t1 = *(ushort*)(addr+4);	mdsum += t2;
-		t2 = *(ushort*)(addr+6);	mdsum += t1;
-		t1 = *(ushort*)(addr+8);	mdsum += t2;
-		t2 = *(ushort*)(addr+10);	mdsum += t1;
-		t1 = *(ushort*)(addr+12);	mdsum += t2;
-		t2 = *(ushort*)(addr+14);	mdsum += t1;
-		mdsum += t2;
-		len -= 16;
-		addr += 16;
-	}
-	while(len >= 2) {
-		mdsum += *(ushort*)addr;
-		len -= 2;
-		addr += 2;
-	}
-	if(x) {
-		if(len)
-			losum += addr[0];
-		if(LITTLE)
-			losum += mdsum;
-		else
-			hisum += mdsum;
-	} else {
-		if(len)
-			hisum += addr[0];
-		if(LITTLE)
-			hisum += mdsum;
-		else
-			losum += mdsum;
-	}
-
-	losum += hisum >> 8;
-	losum += (hisum & 0xff) << 8;
-	while(hisum = losum>>16)
-		losum = hisum + (losum & 0xffff);
-
-	return ~losum;
-}
-
-static ushort
-ip_csum(uchar *addr)
-{
-	int len;
-	ulong sum = 0;
-
-	len = (addr[0]&0xf)<<2;
-
-	while(len > 0) {
-		sum += addr[0]<<8 | addr[1] ;
-		len -= 2;
-		addr += 2;
-	}
-
-	sum = (sum & 0xffff) + (sum >> 16);
-	sum = (sum & 0xffff) + (sum >> 16);
-	return (sum^0xffff);
-}
-
-static void
-udpsend(int ctlrno, Netaddr *a, void *data, int dlen)
-{
-	Udphdr *uh;
-	Etherhdr *ip;
-	static Etherpkt pkt;
-	int len, ptcllen;
-
-
-	uh = (Udphdr*)&pkt;
-
-	memset(uh, 0, sizeof(Etherpkt));
-	memmove(uh->udpcksum+sizeof(uh->udpcksum), data, dlen);
-
-	/*
-	 * UDP portion
-	 */
-	ptcllen = dlen + (UDP_HDRSIZE-UDP_PHDRSIZE);
-	uh->ttl = 0;
-	uh->udpproto = IP_UDPPROTO;
-	uh->frag[0] = 0;
-	uh->frag[1] = 0;
-	hnputs(uh->udpplen, ptcllen);
-	hnputl(uh->udpsrc, myaddr.ip);
-	hnputs(uh->udpsport, myaddr.port);
-	hnputl(uh->udpdst, a->ip);
-	hnputs(uh->udpdport, a->port);
-	hnputs(uh->udplen, ptcllen);
-	uh->udpcksum[0] = 0;
-	uh->udpcksum[1] = 0;
-	/*dlen = (dlen+1)&~1; */
-	hnputs(uh->udpcksum, ptcl_csum(&uh->ttl, dlen+UDP_HDRSIZE));
-
-	/*
-	 * IP portion
-	 */
-	ip = (Etherhdr*)&pkt;
-	len = sizeof(Udphdr)+dlen;
-	ip->vihl = IP_VER|IP_HLEN;
-	ip->tos = 0;
-	ip->ttl = 255;
-	hnputs(ip->length, len-ETHER_HDR);
-	hnputs(ip->id, Id++);
-	ip->frag[0] = 0;
-	ip->frag[1] = 0;
-	ip->cksum[0] = 0;
-	ip->cksum[1] = 0;
-	hnputs(ip->cksum, ip_csum(&ip->vihl));
-
-	/*
-	 * Ethernet MAC portion
-	 */
-	hnputs(ip->type, ET_IP);
-	memmove(ip->d, a->ea, sizeof(ip->d));
-
-	ethertxpkt(ctlrno, &pkt, len, Timeout);
-}
-
-static void
-nak(int ctlrno, Netaddr *a, int code, char *msg, int report)
-{
-	int n;
-	char buf[128];
-
-	buf[0] = 0;
-	buf[1] = Tftp_ERROR;
-	buf[2] = 0;
-	buf[3] = code;
-	strcpy(buf+4, msg);
-	n = strlen(msg) + 4 + 1;
-	udpsend(ctlrno, a, buf, n);
-	if(report)
-		print("\ntftp: error(%d): %s\n", code, msg);
-}
-
-static int
-udprecv(int ctlrno, Netaddr *a, void *data, int dlen)
-{
-	int n, len;
-	ushort csm;
-	Udphdr *h;
-	ulong addr, timo;
-	static Etherpkt pkt;
-	static int rxactive;
-
-	if(rxactive == 0)
-		timo = 1000;
-	else
-		timo = Timeout;
-	timo += TK2MS(m->ticks);
-	while(timo > TK2MS(m->ticks)){
-		n = etherrxpkt(ctlrno, &pkt, timo-TK2MS(m->ticks));
-		if(n <= 0)
-			continue;
-
-		h = (Udphdr*)&pkt;
-		if(nhgets(h->type) != ET_IP)
-			continue;
-
-		if(ip_csum(&h->vihl)) {
-			print("ip chksum error\n");
-			continue;
-		}
-		if(h->vihl != (IP_VER|IP_HLEN)) {
-			print("ip bad vers/hlen\n");
-			continue;
-		}
-
-		if(h->udpproto != IP_UDPPROTO)
-			continue;
-
-		h->ttl = 0;
-		len = nhgets(h->udplen);
-		hnputs(h->udpplen, len);
-
-		if(CHECKSUM && nhgets(h->udpcksum)) {
-			csm = ptcl_csum(&h->ttl, len+UDP_PHDRSIZE);
-			if(csm != 0) {
-				print("udp chksum error csum #%4lux len %d\n", csm, n);
-				break;
-			}
-		}
-
-		if(a->port != 0 && nhgets(h->udpsport) != a->port)
-			continue;
-
-		addr = nhgetl(h->udpsrc);
-		if(a->ip != Bcastip && addr != a->ip)
-			continue;
-
-		len -= UDP_HDRSIZE-UDP_PHDRSIZE;
-		if(len > dlen) {
-			print("udp: packet too big\n");
-			continue;
-		}
-
-		memmove(data, h->udpcksum+sizeof(h->udpcksum), len);
-		a->ip = addr;
-		a->port = nhgets(h->udpsport);
-		memmove(a->ea, pkt.s, sizeof(a->ea));
-
-		rxactive = 1;
-		return len;
-	}
-
-	return 0;
-}
-
-static int tftpblockno;
-
-static int
-tftpopen(int ctlrno, Netaddr *a, char *name, Tftp *tftp)
-{
-	int i, len, rlen, oport;
-	char buf[Segsize+2];
-
-	buf[0] = 0;
-	buf[1] = Tftp_READ;
-	len = sprint(buf+2, "%s", name) + 2;
-	len += sprint(buf+len+1, "octet") + 2;
-
-	oport = a->port;
-	for(i = 0; i < 5; i++){
-		a->port = oport;
-		udpsend(ctlrno, a, buf, len);
-		a->port = 0;
-		if((rlen = udprecv(ctlrno, a, tftp, sizeof(Tftp))) < sizeof(tftp->header))
-			continue;
-
-		switch((tftp->header[0]<<8)|tftp->header[1]){
-
-		case Tftp_ERROR:
-			print("tftpopen: error (%d): %s\n",
-				(tftp->header[2]<<8)|tftp->header[3], tftp->data);
-			return -1;
-
-		case Tftp_DATA:
-			tftpblockno = 1;
-			len = (tftp->header[2]<<8)|tftp->header[3];
-			if(len != tftpblockno){
-				print("tftpopen: block error: %d\n", len);
-				nak(ctlrno, a, 1, "block error", 0);
-				return -1;
-			}
-			return rlen-sizeof(tftp->header);
-		}
-	}
-
-	print("tftpopen: failed to connect to server\n");
-	return -1;
-}
-
-static int
-tftpread(int ctlrno, Netaddr *a, Tftp *tftp, int dlen)
-{
-	int blockno, len, retry;
-	uchar buf[4];
-
-	buf[0] = 0;
-	buf[1] = Tftp_ACK;
-	buf[2] = tftpblockno>>8;
-	buf[3] = tftpblockno;
-	tftpblockno++;
-
-	dlen += sizeof(tftp->header);
-
-	retry = 0;
-buggery:
-	udpsend(ctlrno, a, buf, sizeof(buf));
-
-	if((len = udprecv(ctlrno, a, tftp, dlen)) < dlen){
-		print("tftpread: %d != %d\n", len, dlen);
-		nak(ctlrno, a, 2, "short read", 0);
-		if(retry++ < 5)
-			goto buggery;
-		return -1;
-	}
-
-	blockno = (tftp->header[2]<<8)|tftp->header[3];
-	if(blockno != tftpblockno){
-		print("?");
-
-		if(blockno == tftpblockno-1 && retry++ < 8)
-			goto buggery;
-		print("tftpread: block error: %d, expected %d\n", blockno, tftpblockno);
-		nak(ctlrno, a, 1, "block error", 0);
-
-		return -1;
-	}
-
-	return len-sizeof(tftp->header);
-}
-
-int
-bootp(int ctlrno, char *file)
-{
-	Bootp req, rep;
-	int i, dlen, segsize, text, data, bss, total;
-	uchar *ea, *addr, *p;
-	ulong entry;
-	Exec *exec;
-	char name[128], *filename, *sysname;
-
-	if((ea = etheraddr(ctlrno)) == 0){
-		print("invalid ctlrno %d\n", ctlrno);
-		return -1;
-	}
-
-	filename = 0;
-	sysname = 0;
-	if(file && *file){
-		strcpy(name, file);
-		if(filename = strchr(name, ':')){
-			if(filename != name && *(filename-1) != '\\'){
-				sysname = name;
-				*filename++ = 0;
-			}
-		}
-		else
-			filename = name;
-	}
-		
-
-	memset(&req, 0, sizeof(req));
-	req.op = Bootrequest;
-	req.htype = 1;			/* ethernet */
-	req.hlen = Eaddrlen;		/* ethernet */
-	memmove(req.chaddr, ea, Eaddrlen);
-
-	myaddr.ip = 0;
-	myaddr.port = BPportsrc;
-	memmove(myaddr.ea, ea, Eaddrlen);
-
-	for(i = 0; i < 10; i++) {
-		server.ip = Bcastip;
-		server.port = BPportdst;
-		memmove(server.ea, broadcast, sizeof(server.ea));
-		udpsend(ctlrno, &server, &req, sizeof(req));
-		if(udprecv(ctlrno, &server, &rep, sizeof(rep)) <= 0)
-			continue;
-		if(memcmp(req.chaddr, rep.chaddr, Eaddrlen))
-			continue;
-		if(rep.htype != 1 || rep.hlen != Eaddrlen)
-			continue;
-		if(sysname == 0 || strcmp(sysname, rep.sname) == 0)
-			break;
-	}
-	if(i >= 10) {
-		print("bootp timed out\n");
-		return -1;
-	}
-
-	if(filename == 0 || *filename == 0)
-		filename = rep.file;
-
-	if(rep.sname[0] != '\0')
-		 print("%s ", rep.sname);
-	print("(%d.%d.%d.%d!%d): %s\n",
-		rep.siaddr[0],
-		rep.siaddr[1],
-		rep.siaddr[2],
-		rep.siaddr[3],
-		server.port,
-		filename);uartwait();
-
-	myaddr.ip = nhgetl(rep.yiaddr);
-	myaddr.port = tftpport++;
-	server.ip = nhgetl(rep.siaddr);
-	server.port = TFTPport;
-
-	if((dlen = tftpopen(ctlrno, &server, filename, &tftpb)) < 0)
-		return -1;
-	exec = (Exec*)(tftpb.data);
-	if(dlen < sizeof(Exec) || GLLONG(exec->magic) != Q_MAGIC){
-		nak(ctlrno, &server, 0, "bad magic number", 1);
-		return -1;
-	}
-	text = GLLONG(exec->text);
-	data = GLLONG(exec->data);
-	bss = GLLONG(exec->bss);
-	total = text+data+bss;
-	entry = GLLONG(exec->entry);
-print("load@%8.8lux: ", XPADDR(entry));uartwait();
-	print("%d", text);
-
-	addr = (uchar*)XPADDR(entry);
-	p = tftpb.data+sizeof(Exec);
-	dlen -= sizeof(Exec);
-	segsize = text;
-	for(;;){
-		if(dlen == 0){
-			if((dlen = tftpread(ctlrno, &server, &tftpb, sizeof(tftpb.data))) < 0)
-				return -1;
-			p = tftpb.data;
-		}
-		if(segsize <= dlen)
-			i = segsize;
-		else
-			i = dlen;
-		memmove(addr, p, i);
-
-		addr += i;
-		p += i;
-		segsize -= i;
-		dlen -= i;
-
-		if(segsize <= 0){
-			if(data == 0)
-				break;
-			print("+%d", data);
-			segsize = data;
-			data = 0;
-			addr = (uchar*)PGROUND((ulong)addr);
-		}
-	}
-	nak(ctlrno, &server, 3, "ok", 0);		/* tftpclose */
-	print("+%d=%d\n", bss, total);
-	print("entry: 0x%lux\n", entry);
-	uartwait();
-	scc2stop();
-	splhi();
-	(*(void(*)(void))(XPADDR(entry)))();
-	
-	return 0;
-}
--- a/os/boot/rpcg/clock.c
+++ /dev/null
@@ -1,71 +1,0 @@
-#include	"u.h"
-#include	"lib.h"
-#include	"mem.h"
-#include	"dat.h"
-#include	"fns.h"
-#include	"io.h"
-#include	"ureg.h"
-
-enum {
-	Timebase = 4,	/* system clock cycles per time base cycle */
-};
-
-void	(*archclocktick)(void);	/* set by arch*.c when desired */
-
-static	ulong	clkreload;
-
-void
-delay(int l)
-{
-	ulong i, j;
-
-	j = m->delayloop;
-	while(l-- > 0)
-		for(i=0; i < j; i++)
-			;
-}
-
-void
-microdelay(int l)
-{
-	ulong i;
-
-	l *= m->delayloop;
-	l /= 1000;
-	if(l <= 0)
-		l = 1;
-	for(i = 0; i < l; i++)
-		;
-}
-
-void
-clockintr(Ureg*, void*)
-{
-	putdec(clkreload);
-	m->ticks++;
-	checkalarms();
-	if(archclocktick != nil)
-		archclocktick();
-}
-
-void
-clockinit(void)
-{
-	long x;
-
-	m->delayloop = m->cpuhz/1000;	/* initial estimate */
-	do {
-		x = gettbl();
-		delay(10);
-		x = gettbl() - x;
-	} while(x < 0);
-
-	/*
-	 *  fix count
-	 */
-	m->delayloop = ((vlong)m->delayloop*(10*m->clockgen/1000))/(x*Timebase);
-	if(m->delayloop == 0)
-		m->delayloop = 1;
-	clkreload = (m->clockgen/Timebase)/HZ-1;
-	putdec(clkreload);
-}
--- a/os/boot/rpcg/conf.c
+++ /dev/null
@@ -1,173 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-#include "dosfs.h"
-
-static char *confname[MAXCONF];
-static char *confval[MAXCONF];
-static int nconf;
-
-extern char **ini;
-
-char*
-getconf(char *name)
-{
-	int i;
-
-	for(i = 0; i < nconf; i++)
-		if(strcmp(confname[i], name) == 0)
-			return confval[i];
-	return 0;
-}
-
-/*
- *  read configuration file
- */
-int
-plan9ini(Dos *dos, char *val)
-{
-	Dosfile rc;
-	int i, n;
-	char *cp, *p, *q, *line[MAXCONF];
-
-	cp = BOOTARGS;
-	if(dos) {
-		if(dosstat(dos, *ini, &rc) <= 0)
-			return -1;
-
-		*cp = 0;
-		n = dosread(&rc, cp, BOOTARGSLEN-1);
-		if(n <= 0)
-			return -1;
-		cp[n] = 0;
-	} else if(val != nil){
-		if(memchr(val, 0, BOOTARGSLEN-1) == nil)
-			return -1;
-		print("Using flash configuration\n");
-		strcpy(cp, val);
-		n = strlen(cp);
-	}else{
-		strcpy(cp, archconfig());
-		n = strlen(cp);
-	}
-
-	/*
-	 * Make a working copy.
-	 * We could change this to pass the parsed strings
-	 * to the booted programme instead of the raw
-	 * string, then it only gets done once.
-	 */
-	memmove(cp+BOOTARGSLEN, cp, n+1);
-	cp += BOOTARGSLEN;
-
-	/*
-	 * Strip out '\r', change '\t' -> ' '.
-	 */
-	p = cp;
-	for(q = cp; *q; q++){
-		if(*q == '\r')
-			continue;
-		if(*q == '\t')
-			*q = ' ';
-		*p++ = *q;
-	}
-	*p = 0;
-	n = getcfields(cp, line, MAXCONF, "\n");
-	for(i = 0; i < n; i++){
-		cp = strchr(line[i], '=');
-		if(cp == 0)
-			continue;
-		*cp++ = 0;
-		if(cp - line[i] >= NAMELEN+1)
-			*(line[i]+NAMELEN-1) = 0;
-		confname[nconf] = line[i];
-		confval[nconf] = cp;
-		nconf++;
-	}
-	return 0;
-}
-
-int
-parseether(uchar *to, char *from)
-{
-	char nip[4];
-	char *p;
-	int i;
-
-	p = from;
-	while(*p == ' ')
-		++p;
-	for(i = 0; i < 6; i++){
-		if(*p == 0)
-			return -1;
-		nip[0] = *p++;
-		if(*p == 0)
-			return -1;
-		nip[1] = *p++;
-		nip[2] = 0;
-		to[i] = strtoul(nip, 0, 16);
-		if(*p == ':')
-			p++;
-	}
-	return 0;
-}
-
-int
-isaconfig(char *class, int ctlrno, ISAConf *isa)
-{
-	char cc[NAMELEN], *p, *q, *r;
-	int n;
-
-	sprint(cc, "%s%d", class, ctlrno);
-	for(n = 0; n < nconf; n++){
-		if(strncmp(confname[n], cc, NAMELEN))
-			continue;
-		isa->nopt = 0;
-		p = confval[n];
-		while(*p){
-			while(*p == ' ' || *p == '\t')
-				p++;
-			if(*p == '\0')
-				break;
-			if(strncmp(p, "type=", 5) == 0){
-				p += 5;
-				for(q = isa->type; q < &isa->type[NAMELEN-1]; q++){
-					if(*p == '\0' || *p == ' ' || *p == '\t')
-						break;
-					*q = *p++;
-				}
-				*q = '\0';
-			}
-			else if(strncmp(p, "port=", 5) == 0)
-				isa->port = strtoul(p+5, &p, 0);
-			else if(strncmp(p, "irq=", 4) == 0)
-				isa->irq = strtoul(p+4, &p, 0);
-			else if(strncmp(p, "mem=", 4) == 0)
-				isa->mem = strtoul(p+4, &p, 0);
-			else if(strncmp(p, "size=", 5) == 0)
-				isa->size = strtoul(p+5, &p, 0);
-			else if(strncmp(p, "ea=", 3) == 0){
-				if(parseether(isa->ea, p+3) == -1)
-					memset(isa->ea, 0, 6);
-			}
-			else if(isa->nopt < NISAOPT){
-				r = isa->opt[isa->nopt];
-				while(*p && *p != ' ' && *p != '\t'){
-					*r++ = *p++;
-					if(r-isa->opt[isa->nopt] >= ISAOPTLEN-1)
-						break;
-				}
-				*r = '\0';
-				isa->nopt++;
-			}
-			while(*p && *p != ' ' && *p != '\t')
-				p++;
-		}
-		return 1;
-	}
-	return 0;
-}
--- a/os/boot/rpcg/console.c
+++ /dev/null
@@ -1,173 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-static Queue*	consiq;
-static Queue*	consoq;
-
-void
-bothputs(char *s, int n)
-{
-	uartputs(s, n);
-	screenputs(s, n);
-}
-
-static void (*consputs)(char*, int) = bothputs;	/* or screenputs */
-
-void
-consinit(void)
-{
-	char *p;
-	int baud, port;
-	static int cgadone;
-
-	p = getconf("console");
-	if(0)
-	if(p == 0 || strcmp(p, "lcd") == 0 || strcmp(p, "screen") == 0){
-		consiq = qopen(4*1024, 0, 0, 0);
-		consoq = qopen(8*1024, 0, 0, 0);
-		consputs = screenputs;
-		return;
-	}
-	if(p!=0 && strstr(p, "lcd") == 0)
-		consputs = bothputs;
-	else
-		consputs = uartputs;
-//consputs = screenputs;
-	port = 0;
-	if(p)
-		port = strtoul(p, 0, 0);
-	baud = 0;
-	if(p = getconf("baud"))
-		baud = strtoul(p, 0, 0);
-	if(baud == 0)
-		baud = 9600;
-	uartspecial(port, baud, &consiq, &consoq, kbdchar);
-}
-
-void
-kbdchar(Queue *q, int c)
-{
-	c &= 0x7F;
-	if(c == 0x10)
-		panic("^p");
-	qbputc(q, c);
-}
-
-static int
-getline(char *buf, int size, int dotimeout)
-{
-	int c, i=0;
-	ulong start;
-	char echo;
-
-	for (;;) {
-		start = m->ticks;
-		do{
-			if(dotimeout && ((m->ticks - start) > 5*HZ))
-				return -2;
-			c = qbgetc(consiq);
-		}while(c == -1);
-		if(c == '\r')
-			c = '\n'; 		/* turn carriage return into newline */
-		if(c == '\177')
-			c = '\010';		/* turn delete into backspace */
-		if(c == '\025')
-			echo = '\n';		/* echo ^U as a newline */
-		else
-			echo = c;
-		(*consputs)(&echo, 1);
-
-		if(c == '\010'){
-			if(i > 0)
-				i--; /* bs deletes last character */
-			continue;
-		}
-		/* a newline ends a line */
-		if (c == '\n')
-			break;
-		/* ^U wipes out the line */
-		if (c =='\025')
-			return -1;
-		if(i == size)
-			return size;
-		buf[i++] = c;
-	}
-	buf[i] = 0;
-	return i;
-}
-
-int
-getstr(char *prompt, char *buf, int size, char *def)
-{
-	int len, isdefault;
-
-	buf[0] = 0;
-	isdefault = (def && *def);
-	for (;;) {
-		if(isdefault)
-			print("%s[default==%s]: ", prompt, def);
-		else
-			print("%s: ", prompt);
-		len = getline(buf, size, isdefault);
-		switch(len){
-		case -1:
-			/* ^U typed */
-			continue;
-		case -2:
-			/* timeout, use default */
-			(*consputs)("\n", 1);
-			len = 0;
-			break;
-		default:
-			break;
-		}
-		if(len >= size){
-			print("line too long\n");
-			continue;
-		}
-		break;
-	}
-	if(len == 0 && isdefault)
-		strcpy(buf, def);
-	return 0;
-}
-
-int
-sprint(char *s, char *fmt, ...)
-{
-	return donprint(s, s+PRINTSIZE, fmt, (&fmt+1)) - s;
-}
-
-int
-print(char *fmt, ...)
-{
-	char buf[PRINTSIZE];
-	int n;
-
-	if(consputs == 0)
-		return 0;
-	n = donprint(buf, buf+sizeof(buf), fmt, (&fmt+1)) - buf;
-	(*consputs)(buf, n);
-	return n;
-}
-
-void
-panic(char *fmt, ...)
-{
-	char buf[PRINTSIZE];
-	int n;
-
-	if(consputs){
-		(*consputs)("panic: ", 7);
-		n = donprint(buf, buf+sizeof(buf), fmt, (&fmt+1)) - buf;
-		(*consputs)(buf, n);
-		(*consputs)("\n", 1);
-	}
-	spllo();
-	for(;;)
-		idle();
-}
--- a/os/boot/rpcg/cpm.c
+++ /dev/null
@@ -1,162 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-enum {
-	BDSIZE=	1024,	/* TO DO: check this */
-};
-
-static	Map	bdmapv[BDSIZE/sizeof(BD)];
-static	RMap	bdmap = {"buffer descriptors"};
-
-void
-cpminit(void)
-{
-	IMM *io;
-
-	io = m->iomem;
-	io->sdcr = 1;
-	io->lccr &= ~1;	/* disable LCD */
-	io->pcint = 0;	/* disable all port C interrupts */
-	io->pcso = 0;
-	io->pcdir =0;
-	io->pcpar = 0;
-	io->pcdat = 0;
-	io->papar = 0;
-	io->padir = 0;
-	io->paodr = 0;
-	io->padat = 0;
-	io->pbpar = 0;
-	io->pbdir = 0;
-	io->pbodr = 0;
-	io->pbdat = 0;
-	eieio();
-
-	for(io->cpcr = 0x8001; io->cpcr & 1;)	/* reset all CPM channels */
-		eieio();
-
-	mapinit(&bdmap, bdmapv, sizeof(bdmapv));
-	mapfree(&bdmap, DPBASE, BDSIZE);
-}
-
-void
-cpmop(int op, int cno, int param)
-{
-	IMM *io;
-	int s;
-
-	s = splhi();
-	io = m->iomem;
-	eieio();
-	while(io->cpcr & 1)
-		eieio();
-	io->cpcr = (op<<8)|(cno<<4)|(param<<1)|1;
-	eieio();
-	while(io->cpcr & 1)
-		eieio();
-	splx(s);
-}
-
-/*
- * connect SCCx clocks in NSMI mode (x=1 for USB)
- */
-void
-sccnmsi(int x, int rcs, int tcs)
-{
-	IMM *io;
-	ulong v;
-	int sh;
-
-	sh = (x-1)*8;	/* each SCCx field in sicr is 8 bits */
-	v = (((rcs&7)<<3) | (tcs&7)) << sh;
-	io = ioplock();
-	io->sicr = (io->sicr & ~(0xFF<<sh)) | v;
-	iopunlock();
-}
-
-void
-scc2stop(void)
-{
-	SCC *scc;
-
-	scc = IOREGS(0xA20, SCC);
-	if(scc->gsmrl & (3<<4)){
-		cpmop(GracefulStopTx, SCC2ID, 0);
-		cpmop(CloseRxBD, SCC2ID, 0);
-		delay(1);
-		scc->gsmrl &= ~(3<<4);	/* disable current use */
-		archetherdisable(SCC2ID);
-	}
-}
-
-BD *
-bdalloc(int n)
-{
-	ulong a;
-
-	a = mapalloc(&bdmap, 0, n*sizeof(BD), 0);
-	if(a == 0)
-		panic("bdalloc");
-	return KADDR(a);
-}
-
-void
-bdfree(BD *b, int n)
-{
-	if(b){
-		eieio();
-		mapfree(&bdmap, PADDR(b), n*sizeof(BD));
-	}
-}
-
-/*
- * initialise receive and transmit buffer rings.
- */
-int
-ioringinit(Ring* r, int nrdre, int ntdre, int bufsize)
-{
-	int i, x;
-
-	/* the ring entries must be aligned on sizeof(BD) boundaries */
-	r->nrdre = nrdre;
-	if(r->rdr == nil)
-		r->rdr = bdalloc(nrdre);
-	/* the buffer size must align with cache lines since the cache doesn't snoop */
-	bufsize = (bufsize+CACHELINESZ-1)&~(CACHELINESZ-1);
-	if(r->rrb == nil)
-		r->rrb = malloc(nrdre*bufsize);
-	if(r->rdr == nil || r->rrb == nil)
-		return -1;
-	dcflush(r->rrb, nrdre*bufsize);
-	x = PADDR(r->rrb);
-	for(i = 0; i < nrdre; i++){
-		r->rdr[i].length = 0;
-		r->rdr[i].addr = x;
-		r->rdr[i].status = BDEmpty|BDInt;
-		x += bufsize;
-	}
-	r->rdr[i-1].status |= BDWrap;
-	r->rdrx = 0;
-
-	r->ntdre = ntdre;
-	if(r->tdr == nil)
-		r->tdr = bdalloc(ntdre);
-	if(r->txb == nil)
-		r->txb = malloc(ntdre*sizeof(Block*));
-	if(r->tdr == nil || r->txb == nil)
-		return -1;
-	for(i = 0; i < ntdre; i++){
-		r->txb[i] = nil;
-		r->tdr[i].addr = 0;
-		r->tdr[i].length = 0;
-		r->tdr[i].status = 0;
-	}
-	r->tdr[i-1].status |= BDWrap;
-	r->tdrh = 0;
-	r->tdri = 0;
-	r->ntq = 0;
-	return 0;
-}
--- a/os/boot/rpcg/crc32.c
+++ /dev/null
@@ -1,42 +1,0 @@
-#include "boot.h"
-
-/*
- * from Rob Warnock
- */
-static	ulong	crc32tab[256];	/* initialised on first call to crc32 */
-
-enum {
-	CRC32POLY = 0x04c11db7     /* AUTODIN II, Ethernet, & FDDI */
-};
-
-/*
- * Build auxiliary table for parallel byte-at-a-time CRC-32.
- */
-static void
-initcrc32(void)
-{
-	int i, j;
-	ulong c;
-
-	for(i = 0; i < 256; i++) {
-		for(c = i << 24, j = 8; j > 0; j--)
-			if(c & (1<<31))
-				c = (c<<1) ^ CRC32POLY;
-			else
-				c <<= 1;
-		crc32tab[i] = c;
-	}
-}
-
-ulong
-crc32(void *buf, int n, ulong crc)
-{
-	uchar *p;
-
-	if(crc32tab[1] == 0)
-		initcrc32();
-	crc = ~crc;
-	for(p = buf; --n >= 0;)
-		crc = (crc << 8) ^ crc32tab[(crc >> 24) ^ *p++];
-	return ~crc;
-}
--- a/os/boot/rpcg/dat.h
+++ /dev/null
@@ -1,217 +1,0 @@
-typedef struct Alarm Alarm;
-typedef struct Block Block;
-typedef struct IMM IMM;
-typedef struct Queue Queue;
-
-typedef struct List {
-	void	*next;
-} List;
-
-typedef struct {
-	int	fake;
-	int	pri;
-} Lock;
-#define	lock(x)
-#define	unlock(x)
-
-struct Alarm {
-	List;
-	int	busy;
-	long	dt;
-	void	(*f)(Alarm*);
-	void	*arg;
-};
-
-enum {
-	Eaddrlen	= 6,
-	ETHERMINTU	= 60,		/* minimum transmit size */
-	ETHERMAXTU	= 1514,		/* maximum transmit size */
-	ETHERHDRSIZE	= 14,		/* size of an ethernet header */
-
-	MaxEther	= 4,
-};
-
-typedef struct {
-	uchar	d[Eaddrlen];
-	uchar	s[Eaddrlen];
-	uchar	type[2];
-	uchar	data[1500];
-	uchar	crc[4];
-} Etherpkt;
-
-extern uchar broadcast[Eaddrlen];
-
-enum {
-	Npart		= 20+2,		/* 8 sub partitions, disk, and partition */
-	Maxxfer		= 16*1024,	/* maximum transfer size/cmd */
-};
-
-typedef struct {
-	ulong	start;
-	ulong	end;
-	char	name[NAMELEN+1];
-} Partition;
-
-typedef struct {
-	int	online;
-	int	npart;		/* number of real partitions */
-	Partition p[Npart];
-	ulong	offset;
-	Partition *current;	/* current partition */
-
-	ulong	cap;		/* total bytes */
-	int	bytes;		/* bytes/sector */
-	int	sectors;	/* sectors/track */
-	int	heads;		/* heads/cyl */
-	long	cyl;		/* cylinders/drive */
-
-	char	lba;		/* true if drive has logical block addressing */
-	char	multi;		/* non-zero if drive does multiple block xfers */
-} Disc;
-
-enum {
-	ScsiTestunit	= 0x00,
-	ScsiExtsens	= 0x03,
-	ScsiInquiry	= 0x12,
-	ScsiModesense	= 0x1a,
-	ScsiStartunit	= 0x1B,
-	ScsiStopunit	= 0x1B,
-	ScsiGetcap	= 0x25,
-	ScsiRead	= 0x08,
-	ScsiWrite	= 0x0a,
-	ScsiExtread	= 0x28,
-	ScsiExtwrite	= 0x2a,
-
-	/* data direction */
-	ScsiIn		= 1,
-	ScsiOut		= 0,
-};
-
-typedef struct Scsibuf Scsibuf;
-typedef struct Scsibuf {
-	void*		virt;
-	void*		phys;
-	Scsibuf*	next;
-};
-
-typedef struct Scsidata {
-	uchar*		base;
-	uchar*		lim;
-	uchar*		ptr;
-} Scsidata;
-
-typedef struct Ureg Ureg;
-
-typedef struct Scsi {
-	ulong		pid;
-	ushort		target;
-	ushort		lun;
-	ushort		rflag;
-	ushort		status;
-	Scsidata 	cmd;
-	Scsidata 	data;
-	Scsibuf*	b;
-	uchar*		save;
-	uchar		cmdblk[16];
-} Scsi;
-
-typedef struct Segdesc {
-	ulong	d0;
-	ulong	d1;
-} Segdesc;
-
-typedef struct Mach {
-	ulong	ticks;			/* of the clock since boot time */
-	ulong	delayloop;
-	long	cpuhz;	/* general system clock (cycles) */
-	long	clockgen;	/* clock generator frequency (cycles) */
-	ulong	cpupvr;	/* cpu type in processor version register */
-	ulong	cputype;	/* cpu variant in BCD (eg, 0x823xx) */
-	void*	alarm;			/* alarms bound to this clock */
-	ulong*	bcsr;
-	IMM*	iomem;
-} Mach;
-
-/* Mach.cputype */
-#define MPCREV(x)	((x) & 0xFF)
-#define MPCMODEL(x)	(((x)>>8) & 0xFFF)
-#define MPCFAMILY(x)	(((x)>>24) & 0x0F)
-
-
-extern Mach *m;
-
-#define Q_MAGIC		((((4*21)+0)*21)+7)
-
-typedef struct Exec Exec;
-struct	Exec
-{
-	uchar	magic[4];		/* magic number */
-	uchar	text[4];	 	/* size of text segment */
-	uchar	data[4];	 	/* size of initialized data */
-	uchar	bss[4];	  		/* size of uninitialized data */
-	uchar	syms[4];	 	/* size of symbol table */
-	uchar	entry[4];	 	/* entry point */
-	uchar	spsz[4];		/* size of sp/pc offset table */
-	uchar	pcsz[4];		/* size of pc/line number table */
-};
-
-/*
- *  bootline passed by boot program
- */
-#define BOOTLINE ((char *)0x200000-150)
-
-/*
- * Where we leave configuration info.
- */
-#define BOOTARGS	((char*)(0x200000))
-#define	BOOTARGSLEN	1024
-#define	MAXCONF		32
-
-/*
- *  a parsed plan9.ini line
- */
-#define ISAOPTLEN	16
-#define NISAOPT		8
-
-typedef struct  ISAConf {
-	char	type[NAMELEN];
-	ulong	port;
-	ulong	irq;
-	ulong	mem;
-	ulong	size;
-	uchar	ea[6];
-
-	int	nopt;
-	char	opt[NISAOPT][ISAOPTLEN];
-} ISAConf;
-
-typedef struct {
-	int	size;
-	ulong	addr;
-} Map;
-
-typedef struct {
-	char*	name;
-	Map*	map;
-	Map*	mapend;
-
-	Lock;
-} RMap;
-
-typedef struct PCIcfg PCIcfg;
-
-extern	uchar*	vgamem;
-
-struct Block {
-	uchar	*rp;
-	uchar	*wp;
-	uchar	*lim;
-	uchar	*data;
-	Block*	next;
-	ulong	magic;
-};
-#define	BLEN(b)	((b)->wp-(b)->rp)
-
-typedef struct QLock {
-	int	dummy;
-} QLock;
--- a/os/boot/rpcg/defont0.c
+++ /dev/null
@@ -1,216 +1,0 @@
-#include <u.h>
-#include <libc.h>
-#include <libg.h>
-#include <gnot.h>
-
-
-
-static ulong bits0[] = {
- 0x907070f0,  0xf0f07000,  0xf0888888,  0xf8707070,  0xe0e0e0e0,  0xe09070f0,  0x70f870f0,  0xf870f088, 
- 0x00000000,  0x00000000,  0x00000000,  0x00000000,  0x00000000,  0x00000000,  0x00000000,  0x00000000, 
- 0x00000000,  0x00000000,  0x00000000,  0x00000000,  0x00000000,  0x00000000,  0x00000000,  0x00000000, 
- 0x00000000,  0x00000000,  0x00000000,  0x00000000,  0x00000000,  0x00000000,  0x00000000,  0x000000e0, 
- 0xd0808080,  0x80808800,  0x8888c888,  0x80888888,  0x90909090,  0x90d08080,  0x80808080,  0x80888888, 
- 0x00000000,  0x08000000,  0x0c300000,  0x00000006,  0x00000000,  0x00000000,  0x00000000,  0x00000000, 
- 0x00000000,  0x00000000,  0x00000000,  0x00000000,  0x00000000,  0x00000000,  0x0000003c,  0xc03c0000, 
- 0x00006000,  0x06001e00,  0x60181860,  0x78000000,  0x00000000,  0x00000000,  0x0000001c,  0x18380090, 
- 0xb06060e0,  0xe0e0f800,  0xf088a888,  0x80808080,  0x90909090,  0x90b060e0,  0x808060e0,  0x80808888, 
- 0x00182428,  0x3e707018,  0x18180000,  0x00000006,  0x3c183c3c,  0x1c3e3c7e,  0x3c3c0000,  0x0200403c, 
- 0x3c187c1e,  0x787e7e1e,  0x663c7c66,  0x6066623c,  0x7c3c7c3c,  0x7e6266c2,  0x66667e30,  0xc00c1000, 
- 0x08006000,  0x06003000,  0x60181860,  0x18000000,  0x00000000,  0x10000000,  0x00000030,  0x180c0090, 
- 0x90101080,  0x80808818,  0x88f8a888,  0xe0807070,  0xe0e0e0e0,  0xe0901080,  0x70e01080,  0xe098f088, 
- 0x00182428,  0x6adad818,  0x18181000,  0x0000000c,  0x66386666,  0x2c3e667e,  0x66660000,  0x06006066, 
- 0x42186632,  0x6c606032,  0x66181864,  0x60667224,  0x66246666,  0x186262da,  0x62620630,  0x600c3800, 
- 0x10006000,  0x06003000,  0x60000060,  0x18000000,  0x00000000,  0x30000000,  0x00000030,  0x180c00e0, 
- 0x00e0e0f0,  0xf0f00018,  0x88889850,  0x80880808,  0x201c1c1c,  0x1c00e0f0,  0x0080e0f0,  0x80888888, 
- 0x00182428,  0x68dad808,  0x300c5418,  0x0000000c,  0x66580606,  0x2c206002,  0x66661818,  0x0cfe3006, 
- 0x9e2c6660,  0x66606060,  0x6618186c,  0x60667266,  0x66666660,  0x186262da,  0x36660c30,  0x600c2800, 
- 0x103c6c3c,  0x3e3c7e3e,  0x6c787866,  0x18d46c3c,  0x6c3e763c,  0x7e6666c2,  0x66667e18,  0x18180000, 
- 0x44180000,  0x18241c24,  0xf0888820,  0x8070f0f0,  0x20202020,  0x201c243e,  0x1cf8241c,  0x80708870, 
- 0x0018247c,  0x78745008,  0x300c3818,  0x00000018,  0x66180606,  0x4c206006,  0x76661818,  0x18fe180c, 
- 0xb62c6660,  0x66606060,  0x66181868,  0x607e5a66,  0x66666470,  0x186266da,  0x34340c30,  0x300c6c00, 
- 0x18667666,  0x66663066,  0x76181864,  0x18fe7666,  0x76663666,  0x306662da,  0x62620608,  0x1810323c, 
- 0x44247c7c,  0x24342042,  0x00000000,  0x00000000,  0x20202020,  0x20222408,  0x22002420,  0x00000000, 
- 0x00180028,  0x3c287610,  0x300cee7e,  0x00fe0018,  0x66180c18,  0x4c3c7c0c,  0x3c3e0000,  0x30000c18, 
- 0xb62c7c60,  0x667c7c6e,  0x7e181878,  0x605a5a66,  0x6466783c,  0x186234da,  0x18341830,  0x300c4400, 
- 0x18066660,  0x66663066,  0x66181868,  0x18d66666,  0x66663860,  0x306662da,  0x34620c30,  0x180c5a20, 
- 0x44241010,  0x242c2042,  0x0e3e103e,  0x3e3c1c3e,  0x3c1c1c1c,  0x1c3e1c08,  0x3e222418,  0x0e0e0e0e, 
- 0x0008007c,  0x1e5cdc00,  0x300c387e,  0x00fe0030,  0x66181806,  0x7e066618,  0x6e060000,  0x18001818, 
- 0xb67e6660,  0x66606066,  0x6618186c,  0x605a4e66,  0x78666c0e,  0x1862346c,  0x2c183030,  0x180c4400, 
- 0x003e6660,  0x667e3066,  0x66181878,  0x18d66666,  0x6666303c,  0x306634da,  0x18341808,  0x18104c38, 
- 0x3c181010,  0x18241c42,  0x11081008,  0x20222208,  0x00000000,  0x00220408,  0x22361804,  0x11111111, 
- 0x00000028,  0x16b6cc00,  0x300c5418,  0x00000030,  0x66183006,  0x7e066618,  0x66060000,  0x0cfe3000, 
- 0x9a466660,  0x66606066,  0x6618186c,  0x605a4e66,  0x60666606,  0x1862346c,  0x6c183030,  0x180c0000, 
- 0x00666660,  0x66603066,  0x6618186c,  0x18d66666,  0x66663006,  0x3066346c,  0x2c343018,  0x18180020, 
- 0x00091010,  0x000e0942,  0x10081008,  0x20222208,  0x0f06060f,  0x0a09041e,  0x002a0e38,  0x10101010, 
- 0x00180028,  0x56b6cc00,  0x300c1018,  0x18001860,  0x66187e66,  0x0c666630,  0x66661818,  0x06fe6018, 
- 0x40466632,  0x6c606036,  0x66181866,  0x605a4624,  0x60246666,  0x1834186c,  0x46186030,  0x0c0c0000, 
- 0x006e6666,  0x6e66306e,  0x66181866,  0x18d66666,  0x666e3066,  0x306e186c,  0x46186030,  0x180c003c, 
- 0x08090909,  0x1f110aff,  0x0e081008,  0x382c2208,  0x08020901,  0x0a0a0911,  0x09220907,  0x0e0e0e0e, 
- 0x00180028,  0x7c1c7600,  0x18180000,  0x18001860,  0x3c7e7e3c,  0x0c3c3c30,  0x3c3c1818,  0x02004018, 
- 0x3e467c1e,  0x787e601e,  0x663c1866,  0x7e42463c,  0x603c663c,  0x1818186c,  0x66187e30,  0x0c0c0000, 
- 0x00367c3c,  0x363c7c36,  0x667e1866,  0x7ed6663c,  0x7c367c3c,  0x1e36186c,  0x66187e30,  0x180c0008, 
- 0x080f0606,  0x04110c18,  0x01081008,  0x20222208,  0x0e020203,  0x0a0c0d1e,  0x0d220e08,  0x01010101, 
- 0x00000000,  0x10000000,  0x18180000,  0x080000c0,  0x00000000,  0x00000000,  0x00000008,  0x00000000, 
- 0x00000000,  0x00000000,  0x00001800,  0x00000000,  0x000c0000,  0x00000000,  0x00000030,  0x060c00fe, 
- 0x00000000,  0x00000006,  0x00001800,  0x00000000,  0x60060000,  0x00000000,  0x0010001c,  0x18380008, 
- 0x08090606,  0x040e0a18,  0x11081f08,  0x20221c3e,  0x08020401,  0x0f0a0b11,  0x0b220908,  0x11111111, 
- 0x00000000,  0x00000000,  0x0c300000,  0x080000c0,  0x00000000,  0x00000000,  0x00000008,  0x00000000, 
- 0x00000000,  0x00000000,  0x00007000,  0x00000000,  0x00060000,  0x00000000,  0x0000003c,  0x063c0000, 
- 0x00000000,  0x00000066,  0x00001800,  0x00000000,  0x60060000,  0x00000000,  0x00300000,  0x00000008, 
- 0x0f090909,  0x04030900,  0x0e000000,  0x00000000,  0x0f0f0f0f,  0x0209091e,  0x09000f07,  0x0e0e0e0e, 
- 0x00000000,  0x00000000,  0x00000000,  0x10000000,  0x00000000,  0x00000000,  0x00000010,  0x00000000, 
- 0x00000000,  0x00000000,  0x00000000,  0x00000000,  0x00000000,  0x00000000,  0x00000000,  0x00000000, 
- 0x00000000,  0x0000003c,  0x00007000,  0x00000000,  0x60060000,  0x00000000,  0x00600000,  0x0000000f, 
-
-};
-
-static GBitmap strike0 = {
-	bits0,
-	0,
-	32,
-	0,
-	{0, 0, 1024, 14},
-	{0, 0, 1024, 14},
-};
-
-static Fontchar info0[] = {
-	{ 0, 0, 14, 0, 8 },
-	{ 8, 0, 14, 0, 8 },
-	{ 16, 0, 14, 0, 8 },
-	{ 24, 0, 14, 0, 8 },
-	{ 32, 0, 14, 0, 8 },
-	{ 40, 0, 14, 0, 8 },
-	{ 48, 0, 14, 0, 8 },
-	{ 56, 0, 14, 0, 8 },
-	{ 64, 0, 14, 0, 8 },
-	{ 72, 0, 14, 0, 8 },
-	{ 80, 0, 14, 0, 8 },
-	{ 88, 0, 14, 0, 8 },
-	{ 96, 0, 14, 0, 8 },
-	{ 104, 0, 14, 0, 8 },
-	{ 112, 0, 14, 0, 8 },
-	{ 120, 0, 14, 0, 8 },
-	{ 128, 0, 14, 0, 8 },
-	{ 136, 0, 14, 0, 8 },
-	{ 144, 0, 14, 0, 8 },
-	{ 152, 0, 14, 0, 8 },
-	{ 160, 0, 14, 0, 8 },
-	{ 168, 0, 14, 0, 8 },
-	{ 176, 0, 14, 0, 8 },
-	{ 184, 0, 14, 0, 8 },
-	{ 192, 0, 14, 0, 8 },
-	{ 200, 0, 14, 0, 8 },
-	{ 208, 0, 14, 0, 8 },
-	{ 216, 0, 14, 0, 8 },
-	{ 224, 0, 14, 0, 8 },
-	{ 232, 0, 14, 0, 8 },
-	{ 240, 0, 14, 0, 8 },
-	{ 248, 0, 14, 0, 8 },
-	{ 256, 0, 0, 0, 8 },
-	{ 264, 2, 11, 0, 8 },
-	{ 272, 2, 6, 0, 8 },
-	{ 280, 2, 11, 0, 8 },
-	{ 288, 1, 12, 0, 8 },
-	{ 296, 2, 11, 0, 8 },
-	{ 304, 2, 11, 0, 8 },
-	{ 312, 2, 7, 0, 8 },
-	{ 320, 1, 13, 0, 8 },
-	{ 328, 1, 13, 0, 8 },
-	{ 336, 3, 10, 0, 8 },
-	{ 344, 4, 10, 0, 8 },
-	{ 352, 9, 14, 0, 8 },
-	{ 360, 6, 8, 0, 8 },
-	{ 368, 9, 11, 0, 8 },
-	{ 376, 1, 13, 0, 8 },
-	{ 384, 2, 11, 0, 8 },
-	{ 392, 2, 11, 0, 8 },
-	{ 400, 2, 11, 0, 8 },
-	{ 408, 2, 11, 0, 8 },
-	{ 416, 2, 11, 0, 8 },
-	{ 424, 2, 11, 0, 8 },
-	{ 432, 2, 11, 0, 8 },
-	{ 440, 2, 11, 0, 8 },
-	{ 448, 2, 11, 0, 8 },
-	{ 456, 2, 11, 0, 8 },
-	{ 464, 4, 11, 0, 8 },
-	{ 472, 4, 14, 0, 8 },
-	{ 480, 2, 11, 0, 8 },
-	{ 488, 4, 10, 0, 8 },
-	{ 496, 2, 11, 0, 8 },
-	{ 504, 2, 11, 0, 8 },
-	{ 512, 2, 11, 0, 8 },
-	{ 520, 2, 11, 0, 8 },
-	{ 528, 2, 11, 0, 8 },
-	{ 536, 2, 11, 0, 8 },
-	{ 544, 2, 11, 0, 8 },
-	{ 552, 2, 11, 0, 8 },
-	{ 560, 2, 11, 0, 8 },
-	{ 568, 2, 11, 0, 8 },
-	{ 576, 2, 11, 0, 8 },
-	{ 584, 2, 11, 0, 8 },
-	{ 592, 2, 13, 0, 8 },
-	{ 600, 2, 11, 0, 8 },
-	{ 608, 2, 11, 0, 8 },
-	{ 616, 2, 11, 0, 8 },
-	{ 624, 2, 11, 0, 8 },
-	{ 632, 2, 11, 0, 8 },
-	{ 640, 2, 11, 0, 8 },
-	{ 648, 2, 13, 0, 8 },
-	{ 656, 2, 11, 0, 8 },
-	{ 664, 2, 11, 0, 8 },
-	{ 672, 2, 11, 0, 8 },
-	{ 680, 2, 11, 0, 8 },
-	{ 688, 2, 11, 0, 8 },
-	{ 696, 2, 11, 0, 8 },
-	{ 704, 2, 11, 0, 8 },
-	{ 712, 2, 11, 0, 8 },
-	{ 720, 2, 11, 0, 8 },
-	{ 728, 1, 13, 0, 8 },
-	{ 736, 1, 13, 0, 8 },
-	{ 744, 1, 13, 0, 8 },
-	{ 752, 2, 8, 0, 8 },
-	{ 760, 11, 12, 0, 8 },
-	{ 768, 2, 7, 0, 8 },
-	{ 776, 4, 11, 0, 8 },
-	{ 784, 1, 11, 0, 8 },
-	{ 792, 4, 11, 0, 8 },
-	{ 800, 1, 11, 0, 8 },
-	{ 808, 4, 11, 0, 8 },
-	{ 816, 1, 11, 0, 8 },
-	{ 824, 4, 14, 0, 8 },
-	{ 832, 1, 11, 0, 8 },
-	{ 840, 1, 11, 0, 8 },
-	{ 848, 1, 14, 0, 8 },
-	{ 856, 1, 11, 0, 8 },
-	{ 864, 1, 11, 0, 8 },
-	{ 872, 4, 11, 0, 8 },
-	{ 880, 4, 11, 0, 8 },
-	{ 888, 4, 11, 0, 8 },
-	{ 896, 4, 14, 0, 8 },
-	{ 904, 4, 14, 0, 8 },
-	{ 912, 4, 11, 0, 8 },
-	{ 920, 4, 11, 0, 8 },
-	{ 928, 2, 11, 0, 8 },
-	{ 936, 4, 11, 0, 8 },
-	{ 944, 4, 11, 0, 8 },
-	{ 952, 4, 11, 0, 8 },
-	{ 960, 4, 11, 0, 8 },
-	{ 968, 4, 14, 0, 8 },
-	{ 976, 4, 11, 0, 8 },
-	{ 984, 1, 12, 0, 8 },
-	{ 992, 1, 12, 0, 8 },
-	{ 1000, 1, 12, 0, 8 },
-	{ 1008, 5, 8, 0, 8 },
-	{ 1016, 0, 14, 0, 8 },
-	{ 1024, 0, 14, 0, 8 },
-	{ 0, 0, 0, 0, 0 }
-};
-
-GSubfont defont0 = {
-	129,
-	14,
-	2,
-	info0,
-	&strike0,
-};
--- a/os/boot/rpcg/devether.c
+++ /dev/null
@@ -1,157 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-#include "etherif.h"
-
-static Ctlr ether[MaxEther];
-
-static struct {
-	char	*type;
-	int	(*reset)(Ctlr*);
-} cards[] = {
-	{ "SCC", sccethreset, },
-	{ "SCC2", sccethreset, },
-	{ 0, }
-};
-
-int
-etherinit(void)
-{
-	Ctlr *ctlr;
-	int ctlrno, i, mask, n;
-
-	mask = 0;
-	for(ctlrno = 0; ctlrno < MaxEther; ctlrno++){
-		ctlr = &ether[ctlrno];
-		memset(ctlr, 0, sizeof(Ctlr));
-		if(archether(ctlrno, &ctlr->card) <= 0)
-			continue;
-		for(n = 0; cards[n].type; n++){
-			if(strcmp(cards[n].type, ctlr->card.type))
-				continue;
-			ctlr->ctlrno = ctlrno;
-			if((*cards[n].reset)(ctlr))
-				break;
-
-			ctlr->iq = qopen(16*1024, 1, 0, 0);
-			ctlr->oq = qopen(16*1024, 1, 0, 0);
-
-			ctlr->present = 1;
-			mask |= 1<<ctlrno;
-
-			print("ether%d: %s: port 0x%luX irq %d",
-				ctlr->ctlrno, ctlr->card.type, ctlr->card.port, ctlr->card.irq);
-			if(ctlr->card.mem)
-				print(" addr 0x%luX", PADDR(ctlr->card.mem));
-			if(ctlr->card.size)
-				print(" size 0x%luX", ctlr->card.size);
-			print(":");
-			for(i = 0; i < sizeof(ctlr->card.ea); i++)
-				print(" %2.2uX", ctlr->card.ea[i]);
-			print("\n"); uartwait();
-			setvec(VectorPIC + ctlr->card.irq, ctlr->card.intr, ctlr);
-			break;
-		}
-	}
-
-	return mask;
-}
-
-static Ctlr*
-attach(int ctlrno)
-{
-	Ctlr *ctlr;
-
-	if(ctlrno >= MaxEther || ether[ctlrno].present == 0)
-		return 0;
-
-	ctlr = &ether[ctlrno];
-	if(ctlr->present == 1){
-		ctlr->present = 2;
-		(*ctlr->card.attach)(ctlr);
-	}
-
-	return ctlr;
-}
-
-uchar*
-etheraddr(int ctlrno)
-{
-	Ctlr *ctlr;
-
-	if((ctlr = attach(ctlrno)) == 0)
-		return 0;
-
-	return ctlr->card.ea;
-}
-
-int
-etherrxpkt(int ctlrno, Etherpkt *pkt, int timo)
-{
-	int n;
-	Ctlr *ctlr;
-	Block *b;
-	ulong start;
-
-	if((ctlr = attach(ctlrno)) == 0)
-		return 0;
-
-	start = m->ticks;
-	while((b = qget(ctlr->iq)) == 0){
-		if(TK2MS(m->ticks - start) >= timo){
-			/*
-			print("ether%d: rx timeout\n", ctlrno);
-			 */
-			return 0;
-		}
-	}
-
-	n = BLEN(b);
-	memmove(pkt, b->rp, n);
-	freeb(b);
-
-	return n;
-}
-
-int
-etheriq(Ctlr *ctlr, Block *b, int freebp)
-{
-	if(memcmp(((Etherpkt*)b->rp)->d, ctlr->card.ea, Eaddrlen) != 0 &&
-	   memcmp(((Etherpkt*)b->rp)->d, broadcast, Eaddrlen) != 0){
-		if(freebp)
-			freeb(b);
-		return 0;
-	}
-	qbwrite(ctlr->iq, b);
-	return 1;
-}
-
-int
-ethertxpkt(int ctlrno, Etherpkt *pkt, int len, int)
-{
-	Ctlr *ctlr;
-	Block *b;
-	int s;
-
-	if((ctlr = attach(ctlrno)) == 0)
-		return 0;
-
-	if(qlen(ctlr->oq) > 16*1024){
-		print("ether%d: tx queue full\n", ctlrno);
-		return 0;
-	}
-	b = iallocb(sizeof(Etherpkt));
-	memmove(b->wp, pkt, len);
-	memmove(((Etherpkt*)b->wp)->s, ctlr->card.ea, Eaddrlen);
-	b->wp += len;
-	qbwrite(ctlr->oq, b);
-	s = splhi();
-	(*ctlr->card.transmit)(ctlr);
-	splx(s);
-
-	return 1;
-}
--- a/os/boot/rpcg/devuart.c
+++ /dev/null
@@ -1,230 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-/*
- *  SMC1 in UART mode
- */
-
-typedef struct Uartsmc Uartsmc;
-struct Uartsmc {
-	IOCparam;
-	ushort	maxidl;
-	ushort	idlc;
-	ushort	brkln;
-	ushort	brkec;
-	ushort	brkcr;
-	ushort	rmask;
-};
-
-typedef struct Uart	Uart;
-struct Uart
-{
-	int	port;
-	int	setup;
-	uchar	txbusy;
-
-	Queue*	iq;
-	Queue*	oq;
-	void	(*rx)(Queue*, int);
-	void	(*boot)(uchar*, int);
-
-	ulong	frame;
-	ulong	overrun;
-	uchar	rxbuf[128];
-	char	txbuf[16];
-	BD*	rxb;
-	BD*	txb;
-};
-
-Uart	uart[1];
-int	predawn = 1;
-
-static	void	uartintr(Ureg*, void*);
-static	void	uartkick(void*);
-
-static int
-baudgen(int baud)
-{
-	int d;
-
-	d = ((m->cpuhz/baud)+8)>>4;
-	if(d >= (1<<12))
-		return ((d+15)>>3)|1;
-	return d<<1;
-}
-
-static void
-smcsetup(Uart *up, int baud)
-{
-	IMM *io;
-	Uartsmc *p;
-	BD *bd;
-	SMC *smc;
-
-	archenableuart(SMC1ID, 0);
-	io = m->iomem;
-	io->pbpar |= IBIT(24)|IBIT(25);	/* enable SMC1 TX/RX */
-	io->pbdir &= ~(IBIT(24)|IBIT(25));
-	io->brgc1 = baudgen(baud) | BaudEnable;
-	io->simode &= ~0xF000;	/* SMC1 to NMSI mode, Tx/Rx clocks are BRG1 */
-
-	bd = bdalloc(1);
-	p = (Uartsmc*)KADDR(SMC1P);
-	p->rbase = (ushort)bd;
-	up->rxb = bd;
-	bd->status = BDEmpty|BDWrap|BDInt;
-	bd->length = 0;
-	bd->addr = PADDR(up->rxbuf);
-	bd = bdalloc(1);
-	p->tbase = (ushort)bd;
-	up->txb = bd;
-	bd->status = BDWrap|BDInt;
-	bd->length = 0;
-	bd->addr = PADDR(up->txbuf);
-
-	cpmop(InitRxTx, SMC1ID, 0);
-
-	/* protocol parameters */
-	p->rfcr = 0x18;
-	p->tfcr = 0x18;
-	p->mrblr = 1;
-	p->maxidl = 1;
-	p->brkln = 0;
-	p->brkec = 0;
-	p->brkcr = 1;
-	smc = IOREGS(0xA80, SMC);
-	smc->smce = 0xff;	/* clear events */
-	smc->smcm = 0x17;	/* enable all possible interrupts */
-	setvec(VectorCPIC+4, uartintr, up);
-	smc->smcmr = 0x4820;	/* 8-bit mode, no parity, 1 stop bit, UART mode, ... */
-	smc->smcmr |= 3;	/* enable rx/tx */
-}
-
-static void
-uartintr(Ureg*, void *arg)
-{
-	Uart *up;
-	int ch, i;
-	BD *bd;
-	SMC *smc;
-	Block *b;
-
-	up = arg;
-	smc = IOREGS(0xA80, SMC);
-	smc->smce = 0xff;	/* clear all events */
-	if((bd = up->rxb) != nil && (bd->status & BDEmpty) == 0){
-		if(up->iq != nil && bd->length > 0){
-			if(up->boot != nil){
-				up->boot(up->rxbuf, bd->length);
-			}else if(up->rx != nil){
-				for(i=0; i<bd->length; i++){
-					ch = up->rxbuf[i];
-					up->rx(up->iq, ch);
-				}
-			}else{
-				b = iallocb(bd->length);
-				memmove(b->wp, up->rxbuf, bd->length);
-				b->wp += bd->length;
-				qbwrite(up->iq, b);
-			}
-		}
-		bd->status |= BDEmpty|BDInt;
-	} else if((bd = up->txb) != nil && (bd->status & BDReady) == 0){
-		ch = -1;
-		if(up->oq)
-			ch = qbgetc(up->oq);
-		if(ch != -1){
-			up->txbuf[0] = ch;
-			bd->length = 1;
-			bd->status |= BDReady;
-		}else
-			up->txbusy = 0;
-	}
-	/* TO DO: modem status, errors, etc */
-}
-
-static void
-uartkick(void *arg)
-{
-	Uart *up = arg;
-	int s, c, i;
-
-	s = splhi();
-	while(up->txbusy == 0 && (c = qbgetc(up->oq)) != -1){
-		if(predawn){
-			while(up->txb->status & BDReady)
-				;
-		} else {
-			for(i = 0; i < 100; i++){
-				if((up->txb->status & BDReady) == 0)
-					break;
-				delay(1);
-			}
-		}
-		up->txbuf[0] = c;
-		up->txb->length = 1;
-		up->txb->status |= BDReady;
-		up->txbusy = !predawn;
-	}
-	splx(s);
-}
-
-void
-uartspecial(int port, int baud, Queue **iq, Queue **oq, void (*rx)(Queue*,int))
-{
-	Uart *up = &uart[0];
-
-	if(up->setup)
-		return;
-	up->setup = 1;
-
-	*iq = up->iq = qopen(4*1024, 0, 0, 0);
-	*oq = up->oq = qopen(16*1024, 0, uartkick, up);
-	up->rx = rx;
-	USED(port);
-	up->port = SMC1ID;
-	if(baud == 0)
-		baud = 9600;
-	smcsetup(up, baud);
-	/* if using SCCn's UART, would also set DTR and RTS, but SMC doesn't use them */
-}
-
-void
-uartsetboot(void (*f)(uchar*, int))
-{
-	uart[0].boot = f;
-}
-
-void
-uartputs(char *s, int n)
-{
-	Uart *up = &uart[0];
-	Block *b;
-	int nl;
-	char *p;
-
-	nl = 0;
-	for(p = s; p < s+n; p++)
-		if(*p == '\n')
-			nl++;
-	b = iallocb(n+nl);
-	while(n--){
-		if(*s == '\n')
-			*b->wp++ = '\r';
-		*b->wp++ = *s++;
-	}
-	qbwrite(up->oq, b);
-}
-
-void
-uartwait(void)
-{
-	Uart *up = &uart[0];
-
-	while(up->txbusy)
-		;
-}
--- a/os/boot/rpcg/dload.c
+++ /dev/null
@@ -1,103 +1,0 @@
-#include <u.h>
-#include <libc.h>
-#include <bio.h>
-#include <mach.h>
-
-static	char	*kernelfile = "/power/ipaq";
-ulong	crc32(void *buf, int n, ulong crc);
-
-void
-main(int argc, char **argv)
-{
-	int ifd, n;
-	char buf[64], reply[1];
-	int i, execsize;
-	Fhdr f;
-	ulong csum;
-
-	ARGBEGIN{
-	}ARGEND
-	ifd = open(kernelfile, OREAD);
-	if(ifd < 0){
-		fprint(2, "dload: can't open %s: %r\n", kernelfile);
-		exits("open");
-	}
-	i = 0;
-	if(crackhdr(ifd, &f) == 0){
-		fprint(2, "dload: not an executable file: %r\n");
-		exits("format");
-	}
-	if(f.magic != Q_MAGIC){
-		fprint(2, "dload: not a powerpc executable\n");
-		exits("format");
-	}
-	execsize = f.txtsz + f.datsz + f.txtoff;
-	seek(ifd, 0, 0);
-	csum = ~0;
-	while(execsize > 0 && (n = read(ifd, buf, sizeof(buf))) > 0){
-		if(n > execsize)
-			n = execsize;
-		for(;;){
-			if(write(1, buf, sizeof(buf)) != sizeof(buf)){	/* always writes full buffer */
-				fprint(2, "dload: write error: %r\n");
-				exits("write");
-			}
-			if(read(0, reply, 1) != 1){
-				fprint(2, "dload: bad reply\n");
-				exits("read");
-			}
-			if(reply[0] != 'n')
-				break;
-			fprint(2, "!");
-		}
-		if(reply[0] != 'y'){
-			fprint(2, "dload: bad ack: %c\n", reply[0]);
-			exits("reply");
-		}
-		if(++i%10 == 0)
-			fprint(2, ".");
-		execsize -= n;
-	}
-	exits(0);
-}
-
-/*
- * from Rob Warnock
- */
-static	ulong	crc32tab[256];	/* initialised on first call to crc32 */
-
-enum {
-	CRC32POLY = 0x04c11db7     /* AUTODIN II, Ethernet, & FDDI */
-};
-
-/*
- * Build auxiliary table for parallel byte-at-a-time CRC-32.
- */
-static void
-initcrc32(void)
-{
-	int i, j;
-	ulong c;
-
-	for(i = 0; i < 256; i++) {
-		for(c = i << 24, j = 8; j > 0; j--)
-			if(c & (1<<31))
-				c = (c<<1) ^ CRC32POLY;
-			else
-				c <<= 1;
-		crc32tab[i] = c;
-	}
-}
-
-ulong
-crc32(void *buf, int n, ulong crc)
-{
-	uchar *p;
-
-	if(crc32tab[1] == 0)
-		initcrc32();
-	crc = ~crc;
-	for(p = buf; --n >= 0;)
-		crc = (crc << 8) ^ crc32tab[(crc >> 24) ^ *p++];
-	return ~crc;
-}
--- a/os/boot/rpcg/donprint.c
+++ /dev/null
@@ -1,332 +1,0 @@
-#include	"u.h"
-#include	"lib.h"
-
-#define	PTR	sizeof(char*)
-#define	SHORT	sizeof(int)
-#define	INT	sizeof(int)
-#define	LONG	sizeof(long)
-#define	IDIGIT	30
-#define	MAXCON	30
-
-#define	FLONG	(1<<0)
-#define	FSHORT	(1<<1)
-#define	FUNSIGN	(1<<2)
-
-typedef struct Op	Op;
-struct Op
-{
-	char	*p;
-	char	*ep;
-	void	*argp;
-	int	f1;
-	int	f2;
-	int	f3;
-};
-
-static	int	noconv(Op*);
-static	int	cconv(Op*);
-static	int	dconv(Op*);
-static	int	hconv(Op*);
-static	int	lconv(Op*);
-static	int	oconv(Op*);
-static	int	sconv(Op*);
-static	int	uconv(Op*);
-static	int	xconv(Op*);
-static	int	Xconv(Op*);
-static	int	percent(Op*);
-
-static
-int	(*fmtconv[MAXCON])(Op*) =
-{
-	noconv,
-	cconv, dconv, hconv, lconv,
-	oconv, sconv, uconv, xconv,
-	Xconv, percent,
-};
-static
-char	fmtindex[128] =
-{
-	['c'] 1,
-	['d'] 2,
-	['h'] 3,
-	['l'] 4,
-	['o'] 5,
-	['s'] 6,
-	['u'] 7,
-	['x'] 8,
-	['X'] 9,
-	['%'] 10,
-};
-
-static	int	convcount  = { 11 };
-static	int	ucase;
-
-static void
-PUT(Op *o, int c)
-{
-	static int pos;
-	int opos;
-
-	if(c == '\t'){
-		opos = pos;
-		pos = (opos+8) & ~7;
-		while(opos++ < pos && o->p < o->ep)
-			*o->p++ = ' ';
-		return;
-	}
-	if(o->p < o->ep){
-		*o->p++ = c;
-		pos++;
-	}
-	if(c == '\n')
-		pos = 0;
-}
-
-int
-fmtinstall(char c, int (*f)(Op*))
-{
-
-	c &= 0177;
-	if(fmtindex[c] == 0) {
-		if(convcount >= MAXCON)
-			return 1;
-		fmtindex[c] = convcount++;
-	}
-	fmtconv[fmtindex[c]] = f;
-	return 0;
-}
-
-char*
-donprint(char *p, char *ep, char *fmt, void *argp)
-{
-	int sf1, c;
-	Op o;
-
-	o.p = p;
-	o.ep = ep;
-	o.argp = argp;
-
-loop:
-	c = *fmt++;
-	if(c != '%') {
-		if(c == 0) {
-			if(o.p < o.ep)
-				*o.p = 0;
-			return o.p;
-		}
-		PUT(&o, c);
-		goto loop;
-	}
-	o.f1 = 0;
-	o.f2 = -1;
-	o.f3 = 0;
-	c = *fmt++;
-	sf1 = 0;
-	if(c == '-') {
-		sf1 = 1;
-		c = *fmt++;
-	}
-	while(c >= '0' && c <= '9') {
-		o.f1 = o.f1*10 + c-'0';
-		c = *fmt++;
-	}
-	if(sf1)
-		o.f1 = -o.f1;
-	if(c != '.')
-		goto l1;
-	c = *fmt++;
-	while(c >= '0' && c <= '9') {
-		if(o.f2 < 0)
-			o.f2 = 0;
-		o.f2 = o.f2*10 + c-'0';
-		c = *fmt++;
-	}
-l1:
-	if(c == 0)
-		fmt--;
-	c = (*fmtconv[fmtindex[c&0177]])(&o);
-	if(c < 0) {
-		o.f3 |= -c;
-		c = *fmt++;
-		goto l1;
-	}
-	o.argp = (char*)o.argp + c;
-	goto loop;
-}
-
-void
-strconv(char *o, Op *op, int f1, int f2)
-{
-	int n, c;
-	char *p;
-
-	n = strlen(o);
-	if(f1 >= 0)
-		while(n < f1) {
-			PUT(op, ' ');
-			n++;
-		}
-	for(p=o; c = *p++;)
-		if(f2 != 0) {
-			PUT(op, c);
-			f2--;
-		}
-	if(f1 < 0) {
-		f1 = -f1;
-		while(n < f1) {
-			PUT(op, ' ');
-			n++;
-		}
-	}
-}
-
-int
-numbconv(Op *op, int base)
-{
-	char b[IDIGIT];
-	int i, f, n, r;
-	long v;
-	short h;
-
-	f = 0;
-	switch(op->f3 & (FLONG|FSHORT|FUNSIGN)) {
-	case FLONG:
-		v = *(long*)op->argp;
-		r = LONG;
-		break;
-
-	case FUNSIGN|FLONG:
-		v = *(ulong*)op->argp;
-		r = LONG;
-		break;
-
-	case FSHORT:
-		h = *(int*)op->argp;
-		v = h;
-		r = SHORT;
-		break;
-
-	case FUNSIGN|FSHORT:
-		h = *(int*)op->argp;
-		v = (ushort)h;
-		r = SHORT;
-		break;
-
-	default:
-		v = *(int*)op->argp;
-		r = INT;
-		break;
-
-	case FUNSIGN:
-		v = *(unsigned*)op->argp;
-		r = INT;
-		break;
-	}
-	if(!(op->f3 & FUNSIGN) && v < 0) {
-		v = -v;
-		f = 1;
-	}
-	b[IDIGIT-1] = 0;
-	for(i = IDIGIT-2;; i--) {
-		n = (ulong)v % base;
-		n += '0';
-		if(n > '9'){
-			n += 'a' - ('9'+1);
-			if(ucase)
-				n += 'A'-'a';
-		}
-		b[i] = n;
-		if(i < 2)
-			break;
-		v = (ulong)v / base;
-		if(op->f2 >= 0 && i >= IDIGIT-op->f2)
-			continue;
-		if(v <= 0)
-			break;
-	}
-	if(f)
-		b[--i] = '-';
-	strconv(b+i, op, op->f1, -1);
-	return r;
-}
-
-static	int
-noconv(Op *op)
-{
-
-	strconv("***", op, 0, -1);
-	return 0;
-}
-
-static	int
-cconv(Op *op)
-{
-	char b[2];
-
-	b[0] = *(int*)op->argp;
-	b[1] = 0;
-	strconv(b, op, op->f1, -1);
-	return INT;
-}
-
-static	int
-dconv(Op *op)
-{
-	return numbconv(op, 10);
-}
-
-static	int
-hconv(Op*)
-{
-	return -FSHORT;
-}
-
-static	int
-lconv(Op*)
-{
-	return -FLONG;
-}
-
-static	int
-oconv(Op *op)
-{
-	return numbconv(op, 8);
-}
-
-static	int
-sconv(Op *op)
-{
-	strconv(*(char**)op->argp, op, op->f1, op->f2);
-	return PTR;
-}
-
-static	int
-uconv(Op*)
-{
-	return -FUNSIGN;
-}
-
-static	int
-xconv(Op *op)
-{
-	return numbconv(op, 16);
-}
-
-static	int
-Xconv(Op *op)
-{
-	int r;
-
-	ucase = 1;
-	r = numbconv(op, 16);
-	ucase = 0;
-	return r;
-}
-
-static	int
-percent(Op *op)
-{
-
-	PUT(op, '%');
-	return 0;
-}
--- a/os/boot/rpcg/dosboot.c
+++ /dev/null
@@ -1,614 +1,0 @@
-#include	"u.h"
-#include	"lib.h"
-#include	"mem.h"
-#include	"dat.h"
-#include	"fns.h"
-#include	"dosfs.h"
-
-extern char *premature;
-
-/*
- *  predeclared
- */
-static void	bootdump(Dosboot*);
-static void	setname(Dosfile*, char*);
-long		dosreadseg(Dosfile*, long, long);
-
-/*
- *  debugging
- */
-#define chatty	1
-#define chat	if(chatty)print
-
-/*
- *  block io buffers
- */
-enum
-{
-	Nbio=	16,
-};
-typedef struct	Clustbuf	Clustbuf;
-struct Clustbuf
-{
-	int	age;
-	long	sector;
-	uchar	*iobuf;
-	Dos	*dos;
-	int	size;
-};
-Clustbuf	bio[Nbio];
-
-/*
- *  get an io block from an io buffer
- */
-Clustbuf*
-getclust(Dos *dos, long sector)
-{
-	Clustbuf *p, *oldest;
-	int size;
-
-	chat("getclust @ %d\n", sector);
-
-	/*
-	 *  if we have it, just return it
-	 */
-	for(p = bio; p < &bio[Nbio]; p++){
-		if(sector == p->sector && dos == p->dos){
-			p->age = m->ticks;
-			chat("getclust %d in cache\n", sector);
-			return p;
-		}
-	}
-
-	/*
-	 *  otherwise, reuse the oldest entry
-	 */
-	oldest = bio;
-	for(p = &bio[1]; p < &bio[Nbio]; p++){
-		if(p->age <= oldest->age)
-			oldest = p;
-	}
-	p = oldest;
-
-	/*
-	 *  make sure the buffer is big enough
-	 */
-	size = dos->clustsize*dos->sectsize;
-	if(p->iobuf==0 || p->size < size)
-		p->iobuf = ialloc(size, 0);
-	p->size = size;
-
-	/*
-	 *  read in the cluster
-	 */
-	chat("getclust addr %d\n", (sector+dos->start)*dos->sectsize);
-	if((*dos->seek)(dos->dev, (sector+dos->start)*dos->sectsize) < 0){
-		chat("can't seek block\n");
-		return 0;
-	}
-	if((*dos->read)(dos->dev, p->iobuf, size) != size){
-		chat("can't read block\n");
-		return 0;
-	}
-
-	p->age = m->ticks;
-	p->dos = dos;
-	p->sector = sector;
-	chat("getclust %d read\n", sector);
-	return p;
-}
-
-/*
- *  walk the fat one level ( n is a current cluster number ).
- *  return the new cluster number or -1 if no more.
- */
-static long
-fatwalk(Dos *dos, int n)
-{
-	ulong k, sect;
-	Clustbuf *p;
-	int o;
-
-	chat("fatwalk %d\n", n);
-
-	if(n < 2 || n >= dos->fatclusters)
-		return -1;
-
-	switch(dos->fatbits){
-	case 12:
-		k = (3*n)/2; break;
-	case 16:
-		k = 2*n; break;
-	default:
-		return -1;
-	}
-	if(k >= dos->fatsize*dos->sectsize)
-		panic("getfat");
-
-	sect = (k/(dos->sectsize*dos->clustsize))*dos->clustsize + dos->fataddr;
-	o = k%(dos->sectsize*dos->clustsize);
-	p = getclust(dos, sect);
-	k = p->iobuf[o++];
-	if(o >= dos->sectsize*dos->clustsize){
-		p = getclust(dos, sect+dos->clustsize);
-		o = 0;
-	}
-	k |= p->iobuf[o]<<8;
-	if(dos->fatbits == 12){
-		if(n&1)
-			k >>= 4;
-		else
-			k &= 0xfff;
-		if(k >= 0xff8)
-			k |= 0xf000;
-	}
-	k = k < 0xfff8 ? k : -1;
-	chat("fatwalk %d -> %d\n", n, k);
-	return k;
-}
-
-/*
- *  map a file's logical cluster address to a physical sector address
- */
-static long
-fileaddr(Dosfile *fp, long ltarget)
-{
-	Dos *dos = fp->dos;
-	long l;
-	long p;
-
-	chat("fileaddr %8.8s %d\n", fp->name, ltarget);
-	/*
-	 *  root directory is contiguous and easy
-	 */
-	if(fp->pstart == 0){
-		if(ltarget*dos->sectsize*dos->clustsize >= dos->rootsize*sizeof(Dosdir))
-			return -1;
-		l = dos->rootaddr + ltarget*dos->clustsize;
-		chat("fileaddr %d -> %d\n", ltarget, l);
-		return l;
-	}
-
-	/*
-	 *  anything else requires a walk through the fat
-	 */
-	if(ltarget >= fp->lcurrent && fp->pcurrent){
-		/* start at the currrent point */
-		l = fp->lcurrent;
-		p = fp->pcurrent;
-	} else {
-		/* go back to the beginning */
-		l = 0;
-		p = fp->pstart;
-	}
-	while(l != ltarget){
-		/* walk the fat */
-		p = fatwalk(dos, p);
-		if(p < 0)
-			return -1;
-		l++;
-	}
-	fp->lcurrent = l;
-	fp->pcurrent = p;
-
-	/*
-	 *  clusters start at 2 instead of 0 (why? - presotto)
-	 */
-	l =  dos->dataaddr + (p-2)*dos->clustsize;
-	chat("fileaddr %d -> %d\n", ltarget, l);
-	return l;
-}
-
-/*
- *  read from a dos file
- */
-long
-dosread(Dosfile *fp, void *a, long n)
-{
-	long addr;
-	long rv;
-	int i;
-	int off;
-	Clustbuf *p;
-	uchar *from, *to;
-
-	if((fp->attr & DDIR) == 0){
-		if(fp->offset >= fp->length)
-			return 0;
-		if(fp->offset+n > fp->length)
-			n = fp->length - fp->offset;
-	}
-
-	to = a;
-	for(rv = 0; rv < n; rv+=i){
-		/*
-		 *  read the cluster
-		 */
-		addr = fileaddr(fp, fp->offset/fp->dos->clustbytes);
-		if(addr < 0)
-			return -1;
-		p = getclust(fp->dos, addr);
-		if(p == 0)
-			return -1;
-
-		/*
-		 *  copy the bytes we need
-		 */
-		off = fp->offset % fp->dos->clustbytes;
-		from = &p->iobuf[off];
-		i = n - rv;
-		if(i > fp->dos->clustbytes - off)
-			i = fp->dos->clustbytes - off;
-		memmove(to, from, i);
-		to += i;
-		fp->offset += i;
-	}
-
-	return rv;
-}
-
-/*
- *  walk a directory returns
- * 	-1 if something went wrong
- *	 0 if not found
- *	 1 if found
- */
-int
-doswalk(Dosfile *file, char *name)
-{
-	Dosdir d;
-	long n;
-
-	if((file->attr & DDIR) == 0){
-		chat("walking non-directory!\n");
-		return -1;
-	}
-
-	setname(file, name);
-
-	file->offset = 0;	/* start at the beginning */
-	while((n = dosread(file, &d, sizeof(d))) == sizeof(d)){
-		chat("comparing to %8.8s.%3.3s\n", d.name, d.ext);
-		if(memcmp(file->name, d.name, sizeof(d.name)) != 0)
-			continue;
-		if(memcmp(file->ext, d.ext, sizeof(d.ext)) != 0)
-			continue;
-		if(d.attr & DVLABEL){
-			chat("%8.8s.%3.3s is a LABEL\n", d.name, d.ext);
-			continue;
-		}
-		file->attr = d.attr;
-		file->pstart = GSHORT(d.start);
-		file->length = GLONG(d.length);
-		file->pcurrent = 0;
-		file->lcurrent = 0;
-		file->offset = 0;
-		return 1;
-	}
-	return n >= 0 ? 0 : -1;
-}
-
-
-/*
- *  instructions that boot blocks can start with
- */
-#define	JMPSHORT	0xeb
-#define JMPNEAR		0xe9
-
-/*
- *  read dos file system properties
- */
-int
-dosinit(Dos *dos, int start, int ishard)
-{
-	Dosboot *b;
-	int i;
-	Clustbuf *p;
-	Dospart *dp;
-	ulong mbroffset, offset;
-
-	/* defaults till we know better */
-	dos->start = start;
-	dos->sectsize = 512;
-	dos->clustsize = 1;
-	mbroffset = 0;
-
-dmddo:
-	/* get first sector */
-	p = getclust(dos, mbroffset);
-	if(p == 0){
-		chat("can't read boot block\n");
-		return -1;
-	}
-
-	/*
-	 * If it's a hard disc then look for an MBR and pick either an
-	 * active partition or the FAT with the lowest starting LBA.
-	 * Things are tricky because we could be pointing to, amongst others:
-	 *	1) a floppy BPB;
-	 *	2) a hard disc MBR;
-	 *	3) a hard disc extended partition table;
-	 *	4) a logical drive on a hard disc;
-	 *	5) a disc-manager boot block.
-	 * They all have the same magic at the end of the block.
-	 */
-	if(p->iobuf[0x1FE] != 0x55 || p->iobuf[0x1FF] != 0xAA) {
-		chat("not DOS\n");
-		return -1;
-	}
-	p->dos = 0;
-	b = (Dosboot *)p->iobuf;
-	if(ishard && b->mediadesc != 0xF8){
-		dp = (Dospart*)&p->iobuf[0x1BE];
-		offset = 0xFFFFFFFF;
-		for(i = 0; i < 4; i++, dp++){
-			if(dp->type == DMDDO){
-				mbroffset = 63;
-				goto dmddo;
-			}
-			if(dp->type != FAT12 && dp->type != FAT16 && dp->type != FATHUGE)
-				continue;
-			if(dp->flag & 0x80){
-				offset = GLONG(dp->start);
-				break;
-			}
-			if(GLONG(dp->start) < offset)
-				offset = GLONG(dp->start);
-		}
-		if(i != 4 || offset != 0xFFFFFFFF){
-			dos->start = mbroffset+offset;
-			p = getclust(dos, 0);
-			if(p == 0 || p->iobuf[0x1FE] != 0x55 || p->iobuf[0x1FF] != 0xAA)
-				return -1;
-		}
-		p->dos = 0;
-	}
-
-	b = (Dosboot *)p->iobuf;
-	if(b->magic[0] != JMPNEAR && (b->magic[0] != JMPSHORT || b->magic[2] != 0x90)){
-		chat("no dos file system\n");
-		return -1;
-	}
-
-	if(chatty)
-		bootdump(b);
-
-	/*
-	 *  determine the systems' wondersous properties
-	 */
-	dos->sectsize = GSHORT(b->sectsize);
-	dos->clustsize = b->clustsize;
-	dos->clustbytes = dos->sectsize*dos->clustsize;
-	dos->nresrv = GSHORT(b->nresrv);
-	dos->nfats = b->nfats;
-	dos->rootsize = GSHORT(b->rootsize);
-	dos->volsize = GSHORT(b->volsize);
-	if(dos->volsize == 0)
-		dos->volsize = GLONG(b->bigvolsize);
-	dos->mediadesc = b->mediadesc;
-	dos->fatsize = GSHORT(b->fatsize);
-	dos->fataddr = dos->nresrv;
-	dos->rootaddr = dos->fataddr + dos->nfats*dos->fatsize;
-	i = dos->rootsize*sizeof(Dosdir) + dos->sectsize - 1;
-	i = i/dos->sectsize;
-	dos->dataaddr = dos->rootaddr + i;
-	dos->fatclusters = 2+(dos->volsize - dos->dataaddr)/dos->clustsize;
-	if(dos->fatclusters < 4087)
-		dos->fatbits = 12;
-	else
-		dos->fatbits = 16;
-	dos->freeptr = 2;
-
-	/*
-	 *  set up the root
-	 */
-	dos->root.dos = dos;
-	dos->root.pstart = 0;
-	dos->root.pcurrent = dos->root.lcurrent = 0;
-	dos->root.offset = 0;
-	dos->root.attr = DDIR;
-	dos->root.length = dos->rootsize*sizeof(Dosdir);
-
-	return 0;
-}
-
-static void
-bootdump(Dosboot *b)
-{
-	if(chatty == 0)
-		return;
-	print("magic: 0x%2.2x 0x%2.2x 0x%2.2x\n",
-		b->magic[0], b->magic[1], b->magic[2]);
-	print("version: \"%8.8s\"\n", b->version);
-	print("sectsize: %d\n", GSHORT(b->sectsize));
-	print("allocsize: %d\n", b->clustsize);
-	print("nresrv: %d\n", GSHORT(b->nresrv));
-	print("nfats: %d\n", b->nfats);
-	print("rootsize: %d\n", GSHORT(b->rootsize));
-	print("volsize: %d\n", GSHORT(b->volsize));
-	print("mediadesc: 0x%2.2x\n", b->mediadesc);
-	print("fatsize: %d\n", GSHORT(b->fatsize));
-	print("trksize: %d\n", GSHORT(b->trksize));
-	print("nheads: %d\n", GSHORT(b->nheads));
-	print("nhidden: %d\n", GLONG(b->nhidden));
-	print("bigvolsize: %d\n", GLONG(b->bigvolsize));
-	print("driveno: %d\n", b->driveno);
-	print("reserved0: 0x%2.2x\n", b->reserved0);
-	print("bootsig: 0x%2.2x\n", b->bootsig);
-	print("volid: 0x%8.8x\n", GLONG(b->volid));
-	print("label: \"%11.11s\"\n", b->label);
-}
-
-/*
- *  grab next element from a path, return the pointer to unprocessed portion of
- *  path.
- */
-static char *
-nextelem(char *path, char *elem)
-{
-	int i;
-
-	while(*path == '/')
-		path++;
-	if(*path==0 || *path==' ')
-		return 0;
-	for(i=0; *path!='\0' && *path!='/' && *path!=' '; i++){
-		if(i==28){
-			print("name component too long\n");
-			return 0;
-		}
-		*elem++ = *path++;
-	}
-	*elem = '\0';
-	return path;
-}
-
-int
-dosstat(Dos *dos, char *path, Dosfile *f)
-{
-	char element[NAMELEN];
-
-	*f = dos->root;
-	while(path = nextelem(path, element)){
-		switch(doswalk(f, element)){
-		case -1:
-			return -1;
-		case 0:
-			return 0;
-		}
-	}
-	return 1;
-}
-
-/*
- *  boot
- */
-int
-dosboot(Dos *dos, char *path)
-{
-	Dosfile file;
-	long n;
-	long addr;
-	Exec *ep;
-	void (*b)(void);
-
-	switch(dosstat(dos, path, &file)){
-
-	case -1:
-		print("error walking to %s\n", path);
-		return -1;
-	case 0:
-		print("%s not found\n", path);
-		return -1;
-	case 1:
-		print("found %8.8s.%3.3s attr 0x%ux start 0x%lux len %d\n", file.name,
-			file.ext, file.attr, file.pstart, file.length);
-		break;
-	}
-
-	/*
-	 *  read header
-	 */
-	ep = (Exec*)ialloc(sizeof(Exec), 0);
-	n = sizeof(Exec);
-	if(dosreadseg(&file, n, (ulong) ep) != n){
-		print(premature);
-		return -1;
-	}
-	if(GLLONG(ep->magic) != Q_MAGIC){
-		print("bad magic 0x%lux not a plan 9 executable!\n", GLLONG(ep->magic));
-		return -1;
-	}
-
-	/*
-	 *  read text
-	 */
-	addr = PADDR(GLLONG(ep->entry));
-	n = GLLONG(ep->text);
-	print("+%d", n);
-	if(dosreadseg(&file, n, addr) != n){
-		print(premature);
-		return -1;
-	}
-
-	/*
-	 *  read data (starts at first page after kernel)
-	 */
-	addr = PGROUND(addr+n);
-	n = GLLONG(ep->data);
-	print("+%d", n);
-	if(dosreadseg(&file, n, addr) != n){
-		print(premature);
-		return -1;
-	}
-
-	/*
-	 *  bss and entry point
-	 */
-	print("+%d\nstart at 0x%lux\n", GLLONG(ep->bss), GLLONG(ep->entry));
-
-	/*
-	 *  Go to new code. It's up to the program to get its PC relocated to
-	 *  the right place.
-	 */
-	b = (void (*)(void))(PADDR(GLLONG(ep->entry)));
-	(*b)();
-	return 0;
-}
-
-/*
- *  read in a segment
- */
-long
-dosreadseg(Dosfile *fp, long len, long addr)
-{
-	char *a;
-	long n, sofar;
-
-	a = (char *)addr;
-	for(sofar = 0; sofar < len; sofar += n){
-		n = 8*1024;
-		if(len - sofar < n)
-			n = len - sofar;
-		n = dosread(fp, a + sofar, n);
-		if(n <= 0)
-			break;
-		print(".");
-	}
-	return sofar;
-}
-
-/*
- *  set up a dos file name
- */
-static void
-setname(Dosfile *fp, char *from)
-{
-	char *to;
-
-	to = fp->name;
-	for(; *from && to-fp->name < 8; from++, to++){
-		if(*from == '.'){
-			from++;
-			break;
-		}
-		if(*from >= 'a' && *from <= 'z')
-			*to = *from + 'A' - 'a';
-		else
-			*to = *from;
-	}
-	while(to - fp->name < 8)
-		*to++ = ' ';
-	
-	to = fp->ext;
-	for(; *from && to-fp->ext < 3; from++, to++){
-		if(*from >= 'a' && *from <= 'z')
-			*to = *from + 'A' - 'a';
-		else
-			*to = *from;
-	}
-	while(to-fp->ext < 3)
-		*to++ = ' ';
-
-	chat("name is %8.8s %3.3s\n", fp->name, fp->ext);
-}
--- a/os/boot/rpcg/dosfs.h
+++ /dev/null
@@ -1,110 +1,0 @@
-typedef struct Dosboot	Dosboot;
-typedef struct Dos	Dos;
-typedef struct Dosdir	Dosdir;
-typedef struct Dosfile	Dosfile;
-typedef struct Dospart	Dospart;
-
-struct Dospart
-{
-	uchar flag;		/* active flag */
-	uchar shead;		/* starting head */
-	uchar scs[2];		/* starting cylinder/sector */
-	uchar type;		/* partition type */
-	uchar ehead;		/* ending head */
-	uchar ecs[2];		/* ending cylinder/sector */
-	uchar start[4];		/* starting sector */
-	uchar len[4];		/* length in sectors */
-};
-
-#define FAT12	0x01
-#define FAT16	0x04
-#define FATHUGE	0x06
-#define DMDDO	0x54
-
-struct Dosboot{
-	uchar	magic[3];
-	uchar	version[8];
-	uchar	sectsize[2];
-	uchar	clustsize;
-	uchar	nresrv[2];
-	uchar	nfats;
-	uchar	rootsize[2];
-	uchar	volsize[2];
-	uchar	mediadesc;
-	uchar	fatsize[2];
-	uchar	trksize[2];
-	uchar	nheads[2];
-	uchar	nhidden[4];
-	uchar	bigvolsize[4];
-	uchar	driveno;
-	uchar	reserved0;
-	uchar	bootsig;
-	uchar	volid[4];
-	uchar	label[11];
-	uchar	reserved1[8];
-};
-
-struct Dosfile{
-	Dos	*dos;		/* owning dos file system */
-	char	name[8];
-	char	ext[3];
-	uchar	attr;
-	long	length;
-	long	pstart;		/* physical start cluster address */
-	long	pcurrent;	/* physical current cluster address */
-	long	lcurrent;	/* logical current cluster address */
-	long	offset;
-};
-
-struct Dos{
-	int	dev;				/* device id */
-	long	(*read)(int, void*, long);	/* read routine */
-	long	(*seek)(int, long);		/* seek routine */
-
-	int	start;		/* start of file system */
-	int	sectsize;	/* in bytes */
-	int	clustsize;	/* in sectors */
-	int	clustbytes;	/* in bytes */
-	int	nresrv;		/* sectors */
-	int	nfats;		/* usually 2 */
-	int	rootsize;	/* number of entries */
-	int	volsize;	/* in sectors */
-	int	mediadesc;
-	int	fatsize;	/* in sectors */
-	int	fatclusters;
-	int	fatbits;	/* 12 or 16 */
-	long	fataddr;	/* sector number */
-	long	rootaddr;
-	long	dataaddr;
-	long	freeptr;
-
-	Dosfile	root;
-};
-
-struct Dosdir{
-	uchar	name[8];
-	uchar	ext[3];
-	uchar	attr;
-	uchar	reserved[10];
-	uchar	time[2];
-	uchar	date[2];
-	uchar	start[2];
-	uchar	length[4];
-};
-
-#define	DRONLY	0x01
-#define	DHIDDEN	0x02
-#define	DSYSTEM	0x04
-#define	DVLABEL	0x08
-#define	DDIR	0x10
-#define	DARCH	0x20
-
-extern int chatty;
-
-extern int dosboot(Dos*, char*);
-extern int dosinit(Dos*, int, int);
-extern long dosread(Dosfile*, void*, long);
-extern int dosstat(Dos*, char*, Dosfile*);
-extern int doswalk(Dosfile*, char*);
-
-extern int plan9ini(Dos*, char*);
--- a/os/boot/rpcg/etherif.h
+++ /dev/null
@@ -1,59 +1,0 @@
-/*
- * All the goo for PC ethernet cards.
- */
-typedef struct Card Card;
-typedef struct Type Type;
-typedef struct Ctlr Ctlr;
-
-/*
- * Hardware interface.
- */
-struct Card {
-	ISAConf;
-
-	int	(*reset)(Ctlr*);
-	void	(*attach)(Ctlr*);
-
-	void	*(*read)(Ctlr*, void*, ulong, ulong);
-	void	*(*write)(Ctlr*, ulong, void*, ulong);
-
-	void	(*receive)(Ctlr*);
-	void	(*transmit)(Ctlr*);
-	void	(*intr)(Ureg*, void*);
-	void	(*overflow)(Ctlr*);
-
-	uchar	bit16;			/* true if a 16 bit interface */
-	uchar	ram;			/* true if card has shared memory */
-
-	ulong	dp8390;			/* I/O address of 8390 (if any) */
-	ulong	data;			/* I/O data port if no shared memory */
-	uchar	nxtpkt;			/* software bndry */
-	uchar	tstart;			/* 8390 ring addresses */
-	uchar	pstart;
-	uchar	pstop;
-
-	uchar	dummyrr;		/* do dummy remote read */
-};
-
-/*
- * Software controller.
- */
-struct Ctlr {
-	Card	card;			/* hardware info */
-	int	ctlrno;
-	int	present;
-
-	Queue*	iq;
-	Queue*	oq;
-
-	int	inpackets;
-	int	outpackets;
-	int	crcs;			/* input crc errors */
-	int	oerrs;			/* output errors */
-	int	frames;			/* framing errors */
-	int	overflows;		/* packet overflows */
-	int	buffs;			/* buffering errors */
-};
-
-extern int sccethreset(Ctlr*);
-extern int	etheriq(Ctlr*, Block*, int);
--- a/os/boot/rpcg/etherscc.c
+++ /dev/null
@@ -1,411 +1,0 @@
-/*
- * SCCn ethernet
- */
-
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-#include "etherif.h"
-
-enum {
-	Nrdre		= 32,	/* receive descriptor ring entries */
-	Ntdre		= 4,	/* transmit descriptor ring entries */
-
-	Rbsize		= ETHERMAXTU+4,		/* ring buffer size (+4 for CRC) */
-	Bufsize		= (Rbsize+7)&~7,	/* aligned */
-};
-
-enum {
-	/* ether-specific Rx BD bits */
-	RxMiss=		1<<8,
-	RxeLG=		1<<5,
-	RxeNO=		1<<4,
-	RxeSH=		1<<3,
-	RxeCR=		1<<2,
-	RxeOV=		1<<1,
-	RxeCL=		1<<0,
-	RxError=		(RxeLG|RxeNO|RxeSH|RxeCR|RxeOV|RxeCL),	/* various error flags */
-
-	/* ether-specific Tx BD bits */
-	TxPad=		1<<14,	/* pad short frames */
-	TxTC=		1<<10,	/* transmit CRC */
-	TxeDEF=		1<<9,
-	TxeHB=		1<<8,
-	TxeLC=		1<<7,
-	TxeRL=		1<<6,
-	TxeUN=		1<<1,
-	TxeCSL=		1<<0,
-
-	/* scce */
-	RXB=	1<<0,
-	TXB=	1<<1,
-	BSY=		1<<2,
-	RXF=		1<<3,
-	TXE=		1<<4,
-
-	/* gsmrl */
-	ENR=	1<<5,
-	ENT=	1<<4,
-
-	/* port A */
-	RXD1=	SIBIT(15),
-	TXD1=	SIBIT(14),
-
-	/* port B */
-	RTS1=	IBIT(19),
-
-	/* port C */
-	CTS1=	SIBIT(11),
-	CD1=	SIBIT(10),
-};
-
-typedef struct Etherparam Etherparam;
-struct Etherparam {
-	SCCparam;
-	ulong	c_pres;		/* preset CRC */
-	ulong	c_mask;		/* constant mask for CRC */
-	ulong	crcec;		/* CRC error counter */
-	ulong	alec;		/* alighnment error counter */
-	ulong	disfc;		/* discard frame counter */
-	ushort	pads;		/* short frame PAD characters */
-	ushort	ret_lim;	/* retry limit threshold */
-	ushort	ret_cnt;	/* retry limit counter */
-	ushort	mflr;		/* maximum frame length reg */
-	ushort	minflr;		/* minimum frame length reg */
-	ushort	maxd1;		/* maximum DMA1 length reg */
-	ushort	maxd2;		/* maximum DMA2 length reg */
-	ushort	maxd;		/* rx max DMA */
-	ushort	dma_cnt;	/* rx dma counter */
-	ushort	max_b;		/* max bd byte count */
-	ushort	gaddr[4];		/* group address filter */
-	ulong	tbuf0_data0;	/* save area 0 - current frm */
-	ulong	tbuf0_data1;	/* save area 1 - current frm */
-	ulong	tbuf0_rba0;
-	ulong	tbuf0_crc;
-	ushort	tbuf0_bcnt;
-	ushort	paddr[3];	/* physical address LSB to MSB increasing */
-	ushort	p_per;		/* persistence */
-	ushort	rfbd_ptr;	/* rx first bd pointer */
-	ushort	tfbd_ptr;	/* tx first bd pointer */
-	ushort	tlbd_ptr;	/* tx last bd pointer */
-	ulong	tbuf1_data0;	/* save area 0 - next frame */
-	ulong	tbuf1_data1;	/* save area 1 - next frame */
-	ulong	tbuf1_rba0;
-	ulong	tbuf1_crc;
-	ushort	tbuf1_bcnt;
-	ushort	tx_len;		/* tx frame length counter */
-	ushort	iaddr[4];		/* individual address filter*/
-	ushort	boff_cnt;	/* back-off counter */
-	ushort	taddr[3];	/* temp address */
-};
-
-typedef struct {
-	SCC*	scc;
-	int	port;
-	int	cpm;
-
-	BD*	rdr;				/* receive descriptor ring */
-	void*	rrb;				/* receive ring buffers */
-	int	rdrx;				/* index into rdr */
-
-	BD*	tdr;				/* transmit descriptor ring */
-	void*	trb;				/* transmit ring buffers */
-	int	tdrx;				/* index into tdr */
-} Mot;
-static Mot mot[MaxEther];
-
-static	int	sccid[] = {-1, SCC1ID, SCC2ID, SCC3ID, SCC4ID};
-static	int	sccparam[] = {-1, SCC1P, SCC2P, SCC3P, SCC4P};
-static	int	sccreg[] = {-1, 0xA00, 0xA20, 0xA40, 0xA60};
-static	int	sccirq[] = {-1, 0x1E, 0x1D, 0x1C, 0x1B};
-
-static void
-attach(Ctlr *ctlr)
-{
-	mot[ctlr->ctlrno].scc->gsmrl |= ENR|ENT;
-	eieio();
-}
-
-static void
-transmit(Ctlr *ctlr)
-{
-	int len;
-	Mot *motp;
-	Block *b;
-	BD *tdre;
-
-	motp = &mot[ctlr->ctlrno];
-	while(((tdre = &motp->tdr[motp->tdrx])->status & BDReady) == 0){
-		b = qget(ctlr->oq);
-		if(b == 0)
-			break;
-
-		/*
-		 * Copy the packet to the transmit buffer.
-		 */
-		len = BLEN(b);
-		memmove(KADDR(tdre->addr), b->rp, len);
-	
-		/*
-		 * Give ownership of the descriptor to the chip, increment the
-		 * software ring descriptor pointer and tell the chip to poll.
-		 */
-		tdre->length = len;
-		eieio();
-		tdre->status = (tdre->status & BDWrap) | BDReady|TxPad|BDInt|BDLast|TxTC;
-		eieio();
-		motp->scc->todr = 1<<15;	/* transmit now */
-		eieio();
-		motp->tdrx = NEXT(motp->tdrx, Ntdre);
-
-		freeb(b);
-	
-	}
-}
-
-static void
-interrupt(Ureg*, void *ap)
-{
-	int len, events, status;
-	Mot *motp;
-	BD *rdre;
-	Block *b;
-	Ctlr *ctlr;
-
-	ctlr = ap;
-	motp = &mot[ctlr->ctlrno];
-
-	/*
-	 * Acknowledge all interrupts and whine about those that shouldn't
-	 * happen.
-	 */
-	events = motp->scc->scce;
-	eieio();
-	motp->scc->scce = events;
-	eieio();
-	if(events & (TXE|BSY|RXB))
-		print("ETHER.SCC#%d: scce = 0x%uX\n", ctlr->ctlrno, events);
-	//print(" %ux|", events);
-	/*
-	 * Receiver interrupt: run round the descriptor ring logging
-	 * errors and passing valid receive data up to the higher levels
-	 * until we encounter a descriptor still owned by the chip.
-	 */
-	if(events & (RXF|RXB) || 1){
-		rdre = &motp->rdr[motp->rdrx];
-		while(((status = rdre->status) & BDEmpty) == 0){
-			if(status & RxError || (status & (BDFirst|BDLast)) != (BDFirst|BDLast)){
-				//if(status & RxBuff)
-				//	ctlr->buffs++;
-				if(status & (1<<2))
-					ctlr->crcs++;
-				if(status & (1<<1))
-					ctlr->overflows++;
-				//print("eth rx: %ux\n", status);
-				if(status & RxError)
-					print("~");
-				else if((status & BDLast) == 0)
-					print("@");
-			}
-			else{
-				/*
-				 * We have a packet. Read it into the next
-				 * free ring buffer, if any.
-				 */
-				len = rdre->length-4;
-				if((b = iallocb(len)) != 0){
-					memmove(b->wp, KADDR(rdre->addr), len);
-					b->wp += len;
-					etheriq(ctlr, b, 1);
-				}
-			}
-
-			/*
-			 * Finished with this descriptor, reinitialise it,
-			 * give it back to the chip, then on to the next...
-			 */
-			rdre->length = 0;
-			rdre->status = (rdre->status & BDWrap) | BDEmpty | BDInt;
-			eieio();
-
-			motp->rdrx = NEXT(motp->rdrx, Nrdre);
-			rdre = &motp->rdr[motp->rdrx];
-		}
-	}
-
-	/*
-	 * Transmitter interrupt: handle anything queued for a free descriptor.
-	 */
-	if(events & TXB)
-		transmit(ctlr);
-	if(events & TXE)
-		cpmop(RestartTx, motp->cpm, 0);
-}
-
-static void
-ringinit(Mot* motp)
-{
-	int i, x;
-
-	/*
-	 * Initialise the receive and transmit buffer rings. The ring
-	 * entries must be aligned on 16-byte boundaries.
-	 */
-	if(motp->rdr == 0)
-		motp->rdr = bdalloc(Nrdre);
-	if(motp->rrb == 0)
-		motp->rrb = ialloc(Nrdre*Bufsize, 0);
-	x = PADDR(motp->rrb);
-	for(i = 0; i < Nrdre; i++){
-		motp->rdr[i].length = 0;
-		motp->rdr[i].addr = x;
-		motp->rdr[i].status = BDEmpty|BDInt;
-		x += Bufsize;
-	}
-	motp->rdr[i-1].status |= BDWrap;
-	motp->rdrx = 0;
-
-	if(motp->tdr == 0)
-		motp->tdr = bdalloc(Ntdre);
-	if(motp->trb == 0)
-		motp->trb = ialloc(Ntdre*Bufsize, 0);
-	x = PADDR(motp->trb);
-	for(i = 0; i < Ntdre; i++){
-		motp->tdr[i].addr = x;
-		motp->tdr[i].length = 0;
-		motp->tdr[i].status = TxPad|BDInt|BDLast|TxTC;
-		x += Bufsize;
-	}
-	motp->tdr[i-1].status |= BDWrap;
-	motp->tdrx = 0;
-}
-
-/*
- * This follows the MPC823 user guide: section16.9.23.7's initialisation sequence,
- * except that it sets the right bits for the MPC823ADS board when SCC2 is used,
- * and those for the 860/821 development board for SCC1.
- */
-static void
-sccsetup(Mot *ctlr, SCC *scc, uchar *ea)
-{
-	int i, rcs, tcs, w;
-	Etherparam *p;
-	IMM *io;
-
-
-	i = 2*(ctlr->port-1);
-	io = ioplock();
-	w = (TXD1|RXD1)<<i;	/* TXDn and RXDn in port A */
-	io->papar |= w;	/* enable TXDn and RXDn pins */
-	io->padir &= ~w;
-	io->paodr &= ~w;	/* not open drain */
-
-	w = (CD1|CTS1)<<i;	/* CLSN and RENA: CDn and CTSn in port C */
-	io->pcpar &= ~w;	/* enable CLSN (CTSn) and RENA (CDn) */
-	io->pcdir &= ~w;
-	io->pcso |= w;
-	iopunlock();
-
-	/* clocks and transceiver control: details depend on the board's wiring */
-	archetherenable(ctlr->cpm, &rcs, &tcs);
-
-	sccnmsi(ctlr->port, rcs, tcs);	/* connect the clocks */
-
-	p = (Etherparam*)KADDR(sccparam[ctlr->port]);
-	memset(p, 0, sizeof(*p));
-	p->rfcr = 0x18;
-	p->tfcr = 0x18;
-	p->mrblr = Bufsize;
-	p->rbase = PADDR(ctlr->rdr);
-	p->tbase = PADDR(ctlr->tdr);
-
-	cpmop(InitRxTx, ctlr->cpm, 0);
-
-	p->c_pres = ~0;
-	p->c_mask = 0xDEBB20E3;
-	p->crcec = 0;
-	p->alec = 0;
-	p->disfc = 0;
-	p->pads = 0x8888;
-	p->ret_lim = 0xF;
-	p->mflr = Rbsize;
-	p->minflr = ETHERMINTU+4;
-	p->maxd1 = Bufsize;
-	p->maxd2 = Bufsize;
-	p->p_per = 0;	/* only moderate aggression */
-
-	for(i=0; i<Eaddrlen; i+=2)
-		p->paddr[2-i/2] = (ea[i+1]<<8)|ea[i];	/* it's not the obvious byte order */
-
-	scc->psmr = (2<<10)|(5<<1);	/* 32-bit CRC, ignore 22 bits before SFD */
-	scc->dsr = 0xd555;
-	scc->gsmrh = 0;	/* normal operation */
-	scc->gsmrl = (1<<28)|(4<<21)|(1<<19)|0xC;	/* transmit clock invert, 48 bit preamble, repetitive 10 preamble, ethernet */
-	eieio();
-	scc->scce = ~0;	/* clear all events */
-	eieio();
-	scc->sccm = TXE | RXF | TXB;	/* enable interrupts */
-	eieio();
-
-	io = ioplock();
-	w = RTS1<<(ctlr->port-1);	/* enable TENA pin (RTSn) */
-	io->pbpar |= w;
-	io->pbdir |= w;
-	iopunlock();
-
-	/* gsmrl enable is deferred until attach */
-}
-
-/*
- * Prepare the SCCx ethernet for booting.
- */
-int
-sccethreset(Ctlr* ctlr)
-{
-	uchar ea[Eaddrlen];
-	Mot *motp;
-	SCC *scc;
-	char line[50], def[50];
-
-	/*
-	 * Since there's no EPROM, insist that the configuration entry
-	 * (see conf.c and flash.c) holds the Ethernet address.
-	 */
-	memset(ea, 0, Eaddrlen);
-	if(memcmp(ea, ctlr->card.ea, Eaddrlen) == 0){
-		print("no preset Ether address\n");
-		for(;;){
-			strcpy(def, "00108bf12900");	/* valid MAC address to be used only for initial configuration */
-			if(getstr("ether MAC address", line, sizeof(line), def) < 0)
-				return -1;
-			if(parseether(ctlr->card.ea, line) >= 0 || ctlr->card.ea[0] == 0xFF)
-				break;
-			print("invalid MAC address\n");
-		}
-	}
-
-	scc = IOREGS(sccreg[ctlr->card.port], SCC);
-	ctlr->card.irq = VectorCPIC+sccirq[ctlr->card.port];
-
-	motp = &mot[ctlr->ctlrno];
-	motp->scc = scc;
-	motp->port = ctlr->card.port;
-	motp->cpm = sccid[ctlr->card.port];
-
-	ringinit(motp);
-
-	sccsetup(motp, scc, ctlr->card.ea);
-
-	/* enable is deferred until attach */
-
-	ctlr->card.reset = sccethreset;
-	ctlr->card.attach = attach;
-	ctlr->card.transmit = transmit;
-	ctlr->card.intr = interrupt;
-
-	return 0;
-}
--- a/os/boot/rpcg/fblt.c
+++ /dev/null
@@ -1,531 +1,0 @@
-#include <u.h>
-#include <libc.h>
-#include <libg.h>
-#include <gnot.h>
-
-/*
- * bitblt operates a 'word' at a time.
- * WBITS is the number of bits in a word
- * LWBITS=log2(WBITS),
- * W2L is the number of words in a long
- * WMASK has bits set for the low order word of a long
- * WType is a pointer to a word
- */
-#ifndef WBITS
-#define WBITS	32
-#define LWBITS	5
-#define	W2L	1
-#define WMASK	~0UL
-typedef ulong	*WType;
-#endif
-
-#define DEBUG 
-
-#ifdef TEST
-/*
- * globals used for testing
- */
-int	FORCEFORW;
-int	FORCEBAKW;
-GBitmap	*curdm, *cursm;
-Point	curpt;
-Rectangle curr;
-Fcode	curf;
-void	*mem;
-#endif
-
-static void
-gbitexplode(ulong sw, ulong *buf, int sdep, int x)
-{
-	int j, o, q, n, nw, inc, qinc;
-	ulong s, dw, pix;
-
-	inc = 1 << sdep;
-	pix = (1 << inc) - 1;
-	nw = 1 << x;
-	n = 32 >> x;
-	qinc = (nw << sdep) - inc;
-	for(o = 32 - n; o >= 0; o -= n){
-		dw = 0;
-		s = sw >> o;
-		q = 0;
-		for(j = 0; j < n; j += inc){
-			dw |= (s & (pix << j)) << q;
-			q += qinc;
-		}
-		for(j = 0; j < x; j++)
-			dw |= dw << (inc << j);
-		*buf++ = dw;
-	}
-}
-
-/*
-void
-main(void)
-{
-	ulong buf[128];
-
-	gbitexplode(0x7777, buf, 0, 3);
-	exits(0);
-}
-*/
-
-void
-gbitblt(GBitmap *dm, Point pt, GBitmap *sm, Rectangle r, Fcode fcode)
-{
-	int	width;		/* width in bits of dst */
-	int	wwidth;		/* floor width in words */
-	int	height;		/* height in pixels minus 1 */
-	int	sdep;		/* src ldepth */
-	int 	ddep;		/* dst ldepth */
-	int	deltadep;	/* diff between ldepths */
-	int	sspan;		/* words between scanlines in src */
-	int	dspan;		/* words between scanlines in dst */
-	int	soff;		/* bit offset of src start point */
-	int	sdest;		/* bit offset of src start point that matches doff when expanded */
-	int	doff;		/* bit offset of dst start point */
-	int	delta;		/* amount to shift src by */
-	int	sign;		/* of delta */
-	ulong	*saddr;
-	ulong	*daddr;
-	ulong	*s;
-	ulong	*d;
-	ulong	mask;
-	ulong	tmp;		/* temp storage source word */
-	ulong	sw;		/* source word constructed */
-	ulong	dw;		/* dest word fetched */
-	ulong	lmask;		/* affected pixels in leftmost dst word */
-	ulong	rmask;		/* affected pixels in rightmost dst word */
-	int	i;
-	int	j;
-	ulong	buf[32];	/* for expanding a source */
-	ulong	*p;		/* pointer into buf */
-	int	spare;		/* number of words already converted */
-
-
-#ifdef TEST
-	curdm = dm;
-	cursm = sm;
-	curpt = pt;
-	curr = r;
-	curf = fcode;
-#endif
-
-	gbitbltclip(&dm);
-
-	width = r.max.x - r.min.x;
-	if(width <= 0)
-		return;
-	height = r.max.y - r.min.y - 1;
-	if(height < 0)
-		return;
-
-	ddep = dm->ldepth;
-	pt.x <<= ddep;
-	width <<= ddep;
-
-	sdep = sm->ldepth;
-	r.min.x <<= sdep;
-	r.max.x <<= sdep;
-
-	dspan = dm->width * W2L;
-	sspan = sm->width * W2L;
-
-	daddr = (ulong*)((WType)dm->base
-			+ dm->zero*W2L + pt.y*dspan
-			+ (pt.x >> LWBITS));
-	saddr = (ulong*)((WType)sm->base
-			+ sm->zero*W2L + r.min.y*sspan
-			+ (r.min.x >> LWBITS));
-
-	doff = pt.x & (WBITS - 1);
-	lmask = WMASK >> doff;
-	rmask = (WMASK << (WBITS - ((doff+width) & (WBITS-1))))&WMASK;
-	if(!rmask)
-		rmask = WMASK;
-	soff = r.min.x & (WBITS-1);
-	wwidth = ((pt.x+width-1)>>LWBITS) - (pt.x>>LWBITS);
-
-	if(sm == dm){
-#ifdef TEST
-		if(!FORCEBAKW &&
-		   (FORCEFORW || sm != dm || saddr > daddr ||
-		    (saddr == daddr && soff > doff)))
-			;
-		else{
-			daddr += height * dspan;
-			saddr += height * sspan;
-			sspan -= 2 * W2L * sm->width;
-			dspan -= 2 * W2L * dm->width;
-		}
-#else
-		if(r.min.y < pt.y){	/* bottom to top */
-			daddr += height * dspan;
-			saddr += height * sspan;
-			sspan -= 2 * W2L * sm->width;
-			dspan -= 2 * W2L * dm->width;
-		}else if(r.min.y == pt.y && r.min.x < pt.x)
-			abort()/*goto right*/;
-#endif
-	}
-	if(wwidth == 0)		/* collapse masks for narrow cases */
-		lmask &= rmask;
-	fcode &= F;
-
-	deltadep = ddep - sdep;
-	sdest = doff >> deltadep;
-	delta = soff - sdest;
-	sign = 0;
-	if(delta < 0){
-		sign = 1;
-		delta = -delta;
-	}
-
-	p = 0;
-	for(j = 0; j <= height; j++){
-		d = daddr;
-		s = saddr;
-		mask = lmask;
-		tmp = 0;
-		if(!sign)
-			tmp = *s++;
-		spare = 0;
-		for(i = wwidth; i >= 0; i--){
-			if(spare)
-				sw = *p++;
-			else{
-				if(sign){
-					sw = tmp << (WBITS-delta);
-					tmp = *s++;
-					sw |= tmp >> delta;
-				}else{
-					sw = tmp << delta;
-					tmp = *s++;
-					if(delta)
-						sw |= tmp >> (WBITS-delta);
-				}
-				spare = 1 << deltadep;
-				if(deltadep >= 1){
-					gbitexplode(sw, buf, sdep, deltadep);
-					p = buf;
-					sw = *p++;
-				}
-			}
-
-			dw = *d;
-			switch(fcode){		/* ltor bit aligned */
-			case Zero:	*d = dw & ~mask;		break;
-			case DnorS:	*d = dw ^ ((~sw | dw) & mask);	break;
-			case DandnotS:	*d = dw ^ ((sw & dw) & mask);	break;
-			case notS:	*d = dw ^ ((~sw ^ dw) & mask);	break;
-			case notDandS:	*d = dw ^ ((sw | dw) & mask);	break;
-			case notD:	*d = dw ^ mask;			break;
-			case DxorS:	*d = dw ^ (sw & mask);		break;
-			case DnandS:	*d = dw ^ ((sw | ~dw) & mask);	break;
-			case DandS:	*d = dw ^ ((~sw & dw) & mask);	break;
-			case DxnorS:	*d = dw ^ (~sw & mask);		break;
-			case D:						break;
-			case DornotS:	*d = dw | (~sw & mask);		break;
-			case S:		*d = dw ^ ((sw ^ dw) & mask);	break;
-			case notDorS:	*d = dw ^ (~(sw & dw) & mask);	break;
-			case DorS:	*d = dw | (sw & mask);		break;
-			case F:		*d = dw | mask;			break;
-			}
-			d++;
-
-			mask = WMASK;
-			if(i == 1)
-				mask = rmask;
-			spare--;
-		}
-		saddr += sspan;
-		daddr += dspan;
-	}
-}
-
-#ifdef TEST
-void	prprog(void);
-GBitmap *bb1, *bb2;
-ulong	*src, *dst, *xdst, *xans;
-int	swds, dwds;
-long	ticks;
-int	timeit;
-
-long
-func(int f, long s, int sld, long d, int dld)
-{
-	long a;
-	int sh, i, db, sb;
-
-	db = 1 << dld;
-	sb = 1 << sld;
-	sh = db - sb;
-	if(sh > 0) {
-		a = s;
-		for(i = sb; i<db; i += sb){
-			a <<= sb;
-			s |= a;
-		}
-	} else if(sh < 0)
-		s >>= -sh;
-
-	switch(f){
-	case Zero:	d = 0;			break;
-	case DnorS:	d = ~(d|s);		break;
-	case DandnotS:	d = d & ~s;		break;
-	case notS:	d = ~s;			break;
-	case notDandS:	d = ~d & s;		break;
-	case notD:	d = ~d;			break;
-	case DxorS:	d = d ^ s;		break;
-	case DnandS:	d = ~(d&s);		break;
-	case DandS:	d = d & s;		break;
-	case DxnorS:	d = ~(d^s);		break;
-	case S:		d = s;			break;
-	case DornotS:	d = d | ~s;		break;
-	case D:		d = d;			break;
-	case notDorS:	d = ~d | s;		break;
-	case DorS:	d = d | s;		break;
-	case F:		d = ~0;			break;
-	}
-
-	d &= ((1<<db)-1);
-	return d;
-}
-
-void
-run(int fr, int to, int w, int op)
-{
-	int i, j, f, t, fy, ty;
-	extern long *_clock;
-
-	fr += bb2->r.min.x;
-	to += bb1->r.min.x;
-	fy = bb2->r.min.y + 1;
-	ty = bb1->r.min.y + 1;
-	if(timeit) {
-		memcpy(dst, xdst, dwds * sizeof(long));
-		ticks -= *_clock;
-		gbitblt(bb1, Pt(to,ty), bb2, Rect(fr,fy,fr+w,fy+2), op);
-		ticks += *_clock;
-		return;
-	}
-	f = fr;
-	t = to;
-	memcpy(dst, xdst, dwds * sizeof(long));
-	for(i=0; i<w; i++) {
-		gbitblt(bb1, Pt(t,ty), bb2, Rect(f,fy,f+1,fy+1), op);
-		gbitblt(bb1, Pt(t,ty+1), bb2, Rect(f,fy+1,f+1,fy+2), op);
-		f++;
-		t++;
-	}
-	memcpy(xans, dst, dwds * sizeof(long));
-
-	memcpy(dst, xdst, dwds * sizeof(long));
-	gbitblt(bb1, Pt(to,ty), bb2, Rect(fr,fy,fr+w,fy+2), op);
-
-	if(memcmp(xans, dst, dwds * sizeof(long))) {
-		/*
-		 * print src and dst row offset, width in bits, and forw/back
-		 * then print for each of the four rows: the source (s),
-		 * the dest (d), the good value of the answer (g),
-		 * and the actual bad value of the answer (b)
-		 */
-		print("fr=%d to=%d w=%d fb=%d%d\n",
-			fr, to, w, FORCEFORW, FORCEBAKW);
-		print("dst bitmap b %#lux, z %d, w %d, ld %d, r [%d,%d][%d,%d]\n",
-			bb1->base, bb1->zero, bb1->width, bb1->ldepth,
-			bb1->r.min.x, bb1->r.min.y, bb1->r.max.x, bb1->r.max.y);
-		print("src bitmap b %#lux, z %d, w %d, ld %d, r [%d,%d][%d,%d]\n",
-			bb2->base, bb2->zero, bb2->width, bb2->ldepth,
-			bb2->r.min.x, bb2->r.min.y, bb2->r.max.x, bb2->r.max.y);
-		for(j=0; 7*j < dwds; j++) {
-			print("\ns");
-			for(i=0; i<7 && 7*j+i < dwds; i++)
-				print(" %.8lux", src[7*j + i]);
-			print("\nd");
-			for(i=0; i<7 && 7*j+i < dwds; i++)
-				print(" %.8lux", xdst[7*j + i]);
-			print("\ng");
-			for(i=0; i<7 && 7*j+i < dwds; i++)
-				print(" %.8lux", xans[7*j + i]);
-			print("\nb");
-			for(i=0; i<7 && 7*j+i < dwds; i++)
-				print(" %.8lux", dst[7*j + i]);
-			print("\n");
-		}
-		prprog();
-	}
-}
-
-void
-prprog(void)
-{
-	exits(0);
-}
-
-int
-main(int argc, char *argv[])
-{
-	int f, t, w, i, sld, dld, op, iters, simple;
-	ulong s, d, spix, dpix, apix, fpix, m, *ps, *pd;
-	Point sorg, dorg;
-	GBitmap *bs, *bd;
-	long seed;
-	char *ct;
-
-	sld = 0;
-	dld = 0;
-	timeit = 0;
-	iters = 200;
-	simple = 0;
-	ARGBEGIN {
-	case 'i':
-		iters = atoi(ARGF());
-		break;
-	case 's':
-		simple = 1;
-		break;
-	case 't':
-		timeit = 1;
-		ct = ARGF();
-		if(ct)
-			iters = atoi(ct);
-		break;
-	} ARGEND
-	if(argc > 0)
-		sld = atoi(argv[0]);
-	if(argc > 1)
-		dld = atoi(argv[1]);
-	if(!timeit && !simple) {
-		seed = time(0);
-		print("seed %lux\n", seed); srand(seed);	/**/
-	}
-
-	print("sld %d dld %d\n", sld, dld);
-	op = 1;
-
-	/* bitmaps for 1-bit tests */
-	bd = gballoc(Rect(0,0,32,1), dld);
-	bs = gballoc(Rect(0,0,32,1), sld);
-	for(i=0; i<bs->width; i++)
-		bs->base[i] = lrand();
-
-	/* bitmaps for rect tests */
-	if(simple) {
-		dorg = Pt(0,0);
-		sorg = Pt(0,0);
-	} else {
-		dorg = Pt(nrand(63)-31,nrand(63)-31);
-		sorg = Pt(nrand(63)-31,nrand(63)-31);
-	}
-	bb1 = gballoc(Rpt(dorg,add(dorg,Pt(200,4))), dld);
-	bb2 = gballoc(Rpt(sorg,add(sorg,Pt(200,4))), sld);
-	dwds = bb1->width * Dy(bb1->r);
-	swds = bb2->width * Dy(bb2->r);
-	dst = bb1->base;
-	src = bb2->base;
-	xdst = malloc(dwds * sizeof(long));
-	xans =  malloc(dwds * sizeof(long));
-	for(i=0; i<swds; i++)
-		src[i] = lrand();
-	for(i=0; i<dwds; i++)
-		xdst[i] = lrand();
-
-loop:
-	print("Op %d\n", op);
-	if(!timeit) {
-		print("one pixel\n");
-		ps = bs->base;
-		pd = bd->base;
-		FORCEFORW = 1;
-		FORCEBAKW = 0;
-		for(i=0; i<1000; i++, FORCEFORW = !FORCEFORW, FORCEBAKW = !FORCEBAKW) {
-			f = nrand(32 >> sld);
-			t = nrand(32 >> dld);
-			s = lrand();
-			d = lrand();
-			ps[0] = s;
-			pd[0] = d;
-#ifdef T386
-			spix = (byterev(s) >> (32 - ((f+1)<<sld))) & ((1 << (1<<sld)) - 1);
-			dpix = (byterev(d) >> (32 - ((t+1)<<dld))) & ((1 << (1<<dld)) - 1);
-#else
-			spix = (s >> (32 - ((f+1)<<sld))) & ((1 << (1<<sld)) - 1);
-			dpix = (d >> (32 - ((t+1)<<dld))) & ((1 << (1<<dld)) - 1);
-#endif
-#ifdef T386
-			apix = byterev(func(op, spix, sld, dpix, dld) << (32 - ((t+1)<<dld)));
-#else
-			apix = func(op, spix, sld, dpix, dld) << (32 - ((t+1)<<dld));
-#endif
-			gbitblt(bd, Pt(t,0), bs, Rect(f,0,f+1,1), op);
-			if(ps[0] != s) {
-				print("bb src %.8lux %.8lux %d %d\n", ps[0], s, f, t);
-				exits("error");
-			}
-			m = ((1 << (1<<dld)) - 1) << (32 - ((t+1)<<dld));
-#ifdef T386
-			m = byterev(m);
-#endif
-			if((pd[0] & ~m) != (d & ~m)) {
-					print("bb dst1 %.8lux %.8lux\n",
-						s, d);
-					print("bb      %.8lux %.8lux %d %d\n",
-						ps[0], pd[0], f, t);
-					prprog();
-					exits("error");
-			}
-			if((pd[0] & m) != apix) {
-				spix <<= 32 - ((f+1)<<sld);
-				dpix <<= 32 - ((t+1)<<dld);
-#ifdef T386
-				spix = byterev(spix);
-				dpix = byterev(dpix);
-#endif
-				print("bb dst2 %.8lux %.8lux\n",
-					s, d);
-				print("bb      %.8lux %.8lux %d %d\n",
-					ps[0], pd[0], f, t);
-				print("bb      %.8lux %.8lux %.8lux %.8lux\n",
-					spix, dpix, apix, pd[0] & m);
-				prprog();
-				exits("error");
-			}
-		}
-	}
-
-	print("for\n");
-	FORCEFORW = 1;
-	FORCEBAKW = 0;
-
-	for(i=0; i<iters; i++) {
-		f = nrand(64);
-		t = nrand(64);
-		w = nrand(130);
-		run(f, t, w, op);
-	}
-
-	if(sld == dld) {
-		print("bak\n");
-		FORCEFORW = 0;
-		FORCEBAKW = 1;
-	
-		for(i=0; i<iters; i++) {
-			f = nrand(64);
-			t = nrand(64);
-			w = nrand(130);
-			run(f, t, w, op);
-		}
-	}
-
-	if(op < F) {
-		op++;
-		goto loop;
-	}
-	if(timeit)
-		print("time: %d ticks\n", ticks);
-	exits(0);
-}
-
-
-#endif
--- a/os/boot/rpcg/flash.c
+++ /dev/null
@@ -1,212 +1,0 @@
-#include "boot.h"
-
-typedef struct Flashdev Flashdev;
-struct Flashdev {
-	uchar*	base;
-	int	size;
-	uchar*	exec;
-	char*	config;
-	int	conflen;
-};
-
-enum {
-	FLASHSEG = 256*1024,
-	CONFIGLIM = FLASHSEG,
-	BOOTOFF = FLASHSEG,
-	BOOTLEN = 3*FLASHSEG,	/* third segment might be filsys */
-	/* rest of flash is free */
-};
-
-static Flashdev flash;
-
-/*
- * configuration data is written between the bootstrap and
- * the end of region 0. the region ends with allocation descriptors
- * of the following form:
- *
- * byte order is big endian
- *
- * the last valid region found that starts with the string "#plan9.ini\n" is plan9.ini
- */
-typedef struct Flalloc Flalloc;
-struct Flalloc {
-	ulong	check;	/* checksum of data, or ~0 */
-	ulong	base;	/* base of region; ~0 if unallocated, 0 if deleted */
-	uchar	len[3];
-	uchar	tag;		/* see below */
-	uchar	sig[4];
-};
-
-enum {
-	/* tags */
-	Tdead=	0,
-	Tboot=	0x01,	/* space reserved for boot */
-	Tconf=	0x02,	/* configuration data */
-	Tnone=	0xFF,
-
-	Noval=	~0,
-};
-
-static char flashsig[] = {0xF1, 0xA5, 0x5A, 0x1F};
-static char conftag[] = "#plan9.ini\n";
-
-static ulong
-checksum(uchar* p, int n)
-{
-	ulong s;
-
-	for(s=0; --n >= 0;)
-		s += *p++;
-	return s;
-}
-
-static int
-validptr(Flalloc *ap, uchar *p)
-{
-	return p > (uchar*)&end && p < (uchar*)ap;
-}
-
-static int
-flashcheck(Flalloc *ap, char **val, int *len)
-{
-	uchar *base;
-	int n;
-
-	if(ap->base == Noval || ap->base >= FLASHSEG || ap->tag == Tnone)
-		return 0;
-	base = flash.base+ap->base;
-	if(!validptr(ap, base))
-		return 0;
-	n = (((ap->len[0]<<8)|ap->len[1])<<8)|ap->len[2];
-	if(n == 0xFFFFFF)
-		n = 0;
-	if(n < 0)
-		return 0;
-	if(n > 0 && !validptr(ap, base+n-1))
-		return 0;
-	if(ap->check != Noval && checksum(base, n) != ap->check){
-		print("flash: bad checksum\n");
-		return 0;
-	}
-	*val = (char*)base;
-	*len = n;
-	return 1;
-}
-
-int
-flashinit(void)
-{
-	int len;
-	char *val;
-	Flalloc *ap;
-	void *addr;
-	long mbytes;
-	char type[20];
-
-	flash.base = 0;
-	flash.exec = 0;
-	flash.size = 0;
-	if(archflashreset(type, &addr, &mbytes) < 0){
-		print("flash: flash not present or not enabled\n");	/* shouldn't happen */
-		return 0;
-	}
-	flash.size = mbytes;
-	flash.base = addr;
-	flash.exec = flash.base + BOOTOFF;
-	flash.config = nil;
-	flash.conflen = 0;
-
-	for(ap = (Flalloc*)(flash.base+CONFIGLIM)-1; memcmp(ap->sig, flashsig, 4) == 0; ap--){
-		if(0)
-			print("conf #%8.8lux: #%x #%6.6lux\n", ap, ap->tag, ap->base);
-		if(ap->tag == Tconf &&
-		   flashcheck(ap, &val, &len) &&
-		   len >= sizeof(conftag)-1 &&
-		   memcmp(val, conftag, sizeof(conftag)-1) == 0){
-			flash.config = val;
-			flash.conflen = len;
-			if(0)
-				print("flash: found config %8.8lux(%d):\n%s\n", val, len, val);
-		}
-	}
-	if(flash.config == nil)
-		print("flash: no config\n");
-	else
-		print("flash config %8.8lux(%d):\n%s\n", flash.config, flash.conflen, flash.config);
-	if(issqueezed(flash.exec) == Q_MAGIC){
-		print("flash: squeezed powerpc kernel installed\n");
-		return 1<<0;
-	}
-	if(GLLONG(flash.exec) == Q_MAGIC){
-		print("flash: unsqueezed powerpc kernel installed\n");
-		return 1<<0;
-	}
-	flash.exec = 0;
-	print("flash: no powerpc kernel in Flash\n");
-	return 0;
-}
-
-char*
-flashconfig(int)
-{
-	return flash.config;
-}
-
-int
-flashbootable(int)
-{
-	return flash.exec != nil && (issqueezed(flash.exec) || GLLONG(flash.exec) == Q_MAGIC);
-}
-
-int
-flashboot(int)
-{
-	ulong entry, addr;
-	void (*b)(void);
-	Exec *ep;
-	Block in;
-	long n;
-	uchar *p;
-
-	if(flash.exec == 0)
-		return -1;
-	p = flash.exec;
-	if(GLLONG(p) == Q_MAGIC){
-		/* unsqueezed: copy data and perhaps text, then jump to it */
-		ep = (Exec*)p;
-		entry = PADDR(GLLONG(ep->entry));
-		p += sizeof(Exec);
-		addr = entry;
-		n = GLLONG(ep->text);
-		if(addr != (ulong)p){
-			memmove((void*)addr, p, n);
-			print("text: %8.8lux <- %8.8lux [%ld]\n", addr, p, n);
-		}
-		p += n;
-		if(entry >= FLASHMEM)
-			addr = 3*BY2PG;	/* kernel text is in Flash, data in RAM */
-		else
-			addr = PGROUND(addr+n);
-		n = GLLONG(ep->data);
-		memmove((void*)addr, p, n);
-		print("data: %8.8lux <- %8.8lux [%ld]\n", addr, p, n);
-	}else{
-		in.data = p;
-		in.rp = in.data;
-		in.lim = p+BOOTLEN;
-		in.wp = in.lim;
-		n = unsqueezef(&in, &entry);
-		if(n < 0)
-			return -1;
-	}
-	print("entry=0x%lux\n", entry);
-	uartwait();
-	scc2stop();
-	/*
-	 *  Go to new code. It's up to the program to get its PC relocated to
-	 *  the right place.
-	 */
-	b = (void (*)(void))KADDR(PADDR(entry));
-	(*b)();
-	return -1;
-}
--- a/os/boot/rpcg/fns.h
+++ /dev/null
@@ -1,118 +1,0 @@
-Alarm*	alarm(int, void (*)(Alarm*), void*);
-void	alarminit(void);
-void	archbacklight(int);
-char*	archconfig(void);
-void	archdisableuart(int);
-void	archenableuart(int, int);
-void	archenableusb(int);
-void	archetherdisable(int);
-int	archetherenable(int, int*, int*);
-int	archflashreset(char*, void**, long*);
-void	archinit(void);
-int	archoptionsw(void);
-int	bootp(int, char*);
-void	cancel(Alarm*);
-void	checkalarms(void);
-void	clockinit(void);
-void	clockintr(Ureg*, void*);
-void	consinit(void);
-void	cpminit(void);
-void	cpuidprint(void);
-#define	dcflush(a,b)
-void	delay(int);
-void	eieio(void);
-uchar*	etheraddr(int);
-int	etherinit(void);
-int	etherrxpkt(int, Etherpkt*, int);
-int	ethertxpkt(int, Etherpkt*, int, int);
-void	exception(void);
-int	flashboot(int);
-int	flashbootable(int);
-char*	flashconfig(int);
-int	flashinit(void);
-void	free(void*);
-void	freeb(Block*);
-int	getcfields(char*, char**, int, char*);
-char*	getconf(char*);
-ulong	getdec(void);
-ulong	gethid0(void);
-ulong	getimmr(void);
-ulong	getmsr(void);
-ulong	getpvr(void);
-int	getstr(char*, char*, int, char*);
-ulong	gettbl(void);
-ulong	gettbu(void);
-int	hardinit(void);
-long	hardread(int, void*, long);
-long	hardseek(int, long);
-long	hardwrite(int, void*, long);
-long	i2crecv(int, void*, long);
-long	i2csend(int, void*, long);
-void	i2csetup(void);
-void*	ialloc(ulong, int);
-Block*	iallocb(int);
-void	idle(void);
-int	isaconfig(char*, int, ISAConf*);
-int	issqueezed(uchar*);
-void	kbdchar(Queue*, int);
-void	kbdinit(void);
-void	kbdreset(void);
-void	machinit(void);
-void*	malloc(ulong);
-ulong	mapalloc(RMap*, ulong, int, int);
-void	mapfree(RMap*, ulong, int);
-void	mapinit(RMap*, Map*, int);
-void	meminit(void);
-void	microdelay(int);
-void	mmuinit(void);
-int	optionsw(void);
-void	panic(char*, ...);
-int	parseether(uchar*, char*);
-int	plan9boot(int, long (*)(int, long), long (*)(int, void*, long));
-void	putdec(ulong);
-void	puthid0(ulong);
-void	putmsr(ulong);
-int	qbgetc(Queue*);
-void	qbputc(Queue*, int);
-void	qbwrite(Queue*, Block*);
-Block*	qget(Queue*);
-long	qlen(Queue*);
-Queue*	qopen(int, int, void (*)(void*), void*);
-#define	qpass	qbwrite
-void	scc2stop(void);
-void	sccnmsi(int, int, int);
-void	sched(void);
-void	screeninit(void);
-void	screenputs(char*, int);
-void	sdraminit(ulong);
-Partition*	sethardpart(int, char*);
-Partition*	setscsipart(int, char*);
-void	setvec(int, void (*)(Ureg*, void*), void*);
-int	splhi(void);
-int	spllo(void);
-void	splx(int);
-void	trapinit(void);
-void	uartputs(char*, int);
-void	uartsetboot(void (*f)(uchar*, int));
-void	uartspecial(int, int, Queue**, Queue**, void(*)(Queue*,int));
-void	uartwait(void);
-long	unsqueezef(Block*, ulong*);
-
-#define	GSHORT(p)	(((p)[1]<<8)|(p)[0])
-#define	GLONG(p)	((GSHORT(p+2)<<16)|GSHORT(p))
-#define	GLSHORT(p)	(((p)[0]<<8)|(p)[1])
-#define	GLLONG(p)	((GLSHORT(p)<<16)|GLSHORT(p+2))
-
-#define KADDR(a)	((void*)((ulong)(a)|KZERO))
-#define PADDR(a)	((((ulong)(a)&KSEGM)!=KSEG0)?(ulong)(a):((ulong)(a)&~KZERO))
-
-/* IBM bit field order */
-#define	IBIT(b)	((ulong)1<<(31-(b)))
-#define	SIBIT(n)	((ushort)1<<(15-(n)))
-
-#define IOREGS(x, T)	((T*)((char*)m->iomem+(x)))
-
-int	uartinit(void);
-Partition*	setuartpart(int, char*);
-long	uartread(int, void*, long);
-long	uartseek(int, long);
--- a/os/boot/rpcg/g.mx
+++ /dev/null
@@ -1,1987 +1,0 @@
-S0030000FC
-S325000100007C6000A63C800000608480427C632078606310007C0004AC7C6001247C0004AC52
-S325000100204C00012C7C908AA63C800A007C908BA64C00012C3C800C007C908BA64C00012C0A
-S325000100403C8004007C908BA64C00012C7C0004AC7C988AA63C800A007C988BA64C00012C2F
-S325000100603C800C007C988BA64C00012C3C8004007C988BA64C00012C388000077C9E23A6D3
-S325000100807CBE9AA63C80FA207C9E9BA63860FF88906400043C6001016063244090640000DE
-S325000100A0380000003C40001460427FF83C40001460427FF83C60FFC26063D7103882800866
-S325000100C07C0418004182002C38A2A1F87CA4285038A500037CA516707CA903A63884FFFC7B
-S325000100E03863FFFC84A3000494A400044200FFF83C60FFC2606302007C6803A64E80002026
-S325000101003862A1F8388227107C8320514081001C7C8416707C8903A63863FFFC3800000065
-S32500010120940300044200FFFC3822A3C89022801438210FF8380000004800AA01480086F587
-S32500010140480000003D00FA40806800003CA008007C63287890680000480000007C6000A6CC
-S325000101604E8000207C0004AC7C6001247C0004AC4C00012C4E8000207C0006AC4E800020AE
-S325000101804E8000207C6000A6606480007C0004AC7C8001247C0004AC4C00012C4E800020C4
-S325000101A07C6000A65464045E7C0004AC7C8001247C0004AC4C00012C4E8000207C8000A61A
-S325000101C0506404207C0004AC7C8001247C0004AC4C00012C4E8000207C6C42E64E80002062
-S325000101E07C7F42A64E8000207C7E9AA64E8000207C7602A64E8000207C7603A64E800020EE
-S325000102003821FF58BC4100303C40001460427FF87C9142A69081002C7CB042A690A10028B2
-S325000102207CC902A690C100247C8102A6908100207CB342A690A1001C7CD242A690C100187C
-S325000102407C9A02A6908100107CBB02A690A1000C90010008386100087C60092D3800000018
-S325000102604E800020B8410030800100287C1043A6800100247C0903A6800100207C0103A6A8
-S325000102808001001C7C0FF120800100187C1243A6800100107C1A03A68001000C7C1B03A671
-S325000102A08021002C4E8000207C3143A67C0000267C1343A67C0802A64BFFFF4938000000D6
-S325000102C04800AC294BFFFFA17C1242A67C0803A67C1042A64C00012C4C0000647FE802A6C1
-S325000102E097E1FFE84BFFFF05812280147064FFFF5484C23F418200802C0400204182006CA6
-S325000103002C040021418200587C0A0378914900143D00FA409109001C814900203CC0007AEE
-S3250001032060C6120090C9000C80EA028454E7653E394700018089000C7C8451D6908900086D
-S3250001034080E9001C3CC03E0090C7000083E100007FE803A6382100184E8000203D40000828
-S32500010360614A23A04BFFFFA83D400008614A23004BFFFF9C3D400008614A60004BFFFF9076
-S325000103807FE802A697E1FFE038629EC0480035D538629ED3480035CD4BFFFE49546A843E40
-S325000103A02C0A0006418101B4418201A42C0A0001418201902C0A00034182017C2C0A0004DD
-S325000103C04182016838629F0891410008480035954BFFFE117066FFFF90C1001038629F1CDA
-S325000103E081010010910100084800357938629F2E480035714BFFFDF5706AFFFF9141001881
-S325000104007D464671418201182C060020418201042C060021418200F038629F4F7D4846705C
-S32500010420910100084800353D38629F5A80810018708400FF90810008480035294800019D1D
-S325000104409061001038629F6880810010908100084800351138629F7880E2801480E7001C11
-S3250001046080E7000090E10008480034F98142801438629F87808A002080840284908100083C
-S3250001048080CA002080C6028090C1000C480034D538629FA481028014810800083D20000F84
-S325000104A0612942407D084BD691010008480034B538629FB5480034AD8142801438629FB75A
-S325000104C080AA002080A5010090A1000880EA002080E7010490E1000C4800348938629FD0EB
-S325000104E08082801480840020A084017A908100084800347183E100007FE803A638210020A9
-S325000105004E80002038629F47480034594BFFFF1C38629F404800344D4BFFFF1038629F3523
-S32500010520480034414BFFFF0438629EE7480034354BFFFEA038629EE0480034294BFFFE9459
-S3250001054038629ED94800341D4BFFFE8838629EEE480034114BFFFE7C2C0A00074182001C87
-S325000105602C0A0050418200084BFFFE5C38629F01480033F14BFFFE5C38629EF6480033E5A7
-S325000105804BFFFE507FE802A697E1FFF03862A0A7480033D180628014806300145463C23EF5
-S325000105A070630FFF2C03082340820028386000015463103A388283C07C6322148063000080
-S325000105C083E100007FE803A6382100104E8000207C0303784BFFFFDC806280148063001CB5
-S325000105E080630000706300F05463E13E4E8000208102801480C8000038E000327FE63B96AB
-S325000106007FFF39D67CDF30514082001480E8001C80C700006CC6080090C700004E8000204A
-S325000106207FE802A697E1FFF080A2801480A5002080A5010070A50001408200183860FFFF96
-S3250001064083E100007FE803A6382100104E80002038E2A0C490E100084800CDA18081001802
-S325000106603CC0FFC090C4000080E1001C3C800040908700007C03037883E100007FE803A666
-S32500010680382100104E8000207FE802A697E1FFE87C030000408100183860FFFF83E100003C
-S325000106A07FE803A6382100184E800020806100203882A0CE908100084800CD4180C10020CB
-S325000106C0390000029106001C3862A0D2480000CD7C671B787C030000418200148061002037
-S325000106E03863002C90E10008480029053860000183E100007FE803A6382100184E800020D1
-S325000107003821FFF0814280142C030004418200103860FFFF382100104E800020812A002075
-S32500010720810A001C80E8000064E7800090E80000A0E9095260E70A00B0E90952A0E9095055
-S3250001074070E7F5FFB0E9095080A1001838E0000790E500008101001C38A0000590A80000D5
-S325000107607C030378382100104E80002080A2801480A5001C808500003FE07FFF63FFFFFF28
-S325000107807FE42039908500004E8000204E8000204E8000204E8000207FE802A697E1FFD073
-S325000107A09061003480C284247C0600004082006048008929386000A93882C3A89081000806
-S325000107C038C0008090C1000C48008F4D7C0300004180019C3C600000606380A93882C3A88F
-S325000107E0388400809081000838C0008090C1000C48008F257C0300004180017438E000FF00
-S3250001080098E2C4A839000001910284243922C3A888C900002C0600FF4182001088E90000EA
-S325000108202C07000A408200187C03037883E100007FE803A6382100304E80002091210028DB
-S3250001084088A900002C05000A4182001088C900002C0600FF408201009121002C88C90000DE
-S325000108602C06003D40820050806100344800CB5D8121002C810100287C8848507C041800BF
-S3250001088040820034806100344800CB41906100188061003480A1002890A1000880E10018D9
-S325000108A090E1000C4800CAAD8121002C7C03000041820038888900002C04000A418200108F
-S325000108C088A900002C0500FF40820018888900002C04000A4082FF3C392900014BFFFF34AE
-S325000108E0392900014BFFFFD039490001890900002C08000A41820010888900002C0400FF0F
-S325000109004082004C38628048914100089121002C914100287CCA485090C1000C4800C64520
-S3250001092038E2804880A1002C7CE53A14810100287CE83850980700003862804883E10000D7
-S325000109407FE803A6382100304E800020392900014BFFFF9C88E900002C07003D4082000816
-S325000109604BFFFEF8392900014BFFFED83862A0D548002FF17C03037883E100007FE803A6C8
-S32500010980382100304E8000203821FFF080A2801480A500087CA51BD638A500087CA5267000
-S325000109A02C051000418000183865000F7C631E7060630001382100104E80002054A3083CA7
-S325000109C0382100104E8000207FE802A697E1FFD89061002C38600009900100084BFFFDB10C
-S325000109E0810280148128002080A90ABC60A500C090A90ABC9121002480A90AB83FE0FFFF7F
-S32500010A0063FFFF3F7FE5283990A90AB8806100304BFFFF798121002464680001910909F076
-S32500010A2080A90AE03FE0FFFF63FF0FFF7FE5283990A90AE038600001480032B18141002C75
-S32500010A407C691B783CA0FA2060A53E8090A10020B0650000906A00B43C8000006084B000FA
-S32500010A60B0830000B0030002390A00247508E0003CA020007C0828004182011038EA002401
-S32500010A8090E9000438600001480032618141002C7C691B7881010020B0680002906A00B88A
-S32500010AA038C03000B0C30000B003000238AA00A474A5E0003CE020007C053800418200B8F0
-S32500010AC0388A00A4908900047C03037839000009910100089001000C48003085812100205A
-S32500010AE038E0001898E9000438A0001898A9000539000001B109000638C00001B0C9002870
-S32500010B00B009002CB009002E39000001B1090030808280148084002039240A8038C000FF46
-S32500010B2098C9000691210018388000179889000A386000143CA0FFC260A50C9C90A1000854
-S32500010B4080E1002C90E1000C4800A1298121001838E04820B0E90002A0A9000260A500034A
-S32500010B60B0A9000283E100007FE803A6382100284E800020388A00A43FE0FFFF63FFFFFF4D
-S32500010B807FE420394BFFFF4038EA00243FE0FFFF63FFFFFF7FE738394BFFFEE87FE802A630
-S32500010BA097E1FFD08121003880A2801480A5002038A50A8038E000FF98E50006810900B4D3
-S32500010BC0910100207C0800004182001480810020A0840000708480004182009C816900B847
-S32500010BE07C0B00004182001491610020A08B0000708480004182001483E100007FE803A694
-S32500010C00382100304E8000203940FFFF80C900107C0600004182001C9121002C806900104E
-S32500010C2048009409816100208121002C7C6A1B782C0AFFFF4182002C994900A438C00001DD
-S32500010C40B0CB0002A08B000060848000B08B000083E100007FE803A6382100304E8000205B
-S32500010C609809000883E100007FE803A6382100304E80002080A9000C7C050000418200144C
-S32500010C8080810020A08400027C0400404181002481010020A0A8000060A59000B0A8000089
-S32500010CA083E100007FE803A6382100304E80002080A900187C0500004182002438690024D4
-S32500010CC080A10020A0A5000290A1000880E900187CE803A64E8000214BFFFFB89121002CF0
-S32500010CE080C900147C060000418200487C0A037881010020A10800027C0A40404080FF945C
-S32500010D00914100247CCA4A1488C600248069000C90C1000880E900147CE803A64E800021F9
-S32500010D208121002C80A10024394500014BFFFFC480610020A0630002480090E9906100183D
-S32500010D408063000480C1002C38C6002490C1000880810020A08400029081000C4800C2054A
-S32500010D608121001881010020A1080002808900047D044214910900048061002C8063000CE7
-S32500010D80912100084800920D4BFFFF087FE802A697E1FFE09061001C4BFFF4098121001CE2
-S32500010DA090610018888900087C0400004082001C80690010480092758121001C90610014A1
-S32500010DC02C03FFFF4082001C806100184BFFF3F183E100007FE803A6382100204E800020FF
-S32500010DE080C280B47C06000041820064810900B8A108000071088000418200084BFFFFF0E5
-S32500010E0080C1001498C900A480C900B838A00001B0A6000280C900B8A0A6000060A5800073
-S32500010E20B0A600007D284B7880A280B47C0500004082001038A0000198A800084BFFFF6872
-S32500010E407C05037898A800084BFFFF5C7C0A0378914100102C0A00644080FFA880C900B8BD
-S32500010E60A0C6000070C68000408200084BFFFF943860000148001C098121001C80C1001093
-S32500010E80394600014BFFFFCC7FE802A697E1FFE0906100243902C4B080A800047C050000DF
-S32500010EA04182001483E100007FE803A6382100204E8000209101001C38C0000190C8000476
-S32500010EC038601000900100089001000C90010010480090098121001C9069000C8101002C3A
-S32500010EE09068000038604000900100083CE0FFC260E70E8C90E1000C9121001048008FDDD1
-S32500010F00814100288121001C9069001080C100309066000080A1003490A90014388000094F
-S32500010F20908900007C0A000040820008394025807D234B78914100084BFFFA9183E10000AD
-S32500010F407FE803A6382100204E8000209062C4C84E8000207FE802A697E1FFD88181003017
-S32500010F607C6D1B7838C2C4B090C100247C0B03787C6A1B7891A1002C7D0D62147C0A40402C
-S32500010F804080002C88AA00007CA507742C05000A40820008396B0001394A000191A1002C04
-S32500010FA07D0D62147C0A40404180FFDC7C6C5A1448008E71818100308141002C7C6B1B7851
-S32500010FC07D856378398CFFFF7C0500004182005488AA00007CA507742C05000A40820018EF
-S32500010FE080CB000439060001910B00043900000D99060000808B000438C4000190CB00046B
-S325000110007D465378394A000188C6000098C400007D856378398CFFFF7C0500004082FFB477
-S3250001102080610024806300109161000848008F6583E100007FE803A6382100284E80002098
-S325000110403821FFF03902C4B088E800087C070000418200084BFFFFF4382100104E80002038
-S325000110607FE802A697E1FFE0812100289061002438A2C5707C0900004081001490A1001C6E
-S32500011080808500007C0400004082001483E100007FE803A6382100204E8000207D234B78B0
-S325000110A048008D819061001880630004808100249081000880E1002890E1000C4800BEA5F4
-S325000110C08121001880E10028808900047CE43A1490E900048061001C8063000091210008F4
-S325000110E048008EB183E100007FE803A6382100204E800020386000014E8000207FE802A6F1
-S3250001110097E1FFF08061001838A2819890A100084800C3517C0300004182001C8061001889
-S325000111203882819D908100084800C3397C03000040820038900281F83CC0002090C281FC04
-S32500011140386281F83863000838E281A290E100084800C2A9386281F883E100007FE803A6E2
-S32500011160382100104E8000207C03037883E100007FE803A6382100104E8000207FE802A63D
-S3250001118097E1FFE88082C5707C0400004082001C3C600001900100089001000C90010010E0
-S325000111A048008D399062C5708102C5747C080000418200108062C57448008CC19002C57465
-S325000111C0386281A74800279D3C60FFC2606311604BFFFD7D38C0FFFF90C2C5789002C57C8D
-S325000111E09002C5C09002C5C47C03037883E100007FE803A6382100184E8000207FE802A6DA
-S3250001120097E1FFD08181003890610034810100349101001C3942C57080E2801480E70000B0
-S3250001122090E1002C918100387C0C000040810140812A000491410028900A00047C0900006A
-S32500011240408200A0900A0054806A000048008CC981810038814100287C691B787C03000095
-S325000112604082008080C2801480C600008101002C7CC8305054C5083C7CC62A1454C6183850
-S3250001128054A5482C7CC6285038E000327CC63B9628063A984180FFB480EA005438E7000171
-S325000112A090EA00542C07000341800020386281C1480026B17C03037883E100007FE803A6D9
-S325000112C0382100304E800020386281D039000001910100084BFFFC81814100284BFFFF6C6B
-S325000112E080A9000480C900007D4628507C0A6000408100087D8A63788061001C91210020D6
-S3250001130080E9000090E10008914100249141000C4800BC5181610024814100288121002009
-S32500011320808900007CE45A1490E9000080E9000080C900047C073040418000507D234B7839
-S3250001134048008B39816100248141002880E100387D8B385080E1001C7CA75A1490A1001C06
-S32500011360918100387C0C00004181FEC88061001C80E100347C67185083E100007FE803A6BB
-S32500011380382100304E800020912A00044BFFFFC07FE802A697E1FFE0808100289081001C4B
-S325000113A08122C5C07C0900004081005880E1002C7C093800408100088121002C8102C5C077
-S325000113C07CC9405090C2C5C08061001C38E2C57038E7001090E10008912100189121000CDE
-S325000113E04800BB81812100188081001C7CE44A1490E1001C8081002C7CE9205090E1002CA1
-S3250001140080E1002C7C070000408100C83862815038A0004090A100084BFFFDE58141002C56
-S325000114207C691B782C030040408000187C03037883E100007FE803A6382100204E80002011
-S325000114407C035000408100307C8A48509082C5C03862C5703863001038A281507CA55214E4
-S3250001146090A1000880A2C5C090A1000C4800BAF58121002C8061001C38C2815090C1000862
-S32500011480912100189121000C4800BAD9812100188101002C7CC9405090C1002C8101001C8A
-S325000114A07CC84A1490C1001C80C2C57C38C6000190C2C57C386281D2388000019081000842
-S325000114C04BFFFA9580E1002C7C0700004181FF408061001C810100287C68185083E10000C4
-S325000114E07FE803A6382100204E8000203821FFE87C0B03782C0B0100408000545569C00E54
-S32500011500394000087C0A00004081002875248000418200445526083C3FE004C163FF1DB7DB
-S325000115207FE93278394AFFFF7C0A00004181FFE05567103A38A2DC307CE72A1491270000A5
-S32500011540396B00012C0B01004180FFB4382100184E8000205529083C4BFFFFCC7FE802A6EE
-S3250001156097E1FFF081410018906100148082DC347C0400004082000C4BFFFF758141001826
-S3250001158080C1001C3FE0FFFF63FFFFFF7FE8327881210014394AFFFF7C0A00004180003C9F
-S325000115A05505463E7D264B783929000188C600007CA5327854A5103A38C2DC307CA53214B4
-S325000115C080A500005507402E7CE82A78394AFFFF7C0A00004080FFCC3FE0FFFF63FFFFFF00
-S325000115E07FE3427883E100007FE803A6382100104E800020816100088121000C7C0B0000DE
-S32500011600408200148083000090890000912300004E80002080AB000090A90000912B00000F
-S325000116204E800020814100088121000C7C0A00004082001080890000908300004E800020DB
-S3250001164080C9000090CA00004E8000207FE802A697E1FFE87C09037838E2ED382C09000A06
-S325000116604080002C80C700047C0600004082001080A7000C7C0500004182003039290001CE
-S3250001168038E700142C09000A4180FFDC386282D8480023597C03037883E100007FE803A60F
-S325000116A0382100184E8000209007000C9007001038A0000190A700047CE33B7883E10000F0
-S325000116C07FE803A6382100184E8000207FE802A697E1FFD89061002C7C03000040800008D2
-S325000116E09001002C4BFFEABD906100184BFFFF61818280147C6A1B7880C1002C54C5083CA8
-S325000117007CC62A1454C620367CC62A1438E003E87CC63B9690C3000880A1003090A3000C51
-S3250001172080810034908300107C0B0378812C00187C0900004182003480A90008808A0008C4
-S325000117407C0520004181005480A90008808A00087CA5205090AA00087D2B4B7881290000A0
-S325000117607C0900004082FFD4386C001891610008914100249141000C4BFFFE7D8061001800
-S325000117804BFFEA3D8061002483E100007FE803A6382100284E800020808A00088109000845
-S325000117A07C844050908900084BFFFFC09003000C4E8000204E8000207FE802A697E1FFA8BF
-S325000117C04BFFE9E1814280149061004C812A00187C090000418200A47C0B03787C09000024
-S325000117E04182001080E900087C070000408100A47C0900004182001080E9000838E7FFFFD0
-S3250001180090E900087C090378916100507C095800408000685527103A3901001C7CE7421424
-S3250001182080E7000080E7000C7C07000041820028912100545523103A38C1001C7C63321457
-S32500011840806300007CE803A64E80002181610050812100545525103A3881001C7CA522148A
-S3250001186080A500009005000439290001916100507C0958004180FFA08061004C4BFFE94120
-S3250001188083E100007FE803A6382100584E8000202C0B000A418000084BFFFF589161005041
-S325000118A05568103A38C1001C7D08321491280000386A0018900100089121000C4BFFFD69C0
-S325000118C081428014812A001880E10050396700014BFFFF0CA121000A5527043E54E7C23E7B
-S325000118E098E300005526043E98C300014E800020814100085544463E988300005546843E00
-S3250001190098C300015548C23E99030002994300034E8000207C671B78886300005463C00E76
-S32500011920888700015484801E7C63237888A7000254A5402E7C632B7888C700037C633378AA
-S325000119404E8000207C671B78886300005463402E88A700017C632B784E8000203821FFD83C
-S325000119608222809C814100307C691B787C0F03787C0C03787C0B03787C100378706500014E
-S32500011980418200207C0A000041820014888900007D8C2214394AFFFF392900013A00000191
-S325000119A02C0A001041800054A0E90000A08900027D6B3A14A0C900047DAB2214A109000660
-S325000119C07DCD3214A0A900087DCE4214A0E9000A7DCE2A14A089000C7DCE3A14A0C9000E1D
-S325000119E07DAE22147D6D3214394AFFF0392900102C0A00104080FFB42C0A00024180001C9D
-S32500011A00A0C900007D6B3214394AFFFE392900022C0A00024080FFEC7C10000041820070A2
-S32500011A207C0A00004182000C88A900007DEF2A14889100007C8407747C0400004182004850
-S32500011A407DEF5A145588C23E7D2F4214718800FF5508402E7D2942145528843F41820014F0
-S32500011A607127FFFF7D283A145528843F4082FFF43FE0FFFF63FFFFFF7FE34A7838210028BF
-S32500011A804E8000207D8C5A144BFFFFBC7C0A00004182000C88A900007D8C2A1488910000EF
-S32500011AA07C8407747C0400004182000C7D8C5A144BFFFF947DEF5A144BFFFF8C3821FFF00A
-S32500011AC07C691B787C0B037888E3000070E7000F54EA103A7C0A00004081002888C900006C
-S32500011AE054C6402E890900017CC643787D6B3214394AFFFE392900027C0A00004181FFE08E
-S32500011B007168FFFF5566843E7D0832147104FFFF5507843E7C843A146883FFFF382100106E
-S32500011B204E8000207FE802A697E1FFD0906100343862B7C89061002C9001000838E005F059
-S32500011B4090E1000C4800B1E98061002C3863002A80A1003C90A10008810100409101000C57
-S32500011B604800B4018121002C80C1004039460008980900163900001199090017980900141C
-S32500011B80980900153869001891410020914100084BFFFD458061002C3863001A8102822090
-S32500011BA0910100084BFFFD4D8061002C38630022A0E2822490E100084BFFFD1D8061002C14
-S32500011BC03863001E8101003881080000910100084BFFFD218061002C3863002480810038FB
-S32500011BE0A0840004908100084BFFFCED8061002C3863002680E1002090E100084BFFFCD983
-S32500011C008121002C98090028980900293869001680E1004038E7001490E100084BFFFD41D0
-S32500011C205464043E908100188061002C3863002881010018910100084BFFFC9D3922B7C8B9
-S32500011C40810100403948002C390000459909000E9809000F390000FF990900169121002866
-S32500011C60386900109141002438AAFFF290A100084BFFFC6580610028386300128082801CAB
-S32500011C8038E4000190E2801C908100084BFFFC49812100289809001498090015980900187C
-S32500011CA0980900193869000E4BFFFE155468043E91010018806100283863001880810018DA
-S32500011CC0908100084BFFFC11806100283863000C39000800910100084BFFFBFD80610028B7
-S32500011CE080C1003838C6000690C10008388000069081000C4800B26D8061003438E2B7C817
-S32500011D0090E10008808100249081000C38E0138890E100104800471583E100007FE803A6B5
-S32500011D20382100304E8000207FE802A697E1FF60906100A49801001C38A0000598A1001DC2
-S32500011D409801001E80C100AC98C1001F3861001C3863000480C100B090C100084800B69D27
-S32500011D60806100B04800B66538830005806100A4810100A89101000838C1001C90C1000CED
-S32500011D80908100104BFFFDA180C100B47C0600004182001C38629C48810100AC9101000897
-S32500011DA080C100B090C1000C48001BB983E100007FE803A6382100A04E8000207FE802A648
-S32500011DC097E1FFD09061003480A281F47C0500004082029C392003E880828014808400003A
-S32500011DE05485083C7C842A145484183854A5482C7C84285038C000327C8433967C89221446
-S32500011E009081001880A2801480A5000054A6083C7CA5321454A5183854C6482C7CA530509A
-S32500011E2038E000327CA53B96810100187C082840408102288061003438E2BDB890E10008D1
-S32500011E4080828014808400005486083C7C8432145484183854C6482C7C84305038E00032FD
-S32500011E607C843B96810100187C8440509081000C480044319061002C7C0300004181000820
-S32500011E804BFFFF843882BDB8908100203864000C4BFFFAB55466043E2C060800418200086C
-S32500011EA04BFFFF64806100203863000E4BFFFC11812100207C0300004182001038629C5EC5
-S32500011EC048001AA14BFFFF4088E9000E2C0700454182001038629C6F48001A894BFFFF28A4
-S32500011EE0890900172C080011418200084BFFFF1898090016386900264BFFFA4D5466043EB6
-S32500011F00806100203863001890C1002890C100084BFFF9C580610020386300284BFFFA29FB
-S32500011F207C030000408200F480A10038A0A500047C050000418200208061002038630022A1
-S32500011F404BFFFA0581010038A10800047C0340004082FEB4806100203863001A4BFFF9B9E5
-S32500011F60814100389061001C80AA00003880FFFF7C0520004182001080AA00007C0328002E
-S32500011F804082FE8480C100283926FFF880C100407C0930004081001038629CA6480019C52E
-S32500011FA04BFFFE648061003C808100203884002A90810008912100289121000C4800AFA5FD
-S32500011FC080A1003880E1001C90E5000080610020386300224BFFF97181210038B069000446
-S32500011FE03869000638A2BDB838A5000690A1000838E0000690E1000C4800AF693880000114
-S32500012000908281F48061002883E100007FE803A6382100304E80002080610020386300168C
-S32500012020808100283884000C908100084BFFF9315469043E5528043E7C0800004182FEEC2C
-S3250001204038629C815527043E90E1000880E1002C90E1000C4800190D7C03037883E10000B5
-S325000120607FE803A6382100304E800020392013884BFFFD687FE802A697E1FDC89061023CB4
-S325000120809801002638E0000198E10027386100263863000238829CBB9081000880C10244B4
-S325000120A090C1000C48001879390300023861002638630001910102307C681A1438829CBE60
-S325000120C090810008480018598161024038A3000280C102307CA62A1490A10230A08B0004C1
-S325000120E0908102287C090378912102342C0900054080007081010228B10B00048061023CC1
-S325000121009161000838E1002690E1000C80810230908100104BFFFA1181210240B0090004B8
-S325000121208061023C9121000880A1024890A1000C39000204910100104BFFFC858161024047
-S32500012140812102482C0300044080003480C1023439260001912102342C0900054180FF9814
-S3250001216038629D05480017FD3860FFFF83E100007FE803A6382102384E8000208889000024
-S325000121805484402E88C900017C8433782C040003418200482C040005418200084BFFFFB0BE
-S325000121A038629CC488C9000254C6402E890900037CC6437890C1000838A9000490A1000C36
-S325000121C0480017A13860FFFF83E100007FE803A6382102384E8000203960000188890002C0
-S325000121E05484402E88C900037C843378916283E87C0458004182004838629CDE9081000825
-S32500012200480017618061023C80C1024090C10008388000019081000C38C29CF990C1001036
-S32500012220900100144BFFFB053860FFFF83E100007FE803A6382102384E8000203863FFFC87
-S3250001224083E100007FE803A6382102384E8000207FE802A697E1FFD0812283E890610034F9
-S325000122609801002038800004988100217D25467098A100229921002338A9000190A283E899
-S32500012280810100403908000491010040900100248061003480E1003890E1000838A1002089
-S325000122A090A1000C38E0000490E100104BFFF8798061003480E1003890E1000880A1003CFE
-S325000122C090A1000C81010040910100104BFFFAF1816100408141003C7C691B787C035800B2
-S325000122E04080006438629D2C912100089161000C480016718061003480C1003890C10008E2
-S32500012300388000029081000C38C29D4090C10010900100144BFFFA158101002438C8000102
-S3250001232090C100242C080005408000084BFFFF643860FFFF83E100007FE803A638210030E0
-S325000123404E800020890A00025508402E88AA00037D082B789101002C808283E87C082000FC
-S325000123604182007C38629D4B480015F9814283E88121002C38CAFFFF7C09300040820018B4
-S3250001238080A1002439050001910100242C0500084180FF0038629D4D912100089141000CE7
-S325000123A0480015C18061003480E1003890E1000838A0000190A1000C38E29D7590E100100E
-S325000123C0900100144BFFF9653860FFFF83E100007FE803A6382100304E8000203863FFFC92
-S325000123E083E100007FE803A6382100304E8000207FE802A697E1FC48906103BC48003E6981
-S32500012400814103C0906100C07C0300004082002838629D8180A103BC90A1000848001545A3
-S325000124203860FFFF83E100007FE803A6382103B84E8000209001002C900100287C0A00008D
-S325000124404182001488AA00007CA507747C050000408205C03861024C9001000838A0016C03
-S3250001246090A1000C4800A8C938E0000198E1024C390000019901024D388000069881024E35
-S325000124803861024C3863001C80A100C090A10008390000069101000C4800AAC990028220B1
-S325000124A038A00044B0A28224386282203863000680C100C090C10008388000069081000CEF
-S325000124C04800AAA1900100DC808100DC2C04000A4080009038C0FFFF90C2823838E0004331
-S325000124E0B0E2823C3862823838630006390283689101000838A0000690A1000C4800AA655E
-S32500012500806103BC390282389101000838A1024C90A1000C38E0016C90E100104BFFF609D2
-S32500012520806103BC38C2823890C10008390100E09101000C38A0016C90A100104BFFF881E6
-S325000125407C0300004181045C80C100DC38C6000190C100DC808100DC2C04000A4180FF783B
-S3250001256080C100DC2C06000A4180002038629D94480013F13860FFFF83E100007FE803A6F9
-S32500012580382103B84E8000208101002C7C0800004182040080A1002C88A500007CA5077423
-S325000125A07C050000418203EC8901010C7D0807747C0800004182001838629DA538E100E016
-S325000125C038E7002C90E100084800139938629DA9888100F490810008888100F59081000C2B
-S325000125E0888100F690810010888100F790810014A082823C908100188081002C9081001C2C
-S32500012600480013614BFFEA3D386100E0386300104BFFF30590628220A08283A438E4000126
-S32500012620B0E283A4B0828224386100E0386300144BFFF2E59062823838E00045B0E2823C60
-S32500012640806103BC38C2823890C100088121002C9121000C38C2C5C890C100104BFFFA19F5
-S325000126607C030000408000183860FFFF83E100007FE803A6382103B84E8000203882C5C8A9
-S3250001268039440004906100D82C030020418002CC890A00005508402E88CA00017D0833782A
-S325000126A05508801E88EA000254E7402E888A00037CE723787D083B782C0806EB4082029C2B
-S325000126C088EA000454E7402E88AA00057CE72B7854E7801E88CA000654C6402E890A000744
-S325000126E07CC643787CED337888AA000854A5402E890A00097CA5437854A5801E888A000AF6
-S325000127005484402E88CA000B7C8433787CAC2378890A000C5508402E88CA000D7D083378A8
-S325000127205508801E88EA000E54E7402E888A000F7CE723787D083B78910100C8918100CCDF
-S325000127407CC8621491A100D07CC66A1490C100C488AA001454A5402E890A00157CA54378B0
-S3250001276054A5801E888A00165484402E88CA00177C8433787CA5237838629DD090A100B491
-S325000127803FE01FFF63FFFFFF7FE8283991010008480011D14BFFE8AD38629DDF80C100D003
-S325000127A090C10008480011BD808100B43FE01FFF63FFFFFF7FE42039908100BC38E2C5C821
-S325000127C039A70024808100D83944FFE0816100D0916100D47C0A000040820050806103BC09
-S325000127E0388282389081000838E2C5C890E1000C39000200910100104BFFFA59816100D4F1
-S325000128007C6A1B787C030000408000183860FFFF83E100007FE803A6382103B84E800020D5
-S3250001282038C2C5C839A60004914100D87C0B5000418100087D6A5B78806100BC91A100B89B
-S3250001284091A10008914100DC9141000C4800A715818100CC814100DC80A100BC7D05521476
-S32500012860910100BC80A100B87DA5521491A100B880A100D47D6A285080A100D87D4A28502C
-S32500012880914100D8916100D47C0B00004181FF487C0C000040820088806103BC38C282380B
-S325000128A090C10008390000039101000C38A29DE690A10010900100144BFFF47138629DE9CC
-S325000128C080E100C890E1000880A100C490A1000C4800109138629DF1810100B4910100084C
-S325000128E0480010814BFFE75D4800137D4BFFD8B580C100B43FE01FFF63FFFFFF7FE630395B
-S325000129007CC803A64E8000217C03037883E100007FE803A6382103B84E80002038629DE24B
-S32500012920918100084800103D81A100B8814100D8816100CC916100D4900100CC80E100BC7F
-S3250001294038E70FFF3FE0FFFF63FFF0007FE7383990E100BC4BFFFE80806103BC38C28238B4
-S3250001296090C100089001000C39029DBF9101001038A0000190A100144BFFF3B13860FFFF7F
-S3250001298083E100007FE803A6382103B84E80002038C100E038C6006C90C1002C4BFFFC0CA8
-S325000129A03861024C3863001C390100E03908001C9101000838A0000690A1000C4800AB0D46
-S325000129C0814100287C030000418200084BFFFB7C88E100E12C0700014082FB7088C100E225
-S325000129E02C0600064082FB647C0A00004182FB747D435378388100E03884002C908100089A
-S32500012A004800AA617C0300004182FB584BFFFB3C38610030914100084800A9E13861003008
-S32500012A203880003A908100084800A2E17C0300004182004038E100309061002C7C0338001A
-S32500012A404182FA1488A3FFFF7CA507742C05005C408200084BFFFA0038C1003090C100289C
-S32500012A6038C3000190C1002C980300004BFFF9E8390100309101002C4BFFF9DC3821FFF081
-S32500012A807C691B7880A28014814500047D254B783929FFFF7C050000408100187C0703781A
-S32500012AA07C0750404080FFE838E700014BFFFFF4382100104E8000203821FFF08102801442
-S32500012AC0810800047D0341D638A003E87D482BD741810008394000017C0903787C095040E8
-S32500012AE040800010392900017C0950404180FFF8382100104E8000207FE802A697E1FFF002
-S32500012B00806280284BFFD6F580A2801480E5000038E7000190E500004BFFECA18102823053
-S32500012B207C0800004182000C7D0803A64E80002183E100007FE803A6382100104E80002053
-S32500012B407FE802A697E1FFB88142801480CA000838E003E87CC63BD690CA00044BFFD67D36
-S32500012B60906100443860000A4BFFFF154BFFD66D808100447CE4185090E100447C07000047
-S32500012B80408000084BFFFFD83861002881028014810800049101000848009D69386100203F
-S32500012BA0810280148108000C5504103A7D0822145508083C38A003E87D082BD69101000880
-S32500012BC048009D253861003039010008392100288089000080A900049088000090A80004CD
-S32500012BE038A1001038C10020810600008126000491050000912500044800A0DD38610028C4
-S32500012C00810100445508103A9101000848009CD93861003838C10008390100308128000004
-S32500012C208088000491260000908600043881001038A1002880C500008105000490C40000C3
-S32500012C40910400044800935939010004392100388089000080A900049088000090A8000446
-S32500012C6048009DD581428014906A0004810A00047C0800004082000C38800001908A000486
-S32500012C8080AA000C38C000047CA533D638E000327CA53BD63865FFFF906280284BFFD55DA4
-S32500012CA083E100007FE803A6382100484E8000207FE802A697E1FFE89061001C7C0903788F
-S32500012CC080A282347C09280040800060912100145523103A38C226107C6332148063000088
-S32500012CE08101001C910100084800A779812100147C030000408200245523103A38822690E0
-S32500012D007C6322148063000083E100007FE803A6382100184E8000203929000180A28234A6
-S32500012D207C0928004180FFA87C03037883E100007FE803A6382100184E8000207FE802A69B
-S32500012D4097E1FF28816100E03CE0002090E100A87C0300004182021080E280A080E7000079
-S32500012D6090E1000838E100B490E1000C48002AA9814100A87C030000418100183860FFFF15
-S32500012D8083E100007FE803A6382100D84E800020980A0000386100B49141000838A003FFF6
-S32500012DA090A1000C48001FA57C6A1B787C030000418100183860FFFF83E100007FE803A6E7
-S32500012DC0382100D84E80002080A100A87CA51A1498050000806100A838630400810100A8C6
-S32500012DE09101000838CA000190C1000C4800A175808100A8396404007D6A5B787D6C5B78B4
-S32500012E00888A00007C8407747C04000041820028890A00007D0807742C08000D4082011804
-S32500012E20394A0001888A00007C8407747C0400004082FFE0980B00007D83637838E10020A2
-S32500012E4090E10008388000209081000C38C2886B90C1001048005EF1906100AC7C0A03787A
-S32500012E60808100AC7C0A200040800044914100B05543103A38A100207C632A148063000097
-S32500012E8038E0003D90E1000848009E8181828234814100B07C03000040820028394A0001DE
-S32500012EA0808100AC7C0A20004180FFC47C03037883E100007FE803A6382100D84E800020A7
-S32500012EC039630001980300005547103A390100207CE7421480E700007CE758502C07001DF8
-S32500012EE0418000185546103A38A100207CC62A1480C600009806001B5587103A38A226105F
-S32500012F007CE72A145546103A38A100207CC62A1480C6000090C700005588103A38C2269037
-S32500012F207D08321491680000388C0001908282344BFFFF6C888A00007C8407742C040009BE
-S32500012F404082000C38E0002098EA00007D685B78396B0001892A00007D29077499280000F0
-S32500012F604BFFFEC07C0B00004182005C7D635B7890010008388003FF9081000C4800A5BDCF
-S32500012F807C030000408200183860FFFF83E100007FE803A6382100D84E8000203862885036
-S32500012FA0480009C1806100A880E100E090E100084800A449806100A84800A4117C6A1B7881
-S32500012FC04BFFFE144BFFD5C190610018806100A880C1001890C100084800A421806100A8D4
-S32500012FE04800A3E97C6A1B784BFFFDEC7FE802A697E1FFD89061002C8121003088A90000CC
-S325000130007CA507742C050020408200183929000188A900007CA507742C0500204182FFF0AF
-S325000130207C0A03789141001C2C0A0006408000C0888900007C8407747C04000040820018F8
-S325000130403860FFFF83E100007FE803A6382100284E8000203889000188A900007CA5077461
-S3250001306098A10024890400007D0807747C080000408200183860FFFF83E100007FE803A6F7
-S32500013080382100284E8000203904000191010020888400007C840774988100259801002646
-S325000130A03861002490010008388000109081000C48009EB58141001C812100208101002CE5
-S325000130C07D08521498680000890900007D0807742C08003A4082000839290001394A00014D
-S325000130E09141001C2C0A00064180FF487C03037883E100007FE803A6382100284E800020BA
-S325000131007FE802A697E1FFB87C691B783861002C3902886D910100089121000C81010050D3
-S3250001312091010010480007F97C09037880C282347C093000408000489121001C5523103A59
-S3250001314038E226107C633A14806300003881002C9081000838C0001C90C1000C4800A1F5BB
-S325000131608121001C7C030000418200283929000180C282347C0930004180FFC07C03037896
-S3250001318083E100007FE803A6382100484E80002081010054900800345525103A388226904F
-S325000131A07CA5221480A5000090A1002880E1002888E700007CE707747C07000041820040D7
-S325000131C080C1002888C600007CC607742C0600204182035080E1002888E700007CE7077436
-S325000131E02C0700094182033C80C1002888C600007CC607747C060000408200183860000121
-S3250001320083E100007FE803A6382100484E80002080610028388288729081000838C00005D1
-S3250001322090C1000C4800A12D814100547C030000408200D48101002839080005910100283F
-S325000132407D49537838CA001B7C0930404080002C80A1002888A500007CA507747C05000045
-S325000132604182001880C1002888C600007CC607742C0600204082005C9809000080810028BE
-S32500013280888400007C8407747C0400004182FF2081010028890800007D0807742C080020AF
-S325000132A0408200084BFFFF0880810028888400007C8407742C040009408200084BFFFEF001
-S325000132C080A1002838A5000190A100284BFFFFB080E1002888E700007CE707742C0700095C
-S325000132E04182FF9880A10028388500019081002888A500007CA5077498A9000039290001C0
-S325000133004BFFFF448061002838E2887890E10008388000059081000C4800A0397C03000003
-S3250001332040820028806100283863000539010028910100089001000C48009C2D80A10054D4
-S325000133409065001C4BFFFF388061002838A2887E90A1000838E0000490E1000C48009FF53D
-S325000133607C03000040820028806100283863000438C1002890C100089001000C48009BE952
-S3250001338081010054906800204BFFFEF480610028390288839101000838A0000490A1000CFA
-S325000133A048009FB17C03000040820028806100283863000438810028908100089001000CC6
-S325000133C048009BA580C10054906600244BFFFEB08061002838C2888890C10008390000050D
-S325000133E09101000C48009F6D7C03000040820028806100283863000538E1002890E1000808
-S325000134009001000C48009B6180810054906400284BFFFE6C806100283882888E90810008AD
-S3250001342038C0000390C1000C48009F29812100547C0300004082003C3869002C80A1002894
-S3250001344038A5000390A100084BFFFBA52C03FFFF4082FE2C806100543863002C90010008B4
-S32500013460388000069081000C480098C54BFFFE1080C900342C0600084080FE0480A9003497
-S3250001348054A520367CA54A143945003881010028890800007D0807747C0800004182001807
-S325000134A080E1002888E700007CE707742C07002040820018980A000080C9003438C60001E4
-S325000134C090C900344BFFFDB881010028890800007D0807742C080009408200084BFFFFD8F6
-S325000134E07D445378394A000180A10028390500019101002888A500007CA5077498A400006E
-S325000135007CE9505081090034550820367CE8385038E7FFC82C07000F4180FF744BFFFF9805
-S325000135208101002839080001910100284BFFFC947FE802A697E1FFF09061001480C1001830
-S3250001354090C100084BFFDA118061001480A1001890A100084800729183E100007FE803A6B0
-S32500013560382100104E8000207FE802A697E1FFD0386295484BFFF73D7C691B787C090000A5
-S32500013580418200247D234B789121002C38A2955B90A1000848009C7D8121002C7C0300004B
-S325000135A04182009C3C80FFC260841054908282F4900100247C090000418200187D234B78E0
-S325000135C0900100089001000C4800999D90610024900100283862955F4BFFF6D981210028F1
-S325000135E07C03000041820014900100089001000C480099757C691B787C090000408200081B
-S32500013600392025808061002491210008388281909081000C38C281D890C100103D00FFC24C
-S325000136206108374C910100144BFFD86183E100007FE803A6382100304E8000203CE0FFC2A6
-S3250001364060E7363090E282F44BFFFF687FE802A697E1FFF09061001480C1001870C8007F92
-S32500013660910100182C08001040820010386295644800037981010018806100149101000803
-S3250001368048006A4D83E100007FE803A6382100104E8000207FE802A697E1FFE090610024DE
-S325000136A09001001880C2801480C6000090C100148101002C7C0800004182001C80A2801412
-S325000136C080A5000080C100147CA62850280500FA4181010480628190480069517C691B7874
-S325000136E02C03FFFF408200084BFFFFC82C03000D408200083920000A2C09007F40820008D4
-S32500013700392000089121001C2C090015408200C03900000A99010013386100133880000152
-S325000137209081000880C282F47CC803A64E80002181810024816100288141001C812100180D
-S325000137402C0A0008408200187C0900004081FF5838E9FFFF90E100184BFFFF4C2C0A000A30
-S32500013760408200207CEC4A14980700007D234B7883E100007FE803A6382100204E800020BD
-S325000137802C0A0015408200183860FFFF83E100007FE803A6382100204E8000207C095800AF
-S325000137A0408200187D635B7883E100007FE803A6382100204E8000203909000191010018AD
-S325000137C07C8C4A14994400004BFFFEDC992100134BFFFF483860FFFE83E100007FE803A614
-S325000137E0382100204E8000207FE802A697E1FFE090610024808100289804000080E100308A
-S325000138007C0700004182001880810030888400007C8407747C040000408200FC7C06037850
-S3250001382090C10018808100187C040000418200683862956780C1002490C1000880810030CF
-S325000138409081000C4800011D8061002880E1002C90E1000880C1001890C1000C4BFFFE3998
-S325000138607C691B782C03FFFE4182008C2C03FFFF4182FFB48101002C7C0940004180002C4B
-S3250001388038629580480000DD808100187C0400004082FFA03862957980E1002490E10008AD
-S325000138A0480000C14BFFFFA47C0900004082001080E100187C070000408200187C030378E4
-S325000138C083E100007FE803A6382100204E8000208061002880A1003090A1000848009B1D73
-S325000138E07C03037883E100007FE803A6382100204E8000203862957E38800001908100086D
-S3250001390080C282F47CC803A64E8000217C0903784BFFFF6438C000014BFFFF087FE802A606
-S3250001392097E1FFE89061001C38C3010090C10008808100209081000C38E1002038E7000425
-S3250001394090E10010480007F18081001C7C64185083E100007FE803A6382100184E80002067
-S325000139607FE802A697E1FEE09061012480E282F47C070000408200187C03037883E1000032
-S325000139807FE803A6382101204E8000203861002038C1002038C6010090C1000881010124D7
-S325000139A09101000C38C1012438C6000490C1001048000785390100207C881850386100208E
-S325000139C09081001C90810008810282F47D0803A64E8000218061001C83E100007FE803A613
-S325000139E0382101204E8000207FE802A697E1FEE0812282F4906101247C0900004182007408
-S32500013A003862958F38800007908100087D2803A64E8000213861002038A1002038A501003C
-S32500013A2090A1000880E1012490E1000C38A1012438A5000490A10010480006FD38E100209F
-S32500013A407D071850386100209101000880E282F47CE803A64E8000213862959738800001CD
-S32500013A609081000880C282F47CC803A64E8000214BFFC7154BFFC70D4BFFFFFC7FE802A6FA
-S32500013A8097E1FFE0808280148124002038C0000190C90030808908403FE0FFFF63FFFFFE1E
-S32500013AA07FE4203990890840B0090968B0090964B0090960B0090962B0090966B009095210
-S32500013AC0B0090950B0090954B009095690090ABC90090AB8B0090AC29121001C90090AC42B
-S32500013AE04BFFC6998101001C3CA0000060A58001B0A809C080C1001CA0C609C070C6000132
-S32500013B00418200184BFFC67580C1001CA0C609C070C600014082FFF0386281E038E2B3C83A
-S32500013B2090E10008388004009081000C480065E9386281E03CC0FA2060C6240090C10008E2
-S32500013B40390004009101000C480065F183E100007FE803A6382100204E8000207FE802A6FB
-S32500013B6097E1FFE89061001C4BFFC639906100108102801481080020910100144BFFC5FD16
-S32500013B8081010014A10809C071080001418200184BFFC5E981010014A10809C07108000147
-S32500013BA04082FFF08081001C5484402E80A1002054A520367C842B7880C1002454C6083CF4
-S32500013BC07C8433786084000180A10014B08509C04BFFC5A980E10014A0E709C070E7000146
-S32500013BE0418200184BFFC59580E10014A0E709C070E700014082FFF0806100104BFFC5C1B0
-S32500013C0083E100007FE803A6382100184E8000203821FFE85465183838A5FFF8810100200B
-S32500013C20710800075508183880E1002470E700077D083B787D0B283080E280148127002097
-S32500013C4080E90AEC390000FF7D0828307D0840F87CE740387CE75B7890E90AEC382100183B
-S32500013C604E8000207FE802A697E1FFE080E2801480E7002039270A209121001C80E90000AB
-S32500013C8070E70030418200543860000538C0000490C100089001000C4BFFFEC53860000744
-S32500013CA039000004910100089001000C4BFFFEB1386000014BFFEDC980A1001C80E5000055
-S32500013CC03FE0FFFF63FFFFCF7FE7383990E50000386000044BFFCA9983E100007FE803A687
-S32500013CE0382100204E8000207FE802A697E1FFE07C681B78386281E0900100085507183839
-S32500013D0090E1000C90010010480065997C681B789061001C7C030000408200103862833B0B
-S32500013D204BFFFCC98101001C7D03437883E100007FE803A6382100204E8000207FE802A6AA
-S32500013D4097E1FFE89061001C7C030000418200384BFFC4298121001C386281E07528E00009
-S32500013D603CA020007C0828004182002C7D274B7890E1000880810020548418389081000C5F
-S32500013D80480063B983E100007FE803A6382100184E8000203FE0FFFF63FFFFFF7FE7483981
-S32500013DA04BFFFFD07FE802A697E1FFE83E0000006210900081E1002481C100207C6A1B78D4
-S32500013DC091C3000C9061001C80E300007C070000408200247DC373784BFFFF113E000000E0
-S32500013DE06210900081E1002481C100208141001C906A000080C1002838C6000F3FE0FFFF67
-S32500013E0063FFFFF07FED3039808A00047C0400004082002C91A100287C6E69D64800518558
-S32500013E203E0000006210900081E1002481C1002081A100288141001C906A000480CA0000E3
-S32500013E407C060000418201A880AA00047C0500004182019C80AA000474A5E0003CC020001B
-S32500013E607C05300041820174808A00047C8C23787C0B03787C0B700040800044556418389B
-S32500013E8080EA00007C843A14B004000255661838808A00007CC622149186000455651838FB
-S32500013EA0810A00007CA54214B20500007D8C6A14396B00017C0B70004180FFC4556818388E
-S32500013EC080CA00007D083214A0A8FFF860A52000B0A8FFF8900A000891EA0020808A0010BC
-S32500013EE07C040000408200187DE37B784BFFFDFD81E100248141001C906A0010810A0014BD
-S32500013F007C0800004082001855E3103A4800509581E100248141001C906A001480EA0010A1
-S32500013F207C070000418200A080CA00147C060000418200947C0B03787C0B7800408000504C
-S32500013F405567103A80AA00147CE72A14900700005564183880EA00107C843A149004000475
-S32500013F6055661838808A00107CC62214B00600025568183880CA00107D083214B0080000FB
-S32500013F80396B00017C0B78004180FFB855651838810A00107CA54214A0E5FFF860E72000FF
-S32500013FA0B0E5FFF8900A0018900A001C900A00247C03037883E100007FE803A63821001869
-S32500013FC04E8000203860FFFF83E100007FE803A6382100184E800020808A00043FE0FFFF58
-S32500013FE063FFFFFF7FE420394BFFFE843860FFFF83E100007FE803A6382100184E80002069
-S325000140003821FFF0818282D0816100187C6A1B782C0B00094082005C7D8B6378388C00087C
-S325000140203FE0FFFF63FFFFF87FEC20397D675B78396B0001918282D07C07600040800014C7
-S32500014040808A0000810A00047C0440404180000C382100104E80002080EA000039270001D1
-S32500014060912A000038800020988700004BFFFFC080A30000808300047C0520404080001C97
-S325000140808103000039280001912300009968000038AC000190A282D02C0B000A408200080A
-S325000140A0900282D0382100104E800020814283E07C6907747D26077470C6007F7CC90774A5
-S325000140C07D24077438C285A87C843214888400007C8407747C0400004082002C2C0A001E07
-S325000140E04180000C386000014E8000207D26077438E285A87CC63A14390A0001910283E036
-S32500014100994600007D250774390285A87CA5421488A500007CA5077454A5103A38C284D063
-S325000141207CA5321480E1000890E500007C0303784E8000207FE802A697E1FFC890610018F4
-S3250001414080E1004090E1001C80810048908100208141004438EA000190E10044894A0000FF
-S325000141607D4A07742C0A0025418200487C0A00004082003080A1001880E1001C7C05384069
-S325000141804080000C80810018980400008061001883E100007FE803A6382100384E800020AB
-S325000141A038610018914100084BFFFE594BFFFFA49001002438A0FFFF90A100289001002C3E
-S325000141C03967000191610044894700007D4A07747C0C03782C0A002D4082001C39800001F1
-S325000141E07D6A5B78396B000191610044894A00007D4A07742C0A00304180000C2C0A00396C
-S325000142004081010C7C0C00004182001080A100247D050050910100242C0A002E41820084F6
-S325000142207C0A00004082000C38CBFFFF90C100443861001838A285A87146007F7CA5321438
-S3250001424088A500007CA5077454A5103A38C284D07CA5321480A500007CA803A64E800021B5
-S325000142607C0300004080002C7CA300508081002C7C852B7890A1002C81410044396A000185
-S3250001428091610044894A00007D4A07744BFFFF9480E100207CE71A1490E100204BFFFEB450
-S325000142A07D6A5B78396B000191610044894A00007D4A07742C0A00304180FF682C0A003950
-S325000142C0408100084BFFFF5C808100287C040000408000089001002880C1002854C5103A73
-S325000142E07CC62A1454C6083C7CC6521438C6FFD090C100287D6A5B78396B00019161004456
-S32500014300894A00007D4A07744BFFFFAC810100245507103A7D083A145508083C7D085214E1
-S325000143203908FFD0910100247D6A5B78396B000191610044894A00007D4A07744BFFFEB806
-S325000143407FE802A697E1FFE0906100244800907D7C6A1B789061001C80E1002C7C070000F0
-S325000143604180003C9141001C80C1002C7C0A30004080002C80610028388000209081000842
-S325000143804BFFFC8180C1001C394600019141001C80C1002C7C0A30004180FFDC81610024BF
-S325000143A07D665B78396B00019161001488C600007CC607747C0600004182003480E1003080
-S325000143C07C0700004182FFDC8061002890C100084BFFFC31816100148141001C8101003056
-S325000143E03908FFFF910100304BFFFFB880C1002C7C0600004080004880A1002C7D0500509E
-S325000144009101002C9141001C80A1002C7C0A28004080002C80610028390000209101000806
-S325000144204BFFFBE180A1001C394500019141001C80A1002C7C0A28004180FFDC83E10000AA
-S325000144407FE803A6382100204E8000207FE802A697E1FFA881C282E881A100607C6C1B7806
-S325000144607C0F037880C3001470C600072C0600044181015C418201442C060001418201281F
-S325000144802C0600024182010080AC00088145000038E0000490E1002880CC001470C60004D4
-S325000144A04082000C7C0A0000418000D0980100573960001C7FEA6B967FFF69D67CFF505029
-S325000144C0392700302C09003940810014392900277C0E0000418200083929FFE038C1003AB0
-S325000144E07CC65A14992600002C0B0002408000547C0F0000418200183881003A396BFFFFFE
-S325000145007C845A1438A0002D98A400003861003A7C635A149181000880EC000C90E1000CB6
-S3250001452038E0FFFF90E100104BFFFE198061002883E100007FE803A6382100584E80002060
-S325000145407D4A6B96810C00107C0800004180001880EC00103900001E7CE740507C0B38000D
-S32500014560408000107C0A0000418100084BFFFF84396BFFFF4BFFFF407D4A005039E00001EB
-S325000145804BFFFF2C80AC000880A500007CA907347D2407347C8A2378388000049081002874
-S325000145A04BFFFEF8808C00088144000038C0000490C100284BFFFEE4810C000881480000DC
-S325000145C038A0000490A100284BFFFED02C060005418200302C060006418200084BFFFEAC66
-S325000145E080AC000880A500007CA907345524043E7C8A237838800004908100284BFFFE9CC6
-S3250001460080E300088147000038800004908100284BFFFE887FE802A697E1FFE87C671B78B7
-S32500014620386280B890E100089001000C3880FFFF908100104BFFFD0D7C03037883E1000002
-S325000146407FE803A6382100184E8000207FE802A697E1FFE07C681B7880E3000880E7000035
-S3250001466098E1001E9801001F3861001E910100088088000C9081000C3880FFFF908100108B
-S325000146804BFFFCC13860000483E100007FE803A6382100204E8000207FE802A697E1FFF01F
-S325000146A03900000A910100084BFFFDA583E100007FE803A6382100104E8000203860FFFECA
-S325000146C04E8000203860FFFF4E8000207FE802A697E1FFF038E0000890E100084BFFFD719A
-S325000146E083E100007FE803A6382100104E8000207FE802A697E1FFE87C671B788063000819
-S325000147008063000090E100088107000C9101000C81070010910100104BFFFC2938600004BF
-S3250001472083E100007FE803A6382100184E8000203860FFFC4E8000207FE802A697E1FFF0A8
-S3250001474038A0001090A100084BFFFD0583E100007FE803A6382100104E8000207FE802A60B
-S3250001476097E1FFE839000001910282E838C0001090C100084BFFFCD9900282E883E10000BC
-S325000147807FE803A6382100184E8000207FE802A697E1FFF038E0002590E100084BFFF865D0
-S325000147A07C03037883E100007FE803A6382100104E8000207FE802A697E1FFD89061002CB2
-S325000147C03862889880A1003090A100084BFFF19581A100308181002C3942A1F83902A1F856
-S325000147E0390801407C0A40404080003080CA00047C0D30004082001080EA000C7C0C38002B
-S32500014800418201B4394A00143902A1F8390801407C0A40404180FFD83962A1F838C2A1F8C7
-S325000148203946001438C2A1F838C601407C0A30404080002C808A0000810B00007C044000D4
-S32500014840418100087D4B5378394A001438C2A1F838C601407C0A30404180FFDC7D6A5B783F
-S3250001486080CC001480EC00107D6639D69141002480CA00087C0600004182011480AA001087
-S325000148807C055800418001089161001C916A0010386288BD80AC000C7CAD2A14810C00103A
-S325000148A07CA541D690A100084BFFF0B98141002C806A000080EA000C812100307CE93A14BA
-S325000148C080AA00107CE729D690E1000880AA00087CA803A64E8000218141002C7C03000061
-S325000148E040800020386288CF4BFFF0797C03037883E100007FE803A6382100284E80002050
-S32500014900806A00008101002481080008910100088101001C9101000C80CA00047CC803A65E
-S325000149204E800021816100308141002480A1001C7C03280041820020386288E14BFFF02560
-S325000149407C03037883E100007FE803A6382100284E8000208082801480840000908A0000BF
-S3250001496080C1002C90CA000C916A0004386288F3916100084BFFEFED8061002483E10000C0
-S325000149807FE803A6382100284E8000207D635B789161001C90010008480045818161001C2B
-S325000149A08141002481A100308181002C906A00084BFFFED89141002480A2801480A5000097
-S325000149C090AA0000386288A791A100084BFFEF958061002483E100007FE803A638210028CB
-S325000149E04E8000207FE802A697E1FFD89061002C3862890580E1003090E100084BFFEF6577
-S32500014A00816100308141002C2C0B0002418001AC80EA00347C0B3800408001A0810A003867
-S32500014A202C08000C418201802C080010418200183860FFFF83E100007FE803A63821002841
-S32500014A404E800020556B083C810A0030812A00107D0849D6916100247C0B40404180001451
-S32500014A60386289114BFFEF85816100248141002C808A001080EA00147C8439D67C8B2396E2
-S32500014A80810A00147C8441D680EA003C7C843A1480EA0010810A00147CE741D67FEB3B9697
-S32500014AA07FFF39D67CFF585090E100187D43537890810020908100084BFFFCFD8181002C70
-S32500014AC07C6A1B7880C3000881010018396800017CC6421488C6000090C1002480CC001018
-S32500014AE080EC00147CC639D67C0B3000418000287D836378808C001480A100207C852214CB
-S32500014B00908100084BFFFCB18181002C7C6A1B787C0B0378810A00087D085A1489080000BE
-S32500014B205508402E808100247C8A437880EC00382C07000C4082002080C1003070C6000150
-S32500014B404182005C554AE13E280A0FF841800008614AF0003CE0000060E7FFF87C0A38407C
-S32500014B60408000347D4453783862891880A1003090A10008908100249081000C4BFFEDE57B
-S32500014B808061002483E100007FE803A6382100284E8000203880FFFF4BFFFFD0714A0FFF8E
-S32500014BA04BFFFFA85567083C7D0B3A14392000027D684BD64BFFFE943860FFFF83E10000F0
-S32500014BC07FE803A6382100284E8000207FE802A697E1FFD87C691B7881030000910100243F
-S32500014BE03862892A9121002C390900049101000880C1003090C1000C4BFFED6981A1002CE7
-S32500014C008181003081610024808D00147C04000040820070810B00107D0C41D680CB0014E7
-S32500014C207D0831D680AB002454A528347C082800418000183860FFFF83E100007FE803A6AE
-S32500014C40382100284E800020808B004080AB00147CAC29D67C842A143862893D9181000875
-S32500014C60908100209081000C4BFFECF98061002083E100007FE803A6382100284E800020CC
-S32500014C80808D001C7C0C20004180001080AD00187C050000408200A87C0A0378812D001478
-S32500014CA0914100207C0A6000418200507D635B78912100084BFFFD3181A1002C818100309D
-S32500014CC0816100247C691B787C030000408000183860FFFF83E100007FE803A6382100286D
-S32500014CE04E80002080C1002039460001914100207C0A60004082FFB8914D001C912D0018BD
-S32500014D0038E9FFFE80CB00147CE731D680AB00447CE53A14386289509181000890E1002069
-S32500014D2090E1000C4BFFEC3D8061002083E100007FE803A6382100284E800020814D001CAE
-S32500014D40812D00184BFFFF5C7FE802A697E1FFC87C6A1B788903000F7108001040820050E4
-S32500014D60808A0020810A00107C044000418000187C03037883E100007FE803A638210038CF
-S32500014D804E80002080EA0020810100447CE74214808A00107C07200040810014810A0010E8
-S32500014DA0812A00207D09405091010044810100409101001C7C0B03789161003080E10044FC
-S32500014DC07C0B38004080010C7D43537880CA00209141003C80EA000080E700187CC63BD601
-S32500014DE090C100084BFFFDE97C6A1B787C030000408000183860FFFF83E100007FE803A649
-S32500014E00382100384E8000208061003C80630000914100084BFFF9A18181003C7C03000091
-S32500014E20408200183860FFFF83E100007FE803A6382100384E80002080CC002080EC000030
-S32500014E4080E700187FE63BD67FFF39D67D5F3050810300087DA8521480C1004480810030A0
-S32500014E607D64305080EC000080E700187CEA38507C0B380040810010810C00008108001833
-S32500014E807D6A40508061001C91A100089161002C9161000C480080CD8161002C8141003CA0
-S32500014EA080E1001C7CA75A1490A1001C808A00207CE45A1490EA002080E100307D675A141B
-S32500014EC09161003080E100447C0B38004180FEFC7D635B7883E100007FE803A638210038D2
-S32500014EE04E8000207FE802A697E1FFC08883000F7084001040820020386289634BFFEA6558
-S32500014F003860FFFF83E100007FE803A6382100404E8000209061004480C1004890C10008E2
-S32500014F2048000EA981210044900900207D234B78388100209081000838E0002090E1000CC2
-S32500014F404BFFFE092C030020408201103862897B388100209081000838C1002038C6000828
-S32500014F6090C1000C4BFFE9FD806100443863000438A1002090A1000838E0000890E1000C0A
-S32500014F8048008549812100447C030000418200084BFFFF9C3869000C38C1002038C6000813
-S32500014FA090C10008390000039101000C4800851D812100447C030000418200084BFFFF70E4
-S32500014FC088A1002B70A500084182002838628995388100209081000838C1002038C60008A5
-S32500014FE090C1000C4BFFE97D812100444BFFFF4088A1002B98A9000F88E1003B54E7402E3D
-S325000150008901003A7CE7437890E900148881003F5484402E88A1003E7C842B785484801E0C
-S3250001502088A1003D54A5402E88C1003C7CA533787C842B7890890010900900189009001C19
-S32500015040900900203860000183E100007FE803A6382100404E8000207C03000041800018A4
-S325000150607C03037883E100007FE803A6382100404E8000203860FFFF83E100007FE803A62A
-S32500015080382100404E8000207FE802A697E1FFD07C6D1B7880E1003890E3000C38C002009E
-S325000150A090C3001038800001908300147C0903787DA36B7891A100349121001C91210008B5
-S325000150C04BFFF6F581A100347C6A1B787C03000040820020386289AD4BFFE8893860FFFF43
-S325000150E083E100007FE803A6382100304E80002081030008890801FE2C08005540820380D4
-S3250001510080C3000888C601FF2C0600AA408203709003000C8123000880C1003C7C06000094
-S3250001512041820010890900152C0800F8408201E8812A000888A900002C0500E9418200381E
-S3250001514088C900002C0600EB4082001088E900022C07009041820020386289CD4BFFE805C8
-S325000151603860FFFF83E100007FE803A6382100304E8000207D234B789121002C4800031DFE
-S325000151808141002C81210034888A000C5484402E88CA000B7C8433789089001088EA000D30
-S325000151A090E900148089001080A900147C8429D69089001888CA000F54C6402E890A000E4B
-S325000151C07CC6437890C9001C888A00109089002088CA001254C6402E890A00117CC643786E
-S325000151E090C9002488EA001454E7402E888A00137CE7237890E90028810900287C08000002
-S325000152004082003088EA002354E7402E88AA00227CE72B7854E7801E88CA002154C6402E29
-S32500015220890A00207CC643787CE7337890E90028888A00159089002C88CA001754C6402EAB
-S32500015240890A00167CC6437890C900308089001C9089003C8089002080A900307C8429D61D
-S3250001526080A9003C7C8522149089004080C9002454C6283480E900107CC63A143946FFFFC9
-S3250001528080C900107D4A33D680C900407CC6521490C900448089002880A900447C85205001
-S325000152A080A900147C842BD6388400029089003480C900342C060FF74080005038E0000CB5
-S325000152C090E9003839000002910900489129004C9009006090090068900900649009006CF7
-S325000152E038A0001098A9005B81090024550828349109005C7C03037883E100007FE803A658
-S32500015300382100304E80002038A0001090A900384BFFFFB4808A0008392401BE3980FFFFD4
-S325000153207C0B03782C0B000440800064890900042C0800544082000C3920003F4BFFFD74C6
-S3250001534088A900042C0500014182001088C900042C0600044082011889090000710800801B
-S32500015360418200A88889000B5484402E88E9000A7C843B785484801E890900095508402E4F
-S3250001538088A900087D082B787C8C43782C0B0004408200183900FFFF7C0C40004082000C00
-S325000153A0900A000C4BFFFD8C80C1001C7CC6621490CD000C7DA36B78900100084BFFF3F91D
-S325000153C07C6A1B787C0300004182001480E3000888E701FE2C070055418200183860FFFF25
-S325000153E083E100007FE803A6382100304E80002080A3000888A501FF2C0500AA4082FFE0E7
-S32500015400900A000C4BFFFD2C88E9000B54E7402E88A9000A7CE72B7854E7801E88C90009D3
-S3250001542054C6402E890900087CC643787CE733787C0760404080002C88C9000B54C6402E45
-S325000154408889000A7CC6237854C6801E88A9000954A5402E88E900087CA53B787CCC2B78BC
-S32500015460396B0001392900104BFFFEBC88E900042C0700064082FFEC4BFFFEE0386289C4A0
-S325000154804BFFE4E13860FFFF83E100007FE803A6382100304E8000207FE802A697E1FFE807
-S325000154A07C691B78386289E1888900009081000888C9000190C1000C9121001C890900022E
-S325000154C0910100104BFFE49D38628A0180A1001C38A5000390A100084BFFE4898121001C68
-S325000154E038628A138909000C5508402E88A9000B7D082B78910100084BFFE46938628A212B
-S3250001550080E1001C88E7000D90E100084BFFE4558121001C38628A308889000F5484402E17
-S3250001552088C9000E7C843378908100084BFFE43538628A3C8101001C8908001091010008A5
-S325000155404BFFE4218121001C38628A4788A9001254A5402E88E900117CA53B7890A1000893
-S325000155604BFFE4018121001C38628A55888900145484402E88C900137C843378908100082B
-S325000155804BFFE3E138628A628101001C89080015910100084BFFE3CD8121001C38628A7640
-S325000155A088A9001754A5402E88E900167CA53B7890A100084BFFE3AD8121001C38628A8362
-S325000155C0888900195484402E88C900187C843378908100084BFFE38D8121001C38628A90FB
-S325000155E08909001B5508402E88A9001A7D082B78910100084BFFE36D8121001C38628A9C07
-S3250001560088E9001F54E7402E88A9001E7CE72B7854E7801E88C9001D54C6402E8909001C78
-S325000156207CC643787CE7337890E100084BFFE3358121001C38628AA988A9002354A5402E37
-S32500015640890900227CA5437854A5801E888900215484402E88C900207C8433787CA52378CC
-S3250001566090A100084BFFE2FD38628AB98101001C89080024910100084BFFE2E938628AC6F8
-S3250001568080A1001C88A5002590A100084BFFE2D538628ADA80E1001C88E7002690E10008B1
-S325000156A04BFFE2C18121001C38628AEC8889002A5484402E88E900297C843B785484801EE4
-S325000156C0890900285508402E88A900277D082B787C844378908100084BFFE28938628AFC15
-S325000156E080E1001C38E7002B90E100084BFFE27583E100007FE803A6382100184E800020EF
-S325000157007FE802A697E1FFE8816100207C691B7888C900007CC607742C06002F4082001851
-S325000157203929000188C900007CC607742C06002F4182FFF088A900007CA507747C05000090
-S32500015740418200C088C900007CC607742C060020418200B07C0A037888A900007CA507741E
-S325000157607C0500004182001488C900007CC607742C06002F4082001C980B00007D234B7877
-S3250001578083E100007FE803A6382100184E80002088E900007CE707742C0700204082001CAF
-S325000157A0980B00007D234B7883E100007FE803A6382100184E8000202C0A001C40820020D5
-S325000157C038628B0E4BFFE19D7C03037883E100007FE803A6382100184E8000207D655B7845
-S325000157E0396B00017D264B783929000188C600007CC6077498C50000394A00014BFFFF5CA3
-S325000158007C03037883E100007FE803A6382100184E8000207FE802A697E1FFD080E1003CC1
-S325000158207C641B7838C0000380A4004C8104005090A7000080A400549107000490A7000824
-S3250001584038C6FFFF3884000C38E7000C7C0600004181FFD88061003838A1001490A10008F8
-S325000158604BFFFEA1906100387C030000418200508061003C38A1001490A100084BFFF66991
-S325000158802C03FFFF418200247C030000418200084BFFFFC47C03037883E100007FE803A628
-S325000158A0382100304E8000203860FFFF83E100007FE803A6382100304E8000203860000150
-S325000158C083E100007FE803A6382100304E8000207FE802A697E1FFA880E1006090E100086E
-S325000158E038C1003490C1000C4BFFFF2D814100602C03FFFF418204207C030000418203F82E
-S325000159002C030001418203B43860002090010008480036097C6B1B7838A0002038610034BF
-S3250001592090A1003090A10008916100289161000C4800040581410028810100307C03400002
-S3250001594041820020806282CC4BFFE0193860FFFF83E100007FE803A6382100584E80002041
-S3250001596088CA000054C6402E888A00017CC6237854C6801E88AA000254A5402E88EA00038E
-S325000159807CA53B787CC62B782C0606EB4182004C38628B7C890A00005508402E88CA0001C3
-S325000159A07D0833785508801E88EA000254E7402E888A00037CE723787D083B7891010008B3
-S325000159C04BFFDFA13860FFFF83E100007FE803A6382100584E80002088EA001454E7402E1E
-S325000159E088AA00157CE72B7854E7801E890A00165508402E892A00177D084B787CE74378D6
-S32500015A0074E7E0003C8020007C0720004182027488CA001454C6402E88EA00157CC63B7822
-S32500015A2054C6801E890A00165508402E88AA00177D082B787CC6437890C1002C890A0004B1
-S32500015A405508402E88CA00057D0833785508801E88EA000654E7402E888A00077CE72378BA
-S32500015A607D083B7838628BA791010030910100084BFFDEF13861003480A1003090A100084F
-S32500015A808101002C9101000C480002AD81610030814100287C03580041820020806282CCD6
-S32500015AA04BFFDEC13860FFFF83E100007FE803A6382100584E80002080E1002C7C8B3A146B
-S32500015AC038840FFF3FE0FFFF63FFF0007FE420399081002C88AA000854A5402E890A000950
-S32500015AE07CA5437854A5801E888A000A5484402E88CA000B7C8433787CA5237838628BAB36
-S32500015B0090A1003090A100084BFFDE593861003480E1003090E1000880A1002C90A1000C02
-S32500015B204800021581410028810100307C03400041820020806282CC4BFFDE293860FFFFAA
-S32500015B4083E100007FE803A6382100584E80002038628BAF88CA000C54C6402E888A000D52
-S32500015B607CC6237854C6801E88AA000E54A5402E88EA000F7CA53B787CC62B7890C100084F
-S32500015B80888A00145484402E88EA00157C843B785484801E890A00165508402E88AA001725
-S32500015BA07D082B787C8443789081000C4BFFDDB581410028890A00145508402E88CA00153F
-S32500015BC07D0833785508801E892A00165529402E888A00177D2923787D084B787508E000CF
-S32500015BE03CA020007C0828004182004888EA001454E7402E890A00157CE7437854E7801E1D
-S32500015C00888A00165484402E88CA00177C8433787CE723787CE803A64E8000217C03037807
-S32500015C2083E100007FE803A6382100584E80002088EA001454E7402E888A00157CE72378F6
-S32500015C4054E7801E88AA001654A5402E890A00177CA543787CE72B783FE0FFFF63FFFFFFAC
-S32500015C607FE738397CE803A64E8000217C03037883E100007FE803A6382100584E8000203D
-S32500015C8088CA001454C6402E890A00157CC6437854C6801E888A00165484402E88EA0017BB
-S32500015CA07C843B787CC623783FE0FFFF63FFFFFF7FE630394BFFFD8438628B4A38A10034BB
-S32500015CC038A5000490A1000838E1003438E7000C90E1000C888100439081001080810048F8
-S32500015CE09081001480E1004490E100184BFFDC754BFFFC1838628B3C914100084BFFDC658B
-S32500015D003860FFFF83E100007FE803A6382100584E80002038628B27914100084BFFDC4542
-S32500015D203860FFFF83E100007FE803A6382100584E8000207FE802A697E1FFD88161003043
-S32500015D409061002C80E1003490E100247C0A03787C0A580040800044392020007C8A5850EB
-S32500015D607C044800408000087D2A58508061002C808100249141001C7C845214908100089E
-S32500015D809121000C4BFFEFC58141001C906100207C030000418100187D43537883E1000009
-S32500015DA07FE803A6382100284E80002038628BC44BFFDBB1816100308081002080C1001C0E
-S32500015DC07D4622144BFFFF8C7FE802A697E1FFE0812100287C6B1B783943000488E9000053
-S32500015DE07CE707747C070000418200147CCB505038C6FFFC2C060008418001047CAB5050BD
-S32500015E0038A5FFFC2C050008408000247D455378394A000138C0002098C500007CAB505039
-S32500015E2038A5FFFC2C0500084180FFE4394B000C88A900007CA507747C05000041820014F1
-S32500015E407C8B50503884FFF42C0400034180005C7C8B50503884FFF42C0400034080002428
-S32500015E607D445378394A000138A0002098A400007C8B50503884FFF42C0400034180FFE4AA
-S32500015E8038628BC638AB000490A10008390B000C9101000C4BFFDACD83E100007FE803A69D
-S32500015EA0382100204E800020888900007C8407742C0400614180001488A900007CA50774B5
-S32500015EC02C05007A4081001C888900007C840774988A000039290001394A00014BFFFF5401
-S32500015EE0890900007D0807743908FFE0990A000039290001394A00014BFFFF3888C900008D
-S32500015F007CC607742C06002E4082000C392900014BFFFEEC88A900007CA507742C05006199
-S32500015F204180001488C900007CC607742C06007A4081001C88A900007CA5077498AA0000DF
-S32500015F4039290001394A00014BFFFE94888900007C8407743884FFE0988A000039290001CB
-S32500015F60394A00014BFFFE787FE802A697E1FFC8900100287C0A03782C0A00044080006074
-S32500015F8091410030554818387C8A4214548428347C88205038A2D7D07C642A149061003443
-S32500015FA09001000838E0011890E1000C48006D818061003080C1003490C100084BFFA6CDC1
-S32500015FC0816100347C0300004181002880810030394400012C0A00044180FFA880610028E1
-S32500015FE083E100007FE803A6382100384E8000207C0A03785547183838C282807CE7321415
-S3250001600080E700007C0700004182FFC4914100245543183838E282807C633A1480630000FF
-S32500016020916100084800743D81610034814100247C0300004182000C394A00014BFFFFB897
-S3250001604080810030908B00EC7D635B785548183838E282807D083A14810800047D0803A6B7
-S325000160604E8000217C030000418200084BFFFF603860400038A0000190A100089001000CB0
-S325000160809001001048003E5580E10034906700F43860400038C0000190C100089001000C36
-S325000160A09001001048003E3581410034906A00F839000001910A00F03880000180C10030A6
-S325000160C07C843030810100287D0423789081002838629A1180CA00EC90C100089141000CA8
-S325000160E0808A001C90810010808A0020908100144BFFD87181410034808A00247C040000CC
-S325000161004182002C38629A31808A00247484E0003D2020007C04480041820098810A0024CF
-S32500016120910100084BFFD83D8141003480CA00287C0600004182001438629A3E80AA0028DA
-S3250001614090A100084BFFD81D38629A4B4BFFD8157C0A03782C0A00064080003038629A4D5C
-S325000161609141002C80C100347CAA321488A5002C90A100084BFFD7ED80A1002C39450001CD
-S325000161802C0A00064180FFD838629A554BFFD7D54BFFAEB181410034806A0020810A00D0A1
-S325000161A0910100089141000C48004AC94BFFFE20810A00243FE0FFFF63FFFFFF7FE8403991
-S325000161C04BFFFF607FE802A697E1FFE82C03000440800080546618387CA3321454A528346A
-S325000161E07CA6285038C2D7D07CA5321480A500F07C0500004182005C546718387D033A1468
-S32500016200550828347D0740503922D7D07D484A1480AA00F02C0500014082002438C0000259
-S3250001622090CA00F07D43537891410014810A00BC7D0803A64E800021814100147D435378D7
-S3250001624083E100007FE803A6382100184E8000207C03037883E100007FE803A63821001885
-S325000162604E8000207FE802A697E1FFE84BFFFF597C030000408200187C03037883E1000062
-S325000162807FE803A6382100184E8000203863002C83E100007FE803A6382100184E800020EE
-S325000162A07FE802A697E1FFD84BFFFF1D906100207C030000408200187C03037883E100004B
-S325000162C07FE803A6382100284E80002080828014808400009081001880610020806300F49D
-S325000162E048003C357C6A1B787C0300004082005080A2801480A5000080E100187CA72850E5
-S3250001630054A4083C7CA5221454A518385484482C7CA5205038C000327CA5339680C1003434
-S325000163207C0530404180FFB47C03037883E100007FE803A6382100284E800020810300048C
-S32500016340812300007D094050806100309141001C808A000090810008910100249101000C06
-S3250001636048006C018061001C48003B118061002483E100007FE803A6382100284E800020E8
-S325000163807FE802A697E1FFE87C691B7880610020806300009121001C3889002C9081000858
-S325000163A038E0000690E1000C48007121812100207C03000041820028806900003902836826
-S325000163C09101000838A0000690A1000C480070FD812100207C030000408200288061001C24
-S325000163E0806300F49121000848003BA93860000183E100007FE803A6382100184E8000206D
-S3250001640080E100247C0700004182000C7D234B7848003A697C03037883E100007FE803A6E2
-S32500016420382100184E8000207FE802A697E1FFD89061002C4BFFFD917C030000408200184A
-S325000164407C03037883E100007FE803A6382100284E80002090610024806300F848003BC520
-S325000164602C0340004081002838629A5780A1002C90A100084BFFD4ED7C03037883E1000043
-S325000164807FE803A6382100284E800020386005F0480039919061002080630004810100302D
-S325000164A09101000880C1003490C1000C48006AB580610020806300043863000680E10024F4
-S325000164C038E7002C90E1000838A0000690A1000C48006A91812100208081003480C900044F
-S325000164E07C8622149089000480610024806300F89121000848003A9D4BFF9CA98121002432
-S325000165009061001C7D234B78810900CC7D0803A64E8000218061001C4BFF9CA53860000170
-S3250001652083E100007FE803A6382100284E8000207FE802A697E1FFF880A300EC54A7183899
-S325000165407CA53A1454A5103A3902A3387CA5421480A5000080C5000060C6003090C50000E0
-S325000165604BFF9C1983E100007FE803A6382100084E8000207FE802A697E1FFD89061002CD7
-S325000165808081002C808400EC548518387C842A145484103A38C2A3387D24321481090020E8
-S325000165A0550818389121002080C900187D08321491010018A1080000710880004082001CFF
-S325000165C08061002C806300F84800394D7C691B787C0300004082001483E100007FE803A6BD
-S325000165E0382100284E80002080A3000480C300007CA6285080610018806300049121001C73
-S32500016600810900009101000890A1002490A1000C4800695180C1001881010024B106000203
-S325000166204BFF9B5981210018A0A9000070A5200060A5DC00B0A900004BFF9B41808100205C
-S32500016640808400003D00000061088000B104000C4BFF9B298121002080C9002038C6000110
-S3250001666038E000047FE63BD67FFF39D67CDF305090C900208061001C480038018121002060
-S325000166804BFFFF1C7FE802A697E1FFC8808100409081001C80C400EC54C718387CC63A14A7
-S325000166A054C6103A3902A3387CC6421490C1002880A60000A0A5001090A100304BFF9ABDCB
-S325000166C0808100288084000081010030B10400104BFF9AA98181001C8141002881010030C8
-S325000166E0710800154182002438629BD880AC00EC90A1000880A1003090A1000C4BFFD265B1
-S325000167008181001C8141002881010030710800094082000480AA001454A5183880CA000C93
-S325000167207D65321491610024A0AB00007CA92B7870A58000408201247128003F408200C427
-S3250001674071250C002C050C00408200B8A0AB00023865FFFC90610034480036C98161002482
-S325000167607C0300004182004C9061002080630004808B000490810008808100349081000C12
-S32500016780480067E1812100208081003480C900047C862214908900048061001C9121000812
-S325000167A0390000019101000C4BFFFBD981610024B00B0002A08B0000708420006084900066
-S325000167C0B08B00004BFF99B58181001C8141002880AA001438A5000138C000207FE533D636
-S325000167E07FFF31D67CBF285090AA001480EA001454E71838810A000C7D6742144BFFFF28C1
-S32500016800712700044182001080CC010438C6000190CC01047124000241820010810C011049
-S3250001682039080001910C01107126003F4182001438629BF44BFFD12D816100244BFFFF7480
-S32500016840712808004082FF6C38629BF64BFFD115816100244BFFFF5C80E1003070E7000273
-S32500016860418200107D8363784BFFFD0D8141002880A1003070A50010418200183860000636
-S3250001688080EA000890E100089001000C4BFFD2D183E100007FE803A6382100384E80002089
-S325000168A07FE802A697E1FFE03DA0000061AD90007C6A1B78906100248103000C7C0800004E
-S325000168C04082001C386000204BFFD4213DA0000061AD900081410024906A000C80CA00101B
-S325000168E07C060000408200243C6000006063BE0090010008480026253DA0000061AD900065
-S3250001690081410024906A001080AA001074A5E0003CC020007C0530004182015C808A001046
-S325000169207C8C23787C0B03782C0B0020408000445567183880AA000C7CE72A14B0070002B4
-S325000169405564183880EA000C7C843A14918400045568183880CA000C7D083214B1A80000C3
-S32500016960398C05F0396B00012C0B00204180FFC45564183880EA000C7C843A14A0C4FFF8AE
-S3250001698060C62000B0C4FFF8900A001480CA00187C06000040820014386000044BFFD34DD1
-S325000169A081410024906A0018808A001C7C04000040820018386017C0900100084800255D86
-S325000169C081410024906A001C810A001C7508E0003D2020007C0848004182008880EA001C96
-S325000169E07CEC3B787C0B03782C0B00044080004855651838810A00187CA5421491850004F2
-S32500016A005564183880EA00187C843A14B004000255661838808A00187CC6221439005C00A6
-S32500016A20B1060000398C05F0396B00012C0B00044180FFC05567183880AA00187CE72A148F
-S32500016A40A087FFF860842000B087FFF8900A002083E100007FE803A6382100204E8000204A
-S32500016A6080EA001C3FE0FFFF63FFFFFF7FE738394BFFFF70808A00103FE0FFFF63FFFFFFE5
-S32500016A807FE420394BFFFE9C7FE802A697E1FFD080A3000454A5083C3985FFFE80A2801424
-S32500016AA08145002038A000037CAB6030A0CA09527CC75B78B0EA09527D6658F8A0AA0950B1
-S32500016AC07CA63038B0CA09507D6558F8A08A09547C852838B0AA095438E000307CEB603042
-S32500016AE07D6458F8A10A09627D042038B08A09627D6858F8A0EA09607CE84038B10A0960A2
-S32500016B00A0CA09647CC75B78B0EA0964906100348063000838E1002890E1000838810024D3
-S32500016B209081000C4BFF9BDD8061003480630004808100289081000880E1002490E1000C2F
-S32500016B404BFFD0D180A1003480A5000454A5103A38C283A87CA53214806500009061001C04
-S32500016B609001000838A000A490A1000C480061C13D8020008161001C8141003438800018B1
-S32500016B80988B000438E0001898EB000538A005F0B0AB0006810A000C7508E0007C08600009
-S32500016BA04182018480CA000CB0CB000080AA001874A5E0007C05600041820158810A0018DA
-S32500016BC0B10B00027C03037880AA000890A100089001000C4BFFCF8981A100388181003CB4
-S32500016BE08161001C38E0FFFF90EB00303CA0DEBB60A520E390AB0034900B0038900B003C39
-S32500016C00900B00403C80000060848888B08B004438E0000FB0EB004638A005EEB0AB004AEB
-S32500016C2039000040B10B004C38C005F0B0CB004E388005F0B08B0050B00B00787C0A0378AA
-S32500016C402C0A00064080003C7CEA621488E7000154E7402E7D0C5214890800007CE7437862
-S32500016C60392000027D0A4BD65508083C7D085850B0E80076394A00022C0A00064180FFCCE1
-S32500016C803900080AB10D00083CC0000060C6D555B0CD000E900D00043CC0108860C6000C9E
-S32500016CA090CD00004BFF94D580E100383C8000006084FFFFB08700104BFF94C180A1003847
-S32500016CC038E0001AB0E500144BFF94B1810280148168002081010034810800043908FFFFA1
-S32500016CE0392010007D284030808B0ABC7C87437890EB0ABC80CB0AB87CC44378908B0AB85A
-S32500016D0083E100007FE803A6382100304E800020810A00183FE0FFFF63FFFFFF7FE8403981
-S32500016D204BFFFEA080CA000C3FE0FFFF63FFFFFF7FE630394BFFFE747FE802A697E1FF7011
-S32500016D40906100943861008A9001000838A0000690A1000C48005FD93861008A8101009417
-S32500016D603908002C9101000838C0000690C1000C48006759812100947C030000408200909B
-S32500016D8038629BF84BFFCBDD3861001C39029C11910100084800666538629C1E38C1004EE8
-S32500016DA090C10008390000329101000C38C1001C90C100104BFFCA357C0300004080001854
-S32500016DC03860FFFF83E100007FE803A6382100904E800020806100943863002C3881004E88
-S32500016DE0908100084BFFC209812100947C0300004080001C88C9002C2C0600FF418200104C
-S32500016E0038629C304BFFCB5D4BFFFF8080E9001C54E7103A388280887CE7221480E70000FE
-S32500016E2080C2801480C600207D663A1480C9001C54C6103A38E280307CC63A1480C6000075
-S32500016E4038C6001090C9002080E900EC54E818387CE7421454E7103A3882A3387C672214D7
-S32500016E60916100809163000080E9001C90E3000480E9001C54E7103A390283107CE7421418
-S32500016E8080E7000090E30008906100844BFFFA158061008480A1008090A1000881010094E6
-S32500016EA03908002C9101000C4BFFFBE1812100943D00FFC261086E38910900B83CE0FFC228
-S32500016EC060E7663090E900BC3CC0FFC260C6667490C900CC3CA0FFC260A5678490A900D021
-S32500016EE07C03037883E100007FE803A6382100904E8000203821FFD08161003C82810038C5
-S32500016F00824100407C751B7838A000017CAE583038A000017CA570303A65FFFF38A0000148
-S32500016F207CAA903038A000207CAF96307D4558307E2E2850388000207DAF20507C0D000010
-S32500016F40418000787C0A03787EB06C307C0C03787C0B03787C0B7800408000247E665830D2
-S32500016F607E0630387CC660307D4A33787D8C8A147D6B72147C0B78004180FFE47C0B037820
-S32500016F807C0B90004080001C7DC758307D4738307D4A3B78396B00017C0B90004180FFEC1D
-S32500016FA07E88A3783A940004914800007DAF68507C0D00004080FF90382100304E800020CB
-S32500016FC07FE802A697E1FEF89061010C3861010C480006498141011880C101248081011C93
-S32500016FE07CC430514181001483E100007FE803A6382101084E8000208081012880E1012083
-S325000170007C8720503884FFFF908100FC80A100FC7C0500004080001483E100007FE803A649
-S32500017020382101084E80002080E1010C81A7000C808101107C87683090E1011091A100F402
-S325000170407CCB6830836A000C8081011C7C87D83090E1011C936100F8808101247C87D8307D
-S3250001706090E1012480E1010C83470008832A000880E10114934100E87CE7D1D680A1010C14
-S3250001708080A500047CE72A14808101107C842E707CE43A1454E7103A80C1010C80C60000A8
-S325000170A07EE7321492E100CC80C10120932100EC7CC6C9D6808A00047CC622148101011CD7
-S325000170C07D082E707CC8321454C6103A80AA00007EC62A1492C100D080A1011070AC001F5C
-S325000170E03900FFFF7D086430910100B0918100DC7D0C5A147108001F38A000207D08285085
-S3250001710038C0FFFF7CC840303FE0FFFF63FFFFFF7FE84039910100AC810100AC7C08000071
-S325000171204082000C38A0FFFF90A100AC80C1011C70C6001F90C100E4810101107C8B4214EF
-S325000171403884FFFF7C842E7080A101107CA52E707C8520509081010080A1010C7C0A280080
-S325000171604082005880E10120808101147C0720004080046080C100FC7CC6D1D654C6103A05
-S325000171807EF73214808100FC7C84C9D65484103A7ED6221480EA000854E7083C7F27C85036
-S325000171A0932100EC8081010C808400085484083C7F44D050934100E8808101007C040000D1
-S325000171C04082001480C100AC810100B07D06303890C100B080C1012C70C6000F90C1012C96
-S325000171E07E9B68507D85A63080C100E47E6530507C1803787C1300004080000C3B000001B1
-S325000172007E7300507C1003787C15037892A100A480A100FC7C152800418100F892E100CC6D
-S325000172207EECBB7892E100C492C100D07ECFB37881A100B091A100C07C0E03787C1800007B
-S32500017240408200107DE57B7839EF000481C500007C12037882210100922100A87C110000F9
-S325000172604180008C7C1200004182027C7E0783783A10000481670000814C00008101012CB9
-S325000172802C08000841810194418201702C08000441810110418200F87C080000418200D83B
-S325000172A02C080001418200B02C080002418200942C0800034182006C398C0004918100C48D
-S325000172C039A0FFFF91A100C02C1100014082000C81A100AC91A100C03A52FFFF3A31FFFF1F
-S325000172E0922100A87C1100004080FF7C5727103A7ED63A145747103A7EF73A143AB500015F
-S3250001730092A100A480A100FC7C1528004081FF1083E100007FE803A6382101084E80002025
-S325000173203FE0FFFF63FFFFFF7FE65A787CC652787CC668387D46327890CC00004BFFFF7C16
-S325000173407D6750387CE768387D473A7890EC00004BFFFF683FE0FFFF63FFFFFF7FE85A785E
-S325000173607D0853787D0868387D484278910C00004BFFFF483FE0FFFF63FFFFFF7FE56A7821
-S325000173807D45283890AC00004BFFFF307D6553787CA568387D452A7890AC00004BFFFF1C9C
-S325000173A02C080005418200482C080006418200302C080007418200084BFFFF003FE0FFFFE9
-S325000173C063FFFFFF7FE852787D6843787D0868387D484278910C00004BFFFEE07D67683888
-S325000173E07D473A7890EC00004BFFFED07D446A78908C00004BFFFEC43FE0FFFF63FFFFFF34
-S325000174007FE75A787CE750387CE768387D473A7890EC00004BFFFEA42C08000C41810070EF
-S32500017420418200582C080009418200342C08000A4182FE882C08000B418200084BFFFE7CA1
-S325000174403FE0FFFF63FFFFFF7FE75A787CE768387D473B7890EC00004BFFFE603FE0FFFFB5
-S3250001746063FFFFFF7FE65A787CC668387D46327890CC00004BFFFE447D6852787D08683863
-S325000174807D484278910C00004BFFFE302C08000D418200342C08000E4182001C2C08000FB5
-S325000174A0418200084BFFFE147D476B7890EC00004BFFFE087D6668387D46337890CC0000DE
-S325000174C04BFFFDF87D6750383FE0FFFF63FFFFFF7FE73A787CE768387D473A7890EC000070
-S325000174E04BFFFDD8930100D47C180000418200AC38E000207CF338507DC738307DE57B78CB
-S3250001750039EF000491E100C881C5000091C100BC926100D87DC89C307CEB437838E0000193
-S325000175207CF2A0309241001C2C1400014180FD4C7D635B7838A1002490A100089361000CE3
-S32500017540928100F0928100104BFFF9AD836100F8834100E8832100EC830100D482E100CC6F
-S3250001756082C100D082A100A4828100F0826100D88241001C822100A881E100C881C100BC2A
-S3250001758081A100C0818100C4390100243A080004816800004BFFFCE47DCB98307DE77B781E
-S325000175A039EF000491E100C881C7000091C100BC926100D87C1300004182FF6438E0002050
-S325000175C07CF338507DC73C307D6B3B784BFFFF5080C10120810101147C0640004082FBDC75
-S325000175E080A1011C80E101107C053800418000084BFFFBC84800600181A100F4836100F8AA
-S32500017600834100E8832100EC818100DC82E100CC82C100D04BFFFBA43821FFE87C691B7866
-S3250001762080E30018810300107D68385080E3001C810300147D48385080E3000480C30000B9
-S3250001764080C600207C0730004080003080E9000080E70020808900047CE43850810900109B
-S325000176607CC83A1490C9001080A900047D053A14910900047D6758508109000880E90000E6
-S3250001768080E700247C08380040800030810900008108002480A900087D0540508089001415
-S325000176A07CE4421490E9001480C900087C864214908900087D485050808900047C845A14D6
-S325000176C080C9000080C600287C0430004081002480E900047CEB3A1480A9000080A50028BF
-S325000176E07CE53850810900187CE7405090E9001880C900087CC65214810900008108002C3C
-S325000177007C06400040810024808900087C8A221480E9000080E7002C7C87205080A9001CBA
-S325000177207C8428509089001C8109001080E9000C80E700207C0838004080002C8109000CC1
-S325000177408108002080A900107D054050808900047CE4421490E9000480C900107C8642143D
-S3250001776090890010808900148109000C810800247C0440004080002C8089000C8084002490
-S3250001778080C900147C86205080A900087D0522149109000880E900147CA7221490A9001465
-S325000177A080A900188089000C808400287C0520004081001080E9000C80E7002890E9001839
-S325000177C08089001C8109000C8108002C7C0440004081001080C9000C80C6002C90C9001C65
-S325000177E0382100184E8000203821FFF0814100187C691B787C070378394AFFFF7C0A000084
-S32500017800418000207D244B7839290001888400007CE72214394AFFFF7C0A00004080FFE866
-S325000178207CE33B78382100104E80002081210008390227107C0940404081000C7C0918400D
-S325000178404180000C7C0303784E800020386000014E8000207FE802A697E1FFE080C3000438
-S3250001786038A0FFFF7C0628004182001480C300043CA000047C062840418000187C030378C6
-S3250001788083E100007FE803A6382100204E80002088C3000B2C0600FF4182FFE480E3000472
-S325000178A0810282F87D683A14906100249161001C916100084BFFFF79816100247C0300002D
-S325000178C0408200187C03037883E100007FE803A6382100204E80002088AB000854A5402E50
-S325000178E0890B00097CA5437854A5402E888B000A7CAA23783D0000FF6108FFFF7C0A40005A
-S32500017900408200087C0A03787C0A0000408000187C03037883E100007FE803A63821002050
-S325000179204E8000207C0A0000408100307D635B78914100188121001C7CAA4A1438A5FFFF21
-S3250001794090A100084BFFFEE981610024814100187C0300004182007C80CB000038A0FFFFF7
-S325000179607C062800418200288061001C91410018914100084BFFFE758141001880E100248E
-S3250001798080E700007C0338004082002C80A1002880E1001C90E500008081002C9144000097
-S325000179A03860000183E100007FE803A6382100204E80002038628CD04BFFBFA97C030378AA
-S325000179C083E100007FE803A6382100204E8000207C03037883E100007FE803A638210020DE
-S325000179E04E8000207FE802A697E1FFB8900282F890028300900282FC386100203881003879
-S32500017A009081000838C1003490C1000C4BFF8C157C0300004080002038628CE54BFFBF4519
-S32500017A207C03037883E100007FE803A6382100484E80002081010034910282FC80A1003822
-S32500017A4090A282F880E282F83CE7000490E28300900283049002830880A282F83FE0000387
-S32500017A6063FFFFF07D3F2A149121003C3869000C390282F09101000838A0000490A1000CB9
-S32500017A8048005A497C030000408200A080E1003C88E7000B2C070002408200248061003CC4
-S32500017AA038A1004090A1000838E1004490E1000C4BFFFDA57C030000408200108101003C98
-S32500017AC03928FFF04BFFFFA4808100442C04000B408000108101003C3928FFF04BFFFF8C2F
-S32500017AE080610040390280C09101000838A0000B90A1000C480059D57C0300004182001061
-S32500017B008101003C3928FFF04BFFFF6080E1004090E2830480810044908283088101003C6D
-S32500017B203928FFF04BFFFF4480A283047C050000408200B438628D504BFFBE2980628300B4
-S32500017B404800356D2C0306EB4082002038628D804BFFBE113860000183E100007FE803A665
-S32500017B60382100484E80002081028300890800005508402E80C2830088C600017D083378C9
-S32500017B805508801E80E2830088E7000254E7402E80828300888400037CE723787D083B781A
-S32500017BA02C0806EB4082002038628DAA4BFFBDB53860000183E100007FE803A6382100487C
-S32500017BC04E8000209002830038628DD64BFFBD957C03037883E100007FE803A638210048F3
-S32500017BE04E80002038628D6280E2830490E1000880A2830890A1000C81028304910100100F
-S32500017C004BFFBD614BFFFF38806283044E8000207FE802A697E1FFF080C283007C06000060
-S32500017C204182006880628300480034857C0300004082004480A2830088A5000054A5402EEE
-S32500017C4081028300890800017CA5437854A5801E80828300888400025484402E80C2830074
-S32500017C6088C600037C8433787CA523782C0506EB408200183860000183E100007FE803A63C
-S32500017C80382100104E8000207C03037883E100007FE803A6382100104E8000207FE802A6B2
-S32500017CA097E1FFB080E283007C070000408200183860FFFF83E100007FE803A638210050A1
-S32500017CC04E8000208142830088CA000054C6402E888A00017CC6237854C6801E88AA0002B3
-S32500017CE054A5402E88EA00037CA53B787CC62B782C0606EB408202387D49537888CA0014D2
-S32500017D0054C6402E888A00157CC6237854C6801E88EA001654E7402E890A00177CE743781F
-S32500017D207CC63B7874C6E0003D0020007C064000418201C488A9001454A5402E88C9001574
-S32500017D407CA5337854A5801E88E9001654E7402E888900177CE723787CA53B7890A1004C12
-S32500017D60398A00208161004C88E9000454E7402E88A900057CE72B7854E7801E88C9000661
-S32500017D8054C6402E91210040890900077CC643787CEA33787C0B6000418200507D635B780E
-S32500017DA0916100489181002091810008914100249141000C480051AD38628DF980C1004873
-S32500017DC090C10008808100209081000C80E1002490E100104BFFBB8D818100208161004821
-S32500017DE081410024812100407D8C521480A1004C3CE0FFC07C053840418000E439403000B6
-S32500017E0088A9000854A5402E890900097CA5437854A5801E8889000A5484402E88C9000BF0
-S32500017E207C8433787CA523787D43537891410048918100209181000890A1002490A1000C51
-S32500017E404800512138628E1980A1004890A10008810100209101000C80C1002490C1001078
-S32500017E604BFFBB0138628E398081004C908100084BFFBAF14BFF91CD4BFFBDED8101004CCF
-S32500017E807508E0003CA020007C0828004182002480E1004C7CE803A64E8000213860FFFFB0
-S32500017EA083E100007FE803A6382100504E80002080E1004C3FE0FFFF63FFFFFF7FE73839AF
-S32500017EC07CE803A64E8000213860FFFF83E100007FE803A6382100504E8000207C8A5A148A
-S32500017EE038840FFF3FE0FFFF63FFF0007FEA20394BFFFF1088AA001454A5402E88EA0015F3
-S32500017F007CA53B7854A5801E890A00165508402E88CA00177D0833787CA543783FE0FFFFE9
-S32500017F2063FFFFFF7FE528394BFFFE349141003480C1003490C100283D0A000C9101003090
-S32500017F4080C1003090C1002C386100283881004C90810008480032057C0300004080FF0888
-S32500017F603860FFFF83E100007FE803A6382100504E8000207FE802A697E1FF907C691B78CB
-S32500017F803861003491210008480054713861003438C1002490C10008390000049101000C28
-S32500017FA038C29AD590C1001048000D9D2C030002418201482C030003418200187C030378BA
-S32500017FC083E100007FE803A6382100704E8000208101007C9008000039429E0080AA000492
-S32500017FE07C050000418201007C0903782C090003408000E45524103A7C8452148084001C10
-S325000180007C040000418200C4806100249121001C5528103A9141006C7D0852148108001CEA
-S32500018020910100084800543D8141006C8121001C7C0300004082009480C10078810A0000C1
-S32500018040910600008101007C38A000017CA54830808800007C852B7890A800008061002825
-S3250001806038A1002090A100089001000C48004EF981010080906800007C030000408200144C
-S3250001808080A1002080E100287C053800418200288061008480A1002C90A100084800535D88
-S325000180A03860000183E100007FE803A6382100704E8000207C03037883E100007FE803A687
-S325000180C0382100704E800020392900012C0900034180FF24394A003080AA00047C05000001
-S325000180E04082FF087C03037883E100007FE803A6382100704E80002039029AD79101002C21
-S325000181004BFFFED07FE802A697E1FF30906100D47C0303784BFF8E39814100D8812100D4AA
-S3250001812071440004418200503C60001F6063FF6A38C29AD890C10008810900008108002489
-S325000181409101000C80A9000C90A100104BFFB7D1806100D48063000C810100DC9101000896
-S325000181604BFFA29183E100007FE803A6382100D04E800020714600084182002881090004B8
-S32500018180710800084182001C7C0303784BFFFA85814100D8812100D47C03000040820274EE
-S325000181A071460002418200FC8109000471080010418200348069000C38A29ADE90A10008B2
-S325000181C080E9000080E700187CE803A64E800021806100D43863000C900100084BFFAB6169
-S325000181E0812100D4808100DC7C040000418200A480C100DC88C600007CC607747C06000094
-S32500018200418200908069000C80A100DC90A1000881090000810800187D0803A64E80002191
-S32500018220812100D43C60001F6063FF6A38829AE39081000880C9000080C6002090C1000C7E
-S325000182408109000C91010010810100DC910100144BFFB6CD812100D48069000C80A9001466
-S3250001826090A1000880A9001090A1000C480017A5906100247C0303784BFF8CD58061002485
-S3250001828083E100007FE803A6382100D04E80002080E9000838E7000890E100DC4BFFFF68B6
-S325000182A0714700014182015880890000808400187C040000418200248069000C39029AECA0
-S325000182C09101000880A9000080A500187CA803A64E800021812100D480C9000470C60010D2
-S325000182E0418200103869000C900100084BFFAA5180C100DC7C06000041820084810100DCD5
-S32500018300890800007D0807747C080000418200703861002C810100DC91010008480050DDDC
-S325000183203C60001F6063FF6A38C29AF690C10008810100D4810800008108001C9101000C4A
-S3250001834080A100D480A5000C90A1001038A1002C90A100144BFFB5C9806100D43863000C41
-S325000183603901002C910100084BFFD56983E100007FE803A6382100D04E8000203861002C1E
-S32500018380808280A080840000908100084800506D3861002C38C0002F90C1000848004F3D79
-S325000183A07C03000041820050392300017D234B7838A29AF190A1000848005041806100D438
-S325000183C03863000C3881002C9081000838C100AC90C1000C4BFFD4417C0300004181FF440C
-S325000183E03860FFFF83E100007FE803A6382100D04E8000203921002C4BFFFFB43860FFFF3C
-S3250001840083E100007FE803A6382100D04E8000208069000C4BFFF889814100D8812100D4FA
-S325000184204BFFFD803821FFF08142801838C2E53838C608007C0A3040418000107C030378ED
-S32500018440382100104E8000203923002C80E900007C0700004182001880E900003927007C2A
-S3250001846080E900007C0700004082FFF038EA008090E2801891490000806900003821001080
-S325000184804E8000207FE802A697E1FFA89061005C39629E00810B00047C080000418200302C
-S325000184A080E1005C2C07FFFF41820038808B00008101005C7C08200041820028396B003080
-S325000184C0810B00047C0800004082FFD87C03037883E100007FE803A6382100584E800020DB
-S325000184E080AB000C7C0500004182FFD4808100607C0400004182005C814B002C7C0A0000A9
-S3250001850041820050810A0004812100607D2840394182003480A100642C05FFFF4182001410
-S3250001852080EA000C80C100647C063800408200187D43537883E100007FE803A638210058D5
-S325000185404E800020814A007C7C0A00004082FFB8808B0008708400804082002880AB00083C
-S3250001856060A5008090AB000891610054808B000C7C8803A64E80002181610054906B0028DA
-S325000185807C0D0378808B00287C0400004182FF30810B0028392000017D2968307D084839D9
-S325000185A04082000C39AD00014BFFFFDC3880000191A1004C7C8468307C8420F8810B00283F
-S325000185C07D042038908B00287D635B78916100544BFFFE5581A1004C816100547C6A1B78C5
-S325000185E07C0300004082000C39AD00014BFFFF9891A3000C80CB000890C30004810B0014D5
-S325000186009103001480AB001090A300109163000090610044808300047084000241820078CC
-S325000186207DA36B7838C29AFF90C10008812B00187D2803A64E80002181A1004C816100549F
-S3250001864081410044906A00087C0300004082001880EA00043FE0FFFF63FFFFFD7FE73839F2
-S3250001866090EA000480AA000470A50018408200287DA36B7838A29B0490A1000880EB0018F8
-S325000186807CE803A64E80002181A1004C816100548141004480CA000470C60001418200B82D
-S325000186A09001004838A0000190A1005080CA000080C600187C0600004182005C7DA36B7834
-S325000186C038A29B0990A10008810A0000810800187D0803A64E8000217C0300004182001839
-S325000186E080830000908100487C04000041820008900100508061004C38C29B0D90C10008C3
-S3250001870081010054810800187D0803A64E80002181410044386A000C8081004890810008A8
-S32500018720810100509101000C4BFFC96181A1004C81610054814100447C030000408000DC89
-S3250001874080EA00043FE0FFFF63FFFFEE7FE7383990EA000480AA000470A50010418200705D
-S3250001876080CA00043FE0FFFF63FFFFEF7FE6303990CA0004398282B8918280A0808C0000D7
-S325000187807C04000041820048386A000C80AC000090A1000838A1002090A1000C4BFFD0796B
-S325000187A081A1004C81610054814100447C0300004181005880C280A039860004918280A017
-S325000187C0808C00007C0400004082FFC080EA0004810100607D0738394182FDCC808100644F
-S325000187E02C04FFFF4182001080C100647C0668004082FDB47D43537883E100007FE803A670
-S32500018800382100584E800020808A000460840010908A00044BFFFFB838629B124BFFB1450A
-S3250001882081A1004C81610054814100444BFFFF287FE802A697E1FEF8480004C14BFF7AA127
-S32500018840480006654BFFB2394800254D4BFFAD1D4BFF7B314BFF8F614BFFA2E938629B23FE
-S325000188604BFFB101900280B44BFF791D38629B2C4BFFB0F14BFF7D657C6A1B7838629B32F7
-S32500018880914100E8914100084BFFB0D97C0B037839429E0080CA00047C060000418200209C
-S325000188A080AA00002C050002408203FC394A003080CA00047C0600004082FFE87C0B0000E0
-S325000188C0418203C480CB000470C60010418203B880A100E870A50002408200147C03037804
-S325000188E04BFFF3317C03000040820388900100F0900100F438629B4C4BFFA3B990610024F5
-S32500018900900100FC80A100247C0500004182005838E0000290E100F47C0A03782C0A000329
-S32500018920408002BC80610024914100F855451838388283487CA5221480A5000090A10008BF
-S3250001894048004B21814100F87C030000408202845547183838C283487CE7321480E7000416
-S3250001896090E100F4808100F07C0400004082001080C100F42C060002408201D4980100B0FF
-S325000189803860FFFF9001000838C0FFFF90C1000C4BFFFAF5900100FC39029E0091010020FD
-S325000189A081010020810800047C080000418200D480E100208147002C914101047C0A000094
-S325000189C0418200A4808100FC7C0400004082001838C0000190C100FC38629B884BFFAF8551
-S325000189E08141010480EA000470E700044182002438629B9680CA000080C6002490C1000821
-S32500018A00810A000C9101000C4BFFAF5981410104810A0004710800014182002438629B9D3F
-S32500018A2080EA000080E7001C90E10008808A000C9081000C4BFFAF2D81410104808A00049B
-S32500018A4070840018408200E4810A000471080002408200D8814A007C914101047C0A000015
-S32500018A604082FF6480A1002038A5003090A1002081010020810800047C0800004082FF3483
-S32500018A80808100FC7C0400004182000C38629BAB4BFFAED138629BAD38E1002890E100083E
-S32500018AA0388000509081000C38E100B090E100104BFFAD397C0300004180006838610028A7
-S32500018AC0388100EC9081000838C100FC90C1000C392101009121001038A1007890A10014CC
-S32500018AE04BFFF4957C03000041820038806100EC80A100FC90A10008810101009101000CDE
-S32500018B004BFFF9857C03000041820018810100FC9101000838C1007890C1000C4BFFF5E91E
-S32500018B20980100B04BFFFF7038629BA480EA000080E7002090E10008808A000C9081000CB6
-S32500018B404BFFAE21814101044BFFFF0C3900001F910100FC808100F42C04000140820018F3
-S32500018B6080C100FC3FE0FFFF63FFFFFB7FE6303990C100FC808100E8708400024182001863
-S32500018B8080C100FC3FE0FFFF63FFFFF77FE6303990C100FC3860FFFF80C100FC90C10008D5
-S32500018BA038A0FFFF90A1000C4BFFF8DD7C0300004182FDCC81030004812100FC7D2840382E
-S32500018BC0910100089001000C4BFFF53D4BFFFDB0394A00012C0A00034180FD4C8061002418
-S32500018BE038C100EC90C10008390100FC9101000C38A1010090A1001038E1007890E100142B
-S32500018C004BFFF3757C0300004082001838629B5580810024908100084BFFAD494BFFFD48AB
-S32500018C20806100EC808100FC90810008810101009101000C4BFFF8517C030000408200183D
-S32500018C4038629B6E81010024910100084BFFAD154BFFFD14810100FC9101000838E100781A
-S32500018C6090E1000C4BFFF4A1906100F04BFFFCF838629B404BFFACED7C0303784BFFF021C5
-S32500018C804BFFFC6C7C0303784BFFEF81906100187C03037880E1001890E100084BFFA0A1E7
-S32500018CA04BFFFC3091410020806A000038A0001090A1000838C0FFFF90C1000C4BFFF7C9DD
-S32500018CC0814100207C6B1B787C0300004182FBE0808B000470840010408200084BFFFBD022
-S32500018CE091610104386B000C900100084BFFA051816101044BFFFBC87FE802A697E1FFE891
-S32500018D008062801490010008388000249081000C4800401D80C2801439004E209106000487
-S32500018D204BFF74C180E28014906700103CA0FA2090A7002083E100007FE803A6382100187E
-S32500018D404E8000207FE802A697E1FFE87C691B78900100147C0900004182001488E90000C6
-S32500018D607CE707747C070000408200188061001483E100007FE803A6382100184E800020E9
-S32500018D8080C10014810100247C064000418000188061001483E100007FE803A6382100185C
-S32500018DA04E80002088A900007CA507747C05000041820028806100289121001C88C900005D
-S32500018DC07CC6077490C1000848003F418121001C7C030000408200C0890900007D0807745D
-S32500018DE07C080000408200188061001483E100007FE803A6382100184E8000208081001431
-S32500018E005484103A80E100207C843A149124000088C900007CC607747C060000418200282A
-S32500018E20806100289121001C88E900007CE7077490E1000848003ED58121001C7C030000F4
-S32500018E404182001480E1001438E7000190E100144BFFFF04888900007C8407742C04005CB5
-S32500018E604082001488A900017CA507742C05000A4182000C392900014BFFFF987D264B7893
-S32500018E803929000138E0002098E60000392900014BFFFF807D284B7839290001980800001B
-S32500018EA04BFFFF047FE802A697E1FFE03862813838C2C7D090C10008390010009101000CD4
-S32500018EC04800125538C2271074C6E0003CE020007C0638004182003038A227103862813844
-S32500018EE090A100083CE000407CE5385090E1000C4800124983E100007FE803A638210020E0
-S32500018F004E80002038A227103FE0FFFF63FFFFFF7FE528394BFFFFC87FE802A697E1FFD89A
-S32500018F209061002C810100307C0800004181000C38A0000490A100304BFF72699061002096
-S32500018F4038628138900100088081002C9081000C80E1003090E10010480013499061002409
-S32500018F60806100204BFF725980E100247C0700004082000C38629BC74BFFAA718061002498
-S32500018F809001000880A1002C90A1000C48003DA183E100007FE803A6382100284E8000209E
-S32500018FA07FE802A697E1FFE8388300033FE0FFFF63FFFFFC7FE42039386400089061001C97
-S32500018FC038800004908100084BFFFF5138A300043D00CAFE6108BEEF9103000038650004EC
-S32500018FE08121001C9125000083E100007FE803A6382100184E8000207FE802A697E1FFE0BD
-S325000190007C0300004182005038C3FFF890C1001880C600003CE0CAFE60E7BEEF7C06380084
-S325000190204182000C38629BCE4BFFA9C14BFF7175812100189061001C38628138912100089F
-S32500019040810900049101000C480010F18061001C4BFF716D83E100007FE803A63821002082
-S325000190604E8000204E8000207FE802A697E1FFF0808283809081000C390000FF9904001090
-S325000190804BFF70F98081000C88C4000060C6000198C400004BFF70E58081000C38C000177F
-S325000190A098C400144BFF70D583E100007FE803A6382100104E8000203821FFF080E2838032
-S325000190C09807001489070000710800FE99070000382100104E8000207FE802A697E1FFC092
-S325000190E038C2837090C100308106000C7C0800004182001483E100007FE803A63821004000
-S325000191004E800020386283C84BFFA8598141003038800001908A000C3CA0FA2060A50860F6
-S3250001912090A1003890AA00103CA0FA2060A53C8090AA00144BFFFF858121003080A9002C7B
-S325000191407C050000408200283860008438A0000290A100084BFFFDC5812100309069002C6B
-S3250001916080E9002C38E7008490E9002880E900307C0700004082001C3860008438E00002DF
-S3250001918090E100084BFFFD95812100309069003080E900187C0700004082004838600001D1
-S325000191A04BFFAB49812100309069001880C9003074C6E0003CE020007C06380041820248F1
-S325000191C080A9003080E9001890A7000480E90018B007000280C9001838A02000B0A600008A
-S325000191E080C9001C7C06000040820048386000024BFFAAF9812100309069001C80A9002CB4
-S3250001920074A5E0003CC020007C053000418201E48089002C80C9001C9086000480C9001CC0
-S32500019220B006000280A9001C38802800B085000080A280148145002080EA0AB860E70030D6
-S3250001924090EA0AB8A0EA0AC260E70030B0EA0AC280EA0ABC60E7003090EA0ABC81490014D3
-S3250001926080E9001874E7E0003CC020007C0730004182016C80A90018B0AA00008089001C6C
-S325000192807484E0003D0020007C0440004182013C80E9001CB0EA000238C0001898CA00043B
-S325000192A038800018988A000538E00084B0EA0006900A0008900A000CA08A0000B08A0010B8
-S325000192C0B00A0012900A0018A0AA0002B0AA0020900A001CB00A00224BFF6EA181E2801461
-S325000192E03DC0000161CE86A08181003838C0000198CC000C980C0000980C00047DCD7378F0
-S3250001930080EF00087CE773D6388000027CE723D63A07FFFD7C0B03787C0B80004080008087
-S32500019320394000037C0A000041800068808F000838AA00027C842E305567083C38E700067D
-S325000193407C843BD67D247051408000087D2900507C096800408000307D2D4B78996C00087E
-S3250001936088AC00003FE0FFFF63FFFFF97FE52839390000037D0A40505508083C7CA54378A6
-S3250001938098AC0000394AFFFF7C0A00004080FFA0396B00017C0B80004180FF883860002070
-S325000193A03CC0FFC260C6951890C10008390283709101000C480018BD83E100007FE803A660
-S325000193C0382100404E80002080E9001C3FE0FFFF63FFFFFF7FE738394BFFFEBC80A90018E1
-S325000193E03FE0FFFF63FFFFFF7FE528394BFFFE8C8089002C3FE0FFFF63FFFFFF7FE42039E2
-S325000194004BFFFE1480A900303FE0FFFF63FFFFFF7FE528394BFFFDB07FE802A697E1FFE0F1
-S3250001942080A1002890A10018812500109121001488E9001090E1001C4BFF6D418141001837
-S325000194408121001C80810014992400107126001441820034386283D6912100084BFFA50522
-S325000194608121001880C900207C060000418200089009002083E100007FE803A638210020CF
-S325000194804E8000207127000241820018808A00202C0400034082000C38A0000190AA002004
-S325000194A0712600014182FFD0810A00202C0800044082FFC438800001908A002083E10000BC
-S325000194C07FE803A6382100204E800020806300202C0300024080000C386000014E80002087
-S325000194E07C0303784E8000207FE802A697E1FFE89061001C80C1001C900600249001001446
-S325000195008061001C4BFFFFC97C0300004082007480A280B47C0500004182FFE880E100148A
-S3250001952038E7000190E100142C0700644081002C80C1001C39000001910600208081001C90
-S3250001954038C0000190C4002483E100007FE803A6382100184E800020386000014BFF952127
-S325000195607C03037880E1001C90E100084BFFFEAD8061001C4BFFFF597C0300004182FF948B
-S3250001958083E100007FE803A6382100184E8000207FE802A697E1FFD88181003439628370CF
-S325000195A02C0C0080408100183860FFFF83E100007FE803A6382100284E8000203940000120
-S325000195C080CB002C3FE0FFFF63FFFFFE7FE5183998A60000706500014182001480EB002C5A
-S325000195E07C66467098C70001394A000191610024806B002C914100207C63521480A1003033
-S3250001960090A100089181000C48003959812100243900000391090020808900183D000000F8
-S325000196206108B000B104000080A9002C74A5E0003CC020007C053000418200C88089002C7A
-S3250001964080C9001C9086000480C9001C80A10034808100207CA52214B0A600028109001C54
-S325000196603CE0000060E7B800B0E800004BFFF9FD810100248108001038E0008198E8000C8C
-S325000196804BFF6AF9806100244BFFFE614BFFFA2D81610024814B0020808B001CA0840000BA
-S325000196A0708880004082000C70850007418200183860FFFF83E100007FE803A638210028FB
-S325000196C04E8000202C0A0001418200183860FFFF83E100007FE803A6382100284E8000200A
-S325000196E0808B00247C0400004082FFC88061003483E100007FE803A6382100284E80002033
-S325000197008089002C3FE0FFFF63FFFFFF7FE420394BFFFF307FE802A697E1FFD081E1003C67
-S325000197203DC020007C6C1B78394283702C0F0080408100183860FFFF83E100007FE803A67E
-S32500019740382100304E800020808A002C6068000199040000706800014182002480AA0028DD
-S325000197603FE0FFFF63FFFFFE7FE4603998850000808A00287D8846709904000138A00004E6
-S3250001978090AA002080EA003074E7E0007C077000418201D080CA0030810A001890C8000493
-S325000197A0810A00183CE0000060E7B000B0E800007C0D0378816A001CB00B0008718500018F
-S325000197C04182002C810A00287508E0007C0870004182017C80EA002890EB00043880000284
-S325000197E0B08B0002396B000839A0040080AA002C74A5E0007C0570004182013C9141002C5E
-S32500019800808A002C908B000438CF0001B0CB000261A8A800B10B000091A100207C0D00001F
-S325000198204182001480AA001C3C80000060848000B08500004BFFF83580A1002C80A50010B6
-S32500019840388000819885000C4BFF69318061002C4BFFFC994BFFF86581C1003C8141002CBC
-S3250001986081AA0020816A001CA16B000080A100207C0500004182001080EA001CA0E70008D9
-S325000198807D6B3B78818A0018A18C00027C0C7000408100087DCC7378716800074082000C31
-S325000198A071658000418200183860FFFF83E100007FE803A6382100304E8000202C0D0001B5
-S325000198C0418200183860FFFF83E100007FE803A6382100304E800020808A0018A0840000DF
-S325000198E070848000418200183860FFFF83E100007FE803A6382100304E80002080EA002403
-S325000199007C0700004082FFA48061003880EA003090E10008918100189181000C4800364521
-S325000199208061001883E100007FE803A6382100304E8000209141002C808A002C3FE0FFFFEB
-S3250001994063FFFFFF7FE420394BFFFEBC80EA00283FE0FFFF63FFFFFF7FE738394BFFFE7C36
-S3250001996080CA00303FE0FFFF63FFFFFF7FE630394BFFFE287FE802A697E1FFD88161003437
-S325000199809061002C80A1003890A100247C0A03787C0A58004080004C392020007CEA585083
-S325000199A07C074800408000087D2A58508061002C80E100249141001C7CE7521490E10008FC
-S325000199C09121000C80C100307CC803A64E8000218141001C906100207C030000418100182D
-S325000199E07D43537883E100007FE803A6382100284E800020386285574BFF9F698161003414
-S32500019A0080E100208081001C7D443A144BFFFF847FE802A697E1FFD09061003490010008B1
-S32500019A2080A100387CA803A64E8000217C030000408000183860FFFF83E100007FE803A6A9
-S32500019A40382100304E80002038600020900100084BFFF4C97C6B1B783880002080610034C9
-S32500019A6080E1003C90E100089081002C9081000C91610020916100104BFFFEFD8141002034
-S32500019A8080C1002C7C03300041820020806282CC4BFF9ED13860FFFF83E100007FE803A6CD
-S32500019AA0382100304E800020888A00005484402E88EA00017C843B785484801E890A00029F
-S32500019AC05508402E88AA00037D082B787C8443782C0406EB4182004C3862855988CA0000A2
-S32500019AE054C6402E888A00017CC6237854C6801E88AA000254A5402E88EA00037CA53B784B
-S32500019B007CC62B7890C100084BFF9E593860FFFF83E100007FE803A6382100304E8000203E
-S32500019B2088AA001454A5402E890A00157CA5437854A5801E88CA001654C6402E88EA0017DD
-S32500019B407CC63B787CA5337874A5E0003CE020007C05380041820294888A00145484402E8A
-S32500019B6088AA00157C842B785484801E88CA001654C6402E890A00177CC643787C8433783C
-S32500019B809081002888CA000454C6402E888A00057CC6237854C6801E88AA000654A5402E5C
-S32500019BA088EA00077CA53B787CC62B783862858490C1002C90C100084BFF9DA9806100344E
-S32500019BC08081003C908100088101002C9101000C80A1002890A100104BFFFD9D8161002C60
-S32500019BE0814100207C03580041820020806282CC4BFF9D713860FFFF83E100007FE803A630
-S32500019C00382100304E800020808100287CCB221438C60FFF3FE0FFFF63FFF0007FEB3039D2
-S32500019C2088EA000854E7402E88AA00097CE72B7854E7801E88CA000A54C6402E890A000B5E
-S32500019C407CC643787CE733783862858790E1002C90E10008916100289161000C4BFF9D0532
-S32500019C60806100348101003C9101000880E1002C90E1000C80810028908100104BFFFCF9DD
-S32500019C808141002080E1002C7C03380041820020806282CC4BFF9CCD3860FFFF83E10000D7
-S32500019CA07FE803A6382100304E8000203862859388AA000C54A5402E890A000D7CA5437843
-S32500019CC054A5801E888A000E5484402E88CA000F7C8433787CA5237890A10008890A0014D8
-S32500019CE05508402E88CA00157D0833785508801E88EA001654E7402E888A00177CE72378A8
-S32500019D007D083B789101000C4BFF9C594BFF73354BFF9F554BFF648D8141002088EA001454
-S32500019D2054E7402E88AA00157CE72B7854E7801E890A00165508402E892A00177D084B78C7
-S32500019D407CE7437874E7E0003C8020007C0720004182004888CA001454C6402E88EA0015A4
-S32500019D607CC63B7854C6801E890A00165508402E88AA00177D082B787CC643787CC803A660
-S32500019D804E8000217C03037883E100007FE803A6382100304E80002088CA001454C6402EFA
-S32500019DA0890A00157CC6437854C6801E888A00165484402E88EA00177C843B787CC62378B8
-S32500019DC03FE0FFFF63FFFFFF7FE630397CC803A64E8000217C03037883E100007FE803A6E7
-S32500019DE0382100304E800020888A00145484402E88CA00157C8433785484801E88EA001669
-S32500019E0054E7402E88AA00177CE72B787C843B783FE0FFFF63FFFFFF7FE420394BFFFD64AC
-S32500019E207FE802A697E1FFE89061001C386300184BFFF17138A3001890A3000C8103000C7F
-S32500019E40910300049103000080C3000C80E1001C7CC63A1490C30008900300103D00CAFE70
-S32500019E606108BEE09103001483E100007FE803A6382100184E8000207FE802A697E1FFF0E3
-S32500019E807C691B787C0300004182004090610014810300143CE0CAFE60E7BEE07C0838009F
-S32500019EA041820010386281284BFF9B4181210014900900143CE0DEAD60E7BABE90E900100D
-S32500019EC07D234B784BFFF13583E100007FE803A6382100104E8000207FE802A697E1FFE86F
-S32500019EE0386000144BFFF0BD900300049003000080A1002490A30008808100289083000CC6
-S32500019F009003001083E100007FE803A6382100184E8000207FE802A697E1FFE89061001C49
-S32500019F204BFF62818141001C90610014812A0000912100107C0900004182003C80A90010E0
-S32500019F4090AA00009009001080E90004810900007CE83850810A00107CE7405090EA00101C
-S32500019F6080CA00107C0600004080000C3862812E4BFF9A79806100144BFF624580610010B5
-S32500019F8083E100007FE803A6382100184E8000207FE802A697E1FFE89061001C4BFF6205BB
-S32500019FA08141001C812100207C6B1B789009001080EA00007C0700004082005C912A000011
-S32500019FC0912A000480A9000480C900007CA6285080CA00107CA62A1490AA00107D635B78F4
-S32500019FE04BFF61DD8121001C80A900087C050000418200148069000C80E900087CE803A618
-S3250001A0004E80002183E100007FE803A6382100184E80002080AA0004912500104BFFFFA496
-S3250001A020806300104E8000207FE802A697E1FFE09061002438C0FFFF90C100144BFF616552
-S3250001A04081610014814100247C6C1B78916100147C0B000040800010812A00007C09000015
-S3250001A060408200207D8363784BFF61558061001483E100007FE803A6382100204E8000204C
-S3250001A08080E9000080C900047C073040408000208169000038EB000190E90000896B0000B5
-S3250001A0A0808A00103884FFFF908A001080E9000080C900047C0730404180FF9480E9001025
-S3250001A0C090EA0000900900104BFFFF847FE802A697E1FFE89061001C386000014BFFFD45E9
-S3250001A0E07C681B788083000438C4000190C3000480C1002098C400008061001C9101000833
-S3250001A1004BFFFE9183E100007FE803A6382100184E800020812100089123000480C1000CDD
-S3250001A12038A000087CC62BD654C618387CC64A1490C300084E8000207FE802A697E1FFD844
-S3250001A14081810034816100307C6E1B787C0C00004181001483E100007FE803A638210028E0
-S3250001A1604E8000208143000480AA00047C0558404181001080CA00007C0600004082011C5E
-S3250001A18080AE00047C0A28404081001C38CAFFFC80C6000080EAFFF87CC63A147C065800AD
-S3250001A1A0418200A47D0B6214812A00047C0848004082001080EA00007C07000040820060D7
-S3250001A1C0808E00087C0A20404180002C3862829880AE000090A100089161000C9181001054
-S3250001A1E04BFF978183E100007FE803A6382100284E80002081AA0004916A00047DAB6B78DA
-S3250001A20081AA0000918A0000394A00087DAC6B787C0D00004182FFD04BFFFFA880AA000420
-S3250001A2207D0C2850910A000480EA00007CA7621490AA000083E100007FE803A63821002845
-S3250001A2404E80002080CAFFF87C866214908AFFF87C8B621480AA00047C0428004082FF88A3
-S3250001A26080AA0000808AFFF87CA42A1490AAFFF880EA00007C0700004182FF6C394A000877
-S3250001A280388AFFFC80CA000490C40000810A0000910AFFF84BFFFFDC394A00084BFFFECC77
-S3250001A2A07FE802A697E1FFD881E1003081C1003481A100387C701B7881630004810B0000E4
-S3250001A2C07C08000041820028818B00047C0F00004182005C7C0C784040810028396B000879
-S3250001A2E0810B00007C0800004082FFE07C03037883E100007FE803A6382100284E800020C9
-S3250001A3007D0F7214812B00007D2C4A147C084840408100187C03037883E100007FE803A61E
-S3250001A320382100284E8000207DEC7B787C0D0000408100147C8D62143884FFFF7C846B96B3
-S3250001A3407D8469D680CB000080EB00047CC63A147CCC30507C067040408000084BFFFF80E1
-S3250001A36081AB00047CEC721490EB00047D0C72147D0D4050812B00007D084850910B0000AB
-S3250001A38080CB00007C06000040820028396B000838CBFFFC810B00049106000080AB000003
-S3250001A3A090ABFFF87C050000418200084BFFFFE07C0D6000418200207E03837891A100086D
-S3250001A3C0918100207CCD605090C1000C4BFFFD6D818100207D83637883E100007FE803A6C9
-S3250001A3E0382100284E8000207FE802A697E1FFB8388002809081003438A001E090A1003808
-S3250001A40038C0000390C1003C90010040386100344800042180E100407C07000040820014A8
-S3250001A42083E100007FE803A6382100484E800020388000039082825480A1004090A2824812
-S3250001A44038E000A090E28250900282589002825C3900028091028260388001E0908282645C
-S3250001A46038A2824838C2824880E600108106001490E5002091050024810600188086001C4C
-S3250001A480910500289085002C7C0303783880FFFF9081000838C0FFFF90C1000C3900FFFF63
-S3250001A4A09101001048000641386000FF900100089001000C900100104800062D3862824817
-S3250001A4C038A1000890A1002C80E1002C900700008081002C9004000438C2824890C1001029
-S3250001A4E0390100143882824880A4001080C4001490A8000090C8000480C4001880E4001C87
-S3250001A50090C8000890E8000C900100244BFFCAB538E0000890E280A8900280AC8102800C4B
-S3250001A52089080105910280B083E100007FE803A6382100484E8000207FE802A697E1FFB879
-S3250001A5407C691B7880C282487C0600004082001483E100007FE803A6382100484E80002015
-S3250001A5609061004C2C030008418202302C030009418201D02C03000A4182010480A282609A
-S3250001A580810280B07CA8285080C280A87C062800418000103860000A4BFFFFA18121004C06
-S3250001A5A07129007F408100C8A8E280087C093800408000BC5528183880C2800C7D28321421
-S3250001A5C03881003C38A280A880C5000080E5000490C4000090E400043862824838E100087E
-S3250001A5E090E100348081003488C900047CC607748101003C7CC8321490C4000080C1003457
-S3250001A600810100409106000480A2801090A10010390100149101003080A10030A8E90000F1
-S3250001A62090E50000808100309004000480C1003091210044A90900089106000880A10030C4
-S3250001A64088E2800A7CE7077490E5000C38E0000C90E100244BFFC96D808100448884000511
-S3250001A66080C1003C7C843214908280A883E100007FE803A6382100484E8000203900000892
-S3250001A680910280A88882800A7C840774810280AC7C882214908280AC88C2800A7CC6077431
-S3250001A6A080E282647CC63850810280AC7C0830004081000C80A2825C90A280AC386282488F
-S3250001A6C038E1000890E10034808100349004000080C10034810280AC9106000438A2824881
-S3250001A6E090A1001038E1001490E10030808100309004000080C10030810280AC91060004C4
-S3250001A70080A1003080E2826090E500088081003088C2800A7CC6077454C6083C80E280AC72
-S3250001A7207CC63A1490C4000C900100244BFFC89583E100007FE803A6382100484E800020C3
-S3250001A740808280A83884FFF880A280B07C842BD67084000738C000087C84305080E280B0B5
-S3250001A7607C8439D680A280A87C852214908280A880E280A8808282607C0720004180FEF048
-S3250001A7803860000A4BFFFDB583E100007FE803A6382100484E80002080C280B038C6000899
-S3250001A7A0810280A87C0830004180FEC480A280B080E280A87CA5385090A280A83860002019
-S3250001A7C04BFFFD7980A280B080E280A87CA5385090A280A883E100007FE803A638210048BE
-S3250001A7E04E8000207FE802A697E1FFF07C691B788101001838C8FFFF90C100187C080000F1
-S3250001A8004081002038E9000190E10014886900007C6307744BFFFD25812100144BFFFFD41F
-S3250001A82083E100007FE803A6382100104E8000207FE802A697E1FFD87C6A1B7880E2801479
-S3250001A84080E7002090E10024388001E09083000438E0028090E3000038A0000390A3000802
-S3250001A860806300009141002C80EA00047C6339D638A0001090A100084BFFE6A13DA0017D47
-S3250001A88061AD78408181002C81610024906C000C80AC000080CC00047CA531D690AC0010BF
-S3250001A8A0808B00303FE0FFFF63FFFFBF7FE42039908B0030810C000C7508E0003D2020009F
-S3250001A8C07C0848004182020C80EC000C90EB085080EC0000810C00047CE741D654E7183887
-S3250001A8E038E7007F390000807CE743D654E7881C60E70D6690EB084038A000037C050000C6
-S3250001A900418200142C050002418201A02C050003418201687C0A03782C0A00104080001C3F
-S3250001A9205546083C7CC65A14B1460E00394A00012C0A00104180FFEC808C0004548458289E
-S3250001A9403FE0100063FF00217FE42378908B084880CC000054C6502A3FE0010063FF00E48F
-S3250001A9607FE6337890CB084480C28014818600087D4C6BD67CCC53D67C0668004081000806
-S3250001A980394A00019141001C2C0A00104180000C38E0001090E1001CB00B097638E01FFF06
-S3250001A9A0B0EB0972A0AB097270A5FDFFB0AB097238A01FFFB0AB0970810B0ABC61085001F7
-S3250001A9C0910B0ABC810B0AB861085001910B0AB8A10B0AC27108AFFEB10B0AC24BFF579D44
-S3250001A9E080C100243D0055CC6108AA33910603804BFF578981410024808A02803FE0FFFF74
-S3250001AA0063FFFFE07FE4203938A281108101001C7CA5421488A500007C842B78908A028046
-S3250001AA204BFF575980A100243CE0AA3360E755CC90E503804BFF57458102825091028250D7
-S3250001AA4080A1002438E0000798E508584BFF572D8101002480A8084060A5000190A8084044
-S3250001AA60386000014BFF5D3183E100007FE803A6382100284E8000207C0A03782C0A010043
-S3250001AA804080FEB85544402E554520367C842B787C8453785545083C7CA55A14B0850E0024
-S3250001AAA0394A00014BFFFFD87C0A03782C0A00104080FE885546402E554720367CC63B786D
-S3250001AAC07CC65378B0CB0E00394A00014BFFFFE080EC000C3FE0FFFF63FFFFFF7FE7383960
-S3250001AAE04BFFFDEC80810008548B273E80E1000C54EA273E80A1001054A9273E3FE0FFFF0F
-S3250001AB0063FFFFFF7FE81A78710800FF5508083C80C2801480C600207D0832145565402E8D
-S3250001AB20554620367CA533787CA54B78B0A80E00386000014E8000203821FFE83D4055CCA2
-S3250001AB40614AAA333D20FA209149030038C000C3B0C902009149032038E000C1B0E902204B
-S3250001AB603CA0AA3360A555CC90A903209149034038C00082B0C90240382100184E800020E2
-S3250001AB807FE802A697E1FFE081410028906100247145000341820010386287E44BFF8E4D93
-S3250001ABA081410028812100243CC07C1060C643A690C900003C807C08608402A69089000405
-S3250001ABC03CE07C1260E743A690E900087544E0003CC020007C043000418200887D485378D3
-S3250001ABE07D0A437855053E7F4182000C2C05007F408200303FE003FF63FFFFFC7FE5503919
-S3250001AC003FE0480063FF00037FE52B7890A9000C83E100007FE803A6382100204E8000203A
-S3250001AC205544843E64843C009089000C7144FFFF64846000908900103C807C08608403A678
-S3250001AC40908900143CE04E8060E7002190E9001883E100007FE803A6382100204E80002002
-S3250001AC603FE0FFFF63FFFFFF7FE850394BFFFF747FE802A697E1FFE89061001C8082E53011
-S3250001AC802C0400304180000C386287EC4BFF8D5D80C1001C7D4602148082E53039040001B4
-S3250001ACA09102E5305484203638A2E03038A502007D642A145547103A38C2E0307CE7321436
-S3250001ACC080E7000090EB000881010020910B000080E1002490EB00045544103A38E2E03034
-S3250001ACE07C843A149164000080A28014816500202C0A00104180003038EAFFF070E7001F90
-S3250001AD0038C000017CC7383080CB09487CC73B7890EB094883E100007FE803A63821001845
-S3250001AD204E8000202C0A000841800038714800075508083C38E0001F7D08385039200001E8
-S3250001AD407D284030808B00147C884378910B001483E100007FE803A6382100184E80002076
-S3250001AD605544083C608400013900001F7C84405038A000017CA4203080AB00147CA42378DF
-S3250001AD80908B001483E100007FE803A6382100184E8000207FE802A697E1FFE03D4055CCA6
-S3250001ADA0614AAA33810280148128002080A900043FE0FFFF63FFFFF37FE5283990A9000484
-S3250001ADC09009001438E0FFFF90E900189009094038E0FFFF90E90944900909483CE000E173
-S3250001ADE060E79F0090E9094080A9094060A5008090A909409149030039000001B109020058
-S3250001AE0080C9001464C6004090C900149149030C4BFF53693860FFFF4BFF53E17C090378F4
-S3250001AE202C0930004080002C7D234B789121001C3D00FFC2610803A8910100084BFFFD4551
-S3250001AE4080E1001C392701002C0930004180FFDC83E100007FE803A6382100204E80002031
-S3250001AE607FE802A697E1FFD87C6A1B787C0903782C09002840800064386288065526103A86
-S3250001AE8038A284307CC62A1480C6000090C10008810A00009101000C912100245528103A38
-S3250001AEA038E284307D083A1481080004910100109141002080AA000490A100144BFF8AA5DD
-S3250001AEC0810100243928000280C10020394600082C0900284180FFA483E100007FE803A645
-S3250001AEE0382100284E8000207FE802A697E1FFE87C6A1B789061001C80C3000054C9C23E88
-S3250001AF002C090005418200802C0900094182005C38C0000190C280B47C0900004180003C4F
-S3250001AF202C09001540800034386288345524103A390295A07C8442148084000090810008D0
-S3250001AF404BFF8A218061001C4BFFFF19386288424BFF8A11480000003862881B912100080E
-S3250001AF604BFF8A014BFFFFE07D435378900100084BFF7B8983E100007FE803A63821001875
-S3250001AF804E8000204800001583E100007FE803A6382100184E8000207FE802A697E1FFD82E
-S3250001AFA09061002C810280148168002091610018890B001C550CF0BE7D8A0E7091810024C9
-S3250001AFC071880001418200E02C0A00044082002438800001B08B09304BFF51A1818100241E
-S3250001AFE081610018A0AB093054A5AAFE39450010914100205545103A3882E0307CA52214A6
-S3250001B000814500007C0A00004082000848000000808A000C7C0400004182002038A0001F5B
-S3250001B0207CAC285038C000017CC5283080CB00107CC52B7890AB00108061002C80EA0004D2
-S3250001B04090E100089141001C80EA00007CE803A64E80002180C1001C814600087C0A00006A
-S3250001B060418200084BFFFFD480C100202C060010418000248101001880A1002038A5FFF0B2
-S3250001B080392000017D2528308088094C7C852B7890A8094C83E100007FE803A638210028D2
-S3250001B0A04E800020394A00084BFFFF487C691B7888A3000054A5402E888300017CA52378AD
-S3250001B0C054A5402E88C300027CA5337854A5402E88C300037CA533783CE0FEEF60E70F1EEB
-S3250001B0E07C05380040820030886300205463402E88C900217C6333785463402E88E90022BA
-S3250001B1007C633B785463402E890900237C6343784E8000207C0303784E8000207FE802A63D
-S3250001B12097E1FFE8386001F43CA0FFC260A5B21C90A100089001000C4BFF65959062822CF2
-S3250001B14038628BE04BFF881D83E100007FE803A6382100184E8000207FE802A697E1FFB8E3
-S3250001B160818100507C6B1B788083000480A300007C8520502C040040408000183860FFFF83
-S3250001B18083E100007FE803A6382100484E80002081430000890A00005508402E88EA000110
-S3250001B1A07D083B785508402E892A00027D084B785508402E888A00037D0823783CA0FEEFBF
-S3250001B1C060A50F1E7C082800418200183860FFFF83E100007FE803A6382100484E80002016
-S3250001B1E0900282EC88CA001054C6402E88AA00117CC62B7854C6402E88EA00127CC63B7835
-S3250001B20054C6402E88EA00137CCE3B78888A00145484402E890A00157C8443785484402E08
-S3250001B22088AA00167C842B785484402E88AA00177C842B789081003888EA001854E7402E6E
-S3250001B24088CA00197CE7337854E7402E890A001A7CE7437854E7402E890A001B7CE7437885
-S3250001B26090E1003488AA000C54A5402E888A000D7CA5237854A5402E88CA000E7CA533780F
-S3250001B28054A5402E88CA000F7CA5337890A10030890A00045508402E88EA00057D083B78A1
-S3250001B2A05508402E892A00067D084B785508402E888A00077D0D237888CA000854C6402ED0
-S3250001B2C088AA00097CC62B7854C6402E88EA000A7CC63B7854C6402E88EA000B7CC63B7854
-S3250001B2E090C1002880C3000038C6002090C3000081430000888A00005484402E890A00016A
-S3250001B3007C8443785484402E88AA00027C842B785484402E88AA00037C842B782C0406EB0F
-S3250001B3204182002038628BE24BFF86393860FFFF83E100007FE803A6382100484E8000207A
-S3250001B34088CA001454C6402E88AA00157CC62B7854C6402E88EA00167CC63B7854C6402E3F
-S3250001B36088EA00177CC63B7890CC000081030000390800209103000080EC000074E7E000CC
-S3250001B3803D0020007C0740004182015480CC00007CC3337890C100449161004C916100086B
-S3250001B3A091A1000C91C1001038A28BFF90A1001448000141816100287C6A1B787C030000B1
-S3250001B3C04082002038628C044BFF85993860FFFF83E100007FE803A6382100484E80002059
-S3250001B3E07C0B00004182005C38EA0FFF3FE0FFFF63FFF0007FE3383980E1004C90E1000808
-S3250001B4009161000C810100389101001038C28C1790C10014480000DD7C6A1B787C030000AC
-S3250001B4204082002038628C1C4BFF85393860FFFF83E100007FE803A6382100484E80002040
-S3250001B44080C100307C060000418200407D435378914100408081004C8084000090810008E8
-S3250001B460808100309081000C48001AF981610030808100407D445A1480E1004C80C70000A6
-S3250001B4807C865A1490870000808282EC80C100347C0430004182003038628C2F810282EC50
-S3250001B4A09101000880C1003490C1000C4BFF84B53860FFFF83E100007FE803A638210048EB
-S3250001B4C04E80002080C100447C66505083E100007FE803A6382100484E80002080CC000021
-S3250001B4E03FE0FFFF63FFFFFF7FE630394BFFFEA47FE802A697E1FFE07C6A1B7838628C67A2
-S3250001B5008081003490810008914100249141000C80A1002C90A100104BFF84498101002CAF
-S3250001B5207C080000408200188061002483E100007FE803A6382100204E80002080610028BD
-S3250001B5403902EE00910100089001000C480003257C030000408000187C03037883E100005F
-S3250001B5607FE803A6382100204E8000208061002838E20A0890E10008388000089081000CC2
-S3250001B580480002F1814100287C030000408000187C03037883E100007FE803A63821002041
-S3250001B5A04E80002080CA000480EA00007CC7305080A1002C7C0628004080002038628C7F9F
-S3250001B5C04BFF83A17C03037883E100007FE803A6382100204E800020386001F43D00FFC296
-S3250001B5E06108B21C910100089001000C4BFF60E1814100289062822C80610024810A000031
-S3250001B60091010008810A00008121002C7D084A149101000C38E2EE0090E1001039020A08D9
-S3250001B6209101001480A1003090A100184800006D906100248062822C4BFF61759002822C09
-S3250001B64038628C8E4BFF831D814100247C0A00004082002038628C904BFF83097C03037871
-S3250001B66083E100007FE803A6382100204E80002080E100288081002C80C700007C862214B3
-S3250001B680908700007D43537883E100007FE803A6382100204E8000203821FFE8820100243F
-S3250001B6A081610030812100207C6C1B78556536BE2C050013418201942C05001F4182018C4A
-S3250001B6C02C05003B418201842C05003F4182017C81A282EC7C0980404080016088890000F7
-S3250001B6E07C8F2378392900017C0E03787C8A26707C0A00004082002C7D6A5B78914C00008E
-S3250001B700398C00047DAD521471EA000F39CE00012C0E00014082FFC07C0A00004182FFDC77
-S3250001B7202C0A00014082009488E9000354E7402E88C900027CE7337854E7402E89090001BB
-S3250001B7407CE7437854E7402E890900007CEA4378392900047C098040408100107C030378F2
-S3250001B760382100184E800020554736BE2C070013418200202C07001F418200182C07003B0F
-S3250001B780418200102C07003F418200084BFFFF703FE0FC0063FFF8017FE8503955478BFE4E
-S3250001B7A070E707FE7D083B78714407FE548478207D0A23784BFFFF48280A000841810044D1
-S3250001B7C038AAFFFE54A5402E890900007CA5437854A5103A80C1002C7CA5321480A500046E
-S3250001B7E0890900017CAA4378392900027C0980404081FF787C030378382100184E80002094
-S3250001B800390AFFF75508402E88C900007D0833785508103A80E100287D083A1481480004CC
-S3250001B820392900017C0980404081FF407C030378382100184E80002091A282EC7D83637884
-S3250001B840382100184E8000203FE0FC0063FFF8017FE6583955658BFE70A507FE7CC62B78D4
-S3250001B860716707FE54E778207CCB3B784BFFFE647FE802A697E1FFD08083000480A30000EB
-S3250001B8807C8520502C040002408000183860FFFF83E100007FE803A6382100304E800020A5
-S3250001B8A081030000890800005508402E9061003480E3000088E700017D083B7838628CB398
-S3250001B8C09101001C910100084BFF809981C100388161003480CB000038C6000290CB000080
-S3250001B8E08081001C39A4FFFE7C0D00004081002C810B0004812B00007D0940507C08680096
-S3250001B900408000183860FFFF83E100007FE803A6382100304E800020900E0000814B00005D
-S3250001B92080CB00007D866A14810B00007CC86A1490CB00007C0D03787C0A60404080009011
-S3250001B9407C0B03787C0A6040418000183860FFFF83E100007FE803A6382100304E8000205E
-S3250001B9605568383088CA000070C6007F7D0B33787D455378394A000188A5000070A500808E
-S3250001B980418200207C0A60404180FFD83860FFFF83E100007FE803A6382100304E8000207E
-S3250001B9A07DAD5A14808E000038A4000190AE00005484103A7C84721480E1003C7DA53830F0
-S3250001B9C090A400047C0A60404180FF787C03037883E100007FE803A6382100304E800020E5
-S3250001B9E03821FFF07C6B1B7880A1001C810100247D45421480C10018808100207D26221430
-S3250001BA008081001C7C0A20404080000839290001914B0004912B0000382100104E800020FE
-S3250001BA203821FFF07C6B1B788101001C80C100247D4640508081001880E100207D27205039
-S3250001BA4080E1001C7C0A3840408100083929FFFF914B0004912B0000382100104E80002048
-S3250001BA603821FFD8CA2100307C6E1B78DA210020810100203FE0000F63FFFFFF7FE84039CC
-S3250001BA80650C001081A10024810100205508653E710807FF38C004337D2830507C0B037861
-S3250001BAA07C0A03787C090000418000B02C090020408000847C090000408200607DAB6B783D
-S3250001BAC07D8A637880A1002074A580007C050000418200207C0B0000418200287C040378D2
-S3250001BAE07D6B20503FE0FFFF63FFFFFF7FEA5278914E0000916E0004382100284E800020E6
-S3250001BB007C0703787D4A3850914E0000916E0004382100284E8000207DA54C3038C00020CA
-S3250001BB207CC930507D8630307CAB33787D8A4C304BFFFF942C0900204082000C7D8B63789E
-S3250001BB404BFFFF842C0900404080FF7C38C9FFE07D8B34304BFFFF707C0703787D29385030
-S3250001BB602C09000A418100207DAB48307D85483038C000207CC930507DA634307CAA33784E
-S3250001BB804BFFFF44FC80881ED8828020814280244BFFFF347FE802A697E1FFE8C061002062
-S3250001BBA0D86100084BFFFEBD83E100007FE803A6382100184E8000203D20433080E1000430
-S3250001BBC074E780007C0700004182009C808100087C0400004182007C7C0603788101000852
-S3250001BBE07CC8305090C1000880C100043FE0FFFF63FFFFFF7FE6327890C1000480E1000496
-S3250001BC00912280206CE6800090C28024C8228020FC21D828C8828428FC01013280A100080C
-S3250001BC20912280206CA4800090828024C8628020FC63D828FC03E0004080000CC8428428DA
-S3250001BC40FC63102AFC00182AFC1C00284E8000207C04037880C100047C8620509081000411
-S3250001BC604BFFFF9C80A10004912280206CA4800090828024C8628020FC63D828C84284283B
-S3250001BC80FC0300B281010008912280206D07800090E28024C8228020FC21D828FC01E00081
-S3250001BCA04080000CC8428428FC21102AFC00082A4E8000207FE802A697E1FFF038C1000415
-S3250001BCC038E10014810700008087000491060000908600044BFFFEE5FC00001883E1000047
-S3250001BCE07FE803A6382100104E8000203821FFD83DA080008241003C822100408161002C59
-S3250001BD008181003081210034814100387C0A00004082000C7C090000418200F47C0B68405B
-S3250001BD20418000E07C0F03787C0E03787C096840418000147C096800408200307C0A784031
-S3250001BD40408000285525083C55480FFE7CA94378554A083C39CE00017C0968404180FFE8EC
-S3250001BD607C0968004182FFD87C0F03787C0D03787C0E00004180006455E4083C55A70FFEF6
-S3250001BD807C8F3B7855AD083C7C0B4840418100147C0B4800408200287C0C50404180002001
-S3250001BDA07D9063787D8A60507C0C804040810008396BFFFF7D69585061AD00015547F87E7B
-S3250001BDC05525F8007CEA2B785529F87E39CEFFFF7C0E00004080FFA47C1200004182000C9E
-S3250001BDE091B2000491F200007C1100004182000C9191000491710000382100284E8000207F
-S3250001BE007D6D5B787D8F63784BFFFF207D8C53964BFFFF0C7FE802A697E1FFE07C691B78E9
-S3250001BE2080E100287C07000040820010808100307C0400004182005438E1000439010028D6
-S3250001BE408088000080A800049087000090A7000438A1000C38C1003080E600008106000456
-S3250001BE6090E5000091050004912100147C06037890C100184BFFFE7983E100007FE803A64B
-S3250001BE80382100204E8000207C0803789109000080C1002C80A100347CC62B9690C9000479
-S3250001BEA083E100007FE803A6382100204E8000207FE802A697E1FFE07C691B788101002818
-S3250001BEC07C0800004082001080A100307C05000041820054390100043881002880A40000D9
-S3250001BEE080C4000490A8000090C8000438C1000C38E10030810700008087000491060000E7
-S3250001BF00908600047C04037890810014912100184BFFFDDD83E100007FE803A63821002005
-S3250001BF204E8000207C0403789089000080E1002C80C100347FE733967FFF31D67CFF38503F
-S3250001BF4090E9000483E100007FE803A6382100204E800020808300047C0400004082001821
-S3250001BF6080A300007C0603787CA5305090A300004E800020808300047C0503787C8428505D
-S3250001BF8090830004810300003FE0FFFF63FFFFFF7FE84278910300004E8000207FE802A6D0
-S3250001BFA097E1FFD07C691B78906100348081003C7C84FE7080C100387C06200040820018F6
-S3250001BFC0810100447D08FE7080A100407C054000418200AC80E1003854E70FFE90E1002C92
-S3250001BFE07C07000041820010386100384BFFFF698121003480E1004054E70FFE90E1002809
-S3250001C0007C07000041820010386100404BFFFF498121003438E100043901003880880000EB
-S3250001C02080A800049087000090A7000438A1000C38C1004080E600008106000490E50000F7
-S3250001C04091050004912100147C06037890C100184BFFFC9D80E1002C808100287C072000D7
-S3250001C0604182000C806100344BFFFEED83E100007FE803A6382100304E8000208081003C78
-S3250001C080810100447C8443D69089000480E900047CE7FE7090E9000083E100007FE803A672
-S3250001C0A0382100304E8000207FE802A697E1FFD07C6A1B78906100348101003C7D08FE705D
-S3250001C0C080A100387C0540004082001880E100447CE7FE70808100407C043800418200A48F
-S3250001C0E080C1003854C60FFE90C1002C7C06000041820010386100384BFFFE5D814100345B
-S3250001C10080C1004054C60FFE7C06000041820010386100404BFFFE418141003438C10004C6
-S3250001C12038E10038810700008087000491060000908600043881000C38A1004080C5000040
-S3250001C14080E5000490C4000090E400047C07037890E10014914100184BFFFB9580C1002CEF
-S3250001C1607C0600004182000C806100344BFFFDE983E100007FE803A6382100304E80002037
-S3250001C1808101003C80E100447FE83BD67FFF39D67D1F4050910A000480CA00047CC6FE7067
-S3250001C1A090CA000083E100007FE803A6382100304E8000203821FFF081610020814100180F
-S3250001C1C02C0B0020418000387D46FE7090C300002C0B0040418000147D48FE70910300046D
-S3250001C1E0382100104E800020390BFFE07D48463091030004382100104E8000207C0B00000D
-S3250001C200418100189143000080E1001C90E30004382100104E8000207D465E3090C300007A
-S3250001C22038E000207CEB38507D47383080A1001C7CA55C307CE72B7890E3000438210010D4
-S3250001C2404E8000203821FFF081410020816100182C0A0020418000387C05037890A3000047
-S3250001C2602C0A0040418000147C05037890A30004382100104E800020390AFFE07D68443067
-S3250001C28091030004382100104E8000207C0A0000418100189163000080E1001C90E3000460
-S3250001C2A0382100104E8000207D66543090C3000038E000207CEA38507D67383080A1001CB7
-S3250001C2C07CA554307CE72B7890E30004382100104E8000203821FFF0814100208161001CB6
-S3250001C2E02C0A0020418000387C05037890A300042C0A0040418000147C05037890A300003B
-S3250001C300382100104E800020390AFFE07D68403091030000382100104E8000207C0A0000D7
-S3250001C320418100189163000480E1001890E30000382100104E8000207D66503090C3000427
-S3250001C34038E000207CEA38507D673C3080A100187CA550307CE72B7890E3000038210010A4
-S3250001C3604E80002080C1000880A100107CC6283890C300008081000C810100147C8440383E
-S3250001C380908300044E8000208101000880E100107D083B789103000080C1000C80A1001448
-S3250001C3A07CC62B7890C300044E80002080A10008812100107CA54A7890A300008101000CCD
-S3250001C3C080E100147D083A78910300044E8000208121000880E9000090E300008089000491
-S3250001C3E09083000480C9000438C6000190C90004808900047C0400004082001080A90000EE
-S3250001C40038A5000190A900004E8000208121000880C9000090C300008109000491030004A4
-S3250001C420810900047C08000040820010808900003884FFFF90890000808900043884FFFF6E
-S3250001C440908900044E800020812100087C6A1B7880A9000438A5000190A9000481090004D1
-S3250001C4607C0800004082001080890000388400019089000080890000908A000080C9000410
-S3250001C48090CA00044E800020812100087C6A1B7880E900047C0700004082001081090000DA
-S3250001C4A03908FFFF91090000810900043908FFFF9109000481090000910A000080A90004DF
-S3250001C4C090AA00044E8000207FE802A697E1FFD0814100388121003C90610034390100207C
-S3250001C4E08083000080A300049088000090A8000480A100402C0500064181029C4182023CBE
-S3250001C5002C05000341810164418201002C050001418200942C05000241820030480010D915
-S3250001C5208101003438A1002080C5000080E5000490C8000090E8000483E100007FE803A64F
-S3250001C540382100304E80002088AA000090A1002C7C07037890E1002838610020390100083C
-S3250001C5603881002880A4000080C4000490A8000090C8000438C1001038E1004481070000E5
-S3250001C5808087000491060000908600047D2803A64E80002180C100388101002499060000DD
-S3250001C5A04BFFFF8088AA00007CA5077490A1002C80E1002C54E70FFE90E100283861002059
-S3250001C5C038A1000838C1002880E600008106000490E500009105000439010010388100440B
-S3250001C5E080A4000080C4000490A8000090C800047D2803A64E8000218101003880A10024F8
-S3250001C60098A800004BFFFF1CA90A00009101002C80A1002C54A50FFE90A100283861002098
-S3250001C620390100083881002880A4000080C4000490A8000090C8000438C1001038E100446A
-S3250001C640810700008087000491060000908600047D2803A64E80002180C100388101002433
-S3250001C660B10600004BFFFEBC2C050004418200702C050005418200084BFFFEA4808A000099
-S3250001C6809081002C8081002C54840FFE908100283861002038E100083901002880880000C7
-S3250001C6A080A800049087000090A7000438A1001038C1004480E600008106000490E5000069
-S3250001C6C0910500047D2803A64E80002180A1003880E1002490E500004BFFFE48A10A0000EE
-S3250001C6E09101002C7C05037890A100283861002038C1000838E10028810700008087000492
-S3250001C70091060000908600043881001038A1004480C5000080E5000490C4000090E4000401
-S3250001C7207D2803A64E8000218081003880C10024B0C400004BFFFDEC808A00009081002C29
-S3250001C7407C040378908100283861002038A1000838C1002880E600008106000490E500007D
-S3250001C76091050004390100103881004480A4000080C4000490A8000090C800047D2803A683
-S3250001C7804E8000218101003880A1002490A800004BFFFD902C050007418200DC2C05000885
-S3250001C7A0418200D42C0500094182006C2C05000A418200084BFFFD6880CA000090C1002CF6
-S3250001C7C07C06037890C100283861002038E10008390100288088000080A800049087000055
-S3250001C7E090A7000438A1001038C1004480E600008106000490E50000910500047D2803A683
-S3250001C8004E80002180A1003880E1002490E500004BFFFD1080CA000090C1002C80C1002C44
-S3250001C82054C60FFE90C10028386100203881000838A1002880C5000080E5000490C40000D4
-S3250001C84090E4000438E10010390100448088000080A800049087000090A700047D2803A6DE
-S3250001C8604E80002180E1003880810024908700004BFFFCB0386100203881000880AA000053
-S3250001C88080CA000490A4000090C4000438C1001038E1004481070000808700049106000027
-S3250001C8A0908600047D2803A64E80002180C10038390100208088000080A8000490860000FD
-S3250001C8C090A600044BFFFC5C3821FFF081010018910300047C06037890C300003821001042
-S3250001C8E04E8000203821FFF081010018910300047D06FE7090C30000382100104E8000202E
-S3250001C9003821FFF080A1001890A300047C08037891030000382100104E8000203821FFF026
-S3250001C92080A1001890A300047CA8FE7091030000382100104E8000203821FFF080E1001842
-S3250001C94090E300047C05037890A30000382100104E8000203821FFF080E1001854E7801E39
-S3250001C9607CE88670910300047D06FE7090C30000382100104E8000203821FFF080A10018A2
-S3250001C98070A5FFFF90A300047C04037890830000382100104E8000203821FFF080C1001840
-S3250001C9A054C6C00E7CC7C67090E300047CE5FE7090A30000382100104E8000203821FFF0F7
-S3250001C9C080810018708400FF908300047C08037891030000382100104E8000203821FFF0FB
-S3250001C9E080810018708400FF5483C00E7C63C670382100104E80002080610008706300FF58
-S3250001CA004E8000203821FFF0808100187084FFFF5483801E7C638670382100104E8000202D
-S3250001CA20806100087063FFFF4E800020806100084E800020806100084E80002080610008B0
-S3250001CA404E800020806100084E800020810100087C0800004082001880A100047C0500007C
-S3250001CA604082000C7C0303784E800020386000014E80002080E10008808100107C07200055
-S3250001CA804082001480C100048101000C7C0640004182000C7C0303784E80002038600001D4
-S3250001CAA04E80002080A1000880E100107C0538004082001C8081000480C1000C7C0430004E
-S3250001CAC04082000C7C0303784E800020386000014E8000208101000480A1000C7C082800B3
-S3250001CAE04180002480E100048081000C7C0720004082001C80C10008810100107C0640407A
-S3250001CB004080000C386000014E8000207C0303784E80002080A1000480E1000C7C05380088
-S3250001CB20418000248081000480C1000C7C0430004082001C8101000880A100107C08284082
-S3250001CB404181000C386000014E8000207C0303784E80002080E100048081000C7C0720007C
-S3250001CB604181002480C100048101000C7C0640004082001C80A1000880E100107C053840C2
-S3250001CB804081000C386000014E8000207C0303784E8000208081000480C1000C7C04300050
-S3250001CBA0418100248101000480A1000C7C0828004082001C80E10008808100107C072040EE
-S3250001CBC04180000C386000014E8000207C0303784E80002080C100048101000C7C0640403D
-S3250001CBE04180002480A1000480E1000C7C0538004082001C8081000880C100107C043040D6
-S3250001CC004080000C386000014E8000207C0303784E8000208101000480A1000C7C08284033
-S3250001CC204180002480E100048081000C7C0720004082001C80C10008810100107C06404038
-S3250001CC404181000C386000014E8000207C0303784E80002080A1000480E1000C7C05384005
-S3250001CC60418100248081000480C1000C7C0430004082001C8101000880A100107C08284040
-S3250001CC804081000C386000014E8000207C0303784E80002080E100048081000C7C072040FC
-S3250001CCA04181002480C100048101000C7C0640004082001C80A1000880E100107C05384081
-S3250001CCC04180000C386000014E8000207C0303784E8000208121000C814100088081001484
-S3250001CCE080A100107CC921D67CE920167D0451D67CE742147D0549D67CE7421490C3000413
-S3250001CD0090E300004E8000208881000B3863FFFF8CC300017C062000418200107C060000B7
-S3250001CD204082FFF07C0303784E800020906100048081000C7C0400004081007C80A100086B
-S3250001CD4054A5063E50A5442E50A5801E7CA62B787CA72B787CA82B782C04001040810050F2
-S3250001CD607069000741820018212900087D2103A67CA01D2A7C634A147C8920507C892671A7
-S3250001CD804081002C7D2903A690A300003943000890C3000490EA0000386A0008910A00047F
-S3250001CDA04200FFE85484073F4182000C7C8103A67CA01D2A806100044E8000209061000485
-S3250001CDC08121000C7C6A1B787C090000418200A841800184816100082C0900104081008C73
-S3250001CDE07DAB4A147D8A4A147C0A5840418100CC7D67527870E7000340820084714700038C
-S3250001CE004182002020E700047D2748507CE103A67E005C2A7D6B3A147E00552A7D4A3A148F
-S3250001CE207D2E2671408100447DC903A6396BFFFC394AFFFC860B0004960A0004862B0004AA
-S3250001CE40962A0004860B0004960A0004862B0004962A00044200FFE05529073F4182001895
-S3250001CE60396B0004394A00047D2103A67E005C2A7E00552A806100044E8000207D2E26711F
-S3250001CE80408100247DC903A67E0B84AA396B00107E0A85AA394A00104200FFF05529073F0D
-S3250001CEA04182FFD47D2103A67E005C2A7E00552A806100044E8000202C090004418000843C
-S3250001CEC07DA7627870E700034082007871A70003418200188E0DFFFF9E0CFFFF3929FFFF22
-S3250001CEE071A700034082FFF07D2E2671408100347DC903A6860DFFFC960CFFFC862DFFFC60
-S3250001CF00962CFFFC860DFFFC960CFFFC862DFFFC962CFFFC4200FFE05529073F4182FF58B8
-S3250001CF207D2E16714081001C7DC903A6860DFFFC960CFFFC4200FFF8552907BF4182FF384A
-S3250001CF407C0D58404081FF308E0DFFFF9E0CFFFF4BFFFFF090000000806100044E800020DC
-S3250001CF604BFFFE5C3821FFD08281003881C1003C7C731B787C6B1B787C1203787C0D03781C
-S3250001CF807C1003787C0F0378888B00007C8407742C04000C41810268418202502C04000939
-S3250001CFA0418202482C04000A418202402C04000B4182023888CB00007CC607742C06002D77
-S3250001CFC04182020888EB00007CE707742C07002B418201F87C0E00004082001888AB00007B
-S3250001CFE07CA507742C050030418201B039C0000A2C0E0002418000782C0E002441810070B1
-S3250001D0002C0E00104082001488EB00007CE707742C070030418200F07C0D037838A0FFFFA8
-S3250001D0207E25739688CB00007CC607747CCA33787DCC73782C0600304180000C2C0A00396A
-S3250001D040408100BC2C0A00614180000C2C0A007A408100A42C0A00414180000C2C0A005AFF
-S3250001D0604081008C7C0C7000418000547C100000408200087E6B9B787C14000041820008A2
-S3250001D080917400007C0F0000418200103860FFFF382100304E8000207C12000041820014B4
-S3250001D0A07C0303787C6D1850382100304E8000207DA36B78382100304E8000207C0D8840DC
-S3250001D0C04081000839E000017CAD71D67D4562147C0A68404080000839E000017D4D537819
-S3250001D0E0396B00013A1000014BFFFF3C398AFFC94BFFFF74398AFFA94BFFFF6C398AFFD0BA
-S3250001D1004BFFFF64890B00017D0807742C08007841820018888B00017C8407742C04005828
-S3250001D120418200084BFFFEF488AB00027CA507742C0500304180001C88CB00027CC60774C0
-S3250001D1402C0600394181000C396B00024BFFFECC88EB00027CE707742C0700614180001419
-S3250001D160890B00027D0807742C0800664081FFDC888B00027C8407742C0400414180FE9C80
-S3250001D18088AB00027CA507742C0500464181FE8C396B00024BFFFE8439C00008890B0001EC
-S3250001D1A07D0807742C08007841820018888B00017C8407742C040058418200084BFFFE3483
-S3250001D1C039C000104BFFFE2C7D685B78396B0001890800007D0807742C08002D4082FDF8C5
-S3250001D1E03A4000014BFFFDF0396B0001888B00007C8407742C04000C4081FDA02C04000D6C
-S3250001D2004182FFE82C0400204182FFE04BFFFDA87FE802A697E1FFD8814100309061002C0F
-S3250001D22088AA00007CA5077490A100207C0500004082001483E100007FE803A6382100287C
-S3250001D2404E8000207D435378480001819061001C8061002C80A1002090A100084BFFFAADFF
-S3250001D2607C691B787C0900004182005C7D234B789121002480810030908100088101001C6A
-S3250001D2809101000C480000CD812100247C030000408200187D234B7883E100007FE803A6DE
-S3250001D2A0382100284E8000203869000180C1002090C100084BFFFA557C691B787C09000006
-S3250001D2C04082FFAC7C03037883E100007FE803A6382100284E8000207FE802A697E1FFE88F
-S3250001D2E07C691B7880A100207C050000408200247D234B787C080378910100084BFFFA0DBA
-S3250001D30083E100007FE803A6382100184E8000207C040378908100147D234B78810100200E
-S3250001D320910100084BFFF9E57C0300004182001039230001906100144BFFFFE08061001452
-S3250001D34083E100007FE803A6382100184E8000203821FFF081A100188141001C7C6C1B7818
-S3250001D3607C0A0000408100587D896378398C0001892900007D2907747DAB6B7839AD00019B
-S3250001D380896B00007D6B0774394AFFFF7C095800418200247C095840408100103860000163
-S3250001D3A0382100104E8000203860FFFF382100104E8000207C0900004082FFA87C0303783A
-S3250001D3C0382100104E8000207FE802A697E1FFF0906100147C07037890E100084BFFF92D8D
-S3250001D3E0810100147C68185083E100007FE803A6382100104E8000207FE802A697E1FFE013
-S3250001D400814100287C691B789061001C7D234B789121002491410028914100087C0803788A
-S3250001D4209101000C3900271091010010480001617C0300004082001880A100243925271058
-S3250001D44081010028394827104BFFFFC48061001C83E100007FE803A6382100204E8000207E
-S3250001D4603821FFF0818100187C6B1B787D695B78396B0001892900007D2907747D8A6378B6
-S3250001D480398C0001894A00007D4A07747C095000418200247C09504040810010386000016F
-S3250001D4A0382100104E8000203860FFFF382100104E8000207C0900004082FFB47C0303782D
-S3250001D4C0382100104E8000203821FFE8812100247C6D1B78818100207C0900404081005074
-S3250001D4E07DAB6B7839AD0001896B00007D8A6378398C0001894A00007C0B50004182002406
-S3250001D5007C0B50404081001038600001382100184E8000203860FFFF382100184E8000202F
-S3250001D5203929FFFF7C0900404181FFB87C030378382100184E8000203821FFF08121001CE7
-S3250001D5407C6A1B7880E1001870EB00FF7C090040408100307D475378394A000188E7000040
-S3250001D5607C07580040820010386AFFFF382100104E8000203929FFFF7C0900404181FFD842
-S3250001D5807C030378382100104E8000203821FFF0812100207C6A1B78816100188081001C99
-S3250001D5A0708C00FF7C090040408100407D465378394A00017D645B78396B0001888400002C
-S3250001D5C0988600005484063E7C046000408200107D435378382100104E8000203929FFFF16
-S3250001D5E07C0900404181FFC87C030378382100104E8000207C040378808400007C04000006
-S3150001D600418200084BFFFFF04E8000200000000021
-S3250001D61000810E02001415F0001403E80000000000146530000000010000000000000000A0
-S3250001D6300000000000000000FFFFFFFF0000001E0000001D0000001C0000001B0000000065
-S3250001D6500000000000000000000000000000000000000000000000000000000000000000B3
-S3250001D670000000000000000000000000000000000000000000000000000000000000000093
-S3250001D690FFFFFFFF00000A0000000A2000000A4000000A6000140104000000000000000076
-S3250001D6B0000000000000000000000000000000012A2A2A000000000023706C616E392E6936
-S3250001D6D06E690A00000000005250587369676E61747572653D312E300A4E414D453D71627F
-S3250001D6F0727063670A53544152543D46464332303130300A56455253494F4E3D312E310AC9
-S3250001D710000000000001000000000401080205030C06060909070710100000000000000082
-S3250001D7306672656562007167657400000000000000141BAF0000000000000000000000003F
-S3250001D7500000000000000000000000000000000000000000000000000000000000000000B2
-S3250001D770000000000000000000000000000000000000000000000000000000000000000092
-S3250001D79000000000000000000000000000000000626F6F74006469736B00626F6F740075EA
-S3250001D7B06172743A207374617274207472616E736D697373696F6E0A00756172743A2074A5
-S3250001D7D0696D656F75740A006E007900000000000000000000000000001403200000000077
-S3250001D7F0000000000000000000000000000000000000000000000000000000000000000012
-S3250001D8100000000000000000000000000000000000000000000000000000000000000000F1
-S3250001D8300000000000000000FFC206F000000000000000000000000000000000000000001A
-S3250001D8500000000000000000000000000000000000000000000000000000000000000000B1
-S3250001D87000000000000000000000000000000000000000000000000000141A00FFC26E38FC
-S3250001D89000141A04FFC26E3800000000000000006D6170667265653A2025733A206C6F735E
-S3250001D8B0696E672030782575582C2025640A000000141A9300141AA700141AB300141AC312
-S3250001D8D0000000000014054000000000000000006E6577616C61726D000000000000000081
-S3250001D8F00000000000000000F1A55A1FFFC2363000000000000000000000000000000000DB
-S3250001D9100000000000000000FFFFFFFF0000000000000004000000080000000C00000000DC
-S3250001D9306275666665722064657363726970746F7273006264616C6C6F63000000000000B3
-S3250001D95000141A810000000000141A860000000100141A8C00000002000000000000000090
-S3250001D970FFFFFFFFFFFF000000000000000000000000000000000000000000000000000096
-S3250001D9900000000000000000000000000000000000000000000000000000000013880000D5
-S3250001D9B0FFFFFFFFFA203C00FA203D00FA203E00FA203F000000000000141FD70014203B7D
-S3250001D9D06932632073657475702E2E2E0A004932432325780A0000000000000B00000000BA
-S3250001D9F0000000000000000000140E4000000000000000200000000000000000000000008E
-S3250001DA10000004000000000E0000000000000000000004000000000E0000000000000000CB
-S3250001DA3041F0000000000000001407460014074C0014075100140754001407580014075B12
-S3250001DA500014075E0014076200140766001407690014076C0014076F001407720014077586
-S3250001DA70001407780014077B0014077E0014078100140784001407880014078C001407909D
-S3250001DA9000140794001407980014079C001407A0001407A4001407A8001407AC001407B087
-S3250001DAB0001407B4001407B8001407BC001407C0001407C4001407C8001407CC001407D067
-S3250001DAD0001407D4001407D8FFC24714FFC2474CFFC24798FFC247BCFFC247C4FFC247CCD9
-S3250001DAF0FFC247F0FFC24830FFC24838FFC2485CFFC2488C000000000000000000000000A3
-S3250001DB100000000000000000000000000000000000000000000000000000000000000000EE
-S3250001DB300000000000000000000000000000000000000000000000000000000000000000CE
-S3250001DB507072656D617475726520454F460A002E00626164206D61676963203078256C7591
-S3250001DB7078206E6F74206120706C616E20392065786563757461626C65210A002564002BDF
-S3250001DB9025644025382E386C7578002B25640A7374617274206174203078256C75780A0058
-S3250001DBB000000000000000000000000000000000000000000000000000000000000000004E
-S3250001DBD000000000000A000000000000000000000000000000000000000000000000000024
-S3250001DBF0000000000000000000000000000000000000000000000000090000000000000005
-S3250001DC100000000102000000030000000400000500000006000700000800000000000000C9
-S3250001DC30726573657276656420300073797374656D207265736574006D616368696E652040
-S3250001DC50636865636B00646174612061636365737300696E737472756374696F6E206163DD
-S3250001DC70636573730065787465726E616C20696E7465727275707400616C69676E6D656E24
-S3250001DC90740070726F6772616D20657863657074696F6E00666C6F6174696E672D706F6949
-S3250001DCB06E7420756E617661696C61626C650064656372656D656E74657200726573657218
-S3250001DCD0766564204100726573657276656420420073797374656D2063616C6C0074726123
-S3250001DCF06365207472617000666C6F6174696E6720706F696E742061737369737400726542
-S3250001DD10736572766564204600736F66747761726520656D756C6174696F6E0049544C4279
-S3250001DD30206D6973730044544C42206D6973730049544C42206572726F720044544C422033
-S3250001DD506572726F72004341555345005352523100504300474F4B004C52004352005845A5
-S3250001DD7052004354520052300052310052320052330052340052350052360052370052389B
-S3250001DD900052390052313000523131005231320052313300523134005231350052313600E7
-S3250001DDB052313700523138005231390052323000523231005232320052323300523234008D
-S3250001DDD0523235005232360052323700523238005232390052333000523331007365746866
-S3250001DDF0766563006F7574206F6620696E746572727570742068616E646C6572730025736B
-S3250001DE1009252E386C757809257309252E386C75780A00657863657074696F6E2F696E741D
-S3250001DE30657272757074202325780A00657863657074696F6E2025730A005E5020746F20DD
-S3250001DE5072657365740A00005573696E6720666C61736820636F6E66696775726174696F20
-S3250001DE706E0A000A002573256400747970653D00706F72743D006972713D006D656D3D00E2
-S3250001DE9073697A653D0065613D00000000000000676574636C75737420402025640A00678B
-S3250001DEB06574636C75737420256420696E2063616368650A00676574636C75737420616439
-S3250001DED064722025640A0063616E2774207365656B20626C6F636B0A0063616E2774207279
-S3250001DEF065616420626C6F636B0A00676574636C75737420256420726561640A0066617497
-S3250001DF1077616C6B2025640A006765746661740066617477616C6B202564202D3E20256446
-S3250001DF300A0066696C65616464722025382E38732025640A0066696C656164647220256498
-S3250001DF50202D3E2025640A0066696C6561646472202564202D3E2025640A0077616C6B6932
-S3250001DF706E67206E6F6E2D6469726563746F7279210A00636F6D706172696E6720746F203A
-S3250001DF9025382E38732E25332E33730A0025382E38732E25332E33732069732061204C4116
-S3250001DFB042454C0A0063616E2774207265616420626F6F7420626C6F636B0A006E6F74206A
-S3250001DFD0444F530A006E6F20646F732066696C652073797374656D0A006D616769633A200D
-S3250001DFF0307825322E327820307825322E327820307825322E32780A0076657273696F6E35
-S3250001E0103A202225382E3873220A007365637473697A653A2025640A00616C6C6F637369CD
-S3250001E0307A653A2025640A006E72657372763A2025640A006E666174733A2025640A0072F5
-S3250001E0506F6F7473697A653A2025640A00766F6C73697A653A2025640A006D656469616452
-S3250001E0706573633A20307825322E32780A0066617473697A653A2025640A0074726B736903
-S3250001E0907A653A2025640A006E68656164733A2025640A006E68696464656E3A2025640A76
-S3250001E0B000626967766F6C73697A653A2025640A0064726976656E6F3A2025640A00726563
-S3250001E0D0736572766564303A20307825322E32780A00626F6F747369673A20307825322EB7
-S3250001E0F032780A00766F6C69643A20307825382E38780A006C6162656C3A20222531312EBF
-S3250001E110313173220A006E616D6520636F6D706F6E656E7420746F6F206C6F6E670A0065A2
-S3250001E13072726F722077616C6B696E6720746F2025730A002573206E6F7420666F756E64EC
-S3250001E1500A00666F756E642025382E38732E25332E3373206174747220307825757820738A
-S3250001E17074617274203078256C7578206C656E2025640A00626164206D6167696320307865
-S3250001E190256C7578206E6F74206120706C616E20392065786563757461626C65210A002B3C
-S3250001E1B02564002B2564002B25640A7374617274206174203078256C75780A002E006E61DD
-S3250001E1D06D652069732025382E38732025332E33730A0000000000002E007A71733A206E5A
-S3250001E1F06F7420706F77657250432065786563757461626C650A0074657874007A71733A9C
-S3250001E21020666F726D6174206572726F720A0064617461007A71733A20666F726D617420EF
-S3250001E2306572726F720A000A73717565657A6564206B65726E656C3A20636865636B737542
-S3250001E2506D206572726F723A2025382E386C7578206E6565642025382E386C75780A007503
-S3250001E2706E7061636B2025732025382E386C757820256C75643A00202A2A73697A6520650E
-S3250001E29072726F720A000A007A71733A20636F72727570742073717565657A65642064615C
-S3250001E2B074612073747265616D0A00205425640025642025382E386C75782025382E386CAB
-S3250001E2D075780A0000000000666C6173683A2062616420636865636B73756D0A00666C61F1
-S3250001E2F073683A20666C617368206E6F742070726573656E74206F72206E6F7420656E616C
-S3250001E310626C65640A00636F6E66202325382E386C75783A20232578202325362E366C7543
-S3250001E330780A00666C6173683A20666F756E6420636F6E6669672025382E386C75782825A1
-S3250001E35064293A0A25730A00666C6173683A206E6F20636F6E6669670A00666C6173682020
-S3250001E370636F6E6669672025382E386C7578282564293A0A25730A00666C6173683A207339
-S3250001E390717565657A656420706F7765727063206B65726E656C20696E7374616C6C6564D2
-S3250001E3B00A00666C6173683A20756E73717565657A656420706F7765727063206B65726E9B
-S3250001E3D0656C20696E7374616C6C65640A00666C6173683A206E6F20706F776572706320E6
-S3250001E3F06B65726E656C20696E20466C6173680A00746578743A2025382E386C7578203CDF
-S3250001E4102D2025382E386C7578205B256C645D0A00646174613A2025382E386C7578203C39
-S3250001E4302D2025382E386C7578205B256C645D0A00656E7472793D3078256C75780A0000E6
-S3250001E450907070F0F0F07000F0888888F8707070E0E0E0E0E09070F070F870F0F870F0882D
-S3250001E470000000000000000000000000000000000000000000000000000000000000000085
-S3250001E490000000000000000000000000000000000000000000000000000000000000000065
-S3250001E4B000000000000000000000000000000000000000000000000000000000000000E065
-S3250001E4D0D0808080808088008888C888808888889090909090D0808080808080808888881D
-S3250001E4F000000000080000000C3000000000000600000000000000000000000000000000BB
-S3250001E5100000000000000000000000000000000000000000000000000000003CC03C0000AC
-S3250001E5300000600006001E00601818607800000000000000000000000000001C18380090DC
-S3250001E550B06060E0E0E0F800F088A888808080809090909090B060E0808060E080808888E4
-S3250001E570001824283E70701818180000000000063C183C3C1C3E3C7E3C3C00000200403CDE
-S3250001E5903C187C1E787E7E1E663C7C666066623C7C3C7C3C7E6266C266667E30C00C10002E
-S3250001E5B008006000060030006018186018000000000000001000000000000030180C0090AA
-S3250001E5D0901010808080881888F8A888E0807070E0E0E0E0E090108070E01080E098F08814
-S3250001E5F0001824286ADAD818181810000000000C663866662C3E667E6666000006006066D0
-S3250001E610421866326C606032661818646066722466246666186262DA62620630600C380093
-S3250001E63010006000060030006000006018000000000000003000000000000030180C00E0E1
-S3250001E65000E0E0F0F0F000188888985080880808201C1C1C1C00E0F00080E0F08088888823
-S3250001E6700018242868DAD808300C54180000000C665806062C206002666618180CFE300695
-S3250001E6909E2C6660666060606618186C6066726666666660186262DA36660C30600C2800F9
-S3250001E6B0103C6C3C3E3C7E3E6C78786618D46C3C6C3E763C7E6666C266667E1818180000C9
-S3250001E6D04418000018241C24F08888208070F0F020202020201C243E1CF8241C8070887001
-S3250001E6F00018247C78745008300C381800000018661806064C2060067666181818FE180CC1
-S3250001E710B62C66606660606066181868607E5A6666666470186266DA34340C30300C6C0072
-S3250001E73018667666666630667618186418FE766676663666306662DA626206081810323C58
-S3250001E75044247C7C2434204200000000000000002020202020222408220024200000000034
-S3250001E770001800283C287610300CEE7E00FE001866180C184C3C7C0C3C3E000030000C181A
-S3250001E790B62C7C60667C7C6E7E181878605A5A666466783C186234DA18341830300C44001E
-S3250001E7B018066660666630666618186818D6666666663860306662DA34620C30180C5A209E
-S3250001E7D044241010242C20420E3E103E3E3C1C3E3C1C1C1C1C3E1C083E2224180E0E0E0E98
-S3250001E7F00008007C1E5CDC00300C387E00FE0030661818067E0666186E06000018001818AE
-S3250001E810B67E6660666060666618186C605A4E6678666C0E1862346C2C183030180C44006D
-S3250001E830003E6660667E30666618187818D666666666303C306634DA1834180818104C3887
-S3250001E8503C18101018241C4211081008202222080000000000220408223618041111111110
-S3250001E8700000002816B6CC00300C541800000030661830067E066618660600000CFE30008D
-S3250001E8909A466660666060666618186C605A4E66606666061862346C6C183030180C00006B
-S3250001E8B000666660666030666618186C18D66666666630063066346C2C34301818180020CD
-S3250001E8D000091010000E094210081008202222080F06060F0A09041E002A0E3810101010F4
-S3250001E8F00018002856B6CC00300C10181800186066187E660C6666306666181806FE601813
-S3250001E910404666326C60603666181866605A4624602466661834186C461860300C0C00001A
-S3250001E930006E66666E66306E6618186618D66666666E3066306E186C46186030180C003C84
-S3250001E950080909091F110AFF0E081008382C2208080209010A0A0911092209070E0E0E0ED3
-S3250001E970001800287C1C760018180000180018603C7E7E3C0C3C3C303C3C18180200401848
-S3250001E9903E467C1E787E601E663C18667E42463C603C663C1818186C66187E300C0C000036
-S3250001E9B000367C3C363C7C36667E18667ED6663C7C367C3C1E36186C66187E30180C00083C
-S3250001E9D0080F060604110C1801081008202222080E0202030A0C0D1E0D220E080101010198
-S3250001E9F0000000001000000018180000080000C000000000000000000000000800000000F0
-S3250001EA1000000000000000000000180000000000000C00000000000000000030060C00FE7B
-S3250001EA300000000000000006000018000000000060060000000000000010001C18380008B7
-S3250001EA5008090606040E0A1811081F0820221C3E080204010F0A0B110B22090811111111AC
-S3250001EA7000000000000000000C300000080000C00000000000000000000000080000000073
-S3250001EA900000000000000000000070000000000000060000000000000000003C063C00006B
-S3250001EAB0000000000000006600001800000000006006000000000000003000000000000823
-S3250001EAD00F090909040309000E000000000000000F0F0F0F0209091E09000F070E0E0E0E12
-S3250001EAF00000000000000000000000001000000000000000000000000000001000000000DF
-S3250001EB100000000000000000000000000000000000000000000000000000000000000000DE
-S3250001EB30000000000000003C00007000000000006006000000000000006000000000000F3D
-S3250001EB50636F6E736F6C65006C63640073637265656E006C63640062617564005E70002536
-S3250001EB70735B64656661756C743D3D25735D3A200025733A20000A006C696E6520746F6FEC
-S3250001EB90206C6F6E670A0070616E69633A20000A0000000000000000001406200014062B96
-S3250001EBB000140638001406460014065200140665001406780014068200140694001406AFFC
-S3250001EBD0001406BB001406C6001406D1001406DD001406E8001406FE001407090014071C12
-S3250001EBF000140726001407300014073B000000000000000E000800000008000E00080000E8
-S3250001EC100010000E000800000018000E000800000020000E000800000028000E0008000015
-S3250001EC300030000E000800000038000E000800000040000E000800000048000E0008000075
-S3250001EC500050000E000800000058000E000800000060000E000800000068000E00080000D5
-S3250001EC700070000E000800000078000E000800000080000E000800000088000E0008000035
-S3250001EC900090000E000800000098000E0008000000A0000E0008000000A8000E0008000095
-S3250001ECB000B0000E0008000000B8000E0008000000C0000E0008000000C8000E00080000F5
-S3250001ECD000D0000E0008000000D8000E0008000000E0000E0008000000E8000E0008000055
-S3250001ECF000F0000E0008000000F8000E0008000001000000000800000108020B00080000C2
-S3250001ED1001100206000800000118020B000800000120010C000800000128020B0008000019
-S3250001ED300130020B0008000001380207000800000140010D000800000148010D0008000076
-S3250001ED500150030A000800000158040A000800000160090E000800000168060800080000C8
-S3250001ED700170090B000800000178010D000800000180020B000800000188020B000800002C
-S3250001ED900190020B000800000198020B0008000001A0020B0008000001A8020B0008000094
-S3250001EDB001B0020B0008000001B8020B0008000001C0020B0008000001C8020B00080000F4
-S3250001EDD001D0040B0008000001D8040E0008000001E0020B0008000001E8040A000800004C
-S3250001EDF001F0020B0008000001F8020B000800000200020B000800000208020B00080000B2
-S3250001EE100210020B000800000218020B000800000220020B000800000228020B000800000F
-S3250001EE300230020B000800000238020B000800000240020B000800000248020B000800006F
-S3250001EE500250020D000800000258020B000800000260020B000800000268020B00080000CD
-S3250001EE700270020B000800000278020B000800000280020B000800000288020D000800002D
-S3250001EE900290020B000800000298020B0008000002A0020B0008000002A8020B000800008F
-S3250001EEB002B0020B0008000002B8020B0008000002C0020B0008000002C8020B00080000EF
-S3250001EED002D0020B0008000002D8010D0008000002E0010D0008000002E8010D000800004C
-S3250001EEF002F002080008000002F80B0C0008000003000207000800000308040B00080000A8
-S3250001EF100310010B000800000318040B000800000320010B000800000328040B0008000008
-S3250001EF300330010B000800000338040E000800000340010B000800000348010B0008000068
-S3250001EF500350010E000800000358010B000800000360010B000800000368040B00080000C8
-S3250001EF700370040B000800000378040B000800000380040E000800000388040E000800001C
-S3250001EF900390040B000800000398040B0008000003A0020B0008000003A8040B0008000084
-S3250001EFB003B0040B0008000003B8040B0008000003C0040B0008000003C8040E00080000DF
-S3250001EFD003D0040B0008000003D8010C0008000003E0010C0008000003E8010C0008000048
-S3250001EFF003F005080008000003F8000E000800000400000E000800000000000000000000C7
-S3250001F010534343005343433200657468657225643A2025733A20706F7274203078256C7575
-S3250001F0305820697271202564002061646472203078256C7558002073697A65203078256C37
-S3250001F0507558003A002025322E327558000A00657468657225643A207478207175657565B8
-S3250001F0702066756C6C0A0000666C6173680046006574686572006500617461006864006861
-S3250001F090006175746F006C6F63616C006D616E75616C00696E6665726E6F2F696E666572E3
-S3250001F0B06E6F2E696E6900696E6665726E6F2E696E6900706C616E392F706C616E392E6901
-S3250001F0D06E6900706C616E392E696E69002100002573212564006469736B002573212564A0
-S3250001F0F0212573006469736B00696D706300257321256421257300626F6F74006469736B92
-S3250001F11000646F73006469736B00646F7320696E6974206661696C65640A00707265646132
-S3250001F130776E0A006461776E0A006F7074696F6E733D232575780A00466C61736820626FAE
-S3250001F1506F740A00626F6F7466696C650042616420626F6F7466696C652073796E74617815
-S3250001F1703A2025730A0043616E6E6F7420616363657373206465766963653A2025730A00FB
-S3250001F190426F6F7420646576696365733A00202573212564002025732125640020257321EA
-S3250001F1B02564000A00626F6F742066726F6D00706879736963616C206D656D6F727900699E
-S3250001F1D0616C6C6F63006672656500000000000045544845522E5343432325643A20736310
-S3250001F1F06365203D2030782575580A007E0040006E6F207072657365742045746865722089
-S3250001F210616464726573730A00303031303862663132393030006574686572204D41432001
-S3250001F2306164647265737300696E76616C6964204D414320616464726573730A00000000E9
-S3250001F2500A746674703A206572726F72282564293A2025730A0069702063686B73756D20D1
-S3250001F2706572726F720A0069702062616420766572732F686C656E0A007564702063686BC4
-S3250001F29073756D206572726F72206373756D202325346C7578206C656E2025640A00756400
-S3250001F2B0703A207061636B657420746F6F206269670A002573006F637465740074667470B2
-S3250001F2D06F70656E3A206572726F7220282564293A2025730A00746674706F70656E3A2021
-S3250001F2F0626C6F636B206572726F723A2025640A00626C6F636B206572726F720074667412
-S3250001F310706F70656E3A206661696C656420746F20636F6E6E65637420746F207365727605
-S3250001F33065720A0074667470726561643A20256420213D2025640A0073686F727420726540
-S3250001F3506164003F0074667470726561643A20626C6F636B206572726F723A2025642C205A
-S3250001F37065787065637465642025640A00626C6F636B206572726F7200696E76616C696435
-S3250001F3902063746C726E6F2025640A00626F6F74702074696D6564206F75740A0025732060
-S3250001F3B0002825642E25642E25642E2564212564293A2025730A00626164206D6167696349
-S3250001F3D0206E756D626572006C6F61644025382E386C75783A20002564002B2564006F6B00
-S3250001F3F0002B25643D25640A00656E7472793A203078256C75780A000000000000141A6820
-S3250001F41000000008FFC27AE40000000000000000000000000000000000141A6E0000000012
-S3250001F43000000000000000000000000200141A7000000004FFC26068000000000000000088
-S3250001F45000000000000000000000000000141A7600000000000000000000000300141A7848
-S3250001F470000000130000000000000000000000000000000000141A7C00141A7F000000000B
-S3250001F4900000000000000000FFFFFFFF000000000000000000000000000000000000000059
-S3250001F4B0000000000000000000000000000000000000000000000000496E6665726E6F2044
-S3250001F4D0626F6F7473747261700A005056523A20004D5043363031004D5043363033004D9E
-S3250001F4F05043363034004D504336303365004D5043363033652D7637004D5043387878002A
-S3250001F510506F77657250432076657273696F6E20232578002C207265766973696F6E202330
-S3250001F530256C75780A00494D4D523A20004D50433836302F383231004D5043383233004D8B
-S3250001F55050433832334100547970652023256C7578002C206D61736B2023256C75780A00FD
-S3250001F5706F7074696F6E733A2023256C75780A00626373723A2025382E386C75780A0050E9
-S3250001F5904C505243523D25382E386C757820534343523D25382E386C75780A00256C756460
-S3250001F5B0204D487A2073797374656D0A000A004252303D25382E386C7578204F52303D25BC
-S3250001F5D0382E386C75780A004D505450523D25382E386C75780A006574686572303D7479AB
-S3250001F5F070653D53434320706F72743D312065613D3030313065633030303035310D0A7657
-S3250001F610676173697A653D3634307834383078380D0A6B65726E656C70657263656E743DEF
-S3250001F63034300D0A636F6E736F6C653D300D0A626175643D393630300D0A006574686572EA
-S3250001F650303D747970653D53434320706F72743D322065613D303031306563303030303559
-S3250001F670310D0A76676173697A653D3634307834383078380D0A6B65726E656C7065726355
-S3250001F690656E743D34300D0A636F6E736F6C653D300D0A626175643D393630300D0A0055C9
-S3250001F6B073696E672064656661756C7420636F6E66696775726174696F6E0A00414D4432D7
-S3250001F6D039463078300053434300454100693263206661696C65640A00656570726F6D3A0E
-S3250001F6F00A002025322E3275785B25635D000A00CFFFCC240FFFCC040CAFCC0403AFCC082E
-S3250001F7103FBFCC27FFFFCC25FFFFCC25FFFFCC25CFFFCC240FFFCC040CAFCC8403AFCC8867
-S3250001F7303FBFCC27FFFFCC25FFFFCC25FFFFCC25FFFFCC25FFFFCC25FFFFCC25FFFFCC2538
-S3250001F750FFFFCC25FFFFCC25FFFFCC25FFFFCC25CFFFCC240FFFCC040CFFCC0403FFCC0091
-S3250001F7703FFFCC27FFFFCC25FFFFCC25FFFFCC25CFFFCC240FFFCC040CFFCC8403FFCC842B
-S3250001F7900CFFCC0033FFCC27FFFFCC25FFFFCC25FFFFCC25FFFFCC25FFFFCC25FFFFCC25BC
-S3250001F7B0FFFFCC25FFFFCC25FFFFCC25FFFFCC25C0FFCC2403FFCC240FFFCC240FFFCC24D9
-S3250001F7D03FFFCC27FFFFCC25FFFFCC25FFFFCC25FFFFCC25FFFFCC25FFFFCC25FFFFCC2558
-S3150001F7F0FFFFCC25FFFFCC25FFFFCC25FFFFCC2546
-S700000100FE
--- a/os/boot/rpcg/gbitbltclip.c
+++ /dev/null
@@ -1,52 +1,0 @@
-#include <u.h>
-#include <libc.h>
-#include <libg.h>
-#include <gnot.h>
-
-void
-gbitbltclip(void *vp)
-{
-	int dx, dy;
-	int i;
-	struct{
-		GBitmap *dm;
-		Point p;
-		GBitmap *sm;
-		Rectangle r;
-		Fcode f;
-	}*bp;
-
-	bp = vp;
-	dx = Dx(bp->r);
-	dy = Dy(bp->r);
-	if(bp->p.x < bp->dm->clipr.min.x){
-		i = bp->dm->clipr.min.x-bp->p.x;
-		bp->r.min.x += i;
-		bp->p.x += i;
-		dx -= i;
-	}
-	if(bp->p.y < bp->dm->clipr.min.y){
-		i = bp->dm->clipr.min.y-bp->p.y;
-		bp->r.min.y += i;
-		bp->p.y += i;
-		dy -= i;
-	}
-	if(bp->p.x+dx > bp->dm->clipr.max.x)
-		bp->r.max.x -= bp->p.x+dx-bp->dm->clipr.max.x;
-	if(bp->p.y+dy > bp->dm->clipr.max.y)
-		bp->r.max.y -= bp->p.y+dy-bp->dm->clipr.max.y;
-	if(bp->r.min.x < bp->sm->clipr.min.x){
-		i = bp->sm->clipr.min.x-bp->r.min.x;
-		bp->p.x += i;
-		bp->r.min.x += i;
-	}
-	if(bp->r.min.y < bp->sm->clipr.min.y){
-		i = bp->sm->clipr.min.y-bp->r.min.y;
-		bp->p.y += i;
-		bp->r.min.y += i;
-	}
-	if(bp->r.max.x > bp->sm->clipr.max.x)
-		bp->r.max.x = bp->sm->clipr.max.x;
-	if(bp->r.max.y > bp->sm->clipr.max.y)
-		bp->r.max.y = bp->sm->clipr.max.y;
-}
--- a/os/boot/rpcg/gnot.h
+++ /dev/null
@@ -1,71 +1,0 @@
-
-extern void	*bbmalloc(int);
-extern void	bbfree(void *, int);
-extern int	bbonstack(void);
-extern void	bbexec(void(*)(void), int, int);
-
-/*
- * Graphics types
- */
-
-typedef	struct	GBitmap		GBitmap;
-typedef struct	GFont		GFont;
-typedef struct	GSubfont	GSubfont;
-typedef struct	GCacheinfo	GCacheinfo;
-
-struct	GBitmap
-{
-	ulong	*base;		/* pointer to start of data */
-	long	zero;		/* base+zero=&word containing (0,0) */
-	ulong	width;		/* width in 32 bit words of total data area */
-	int	ldepth;		/* log base 2 of number of bits per pixel */
-	Rectangle r;		/* rectangle in data area, local coords */
-	Rectangle clipr;	/* clipping region */
-	GBitmap	*cache;		/* zero; distinguishes bitmap from layer */
-};
-
-
-/*
- * GFont etc. are not used in the library, only in devbit.c.
- * GSubfont is only barely used.
- */
-struct	GSubfont
-{
-	short	n;		/* number of chars in font */
-	char	height;		/* height of bitmap */
-	char	ascent;		/* top of bitmap to baseline */
-	Fontchar *info;		/* n+1 character descriptors */
-	GBitmap	*bits;		/* where the characters are */
-};
-struct GCacheinfo
-{
-	ulong		xright;	/* right edge of bits */
-	Fontchar;
-};
-
-struct GFont
-{
-	uchar		height;	/* max height of bitmap, interline spacing */
-	char		ascent;	/* top of bitmap to baseline */
-	char		width;	/* widest so far; used in caching only */	
-	char		ldepth;	/* of images */
-	short		id;	/* of font */
-	int		ncache;	/* number of entries in cache */
-	GCacheinfo	*cache;	/* cached characters */
-	GBitmap		*b;	/* cached images */
-};
-
-extern ulong	 *gaddr(GBitmap*, Point);
-extern uchar	 *gbaddr(GBitmap*, Point);
-extern void	 gbitblt(GBitmap*, Point, GBitmap*, Rectangle, Fcode);
-extern void	 gbitbltclip(void*);
-extern void	 gtexture(GBitmap*, Rectangle, GBitmap*, Fcode);
-extern Point	 gsubfstrsize(GSubfont*, char*);
-extern int	 gsubfstrwidth(GSubfont*, char*);
-extern Point	 gsubfstring(GBitmap*, Point, GSubfont*, char*, Fcode);
-extern Point	 gbitbltstring(GBitmap*, Point, GSubfont*, char*, Fcode);
-extern void	 gsegment(GBitmap*, Point, Point, int, Fcode);
-extern void	 gpoint(GBitmap*, Point, int, Fcode);
-extern void	 gflushcpucache(void);
-extern GBitmap*	 gballoc(Rectangle, int);
-extern void	 gbfree(GBitmap*);
--- a/os/boot/rpcg/i2c.c
+++ /dev/null
@@ -1,360 +1,0 @@
-#include "boot.h"
-
-/*
- * basic read/write interface to mpc8xx I2C bus (master mode)
- */
-
-typedef struct I2C I2C;
-
-struct I2C {
-	uchar	i2mod;
-	uchar	rsv12a[3];
-	uchar	i2add;
-	uchar	rsv12b[3];
-	uchar	i2brg;
-	uchar	rsv12c[3];
-	uchar	i2com;
-	uchar	rsv12d[3];
-	uchar	i2cer;
-	uchar	rsv12e[3];
-	uchar	i2cmr;
-};
-
-enum {
-	/* i2c-specific BD flags */
-	RxeOV=		1<<1,	/* overrun */
-	TxS=			1<<10,	/* transmit start condition */
-	TxeNAK=		1<<2,	/* last transmitted byte not acknowledged */
-	TxeUN=		1<<1,	/* underflow */
-	TxeCL=		1<<0,	/* collision */
-	TxERR=		(TxeNAK|TxeUN|TxeCL),
-
-	/* i2cmod */
-	REVD=	1<<5,	/* =1, LSB first */
-	GCD=	1<<4,	/* =1, general call address disabled */
-	FLT=		1<<3,	/* =0, not filtered; =1, filtered */
-	PDIV=	3<<1,	/* predivisor field */
-	EN=		1<<0,	/* enable */
-
-	/* i2com */
-	STR=		1<<7,	/* start transmit */
-	I2CM=	1<<0,	/* master */
-	I2CS=	0<<0,	/* slave */
-
-	/* i2cer */
-	TXE =	1<<4,
-	BSY =	1<<2,
-	TXB =	1<<1,
-	RXB =	1<<0,
-
-	/* port B bits */
-	I2CSDA =	IBIT(27),
-	I2CSCL = IBIT(26),
-
-	Rbit =	1<<0,	/* bit in address byte denoting read */
-
-	/* maximum I2C I/O (can change) */
-	MaxIO=	128,
-	Bufsize =	MaxIO+4,	/* extra space for address/clock bytes and alignment */
-	Freq =	100000,
-	I2CTimeout = 250,	/* msec */
-};
-
-/* data cache needn't be flushed if buffers allocated in uncached INTMEM */
-#define	DCFLUSH(a,n)
-
-/*
- * I2C software structures
- */
-
-struct Ctlr {
-	Lock;
-	QLock	io;
-	int	init;
-	I2C*	i2c;
-	IOCparam*	sp;
-
-	BD*	rd;
-	BD*	td;
-	int	phase;
-	int	timeout;
-	char*	addr;
-	char*	txbuf;
-	char*	rxbuf;
-};
-typedef struct Ctlr Ctlr;
-
-static	Ctlr	i2ctlr[1];
-extern	int	predawn;
-
-static	void	interrupt(Ureg*, void*);
-
-static void
-enable(void)
-{
-	I2C *i2c;
-
-	i2c = i2ctlr->i2c;
-	i2c->i2cer = ~0;	/* clear events */
-	eieio();
-	i2c->i2mod |= EN;
-	eieio();
-	i2c->i2cmr = TXE|BSY|TXB|RXB;	/* enable all interrupts */
-	eieio();
-}
-
-static void
-disable(void)
-{
-	I2C *i2c;
-
-	i2c = i2ctlr->i2c;
-	i2c->i2cmr = 0;	/* mask all interrupts */
-	i2c->i2mod &= ~EN;
-}
-
-/*
- * called by the reset routine of any driver using the I2C
- */
-void
-i2csetup(void)
-{
-	IMM *io;
-	I2C *i2c;
-	IOCparam *sp;
-	Ctlr *ctlr;
-	long f, e, emin;
-	int p, d, dmax;
-
-	ctlr = i2ctlr;
-	if(ctlr->init)
-		return;
-	print("i2c setup...\n");
-	ctlr->init = 1;
-	i2c = KADDR(INTMEM+0x860);
-	ctlr->i2c = i2c;
-	sp = KADDR(INTMEM+0x3c80);
-	ctlr->sp = sp;
-	disable();
-
-	if(ctlr->txbuf == nil){
-		ctlr->txbuf = ialloc(Bufsize, 2);
-		ctlr->addr = ctlr->txbuf+Bufsize;
-	}
-	if(ctlr->rxbuf == nil)
-		ctlr->rxbuf = ialloc(Bufsize, 2);
-	if(ctlr->rd == nil){
-		ctlr->rd = bdalloc(1);
-		ctlr->rd->addr = PADDR(ctlr->rxbuf);
-		ctlr->rd->length = 0;
-		ctlr->rd->status = BDWrap;
-	}
-	if(ctlr->td == nil){
-		ctlr->td = bdalloc(2);
-		ctlr->td->addr = PADDR(ctlr->txbuf);
-		ctlr->td->length = 0;
-		ctlr->td->status = BDWrap|BDLast;
-	}
-
-	/* select port pins */
-	io = ioplock();
-	io->pbdir |= I2CSDA | I2CSCL;
-	io->pbodr |= I2CSDA | I2CSCL;
-	io->pbpar |= I2CSDA | I2CSCL;
-	iopunlock();
-
-	/* explicitly initialise parameters, because InitRxTx can't be used (see i2c/spi relocation errata) */
-	sp = ctlr->sp;
-	sp->rbase = PADDR(ctlr->rd);
-	sp->tbase = PADDR(ctlr->td);
-	sp->rfcr = 0x18;
-	sp->tfcr = 0x18;
-	sp->mrblr = Bufsize;
-	sp->rstate = 0;
-	sp->rptr = 0;
-	sp->rbptr = sp->rbase;
-	sp->rcnt = 0;
-	sp->tstate = 0;
-	sp->tbptr = sp->tbase;
-	sp->tptr = 0;
-	sp->tcnt = 0;
-	eieio();
-
-	i2c->i2com = I2CM;
-	i2c->i2mod = 0;	/* normal mode */
-	i2c->i2add = 0;
-
-	emin = Freq;
-	dmax = (m->cpuhz/Freq)/2-3;
-	for(d=0; d < dmax; d++){
-		for(p=3; p>=0; p--){
-			f = (m->cpuhz>>(p+2))/(2*(d+3));
-			e = Freq - f;
-			if(e < 0)
-				e = -e;
-			if(e < emin){
-				emin = e;
-				i2c->i2brg = d;
-				i2c->i2mod = (i2c->i2mod&~PDIV)|((3-p)<<1); /* set PDIV */
-			}
-		}
-	}
-	//print("i2brg=%d i2mod=#%2.2ux\n", i2c->i2brg, i2c->i2mod);
-	setvec(VectorCPIC+0x10, interrupt, i2ctlr);
-}
-
-enum {
-	Idling,
-	Done,
-	Busy,
-		Sending,
-		Recving,
-};
-
-static void
-interrupt(Ureg*, void *arg)
-{
-	int events;
-	Ctlr *ctlr;
-	I2C *i2c;
-
-	ctlr = arg;
-	i2c = ctlr->i2c;
-	events = i2c->i2cer;
-	eieio();
-	i2c->i2cer = events;
-	if(events & (BSY|TXE)){
-		print("I2C#%x\n", events);
-		if(ctlr->phase != Idling){
-			ctlr->phase = Idling;
-		}
-	}else{
-		if(events & TXB){
-			//print("i2c: xmt %d %4.4ux %4.4ux\n", ctlr->phase, ctlr->td->status, ctlr->td[1].status);
-			if(ctlr->phase == Sending){
-				ctlr->phase = Done;
-			}
-		}
-		if(events & RXB){
-			//print("i2c: rcv %d %4.4ux %d\n", ctlr->phase, ctlr->rd->status, ctlr->rd->length);
-			if(ctlr->phase == Recving){
-				ctlr->phase = Done;
-			}
-		}
-	}
-}
-
-static int
-done(void *a)
-{
-	return ((Ctlr*)a)->phase < Busy;
-}
-
-static void
-i2cwait(Ctlr *ctlr)
-{
-	int i;
-
-	ctlr->timeout = 0;
-	i = 0;
-	while(!done(ctlr)){
-		if(predawn){
-			if(++i > 100){
-				ctlr->phase = Done;
-				ctlr->timeout = 1;
-				return;
-			}
-			delay(1);
-			interrupt(nil, ctlr);
-		}
-	}
-}
-
-long
-i2csend(int addr, void *buf, long n)
-{
-	Ctlr *ctlr;
-	int i, p, s;
-
-	ctlr = i2ctlr;
-	if(n > MaxIO)
-		return -1;
-	i = 1;
-	ctlr->txbuf[0] = addr & ~1;
-	if(addr & 1){
-		ctlr->txbuf[1] = addr>>8;
-		i++;
-	}
-	memmove(ctlr->txbuf+i, buf, n);
-	DCFLUSH(ctlr->txbuf, Bufsize);
-	ctlr->phase = Sending;
-	ctlr->rd->status = BDEmpty|BDWrap|BDInt;
-	ctlr->td->addr = PADDR(ctlr->txbuf);
-	ctlr->td->length = n+i;
-	ctlr->td->status = BDReady|BDWrap|BDLast|BDInt;
-	enable();
-	ctlr->i2c->i2com = STR|I2CM;
-	eieio();
-	i2cwait(ctlr);
-	disable();
-	p = ctlr->phase;
-	s = ctlr->td->status;
-	if(s & BDReady || s & TxERR || p != Done || ctlr->timeout)
-		return -1;
-	return n;
-}
-
-long
-i2crecv(int addr, void *buf, long n)
-{
-	Ctlr *ctlr;
-	int p, s, flag;
-	BD *td;
-	long nr;
-
-	ctlr = i2ctlr;
-	if(n > MaxIO)
-		return -1;
-	ctlr->txbuf[0] = addr|Rbit;
-	if(addr & 1){	/* special select sequence */
-		ctlr->addr[0] = addr &~ 1;
-		ctlr->addr[1] = addr>>8;
-	}
-	DCFLUSH(ctlr->txbuf, Bufsize);
-	DCFLUSH(ctlr->rxbuf, Bufsize);
-	ctlr->phase = Recving;
-	ctlr->rd->addr = PADDR(ctlr->rxbuf);
-	ctlr->rd->status = BDEmpty|BDWrap|BDInt;
-	flag = 0;
-	td = ctlr->td;
-	td[1].status = 0;
-	if(addr & 1){
-		/* special select sequence */
-		td->addr = PADDR(ctlr->addr);
-		td->length = 2;
-		/* td->status made BDReady below */
-		td++;
-		flag = TxS;
-	}
-	td->addr = PADDR(ctlr->txbuf);
-	td->length = n+1;
-	td->status = BDReady|BDWrap|BDLast | flag;	/* not BDInt: leave that to receive */
-	if(flag)
-		ctlr->td->status = BDReady;
-	enable();
-	ctlr->i2c->i2com = STR|I2CM;
-	eieio();
-	i2cwait(ctlr);
-	disable();
-	p = ctlr->phase;
-	s = ctlr->td->status;
-	if(flag)
-		s |= ctlr->td[1].status;
-	nr = ctlr->rd->length;
-	if(nr > n)
-		nr = n;	/* shouldn't happen */
-	if(s & TxERR || s & BDReady || p != Done || ctlr->rd->status & BDEmpty || ctlr->timeout)
-		return -1;
-	memmove(buf, ctlr->rxbuf, nr);
-	return nr;
-}
--- a/os/boot/rpcg/initfads.c
+++ /dev/null
@@ -1,187 +1,0 @@
-/*
- * Called from l.s in EPROM to set up a minimal working environment.
- * Since there is no DRAM yet, and therefore no stack, no function
- * calls may be made from sysinit0, and values can't be stored,
- * except to INTMEM.  Global values are accessed by offset from SB,
- * which has been set by l.s to point into EPROM.
- *
- * This is FADS-specific in CS assignment and access of the FADS BCSR
- * to discover memory size and speed.
- */
-
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-#include "archfads.h"
-
-#define	MB	(1024*1024)
-
-enum {
-	UPMSIZE = 64,	/* memory controller instruction RAM */
-	SPEED = 50,	/* maximum memory clock in MHz */
-	SDRAMSIZE = 4*MB,
-
-	/* mcr */
-	WriteRAM = 0<<30,
-	ReadRAM = 1<<30,
-	ExecRAM = 2<<30,
-
-	SelUPMA = 0<<23,
-	SelUPMB = 1<<23,
-
-	Once = 1<<8,
-};
-
-/*
- * mpc8bug uses the following for 60ns EDO DRAMs 32-50MHz
- */
-static ulong upma50[UPMSIZE] = {
-	0x8FFFEC24,	0xFFFEC04,	0xCFFEC04,	0xFFEC04,       
-	0xFFEC00,	0x37FFEC47,	0xFFFFFFFF,	0xFFFFFFFF,
-	0x8FFFEC24,	0xFFFEC04,	0x8FFEC04,	0xFFEC0C,
-	0x3FFEC00,	0xFFEC44,	0xFFCC08,	0xCFFCC44,
-	0xFFEC0C,	0x3FFEC00,	0xFFEC44,	0xFFCC00,
-	0x3FFFC847,	0x3FFFEC47,	0xFFFFFFFF,	0xFFFFFFFF,
-	0x8FAFCC24,	0xFAFCC04,	0xCAFCC00,	0x11BFCC47,
-	0xC0FFCC84,	0xFFFFFFFF,	0xFFFFFFFF,	0xFFFFFFFF,
-	0x8FAFCC24,	0xFAFCC04,	0xCAFCC00,	0x3AFCC4C,
-	0xCAFCC00,	0x3AFCC4C,	0xCAFCC00,	0x3AFCC4C,
-	0xCAFCC00,	0x33BFCC4F,	0xFFFFFFFF,	0xFFFFFFFF,
-	0xFFFFFFFF,	0xFFFFFFFF,	0xFFFFFFFF,	0xFFFFFFFF,
-	0xC0FFCC84,	0xFFCC04,	0x7FFCC04,	0x3FFFCC06,
-	0xFFFFCC85,	0xFFFFCC05,	0xFFFFCC05,	0xFFFFFFFF,
-	0xFFFFFFFF,	0xFFFFFFFF,	0xFFFFFFFF,	0xFFFFFFFF,
-	0x33FFCC07,	0xFFFFFFFF,	0xFFFFFFFF,	0xFFFFFFFF,
-};
-
-/*
- * the FADS manual table 3-7 suggests the following for 60ns EDO DRAMs at 20MHz
- */
-static ulong upma20[UPMSIZE] = {
-	0x8FFFCC04, 0x08FFCC00, 0x33FFCC47, ~0, ~0, ~0, ~0, ~0,
-	[0x08]	0x8FFFCC04, 0x08FFCC08, 0x08FFCC08, 0x08FFCC08, 0x08FFCC00, 0x3FFFCC47, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0,
-	[0x18]	0x8FEFCC00, 0x39BFCC47, ~0, ~0, ~0, ~0, ~0, ~0,
-	[0x20]	0x8FEFCC00, 0x09AFCC48, 0x09AFCC48, 0x08AFCC48, 0x39BFCC47, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0,
-	[0x30]	0x80FFCC84, 0x17FFCC04, 0xFFFFCC86, 0xFFFFCC05, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0,
-	[0x3C]	0x33FFCC07, ~0, ~0, ~0,
-};
-
-void
-sysinit0(int inrom)
-{
-	ulong *upm, *bcsr;
-	IMM *io;
-	int i, mb;
-
-	io = (IMM*)INTMEM;		/* running before maps, no KADDR */
-
-	/* system interface unit initialisation, FADS manual table 3-2, except as noted */
-	io->siumcr = 0x01012440;
-	io->sypcr = 0xFFFFFF88;
-	io->tbscrk = KEEP_ALIVE_KEY;
-	io->tbscr = 0xC3;	/* time base enabled */
-	io->rtcsck = KEEP_ALIVE_KEY;
-	io->rtcsc = 0xC1;	/* don't FRZ, real-time clock enabled */
-	io->rtcsck = ~KEEP_ALIVE_KEY;
-	io->piscrk = KEEP_ALIVE_KEY;
-	io->piscr = 0x82;
-
-	io->memc[BCSRCS].option = 0xFFFF8110;	/* 32k block, all types access, CS early negate, 1 ws */
-	io->memc[BCSRCS].base = BCSRMEM | 1;	/* base, 32-bit port, no parity, GPCM */
-
-	io->memc[BOOTCS].base = FLASHMEM | 1;
-	io->memc[BOOTCS].option = 0xFF800D54;
-
-	if(!inrom)
-		return;	/* can't initialise DRAM controller from DRAM */
-
-	bcsr = (ulong*)BCSRMEM;
-//	bcsr[1] &= ~DisableDRAM;
-	/* could check DRAM speed here; assume 60ns */
-	switch((bcsr[2]>>23)&3){
-	default:	return;	/* can't happen; for the compiler */
-	case 0:	mb = 4; break;
-	case 1:	mb = 32; break;
-	case 2:	mb = 16; break;
-	case 3:	mb = 8; break;
-	}
-
-	upm = upma50;
-	for(i=0; i<UPMSIZE; i++){
-		io->mdr = upm[i];
-		io->mcr = WriteRAM | SelUPMA | i;
-	}
-	io->mptpr = 0x0400;
-	if(SPEED >= 32)
-		io->mamr = (0x9C<<24) | 0xA21114;	/* 50MHz BRGCLK; FADS manual says 0xC0, mpc8bug sets 0x9C */
-	else if(SPEED >= 20)
-		io->mamr = (0x60<<24) | 0xA21114;	/* 25MHz BRGCLK */
-	else
-		io->mamr = (0x40<<24) | 0xA21114;	/* 16.67MHz BRGCLK */
-	io->memc[DRAM1].option = ~((mb<<20)-1)|0x0800;	/* address mask, SAM=1 */
-	io->memc[DRAM1].base = 0 | 0x81;	/* base at 0, 32-bit port size, no parity, UPMA */
-}
-
-/*
- * the FADS manual table 3-9's suggestion for MB811171622A-100 32+MHz-50MHz
- */
-static ulong upmb50[UPMSIZE] = {
-	[0x00]	0x1F07FC04, 0xEEAEFC04, 0x11ADFC04, 0xEFBBBC00, 0x1FF77C47,
-	[0x05]	0x1FF77C34, 0xEFEABC34, 0x1FB57C35,
-	[0x08]	0x1F07FC04, 0xEEAEFC04, 0x10ADFC04, 0xF0AFFC00, 0xF0AFFC00, 0xF1AFFC00, 0xEFBBBC00, 0x1FF77C47, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0,
-	[0x18]	0x1F27FC04, 0xEEAEBC00, 0x01B93C04, 0x1FF77C47, ~0, ~0, ~0, ~0,
-	[0x20]	0x1F07FC04, 0xEEAEBC00, 0x10AD7C00, 0xF0AFFC00, 0xF0AFFC00, 0xE1BBBC04, 0x1FF77C47, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0,
-	[0x30] 	0x1FF5FC84, 0xFFFFFC04, 0xFFFFFC04, 0xFFFFFC04, 0xFFFFFC84, 0xFFFFFC07, ~0, ~0, ~0, ~0, ~0, ~0,
-	[0x3C]	0x7FFFFC07, ~0, ~0, ~0,
-};
-
-/*
- * the FADS manual table 3-8's suggestion for MB811171622A-100 up to 32MHz
- */
-static	ulong	upmb32[UPMSIZE] = {
-	[0x00]	0x126CC04, 0xFB98C00, 0x1FF74C45, ~0, ~0,
-	[0x05]	0x1FE77C34, 0xEFAABC34, 0x1FA57C35,
-	[0x08]	0x0026FC04, 0x10ADFC00, 0xF0AFFC00, 0xF1AFFC00, 0xEFBBBC00, 0x1FF77C45, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0,
-	[0x18]	0x0E26BC04, 0x01B93C00, 0x1FF77C45, ~0, ~0, ~0, ~0, ~0,
-	[0x20]	0x0E26BC00, 0x10AD7C00, 0xF0AFFC00, 0xF0AFFC00, 0xE1BBBC04, 0x1FF77C45, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0,
-	[0x30]	0x1FF5FC84, 0xFFFFFC04, 0xFFFFFC84, 0xFFFFFC05, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0,
-	[0x3C]	0x7FFFFC07, ~0, ~0, ~0,
-};
-
-/*
- * optionally called by archfads.c:/^archinit to initialise access to SDRAM
- */
-void
-sdraminit(ulong base)
-{
-	ulong *upm;
-	IMM *io;
-	int i;
-
-	io = (IMM*)INTMEM;		/* running before maps, no KADDR */
-	if(SPEED > 32)
-		upm = upmb50;
-	else
-		upm = upmb32;
-	for(i=0; i<UPMSIZE; i++){
-		io->mdr = upm[i];
-		io->mcr = WriteRAM | SelUPMB | i;
-	}
-	io->memc[SDRAM].option = ~(SDRAMSIZE-1)|0x0A00;	/* address mask, SAM=1, G5LS=1 */
-	io->memc[SDRAM].base = base | 0xC1;
-	if(SPEED > 32){
-		io->mbmr = 0xD0802114;	/* 50MHz BRGCLK */
-		io->mar = 0x88;
-	}else{
-		io->mbmr = 0x80802114;	/* 32MHz BRGCLK */
-		io->mar = 0x48;
-	}
-	io->mcr = ExecRAM | SelUPMB | (SDRAM<<13) | Once | 5;	/* run MRS command in locations 5-8 of UPMB */
-	io->mbmr = (io->mbmr & ~0xF) | 8;
-	io->mcr = ExecRAM | SelUPMB | (SDRAM<<13) | Once | 0x30;	/* run refresh sequence */
-	io->mbmr = (io->mbmr & ~0xF) | 4;	/* 4-beat refresh bursts */
-}
--- a/os/boot/rpcg/initpaq.c
+++ /dev/null
@@ -1,101 +1,0 @@
-/*
- * Called from l.s in EPROM to set up a minimal working environment.
- * Since there is no DRAM yet, and therefore no stack, no function
- * calls may be made from sysinit0, and values can't be stored,
- * except to INTMEM.  Global values are accessed by offset from SB,
- * which has been set by l.s to point into EPROM.
- *
- * This is PowerPAQ-specific:
- *	- assumes 8mbytes
- *	- powerpaq CS assignment
- */
-
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-#include "archpaq.h"
-
-#define	MB	(1024*1024)
-
-enum {
-	DRAMSIZE = 8*MB,
-	FLASHSIZE = 8*MB,
-
-	UPMSIZE = 64,	/* memory controller instruction RAM */
-	SPEED = 50,	/* maximum memory clock in MHz */
-
-	/* mcr */
-	WriteRAM = 0<<30,
-	ReadRAM = 1<<30,
-	ExecRAM = 2<<30,
-
-	SelUPMA = 0<<23,
-	SelUPMB = 1<<23,
-
-	Once = 1<<8,
-};
-
-/*
- * mpc8bug uses the following for 60ns EDO DRAMs 32-50MHz
- */
-static ulong upmb50[UPMSIZE] = {
-	0x8FFFEC24,	0xFFFEC04,	0xCFFEC04,	0xFFEC04,       
-	0xFFEC00,	0x37FFEC47,	0xFFFFFFFF,	0xFFFFFFFF,
-	0x8FFFEC24,	0xFFFEC04,	0x8FFEC04,	0xFFEC0C,
-	0x3FFEC00,	0xFFEC44,	0xFFCC08,	0xCFFCC44,
-	0xFFEC0C,	0x3FFEC00,	0xFFEC44,	0xFFCC00,
-	0x3FFFC847,	0x3FFFEC47,	0xFFFFFFFF,	0xFFFFFFFF,
-	0x8FAFCC24,	0xFAFCC04,	0xCAFCC00,	0x11BFCC47,
-	0xC0FFCC84,	0xFFFFFFFF,	0xFFFFFFFF,	0xFFFFFFFF,
-	0x8FAFCC24,	0xFAFCC04,	0xCAFCC00,	0x3AFCC4C,
-	0xCAFCC00,	0x3AFCC4C,	0xCAFCC00,	0x3AFCC4C,
-	0xCAFCC00,	0x33BFCC4F,	0xFFFFFFFF,	0xFFFFFFFF,
-	0xFFFFFFFF,	0xFFFFFFFF,	0xFFFFFFFF,	0xFFFFFFFF,
-	0xC0FFCC84,	0xFFCC04,	0x7FFCC04,	0x3FFFCC06,
-	0xFFFFCC85,	0xFFFFCC05,	0xFFFFCC05,	0xFFFFFFFF,
-	0xFFFFFFFF,	0xFFFFFFFF,	0xFFFFFFFF,	0xFFFFFFFF,
-	0x33FFCC07,	0xFFFFFFFF,	0xFFFFFFFF,	0xFFFFFFFF,
-};
-
-void
-sysinit0(int inrom)
-{
-	ulong *upm;
-	IMM *io;
-	int i;
-
-	io = (IMM*)INTMEM;		/* running before maps, no KADDR */
-
-	/* system interface unit initialisation, FADS manual table 3-2, except as noted */
-	io->siumcr = 0x01012440;
-	io->sypcr = 0xFFFFFF88;
-	io->tbscrk = KEEP_ALIVE_KEY;
-	io->tbscr = 0xC3;	/* time base enabled */
-	io->rtcsck = KEEP_ALIVE_KEY;
-	io->rtcsc = 0xC1;	/* don't FRZ, real-time clock enabled */
-	io->rtcsck = ~KEEP_ALIVE_KEY;
-	io->piscrk = KEEP_ALIVE_KEY;
-	io->piscr = 0x82;
-
-	io->memc[BOOTCS].base = FLASHMEM | 1;
-	io->memc[BOOTCS].option = ~(FLASHSIZE-1)|(1<<8)|(2<<4);	/* mask, BIH, 2 wait states */
-
-	if(!inrom)
-		return;	/* can't initialise DRAM controller from DRAM */
-
-	/* could check DRAM speed here; assume 60ns */
-	/* could probe DRAM for size here; assume DRAMSIZE */
-	io->mptpr = 0x400;	/* powerpaq flash has 0x1000 */
-	io->mbmr = (0xC0<<24) | 0xA21114;	/* 50MHz BRGCLK */
-	upm = upmb50;
-	for(i=0; i<UPMSIZE; i++){
-		io->mdr = upm[i];
-		io->mcr = WriteRAM | SelUPMB | i;
-	}
-	io->memc[DRAM1].option = ~(DRAMSIZE-1)|0x0800;	/* address mask, SAM=1 */
-	io->memc[DRAM1].base = 0 | 0xC1;	/* base at 0, 32-bit port size, no parity, UPMB */
-}
--- a/os/boot/rpcg/initrpcg.c
+++ /dev/null
@@ -1,91 +1,0 @@
-
-/*
- * Called from l.s in EPROM to set up a minimal working environment.
- * Since there is no DRAM yet, and therefore no stack, no function
- * calls may be made from sysinit, and values can't be stored,
- * except to INTMEM.  Global values are accessed by offset from SB,
- * which has been set by l.s to point into EPROM.
- */
-
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-#include	"archrpcg.h"
-
-#define	MB	(1024*1024)
-
-enum {
-	UPMSIZE = 64,	/* memory controller instruction RAM */
-	DRAMSIZE = 16*MB,
-	FLASHSIZE = 4*MB,
-
-	WriteRAM = 0<<30,
-	ReadRAM = 1<<30,
-	ExecRAM = 2<<30,
-
-	SelUPMA = 0<<23,
-	SelUPMB = 1<<23,
-};
-/* RPCG values for RPXLite AW */
-static	ulong	upma50[UPMSIZE] = {
-	0xCFFFCC24,	0x0FFFCC04,	0x0CAFCC04,	0x03AFCC08,       
-	0x3FBFCC27,	0xFFFFCC25,	0xFFFFCC25,	0xFFFFCC25,
-	0xCFFFCC24,	0x0FFFCC04,	0x0CAFCC84,	0x03AFCC88,
-	0x3FBFCC27,	0xFFFFCC25,	0xFFFFCC25,	0xFFFFCC25,
-	0xFFFFCC25,	0xFFFFCC25,	0xFFFFCC25,	0xFFFFCC25,
-	0xFFFFCC25,	0xFFFFCC25,	0xFFFFCC25,	0xFFFFCC25,
-	0xCFFFCC24,	0x0FFFCC04,	0x0CFFCC04,	0x03FFCC00,
-	0x3FFFCC27,	0xFFFFCC25,	0xFFFFCC25,	0xFFFFCC25,
-	0xCFFFCC24,	0x0FFFCC04,	0x0CFFCC84,	0x03FFCC84,
-	0x0CFFCC00,	0x33FFCC27,	0xFFFFCC25,	0xFFFFCC25,
-	0xFFFFCC25,	0xFFFFCC25,	0xFFFFCC25,	0xFFFFCC25,
-	0xFFFFCC25,	0xFFFFCC25,	0xFFFFCC25,	0xFFFFCC25,
-	0xC0FFCC24,	0x03FFCC24,	0x0FFFCC24,	0x0FFFCC24,
-	0x3FFFCC27,	0xFFFFCC25,	0xFFFFCC25,	0xFFFFCC25,
-	0xFFFFCC25,	0xFFFFCC25,	0xFFFFCC25,	0xFFFFCC25,
-	0xFFFFCC25,	0xFFFFCC25,	0xFFFFCC25,	0xFFFFCC25,
-};
-
-void
-sysinit0(int inrom)
-{
-	ulong *upm;
-	IMM *io;
-	int i;
-
-	io = (IMM*)INTMEM;		/* running before maps, no KADDR */
-//	io->siumcr = 0x01012440;
-//	io->sypcr = 0xFFFFFF88;
-	io->tbscrk = KEEP_ALIVE_KEY;
-	io->tbscr = 0xC3;
-	io->rtcsck = KEEP_ALIVE_KEY;
-	io->rtcsc = 0xC1;
-	io->rtcsck = ~KEEP_ALIVE_KEY;
-	io->piscrk = KEEP_ALIVE_KEY;
-	io->piscr = 0x82;
-return;
-	io->memc[BCSRCS].option = 0xFFFF8910;	/* 32k block, all types access, CSNT, CS early negate, burst inhibit, 1 ws */
-	io->memc[BCSRCS].base = BCSRMEM | 1;	/* base, 32-bit port, no parity, GPCM */
-
-//	io->memc[BOOTCS].base = FLASHMEM | 0x801; /* base, 16 bit port */
-//	io->memc[BOOTCS].option = ~(FLASHSIZE-1)|(1<<8)|(4<<4);	/* mask, BIH, 4 wait states */
-
-	if(1||!inrom)
-		return;	/* can't initialise DRAM controller from DRAM */
-
-	/* TO DO: could check DRAM size and speed now */
-
-	upm = upma50;
-	for(i=0; i<nelem(upma50); i++){
-		io->mdr = upm[i];
-		io->mcr = WriteRAM | SelUPMA | i;
-	}
-	io->mptpr = 0x0800;	/* divide by 8 */
-	io->mamr = (0x58<<24) | 0xA01430;	/* 40MHz BRGCLK */
-	io->memc[DRAM1].option = ~(DRAMSIZE-1)|0x0E00;	/* address mask, SAM=1, G5LA/S=3 */
-	io->memc[DRAM1].base = 0 | 0x81;	/* base at 0, 32-bit port size, no parity, UPMA */
-}
--- a/os/boot/rpcg/io.h
+++ /dev/null
@@ -1,463 +1,0 @@
-enum
-{
-	/* software interrupt vectors (SIU and CPM) */
-	VectorPIC= 0,	/* level 0 to level 7, assigned by software */
-		CPIClevel=	4,
-	VectorIRQ=	VectorPIC+8,	/* IRQ0 to IRQ7 */
-	VectorCPIC=	VectorIRQ+8,	/* 32 CPM interrupts: 0 (error) to 0x1F (PC15) */
-};
-
-enum
-{
-	BUSUNKNOWN = 0,
-};
-
-/*
- * Buffer Descriptors and IO Rings
- */
-
-typedef struct BD BD;
-struct BD {
-	ushort	status;
-	ushort	length;
-	ulong	addr;
-};
-
-BD*	bdalloc(int);
-void	bdfree(BD*, int);
-
-enum {
-	/* Rx BDs, bits common to all protocols */
-	BDEmpty=	1<<15,
-	BDWrap=		1<<13,
-	BDInt=		1<<12,
-	BDLast=		1<<11,
-	BDFirst=		1<<10,
-
-	/* Tx BDs */
-	BDReady=		1<<15,
-	/* BDWrap, BDInt, BDLast */
-};
-
-typedef struct Ring Ring;
-struct Ring {
-	BD*	rdr;				/* receive descriptor ring */
-	void*	rrb;				/* receive ring buffers */
-	int	rdrx;				/* index into rdr */
-	int	nrdre;			/* length of rdr */
-
-	BD*	tdr;				/* transmit descriptor ring */
-	Block**	txb;				/* corresponding transmit ring buffers */
-	int	tdrh;				/* host index into tdr */
-	int	tdri;				/* interface index into tdr */
-	int	ntdre;			/* length of tdr */
-	int	ntq;				/* pending transmit requests */
-};
-
-#define NEXT(x, l)	(((x)+1)%(l))
-#define PREV(x, l)	(((x) == 0) ? (l)-1: (x)-1)
-#define	HOWMANY(x, y)	(((x)+((y)-1))/(y))
-#define ROUNDUP(x, y)	(HOWMANY((x), (y))*(y))
-
-int	ioringinit(Ring*, int, int, int);
-
-/*
- * CPM
- */
-enum {
-	/* commands */
-	InitRxTx =	0,
-	InitRx =		1,
-	InitTx =		2,
-	EnterHunt=	3,
-	StopTx=		4,
-	GracefulStopTx = 5,
-	InitIDMA =	5,
-	RestartTx =	6,
-	CloseRxBD =	7,
-	SetGroupAddr = 8,
-	SetTimer =	8,
-	GCITimeout =	9,
-	GCIAbort =	10,
-	StopIDMA =	11,
-	StartDSP = 	12,
-	ArmIDMA =	13,
-	InitDSP =		13,
-	USBCmd =	15,
-
-	/* channel IDs */
-	SCC1ID=	0,
-	USBID=	0,
-	I2CID=	1,
-	IDMA1ID= 1,
-	SCC2ID=	4,
-	SPIID=	5,
-	IDMA2ID= 5,
-	TIMERID=	5,
-	SCC3ID=	8,
-	SMC1ID=	9,
-	DSP1ID=9,
-	SCC4ID=	12,
-	SMC2ID=	13,
-	DSP2ID=	13,
-
-	BaudEnable = 1<<16,
-
-	/* sicr */
-	CLK1 = 4,		/* SCC1,2 */
-	CLK2 = 5,
-	CLK3 = 6,
-	CLK4 = 7,
-	CLK5 = CLK1,	/* SCC3,4 */
-	CLK6 = CLK2,
-	CLK7 = CLK3,
-	CLK8 = CLK4,
-};
-
-void	cpmop(int, int, int);
-#define	ioplock()	(m->iomem)
-#define	iopunlock()
-
-/*
- * the structures below follow hardware/firmware layouts in the 8xx manuals:
- * mind the data types, offsets and alignment
- */
-
-/*
- * basic IO controller parameters (SMC and SCC)
- */
-typedef struct IOCparam IOCparam;
-struct IOCparam {
-	ushort	rbase;
-	ushort	tbase;
-	uchar	rfcr;
-	uchar	tfcr;
-	ushort	mrblr;
-	ulong	rstate;
-	ulong	rptr;
-	ushort	rbptr;
-	ushort	rcnt;
-	ulong	rtmp;
-	ulong	tstate;
-	ulong	tptr;
-	ushort	tbptr;
-	ushort	tcnt;
-	ulong	ttmp;
-};
-
-typedef struct SCCparam SCCparam;
-struct SCCparam {
-	IOCparam;
-	ulong	rcrc;
-	ulong	tcrc;
-};
-
-typedef struct SCC SCC;
-struct SCC {
-	ulong	gsmrl;
-	ulong	gsmrh;
-	ushort	psmr;
-	uchar	rsvscc0[2];
-	ushort	todr;
-	ushort	dsr;
-	ushort	scce;
-	uchar	rsvscc1[2];
-	ushort	sccm;
-	uchar	rsvscc3;
-	uchar	sccs;
-	ushort	irmode;
-	ushort	irsip;
-};
-
-typedef struct SMC SMC;
-struct SMC {
-	uchar	pad1[2];
-	ushort	smcmr;
-	uchar	pad2[2];
-	uchar	smce;
-	uchar	pad3[3];
-	uchar	smcm;
-	uchar	pad4[5];
-};
-
-typedef struct SPI SPI;
-struct SPI {
-	ushort	spmode;
-	uchar	res1[4];
-	uchar	spie;
-	uchar	res2[3];
-	uchar	spim;
-	uchar	res3[2];
-	uchar	spcom;
-	uchar	res4[10];
-};
-
-typedef struct USB USB;
-struct USB {	/* 823 only */
-	uchar	usmod;
-	uchar	usadr;
-	uchar	uscom;
-	uchar	rsvu1;
-	ushort	usep[4];
-	uchar	rsvu2[4];
-	ushort	usber;
-	uchar	rsvu3[2];
-	ushort	usbmr;
-	uchar	rsvu4;
-	uchar	usbs;
-	uchar	rsvu5[8];
-};
-
-typedef struct IMM IMM;
-struct IMM {
-	struct {	/* general SIU */
-		ulong	siumcr;
-		ulong	sypcr;
-		uchar	rsv0[0xE-0x8];
-		ushort	swsr;
-		ulong	sipend;
-		ulong	simask;
-		ulong	siel;
-		uchar	sivec;
-		uchar	padv[3];
-		ulong	tesr;
-		uchar	rsv1[0x30-0x24];
-		ulong	sdcr;
-		uchar	rsv2[0x80-0x34];
-	};
-	struct {	/* PCMCIA */
-		struct {
-			ulong	base;
-			ulong	option;
-		} pcmr[8];
-		uchar	rsv3[0xe0-0xc0];
-		ulong	pgcra;
-		ulong	pgcrb;
-		ulong	pscr;
-		uchar	rsv4[0xf0-0xec];
-		ulong	pipr;
-		uchar	rsv5[4];
-		ulong	per;
-		uchar	rsv6[4];
-	};
-	struct {	/* MEMC */
-		struct {
-			ulong	base;
-			ulong	option;
-		} memc[8];
-		uchar	rsv7a[0x24];
-		ulong	mar;
-		ulong	mcr;
-		uchar	rsv7b[4];
-		ulong	mamr;
-		ulong	mbmr;
-		ushort	mstat;
-		ushort	mptpr;
-		ulong	mdr;
-		uchar	rsv7c[0x80];
-	};
-	struct {	/* system integration timers */
-		ushort	tbscr;
-		uchar	rsv8a[2];
-		ulong	tbrefu;
-		ulong	tbrefl;
-		uchar	rsv8b[0x14];
-		ushort	rtcsc;
-		uchar	rsv8c[2];
-		ulong	rtc;
-		ulong	rtsec;
-		ulong	rtcal;
-		uchar	rsv8d[0x10];
-		ushort	piscr;
-		ushort	rsv8e;
-		ulong	pitc;
-		ulong	pitr;
-		uchar	rsv8f[0x34];
-	};
-	struct {	/* 280: clocks and resets */
-		ulong	sccr;
-		ulong	plprcr;
-		ulong	rsr;
-		uchar	rsv9[0x300-0x28c];
-	};
-	struct {	/* 300: system integration timers keys */
-		ulong	tbscrk;
-		ulong	tbrefuk;
-		ulong	tbreflk;
-		ulong	tbk;
-		uchar	rsv10a[0x10];
-		ulong	rtcsck;
-		ulong	rtck;
-		ulong	rtseck;
-		ulong	rtcalk;
-		uchar	rsv10b[0x10];
-		ulong	piscrk;
-		ulong	pitck;
-		uchar	rsv10c[0x38];
-	};
-	struct {	/* 380: clocks and resets keys */
-		ulong	sccrk;
-		ulong	plprcrk;
-		ulong	rsrk;
-		uchar	rsv11[0x800-0x38C];
-	};
-	struct {	/* 800: video controller */
-		ushort	vccr;
-		ushort	pad11a;
-		uchar	vsr;
-		uchar	pad11b;
-		uchar	vcmr;
-		uchar	pad11c;
-		ulong	vbcb;
-		ulong	pad11d;
-		ulong	vfcr0;
-		ulong	vfaa0;
-		ulong	vfba0;
-		ulong	vfcr1;
-		ulong	vfaa1;
-		ulong	vfba1;
-		uchar	rsv11a[0x840-0x828];
-	};
-	struct {	/* 840: LCD */
-		ulong	lccr;
-		ulong	lchcr;
-		ulong	lcvcr;
-		ulong	rsv11b;
-		ulong	lcfaa;
-		ulong	lcfba;
-		uchar	lcsr;
-		uchar	rsv11c[0x860-0x859];
-	};
-	struct {	/* 860: I2C */
-		uchar	i2mod;
-		uchar	rsv12a[3];
-		uchar	i2add;
-		uchar	rsv12b[3];
-		uchar	i2brg;
-		uchar	rsv12c[3];
-		uchar	i2com;
-		uchar	rsv12d[3];
-		uchar	i2cer;
-		uchar	rsv12e[3];
-		uchar	i2cmr;
-		uchar	rsv12[0x900-0x875];
-	};
-	struct {	/* 900: DMA */
-		uchar	rsv13[4];
-		ulong	sdar;
-		uchar	sdsr;
-		uchar	pad1[3];
-		uchar	sdmr;
-		uchar	pad2[3];
-		uchar	idsr1;
-		uchar	pad3[3];
-		uchar	idmr1;
-		uchar	pad4[3];
-		uchar	idsr2;
-		uchar	pad5[3];
-		uchar	idmr2;
-		uchar	pad6[0x930-0x91D];
-	};
-	struct {	/* CPM interrupt control */
-		ushort	civr;
-		uchar	pad7[0x940-0x932];
-		ulong	cicr;
-		ulong	cipr;
-		ulong	cimr;
-		ulong	cisr;
-	};
-	struct {	/* input/output port */
-		ushort	padir;
-		ushort	papar;
-		ushort	paodr;
-		ushort	padat;
-		uchar	pad8[8];
-		ushort	pcdir;
-		ushort	pcpar;
-		ushort	pcso;
-		ushort	pcdat;
-		ushort	pcint;
-		uchar	pad9[6];
-		ushort	pddir;
-		ushort	pdpar;
-		ushort	rsv14a;
-		ushort	pddat;
-		uchar	rsv14[0x980-0x978];
-	};
-	struct {	/* CPM timers */
-		ushort	tgcr;
-		uchar	rsv15a[0x990-0x982];
-		ushort	tmr1;
-		ushort	tmr2;
-		ushort	trr1;
-		ushort	trr2;
-		ushort	tcr1;
-		ushort	tcr2;
-		ushort	tcn1;
-		ushort	tcn2;
-		ushort	tmr3;
-		ushort	tmr4;
-		ushort	trr3;
-		ushort	trr4;
-		ushort	tcr3;
-		ushort	tcr4;
-		ushort	tcn3;
-		ushort	tcn4;
-		ushort	ter1;
-		ushort	ter2;
-		ushort	ter3;
-		ushort	ter4;
-		uchar	rsv15[0x9C0-0x9B8];
-	};
-	struct {	/* CPM */
-		ushort	cpcr;
-		uchar	res0[2];
-		ushort	rccr;
-		uchar	res1;
-		uchar	rmds;
-		uchar	res2a[4];
-		ushort	rctr1;
-		ushort	rctr2;
-		ushort	rctr3;
-		ushort	rctr4;
-		uchar	res2[2];
-		ushort	rter;
-		uchar	res3[2];
-		ushort	rtmr;
-		uchar	rsv16[0x9F0-0x9DC];
-	};
-	union {	/* BRG */
-		struct {
-			ulong	brgc1;
-			ulong	brgc2;
-			ulong	brgc3;
-			ulong	brgc4;
-		};
-		ulong	brgc[4];
-	};
-	uchar	skip0[0xAB2-0xA00];	/* USB, SCC, SMC, SPI: address using cpmdev(CP...)->regs */
-	struct {	/* PIP */
-		ushort	pipc;		/* not 823 */
-		ushort	ptpr;		/* not 823 */
-		ulong	pbdir;
-		ulong	pbpar;
-		uchar	pad10[2];
-		ushort	pbodr;
-		ulong	pbdat;
-		uchar	pad11[0xAE0-0xAC8];
-	};
-	struct {	/* SI */
-		ulong	simode;
-		uchar	sigmr;
-		uchar	pad12;
-		uchar	sistr;
-		uchar	sicmr;
-		uchar	pad13[4];
-		ulong	sicr;
-		ulong	sirp;
-		uchar	pad14[0xB00-0xAF4];
-	};
-	ulong	vcram[64];
-	ushort	siram[256];
-	ushort	lcdmap[256];
-};
--- a/os/boot/rpcg/ip.h
+++ /dev/null
@@ -1,98 +1,0 @@
-typedef struct Udphdr Udphdr;
-struct Udphdr
-{
-	uchar	d[6];		/* Ethernet destination */
-	uchar	s[6];		/* Ethernet source */
-	uchar	type[2];	/* Ethernet packet type */
-
-	uchar	vihl;		/* Version and header length */
-	uchar	tos;		/* Type of service */
-	uchar	length[2];	/* packet length */
-	uchar	id[2];		/* Identification */
-	uchar	frag[2];	/* Fragment information */
-
-	/* Udp pseudo ip really starts here */
-	uchar	ttl;	
-	uchar	udpproto;	/* Protocol */
-	uchar	udpplen[2];	/* Header plus data length */
-	uchar	udpsrc[4];	/* Ip source */
-	uchar	udpdst[4];	/* Ip destination */
-	uchar	udpsport[2];	/* Source port */
-	uchar	udpdport[2];	/* Destination port */
-	uchar	udplen[2];	/* data length */
-	uchar	udpcksum[2];	/* Checksum */
-};
-
-typedef struct Etherhdr Etherhdr;
-struct Etherhdr
-{
-	uchar	d[6];
-	uchar	s[6];
-	uchar	type[2];
-
-	/* Now we have the ip fields */
-	uchar	vihl;		/* Version and header length */
-	uchar	tos;		/* Type of service */
-	uchar	length[2];	/* packet length */
-	uchar	id[2];		/* Identification */
-	uchar	frag[2];	/* Fragment information */
-	uchar	ttl;		/* Time to live */
-	uchar	proto;		/* Protocol */
-	uchar	cksum[2];	/* Header checksum */
-	uchar	src[4];		/* Ip source */
-	uchar	dst[4];		/* Ip destination */
-};
-
-enum
-{
-	IP_VER		= 0x40,
-	IP_HLEN		= 0x05,			
- 	UDP_EHSIZE	= 22,
-	UDP_PHDRSIZE	= 12,
-	UDP_HDRSIZE	= 20,
-	ETHER_HDR	= 14,
-	IP_UDPPROTO	= 17,
-	ET_IP		= 0x800,
-	Bcastip		= 0xffffffff,
-	BPportsrc	= 68,
-	BPportdst	= 67,
-	TFTPport	= 69,
-	Timeout		= 5000,	/* milliseconds */
-	Bootrequest 	= 1,
-	Bootreply   	= 2,
-	Tftp_READ	= 1,
-	Tftp_WRITE	= 2,
-	Tftp_DATA	= 3,
-	Tftp_ACK	= 4,
-	Tftp_ERROR	= 5,
-	Segsize		= 512,
-	TFTPSZ		= Segsize+10,
-};
-
-typedef struct Bootp Bootp;
-struct Bootp
-{
-	uchar	op;		/* opcode */
-	uchar	htype;		/* hardware type */
-	uchar	hlen;		/* hardware address len */
-	uchar	hops;		/* hops */
-	uchar	xid[4];		/* a random number */
-	uchar	secs[2];	/* elapsed snce client started booting */
-	uchar	pad[2];
-	uchar	ciaddr[4];	/* client IP address (client tells server) */
-	uchar	yiaddr[4];	/* client IP address (server tells client) */
-	uchar	siaddr[4];	/* server IP address */
-	uchar	giaddr[4];	/* gateway IP address */
-	uchar	chaddr[16];	/* client hardware address */
-	char	sname[64];	/* server host name (optional) */
-	char	file[128];	/* boot file name */
-	char	vend[128];	/* vendor-specific goo */
-};
-
-typedef struct Netaddr Netaddr;
-struct Netaddr
-{
-	ulong	ip;
-	ushort	port;
-	char	ea[Eaddrlen];
-};
--- a/os/boot/rpcg/l.s
+++ /dev/null
@@ -1,388 +1,0 @@
-#include "mem.h"
-
-/* special instruction definitions */
-#define	BDNE	BC	0,2,
-#define	BDNZ	BC	16,0,
-#define	NOOP	OR	R0,R0,R0
-
-/*
- * common ppc special purpose registers
- */
-#define DSISR	18
-#define DAR	19	/* Data Address Register */
-#define DEC	22	/* Decrementer */
-#define SRR0	26	/* Saved Registers (exception) */
-#define SRR1	27
-#define SPRG0	272	/* Supervisor Private Registers */
-#define SPRG1	273
-#define SPRG2	274
-#define SPRG3	275
-#define TBRU	269	/* Time base Upper/Lower (Reading) */
-#define TBRL	268
-#define TBWU	285	/* Time base Upper/Lower (Writing) */
-#define TBWL	284
-#define PVR	287	/* Processor Version */
-
-/*
- * mpc82x-specific special purpose registers of interest here
- */
-#define EIE	80
-#define EID	81
-#define NRI	82
-#define IMMR	638
-#define IC_CST	560
-#define IC_ADR	561
-#define IC_DAT	562
-#define DC_CST	568
-#define DC_ADR	569
-#define DC_DAT	570
-#define MI_CTR	784
-#define MI_AP	786
-#define MI_EPN	787
-#define MI_TWC	789
-#define MI_RPN	790
-#define MI_DBCAM	816
-#define MI_DBRAM0	817
-#define MI_DBRAM1	818
-#define MD_CTR	792
-#define M_CASID	793
-#define MD_AP	794
-#define MD_EPN	795
-#define M_TWB	796
-#define MD_TWC	797
-#define MD_RPN	798
-#define	M_TW	799
-#define	MD_DBCAM	824
-#define	MD_DBRAM0	825
-#define	MD_DBRAM1	826
-
-/* as on 603e, apparently mtmsr needs help in some chip revisions */
-#define	WAITMSR	SYNC; ISYNC
-
-/* use of SPRG registers in save/restore */
-#define	SAVER0	SPRG0
-#define	SAVER1	SPRG1
-#define	SAVELR	SPRG2
-#define	SAVECR	SPRG3
-
-#define	UREGSIZE	((8+32)*4)
-#define	UREGSPACE	(UREGSIZE+8)	/* allow for arg to trap, and align */
-
-/*
- * This code is loaded by the ROM loader at location 0x3000,
- * or lives in flash memory at FLASHMEM+0x100
- * Move it to high memory so that it can load the kernel at 0x0000.
- */
-
-#define LOADCODEBASE	0x3000	/* when downloaded in S records */
-#define FLASHCODEBASE	(FLASHMEM+0x20000+0x100)	/* when in flash */
-
-	TEXT	start(SB), $-4
-	MOVW	MSR, R3
-	MOVW	$(EE|IP|RI), R4
-	ANDN	R4, R3
-	OR	$ME, R3
-	SYNC
-	MOVW	R3, MSR	/* turn off interrupts but enable traps */
-	WAITMSR
-
-/*
- * reset the caches and disable them for now
- */
-	MOVW	SPR(IC_CST), R4	/* read and clear */
-	MOVW	$(5<<25), R4
-	MOVW	R4, SPR(IC_CST)	/* unlock all */
-	ISYNC
-	MOVW	$(6<<25), R4
-	MOVW	R4, SPR(IC_CST)	/* invalidate all */
-	ISYNC
-	MOVW	$(2<<25), R4
-	MOVW	R4, SPR(IC_CST)	/* disable i-cache */
-	ISYNC
-
-	SYNC
-	MOVW	SPR(DC_CST), R4	/* read and clear */
-	MOVW	$(10<<24), R4
-	MOVW	R4, SPR(DC_CST)	/* unlock all */
-	ISYNC
-	MOVW	$(12<<24), R4
-	MOVW	R4, SPR(DC_CST)	/* invalidate all */
-	ISYNC
-	MOVW	$(4<<24), R4
-	MOVW	R4, SPR(DC_CST)	/* disable i-cache */
-	ISYNC
-
-	MOVW	$7, R4
-	MOVW	R4, SPR(158)		/* cancel `show cycle' for normal instruction execution */
-
-/*
- * set other system configuration values
- */
-	MOVW	SPR(IMMR), R5		/* save initial space pointer */
-	MOVW	$INTMEM, R4
-	MOVW	R4, SPR(IMMR)		/* set internal memory base */
-	MOVW	$0xFFFFFF88, R3
-	MOVW	R3, 4(R4)	/* disable watchdog in sypcr */
-	MOVW	$0x01012440, R3
-	MOVW	R3, 0(R4)	/* siumcr */
-
-/*
- * system initialisation (init and map DRAM)
- */
-	MOVW	$0, R0
-	MOVW	$setSB(SB), R2
-#ifndef confrpcg
-	MOVW	$(0xF000<<16), R3
-/*MOVW R0, R3*/
-	ANDCC	R5, R3	/* initial space is high? */
-	BEQ	notrom
-	MOVW	$FLASHCODEBASE, R5	/* where $start(SB) actually is now */
-	MOVW	$start(SB), R4	/* logical start address */
-	SUB	R4, R5, R6	/* text relocation value */
-	MOVW	$etext(SB), R7
-	SUB	R4, R7
-	ADD	R5, R7	/* data address in ROM */
-	MOVW	$bdata(SB), R8
-	SUB	R8, R2
-	ADD	R7, R2	/* relocate SB: SB' = romdata+(SB-bdata) */
-	MOVW	$sysinit0(SB), R4
-	ADD	R6, R4	/* relocate sysinit0's address */
-	MOVW	R4, CTR
-	MOVW	$inmem(SB), R4
-	ADD	R6, R4
-	MOVW	R4, LR	/* and the return address */
-	BR	(CTR)	/* call sysinit0 */
-	TEXT	inmem(SB), $-4
-	MOVW	$FLASHCODEBASE, R3
-	BR	cpu0
-notrom:
-	MOVW	$start(SB), R6
-	SUB	R6, R2
-	ADD	$LOADCODEBASE, R2
-	BL	sysinit0(SB)
-	MOVW	$LOADCODEBASE, R3
-#endif
-
-/*
- * cpu 0
- *	relocate bootstrap to our link addresses for text and data
- *	set new PC
- */
-cpu0:
-	MOVW	$setSB(SB), R2	/* set correct static base register */
-#ifndef confrpcg
-	MOVW	$start(SB), R4
-	MOVW	$etext(SB), R5
-	SUB	R4, R5
-	CMP	R4, R3	/* already there? */
-	BNE	copytext
-	ADD	R5, R3	/* start of data image */
-#else
-	MOVW	$etext(SB), R3
-#endif
-	BR	copydata
-
-copytext:
-	ADD	$3, R5
-	SRAW	$2, R5
-	MOVW	R5, CTR
-	SUB	$4, R4
-	SUB	$4, R3
-copyt:			/* copy text */
-	MOVWU	4(R3), R5
-	MOVWU	R5, 4(R4)
-	BDNZ	copyt
-	ADD	$4, R3
-
-copydata:
-	/* copy data */
-	MOVW	$bdata(SB), R4
-	CMP	R4, R3	/* already there? */
-	BEQ	loadkpc
-	MOVW	$edata(SB), R5
-	SUB	R4, R5
-	ADD	$3, R5
-	SRAW	$2, R5
-	MOVW	R5, CTR
-	SUB	$4, R4
-	SUB	$4, R3
-copyd:
-	MOVWU	4(R3), R5
-	MOVWU	R5, 4(R4)
-	BDNZ	copyd
-#endif
-
-	/* load correct PC */
-loadkpc:
-	MOVW	$start1(SB), R3
-	MOVW	R3, LR
-	BR	(LR)
-TEXT start1(SB), $-4
-	MOVW	$edata(SB), R3
-	MOVW	$end(SB), R4
-	SUBCC	R3, R4
-	BLE	skipz
-	SRAW	$2, R4
-	MOVW	R4, CTR
-	SUB	$4, R3
-	MOVW	$0, R0
-zero:
-	MOVWU	R0, 4(R3)
-	BDNZ	zero
-skipz:
-	MOVW	$mach0(SB), R1
-	MOVW	R1, m(SB)
-	ADD	$(MACHSIZE-8), R1
-	MOVW	$0, R0
-
-	BL	sysinit0(SB)
-
-	BL	main(SB)
-	BR	0(PC)
-
-TEXT ledx(SB), $0
-
-	MOVW	$BCSRMEM, R8
-	MOVW	0(R8), R3
-	MOVW	$(0x0800<<16), R5
-	ANDN	R5, R3, R3
-	MOVW	R3, 0(R8)
-	BR	0(PC)
-
-TEXT	getmsr(SB), $0
-	MOVW	MSR, R3
-	RETURN
-
-TEXT	putmsr(SB), $0
-	SYNC
-	MOVW	R3, MSR
-	WAITMSR
-	RETURN
-
-TEXT	eieio(SB), $0
-	EIEIO
-	RETURN
-
-TEXT	idle(SB), $0
-	RETURN
-
-TEXT	spllo(SB), $0
-	MOVW	MSR, R3
-	OR	$EE, R3, R4
-	SYNC
-	MOVW	R4, MSR
-	WAITMSR
-	RETURN
-
-TEXT	splhi(SB), $0
-	MOVW	MSR, R3
-	RLWNM	$0, R3, $~EE, R4
-	SYNC
-	MOVW	R4, MSR
-	WAITMSR
-	RETURN
-
-TEXT	splx(SB), $0
-	MOVW	MSR, R4
-	RLWMI	$0, R3, $EE, R4
-	SYNC
-	MOVW	R4, MSR
-	WAITMSR
-	RETURN
-
-TEXT	gettbl(SB), $0
-/*	MOVW	SPR(TBRL), R3	*/
-	WORD	$0x7c6c42e6	/* mftbl on 8xx series */
-	RETURN
-
-TEXT	getpvr(SB), $0
-	MOVW	SPR(PVR), R3
-	RETURN
-
-TEXT	getimmr(SB), $0
-	MOVW	SPR(IMMR), R3
-	RETURN
-
-TEXT	getdec(SB), $0
-	MOVW	SPR(DEC), R3
-	RETURN
-
-TEXT	putdec(SB), $0
-	MOVW	R3, SPR(DEC)
-	RETURN
-
-/*
- * save state in Ureg on kernel stack.
- * enter with R0 giving the PC from the call to `exception' from the vector.
- * on return, SB (R2) has been set, and R3 has the Ureg*
- */
-TEXT saveureg(SB), $-4
-	SUB	$UREGSPACE, R1
-	MOVMW	R2, 48(R1)	/* r2:r31 */
-	MOVW	$setSB(SB), R2
-	MOVW	SPR(SAVER1), R4
-	MOVW	R4, 44(R1)
-	MOVW	SPR(SAVER0), R5
-	MOVW	R5, 40(R1)
-	MOVW	CTR, R6
-	MOVW	R6, 36(R1)
-	MOVW	XER, R4
-	MOVW	R4, 32(R1)
-	MOVW	SPR(SAVECR), R5	/* CR */
-	MOVW	R5, 28(R1)
-	MOVW	SPR(SAVELR), R6	/* LR */
-	MOVW	R6, 24(R1)
-	/* pad at 20(R1) */
-	MOVW	SPR(SRR0), R4
-	MOVW	R4, 16(R1)	/* old PC */
-	MOVW	SPR(SRR1), R5
-	MOVW	R5, 12(R1)
-	MOVW	R0, 8(R1)	/* cause/vector, encoded in LR from vector */
-	ADD	$8, R1, R3	/* Ureg* */
-	STWCCC	R3, (R1)	/* break any pending reservations */
-	MOVW	$0, R0	/* R0ISZERO */
-	BR	(LR)
-
-/*
- * restore state from Ureg
- * SB (R2) is unusable on return
- */
-TEXT restoreureg(SB), $-4
-	MOVMW	48(R1), R2	/* r2:r31 */
-	/* defer R1 */
-	MOVW	40(R1), R0
-	MOVW	R0, SPR(SAVER0)
-	MOVW	36(R1), R0
-	MOVW	R0, CTR
-	MOVW	32(R1), R0
-	MOVW	R0, XER
-	MOVW	28(R1), R0
-	MOVW	R0, CR	/* CR */
-	MOVW	24(R1), R0
-	MOVW	R0, SPR(SAVELR)	/* LR */
-	/* pad, skip */
-	MOVW	16(R1), R0
-	MOVW	R0, SPR(SRR0)	/* old PC */
-	MOVW	12(R1), R0
-	MOVW	R0, SPR(SRR1)	/* old MSR */
-	/* cause, skip */
-	MOVW	44(R1), R1	/* old SP */
-	BR	(LR)
-
-TEXT	exception(SB), $-4
-	MOVW	R1, SPR(SAVER1)
-	MOVW	CR, R0
-	MOVW	R0, SPR(SAVECR)
-	MOVW	LR, R0
-	BL	saveureg(SB)
-	MOVW	$0, R0
-	BL	trap(SB)
-	BL	restoreureg(SB)
-	MOVW	SPR(SAVELR), R0
-	MOVW	R0, LR
-	MOVW	SPR(SAVER0), R0
-	ISYNC
-	RFI
-
-GLOBL	mach0+0(SB), $MACHSIZE
-GLOBL	m(SB), $4
--- a/os/boot/rpcg/lib.h
+++ /dev/null
@@ -1,106 +1,0 @@
-/*
- * functions (possibly) linked in, complete, from libc.
- */
-
-/*
- * mem routines
- */
-extern	void*	memccpy(void*, void*, int, long);
-extern	void*	memset(void*, int, long);
-extern	int	memcmp(void*, void*, long);
-extern	void*	memmove(void*, void*, long);
-extern	void*	memchr(void*, int, long);
-
-/*
- * string routines
- */
-extern	char*	strcat(char*, char*);
-extern	char*	strchr(char*, char);
-extern	int	strcmp(char*, char*);
-extern	char*	strcpy(char*, char*);
-extern	char*	strncat(char*, char*, long);
-extern	char*	strncpy(char*, char*, long);
-extern	int	strncmp(char*, char*, long);
-extern	long	strlen(char*);
-extern	char*	strrchr(char*, char);
-extern	char*	strstr(char*, char*);
-
-/*
- * print routines
- * 	Fconv isn't used but is defined to satisfy prototypes in libg.h
- *	that are never called.
- */
-typedef	struct Fconv Fconv;
-
-extern	char*	donprint(char*, char*, char*, void*);
-extern	int	sprint(char*, char*, ...);
-extern	int	print(char*, ...);
-
-#define	PRINTSIZE	256
-
-/*
- * one-of-a-kind
- */
-extern	int	atoi(char*);
-extern	long	strtol(char*, char**, int);
-extern	ulong	strtoul(char*, char**, int);
-extern	long	end;
-
-/*
- * Syscall data structures
- */
-
-#define	MORDER	0x0003	/* mask for bits defining order of mounting */
-#define	MREPL	0x0000	/* mount replaces object */
-#define	MBEFORE	0x0001	/* mount goes before others in union directory */
-#define	MAFTER	0x0002	/* mount goes after others in union directory */
-#define	MCREATE	0x0004	/* permit creation in mounted directory */
-#define	MMASK	0x0007	/* all bits on */
-
-#define	OREAD	0	/* open for read */
-#define	OWRITE	1	/* write */
-#define	ORDWR	2	/* read and write */
-#define	OEXEC	3	/* execute, == read but check execute permission */
-#define	OTRUNC	16	/* or'ed in (except for exec), truncate file first */
-#define	OCEXEC	32	/* or'ed in, close on exec */
-#define	ORCLOSE	64	/* or'ed in, remove on close */
-
-#define	NCONT	0	/* continue after note */
-#define	NDFLT	1	/* terminate after note */
-
-typedef struct Qid	Qid;
-typedef struct Dir	Dir;
-typedef struct Waitmsg	Waitmsg;
-
-#define	ERRLEN	64
-#define	DIRLEN	116
-#define	NAMELEN	28
-
-struct Qid
-{
-	ulong	path;
-	ulong	vers;
-};
-
-struct Dir
-{
-	char	name[NAMELEN];
-	char	uid[NAMELEN];
-	char	gid[NAMELEN];
-	Qid	qid;
-	ulong	mode;
-	long	atime;
-	long	mtime;
-	vlong	length;
-	short	type;
-	short	dev;
-};
-
-struct Waitmsg
-{
-	int	pid;		/* of loved one */
-	int	status;		/* unused; a placeholder */
-	ulong	time[3];	/* of loved one */
-	char	msg[ERRLEN];
-};
-#define	nelem(x)	(sizeof(x)/sizeof((x)[0]))
--- a/os/boot/rpcg/libg.h
+++ /dev/null
@@ -1,418 +1,0 @@
-#pragma	src	"/sys/src/libg"
-#pragma	lib	"libg.a"
-
-enum	/* constants for I/O to devgraphics */
-{
-	Tilehdr = 40,
-	Tilesize = 8000
-};
-
-/*
- *  you may think it's a blit, but it's gnot
- */
-enum
-{
-	EMAXMSG = 128+8192,	/* size of 9p header+data */
-};
-
-/*
- * Types
- */
-
-typedef struct	Bitmap		Bitmap;
-typedef struct	Display	Display;
-typedef struct	Point		Point;
-typedef struct	Rectangle 	Rectangle;
-typedef struct	Cursor		Cursor;
-typedef struct	Mouse		Mouse;
-typedef struct	Menu		Menu;
-typedef struct	Font		Font;
-typedef struct	Fontchar	Fontchar;
-typedef struct	Subfont		Subfont;
-typedef struct	Cachefont	Cachefont;
-typedef struct	Cacheinfo	Cacheinfo;
-typedef struct	Cachesubf	Cachesubf;
-typedef struct	Event		Event;
-typedef struct	Slave		Slave;
-typedef struct	Ebuf		Ebuf;
-typedef struct	RGB		RGB;
-typedef struct	Linedesc	Linedesc;
-typedef struct	DRefret	DRefret;
-
-struct DRefret
-{
-	int		n;	/* number of bytes */
-	int		dy;	/* number of lines */
-	uchar	*dp;	/* pointer to data */
-};
-
-struct	Point
-{
-	int	x;
-	int	y;
-};
-
-struct Rectangle
-{
-	Point min;
-	Point max;
-};
-
-typedef	DRefret DRefresh(Display*, int, Rectangle, uchar*, uchar*, int);
-
-struct	Bitmap
-{
-	Rectangle		r;		/* rectangle in data area, local coords */
-	Rectangle 	clipr;		/* clipping region */
-	int			ldepth;	/* log base 2 of number of bits per pixel */
-	ulong		*base;	/* pointer to start of data */
-	int			zero;		/* base+zero=&word containing (0,0) */
-	ulong		width;	/* width in words of total data area */
-	Display		*display;	/* if present */
-};
-
-struct	Display
-{
-	uchar		*data;	/* transfer buffer */
-	Rectangle		r;
-	int			ldepth;
-	Rectangle		bb;		/* bounding box of changes */
-	int			waste;	/* unused part of bb */
-	Rectangle		bound;	/* memory for boundin/boundout */
-	Bitmap		*image;	/* owner */
-	int			id;
-	int			fd;
-	int			ctlfd;
-	int			local;
-	int			bytewidth;
-	void			*drdata1;	/* storage for drefresh() */
-	void			*drdata2;	/* storage for drefresh() */
-	DRefresh		*drefresh;
-};
-
-
-struct	Mouse
-{
-	int	buttons;	/* bit array: LMR=124 */
-	Point	xy;
-	ulong	msec;
-};
-
-struct	Cursor
-{
-	Point	offset;
-	uchar	clr[2*16];
-	uchar	set[2*16];
-};
-
-struct Menu
-{
-	char	**item;
-	char	*(*gen)(int);
-	int	lasthit;
-};
-
-struct Linedesc
-{
-	int	x0;
-	int	y0;
-	char	xmajor;
-	char	slopeneg;
-	long	dminor;
-	long	dmajor;
-};
-
-/*
- * Subfonts
- *
- * given char c, Subfont *f, Fontchar *i, and Point p, one says
- *	i = f->info+c;
- *	bitblt(b, Pt(p.x+i->left,p.y+i->top),
- *		bitmap, Rect(i->x,i->top,(i+1)->x,i->bottom),
- *		fc);
- *	p.x += i->width;
- * where bitmap b is the repository of the images.
- *
- */
-
-struct	Fontchar
-{
-	short	x;		/* left edge of bits */
-	uchar	top;		/* first non-zero scan-line */
-	uchar	bottom;		/* last non-zero scan-line + 1 */
-	char	left;		/* offset of baseline */
-	uchar	width;		/* width of baseline */
-};
-
-struct	Subfont
-{
-	short	n;		/* number of chars in font */
-	uchar	height;		/* height of bitmap */
-	char	ascent;		/* top of bitmap to baseline */
-	Fontchar *info;		/* n+1 character descriptors */
-	Bitmap	*bits;		/* of font */
-};
-
-enum
-{
-	/* starting values */
-	LOG2NFCACHE =	6,
-	NFCACHE =	(1<<LOG2NFCACHE),	/* #chars cached */
-	NFLOOK =	5,			/* #chars to scan in cache */
-	NFSUBF =	2,			/* #subfonts to cache */
-	/* max value */
-	MAXFCACHE =	2048+NFLOOK,		/* generous upper limit */
-	MAXSUBF =	50,			/* generous upper limit */
-	/* deltas */
-	DSUBF = 	4,
-	/* expiry ages */
-	SUBFAGE	=	10000,
-	CACHEAGE =	10000,
-};
-
-struct Cachefont
-{
-	Rune	min;	/* lowest rune value to be taken from subfont */
-	Rune	max;	/* highest rune value+1 to be taken from subfont */
-	int	offset;	/* position in subfont of character at min */
-	int	abs;	/* name has been made absolute */
-	char	*name;
-};
-
-struct Cacheinfo
-{
-	Rune		value;	/* value of character at this slot in cache */
-	ushort		age;
-	ulong		xright;	/* right edge of bits */
-	Fontchar;
-};
-
-struct Cachesubf
-{
-	ulong		age;	/* for replacement */
-	Cachefont	*cf;	/* font info that owns us */
-	Subfont		*f;	/* attached subfont */
-};
-
-struct Font
-{
-	char		*name;
-	short		height;	/* max height of bitmap, interline spacing */
-	short		ascent;	/* top of bitmap to baseline */
-	int			maxldepth;	/* over all loaded subfonts */
-	short		width;	/* widest so far; used in caching only */	
-	short		ldepth;	/* of images */
-	short		nsub;	/* number of subfonts */
-	ulong		age;	/* increasing counter; used for LRU */
-	int		ncache;	/* size of cache */
-	int		nsubf;	/* size of subfont list */
-	Cacheinfo	*cache;
-	Cachesubf	*subf;
-	Cachefont	**sub;	/* as read from file */
-	Bitmap	*cacheimage;
-};
-
-struct	Event
-{
-	int	kbdc;
-	Mouse	mouse;
-	int	n;		/* number of characters in mesage */
-	uchar	data[EMAXMSG];	/* message from an arbitrary file descriptor */
-};
-
-struct Slave{
-	int	pid;
-	Ebuf	*head;		/* queue of messages for this descriptor */
-	Ebuf	*tail;
-};
-
-struct Ebuf{
-	Ebuf	*next;
-	int	n;		/* number of bytes in buf */
-	uchar	buf[EMAXMSG];
-};
-
-struct RGB
-{
-	ulong	red;
-	ulong	green;
-	ulong	blue;
-};
-
-/*
- * Codes for bitblt etc.
- *
- *	       D
- *	     0   1
- *         ---------
- *	 0 | 1 | 2 |
- *     S   |---|---|
- * 	 1 | 4 | 8 |
- *         ---------
- *
- *	Usually used as D|S; DorS is so tracebacks are readable.
- */
-typedef
-enum	Fcode
-{
-	Zero		= 0x0,
-	DnorS		= 0x1,
-	DandnotS	= 0x2,
-	notS		= 0x3,
-	notDandS	= 0x4,
-	notD		= 0x5,
-	DxorS		= 0x6,
-	DnandS		= 0x7,
-	DandS		= 0x8,
-	DxnorS		= 0x9,
-	D		= 0xA,
-	DornotS		= 0xB,
-	S		= 0xC,
-	notDorS		= 0xD,
-	DorS		= 0xE,
-	F		= 0xF,
-} Fcode;
-
-/*
- * Miscellany
- */
-
-extern Point	 add(Point, Point), sub(Point, Point);
-extern Point	 mul(Point, int), div(Point, int);
-extern Rectangle rsubp(Rectangle, Point), raddp(Rectangle, Point), inset(Rectangle, int);
-extern Rectangle rmul(Rectangle, int), rdiv(Rectangle, int);
-extern Rectangle rshift(Rectangle, int), rcanon(Rectangle);
-extern Bitmap*	 balloc(Rectangle, int);
-extern Bitmap*	 ballocnomem(Rectangle, int);
-extern Bitmap*	 brealloc(Bitmap*, Rectangle, int);
-extern Bitmap*	 breallocnomem(Bitmap*, Rectangle, int);
-extern int		bbytewidth(Bitmap*, int*, int*);
-extern void	 bfree(Bitmap*);
-extern void	 bfreemem(Bitmap*);
-extern int	 rectclip(Rectangle*, Rectangle);
-extern void	 binit(void(*)(char*), char*, char*);
-extern void	 binit1(void(*)(char*), char*, char*, int);
-extern void	 bclose(void);
-extern void	 berror(char*);
-extern void	 bitblt(Bitmap*, Point, Bitmap*, Rectangle, Fcode);
-extern int	 bitbltclip(void*);
-extern Font*	 rdfontfile(char*, int);
-extern void	 ffree(Font*);
-extern void	fminldepth(Font*);
-extern Font*	 mkfont(Subfont*, Rune);
-extern Subfont*	 subfalloc(int, int, int, Fontchar*, Bitmap*);
-extern void	 subffree(Subfont*);
-extern int	 cachechars(Font*, char**, ushort*, int, int*);
-extern Point	 string(Bitmap*, Point, Font*, char*, Fcode);
-extern Point	 subfstring(Bitmap*, Point, Subfont*, char*, Fcode);
-extern void	 segment(Bitmap*, Point, Point, int, Fcode);
-extern void	 point(Bitmap*, Point, int, Fcode);
-extern void	 arc(Bitmap*, Point, Point, Point, int, Fcode);
-extern void	 circle(Bitmap*, Point, int, int, Fcode);
-extern void	 disc(Bitmap*, Point, int, int, Fcode);
-extern void	 ellipse(Bitmap*, Point, int, int, int, Fcode);
-extern long	 strwidth(Font*, char*);
-extern void	 agefont(Font*);
-extern int	 loadchar(Font*, Rune, Cacheinfo*, int, int);
-extern Point	 strsize(Font*, char*);
-extern long	 charwidth(Font*, Rune);
-extern void	 texture(Bitmap*, Rectangle, Bitmap*, Fcode);
-extern void	 wrbitmap(Bitmap*, int, int, uchar*);
-extern void	 rdbitmap(Bitmap*, int, int, uchar*);
-extern void	 wrbitmapfile(int, Bitmap*);
-extern Bitmap*	 rdbitmapfile(int);
-extern void	 wrsubfontfile(int, Subfont*);
-extern void	 wrcolmap(Bitmap*, RGB*);
-extern void	 rdcolmap(Bitmap*, RGB*);
-extern Subfont*	 rdsubfontfile(int, Bitmap*);
-extern void	_unpackinfo(Fontchar*, uchar*, int);
-
-extern int	 ptinrect(Point, Rectangle), rectinrect(Rectangle, Rectangle);
-extern int	 rectXrect(Rectangle, Rectangle);
-extern int	 eqpt(Point, Point), eqrect(Rectangle, Rectangle);
-extern void	 border(Bitmap*, Rectangle, int, Fcode);
-extern void	 cursorswitch(Cursor*);
-extern void	 cursorset(Point);
-extern Rectangle bscreenrect(Rectangle*);
-extern void	 bflush(void);
-extern void	 bexit(void);
-extern int	 _clipline(Rectangle, Point*, Point*, Linedesc*);
-extern int	 clipline(Rectangle, Point*, Point*);
-extern int	 clipr(Bitmap*, Rectangle);
-
-extern void	 einit(ulong);
-extern ulong	 estart(ulong, int, int);
-extern ulong	 etimer(ulong, int);
-extern ulong	 event(Event*);
-extern ulong	 eread(ulong, Event*);
-extern Ebuf*	 ebread(Slave*);
-extern Mouse	 emouse(void);
-extern int	 ekbd(void);
-extern int	 ecanread(ulong);
-extern int	 ecanmouse(void);
-extern int	 ecankbd(void);
-extern void	 ereshaped(Rectangle);	/* supplied by user */
-extern int	 menuhit(int, Mouse*, Menu*);
-extern Rectangle getrect(int, Mouse*);
-extern ulong	 rgbpix(Bitmap*, RGB);
-extern int	_gminor(long, Linedesc*);
-
-enum{
-	Emouse		= 1,
-	Ekeyboard	= 2,
-};
-
-enum
-{
-	MAXSLAVE = 32,
-};
-
-#define	Pt(x, y)		((Point){(x), (y)})
-#define	Rect(x1, y1, x2, y2)	((Rectangle){Pt(x1, y1), Pt(x2, y2)})
-#define	Rpt(p1, p2)		((Rectangle){(p1), (p2)})
-
-
-#define	Dx(r)	((r).max.x-(r).min.x)
-#define	Dy(r)	((r).max.y-(r).min.y)
-
-extern	Bitmap	screen;
-extern	Font	*font;
-extern	uchar	_btmp[8192];
-
-extern	int	_mousefd;
-extern	int	_cursorfd;
-
-#define	BGSHORT(p)		(((p)[0]<<0) | ((p)[1]<<8))
-#define	BG32INT(p)		((s32int)((BGSHORT(p)<<0) | (BGSHORT(p+2)<<16)))
-#define	BPSHORT(p, v)		((p)[0]=(v), (p)[1]=((v)>>8))
-#define	BP32INT(p, v)		(BPSHORT(p, ((s32int)v)), BPSHORT(p+2, ((s32int)v)>>16))
-
-ulong	*wordaddr(Bitmap*, Point);
-uchar	*byteaddr(Bitmap*, Point);
-int		dfree(Display*);
-int		dwritectl(Display*, char*, int);
-int		dreadctl(Display*, char*, int);
-int		dinfo(Display*, int, int*, Rectangle*);
-void*	dinit(Display*, Bitmap*, int, int);
-int		ddelete(Display*);
-void		dfreemem(Display*);
-int		dreadctl(Display*, char*, int);
-int		dwritectl(Display*, char*, int);
-void	dbound(Display*, Rectangle);
-void	bload(Bitmap*, Rectangle, uchar*);
-ulong	bunload(Bitmap*, Rectangle, uchar*);
-void		drefresh(Display*, Rectangle);
-Display	*dopen(char*, int, DRefresh*);
-Bitmap*	dbitmap(Display*, DRefresh*, int);
-void		dclose(Display*);
-void		dflush(Display*);
-void		_bltinit(void);
-Bitmap*	battach(Bitmap*, int, int);
-int		readmouse(Mouse*);
-int		atomouse(Mouse*, char*, int);
-
-/*
- * Refresh functions
- */
-DRefresh	drtexture;
-DRefresh	drbackstore;
--- a/os/boot/rpcg/main.c
+++ /dev/null
@@ -1,527 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-#include "dosfs.h"
-
-typedef struct Type Type;
-typedef struct Medium Medium;
-typedef struct Mode Mode;
-
-enum {
-	Dany		= -1,
-	Nmedia		= 16,
-
-	/* DS1 switch options */
-	Sflashfs		= 1<<0,	/* take local fs from flash */
-	Snotflash		= 1<<1,	/* don't boot from flash */
-};
-
-enum {					/* type */
-	Tflash,
-	Tuart,
-	Tether,
-	Thard,
-
-	Tany		= -1,
-};
-
-enum {					/* flag and name */
-	Fnone		= 0x00,
-
-	Fdos		= 0x01,
-	Ndos		= 0x00,
-	Fboot		= 0x02,
-	Nboot		= 0x01,
-	Fbootp		= 0x04,
-	Nbootp		= 0x02,
-	Fflash		= 0x08,
-	Fuart		= 0x10,
-	NName		= 0x03,
-
-	Fany		= Fbootp|Fboot|Fdos|Fflash|Fuart,
-
-	Fini		= 0x10,
-	Fprobe		= 0x80,
-};
-
-enum {					/* mode */
-	Mauto		= 0x00,
-	Mlocal		= 0x01,
-	Manual		= 0x02,
-	NMode		= 0x03,
-};
-
-typedef struct Type {
-	int	type;
-	char	*cname;
-	int	flag;
-	int	(*init)(void);
-	long	(*read)(int, void*, long);
-	long	(*seek)(int, long);
-	Partition* (*setpart)(int, char*);
-	char*	name[NName];
-
-	int	mask;
-	Medium*	media;
-} Type;
-
-typedef struct Medium {
-	Type*	type;
-	int	flag;
-	Partition* partition;
-	Dos;
-
-	Medium*	next;
-} Medium;
-
-typedef struct Mode {
-	char*	name;
-	int	mode;
-} Mode;
-
-static Type types[] = {
-	{	Tflash, "flash",
-		Fflash,
-		flashinit, 0, 0, 0,
-		{ 0, "F", 0, }
-	},
-/*
-	{	Tuart, "uart",
-		Fuart|Fboot,
-		uartinit, uartread, uartseek, setuartpart,
-		{ 0, "u", 0, }
-	},
-*/
-	{	Tether, "ether",
-		Fbootp,
-		etherinit, 0, 0, 0,
-		{ 0, 0, "e", },
-	},
-	{	Thard, "ata",
-		Fini|Fboot|Fdos,
-		0, 0, 0, 0,		/* not used now, will be later with PCMCIA */
-		{ "hd", "h", 0, },
-	},
-	{-1},
-};
-
-static Medium media[Nmedia];
-static Medium *curmedium = media;
-
-static Mode modes[NMode+1] = {
-	[Mauto]		{ "auto",   Mauto,  },
-	[Mlocal]	{ "local",  Mlocal, },
-	[Manual]	{ "manual", Manual, },
-};
-
-static char *inis[] = {
-	"inferno/inferno.ini",
-	"inferno.ini",
-	"plan9/plan9.ini",
-	"plan9.ini",
-	0,
-};
-char **ini;
-int	predawn;
-
-static int
-parse(char *line, int *type, int *flag, int *dev, char *file)
-{
-	Type *tp;
-	char buf[2*NAMELEN], *v[4], *p;
-	int i;
-
-	strcpy(buf, line);
-	switch(getcfields(buf, v, 4, "!")){
-
-	case 3:
-		break;
-
-	case 2:
-		v[2] = "";
-		break;
-
-	default:
-		return 0;
-	}
-
-	*flag = 0;
-	for(tp = types; tp->cname; tp++){
-		for(i = 0; i < NName; i++){
-
-			if(tp->name[i] == 0 || strcmp(v[0], tp->name[i]))
-				continue;
-			*type = tp->type;
-			*flag |= 1<<i;
-
-			if((*dev = strtoul(v[1], &p, 0)) == 0 && p == v[1])
-				return 0;
-		
-			strcpy(file, v[2]);
-		
-			return 1;
-		}
-	}
-
-	return 0;
-
-}
-
-static int
-boot(Medium *mp, int flag, char *file)
-{
-	Dosfile df;
-	char ixdos[128], *p;
-	int r;
-
-	uartsetboot(0);
-	if(flag & Fbootp){
-		sprint(BOOTLINE, "%s!%d", mp->type->name[Nbootp], mp->dev);
-		return bootp(mp->dev, file);
-	}
-
-	if(flag & Fflash){
-		if(mp->flag & Fflash && flashbootable(0))
-			flashboot(mp->dev);
-	}
-
-	if(flag & Fboot){
-
-		if(mp->flag & Fini){
-			(*mp->type->setpart)(mp->dev, "disk");
-			plan9ini(mp, nil);
-		}
-		if(file == 0 || *file == 0)
-			file = mp->partition->name;
-		(*mp->type->setpart)(mp->dev, file);
-		sprint(BOOTLINE, "%s!%d!%s", mp->type->name[Nboot], mp->dev, file);
-		r = plan9boot(mp->dev, mp->seek, mp->read);
-		uartsetboot(0);
-		return r;
-	}
-
-	if(flag & Fdos){
-		if(mp->type->setpart)
-			(*mp->type->setpart)(mp->dev, "disk");
-		if(mp->flag & Fini)
-			plan9ini(mp, nil);
-		if(file == 0 || *file == 0){
-			strcpy(ixdos, *ini);
-			if(p = strrchr(ixdos, '/'))
-				p++;
-			else
-				p = ixdos;
-			strcpy(p, "impc");
-			if(dosstat(mp, ixdos, &df) <= 0)
-				return -1;
-		}
-		else
-			strcpy(ixdos, file);
-		sprint(BOOTLINE, "%s!%d!%s", mp->type->name[Ndos], mp->dev, ixdos);
-		return dosboot(mp, ixdos);
-	}
-
-	return -1;
-}
-
-static Medium*
-allocm(Type *tp)
-{
-	Medium **l;
-
-	if(curmedium >= &media[Nmedia])
-		return 0;
-
-	for(l = &tp->media; *l; l = &(*l)->next)
-		;
-	*l = curmedium++;
-	return *l;
-}
-
-Medium*
-probe(int type, int flag, int dev)
-{
-	Type *tp;
-	int dombr, i, start;
-	Medium *mp;
-	Dosfile df;
-	Partition *pp;
-
-	for(tp = types; tp->cname; tp++){
-		if(type != Tany && type != tp->type || tp->init == 0)
-			continue;
-
-		if(flag != Fnone){
-			for(mp = tp->media; mp; mp = mp->next){
-				if((flag & mp->flag) && (dev == Dany || dev == mp->dev))
-					return mp;
-			}
-		}
-		if((tp->flag & Fprobe) == 0){
-			tp->flag |= Fprobe;
-			tp->mask = (*tp->init)();
-		}
-
-		for(i = 0; tp->mask; i++){
-			if((tp->mask & (1<<i)) == 0)
-				continue;
-			tp->mask &= ~(1<<i);
-
-			if((mp = allocm(tp)) == 0)
-				continue;
-
-			mp->dev = i;
-			mp->flag = tp->flag;
-			mp->seek = tp->seek;
-			mp->read = tp->read;
-			mp->type = tp;
-
-			if(mp->flag & Fboot){
-				if((mp->partition = (*tp->setpart)(i, "boot")) == 0)
-					mp->flag &= ~Fboot;
-				if((mp->flag & (Fflash|Fuart)) == 0)
-					(*tp->setpart)(i, "disk");
-			}
-
-			if(mp->flag & Fdos){
-				start = 0;
-				dombr = 1;
-				if(mp->type->setpart){
-					if(pp = (*mp->type->setpart)(i, "dos")){
-						if(start = pp->start)
-							dombr = 0;
-					}
-					(*tp->setpart)(i, "disk");
-				}
-				if(dosinit(mp, start, dombr) < 0)
-					mp->flag &= ~(Fini|Fdos);
-				else
-					print("dos init failed\n");
-			}
-
-			if(mp->flag & Fini){
-				mp->flag &= ~Fini;
-				for(ini = inis; *ini; ini++){
-					if(dosstat(mp, *ini, &df) <= 0)
-						continue;
-					mp->flag |= Fini;
-					break;
-				}
-			}
-
-			if((flag & mp->flag) && (dev == Dany || dev == i))
-				return mp;
-		}
-	}
-
-	return 0;
-}
-
-void
-main(void)
-{
-	Medium *mp;
-	int dev, flag, i, mode, tried, type, options;
-	char def[2*NAMELEN], file[2*NAMELEN], line[80], *p;
-	Type *tp;
-
-	machinit();
-	archinit();
-	meminit();
-	cpminit();
-	trapinit();
-	consinit();	/* screen and keyboard initially */
-/*	screeninit();	*/
-	cpuidprint();
-	alarminit();
-	clockinit();
-print("predawn\n");
-	predawn = 0;
-	spllo();
-print("dawn\n");
-	options = archoptionsw();
-print("options=#%ux\n", options);
-
-	mp = 0;
-	for(tp = types; tp->cname; tp++){
-		if(tp->type == Tether)
-			continue;
-		if((mp = probe(tp->type, Fini, Dany)) && (mp->flag & Fini)){
-			plan9ini(mp, nil);
-			break;
-		}
-	}
-
-	if(mp == 0 || (mp->flag & Fini) == 0)
-		plan9ini(nil, flashconfig(0));
-
-	//consinit();	/* establish new console location */
-
-	if((options & Snotflash) == 0 && flashbootable(0)){
-		print("Flash boot\n");
-		flashboot(0);
-	}
-
-	tried = 0;
-	mode = Mauto;
-	p = getconf("bootfile");
-	flag = 0;
-
-	if(p != 0) {
-		mode = Manual;
-		for(i = 0; i < NMode; i++){
-			if(strcmp(p, modes[i].name) == 0){
-				mode = modes[i].mode;
-				goto done;
-			}
-		}
-		if(parse(p, &type, &flag, &dev, file) == 0) {
-			print("Bad bootfile syntax: %s\n", p);
-			goto done;
-		}
-		mp = probe(type, flag, dev);
-		if(mp == 0) {
-			print("Cannot access device: %s\n", p);
-			goto done;
-		}
-		tried = boot(mp, flag, file);
-	}
-done:
-	if(tried == 0 && mode != Manual){
-		flag = Fany;
-		if(mode == Mlocal)
-			flag &= ~Fbootp;
-		if(options & Snotflash)
-			flag &= ~Fflash;
-		if((mp = probe(Tany, flag, Dany)) != 0)
-			boot(mp, flag & mp->flag, 0);
-	}
-
-	def[0] = 0;
-	probe(Tany, Fnone, Dany);
-
-	flag = 0;
-	for(tp = types; tp->cname; tp++){
-		for(mp = tp->media; mp; mp = mp->next){
-			if(flag == 0){
-				flag = 1;
-				print("Boot devices:");
-			}
-
-			if(mp->flag & Fbootp)
-				print(" %s!%d", mp->type->name[Nbootp], mp->dev);
-			if(mp->flag & Fdos)
-				print(" %s!%d", mp->type->name[Ndos], mp->dev);
-			if(mp->flag & (Fflash|Fuart) || mp->flag & Fboot)
-				print(" %s!%d", mp->type->name[Nboot], mp->dev);
-		}
-	}
-	if(flag)
-		print("\n");
-
-	for(;;){
-		if(getstr("boot from", line, sizeof(line), def) >= 0){
-			if(parse(line, &type, &flag, &dev, file)){
-				if(mp = probe(type, flag, dev))
-					boot(mp, flag, file);
-			}
-		}
-		def[0] = 0;
-	}
-}
-
-void
-machinit(void)
-{
-	memset(m, 0, sizeof(*m));
-	m->delayloop = 20000;
-	m->cpupvr = getpvr();
-	m->iomem = KADDR(INTMEM);
-}
-
-int
-getcfields(char* lp, char** fields, int n, char* sep)
-{
-	int i;
-
-	for(i = 0; lp && *lp && i < n; i++){
-		while(*lp && strchr(sep, *lp) != 0)
-			*lp++ = 0;
-		if(*lp == 0)
-			break;
-		fields[i] = lp;
-		while(*lp && strchr(sep, *lp) == 0){
-			if(*lp == '\\' && *(lp+1) == '\n')
-				*lp++ = ' ';
-			lp++;
-		}
-	}
-
-	return i;
-}
-
-static	Map	memv[512];
-static	RMap	rammap = {"physical memory"};
-
-void
-meminit(void)
-{
-	ulong e;
-
-	mapinit(&rammap, memv, sizeof(memv));
-	e = PADDR(&end);
-	mapfree(&rammap, e, 4*1024*1024-e);	/* fixed 4Mbytes is plenty for bootstrap */
-}
-
-void*
-ialloc(ulong n, int align)
-{
-	ulong a;
-	int s;
-
-	if(align <= 0)
-		align = 4;
-	s = splhi();
-	a = mapalloc(&rammap, 0, n, align);
-	splx(s);
-	if(a == 0)
-		panic("ialloc");
-	return memset(KADDR(a), 0, n);
-}
-
-void*
-malloc(ulong n)
-{
-	ulong *p;
-
-	n = ((n+sizeof(int)-1)&~(sizeof(int)-1))+2*sizeof(int);
-	p = ialloc(n, sizeof(int));
-	*p++ = 0xcafebeef;
-	*p++ = n;
-	return p;
-}
-
-void
-free(void *ap)
-{
-	int s;
-	ulong *p;
-
-	p = ap;
-	if(p){
-		if(*(p -= 2) != 0xcafebeef)
-			panic("free");
-		s = splhi();
-		mapfree(&rammap, (ulong)p, p[1]);
-		splx(s);
-	}
-}
-
-void
-sched(void)
-{
-}
--- a/os/boot/rpcg/mem.h
+++ /dev/null
@@ -1,94 +1,0 @@
-/*
- * Memory and machine-specific definitions.  Used in C and assembler.
- */
-
-/*
- * Sizes
- */
-#define	BI2BY		8			/* bits per byte */
-#define BI2WD		32			/* bits per word */
-#define	BY2WD		4			/* bytes per word */
-#define	BY2PG		4096			/* bytes per page */
-#define	WD2PG		(BY2PG/BY2WD)		/* words per page */
-#define	PGSHIFT		12			/* log(BY2PG) */
-#define PGROUND(s)	(((s)+(BY2PG-1))&~(BY2PG-1))
-
-#define	MAXMACH		1			/* max # cpus system can run */
-#define	CACHELINELOG	4
-#define CACHELINESZ	(1<<CACHELINELOG)
-
-/*
- * Time
- */
-#define	HZ		(50)				/* clock frequency */
-#define	MS2HZ		(1000/HZ)			/* millisec per clock tick */
-#define	TK2SEC(t)	((t)/HZ)			/* ticks to seconds */
-#define	TK2MS(t)	((((ulong)(t))*1000)/HZ)	/* ticks to milliseconds */
-#define	MS2TK(t)	((((ulong)(t))*HZ)/1000)	/* milliseconds to ticks */
-#define	MHz	1000000
-
-/*
- * Fundamental values
- */
-
-#define	KZERO	0	/* bootstrap runs in real mode */
-#define	MACHSIZE	4096
-
-/*
- *  physical MMU
- */
-#define KSEG0	0x20000000
-#define	KSEGM	0xE0000000	/* mask to check which seg */
-
-/*
- * MSR bits
- */
-
-#define	POW	0x40000	/* enable power mgmt */
-#define	TGPR	0x20000	/* GPR0-3 remapped; 603/603e specific */
-#define	ILE	0x10000	/* interrupts little endian */
-#define	EE	0x08000	/* enable external/decrementer interrupts */
-#define	PR	0x04000	/* =1, user mode */
-#define	FPE	0x02000	/* enable floating point */
-#define	ME	0x01000	/* enable machine check exceptions */
-#define	FE0	0x00800
-#define	SE	0x00400	/* single-step trace */
-#define	BE	0x00200	/* branch trace */
-#define	FE1	0x00100
-#define	IP	0x00040	/* =0, vector to nnnnn; =1, vector to FFFnnnnn */
-#define	IR	0x00020	/* enable instruction address translation */
-#define	DR	0x00010	/* enable data address translation */
-#define	RI	0x00002	/* exception is recoverable */
-#define	LE	0x00001	/* little endian mode */
-
-#define	KMSR	(ME|FE0|FE1|FPE)
-#define	UMSR	(KMSR|PR|EE|IR|DR)
-
-/*
- * MPC82x addresses
- */
-#define	BCSRMEM	0xFA400000
-#define	FLASHMEM	0xFFC00000
-#define	INTMEM	0xFA200000
-
-#define	DPRAM	(INTMEM+0x2000)
-#define	DPLEN1	0x400
-#define	DPLEN2	0x200
-#define	DPLEN3	0x100
-#define	DPBASE	(DPRAM+DPLEN1)
-
-#define	SCC1P	(INTMEM+0x3C00)
-#define	I2CP	(INTMEM+0x3C80)
-#define	MISCP	(INTMEM+0x3CB0)
-#define	IDMA1P	(INTMEM+0x3CC0)
-#define	SCC2P	(INTMEM+0x3D00)
-#define	SCC3P	(INTMEM+0x3E00)
-#define	SCC4P	(INTMEM+0x3F00)
-#define	SPIP	(INTMEM+0x3D80)
-#define	TIMERP	(INTMEM+0x3DB0)
-#define	SMC1P	(INTMEM+0x3E80)
-#define	DSP1P	(INTMEM+0x3EC0)
-#define	SMC2P	(INTMEM+0x3F80)
-#define	DSP2P	(INTMEM+0x3FC0)
-
-#define KEEP_ALIVE_KEY 0x55ccaa33	/* clock and rtc register key */
--- a/os/boot/rpcg/mkfile
+++ /dev/null
@@ -1,120 +1,0 @@
-objtype=power
-OBJTYPE=power	# always
-<../../../mkconfig
-SYSTARG=$OSTARG	# always
-<$ROOT/mkfiles/mkfile-$SYSTARG-$OBJTYPE
-INSTALLDIR=$ROOT/Inferno/$OBJTYPE/bin	#path of directory where kernel is installed
-CONF=rpcg	# selects board dependent code
-TARG=qb$CONF
-OFILES=\
-	l.$O\
-	arch$CONF.$O\
-	devuart.$O\
-	uartboot.$O\
-	alarm.$O\
-	bootp.$O\
-	clock.$O\
-	conf.$O\
-	console.$O\
-	cpm.$O\
-	defont0.$O\
-	donprint.$O\
-	dosboot.$O\
-	devether.$O\
-	etherscc.$O\
-	fblt.$O\
-	gbitbltclip.$O\
-	flash.$O\
-	main.$O\
-	i2c.$O\
-	plan9boot.$O\
-	qio.$O\
-	rmap.$O\
-	screen.$O\
-	init$CONF.$O\
-	trap.$O\
-	zqs.$O\
-
-HFILES=\
-	boot.h\
-	dat.h\
-	fns.h\
-	io.h\
-	lib.h\
-	mem.h\
-	squeeze.h\
-	gnot.h\
-	arch$CONF.h\
-
-LIBS=\
-	kern\
-
-LIBDIRS=$LIBS
-LIBNAMES=${LIBS:%=lib%.a}
-LIBFILES=${LIBS:%=$ROOT/$TARGMODEL/$OBJTYPE/lib/lib%.a}
-
-#all:NV:	$TARG k.mx f.mx
-all:NV:	$TARG
-install:V: 	$INSTALLDIR/$TARG
-installall:V: 	$INSTALLDIR/$TARG
-
-$INSTALLDIR/%: %
-	rm -f $INSTALLDIR/$stem && cp $stem $INSTALLDIR/$stem
-
-$TARG: $OFILES $LIBNAMES
-	$LD -o $target -l  -T0x140000 -R4 $OFILES $LIBFILES
-	ls -l $target
-
-qbrom$CONF:	$OFILES $LIBNAMES
-	$LD -o $target -l -T0xFFC20100 -R0 -D0x140000 $OFILES $LIBFILES
-
-k.mx:	$TARG
-	ms2 -S 0x100 -a 0x140000 -3 -p 4 $TARG >$target
-
-f.mx:	qbrom$CONF
-	ms2 -S 0x100 -a 0xFFC20100 -3 -p 4 $prereq >$target
-
-g.mx:	qbrom$CONF
-	ms2 -S 0x100 -a 0x10000 -3 -p 4 $prereq >$target
-
-%.$O:	%.s
-	$AS -Dconf$CONF $stem.s
-
-%.$O:	%.c
-	$CC $CFLAGS $stem.c
-
-%.$O:	$HFILES
-
-lib%.a:V:	$SHELLTYPE-lib%.a
-
-rc-lib%.a nt-lib%.a:VQ:
-	echo '@{builtin cd ' $ROOT/lib$stem ';mk SHELLTYPE=$SHELLTYPE SYSTARG=$SYSTARG OBJTYPE=$OBJTYPE install}'
-	@{builtin cd  $ROOT/lib$stem ;mk 'SHELLTYPE='$SHELLTYPE 'SYSTARG='$SYSTARG 'OBJTYPE='$OBJTYPE install}
-
-sh-lib%.a:VQ:
-	echo "(cd $ROOT/lib$stem ; mk SHELLTYPE=$SHELLTYPE SYSTARG=$SYSTARG OBJTYPE=$OBJTYPE install)"
-	(cd $ROOT/lib$stem ; mk SHELLTYPE=$SHELLTYPE SYSTARG=$SYSTARG OBJTYPE=$OBJTYPE install)
-
-clock.$O floppy.$O trap.$O:	ureg.h
-conf.$O dosboot.$O main.$O:	dosfs.h
-ether.$O etherscc.$O:	etherif.h
-bootp.$O:	ip.h
-
-clean:V:
-	rm -f *.[$OS] [$OS].out y.tab.? y.debug y.output $TARG qboot k.mx f.mx romboot
-
-nuke-sh:QV:
-		for i in $LIBDIRS
-		do
-			echo "(cd $ROOT/lib$i ; mk SHELLTYPE=$SHELLTYPE SYSTARG=$SYSTARG OBJTYPE=$OBJTYPE nuke)"
-			(cd $ROOT/lib$i; mk 'SHELLTYPE='$SHELLTYPE 'SYSTARG='$SYSTARG 'OBJTYPE='$OBJTYPE nuke)
-		done
-
-nuke-rc nuke-nt:QV:
-		for (i in $LIBDIRS)
-		{
-			echo '@{cd $ROOT/lib$i ; mk SHELLTYPE=$SHELLTYPE SYSTARG=$SYSTARG OBJTYPE=$OBJTYPE nuke}'
-			@{cd $ROOT/lib$i; mk 'SHELLTYPE='$SHELLTYPE 'SYSTARG='$SYSTARG 'OBJTYPE='$OBJTYPE nuke}
-		}
-
-nuke:V:		clean nuke-$SHELLTYPE
--- a/os/boot/rpcg/ms2.c
+++ /dev/null
@@ -1,179 +1,0 @@
-#include <u.h>
-#include <libc.h>
-#include <bio.h>
-#include <mach.h>
-
-void	record(uchar*, int);
-void	usage(void);
-void	dosegment(long, int);
-void trailer(ulong);
-
-enum
-{
-	Recordsize = 32,
-};
-
-int	dsegonly;
-int	supressend;
-int	binary;
-int	addr4;
-ulong	addr;
-ulong 	psize = 4096;
-ulong	startaddr = 0x030000;
-Biobuf 	stdout;
-Biobuf	bio;
-
-void
-main(int argc, char **argv)
-{
-	Dir dir;
-	Fhdr f;
-	int fd;
-
-	ARGBEGIN{
-	case 'd':
-		dsegonly++;
-		break;
-	case 's':
-		supressend++;
-		break;
-	case 'a':
-		addr = strtoul(ARGF(), 0, 0);
-		break;
-	case 'p':
-		psize = strtoul(ARGF(), 0, 0);
-		break;
-	case 'b':
-		binary++;
-		break;
-	case 'S':
-		startaddr = strtoul(ARGF(), 0, 0);
-		break;
-	case '4':
-		addr4++;
-		break;
-	default:
-		usage();
-	}ARGEND
-
-	if(argc != 1)
-		usage();
-
-	Binit(&stdout, 1, OWRITE);
-
-	fd = open(argv[0], OREAD);
-	if(fd < 0) {
-		fprint(2, "ms2: open %s: %r\n", argv[0]);
-		exits("open");
-	}
-
-	if(binary) {
-		if(dirfstat(fd, &dir) < 0) {
-			fprint(2, "ms2: stat failed %r");
-			exits("dirfstat");
-		}
-		Binit(&bio, fd, OREAD);
-		dosegment(0, dir.length);
-		if(supressend == 0)
-			trailer(startaddr);
-		Bterm(&stdout);
-		Bterm(&bio);
-		exits(0);
-	}
-
-	if(crackhdr(fd, &f) == 0){
-		fprint(2, "ms2: bad magic: %r\n");
-		exits("magic");
-	}
-	seek(fd, 0, 0);
-
-	Binit(&bio, fd, OREAD);
-
-	if(dsegonly)
-		dosegment(f.datoff, f.datsz);
-	else {
-		dosegment(f.txtoff, f.txtsz);
-		addr = (addr+(psize-1))&~(psize-1);
-		dosegment(f.datoff, f.datsz);
-	}
-
-	if(supressend == 0)
-		trailer(startaddr);
-
-	Bterm(&stdout);
-	Bterm(&bio);
-	exits(0);
-}
-
-void
-dosegment(long foff, int len)
-{
-	int l, n;
-	uchar buf[2*Recordsize];
-
-	Bseek(&bio, foff, 0);
-	for(;;) {
-		l = len;
-		if(l > Recordsize)
-			l = Recordsize;
-		n = Bread(&bio, buf, l);
-		if(n == 0)
-			break;
-		if(n < 0) {
-			fprint(2, "ms2: read error: %r\n");
-			exits("read");
-		}
-		record(buf, l);
-		len -= l;
-	}
-}
-
-void
-record(uchar *s, int l)
-{
-	int i;
-	ulong cksum;
-
-	if(addr4 || addr & (0xFF<<24)){
-		Bprint(&stdout, "S3%.2X%.8luX", l+5, addr);
-		cksum = l+5;
-		cksum += (addr>>24)&0xff;
-	}else{
-		Bprint(&stdout, "S2%.2X%.6X", l+4, addr);
-		cksum = l+4;
-	}
-	cksum += addr&0xff;
-	cksum += (addr>>8)&0xff;
-	cksum += (addr>>16)&0xff;
-
-	for(i = 0; i < l; i++) {
-		cksum += *s;
-		Bprint(&stdout, "%.2X", *s++);
-	}
-	Bprint(&stdout, "%.2X\n", (~cksum)&0xff);
-	addr += l;
-}
-
-void
-trailer(ulong a)
-{
-	ulong cksum;
-
-	cksum = 0;
-	if(addr4 || a & (0xFF<<24)){
-		Bprint(&stdout, "S7%.8luX", a);
-		cksum += (a>>24)&0xff;
-	}else
-		Bprint(&stdout, "S9%.6X", a);
-	cksum += a&0xff;
-	cksum += (a>>8)&0xff;
-	cksum += (a>>16)&0xff;
-	Bprint(&stdout, "%.2X\n", (~cksum)&0xff);
-}
-
-void
-usage(void)
-{
-	fprint(2, "usage: ms2 [-ds] [-a address] [-p pagesize] ?.out\n");
-	exits("usage");
-}
--- a/os/boot/rpcg/plan9boot.c
+++ /dev/null
@@ -1,96 +1,0 @@
-#include	"u.h"
-#include	"lib.h"
-#include	"mem.h"
-#include	"dat.h"
-#include	"fns.h"
-
-char *premature = "premature EOF\n";
-
-/*
- *  read in a segment
- */
-static long
-readseg(int dev, long (*read)(int, void*, long), long len, long addr)
-{
-	char *a;
-	long n, sofar;
-
-	a = (char *)addr;
-	for(sofar = 0; sofar < len; sofar += n){
-		n = 8*1024;
-		if(len - sofar < n)
-			n = len - sofar;
-		n = (*read)(dev, a + sofar, n);
-		if(n <= 0)
-			break;
-		print(".");
-	}
-	return sofar;
-}
-
-/*
- *  boot
- */
-int
-plan9boot(int dev, long (*seek)(int, long), long (*read)(int, void*, long))
-{
-	long n;
-	long addr;
-	void (*b)(void);
-	Exec *ep;
-
-	if((*seek)(dev, 0) < 0)
-		return -1;
-
-	/*
-	 *  read header
-	 */
-	ep = (Exec *) ialloc(sizeof(Exec), 0);
-	n = sizeof(Exec);
-	if(readseg(dev, read, n, (long) ep) != n){
-		print(premature);
-		return -1;
-	}
-	if(GLLONG(ep->magic) != Q_MAGIC){
-		print("bad magic 0x%lux not a plan 9 executable!\n", GLLONG(ep->magic));
-		return -1;
-	}
-
-	/*
-	 *  read text
-	 */
-	addr = PADDR(GLLONG(ep->entry));
-	n = GLLONG(ep->text);
-	print("%d", n);
-	if(readseg(dev, read, n, addr) != n){
-		print(premature);
-		return -1;
-	}
-
-	/*
-	 *  read data (starts at first page after kernel)
-	 */
-	addr = PGROUND(addr+n);
-	n = GLLONG(ep->data);
-	print("+%d@%8.8lux", n, addr);
-	if(readseg(dev, read, n, addr) != n){
-		print(premature);
-		return -1;
-	}
-
-	/*
-	 *  bss and entry point
-	 */
-	print("+%d\nstart at 0x%lux\n", GLLONG(ep->bss), GLLONG(ep->entry));
-	uartwait();
-	scc2stop();
-	splhi();
-
-	/*
-	 *  Go to new code. It's up to the program to get its PC relocated to
-	 *  the right place.
-	 */
-	b = (void (*)(void))(PADDR(GLLONG(ep->entry)));
-	(*b)();
-	return 0;
-}
binary files a/os/boot/rpcg/qbromrpcg /dev/null differ
--- a/os/boot/rpcg/qio.c
+++ /dev/null
@@ -1,128 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-struct Queue {
-	Block*	first;
-	Block*	last;
-	void	(*kick)(void*);
-	void*	arg;
-	long	len;
-};
-
-Block *
-iallocb(int n)
-{
-	Block *b;
-
-	b = (Block*)malloc(sizeof(Block)+n);
-	b->data = (uchar*)b + sizeof(Block);
-	b->rp = b->wp = b->data;
-	b->lim = b->data + n;
-	b->next = 0;
-	b->magic = 0xcafebee0;
-	return b;
-}
-
-void
-freeb(Block *b)
-{
-	if(b){
-		if(b->magic != 0xcafebee0)
-			panic("freeb");
-		b->magic = 0;
-		b->next = (Block*)0xdeadbabe;
-		free(b);
-	}
-}
-
-Queue *
-qopen(int limit, int msg, void (*kick)(void*), void *arg)
-{
-	Queue *q;
-
-	USED(limit, msg);
-	q = (Queue*)malloc(sizeof(Queue));
-	q->first = q->last = 0;
-	q->kick = kick;
-	q->arg = arg;
-	q->len = 0;
-	return q;
-}
-
-Block *
-qget(Queue *q)
-{
-	int s;
-	Block *b;
-
-	s = splhi();
-	if((b = q->first) != 0){
-		q->first = b->next;
-		b->next = 0;
-		q->len -= BLEN(b);
-		if(q->len < 0)
-			panic("qget");
-	}
-	splx(s);
-	return b;
-}
-
-void
-qbwrite(Queue *q, Block *b)
-{
-	int s;
-
-	s = splhi();
-	b->next = 0;
-	if(q->first == 0)
-		q->first = b;
-	else
-		q->last->next = b;
-	q->last = b;
-	q->len += BLEN(b);
-	splx(s);
-	if(q->kick)
-		q->kick(q->arg);
-}
-
-long
-qlen(Queue *q)
-{
-	return q->len;
-}
-
-int
-qbgetc(Queue *q)
-{
-	Block *b;
-	int s, c;
-
-	c = -1;
-	s = splhi();
-	while(c < 0 && (b = q->first) != nil){
-		if(b->rp < b->wp){
-			c = *b->rp++;
-			q->len--;
-		}
-		if(b->rp >= b->wp){
-			q->first = b->next;
-			b->next = nil;
-		}
-	}
-	splx(s);
-	return c;
-}
-
-void
-qbputc(Queue *q, int c)
-{
-	Block *b;
-
-	b = iallocb(1);
-	*b->wp++ = c;
-	qbwrite(q, b);
-}
--- a/os/boot/rpcg/rmap.c
+++ /dev/null
@@ -1,104 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-
-void
-mapinit(RMap *rmap, Map *map, int size)
-{
-	lock(rmap);
-	rmap->map = map;
-	rmap->mapend = map+(size/sizeof(Map));
-	unlock(rmap);
-}
-
-void
-mapfree(RMap* rmap, ulong addr, int size)
-{
-	Map *mp;
-	ulong t;
-
-	if(size <= 0)
-		return;
-
-	lock(rmap);
-	for(mp = rmap->map; mp->addr <= addr && mp->size; mp++)
-		;
-
-	if(mp > rmap->map && (mp-1)->addr+(mp-1)->size == addr){
-		(mp-1)->size += size;
-		if(addr+size == mp->addr){
-			(mp-1)->size += mp->size;
-			while(mp->size){
-				mp++;
-				(mp-1)->addr = mp->addr;
-				(mp-1)->size = mp->size;
-			}
-		}
-	}
-	else{
-		if(addr+size == mp->addr && mp->size){
-			mp->addr -= size;
-			mp->size += size;
-		}
-		else do{
-			if(mp >= rmap->mapend){
-				print("mapfree: %s: losing 0x%uX, %d\n",
-					rmap->name, addr, size);
-				break;
-			}
-			t = mp->addr;
-			mp->addr = addr;
-			addr = t;
-			t = mp->size;
-			mp->size = size;
-			mp++;
-		}while(size = t);
-	}
-	unlock(rmap);
-}
-
-ulong
-mapalloc(RMap* rmap, ulong addr, int size, int align)
-{
-	Map *mp;
-	ulong maddr, oaddr;
-
-	lock(rmap);
-	for(mp = rmap->map; mp->size; mp++){
-		maddr = mp->addr;
-
-		if(addr){
-			if(maddr > addr)
-				continue;
-			if(addr+size > maddr+mp->size)
-				break;
-			maddr = addr;
-		}
-
-		if(align > 0)
-			maddr = ((maddr+align-1)/align)*align;
-		if(mp->addr+mp->size-maddr < size)
-			continue;
-
-		oaddr = mp->addr;
-		mp->addr = maddr+size;
-		mp->size -= maddr-oaddr+size;
-		if(mp->size == 0){
-			do{
-				mp++;
-				(mp-1)->addr = mp->addr;
-			}while((mp-1)->size = mp->size);
-		}
-
-		unlock(rmap);
-		if(oaddr != maddr)
-			mapfree(rmap, oaddr, maddr-oaddr);
-
-		return maddr;
-	}
-	unlock(rmap);
-
-	return 0;
-}
--- a/os/boot/rpcg/screen.c
+++ /dev/null
@@ -1,242 +1,0 @@
-#include	"all.h"
-#include	<libg.h>
-#include	<gnot.h>
-
-enum {
-	Colldepth		= 3,
-	Colmaxx		= 640,
-	Colmaxxvis	= 640,
-	Colmaxy		= 480,
-};
-
-#define	MINX	8
-
-extern	GSubfont	defont0;
-
-struct{
-	Point	pos;
-	int	bwid;
-}out;
-
-typedef struct Mode Mode;
-struct Mode {
-	int	x;
-	int	y;
-	int	d;
-	char*	aperture;
-	int	apsize;
-};
-
-GBitmap	gscreen;
-Point	gchar(GBitmap*, Point, GFont*, int, Fcode);
-int	setcolor(ulong, ulong, ulong, ulong);
-static	void	lcdinit(Mode*);
-
-void
-screeninit(void)
-{
-	Mode m;
-
-	m.x = Colmaxx;
-	m.y = Colmaxy;
-	m.d = Colldepth;
-	m.aperture = 0;
-	lcdinit(&m);
-	if(m.aperture == 0)
-		return;
-	gscreen.ldepth = 3;
-	gscreen.base = (ulong*)m.aperture;
-	gscreen.width = Colmaxx/BY2WD;
-	gscreen.r = Rect(0, 0, Colmaxxvis, Colmaxy);
-	gscreen.clipr = gscreen.r;
-	/*
-	 * For now, just use a fixed colormap:
-	 * 0 == white and 255 == black
-	 */
-	setcolor(0, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF);
-	setcolor(255, 0x00000000, 0x00000000, 0x00000000);
-
-	gbitblt(&gscreen, Pt(0, 0), &gscreen, gscreen.r, Zero);
-	out.pos.x = MINX;
-	out.pos.y = 0;
-	out.bwid = defont0.info[' '].width;
-}
-
-void
-screenputc(int c)
-{
-	Fontchar *i;
-	Point p;
-
-	if(gscreen.base == nil)
-		return;
-	switch(c){
-	case '\n':
-		out.pos.x = MINX;
-		out.pos.y += defont0.height;
-		if(out.pos.y > gscreen.r.max.y-defont0.height)
-			out.pos.y = gscreen.r.min.y;
-		gbitblt(&gscreen, Pt(0, out.pos.y), &gscreen,
-		  Rect(0, out.pos.y, gscreen.r.max.x, out.pos.y+2*defont0.height),
-		  Zero);
-		break;
-	case '\t':
-		out.pos.x += (8-((out.pos.x-MINX)/out.bwid&7))*out.bwid;
-		if(out.pos.x >= gscreen.r.max.x)
-			screenputc('\n');
-		break;
-	case '\b':
-		if(out.pos.x >= out.bwid+MINX){
-			out.pos.x -= out.bwid;
-			screenputc(' ');
-			out.pos.x -= out.bwid;
-		}
-		break;
-	default:
-		if(out.pos.x >= gscreen.r.max.x-out.bwid)
-			screenputc('\n');
-		c &= 0x7f;
-		if(c <= 0 || c >= defont0.n)
-			break;
-		i = defont0.info + c;
-		p = out.pos;
-		gbitblt(&gscreen, Pt(p.x+i->left, p.y), defont0.bits,
-			Rect(i[0].x, 0, i[1].x, defont0.height),
-			S);
-		out.pos.x = p.x + i->width;
-		break;
-	}
-}
-
-void
-screenputs(char *s, int n)
-{
-	while(n-- > 0)
-		screenputc(*s++);
-}
-
-/*
- * See section 5.2.1 (page 5-6) of the MPC823 manual
- */
-static uchar lcdclock[17] = {	/* (a<<2)|b => divisor of (1<<a)*((b<<1)+1) */
-	0, 0, (1<<2), 1,
-	(2<<2), 2, (1<<2)|1, 3,
-	(3<<2), (1<<2)|2, (1<<2)|2, (2<<2)|1,
-	(2<<2)|1, (1<<2)|3, (1<<2)|3, (4<<2),
-	(4<<2)
-};
-	
-/*
- * support for the Sharp LQ64D341 TFT colour display
- */
-
-enum {
-	COLS = 640,
-	ROWS = 480,
-	LDEPTH = 3,	/* screen depth */
-	LCDFREQ = 25000000,
-
-	/* lccr */
-	ClockLow = 1<<11,
-	OELow = 1<<10,
-	HsyncLow = 1<<9,
-	VsyncLow = 1<<8,
-	DataLow = 1<<7,
-	Passive8 = 1<<4,
-	DualScan = 1<<3,
-	IsColour = 1<<2,
-	IsTFT = 1<<1,
-	Enable = 1<<0,
-
-	/* lchcr */
-	BigEndian = 1<<24,
-	AT7 = 7<<21,	/* access type */
-
-	/* sdcr */
-	LAM = 1<<6,	/* ``LCD aggressive mode'' */
-};
-
-/*
- * TO DO: most of the data could come from a table
- */
-static void
-lcdinit(Mode *mode)
-{
-	IMM *io;
-	int i, d;
-	long hz;
-
-	io = m->iomem;
-	mode->y = ROWS;
-	mode->x = COLS;
-	mode->d = LDEPTH;
-	mode->aperture = ialloc(mode->x*mode->y, 16);
-	mode->apsize = mode->x*mode->y;
-
-	io->sdcr &= ~LAM;	/* MPC823 errata: turn off LAM before disabling controller */
-	io->lcfaa = PADDR(mode->aperture);
-	io->lccr = (((mode->x*mode->y*(1<<LDEPTH)+127)/128) << 17) | (LDEPTH << 5) | IsColour | IsTFT | OELow | VsyncLow | ClockLow;
-
-	switch(LDEPTH){
-	default:
-	case 0:
-		/* monochrome/greyscale identity map */
-		for(i=0; i<16; i++)
-			io->lcdmap[i] = i;
-		break;
-	case 2:
-		/* 4-bit grey scale map */
-		for(i=0; i<16; i++)
-			io->lcdmap[0] = (i<<8)|(i<<4)|i;
-		break;
-	case 3:
-		/* 8-bit linear map */
-		for(i=0; i<256; i++)
-			io->lcdmap[i] = (i<<8)|(i<<4)|i;
-		break;
-	}
-
-	io->lcvcr = (mode->y << 11) | (1<<28) | 33;	/* 2 line vsync pulse, 34 line wait between frames */
-	io->lchcr = (mode->x<<10) | BigEndian | 228;	/* clock cycles between lines */
-
-	hz = m->cpuhz;
-	d = hz/LCDFREQ;
-	if(hz/d > LCDFREQ)
-		d++;
-	if(d >= 16)
-		d = 16;
-
-	/*
-	 * enable LCD outputs
-	 */
-	io->pddat = 0;
-	io->pdpar = 0x1fff;
-io->pdpar &= ~SIBIT(6);	/* 823 bug fix? */
-	io->pddir = 0x1fff;
-	io->pbpar |= IBIT(31) | IBIT(19) | IBIT(17);
-	io->pbdir |= IBIT(31) | IBIT(19) | IBIT(17);
-	io->pbodr &= ~(IBIT(31) | IBIT(19) | IBIT(17));
-
-	eieio();
-	io->sccrk = KEEP_ALIVE_KEY;
-	eieio();
-	io->sccr  = (io->sccr & ~0x1F) | lcdclock[d];
-	eieio();
-	io->sccrk = ~KEEP_ALIVE_KEY;
-	eieio();
-	gscreen.width = gscreen.width;	/* access external memory before enabling (mpc823 errata) */
-	io->lcsr = 7;	/* clear status */
-	eieio();
-	io->lccr |= Enable;
-	archbacklight(1);
-}
-
-int
-setcolor(ulong p, ulong r, ulong g, ulong b)
-{
-	r >>= 28;
-	g >>= 28;
-	b >>= 28;
-	m->iomem->lcdmap[~p&0xFF] = (r<<8) | (g<<4) | b;	/* TO DO: it's a function of the ldepth */
-	return 1;
-}
binary files a/os/boot/rpcg/sload /dev/null differ
--- a/os/boot/rpcg/sload.c
+++ /dev/null
@@ -1,71 +1,0 @@
-/*
- * send S records to rpcg
- */
-
-#include <u.h>
-#include <libc.h>
-#include <bio.h>
-
-static	int	dbg;
-static	char	buf[2048];
-static	int	run=1;
-static	void	stuffbym(char*, int, int);
-static	void	getdot(void);
-
-void
-main(int argc, char **argv)
-{
-	int n;
-	char *l;
-	Biobuf *f;
-	static int p;
-
-	ARGBEGIN{
-	case 'd': dbg++; break;
-	case 'n': run=0; break;
-	}ARGEND
-
-	f = Bopen(*argv? *argv: "k.mx", OREAD);
-	if(f == 0) {
-		fprint(2, "sload: cannot open k.mx: %r\n");
-		exits("sload");
-	}
-	getdot();
-	while((l = Brdline(f, '\n')) != 0) {
-		l[Blinelen(f)-1] = '\r';
-		stuffbym(l, Blinelen(f), 16);
-		getdot();
-		if(++p % 25 == 0)
-			write(2, ".", 1);
-	}
-	exits(0);
-}
-
-static void
-stuffbym(char *l, int n, int m)
-{
-	int nr, ns;
-
-	while(n > 0) {
-		ns = n;
-		if(ns > m)
-			ns = m;
-		write(1, l, ns);
-		l += ns;
-		n -= ns;
-	}
-}
-
-static void
-getdot(void)
-{
-	char c;
-
-	for(;;){
-		if(read(0, &c, 1) != 1)
-			exits("bang");
-		write(2, &c, 1);
-		if(c == '.')
-			break;
-	}
-}
--- a/os/boot/rpcg/squeeze.h
+++ /dev/null
@@ -1,34 +1,0 @@
-
-/*
- * squeezed file format:
- *	Sqhdr
- *	original Exec header
- *	two Squeeze tables
- *	squeezed segment
- *	unsqueezed segment, if any
- */
-#define	SQMAGIC	(ulong)0xFEEF0F1E
-
-typedef struct Sqhdr Sqhdr;
-struct Sqhdr {
-	uchar	magic[4];	/* SQMAGIC */
-	uchar	text[4];	/* squeezed length of text (excluding tables) */
-	uchar	data[4];	/* squeezed length of data (excluding tables) */
-	uchar	asis[4];	/* length of unsqueezed segment */
-	uchar	toptxt[4];	/* value for 0 encoding in text */
-	uchar	topdat[4];	/* value for 0 encoding in data */
-	uchar	sum[4];	/* simple checksum of unsqueezed data */
-	uchar	flags[4];
-};
-#define	SQHDRLEN	(8*4)
-
-/*
- * certain power instruction types are rearranged by sqz
- * so as to move the variable part of the instruction word to the
- * low order bits.  note that the mapping is its own inverse.
- */
-#define	QREMAP(X)\
-	switch((X)>>26){\
-	case 19: case 31: case 59: case 63:\
-		(X) = (((X) & 0xFC00F801) | (((X)>>15)&0x7FE) | (((X)&0x7FE)<<15));\
-	}
--- a/os/boot/rpcg/trap.c
+++ /dev/null
@@ -1,233 +1,0 @@
-#include "boot.h"
-
-enum 
-{
-	Maxhandler=	32+16,		/* max number of interrupt handlers */
-};
-
-typedef struct Handler	Handler;
-struct Handler
-{
-	void	(*r)(Ureg*, void*);
-	void	*arg;
-	Handler	*next;
-	int	edge;
-};
-
-struct
-{
-	Handler	*ivec[128];
-	Handler	h[Maxhandler];
-	int	free;
-} halloc;
-
-char	*excname[] = {
-	"reserved 0",
-	"system reset",
-	"machine check",
-	"data access",
-	"instruction access",
-	"external interrupt",
-	"alignment",
-	"program exception",
-	"floating-point unavailable",
-	"decrementer",
-	"reserved A",
-	"reserved B",
-	"system call",
-	"trace trap",
-	"floating point assist",
-	"reserved F",
-	"software emulation",
-	"ITLB miss",
-	"DTLB miss",
-	"ITLB error",
-	"DTLB error",
-};
-
-char *regname[]={
-	"CAUSE",	"SRR1",
-	"PC",		"GOK",
-	"LR",		"CR",
-	"XER",	"CTR",
-	"R0",		"R1",
-	"R2",		"R3",
-	"R4",		"R5",
-	"R6",		"R7",
-	"R8",		"R9",
-	"R10",	"R11",
-	"R12",	"R13",
-	"R14",	"R15",
-	"R16",	"R17",
-	"R18",	"R19",
-	"R20",	"R21",
-	"R22",	"R23",
-	"R24",	"R25",
-	"R26",	"R27",
-	"R28",	"R29",
-	"R30",	"R31",
-};
-
-static	void	intr(Ureg*);
-
-void
-sethvec(int v, void (*r)(void))
-{
-	ulong *vp, pa, o;
-
-	if((ulong)r & 3)
-		panic("sethvec");
-	vp = (ulong*)KADDR(v);
-	vp[0] = 0x7c1043a6;	/* MOVW R0, SPR(SPRG0) */
-	vp[1] = 0x7c0802a6;	/* MOVW LR, R0 */
-	vp[2] = 0x7c1243a6;	/* MOVW R0, SPR(SPRG2) */
-	pa = PADDR(r);
-	o = pa >> 25;
-	if(o != 0 && o != 0x7F){
-		/* a branch too far: running from ROM */
-		vp[3] = (15<<26)|(pa>>16);	/* MOVW $r&~0xFFFF, R0 */
-		vp[4] = (24<<26)|(pa&0xFFFF);	/* OR $r&0xFFFF, R0 */
-		vp[5] = 0x7c0803a6;	/* MOVW	R0, LR */
-		vp[6] = 0x4e800021;	/* BL (LR) */
-	}else
-		vp[3] = (18<<26)|(pa&0x3FFFFFC)|3;	/* bla */
-}
-
-#define	LEV(n)	(((n)<<1)|1)
-#define	IRQ(n)	(((n)<<1)|0)
-
-void
-setvec(int v, void (*r)(Ureg*, void*), void *arg)
-{
-	Handler *h;
-	IMM *io;
-
-	if(halloc.free >= Maxhandler)
-		panic("out of interrupt handlers");
-	v -= VectorPIC;
-	h = &halloc.h[halloc.free++];
-	h->next = halloc.ivec[v];
-	h->r = r;
-	h->arg = arg;
-	halloc.ivec[v] = h;
-
-	/*
-	 * enable corresponding interrupt in SIU/CPM
-	 */
-
-	io = m->iomem;
-	if(v >= VectorCPIC){
-		v -= VectorCPIC;
-		io->cimr |= 1<<(v&0x1F);
-	}
-	else if(v >= VectorIRQ)
-		io->simask |= 1<<(31-IRQ(v&7));
-	else
-		io->simask |= 1<<(31-LEV(v));
-}
-
-void
-trapinit(void)
-{
-	int i;
-	IMM *io;
-
-	io = m->iomem;
-	io->sypcr &= ~(3<<2);	/* disable watchdog (821/823) */
-	io->simask = 0;	/* mask all */
-	io->siel = ~0;	/* edge sensitive, wake on all */
-	io->cicr = 0;	/* disable CPM interrupts */
-	io->cipr = ~0;	/* clear all interrupts */
-	io->cimr = 0;	/* mask all events */
-	io->cicr = (0xE1<<16)|(CPIClevel<<13)|(0x1F<<8);
-	io->cicr |= 1 << 7;	/* enable */
-	io->tbscrk = KEEP_ALIVE_KEY;
-	io->tbscr = 1;	/* TBE */
-	io->simask |= 1<<(31-LEV(CPIClevel));	/* CPM's level */
-	io->tbk = KEEP_ALIVE_KEY;
-	eieio();
-	putdec(~0);
-
-	/*
-	 * set all exceptions to trap
-	 */
-	for(i = 0x0; i < 0x3000; i += 0x100)
-		sethvec(i, exception);
-}
-
-void
-dumpregs(Ureg *ur)
-{
-	int i;
-	ulong *l;
-	l = &ur->cause;
-	for(i=0; i<sizeof regname/sizeof(char*); i+=2, l+=2)
-		print("%s\t%.8lux\t%s\t%.8lux\n", regname[i], l[0], regname[i+1], l[1]);
-}
-
-void
-trap(Ureg *ur)
-{
-	int c;
-
-	c = ur->cause >> 8;
-	switch(c){
-	default:
-		{extern int predawn; predawn = 1;}
-		if(c < 0 || c >= nelem(excname))
-			print("exception/interrupt #%x\n", c);
-		else
-			print("exception %s\n", excname[c]);
-		dumpregs(ur);
-		/* spllo(); */
-		print("^P to reset\n");
-		for(;;)
-			;
-
-	case 0x09:	/* decrementer */
-		clockintr(ur, 0);
-		return;
-
-	case 0x05:	/* external interrupt */
-		intr(ur);
-		break;
-	}
-}
-
-static void
-intr(Ureg *ur)
-{
-	int b, v;
-	Handler *h;
-	IMM *io;
-
-	io = m->iomem;
-	b = io->sivec>>2;
-	v = b>>1;
-	if(b & 1) {
-		if(v == CPIClevel){
-			io->civr = 1;
-			eieio();
-			v = VectorCPIC+(io->civr>>11);
-		}
-	}else
-		v += VectorIRQ;
-	h = halloc.ivec[v];
-	if(h == nil){
-		for(;;)
-			;
-		//print("unknown interrupt %d pc=0x%lux\n", v, ur->pc);
-		return;
-	}
-	if(h->edge)
-		io->sipend |= 1<<(31-b);
-	/*
-	 *  call the interrupt handlers
-	 */
-	do {
-		(*h->r)(ur, h->arg);
-		h = h->next;
-	} while(h != nil);
-	if(v >= VectorCPIC)
-		io->cisr |= 1<<(v-VectorCPIC);
-}
--- a/os/boot/rpcg/uartboot.c
+++ /dev/null
@@ -1,189 +1,0 @@
-#include "boot.h"
-
-/*
- * this doesn't yet use the crc
- */
-
-typedef struct Uboot Uboot;
-struct Uboot {
-	Queue*	iq;
-	Block*	partial;
-	ulong	csum;
-	long	bno;
-	uchar	buf[64];
-	int	nleft;
-	int	ntimeout;
-};
-
-static	Uboot	uboot;
-ulong	crc32(void *buf, int n, ulong crc);
-
-static void
-uartbrecv(uchar *p, int n)
-{
-	Uboot *ub;
-	Block *b;
-
-	ub = &uboot;
-	if(n > 0 && ub->iq != nil){
-		b = iallocb(n);
-		memmove(b->wp, p, n);
-		b->wp += n;
-		qbwrite(ub->iq, b);
-	}
-}
-
-int
-uartinit(void)
-{
-	return 1<<0;
-}
-
-Partition*
-setuartpart(int, char *s)
-{
-	static Partition pp[1];
-
-	if(strcmp(s, "boot") != 0 && strcmp(s, "disk") != 0)
-		return 0;
-	pp[0].start = 0;
-	pp[0].end = 2*1024*1024;
-	strcpy(pp[0].name, "boot");
-	return pp;
-}
-
-long
-uartseek(int, long)
-{
-	/* start the boot */
-	if(uboot.iq == nil)
-		uboot.iq = qopen(64*1024, 0, 0, 0);
-	if(uboot.partial){
-		freeb(uboot.partial);
-		uboot.partial = 0;
-	}
-	print("uart: start transmission\n");
-	uartsetboot(uartbrecv);
-	uboot.csum = ~0;
-	uboot.bno = 0;
-	uboot.nleft = 0;
-	uboot.ntimeout = 0;
-	return 0;
-}
-
-static long
-uartreadn(void *buf, int nb)
-{
-	ulong start;
-	Uboot *ub;
-	int l;
-	Block *b;
-	uchar *p;
-
-	p = buf;
-	ub = &uboot;
-	start = m->ticks;
-	while(nb > 0){
-		b = ub->partial;
-		ub->partial = nil;
-		if(b == nil){
-			ub->ntimeout = 0;
-			while((b = qget(ub->iq)) == 0){
-				if(TK2MS(m->ticks - start) >= 15*1000){
-					if(++ub->ntimeout >= 3){
-						print("uart: timeout\n");
-						return 0;
-					}
-					uartputs("n", 1);
-				}
-			}
-		}
-		l = BLEN(b);
-		if(l > nb)
-			l = nb;
-		memmove(p, b->rp, l);
-		b->rp += l;
-		if(b->rp >= b->wp)
-			freeb(b);
-		else
-			ub->partial = b;
-		nb -= l;
-		p += l;
-	}
-	return p-(uchar*)buf;
-}
-
-long
-uartread(int, void *buf, long n)
-{
-	uchar *p;
-	int l;
-	static uchar lbuf[64];
-
-	p = buf;
-	if((l = uboot.nleft) > 0){
-		if(l > n)
-			l = n;
-		uboot.nleft -= l;
-		memmove(p, uboot.buf, l);
-		p += l;
-		n -= l;
-	}
-	while(n > 0){
-		l = uartreadn(lbuf, sizeof(lbuf));
-		if(l < sizeof(lbuf))
-			return 0;
-		if(l > n){
-			uboot.nleft = l-n;
-			memmove(uboot.buf, lbuf+n, uboot.nleft);
-			l = n;
-		}
-		memmove(p, lbuf, l);
-		n -= l;
-		p += l;
-		uboot.bno++;
-		uartputs("y", 1);
-	}
-	return p-(uchar*)buf;
-}
-
-/*
- * from Rob Warnock
- */
-static	ulong	crc32tab[256];	/* initialised on first call to crc32 */
-
-enum {
-	CRC32POLY = 0x04c11db7     /* AUTODIN II, Ethernet, & FDDI */
-};
-
-/*
- * Build auxiliary table for parallel byte-at-a-time CRC-32.
- */
-static void
-initcrc32(void)
-{
-	int i, j;
-	ulong c;
-
-	for(i = 0; i < 256; i++) {
-		for(c = i << 24, j = 8; j > 0; j--)
-			if(c & (1<<31))
-				c = (c<<1) ^ CRC32POLY;
-			else
-				c <<= 1;
-		crc32tab[i] = c;
-	}
-}
-
-ulong
-crc32(void *buf, int n, ulong crc)
-{
-	uchar *p;
-
-	if(crc32tab[1] == 0)
-		initcrc32();
-	crc = ~crc;
-	for(p = buf; --n >= 0;)
-		crc = (crc << 8) ^ crc32tab[(crc >> 24) ^ *p++];
-	return ~crc;
-}
--- a/os/boot/rpcg/ureg.h
+++ /dev/null
@@ -1,43 +1,0 @@
-struct Ureg
-{
-	ulong	cause;
-	union { ulong	srr1; ulong status;};
-	ulong	pc;	/* SRR0 */
-	ulong	pad;
-	ulong	lr;
-	ulong	cr;
-	ulong	xer;
-	ulong	ctr;
-	ulong	r0;
-	union{ ulong r1;	ulong	sp;	ulong	usp; };
-	ulong	r2;
-	ulong	r3;
-	ulong	r4;
-	ulong	r5;
-	ulong	r6;
-	ulong	r7;
-	ulong	r8;
-	ulong	r9;
-	ulong	r10;
-	ulong	r11;
-	ulong	r12;
-	ulong	r13;
-	ulong	r14;
-	ulong	r15;
-	ulong	r16;
-	ulong	r17;
-	ulong	r18;
-	ulong	r19;
-	ulong	r20;
-	ulong	r21;
-	ulong	r22;
-	ulong	r23;
-	ulong	r24;
-	ulong	r25;
-	ulong	r26;
-	ulong	r27;
-	ulong	r28;
-	ulong	r29;
-	ulong	r30;
-	ulong	r31;
-};
--- a/os/boot/rpcg/zqs.c
+++ /dev/null
@@ -1,234 +1,0 @@
-#include "boot.h"
-#include "squeeze.h"
-
-/*
- * for details of `unsqueeze' see:
- *
- * %A Mark Taunton
- * %T Compressed Executables: An Exercise in Thinking Small
- * %P 385-404
- * %I USENIX
- * %B USENIX Conference Proceedings
- * %D Summer 1991
- * %C Nashville, TN
- *
- * several of the unimplemented improvements described in the paper
- * have been implemented here
- *
- * there is a further transformation on the powerpc (QFLAG!=0) to shuffle bits
- * in certain instructions so as to push the fixed bits to the top of the word.
- */
-
-#define	EXECHDRLEN	(8*4)
-
-typedef struct Squeeze Squeeze;
-struct Squeeze {
-	int	n;
-	ulong	tab[7*256];
-};
-
-#define	GET4(p)	(((((((p)[0]<<8)|(p)[1])<<8)|(p)[2])<<8)|(p)[3])
-
-/*
- * for speed of unsqueezing from Flash, certain checks are
- * not done inside the loop (as they would be in the unsqueeze program zqs),
- * but instead the checksum is expected to catch corrupted files.
- * in fact the Squeeze array bounds can't be exceeded in practice
- * because the tables are always full for a squeezed kernel.
- */
-enum {
-	QFLAG = 1,	/* invert powerpc-specific code transformation */
-	CHECK = 0,	/* check precise bounds in Squeeze array (otherwise checksum detects error) */
-};
-
-static	ulong	chksum;
-static	int	rdtab(Block*, Squeeze*, int);
-static	ulong*	unsqueeze(ulong*, uchar*, uchar*, Squeeze*, Squeeze*, ulong);
-static	uchar*	unsqzseg(uchar*, Block*, long, long, char*);
-static	Alarm*	unsqzal;
-
-int
-issqueezed(uchar *b)
-{
-	return GET4(b) == SQMAGIC? GET4(b+SQHDRLEN): 0;
-}
-
-static void
-unsqzdot(Alarm*)
-{
-	unsqzal = alarm(500, unsqzdot, nil);
-	print(".");
-}
-
-long
-unsqueezef(Block *b, ulong *entryp)
-{
-	uchar *loada, *wp;
-	ulong toptxt, topdat, oldsum;
-	long asis, nst, nsd;
-	Sqhdr *sqh;
-	Exec *ex;
-
-	if(BLEN(b) < SQHDRLEN+EXECHDRLEN)
-		return -1;
-	sqh = (Sqhdr*)b->rp;
-	if(GET4(sqh->magic) != SQMAGIC)
-		return -1;
-	chksum = 0;
-	toptxt = GET4(sqh->toptxt);
-	topdat = GET4(sqh->topdat);
-	oldsum = GET4(sqh->sum);
-	asis = GET4(sqh->asis);
-	nst = GET4(sqh->text);
-	nsd = GET4(sqh->data);
-	b->rp += SQHDRLEN;
-	ex = (Exec*)b->rp;
-	if(GET4(ex->magic) != Q_MAGIC){
-		print("zqs: not powerPC executable\n");
-		return -1;
-	}
-	*entryp = GET4(ex->entry);
-	b->rp += EXECHDRLEN;
-	loada = KADDR(PADDR(*entryp));
-	wp = unsqzseg(loada, b, nst, toptxt, "text");
-	if(wp == nil){
-		print("zqs: format error\n");
-		return -1;
-	}
-	if(nsd){
-		wp = (uchar*)PGROUND((ulong)wp);
-		wp = unsqzseg(wp, b, nsd, topdat, "data");
-		if(wp == nil){
-			print("zqs: format error\n");
-			return -1;
-		}
-	}
-	if(asis){
-		memmove(wp, b->rp, asis);
-		wp += asis;
-		b->rp += asis;
-	}
-	if(chksum != oldsum){
-		print("\nsqueezed kernel: checksum error: %8.8lux need %8.8lux\n", chksum, oldsum);
-		return -1;
-	}
-	return wp-loada;
-}
-
-static uchar *
-unsqzseg(uchar *wp, Block *b, long ns, long top, char *what)
-{
-	static Squeeze sq3, sq4;
-
-	print("unpack %s %8.8lux %lud:", what, wp, ns);
-	if(ns == 0)
-		return wp;
-	if(rdtab(b, &sq3, 0) < 0)
-		return nil;
-	if(rdtab(b, &sq4, 8) < 0)
-		return nil;
-	if(BLEN(b) < ns){
-		print(" **size error\n");
-		return nil;
-	}
-	unsqzal = alarm(500, unsqzdot, nil);
-	wp = (uchar*)unsqueeze((ulong*)wp, b->rp, b->rp+ns, &sq3, &sq4, top);
-	cancel(unsqzal);
-	unsqzal = nil;
-	print("\n");
-	if(wp == nil){
-		print("zqs: corrupt squeezed data stream\n");
-		return nil;
-	}
-	b->rp += ns;
-	return wp;
-}
-
-static ulong*
-unsqueeze(ulong *wp, uchar *rp, uchar *ep, Squeeze *sq3, Squeeze *sq4, ulong top)
-{
-	ulong nx, csum;
-	int code, n;
-
-	if(QFLAG){
-		QREMAP(top);	/* adjust top just once, outside the loop */
-	}
-	csum = chksum;
-	while(rp < ep){
-		/* no function calls within this loop for speed */
-		code = *rp;
-		rp++;
-		n = 0;
-		nx = code>>4;
-		do{
-			if(nx == 0){
-				nx = top;
-			}else{
-				if(nx==1){
-					nx = (((((rp[3]<<8)|rp[2])<<8)|rp[1])<<8)|rp[0];
-					rp += 4;
-				}else if(nx <= 8){	/* 2 to 8 */
-					nx = ((nx-2)<<8) | rp[0];
-					if(CHECK && nx >= sq4->n)
-						return nil;	/* corrupted file */
-					nx = sq4->tab[nx] | rp[1];
-					rp += 2;
-				}else{	/* 9 to 15 */
-					nx = ((nx-9)<<8) | rp[0];
-					if(CHECK && nx >= sq3->n)
-						return nil;	/* corrupted file */
-					nx = sq3->tab[nx];
-					rp++;
-				}
-				if(rp > ep)
-					return nil;	/* corrupted file */
-				if(QFLAG){
-					QREMAP(nx);
-				}
-			}
-			*wp = nx;
-			wp++;
-			csum += nx;
-			nx = code & 0xF;
-		}while(++n == 1);
-	}
-	chksum = csum;
-	return wp;
-}
-
-static int
-rdtab(Block *b, Squeeze *sq, int shift)
-{
-	uchar *p, *ep;
-	ulong v, w;
-	int i;
-
-	if(BLEN(b) < 2)
-		return -1;
-	i = (b->rp[0]<<8) | b->rp[1];
-	if(1)
-		print(" T%d", i);
-	b->rp += 2;
-	if((i -= 2) > 0){
-		if(BLEN(b) < i)
-			return -1;
-	}
-	sq->n = 0;
-	p = b->rp;
-	ep = b->rp+i;
-	b->rp += i;
-	v = 0;
-	while(p < ep){
-		w = 0;
-		do{
-			if(p >= ep)
-				return -1;
-			w = (w<<7) | (*p & 0x7F);
-		}while(*p++ & 0x80);
-		v += w;
-		if(0)
-			print("%d %8.8lux %8.8lux\n", sq->n, v, w);
-		sq->tab[sq->n++] = v<<shift;
-	}
-	return 0;
-}
--- /dev/null
+++ b/os/boot.original/README
@@ -1,0 +1,33 @@
+Often the devices we use now come with some
+form of bootstrap (often annoyingly complicated,
+which gets in the way).  Older boards were sometimes
+bare, and we had to provide something (often annoyingly
+complicated...).  On the PC it's currently helpful to
+have something that can boot from disc or ether;
+since it's a thankless task to write such a thing, we
+use Plan 9's, and thank its authors.
+
+The current scheme on newer devices is to have a simple
+program that can put a stripped-down Inferno kernel into
+flash, and use that to boot from other devices (including over the net)
+as required during development.
+
+There are two distinct models for bootstrap in this directory.
+
+	Model I
+
+Each member of the first model is represented by a self-contained directory.
+They are derived from various ages of Plan 9's /sys/src/boot/pc.
+
+arm1110	arm	a prefix to a gzip'd kernel to decompress it (runs after basic bootloader)
+pc	386	pc-specific bootstrap essentially identical to current Plan 9
+		and covered by the Lucent Public License; it uses
+libflate	-	zlib-style inflate/deflate library
+mpc	power	PowerPC bootstrap for FADS board derived from an older version
+		of Plan 9 but covered by our Inferno licence (because it came with Inferno)
+puma	arm	SA110 bootstrap for Teralogics Puma, also covered by the Inferno licence
+
+	Model II
+omap	purpose-built bootstrap for the OMAP processor
+
+Not all of these are being distributed.
--- /dev/null
+++ b/os/boot.original/arm1110/Mk
@@ -1,0 +1,8 @@
+#!/bin/rc
+rfork ne
+ROOT=/usr/inferno
+fn cd
+NPROC=3
+path=(/usr/inferno/Plan9/$cputype/bin $path)
+#bind /usr/inferno/mkconfig.dist /usr/inferno/mkconfig
+exec mk $*
--- /dev/null
+++ b/os/boot.original/arm1110/dat.h
@@ -1,0 +1,1 @@
+/* deliberately empty */
--- /dev/null
+++ b/os/boot.original/arm1110/donprint.c
@@ -1,0 +1,332 @@
+#include	"u.h"
+#include	"lib.h"
+
+#define	PTR	sizeof(char*)
+#define	SHORT	sizeof(int)
+#define	INT	sizeof(int)
+#define	LONG	sizeof(long)
+#define	IDIGIT	30
+#define	MAXCON	30
+
+#define	FLONG	(1<<0)
+#define	FSHORT	(1<<1)
+#define	FUNSIGN	(1<<2)
+
+typedef struct Op	Op;
+struct Op
+{
+	char	*p;
+	char	*ep;
+	void	*argp;
+	int	f1;
+	int	f2;
+	int	f3;
+};
+
+static	int	noconv(Op*);
+static	int	cconv(Op*);
+static	int	dconv(Op*);
+static	int	hconv(Op*);
+static	int	lconv(Op*);
+static	int	oconv(Op*);
+static	int	sconv(Op*);
+static	int	uconv(Op*);
+static	int	xconv(Op*);
+static	int	Xconv(Op*);
+static	int	percent(Op*);
+
+static
+int	(*fmtconv[MAXCON])(Op*) =
+{
+	noconv,
+	cconv, dconv, hconv, lconv,
+	oconv, sconv, uconv, xconv,
+	Xconv, percent,
+};
+static
+char	fmtindex[128] =
+{
+	['c'] 1,
+	['d'] 2,
+	['h'] 3,
+	['l'] 4,
+	['o'] 5,
+	['s'] 6,
+	['u'] 7,
+	['x'] 8,
+	['X'] 9,
+	['%'] 10,
+};
+
+static	int	convcount  = { 11 };
+static	int	ucase;
+
+static void
+PUT(Op *o, int c)
+{
+	static int pos;
+	int opos;
+
+	if(c == '\t'){
+		opos = pos;
+		pos = (opos+8) & ~7;
+		while(opos++ < pos && o->p < o->ep)
+			*o->p++ = ' ';
+		return;
+	}
+	if(o->p < o->ep){
+		*o->p++ = c;
+		pos++;
+	}
+	if(c == '\n')
+		pos = 0;
+}
+
+int
+fmtinstall(char c, int (*f)(Op*))
+{
+
+	c &= 0177;
+	if(fmtindex[c] == 0) {
+		if(convcount >= MAXCON)
+			return 1;
+		fmtindex[c] = convcount++;
+	}
+	fmtconv[fmtindex[c]] = f;
+	return 0;
+}
+
+char*
+donprint(char *p, char *ep, char *fmt, void *argp)
+{
+	int sf1, c;
+	Op o;
+
+	o.p = p;
+	o.ep = ep;
+	o.argp = argp;
+
+loop:
+	c = *fmt++;
+	if(c != '%') {
+		if(c == 0) {
+			if(o.p < o.ep)
+				*o.p = 0;
+			return o.p;
+		}
+		PUT(&o, c);
+		goto loop;
+	}
+	o.f1 = 0;
+	o.f2 = -1;
+	o.f3 = 0;
+	c = *fmt++;
+	sf1 = 0;
+	if(c == '-') {
+		sf1 = 1;
+		c = *fmt++;
+	}
+	while(c >= '0' && c <= '9') {
+		o.f1 = o.f1*10 + c-'0';
+		c = *fmt++;
+	}
+	if(sf1)
+		o.f1 = -o.f1;
+	if(c != '.')
+		goto l1;
+	c = *fmt++;
+	while(c >= '0' && c <= '9') {
+		if(o.f2 < 0)
+			o.f2 = 0;
+		o.f2 = o.f2*10 + c-'0';
+		c = *fmt++;
+	}
+l1:
+	if(c == 0)
+		fmt--;
+	c = (*fmtconv[fmtindex[c&0177]])(&o);
+	if(c < 0) {
+		o.f3 |= -c;
+		c = *fmt++;
+		goto l1;
+	}
+	o.argp = (char*)o.argp + c;
+	goto loop;
+}
+
+void
+strconv(char *o, Op *op, int f1, int f2)
+{
+	int n, c;
+	char *p;
+
+	n = strlen(o);
+	if(f1 >= 0)
+		while(n < f1) {
+			PUT(op, ' ');
+			n++;
+		}
+	for(p=o; c = *p++;)
+		if(f2 != 0) {
+			PUT(op, c);
+			f2--;
+		}
+	if(f1 < 0) {
+		f1 = -f1;
+		while(n < f1) {
+			PUT(op, ' ');
+			n++;
+		}
+	}
+}
+
+int
+numbconv(Op *op, int base)
+{
+	char b[IDIGIT];
+	int i, f, n, r;
+	long v;
+	short h;
+
+	f = 0;
+	switch(op->f3 & (FLONG|FSHORT|FUNSIGN)) {
+	case FLONG:
+		v = *(long*)op->argp;
+		r = LONG;
+		break;
+
+	case FUNSIGN|FLONG:
+		v = *(ulong*)op->argp;
+		r = LONG;
+		break;
+
+	case FSHORT:
+		h = *(int*)op->argp;
+		v = h;
+		r = SHORT;
+		break;
+
+	case FUNSIGN|FSHORT:
+		h = *(int*)op->argp;
+		v = (ushort)h;
+		r = SHORT;
+		break;
+
+	default:
+		v = *(int*)op->argp;
+		r = INT;
+		break;
+
+	case FUNSIGN:
+		v = *(unsigned*)op->argp;
+		r = INT;
+		break;
+	}
+	if(!(op->f3 & FUNSIGN) && v < 0) {
+		v = -v;
+		f = 1;
+	}
+	b[IDIGIT-1] = 0;
+	for(i = IDIGIT-2;; i--) {
+		n = (ulong)v % base;
+		n += '0';
+		if(n > '9'){
+			n += 'a' - ('9'+1);
+			if(ucase)
+				n += 'A'-'a';
+		}
+		b[i] = n;
+		if(i < 2)
+			break;
+		v = (ulong)v / base;
+		if(op->f2 >= 0 && i >= IDIGIT-op->f2)
+			continue;
+		if(v <= 0)
+			break;
+	}
+	if(f)
+		b[--i] = '-';
+	strconv(b+i, op, op->f1, -1);
+	return r;
+}
+
+static	int
+noconv(Op *op)
+{
+
+	strconv("***", op, 0, -1);
+	return 0;
+}
+
+static	int
+cconv(Op *op)
+{
+	char b[2];
+
+	b[0] = *(int*)op->argp;
+	b[1] = 0;
+	strconv(b, op, op->f1, -1);
+	return INT;
+}
+
+static	int
+dconv(Op *op)
+{
+	return numbconv(op, 10);
+}
+
+static	int
+hconv(Op*)
+{
+	return -FSHORT;
+}
+
+static	int
+lconv(Op*)
+{
+	return -FLONG;
+}
+
+static	int
+oconv(Op *op)
+{
+	return numbconv(op, 8);
+}
+
+static	int
+sconv(Op *op)
+{
+	strconv(*(char**)op->argp, op, op->f1, op->f2);
+	return PTR;
+}
+
+static	int
+uconv(Op*)
+{
+	return -FUNSIGN;
+}
+
+static	int
+xconv(Op *op)
+{
+	return numbconv(op, 16);
+}
+
+static	int
+Xconv(Op *op)
+{
+	int r;
+
+	ucase = 1;
+	r = numbconv(op, 16);
+	ucase = 0;
+	return r;
+}
+
+static	int
+percent(Op *op)
+{
+
+	PUT(op, '%');
+	return 0;
+}
--- /dev/null
+++ b/os/boot.original/arm1110/fns.h
@@ -1,0 +1,7 @@
+/*
+ *  functions defined locally
+ */
+extern int	gunzip(uchar *out, int outn, uchar *in, int inn);
+extern void	delay(int ms);
+extern void	serialputs(char *str, int n);
+extern void	draincache(void);
--- /dev/null
+++ b/os/boot.original/arm1110/il.s
@@ -1,0 +1,99 @@
+#include "mem.h"
+/*
+ *  Entered here from Compaq's bootldr.  First relocate to
+ *  the location we're linked for and then copy back the
+ *  decompressed kernel.
+ *
+ *  All 
+ */
+TEXT _start(SB), $-4
+	MOVW	$setR12(SB), R12		/* load the SB */
+	MOVW	$1, R0		/* dance to make 5l think that the magic */
+	MOVW	$1, R1		/* numbers in WORDs below are being used */
+	CMP.S	R0, R1		/* and to align them to where bootldr wants */
+	BEQ	_start2
+	WORD	$0x016f2818	/* magic number to say we are a kernel */
+	WORD	$0xc0008000	/* entry point address */
+	WORD	$0		/* size?, or end of data? */
+
+_start2:
+
+	/* SVC mode, interrupts disabled */
+	MOVW	$(PsrDirq|PsrDfiq|PsrMsvc), R1
+	MOVW	R1, CPSR
+
+	/* disable the MMU */
+	MOVW	$0x130, R1
+	MCR     CpMMU, 0, R1, C(CpControl), C(0x0)
+
+	/* enable caches */
+	MRC	CpMMU, 0, R0, C(CpControl), C(0x0)
+	ORR	$(CpCdcache|CpCicache|CpCwb), R0
+	MCR     CpMMU, 0, R0, C(CpControl), C(0x0)
+
+	/* flush caches */
+	MCR	CpMMU, 0, R0, C(CpCacheFlush), C(0x7), 0
+	/* drain prefetch */
+	MOVW	R0,R0						
+	MOVW	R0,R0
+	MOVW	R0,R0
+	MOVW	R0,R0
+
+	/* drain write buffer */
+	MCR	CpMMU, 0, R0, C(CpCacheFlush), C(0xa), 4
+
+	/* relocate to where we expect to be */
+	MOVW	$(FLATESIZE),R3
+	MOVW	$0xC0008000,R1
+	MOVW	$0xC0200000,R2
+	ADD	R1,R3
+_relloop:
+	MOVW	(R1),R0
+	MOVW	R0,(R2)
+	ADD	$4,R1
+	ADD	$4,R2
+	CMP.S	R1,R3
+	BNE	_relloop
+
+	MOVW	$(MACHADDR+BY2PG), R13		/* stack */
+	SUB	$4, R13				/* link */
+
+	/* jump to where we've been relocated */
+	MOVW	$_relocated(SB),R15
+
+TEXT _relocated(SB),$-4
+	BL	main(SB)
+	BL	exit(SB)
+	/* we shouldn't get here */
+_mainloop:
+	B	_mainloop
+	BL	_div(SB)			/* hack to get _div etc loaded */
+
+TEXT mypc(SB),$-4
+	MOVW	R14,R0
+	RET
+
+TEXT draincache(SB),$-4
+	/* write back any dirty data */
+	MOVW	$0xe0000000,R0
+	ADD	$(8*1024),R0,R1
+_cfloop:
+	MOVW.P	32(R0),R2
+	CMP.S	R0,R1
+	BNE	_cfloop
+	
+	/* drain write buffer and invalidate i&d cache contents */
+	MCR	CpMMU, 0, R0, C(CpCacheFlush), C(0xa), 4
+	MCR	CpMMU, 0, R0, C(CpCacheFlush), C(0x7), 0
+
+	/* drain prefetch */
+	MOVW	R0,R0						
+	MOVW	R0,R0
+	MOVW	R0,R0
+	MOVW	R0,R0
+
+	/* disable caches */
+	MRC	CpMMU, 0, R0, C(CpControl), C(0x0)
+	BIC	$(CpCdcache|CpCicache|CpCwb), R0
+	MCR     CpMMU, 0, R0, C(CpControl), C(0x0)
+	RET
--- /dev/null
+++ b/os/boot.original/arm1110/imain.c
@@ -1,0 +1,48 @@
+#include "u.h"
+#include "lib.h"
+#include "fns.h"
+#include "dat.h"
+#include "mem.h"
+
+void
+main(void)
+{
+	void (*f)(void);
+	ulong *kernel;
+
+	print("inflating kernel\n");
+
+	kernel = (ulong*)(0xc0200000+20*1024);
+	if(gunzip((uchar*)0xc0008000, 2*1024*1024, (uchar*)kernel, FLATESIZE) > 0){
+		f = (void (*)(void))0xc0008010;
+		draincache();
+	} else {
+		print("inflation failed\n");
+		f = nil;
+	}
+	(*f)();
+}
+
+void
+exit(void)
+{
+
+	void (*f)(void);
+
+	delay(1000);
+
+	print("it's a wonderful day to die\n");
+	f = nil;
+	(*f)();
+}
+
+void
+delay(int ms)
+{
+	int i;
+
+	while(ms-- > 0){
+		for(i = 0; i < 1000; i++)
+			;
+	}
+}
--- /dev/null
+++ b/os/boot.original/arm1110/inflate.c
@@ -1,0 +1,208 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include <flate.h>
+
+typedef struct Biobuf	Biobuf;
+
+struct Biobuf
+{
+	uchar *bp;
+	uchar *p;
+	uchar *ep;
+};
+
+static int	header(Biobuf*);
+static int	trailer(Biobuf*, Biobuf*);
+static int	getc(void*);
+static ulong	offset(Biobuf*);
+static int	crcwrite(void *out, void *buf, int n);
+static ulong	get4(Biobuf *b);
+static ulong	Boffset(Biobuf *bp);
+
+/* GZIP flags */
+enum {
+	Ftext=		(1<<0),
+	Fhcrc=		(1<<1),
+	Fextra=		(1<<2),
+	Fname=		(1<<3),
+	Fcomment=	(1<<4),
+
+	GZCRCPOLY	= 0xedb88320UL,
+};
+
+static ulong	*crctab;
+static ulong	crc;
+
+int
+gunzip(uchar *out, int outn, uchar *in, int inn)
+{
+	Biobuf bin, bout;
+	int err;
+
+	crc = 0;
+	crctab = mkcrctab(GZCRCPOLY);
+	err = inflateinit();
+	if(err != FlateOk)
+		print("inflateinit failed: %s\n", flateerr(err));
+
+	bin.bp = bin.p = in;
+	bin.ep = in+inn;
+	bout.bp = bout.p = out;
+	bout.ep = out+outn;
+
+	err = header(&bin);
+	if(err != FlateOk)
+		return err;
+
+	err = inflate(&bout, crcwrite, &bin, getc);
+	if(err != FlateOk)
+		print("inflate failed: %s\n", flateerr(err));
+
+	err = trailer(&bout, &bin);
+	if(err != FlateOk)
+		return err;
+
+	return Boffset(&bout);
+}
+
+static int
+header(Biobuf *bin)
+{
+	int i, flag;
+
+	if(getc(bin) != 0x1f || getc(bin) != 0x8b){
+		print("bad magic\n");
+		return FlateCorrupted;
+	}
+	if(getc(bin) != 8){
+		print("unknown compression type\n");
+		return FlateCorrupted;
+	}
+	
+	flag = getc(bin);
+	
+	/* mod time */
+	get4(bin);
+	
+	/* extra flags */
+	getc(bin);
+	
+	/* OS type */
+	getc(bin);
+
+	if(flag & Fextra)
+		for(i=getc(bin); i>0; i--)
+			getc(bin);
+	
+	/* name */
+	if(flag&Fname)
+		while(getc(bin) != 0)
+			;
+
+	/* comment */
+	if(flag&Fcomment)
+		while(getc(bin) != 0)
+			;
+
+	/* crc16 */
+	if(flag&Fhcrc) {
+		getc(bin);
+		getc(bin);
+	}
+		
+	return FlateOk;
+}
+
+static int
+trailer(Biobuf *bout, Biobuf *bin)
+{
+	/* crc32 */
+	ulong x;
+
+	x = get4(bin);
+	if(crc != x){
+		print("crc mismatch %lux %lux\n", crc, x);
+		return FlateCorrupted;
+	}
+
+	/* length */
+	if(get4(bin) != Boffset(bout)){
+		print("bad output len\n");
+		return FlateCorrupted;
+	}
+	return FlateOk;
+}
+
+static ulong
+get4(Biobuf *b)
+{
+	ulong v;
+	int i, c;
+
+	v = 0;
+	for(i = 0; i < 4; i++){
+		c = getc(b);
+		v |= c << (i * 8);
+	}
+	return v;
+}
+
+static int
+getc(void *in)
+{
+	Biobuf *bp = in;
+
+	if((bp->p - bp->bp) % 10000 == 0)
+		print(".");
+	if(bp->p >= bp->ep)
+		return -1;
+	return *bp->p++;
+}
+
+static ulong
+Boffset(Biobuf *bp)
+{
+	return bp->p - bp->bp;
+}
+
+static int
+crcwrite(void *out, void *buf, int n)
+{
+	Biobuf *bp;
+
+	crc = blockcrc(crctab, crc, buf, n);
+	bp = out;
+	if(n > bp->ep-bp->p)
+		n = bp->ep-bp->p;
+	memmove(bp->p, buf, n);
+	bp->p += n;
+	return n;
+}
+
+#undef malloc
+#undef free
+
+static ulong ibrkp = ~0;
+
+void *
+malloc(ulong n)
+{
+	ulong rv;
+
+	if(ibrkp == ~0)
+		ibrkp = ((ulong)end)+1024*1024;
+	n = (n+3)>>2;
+	n <<= 2;
+	rv = ibrkp;
+	ibrkp += n;
+	return (void*)rv;
+}
+
+void
+free(void *)
+{
+}
--- /dev/null
+++ b/os/boot.original/arm1110/io.h
@@ -1,0 +1,261 @@
+/*
+ *  Definitions for IO devices.  Used only in C.
+ */
+
+enum
+{
+	/* hardware counter frequency */
+	ClockFreq=	3686400,
+};
+
+/*
+ *  IRQ's defined by SA1100
+ */
+enum
+{
+	IRQgpio0=	0,
+	IRQgpio1=	1,
+	IRQgpio2=	2,
+	IRQgpio3=	3,
+	IRQgpio4=	4,
+	IRQgpio5=	5,
+	IRQgpio6=	6,
+	IRQgpio7=	7,
+	IRQgpio8=	8,
+	IRQgpio9=	9,
+	IRQgpio10=	10,
+	IRQgpiohi=	11,
+	IRQlcd=		12,
+	IRQudc=		13,
+	IRQuart1b=	15,
+	IRQuart2=	16,
+	IRQuart3=	17,
+	IRQmcp=		18,
+	IRQssp=		19,
+	IRQdma0=	20,
+	IRQdma1=	21,
+	IRQdma2=	22,
+	IRQdma3=	23,
+	IRQdma4=	24,
+	IRQdma5=	25,
+	IRQtimer0=	26,
+	IRQtimer1=	27,
+	IRQtimer2=	28,
+	IRQtimer3=	29,
+	IRQsecond=	30,
+	IRQrtc=		31,
+};
+
+/*
+ *  GPIO lines (signal names from compaq document).  _i indicates input
+ *  and _o output.
+ */
+enum
+{
+	GPIO_PWR_ON_i=		1<<0,	/* power button */
+	GPIO_UP_IRQ_i=		1<<1,	/* microcontroller interrupts */
+	GPIO_LDD8_o=		1<<2,	/* LCD data 8-15 */
+	GPIO_LDD9_o=		1<<3,
+	GPIO_LDD10_o=		1<<4,
+	GPIO_LDD11_o=		1<<5,
+	GPIO_LDD12_o=		1<<6,
+	GPIO_LDD13_o=		1<<7,
+	GPIO_LDD14_o=		1<<8,
+	GPIO_LDD15_o=		1<<9,
+	GPIO_CARD_IND1_i=	1<<10,	/* card inserted in PCMCIA socket 1 */
+	GPIO_CARD_IRQ1_i=	1<<11,	/* PCMCIA socket 1 interrupt */
+	GPIO_CLK_SET0_o=	1<<12,	/* clock selects for audio codec */
+	GPIO_CLK_SET1_o=	1<<13,
+	GPIO_L3_SDA_io=		1<<14,	/* UDA1341 interface */
+	GPIO_L3_MODE_o=		1<<15,
+	GPIO_L3_SCLK_o=		1<<16,
+	GPIO_CARD_IND0_i=	1<<17,	/* card inserted in PCMCIA socket 0 */
+	GPIO_KEY_ACT_i=		1<<18,	/* hot key from cradle */
+	GPIO_SYS_CLK_i=		1<<19,	/* clock from codec */
+	GPIO_BAT_FAULT_i=	1<<20,	/* battery fault */
+	GPIO_CARD_IRQ0_i=	1<<21,	/* PCMCIA socket 0 interrupt */
+	GPIO_LOCK_i=		1<<22,	/* expansion pack lock/unlock */
+	GPIO_COM_DCD_i=		1<<23,	/* DCD from UART3 */
+	GPIO_OPT_IRQ_i=		1<<24,	/* expansion pack IRQ */
+	GPIO_COM_CTS_i=		1<<25,	/* CTS from UART3 */
+	GPIO_COM_RTS_o=		1<<26,	/* RTS to UART3 */
+	GPIO_OPT_IND_i=		1<<27,	/* expansion pack inserted */
+
+/* Peripheral Unit GPIO pin assignments: alternate functions */
+	GPIO_SSP_TXD_o=		1<<10,	/* SSP Transmit Data */
+	GPIO_SSP_RXD_i=		1<<11,	/* SSP Receive Data */
+	GPIO_SSP_SCLK_o=	1<<12,	/* SSP Sample CLocK */
+	GPIO_SSP_SFRM_o=	1<<13,	/* SSP Sample FRaMe */
+	/* ser. port 1: */
+	GPIO_UART_TXD_o=	1<<14,	/* UART Transmit Data */
+	GPIO_UART_RXD_i=	1<<15,	/* UART Receive Data */
+	GPIO_SDLC_SCLK_io=	1<<16,	/* SDLC Sample CLocK (I/O) */
+	GPIO_SDLC_AAF_o=	1<<17,	/* SDLC Abort After Frame */
+	GPIO_UART_SCLK1_i=	1<<18,	/* UART Sample CLocK 1 */
+	/* ser. port 4: */
+	GPIO_SSP_CLK_i=		1<<19,	/* SSP external CLocK */
+	/* ser. port 3: */
+	GPIO_UART_SCLK3_i=	1<<20,	/* UART Sample CLocK 3 */
+	/* ser. port 4: */
+	GPIO_MCP_CLK_i=		1<<21,	/* MCP CLocK */
+	/* test controller: */
+	GPIO_TIC_ACK_o=		1<<21,	/* TIC ACKnowledge */
+	GPIO_MBGNT_o=		1<<21,	/* Memory Bus GraNT */
+	GPIO_TREQA_i=		1<<22,	/* TIC REQuest A */
+	GPIO_MBREQ_i=		1<<22,	/* Memory Bus REQuest */
+	GPIO_TREQB_i=		1<<23,	/* TIC REQuest B */
+	GPIO_1Hz_o=			1<<25,	/* 1 Hz clock */
+	GPIO_RCLK_o=		1<<26,	/* internal (R) CLocK (O, fcpu/2) */
+	GPIO_32_768kHz_o=	1<<27,	/* 32.768 kHz clock (O, RTC) */
+};
+
+/*
+ *  types of interrupts
+ */
+enum
+{
+	GPIOrising,
+	GPIOfalling,
+	GPIOboth,
+	IRQ,
+};
+
+/* hardware registers */
+typedef struct Uartregs Uartregs;
+struct Uartregs
+{
+	ulong	ctl[4];
+	ulong	dummya;
+	ulong	data;
+	ulong	dummyb;
+	ulong	status[2];
+};
+Uartregs *uart3regs;
+
+/* general purpose I/O lines control registers */
+typedef struct GPIOregs GPIOregs;
+struct GPIOregs
+{
+	ulong	level;		/* 1 == high */
+	ulong	direction;	/* 1 == output */
+	ulong	set;		/* a 1 sets the bit, 0 leaves it alone */
+	ulong	clear;		/* a 1 clears the bit, 0 leaves it alone */
+	ulong	rising;		/* rising edge detect enable */
+	ulong	falling;	/* falling edge detect enable */
+	ulong	edgestatus;	/* writing a 1 bit clears */
+	ulong	altfunc;	/* turn on alternate function for any set bits */
+};
+
+extern GPIOregs *gpioregs;
+
+/* extra general purpose I/O bits, output only */
+enum
+{
+	EGPIO_prog_flash=	1<<0,
+	EGPIO_pcmcia_reset=	1<<1,
+	EGPIO_exppack_reset=	1<<2,
+	EGPIO_codec_reset=	1<<3,
+	EGPIO_exp_nvram_power=	1<<4,
+	EGPIO_exp_full_power=	1<<5,
+	EGPIO_lcd_3v=		1<<6,
+	EGPIO_rs232_power=	1<<7,
+	EGPIO_lcd_ic_power=	1<<8,
+	EGPIO_ir_power=		1<<9,
+	EGPIO_audio_power=	1<<10,
+	EGPIO_audio_ic_power=	1<<11,
+	EGPIO_audio_mute=	1<<12,
+	EGPIO_fir=		1<<13,	/* not set is sir */
+	EGPIO_lcd_5v=		1<<14,
+	EGPIO_lcd_9v=		1<<15,
+};
+extern ulong *egpioreg;
+
+/* Peripheral pin controller registers */
+typedef struct PPCregs PPCregs;
+struct PPCregs {
+	ulong	direction;
+	ulong	state;
+	ulong	assignment;
+	ulong	sleepdir;
+	ulong	flags;
+};
+extern PPCregs *ppcregs;
+
+/* Synchronous Serial Port controller registers */
+typedef struct SSPregs SSPregs;
+struct SSPregs {
+	ulong	control0;
+	ulong	control1;
+	ulong	dummy0;
+	ulong	data;
+	ulong	dummy1;
+	ulong	status;
+};
+extern SSPregs *sspregs;
+
+/* Multimedia Communications Port controller registers */
+typedef struct MCPregs MCPregs;
+struct MCPregs {
+	ulong	control0;
+	ulong	reserved0;
+	ulong	data0;
+	ulong	data1;
+	ulong	data2;
+	ulong	reserved1;
+	ulong	status;
+	ulong	reserved[11];
+	ulong	control1;
+};
+extern MCPregs *mcpregs;
+
+/*
+ *  memory configuration
+ */
+enum
+{
+	/* bit shifts for pcmcia access time counters */
+	MECR_io0=	0,
+	MECR_attr0=	5,
+	MECR_mem0=	10,
+	MECR_fast0=	11,
+	MECR_io1=	MECR_io0+16,
+	MECR_attr1=	MECR_attr0+16,
+	MECR_mem1=	MECR_mem0+16,
+	MECR_fast1=	MECR_fast0+16,
+};
+
+typedef struct MemConfRegs MemConfRegs;
+struct MemConfRegs
+{
+	ulong	mdcnfg;		/* dram */
+	ulong	mdcas00;	/* dram banks 0/1 */
+	ulong	mdcas01;
+	ulong	mdcas02;
+	ulong	msc0;		/* static */
+	ulong	msc1;
+	ulong	mecr;		/* pcmcia */
+	ulong	mdrefr;		/* dram refresh */
+	ulong	mdcas20;	/* dram banks 2/3 */
+	ulong	mdcas21;
+	ulong	mdcas22;
+	ulong	msc2;		/* static */
+	ulong	smcnfg;		/* SMROM config */
+};
+extern MemConfRegs *memconfregs;
+
+/*
+ *  power management
+ */
+typedef struct PowerRegs PowerRegs;
+struct PowerRegs
+{
+	ulong	pmcr;	/* Power manager control register */
+	ulong	pssr;	/* Power manager sleep status register */
+	ulong	pspr;	/* Power manager scratch pad register */
+	ulong	pwer;	/* Power manager wakeup enable register */
+	ulong	pcfr;	/* Power manager general configuration register */
+	ulong	ppcr;	/* Power manager PPL configuration register */
+	ulong	pgsr;	/* Power manager GPIO sleep state register */
+	ulong	posr;	/* Power manager oscillator status register */
+};
+extern PowerRegs *powerregs;
--- /dev/null
+++ b/os/boot.original/arm1110/l.s
@@ -1,0 +1,454 @@
+#include "mem.h"
+
+/*
+ * Entered here from Compaq's bootldr with MMU disabled.
+ */
+TEXT _start(SB), $-4
+	MOVW	$setR12(SB), R12		/* load the SB */
+_main:
+	/* SVC mode, interrupts disabled */
+	MOVW	$(PsrDirq|PsrDfiq|PsrMsvc), R1
+	MOVW	R1, CPSR
+
+	/* disable the MMU */
+	MOVW	$0x130, R1
+	MCR     CpMMU, 0, R1, C(CpControl), C(0x0)
+
+	/* flush caches */
+	MCR	CpMMU, 0, R0, C(CpCacheFlush), C(0x7), 0
+	/* drain prefetch */
+	MOVW	R0,R0						
+	MOVW	R0,R0
+	MOVW	R0,R0
+	MOVW	R0,R0
+
+	/* drain write buffer */
+	MCR	CpMMU, 0, R0, C(CpCacheFlush), C(0xa), 4
+
+	MOVW	$(MACHADDR+BY2PG), R13		/* stack */
+	SUB	$4, R13				/* link */
+	BL	main(SB)
+	BL	exit(SB)
+	/* we shouldn't get here */
+_mainloop:
+	B	_mainloop
+	BL	_div(SB)			/* hack to get _div etc loaded */
+
+/* flush tlb's */
+TEXT mmuinvalidate(SB), $-4
+	MCR	CpMMU, 0, R0, C(CpTLBFlush), C(0x7)
+	RET
+
+/* flush tlb's */
+TEXT mmuinvalidateaddr(SB), $-4
+	MCR	CpMMU, 0, R0, C(CpTLBFlush), C(0x6), 1
+	RET
+
+/* write back and invalidate i and d caches */
+TEXT cacheflush(SB), $-4
+	/* write back any dirty data */
+	MOVW	$0xe0000000,R0
+	ADD	$(8*1024),R0,R1
+_cfloop:
+	MOVW.P	32(R0),R2
+	CMP.S	R0,R1
+	BNE	_cfloop
+	
+	/* drain write buffer and invalidate i&d cache contents */
+	MCR	CpMMU, 0, R0, C(CpCacheFlush), C(0xa), 4
+	MCR	CpMMU, 0, R0, C(CpCacheFlush), C(0x7), 0
+
+	/* drain prefetch */
+	MOVW	R0,R0						
+	MOVW	R0,R0
+	MOVW	R0,R0
+	MOVW	R0,R0
+	RET
+
+/* write back d cache */
+TEXT cachewb(SB), $-4
+	/* write back any dirty data */
+_cachewb:
+	MOVW	$0xe0000000,R0
+	ADD	$(8*1024),R0,R1
+_cwbloop:
+	MOVW.P	32(R0),R2
+	CMP.S	R0,R1
+	BNE	_cwbloop
+	
+	/* drain write buffer */
+	MCR	CpMMU, 0, R0, C(CpCacheFlush), C(0xa), 4
+	RET
+
+/* write back a single cache line */
+TEXT cachewbaddr(SB), $-4
+	BIC	$31,R0
+	MCR	CpMMU, 0, R0, C(CpCacheFlush), C(0xa), 1
+	B	_wbflush
+
+/* write back a region of cache lines */
+TEXT cachewbregion(SB), $-4
+	MOVW	4(FP),R1
+	CMP.S	$(4*1024),R1
+	BGT	_cachewb
+	ADD	R0,R1
+	BIC	$31,R0
+_cwbrloop:
+	MCR	CpMMU, 0, R0, C(CpCacheFlush), C(0xa), 1
+	ADD	$32,R0
+	CMP.S	R0,R1
+	BGT	_cwbrloop
+	B	_wbflush
+
+/* invalidate the dcache */
+TEXT dcacheinvalidate(SB), $-4
+	MCR	CpMMU, 0, R0, C(CpCacheFlush), C(0x6)
+	RET
+
+/* invalidate the icache */
+TEXT icacheinvalidate(SB), $-4
+	MCR	CpMMU, 0, R0, C(CpCacheFlush), C(0x9)
+	RET
+
+/* drain write buffer */
+TEXT wbflush(SB), $-4
+_wbflush:
+	MCR	CpMMU, 0, R0, C(CpCacheFlush), C(0xa), 4
+	RET
+
+/* return cpu id */
+TEXT getcpuid(SB), $-4
+	MRC	CpMMU, 0, R0, C(CpCPUID), C(0x0)
+	RET
+
+/* return fault status */
+TEXT getfsr(SB), $-4
+	MRC	CpMMU, 0, R0, C(CpFSR), C(0x0)
+	RET
+
+/* return fault address */
+TEXT getfar(SB), $-4
+	MRC	CpMMU, 0, R0, C(CpFAR), C(0x0)
+	RET
+
+/* return fault address */
+TEXT putfar(SB), $-4
+	MRC	CpMMU, 0, R0, C(CpFAR), C(0x0)
+	RET
+
+/* set the translation table base */
+TEXT putttb(SB), $-4
+	MCR	CpMMU, 0, R0, C(CpTTB), C(0x0)
+	RET
+
+/*
+ *  enable mmu, i and d caches
+ */
+TEXT mmuenable(SB), $-4
+	MRC	CpMMU, 0, R0, C(CpControl), C(0x0)
+	ORR	$(CpCmmuena|CpCdcache|CpCicache|CpCwb), R0
+	MCR     CpMMU, 0, R0, C(CpControl), C(0x0)
+	RET
+
+TEXT mmudisable(SB), $-4
+	MRC	CpMMU, 0, R0, C(CpControl), C(0x0)
+	BIC	$(CpCmmuena|CpCdcache|CpCicache|CpCwb|CpCvivec), R0
+	MCR     CpMMU, 0, R0, C(CpControl), C(0x0)
+	RET
+
+/*
+ *  use exception vectors at 0xffff0000
+ */
+TEXT mappedIvecEnable(SB), $-4
+	MRC	CpMMU, 0, R0, C(CpControl), C(0x0)
+	ORR	$(CpCvivec), R0
+	MCR     CpMMU, 0, R0, C(CpControl), C(0x0)
+	RET
+TEXT mappedIvecDisable(SB), $-4
+	MRC	CpMMU, 0, R0, C(CpControl), C(0x0)
+	BIC	$(CpCvivec), R0
+	MCR     CpMMU, 0, R0, C(CpControl), C(0x0)
+	RET
+
+/* set the translation table base */
+TEXT putdac(SB), $-4
+	MCR	CpMMU, 0, R0, C(CpDAC), C(0x0)
+	RET
+
+/* set address translation pid */
+TEXT putpid(SB), $-4
+	MCR	CpMMU, 0, R0, C(CpPID), C(0x0)
+	RET
+
+/*
+ *  set the stack value for the mode passed in R0
+ */
+TEXT setr13(SB), $-4
+	MOVW	4(FP), R1
+
+	MOVW	CPSR, R2
+	BIC	$PsrMask, R2, R3
+	ORR	R0, R3
+	MOVW	R3, CPSR
+
+	MOVW	R13, R0
+	MOVW	R1, R13
+
+	MOVW	R2, CPSR
+	RET
+
+/*
+ *  exception vectors, copied by trapinit() to somewhere useful
+ */
+
+TEXT vectors(SB), $-4
+	MOVW	0x18(R15), R15			/* reset */
+	MOVW	0x18(R15), R15			/* undefined */
+	MOVW	0x18(R15), R15			/* SWI */
+	MOVW	0x18(R15), R15			/* prefetch abort */
+	MOVW	0x18(R15), R15			/* data abort */
+	MOVW	0x18(R15), R15			/* reserved */
+	MOVW	0x18(R15), R15			/* IRQ */
+	MOVW	0x18(R15), R15			/* FIQ */
+
+TEXT vtable(SB), $-4
+	WORD	$_vsvc(SB)			/* reset, in svc mode already */
+	WORD	$_vund(SB)			/* undefined, switch to svc mode */
+	WORD	$_vsvc(SB)			/* swi, in svc mode already */
+	WORD	$_vpabt(SB)			/* prefetch abort, switch to svc mode */
+	WORD	$_vdabt(SB)			/* data abort, switch to svc mode */
+	WORD	$_vsvc(SB)			/* reserved */
+	WORD	$_virq(SB)			/* IRQ, switch to svc mode */
+	WORD	$_vfiq(SB)			/* FIQ, switch to svc mode */
+
+TEXT _vrst(SB), $-4
+	BL	resettrap(SB)
+
+TEXT _vsvc(SB), $-4			/* SWI */
+	MOVW.W	R14, -4(R13)		/* ureg->pc = interupted PC */
+	MOVW	SPSR, R14		/* ureg->psr = SPSR */
+	MOVW.W	R14, -4(R13)		/* ... */
+	MOVW	$PsrMsvc, R14		/* ureg->type = PsrMsvc */
+	MOVW.W	R14, -4(R13)		/* ... */
+	MOVM.DB.W.S [R0-R14], (R13)	/* save user level registers, at end r13 points to ureg */
+	MOVW	$setR12(SB), R12	/* Make sure we've got the kernel's SB loaded */
+	MOVW	R13, R0			/* first arg is pointer to ureg */
+	SUB	$8, R13			/* space for argument+link */
+
+	BL	syscall(SB)
+
+	ADD	$(8+4*15), R13		/* make r13 point to ureg->type */
+	MOVW	8(R13), R14		/* restore link */
+	MOVW	4(R13), R0		/* restore SPSR */
+	MOVW	R0, SPSR		/* ... */
+	MOVM.DB.S (R13), [R0-R14]	/* restore registers */
+	ADD	$8, R13			/* pop past ureg->{type+psr} */
+	RFE				/* MOVM.IA.S.W (R13), [R15] */
+
+TEXT _vund(SB), $-4			/* undefined */
+	MOVM.IA	[R0-R4], (R13)		/* free some working space */
+	MOVW	$PsrMund, R0
+	B	_vswitch
+
+TEXT _vpabt(SB), $-4			/* prefetch abort */
+	MOVM.IA	[R0-R4], (R13)		/* free some working space */
+	MOVW	$PsrMabt, R0		/* r0 = type */
+	B	_vswitch
+
+TEXT _vdabt(SB), $-4			/* prefetch abort */
+	MOVM.IA	[R0-R4], (R13)		/* free some working space */
+	MOVW	$(PsrMabt+1), R0		/* r0 = type */
+	B	_vswitch
+
+TEXT _virq(SB), $-4			/* IRQ */
+	MOVM.IA	[R0-R4], (R13)		/* free some working space */
+	MOVW	$PsrMirq, R0		/* r0 = type */
+	B	_vswitch
+
+	/*
+	 *  come here with type in R0 and R13 pointing above saved [r0-r4]
+	 *  and type in r0.  we'll switch to SVC mode and then call trap.
+	 */
+_vswitch:
+	MOVW	SPSR, R1		/* save SPSR for ureg */
+	MOVW	R14, R2			/* save interrupted pc for ureg */
+	MOVW	R13, R3			/* save pointer to where the original [R0-R3] are */
+
+	/* switch to svc mode */
+	MOVW	CPSR, R14
+	BIC	$PsrMask, R14
+	ORR	$(PsrDirq|PsrDfiq|PsrMsvc), R14
+	MOVW	R14, CPSR
+
+	/* interupted code kernel or user? */
+	AND.S	$0xf, R1, R4
+	BEQ	_userexcep
+
+	/* here for trap from SVC mode */
+	MOVM.DB.W [R0-R2], (R13)	/* set ureg->{type, psr, pc}; r13 points to ureg->type  */
+	MOVM.IA	  (R3), [R0-R4]		/* restore [R0-R4] from previous mode's stack */
+	MOVM.DB.W [R0-R14], (R13)	/* save kernel level registers, at end r13 points to ureg */
+	MOVW	$setR12(SB), R12	/* Make sure we've got the kernel's SB loaded */
+	MOVW	R13, R0			/* first arg is pointer to ureg */
+	SUB	$8, R13			/* space for argument+link (for debugger) */
+	MOVW	$0xdeaddead,R11		/* marker */
+
+	BL	trap(SB)
+
+	ADD	$(8+4*15), R13		/* make r13 point to ureg->type */
+	MOVW	8(R13), R14		/* restore link */
+	MOVW	4(R13), R0		/* restore SPSR */
+	MOVW	R0, SPSR		/* ... */
+	MOVM.DB (R13), [R0-R14]	/* restore registers */
+	ADD	$8, R13			/* pop past ureg->{type+psr} */
+	RFE				/* MOVM.IA.S.W (R13), [R15] */
+
+	/* here for trap from USER mode */
+_userexcep:
+	MOVM.DB.W [R0-R2], (R13)	/* set ureg->{type, psr, pc}; r13 points to ureg->type  */
+	MOVM.IA	  (R3), [R0-R4]		/* restore [R0-R4] from previous mode's stack */
+	MOVM.DB.W.S [R0-R14], (R13)	/* save kernel level registers, at end r13 points to ureg */
+	MOVW	$setR12(SB), R12	/* Make sure we've got the kernel's SB loaded */
+	MOVW	R13, R0			/* first arg is pointer to ureg */
+	SUB	$8, R13			/* space for argument+link (for debugger) */
+
+	BL	trap(SB)
+
+	ADD	$(8+4*15), R13		/* make r13 point to ureg->type */
+	MOVW	8(R13), R14		/* restore link */
+	MOVW	4(R13), R0		/* restore SPSR */
+	MOVW	R0, SPSR		/* ... */
+	MOVM.DB.S (R13), [R0-R14]	/* restore registers */
+	ADD	$8, R13			/* pop past ureg->{type+psr} */
+	RFE				/* MOVM.IA.S.W (R13), [R15] */
+
+TEXT _vfiq(SB), $-4			/* FIQ */
+	RFE				/* FIQ is special, ignore it for now */
+
+/*
+ *  This is the first jump from kernel to user mode.
+ *  Fake a return from interrupt.
+ *
+ *  Enter with R0 containing the user stack pointer.
+ *  UTZERO + 0x20 is always the entry point.
+ *  
+ */
+TEXT touser(SB),$-4
+	/* store the user stack pointer into the USR_r13 */
+	MOVM.DB.W [R0], (R13)
+	MOVM.S.IA.W (R13),[R13]
+
+	/* set up a PSR for user level */
+	MOVW	$(PsrMusr), R0
+	MOVW	R0,SPSR
+
+	/* save the PC on the stack */
+	MOVW	$(UTZERO+0x20), R0
+	MOVM.DB.W [R0],(R13)
+
+	/* return from interrupt */
+	RFE				/* MOVM.IA.S.W (R13), [R15] */
+	
+/*
+ *  here to jump to a newly forked process
+ */
+TEXT forkret(SB),$-4
+	ADD	$(4*15), R13		/* make r13 point to ureg->type */
+	MOVW	8(R13), R14		/* restore link */
+	MOVW	4(R13), R0		/* restore SPSR */
+	MOVW	R0, SPSR		/* ... */
+	MOVM.DB.S (R13), [R0-R14]	/* restore registers */
+	ADD	$8, R13			/* pop past ureg->{type+psr} */
+	RFE				/* MOVM.IA.S.W (R13), [R15] */
+
+TEXT splhi(SB), $-4
+	/* save caller pc in Mach */
+	MOVW	$(MACHADDR+0x04),R2
+	MOVW	R14,0(R2)
+	/* turn off interrupts */
+	MOVW	CPSR, R0
+	ORR	$(PsrDfiq|PsrDirq), R0, R1
+	MOVW	R1, CPSR
+	RET
+
+TEXT spllo(SB), $-4
+	MOVW	CPSR, R0
+	BIC	$(PsrDfiq|PsrDirq), R0, R1
+	MOVW	R1, CPSR
+	RET
+
+TEXT splx(SB), $-4
+	/* save caller pc in Mach */
+	MOVW	$(MACHADDR+0x04),R2
+	MOVW	R14,0(R2)
+	/* reset interrupt level */
+	MOVW	R0, R1
+	MOVW	CPSR, R0
+	MOVW	R1, CPSR
+	RET
+
+TEXT splxpc(SB), $-4				/* for iunlock */
+	MOVW	R0, R1
+	MOVW	CPSR, R0
+	MOVW	R1, CPSR
+	RET
+
+TEXT spldone(SB), $0
+	RET
+
+TEXT islo(SB), $-4
+	MOVW	CPSR, R0
+	AND	$(PsrDfiq|PsrDirq), R0
+	EOR	$(PsrDfiq|PsrDirq), R0
+	RET
+
+TEXT cpsrr(SB), $-4
+	MOVW	CPSR, R0
+	RET
+
+TEXT spsrr(SB), $-4
+	MOVW	SPSR, R0
+	RET
+
+TEXT getcallerpc(SB), $-4
+	MOVW	0(R13), R0
+	RET
+
+TEXT tas(SB), $-4
+	MOVW	R0, R1
+	MOVW	$0xDEADDEAD, R2
+	SWPW	R2, (R1), R0
+	RET
+
+TEXT setlabel(SB), $-4
+	MOVW	R13, 0(R0)			/* sp */
+	MOVW	R14, 4(R0)			/* pc */
+	MOVW	$0, R0
+	RET
+
+TEXT gotolabel(SB), $-4
+	MOVW	0(R0), R13			/* sp */
+	MOVW	4(R0), R14			/* pc */
+	MOVW	$1, R0
+	RET
+
+
+/* The first MCR instruction of this function needs to be on a cache-line
+ * boundary; to make this happen, it will be copied (in trap.c).
+ *
+ * Doze puts the machine into idle mode.  Any interrupt will get it out
+ * at the next instruction (the RET, to be precise).
+ */
+TEXT _doze(SB), $-4
+	MOVW	$UCDRAMZERO, R1
+	MOVW	R0,R0
+	MOVW	R0,R0
+	MOVW	R0,R0
+	MOVW	R0,R0
+	MOVW	R0,R0
+	MOVW	R0,R0
+	MOVW	R0,R0
+	MCR     CpPWR, 0, R0, C(CpTest), C(0x2), 2
+	MOVW	(R1), R0
+	MCR     CpPWR, 0, R0, C(CpTest), C(0x8), 2
+	RET
--- /dev/null
+++ b/os/boot.original/arm1110/lib.h
@@ -1,0 +1,143 @@
+/*
+ * functions (possibly) linked in, complete, from libc.
+ */
+
+/*
+ * mem routines
+ */
+extern	void	*memccpy(void*, void*, int, long);
+extern	void	*memset(void*, int, long);
+extern	int	memcmp(void*, void*, long);
+extern	void	*memmove(void*, void*, long);
+extern	void	*memchr(void*, int, long);
+
+/*
+ * string routines
+ */
+extern	char	*strcat(char*, char*);
+extern	char	*strchr(char*, char);
+extern	char	*strrchr(char*, char);
+extern	int	strcmp(char*, char*);
+extern	char	*strcpy(char*, char*);
+extern	char	*strncat(char*, char*, long);
+extern	char	*strncpy(char*, char*, long);
+extern	int	strncmp(char*, char*, long);
+extern	long	strlen(char*);
+extern	char*	strstr(char*, char*);
+extern	int	atoi(char*);
+
+enum
+{
+	UTFmax		= 3,	/* maximum bytes per rune */
+	Runesync	= 0x80,	/* cannot represent part of a UTF sequence */
+	Runeself	= 0x80,	/* rune and UTF sequences are the same (<) */
+	Runeerror	= 0x80,	/* decoding error in UTF */
+};
+
+/*
+ * rune routines
+ */
+extern	int	runetochar(char*, Rune*);
+extern	int	chartorune(Rune*, char*);
+extern	char*	utfrune(char*, long);
+extern	int	utflen(char*);
+extern	int	runelen(long);
+
+extern	int	abs(int);
+
+/*
+ * print routines
+ */
+typedef struct Cconv Fconv;
+extern	char*	donprint(char*, char*, char*, void*);
+extern	int	sprint(char*, char*, ...);
+extern	char*	seprint(char*, char*, char*, ...);
+extern	int	snprint(char*, int, char*, ...);
+extern	int	print(char*, ...);
+
+/*
+ * one-of-a-kind
+ */
+extern	char*	cleanname(char*);
+extern	ulong	getcallerpc(void*);
+extern	long	strtol(char*, char**, int);
+extern	ulong	strtoul(char*, char**, int);
+extern	vlong	strtoll(char*, char**, int);
+extern	uvlong	strtoull(char*, char**, int);
+extern	char	etext[];
+extern	char	edata[];
+extern	char	end[];
+extern	int	getfields(char*, char**, int, int, char*);
+
+/*
+ * Syscall data structures
+ */
+#define	MORDER	0x0003	/* mask for bits defining order of mounting */
+#define	MREPL	0x0000	/* mount replaces object */
+#define	MBEFORE	0x0001	/* mount goes before others in union directory */
+#define	MAFTER	0x0002	/* mount goes after others in union directory */
+#define	MCREATE	0x0004	/* permit creation in mounted directory */
+#define	MCACHE	0x0010	/* cache some data */
+#define	MMASK	0x001F	/* all bits on */
+
+#define	OREAD	0	/* open for read */
+#define	OWRITE	1	/* write */
+#define	ORDWR	2	/* read and write */
+#define	OEXEC	3	/* execute, == read but check execute permission */
+#define	OTRUNC	16	/* or'ed in (except for exec), truncate file first */
+#define	OCEXEC	32	/* or'ed in, close on exec */
+#define	ORCLOSE	64	/* or'ed in, remove on close */
+
+#define	NCONT	0	/* continue after note */
+#define	NDFLT	1	/* terminate after note */
+#define	NSAVE	2	/* clear note but hold state */
+#define	NRSTR	3	/* restore saved state */
+
+typedef struct Qid	Qid;
+typedef struct Dir	Dir;
+typedef struct Waitmsg	Waitmsg;
+
+#define	ERRLEN		64
+#define	DIRLEN		116
+#define	NAMELEN		28
+
+struct Qid
+{
+	ulong	path;
+	ulong	vers;
+};
+
+struct Dir
+{
+	char	name[NAMELEN];
+	char	uid[NAMELEN];
+	char	gid[NAMELEN];
+	Qid	qid;
+	ulong	mode;
+	long	atime;
+	long	mtime;
+	vlong	length;
+	short	type;
+	short	dev;
+};
+
+struct Waitmsg
+{
+	char	pid[12];	/* of loved one */
+	char	time[3*12];	/* of loved one and descendants */
+	char	msg[ERRLEN];
+};
+
+/*
+ *  locks
+ */
+typedef
+struct Lock {
+	int	val;
+} Lock;
+
+extern int	_tas(int*);
+
+extern	void	lock(Lock*);
+extern	void	unlock(Lock*);
+extern	int	canlock(Lock*);
--- /dev/null
+++ b/os/boot.original/arm1110/map
@@ -1,0 +1,10 @@
+defn acidmap()
+{
+	local dfoffset;
+
+	dfoffset = map()[1][3];
+	map({"text", _start, etext, 0x20});
+	map({"data", etext+1, edata, dfoffset});
+	print("Set map for plan 9 kernel image\n");
+	print("btext ", _start, " etext ", etext, "\n");
+}
--- /dev/null
+++ b/os/boot.original/arm1110/mem.h
@@ -1,0 +1,215 @@
+/*
+ * Memory and machine-specific definitions.  Used in C and assembler.
+ */
+
+/*
+ * Sizes
+ */
+#define	BI2BY		8			/* bits per byte */
+#define BI2WD		32			/* bits per word */
+#define	BY2WD		4			/* bytes per word */
+#define	BY2V		8			/* bytes per double word */
+#define	BY2PG		4096			/* bytes per page */
+#define	WD2PG		(BY2PG/BY2WD)		/* words per page */
+#define	PGSHIFT		12			/* log(BY2PG) */
+#define ROUND(s, sz)	(((s)+(sz-1))&~(sz-1))
+#define PGROUND(s)	ROUND(s, BY2PG)
+#define	BLOCKALIGN	8
+
+#define	MAXMACH		1			/* max # cpus system can run */
+
+/*
+ * Time
+ */
+#define	HZ		(20)				/* clock frequency */
+#define	MS2HZ		(1000/HZ)			/* millisec per clock tick */
+#define	TK2SEC(t)	((t)/HZ)			/* ticks to seconds */
+#define	TK2MS(t)	((((ulong)(t))*1000)/HZ)	/* ticks to milliseconds */
+#define	MS2TK(t)	((((ulong)(t))*HZ)/1000)	/* milliseconds to ticks */
+
+/*
+ *  Virtual addresses:
+ *
+ *  We direct map all discovered DRAM and the area twixt 0xe0000000 and
+ *  0xe8000000 used to provide zeros for cache flushing.
+ *
+ *  Flash is mapped to 0xb0000000 and special registers are mapped
+ *  on demand to areas starting at 0xa0000000.
+ *
+ *  The direct mapping is convenient but not necessary.  It means
+ *  that we don't have to turn on the MMU till well into the
+ *  kernel.  This can be changed by providing a mapping in l.s
+ *  before calling main.
+ */
+#define	UZERO		0			/* base of user address space */
+#define	UTZERO		(UZERO+BY2PG)		/* first address in user text */
+#define	KZERO		0xC0000000		/* base of kernel address space */
+#define	KTZERO		0xC0008000		/* first address in kernel text */
+#define	EMEMZERO	0x90000000		/* 256 meg for add on memory */
+#define	EMEMTOP		0xA0000000		/* ... */
+#define	REGZERO		0xA0000000		/* 128 meg for mapspecial regs */
+#define	REGTOP		0xA8000000		/* ... */
+#define	FLASHZERO	0xB0000000		/* 128 meg for flash */
+#define	FLASHTOP	0xB8000000		/* ... */
+#define	DRAMZERO	0xC0000000		/* 128 meg for dram */
+#define DRAMTOP		0xC8000000		/* ... */
+#define	UCDRAMZERO	0xC8000000		/* 128 meg for dram (uncached/unbuffered) */
+#define UCDRAMTOP	0xD0000000		/* ... */
+#define	NULLZERO	0xE0000000		/* 128 meg for cache flush zeroes */
+#define NULLTOP		0xE8000000		/* ... */
+#define	USTKTOP		0x2000000		/* byte just beyond user stack */
+#define	USTKSIZE	(8*1024*1024)		/* size of user stack */
+#define	TSTKTOP		(USTKTOP-USTKSIZE)	/* end of new stack in sysexec */
+#define TSTKSIZ 	100
+#define MACHADDR	(KZERO+0x00001000)
+#define	EVECTORS	0xFFFF0000		/* virt base of exception vectors */
+
+#define KSTACK		(16*1024)		/* Size of kernel stack */
+
+#define	FLATESIZE	(700*1024)		/* maximum size of compressed image */
+
+/*
+ *  Offsets into flash
+ */
+#define Flash_bootldr	(FLASHZERO+0x0)		/* boot loader */
+#define Flash_kernel	(FLASHZERO+0x10000)	/* boot kernel */
+#define	Flash_tar	(FLASHZERO+0x100000)	/* tar file containing fs.sac */
+
+/*
+ *  virtual MMU
+ */
+#define PTEMAPMEM	(1024*1024)	
+#define	PTEPERTAB	(PTEMAPMEM/BY2PG)
+#define SEGMAPSIZE	1984
+#define SSEGMAPSIZE	16
+#define PPN(x)		((x)&~(BY2PG-1))
+
+/*
+ *  SA1110 definitions
+ */
+
+/*
+ *  memory physical addresses
+ */
+#define PHYSFLASH0	0x00000000
+#define PHYSDRAM0	0xC0000000
+#define	PHYSNULL0	0xE0000000
+
+/*
+ *  peripheral control module physical addresses
+ */
+#define USBREGS		0x80000000	/* serial port 0 - USB */
+#define UART1REGS	0x80010000	/* serial port 1 - UART */
+#define GPCLKREGS	0x80020060	/* serial port 1 - general purpose clock */
+#define UART2REGS	0x80030000	/* serial port 2 - low speed IR */
+#define HSSPREGS	0x80040060	/* serial port 2 - high speed IR */
+#define UART3REGS	0x80050000	/* serial port 3 - RS232 UART */
+#define MCPREGS		0x80060000	/* serial port 4 - multimedia comm port */
+#define SSPREGS		0x80070060	/* serial port 4 - synchronous serial port */
+#define OSTIMERREGS	0x90000000	/* operating system timer registers */
+#define POWERREGS	0x90020000	/* power management */
+#define GPIOREGS	0x90040000	/* 28 general purpose IO pins */
+#define INTRREGS	0x90050000	/* interrupt registers */
+#define PPCREGS		0x90060000	/* peripheral pin controller */
+#define MEMCONFREGS	0xA0000000	/* memory configuration */
+#define LCDREGS		0xB0100000	/* display */
+
+/*
+ *  PCMCIA addresses
+ */
+#define PHYSPCM0REGS	0x20000000
+#define PYHSPCM0ATTR	0x28000000
+#define PYHSPCM0MEM	0x2C000000
+#define PHYSPCM1REGS	0x30000000
+#define PYHSPCM1ATTR	0x38000000
+#define PYHSPCM1MEM	0x3C000000
+
+/*
+ *  Program Status Registers
+ */
+#define PsrMusr		0x00000010	/* mode */
+#define PsrMfiq		0x00000011
+#define PsrMirq		0x00000012
+#define PsrMsvc		0x00000013
+#define PsrMabt		0x00000017
+#define PsrMund		0x0000001B
+#define PsrMask		0x0000001F
+
+#define PsrDfiq		0x00000040	/* disable FIQ interrupts */
+#define PsrDirq		0x00000080	/* disable IRQ interrupts */
+
+#define PsrV		0x10000000	/* overflow */
+#define PsrC		0x20000000	/* carry/borrow/extend */
+#define PsrZ		0x40000000	/* zero */
+#define PsrN		0x80000000	/* negative/less than */
+
+/*
+ *  Coprocessors
+ */
+#define CpMMU		15
+#define CpPWR		15
+
+/*
+ *  Internal MMU coprocessor registers
+ */
+#define CpCPUID		0		/* R: */
+#define CpControl	1		/* R: */
+#define CpTTB		2		/* RW: translation table base */
+#define CpDAC		3		/* RW: domain access control */
+#define CpFSR		5		/* RW: fault status */
+#define CpFAR		6		/* RW: fault address */
+#define CpCacheFlush	7		/* W: cache flushing, wb draining*/
+#define CpTLBFlush	8		/* W: TLB flushing */
+#define CpRBFlush	9		/* W: Read Buffer ops */
+#define CpPID		13		/* RW: PID for virtual mapping */
+#define	CpBpt		14		/* W: Breakpoint register */
+#define CpTest		15		/* W: Test, Clock and Idle Control */
+
+/*
+ *  CpControl
+ */
+#define CpCmmuena	0x00000001	/* M: MMU enable */
+#define CpCalign	0x00000002	/* A: alignment fault enable */
+#define CpCdcache	0x00000004	/* C: data cache on */
+#define CpCwb		0x00000008	/* W: write buffer turned on */
+#define CpCi32		0x00000010	/* P: 32-bit program space */
+#define CpCd32		0x00000020	/* D: 32-bit data space */
+#define CpCbe		0x00000080	/* B: big-endian operation */
+#define CpCsystem	0x00000100	/* S: system permission */
+#define CpCrom		0x00000200	/* R: ROM permission */
+#define CpCicache	0x00001000	/* I: instruction cache on */
+#define CpCvivec	0x00002000	/* X: virtual interrupt vector adjust */
+
+/*
+ *  fault codes
+ */
+#define	FCterm		0x2	/* terminal */
+#define	FCvec		0x0	/* vector */
+#define	FCalignf	0x1	/* unaligned full word data access */
+#define	FCalignh	0x3	/* unaligned half word data access */
+#define	FCl1abort	0xc	/* level 1 external abort on translation */
+#define	FCl2abort	0xe	/* level 2 external abort on translation */
+#define	FCtransSec	0x5	/* section translation */
+#define	FCtransPage	0x7	/* page translation */
+#define	FCdomainSec	0x9	/* section domain  */
+#define	FCdomainPage	0x11	/* page domain */
+#define	FCpermSec	0x9	/* section permissions  */
+#define	FCpermPage	0x11	/* page permissions */
+#define	FCabortLFSec	0x4	/* external abort on linefetch for section */
+#define	FCabortLFPage	0x6	/* external abort on linefetch for page */
+#define	FCabortNLFSec	0x8	/* external abort on non-linefetch for section */
+#define	FCabortNLFPage	0xa	/* external abort on non-linefetch for page */
+
+/*
+ *  PTE bits used by fault.h.  mmu.c translates them to real values.
+ */
+#define	PTEVALID	(1<<0)
+#define	PTERONLY	0	/* this is implied by the absence of PTEWRITE */
+#define	PTEWRITE	(1<<1)
+#define	PTEUNCACHED	(1<<2)
+#define PTEKERNEL	(1<<3)	/* no user access */
+
+/*
+ *  H3650 specific definitions
+ */
+#define EGPIOREGS	0x49000000	/* Additional GPIO register */
--- /dev/null
+++ b/os/boot.original/arm1110/mkfile
@@ -1,0 +1,86 @@
+<../../../mkconfig
+objtype=arm
+SYSTARG=$OSTARG
+OBJTYPE=arm
+BIN=$ROOT/Inferno/$OBJTYPE
+LIBDIR=$ROOT/Inferno/$OBJTYPE/lib
+LIBDIRS=../libflate $ROOT/libkern
+LIBS=\
+	libflate\
+	libkern\
+
+LIBFILES=${LIBS:%=$LIBDIR/%.a}
+<$ROOT/mkfiles/mkfile-$SYSTARG-$OBJTYPE
+
+BIN=$ROOT/Inferno/$OBJTYPE
+
+TARG=\
+	inflate\
+
+INFLATE=\
+	il.$O\
+	imain.$O\
+
+CORE=\
+	uart.$O\
+	inflate.$O\
+	donprint.$O\
+	print.$O\
+
+HFILES=\
+	mem.h\
+
+CFLAGS=-FVw -I.  -I$ROOT/Inferno/$OBJTYPE/include -I$ROOT/include
+
+all:V:	$TARG
+
+install:V:	$BIN/$TARG
+
+$BIN/%:	%
+	cp $stem $BIN/$stem
+
+inflate: $INFLATE $CORE $LIBFILES
+	$LD -o s$target -R4 -T0xC0200010 -l $prereq
+	$LD -o _$target -H5 -R4 -T0xC0200010 -l $prereq
+	dd -conv sync -ibs 20k -if _$target -of $target
+
+%.$O:	%.s
+	$AS $stem.s
+
+%.$O:	%.c
+	$CC $CFLAGS $stem.c
+
+%.$O:	$HFILES
+
+clean:
+	rm -f *.[$OS] [$OS].out y.tab.? y.debug y.output $TARG _$TARG s$TARG
+
+
+# added to cause libflate to be made automatically:
+
+$ROOT/Inferno/$OBJTYPE/lib/lib%.a:Q:	all-$SHELLTYPE
+	#
+
+rc-lib%.a nt-lib%.a:VQ:
+	echo '@{builtin cd ' $ROOT/lib$stem ';mk SHELLTYPE=$SHELLTYPE SYSTARG=$SYSTARG OBJTYPE=$OBJTYPE install}'
+	@{builtin cd  $ROOT/lib$stem ;mk 'SHELLTYPE='$SHELLTYPE 'SYSTARG='$SYSTARG 'OBJTYPE='$OBJTYPE install}
+
+sh-lib%.a:VQ:
+	echo "(cd $ROOT/lib$stem ; mk SHELLTYPE=$SHELLTYPE SYSTARG=$SYSTARG OBJTYPE=$OBJTYPE install)"
+	(cd $ROOT/lib$stem ; mk SHELLTYPE=$SHELLTYPE SYSTARG=$SYSTARG OBJTYPE=$OBJTYPE install)
+
+%-sh:QV:
+		for i in $LIBDIRS
+		do
+			echo "(cd $i ; mk SHELLTYPE=$SHELLTYPE SYSTARG=$SYSTARG OBJTYPE=$OBJTYPE $stem)"
+			(cd $i; mk 'SHELLTYPE='$SHELLTYPE 'SYSTARG='$SYSTARG 'OBJTYPE='$OBJTYPE $stem)
+		done
+
+%-rc %-nt:QV:
+		for (i in $LIBDIRS)
+		{
+			echo '@{cd $i ; mk SHELLTYPE=$SHELLTYPE SYSTARG=$SYSTARG OBJTYPE=$OBJTYPE $stem}'
+			@{cd $i; mk 'SHELLTYPE='$SHELLTYPE 'SYSTARG='$SYSTARG 'OBJTYPE='$OBJTYPE $stem}
+		}
+
+nuke:V:		clean nuke-$SHELLTYPE
--- /dev/null
+++ b/os/boot.original/arm1110/print.c
@@ -1,0 +1,56 @@
+#include "u.h"
+#include "lib.h"
+#include "fns.h"
+#include "dat.h"
+
+
+#define	SIZE	1024
+
+int
+print(char *fmt, ...)
+{
+	char buf[SIZE], *out;
+	va_list arg;
+
+	va_start(arg, fmt);
+	out = donprint(buf, buf+SIZE, fmt, arg);
+	va_end(arg);
+	serialputs(buf, out-buf);
+	return out-buf;
+}
+
+int
+sprint(char *buf, char *fmt, ...)
+{
+	char *out;
+	va_list arg;
+
+	va_start(arg, fmt);
+	out = donprint(buf, buf+SIZE, fmt, arg);
+	va_end(arg);
+	return out-buf;
+}
+
+int
+snprint(char *buf, int len, char *fmt, ...)
+{
+	char *out;
+	va_list arg;
+
+	va_start(arg, fmt);
+	out = donprint(buf, buf+len, fmt, arg);
+	va_end(arg);
+	return out-buf;
+}
+
+char*
+seprint(char *buf, char *e, char *fmt, ...)
+{
+	char *out;
+	va_list arg;
+
+	va_start(arg, fmt);
+	out = donprint(buf, e, fmt, arg);
+	va_end(arg);
+	return out;
+}
--- /dev/null
+++ b/os/boot.original/arm1110/uart.c
@@ -1,0 +1,69 @@
+#include	"u.h"
+#include	"lib.h"
+#include	"mem.h"
+#include	"dat.h"
+#include	"fns.h"
+#include	"io.h"
+
+enum
+{
+	/* ctl[0] bits */
+	Parity=		1<<0,
+	Even=		1<<1,
+	Stop2=		1<<2,
+	Bits8=		1<<3,
+	SCE=		1<<4,	/* synchronous clock enable */
+	RCE=		1<<5,	/* rx on falling edge of clock */
+	TCE=		1<<6,	/* tx on falling edge of clock */
+
+	/* ctl[3] bits */
+	Rena=		1<<0,	/* receiver enable */
+	Tena=		1<<1,	/* transmitter enable */
+	Break=		1<<2,	/* force TXD3 low */
+	Rintena=	1<<3,	/* enable receive interrupt */
+	Tintena=	1<<4,	/* enable transmitter interrupt */
+	Loopback=	1<<5,	/* loop back data */
+
+	/* data bits */
+	DEparity=	1<<8,	/* parity error */
+	DEframe=	1<<9,	/* framing error */
+	DEoverrun=	1<<10,	/* overrun error */
+
+	/* status[0] bits */
+	Tint=		1<<0,	/* transmit fifo half full interrupt */
+	Rint0=		1<<1,	/* receiver fifo 1/3-2/3 full */
+	Rint1=		1<<2,	/* receiver fifo not empty and receiver idle */
+	Breakstart=	1<<3,
+	Breakend=	1<<4,
+	Fifoerror=	1<<5,	/* fifo error */
+
+	/* status[1] bits */
+	Tbusy=		1<<0,	/* transmitting */
+	Rnotempty=	1<<1,	/* receive fifo not empty */
+	Tnotfull=	1<<2,	/* transmit fifo not full */
+	ParityError=	1<<3,
+	FrameError=	1<<4,
+	Overrun=	1<<5,
+};
+
+Uartregs *uart3regs = UART3REGS;
+
+
+/*
+ *  for iprint, just write it
+ */
+void
+serialputs(char *str, int n)
+{
+	Uartregs *ur;
+
+	ur = uart3regs;
+	while(n-- > 0){
+		/* wait for output ready */
+		while((ur->status[1] & Tnotfull) == 0)
+			;
+		ur->data = *str++;
+	}
+	while((ur->status[1] & Tbusy))
+		;
+}
--- /dev/null
+++ b/os/boot.original/libflate/LICENCE
@@ -1,0 +1,237 @@
+Lucent Public License Version 1.02
+
+THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS PUBLIC
+LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE
+PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT.
+
+1. DEFINITIONS
+
+"Contribution" means:
+
+  a. in the case of Lucent Technologies Inc. ("LUCENT"), the Original
+     Program, and
+  b. in the case of each Contributor,
+
+     i. changes to the Program, and
+    ii. additions to the Program;
+
+    where such changes and/or additions to the Program were added to the
+    Program by such Contributor itself or anyone acting on such
+    Contributor's behalf, and the Contributor explicitly consents, in
+    accordance with Section 3C, to characterization of the changes and/or
+    additions as Contributions.
+
+"Contributor" means LUCENT and any other entity that has Contributed a
+Contribution to the Program.
+
+"Distributor" means a Recipient that distributes the Program,
+modifications to the Program, or any part thereof.
+
+"Licensed Patents" mean patent claims licensable by a Contributor
+which are necessarily infringed by the use or sale of its Contribution
+alone or when combined with the Program.
+
+"Original Program" means the original version of the software
+accompanying this Agreement as released by LUCENT, including source
+code, object code and documentation, if any.
+
+"Program" means the Original Program and Contributions or any part
+thereof
+
+"Recipient" means anyone who receives the Program under this
+Agreement, including all Contributors.
+
+2. GRANT OF RIGHTS
+
+ a. Subject to the terms of this Agreement, each Contributor hereby
+    grants Recipient a non-exclusive, worldwide, royalty-free copyright
+    license to reproduce, prepare derivative works of, publicly display,
+    publicly perform, distribute and sublicense the Contribution of such
+    Contributor, if any, and such derivative works, in source code and
+    object code form.
+    
+ b. Subject to the terms of this Agreement, each Contributor hereby
+    grants Recipient a non-exclusive, worldwide, royalty-free patent
+    license under Licensed Patents to make, use, sell, offer to sell,
+    import and otherwise transfer the Contribution of such Contributor, if
+    any, in source code and object code form. The patent license granted
+    by a Contributor shall also apply to the combination of the
+    Contribution of that Contributor and the Program if, at the time the
+    Contribution is added by the Contributor, such addition of the
+    Contribution causes such combination to be covered by the Licensed
+    Patents. The patent license granted by a Contributor shall not apply
+    to (i) any other combinations which include the Contribution, nor to
+    (ii) Contributions of other Contributors. No hardware per se is
+    licensed hereunder.
+    
+ c. Recipient understands that although each Contributor grants the
+    licenses to its Contributions set forth herein, no assurances are
+    provided by any Contributor that the Program does not infringe the
+    patent or other intellectual property rights of any other entity. Each
+    Contributor disclaims any liability to Recipient for claims brought by
+    any other entity based on infringement of intellectual property rights
+    or otherwise. As a condition to exercising the rights and licenses
+    granted hereunder, each Recipient hereby assumes sole responsibility
+    to secure any other intellectual property rights needed, if any. For
+    example, if a third party patent license is required to allow
+    Recipient to distribute the Program, it is Recipient's responsibility
+    to acquire that license before distributing the Program.
+
+ d. Each Contributor represents that to its knowledge it has sufficient
+    copyright rights in its Contribution, if any, to grant the copyright
+    license set forth in this Agreement.
+
+3. REQUIREMENTS
+
+A. Distributor may choose to distribute the Program in any form under
+this Agreement or under its own license agreement, provided that:
+
+ a. it complies with the terms and conditions of this Agreement;
+
+ b. if the Program is distributed in source code or other tangible
+    form, a copy of this Agreement or Distributor's own license agreement
+    is included with each copy of the Program; and
+
+ c. if distributed under Distributor's own license agreement, such
+    license agreement:
+
+      i. effectively disclaims on behalf of all Contributors all warranties
+         and conditions, express and implied, including warranties or
+         conditions of title and non-infringement, and implied warranties or
+         conditions of merchantability and fitness for a particular purpose;
+     ii. effectively excludes on behalf of all Contributors all liability
+         for damages, including direct, indirect, special, incidental and
+         consequential damages, such as lost profits; and
+    iii. states that any provisions which differ from this Agreement are
+         offered by that Contributor alone and not by any other party.
+
+B. Each Distributor must include the following in a conspicuous
+   location in the Program:
+
+   Copyright (C) 2003, Lucent Technologies Inc. and others. All Rights
+   Reserved.
+
+C. In addition, each Contributor must identify itself as the
+originator of its Contribution in a manner that reasonably allows
+subsequent Recipients to identify the originator of the Contribution.
+Also, each Contributor must agree that the additions and/or changes
+are intended to be a Contribution. Once a Contribution is contributed,
+it may not thereafter be revoked.
+
+4. COMMERCIAL DISTRIBUTION
+
+Commercial distributors of software may accept certain
+responsibilities with respect to end users, business partners and the
+like. While this license is intended to facilitate the commercial use
+of the Program, the Distributor who includes the Program in a
+commercial product offering should do so in a manner which does not
+create potential liability for Contributors. Therefore, if a
+Distributor includes the Program in a commercial product offering,
+such Distributor ("Commercial Distributor") hereby agrees to defend
+and indemnify every Contributor ("Indemnified Contributor") against
+any losses, damages and costs (collectively"Losses") arising from
+claims, lawsuits and other legal actions brought by a third party
+against the Indemnified Contributor to the extent caused by the acts
+or omissions of such Commercial Distributor in connection with its
+distribution of the Program in a commercial product offering. The
+obligations in this section do not apply to any claims or Losses
+relating to any actual or alleged intellectual property infringement.
+In order to qualify, an Indemnified Contributor must: a) promptly
+notify the Commercial Distributor in writing of such claim, and b)
+allow the Commercial Distributor to control, and cooperate with the
+Commercial Distributor in, the defense and any related settlement
+negotiations. The Indemnified Contributor may participate in any such
+claim at its own expense.
+
+For example, a Distributor might include the Program in a commercial
+product offering, Product X. That Distributor is then a Commercial
+Distributor. If that Commercial Distributor then makes performance
+claims, or offers warranties related to Product X, those performance
+claims and warranties are such Commercial Distributor's responsibility
+alone. Under this section, the Commercial Distributor would have to
+defend claims against the Contributors related to those performance
+claims and warranties, and if a court requires any Contributor to pay
+any damages as a result, the Commercial Distributor must pay those
+damages.
+
+5. NO WARRANTY
+
+EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS
+PROVIDED ON AN"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY
+WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY
+OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely
+responsible for determining the appropriateness of using and
+distributing the Program and assumes all risks associated with its
+exercise of rights under this Agreement, including but not limited to
+the risks and costs of program errors, compliance with applicable
+laws, damage to or loss of data, programs or equipment, and
+unavailability or interruption of operations.
+
+6. DISCLAIMER OF LIABILITY
+
+EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR
+ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING
+WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR
+DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
+HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+7. EXPORT CONTROL
+
+Recipient agrees that Recipient alone is responsible for compliance
+with the United States export administration regulations (and the
+export control laws and regulation of any other countries).
+
+8. GENERAL
+
+If any provision of this Agreement is invalid or unenforceable under
+applicable law, it shall not affect the validity or enforceability of
+the remainder of the terms of this Agreement, and without further
+action by the parties hereto, such provision shall be reformed to the
+minimum extent necessary to make such provision valid and enforceable.
+
+If Recipient institutes patent litigation against a Contributor with
+respect to a patent applicable to software (including a cross-claim or
+counterclaim in a lawsuit), then any patent licenses granted by that
+Contributor to such Recipient under this Agreement shall terminate as
+of the date such litigation is filed. In addition, if Recipient
+institutes patent litigation against any entity (including a
+cross-claim or counterclaim in a lawsuit) alleging that the Program
+itself (excluding combinations of the Program with other software or
+hardware) infringes such Recipient's patent(s), then such Recipient's
+rights granted under Section 2(b) shall terminate as of the date such
+litigation is filed.
+
+All Recipient's rights under this Agreement shall terminate if it
+fails to comply with any of the material terms or conditions of this
+Agreement and does not cure such failure in a reasonable period of
+time after becoming aware of such noncompliance. If all Recipient's
+rights under this Agreement terminate, Recipient agrees to cease use
+and distribution of the Program as soon as reasonably practicable.
+However, Recipient's obligations under this Agreement and any licenses
+granted by Recipient relating to the Program shall continue and
+survive.
+
+LUCENT may publish new versions (including revisions) of this
+Agreement from time to time. Each new version of the Agreement will be
+given a distinguishing version number. The Program (including
+Contributions) may always be distributed subject to the version of the
+Agreement under which it was received. In addition, after a new
+version of the Agreement is published, Contributor may elect to
+distribute the Program (including its Contributions) under the new
+version. No one other than LUCENT has the right to modify this
+Agreement. Except as expressly stated in Sections 2(a) and 2(b) above,
+Recipient receives no rights or licenses to the intellectual property
+of any Contributor under this Agreement, whether expressly, by
+implication, estoppel or otherwise. All rights in the Program not
+expressly granted under this Agreement are reserved.
+
+This Agreement is governed by the laws of the State of New York and
+the intellectual property laws of the United States of America. No
+party to this Agreement will bring a legal action under this Agreement
+more than one year after the cause of action arose. Each party waives
+its rights to a jury trial in any resulting litigation.
+
--- /dev/null
+++ b/os/boot.original/libflate/NOTICE
@@ -1,0 +1,8 @@
+Copyright © 2002 Lucent Technologies Inc.
+All Rights Reserved
+
+This software was originally developed for Plan 9.
+It is provided under the terms of the Lucent Public License, Version 1.02.
+
+Trivial modifications have been made to make it compile for Inferno.
+	Vita Nuova Holdings Limited.
--- /dev/null
+++ b/os/boot.original/libflate/adler.c
@@ -1,0 +1,71 @@
+#include "lib9.h"
+#include <flate.h>
+
+enum
+{
+	ADLERITERS	= 5552,	/* max iters before can overflow 32 bits */
+	ADLERBASE	= 65521 /* largest prime smaller than 65536 */
+};
+
+ulong
+adler32(ulong adler, void *vbuf, int n)
+{
+	ulong s1, s2;
+	uchar *buf, *ebuf;
+	int m;
+
+	buf = vbuf;
+	s1 = adler & 0xffff;
+	s2 = (adler >> 16) & 0xffff;
+	for(; n >= 16; n -= m){
+		m = n;
+		if(m > ADLERITERS)
+			m = ADLERITERS;
+		m &= ~15;
+		for(ebuf = buf + m; buf < ebuf; buf += 16){
+			s1 += buf[0];
+			s2 += s1;
+			s1 += buf[1];
+			s2 += s1;
+			s1 += buf[2];
+			s2 += s1;
+			s1 += buf[3];
+			s2 += s1;
+			s1 += buf[4];
+			s2 += s1;
+			s1 += buf[5];
+			s2 += s1;
+			s1 += buf[6];
+			s2 += s1;
+			s1 += buf[7];
+			s2 += s1;
+			s1 += buf[8];
+			s2 += s1;
+			s1 += buf[9];
+			s2 += s1;
+			s1 += buf[10];
+			s2 += s1;
+			s1 += buf[11];
+			s2 += s1;
+			s1 += buf[12];
+			s2 += s1;
+			s1 += buf[13];
+			s2 += s1;
+			s1 += buf[14];
+			s2 += s1;
+			s1 += buf[15];
+			s2 += s1;
+		}
+		s1 %= ADLERBASE;
+		s2 %= ADLERBASE;
+	}
+	if(n){
+		for(ebuf = buf + n; buf < ebuf; buf++){
+			s1 += buf[0];
+			s2 += s1;
+		}
+		s1 %= ADLERBASE;
+		s2 %= ADLERBASE;
+	}
+	return (s2 << 16) + s1;
+}
--- /dev/null
+++ b/os/boot.original/libflate/crc.c
@@ -1,0 +1,39 @@
+#include "lib9.h"
+#include <flate.h>
+
+ulong*
+mkcrctab(ulong poly)
+{
+	ulong *crctab;
+	ulong crc;
+	int i, j;
+
+	crctab = malloc(256 * sizeof(ulong));
+	if(crctab == nil)
+		return nil;
+
+	for(i = 0; i < 256; i++){
+		crc = i;
+		for(j = 0; j < 8; j++){
+			if(crc & 1)
+				crc = (crc >> 1) ^ poly;
+			else
+				crc >>= 1;
+		}
+		crctab[i] = crc;
+	}
+	return crctab;
+}
+
+ulong
+blockcrc(ulong *crctab, ulong crc, void *vbuf, int n)
+{
+	uchar *buf, *ebuf;
+
+	crc ^= 0xffffffff;
+	buf = vbuf;
+	ebuf = buf + n;
+	while(buf < ebuf)
+		crc = crctab[(crc & 0xff) ^ *buf++] ^ (crc >> 8);
+	return crc ^ 0xffffffff;
+}
--- /dev/null
+++ b/os/boot.original/libflate/deflate.c
@@ -1,0 +1,1358 @@
+#include "lib9.h"
+#include <flate.h>
+
+typedef struct Chain	Chain;
+typedef struct Chains	Chains;
+typedef struct Dyncode	Dyncode;
+typedef struct Huff	Huff;
+typedef struct LZblock	LZblock;
+typedef struct LZstate	LZstate;
+
+enum
+{
+	/*
+	 * deflate format paramaters
+	 */
+	DeflateUnc	= 0,			/* uncompressed block */
+	DeflateFix	= 1,			/* fixed huffman codes */
+	DeflateDyn	= 2,			/* dynamic huffman codes */
+
+	DeflateEob	= 256,			/* end of block code in lit/len book */
+	DeflateMaxBlock	= 64*1024-1,		/* maximum size of uncompressed block */
+
+	DeflateMaxExp	= 10,			/* maximum expansion for a block */
+
+	LenStart	= 257,			/* start of length codes in litlen */
+	Nlitlen		= 288,			/* number of litlen codes */
+	Noff		= 30,			/* number of offset codes */
+	Nclen		= 19,			/* number of codelen codes */
+
+	MaxOff		= 32*1024,
+	MinMatch	= 3,			/* shortest match possible */
+	MaxMatch	= 258,			/* longest match possible */
+
+	/*
+	 * huffman code paramaters
+	 */
+	MaxLeaf		= Nlitlen,
+	MaxHuffBits	= 16,			/* max bits in a huffman code */
+	ChainMem	= 2 * (MaxHuffBits - 1) * MaxHuffBits,
+
+	/*
+	 * coding of the lz parse
+	 */
+	LenFlag		= 1 << 3,
+	LenShift	= 4,			/* leaves enough space for MinMatchMaxOff */
+	MaxLitRun	= LenFlag - 1,
+
+	/*
+	 * internal lz paramaters
+	 */
+	DeflateOut	= 4096,			/* output buffer size */
+	BlockSize	= 8192,			/* attempted input read quanta */
+	DeflateBlock	= DeflateMaxBlock & ~(BlockSize - 1),
+	MinMatchMaxOff	= 4096,			/* max profitable offset for small match;
+						 * assumes 8 bits for len, 5+10 for offset
+						 * DONT CHANGE WITHOUT CHANGING LZPARSE CONSTANTS
+						 */
+	HistSlop	= 512,			/* must be at lead MaxMatch */
+	HistBlock	= 64*1024,
+	HistSize	= HistBlock + HistSlop,
+
+	HashLog		= 13,
+	HashSize	= 1<<HashLog,
+
+	MaxOffCode	= 256,			/* biggest offset looked up in direct table */
+
+	EstLitBits	= 8,
+	EstLenBits	= 4,
+	EstOffBits	= 5,
+};
+
+/*
+ * knuth vol. 3 multiplicative hashing
+ * each byte x chosen according to rules
+ * 1/4 < x < 3/10, 1/3 x < < 3/7, 4/7 < x < 2/3, 7/10 < x < 3/4
+ * with reasonable spread between the bytes & their complements
+ *
+ * the 3 byte value appears to be as almost good as the 4 byte value,
+ * and might be faster on some machines
+ */
+/*
+#define hashit(c)	(((ulong)(c) * 0x6b43a9) >> (24 - HashLog))
+*/
+#define hashit(c)	((((ulong)(c) & 0xffffff) * 0x6b43a9b5) >> (32 - HashLog))
+
+/*
+ * lempel-ziv style compression state
+ */
+struct LZstate
+{
+	uchar	hist[HistSize];
+	ulong	pos;				/* current location in history buffer */
+	ulong	avail;				/* data available after pos */
+	int	eof;
+	ushort	hash[HashSize];			/* hash chains */
+	ushort	nexts[MaxOff];
+	int	now;				/* pos in hash chains */
+	int	dot;				/* dawn of time in history */
+	int	prevlen;			/* lazy matching state */
+	int	prevoff;
+	int	maxcheck;			/* compressor tuning */
+
+	uchar	obuf[DeflateOut];
+	uchar	*out;				/* current position in the output buffer */
+	uchar	*eout;
+	ulong	bits;				/* bit shift register */
+	int	nbits;
+	int	rbad;				/* got an error reading the buffer */
+	int	wbad;				/* got an error writing the buffer */
+	int	(*w)(void*, void*, int);
+	void	*wr;
+
+	ulong	totr;				/* total input size */
+	ulong	totw;				/* total output size */
+	int	debug;
+};
+
+struct LZblock
+{
+	ushort	parse[DeflateMaxBlock / 2 + 1];
+	int	lastv;				/* value being constucted for parse */
+	ulong	litlencount[Nlitlen];
+	ulong	offcount[Noff];
+	ushort	*eparse;			/* limit for parse table */
+	int	bytes;				/* consumed from the input */
+	int	excost;				/* cost of encoding extra len & off bits */
+};
+
+/*
+ * huffman code table
+ */
+struct Huff
+{
+	short	bits;				/* length of the code */
+	ushort	encode;				/* the code */
+};
+
+/*
+ * encoding of dynamic huffman trees
+ */
+struct Dyncode
+{
+	int	nlit;
+	int	noff;
+	int	nclen;
+	int	ncode;
+	Huff	codetab[Nclen];
+	uchar	codes[Nlitlen+Noff];
+	uchar	codeaux[Nlitlen+Noff];
+};
+
+static	int	deflateb(LZstate *lz, LZblock *lzb, void *rr, int (*r)(void*, void*, int));
+static	int	lzcomp(LZstate*, LZblock*, uchar*, ushort*, int finish);
+static	void	wrblock(LZstate*, int, ushort*, ushort*, Huff*, Huff*);
+static	int	bitcost(Huff*, ulong*, int);
+static	int	huffcodes(Dyncode*, Huff*, Huff*);
+static	void	wrdyncode(LZstate*, Dyncode*);
+static	void	lzput(LZstate*, ulong bits, int nbits);
+static	void	lzflushbits(LZstate*);
+static	void	lzflush(LZstate *lz);
+static	void	lzwrite(LZstate *lz, void *buf, int n);
+
+static	int	hufftabinit(Huff*, int, ulong*, int);
+static	int	mkgzprecode(Huff*, ulong *, int, int);
+
+static	int	mkprecode(Huff*, ulong *, int, int, ulong*);
+static	void	nextchain(Chains*, int);
+static	void	leafsort(ulong*, ushort*, int, int);
+
+/* conversion from len to code word */
+static int lencode[MaxMatch];
+
+/*
+ * conversion from off to code word
+ * off <= MaxOffCode ? offcode[off] : bigoffcode[off >> 7]
+*/
+static int offcode[MaxOffCode];
+static int bigoffcode[256];
+
+/* litlen code words LenStart-285 extra bits */
+static int litlenbase[Nlitlen-LenStart];
+static int litlenextra[Nlitlen-LenStart] =
+{
+/* 257 */	0, 0, 0,
+/* 260 */	0, 0, 0, 0, 0, 1, 1, 1, 1, 2,
+/* 270 */	2, 2, 2, 3, 3, 3, 3, 4, 4, 4,
+/* 280 */	4, 5, 5, 5, 5, 0, 0, 0
+};
+
+/* offset code word extra bits */
+static int offbase[Noff];
+static int offextra[] =
+{
+	0,  0,  0,  0,  1,  1,  2,  2,  3,  3,
+	4,  4,  5,  5,  6,  6,  7,  7,  8,  8,
+	9,  9,  10, 10, 11, 11, 12, 12, 13, 13,
+	0,  0,
+};
+
+/* order code lengths */
+static int clenorder[Nclen] =
+{
+        16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
+};
+
+/* static huffman tables */
+static	Huff	litlentab[Nlitlen];
+static	Huff	offtab[Noff];
+static	Huff	hofftab[Noff];
+
+/* bit reversal for brain dead endian swap in huffman codes */
+static	uchar	revtab[256];
+static	ulong	nlits;
+static	ulong	nmatches;
+
+int
+deflateinit(void)
+{
+	ulong bitcount[MaxHuffBits];
+	int i, j, ci, n;
+
+	/* byte reverse table */
+	for(i=0; i<256; i++)
+		for(j=0; j<8; j++)
+			if(i & (1<<j))
+				revtab[i] |= 0x80 >> j;
+
+	/* static Litlen bit lengths */
+	for(i=0; i<144; i++)
+		litlentab[i].bits = 8;
+	for(i=144; i<256; i++)
+		litlentab[i].bits = 9;
+	for(i=256; i<280; i++)
+		litlentab[i].bits = 7;
+	for(i=280; i<Nlitlen; i++)
+		litlentab[i].bits = 8;
+
+	memset(bitcount, 0, sizeof(bitcount));
+	bitcount[8] += 144 - 0;
+	bitcount[9] += 256 - 144;
+	bitcount[7] += 280 - 256;
+	bitcount[8] += Nlitlen - 280;
+
+	if(!hufftabinit(litlentab, Nlitlen, bitcount, 9))
+		return FlateInternal;
+
+	/* static offset bit lengths */
+	for(i = 0; i < Noff; i++)
+		offtab[i].bits = 5;
+
+	memset(bitcount, 0, sizeof(bitcount));
+	bitcount[5] = Noff;
+
+	if(!hufftabinit(offtab, Noff, bitcount, 5))
+		return FlateInternal;
+
+	bitcount[0] = 0;
+	bitcount[1] = 0;
+	if(!mkgzprecode(hofftab, bitcount, 2, MaxHuffBits))
+		return FlateInternal;
+
+	/* conversion tables for lens & offs to codes */
+	ci = 0;
+	for(i = LenStart; i < 286; i++){
+		n = ci + (1 << litlenextra[i - LenStart]);
+		litlenbase[i - LenStart] = ci;
+		for(; ci < n; ci++)
+			lencode[ci] = i;
+	}
+	/* patch up special case for len MaxMatch */
+	lencode[MaxMatch-MinMatch] = 285;
+	litlenbase[285-LenStart] = MaxMatch-MinMatch;
+
+	ci = 0;
+	for(i = 0; i < 16; i++){
+		n = ci + (1 << offextra[i]);
+		offbase[i] = ci;
+		for(; ci < n; ci++)
+			offcode[ci] = i;
+	}
+
+	ci = ci >> 7;
+	for(; i < 30; i++){
+		n = ci + (1 << (offextra[i] - 7));
+		offbase[i] = ci << 7;
+		for(; ci < n; ci++)
+			bigoffcode[ci] = i;
+	}
+	return FlateOk;
+}
+
+static void
+deflatereset(LZstate *lz, int level, int debug)
+{
+	memset(lz->nexts, 0, sizeof lz->nexts);
+	memset(lz->hash, 0, sizeof lz->hash);
+	lz->totr = 0;
+	lz->totw = 0;
+	lz->pos = 0;
+	lz->avail = 0;
+	lz->out = lz->obuf;
+	lz->eout = &lz->obuf[DeflateOut];
+	lz->prevlen = MinMatch - 1;
+	lz->prevoff = 0;
+	lz->now = MaxOff + 1;
+	lz->dot = lz->now;
+	lz->bits = 0;
+	lz->nbits = 0;
+	lz->maxcheck = (1 << level);
+	lz->maxcheck -= lz->maxcheck >> 2;
+	if(lz->maxcheck < 2)
+		lz->maxcheck = 2;
+	else if(lz->maxcheck > 1024)
+		lz->maxcheck = 1024;
+
+	lz->debug = debug;
+}
+
+int
+deflate(void *wr, int (*w)(void*, void*, int), void *rr, int (*r)(void*, void*, int), int level, int debug)
+{
+	LZstate *lz;
+	LZblock *lzb;
+	int ok;
+
+	lz = malloc(sizeof *lz + sizeof *lzb);
+	if(lz == nil)
+		return FlateNoMem;
+	lzb = (LZblock*)&lz[1];
+
+	deflatereset(lz, level, debug);
+	lz->w = w;
+	lz->wr = wr;
+	lz->wbad = 0;
+	lz->rbad = 0;
+	lz->eof = 0;
+	ok = FlateOk;
+	while(!lz->eof || lz->avail){
+		ok = deflateb(lz, lzb, rr, r);
+		if(ok != FlateOk)
+			break;
+	}
+	if(ok == FlateOk && lz->rbad)
+		ok = FlateInputFail;
+	if(ok == FlateOk && lz->wbad)
+		ok = FlateOutputFail;
+	free(lz);
+	return ok;
+}
+
+static int
+deflateb(LZstate *lz, LZblock *lzb, void *rr, int (*r)(void*, void*, int))
+{
+	Dyncode dyncode, hdyncode;
+	Huff dlitlentab[Nlitlen], dofftab[Noff], hlitlentab[Nlitlen];
+	ulong litcount[Nlitlen];
+	long nunc, ndyn, nfix, nhuff;
+	uchar *slop, *hslop;
+	ulong ep;
+	int i, n, m, mm, nslop;
+
+	memset(lzb->litlencount, 0, sizeof lzb->litlencount);
+	memset(lzb->offcount, 0, sizeof lzb->offcount);
+	lzb->litlencount[DeflateEob]++;
+
+	lzb->bytes = 0;
+	lzb->eparse = lzb->parse;
+	lzb->lastv = 0;
+	lzb->excost = 0;
+
+	slop = &lz->hist[lz->pos];
+	n = lz->avail;
+	while(n < DeflateBlock && (!lz->eof || lz->avail)){
+		/*
+		 * fill the buffer as much as possible,
+		 * while leaving room for MaxOff history behind lz->pos,
+		 * and not reading more than we can handle.
+		 *
+		 * make sure we read at least HistSlop bytes.
+		 */
+		if(!lz->eof){
+			ep = lz->pos + lz->avail;
+			if(ep >= HistBlock)
+				ep -= HistBlock;
+			m = HistBlock - MaxOff - lz->avail;
+			if(m > HistBlock - n)
+				m = HistBlock - n;
+			if(m > (HistBlock + HistSlop) - ep)
+				m = (HistBlock + HistSlop) - ep;
+			if(m & ~(BlockSize - 1))
+				m &= ~(BlockSize - 1);
+
+			/*
+			 * be nice to the caller: stop reads that are too small.
+			 * can only get here when we've already filled the buffer some
+			 */
+			if(m < HistSlop){
+				if(!m || !lzb->bytes)
+					return FlateInternal;
+				break;
+			}
+
+			mm = (*r)(rr, &lz->hist[ep], m);
+			if(mm > 0){
+				/*
+				 * wrap data to end if we're read it from the beginning
+				 * this way, we don't have to wrap searches.
+				 *
+				 * wrap reads past the end to the beginning.
+				 * this way, we can guarantee minimum size reads.
+				 */
+				if(ep < HistSlop)
+					memmove(&lz->hist[ep + HistBlock], &lz->hist[ep], HistSlop - ep);
+				else if(ep + mm > HistBlock)
+					memmove(&lz->hist[0], &lz->hist[HistBlock], ep + mm - HistBlock);
+
+				lz->totr += mm;
+				n += mm;
+				lz->avail += mm;
+			}else{
+				if(mm < 0)
+					lz->rbad = 1;
+				lz->eof = 1;
+			}
+		}
+		ep = lz->pos + lz->avail;
+		if(ep > HistSize)
+			ep = HistSize;
+		if(lzb->bytes + ep - lz->pos > DeflateMaxBlock)
+			ep = lz->pos + DeflateMaxBlock - lzb->bytes;
+		m = lzcomp(lz, lzb, &lz->hist[ep], lzb->eparse, lz->eof);
+		lzb->bytes += m;
+		lz->pos = (lz->pos + m) & (HistBlock - 1);
+		lz->avail -= m;
+	}
+	if(lzb->lastv)
+		*lzb->eparse++ = lzb->lastv;
+	if(lzb->eparse > lzb->parse + nelem(lzb->parse))
+		return FlateInternal;
+	nunc = lzb->bytes;
+
+	if(!mkgzprecode(dlitlentab, lzb->litlencount, Nlitlen, MaxHuffBits)
+	|| !mkgzprecode(dofftab, lzb->offcount, Noff, MaxHuffBits))
+		return FlateInternal;
+
+	ndyn = huffcodes(&dyncode, dlitlentab, dofftab);
+	if(ndyn < 0)
+		return FlateInternal;
+	ndyn += bitcost(dlitlentab, lzb->litlencount, Nlitlen)
+		+ bitcost(dofftab, lzb->offcount, Noff)
+		+ lzb->excost;
+
+	memset(litcount, 0, sizeof litcount);
+
+	nslop = nunc;
+	if(nslop > &lz->hist[HistSize] - slop)
+		nslop = &lz->hist[HistSize] - slop;
+
+	for(i = 0; i < nslop; i++)
+		litcount[slop[i]]++;
+	hslop = &lz->hist[HistSlop - nslop];
+	for(; i < nunc; i++)
+		litcount[hslop[i]]++;
+	litcount[DeflateEob]++;
+
+	if(!mkgzprecode(hlitlentab, litcount, Nlitlen, MaxHuffBits))
+		return FlateInternal;
+	nhuff = huffcodes(&hdyncode, hlitlentab, hofftab);
+	if(nhuff < 0)
+		return FlateInternal;
+	nhuff += bitcost(hlitlentab, litcount, Nlitlen);
+
+	nfix = bitcost(litlentab, lzb->litlencount, Nlitlen)
+		+ bitcost(offtab, lzb->offcount, Noff)
+		+ lzb->excost;
+
+	lzput(lz, lz->eof && !lz->avail, 1);
+
+	if(lz->debug){
+		fprint(2, "block: bytes=%lud entries=%ld extra bits=%d\n\tuncompressed=%lud fixed=%lud dynamic=%lud huffman=%lud\n",
+			nunc, lzb->eparse - lzb->parse, lzb->excost, (nunc + 4) * 8, nfix, ndyn, nhuff);
+		fprint(2, "\tnlit=%lud matches=%lud eof=%d\n", nlits, nmatches, lz->eof && !lz->avail);
+	}
+
+	if((nunc + 4) * 8 < ndyn && (nunc + 4) * 8 < nfix && (nunc + 4) * 8 < nhuff){
+		lzput(lz, DeflateUnc, 2);
+		lzflushbits(lz);
+
+		lzput(lz, nunc & 0xff, 8);
+		lzput(lz, (nunc >> 8) & 0xff, 8);
+		lzput(lz, ~nunc & 0xff, 8);
+		lzput(lz, (~nunc >> 8) & 0xff, 8);
+		lzflush(lz);
+
+		lzwrite(lz, slop, nslop);
+		lzwrite(lz, &lz->hist[HistSlop], nunc - nslop);
+	}else if(ndyn < nfix && ndyn < nhuff){
+		lzput(lz, DeflateDyn, 2);
+
+		wrdyncode(lz, &dyncode);
+		wrblock(lz, slop - lz->hist, lzb->parse, lzb->eparse, dlitlentab, dofftab);
+		lzput(lz, dlitlentab[DeflateEob].encode, dlitlentab[DeflateEob].bits);
+	}else if(nhuff < nfix){
+		lzput(lz, DeflateDyn, 2);
+
+		wrdyncode(lz, &hdyncode);
+
+		m = 0;
+		for(i = nunc; i > MaxLitRun; i -= MaxLitRun)
+			lzb->parse[m++] = MaxLitRun;
+		lzb->parse[m++] = i;
+
+		wrblock(lz, slop - lz->hist, lzb->parse, lzb->parse + m, hlitlentab, hofftab);
+		lzput(lz, hlitlentab[DeflateEob].encode, hlitlentab[DeflateEob].bits);
+	}else{
+		lzput(lz, DeflateFix, 2);
+
+		wrblock(lz, slop - lz->hist, lzb->parse, lzb->eparse, litlentab, offtab);
+		lzput(lz, litlentab[DeflateEob].encode, litlentab[DeflateEob].bits);
+	}
+
+	if(lz->eof && !lz->avail){
+		lzflushbits(lz);
+		lzflush(lz);
+	}
+	return FlateOk;
+}
+
+static void
+lzwrite(LZstate *lz, void *buf, int n)
+{
+	int nw;
+
+	if(n && lz->w){
+		nw = (*lz->w)(lz->wr, buf, n);
+		if(nw != n){
+			lz->w = nil;
+			lz->wbad = 1;
+		}else
+			lz->totw += n;
+	}
+}
+
+static void
+lzflush(LZstate *lz)
+{
+	lzwrite(lz, lz->obuf, lz->out - lz->obuf);
+	lz->out = lz->obuf;
+}
+
+static void
+lzput(LZstate *lz, ulong bits, int nbits)
+{
+	bits = (bits << lz->nbits) | lz->bits;
+	for(nbits += lz->nbits; nbits >= 8; nbits -= 8){
+		*lz->out++ = bits;
+		if(lz->out == lz->eout)
+			lzflush(lz);
+		bits >>= 8;
+	}
+	lz->bits = bits;
+	lz->nbits = nbits;
+}
+
+static void
+lzflushbits(LZstate *lz)
+{
+	if(lz->nbits)
+		lzput(lz, 0, 8 - (lz->nbits & 7));
+}
+
+/*
+ * write out a block of n samples,
+ * given lz encoding and counts for huffman tables
+ */
+static void
+wrblock(LZstate *out, int litoff, ushort *soff, ushort *eoff, Huff *litlentab, Huff *offtab)
+{
+	ushort *off;
+	int i, run, offset, lit, len, c;
+
+	if(out->debug > 2){
+		for(off = soff; off < eoff; ){
+			offset = *off++;
+			run = offset & MaxLitRun;
+			if(run){
+				for(i = 0; i < run; i++){
+					lit = out->hist[litoff & (HistBlock - 1)];
+					litoff++;
+					fprint(2, "\tlit %.2ux %c\n", lit, lit);
+				}
+				if(!(offset & LenFlag))
+					continue;
+				len = offset >> LenShift;
+				offset = *off++;
+			}else if(offset & LenFlag){
+				len = offset >> LenShift;
+				offset = *off++;
+			}else{
+				len = 0;
+				offset >>= LenShift;
+			}
+			litoff += len + MinMatch;
+			fprint(2, "\t<%d, %d>\n", offset + 1, len + MinMatch);
+		}
+	}
+
+	for(off = soff; off < eoff; ){
+		offset = *off++;
+		run = offset & MaxLitRun;
+		if(run){
+			for(i = 0; i < run; i++){
+				lit = out->hist[litoff & (HistBlock - 1)];
+				litoff++;
+				lzput(out, litlentab[lit].encode, litlentab[lit].bits);
+			}
+			if(!(offset & LenFlag))
+				continue;
+			len = offset >> LenShift;
+			offset = *off++;
+		}else if(offset & LenFlag){
+			len = offset >> LenShift;
+			offset = *off++;
+		}else{
+			len = 0;
+			offset >>= LenShift;
+		}
+		litoff += len + MinMatch;
+		c = lencode[len];
+		lzput(out, litlentab[c].encode, litlentab[c].bits);
+		c -= LenStart;
+		if(litlenextra[c])
+			lzput(out, len - litlenbase[c], litlenextra[c]);
+
+		if(offset < MaxOffCode)
+			c = offcode[offset];
+		else
+			c = bigoffcode[offset >> 7];
+		lzput(out, offtab[c].encode, offtab[c].bits);
+		if(offextra[c])
+			lzput(out, offset - offbase[c], offextra[c]);
+	}
+}
+
+/*
+ * look for the longest, closest string which matches
+ * the next prefix.  the clever part here is looking for
+ * a string 1 longer than the previous best match.
+ *
+ * follows the recommendation of limiting number of chains
+ * which are checked.  this appears to be the best heuristic.
+ */
+static int
+lzmatch(int now, int then, uchar *p, uchar *es, ushort *nexts, uchar *hist, int runlen, int check, int *m)
+{
+	uchar *s, *t;
+	int ml, off, last;
+
+	ml = check;
+	if(runlen >= 8)
+		check >>= 2;
+	*m = 0;
+	if(p + runlen >= es)
+		return runlen;
+	last = 0;
+	for(; check-- > 0; then = nexts[then & (MaxOff-1)]){
+		off = (ushort)(now - then);
+		if(off <= last || off > MaxOff)
+			break;
+		s = p + runlen;
+		t = hist + (((p - hist) - off) & (HistBlock-1));
+		t += runlen;
+		for(; s >= p; s--){
+			if(*s != *t)
+				goto matchloop;
+			t--;
+		}
+
+		/*
+		 * we have a new best match.
+		 * extend it to it's maximum length
+		 */
+		t += runlen + 2;
+		s += runlen + 2;
+		for(; s < es; s++){
+			if(*s != *t)
+				break;
+			t++;
+		}
+		runlen = s - p;
+		*m = off - 1;
+		if(s == es || runlen > ml)
+			break;
+matchloop:;
+		last = off;
+	}
+	return runlen;
+}
+
+static int
+lzcomp(LZstate *lz, LZblock *lzb, uchar *ep, ushort *parse, int finish)
+{
+	ulong cont, excost, *litlencount, *offcount;
+	uchar *p, *q, *s, *es;
+	ushort *nexts, *hash;
+	int v, i, h, runlen, n, now, then, m, prevlen, prevoff, maxdefer;
+
+	litlencount = lzb->litlencount;
+	offcount = lzb->offcount;
+	nexts = lz->nexts;
+	hash = lz->hash;
+	now = lz->now;
+
+	p = &lz->hist[lz->pos];
+	if(lz->prevlen != MinMatch - 1)
+		p++;
+
+	/*
+	 * hash in the links for any hanging link positions,
+	 * and calculate the hash for the current position.
+	 */
+	n = MinMatch;
+	if(n > ep - p)
+		n = ep - p;
+	cont = 0;
+	for(i = 0; i < n - 1; i++){
+		m = now - ((MinMatch-1) - i);
+		if(m < lz->dot)
+			continue;
+		s = lz->hist + (((p - lz->hist) - (now - m)) & (HistBlock-1));
+
+		cont = (s[0] << 16) | (s[1] << 8) | s[2];
+		h = hashit(cont);
+		prevoff = 0;
+		for(then = hash[h]; ; then = nexts[then & (MaxOff-1)]){
+			v = (ushort)(now - then);
+			if(v <= prevoff || v >= (MinMatch-1) - i)
+				break;
+			prevoff = v;
+		}
+		if(then == (ushort)m)
+			continue;
+		nexts[m & (MaxOff-1)] = hash[h];
+		hash[h] = m;
+	}
+	for(i = 0; i < n; i++)
+		cont = (cont << 8) | p[i];
+
+	/*
+	 * now must point to the index in the nexts array
+	 * corresponding to p's position in the history
+	 */
+	prevlen = lz->prevlen;
+	prevoff = lz->prevoff;
+	maxdefer = lz->maxcheck >> 2;
+	excost = 0;
+	v = lzb->lastv;
+	for(;;){
+		es = p + MaxMatch;
+		if(es > ep){
+			if(!finish || p >= ep)
+				break;
+			es = ep;
+		}
+
+		h = hashit(cont);
+		runlen = lzmatch(now, hash[h], p, es, nexts, lz->hist, prevlen, lz->maxcheck, &m);
+
+		/*
+		 * back out of small matches too far in the past
+		 */
+		if(runlen == MinMatch && m >= MinMatchMaxOff){
+			runlen = MinMatch - 1;
+			m = 0;
+		}
+
+		/*
+		 * record the encoding and increment counts for huffman trees
+		 * if we get a match, defer selecting it until we check for
+		 * a longer match at the next position.
+		 */
+		if(prevlen >= runlen && prevlen != MinMatch - 1){
+			/*
+			 * old match at least as good; use that one
+			 */
+			n = prevlen - MinMatch;
+			if(v || n){
+				*parse++ = v | LenFlag | (n << LenShift);
+				*parse++ = prevoff;
+			}else
+				*parse++ = prevoff << LenShift;
+			v = 0;
+
+			n = lencode[n];
+			litlencount[n]++;
+			excost += litlenextra[n - LenStart];
+
+			if(prevoff < MaxOffCode)
+				n = offcode[prevoff];
+			else
+				n = bigoffcode[prevoff >> 7];
+			offcount[n]++;
+			excost += offextra[n];
+
+			runlen = prevlen - 1;
+			prevlen = MinMatch - 1;
+			nmatches++;
+		}else if(runlen == MinMatch - 1){
+			/*
+			 * no match; just put out the literal
+			 */
+			if(++v == MaxLitRun){
+				*parse++ = v;
+				v = 0;
+			}
+			litlencount[*p]++;
+			nlits++;
+			runlen = 1;
+		}else{
+			if(prevlen != MinMatch - 1){
+				/*
+				 * longer match now. output previous literal,
+				 * update current match, and try again
+				 */
+				if(++v == MaxLitRun){
+					*parse++ = v;
+					v = 0;
+				}
+				litlencount[p[-1]]++;
+				nlits++;
+			}
+
+			prevoff = m;
+
+			if(runlen < maxdefer){
+				prevlen = runlen;
+				runlen = 1;
+			}else{
+				n = runlen - MinMatch;
+				if(v || n){
+					*parse++ = v | LenFlag | (n << LenShift);
+					*parse++ = prevoff;
+				}else
+					*parse++ = prevoff << LenShift;
+				v = 0;
+
+				n = lencode[n];
+				litlencount[n]++;
+				excost += litlenextra[n - LenStart];
+
+				if(prevoff < MaxOffCode)
+					n = offcode[prevoff];
+				else
+					n = bigoffcode[prevoff >> 7];
+				offcount[n]++;
+				excost += offextra[n];
+
+				prevlen = MinMatch - 1;
+				nmatches++;
+			}
+		}
+
+		/*
+		 * update the hash for the newly matched data
+		 * this is constructed so the link for the old
+		 * match in this position must be at the end of a chain,
+		 * and will expire when this match is added, ie it will
+		 * never be examined by the match loop.
+		 * add to the hash chain only if we have the real hash data.
+		 */
+		for(q = p + runlen; p != q; p++){
+			if(p + MinMatch <= ep){
+				h = hashit(cont);
+				nexts[now & (MaxOff-1)] = hash[h];
+				hash[h] = now;
+				if(p + MinMatch < ep)
+					cont = (cont << 8) | p[MinMatch];
+			}
+			now++;
+		}
+	}
+
+	/*
+	 * we can just store away the lazy state and
+	 * pick it up next time.  the last block will have finish set
+	 * so we won't have any pending matches
+	 * however, we need to correct for how much we've encoded
+	 */
+	if(prevlen != MinMatch - 1)
+		p--;
+
+	lzb->excost += excost;
+	lzb->eparse = parse;
+	lzb->lastv = v;
+
+	lz->now = now;
+	lz->prevlen = prevlen;
+	lz->prevoff = prevoff;
+
+	return p - &lz->hist[lz->pos];
+}
+
+/*
+ * make up the dynamic code tables, and return the number of bits
+ * needed to transmit them.
+ */
+static int
+huffcodes(Dyncode *dc, Huff *littab, Huff *offtab)
+{
+	Huff *codetab;
+	uchar *codes, *codeaux;
+	ulong codecount[Nclen], excost;
+	int i, n, m, v, c, nlit, noff, ncode, nclen;
+
+	codetab = dc->codetab;
+	codes = dc->codes;
+	codeaux = dc->codeaux;
+
+	/*
+	 * trim the sizes of the tables
+	 */
+	for(nlit = Nlitlen; nlit > 257 && littab[nlit-1].bits == 0; nlit--)
+		;
+	for(noff = Noff; noff > 1 && offtab[noff-1].bits == 0; noff--)
+		;
+
+	/*
+	 * make the code-length code
+	 */
+	for(i = 0; i < nlit; i++)
+		codes[i] = littab[i].bits;
+	for(i = 0; i < noff; i++)
+		codes[i + nlit] = offtab[i].bits;
+
+	/*
+	 * run-length compress the code-length code
+	 */
+	excost = 0;
+	c = 0;
+	ncode = nlit+noff;
+	for(i = 0; i < ncode; ){
+		n = i + 1;
+		v = codes[i];
+		while(n < ncode && v == codes[n])
+			n++;
+		n -= i;
+		i += n;
+		if(v == 0){
+			while(n >= 11){
+				m = n;
+				if(m > 138)
+					m = 138;
+				codes[c] = 18;
+				codeaux[c++] = m - 11;
+				n -= m;
+				excost += 7;
+			}
+			if(n >= 3){
+				codes[c] = 17;
+				codeaux[c++] = n - 3;
+				n = 0;
+				excost += 3;
+			}
+		}
+		while(n--){
+			codes[c++] = v;
+			while(n >= 3){
+				m = n;
+				if(m > 6)
+					m = 6;
+				codes[c] = 16;
+				codeaux[c++] = m - 3;
+				n -= m;
+				excost += 3;
+			}
+		}
+	}
+
+	memset(codecount, 0, sizeof codecount);
+	for(i = 0; i < c; i++)
+		codecount[codes[i]]++;
+	if(!mkgzprecode(codetab, codecount, Nclen, 8))
+		return -1;
+
+	for(nclen = Nclen; nclen > 4 && codetab[clenorder[nclen-1]].bits == 0; nclen--)
+		;
+
+	dc->nlit = nlit;
+	dc->noff = noff;
+	dc->nclen = nclen;
+	dc->ncode = c;
+
+	return 5 + 5 + 4 + nclen * 3 + bitcost(codetab, codecount, Nclen) + excost;
+}
+
+static void
+wrdyncode(LZstate *out, Dyncode *dc)
+{
+	Huff *codetab;
+	uchar *codes, *codeaux;
+	int i, v, c;
+
+	/*
+	 * write out header, then code length code lengths,
+	 * and code lengths
+	 */
+	lzput(out, dc->nlit-257, 5);
+	lzput(out, dc->noff-1, 5);
+	lzput(out, dc->nclen-4, 4);
+
+	codetab = dc->codetab;
+	for(i = 0; i < dc->nclen; i++)
+		lzput(out, codetab[clenorder[i]].bits, 3);
+
+	codes = dc->codes;
+	codeaux = dc->codeaux;
+	c = dc->ncode;
+	for(i = 0; i < c; i++){
+		v = codes[i];
+		lzput(out, codetab[v].encode, codetab[v].bits);
+		if(v >= 16){
+			if(v == 16)
+				lzput(out, codeaux[i], 2);
+			else if(v == 17)
+				lzput(out, codeaux[i], 3);
+			else /* v == 18 */
+				lzput(out, codeaux[i], 7);
+		}
+	}
+}
+
+static int
+bitcost(Huff *tab, ulong *count, int n)
+{
+	ulong tot;
+	int i;
+
+	tot = 0;
+	for(i = 0; i < n; i++)
+		tot += count[i] * tab[i].bits;
+	return tot;
+}
+
+static int
+mkgzprecode(Huff *tab, ulong *count, int n, int maxbits)
+{
+	ulong bitcount[MaxHuffBits];
+	int i, nbits;
+
+	nbits = mkprecode(tab, count, n, maxbits, bitcount);
+	for(i = 0; i < n; i++){
+		if(tab[i].bits == -1)
+			tab[i].bits = 0;
+		else if(tab[i].bits == 0){
+			if(nbits != 0 || bitcount[0] != 1)
+				return 0;
+			bitcount[1] = 1;
+			bitcount[0] = 0;
+			nbits = 1;
+			tab[i].bits = 1;
+		}
+	}
+	if(bitcount[0] != 0)
+		return 0;
+	return hufftabinit(tab, n, bitcount, nbits);
+}
+
+static int
+hufftabinit(Huff *tab, int n, ulong *bitcount, int nbits)
+{
+	ulong code, nc[MaxHuffBits];
+	int i, bits;
+
+	code = 0;
+	for(bits = 1; bits <= nbits; bits++){
+		code = (code + bitcount[bits-1]) << 1;
+		nc[bits] = code;
+	}
+
+	for(i = 0; i < n; i++){
+		bits = tab[i].bits;
+		if(bits){
+			code = nc[bits]++ << (16 - bits);
+			if(code & ~0xffff)
+				return 0;
+			tab[i].encode = revtab[code >> 8] | (revtab[code & 0xff] << 8);
+		}
+	}
+	return 1;
+}
+
+
+/*
+ * this should be in a library
+ */
+struct Chain
+{
+	ulong	count;				/* occurances of everything in the chain */
+	ushort	leaf;				/* leaves to the left of chain, or leaf value */
+	char	col;				/* ref count for collecting unused chains */
+	char	gen;				/* need to generate chains for next lower level */
+	Chain	*up;				/* Chain up in the lists */
+};
+
+struct Chains
+{
+	Chain	*lists[(MaxHuffBits - 1) * 2];
+	ulong	leafcount[MaxLeaf];		/* sorted list of leaf counts */
+	ushort	leafmap[MaxLeaf];		/* map to actual leaf number */
+	int	nleaf;				/* number of leaves */
+	Chain	chains[ChainMem];
+	Chain	*echains;
+	Chain	*free;
+	char	col;
+	int	nlists;
+};
+
+/*
+ * fast, low space overhead algorithm for max depth huffman type codes
+ *
+ * J. Katajainen, A. Moffat and A. Turpin, "A fast and space-economical
+ * algorithm for length-limited coding," Proc. Intl. Symp. on Algorithms
+ * and Computation, Cairns, Australia, Dec. 1995, Lecture Notes in Computer
+ * Science, Vol 1004, J. Staples, P. Eades, N. Katoh, and A. Moffat, eds.,
+ * pp 12-21, Springer Verlag, New York, 1995.
+ */
+static int
+mkprecode(Huff *tab, ulong *count, int n, int maxbits, ulong *bitcount)
+{
+	Chains cs;
+	Chain *c;
+	int i, m, em, bits;
+
+	/*
+	 * set up the sorted list of leaves
+	 */
+	m = 0;
+	for(i = 0; i < n; i++){
+		tab[i].bits = -1;
+		tab[i].encode = 0;
+		if(count[i] != 0){
+			cs.leafcount[m] = count[i];
+			cs.leafmap[m] = i;
+			m++;
+		}
+	}
+	if(m < 2){
+		if(m != 0){
+			tab[cs.leafmap[0]].bits = 0;
+			bitcount[0] = 1;
+		}else
+			bitcount[0] = 0;
+		return 0;
+	}
+	cs.nleaf = m;
+	leafsort(cs.leafcount, cs.leafmap, 0, m);
+
+	for(i = 0; i < m; i++)
+		cs.leafcount[i] = count[cs.leafmap[i]];
+
+	/*
+	 * set up free list
+	 */
+	cs.free = &cs.chains[2];
+	cs.echains = &cs.chains[ChainMem];
+	cs.col = 1;
+
+	/*
+	 * initialize chains for each list
+	 */
+	c = &cs.chains[0];
+	c->count = cs.leafcount[0];
+	c->leaf = 1;
+	c->col = cs.col;
+	c->up = nil;
+	c->gen = 0;
+	cs.chains[1] = cs.chains[0];
+	cs.chains[1].leaf = 2;
+	cs.chains[1].count = cs.leafcount[1];
+	for(i = 0; i < maxbits-1; i++){
+		cs.lists[i * 2] = &cs.chains[0];
+		cs.lists[i * 2 + 1] = &cs.chains[1];
+	}
+
+	cs.nlists = 2 * (maxbits - 1);
+	m = 2 * m - 2;
+	for(i = 2; i < m; i++)
+		nextchain(&cs, cs.nlists - 2);
+
+	bits = 0;
+	bitcount[0] = cs.nleaf;
+	for(c = cs.lists[cs.nlists - 1]; c != nil; c = c->up){
+		m = c->leaf;
+		bitcount[bits++] -= m;
+		bitcount[bits] = m;
+	}
+	m = 0;
+	for(i = bits; i >= 0; i--)
+		for(em = m + bitcount[i]; m < em; m++)
+			tab[cs.leafmap[m]].bits = i;
+
+	return bits;
+}
+
+/*
+ * calculate the next chain on the list
+ * we can always toss out the old chain
+ */
+static void
+nextchain(Chains *cs, int list)
+{
+	Chain *c, *oc;
+	int i, nleaf, sumc;
+
+	oc = cs->lists[list + 1];
+	cs->lists[list] = oc;
+	if(oc == nil)
+		return;
+
+	/*
+	 * make sure we have all chains needed to make sumc
+	 * note it is possible to generate only one of these,
+	 * use twice that value for sumc, and then generate
+	 * the second if that preliminary sumc would be chosen.
+	 * however, this appears to be slower on current tests
+	 */
+	if(oc->gen){
+		nextchain(cs, list - 2);
+		nextchain(cs, list - 2);
+		oc->gen = 0;
+	}
+
+	/*
+	 * pick up the chain we're going to add;
+	 * collect unused chains no free ones are left
+	 */
+	for(c = cs->free; ; c++){
+		if(c >= cs->echains){
+			cs->col++;
+			for(i = 0; i < cs->nlists; i++)
+				for(c = cs->lists[i]; c != nil; c = c->up)
+					c->col = cs->col;
+			c = cs->chains;
+		}
+		if(c->col != cs->col)
+			break;
+	}
+
+	/*
+	 * pick the cheapest of
+	 * 1) the next package from the previous list
+	 * 2) the next leaf
+	 */
+	nleaf = oc->leaf;
+	sumc = 0;
+	if(list > 0 && cs->lists[list-1] != nil)
+		sumc = cs->lists[list-2]->count + cs->lists[list-1]->count;
+	if(sumc != 0 && (nleaf >= cs->nleaf || cs->leafcount[nleaf] > sumc)){
+		c->count = sumc;
+		c->leaf = oc->leaf;
+		c->up = cs->lists[list-1];
+		c->gen = 1;
+	}else if(nleaf >= cs->nleaf){
+		cs->lists[list + 1] = nil;
+		return;
+	}else{
+		c->leaf = nleaf + 1;
+		c->count = cs->leafcount[nleaf];
+		c->up = oc->up;
+		c->gen = 0;
+	}
+	cs->free = c + 1;
+
+	cs->lists[list + 1] = c;
+	c->col = cs->col;
+}
+
+static int
+pivot(ulong *c, int a, int n)
+{
+	int j, pi, pj, pk;
+
+	j = n/6;
+	pi = a + j;	/* 1/6 */
+	j += j;
+	pj = pi + j;	/* 1/2 */
+	pk = pj + j;	/* 5/6 */
+	if(c[pi] < c[pj]){
+		if(c[pi] < c[pk]){
+			if(c[pj] < c[pk])
+				return pj;
+			return pk;
+		}
+		return pi;
+	}
+	if(c[pj] < c[pk]){
+		if(c[pi] < c[pk])
+			return pi;
+		return pk;
+	}
+	return pj;
+}
+
+static	void
+leafsort(ulong *leafcount, ushort *leafmap, int a, int n)
+{
+	ulong t;
+	int j, pi, pj, pn;
+
+	while(n > 1){
+		if(n > 10){
+			pi = pivot(leafcount, a, n);
+		}else
+			pi = a + (n>>1);
+
+		t = leafcount[pi];
+		leafcount[pi] = leafcount[a];
+		leafcount[a] = t;
+		t = leafmap[pi];
+		leafmap[pi] = leafmap[a];
+		leafmap[a] = t;
+		pi = a;
+		pn = a + n;
+		pj = pn;
+		for(;;){
+			do
+				pi++;
+			while(pi < pn && (leafcount[pi] < leafcount[a] || leafcount[pi] == leafcount[a] && leafmap[pi] > leafmap[a]));
+			do
+				pj--;
+			while(pj > a && (leafcount[pj] > leafcount[a] || leafcount[pj] == leafcount[a] && leafmap[pj] < leafmap[a]));
+			if(pj < pi)
+				break;
+			t = leafcount[pi];
+			leafcount[pi] = leafcount[pj];
+			leafcount[pj] = t;
+			t = leafmap[pi];
+			leafmap[pi] = leafmap[pj];
+			leafmap[pj] = t;
+		}
+		t = leafcount[a];
+		leafcount[a] = leafcount[pj];
+		leafcount[pj] = t;
+		t = leafmap[a];
+		leafmap[a] = leafmap[pj];
+		leafmap[pj] = t;
+		j = pj - a;
+
+		n = n-j-1;
+		if(j >= n){
+			leafsort(leafcount, leafmap, a, j);
+			a += j+1;
+		}else{
+			leafsort(leafcount, leafmap, a + (j+1), n);
+			n = j;
+		}
+	}
+}
--- /dev/null
+++ b/os/boot.original/libflate/deflateblock.c
@@ -1,0 +1,55 @@
+#include "lib9.h"
+#include <flate.h>
+
+typedef struct Block	Block;
+
+struct Block
+{
+	uchar	*pos;
+	uchar	*limit;
+};
+
+static int
+blread(void *vb, void *buf, int n)
+{
+	Block *b;
+
+	b = vb;
+	if(n > b->limit - b->pos)
+		n = b->limit - b->pos;
+	memmove(buf, b->pos, n);
+	b->pos += n;
+	return n;
+}
+
+static int
+blwrite(void *vb, void *buf, int n)
+{
+	Block *b;
+
+	b = vb;
+
+	if(n > b->limit - b->pos)
+		n = b->limit - b->pos;
+	memmove(b->pos, buf, n);
+	b->pos += n;
+	return n;
+}
+
+int
+deflateblock(uchar *dst, int dsize, uchar *src, int ssize, int level, int debug)
+{
+	Block bd, bs;
+	int ok;
+
+	bs.pos = src;
+	bs.limit = src + ssize;
+
+	bd.pos = dst;
+	bd.limit = dst + dsize;
+
+	ok = deflate(&bd, blwrite, &bs, blread, level, debug);
+	if(ok != FlateOk)
+		return ok;
+	return bd.pos - dst;
+}
--- /dev/null
+++ b/os/boot.original/libflate/deflatezlib.c
@@ -1,0 +1,59 @@
+#include "lib9.h"
+#include <flate.h>
+#include "zlib.h"
+
+typedef struct ZRead	ZRead;
+
+struct ZRead
+{
+	ulong	adler;
+	void	*rr;
+	int	(*r)(void*, void*, int);
+};
+
+static int
+zlread(void *vzr, void *buf, int n)
+{
+	ZRead *zr;
+
+	zr = vzr;
+	n = (*zr->r)(zr->rr, buf, n);
+	if(n <= 0)
+		return n;
+	zr->adler = adler32(zr->adler, buf, n);
+	return n;
+}
+
+int
+deflatezlib(void *wr, int (*w)(void*, void*, int), void *rr, int (*r)(void*, void*, int), int level, int debug)
+{
+	ZRead zr;
+	uchar buf[4];
+	int ok;
+
+	buf[0] = ZlibDeflate | ZlibWin32k;
+
+	/* bogus zlib encoding of compression level */
+	buf[1] = ((level > 2) + (level > 5) + (level > 8)) << 6;
+
+	/* header check field */
+	buf[1] |= 31 - ((buf[0] << 8) | buf[1]) % 31;
+	if((*w)(wr, buf, 2) != 2)
+		return FlateOutputFail;
+
+	zr.rr = rr;
+	zr.r = r;
+	zr.adler = 1;
+	ok = deflate(wr, w, &zr, zlread, level, debug);
+	if(ok != FlateOk)
+		return ok;
+
+	buf[0] = zr.adler >> 24;
+	buf[1] = zr.adler >> 16;
+	buf[2] = zr.adler >> 8;
+	buf[3] = zr.adler;
+	if((*w)(wr, buf, 4) != 4)
+		return FlateOutputFail;
+
+	return FlateOk;
+}
--- /dev/null
+++ b/os/boot.original/libflate/deflatezlibblock.c
@@ -1,0 +1,33 @@
+#include "lib9.h"
+#include <flate.h>
+#include "zlib.h"
+
+int
+deflatezlibblock(uchar *dst, int dsize, uchar *src, int ssize, int level, int debug)
+{
+	ulong adler;
+	int n;
+
+	if(dsize < 6)
+		return FlateOutputFail;
+
+	n = deflateblock(dst + 2, dsize - 6, src, ssize, level, debug);
+	if(n < 0)
+		return n;
+
+	dst[0] = ZlibDeflate | ZlibWin32k;
+
+	/* bogus zlib encoding of compression level */
+	dst[1] = ((level > 2) + (level > 5) + (level > 8)) << 6;
+
+	/* header check field */
+	dst[1] |= 31 - ((dst[0] << 8) | dst[1]) % 31;
+
+	adler = adler32(1, src, ssize);
+	dst[n + 2] = adler >> 24;
+	dst[n + 3] = adler >> 16;
+	dst[n + 4] = adler >> 8;
+	dst[n + 5] = adler;
+
+	return n + 6;
+}
--- /dev/null
+++ b/os/boot.original/libflate/flateerr.c
@@ -1,0 +1,22 @@
+#include "lib9.h"
+#include <flate.h>
+
+char *
+flateerr(int err)
+{
+	switch(err){
+	case FlateOk:
+		return "no error";
+	case FlateNoMem:
+		return "out of memory";
+	case FlateInputFail:
+		return "input error";
+	case FlateOutputFail:
+		return "output error";
+	case FlateCorrupted:
+		return "corrupted data";
+	case FlateInternal:
+		return "internal error";
+	}
+	return "unknown error";
+}
--- /dev/null
+++ b/os/boot.original/libflate/inflate.c
@@ -1,0 +1,692 @@
+#include "lib9.h"
+#include <flate.h>
+
+enum {
+	HistorySize=	32*1024,
+	BufSize=	4*1024,
+	MaxHuffBits=	17,	/* maximum bits in a encoded code */
+	Nlitlen=	288,	/* number of litlen codes */
+	Noff=		32,	/* number of offset codes */
+	Nclen=		19,	/* number of codelen codes */
+	LenShift=	10,	/* code = len<<LenShift|code */
+	LitlenBits=	7,	/* number of bits in litlen decode table */
+	OffBits=	6,	/* number of bits in offset decode table */
+	ClenBits=	6,	/* number of bits in code len decode table */
+	MaxFlatBits=	LitlenBits,
+	MaxLeaf=	Nlitlen
+};
+
+typedef struct Input	Input;
+typedef struct History	History;
+typedef struct Huff	Huff;
+
+struct Input
+{
+	int	error;		/* first error encountered, or FlateOk */
+	void	*wr;
+	int	(*w)(void*, void*, int);
+	void	*getr;
+	int	(*get)(void*);
+	ulong	sreg;
+	int	nbits;
+};
+
+struct History
+{
+	uchar	his[HistorySize];
+	uchar	*cp;		/* current pointer in history */
+	int	full;		/* his has been filled up at least once */
+};
+
+struct Huff
+{
+	int	maxbits;	/* max bits for any code */
+	int	minbits;	/* min bits to get before looking in flat */
+	int	flatmask;	/* bits used in "flat" fast decoding table */
+	ulong	flat[1<<MaxFlatBits];
+	ulong	maxcode[MaxHuffBits];
+	ulong	last[MaxHuffBits];
+	ulong	decode[MaxLeaf];
+};
+
+/* litlen code words 257-285 extra bits */
+static int litlenextra[Nlitlen-257] =
+{
+/* 257 */	0, 0, 0,
+/* 260 */	0, 0, 0, 0, 0, 1, 1, 1, 1, 2,
+/* 270 */	2, 2, 2, 3, 3, 3, 3, 4, 4, 4,
+/* 280 */	4, 5, 5, 5, 5, 0, 0, 0
+};
+
+static int litlenbase[Nlitlen-257];
+
+/* offset code word extra bits */
+static int offextra[Noff] =
+{
+	0,  0,  0,  0,  1,  1,  2,  2,  3,  3,
+	4,  4,  5,  5,  6,  6,  7,  7,  8,  8,
+	9,  9,  10, 10, 11, 11, 12, 12, 13, 13,
+	0,  0,
+};
+static int offbase[Noff];
+
+/* order code lengths */
+static int clenorder[Nclen] =
+{
+        16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
+};
+
+/* for static huffman tables */
+static	Huff	litlentab;
+static	Huff	offtab;
+static	uchar	revtab[256];
+
+static int	uncblock(Input *in, History*);
+static int	fixedblock(Input *in, History*);
+static int	dynamicblock(Input *in, History*);
+static int	sregfill(Input *in, int n);
+static int	sregunget(Input *in);
+static int	decode(Input*, History*, Huff*, Huff*);
+static int	hufftab(Huff*, char*, int, int);
+static int	hdecsym(Input *in, Huff *h, int b);
+
+int
+inflateinit(void)
+{
+	char *len;
+	int i, j, base;
+
+	/* byte reverse table */
+	for(i=0; i<256; i++)
+		for(j=0; j<8; j++)
+			if(i & (1<<j))
+				revtab[i] |= 0x80 >> j;
+
+	for(i=257,base=3; i<Nlitlen; i++) {
+		litlenbase[i-257] = base;
+		base += 1<<litlenextra[i-257];
+	}
+	/* strange table entry in spec... */
+	litlenbase[285-257]--;
+
+	for(i=0,base=1; i<Noff; i++) {
+		offbase[i] = base;
+		base += 1<<offextra[i];
+	}
+
+	len = malloc(MaxLeaf);
+	if(len == nil)
+		return FlateNoMem;
+
+	/* static Litlen bit lengths */
+	for(i=0; i<144; i++)
+		len[i] = 8;
+	for(i=144; i<256; i++)
+		len[i] = 9;
+	for(i=256; i<280; i++)
+		len[i] = 7;
+	for(i=280; i<Nlitlen; i++)
+		len[i] = 8;
+
+	if(!hufftab(&litlentab, len, Nlitlen, MaxFlatBits))
+		return FlateInternal;
+
+	/* static Offset bit lengths */
+	for(i=0; i<Noff; i++)
+		len[i] = 5;
+
+	if(!hufftab(&offtab, len, Noff, MaxFlatBits))
+		return FlateInternal;
+	free(len);
+
+	return FlateOk;
+}
+
+int
+inflate(void *wr, int (*w)(void*, void*, int), void *getr, int (*get)(void*))
+{
+	History *his;
+	Input in;
+	int final, type;
+
+	his = malloc(sizeof(History));
+	if(his == nil)
+		return FlateNoMem;
+	his->cp = his->his;
+	his->full = 0;
+	in.getr = getr;
+	in.get = get;
+	in.wr = wr;
+	in.w = w;
+	in.nbits = 0;
+	in.sreg = 0;
+	in.error = FlateOk;
+
+	do {
+		if(!sregfill(&in, 3))
+			goto bad;
+		final = in.sreg & 0x1;
+		type = (in.sreg>>1) & 0x3;
+		in.sreg >>= 3;
+		in.nbits -= 3;
+		switch(type) {
+		default:
+			in.error = FlateCorrupted;
+			goto bad;
+		case 0:
+			/* uncompressed */
+			if(!uncblock(&in, his))
+				goto bad;
+			break;
+		case 1:
+			/* fixed huffman */
+			if(!fixedblock(&in, his))
+				goto bad;
+			break;
+		case 2:
+			/* dynamic huffman */
+			if(!dynamicblock(&in, his))
+				goto bad;
+			break;
+		}
+	} while(!final);
+
+	if(his->cp != his->his && (*w)(wr, his->his, his->cp - his->his) != his->cp - his->his) {
+		in.error = FlateOutputFail;
+		goto bad;
+	}
+
+	if(!sregunget(&in))
+		goto bad;
+
+	free(his);
+	if(in.error != FlateOk)
+		return FlateInternal;
+	return FlateOk;
+
+bad:
+	free(his);
+	if(in.error == FlateOk)
+		return FlateInternal;
+	return in.error;
+}
+
+static int
+uncblock(Input *in, History *his)
+{
+	int len, nlen, c;
+	uchar *hs, *hp, *he;
+
+	if(!sregunget(in))
+		return 0;
+	len = (*in->get)(in->getr);
+	len |= (*in->get)(in->getr)<<8;
+	nlen = (*in->get)(in->getr);
+	nlen |= (*in->get)(in->getr)<<8;
+	if(len != (~nlen&0xffff)) {
+		in->error = FlateCorrupted;
+		return 0;
+	}
+
+	hp = his->cp;
+	hs = his->his;
+	he = hs + HistorySize;
+
+	while(len > 0) {
+		c = (*in->get)(in->getr);
+		if(c < 0)
+			return 0;
+		*hp++ = c;
+		if(hp == he) {
+			his->full = 1;
+			if((*in->w)(in->wr, hs, HistorySize) != HistorySize) {
+				in->error = FlateOutputFail;
+				return 0;
+			}
+			hp = hs;
+		}
+		len--;
+	}
+
+	his->cp = hp;
+
+	return 1;
+}
+
+static int
+fixedblock(Input *in, History *his)
+{
+	return decode(in, his, &litlentab, &offtab);
+}
+
+static int
+dynamicblock(Input *in, History *his)
+{
+	Huff *lentab, *offtab;
+	char *len;
+	int i, j, n, c, nlit, ndist, nclen, res, nb;
+
+	if(!sregfill(in, 14))
+		return 0;
+	nlit = (in->sreg&0x1f) + 257;
+	ndist = ((in->sreg>>5) & 0x1f) + 1;
+	nclen = ((in->sreg>>10) & 0xf) + 4;
+	in->sreg >>= 14;
+	in->nbits -= 14;
+
+	if(nlit > Nlitlen || ndist > Noff || nlit < 257) {
+		in->error = FlateCorrupted;
+		return 0;
+	}
+
+	/* huff table header */
+	len = malloc(Nlitlen+Noff);
+	lentab = malloc(sizeof(Huff));
+	offtab = malloc(sizeof(Huff));
+	if(len == nil || lentab == nil || offtab == nil){
+		in->error = FlateNoMem;
+		goto bad;
+	}
+	for(i=0; i < Nclen; i++)
+		len[i] = 0;
+	for(i=0; i<nclen; i++) {
+		if(!sregfill(in, 3))
+			goto bad;
+		len[clenorder[i]] = in->sreg & 0x7;
+		in->sreg >>= 3;
+		in->nbits -= 3;
+	}
+
+	if(!hufftab(lentab, len, Nclen, ClenBits)){
+		in->error = FlateCorrupted;
+		goto bad;
+	}
+
+	n = nlit+ndist;
+	for(i=0; i<n;) {
+		nb = lentab->minbits;
+		for(;;){
+			if(in->nbits<nb && !sregfill(in, nb))
+				goto bad;
+			c = lentab->flat[in->sreg & lentab->flatmask];
+			nb = c & 0xff;
+			if(nb > in->nbits){
+				if(nb != 0xff)
+					continue;
+				c = hdecsym(in, lentab, c);
+				if(c < 0)
+					goto bad;
+			}else{
+				c >>= 8;
+				in->sreg >>= nb;
+				in->nbits -= nb;
+			}
+			break;
+		}
+
+		if(c < 16) {
+			j = 1;
+		} else if(c == 16) {
+			if(in->nbits<2 && !sregfill(in, 2))
+				goto bad;
+			j = (in->sreg&0x3)+3;
+			in->sreg >>= 2;
+			in->nbits -= 2;
+			if(i == 0) {
+				in->error = FlateCorrupted;
+				goto bad;
+			}
+			c = len[i-1];
+		} else if(c == 17) {
+			if(in->nbits<3 && !sregfill(in, 3))
+				goto bad;
+			j = (in->sreg&0x7)+3;
+			in->sreg >>= 3;
+			in->nbits -= 3;
+			c = 0;
+		} else if(c == 18) {
+			if(in->nbits<7 && !sregfill(in, 7))
+				goto bad;
+			j = (in->sreg&0x7f)+11;
+			in->sreg >>= 7;
+			in->nbits -= 7;
+			c = 0;
+		} else {
+			in->error = FlateCorrupted;
+			goto bad;
+		}
+
+		if(i+j > n) {
+			in->error = FlateCorrupted;
+			goto bad;
+		}
+
+		while(j) {
+			len[i] = c;
+			i++;
+			j--;
+		}
+	}
+
+	if(!hufftab(lentab, len, nlit, LitlenBits)
+	|| !hufftab(offtab, &len[nlit], ndist, OffBits)){
+		in->error = FlateCorrupted;
+		goto bad;
+	}
+
+	res = decode(in, his, lentab, offtab);
+
+	free(len);
+	free(lentab);
+	free(offtab);
+
+	return res;
+
+bad:
+	free(len);
+	free(lentab);
+	free(offtab);
+	return 0;
+}
+
+static int
+decode(Input *in, History *his, Huff *litlentab, Huff *offtab)
+{
+	int len, off;
+	uchar *hs, *hp, *hq, *he;
+	int c;
+	int nb;
+
+	hs = his->his;
+	he = hs + HistorySize;
+	hp = his->cp;
+
+	for(;;) {
+		nb = litlentab->minbits;
+		for(;;){
+			if(in->nbits<nb && !sregfill(in, nb))
+				return 0;
+			c = litlentab->flat[in->sreg & litlentab->flatmask];
+			nb = c & 0xff;
+			if(nb > in->nbits){
+				if(nb != 0xff)
+					continue;
+				c = hdecsym(in, litlentab, c);
+				if(c < 0)
+					return 0;
+			}else{
+				c >>= 8;
+				in->sreg >>= nb;
+				in->nbits -= nb;
+			}
+			break;
+		}
+
+		if(c < 256) {
+			/* literal */
+			*hp++ = c;
+			if(hp == he) {
+				his->full = 1;
+				if((*in->w)(in->wr, hs, HistorySize) != HistorySize) {
+					in->error = FlateOutputFail;
+					return 0;
+				}
+				hp = hs;
+			}
+			continue;
+		}
+
+		if(c == 256)
+			break;
+
+		if(c > 285) {
+			in->error = FlateCorrupted;
+			return 0;
+		}
+
+		c -= 257;
+		nb = litlenextra[c];
+		if(in->nbits < nb && !sregfill(in, nb))
+			return 0;
+		len = litlenbase[c] + (in->sreg & ((1<<nb)-1));
+		in->sreg >>= nb;
+		in->nbits -= nb;
+
+		/* get offset */
+		nb = offtab->minbits;
+		for(;;){
+			if(in->nbits<nb && !sregfill(in, nb))
+				return 0;
+			c = offtab->flat[in->sreg & offtab->flatmask];
+			nb = c & 0xff;
+			if(nb > in->nbits){
+				if(nb != 0xff)
+					continue;
+				c = hdecsym(in, offtab, c);
+				if(c < 0)
+					return 0;
+			}else{
+				c >>= 8;
+				in->sreg >>= nb;
+				in->nbits -= nb;
+			}
+			break;
+		}
+
+		if(c > 29) {
+			in->error = FlateCorrupted;
+			return 0;
+		}
+
+		nb = offextra[c];
+		if(in->nbits < nb && !sregfill(in, nb))
+			return 0;
+
+		off = offbase[c] + (in->sreg & ((1<<nb)-1));
+		in->sreg >>= nb;
+		in->nbits -= nb;
+
+		hq = hp - off;
+		if(hq < hs) {
+			if(!his->full) {
+				in->error = FlateCorrupted;
+				return 0;
+			}
+			hq += HistorySize;
+		}
+
+		/* slow but correct */
+		while(len) {
+			*hp = *hq;
+			hq++;
+			hp++;
+			if(hq >= he)
+				hq = hs;
+			if(hp == he) {
+				his->full = 1;
+				if((*in->w)(in->wr, hs, HistorySize) != HistorySize) {
+					in->error = FlateOutputFail;
+					return 0;
+				}
+				hp = hs;
+			}
+			len--;
+		}
+
+	}
+
+	his->cp = hp;
+
+	return 1;
+}
+
+static int
+revcode(int c, int b)
+{
+	/* shift encode up so it starts on bit 15 then reverse */
+	c <<= (16-b);
+	c = revtab[c>>8] | (revtab[c&0xff]<<8);
+	return c;
+}
+
+/*
+ * construct the huffman decoding arrays and a fast lookup table.
+ * the fast lookup is a table indexed by the next flatbits bits,
+ * which returns the symbol matched and the number of bits consumed,
+ * or the minimum number of bits needed and 0xff if more than flatbits
+ * bits are needed.
+ *
+ * flatbits can be longer than the smallest huffman code,
+ * because shorter codes are assigned smaller lexical prefixes.
+ * this means assuming zeros for the next few bits will give a
+ * conservative answer, in the sense that it will either give the
+ * correct answer, or return the minimum number of bits which
+ * are needed for an answer.
+ */
+static int
+hufftab(Huff *h, char *hb, int maxleaf, int flatbits)
+{
+	ulong bitcount[MaxHuffBits];
+	ulong c, fc, ec, mincode, code, nc[MaxHuffBits];
+	int i, b, minbits, maxbits;
+
+	for(i = 0; i < MaxHuffBits; i++)
+		bitcount[i] = 0;
+	maxbits = -1;
+	minbits = MaxHuffBits + 1;
+	for(i=0; i < maxleaf; i++){
+		b = hb[i];
+		if(b){
+			bitcount[b]++;
+			if(b < minbits)
+				minbits = b;
+			if(b > maxbits)
+				maxbits = b;
+		}
+	}
+
+	h->maxbits = maxbits;
+	if(maxbits <= 0){
+		h->maxbits = 0;
+		h->minbits = 0;
+		h->flatmask = 0;
+		return 1;
+	}
+	code = 0;
+	c = 0;
+	for(b = 0; b <= maxbits; b++){
+		h->last[b] = c;
+		c += bitcount[b];
+		mincode = code << 1;
+		nc[b] = mincode;
+		code = mincode + bitcount[b];
+		if(code > (1 << b))
+			return 0;
+		h->maxcode[b] = code - 1;
+		h->last[b] += code - 1;
+	}
+
+	if(flatbits > maxbits)
+		flatbits = maxbits;
+	h->flatmask = (1 << flatbits) - 1;
+	if(minbits > flatbits)
+		minbits = flatbits;
+	h->minbits = minbits;
+
+	b = 1 << flatbits;
+	for(i = 0; i < b; i++)
+		h->flat[i] = ~0;
+
+	/*
+	 * initialize the flat table to include the minimum possible
+	 * bit length for each code prefix
+	 */
+	for(b = maxbits; b > flatbits; b--){
+		code = h->maxcode[b];
+		if(code == -1)
+			break;
+		mincode = code + 1 - bitcount[b];
+		mincode >>= b - flatbits;
+		code >>= b - flatbits;
+		for(; mincode <= code; mincode++)
+			h->flat[revcode(mincode, flatbits)] = (b << 8) | 0xff;
+	}
+
+	for(i = 0; i < maxleaf; i++){
+		b = hb[i];
+		if(b <= 0)
+			continue;
+		c = nc[b]++;
+		if(b <= flatbits){
+			code = (i << 8) | b;
+			ec = (c + 1) << (flatbits - b);
+			if(ec > (1<<flatbits))
+				return 0;	/* this is actually an internal error */
+			for(fc = c << (flatbits - b); fc < ec; fc++)
+				h->flat[revcode(fc, flatbits)] = code;
+		}
+		if(b > minbits){
+			c = h->last[b] - c;
+			if(c >= maxleaf)
+				return 0;
+			h->decode[c] = i;
+		}
+	}
+	return 1;
+}
+
+static int
+hdecsym(Input *in, Huff *h, int nb)
+{
+	long c;
+
+	if((nb & 0xff) == 0xff)
+		nb = nb >> 8;
+	else
+		nb = nb & 0xff;
+	for(; nb <= h->maxbits; nb++){
+		if(in->nbits<nb && !sregfill(in, nb))
+			return -1;
+		c = revtab[in->sreg&0xff]<<8;
+		c |= revtab[(in->sreg>>8)&0xff];
+		c >>= (16-nb);
+		if(c <= h->maxcode[nb]){
+			in->sreg >>= nb;
+			in->nbits -= nb;
+			return h->decode[h->last[nb] - c];
+		}
+	}
+	in->error = FlateCorrupted;
+	return -1;
+}
+
+static int
+sregfill(Input *in, int n)
+{
+	int c;
+
+	while(n > in->nbits) {
+		c = (*in->get)(in->getr);
+		if(c < 0){
+			in->error = FlateInputFail;
+			return 0;
+		}
+		in->sreg |= c<<in->nbits;
+		in->nbits += 8;
+	}
+	return 1;
+}
+
+static int
+sregunget(Input *in)
+{
+	if(in->nbits >= 8) {
+		in->error = FlateInternal;
+		return 0;
+	}
+
+	/* throw other bits on the floor */
+	in->nbits = 0;
+	in->sreg = 0;
+	return 1;
+}
--- /dev/null
+++ b/os/boot.original/libflate/inflateblock.c
@@ -1,0 +1,53 @@
+#include "lib9.h"
+#include <flate.h>
+
+typedef struct Block	Block;
+
+struct Block
+{
+	uchar	*pos;
+	uchar	*limit;
+};
+
+static int
+blgetc(void *vb)
+{
+	Block *b;
+
+	b = vb;
+	if(b->pos >= b->limit)
+		return -1;
+	return *b->pos++;
+}
+
+static int
+blwrite(void *vb, void *buf, int n)
+{
+	Block *b;
+
+	b = vb;
+
+	if(n > b->limit - b->pos)
+		n = b->limit - b->pos;
+	memmove(b->pos, buf, n);
+	b->pos += n;
+	return n;
+}
+
+int
+inflateblock(uchar *dst, int dsize, uchar *src, int ssize)
+{
+	Block bd, bs;
+	int ok;
+
+	bs.pos = src;
+	bs.limit = src + ssize;
+
+	bd.pos = dst;
+	bd.limit = dst + dsize;
+
+	ok = inflate(&bd, blwrite, &bs, blgetc);
+	if(ok != FlateOk)
+		return ok;
+	return bd.pos - dst;
+}
--- /dev/null
+++ b/os/boot.original/libflate/inflatezlib.c
@@ -1,0 +1,65 @@
+#include "lib9.h"
+#include <flate.h>
+#include "zlib.h"
+
+typedef struct ZWrite	ZWrite;
+
+struct ZWrite
+{
+	ulong	adler;
+	void	*wr;
+	int	(*w)(void*, void*, int);
+};
+
+static int
+zlwrite(void *vzw, void *buf, int n)
+{
+	ZWrite *zw;
+
+	zw = vzw;
+	zw->adler = adler32(zw->adler, buf, n);
+	n = (*zw->w)(zw->wr, buf, n);
+	if(n <= 0)
+		return n;
+	return n;
+}
+
+int
+inflatezlib(void *wr, int (*w)(void*, void*, int), void *getr, int (*get)(void*))
+{
+	ZWrite zw;
+	ulong v;
+	int c, i;
+
+	c = (*get)(getr);
+	if(c < 0)
+		return FlateInputFail;
+	i = (*get)(getr);
+	if(i < 0)
+		return FlateInputFail;
+
+	if(((c << 8) | i) % 31)
+		return FlateCorrupted;
+	if((c & ZlibMeth) != ZlibDeflate
+	|| (c & ZlibCInfo) > ZlibWin32k)
+		return FlateCorrupted;
+
+	zw.wr = wr;
+	zw.w = w;
+	zw.adler = 1;
+	i = inflate(&zw, zlwrite, getr, get);
+	if(i != FlateOk)
+		return i;
+
+	v = 0;
+	for(i = 0; i < 4; i++){
+		c = (*get)(getr);
+		if(c < 0)
+			return FlateInputFail;
+		v = (v << 8) | c;
+	}
+	if(zw.adler != v)
+		return FlateCorrupted;
+
+	return FlateOk;
+}
--- /dev/null
+++ b/os/boot.original/libflate/inflatezlibblock.c
@@ -1,0 +1,67 @@
+#include "lib9.h"
+#include <flate.h>
+#include "zlib.h"
+
+typedef struct Block	Block;
+
+struct Block
+{
+	uchar	*pos;
+	uchar	*limit;
+};
+
+static int
+blgetc(void *vb)
+{
+	Block *b;
+
+	b = vb;
+	if(b->pos >= b->limit)
+		return -1;
+	return *b->pos++;
+}
+
+static int
+blwrite(void *vb, void *buf, int n)
+{
+	Block *b;
+
+	b = vb;
+
+	if(n > b->limit - b->pos)
+		n = b->limit - b->pos;
+	memmove(b->pos, buf, n);
+	b->pos += n;
+	return n;
+}
+
+int
+inflatezlibblock(uchar *dst, int dsize, uchar *src, int ssize)
+{
+	Block bd, bs;
+	int ok;
+
+	if(ssize < 6)
+		return FlateInputFail;
+
+	if(((src[0] << 8) | src[1]) % 31)
+		return FlateCorrupted;
+	if((src[0] & ZlibMeth) != ZlibDeflate
+	|| (src[0] & ZlibCInfo) > ZlibWin32k)
+		return FlateCorrupted;
+
+	bs.pos = src + 2;
+	bs.limit = src + ssize - 6;
+
+	bd.pos = dst;
+	bd.limit = dst + dsize;
+
+	ok = inflate(&bd, blwrite, &bs, blgetc);
+	if(ok != FlateOk)
+		return ok;
+
+	if(adler32(1, dst, bs.pos - dst) != ((bs.pos[0] << 24) | (bs.pos[1] << 16) | (bs.pos[2] << 8) | bs.pos[3]))
+		return FlateCorrupted;
+
+	return bd.pos - dst;
+}
--- /dev/null
+++ b/os/boot.original/libflate/mkfile
@@ -1,0 +1,21 @@
+<../../../mkconfig
+
+LIB=libflate.a
+OFILES=\
+	deflate.$O\
+	deflatezlib.$O\
+	deflateblock.$O\
+	deflatezlibblock.$O\
+	inflate.$O\
+	inflatezlib.$O\
+	inflateblock.$O\
+	inflatezlibblock.$O\
+	flateerr.$O\
+	crc.$O\
+	adler.$O\
+
+HFILES=\
+	$ROOT/include/flate.h\
+	zlib.h\
+
+<$ROOT/mkfiles/mksyslib-$SHELLTYPE
--- /dev/null
+++ b/os/boot.original/libflate/zlib.h
@@ -1,0 +1,11 @@
+/*
+ * zlib header fields
+ */
+enum
+{
+	ZlibMeth	= 0x0f,			/* mask of compression methods */
+	ZlibDeflate	= 0x08,
+
+	ZlibCInfo	= 0xf0,			/* mask of compression aux. info */
+	ZlibWin32k	= 0x70,			/* 32k history window */
+};
--- /dev/null
+++ b/os/boot.original/mpc/NOTICE
@@ -1,0 +1,3 @@
+Inferno® Copyright © 1996-1999 Lucent Technologies Inc.  All rights reserved.
+PowerPC support Copyright © 1995-1997 C H Forsyth (forsyth@caldo.demon.co.uk).  All rights reserved.
+MPC8xx Inferno PowerPC port Copyright © 1998-2003 Vita Nuova Holdings Limited.  All rights reserved.
--- /dev/null
+++ b/os/boot.original/mpc/alarm.c
@@ -1,0 +1,123 @@
+#include	"u.h"
+#include	"lib.h"
+#include	"mem.h"
+#include	"dat.h"
+#include	"fns.h"
+#include	"io.h"
+#define	MAXALARM	10
+
+Alarm	alarmtab[MAXALARM];
+
+/*
+ * Insert new into list after where
+ */
+void
+insert(List **head, List *where, List *new)
+{
+	if(where == 0){
+		new->next = *head;
+		*head = new;
+	}else{
+		new->next = where->next;
+		where->next = new;
+	}
+		
+}
+
+/*
+ * Delete old from list.  where->next is known to be old.
+ */
+void
+delete(List **head, List *where, List *old)
+{
+	if(where == 0){
+		*head = old->next;
+		return;
+	}
+	where->next = old->next;
+}
+
+Alarm*
+newalarm(void)
+{
+	int i;
+	Alarm *a;
+
+	for(i=0,a=alarmtab; i < nelem(alarmtab); i++,a++)
+		if(a->busy==0 && a->f==0){
+			a->f = 0;
+			a->arg = 0;
+			a->busy = 1;
+			return a;
+		}
+	panic("newalarm");
+	return 0;	/* not reached */
+}
+
+Alarm*
+alarm(int ms, void (*f)(Alarm*), void *arg)
+{
+	Alarm *a, *w, *pw;
+	ulong s;
+
+	if(ms < 0)
+		ms = 0;
+	s = splhi();
+	a = newalarm();
+	a->dt = MS2TK(ms);
+	a->f = f;
+	a->arg = arg;
+	pw = 0;
+	for(w=m->alarm; w; pw=w, w=w->next){
+		if(w->dt <= a->dt){
+			a->dt -= w->dt;
+			continue;
+		}
+		w->dt -= a->dt;
+		break;
+	}
+	insert(&m->alarm, pw, a);
+	splx(s);
+	return a;
+}
+
+void
+cancel(Alarm *a)
+{
+	a->f = 0;
+}
+
+void
+alarminit(void)
+{
+}
+
+#define NA 10		/* alarms per clock tick */
+void
+checkalarms(void)
+{
+	int i, n, s;
+	Alarm *a;
+	void (*f)(Alarm*);
+	Alarm *alist[NA];
+
+	s = splhi();
+	a = m->alarm;
+	if(a){
+		for(n=0; a && a->dt<=0 && n<NA; n++){
+			alist[n] = a;
+			delete(&m->alarm, 0, a);
+			a = m->alarm;
+		}
+		if(a)
+			a->dt--;
+
+		for(i = 0; i < n; i++){
+			f = alist[i]->f;	/* avoid race with cancel */
+			if(f)
+				(*f)(alist[i]);
+			alist[i]->busy = 0;
+		}
+	}
+	splx(s);
+}
--- /dev/null
+++ b/os/boot.original/mpc/all.h
@@ -1,0 +1,6 @@
+#include	"u.h"
+#include	"lib.h"
+#include	"dat.h"
+#include	"fns.h"
+#include	"mem.h"
+#include	"io.h"
--- /dev/null
+++ b/os/boot.original/mpc/archfads.c
@@ -1,0 +1,355 @@
+#include	"u.h"
+#include	"lib.h"
+#include	"mem.h"
+#include	"dat.h"
+#include	"fns.h"
+#include	"io.h"
+#include	"archfads.h"
+
+/*
+ * board-specific support for the 8xxFADS (including 860/21 development system)
+ */
+
+enum {
+	USESDRAM = 0,	/* set to 1 if kernel is to use SDRAM as well as DRAM */
+
+	/* sccr */
+	RTSEL = IBIT(8),	/* =0, select main oscillator (OSCM); =1, select external crystal (EXTCLK) */
+	RTDIV = IBIT(7),	/* =0, divide by 4; =1, divide by 512 */
+	CRQEN = IBIT(9),	/* =1, switch to high frequency when CPM active */
+	PRQEN = IBIT(10),	/* =1, switch to high frequency when interrupt pending */
+
+	/* plprcr */
+	CSRC = IBIT(21),	/* =0, clock is DFNH; =1, clock is DFNL */
+};
+
+/*
+ * called early in main.c, after machinit:
+ * using board and architecture specific registers, initialise
+ * 8xx registers that need it and complete initialisation of the Mach structure.
+ */
+void
+archinit(void)
+{
+	IMM *io;
+	int mf, isfads, sysmhz, t;
+	ulong v;
+
+	v = getimmr() & 0xFFFF;
+	isfads = 0;		/* assume it's the 860/821 board */
+	sysmhz = 40;
+	switch(v>>8){
+	case 0x00:	t = 0x86000; break;
+	case 0x20:	t = 0x82300; isfads = 1; break;
+	case 0x21:	t = 0x823a0; isfads = 1; break;
+	default:	t = 0; break;
+	}
+	m->cputype = t;
+	m->bcsr = KADDR(BCSRMEM);
+	m->bcsr[1] |= DisableRS232a | DisableIR | DisableEther | DisablePCMCIA | DisableRS232b;
+	m->bcsr[1] &= ~(DisableDRAM|DisableFlash);
+	if(isfads){
+		sysmhz = 50;
+		m->bcsr[1] &= ~EnableSDRAM;
+		m->bcsr[4] &= ~(EnableVideoClock|EnableVideoPort);
+		m->bcsr[4] |= DisableVideoLamp;
+	}
+	io = m->iomem;
+	if(1 || io->sccr & IBIT(7)){	/* RTDIV=1 */
+		/* oscillator frequency can't be determined independently: check a switch */
+		if((m->bcsr[2]>>19)&(1<<2))
+			m->clockgen = 5*MHz;
+		else
+			m->clockgen = 4*MHz;
+	} else
+		m->clockgen = 32768;
+	mf = (sysmhz*MHz)/m->clockgen;
+	m->cpuhz = m->clockgen*mf;
+	io->plprcrk = KEEP_ALIVE_KEY;
+	io->plprcr &= ~IBIT(21);	/* general system clock is DFNH */
+	io->plprcr = (io->plprcr & ((1<<20)-1)) | ((mf-1)<<20);
+	io->mptpr = 0x0400;	/* memory prescaler = 16 for refresh */
+	io->plprcrk = ~KEEP_ALIVE_KEY;
+	if(isfads){
+		m->bcsr[1] |= EnableSDRAM;
+		sdraminit(SDRAMMEM);
+		if(!USESDRAM)
+			m->bcsr[1] &= ~EnableSDRAM;	/* tells kernel not to map it */
+	}
+}
+
+static void
+archidprint(void)
+{
+	int f, i;
+	ulong v;
+
+	/* 8xx and FADS specific */
+	print("IMMR: ");
+	v = getimmr() & 0xFFFF;
+	switch(v>>8){
+	case 0x00:	print("MPC860/821"); break;
+	case 0x20:	print("MPC823"); break;
+	case 0x21:	print("MPC823A"); break;
+	default:	print("Type #%lux", v>>8); break;
+	}
+	print(", mask #%lux\n", v&0xFF);
+	v = m->bcsr[3]>>16;
+	print("MPC8xxFADS rev %lud, DB: ", ((v>>4)&8)|((v>>1)&4)|(v&3));
+	f = (v>>8)&0x3F;
+	switch(f){
+	default:	print("ID#%x", f); break;
+	case 0x00:	print("MPC860/821"); break;
+	case 0x01:	print("MPC813"); break;
+	case 0x02:	print("MPC821"); break;
+	case 0x03:	print("MPC823"); break;
+	case 0x20:	print("MPC801"); break;
+	case 0x21:	print("MPC850"); break;
+	case 0x22:	print("MPC860"); break;
+	case 0x23:	print("MPC860SAR"); break;
+	case 0x24:	print("MPC860T"); break;
+	}
+	print("ADS, rev #%lux\n", (m->bcsr[2]>>16)&7);
+	for(i=0; i<=4; i++)
+		print("BCSR%d: %8.8lux\n", i, m->bcsr[i]);
+	v = m->bcsr[2];
+	f = (v>>28)&0xF;
+	switch(f){
+	default:	print("Unknown"); break;
+	case 4:	print("SM732A2000/SM73228 - 8M SIMM"); break;
+	case 5:	print("SM732A1000A/SM73218 - 4M SIMM"); break;
+	case 6:	print("MCM29080 - 8M SIMM"); break;
+	case 7:	print("MCM29040 - 4M SIMM"); break;
+	case 8:	print("MCM29020 - 2M SIMM"); break;
+	}
+	switch((m->bcsr[3]>>20)&7){
+	default:	i = 0; break;
+	case 1:	i = 150; break;
+	case 2:	i = 120; break;
+	case 3:	i = 90; break;
+	}
+	print(" flash, %dns\n", i);
+	f = (v>>23)&0xF;
+	switch(f&3){
+	case 0:	i = 4; break;
+	case 1:	i = 32; break;
+	case 2:	i = 16; break;
+	case 3:	i = 8; break;
+	}
+	print("%dM SIMM, ", i);
+	switch(f>>2){
+	default: 	i = 0; break;
+	case 2:	i = 70; break;
+	case 3:	i = 60; break;
+	}
+	print("%dns\n", i);
+	print("options: #%lux\n", (m->bcsr[2]>>19)&0xF);
+	print("plprcr=%8.8lux sccr=%8.8lux\n", m->iomem->plprcr, m->iomem->sccr);
+}
+
+void
+cpuidprint(void)
+{
+	int t;
+
+	print("PVR: ");
+	t = getpvr()>>16;
+	switch(t){
+	case 0x01:	print("MPC601"); break;
+	case 0x03:	print("MPC603"); break;
+	case 0x04:	print("MPC604"); break;
+	case 0x06:	print("MPC603e"); break;
+	case 0x07:	print("MPC603e-v7"); break;
+	case 0x50:	print("MPC8xx"); break;
+	default:	print("PowerPC version #%x", t); break;
+	}
+	print(", revision #%lux\n", getpvr()&0xffff);
+	archidprint();
+	print("%lud MHz system\n", m->cpuhz/MHz);
+	print("\n");
+}
+
+static	char*	defplan9ini[2] = {
+	/* 860/821 */
+	"ether0=type=SCC port=1 ea=00108bf12900\r\n"
+	"vgasize=640x480x8\r\n"
+	"kernelpercent=40\r\n"
+	"console=0 lcd\r\nbaud=9600\r\n",
+
+	/* 823 */
+	"ether0=type=SCC port=2 ea=00108bf12900\r\n"
+	"vgasize=640x480x8\r\n"
+	"kernelpercent=40\r\n"
+	"console=0 lcd\r\nbaud=9600\r\n",
+};
+
+char *
+archconfig(void)
+{
+	print("Using default configuration\n");
+	return defplan9ini[MPCMODEL(m->cputype) == 0x823];
+}
+
+/*
+ * provide value for #r/switch (devrtc.c)
+ */
+int
+archoptionsw(void)
+{
+	return (m->bcsr[2]>>19)&0xF;	/* value of switch DS1 */
+}
+
+/*
+ * invoked by clock.c:/^clockintr
+ */
+static void
+twinkle(void)
+{
+	if(m->ticks%MS2TK(1000) == 0)
+		m->bcsr[4] ^= DisableLamp;
+}
+
+void	(*archclocktick)(void) = twinkle;
+
+/*
+ * for flash.c:/^flashreset
+ * retrieve flash type, virtual base and length and return 0;
+ * return -1 on error (no flash)
+ */
+int
+archflashreset(char *type, void **addr, long *length)
+{
+	char *t;
+	int mbyte;
+
+	if((m->iomem->memc[0].base & 1) == 0)
+		return -1;		/* shouldn't happen */
+	switch((m->bcsr[2]>>28)&0xF){
+	default:	return -1;	/* unknown or not there */
+	case 4:	mbyte=8; t = "SM732x8"; break;
+	case 5:	mbyte=4; t = "SM732x8"; break;
+	case 6:	mbyte=8; t = "AMD29F0x0"; break;
+	case 7:	mbyte=4; t = "AMD29F0x0"; break;
+	case 8:	mbyte=2; t = "AMD29F0x0"; break;
+	}
+	strcpy(type, t);
+	*addr = KADDR(FLASHMEM);
+	*length = mbyte*1024*1024;
+	return 0;
+}
+
+/*
+ * enable the clocks for the given SCC ether and reveal them to the caller.
+ * do anything else required to prepare the transceiver (eg, set full-duplex, reset loopback).
+ */
+int
+archetherenable(int cpmid, int *rcs, int *tcs)
+{
+	IMM *io;
+
+	switch(cpmid){
+	default:
+		/* no other SCCs are wired on the FADS board */
+		return -1;
+
+	case SCC2ID:	/* assume 8xxFADS board with 823DABS */
+		io = ioplock();
+		m->bcsr[1] |= DisableIR|DisableRS232b;
+		m->bcsr[1] &= ~DisableEther;
+		io->papar |= SIBIT(6)|SIBIT(5);	/* enable CLK2 and CLK3 */
+		io->padir &= ~(SIBIT(6)|SIBIT(5));
+
+		/* ETHLOOP etc set in BCSR elsewhere */
+		*rcs = CLK2;
+		*tcs = CLK3;
+		iopunlock();
+		break;
+
+	case SCC1ID:	/* assume 860/21 development board */
+		io = ioplock();
+		m->bcsr[1] |= DisableIR|DisableRS232b;	/* TO DO: might not be shared with RS232b */
+		m->bcsr[1] &= ~DisableEther;
+		io->papar |= SIBIT(6)|SIBIT(7);	/* enable CLK2 and CLK1 */
+		io->padir &= ~(SIBIT(6)|SIBIT(7));
+
+		/* settings peculiar to 860/821 development board */
+		io->pcpar &= ~(SIBIT(4)|SIBIT(5)|SIBIT(6));	/* ETHLOOP, TPFULDL~, TPSQEL~ */
+		io->pcdir |= SIBIT(4)|SIBIT(5)|SIBIT(6);
+		io->pcdat &= ~SIBIT(4);
+		io->pcdat |= SIBIT(5)|SIBIT(6);
+		*rcs = CLK2;
+		*tcs = CLK1;
+		iopunlock();
+		break;
+	}
+	return 0;
+}
+
+void
+archetherdisable(int id)
+{
+	USED(id);
+	m->bcsr[1] |= DisableEther|DisableIR|DisableRS232b;
+}
+
+/*
+ * do anything extra required to enable the UART on the given CPM port
+ */
+void
+archenableuart(int id, int irda)
+{
+	switch(id){
+	case SMC1ID:
+		m->bcsr[1] &= ~DisableRS232a;
+		break;
+	case SCC2ID:
+		m->bcsr[1] |= DisableEther|DisableIR|DisableRS232b;
+		if(irda)
+			m->bcsr[1] &= ~DisableIR;
+		else
+			m->bcsr[1] &= ~DisableRS232b;
+		break;
+	default:
+		/* nothing special */
+		break;
+	}
+}
+
+/*
+ * do anything extra required to disable the UART on the given CPM port
+ */
+void
+archdisableuart(int id)
+{
+	switch(id){
+	case SMC1ID:
+		m->bcsr[1] |= DisableRS232a;
+		break;
+	case SCC2ID:
+		m->bcsr[1] |= DisableIR|DisableRS232b;
+		break;
+	default:
+		/* nothing special */
+		break;
+	}
+}
+
+/*
+ * enable/disable the LCD panel's backlight via
+ * York touch panel interface (does no harm without it)
+ */
+void
+archbacklight(int on)
+{
+	IMM *io;
+
+	delay(2);
+	io = ioplock();
+	io->papar &= ~SIBIT(4);
+	io->padir |= SIBIT(4);
+	if(on)
+		io->padat |= SIBIT(4);
+	else
+		io->padat &= ~SIBIT(4);
+	iopunlock();
+}
--- /dev/null
+++ b/os/boot.original/mpc/archfads.h
@@ -1,0 +1,42 @@
+
+enum {
+	/* BCSR1 bits */
+	DisableFlash=	IBIT(0),
+	DisableDRAM=	IBIT(1),
+	DisableEther=	IBIT(2),
+	DisableIR=	IBIT(3),
+	DisableRS232a=	IBIT(7),
+	DisablePCMCIA=	IBIT(8),
+	PCCVCCMask=	IBIT(9)|IBIT(15),
+	PCCVPPMask=	IBIT(10)|IBIT(11),
+	DisableRS232b=	IBIT(13),
+	EnableSDRAM=	IBIT(14),
+
+	PCCVCC0V=	IBIT(15)|IBIT(9),
+	PCCVCC5V=	IBIT(9),	/* active low */
+	PCCVCC3V=	IBIT(15),	/* active low */
+	PCCVPP0V=	IBIT(10)|IBIT(11),	/* active low */
+	PCCVPP5V=	IBIT(10),	/* active low */
+	PCCVPP12V=	IBIT(11),	/* active low */
+	PCCVPPHiZ=	IBIT(10)|IBIT(11),
+
+	/* BCSR4 bits */
+	DisableTPDuplex=	IBIT(1),
+	DisableLamp=	IBIT(3),
+	DisableUSB=	IBIT(4),
+	USBFullSpeed=	IBIT(5),
+	DisableUSBVcc=	IBIT(6),
+	DisableVideoLamp=	IBIT(8),
+	EnableVideoClock=	IBIT(9),
+	EnableVideoPort=	IBIT(10),
+	DisableModem=	IBIT(11),
+};
+
+enum {
+	/* memory controller CS assignment on FADS boards */
+	BOOTCS = 0,
+	BCSRCS = 1,
+	DRAM1 = 2,
+	DRAM2 = 3,
+	SDRAM = 4,
+};
--- /dev/null
+++ b/os/boot.original/mpc/archpaq.c
@@ -1,0 +1,240 @@
+#include	"u.h"
+#include	"lib.h"
+#include	"mem.h"
+#include	"dat.h"
+#include	"fns.h"
+#include	"io.h"
+
+#include	"archpaq.h"
+
+/*
+ * board-specific support for the 82x PowerPAQ
+ */
+
+enum {
+	SYSMHZ = 50,	/* desired system clock in MHz */
+
+	/* sccr */
+	RTSEL = IBIT(8),	/* =0, select main oscillator (OSCM); =1, select external crystal (EXTCLK) */
+	RTDIV = IBIT(7),	/* =0, divide by 4; =1, divide by 512 */
+	CRQEN = IBIT(9),	/* =1, switch to high frequency when CPM active */
+	PRQEN = IBIT(10),	/* =1, switch to high frequency when interrupt pending */
+
+	/* plprcr */
+	CSRC = IBIT(21),	/* =0, clock is DFNH; =1, clock is DFNL */
+};
+
+/*
+ * called early in main.c, after machinit:
+ * using board and architecture specific registers, initialise
+ * 8xx registers that need it and complete initialisation of the Mach structure.
+ */
+void
+archinit(void)
+{
+	IMM *io;
+	int mf, t;
+
+	switch((getimmr()>>8)&0xFF){
+	case 0x00:	t = 0x86000; break;	/* also 821 */
+	case 0x20:	t = 0x82300; break;
+	case 0x21:	t = 0x823a0; break;
+	default:	t = 0; break;
+	}
+	m->cputype = t;
+	m->bcsr = nil;	/* there isn't one */
+	m->clockgen = 32*1024;	/* crystal frequency */
+	io = m->iomem;
+	io->sccrk = KEEP_ALIVE_KEY;
+	io->sccr &= ~RTDIV;	/* divide 32k by 4 */
+	io->sccr |= RTSEL;
+	io->sccrk = ~KEEP_ALIVE_KEY;
+	mf = (SYSMHZ*MHz)/m->clockgen;
+	m->cpuhz = m->clockgen*mf;
+	io->plprcrk = KEEP_ALIVE_KEY;
+	io->plprcr &= ~IBIT(21);	/* general system clock is DFNH */
+	io->plprcr = (io->plprcr & ((1<<20)-1)) | ((mf-1)<<20);
+	io->mptpr = 0x0400;	/* memory prescaler = 16 for refresh */
+	io->plprcrk = ~KEEP_ALIVE_KEY;
+}
+
+void
+cpuidprint(void)
+{
+	int t, v;
+
+	print("PVR: ");
+	t = getpvr()>>16;
+	switch(t){
+	case 0x01:	print("MPC601"); break;
+	case 0x03:	print("MPC603"); break;
+	case 0x04:	print("MPC604"); break;
+	case 0x06:	print("MPC603e"); break;
+	case 0x07:	print("MPC603e-v7"); break;
+	case 0x50:	print("MPC8xx"); break;
+	default:	print("PowerPC version #%x", t); break;
+	}
+	print(", revision #%lux\n", getpvr()&0xffff);
+	print("IMMR: ");
+	v = getimmr() & 0xFFFF;
+	switch(v>>8){
+	case 0x00:	print("MPC860/821"); break;
+	case 0x20:	print("MPC823"); break;
+	case 0x21:	print("MPC823A"); break;
+	default:	print("Type #%lux", v>>8); break;
+	}
+	print(", mask #%lux\n", v&0xFF);
+	print("plprcr=%8.8lux sccr=%8.8lux\n", m->iomem->plprcr, m->iomem->sccr);
+	print("%lud MHz system\n", m->cpuhz/MHz);
+	print("\n");
+}
+
+static	char*	defplan9ini[2] = {
+	/* 860/821 */
+	"ether0=type=SCC port=1 ea=00108bf12900\r\n"
+	"vgasize=640x480x8\r\n"
+	"kernelpercent=40\r\n"
+	"console=0 lcd\r\nbaud=19200\r\n",
+
+	/* 823 */
+	"ether0=type=SCC port=2 ea=00108bf12900\r\n"
+	"vgasize=640x480x8\r\n"
+	"kernelpercent=40\r\n"
+	"console=0 lcd\r\nbaud=19200\r\n",
+};
+
+char *
+archconfig(void)
+{
+	print("Using default configuration\n");
+	return defplan9ini[MPCMODEL(m->cputype) == 0x823];
+}
+
+/*
+ * provide value for #r/switch (devrtc.c)
+ */
+int
+archoptionsw(void)
+{
+	return 0;
+}
+
+/*
+ * invoked by clock.c:/^clockintr
+ */
+static void
+twinkle(void)
+{
+	/* no easy-to-use LED on PAQ (they use i2c) */
+}
+
+void	(*archclocktick)(void) = twinkle;
+
+/*
+ * for flash.c:/^flashinit
+ * retrieve flash type, virtual base and length and return 0;
+ * return -1 on error (no flash)
+ */
+int
+archflashreset(char *type, void **addr, long *length)
+{
+	strcpy(type, "AMD29F0x0");
+	*addr = KADDR(FLASHMEM);
+	*length = 8*1024*1024;	/* 8mbytes on some models */
+	return 0;
+}
+
+/*
+ * enable the clocks for the given SCC ether and reveal them to the caller.
+ * do anything else required to prepare the transceiver (eg, set full-duplex, reset loopback).
+ */
+int
+archetherenable(int cpmid, int *rcs, int *tcs)
+{
+	USED(cpmid, rcs, tcs);
+	return -1;	/* there isn't an ether on the PAQs */
+}
+
+void
+archetherdisable(int id)
+{
+	USED(id);
+}
+
+/*
+ * do anything extra required to enable the UART on the given CPM port
+ */
+void
+archenableuart(int id, int irda)
+{
+	IMM *io;
+
+	USED(irda);
+	switch(id){
+	case SMC1ID:
+		io = ioplock();
+		io->pbodr &= ~0xc0;
+		io->pbdat |= 0xc0;
+		io->pcdat |= 0x400;
+		io->pcpar &= ~0x400;
+		io->pcdir |= 0x400;
+		io->pcdat &= ~0x400;	/* enable SMC RS232 buffer */
+		iopunlock();
+		break;
+	case SCC2ID:
+		/* TO DO */
+		break;
+	default:
+		/* nothing special */
+		break;
+	}
+}
+
+/*
+ * do anything extra required to disable the UART on the given CPM port
+ */
+void
+archdisableuart(int id)
+{
+	switch(id){
+	case SMC1ID:
+		/* TO DO */
+		break;
+	case SCC2ID:
+		/* TO DO */
+		break;
+	default:
+		/* nothing special */
+		break;
+	}
+}
+
+/*
+ * enable/disable the LCD panel's backlight via i2c
+ */
+void
+archbacklight(int on)
+{
+	uchar msg;
+	IMM *io;
+
+	i2csetup();
+	msg = ~7;
+	i2csend(LEDRegI2C, &msg, 1);
+	io = ioplock();
+	io->pbpar &= ~EnableLCD;
+	io->pbodr &= ~EnableLCD;
+	io->pbdir |= EnableLCD;
+	if(on)
+		io->pbdat |= EnableLCD;
+	else
+		io->pbdat &= ~EnableLCD;
+	iopunlock();
+	if(on){
+		msg = ~(DisablePanelVCC5|DisableTFT);
+		i2csend(PanelI2C, &msg, 1);
+	}else{
+		msg = ~0;
+		i2csend(PanelI2C, &msg, 1);
+	}
+}
--- /dev/null
+++ b/os/boot.original/mpc/archpaq.h
@@ -1,0 +1,29 @@
+enum {
+	/* memory controller CS assignment on PowerPAQ */
+	BOOTCS = 0,
+	DRAM1 = 1,	/* UPMB */
+	DRAM2 = 2,	/* UPMB */
+	/* CS3 also connected to DRAM */
+	/* CS4 128mbyte 8-bit gpcm, trlx, 15 wait; it's DAC */
+	/* CS5 is external*/
+};
+
+enum {
+	/* I2C addresses */
+	PanelI2C = 0x21<<1,
+	  /* the control bits are active low enables, or high disables */
+	  DisableVGA = ~0xFD,	/* disable VGA signals */
+	  DisableTFT = ~0xFB,	/* disable TFT panel signals */
+	  DisableSPIBus = ~0xF7,	/* disable SPI/I2C to panel */
+	  DisablePanelVCC5 = ~0xEF,	/* disable +5V to panel(s) */
+	  DisablePanelVCC3 = ~0xDF,	/* disable +3.3V to panel(s) */
+	  DisableMonoPanel = ~0xBF,	/* disable mono panel signals */
+	  DisableSPISelect = ~0x7F,	/* disable SPI chip select to LVDS panel */
+	ContrastI2C = 0x2E<<1,
+	LEDRegI2C = 0x20<<1,
+	  DisableGreenLED = ~0xFE,
+	  DisableYellowLED = ~0xFD,
+	  DisableRedLED = ~0xFB,
+
+	EnableLCD = IBIT(23),	/* LCD enable bit in i/o port B */
+};
--- /dev/null
+++ b/os/boot.original/mpc/boot.h
@@ -1,0 +1,8 @@
+#include <u.h>
+#include "lib.h"
+
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "ureg.h"
--- /dev/null
+++ b/os/boot.original/mpc/bootp.c
@@ -1,0 +1,507 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+#include "ip.h"
+
+enum {
+	CHECKSUM = 1,	/* set zero if trouble booting from Linux */
+};
+
+uchar broadcast[Eaddrlen] = {
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+};
+
+static ushort tftpport = 5000;
+static int Id = 1;
+static Netaddr myaddr;
+static Netaddr server;
+
+typedef struct {
+	uchar	header[4];
+	uchar	data[Segsize];
+} Tftp;
+static Tftp tftpb;
+
+static void
+hnputs(uchar *ptr, ushort val)
+{
+	ptr[0] = val>>8;
+	ptr[1] = val;
+}
+
+static void
+hnputl(uchar *ptr, ulong val)
+{
+	ptr[0] = val>>24;
+	ptr[1] = val>>16;
+	ptr[2] = val>>8;
+	ptr[3] = val;
+}
+
+static ulong
+nhgetl(uchar *ptr)
+{
+	return ((ptr[0]<<24) | (ptr[1]<<16) | (ptr[2]<<8) | ptr[3]);
+}
+
+static ushort
+nhgets(uchar *ptr)
+{
+	return ((ptr[0]<<8) | ptr[1]);
+}
+
+static	short	endian	= 1;
+static	char*	aendian	= (char*)&endian;
+#define	LITTLE	*aendian
+
+static ushort
+ptcl_csum(void *a, int len)
+{
+	uchar *addr;
+	ulong t1, t2;
+	ulong losum, hisum, mdsum, x;
+
+	addr = a;
+	losum = 0;
+	hisum = 0;
+	mdsum = 0;
+
+	x = 0;
+	if((ulong)addr & 1) {
+		if(len) {
+			hisum += addr[0];
+			len--;
+			addr++;
+		}
+		x = 1;
+	}
+	while(len >= 16) {
+		t1 = *(ushort*)(addr+0);
+		t2 = *(ushort*)(addr+2);	mdsum += t1;
+		t1 = *(ushort*)(addr+4);	mdsum += t2;
+		t2 = *(ushort*)(addr+6);	mdsum += t1;
+		t1 = *(ushort*)(addr+8);	mdsum += t2;
+		t2 = *(ushort*)(addr+10);	mdsum += t1;
+		t1 = *(ushort*)(addr+12);	mdsum += t2;
+		t2 = *(ushort*)(addr+14);	mdsum += t1;
+		mdsum += t2;
+		len -= 16;
+		addr += 16;
+	}
+	while(len >= 2) {
+		mdsum += *(ushort*)addr;
+		len -= 2;
+		addr += 2;
+	}
+	if(x) {
+		if(len)
+			losum += addr[0];
+		if(LITTLE)
+			losum += mdsum;
+		else
+			hisum += mdsum;
+	} else {
+		if(len)
+			hisum += addr[0];
+		if(LITTLE)
+			hisum += mdsum;
+		else
+			losum += mdsum;
+	}
+
+	losum += hisum >> 8;
+	losum += (hisum & 0xff) << 8;
+	while(hisum = losum>>16)
+		losum = hisum + (losum & 0xffff);
+
+	return ~losum;
+}
+
+static ushort
+ip_csum(uchar *addr)
+{
+	int len;
+	ulong sum = 0;
+
+	len = (addr[0]&0xf)<<2;
+
+	while(len > 0) {
+		sum += addr[0]<<8 | addr[1] ;
+		len -= 2;
+		addr += 2;
+	}
+
+	sum = (sum & 0xffff) + (sum >> 16);
+	sum = (sum & 0xffff) + (sum >> 16);
+	return (sum^0xffff);
+}
+
+static void
+udpsend(int ctlrno, Netaddr *a, void *data, int dlen)
+{
+	Udphdr *uh;
+	Etherhdr *ip;
+	static Etherpkt pkt;
+	int len, ptcllen;
+
+
+	uh = (Udphdr*)&pkt;
+
+	memset(uh, 0, sizeof(Etherpkt));
+	memmove(uh->udpcksum+sizeof(uh->udpcksum), data, dlen);
+
+	/*
+	 * UDP portion
+	 */
+	ptcllen = dlen + (UDP_HDRSIZE-UDP_PHDRSIZE);
+	uh->ttl = 0;
+	uh->udpproto = IP_UDPPROTO;
+	uh->frag[0] = 0;
+	uh->frag[1] = 0;
+	hnputs(uh->udpplen, ptcllen);
+	hnputl(uh->udpsrc, myaddr.ip);
+	hnputs(uh->udpsport, myaddr.port);
+	hnputl(uh->udpdst, a->ip);
+	hnputs(uh->udpdport, a->port);
+	hnputs(uh->udplen, ptcllen);
+	uh->udpcksum[0] = 0;
+	uh->udpcksum[1] = 0;
+	/*dlen = (dlen+1)&~1; */
+	hnputs(uh->udpcksum, ptcl_csum(&uh->ttl, dlen+UDP_HDRSIZE));
+
+	/*
+	 * IP portion
+	 */
+	ip = (Etherhdr*)&pkt;
+	len = sizeof(Udphdr)+dlen;
+	ip->vihl = IP_VER|IP_HLEN;
+	ip->tos = 0;
+	ip->ttl = 255;
+	hnputs(ip->length, len-ETHER_HDR);
+	hnputs(ip->id, Id++);
+	ip->frag[0] = 0;
+	ip->frag[1] = 0;
+	ip->cksum[0] = 0;
+	ip->cksum[1] = 0;
+	hnputs(ip->cksum, ip_csum(&ip->vihl));
+
+	/*
+	 * Ethernet MAC portion
+	 */
+	hnputs(ip->type, ET_IP);
+	memmove(ip->d, a->ea, sizeof(ip->d));
+
+	ethertxpkt(ctlrno, &pkt, len, Timeout);
+}
+
+static void
+nak(int ctlrno, Netaddr *a, int code, char *msg, int report)
+{
+	int n;
+	char buf[128];
+
+	buf[0] = 0;
+	buf[1] = Tftp_ERROR;
+	buf[2] = 0;
+	buf[3] = code;
+	strcpy(buf+4, msg);
+	n = strlen(msg) + 4 + 1;
+	udpsend(ctlrno, a, buf, n);
+	if(report)
+		print("\ntftp: error(%d): %s\n", code, msg);
+}
+
+static int
+udprecv(int ctlrno, Netaddr *a, void *data, int dlen)
+{
+	int n, len;
+	ushort csm;
+	Udphdr *h;
+	ulong addr, timo;
+	static Etherpkt pkt;
+	static int rxactive;
+
+	if(rxactive == 0)
+		timo = 1000;
+	else
+		timo = Timeout;
+	timo += TK2MS(m->ticks);
+	while(timo > TK2MS(m->ticks)){
+		n = etherrxpkt(ctlrno, &pkt, timo-TK2MS(m->ticks));
+		if(n <= 0)
+			continue;
+
+		h = (Udphdr*)&pkt;
+		if(nhgets(h->type) != ET_IP)
+			continue;
+
+		if(ip_csum(&h->vihl)) {
+			print("ip chksum error\n");
+			continue;
+		}
+		if(h->vihl != (IP_VER|IP_HLEN)) {
+			print("ip bad vers/hlen\n");
+			continue;
+		}
+
+		if(h->udpproto != IP_UDPPROTO)
+			continue;
+
+		h->ttl = 0;
+		len = nhgets(h->udplen);
+		hnputs(h->udpplen, len);
+
+		if(CHECKSUM && nhgets(h->udpcksum)) {
+			csm = ptcl_csum(&h->ttl, len+UDP_PHDRSIZE);
+			if(csm != 0) {
+				print("udp chksum error csum #%4lux len %d\n", csm, n);
+				break;
+			}
+		}
+
+		if(a->port != 0 && nhgets(h->udpsport) != a->port)
+			continue;
+
+		addr = nhgetl(h->udpsrc);
+		if(a->ip != Bcastip && addr != a->ip)
+			continue;
+
+		len -= UDP_HDRSIZE-UDP_PHDRSIZE;
+		if(len > dlen) {
+			print("udp: packet too big\n");
+			continue;
+		}
+
+		memmove(data, h->udpcksum+sizeof(h->udpcksum), len);
+		a->ip = addr;
+		a->port = nhgets(h->udpsport);
+		memmove(a->ea, pkt.s, sizeof(a->ea));
+
+		rxactive = 1;
+		return len;
+	}
+
+	return 0;
+}
+
+static int tftpblockno;
+
+static int
+tftpopen(int ctlrno, Netaddr *a, char *name, Tftp *tftp)
+{
+	int i, len, rlen, oport;
+	char buf[Segsize+2];
+
+	buf[0] = 0;
+	buf[1] = Tftp_READ;
+	len = sprint(buf+2, "%s", name) + 2;
+	len += sprint(buf+len+1, "octet") + 2;
+
+	oport = a->port;
+	for(i = 0; i < 5; i++){
+		a->port = oport;
+		udpsend(ctlrno, a, buf, len);
+		a->port = 0;
+		if((rlen = udprecv(ctlrno, a, tftp, sizeof(Tftp))) < sizeof(tftp->header))
+			continue;
+
+		switch((tftp->header[0]<<8)|tftp->header[1]){
+
+		case Tftp_ERROR:
+			print("tftpopen: error (%d): %s\n",
+				(tftp->header[2]<<8)|tftp->header[3], tftp->data);
+			return -1;
+
+		case Tftp_DATA:
+			tftpblockno = 1;
+			len = (tftp->header[2]<<8)|tftp->header[3];
+			if(len != tftpblockno){
+				print("tftpopen: block error: %d\n", len);
+				nak(ctlrno, a, 1, "block error", 0);
+				return -1;
+			}
+			return rlen-sizeof(tftp->header);
+		}
+	}
+
+	print("tftpopen: failed to connect to server\n");
+	return -1;
+}
+
+static int
+tftpread(int ctlrno, Netaddr *a, Tftp *tftp, int dlen)
+{
+	int blockno, len, retry;
+	uchar buf[4];
+
+	buf[0] = 0;
+	buf[1] = Tftp_ACK;
+	buf[2] = tftpblockno>>8;
+	buf[3] = tftpblockno;
+	tftpblockno++;
+
+	dlen += sizeof(tftp->header);
+
+	retry = 0;
+buggery:
+	udpsend(ctlrno, a, buf, sizeof(buf));
+
+	if((len = udprecv(ctlrno, a, tftp, dlen)) < dlen){
+		print("tftpread: %d != %d\n", len, dlen);
+		nak(ctlrno, a, 2, "short read", 0);
+		if(retry++ < 5)
+			goto buggery;
+		return -1;
+	}
+
+	blockno = (tftp->header[2]<<8)|tftp->header[3];
+	if(blockno != tftpblockno){
+		print("?");
+
+		if(blockno == tftpblockno-1 && retry++ < 8)
+			goto buggery;
+		print("tftpread: block error: %d, expected %d\n", blockno, tftpblockno);
+		nak(ctlrno, a, 1, "block error", 0);
+
+		return -1;
+	}
+
+	return len-sizeof(tftp->header);
+}
+
+int
+bootp(int ctlrno, char *file)
+{
+	Bootp req, rep;
+	int i, dlen, segsize, text, data, bss, total;
+	uchar *ea, *addr, *p;
+	ulong entry;
+	Exec *exec;
+	char name[128], *filename, *sysname;
+
+	if((ea = etheraddr(ctlrno)) == 0){
+		print("invalid ctlrno %d\n", ctlrno);
+		return -1;
+	}
+
+	filename = 0;
+	sysname = 0;
+	if(file && *file){
+		strcpy(name, file);
+		if(filename = strchr(name, ':')){
+			if(filename != name && *(filename-1) != '\\'){
+				sysname = name;
+				*filename++ = 0;
+			}
+		}
+		else
+			filename = name;
+	}
+		
+
+	memset(&req, 0, sizeof(req));
+	req.op = Bootrequest;
+	req.htype = 1;			/* ethernet */
+	req.hlen = Eaddrlen;		/* ethernet */
+	memmove(req.chaddr, ea, Eaddrlen);
+
+	myaddr.ip = 0;
+	myaddr.port = BPportsrc;
+	memmove(myaddr.ea, ea, Eaddrlen);
+
+	for(i = 0; i < 10; i++) {
+		server.ip = Bcastip;
+		server.port = BPportdst;
+		memmove(server.ea, broadcast, sizeof(server.ea));
+		udpsend(ctlrno, &server, &req, sizeof(req));
+		if(udprecv(ctlrno, &server, &rep, sizeof(rep)) <= 0)
+			continue;
+		if(memcmp(req.chaddr, rep.chaddr, Eaddrlen))
+			continue;
+		if(rep.htype != 1 || rep.hlen != Eaddrlen)
+			continue;
+		if(sysname == 0 || strcmp(sysname, rep.sname) == 0)
+			break;
+	}
+	if(i >= 10) {
+		print("bootp timed out\n");
+		return -1;
+	}
+
+	if(filename == 0 || *filename == 0)
+		filename = rep.file;
+
+	if(rep.sname[0] != '\0')
+		 print("%s ", rep.sname);
+	print("(%d.%d.%d.%d!%d): %s\n",
+		rep.siaddr[0],
+		rep.siaddr[1],
+		rep.siaddr[2],
+		rep.siaddr[3],
+		server.port,
+		filename);uartwait();
+
+	myaddr.ip = nhgetl(rep.yiaddr);
+	myaddr.port = tftpport++;
+	server.ip = nhgetl(rep.siaddr);
+	server.port = TFTPport;
+
+	if((dlen = tftpopen(ctlrno, &server, filename, &tftpb)) < 0)
+		return -1;
+	exec = (Exec*)(tftpb.data);
+	if(dlen < sizeof(Exec) || GLLONG(exec->magic) != Q_MAGIC){
+		nak(ctlrno, &server, 0, "bad magic number", 1);
+		return -1;
+	}
+	text = GLLONG(exec->text);
+	data = GLLONG(exec->data);
+	bss = GLLONG(exec->bss);
+	total = text+data+bss;
+	entry = GLLONG(exec->entry);
+print("load@%8.8lux: ", PADDR(entry));uartwait();
+	print("%d", text);
+
+	addr = (uchar*)PADDR(entry);
+	p = tftpb.data+sizeof(Exec);
+	dlen -= sizeof(Exec);
+	segsize = text;
+	for(;;){
+		if(dlen == 0){
+			if((dlen = tftpread(ctlrno, &server, &tftpb, sizeof(tftpb.data))) < 0)
+				return -1;
+			p = tftpb.data;
+		}
+		if(segsize <= dlen)
+			i = segsize;
+		else
+			i = dlen;
+		memmove(addr, p, i);
+
+		addr += i;
+		p += i;
+		segsize -= i;
+		dlen -= i;
+
+		if(segsize <= 0){
+			if(data == 0)
+				break;
+			print("+%d", data);
+			segsize = data;
+			data = 0;
+			addr = (uchar*)PGROUND((ulong)addr);
+		}
+	}
+	nak(ctlrno, &server, 3, "ok", 0);		/* tftpclose */
+	print("+%d=%d\n", bss, total);
+	print("entry: 0x%lux\n", entry);
+	uartwait();
+	scc2stop();
+	splhi();
+	(*(void(*)(void))(PADDR(entry)))();
+	
+	return 0;
+}
--- /dev/null
+++ b/os/boot.original/mpc/clock.c
@@ -1,0 +1,71 @@
+#include	"u.h"
+#include	"lib.h"
+#include	"mem.h"
+#include	"dat.h"
+#include	"fns.h"
+#include	"io.h"
+#include	"ureg.h"
+
+enum {
+	Timebase = 4,	/* system clock cycles per time base cycle */
+};
+
+void	(*archclocktick)(void);	/* set by arch*.c when desired */
+
+static	ulong	clkreload;
+
+void
+delay(int l)
+{
+	ulong i, j;
+
+	j = m->delayloop;
+	while(l-- > 0)
+		for(i=0; i < j; i++)
+			;
+}
+
+void
+microdelay(int l)
+{
+	ulong i;
+
+	l *= m->delayloop;
+	l /= 1000;
+	if(l <= 0)
+		l = 1;
+	for(i = 0; i < l; i++)
+		;
+}
+
+void
+clockintr(Ureg*, void*)
+{
+	putdec(clkreload);
+	m->ticks++;
+	checkalarms();
+	if(archclocktick != nil)
+		archclocktick();
+}
+
+void
+clockinit(void)
+{
+	long x;
+
+	m->delayloop = m->cpuhz/1000;	/* initial estimate */
+	do {
+		x = gettbl();
+		delay(10);
+		x = gettbl() - x;
+	} while(x < 0);
+
+	/*
+	 *  fix count
+	 */
+	m->delayloop = ((vlong)m->delayloop*(10*m->clockgen/1000))/(x*Timebase);
+	if(m->delayloop == 0)
+		m->delayloop = 1;
+	clkreload = (m->clockgen/Timebase)/HZ-1;
+	putdec(clkreload);
+}
--- /dev/null
+++ b/os/boot.original/mpc/conf.c
@@ -1,0 +1,173 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+#include "dosfs.h"
+
+static char *confname[MAXCONF];
+static char *confval[MAXCONF];
+static int nconf;
+
+extern char **ini;
+
+char*
+getconf(char *name)
+{
+	int i;
+
+	for(i = 0; i < nconf; i++)
+		if(strcmp(confname[i], name) == 0)
+			return confval[i];
+	return 0;
+}
+
+/*
+ *  read configuration file
+ */
+int
+plan9ini(Dos *dos, char *val)
+{
+	Dosfile rc;
+	int i, n;
+	char *cp, *p, *q, *line[MAXCONF];
+
+	cp = BOOTARGS;
+	if(dos) {
+		if(dosstat(dos, *ini, &rc) <= 0)
+			return -1;
+
+		*cp = 0;
+		n = dosread(&rc, cp, BOOTARGSLEN-1);
+		if(n <= 0)
+			return -1;
+		cp[n] = 0;
+	} else if(val != nil){
+		if(memchr(val, 0, BOOTARGSLEN-1) == nil)
+			return -1;
+		print("Using flash configuration\n");
+		strcpy(cp, val);
+		n = strlen(cp);
+	}else{
+		strcpy(cp, archconfig());
+		n = strlen(cp);
+	}
+
+	/*
+	 * Make a working copy.
+	 * We could change this to pass the parsed strings
+	 * to the booted programme instead of the raw
+	 * string, then it only gets done once.
+	 */
+	memmove(cp+BOOTARGSLEN, cp, n+1);
+	cp += BOOTARGSLEN;
+
+	/*
+	 * Strip out '\r', change '\t' -> ' '.
+	 */
+	p = cp;
+	for(q = cp; *q; q++){
+		if(*q == '\r')
+			continue;
+		if(*q == '\t')
+			*q = ' ';
+		*p++ = *q;
+	}
+	*p = 0;
+	n = getcfields(cp, line, MAXCONF, "\n");
+	for(i = 0; i < n; i++){
+		cp = strchr(line[i], '=');
+		if(cp == 0)
+			continue;
+		*cp++ = 0;
+		if(cp - line[i] >= NAMELEN+1)
+			*(line[i]+NAMELEN-1) = 0;
+		confname[nconf] = line[i];
+		confval[nconf] = cp;
+		nconf++;
+	}
+	return 0;
+}
+
+int
+parseether(uchar *to, char *from)
+{
+	char nip[4];
+	char *p;
+	int i;
+
+	p = from;
+	while(*p == ' ')
+		++p;
+	for(i = 0; i < 6; i++){
+		if(*p == 0)
+			return -1;
+		nip[0] = *p++;
+		if(*p == 0)
+			return -1;
+		nip[1] = *p++;
+		nip[2] = 0;
+		to[i] = strtoul(nip, 0, 16);
+		if(*p == ':')
+			p++;
+	}
+	return 0;
+}
+
+int
+isaconfig(char *class, int ctlrno, ISAConf *isa)
+{
+	char cc[NAMELEN], *p, *q, *r;
+	int n;
+
+	sprint(cc, "%s%d", class, ctlrno);
+	for(n = 0; n < nconf; n++){
+		if(strncmp(confname[n], cc, NAMELEN))
+			continue;
+		isa->nopt = 0;
+		p = confval[n];
+		while(*p){
+			while(*p == ' ' || *p == '\t')
+				p++;
+			if(*p == '\0')
+				break;
+			if(strncmp(p, "type=", 5) == 0){
+				p += 5;
+				for(q = isa->type; q < &isa->type[NAMELEN-1]; q++){
+					if(*p == '\0' || *p == ' ' || *p == '\t')
+						break;
+					*q = *p++;
+				}
+				*q = '\0';
+			}
+			else if(strncmp(p, "port=", 5) == 0)
+				isa->port = strtoul(p+5, &p, 0);
+			else if(strncmp(p, "irq=", 4) == 0)
+				isa->irq = strtoul(p+4, &p, 0);
+			else if(strncmp(p, "mem=", 4) == 0)
+				isa->mem = strtoul(p+4, &p, 0);
+			else if(strncmp(p, "size=", 5) == 0)
+				isa->size = strtoul(p+5, &p, 0);
+			else if(strncmp(p, "ea=", 3) == 0){
+				if(parseether(isa->ea, p+3) == -1)
+					memset(isa->ea, 0, 6);
+			}
+			else if(isa->nopt < NISAOPT){
+				r = isa->opt[isa->nopt];
+				while(*p && *p != ' ' && *p != '\t'){
+					*r++ = *p++;
+					if(r-isa->opt[isa->nopt] >= ISAOPTLEN-1)
+						break;
+				}
+				*r = '\0';
+				isa->nopt++;
+			}
+			while(*p && *p != ' ' && *p != '\t')
+				p++;
+		}
+		return 1;
+	}
+	return 0;
+}
--- /dev/null
+++ b/os/boot.original/mpc/console.c
@@ -1,0 +1,173 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+static Queue*	consiq;
+static Queue*	consoq;
+
+void
+bothputs(char *s, int n)
+{
+	uartputs(s, n);
+	screenputs(s, n);
+}
+
+static void (*consputs)(char*, int) = bothputs;	/* or screenputs */
+
+void
+consinit(void)
+{
+	char *p;
+	int baud, port;
+	static int cgadone;
+
+	p = getconf("console");
+	if(0)
+	if(p == 0 || strcmp(p, "lcd") == 0 || strcmp(p, "screen") == 0){
+		consiq = qopen(4*1024, 0, 0, 0);
+		consoq = qopen(8*1024, 0, 0, 0);
+		consputs = screenputs;
+		return;
+	}
+	if(p!=0 && strstr(p, "lcd") == 0)
+		consputs = bothputs;
+	else
+		consputs = uartputs;
+//consputs = screenputs;
+	port = 0;
+	if(p)
+		port = strtoul(p, 0, 0);
+	baud = 0;
+	if(p = getconf("baud"))
+		baud = strtoul(p, 0, 0);
+	if(baud == 0)
+		baud = 9600;
+	uartspecial(port, baud, &consiq, &consoq, kbdchar);
+}
+
+void
+kbdchar(Queue *q, int c)
+{
+	c &= 0x7F;
+	if(c == 0x10)
+		panic("^p");
+	qbputc(q, c);
+}
+
+static int
+getline(char *buf, int size, int dotimeout)
+{
+	int c, i=0;
+	ulong start;
+	char echo;
+
+	for (;;) {
+		start = m->ticks;
+		do{
+			if(dotimeout && ((m->ticks - start) > 5*HZ))
+				return -2;
+			c = qbgetc(consiq);
+		}while(c == -1);
+		if(c == '\r')
+			c = '\n'; 		/* turn carriage return into newline */
+		if(c == '\177')
+			c = '\010';		/* turn delete into backspace */
+		if(c == '\025')
+			echo = '\n';		/* echo ^U as a newline */
+		else
+			echo = c;
+		(*consputs)(&echo, 1);
+
+		if(c == '\010'){
+			if(i > 0)
+				i--; /* bs deletes last character */
+			continue;
+		}
+		/* a newline ends a line */
+		if (c == '\n')
+			break;
+		/* ^U wipes out the line */
+		if (c =='\025')
+			return -1;
+		if(i == size)
+			return size;
+		buf[i++] = c;
+	}
+	buf[i] = 0;
+	return i;
+}
+
+int
+getstr(char *prompt, char *buf, int size, char *def)
+{
+	int len, isdefault;
+
+	buf[0] = 0;
+	isdefault = (def && *def);
+	for (;;) {
+		if(isdefault)
+			print("%s[default==%s]: ", prompt, def);
+		else
+			print("%s: ", prompt);
+		len = getline(buf, size, isdefault);
+		switch(len){
+		case -1:
+			/* ^U typed */
+			continue;
+		case -2:
+			/* timeout, use default */
+			(*consputs)("\n", 1);
+			len = 0;
+			break;
+		default:
+			break;
+		}
+		if(len >= size){
+			print("line too long\n");
+			continue;
+		}
+		break;
+	}
+	if(len == 0 && isdefault)
+		strcpy(buf, def);
+	return 0;
+}
+
+int
+sprint(char *s, char *fmt, ...)
+{
+	return donprint(s, s+PRINTSIZE, fmt, (&fmt+1)) - s;
+}
+
+int
+print(char *fmt, ...)
+{
+	char buf[PRINTSIZE];
+	int n;
+
+	if(consputs == 0)
+		return 0;
+	n = donprint(buf, buf+sizeof(buf), fmt, (&fmt+1)) - buf;
+	(*consputs)(buf, n);
+	return n;
+}
+
+void
+panic(char *fmt, ...)
+{
+	char buf[PRINTSIZE];
+	int n;
+
+	if(consputs){
+		(*consputs)("panic: ", 7);
+		n = donprint(buf, buf+sizeof(buf), fmt, (&fmt+1)) - buf;
+		(*consputs)(buf, n);
+		(*consputs)("\n", 1);
+	}
+	spllo();
+	for(;;)
+		idle();
+}
--- /dev/null
+++ b/os/boot.original/mpc/cpm.c
@@ -1,0 +1,162 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+enum {
+	BDSIZE=	1024,	/* TO DO: check this */
+};
+
+static	Map	bdmapv[BDSIZE/sizeof(BD)];
+static	RMap	bdmap = {"buffer descriptors"};
+
+void
+cpminit(void)
+{
+	IMM *io;
+
+	io = m->iomem;
+	io->sdcr = 1;
+	io->lccr &= ~1;	/* disable LCD */
+	io->pcint = 0;	/* disable all port C interrupts */
+	io->pcso = 0;
+	io->pcdir =0;
+	io->pcpar = 0;
+	io->pcdat = 0;
+	io->papar = 0;
+	io->padir = 0;
+	io->paodr = 0;
+	io->padat = 0;
+	io->pbpar = 0;
+	io->pbdir = 0;
+	io->pbodr = 0;
+	io->pbdat = 0;
+	eieio();
+
+	for(io->cpcr = 0x8001; io->cpcr & 1;)	/* reset all CPM channels */
+		eieio();
+
+	mapinit(&bdmap, bdmapv, sizeof(bdmapv));
+	mapfree(&bdmap, DPBASE, BDSIZE);
+}
+
+void
+cpmop(int op, int cno, int param)
+{
+	IMM *io;
+	int s;
+
+	s = splhi();
+	io = m->iomem;
+	eieio();
+	while(io->cpcr & 1)
+		eieio();
+	io->cpcr = (op<<8)|(cno<<4)|(param<<1)|1;
+	eieio();
+	while(io->cpcr & 1)
+		eieio();
+	splx(s);
+}
+
+/*
+ * connect SCCx clocks in NSMI mode (x=1 for USB)
+ */
+void
+sccnmsi(int x, int rcs, int tcs)
+{
+	IMM *io;
+	ulong v;
+	int sh;
+
+	sh = (x-1)*8;	/* each SCCx field in sicr is 8 bits */
+	v = (((rcs&7)<<3) | (tcs&7)) << sh;
+	io = ioplock();
+	io->sicr = (io->sicr & ~(0xFF<<sh)) | v;
+	iopunlock();
+}
+
+void
+scc2stop(void)
+{
+	SCC *scc;
+
+	scc = IOREGS(0xA20, SCC);
+	if(scc->gsmrl & (3<<4)){
+		cpmop(GracefulStopTx, SCC2ID, 0);
+		cpmop(CloseRxBD, SCC2ID, 0);
+		delay(1);
+		scc->gsmrl &= ~(3<<4);	/* disable current use */
+		archetherdisable(SCC2ID);
+	}
+}
+
+BD *
+bdalloc(int n)
+{
+	ulong a;
+
+	a = mapalloc(&bdmap, 0, n*sizeof(BD), 0);
+	if(a == 0)
+		panic("bdalloc");
+	return KADDR(a);
+}
+
+void
+bdfree(BD *b, int n)
+{
+	if(b){
+		eieio();
+		mapfree(&bdmap, PADDR(b), n*sizeof(BD));
+	}
+}
+
+/*
+ * initialise receive and transmit buffer rings.
+ */
+int
+ioringinit(Ring* r, int nrdre, int ntdre, int bufsize)
+{
+	int i, x;
+
+	/* the ring entries must be aligned on sizeof(BD) boundaries */
+	r->nrdre = nrdre;
+	if(r->rdr == nil)
+		r->rdr = bdalloc(nrdre);
+	/* the buffer size must align with cache lines since the cache doesn't snoop */
+	bufsize = (bufsize+CACHELINESZ-1)&~(CACHELINESZ-1);
+	if(r->rrb == nil)
+		r->rrb = malloc(nrdre*bufsize);
+	if(r->rdr == nil || r->rrb == nil)
+		return -1;
+	dcflush(r->rrb, nrdre*bufsize);
+	x = PADDR(r->rrb);
+	for(i = 0; i < nrdre; i++){
+		r->rdr[i].length = 0;
+		r->rdr[i].addr = x;
+		r->rdr[i].status = BDEmpty|BDInt;
+		x += bufsize;
+	}
+	r->rdr[i-1].status |= BDWrap;
+	r->rdrx = 0;
+
+	r->ntdre = ntdre;
+	if(r->tdr == nil)
+		r->tdr = bdalloc(ntdre);
+	if(r->txb == nil)
+		r->txb = malloc(ntdre*sizeof(Block*));
+	if(r->tdr == nil || r->txb == nil)
+		return -1;
+	for(i = 0; i < ntdre; i++){
+		r->txb[i] = nil;
+		r->tdr[i].addr = 0;
+		r->tdr[i].length = 0;
+		r->tdr[i].status = 0;
+	}
+	r->tdr[i-1].status |= BDWrap;
+	r->tdrh = 0;
+	r->tdri = 0;
+	r->ntq = 0;
+	return 0;
+}
--- /dev/null
+++ b/os/boot.original/mpc/crc32.c
@@ -1,0 +1,42 @@
+#include "boot.h"
+
+/*
+ * from Rob Warnock
+ */
+static	ulong	crc32tab[256];	/* initialised on first call to crc32 */
+
+enum {
+	CRC32POLY = 0x04c11db7     /* AUTODIN II, Ethernet, & FDDI */
+};
+
+/*
+ * Build auxiliary table for parallel byte-at-a-time CRC-32.
+ */
+static void
+initcrc32(void)
+{
+	int i, j;
+	ulong c;
+
+	for(i = 0; i < 256; i++) {
+		for(c = i << 24, j = 8; j > 0; j--)
+			if(c & (1<<31))
+				c = (c<<1) ^ CRC32POLY;
+			else
+				c <<= 1;
+		crc32tab[i] = c;
+	}
+}
+
+ulong
+crc32(void *buf, int n, ulong crc)
+{
+	uchar *p;
+
+	if(crc32tab[1] == 0)
+		initcrc32();
+	crc = ~crc;
+	for(p = buf; --n >= 0;)
+		crc = (crc << 8) ^ crc32tab[(crc >> 24) ^ *p++];
+	return ~crc;
+}
--- /dev/null
+++ b/os/boot.original/mpc/dat.h
@@ -1,0 +1,217 @@
+typedef struct Alarm Alarm;
+typedef struct Block Block;
+typedef struct IMM IMM;
+typedef struct Queue Queue;
+
+typedef struct List {
+	void	*next;
+} List;
+
+typedef struct {
+	int	fake;
+	int	pri;
+} Lock;
+#define	lock(x)
+#define	unlock(x)
+
+struct Alarm {
+	List;
+	int	busy;
+	long	dt;
+	void	(*f)(Alarm*);
+	void	*arg;
+};
+
+enum {
+	Eaddrlen	= 6,
+	ETHERMINTU	= 60,		/* minimum transmit size */
+	ETHERMAXTU	= 1514,		/* maximum transmit size */
+	ETHERHDRSIZE	= 14,		/* size of an ethernet header */
+
+	MaxEther	= 4,
+};
+
+typedef struct {
+	uchar	d[Eaddrlen];
+	uchar	s[Eaddrlen];
+	uchar	type[2];
+	uchar	data[1500];
+	uchar	crc[4];
+} Etherpkt;
+
+extern uchar broadcast[Eaddrlen];
+
+enum {
+	Npart		= 20+2,		/* 8 sub partitions, disk, and partition */
+	Maxxfer		= 16*1024,	/* maximum transfer size/cmd */
+};
+
+typedef struct {
+	ulong	start;
+	ulong	end;
+	char	name[NAMELEN+1];
+} Partition;
+
+typedef struct {
+	int	online;
+	int	npart;		/* number of real partitions */
+	Partition p[Npart];
+	ulong	offset;
+	Partition *current;	/* current partition */
+
+	ulong	cap;		/* total bytes */
+	int	bytes;		/* bytes/sector */
+	int	sectors;	/* sectors/track */
+	int	heads;		/* heads/cyl */
+	long	cyl;		/* cylinders/drive */
+
+	char	lba;		/* true if drive has logical block addressing */
+	char	multi;		/* non-zero if drive does multiple block xfers */
+} Disc;
+
+enum {
+	ScsiTestunit	= 0x00,
+	ScsiExtsens	= 0x03,
+	ScsiInquiry	= 0x12,
+	ScsiModesense	= 0x1a,
+	ScsiStartunit	= 0x1B,
+	ScsiStopunit	= 0x1B,
+	ScsiGetcap	= 0x25,
+	ScsiRead	= 0x08,
+	ScsiWrite	= 0x0a,
+	ScsiExtread	= 0x28,
+	ScsiExtwrite	= 0x2a,
+
+	/* data direction */
+	ScsiIn		= 1,
+	ScsiOut		= 0,
+};
+
+typedef struct Scsibuf Scsibuf;
+typedef struct Scsibuf {
+	void*		virt;
+	void*		phys;
+	Scsibuf*	next;
+};
+
+typedef struct Scsidata {
+	uchar*		base;
+	uchar*		lim;
+	uchar*		ptr;
+} Scsidata;
+
+typedef struct Ureg Ureg;
+
+typedef struct Scsi {
+	ulong		pid;
+	ushort		target;
+	ushort		lun;
+	ushort		rflag;
+	ushort		status;
+	Scsidata 	cmd;
+	Scsidata 	data;
+	Scsibuf*	b;
+	uchar*		save;
+	uchar		cmdblk[16];
+} Scsi;
+
+typedef struct Segdesc {
+	ulong	d0;
+	ulong	d1;
+} Segdesc;
+
+typedef struct Mach {
+	ulong	ticks;			/* of the clock since boot time */
+	ulong	delayloop;
+	long	cpuhz;	/* general system clock (cycles) */
+	long	clockgen;	/* clock generator frequency (cycles) */
+	ulong	cpupvr;	/* cpu type in processor version register */
+	ulong	cputype;	/* cpu variant in BCD (eg, 0x823xx) */
+	void*	alarm;			/* alarms bound to this clock */
+	ulong*	bcsr;
+	IMM*	iomem;
+} Mach;
+
+/* Mach.cputype */
+#define MPCREV(x)	((x) & 0xFF)
+#define MPCMODEL(x)	(((x)>>8) & 0xFFF)
+#define MPCFAMILY(x)	(((x)>>24) & 0x0F)
+
+
+extern Mach *m;
+
+#define Q_MAGIC		((((4*21)+0)*21)+7)
+
+typedef struct Exec Exec;
+struct	Exec
+{
+	uchar	magic[4];		/* magic number */
+	uchar	text[4];	 	/* size of text segment */
+	uchar	data[4];	 	/* size of initialized data */
+	uchar	bss[4];	  		/* size of uninitialized data */
+	uchar	syms[4];	 	/* size of symbol table */
+	uchar	entry[4];	 	/* entry point */
+	uchar	spsz[4];		/* size of sp/pc offset table */
+	uchar	pcsz[4];		/* size of pc/line number table */
+};
+
+/*
+ *  bootline passed by boot program
+ */
+#define BOOTLINE ((char *)0x200000-150)
+
+/*
+ * Where we leave configuration info.
+ */
+#define BOOTARGS	((char*)(0x200000))
+#define	BOOTARGSLEN	1024
+#define	MAXCONF		32
+
+/*
+ *  a parsed plan9.ini line
+ */
+#define ISAOPTLEN	16
+#define NISAOPT		8
+
+typedef struct  ISAConf {
+	char	type[NAMELEN];
+	ulong	port;
+	ulong	irq;
+	ulong	mem;
+	ulong	size;
+	uchar	ea[6];
+
+	int	nopt;
+	char	opt[NISAOPT][ISAOPTLEN];
+} ISAConf;
+
+typedef struct {
+	int	size;
+	ulong	addr;
+} Map;
+
+typedef struct {
+	char*	name;
+	Map*	map;
+	Map*	mapend;
+
+	Lock;
+} RMap;
+
+typedef struct PCIcfg PCIcfg;
+
+extern	uchar*	vgamem;
+
+struct Block {
+	uchar	*rp;
+	uchar	*wp;
+	uchar	*lim;
+	uchar	*data;
+	Block*	next;
+	ulong	magic;
+};
+#define	BLEN(b)	((b)->wp-(b)->rp)
+
+typedef struct QLock {
+	int	dummy;
+} QLock;
--- /dev/null
+++ b/os/boot.original/mpc/defont0.c
@@ -1,0 +1,216 @@
+#include <u.h>
+#include <libc.h>
+#include <libg.h>
+#include <gnot.h>
+
+
+
+static ulong bits0[] = {
+ 0x907070f0,  0xf0f07000,  0xf0888888,  0xf8707070,  0xe0e0e0e0,  0xe09070f0,  0x70f870f0,  0xf870f088, 
+ 0x00000000,  0x00000000,  0x00000000,  0x00000000,  0x00000000,  0x00000000,  0x00000000,  0x00000000, 
+ 0x00000000,  0x00000000,  0x00000000,  0x00000000,  0x00000000,  0x00000000,  0x00000000,  0x00000000, 
+ 0x00000000,  0x00000000,  0x00000000,  0x00000000,  0x00000000,  0x00000000,  0x00000000,  0x000000e0, 
+ 0xd0808080,  0x80808800,  0x8888c888,  0x80888888,  0x90909090,  0x90d08080,  0x80808080,  0x80888888, 
+ 0x00000000,  0x08000000,  0x0c300000,  0x00000006,  0x00000000,  0x00000000,  0x00000000,  0x00000000, 
+ 0x00000000,  0x00000000,  0x00000000,  0x00000000,  0x00000000,  0x00000000,  0x0000003c,  0xc03c0000, 
+ 0x00006000,  0x06001e00,  0x60181860,  0x78000000,  0x00000000,  0x00000000,  0x0000001c,  0x18380090, 
+ 0xb06060e0,  0xe0e0f800,  0xf088a888,  0x80808080,  0x90909090,  0x90b060e0,  0x808060e0,  0x80808888, 
+ 0x00182428,  0x3e707018,  0x18180000,  0x00000006,  0x3c183c3c,  0x1c3e3c7e,  0x3c3c0000,  0x0200403c, 
+ 0x3c187c1e,  0x787e7e1e,  0x663c7c66,  0x6066623c,  0x7c3c7c3c,  0x7e6266c2,  0x66667e30,  0xc00c1000, 
+ 0x08006000,  0x06003000,  0x60181860,  0x18000000,  0x00000000,  0x10000000,  0x00000030,  0x180c0090, 
+ 0x90101080,  0x80808818,  0x88f8a888,  0xe0807070,  0xe0e0e0e0,  0xe0901080,  0x70e01080,  0xe098f088, 
+ 0x00182428,  0x6adad818,  0x18181000,  0x0000000c,  0x66386666,  0x2c3e667e,  0x66660000,  0x06006066, 
+ 0x42186632,  0x6c606032,  0x66181864,  0x60667224,  0x66246666,  0x186262da,  0x62620630,  0x600c3800, 
+ 0x10006000,  0x06003000,  0x60000060,  0x18000000,  0x00000000,  0x30000000,  0x00000030,  0x180c00e0, 
+ 0x00e0e0f0,  0xf0f00018,  0x88889850,  0x80880808,  0x201c1c1c,  0x1c00e0f0,  0x0080e0f0,  0x80888888, 
+ 0x00182428,  0x68dad808,  0x300c5418,  0x0000000c,  0x66580606,  0x2c206002,  0x66661818,  0x0cfe3006, 
+ 0x9e2c6660,  0x66606060,  0x6618186c,  0x60667266,  0x66666660,  0x186262da,  0x36660c30,  0x600c2800, 
+ 0x103c6c3c,  0x3e3c7e3e,  0x6c787866,  0x18d46c3c,  0x6c3e763c,  0x7e6666c2,  0x66667e18,  0x18180000, 
+ 0x44180000,  0x18241c24,  0xf0888820,  0x8070f0f0,  0x20202020,  0x201c243e,  0x1cf8241c,  0x80708870, 
+ 0x0018247c,  0x78745008,  0x300c3818,  0x00000018,  0x66180606,  0x4c206006,  0x76661818,  0x18fe180c, 
+ 0xb62c6660,  0x66606060,  0x66181868,  0x607e5a66,  0x66666470,  0x186266da,  0x34340c30,  0x300c6c00, 
+ 0x18667666,  0x66663066,  0x76181864,  0x18fe7666,  0x76663666,  0x306662da,  0x62620608,  0x1810323c, 
+ 0x44247c7c,  0x24342042,  0x00000000,  0x00000000,  0x20202020,  0x20222408,  0x22002420,  0x00000000, 
+ 0x00180028,  0x3c287610,  0x300cee7e,  0x00fe0018,  0x66180c18,  0x4c3c7c0c,  0x3c3e0000,  0x30000c18, 
+ 0xb62c7c60,  0x667c7c6e,  0x7e181878,  0x605a5a66,  0x6466783c,  0x186234da,  0x18341830,  0x300c4400, 
+ 0x18066660,  0x66663066,  0x66181868,  0x18d66666,  0x66663860,  0x306662da,  0x34620c30,  0x180c5a20, 
+ 0x44241010,  0x242c2042,  0x0e3e103e,  0x3e3c1c3e,  0x3c1c1c1c,  0x1c3e1c08,  0x3e222418,  0x0e0e0e0e, 
+ 0x0008007c,  0x1e5cdc00,  0x300c387e,  0x00fe0030,  0x66181806,  0x7e066618,  0x6e060000,  0x18001818, 
+ 0xb67e6660,  0x66606066,  0x6618186c,  0x605a4e66,  0x78666c0e,  0x1862346c,  0x2c183030,  0x180c4400, 
+ 0x003e6660,  0x667e3066,  0x66181878,  0x18d66666,  0x6666303c,  0x306634da,  0x18341808,  0x18104c38, 
+ 0x3c181010,  0x18241c42,  0x11081008,  0x20222208,  0x00000000,  0x00220408,  0x22361804,  0x11111111, 
+ 0x00000028,  0x16b6cc00,  0x300c5418,  0x00000030,  0x66183006,  0x7e066618,  0x66060000,  0x0cfe3000, 
+ 0x9a466660,  0x66606066,  0x6618186c,  0x605a4e66,  0x60666606,  0x1862346c,  0x6c183030,  0x180c0000, 
+ 0x00666660,  0x66603066,  0x6618186c,  0x18d66666,  0x66663006,  0x3066346c,  0x2c343018,  0x18180020, 
+ 0x00091010,  0x000e0942,  0x10081008,  0x20222208,  0x0f06060f,  0x0a09041e,  0x002a0e38,  0x10101010, 
+ 0x00180028,  0x56b6cc00,  0x300c1018,  0x18001860,  0x66187e66,  0x0c666630,  0x66661818,  0x06fe6018, 
+ 0x40466632,  0x6c606036,  0x66181866,  0x605a4624,  0x60246666,  0x1834186c,  0x46186030,  0x0c0c0000, 
+ 0x006e6666,  0x6e66306e,  0x66181866,  0x18d66666,  0x666e3066,  0x306e186c,  0x46186030,  0x180c003c, 
+ 0x08090909,  0x1f110aff,  0x0e081008,  0x382c2208,  0x08020901,  0x0a0a0911,  0x09220907,  0x0e0e0e0e, 
+ 0x00180028,  0x7c1c7600,  0x18180000,  0x18001860,  0x3c7e7e3c,  0x0c3c3c30,  0x3c3c1818,  0x02004018, 
+ 0x3e467c1e,  0x787e601e,  0x663c1866,  0x7e42463c,  0x603c663c,  0x1818186c,  0x66187e30,  0x0c0c0000, 
+ 0x00367c3c,  0x363c7c36,  0x667e1866,  0x7ed6663c,  0x7c367c3c,  0x1e36186c,  0x66187e30,  0x180c0008, 
+ 0x080f0606,  0x04110c18,  0x01081008,  0x20222208,  0x0e020203,  0x0a0c0d1e,  0x0d220e08,  0x01010101, 
+ 0x00000000,  0x10000000,  0x18180000,  0x080000c0,  0x00000000,  0x00000000,  0x00000008,  0x00000000, 
+ 0x00000000,  0x00000000,  0x00001800,  0x00000000,  0x000c0000,  0x00000000,  0x00000030,  0x060c00fe, 
+ 0x00000000,  0x00000006,  0x00001800,  0x00000000,  0x60060000,  0x00000000,  0x0010001c,  0x18380008, 
+ 0x08090606,  0x040e0a18,  0x11081f08,  0x20221c3e,  0x08020401,  0x0f0a0b11,  0x0b220908,  0x11111111, 
+ 0x00000000,  0x00000000,  0x0c300000,  0x080000c0,  0x00000000,  0x00000000,  0x00000008,  0x00000000, 
+ 0x00000000,  0x00000000,  0x00007000,  0x00000000,  0x00060000,  0x00000000,  0x0000003c,  0x063c0000, 
+ 0x00000000,  0x00000066,  0x00001800,  0x00000000,  0x60060000,  0x00000000,  0x00300000,  0x00000008, 
+ 0x0f090909,  0x04030900,  0x0e000000,  0x00000000,  0x0f0f0f0f,  0x0209091e,  0x09000f07,  0x0e0e0e0e, 
+ 0x00000000,  0x00000000,  0x00000000,  0x10000000,  0x00000000,  0x00000000,  0x00000010,  0x00000000, 
+ 0x00000000,  0x00000000,  0x00000000,  0x00000000,  0x00000000,  0x00000000,  0x00000000,  0x00000000, 
+ 0x00000000,  0x0000003c,  0x00007000,  0x00000000,  0x60060000,  0x00000000,  0x00600000,  0x0000000f, 
+
+};
+
+static GBitmap strike0 = {
+	bits0,
+	0,
+	32,
+	0,
+	{0, 0, 1024, 14},
+	{0, 0, 1024, 14},
+};
+
+static Fontchar info0[] = {
+	{ 0, 0, 14, 0, 8 },
+	{ 8, 0, 14, 0, 8 },
+	{ 16, 0, 14, 0, 8 },
+	{ 24, 0, 14, 0, 8 },
+	{ 32, 0, 14, 0, 8 },
+	{ 40, 0, 14, 0, 8 },
+	{ 48, 0, 14, 0, 8 },
+	{ 56, 0, 14, 0, 8 },
+	{ 64, 0, 14, 0, 8 },
+	{ 72, 0, 14, 0, 8 },
+	{ 80, 0, 14, 0, 8 },
+	{ 88, 0, 14, 0, 8 },
+	{ 96, 0, 14, 0, 8 },
+	{ 104, 0, 14, 0, 8 },
+	{ 112, 0, 14, 0, 8 },
+	{ 120, 0, 14, 0, 8 },
+	{ 128, 0, 14, 0, 8 },
+	{ 136, 0, 14, 0, 8 },
+	{ 144, 0, 14, 0, 8 },
+	{ 152, 0, 14, 0, 8 },
+	{ 160, 0, 14, 0, 8 },
+	{ 168, 0, 14, 0, 8 },
+	{ 176, 0, 14, 0, 8 },
+	{ 184, 0, 14, 0, 8 },
+	{ 192, 0, 14, 0, 8 },
+	{ 200, 0, 14, 0, 8 },
+	{ 208, 0, 14, 0, 8 },
+	{ 216, 0, 14, 0, 8 },
+	{ 224, 0, 14, 0, 8 },
+	{ 232, 0, 14, 0, 8 },
+	{ 240, 0, 14, 0, 8 },
+	{ 248, 0, 14, 0, 8 },
+	{ 256, 0, 0, 0, 8 },
+	{ 264, 2, 11, 0, 8 },
+	{ 272, 2, 6, 0, 8 },
+	{ 280, 2, 11, 0, 8 },
+	{ 288, 1, 12, 0, 8 },
+	{ 296, 2, 11, 0, 8 },
+	{ 304, 2, 11, 0, 8 },
+	{ 312, 2, 7, 0, 8 },
+	{ 320, 1, 13, 0, 8 },
+	{ 328, 1, 13, 0, 8 },
+	{ 336, 3, 10, 0, 8 },
+	{ 344, 4, 10, 0, 8 },
+	{ 352, 9, 14, 0, 8 },
+	{ 360, 6, 8, 0, 8 },
+	{ 368, 9, 11, 0, 8 },
+	{ 376, 1, 13, 0, 8 },
+	{ 384, 2, 11, 0, 8 },
+	{ 392, 2, 11, 0, 8 },
+	{ 400, 2, 11, 0, 8 },
+	{ 408, 2, 11, 0, 8 },
+	{ 416, 2, 11, 0, 8 },
+	{ 424, 2, 11, 0, 8 },
+	{ 432, 2, 11, 0, 8 },
+	{ 440, 2, 11, 0, 8 },
+	{ 448, 2, 11, 0, 8 },
+	{ 456, 2, 11, 0, 8 },
+	{ 464, 4, 11, 0, 8 },
+	{ 472, 4, 14, 0, 8 },
+	{ 480, 2, 11, 0, 8 },
+	{ 488, 4, 10, 0, 8 },
+	{ 496, 2, 11, 0, 8 },
+	{ 504, 2, 11, 0, 8 },
+	{ 512, 2, 11, 0, 8 },
+	{ 520, 2, 11, 0, 8 },
+	{ 528, 2, 11, 0, 8 },
+	{ 536, 2, 11, 0, 8 },
+	{ 544, 2, 11, 0, 8 },
+	{ 552, 2, 11, 0, 8 },
+	{ 560, 2, 11, 0, 8 },
+	{ 568, 2, 11, 0, 8 },
+	{ 576, 2, 11, 0, 8 },
+	{ 584, 2, 11, 0, 8 },
+	{ 592, 2, 13, 0, 8 },
+	{ 600, 2, 11, 0, 8 },
+	{ 608, 2, 11, 0, 8 },
+	{ 616, 2, 11, 0, 8 },
+	{ 624, 2, 11, 0, 8 },
+	{ 632, 2, 11, 0, 8 },
+	{ 640, 2, 11, 0, 8 },
+	{ 648, 2, 13, 0, 8 },
+	{ 656, 2, 11, 0, 8 },
+	{ 664, 2, 11, 0, 8 },
+	{ 672, 2, 11, 0, 8 },
+	{ 680, 2, 11, 0, 8 },
+	{ 688, 2, 11, 0, 8 },
+	{ 696, 2, 11, 0, 8 },
+	{ 704, 2, 11, 0, 8 },
+	{ 712, 2, 11, 0, 8 },
+	{ 720, 2, 11, 0, 8 },
+	{ 728, 1, 13, 0, 8 },
+	{ 736, 1, 13, 0, 8 },
+	{ 744, 1, 13, 0, 8 },
+	{ 752, 2, 8, 0, 8 },
+	{ 760, 11, 12, 0, 8 },
+	{ 768, 2, 7, 0, 8 },
+	{ 776, 4, 11, 0, 8 },
+	{ 784, 1, 11, 0, 8 },
+	{ 792, 4, 11, 0, 8 },
+	{ 800, 1, 11, 0, 8 },
+	{ 808, 4, 11, 0, 8 },
+	{ 816, 1, 11, 0, 8 },
+	{ 824, 4, 14, 0, 8 },
+	{ 832, 1, 11, 0, 8 },
+	{ 840, 1, 11, 0, 8 },
+	{ 848, 1, 14, 0, 8 },
+	{ 856, 1, 11, 0, 8 },
+	{ 864, 1, 11, 0, 8 },
+	{ 872, 4, 11, 0, 8 },
+	{ 880, 4, 11, 0, 8 },
+	{ 888, 4, 11, 0, 8 },
+	{ 896, 4, 14, 0, 8 },
+	{ 904, 4, 14, 0, 8 },
+	{ 912, 4, 11, 0, 8 },
+	{ 920, 4, 11, 0, 8 },
+	{ 928, 2, 11, 0, 8 },
+	{ 936, 4, 11, 0, 8 },
+	{ 944, 4, 11, 0, 8 },
+	{ 952, 4, 11, 0, 8 },
+	{ 960, 4, 11, 0, 8 },
+	{ 968, 4, 14, 0, 8 },
+	{ 976, 4, 11, 0, 8 },
+	{ 984, 1, 12, 0, 8 },
+	{ 992, 1, 12, 0, 8 },
+	{ 1000, 1, 12, 0, 8 },
+	{ 1008, 5, 8, 0, 8 },
+	{ 1016, 0, 14, 0, 8 },
+	{ 1024, 0, 14, 0, 8 },
+	{ 0, 0, 0, 0, 0 }
+};
+
+GSubfont defont0 = {
+	129,
+	14,
+	2,
+	info0,
+	&strike0,
+};
--- /dev/null
+++ b/os/boot.original/mpc/devether.c
@@ -1,0 +1,157 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+#include "etherif.h"
+
+static Ctlr ether[MaxEther];
+
+static struct {
+	char	*type;
+	int	(*reset)(Ctlr*);
+} cards[] = {
+	{ "SCC", sccethreset, },
+	{ "SCC2", sccethreset, },
+	{ 0, }
+};
+
+int
+etherinit(void)
+{
+	Ctlr *ctlr;
+	int ctlrno, i, mask, n;
+
+	mask = 0;
+	for(ctlrno = 0; ctlrno < MaxEther; ctlrno++){
+		ctlr = &ether[ctlrno];
+		memset(ctlr, 0, sizeof(Ctlr));
+		if(isaconfig("ether", ctlrno, &ctlr->card) == 0)
+			continue;
+		for(n = 0; cards[n].type; n++){
+			if(strcmp(cards[n].type, ctlr->card.type))
+				continue;
+			ctlr->ctlrno = ctlrno;
+			if((*cards[n].reset)(ctlr))
+				break;
+
+			ctlr->iq = qopen(16*1024, 1, 0, 0);
+			ctlr->oq = qopen(16*1024, 1, 0, 0);
+
+			ctlr->present = 1;
+			mask |= 1<<ctlrno;
+
+			print("ether%d: %s: port 0x%luX irq %d",
+				ctlr->ctlrno, ctlr->card.type, ctlr->card.port, ctlr->card.irq);
+			if(ctlr->card.mem)
+				print(" addr 0x%luX", PADDR(ctlr->card.mem));
+			if(ctlr->card.size)
+				print(" size 0x%luX", ctlr->card.size);
+			print(":");
+			for(i = 0; i < sizeof(ctlr->card.ea); i++)
+				print(" %2.2uX", ctlr->card.ea[i]);
+			print("\n"); uartwait();
+			setvec(VectorPIC + ctlr->card.irq, ctlr->card.intr, ctlr);
+			break;
+		}
+	}
+
+	return mask;
+}
+
+static Ctlr*
+attach(int ctlrno)
+{
+	Ctlr *ctlr;
+
+	if(ctlrno >= MaxEther || ether[ctlrno].present == 0)
+		return 0;
+
+	ctlr = &ether[ctlrno];
+	if(ctlr->present == 1){
+		ctlr->present = 2;
+		(*ctlr->card.attach)(ctlr);
+	}
+
+	return ctlr;
+}
+
+uchar*
+etheraddr(int ctlrno)
+{
+	Ctlr *ctlr;
+
+	if((ctlr = attach(ctlrno)) == 0)
+		return 0;
+
+	return ctlr->card.ea;
+}
+
+int
+etherrxpkt(int ctlrno, Etherpkt *pkt, int timo)
+{
+	int n;
+	Ctlr *ctlr;
+	Block *b;
+	ulong start;
+
+	if((ctlr = attach(ctlrno)) == 0)
+		return 0;
+
+	start = m->ticks;
+	while((b = qget(ctlr->iq)) == 0){
+		if(TK2MS(m->ticks - start) >= timo){
+			/*
+			print("ether%d: rx timeout\n", ctlrno);
+			 */
+			return 0;
+		}
+	}
+
+	n = BLEN(b);
+	memmove(pkt, b->rp, n);
+	freeb(b);
+
+	return n;
+}
+
+int
+etheriq(Ctlr *ctlr, Block *b, int freebp)
+{
+	if(memcmp(((Etherpkt*)b->rp)->d, ctlr->card.ea, Eaddrlen) != 0 &&
+	   memcmp(((Etherpkt*)b->rp)->d, broadcast, Eaddrlen) != 0){
+		if(freebp)
+			freeb(b);
+		return 0;
+	}
+	qbwrite(ctlr->iq, b);
+	return 1;
+}
+
+int
+ethertxpkt(int ctlrno, Etherpkt *pkt, int len, int)
+{
+	Ctlr *ctlr;
+	Block *b;
+	int s;
+
+	if((ctlr = attach(ctlrno)) == 0)
+		return 0;
+
+	if(qlen(ctlr->oq) > 16*1024){
+		print("ether%d: tx queue full\n", ctlrno);
+		return 0;
+	}
+	b = iallocb(sizeof(Etherpkt));
+	memmove(b->wp, pkt, len);
+	memmove(((Etherpkt*)b->wp)->s, ctlr->card.ea, Eaddrlen);
+	b->wp += len;
+	qbwrite(ctlr->oq, b);
+	s = splhi();
+	(*ctlr->card.transmit)(ctlr);
+	splx(s);
+
+	return 1;
+}
--- /dev/null
+++ b/os/boot.original/mpc/devuart.c
@@ -1,0 +1,230 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+/*
+ *  SMC1 in UART mode
+ */
+
+typedef struct Uartsmc Uartsmc;
+struct Uartsmc {
+	IOCparam;
+	ushort	maxidl;
+	ushort	idlc;
+	ushort	brkln;
+	ushort	brkec;
+	ushort	brkcr;
+	ushort	rmask;
+};
+
+typedef struct Uart	Uart;
+struct Uart
+{
+	int	port;
+	int	setup;
+	uchar	txbusy;
+
+	Queue*	iq;
+	Queue*	oq;
+	void	(*rx)(Queue*, int);
+	void	(*boot)(uchar*, int);
+
+	ulong	frame;
+	ulong	overrun;
+	uchar	rxbuf[128];
+	char	txbuf[16];
+	BD*	rxb;
+	BD*	txb;
+};
+
+Uart	uart[1];
+int	predawn = 1;
+
+static	void	uartintr(Ureg*, void*);
+static	void	uartkick(void*);
+
+static int
+baudgen(int baud)
+{
+	int d;
+
+	d = ((m->cpuhz/baud)+8)>>4;
+	if(d >= (1<<12))
+		return ((d+15)>>3)|1;
+	return d<<1;
+}
+
+static void
+smcsetup(Uart *up, int baud)
+{
+	IMM *io;
+	Uartsmc *p;
+	BD *bd;
+	SMC *smc;
+
+	archenableuart(SMC1ID, 0);
+	io = m->iomem;
+	io->pbpar |= IBIT(24)|IBIT(25);	/* enable SMC1 TX/RX */
+	io->pbdir &= ~(IBIT(24)|IBIT(25));
+	io->brgc1 = baudgen(baud) | BaudEnable;
+	io->simode &= ~0xF000;	/* SMC1 to NMSI mode, Tx/Rx clocks are BRG1 */
+
+	bd = bdalloc(1);
+	p = (Uartsmc*)KADDR(SMC1P);
+	p->rbase = (ushort)bd;
+	up->rxb = bd;
+	bd->status = BDEmpty|BDWrap|BDInt;
+	bd->length = 0;
+	bd->addr = PADDR(up->rxbuf);
+	bd = bdalloc(1);
+	p->tbase = (ushort)bd;
+	up->txb = bd;
+	bd->status = BDWrap|BDInt;
+	bd->length = 0;
+	bd->addr = PADDR(up->txbuf);
+
+	cpmop(InitRxTx, SMC1ID, 0);
+
+	/* protocol parameters */
+	p->rfcr = 0x18;
+	p->tfcr = 0x18;
+	p->mrblr = 1;
+	p->maxidl = 1;
+	p->brkln = 0;
+	p->brkec = 0;
+	p->brkcr = 1;
+	smc = IOREGS(0xA80, SMC);
+	smc->smce = 0xff;	/* clear events */
+	smc->smcm = 0x17;	/* enable all possible interrupts */
+	setvec(VectorCPIC+4, uartintr, up);
+	smc->smcmr = 0x4820;	/* 8-bit mode, no parity, 1 stop bit, UART mode, ... */
+	smc->smcmr |= 3;	/* enable rx/tx */
+}
+
+static void
+uartintr(Ureg*, void *arg)
+{
+	Uart *up;
+	int ch, i;
+	BD *bd;
+	SMC *smc;
+	Block *b;
+
+	up = arg;
+	smc = IOREGS(0xA80, SMC);
+	smc->smce = 0xff;	/* clear all events */
+	if((bd = up->rxb) != nil && (bd->status & BDEmpty) == 0){
+		if(up->iq != nil && bd->length > 0){
+			if(up->boot != nil){
+				up->boot(up->rxbuf, bd->length);
+			}else if(up->rx != nil){
+				for(i=0; i<bd->length; i++){
+					ch = up->rxbuf[i];
+					up->rx(up->iq, ch);
+				}
+			}else{
+				b = iallocb(bd->length);
+				memmove(b->wp, up->rxbuf, bd->length);
+				b->wp += bd->length;
+				qbwrite(up->iq, b);
+			}
+		}
+		bd->status |= BDEmpty|BDInt;
+	} else if((bd = up->txb) != nil && (bd->status & BDReady) == 0){
+		ch = -1;
+		if(up->oq)
+			ch = qbgetc(up->oq);
+		if(ch != -1){
+			up->txbuf[0] = ch;
+			bd->length = 1;
+			bd->status |= BDReady;
+		}else
+			up->txbusy = 0;
+	}
+	/* TO DO: modem status, errors, etc */
+}
+
+static void
+uartkick(void *arg)
+{
+	Uart *up = arg;
+	int s, c, i;
+
+	s = splhi();
+	while(up->txbusy == 0 && (c = qbgetc(up->oq)) != -1){
+		if(predawn){
+			while(up->txb->status & BDReady)
+				;
+		} else {
+			for(i = 0; i < 100; i++){
+				if((up->txb->status & BDReady) == 0)
+					break;
+				delay(1);
+			}
+		}
+		up->txbuf[0] = c;
+		up->txb->length = 1;
+		up->txb->status |= BDReady;
+		up->txbusy = !predawn;
+	}
+	splx(s);
+}
+
+void
+uartspecial(int port, int baud, Queue **iq, Queue **oq, void (*rx)(Queue*,int))
+{
+	Uart *up = &uart[0];
+
+	if(up->setup)
+		return;
+	up->setup = 1;
+
+	*iq = up->iq = qopen(4*1024, 0, 0, 0);
+	*oq = up->oq = qopen(16*1024, 0, uartkick, up);
+	up->rx = rx;
+	USED(port);
+	up->port = SMC1ID;
+	if(baud == 0)
+		baud = 9600;
+	smcsetup(up, baud);
+	/* if using SCCn's UART, would also set DTR and RTS, but SMC doesn't use them */
+}
+
+void
+uartsetboot(void (*f)(uchar*, int))
+{
+	uart[0].boot = f;
+}
+
+void
+uartputs(char *s, int n)
+{
+	Uart *up = &uart[0];
+	Block *b;
+	int nl;
+	char *p;
+
+	nl = 0;
+	for(p = s; p < s+n; p++)
+		if(*p == '\n')
+			nl++;
+	b = iallocb(n+nl);
+	while(n--){
+		if(*s == '\n')
+			*b->wp++ = '\r';
+		*b->wp++ = *s++;
+	}
+	qbwrite(up->oq, b);
+}
+
+void
+uartwait(void)
+{
+	Uart *up = &uart[0];
+
+	while(up->txbusy)
+		;
+}
--- /dev/null
+++ b/os/boot.original/mpc/dload.c
@@ -1,0 +1,103 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+#include <mach.h>
+
+static	char	*kernelfile = "/power/ipaq";
+ulong	crc32(void *buf, int n, ulong crc);
+
+void
+main(int argc, char **argv)
+{
+	int ifd, n;
+	char buf[64], reply[1];
+	int i, execsize;
+	Fhdr f;
+	ulong csum;
+
+	ARGBEGIN{
+	}ARGEND
+	ifd = open(kernelfile, OREAD);
+	if(ifd < 0){
+		fprint(2, "dload: can't open %s: %r\n", kernelfile);
+		exits("open");
+	}
+	i = 0;
+	if(crackhdr(ifd, &f) == 0){
+		fprint(2, "dload: not an executable file: %r\n");
+		exits("format");
+	}
+	if(f.magic != Q_MAGIC){
+		fprint(2, "dload: not a powerpc executable\n");
+		exits("format");
+	}
+	execsize = f.txtsz + f.datsz + f.txtoff;
+	seek(ifd, 0, 0);
+	csum = ~0;
+	while(execsize > 0 && (n = read(ifd, buf, sizeof(buf))) > 0){
+		if(n > execsize)
+			n = execsize;
+		for(;;){
+			if(write(1, buf, sizeof(buf)) != sizeof(buf)){	/* always writes full buffer */
+				fprint(2, "dload: write error: %r\n");
+				exits("write");
+			}
+			if(read(0, reply, 1) != 1){
+				fprint(2, "dload: bad reply\n");
+				exits("read");
+			}
+			if(reply[0] != 'n')
+				break;
+			fprint(2, "!");
+		}
+		if(reply[0] != 'y'){
+			fprint(2, "dload: bad ack: %c\n", reply[0]);
+			exits("reply");
+		}
+		if(++i%10 == 0)
+			fprint(2, ".");
+		execsize -= n;
+	}
+	exits(0);
+}
+
+/*
+ * from Rob Warnock
+ */
+static	ulong	crc32tab[256];	/* initialised on first call to crc32 */
+
+enum {
+	CRC32POLY = 0x04c11db7     /* AUTODIN II, Ethernet, & FDDI */
+};
+
+/*
+ * Build auxiliary table for parallel byte-at-a-time CRC-32.
+ */
+static void
+initcrc32(void)
+{
+	int i, j;
+	ulong c;
+
+	for(i = 0; i < 256; i++) {
+		for(c = i << 24, j = 8; j > 0; j--)
+			if(c & (1<<31))
+				c = (c<<1) ^ CRC32POLY;
+			else
+				c <<= 1;
+		crc32tab[i] = c;
+	}
+}
+
+ulong
+crc32(void *buf, int n, ulong crc)
+{
+	uchar *p;
+
+	if(crc32tab[1] == 0)
+		initcrc32();
+	crc = ~crc;
+	for(p = buf; --n >= 0;)
+		crc = (crc << 8) ^ crc32tab[(crc >> 24) ^ *p++];
+	return ~crc;
+}
--- /dev/null
+++ b/os/boot.original/mpc/donprint.c
@@ -1,0 +1,332 @@
+#include	"u.h"
+#include	"lib.h"
+
+#define	PTR	sizeof(char*)
+#define	SHORT	sizeof(int)
+#define	INT	sizeof(int)
+#define	LONG	sizeof(long)
+#define	IDIGIT	30
+#define	MAXCON	30
+
+#define	FLONG	(1<<0)
+#define	FSHORT	(1<<1)
+#define	FUNSIGN	(1<<2)
+
+typedef struct Op	Op;
+struct Op
+{
+	char	*p;
+	char	*ep;
+	void	*argp;
+	int	f1;
+	int	f2;
+	int	f3;
+};
+
+static	int	noconv(Op*);
+static	int	cconv(Op*);
+static	int	dconv(Op*);
+static	int	hconv(Op*);
+static	int	lconv(Op*);
+static	int	oconv(Op*);
+static	int	sconv(Op*);
+static	int	uconv(Op*);
+static	int	xconv(Op*);
+static	int	Xconv(Op*);
+static	int	percent(Op*);
+
+static
+int	(*fmtconv[MAXCON])(Op*) =
+{
+	noconv,
+	cconv, dconv, hconv, lconv,
+	oconv, sconv, uconv, xconv,
+	Xconv, percent,
+};
+static
+char	fmtindex[128] =
+{
+	['c'] 1,
+	['d'] 2,
+	['h'] 3,
+	['l'] 4,
+	['o'] 5,
+	['s'] 6,
+	['u'] 7,
+	['x'] 8,
+	['X'] 9,
+	['%'] 10,
+};
+
+static	int	convcount  = { 11 };
+static	int	ucase;
+
+static void
+PUT(Op *o, int c)
+{
+	static int pos;
+	int opos;
+
+	if(c == '\t'){
+		opos = pos;
+		pos = (opos+8) & ~7;
+		while(opos++ < pos && o->p < o->ep)
+			*o->p++ = ' ';
+		return;
+	}
+	if(o->p < o->ep){
+		*o->p++ = c;
+		pos++;
+	}
+	if(c == '\n')
+		pos = 0;
+}
+
+int
+fmtinstall(char c, int (*f)(Op*))
+{
+
+	c &= 0177;
+	if(fmtindex[c] == 0) {
+		if(convcount >= MAXCON)
+			return 1;
+		fmtindex[c] = convcount++;
+	}
+	fmtconv[fmtindex[c]] = f;
+	return 0;
+}
+
+char*
+donprint(char *p, char *ep, char *fmt, void *argp)
+{
+	int sf1, c;
+	Op o;
+
+	o.p = p;
+	o.ep = ep;
+	o.argp = argp;
+
+loop:
+	c = *fmt++;
+	if(c != '%') {
+		if(c == 0) {
+			if(o.p < o.ep)
+				*o.p = 0;
+			return o.p;
+		}
+		PUT(&o, c);
+		goto loop;
+	}
+	o.f1 = 0;
+	o.f2 = -1;
+	o.f3 = 0;
+	c = *fmt++;
+	sf1 = 0;
+	if(c == '-') {
+		sf1 = 1;
+		c = *fmt++;
+	}
+	while(c >= '0' && c <= '9') {
+		o.f1 = o.f1*10 + c-'0';
+		c = *fmt++;
+	}
+	if(sf1)
+		o.f1 = -o.f1;
+	if(c != '.')
+		goto l1;
+	c = *fmt++;
+	while(c >= '0' && c <= '9') {
+		if(o.f2 < 0)
+			o.f2 = 0;
+		o.f2 = o.f2*10 + c-'0';
+		c = *fmt++;
+	}
+l1:
+	if(c == 0)
+		fmt--;
+	c = (*fmtconv[fmtindex[c&0177]])(&o);
+	if(c < 0) {
+		o.f3 |= -c;
+		c = *fmt++;
+		goto l1;
+	}
+	o.argp = (char*)o.argp + c;
+	goto loop;
+}
+
+void
+strconv(char *o, Op *op, int f1, int f2)
+{
+	int n, c;
+	char *p;
+
+	n = strlen(o);
+	if(f1 >= 0)
+		while(n < f1) {
+			PUT(op, ' ');
+			n++;
+		}
+	for(p=o; c = *p++;)
+		if(f2 != 0) {
+			PUT(op, c);
+			f2--;
+		}
+	if(f1 < 0) {
+		f1 = -f1;
+		while(n < f1) {
+			PUT(op, ' ');
+			n++;
+		}
+	}
+}
+
+int
+numbconv(Op *op, int base)
+{
+	char b[IDIGIT];
+	int i, f, n, r;
+	long v;
+	short h;
+
+	f = 0;
+	switch(op->f3 & (FLONG|FSHORT|FUNSIGN)) {
+	case FLONG:
+		v = *(long*)op->argp;
+		r = LONG;
+		break;
+
+	case FUNSIGN|FLONG:
+		v = *(ulong*)op->argp;
+		r = LONG;
+		break;
+
+	case FSHORT:
+		h = *(int*)op->argp;
+		v = h;
+		r = SHORT;
+		break;
+
+	case FUNSIGN|FSHORT:
+		h = *(int*)op->argp;
+		v = (ushort)h;
+		r = SHORT;
+		break;
+
+	default:
+		v = *(int*)op->argp;
+		r = INT;
+		break;
+
+	case FUNSIGN:
+		v = *(unsigned*)op->argp;
+		r = INT;
+		break;
+	}
+	if(!(op->f3 & FUNSIGN) && v < 0) {
+		v = -v;
+		f = 1;
+	}
+	b[IDIGIT-1] = 0;
+	for(i = IDIGIT-2;; i--) {
+		n = (ulong)v % base;
+		n += '0';
+		if(n > '9'){
+			n += 'a' - ('9'+1);
+			if(ucase)
+				n += 'A'-'a';
+		}
+		b[i] = n;
+		if(i < 2)
+			break;
+		v = (ulong)v / base;
+		if(op->f2 >= 0 && i >= IDIGIT-op->f2)
+			continue;
+		if(v <= 0)
+			break;
+	}
+	if(f)
+		b[--i] = '-';
+	strconv(b+i, op, op->f1, -1);
+	return r;
+}
+
+static	int
+noconv(Op *op)
+{
+
+	strconv("***", op, 0, -1);
+	return 0;
+}
+
+static	int
+cconv(Op *op)
+{
+	char b[2];
+
+	b[0] = *(int*)op->argp;
+	b[1] = 0;
+	strconv(b, op, op->f1, -1);
+	return INT;
+}
+
+static	int
+dconv(Op *op)
+{
+	return numbconv(op, 10);
+}
+
+static	int
+hconv(Op*)
+{
+	return -FSHORT;
+}
+
+static	int
+lconv(Op*)
+{
+	return -FLONG;
+}
+
+static	int
+oconv(Op *op)
+{
+	return numbconv(op, 8);
+}
+
+static	int
+sconv(Op *op)
+{
+	strconv(*(char**)op->argp, op, op->f1, op->f2);
+	return PTR;
+}
+
+static	int
+uconv(Op*)
+{
+	return -FUNSIGN;
+}
+
+static	int
+xconv(Op *op)
+{
+	return numbconv(op, 16);
+}
+
+static	int
+Xconv(Op *op)
+{
+	int r;
+
+	ucase = 1;
+	r = numbconv(op, 16);
+	ucase = 0;
+	return r;
+}
+
+static	int
+percent(Op *op)
+{
+
+	PUT(op, '%');
+	return 0;
+}
--- /dev/null
+++ b/os/boot.original/mpc/dosboot.c
@@ -1,0 +1,614 @@
+#include	"u.h"
+#include	"lib.h"
+#include	"mem.h"
+#include	"dat.h"
+#include	"fns.h"
+#include	"dosfs.h"
+
+extern char *premature;
+
+/*
+ *  predeclared
+ */
+static void	bootdump(Dosboot*);
+static void	setname(Dosfile*, char*);
+long		dosreadseg(Dosfile*, long, long);
+
+/*
+ *  debugging
+ */
+#define chatty	1
+#define chat	if(chatty)print
+
+/*
+ *  block io buffers
+ */
+enum
+{
+	Nbio=	16,
+};
+typedef struct	Clustbuf	Clustbuf;
+struct Clustbuf
+{
+	int	age;
+	long	sector;
+	uchar	*iobuf;
+	Dos	*dos;
+	int	size;
+};
+Clustbuf	bio[Nbio];
+
+/*
+ *  get an io block from an io buffer
+ */
+Clustbuf*
+getclust(Dos *dos, long sector)
+{
+	Clustbuf *p, *oldest;
+	int size;
+
+	chat("getclust @ %d\n", sector);
+
+	/*
+	 *  if we have it, just return it
+	 */
+	for(p = bio; p < &bio[Nbio]; p++){
+		if(sector == p->sector && dos == p->dos){
+			p->age = m->ticks;
+			chat("getclust %d in cache\n", sector);
+			return p;
+		}
+	}
+
+	/*
+	 *  otherwise, reuse the oldest entry
+	 */
+	oldest = bio;
+	for(p = &bio[1]; p < &bio[Nbio]; p++){
+		if(p->age <= oldest->age)
+			oldest = p;
+	}
+	p = oldest;
+
+	/*
+	 *  make sure the buffer is big enough
+	 */
+	size = dos->clustsize*dos->sectsize;
+	if(p->iobuf==0 || p->size < size)
+		p->iobuf = ialloc(size, 0);
+	p->size = size;
+
+	/*
+	 *  read in the cluster
+	 */
+	chat("getclust addr %d\n", (sector+dos->start)*dos->sectsize);
+	if((*dos->seek)(dos->dev, (sector+dos->start)*dos->sectsize) < 0){
+		chat("can't seek block\n");
+		return 0;
+	}
+	if((*dos->read)(dos->dev, p->iobuf, size) != size){
+		chat("can't read block\n");
+		return 0;
+	}
+
+	p->age = m->ticks;
+	p->dos = dos;
+	p->sector = sector;
+	chat("getclust %d read\n", sector);
+	return p;
+}
+
+/*
+ *  walk the fat one level ( n is a current cluster number ).
+ *  return the new cluster number or -1 if no more.
+ */
+static long
+fatwalk(Dos *dos, int n)
+{
+	ulong k, sect;
+	Clustbuf *p;
+	int o;
+
+	chat("fatwalk %d\n", n);
+
+	if(n < 2 || n >= dos->fatclusters)
+		return -1;
+
+	switch(dos->fatbits){
+	case 12:
+		k = (3*n)/2; break;
+	case 16:
+		k = 2*n; break;
+	default:
+		return -1;
+	}
+	if(k >= dos->fatsize*dos->sectsize)
+		panic("getfat");
+
+	sect = (k/(dos->sectsize*dos->clustsize))*dos->clustsize + dos->fataddr;
+	o = k%(dos->sectsize*dos->clustsize);
+	p = getclust(dos, sect);
+	k = p->iobuf[o++];
+	if(o >= dos->sectsize*dos->clustsize){
+		p = getclust(dos, sect+dos->clustsize);
+		o = 0;
+	}
+	k |= p->iobuf[o]<<8;
+	if(dos->fatbits == 12){
+		if(n&1)
+			k >>= 4;
+		else
+			k &= 0xfff;
+		if(k >= 0xff8)
+			k |= 0xf000;
+	}
+	k = k < 0xfff8 ? k : -1;
+	chat("fatwalk %d -> %d\n", n, k);
+	return k;
+}
+
+/*
+ *  map a file's logical cluster address to a physical sector address
+ */
+static long
+fileaddr(Dosfile *fp, long ltarget)
+{
+	Dos *dos = fp->dos;
+	long l;
+	long p;
+
+	chat("fileaddr %8.8s %d\n", fp->name, ltarget);
+	/*
+	 *  root directory is contiguous and easy
+	 */
+	if(fp->pstart == 0){
+		if(ltarget*dos->sectsize*dos->clustsize >= dos->rootsize*sizeof(Dosdir))
+			return -1;
+		l = dos->rootaddr + ltarget*dos->clustsize;
+		chat("fileaddr %d -> %d\n", ltarget, l);
+		return l;
+	}
+
+	/*
+	 *  anything else requires a walk through the fat
+	 */
+	if(ltarget >= fp->lcurrent && fp->pcurrent){
+		/* start at the currrent point */
+		l = fp->lcurrent;
+		p = fp->pcurrent;
+	} else {
+		/* go back to the beginning */
+		l = 0;
+		p = fp->pstart;
+	}
+	while(l != ltarget){
+		/* walk the fat */
+		p = fatwalk(dos, p);
+		if(p < 0)
+			return -1;
+		l++;
+	}
+	fp->lcurrent = l;
+	fp->pcurrent = p;
+
+	/*
+	 *  clusters start at 2 instead of 0 (why? - presotto)
+	 */
+	l =  dos->dataaddr + (p-2)*dos->clustsize;
+	chat("fileaddr %d -> %d\n", ltarget, l);
+	return l;
+}
+
+/*
+ *  read from a dos file
+ */
+long
+dosread(Dosfile *fp, void *a, long n)
+{
+	long addr;
+	long rv;
+	int i;
+	int off;
+	Clustbuf *p;
+	uchar *from, *to;
+
+	if((fp->attr & DDIR) == 0){
+		if(fp->offset >= fp->length)
+			return 0;
+		if(fp->offset+n > fp->length)
+			n = fp->length - fp->offset;
+	}
+
+	to = a;
+	for(rv = 0; rv < n; rv+=i){
+		/*
+		 *  read the cluster
+		 */
+		addr = fileaddr(fp, fp->offset/fp->dos->clustbytes);
+		if(addr < 0)
+			return -1;
+		p = getclust(fp->dos, addr);
+		if(p == 0)
+			return -1;
+
+		/*
+		 *  copy the bytes we need
+		 */
+		off = fp->offset % fp->dos->clustbytes;
+		from = &p->iobuf[off];
+		i = n - rv;
+		if(i > fp->dos->clustbytes - off)
+			i = fp->dos->clustbytes - off;
+		memmove(to, from, i);
+		to += i;
+		fp->offset += i;
+	}
+
+	return rv;
+}
+
+/*
+ *  walk a directory returns
+ * 	-1 if something went wrong
+ *	 0 if not found
+ *	 1 if found
+ */
+int
+doswalk(Dosfile *file, char *name)
+{
+	Dosdir d;
+	long n;
+
+	if((file->attr & DDIR) == 0){
+		chat("walking non-directory!\n");
+		return -1;
+	}
+
+	setname(file, name);
+
+	file->offset = 0;	/* start at the beginning */
+	while((n = dosread(file, &d, sizeof(d))) == sizeof(d)){
+		chat("comparing to %8.8s.%3.3s\n", d.name, d.ext);
+		if(memcmp(file->name, d.name, sizeof(d.name)) != 0)
+			continue;
+		if(memcmp(file->ext, d.ext, sizeof(d.ext)) != 0)
+			continue;
+		if(d.attr & DVLABEL){
+			chat("%8.8s.%3.3s is a LABEL\n", d.name, d.ext);
+			continue;
+		}
+		file->attr = d.attr;
+		file->pstart = GSHORT(d.start);
+		file->length = GLONG(d.length);
+		file->pcurrent = 0;
+		file->lcurrent = 0;
+		file->offset = 0;
+		return 1;
+	}
+	return n >= 0 ? 0 : -1;
+}
+
+
+/*
+ *  instructions that boot blocks can start with
+ */
+#define	JMPSHORT	0xeb
+#define JMPNEAR		0xe9
+
+/*
+ *  read dos file system properties
+ */
+int
+dosinit(Dos *dos, int start, int ishard)
+{
+	Dosboot *b;
+	int i;
+	Clustbuf *p;
+	Dospart *dp;
+	ulong mbroffset, offset;
+
+	/* defaults till we know better */
+	dos->start = start;
+	dos->sectsize = 512;
+	dos->clustsize = 1;
+	mbroffset = 0;
+
+dmddo:
+	/* get first sector */
+	p = getclust(dos, mbroffset);
+	if(p == 0){
+		chat("can't read boot block\n");
+		return -1;
+	}
+
+	/*
+	 * If it's a hard disc then look for an MBR and pick either an
+	 * active partition or the FAT with the lowest starting LBA.
+	 * Things are tricky because we could be pointing to, amongst others:
+	 *	1) a floppy BPB;
+	 *	2) a hard disc MBR;
+	 *	3) a hard disc extended partition table;
+	 *	4) a logical drive on a hard disc;
+	 *	5) a disc-manager boot block.
+	 * They all have the same magic at the end of the block.
+	 */
+	if(p->iobuf[0x1FE] != 0x55 || p->iobuf[0x1FF] != 0xAA) {
+		chat("not DOS\n");
+		return -1;
+	}
+	p->dos = 0;
+	b = (Dosboot *)p->iobuf;
+	if(ishard && b->mediadesc != 0xF8){
+		dp = (Dospart*)&p->iobuf[0x1BE];
+		offset = 0xFFFFFFFF;
+		for(i = 0; i < 4; i++, dp++){
+			if(dp->type == DMDDO){
+				mbroffset = 63;
+				goto dmddo;
+			}
+			if(dp->type != FAT12 && dp->type != FAT16 && dp->type != FATHUGE)
+				continue;
+			if(dp->flag & 0x80){
+				offset = GLONG(dp->start);
+				break;
+			}
+			if(GLONG(dp->start) < offset)
+				offset = GLONG(dp->start);
+		}
+		if(i != 4 || offset != 0xFFFFFFFF){
+			dos->start = mbroffset+offset;
+			p = getclust(dos, 0);
+			if(p == 0 || p->iobuf[0x1FE] != 0x55 || p->iobuf[0x1FF] != 0xAA)
+				return -1;
+		}
+		p->dos = 0;
+	}
+
+	b = (Dosboot *)p->iobuf;
+	if(b->magic[0] != JMPNEAR && (b->magic[0] != JMPSHORT || b->magic[2] != 0x90)){
+		chat("no dos file system\n");
+		return -1;
+	}
+
+	if(chatty)
+		bootdump(b);
+
+	/*
+	 *  determine the systems' wondersous properties
+	 */
+	dos->sectsize = GSHORT(b->sectsize);
+	dos->clustsize = b->clustsize;
+	dos->clustbytes = dos->sectsize*dos->clustsize;
+	dos->nresrv = GSHORT(b->nresrv);
+	dos->nfats = b->nfats;
+	dos->rootsize = GSHORT(b->rootsize);
+	dos->volsize = GSHORT(b->volsize);
+	if(dos->volsize == 0)
+		dos->volsize = GLONG(b->bigvolsize);
+	dos->mediadesc = b->mediadesc;
+	dos->fatsize = GSHORT(b->fatsize);
+	dos->fataddr = dos->nresrv;
+	dos->rootaddr = dos->fataddr + dos->nfats*dos->fatsize;
+	i = dos->rootsize*sizeof(Dosdir) + dos->sectsize - 1;
+	i = i/dos->sectsize;
+	dos->dataaddr = dos->rootaddr + i;
+	dos->fatclusters = 2+(dos->volsize - dos->dataaddr)/dos->clustsize;
+	if(dos->fatclusters < 4087)
+		dos->fatbits = 12;
+	else
+		dos->fatbits = 16;
+	dos->freeptr = 2;
+
+	/*
+	 *  set up the root
+	 */
+	dos->root.dos = dos;
+	dos->root.pstart = 0;
+	dos->root.pcurrent = dos->root.lcurrent = 0;
+	dos->root.offset = 0;
+	dos->root.attr = DDIR;
+	dos->root.length = dos->rootsize*sizeof(Dosdir);
+
+	return 0;
+}
+
+static void
+bootdump(Dosboot *b)
+{
+	if(chatty == 0)
+		return;
+	print("magic: 0x%2.2x 0x%2.2x 0x%2.2x\n",
+		b->magic[0], b->magic[1], b->magic[2]);
+	print("version: \"%8.8s\"\n", b->version);
+	print("sectsize: %d\n", GSHORT(b->sectsize));
+	print("allocsize: %d\n", b->clustsize);
+	print("nresrv: %d\n", GSHORT(b->nresrv));
+	print("nfats: %d\n", b->nfats);
+	print("rootsize: %d\n", GSHORT(b->rootsize));
+	print("volsize: %d\n", GSHORT(b->volsize));
+	print("mediadesc: 0x%2.2x\n", b->mediadesc);
+	print("fatsize: %d\n", GSHORT(b->fatsize));
+	print("trksize: %d\n", GSHORT(b->trksize));
+	print("nheads: %d\n", GSHORT(b->nheads));
+	print("nhidden: %d\n", GLONG(b->nhidden));
+	print("bigvolsize: %d\n", GLONG(b->bigvolsize));
+	print("driveno: %d\n", b->driveno);
+	print("reserved0: 0x%2.2x\n", b->reserved0);
+	print("bootsig: 0x%2.2x\n", b->bootsig);
+	print("volid: 0x%8.8x\n", GLONG(b->volid));
+	print("label: \"%11.11s\"\n", b->label);
+}
+
+/*
+ *  grab next element from a path, return the pointer to unprocessed portion of
+ *  path.
+ */
+static char *
+nextelem(char *path, char *elem)
+{
+	int i;
+
+	while(*path == '/')
+		path++;
+	if(*path==0 || *path==' ')
+		return 0;
+	for(i=0; *path!='\0' && *path!='/' && *path!=' '; i++){
+		if(i==28){
+			print("name component too long\n");
+			return 0;
+		}
+		*elem++ = *path++;
+	}
+	*elem = '\0';
+	return path;
+}
+
+int
+dosstat(Dos *dos, char *path, Dosfile *f)
+{
+	char element[NAMELEN];
+
+	*f = dos->root;
+	while(path = nextelem(path, element)){
+		switch(doswalk(f, element)){
+		case -1:
+			return -1;
+		case 0:
+			return 0;
+		}
+	}
+	return 1;
+}
+
+/*
+ *  boot
+ */
+int
+dosboot(Dos *dos, char *path)
+{
+	Dosfile file;
+	long n;
+	long addr;
+	Exec *ep;
+	void (*b)(void);
+
+	switch(dosstat(dos, path, &file)){
+
+	case -1:
+		print("error walking to %s\n", path);
+		return -1;
+	case 0:
+		print("%s not found\n", path);
+		return -1;
+	case 1:
+		print("found %8.8s.%3.3s attr 0x%ux start 0x%lux len %d\n", file.name,
+			file.ext, file.attr, file.pstart, file.length);
+		break;
+	}
+
+	/*
+	 *  read header
+	 */
+	ep = (Exec*)ialloc(sizeof(Exec), 0);
+	n = sizeof(Exec);
+	if(dosreadseg(&file, n, (ulong) ep) != n){
+		print(premature);
+		return -1;
+	}
+	if(GLLONG(ep->magic) != Q_MAGIC){
+		print("bad magic 0x%lux not a plan 9 executable!\n", GLLONG(ep->magic));
+		return -1;
+	}
+
+	/*
+	 *  read text
+	 */
+	addr = PADDR(GLLONG(ep->entry));
+	n = GLLONG(ep->text);
+	print("+%d", n);
+	if(dosreadseg(&file, n, addr) != n){
+		print(premature);
+		return -1;
+	}
+
+	/*
+	 *  read data (starts at first page after kernel)
+	 */
+	addr = PGROUND(addr+n);
+	n = GLLONG(ep->data);
+	print("+%d", n);
+	if(dosreadseg(&file, n, addr) != n){
+		print(premature);
+		return -1;
+	}
+
+	/*
+	 *  bss and entry point
+	 */
+	print("+%d\nstart at 0x%lux\n", GLLONG(ep->bss), GLLONG(ep->entry));
+
+	/*
+	 *  Go to new code. It's up to the program to get its PC relocated to
+	 *  the right place.
+	 */
+	b = (void (*)(void))(PADDR(GLLONG(ep->entry)));
+	(*b)();
+	return 0;
+}
+
+/*
+ *  read in a segment
+ */
+long
+dosreadseg(Dosfile *fp, long len, long addr)
+{
+	char *a;
+	long n, sofar;
+
+	a = (char *)addr;
+	for(sofar = 0; sofar < len; sofar += n){
+		n = 8*1024;
+		if(len - sofar < n)
+			n = len - sofar;
+		n = dosread(fp, a + sofar, n);
+		if(n <= 0)
+			break;
+		print(".");
+	}
+	return sofar;
+}
+
+/*
+ *  set up a dos file name
+ */
+static void
+setname(Dosfile *fp, char *from)
+{
+	char *to;
+
+	to = fp->name;
+	for(; *from && to-fp->name < 8; from++, to++){
+		if(*from == '.'){
+			from++;
+			break;
+		}
+		if(*from >= 'a' && *from <= 'z')
+			*to = *from + 'A' - 'a';
+		else
+			*to = *from;
+	}
+	while(to - fp->name < 8)
+		*to++ = ' ';
+	
+	to = fp->ext;
+	for(; *from && to-fp->ext < 3; from++, to++){
+		if(*from >= 'a' && *from <= 'z')
+			*to = *from + 'A' - 'a';
+		else
+			*to = *from;
+	}
+	while(to-fp->ext < 3)
+		*to++ = ' ';
+
+	chat("name is %8.8s %3.3s\n", fp->name, fp->ext);
+}
--- /dev/null
+++ b/os/boot.original/mpc/dosfs.h
@@ -1,0 +1,110 @@
+typedef struct Dosboot	Dosboot;
+typedef struct Dos	Dos;
+typedef struct Dosdir	Dosdir;
+typedef struct Dosfile	Dosfile;
+typedef struct Dospart	Dospart;
+
+struct Dospart
+{
+	uchar flag;		/* active flag */
+	uchar shead;		/* starting head */
+	uchar scs[2];		/* starting cylinder/sector */
+	uchar type;		/* partition type */
+	uchar ehead;		/* ending head */
+	uchar ecs[2];		/* ending cylinder/sector */
+	uchar start[4];		/* starting sector */
+	uchar len[4];		/* length in sectors */
+};
+
+#define FAT12	0x01
+#define FAT16	0x04
+#define FATHUGE	0x06
+#define DMDDO	0x54
+
+struct Dosboot{
+	uchar	magic[3];
+	uchar	version[8];
+	uchar	sectsize[2];
+	uchar	clustsize;
+	uchar	nresrv[2];
+	uchar	nfats;
+	uchar	rootsize[2];
+	uchar	volsize[2];
+	uchar	mediadesc;
+	uchar	fatsize[2];
+	uchar	trksize[2];
+	uchar	nheads[2];
+	uchar	nhidden[4];
+	uchar	bigvolsize[4];
+	uchar	driveno;
+	uchar	reserved0;
+	uchar	bootsig;
+	uchar	volid[4];
+	uchar	label[11];
+	uchar	reserved1[8];
+};
+
+struct Dosfile{
+	Dos	*dos;		/* owning dos file system */
+	char	name[8];
+	char	ext[3];
+	uchar	attr;
+	long	length;
+	long	pstart;		/* physical start cluster address */
+	long	pcurrent;	/* physical current cluster address */
+	long	lcurrent;	/* logical current cluster address */
+	long	offset;
+};
+
+struct Dos{
+	int	dev;				/* device id */
+	long	(*read)(int, void*, long);	/* read routine */
+	long	(*seek)(int, long);		/* seek routine */
+
+	int	start;		/* start of file system */
+	int	sectsize;	/* in bytes */
+	int	clustsize;	/* in sectors */
+	int	clustbytes;	/* in bytes */
+	int	nresrv;		/* sectors */
+	int	nfats;		/* usually 2 */
+	int	rootsize;	/* number of entries */
+	int	volsize;	/* in sectors */
+	int	mediadesc;
+	int	fatsize;	/* in sectors */
+	int	fatclusters;
+	int	fatbits;	/* 12 or 16 */
+	long	fataddr;	/* sector number */
+	long	rootaddr;
+	long	dataaddr;
+	long	freeptr;
+
+	Dosfile	root;
+};
+
+struct Dosdir{
+	uchar	name[8];
+	uchar	ext[3];
+	uchar	attr;
+	uchar	reserved[10];
+	uchar	time[2];
+	uchar	date[2];
+	uchar	start[2];
+	uchar	length[4];
+};
+
+#define	DRONLY	0x01
+#define	DHIDDEN	0x02
+#define	DSYSTEM	0x04
+#define	DVLABEL	0x08
+#define	DDIR	0x10
+#define	DARCH	0x20
+
+extern int chatty;
+
+extern int dosboot(Dos*, char*);
+extern int dosinit(Dos*, int, int);
+extern long dosread(Dosfile*, void*, long);
+extern int dosstat(Dos*, char*, Dosfile*);
+extern int doswalk(Dosfile*, char*);
+
+extern int plan9ini(Dos*, char*);
--- /dev/null
+++ b/os/boot.original/mpc/etherif.h
@@ -1,0 +1,59 @@
+/*
+ * All the goo for PC ethernet cards.
+ */
+typedef struct Card Card;
+typedef struct Type Type;
+typedef struct Ctlr Ctlr;
+
+/*
+ * Hardware interface.
+ */
+struct Card {
+	ISAConf;
+
+	int	(*reset)(Ctlr*);
+	void	(*attach)(Ctlr*);
+
+	void	*(*read)(Ctlr*, void*, ulong, ulong);
+	void	*(*write)(Ctlr*, ulong, void*, ulong);
+
+	void	(*receive)(Ctlr*);
+	void	(*transmit)(Ctlr*);
+	void	(*intr)(Ureg*, void*);
+	void	(*overflow)(Ctlr*);
+
+	uchar	bit16;			/* true if a 16 bit interface */
+	uchar	ram;			/* true if card has shared memory */
+
+	ulong	dp8390;			/* I/O address of 8390 (if any) */
+	ulong	data;			/* I/O data port if no shared memory */
+	uchar	nxtpkt;			/* software bndry */
+	uchar	tstart;			/* 8390 ring addresses */
+	uchar	pstart;
+	uchar	pstop;
+
+	uchar	dummyrr;		/* do dummy remote read */
+};
+
+/*
+ * Software controller.
+ */
+struct Ctlr {
+	Card	card;			/* hardware info */
+	int	ctlrno;
+	int	present;
+
+	Queue*	iq;
+	Queue*	oq;
+
+	int	inpackets;
+	int	outpackets;
+	int	crcs;			/* input crc errors */
+	int	oerrs;			/* output errors */
+	int	frames;			/* framing errors */
+	int	overflows;		/* packet overflows */
+	int	buffs;			/* buffering errors */
+};
+
+extern int sccethreset(Ctlr*);
+extern int	etheriq(Ctlr*, Block*, int);
--- /dev/null
+++ b/os/boot.original/mpc/etherscc.c
@@ -1,0 +1,411 @@
+/*
+ * SCCn ethernet
+ */
+
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+#include "etherif.h"
+
+enum {
+	Nrdre		= 32,	/* receive descriptor ring entries */
+	Ntdre		= 4,	/* transmit descriptor ring entries */
+
+	Rbsize		= ETHERMAXTU+4,		/* ring buffer size (+4 for CRC) */
+	Bufsize		= (Rbsize+7)&~7,	/* aligned */
+};
+
+enum {
+	/* ether-specific Rx BD bits */
+	RxMiss=		1<<8,
+	RxeLG=		1<<5,
+	RxeNO=		1<<4,
+	RxeSH=		1<<3,
+	RxeCR=		1<<2,
+	RxeOV=		1<<1,
+	RxeCL=		1<<0,
+	RxError=		(RxeLG|RxeNO|RxeSH|RxeCR|RxeOV|RxeCL),	/* various error flags */
+
+	/* ether-specific Tx BD bits */
+	TxPad=		1<<14,	/* pad short frames */
+	TxTC=		1<<10,	/* transmit CRC */
+	TxeDEF=		1<<9,
+	TxeHB=		1<<8,
+	TxeLC=		1<<7,
+	TxeRL=		1<<6,
+	TxeUN=		1<<1,
+	TxeCSL=		1<<0,
+
+	/* scce */
+	RXB=	1<<0,
+	TXB=	1<<1,
+	BSY=		1<<2,
+	RXF=		1<<3,
+	TXE=		1<<4,
+
+	/* gsmrl */
+	ENR=	1<<5,
+	ENT=	1<<4,
+
+	/* port A */
+	RXD1=	SIBIT(15),
+	TXD1=	SIBIT(14),
+
+	/* port B */
+	RTS1=	IBIT(19),
+
+	/* port C */
+	CTS1=	SIBIT(11),
+	CD1=	SIBIT(10),
+};
+
+typedef struct Etherparam Etherparam;
+struct Etherparam {
+	SCCparam;
+	ulong	c_pres;		/* preset CRC */
+	ulong	c_mask;		/* constant mask for CRC */
+	ulong	crcec;		/* CRC error counter */
+	ulong	alec;		/* alighnment error counter */
+	ulong	disfc;		/* discard frame counter */
+	ushort	pads;		/* short frame PAD characters */
+	ushort	ret_lim;	/* retry limit threshold */
+	ushort	ret_cnt;	/* retry limit counter */
+	ushort	mflr;		/* maximum frame length reg */
+	ushort	minflr;		/* minimum frame length reg */
+	ushort	maxd1;		/* maximum DMA1 length reg */
+	ushort	maxd2;		/* maximum DMA2 length reg */
+	ushort	maxd;		/* rx max DMA */
+	ushort	dma_cnt;	/* rx dma counter */
+	ushort	max_b;		/* max bd byte count */
+	ushort	gaddr[4];		/* group address filter */
+	ulong	tbuf0_data0;	/* save area 0 - current frm */
+	ulong	tbuf0_data1;	/* save area 1 - current frm */
+	ulong	tbuf0_rba0;
+	ulong	tbuf0_crc;
+	ushort	tbuf0_bcnt;
+	ushort	paddr[3];	/* physical address LSB to MSB increasing */
+	ushort	p_per;		/* persistence */
+	ushort	rfbd_ptr;	/* rx first bd pointer */
+	ushort	tfbd_ptr;	/* tx first bd pointer */
+	ushort	tlbd_ptr;	/* tx last bd pointer */
+	ulong	tbuf1_data0;	/* save area 0 - next frame */
+	ulong	tbuf1_data1;	/* save area 1 - next frame */
+	ulong	tbuf1_rba0;
+	ulong	tbuf1_crc;
+	ushort	tbuf1_bcnt;
+	ushort	tx_len;		/* tx frame length counter */
+	ushort	iaddr[4];		/* individual address filter*/
+	ushort	boff_cnt;	/* back-off counter */
+	ushort	taddr[3];	/* temp address */
+};
+
+typedef struct {
+	SCC*	scc;
+	int	port;
+	int	cpm;
+
+	BD*	rdr;				/* receive descriptor ring */
+	void*	rrb;				/* receive ring buffers */
+	int	rdrx;				/* index into rdr */
+
+	BD*	tdr;				/* transmit descriptor ring */
+	void*	trb;				/* transmit ring buffers */
+	int	tdrx;				/* index into tdr */
+} Mot;
+static Mot mot[MaxEther];
+
+static	int	sccid[] = {-1, SCC1ID, SCC2ID, SCC3ID, SCC4ID};
+static	int	sccparam[] = {-1, SCC1P, SCC2P, SCC3P, SCC4P};
+static	int	sccreg[] = {-1, 0xA00, 0xA20, 0xA40, 0xA60};
+static	int	sccirq[] = {-1, 0x1E, 0x1D, 0x1C, 0x1B};
+
+static void
+attach(Ctlr *ctlr)
+{
+	mot[ctlr->ctlrno].scc->gsmrl |= ENR|ENT;
+	eieio();
+}
+
+static void
+transmit(Ctlr *ctlr)
+{
+	int len;
+	Mot *motp;
+	Block *b;
+	BD *tdre;
+
+	motp = &mot[ctlr->ctlrno];
+	while(((tdre = &motp->tdr[motp->tdrx])->status & BDReady) == 0){
+		b = qget(ctlr->oq);
+		if(b == 0)
+			break;
+
+		/*
+		 * Copy the packet to the transmit buffer.
+		 */
+		len = BLEN(b);
+		memmove(KADDR(tdre->addr), b->rp, len);
+	
+		/*
+		 * Give ownership of the descriptor to the chip, increment the
+		 * software ring descriptor pointer and tell the chip to poll.
+		 */
+		tdre->length = len;
+		eieio();
+		tdre->status = (tdre->status & BDWrap) | BDReady|TxPad|BDInt|BDLast|TxTC;
+		eieio();
+		motp->scc->todr = 1<<15;	/* transmit now */
+		eieio();
+		motp->tdrx = NEXT(motp->tdrx, Ntdre);
+
+		freeb(b);
+	
+	}
+}
+
+static void
+interrupt(Ureg*, void *ap)
+{
+	int len, events, status;
+	Mot *motp;
+	BD *rdre;
+	Block *b;
+	Ctlr *ctlr;
+
+	ctlr = ap;
+	motp = &mot[ctlr->ctlrno];
+
+	/*
+	 * Acknowledge all interrupts and whine about those that shouldn't
+	 * happen.
+	 */
+	events = motp->scc->scce;
+	eieio();
+	motp->scc->scce = events;
+	eieio();
+	if(events & (TXE|BSY|RXB))
+		print("ETHER.SCC#%d: scce = 0x%uX\n", ctlr->ctlrno, events);
+	//print(" %ux|", events);
+	/*
+	 * Receiver interrupt: run round the descriptor ring logging
+	 * errors and passing valid receive data up to the higher levels
+	 * until we encounter a descriptor still owned by the chip.
+	 */
+	if(events & (RXF|RXB) || 1){
+		rdre = &motp->rdr[motp->rdrx];
+		while(((status = rdre->status) & BDEmpty) == 0){
+			if(status & RxError || (status & (BDFirst|BDLast)) != (BDFirst|BDLast)){
+				//if(status & RxBuff)
+				//	ctlr->buffs++;
+				if(status & (1<<2))
+					ctlr->crcs++;
+				if(status & (1<<1))
+					ctlr->overflows++;
+				//print("eth rx: %ux\n", status);
+				if(status & RxError)
+					print("~");
+				else if((status & BDLast) == 0)
+					print("@");
+			}
+			else{
+				/*
+				 * We have a packet. Read it into the next
+				 * free ring buffer, if any.
+				 */
+				len = rdre->length-4;
+				if((b = iallocb(len)) != 0){
+					memmove(b->wp, KADDR(rdre->addr), len);
+					b->wp += len;
+					etheriq(ctlr, b, 1);
+				}
+			}
+
+			/*
+			 * Finished with this descriptor, reinitialise it,
+			 * give it back to the chip, then on to the next...
+			 */
+			rdre->length = 0;
+			rdre->status = (rdre->status & BDWrap) | BDEmpty | BDInt;
+			eieio();
+
+			motp->rdrx = NEXT(motp->rdrx, Nrdre);
+			rdre = &motp->rdr[motp->rdrx];
+		}
+	}
+
+	/*
+	 * Transmitter interrupt: handle anything queued for a free descriptor.
+	 */
+	if(events & TXB)
+		transmit(ctlr);
+	if(events & TXE)
+		cpmop(RestartTx, motp->cpm, 0);
+}
+
+static void
+ringinit(Mot* motp)
+{
+	int i, x;
+
+	/*
+	 * Initialise the receive and transmit buffer rings. The ring
+	 * entries must be aligned on 16-byte boundaries.
+	 */
+	if(motp->rdr == 0)
+		motp->rdr = bdalloc(Nrdre);
+	if(motp->rrb == 0)
+		motp->rrb = ialloc(Nrdre*Bufsize, 0);
+	x = PADDR(motp->rrb);
+	for(i = 0; i < Nrdre; i++){
+		motp->rdr[i].length = 0;
+		motp->rdr[i].addr = x;
+		motp->rdr[i].status = BDEmpty|BDInt;
+		x += Bufsize;
+	}
+	motp->rdr[i-1].status |= BDWrap;
+	motp->rdrx = 0;
+
+	if(motp->tdr == 0)
+		motp->tdr = bdalloc(Ntdre);
+	if(motp->trb == 0)
+		motp->trb = ialloc(Ntdre*Bufsize, 0);
+	x = PADDR(motp->trb);
+	for(i = 0; i < Ntdre; i++){
+		motp->tdr[i].addr = x;
+		motp->tdr[i].length = 0;
+		motp->tdr[i].status = TxPad|BDInt|BDLast|TxTC;
+		x += Bufsize;
+	}
+	motp->tdr[i-1].status |= BDWrap;
+	motp->tdrx = 0;
+}
+
+/*
+ * This follows the MPC823 user guide: section16.9.23.7's initialisation sequence,
+ * except that it sets the right bits for the MPC823ADS board when SCC2 is used,
+ * and those for the 860/821 development board for SCC1.
+ */
+static void
+sccsetup(Mot *ctlr, SCC *scc, uchar *ea)
+{
+	int i, rcs, tcs, w;
+	Etherparam *p;
+	IMM *io;
+
+
+	i = 2*(ctlr->port-1);
+	io = ioplock();
+	w = (TXD1|RXD1)<<i;	/* TXDn and RXDn in port A */
+	io->papar |= w;	/* enable TXDn and RXDn pins */
+	io->padir &= ~w;
+	io->paodr &= ~w;	/* not open drain */
+
+	w = (CD1|CTS1)<<i;	/* CLSN and RENA: CDn and CTSn in port C */
+	io->pcpar &= ~w;	/* enable CLSN (CTSn) and RENA (CDn) */
+	io->pcdir &= ~w;
+	io->pcso |= w;
+	iopunlock();
+
+	/* clocks and transceiver control: details depend on the board's wiring */
+	archetherenable(ctlr->cpm, &rcs, &tcs);
+
+	sccnmsi(ctlr->port, rcs, tcs);	/* connect the clocks */
+
+	p = (Etherparam*)KADDR(sccparam[ctlr->port]);
+	memset(p, 0, sizeof(*p));
+	p->rfcr = 0x18;
+	p->tfcr = 0x18;
+	p->mrblr = Bufsize;
+	p->rbase = PADDR(ctlr->rdr);
+	p->tbase = PADDR(ctlr->tdr);
+
+	cpmop(InitRxTx, ctlr->cpm, 0);
+
+	p->c_pres = ~0;
+	p->c_mask = 0xDEBB20E3;
+	p->crcec = 0;
+	p->alec = 0;
+	p->disfc = 0;
+	p->pads = 0x8888;
+	p->ret_lim = 0xF;
+	p->mflr = Rbsize;
+	p->minflr = ETHERMINTU+4;
+	p->maxd1 = Bufsize;
+	p->maxd2 = Bufsize;
+	p->p_per = 0;	/* only moderate aggression */
+
+	for(i=0; i<Eaddrlen; i+=2)
+		p->paddr[2-i/2] = (ea[i+1]<<8)|ea[i];	/* it's not the obvious byte order */
+
+	scc->psmr = (2<<10)|(5<<1);	/* 32-bit CRC, ignore 22 bits before SFD */
+	scc->dsr = 0xd555;
+	scc->gsmrh = 0;	/* normal operation */
+	scc->gsmrl = (1<<28)|(4<<21)|(1<<19)|0xC;	/* transmit clock invert, 48 bit preamble, repetitive 10 preamble, ethernet */
+	eieio();
+	scc->scce = ~0;	/* clear all events */
+	eieio();
+	scc->sccm = TXE | RXF | TXB;	/* enable interrupts */
+	eieio();
+
+	io = ioplock();
+	w = RTS1<<(ctlr->port-1);	/* enable TENA pin (RTSn) */
+	io->pbpar |= w;
+	io->pbdir |= w;
+	iopunlock();
+
+	/* gsmrl enable is deferred until attach */
+}
+
+/*
+ * Prepare the SCCx ethernet for booting.
+ */
+int
+sccethreset(Ctlr* ctlr)
+{
+	uchar ea[Eaddrlen];
+	Mot *motp;
+	SCC *scc;
+	char line[50], def[50];
+
+	/*
+	 * Since there's no EPROM, insist that the configuration entry
+	 * (see conf.c and flash.c) holds the Ethernet address.
+	 */
+	memset(ea, 0, Eaddrlen);
+	if(memcmp(ea, ctlr->card.ea, Eaddrlen) == 0){
+		print("no preset Ether address\n");
+		for(;;){
+			strcpy(def, "00108bf12900");	/* valid MAC address to be used only for initial configuration */
+			if(getstr("ether MAC address", line, sizeof(line), def) < 0)
+				return -1;
+			if(parseether(ctlr->card.ea, line) >= 0 || ctlr->card.ea[0] == 0xFF)
+				break;
+			print("invalid MAC address\n");
+		}
+	}
+
+	scc = IOREGS(sccreg[ctlr->card.port], SCC);
+	ctlr->card.irq = VectorCPIC+sccirq[ctlr->card.port];
+
+	motp = &mot[ctlr->ctlrno];
+	motp->scc = scc;
+	motp->port = ctlr->card.port;
+	motp->cpm = sccid[ctlr->card.port];
+
+	ringinit(motp);
+
+	sccsetup(motp, scc, ctlr->card.ea);
+
+	/* enable is deferred until attach */
+
+	ctlr->card.reset = sccethreset;
+	ctlr->card.attach = attach;
+	ctlr->card.transmit = transmit;
+	ctlr->card.intr = interrupt;
+
+	return 0;
+}
--- /dev/null
+++ b/os/boot.original/mpc/fblt.c
@@ -1,0 +1,531 @@
+#include <u.h>
+#include <libc.h>
+#include <libg.h>
+#include <gnot.h>
+
+/*
+ * bitblt operates a 'word' at a time.
+ * WBITS is the number of bits in a word
+ * LWBITS=log2(WBITS),
+ * W2L is the number of words in a long
+ * WMASK has bits set for the low order word of a long
+ * WType is a pointer to a word
+ */
+#ifndef WBITS
+#define WBITS	32
+#define LWBITS	5
+#define	W2L	1
+#define WMASK	~0UL
+typedef ulong	*WType;
+#endif
+
+#define DEBUG 
+
+#ifdef TEST
+/*
+ * globals used for testing
+ */
+int	FORCEFORW;
+int	FORCEBAKW;
+GBitmap	*curdm, *cursm;
+Point	curpt;
+Rectangle curr;
+Fcode	curf;
+void	*mem;
+#endif
+
+static void
+gbitexplode(ulong sw, ulong *buf, int sdep, int x)
+{
+	int j, o, q, n, nw, inc, qinc;
+	ulong s, dw, pix;
+
+	inc = 1 << sdep;
+	pix = (1 << inc) - 1;
+	nw = 1 << x;
+	n = 32 >> x;
+	qinc = (nw << sdep) - inc;
+	for(o = 32 - n; o >= 0; o -= n){
+		dw = 0;
+		s = sw >> o;
+		q = 0;
+		for(j = 0; j < n; j += inc){
+			dw |= (s & (pix << j)) << q;
+			q += qinc;
+		}
+		for(j = 0; j < x; j++)
+			dw |= dw << (inc << j);
+		*buf++ = dw;
+	}
+}
+
+/*
+void
+main(void)
+{
+	ulong buf[128];
+
+	gbitexplode(0x7777, buf, 0, 3);
+	exits(0);
+}
+*/
+
+void
+gbitblt(GBitmap *dm, Point pt, GBitmap *sm, Rectangle r, Fcode fcode)
+{
+	int	width;		/* width in bits of dst */
+	int	wwidth;		/* floor width in words */
+	int	height;		/* height in pixels minus 1 */
+	int	sdep;		/* src ldepth */
+	int 	ddep;		/* dst ldepth */
+	int	deltadep;	/* diff between ldepths */
+	int	sspan;		/* words between scanlines in src */
+	int	dspan;		/* words between scanlines in dst */
+	int	soff;		/* bit offset of src start point */
+	int	sdest;		/* bit offset of src start point that matches doff when expanded */
+	int	doff;		/* bit offset of dst start point */
+	int	delta;		/* amount to shift src by */
+	int	sign;		/* of delta */
+	ulong	*saddr;
+	ulong	*daddr;
+	ulong	*s;
+	ulong	*d;
+	ulong	mask;
+	ulong	tmp;		/* temp storage source word */
+	ulong	sw;		/* source word constructed */
+	ulong	dw;		/* dest word fetched */
+	ulong	lmask;		/* affected pixels in leftmost dst word */
+	ulong	rmask;		/* affected pixels in rightmost dst word */
+	int	i;
+	int	j;
+	ulong	buf[32];	/* for expanding a source */
+	ulong	*p;		/* pointer into buf */
+	int	spare;		/* number of words already converted */
+
+
+#ifdef TEST
+	curdm = dm;
+	cursm = sm;
+	curpt = pt;
+	curr = r;
+	curf = fcode;
+#endif
+
+	gbitbltclip(&dm);
+
+	width = r.max.x - r.min.x;
+	if(width <= 0)
+		return;
+	height = r.max.y - r.min.y - 1;
+	if(height < 0)
+		return;
+
+	ddep = dm->ldepth;
+	pt.x <<= ddep;
+	width <<= ddep;
+
+	sdep = sm->ldepth;
+	r.min.x <<= sdep;
+	r.max.x <<= sdep;
+
+	dspan = dm->width * W2L;
+	sspan = sm->width * W2L;
+
+	daddr = (ulong*)((WType)dm->base
+			+ dm->zero*W2L + pt.y*dspan
+			+ (pt.x >> LWBITS));
+	saddr = (ulong*)((WType)sm->base
+			+ sm->zero*W2L + r.min.y*sspan
+			+ (r.min.x >> LWBITS));
+
+	doff = pt.x & (WBITS - 1);
+	lmask = WMASK >> doff;
+	rmask = (WMASK << (WBITS - ((doff+width) & (WBITS-1))))&WMASK;
+	if(!rmask)
+		rmask = WMASK;
+	soff = r.min.x & (WBITS-1);
+	wwidth = ((pt.x+width-1)>>LWBITS) - (pt.x>>LWBITS);
+
+	if(sm == dm){
+#ifdef TEST
+		if(!FORCEBAKW &&
+		   (FORCEFORW || sm != dm || saddr > daddr ||
+		    (saddr == daddr && soff > doff)))
+			;
+		else{
+			daddr += height * dspan;
+			saddr += height * sspan;
+			sspan -= 2 * W2L * sm->width;
+			dspan -= 2 * W2L * dm->width;
+		}
+#else
+		if(r.min.y < pt.y){	/* bottom to top */
+			daddr += height * dspan;
+			saddr += height * sspan;
+			sspan -= 2 * W2L * sm->width;
+			dspan -= 2 * W2L * dm->width;
+		}else if(r.min.y == pt.y && r.min.x < pt.x)
+			abort()/*goto right*/;
+#endif
+	}
+	if(wwidth == 0)		/* collapse masks for narrow cases */
+		lmask &= rmask;
+	fcode &= F;
+
+	deltadep = ddep - sdep;
+	sdest = doff >> deltadep;
+	delta = soff - sdest;
+	sign = 0;
+	if(delta < 0){
+		sign = 1;
+		delta = -delta;
+	}
+
+	p = 0;
+	for(j = 0; j <= height; j++){
+		d = daddr;
+		s = saddr;
+		mask = lmask;
+		tmp = 0;
+		if(!sign)
+			tmp = *s++;
+		spare = 0;
+		for(i = wwidth; i >= 0; i--){
+			if(spare)
+				sw = *p++;
+			else{
+				if(sign){
+					sw = tmp << (WBITS-delta);
+					tmp = *s++;
+					sw |= tmp >> delta;
+				}else{
+					sw = tmp << delta;
+					tmp = *s++;
+					if(delta)
+						sw |= tmp >> (WBITS-delta);
+				}
+				spare = 1 << deltadep;
+				if(deltadep >= 1){
+					gbitexplode(sw, buf, sdep, deltadep);
+					p = buf;
+					sw = *p++;
+				}
+			}
+
+			dw = *d;
+			switch(fcode){		/* ltor bit aligned */
+			case Zero:	*d = dw & ~mask;		break;
+			case DnorS:	*d = dw ^ ((~sw | dw) & mask);	break;
+			case DandnotS:	*d = dw ^ ((sw & dw) & mask);	break;
+			case notS:	*d = dw ^ ((~sw ^ dw) & mask);	break;
+			case notDandS:	*d = dw ^ ((sw | dw) & mask);	break;
+			case notD:	*d = dw ^ mask;			break;
+			case DxorS:	*d = dw ^ (sw & mask);		break;
+			case DnandS:	*d = dw ^ ((sw | ~dw) & mask);	break;
+			case DandS:	*d = dw ^ ((~sw & dw) & mask);	break;
+			case DxnorS:	*d = dw ^ (~sw & mask);		break;
+			case D:						break;
+			case DornotS:	*d = dw | (~sw & mask);		break;
+			case S:		*d = dw ^ ((sw ^ dw) & mask);	break;
+			case notDorS:	*d = dw ^ (~(sw & dw) & mask);	break;
+			case DorS:	*d = dw | (sw & mask);		break;
+			case F:		*d = dw | mask;			break;
+			}
+			d++;
+
+			mask = WMASK;
+			if(i == 1)
+				mask = rmask;
+			spare--;
+		}
+		saddr += sspan;
+		daddr += dspan;
+	}
+}
+
+#ifdef TEST
+void	prprog(void);
+GBitmap *bb1, *bb2;
+ulong	*src, *dst, *xdst, *xans;
+int	swds, dwds;
+long	ticks;
+int	timeit;
+
+long
+func(int f, long s, int sld, long d, int dld)
+{
+	long a;
+	int sh, i, db, sb;
+
+	db = 1 << dld;
+	sb = 1 << sld;
+	sh = db - sb;
+	if(sh > 0) {
+		a = s;
+		for(i = sb; i<db; i += sb){
+			a <<= sb;
+			s |= a;
+		}
+	} else if(sh < 0)
+		s >>= -sh;
+
+	switch(f){
+	case Zero:	d = 0;			break;
+	case DnorS:	d = ~(d|s);		break;
+	case DandnotS:	d = d & ~s;		break;
+	case notS:	d = ~s;			break;
+	case notDandS:	d = ~d & s;		break;
+	case notD:	d = ~d;			break;
+	case DxorS:	d = d ^ s;		break;
+	case DnandS:	d = ~(d&s);		break;
+	case DandS:	d = d & s;		break;
+	case DxnorS:	d = ~(d^s);		break;
+	case S:		d = s;			break;
+	case DornotS:	d = d | ~s;		break;
+	case D:		d = d;			break;
+	case notDorS:	d = ~d | s;		break;
+	case DorS:	d = d | s;		break;
+	case F:		d = ~0;			break;
+	}
+
+	d &= ((1<<db)-1);
+	return d;
+}
+
+void
+run(int fr, int to, int w, int op)
+{
+	int i, j, f, t, fy, ty;
+	extern long *_clock;
+
+	fr += bb2->r.min.x;
+	to += bb1->r.min.x;
+	fy = bb2->r.min.y + 1;
+	ty = bb1->r.min.y + 1;
+	if(timeit) {
+		memcpy(dst, xdst, dwds * sizeof(long));
+		ticks -= *_clock;
+		gbitblt(bb1, Pt(to,ty), bb2, Rect(fr,fy,fr+w,fy+2), op);
+		ticks += *_clock;
+		return;
+	}
+	f = fr;
+	t = to;
+	memcpy(dst, xdst, dwds * sizeof(long));
+	for(i=0; i<w; i++) {
+		gbitblt(bb1, Pt(t,ty), bb2, Rect(f,fy,f+1,fy+1), op);
+		gbitblt(bb1, Pt(t,ty+1), bb2, Rect(f,fy+1,f+1,fy+2), op);
+		f++;
+		t++;
+	}
+	memcpy(xans, dst, dwds * sizeof(long));
+
+	memcpy(dst, xdst, dwds * sizeof(long));
+	gbitblt(bb1, Pt(to,ty), bb2, Rect(fr,fy,fr+w,fy+2), op);
+
+	if(memcmp(xans, dst, dwds * sizeof(long))) {
+		/*
+		 * print src and dst row offset, width in bits, and forw/back
+		 * then print for each of the four rows: the source (s),
+		 * the dest (d), the good value of the answer (g),
+		 * and the actual bad value of the answer (b)
+		 */
+		print("fr=%d to=%d w=%d fb=%d%d\n",
+			fr, to, w, FORCEFORW, FORCEBAKW);
+		print("dst bitmap b %#lux, z %d, w %d, ld %d, r [%d,%d][%d,%d]\n",
+			bb1->base, bb1->zero, bb1->width, bb1->ldepth,
+			bb1->r.min.x, bb1->r.min.y, bb1->r.max.x, bb1->r.max.y);
+		print("src bitmap b %#lux, z %d, w %d, ld %d, r [%d,%d][%d,%d]\n",
+			bb2->base, bb2->zero, bb2->width, bb2->ldepth,
+			bb2->r.min.x, bb2->r.min.y, bb2->r.max.x, bb2->r.max.y);
+		for(j=0; 7*j < dwds; j++) {
+			print("\ns");
+			for(i=0; i<7 && 7*j+i < dwds; i++)
+				print(" %.8lux", src[7*j + i]);
+			print("\nd");
+			for(i=0; i<7 && 7*j+i < dwds; i++)
+				print(" %.8lux", xdst[7*j + i]);
+			print("\ng");
+			for(i=0; i<7 && 7*j+i < dwds; i++)
+				print(" %.8lux", xans[7*j + i]);
+			print("\nb");
+			for(i=0; i<7 && 7*j+i < dwds; i++)
+				print(" %.8lux", dst[7*j + i]);
+			print("\n");
+		}
+		prprog();
+	}
+}
+
+void
+prprog(void)
+{
+	exits(0);
+}
+
+int
+main(int argc, char *argv[])
+{
+	int f, t, w, i, sld, dld, op, iters, simple;
+	ulong s, d, spix, dpix, apix, fpix, m, *ps, *pd;
+	Point sorg, dorg;
+	GBitmap *bs, *bd;
+	long seed;
+	char *ct;
+
+	sld = 0;
+	dld = 0;
+	timeit = 0;
+	iters = 200;
+	simple = 0;
+	ARGBEGIN {
+	case 'i':
+		iters = atoi(ARGF());
+		break;
+	case 's':
+		simple = 1;
+		break;
+	case 't':
+		timeit = 1;
+		ct = ARGF();
+		if(ct)
+			iters = atoi(ct);
+		break;
+	} ARGEND
+	if(argc > 0)
+		sld = atoi(argv[0]);
+	if(argc > 1)
+		dld = atoi(argv[1]);
+	if(!timeit && !simple) {
+		seed = time(0);
+		print("seed %lux\n", seed); srand(seed);	/**/
+	}
+
+	print("sld %d dld %d\n", sld, dld);
+	op = 1;
+
+	/* bitmaps for 1-bit tests */
+	bd = gballoc(Rect(0,0,32,1), dld);
+	bs = gballoc(Rect(0,0,32,1), sld);
+	for(i=0; i<bs->width; i++)
+		bs->base[i] = lrand();
+
+	/* bitmaps for rect tests */
+	if(simple) {
+		dorg = Pt(0,0);
+		sorg = Pt(0,0);
+	} else {
+		dorg = Pt(nrand(63)-31,nrand(63)-31);
+		sorg = Pt(nrand(63)-31,nrand(63)-31);
+	}
+	bb1 = gballoc(Rpt(dorg,add(dorg,Pt(200,4))), dld);
+	bb2 = gballoc(Rpt(sorg,add(sorg,Pt(200,4))), sld);
+	dwds = bb1->width * Dy(bb1->r);
+	swds = bb2->width * Dy(bb2->r);
+	dst = bb1->base;
+	src = bb2->base;
+	xdst = malloc(dwds * sizeof(long));
+	xans =  malloc(dwds * sizeof(long));
+	for(i=0; i<swds; i++)
+		src[i] = lrand();
+	for(i=0; i<dwds; i++)
+		xdst[i] = lrand();
+
+loop:
+	print("Op %d\n", op);
+	if(!timeit) {
+		print("one pixel\n");
+		ps = bs->base;
+		pd = bd->base;
+		FORCEFORW = 1;
+		FORCEBAKW = 0;
+		for(i=0; i<1000; i++, FORCEFORW = !FORCEFORW, FORCEBAKW = !FORCEBAKW) {
+			f = nrand(32 >> sld);
+			t = nrand(32 >> dld);
+			s = lrand();
+			d = lrand();
+			ps[0] = s;
+			pd[0] = d;
+#ifdef T386
+			spix = (byterev(s) >> (32 - ((f+1)<<sld))) & ((1 << (1<<sld)) - 1);
+			dpix = (byterev(d) >> (32 - ((t+1)<<dld))) & ((1 << (1<<dld)) - 1);
+#else
+			spix = (s >> (32 - ((f+1)<<sld))) & ((1 << (1<<sld)) - 1);
+			dpix = (d >> (32 - ((t+1)<<dld))) & ((1 << (1<<dld)) - 1);
+#endif
+#ifdef T386
+			apix = byterev(func(op, spix, sld, dpix, dld) << (32 - ((t+1)<<dld)));
+#else
+			apix = func(op, spix, sld, dpix, dld) << (32 - ((t+1)<<dld));
+#endif
+			gbitblt(bd, Pt(t,0), bs, Rect(f,0,f+1,1), op);
+			if(ps[0] != s) {
+				print("bb src %.8lux %.8lux %d %d\n", ps[0], s, f, t);
+				exits("error");
+			}
+			m = ((1 << (1<<dld)) - 1) << (32 - ((t+1)<<dld));
+#ifdef T386
+			m = byterev(m);
+#endif
+			if((pd[0] & ~m) != (d & ~m)) {
+					print("bb dst1 %.8lux %.8lux\n",
+						s, d);
+					print("bb      %.8lux %.8lux %d %d\n",
+						ps[0], pd[0], f, t);
+					prprog();
+					exits("error");
+			}
+			if((pd[0] & m) != apix) {
+				spix <<= 32 - ((f+1)<<sld);
+				dpix <<= 32 - ((t+1)<<dld);
+#ifdef T386
+				spix = byterev(spix);
+				dpix = byterev(dpix);
+#endif
+				print("bb dst2 %.8lux %.8lux\n",
+					s, d);
+				print("bb      %.8lux %.8lux %d %d\n",
+					ps[0], pd[0], f, t);
+				print("bb      %.8lux %.8lux %.8lux %.8lux\n",
+					spix, dpix, apix, pd[0] & m);
+				prprog();
+				exits("error");
+			}
+		}
+	}
+
+	print("for\n");
+	FORCEFORW = 1;
+	FORCEBAKW = 0;
+
+	for(i=0; i<iters; i++) {
+		f = nrand(64);
+		t = nrand(64);
+		w = nrand(130);
+		run(f, t, w, op);
+	}
+
+	if(sld == dld) {
+		print("bak\n");
+		FORCEFORW = 0;
+		FORCEBAKW = 1;
+	
+		for(i=0; i<iters; i++) {
+			f = nrand(64);
+			t = nrand(64);
+			w = nrand(130);
+			run(f, t, w, op);
+		}
+	}
+
+	if(op < F) {
+		op++;
+		goto loop;
+	}
+	if(timeit)
+		print("time: %d ticks\n", ticks);
+	exits(0);
+}
+
+
+#endif
--- /dev/null
+++ b/os/boot.original/mpc/flash.c
@@ -1,0 +1,212 @@
+#include "boot.h"
+
+typedef struct Flashdev Flashdev;
+struct Flashdev {
+	uchar*	base;
+	int	size;
+	uchar*	exec;
+	char*	config;
+	int	conflen;
+};
+
+enum {
+	FLASHSEG = 256*1024,
+	CONFIGLIM = FLASHSEG,
+	BOOTOFF = FLASHSEG,
+	BOOTLEN = 3*FLASHSEG,	/* third segment might be filsys */
+	/* rest of flash is free */
+};
+
+static Flashdev flash;
+
+/*
+ * configuration data is written between the bootstrap and
+ * the end of region 0. the region ends with allocation descriptors
+ * of the following form:
+ *
+ * byte order is big endian
+ *
+ * the last valid region found that starts with the string "#plan9.ini\n" is plan9.ini
+ */
+typedef struct Flalloc Flalloc;
+struct Flalloc {
+	ulong	check;	/* checksum of data, or ~0 */
+	ulong	base;	/* base of region; ~0 if unallocated, 0 if deleted */
+	uchar	len[3];
+	uchar	tag;		/* see below */
+	uchar	sig[4];
+};
+
+enum {
+	/* tags */
+	Tdead=	0,
+	Tboot=	0x01,	/* space reserved for boot */
+	Tconf=	0x02,	/* configuration data */
+	Tnone=	0xFF,
+
+	Noval=	~0,
+};
+
+static char flashsig[] = {0xF1, 0xA5, 0x5A, 0x1F};
+static char conftag[] = "#plan9.ini\n";
+
+static ulong
+checksum(uchar* p, int n)
+{
+	ulong s;
+
+	for(s=0; --n >= 0;)
+		s += *p++;
+	return s;
+}
+
+static int
+validptr(Flalloc *ap, uchar *p)
+{
+	return p > (uchar*)&end && p < (uchar*)ap;
+}
+
+static int
+flashcheck(Flalloc *ap, char **val, int *len)
+{
+	uchar *base;
+	int n;
+
+	if(ap->base == Noval || ap->base >= FLASHSEG || ap->tag == Tnone)
+		return 0;
+	base = flash.base+ap->base;
+	if(!validptr(ap, base))
+		return 0;
+	n = (((ap->len[0]<<8)|ap->len[1])<<8)|ap->len[2];
+	if(n == 0xFFFFFF)
+		n = 0;
+	if(n < 0)
+		return 0;
+	if(n > 0 && !validptr(ap, base+n-1))
+		return 0;
+	if(ap->check != Noval && checksum(base, n) != ap->check){
+		print("flash: bad checksum\n");
+		return 0;
+	}
+	*val = (char*)base;
+	*len = n;
+	return 1;
+}
+
+int
+flashinit(void)
+{
+	int len;
+	char *val;
+	Flalloc *ap;
+	void *addr;
+	long mbytes;
+	char type[20];
+
+	flash.base = 0;
+	flash.exec = 0;
+	flash.size = 0;
+	if(archflashreset(type, &addr, &mbytes) < 0){
+		print("flash: flash not present or not enabled\n");	/* shouldn't happen */
+		return 0;
+	}
+	flash.size = mbytes;
+	flash.base = addr;
+	flash.exec = flash.base + BOOTOFF;
+	flash.config = nil;
+	flash.conflen = 0;
+
+	for(ap = (Flalloc*)(flash.base+CONFIGLIM)-1; memcmp(ap->sig, flashsig, 4) == 0; ap--){
+		if(0)
+			print("conf #%8.8lux: #%x #%6.6lux\n", ap, ap->tag, ap->base);
+		if(ap->tag == Tconf &&
+		   flashcheck(ap, &val, &len) &&
+		   len >= sizeof(conftag)-1 &&
+		   memcmp(val, conftag, sizeof(conftag)-1) == 0){
+			flash.config = val;
+			flash.conflen = len;
+			if(0)
+				print("flash: found config %8.8lux(%d):\n%s\n", val, len, val);
+		}
+	}
+	if(flash.config == nil)
+		print("flash: no config\n");
+	else
+		print("flash config %8.8lux(%d):\n%s\n", flash.config, flash.conflen, flash.config);
+	if(issqueezed(flash.exec) == Q_MAGIC){
+		print("flash: squeezed powerpc kernel installed\n");
+		return 1<<0;
+	}
+	if(GLLONG(flash.exec) == Q_MAGIC){
+		print("flash: unsqueezed powerpc kernel installed\n");
+		return 1<<0;
+	}
+	flash.exec = 0;
+	print("flash: no powerpc kernel in Flash\n");
+	return 0;
+}
+
+char*
+flashconfig(int)
+{
+	return flash.config;
+}
+
+int
+flashbootable(int)
+{
+	return flash.exec != nil && (issqueezed(flash.exec) || GLLONG(flash.exec) == Q_MAGIC);
+}
+
+int
+flashboot(int)
+{
+	ulong entry, addr;
+	void (*b)(void);
+	Exec *ep;
+	Block in;
+	long n;
+	uchar *p;
+
+	if(flash.exec == 0)
+		return -1;
+	p = flash.exec;
+	if(GLLONG(p) == Q_MAGIC){
+		/* unsqueezed: copy data and perhaps text, then jump to it */
+		ep = (Exec*)p;
+		entry = PADDR(GLLONG(ep->entry));
+		p += sizeof(Exec);
+		addr = entry;
+		n = GLLONG(ep->text);
+		if(addr != (ulong)p){
+			memmove((void*)addr, p, n);
+			print("text: %8.8lux <- %8.8lux [%ld]\n", addr, p, n);
+		}
+		p += n;
+		if(entry >= FLASHMEM)
+			addr = 3*BY2PG;	/* kernel text is in Flash, data in RAM */
+		else
+			addr = PGROUND(addr+n);
+		n = GLLONG(ep->data);
+		memmove((void*)addr, p, n);
+		print("data: %8.8lux <- %8.8lux [%ld]\n", addr, p, n);
+	}else{
+		in.data = p;
+		in.rp = in.data;
+		in.lim = p+BOOTLEN;
+		in.wp = in.lim;
+		n = unsqueezef(&in, &entry);
+		if(n < 0)
+			return -1;
+	}
+	print("entry=0x%lux\n", entry);
+	uartwait();
+	scc2stop();
+	/*
+	 *  Go to new code. It's up to the program to get its PC relocated to
+	 *  the right place.
+	 */
+	b = (void (*)(void))KADDR(PADDR(entry));
+	(*b)();
+	return -1;
+}
--- /dev/null
+++ b/os/boot.original/mpc/fns.h
@@ -1,0 +1,117 @@
+Alarm*	alarm(int, void (*)(Alarm*), void*);
+void	alarminit(void);
+void	archbacklight(int);
+char*	archconfig(void);
+void	archdisableuart(int);
+void	archenableuart(int, int);
+void	archenableusb(int);
+void	archetherdisable(int);
+int	archetherenable(int, int*, int*);
+int	archflashreset(char*, void**, long*);
+void	archinit(void);
+int	archoptionsw(void);
+int	bootp(int, char*);
+void	cancel(Alarm*);
+void	checkalarms(void);
+void	clockinit(void);
+void	clockintr(Ureg*, void*);
+void	consinit(void);
+void	cpminit(void);
+void	cpuidprint(void);
+#define	dcflush(a,b)
+void	delay(int);
+void	eieio(void);
+uchar*	etheraddr(int);
+int	etherinit(void);
+int	etherrxpkt(int, Etherpkt*, int);
+int	ethertxpkt(int, Etherpkt*, int, int);
+void	exception(void);
+int	flashboot(int);
+int	flashbootable(int);
+char*	flashconfig(int);
+int	flashinit(void);
+void	free(void*);
+void	freeb(Block*);
+int	getcfields(char*, char**, int, char*);
+char*	getconf(char*);
+ulong	getdec(void);
+ulong	gethid0(void);
+ulong	getimmr(void);
+ulong	getmsr(void);
+ulong	getpvr(void);
+int	getstr(char*, char*, int, char*);
+ulong	gettbl(void);
+ulong	gettbu(void);
+int	hardinit(void);
+long	hardread(int, void*, long);
+long	hardseek(int, long);
+long	hardwrite(int, void*, long);
+long	i2csend(int, void*, long);
+void	i2csetup(void);
+void*	ialloc(ulong, int);
+Block*	iallocb(int);
+void	idle(void);
+int	isaconfig(char*, int, ISAConf*);
+int	issqueezed(uchar*);
+void	kbdchar(Queue*, int);
+void	kbdinit(void);
+void	kbdreset(void);
+void	machinit(void);
+void*	malloc(ulong);
+ulong	mapalloc(RMap*, ulong, int, int);
+void	mapfree(RMap*, ulong, int);
+void	mapinit(RMap*, Map*, int);
+void	meminit(void);
+void	microdelay(int);
+void	mmuinit(void);
+int	optionsw(void);
+void	panic(char*, ...);
+int	parseether(uchar*, char*);
+int	plan9boot(int, long (*)(int, long), long (*)(int, void*, long));
+void	putdec(ulong);
+void	puthid0(ulong);
+void	putmsr(ulong);
+int	qbgetc(Queue*);
+void	qbputc(Queue*, int);
+void	qbwrite(Queue*, Block*);
+Block*	qget(Queue*);
+long	qlen(Queue*);
+Queue*	qopen(int, int, void (*)(void*), void*);
+#define	qpass	qbwrite
+void	scc2stop(void);
+void	sccnmsi(int, int, int);
+void	sched(void);
+void	screeninit(void);
+void	screenputs(char*, int);
+void	sdraminit(ulong);
+Partition*	sethardpart(int, char*);
+Partition*	setscsipart(int, char*);
+void	setvec(int, void (*)(Ureg*, void*), void*);
+int	splhi(void);
+int	spllo(void);
+void	splx(int);
+void	trapinit(void);
+void	uartputs(char*, int);
+void	uartsetboot(void (*f)(uchar*, int));
+void	uartspecial(int, int, Queue**, Queue**, void(*)(Queue*,int));
+void	uartwait(void);
+long	unsqueezef(Block*, ulong*);
+
+#define	GSHORT(p)	(((p)[1]<<8)|(p)[0])
+#define	GLONG(p)	((GSHORT(p+2)<<16)|GSHORT(p))
+#define	GLSHORT(p)	(((p)[0]<<8)|(p)[1])
+#define	GLLONG(p)	((GLSHORT(p)<<16)|GLSHORT(p+2))
+
+#define KADDR(a)	((void*)((ulong)(a)|KZERO))
+#define PADDR(a)	((ulong)(a)&~KSEGM)
+
+/* IBM bit field order */
+#define	IBIT(b)	((ulong)1<<(31-(b)))
+#define	SIBIT(n)	((ushort)1<<(15-(n)))
+
+#define IOREGS(x, T)	((T*)((char*)m->iomem+(x)))
+
+int	uartinit(void);
+Partition*	setuartpart(int, char*);
+long	uartread(int, void*, long);
+long	uartseek(int, long);
--- /dev/null
+++ b/os/boot.original/mpc/gbitbltclip.c
@@ -1,0 +1,52 @@
+#include <u.h>
+#include <libc.h>
+#include <libg.h>
+#include <gnot.h>
+
+void
+gbitbltclip(void *vp)
+{
+	int dx, dy;
+	int i;
+	struct{
+		GBitmap *dm;
+		Point p;
+		GBitmap *sm;
+		Rectangle r;
+		Fcode f;
+	}*bp;
+
+	bp = vp;
+	dx = Dx(bp->r);
+	dy = Dy(bp->r);
+	if(bp->p.x < bp->dm->clipr.min.x){
+		i = bp->dm->clipr.min.x-bp->p.x;
+		bp->r.min.x += i;
+		bp->p.x += i;
+		dx -= i;
+	}
+	if(bp->p.y < bp->dm->clipr.min.y){
+		i = bp->dm->clipr.min.y-bp->p.y;
+		bp->r.min.y += i;
+		bp->p.y += i;
+		dy -= i;
+	}
+	if(bp->p.x+dx > bp->dm->clipr.max.x)
+		bp->r.max.x -= bp->p.x+dx-bp->dm->clipr.max.x;
+	if(bp->p.y+dy > bp->dm->clipr.max.y)
+		bp->r.max.y -= bp->p.y+dy-bp->dm->clipr.max.y;
+	if(bp->r.min.x < bp->sm->clipr.min.x){
+		i = bp->sm->clipr.min.x-bp->r.min.x;
+		bp->p.x += i;
+		bp->r.min.x += i;
+	}
+	if(bp->r.min.y < bp->sm->clipr.min.y){
+		i = bp->sm->clipr.min.y-bp->r.min.y;
+		bp->p.y += i;
+		bp->r.min.y += i;
+	}
+	if(bp->r.max.x > bp->sm->clipr.max.x)
+		bp->r.max.x = bp->sm->clipr.max.x;
+	if(bp->r.max.y > bp->sm->clipr.max.y)
+		bp->r.max.y = bp->sm->clipr.max.y;
+}
--- /dev/null
+++ b/os/boot.original/mpc/gnot.h
@@ -1,0 +1,71 @@
+
+extern void	*bbmalloc(int);
+extern void	bbfree(void *, int);
+extern int	bbonstack(void);
+extern void	bbexec(void(*)(void), int, int);
+
+/*
+ * Graphics types
+ */
+
+typedef	struct	GBitmap		GBitmap;
+typedef struct	GFont		GFont;
+typedef struct	GSubfont	GSubfont;
+typedef struct	GCacheinfo	GCacheinfo;
+
+struct	GBitmap
+{
+	ulong	*base;		/* pointer to start of data */
+	long	zero;		/* base+zero=&word containing (0,0) */
+	ulong	width;		/* width in 32 bit words of total data area */
+	int	ldepth;		/* log base 2 of number of bits per pixel */
+	Rectangle r;		/* rectangle in data area, local coords */
+	Rectangle clipr;	/* clipping region */
+	GBitmap	*cache;		/* zero; distinguishes bitmap from layer */
+};
+
+
+/*
+ * GFont etc. are not used in the library, only in devbit.c.
+ * GSubfont is only barely used.
+ */
+struct	GSubfont
+{
+	short	n;		/* number of chars in font */
+	char	height;		/* height of bitmap */
+	char	ascent;		/* top of bitmap to baseline */
+	Fontchar *info;		/* n+1 character descriptors */
+	GBitmap	*bits;		/* where the characters are */
+};
+struct GCacheinfo
+{
+	ulong		xright;	/* right edge of bits */
+	Fontchar;
+};
+
+struct GFont
+{
+	uchar		height;	/* max height of bitmap, interline spacing */
+	char		ascent;	/* top of bitmap to baseline */
+	char		width;	/* widest so far; used in caching only */	
+	char		ldepth;	/* of images */
+	short		id;	/* of font */
+	int		ncache;	/* number of entries in cache */
+	GCacheinfo	*cache;	/* cached characters */
+	GBitmap		*b;	/* cached images */
+};
+
+extern ulong	 *gaddr(GBitmap*, Point);
+extern uchar	 *gbaddr(GBitmap*, Point);
+extern void	 gbitblt(GBitmap*, Point, GBitmap*, Rectangle, Fcode);
+extern void	 gbitbltclip(void*);
+extern void	 gtexture(GBitmap*, Rectangle, GBitmap*, Fcode);
+extern Point	 gsubfstrsize(GSubfont*, char*);
+extern int	 gsubfstrwidth(GSubfont*, char*);
+extern Point	 gsubfstring(GBitmap*, Point, GSubfont*, char*, Fcode);
+extern Point	 gbitbltstring(GBitmap*, Point, GSubfont*, char*, Fcode);
+extern void	 gsegment(GBitmap*, Point, Point, int, Fcode);
+extern void	 gpoint(GBitmap*, Point, int, Fcode);
+extern void	 gflushcpucache(void);
+extern GBitmap*	 gballoc(Rectangle, int);
+extern void	 gbfree(GBitmap*);
--- /dev/null
+++ b/os/boot.original/mpc/i2c.c
@@ -1,0 +1,351 @@
+#include "boot.h"
+
+/*
+ * basic read/write interface to mpc8xx I2C bus (master mode)
+ */
+
+typedef struct I2C I2C;
+
+struct I2C {
+	uchar	i2mod;
+	uchar	rsv12a[3];
+	uchar	i2add;
+	uchar	rsv12b[3];
+	uchar	i2brg;
+	uchar	rsv12c[3];
+	uchar	i2com;
+	uchar	rsv12d[3];
+	uchar	i2cer;
+	uchar	rsv12e[3];
+	uchar	i2cmr;
+};
+
+enum {
+	/* i2c-specific BD flags */
+	RxeOV=		1<<1,	/* overrun */
+	TxS=			1<<10,	/* transmit start condition */
+	TxeNAK=		1<<2,	/* last transmitted byte not acknowledged */
+	TxeUN=		1<<1,	/* underflow */
+	TxeCL=		1<<0,	/* collision */
+	TxERR=		(TxeNAK|TxeUN|TxeCL),
+
+	/* i2cmod */
+	REVD=	1<<5,	/* =1, LSB first */
+	GCD=	1<<4,	/* =1, general call address disabled */
+	FLT=		1<<3,	/* =0, not filtered; =1, filtered */
+	PDIV=	3<<1,	/* predivisor field */
+	EN=		1<<0,	/* enable */
+
+	/* i2com */
+	STR=		1<<7,	/* start transmit */
+	I2CM=	1<<0,	/* master */
+	I2CS=	0<<0,	/* slave */
+
+	/* i2cer */
+	TXE =	1<<4,
+	BSY =	1<<2,
+	TXB =	1<<1,
+	RXB =	1<<0,
+
+	/* port B bits */
+	I2CSDA =	IBIT(27),
+	I2CSCL = IBIT(26),
+
+	Rbit =	1<<0,	/* bit in address byte denoting read */
+
+	/* maximum I2C I/O (can change) */
+	Bufsize =	64,
+	Tbuflen=	Bufsize+4,	/* extra address bytes and alignment */
+	Freq =	100000,
+	I2CTimeout = 250,	/* msec */
+};
+
+/* data cache needn't be flushed if buffers allocated in uncached INTMEM */
+#define	DCFLUSH(a,n)
+
+/*
+ * I2C software structures
+ */
+
+struct Ctlr {
+	Lock;
+	QLock	io;
+	int	init;
+	I2C*	i2c;
+	IOCparam*	sp;
+
+	BD*	rd;
+	BD*	td;
+	int	phase;
+	char*	addr;
+	char*	txbuf;
+	char*	rxbuf;
+};
+typedef struct Ctlr Ctlr;
+
+static	Ctlr	i2ctlr[1];
+extern	int	predawn;
+
+static	void	interrupt(Ureg*, void*);
+
+static void
+enable(void)
+{
+	I2C *i2c;
+
+	i2c = i2ctlr->i2c;
+	i2c->i2cer = ~0;	/* clear events */
+	eieio();
+	i2c->i2mod |= EN;
+	eieio();
+	i2c->i2cmr = TXE|BSY|TXB|RXB;	/* enable all interrupts */
+	eieio();
+}
+
+static void
+disable(void)
+{
+	I2C *i2c;
+
+	i2c = i2ctlr->i2c;
+	i2c->i2cmr = 0;	/* mask all interrupts */
+	i2c->i2mod &= ~EN;
+}
+
+/*
+ * called by the reset routine of any driver using the I2C
+ */
+void
+i2csetup(void)
+{
+	IMM *io;
+	I2C *i2c;
+	IOCparam *sp;
+	Ctlr *ctlr;
+	long f, e, emin;
+	int p, d, dmax;
+
+	ctlr = i2ctlr;
+	if(ctlr->init)
+		return;
+	print("i2c setup...\n");
+	ctlr->init = 1;
+	i2c = KADDR(INTMEM+0x860);
+	ctlr->i2c = i2c;
+	sp = KADDR(INTMEM+0x3c80);
+	ctlr->sp = sp;
+	disable();
+
+	if(ctlr->txbuf == nil){
+		ctlr->txbuf = ialloc(Tbuflen, 2);
+		ctlr->addr = ctlr->txbuf+Bufsize;
+	}
+	if(ctlr->rxbuf == nil)
+		ctlr->rxbuf = ialloc(Bufsize, 2);
+	if(ctlr->rd == nil){
+		ctlr->rd = bdalloc(1);
+		ctlr->rd->addr = PADDR(ctlr->rxbuf);
+		ctlr->rd->length = 0;
+		ctlr->rd->status = BDWrap;
+	}
+	if(ctlr->td == nil){
+		ctlr->td = bdalloc(2);
+		ctlr->td->addr = PADDR(ctlr->txbuf);
+		ctlr->td->length = 0;
+		ctlr->td->status = BDWrap|BDLast;
+	}
+
+	/* select port pins */
+	io = ioplock();
+	io->pbdir |= I2CSDA | I2CSCL;
+	io->pbodr |= I2CSDA | I2CSCL;
+	io->pbpar |= I2CSDA | I2CSCL;
+	iopunlock();
+
+	/* explicitly initialise parameters, because InitRxTx can't be used (see i2c/spi relocation errata) */
+	sp = ctlr->sp;
+	sp->rbase = PADDR(ctlr->rd);
+	sp->tbase = PADDR(ctlr->td);
+	sp->rfcr = 0x18;
+	sp->tfcr = 0x18;
+	sp->mrblr = Bufsize;
+	sp->rstate = 0;
+	sp->rptr = 0;
+	sp->rbptr = sp->rbase;
+	sp->rcnt = 0;
+	sp->tstate = 0;
+	sp->tbptr = sp->tbase;
+	sp->tptr = 0;
+	sp->tcnt = 0;
+	eieio();
+
+	i2c->i2com = I2CM;
+	i2c->i2mod = 0;	/* normal mode */
+	i2c->i2add = 0;
+
+	emin = Freq;
+	dmax = (m->cpuhz/Freq)/2-3;
+	for(d=0; d < dmax; d++){
+		for(p=3; p>=0; p--){
+			f = (m->cpuhz>>(p+2))/(2*(d+3));
+			e = Freq - f;
+			if(e < 0)
+				e = -e;
+			if(e < emin){
+				emin = e;
+				i2c->i2brg = d;
+				i2c->i2mod = (i2c->i2mod&~PDIV)|((3-p)<<1); /* set PDIV */
+			}
+		}
+	}
+	//print("i2brg=%d i2mod=#%2.2ux\n", i2c->i2brg, i2c->i2mod);
+	setvec(VectorCPIC+0x10, interrupt, i2ctlr);
+}
+
+enum {
+	Idling,
+	Done,
+	Busy,
+		Sending,
+		Recving,
+};
+
+static void
+interrupt(Ureg*, void *arg)
+{
+	int events;
+	Ctlr *ctlr;
+	I2C *i2c;
+
+	ctlr = arg;
+	i2c = ctlr->i2c;
+	events = i2c->i2cer;
+	eieio();
+	i2c->i2cer = events;
+	if(events & (BSY|TXE)){
+		//print("I2C#%x\n", events);
+		if(ctlr->phase != Idling){
+			ctlr->phase = Idling;
+		}
+	}else{
+		if(events & TXB){
+			//print("i2c: xmt %d %4.4ux %4.4ux\n", ctlr->phase, ctlr->td->status, ctlr->td[1].status);
+			if(ctlr->phase == Sending){
+				ctlr->phase = Done;
+			}
+		}
+		if(events & RXB){
+			//print("i2c: rcv %d %4.4ux %d\n", ctlr->phase, ctlr->rd->status, ctlr->rd->length);
+			if(ctlr->phase == Recving){
+				ctlr->phase = Done;
+			}
+		}
+	}
+}
+
+static int
+done(void *a)
+{
+	return ((Ctlr*)a)->phase < Busy;
+}
+
+static void
+i2cwait(Ctlr *ctlr)
+{
+	/* TO DO: timeout */
+	while(!done(ctlr)){
+		if(predawn)
+			interrupt(nil, ctlr);
+	}
+}
+
+long
+i2csend(int addr, void *buf, long n)
+{
+	Ctlr *ctlr;
+	int i, p, s;
+
+	ctlr = i2ctlr;
+	if(n > Bufsize)
+		return -1;
+	i = 1;
+	ctlr->txbuf[0] = addr & ~1;
+	if(addr & 1){
+		ctlr->txbuf[1] = addr>>8;
+		i++;
+	}
+	memmove(ctlr->txbuf+i, buf, n);
+	DCFLUSH(ctlr->txbuf, Tbuflen);
+	ctlr->phase = Sending;
+	ctlr->rd->status = BDEmpty|BDWrap|BDInt;
+	ctlr->td->addr = PADDR(ctlr->txbuf);
+	ctlr->td->length = n+i;
+	ctlr->td->status = BDReady|BDWrap|BDLast|BDInt;
+	enable();
+	ctlr->i2c->i2com = STR|I2CM;
+	eieio();
+	i2cwait(ctlr);
+	disable();
+	p = ctlr->phase;
+	s = ctlr->td->status;
+	if(s & BDReady || s & TxERR || p != Done)
+		return -1;
+	return n;
+}
+
+long
+i2crecv(int addr, void *buf, long n)
+{
+	Ctlr *ctlr;
+	int p, s, flag;
+	BD *td;
+	long nr;
+
+	ctlr = i2ctlr;
+	if(n > Bufsize)
+		return -1;
+	ctlr->txbuf[0] = addr|Rbit;
+	if(addr & 1){	/* special select sequence */
+		ctlr->addr[0] = addr &~ 1;
+		ctlr->addr[1] = addr>>8;
+	}
+	DCFLUSH(ctlr->txbuf, Tbuflen);
+	DCFLUSH(ctlr->rxbuf, Bufsize);
+	ctlr->phase = Recving;
+	ctlr->rd->addr = PADDR(ctlr->rxbuf);
+	ctlr->rd->status = BDEmpty|BDWrap|BDInt;
+	flag = 0;
+	td = ctlr->td;
+	td[1].status = 0;
+	if(addr & 1){
+		/* special select sequence */
+		td->addr = PADDR(ctlr->addr);
+		td->length = 2;
+		/* td->status made BDReady below */
+		td++;
+		flag = TxS;
+	}
+	td->addr = PADDR(ctlr->txbuf);
+	td->length = n+1;
+	td->status = BDReady|BDWrap|BDLast | flag;	/* not BDInt: leave that to receive */
+	if(flag)
+		ctlr->td->status = BDReady;
+	enable();
+	ctlr->i2c->i2com = STR|I2CM;
+	eieio();
+	i2cwait(ctlr);
+	disable();
+	p = ctlr->phase;
+	s = ctlr->td->status;
+	if(flag)
+		s |= ctlr->td[1].status;
+	nr = ctlr->rd->length;
+	if(nr > n)
+		nr = n;	/* shouldn't happen */
+	if(s & TxERR || s & BDReady || ctlr->rd->status & BDEmpty)
+		return -1;
+	if(p != Done)
+		return -1;
+	memmove(buf, ctlr->rxbuf, nr);
+	return nr;
+}
--- /dev/null
+++ b/os/boot.original/mpc/initfads.c
@@ -1,0 +1,187 @@
+/*
+ * Called from l.s in EPROM to set up a minimal working environment.
+ * Since there is no DRAM yet, and therefore no stack, no function
+ * calls may be made from sysinit0, and values can't be stored,
+ * except to INTMEM.  Global values are accessed by offset from SB,
+ * which has been set by l.s to point into EPROM.
+ *
+ * This is FADS-specific in CS assignment and access of the FADS BCSR
+ * to discover memory size and speed.
+ */
+
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+#include "archfads.h"
+
+#define	MB	(1024*1024)
+
+enum {
+	UPMSIZE = 64,	/* memory controller instruction RAM */
+	SPEED = 50,	/* maximum memory clock in MHz */
+	SDRAMSIZE = 4*MB,
+
+	/* mcr */
+	WriteRAM = 0<<30,
+	ReadRAM = 1<<30,
+	ExecRAM = 2<<30,
+
+	SelUPMA = 0<<23,
+	SelUPMB = 1<<23,
+
+	Once = 1<<8,
+};
+
+/*
+ * mpc8bug uses the following for 60ns EDO DRAMs 32-50MHz
+ */
+static ulong upma50[UPMSIZE] = {
+	0x8FFFEC24,	0xFFFEC04,	0xCFFEC04,	0xFFEC04,       
+	0xFFEC00,	0x37FFEC47,	0xFFFFFFFF,	0xFFFFFFFF,
+	0x8FFFEC24,	0xFFFEC04,	0x8FFEC04,	0xFFEC0C,
+	0x3FFEC00,	0xFFEC44,	0xFFCC08,	0xCFFCC44,
+	0xFFEC0C,	0x3FFEC00,	0xFFEC44,	0xFFCC00,
+	0x3FFFC847,	0x3FFFEC47,	0xFFFFFFFF,	0xFFFFFFFF,
+	0x8FAFCC24,	0xFAFCC04,	0xCAFCC00,	0x11BFCC47,
+	0xC0FFCC84,	0xFFFFFFFF,	0xFFFFFFFF,	0xFFFFFFFF,
+	0x8FAFCC24,	0xFAFCC04,	0xCAFCC00,	0x3AFCC4C,
+	0xCAFCC00,	0x3AFCC4C,	0xCAFCC00,	0x3AFCC4C,
+	0xCAFCC00,	0x33BFCC4F,	0xFFFFFFFF,	0xFFFFFFFF,
+	0xFFFFFFFF,	0xFFFFFFFF,	0xFFFFFFFF,	0xFFFFFFFF,
+	0xC0FFCC84,	0xFFCC04,	0x7FFCC04,	0x3FFFCC06,
+	0xFFFFCC85,	0xFFFFCC05,	0xFFFFCC05,	0xFFFFFFFF,
+	0xFFFFFFFF,	0xFFFFFFFF,	0xFFFFFFFF,	0xFFFFFFFF,
+	0x33FFCC07,	0xFFFFFFFF,	0xFFFFFFFF,	0xFFFFFFFF,
+};
+
+/*
+ * the FADS manual table 3-7 suggests the following for 60ns EDO DRAMs at 20MHz
+ */
+static ulong upma20[UPMSIZE] = {
+	0x8FFFCC04, 0x08FFCC00, 0x33FFCC47, ~0, ~0, ~0, ~0, ~0,
+	[0x08]	0x8FFFCC04, 0x08FFCC08, 0x08FFCC08, 0x08FFCC08, 0x08FFCC00, 0x3FFFCC47, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0,
+	[0x18]	0x8FEFCC00, 0x39BFCC47, ~0, ~0, ~0, ~0, ~0, ~0,
+	[0x20]	0x8FEFCC00, 0x09AFCC48, 0x09AFCC48, 0x08AFCC48, 0x39BFCC47, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0,
+	[0x30]	0x80FFCC84, 0x17FFCC04, 0xFFFFCC86, 0xFFFFCC05, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0,
+	[0x3C]	0x33FFCC07, ~0, ~0, ~0,
+};
+
+void
+sysinit0(int inrom)
+{
+	ulong *upm, *bcsr;
+	IMM *io;
+	int i, mb;
+
+	io = (IMM*)INTMEM;		/* running before maps, no KADDR */
+
+	/* system interface unit initialisation, FADS manual table 3-2, except as noted */
+	io->siumcr = 0x01012440;
+	io->sypcr = 0xFFFFFF88;
+	io->tbscrk = KEEP_ALIVE_KEY;
+	io->tbscr = 0xC3;	/* time base enabled */
+	io->rtcsck = KEEP_ALIVE_KEY;
+	io->rtcsc = 0xC1;	/* don't FRZ, real-time clock enabled */
+	io->rtcsck = ~KEEP_ALIVE_KEY;
+	io->piscrk = KEEP_ALIVE_KEY;
+	io->piscr = 0x82;
+
+	io->memc[BCSRCS].option = 0xFFFF8110;	/* 32k block, all types access, CS early negate, 1 ws */
+	io->memc[BCSRCS].base = BCSRMEM | 1;	/* base, 32-bit port, no parity, GPCM */
+
+	io->memc[BOOTCS].base = FLASHMEM | 1;
+	io->memc[BOOTCS].option = 0xFF800D54;
+
+	if(!inrom)
+		return;	/* can't initialise DRAM controller from DRAM */
+
+	bcsr = (ulong*)BCSRMEM;
+//	bcsr[1] &= ~DisableDRAM;
+	/* could check DRAM speed here; assume 60ns */
+	switch((bcsr[2]>>23)&3){
+	default:	return;	/* can't happen; for the compiler */
+	case 0:	mb = 4; break;
+	case 1:	mb = 32; break;
+	case 2:	mb = 16; break;
+	case 3:	mb = 8; break;
+	}
+
+	upm = upma50;
+	for(i=0; i<UPMSIZE; i++){
+		io->mdr = upm[i];
+		io->mcr = WriteRAM | SelUPMA | i;
+	}
+	io->mptpr = 0x0400;
+	if(SPEED >= 32)
+		io->mamr = (0x9C<<24) | 0xA21114;	/* 50MHz BRGCLK; FADS manual says 0xC0, mpc8bug sets 0x9C */
+	else if(SPEED >= 20)
+		io->mamr = (0x60<<24) | 0xA21114;	/* 25MHz BRGCLK */
+	else
+		io->mamr = (0x40<<24) | 0xA21114;	/* 16.67MHz BRGCLK */
+	io->memc[DRAM1].option = ~((mb<<20)-1)|0x0800;	/* address mask, SAM=1 */
+	io->memc[DRAM1].base = 0 | 0x81;	/* base at 0, 32-bit port size, no parity, UPMA */
+}
+
+/*
+ * the FADS manual table 3-9's suggestion for MB811171622A-100 32+MHz-50MHz
+ */
+static ulong upmb50[UPMSIZE] = {
+	[0x00]	0x1F07FC04, 0xEEAEFC04, 0x11ADFC04, 0xEFBBBC00, 0x1FF77C47,
+	[0x05]	0x1FF77C34, 0xEFEABC34, 0x1FB57C35,
+	[0x08]	0x1F07FC04, 0xEEAEFC04, 0x10ADFC04, 0xF0AFFC00, 0xF0AFFC00, 0xF1AFFC00, 0xEFBBBC00, 0x1FF77C47, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0,
+	[0x18]	0x1F27FC04, 0xEEAEBC00, 0x01B93C04, 0x1FF77C47, ~0, ~0, ~0, ~0,
+	[0x20]	0x1F07FC04, 0xEEAEBC00, 0x10AD7C00, 0xF0AFFC00, 0xF0AFFC00, 0xE1BBBC04, 0x1FF77C47, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0,
+	[0x30] 	0x1FF5FC84, 0xFFFFFC04, 0xFFFFFC04, 0xFFFFFC04, 0xFFFFFC84, 0xFFFFFC07, ~0, ~0, ~0, ~0, ~0, ~0,
+	[0x3C]	0x7FFFFC07, ~0, ~0, ~0,
+};
+
+/*
+ * the FADS manual table 3-8's suggestion for MB811171622A-100 up to 32MHz
+ */
+static	ulong	upmb32[UPMSIZE] = {
+	[0x00]	0x126CC04, 0xFB98C00, 0x1FF74C45, ~0, ~0,
+	[0x05]	0x1FE77C34, 0xEFAABC34, 0x1FA57C35,
+	[0x08]	0x0026FC04, 0x10ADFC00, 0xF0AFFC00, 0xF1AFFC00, 0xEFBBBC00, 0x1FF77C45, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0,
+	[0x18]	0x0E26BC04, 0x01B93C00, 0x1FF77C45, ~0, ~0, ~0, ~0, ~0,
+	[0x20]	0x0E26BC00, 0x10AD7C00, 0xF0AFFC00, 0xF0AFFC00, 0xE1BBBC04, 0x1FF77C45, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0,
+	[0x30]	0x1FF5FC84, 0xFFFFFC04, 0xFFFFFC84, 0xFFFFFC05, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0,
+	[0x3C]	0x7FFFFC07, ~0, ~0, ~0,
+};
+
+/*
+ * optionally called by archfads.c:/^archinit to initialise access to SDRAM
+ */
+void
+sdraminit(ulong base)
+{
+	ulong *upm;
+	IMM *io;
+	int i;
+
+	io = (IMM*)INTMEM;		/* running before maps, no KADDR */
+	if(SPEED > 32)
+		upm = upmb50;
+	else
+		upm = upmb32;
+	for(i=0; i<UPMSIZE; i++){
+		io->mdr = upm[i];
+		io->mcr = WriteRAM | SelUPMB | i;
+	}
+	io->memc[SDRAM].option = ~(SDRAMSIZE-1)|0x0A00;	/* address mask, SAM=1, G5LS=1 */
+	io->memc[SDRAM].base = base | 0xC1;
+	if(SPEED > 32){
+		io->mbmr = 0xD0802114;	/* 50MHz BRGCLK */
+		io->mar = 0x88;
+	}else{
+		io->mbmr = 0x80802114;	/* 32MHz BRGCLK */
+		io->mar = 0x48;
+	}
+	io->mcr = ExecRAM | SelUPMB | (SDRAM<<13) | Once | 5;	/* run MRS command in locations 5-8 of UPMB */
+	io->mbmr = (io->mbmr & ~0xF) | 8;
+	io->mcr = ExecRAM | SelUPMB | (SDRAM<<13) | Once | 0x30;	/* run refresh sequence */
+	io->mbmr = (io->mbmr & ~0xF) | 4;	/* 4-beat refresh bursts */
+}
--- /dev/null
+++ b/os/boot.original/mpc/initpaq.c
@@ -1,0 +1,101 @@
+/*
+ * Called from l.s in EPROM to set up a minimal working environment.
+ * Since there is no DRAM yet, and therefore no stack, no function
+ * calls may be made from sysinit0, and values can't be stored,
+ * except to INTMEM.  Global values are accessed by offset from SB,
+ * which has been set by l.s to point into EPROM.
+ *
+ * This is PowerPAQ-specific:
+ *	- assumes 8mbytes
+ *	- powerpaq CS assignment
+ */
+
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+#include "archpaq.h"
+
+#define	MB	(1024*1024)
+
+enum {
+	DRAMSIZE = 8*MB,
+	FLASHSIZE = 8*MB,
+
+	UPMSIZE = 64,	/* memory controller instruction RAM */
+	SPEED = 50,	/* maximum memory clock in MHz */
+
+	/* mcr */
+	WriteRAM = 0<<30,
+	ReadRAM = 1<<30,
+	ExecRAM = 2<<30,
+
+	SelUPMA = 0<<23,
+	SelUPMB = 1<<23,
+
+	Once = 1<<8,
+};
+
+/*
+ * mpc8bug uses the following for 60ns EDO DRAMs 32-50MHz
+ */
+static ulong upmb50[UPMSIZE] = {
+	0x8FFFEC24,	0xFFFEC04,	0xCFFEC04,	0xFFEC04,       
+	0xFFEC00,	0x37FFEC47,	0xFFFFFFFF,	0xFFFFFFFF,
+	0x8FFFEC24,	0xFFFEC04,	0x8FFEC04,	0xFFEC0C,
+	0x3FFEC00,	0xFFEC44,	0xFFCC08,	0xCFFCC44,
+	0xFFEC0C,	0x3FFEC00,	0xFFEC44,	0xFFCC00,
+	0x3FFFC847,	0x3FFFEC47,	0xFFFFFFFF,	0xFFFFFFFF,
+	0x8FAFCC24,	0xFAFCC04,	0xCAFCC00,	0x11BFCC47,
+	0xC0FFCC84,	0xFFFFFFFF,	0xFFFFFFFF,	0xFFFFFFFF,
+	0x8FAFCC24,	0xFAFCC04,	0xCAFCC00,	0x3AFCC4C,
+	0xCAFCC00,	0x3AFCC4C,	0xCAFCC00,	0x3AFCC4C,
+	0xCAFCC00,	0x33BFCC4F,	0xFFFFFFFF,	0xFFFFFFFF,
+	0xFFFFFFFF,	0xFFFFFFFF,	0xFFFFFFFF,	0xFFFFFFFF,
+	0xC0FFCC84,	0xFFCC04,	0x7FFCC04,	0x3FFFCC06,
+	0xFFFFCC85,	0xFFFFCC05,	0xFFFFCC05,	0xFFFFFFFF,
+	0xFFFFFFFF,	0xFFFFFFFF,	0xFFFFFFFF,	0xFFFFFFFF,
+	0x33FFCC07,	0xFFFFFFFF,	0xFFFFFFFF,	0xFFFFFFFF,
+};
+
+void
+sysinit0(int inrom)
+{
+	ulong *upm;
+	IMM *io;
+	int i;
+
+	io = (IMM*)INTMEM;		/* running before maps, no KADDR */
+
+	/* system interface unit initialisation, FADS manual table 3-2, except as noted */
+	io->siumcr = 0x01012440;
+	io->sypcr = 0xFFFFFF88;
+	io->tbscrk = KEEP_ALIVE_KEY;
+	io->tbscr = 0xC3;	/* time base enabled */
+	io->rtcsck = KEEP_ALIVE_KEY;
+	io->rtcsc = 0xC1;	/* don't FRZ, real-time clock enabled */
+	io->rtcsck = ~KEEP_ALIVE_KEY;
+	io->piscrk = KEEP_ALIVE_KEY;
+	io->piscr = 0x82;
+
+	io->memc[BOOTCS].base = FLASHMEM | 1;
+	io->memc[BOOTCS].option = ~(FLASHSIZE-1)|(1<<8)|(2<<4);	/* mask, BIH, 2 wait states */
+
+	if(!inrom)
+		return;	/* can't initialise DRAM controller from DRAM */
+
+	/* could check DRAM speed here; assume 60ns */
+	/* could probe DRAM for size here; assume DRAMSIZE */
+	io->mptpr = 0x400;	/* powerpaq flash has 0x1000 */
+	io->mbmr = (0xC0<<24) | 0xA21114;	/* 50MHz BRGCLK */
+	upm = upmb50;
+	for(i=0; i<UPMSIZE; i++){
+		io->mdr = upm[i];
+		io->mcr = WriteRAM | SelUPMB | i;
+	}
+	io->memc[DRAM1].option = ~(DRAMSIZE-1)|0x0800;	/* address mask, SAM=1 */
+	io->memc[DRAM1].base = 0 | 0xC1;	/* base at 0, 32-bit port size, no parity, UPMB */
+}
--- /dev/null
+++ b/os/boot.original/mpc/initrpcg.c
@@ -1,0 +1,91 @@
+
+/*
+ * Called from l.s in EPROM to set up a minimal working environment.
+ * Since there is no DRAM yet, and therefore no stack, no function
+ * calls may be made from sysinit, and values can't be stored,
+ * except to INTMEM.  Global values are accessed by offset from SB,
+ * which has been set by l.s to point into EPROM.
+ */
+
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+#include	"archrpcg.h"
+
+#define	MB	(1024*1024)
+
+enum {
+	UPMSIZE = 64,	/* memory controller instruction RAM */
+	DRAMSIZE = 16*MB,
+	FLASHSIZE = 4*MB,
+
+	WriteRAM = 0<<30,
+	ReadRAM = 1<<30,
+	ExecRAM = 2<<30,
+
+	SelUPMA = 0<<23,
+	SelUPMB = 1<<23,
+};
+/* RPCG values for RPXLite AW */
+static	ulong	upma50[UPMSIZE] = {
+	0xCFFFCC24,	0x0FFFCC04,	0x0CAFCC04,	0x03AFCC08,       
+	0x3FBFCC27,	0xFFFFCC25,	0xFFFFCC25,	0xFFFFCC25,
+	0xCFFFCC24,	0x0FFFCC04,	0x0CAFCC84,	0x03AFCC88,
+	0x3FBFCC27,	0xFFFFCC25,	0xFFFFCC25,	0xFFFFCC25,
+	0xFFFFCC25,	0xFFFFCC25,	0xFFFFCC25,	0xFFFFCC25,
+	0xFFFFCC25,	0xFFFFCC25,	0xFFFFCC25,	0xFFFFCC25,
+	0xCFFFCC24,	0x0FFFCC04,	0x0CFFCC04,	0x03FFCC00,
+	0x3FFFCC27,	0xFFFFCC25,	0xFFFFCC25,	0xFFFFCC25,
+	0xCFFFCC24,	0x0FFFCC04,	0x0CFFCC84,	0x03FFCC84,
+	0x0CFFCC00,	0x33FFCC27,	0xFFFFCC25,	0xFFFFCC25,
+	0xFFFFCC25,	0xFFFFCC25,	0xFFFFCC25,	0xFFFFCC25,
+	0xFFFFCC25,	0xFFFFCC25,	0xFFFFCC25,	0xFFFFCC25,
+	0xC0FFCC24,	0x03FFCC24,	0x0FFFCC24,	0x0FFFCC24,
+	0x3FFFCC27,	0xFFFFCC25,	0xFFFFCC25,	0xFFFFCC25,
+	0xFFFFCC25,	0xFFFFCC25,	0xFFFFCC25,	0xFFFFCC25,
+	0xFFFFCC25,	0xFFFFCC25,	0xFFFFCC25,	0xFFFFCC25,
+};
+
+void
+sysinit0(int inrom)
+{
+	ulong *upm;
+	IMM *io;
+	int i;
+
+	io = (IMM*)INTMEM;		/* running before maps, no KADDR */
+	io->siumcr = 0x01012440;
+	io->sypcr = 0xFFFFFF88;
+	io->tbscrk = KEEP_ALIVE_KEY;
+	io->tbscr = 0xC3;
+	io->rtcsck = KEEP_ALIVE_KEY;
+	io->rtcsc = 0xC1;
+	io->rtcsck = ~KEEP_ALIVE_KEY;
+	io->piscrk = KEEP_ALIVE_KEY;
+	io->piscr = 0x82;
+return;
+	io->memc[BCSRCS].option = 0xFFFF8910;	/* 32k block, all types access, CSNT, CS early negate, burst inhibit, 1 ws */
+	io->memc[BCSRCS].base = BCSRMEM | 1;	/* base, 32-bit port, no parity, GPCM */
+
+	io->memc[BOOTCS].base = FLASHMEM | 0x801; /* base, 16 bit port */
+	io->memc[BOOTCS].option = ~(FLASHSIZE-1)|(1<<8)|(4<<4);	/* mask, BIH, 4 wait states */
+
+	if(1||!inrom)
+		return;	/* can't initialise DRAM controller from DRAM */
+
+	/* TO DO: could check DRAM size and speed now */
+
+	upm = upma50;
+	for(i=0; i<nelem(upma50); i++){
+		io->mdr = upm[i];
+		io->mcr = WriteRAM | SelUPMA | i;
+	}
+	io->mptpr = 0x0800;	/* divide by 8 */
+	io->mamr = (0x58<<24) | 0xA01430;	/* 40MHz BRGCLK */
+	io->memc[DRAM1].option = ~(DRAMSIZE-1)|0x0E00;	/* address mask, SAM=1, G5LA/S=3 */
+	io->memc[DRAM1].base = 0 | 0x81;	/* base at 0, 32-bit port size, no parity, UPMA */
+}
--- /dev/null
+++ b/os/boot.original/mpc/io.h
@@ -1,0 +1,463 @@
+enum
+{
+	/* software interrupt vectors (SIU and CPM) */
+	VectorPIC= 0,	/* level 0 to level 7, assigned by software */
+		CPIClevel=	4,
+	VectorIRQ=	VectorPIC+8,	/* IRQ0 to IRQ7 */
+	VectorCPIC=	VectorIRQ+8,	/* 32 CPM interrupts: 0 (error) to 0x1F (PC15) */
+};
+
+enum
+{
+	BUSUNKNOWN = 0,
+};
+
+/*
+ * Buffer Descriptors and IO Rings
+ */
+
+typedef struct BD BD;
+struct BD {
+	ushort	status;
+	ushort	length;
+	ulong	addr;
+};
+
+BD*	bdalloc(int);
+void	bdfree(BD*, int);
+
+enum {
+	/* Rx BDs, bits common to all protocols */
+	BDEmpty=	1<<15,
+	BDWrap=		1<<13,
+	BDInt=		1<<12,
+	BDLast=		1<<11,
+	BDFirst=		1<<10,
+
+	/* Tx BDs */
+	BDReady=		1<<15,
+	/* BDWrap, BDInt, BDLast */
+};
+
+typedef struct Ring Ring;
+struct Ring {
+	BD*	rdr;				/* receive descriptor ring */
+	void*	rrb;				/* receive ring buffers */
+	int	rdrx;				/* index into rdr */
+	int	nrdre;			/* length of rdr */
+
+	BD*	tdr;				/* transmit descriptor ring */
+	Block**	txb;				/* corresponding transmit ring buffers */
+	int	tdrh;				/* host index into tdr */
+	int	tdri;				/* interface index into tdr */
+	int	ntdre;			/* length of tdr */
+	int	ntq;				/* pending transmit requests */
+};
+
+#define NEXT(x, l)	(((x)+1)%(l))
+#define PREV(x, l)	(((x) == 0) ? (l)-1: (x)-1)
+#define	HOWMANY(x, y)	(((x)+((y)-1))/(y))
+#define ROUNDUP(x, y)	(HOWMANY((x), (y))*(y))
+
+int	ioringinit(Ring*, int, int, int);
+
+/*
+ * CPM
+ */
+enum {
+	/* commands */
+	InitRxTx =	0,
+	InitRx =		1,
+	InitTx =		2,
+	EnterHunt=	3,
+	StopTx=		4,
+	GracefulStopTx = 5,
+	InitIDMA =	5,
+	RestartTx =	6,
+	CloseRxBD =	7,
+	SetGroupAddr = 8,
+	SetTimer =	8,
+	GCITimeout =	9,
+	GCIAbort =	10,
+	StopIDMA =	11,
+	StartDSP = 	12,
+	ArmIDMA =	13,
+	InitDSP =		13,
+	USBCmd =	15,
+
+	/* channel IDs */
+	SCC1ID=	0,
+	USBID=	0,
+	I2CID=	1,
+	IDMA1ID= 1,
+	SCC2ID=	4,
+	SPIID=	5,
+	IDMA2ID= 5,
+	TIMERID=	5,
+	SCC3ID=	8,
+	SMC1ID=	9,
+	DSP1ID=9,
+	SCC4ID=	12,
+	SMC2ID=	13,
+	DSP2ID=	13,
+
+	BaudEnable = 1<<16,
+
+	/* sicr */
+	CLK1 = 4,		/* SCC1,2 */
+	CLK2 = 5,
+	CLK3 = 6,
+	CLK4 = 7,
+	CLK5 = CLK1,	/* SCC3,4 */
+	CLK6 = CLK2,
+	CLK7 = CLK3,
+	CLK8 = CLK4,
+};
+
+void	cpmop(int, int, int);
+#define	ioplock()	(m->iomem)
+#define	iopunlock()
+
+/*
+ * the structures below follow hardware/firmware layouts in the 8xx manuals:
+ * mind the data types, offsets and alignment
+ */
+
+/*
+ * basic IO controller parameters (SMC and SCC)
+ */
+typedef struct IOCparam IOCparam;
+struct IOCparam {
+	ushort	rbase;
+	ushort	tbase;
+	uchar	rfcr;
+	uchar	tfcr;
+	ushort	mrblr;
+	ulong	rstate;
+	ulong	rptr;
+	ushort	rbptr;
+	ushort	rcnt;
+	ulong	rtmp;
+	ulong	tstate;
+	ulong	tptr;
+	ushort	tbptr;
+	ushort	tcnt;
+	ulong	ttmp;
+};
+
+typedef struct SCCparam SCCparam;
+struct SCCparam {
+	IOCparam;
+	ulong	rcrc;
+	ulong	tcrc;
+};
+
+typedef struct SCC SCC;
+struct SCC {
+	ulong	gsmrl;
+	ulong	gsmrh;
+	ushort	psmr;
+	uchar	rsvscc0[2];
+	ushort	todr;
+	ushort	dsr;
+	ushort	scce;
+	uchar	rsvscc1[2];
+	ushort	sccm;
+	uchar	rsvscc3;
+	uchar	sccs;
+	ushort	irmode;
+	ushort	irsip;
+};
+
+typedef struct SMC SMC;
+struct SMC {
+	uchar	pad1[2];
+	ushort	smcmr;
+	uchar	pad2[2];
+	uchar	smce;
+	uchar	pad3[3];
+	uchar	smcm;
+	uchar	pad4[5];
+};
+
+typedef struct SPI SPI;
+struct SPI {
+	ushort	spmode;
+	uchar	res1[4];
+	uchar	spie;
+	uchar	res2[3];
+	uchar	spim;
+	uchar	res3[2];
+	uchar	spcom;
+	uchar	res4[10];
+};
+
+typedef struct USB USB;
+struct USB {	/* 823 only */
+	uchar	usmod;
+	uchar	usadr;
+	uchar	uscom;
+	uchar	rsvu1;
+	ushort	usep[4];
+	uchar	rsvu2[4];
+	ushort	usber;
+	uchar	rsvu3[2];
+	ushort	usbmr;
+	uchar	rsvu4;
+	uchar	usbs;
+	uchar	rsvu5[8];
+};
+
+typedef struct IMM IMM;
+struct IMM {
+	struct {	/* general SIU */
+		ulong	siumcr;
+		ulong	sypcr;
+		uchar	rsv0[0xE-0x8];
+		ushort	swsr;
+		ulong	sipend;
+		ulong	simask;
+		ulong	siel;
+		uchar	sivec;
+		uchar	padv[3];
+		ulong	tesr;
+		uchar	rsv1[0x30-0x24];
+		ulong	sdcr;
+		uchar	rsv2[0x80-0x34];
+	};
+	struct {	/* PCMCIA */
+		struct {
+			ulong	base;
+			ulong	option;
+		} pcmr[8];
+		uchar	rsv3[0xe0-0xc0];
+		ulong	pgcra;
+		ulong	pgcrb;
+		ulong	pscr;
+		uchar	rsv4[0xf0-0xec];
+		ulong	pipr;
+		uchar	rsv5[4];
+		ulong	per;
+		uchar	rsv6[4];
+	};
+	struct {	/* MEMC */
+		struct {
+			ulong	base;
+			ulong	option;
+		} memc[8];
+		uchar	rsv7a[0x24];
+		ulong	mar;
+		ulong	mcr;
+		uchar	rsv7b[4];
+		ulong	mamr;
+		ulong	mbmr;
+		ushort	mstat;
+		ushort	mptpr;
+		ulong	mdr;
+		uchar	rsv7c[0x80];
+	};
+	struct {	/* system integration timers */
+		ushort	tbscr;
+		uchar	rsv8a[2];
+		ulong	tbrefu;
+		ulong	tbrefl;
+		uchar	rsv8b[0x14];
+		ushort	rtcsc;
+		uchar	rsv8c[2];
+		ulong	rtc;
+		ulong	rtsec;
+		ulong	rtcal;
+		uchar	rsv8d[0x10];
+		ushort	piscr;
+		ushort	rsv8e;
+		ulong	pitc;
+		ulong	pitr;
+		uchar	rsv8f[0x34];
+	};
+	struct {	/* 280: clocks and resets */
+		ulong	sccr;
+		ulong	plprcr;
+		ulong	rsr;
+		uchar	rsv9[0x300-0x28c];
+	};
+	struct {	/* 300: system integration timers keys */
+		ulong	tbscrk;
+		ulong	tbrefuk;
+		ulong	tbreflk;
+		ulong	tbk;
+		uchar	rsv10a[0x10];
+		ulong	rtcsck;
+		ulong	rtck;
+		ulong	rtseck;
+		ulong	rtcalk;
+		uchar	rsv10b[0x10];
+		ulong	piscrk;
+		ulong	pitck;
+		uchar	rsv10c[0x38];
+	};
+	struct {	/* 380: clocks and resets keys */
+		ulong	sccrk;
+		ulong	plprcrk;
+		ulong	rsrk;
+		uchar	rsv11[0x800-0x38C];
+	};
+	struct {	/* 800: video controller */
+		ushort	vccr;
+		ushort	pad11a;
+		uchar	vsr;
+		uchar	pad11b;
+		uchar	vcmr;
+		uchar	pad11c;
+		ulong	vbcb;
+		ulong	pad11d;
+		ulong	vfcr0;
+		ulong	vfaa0;
+		ulong	vfba0;
+		ulong	vfcr1;
+		ulong	vfaa1;
+		ulong	vfba1;
+		uchar	rsv11a[0x840-0x828];
+	};
+	struct {	/* 840: LCD */
+		ulong	lccr;
+		ulong	lchcr;
+		ulong	lcvcr;
+		ulong	rsv11b;
+		ulong	lcfaa;
+		ulong	lcfba;
+		uchar	lcsr;
+		uchar	rsv11c[0x860-0x859];
+	};
+	struct {	/* 860: I2C */
+		uchar	i2mod;
+		uchar	rsv12a[3];
+		uchar	i2add;
+		uchar	rsv12b[3];
+		uchar	i2brg;
+		uchar	rsv12c[3];
+		uchar	i2com;
+		uchar	rsv12d[3];
+		uchar	i2cer;
+		uchar	rsv12e[3];
+		uchar	i2cmr;
+		uchar	rsv12[0x900-0x875];
+	};
+	struct {	/* 900: DMA */
+		uchar	rsv13[4];
+		ulong	sdar;
+		uchar	sdsr;
+		uchar	pad1[3];
+		uchar	sdmr;
+		uchar	pad2[3];
+		uchar	idsr1;
+		uchar	pad3[3];
+		uchar	idmr1;
+		uchar	pad4[3];
+		uchar	idsr2;
+		uchar	pad5[3];
+		uchar	idmr2;
+		uchar	pad6[0x930-0x91D];
+	};
+	struct {	/* CPM interrupt control */
+		ushort	civr;
+		uchar	pad7[0x940-0x932];
+		ulong	cicr;
+		ulong	cipr;
+		ulong	cimr;
+		ulong	cisr;
+	};
+	struct {	/* input/output port */
+		ushort	padir;
+		ushort	papar;
+		ushort	paodr;
+		ushort	padat;
+		uchar	pad8[8];
+		ushort	pcdir;
+		ushort	pcpar;
+		ushort	pcso;
+		ushort	pcdat;
+		ushort	pcint;
+		uchar	pad9[6];
+		ushort	pddir;
+		ushort	pdpar;
+		ushort	rsv14a;
+		ushort	pddat;
+		uchar	rsv14[0x980-0x978];
+	};
+	struct {	/* CPM timers */
+		ushort	tgcr;
+		uchar	rsv15a[0x990-0x982];
+		ushort	tmr1;
+		ushort	tmr2;
+		ushort	trr1;
+		ushort	trr2;
+		ushort	tcr1;
+		ushort	tcr2;
+		ushort	tcn1;
+		ushort	tcn2;
+		ushort	tmr3;
+		ushort	tmr4;
+		ushort	trr3;
+		ushort	trr4;
+		ushort	tcr3;
+		ushort	tcr4;
+		ushort	tcn3;
+		ushort	tcn4;
+		ushort	ter1;
+		ushort	ter2;
+		ushort	ter3;
+		ushort	ter4;
+		uchar	rsv15[0x9C0-0x9B8];
+	};
+	struct {	/* CPM */
+		ushort	cpcr;
+		uchar	res0[2];
+		ushort	rccr;
+		uchar	res1;
+		uchar	rmds;
+		uchar	res2a[4];
+		ushort	rctr1;
+		ushort	rctr2;
+		ushort	rctr3;
+		ushort	rctr4;
+		uchar	res2[2];
+		ushort	rter;
+		uchar	res3[2];
+		ushort	rtmr;
+		uchar	rsv16[0x9F0-0x9DC];
+	};
+	union {	/* BRG */
+		struct {
+			ulong	brgc1;
+			ulong	brgc2;
+			ulong	brgc3;
+			ulong	brgc4;
+		};
+		ulong	brgc[4];
+	};
+	uchar	skip0[0xAB2-0xA00];	/* USB, SCC, SMC, SPI: address using cpmdev(CP...)->regs */
+	struct {	/* PIP */
+		ushort	pipc;		/* not 823 */
+		ushort	ptpr;		/* not 823 */
+		ulong	pbdir;
+		ulong	pbpar;
+		uchar	pad10[2];
+		ushort	pbodr;
+		ulong	pbdat;
+		uchar	pad11[0xAE0-0xAC8];
+	};
+	struct {	/* SI */
+		ulong	simode;
+		uchar	sigmr;
+		uchar	pad12;
+		uchar	sistr;
+		uchar	sicmr;
+		uchar	pad13[4];
+		ulong	sicr;
+		ulong	sirp;
+		uchar	pad14[0xB00-0xAF4];
+	};
+	ulong	vcram[64];
+	ushort	siram[256];
+	ushort	lcdmap[256];
+};
--- /dev/null
+++ b/os/boot.original/mpc/ip.h
@@ -1,0 +1,98 @@
+typedef struct Udphdr Udphdr;
+struct Udphdr
+{
+	uchar	d[6];		/* Ethernet destination */
+	uchar	s[6];		/* Ethernet source */
+	uchar	type[2];	/* Ethernet packet type */
+
+	uchar	vihl;		/* Version and header length */
+	uchar	tos;		/* Type of service */
+	uchar	length[2];	/* packet length */
+	uchar	id[2];		/* Identification */
+	uchar	frag[2];	/* Fragment information */
+
+	/* Udp pseudo ip really starts here */
+	uchar	ttl;	
+	uchar	udpproto;	/* Protocol */
+	uchar	udpplen[2];	/* Header plus data length */
+	uchar	udpsrc[4];	/* Ip source */
+	uchar	udpdst[4];	/* Ip destination */
+	uchar	udpsport[2];	/* Source port */
+	uchar	udpdport[2];	/* Destination port */
+	uchar	udplen[2];	/* data length */
+	uchar	udpcksum[2];	/* Checksum */
+};
+
+typedef struct Etherhdr Etherhdr;
+struct Etherhdr
+{
+	uchar	d[6];
+	uchar	s[6];
+	uchar	type[2];
+
+	/* Now we have the ip fields */
+	uchar	vihl;		/* Version and header length */
+	uchar	tos;		/* Type of service */
+	uchar	length[2];	/* packet length */
+	uchar	id[2];		/* Identification */
+	uchar	frag[2];	/* Fragment information */
+	uchar	ttl;		/* Time to live */
+	uchar	proto;		/* Protocol */
+	uchar	cksum[2];	/* Header checksum */
+	uchar	src[4];		/* Ip source */
+	uchar	dst[4];		/* Ip destination */
+};
+
+enum
+{
+	IP_VER		= 0x40,
+	IP_HLEN		= 0x05,			
+ 	UDP_EHSIZE	= 22,
+	UDP_PHDRSIZE	= 12,
+	UDP_HDRSIZE	= 20,
+	ETHER_HDR	= 14,
+	IP_UDPPROTO	= 17,
+	ET_IP		= 0x800,
+	Bcastip		= 0xffffffff,
+	BPportsrc	= 68,
+	BPportdst	= 67,
+	TFTPport	= 69,
+	Timeout		= 5000,	/* milliseconds */
+	Bootrequest 	= 1,
+	Bootreply   	= 2,
+	Tftp_READ	= 1,
+	Tftp_WRITE	= 2,
+	Tftp_DATA	= 3,
+	Tftp_ACK	= 4,
+	Tftp_ERROR	= 5,
+	Segsize		= 512,
+	TFTPSZ		= Segsize+10,
+};
+
+typedef struct Bootp Bootp;
+struct Bootp
+{
+	uchar	op;		/* opcode */
+	uchar	htype;		/* hardware type */
+	uchar	hlen;		/* hardware address len */
+	uchar	hops;		/* hops */
+	uchar	xid[4];		/* a random number */
+	uchar	secs[2];	/* elapsed snce client started booting */
+	uchar	pad[2];
+	uchar	ciaddr[4];	/* client IP address (client tells server) */
+	uchar	yiaddr[4];	/* client IP address (server tells client) */
+	uchar	siaddr[4];	/* server IP address */
+	uchar	giaddr[4];	/* gateway IP address */
+	uchar	chaddr[16];	/* client hardware address */
+	char	sname[64];	/* server host name (optional) */
+	char	file[128];	/* boot file name */
+	char	vend[128];	/* vendor-specific goo */
+};
+
+typedef struct Netaddr Netaddr;
+struct Netaddr
+{
+	ulong	ip;
+	ushort	port;
+	char	ea[Eaddrlen];
+};
--- /dev/null
+++ b/os/boot.original/mpc/l.s
@@ -1,0 +1,370 @@
+#include "mem.h"
+
+/* special instruction definitions */
+#define	BDNE	BC	0,2,
+#define	BDNZ	BC	16,0,
+#define	NOOP	OR	R0,R0,R0
+
+/*
+ * common ppc special purpose registers
+ */
+#define DSISR	18
+#define DAR	19	/* Data Address Register */
+#define DEC	22	/* Decrementer */
+#define SRR0	26	/* Saved Registers (exception) */
+#define SRR1	27
+#define SPRG0	272	/* Supervisor Private Registers */
+#define SPRG1	273
+#define SPRG2	274
+#define SPRG3	275
+#define TBRU	269	/* Time base Upper/Lower (Reading) */
+#define TBRL	268
+#define TBWU	285	/* Time base Upper/Lower (Writing) */
+#define TBWL	284
+#define PVR	287	/* Processor Version */
+
+/*
+ * mpc82x-specific special purpose registers of interest here
+ */
+#define EIE	80
+#define EID	81
+#define NRI	82
+#define IMMR	638
+#define IC_CST	560
+#define IC_ADR	561
+#define IC_DAT	562
+#define DC_CST	568
+#define DC_ADR	569
+#define DC_DAT	570
+#define MI_CTR	784
+#define MI_AP	786
+#define MI_EPN	787
+#define MI_TWC	789
+#define MI_RPN	790
+#define MI_DBCAM	816
+#define MI_DBRAM0	817
+#define MI_DBRAM1	818
+#define MD_CTR	792
+#define M_CASID	793
+#define MD_AP	794
+#define MD_EPN	795
+#define M_TWB	796
+#define MD_TWC	797
+#define MD_RPN	798
+#define	M_TW	799
+#define	MD_DBCAM	824
+#define	MD_DBRAM0	825
+#define	MD_DBRAM1	826
+
+/* as on 603e, apparently mtmsr needs help in some chip revisions */
+#define	WAITMSR	SYNC; ISYNC
+
+/* use of SPRG registers in save/restore */
+#define	SAVER0	SPRG0
+#define	SAVER1	SPRG1
+#define	SAVELR	SPRG2
+#define	SAVECR	SPRG3
+
+#define	UREGSIZE	((8+32)*4)
+#define	UREGSPACE	(UREGSIZE+8)	/* allow for arg to trap, and align */
+
+/*
+ * This code is loaded by the ROM loader at location 0x3000,
+ * or lives in flash memory at 0x2800100.
+ * Move it to high memory so that it can load the kernel at 0x0000.
+ */
+
+#define LOADCODEBASE	0x3000	/* when downloaded in S records */
+#define FLASHCODEBASE	(FLASHMEM+0x100)	/* when in flash */
+
+	TEXT	start(SB), $-4
+	MOVW	MSR, R3
+	MOVW	$(EE|IP|RI), R4
+	ANDN	R4, R3
+	OR	$ME, R3
+	SYNC
+	MOVW	R3, MSR	/* turn off interrupts but enable traps */
+	WAITMSR
+
+/*
+ * reset the caches and disable them for now
+ */
+	MOVW	SPR(IC_CST), R4	/* read and clear */
+	MOVW	$(5<<25), R4
+	MOVW	R4, SPR(IC_CST)	/* unlock all */
+	ISYNC
+	MOVW	$(6<<25), R4
+	MOVW	R4, SPR(IC_CST)	/* invalidate all */
+	ISYNC
+	MOVW	$(2<<25), R4
+	MOVW	R4, SPR(IC_CST)	/* disable i-cache */
+	ISYNC
+
+	SYNC
+	MOVW	SPR(DC_CST), R4	/* read and clear */
+	MOVW	$(10<<24), R4
+	MOVW	R4, SPR(DC_CST)	/* unlock all */
+	ISYNC
+	MOVW	$(12<<24), R4
+	MOVW	R4, SPR(DC_CST)	/* invalidate all */
+	ISYNC
+	MOVW	$(4<<24), R4
+	MOVW	R4, SPR(DC_CST)	/* disable i-cache */
+	ISYNC
+
+	MOVW	$7, R4
+ANDN R4, R4, R4
+	MOVW	R4, SPR(158)		/* cancel `show cycle' for normal instruction execution */
+
+/*
+ * set other system configuration values
+ */
+	MOVW	SPR(IMMR), R5		/* save initial space pointer */
+	MOVW	$INTMEM, R4
+	MOVW	R4, SPR(IMMR)		/* set internal memory base */
+	MOVW	$0xFFFFFF88, R3
+	MOVW	R3, 4(R4)	/* disable watchdog in sypcr */
+	MOVW	$0x01012440, R3
+	MOVW	R3, 0(R4)	/* siumcr */
+
+/*
+ * system initialisation (init and map DRAM)
+ */
+	MOVW	$0, R0
+	MOVW	$setSB(SB), R2
+	MOVW	$(0xF000<<16), R3
+/*MOVW R0, R3*/
+	ANDCC	R5, R3	/* initial space is high? */
+	BEQ	notrom
+	MOVW	$FLASHCODEBASE, R5	/* where $start(SB) actually is now */
+	MOVW	$start(SB), R4	/* logical start address */
+	SUB	R4, R5, R6	/* text relocation value */
+	MOVW	$etext(SB), R7
+	SUB	R4, R7
+	ADD	R5, R7	/* data address in ROM */
+	MOVW	$bdata(SB), R8
+	SUB	R8, R2
+	ADD	R7, R2	/* relocate SB: SB' = romdata+(SB-bdata) */
+	MOVW	$sysinit0(SB), R4
+	ADD	R6, R4	/* relocate sysinit0's address */
+	MOVW	R4, CTR
+	MOVW	$inmem(SB), R4
+	ADD	R6, R4
+	MOVW	R4, LR	/* and the return address */
+	BR	(CTR)	/* call sysinit0 */
+	TEXT	inmem(SB), $-4
+	MOVW	$FLASHCODEBASE, R3
+	BR	cpu0
+notrom:
+	MOVW	$start(SB), R6
+	SUB	R6, R2
+	ADD	$LOADCODEBASE, R2
+	BL	sysinit0(SB)
+	MOVW	$LOADCODEBASE, R3
+
+/*
+ * cpu 0
+ *	relocate bootstrap to our link addresses for text and data
+ *	set new PC
+ */
+cpu0:
+	MOVW	$setSB(SB), R2	/* set correct static base register */
+	MOVW	$start(SB), R4
+	MOVW	$etext(SB), R5
+	SUB	R4, R5
+	CMP	R4, R3	/* already there? */
+	BNE	copytext
+	ADD	R5, R3	/* start of data image */
+	BR	copydata
+
+copytext:
+	ADD	$3, R5
+	SRAW	$2, R5
+	MOVW	R5, CTR
+	SUB	$4, R4
+	SUB	$4, R3
+copyt:			/* copy text */
+	MOVWU	4(R3), R5
+	MOVWU	R5, 4(R4)
+	BDNZ	copyt
+	ADD	$4, R3
+
+copydata:
+	/* copy data */
+	MOVW	$bdata(SB), R4
+	CMP	R4, R3	/* already there? */
+	BEQ	loadkpc
+	MOVW	$edata(SB), R5
+	SUB	R4, R5
+	ADD	$3, R5
+	SRAW	$2, R5
+	MOVW	R5, CTR
+	SUB	$4, R4
+	SUB	$4, R3
+copyd:
+	MOVWU	4(R3), R5
+	MOVWU	R5, 4(R4)
+	BDNZ	copyd
+
+	/* load correct PC */
+loadkpc:
+	MOVW	$start1(SB), R3
+	MOVW	R3, LR
+	BR	(LR)
+TEXT start1(SB), $-4
+	MOVW	$edata(SB), R3
+	MOVW	$end(SB), R4
+	SUBCC	R3, R4
+	BLE	skipz
+	SRAW	$2, R4
+	MOVW	R4, CTR
+	SUB	$4, R3
+	MOVW	$0, R0
+zero:
+	MOVWU	R0, 4(R3)
+	BDNZ	zero
+skipz:
+	MOVW	$mach0(SB), R1
+	MOVW	R1, m(SB)
+	ADD	$(MACHSIZE-8), R1
+	MOVW	$0, R0
+	BL	main(SB)
+	BR	0(PC)
+
+TEXT	getmsr(SB), $0
+	MOVW	MSR, R3
+	RETURN
+
+TEXT	putmsr(SB), $0
+	SYNC
+	MOVW	R3, MSR
+	WAITMSR
+	RETURN
+
+TEXT	eieio(SB), $0
+	EIEIO
+	RETURN
+
+TEXT	idle(SB), $0
+	RETURN
+
+TEXT	spllo(SB), $0
+	MOVW	MSR, R3
+	OR	$EE, R3, R4
+	SYNC
+	MOVW	R4, MSR
+	WAITMSR
+	RETURN
+
+TEXT	splhi(SB), $0
+	MOVW	MSR, R3
+	RLWNM	$0, R3, $~EE, R4
+	SYNC
+	MOVW	R4, MSR
+	WAITMSR
+	RETURN
+
+TEXT	splx(SB), $0
+	MOVW	MSR, R4
+	RLWMI	$0, R3, $EE, R4
+	SYNC
+	MOVW	R4, MSR
+	WAITMSR
+	RETURN
+
+TEXT	gettbl(SB), $0
+/*	MOVW	SPR(TBRL), R3	*/
+	WORD	$0x7c6c42e6	/* mftbl on 8xx series */
+	RETURN
+
+TEXT	getpvr(SB), $0
+	MOVW	SPR(PVR), R3
+	RETURN
+
+TEXT	getimmr(SB), $0
+	MOVW	SPR(IMMR), R3
+	RETURN
+
+TEXT	getdec(SB), $0
+	MOVW	SPR(DEC), R3
+	RETURN
+
+TEXT	putdec(SB), $0
+	MOVW	R3, SPR(DEC)
+	RETURN
+
+/*
+ * save state in Ureg on kernel stack.
+ * enter with R0 giving the PC from the call to `exception' from the vector.
+ * on return, SB (R2) has been set, and R3 has the Ureg*
+ */
+TEXT saveureg(SB), $-4
+	SUB	$UREGSPACE, R1
+	MOVMW	R2, 48(R1)	/* r2:r31 */
+	MOVW	$setSB(SB), R2
+	MOVW	SPR(SAVER1), R4
+	MOVW	R4, 44(R1)
+	MOVW	SPR(SAVER0), R5
+	MOVW	R5, 40(R1)
+	MOVW	CTR, R6
+	MOVW	R6, 36(R1)
+	MOVW	XER, R4
+	MOVW	R4, 32(R1)
+	MOVW	SPR(SAVECR), R5	/* CR */
+	MOVW	R5, 28(R1)
+	MOVW	SPR(SAVELR), R6	/* LR */
+	MOVW	R6, 24(R1)
+	/* pad at 20(R1) */
+	MOVW	SPR(SRR0), R4
+	MOVW	R4, 16(R1)	/* old PC */
+	MOVW	SPR(SRR1), R5
+	MOVW	R5, 12(R1)
+	MOVW	R0, 8(R1)	/* cause/vector, encoded in LR from vector */
+	ADD	$8, R1, R3	/* Ureg* */
+	STWCCC	R3, (R1)	/* break any pending reservations */
+	MOVW	$0, R0	/* R0ISZERO */
+	BR	(LR)
+
+/*
+ * restore state from Ureg
+ * SB (R2) is unusable on return
+ */
+TEXT restoreureg(SB), $-4
+	MOVMW	48(R1), R2	/* r2:r31 */
+	/* defer R1 */
+	MOVW	40(R1), R0
+	MOVW	R0, SPR(SAVER0)
+	MOVW	36(R1), R0
+	MOVW	R0, CTR
+	MOVW	32(R1), R0
+	MOVW	R0, XER
+	MOVW	28(R1), R0
+	MOVW	R0, CR	/* CR */
+	MOVW	24(R1), R0
+	MOVW	R0, SPR(SAVELR)	/* LR */
+	/* pad, skip */
+	MOVW	16(R1), R0
+	MOVW	R0, SPR(SRR0)	/* old PC */
+	MOVW	12(R1), R0
+	MOVW	R0, SPR(SRR1)	/* old MSR */
+	/* cause, skip */
+	MOVW	44(R1), R1	/* old SP */
+	BR	(LR)
+
+TEXT	exception(SB), $-4
+	MOVW	R1, SPR(SAVER1)
+	MOVW	CR, R0
+	MOVW	R0, SPR(SAVECR)
+	MOVW	LR, R0
+	BL	saveureg(SB)
+	MOVW	$0, R0
+	BL	trap(SB)
+	BL	restoreureg(SB)
+	MOVW	SPR(SAVELR), R0
+	MOVW	R0, LR
+	MOVW	SPR(SAVER0), R0
+	ISYNC
+	RFI
+
+GLOBL	mach0+0(SB), $MACHSIZE
+GLOBL	m(SB), $4
--- /dev/null
+++ b/os/boot.original/mpc/lib.h
@@ -1,0 +1,106 @@
+/*
+ * functions (possibly) linked in, complete, from libc.
+ */
+
+/*
+ * mem routines
+ */
+extern	void*	memccpy(void*, void*, int, long);
+extern	void*	memset(void*, int, long);
+extern	int	memcmp(void*, void*, long);
+extern	void*	memmove(void*, void*, long);
+extern	void*	memchr(void*, int, long);
+
+/*
+ * string routines
+ */
+extern	char*	strcat(char*, char*);
+extern	char*	strchr(char*, char);
+extern	int	strcmp(char*, char*);
+extern	char*	strcpy(char*, char*);
+extern	char*	strncat(char*, char*, long);
+extern	char*	strncpy(char*, char*, long);
+extern	int	strncmp(char*, char*, long);
+extern	long	strlen(char*);
+extern	char*	strrchr(char*, char);
+extern	char*	strstr(char*, char*);
+
+/*
+ * print routines
+ * 	Fconv isn't used but is defined to satisfy prototypes in libg.h
+ *	that are never called.
+ */
+typedef	struct Fconv Fconv;
+
+extern	char*	donprint(char*, char*, char*, void*);
+extern	int	sprint(char*, char*, ...);
+extern	int	print(char*, ...);
+
+#define	PRINTSIZE	256
+
+/*
+ * one-of-a-kind
+ */
+extern	int	atoi(char*);
+extern	long	strtol(char*, char**, int);
+extern	ulong	strtoul(char*, char**, int);
+extern	long	end;
+
+/*
+ * Syscall data structures
+ */
+
+#define	MORDER	0x0003	/* mask for bits defining order of mounting */
+#define	MREPL	0x0000	/* mount replaces object */
+#define	MBEFORE	0x0001	/* mount goes before others in union directory */
+#define	MAFTER	0x0002	/* mount goes after others in union directory */
+#define	MCREATE	0x0004	/* permit creation in mounted directory */
+#define	MMASK	0x0007	/* all bits on */
+
+#define	OREAD	0	/* open for read */
+#define	OWRITE	1	/* write */
+#define	ORDWR	2	/* read and write */
+#define	OEXEC	3	/* execute, == read but check execute permission */
+#define	OTRUNC	16	/* or'ed in (except for exec), truncate file first */
+#define	OCEXEC	32	/* or'ed in, close on exec */
+#define	ORCLOSE	64	/* or'ed in, remove on close */
+
+#define	NCONT	0	/* continue after note */
+#define	NDFLT	1	/* terminate after note */
+
+typedef struct Qid	Qid;
+typedef struct Dir	Dir;
+typedef struct Waitmsg	Waitmsg;
+
+#define	ERRLEN	64
+#define	DIRLEN	116
+#define	NAMELEN	28
+
+struct Qid
+{
+	ulong	path;
+	ulong	vers;
+};
+
+struct Dir
+{
+	char	name[NAMELEN];
+	char	uid[NAMELEN];
+	char	gid[NAMELEN];
+	Qid	qid;
+	ulong	mode;
+	long	atime;
+	long	mtime;
+	vlong	length;
+	short	type;
+	short	dev;
+};
+
+struct Waitmsg
+{
+	int	pid;		/* of loved one */
+	int	status;		/* unused; a placeholder */
+	ulong	time[3];	/* of loved one */
+	char	msg[ERRLEN];
+};
+#define	nelem(x)	(sizeof(x)/sizeof((x)[0]))
--- /dev/null
+++ b/os/boot.original/mpc/main.c
@@ -1,0 +1,524 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+#include "dosfs.h"
+
+typedef struct Type Type;
+typedef struct Medium Medium;
+typedef struct Mode Mode;
+
+enum {
+	Dany		= -1,
+	Nmedia		= 16,
+
+	/* DS1 switch options */
+	Sflashfs		= 1<<0,	/* take local fs from flash */
+	Snotflash		= 1<<1,	/* don't boot from flash */
+};
+
+enum {					/* type */
+	Tflash,
+	Tuart,
+	Tether,
+	Thard,
+
+	Tany		= -1,
+};
+
+enum {					/* flag and name */
+	Fnone		= 0x00,
+
+	Fdos		= 0x01,
+	Ndos		= 0x00,
+	Fboot		= 0x02,
+	Nboot		= 0x01,
+	Fbootp		= 0x04,
+	Nbootp		= 0x02,
+	Fflash		= 0x08,
+	Fuart		= 0x10,
+	NName		= 0x03,
+
+	Fany		= Fbootp|Fboot|Fdos|Fflash|Fuart,
+
+	Fini		= 0x10,
+	Fprobe		= 0x80,
+};
+
+enum {					/* mode */
+	Mauto		= 0x00,
+	Mlocal		= 0x01,
+	Manual		= 0x02,
+	NMode		= 0x03,
+};
+
+typedef struct Type {
+	int	type;
+	char	*cname;
+	int	flag;
+	int	(*init)(void);
+	long	(*read)(int, void*, long);
+	long	(*seek)(int, long);
+	Partition* (*setpart)(int, char*);
+	char*	name[NName];
+
+	int	mask;
+	Medium*	media;
+} Type;
+
+typedef struct Medium {
+	Type*	type;
+	int	flag;
+	Partition* partition;
+	Dos;
+
+	Medium*	next;
+} Medium;
+
+typedef struct Mode {
+	char*	name;
+	int	mode;
+} Mode;
+
+static Type types[] = {
+	{	Tflash, "flash",
+		Fflash,
+		flashinit, 0, 0, 0,
+		{ 0, "F", 0, }
+	},
+/*
+	{	Tuart, "uart",
+		Fuart|Fboot,
+		uartinit, uartread, uartseek, setuartpart,
+		{ 0, "u", 0, }
+	},
+*/
+	{	Tether, "ether",
+		Fbootp,
+		etherinit, 0, 0, 0,
+		{ 0, 0, "e", },
+	},
+	{	Thard, "ata",
+		Fini|Fboot|Fdos,
+		0, 0, 0, 0,		/* not used now, will be later with PCMCIA */
+		{ "hd", "h", 0, },
+	},
+	{-1},
+};
+
+static Medium media[Nmedia];
+static Medium *curmedium = media;
+
+static Mode modes[NMode+1] = {
+	[Mauto]		{ "auto",   Mauto,  },
+	[Mlocal]	{ "local",  Mlocal, },
+	[Manual]	{ "manual", Manual, },
+};
+
+static char *inis[] = {
+	"inferno/inferno.ini",
+	"inferno.ini",
+	"plan9/plan9.ini",
+	"plan9.ini",
+	0,
+};
+char **ini;
+int	predawn;
+
+static int
+parse(char *line, int *type, int *flag, int *dev, char *file)
+{
+	Type *tp;
+	char buf[2*NAMELEN], *v[4], *p;
+	int i;
+
+	strcpy(buf, line);
+	switch(getcfields(buf, v, 4, "!")){
+
+	case 3:
+		break;
+
+	case 2:
+		v[2] = "";
+		break;
+
+	default:
+		return 0;
+	}
+
+	*flag = 0;
+	for(tp = types; tp->cname; tp++){
+		for(i = 0; i < NName; i++){
+
+			if(tp->name[i] == 0 || strcmp(v[0], tp->name[i]))
+				continue;
+			*type = tp->type;
+			*flag |= 1<<i;
+
+			if((*dev = strtoul(v[1], &p, 0)) == 0 && p == v[1])
+				return 0;
+		
+			strcpy(file, v[2]);
+		
+			return 1;
+		}
+	}
+
+	return 0;
+
+}
+
+static int
+boot(Medium *mp, int flag, char *file)
+{
+	Dosfile df;
+	char ixdos[128], *p;
+	int r;
+
+	uartsetboot(0);
+	if(flag & Fbootp){
+		sprint(BOOTLINE, "%s!%d", mp->type->name[Nbootp], mp->dev);
+		return bootp(mp->dev, file);
+	}
+
+	if(flag & Fflash){
+		if(mp->flag & Fflash && flashbootable(0))
+			flashboot(mp->dev);
+	}
+
+	if(flag & Fboot){
+
+		if(mp->flag & Fini){
+			(*mp->type->setpart)(mp->dev, "disk");
+			plan9ini(mp, nil);
+		}
+		if(file == 0 || *file == 0)
+			file = mp->partition->name;
+		(*mp->type->setpart)(mp->dev, file);
+		sprint(BOOTLINE, "%s!%d!%s", mp->type->name[Nboot], mp->dev, file);
+		r = plan9boot(mp->dev, mp->seek, mp->read);
+		uartsetboot(0);
+		return r;
+	}
+
+	if(flag & Fdos){
+		if(mp->type->setpart)
+			(*mp->type->setpart)(mp->dev, "disk");
+		if(mp->flag & Fini)
+			plan9ini(mp, nil);
+		if(file == 0 || *file == 0){
+			strcpy(ixdos, *ini);
+			if(p = strrchr(ixdos, '/'))
+				p++;
+			else
+				p = ixdos;
+			strcpy(p, "impc");
+			if(dosstat(mp, ixdos, &df) <= 0)
+				return -1;
+		}
+		else
+			strcpy(ixdos, file);
+		sprint(BOOTLINE, "%s!%d!%s", mp->type->name[Ndos], mp->dev, ixdos);
+		return dosboot(mp, ixdos);
+	}
+
+	return -1;
+}
+
+static Medium*
+allocm(Type *tp)
+{
+	Medium **l;
+
+	if(curmedium >= &media[Nmedia])
+		return 0;
+
+	for(l = &tp->media; *l; l = &(*l)->next)
+		;
+	*l = curmedium++;
+	return *l;
+}
+
+Medium*
+probe(int type, int flag, int dev)
+{
+	Type *tp;
+	int dombr, i, start;
+	Medium *mp;
+	Dosfile df;
+	Partition *pp;
+
+	for(tp = types; tp->cname; tp++){
+		if(type != Tany && type != tp->type || tp->init == 0)
+			continue;
+
+		if(flag != Fnone){
+			for(mp = tp->media; mp; mp = mp->next){
+				if((flag & mp->flag) && (dev == Dany || dev == mp->dev))
+					return mp;
+			}
+		}
+		if((tp->flag & Fprobe) == 0){
+			tp->flag |= Fprobe;
+			tp->mask = (*tp->init)();
+		}
+
+		for(i = 0; tp->mask; i++){
+			if((tp->mask & (1<<i)) == 0)
+				continue;
+			tp->mask &= ~(1<<i);
+
+			if((mp = allocm(tp)) == 0)
+				continue;
+
+			mp->dev = i;
+			mp->flag = tp->flag;
+			mp->seek = tp->seek;
+			mp->read = tp->read;
+			mp->type = tp;
+
+			if(mp->flag & Fboot){
+				if((mp->partition = (*tp->setpart)(i, "boot")) == 0)
+					mp->flag &= ~Fboot;
+				if((mp->flag & (Fflash|Fuart)) == 0)
+					(*tp->setpart)(i, "disk");
+			}
+
+			if(mp->flag & Fdos){
+				start = 0;
+				dombr = 1;
+				if(mp->type->setpart){
+					if(pp = (*mp->type->setpart)(i, "dos")){
+						if(start = pp->start)
+							dombr = 0;
+					}
+					(*tp->setpart)(i, "disk");
+				}
+				if(dosinit(mp, start, dombr) < 0)
+					mp->flag &= ~(Fini|Fdos);
+				else
+					print("dos init failed\n");
+			}
+
+			if(mp->flag & Fini){
+				mp->flag &= ~Fini;
+				for(ini = inis; *ini; ini++){
+					if(dosstat(mp, *ini, &df) <= 0)
+						continue;
+					mp->flag |= Fini;
+					break;
+				}
+			}
+
+			if((flag & mp->flag) && (dev == Dany || dev == i))
+				return mp;
+		}
+	}
+
+	return 0;
+}
+
+void
+main(void)
+{
+	Medium *mp;
+	int dev, flag, i, mode, tried, type, options;
+	char def[2*NAMELEN], file[2*NAMELEN], line[80], *p;
+	Type *tp;
+
+	machinit();
+	archinit();
+	meminit();
+	cpminit();
+	trapinit();
+	consinit();	/* screen and keyboard initially */
+	screeninit();
+	cpuidprint();
+	alarminit();
+	clockinit();
+	predawn = 0;
+	spllo();
+	options = archoptionsw();
+
+	mp = 0;
+	for(tp = types; tp->cname; tp++){
+		if(tp->type == Tether)
+			continue;
+		if((mp = probe(tp->type, Fini, Dany)) && (mp->flag & Fini)){
+			plan9ini(mp, nil);
+			break;
+		}
+	}
+
+	if(mp == 0 || (mp->flag & Fini) == 0)
+		plan9ini(nil, flashconfig(0));
+
+	//consinit();	/* establish new console location */
+
+	if((options & Snotflash) == 0 && flashbootable(0)){
+		print("Flash boot\n");
+		flashboot(0);
+	}
+
+	tried = 0;
+	mode = Mauto;
+	p = getconf("bootfile");
+	flag = 0;
+
+	if(p != 0) {
+		mode = Manual;
+		for(i = 0; i < NMode; i++){
+			if(strcmp(p, modes[i].name) == 0){
+				mode = modes[i].mode;
+				goto done;
+			}
+		}
+		if(parse(p, &type, &flag, &dev, file) == 0) {
+			print("Bad bootfile syntax: %s\n", p);
+			goto done;
+		}
+		mp = probe(type, flag, dev);
+		if(mp == 0) {
+			print("Cannot access device: %s\n", p);
+			goto done;
+		}
+		tried = boot(mp, flag, file);
+	}
+done:
+	if(tried == 0 && mode != Manual){
+		flag = Fany;
+		if(mode == Mlocal)
+			flag &= ~Fbootp;
+		if(options & Snotflash)
+			flag &= ~Fflash;
+		if((mp = probe(Tany, flag, Dany)) != 0)
+			boot(mp, flag & mp->flag, 0);
+	}
+
+	def[0] = 0;
+	probe(Tany, Fnone, Dany);
+
+	flag = 0;
+	for(tp = types; tp->cname; tp++){
+		for(mp = tp->media; mp; mp = mp->next){
+			if(flag == 0){
+				flag = 1;
+				print("Boot devices:");
+			}
+
+			if(mp->flag & Fbootp)
+				print(" %s!%d", mp->type->name[Nbootp], mp->dev);
+			if(mp->flag & Fdos)
+				print(" %s!%d", mp->type->name[Ndos], mp->dev);
+			if(mp->flag & (Fflash|Fuart) || mp->flag & Fboot)
+				print(" %s!%d", mp->type->name[Nboot], mp->dev);
+		}
+	}
+	if(flag)
+		print("\n");
+
+	for(;;){
+		if(getstr("boot from", line, sizeof(line), def) >= 0){
+			if(parse(line, &type, &flag, &dev, file)){
+				if(mp = probe(type, flag, dev))
+					boot(mp, flag, file);
+			}
+		}
+		def[0] = 0;
+	}
+}
+
+void
+machinit(void)
+{
+	memset(m, 0, sizeof(*m));
+	m->delayloop = 20000;
+	m->cpupvr = getpvr();
+	m->iomem = KADDR(INTMEM);
+}
+
+int
+getcfields(char* lp, char** fields, int n, char* sep)
+{
+	int i;
+
+	for(i = 0; lp && *lp && i < n; i++){
+		while(*lp && strchr(sep, *lp) != 0)
+			*lp++ = 0;
+		if(*lp == 0)
+			break;
+		fields[i] = lp;
+		while(*lp && strchr(sep, *lp) == 0){
+			if(*lp == '\\' && *(lp+1) == '\n')
+				*lp++ = ' ';
+			lp++;
+		}
+	}
+
+	return i;
+}
+
+static	Map	memv[512];
+static	RMap	rammap = {"physical memory"};
+
+void
+meminit(void)
+{
+	ulong e;
+
+	mapinit(&rammap, memv, sizeof(memv));
+	e = PADDR(&end);
+	mapfree(&rammap, e, 4*1024*1024-e);	/* fixed 4Mbytes is plenty for bootstrap */
+}
+
+void*
+ialloc(ulong n, int align)
+{
+	ulong a;
+	int s;
+
+	if(align <= 0)
+		align = 4;
+	s = splhi();
+	a = mapalloc(&rammap, 0, n, align);
+	splx(s);
+	if(a == 0)
+		panic("ialloc");
+	return memset(KADDR(a), 0, n);
+}
+
+void*
+malloc(ulong n)
+{
+	ulong *p;
+
+	n = ((n+sizeof(int)-1)&~(sizeof(int)-1))+2*sizeof(int);
+	p = ialloc(n, sizeof(int));
+	*p++ = 0xcafebeef;
+	*p++ = n;
+	return p;
+}
+
+void
+free(void *ap)
+{
+	int s;
+	ulong *p;
+
+	p = ap;
+	if(p){
+		if(*(p -= 2) != 0xcafebeef)
+			panic("free");
+		s = splhi();
+		mapfree(&rammap, (ulong)p, p[1]);
+		splx(s);
+	}
+}
+
+void
+sched(void)
+{
+}
--- /dev/null
+++ b/os/boot.original/mpc/mem.h
@@ -1,0 +1,95 @@
+/*
+ * Memory and machine-specific definitions.  Used in C and assembler.
+ */
+
+/*
+ * Sizes
+ */
+#define	BI2BY		8			/* bits per byte */
+#define BI2WD		32			/* bits per word */
+#define	BY2WD		4			/* bytes per word */
+#define	BY2PG		4096			/* bytes per page */
+#define	WD2PG		(BY2PG/BY2WD)		/* words per page */
+#define	PGSHIFT		12			/* log(BY2PG) */
+#define PGROUND(s)	(((s)+(BY2PG-1))&~(BY2PG-1))
+
+#define	MAXMACH		1			/* max # cpus system can run */
+#define	CACHELINELOG	4
+#define CACHELINESZ	(1<<CACHELINELOG)
+
+/*
+ * Time
+ */
+#define	HZ		(50)				/* clock frequency */
+#define	MS2HZ		(1000/HZ)			/* millisec per clock tick */
+#define	TK2SEC(t)	((t)/HZ)			/* ticks to seconds */
+#define	TK2MS(t)	((((ulong)(t))*1000)/HZ)	/* ticks to milliseconds */
+#define	MS2TK(t)	((((ulong)(t))*HZ)/1000)	/* milliseconds to ticks */
+#define	MHz	1000000
+
+/*
+ * Fundamental values
+ */
+
+#define	KZERO	0	/* bootstrap runs in real mode */
+#define	MACHSIZE	4096
+
+/*
+ *  physical MMU
+ */
+#define KSEG0	0x20000000
+#define	KSEGM	0xE0000000	/* mask to check which seg */
+
+/*
+ * MSR bits
+ */
+
+#define	POW	0x40000	/* enable power mgmt */
+#define	TGPR	0x20000	/* GPR0-3 remapped; 603/603e specific */
+#define	ILE	0x10000	/* interrupts little endian */
+#define	EE	0x08000	/* enable external/decrementer interrupts */
+#define	PR	0x04000	/* =1, user mode */
+#define	FPE	0x02000	/* enable floating point */
+#define	ME	0x01000	/* enable machine check exceptions */
+#define	FE0	0x00800
+#define	SE	0x00400	/* single-step trace */
+#define	BE	0x00200	/* branch trace */
+#define	FE1	0x00100
+#define	IP	0x00040	/* =0, vector to nnnnn; =1, vector to FFFnnnnn */
+#define	IR	0x00020	/* enable instruction address translation */
+#define	DR	0x00010	/* enable data address translation */
+#define	RI	0x00002	/* exception is recoverable */
+#define	LE	0x00001	/* little endian mode */
+
+#define	KMSR	(ME|FE0|FE1|FPE)
+#define	UMSR	(KMSR|PR|EE|IR|DR)
+
+/*
+ * MPC82x addresses; mpc8bug is happy with these
+ */
+#define	BCSRMEM	0x02100000
+#define	INTMEM	0x02200000
+#define	FLASHMEM	0x02800000
+#define	SDRAMMEM	0x03000000
+
+#define	DPRAM	(INTMEM+0x2000)
+#define	DPLEN1	0x400
+#define	DPLEN2	0x200
+#define	DPLEN3	0x100
+#define	DPBASE	(DPRAM+DPLEN1)
+
+#define	SCC1P	(INTMEM+0x3C00)
+#define	I2CP	(INTMEM+0x3C80)
+#define	MISCP	(INTMEM+0x3CB0)
+#define	IDMA1P	(INTMEM+0x3CC0)
+#define	SCC2P	(INTMEM+0x3D00)
+#define	SCC3P	(INTMEM+0x3E00)
+#define	SCC4P	(INTMEM+0x3F00)
+#define	SPIP	(INTMEM+0x3D80)
+#define	TIMERP	(INTMEM+0x3DB0)
+#define	SMC1P	(INTMEM+0x3E80)
+#define	DSP1P	(INTMEM+0x3EC0)
+#define	SMC2P	(INTMEM+0x3F80)
+#define	DSP2P	(INTMEM+0x3FC0)
+
+#define KEEP_ALIVE_KEY 0x55ccaa33	/* clock and rtc register key */
--- /dev/null
+++ b/os/boot.original/mpc/mkfile
@@ -1,0 +1,116 @@
+objtype=power
+OBJTYPE=power	# always
+<../../../mkconfig
+SYSTARG=$OSTARG	# always
+<$ROOT/mkfiles/mkfile-$SYSTARG-$OBJTYPE
+INSTALLDIR=$ROOT/Inferno/$OBJTYPE/bin	#path of directory where kernel is installed
+ARCH=fads	# selects board dependent code
+TARG=qb$ARCH
+OFILES=\
+	l.$O\
+	arch$ARCH.$O\
+	devuart.$O\
+	uartboot.$O\
+	alarm.$O\
+	bootp.$O\
+	clock.$O\
+	conf.$O\
+	console.$O\
+	cpm.$O\
+	defont0.$O\
+	donprint.$O\
+	dosboot.$O\
+	devether.$O\
+	etherscc.$O\
+	fblt.$O\
+	gbitbltclip.$O\
+	flash.$O\
+	main.$O\
+	plan9boot.$O\
+	qio.$O\
+	rmap.$O\
+	screen.$O\
+	init$ARCH.$O\
+	trap.$O\
+	zqs.$O\
+
+HFILES=\
+	boot.h\
+	dat.h\
+	fns.h\
+	io.h\
+	lib.h\
+	mem.h\
+	squeeze.h\
+	gnot.h\
+	arch$ARCH.h\
+
+LIBS=\
+	kern\
+
+LIBDIRS=$LIBS
+LIBNAMES=${LIBS:%=lib%.a}
+LIBFILES=${LIBS:%=$ROOT/$TARGMODEL/$OBJTYPE/lib/lib%.a}
+
+#all:NV:	$TARG k.mx f.mx
+all:NV:	$TARG
+install:V: 	$INSTALLDIR/$TARG
+installall:V: 	$INSTALLDIR/$TARG
+
+$INSTALLDIR/%: %
+	rm -f $INSTALLDIR/$stem && cp $stem $INSTALLDIR/$stem
+
+$TARG: $OFILES $LIBNAMES
+	$LD -o $target -l  -T0x140000 -R4 $OFILES $LIBFILES
+	ls -l $target
+
+qbrom$ARCH:	$OFILES $LIBNAMES
+	$LD -o $target -l -T0x02800100 -R0 -D0x140000 $OFILES $LIBFILES
+
+k.mx:	$TARG
+	ms2 -S 0x100 -a 0x100 -p 4 $TARG >k.mx
+
+f.mx:	qbrom$ARCH
+	ms2 -S 0x100 -a 0x2800100 -p 4 $prereq >f.mx
+
+%.$O:	%.s
+	$AS $stem.s
+
+%.$O:	%.c
+	$CC $CFLAGS $stem.c
+
+%.$O:	$HFILES
+
+lib%.a:V:	$SHELLTYPE-lib%.a
+
+rc-lib%.a nt-lib%.a:VQ:
+	echo '@{builtin cd ' $ROOT/lib$stem ';mk SHELLTYPE=$SHELLTYPE SYSTARG=$SYSTARG OBJTYPE=$OBJTYPE install}'
+	@{builtin cd  $ROOT/lib$stem ;mk 'SHELLTYPE='$SHELLTYPE 'SYSTARG='$SYSTARG 'OBJTYPE='$OBJTYPE install}
+
+sh-lib%.a:VQ:
+	echo "(cd $ROOT/lib$stem ; mk SHELLTYPE=$SHELLTYPE SYSTARG=$SYSTARG OBJTYPE=$OBJTYPE install)"
+	(cd $ROOT/lib$stem ; mk SHELLTYPE=$SHELLTYPE SYSTARG=$SYSTARG OBJTYPE=$OBJTYPE install)
+
+clock.$O floppy.$O trap.$O:	ureg.h
+conf.$O dosboot.$O main.$O:	dosfs.h
+ether.$O etherscc.$O:	etherif.h
+bootp.$O:	ip.h
+
+clean:V:
+	rm -f *.[$OS] [$OS].out y.tab.? y.debug y.output $TARG qboot k.mx f.mx romboot
+
+nuke-sh:QV:
+		for i in $LIBDIRS
+		do
+			echo "(cd $ROOT/lib$i ; mk SHELLTYPE=$SHELLTYPE SYSTARG=$SYSTARG OBJTYPE=$OBJTYPE nuke)"
+			(cd $ROOT/lib$i; mk 'SHELLTYPE='$SHELLTYPE 'SYSTARG='$SYSTARG 'OBJTYPE='$OBJTYPE nuke)
+		done
+
+nuke-rc nuke-nt:QV:
+		for (i in $LIBDIRS)
+		{
+			echo '@{cd $ROOT/lib$i ; mk SHELLTYPE=$SHELLTYPE SYSTARG=$SYSTARG OBJTYPE=$OBJTYPE nuke}'
+			@{cd $ROOT/lib$i; mk 'SHELLTYPE='$SHELLTYPE 'SYSTARG='$SYSTARG 'OBJTYPE='$OBJTYPE nuke}
+		}
+
+nuke:V:		clean nuke-$SHELLTYPE
--- /dev/null
+++ b/os/boot.original/mpc/ms2.c
@@ -1,0 +1,179 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+#include <mach.h>
+
+void	record(uchar*, int);
+void	usage(void);
+void	dosegment(long, int);
+void trailer(ulong);
+
+enum
+{
+	Recordsize = 32,
+};
+
+int	dsegonly;
+int	supressend;
+int	binary;
+int	addr4;
+ulong	addr;
+ulong 	psize = 4096;
+ulong	startaddr = 0x030000;
+Biobuf 	stdout;
+Biobuf	bio;
+
+void
+main(int argc, char **argv)
+{
+	Dir dir;
+	Fhdr f;
+	int fd;
+
+	ARGBEGIN{
+	case 'd':
+		dsegonly++;
+		break;
+	case 's':
+		supressend++;
+		break;
+	case 'a':
+		addr = strtoul(ARGF(), 0, 0);
+		break;
+	case 'p':
+		psize = strtoul(ARGF(), 0, 0);
+		break;
+	case 'b':
+		binary++;
+		break;
+	case 'S':
+		startaddr = strtoul(ARGF(), 0, 0);
+		break;
+	case '4':
+		addr4++;
+		break;
+	default:
+		usage();
+	}ARGEND
+
+	if(argc != 1)
+		usage();
+
+	Binit(&stdout, 1, OWRITE);
+
+	fd = open(argv[0], OREAD);
+	if(fd < 0) {
+		fprint(2, "ms2: open %s: %r\n", argv[0]);
+		exits("open");
+	}
+
+	if(binary) {
+		if(dirfstat(fd, &dir) < 0) {
+			fprint(2, "ms2: stat failed %r");
+			exits("dirfstat");
+		}
+		Binit(&bio, fd, OREAD);
+		dosegment(0, dir.length);
+		if(supressend == 0)
+			trailer(startaddr);
+		Bterm(&stdout);
+		Bterm(&bio);
+		exits(0);
+	}
+
+	if(crackhdr(fd, &f) == 0){
+		fprint(2, "ms2: bad magic: %r\n");
+		exits("magic");
+	}
+	seek(fd, 0, 0);
+
+	Binit(&bio, fd, OREAD);
+
+	if(dsegonly)
+		dosegment(f.datoff, f.datsz);
+	else {
+		dosegment(f.txtoff, f.txtsz);
+		addr = (addr+(psize-1))&~(psize-1);
+		dosegment(f.datoff, f.datsz);
+	}
+
+	if(supressend == 0)
+		trailer(startaddr);
+
+	Bterm(&stdout);
+	Bterm(&bio);
+	exits(0);
+}
+
+void
+dosegment(long foff, int len)
+{
+	int l, n;
+	uchar buf[2*Recordsize];
+
+	Bseek(&bio, foff, 0);
+	for(;;) {
+		l = len;
+		if(l > Recordsize)
+			l = Recordsize;
+		n = Bread(&bio, buf, l);
+		if(n == 0)
+			break;
+		if(n < 0) {
+			fprint(2, "ms2: read error: %r\n");
+			exits("read");
+		}
+		record(buf, l);
+		len -= l;
+	}
+}
+
+void
+record(uchar *s, int l)
+{
+	int i;
+	ulong cksum;
+
+	if(addr4 || addr & (0xFF<<24)){
+		Bprint(&stdout, "S3%.2X%.8luX", l+5, addr);
+		cksum = l+5;
+		cksum += (addr>>24)&0xff;
+	}else{
+		Bprint(&stdout, "S2%.2X%.6X", l+4, addr);
+		cksum = l+4;
+	}
+	cksum += addr&0xff;
+	cksum += (addr>>8)&0xff;
+	cksum += (addr>>16)&0xff;
+
+	for(i = 0; i < l; i++) {
+		cksum += *s;
+		Bprint(&stdout, "%.2X", *s++);
+	}
+	Bprint(&stdout, "%.2X\n", (~cksum)&0xff);
+	addr += l;
+}
+
+void
+trailer(ulong a)
+{
+	ulong cksum;
+
+	cksum = 0;
+	if(addr4 || a & (0xFF<<24)){
+		Bprint(&stdout, "S7%.8luX", a);
+		cksum += (a>>24)&0xff;
+	}else
+		Bprint(&stdout, "S9%.6X", a);
+	cksum += a&0xff;
+	cksum += (a>>8)&0xff;
+	cksum += (a>>16)&0xff;
+	Bprint(&stdout, "%.2X\n", (~cksum)&0xff);
+}
+
+void
+usage(void)
+{
+	fprint(2, "usage: ms2 [-ds] [-a address] [-p pagesize] ?.out\n");
+	exits("usage");
+}
--- /dev/null
+++ b/os/boot.original/mpc/plan9boot.c
@@ -1,0 +1,96 @@
+#include	"u.h"
+#include	"lib.h"
+#include	"mem.h"
+#include	"dat.h"
+#include	"fns.h"
+
+char *premature = "premature EOF\n";
+
+/*
+ *  read in a segment
+ */
+static long
+readseg(int dev, long (*read)(int, void*, long), long len, long addr)
+{
+	char *a;
+	long n, sofar;
+
+	a = (char *)addr;
+	for(sofar = 0; sofar < len; sofar += n){
+		n = 8*1024;
+		if(len - sofar < n)
+			n = len - sofar;
+		n = (*read)(dev, a + sofar, n);
+		if(n <= 0)
+			break;
+		print(".");
+	}
+	return sofar;
+}
+
+/*
+ *  boot
+ */
+int
+plan9boot(int dev, long (*seek)(int, long), long (*read)(int, void*, long))
+{
+	long n;
+	long addr;
+	void (*b)(void);
+	Exec *ep;
+
+	if((*seek)(dev, 0) < 0)
+		return -1;
+
+	/*
+	 *  read header
+	 */
+	ep = (Exec *) ialloc(sizeof(Exec), 0);
+	n = sizeof(Exec);
+	if(readseg(dev, read, n, (long) ep) != n){
+		print(premature);
+		return -1;
+	}
+	if(GLLONG(ep->magic) != Q_MAGIC){
+		print("bad magic 0x%lux not a plan 9 executable!\n", GLLONG(ep->magic));
+		return -1;
+	}
+
+	/*
+	 *  read text
+	 */
+	addr = PADDR(GLLONG(ep->entry));
+	n = GLLONG(ep->text);
+	print("%d", n);
+	if(readseg(dev, read, n, addr) != n){
+		print(premature);
+		return -1;
+	}
+
+	/*
+	 *  read data (starts at first page after kernel)
+	 */
+	addr = PGROUND(addr+n);
+	n = GLLONG(ep->data);
+	print("+%d@%8.8lux", n, addr);
+	if(readseg(dev, read, n, addr) != n){
+		print(premature);
+		return -1;
+	}
+
+	/*
+	 *  bss and entry point
+	 */
+	print("+%d\nstart at 0x%lux\n", GLLONG(ep->bss), GLLONG(ep->entry));
+	uartwait();
+	scc2stop();
+	splhi();
+
+	/*
+	 *  Go to new code. It's up to the program to get its PC relocated to
+	 *  the right place.
+	 */
+	b = (void (*)(void))(PADDR(GLLONG(ep->entry)));
+	(*b)();
+	return 0;
+}
--- /dev/null
+++ b/os/boot.original/mpc/qio.c
@@ -1,0 +1,128 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+struct Queue {
+	Block*	first;
+	Block*	last;
+	void	(*kick)(void*);
+	void*	arg;
+	long	len;
+};
+
+Block *
+iallocb(int n)
+{
+	Block *b;
+
+	b = (Block*)malloc(sizeof(Block)+n);
+	b->data = (uchar*)b + sizeof(Block);
+	b->rp = b->wp = b->data;
+	b->lim = b->data + n;
+	b->next = 0;
+	b->magic = 0xcafebee0;
+	return b;
+}
+
+void
+freeb(Block *b)
+{
+	if(b){
+		if(b->magic != 0xcafebee0)
+			panic("freeb");
+		b->magic = 0;
+		b->next = (Block*)0xdeadbabe;
+		free(b);
+	}
+}
+
+Queue *
+qopen(int limit, int msg, void (*kick)(void*), void *arg)
+{
+	Queue *q;
+
+	USED(limit, msg);
+	q = (Queue*)malloc(sizeof(Queue));
+	q->first = q->last = 0;
+	q->kick = kick;
+	q->arg = arg;
+	q->len = 0;
+	return q;
+}
+
+Block *
+qget(Queue *q)
+{
+	int s;
+	Block *b;
+
+	s = splhi();
+	if((b = q->first) != 0){
+		q->first = b->next;
+		b->next = 0;
+		q->len -= BLEN(b);
+		if(q->len < 0)
+			panic("qget");
+	}
+	splx(s);
+	return b;
+}
+
+void
+qbwrite(Queue *q, Block *b)
+{
+	int s;
+
+	s = splhi();
+	b->next = 0;
+	if(q->first == 0)
+		q->first = b;
+	else
+		q->last->next = b;
+	q->last = b;
+	q->len += BLEN(b);
+	splx(s);
+	if(q->kick)
+		q->kick(q->arg);
+}
+
+long
+qlen(Queue *q)
+{
+	return q->len;
+}
+
+int
+qbgetc(Queue *q)
+{
+	Block *b;
+	int s, c;
+
+	c = -1;
+	s = splhi();
+	while(c < 0 && (b = q->first) != nil){
+		if(b->rp < b->wp){
+			c = *b->rp++;
+			q->len--;
+		}
+		if(b->rp >= b->wp){
+			q->first = b->next;
+			b->next = nil;
+		}
+	}
+	splx(s);
+	return c;
+}
+
+void
+qbputc(Queue *q, int c)
+{
+	Block *b;
+
+	b = iallocb(1);
+	*b->wp++ = c;
+	qbwrite(q, b);
+}
--- /dev/null
+++ b/os/boot.original/mpc/rmap.c
@@ -1,0 +1,104 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+
+void
+mapinit(RMap *rmap, Map *map, int size)
+{
+	lock(rmap);
+	rmap->map = map;
+	rmap->mapend = map+(size/sizeof(Map));
+	unlock(rmap);
+}
+
+void
+mapfree(RMap* rmap, ulong addr, int size)
+{
+	Map *mp;
+	ulong t;
+
+	if(size <= 0)
+		return;
+
+	lock(rmap);
+	for(mp = rmap->map; mp->addr <= addr && mp->size; mp++)
+		;
+
+	if(mp > rmap->map && (mp-1)->addr+(mp-1)->size == addr){
+		(mp-1)->size += size;
+		if(addr+size == mp->addr){
+			(mp-1)->size += mp->size;
+			while(mp->size){
+				mp++;
+				(mp-1)->addr = mp->addr;
+				(mp-1)->size = mp->size;
+			}
+		}
+	}
+	else{
+		if(addr+size == mp->addr && mp->size){
+			mp->addr -= size;
+			mp->size += size;
+		}
+		else do{
+			if(mp >= rmap->mapend){
+				print("mapfree: %s: losing 0x%uX, %d\n",
+					rmap->name, addr, size);
+				break;
+			}
+			t = mp->addr;
+			mp->addr = addr;
+			addr = t;
+			t = mp->size;
+			mp->size = size;
+			mp++;
+		}while(size = t);
+	}
+	unlock(rmap);
+}
+
+ulong
+mapalloc(RMap* rmap, ulong addr, int size, int align)
+{
+	Map *mp;
+	ulong maddr, oaddr;
+
+	lock(rmap);
+	for(mp = rmap->map; mp->size; mp++){
+		maddr = mp->addr;
+
+		if(addr){
+			if(maddr > addr)
+				continue;
+			if(addr+size > maddr+mp->size)
+				break;
+			maddr = addr;
+		}
+
+		if(align > 0)
+			maddr = ((maddr+align-1)/align)*align;
+		if(mp->addr+mp->size-maddr < size)
+			continue;
+
+		oaddr = mp->addr;
+		mp->addr = maddr+size;
+		mp->size -= maddr-oaddr+size;
+		if(mp->size == 0){
+			do{
+				mp++;
+				(mp-1)->addr = mp->addr;
+			}while((mp-1)->size = mp->size);
+		}
+
+		unlock(rmap);
+		if(oaddr != maddr)
+			mapfree(rmap, oaddr, maddr-oaddr);
+
+		return maddr;
+	}
+	unlock(rmap);
+
+	return 0;
+}
--- /dev/null
+++ b/os/boot.original/mpc/screen.c
@@ -1,0 +1,242 @@
+#include	"all.h"
+#include	<libg.h>
+#include	<gnot.h>
+
+enum {
+	Colldepth		= 3,
+	Colmaxx		= 640,
+	Colmaxxvis	= 640,
+	Colmaxy		= 480,
+};
+
+#define	MINX	8
+
+extern	GSubfont	defont0;
+
+struct{
+	Point	pos;
+	int	bwid;
+}out;
+
+typedef struct Mode Mode;
+struct Mode {
+	int	x;
+	int	y;
+	int	d;
+	char*	aperture;
+	int	apsize;
+};
+
+GBitmap	gscreen;
+Point	gchar(GBitmap*, Point, GFont*, int, Fcode);
+int	setcolor(ulong, ulong, ulong, ulong);
+static	void	lcdinit(Mode*);
+
+void
+screeninit(void)
+{
+	Mode m;
+
+	m.x = Colmaxx;
+	m.y = Colmaxy;
+	m.d = Colldepth;
+	m.aperture = 0;
+	lcdinit(&m);
+	if(m.aperture == 0)
+		return;
+	gscreen.ldepth = 3;
+	gscreen.base = (ulong*)m.aperture;
+	gscreen.width = Colmaxx/BY2WD;
+	gscreen.r = Rect(0, 0, Colmaxxvis, Colmaxy);
+	gscreen.clipr = gscreen.r;
+	/*
+	 * For now, just use a fixed colormap:
+	 * 0 == white and 255 == black
+	 */
+	setcolor(0, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF);
+	setcolor(255, 0x00000000, 0x00000000, 0x00000000);
+
+	gbitblt(&gscreen, Pt(0, 0), &gscreen, gscreen.r, Zero);
+	out.pos.x = MINX;
+	out.pos.y = 0;
+	out.bwid = defont0.info[' '].width;
+}
+
+void
+screenputc(int c)
+{
+	Fontchar *i;
+	Point p;
+
+	if(gscreen.base == nil)
+		return;
+	switch(c){
+	case '\n':
+		out.pos.x = MINX;
+		out.pos.y += defont0.height;
+		if(out.pos.y > gscreen.r.max.y-defont0.height)
+			out.pos.y = gscreen.r.min.y;
+		gbitblt(&gscreen, Pt(0, out.pos.y), &gscreen,
+		  Rect(0, out.pos.y, gscreen.r.max.x, out.pos.y+2*defont0.height),
+		  Zero);
+		break;
+	case '\t':
+		out.pos.x += (8-((out.pos.x-MINX)/out.bwid&7))*out.bwid;
+		if(out.pos.x >= gscreen.r.max.x)
+			screenputc('\n');
+		break;
+	case '\b':
+		if(out.pos.x >= out.bwid+MINX){
+			out.pos.x -= out.bwid;
+			screenputc(' ');
+			out.pos.x -= out.bwid;
+		}
+		break;
+	default:
+		if(out.pos.x >= gscreen.r.max.x-out.bwid)
+			screenputc('\n');
+		c &= 0x7f;
+		if(c <= 0 || c >= defont0.n)
+			break;
+		i = defont0.info + c;
+		p = out.pos;
+		gbitblt(&gscreen, Pt(p.x+i->left, p.y), defont0.bits,
+			Rect(i[0].x, 0, i[1].x, defont0.height),
+			S);
+		out.pos.x = p.x + i->width;
+		break;
+	}
+}
+
+void
+screenputs(char *s, int n)
+{
+	while(n-- > 0)
+		screenputc(*s++);
+}
+
+/*
+ * See section 5.2.1 (page 5-6) of the MPC823 manual
+ */
+static uchar lcdclock[17] = {	/* (a<<2)|b => divisor of (1<<a)*((b<<1)+1) */
+	0, 0, (1<<2), 1,
+	(2<<2), 2, (1<<2)|1, 3,
+	(3<<2), (1<<2)|2, (1<<2)|2, (2<<2)|1,
+	(2<<2)|1, (1<<2)|3, (1<<2)|3, (4<<2),
+	(4<<2)
+};
+	
+/*
+ * support for the Sharp LQ64D341 TFT colour display
+ */
+
+enum {
+	COLS = 640,
+	ROWS = 480,
+	LDEPTH = 3,	/* screen depth */
+	LCDFREQ = 25000000,
+
+	/* lccr */
+	ClockLow = 1<<11,
+	OELow = 1<<10,
+	HsyncLow = 1<<9,
+	VsyncLow = 1<<8,
+	DataLow = 1<<7,
+	Passive8 = 1<<4,
+	DualScan = 1<<3,
+	IsColour = 1<<2,
+	IsTFT = 1<<1,
+	Enable = 1<<0,
+
+	/* lchcr */
+	BigEndian = 1<<24,
+	AT7 = 7<<21,	/* access type */
+
+	/* sdcr */
+	LAM = 1<<6,	/* ``LCD aggressive mode'' */
+};
+
+/*
+ * TO DO: most of the data could come from a table
+ */
+static void
+lcdinit(Mode *mode)
+{
+	IMM *io;
+	int i, d;
+	long hz;
+
+	io = m->iomem;
+	mode->y = ROWS;
+	mode->x = COLS;
+	mode->d = LDEPTH;
+	mode->aperture = ialloc(mode->x*mode->y, 16);
+	mode->apsize = mode->x*mode->y;
+
+	io->sdcr &= ~LAM;	/* MPC823 errata: turn off LAM before disabling controller */
+	io->lcfaa = PADDR(mode->aperture);
+	io->lccr = (((mode->x*mode->y*(1<<LDEPTH)+127)/128) << 17) | (LDEPTH << 5) | IsColour | IsTFT | OELow | VsyncLow | ClockLow;
+
+	switch(LDEPTH){
+	default:
+	case 0:
+		/* monochrome/greyscale identity map */
+		for(i=0; i<16; i++)
+			io->lcdmap[i] = i;
+		break;
+	case 2:
+		/* 4-bit grey scale map */
+		for(i=0; i<16; i++)
+			io->lcdmap[0] = (i<<8)|(i<<4)|i;
+		break;
+	case 3:
+		/* 8-bit linear map */
+		for(i=0; i<256; i++)
+			io->lcdmap[i] = (i<<8)|(i<<4)|i;
+		break;
+	}
+
+	io->lcvcr = (mode->y << 11) | (1<<28) | 33;	/* 2 line vsync pulse, 34 line wait between frames */
+	io->lchcr = (mode->x<<10) | BigEndian | 228;	/* clock cycles between lines */
+
+	hz = m->cpuhz;
+	d = hz/LCDFREQ;
+	if(hz/d > LCDFREQ)
+		d++;
+	if(d >= 16)
+		d = 16;
+
+	/*
+	 * enable LCD outputs
+	 */
+	io->pddat = 0;
+	io->pdpar = 0x1fff;
+io->pdpar &= ~SIBIT(6);	/* 823 bug fix? */
+	io->pddir = 0x1fff;
+	io->pbpar |= IBIT(31) | IBIT(19) | IBIT(17);
+	io->pbdir |= IBIT(31) | IBIT(19) | IBIT(17);
+	io->pbodr &= ~(IBIT(31) | IBIT(19) | IBIT(17));
+
+	eieio();
+	io->sccrk = KEEP_ALIVE_KEY;
+	eieio();
+	io->sccr  = (io->sccr & ~0x1F) | lcdclock[d];
+	eieio();
+	io->sccrk = ~KEEP_ALIVE_KEY;
+	eieio();
+	gscreen.width = gscreen.width;	/* access external memory before enabling (mpc823 errata) */
+	io->lcsr = 7;	/* clear status */
+	eieio();
+	io->lccr |= Enable;
+	archbacklight(1);
+}
+
+int
+setcolor(ulong p, ulong r, ulong g, ulong b)
+{
+	r >>= 28;
+	g >>= 28;
+	b >>= 28;
+	m->iomem->lcdmap[~p&0xFF] = (r<<8) | (g<<4) | b;	/* TO DO: it's a function of the ldepth */
+	return 1;
+}
--- /dev/null
+++ b/os/boot.original/mpc/sload.c
@@ -1,0 +1,71 @@
+/*
+ * send S records to rpcg
+ */
+
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+
+static	int	dbg;
+static	char	buf[2048];
+static	int	run=1;
+static	void	stuffbym(char*, int, int);
+static	void	getdot(void);
+
+void
+main(int argc, char **argv)
+{
+	int n;
+	char *l;
+	Biobuf *f;
+	static int p;
+
+	ARGBEGIN{
+	case 'd': dbg++; break;
+	case 'n': run=0; break;
+	}ARGEND
+
+	f = Bopen(*argv? *argv: "k.mx", OREAD);
+	if(f == 0) {
+		fprint(2, "sload: cannot open k.mx: %r\n");
+		exits("sload");
+	}
+	getdot();
+	while((l = Brdline(f, '\n')) != 0) {
+		l[Blinelen(f)-1] = '\r';
+		stuffbym(l, Blinelen(f), 16);
+		getdot();
+		if(++p % 25 == 0)
+			write(2, ".", 1);
+	}
+	exits(0);
+}
+
+static void
+stuffbym(char *l, int n, int m)
+{
+	int nr, ns;
+
+	while(n > 0) {
+		ns = n;
+		if(ns > m)
+			ns = m;
+		write(1, l, ns);
+		l += ns;
+		n -= ns;
+	}
+}
+
+static void
+getdot(void)
+{
+	char c;
+
+	for(;;){
+		if(read(0, &c, 1) != 1)
+			exits("bang");
+		write(2, &c, 1);
+		if(c == '.')
+			break;
+	}
+}
--- /dev/null
+++ b/os/boot.original/mpc/squeeze.h
@@ -1,0 +1,34 @@
+
+/*
+ * squeezed file format:
+ *	Sqhdr
+ *	original Exec header
+ *	two Squeeze tables
+ *	squeezed segment
+ *	unsqueezed segment, if any
+ */
+#define	SQMAGIC	(ulong)0xFEEF0F1E
+
+typedef struct Sqhdr Sqhdr;
+struct Sqhdr {
+	uchar	magic[4];	/* SQMAGIC */
+	uchar	text[4];	/* squeezed length of text (excluding tables) */
+	uchar	data[4];	/* squeezed length of data (excluding tables) */
+	uchar	asis[4];	/* length of unsqueezed segment */
+	uchar	toptxt[4];	/* value for 0 encoding in text */
+	uchar	topdat[4];	/* value for 0 encoding in data */
+	uchar	sum[4];	/* simple checksum of unsqueezed data */
+	uchar	flags[4];
+};
+#define	SQHDRLEN	(8*4)
+
+/*
+ * certain power instruction types are rearranged by sqz
+ * so as to move the variable part of the instruction word to the
+ * low order bits.  note that the mapping is its own inverse.
+ */
+#define	QREMAP(X)\
+	switch((X)>>26){\
+	case 19: case 31: case 59: case 63:\
+		(X) = (((X) & 0xFC00F801) | (((X)>>15)&0x7FE) | (((X)&0x7FE)<<15));\
+	}
--- /dev/null
+++ b/os/boot.original/mpc/trap.c
@@ -1,0 +1,233 @@
+#include "boot.h"
+
+enum 
+{
+	Maxhandler=	32+16,		/* max number of interrupt handlers */
+};
+
+typedef struct Handler	Handler;
+struct Handler
+{
+	void	(*r)(Ureg*, void*);
+	void	*arg;
+	Handler	*next;
+	int	edge;
+};
+
+struct
+{
+	Handler	*ivec[128];
+	Handler	h[Maxhandler];
+	int	free;
+} halloc;
+
+char	*excname[] = {
+	"reserved 0",
+	"system reset",
+	"machine check",
+	"data access",
+	"instruction access",
+	"external interrupt",
+	"alignment",
+	"program exception",
+	"floating-point unavailable",
+	"decrementer",
+	"reserved A",
+	"reserved B",
+	"system call",
+	"trace trap",
+	"floating point assist",
+	"reserved F",
+	"software emulation",
+	"ITLB miss",
+	"DTLB miss",
+	"ITLB error",
+	"DTLB error",
+};
+
+char *regname[]={
+	"CAUSE",	"SRR1",
+	"PC",		"GOK",
+	"LR",		"CR",
+	"XER",	"CTR",
+	"R0",		"R1",
+	"R2",		"R3",
+	"R4",		"R5",
+	"R6",		"R7",
+	"R8",		"R9",
+	"R10",	"R11",
+	"R12",	"R13",
+	"R14",	"R15",
+	"R16",	"R17",
+	"R18",	"R19",
+	"R20",	"R21",
+	"R22",	"R23",
+	"R24",	"R25",
+	"R26",	"R27",
+	"R28",	"R29",
+	"R30",	"R31",
+};
+
+static	void	intr(Ureg*);
+
+void
+sethvec(int v, void (*r)(void))
+{
+	ulong *vp, pa, o;
+
+	if((ulong)r & 3)
+		panic("sethvec");
+	vp = (ulong*)KADDR(v);
+	vp[0] = 0x7c1043a6;	/* MOVW R0, SPR(SPRG0) */
+	vp[1] = 0x7c0802a6;	/* MOVW LR, R0 */
+	vp[2] = 0x7c1243a6;	/* MOVW R0, SPR(SPRG2) */
+	pa = PADDR(r);
+	o = pa >> 25;
+	if(o != 0 && o != 0x7F){
+		/* a branch too far: running from ROM */
+		vp[3] = (15<<26)|(pa>>16);	/* MOVW $r&~0xFFFF, R0 */
+		vp[4] = (24<<26)|(pa&0xFFFF);	/* OR $r&0xFFFF, R0 */
+		vp[5] = 0x7c0803a6;	/* MOVW	R0, LR */
+		vp[6] = 0x4e800021;	/* BL (LR) */
+	}else
+		vp[3] = (18<<26)|(pa&0x3FFFFFC)|3;	/* bla */
+}
+
+#define	LEV(n)	(((n)<<1)|1)
+#define	IRQ(n)	(((n)<<1)|0)
+
+void
+setvec(int v, void (*r)(Ureg*, void*), void *arg)
+{
+	Handler *h;
+	IMM *io;
+
+	if(halloc.free >= Maxhandler)
+		panic("out of interrupt handlers");
+	v -= VectorPIC;
+	h = &halloc.h[halloc.free++];
+	h->next = halloc.ivec[v];
+	h->r = r;
+	h->arg = arg;
+	halloc.ivec[v] = h;
+
+	/*
+	 * enable corresponding interrupt in SIU/CPM
+	 */
+
+	io = m->iomem;
+	if(v >= VectorCPIC){
+		v -= VectorCPIC;
+		io->cimr |= 1<<(v&0x1F);
+	}
+	else if(v >= VectorIRQ)
+		io->simask |= 1<<(31-IRQ(v&7));
+	else
+		io->simask |= 1<<(31-LEV(v));
+}
+
+void
+trapinit(void)
+{
+	int i;
+	IMM *io;
+
+	io = m->iomem;
+	io->sypcr &= ~(3<<2);	/* disable watchdog (821/823) */
+	io->simask = 0;	/* mask all */
+	io->siel = ~0;	/* edge sensitive, wake on all */
+	io->cicr = 0;	/* disable CPM interrupts */
+	io->cipr = ~0;	/* clear all interrupts */
+	io->cimr = 0;	/* mask all events */
+	io->cicr = (0xE1<<16)|(CPIClevel<<13)|(0x1F<<8);
+	io->cicr |= 1 << 7;	/* enable */
+	io->tbscrk = KEEP_ALIVE_KEY;
+	io->tbscr = 1;	/* TBE */
+	io->simask |= 1<<(31-LEV(CPIClevel));	/* CPM's level */
+	io->tbk = KEEP_ALIVE_KEY;
+	eieio();
+	putdec(~0);
+
+	/*
+	 * set all exceptions to trap
+	 */
+	for(i = 0x0; i < 0x3000; i += 0x100)
+		sethvec(i, exception);
+}
+
+void
+dumpregs(Ureg *ur)
+{
+	int i;
+	ulong *l;
+	l = &ur->cause;
+	for(i=0; i<sizeof regname/sizeof(char*); i+=2, l+=2)
+		print("%s\t%.8lux\t%s\t%.8lux\n", regname[i], l[0], regname[i+1], l[1]);
+}
+
+void
+trap(Ureg *ur)
+{
+	int c;
+
+	c = ur->cause >> 8;
+	switch(c){
+	default:
+		{extern int predawn; predawn = 1;}
+		if(c < 0 || c >= nelem(excname))
+			print("exception/interrupt #%x\n", c);
+		else
+			print("exception %s\n", excname[c]);
+		dumpregs(ur);
+		/* spllo(); */
+		print("^P to reset\n");
+		for(;;)
+			;
+
+	case 0x09:	/* decrementer */
+		clockintr(ur, 0);
+		return;
+
+	case 0x05:	/* external interrupt */
+		intr(ur);
+		break;
+	}
+}
+
+static void
+intr(Ureg *ur)
+{
+	int b, v;
+	Handler *h;
+	IMM *io;
+
+	io = m->iomem;
+	b = io->sivec>>2;
+	v = b>>1;
+	if(b & 1) {
+		if(v == CPIClevel){
+			io->civr = 1;
+			eieio();
+			v = VectorCPIC+(io->civr>>11);
+		}
+	}else
+		v += VectorIRQ;
+	h = halloc.ivec[v];
+	if(h == nil){
+		for(;;)
+			;
+		//print("unknown interrupt %d pc=0x%lux\n", v, ur->pc);
+		return;
+	}
+	if(h->edge)
+		io->sipend |= 1<<(31-b);
+	/*
+	 *  call the interrupt handlers
+	 */
+	do {
+		(*h->r)(ur, h->arg);
+		h = h->next;
+	} while(h != nil);
+	if(v >= VectorCPIC)
+		io->cisr |= 1<<(v-VectorCPIC);
+}
--- /dev/null
+++ b/os/boot.original/mpc/uartboot.c
@@ -1,0 +1,189 @@
+#include "boot.h"
+
+/*
+ * this doesn't yet use the crc
+ */
+
+typedef struct Uboot Uboot;
+struct Uboot {
+	Queue*	iq;
+	Block*	partial;
+	ulong	csum;
+	long	bno;
+	uchar	buf[64];
+	int	nleft;
+	int	ntimeout;
+};
+
+static	Uboot	uboot;
+ulong	crc32(void *buf, int n, ulong crc);
+
+static void
+uartbrecv(uchar *p, int n)
+{
+	Uboot *ub;
+	Block *b;
+
+	ub = &uboot;
+	if(n > 0 && ub->iq != nil){
+		b = iallocb(n);
+		memmove(b->wp, p, n);
+		b->wp += n;
+		qbwrite(ub->iq, b);
+	}
+}
+
+int
+uartinit(void)
+{
+	return 1<<0;
+}
+
+Partition*
+setuartpart(int, char *s)
+{
+	static Partition pp[1];
+
+	if(strcmp(s, "boot") != 0 && strcmp(s, "disk") != 0)
+		return 0;
+	pp[0].start = 0;
+	pp[0].end = 2*1024*1024;
+	strcpy(pp[0].name, "boot");
+	return pp;
+}
+
+long
+uartseek(int, long)
+{
+	/* start the boot */
+	if(uboot.iq == nil)
+		uboot.iq = qopen(64*1024, 0, 0, 0);
+	if(uboot.partial){
+		freeb(uboot.partial);
+		uboot.partial = 0;
+	}
+	print("uart: start transmission\n");
+	uartsetboot(uartbrecv);
+	uboot.csum = ~0;
+	uboot.bno = 0;
+	uboot.nleft = 0;
+	uboot.ntimeout = 0;
+	return 0;
+}
+
+static long
+uartreadn(void *buf, int nb)
+{
+	ulong start;
+	Uboot *ub;
+	int l;
+	Block *b;
+	uchar *p;
+
+	p = buf;
+	ub = &uboot;
+	start = m->ticks;
+	while(nb > 0){
+		b = ub->partial;
+		ub->partial = nil;
+		if(b == nil){
+			ub->ntimeout = 0;
+			while((b = qget(ub->iq)) == 0){
+				if(TK2MS(m->ticks - start) >= 15*1000){
+					if(++ub->ntimeout >= 3){
+						print("uart: timeout\n");
+						return 0;
+					}
+					uartputs("n", 1);
+				}
+			}
+		}
+		l = BLEN(b);
+		if(l > nb)
+			l = nb;
+		memmove(p, b->rp, l);
+		b->rp += l;
+		if(b->rp >= b->wp)
+			freeb(b);
+		else
+			ub->partial = b;
+		nb -= l;
+		p += l;
+	}
+	return p-(uchar*)buf;
+}
+
+long
+uartread(int, void *buf, long n)
+{
+	uchar *p;
+	int l;
+	static uchar lbuf[64];
+
+	p = buf;
+	if((l = uboot.nleft) > 0){
+		if(l > n)
+			l = n;
+		uboot.nleft -= l;
+		memmove(p, uboot.buf, l);
+		p += l;
+		n -= l;
+	}
+	while(n > 0){
+		l = uartreadn(lbuf, sizeof(lbuf));
+		if(l < sizeof(lbuf))
+			return 0;
+		if(l > n){
+			uboot.nleft = l-n;
+			memmove(uboot.buf, lbuf+n, uboot.nleft);
+			l = n;
+		}
+		memmove(p, lbuf, l);
+		n -= l;
+		p += l;
+		uboot.bno++;
+		uartputs("y", 1);
+	}
+	return p-(uchar*)buf;
+}
+
+/*
+ * from Rob Warnock
+ */
+static	ulong	crc32tab[256];	/* initialised on first call to crc32 */
+
+enum {
+	CRC32POLY = 0x04c11db7     /* AUTODIN II, Ethernet, & FDDI */
+};
+
+/*
+ * Build auxiliary table for parallel byte-at-a-time CRC-32.
+ */
+static void
+initcrc32(void)
+{
+	int i, j;
+	ulong c;
+
+	for(i = 0; i < 256; i++) {
+		for(c = i << 24, j = 8; j > 0; j--)
+			if(c & (1<<31))
+				c = (c<<1) ^ CRC32POLY;
+			else
+				c <<= 1;
+		crc32tab[i] = c;
+	}
+}
+
+ulong
+crc32(void *buf, int n, ulong crc)
+{
+	uchar *p;
+
+	if(crc32tab[1] == 0)
+		initcrc32();
+	crc = ~crc;
+	for(p = buf; --n >= 0;)
+		crc = (crc << 8) ^ crc32tab[(crc >> 24) ^ *p++];
+	return ~crc;
+}
--- /dev/null
+++ b/os/boot.original/mpc/ureg.h
@@ -1,0 +1,43 @@
+struct Ureg
+{
+	ulong	cause;
+	union { ulong	srr1; ulong status;};
+	ulong	pc;	/* SRR0 */
+	ulong	pad;
+	ulong	lr;
+	ulong	cr;
+	ulong	xer;
+	ulong	ctr;
+	ulong	r0;
+	union{ ulong r1;	ulong	sp;	ulong	usp; };
+	ulong	r2;
+	ulong	r3;
+	ulong	r4;
+	ulong	r5;
+	ulong	r6;
+	ulong	r7;
+	ulong	r8;
+	ulong	r9;
+	ulong	r10;
+	ulong	r11;
+	ulong	r12;
+	ulong	r13;
+	ulong	r14;
+	ulong	r15;
+	ulong	r16;
+	ulong	r17;
+	ulong	r18;
+	ulong	r19;
+	ulong	r20;
+	ulong	r21;
+	ulong	r22;
+	ulong	r23;
+	ulong	r24;
+	ulong	r25;
+	ulong	r26;
+	ulong	r27;
+	ulong	r28;
+	ulong	r29;
+	ulong	r30;
+	ulong	r31;
+};
--- /dev/null
+++ b/os/boot.original/mpc/zqs.c
@@ -1,0 +1,234 @@
+#include "boot.h"
+#include "squeeze.h"
+
+/*
+ * for details of `unsqueeze' see:
+ *
+ * %A Mark Taunton
+ * %T Compressed Executables: An Exercise in Thinking Small
+ * %P 385-404
+ * %I USENIX
+ * %B USENIX Conference Proceedings
+ * %D Summer 1991
+ * %C Nashville, TN
+ *
+ * several of the unimplemented improvements described in the paper
+ * have been implemented here
+ *
+ * there is a further transformation on the powerpc (QFLAG!=0) to shuffle bits
+ * in certain instructions so as to push the fixed bits to the top of the word.
+ */
+
+#define	EXECHDRLEN	(8*4)
+
+typedef struct Squeeze Squeeze;
+struct Squeeze {
+	int	n;
+	ulong	tab[7*256];
+};
+
+#define	GET4(p)	(((((((p)[0]<<8)|(p)[1])<<8)|(p)[2])<<8)|(p)[3])
+
+/*
+ * for speed of unsqueezing from Flash, certain checks are
+ * not done inside the loop (as they would be in the unsqueeze program zqs),
+ * but instead the checksum is expected to catch corrupted files.
+ * in fact the Squeeze array bounds can't be exceeded in practice
+ * because the tables are always full for a squeezed kernel.
+ */
+enum {
+	QFLAG = 1,	/* invert powerpc-specific code transformation */
+	CHECK = 0,	/* check precise bounds in Squeeze array (otherwise checksum detects error) */
+};
+
+static	ulong	chksum;
+static	int	rdtab(Block*, Squeeze*, int);
+static	ulong*	unsqueeze(ulong*, uchar*, uchar*, Squeeze*, Squeeze*, ulong);
+static	uchar*	unsqzseg(uchar*, Block*, long, long, char*);
+static	Alarm*	unsqzal;
+
+int
+issqueezed(uchar *b)
+{
+	return GET4(b) == SQMAGIC? GET4(b+SQHDRLEN): 0;
+}
+
+static void
+unsqzdot(Alarm*)
+{
+	unsqzal = alarm(500, unsqzdot, nil);
+	print(".");
+}
+
+long
+unsqueezef(Block *b, ulong *entryp)
+{
+	uchar *loada, *wp;
+	ulong toptxt, topdat, oldsum;
+	long asis, nst, nsd;
+	Sqhdr *sqh;
+	Exec *ex;
+
+	if(BLEN(b) < SQHDRLEN+EXECHDRLEN)
+		return -1;
+	sqh = (Sqhdr*)b->rp;
+	if(GET4(sqh->magic) != SQMAGIC)
+		return -1;
+	chksum = 0;
+	toptxt = GET4(sqh->toptxt);
+	topdat = GET4(sqh->topdat);
+	oldsum = GET4(sqh->sum);
+	asis = GET4(sqh->asis);
+	nst = GET4(sqh->text);
+	nsd = GET4(sqh->data);
+	b->rp += SQHDRLEN;
+	ex = (Exec*)b->rp;
+	if(GET4(ex->magic) != Q_MAGIC){
+		print("zqs: not powerPC executable\n");
+		return -1;
+	}
+	*entryp = GET4(ex->entry);
+	b->rp += EXECHDRLEN;
+	loada = KADDR(PADDR(*entryp));
+	wp = unsqzseg(loada, b, nst, toptxt, "text");
+	if(wp == nil){
+		print("zqs: format error\n");
+		return -1;
+	}
+	if(nsd){
+		wp = (uchar*)PGROUND((ulong)wp);
+		wp = unsqzseg(wp, b, nsd, topdat, "data");
+		if(wp == nil){
+			print("zqs: format error\n");
+			return -1;
+		}
+	}
+	if(asis){
+		memmove(wp, b->rp, asis);
+		wp += asis;
+		b->rp += asis;
+	}
+	if(chksum != oldsum){
+		print("\nsqueezed kernel: checksum error: %8.8lux need %8.8lux\n", chksum, oldsum);
+		return -1;
+	}
+	return wp-loada;
+}
+
+static uchar *
+unsqzseg(uchar *wp, Block *b, long ns, long top, char *what)
+{
+	static Squeeze sq3, sq4;
+
+	print("unpack %s %8.8lux %lud:", what, wp, ns);
+	if(ns == 0)
+		return wp;
+	if(rdtab(b, &sq3, 0) < 0)
+		return nil;
+	if(rdtab(b, &sq4, 8) < 0)
+		return nil;
+	if(BLEN(b) < ns){
+		print(" **size error\n");
+		return nil;
+	}
+	unsqzal = alarm(500, unsqzdot, nil);
+	wp = (uchar*)unsqueeze((ulong*)wp, b->rp, b->rp+ns, &sq3, &sq4, top);
+	cancel(unsqzal);
+	unsqzal = nil;
+	print("\n");
+	if(wp == nil){
+		print("zqs: corrupt squeezed data stream\n");
+		return nil;
+	}
+	b->rp += ns;
+	return wp;
+}
+
+static ulong*
+unsqueeze(ulong *wp, uchar *rp, uchar *ep, Squeeze *sq3, Squeeze *sq4, ulong top)
+{
+	ulong nx, csum;
+	int code, n;
+
+	if(QFLAG){
+		QREMAP(top);	/* adjust top just once, outside the loop */
+	}
+	csum = chksum;
+	while(rp < ep){
+		/* no function calls within this loop for speed */
+		code = *rp;
+		rp++;
+		n = 0;
+		nx = code>>4;
+		do{
+			if(nx == 0){
+				nx = top;
+			}else{
+				if(nx==1){
+					nx = (((((rp[3]<<8)|rp[2])<<8)|rp[1])<<8)|rp[0];
+					rp += 4;
+				}else if(nx <= 8){	/* 2 to 8 */
+					nx = ((nx-2)<<8) | rp[0];
+					if(CHECK && nx >= sq4->n)
+						return nil;	/* corrupted file */
+					nx = sq4->tab[nx] | rp[1];
+					rp += 2;
+				}else{	/* 9 to 15 */
+					nx = ((nx-9)<<8) | rp[0];
+					if(CHECK && nx >= sq3->n)
+						return nil;	/* corrupted file */
+					nx = sq3->tab[nx];
+					rp++;
+				}
+				if(rp > ep)
+					return nil;	/* corrupted file */
+				if(QFLAG){
+					QREMAP(nx);
+				}
+			}
+			*wp = nx;
+			wp++;
+			csum += nx;
+			nx = code & 0xF;
+		}while(++n == 1);
+	}
+	chksum = csum;
+	return wp;
+}
+
+static int
+rdtab(Block *b, Squeeze *sq, int shift)
+{
+	uchar *p, *ep;
+	ulong v, w;
+	int i;
+
+	if(BLEN(b) < 2)
+		return -1;
+	i = (b->rp[0]<<8) | b->rp[1];
+	if(1)
+		print(" T%d", i);
+	b->rp += 2;
+	if((i -= 2) > 0){
+		if(BLEN(b) < i)
+			return -1;
+	}
+	sq->n = 0;
+	p = b->rp;
+	ep = b->rp+i;
+	b->rp += i;
+	v = 0;
+	while(p < ep){
+		w = 0;
+		do{
+			if(p >= ep)
+				return -1;
+			w = (w<<7) | (*p & 0x7F);
+		}while(*p++ & 0x80);
+		v += w;
+		if(0)
+			print("%d %8.8lux %8.8lux\n", sq->n, v, w);
+		sq->tab[sq->n++] = v<<shift;
+	}
+	return 0;
+}
--- /dev/null
+++ b/os/boot.original/pc/8250.c
@@ -1,0 +1,308 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+/*
+ *  INS8250 uart
+ */
+enum
+{
+	/*
+	 *  register numbers
+	 */
+	Data=	0,		/* xmit/rcv buffer */
+	Iena=	1,		/* interrupt enable */
+	 Ircv=	(1<<0),		/*  for char rcv'd */
+	 Ixmt=	(1<<1),		/*  for xmit buffer empty */
+	 Irstat=(1<<2),		/*  for change in rcv'er status */
+	 Imstat=(1<<3),		/*  for change in modem status */
+	Istat=	2,		/* interrupt flag (read) */
+	Tctl=	2,		/* test control (write) */
+	Format=	3,		/* byte format */
+	 Bits8=	(3<<0),		/*  8 bits/byte */
+	 Stop2=	(1<<2),		/*  2 stop bits */
+	 Pena=	(1<<3),		/*  generate parity */
+	 Peven=	(1<<4),		/*  even parity */
+	 Pforce=(1<<5),		/*  force parity */
+	 Break=	(1<<6),		/*  generate a break */
+	 Dra=	(1<<7),		/*  address the divisor */
+	Mctl=	4,		/* modem control */
+	 Dtr=	(1<<0),		/*  data terminal ready */
+	 Rts=	(1<<1),		/*  request to send */
+	 Ri=	(1<<2),		/*  ring */
+	 Inton=	(1<<3),		/*  turn on interrupts */
+	 Loop=	(1<<4),		/*  loop back */
+	Lstat=	5,		/* line status */
+	 Inready=(1<<0),	/*  receive buffer full */
+	 Oerror=(1<<1),		/*  receiver overrun */
+	 Perror=(1<<2),		/*  receiver parity error */
+	 Ferror=(1<<3),		/*  rcv framing error */
+	 Outready=(1<<5),	/*  output buffer empty */
+	Mstat=	6,		/* modem status */
+	 Ctsc=	(1<<0),		/*  clear to send changed */
+	 Dsrc=	(1<<1),		/*  data set ready changed */
+	 Rire=	(1<<2),		/*  rising edge of ring indicator */
+	 Dcdc=	(1<<3),		/*  data carrier detect changed */
+	 Cts=	(1<<4),		/*  complement of clear to send line */
+	 Dsr=	(1<<5),		/*  complement of data set ready line */
+	 Ring=	(1<<6),		/*  complement of ring indicator line */
+	 Dcd=	(1<<7),		/*  complement of data carrier detect line */
+	Scratch=7,		/* scratchpad */
+	Dlsb=	0,		/* divisor lsb */
+	Dmsb=	1,		/* divisor msb */
+
+	Serial=	0,
+	Modem=	1,
+};
+
+typedef struct Uart	Uart;
+struct Uart
+{
+	int	port;
+	uchar	sticky[8];	/* sticky write register values */
+	uchar	txbusy;
+
+	void	(*rx)(int);	/* routine to take a received character */
+	int	(*tx)(void);	/* routine to get a character to transmit */
+
+	ulong	frame;
+	ulong	overrun;
+};
+
+static Uart com[2];
+static Uart* uart;
+
+#define UartFREQ 1843200
+
+#define uartwrreg(u,r,v)	outb((u)->port + r, (u)->sticky[r] | (v))
+#define uartrdreg(u,r)		inb((u)->port + r)
+
+/*
+ *  set the baud rate by calculating and setting the baudrate
+ *  generator constant.  This will work with fairly non-standard
+ *  baud rates.
+ */
+static void
+uartsetbaud(Uart *up, int rate)
+{
+	ulong brconst;
+
+	brconst = (UartFREQ+8*rate-1)/(16*rate);
+
+	uartwrreg(up, Format, Dra);
+	outb(up->port+Dmsb, (brconst>>8) & 0xff);
+	outb(up->port+Dlsb, brconst & 0xff);
+	uartwrreg(up, Format, 0);
+}
+
+/*
+ *  toggle DTR
+ */
+static void
+uartdtr(Uart *up, int n)
+{
+	if(n)
+		up->sticky[Mctl] |= Dtr;
+	else
+		up->sticky[Mctl] &= ~Dtr;
+	uartwrreg(up, Mctl, 0);
+}
+
+/*
+ *  toggle RTS
+ */
+static void
+uartrts(Uart *up, int n)
+{
+	if(n)
+		up->sticky[Mctl] |= Rts;
+	else
+		up->sticky[Mctl] &= ~Rts;
+	uartwrreg(up, Mctl, 0);
+}
+
+static void
+uartintr(Ureg*, void *arg)
+{
+	Uart *up;
+	int ch;
+	int s, l, loops;
+
+	up = arg;
+	for(loops = 0; loops < 1024; loops++){
+		s = uartrdreg(up, Istat);
+		switch(s & 0x3F){
+		case 6:	/* receiver line status */
+			l = uartrdreg(up, Lstat);
+			if(l & Ferror)
+				up->frame++;
+			if(l & Oerror)
+				up->overrun++;
+			break;
+	
+		case 4:	/* received data available */
+		case 12:
+			ch = inb(up->port+Data);
+			if(up->rx)
+				(*up->rx)(ch);
+			break;
+	
+		case 2:	/* transmitter empty */
+			ch = -1;
+			if(up->tx)
+				ch = (*up->tx)();
+			if(ch != -1)
+				outb(up->port+Data, ch);
+			else
+				up->txbusy = 0;
+			break;
+	
+		case 0:	/* modem status */
+			uartrdreg(up, Mstat);
+			break;
+	
+		default:
+			if(s&1)
+				return;
+			print("weird modem interrupt #%2.2ux\n", s);
+			break;
+		}
+	}
+	panic("uartintr: 0x%2.2ux\n", uartrdreg(up, Istat));
+}
+
+/*
+ *  turn on a port's interrupts.  set DTR and RTS
+ */
+static void
+uartenable(Uart *up)
+{
+	/*
+ 	 *  turn on interrupts
+	 */
+	up->sticky[Iena] = 0;
+	if(up->tx)
+		up->sticky[Iena] |= Ixmt;
+	if(up->rx)
+		up->sticky[Iena] |= Ircv|Irstat;
+	uartwrreg(up, Iena, 0);
+
+	/*
+	 *  turn on DTR and RTS
+	 */
+	uartdtr(up, 1);
+	uartrts(up, 1);
+}
+
+static void
+uartdisable(Uart* up)
+{
+	/*
+ 	 * Disable interrupts.
+	 */
+	up->sticky[Iena] = 0;
+	uartwrreg(up, Iena, 0);
+	uartdtr(up, 0);
+	uartrts(up, 0);
+}
+
+void
+uartspecial(int port, void (*rx)(int), int (*tx)(void), int baud)
+{
+	Uart *up;
+	int vector;
+
+	switch(port){
+	case 0:
+		port = 0x3F8;
+		vector = VectorUART0;
+		up = &com[0];
+		break;
+	case 1:
+		port = 0x2F8;
+		vector = VectorUART1;
+		up = &com[1];
+		break;
+	default:
+		return;
+	}
+
+	if(uart != nil && uart != up)
+		uartdisable(uart);
+	uart = up;
+
+	if(up->port == 0){
+		up->port = port;
+		setvec(vector, uartintr, up);
+	}
+
+	/*
+	 *  set rate to 9600 baud.
+	 *  8 bits/character.
+	 *  1 stop bit.
+	 *  interrupts enabled.
+	 */
+	uartsetbaud(up, 9600);
+	up->sticky[Format] = Bits8;
+	uartwrreg(up, Format, 0);
+	up->sticky[Mctl] |= Inton;
+	uartwrreg(up, Mctl, 0x0);
+
+	up->rx = rx;
+	up->tx = tx;
+	uartenable(up);
+	if(baud)
+		uartsetbaud(up, baud);
+}
+
+void
+uartputc(int c)
+{
+	int i;
+	Uart *up;
+
+	if((up = uart) == nil)
+		return;
+	for(i = 0; i < 100; i++){
+		if(uartrdreg(up, Lstat) & Outready)
+			break;
+		delay(1);
+	}
+	outb(up->port+Data, c);
+}
+
+void
+uartputs(IOQ *q, char *s, int n)
+{
+	Uart *up;
+	int c, x;
+
+	if((up = uart) == nil)
+		return;
+	while(n--){
+		if(*s == '\n')
+			q->putc(q, '\r');
+		q->putc(q, *s++);
+	}
+	x = splhi();
+	if(up->txbusy == 0 && (c = q->getc(q)) != -1){
+		uartputc(c & 0xFF);
+		up->txbusy = 1;
+	}
+	splx(x);
+}
+
+void
+uartdrain(void)
+{
+	Uart *up;
+	int timeo;
+
+	if((up = uart) == nil)
+		return;
+	for(timeo = 0; timeo < 10000 && up->txbusy; timeo++)
+		delay(1);
+}
--- /dev/null
+++ b/os/boot.original/pc/LICENCE
@@ -1,0 +1,237 @@
+Lucent Public License Version 1.02
+
+THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS PUBLIC
+LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE
+PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT.
+
+1. DEFINITIONS
+
+"Contribution" means:
+
+  a. in the case of Lucent Technologies Inc. ("LUCENT"), the Original
+     Program, and
+  b. in the case of each Contributor,
+
+     i. changes to the Program, and
+    ii. additions to the Program;
+
+    where such changes and/or additions to the Program were added to the
+    Program by such Contributor itself or anyone acting on such
+    Contributor's behalf, and the Contributor explicitly consents, in
+    accordance with Section 3C, to characterization of the changes and/or
+    additions as Contributions.
+
+"Contributor" means LUCENT and any other entity that has Contributed a
+Contribution to the Program.
+
+"Distributor" means a Recipient that distributes the Program,
+modifications to the Program, or any part thereof.
+
+"Licensed Patents" mean patent claims licensable by a Contributor
+which are necessarily infringed by the use or sale of its Contribution
+alone or when combined with the Program.
+
+"Original Program" means the original version of the software
+accompanying this Agreement as released by LUCENT, including source
+code, object code and documentation, if any.
+
+"Program" means the Original Program and Contributions or any part
+thereof
+
+"Recipient" means anyone who receives the Program under this
+Agreement, including all Contributors.
+
+2. GRANT OF RIGHTS
+
+ a. Subject to the terms of this Agreement, each Contributor hereby
+    grants Recipient a non-exclusive, worldwide, royalty-free copyright
+    license to reproduce, prepare derivative works of, publicly display,
+    publicly perform, distribute and sublicense the Contribution of such
+    Contributor, if any, and such derivative works, in source code and
+    object code form.
+    
+ b. Subject to the terms of this Agreement, each Contributor hereby
+    grants Recipient a non-exclusive, worldwide, royalty-free patent
+    license under Licensed Patents to make, use, sell, offer to sell,
+    import and otherwise transfer the Contribution of such Contributor, if
+    any, in source code and object code form. The patent license granted
+    by a Contributor shall also apply to the combination of the
+    Contribution of that Contributor and the Program if, at the time the
+    Contribution is added by the Contributor, such addition of the
+    Contribution causes such combination to be covered by the Licensed
+    Patents. The patent license granted by a Contributor shall not apply
+    to (i) any other combinations which include the Contribution, nor to
+    (ii) Contributions of other Contributors. No hardware per se is
+    licensed hereunder.
+    
+ c. Recipient understands that although each Contributor grants the
+    licenses to its Contributions set forth herein, no assurances are
+    provided by any Contributor that the Program does not infringe the
+    patent or other intellectual property rights of any other entity. Each
+    Contributor disclaims any liability to Recipient for claims brought by
+    any other entity based on infringement of intellectual property rights
+    or otherwise. As a condition to exercising the rights and licenses
+    granted hereunder, each Recipient hereby assumes sole responsibility
+    to secure any other intellectual property rights needed, if any. For
+    example, if a third party patent license is required to allow
+    Recipient to distribute the Program, it is Recipient's responsibility
+    to acquire that license before distributing the Program.
+
+ d. Each Contributor represents that to its knowledge it has sufficient
+    copyright rights in its Contribution, if any, to grant the copyright
+    license set forth in this Agreement.
+
+3. REQUIREMENTS
+
+A. Distributor may choose to distribute the Program in any form under
+this Agreement or under its own license agreement, provided that:
+
+ a. it complies with the terms and conditions of this Agreement;
+
+ b. if the Program is distributed in source code or other tangible
+    form, a copy of this Agreement or Distributor's own license agreement
+    is included with each copy of the Program; and
+
+ c. if distributed under Distributor's own license agreement, such
+    license agreement:
+
+      i. effectively disclaims on behalf of all Contributors all warranties
+         and conditions, express and implied, including warranties or
+         conditions of title and non-infringement, and implied warranties or
+         conditions of merchantability and fitness for a particular purpose;
+     ii. effectively excludes on behalf of all Contributors all liability
+         for damages, including direct, indirect, special, incidental and
+         consequential damages, such as lost profits; and
+    iii. states that any provisions which differ from this Agreement are
+         offered by that Contributor alone and not by any other party.
+
+B. Each Distributor must include the following in a conspicuous
+   location in the Program:
+
+   Copyright (C) 2003, Lucent Technologies Inc. and others. All Rights
+   Reserved.
+
+C. In addition, each Contributor must identify itself as the
+originator of its Contribution in a manner that reasonably allows
+subsequent Recipients to identify the originator of the Contribution.
+Also, each Contributor must agree that the additions and/or changes
+are intended to be a Contribution. Once a Contribution is contributed,
+it may not thereafter be revoked.
+
+4. COMMERCIAL DISTRIBUTION
+
+Commercial distributors of software may accept certain
+responsibilities with respect to end users, business partners and the
+like. While this license is intended to facilitate the commercial use
+of the Program, the Distributor who includes the Program in a
+commercial product offering should do so in a manner which does not
+create potential liability for Contributors. Therefore, if a
+Distributor includes the Program in a commercial product offering,
+such Distributor ("Commercial Distributor") hereby agrees to defend
+and indemnify every Contributor ("Indemnified Contributor") against
+any losses, damages and costs (collectively"Losses") arising from
+claims, lawsuits and other legal actions brought by a third party
+against the Indemnified Contributor to the extent caused by the acts
+or omissions of such Commercial Distributor in connection with its
+distribution of the Program in a commercial product offering. The
+obligations in this section do not apply to any claims or Losses
+relating to any actual or alleged intellectual property infringement.
+In order to qualify, an Indemnified Contributor must: a) promptly
+notify the Commercial Distributor in writing of such claim, and b)
+allow the Commercial Distributor to control, and cooperate with the
+Commercial Distributor in, the defense and any related settlement
+negotiations. The Indemnified Contributor may participate in any such
+claim at its own expense.
+
+For example, a Distributor might include the Program in a commercial
+product offering, Product X. That Distributor is then a Commercial
+Distributor. If that Commercial Distributor then makes performance
+claims, or offers warranties related to Product X, those performance
+claims and warranties are such Commercial Distributor's responsibility
+alone. Under this section, the Commercial Distributor would have to
+defend claims against the Contributors related to those performance
+claims and warranties, and if a court requires any Contributor to pay
+any damages as a result, the Commercial Distributor must pay those
+damages.
+
+5. NO WARRANTY
+
+EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS
+PROVIDED ON AN"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY
+WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY
+OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely
+responsible for determining the appropriateness of using and
+distributing the Program and assumes all risks associated with its
+exercise of rights under this Agreement, including but not limited to
+the risks and costs of program errors, compliance with applicable
+laws, damage to or loss of data, programs or equipment, and
+unavailability or interruption of operations.
+
+6. DISCLAIMER OF LIABILITY
+
+EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR
+ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING
+WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR
+DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
+HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+7. EXPORT CONTROL
+
+Recipient agrees that Recipient alone is responsible for compliance
+with the United States export administration regulations (and the
+export control laws and regulation of any other countries).
+
+8. GENERAL
+
+If any provision of this Agreement is invalid or unenforceable under
+applicable law, it shall not affect the validity or enforceability of
+the remainder of the terms of this Agreement, and without further
+action by the parties hereto, such provision shall be reformed to the
+minimum extent necessary to make such provision valid and enforceable.
+
+If Recipient institutes patent litigation against a Contributor with
+respect to a patent applicable to software (including a cross-claim or
+counterclaim in a lawsuit), then any patent licenses granted by that
+Contributor to such Recipient under this Agreement shall terminate as
+of the date such litigation is filed. In addition, if Recipient
+institutes patent litigation against any entity (including a
+cross-claim or counterclaim in a lawsuit) alleging that the Program
+itself (excluding combinations of the Program with other software or
+hardware) infringes such Recipient's patent(s), then such Recipient's
+rights granted under Section 2(b) shall terminate as of the date such
+litigation is filed.
+
+All Recipient's rights under this Agreement shall terminate if it
+fails to comply with any of the material terms or conditions of this
+Agreement and does not cure such failure in a reasonable period of
+time after becoming aware of such noncompliance. If all Recipient's
+rights under this Agreement terminate, Recipient agrees to cease use
+and distribution of the Program as soon as reasonably practicable.
+However, Recipient's obligations under this Agreement and any licenses
+granted by Recipient relating to the Program shall continue and
+survive.
+
+LUCENT may publish new versions (including revisions) of this
+Agreement from time to time. Each new version of the Agreement will be
+given a distinguishing version number. The Program (including
+Contributions) may always be distributed subject to the version of the
+Agreement under which it was received. In addition, after a new
+version of the Agreement is published, Contributor may elect to
+distribute the Program (including its Contributions) under the new
+version. No one other than LUCENT has the right to modify this
+Agreement. Except as expressly stated in Sections 2(a) and 2(b) above,
+Recipient receives no rights or licenses to the intellectual property
+of any Contributor under this Agreement, whether expressly, by
+implication, estoppel or otherwise. All rights in the Program not
+expressly granted under this Agreement are reserved.
+
+This Agreement is governed by the laws of the State of New York and
+the intellectual property laws of the United States of America. No
+party to this Agreement will bring a legal action under this Agreement
+more than one year after the cause of action arose. Each party waives
+its rights to a jury trial in any resulting litigation.
+
--- /dev/null
+++ b/os/boot.original/pc/NOTICE
@@ -1,0 +1,4 @@
+Copyright © 1995-2007 Lucent Technologies Inc. and others.  All rights reserved.
+Revisions for use with Inferno © 2003-2007 Vita Nuova Holdings Limited.
+
+This software is provided under the terms of the Lucent Public License, Version 1.02.
--- /dev/null
+++ b/os/boot.original/pc/ahci.h
@@ -1,0 +1,275 @@
+/*
+ * advanced host controller interface (sata)
+ * © 2007  coraid, inc
+ */
+
+/* ata errors */
+enum {
+	Emed	= 1<<0,		/* media error */
+	Enm	= 1<<1,		/* no media */
+	Eabrt	= 1<<2,		/* abort */
+	Emcr	= 1<<3,		/* media change request */
+	Eidnf	= 1<<4,		/* no user-accessible address */
+	Emc	= 1<<5,		/* media change */
+	Eunc	= 1<<6,		/* data error */
+	Ewp	= 1<<6,		/* write protect */
+	Eicrc	= 1<<7,		/* interface crc error */
+
+	Efatal	= Eidnf|Eicrc,	/* must sw reset */
+};
+
+/* ata status */
+enum {
+	ASerr	= 1<<0,		/* error */
+	ASdrq	= 1<<3,		/* request */
+	ASdf	= 1<<5,		/* fault */
+	ASdrdy	= 1<<6,		/* ready */
+	ASbsy	= 1<<7,		/* busy */
+
+	ASobs	= 1<<1|1<<2|1<<4,
+};
+
+/* pci configuration */
+enum {
+	Abar	= 5,
+};
+
+/*
+ * ahci memory configuration
+ *
+ * 0000-0023	generic host control
+ * 0024-009f	reserved
+ * 00a0-00ff	vendor specific.
+ * 0100-017f	port 0
+ * ...
+ * 1080-1100	port 31
+ */
+
+/* cap bits: supported features */
+enum {
+	Hs64a	= 1<<31,	/* 64-bit addressing */
+	Hsncq	= 1<<30,	/* ncq */
+	Hssntf	= 1<<29,	/* snotification reg. */
+	Hsmps	= 1<<28,	/* mech pres switch */
+	Hsss	= 1<<27,	/* staggered spinup */
+	Hsalp	= 1<<26,	/* aggressive link pm */
+	Hsal	= 1<<25,	/* activity led */
+	Hsclo	= 1<<24,	/* command-list override */
+	Hiss	= 1<<20,	/* for interface speed */
+//	Hsnzo	= 1<<19,
+	Hsam	= 1<<18,	/* ahci-mode only */
+	Hspm	= 1<<17,	/* port multiplier */
+//	Hfbss	= 1<<16,
+	Hpmb	= 1<<15,	/* multiple-block pio */
+	Hssc	= 1<<14,	/* slumber state */
+	Hpsc	= 1<<13,	/* partial-slumber state */
+	Hncs	= 1<<8,		/* n command slots */
+	Hcccs	= 1<<7,		/* coal */
+	Hems	= 1<<6,		/* enclosure mgmt. */
+	Hsxs	= 1<<5,		/* external sata */
+	Hnp	= 1<<0,		/* n ports */
+};
+
+/* ghc bits */
+enum {
+	Hae	= 1<<31,	/* enable ahci */
+	Hie	= 1<<1,		/* " interrupts */
+	Hhr	= 1<<0,		/* hba reset */
+};
+
+typedef struct {
+	ulong	cap;
+	ulong	ghc;
+	ulong	isr;
+	ulong	pi;		/* ports implemented */
+	ulong	ver;
+	ulong	ccc;		/* coaleasing control */
+	ulong	cccports;
+	ulong	emloc;
+	ulong	emctl;
+} Ahba;
+
+enum {
+	Acpds	= 1<<31,	/* cold port detect status */
+	Atfes	= 1<<30,	/* task file error status */
+	Ahbfs	= 1<<29,	/* hba fatal */
+	Ahbds	= 1<<28,	/* hba error (parity error) */
+	Aifs	= 1<<27,	/* interface fatal  §6.1.2 */
+	Ainfs	= 1<<26,	/* interface error (recovered) */
+	Aofs	= 1<<24,	/* too many bytes from disk */
+	Aipms	= 1<<23,	/* incorrect prt mul status */
+	Aprcs	= 1<<22,	/* PhyRdy change status Pxserr.diag.n */
+	Adpms	= 1<<7,		/* mechanical presence status */
+	Apcs 	= 1<<6,		/* port connect  diag.x */
+	Adps 	= 1<<5,		/* descriptor processed */
+	Aufs 	= 1<<4,		/* unknown fis diag.f */
+	Asdbs	= 1<<3,		/* set device bits fis received w/ i bit set */
+	Adss	= 1<<2,		/* dma setup */
+	Apio	= 1<<1,		/* pio setup fis */
+	Adhrs	= 1<<0,		/* device to host register fis */
+
+	IEM	= Acpds|Atfes|Ahbds|Ahbfs|Ahbds|Aifs|Ainfs|Aprcs|Apcs|Adps|
+			Aufs|Asdbs|Adss|Adhrs,
+	Ifatal	= Atfes|Ahbfs|Ahbds|Aifs,
+};
+
+/* serror bits */
+enum {
+	SerrX	= 1<<26,	/* exchanged */
+	SerrF	= 1<<25,	/* unknown fis */
+	SerrT	= 1<<24,	/* transition error */
+	SerrS	= 1<<23,	/* link sequence */
+	SerrH	= 1<<22,	/* handshake */
+	SerrC	= 1<<21,	/* crc */
+	SerrD	= 1<<20,	/* not used by ahci */
+	SerrB	= 1<<19,	/* 10-tp-8 decode */
+	SerrW	= 1<<18,	/* comm wake */
+	SerrI	= 1<<17,	/* phy internal */
+	SerrN	= 1<<16,	/* phyrdy change */
+
+	ErrE	= 1<<11,	/* internal */
+	ErrP	= 1<<10,	/* ata protocol violation */
+	ErrC	= 1<<9,		/* communication */
+	ErrT	= 1<<8,		/* transient */
+	ErrM	= 1<<1,		/* recoverd comm */
+	ErrI	= 1<<0,		/* recovered data integrety */
+
+	ErrAll	= ErrE|ErrP|ErrC|ErrT|ErrM|ErrI,
+	SerrAll	= SerrX|SerrF|SerrT|SerrS|SerrH|SerrC|SerrD|SerrB|SerrW|
+			SerrI|SerrN|ErrAll,
+	SerrBad	= 0x7f<<19,
+};
+
+/* cmd register bits */
+enum {
+	Aicc	= 1<<28,	/* interface communcations control. 4 bits */
+	Aasp	= 1<<27,	/* agressive slumber & partial sleep */
+	Aalpe 	= 1<<26,	/* agressive link pm enable */
+	Adlae	= 1<<25,	/* drive led on atapi */
+	Aatapi	= 1<<24,	/* device is atapi */
+	Aesp	= 1<<21,	/* external sata port */
+	Acpd	= 1<<20,	/* cold presence detect */
+	Ampsp	= 1<<19,	/* mechanical pres. */
+	Ahpcp	= 1<<18,	/* hot plug capable */
+	Apma	= 1<<17,	/* pm attached */
+	Acps	= 1<<16,	/* cold presence state */
+	Acr	= 1<<15,	/* cmdlist running */
+	Afr	= 1<<14,	/* fis running */
+	Ampss	= 1<<13,	/* mechanical presence switch state */
+	Accs	= 1<<8,		/* current command slot 12:08 */
+	Afre	= 1<<4,		/* fis enable receive */
+	Aclo	= 1<<3,		/* command list override */
+	Apod	= 1<<2,		/* power on dev (requires cold-pres. detect) */
+	Asud	= 1<<1,		/* spin-up device;  requires ss capability */
+	Ast	= 1<<0,		/* start */
+
+	Arun	= Ast|Acr|Afre|Afr,
+};
+
+/* ctl register bits */
+enum {
+	Aipm	= 1<<8,		/* interface power mgmt. 3=off */
+	Aspd	= 1<<4,
+	Adet	= 1<<0,		/* device detection */
+};
+
+#define	sstatus	scr0
+#define	sctl	scr2
+#define	serror	scr1
+#define	sactive	scr3
+
+typedef struct {
+	ulong	list;		/* PxCLB must be 1kb aligned. */
+	ulong	listhi;
+	ulong	fis;		/* 256-byte aligned */
+	ulong	fishi;
+	ulong	isr;
+	ulong	ie;		/* interrupt enable */
+	ulong	cmd;
+	ulong	res1;
+	ulong	task;
+	ulong	sig;
+	ulong	scr0;
+	ulong	scr2;
+	ulong	scr1;
+	ulong	scr3;
+	ulong	ci;		/* command issue */
+	ulong	ntf;
+	uchar	res2[8];
+	ulong	vendor;
+} Aport;
+
+/* in host's memory; not memory mapped */
+typedef struct {
+	uchar	*base;
+	uchar	*d;
+	uchar	*p;
+	uchar	*r;
+	uchar	*u;
+	ulong	*devicebits;
+} Afis;
+
+enum {
+	Lprdtl	= 1<<16,	/* physical region descriptor table len */
+	Lpmp	= 1<<12,	/* port multiplier port */
+	Lclear	= 1<<10,	/* clear busy on R_OK */
+	Lbist	= 1<<9,
+	Lreset	= 1<<8,
+	Lpref	= 1<<7,		/* prefetchable */
+	Lwrite	= 1<<6,
+	Latapi	= 1<<5,
+	Lcfl	= 1<<0,		/* command fis length in double words */
+};
+
+/* in hosts memory; memory mapped */
+typedef struct {
+	ulong	flags;
+	ulong	len;
+	ulong	ctab;
+	ulong	ctabhi;
+	uchar	reserved[16];
+} Alist;
+
+typedef struct {
+	ulong	dba;
+	ulong	dbahi;
+	ulong	pad;
+	ulong	count;
+} Aprdt;
+
+typedef struct {
+	uchar	cfis[0x40];
+	uchar	atapi[0x10];
+	uchar	pad[0x30];
+	Aprdt	prdt;
+} Actab;
+
+enum {
+	Ferror	= 1,
+	Fdone	= 2,
+};
+
+enum {
+	Dllba 	= 1,
+	Dsmart	= 1<<1,
+	Dpower	= 1<<2,
+	Dnop	= 1<<3,
+	Datapi	= 1<<4,
+	Datapi16= 1<<5,
+};
+
+typedef struct {
+//	QLock;
+//	Rendez;
+	uchar	flag;
+	uchar	feat;
+	uchar	smart;
+	Afis	fis;
+	Alist	*list;
+	Actab	*ctab;
+} Aportm;
+
+typedef struct {
+	Aport	*p;
+	Aportm	*m;
+} Aportc;
--- /dev/null
+++ b/os/boot.original/pc/alarm.c
@@ -1,0 +1,123 @@
+#include	"u.h"
+#include	"lib.h"
+#include	"mem.h"
+#include	"dat.h"
+#include	"fns.h"
+#include	"io.h"
+#define	MAXALARM	10
+
+Alarm	alarmtab[MAXALARM];
+
+/*
+ * Insert new into list after where
+ */
+void
+insert(List **head, List *where, List *new)
+{
+	if(where == 0){
+		new->next = *head;
+		*head = new;
+	}else{
+		new->next = where->next;
+		where->next = new;
+	}
+		
+}
+
+/*
+ * Delete old from list.  where->next is known to be old.
+ */
+void
+delete(List **head, List *where, List *old)
+{
+	if(where == 0){
+		*head = old->next;
+		return;
+	}
+	where->next = old->next;
+}
+
+Alarm*
+newalarm(void)
+{
+	int i;
+	Alarm *a;
+
+	for(i=0,a=alarmtab; i < nelem(alarmtab); i++,a++)
+		if(a->busy==0 && a->f==0){
+			a->f = 0;
+			a->arg = 0;
+			a->busy = 1;
+			return a;
+		}
+	panic("newalarm");
+	return 0;	/* not reached */
+}
+
+Alarm*
+alarm(int ms, void (*f)(Alarm*), void *arg)
+{
+	Alarm *a, *w, *pw;
+	ulong s;
+
+	if(ms < 0)
+		ms = 0;
+	s = splhi();
+	a = newalarm();
+	a->dt = MS2TK(ms);
+	a->f = f;
+	a->arg = arg;
+	pw = 0;
+	for(w=m->alarm; w; pw=w, w=w->next){
+		if(w->dt <= a->dt){
+			a->dt -= w->dt;
+			continue;
+		}
+		w->dt -= a->dt;
+		break;
+	}
+	insert(&m->alarm, pw, a);
+	splx(s);
+	return a;
+}
+
+void
+cancel(Alarm *a)
+{
+	a->f = 0;
+}
+
+void
+alarminit(void)
+{
+}
+
+#define NA 10		/* alarms per clock tick */
+void
+checkalarms(void)
+{
+	int i, n, s;
+	Alarm *a;
+	void (*f)(Alarm*);
+	Alarm *alist[NA];
+
+	s = splhi();
+	a = m->alarm;
+	if(a){
+		for(n=0; a && a->dt<=0 && n<NA; n++){
+			alist[n] = a;
+			delete(&m->alarm, 0, a);
+			a = m->alarm;
+		}
+		if(a)
+			a->dt--;
+
+		for(i = 0; i < n; i++){
+			f = alist[i]->f;	/* avoid race with cancel */
+			if(f)
+				(*f)(alist[i]);
+			alist[i]->busy = 0;
+		}
+	}
+	splx(s);
+}
--- /dev/null
+++ b/os/boot.original/pc/aoe.h
@@ -1,0 +1,76 @@
+/*
+ * ATA-over-Ethernet
+ */
+enum {
+	ACata,
+	ACconfig,
+};
+
+enum {
+	AQCread,
+	AQCtest,
+	AQCprefix,
+	AQCset,
+	AQCfset,
+};
+
+enum {
+	AEcmd	= 1,
+	AEarg,
+	AEdev,
+	AEcfg,
+	AEver,
+};
+
+enum {
+	Aoetype	= 0x88a2,
+	Aoever	= 1,
+
+	AFerr	= 1<<2,
+	AFrsp	= 1<<3,
+
+	AAFwrite= 1,
+	AAFext	= 1<<6,
+};
+
+enum {
+	Crd	= 0x20,
+	Crdext	= 0x24,
+	Cwr	= 0x30,
+	Cwrext	= 0x34,
+	Cid	= 0xec,
+};
+
+typedef struct {
+	uchar	dst[Eaddrlen];
+	uchar	src[Eaddrlen];
+	uchar	type[2];
+	uchar	verflag;
+	uchar	error;
+	uchar	major[2];
+	uchar	minor;
+	uchar	cmd;
+	uchar	tag[4];
+} Aoehdr;
+
+typedef struct {
+	Aoehdr;
+	uchar	aflag;
+	uchar	errfeat;
+	uchar	scnt;
+	uchar	cmdstat;
+	uchar	lba[6];
+	uchar	res[2];
+} Aoeata;
+
+typedef struct {
+	Aoehdr;
+	uchar	bufcnt[2];
+	uchar	fwver[2];
+	uchar	scnt;
+	uchar	verccmd;
+	uchar	cslen[2];
+} Aoeqc;
+
+extern char Echange[];
+extern char Enotup[];
--- /dev/null
+++ b/os/boot.original/pc/apm.c
@@ -1,0 +1,16 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+Apminfo apm;
+
+void
+apminit(void)
+{
+	if(getconf("apm0") && apm.haveinfo)
+		changeconf("apm0=ax=%x ebx=%x cx=%x dx=%x di=%x esi=%x\n",
+			apm.ax, apm.ebx, apm.cx, apm.dx, apm.di, apm.esi);
+}
--- /dev/null
+++ b/os/boot.original/pc/bcom.c
@@ -1,0 +1,463 @@
+/*
+ * ld - DOS boot loader of Plan 9
+ */
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+#include "fs.h"
+
+Type types[] = {
+	{	Tfloppy,
+		Fini|Ffs,
+		floppyinit, floppyinitdev,
+		floppygetfspart, 0, floppyboot,
+	},
+	{	Tsd,
+		Fini|Ffs,
+		sdinit, sdinitdev,
+		sdgetfspart, sdaddconf, sdboot,
+	},
+	{	Tnil,
+		0,
+		0, 0,
+		0, 0, 0,
+	},
+};
+
+#include "sd.h"
+
+extern SDifc sdataifc;
+extern SDifc sdmylexifc;
+extern SDifc sd53c8xxifc;
+SDifc* sdifc[] = {
+	&sdataifc,
+//	&sdmylexifc,
+//	&sd53c8xxifc,
+	nil,
+};
+
+typedef struct Mode Mode;
+
+enum {
+	Maxdev		= 7,
+	Dany		= -1,
+	Nmedia		= 16,
+	Nini		= 10,
+};
+
+enum {					/* mode */
+	Mauto		= 0x00,
+	Mlocal		= 0x01,
+	Manual		= 0x02,
+	NMode		= 0x03,
+};
+
+typedef struct Medium Medium;
+struct Medium {
+	Type*	type;
+	int	flag;
+	int	dev;
+	char name[NAMELEN];
+	Fs*	inifs;
+
+	Medium*	next;
+};
+
+typedef struct Mode {
+	char*	name;
+	int	mode;
+} Mode;
+
+static Medium media[Nmedia];
+static Medium *curmedium = media;
+
+static Mode modes[NMode+1] = {
+	[Mauto]		{ "auto",   Mauto,  },
+	[Mlocal]	{ "local",  Mlocal, },
+	[Manual]	{ "manual", Manual, },
+};
+
+char *defaultpartition = "new";
+
+static Medium*
+parse(char *line, char **file)
+{
+	char *p;
+	Type *tp;
+	Medium *mp;
+
+	if(p = strchr(line, '!')) {
+		*p++ = 0;
+		*file = p;
+	} else
+		*file = "";
+
+	for(tp = types; tp->type != Tnil; tp++)
+		for(mp = tp->media; mp; mp = mp->next)
+			if(strcmp(mp->name, line) == 0)
+				return mp;
+	return nil;
+}
+
+static int
+boot(Medium *mp, char *file)
+{
+	static Boot b;
+
+	memset(&b, 0, sizeof b);
+	b.state = INIT9LOAD;
+
+//	sprint(BOOTLINE, "%s!%s", mp->name, file);
+	return (*mp->type->boot)(mp->dev, file, &b);
+}
+
+static Medium*
+allocm(Type *tp)
+{
+	Medium **l;
+
+	if(curmedium >= &media[Nmedia])
+		return 0;
+
+	for(l = &tp->media; *l; l = &(*l)->next)
+		;
+	*l = curmedium++;
+	return *l;
+}
+
+char *parts[] = { "dos", "9fat", "fs", 0 };
+
+Medium*
+probe(int type, int flag, int dev)
+{
+	Type *tp;
+	int i;
+	Medium *mp;
+
+	for(tp = types; tp->type != Tnil; tp++){
+		if(type != Tany && type != tp->type)
+			continue;
+
+		if(flag != Fnone){
+			for(mp = tp->media; mp; mp = mp->next){
+				if((flag & mp->flag) && (dev == Dany || dev == mp->dev))
+					return mp;
+			}
+		}
+
+		if((tp->flag & Fprobe) == 0){
+			tp->flag |= Fprobe;
+			tp->mask = (*tp->init)();
+		}
+
+		for(i = 0; tp->mask; i++){
+			if((tp->mask & (1<<i)) == 0)
+				continue;
+			tp->mask &= ~(1<<i);
+
+			if((mp = allocm(tp)) == 0)
+				continue;
+
+			mp->dev = i;
+			mp->flag = tp->flag;
+			mp->type = tp;
+			(*tp->initdev)(i, mp->name);
+
+			if((flag & mp->flag) && (dev == Dany || dev == i))
+				return mp;
+		}
+	}
+
+	return 0;
+}
+
+extern int loopconst;
+void
+main(void)
+{
+	Medium *mp;
+	int flag;
+	char def[2*NAMELEN], line[80], *p, *file;
+	Type *tp;
+
+	i8042a20();
+	memset(m, 0, sizeof(Mach));
+	trapinit();
+	clockinit();
+	alarminit();
+	spllo();
+
+	kbdinit();
+	
+	if((ulong)&end > (KZERO|(640*1024)))
+		panic("i'm too big");
+
+	/*
+	 * If there were any arguments, MS-DOS leaves a character
+	 * count followed by the arguments in the runtime header.
+	 * Step over the leading space.
+	 */
+	p = (char*)0x80080080;
+	if(p[0]){
+		p[p[0]+1] = 0;
+		p += 2;
+	}
+	else
+		p = 0;
+
+	/*
+	 * Advance command line to first option, if any
+	 */
+	if(p) {
+		while(*p==' ' || *p=='\t')
+			p++;
+		if(*p == 0)
+			p = nil;
+	}
+
+	/*
+ 	 * Probe everything, to collect device names.
+	 */
+	probe(Tany, Fnone, Dany);
+
+	if(p != 0) {
+		if((mp = parse(p, &file)) == nil) {
+			print("bad loadfile syntax: %s\n", p);
+			goto done;
+		}
+		boot(mp, file);
+	}
+
+done:
+	flag = 0;
+	for(tp = types; tp->type != Tnil; tp++){
+		for(mp = tp->media; mp; mp = mp->next){
+			if(flag == 0){
+				flag = 1;
+				print("Load devices:");
+			}
+			print(" %s", mp->name);
+		}
+	}
+	if(flag)
+		print("\n");
+
+	for(;;){
+		if(getstr("load from", line, sizeof(line), nil, 0) >= 0)
+			if(mp = parse(line, &file))
+				boot(mp, file);
+		def[0] = 0;
+	}
+}
+
+int
+getfields(char *lp, char **fields, int n, char sep)
+{
+	int i;
+
+	for(i = 0; lp && *lp && i < n; i++){
+		while(*lp == sep)
+			*lp++ = 0;
+		if(*lp == 0)
+			break;
+		fields[i] = lp;
+		while(*lp && *lp != sep){
+			if(*lp == '\\' && *(lp+1) == '\n')
+				*lp++ = ' ';
+			lp++;
+		}
+	}
+	return i;
+}
+
+int
+cistrcmp(char *a, char *b)
+{
+	int ac, bc;
+
+	for(;;){
+		ac = *a++;
+		bc = *b++;
+	
+		if(ac >= 'A' && ac <= 'Z')
+			ac = 'a' + (ac - 'A');
+		if(bc >= 'A' && bc <= 'Z')
+			bc = 'a' + (bc - 'A');
+		ac -= bc;
+		if(ac)
+			return ac;
+		if(bc == 0)
+			break;
+	}
+	return 0;
+}
+
+int
+cistrncmp(char *a, char *b, int n)
+{
+	unsigned ac, bc;
+
+	while(n > 0){
+		ac = *a++;
+		bc = *b++;
+		n--;
+
+		if(ac >= 'A' && ac <= 'Z')
+			ac = 'a' + (ac - 'A');
+		if(bc >= 'A' && bc <= 'Z')
+			bc = 'a' + (bc - 'A');
+
+		ac -= bc;
+		if(ac)
+			return ac;
+		if(bc == 0)
+			break;
+	}
+
+	return 0;
+}
+
+void*
+ialloc(ulong n, int align)
+{
+
+	static ulong palloc;
+	ulong p;
+	int a;
+
+	if(palloc == 0)
+		palloc = 3*1024*1024;
+
+	p = palloc;
+	if(align <= 0)
+		align = 4;
+	if(a = n % align)
+		n += align - a;
+	if(a = p % align)
+		p += align - a;
+
+	palloc = p+n;
+
+	return memset((void*)(p|KZERO), 0, n);
+}
+
+void*
+xspanalloc(ulong size, int align, ulong span)
+{
+	ulong a, v;
+
+	a = (ulong)ialloc(size+align+span, 0);
+
+	if(span > 2)
+		v = (a + span) & ~(span-1);
+	else
+		v = a;
+
+	if(align > 1)
+		v = (v + align) & ~(align-1);
+
+	return (void*)v;
+}
+
+static Block *allocbp;
+
+Block*
+allocb(int size)
+{
+	Block *bp, **lbp;
+	ulong addr;
+
+	lbp = &allocbp;
+	for(bp = *lbp; bp; bp = bp->next){
+		if((bp->lim - bp->base) >= size){
+			*lbp = bp->next;
+			break;
+		}
+		lbp = &bp->next;
+	}
+	if(bp == 0){
+		bp = ialloc(sizeof(Block)+size+64, 0);
+		addr = (ulong)bp;
+		addr = ROUNDUP(addr + sizeof(Block), 8);
+		bp->base = (uchar*)addr;
+		bp->lim = ((uchar*)bp) + sizeof(Block)+size+64;
+	}
+
+	if(bp->flag)
+		panic("allocb reuse\n");
+
+	bp->rp = bp->base;
+	bp->wp = bp->rp;
+	bp->next = 0;
+	bp->flag = 1;
+
+	return bp;
+}
+
+void
+freeb(Block* bp)
+{
+	bp->next = allocbp;
+	allocbp = bp;
+
+	bp->flag = 0;
+}
+
+enum {
+	Paddr=		0x70,	/* address port */
+	Pdata=		0x71,	/* data port */
+};
+
+uchar
+nvramread(int offset)
+{
+	outb(Paddr, offset);
+	return inb(Pdata);
+}
+
+void (*etherdetach)(void);
+void (*floppydetach)(void);
+void (*sddetach)(void);
+
+void
+warp9(ulong entry)
+{
+	if(etherdetach)
+		etherdetach();
+	consdrain();
+	(*(void(*)(void))(PADDR(entry)))();
+}
+
+char*
+getconf(char*)
+{
+	return nil;
+}
+
+void
+addconf(char*, ...)
+{
+}
+
+void
+uartspecial(int, void(*)(int), int(*)(void), int)
+{
+}
+
+void
+uartputs(IOQ*, char*, int)
+{
+}
+
+void
+uartputc(int)
+{}
+
+void
+uartdrain(void)
+{
+}
--- /dev/null
+++ b/os/boot.original/pc/boot.c
@@ -1,0 +1,451 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+#include "../../../utils/libmach/elf.h"
+
+static uchar elfident[7] = {
+	'\177', 'E', 'L', 'F', '\1', '\1', '\1'
+};
+static Ehdr ehdr, rehdr;
+static Phdr *phdr;
+static int curphdr;
+static ulong curoff;
+static ulong elftotal;
+static long (*swal)(long);
+static ushort (*swab)(ushort);
+
+/*
+ * big-endian short
+ */
+ushort
+beswab(ushort s)
+{
+	uchar *p;
+
+	p = (uchar*)&s;
+	return (p[0]<<8) | p[1];
+}
+
+/*
+ * big-endian long
+ */
+long
+beswal(long l)
+{
+	uchar *p;
+
+	p = (uchar*)&l;
+	return (p[0]<<24) | (p[1]<<16) | (p[2]<<8) | p[3];
+}
+
+/*
+ * little-endian short
+ */
+ushort
+leswab(ushort s)
+{
+	uchar *p;
+
+	p = (uchar*)&s;
+	return (p[1]<<8) | p[0];
+}
+
+/*
+ * little-endian long
+ */
+long
+leswal(long l)
+{
+	uchar *p;
+
+	p = (uchar*)&l;
+	return (p[3]<<24) | (p[2]<<16) | (p[1]<<8) | p[0];
+}
+
+/*
+ * Convert header to canonical form
+ */
+static void
+hswal(long *lp, int n, long (*swap) (long))
+{
+	while (n--) {
+		*lp = (*swap) (*lp);
+		lp++;
+	}
+}
+
+static int
+readehdr(Boot *b)
+{
+	int i;
+
+	/* bitswap the header according to the DATA format */
+	if(ehdr.ident[CLASS] != ELFCLASS32) {
+		print("bad ELF class - not 32 bit\n");
+		return 0;
+	}
+	if(ehdr.ident[DATA] == ELFDATA2LSB) {
+		swab = leswab;
+		swal = leswal;
+	} else if(ehdr.ident[DATA] == ELFDATA2MSB) {
+		swab = beswab;
+		swal = beswal;
+	} else {
+		print("bad ELF encoding - not big or little endian\n");
+		return 0;
+	}
+	memmove(&rehdr, &ehdr, sizeof(Ehdr));
+
+	ehdr.type = swab(ehdr.type);
+	ehdr.machine = swab(ehdr.machine);
+	ehdr.version = swal(ehdr.version);
+	ehdr.elfentry = swal(ehdr.elfentry);
+	ehdr.phoff = swal(ehdr.phoff);
+	ehdr.shoff = swal(ehdr.shoff);
+	ehdr.flags = swal(ehdr.flags);
+	ehdr.ehsize = swab(ehdr.ehsize);
+	ehdr.phentsize = swab(ehdr.phentsize);
+	ehdr.phnum = swab(ehdr.phnum);
+	ehdr.shentsize = swab(ehdr.shentsize);
+	ehdr.shnum = swab(ehdr.shnum);
+	ehdr.shstrndx = swab(ehdr.shstrndx);
+	if(ehdr.type != EXEC || ehdr.version != CURRENT)
+		return 0;
+	if(ehdr.phentsize != sizeof(Phdr))
+		return 0;
+
+	if(debug)
+		print("readehdr OK entry 0x%lux\n", ehdr.elfentry);
+
+	curoff = sizeof(Ehdr);
+	i = ehdr.phoff+ehdr.phentsize*ehdr.phnum - curoff;
+	b->state = READPHDR;
+	b->bp = (char*)malloc(i);
+	b->wp = b->bp;
+	b->ep = b->wp + i;
+	phdr = (Phdr*)(b->bp + ehdr.phoff-sizeof(Ehdr));
+	if(debug)
+		print("phdr...");
+
+	return 1;
+}
+
+static int
+nextphdr(Boot *b)
+{
+	Phdr *php;
+	ulong entry, offset;
+	char *paddr;
+
+	if(debug)
+		print("readedata %d\n", curphdr);
+
+	for(; curphdr < ehdr.phnum; curphdr++){
+		php = phdr+curphdr;
+		if(php->type != LOAD)
+			continue;
+		offset = php->offset;
+		paddr = (char*)PADDR(php->paddr);
+		if(offset < curoff){
+			/*
+			 * Can't (be bothered to) rewind the
+			 * input, it might be from tftp. If we
+			 * did then we could boot FreeBSD kernels
+			 * too maybe.
+			 */
+			return 0;
+		}
+		if(php->offset > curoff){
+			b->state = READEPAD;
+			b->bp = (char*)malloc(offset - curoff);
+			b->wp = b->bp;
+			b->ep = b->wp + offset - curoff;
+			if(debug)
+				print("nextphdr %lud...\n", offset - curoff);
+			return 1;
+		}
+		b->state = READEDATA;
+		b->bp = paddr;
+		b->wp = b->bp;
+		b->ep = b->wp+php->filesz;
+		print("%ud+", php->filesz);
+		elftotal += php->filesz;
+		if(debug)
+			print("nextphdr %ud@0x%p\n", php->filesz, paddr);
+
+		return 1;
+	}
+
+	if(curphdr != 0){
+		print("=%lud\n", elftotal);
+		b->state = TRYBOOT;
+		entry = ehdr.elfentry & ~0xF0000000;
+		PLLONG(b->exec.entry, entry);
+		return 1;
+	}
+
+	return 0;
+}
+
+static int
+readepad(Boot *b)
+{
+	Phdr *php;
+
+	php = phdr+curphdr;
+	if(debug)
+		print("readepad %d\n", curphdr);
+	curoff = php->offset;
+
+	return nextphdr(b);
+}
+
+static int
+readedata(Boot *b)
+{
+	Phdr *php;
+
+	php = phdr+curphdr;
+	if(debug)
+		print("readedata %d\n", curphdr);
+	if(php->filesz < php->memsz){
+		print("%lud",  php->memsz-php->filesz);
+		elftotal += php->memsz-php->filesz;
+		memset((char*)(PADDR(php->paddr)+php->filesz), 0, php->memsz-php->filesz);
+	}
+	curoff = php->offset+php->filesz;
+	curphdr++;
+
+	return nextphdr(b);
+}
+
+static int
+readphdr(Boot *b)
+{
+	Phdr *php;
+
+	php = phdr;
+	hswal((long*)php, ehdr.phentsize*ehdr.phnum/sizeof(long), swal);
+	if(debug)
+		print("phdr curoff %lud vaddr 0x%lux paddr 0x%lux\n",
+			curoff, php->vaddr, php->paddr);
+
+	curoff = ehdr.phoff+ehdr.phentsize*ehdr.phnum;
+	curphdr = 0;
+
+	return nextphdr(b);
+}
+
+static int
+addbytes(char **dbuf, char *edbuf, char **sbuf, char *esbuf)
+{
+	int n;
+
+	n = edbuf - *dbuf;
+	if(n <= 0)
+		return 0;
+	if(n > esbuf - *sbuf)
+		n = esbuf - *sbuf;
+	if(n <= 0)
+		return -1;
+
+	memmove(*dbuf, *sbuf, n);
+	*sbuf += n;
+	*dbuf += n;
+	return edbuf - *dbuf;
+}
+
+int
+bootpass(Boot *b, void *vbuf, int nbuf)
+{
+	char *buf, *ebuf;
+	Exec *ep;
+	ulong entry, data, text, bss;
+
+	if(b->state == FAILED)
+		return FAIL;
+
+	if(nbuf == 0)
+		goto Endofinput;
+
+	buf = vbuf;
+	ebuf = buf+nbuf;
+	while(addbytes(&b->wp, b->ep, &buf, ebuf) == 0) {
+		switch(b->state) {
+		case INITKERNEL:
+			b->state = READEXEC;
+			b->bp = (char*)&b->exec;
+			b->wp = b->bp;
+			b->ep = b->bp+sizeof(Exec);
+			break;
+		case READEXEC:
+			ep = &b->exec;
+			if(GLLONG(ep->magic) == I_MAGIC) {
+				b->state = READ9TEXT;
+				b->bp = (char*)PADDR(GLLONG(ep->entry));
+				b->wp = b->bp;
+				b->ep = b->wp+GLLONG(ep->text);
+				print("%lud", GLLONG(ep->text));
+				break;
+			}
+
+			/* check for gzipped kernel */
+			if(b->bp[0] == 0x1F && (uchar)b->bp[1] == 0x8B && b->bp[2] == 0x08) {
+				b->state = READGZIP;
+				b->bp = (char*)malloc(1440*1024);
+				b->wp = b->bp;
+				b->ep = b->wp + 1440*1024;
+				memmove(b->bp, &b->exec, sizeof(Exec));
+				b->wp += sizeof(Exec);
+				print("gz...");
+				break;
+			}
+
+			/*
+			 * Check for ELF.
+			 */
+			if(memcmp(b->bp, elfident, 4) == 0){
+				b->state = READEHDR;
+				b->bp = (char*)&ehdr;
+				b->wp = b->bp;
+				b->ep = b->wp + sizeof(Ehdr);
+				memmove(b->bp, &b->exec, sizeof(Exec));
+				b->wp += sizeof(Exec);
+				print("elf...");
+				break;
+			}
+
+			print("bad kernel format\n");
+			b->state = FAILED;
+			return FAIL;
+
+		case READ9TEXT:
+			ep = &b->exec;
+			b->state = READ9DATA;
+			b->bp = (char*)PGROUND(PADDR(GLLONG(ep->entry))+GLLONG(ep->text));
+			b->wp = b->bp;
+			b->ep = b->wp + GLLONG(ep->data);
+			print("+%ld", GLLONG(ep->data));
+			break;
+	
+		case READ9DATA:
+			ep = &b->exec;
+			bss = GLLONG(ep->bss);
+			print("+%ld=%ld\n",
+				bss, GLLONG(ep->text)+GLLONG(ep->data)+bss);
+			b->state = TRYBOOT;
+			return ENOUGH;
+
+		case READEHDR:
+			if(!readehdr(b)){
+				print("readehdr failed\n");
+				b->state = FAILED;
+				return FAIL;
+			}
+			break;
+
+		case READPHDR:
+			if(!readphdr(b)){
+				b->state = FAILED;
+				return FAIL;
+			}
+			break;
+
+		case READEPAD:
+			if(!readepad(b)){
+				b->state = FAILED;
+				return FAIL;
+			}
+			break;
+
+		case READEDATA:
+			if(!readedata(b)){
+				b->state = FAILED;
+				return FAIL;
+			}
+			if(b->state == TRYBOOT)
+				return ENOUGH;
+			break;
+
+		case TRYBOOT:
+		case READGZIP:
+			return ENOUGH;
+
+		case READ9LOAD:
+		case INIT9LOAD:
+			panic("9load");
+
+		default:
+			panic("bootstate");
+		}
+	}
+	return MORE;
+
+
+Endofinput:
+	/* end of input */
+	switch(b->state) {
+	case INITKERNEL:
+	case READEXEC:
+	case READ9TEXT:
+	case READ9DATA:
+	case READEHDR:
+	case READPHDR:
+	case READEPAD:
+	case READEDATA:
+		print("premature EOF\n");
+		b->state = FAILED;
+		return FAIL;
+	
+	case TRYBOOT:
+		entry = GLLONG(b->exec.entry);
+		print("entry: 0x%lux\n", entry);
+		warp9(PADDR(entry));
+		b->state = FAILED;
+		return FAIL;
+
+	case READGZIP:
+		ep = &b->exec;
+		if(b->bp[0] != 0x1F || (uchar)b->bp[1] != 0x8B || b->bp[2] != 0x08)
+			print("lost magic\n");
+
+		print("%ld => ", b->wp - b->bp);
+		if(gunzip((uchar*)ep, sizeof(*ep), (uchar*)b->bp, b->wp - b->bp) < sizeof(*ep)) {
+			print("badly compressed kernel\n");
+			return FAIL;
+		}
+
+		entry = GLLONG(ep->entry);
+		text = GLLONG(ep->text);
+		data = GLLONG(ep->data);
+		bss = GLLONG(ep->bss);
+		print("%lud+%lud+%lud=%lud\n", text, data, bss, text+data+bss);
+
+		if(gunzip((uchar*)PADDR(entry)-sizeof(Exec), sizeof(Exec)+text+data, 
+		     (uchar*)b->bp, b->wp-b->bp) < sizeof(Exec)+text+data) {
+			print("error uncompressing kernel\n");
+			return FAIL;
+		}
+
+		/* relocate data to start at page boundary */
+		memmove((void*)PGROUND(PADDR(entry+text)), (void*)(PADDR(entry+text)), data);
+
+		print("entry: %lux\n", entry);
+		warp9(PADDR(entry));
+		b->state = FAILED;
+		return FAIL;
+
+	case INIT9LOAD:
+	case READ9LOAD:
+		panic("end 9load");
+
+	default:
+		panic("bootdone");
+	}
+	b->state = FAILED;
+	return FAIL;
+}
--- /dev/null
+++ b/os/boot.original/pc/bootld.c
@@ -1,0 +1,108 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+static int
+addbytes(char **dbuf, char *edbuf, char **sbuf, char *esbuf)
+{
+	int n;
+
+	n = edbuf - *dbuf;
+	if(n <= 0)
+		return 0;
+	if(n > esbuf - *sbuf)
+		n = esbuf - *sbuf;
+	if(n <= 0)
+		return -1;
+
+	memmove(*dbuf, *sbuf, n);
+	*sbuf += n;
+	*dbuf += n;
+	return edbuf - *dbuf;
+}
+
+extern void origin(void);
+
+int
+bootpass(Boot *b, void *vbuf, int nbuf)
+{
+	char *buf, *ebuf, *p, *q;
+	ulong size;
+
+	if(b->state == FAILED)
+		return FAIL;
+
+	if(nbuf == 0)
+		goto Endofinput;
+
+	buf = vbuf;
+	ebuf = buf+nbuf;
+	while(addbytes(&b->wp, b->ep, &buf, ebuf) == 0) {
+		switch(b->state) {
+		case INIT9LOAD:
+			b->state = READ9LOAD;
+			b->bp = (char*)0x10000;
+			b->wp = b->bp;
+			b->ep = b->bp + 256*1024;
+			break;
+
+		case READ9LOAD:
+			return ENOUGH;
+
+		default:
+			panic("bootstate");
+		}
+	}
+	return MORE;
+
+
+Endofinput:
+	/* end of input */
+	print("\n");
+	switch(b->state) {
+	case INIT9LOAD:
+		print("premature EOF\n");
+		b->state = FAILED;
+		return FAIL;
+	
+	case READ9LOAD:
+		size = b->wp - b->bp;
+		if(memcmp(b->bp, origin, 16) != 0) {
+			print("beginning of file does not look right\n");
+			b->state = FAILED;
+			return FAIL;
+		}
+		if(size < 32*1024 || size > 256*1024) {
+			print("got %lud byte loader; not likely\n", size);
+			b->state = FAILED;
+			return FAIL;
+		}
+
+		p = b->bp;
+		q = b->wp;
+		if(q - p > 10000)	/* don't search much past l.s */
+			q = p+10000;
+
+		/*
+		 * The string `JUMP' appears right before
+		 * tokzero, which is where we want to jump.
+		 */
+		for(; p<q; p++) {
+			if(strncmp(p, "JUMP", 4) == 0) {
+				p += 4;
+				warp9((ulong)p);
+			}
+		}
+		print("could not find jump destination\n");
+		b->state = FAILED;
+		return FAIL;
+
+	default:
+		panic("bootdone");
+	}
+	b->state = FAILED;
+	return FAIL;
+}
--- /dev/null
+++ b/os/boot.original/pc/bootp.c
@@ -1,0 +1,659 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+#include "ip.h"
+
+extern int debugload;
+
+uchar broadcast[Eaddrlen] = {
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+};
+
+static ushort tftpport = 5000;
+static int Id = 1;
+static Netaddr myaddr;
+static Netaddr server;
+
+typedef struct {
+	uchar	header[4];
+	uchar	data[Segsize];
+} Tftp;
+static Tftp tftpb;
+
+static void
+hnputs(uchar *ptr, ushort val)
+{
+	ptr[0] = val>>8;
+	ptr[1] = val;
+}
+
+static void
+hnputl(uchar *ptr, ulong val)
+{
+	ptr[0] = val>>24;
+	ptr[1] = val>>16;
+	ptr[2] = val>>8;
+	ptr[3] = val;
+}
+
+static ulong
+nhgetl(uchar *ptr)
+{
+	return ((ptr[0]<<24) | (ptr[1]<<16) | (ptr[2]<<8) | ptr[3]);
+}
+
+static ushort
+nhgets(uchar *ptr)
+{
+	return ((ptr[0]<<8) | ptr[1]);
+}
+
+static	short	endian	= 1;
+static	char*	aendian	= (char*)&endian;
+#define	LITTLE	*aendian
+
+static ushort
+ptcl_csum(void *a, int len)
+{
+	uchar *addr;
+	ulong t1, t2;
+	ulong losum, hisum, mdsum, x;
+
+	addr = a;
+	losum = 0;
+	hisum = 0;
+	mdsum = 0;
+
+	x = 0;
+	if((ulong)addr & 1) {
+		if(len) {
+			hisum += addr[0];
+			len--;
+			addr++;
+		}
+		x = 1;
+	}
+	while(len >= 16) {
+		t1 = *(ushort*)(addr+0);
+		t2 = *(ushort*)(addr+2);	mdsum += t1;
+		t1 = *(ushort*)(addr+4);	mdsum += t2;
+		t2 = *(ushort*)(addr+6);	mdsum += t1;
+		t1 = *(ushort*)(addr+8);	mdsum += t2;
+		t2 = *(ushort*)(addr+10);	mdsum += t1;
+		t1 = *(ushort*)(addr+12);	mdsum += t2;
+		t2 = *(ushort*)(addr+14);	mdsum += t1;
+		mdsum += t2;
+		len -= 16;
+		addr += 16;
+	}
+	while(len >= 2) {
+		mdsum += *(ushort*)addr;
+		len -= 2;
+		addr += 2;
+	}
+	if(x) {
+		if(len)
+			losum += addr[0];
+		if(LITTLE)
+			losum += mdsum;
+		else
+			hisum += mdsum;
+	} else {
+		if(len)
+			hisum += addr[0];
+		if(LITTLE)
+			hisum += mdsum;
+		else
+			losum += mdsum;
+	}
+
+	losum += hisum >> 8;
+	losum += (hisum & 0xff) << 8;
+	while(hisum = losum>>16)
+		losum = hisum + (losum & 0xffff);
+
+	return ~losum;
+}
+
+static ushort
+ip_csum(uchar *addr)
+{
+	int len;
+	ulong sum = 0;
+
+	len = (addr[0]&0xf)<<2;
+
+	while(len > 0) {
+		sum += addr[0]<<8 | addr[1] ;
+		len -= 2;
+		addr += 2;
+	}
+
+	sum = (sum & 0xffff) + (sum >> 16);
+	sum = (sum & 0xffff) + (sum >> 16);
+	return (sum^0xffff);
+}
+
+enum {
+	/* this is only true of IPv4, but we're not doing v6 yet */
+	Min_udp_payload = ETHERMINTU - ETHERHDRSIZE - UDP_HDRSIZE,
+};
+
+static void
+udpsend(int ctlrno, Netaddr *a, void *data, int dlen)
+{
+	char payload[ETHERMAXTU];
+	Udphdr *uh;
+	Etherhdr *ip;
+	Etherpkt pkt;
+	int len, ptcllen;
+
+	/*
+	 * if packet is too short, make it longer rather than relying
+	 * on ethernet interface or lower layers to pad it.
+	 */
+	if (dlen < Min_udp_payload) {
+		memmove(payload, data, dlen);
+		data = payload;
+		dlen = Min_udp_payload;
+	}
+
+	uh = (Udphdr*)&pkt;
+
+	memset(uh, 0, sizeof(Etherpkt));
+	memmove(uh->udpcksum+sizeof(uh->udpcksum), data, dlen);
+
+	/*
+	 * UDP portion
+	 */
+	ptcllen = dlen + (UDP_HDRSIZE-UDP_PHDRSIZE);
+	uh->ttl = 0;
+	uh->udpproto = IP_UDPPROTO;
+	uh->frag[0] = 0;
+	uh->frag[1] = 0;
+	hnputs(uh->udpplen, ptcllen);
+	hnputl(uh->udpsrc, myaddr.ip);
+	hnputs(uh->udpsport, myaddr.port);
+	hnputl(uh->udpdst, a->ip);
+	hnputs(uh->udpdport, a->port);
+	hnputs(uh->udplen, ptcllen);
+	uh->udpcksum[0] = 0;
+	uh->udpcksum[1] = 0;
+	dlen = (dlen+1)&~1;
+	hnputs(uh->udpcksum, ptcl_csum(&uh->ttl, dlen+UDP_HDRSIZE));
+
+	/*
+	 * IP portion
+	 */
+	ip = (Etherhdr*)&pkt;
+	len = UDP_EHSIZE+UDP_HDRSIZE+dlen;		/* non-descriptive names */
+	ip->vihl = IP_VER|IP_HLEN;
+	ip->tos = 0;
+	ip->ttl = 255;
+	hnputs(ip->length, len-ETHER_HDR);
+	hnputs(ip->id, Id++);
+	ip->frag[0] = 0;
+	ip->frag[1] = 0;
+	ip->cksum[0] = 0;
+	ip->cksum[1] = 0;
+	hnputs(ip->cksum, ip_csum(&ip->vihl));
+
+	/*
+	 * Ethernet MAC portion
+	 */
+	hnputs(ip->type, ET_IP);
+	memmove(ip->d, a->ea, sizeof(ip->d));
+
+if(debug) {
+	print("udpsend ");
+}
+	ethertxpkt(ctlrno, &pkt, len, Timeout);
+}
+
+static void
+nak(int ctlrno, Netaddr *a, int code, char *msg, int report)
+{
+	int n;
+	char buf[128];
+
+	buf[0] = 0;
+	buf[1] = Tftp_ERROR;
+	buf[2] = 0;
+	buf[3] = code;
+	strcpy(buf+4, msg);
+	n = strlen(msg) + 4 + 1;
+	udpsend(ctlrno, a, buf, n);
+	if(report)
+		print("\ntftp: error(%d): %s\n", code, msg);
+}
+
+static int
+udprecv(int ctlrno, Netaddr *a, void *data, int dlen)
+{
+	int n, len;
+	ushort csm;
+	Udphdr *h;
+	ulong addr, timo;
+	Etherpkt pkt;
+	static int rxactive;
+
+	if(rxactive == 0)
+		timo = 1000;
+	else
+		timo = Timeout;
+	timo += TK2MS(m->ticks);
+	while(timo > TK2MS(m->ticks)){
+		n = etherrxpkt(ctlrno, &pkt, timo-TK2MS(m->ticks));
+		if(n <= 0)
+			continue;
+
+		h = (Udphdr*)&pkt;
+		if(debug)
+			print("udprecv %E to %E...\n", h->s, h->d);
+
+		if(nhgets(h->type) != ET_IP) {
+			if(debug)
+				print("not ip...");
+			continue;
+		}
+
+		if(ip_csum(&h->vihl)) {
+			print("ip chksum error\n");
+			continue;
+		}
+		if(h->vihl != (IP_VER|IP_HLEN)) {
+			print("ip bad vers/hlen\n");
+			continue;
+		}
+
+		if(h->udpproto != IP_UDPPROTO) {
+			if(debug)
+				print("not udp (%d)...", h->udpproto);
+			continue;
+		}
+
+		if(debug)
+			print("okay udp...");
+
+		h->ttl = 0;
+		len = nhgets(h->udplen);
+		hnputs(h->udpplen, len);
+
+		if(nhgets(h->udpcksum)) {
+			csm = ptcl_csum(&h->ttl, len+UDP_PHDRSIZE);
+			if(csm != 0) {
+				print("udp chksum error csum #%4ux len %d\n",
+					csm, n);
+				break;
+			}
+		}
+
+		if(a->port != 0 && nhgets(h->udpsport) != a->port) {
+			if(debug)
+				print("udpport %ux not %ux\n",
+					nhgets(h->udpsport), a->port);
+			continue;
+		}
+
+		addr = nhgetl(h->udpsrc);
+		if(a->ip != Bcastip && a->ip != addr) {
+			if(debug)
+				print("bad ip %lux not %lux\n", addr, a->ip);
+			continue;
+		}
+
+		len -= UDP_HDRSIZE-UDP_PHDRSIZE;
+		if(len > dlen) {
+			print("udp: packet too big: %d > %d; from addr %E\n",
+				len, dlen, h->udpsrc);
+			continue;
+		}
+
+		memmove(data, h->udpcksum+sizeof(h->udpcksum), len);
+		a->ip = addr;
+		a->port = nhgets(h->udpsport);
+		memmove(a->ea, pkt.s, sizeof(a->ea));
+
+		rxactive = 1;
+		return len;
+	}
+
+	return 0;
+}
+
+static int tftpblockno;
+
+/*
+ * format of a request packet, from the RFC:
+ *
+            2 bytes     string    1 byte     string   1 byte
+            ------------------------------------------------
+           | Opcode |  Filename  |   0  |    Mode    |   0  |
+            ------------------------------------------------
+ */
+static int
+tftpopen(int ctlrno, Netaddr *a, char *name, Tftp *tftp)
+{
+	int i, len, rlen, oport;
+	char buf[Segsize+2];
+
+	buf[0] = 0;
+	buf[1] = Tftp_READ;
+	len = 2 + sprint(buf+2, "%s", name) + 1;
+	len += sprint(buf+len, "octet") + 1;
+
+	oport = a->port;
+	for(i = 0; i < 5; i++){
+		a->port = oport;
+		udpsend(ctlrno, a, buf, len);
+		a->port = 0;
+		if((rlen = udprecv(ctlrno, a, tftp, sizeof(Tftp))) < sizeof(tftp->header))
+			continue;
+
+		switch((tftp->header[0]<<8)|tftp->header[1]){
+
+		case Tftp_ERROR:
+			print("tftpopen: error (%d): %s\n",
+				(tftp->header[2]<<8)|tftp->header[3], (char*)tftp->data);
+			return -1;
+
+		case Tftp_DATA:
+			tftpblockno = 1;
+			len = (tftp->header[2]<<8)|tftp->header[3];
+			if(len != tftpblockno){
+				print("tftpopen: block error: %d\n", len);
+				nak(ctlrno, a, 1, "block error", 0);
+				return -1;
+			}
+			rlen -= sizeof(tftp->header);
+			if(rlen < Segsize){
+				/* ACK now, in case we don't later */
+				buf[0] = 0;
+				buf[1] = Tftp_ACK;
+				buf[2] = tftpblockno>>8;
+				buf[3] = tftpblockno;
+				udpsend(ctlrno, a, buf, sizeof(tftp->header));
+			}
+			return rlen;
+		}
+	}
+
+	print("tftpopen: failed to connect to server\n");
+	return -1;
+}
+
+static int
+tftpread(int ctlrno, Netaddr *a, Tftp *tftp, int dlen)
+{
+	uchar buf[4];
+	int try, blockno, len;
+
+	dlen += sizeof(tftp->header);
+
+	for(try = 0; try < 10; try++) {
+		buf[0] = 0;
+		buf[1] = Tftp_ACK;
+		buf[2] = tftpblockno>>8;
+		buf[3] = tftpblockno;
+
+		udpsend(ctlrno, a, buf, sizeof(buf));
+		len = udprecv(ctlrno, a, tftp, dlen);
+		if(len <= sizeof(tftp->header)){
+			if(debug)
+				print("tftpread: too short %d <= %d\n",
+					len, sizeof(tftp->header));
+			continue;
+		}
+		blockno = (tftp->header[2]<<8)|tftp->header[3];
+		if(blockno <= tftpblockno){
+			if(debug)
+				print("tftpread: blkno %d <= %d\n",
+					blockno, tftpblockno);
+			continue;
+		}
+
+		if(blockno == tftpblockno+1) {
+			tftpblockno++;
+			if(len < dlen) {	/* last packet; send final ack */
+				tftpblockno++;
+				buf[0] = 0;
+				buf[1] = Tftp_ACK;
+				buf[2] = tftpblockno>>8;
+				buf[3] = tftpblockno;
+				udpsend(ctlrno, a, buf, sizeof(buf));
+			}
+			return len-sizeof(tftp->header);
+		}
+		print("tftpread: block error: %d, expected %d\n",
+			blockno, tftpblockno+1);
+	}
+
+	return -1;
+}
+
+static int
+bootpopen(int ctlrno, char *file, Bootp *rep, int dotftpopen)
+{
+	Bootp req;
+	int i, n;
+	uchar *ea;
+	char name[128], *filename, *sysname;
+
+	if (debugload)
+		print("bootpopen: ether%d!%s...", ctlrno, file);
+	if((ea = etheraddr(ctlrno)) == 0){
+		print("invalid ctlrno %d\n", ctlrno);
+		return -1;
+	}
+
+	filename = 0;
+	sysname = 0;
+	if(file && *file){
+		strcpy(name, file);
+		if(filename = strchr(name, '!')){
+			sysname = name;
+			*filename++ = 0;
+		}
+		else
+			filename = name;
+	}
+
+	memset(&req, 0, sizeof(req));
+	req.op = Bootrequest;
+	req.htype = 1;			/* ethernet */
+	req.hlen = Eaddrlen;		/* ethernet */
+	memmove(req.chaddr, ea, Eaddrlen);
+	if(filename != nil)
+		strncpy(req.file, filename, sizeof(req.file));
+	if(sysname != nil)
+		strncpy(req.sname, sysname, sizeof(req.sname));
+
+	myaddr.ip = 0;
+	myaddr.port = BPportsrc;
+	memmove(myaddr.ea, ea, Eaddrlen);
+
+	etherrxflush(ctlrno);
+	for(i = 0; i < 10; i++) {
+		server.ip = Bcastip;
+		server.port = BPportdst;
+		memmove(server.ea, broadcast, sizeof(server.ea));
+		udpsend(ctlrno, &server, &req, sizeof(req));
+		if(udprecv(ctlrno, &server, rep, sizeof(*rep)) <= 0)
+			continue;
+		if(memcmp(req.chaddr, rep->chaddr, Eaddrlen))
+			continue;
+		if(rep->htype != 1 || rep->hlen != Eaddrlen)
+			continue;
+		if(sysname == 0 || strcmp(sysname, rep->sname) == 0)
+			break;
+	}
+	if(i >= 10) {
+		print("bootp timed out\n");
+		return -1;
+	}
+
+	if(!dotftpopen)
+		return 0;
+
+	if(filename == 0 || *filename == 0){
+		if(strcmp(rep->file, "/386/9pxeload") == 0)
+			return -1;
+		filename = rep->file;
+	}
+
+	if(rep->sname[0] != '\0')
+		 print("%s ", rep->sname);
+	print("(%d.%d.%d.%d!%d): %s\n",
+		rep->siaddr[0],
+		rep->siaddr[1],
+		rep->siaddr[2],
+		rep->siaddr[3],
+		server.port,
+		filename);
+
+	myaddr.ip = nhgetl(rep->yiaddr);
+	myaddr.port = tftpport++;
+	server.ip = nhgetl(rep->siaddr);
+	server.port = TFTPport;
+
+	if((n = tftpopen(ctlrno, &server, filename, &tftpb)) < 0)
+		return -1;
+
+	return n;
+}
+
+int
+bootpboot(int ctlrno, char *file, Boot *b)
+{
+	int n;
+	Bootp rep;
+
+	if((n = bootpopen(ctlrno, file, &rep, 1)) < 0)
+		return -1;
+
+	while(bootpass(b, tftpb.data, n) == MORE){
+		n = tftpread(ctlrno, &server, &tftpb, sizeof(tftpb.data));
+		if(n < sizeof(tftpb.data))
+			break;
+	}
+
+	if(0 < n && n < sizeof(tftpb.data))	/* got to end of file */
+		bootpass(b, tftpb.data, n);
+	else
+		nak(ctlrno, &server, 3, "ok", 0);	/* tftpclose to abort transfer */
+	bootpass(b, nil, 0);	/* boot if possible */
+	return -1;
+}
+
+#include "fs.h"
+
+#define INIPATHLEN	64
+
+static struct {
+	Fs	fs;
+	char	ini[INIPATHLEN];
+} pxether[MaxEther];
+
+static vlong
+pxediskseek(Fs*, vlong)
+{
+	return -1LL;
+}
+
+static long
+pxediskread(Fs*, void*, long)
+{
+	return -1;
+}
+
+static long
+pxeread(File* f, void* va, long len)
+{
+	int n;
+	Bootp rep;
+	char *p, *v;
+
+	if((n = bootpopen(f->fs->dev, pxether[f->fs->dev].ini, &rep, 1)) < 0)
+		return -1;
+
+	p = v = va;
+	while(n > 0) {
+		if((p-v)+n > len)
+			n = len - (p-v);
+		memmove(p, tftpb.data, n);
+		p += n;
+		if(n != Segsize)
+			break;
+		if((n = tftpread(f->fs->dev, &server, &tftpb, sizeof(tftpb.data))) < 0)
+			return -1;
+	}
+	return p-v;
+}
+
+static int
+pxewalk(File* f, char* name)
+{
+	Bootp rep;
+	char *ini;
+
+	switch(f->walked){
+	default:
+		return -1;
+	case 0:
+		if(strcmp(name, "cfg") == 0){
+			f->walked = 1;
+			return 1;
+		}
+		break;
+	case 1:
+		if(strcmp(name, "pxe") == 0){
+			f->walked = 2;
+			return 1;
+		}
+		break;
+	case 2:
+		if(strcmp(name, "%E") != 0)
+			break;
+		f->walked = 3;
+
+		if(bootpopen(f->fs->dev, nil, &rep, 0) < 0)
+			return 0;
+
+		ini = pxether[f->fs->dev].ini;
+		/* use our mac address instead of relying on a bootp answer */
+		snprint(ini, INIPATHLEN, "/cfg/pxe/%E", (uchar *)myaddr.ea);
+		f->path = ini;
+
+		return 1;
+	}
+	return 0;
+}
+
+void*
+pxegetfspart(int ctlrno, char* part, int)
+{
+	if(!pxe)
+		return nil;
+	if(strcmp(part, "*") != 0)
+		return nil;
+	if(ctlrno >= MaxEther)
+		return nil;
+	if(iniread && getconf("*pxeini") != nil)
+		return nil;
+
+	pxether[ctlrno].fs.dev = ctlrno;
+	pxether[ctlrno].fs.diskread = pxediskread;
+	pxether[ctlrno].fs.diskseek = pxediskseek;
+
+	pxether[ctlrno].fs.read = pxeread;
+	pxether[ctlrno].fs.walk = pxewalk;
+
+	pxether[ctlrno].fs.root.fs = &pxether[ctlrno].fs;
+	pxether[ctlrno].fs.root.walked = 0;
+
+	return &pxether[ctlrno].fs;
+}
--- /dev/null
+++ b/os/boot.original/pc/cga.c
@@ -1,0 +1,91 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+
+enum {
+	Width		= 160,
+	Height		= 25,
+
+	Attr		= 7,		/* white on black */
+};
+
+#define CGASCREENBASE	((uchar*)KADDR(0xB8000))
+
+static int pos;
+static int screeninitdone;
+
+static uchar
+cgaregr(int index)
+{
+	outb(0x3D4, index);
+	return inb(0x3D4+1) & 0xFF;
+}
+
+static void
+cgaregw(int index, int data)
+{
+	outb(0x3D4, index);
+	outb(0x3D4+1, data);
+}
+
+static void
+movecursor(void)
+{
+	cgaregw(0x0E, (pos/2>>8) & 0xFF);
+	cgaregw(0x0F, pos/2 & 0xFF);
+	CGASCREENBASE[pos+1] = Attr;
+}
+
+static void
+cgascreenputc(int c)
+{
+	int i;
+
+	if(c == '\n'){
+		pos = pos/Width;
+		pos = (pos+1)*Width;
+	}
+	else if(c == '\t'){
+		i = 8 - ((pos/2)&7);
+		while(i-->0)
+			cgascreenputc(' ');
+	}
+	else if(c == '\b'){
+		if(pos >= 2)
+			pos -= 2;
+		cgascreenputc(' ');
+		pos -= 2;
+	}
+	else{
+		CGASCREENBASE[pos++] = c;
+		CGASCREENBASE[pos++] = Attr;
+	}
+	if(pos >= Width*Height){
+		memmove(CGASCREENBASE, &CGASCREENBASE[Width], Width*(Height-1));
+		memset(&CGASCREENBASE[Width*(Height-1)], 0, Width);
+		pos = Width*(Height-1);
+	}
+	movecursor();
+}
+
+static void
+screeninit(void)
+{
+	if(screeninitdone == 0){
+		pos = cgaregr(0x0E)<<8;
+		pos |= cgaregr(0x0F);
+		pos *= 2;
+		screeninitdone = 1;
+	}
+}
+
+void
+cgascreenputs(char* s, int n)
+{
+	if(screeninitdone == 0)
+		screeninit();
+	while(n-- > 0)
+		cgascreenputc(*s++);
+}
--- /dev/null
+++ b/os/boot.original/pc/cis.c
@@ -1,0 +1,539 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "error.h"
+#include "io.h"
+
+enum{
+	Linktarget = 0x13,
+};
+	
+/*
+ *  read and crack the card information structure enough to set
+ *  important parameters like power
+ */
+/* cis memory walking */
+typedef struct Cisdat {
+	uchar	*cisbase;
+	int	cispos;
+	int	cisskip;
+	int	cislen;
+} Cisdat;
+
+static void	tcfig(PCMslot*, Cisdat*, int);
+static void	tentry(PCMslot*, Cisdat*, int);
+static void	tvers1(PCMslot*, Cisdat*, int);
+static void	tlonglnkmfc(PCMslot*, Cisdat*, int);
+
+static int
+readc(Cisdat *cis, uchar *x)
+{
+	if(cis->cispos >= cis->cislen)
+		return 0;
+	*x = cis->cisbase[cis->cisskip*cis->cispos];
+	cis->cispos++;
+	return 1;
+}
+
+static int
+xcistuple(int slotno, int tuple, int subtuple, void *v, int nv, int attr)
+{
+	PCMmap *m;
+	Cisdat cis;
+	int i, l;
+	uchar *p;
+	uchar type, link, n, c;
+	int this, subtype;
+
+	m = pcmmap(slotno, 0, 0, attr);
+	if(m == 0)
+		return -1;
+
+	cis.cisbase = KADDR(m->isa);
+	cis.cispos = 0;
+	cis.cisskip = attr ? 2 : 1;
+	cis.cislen = m->len;
+
+	/* loop through all the tuples */
+	for(i = 0; i < 1000; i++){
+		this = cis.cispos;
+		if(readc(&cis, &type) != 1)
+			break;
+		if(type == 0xFF)
+			break;
+		if(readc(&cis, &link) != 1)
+			break;
+		if(link == 0xFF)
+			break;
+
+		n = link;
+		if(link > 1 && subtuple != -1){
+			if(readc(&cis, &c) != 1)
+				break;
+			subtype = c;
+			n--;
+		}else
+			subtype = -1;
+
+		if(type == tuple && subtype == subtuple){
+			p = v;
+			for(l=0; l<nv && l<n; l++)
+				if(readc(&cis, p++) != 1)
+					break;
+			pcmunmap(slotno, m);
+			return nv;
+		}
+		cis.cispos = this + (2+link);
+	}
+	pcmunmap(slotno, m);
+	return -1;
+}
+
+int
+pcmcistuple(int slotno, int tuple, int subtuple, void *v, int nv)
+{
+	int n;
+
+	/* try attribute space, then memory */
+	if((n = xcistuple(slotno, tuple, subtuple, v, nv, 1)) >= 0)
+		return n;
+	return xcistuple(slotno, tuple, subtuple, v, nv, 0);
+}
+
+void
+pcmcisread(PCMslot *pp)
+{
+	int this;
+	Cisdat cis;
+	PCMmap *m;
+	uchar type, link;
+
+	memset(pp->ctab, 0, sizeof(pp->ctab));
+	pp->ncfg = 0;
+	memset(pp->cfg, 0, sizeof(pp->cfg));
+	pp->configed = 0;
+	pp->nctab = 0;
+	pp->verstr[0] = 0;
+
+	/*
+	 * Read all tuples in attribute space.
+	 */
+	m = pcmmap(pp->slotno, 0, 0, 1);
+	if(m == 0)
+		return;
+
+	cis.cisbase = KADDR(m->isa);
+	cis.cispos = 0;
+	cis.cisskip = 2;
+	cis.cislen = m->len;
+
+	/* loop through all the tuples */
+	for(;;){
+		this = cis.cispos;
+		if(readc(&cis, &type) != 1)
+			break;
+		if(type == 0xFF)
+			break;
+		if(readc(&cis, &link) != 1)
+			break;
+
+		switch(type){
+		default:
+			break;
+		case 6:
+			tlonglnkmfc(pp, &cis, type);
+			break;
+		case 0x15:
+			tvers1(pp, &cis, type);
+			break;
+		case 0x1A:
+			tcfig(pp, &cis, type);
+			break;
+		case 0x1B:
+			tentry(pp, &cis, type);
+			break;
+		}
+
+		if(link == 0xFF)
+			break;
+		cis.cispos = this + (2+link);
+	}
+	pcmunmap(pp->slotno, m);
+}
+
+static ulong
+getlong(Cisdat *cis, int size)
+{
+	uchar c;
+	int i;
+	ulong x;
+
+	x = 0;
+	for(i = 0; i < size; i++){
+		if(readc(cis, &c) != 1)
+			break;
+		x |= c<<(i*8);
+	}
+	return x;
+}
+
+static void
+tcfig(PCMslot *pp, Cisdat *cis, int )
+{
+	uchar size, rasize, rmsize;
+	uchar last;
+
+	if(readc(cis, &size) != 1)
+		return;
+	rasize = (size&0x3) + 1;
+	rmsize = ((size>>2)&0xf) + 1;
+	if(readc(cis, &last) != 1)
+		return;
+
+	if(pp->ncfg >= 8){
+		print("tcfig: too many configuration registers\n");
+		return;
+	}
+	
+	pp->cfg[pp->ncfg].caddr = getlong(cis, rasize);
+	pp->cfg[pp->ncfg].cpresent = getlong(cis, rmsize);
+	pp->ncfg++;
+}
+
+static ulong vexp[8] =
+{
+	1, 10, 100, 1000, 10000, 100000, 1000000, 10000000
+};
+static ulong vmant[16] =
+{
+	10, 12, 13, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 70, 80, 90,
+};
+
+static ulong
+microvolt(Cisdat *cis)
+{
+	uchar c;
+	ulong microvolts;
+	ulong exp;
+
+	if(readc(cis, &c) != 1)
+		return 0;
+	exp = vexp[c&0x7];
+	microvolts = vmant[(c>>3)&0xf]*exp;
+	while(c & 0x80){
+		if(readc(cis, &c) != 1)
+			return 0;
+		switch(c){
+		case 0x7d:
+			break;		/* high impedence when sleeping */
+		case 0x7e:
+		case 0x7f:
+			microvolts = 0;	/* no connection */
+			break;
+		default:
+			exp /= 10;
+			microvolts += exp*(c&0x7f);
+		}
+	}
+	return microvolts;
+}
+
+static ulong
+nanoamps(Cisdat *cis)
+{
+	uchar c;
+	ulong nanoamps;
+
+	if(readc(cis, &c) != 1)
+		return 0;
+	nanoamps = vexp[c&0x7]*vmant[(c>>3)&0xf];
+	while(c & 0x80){
+		if(readc(cis, &c) != 1)
+			return 0;
+		if(c == 0x7d || c == 0x7e || c == 0x7f)
+			nanoamps = 0;
+	}
+	return nanoamps;
+}
+
+/*
+ * only nominal voltage (feature 1) is important for config,
+ * other features must read card to stay in sync.
+ */
+static ulong
+power(Cisdat *cis)
+{
+	uchar feature;
+	ulong mv;
+
+	mv = 0;
+	if(readc(cis, &feature) != 1)
+		return 0;
+	if(feature & 1)
+		mv = microvolt(cis);
+	if(feature & 2)
+		microvolt(cis);
+	if(feature & 4)
+		microvolt(cis);
+	if(feature & 8)
+		nanoamps(cis);
+	if(feature & 0x10)
+		nanoamps(cis);
+	if(feature & 0x20)
+		nanoamps(cis);
+	if(feature & 0x40)
+		nanoamps(cis);
+	return mv/1000000;
+}
+
+static ulong mantissa[16] =
+{ 0, 10, 12, 13, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 70, 80, };
+
+static ulong exponent[8] =
+{ 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, };
+
+static ulong
+ttiming(Cisdat *cis, int scale)
+{
+	uchar unscaled;
+	ulong nanosecs;
+
+	if(readc(cis, &unscaled) != 1)
+		return 0;
+	nanosecs = (mantissa[(unscaled>>3)&0xf]*exponent[unscaled&7])/10;
+	nanosecs = nanosecs * vexp[scale];
+	return nanosecs;
+}
+
+static void
+timing(Cisdat *cis, PCMconftab *ct)
+{
+	uchar c, i;
+
+	if(readc(cis, &c) != 1)
+		return;
+	i = c&0x3;
+	if(i != 3)
+		ct->maxwait = ttiming(cis, i);		/* max wait */
+	i = (c>>2)&0x7;
+	if(i != 7)
+		ct->readywait = ttiming(cis, i);		/* max ready/busy wait */
+	i = (c>>5)&0x7;
+	if(i != 7)
+		ct->otherwait = ttiming(cis, i);		/* reserved wait */
+}
+
+static void
+iospaces(Cisdat *cis, PCMconftab *ct)
+{
+	uchar c;
+	int i, nio;
+
+	ct->nio = 0;
+	if(readc(cis, &c) != 1)
+		return;
+
+	ct->bit16 = ((c>>5)&3) >= 2;
+	if(!(c & 0x80)){
+		ct->io[0].start = 0;
+		ct->io[0].len = 1<<(c&0x1f);
+		ct->nio = 1;
+		return;
+	}
+
+	if(readc(cis, &c) != 1)
+		return;
+
+	/*
+	 * For each of the range descriptions read the
+	 * start address and the length (value is length-1).
+	 */
+	nio = (c&0xf)+1;
+	for(i = 0; i < nio; i++){
+		ct->io[i].start = getlong(cis, (c>>4)&0x3);
+		ct->io[i].len = getlong(cis, (c>>6)&0x3)+1;
+	}
+	ct->nio = nio;
+}
+
+static void
+irq(Cisdat *cis, PCMconftab *ct)
+{
+	uchar c;
+
+	if(readc(cis, &c) != 1)
+		return;
+	ct->irqtype = c & 0xe0;
+	if(c & 0x10)
+		ct->irqs = getlong(cis, 2);
+	else
+		ct->irqs = 1<<(c&0xf);
+	ct->irqs &= 0xDEB8;		/* levels available to card */
+}
+
+static void
+memspace(Cisdat *cis, int asize, int lsize, int host)
+{
+	ulong haddress, address, len;
+
+	len = getlong(cis, lsize)*256;
+	address = getlong(cis, asize)*256;
+	USED(len, address);
+	if(host){
+		haddress = getlong(cis, asize)*256;
+		USED(haddress);
+	}
+}
+
+static void
+tentry(PCMslot *pp, Cisdat *cis, int )
+{
+	uchar c, i, feature;
+	PCMconftab *ct;
+
+	if(pp->nctab >= nelem(pp->ctab))
+		return;
+	if(readc(cis, &c) != 1)
+		return;
+	ct = &pp->ctab[pp->nctab++];
+
+	/* copy from last default config */
+	if(pp->def)
+		*ct = *pp->def;
+
+	ct->index = c & 0x3f;
+
+	/* is this the new default? */
+	if(c & 0x40)
+		pp->def = ct;
+
+	/* memory wait specified? */
+	if(c & 0x80){
+		if(readc(cis, &i) != 1)
+			return;
+		if(i&0x80)
+			ct->memwait = 1;
+	}
+
+	if(readc(cis, &feature) != 1)
+		return;
+	switch(feature&0x3){
+	case 1:
+		ct->vpp1 = ct->vpp2 = power(cis);
+		break;
+	case 2:
+		power(cis);
+		ct->vpp1 = ct->vpp2 = power(cis);
+		break;
+	case 3:
+		power(cis);
+		ct->vpp1 = power(cis);
+		ct->vpp2 = power(cis);
+		break;
+	default:
+		break;
+	}
+	if(feature&0x4)
+		timing(cis, ct);
+	if(feature&0x8)
+		iospaces(cis, ct);
+	if(feature&0x10)
+		irq(cis, ct);
+	switch((feature>>5)&0x3){
+	case 1:
+		memspace(cis, 0, 2, 0);
+		break;
+	case 2:
+		memspace(cis, 2, 2, 0);
+		break;
+	case 3:
+		if(readc(cis, &c) != 1)
+			return;
+		for(i = 0; i <= (c&0x7); i++)
+			memspace(cis, (c>>5)&0x3, (c>>3)&0x3, c&0x80);
+		break;
+	}
+	pp->configed++;
+}
+
+static void
+tvers1(PCMslot *pp, Cisdat *cis, int )
+{
+	uchar c, major, minor, last;
+	int  i;
+
+	if(readc(cis, &major) != 1)
+		return;
+	if(readc(cis, &minor) != 1)
+		return;
+	last = 0;
+	for(i = 0; i < sizeof(pp->verstr)-1; i++){
+		if(readc(cis, &c) != 1)
+			return;
+		if(c == 0)
+			c = ';';
+		if(c == '\n')
+			c = ';';
+		if(c == 0xff)
+			break;
+		if(c == ';' && last == ';')
+			continue;
+		pp->verstr[i] = c;
+		last = c;
+	}
+	pp->verstr[i] = 0;
+}
+
+static void
+tlonglnkmfc(PCMslot *pp, Cisdat *cis, int)
+{
+	int i, npos, opos;
+	uchar nfn, space, expect, type, this, link;
+
+	readc(cis, &nfn);
+	for(i = 0; i < nfn; i++){
+		readc(cis, &space);
+		npos        = getlong(cis, 4);
+		opos        = cis->cispos;
+		cis->cispos = npos;
+		expect      = Linktarget;
+
+		while(1){
+			this = cis->cispos;
+			if(readc(cis, &type) != 1)
+				break;
+			if(type == 0xFF)
+				break;
+			if(readc(cis, &link) != 1)
+				break;
+
+			if(expect && expect != type){
+				print("tlonglnkmfc: expected %X found %X\n",
+					expect, type);
+				break;
+			}
+			expect = 0;
+
+			switch(type){
+			default:
+				break;
+			case 0x15:
+				tvers1(pp, cis, type);
+				break;
+			case 0x1A:
+				tcfig(pp, cis, type);
+				break;
+			case 0x1B:
+				tentry(pp, cis, type);
+				break;
+			}
+
+			if(link == 0xFF)
+				break;
+			cis->cispos = this + (2+link);
+		}
+		cis->cispos = opos;
+	}
+}
--- /dev/null
+++ b/os/boot.original/pc/clock.c
@@ -1,0 +1,309 @@
+#include	"u.h"
+#include	"lib.h"
+#include	"mem.h"
+#include	"dat.h"
+#include	"fns.h"
+#include	"io.h"
+#include	"ureg.h"
+
+/*
+ *  8253 timer
+ */
+enum
+{
+	T0cntr=	0x40,		/* counter ports */
+	T1cntr=	0x41,		/* ... */
+	T2cntr=	0x42,		/* ... */
+	Tmode=	0x43,		/* mode port */
+
+	/* commands */
+	Latch0=	0x00,		/* latch counter 0's value */
+	Load0=	0x30,		/* load counter 0 with 2 bytes */
+
+	/* modes */
+	Square=	0x36,		/* perioic square wave */
+
+	Freq=	1193182,	/* Real clock frequency */
+};
+
+static uvlong cpuhz = 66000000;
+static int cpumhz = 66;
+static int loopconst = 100;
+int cpuidax, cpuiddx;
+int havetsc;
+
+extern void _cycles(uvlong*);		/* in l.s */
+extern void wrmsr(int, vlong);
+
+static void
+clockintr(Ureg*, void*)
+{
+	m->ticks++;
+	checkalarms();
+}
+
+#define STEPPING(x)	((x)&0xf)
+#define X86MODEL(x)	(((x)>>4)&0xf)
+#define X86FAMILY(x)	(((x)>>8)&0xf)
+
+enum
+{
+	/* flags */
+	CpuidFPU	= 0x001,	/* on-chip floating point unit */
+	CpuidMCE	= 0x080,	/* machine check exception */
+	CpuidCX8	= 0x100,	/* CMPXCHG8B instruction */
+};
+
+typedef struct
+{
+	int family;
+	int model;
+	int aalcycles;
+	char *name;
+} X86type;
+
+X86type x86intel[] =
+{
+	{ 4,	0,	22,	"486DX", },	/* known chips */
+	{ 4,	1,	22,	"486DX50", },
+	{ 4,	2,	22,	"486SX", },
+	{ 4,	3,	22,	"486DX2", },
+	{ 4,	4,	22,	"486SL", },
+	{ 4,	5,	22,	"486SX2", },
+	{ 4,	7,	22,	"DX2WB", },	/* P24D */
+	{ 4,	8,	22,	"DX4", },	/* P24C */
+	{ 4,	9,	22,	"DX4WB", },	/* P24CT */
+	{ 5,	0,	23,	"P5", },
+	{ 5,	1,	23,	"P5", },
+	{ 5,	2,	23,	"P54C", },
+	{ 5,	3,	23,	"P24T", },
+	{ 5,	4,	23,	"P55C MMX", },
+	{ 5,	7,	23,	"P54C VRT", },
+	{ 6,	1,	16,	"PentiumPro", },/* trial and error */
+	{ 6,	3,	16,	"PentiumII", },
+	{ 6,	5,	16,	"PentiumII/Xeon", },
+	{ 6,	6,	16,	"Celeron", },
+	{ 6,	7,	16,	"PentiumIII/Xeon", },
+	{ 6,	8,	16,	"PentiumIII/Xeon", },
+	{ 6,	0xB,	16,	"PentiumIII/Xeon", },
+	{ 0xF,	1,	16,	"P4", },	/* P4 */
+	{ 0xF,	2,	16,	"PentiumIV/Xeon", },
+
+	{ 3,	-1,	32,	"386", },	/* family defaults */
+	{ 4,	-1,	22,	"486", },
+	{ 5,	-1,	23,	"P5", },
+	{ 6,	-1,	16,	"P6", },
+	{ 0xF,	-1,	16,	"P4", },	/* P4 */
+
+	{ -1,	-1,	16,	"unknown", },	/* total default */
+};
+
+
+/*
+ * The AMD processors all implement the CPUID instruction.
+ * The later ones also return the processor name via functions
+ * 0x80000002, 0x80000003 and 0x80000004 in registers AX, BX, CX
+ * and DX:
+ *	K5	"AMD-K5(tm) Processor"
+ *	K6	"AMD-K6tm w/ multimedia extensions"
+ *	K6 3D	"AMD-K6(tm) 3D processor"
+ *	K6 3D+	?
+ */
+static X86type x86amd[] =
+{
+	{ 5,	0,	23,	"AMD-K5", },	/* guesswork */
+	{ 5,	1,	23,	"AMD-K5", },	/* guesswork */
+	{ 5,	2,	23,	"AMD-K5", },	/* guesswork */
+	{ 5,	3,	23,	"AMD-K5", },	/* guesswork */
+	{ 5,	4,	23,	"AMD Geode GX1", },	/* guesswork */
+	{ 5,	5,	23,	"AMD Geode GX2", },	/* guesswork */
+	{ 5,	6,	11,	"AMD-K6", },	/* trial and error */
+	{ 5,	7,	11,	"AMD-K6", },	/* trial and error */
+	{ 5,	8,	11,	"AMD-K6-2", },	/* trial and error */
+	{ 5,	9,	11,	"AMD-K6-III", },/* trial and error */
+	{ 5,	0xa,	23,	"AMD Geode LX", },	/* guesswork */
+
+	{ 6,	1,	11,	"AMD-Athlon", },/* trial and error */
+	{ 6,	2,	11,	"AMD-Athlon", },/* trial and error */
+
+	{ 4,	-1,	22,	"Am486", },	/* guesswork */
+	{ 5,	-1,	23,	"AMD-K5/K6", },	/* guesswork */
+	{ 6,	-1,	11,	"AMD-Athlon", },/* guesswork */
+	{ 0xF,	-1,	11,	"AMD64", },	/* guesswork */
+
+	{ -1,	-1,	11,	"unknown", },	/* total default */
+};
+
+static X86type	*cputype;
+
+
+void
+delay(int millisecs)
+{
+	millisecs *= loopconst;
+	if(millisecs <= 0)
+		millisecs = 1;
+	aamloop(millisecs);
+}
+
+void
+microdelay(int microsecs)
+{
+	microsecs *= loopconst;
+	microsecs /= 1000;
+	if(microsecs <= 0)
+		microsecs = 1;
+	aamloop(microsecs);
+}
+
+extern void cpuid(char*, int*, int*);
+
+X86type*
+cpuidentify(void)
+{
+	int family, model;
+	X86type *t;
+	char cpuidid[16];
+	int cpuidax, cpuiddx;
+
+	cpuid(cpuidid, &cpuidax, &cpuiddx);
+	if(strncmp(cpuidid, "AuthenticAMD", 12) == 0 ||
+	   strncmp(cpuidid, "Geode by NSC", 12) == 0)
+		t = x86amd;
+	else
+		t = x86intel;
+	family = X86FAMILY(cpuidax);
+	model = X86MODEL(cpuidax);
+	if (0)
+		print("cpuidentify: cpuidax 0x%ux cpuiddx 0x%ux\n",
+			cpuidax, cpuiddx);
+	while(t->name){
+		if((t->family == family && t->model == model)
+		|| (t->family == family && t->model == -1)
+		|| (t->family == -1))
+			break;
+		t++;
+	}
+	if(t->name == nil)
+		panic("cpuidentify");
+
+	if(cpuiddx & 0x10){
+		havetsc = 1;
+		if(cpuiddx & 0x20)
+			wrmsr(0x10, 0);
+	}
+
+	return t;
+}
+
+void
+clockinit(void)
+{
+	uvlong a, b, cpufreq;
+	int loops, incr, x, y;
+	X86type *t;
+
+	/*
+	 *  set vector for clock interrupts
+	 */
+	setvec(VectorCLOCK, clockintr, 0);
+
+	t = cpuidentify();
+
+	/*
+	 *  set clock for 1/HZ seconds
+	 */
+	outb(Tmode, Load0|Square);
+	outb(T0cntr, (Freq/HZ));	/* low byte */
+	outb(T0cntr, (Freq/HZ)>>8);	/* high byte */
+
+	/*
+	 * Introduce a little delay to make sure the count is
+	 * latched and the timer is counting down; with a fast
+	 * enough processor this may not be the case.
+	 * The i8254 (which this probably is) has a read-back
+	 * command which can be used to make sure the counting
+	 * register has been written into the counting element.
+	 */
+	x = (Freq/HZ);
+	for(loops = 0; loops < 100000 && x >= (Freq/HZ); loops++){
+		outb(Tmode, Latch0);
+		x = inb(T0cntr);
+		x |= inb(T0cntr)<<8;
+	}
+
+	/* find biggest loop that doesn't wrap */
+	incr = 16000000/(t->aalcycles*HZ*2);
+	x = 2000;
+	for(loops = incr; loops < 64*1024; loops += incr) {
+	
+		/*
+		 *  measure time for the loop
+		 *
+		 *			MOVL	loops,CX
+		 *	aaml1:	 	AAM
+		 *			LOOP	aaml1
+		 *
+		 *  the time for the loop should be independent of external
+		 *  cache and memory system since it fits in the execution
+		 *  prefetch buffer.
+		 *
+		 */
+		outb(Tmode, Latch0);
+		if(havetsc)
+			_cycles(&a);
+		x = inb(T0cntr);
+		x |= inb(T0cntr)<<8;
+		aamloop(loops);
+		outb(Tmode, Latch0);
+		if(havetsc)
+			_cycles(&b);
+		y = inb(T0cntr);
+		y |= inb(T0cntr)<<8;
+		x -= y;
+	
+		if(x < 0)
+			x += Freq/HZ;
+
+		if(x > Freq/(3*HZ))
+			break;
+	}
+
+	/*
+ 	 *  figure out clock frequency and a loop multiplier for delay().
+	 *  counter  goes at twice the frequency, once per transition,
+	 *  i.e., twice per square wave
+	 */
+	cpufreq = (vlong)loops*((t->aalcycles*2*Freq)/x);
+	loopconst = (cpufreq/1000)/t->aalcycles;	/* AAM+LOOP's for 1 ms */
+
+	if(havetsc){
+		/* counter goes up by 2*Freq */
+		b = (b-a)<<1;
+		b *= Freq;
+		b /= x;
+
+		/*
+		 *  round to the nearest megahz
+		 */
+		cpumhz = (b+500000)/1000000L;
+		cpuhz = b;
+	}
+	else{
+		/*
+		 *  add in possible .5% error and convert to MHz
+		 */
+		cpumhz = (cpufreq + cpufreq/200)/1000000;
+		cpuhz = cpufreq;
+	}
+
+	if(debug){
+		int timeo;
+
+		print("%dMHz %s loop %d\n", cpumhz, t->name, loopconst);
+		print("tick...");
+		for(timeo = 0; timeo < 10; timeo++)
+			delay(1000);
+		print("tock...\n");
+	}
+}
--- /dev/null
+++ b/os/boot.original/pc/conf.c
@@ -1,0 +1,537 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+#include "fs.h"
+
+/*
+ * Where configuration info is left for the loaded programme.
+ * This will turn into a structure as more is done by the boot loader
+ * (e.g. why parse the .ini file twice?).
+ * There are 3584 bytes available at CONFADDR.
+ *
+ * The low-level boot routines in l.s leave data for us at CONFADDR,
+ * which we pick up before reading the plan9.ini file.
+ */
+#define BOOTLINELEN	64
+#define BOOTARGS	((char*)(CONFADDR+BOOTLINELEN))
+#define	BOOTARGSLEN	(3584-0x200-BOOTLINELEN)
+#define	MAXCONF		100
+
+static char *confname[MAXCONF];
+static char *confval[MAXCONF];
+static int nconf;
+
+extern char **ini;
+
+typedef struct {
+	char*	name;
+	int	start;
+	int	end;
+} Mblock;
+
+typedef struct {
+	char*	tag;
+	Mblock*	mb;
+} Mitem;
+
+static Mblock mblock[MAXCONF];
+static int nmblock;
+static Mitem mitem[MAXCONF];
+static int nmitem;
+static char* mdefault;
+static char mdefaultbuf[10];
+static int mtimeout;
+
+static char*
+comma(char* line, char** residue)
+{
+	char *q, *r;
+
+	if((q = strchr(line, ',')) != nil){
+		*q++ = 0;
+		if(*q == ' ')
+			q++;
+	}
+	*residue = q;
+
+	if((r = strchr(line, ' ')) != nil)
+		*r = 0;
+
+	if(*line == ' ')
+		line++;
+	return line;
+}
+
+static Mblock*
+findblock(char* name, char** residue)
+{
+	int i;
+	char *p;
+
+	p = comma(name, residue);
+	for(i = 0; i < nmblock; i++){
+		if(strcmp(p, mblock[i].name) == 0)
+			return &mblock[i];
+	}
+	return nil;
+}
+
+static Mitem*
+finditem(char* name, char** residue)
+{
+	int i;
+	char *p;
+
+	p = comma(name, residue);
+	for(i = 0; i < nmitem; i++){
+		if(strcmp(p, mitem[i].mb->name) == 0)
+			return &mitem[i];
+	}
+	return nil;
+}
+
+static void
+parsemenu(char* str, char* scratch, int len)
+{
+	Mitem *mi;
+	Mblock *mb, *menu;
+	char buf[20], *p, *q, *line[MAXCONF];
+	int i, inblock, n, show;
+
+	inblock = 0;
+	menu = nil;
+	memmove(scratch, str, len);
+	n = getfields(scratch, line, MAXCONF, '\n');
+	if(n >= MAXCONF)
+		print("warning: possibly too many lines in plan9.ini\n");
+	for(i = 0; i < n; i++){
+		p = line[i];
+		if(inblock && *p == '['){
+			mblock[nmblock].end = i;
+			if(strcmp(mblock[nmblock].name, "menu") == 0)
+				menu = &mblock[nmblock];
+			nmblock++;
+			inblock = 0;
+		}
+		if(*p == '['){
+			if(nmblock == 0 && i != 0){
+				mblock[nmblock].name = "common";
+				mblock[nmblock].start = 0;
+				mblock[nmblock].end = i;
+				nmblock++;
+			}
+			q = strchr(p+1, ']');
+			if(q == nil || *(q+1) != 0){
+				print("malformed menu block header - %s\n", p);
+				return;
+			}
+			*q = 0;
+			mblock[nmblock].name = p+1;
+			mblock[nmblock].start = i+1;
+			inblock = 1;
+		}
+	}
+
+	if(inblock){
+		mblock[nmblock].end = i;
+		nmblock++;
+	}
+	if(menu == nil)
+		return;
+	if(nmblock < 2){
+		print("incomplete menu specification\n");
+		return;
+	}
+
+	for(i = menu->start; i < menu->end; i++){
+		p = line[i];
+		if(cistrncmp(p, "menuitem=", 9) == 0){
+			p += 9;
+			if((mb = findblock(p, &q)) == nil){
+				print("no block for menuitem %s\n", p);
+				return;
+			}
+			if(q != nil)
+				mitem[nmitem].tag = q;
+			else
+				mitem[nmitem].tag = mb->name;
+			mitem[nmitem].mb = mb;
+			nmitem++;
+		}
+		else if(cistrncmp(p, "menudefault=", 12) == 0){
+			p += 12;
+			if((mi = finditem(p, &q)) == nil){
+				print("no item for menudefault %s\n", p);
+				return;
+			}
+			if(q != nil)
+				mtimeout = strtol(q, 0, 0);
+			sprint(mdefaultbuf, "%ld", mi-mitem+1);
+			mdefault = mdefaultbuf;
+		}
+		else if(cistrncmp(p, "menuconsole=", 12) == 0){
+			p += 12;
+			p = comma(p, &q);
+			consinit(p, q);
+		}
+		else{
+			print("invalid line in [menu] block - %s\n", p);
+			return;
+		}
+	}
+
+again:
+	print("\nPlan 9 Startup Menu:\n====================\n");
+	for(i = 0; i < nmitem; i++)
+		print("    %d. %s\n", i+1, mitem[i].tag);
+	for(;;){
+		getstr("Selection", buf, sizeof(buf), mdefault, mtimeout);
+		mtimeout = 0;
+		i = strtol(buf, &p, 0)-1;
+		if(i < 0 || i >= nmitem)
+			goto again;
+		switch(*p){
+		case 'p':
+		case 'P':
+			show = 1;
+			print("\n");
+			break;
+		case 0:
+			show = 0;
+			break;
+		default:
+			continue;
+			
+		}
+		mi = &mitem[i];
+	
+		p = str;
+		p += sprint(p, "menuitem=%s\n", mi->mb->name);
+		for(i = 0; i < nmblock; i++){
+			mb = &mblock[i];
+			if(mi->mb != mb && cistrcmp(mb->name, "common") != 0)
+				continue;
+			for(n = mb->start; n < mb->end; n++)
+				p += sprint(p, "%s\n", line[n]);
+		}
+
+		if(show){
+			for(q = str; q < p; q += i){
+				if((i = print(q)) <= 0)
+					break;
+			}
+			goto again;
+		}
+		break;
+	}
+	print("\n");
+}
+
+/*
+static void
+msleep(int msec)
+{
+	ulong start;
+
+	for(start = m->ticks; TK2MS(m->ticks - start) < msec; )
+		;
+}
+*/
+
+void
+readlsconf(void)
+{
+	uchar *p;
+
+	p = (uchar*)CONFADDR;
+	for(;;) {
+		if(strcmp((char*)p, "APM") == 0){
+			apm.haveinfo = 1;
+			apm.ax = *(ushort*)(p+4);
+			apm.cx = *(ushort*)(p+6);
+			apm.dx = *(ushort*)(p+8);
+			apm.di = *(ushort*)(p+10);
+			apm.ebx = *(ulong*)(p+12);
+			apm.esi = *(ulong*)(p+16);
+			print("apm ax=%x cx=%x dx=%x di=%x ebx=%x esi=%x\n",
+				apm.ax, apm.cx, apm.dx, apm.di, apm.ebx, apm.esi);
+			p += 20;
+			continue;
+		}
+		break;
+	}
+}
+
+char*
+getconf(char *name)
+{
+	int i, n, nmatch;
+	char buf[20];
+
+	nmatch = 0;
+	for(i = 0; i < nconf; i++)
+		if(cistrcmp(confname[i], name) == 0)
+			nmatch++;
+
+	switch(nmatch) {
+	default:
+		print("\n");
+		nmatch = 0;
+		for(i = 0; i < nconf; i++)
+			if(cistrcmp(confname[i], name) == 0)
+				print("%d. %s\n", ++nmatch, confval[i]);
+		print("%d. none of the above\n", ++nmatch);
+		do {
+			getstr(name, buf, sizeof(buf), nil, 0);
+			n = atoi(buf);
+		} while(n < 1 || n > nmatch);
+
+		for(i = 0; i < nconf; i++)
+			if(cistrcmp(confname[i], name) == 0)
+				if(--n == 0)
+					return confval[i];
+		break;
+
+	case 1:
+		for(i = 0; i < nconf; i++)
+			if(cistrcmp(confname[i], name) == 0)
+				return confval[i];
+		break;
+
+	case 0:
+		break;
+	}
+	return nil;
+}
+
+void
+addconf(char *fmt, ...)
+{
+	va_list arg;
+
+	va_start(arg, fmt);
+	vseprint(BOOTARGS+strlen(BOOTARGS), BOOTARGS+BOOTARGSLEN, fmt, arg);
+	va_end(arg);
+}
+
+void
+changeconf(char *fmt, ...)
+{
+	va_list arg;
+	char *p, *q, pref[20], buf[128];
+
+	va_start(arg, fmt);
+	vseprint(buf, buf+sizeof buf, fmt, arg);
+	va_end(arg);
+	strncpy(pref+1, buf, 19);
+	pref[19] = '\0';
+	if(p = strchr(pref, '='))
+		*(p+1) = '\0';
+	else
+		print("warning: did not change %s in plan9.ini\n", buf);
+
+	/* find old line by looking for \nwhat= */
+	pref[0] = '\n';
+	if(strncmp(BOOTARGS, pref+1, strlen(pref+1)) == 0)
+		p = BOOTARGS;
+	else if(p = strstr(BOOTARGS, pref))
+		p++;
+	else
+		p = nil;
+
+	/* move rest of args up, deleting what= line. */
+	if(p != nil && (q = strchr(p, '\n')) != nil)
+		memmove(p, q+1, strlen(q+1)+1);
+
+	/* add replacement to end */
+	addconf("%s", buf);
+}
+
+/*
+ *  read configuration file
+ */
+static char inibuf[BOOTARGSLEN];
+static char id[8] = "ZORT 0\r\n";
+
+int
+dotini(Fs *fs)
+{
+	File rc;
+	int blankline, i, incomment, inspace, n;
+	char *cp, *p, *q, *line[MAXCONF];
+
+	if(fswalk(fs, *ini, &rc) <= 0)
+		return -1;
+
+	cp = inibuf;
+	*cp = 0;
+	n = fsread(&rc, cp, BOOTARGSLEN-1);
+	if(n <= 0)
+		return -1;
+
+	cp[n] = 0;
+
+	/*
+	 * Strip out '\r', change '\t' -> ' '.
+	 * Change runs of spaces into single spaces.
+	 * Strip out trailing spaces, blank lines.
+	 *
+	 * We do this before we make the copy so that if we 
+	 * need to change the copy, it is already fairly clean.
+	 * The main need is in the case when plan9.ini has been
+	 * padded with lots of trailing spaces, as is the case 
+	 * for those created during a distribution install.
+	 */
+	p = cp;
+	blankline = 1;
+	incomment = inspace = 0;
+	for(q = cp; *q; q++){
+		if(*q == '\r')
+			continue;
+		if(*q == '\t')
+			*q = ' ';
+		if(*q == ' '){
+			inspace = 1;
+			continue;
+		}
+		if(*q == '\n'){
+			if(!blankline){
+				if(!incomment)
+					*p++ = '\n';
+				blankline = 1;
+			}
+			incomment = inspace = 0;
+			continue;
+		}
+		if(inspace){
+			if(!blankline && !incomment)
+				*p++ = ' ';
+			inspace = 0;
+		}
+		if(blankline && *q == '#')
+			incomment = 1;
+		blankline = 0;
+		if(!incomment)
+			*p++ = *q;	
+	}
+	if(p > cp && p[-1] != '\n')
+		*p++ = '\n';
+	*p++ = 0;
+	n = p-cp;
+
+	parsemenu(cp, BOOTARGS, n);
+
+	/*
+	 * Keep a copy.
+	 * We could change this to pass the parsed strings
+	 * to the booted programme instead of the raw
+	 * string, then it only gets done once.
+	 */
+	if(strncmp(cp, id, sizeof(id))){
+		memmove(BOOTARGS, id, sizeof(id));
+		if(n+1+sizeof(id) >= BOOTARGSLEN)
+			n -= sizeof(id);
+		memmove(BOOTARGS+sizeof(id), cp, n+1);
+	}
+	else
+		memmove(BOOTARGS, cp, n+1);
+
+	n = getfields(cp, line, MAXCONF, '\n');
+	for(i = 0; i < n; i++){
+		cp = strchr(line[i], '=');
+		if(cp == 0)
+			continue;
+		*cp++ = 0;
+		if(cp - line[i] >= NAMELEN+1)
+			*(line[i]+NAMELEN-1) = 0;
+		confname[nconf] = line[i];
+		confval[nconf] = cp;
+		nconf++;
+	}
+	return 0;
+}
+
+static int
+parseether(uchar *to, char *from)
+{
+	char nip[4];
+	char *p;
+	int i;
+
+	p = from;
+	while(*p == ' ')
+		++p;
+	for(i = 0; i < 6; i++){
+		if(*p == 0)
+			return -1;
+		nip[0] = *p++;
+		if(*p == 0)
+			return -1;
+		nip[1] = *p++;
+		nip[2] = 0;
+		to[i] = strtoul(nip, 0, 16);
+		if(*p == ':')
+			p++;
+	}
+	return 0;
+}
+
+int
+isaconfig(char *class, int ctlrno, ISAConf *isa)
+{
+	char cc[NAMELEN], *p, *q, *r;
+	int n;
+
+	sprint(cc, "%s%d", class, ctlrno);
+	for(n = 0; n < nconf; n++){
+		if(cistrncmp(confname[n], cc, NAMELEN))
+			continue;
+		isa->nopt = 0;
+		p = confval[n];
+		while(*p){
+			while(*p == ' ' || *p == '\t')
+				p++;
+			if(*p == '\0')
+				break;
+			if(cistrncmp(p, "type=", 5) == 0){
+				p += 5;
+				for(q = isa->type; q < &isa->type[NAMELEN-1]; q++){
+					if(*p == '\0' || *p == ' ' || *p == '\t')
+						break;
+					*q = *p++;
+				}
+				*q = '\0';
+			}
+			else if(cistrncmp(p, "port=", 5) == 0)
+				isa->port = strtoul(p+5, &p, 0);
+			else if(cistrncmp(p, "irq=", 4) == 0)
+				isa->irq = strtoul(p+4, &p, 0);
+			else if(cistrncmp(p, "mem=", 4) == 0)
+				isa->mem = strtoul(p+4, &p, 0);
+			else if(cistrncmp(p, "size=", 5) == 0)
+				isa->size = strtoul(p+5, &p, 0);
+			else if(cistrncmp(p, "ea=", 3) == 0){
+				if(parseether(isa->ea, p+3) == -1)
+					memset(isa->ea, 0, 6);
+			}
+			else if(isa->nopt < NISAOPT){
+				r = isa->opt[isa->nopt];
+				while(*p && *p != ' ' && *p != '\t'){
+					*r++ = *p++;
+					if(r-isa->opt[isa->nopt] >= ISAOPTLEN-1)
+						break;
+				}
+				*r = '\0';
+				isa->nopt++;
+			}
+			while(*p && *p != ' ' && *p != '\t')
+				p++;
+		}
+		return 1;
+	}
+	return 0;
+}
--- /dev/null
+++ b/os/boot.original/pc/console.c
@@ -1,0 +1,236 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+IOQ consiq;
+IOQ consoq;
+
+static int useuart;
+
+int	debug = 0;
+
+void
+kbdchar(int c)
+{
+	c &= 0x7F;
+	if(c == 0x10)
+		warp86("\n^P\n", 0);
+	if(c == 0x12)
+		debug = !debug;
+	consiq.putc(&consiq, c);
+}
+
+static int
+consputc(void)
+{
+	return consoq.getc(&consoq);
+}
+
+void
+kbdinit(void)
+{
+	i8042init();
+	qinit(&consiq);
+}
+
+void
+consinit(char* name, char* speed)
+{
+	int baud, port;
+
+	if(name == nil || cistrcmp(name, "cga") == 0)
+		return;
+	port = strtoul(name, 0, 0);
+	if(port < 0 || port > 1)
+		return;
+	if(speed == nil || (baud = strtoul(speed, 0, 0)) == 0)
+		baud = 9600;
+
+	qinit(&consoq);
+
+	uartspecial(port, kbdchar, consputc, baud);
+	useuart = 1;
+	uartputs(&consoq, "\n", 1);
+}
+
+void
+consdrain(void)
+{
+	if(useuart)
+		uartdrain();
+}
+
+void
+consputs(char* s, int n)
+{
+	cgascreenputs(s, n);
+	if(useuart)
+		uartputs(&consoq, s, n);
+}
+
+void
+warp86(char* s, ulong)
+{
+	if(s != nil)
+		print(s);
+	spllo();
+	consdrain();
+
+	i8042reset();
+	print("Takes a licking and keeps on ticking...\n");
+	for(;;)
+		idle();
+}
+
+static int
+getline(char *buf, int size, int timeout)
+{
+	int c, i=0;
+	ulong start;
+	char echo;
+
+	for (;;) {
+		start = m->ticks;
+		do{
+			/* timeout seconds to first char */
+			if(timeout && ((m->ticks - start) > timeout*HZ))
+				return -2;
+			c = consiq.getc(&consiq);
+		}while(c == -1);
+		timeout = 0;
+
+		if(c == '\r')
+			c = '\n'; 		/* turn carriage return into newline */
+		if(c == '\177')
+			c = '\010';		/* turn delete into backspace */
+		if(c == '\025')
+			echo = '\n';		/* echo ^U as a newline */
+		else
+			echo = c;
+		consputs(&echo, 1);
+
+		if(c == '\010'){
+			if(i > 0)
+				i--; /* bs deletes last character */
+			continue;
+		}
+		/* a newline ends a line */
+		if (c == '\n')
+			break;
+		/* ^U wipes out the line */
+		if (c =='\025')
+			return -1;
+		if(i == size)
+			return size;
+		buf[i++] = c;
+	}
+	buf[i] = 0;
+	return i;
+}
+
+int
+getstr(char *prompt, char *buf, int size, char *def, int timeout)
+{
+	int len, isdefault;
+	char pbuf[PRINTSIZE];
+
+	buf[0] = 0;
+	isdefault = (def && *def);
+	if(isdefault == 0){
+		timeout = 0;
+		sprint(pbuf, "%s: ", prompt);
+	}
+	else if(timeout)
+		sprint(pbuf, "%s[default==%s (%ds timeout)]: ", prompt, def, timeout);
+	else
+		sprint(pbuf, "%s[default==%s]: ", prompt, def);
+	for (;;) {
+		print(pbuf);
+		len = getline(buf, size, timeout);
+		switch(len){
+		case 0:
+			/* RETURN */
+			if(isdefault)
+				break;
+			continue;
+		case -1:
+			/* ^U typed */
+			continue;
+		case -2:
+			/* timeout, use default */
+			consputs("\n", 1);
+			len = 0;
+			break;
+		default:
+			break;
+		}
+		if(len >= size){
+			print("line too long\n");
+			continue;
+		}
+		break;
+	}
+	if(len == 0 && isdefault)
+		strcpy(buf, def);
+	return 0;
+}
+
+int
+print(char *fmt, ...)
+{
+	int n;
+	va_list arg;
+	char buf[PRINTSIZE];
+
+	va_start(arg, fmt);
+	n = vseprint(buf, buf+sizeof(buf), fmt, arg) - buf;
+	va_end(arg);
+	consputs(buf, n);
+
+	return n;
+}
+
+int
+sprint(char *s, char *fmt, ...)
+{
+	int n;
+	va_list arg;
+
+	va_start(arg, fmt);
+	n = vseprint(s, s+PRINTSIZE, fmt, arg) - s;
+	va_end(arg);
+
+	return n;
+}
+
+void
+panic(char *fmt, ...)
+{
+	int n;
+	va_list arg;
+	char buf[PRINTSIZE];
+
+	strcpy(buf, "panic: ");
+	va_start(arg, fmt);
+	n = vseprint(buf+7, buf+sizeof(buf), fmt, arg) - buf;
+	va_end(arg);
+	buf[n] = '\n';
+	consputs(buf, n+1);
+
+//floppymemwrite();
+//splhi(); for(;;);
+	if(etherdetach)
+		etherdetach();
+	if(sddetach)
+		sddetach();
+
+	consputs("\nPress almost any key to reset...", 32);
+	spllo();
+	while(consiq.getc(&consiq) == -1)
+		;
+
+	warp86(nil, 0);
+}
--- /dev/null
+++ b/os/boot.original/pc/dat.h
@@ -1,0 +1,215 @@
+typedef struct List {
+	void	*next;
+} List;
+
+typedef struct Alarm Alarm;
+typedef struct Alarm {
+	List;
+	int	busy;
+	long	dt;
+	void	(*f)(Alarm*);
+	void	*arg;
+} Alarm;
+
+typedef struct Apminfo {
+	int haveinfo;
+	int ax;
+	int cx;
+	int dx;
+	int di;
+	int ebx;
+	int esi;
+} Apminfo;
+
+typedef struct Block Block;
+struct Block {
+	Block*	next;
+	uchar*	rp;			/* first unconsumed byte */
+	uchar*	wp;			/* first empty byte */
+	uchar*	lim;			/* 1 past the end of the buffer */
+	uchar*	base;			/* start of the buffer */
+	ulong	flag;
+};
+#define BLEN(s)	((s)->wp - (s)->rp)
+
+typedef struct IOQ IOQ;
+typedef struct IOQ {
+	uchar	buf[4096];
+	uchar	*in;
+	uchar	*out;
+	int	state;
+	int	(*getc)(IOQ*);
+	int	(*putc)(IOQ*, int);
+	void	*ptr;
+};
+
+enum {
+	Eaddrlen	= 6,
+	/* next two exclude 4-byte ether CRC */
+	ETHERMINTU	= 60,		/* minimum transmit size */
+	ETHERMAXTU	= 1514,		/* maximum transmit size */
+	ETHERHDRSIZE	= 14,		/* size of an ethernet header */
+
+	MaxEther	= 6,
+};
+
+typedef struct {
+	uchar	d[Eaddrlen];
+	uchar	s[Eaddrlen];
+	uchar	type[2];
+	uchar	data[1500];
+	uchar	crc[4];
+} Etherpkt;
+
+extern uchar broadcast[Eaddrlen];
+
+typedef struct Ureg Ureg;
+#pragma incomplete Ureg
+
+typedef struct Segdesc {
+	ulong	d0;
+	ulong	d1;
+} Segdesc;
+
+typedef struct Mach {
+	ulong	ticks;			/* of the clock since boot time */
+	void	*alarm;			/* alarms bound to this clock */
+} Mach;
+
+extern Mach *m;
+
+#define I_MAGIC		((((4*11)+0)*11)+7)
+
+typedef struct Exec Exec;
+struct	Exec
+{
+	uchar	magic[4];		/* magic number */
+	uchar	text[4];	 	/* size of text segment */
+	uchar	data[4];	 	/* size of initialized data */
+	uchar	bss[4];	  		/* size of uninitialized data */
+	uchar	syms[4];	 	/* size of symbol table */
+	uchar	entry[4];	 	/* entry point */
+	uchar	spsz[4];		/* size of sp/pc offset table */
+	uchar	pcsz[4];		/* size of pc/line number table */
+};
+
+/*
+ *  a parsed .ini line
+ */
+#define ISAOPTLEN	32
+#define NISAOPT		8
+
+typedef struct  ISAConf {
+	char	type[NAMELEN];
+	ulong	port;
+	ulong	irq;
+	ulong	mem;
+	ulong	size;
+	uchar	ea[6];
+
+	int	nopt;
+	char	opt[NISAOPT][ISAOPTLEN];
+} ISAConf;
+
+typedef struct Pcidev Pcidev;
+typedef struct PCMmap PCMmap;
+typedef struct PCMslot PCMslot;
+
+#define BOOTLINE	((char*)CONFADDR)
+
+enum {
+	MB =		(1024*1024),
+};
+#define ROUND(s, sz)	(((s)+((sz)-1))&~((sz)-1))
+
+
+typedef struct Type Type;
+typedef struct Medium Medium;
+typedef struct Boot Boot;
+
+enum {					/* type */
+	Tnil		= 0x00,
+
+	Tfloppy		= 0x01,
+	Tsd		= 0x02,
+	Tether		= 0x03,
+	Tcd		= 0x04,
+	Tbios		= 0x05,
+
+	Tany		= -1,
+};
+
+enum {					/* name and flag */
+	Fnone		= 0x00,
+
+	Nfs		= 0x00,
+	Ffs		= (1<<Nfs),
+	Nboot		= 0x01,
+	Fboot		= (1<<Nboot),
+	Nbootp		= 0x02,
+	Fbootp		= (1<<Nbootp),
+	NName		= 3,
+
+	Fany		= Fbootp|Fboot|Ffs,
+
+	Fini		= 0x10,
+	Fprobe		= 0x80,
+};
+
+typedef struct Type {
+	int	type;
+	int	flag;
+	int	(*init)(void);
+	void	(*initdev)(int, char*);
+	void*	(*getfspart)(int, char*, int);	/* actually returns Dos* */
+	void	(*addconf)(int);
+	int	(*boot)(int, char*, Boot*);
+	void	(*printdevs)(int);
+	char**	parts;
+	char**	inis;
+	int	mask;
+	Medium*	media;
+} Type;
+
+extern void (*etherdetach)(void);
+extern void (*floppydetach)(void);
+extern void (*sddetach)(void);
+
+typedef struct Lock {	/* for ilock, iunlock */
+	int locked;
+	int spl;
+} Lock;
+
+enum {	/* returned by bootpass */
+	MORE, ENOUGH, FAIL
+};
+enum {
+	INITKERNEL,
+	READEXEC,
+	READ9TEXT,
+	READ9DATA,
+	READGZIP,
+	READEHDR,
+	READPHDR,
+	READEPAD,
+	READEDATA,
+	TRYBOOT,
+	INIT9LOAD,
+	READ9LOAD,
+	FAILED
+};
+
+struct Boot {
+	int state;
+
+	Exec exec;
+	char *bp;	/* base ptr */
+	char *wp;	/* write ptr */
+	char *ep;	/* end ptr */
+};
+
+extern int	debug;
+extern Apminfo	apm;
+extern char	*defaultpartition;
+extern int	iniread;
+extern int	pxe;
--- /dev/null
+++ b/os/boot.original/pc/devbios.c
@@ -1,0 +1,428 @@
+/*
+ * boot driver for BIOS devices
+ */
+#include <u.h>
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "ureg.h"
+#include "fs.h"
+
+typedef uvlong Devbytes, Devsects;
+
+typedef struct Biosdrive Biosdrive;	/* 1 drive -> ndevs */
+typedef struct Biosdev Biosdev;
+
+enum {
+	Debug = 0,
+	Maxdevs = 4,
+
+	CF = 1,
+	Flopid = 0,			/* first floppy */
+	Baseid = 0x80,			/* first disk */
+
+	/* bios calls: int 13 disk services */
+	Biosinit	= 0,		/* initialise disk & floppy ctlrs */
+	Biosdrvsts,
+	Bioschsrdsects,
+	Biosdrvparam	= 8,
+	Biosctlrinit,
+	Biosreset	=  0xd,		/* reset disk */
+	Biosdrvrdy	= 0x10,
+	Biosdrvtype	= 0x15,
+	Biosckext	= 0x41,
+	Biosrdsect,
+	Biosedrvparam	= 0x48,
+
+	/* disk types */
+	Typenone = 0,
+	Typedisk = 3,
+};
+
+struct Biosdrive {
+	int	ndevs;
+};
+struct Biosdev {
+	Devbytes size;
+	Devbytes offset;
+	uchar	id;			/* drive number; e.g., 0x80 */
+	char	type;
+	ushort	sectsz;
+};
+
+typedef struct Extread {
+	uchar	size;
+	uchar	unused1;
+	uchar	nsects;
+	uchar	unused2;
+	ulong	addr;		/* segment:offset */
+	uvlong	stsect;		/* starting sector */
+} Extread;
+typedef struct Edrvparam {
+	/* from edd 1.1 spec */
+	ushort	size;			/* max. buffer size */
+	ushort	flags;
+	ulong	physcyls;
+	ulong	physheads;
+	ulong	phystracksects;
+	uvlong	physsects;
+	ushort	sectsz;
+	void	*dpte;			/* ~0ull: invalid */
+
+	/* remainder from edd 3.0 spec */
+	ushort	key;			/* 0xbedd if present */
+	uchar	dpilen;
+	uchar	unused1;
+	ushort	unused2;
+	char	bustype[4];		/* "PCI" or "ISA" */
+	char	ifctype[8]; /* "ATA", "ATAPI", "SCSI", "USB", "1394", "FIBRE" */
+	uvlong	ifcpath;
+	uvlong	devpath;
+	uchar	unused3;
+	uchar	dpicksum;
+} Edrvparam;
+
+void	realmode(int intr, Ureg *ureg);		/* from trap.c */
+
+int onlybios0;
+int biosinited;
+
+static Biosdev bdev[Maxdevs];
+static Biosdrive bdrive;
+static Ureg regs;
+
+static int	dreset(uchar drive);
+static Devbytes	extgetsize(Biosdev *);
+static Devsects	getsize(uchar drive, char *type);
+static int	islba(uchar drive);
+
+static int
+biosdiskcall(Ureg *rp, uchar op, ulong bx, ulong dx, ulong si)
+{
+	memset(rp, 0, sizeof *rp);
+	rp->ax = op << 8;
+	rp->bx = bx;
+	rp->dx = dx;			/* often drive id */
+	rp->si = si;
+	/* pass command in *rp, get results from there */
+	realmode(0x13, rp);
+	if (rp->flags & CF) {
+//		print("biosdiskcall: int 13 op 0x%ux drive 0x%lux failed, "
+//			"ah error code 0x%ux\n", op, dx, (uchar)(rp->ax >> 8));
+		return -1;
+	}
+	return 0;
+}
+
+/*
+ * Find out what the bios knows about devices.
+ * our boot device could be usb; ghod only knows where it will appear.
+ */
+int
+biosinit(void)
+{
+	int devid, lba, mask, lastbit;
+	Devbytes size;
+	char type;
+	Biosdev *bdp;
+	static int beenhere;
+
+	mask = lastbit = 0;
+	if (beenhere)
+		return mask;
+	beenhere = 1;
+	/* 9pxeload can't use bios int 13 calls; they wedge the machine */
+	if (pxe || getconf("*nobiosload") != nil || onlybios0 || !biosinited)
+		return mask;
+	for (devid = 0; devid < (1 << 8) && bdrive.ndevs < Maxdevs; devid++) {
+		lba = islba(devid);
+		if(!lba /* || devid != Baseid && dreset(devid) < 0 */ )
+			continue;
+		type = Typedisk;		/* HACK */
+		if (getsize(devid, &type) == 0) { /* no device, end of range */
+			devid &= ~0xf;
+			devid += 0x10;
+			devid--;
+			continue;
+		}
+		lastbit = 1 << bdrive.ndevs;
+		mask |= lastbit;
+		bdp = &bdev[bdrive.ndevs];
+		bdp->id = devid;
+		bdp->type = type;
+		size = extgetsize(bdp);
+		bdp->size = size;
+		print("bios%d: drive 0x%ux: %llud bytes, type %d\n",
+			bdrive.ndevs, devid, size, type);
+		bdrive.ndevs++;
+	}
+	/*
+	 * bioses seem to only be able to read from drive number 0x80
+	 * and certainly can't read from the highest drive number when we
+	 * call them, even if there is only one.  attempting to read from
+	 * the last drive number yields a hung machine or a two-minute pause.
+	 */
+	if (bdrive.ndevs > 0) {
+		if (bdrive.ndevs == 1) {
+			print("biosinit: sorry, only one bios drive; "
+				"can't read last one\n");
+			onlybios0 = 1;
+		} else
+			biosinited = 1;
+		bdrive.ndevs--;	/* omit last drive number; it can't be read */
+		mask &= ~lastbit;
+	}
+	return mask;
+}
+
+void
+biosinitdev(int i, char *name)
+{
+	if(i >= bdrive.ndevs)
+		panic("biosinitdev");
+	sprint(name, "bios%d", i);
+}
+
+void
+biosprintdevs(int i)
+{
+	if(i >= bdrive.ndevs){
+		print("got a print for %d, only got %d\n", i, bdrive.ndevs);
+		panic("biosprintdevs");
+	}
+	print(" bios%d", i);
+}
+
+int
+biosboot(int dev, char *file, Boot *b)
+{
+	Fs *fs;
+
+	if(strncmp(file, "dos!", 4) == 0)
+		file += 4;
+	if(strchr(file, '!') != nil || strcmp(file, "") == 0) {
+		print("syntax is bios0!file\n");
+		return -1;
+	}
+
+	fs = biosgetfspart(dev, "9fat", 1);
+	if(fs == nil)
+		return -1;
+	return fsboot(fs, file, b);
+}
+
+/* read n bytes at sector offset into a from drive id */
+long
+sectread(Biosdev *bdp, void *a, long n, Devsects offset)
+{
+	uchar *biosparam, *cp;
+	Extread *erp;
+
+	if(n < 0 || n > bdp->sectsz)
+		return -1;
+	if(Debug)
+		memset((uchar *)BIOSXCHG, 'r', bdp->sectsz); /* preclean the buffer. */
+
+	biosdiskcall(&regs, Biosdrvrdy, 0, bdp->id, 0);
+
+	/* space for a BIG sector, just in case... */
+	biosparam = (uchar *)BIOSXCHG + 2*1024;
+
+	/* read into BIOSXCHG */
+	erp = (Extread *)biosparam;
+	memset(erp, 0, sizeof *erp);
+	erp->size = sizeof *erp;
+	erp->nsects = 1;
+	erp->addr = PADDR(BIOSXCHG);
+	erp->stsect = offset;
+	if (biosdiskcall(&regs, Biosrdsect, 0, bdp->id, PADDR(erp)) < 0) {
+		print("sectread: bios failed to read %ld @ sector %lld of 0x%ux\n",
+			n, offset, bdp->id);
+		return -1;
+	}
+
+	/* copy into caller's buffer */
+	memmove(a, (char *)BIOSXCHG, n);
+	if(Debug){
+		cp = (uchar *)BIOSXCHG;
+		print("-%ux %ux %ux %ux--%16.16s-\n",
+			cp[0], cp[1], cp[2], cp[3], (char *)cp + 480);
+	}
+	return n;
+}
+
+/* not tested yet. */
+static int
+dreset(uchar drive)
+{
+if (0) {
+print("devbios: resetting disk controllers...");
+	biosdiskcall(&regs, Biosinit, 0, drive, 0);
+print("\n");
+}
+	return regs.ax? -1: 0;		/* ax!=0 on error */
+}
+
+static int
+islba(uchar drive)
+{
+	if (biosdiskcall(&regs, Biosckext, 0x55aa, drive, 0) < 0)
+		return 0;
+	if(regs.bx != 0xaa55){
+		print("islba: buggy bios\n");
+		return 0;
+	}
+	if (Debug)
+		print("islba: drive 0x%ux extensions version %d.%d cx 0x%lux\n",
+			drive, (uchar)(regs.ax >> 8),
+			(uchar)regs.ax, regs.cx); /* cx: 4=edd, 1=use dap */
+	return regs.cx & 1;		/* dap bit */
+}
+
+/*
+ * works so so... some floppies are 0x80+x when they shouldn't be,
+ * and report lba even if they cannot...
+ */
+static Devsects
+getsize(uchar id, char *typep)
+{
+	int dtype;
+
+	if (biosdiskcall(&regs, Biosdrvtype, 0x55aa, id, 0) < 0)
+		return 0;
+
+	dtype = (ushort)regs.ax >> 8;
+	if(dtype == Typenone){
+		print("no such device 0x%ux of type %d\n", id, dtype);
+		return 0;
+	}
+	if(dtype != Typedisk){
+		print("non-disk device 0x%ux of type %d\n", id, dtype);
+		return 0;
+	}
+	*typep = dtype;
+	return (ushort)regs.cx | regs.dx << 16;
+}
+
+/* extended get size */
+static Devbytes
+extgetsize(Biosdev *bdp)
+{
+	Edrvparam *edp;
+
+	edp = (Edrvparam *)BIOSXCHG;
+	memset(edp, 0, sizeof *edp);
+	edp->size = sizeof *edp;
+	edp->dpilen = 36;
+	if (biosdiskcall(&regs, Biosedrvparam, 0, bdp->id, PADDR(edp)) < 0)
+		return 0;
+	if(Debug) {
+		print("extgetsize: drive 0x%ux info flags 0x%ux",
+			bdp->id, edp->flags);
+		if (edp->key == 0xbedd)
+			print(" %s %s", edp->bustype, edp->ifctype);
+		print("\n");
+	}
+	if (edp->sectsz <= 0) {
+		print("extgetsize: drive 0x%ux: non-positive sector size\n",
+			bdp->id);
+		edp->sectsz = 1;		/* don't divide by zero */
+	}
+	bdp->sectsz = edp->sectsz;
+	return edp->physsects * edp->sectsz;
+}
+
+long
+biosread(Fs *fs, void *a, long n)
+{
+	int want, got, part;
+	long totnr, stuck;
+	Devbytes offset;
+	Biosdev *bdp;
+
+	if(fs->dev > bdrive.ndevs)
+		return -1;
+	if (n <= 0)
+		return n;
+	bdp = &bdev[fs->dev];
+	offset = bdp->offset;
+	stuck = 0;
+	for (totnr = 0; totnr < n && stuck < 4; totnr += got) {
+		want = bdp->sectsz;
+		if (totnr + want > n)
+			want = n - totnr;
+		if(Debug)
+			print("bios%d, read: %ld @ off %lld, want: %d, id: 0x%ux\n",
+				fs->dev, n, offset, want, bdp->id);
+		part = offset % bdp->sectsz;
+		if (part != 0) {	/* back up to start of sector */
+			offset -= part;
+			totnr  -= part;
+			if (totnr < 0) {
+				print("biosread: negative count %ld\n", totnr);
+				return -1;
+			}
+		}
+		if ((vlong)offset < 0) {
+			print("biosread: negative offset %lld\n", offset);
+			return -1;
+		}
+		got = sectread(bdp, (char *)a + totnr, want, offset/bdp->sectsz);
+		if(got <= 0){
+//			print("biosread: failed to read %ld @ off %lld of 0x%ux, "
+//				"want %d got %d\n",
+//				n, offset, bdp->id, want, got);
+			return -1;
+		}
+		offset += got;
+		bdp->offset = offset;
+		if (got < bdp->sectsz)
+			stuck++;	/* we'll have to re-read this sector */
+		else
+			stuck = 0;
+	}
+	return totnr;
+}
+
+vlong
+biosseek(Fs *fs, vlong off)
+{
+	if (off < 0) {
+		print("biosseek(fs, %lld) is illegal\n", off);
+		return -1;
+	}
+	if(fs->dev > bdrive.ndevs) {
+		print("biosseek: fs->dev %d > bdrive.ndevs %d\n",
+			fs->dev, bdrive.ndevs);
+		return -1;
+	}
+	bdev[fs->dev].offset = off;	/* do not know size... (yet) */
+	return off;
+}
+
+void *
+biosgetfspart(int i, char *name, int chatty)
+{
+	static Fs fs;
+
+	if(strcmp(name, "9fat") != 0){
+		if(chatty)
+			print("unknown partition bios%d!%s (use bios%d!9fat)\n",
+				i, name, i);
+		return nil;
+	}
+
+	fs.dev = i;
+	fs.diskread = biosread;
+	fs.diskseek = biosseek;
+
+	if(dosinit(&fs) < 0){
+		if(chatty)
+			print("bios%d!%s does not contain a FAT file system\n",
+				i, name);
+		return nil;
+	}
+	return &fs;
+}
--- /dev/null
+++ b/os/boot.original/pc/devbios.h
@@ -1,0 +1,22 @@
+typedef uvlong Devbytes, Devsects;
+
+typedef struct Biosdrive Biosdrive;	/* 1 drive -> ndevs */
+typedef struct Biosdev Biosdev;
+
+struct Biosdrive {
+	int	ndevs;
+};
+struct Biosdev {
+	Devbytes size;
+	Devbytes offset;
+	uchar	id;
+	char	type;
+};
+
+int	biosboot(int dev, char *file, Boot *b);
+void*	biosgetfspart(int i, char *name, int chatty);
+void	biosinitdev(int i, char *name);
+int	biosinit(void);
+void	biosprintbootdevs(int dev);
+void	biosprintdevs(int i);
+long	biosread(Fs *fs, void *a, long n);
--- /dev/null
+++ b/os/boot.original/pc/devfloppy.c
@@ -1,0 +1,853 @@
+#include <u.h>
+
+#include	"lib.h"
+#include	"mem.h"
+#include	"dat.h"
+#include	"fns.h"
+#include	"io.h"
+#include	"ureg.h"
+
+#include	"fs.h"
+#include	"devfloppy.h"
+
+
+/* Intel 82077A (8272A compatible) floppy controller */
+
+/* This module expects the following functions to be defined
+ * elsewhere: 
+ * 
+ * inb()
+ * outb()
+ * floppyexec()
+ * floppyeject() 
+ * floppysetup0()
+ * floppysetup1()
+ * dmainit()
+ * dmasetup()
+ * dmaend()
+ * 
+ * On DMA systems, floppyexec() should be an empty function; 
+ * on non-DMA systems, dmaend() should be an empty function; 
+ * dmasetup() may enforce maximum transfer sizes. 
+ */
+
+enum {
+	/* file types */
+	Qdir=		0, 
+	Qdata=		(1<<2),
+	Qctl=		(2<<2),
+	Qmask=		(3<<2),
+
+	DMAchan=	2,	/* floppy dma channel */
+};
+
+#define DPRINT if(0)print
+
+FType floppytype[] =
+{
+ { "3½HD",	T1440kb, 512, 18, 2, 1, 80, 0x1B, 0x54,	0, },
+ { "3½DD",	T1440kb, 512,  9, 2, 1, 80, 0x1B, 0x54, 2, },
+ { "3½DD",	T720kb,  512,  9, 2, 1, 80, 0x1B, 0x54, 2, },
+ { "5¼HD",	T1200kb, 512, 15, 2, 1, 80, 0x2A, 0x50, 0, },
+ { "5¼DD",	T1200kb, 512,  9, 2, 2, 40, 0x2A, 0x50, 1, },
+ { "ATT3B1",	T1200kb, 512,  8, 2, 2, 48, 0x2A, 0x50, 1, },
+ { "5¼DD",	T360kb,  512,  9, 2, 1, 40, 0x2A, 0x50, 2, },
+};
+
+/*
+ *  bytes per sector encoding for the controller.
+ *  - index for b2c is is (bytes per sector/128).
+ *  - index for c2b is code from b2c
+ */
+static int b2c[] =
+{
+[1]	0,
+[2]	1,
+[4]	2,
+[8]	3,
+};
+static int c2b[] =
+{
+	128,
+	256,
+	512,
+	1024,
+};
+
+FController	fl;
+
+#define MOTORBIT(i)	(1<<((i)+4))
+
+/*
+ *  predeclared
+ */
+static int	cmddone(void*);
+static void	floppyformat(FDrive*, char*);
+static void	floppykproc(void*);
+static void	floppypos(FDrive*,long);
+static int	floppyrecal(FDrive*);
+static int	floppyresult(void);
+static void	floppyrevive(void);
+static vlong	pcfloppyseek(FDrive*, vlong);
+static int	floppysense(void);
+static void	floppywait(int);
+static long	floppyxfer(FDrive*, int, void*, long, long);
+
+static void
+fldump(void)
+{
+	DPRINT("sra %ux srb %ux dor %ux msr %ux dir %ux\n", inb(Psra), inb(Psrb),
+		inb(Pdor), inb(Pmsr), inb(Pdir));
+}
+
+static void
+floppyalarm(Alarm* a)
+{
+	FDrive *dp;
+
+	for(dp = fl.d; dp < &fl.d[fl.ndrive]; dp++){
+		if((fl.motor&MOTORBIT(dp->dev)) && TK2SEC(m->ticks - dp->lasttouched) > 5)
+			floppyoff(dp);
+	}
+
+	alarm(5*1000, floppyalarm, 0);
+	cancel(a);
+}
+
+/*
+ *  set floppy drive to its default type
+ */
+static void
+floppysetdef(FDrive *dp)
+{
+	FType *t;
+
+	for(t = floppytype; t < &floppytype[nelem(floppytype)]; t++)
+		if(dp->dt == t->dt){
+			dp->t = t;
+			break;
+		}
+}
+
+static void
+_floppydetach(void)
+{
+	/*
+	 *  stop the motors
+	 */
+	fl.motor = 0;
+	delay(10);
+	outb(Pdor, fl.motor | Fintena | Fena);
+	delay(10);
+}
+
+int
+floppyinit(void)
+{
+	FDrive *dp;
+	FType *t;
+	ulong maxtsize;
+	int mask;
+
+	dmainit(DMAchan);
+
+	floppysetup0(&fl);
+
+	/*
+	 *  init dependent parameters
+	 */
+	maxtsize = 0;
+	for(t = floppytype; t < &floppytype[nelem(floppytype)]; t++){
+		t->cap = t->bytes * t->heads * t->sectors * t->tracks;
+		t->bcode = b2c[t->bytes/128];
+		t->tsize = t->bytes * t->sectors;
+		if(maxtsize < t->tsize)
+			maxtsize = t->tsize;
+	}
+
+	fl.selected = fl.d;
+
+	floppydetach = _floppydetach;
+	floppydetach();
+
+	/*
+	 *  init drives
+	 */
+	mask = 0;
+	for(dp = fl.d; dp < &fl.d[fl.ndrive]; dp++){
+		dp->dev = dp - fl.d;
+		if(dp->dt == Tnone)
+			continue;
+		mask |= 1<<dp->dev;
+		floppysetdef(dp);
+		dp->cyl = -1;			/* because we don't know */
+		dp->cache = (uchar*)xspanalloc(maxtsize, BY2PG, 64*1024);
+		dp->ccyl = -1;
+		dp->vers = 0;
+		dp->maxtries = 5;
+	}
+
+	/*
+	 *  first operation will recalibrate
+	 */
+	fl.confused = 1;
+
+	floppysetup1(&fl);
+
+	/* to turn the motor off when inactive */
+	alarm(5*1000, floppyalarm, 0);
+
+	return mask;
+}
+
+void
+floppyinitdev(int i, char *name)
+{
+	if(i >= fl.ndrive)
+		panic("floppyinitdev");
+	sprint(name, "fd%d", i);
+}
+
+void
+floppyprintdevs(int i)
+{
+	if(i >= fl.ndrive)
+		panic("floppyprintdevs");
+	print(" fd%d", i);
+}
+
+int
+floppyboot(int dev, char *file, Boot *b)
+{
+	Fs *fs;
+
+	if(strncmp(file, "dos!", 4) == 0)
+		file += 4;
+	else if(strchr(file, '!') || strcmp(file, "")==0) {
+		print("syntax is fd0!file\n");
+		return -1;
+	}
+
+	fs = floppygetfspart(dev, "dos", 1);
+	if(fs == nil)
+		return -1;
+
+	return fsboot(fs, file, b);
+}
+
+void
+floppyprintbootdevs(int dev)
+{
+	print(" fd%d", dev);
+}
+
+/*
+ *  check if the floppy has been replaced under foot.  cause
+ *  an error if it has.
+ *
+ *  a seek and a read clears the condition.  this was determined
+ *  experimentally, there has to be a better way.
+ *
+ *  if the read fails, cycle through the possible floppy
+ *  density till one works or we've cycled through all
+ *  possibilities for this drive.
+ */
+static int
+changed(FDrive *dp)
+{
+	FType *start;
+
+	/*
+	 *  if floppy has changed or first time through
+	 */
+	if((inb(Pdir)&Fchange) || dp->vers == 0){
+		DPRINT("changed\n");
+		fldump();
+		dp->vers++;
+		floppysetdef(dp);
+		dp->maxtries = 3;
+		start = dp->t;
+
+		/* flopppyon fails if there's no drive */
+		dp->confused = 1;	/* make floppyon recal */
+		if(floppyon(dp) < 0)
+			return -1;
+
+		pcfloppyseek(dp, dp->t->heads*dp->t->tsize);
+
+		while(floppyxfer(dp, Fread, dp->cache, 0, dp->t->tsize) <= 0){
+
+			/*
+			 *  if the xfer attempt doesn't clear the changed bit,
+			 *  there's no floppy in the drive
+			 */
+			if(inb(Pdir)&Fchange)
+				return -1;
+
+			while(++dp->t){
+				if(dp->t == &floppytype[nelem(floppytype)])
+					dp->t = floppytype;
+				if(dp->dt == dp->t->dt)
+					break;
+			}
+
+			/* flopppyon fails if there's no drive */
+			if(floppyon(dp) < 0)
+				return -1;
+
+			DPRINT("changed: trying %s\n", dp->t->name);
+			fldump();
+			if(dp->t == start)
+				return -1;
+		}
+	}
+
+	return 0;
+}
+
+static int
+readtrack(FDrive *dp, int cyl, int head)
+{
+	int i, nn, sofar;
+	ulong pos;
+
+	nn = dp->t->tsize;
+	if(dp->ccyl==cyl && dp->chead==head)
+		return nn;
+	pos = (cyl*dp->t->heads+head) * nn;
+	for(sofar = 0; sofar < nn; sofar += i){
+		dp->ccyl = -1;
+		i = floppyxfer(dp, Fread, dp->cache + sofar, pos + sofar, nn - sofar);
+		if(i <= 0)
+			return -1;
+	}
+	dp->ccyl = cyl;
+	dp->chead = head;
+	return nn;
+}
+
+long
+floppyread(Fs *fs, void *a, long n)
+{
+	FDrive *dp;
+	long rv, offset;
+	int sec, head, cyl;
+	long len;
+	uchar *aa;
+
+	aa = a;
+	dp = &fl.d[fs->dev];
+
+	offset = dp->offset;
+	floppyon(dp);
+	if(changed(dp))
+		return -1;
+
+	for(rv = 0; rv < n; rv += len){
+		/*
+		 *  all xfers come out of the track cache
+		 */
+		dp->len = n - rv;
+		floppypos(dp, offset+rv);
+		cyl = dp->tcyl;
+		head = dp->thead;
+		len = dp->len;
+		sec = dp->tsec;
+		if(readtrack(dp, cyl, head) < 0)
+			break;
+		memmove(aa+rv, dp->cache + (sec-1)*dp->t->bytes, len);
+	}
+	dp->offset = offset+rv;
+
+	return rv;
+}
+
+void*
+floppygetfspart(int i, char *name, int chatty)
+{
+	static Fs fs;
+
+	if(strcmp(name, "dos") != 0){
+		if(chatty)
+			print("unknown partition fd%d!%s (use fd%d!dos)\n", i, name, i);
+		return nil;
+	}
+
+	fs.dev = i;
+	fs.diskread = floppyread;
+	fs.diskseek = floppyseek;
+
+	/* sometimes we get spurious errors and doing it again works */
+	if(dosinit(&fs) < 0 && dosinit(&fs) < 0){
+		if(chatty)
+			print("fd%d!%s does not contain a FAT file system\n", i, name);
+		return nil;
+	}
+	return &fs;
+}
+
+static int
+return0(void*)
+{
+	return 0;
+}
+
+static void
+timedsleep(int (*f)(void*), void* arg, int ms)
+{
+	int s;
+	ulong end;
+
+	end = m->ticks + 1 + MS2TK(ms);
+	while(m->ticks < end && !(*f)(arg)){
+		s = spllo();
+		delay(10);
+		splx(s);
+	}
+}
+
+/*
+ *  start a floppy drive's motor.
+ */
+static int
+floppyon(FDrive *dp)
+{
+	int alreadyon;
+	int tries;
+
+	if(fl.confused)
+		floppyrevive();
+
+	/* start motor and select drive */
+	dp->lasttouched = m->ticks;
+	alreadyon = fl.motor & MOTORBIT(dp->dev);
+	if(!alreadyon){
+		fl.motor |= MOTORBIT(dp->dev);
+		outb(Pdor, fl.motor | Fintena | Fena | dp->dev);
+		/* wait for drive to spin up */
+		timedsleep(return0, 0, 750);
+
+		/* clear any pending interrupts */
+		floppysense();
+	}
+
+	/* set transfer rate */
+	if(fl.rate != dp->t->rate){
+		fl.rate = dp->t->rate;
+		outb(Pdsr, fl.rate);
+	}
+
+	/* get drive to a known cylinder */
+	if(dp->confused)
+		for(tries = 0; tries < 4; tries++)
+			if(floppyrecal(dp) >= 0)
+				break;
+	dp->lasttouched = m->ticks;
+	fl.selected = dp;
+	if(dp->confused)
+		return -1;
+	return 0;
+}
+
+/*
+ *  stop the floppy if it hasn't been used in 5 seconds
+ */
+static void
+floppyoff(FDrive *dp)
+{
+	fl.motor &= ~MOTORBIT(dp->dev);
+	outb(Pdor, fl.motor | Fintena | Fena | dp->dev);
+}
+
+/*
+ *  send a command to the floppy
+ */
+static int
+floppycmd(void)
+{
+	int i;
+	int tries;
+
+	fl.nstat = 0;
+	for(i = 0; i < fl.ncmd; i++){
+		for(tries = 0; ; tries++){
+			if((inb(Pmsr)&(Ffrom|Fready)) == Fready)
+				break;
+			if(tries > 1000){
+				DPRINT("cmd %ux can't be sent (%d)\n", fl.cmd[0], i);
+				fldump();
+
+				/* empty fifo, might have been a bad command */
+				floppyresult();
+				return -1;
+			}
+			microdelay(1);
+		}
+		outb(Pfdata, fl.cmd[i]);
+	}
+	return 0;
+}
+
+/*
+ *  get a command result from the floppy
+ *
+ *  when the controller goes ready waiting for a command
+ *  (instead of sending results), we're done
+ * 
+ */
+static int
+floppyresult(void)
+{
+	int i, s;
+	int tries;
+
+	/* get the result of the operation */
+	for(i = 0; i < sizeof(fl.stat); i++){
+		/* wait for status byte */
+		for(tries = 0; ; tries++){
+			s = inb(Pmsr)&(Ffrom|Fready);
+			if(s == Fready){
+				fl.nstat = i;
+				return fl.nstat;
+			}
+			if(s == (Ffrom|Fready))
+				break;
+			if(tries > 1000){
+				DPRINT("floppyresult: %d stats\n", i);
+				fldump();
+				fl.confused = 1;
+				return -1;
+			}
+			microdelay(1);
+		}
+		fl.stat[i] = inb(Pfdata);
+	}
+	fl.nstat = sizeof(fl.stat);
+	return fl.nstat;
+}
+
+/*
+ *  calculate physical address of a logical byte offset into the disk
+ *
+ *  truncate dp->length if it crosses a track boundary
+ */
+static void
+floppypos(FDrive *dp, long off)
+{
+	int lsec;
+	int ltrack;
+	int end;
+
+	lsec = off/dp->t->bytes;
+	ltrack = lsec/dp->t->sectors;
+	dp->tcyl = ltrack/dp->t->heads;
+	dp->tsec = (lsec % dp->t->sectors) + 1;
+	dp->thead = (lsec/dp->t->sectors) % dp->t->heads;
+
+	/*
+	 *  can't read across track boundaries.
+	 *  if so, decrement the bytes to be read.
+	 */
+	end = (ltrack+1)*dp->t->sectors*dp->t->bytes;
+	if(off+dp->len > end)
+		dp->len = end - off;
+}
+
+/*
+ *  get the interrupt cause from the floppy.
+ */
+static int
+floppysense(void)
+{
+	fl.ncmd = 0;
+	fl.cmd[fl.ncmd++] = Fsense;
+	if(floppycmd() < 0)
+		return -1;
+	if(floppyresult() < 2){
+		DPRINT("can't read sense response\n");
+		fldump();
+		fl.confused = 1;
+		return -1;
+	}
+	return 0;
+}
+
+static int
+cmddone(void *a)
+{
+	USED(a);
+	return fl.ncmd == 0;
+}
+
+/*
+ *  Wait for a floppy interrupt.  If none occurs in 5 seconds, we
+ *  may have missed one.  This only happens on some portables which
+ *  do power management behind our backs.  Call the interrupt
+ *  routine to try to clear any conditions.
+ */
+static void
+floppywait(int slow)
+{
+	timedsleep(cmddone, 0, slow ? 5000 : 1000);
+	if(!cmddone(0)){
+		floppyintr(0);
+		fl.confused = 1;
+	}
+}
+
+/*
+ *  we've lost the floppy position, go to cylinder 0.
+ */
+static int
+floppyrecal(FDrive *dp)
+{
+	dp->ccyl = -1;
+	dp->cyl = -1;
+
+	fl.ncmd = 0;
+	fl.cmd[fl.ncmd++] = Frecal;
+	fl.cmd[fl.ncmd++] = dp->dev;
+	if(floppycmd() < 0)
+		return -1;
+	floppywait(1);
+	if(fl.nstat < 2){
+		DPRINT("recalibrate: confused %ux\n", inb(Pmsr));
+		fl.confused = 1;
+		return -1;
+	}
+	if((fl.stat[0] & (Codemask|Seekend)) != Seekend){
+		DPRINT("recalibrate: failed\n");
+		dp->confused = 1;
+		return -1;
+	}
+	dp->cyl = fl.stat[1];
+	if(dp->cyl != 0){
+		DPRINT("recalibrate: wrong cylinder %d\n", dp->cyl);
+		dp->cyl = -1;
+		dp->confused = 1;
+		return -1;
+	}
+
+	dp->confused = 0;
+	return 0;
+}
+
+/*
+ *  if the controller or a specific drive is in a confused state,
+ *  reset it and get back to a kown state
+ */
+static void
+floppyrevive(void)
+{
+	FDrive *dp;
+
+	/*
+	 *  reset the controller if it's confused
+	 */
+	if(fl.confused){
+		DPRINT("floppyrevive in\n");
+		fldump();
+
+		/* reset controller and turn all motors off */
+		splhi();
+		fl.ncmd = 1;
+		fl.cmd[0] = 0;
+		outb(Pdor, 0);
+		delay(10);
+		outb(Pdor, Fintena|Fena);
+		delay(10);
+		spllo();
+		fl.motor = 0;
+		fl.confused = 0;
+		floppywait(0);
+
+		/* mark all drives in an unknown state */
+		for(dp = fl.d; dp < &fl.d[fl.ndrive]; dp++)
+			dp->confused = 1;
+
+		/* set rate to a known value */
+		outb(Pdsr, 0);
+		fl.rate = 0;
+
+		DPRINT("floppyrevive out\n");
+		fldump();
+	}
+}
+
+/*
+ *  seek to the target cylinder
+ *
+ *	interrupt, no results
+ */
+static vlong
+pcfloppyseek(FDrive *dp, vlong off)
+{
+	floppypos(dp, off);
+	if(dp->cyl == dp->tcyl){
+		dp->offset = off;
+		return off;
+	}
+	dp->cyl = -1;
+
+	fl.ncmd = 0;
+	fl.cmd[fl.ncmd++] = Fseek;
+	fl.cmd[fl.ncmd++] = (dp->thead<<2) | dp->dev;
+	fl.cmd[fl.ncmd++] = dp->tcyl * dp->t->steps;
+	if(floppycmd() < 0)
+		return -1;
+	floppywait(1);
+	if(fl.nstat < 2){
+		DPRINT("seek: confused\n");
+		fl.confused = 1;
+		return -1;
+	}
+	if((fl.stat[0] & (Codemask|Seekend)) != Seekend){
+		DPRINT("seek: failed\n");
+		dp->confused = 1;
+		return -1;
+	}
+
+	dp->cyl = dp->tcyl;
+	dp->offset = off;
+	DPRINT("seek to %d succeeded\n", dp->offset);
+
+	return dp->offset;
+}
+
+/*
+ *  read or write to floppy.  try up to three times.
+ */
+static long
+floppyxfer(FDrive *dp, int cmd, void *a, long off, long n)
+{
+	long offset;
+	int tries;
+
+	if(off >= dp->t->cap)
+		return 0;
+	if(off + n > dp->t->cap)
+		n = dp->t->cap - off;
+
+	/* retry on error (until it gets ridiculous) */
+	for(tries = 0; tries < dp->maxtries; tries++){
+
+		dp->len = n;
+		if(pcfloppyseek(dp, off) < 0){
+			DPRINT("xfer: seek failed\n");
+			dp->confused = 1;
+			continue;
+		}
+
+		/*
+		 *  set up the dma (dp->len may be trimmed)
+		 */
+		dp->len = dmasetup(DMAchan, a, dp->len, cmd==Fread);
+		if(dp->len < 0){
+	buggery:
+			dmaend(DMAchan);
+			continue;
+		}
+	
+		/*
+		 *  start operation
+		 */
+		fl.ncmd = 0;
+		fl.cmd[fl.ncmd++] = cmd | (dp->t->heads > 1 ? Fmulti : 0);
+		fl.cmd[fl.ncmd++] = (dp->thead<<2) | dp->dev;
+		fl.cmd[fl.ncmd++] = dp->tcyl;
+		fl.cmd[fl.ncmd++] = dp->thead;
+		fl.cmd[fl.ncmd++] = dp->tsec;
+		fl.cmd[fl.ncmd++] = dp->t->bcode;
+		fl.cmd[fl.ncmd++] = dp->t->sectors;
+		fl.cmd[fl.ncmd++] = dp->t->gpl;
+		fl.cmd[fl.ncmd++] = 0xFF;
+		if(floppycmd() < 0)
+			goto buggery;
+
+		/*
+		 *  give bus to DMA, floppyintr() will read result
+		 */
+		floppywait(0);
+		dmaend(DMAchan);
+
+		/*
+		 *  check for errors
+		 */
+		if(fl.nstat < 7){
+			DPRINT("xfer: confused\n");
+			fl.confused = 1;
+			continue;
+		}
+		if((fl.stat[0] & Codemask)!=0 || fl.stat[1] || fl.stat[2]){
+			DPRINT("xfer: failed %ux %ux %ux\n", fl.stat[0],
+				fl.stat[1], fl.stat[2]);
+			DPRINT("offset %lud len %ld\n", off, dp->len);
+			if((fl.stat[0]&Codemask)==Cmdexec && fl.stat[1]==Overrun){
+				DPRINT("DMA overrun: retry\n");
+			} else
+				dp->confused = 1;
+			continue;
+		}
+
+		/*
+		 *  check for correct cylinder
+		 */
+		offset = fl.stat[3] * dp->t->heads + fl.stat[4];
+		offset = offset*dp->t->sectors + fl.stat[5] - 1;
+		offset = offset * c2b[fl.stat[6]];
+		if(offset != off+dp->len){
+			DPRINT("xfer: ends on wrong cyl\n");
+			dp->confused = 1;
+			continue;
+		}
+	
+		dp->lasttouched = m->ticks;
+		dp->maxtries = 20;
+		return dp->len;
+	}
+
+	return -1;
+}
+
+/*
+void
+floppymemwrite(void)
+{
+	int i;
+	int n;
+	uchar *a;
+	FDrive *dp;
+
+	dp = &fl.d[0];
+	a = (uchar*)0x80000000;
+	n = 0;
+	while(n < 1440*1024){
+		i = floppyxfer(dp, Fwrite, a+n, n, 1440*1024-n);
+		if(i <= 0)
+			break;
+		n += i;
+	}
+	print("floppymemwrite wrote %d bytes\n", n);
+splhi(); for(;;);
+}
+*/
+
+static void
+floppyintr(Ureg *ur)
+{
+	USED(ur);
+	switch(fl.cmd[0]&~Fmulti){
+	case Fread:
+	case Fwrite:
+	case Fformat:
+	case Fdumpreg: 
+		floppyresult();
+		break;
+	case Fseek:
+	case Frecal:
+	default:
+		floppysense();	/* to clear interrupt */
+		break;
+	}
+	fl.ncmd = 0;
+}
--- /dev/null
+++ b/os/boot.original/pc/devfloppy.h
@@ -1,0 +1,196 @@
+typedef	struct FController FController;
+typedef	struct FDrive FDrive;
+typedef struct FType FType;
+
+static void floppyintr(Ureg*);
+static int floppyon(FDrive*);
+static void floppyoff(FDrive*);
+static void floppysetdef(FDrive*);
+
+/*
+ *  a floppy drive
+ */
+struct FDrive
+{
+	FType	*t;		/* floppy type */
+	int	dt;		/* drive type */
+	int	dev;
+
+	ulong	lasttouched;	/* time last touched */
+	int	cyl;		/* current arm position */
+	int	confused;	/* needs to be recalibrated */
+	int	offset;		/* current offset */
+	int	vers;
+	int	maxtries;
+
+	int	tcyl;		/* target cylinder */
+	int	thead;		/* target head */
+	int	tsec;		/* target sector */
+	long	len;		/* size of xfer */
+
+	uchar	*cache;		/* track cache */
+	int	ccyl;
+	int	chead;
+
+//	Rendez	r;		/* waiting here for motor to spin up */
+	void	*aux;
+};
+
+/*
+ *  controller for 4 floppys
+ */
+struct FController
+{
+//	QLock;			/* exclusive access to the contoller */
+
+	int	ndrive;
+	FDrive	*d;		/* the floppy drives */
+	FDrive	*selected;
+	int	rate;		/* current rate selected */
+	uchar	cmd[14];	/* command */
+	int	ncmd;		/* # command bytes */
+	uchar	stat[14];	/* command status */
+	int	nstat;		/* # status bytes */
+	int	confused;	/* controler needs to be reset */
+//	Rendez	r;		/* wait here for command termination */
+	int	motor;		/* bit mask of spinning disks */
+//	Rendez	kr;		/* for motor watcher */
+};
+
+/*
+ *  floppy types (all MFM encoding)
+ */
+struct FType
+{
+	char	*name;
+	int	dt;		/* compatible drive type */
+	int	bytes;		/* bytes/sector */
+	int	sectors;	/* sectors/track */
+	int	heads;		/* number of heads */
+	int	steps;		/* steps per cylinder */
+	int	tracks;		/* tracks/disk */
+	int	gpl;		/* intersector gap length for read/write */	
+	int	fgpl;		/* intersector gap length for format */
+	int	rate;		/* rate code */
+
+	/*
+	 *  these depend on previous entries and are set filled in
+	 *  by floppyinit
+	 */
+	int	bcode;		/* coded version of bytes for the controller */
+	long	cap;		/* drive capacity in bytes */
+	long	tsize;		/* track size in bytes */
+};
+/* bits in the registers */
+enum
+{
+	/* status registers a & b */
+	Psra=		0x3f0,
+	Psrb=		0x3f1,
+
+	/* digital output register */
+	Pdor=		0x3f2,
+	Fintena=	0x8,	/* enable floppy interrupt */
+	Fena=		0x4,	/* 0 == reset controller */
+
+	/* main status register */
+	Pmsr=		0x3f4,
+	Fready=		0x80,	/* ready to be touched */
+	Ffrom=		0x40,	/* data from controller */
+	Ffloppybusy=	0x10,	/* operation not over */
+
+	/* data register */
+	Pfdata=		0x3f5,
+	Frecal=		0x07,	/* recalibrate cmd */
+	Fseek=		0x0f,	/* seek cmd */
+	Fsense=		0x08,	/* sense cmd */
+	Fread=		0x66,	/* read cmd */
+	Freadid=	0x4a,	/* read track id */
+	Fspec=		0x03,	/* set hold times */
+	Fwrite=		0x45,	/* write cmd */
+	Fformat=	0x4d,	/* format cmd */
+	Fmulti=		0x80,	/* or'd with Fread or Fwrite for multi-head */
+	Fdumpreg=	0x0e,	/* dump internal registers */
+
+	/* digital input register */
+	Pdir=		0x3F7,	/* disk changed port (read only) */
+	Pdsr=		0x3F7,	/* data rate select port (write only) */
+	Fchange=	0x80,	/* disk has changed */
+
+	/* status 0 byte */
+	Drivemask=	3<<0,
+	Seekend=	1<<5,
+	Codemask=	(3<<6)|(3<<3),
+	Cmdexec=	1<<6,
+
+	/* status 1 byte */
+	Overrun=	0x10,
+};
+
+/*
+ *  types of drive (from PC equipment byte)
+ */
+enum
+{
+	Tnone=		0,
+	T360kb=		1,
+	T1200kb=	2,
+	T720kb=		3,
+	T1440kb=	4,
+};
+
+static void
+pcfloppyintr(Ureg *ur, void *a)
+{
+	USED(a);
+
+	floppyintr(ur);
+}
+
+void
+floppysetup0(FController *fl)
+{
+	uchar equip;
+
+	/*
+	 * Read nvram for types of floppies 0 & 1.
+	 * Always try floppy 0.
+	 */
+	equip = nvramread(0x10);
+	fl->ndrive = 1;
+
+	if(equip & 0xf)
+		fl->ndrive++;
+
+	/*
+	 * Allocate the drive storage.
+	 * There's always one.
+	 */
+	fl->d = xalloc(fl->ndrive*sizeof(FDrive));
+	fl->d[0].dt = (equip >> 4) & 0xf;
+	if(fl->d[0].dt == Tnone)
+		fl->d[0].dt = T1440kb;
+
+	if(fl->ndrive == 2)
+		fl->d[1].dt = equip & 0xf;
+}
+
+void
+floppysetup1(FController*)
+{
+//	intrenable(VectorFLOPPY, pcfloppyintr, fl, BUSUNKNOWN);
+	setvec(VectorFLOPPY, pcfloppyintr, 0);
+}
+
+
+static vlong pcfloppyseek(FDrive*, vlong);
+FController	fl;
+
+vlong
+floppyseek(Fs *fs, vlong off)
+{
+	FDrive *dp;
+
+	dp = &fl.d[fs->dev];
+	return pcfloppyseek(dp, off);
+}
--- /dev/null
+++ b/os/boot.original/pc/devi82365.c
@@ -1,0 +1,742 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "error.h"
+#include "io.h"
+
+/*
+ *  Intel 82365SL PCIC controller and compatibles.
+ */
+enum
+{
+	/*
+	 *  registers indices
+	 */
+	Rid=		0x0,		/* identification and revision */
+	Ris=		0x1,		/* interface status */
+	Rpc=	 	0x2,		/* power control */
+	 Foutena=	 (1<<7),	/*  output enable */
+	 Fautopower=	 (1<<5),	/*  automatic power switching */
+	 Fcardena=	 (1<<4),	/*  PC card enable */
+	Rigc= 		0x3,		/* interrupt and general control */
+	 Fiocard=	 (1<<5),	/*  I/O card (vs memory) */
+	 Fnotreset=	 (1<<6),	/*  reset if not set */	
+	 FSMIena=	 (1<<4),	/*  enable change interrupt on SMI */ 
+	Rcsc= 		0x4,		/* card status change */
+	Rcscic= 	0x5,		/* card status change interrupt config */
+	 Fchangeena=	 (1<<3),	/*  card changed */
+	 Fbwarnena=	 (1<<1),	/*  card battery warning */
+	 Fbdeadena=	 (1<<0),	/*  card battery dead */
+	Rwe= 		0x6,		/* address window enable */
+	 Fmem16=	 (1<<5),	/*  use A23-A12 to decode address */
+	Rio= 		0x7,		/* I/O control */
+	 Fwidth16=	 (1<<0),	/*  16 bit data width */
+	 Fiocs16=	 (1<<1),	/*  IOCS16 determines data width */
+	 Fzerows=	 (1<<2),	/*  zero wait state */
+	 Ftiming=	 (1<<3),	/*  timing register to use */
+	Riobtm0lo=	0x8,		/* I/O address 0 start low byte */
+	Riobtm0hi=	0x9,		/* I/O address 0 start high byte */
+	Riotop0lo=	0xa,		/* I/O address 0 stop low byte */
+	Riotop0hi=	0xb,		/* I/O address 0 stop high byte */
+	Riobtm1lo=	0xc,		/* I/O address 1 start low byte */
+	Riobtm1hi=	0xd,		/* I/O address 1 start high byte */
+	Riotop1lo=	0xe,		/* I/O address 1 stop low byte */
+	Riotop1hi=	0xf,		/* I/O address 1 stop high byte */
+	Rmap=		0x10,		/* map 0 */
+
+	/*
+	 *  CL-PD67xx extension registers
+	 */
+	Rmisc1=		0x16,		/* misc control 1 */
+	 F5Vdetect=	 (1<<0),
+	 Fvcc3V=	 (1<<1),
+	 Fpmint=	 (1<<2),
+	 Fpsirq=	 (1<<3),
+	 Fspeaker=	 (1<<4),
+	 Finpack=	 (1<<7),
+	Rfifo=		0x17,		/* fifo control */
+	 Fflush=	 (1<<7),	/*  flush fifo */
+	Rmisc2=		0x1E,		/* misc control 2 */
+	 Flowpow=	 (1<<1),	/*  low power mode */
+	Rchipinfo=	0x1F,		/* chip information */
+	Ratactl=	0x26,		/* ATA control */
+
+	/*
+	 *  offsets into the system memory address maps
+	 */
+	Mbtmlo=		0x0,		/* System mem addr mapping start low byte */
+	Mbtmhi=		0x1,		/* System mem addr mapping start high byte */
+	 F16bit=	 (1<<7),	/*  16-bit wide data path */
+	Mtoplo=		0x2,		/* System mem addr mapping stop low byte */
+	Mtophi=		0x3,		/* System mem addr mapping stop high byte */
+	 Ftimer1=	 (1<<6),	/*  timer set 1 */
+	Mofflo=		0x4,		/* Card memory offset address low byte */
+	Moffhi=		0x5,		/* Card memory offset address high byte */
+	 Fregactive=	 (1<<6),	/*  attribute memory */
+
+	/*
+	 *  configuration registers - they start at an offset in attribute
+	 *  memory found in the CIS.
+	 */
+	Rconfig=	0,
+	 Creset=	 (1<<7),	/*  reset device */
+	 Clevel=	 (1<<6),	/*  level sensitive interrupt line */
+	 Cirq=		 (1<<2),	/*  IRQ enable */
+	 Cdecode=	 (1<<1),	/*  address decode */
+	 Cfunc=		 (1<<0),	/*  function enable */
+	Riobase0=	5,
+	Riobase1=	6,
+	Riosize=	9,
+};
+
+static int pcmcia_pcmspecial(char *, ISAConf *);
+static void pcmcia_pcmspecialclose(int);
+
+#define MAP(x,o)	(Rmap + (x)*0x8 + o)
+
+typedef struct I82365	I82365;
+
+/* a controller */
+enum
+{
+	Ti82365,
+	Tpd6710,
+	Tpd6720,
+	Tvg46x,
+};
+struct I82365
+{
+	int	type;
+	int	dev;
+	int	nslot;
+	int	xreg;		/* index register address */
+	int	dreg;		/* data register address */
+	int	irq;
+};
+static I82365 *controller[4];
+static int ncontroller;
+static PCMslot	*slot;
+static PCMslot	*lastslot;
+static nslot;
+
+static void	i82365intr(Ureg*, void*);
+static void	i82365reset(void);
+static int	pcmio(int, ISAConf*);
+
+static void i82365dump(PCMslot*);
+
+void
+devi82365link(void)
+{
+	static int already;
+	char *p;
+
+	if(already)
+		return;
+	already = 1;
+
+	if((p=getconf("pcmcia0")) && strncmp(p, "disabled", 8)==0)
+		return;
+
+	if (_pcmspecial)
+		return;
+	
+	_pcmspecial = pcmcia_pcmspecial;
+	_pcmspecialclose = pcmcia_pcmspecialclose;
+}
+
+/*
+ *  reading and writing card registers
+ */
+static uchar
+rdreg(PCMslot *pp, int index)
+{
+	outb(((I82365*)pp->cp)->xreg, pp->base + index);
+	return inb(((I82365*)pp->cp)->dreg);
+}
+static void
+wrreg(PCMslot *pp, int index, uchar val)
+{
+	outb(((I82365*)pp->cp)->xreg, pp->base + index);
+	outb(((I82365*)pp->cp)->dreg, val);
+}
+
+/*
+ *  get info about card
+ */
+static void
+slotinfo(PCMslot *pp)
+{
+	uchar isr;
+
+	isr = rdreg(pp, Ris);
+	pp->occupied = (isr & (3<<2)) == (3<<2);
+	pp->powered = isr & (1<<6);
+	pp->battery = (isr & 3) == 3;
+	pp->wrprot = isr & (1<<4);
+	pp->busy = isr & (1<<5);
+	//pp->msec = TK2MS(MACHP(0)->ticks);
+}
+
+static int
+vcode(int volt)
+{
+	switch(volt){
+	case 5:
+		return 1;
+	case 12:
+		return 2;
+	default:
+		return 0;
+	}
+}
+
+/*
+ *  enable the slot card
+ */
+static void
+slotena(PCMslot *pp)
+{
+	if(pp->enabled)
+		return;
+
+	/* power up and unreset, wait's are empirical (???) */
+	wrreg(pp, Rpc, Fautopower|Foutena|Fcardena);
+	delay(300);
+	wrreg(pp, Rigc, 0);
+	delay(100);
+	wrreg(pp, Rigc, Fnotreset);
+	delay(500);
+
+	/* get configuration */
+	slotinfo(pp);
+	if(pp->occupied){
+		pcmcisread(pp);
+		pp->enabled = 1;
+	} else
+		wrreg(pp, Rpc, Fautopower);
+}
+
+/*
+ *  disable the slot card
+ */
+static void
+slotdis(PCMslot *pp)
+{
+	wrreg(pp, Rpc, 0);	/* turn off card power */
+	wrreg(pp, Rwe, 0);	/* no windows */
+	pp->enabled = 0;
+}
+
+/*
+ *  status change interrupt
+ */
+static void
+i82365intr(Ureg *, void *)
+{
+	uchar csc, was;
+	PCMslot *pp;
+
+	if(slot == 0)
+		return;
+
+	for(pp = slot; pp < lastslot; pp++){
+		csc = rdreg(pp, Rcsc);
+		was = pp->occupied;
+		slotinfo(pp);
+		if(csc & (1<<3) && was != pp->occupied){
+			if(!pp->occupied)
+				slotdis(pp);
+		}
+	}
+}
+
+enum
+{
+	Mshift=	12,
+	Mgran=	(1<<Mshift),	/* granularity of maps */
+	Mmask=	~(Mgran-1),	/* mask for address bits important to the chip */
+};
+
+/*
+ *  get a map for pc card region, return corrected len
+ */
+PCMmap*
+pcmmap(int slotno, ulong offset, int len, int attr)
+{
+	PCMslot *pp;
+	uchar we, bit;
+	PCMmap *m, *nm;
+	int i;
+	ulong e;
+
+	pp = slot + slotno;
+	lock(&pp->mlock);
+
+	/* convert offset to granularity */
+	if(len <= 0)
+		len = 1;
+	e = ROUND(offset+len, Mgran);
+	offset &= Mmask;
+	len = e - offset;
+
+	/* look for a map that covers the right area */
+	we = rdreg(pp, Rwe);
+	bit = 1;
+	nm = 0;
+	for(m = pp->mmap; m < &pp->mmap[nelem(pp->mmap)]; m++){
+		if((we & bit))
+		if(m->attr == attr)
+		if(offset >= m->ca && e <= m->cea){
+
+			m->ref++;
+			unlock(&pp->mlock);
+			return m;
+		}
+		bit <<= 1;
+		if(nm == 0 && m->ref == 0)
+			nm = m;
+	}
+	m = nm;
+	if(m == 0){
+		unlock(&pp->mlock);
+		return 0;
+	}
+
+	/* if isa space isn't big enough, free it and get more */
+	if(m->len < len){
+		if(m->isa){
+			umbfree(m->isa, m->len);
+			m->len = 0;
+		}
+		m->isa = PADDR(umbmalloc(0, len, Mgran));
+		if(m->isa == 0){
+			print("pcmmap %d: out of isa space\n", len);
+			unlock(&pp->mlock);
+			return 0;
+		}
+		m->len = len;
+	}
+
+	/* set up new map */
+	m->ca = offset;
+	m->cea = m->ca + m->len;
+	m->attr = attr;
+	i = m-pp->mmap;
+	bit = 1<<i;
+	wrreg(pp, Rwe, we & ~bit);		/* disable map before changing it */
+	wrreg(pp, MAP(i, Mbtmlo), m->isa>>Mshift);
+	wrreg(pp, MAP(i, Mbtmhi), (m->isa>>(Mshift+8)) | F16bit);
+	wrreg(pp, MAP(i, Mtoplo), (m->isa+m->len-1)>>Mshift);
+	wrreg(pp, MAP(i, Mtophi), ((m->isa+m->len-1)>>(Mshift+8)));
+	offset -= m->isa;
+	offset &= (1<<25)-1;
+	offset >>= Mshift;
+	wrreg(pp, MAP(i, Mofflo), offset);
+	wrreg(pp, MAP(i, Moffhi), (offset>>8) | (attr ? Fregactive : 0));
+	wrreg(pp, Rwe, we | bit);		/* enable map */
+	m->ref = 1;
+
+	unlock(&pp->mlock);
+	return m;
+}
+
+void
+pcmunmap(int slotno, PCMmap* m)
+{
+	PCMslot *pp;
+
+	pp = slot + slotno;
+	lock(&pp->mlock);
+	m->ref--;
+	unlock(&pp->mlock);
+}
+
+static void
+increfp(PCMslot *pp)
+{
+	lock(pp);
+	if(pp->ref++ == 0)
+		slotena(pp);
+	unlock(pp);
+}
+
+static void
+decrefp(PCMslot *pp)
+{
+	lock(pp);
+	if(pp->ref-- == 1)
+		slotdis(pp);
+	unlock(pp);
+}
+
+/*
+ *  look for a card whose version contains 'idstr'
+ */
+static int
+pcmcia_pcmspecial(char *idstr, ISAConf *isa)
+{
+	PCMslot *pp;
+	extern char *strstr(char*, char*);
+	int enabled;
+
+	i82365reset();
+	for(pp = slot; pp < lastslot; pp++){
+		if(pp->special)
+			continue;	/* already taken */
+		enabled = 0;
+		/* make sure we don't power on cards when we already know what's
+		 * in them.  We'll reread every two minutes if necessary
+		 */
+		if (pp->verstr[0] == '\0') {
+			increfp(pp);
+			enabled++;
+		}
+
+		if(pp->occupied) {
+			if(strstr(pp->verstr, idstr)){
+				if (!enabled){
+					enabled = 1;
+					increfp(pp);
+				}
+				if(isa == 0 || pcmio(pp->slotno, isa) == 0){
+					pp->special = 1;
+					return pp->slotno;
+				}
+			}
+		} else
+			pp->special = 1;
+		if (enabled)
+			decrefp(pp);
+	}
+	return -1;
+}
+
+static void
+pcmcia_pcmspecialclose(int slotno)
+{
+	PCMslot *pp;
+
+	print("pcmspecialclose called\n");
+	if(slotno >= nslot)
+		panic("pcmspecialclose");
+	pp = slot + slotno;
+	pp->special = 0;
+	decrefp(pp);
+}
+
+static char *chipname[] =
+{
+[Ti82365]	"Intel 82365SL",
+[Tpd6710]	"Cirrus Logic PD6710",
+[Tpd6720]	"Cirrus Logic PD6720",
+[Tvg46x]	"Vadem VG-46x",
+};
+
+static I82365*
+i82365probe(int x, int d, int dev)
+{
+	uchar c, id;
+	I82365 *cp;
+	ISAConf isa;
+	int i, nslot;
+
+	outb(x, Rid + (dev<<7));
+	id = inb(d);
+	if((id & 0xf0) != 0x80)
+		return 0;		/* not a memory & I/O card */
+	if((id & 0x0f) == 0x00)
+		return 0;		/* no revision number, not possible */
+
+	cp = xalloc(sizeof(I82365));
+	cp->xreg = x;
+	cp->dreg = d;
+	cp->dev = dev;
+	cp->type = Ti82365;
+	cp->nslot = 2;
+
+	switch(id){
+	case 0x82:
+	case 0x83:
+	case 0x84:
+		/* could be a cirrus */
+		outb(x, Rchipinfo + (dev<<7));
+		outb(d, 0);
+		c = inb(d);
+		if((c & 0xc0) != 0xc0)
+			break;
+		c = inb(d);
+		if((c & 0xc0) != 0x00)
+			break;
+		if(c & 0x20){
+			cp->type = Tpd6720;
+		} else {
+			cp->type = Tpd6710;
+			cp->nslot = 1;
+		}
+
+		/* low power mode */
+		outb(x, Rmisc2 + (dev<<7));
+		c = inb(d);
+		outb(d, c & ~Flowpow);
+		break;
+	}
+
+	/* if it's not a Cirrus, it could be a Vadem... */
+	if(cp->type == Ti82365){
+		/* unlock the Vadem extended regs */
+		outb(x, 0x0E + (dev<<7));
+		outb(x, 0x37 + (dev<<7));
+
+		/* make the id register show the Vadem id */
+		outb(x, 0x3A + (dev<<7));
+		c = inb(d);
+		outb(d, c|0xC0);
+		outb(x, Rid + (dev<<7));
+		c = inb(d);
+		if(c & 0x08)
+			cp->type = Tvg46x;
+
+		/* go back to Intel compatible id */
+		outb(x, 0x3A + (dev<<7));
+		c = inb(d);
+		outb(d, c & ~0xC0);
+	}
+
+	memset(&isa, 0, sizeof(ISAConf));
+	if(isaconfig("pcmcia", ncontroller, &isa) && isa.irq)
+		cp->irq = isa.irq;
+	else
+		cp->irq = VectorPCMCIA - VectorPIC;
+
+	for(i = 0; i < isa.nopt; i++){
+		if(cistrncmp(isa.opt[i], "nslot=", 6))
+			continue;
+		nslot = strtol(&isa.opt[i][6], nil, 0);
+		if(nslot > 0 && nslot <= 2)
+			cp->nslot = nslot;
+	}
+
+	controller[ncontroller++] = cp;
+	return cp;
+}
+
+static void
+i82365dump(PCMslot *pp)
+{
+	int i;
+
+	for(i = 0; i < 0x40; i++){
+		if((i&0x0F) == 0)
+			print("\n%2.2uX:	", i);
+		if(((i+1) & 0x0F) == 0x08)
+			print(" - ");
+		print("%2.2uX ", rdreg(pp, i));
+	}
+	print("\n");
+}
+
+/*
+ *  set up for slot cards
+ */
+static void
+i82365reset(void)
+{
+	static int already;
+	int i, j;
+	I82365 *cp;
+	PCMslot *pp;
+
+	if(already)
+		return;
+	already = 1;
+
+
+	/* look for controllers */
+	i82365probe(0x3E0, 0x3E1, 0);
+	i82365probe(0x3E0, 0x3E1, 1);
+	i82365probe(0x3E2, 0x3E3, 0);
+	i82365probe(0x3E2, 0x3E3, 1);
+
+	for(i = 0; i < ncontroller; i++)
+		nslot += controller[i]->nslot;
+	slot = xalloc(nslot * sizeof(PCMslot));
+
+	lastslot = slot;
+	for(i = 0; i < ncontroller; i++){
+		cp = controller[i];
+		print("#y%d: %d slot %s: port 0x%uX irq %d\n",
+			i, cp->nslot, chipname[cp->type], cp->xreg, cp->irq);
+		for(j = 0; j < cp->nslot; j++){
+			pp = lastslot++;
+			pp->slotno = pp - slot;
+			pp->memlen = 64*MB;
+			pp->base = (cp->dev<<7) | (j<<6);
+			pp->cp = cp;
+			pp->msec = ~0;
+			pp->verstr[0] = 0;
+			slotdis(pp);
+
+			/* interrupt on status change */
+			wrreg(pp, Rcscic, (cp->irq<<4) | Fchangeena);
+			rdreg(pp, Rcsc);
+		}
+
+		/* for card management interrupts */
+		setvec(cp->irq+VectorPIC, i82365intr, 0);
+	}
+}
+
+/*
+ *  configure the PCMslot for IO.  We assume very heavily that we can read
+ *  configuration info from the CIS.  If not, we won't set up correctly.
+ */
+static int
+pcmio(int slotno, ISAConf *isa)
+{
+	uchar we, x, *p;
+	PCMslot *pp;
+	PCMconftab *ct, *et, *t;
+	PCMmap *m;
+	int i, index, irq;
+	char *cp;
+
+	irq = isa->irq;
+	if(irq == 2)
+		irq = 9;
+
+	if(slotno > nslot)
+		return -1;
+	pp = slot + slotno;
+
+	if(!pp->occupied)
+		return -1;
+
+	et = &pp->ctab[pp->nctab];
+
+	ct = 0;
+	for(i = 0; i < isa->nopt; i++){
+		if(strncmp(isa->opt[i], "index=", 6))
+			continue;
+		index = strtol(&isa->opt[i][6], &cp, 0);
+		if(cp == &isa->opt[i][6] || index >= pp->nctab)
+			return -1;
+		ct = &pp->ctab[index];
+	}
+
+	if(ct == 0){
+	
+		/* assume default is right */
+		if(pp->def)
+			ct = pp->def;
+		else
+			ct = pp->ctab;
+	
+		/* try for best match */
+		if(ct->nio == 0
+		|| ct->io[0].start != isa->port || ((1<<irq) & ct->irqs) == 0){
+			for(t = pp->ctab; t < et; t++)
+				if(t->nio
+				&& t->io[0].start == isa->port
+				&& ((1<<irq) & t->irqs)){
+					ct = t;
+					break;
+				}
+		}
+		if(ct->nio == 0 || ((1<<irq) & ct->irqs) == 0){
+			for(t = pp->ctab; t < et; t++)
+				if(t->nio && ((1<<irq) & t->irqs)){
+					ct = t;
+					break;
+				}
+		}
+		if(ct->nio == 0){
+			for(t = pp->ctab; t < et; t++)
+				if(t->nio){
+					ct = t;
+					break;
+				}
+		}
+	}
+
+	if(ct == et || ct->nio == 0)
+		return -1;
+	if(isa->port == 0 && ct->io[0].start == 0)
+		return -1;
+
+	/* route interrupts */
+	isa->irq = irq;
+	wrreg(pp, Rigc, irq | Fnotreset | Fiocard);
+	
+	/* set power and enable device */
+	x = vcode(ct->vpp1);
+	wrreg(pp, Rpc, x|Fautopower|Foutena|Fcardena);
+
+	/* 16-bit data path */
+	if(ct->bit16)
+		x = Ftiming|Fiocs16|Fwidth16;
+	else
+		x = Ftiming;
+	if(ct->nio == 2 && ct->io[1].start)
+		x |= x<<4;
+	wrreg(pp, Rio, x);
+
+	/*
+	 * enable io port map 0
+	 * the 'top' register value includes the last valid address
+	 */
+	if(isa->port == 0)
+		isa->port = ct->io[0].start;
+	we = rdreg(pp, Rwe);
+	wrreg(pp, Riobtm0lo, isa->port);
+	wrreg(pp, Riobtm0hi, isa->port>>8);
+	i = isa->port+ct->io[0].len-1;
+	wrreg(pp, Riotop0lo, i);
+	wrreg(pp, Riotop0hi, i>>8);
+	we |= 1<<6;
+	if(ct->nio >= 2 && ct->io[1].start){
+		wrreg(pp, Riobtm1lo, ct->io[1].start);
+		wrreg(pp, Riobtm1hi, ct->io[1].start>>8);
+		i = ct->io[1].start+ct->io[1].len-1;
+		wrreg(pp, Riotop1lo, i);
+		wrreg(pp, Riotop1hi, i>>8);
+		we |= 1<<7;
+	}
+	wrreg(pp, Rwe, we);
+
+	/* only touch Rconfig if it is present */
+	m = pcmmap(slotno, pp->cfg[0].caddr + Rconfig, 0x20, 1);
+	p = KADDR(m->isa + pp->cfg[0].caddr - m->ca);
+	if(pp->cfg[0].cpresent & (1<<Rconfig)){
+		/*  Reset adapter */
+
+		/*  set configuration and interrupt type.
+		 *  if level is possible on the card, use it.
+		 */
+		x = ct->index;
+		if(ct->irqtype & 0x20)
+			x |= Clevel;
+
+		/*  enable the device, enable address decode and
+		 *  irq enable.
+		 */
+		x |= Cfunc|Cdecode|Cirq;
+
+		p[0] = x;
+		//delay(5);
+		microdelay(40);
+	}
+
+	if(pp->cfg[0].cpresent & (1<<Riobase0)){
+		/* set up the iobase 0 */
+		p[Riobase0 << 1] = isa->port;
+		p[Riobase1 << 1] = isa->port >> 8;
+	}
+
+	if(pp->cfg[0].cpresent & (1<<Riosize))
+		p[Riosize << 1] = ct->io[0].len;
+	pcmunmap(slotno, m);
+	return 0;
+}
--- /dev/null
+++ b/os/boot.original/pc/devpccard.c
@@ -1,0 +1,1606 @@
+/*
+     cardbus and pcmcia (grmph) support.
+*/
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "error.h"
+#include "io.h"
+
+extern int pciscan(int, Pcidev **);
+
+int (*_pcmspecial)(char *, ISAConf *);
+void (*_pcmspecialclose)(int);
+
+int
+pcmspecial(char *idstr, ISAConf *isa)
+{
+	return (_pcmspecial  != nil)? _pcmspecial(idstr, isa): -1;
+}
+
+void
+pcmspecialclose(int a)
+{
+	if (_pcmspecialclose != nil)
+		_pcmspecialclose(a);
+}
+
+static ulong
+ioreserve(ulong, int size, int align, char *)
+{
+	static ulong isaend = 0x400; /*0xfd00*/
+	ulong ioaddr;
+
+	if (align)
+		isaend = ((isaend + align - 1) / align) * align;
+	ioaddr = isaend;
+	isaend += size;
+	return ioaddr;
+}
+
+#define MAP(x,o)	(Rmap + (x)*0x8 + o)
+
+enum {
+	TI_vid = 0x104c,
+	TI_1131_did = 0xAC15,
+	TI_1250_did = 0xAC16,
+	TI_1450_did = 0xAC1B,
+	TI_1251A_did = 0xAC1D,
+	TI_1420_did = 0xAC51,
+
+	Ricoh_vid = 0x1180,
+	Ricoh_475_did = 0x0475,
+	Ricoh_476_did = 0x0476,
+	Ricoh_478_did = 0x0478,
+
+	O2_vid = 0x1217,
+	O2_OZ711M3_did = 0x7134,
+
+	Nslots = 4,		/* Maximum number of CardBus slots to use */
+
+	K = 1024,
+	M = K * K,
+
+	LegacyAddr = 0x3e0,
+	NUMEVENTS = 10,
+
+	TI1131xSC = 0x80,		// system control
+		TI122X_SC_INTRTIE	= 1 << 29,
+	TI12xxIM = 0x8c,		// 
+	TI1131xCC = 0x91,		// card control
+		TI113X_CC_RIENB = 1 << 7,
+		TI113X_CC_ZVENABLE = 1 << 6,
+		TI113X_CC_PCI_IRQ_ENA = 1 << 5,
+		TI113X_CC_PCI_IREQ = 1 << 4,
+		TI113X_CC_PCI_CSC = 1 << 3,
+		TI113X_CC_SPKROUTEN = 1 << 1,
+		TI113X_CC_IFG = 1 << 0,
+	TI1131xDC = 0x92,		// device control
+};
+
+typedef struct Variant Variant;
+struct Variant {
+	ushort	vid;
+	ushort	did;
+	char	*name;
+};
+
+static Variant variant[] = {
+{	Ricoh_vid,	Ricoh_475_did,	"Ricoh 475 PCI/Cardbus bridge",	},
+{	Ricoh_vid,	Ricoh_476_did,	"Ricoh 476 PCI/Cardbus bridge",	},
+{	Ricoh_vid,	Ricoh_478_did,	"Ricoh 478 PCI/Cardbus bridge",	},
+{	TI_vid,		TI_1131_did,	"TI PCI-1131 Cardbus Controller", },
+{	TI_vid,		TI_1250_did,	"TI PCI-1250 Cardbus Controller", },
+{	TI_vid,		TI_1450_did,	"TI PCI-1450 Cardbus Controller", },
+{	TI_vid,		TI_1251A_did,	"TI PCI-1251A Cardbus Controller", },
+{	TI_vid,		TI_1420_did,	"TI PCI-1420 Cardbus Controller", },
+{	O2_vid,		O2_OZ711M3_did,	"O2Micro OZ711M3 MemoryCardBus", },
+};
+
+/* Cardbus registers */
+enum {
+	SocketEvent = 0,
+		SE_CCD = 3 << 1,
+		SE_POWER = 1 << 3,
+	SocketMask = 1,
+	SocketState = 2,
+		SS_CCD = 3 << 1,
+		SS_POWER = 1 << 3,
+		SS_PC16 = 1 << 4,
+		SS_CBC = 1 << 5,
+		SS_NOTCARD = 1 << 7,
+		SS_BADVCC = 1 << 9,
+		SS_5V = 1 << 10,
+		SS_3V = 1 << 11,
+	SocketForce = 3,
+	SocketControl = 4,
+		SC_5V = 0x22,
+		SC_3V = 0x33,
+};
+
+enum {
+	PciPCR_IO = 1 << 0,
+	PciPCR_MEM = 1 << 1,
+	PciPCR_Master = 1 << 2,
+
+	PciPMC = 0xa4,
+
+	Nbars = 6,
+	Ncmd = 10,
+	CBIRQ = 9,
+
+	PC16,
+	PC32,
+};
+
+enum {
+	Ti82365,
+	Tpd6710,
+	Tpd6720,
+	Tvg46x,
+};
+
+/*
+ *  Intel 82365SL PCIC controller for the PCMCIA or
+ *  Cirrus Logic PD6710/PD6720 which is mostly register compatible
+ */
+enum
+{
+	/*
+	 *  registers indices
+	 */
+	Rid=		0x0,		/* identification and revision */
+	Ris=		0x1,		/* interface status */
+	Rpc=	 	0x2,		/* power control */
+	 Foutena=	 (1<<7),	/*  output enable */
+	 Fautopower=	 (1<<5),	/*  automatic power switching */
+	 Fcardena=	 (1<<4),	/*  PC card enable */
+	Rigc= 		0x3,		/* interrupt and general control */
+	 Fiocard=	 (1<<5),	/*  I/O card (vs memory) */
+	 Fnotreset=	 (1<<6),	/*  reset if not set */	
+	 FSMIena=	 (1<<4),	/*  enable change interrupt on SMI */ 
+	Rcsc= 		0x4,		/* card status change */
+	Rcscic= 	0x5,		/* card status change interrupt config */
+	 Fchangeena=	 (1<<3),	/*  card changed */
+	 Fbwarnena=	 (1<<1),	/*  card battery warning */
+	 Fbdeadena=	 (1<<0),	/*  card battery dead */
+	Rwe= 		0x6,		/* address window enable */
+	 Fmem16=	 (1<<5),	/*  use A23-A12 to decode address */
+	Rio= 		0x7,		/* I/O control */
+	 Fwidth16=	 (1<<0),	/*  16 bit data width */
+	 Fiocs16=	 (1<<1),	/*  IOCS16 determines data width */
+	 Fzerows=	 (1<<2),	/*  zero wait state */
+	 Ftiming=	 (1<<3),	/*  timing register to use */
+	Riobtm0lo=	0x8,		/* I/O address 0 start low byte */
+	Riobtm0hi=	0x9,		/* I/O address 0 start high byte */
+	Riotop0lo=	0xa,		/* I/O address 0 stop low byte */
+	Riotop0hi=	0xb,		/* I/O address 0 stop high byte */
+	Riobtm1lo=	0xc,		/* I/O address 1 start low byte */
+	Riobtm1hi=	0xd,		/* I/O address 1 start high byte */
+	Riotop1lo=	0xe,		/* I/O address 1 stop low byte */
+	Riotop1hi=	0xf,		/* I/O address 1 stop high byte */
+	Rmap=		0x10,		/* map 0 */
+
+	/*
+	 *  CL-PD67xx extension registers
+	 */
+	Rmisc1=		0x16,		/* misc control 1 */
+	 F5Vdetect=	 (1<<0),
+	 Fvcc3V=	 (1<<1),
+	 Fpmint=	 (1<<2),
+	 Fpsirq=	 (1<<3),
+	 Fspeaker=	 (1<<4),
+	 Finpack=	 (1<<7),
+	Rfifo=		0x17,		/* fifo control */
+	 Fflush=	 (1<<7),	/*  flush fifo */
+	Rmisc2=		0x1E,		/* misc control 2 */
+	 Flowpow=	 (1<<1),	/*  low power mode */
+	Rchipinfo=	0x1F,		/* chip information */
+	Ratactl=	0x26,		/* ATA control */
+
+	/*
+	 *  offsets into the system memory address maps
+	 */
+	Mbtmlo=		0x0,		/* System mem addr mapping start low byte */
+	Mbtmhi=		0x1,		/* System mem addr mapping start high byte */
+	 F16bit=	 (1<<7),	/*  16-bit wide data path */
+	Mtoplo=		0x2,		/* System mem addr mapping stop low byte */
+	Mtophi=		0x3,		/* System mem addr mapping stop high byte */
+	 Ftimer1=	 (1<<6),	/*  timer set 1 */
+	Mofflo=		0x4,		/* Card memory offset address low byte */
+	Moffhi=		0x5,		/* Card memory offset address high byte */
+	 Fregactive=	 (1<<6),	/*  attribute memory */
+
+	/*
+	 *  configuration registers - they start at an offset in attribute
+	 *  memory found in the CIS.
+	 */
+	Rconfig=	0,
+	 Creset=	 (1<<7),	/*  reset device */
+	 Clevel=	 (1<<6),	/*  level sensitive interrupt line */
+};
+
+/*
+ *  read and crack the card information structure enough to set
+ *  important parameters like power
+ */
+/* cis memory walking */
+typedef struct Cisdat Cisdat;
+struct Cisdat {
+	uchar		*cisbase;
+	int		cispos;
+	int		cisskip;
+	int		cislen;
+};
+
+typedef struct Pcminfo Pcminfo;
+struct Pcminfo {
+	char		verstr[512];		/* Version string */
+	PCMmap		mmap[4];		/* maps, last is always for the kernel */
+	ulong		conf_addr;		/* Config address */
+	uchar		conf_present;		/* Config register present */
+	int		nctab;			/* In use configuration tables */
+	PCMconftab	ctab[8];		/* Configuration tables */
+	PCMconftab	*defctab;		/* Default conftab */
+
+	int		port;			/* Actual port usage */
+	int		irq;			/* Actual IRQ usage */
+};
+
+typedef struct Cardbus Cardbus;
+struct Cardbus {
+	Lock;
+	Variant		*variant;		/* Which CardBus chipset */
+	Pcidev		*pci;			/* The bridge itself */
+	ulong		*regs;			/* Cardbus registers */
+	int		ltype;			/* Legacy type */
+	int		lindex;			/* Legacy port index address */
+	int		ldata;			/* Legacy port data address */
+	int		lbase;			/* Base register for this socket */
+
+	int		state;			/* Current state of card */
+	int		type;			/* Type of card */
+	Pcminfo		linfo;			/* PCMCIA slot info */
+
+	int		special;		/* card is allocated to a driver */
+
+	int		refs;			/* Number of refs to slot */
+	Lock		refslock;		/* inc/dev ref lock */
+};
+
+enum {
+	Mshift=	12,
+	Mgran=	(1<<Mshift),	/* granularity of maps */
+	Mmask=	~(Mgran-1),	/* mask for address bits important to the chip */
+};
+
+static Cardbus cbslots[Nslots];
+static int nslots;
+
+static ulong exponent[8] = { 
+	1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 
+};
+
+static ulong vmant[16] = {
+	10, 12, 13, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 70, 80, 90,
+};
+
+static ulong mantissa[16] = { 
+	0, 10, 12, 13, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 70, 80, 
+};
+
+static void cbint(Ureg *, void *);
+static int powerup(Cardbus *);
+static void configure(Cardbus *);
+static void managecard(Cardbus *);
+static void cardmanager(void *);
+static void eject(Cardbus *);
+static void interrupt(Ureg *, void *);
+static void powerdown(Cardbus *cb);
+static void unconfigure(Cardbus *cb);
+
+static void i82365probe(Cardbus *cb, int lindex, int ldata);
+static void i82365configure(Cardbus *cb);
+static PCMmap *isamap(Cardbus *cb, ulong offset, int len, int attr);
+static void isaunmap(PCMmap* m);
+static uchar rdreg(Cardbus *cb, int index);
+static void wrreg(Cardbus *cb, int index, uchar val);
+static int readc(Cisdat *cis, uchar *x);
+static void tvers1(Cardbus *cb, Cisdat *cis, int );
+static void tcfig(Cardbus *cb, Cisdat *cis, int );
+static void tentry(Cardbus *cb, Cisdat *cis, int );
+static int vcode(int volt);
+static int pccard_pcmspecial(char *idstr, ISAConf *isa);
+static void pccard_pcmspecialclose(int slotno);
+
+enum {
+	CardDetected,
+	CardPowered,
+	CardEjected,
+	CardConfigured,
+};
+
+static char *messages[] = {
+[CardDetected]		"CardDetected",
+[CardPowered]		"CardPowered",
+[CardEjected]		"CardEjected",
+[CardConfigured]	"CardConfigured",
+};
+
+enum {
+	SlotEmpty,
+	SlotFull,
+	SlotPowered,
+	SlotConfigured,
+};
+
+static char *states[] = {
+[SlotEmpty]		"SlotEmpty",
+[SlotFull]		"SlotFull",
+[SlotPowered]		"SlotPowered",
+[SlotConfigured]	"SlotConfigured",
+};
+
+static void
+engine(Cardbus *cb, int message)
+{
+	// print("engine(%d): %s(%s)\n", 
+	//	 (int)(cb - cbslots), states[cb->state], messages[message]);
+	switch (cb->state) {
+	case SlotEmpty:
+
+		switch (message) {
+		case CardDetected:
+			cb->state = SlotFull;
+			powerup(cb);
+			break;
+		case CardEjected:
+			break;
+		default:
+			//print("#Y%d: Invalid message %s in SlotEmpty state\n",
+			//	(int)(cb - cbslots), messages[message]);
+			break;
+		}
+		break;
+
+	case SlotFull:
+
+		switch (message) {
+		case CardPowered:
+			cb->state = SlotPowered;
+			configure(cb);
+			break;
+		case CardEjected:
+			cb->state = SlotEmpty;
+			powerdown(cb);
+			break;
+		default:
+			//print("#Y%d: Invalid message %s in SlotFull state\n",
+			//	(int)(cb - cbslots), messages[message]);
+			break;
+		}
+		break;
+
+	case SlotPowered:
+
+		switch (message) {
+		case CardConfigured:
+			cb->state = SlotConfigured;
+			break;
+		case CardEjected:
+			cb->state = SlotEmpty;
+			unconfigure(cb);
+			powerdown(cb);
+			break;
+		default:
+			print("#Y%d: Invalid message %s in SlotPowered state\n",
+				(int)(cb - cbslots), messages[message]);
+			break;
+		}
+		break;
+
+	case SlotConfigured:
+
+		switch (message) {
+		case CardEjected:
+			cb->state = SlotEmpty;
+			unconfigure(cb);
+			powerdown(cb);
+			break;
+		default:
+			//print("#Y%d: Invalid message %s in SlotConfigured state\n",
+			//	(int)(cb - cbslots), messages[message]);
+			break;
+		}
+		break;
+	}
+}
+
+void
+devpccardlink(void)
+{
+	static int initialized;
+	Pcidev *pci;
+	int i;
+	char *p;
+
+	if (initialized) 
+		return;
+	initialized = 1;
+
+	if((p=getconf("pccard0")) && strncmp(p, "disabled", 8)==0)
+		return;
+
+	if(_pcmspecial)
+		return;
+
+
+	/* Allocate legacy space */
+	if (ioalloc(LegacyAddr, 2, 0, "i82365.0") < 0)
+		print("#Y: WARNING: Cannot allocate legacy ports\n");
+
+	/* Find all CardBus controllers */
+	pci = nil;
+	while ((pci = pcimatch(pci, 0, 0)) != nil) {
+		ulong baddr;
+		uchar pin;
+		Cardbus *cb;
+		int slot;
+
+		if(pci->ccrb != 6 || pci->ccru != 7)
+			continue;
+		for (i = 0; i != nelem(variant); i++)
+			if (pci->vid == variant[i].vid && pci->did == variant[i].did)
+				break;
+		if (i == nelem(variant))
+			continue;
+
+		/* initialize this slot */
+		slot = nslots++;
+		cb = &cbslots[slot];
+
+		cb->pci = pci;
+		cb->variant = &variant[i];
+
+		// Set up PCI bus numbers if needed.
+		if (pcicfgr8(pci, PciSBN) == 0) {
+			static int busbase = 0x20;
+
+			pcicfgw8(pci, PciSBN, busbase);
+			pcicfgw8(pci, PciUBN, busbase + 2);
+			busbase += 3;
+		}
+
+		// Patch up intl if needed.
+		if ((pin = pcicfgr8(pci, PciINTP)) != 0 && 
+		    (pci->intl == 0xff || pci->intl == 0)) {
+			pci->intl = pciipin(nil, pin);
+			pcicfgw8(pci, PciINTL, pci->intl);
+
+			if (pci->intl == 0xff || pci->intl == 0)
+				print("#Y%d: No interrupt?\n", (int)(cb - cbslots));
+		}
+		
+		// Don't you love standards!
+		if (pci->vid == TI_vid) {
+			if (pci->did <= TI_1131_did) {
+				uchar cc;
+
+				cc = pcicfgr8(pci, TI1131xCC);
+				cc &= ~(TI113X_CC_PCI_IRQ_ENA |
+						TI113X_CC_PCI_IREQ | 
+						TI113X_CC_PCI_CSC |
+						TI113X_CC_ZVENABLE);
+				cc |= TI113X_CC_PCI_IRQ_ENA | 
+						TI113X_CC_PCI_IREQ | 
+						TI113X_CC_SPKROUTEN;
+				pcicfgw8(pci, TI1131xCC, cc);
+
+				// PCI interrupts only
+				pcicfgw8(pci, TI1131xDC, 
+						pcicfgr8(pci, TI1131xDC) & ~6);
+
+				// CSC ints to PCI bus.
+				wrreg(cb, Rigc, rdreg(cb, Rigc) | 0x10);
+			}
+			else if (pci->did == TI_1250_did) {
+				print("No support yet for the TI_1250_did, prod pb\n");
+			}
+			else if (pci->did == TI_1420_did) {
+				// Disable Vcc protection
+				pcicfgw32(cb->pci, 0x80, 
+					pcicfgr32(cb->pci, 0x80) | (1 << 21));
+			}
+			
+			pcicfgw16(cb->pci, PciPMC, pcicfgr16(cb->pci, PciPMC) & ~3);
+		}
+	
+		if ((baddr = pcicfgr32(cb->pci, PciBAR0)) == 0) {
+			int size = (pci->did == Ricoh_478_did)? 0x10000: 0x1000;
+
+			baddr = upamalloc(baddr, size, size);
+			pcicfgw32(cb->pci, PciBAR0, baddr);
+			cb->regs = (ulong *)KADDR(baddr);
+		}
+		else
+			cb->regs = (ulong *)KADDR(upamalloc(baddr, 4096, 0));
+		cb->state = SlotEmpty;
+
+		/* Don't really know what to do with this... */
+		i82365probe(cb, LegacyAddr, LegacyAddr + 1);
+
+		print("#Y%ld: %s, %.8ulX intl %d\n", cb - cbslots, 
+			 variant[i].name, baddr, pci->intl);
+	}
+
+	if (nslots == 0)
+		return;
+
+	_pcmspecial = pccard_pcmspecial;
+	_pcmspecialclose = pccard_pcmspecialclose;
+
+	for (i = 0; i != nslots; i++) {
+		Cardbus *cb = &cbslots[i];
+
+		if ((cb->regs[SocketState] & SE_CCD) == 0)
+			engine(cb, CardDetected);
+	}
+
+	delay(500);			/* Allow time for power up */
+
+	for (i = 0; i != nslots; i++) {
+		Cardbus *cb = &cbslots[i];
+
+		if (cb->regs[SocketState] & SE_POWER)
+			engine(cb, CardPowered);
+
+		/* Ack and enable interrupts on all events */
+		//cb->regs[SocketEvent] = cb->regs[SocketEvent];
+		//cb->regs[SocketMask] |= 0xF;	
+		//wrreg(cb, Rcscic, 0xC);
+	}
+}
+
+static int
+powerup(Cardbus *cb)
+{
+	ulong state;
+	ushort bcr;
+
+	state = cb->regs[SocketState];
+	if (state & SS_PC16) {
+	
+		// print("#Y%ld: Probed a PC16 card, powering up card\n", cb - cbslots);
+		cb->type = PC16;
+		memset(&cb->linfo, 0, sizeof(Pcminfo));
+
+		/* power up and unreset, wait's are empirical (???) */
+		wrreg(cb, Rpc, Fautopower|Foutena|Fcardena);
+		delay(300);
+		wrreg(cb, Rigc, 0);
+		delay(100);
+		wrreg(cb, Rigc, Fnotreset);
+		delay(500);
+
+		return 1;
+	}
+
+	if (state & SS_CCD)
+		return 0;
+
+	if (state & SS_NOTCARD) {
+		print("#Y%ld: No card inserted\n", cb - cbslots);
+		return 0;
+	}
+
+	if (state & SS_BADVCC) {
+		print("#Y%ld: Bad VCC request to card, powering down card!\n", 
+			 cb - cbslots);
+		cb->regs[SocketControl] = 0;
+		return 0;
+	}
+
+	if ((state & SS_3V) == 0 && (state & SS_5V) == 0) {
+		print("#Y%ld: Unsupported voltage, powering down card!\n", 
+			cb - cbslots);
+		cb->regs[SocketControl] = 0;
+		return 0;
+	}
+
+	//print("#Y%ld: card %spowered at %d volt\n", cb - cbslots, 
+	//	(state & SS_POWER)? "": "not ", 
+	//	(state & SS_3V)? 3: (state & SS_5V)? 5: -1);
+
+	/* Power up the card
+	 * and make sure the secondary bus is not in reset.
+	 */
+	cb->regs[SocketControl] = (state & SS_5V)? SC_5V: SC_3V;
+	delay(50);
+	bcr = pcicfgr16(cb->pci, PciBCR);
+	bcr &= ~0x40;
+	pcicfgw16(cb->pci, PciBCR, bcr);
+	delay(100);
+
+	cb->type = PC32;
+
+	return 1;
+}
+
+static void
+powerdown(Cardbus *cb)
+{
+	ushort bcr;
+
+	if (cb->type == PC16) {
+
+		wrreg(cb, Rpc, 0);	/* turn off card power */
+		wrreg(cb, Rwe, 0);	/* no windows */
+
+		cb->type = -1;
+		return;
+	}
+
+	bcr = pcicfgr16(cb->pci, PciBCR);
+	bcr |= 0x40;
+	pcicfgw16(cb->pci, PciBCR, bcr);
+	cb->regs[SocketControl] = 0;
+	cb->type = -1;
+}
+
+static void
+configure(Cardbus *cb)
+{
+	Pcidev *pci;
+	ulong size, bar;
+	int i, ioindex, memindex, r;
+
+	//print("configuring slot %d (%s)\n", (int)(cb - cbslots), states[cb->state]);
+	if (cb->state == SlotConfigured)
+		return;
+	engine(cb, CardConfigured);
+
+	delay(50);					/* Emperically established */
+
+	if (cb->type == PC16) {
+		i82365configure(cb);
+		return;
+	}
+
+	/* Scan the CardBus for new PCI devices */
+	pciscan(pcicfgr8(cb->pci, PciSBN), &cb->pci->bridge);
+	pci = cb->pci->bridge;
+	while (pci) {
+		r = pcicfgr16(pci, PciPCR);
+		r &= ~(PciPCR_IO|PciPCR_MEM);
+		pcicfgw16(pci, PciPCR, r);
+
+		/*
+		 * Treat the found device as an ordinary PCI card.
+		 * It seems that the CIS is not always present in
+		 * CardBus cards.
+		 * XXX, need to support multifunction cards
+		 */
+		memindex = ioindex = 0;
+		for (i = 0; i != Nbars; i++) {
+
+			if (pci->mem[i].size == 0)
+				continue;
+			if (pci->mem[i].bar & 1) {
+
+				// Allocate I/O space
+				if (ioindex > 1) {
+					print("#Y%ld: WARNING: Can only configure 2 I/O slots\n", cb - cbslots);
+					continue;
+				}
+				bar = ioreserve(-1, pci->mem[i].size, 0, "cardbus");
+				pci->mem[i].bar = bar | 1;
+				pcicfgw32(pci, PciBAR0 + i * sizeof(ulong), 
+					          pci->mem[i].bar);
+				pcicfgw16(cb->pci, PciCBIBR0 + ioindex * 8, bar);
+				pcicfgw16(cb->pci, PciCBILR0 + ioindex * 8, 
+						 bar + pci->mem[i].size - 1);
+				//print("ioindex[%d] %.8uX (%d)\n", 
+				//	ioindex, bar, pci->mem[i].size);
+				ioindex++;
+				continue;
+			}
+
+			// Allocating memory space
+			if (memindex > 1) {
+				print("#Y%ld: WARNING: Can only configure 2 memory slots\n", cb - cbslots);
+				continue;
+			}
+
+			bar = upamalloc(0, pci->mem[i].size, BY2PG);
+			pci->mem[i].bar = bar | (pci->mem[i].bar & 0x80);
+			pcicfgw32(pci, PciBAR0 + i * sizeof(ulong), pci->mem[i].bar);
+			pcicfgw32(cb->pci, PciCBMBR0 + memindex * 8, bar);
+			pcicfgw32(cb->pci, PciCBMLR0 + memindex * 8, 
+					  bar + pci->mem[i].size - 1);
+
+			if (pci->mem[i].bar & 0x80) {
+				/* Enable prefetch */
+				r = pcicfgr16(cb->pci, PciBCR);
+				r |= 1 << (8 + memindex);
+				pcicfgw16(cb->pci, PciBCR, r);
+			}
+
+			//print("memindex[%d] %.8uX (%d)\n", 
+			//	  memindex, bar, pci->mem[i].size);
+			memindex++;
+		}
+
+		if ((size = pcibarsize(pci, PciEBAR0)) > 0) {
+
+			if (memindex > 1)
+				print("#Y%ld: WARNING: Too many memory spaces, not mapping ROM space\n",
+					cb - cbslots);
+			else {
+				pci->rom.bar = upamalloc(0, size, BY2PG);
+				pci->rom.size = size;
+
+				pcicfgw32(pci, PciEBAR0, pci->rom.bar);
+				pcicfgw32(cb->pci, PciCBMBR0 + memindex * 8,
+						 pci->rom.bar);
+				pcicfgw32(cb->pci, PciCBMLR0 + memindex * 8, 
+						 pci->rom.bar + pci->rom.size - 1);
+			}
+		}
+
+		/* Set the basic PCI registers for the device */
+		pci->pcr = pcicfgr16(pci, PciPCR);
+		pci->pcr |= PciPCR_IO|PciPCR_MEM|PciPCR_Master;
+		pci->cls = 8;
+		pci->ltr = 64;
+		pcicfgw16(pci, PciPCR, pci->pcr);
+		pcicfgw8(pci, PciCLS, pci->cls);
+		pcicfgw8(pci, PciLTR, pci->ltr);
+
+		if (pcicfgr8(pci, PciINTP)) {
+			pci->intl = pcicfgr8(cb->pci, PciINTL);
+			pcicfgw8(pci, PciINTL, pci->intl);
+
+			/* Route interrupts to INTA#/B# */
+			pcicfgw16(cb->pci, PciBCR, 
+					  pcicfgr16(cb->pci, PciBCR) & ~(1 << 7));
+		}
+			
+		pci = pci->list;
+	}
+}
+
+static void
+unconfigure(Cardbus *cb)
+{
+	Pcidev *pci;
+	int i, ioindex, memindex, r;
+
+	if (cb->type == PC16) {
+		print("#Y%d: Don't know how to unconfigure a PC16 card\n",
+			 (int)(cb - cbslots));
+
+		memset(&cb->linfo, 0, sizeof(Pcminfo));
+		return;
+	}
+
+	pci = cb->pci->bridge;
+	if (pci == nil) 
+		return;		/* Not configured */
+	cb->pci->bridge = nil;		
+
+	memindex = ioindex = 0;
+	while (pci) {
+		Pcidev *_pci;
+
+		for (i = 0; i != Nbars; i++) {
+			if (pci->mem[i].size == 0)
+				continue;
+			if (pci->mem[i].bar & 1) {
+				iofree(pci->mem[i].bar & ~1);
+				pcicfgw16(cb->pci, PciCBIBR0 + ioindex * 8, 
+						 (ushort)-1);
+				pcicfgw16(cb->pci, PciCBILR0 + ioindex * 8, 0);
+				ioindex++;
+				continue;
+			}
+
+			upafree(pci->mem[i].bar & ~0xF, pci->mem[i].size);
+			pcicfgw32(cb->pci, PciCBMBR0 + memindex * 8, (ulong)-1);
+			pcicfgw32(cb->pci, PciCBMLR0 + memindex * 8, 0);
+			r = pcicfgr16(cb->pci, PciBCR);
+			r &= ~(1 << (8 + memindex));
+			pcicfgw16(cb->pci, PciBCR, r);
+			memindex++;
+		}
+
+		if (pci->rom.bar && memindex < 2) {
+			upafree(pci->rom.bar & ~0xF, pci->rom.size);
+			pcicfgw32(cb->pci, PciCBMBR0 + memindex * 8, (ulong)-1);
+			pcicfgw32(cb->pci, PciCBMLR0 + memindex * 8, 0);
+			memindex++;
+		}
+
+		_pci = pci->list;
+		free(_pci);
+		pci = _pci;
+	}
+}
+
+static void
+i82365configure(Cardbus *cb)
+{
+	int this;
+	Cisdat cis;
+	PCMmap *m;
+	uchar type, link;
+
+	/*
+	 * Read all tuples in attribute space.
+	 */
+	m = isamap(cb, 0, 0, 1);
+	if(m == 0)
+		return;
+
+	cis.cisbase = KADDR(m->isa);
+	cis.cispos = 0;
+	cis.cisskip = 2;
+	cis.cislen = m->len;
+
+	/* loop through all the tuples */
+	for(;;){
+		this = cis.cispos;
+		if(readc(&cis, &type) != 1)
+			break;
+		if(type == 0xFF)
+			break;
+		if(readc(&cis, &link) != 1)
+			break;
+
+		switch(type){
+		default:
+			break;
+		case 0x15:
+			tvers1(cb, &cis, type);
+			break;
+		case 0x1A:
+			tcfig(cb, &cis, type);
+			break;
+		case 0x1B:
+			tentry(cb, &cis, type);
+			break;
+		}
+
+		if(link == 0xFF)
+			break;
+		cis.cispos = this + (2+link);
+	}
+	isaunmap(m);
+}
+
+/*
+ *  look for a card whose version contains 'idstr'
+ */
+static int
+pccard_pcmspecial(char *idstr, ISAConf *isa)
+{
+	int i, irq;
+	PCMconftab *ct, *et;
+	Pcminfo *pi;
+	Cardbus *cb;
+	uchar x, we, *p;
+
+	cb = nil;
+	for (i = 0; i != nslots; i++) {
+		cb = &cbslots[i];
+
+		lock(cb);
+		if (cb->state == SlotConfigured &&
+		    cb->type == PC16 && 
+		    !cb->special &&
+		    strstr(cb->linfo.verstr, idstr)) 
+			break;
+		unlock(cb);
+	}
+
+	if (i == nslots) {
+		// print("#Y: %s not found\n", idstr);
+		return -1;
+	}
+
+	pi = &cb->linfo;
+
+	/*
+ 	  *  configure the PCMslot for IO.  We assume very heavily that we can read
+ 	  *  configuration info from the CIS.  If not, we won't set up correctly.
+ 	  */
+	irq = isa->irq;
+	if(irq == 2)
+		irq = 9;
+
+	et = &pi->ctab[pi->nctab];
+	ct = nil;
+	for(i = 0; i < isa->nopt; i++){
+		int index;
+		char *cp;
+
+		if(strncmp(isa->opt[i], "index=", 6))
+			continue;
+		index = strtol(&isa->opt[i][6], &cp, 0);
+		if(cp == &isa->opt[i][6] || index >= pi->nctab) {
+			unlock(cb);
+			print("#Y%d: Cannot find index %d in conf table\n", 
+				 (int)(cb - cbslots), index);
+			return -1;
+		}
+		ct = &pi->ctab[index];
+	}
+
+	if(ct == nil){
+		PCMconftab *t;
+
+		/* assume default is right */
+		if(pi->defctab)
+			ct = pi->defctab;
+		else
+			ct = pi->ctab;
+	
+		/* try for best match */
+		if(ct->nio == 0
+		|| ct->io[0].start != isa->port || ((1<<irq) & ct->irqs) == 0){
+			for(t = pi->ctab; t < et; t++)
+				if(t->nio
+				&& t->io[0].start == isa->port
+				&& ((1<<irq) & t->irqs)){
+					ct = t;
+					break;
+				}
+		}
+		if(ct->nio == 0 || ((1<<irq) & ct->irqs) == 0){
+			for(t = pi->ctab; t < et; t++)
+				if(t->nio && ((1<<irq) & t->irqs)){
+					ct = t;
+					break;
+				}
+		}
+		if(ct->nio == 0){
+			for(t = pi->ctab; t < et; t++)
+				if(t->nio){
+					ct = t;
+					break;
+				}
+		}
+	}
+
+	if(ct == et || ct->nio == 0) {
+		unlock(cb);
+		print("#Y%d: No configuration?\n", (int)(cb - cbslots));
+		return -1;
+	}
+	if(isa->port == 0 && ct->io[0].start == 0) {
+		unlock(cb);
+		print("#Y%d: No part or start address\n", (int)(cb - cbslots));
+		return -1;
+	}
+
+	cb->special = 1;	/* taken */
+
+	/* route interrupts */
+	isa->irq = irq;
+	wrreg(cb, Rigc, irq | Fnotreset | Fiocard);
+
+	/* set power and enable device */
+	x = vcode(ct->vpp1);
+	wrreg(cb, Rpc, x|Fautopower|Foutena|Fcardena);
+
+	/* 16-bit data path */
+	if(ct->bit16)
+		x = Ftiming|Fiocs16|Fwidth16;
+	else
+		x = Ftiming;
+	if(ct->nio == 2 && ct->io[1].start)
+		x |= x<<4;
+	wrreg(cb, Rio, x);
+
+	/*
+	 * enable io port map 0
+	 * the 'top' register value includes the last valid address
+	 */
+	if(isa->port == 0)
+		isa->port = ct->io[0].start;
+	we = rdreg(cb, Rwe);
+	wrreg(cb, Riobtm0lo, isa->port);
+	wrreg(cb, Riobtm0hi, isa->port>>8);
+	i = isa->port+ct->io[0].len-1;
+	wrreg(cb, Riotop0lo, i);
+	wrreg(cb, Riotop0hi, i>>8);
+	we |= 1<<6;
+	if(ct->nio == 2 && ct->io[1].start){
+		wrreg(cb, Riobtm1lo, ct->io[1].start);
+		wrreg(cb, Riobtm1hi, ct->io[1].start>>8);
+		i = ct->io[1].start+ct->io[1].len-1;
+		wrreg(cb, Riotop1lo, i);
+		wrreg(cb, Riotop1hi, i>>8);
+		we |= 1<<7;
+	}
+	wrreg(cb, Rwe, we);
+
+	/* only touch Rconfig if it is present */
+	if(pi->conf_present & (1<<Rconfig)){
+		PCMmap *m;
+
+		/*  Reset adapter */
+		m = isamap(cb, pi->conf_addr + Rconfig, 1, 1);
+		p = KADDR(m->isa + pi->conf_addr + Rconfig - m->ca);
+
+		/* set configuration and interrupt type */
+		x = ct->index;
+		if((ct->irqtype & 0x20)/* && ((ct->irqtype & 0x40)==0 || isa->irq>7)*/)
+			x |= Clevel;
+		*p = x;
+		delay(5);
+
+		isaunmap(m);
+	}
+
+	pi->port = isa->port;
+	pi->irq = isa->irq;
+	unlock(cb);
+
+	print("#Y%d: %s irq %ld, port %lX\n", (int)(cb - cbslots), pi->verstr, isa->irq, isa->port);
+	return (int)(cb - cbslots);
+}
+
+static void
+pccard_pcmspecialclose(int slotno)
+{
+	Cardbus *cb = &cbslots[slotno];
+
+	wrreg(cb, Rwe, 0);	/* no windows */
+	cb->special = 0;
+}
+
+static int
+xcistuple(int slotno, int tuple, int subtuple, void *v, int nv, int attr)
+{
+	PCMmap *m;
+	Cisdat cis;
+	int i, l;
+	uchar *p;
+	uchar type, link, n, c;
+	int this, subtype;
+	Cardbus *cb = &cbslots[slotno];
+
+	m = isamap(cb, 0, 0, attr);
+	if(m == 0)
+		return -1;
+
+	cis.cisbase = KADDR(m->isa);
+	cis.cispos = 0;
+	cis.cisskip = attr ? 2 : 1;
+	cis.cislen = m->len;
+
+	/* loop through all the tuples */
+	for(i = 0; i < 1000; i++){
+		this = cis.cispos;
+		if(readc(&cis, &type) != 1)
+			break;
+		if(type == 0xFF)
+			break;
+		if(readc(&cis, &link) != 1)
+			break;
+		if(link == 0xFF)
+			break;
+
+		n = link;
+		if (link > 1 && subtuple != -1) {
+			if (readc(&cis, &c) != 1)
+				break;
+			subtype = c;
+			n--;
+		} else
+			subtype = -1;
+
+		if(type == tuple && subtype == subtuple) {
+			p = v;
+			for(l=0; l<nv && l<n; l++)
+				if(readc(&cis, p++) != 1)
+					break;
+			isaunmap(m);
+			return nv;
+		}
+		cis.cispos = this + (2+link);
+	}
+	isaunmap(m);
+	return -1;
+}
+
+static PCMmap *
+isamap(Cardbus *cb, ulong offset, int len, int attr)
+{
+	uchar we, bit;
+	PCMmap *m, *nm;
+	Pcminfo *pi;
+	int i;
+	ulong e;
+
+	pi = &cb->linfo;
+
+	/* convert offset to granularity */
+	if(len <= 0)
+		len = 1;
+	e = ROUND(offset+len, Mgran);
+	offset &= Mmask;
+	len = e - offset;
+
+	/* look for a map that covers the right area */
+	we = rdreg(cb, Rwe);
+	bit = 1;
+	nm = 0;
+	for(m = pi->mmap; m < &pi->mmap[nelem(pi->mmap)]; m++){
+		if((we & bit))
+		if(m->attr == attr)
+		if(offset >= m->ca && e <= m->cea){
+
+			m->ref++;
+			return m;
+		}
+		bit <<= 1;
+		if(nm == 0 && m->ref == 0)
+			nm = m;
+	}
+	m = nm;
+	if(m == 0)
+		return 0;
+
+	/* if isa space isn't big enough, free it and get more */
+	if(m->len < len){
+		if(m->isa){
+			umbfree(m->isa, m->len);
+			m->len = 0;
+		}
+		m->isa = PADDR(umbmalloc(0, len, Mgran));
+		if(m->isa == 0){
+			print("isamap: out of isa space\n");
+			return 0;
+		}
+		m->len = len;
+	}
+
+	/* set up new map */
+	m->ca = offset;
+	m->cea = m->ca + m->len;
+	m->attr = attr;
+	i = m - pi->mmap;
+	bit = 1<<i;
+	wrreg(cb, Rwe, we & ~bit);		/* disable map before changing it */
+	wrreg(cb, MAP(i, Mbtmlo), m->isa>>Mshift);
+	wrreg(cb, MAP(i, Mbtmhi), (m->isa>>(Mshift+8)) | F16bit);
+	wrreg(cb, MAP(i, Mtoplo), (m->isa+m->len-1)>>Mshift);
+	wrreg(cb, MAP(i, Mtophi), ((m->isa+m->len-1)>>(Mshift+8)));
+	offset -= m->isa;
+	offset &= (1<<25)-1;
+	offset >>= Mshift;
+	wrreg(cb, MAP(i, Mofflo), offset);
+	wrreg(cb, MAP(i, Moffhi), (offset>>8) | (attr ? Fregactive : 0));
+	wrreg(cb, Rwe, we | bit);		/* enable map */
+	m->ref = 1;
+
+	return m;
+}
+
+static void
+isaunmap(PCMmap* m)
+{
+	m->ref--;
+}
+
+/*
+ *  reading and writing card registers
+ */
+static uchar
+rdreg(Cardbus *cb, int index)
+{
+	outb(cb->lindex, cb->lbase + index);
+	return inb(cb->ldata);
+}
+
+static void
+wrreg(Cardbus *cb, int index, uchar val)
+{
+	outb(cb->lindex, cb->lbase + index);
+	outb(cb->ldata, val);
+}
+
+static int
+readc(Cisdat *cis, uchar *x)
+{
+	if(cis->cispos >= cis->cislen)
+		return 0;
+	*x = cis->cisbase[cis->cisskip*cis->cispos];
+	cis->cispos++;
+	return 1;
+}
+
+static ulong
+getlong(Cisdat *cis, int size)
+{
+	uchar c;
+	int i;
+	ulong x;
+
+	x = 0;
+	for(i = 0; i < size; i++){
+		if(readc(cis, &c) != 1)
+			break;
+		x |= c<<(i*8);
+	}
+	return x;
+}
+
+static void
+tcfig(Cardbus *cb, Cisdat *cis, int )
+{
+	uchar size, rasize, rmsize;
+	uchar last;
+	Pcminfo *pi;
+
+	if(readc(cis, &size) != 1)
+		return;
+	rasize = (size&0x3) + 1;
+	rmsize = ((size>>2)&0xf) + 1;
+	if(readc(cis, &last) != 1)
+		return;
+
+	pi = &cb->linfo;
+	pi->conf_addr = getlong(cis, rasize);
+	pi->conf_present = getlong(cis, rmsize);
+}
+
+static void
+tvers1(Cardbus *cb, Cisdat *cis, int )
+{
+	uchar c, major, minor, last;
+	int  i;
+	Pcminfo *pi;
+
+	pi = &cb->linfo;
+	if(readc(cis, &major) != 1)
+		return;
+	if(readc(cis, &minor) != 1)
+		return;
+	last = 0;
+	for(i = 0; i < sizeof(pi->verstr) - 1; i++){
+		if(readc(cis, &c) != 1)
+			return;
+		if(c == 0)
+			c = ';';
+		if(c == '\n')
+			c = ';';
+		if(c == 0xff)
+			break;
+		if(c == ';' && last == ';')
+			continue;
+		pi->verstr[i] = c;
+		last = c;
+	}
+	pi->verstr[i] = 0;
+}
+
+static ulong
+microvolt(Cisdat *cis)
+{
+	uchar c;
+	ulong microvolts;
+	ulong exp;
+
+	if(readc(cis, &c) != 1)
+		return 0;
+	exp = exponent[c&0x7];
+	microvolts = vmant[(c>>3)&0xf]*exp;
+	while(c & 0x80){
+		if(readc(cis, &c) != 1)
+			return 0;
+		switch(c){
+		case 0x7d:
+			break;		/* high impedence when sleeping */
+		case 0x7e:
+		case 0x7f:
+			microvolts = 0;	/* no connection */
+			break;
+		default:
+			exp /= 10;
+			microvolts += exp*(c&0x7f);
+		}
+	}
+	return microvolts;
+}
+
+static ulong
+nanoamps(Cisdat *cis)
+{
+	uchar c;
+	ulong nanoamps;
+
+	if(readc(cis, &c) != 1)
+		return 0;
+	nanoamps = exponent[c&0x7]*vmant[(c>>3)&0xf];
+	while(c & 0x80){
+		if(readc(cis, &c) != 1)
+			return 0;
+		if(c == 0x7d || c == 0x7e || c == 0x7f)
+			nanoamps = 0;
+	}
+	return nanoamps;
+}
+
+/*
+ * only nominal voltage (feature 1) is important for config,
+ * other features must read card to stay in sync.
+ */
+static ulong
+power(Cisdat *cis)
+{
+	uchar feature;
+	ulong mv;
+
+	mv = 0;
+	if(readc(cis, &feature) != 1)
+		return 0;
+	if(feature & 1)
+		mv = microvolt(cis);
+	if(feature & 2)
+		microvolt(cis);
+	if(feature & 4)
+		microvolt(cis);
+	if(feature & 8)
+		nanoamps(cis);
+	if(feature & 0x10)
+		nanoamps(cis);
+	if(feature & 0x20)
+		nanoamps(cis);
+	if(feature & 0x40)
+		nanoamps(cis);
+	return mv/1000000;
+}
+
+static ulong
+ttiming(Cisdat *cis, int scale)
+{
+	uchar unscaled;
+	ulong nanosecs;
+
+	if(readc(cis, &unscaled) != 1)
+		return 0;
+	nanosecs = (mantissa[(unscaled>>3)&0xf]*exponent[unscaled&7])/10;
+	nanosecs = nanosecs * exponent[scale];
+	return nanosecs;
+}
+
+static void
+timing(Cisdat *cis, PCMconftab *ct)
+{
+	uchar c, i;
+
+	if(readc(cis, &c) != 1)
+		return;
+	i = c&0x3;
+	if(i != 3)
+		ct->maxwait = ttiming(cis, i);		/* max wait */
+	i = (c>>2)&0x7;
+	if(i != 7)
+		ct->readywait = ttiming(cis, i);	/* max ready/busy wait */
+	i = (c>>5)&0x7;
+	if(i != 7)
+		ct->otherwait = ttiming(cis, i);	/* reserved wait */
+}
+
+static void
+iospaces(Cisdat *cis, PCMconftab *ct)
+{
+	uchar c;
+	int i, nio;
+
+	ct->nio = 0;
+	if(readc(cis, &c) != 1)
+		return;
+
+	ct->bit16 = ((c>>5)&3) >= 2;
+	if(!(c & 0x80)){
+		ct->io[0].start = 0;
+		ct->io[0].len = 1<<(c&0x1f);
+		ct->nio = 1;
+		return;
+	}
+
+	if(readc(cis, &c) != 1)
+		return;
+
+	/*
+	 * For each of the range descriptions read the
+	 * start address and the length (value is length-1).
+	 */
+	nio = (c&0xf)+1;
+	for(i = 0; i < nio; i++){
+		ct->io[i].start = getlong(cis, (c>>4)&0x3);
+		ct->io[i].len = getlong(cis, (c>>6)&0x3)+1;
+	}
+	ct->nio = nio;
+}
+
+static void
+irq(Cisdat *cis, PCMconftab *ct)
+{
+	uchar c;
+
+	if(readc(cis, &c) != 1)
+		return;
+	ct->irqtype = c & 0xe0;
+	if(c & 0x10)
+		ct->irqs = getlong(cis, 2);
+	else
+		ct->irqs = 1<<(c&0xf);
+	ct->irqs &= 0xDEB8;		/* levels available to card */
+}
+
+static void
+memspace(Cisdat *cis, int asize, int lsize, int host)
+{
+	ulong haddress, address, len;
+
+	len = getlong(cis, lsize)*256;
+	address = getlong(cis, asize)*256;
+	USED(len, address);
+	if(host){
+		haddress = getlong(cis, asize)*256;
+		USED(haddress);
+	}
+}
+
+static void
+tentry(Cardbus *cb, Cisdat *cis, int )
+{
+	uchar c, i, feature;
+	PCMconftab *ct;
+	Pcminfo *pi;
+
+	pi = &cb->linfo;
+	if(pi->nctab >= nelem(pi->ctab))
+		return;
+	if(readc(cis, &c) != 1)
+		return;
+	ct = &pi->ctab[pi->nctab++];
+
+	/* copy from last default config */
+	if(pi->defctab)
+		*ct = *pi->defctab;
+
+	ct->index = c & 0x3f;
+
+	/* is this the new default? */
+	if(c & 0x40)
+		pi->defctab = ct;
+
+	/* memory wait specified? */
+	if(c & 0x80){
+		if(readc(cis, &i) != 1)
+			return;
+		if(i&0x80)
+			ct->memwait = 1;
+	}
+
+	if(readc(cis, &feature) != 1)
+		return;
+	switch(feature&0x3){
+	case 1:
+		ct->vpp1 = ct->vpp2 = power(cis);
+		break;
+	case 2:
+		power(cis);
+		ct->vpp1 = ct->vpp2 = power(cis);
+		break;
+	case 3:
+		power(cis);
+		ct->vpp1 = power(cis);
+		ct->vpp2 = power(cis);
+		break;
+	default:
+		break;
+	}
+	if(feature&0x4)
+		timing(cis, ct);
+	if(feature&0x8)
+		iospaces(cis, ct);
+	if(feature&0x10)
+		irq(cis, ct);
+	switch((feature>>5)&0x3){
+	case 1:
+		memspace(cis, 0, 2, 0);
+		break;
+	case 2:
+		memspace(cis, 2, 2, 0);
+		break;
+	case 3:
+		if(readc(cis, &c) != 1)
+			return;
+		for(i = 0; i <= (c&0x7); i++)
+			memspace(cis, (c>>5)&0x3, (c>>3)&0x3, c&0x80);
+		break;
+	}
+}
+
+static void
+i82365probe(Cardbus *cb, int lindex, int ldata)
+{
+	uchar c, id;
+	int dev = 0;	/* According to the Ricoh spec 00->3F _and_ 80->BF seem
+				     to be the same socket A (ditto for B). */
+
+	outb(lindex, Rid + (dev<<7));
+	id = inb(ldata);
+	if((id & 0xf0) != 0x80)
+		return;		/* not a memory & I/O card */
+	if((id & 0x0f) == 0x00)
+		return;		/* no revision number, not possible */
+
+	cb->lindex = lindex;
+	cb->ldata = ldata;
+	cb->ltype = Ti82365;
+	cb->lbase = (int)(cb - cbslots) * 0x40;
+
+	switch(id){
+	case 0x82:
+	case 0x83:
+	case 0x84:
+		/* could be a cirrus */
+		outb(cb->lindex, Rchipinfo + (dev<<7));
+		outb(cb->ldata, 0);
+		c = inb(cb->ldata);
+		if((c & 0xc0) != 0xc0)
+			break;
+		c = inb(cb->ldata);
+		if((c & 0xc0) != 0x00)
+			break;
+		if(c & 0x20){
+			cb->ltype = Tpd6720;
+		} else {
+			cb->ltype = Tpd6710;
+		}
+		break;
+	}
+
+	/* if it's not a Cirrus, it could be a Vadem... */
+	if(cb->ltype == Ti82365){
+		/* unlock the Vadem extended regs */
+		outb(cb->lindex, 0x0E + (dev<<7));
+		outb(cb->lindex, 0x37 + (dev<<7));
+
+		/* make the id register show the Vadem id */
+		outb(cb->lindex, 0x3A + (dev<<7));
+		c = inb(cb->ldata);
+		outb(cb->ldata, c|0xC0);
+		outb(cb->lindex, Rid + (dev<<7));
+		c = inb(cb->ldata);
+		if(c & 0x08)
+			cb->ltype = Tvg46x;
+
+		/* go back to Intel compatible id */
+		outb(cb->lindex, 0x3A + (dev<<7));
+		c = inb(cb->ldata);
+		outb(cb->ldata, c & ~0xC0);
+	}
+}
+
+static int
+vcode(int volt)
+{
+	switch(volt){
+	case 5:
+		return 1;
+	case 12:
+		return 2;
+	default:
+		return 0;
+	}
+}
--- /dev/null
+++ b/os/boot.original/pc/devsd.c
@@ -1,0 +1,631 @@
+/*
+ * Storage Device.
+ */
+#include "u.h"
+#include "mem.h"
+#include "lib.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "ureg.h"
+#include "error.h"
+
+#include "sd.h"
+#include "fs.h"
+
+#define parttrace 0
+
+
+extern SDifc* sdifc[];
+
+static SDev* sdlist;
+static SDunit** sdunit;
+static int sdnunit;
+static int _sdmask;
+static int cdmask;
+static int sdmask;
+
+enum {
+	Rawcmd,
+	Rawdata,
+	Rawstatus,
+};
+
+void
+sdaddpart(SDunit* unit, char* name, uvlong start, uvlong end)
+{
+	SDpart *pp;
+	int i, partno;
+
+	if(parttrace)
+		print("add %d %s %s %lld %lld\n", unit->npart, unit->name, name, start, end);
+	/*
+	 * Check name not already used
+	 * and look for a free slot.
+	 */
+	if(unit->part != nil){
+		partno = -1;
+		for(i = 0; i < SDnpart; i++){
+			pp = &unit->part[i];
+			if(!pp->valid){
+				if(partno == -1)
+					partno = i;
+				break;
+			}
+			if(strcmp(name, pp->name) == 0){
+				if(pp->start == start && pp->end == end){
+					if(parttrace)
+						print("already present\n");
+					return;
+				}
+			}
+		}
+	}else{
+		if((unit->part = malloc(sizeof(SDpart)*SDnpart)) == nil){
+			if(parttrace)
+				print("malloc failed\n");
+			return;
+		}
+		partno = 0;
+	}
+
+	/*
+	 * Check there is a free slot and size and extent are valid.
+	 */
+	if(partno == -1 || start > end || end > unit->sectors){
+		print("cannot add %s!%s [%llud,%llud) to disk [0,%llud): %s\n",
+			unit->name, name, start, end, unit->sectors, 
+			partno==-1 ? "no free partitions" : "partition boundaries out of range");
+		return;
+	}
+	pp = &unit->part[partno];
+	pp->start = start;
+	pp->end = end;
+	strncpy(pp->name, name, NAMELEN);
+	pp->valid = 1;
+	unit->npart++;
+}
+
+void
+sddelpart(SDunit* unit,  char* name)
+{
+	int i;
+	SDpart *pp;
+
+	if(parttrace)
+		print("del %d %s %s\n", unit->npart, unit->name, name);
+	/*
+	 * Look for the partition to delete.
+	 * Can't delete if someone still has it open.
+	 * If it's the last valid partition zap the
+	 * whole table.
+	 */
+	pp = unit->part;
+	for(i = 0; i < SDnpart; i++){
+		if(strncmp(name, pp->name, NAMELEN) == 0)
+			break;
+		pp++;
+	}
+	if(i >= SDnpart)
+		return;
+	pp->valid = 0;
+
+	unit->npart--;
+	if(unit->npart == 0){
+		free(unit->part);
+		unit->part = nil;
+	}
+}
+
+static int
+sdinitpart(SDunit* unit)
+{
+	unit->sectors = unit->secsize = 0;
+	unit->npart = 0;
+	if(unit->part){
+		free(unit->part);
+		unit->part = nil;
+	}
+
+	if(unit->inquiry[0] & 0xC0)
+		return 0;
+	switch(unit->inquiry[0] & 0x1F){
+	case 0x00:			/* DA */
+	case 0x04:			/* WORM */
+	case 0x05:			/* CD-ROM */
+	case 0x07:			/* MO */
+		break;
+	default:
+		return 0;
+	}
+
+	if(unit->dev->ifc->online == nil || unit->dev->ifc->online(unit) == 0)
+		return 0;
+	sdaddpart(unit, "data", 0, unit->sectors);
+	return 1;
+}
+
+static SDunit*
+sdgetunit(SDev* sdev, int subno)
+{
+	int index;
+	SDunit *unit;
+
+	/*
+	 * Associate a unit with a given device and sub-unit
+	 * number on that device.
+	 * The device will be probed if it has not already been
+	 * successfully accessed.
+	 */
+	qlock(&sdqlock);
+	index = sdev->index+subno;
+	unit = sdunit[index];
+	if(unit == nil){
+		if((unit = malloc(sizeof(SDunit))) == nil){
+			qunlock(&sdqlock);
+			return nil;
+		}
+
+		if(sdev->enabled == 0 && sdev->ifc->enable)
+			sdev->ifc->enable(sdev);
+		sdev->enabled = 1;
+
+		snprint(unit->name, NAMELEN, "sd%c%d", sdev->idno, subno);
+		unit->subno = subno;
+		unit->dev = sdev;
+
+		/*
+		 * No need to lock anything here as this is only
+		 * called before the unit is made available in the
+		 * sdunit[] array.
+		 */
+		if(unit->dev->ifc->verify(unit) == 0){
+			qunlock(&sdqlock);
+			free(unit);
+			return nil;
+		}
+		sdunit[index] = unit;
+	}
+	qunlock(&sdqlock);
+
+	return unit;
+}
+
+static SDunit*
+sdindex2unit(int index)
+{
+	SDev *sdev;
+
+	/*
+	 * Associate a unit with a given index into the top-level
+	 * device directory.
+	 * The device will be probed if it has not already been
+	 * successfully accessed.
+	 */
+	for(sdev = sdlist; sdev != nil; sdev = sdev->next){
+		if(index >= sdev->index && index < sdev->index+sdev->nunit)
+			return sdgetunit(sdev, index-sdev->index);
+	}
+
+	return nil;
+}
+
+static void
+_sddetach(void)
+{
+	SDev *sdev;
+
+	for(sdev = sdlist; sdev != nil; sdev = sdev->next){
+		if(sdev->enabled == 0)
+			continue;
+		if(sdev->ifc->disable)
+			sdev->ifc->disable(sdev);
+		sdev->enabled = 0;
+	}
+}
+
+static void
+sddump(void)
+{
+	SDev *sdev;
+
+	print("sdevs:\n");
+	for(sdev = sdlist; sdev != nil; sdev = sdev->next){
+		print("sdev %c index %d nunit %d: ",
+			sdev->idno, sdev->index, sdev->nunit);
+		print("\n");
+	}
+}
+
+static int
+_sdinit(void)
+{
+	ulong m;
+	int i;
+	SDev *sdev, *tail;
+	SDunit *unit;
+
+	/*
+	 * Probe all configured controllers and make a list
+	 * of devices found, accumulating a possible maximum number
+	 * of units attached and marking each device with an index
+	 * into the linear top-level directory array of units.
+	 */
+	tail = nil;
+	for(i = 0; sdifc[i] != nil; i++){
+		if((sdev = sdifc[i]->pnp()) == nil)
+			continue;
+		if(sdlist != nil)
+			tail->next = sdev;
+		else
+			sdlist = sdev;
+		for(tail = sdev; tail->next != nil; tail = tail->next){
+			tail->index = sdnunit;
+			sdnunit += tail->nunit;
+		}
+		tail->index = sdnunit;
+		sdnunit += tail->nunit;
+	}
+	/*
+	 * Legacy and option code goes here. This will be hard...
+	 */
+
+	/*
+	 * The maximum number of possible units is known, allocate
+	 * placeholders for their datastructures; the units will be
+	 * probed and structures allocated when attached.
+	 * Allocate controller names for the different types.
+	 */
+	if(sdnunit == 0)
+		return 0;
+	if((sdunit = malloc(sdnunit*sizeof(SDunit*))) == nil)
+		return 0;
+	sddetach = _sddetach;
+
+	for(i = 0; sdifc[i] != nil; i++){
+		if(sdifc[i]->id)
+			sdifc[i]->id(sdlist);
+	}
+	if (0)
+		sddump();
+
+	m = 0;
+	cdmask = sdmask = 0;
+	for(i=0; i<sdnunit && i < 32; i++) {
+		unit = sdindex2unit(i);
+		if(unit == nil)
+			continue;
+		sdinitpart(unit);
+		partition(unit);
+		if(unit->npart > 0){	/* BUG */
+			if((unit->inquiry[0] & 0x1F) == 0x05)
+				cdmask |= (1<<i);
+			else
+				sdmask |= (1<<i);
+			m |= (1<<i);
+		}
+	}
+
+//notesdinfo();
+	_sdmask = m;
+	return m;
+}
+
+int
+cdinit(void)
+{
+	if(sdnunit == 0)
+		_sdinit();
+	return cdmask;
+}
+
+int
+sdinit(void)
+{
+	if(sdnunit == 0)
+		_sdinit();
+	return sdmask;
+}
+
+void
+sdinitdev(int i, char *s)
+{
+	SDunit *unit;
+
+	unit = sdindex2unit(i);
+	strcpy(s, unit->name);
+}
+
+void
+sdprintdevs(int i)
+{
+	char *s;
+	SDunit *unit;
+
+	unit = sdindex2unit(i);
+	for(i=0; i<unit->npart; i++){
+		s = unit->part[i].name;
+		if(strncmp(s, "dos", 3) == 0
+		|| strncmp(s, "9fat", 4) == 0
+		|| strncmp(s, "fs", 2) == 0)
+			print(" %s!%s", unit->name, s);
+	}
+}
+
+SDpart*
+sdfindpart(SDunit *unit, char *name)
+{
+	int i;
+
+	if(parttrace)
+		print("findpart %d %s %s\t\n", unit->npart, unit->name, name);
+	for(i=0; i<unit->npart; i++) {
+		if(parttrace)
+			print("%s...", unit->part[i].name);
+		if(strcmp(unit->part[i].name, name) == 0){
+			if(parttrace)
+				print("\n");
+			return &unit->part[i];
+		}
+	}
+	if(parttrace)
+		print("not found\n");
+	return nil;
+}
+
+typedef struct Scsicrud Scsicrud;
+struct Scsicrud {
+	Fs fs;
+	vlong offset;
+	SDunit *unit;
+	SDpart *part;
+};
+
+long
+sdread(Fs *vcrud, void *v, long n)
+{
+	Scsicrud *crud;
+	long x;
+
+	crud = (Scsicrud*)vcrud;
+	x = sdbio(crud->unit, crud->part, v, n, crud->offset);
+	if(x > 0)
+		crud->offset += x;
+	return x;
+}
+
+vlong
+sdseek(Fs *vcrud, vlong seek)
+{
+	((Scsicrud*)vcrud)->offset = seek;
+	return seek;
+}
+
+void*
+sdgetfspart(int i, char *s, int chatty)
+{
+	SDunit *unit;
+	SDpart *p;
+	Scsicrud *crud;
+
+	if(cdmask&(1<<i)){
+		if(strcmp(s, "cdboot") != 0)
+			return nil;
+	}else if(sdmask&(1<<i)){
+		if(strcmp(s, "cdboot") == 0)
+			return nil;
+	}
+
+	unit = sdindex2unit(i);
+	if((p = sdfindpart(unit, s)) == nil){
+		if(chatty)
+			print("unknown partition %s!%s\n", unit->name, s);
+		return nil;
+	}
+	if(p->crud == nil) {
+		crud = malloc(sizeof(Scsicrud));
+		crud->fs.dev = i;
+		crud->fs.diskread = sdread;
+		crud->fs.diskseek = sdseek;
+	//	crud->start = 0;
+		crud->unit = unit;
+		crud->part = p;
+		if(dosinit(&crud->fs) < 0 && dosinit(&crud->fs) < 0 && kfsinit(&crud->fs) < 0){
+			if(chatty)
+				print("partition %s!%s does not contain a DOS or KFS file system\n",
+					unit->name, s);
+			return nil;
+		}
+		p->crud = crud;
+	}
+	return p->crud;
+}
+
+/*
+ * Leave partitions around for devsd to pick up.
+ * (Needed by boot process; more extensive 
+ * partitioning is done by termrc or cpurc).
+ */
+void
+sdaddconf(int i)
+{
+	SDunit *unit;
+	SDpart *pp;
+
+	unit = sdindex2unit(i);
+	
+	/*
+	 * If there were no partitions (just data and partition), don't bother.
+	 */
+	if(unit->npart<= 1 || (unit->npart==2 && strcmp(unit->part[1].name, "partition")==0))
+		return;
+
+	addconf("%spart=", unit->name);
+	for(i=1, pp=&unit->part[i]; i<unit->npart; i++, pp++)	/* skip 0, which is "data" */
+		addconf("%s%s %lld %lld", i==1 ? "" : "/", pp->name,
+			pp->start, pp->end);
+	addconf("\n");
+}
+
+int
+sdboot(int dev, char *pname, Boot *b)
+{
+	char *file;
+	Fs *fs;
+
+	if((file = strchr(pname, '!')) == nil) {
+		print("syntax is sdC0!partition!file\n");
+		return -1;
+	}
+	*file++ = '\0';
+
+	fs = sdgetfspart(dev, pname, 1);
+	if(fs == nil)
+		return -1;
+
+	return fsboot(fs, file, b);
+}
+
+long
+sdbio(SDunit *unit, SDpart *pp, void* va, long len, vlong off)
+{
+	long l;
+	ulong bno, max, nb, offset;
+	static uchar *b;
+	char *a;
+	static ulong bsz;
+
+	a = va;
+memset(a, 0xDA, len);
+	qlock(&unit->ctl);
+	if(unit->changed){
+		qunlock(&unit->ctl);
+		return 0;
+	}
+
+	/*
+	 * Check the request is within bounds.
+	 * Removeable drives are locked throughout the I/O
+	 * in case the media changes unexpectedly.
+	 * Non-removeable drives are not locked during the I/O
+	 * to allow the hardware to optimise if it can; this is
+	 * a little fast and loose.
+	 * It's assumed that non-removable media parameters
+	 * (sectors, secsize) can't change once the drive has
+	 * been brought online.
+	 */
+	bno = (off/unit->secsize) + pp->start;
+	nb = ((off+len+unit->secsize-1)/unit->secsize) + pp->start - bno;
+	max = SDmaxio/unit->secsize;
+	if(nb > max)
+		nb = max;
+	if(bno+nb > pp->end)
+		nb = pp->end - bno;
+	if(bno >= pp->end || nb == 0){
+		qunlock(&unit->ctl);
+		return 0;
+	}
+	if(!(unit->inquiry[1] & 0x80))
+		qunlock(&unit->ctl);
+
+	if(bsz < nb*unit->secsize){
+		b = malloc(nb*unit->secsize);
+		bsz = nb*unit->secsize;
+	}
+//	b = sdmalloc(nb*unit->secsize);
+//	if(b == nil)
+//		return 0;
+
+	offset = off%unit->secsize;
+	if((l = unit->dev->ifc->bio(unit, 0, 0, b, nb, bno)) < 0) {
+//		sdfree(b);
+		return 0;
+	}
+
+	if(l < offset)
+		len = 0;
+	else if(len > l - offset)
+		len = l - offset;
+	if(len)
+		memmove(a, b+offset, len);
+//	sdfree(b);
+
+	if(unit->inquiry[1] & 0x80)
+		qunlock(&unit->ctl);
+
+	return len;
+}
+
+#ifdef DMA
+long
+sdrio(SDreq *r, void* a, long n)
+{
+	if(n >= SDmaxio || n < 0)
+		return 0;
+
+	r->data = nil;
+	if(n){
+		if((r->data = malloc(n)) == nil)
+			return 0;
+		if(r->write)
+			memmove(r->data, a, n);
+	}
+	r->dlen = n;
+
+	if(r->unit->dev->ifc->rio(r) != SDok){
+// cgascreenputs("1", 1);
+		if(r->data != nil){
+			sdfree(r->data);
+			r->data = nil;
+		}
+		return 0;
+	}
+// cgascreenputs("2", 1);
+
+	if(!r->write && r->rlen > 0)
+		memmove(a, r->data, r->rlen);
+// cgascreenputs("3", 1);
+	if(r->data != nil){
+		sdfree(r->data);
+		r->data = nil;
+	}
+
+// cgascreenputs("4", 1);
+	return r->rlen;
+}
+#endif /* DMA */
+
+void
+sleep(void*, int (*fn)(void*), void *v)
+{
+	int x;
+	x = spllo();
+	while(!fn(v))
+		;
+	splx(x);
+	return;
+}
+
+void
+tsleep(void*, int (*fn)(void*), void *v, int msec)
+{
+	int x;
+	ulong start;
+
+	x = spllo();
+	for(start = m->ticks; TK2MS(m->ticks - start) < msec
+		&& !fn(v); )
+		;
+	splx(x);
+	return;
+}
+
+void*
+sdmalloc(void *p, ulong sz)
+{
+	if(p != nil) {
+		memset(p, 0, sz);
+		return p;
+	}
+	return malloc(sz);
+}
--- /dev/null
+++ b/os/boot.original/pc/dma.c
@@ -1,0 +1,245 @@
+#include	"u.h"
+#include	"lib.h"
+#include	"mem.h"
+#include	"dat.h"
+#include	"fns.h"
+
+typedef struct DMAport	DMAport;
+typedef struct DMA	DMA;
+typedef struct DMAxfer	DMAxfer;
+
+enum
+{
+	/*
+	 *  the byte registers for DMA0 are all one byte apart
+	 */
+	Dma0=		0x00,
+	Dma0status=	Dma0+0x8,	/* status port */
+	Dma0reset=	Dma0+0xD,	/* reset port */
+
+	/*
+	 *  the byte registers for DMA1 are all two bytes apart (why?)
+	 */
+	Dma1=		0xC0,
+	Dma1status=	Dma1+2*0x8,	/* status port */
+	Dma1reset=	Dma1+2*0xD,	/* reset port */
+};
+
+/*
+ *  state of a dma transfer
+ */
+struct DMAxfer
+{
+	ulong	bpa;		/* bounce buffer physical address */
+	void*	bva;		/* bounce buffer virtual address */
+	void*	va;		/* virtual address destination/src */
+	long	len;		/* bytes to be transferred */
+	int	isread;
+};
+
+/*
+ *  the dma controllers.  the first half of this structure specifies
+ *  the I/O ports used by the DMA controllers.
+ */
+struct DMAport
+{
+	uchar	addr[4];	/* current address (4 channels) */
+	uchar	count[4];	/* current count (4 channels) */
+	uchar	page[4];	/* page registers (4 channels) */
+	uchar	cmd;		/* command status register */
+	uchar	req;		/* request registers */
+	uchar	sbm;		/* single bit mask register */
+	uchar	mode;		/* mode register */
+	uchar	cbp;		/* clear byte pointer */
+	uchar	mc;		/* master clear */
+	uchar	cmask;		/* clear mask register */
+	uchar	wam;		/* write all mask register bit */
+};
+
+struct DMA
+{
+	DMAport;
+	int	shift;
+	Lock;
+	DMAxfer	x[4];
+};
+
+DMA dma[2] = {
+	{ 0x00, 0x02, 0x04, 0x06,
+	  0x01, 0x03, 0x05, 0x07,
+	  0x87, 0x83, 0x81, 0x82,
+	  0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+	 0 },
+
+	{ 0xc0, 0xc4, 0xc8, 0xcc,
+	  0xc2, 0xc6, 0xca, 0xce,
+	  0x8f, 0x8b, 0x89, 0x8a,
+	  0xd0, 0xd2, 0xd4, 0xd6, 0xd8, 0xda, 0xdc, 0xde,
+	 1 },
+};
+
+/*
+ *  DMA must be in the first 16MB.  This gets called early by the
+ *  initialisation routines of any devices which require DMA to ensure
+ *  the allocated bounce buffers are below the 16MB limit.
+ */
+void
+dmainit(int chan)
+{
+	DMA *dp;
+	DMAxfer *xp;
+	ulong v;
+	static int once;
+
+	if(once == 0){
+//		if(ioalloc(0x00, 0x10, 0, "dma") < 0
+//		|| ioalloc(0x80, 0x10, 0, "dma") < 0
+//		|| ioalloc(0xd0, 0x10, 0, "dma") < 0)
+//			panic("dmainit");
+		outb(dma[0].mc, 0);
+		outb(dma[1].mc, 0);
+		outb(dma[0].cmask, 0);
+		outb(dma[1].cmask, 0);
+		outb(dma[1].mode, 0xC0);
+		once = 1;
+	}
+
+	dp = &dma[(chan>>2)&1];
+	chan = chan & 3;
+	xp = &dp->x[chan];
+	if(xp->bva != nil)
+		return;
+
+	v = (ulong)xalloc(BY2PG+BY2PG);
+	if(v == 0 || PADDR(v) >= 16*MB){
+		print("dmainit: chan %d: 0x%luX out of range\n", chan, v);
+		xfree((void*)v);
+		v = 0;
+	}
+	xp->bva = (void*)ROUND(v, BY2PG);
+	xp->bpa = PADDR(xp->bva);
+	xp->len = 0;
+	xp->isread = 0;
+}
+
+/*
+ *  setup a dma transfer.  if the destination is not in kernel
+ *  memory, allocate a page for the transfer.
+ *
+ *  we assume BIOS has set up the command register before we
+ *  are booted.
+ *
+ *  return the updated transfer length (we can't transfer across 64k
+ *  boundaries)
+ */
+long
+dmasetup(int chan, void *va, long len, int isread)
+{
+	DMA *dp;
+	ulong pa;
+	uchar mode;
+	DMAxfer *xp;
+
+	dp = &dma[(chan>>2)&1];
+	chan = chan & 3;
+	xp = &dp->x[chan];
+
+	/*
+	 *  if this isn't kernel memory or crossing 64k boundary or above 16 meg
+	 *  use the allocated low memory page.
+	 */
+	pa = PADDR(va);
+	if((((ulong)va)&0xF0000000) != KZERO
+	|| (pa&0xFFFF0000) != ((pa+len)&0xFFFF0000)
+	|| pa > 16*MB) {
+		if(xp->bva == nil)
+			return -1;
+		if(len > BY2PG)
+			len = BY2PG;
+		if(!isread)
+			memmove(xp->bva, va, len);
+		xp->va = va;
+		xp->len = len;
+		xp->isread = isread;
+		pa = xp->bpa;
+	}
+	else
+		xp->len = 0;
+
+	/*
+	 * this setup must be atomic
+	 */
+	ilock(dp);
+	mode = (isread ? 0x44 : 0x48) | chan;
+	outb(dp->mode, mode);	/* single mode dma (give CPU a chance at mem) */
+	outb(dp->page[chan], pa>>16);
+	outb(dp->cbp, 0);		/* set count & address to their first byte */
+	outb(dp->addr[chan], pa>>dp->shift);		/* set address */
+	outb(dp->addr[chan], pa>>(8+dp->shift));
+	outb(dp->count[chan], (len>>dp->shift)-1);		/* set count */
+	outb(dp->count[chan], ((len>>dp->shift)-1)>>8);
+	outb(dp->sbm, chan);		/* enable the channel */
+	iunlock(dp);
+
+	return len;
+}
+
+int
+dmadone(int chan)
+{
+	DMA *dp;
+
+	dp = &dma[(chan>>2)&1];
+	chan = chan & 3;
+
+	return inb(dp->cmd) & (1<<chan);
+}
+
+/*
+ *  this must be called after a dma has been completed.
+ *
+ *  if a page has been allocated for the dma,
+ *  copy the data into the actual destination
+ *  and free the page.
+ */
+void
+dmaend(int chan)
+{
+	DMA *dp;
+	DMAxfer *xp;
+
+	dp = &dma[(chan>>2)&1];
+	chan = chan & 3;
+
+	/*
+	 *  disable the channel
+	 */
+	ilock(dp);
+	outb(dp->sbm, 4|chan);
+	iunlock(dp);
+
+	xp = &dp->x[chan];
+	if(xp->len == 0 || !xp->isread)
+		return;
+
+	/*
+	 *  copy out of temporary page
+	 */
+	memmove(xp->va, xp->bva, xp->len);
+	xp->len = 0;
+}
+
+/*
+int
+dmacount(int chan)
+{
+	int     retval;
+	DMA     *dp;
+ 
+	dp = &dma[(chan>>2)&1];
+	outb(dp->cbp, 0);
+	retval = inb(dp->count[chan]);
+	retval |= inb(dp->count[chan]) << 8;
+	return((retval<<dp->shift)+1);
+}
+ */
--- /dev/null
+++ b/os/boot.original/pc/dosboot.c
@@ -1,0 +1,582 @@
+#include	"u.h"
+#include	"lib.h"
+#include	"mem.h"
+#include	"dat.h"
+#include	"fns.h"
+#include	"fs.h"
+
+struct Dosboot{
+	uchar	magic[3];
+	uchar	version[8];
+	uchar	sectsize[2];
+	uchar	clustsize;
+	uchar	nresrv[2];
+	uchar	nfats;
+	uchar	rootsize[2];
+	uchar	volsize[2];
+	uchar	mediadesc;
+	uchar	fatsize[2];
+	uchar	trksize[2];
+	uchar	nheads[2];
+	uchar	nhidden[4];
+	uchar	bigvolsize[4];
+/* fat 32 */
+	uchar	bigfatsize[4];
+	uchar	extflags[2];
+	uchar	fsversion[2];
+	uchar	rootdirstartclust[4];
+	uchar	fsinfosect[2];
+	uchar	backupbootsect[2];
+/* ???
+	uchar	driveno;
+	uchar	reserved0;
+	uchar	bootsig;
+	uchar	volid[4];
+	uchar	label[11];
+	uchar	reserved1[8];
+*/
+};
+
+struct Dosdir{
+	uchar	name[8];
+	uchar	ext[3];
+	uchar	attr;
+	uchar	lowercase;
+	uchar	hundredth;
+	uchar	ctime[2];
+	uchar	cdate[2];
+	uchar	adate[2];
+	uchar	highstart[2];
+	uchar	mtime[2];
+	uchar	mdate[2];
+	uchar	start[2];
+	uchar	length[4];
+};
+
+#define	DOSRONLY	0x01
+#define	DOSHIDDEN	0x02
+#define	DOSSYSTEM	0x04
+#define	DOSVLABEL	0x08
+#define	DOSDIR	0x10
+#define	DOSARCH	0x20
+
+/*
+ *  predeclared
+ */
+static void	bootdump(Dosboot*);
+static void	setname(Dosfile*, char*);
+
+/*
+ *  debugging
+ */
+#define chatty	0
+#define chat	if(chatty)print
+
+/*
+ *  block io buffers
+ */
+enum
+{
+	Nbio=	16,
+};
+typedef struct	Clustbuf	Clustbuf;
+struct Clustbuf
+{
+	int	age;
+	long	sector;
+	uchar	*iobuf;
+	Dos	*dos;
+	int	size;
+};
+Clustbuf	bio[Nbio];
+
+/*
+ *  get an io block from an io buffer
+ */
+Clustbuf*
+getclust(Dos *dos, long sector)
+{
+	Fs *fs;
+	Clustbuf *p, *oldest;
+	int size;
+
+	chat("getclust @ %ld\n", sector);
+
+	/*
+	 *  if we have it, just return it
+	 */
+	for(p = bio; p < &bio[Nbio]; p++){
+		if(sector == p->sector && dos == p->dos){
+			p->age = m->ticks;
+			chat("getclust %ld in cache\n", sector);
+			return p;
+		}
+	}
+
+	/*
+	 *  otherwise, reuse the oldest entry
+	 */
+	oldest = bio;
+	for(p = &bio[1]; p < &bio[Nbio]; p++){
+		if(p->age <= oldest->age)
+			oldest = p;
+	}
+	p = oldest;
+
+	/*
+	 *  make sure the buffer is big enough
+	 */
+	size = dos->clustsize*dos->sectsize;
+	if(p->iobuf==0 || p->size < size)
+		p->iobuf = ialloc(size, 0);
+	p->size = size;
+
+	/*
+	 *  read in the cluster
+	 */
+	fs = (Fs*)dos;
+	chat("getclust addr %lud %p %p %p\n", (ulong)((sector+dos->start)*(vlong)dos->sectsize),
+		fs, fs->diskseek, fs->diskread);
+	if(fs->diskseek(fs, (sector+dos->start)*(vlong)dos->sectsize) < 0){
+		chat("can't seek block\n");
+		return 0;
+	}
+	if(fs->diskread(fs, p->iobuf, size) != size){
+		chat("can't read block\n");
+		return 0;
+	}
+
+	p->age = m->ticks;
+	p->dos = dos;
+	p->sector = sector;
+	chat("getclust %ld read\n", sector);
+	return p;
+}
+
+/*
+ *  walk the fat one level ( n is a current cluster number ).
+ *  return the new cluster number or -1 if no more.
+ */
+static long
+fatwalk(Dos *dos, int n)
+{
+	ulong k, sect;
+	Clustbuf *p;
+	int o;
+
+	chat("fatwalk %d\n", n);
+
+	if(n < 2 || n >= dos->fatclusters)
+		return -1;
+
+	switch(dos->fatbits){
+	case 12:
+		k = (3*n)/2; break;
+	case 16:
+		k = 2*n; break;
+	case 32:
+		k = 4*n; break;
+	default:
+		return -1;
+	}
+	if(k >= dos->fatsize*dos->sectsize)
+		panic("getfat");
+
+	sect = (k/(dos->sectsize*dos->clustsize))*dos->clustsize + dos->fataddr;
+	o = k%(dos->sectsize*dos->clustsize);
+	p = getclust(dos, sect);
+	k = p->iobuf[o++];
+	if(o >= dos->sectsize*dos->clustsize){
+		p = getclust(dos, sect+dos->clustsize);
+		o = 0;
+	}
+	k |= p->iobuf[o++]<<8;
+	if(dos->fatbits == 12){
+		if(n&1)
+			k >>= 4;
+		else
+			k &= 0xfff;
+		if(k >= 0xff8)
+			k = -1;
+	}
+	else if (dos->fatbits == 32){
+		if(o >= dos->sectsize*dos->clustsize){
+			p = getclust(dos, sect+dos->clustsize);
+			o = 0;
+		}
+		k |= p->iobuf[o++]<<16;
+		k |= p->iobuf[o]<<24;
+		if (k >= 0xfffffff8)
+			k = -1;
+	}
+	else
+		k = k < 0xfff8 ? k : -1;
+	chat("fatwalk %d -> %lud\n", n, k);
+	return k;
+}
+
+/*
+ *  map a file's logical cluster address to a physical sector address
+ */
+static long
+fileaddr(Dosfile *fp, long ltarget)
+{
+	Dos *dos = fp->dos;
+	long l;
+	long p;
+
+	chat("fileaddr %8.8s %ld\n", fp->name, ltarget);
+	/*
+	 *  root directory is contiguous and easy (unless FAT32)
+	 */
+	if(fp->pstart == 0 && dos->rootsize != 0) {
+		if(ltarget*dos->sectsize*dos->clustsize >= dos->rootsize*sizeof(Dosdir))
+			return -1;
+		l = dos->rootaddr + ltarget*dos->clustsize;
+		chat("fileaddr %ld -> %ld\n", ltarget, l);
+		return l;
+	}
+
+	/*
+	 *  anything else requires a walk through the fat
+	 */
+	if(ltarget >= fp->lcurrent && fp->pcurrent){
+		/* start at the currrent point */
+		l = fp->lcurrent;
+		p = fp->pcurrent;
+	} else {
+		/* go back to the beginning */
+		l = 0;
+		p = fp->pstart;
+	}
+	while(l != ltarget){
+		/* walk the fat */
+		p = fatwalk(dos, p);
+		if(p < 0)
+			return -1;
+		l++;
+	}
+	fp->lcurrent = l;
+	fp->pcurrent = p;
+
+	/*
+	 *  clusters start at 2 instead of 0 (why? - presotto)
+	 */
+	l =  dos->dataaddr + (p-2)*dos->clustsize;
+	chat("fileaddr %ld -> %ld\n", ltarget, l);
+	return l;
+}
+
+/*
+ *  read from a dos file
+ */
+long
+dosread(Dosfile *fp, void *a, long n)
+{
+	long addr;
+	long rv;
+	int i;
+	int off;
+	Clustbuf *p;
+	uchar *from, *to;
+
+	if((fp->attr & DOSDIR) == 0){
+		if(fp->offset >= fp->length)
+			return 0;
+		if(fp->offset+n > fp->length)
+			n = fp->length - fp->offset;
+	}
+
+	to = a;
+	for(rv = 0; rv < n; rv+=i){
+		/*
+		 *  read the cluster
+		 */
+		addr = fileaddr(fp, fp->offset/fp->dos->clustbytes);
+		if(addr < 0)
+			return -1;
+		p = getclust(fp->dos, addr);
+		if(p == 0)
+			return -1;
+
+		/*
+		 *  copy the bytes we need
+		 */
+		off = fp->offset % fp->dos->clustbytes;
+		from = &p->iobuf[off];
+		i = n - rv;
+		if(i > fp->dos->clustbytes - off)
+			i = fp->dos->clustbytes - off;
+		memmove(to, from, i);
+		to += i;
+		fp->offset += i;
+	}
+
+	return rv;
+}
+
+/*
+ *  walk a directory returns
+ * 	-1 if something went wrong
+ *	 0 if not found
+ *	 1 if found
+ */
+int
+doswalk(File *f, char *name)
+{
+	Dosdir d;
+	long n;
+	Dosfile *file;
+
+	chat("doswalk %s\n", name);
+
+	file = &f->dos;
+
+	if((file->attr & DOSDIR) == 0){
+		chat("walking non-directory!\n");
+		return -1;
+	}
+
+	setname(file, name);
+
+	file->offset = 0;	/* start at the beginning */
+	while((n = dosread(file, &d, sizeof(d))) == sizeof(d)){
+		chat("comparing to %8.8s.%3.3s\n", (char*)d.name, (char*)d.ext);
+		if(memcmp(file->name, d.name, sizeof(d.name)) != 0)
+			continue;
+		if(memcmp(file->ext, d.ext, sizeof(d.ext)) != 0)
+			continue;
+		if(d.attr & DOSVLABEL){
+			chat("%8.8s.%3.3s is a LABEL\n", (char*)d.name, (char*)d.ext);
+			continue;
+		}
+		file->attr = d.attr;
+		file->pstart = GSHORT(d.start);
+		if (file->dos->fatbits == 32)
+			file->pstart |= GSHORT(d.highstart) << 16;
+		file->length = GLONG(d.length);
+		file->pcurrent = 0;
+		file->lcurrent = 0;
+		file->offset = 0;
+		return 1;
+	}
+	return n >= 0 ? 0 : -1;
+}
+
+/*
+ *  instructions that boot blocks can start with
+ */
+#define	JMPSHORT	0xeb
+#define JMPNEAR		0xe9
+
+/*
+ *  read in a segment
+ */
+long
+dosreadseg(File *f, void *va, long len)
+{
+	char *a;
+	long n, sofar;
+	Dosfile *fp;
+
+	fp = &f->dos;
+	a = va;
+	for(sofar = 0; sofar < len; sofar += n){
+		n = 8*1024;
+		if(len - sofar < n)
+			n = len - sofar;
+		n = dosread(fp, a + sofar, n);
+		if(n <= 0)
+			break;
+		print(".");
+	}
+	return sofar;
+}
+
+int
+dosinit(Fs *fs)
+{
+	Clustbuf *p;
+	Dosboot *b;
+	int i;
+	Dos *dos;
+	Dosfile *root;
+
+chat("dosinit0 %p %p %p\n", fs, fs->diskseek, fs->diskread);
+
+	dos = &fs->dos;
+	/* defaults till we know better */
+	dos->sectsize = 512;
+	dos->clustsize = 1;
+
+	/* get first sector */
+	p = getclust(dos, 0);
+	if(p == 0){
+		chat("can't read boot block\n");
+		return -1;
+	}
+
+chat("dosinit0a\n");
+
+	p->dos = 0;
+	b = (Dosboot *)p->iobuf;
+	if(b->magic[0] != JMPNEAR && (b->magic[0] != JMPSHORT || b->magic[2] != 0x90)){
+		chat("no dos file system %x %x %x %x\n",
+			b->magic[0], b->magic[1], b->magic[2], b->magic[3]);
+		return -1;
+	}
+
+	if(chatty)
+		bootdump(b);
+
+	if(b->clustsize == 0) {
+unreasonable:
+		if(chatty){
+			print("unreasonable FAT BPB: ");
+			for(i=0; i<3+8+2+1; i++)
+				print(" %.2ux", p->iobuf[i]);
+			print("\n");
+		}
+		return -1;
+	}
+
+chat("dosinit1\n");
+
+	/*
+	 * Determine the systems' wondrous properties.
+	 * There are heuristics here, but there's no real way
+	 * of knowing if this is a reasonable FAT.
+	 */
+	dos->fatbits = 0;
+	dos->sectsize = GSHORT(b->sectsize);
+	if(dos->sectsize & 0xFF)
+		goto unreasonable;
+	dos->clustsize = b->clustsize;
+	dos->clustbytes = dos->sectsize*dos->clustsize;
+	dos->nresrv = GSHORT(b->nresrv);
+	dos->nfats = b->nfats;
+	dos->fatsize = GSHORT(b->fatsize);
+	dos->rootsize = GSHORT(b->rootsize);
+	dos->volsize = GSHORT(b->volsize);
+	if(dos->volsize == 0)
+		dos->volsize = GLONG(b->bigvolsize);
+	dos->mediadesc = b->mediadesc;
+	if(dos->fatsize == 0) {
+		chat("fat32\n");
+		dos->rootsize = 0;
+		dos->fatsize = GLONG(b->bigfatsize);
+		dos->fatbits = 32;
+	}
+	dos->fataddr = dos->nresrv;
+	if (dos->rootsize == 0) {
+		dos->rootaddr = 0;
+		dos->rootclust = GLONG(b->rootdirstartclust);
+		dos->dataaddr = dos->fataddr + dos->nfats*dos->fatsize;
+	} else {
+		dos->rootaddr = dos->fataddr + dos->nfats*dos->fatsize;
+		i = dos->rootsize*sizeof(Dosdir) + dos->sectsize - 1;
+		i = i/dos->sectsize;
+		dos->dataaddr = dos->rootaddr + i;
+	}
+	dos->fatclusters = 2+(dos->volsize - dos->dataaddr)/dos->clustsize;
+	if(dos->fatbits != 32) {
+		if(dos->fatclusters < 4087)
+			dos->fatbits = 12;
+		else
+			dos->fatbits = 16;
+	}
+	dos->freeptr = 2;
+
+	if(dos->clustbytes < 512 || dos->clustbytes > 64*1024)
+		goto unreasonable;
+
+chat("dosinit2\n");
+
+	/*
+	 *  set up the root
+	 */
+
+	fs->root.fs = fs;
+	root = &fs->root.dos;
+	root->dos = dos;
+	root->pstart = dos->rootsize == 0 ? dos->rootclust : 0;
+	root->pcurrent = root->lcurrent = 0;
+	root->offset = 0;
+	root->attr = DOSDIR;
+	root->length = dos->rootsize*sizeof(Dosdir);
+
+chat("dosinit3\n");
+
+	fs->read = dosreadseg;
+	fs->walk = doswalk;
+	return 0;
+}
+
+static void
+bootdump(Dosboot *b)
+{
+	if(chatty == 0)
+		return;
+	print("magic: 0x%2.2x 0x%2.2x 0x%2.2x ",
+		b->magic[0], b->magic[1], b->magic[2]);
+	print("version: \"%8.8s\"\n", (char*)b->version);
+	print("sectsize: %d ", GSHORT(b->sectsize));
+	print("allocsize: %d ", b->clustsize);
+	print("nresrv: %d ", GSHORT(b->nresrv));
+	print("nfats: %d\n", b->nfats);
+	print("rootsize: %d ", GSHORT(b->rootsize));
+	print("volsize: %d ", GSHORT(b->volsize));
+	print("mediadesc: 0x%2.2x\n", b->mediadesc);
+	print("fatsize: %d ", GSHORT(b->fatsize));
+	print("trksize: %d ", GSHORT(b->trksize));
+	print("nheads: %d ", GSHORT(b->nheads));
+	print("nhidden: %d ", GLONG(b->nhidden));
+	print("bigvolsize: %d\n", GLONG(b->bigvolsize));
+/*
+	print("driveno: %d\n", b->driveno);
+	print("reserved0: 0x%2.2x\n", b->reserved0);
+	print("bootsig: 0x%2.2x\n", b->bootsig);
+	print("volid: 0x%8.8x\n", GLONG(b->volid));
+	print("label: \"%11.11s\"\n", b->label);
+*/
+}
+
+
+/*
+ *  set up a dos file name
+ */
+static void
+setname(Dosfile *fp, char *from)
+{
+	char *to;
+
+	to = fp->name;
+	for(; *from && to-fp->name < 8; from++, to++){
+		if(*from == '.'){
+			from++;
+			break;
+		}
+		if(*from >= 'a' && *from <= 'z')
+			*to = *from + 'A' - 'a';
+		else
+			*to = *from;
+	}
+	while(to - fp->name < 8)
+		*to++ = ' ';
+	
+	/* from might be 12345678.123: don't save the '.' in ext */
+	if(*from == '.')
+		from++;
+
+	to = fp->ext;
+	for(; *from && to-fp->ext < 3; from++, to++){
+		if(*from >= 'a' && *from <= 'z')
+			*to = *from + 'A' - 'a';
+		else
+			*to = *from;
+	}
+	while(to-fp->ext < 3)
+		*to++ = ' ';
+
+	chat("name is %8.8s.%3.3s\n", fp->name, fp->ext);
+}
--- /dev/null
+++ b/os/boot.original/pc/dosfs.h
@@ -1,0 +1,62 @@
+typedef struct Dosboot	Dosboot;
+typedef struct Dos	Dos;
+typedef struct Dosdir	Dosdir;
+typedef struct Dosfile	Dosfile;
+typedef struct Dospart	Dospart;
+
+struct Dospart
+{
+	uchar flag;		/* active flag */
+	uchar shead;		/* starting head */
+	uchar scs[2];		/* starting cylinder/sector */
+	uchar type;		/* partition type */
+	uchar ehead;		/* ending head */
+	uchar ecs[2];		/* ending cylinder/sector */
+	uchar start[4];		/* starting sector */
+	uchar len[4];		/* length in sectors */
+};
+
+#define FAT12	0x01
+#define FAT16	0x04
+#define EXTEND	0x05
+#define FATHUGE	0x06
+#define FAT32	0x0b
+#define FAT32X	0x0c
+#define EXTHUGE	0x0f
+#define DMDDO	0x54
+#define PLAN9	0x39
+#define LEXTEND 0x85
+
+struct Dosfile{
+	Dos	*dos;		/* owning dos file system */
+	char	name[8];
+	char	ext[3];
+	uchar	attr;
+	long	length;
+	long	pstart;		/* physical start cluster address */
+	long	pcurrent;	/* physical current cluster address */
+	long	lcurrent;	/* logical current cluster address */
+	long	offset;
+};
+
+struct Dos{
+	long	start;		/* start of file system */
+	int	sectsize;	/* in bytes */
+	int	clustsize;	/* in sectors */
+	int	clustbytes;	/* in bytes */
+	int	nresrv;		/* sectors */
+	int	nfats;		/* usually 2 */
+	int	rootsize;	/* number of entries */
+	int	volsize;	/* in sectors */
+	int	mediadesc;
+	int	fatsize;	/* in sectors */
+	int	fatclusters;
+	int	fatbits;	/* 12 or 16 */
+	long	fataddr;	/* sector number */
+	long	rootaddr;
+	long	rootclust;
+	long	dataaddr;
+	long	freeptr;
+};
+
+extern int	dosinit(Fs*);
--- /dev/null
+++ b/os/boot.original/pc/eipfmt.c
@@ -1,0 +1,145 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "ip.h"
+
+
+enum 
+{
+	IPaddrlen=	16,
+	IPv4addrlen=	4,
+	IPv4off=	12,
+	IPllen=		4,
+};
+extern	int	fmtstrcpy(Fmt*, char*);
+
+
+/*
+ *  prefix of all v4 addresses
+ */
+uchar v4prefix[IPaddrlen] = {
+	0, 0, 0, 0,
+	0, 0, 0, 0,
+	0, 0, 0xff, 0xff,
+	0, 0, 0, 0
+};
+
+enum
+{
+	Isprefix= 16,
+};
+
+uchar prefixvals[256] =
+{
+[0x00] 0 | Isprefix,
+[0x80] 1 | Isprefix,
+[0xC0] 2 | Isprefix,
+[0xE0] 3 | Isprefix,
+[0xF0] 4 | Isprefix,
+[0xF8] 5 | Isprefix,
+[0xFC] 6 | Isprefix,
+[0xFE] 7 | Isprefix,
+[0xFF] 8 | Isprefix,
+};
+
+void
+hnputl(void *p, uint v)
+{
+	uchar *a;
+
+	a = p;
+	a[0] = v>>24;
+	a[1] = v>>16;
+	a[2] = v>>8;
+	a[3] = v;
+}
+
+int
+eipfmt(Fmt *f)
+{
+	char buf[5*8];
+	static char *efmt = "%.2lux%.2lux%.2lux%.2lux%.2lux%.2lux";
+	static char *ifmt = "%d.%d.%d.%d";
+	uchar *p, ip[16];
+	ulong *lp;
+	ushort s;
+	int i, j, n, eln, eli;
+
+	switch(f->r) {
+	case 'E':		/* Ethernet address */
+		p = va_arg(f->args, uchar*);
+		snprint(buf, sizeof buf, efmt, p[0], p[1], p[2], p[3], p[4], p[5]);
+		return fmtstrcpy(f, buf);
+
+	case 'I':		/* Ip address */
+		p = va_arg(f->args, uchar*);
+common:
+		if(memcmp(p, v4prefix, 12) == 0){
+			snprint(buf, sizeof buf, ifmt, p[12], p[13], p[14], p[15]);
+			return fmtstrcpy(f, buf);
+		}
+
+		/* find longest elision */
+		eln = eli = -1;
+		for(i = 0; i < 16; i += 2){
+			for(j = i; j < 16; j += 2)
+				if(p[j] != 0 || p[j+1] != 0)
+					break;
+			if(j > i && j - i > eln){
+				eli = i;
+				eln = j - i;
+			}
+		}
+
+		/* print with possible elision */
+		n = 0;
+		for(i = 0; i < 16; i += 2){
+			if(i == eli){
+				n += sprint(buf+n, "::");
+				i += eln;
+				if(i >= 16)
+					break;
+			} else if(i != 0)
+				n += sprint(buf+n, ":");
+			s = (p[i]<<8) + p[i+1];
+			n += sprint(buf+n, "%ux", s);
+		}
+		return fmtstrcpy(f, buf);
+
+	case 'i':		/* v6 address as 4 longs */
+		lp = va_arg(f->args, ulong*);
+		for(i = 0; i < 4; i++)
+			hnputl(ip+4*i, *lp++);
+		p = ip;
+		goto common;
+
+	case 'V':		/* v4 ip address */
+		p = va_arg(f->args, uchar*);
+		snprint(buf, sizeof buf, ifmt, p[0], p[1], p[2], p[3]);
+		return fmtstrcpy(f, buf);
+
+	case 'M':		/* ip mask */
+		p = va_arg(f->args, uchar*);
+
+		/* look for a prefix mask */
+		for(i = 0; i < 16; i++)
+			if(p[i] != 0xff)
+				break;
+		if(i < 16){
+			if((prefixvals[p[i]] & Isprefix) == 0)
+				goto common;
+			for(j = i+1; j < 16; j++)
+				if(p[j] != 0)
+					goto common;
+			n = 8*i + (prefixvals[p[i]] & ~Isprefix);
+		} else
+			n = 8*16;
+
+		/* got one, use /xx format */
+		snprint(buf, sizeof buf, "/%d", n);
+		return fmtstrcpy(f, buf);
+	}
+	return fmtstrcpy(f, "(eipfmt)");
+}
--- /dev/null
+++ b/os/boot.original/pc/error.h
@@ -1,0 +1,58 @@
+extern char Enoerror[];		/* no error */
+extern char Emount[];		/* inconsistent mount */
+extern char Eunmount[];		/* not mounted */
+extern char Eunion[];		/* not in union */
+extern char Emountrpc[];	/* mount rpc error */
+extern char Eshutdown[];	/* mounted device shut down */
+extern char Enocreate[];	/* mounted directory forbids creation */
+extern char Enonexist[];	/* file does not exist */
+extern char Eexist[];		/* file already exists */
+extern char Ebadsharp[];	/* unknown device in # filename */
+extern char Enotdir[];		/* not a directory */
+extern char Eisdir[];		/* file is a directory */
+extern char Ebadchar[];		/* bad character in file name */
+extern char Efilename[];	/* file name syntax */
+extern char Eperm[];		/* permission denied */
+extern char Ebadusefd[];	/* inappropriate use of fd */
+extern char Ebadarg[];		/* bad arg in system call */
+extern char Einuse[];		/* device or object already in use */
+extern char Eio[];		/* i/o error */
+extern char Etoobig[];		/* read or write too large */
+extern char Etoosmall[];	/* read or write too small */
+extern char Enetaddr[];		/* bad network address */
+extern char Emsgsize[];		/* message is too big for protocol */
+extern char Enetbusy[];		/* network device is busy or allocated */
+extern char Enoproto[];		/* network protocol not supported */
+extern char Enoport[];		/* network port not available */
+extern char Enoifc[];		/* bad interface or no free interface slots */
+extern char Enolisten[];	/* not announced */
+extern char Ehungup[];		/* write to hungup channel */
+extern char Ebadctl[];		/* bad process or channel control request */
+extern char Enodev[];		/* no free devices */
+extern char Enoenv[];		/* no free environment resources */
+extern char Emuxshutdown[];	/* mux server shut down */
+extern char Emuxbusy[];		/* all mux channels busy */
+extern char Emuxmsg[];		/* bad mux message format or mismatch */
+extern char Eprocdied[];	/* process exited */
+extern char Enochild[];		/* no living children */
+extern char Eioload[];		/* i/o error in demand load */
+extern char Enovmem[];		/* virtual memory allocation failed */
+extern char Ebadld[];		/* illegal line discipline */
+extern char Ebadfd[];		/* fd out of range or not open */
+extern char Eisstream[];	/* seek on a stream */
+extern char Ebadexec[];		/* exec header invalid */
+extern char Etimedout[];	/* connection timed out */
+extern char Econrefused[];	/* connection refused */
+extern char Enetunreach[];	/* network unreachable */
+extern char Eintr[];		/* interrupted */
+extern char Eneedservice[];	/* service required for tcp/udp/il calls */
+extern char Enomem[];		/* kernel allocate failed */
+extern char Enoswap[];		/* swap space full */
+extern char Esfnotcached[];	/* subfont not cached */
+extern char Esoverlap[];	/* segments overlap */
+extern char Emouseset[];	/* mouse type already set */
+extern char Erecover[];		/* failed to recover fd */
+extern char Eshort[];		/* i/o count too small */
+extern char Egreg[];		/* ken scheduled it */
+extern char Ebadspec[];		/* bad attach specifier */
+extern char Enoreg[];		/* process has no saved registers */
--- /dev/null
+++ b/os/boot.original/pc/ether.c
@@ -1,0 +1,291 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "ip.h"
+
+#include "etherif.h"
+
+static Ether ether[MaxEther];
+
+extern int ether2114xreset(Ether*);
+extern int elnk3reset(Ether*);
+extern int i82557reset(Ether*);
+extern int igbepnp(Ether *);
+extern int i82563pnp(Ether *);
+extern int elnk3reset(Ether*);
+extern int ether589reset(Ether*);
+extern int ne2000reset(Ether*);
+extern int wd8003reset(Ether*);
+extern int ec2treset(Ether*);
+extern int amd79c970reset(Ether*);
+extern int rtl8139pnp(Ether*);
+extern int rtl8169pnp(Ether*);
+extern int ether83815reset(Ether*);
+extern int rhinepnp(Ether*);
+extern int ga620pnp(Ether*);
+extern int dp83820pnp(Ether*);
+
+struct {
+	char	*type;
+	int	(*reset)(Ether*);
+	int	noprobe;
+} ethercards[] = {
+	{ "21140", ether2114xreset, 0, },
+	{ "2114x", ether2114xreset, 0, },
+	{ "i82557", i82557reset, 0, },
+	{ "igbe",  igbepnp, 0, },
+	{ "i82563",i82563pnp, 0, },
+	{ "igbepcie",i82563pnp, 0, },
+	{ "elnk3", elnk3reset, 0, },
+	{ "3C509", elnk3reset, 0, },
+	{ "3C575", elnk3reset, 0, },
+	{ "3C589", ether589reset, 1, },
+	{ "3C562", ether589reset, 1, },
+	{ "589E", ether589reset, 1, },
+	{ "NE2000", ne2000reset, 0, },
+	{ "WD8003", wd8003reset, 1, },
+	{ "EC2T", ec2treset, 0, },
+	{ "AMD79C970", amd79c970reset, 0, },
+	{ "RTL8139", rtl8139pnp, 0, },
+	{ "RTL8169", rtl8169pnp, 0, },
+	{ "83815", ether83815reset, 0, },
+	{ "rhine", rhinepnp, 0, },
+	{ "vt6102", rhinepnp, 0, },
+	{ "GA620", ga620pnp, 0, },
+	{ "83820",   dp83820pnp, 0, },
+	{ "dp83820", dp83820pnp, 0, },
+
+	{ 0, }
+};
+
+static void xetherdetach(void);
+
+int
+etherinit(void)
+{
+	Ether *ctlr;
+	int ctlrno, i, mask, n, x;
+
+	fmtinstall('E', eipfmt);
+
+	etherdetach = xetherdetach;
+	mask = 0;
+	for(ctlrno = 0; ctlrno < MaxEther; ctlrno++){
+		ctlr = &ether[ctlrno];
+		memset(ctlr, 0, sizeof(Ether));
+		if(iniread && isaconfig("ether", ctlrno, ctlr) == 0)
+			continue;
+
+		for(n = 0; ethercards[n].type; n++){
+			if(!iniread){
+				if(ethercards[n].noprobe)
+					continue;
+				memset(ctlr, 0, sizeof(Ether));
+				strcpy(ctlr->type, ethercards[n].type);
+			}
+			else if(cistrcmp(ethercards[n].type, ctlr->type))
+				continue;
+			ctlr->ctlrno = ctlrno;
+
+			x = splhi();
+			if((*ethercards[n].reset)(ctlr)){
+				splx(x);
+				if(iniread)
+					break;
+				else
+					continue;
+			}
+
+			ctlr->state = 1;		/* card found */
+			mask |= 1<<ctlrno;
+			if(ctlr->irq == 2)
+				ctlr->irq = 9;
+			setvec(VectorPIC + ctlr->irq, ctlr->interrupt, ctlr);
+
+			print("ether#%d: %s: port 0x%luX irq %lud",
+				ctlr->ctlrno, ctlr->type, ctlr->port, ctlr->irq);
+			if(ctlr->mem)
+				print(" addr 0x%luX", ctlr->mem & ~KZERO);
+			if(ctlr->size)
+				print(" size 0x%luX", ctlr->size);
+			print(": %E\n", ctlr->ea);
+		
+			if(ctlr->nrb == 0)
+				ctlr->nrb = Nrb;
+			ctlr->rb = ialloc(sizeof(RingBuf)*ctlr->nrb, 0);
+			if(ctlr->ntb == 0)
+				ctlr->ntb = Ntb;
+			ctlr->tb = ialloc(sizeof(RingBuf)*ctlr->ntb, 0);
+
+			ctlr->rh = 0;
+			ctlr->ri = 0;
+			for(i = 0; i < ctlr->nrb; i++)
+				ctlr->rb[i].owner = Interface;
+		
+			ctlr->th = 0;
+			ctlr->ti = 0;
+			for(i = 0; i < ctlr->ntb; i++)
+				ctlr->tb[i].owner = Host;
+
+			splx(x);
+			break;
+		}
+	}
+
+	return mask;
+}
+
+void
+etherinitdev(int i, char *s)
+{
+	sprint(s, "ether%d", i);
+}
+
+void
+etherprintdevs(int i)
+{
+	print(" ether%d", i);
+}
+
+static Ether*
+attach(int ctlrno)
+{
+	Ether *ctlr;
+
+	if(ctlrno >= MaxEther || ether[ctlrno].state == 0)
+		return 0;
+
+	ctlr = &ether[ctlrno];
+	if(ctlr->state == 1){		/* card found? */
+		ctlr->state = 2;	/* attaching */
+		(*ctlr->attach)(ctlr);
+	}
+
+	return ctlr;
+}
+
+static void
+xetherdetach(void)
+{
+	Ether *ctlr;
+	int ctlrno, x;
+
+	x = splhi();
+	for(ctlrno = 0; ctlrno < MaxEther; ctlrno++){
+		ctlr = &ether[ctlrno];
+		if(ctlr->detach && ctlr->state != 0)	/* found | attaching? */
+			ctlr->detach(ctlr);
+	}
+	splx(x);
+}
+
+uchar*
+etheraddr(int ctlrno)
+{
+	Ether *ctlr;
+
+	if((ctlr = attach(ctlrno)) == 0)
+		return 0;
+
+	return ctlr->ea;
+}
+
+static int
+wait(RingBuf* ring, uchar owner, int timo)
+{
+	ulong start;
+
+	start = m->ticks;
+	while(TK2MS(m->ticks - start) < timo){
+		if(ring->owner != owner)
+			return 1;
+	}
+
+	return 0;
+}
+
+int
+etherrxpkt(int ctlrno, Etherpkt* pkt, int timo)
+{
+	int n;
+	Ether *ctlr;
+	RingBuf *ring;
+
+	if((ctlr = attach(ctlrno)) == 0)
+		return 0;
+
+	ring = &ctlr->rb[ctlr->rh];
+	if(wait(ring, Interface, timo) == 0){
+		if(debug)
+			print("ether%d: rx timeout\n", ctlrno);
+		return 0;
+	}
+
+	n = ring->len;
+	memmove(pkt, ring->pkt, n);
+	ring->owner = Interface;
+	ctlr->rh = NEXT(ctlr->rh, ctlr->nrb);
+
+	return n;
+}
+
+int
+etherrxflush(int ctlrno)
+{
+	int n;
+	Ether *ctlr;
+	RingBuf *ring;
+
+	if((ctlr = attach(ctlrno)) == 0)
+		return 0;
+
+	n = 0;
+	for(;;){
+		ring = &ctlr->rb[ctlr->rh];
+		if(wait(ring, Interface, 100) == 0)
+			break;
+
+		ring->owner = Interface;
+		ctlr->rh = NEXT(ctlr->rh, ctlr->nrb);
+		n++;
+	}
+
+	return n;
+}
+
+int
+ethertxpkt(int ctlrno, Etherpkt* pkt, int len, int)
+{
+	Ether *ctlr;
+	RingBuf *ring;
+	int s;
+
+	if((ctlr = attach(ctlrno)) == 0)
+		return 0;
+
+	ring = &ctlr->tb[ctlr->th];
+	if(wait(ring, Interface, 1000) == 0){
+		print("ether%d: tx buffer timeout\n", ctlrno);
+		return 0;
+	}
+
+	memmove(pkt->s, ctlr->ea, Eaddrlen);
+	if(debug)
+		print("%E to %E...\n", pkt->s, pkt->d);
+	memmove(ring->pkt, pkt, len);
+	if(len < ETHERMINTU){
+		memset(ring->pkt+len, 0, ETHERMINTU-len);
+		len = ETHERMINTU;
+	}
+	ring->len = len;
+	ring->owner = Interface;
+	ctlr->th = NEXT(ctlr->th, ctlr->ntb);
+	s = splhi();
+	(*ctlr->transmit)(ctlr);
+	splx(s);
+
+	return 1;
+}
--- /dev/null
+++ b/os/boot.original/pc/ether2000.c
@@ -1,0 +1,110 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+#include "etherif.h"
+#include "ether8390.h"
+
+/*
+ * Driver written for the 'Notebook Computer Ethernet LAN Adapter',
+ * a plug-in to the bus-slot on the rear of the Gateway NOMAD 425DXL
+ * laptop. The manual says NE2000 compatible.
+ * The interface appears to be pretty well described in the National
+ * Semiconductor Local Area Network Databook (1992) as one of the
+ * AT evaluation cards.
+ *
+ * The NE2000 is really just a DP8390[12] plus a data port
+ * and a reset port.
+ */
+enum {
+	Data		= 0x10,		/* offset from I/O base of data port */
+	Reset		= 0x1F,		/* offset from I/O base of reset port */
+};
+
+int
+ne2000reset(Ether* ether)
+{
+	ushort buf[16];
+	ulong port;
+	Dp8390 *ctlr;
+	int i;
+	uchar ea[Eaddrlen];
+
+	/*
+	 * Set up the software configuration.
+	 * Use defaults for port, irq, mem and size
+	 * if not specified.
+	 */
+	if(ether->port == 0)
+		ether->port = 0x300;
+	if(ether->irq == 0)
+		ether->irq = 2;
+	if(ether->mem == 0)
+		ether->mem = 0x4000;
+	if(ether->size == 0)
+		ether->size = 16*1024;
+	port = ether->port;
+
+	ether->ctlr = malloc(sizeof(Dp8390));
+	ctlr = ether->ctlr;
+	ctlr->width = 2;
+	ctlr->ram = 0;
+
+	ctlr->port = port;
+	ctlr->data = port+Data;
+
+	ctlr->tstart = HOWMANY(ether->mem, Dp8390BufSz);
+	ctlr->pstart = ctlr->tstart + HOWMANY(sizeof(Etherpkt), Dp8390BufSz);
+	ctlr->pstop = ctlr->tstart + HOWMANY(ether->size, Dp8390BufSz);
+
+	ctlr->dummyrr = 1;
+	for(i = 0; i < ether->nopt; i++){
+		if(strcmp(ether->opt[i], "nodummyrr"))
+			continue;
+		ctlr->dummyrr = 0;
+		break;
+	}
+
+	/*
+	 * Reset the board. This is done by doing a read
+	 * followed by a write to the Reset address.
+	 */
+	buf[0] = inb(port+Reset);
+	delay(2);
+	outb(port+Reset, buf[0]);
+	delay(2);
+	
+	/*
+	 * Init the (possible) chip, then use the (possible)
+	 * chip to read the (possible) PROM for ethernet address
+	 * and a marker byte.
+	 * Could just look at the DP8390 command register after
+	 * initialisation has been tried, but that wouldn't be
+	 * enough, there are other ethernet boards which could
+	 * match.
+	 */
+	dp8390reset(ether);
+	memset(buf, 0, sizeof(buf));
+	dp8390read(ctlr, buf, 0, sizeof(buf));
+	if((buf[0x0E] & 0xFF) != 0x57 || (buf[0x0F] & 0xFF) != 0x57){
+		free(ether->ctlr);
+		return -1;
+	}
+
+	/*
+	 * Stupid machine. Shorts were asked for,
+	 * shorts were delivered, although the PROM is a byte array.
+	 * Set the ethernet address.
+	 */
+	memset(ea, 0, Eaddrlen);
+	if(memcmp(ea, ether->ea, Eaddrlen) == 0){
+		for(i = 0; i < sizeof(ether->ea); i++)
+			ether->ea[i] = buf[i];
+	}
+	dp8390setea(ether);
+
+	return 0;
+}
--- /dev/null
+++ b/os/boot.original/pc/ether2114x.c
@@ -1,0 +1,1652 @@
+/*
+ * Digital Semiconductor DECchip 21140 PCI Fast Ethernet LAN Controller
+ * as found on the Digital Fast EtherWORKS PCI 10/100 adapter (DE-500-X).
+ * To do:
+ *	thresholds;
+ *	ring sizing;
+ *	handle more error conditions;
+ *	all the rest of it...
+ */
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+#include "etherif.h"
+
+#define DEBUG		(0)
+#define debug		if(DEBUG)print
+
+enum {
+	Nrde		= 32,
+	Ntde		= 4,
+};
+
+#define Rbsz		ROUNDUP(sizeof(Etherpkt)+4, 4)
+
+enum {					/* CRS0 - Bus Mode */
+	Swr		= 0x00000001,	/* Software Reset */
+	Bar		= 0x00000002,	/* Bus Arbitration */
+	Dsl		= 0x0000007C,	/* Descriptor Skip Length (field) */
+	Ble		= 0x00000080,	/* Big/Little Endian */
+	Pbl		= 0x00003F00,	/* Programmable Burst Length (field) */
+	Cal		= 0x0000C000,	/* Cache Alignment (field) */
+	Cal8		= 0x00004000,	/* 8 longword boundary alignment */
+	Cal16		= 0x00008000,	/* 16 longword boundary alignment */
+	Cal32		= 0x0000C000,	/* 32 longword boundary alignment */
+	Tap		= 0x000E0000,	/* Transmit Automatic Polling (field) */
+	Dbo		= 0x00100000,	/* Descriptor Byte Ordering Mode */
+	Rml		= 0x00200000,	/* Read Multiple */
+}; 
+
+enum {					/* CSR[57] - Status and Interrupt Enable */
+	Ti		= 0x00000001,	/* Transmit Interrupt */
+	Tps		= 0x00000002,	/* Transmit Process Stopped */
+	Tu		= 0x00000004,	/* Transmit buffer Unavailable */
+	Tjt		= 0x00000008,	/* Transmit Jabber Timeout */
+	Unf		= 0x00000020,	/* transmit UNderFlow */
+	Ri		= 0x00000040,	/* Receive Interrupt */
+	Ru		= 0x00000080,	/* Receive buffer Unavailable */
+	Rps		= 0x00000100,	/* Receive Process Stopped */
+	Rwt		= 0x00000200,	/* Receive Watchdog Timeout */
+	Eti		= 0x00000400,	/* Early Transmit Interrupt */
+	Gte		= 0x00000800,	/* General purpose Timer Expired */
+	Fbe		= 0x00002000,	/* Fatal Bit Error */
+	Ais		= 0x00008000,	/* Abnormal Interrupt Summary */
+	Nis		= 0x00010000,	/* Normal Interrupt Summary */
+	Rs		= 0x000E0000,	/* Receive process State (field) */
+	Ts		= 0x00700000,	/* Transmit process State (field) */
+	Eb		= 0x03800000,	/* Error bits */
+};
+
+enum {					/* CSR6 - Operating Mode */
+	Hp		= 0x00000001,	/* Hash/Perfect receive filtering mode */
+	Sr		= 0x00000002,	/* Start/stop Receive */
+	Ho		= 0x00000004,	/* Hash-Only filtering mode */
+	Pb		= 0x00000008,	/* Pass Bad frames */
+	If		= 0x00000010,	/* Inverse Filtering */
+	Sb		= 0x00000020,	/* Start/stop Backoff counter */
+	Pr		= 0x00000040,	/* Promiscuous Mode */
+	Pm		= 0x00000080,	/* Pass all Multicast */
+	Fd		= 0x00000200,	/* Full Duplex mode */
+	Om		= 0x00000C00,	/* Operating Mode (field) */
+	Fc		= 0x00001000,	/* Force Collision */
+	St		= 0x00002000,	/* Start/stop Transmission Command */
+	Tr		= 0x0000C000,	/* ThReshold control bits (field) */
+	Tr128		= 0x00000000,
+	Tr256		= 0x00004000,
+	Tr512		= 0x00008000,
+	Tr1024		= 0x0000C000,
+	Ca		= 0x00020000,	/* CApture effect enable */
+	Ps		= 0x00040000,	/* Port Select */
+	Hbd		= 0x00080000,	/* HeartBeat Disable */
+	Imm		= 0x00100000,	/* IMMediate mode */
+	Sf		= 0x00200000,	/* Store and Forward */
+	Ttm		= 0x00400000,	/* Transmit Threshold Mode */
+	Pcs		= 0x00800000,	/* PCS function */
+	Scr		= 0x01000000,	/* SCRambler mode */
+	Mbo		= 0x02000000,	/* Must Be One */
+	Ra		= 0x40000000,	/* Receive All */
+	Sc		= 0x80000000,	/* Special Capture effect enable */
+
+	TrMODE		= Tr512,	/* default transmission threshold */
+};
+
+enum {					/* CSR9 - ROM and MII Management */
+	Scs		= 0x00000001,	/* serial ROM chip select */
+	Sclk		= 0x00000002,	/* serial ROM clock */
+	Sdi		= 0x00000004,	/* serial ROM data in */
+	Sdo		= 0x00000008,	/* serial ROM data out */
+	Ss		= 0x00000800,	/* serial ROM select */
+	Wr		= 0x00002000,	/* write */
+	Rd		= 0x00004000,	/* read */
+
+	Mdc		= 0x00010000,	/* MII management clock */
+	Mdo		= 0x00020000,	/* MII management write data */
+	Mii		= 0x00040000,	/* MII management operation mode (W) */
+	Mdi		= 0x00080000,	/* MII management data in */
+};
+
+enum {					/* CSR12 - General-Purpose Port */
+	Gpc		= 0x00000100,	/* General Purpose Control */
+};
+
+typedef struct Des {
+	int	status;
+	int	control;
+	ulong	addr;
+	void*	bp;
+} Des;
+
+enum {					/* status */
+	Of		= 0x00000001,	/* Rx: OverFlow */
+	Ce		= 0x00000002,	/* Rx: CRC Error */
+	Db		= 0x00000004,	/* Rx: Dribbling Bit */
+	Re		= 0x00000008,	/* Rx: Report on MII Error */
+	Rw		= 0x00000010,	/* Rx: Receive Watchdog */
+	Ft		= 0x00000020,	/* Rx: Frame Type */
+	Cs		= 0x00000040,	/* Rx: Collision Seen */
+	Tl		= 0x00000080,	/* Rx: Frame too Long */
+	Ls		= 0x00000100,	/* Rx: Last deScriptor */
+	Fs		= 0x00000200,	/* Rx: First deScriptor */
+	Mf		= 0x00000400,	/* Rx: Multicast Frame */
+	Rf		= 0x00000800,	/* Rx: Runt Frame */
+	Dt		= 0x00003000,	/* Rx: Data Type (field) */
+	De		= 0x00004000,	/* Rx: Descriptor Error */
+	Fl		= 0x3FFF0000,	/* Rx: Frame Length (field) */
+	Ff		= 0x40000000,	/* Rx: Filtering Fail */
+
+	Def		= 0x00000001,	/* Tx: DEFerred */
+	Uf		= 0x00000002,	/* Tx: UnderFlow error */
+	Lf		= 0x00000004,	/* Tx: Link Fail report */
+	Cc		= 0x00000078,	/* Tx: Collision Count (field) */
+	Hf		= 0x00000080,	/* Tx: Heartbeat Fail */
+	Ec		= 0x00000100,	/* Tx: Excessive Collisions */
+	Lc		= 0x00000200,	/* Tx: Late Collision */
+	Nc		= 0x00000400,	/* Tx: No Carrier */
+	Lo		= 0x00000800,	/* Tx: LOss of carrier */
+	To		= 0x00004000,	/* Tx: Transmission jabber timeOut */
+
+	Es		= 0x00008000,	/* [RT]x: Error Summary */
+	Own		= 0x80000000,	/* [RT]x: OWN bit */
+};
+
+enum {					/* control */
+	Bs1		= 0x000007FF,	/* [RT]x: Buffer 1 Size */
+	Bs2		= 0x003FF800,	/* [RT]x: Buffer 2 Size */
+
+	Ch		= 0x01000000,	/* [RT]x: second address CHained */
+	Er		= 0x02000000,	/* [RT]x: End of Ring */
+
+	Ft0		= 0x00400000,	/* Tx: Filtering Type 0 */
+	Dpd		= 0x00800000,	/* Tx: Disabled PaDding */
+	Ac		= 0x04000000,	/* Tx: Add CRC disable */
+	Set		= 0x08000000,	/* Tx: SETup packet */
+	Ft1		= 0x10000000,	/* Tx: Filtering Type 1 */
+	Fseg		= 0x20000000,	/* Tx: First SEGment */
+	Lseg		= 0x40000000,	/* Tx: Last SEGment */
+	Ic		= 0x80000000,	/* Tx: Interrupt on Completion */
+};
+
+enum {					/* PHY registers */
+	Bmcr		= 0,		/* Basic Mode Control */
+	Bmsr		= 1,		/* Basic Mode Status */
+	Phyidr1		= 2,		/* PHY Identifier #1 */
+	Phyidr2		= 3,		/* PHY Identifier #2 */
+	Anar		= 4,		/* Auto-Negotiation Advertisment */
+	Anlpar		= 5,		/* Auto-Negotiation Link Partner Ability */
+	Aner		= 6,		/* Auto-Negotiation Expansion */
+};
+
+enum {					/* Variants */
+	Tulip0		= (0x0009<<16)|0x1011,
+	Tulip1		= (0x0014<<16)|0x1011,
+	Tulip3		= (0x0019<<16)|0x1011,
+	Pnic		= (0x0002<<16)|0x11AD,
+	Pnic2		= (0xC115<<16)|0x11AD,
+};
+
+typedef struct Ctlr Ctlr;
+typedef struct Ctlr {
+	int	port;
+	Pcidev*	pcidev;
+	Ctlr*	next;
+	int	active;
+	int	id;			/* (pcidev->did<<16)|pcidev->vid */
+
+	uchar	*srom;
+	int	sromsz;
+	uchar*	sromea;			/* MAC address */
+	uchar*	leaf;
+	int	sct;			/* selected connection type */
+	int	k;			/* info block count */
+	uchar*	infoblock[16];
+	int	sctk;			/* sct block index */
+	int	curk;			/* current block index */
+	uchar*	type5block;
+
+	int	phy[32];		/* logical to physical map */
+	int	phyreset;		/* reset bitmap */
+	int	curphyad;
+	int	fdx;
+	int	ttm;
+
+	uchar	fd;			/* option */
+	int	medium;			/* option */
+
+	int	csr6;			/* CSR6 - operating mode */
+	int	mask;			/* CSR[57] - interrupt mask */
+	int	mbps;
+
+	Des*	rdr;			/* receive descriptor ring */
+	int	nrdr;			/* size of rdr */
+	int	rdrx;			/* index into rdr */
+
+	Des*	tdr;			/* transmit descriptor ring */
+	int	ntdr;			/* size of tdr */
+	int	tdrh;			/* host index into tdr */
+	int	tdri;			/* interface index into tdr */
+	int	ntq;			/* descriptors active */
+	Block*	setupbp;
+
+	ulong	of;			/* receive statistics */
+	ulong	ce;
+	ulong	cs;
+	ulong	tl;
+	ulong	rf;
+	ulong	de;
+
+	ulong	uf;			/* transmit statistics */
+	ulong	ec;
+	ulong	lc;
+	ulong	nc;
+	ulong	lo;
+	ulong	to;
+
+} Ctlr;
+
+static Ctlr* ctlrhead;
+static Ctlr* ctlrtail;
+
+#define csr32r(c, r)	(inl((c)->port+((r)*8)))
+#define csr32w(c, r, l)	(outl((c)->port+((r)*8), (ulong)(l)))
+
+static void
+attach(Ether* ether)
+{
+	Ctlr *ctlr;
+
+	ctlr = ether->ctlr;
+	if(!(ctlr->csr6 & Sr)){
+		ctlr->csr6 |= Sr;
+		csr32w(ctlr, 6, ctlr->csr6);
+	}
+}
+
+static void
+transmit(Ether* ether)
+{
+	Ctlr *ctlr;
+	Block *bp;
+	Des *des;
+	int control;
+	RingBuf *tb;
+
+	ctlr = ether->ctlr;
+	while(ctlr->ntq < (ctlr->ntdr-1)){
+		if(ctlr->setupbp){
+			bp = ctlr->setupbp;
+			ctlr->setupbp = 0;
+			control = Ic|Set|BLEN(bp);
+		}
+		else{
+			if(ether->ntb == 0)
+				break;
+			tb = &ether->tb[ether->ti];
+			if(tb->owner != Interface)
+				break;
+			bp = allocb(tb->len);
+			memmove(bp->wp, tb->pkt, tb->len);
+			memmove(bp->wp+Eaddrlen, ether->ea, Eaddrlen);
+			bp->wp += tb->len;
+
+			tb->owner = Host;
+			ether->ti = NEXT(ether->ti, ether->ntb);
+
+			control = Ic|Lseg|Fseg|BLEN(bp);
+		}
+
+		ctlr->tdr[PREV(ctlr->tdrh, ctlr->ntdr)].control &= ~Ic;
+		des = &ctlr->tdr[ctlr->tdrh];
+		des->bp = bp;
+		des->addr = PADDR(bp->rp);
+		des->control |= control;
+		ctlr->ntq++;
+		//coherence();
+		des->status = Own;
+		csr32w(ctlr, 1, 0);
+		ctlr->tdrh = NEXT(ctlr->tdrh, ctlr->ntdr);
+	}
+}
+
+static void
+interrupt(Ureg*, void* arg)
+{
+	Ctlr *ctlr;
+	Ether *ether;
+	int len, status;
+	Des *des;
+	RingBuf *ring;
+
+	ether = arg;
+	ctlr = ether->ctlr;
+
+	while((status = csr32r(ctlr, 5)) & (Nis|Ais)){
+		/*
+		 * Acknowledge the interrupts and mask-out
+		 * the ones that are implicitly handled.
+		 */
+		csr32w(ctlr, 5, status);
+		status &= (ctlr->mask & ~(Nis|Ais|Ti));
+
+		/*
+		 * Received packets.
+		 */
+		if(status & Ri){
+			des = &ctlr->rdr[ctlr->rdrx];
+			while((des->status & Own) == 0){
+				len = ((des->status & Fl)>>16)-4;
+				if(des->status & Es){
+					if(des->status & Of)
+						ctlr->of++;
+					if(des->status & Ce)
+						ctlr->ce++;
+					if(des->status & Cs)
+						ctlr->cs++;
+					if(des->status & Tl)
+						ctlr->tl++;
+					if(des->status & Rf)
+						ctlr->rf++;
+					if(des->status & De)
+						ctlr->de++;
+				}
+				else{
+					ring = &ether->rb[ether->ri];
+					if(ring->owner == Interface){
+						ring->owner = Host;
+						ring->len = len;
+						memmove(ring->pkt, des->bp, len);
+						ether->ri = NEXT(ether->ri, ether->nrb);
+					}
+				}
+
+				des->control &= Er;
+				des->control |= Rbsz;
+				des->status = Own;
+
+				ctlr->rdrx = NEXT(ctlr->rdrx, ctlr->nrdr);
+				des = &ctlr->rdr[ctlr->rdrx];
+			}
+			status &= ~Ri;
+		}
+
+		/*
+		 * Check the transmit side:
+		 *	check for Transmit Underflow and Adjust
+		 *	the threshold upwards;
+		 *	free any transmitted buffers and try to
+		 *	top-up the ring.
+		 */
+		if(status & Unf){
+			csr32w(ctlr, 6, ctlr->csr6 & ~St);
+			switch(ctlr->csr6 & Tr){
+			case Tr128:
+				len = Tr256;
+				break;
+			case Tr256:
+				len = Tr512;
+				break;
+			case Tr512:
+				len = Tr1024;
+				break;
+			default:
+			case Tr1024:
+				len = Sf;
+				break;
+			}
+			ctlr->csr6 = (ctlr->csr6 & ~Tr)|len;
+			csr32w(ctlr, 6, ctlr->csr6);
+			csr32w(ctlr, 5, Tps);
+			status &= ~(Unf|Tps);
+		}
+
+		while(ctlr->ntq){
+			des = &ctlr->tdr[ctlr->tdri];
+			if(des->status & Own)
+				break;
+
+			if(des->status & Es){
+				if(des->status & Uf)
+					ctlr->uf++;
+				if(des->status & Ec)
+					ctlr->ec++;
+				if(des->status & Lc)
+					ctlr->lc++;
+				if(des->status & Nc)
+					ctlr->nc++;
+				if(des->status & Lo)
+					ctlr->lo++;
+				if(des->status & To)
+					ctlr->to++;
+			}
+
+			freeb(des->bp);
+			des->control &= Er;
+
+			ctlr->ntq--;
+			ctlr->tdri = NEXT(ctlr->tdri, ctlr->ntdr);
+		}
+		transmit(ether);
+
+		/*
+		 * Anything left not catered for?
+		 */
+		if(status)
+			panic("#l%d: status %8.8uX\n", ether->ctlrno, status);
+	}
+}
+
+static void
+ctlrinit(Ether* ether)
+{
+	Ctlr *ctlr;
+	Des *des;
+	Block *bp;
+	int i;
+	uchar bi[Eaddrlen*2];
+
+	ctlr = ether->ctlr;
+
+	/*
+	 * Allocate and initialise the receive ring;
+	 * allocate and initialise the transmit ring;
+	 * unmask interrupts and start the transmit side;
+	 * create and post a setup packet to initialise
+	 * the physical ethernet address.
+	 */
+	ctlr->rdr = malloc(ctlr->nrdr*sizeof(Des));
+	for(des = ctlr->rdr; des < &ctlr->rdr[ctlr->nrdr]; des++){
+		des->bp = malloc(Rbsz);
+		des->status = Own;
+		des->control = Rbsz;
+		des->addr = PADDR(des->bp);
+	}
+	ctlr->rdr[ctlr->nrdr-1].control |= Er;
+	ctlr->rdrx = 0;
+	csr32w(ctlr, 3, PADDR(ctlr->rdr));
+
+	ctlr->tdr = ialloc(ctlr->ntdr*sizeof(Des), 32);
+	ctlr->tdr[ctlr->ntdr-1].control |= Er;
+	ctlr->tdrh = 0;
+	ctlr->tdri = 0;
+	csr32w(ctlr, 4, PADDR(ctlr->tdr));
+
+	/*
+	 * Clear any bits in the Status Register (CSR5) as
+	 * the PNIC has a different reset value from a true 2114x.
+	 */
+	ctlr->mask = Nis|Ais|Fbe|Rwt|Rps|Ru|Ri|Unf|Tjt|Tps|Ti;
+	csr32w(ctlr, 5, ctlr->mask);
+	csr32w(ctlr, 7, ctlr->mask);
+	ctlr->csr6 |= St;
+	csr32w(ctlr, 6, ctlr->csr6);
+
+	for(i = 0; i < Eaddrlen/2; i++){
+		bi[i*4] = ether->ea[i*2];
+		bi[i*4+1] = ether->ea[i*2+1];
+		bi[i*4+2] = ether->ea[i*2+1];
+		bi[i*4+3] = ether->ea[i*2];
+	}
+	bp = allocb(Eaddrlen*2*16);
+	memset(bp->rp, 0xFF, sizeof(bi));
+	for(i = sizeof(bi); i < sizeof(bi)*16; i += sizeof(bi))
+		memmove(bp->rp+i, bi, sizeof(bi));
+	bp->wp += sizeof(bi)*16;
+
+	ctlr->setupbp = bp;
+	transmit(ether);
+}
+
+static void
+csr9w(Ctlr* ctlr, int data)
+{
+	csr32w(ctlr, 9, data);
+	microdelay(1);
+}
+
+static int
+miimdi(Ctlr* ctlr, int n)
+{
+	int data, i;
+
+	/*
+	 * Read n bits from the MII Management Register.
+	 */
+	data = 0;
+	for(i = n-1; i >= 0; i--){
+		if(csr32r(ctlr, 9) & Mdi)
+			data |= (1<<i);
+		csr9w(ctlr, Mii|Mdc);
+		csr9w(ctlr, Mii);
+	}
+	csr9w(ctlr, 0);
+
+	return data;
+}
+
+static void
+miimdo(Ctlr* ctlr, int bits, int n)
+{
+	int i, mdo;
+
+	/*
+	 * Write n bits to the MII Management Register.
+	 */
+	for(i = n-1; i >= 0; i--){
+		if(bits & (1<<i))
+			mdo = Mdo;
+		else
+			mdo = 0;
+		csr9w(ctlr, mdo);
+		csr9w(ctlr, mdo|Mdc);
+		csr9w(ctlr, mdo);
+	}
+}
+
+static int
+miir(Ctlr* ctlr, int phyad, int regad)
+{
+	int data, i;
+
+	if(ctlr->id == Pnic){
+		i = 1000;
+		csr32w(ctlr, 20, 0x60020000|(phyad<<23)|(regad<<18));
+		do{
+			microdelay(1);
+			data = csr32r(ctlr, 20);
+		}while((data & 0x80000000) && --i);
+
+		if(i == 0)
+			return -1;
+		return data & 0xFFFF;
+	}
+
+	/*
+	 * Preamble;
+	 * ST+OP+PHYAD+REGAD;
+	 * TA + 16 data bits.
+	 */
+	miimdo(ctlr, 0xFFFFFFFF, 32);
+	miimdo(ctlr, 0x1800|(phyad<<5)|regad, 14);
+	data = miimdi(ctlr, 18);
+
+	if(data & 0x10000)
+		return -1;
+
+	return data & 0xFFFF;
+}
+
+static void
+miiw(Ctlr* ctlr, int phyad, int regad, int data)
+{
+	/*
+	 * Preamble;
+	 * ST+OP+PHYAD+REGAD+TA + 16 data bits;
+	 * Z.
+	 */
+	miimdo(ctlr, 0xFFFFFFFF, 32);
+	data &= 0xFFFF;
+	data |= (0x05<<(5+5+2+16))|(phyad<<(5+2+16))|(regad<<(2+16))|(0x02<<16);
+	miimdo(ctlr, data, 32);
+	csr9w(ctlr, Mdc);
+	csr9w(ctlr, 0);
+}
+
+static int
+sromr(Ctlr* ctlr, int r)
+{
+	int i, op, data, size;
+
+	if(ctlr->id == Pnic){
+		i = 1000;
+		csr32w(ctlr, 19, 0x600|r);
+		do{
+			microdelay(1);
+			data = csr32r(ctlr, 19);
+		}while((data & 0x80000000) && --i);
+
+		if(ctlr->sromsz == 0)
+			ctlr->sromsz = 6;
+
+		return csr32r(ctlr, 9) & 0xFFFF;
+	}
+
+	/*
+	 * This sequence for reading a 16-bit register 'r'
+	 * in the EEPROM is taken (pretty much) straight from Section
+	 * 7.4 of the 21140 Hardware Reference Manual.
+	 */
+reread:
+	csr9w(ctlr, Rd|Ss);
+	csr9w(ctlr, Rd|Ss|Scs);
+	csr9w(ctlr, Rd|Ss|Sclk|Scs);
+	csr9w(ctlr, Rd|Ss);
+
+	op = 0x06;
+	for(i = 3-1; i >= 0; i--){
+		data = Rd|Ss|(((op>>i) & 0x01)<<2)|Scs;
+		csr9w(ctlr, data);
+		csr9w(ctlr, data|Sclk);
+		csr9w(ctlr, data);
+	}
+
+	/*
+	 * First time through must work out the EEPROM size.
+	 * This doesn't seem to work on the 21041 as implemented
+	 * in Virtual PC for the Mac, so wire any 21041 to 6,
+	 * it's the only 21041 this code will ever likely see.
+	 */
+	if((size = ctlr->sromsz) == 0){
+		if(ctlr->id == Tulip1)
+			ctlr->sromsz = size = 6;
+		else
+			size = 8;
+	}
+
+	for(size = size-1; size >= 0; size--){
+		data = Rd|Ss|(((r>>size) & 0x01)<<2)|Scs;
+		csr9w(ctlr, data);
+		csr9w(ctlr, data|Sclk);
+		csr9w(ctlr, data);
+		microdelay(1);
+		if(ctlr->sromsz == 0 && !(csr32r(ctlr, 9) & Sdo))
+			break;
+	}
+
+	data = 0;
+	for(i = 16-1; i >= 0; i--){
+		csr9w(ctlr, Rd|Ss|Sclk|Scs);
+		if(csr32r(ctlr, 9) & Sdo)
+			data |= (1<<i);
+		csr9w(ctlr, Rd|Ss|Scs);
+	}
+
+	csr9w(ctlr, 0);
+
+	if(ctlr->sromsz == 0){
+		ctlr->sromsz = 8-size;
+		goto reread;
+	}
+
+	return data & 0xFFFF;
+}
+
+static void
+softreset(Ctlr* ctlr)
+{
+	/*
+	 * Soft-reset the controller and initialise bus mode.
+	 * Delay should be >= 50 PCI cycles (2×S @ 25MHz).
+	 */
+	csr32w(ctlr, 0, Swr);
+	microdelay(10);
+	csr32w(ctlr, 0, Rml|Cal16);
+	delay(1);
+}
+
+static int
+type5block(Ctlr* ctlr, uchar* block)
+{
+	int csr15, i, len;
+
+	/*
+	 * Reset or GPR sequence. Reset should be once only,
+	 * before the GPR sequence.
+	 * Note 'block' is not a pointer to the block head but
+	 * a pointer to the data in the block starting at the
+	 * reset length value so type5block can be used for the
+	 * sequences contained in type 1 and type 3 blocks.
+	 * The SROM docs state the 21140 type 5 block is the
+	 * same as that for the 21143, but the two controllers
+	 * use different registers and sequence-element lengths
+	 * so the 21140 code here is a guess for a real type 5
+	 * sequence.
+	 */
+	len = *block++;
+	if(ctlr->id != Tulip3){
+		for(i = 0; i < len; i++){
+			csr32w(ctlr, 12, *block);
+			block++;
+		}
+		return len;
+	}
+
+	for(i = 0; i < len; i++){
+		csr15 = *block++<<16;
+		csr15 |= *block++<<24;
+		csr32w(ctlr, 15, csr15);
+		debug("%8.8uX ", csr15);
+	}
+	return 2*len;
+}
+
+static int
+typephylink(Ctlr* ctlr, uchar*)
+{
+	int an, bmcr, bmsr, csr6, x;
+
+	/*
+	 * Fail if
+	 *	auto-negotiataion enabled but not complete;
+	 *	no valid link established.
+	 */
+	bmcr = miir(ctlr, ctlr->curphyad, Bmcr);
+	miir(ctlr, ctlr->curphyad, Bmsr);
+	bmsr = miir(ctlr, ctlr->curphyad, Bmsr);
+	debug("bmcr 0x%2.2uX bmsr 0x%2.2uX\n", bmcr, bmsr);
+	if(((bmcr & 0x1000) && !(bmsr & 0x0020)) || !(bmsr & 0x0004))
+		return 0;
+
+	if(bmcr & 0x1000){
+		an = miir(ctlr, ctlr->curphyad, Anar);
+		an &= miir(ctlr, ctlr->curphyad, Anlpar) & 0x3E0;
+		debug("an 0x%2.uX 0x%2.2uX 0x%2.2uX\n",
+	    		miir(ctlr, ctlr->curphyad, Anar),
+			miir(ctlr, ctlr->curphyad, Anlpar),
+			an);
+	
+		if(an & 0x0100)
+			x = 0x4000;
+		else if(an & 0x0080)
+			x = 0x2000;
+		else if(an & 0x0040)
+			x = 0x1000;
+		else if(an & 0x0020)
+			x = 0x0800;
+		else
+			x = 0;
+	}
+	else if((bmcr & 0x2100) == 0x2100)
+		x = 0x4000;
+	else if(bmcr & 0x2000){
+		/*
+		 * If FD capable, force it if necessary.
+		 */
+		if((bmsr & 0x4000) && ctlr->fd){
+			miiw(ctlr, ctlr->curphyad, Bmcr, 0x2100);
+			x = 0x4000;
+		}
+		else
+			x = 0x2000;
+	}
+	else if(bmcr & 0x0100)
+		x = 0x1000;
+	else
+		x = 0x0800;
+
+	csr6 = Sc|Mbo|Hbd|Ps|Ca|TrMODE|Sb;
+	if(ctlr->fdx & x)
+		csr6 |= Fd;
+	if(ctlr->ttm & x)
+		csr6 |= Ttm;
+	debug("csr6 0x%8.8uX 0x%8.8uX 0x%8.8luX\n",
+		csr6, ctlr->csr6, csr32r(ctlr, 6));
+	if(csr6 != ctlr->csr6){
+		ctlr->csr6 = csr6;
+		csr32w(ctlr, 6, csr6);
+	}
+
+	return 1;
+}
+
+static int
+typephymode(Ctlr* ctlr, uchar* block, int wait)
+{
+	uchar *p;
+	int len, mc, nway, phyx, timeo;
+
+	if(DEBUG){
+		int i;
+
+		len = (block[0] & ~0x80)+1;
+		for(i = 0; i < len; i++)
+			debug("%2.2uX ", block[i]);
+		debug("\n");
+	}
+
+	if(block[1] == 1)
+		len = 1;
+	else if(block[1] == 3)
+		len = 2;
+	else
+		return -1;
+
+	/*
+	 * Snarf the media capabilities, nway advertisment,
+	 * FDX and TTM bitmaps.
+	 */
+	p = &block[5+len*block[3]+len*block[4+len*block[3]]];
+	mc = *p++;
+	mc |= *p++<<8;
+	nway = *p++;
+	nway |= *p++<<8;
+	ctlr->fdx = *p++;
+	ctlr->fdx |= *p++<<8;
+	ctlr->ttm = *p++;
+	ctlr->ttm |= *p<<8;
+	debug("mc %4.4uX nway %4.4uX fdx %4.4uX ttm %4.4uX\n",
+		mc, nway, ctlr->fdx, ctlr->ttm);
+	USED(mc);
+
+	phyx = block[2];
+	ctlr->curphyad = ctlr->phy[phyx];
+
+	ctlr->csr6 = 0;//Sc|Mbo|Hbd|Ps|Ca|TrMODE|Sb;
+	//csr32w(ctlr, 6, ctlr->csr6);
+	if(typephylink(ctlr, block))
+		return 0;
+
+	if(!(ctlr->phyreset & (1<<phyx))){
+		debug("reset seq: len %d: ", block[3]);
+		if(ctlr->type5block)
+			type5block(ctlr, &ctlr->type5block[2]);
+		else
+			type5block(ctlr, &block[4+len*block[3]]);
+		debug("\n");
+		ctlr->phyreset |= (1<<phyx);
+	}
+
+	/*
+	 * GPR sequence.
+	 */
+	debug("gpr seq: len %d: ", block[3]);
+	type5block(ctlr, &block[3]);
+	debug("\n");
+
+	ctlr->csr6 = 0;//Sc|Mbo|Hbd|Ps|Ca|TrMODE|Sb;
+	//csr32w(ctlr, 6, ctlr->csr6);
+	if(typephylink(ctlr, block))
+		return 0;
+
+	/*
+	 * Turn off auto-negotiation, set the auto-negotiation
+	 * advertisment register then start the auto-negotiation
+	 * process again.
+	 */
+	miiw(ctlr, ctlr->curphyad, Bmcr, 0);
+	miiw(ctlr, ctlr->curphyad, Anar, nway|1);
+	miiw(ctlr, ctlr->curphyad, Bmcr, 0x1000);
+
+	if(!wait)
+		return 0;
+
+	for(timeo = 0; timeo < 30; timeo++){
+		if(typephylink(ctlr, block))
+			return 0;
+		delay(100);
+	}
+
+	return -1;
+}
+
+static int
+typesymmode(Ctlr *ctlr, uchar *block, int wait)
+{
+	uint gpmode, gpdata, command;
+
+	USED(wait);
+	gpmode = block[3] | ((uint) block[4] << 8);
+	gpdata = block[5] | ((uint) block[6] << 8);
+	command = (block[7] | ((uint) block[8] << 8)) & 0x71;
+	if (command & 0x8000) {
+		print("ether2114x.c: FIXME: handle type 4 mode blocks where cmd.active_invalid != 0\n");
+		return -1;
+	}
+	csr32w(ctlr, 15, gpmode);
+	csr32w(ctlr, 15, gpdata);
+	ctlr->csr6 = (command & 0x71) << 18;
+	csr32w(ctlr, 6, ctlr->csr6);
+	return 0;
+}
+
+static int
+type2mode(Ctlr* ctlr, uchar* block, int)
+{
+	uchar *p;
+	int csr6, csr13, csr14, csr15, gpc, gpd;
+
+	csr6 = Sc|Mbo|Ca|TrMODE|Sb;
+	debug("type2mode: medium 0x%2.2uX\n", block[2]);
+
+	/*
+	 * Don't attempt full-duplex
+	 * unless explicitly requested.
+	 */
+	if((block[2] & 0x3F) == 0x04){	/* 10BASE-TFD */
+		if(!ctlr->fd)
+			return -1;
+		csr6 |= Fd;
+	}
+
+	/*
+	 * Operating mode programming values from the datasheet
+	 * unless media specific data is explicitly given.
+	 */
+	p = &block[3];
+	if(block[2] & 0x40){
+		csr13 = (block[4]<<8)|block[3];
+		csr14 = (block[6]<<8)|block[5];
+		csr15 = (block[8]<<8)|block[7];
+		p += 6;
+	}
+	else switch(block[2] & 0x3F){
+	default:
+		return -1;
+	case 0x00:			/* 10BASE-T */
+		csr13 = 0x00000001;
+		csr14 = 0x00007F3F;
+		csr15 = 0x00000008;
+		break;
+	case 0x01:			/* 10BASE-2 */
+		csr13 = 0x00000009;
+		csr14 = 0x00000705;
+		csr15 = 0x00000006;
+		break;
+	case 0x02:			/* 10BASE-5 (AUI) */
+		csr13 = 0x00000009;
+		csr14 = 0x00000705;
+		csr15 = 0x0000000E;
+		break;
+	case 0x04:			/* 10BASE-TFD */
+		csr13 = 0x00000001;
+		csr14 = 0x00007F3D;
+		csr15 = 0x00000008;
+		break;
+	}
+	gpc = *p++<<16;
+	gpc |= *p++<<24;
+	gpd = *p++<<16;
+	gpd |= *p<<24;
+
+	csr32w(ctlr, 13, 0);
+	csr32w(ctlr, 14, csr14);
+	csr32w(ctlr, 15, gpc|csr15);
+	delay(10);
+	csr32w(ctlr, 15, gpd|csr15);
+	csr32w(ctlr, 13, csr13);
+
+	ctlr->csr6 = csr6;
+	csr32w(ctlr, 6, ctlr->csr6);
+
+	debug("type2mode: csr13 %8.8uX csr14 %8.8uX csr15 %8.8uX\n",
+		csr13, csr14, csr15);
+	debug("type2mode: gpc %8.8uX gpd %8.8uX csr6 %8.8uX\n",
+		gpc, gpd, csr6);
+
+	return 0;
+}
+
+static int
+type0link(Ctlr* ctlr, uchar* block)
+{
+	int m, polarity, sense;
+
+	m = (block[3]<<8)|block[2];
+	sense = 1<<((m & 0x000E)>>1);
+	if(m & 0x0080)
+		polarity = sense;
+	else
+		polarity = 0;
+
+	return (csr32r(ctlr, 12) & sense)^polarity;
+}
+
+static int
+type0mode(Ctlr* ctlr, uchar* block, int wait)
+{
+	int csr6, m, timeo;
+
+	csr6 = Sc|Mbo|Hbd|Ca|TrMODE|Sb;
+debug("type0: medium 0x%uX, fd %d: 0x%2.2uX 0x%2.2uX 0x%2.2uX 0x%2.2uX\n",
+    ctlr->medium, ctlr->fd, block[0], block[1], block[2], block[3]); 
+	switch(block[0]){
+	default:
+		break;
+
+	case 0x04:			/* 10BASE-TFD */
+	case 0x05:			/* 100BASE-TXFD */
+	case 0x08:			/* 100BASE-FXFD */
+		/*
+		 * Don't attempt full-duplex
+		 * unless explicitly requested.
+		 */
+		if(!ctlr->fd)
+			return -1;
+		csr6 |= Fd;
+		break;
+	}
+
+	m = (block[3]<<8)|block[2];
+	if(m & 0x0001)
+		csr6 |= Ps;
+	if(m & 0x0010)
+		csr6 |= Ttm;
+	if(m & 0x0020)
+		csr6 |= Pcs;
+	if(m & 0x0040)
+		csr6 |= Scr;
+
+	csr32w(ctlr, 12, block[1]);
+	microdelay(10);
+	csr32w(ctlr, 6, csr6);
+	ctlr->csr6 = csr6;
+
+	if(!wait)
+		return 0;
+
+	for(timeo = 0; timeo < 30; timeo++){
+		if(type0link(ctlr, block))
+			return 0;
+		delay(100);
+	}
+
+	return -1;
+}
+
+static int
+media21041(Ether* ether, int wait)
+{
+	Ctlr* ctlr;
+	uchar *block;
+	int csr6, csr13, csr14, csr15, medium, timeo;
+
+	ctlr = ether->ctlr;
+	block = ctlr->infoblock[ctlr->curk];
+	debug("media21041: block[0] %2.2uX, medium %4.4uX sct %4.4uX\n",
+		block[0], ctlr->medium, ctlr->sct);
+
+	medium = block[0] & 0x3F;
+	if(ctlr->medium >= 0 && medium != ctlr->medium)
+		return 0;
+	if(ctlr->sct != 0x0800 && (ctlr->sct & 0x3F) != medium)
+		return 0;
+
+	csr6 = Sc|Mbo|Ca|TrMODE|Sb;
+	if(block[0] & 0x40){
+		csr13 = (block[2]<<8)|block[1];
+		csr14 = (block[4]<<8)|block[3];
+		csr15 = (block[6]<<8)|block[5];
+	}
+	else switch(medium){
+	default:
+		return -1;
+	case 0x00:		/* 10BASE-T */
+		csr13 = 0xEF01;
+		csr14 = 0xFF3F;
+		csr15 = 0x0008;
+		break;
+	case 0x01:		/* 10BASE-2 */
+		csr13 = 0xEF09;
+		csr14 = 0xF73D;
+		csr15 = 0x0006;
+		break;
+	case 0x02:		/* 10BASE-5 */
+		csr13 = 0xEF09;
+		csr14 = 0xF73D;
+		csr15 = 0x000E;
+		break;
+	case 0x04:		/* 10BASE-TFD */
+		csr13 = 0xEF01;
+		csr14 = 0xFF3D;
+		csr15 = 0x0008;
+		break;
+	}
+
+	csr32w(ctlr, 13, 0);
+	csr32w(ctlr, 14, csr14);
+	csr32w(ctlr, 15, csr15);
+	csr32w(ctlr, 13, csr13);
+	delay(10);
+
+	if(medium == 0x04)
+		csr6 |= Fd;
+	ctlr->csr6 = csr6;
+	csr32w(ctlr, 6, ctlr->csr6);
+
+	debug("media21041: csr6 %8.8uX csr13 %4.4uX csr14 %4.4uX csr15 %4.4uX\n",
+		csr6, csr13, csr14, csr15);
+
+	if(!wait)
+		return 0;
+
+	for(timeo = 0; timeo < 30; timeo++){
+		if(!(csr32r(ctlr, 12) & 0x0002)){
+			debug("media21041: ok: csr12 %4.4luX timeo %d\n",
+				csr32r(ctlr, 12), timeo);
+			return 10;
+		}
+		delay(100);
+	}
+	debug("media21041: !ok: csr12 %4.4luX\n", csr32r(ctlr, 12));
+
+	return -1;
+}
+
+static int
+mediaxx(Ether* ether, int wait)
+{
+	Ctlr* ctlr;
+	uchar *block;
+
+	ctlr = ether->ctlr;
+	block = ctlr->infoblock[ctlr->curk];
+	if(block[0] & 0x80){
+		switch(block[1]){
+		default:
+			return -1;
+		case 0:
+			if(ctlr->medium >= 0 && block[2] != ctlr->medium)
+				return 0;
+/* need this test? */	if(ctlr->sct != 0x0800 && (ctlr->sct & 0x3F) != block[2])
+				return 0;
+			if(type0mode(ctlr, block+2, wait))
+				return 0;
+			break;
+		case 1:
+			if(typephymode(ctlr, block, wait))
+				return 0;
+			break;
+		case 2:
+			debug("type2: medium %d block[2] %d\n",
+				ctlr->medium, block[2]);
+			if(ctlr->medium >= 0 && ((block[2] & 0x3F) != ctlr->medium))
+				return 0;
+			if(type2mode(ctlr, block, wait))
+				return 0;
+			break;
+		case 3:
+			if(typephymode(ctlr, block, wait))
+				return 0;
+			break;
+		case 4:
+			debug("type4: medium %d block[2] %d\n",
+				ctlr->medium, block[2]);
+			if(ctlr->medium >= 0 && ((block[2] & 0x3F) != ctlr->medium))
+				return 0;
+			if(typesymmode(ctlr, block, wait))
+				return 0;
+			break;
+		}
+	}
+	else{
+		if(ctlr->medium >= 0 && block[0] != ctlr->medium)
+			return 0;
+/* need this test? */if(ctlr->sct != 0x0800 && (ctlr->sct & 0x3F) != block[0])
+			return 0;
+		if(type0mode(ctlr, block, wait))
+			return 0;
+	}
+
+	if(ctlr->csr6){
+		if(!(ctlr->csr6 & Ps) || (ctlr->csr6 & Ttm))
+			return 10;
+		return 100;
+	}
+
+	return 0;
+}
+
+static int
+media(Ether* ether, int wait)
+{
+	Ctlr* ctlr;
+	int k, mbps;
+
+	ctlr = ether->ctlr;
+	for(k = 0; k < ctlr->k; k++){
+		switch(ctlr->id){
+		default:
+			mbps = mediaxx(ether, wait);
+			break;
+		case Tulip1:			/* 21041 */
+			mbps = media21041(ether, wait);
+			break;
+		}
+		if(mbps > 0)
+			return mbps;
+		if(ctlr->curk == 0)
+			ctlr->curk = ctlr->k-1;
+		else
+			ctlr->curk--;
+	}
+
+	return 0;
+}
+
+static char* mediatable[9] = {
+	"10BASE-T",			/* TP */
+	"10BASE-2",			/* BNC */
+	"10BASE-5",			/* AUI */
+	"100BASE-TX",
+	"10BASE-TFD",
+	"100BASE-TXFD",
+	"100BASE-T4",
+	"100BASE-FX",
+	"100BASE-FXFD",
+};
+
+static uchar en1207[] = {		/* Accton EN1207-COMBO */
+	0x00, 0x00, 0xE8,		/* [0]  vendor ethernet code */
+	0x00,				/* [3]  spare */
+
+	0x00, 0x08,			/* [4]  connection (LSB+MSB = 0x0800) */
+	0x1F,				/* [6]  general purpose control */
+	2,				/* [7]  block count */
+
+	0x00,				/* [8]  media code (10BASE-TX) */
+	0x0B,				/* [9]  general purpose port data */
+	0x9E, 0x00,			/* [10] command (LSB+MSB = 0x009E) */
+
+	0x03,				/* [8]  media code (100BASE-TX) */
+	0x1B,				/* [9]  general purpose port data */
+	0x6D, 0x00,			/* [10] command (LSB+MSB = 0x006D) */
+
+					/* There is 10BASE-2 as well, but... */
+};
+
+static uchar ana6910fx[] = {		/* Adaptec (Cogent) ANA-6910FX */
+	0x00, 0x00, 0x92,		/* [0]  vendor ethernet code */
+	0x00,				/* [3]  spare */
+
+	0x00, 0x08,			/* [4]  connection (LSB+MSB = 0x0800) */
+	0x3F,				/* [6]  general purpose control */
+	1,				/* [7]  block count */
+
+	0x07,				/* [8]  media code (100BASE-FX) */
+	0x03,				/* [9]  general purpose port data */
+	0x2D, 0x00			/* [10] command (LSB+MSB = 0x000D) */
+};
+
+static uchar smc9332[] = {		/* SMC 9332 */
+	0x00, 0x00, 0xC0,		/* [0]  vendor ethernet code */
+	0x00,				/* [3]  spare */
+
+	0x00, 0x08,			/* [4]  connection (LSB+MSB = 0x0800) */
+	0x1F,				/* [6]  general purpose control */
+	2,				/* [7]  block count */
+
+	0x00,				/* [8]  media code (10BASE-TX) */
+	0x00,				/* [9]  general purpose port data */
+	0x9E, 0x00,			/* [10] command (LSB+MSB = 0x009E) */
+
+	0x03,				/* [8]  media code (100BASE-TX) */
+	0x09,				/* [9]  general purpose port data */
+	0x6D, 0x00,			/* [10] command (LSB+MSB = 0x006D) */
+};
+
+static uchar* leaf21140[] = {
+	en1207,				/* Accton EN1207-COMBO */
+	ana6910fx,			/* Adaptec (Cogent) ANA-6910FX */
+	smc9332,			/* SMC 9332 */
+	0,
+};
+
+/*
+ * Copied to ctlr->srom at offset 20.
+ */
+static uchar leafpnic[] = {
+	0x00, 0x00, 0x00, 0x00,		/* MAC address */
+	0x00, 0x00,
+	0x00,				/* controller 0 device number */
+	0x1E, 0x00,			/* controller 0 info leaf offset */
+	0x00,				/* reserved */
+	0x00, 0x08,			/* selected connection type */
+	0x00,				/* general purpose control */
+	0x01,				/* block count */
+
+	0x8C,				/* format indicator and count */
+	0x01,				/* block type */
+	0x00,				/* PHY number */
+	0x00,				/* GPR sequence length */
+	0x00,				/* reset sequence length */
+	0x00, 0x78,			/* media capabilities */
+	0xE0, 0x01,			/* Nway advertisment */
+	0x00, 0x50,			/* FDX bitmap */
+	0x00, 0x18,			/* TTM bitmap */
+};
+
+static int
+srom(Ctlr* ctlr)
+{
+	int i, k, oui, phy, x;
+	uchar *p;
+
+	/*
+	 * This is a partial decoding of the SROM format described in
+	 * 'Digital Semiconductor 21X4 Serial ROM Format, Version 4.05,
+	 * 2-Mar-98'. Only the 2114[03] are handled, support for other
+	 * controllers can be added as needed.
+	 */
+	sromr(ctlr, 0);
+	if(ctlr->srom == nil)
+		ctlr->srom = malloc((1<<ctlr->sromsz)*sizeof(ushort));
+	for(i = 0; i < (1<<ctlr->sromsz); i++){
+		x = sromr(ctlr, i);
+		ctlr->srom[2*i] = x;
+		ctlr->srom[2*i+1] = x>>8;
+	}
+
+	if(DEBUG){
+		print("srom:");
+		for(i = 0; i < ((1<<ctlr->sromsz)*sizeof(ushort)); i++){
+			if(i && ((i & 0x0F) == 0))
+				print("\n     ");
+			print(" %2.2uX", ctlr->srom[i]);
+		}
+		print("\n");
+	}
+
+	/*
+	 * There are 2 SROM layouts:
+	 *	e.g. Digital EtherWORKS	station address at offset 20;
+	 *				this complies with the 21140A SROM
+	 *				application note from Digital;
+	 * 	e.g. SMC9332		station address at offset 0 followed by
+	 *				2 additional bytes, repeated at offset
+	 *				6; the 8 bytes are also repeated in
+	 *				reverse order at offset 8.
+	 * To check which it is, read the SROM and check for the repeating
+	 * patterns of the non-compliant cards; if that fails use the one at
+	 * offset 20.
+	 */
+	ctlr->sromea = ctlr->srom;
+	for(i = 0; i < 8; i++){
+		x = ctlr->srom[i];
+		if(x != ctlr->srom[15-i] || x != ctlr->srom[16+i]){
+			ctlr->sromea = &ctlr->srom[20];
+			break;
+		}
+	}
+
+	/*
+	 * Fake up the SROM for the PNIC.
+	 * It looks like a 21140 with a PHY.
+	 * The MAC address is byte-swapped in the orginal SROM data.
+	 */
+	if(ctlr->id == Pnic){
+		memmove(&ctlr->srom[20], leafpnic, sizeof(leafpnic));
+		for(i = 0; i < Eaddrlen; i += 2){
+			ctlr->srom[20+i] = ctlr->srom[i+1];
+			ctlr->srom[20+i+1] = ctlr->srom[i];
+		}
+	}
+
+	/*
+	 * Next, try to find the info leaf in the SROM for media detection.
+	 * If it's a non-conforming card try to match the vendor ethernet code
+	 * and point p at a fake info leaf with compact 21140 entries.
+	 */
+	if(ctlr->sromea == ctlr->srom){
+		p = nil;
+		for(i = 0; leaf21140[i] != nil; i++){
+			if(memcmp(leaf21140[i], ctlr->sromea, 3) == 0){
+				p = &leaf21140[i][4];
+				break;
+			}
+		}
+		if(p == nil)
+			return -1;
+	}
+	else
+		p = &ctlr->srom[(ctlr->srom[28]<<8)|ctlr->srom[27]];
+
+	/*
+	 * Set up the info needed for later media detection.
+	 * For the 21140, set the general-purpose mask in CSR12.
+	 * The info block entries are stored in order of increasing
+	 * precedence, so detection will work backwards through the
+	 * stored indexes into ctlr->srom.
+	 * If an entry is found which matches the selected connection
+	 * type, save the index. Otherwise, start at the last entry.
+	 * If any MII entries are found (type 1 and 3 blocks), scan
+	 * for PHYs.
+	 */
+	ctlr->leaf = p;
+	ctlr->sct = *p++;
+	ctlr->sct |= *p++<<8;
+	if(ctlr->id != Tulip3 && ctlr->id != Tulip1){
+		csr32w(ctlr, 12, Gpc|*p++);
+		delay(200);
+	}
+	ctlr->k = *p++;
+	if(ctlr->k >= nelem(ctlr->infoblock))
+		ctlr->k = nelem(ctlr->infoblock)-1;
+	ctlr->sctk = ctlr->k-1;
+	phy = 0;
+	for(k = 0; k < ctlr->k; k++){
+		ctlr->infoblock[k] = p;
+		if(ctlr->id == Tulip1){
+			debug("type21041: 0x%2.2uX\n", p[0]); 
+			if(ctlr->sct != 0x0800 && *p == (ctlr->sct & 0xFF))
+				ctlr->sctk = k;
+			if(*p & 0x40)
+				p += 7;
+			else
+				p += 1;
+		}
+		/*
+		 * The RAMIX PMC665 has a badly-coded SROM,
+		 * hence the test for 21143 and type 3.
+		 */
+		else if((*p & 0x80) || (ctlr->id == Tulip3 && *(p+1) == 3)){
+			*p |= 0x80;
+			if(*(p+1) == 1 || *(p+1) == 3)
+				phy = 1;
+			if(*(p+1) == 5)
+				ctlr->type5block = p;
+			p += (*p & ~0x80)+1;
+		}
+		else{
+			debug("type0: 0x%2.2uX 0x%2.2uX 0x%2.2uX 0x%2.2uX\n",
+				p[0], p[1], p[2], p[3]); 
+			if(ctlr->sct != 0x0800 && *p == (ctlr->sct & 0xFF))
+				ctlr->sctk = k;
+			p += 4;
+		}
+	}
+	ctlr->curk = ctlr->sctk;
+	debug("sct 0x%uX medium 0x%uX k %d curk %d phy %d\n",
+		ctlr->sct, ctlr->medium, ctlr->k, ctlr->curk, phy);
+
+	if(phy){
+		x = 0;
+		for(k = 0; k < nelem(ctlr->phy); k++){
+			if((oui = miir(ctlr, k, 2)) == -1 || oui == 0)
+				continue;
+			if(DEBUG){
+				oui = (oui & 0x3FF)<<6;
+				oui |= miir(ctlr, k, 3)>>10;
+				miir(ctlr, k, 1);
+				debug("phy%d: index %d oui %uX reg1 %uX\n",
+					x, k, oui, miir(ctlr, k, 1));
+				USED(oui);
+			}
+			ctlr->phy[x] = k;
+		}
+	}
+
+	ctlr->fd = 0;
+	ctlr->medium = -1;
+
+	return 0;
+}
+
+static void
+dec2114xpci(void)
+{
+	Ctlr *ctlr;
+	Pcidev *p;
+	int x;
+
+	p = nil;
+	while(p = pcimatch(p, 0, 0)){
+		if(p->ccrb != 0x02 || p->ccru != 0)
+			continue;
+		switch((p->did<<16)|p->vid){
+		default:
+			continue;
+
+		case Tulip3:			/* 21143 */
+			/*
+			 * Exit sleep mode.
+			 */
+			x = pcicfgr32(p, 0x40);
+			x &= ~0xC0000000;
+			pcicfgw32(p, 0x40, x);
+			/*FALLTHROUGH*/
+
+		case Pnic:			/* PNIC */
+		case Pnic2:			/* PNIC-II */
+		case Tulip0:			/* 21140 */
+		case Tulip1:			/* 21041 */
+			break;
+		}
+
+		/*
+		 * bar[0] is the I/O port register address and
+		 * bar[1] is the memory-mapped register address.
+		 */
+		ctlr = malloc(sizeof(Ctlr));
+		ctlr->port = p->mem[0].bar & ~0x01;
+		ctlr->pcidev = p;
+		ctlr->id = (p->did<<16)|p->vid;
+		debug("2114x: type 0x%8.8uX rev 0x%4.4uX at port 0x%4.4uX\n",
+			ctlr->id, p->rid, ctlr->port);
+
+		/*
+		 * Some cards (e.g. ANA-6910FX) seem to need the Ps bit
+		 * set or they don't always work right after a hardware
+		 * reset.
+		 */
+		csr32w(ctlr, 6, Mbo|Ps);
+		softreset(ctlr);
+
+		if(srom(ctlr)){
+			free(ctlr);
+			break;
+		}
+
+		switch(ctlr->id){
+		default:
+			break;
+
+		case Pnic:			/* PNIC */
+			/*
+			 * Turn off the jabber timer.
+			 */
+			csr32w(ctlr, 15, 0x00000001);
+			break;
+		}
+
+		if(ctlrhead != nil)
+			ctlrtail->next = ctlr;
+		else
+			ctlrhead = ctlr;
+		ctlrtail = ctlr;
+	}
+}
+
+static void
+detach(Ether* ether)
+{
+	softreset(ether->ctlr);
+}
+
+int
+ether2114xreset(Ether* ether)
+{
+	Ctlr *ctlr;
+	int i, x;
+	uchar ea[Eaddrlen];
+	static int scandone;
+
+	if(scandone == 0){
+		dec2114xpci();
+		scandone = 1;
+	}
+
+	/*
+	 * Any adapter matches if no ether->port is supplied,
+	 * otherwise the ports must match.
+	 */
+	for(ctlr = ctlrhead; ctlr != nil; ctlr = ctlr->next){
+		if(ctlr->active)
+			continue;
+		if(ether->port == 0 || ether->port == ctlr->port){
+			ctlr->active = 1;
+			break;
+		}
+	}
+	if(ctlr == nil)
+		return -1;
+
+	ether->ctlr = ctlr;
+	ether->port = ctlr->port;
+	ether->irq = ctlr->pcidev->intl;
+	ether->tbdf = ctlr->pcidev->tbdf;
+
+	/*
+	 * Check if the adapter's station address is to be overridden.
+	 * If not, read it from the EEPROM and set in ether->ea prior to
+	 * loading the station address in the hardware.
+	 */
+	memset(ea, 0, Eaddrlen);
+	if(memcmp(ea, ether->ea, Eaddrlen) == 0)
+		memmove(ether->ea, ctlr->sromea, Eaddrlen);
+
+	/*
+	 * Look for a medium override in case there's no autonegotiation
+	 * (no MII) or the autonegotiation fails.
+	 */
+	for(i = 0; i < ether->nopt; i++){
+		if(cistrcmp(ether->opt[i], "FD") == 0){
+			ctlr->fd = 1;
+			continue;
+		}
+		for(x = 0; x < nelem(mediatable); x++){
+			debug("compare <%s> <%s>\n", mediatable[x],
+				ether->opt[i]);
+			if(cistrcmp(mediatable[x], ether->opt[i]))
+				continue;
+			ctlr->medium = x;
+	
+			switch(ctlr->medium){
+			default:
+				ctlr->fd = 0;
+				break;
+	
+			case 0x04:		/* 10BASE-TFD */
+			case 0x05:		/* 100BASE-TXFD */
+			case 0x08:		/* 100BASE-FXFD */
+				ctlr->fd = 1;
+				break;
+			}
+			break;
+		}
+	}
+
+	/*
+	 * Determine media.
+	 */
+	ctlr->mbps = media(ether, 1);
+
+	/*
+	 * Initialise descriptor rings, ethernet address.
+	 */
+	ctlr->nrdr = Nrde;
+	ctlr->ntdr = Ntde;
+	pcisetbme(ctlr->pcidev);
+	ctlrinit(ether);
+
+	/*
+	 * Linkage to the generic ethernet driver.
+	 */
+	ether->attach = attach;
+	ether->transmit = transmit;
+	ether->interrupt = interrupt;
+	ether->detach = detach;
+
+	return 0;
+}
--- /dev/null
+++ b/os/boot.original/pc/ether589.c
@@ -1,0 +1,211 @@
+/*
+ * 3C589 and 3C562.
+ * To do:
+ *	check xcvr10Base2 still works (is GlobalReset necessary?).
+ */
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "error.h"
+
+#include "etherif.h"
+
+enum {						/* all windows */
+	CommandR		= 0x000E,
+	IntStatusR		= 0x000E,
+};
+
+enum {						/* Commands */
+	GlobalReset		= 0x0000,
+	SelectRegisterWindow	= 0x0001,
+	RxReset			= 0x0005,
+	TxReset			= 0x000B,
+	AcknowledgeInterrupt	= 0x000D,
+};
+
+enum {						/* IntStatus bits */
+	commandInProgress	= 0x1000,
+};
+
+#define COMMAND(port, cmd, a)	outs((port)+CommandR, ((cmd)<<11)|(a))
+#define STATUS(port)		ins((port)+IntStatusR)
+
+enum {						/* Window 0 - setup */
+	Wsetup			= 0x0000,
+						/* registers */
+	ManufacturerID		= 0x0000,	/* 3C5[08]*, 3C59[27] */
+	ProductID		= 0x0002,	/* 3C5[08]*, 3C59[27] */
+	ConfigControl		= 0x0004,	/* 3C5[08]*, 3C59[27] */
+	AddressConfig		= 0x0006,	/* 3C5[08]*, 3C59[27] */
+	ResourceConfig		= 0x0008,	/* 3C5[08]*, 3C59[27] */
+	EepromCommand		= 0x000A,
+	EepromData		= 0x000C,
+						/* AddressConfig Bits */
+	autoSelect9		= 0x0080,
+	xcvrMask9		= 0xC000,
+						/* ConfigControl bits */
+	Ena			= 0x0001,
+	base10TAvailable9	= 0x0200,
+	coaxAvailable9		= 0x1000,
+	auiAvailable9		= 0x2000,
+						/* EepromCommand bits */
+	EepromReadRegister	= 0x0080,
+	EepromBusy		= 0x8000,
+};
+
+enum {						/* Window 1 - operating set */
+	Wop			= 0x0001,
+};
+
+enum {						/* Window 3 - FIFO management */
+	Wfifo			= 0x0003,
+						/* registers */
+	InternalConfig		= 0x0000,	/* 3C509B, 3C589, 3C59[0257] */
+						/* InternalConfig bits */
+	xcvr10BaseT		= 0x00000000,
+	xcvr10Base2		= 0x00300000,
+};
+
+enum {						/* Window 4 - diagnostic */
+	Wdiagnostic		= 0x0004,
+						/* registers */
+	MediaStatus		= 0x000A,
+						/* MediaStatus bits */
+	linkBeatDetect		= 0x0800,
+};
+
+extern int elnk3reset(Ether*);
+
+static char *tcmpcmcia[] = {
+	"3C589",			/* 3COM 589[ABCD] */
+	"3C562",			/* 3COM 562 */
+	"589E",				/* 3COM Megahertz 589E */
+	nil,
+};
+
+static int
+configASIC(Ether* ether, int port, int xcvr)
+{
+	int x;
+
+	/* set Window 0 configuration registers */
+	COMMAND(port, SelectRegisterWindow, Wsetup);
+	outs(port+ConfigControl, Ena);
+
+	/* IRQ must be 3 on 3C589/3C562 */
+	outs(port + ResourceConfig, 0x3F00);
+
+	x = ins(port+AddressConfig) & ~xcvrMask9;
+	x |= (xcvr>>20)<<14;
+	outs(port+AddressConfig, x);
+
+	COMMAND(port, TxReset, 0);
+	while(STATUS(port) & commandInProgress)
+		;
+	COMMAND(port, RxReset, 0);
+	while(STATUS(port) & commandInProgress)
+		;
+
+	return elnk3reset(ether);
+}
+
+int
+ether589reset(Ether* ether)
+{
+	int i, t, slot;
+	char *type;
+	int port;
+	enum { WantAny, Want10BT, Want10B2 };
+	int want;
+	uchar ea[6];
+	char *p;
+
+	if(ether->irq == 0)
+		ether->irq = 10;
+	if(ether->port == 0)
+		ether->port = 0x240;
+	port = ether->port;
+
+//	if(ioalloc(port, 0x10, 0, "3C589") < 0)
+//		return -1;
+
+	type = nil;
+	slot = -1;
+	for(i = 0; tcmpcmcia[i] != nil; i++){
+		type = tcmpcmcia[i];
+if(debug) print("try %s...", type);
+		if((slot = pcmspecial(type, ether)) >= 0)
+			break;
+	}
+	if(slot < 0){
+if(debug) print("none found\n");
+//		iofree(port);
+		return -1;
+	}
+
+	/*
+	 * Read Ethernet address from card memory
+	 * on 3C562, but only if the user has not 
+	 * overridden it.
+	 */
+	memset(ea, 0, sizeof ea);
+	if(memcmp(ea, ether->ea, 6) == 0 && strcmp(type, "3C562") == 0) {
+		if(debug)
+			print("read 562...");
+		if(pcmcistuple(slot, 0x88, -1, ea, 6) == 6) {
+			for(i = 0; i < 6; i += 2){
+				t = ea[i];
+				ea[i] = ea[i+1];
+				ea[i+1] = t;
+			}
+			memmove(ether->ea, ea, 6);
+			if(debug)
+				print("ea %E", ea);
+		}
+	}
+	/*
+	 * Allow user to specify desired media in plan9.ini
+	 */
+	want = WantAny;
+	for(i = 0; i < ether->nopt; i++){
+		if(cistrncmp(ether->opt[i], "media=", 6) != 0)
+			continue;
+		p = ether->opt[i]+6;
+		if(cistrcmp(p, "10base2") == 0)
+			want = Want10B2;
+		else if(cistrcmp(p, "10baseT") == 0)
+			want = Want10BT;
+	}
+	
+	/* try configuring as a 10BaseT */
+	if(want==WantAny || want==Want10BT){
+		if(configASIC(ether, port, xcvr10BaseT) < 0){
+			pcmspecialclose(slot);
+//			iofree(port);
+			return -1;
+		}
+		delay(100);
+		COMMAND(port, SelectRegisterWindow, Wdiagnostic);
+		if((ins(port+MediaStatus)&linkBeatDetect) || want==Want10BT){
+			COMMAND(port, SelectRegisterWindow, Wop);
+			print("#l%d: xcvr10BaseT %s\n", ether->ctlrno, type);
+			return 0;
+		}
+	}
+
+	/* try configuring as a 10base2 */
+	if(want==WantAny || want==Want10B2){
+		COMMAND(port, GlobalReset, 0);
+		if(configASIC(ether, port, xcvr10Base2) < 0){
+			pcmspecialclose(slot);
+//			iofree(port);
+			return -1;
+		}
+		print("#l%d: xcvr10Base2 %s\n", ether->ctlrno, type);
+		return 0;
+	}
+	return -1;		/* not reached */
+}
--- /dev/null
+++ b/os/boot.original/pc/ether79c970.c
@@ -1,0 +1,539 @@
+/*
+ * AMD79C970
+ * PCnet-PCI Single-Chip Ethernet Controller for PCI Local Bus
+ * To do:
+ *	finish this rewrite
+ */
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+#include "etherif.h"
+
+enum {
+	Lognrdre	= 6,
+	Nrdre		= (1<<Lognrdre),/* receive descriptor ring entries */
+	Logntdre	= 4,
+	Ntdre		= (1<<Logntdre),/* transmit descriptor ring entries */
+
+	Rbsize		= ETHERMAXTU+4,	/* ring buffer size (+4 for CRC) */
+};
+
+enum {					/* DWIO I/O resource map */
+	Aprom		= 0x0000,	/* physical address */
+	Rdp		= 0x0010,	/* register data port */
+	Rap		= 0x0014,	/* register address port */
+	Sreset		= 0x0018,	/* software reset */
+	Bdp		= 0x001C,	/* bus configuration register data port */
+};
+
+enum {					/* CSR0 */
+	Init		= 0x0001,	/* begin initialisation */
+	Strt		= 0x0002,	/* enable chip */
+	Stop		= 0x0004,	/* disable chip */
+	Tdmd		= 0x0008,	/* transmit demand */
+	Txon		= 0x0010,	/* transmitter on */
+	Rxon		= 0x0020,	/* receiver on */
+	Iena		= 0x0040,	/* interrupt enable */
+	Intr		= 0x0080,	/* interrupt flag */
+	Idon		= 0x0100,	/* initialisation done */
+	Tint		= 0x0200,	/* transmit interrupt */
+	Rint		= 0x0400,	/* receive interrupt */
+	Merr		= 0x0800,	/* memory error */
+	Miss		= 0x1000,	/* missed frame */
+	Cerr		= 0x2000,	/* collision */
+	Babl		= 0x4000,	/* transmitter timeout */
+	Err		= 0x8000,	/* Babl|Cerr|Miss|Merr */
+};
+	
+enum {					/* CSR3 */
+	Bswp		= 0x0004,	/* byte swap */
+	Emba		= 0x0008,	/* enable modified back-off algorithm */
+	Dxmt2pd		= 0x0010,	/* disable transmit two part deferral */
+	Lappen		= 0x0020,	/* look-ahead packet processing enable */
+};
+
+enum {					/* CSR4 */
+	ApadXmt		= 0x0800,	/* auto pad transmit */
+};
+
+enum {					/* CSR15 */
+	Prom		= 0x8000,	/* promiscuous mode */
+};
+
+typedef struct {			/* Initialisation Block */
+	ushort	mode;
+	uchar	rlen;			/* upper 4 bits */
+	uchar	tlen;			/* upper 4 bits */
+	uchar	padr[6];
+	uchar	res[2];
+	uchar	ladr[8];
+	ulong	rdra;
+	ulong	tdra;
+} Iblock;
+
+typedef struct {			/* descriptor ring entry */
+	ulong	addr;
+	ulong	md1;			/* status|bcnt */
+	ulong	md2;			/* rcc|rpc|mcnt */
+	void*	data;
+} Dre;
+
+enum {					/* md1 */
+	Enp		= 0x01000000,	/* end of packet */
+	Stp		= 0x02000000,	/* start of packet */
+	RxBuff		= 0x04000000,	/* buffer error */
+	Def		= 0x04000000,	/* deferred */
+	Crc		= 0x08000000,	/* CRC error */
+	One		= 0x08000000,	/* one retry needed */
+	Oflo		= 0x10000000,	/* overflow error */
+	More		= 0x10000000,	/* more than one retry needed */
+	Fram		= 0x20000000,	/* framing error */
+	RxErr		= 0x40000000,	/* Fram|Oflo|Crc|RxBuff */
+	TxErr		= 0x40000000,	/* Uflo|Lcol|Lcar|Rtry */
+	Own		= 0x80000000,
+};
+
+enum {					/* md2 */
+	Rtry		= 0x04000000,	/* failed after repeated retries */
+	Lcar		= 0x08000000,	/* loss of carrier */
+	Lcol		= 0x10000000,	/* late collision */
+	Uflo		= 0x40000000,	/* underflow error */
+	TxBuff		= 0x80000000,	/* buffer error */
+};
+
+typedef struct Ctlr Ctlr;
+struct Ctlr {
+	Lock;
+	int	port;
+	Pcidev*	pcidev;
+	Ctlr*	next;
+	int	active;
+
+	int	init;			/* initialisation in progress */
+	Iblock	iblock;
+
+	Dre*	rdr;			/* receive descriptor ring */
+	int	rdrx;
+
+	Dre*	tdr;			/* transmit descriptor ring */
+	int	tdrh;			/* host index into tdr */
+	int	tdri;			/* interface index into tdr */
+	int	ntq;			/* descriptors active */
+
+	ulong	rxbuff;			/* receive statistics */
+	ulong	crc;
+	ulong	oflo;
+	ulong	fram;
+
+	ulong	rtry;			/* transmit statistics */
+	ulong	lcar;
+	ulong	lcol;
+	ulong	uflo;
+	ulong	txbuff;
+
+	ulong	merr;			/* bobf is such a whiner */
+	ulong	miss;
+	ulong	babl;
+
+	int		(*ior)(Ctlr*, int);
+	void		(*iow)(Ctlr*, int, int);
+};
+
+static Ctlr* ctlrhead;
+static Ctlr* ctlrtail;
+
+/*
+ * The Rdp, Rap, Sreset, Bdp ports are 32-bit port offset in the enumeration above.
+ * To get to 16-bit offsets, scale down with 0x10 staying the same.
+ */
+static int
+io16r(Ctlr* c, int r)
+{
+	if(r >= Rdp)
+		r = (r-Rdp)/2+Rdp;
+	return ins(c->port+r);
+}
+
+static void
+io16w(Ctlr* c, int r, int v)
+{
+	if(r >= Rdp)
+		r = (r-Rdp)/2+Rdp;
+	outs(c->port+r, v);
+}
+
+static int
+io32r(Ctlr* c, int r)
+{
+	return inl(c->port+r);
+}
+
+static void
+io32w(Ctlr* c, int r, int v)
+{
+	outl(c->port+r, v);
+}
+
+static void
+attach(Ether*)
+{
+}
+
+static void
+detach(Ether* ether)
+{
+	Ctlr *ctlr;
+
+	ctlr = ether->ctlr;
+	ctlr->iow(ctlr, Rdp, Iena|Stop);
+}
+
+static void
+ringinit(Ctlr* ctlr)
+{
+	Dre *dre;
+
+	/*
+	 * Initialise the receive and transmit buffer rings.
+	 * The ring entries must be aligned on 16-byte boundaries.
+	 *
+	 * This routine is protected by ctlr->init.
+	 */
+	if(ctlr->rdr == 0){
+		ctlr->rdr = ialloc(Nrdre*sizeof(Dre), 0x10);
+		for(dre = ctlr->rdr; dre < &ctlr->rdr[Nrdre]; dre++){
+			dre->data = malloc(Rbsize);
+			dre->addr = PADDR(dre->data);
+			dre->md2 = 0;
+			dre->md1 = Own|(-Rbsize & 0xFFFF);
+		}
+	}
+	ctlr->rdrx = 0;
+
+	if(ctlr->tdr == 0)
+		ctlr->tdr = ialloc(Ntdre*sizeof(Dre), 0x10);
+	memset(ctlr->tdr, 0, Ntdre*sizeof(Dre));
+	ctlr->tdrh = ctlr->tdri = 0;
+}
+
+static void
+transmit(Ether* ether)
+{
+	Ctlr *ctlr;
+	Block *bp;
+	Dre *dre;
+	RingBuf *tb;
+
+	ctlr = ether->ctlr;
+
+	if(ctlr->init)
+		return;
+
+	while(ctlr->ntq < (Ntdre-1)){
+		tb = &ether->tb[ether->ti];
+		if(tb->owner != Interface)
+			break;
+
+		bp = allocb(tb->len);
+		memmove(bp->wp, tb->pkt, tb->len);
+		memmove(bp->wp+Eaddrlen, ether->ea, Eaddrlen);
+		bp->wp += tb->len;
+
+		/*
+		 * Give ownership of the descriptor to the chip,
+		 * increment the software ring descriptor pointer
+		 * and tell the chip to poll.
+		 * There's no need to pad to ETHERMINTU
+		 * here as ApadXmt is set in CSR4.
+		 */
+		dre = &ctlr->tdr[ctlr->tdrh];
+		dre->data = bp;
+		dre->addr = PADDR(bp->rp);
+		dre->md2 = 0;
+		dre->md1 = Own|Stp|Enp|Oflo|(-BLEN(bp) & 0xFFFF);
+		ctlr->ntq++;
+		ctlr->iow(ctlr, Rap, 0);
+		ctlr->iow(ctlr, Rdp, Iena|Tdmd);
+		ctlr->tdrh = NEXT(ctlr->tdrh, Ntdre);
+
+		tb->owner = Host;
+		ether->ti = NEXT(ether->ti, ether->ntb);
+	}
+}
+
+static void
+interrupt(Ureg*, void* arg)
+{
+	Ctlr *ctlr;
+	Ether *ether;
+	int csr0;
+	Dre *dre;
+	RingBuf *rb;
+
+	ether = arg;
+	ctlr = ether->ctlr;
+
+	/*
+	 * Acknowledge all interrupts and whine about those that shouldn't
+	 * happen.
+	 */
+intrloop:
+	csr0 = ctlr->ior(ctlr, Rdp) & 0xFFFF;
+	ctlr->iow(ctlr, Rdp, Babl|Cerr|Miss|Merr|Rint|Tint|Iena);
+	if(csr0 & Merr)
+		ctlr->merr++;
+	if(csr0 & Miss)
+		ctlr->miss++;
+	if(csr0 & Babl)
+		ctlr->babl++;
+	//if(csr0 & (Babl|Miss|Merr))
+	//	print("#l%d: csr0 = 0x%uX\n", ether->ctlrno, csr0);
+	if(!(csr0 & (Rint|Tint)))
+		return;
+
+	/*
+	 * Receiver interrupt: run round the descriptor ring logging
+	 * errors and passing valid receive data up to the higher levels
+	 * until a descriptor is encountered still owned by the chip.
+	 */
+	if(csr0 & Rint){
+		dre = &ctlr->rdr[ctlr->rdrx];
+		while(!(dre->md1 & Own)){
+			rb = &ether->rb[ether->ri];
+			if(dre->md1 & RxErr){
+				if(dre->md1 & RxBuff)
+					ctlr->rxbuff++;
+				if(dre->md1 & Crc)
+					ctlr->crc++;
+				if(dre->md1 & Oflo)
+					ctlr->oflo++;
+				if(dre->md1 & Fram)
+					ctlr->fram++;
+			}
+			else if(rb->owner == Interface){
+				rb->owner = Host;
+				rb->len = (dre->md2 & 0x0FFF)-4;
+				memmove(rb->pkt, dre->data, rb->len);
+				ether->ri = NEXT(ether->ri, ether->nrb);
+			}
+
+			/*
+			 * Finished with this descriptor, reinitialise it,
+			 * give it back to the chip, then on to the next...
+			 */
+			dre->md2 = 0;
+			dre->md1 = Own|(-Rbsize & 0xFFFF);
+
+			ctlr->rdrx = NEXT(ctlr->rdrx, Nrdre);
+			dre = &ctlr->rdr[ctlr->rdrx];
+		}
+	}
+
+	/*
+	 * Transmitter interrupt: wakeup anyone waiting for a free descriptor.
+	 */
+	if(csr0 & Tint){
+		lock(ctlr);
+		while(ctlr->ntq){
+			dre = &ctlr->tdr[ctlr->tdri];
+			if(dre->md1 & Own)
+				break;
+	
+			if(dre->md1 & TxErr){
+				if(dre->md2 & Rtry)
+					ctlr->rtry++;
+				if(dre->md2 & Lcar)
+					ctlr->lcar++;
+				if(dre->md2 & Lcol)
+					ctlr->lcol++;
+				if(dre->md2 & Uflo)
+					ctlr->uflo++;
+				if(dre->md2 & TxBuff)
+					ctlr->txbuff++;
+			}
+	
+			freeb(dre->data);
+	
+			ctlr->ntq--;
+			ctlr->tdri = NEXT(ctlr->tdri, Ntdre);
+		}
+		transmit(ether);
+		unlock(ctlr);
+	}
+	goto intrloop;
+}
+
+static void
+amd79c970pci(void)
+{
+	Ctlr *ctlr;
+	Pcidev *p;
+
+	p = nil;
+	while(p = pcimatch(p, 0x1022, 0x2000)){
+		ctlr = malloc(sizeof(Ctlr));
+		ctlr->port = p->mem[0].bar & ~0x01;
+		ctlr->pcidev = p;
+
+		if(ctlrhead != nil)
+			ctlrtail->next = ctlr;
+		else
+			ctlrhead = ctlr;
+		ctlrtail = ctlr;
+	}
+}
+
+int
+amd79c970reset(Ether* ether)
+{
+	int x;
+	uchar ea[Eaddrlen];
+	Ctlr *ctlr;
+
+	if(ctlrhead == nil)
+		amd79c970pci();
+
+	/*
+	 * Any adapter matches if no port is supplied,
+	 * otherwise the ports must match.
+	 */
+	for(ctlr = ctlrhead; ctlr != nil; ctlr = ctlr->next){
+		if(ctlr->active)
+			continue;
+		if(ether->port == 0 || ether->port == ctlr->port){
+			ctlr->active = 1;
+			break;
+		}
+	}
+	if(ctlr == nil)
+		return -1;
+
+	/*
+	 * Allocate a controller structure and start to initialise it.
+	 */
+	ether->ctlr = ctlr;
+	ether->port = ctlr->port;
+	ether->irq = ctlr->pcidev->intl;
+	ether->tbdf = ctlr->pcidev->tbdf;
+	pcisetbme(ctlr->pcidev);
+	ilock(ctlr);
+	ctlr->init = 1;
+
+	io32r(ctlr, Sreset);
+	io16r(ctlr, Sreset);
+
+	if(io16w(ctlr, Rap, 0), io16r(ctlr, Rdp) == 4){
+		ctlr->ior = io16r;
+		ctlr->iow = io16w;
+	}else if(io32w(ctlr, Rap, 0), io32r(ctlr, Rdp) == 4){
+		ctlr->ior = io32r;
+		ctlr->iow = io32w;
+	}else{
+		print("#l%d: card doesn't talk right\n", ether->ctlrno);
+		iunlock(ctlr);
+		return -1;
+	}
+
+	ctlr->iow(ctlr, Rap, 88);
+	x = ctlr->ior(ctlr, Rdp);
+	ctlr->iow(ctlr, Rap, 89);
+	x |= ctlr->ior(ctlr, Rdp)<<16;
+
+	switch(x&0xFFFFFFF){
+	case 0x2420003:	/* PCnet/PCI 79C970 */
+	case 0x2621003:	/* PCnet/PCI II 79C970A */
+		break;
+	default:
+		print("unknown PCnet card version %.7ux\n", x&0xFFFFFFF);
+		iunlock(ctlr);
+		return -1;
+	}
+
+	/*
+	 * Set the software style in BCR20 to be PCnet-PCI to ensure 32-bit access.
+	 * Set the auto pad transmit in CSR4.
+	 */
+	ctlr->iow(ctlr, Rap, 20);
+	ctlr->iow(ctlr, Bdp, 0x0002);
+
+	ctlr->iow(ctlr, Rap, 4);
+	x = ctlr->ior(ctlr, Rdp) & 0xFFFF;
+	ctlr->iow(ctlr, Rdp, ApadXmt|x);
+
+	ctlr->iow(ctlr, Rap, 0);
+
+	/*
+	 * Check if the adapter's station address is to be overridden.
+	 * If not, read it from the I/O-space and set in ether->ea prior to
+	 * loading the station address in the initialisation block.
+	 */
+	memset(ea, 0, Eaddrlen);
+	if(!memcmp(ea, ether->ea, Eaddrlen)){
+		x = ctlr->ior(ctlr, Aprom);
+		ether->ea[0] = x;
+		ether->ea[1] = x>>8;
+		if(ctlr->ior == io16r)
+			x = ctlr->ior(ctlr, Aprom+2);
+		else
+			x >>= 16;
+		ether->ea[2] = x;
+		ether->ea[3] = x>>8;
+		x = ctlr->ior(ctlr, Aprom+4);
+		ether->ea[4] = x;
+		ether->ea[5] = x>>8;
+	}
+
+	/*
+	 * Start to fill in the initialisation block
+	 * (must be DWORD aligned).
+	 */
+	ctlr->iblock.rlen = Lognrdre<<4;
+	ctlr->iblock.tlen = Logntdre<<4;
+	memmove(ctlr->iblock.padr, ether->ea, sizeof(ctlr->iblock.padr));
+
+	ringinit(ctlr);
+	ctlr->iblock.rdra = PADDR(ctlr->rdr);
+	ctlr->iblock.tdra = PADDR(ctlr->tdr);
+
+	/*
+	 * Point the chip at the initialisation block and tell it to go.
+	 * Mask the Idon interrupt and poll for completion. Strt and interrupt
+	 * enables will be set later when attaching to the network.
+	 */
+	x = PADDR(&ctlr->iblock);
+	ctlr->iow(ctlr, Rap, 1);
+	ctlr->iow(ctlr, Rdp, x & 0xFFFF);
+	ctlr->iow(ctlr, Rap, 2);
+	ctlr->iow(ctlr, Rdp, (x>>16) & 0xFFFF);
+	ctlr->iow(ctlr, Rap, 3);
+	ctlr->iow(ctlr, Rdp, Idon);
+	ctlr->iow(ctlr, Rap, 0);
+	ctlr->iow(ctlr, Rdp, Init);
+
+	while(!(ctlr->ior(ctlr, Rdp) & Idon))
+		;
+
+	/*
+	 * We used to set CSR0 to Idon|Stop here, and then
+	 * in attach change it to Iena|Strt.  Apparently the simulated
+	 * 79C970 in VMware never enables after a write of Idon|Stop,
+	 * so we enable the device here now.
+	 */
+	ctlr->iow(ctlr, Rdp, Iena|Strt);
+	ctlr->init = 0;
+	iunlock(ctlr);
+
+	/*
+	 * Linkage to the generic ethernet driver.
+	 */
+	ether->attach = attach;
+	ether->transmit = transmit;
+	ether->interrupt = interrupt;
+	ether->detach = detach;
+
+	return 0;
+}
--- /dev/null
+++ b/os/boot.original/pc/ether8003.c
@@ -1,0 +1,258 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+#include "etherif.h"
+#include "ether8390.h"
+
+/*
+ * Western Digital/Standard Microsystems Corporation cards (WD80[01]3).
+ * Also handles 8216 cards (Elite Ultra).
+ * Configuration code based on that provided by SMC a long time ago.
+ */
+enum {					/* 83C584 Bus Interface Controller */
+	Msr		= 0x00,		/* Memory Select Register */
+	Icr		= 0x01,		/* Interface Configuration Register */
+	Iar		= 0x02,		/* I/O Address Register */
+	Bio		= 0x03,		/* BIOS ROM Address Register */
+	Ear		= 0x03,		/* EEROM Address Register (shared with Bio) */
+	Irr		= 0x04,		/* Interrupt Request Register */
+	Hcr		= 0x04,		/* 8216 hardware control */
+	Laar		= 0x05,		/* LA Address Register */
+	Ijr		= 0x06,		/* Initialisation Jumpers */
+	Gp2		= 0x07,		/* General Purpose Data Register */
+	Lar		= 0x08,		/* LAN Address Registers */
+	Id		= 0x0E,		/* Card ID byte */
+	Cksum		= 0x0F,		/* Checksum */
+};
+
+enum {					/* Msr */
+	Rst		= 0x80,		/* software reset */
+	Menb		= 0x40,		/* memory enable */
+};
+
+enum {					/* Icr */
+	Bit16		= 0x01,		/* 16-bit bus */
+	Other		= 0x02,		/* other register access */
+	Ir2		= 0x04,		/* IR2 */
+	Msz		= 0x08,		/* SRAM size */
+	Rla		= 0x10,		/* recall LAN address */
+	Rx7		= 0x20,		/* recall all but I/O and LAN address */
+	Rio		= 0x40,		/* recall I/O address from EEROM */
+	Sto		= 0x80,		/* non-volatile EEROM store */
+};
+
+enum {					/* Laar */
+	ZeroWS16	= 0x20,		/* zero wait states for 16-bit ops */
+	L16en		= 0x40,		/* enable 16-bit LAN operation */
+	M16en		= 0x80,		/* enable 16-bit memory access */
+};
+
+enum {					/* Ijr */
+	Ienable		= 0x01,		/* 8216 interrupt enable */
+};
+
+/*
+ * Mapping from configuration bits to interrupt level.
+ */
+static int irq8003[8] = {
+	9, 3, 5, 7, 10, 11, 15, 4,
+};
+
+static int irq8216[8] = {
+	0, 9, 3, 5, 7, 10, 11, 15,
+};
+
+static void
+reset8003(Ether* ether, uchar ea[Eaddrlen], uchar ic[8])
+{
+	Dp8390 *ctlr;
+	ulong port;
+
+	ctlr = ether->ctlr;
+	port = ether->port;
+
+	/*
+	 * Check for old, dumb 8003E, which doesn't have an interface
+	 * chip. Only Msr exists out of the 1st eight registers, reads
+	 * of the others just alias the 2nd eight registers, the LAN
+	 * address ROM. Can check Icr, Irr and Laar against the ethernet
+	 * address read above and if they match it's an 8003E (or an
+	 * 8003EBT, 8003S, 8003SH or 8003WT, doesn't matter), in which
+	 * case the default irq gets used.
+	 */
+	if(memcmp(&ea[1], &ic[1], 5) == 0){
+		memset(ic, 0, sizeof(ic));
+		ic[Msr] = (((ulong)ether->mem)>>13) & 0x3F;
+	}
+	else{
+		/*
+		 * As a final sanity check for the 8013EBT, which doesn't have
+		 * the 83C584 interface chip, but has 2 real registers, write Gp2
+		 * and if it reads back the same, it's not an 8013EBT.
+		 */
+		outb(port+Gp2, 0xAA);
+		inb(port+Msr);				/* wiggle bus */
+		if(inb(port+Gp2) != 0xAA){
+			memset(ic, 0, sizeof(ic));
+			ic[Msr] = (((ulong)ether->mem)>>13) & 0x3F;
+		}
+		else
+			ether->irq = irq8003[((ic[Irr]>>5) & 0x3)|(ic[Icr] & 0x4)];
+
+		/*
+		 * Check if 16-bit card.
+		 * If Bit16 is read/write, then it's an 8-bit card.
+		 * If Bit16 is set, it's in a 16-bit slot.
+		 */
+		outb(port+Icr, ic[Icr]^Bit16);
+		inb(port+Msr);				/* wiggle bus */
+		if((inb(port+Icr) & Bit16) == (ic[Icr] & Bit16)){
+			ctlr->width = 2;
+			ic[Icr] &= ~Bit16;
+		}
+		outb(port+Icr, ic[Icr]);
+
+		if(ctlr->width == 2 && (inb(port+Icr) & Bit16) == 0)
+			ctlr->width = 1;
+	}
+
+	ether->mem = (ulong)KADDR((ic[Msr] & 0x3F)<<13);
+	if(ctlr->width == 2)
+		ether->mem |= (ic[Laar] & 0x1F)<<19;
+	else
+		ether->mem |= 0x80000;
+
+	if(ic[Icr] & (1<<3))
+		ether->size = 32*1024;
+	if(ctlr->width == 2)
+		ether->size <<= 1;
+
+	/*
+	 * Enable interface RAM, set interface width.
+	 */
+	outb(port+Msr, ic[Msr]|Menb);
+	if(ctlr->width == 2)
+		outb(port+Laar, ic[Laar]|L16en|M16en|ZeroWS16);
+}
+
+static void
+reset8216(Ether* ether, uchar[8])
+{
+	uchar hcr, irq, x;
+	ulong addr, port;
+	Dp8390 *ctlr;
+
+	ctlr = ether->ctlr;
+	port = ether->port;
+
+	ctlr->width = 2;
+
+	/*
+	 * Switch to the alternate register set and retrieve the memory
+	 * and irq information.
+	 */
+	hcr = inb(port+Hcr);
+	outb(port+Hcr, 0x80|hcr);
+	addr = inb(port+0x0B) & 0xFF;
+	irq = inb(port+0x0D);
+	outb(port+Hcr, hcr);
+
+	ether->mem = (ulong)KADDR(0xC0000+((((addr>>2) & 0x30)|(addr & 0x0F))<<13));
+	ether->size = 8192*(1<<((addr>>4) & 0x03));
+	ether->irq = irq8216[((irq>>4) & 0x04)|((irq>>2) & 0x03)];
+
+	/*
+	 * Enable interface RAM, set interface width, and enable interrupts.
+	 */
+	x = inb(port+Msr) & ~Rst;
+	outb(port+Msr, Menb|x);
+	x = inb(port+Laar);
+	outb(port+Laar, M16en|x);
+	outb(port+Ijr, Ienable);
+}
+
+/*
+ * Get configuration parameters, enable memory.
+ * There are opportunities here for buckets of code, try to resist.
+ */
+int
+wd8003reset(Ether* ether)
+{
+	int i;
+	uchar ea[Eaddrlen], ic[8], id, nullea[Eaddrlen], sum;
+	ulong port;
+	Dp8390 *ctlr;
+
+	/*
+	 * Set up the software configuration.
+	 * Use defaults for port, irq, mem and size if not specified.
+	 * Defaults are set for the dumb 8003E which can't be
+	 * autoconfigured.
+	 */
+	if(ether->port == 0)
+		ether->port = 0x280;
+	if(ether->irq == 0)
+		ether->irq = 3;
+	if(ether->mem == 0)
+		ether->mem = 0xD0000;
+	if(ether->size == 0)
+		ether->size = 8*1024;
+
+	/*
+	 * Look for the interface. Read the LAN address ROM
+	 * and validate the checksum - the sum of all 8 bytes
+	 * should be 0xFF.
+	 * At the same time, get the (possible) interface chip
+	 * registers, they'll be used later to check for aliasing.
+	 */
+	port = ether->port;
+	sum = 0;
+	for(i = 0; i < sizeof(ea); i++){
+		ea[i] = inb(port+Lar+i);
+		sum += ea[i];
+		ic[i] = inb(port+i);
+	}
+	id = inb(port+Id);
+	sum += id;
+	sum += inb(port+Cksum);
+	if(sum != 0xFF)
+		return -1;
+
+	ether->ctlr = malloc(sizeof(Dp8390));
+	ctlr = ether->ctlr;
+	ctlr->ram = 1;
+
+	if((id & 0xFE) == 0x2A)
+		reset8216(ether, ic);
+	else
+		reset8003(ether, ea, ic);
+
+	/*
+	 * Set the DP8390 ring addresses.
+	 */
+	ctlr->port = port+0x10;
+	ctlr->tstart = 0;
+	ctlr->pstart = HOWMANY(sizeof(Etherpkt), Dp8390BufSz);
+	ctlr->pstop = HOWMANY(ether->size, Dp8390BufSz);
+
+	/*
+	 * Finally, init the 8390, set the ethernet address
+	 * and claim the memory used.
+	 */
+	dp8390reset(ether);
+	memset(nullea, 0, Eaddrlen);
+	if(memcmp(nullea, ether->ea, Eaddrlen) == 0){
+		for(i = 0; i < sizeof(ether->ea); i++)
+			ether->ea[i] = ea[i];
+	}
+	dp8390setea(ether);
+
+	if(umbrwmalloc(PADDR(ether->mem), ether->size, 0) == 0)
+		print("ether8003: warning - 0x%luX unavailable", PADDR(ether->mem));
+
+	return 0;
+}
--- /dev/null
+++ b/os/boot.original/pc/ether8139.c
@@ -1,0 +1,614 @@
+/*
+ * Realtek 8139 (but not the 8129).
+ * Error recovery for the various over/under -flow conditions
+ * may need work.
+ */
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+#include "etherif.h"
+
+enum {					/* registers */
+	Idr0		= 0x0000,	/* MAC address */
+	Mar0		= 0x0008,	/* Multicast address */
+	Tsd0		= 0x0010,	/* Transmit Status Descriptor0 */
+	Tsad0		= 0x0020,	/* Transmit Start Address Descriptor0 */
+	Rbstart		= 0x0030,	/* Receive Buffer Start Address */
+	Erbcr		= 0x0034,	/* Early Receive Byte Count */
+	Ersr		= 0x0036,	/* Early Receive Status */
+	Cr		= 0x0037,	/* Command Register */
+	Capr		= 0x0038,	/* Current Address of Packet Read */
+	Cbr		= 0x003A,	/* Current Buffer Address */
+	Imr		= 0x003C,	/* Interrupt Mask */
+	Isr		= 0x003E,	/* Interrupt Status */
+	Tcr		= 0x0040,	/* Transmit Configuration */
+	Rcr		= 0x0044,	/* Receive Configuration */
+	Tctr		= 0x0048,	/* Timer Count */
+	Mpc		= 0x004C,	/* Missed Packet Counter */
+	Cr9346		= 0x0050,	/* 9346 Command Register */
+	Config0		= 0x0051,	/* Configuration Register 0 */
+	Config1		= 0x0052,	/* Configuration Register 1 */
+	TimerInt	= 0x0054,	/* Timer Interrupt */
+	Msr		= 0x0058,	/* Media Status */
+	Config3		= 0x0059,	/* Configuration Register 3 */
+	Config4		= 0x005A,	/* Configuration Register 4 */
+	Mulint		= 0x005C,	/* Multiple Interrupt Select */
+	RerID		= 0x005E,	/* PCI Revision ID */
+	Tsad		= 0x0060,	/* Transmit Status of all Descriptors */
+
+	Bmcr		= 0x0062,	/* Basic Mode Control */
+	Bmsr		= 0x0064,	/* Basic Mode Status */
+	Anar		= 0x0066,	/* Auto-Negotiation Advertisment */
+	Anlpar		= 0x0068,	/* Auto-Negotiation Link Partner */
+	Aner		= 0x006A,	/* Auto-Negotiation Expansion */
+	Dis		= 0x006C,	/* Disconnect Counter */
+	Fcsc		= 0x006E,	/* False Carrier Sense Counter */
+	Nwaytr		= 0x0070,	/* N-way Test */
+	Rec		= 0x0072,	/* RX_ER Counter */
+	Cscr		= 0x0074,	/* CS Configuration */
+	Phy1parm	= 0x0078,	/* PHY Parameter 1 */
+	Twparm		= 0x007C,	/* Twister Parameter */
+	Phy2parm	= 0x0080,	/* PHY Parameter 2 */
+};
+
+enum {					/* Cr */
+	Bufe		= 0x01,		/* Rx Buffer Empty */
+	Te		= 0x04,		/* Transmitter Enable */
+	Re		= 0x08,		/* Receiver Enable */
+	Rst		= 0x10,		/* Software Reset */
+};
+
+enum {					/* Imr/Isr */
+	Rok		= 0x0001,	/* Receive OK */
+	Rer		= 0x0002,	/* Receive Error */
+	Tok		= 0x0004,	/* Transmit OK */
+	Ter		= 0x0008,	/* Transmit Error */
+	Rxovw		= 0x0010,	/* Receive Buffer Overflow */
+	PunLc		= 0x0020,	/* Packet Underrun or Link Change */
+	Fovw		= 0x0040,	/* Receive FIFO Overflow */
+	Clc		= 0x2000,	/* Cable Length Change */
+	Timer		= 0x4000,	/* Timer */
+	Serr		= 0x8000,	/* System Error */
+};
+
+enum {					/* Tcr */
+	Clrabt		= 0x00000001,	/* Clear Abort */
+	TxrrSHIFT	= 4,		/* Transmit Retry Count */
+	TxrrMASK	= 0x000000F0,
+	MtxdmaSHIFT	= 8,		/* Max. DMA Burst Size */
+	MtxdmaMASK	= 0x00000700,
+	Mtxdma2048	= 0x00000700,
+	Acrc		= 0x00010000,	/* Append CRC (not) */
+	LbkSHIFT	= 17,		/* Loopback Test */
+	LbkMASK		= 0x00060000,
+	IfgSHIFT	= 24,		/* Interframe Gap */
+	IfgMASK		= 0x03000000,
+	HwveridSHIFT	= 22,		/* Hardware Version ID */
+	HwveridMASK	= 0x7CC00000,
+};
+
+enum {					/* Rcr */
+	Aap		= 0x00000001,	/* Accept All Packets */
+	Apm		= 0x00000002,	/* Accept Physical Match */
+	Am		= 0x00000004,	/* Accept Multicast */
+	Ab		= 0x00000008,	/* Accept Broadcast */
+	Ar		= 0x00000010,	/* Accept Runt */
+	Aer		= 0x00000020,	/* Accept Error */
+	Sel9356		= 0x00000040,	/* 9356 EEPROM used */
+	Wrap		= 0x00000080,	/* Rx Buffer Wrap Control */
+	MrxdmaSHIFT	= 8,		/* Max. DMA Burst Size */
+	MrxdmaMASK	= 0x00000700,
+	Mrxdmaunlimited	= 0x00000700,
+	RblenSHIFT	= 11,		/* Receive Buffer Length */
+	RblenMASK	= 0x00001800,
+	Rblen8K		= 0x00000000,	/* 8KB+16 */
+	Rblen16K	= 0x00000800,	/* 16KB+16 */
+	Rblen32K	= 0x00001000,	/* 32KB+16 */
+	Rblen64K	= 0x00001800,	/* 64KB+16 */
+	RxfthSHIFT	= 13,		/* Receive Buffer Length */
+	RxfthMASK	= 0x0000E000,
+	Rxfth256	= 0x00008000,
+	Rxfthnone	= 0x0000E000,
+	Rer8		= 0x00010000,	/* Accept Error Packets > 8 bytes */
+	MulERINT	= 0x00020000,	/* Multiple Early Interrupt Select */
+	ErxthSHIFT	= 24,		/* Early Rx Threshold */
+	ErxthMASK	= 0x0F000000,
+	Erxthnone	= 0x00000000,
+};
+
+enum {					/* Received Packet Status */
+	Rcok		= 0x0001,	/* Receive Completed OK */
+	Fae		= 0x0002,	/* Frame Alignment Error */
+	Crc		= 0x0004,	/* CRC Error */
+	Long		= 0x0008,	/* Long Packet */
+	Runt		= 0x0010,	/* Runt Packet Received */
+	Ise		= 0x0020,	/* Invalid Symbol Error */
+	Bar		= 0x2000,	/* Broadcast Address Received */
+	Pam		= 0x4000,	/* Physical Address Matched */
+	Mar		= 0x8000,	/* Multicast Address Received */
+};
+
+enum {					/* Media Status Register */
+	Rxpf		= 0x01,		/* Pause Flag */
+	Txpf		= 0x02,		/* Pause Flag */
+	Linkb		= 0x04,		/* Inverse of Link Status */
+	Speed10		= 0x08,		/* 10Mbps */
+	Auxstatus	= 0x10,		/* Aux. Power Present Status */
+	Rxfce		= 0x40,		/* Receive Flow Control Enable */
+	Txfce		= 0x80,		/* Transmit Flow Control Enable */
+};
+
+typedef struct {			/* Soft Transmit Descriptor */
+	int	tsd;
+	int	tsad;
+	uchar*	data;
+} Td;
+
+enum {					/* Tsd0 */
+	SizeSHIFT	= 0,		/* Descriptor Size */
+	SizeMASK	= 0x00001FFF,
+	Own		= 0x00002000,
+	Tun		= 0x00004000,	/* Transmit FIFO Underrun */
+	Tcok		= 0x00008000,	/* Transmit COmpleted OK */
+	EtxthSHIFT	= 16,		/* Early Tx Threshold */
+	EtxthMASK	= 0x001F0000,
+	NccSHIFT	= 24,		/* Number of Collisions Count */
+	NccMASK		= 0x0F000000,
+	Cdh		= 0x10000000,	/* CD Heartbeat */
+	Owc		= 0x20000000,	/* Out of Window Collision */
+	Tabt		= 0x40000000,	/* Transmit Abort */
+	Crs		= 0x80000000,	/* Carrier Sense Lost */
+};
+
+enum {
+	Rblen		= Rblen64K,	/* Receive Buffer Length */
+	Ntd		= 4,		/* Number of Transmit Descriptors */
+	Tdbsz		= ROUNDUP(sizeof(Etherpkt), 4),
+};
+
+typedef struct Ctlr Ctlr;
+typedef struct Ctlr {
+	int	port;
+	Pcidev*	pcidev;
+	Ctlr*	next;
+	int	active;
+	int	id;
+
+	Lock	ilock;			/* init */
+	void*	alloc;			/* base of per-Ctlr allocated data */
+
+	int	rcr;			/* receive configuration register */
+	uchar*	rbstart;		/* receive buffer */
+	int	rblen;			/* receive buffer length */
+	int	ierrs;			/* receive errors */
+
+	Lock	tlock;			/* transmit */
+	Td	td[Ntd];
+	int	ntd;			/* descriptors active */
+	int	tdh;			/* host index into td */
+	int	tdi;			/* interface index into td */
+	int	etxth;			/* early transmit threshold */
+	int	taligned;		/* packet required no alignment */
+	int	tunaligned;		/* packet required alignment */
+
+	int	dis;			/* disconnect counter */
+	int	fcsc;			/* false carrier sense counter */
+	int	rec;			/* RX_ER counter */
+} Ctlr;
+
+static Ctlr* ctlrhead;
+static Ctlr* ctlrtail;
+
+#define csr8r(c, r)	(inb((c)->port+(r)))
+#define csr16r(c, r)	(ins((c)->port+(r)))
+#define csr32r(c, r)	(inl((c)->port+(r)))
+#define csr8w(c, r, b)	(outb((c)->port+(r), (int)(b)))
+#define csr16w(c, r, w)	(outs((c)->port+(r), (ushort)(w)))
+#define csr32w(c, r, l)	(outl((c)->port+(r), (ulong)(l)))
+
+static int
+rtl8139reset(Ctlr* ctlr)
+{
+	/*
+	 * Soft reset the controller.
+	 */
+	csr8w(ctlr, Cr, Rst);
+	while(csr8r(ctlr, Cr) & Rst)
+		;
+
+	return 0;
+}
+
+static void
+rtl8139detach(Ether* edev)
+{
+	rtl8139reset(edev->ctlr);
+}
+
+static void
+rtl8139halt(Ctlr* ctlr)
+{
+	csr8w(ctlr, Cr, 0);
+	csr16w(ctlr, Imr, 0);
+	csr16w(ctlr, Isr, ~0);
+}
+
+static void
+rtl8139init(Ether* edev)
+{
+	int i;
+	ulong r;
+	Ctlr *ctlr;
+	uchar *alloc;
+
+	ctlr = edev->ctlr;
+	ilock(&ctlr->ilock);
+
+	rtl8139halt(ctlr);
+
+	/*
+	 * MAC Address.
+	 */
+	r = (edev->ea[3]<<24)|(edev->ea[2]<<16)|(edev->ea[1]<<8)|edev->ea[0];
+	csr32w(ctlr, Idr0, r);
+	r = (edev->ea[5]<<8)|edev->ea[4];
+	csr32w(ctlr, Idr0+4, r);
+
+	/*
+	 * Receiver
+	 */
+	alloc = (uchar*)ROUNDUP((ulong)ctlr->alloc, 32);
+	ctlr->rbstart = alloc;
+	alloc += ctlr->rblen+16;
+	memset(ctlr->rbstart, 0, ctlr->rblen+16);
+	csr32w(ctlr, Rbstart, PADDR(ctlr->rbstart));
+	ctlr->rcr = Rxfth256|Rblen|Mrxdmaunlimited|Ab|Apm;
+
+	/*
+	 * Transmitter.
+	 */
+	for(i = 0; i < Ntd; i++){
+		ctlr->td[i].tsd = Tsd0+i*4;
+		ctlr->td[i].tsad = Tsad0+i*4;
+		ctlr->td[i].data = alloc;
+		alloc += Tdbsz;
+	}
+	ctlr->ntd = ctlr->tdh = ctlr->tdi = 0;
+	ctlr->etxth = 128/32;
+
+	/*
+	 * Interrupts.
+	 */
+	csr32w(ctlr, TimerInt, 0);
+	csr16w(ctlr, Imr, Serr|Timer|Fovw|PunLc|Rxovw|Ter|Tok|Rer|Rok);
+	csr32w(ctlr, Mpc, 0);
+
+	/*
+	 * Enable receiver/transmitter.
+	 * Need to enable before writing the Rcr or it won't take.
+	 */
+	csr8w(ctlr, Cr, Te|Re);
+	csr32w(ctlr, Tcr, Mtxdma2048);
+	csr32w(ctlr, Rcr, ctlr->rcr);
+
+	iunlock(&ctlr->ilock);
+}
+
+static void
+rtl8139attach(Ether* edev)
+{
+	Ctlr *ctlr;
+
+	ctlr = edev->ctlr;
+	if(ctlr->alloc == nil){
+		ctlr->rblen = 1<<((Rblen>>RblenSHIFT)+13);
+		ctlr->alloc = mallocz(ctlr->rblen+16 + Ntd*Tdbsz + 32, 0);
+		rtl8139init(edev);
+	}
+}
+
+static void
+rtl8139txstart(Ether* edev)
+{
+	Td *td;
+	Ctlr *ctlr;
+	RingBuf *tb;
+
+	ctlr = edev->ctlr;
+	while(ctlr->ntd < Ntd){
+		tb = &edev->tb[edev->ti];
+		if(tb->owner != Interface)
+			break;
+
+		td = &ctlr->td[ctlr->tdh];
+		memmove(td->data, tb->pkt, tb->len);
+		csr32w(ctlr, td->tsad, PADDR(tb->pkt));
+		csr32w(ctlr, td->tsd, (ctlr->etxth<<EtxthSHIFT)|tb->len);
+
+		ctlr->ntd++;
+		ctlr->tdh = NEXT(ctlr->tdh, Ntd);
+		tb->owner = Host;
+		edev->ti = NEXT(edev->ti, edev->ntb);
+	}
+}
+
+static void
+rtl8139transmit(Ether* edev)
+{
+	Ctlr *ctlr;
+
+	ctlr = edev->ctlr;
+	ilock(&ctlr->tlock);
+	rtl8139txstart(edev);
+	iunlock(&ctlr->tlock);
+}
+
+static void
+rtl8139receive(Ether* edev)
+{
+	Ctlr *ctlr;
+	RingBuf *rb;
+	ushort capr;
+	uchar cr, *p;
+	int l, length, status;
+
+	ctlr = edev->ctlr;
+
+	/*
+	 * Capr is where the host is reading from,
+	 * Cbr is where the NIC is currently writing.
+	 */
+	capr = (csr16r(ctlr, Capr)+16) % ctlr->rblen;
+	while(!(csr8r(ctlr, Cr) & Bufe)){
+		p = ctlr->rbstart+capr;
+
+		/*
+		 * Apparently the packet length may be 0xFFF0 if
+		 * the NIC is still copying the packet into memory.
+		 */
+		length = (*(p+3)<<8)|*(p+2);
+		if(length == 0xFFF0)
+			break;
+		status = (*(p+1)<<8)|*p;
+
+		if(!(status & Rcok)){
+			/*
+			 * Reset the receiver.
+			 * Also may have to restore the multicast list
+			 * here too if it ever gets used.
+			 */
+			cr = csr8r(ctlr, Cr);
+			csr8w(ctlr, Cr, cr & ~Re);
+			csr32w(ctlr, Rbstart, PADDR(ctlr->rbstart));
+			csr8w(ctlr, Cr, cr);
+			csr32w(ctlr, Rcr, ctlr->rcr);
+
+			continue;
+		}
+
+		/*
+		 * Receive Completed OK.
+		 * Very simplistic; there are ways this could be done
+		 * without copying, but the juice probably isn't worth
+		 * the squeeze.
+		 * The packet length includes a 4 byte CRC on the end.
+		 */
+		capr = (capr+4) % ctlr->rblen;
+		p = ctlr->rbstart+capr;
+		capr = (capr+length) % ctlr->rblen;
+
+		rb = &edev->rb[edev->ri];
+		l = 0;
+		if(p+length >= ctlr->rbstart+ctlr->rblen){
+			l = ctlr->rbstart+ctlr->rblen - p;
+			if(rb->owner == Interface)
+				memmove(rb->pkt, p, l);
+			length -= l;
+			p = ctlr->rbstart;
+		}
+		if(length > 0 && rb->owner == Interface){
+			memmove(rb->pkt+l, p, length);
+			l += length;
+		}
+		if(rb->owner == Interface){
+			rb->owner = Host;
+			rb->len = l-4;
+			edev->ri = NEXT(edev->ri, edev->nrb);
+		}
+
+		capr = ROUNDUP(capr, 4);
+		csr16w(ctlr, Capr, capr-16);
+	}
+}
+
+static void
+rtl8139interrupt(Ureg*, void* arg)
+{
+	Td *td;
+	Ctlr *ctlr;
+	Ether *edev;
+	int isr, tsd;
+
+	edev = arg;
+	ctlr = edev->ctlr;
+
+	while((isr = csr16r(ctlr, Isr)) != 0){
+		csr16w(ctlr, Isr, isr);
+		if(isr & (Fovw|PunLc|Rxovw|Rer|Rok)){
+			rtl8139receive(edev);
+			if(!(isr & Rok))
+				ctlr->ierrs++;
+			isr &= ~(Fovw|Rxovw|Rer|Rok);
+		}
+
+		if(isr & (Ter|Tok)){
+			ilock(&ctlr->tlock);
+			while(ctlr->ntd){
+				td = &ctlr->td[ctlr->tdi];
+				tsd = csr32r(ctlr, td->tsd);
+				if(!(tsd & (Tabt|Tun|Tcok)))
+					break;
+
+				if(!(tsd & Tcok)){
+					if(tsd & Tun){
+						if(ctlr->etxth < ETHERMAXTU/32)
+							ctlr->etxth++;
+					}
+				}
+
+				ctlr->ntd--;
+				ctlr->tdi = NEXT(ctlr->tdi, Ntd);
+			}
+			rtl8139txstart(edev);
+			iunlock(&ctlr->tlock);
+			isr &= ~(Ter|Tok);
+		}
+
+		if(isr & PunLc)
+			isr &= ~(Clc|PunLc);
+
+		/*
+		 * Only Serr|Timer should be left by now.
+		 * Should anything be done to tidy up? TimerInt isn't
+		 * used so that can be cleared. A PCI bus error is indicated
+		 * by Serr, that's pretty serious; is there anyhing to do
+		 * other than try to reinitialise the chip?
+		 */
+		if((isr & (Serr|Timer)) != 0){
+			print("rtl8139interrupt: imr %4.4uX isr %4.4uX\n",
+				csr16r(ctlr, Imr), isr);
+			if(isr & Timer)
+				csr32w(ctlr, TimerInt, 0);
+			if(isr & Serr)
+				rtl8139init(edev);
+		}
+	}
+}
+
+static Ctlr*
+rtl8139match(Ether* edev, int id)
+{
+	int port;
+	Pcidev *p;
+	Ctlr *ctlr;
+
+	/*
+	 * Any adapter matches if no edev->port is supplied,
+	 * otherwise the ports must match.
+	 */
+	for(ctlr = ctlrhead; ctlr != nil; ctlr = ctlr->next){
+		if(ctlr->active)
+			continue;
+		p = ctlr->pcidev;
+		if(((p->did<<16)|p->vid) != id)
+			continue;
+		port = p->mem[0].bar & ~0x01;
+		if(edev->port != 0 && edev->port != port)
+			continue;
+
+		ctlr->port = port;
+		if(rtl8139reset(ctlr))
+			continue;
+		pcisetbme(p);
+
+		ctlr->active = 1;
+		return ctlr;
+	}
+	return nil;
+}
+
+static struct {
+	char*	name;
+	int	id;
+} rtl8139pci[] = {
+	{ "rtl8139",	(0x8139<<16)|0x10EC, },	/* generic */
+	{ "smc1211",	(0x1211<<16)|0x1113, },	/* SMC EZ-Card */
+	{ "dfe-538tx",	(0x1300<<16)|0x1186, }, /* D-Link DFE-538TX */
+	{ "dfe-560txd",	(0x1340<<16)|0x1186, }, /* D-Link DFE-560TXD */
+	{ nil },
+};
+
+int
+rtl8139pnp(Ether* edev)
+{
+	int i, id;
+	Pcidev *p;
+	Ctlr *ctlr;
+	uchar ea[Eaddrlen];
+
+	/*
+	 * Make a list of all ethernet controllers
+	 * if not already done.
+	 */
+	if(ctlrhead == nil){
+		p = nil;
+		while(p = pcimatch(p, 0, 0)){
+			if(p->ccrb != 0x02 || p->ccru != 0)
+				continue;
+			ctlr = malloc(sizeof(Ctlr));
+			ctlr->pcidev = p;
+			ctlr->id = (p->did<<16)|p->vid;
+
+			if(ctlrhead != nil)
+				ctlrtail->next = ctlr;
+			else
+				ctlrhead = ctlr;
+			ctlrtail = ctlr;
+		}
+	}
+
+	/*
+	 * Is it an RTL8139 under a different name?
+	 * Normally a search is made through all the found controllers
+	 * for one which matches any of the known vid+did pairs.
+	 * If a vid+did pair is specified a search is made for that
+	 * specific controller only.
+	 */
+	id = 0;
+	for(i = 0; i < edev->nopt; i++){
+		if(cistrncmp(edev->opt[i], "id=", 3) == 0)
+			id = strtol(&edev->opt[i][3], nil, 0);
+	}
+
+	ctlr = nil;
+	if(id != 0)
+		ctlr = rtl8139match(edev, id);
+	else for(i = 0; rtl8139pci[i].name; i++){
+		if((ctlr = rtl8139match(edev, rtl8139pci[i].id)) != nil)
+			break;
+	}
+	if(ctlr == nil)
+		return -1;
+
+	edev->ctlr = ctlr;
+	edev->port = ctlr->port;
+	edev->irq = ctlr->pcidev->intl;
+	edev->tbdf = ctlr->pcidev->tbdf;
+
+	/*
+	 * Check if the adapter's station address is to be overridden.
+	 * If not, read it from the device and set in edev->ea.
+	 */
+	memset(ea, 0, Eaddrlen);
+	if(memcmp(ea, edev->ea, Eaddrlen) == 0){
+		i = csr32r(ctlr, Idr0);
+		edev->ea[0] = i;
+		edev->ea[1] = i>>8;
+		edev->ea[2] = i>>16;
+		edev->ea[3] = i>>24;
+		i = csr32r(ctlr, Idr0+4);
+		edev->ea[4] = i;
+		edev->ea[5] = i>>8;
+	}
+
+	edev->attach = rtl8139attach;
+	edev->transmit = rtl8139transmit;
+	edev->interrupt = rtl8139interrupt;
+	edev->detach = rtl8139detach;
+
+	return 0;
+}
--- /dev/null
+++ b/os/boot.original/pc/ether8169.c
@@ -1,0 +1,958 @@
+/*
+ * Realtek RTL8110S/8169S.
+ * Mostly there. There are some magic register values used
+ * which are not described in any datasheet or driver but seem
+ * to be necessary.
+ * Why is the Fovf descriptor bit set for every received packet?
+ * Occasionally the hardware indicates an input TCP checksum error
+ * although the higher-level software seems to check the packet OK?
+ * No tuning has been done. Only tested on an RTL8110S, there
+ * are slight differences between the chips in the series so some
+ * tweaks may be needed.
+ */
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+typedef struct QLock { int r; } QLock;
+#define qlock(i)	while(0)
+#define qunlock(i)	while(0)
+#define iallocb		allocb
+#define iprint		print
+#define mallocalign(n, a, o, s)	ialloc((n), (a))
+
+#include "etherif.h"
+#include "ethermii.h"
+
+enum {					/* registers */
+	Idr0		= 0x00,		/* MAC address */
+	Mar0		= 0x08,		/* Multicast address */
+	Dtccr		= 0x10,		/* Dump Tally Counter Command */
+	Tnpds		= 0x20,		/* Transmit Normal Priority Descriptors */
+	Thpds		= 0x28,		/* Transmit High Priority Descriptors */
+	Flash		= 0x30,		/* Flash Memory Read/Write */
+	Erbcr		= 0x34,		/* Early Receive Byte Count */
+	Ersr		= 0x36,		/* Early Receive Status */
+	Cr		= 0x37,		/* Command Register */
+	Tppoll		= 0x38,		/* Transmit Priority Polling */
+	Imr		= 0x3C,		/* Interrupt Mask */
+	Isr		= 0x3E,		/* Interrupt Status */
+	Tcr		= 0x40,		/* Transmit Configuration */
+	Rcr		= 0x44,		/* Receive Configuration */
+	Tctr		= 0x48,		/* Timer Count */
+	Mpc		= 0x4C,		/* Missed Packet Counter */
+	Cr9346		= 0x50,		/* 9346 Command Register */
+	Config0		= 0x51,		/* Configuration Register 0 */
+	Config1		= 0x52,		/* Configuration Register 1 */
+	Config2		= 0x53,		/* Configuration Register 2 */
+	Config3		= 0x54,		/* Configuration Register 3 */
+	Config4		= 0x55,		/* Configuration Register 4 */
+	Config5		= 0x56,		/* Configuration Register 5 */
+	Timerint	= 0x58,		/* Timer Interrupt */
+	Mulint		= 0x5C,		/* Multiple Interrupt Select */
+	Phyar		= 0x60,		/* PHY Access */
+	Tbicsr0		= 0x64,		/* TBI Control and Status */
+	Tbianar		= 0x68,		/* TBI Auto-Negotiation Advertisment */
+	Tbilpar		= 0x6A,		/* TBI Auto-Negotiation Link Partner */
+	Phystatus	= 0x6C,		/* PHY Status */
+
+	Rms		= 0xDA,		/* Receive Packet Maximum Size */
+	Cplusc		= 0xE0,		/* C+ Command */
+	Rdsar		= 0xE4,		/* Receive Descriptor Start Address */
+	Mtps		= 0xEC,		/* Max. Transmit Packet Size */
+};
+
+enum {					/* Dtccr */
+	Cmd		= 0x00000008,	/* Command */
+};
+
+enum {					/* Cr */
+	Te		= 0x04,		/* Transmitter Enable */
+	Re		= 0x08,		/* Receiver Enable */
+	Rst		= 0x10,		/* Software Reset */
+};
+
+enum {					/* Tppoll */
+	Fswint		= 0x01,		/* Forced Software Interrupt */
+	Npq		= 0x40,		/* Normal Priority Queue polling */
+	Hpq		= 0x80,		/* High Priority Queue polling */
+};
+
+enum {					/* Imr/Isr */
+	Rok		= 0x0001,	/* Receive OK */
+	Rer		= 0x0002,	/* Receive Error */
+	Tok		= 0x0004,	/* Transmit OK */
+	Ter		= 0x0008,	/* Transmit Error */
+	Rdu		= 0x0010,	/* Receive Descriptor Unavailable */
+	Punlc		= 0x0020,	/* Packet Underrun or Link Change */
+	Fovw		= 0x0040,	/* Receive FIFO Overflow */
+	Tdu		= 0x0080,	/* Transmit Descriptor Unavailable */
+	Swint		= 0x0100,	/* Software Interrupt */
+	Timeout		= 0x4000,	/* Timer */
+	Serr		= 0x8000,	/* System Error */
+};
+
+enum {					/* Tcr */
+	MtxdmaSHIFT	= 8,		/* Max. DMA Burst Size */
+	MtxdmaMASK	= 0x00000700,
+	Mtxdmaunlimited	= 0x00000700,
+	Acrc		= 0x00010000,	/* Append CRC (not) */
+	Lbk0		= 0x00020000,	/* Loopback Test 0 */
+	Lbk1		= 0x00040000,	/* Loopback Test 1 */
+	Ifg2		= 0x00080000,	/* Interframe Gap 2 */
+	HwveridSHIFT	= 23,		/* Hardware Version ID */
+	HwveridMASK	= 0x7C800000,
+	Macv01		= 0x00000000,	/* RTL8169 */
+	Macv02		= 0x00800000,	/* RTL8169S/8110S */
+	Macv03		= 0x04000000,	/* RTL8169S/8110S */
+	Macv04		= 0x10000000,	/* RTL8169SB/8110SB */
+	Macv05		= 0x18000000,	/* RTL8169SC/8110SC */
+	Macv11		= 0x30000000,	/* RTL8168B/8111B */
+	Macv12		= 0x38000000,	/* RTL8169B/8111B */
+	Macv13		= 0x34000000,	/* RTL8101E */
+	Macv14		= 0x30800000,	/* RTL8100E */
+	Macv15		= 0x38800000,	/* RTL8100E */
+	Ifg0		= 0x01000000,	/* Interframe Gap 0 */
+	Ifg1		= 0x02000000,	/* Interframe Gap 1 */
+};
+
+enum {					/* Rcr */
+	Aap		= 0x00000001,	/* Accept All Packets */
+	Apm		= 0x00000002,	/* Accept Physical Match */
+	Am		= 0x00000004,	/* Accept Multicast */
+	Ab		= 0x00000008,	/* Accept Broadcast */
+	Ar		= 0x00000010,	/* Accept Runt */
+	Aer		= 0x00000020,	/* Accept Error */
+	Sel9356		= 0x00000040,	/* 9356 EEPROM used */
+	MrxdmaSHIFT	= 8,		/* Max. DMA Burst Size */
+	MrxdmaMASK	= 0x00000700,
+	Mrxdmaunlimited	= 0x00000700,
+	RxfthSHIFT	= 13,		/* Receive Buffer Length */
+	RxfthMASK	= 0x0000E000,
+	Rxfth256	= 0x00008000,
+	Rxfthnone	= 0x0000E000,
+	Rer8		= 0x00010000,	/* Accept Error Packets > 8 bytes */
+	MulERINT	= 0x01000000,	/* Multiple Early Interrupt Select */
+};
+
+enum {					/* Cr9346 */
+	Eedo		= 0x01,		/* */
+	Eedi		= 0x02,		/* */
+	Eesk		= 0x04,		/* */
+	Eecs		= 0x08,		/* */
+	Eem0		= 0x40,		/* Operating Mode */
+	Eem1		= 0x80,
+};
+
+enum {					/* Phyar */
+	DataMASK	= 0x0000FFFF,	/* 16-bit GMII/MII Register Data */
+	DataSHIFT	= 0,
+	RegaddrMASK	= 0x001F0000,	/* 5-bit GMII/MII Register Address */
+	RegaddrSHIFT	= 16,
+	Flag		= 0x80000000,	/* */
+};
+
+enum {					/* Phystatus */
+	Fd		= 0x01,		/* Full Duplex */
+	Linksts		= 0x02,		/* Link Status */
+	Speed10		= 0x04,		/* */
+	Speed100	= 0x08,		/* */
+	Speed1000	= 0x10,		/* */
+	Rxflow		= 0x20,		/* */
+	Txflow		= 0x40,		/* */
+	Entbi		= 0x80,		/* */
+};
+
+enum {					/* Cplusc */
+	Mulrw		= 0x0008,	/* PCI Multiple R/W Enable */
+	Dac		= 0x0010,	/* PCI Dual Address Cycle Enable */
+	Rxchksum	= 0x0020,	/* Receive Checksum Offload Enable */
+	Rxvlan		= 0x0040,	/* Receive VLAN De-tagging Enable */
+	Endian		= 0x0200,	/* Endian Mode */
+};
+
+typedef struct D D;			/* Transmit/Receive Descriptor */
+struct D {
+	u32	control;
+	u32	vlan;
+	u32	addrlo;
+	u32	addrhi;
+};
+
+enum {					/* Transmit Descriptor control */
+	TxflMASK	= 0x0000FFFF,	/* Transmit Frame Length */
+	TxflSHIFT	= 0,
+	Tcps		= 0x00010000,	/* TCP Checksum Offload */
+	Udpcs		= 0x00020000,	/* UDP Checksum Offload */
+	Ipcs		= 0x00040000,	/* IP Checksum Offload */
+	Lgsen		= 0x08000000,	/* Large Send */
+};
+
+enum {					/* Receive Descriptor control */
+	RxflMASK	= 0x00003FFF,	/* Receive Frame Length */
+	RxflSHIFT	= 0,
+	Tcpf		= 0x00004000,	/* TCP Checksum Failure */
+	Udpf		= 0x00008000,	/* UDP Checksum Failure */
+	Ipf		= 0x00010000,	/* IP Checksum Failure */
+	Pid0		= 0x00020000,	/* Protocol ID0 */
+	Pid1		= 0x00040000,	/* Protocol ID1 */
+	Crce		= 0x00080000,	/* CRC Error */
+	Runt		= 0x00100000,	/* Runt Packet */
+	Res		= 0x00200000,	/* Receive Error Summary */
+	Rwt		= 0x00400000,	/* Receive Watchdog Timer Expired */
+	Fovf		= 0x00800000,	/* FIFO Overflow */
+	Bovf		= 0x01000000,	/* Buffer Overflow */
+	Bar		= 0x02000000,	/* Broadcast Address Received */
+	Pam		= 0x04000000,	/* Physical Address Matched */
+	Mar		= 0x08000000,	/* Multicast Address Received */
+};
+
+enum {					/* General Descriptor control */
+	Ls		= 0x10000000,	/* Last Segment Descriptor */
+	Fs		= 0x20000000,	/* First Segment Descriptor */
+	Eor		= 0x40000000,	/* End of Descriptor Ring */
+	Own		= 0x80000000,	/* Ownership */
+};
+
+/*
+ */
+enum {					/* Ring sizes  (<= 1024) */
+	Ntd		= 8,		/* Transmit Ring */
+	Nrd		= 32,		/* Receive Ring */
+
+	Mps		= ROUNDUP(ETHERMAXTU+4, 128),
+};
+
+typedef struct Dtcc Dtcc;
+struct Dtcc {
+	u64int	txok;
+	u64int	rxok;
+	u64int	txer;
+	u32	rxer;
+	u16int	misspkt;
+	u16int	fae;
+	u32	tx1col;
+	u32	txmcol;
+	u64int	rxokph;
+	u64int	rxokbrd;
+	u32	rxokmu;
+	u16int	txabt;
+	u16int	txundrn;
+};
+
+enum {						/* Variants */
+	Rtl8100e	= (0x8136<<16)|0x10EC,	/* RTL810[01]E ? */
+	Rtl8169c		= (0x0116<<16)|0x16EC,	/* RTL8169C+ (USR997902) */
+	Rtl8169sc	= (0x8167<<16)|0x10EC,	/* RTL8169SC */
+	Rtl8168b	= (0x8168<<16)|0x10EC,	/* RTL8168B */
+	Rtl8169		= (0x8169<<16)|0x10EC,	/* RTL8169 */
+};
+
+typedef struct Ctlr Ctlr;
+typedef struct Ctlr {
+	int	port;
+	Pcidev*	pcidev;
+	Ctlr*	next;
+	int	active;
+
+	void*	nic;
+
+	QLock	alock;			/* attach */
+	Lock	ilock;			/* init */
+	int	init;			/*  */
+
+	int	pciv;			/*  */
+	int	macv;			/* MAC version */
+	int	phyv;			/* PHY version */
+
+	Mii*	mii;
+
+	Lock	tlock;			/* transmit */
+	D*	td;			/* descriptor ring */
+	Block**	tb;			/* transmit buffers */
+	int	ntd;
+
+	int	tdh;			/* head - producer index (host) */
+	int	tdt;			/* tail - consumer index (NIC) */
+	int	ntdfree;
+	int	ntq;
+
+	int	mtps;			/* Max. Transmit Packet Size */
+
+	Lock	rlock;			/* receive */
+	D*	rd;			/* descriptor ring */
+	void**	rb;			/* receive buffers */
+	int	nrd;
+
+	int	rdh;			/* head - producer index (NIC) */
+	int	rdt;			/* tail - consumer index (host) */
+	int	nrdfree;
+
+	int	rcr;			/* receive configuration register */
+
+	QLock	slock;			/* statistics */
+	Dtcc*	dtcc;
+	uint	txdu;
+	uint	tcpf;
+	uint	udpf;
+	uint	ipf;
+	uint	fovf;
+	uint	ierrs;
+	uint	rer;
+	uint	rdu;
+	uint	punlc;
+	uint	fovw;
+} Ctlr;
+
+static Ctlr* rtl8169ctlrhead;
+static Ctlr* rtl8169ctlrtail;
+
+#define csr8r(c, r)	(inb((c)->port+(r)))
+#define csr16r(c, r)	(ins((c)->port+(r)))
+#define csr32r(c, r)	(inl((c)->port+(r)))
+#define csr8w(c, r, b)	(outb((c)->port+(r), (int)(b)))
+#define csr16w(c, r, w)	(outs((c)->port+(r), (ushort)(w)))
+#define csr32w(c, r, l)	(outl((c)->port+(r), (ulong)(l)))
+
+static int
+rtl8169miimir(Mii* mii, int pa, int ra)
+{
+	uint r;
+	int timeo;
+	Ctlr *ctlr;
+
+	if(pa != 1)
+		return -1;
+	ctlr = mii->ctlr;
+
+	r = (ra<<16) & RegaddrMASK;
+	csr32w(ctlr, Phyar, r);
+	delay(1);
+	for(timeo = 0; timeo < 2000; timeo++){
+		if((r = csr32r(ctlr, Phyar)) & Flag)
+			break;
+		microdelay(100);
+	}
+	if(!(r & Flag))
+		return -1;
+
+	return (r & DataMASK)>>DataSHIFT;
+}
+
+static int
+rtl8169miimiw(Mii* mii, int pa, int ra, int data)
+{
+	uint r;
+	int timeo;
+	Ctlr *ctlr;
+
+	if(pa != 1)
+		return -1;
+	ctlr = mii->ctlr;
+
+	r = Flag|((ra<<16) & RegaddrMASK)|((data<<DataSHIFT) & DataMASK);
+	csr32w(ctlr, Phyar, r);
+	delay(1);
+	for(timeo = 0; timeo < 2000; timeo++){
+		if(!((r = csr32r(ctlr, Phyar)) & Flag))
+			break;
+		microdelay(100);
+	}
+	if(r & Flag)
+		return -1;
+
+	return 0;
+}
+
+static int
+rtl8169mii(Ctlr* ctlr)
+{
+	MiiPhy *phy;
+
+	/*
+	 * Link management.
+	 */
+	if((ctlr->mii = malloc(sizeof(Mii))) == nil)
+		return -1;
+	ctlr->mii->mir = rtl8169miimir;
+	ctlr->mii->miw = rtl8169miimiw;
+	ctlr->mii->ctlr = ctlr;
+
+	/*
+	 * Get rev number out of Phyidr2 so can config properly.
+	 * There's probably more special stuff for Macv0[234] needed here.
+	 */
+	ctlr->phyv = rtl8169miimir(ctlr->mii, 1, Phyidr2) & 0x0F;
+	if(ctlr->macv == Macv02){
+		csr8w(ctlr, 0x82, 1);				/* magic */
+		rtl8169miimiw(ctlr->mii, 1, 0x0B, 0x0000);	/* magic */
+	}
+
+	if(mii(ctlr->mii, (1<<1)) == 0 || (phy = ctlr->mii->curphy) == nil){
+		free(ctlr->mii);
+		ctlr->mii = nil;
+		return -1;
+	}
+	print("oui %#ux phyno %d, macv = %#8.8ux phyv = %#4.4ux\n",
+		phy->oui, phy->phyno, ctlr->macv, ctlr->phyv);
+
+	miiane(ctlr->mii, ~0, ~0, ~0);
+
+	return 0;
+}
+
+static void
+rtl8169halt(Ctlr* ctlr)
+{
+	csr8w(ctlr, Cr, 0);
+	csr16w(ctlr, Imr, 0);
+	csr16w(ctlr, Isr, ~0);
+}
+
+static int
+rtl8169reset(Ctlr* ctlr)
+{
+	u32 r;
+	int timeo;
+
+	/*
+	 * Soft reset the controller.
+	 */
+	csr8w(ctlr, Cr, Rst);
+	for(r = timeo = 0; timeo < 1000; timeo++){
+		r = csr8r(ctlr, Cr);
+		if(!(r & Rst))
+			break;
+		delay(1);
+	}
+	rtl8169halt(ctlr);
+
+	if(r & Rst)
+		return -1;
+	return 0;
+}
+
+static void
+rtl8169detach(Ether* edev)
+{
+	rtl8169reset(edev->ctlr);
+}
+
+static void
+rtl8169replenish(Ctlr* ctlr)
+{
+	D *d;
+	int rdt;
+	void *bp;
+
+	rdt = ctlr->rdt;
+	while(NEXT(rdt, ctlr->nrd) != ctlr->rdh){
+		d = &ctlr->rd[rdt];
+		if(ctlr->rb[rdt] == nil){
+			/*
+			 * simple allocation for now
+			 */
+			bp = mallocalign(Mps, 8, 0, 0);
+			ctlr->rb[rdt] = bp;
+			d->addrlo = PCIWADDR(bp);
+			d->addrhi = 0;
+		}
+		coherence();
+		d->control |= Own|Mps;
+		rdt = NEXT(rdt, ctlr->nrd);
+		ctlr->nrdfree++;
+	}
+	ctlr->rdt = rdt;
+}
+
+static int
+rtl8169init(Ether* edev)
+{
+	u32 r;
+	Ctlr *ctlr;
+	u8int cplusc;
+
+	ctlr = edev->ctlr;
+	ilock(&ctlr->ilock);
+
+	rtl8169halt(ctlr);
+
+	/*
+	 * MAC Address.
+	 * Must put chip into config register write enable mode.
+	 */
+	csr8w(ctlr, Cr9346, Eem1|Eem0);
+	r = (edev->ea[3]<<24)|(edev->ea[2]<<16)|(edev->ea[1]<<8)|edev->ea[0];
+	csr32w(ctlr, Idr0, r);
+	r = (edev->ea[5]<<8)|edev->ea[4];
+	csr32w(ctlr, Idr0+4, r);
+
+	/*
+	 * Transmitter.
+	 */
+	memset(ctlr->td, 0, sizeof(D)*ctlr->ntd);
+	ctlr->tdh = ctlr->tdt = 0;
+	ctlr->td[ctlr->ntd-1].control = Eor;
+
+	/*
+	 * Receiver.
+	 * Need to do something here about the multicast filter.
+	 */
+	memset(ctlr->rd, 0, sizeof(D)*ctlr->nrd);
+	ctlr->rdh = ctlr->rdt = 0;
+	ctlr->rd[ctlr->nrd-1].control = Eor;
+	rtl8169replenish(ctlr);
+	ctlr->rcr = Rxfthnone|Mrxdmaunlimited|Ab|Apm;
+
+	/*
+	 * Mtps is in units of 128 except for the RTL8169
+	 * where is is 32. If using jumbo frames should be
+	 * set to 0x3F.
+	 * Setting Mulrw in Cplusc disables the Tx/Rx DMA burst
+	 * settings in Tcr/Rcr; the (1<<14) is magic.
+	 */
+	ctlr->mtps = HOWMANY(Mps, 128);
+	cplusc = csr16r(ctlr, Cplusc) & ~(1<<14);
+	cplusc |= Rxchksum|Mulrw;
+	switch(ctlr->macv){
+	default:
+		return -1;
+	case Macv01:
+		ctlr->mtps = HOWMANY(Mps, 32);
+		break;
+	case Macv02:
+	case Macv03:
+		cplusc |= (1<<14);			/* magic */
+		break;
+	case Macv05:
+		/*
+		 * This is interpreted from clearly bogus code
+		 * in the manufacturer-supplied driver, it could
+		 * be wrong. Untested.
+		 */
+		r = csr8r(ctlr, Config2) & 0x07;
+		if(r == 0x01)				/* 66MHz PCI */
+			csr32w(ctlr, 0x7C, 0x0007FFFF);	/* magic */
+		else
+			csr32w(ctlr, 0x7C, 0x0007FF00);	/* magic */
+		pciclrmwi(ctlr->pcidev);
+		break;
+	case Macv13:
+		/*
+		 * This is interpreted from clearly bogus code
+		 * in the manufacturer-supplied driver, it could
+		 * be wrong. Untested.
+		 */
+		pcicfgw8(ctlr->pcidev, 0x68, 0x00);	/* magic */
+		pcicfgw8(ctlr->pcidev, 0x69, 0x08);	/* magic */
+		break;
+	case Macv04:
+	case Macv11:
+	case Macv12:
+	case Macv14:
+	case Macv15:
+		break;
+	}
+
+	/*
+	 * Enable receiver/transmitter.
+	 * Need to do this first or some of the settings below
+	 * won't take.
+	 */
+	switch(ctlr->pciv){
+	default:
+		csr8w(ctlr, Cr, Te|Re);
+		csr32w(ctlr, Tcr, Ifg1|Ifg0|Mtxdmaunlimited);
+		csr32w(ctlr, Rcr, ctlr->rcr);
+	case Rtl8169sc:
+	case Rtl8168b:
+		break;
+	}
+
+	/*
+	 * Interrupts.
+	 * Disable Tdu|Tok for now, the transmit routine will tidy.
+	 * Tdu means the NIC ran out of descriptors to send, so it
+	 * doesn't really need to ever be on.
+	 */
+	csr32w(ctlr, Timerint, 0);
+	csr16w(ctlr, Imr, Serr|Timeout|Fovw|Punlc|Rdu|Ter|Rer|Rok);
+
+	/*
+	 * Clear missed-packet counter;
+	 * initial early transmit threshold value;
+	 * set the descriptor ring base addresses;
+	 * set the maximum receive packet size;
+	 * no early-receive interrupts.
+	 */
+	csr32w(ctlr, Mpc, 0);
+	csr8w(ctlr, Mtps, ctlr->mtps);
+	csr32w(ctlr, Tnpds+4, 0);
+	csr32w(ctlr, Tnpds, PCIWADDR(ctlr->td));
+	csr32w(ctlr, Rdsar+4, 0);
+	csr32w(ctlr, Rdsar, PCIWADDR(ctlr->rd));
+	csr16w(ctlr, Rms, Mps);
+	r = csr16r(ctlr, Mulint) & 0xF000;
+	csr16w(ctlr, Mulint, r);
+	csr16w(ctlr, Cplusc, cplusc);
+
+	/*
+	 * Set configuration.
+	 */
+	switch(ctlr->pciv){
+	default:
+		break;
+	case Rtl8169sc:
+		csr16w(ctlr, 0xE2, 0);			/* magic */
+		csr8w(ctlr, Cr, Te|Re);
+		csr32w(ctlr, Tcr, Ifg1|Ifg0|Mtxdmaunlimited);
+		csr32w(ctlr, Rcr, ctlr->rcr);
+		break;
+	case Rtl8168b:
+	case Rtl8169c:
+		csr16w(ctlr, 0xE2, 0);			/* magic */
+		csr16w(ctlr, Cplusc, 0x2000);		/* magic */
+		csr8w(ctlr, Cr, Te|Re);
+		csr32w(ctlr, Tcr, Ifg1|Ifg0|Mtxdmaunlimited);
+		csr32w(ctlr, Rcr, ctlr->rcr);
+		csr16w(ctlr, Rms, 0x0800);
+		csr8w(ctlr, Mtps, 0x3F);
+		break;
+	}
+
+	csr8w(ctlr, Cr9346, 0);
+
+	iunlock(&ctlr->ilock);
+
+//	rtl8169mii(ctlr);
+
+	return 0;
+}
+
+static void
+rtl8169attach(Ether* edev)
+{
+	int timeo;
+	Ctlr *ctlr;
+
+	ctlr = edev->ctlr;
+	qlock(&ctlr->alock);
+	if(ctlr->init == 0){
+		/*
+		 * Handle allocation/init errors here.
+		 */
+		ctlr->td = xspanalloc(sizeof(D)*Ntd, 256, 0);
+		ctlr->tb = malloc(Ntd*sizeof(Block*));
+		ctlr->ntd = Ntd;
+		ctlr->rd = xspanalloc(sizeof(D)*Nrd, 256, 0);
+		ctlr->rb = malloc(Nrd*sizeof(Block*));
+		ctlr->nrd = Nrd;
+		ctlr->dtcc = xspanalloc(sizeof(Dtcc), 64, 0);
+		rtl8169init(edev);
+		ctlr->init = 1;
+	}
+	qunlock(&ctlr->alock);
+
+	for(timeo = 0; timeo < 3500; timeo++){
+		if(miistatus(ctlr->mii) == 0)
+			break;
+		delay(10);
+	}
+}
+
+static void
+rtl8169transmit(Ether* edev)
+{
+	D *d;
+	Block *bp;
+	Ctlr *ctlr;
+	int control, x;
+	RingBuf *tb;
+
+	ctlr = edev->ctlr;
+
+	ilock(&ctlr->tlock);
+	for(x = ctlr->tdh; ctlr->ntq > 0; x = NEXT(x, ctlr->ntd)){
+		d = &ctlr->td[x];
+		if((control = d->control) & Own)
+			break;
+
+		/*
+		 * Check errors and log here.
+		 */
+		USED(control);
+
+		/*
+		 * Free it up.
+		 * Need to clean the descriptor here? Not really.
+		 * Simple freeb for now (no chain and freeblist).
+		 * Use ntq count for now.
+		 */
+		freeb(ctlr->tb[x]);
+		ctlr->tb[x] = nil;
+		d->control &= Eor;
+
+		ctlr->ntq--;
+	}
+	ctlr->tdh = x;
+
+	x = ctlr->tdt;
+	while(ctlr->ntq < (ctlr->ntd-1)){
+		tb = &edev->tb[edev->ti];
+		if(tb->owner != Interface)
+			break;
+
+		bp = allocb(tb->len);
+		memmove(bp->wp, tb->pkt, tb->len);
+		memmove(bp->wp+Eaddrlen, edev->ea, Eaddrlen);
+		bp->wp += tb->len;
+
+		tb->owner = Host;
+		edev->ti = NEXT(edev->ti, edev->ntb);
+
+		d = &ctlr->td[x];
+		d->addrlo = PCIWADDR(bp->rp);
+		d->addrhi = 0;
+		ctlr->tb[x] = bp;
+		coherence();
+		d->control |= Own|Fs|Ls|((BLEN(bp)<<TxflSHIFT) & TxflMASK);
+
+		x = NEXT(x, ctlr->ntd);
+		ctlr->ntq++;
+	}
+	if(x != ctlr->tdt){
+		ctlr->tdt = x;
+		csr8w(ctlr, Tppoll, Npq);
+	}
+	else if(ctlr->ntq >= (ctlr->ntd-1))
+		ctlr->txdu++;
+
+	iunlock(&ctlr->tlock);
+}
+
+static void
+rtl8169receive(Ether* edev)
+{
+	D *d;
+	int len, rdh;
+	Ctlr *ctlr;
+	u32 control;
+	RingBuf *ring;
+
+	ctlr = edev->ctlr;
+
+	rdh = ctlr->rdh;
+	for(;;){
+		d = &ctlr->rd[rdh];
+	
+		if(d->control & Own)
+			break;
+
+		control = d->control;
+		if((control & (Fs|Ls|Res)) == (Fs|Ls)){
+			len = ((control & RxflMASK)>>RxflSHIFT) - 4;
+
+			ring = &edev->rb[edev->ri];
+			if(ring->owner == Interface){
+				ring->owner = Host;
+				ring->len = len;
+				memmove(ring->pkt, ctlr->rb[rdh], len);
+				edev->ri = NEXT(edev->ri, edev->nrb);
+			}
+		}
+		else{
+			/*
+			 * Error stuff here.
+			print("control %#8.8ux\n", control);
+			 */
+		}
+		d->control &= Eor;
+		ctlr->nrdfree--;
+		rdh = NEXT(rdh, ctlr->nrd);
+	}
+	ctlr->rdh = rdh;
+	
+	if(ctlr->nrdfree < ctlr->nrd/2)
+		rtl8169replenish(ctlr);
+}
+
+static void
+rtl8169interrupt(Ureg*, void* arg)
+{
+	Ctlr *ctlr;
+	Ether *edev;
+	u32 isr;
+
+	edev = arg;
+	ctlr = edev->ctlr;
+
+	while((isr = csr16r(ctlr, Isr)) != 0 && isr != 0xFFFF){
+		csr16w(ctlr, Isr, isr);
+		if(isr & (Fovw|Punlc|Rdu|Rer|Rok)){
+			rtl8169receive(edev);
+			if(!(isr & (Punlc|Rok)))
+				ctlr->ierrs++;
+			if(isr & Rer)
+				ctlr->rer++;
+			if(isr & Rdu)
+				ctlr->rdu++;
+			if(isr & Punlc)
+				ctlr->punlc++;
+			if(isr & Fovw)
+				ctlr->fovw++;
+			isr &= ~(Fovw|Rdu|Rer|Rok);
+		}
+
+		if(isr & (Tdu|Ter|Tok)){
+			rtl8169transmit(edev);
+			isr &= ~(Tdu|Ter|Tok);
+		}
+
+		if(isr & Punlc){
+//			rtl8169link(edev);
+			isr &= ~Punlc;
+		}
+
+		/*
+		 * Some of the reserved bits get set sometimes...
+		 */
+		if(isr & (Serr|Timeout|Tdu|Fovw|Punlc|Rdu|Ter|Tok|Rer|Rok))
+			panic("rtl8169interrupt: imr %#4.4ux isr %#4.4ux\n",
+				csr16r(ctlr, Imr), isr);
+	}
+}
+
+static void
+rtl8169pci(void)
+{
+	Pcidev *p;
+	Ctlr *ctlr;
+	int i, port;
+	u32 bar;
+
+	p = nil;
+	while(p = pcimatch(p, 0, 0)){
+		if(p->ccrb != 0x02 || p->ccru != 0)
+			continue;
+
+		switch(i = ((p->did<<16)|p->vid)){
+		default:
+			continue;
+		case Rtl8100e:			/* RTL810[01]E ? */
+		case Rtl8169c:			/* RTL8169C */
+		case Rtl8169sc:			/* RTL8169SC */
+		case Rtl8168b:			/* RTL8168B */
+		case Rtl8169:			/* RTL8169 */
+			break;
+		case (0xC107<<16)|0x1259:	/* Corega CG-LAPCIGT */
+			i = Rtl8169;
+			break;
+		}
+
+		bar = p->mem[0].bar;
+		port = bar & ~0x01;
+		if(ioalloc(port, p->mem[0].size, 0, "rtl8169") < 0){
+			print("rtl8169: port %#ux in use\n", port);
+			continue;
+		}
+		ctlr = malloc(sizeof(Ctlr));
+		ctlr->port = port;
+		ctlr->pcidev = p;
+		ctlr->pciv = i;
+
+		if(pcigetpms(p) > 0){
+			pcisetpms(p, 0);
+	
+			for(i = 0; i < 6; i++)
+				pcicfgw32(p, PciBAR0+i*4, p->mem[i].bar);
+			pcicfgw8(p, PciINTL, p->intl);
+			pcicfgw8(p, PciLTR, p->ltr);
+			pcicfgw8(p, PciCLS, p->cls);
+			pcicfgw16(p, PciPCR, p->pcr);
+		}
+
+		if(rtl8169reset(ctlr)){
+			iofree(port);
+			free(ctlr);
+			continue;
+		}
+
+		/*
+		 * Extract the chip hardware version,
+		 * needed to configure each properly.
+		 */
+		ctlr->macv = csr32r(ctlr, Tcr) & HwveridMASK;
+
+		rtl8169mii(ctlr);
+
+		pcisetbme(p);
+
+		if(rtl8169ctlrhead != nil)
+			rtl8169ctlrtail->next = ctlr;
+		else
+			rtl8169ctlrhead = ctlr;
+		rtl8169ctlrtail = ctlr;
+	}
+}
+
+int
+rtl8169pnp(Ether* edev)
+{
+	u32 r;
+	Ctlr *ctlr;
+
+	if(rtl8169ctlrhead == nil)
+		rtl8169pci();
+
+	/*
+	 * Any adapter matches if no edev->port is supplied,
+	 * otherwise the ports must match.
+	 */
+	for(ctlr = rtl8169ctlrhead; ctlr != nil; ctlr = ctlr->next){
+		if(ctlr->active)
+			continue;
+		if(edev->port == 0 || edev->port == ctlr->port){
+			ctlr->active = 1;
+			break;
+		}
+	}
+	if(ctlr == nil)
+		return -1;
+
+	edev->ctlr = ctlr;
+	edev->port = ctlr->port;
+	edev->irq = ctlr->pcidev->intl;
+	edev->tbdf = ctlr->pcidev->tbdf;
+//	edev->mbps = 100;
+
+	/*
+	 * Pull the MAC address out of the chip.
+	 */
+	r = csr32r(ctlr, Idr0);
+	edev->ea[0] = r;
+	edev->ea[1] = r>>8;
+	edev->ea[2] = r>>16;
+	edev->ea[3] = r>>24;
+	r = csr32r(ctlr, Idr0+4);
+	edev->ea[4] = r;
+	edev->ea[5] = r>>8;
+
+	/*
+	 * Linkage to the generic ethernet driver.
+	 */
+	edev->attach = rtl8169attach;
+	edev->transmit = rtl8169transmit;
+	edev->interrupt = rtl8169interrupt;
+	edev->detach = rtl8169detach;
+//	edev->ifstat = rtl8169ifstat;
+//	edev->ctl = nil;
+//
+//	edev->arg = edev;
+//	edev->promiscuous = rtl8169promiscuous;
+//	edev->multicast = rtl8169multicast;
+
+	return 0;
+}
--- /dev/null
+++ b/os/boot.original/pc/ether82557.c
@@ -1,0 +1,882 @@
+/*
+ * Intel 82557 Fast Ethernet PCI Bus LAN Controller
+ * as found on the Intel EtherExpress PRO/100B. This chip is full
+ * of smarts, unfortunately none of them are in the right place.
+ * To do:
+ *	the PCI scanning code could be made common to other adapters;
+ *	PCI code needs rewritten to handle byte, word, dword accesses
+ *	  and using the devno as a bus+dev+function triplet.
+ */
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+#include "etherif.h"
+
+enum {
+	Nrfd		= 4,		/* receive frame area */
+
+	NullPointer	= 0xFFFFFFFF,	/* 82557 NULL pointer */
+};
+
+enum {					/* CSR */
+	Status		= 0x00,		/* byte or word (word includes Ack) */
+	Ack		= 0x01,		/* byte */
+	CommandR	= 0x02,		/* byte or word (word includes Interrupt) */
+	Interrupt	= 0x03,		/* byte */
+	Pointer		= 0x04,		/* dword */
+	Port		= 0x08,		/* dword */
+	Fcr		= 0x0C,		/* Flash control register */
+	Ecr		= 0x0E,		/* EEPROM control register */
+	Mcr		= 0x10,		/* MDI control register */
+};
+
+enum {					/* Status */
+	RUidle		= 0x0000,
+	RUsuspended	= 0x0004,
+	RUnoresources	= 0x0008,
+	RUready		= 0x0010,
+	RUrbd		= 0x0020,	/* bit */
+	RUstatus	= 0x003F,	/* mask */
+
+	CUidle		= 0x0000,
+	CUsuspended	= 0x0040,
+	CUactive	= 0x0080,
+	CUstatus	= 0x00C0,	/* mask */
+
+	StatSWI		= 0x0400,	/* SoftWare generated Interrupt */
+	StatMDI		= 0x0800,	/* MDI r/w done */
+	StatRNR		= 0x1000,	/* Receive unit Not Ready */
+	StatCNA		= 0x2000,	/* Command unit Not Active (Active->Idle) */
+	StatFR		= 0x4000,	/* Finished Receiving */
+	StatCX		= 0x8000,	/* Command eXecuted */
+	StatTNO		= 0x8000,	/* Transmit NOT OK */
+};
+
+enum {					/* Command (byte) */
+	CUnop		= 0x00,
+	CUstart		= 0x10,
+	CUresume	= 0x20,
+	LoadDCA		= 0x40,		/* Load Dump Counters Address */
+	DumpSC		= 0x50,		/* Dump Statistical Counters */
+	LoadCUB		= 0x60,		/* Load CU Base */
+	ResetSA		= 0x70,		/* Dump and Reset Statistical Counters */
+
+	RUstart		= 0x01,
+	RUresume	= 0x02,
+	RUabort		= 0x04,
+	LoadHDS		= 0x05,		/* Load Header Data Size */
+	LoadRUB		= 0x06,		/* Load RU Base */
+	RBDresume	= 0x07,		/* Resume frame reception */
+};
+
+enum {					/* Interrupt (byte) */
+	InterruptM	= 0x01,		/* interrupt Mask */
+	InterruptSI	= 0x02,		/* Software generated Interrupt */
+};
+
+enum {					/* Ecr */
+	EEsk		= 0x01,		/* serial clock */
+	EEcs		= 0x02,		/* chip select */
+	EEdi		= 0x04,		/* serial data in */
+	EEdo		= 0x08,		/* serial data out */
+
+	EEstart		= 0x04,		/* start bit */
+	EEread		= 0x02,		/* read opcode */
+};
+
+enum {					/* Mcr */
+	MDIread		= 0x08000000,	/* read opcode */
+	MDIwrite	= 0x04000000,	/* write opcode */
+	MDIready	= 0x10000000,	/* ready bit */
+	MDIie		= 0x20000000,	/* interrupt enable */
+};
+
+typedef struct Rfd {
+	int	field;
+	ulong	link;
+	ulong	rbd;
+	ushort	count;
+	ushort	size;
+
+	Etherpkt;
+} Rfd;
+
+enum {					/* field */
+	RfdCollision	= 0x00000001,
+	RfdIA		= 0x00000002,	/* IA match */
+	RfdRxerr	= 0x00000010,	/* PHY character error */
+	RfdType		= 0x00000020,	/* Type frame */
+	RfdRunt		= 0x00000080,
+	RfdOverrun	= 0x00000100,
+	RfdBuffer	= 0x00000200,
+	RfdAlignment	= 0x00000400,
+	RfdCRC		= 0x00000800,
+
+	RfdOK		= 0x00002000,	/* frame received OK */
+	RfdC		= 0x00008000,	/* reception Complete */
+	RfdSF		= 0x00080000,	/* Simplified or Flexible (1) Rfd */
+	RfdH		= 0x00100000,	/* Header RFD */
+
+	RfdI		= 0x20000000,	/* Interrupt after completion */
+	RfdS		= 0x40000000,	/* Suspend after completion */
+	RfdEL		= 0x80000000,	/* End of List */
+};
+
+enum {					/* count */
+	RfdF		= 0x00004000,
+	RfdEOF		= 0x00008000,
+};
+
+typedef struct Cb {
+	int	command;
+	ulong	link;
+	uchar	data[24];	/* CbIAS + CbConfigure */
+} Cb;
+
+typedef struct TxCB {
+	int	command;
+	ulong	link;
+	ulong	tbd;
+	ushort	count;
+	uchar	threshold;
+	uchar	number;
+} TxCB;
+
+enum {					/* action command */
+	CbOK		= 0x00002000,	/* DMA completed OK */
+	CbC		= 0x00008000,	/* execution Complete */
+
+	CbNOP		= 0x00000000,
+	CbIAS		= 0x00010000,	/* Indvidual Address Setup */
+	CbConfigure	= 0x00020000,
+	CbMAS		= 0x00030000,	/* Multicast Address Setup */
+	CbTransmit	= 0x00040000,
+	CbDump		= 0x00060000,
+	CbDiagnose	= 0x00070000,
+	CbCommand	= 0x00070000,	/* mask */
+
+	CbSF		= 0x00080000,	/* CbTransmit */
+
+	CbI		= 0x20000000,	/* Interrupt after completion */
+	CbS		= 0x40000000,	/* Suspend after completion */
+	CbEL		= 0x80000000,	/* End of List */
+};
+
+enum {					/* CbTransmit count */
+	CbEOF		= 0x00008000,
+};
+
+typedef struct Ctlr Ctlr;
+typedef struct Ctlr {
+	int	port;
+	Pcidev*	pcidev;
+	Ctlr*	next;
+	int	active;
+
+	int	eepromsz;		/* address size in bits */
+	ushort*	eeprom;
+
+	int	ctlrno;
+	char*	type;
+
+	uchar	configdata[24];
+
+	Rfd	rfd[Nrfd];
+	int	rfdl;
+	int	rfdx;
+
+	Block*	cbqhead;
+	Block*	cbqtail;
+	int	cbqbusy;
+} Ctlr;
+
+static Ctlr* ctlrhead;
+static Ctlr* ctlrtail;
+
+static uchar configdata[24] = {
+	0x16,				/* byte count */
+	0x44,				/* Rx/Tx FIFO limit */
+	0x00,				/* adaptive IFS */
+	0x00,	
+	0x04,				/* Rx DMA maximum byte count */
+	0x84,				/* Tx DMA maximum byte count */
+	0x33,				/* late SCB, CNA interrupts */
+	0x01,				/* discard short Rx frames */
+	0x00,				/* 503/MII */
+
+	0x00,	
+	0x2E,				/* normal operation, NSAI */
+	0x00,				/* linear priority */
+	0x60,				/* inter-frame spacing */
+	0x00,	
+	0xF2,	
+	0x48,				/* promiscuous mode off */
+	0x00,	
+	0x40,	
+	0xF2,				/* transmit padding enable */
+	0x80,				/* full duplex pin enable */
+	0x3F,				/* no Multi IA */
+	0x05,				/* no Multi Cast ALL */
+};
+
+#define csr8r(c, r)	(inb((c)->port+(r)))
+#define csr16r(c, r)	(ins((c)->port+(r)))
+#define csr32r(c, r)	(inl((c)->port+(r)))
+#define csr8w(c, r, b)	(outb((c)->port+(r), (int)(b)))
+#define csr16w(c, r, w)	(outs((c)->port+(r), (ushort)(w)))
+#define csr32w(c, r, l)	(outl((c)->port+(r), (ulong)(l)))
+
+static void
+custart(Ctlr* ctlr)
+{
+	if(ctlr->cbqhead == 0){
+		ctlr->cbqbusy = 0;
+		return;
+	}
+	ctlr->cbqbusy = 1;
+
+	csr32w(ctlr, Pointer, PADDR(ctlr->cbqhead->rp));
+	while(csr8r(ctlr, CommandR))
+		;
+	csr8w(ctlr, CommandR, CUstart);
+}
+
+static void
+action(Ctlr* ctlr, Block* bp)
+{
+	Cb *cb;
+
+	cb = (Cb*)bp->rp;
+	cb->command |= CbEL;
+
+	if(ctlr->cbqhead){
+		ctlr->cbqtail->next = bp;
+		cb = (Cb*)ctlr->cbqtail->rp;
+		cb->link = PADDR(bp->rp);
+		cb->command &= ~CbEL;
+	}
+	else
+		ctlr->cbqhead = bp;
+	ctlr->cbqtail = bp;
+
+	if(ctlr->cbqbusy == 0)
+		custart(ctlr);
+}
+
+static void
+attach(Ether* ether)
+{
+	int status;
+	Ctlr *ctlr;
+
+	ctlr = ether->ctlr;
+	status = csr16r(ctlr, Status);
+	if((status & RUstatus) == RUidle){
+		csr32w(ctlr, Pointer, PADDR(&ctlr->rfd[ctlr->rfdx]));
+		while(csr8r(ctlr, CommandR))
+			;
+		csr8w(ctlr, CommandR, RUstart);
+	}
+}
+
+static void
+configure(void* arg, int promiscuous)
+{
+	Ctlr *ctlr;
+	Block *bp;
+	Cb *cb;
+
+	ctlr = ((Ether*)arg)->ctlr;
+
+	bp = allocb(sizeof(Cb));
+	cb = (Cb*)bp->rp;
+	bp->wp += sizeof(Cb);
+
+	cb->command = CbConfigure;
+	cb->link = NullPointer;
+	memmove(cb->data, ctlr->configdata, sizeof(ctlr->configdata));
+	if(promiscuous)
+		cb->data[15] |= 0x01;
+	action(ctlr, bp);
+}
+
+static void
+transmit(Ether* ether)
+{
+	Block *bp;
+	TxCB *txcb;
+	RingBuf *tb;
+
+	for(tb = &ether->tb[ether->ti]; tb->owner == Interface; tb = &ether->tb[ether->ti]){
+		bp = allocb(tb->len+sizeof(TxCB));
+		txcb = (TxCB*)bp->wp;
+		bp->wp += sizeof(TxCB);
+
+		txcb->command = CbTransmit;
+		txcb->link = NullPointer;
+		txcb->tbd = NullPointer;
+		txcb->count = CbEOF|tb->len;
+		txcb->threshold = 2;
+		txcb->number = 0;
+
+		memmove(bp->wp, tb->pkt, tb->len);
+		memmove(bp->wp+Eaddrlen, ether->ea, Eaddrlen);
+		bp->wp += tb->len;
+
+		action(ether->ctlr, bp);
+
+		tb->owner = Host;
+		ether->ti = NEXT(ether->ti, ether->ntb);
+	}
+}
+
+static void
+interrupt(Ureg*, void* arg)
+{
+	Rfd *rfd;
+	Block *bp;
+	Ctlr *ctlr;
+	Ether *ether;
+	int status;
+	RingBuf *rb;
+
+	ether = arg;
+	ctlr = ether->ctlr;
+
+	for(;;){
+		status = csr16r(ctlr, Status);
+		csr8w(ctlr, Ack, (status>>8) & 0xFF);
+
+		if((status & (StatCX|StatFR|StatCNA|StatRNR)) == 0)
+			return;
+
+		if(status & StatFR){
+			rfd = &ctlr->rfd[ctlr->rfdx];
+			while(rfd->field & RfdC){
+				rb = &ether->rb[ether->ri];
+				if(rb->owner == Interface){
+					rb->owner = Host;
+					rb->len = rfd->count & 0x3FFF;
+					memmove(rb->pkt, rfd->d, rfd->count & 0x3FFF);
+					ether->ri = NEXT(ether->ri, ether->nrb);
+				}
+
+				/*
+				 * Reinitialise the frame for reception and bump
+				 * the receive frame processing index;
+				 * bump the sentinel index, mark the new sentinel
+				 * and clear the old sentinel suspend bit;
+				 * set bp and rfd for the next receive frame to
+				 * process.
+				 */
+				rfd->field = 0;
+				rfd->count = 0;
+				ctlr->rfdx = NEXT(ctlr->rfdx, Nrfd);
+
+				rfd = &ctlr->rfd[ctlr->rfdl];
+				ctlr->rfdl = NEXT(ctlr->rfdl, Nrfd);
+				ctlr->rfd[ctlr->rfdl].field |= RfdS;
+				rfd->field &= ~RfdS;
+
+				rfd = &ctlr->rfd[ctlr->rfdx];
+			}
+			status &= ~StatFR;
+		}
+
+		if(status & StatRNR){
+			while(csr8r(ctlr, CommandR))
+				;
+			csr8w(ctlr, CommandR, RUresume);
+
+			status &= ~StatRNR;
+		}
+
+		if(status & StatCNA){
+			while(bp = ctlr->cbqhead){
+				if((((Cb*)bp->rp)->command & CbC) == 0)
+					break;
+				ctlr->cbqhead = bp->next;
+				freeb(bp);
+			}
+			custart(ctlr);
+
+			status &= ~StatCNA;
+		}
+
+		if(status & (StatCX|StatFR|StatCNA|StatRNR|StatMDI|StatSWI))
+			panic("%s#%d: status %uX\n", ctlr->type,  ctlr->ctlrno, status);
+	}
+}
+
+static void
+ctlrinit(Ctlr* ctlr)
+{
+	int i;
+	Rfd *rfd;
+	ulong link;
+
+	link = NullPointer;
+	for(i = Nrfd-1; i >= 0; i--){
+		rfd = &ctlr->rfd[i];
+
+		rfd->field = 0;
+		rfd->link = link;
+		link = PADDR(rfd);
+		rfd->rbd = NullPointer;
+		rfd->count = 0;
+		rfd->size = sizeof(Etherpkt);
+	}
+	ctlr->rfd[Nrfd-1].link = PADDR(&ctlr->rfd[0]);
+
+	ctlr->rfdl = 0;
+	ctlr->rfd[0].field |= RfdS;
+	ctlr->rfdx = 2;
+
+	memmove(ctlr->configdata, configdata, sizeof(configdata));
+}
+
+static int
+miir(Ctlr* ctlr, int phyadd, int regadd)
+{
+	int mcr, timo;
+
+	csr32w(ctlr, Mcr, MDIread|(phyadd<<21)|(regadd<<16));
+	mcr = 0;
+	for(timo = 64; timo; timo--){
+		mcr = csr32r(ctlr, Mcr);
+		if(mcr & MDIready)
+			break;
+		microdelay(1);
+	}
+
+	if(mcr & MDIready)
+		return mcr & 0xFFFF;
+
+	return -1;
+}
+
+static int
+miiw(Ctlr* ctlr, int phyadd, int regadd, int data)
+{
+	int mcr, timo;
+
+	csr32w(ctlr, Mcr, MDIwrite|(phyadd<<21)|(regadd<<16)|(data & 0xFFFF));
+	mcr = 0;
+	for(timo = 64; timo; timo--){
+		mcr = csr32r(ctlr, Mcr);
+		if(mcr & MDIready)
+			break;
+		microdelay(1);
+	}
+
+	if(mcr & MDIready)
+		return 0;
+
+	return -1;
+}
+
+static int
+hy93c46r(Ctlr* ctlr, int r)
+{
+	int data, i, op, size;
+
+	/*
+	 * Hyundai HY93C46 or equivalent serial EEPROM.
+	 * This sequence for reading a 16-bit register 'r'
+	 * in the EEPROM is taken straight from Section
+	 * 3.3.4.2 of the Intel 82557 User's Guide.
+	 */
+reread:
+	csr16w(ctlr, Ecr, EEcs);
+	op = EEstart|EEread;
+	for(i = 2; i >= 0; i--){
+		data = (((op>>i) & 0x01)<<2)|EEcs;
+		csr16w(ctlr, Ecr, data);
+		csr16w(ctlr, Ecr, data|EEsk);
+		microdelay(1);
+		csr16w(ctlr, Ecr, data);
+		microdelay(1);
+	}
+
+	/*
+	 * First time through must work out the EEPROM size.
+	 */
+	if((size = ctlr->eepromsz) == 0)
+		size = 8;
+
+	for(size = size-1; size >= 0; size--){
+		data = (((r>>size) & 0x01)<<2)|EEcs;
+		csr16w(ctlr, Ecr, data);
+		csr16w(ctlr, Ecr, data|EEsk);
+		delay(1);
+		csr16w(ctlr, Ecr, data);
+		microdelay(1);
+		if(!(csr16r(ctlr, Ecr) & EEdo))
+			break;
+	}
+
+	data = 0;
+	for(i = 15; i >= 0; i--){
+		csr16w(ctlr, Ecr, EEcs|EEsk);
+		microdelay(1);
+		if(csr16r(ctlr, Ecr) & EEdo)
+			data |= (1<<i);
+		csr16w(ctlr, Ecr, EEcs);
+		microdelay(1);
+	}
+
+	csr16w(ctlr, Ecr, 0);
+
+	if(ctlr->eepromsz == 0){
+		ctlr->eepromsz = 8-size;
+		ctlr->eeprom = malloc((1<<ctlr->eepromsz)*sizeof(ushort));
+		goto reread;
+	}
+
+	return data;
+}
+
+static void
+i82557pci(void)
+{
+	Pcidev *p;
+	Ctlr *ctlr;
+
+	p = nil;
+	while(p = pcimatch(p, 0x8086, 0)){
+		switch(p->did){
+		default:
+			continue;
+		case 0x1031:		/* Intel 82562EM */
+		case 0x1050:		/* Intel 82562EZ */
+		case 0x1039:		/* Intel 82801BD PRO/100 VE */
+		case 0x103A:		/* Intel 82562 PRO/100 VE */
+		case 0x1064:		/* Intel 82562 PRO/100 VE */
+		case 0x2449:		/* Intel 82562ET */
+		case 0x1209:		/* Intel 82559ER */
+		case 0x1229:		/* Intel 8255[789] */
+		case 0x1030:		/* Intel 82559 InBusiness 10/100  */
+			break;
+		}
+
+		/*
+		 * bar[0] is the memory-mapped register address (4KB),
+		 * bar[1] is the I/O port register address (32 bytes) and
+		 * bar[2] is for the flash ROM (1MB).
+		 */
+		ctlr = malloc(sizeof(Ctlr));
+		ctlr->port = p->mem[1].bar & ~0x01;
+		ctlr->pcidev = p;
+
+		if(ctlrhead != nil)
+			ctlrtail->next = ctlr;
+		else
+			ctlrhead = ctlr;
+		ctlrtail = ctlr;
+
+		pcisetbme(p);
+	}
+}
+
+static void
+detach(Ether* ether)
+{
+	Ctlr *ctlr;
+
+	ctlr = ether->ctlr;
+
+	csr32w(ctlr, Port, 0);
+	delay(1);
+
+	while(csr8r(ctlr, CommandR))
+		;
+}
+
+static int
+scanphy(Ctlr* ctlr)
+{
+	int i, oui, x;
+
+	for(i = 0; i < 32; i++){
+		if((oui = miir(ctlr, i, 2)) == -1 || oui == 0 || oui == 0xFFFF)
+			continue;
+		oui <<= 6;
+		x = miir(ctlr, i, 3);
+		oui |= x>>10;
+		//print("phy%d: oui %uX reg1 %uX\n", i, oui, miir(ctlr, i, 1));
+
+		if(oui == 0xAA00)
+			ctlr->eeprom[6] = 0x07<<8;
+		else if(oui == 0x80017){
+			if(x & 0x01)
+				ctlr->eeprom[6] = 0x0A<<8;
+			else
+				ctlr->eeprom[6] = 0x04<<8;
+		}
+		return i;
+	}
+	return -1;
+}
+
+int
+i82557reset(Ether* ether)
+{
+	int anar, anlpar, bmcr, bmsr, force, i, phyaddr, x;
+	unsigned short sum;
+	Block *bp;
+	uchar ea[Eaddrlen];
+	Ctlr *ctlr;
+	Cb *cb;
+
+
+	if(ctlrhead == nil)
+		i82557pci();
+
+	/*
+	 * Any adapter matches if no ether->port is supplied,
+	 * otherwise the ports must match.
+	 */
+	for(ctlr = ctlrhead; ctlr != nil; ctlr = ctlr->next){
+		if(ctlr->active)
+			continue;
+		if(ether->port == 0 || ether->port == ctlr->port){
+			ctlr->active = 1;
+			break;
+		}
+	}
+	if(ctlr == nil)
+		return -1;
+
+	/*
+	 * Initialise the Ctlr structure.
+	 * Perform a software reset after which need to ensure busmastering
+	 * is still enabled. The EtherExpress PRO/100B appears to leave
+	 * the PCI configuration alone (see the 'To do' list above) so punt
+	 * for now.
+	 * Load the RUB and CUB registers for linear addressing (0).
+	 */
+	ether->ctlr = ctlr;
+	ether->port = ctlr->port;
+	ether->irq = ctlr->pcidev->intl;
+	ether->tbdf = ctlr->pcidev->tbdf;
+	ctlr->ctlrno = ether->ctlrno;
+	ctlr->type = ether->type;
+
+	csr32w(ctlr, Port, 0);
+	delay(1);
+
+	while(csr8r(ctlr, CommandR))
+		;
+	csr32w(ctlr, Pointer, 0);
+	csr8w(ctlr, CommandR, LoadRUB);
+	while(csr8r(ctlr, CommandR))
+		;
+	csr8w(ctlr, CommandR, LoadCUB);
+
+	/*
+	 * Initialise the action and receive frame areas.
+	 */
+	ctlrinit(ctlr);
+
+	/*
+	 * Read the EEPROM.
+	 * Do a dummy read first to get the size
+	 * and allocate ctlr->eeprom.
+	 */
+	hy93c46r(ctlr, 0);
+	sum = 0;
+	for(i = 0; i < (1<<ctlr->eepromsz); i++){
+		x = hy93c46r(ctlr, i);
+		ctlr->eeprom[i] = x;
+		sum += x;
+	}
+	if(sum != 0xBABA)
+		print("#l%d: EEPROM checksum - 0x%4.4uX\n", ether->ctlrno, sum);
+
+	/*
+	 * Eeprom[6] indicates whether there is a PHY and whether
+	 * it's not 10Mb-only, in which case use the given PHY address
+	 * to set any PHY specific options and determine the speed.
+	 * Unfortunately, sometimes the EEPROM is blank except for
+	 * the ether address and checksum; in this case look at the
+	 * controller type and if it's am 82558 or 82559 it has an
+	 * embedded PHY so scan for that.
+	 * If no PHY, assume 82503 (serial) operation.
+	 */
+	if((ctlr->eeprom[6] & 0x1F00) && !(ctlr->eeprom[6] & 0x8000))
+		phyaddr = ctlr->eeprom[6] & 0x00FF;
+	else
+	switch(ctlr->pcidev->rid){
+	case 0x01:			/* 82557 A-step */
+	case 0x02:			/* 82557 B-step */
+	case 0x03:			/* 82557 C-step */
+	default:
+		phyaddr = -1;
+		break;
+	case 0x04:			/* 82558 A-step */
+	case 0x05:			/* 82558 B-step */
+	case 0x06:			/* 82559 A-step */
+	case 0x07:			/* 82559 B-step */
+	case 0x08:			/* 82559 C-step */
+	case 0x09:			/* 82559ER A-step */
+		phyaddr = scanphy(ctlr);
+		break;
+	}
+	if(phyaddr >= 0){
+		/*
+		 * Resolve the highest common ability of the two
+		 * link partners. In descending order:
+		 *	0x0100		100BASE-TX Full Duplex
+		 *	0x0200		100BASE-T4
+		 *	0x0080		100BASE-TX
+		 *	0x0040		10BASE-T Full Duplex
+		 *	0x0020		10BASE-T
+		 */
+		anar = miir(ctlr, phyaddr, 0x04);
+		anlpar = miir(ctlr, phyaddr, 0x05) & 0x03E0;
+		anar &= anlpar;
+		bmcr = 0;
+		if(anar & 0x380)
+			bmcr = 0x2000;
+		if(anar & 0x0140)
+			bmcr |= 0x0100;
+
+		switch((ctlr->eeprom[6]>>8) & 0x001F){
+
+		case 0x04:				/* DP83840 */
+		case 0x0A:				/* DP83840A */
+			/*
+			 * The DP83840[A] requires some tweaking for
+			 * reliable operation.
+			 * The manual says bit 10 should be unconditionally
+			 * set although it supposedly only affects full-duplex
+			 * operation (an & 0x0140).
+			 */
+			x = miir(ctlr, phyaddr, 0x17) & ~0x0520;
+			x |= 0x0420;
+			for(i = 0; i < ether->nopt; i++){
+				if(cistrcmp(ether->opt[i], "congestioncontrol"))
+					continue;
+				x |= 0x0100;
+				break;
+			}
+			miiw(ctlr, phyaddr, 0x17, x);
+
+			/*
+			 * If the link partner can't autonegotiate, determine
+			 * the speed from elsewhere.
+			 */
+			if(anlpar == 0){
+				miir(ctlr, phyaddr, 0x01);
+				bmsr = miir(ctlr, phyaddr, 0x01);
+				x = miir(ctlr, phyaddr, 0x19);
+				if((bmsr & 0x0004) && !(x & 0x0040))
+					bmcr = 0x2000;
+			}
+			break;
+
+		case 0x07:				/* Intel 82555 */
+			/*
+			 * Auto-negotiation may fail if the other end is
+			 * a DP83840A and the cable is short.
+			 */
+			bmsr = miir(ctlr, phyaddr, 0x01);
+			if((miir(ctlr, phyaddr, 0) & 0x1000) && !(bmsr & 0x0020)){
+				miiw(ctlr, phyaddr, 0x1A, 0x2010);
+				x = miir(ctlr, phyaddr, 0);
+				miiw(ctlr, phyaddr, 0, 0x0200|x);
+				for(i = 0; i < 3000; i++){
+					delay(1);
+					if(miir(ctlr, phyaddr, 0x01) & 0x0020)
+						break;
+				}
+				miiw(ctlr, phyaddr, 0x1A, 0x2000);
+					
+				anar = miir(ctlr, phyaddr, 0x04);
+				anlpar = miir(ctlr, phyaddr, 0x05) & 0x03E0;
+				anar &= anlpar;
+				bmcr = 0;
+				if(anar & 0x380)
+					bmcr = 0x2000;
+				if(anar & 0x0140)
+					bmcr |= 0x0100;
+			}
+			break;
+		}
+
+		/*
+		 * Force speed and duplex if no auto-negotiation.
+		 */
+		if(anlpar == 0){
+			force = 0;
+			for(i = 0; i < ether->nopt; i++){
+				if(cistrcmp(ether->opt[i], "fullduplex") == 0){
+					force = 1;
+					bmcr |= 0x0100;
+					ctlr->configdata[19] |= 0x40;
+				}
+				else if(cistrcmp(ether->opt[i], "speed") == 0){
+					force = 1;
+					x = strtol(&ether->opt[i][6], 0, 0);
+					if(x == 10)
+						bmcr &= ~0x2000;
+					else if(x == 100)
+						bmcr |= 0x2000;
+					else
+						force = 0;
+				}
+			}
+			if(force)
+				miiw(ctlr, phyaddr, 0x00, bmcr);
+		}
+
+		ctlr->configdata[8] = 1;
+		ctlr->configdata[15] &= ~0x80;
+	}
+	else{
+		ctlr->configdata[8] = 0;
+		ctlr->configdata[15] |= 0x80;
+	}
+
+	/*
+	 * Load the chip configuration
+	 */
+	configure(ether, 0);
+
+	/*
+	 * Check if the adapter's station address is to be overridden.
+	 * If not, read it from the EEPROM and set in ether->ea prior to loading
+	 * the station address with the Individual Address Setup command.
+	 */
+	memset(ea, 0, Eaddrlen);
+	if(memcmp(ea, ether->ea, Eaddrlen) == 0){
+		for(i = 0; i < Eaddrlen/2; i++){
+			x = ctlr->eeprom[i];
+			ether->ea[2*i] = x & 0xFF;
+			ether->ea[2*i+1] = (x>>8) & 0xFF;
+		}
+	}
+
+	bp = allocb(sizeof(Cb));
+	cb = (Cb*)bp->rp;
+	bp->wp += sizeof(Cb);
+
+	cb->command = CbIAS;
+	cb->link = NullPointer;
+	memmove(cb->data, ether->ea, Eaddrlen);
+	action(ctlr, bp);
+
+	/*
+	 * Linkage to the generic ethernet driver.
+	 */
+	ether->attach = attach;
+	ether->transmit = transmit;
+	ether->interrupt = interrupt;
+	ether->detach = detach;
+
+	return 0;
+}
--- /dev/null
+++ b/os/boot.original/pc/ether82563.c
@@ -1,0 +1,977 @@
+/*
+ * bootstrap driver for
+ * Intel 82563, 82571, 82573 Gigabit Ethernet PCI-Express Controllers
+ */
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+#include "etherif.h"
+
+/* compatibility with cpu kernels */
+#define iallocb allocb
+#ifndef CACHELINESZ
+#define CACHELINESZ	32		/* pentium & later */
+#endif
+
+/* from pci.c */
+enum
+{					/* command register pcidev->pcr */
+	IOen		= 1<<0,
+	MEMen		= 1<<1,
+	MASen		= 1<<2,
+	MemWrInv	= 1<<4,
+	PErrEn		= 1<<6,
+	SErrEn		= 1<<8,
+};
+
+/*
+ * these are in the order they appear in the manual, not numeric order.
+ * It was too hard to find them in the book. Ref 21489, rev 2.6
+ */
+
+enum {
+	/* General */
+
+	Ctrl		= 0x00000000,	/* Device Control */
+	Status		= 0x00000008,	/* Device Status */
+	Eec		= 0x00000010,	/* EEPROM/Flash Control/Data */
+	Eerd		= 0x00000014,	/* EEPROM Read */
+	Ctrlext		= 0x00000018,	/* Extended Device Control */
+	Fla		= 0x0000001c,	/* Flash Access */
+	Mdic		= 0x00000020,	/* MDI Control */
+	Seresctl	= 0x00000024,	/* Serdes ana */
+	Fcal		= 0x00000028,	/* Flow Control Address Low */
+	Fcah		= 0x0000002C,	/* Flow Control Address High */
+	Fct		= 0x00000030,	/* Flow Control Type */
+	Kumctrlsta	= 0x00000034,	/* Kumeran Controll and Status Register */
+	Vet		= 0x00000038,	/* VLAN EtherType */
+	Fcttv		= 0x00000170,	/* Flow Control Transmit Timer Value */
+	Txcw		= 0x00000178,	/* Transmit Configuration Word */
+	Rxcw		= 0x00000180,	/* Receive Configuration Word */
+	Ledctl		= 0x00000E00,	/* LED control */
+	Pba		= 0x00001000,	/* Packet Buffer Allocation */
+
+	/* Interrupt */
+
+	Icr		= 0x000000C0,	/* Interrupt Cause Read */
+	Ics		= 0x000000C8,	/* Interrupt Cause Set */
+	Ims		= 0x000000D0,	/* Interrupt Mask Set/Read */
+	Imc		= 0x000000D8,	/* Interrupt mask Clear */
+	Iam		= 0x000000E0,	/* Interrupt acknowledge Auto Mask */
+
+	/* Receive */
+
+	Rctl		= 0x00000100,	/* Receive Control */
+	Ert		= 0x00002008,	/* Early Receive Threshold (573[EVL] only) */
+	Fcrtl		= 0x00002160,	/* Flow Control RX Threshold Low */
+	Fcrth		= 0x00002168,	/* Flow Control Rx Threshold High */
+	Psrctl		= 0x00002170,	/* Packet Split Receive Control */
+	Rdbal		= 0x00002800,	/* Rdesc Base Address Low Queue 0 */
+	Rdbah		= 0x00002804,	/* Rdesc Base Address High Queue 0 */
+	Rdlen		= 0x00002808,	/* Receive Descriptor Length Queue 0 */
+	Rdh		= 0x00002810,	/* Receive Descriptor Head Queue 0 */
+	Rdt		= 0x00002818,	/* Receive Descriptor Tail Queue 0 */
+	Rdtr		= 0x00002820,	/* Receive Descriptor Timer Ring */
+	Rxdctl		= 0x00002828,	/* Receive Descriptor Control */
+	Radv		= 0x0000282C,	/* Receive Interrupt Absolute Delay Timer */
+	Rdbal1		= 0x00002900,	/* Rdesc Base Address Low Queue 1 */
+	Rdbah1		= 0x00002804,	/* Rdesc Base Address High Queue 1 */
+	Rdlen1		= 0x00002908,	/* Receive Descriptor Length Queue 1 */
+	Rdh1		= 0x00002910,	/* Receive Descriptor Head Queue 1 */
+	Rdt1		= 0x00002918,	/* Receive Descriptor Tail Queue 1 */
+	Rxdctl1		= 0x00002928,	/* Receive Descriptor Control Queue 1 */
+	Rsrpd		= 0x00002c00,	/* Receive Small Packet Detect */
+	Raid		= 0x00002c08,	/* Receive ACK interrupt delay */
+	Cpuvec		= 0x00002c10,	/* CPU Vector */
+	Rxcsum		= 0x00005000,	/* Receive Checksum Control */
+	Rfctl		= 0x00005008,	/* Receive Filter Control */
+	Mta		= 0x00005200,	/* Multicast Table Array */
+	Ral		= 0x00005400,	/* Receive Address Low */
+	Rah		= 0x00005404,	/* Receive Address High */
+	Vfta		= 0x00005600,	/* VLAN Filter Table Array */
+	Mrqc		= 0x00005818,	/* Multiple Receive Queues Command */
+	Rssim		= 0x00005864,	/* RSS Interrupt Mask */
+	Rssir		= 0x00005868,	/* RSS Interrupt Request */
+	Reta		= 0x00005c00,	/* Redirection Table */
+	Rssrk		= 0x00005c80,	/* RSS Random Key */
+
+	/* Transmit */
+
+	Tctl		= 0x00000400,	/* Transmit Control */
+	Tipg		= 0x00000410,	/* Transmit IPG */
+	Tdbal		= 0x00003800,	/* Tdesc Base Address Low */
+	Tdbah		= 0x00003804,	/* Tdesc Base Address High */
+	Tdlen		= 0x00003808,	/* Transmit Descriptor Length */
+	Tdh		= 0x00003810,	/* Transmit Descriptor Head */
+	Tdt		= 0x00003818,	/* Transmit Descriptor Tail */
+	Tidv		= 0x00003820,	/* Transmit Interrupt Delay Value */
+	Txdctl		= 0x00003828,	/* Transmit Descriptor Control */
+	Tadv		= 0x0000382C,	/* Transmit Interrupt Absolute Delay Timer */
+	Tarc0		= 0x00003840,	/* Transmit Arbitration Counter Queue 0 */
+	Tdbal1		= 0x00003900,	/* Transmit Descriptor Base Low Queue 1 */
+	Tdbah1		= 0x00003904,	/* Transmit Descriptor Base High Queue 1 */
+	Tdlen1		= 0x00003908,	/* Transmit Descriptor Length Queue 1 */
+	Tdh1		= 0x00003910,	/* Transmit Descriptor Head Queue 1 */
+	Tdt1		= 0x00003918,	/* Transmit Descriptor Tail Queue 1 */
+	Txdctl1		= 0x00003928,	/* Transmit Descriptor Control 1 */
+	Tarc1		= 0x00003940,	/* Transmit Arbitration Counter Queue 1 */
+
+	/* Statistics */
+
+	Statistics	= 0x00004000,	/* Start of Statistics Area */
+	Gorcl		= 0x88/4,	/* Good Octets Received Count */
+	Gotcl		= 0x90/4,	/* Good Octets Transmitted Count */
+	Torl		= 0xC0/4,	/* Total Octets Received */
+	Totl		= 0xC8/4,	/* Total Octets Transmitted */
+	Nstatistics	= 64,
+
+};
+
+enum {					/* Ctrl */
+	GIOmd		= 1<<2,		/* BIO master disable */
+	Lrst		= 1<<3,		/* link reset */
+	Slu		= 1<<6,		/* Set Link Up */
+	SspeedMASK	= 3<<8,		/* Speed Selection */
+	SspeedSHIFT	= 8,
+	Sspeed10	= 0x00000000,	/* 10Mb/s */
+	Sspeed100	= 0x00000100,	/* 100Mb/s */
+	Sspeed1000	= 0x00000200,	/* 1000Mb/s */
+	Frcspd		= 1<<11,	/* Force Speed */
+	Frcdplx		= 1<<12,	/* Force Duplex */
+	SwdpinsloMASK	= 0x003C0000,	/* Software Defined Pins - lo nibble */
+	SwdpinsloSHIFT	= 18,
+	SwdpioloMASK	= 0x03C00000,	/* Software Defined Pins - I or O */
+	SwdpioloSHIFT	= 22,
+	Devrst		= 1<<26,	/* Device Reset */
+	Rfce		= 1<<27,	/* Receive Flow Control Enable */
+	Tfce		= 1<<28,	/* Transmit Flow Control Enable */
+	Vme		= 1<<30,	/* VLAN Mode Enable */
+	Phy_rst		= 1<<31,	/* Phy Reset */
+};
+
+enum {					/* Status */
+	Lu		= 1<<1,		/* Link Up */
+	Lanid		= 3<<2,		/* mask for Lan ID. */
+	Txoff		= 1<<4,		/* Transmission Paused */
+	Tbimode		= 1<<5,		/* TBI Mode Indication */
+	SpeedMASK	= 0x000000C0,
+	Speed10		= 0x00000000,	/* 10Mb/s */
+	Speed100	= 0x00000040,	/* 100Mb/s */
+	Speed1000	= 0x00000080,	/* 1000Mb/s */
+	Phyra		= 1<<10,	/* PHY Reset Asserted */
+	GIOme		= 1<<19,	/* GIO Master Enable Status */
+};
+
+enum {					/* Ctrl and Status */
+	Fd		= 0x00000001,	/* Full-Duplex */
+	AsdvMASK	= 0x00000300,
+	Asdv10		= 0x00000000,	/* 10Mb/s */
+	Asdv100		= 0x00000100,	/* 100Mb/s */
+	Asdv1000	= 0x00000200,	/* 1000Mb/s */
+};
+
+enum {					/* Eec */
+	Sk		= 1<<0,		/* Clock input to the EEPROM */
+	Cs		= 1<<1,		/* Chip Select */
+	Di		= 1<<2,		/* Data Input to the EEPROM */
+	Do		= 1<<3,		/* Data Output from the EEPROM */
+	Areq		= 1<<6,		/* EEPROM Access Request */
+	Agnt		= 1<<7,		/* EEPROM Access Grant */
+};
+
+enum {					/* Eerd */
+	ee_start	= 1<<0,		/* Start Read */
+	ee_done		= 1<<1,		/* Read done */
+	ee_addr		= 0xfff8<<2,	/* Read address [15:2] */
+	ee_data		= 0xffff<<16,	/* Read Data; Data returned from eeprom/nvm */
+};
+
+enum {					/* Ctrlext */
+	Asdchk		= 1<<12,	/* ASD Check */
+	Eerst		= 1<<13,	/* EEPROM Reset */
+	Spdbyps		= 1<<15,	/* Speed Select Bypass */
+};
+
+enum {					/* EEPROM content offsets */
+	Ea		= 0x00,		/* Ethernet Address */
+	Cf		= 0x03,		/* Compatibility Field */
+	Icw1		= 0x0A,		/* Initialization Control Word 1 */
+	Sid		= 0x0B,		/* Subsystem ID */
+	Svid		= 0x0C,		/* Subsystem Vendor ID */
+	Did		= 0x0D,		/* Device ID */
+	Vid		= 0x0E,		/* Vendor ID */
+	Icw2		= 0x0F,		/* Initialization Control Word 2 */
+};
+
+enum {					/* Mdic */
+	MDIdMASK	= 0x0000FFFF,	/* Data */
+	MDIdSHIFT	= 0,
+	MDIrMASK	= 0x001F0000,	/* PHY Register Address */
+	MDIrSHIFT	= 16,
+	MDIpMASK	= 0x03E00000,	/* PHY Address */
+	MDIpSHIFT	= 21,
+	MDIwop		= 0x04000000,	/* Write Operation */
+	MDIrop		= 0x08000000,	/* Read Operation */
+	MDIready	= 0x10000000,	/* End of Transaction */
+	MDIie		= 0x20000000,	/* Interrupt Enable */
+	MDIe		= 0x40000000,	/* Error */
+};
+
+enum {					/* Icr, Ics, Ims, Imc */
+	Txdw		= 0x00000001,	/* Transmit Descriptor Written Back */
+	Txqe		= 0x00000002,	/* Transmit Queue Empty */
+	Lsc		= 0x00000004,	/* Link Status Change */
+	Rxseq		= 0x00000008,	/* Receive Sequence Error */
+	Rxdmt0		= 0x00000010,	/* Rdesc Minimum Threshold Reached */
+	Rxo		= 0x00000040,	/* Receiver Overrun */
+	Rxt0		= 0x00000080,	/* Receiver Timer Interrupt */
+	Mdac		= 0x00000200,	/* MDIO Access Completed */
+	Rxcfg		= 0x00000400,	/* Receiving /C/ ordered sets */
+	Gpi0		= 0x00000800,	/* General Purpose Interrupts */
+	Gpi1		= 0x00001000,
+	Gpi2		= 0x00002000,
+	Gpi3		= 0x00004000,
+	Ack		= 0x00020000,	/* receive ACK frame */
+};
+
+enum {					/* Txcw */
+	TxcwFd		= 0x00000020,	/* Full Duplex */
+	TxcwHd		= 0x00000040,	/* Half Duplex */
+	TxcwPauseMASK	= 0x00000180,	/* Pause */
+	TxcwPauseSHIFT	= 7,
+	TxcwPs		= 1<<TxcwPauseSHIFT,	/* Pause Supported */
+	TxcwAs		= 2<<TxcwPauseSHIFT,	/* Asymmetric FC desired */
+	TxcwRfiMASK	= 0x00003000,	/* Remote Fault Indication */
+	TxcwRfiSHIFT	= 12,
+	TxcwNpr		= 0x00008000,	/* Next Page Request */
+	TxcwConfig	= 0x40000000,	/* Transmit COnfig Control */
+	TxcwAne		= 0x80000000,	/* Auto-Negotiation Enable */
+};
+
+enum {					/* Rctl */
+	Rrst		= 0x00000001,	/* Receiver Software Reset */
+	Ren		= 0x00000002,	/* Receiver Enable */
+	Sbp		= 0x00000004,	/* Store Bad Packets */
+	Upe		= 0x00000008,	/* Unicast Promiscuous Enable */
+	Mpe		= 0x00000010,	/* Multicast Promiscuous Enable */
+	Lpe		= 0x00000020,	/* Long Packet Reception Enable */
+	LbmMASK		= 0x000000C0,	/* Loopback Mode */
+	LbmOFF		= 0x00000000,	/* No Loopback */
+	LbmTBI		= 0x00000040,	/* TBI Loopback */
+	LbmMII		= 0x00000080,	/* GMII/MII Loopback */
+	LbmXCVR		= 0x000000C0,	/* Transceiver Loopback */
+	RdtmsMASK	= 0x00000300,	/* Rdesc Minimum Threshold Size */
+	RdtmsHALF	= 0x00000000,	/* Threshold is 1/2 Rdlen */
+	RdtmsQUARTER	= 0x00000100,	/* Threshold is 1/4 Rdlen */
+	RdtmsEIGHTH	= 0x00000200,	/* Threshold is 1/8 Rdlen */
+	MoMASK		= 0x00003000,	/* Multicast Offset */
+	Bam		= 0x00008000,	/* Broadcast Accept Mode */
+	BsizeMASK	= 0x00030000,	/* Receive Buffer Size */
+	Bsize2048	= 0x00000000,
+	Bsize1024	= 0x00010000,
+	Bsize512	= 0x00020000,
+	Bsize256	= 0x00030000,
+	Vfe		= 0x00040000,	/* VLAN Filter Enable */
+	Cfien		= 0x00080000,	/* Canonical Form Indicator Enable */
+	Cfi		= 0x00100000,	/* Canonical Form Indicator value */
+	Dpf		= 0x00400000,	/* Discard Pause Frames */
+	Pmcf		= 0x00800000,	/* Pass MAC Control Frames */
+	Bsex		= 0x02000000,	/* Buffer Size Extension */
+	Secrc		= 0x04000000,	/* Strip CRC from incoming packet */
+};
+
+enum {					/* Tctl */
+	Trst		= 0x00000001,	/* Transmitter Software Reset */
+	Ten		= 0x00000002,	/* Transmit Enable */
+	Psp		= 0x00000008,	/* Pad Short Packets */
+	Mulr		= 0x10000000,	/* Allow multiple concurrent requests */
+	CtMASK		= 0x00000FF0,	/* Collision Threshold */
+	CtSHIFT		= 4,
+	ColdMASK	= 0x003FF000,	/* Collision Distance */
+	ColdSHIFT	= 12,
+	Swxoff		= 0x00400000,	/* Sofware XOFF Transmission */
+	Pbe		= 0x00800000,	/* Packet Burst Enable */
+	Rtlc		= 0x01000000,	/* Re-transmit on Late Collision */
+	Nrtu		= 0x02000000,	/* No Re-transmit on Underrrun */
+};
+
+enum {					/* [RT]xdctl */
+	PthreshMASK	= 0x0000003F,	/* Prefetch Threshold */
+	PthreshSHIFT	= 0,
+	HthreshMASK	= 0x00003F00,	/* Host Threshold */
+	HthreshSHIFT	= 8,
+	WthreshMASK	= 0x003F0000,	/* Writebacj Threshold */
+	WthreshSHIFT	= 16,
+	Gran		= 0x01000000,	/* Granularity */
+};
+
+enum {					/* Rxcsum */
+	PcssMASK	= 0x000000FF,	/* Packet Checksum Start */
+	PcssSHIFT	= 0,
+	Ipofl		= 0x00000100,	/* IP Checksum Off-load Enable */
+	Tuofl		= 0x00000200,	/* TCP/UDP Checksum Off-load Enable */
+};
+
+typedef struct Rdesc {			/* Receive Descriptor */
+	uint	addr[2];
+	ushort	length;
+	ushort	checksum;
+	uchar	status;
+	uchar	errors;
+	ushort	special;
+} Rdesc;
+
+enum {					/* Rdesc status */
+	Rdd		= 0x01,		/* Descriptor Done */
+	Reop		= 0x02,		/* End of Packet */
+	Ixsm		= 0x04,		/* Ignore Checksum Indication */
+	Vp		= 0x08,		/* Packet is 802.1Q (matched VET) */
+	Tcpcs		= 0x20,		/* TCP Checksum Calculated on Packet */
+	Ipcs		= 0x40,		/* IP Checksum Calculated on Packet */
+	Pif		= 0x80,		/* Passed in-exact filter */
+};
+
+enum {					/* Rdesc errors */
+	Ce		= 0x01,		/* CRC Error or Alignment Error */
+	Se		= 0x02,		/* Symbol Error */
+	Seq		= 0x04,		/* Sequence Error */
+	Cxe		= 0x10,		/* Carrier Extension Error */
+	Tcpe		= 0x20,		/* TCP/UDP Checksum Error */
+	Ipe		= 0x40,		/* IP Checksum Error */
+	Rxe		= 0x80,		/* RX Data Error */
+};
+
+typedef struct Tdesc {			/* Legacy+Normal Transmit Descriptor */
+	uint	addr[2];
+	uint	control;		/* varies with descriptor type */
+	uint	status;			/* varies with descriptor type */
+} Tdesc;
+
+enum {					/* Tdesc control */
+	LenMASK		= 0x000FFFFF,	/* Data/Packet Length Field */
+	LenSHIFT	= 0,
+	DtypeCD		= 0x00000000,	/* Data Type 'Context Descriptor' */
+	DtypeDD		= 0x00100000,	/* Data Type 'Data Descriptor' */
+	PtypeTCP	= 0x01000000,	/* TCP/UDP Packet Type (CD) */
+	Teop		= 0x01000000,	/* End of Packet (DD) */
+	PtypeIP		= 0x02000000,	/* IP Packet Type (CD) */
+	Ifcs		= 0x02000000,	/* Insert FCS (DD) */
+	Tse		= 0x04000000,	/* TCP Segmentation Enable */
+	Rs		= 0x08000000,	/* Report Status */
+	Rps		= 0x10000000,	/* Report Status Sent */
+	Dext		= 0x20000000,	/* Descriptor Extension */
+	Vle		= 0x40000000,	/* VLAN Packet Enable */
+	Ide		= 0x80000000,	/* Interrupt Delay Enable */
+};
+
+enum {					/* Tdesc status */
+	Tdd		= 0x00000001,	/* Descriptor Done */
+	Ec		= 0x00000002,	/* Excess Collisions */
+	Lc		= 0x00000004,	/* Late Collision */
+	Tu		= 0x00000008,	/* Transmit Underrun */
+	CssMASK		= 0x0000FF00,	/* Checksum Start Field */
+	CssSHIFT	= 8,
+};
+
+enum {
+	Nrdesc		= 128,		/* multiple of 8 */
+	Ntdesc		= 128,		/* multiple of 8 */
+};
+
+enum {
+	i82563,
+	i82571,
+	i82573,
+};
+
+static char *tname[] = {
+	"i82563",
+	"i82571",
+	"i82573",
+};
+
+#define Type	tname[ctlr->type]
+
+typedef struct Ctlr Ctlr;
+struct Ctlr {
+	int	port;
+	Pcidev	*pcidev;
+	Ctlr	*next;
+	int	active;
+	int	cls;
+	ushort	eeprom[0x40];
+	uchar	ra[Eaddrlen];		/* receive address */
+	int	type;
+
+	int*	nic;
+	Lock	imlock;
+	int	im;			/* interrupt mask */
+
+	Lock	slock;
+	uint	statistics[Nstatistics];
+
+	Rdesc	*rdba;			/* receive descriptor base address */
+	Block	**rb;			/* receive buffers */
+	int	rdh;			/* receive descriptor head */
+	int	rdt;			/* receive descriptor tail */
+
+	Tdesc	*tdba;			/* transmit descriptor base address */
+	Lock	tdlock;
+	Block	**tb;			/* transmit buffers */
+	int	tdh;			/* transmit descriptor head */
+	int	tdt;			/* transmit descriptor tail */
+
+	int	txcw;
+	int	fcrtl;
+	int	fcrth;
+
+	/* bootstrap goo */
+	Block	*bqhead;		/* transmission queue */
+	Block	*bqtail;
+};
+
+static Ctlr	*ctlrhead;
+static Ctlr	*ctlrtail;
+
+#define csr32r(c, r)	(*((c)->nic+((r)/4)))
+#define csr32w(c, r, v)	(*((c)->nic+((r)/4)) = (v))
+
+static void
+i82563im(Ctlr* ctlr, int im)
+{
+	ilock(&ctlr->imlock);
+	ctlr->im |= im;
+	csr32w(ctlr, Ims, ctlr->im);
+	iunlock(&ctlr->imlock);
+}
+
+static void
+i82563attach(Ether* edev)
+{
+	int ctl;
+	Ctlr *ctlr;
+
+	ctlr = edev->ctlr;
+	i82563im(ctlr, 0);
+	ctl = csr32r(ctlr, Rctl)|Ren;
+	csr32w(ctlr, Rctl, ctl);
+	ctl = csr32r(ctlr, Tctl)|Ten;
+	csr32w(ctlr, Tctl, ctl);
+}
+
+
+static void
+txstart(Ether *edev)
+{
+	int tdh, tdt;
+	Ctlr *ctlr = edev->ctlr;
+	Block *bp;
+	Tdesc *tdesc;
+
+	/*
+	 * Try to fill the ring back up, moving buffers from the transmit q.
+	 */
+	tdh = PREV(ctlr->tdh, Ntdesc);
+	for(tdt = ctlr->tdt; tdt != tdh; tdt = NEXT(tdt, Ntdesc)){
+		/* pull off the head of the transmission queue */
+		if((bp = ctlr->bqhead) == nil)	/* was qget(edev->oq) */
+			break;
+		ctlr->bqhead = bp->next;
+		if (ctlr->bqtail == bp)
+			ctlr->bqtail = nil;
+
+		/* set up a descriptor for it */
+		tdesc = &ctlr->tdba[tdt];
+		tdesc->addr[0] = PCIWADDR(bp->rp);
+		tdesc->addr[1] = 0;
+		tdesc->control = /* Ide | */ Rs | Ifcs | Teop | BLEN(bp);
+
+		ctlr->tb[tdt] = bp;
+	}
+	ctlr->tdt = tdt;
+	csr32w(ctlr, Tdt, tdt);
+	i82563im(ctlr, Txdw);
+}
+
+static Block *
+fromringbuf(Ether *ether)
+{
+	RingBuf *tb = &ether->tb[ether->ti];
+	Block *bp = allocb(tb->len);
+
+	memmove(bp->wp, tb->pkt, tb->len);
+	memmove(bp->wp+Eaddrlen, ether->ea, Eaddrlen);
+	bp->wp += tb->len;
+	return bp;
+}
+
+static void
+i82563transmit(Ether* edev)
+{
+	Block *bp;
+	Ctlr *ctlr;
+	Tdesc *tdesc;
+	RingBuf *tb;
+	int tdh;
+
+	ctlr = edev->ctlr;
+	ilock(&ctlr->tdlock);
+
+	/*
+	 * Free any completed packets
+	 * - try to get the soft tdh to catch the tdt;
+	 * - if the packet had an underrun bump the threshold
+	 *   - the Tu bit doesn't seem to ever be set, perhaps
+	 *     because Rs mode is used?
+	 */
+	tdh = ctlr->tdh;
+	for(;;){
+		tdesc = &ctlr->tdba[tdh];
+		if(!(tdesc->status & Tdd))
+			break;
+		if(ctlr->tb[tdh] != nil){
+			freeb(ctlr->tb[tdh]);
+			ctlr->tb[tdh] = nil;
+		}
+		tdesc->status = 0;
+		tdh = NEXT(tdh, Ntdesc);
+	}
+	ctlr->tdh = tdh;
+
+	/* copy packets from the software RingBuf to the transmission q */
+	while((tb = &edev->tb[edev->ti])->owner == Interface){
+		bp = fromringbuf(edev);
+//		print("#l%d: tx %d %E %E\n", edev->ctlrno, edev->ti, bp->rp,
+//			bp->rp+6);
+
+		if(ctlr->bqhead)
+			ctlr->bqtail->next = bp;
+		else
+			ctlr->bqhead = bp;
+		ctlr->bqtail = bp;
+
+		txstart(edev);		/* kick transmitter */
+		tb->owner = Host;	/* give descriptor back */
+		edev->ti = NEXT(edev->ti, edev->ntb);
+	}
+	iunlock(&ctlr->tdlock);
+}
+
+static void
+i82563replenish(Ctlr* ctlr)
+{
+	int rdt;
+	Block *bp;
+	Rdesc *rdesc;
+
+	rdt = ctlr->rdt;
+	while(NEXT(rdt, Nrdesc) != ctlr->rdh){
+		rdesc = &ctlr->rdba[rdt];
+		if(ctlr->rb[rdt] != nil){
+			/* nothing to do */
+		}
+		else if((bp = iallocb(2048)) != nil){
+			ctlr->rb[rdt] = bp;
+			rdesc->addr[0] = PCIWADDR(bp->rp);
+			rdesc->addr[1] = 0;
+		}
+		else
+			break;
+		rdesc->status = 0;
+
+		rdt = NEXT(rdt, Nrdesc);
+	}
+	ctlr->rdt = rdt;
+	csr32w(ctlr, Rdt, rdt);
+}
+
+static void
+toringbuf(Ether *ether, Block *bp)
+{
+	RingBuf *rb = &ether->rb[ether->ri];
+
+	if (rb->owner == Interface) {
+		rb->len = BLEN(bp);
+		memmove(rb->pkt, bp->rp, rb->len);
+		rb->owner = Host;
+		ether->ri = NEXT(ether->ri, ether->nrb);
+	} else if (debug)
+		print("#l%d: toringbuf: dropping packets @ ri %d\n",
+			ether->ctlrno, ether->ri);
+}
+
+static void
+i82563interrupt(Ureg*, void* arg)
+{
+	int icr, im, rdh, txdw = 0;
+	Block *bp;
+	Ctlr *ctlr;
+	Ether *edev;
+	Rdesc *rdesc;
+
+	edev = arg;
+	ctlr = edev->ctlr;
+
+	ilock(&ctlr->imlock);
+	csr32w(ctlr, Imc, ~0);
+	im = ctlr->im;
+
+	for(icr = csr32r(ctlr, Icr); icr & ctlr->im; icr = csr32r(ctlr, Icr)){
+		if(icr & (Rxseq|Lsc)){
+			/* should be more here */
+		}
+
+		rdh = ctlr->rdh;
+		for (;;) {
+			rdesc = &ctlr->rdba[rdh];
+			if(!(rdesc->status & Rdd))
+				break;
+			if ((rdesc->status & Reop) && rdesc->errors == 0) {
+				bp = ctlr->rb[rdh];
+				if(0 && memcmp(bp->rp, broadcast, 6) != 0)
+					print("#l%d: rx %d %E %E %d\n",
+						edev->ctlrno, rdh, bp->rp,
+						bp->rp+6, rdesc->length);
+				ctlr->rb[rdh] = nil;
+				bp->wp += rdesc->length;
+				toringbuf(edev, bp);
+				freeb(bp);
+			} else if (rdesc->status & Reop && rdesc->errors)
+				print("%s: input packet error 0x%ux\n",
+					Type, rdesc->errors);
+			rdesc->status = 0;
+			rdh = NEXT(rdh, Nrdesc);
+		}
+		ctlr->rdh = rdh;
+		if(icr & Rxdmt0)
+			i82563replenish(ctlr);
+		if(icr & Txdw){
+			im &= ~Txdw;
+			txdw++;
+		}
+	}
+	ctlr->im = im;
+	csr32w(ctlr, Ims, im);
+	iunlock(&ctlr->imlock);
+	if(txdw)
+		i82563transmit(edev);
+}
+
+static void
+i82563init(Ether* edev)
+{
+	int csr, i, r;
+	Ctlr *ctlr;
+
+	ctlr = edev->ctlr;
+	csr = edev->ea[3]<<24 | edev->ea[2]<<16 | edev->ea[1]<<8 | edev->ea[0];
+	csr32w(ctlr, Ral, csr);
+	csr = 0x80000000 | edev->ea[5]<<8 | edev->ea[4];
+	csr32w(ctlr, Rah, csr);
+	for (i = 1; i < 16; i++) {
+		csr32w(ctlr, Ral+i*8, 0);
+		csr32w(ctlr, Rah+i*8, 0);
+	}
+	for(i = 0; i < 128; i++)
+		csr32w(ctlr, Mta+i*4, 0);
+	csr32w(ctlr, Rctl, 0);
+	ctlr->rdba = xspanalloc(Nrdesc*sizeof(Rdesc), 256, 0);
+	csr32w(ctlr, Rdbal, PCIWADDR(ctlr->rdba));
+	csr32w(ctlr, Rdbah, 0);
+	csr32w(ctlr, Rdlen, Nrdesc*sizeof(Rdesc));
+	ctlr->rdh = 0;
+	csr32w(ctlr, Rdh, ctlr->rdh);
+	ctlr->rdt = 0;
+	csr32w(ctlr, Rdt, ctlr->rdt);
+	ctlr->rb = malloc(sizeof(Block*)*Nrdesc);
+	i82563replenish(ctlr);
+	csr32w(ctlr, Rdtr, 0);
+	csr32w(ctlr, Rctl, Dpf | Bsize2048 | Bam | RdtmsHALF);
+	i82563im(ctlr, Rxt0 | Rxo | Rxdmt0 | Rxseq | Ack);
+
+	csr32w(ctlr, Tctl, 0x0F<<CtSHIFT | Psp | 0x3f<<ColdSHIFT | Mulr);
+	csr32w(ctlr, Tipg, 6<<20 | 8<<10 | 8);
+	csr32w(ctlr, Tidv, 1);
+
+	ctlr->tdba = xspanalloc(Ntdesc*sizeof(Tdesc), 256, 0);
+	memset(ctlr->tdba, 0, Ntdesc*sizeof(Tdesc));
+	csr32w(ctlr, Tdbal, PCIWADDR(ctlr->tdba));
+
+	csr32w(ctlr, Tdbah, 0);
+	csr32w(ctlr, Tdlen, Ntdesc*sizeof(Tdesc));
+	ctlr->tdh = 0;
+	csr32w(ctlr, Tdh, ctlr->tdh);
+	ctlr->tdt = 0;
+	csr32w(ctlr, Tdt, ctlr->tdt);
+	ctlr->tb = malloc(sizeof(Block*)*Ntdesc);
+
+//	r = 4<<WthreshSHIFT | 4<<HthreshSHIFT | 8<<PthreshSHIFT;
+//	csr32w(ctlr, Txdctl, r);
+	csr32w(ctlr, Rxcsum, Tuofl | Ipofl | ETHERHDRSIZE<<PcssSHIFT);
+	r = csr32r(ctlr, Tctl);
+	r |= Ten;
+	csr32w(ctlr, Tctl, r);
+}
+
+
+static ushort
+eeread(Ctlr* ctlr, int adr)
+{
+	csr32w(ctlr, Eerd, ee_start | adr << 2);
+	while ((csr32r(ctlr, Eerd) & ee_done) == 0)
+		;
+	return csr32r(ctlr, Eerd) >> 16;
+}
+
+static int
+eeload(Ctlr* ctlr)
+{
+	ushort sum;
+	int data, adr;
+
+	sum = 0;
+	for (adr = 0; adr < 0x40; adr++) {
+		data = eeread(ctlr, adr);
+		ctlr->eeprom[adr] = data;
+		sum += data;
+	}
+	return sum;
+}
+
+
+static void
+detach(Ctlr *ctlr)
+{
+	int r;
+
+	csr32w(ctlr, Imc, ~0);
+	csr32w(ctlr, Rctl, 0);
+	csr32w(ctlr, Tctl, 0);
+
+	delay(10);
+
+	r = csr32r(ctlr, Ctrl);
+	csr32w(ctlr, Ctrl, Devrst | r);
+	/* apparently needed on multi-GHz processors to avoid infinite loops */
+	delay(1);
+	while(csr32r(ctlr, Ctrl) & Devrst)
+		;
+
+	if(1 || ctlr->type != i82563){
+		r = csr32r(ctlr, Ctrl);
+		csr32w(ctlr, Ctrl, Slu | r);
+	}
+
+	csr32w(ctlr, Ctrlext, Eerst | csr32r(ctlr, Ctrlext));
+	delay(1);
+	while(csr32r(ctlr, Ctrlext) & Eerst)
+		;
+
+	csr32w(ctlr, Imc, ~0);
+	delay(1);
+	while(csr32r(ctlr, Icr))
+		;
+}
+
+static void
+i82563detach(Ether *edev)
+{
+	detach(edev->ctlr);
+}
+
+static void
+i82563shutdown(Ether* ether)
+{
+	i82563detach(ether);
+}
+
+static int
+i82563reset(Ctlr* ctlr)
+{
+	int i, r;
+
+	detach(ctlr);
+
+	r = eeload(ctlr);
+	if (r != 0 && r != 0xBABA){
+		print("%s: bad EEPROM checksum - 0x%4.4ux\n", Type, r);
+		return -1;
+	}
+
+	for(i = Ea; i < Eaddrlen/2; i++){
+		ctlr->ra[2*i]   = ctlr->eeprom[i];
+		ctlr->ra[2*i+1] = ctlr->eeprom[i]>>8;
+	}
+	r = (csr32r(ctlr, Status) & Lanid) >> 2;
+	ctlr->ra[5] += r;		/* ea ctlr[1] = ea ctlr[0]+1 */
+
+	r = ctlr->ra[3]<<24 | ctlr->ra[2]<<16 | ctlr->ra[1]<<8 | ctlr->ra[0];
+	csr32w(ctlr, Ral, r);
+	r = 0x80000000 | ctlr->ra[5]<<8 | ctlr->ra[4];
+	csr32w(ctlr, Rah, r);
+	for(i = 1; i < 16; i++){
+		csr32w(ctlr, Ral+i*8, 0);
+		csr32w(ctlr, Rah+i*8, 0);
+	}
+
+	for(i = 0; i < 128; i++)
+		csr32w(ctlr, Mta+i*4, 0);
+
+	csr32w(ctlr, Fcal, 0x00C28001);
+	csr32w(ctlr, Fcah, 0x00000100);
+	csr32w(ctlr, Fct,  0x00008808);
+	csr32w(ctlr, Fcttv, 0x00000100);
+
+	csr32w(ctlr, Fcrtl, ctlr->fcrtl);
+	csr32w(ctlr, Fcrth, ctlr->fcrth);
+
+	ilock(&ctlr->imlock);
+	csr32w(ctlr, Imc, ~0);
+	ctlr->im = 0;		/* was = Lsc, which hangs some controllers */
+	csr32w(ctlr, Ims, ctlr->im);
+	iunlock(&ctlr->imlock);
+
+	return 0;
+}
+
+static void
+i82563pci(void)
+{
+	int port, type, cls;
+	Pcidev *p;
+	Ctlr *ctlr;
+	static int first = 1;
+
+	if (first)
+		first = 0;
+	else
+		return;
+
+	p = nil;
+	while(p = pcimatch(p, 0x8086, 0)){
+		switch(p->did){
+		case 0x1096:
+		case 0x10ba:
+			type = i82563;
+			break;
+		case 0x108b:		/*  e */
+		case 0x108c:		/*  e (iamt) */
+		case 0x109a:		/*  l */
+			type = i82573;
+			break;
+		default:
+			continue;
+		}
+
+		port = upamalloc(p->mem[0].bar & ~0x0F, p->mem[0].size, 0);
+		if(port == 0){
+			print("%s: can't map %d @ 0x%8.8lux\n", tname[type],
+				p->mem[0].size, p->mem[0].bar);
+			continue;
+		}
+
+		if(p->pcr & MemWrInv){
+			cls = pcicfgr8(p, PciCLS) * 4;
+			if(cls != CACHELINESZ)
+				pcicfgw8(p, PciCLS, CACHELINESZ/4);
+		}
+
+		cls = pcicfgr8(p, PciCLS);
+		switch(cls){
+		default:
+			print("%s: unexpected CLS - %d bytes\n",
+				tname[type], cls*sizeof(long));
+			break;
+		case 0x00:
+		case 0xFF:
+			/* alphapc 164lx returns 0 */
+			print("%s: unusable PciCLS: %d, using %d longs\n",
+				tname[type], cls, CACHELINESZ/sizeof(long));
+			cls = CACHELINESZ/sizeof(long);
+			pcicfgw8(p, PciCLS, cls);
+			break;
+		case 0x08:
+		case 0x10:
+			break;
+		}
+
+		ctlr = malloc(sizeof(Ctlr));
+		ctlr->port = port;
+		ctlr->pcidev = p;
+		ctlr->cls = cls*4;
+		ctlr->type = type;
+		ctlr->nic = KADDR(ctlr->port);
+		if(i82563reset(ctlr)){
+			free(ctlr);
+			continue;
+		}
+		pcisetbme(p);
+
+		if(ctlrhead != nil)
+			ctlrtail->next = ctlr;
+		else
+			ctlrhead = ctlr;
+		ctlrtail = ctlr;
+	}
+}
+
+static uchar nilea[Eaddrlen];
+
+int
+i82563pnp(Ether* edev)
+{
+	Ctlr *ctlr;
+
+	if(ctlrhead == nil)
+		i82563pci();
+
+	/*
+	 * Any adapter matches if no edev->port is supplied,
+	 * otherwise the ports must match.
+	 */
+	for(ctlr = ctlrhead; ctlr != nil; ctlr = ctlr->next){
+		if(ctlr->active)
+			continue;
+		if(edev->port == 0 || edev->port == ctlr->port){
+			ctlr->active = 1;
+			break;
+		}
+	}
+	if(ctlr == nil)
+		return -1;
+
+	edev->ctlr = ctlr;
+	edev->port = ctlr->port;
+	edev->irq = ctlr->pcidev->intl;
+	edev->tbdf = ctlr->pcidev->tbdf;
+//	edev->mbps = 1000;
+
+	if(memcmp(edev->ea, nilea, Eaddrlen) == 0)
+		memmove(edev->ea, ctlr->ra, Eaddrlen);
+	i82563init(edev);
+
+	/*
+	 * Linkage to the generic ethernet driver.
+	 */
+	edev->attach = i82563attach;
+	edev->transmit = i82563transmit;
+	edev->interrupt = i82563interrupt;
+	edev->detach = i82563detach;
+
+	/*
+	 * with the current structure, there is no right place for this.
+	 * ideally, we recognize the interface, note it's down and move on.
+	 * currently either we can skip the interface or note it is down,
+	 * but not both.
+	 */
+	if((csr32r(ctlr, Status)&Lu) == 0){
+		print("ether#%d: 82563 (%s): link down\n", edev->ctlrno, Type);
+		return -1;
+	}
+
+	return 0;
+}
--- /dev/null
+++ b/os/boot.original/pc/ether83815.c
@@ -1,0 +1,820 @@
+/*
+ * National Semiconductor DP83815
+ *
+ * Supports only internal PHY and has been tested on:
+ *	Netgear FA311TX (using Netgear DS108 10/100 hub)
+ * To do:
+ *	check Ethernet address;
+ *	test autonegotiation on 10 Mbit, and 100 Mbit full duplex;
+ *	external PHY via MII (should be common code for MII);
+ *	thresholds;
+ *	ring sizing;
+ *	physical link changes/disconnect;
+ *	push initialisation back to attach.
+ *
+ * C H Forsyth, forsyth@vitanuova.com, 18th June 2001.
+ */
+
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+#include "etherif.h"
+
+#define DEBUG		(1)
+#define debug		if(DEBUG)print
+
+enum {
+	Nrde		= 8,
+	Ntde		= 8,
+};
+
+#define Rbsz		ROUNDUP(sizeof(Etherpkt)+4, 4)
+
+typedef struct Des {
+	ulong	next;
+	int	cmdsts;
+	ulong	addr;
+	Block*	bp;
+} Des;
+
+enum {	/* cmdsts */
+	Own		= 1<<31,	/* set by data producer to hand to consumer */
+	More	= 1<<30,	/* more of packet in next descriptor */
+	Intr		= 1<<29,	/* interrupt when device is done with it */
+	Supcrc	= 1<<28,	/* suppress crc on transmit */
+	Inccrc	= 1<<28,	/* crc included on receive (always) */
+	Ok		= 1<<27,	/* packet ok */
+	Size		= 0xFFF,	/* packet size in bytes */
+
+	/* transmit */
+	Txa	= 1<<26,	/* transmission aborted */
+	Tfu	= 1<<25,	/* transmit fifo underrun */
+	Crs	= 1<<24,	/* carrier sense lost */
+	Td	= 1<<23,	/* transmission deferred */
+	Ed	= 1<<22,	/* excessive deferral */
+	Owc	= 1<<21,	/* out of window collision */
+	Ec	= 1<<20,	/* excessive collisions */
+	/* 19-16 collision count */
+
+	/* receive */
+	Rxa	= 1<<26,	/* receive aborted (same as Rxo) */
+	Rxo	= 1<<25,	/* receive overrun */
+	Dest	= 3<<23,	/* destination class */
+	  Drej=	0<<23,		/* packet was rejected */
+	  Duni=	1<<23,		/* unicast */
+	  Dmulti=	2<<23,		/* multicast */
+	  Dbroad=	3<<23,		/* broadcast */
+	Long = 1<<22,	/* too long packet received */
+	Runt =  1<<21,	/* packet less than 64 bytes */
+	Ise =	1<<20,	/* invalid symbol */
+	Crce =	1<<19,	/* invalid crc */
+	Fae =	1<<18,	/* frame alignment error */
+	Lbp =	1<<17,	/* loopback packet */
+	Col =	1<<16,	/* collision during receive */
+};
+
+enum {					/* Variants */
+	Nat83815		= (0x0020<<16)|0x100B,
+};
+
+typedef struct Ctlr Ctlr;
+typedef struct Ctlr {
+	int	port;
+	Pcidev*	pcidev;
+	Ctlr*	next;
+	int	active;
+	int	id;			/* (pcidev->did<<16)|pcidev->vid */
+
+	ushort	srom[0xB+1];
+	uchar	sromea[Eaddrlen];			/* MAC address */
+
+	uchar	fd;			/* option or auto negotiation */
+
+	int	mbps;
+
+	Lock	ilock;
+
+	Des*	rdr;			/* receive descriptor ring */
+	int	nrdr;			/* size of rdr */
+	int	rdrx;			/* index into rdr */
+
+	Lock	tlock;
+	Des*	tdr;			/* transmit descriptor ring */
+	int	ntdr;			/* size of tdr */
+	int	tdrh;			/* host index into tdr */
+	int	tdri;			/* interface index into tdr */
+	int	ntq;			/* descriptors active */
+	int	ntqmax;
+	Block*	bqhead;	/* transmission queue */
+	Block*	bqtail;
+
+	ulong	rxa;			/* receive statistics */
+	ulong	rxo;
+	ulong	rlong;
+	ulong	runt;
+	ulong	ise;
+	ulong	crce;
+	ulong	fae;
+	ulong	lbp;
+	ulong	col;
+	ulong	rxsovr;
+	ulong	rxorn;
+
+	ulong	txa;			/* transmit statistics */
+	ulong	tfu;
+	ulong	crs;
+	ulong	td;
+	ulong	ed;
+	ulong	owc;
+	ulong	ec;
+	ulong	txurn;
+
+	ulong	dperr;		/* system errors */
+	ulong	rmabt;
+	ulong	rtabt;
+	ulong	sserr;
+	ulong	rxsover;
+} Ctlr;
+
+static Ctlr* ctlrhead;
+static Ctlr* ctlrtail;
+
+enum {
+	/* registers (could memory map) */
+	Rcr=		0x00,	/* command register */
+	  Rst=		1<<8,
+	  Rxr=		1<<5,	/* receiver reset */
+	  Txr=		1<<4,	/* transmitter reset */
+	  Rxd=		1<<3,	/* receiver disable */
+	  Rxe=		1<<2,	/* receiver enable */
+	  Txd=		1<<1,	/* transmitter disable */
+	  Txe=		1<<0,	/* transmitter enable */
+	Rcfg=	0x04,	/* configuration */
+	  Lnksts=		1<<31,	/* link good */
+	  Speed100=	1<<30,	/* 100 Mb/s link */
+	  Fdup=		1<<29,	/* full duplex */
+	  Pol=		1<<28,	/* polarity reversal (10baseT) */
+	  Aneg_dn=	1<<27,	/* autonegotiation done */
+	  Pint_acen=	1<<17,	/* PHY interrupt auto clear enable */
+	  Pause_adv=	1<<16,	/* advertise pause during auto neg */
+	  Paneg_ena=	1<<13,	/* auto negotiation enable */
+	  Paneg_all=	7<<13,	/* auto negotiation enable 10/100 half & full */
+	  Ext_phy=	1<<12,	/* enable MII for external PHY */
+	  Phy_rst=		1<<10,	/* reset internal PHY */
+	  Phy_dis=		1<<9,	/* disable internal PHY (eg, low power) */
+	  Req_alg=	1<<7,	/* PCI bus request: set means less aggressive */
+	  Sb=			1<<6,	/* single slot back-off not random */
+	  Pow=		1<<5,	/* out of window timer selection */
+	  Exd=		1<<4,	/* disable excessive deferral timer */
+	  Pesel=		1<<3,	/* parity error algorithm selection */
+	  Brom_dis=	1<<2,	/* disable boot rom interface */
+	  Bem=		1<<0,	/* big-endian mode */
+	Rmear=	0x08,	/* eeprom access */
+	  Mdc=		1<<6,	/* MII mangement check */
+	  Mddir=		1<<5,	/* MII management direction */
+	  Mdio=		1<<4,	/* MII mangement data */
+	  Eesel=		1<<3,	/* EEPROM chip select */
+	  Eeclk=		1<<2,	/* EEPROM clock */
+	  Eedo=		1<<1,	/* EEPROM data out (from chip) */
+	  Eedi=		1<<0,	/* EEPROM data in (to chip) */
+	Rptscr=	0x0C,	/* pci test control */
+	Risr=		0x10,	/* interrupt status */
+	  Txrcmp=	1<<25,	/* transmit reset complete */
+	  Rxrcmp=	1<<24,	/* receiver reset complete */
+	  Dperr=		1<<23,	/* detected parity error */
+	  Sserr=		1<<22,	/* signalled system error */
+	  Rmabt=		1<<21,	/* received master abort */
+	  Rtabt=		1<<20,	/* received target abort */
+	  Rxsovr=		1<<16,	/* RX status FIFO overrun */
+	  Hiberr=		1<<15,	/* high bits error set (OR of 25-16) */
+	  Phy=		1<<14,	/* PHY interrupt */
+	  Pme=		1<<13,	/* power management event (wake online) */
+	  Swi=		1<<12,	/* software interrupt */
+	  Mib=		1<<11,	/* MIB service */
+	  Txurn=		1<<10,	/* TX underrun */
+	  Txidle=		1<<9,	/* TX idle */
+	  Txerr=		1<<8,	/* TX packet error */
+	  Txdesc=		1<<7,	/* TX descriptor (with Intr bit done) */
+	  Txok=		1<<6,	/* TX ok */
+	  Rxorn=		1<<5,	/* RX overrun */
+	  Rxidle=		1<<4,	/* RX idle */
+	  Rxearly=		1<<3,	/* RX early threshold */
+	  Rxerr=		1<<2,	/* RX packet error */
+	  Rxdesc=		1<<1,	/* RX descriptor (with Intr bit done) */
+	  Rxok=		1<<0,	/* RX ok */
+	Rimr=	0x14,	/* interrupt mask */
+	Rier=	0x18,	/* interrupt enable */
+	  Ie=			1<<0,	/* interrupt enable */
+	Rtxdp=	0x20,	/* transmit descriptor pointer */
+	Rtxcfg=	0x24,	/* transmit configuration */
+	  Csi=		1<<31,	/* carrier sense ignore (needed for full duplex) */
+	  Hbi=		1<<30,	/* heartbeat ignore (needed for full duplex) */
+	  Atp=		1<<28,	/* automatic padding of runt packets */
+	  Mxdma=		7<<20,	/* maximum dma transfer field */
+	  Mxdma32=	4<<20,	/* 4x32-bit words (32 bytes) */
+	  Mxdma64=	5<<20,	/* 8x32-bit words (64 bytes) */
+	  Flth=		0x3F<<8,	/* Tx fill threshold, units of 32 bytes (must be > Mxdma) */
+	  Drth=		0x3F<<0,	/* Tx drain threshold (units of 32 bytes) */
+	  Flth128=		4<<8,	/* fill at 128 bytes */
+	  Drth512=	16<<0,	/* drain at 512 bytes */
+	Rrxdp=	0x30,	/* receive descriptor pointer */
+	Rrxcfg=	0x34,	/* receive configuration */
+	  Atx=		1<<28,	/* accept transmit packets (needed for full duplex) */
+	  Rdrth=		0x1F<<1,	/* Rx drain threshold (units of 32 bytes) */
+	  Rdrth64=	2<<1,	/* drain at 64 bytes */
+	Rccsr=	0x3C,	/* CLKRUN control/status */
+	  Pmests=		1<<15,	/* PME status */
+	Rwcsr=	0x40,	/* wake on lan control/status */
+	Rpcr=	0x44,	/* pause control/status */
+	Rrfcr=	0x48,	/* receive filter/match control */
+	  Rfen=		1<<31,	/* receive filter enable */
+	  Aab=		1<<30,	/* accept all broadcast */
+	  Aam=		1<<29,	/* accept all multicast */
+	  Aau=		1<<28,	/* accept all unicast */
+	  Apm=		1<<27,	/* accept on perfect match */
+	  Apat=		0xF<<23,	/* accept on pattern match */
+	  Aarp=		1<<22,	/* accept ARP */
+	  Mhen=		1<<21,	/* multicast hash enable */
+	  Uhen=		1<<20,	/* unicast hash enable */
+	  Ulm=		1<<19,	/* U/L bit mask */
+						/* bits 0-9 are rfaddr */
+	Rrfdr=	0x4C,	/* receive filter/match data */
+	Rbrar=	0x50,	/* boot rom address */
+	Rbrdr=	0x54,	/* boot rom data */
+	Rsrr=	0x58,	/* silicon revision */
+	Rmibc=	0x5C,	/* MIB control */
+					/* 60-78 MIB data */
+
+	/* PHY registers */
+	Rbmcr=	0x80,	/* basic mode configuration */
+	  Reset=		1<<15,
+	  Sel100=		1<<13,	/* select 100Mb/sec if no auto neg */
+	  Anena=		1<<12,	/* auto negotiation enable */
+	  Anrestart=	1<<9,	/* restart auto negotiation */
+	  Selfdx=		1<<8,	/* select full duplex if no auto neg */
+	Rbmsr=	0x84,	/* basic mode status */
+	  Ancomp=	1<<5,	/* autonegotiation complete */
+	Rphyidr1= 0x88,
+	Rphyidr2= 0x8C,
+	Ranar=	0x90,	/* autonegotiation advertisement */
+	Ranlpar=	0x94,	/* autonegotiation link partner ability */
+	Raner=	0x98,	/* autonegotiation expansion */
+	Rannptr=	0x9C,	/* autonegotiation next page TX */
+	Rphysts=	0xC0,	/* PHY status */
+	Rmicr=	0xC4,	/* MII control */
+	  Inten=		1<<1,	/* PHY interrupt enable */
+	Rmisr=	0xC8,	/* MII status */
+	Rfcscr=	0xD0,	/* false carrier sense counter */
+	Rrecr=	0xD4,	/* receive error counter */
+	Rpcsr=	0xD8,	/* 100Mb config/status */
+	Rphycr=	0xE4,	/* PHY control */
+	Rtbscr=	0xE8,	/* 10BaseT status/control */
+};
+
+/*
+ * eeprom addresses
+ * 	7 to 9 (16 bit words): mac address, shifted and reversed
+ */
+
+#define csr32r(c, r)	(inl((c)->port+(r)))
+#define csr32w(c, r, l)	(outl((c)->port+(r), (ulong)(l)))
+#define csr16r(c, r)	(ins((c)->port+(r)))
+#define csr16w(c, r, l)	(outs((c)->port+(r), (ulong)(l)))
+
+static void
+dumpcregs(Ctlr *ctlr)
+{
+	int i;
+
+	for(i=0; i<=0x5C; i+=4)
+		print("%2.2ux %8.8lux\n", i, csr32r(ctlr, i));
+}
+
+static void
+attach(Ether* ether)
+{
+	Ctlr *ctlr;
+
+	ctlr = ether->ctlr;
+	ilock(&ctlr->ilock);
+	if(0)
+		dumpcregs(ctlr);
+	csr32w(ctlr, Rcr, Rxe);
+	iunlock(&ctlr->ilock);
+}
+
+static void
+detach(Ether* ether)
+{
+	Ctlr *ctlr;
+
+	ctlr = ether->ctlr;
+	csr32w(ctlr, Rcr, 0);
+	delay(1);
+}
+
+static void
+txstart(Ether* ether)
+{
+	Ctlr *ctlr;
+	Block *bp;
+	Des *des;
+	int started;
+
+	ctlr = ether->ctlr;
+	started = 0;
+	while(ctlr->ntq < ctlr->ntdr-1){
+		bp = ctlr->bqhead;
+		if(bp == nil)
+			break;
+		ctlr->bqhead = bp->next;
+		des = &ctlr->tdr[ctlr->tdrh];
+		des->bp = bp;
+		des->addr = PADDR(bp->rp);
+		ctlr->ntq++;
+		coherence();
+		des->cmdsts = Own | BLEN(bp);
+		ctlr->tdrh = NEXT(ctlr->tdrh, ctlr->ntdr);
+		started = 1;
+	}
+	if(started){
+		coherence();
+		csr32w(ctlr, Rcr, Txe);	/* prompt */
+	}
+
+	if(ctlr->ntq > ctlr->ntqmax)
+		ctlr->ntqmax = ctlr->ntq;
+}
+
+static void
+transmit(Ether* ether)
+{
+	Ctlr *ctlr;
+	Block *bp;
+	RingBuf *tb;
+
+	ctlr = ether->ctlr;
+	ilock(&ctlr->tlock);
+	while((tb = &ether->tb[ether->ti])->owner == Interface){
+		bp = allocb(tb->len);
+		memmove(bp->wp, tb->pkt, tb->len);
+		memmove(bp->wp+Eaddrlen, ether->ea, Eaddrlen);
+		bp->wp += tb->len;
+		if(ctlr->bqhead)
+			ctlr->bqtail->next = bp;
+		else
+			ctlr->bqhead = bp;
+		ctlr->bqtail = bp;
+		txstart(ether);
+		tb->owner = Host;
+		ether->ti = NEXT(ether->ti, ether->ntb);
+	}
+	iunlock(&ctlr->tlock);
+}
+
+static void
+txrxcfg(Ctlr *ctlr, int txdrth)
+{
+	ulong rx, tx;
+
+	rx = csr32r(ctlr, Rrxcfg);
+	tx = csr32r(ctlr, Rtxcfg);
+	if(ctlr->fd){
+		rx |= Atx;
+		tx |= Csi | Hbi;
+	}else{
+		rx &= ~Atx;
+		tx &= ~(Csi | Hbi);
+	}
+	tx &= ~(Mxdma|Drth|Flth);
+	tx |= Mxdma64 | Flth128 | txdrth;
+	csr32w(ctlr, Rtxcfg, tx);
+	rx &= ~(Mxdma|Rdrth);
+	rx |= Mxdma64 | Rdrth64;
+	csr32w(ctlr, Rrxcfg, rx);
+}
+
+static void
+interrupt(Ureg*, void* arg)
+{
+	Ctlr *ctlr;
+	Ether *ether;
+	int status, cmdsts;
+	Des *des;
+	RingBuf *rb;
+
+	ether = arg;
+	ctlr = ether->ctlr;
+
+	while((status = csr32r(ctlr, Risr)) != 0){
+
+		status &= ~(Pme|Mib);
+		status &= ~(Hiberr|Txrcmp|Rxrcmp|Rxsovr|Dperr|Sserr|Rmabt|Rtabt);
+
+		/*
+		 * Received packets.
+		 */
+		if(status & (Rxdesc|Rxok|Rxerr|Rxearly|Rxorn)){
+			des = &ctlr->rdr[ctlr->rdrx];
+			while((cmdsts = des->cmdsts) & Own){
+				rb = &ether->rb[ether->ri];
+				if(rb->owner == Interface && (cmdsts&Ok)){
+					rb->len = (cmdsts&Size)-4;
+					memmove(rb->pkt, des->bp->rp, rb->len);
+					rb->owner = Host;
+					ether->ri = NEXT(ether->ri, ether->nrb);
+				}
+
+				des->cmdsts = Rbsz;
+				coherence();
+
+				ctlr->rdrx = NEXT(ctlr->rdrx, ctlr->nrdr);
+				des = &ctlr->rdr[ctlr->rdrx];
+			}
+			status &= ~(Rxdesc|Rxok|Rxerr|Rxearly|Rxorn);
+		}
+
+		/*
+		 * Check the transmit side:
+		 *	check for Transmit Underflow and Adjust
+		 *	the threshold upwards;
+		 *	free any transmitted buffers and try to
+		 *	top-up the ring.
+		 */
+		if(status & Txurn){
+			ctlr->txurn++;
+			ilock(&ctlr->ilock);
+			/* change threshold */
+			iunlock(&ctlr->ilock);
+			status &= ~(Txurn);
+		}
+
+		ilock(&ctlr->tlock);
+		while(ctlr->ntq){
+			des = &ctlr->tdr[ctlr->tdri];
+			cmdsts = des->cmdsts;
+			if(cmdsts & Own)
+				break;
+
+			freeb(des->bp);
+			des->bp = nil;
+			des->cmdsts = 0;
+
+			ctlr->ntq--;
+			ctlr->tdri = NEXT(ctlr->tdri, ctlr->ntdr);
+		}
+		txstart(ether);
+		iunlock(&ctlr->tlock);
+
+		status &= ~(Txurn|Txidle|Txerr|Txdesc|Txok);
+
+		/*
+		 * Anything left not catered for?
+		 */
+		if(status)
+			print("#l%d: status %8.8uX\n", ether->ctlrno, status);
+	}
+}
+
+static void
+ctlrinit(Ether* ether)
+{
+	Ctlr *ctlr;
+	Des *des, *last;
+
+	ctlr = ether->ctlr;
+
+	/*
+	 * Allocate and initialise the receive ring;
+	 * allocate and initialise the transmit ring;
+	 * unmask interrupts and start the transmit side
+	 */
+	ctlr->rdr = malloc(ctlr->nrdr*sizeof(Des));
+	last = nil;
+	for(des = ctlr->rdr; des < &ctlr->rdr[ctlr->nrdr]; des++){
+		des->bp = allocb(Rbsz);
+		des->cmdsts = Rbsz;
+		des->addr = PADDR(des->bp->rp);
+		if(last != nil)
+			last->next = PADDR(des);
+		last = des;
+	}
+	ctlr->rdr[ctlr->nrdr-1].next = PADDR(ctlr->rdr);
+	ctlr->rdrx = 0;
+	csr32w(ctlr, Rrxdp, PADDR(ctlr->rdr));
+
+	ctlr->tdr = xspanalloc(ctlr->ntdr*sizeof(Des), 8*sizeof(ulong), 0);
+	last = nil;
+	for(des = ctlr->tdr; des < &ctlr->tdr[ctlr->ntdr]; des++){
+		des->cmdsts = 0;
+		des->bp = nil;
+		des->addr = ~0;
+		if(last != nil)
+			last->next = PADDR(des);
+		last = des;
+	}
+	ctlr->tdr[ctlr->ntdr-1].next = PADDR(ctlr->tdr);
+	ctlr->tdrh = 0;
+	ctlr->tdri = 0;
+	csr32w(ctlr, Rtxdp, PADDR(ctlr->tdr));
+
+	txrxcfg(ctlr, Drth512);
+
+	csr32w(ctlr, Rimr, Dperr|Sserr|Rmabt|Rtabt|Rxsovr|Hiberr|Txurn|Txerr|Txdesc|Txok|Rxorn|Rxerr|Rxdesc|Rxok);	/* Phy|Pme|Mib */
+	csr32r(ctlr, Risr);	/* clear status */
+	csr32w(ctlr, Rier, Ie);
+}
+
+static void
+eeclk(Ctlr *ctlr, int clk)
+{
+	csr32w(ctlr, Rmear, Eesel | clk);
+	microdelay(2);
+}
+
+static void
+eeidle(Ctlr *ctlr)
+{
+	int i;
+
+	eeclk(ctlr, 0);
+	eeclk(ctlr, Eeclk);
+	for(i=0; i<25; i++){
+		eeclk(ctlr, 0);
+		eeclk(ctlr, Eeclk);
+	}
+	eeclk(ctlr, 0);
+	csr32w(ctlr, Rmear, 0);
+	microdelay(2);
+}
+
+static int
+eegetw(Ctlr *ctlr, int a)
+{
+	int d, i, w, v;
+
+	eeidle(ctlr);
+	eeclk(ctlr, 0);
+	eeclk(ctlr, Eeclk);
+	d = 0x180 | a;
+	for(i=0x400; i; i>>=1){
+		v = (d & i) ? Eedi : 0;
+		eeclk(ctlr, v);
+		eeclk(ctlr, Eeclk|v);
+	}
+	eeclk(ctlr, 0);
+
+	w = 0;
+	for(i=0x8000; i; i >>= 1){
+		eeclk(ctlr, Eeclk);
+		if(csr32r(ctlr, Rmear) & Eedo)
+			w |= i;
+		microdelay(2);
+		eeclk(ctlr, 0);
+	}
+	eeidle(ctlr);
+	return w;
+}
+
+static void
+softreset(Ctlr* ctlr, int resetphys)
+{
+	int i, w;
+
+	/*
+	 * Soft-reset the controller
+	 */
+	csr32w(ctlr, Rcr, Rst);
+	for(i=0;; i++){
+		if(i > 100)
+			panic("ns83815: soft reset did not complete");
+		microdelay(250);
+		if((csr32r(ctlr, Rcr) & Rst) == 0)
+			break;
+		delay(1);
+	}
+
+	csr32w(ctlr, Rccsr, Pmests);
+	csr32w(ctlr, Rccsr, 0);
+	csr32w(ctlr, Rcfg, csr32r(ctlr, Rcfg) | Pint_acen);
+
+	if(resetphys){
+		/*
+		 * Soft-reset the PHY
+		 */
+		csr32w(ctlr, Rbmcr, Reset);
+		for(i=0;; i++){
+			if(i > 100)
+				panic("ns83815: PHY soft reset time out");
+			if((csr32r(ctlr, Rbmcr) & Reset) == 0)
+				break;
+			delay(1);
+		}
+	}
+
+	/*
+	 * Initialisation values, in sequence (see 4.4 Recommended Registers Configuration)
+	 */
+	csr16w(ctlr, 0xCC, 0x0001);	/* PGSEL */
+	csr16w(ctlr, 0xE4, 0x189C);	/* PMCCSR */
+	csr16w(ctlr, 0xFC, 0x0000);	/* TSTDAT */
+	csr16w(ctlr, 0xF4, 0x5040);	/* DSPCFG */
+	csr16w(ctlr, 0xF8, 0x008C);	/* SDCFG */
+
+	/*
+	 * Auto negotiate
+	 */
+	w = csr16r(ctlr, Rbmsr);	/* clear latched bits */
+	debug("anar: %4.4ux\n", csr16r(ctlr, Ranar));
+	csr16w(ctlr, Rbmcr, Anena);
+	if(csr16r(ctlr, Ranar) == 0 || (csr32r(ctlr, Rcfg) & Aneg_dn) == 0){
+		csr16w(ctlr, Rbmcr, Anena|Anrestart);
+		for(i=0;; i++){
+			if(i > 6000){
+				print("ns83815: auto neg timed out\n");
+				break;
+			}
+			if((w = csr16r(ctlr, Rbmsr)) & Ancomp)
+				break;
+			delay(1);
+		}
+		debug("%d ms\n", i);
+		w &= 0xFFFF;
+		debug("bmsr: %4.4ux\n", w);
+	}
+	debug("anar: %4.4ux\n", csr16r(ctlr, Ranar));
+	debug("anlpar: %4.4ux\n", csr16r(ctlr, Ranlpar));
+	debug("aner: %4.4ux\n", csr16r(ctlr, Raner));
+	debug("physts: %4.4ux\n", csr16r(ctlr, Rphysts));
+	debug("tbscr: %4.4ux\n", csr16r(ctlr, Rtbscr));
+}
+
+static char* mediatable[9] = {
+	"10BASE-T",				/* TP */
+	"10BASE-2",				/* BNC */
+	"10BASE-5",				/* AUI */
+	"100BASE-TX",
+	"10BASE-TFD",
+	"100BASE-TXFD",
+	"100BASE-T4",
+	"100BASE-FX",
+	"100BASE-FXFD",
+};
+
+static void
+srom(Ctlr* ctlr)
+{
+	int i, j;
+
+	for(i = 0; i < nelem(ctlr->srom); i++)
+		ctlr->srom[i] = eegetw(ctlr, i);
+
+	/*
+	 * the MAC address is reversed, straddling word boundaries
+	 */
+	memset(ctlr->sromea, 0, sizeof(ctlr->sromea));
+	j = 6*16 + 15;
+	for(i=0; i<48; i++){
+		ctlr->sromea[i>>3] |= ((ctlr->srom[j>>4] >> (15-(j&0xF))) & 1) << (i&7);
+		j++;
+	}
+}
+
+static void
+scanpci83815(void)
+{
+	Ctlr *ctlr;
+	Pcidev *p;
+
+	p = nil;
+	while(p = pcimatch(p, 0, 0)){
+		if(p->ccrb != 0x02 || p->ccru != 0)
+			continue;
+		switch((p->did<<16)|p->vid){
+		default:
+			continue;
+
+		case Nat83815:
+			break;
+		}
+
+		/*
+		 * bar[0] is the I/O port register address and
+		 * bar[1] is the memory-mapped register address.
+		 */
+		ctlr = malloc(sizeof(Ctlr));
+		ctlr->port = p->mem[0].bar & ~0x01;
+		ctlr->pcidev = p;
+		ctlr->id = (p->did<<16)|p->vid;
+
+		softreset(ctlr, 0);
+		srom(ctlr);
+
+		if(ctlrhead != nil)
+			ctlrtail->next = ctlr;
+		else
+			ctlrhead = ctlr;
+		ctlrtail = ctlr;
+	}
+}
+
+int
+ether83815reset(Ether* ether)
+{
+	Ctlr *ctlr;
+	int i, x;
+	uchar ea[Eaddrlen];
+	static int scandone;
+
+	if(scandone == 0){
+		scanpci83815();
+		scandone = 1;
+	}
+
+	/*
+	 * Any adapter matches if no ether->port is supplied,
+	 * otherwise the ports must match.
+	 */
+	for(ctlr = ctlrhead; ctlr != nil; ctlr = ctlr->next){
+		if(ctlr->active)
+			continue;
+		if(ether->port == 0 || ether->port == ctlr->port){
+			ctlr->active = 1;
+			break;
+		}
+	}
+	if(ctlr == nil)
+		return -1;
+
+	ether->ctlr = ctlr;
+	ether->port = ctlr->port;
+	ether->irq = ctlr->pcidev->intl;
+	ether->tbdf = ctlr->pcidev->tbdf;
+
+	/*
+	 * Check if the adapter's station address is to be overridden.
+	 * If not, read it from the EEPROM and set in ether->ea prior to
+	 * loading the station address in the hardware.
+	 */
+	memset(ea, 0, Eaddrlen);
+	if(memcmp(ea, ether->ea, Eaddrlen) == 0)
+		memmove(ether->ea, ctlr->sromea, Eaddrlen);
+	for(i=0; i<Eaddrlen; i+=2){
+		x = ether->ea[i] | (ether->ea[i+1]<<8);
+		csr32w(ctlr, Rrfcr, i);
+		csr32w(ctlr, Rrfdr, x);
+	}
+	csr32w(ctlr, Rrfcr, Rfen|Apm|Aab|Aam);
+
+	/*
+	 * Look for a medium override in case there's no autonegotiation
+	 * the autonegotiation fails.
+	 */
+
+	for(i = 0; i < ether->nopt; i++){
+		if(cistrcmp(ether->opt[i], "FD") == 0){
+			ctlr->fd = 1;
+			continue;
+		}
+		for(x = 0; x < nelem(mediatable); x++){
+			debug("compare <%s> <%s>\n", mediatable[x],
+				ether->opt[i]);
+			if(cistrcmp(mediatable[x], ether->opt[i]) == 0){
+				switch(x){
+				default:
+					ctlr->fd = 0;
+					break;
+
+				case 0x04:		/* 10BASE-TFD */
+				case 0x05:		/* 100BASE-TXFD */
+				case 0x08:		/* 100BASE-FXFD */
+					ctlr->fd = 1;
+					break;
+				}
+				break;
+			}
+		}
+	}
+
+	/*
+	 * Initialise descriptor rings, ethernet address.
+	 */
+	ctlr->nrdr = Nrde;
+	ctlr->ntdr = Ntde;
+	pcisetbme(ctlr->pcidev);
+	ctlrinit(ether);
+
+	/*
+	 * Linkage to the generic ethernet driver.
+	 */
+	ether->attach = attach;
+	ether->transmit = transmit;
+	ether->interrupt = interrupt;
+	ether->detach = detach;
+
+	return 0;
+}
--- /dev/null
+++ b/os/boot.original/pc/ether8390.c
@@ -1,0 +1,715 @@
+/*
+ * National Semiconductor DP8390 and clone
+ * Network Interface Controller.
+ */
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+#include "etherif.h"
+#include "ether8390.h"
+
+enum {					/* NIC core registers */
+	Cr		= 0x00,		/* command register, all pages */
+
+					/* Page 0, read */
+	Clda0		= 0x01,		/* current local DMA address 0 */
+	Clda1		= 0x02,		/* current local DMA address 1 */
+	Bnry		= 0x03,		/* boundary pointer (R/W) */
+	Tsr		= 0x04,		/* transmit status register */
+	Ncr		= 0x05,		/* number of collisions register */
+	Fifo		= 0x06,		/* FIFO */
+	Isr		= 0x07,		/* interrupt status register (R/W) */
+	Crda0		= 0x08,		/* current remote DMA address 0 */
+	Crda1		= 0x09,		/* current remote DMA address 1 */
+	Rsr		= 0x0C,		/* receive status register */
+	Cntr0		= 0x0D,		/* frame alignment errors */
+	Cntr1		= 0x0E,		/* CRC errors */
+	Cntr2		= 0x0F,		/* missed packet errors */
+
+					/* Page 0, write */
+	Pstart		= 0x01,		/* page start register */
+	Pstop		= 0x02,		/* page stop register */
+	Tpsr		= 0x04,		/* transmit page start address */
+	Tbcr0		= 0x05,		/* transmit byte count register 0 */
+	Tbcr1		= 0x06,		/* transmit byte count register 1 */
+	Rsar0		= 0x08,		/* remote start address register 0 */
+	Rsar1		= 0x09,		/* remote start address register 1 */
+	Rbcr0		= 0x0A,		/* remote byte count register 0 */
+	Rbcr1		= 0x0B,		/* remote byte count register 1 */
+	Rcr		= 0x0C,		/* receive configuration register */
+	Tcr		= 0x0D,		/* transmit configuration register */
+	Dcr		= 0x0E,		/* data configuration register */
+	Imr		= 0x0F,		/* interrupt mask */
+
+					/* Page 1, read/write */
+	Par0		= 0x01,		/* physical address register 0 */
+	Curr		= 0x07,		/* current page register */
+	Mar0		= 0x08,		/* multicast address register 0 */
+};
+
+enum {					/* Cr */
+	Stp		= 0x01,		/* stop */
+	Sta		= 0x02,		/* start */
+	Txp		= 0x04,		/* transmit packet */
+	Rd0		= 0x08,		/* remote DMA command */
+	Rd1		= 0x10,	
+	Rd2		= 0x20,
+	RdREAD		= Rd0,		/* remote read */
+	RdWRITE		= Rd1,		/* remote write */
+	RdSEND		= Rd1|Rd0,	/* send packet */
+	RdABORT		= Rd2,		/* abort/complete remote DMA */
+	Ps0		= 0x40,		/* page select */
+	Ps1		= 0x80,
+	Page0		= 0x00,
+	Page1		= Ps0,
+	Page2		= Ps1,
+};
+
+enum {					/* Isr/Imr */
+	Prx		= 0x01,		/* packet received */
+	Ptx		= 0x02,		/* packet transmitted */
+	Rxe		= 0x04,		/* receive error */
+	Txe		= 0x08,		/* transmit error */
+	Ovw		= 0x10,		/* overwrite warning */
+	Cnt		= 0x20,		/* counter overflow */
+	Rdc		= 0x40,		/* remote DMA complete */
+	Rst		= 0x80,		/* reset status */
+};
+
+enum {					/* Dcr */
+	Wts		= 0x01,		/* word transfer select */
+	Bos		= 0x02,		/* byte order select */
+	Las		= 0x04,		/* long address select */
+	Ls		= 0x08,		/* loopback select */
+	Arm		= 0x10,		/* auto-initialise remote */
+	Ft0		= 0x20,		/* FIFO threshold select */
+	Ft1		= 0x40,
+	Ft1WORD		= 0x00,
+	Ft2WORD		= Ft0,
+	Ft4WORD		= Ft1,
+	Ft6WORD		= Ft1|Ft0,
+};
+
+enum {					/* Tcr */
+	Crc		= 0x01,		/* inhibit CRC */
+	Lb0		= 0x02,		/* encoded loopback control */
+	Lb1		= 0x04,
+	LpbkNORMAL	= 0x00,		/* normal operation */
+	LpbkNIC		= Lb0,		/* internal NIC module loopback */
+	LpbkENDEC	= Lb1,		/* internal ENDEC module loopback */
+	LpbkEXTERNAL	= Lb1|Lb0,	/* external loopback */
+	Atd		= 0x08,		/* auto transmit disable */
+	Ofst		= 0x10,		/* collision offset enable */
+};
+
+enum {					/* Tsr */
+	Ptxok		= 0x01,		/* packet transmitted */
+	Col		= 0x04,		/* transmit collided */
+	Abt		= 0x08,		/* tranmit aborted */
+	Crs		= 0x10,		/* carrier sense lost */
+	Fu		= 0x20,		/* FIFO underrun */
+	Cdh		= 0x40,		/* CD heartbeat */
+	Owc		= 0x80,		/* out of window collision */
+};
+
+enum {					/* Rcr */
+	Sep		= 0x01,		/* save errored packets */
+	Ar		= 0x02,		/* accept runt packets */
+	Ab		= 0x04,		/* accept broadcast */
+	Am		= 0x08,		/* accept multicast */
+	Pro		= 0x10,		/* promiscuous physical */
+	Mon		= 0x20,		/* monitor mode */
+};
+
+enum {					/* Rsr */
+	Prxok		= 0x01,		/* packet received intact */
+	Crce		= 0x02,		/* CRC error */
+	Fae		= 0x04,		/* frame alignment error */
+	Fo		= 0x08,		/* FIFO overrun */
+	Mpa		= 0x10,		/* missed packet */
+	Phy		= 0x20,		/* physical/multicast address */
+	Dis		= 0x40,		/* receiver disabled */
+	Dfr		= 0x80,		/* deferring */
+};
+
+typedef struct {
+	uchar	status;
+	uchar	next;
+	uchar	len0;
+	uchar	len1;
+} Hdr;
+
+void
+dp8390getea(Ether* ether, uchar* ea)
+{
+	Dp8390 *ctlr;
+	uchar cr;
+	int i;
+
+	ctlr = ether->ctlr;
+
+	/*
+	 * Get the ethernet address from the chip.
+	 * Take care to restore the command register
+	 * afterwards.
+	 */
+	ilock(ctlr);
+	cr = regr(ctlr, Cr) & ~Txp;
+	regw(ctlr, Cr, Page1|(~(Ps1|Ps0) & cr));
+	for(i = 0; i < Eaddrlen; i++)
+		ea[i] = regr(ctlr, Par0+i);
+	regw(ctlr, Cr, cr);
+	iunlock(ctlr);
+}
+
+void
+dp8390setea(Ether* ether)
+{
+	int i;
+	uchar cr;
+	Dp8390 *ctlr;
+
+	ctlr = ether->ctlr;
+
+	/*
+	 * Set the ethernet address into the chip.
+	 * Take care to restore the command register
+	 * afterwards. Don't care about multicast
+	 * addresses as multicast is never enabled
+	 * (currently).
+	 */
+	ilock(ctlr);
+	cr = regr(ctlr, Cr) & ~Txp;
+	regw(ctlr, Cr, Page1|(~(Ps1|Ps0) & cr));
+	for(i = 0; i < Eaddrlen; i++)
+		regw(ctlr, Par0+i, ether->ea[i]);
+	regw(ctlr, Cr, cr);
+	iunlock(ctlr);
+}
+
+static void*
+_dp8390read(Dp8390* ctlr, void* to, ulong from, ulong len)
+{
+	uchar cr;
+	int timo;
+
+	/*
+	 * Read some data at offset 'from' in the card's memory
+	 * using the DP8390 remote DMA facility, and place it at
+	 * 'to' in main memory, via the I/O data port.
+	 */
+	cr = regr(ctlr, Cr) & ~Txp;
+	regw(ctlr, Cr, Page0|RdABORT|Sta);
+	regw(ctlr, Isr, Rdc);
+
+	/*
+	 * Set up the remote DMA address and count.
+	 */
+	len = ROUNDUP(len, ctlr->width);
+	regw(ctlr, Rbcr0, len & 0xFF);
+	regw(ctlr, Rbcr1, (len>>8) & 0xFF);
+	regw(ctlr, Rsar0, from & 0xFF);
+	regw(ctlr, Rsar1, (from>>8) & 0xFF);
+
+	/*
+	 * Start the remote DMA read and suck the data
+	 * out of the I/O port.
+	 */
+	regw(ctlr, Cr, Page0|RdREAD|Sta);
+	rdread(ctlr, to, len);
+
+	/*
+	 * Wait for the remote DMA to complete. The timeout
+	 * is necessary because this routine may be called on
+	 * a non-existent chip during initialisation and, due
+	 * to the miracles of the bus, it's possible to get this
+	 * far and still be talking to a slot full of nothing.
+	 */
+	for(timo = 10000; (regr(ctlr, Isr) & Rdc) == 0 && timo; timo--)
+			;
+
+	regw(ctlr, Isr, Rdc);
+	regw(ctlr, Cr, cr);
+
+	return to;
+}
+
+void*
+dp8390read(Dp8390* ctlr, void* to, ulong from, ulong len)
+{
+	void *v;
+
+	ilock(ctlr);
+	v = _dp8390read(ctlr, to, from, len);
+	iunlock(ctlr);
+
+	return v;
+}
+
+static void*
+dp8390write(Dp8390* ctlr, ulong to, void* from, ulong len)
+{
+	ulong crda;
+	uchar cr;
+	int timo, width;
+
+top:
+	/*
+	 * Write some data to offset 'to' in the card's memory
+	 * using the DP8390 remote DMA facility, reading it at
+	 * 'from' in main memory, via the I/O data port.
+	 */
+	cr = regr(ctlr, Cr) & ~Txp;
+	regw(ctlr, Cr, Page0|RdABORT|Sta);
+	regw(ctlr, Isr, Rdc);
+
+	len = ROUNDUP(len, ctlr->width);
+
+	/*
+	 * Set up the remote DMA address and count.
+	 * This is straight from the DP8390[12D] datasheet,
+	 * hence the initial set up for read.
+	 * Assumption here that the A7000 EtherV card will
+	 * never need a dummyrr.
+	 */
+	if(ctlr->dummyrr && (ctlr->width == 1 || ctlr->width == 2)){
+		if(ctlr->width == 2)
+			width = 1;
+		else
+			width = 0;
+		crda = to-1-width;
+		regw(ctlr, Rbcr0, (len+1+width) & 0xFF);
+		regw(ctlr, Rbcr1, ((len+1+width)>>8) & 0xFF);
+		regw(ctlr, Rsar0, crda & 0xFF);
+		regw(ctlr, Rsar1, (crda>>8) & 0xFF);
+		regw(ctlr, Cr, Page0|RdREAD|Sta);
+	
+		for(timo=0;; timo++){
+			if(timo > 10000){
+				print("ether8390: dummyrr timeout; assuming nodummyrr\n");
+				ctlr->dummyrr = 0;
+				goto top;
+			}
+			crda = regr(ctlr, Crda0);
+			crda |= regr(ctlr, Crda1)<<8;
+			if(crda == to){
+				/*
+				 * Start the remote DMA write and make sure
+				 * the registers are correct.
+				 */
+				regw(ctlr, Cr, Page0|RdWRITE|Sta);
+	
+				crda = regr(ctlr, Crda0);
+				crda |= regr(ctlr, Crda1)<<8;
+				if(crda != to)
+					panic("crda write %d to %d\n", crda, to);
+	
+				break;
+			}
+		}
+	}
+	else{
+		regw(ctlr, Rsar0, to & 0xFF);
+		regw(ctlr, Rsar1, (to>>8) & 0xFF);
+		regw(ctlr, Rbcr0, len & 0xFF);
+		regw(ctlr, Rbcr1, (len>>8) & 0xFF);
+		regw(ctlr, Cr, Page0|RdWRITE|Sta);
+	}
+
+	/*
+	 * Pump the data into the I/O port
+	 * then wait for the remote DMA to finish.
+	 */
+	rdwrite(ctlr, from, len);
+	for(timo = 10000; (regr(ctlr, Isr) & Rdc) == 0 && timo; timo--)
+			;
+
+	regw(ctlr, Isr, Rdc);
+	regw(ctlr, Cr, cr);
+
+	return (void*)to;
+}
+
+static void
+ringinit(Dp8390* ctlr)
+{
+	regw(ctlr, Pstart, ctlr->pstart);
+	regw(ctlr, Pstop, ctlr->pstop);
+	regw(ctlr, Bnry, ctlr->pstop-1);
+
+	regw(ctlr, Cr, Page1|RdABORT|Stp);
+	regw(ctlr, Curr, ctlr->pstart);
+	regw(ctlr, Cr, Page0|RdABORT|Stp);
+
+	ctlr->nxtpkt = ctlr->pstart;
+}
+
+static uchar
+getcurr(Dp8390* ctlr)
+{
+	uchar cr, curr;
+
+	cr = regr(ctlr, Cr) & ~Txp;
+	regw(ctlr, Cr, Page1|(~(Ps1|Ps0) & cr));
+	curr = regr(ctlr, Curr);
+	regw(ctlr, Cr, cr);
+
+	return curr;
+}
+
+static void
+receive(Ether* ether)
+{
+	Dp8390 *ctlr;
+	uchar curr, *p;
+	Hdr hdr;
+	ulong count, data, len;
+	RingBuf *ring;
+
+	ctlr = ether->ctlr;
+	for(curr = getcurr(ctlr); ctlr->nxtpkt != curr; curr = getcurr(ctlr)){
+		data = ctlr->nxtpkt*Dp8390BufSz;
+		if(ctlr->ram)
+			memmove(&hdr, (void*)(ether->mem+data), sizeof(Hdr));
+		else
+			_dp8390read(ctlr, &hdr, data, sizeof(Hdr));
+
+		/*
+		 * Don't believe the upper byte count, work it
+		 * out from the software next-page pointer and
+		 * the current next-page pointer.
+		 */
+		if(hdr.next > ctlr->nxtpkt)
+			len = hdr.next - ctlr->nxtpkt - 1;
+		else
+			len = (ctlr->pstop-ctlr->nxtpkt) + (hdr.next-ctlr->pstart) - 1;
+		if(hdr.len0 > (Dp8390BufSz-sizeof(Hdr)))
+			len--;
+
+		len = ((len<<8)|hdr.len0)-4;
+
+		/*
+		 * Chip is badly scrogged, reinitialise the ring.
+		 */
+		if(hdr.next < ctlr->pstart || hdr.next >= ctlr->pstop
+		  || len < 60 || len > sizeof(Etherpkt)){
+			print("dp8390: H#%2.2ux#%2.2ux#%2.2ux#%2.2ux,%lud\n",
+				hdr.status, hdr.next, hdr.len0, hdr.len1, len);
+			regw(ctlr, Cr, Page0|RdABORT|Stp);
+			ringinit(ctlr);
+			regw(ctlr, Cr, Page0|RdABORT|Sta);
+
+			return;
+		}
+
+		/*
+		 * If it's a good packet read it in to the software buffer.
+		 * If the packet wraps round the hardware ring, read it in
+		 * two pieces.
+		 */
+		ring = &ether->rb[ether->ri];
+		if((hdr.status & (Fo|Fae|Crce|Prxok)) == Prxok && ring->owner == Interface){
+			p = ring->pkt;
+			ring->len = len;
+			data += sizeof(Hdr);
+
+			if((data+len) >= ctlr->pstop*Dp8390BufSz){
+				count = ctlr->pstop*Dp8390BufSz - data;
+				if(ctlr->ram)
+					memmove(p, (void*)(ether->mem+data), count);
+				else
+					_dp8390read(ctlr, p, data, count);
+				p += count;
+				data = ctlr->pstart*Dp8390BufSz;
+				len -= count;
+			}
+			if(len){
+				if(ctlr->ram)
+					memmove(p, (void*)(ether->mem+data), len);
+				else
+					_dp8390read(ctlr, p, data, len);
+			}
+
+			/*
+			 * Copy the packet to whoever wants it.
+			 */
+			ring->owner = Host;
+			ether->ri = NEXT(ether->ri, ether->nrb);
+		}
+
+		/*
+		 * Finished with this packet, update the
+		 * hardware and software ring pointers.
+		 */
+		ctlr->nxtpkt = hdr.next;
+
+		hdr.next--;
+		if(hdr.next < ctlr->pstart)
+			hdr.next = ctlr->pstop-1;
+		regw(ctlr, Bnry, hdr.next);
+	}
+}
+
+static void
+txstart(Ether* ether)
+{
+	int len;
+	Dp8390 *ctlr;
+	RingBuf *ring;
+	uchar minpkt[ETHERMINTU], *rp;
+
+	ctlr = ether->ctlr;
+
+	/*
+	 * This routine is called both from the top level and from interrupt
+	 * level and expects to be called with ctlr already locked.
+	 */
+	if(ether->tbusy)
+		return;
+	ring = &ether->tb[ether->ti];
+	if(ring->owner != Interface)
+		return;
+
+	/*
+	 * Make sure the packet is of minimum length;
+	 * copy it to the card's memory by the appropriate means;
+	 * start the transmission.
+	 */
+	len = ring->len;
+	rp = ring->pkt;
+	if(len < ETHERMINTU){
+		rp = minpkt;
+		memmove(rp, ring->pkt, len);
+		memset(rp+len, 0, ETHERMINTU-len);
+		len = ETHERMINTU;
+	}
+
+	if(ctlr->ram)
+		memmove((void*)(ether->mem+ctlr->tstart*Dp8390BufSz), rp, len);
+	else
+		dp8390write(ctlr, ctlr->tstart*Dp8390BufSz, rp, len);
+
+	regw(ctlr, Tbcr0, len & 0xFF);
+	regw(ctlr, Tbcr1, (len>>8) & 0xFF);
+	regw(ctlr, Cr, Page0|RdABORT|Txp|Sta);
+
+	ether->tbusy = 1;
+}
+
+static void
+transmit(Ether* ether)
+{
+	Dp8390 *ctlr;
+
+	ctlr = ether->ctlr;
+
+	ilock(ctlr);
+	txstart(ether);
+	iunlock(ctlr);
+}
+
+static void
+overflow(Ether *ether)
+{
+	Dp8390 *ctlr;
+	uchar txp;
+	int resend;
+
+	ctlr = ether->ctlr;
+
+	/*
+	 * The following procedure is taken from the DP8390[12D] datasheet,
+	 * it seems pretty adamant that this is what has to be done.
+	 */
+	txp = regr(ctlr, Cr) & Txp;
+	regw(ctlr, Cr, Page0|RdABORT|Stp);
+	delay(2);
+	regw(ctlr, Rbcr0, 0);
+	regw(ctlr, Rbcr1, 0);
+
+	resend = 0;
+	if(txp && (regr(ctlr, Isr) & (Txe|Ptx)) == 0)
+		resend = 1;
+
+	regw(ctlr, Tcr, LpbkNIC);
+	regw(ctlr, Cr, Page0|RdABORT|Sta);
+	receive(ether);
+	regw(ctlr, Isr, Ovw);
+	regw(ctlr, Tcr, LpbkNORMAL);
+
+	if(resend)
+		regw(ctlr, Cr, Page0|RdABORT|Txp|Sta);
+}
+
+static void
+interrupt(Ureg*, void* arg)
+{
+	Ether *ether;
+	Dp8390 *ctlr;
+	RingBuf *ring;
+	uchar isr, r;
+
+	ether = arg;
+	ctlr = ether->ctlr;
+
+	/*
+	 * While there is something of interest,
+	 * clear all the interrupts and process.
+	 */
+	ilock(ctlr);
+	regw(ctlr, Imr, 0x00);
+	while(isr = (regr(ctlr, Isr) & (Cnt|Ovw|Txe|Rxe|Ptx|Prx))){
+		if(isr & Ovw){
+			overflow(ether);
+			regw(ctlr, Isr, Ovw);
+		}
+
+		/*
+		 * Packets have been received.
+		 * Take a spin round the ring.
+		 */
+		if(isr & (Rxe|Prx)){
+			receive(ether);
+			regw(ctlr, Isr, Rxe|Prx);
+		}
+
+		/*
+		 * A packet completed transmission, successfully or
+		 * not. Start transmission on the next buffered packet,
+		 * and wake the output routine.
+		 */
+		if(isr & (Txe|Ptx)){
+			r = regr(ctlr, Tsr);
+			if((isr & Txe) && (r & (Cdh|Fu|Crs|Abt))){
+				print("dp8390: Tsr#%2.2ux|", r);
+			}
+
+			regw(ctlr, Isr, Txe|Ptx);
+
+			ring = &ether->tb[ether->ti];
+			ring->owner = Host;
+			ether->ti = NEXT(ether->ti, ether->ntb);
+			ether->tbusy = 0;
+			txstart(ether);
+		}
+
+		if(isr & Cnt){
+			regr(ctlr, Cntr0);
+			regr(ctlr, Cntr1);
+			regr(ctlr, Cntr2);
+			regw(ctlr, Isr, Cnt);
+		}
+	}
+	regw(ctlr, Imr, Cnt|Ovw|Txe|Rxe|Ptx|Prx);
+	iunlock(ctlr);
+}
+
+static void
+attach(Ether* ether)
+{
+	Dp8390 *ctlr;
+	uchar r;
+
+	ctlr = ether->ctlr;
+
+	/*
+	 * Enable the chip for transmit/receive.
+	 * The init routine leaves the chip in monitor
+	 * mode. Clear the missed-packet counter, it
+	 * increments while in monitor mode.
+	 * Sometimes there's an interrupt pending at this
+	 * point but there's nothing in the Isr, so
+	 * any pending interrupts are cleared and the
+	 * mask of acceptable interrupts is enabled here.
+	 */
+	r = Ab;
+	ilock(ctlr);
+	regw(ctlr, Isr, 0xFF);
+	regw(ctlr, Imr, Cnt|Ovw|Txe|Rxe|Ptx|Prx);
+	regw(ctlr, Rcr, r);
+	r = regr(ctlr, Cntr2);
+	regw(ctlr, Tcr, LpbkNORMAL);
+	iunlock(ctlr);
+	USED(r);
+}
+
+static void
+detach(Ether* ether)
+{
+	int timo;
+	Dp8390 *ctlr;
+
+	/*
+	 * Stop the chip. Set the Stp bit and wait for the chip
+	 * to finish whatever was on its tiny mind before it sets
+	 * the Rst bit.
+	 * The timeout is needed because there may not be a real
+	 * chip there if this is called when probing for a device
+	 * at boot.
+	 */
+	ctlr = ether->ctlr;
+	regw(ctlr, Cr, Page0|RdABORT|Stp);
+	regw(ctlr, Rbcr0, 0);
+	regw(ctlr, Rbcr1, 0);
+	for(timo = 10000; (regr(ctlr, Isr) & Rst) == 0 && timo; timo--)
+			;
+}
+
+int
+dp8390reset(Ether* ether)
+{
+	Dp8390 *ctlr;
+
+	ctlr = ether->ctlr;
+
+	/*
+	 * This is the initialisation procedure described
+	 * as 'mandatory' in the datasheet, with references
+	 * to the 3C503 technical reference manual.
+	 */ 
+	detach(ether);
+	if(ctlr->width != 1)
+		regw(ctlr, Dcr, Ft4WORD|Ls|Wts);
+	else
+		regw(ctlr, Dcr, Ft4WORD|Ls);
+
+	regw(ctlr, Rbcr0, 0);
+	regw(ctlr, Rbcr1, 0);
+
+	regw(ctlr, Tcr, LpbkNIC);
+	regw(ctlr, Rcr, Mon);
+
+	/*
+	 * Init the ring hardware and software ring pointers.
+	 * Can't initialise ethernet address as it may not be
+	 * known yet.
+	 */
+	ringinit(ctlr);
+	regw(ctlr, Tpsr, ctlr->tstart);
+
+	/*
+	 * Clear any pending interrupts and mask then all off.
+	 */
+	regw(ctlr, Isr, 0xFF);
+	regw(ctlr, Imr, 0);
+
+	/*
+	 * Leave the chip initialised,
+	 * but in monitor mode.
+	 */
+	regw(ctlr, Cr, Page0|RdABORT|Sta);
+
+	/*
+	 * Set up the software configuration.
+	 */
+	ether->attach = attach;
+	ether->transmit = transmit;
+	ether->interrupt = interrupt;
+	ether->detach = detach;
+
+	return 0;
+}
--- /dev/null
+++ b/os/boot.original/pc/ether8390.h
@@ -1,0 +1,71 @@
+/*
+ * Ctlr for the boards using the National Semiconductor DP8390
+ * and SMC 83C90 Network Interface Controller.
+ * Common code is in ether8390.c.
+ */
+typedef struct {
+	Lock;
+
+	ulong	port;			/* I/O address of 8390 */
+	ulong	data;			/* I/O data port if no shared memory */
+
+	uchar	width;			/* data transfer width in bytes */
+	uchar	ram;			/* true if card has shared memory */
+	uchar	dummyrr;		/* do dummy remote read */
+
+	uchar	nxtpkt;			/* receive: software bndry */
+	uchar	pstart;
+	uchar	pstop;
+
+	int	txbusy;			/* transmit */
+	uchar	tstart;			/* 8390 ring addresses */
+} Dp8390;
+
+#define Dp8390BufSz	256
+
+extern int dp8390reset(Ether*);
+extern void *dp8390read(Dp8390*, void*, ulong, ulong);
+extern void dp8390getea(Ether*, uchar*);
+extern void dp8390setea(Ether*);
+
+/*
+ * x86-specific code.
+ */
+#define regr(c, r)	inb((c)->port+(r))
+#define regw(c, r, v)	outb((c)->port+(r), (v))
+
+static void
+rdread(Dp8390* ctlr, void* to, int len)
+{
+	switch(ctlr->width){
+	default:
+		panic("dp8390 rdread: width %d\n", ctlr->width);
+		break;
+
+	case 2:
+		inss(ctlr->data, to, len/2);
+		break;
+
+	case 1:
+		insb(ctlr->data, to, len);
+		break;
+	}
+}
+
+static void
+rdwrite(Dp8390* ctlr, void* from, int len)
+{
+	switch(ctlr->width){
+	default:
+		panic("dp8390 rdwrite: width %d\n", ctlr->width);
+		break;
+
+	case 2:
+		outss(ctlr->data, from, len/2);
+		break;
+
+	case 1:
+		outsb(ctlr->data, from, len);
+		break;
+	}
+}
--- /dev/null
+++ b/os/boot.original/pc/etherdp83820.c
@@ -1,0 +1,1222 @@
+/*
+ * boot driver for
+ * National Semiconductor DP83820
+ * 10/100/1000 Mb/s Ethernet Network Interface Controller
+ * (Gig-NIC).
+ * Driver assumes little-endian and 32-bit host throughout.
+ */
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+#include "etherif.h"
+#include "ethermii.h"
+
+#define iprint print
+#define waserror()	(0)
+#define poperror()
+
+enum {					/* Registers */
+	Cr		= 0x00,		/* Command */
+	Cfg		= 0x04,		/* Configuration and Media Status */
+	Mear		= 0x08,		/* MII/EEPROM Access */
+	Ptscr		= 0x0C,		/* PCI Test Control */
+	Isr		= 0x10,		/* Interrupt Status */
+	Imr		= 0x14,		/* Interrupt Mask */
+	Ier		= 0x18,		/* Interrupt Enable */
+	Ihr		= 0x1C,		/* Interrupt Holdoff */
+	Txdp		= 0x20,		/* Transmit Descriptor Pointer */
+	Txdphi		= 0x24,		/* Transmit Descriptor Pointer Hi */
+	Txcfg		= 0x28,		/* Transmit Configuration */
+	Gpior		= 0x2C,		/* General Purpose I/O Control */
+	Rxdp		= 0x30,		/* Receive Descriptor Pointer */
+	Rxdphi		= 0x34,		/* Receive Descriptor Pointer Hi */
+	Rxcfg		= 0x38,		/* Receive Configuration */
+	Pqcr		= 0x3C,		/* Priority Queueing Control */
+	Wcsr		= 0x40,		/* Wake on LAN Control/Status */
+	Pcr		= 0x44,		/* Pause Control/Status */
+	Rfcr		= 0x48,		/* Receive Filter/Match Control */
+	Rfdr		= 0x4C,		/* Receive Filter/Match Data */
+	Brar		= 0x50,		/* Boot ROM Address */
+	Brdr		= 0x54,		/* Boot ROM Data */
+	Srr		= 0x58,		/* Silicon Revision */
+	Mibc		= 0x5C,		/* MIB Control */
+	Mibd		= 0x60,		/* MIB Data */
+	Txdp1		= 0xA0,		/* Txdp Priority 1 */
+	Txdp2		= 0xA4,		/* Txdp Priority 2 */
+	Txdp3		= 0xA8,		/* Txdp Priority 3 */
+	Rxdp1		= 0xB0,		/* Rxdp Priority 1 */
+	Rxdp2		= 0xB4,		/* Rxdp Priority 2 */
+	Rxdp3		= 0xB8,		/* Rxdp Priority 3 */
+	Vrcr		= 0xBC,		/* VLAN/IP Receive Control */
+	Vtcr		= 0xC0,		/* VLAN/IP Transmit Control */
+	Vdr		= 0xC4,		/* VLAN Data */
+	Ccsr		= 0xCC,		/* Clockrun Control/Status */
+	Tbicr		= 0xE0,		/* TBI Control */
+	Tbisr		= 0xE4,		/* TBI Status */
+	Tanar		= 0xE8,		/* TBI ANAR */
+	Tanlpar		= 0xEC,		/* TBI ANLPAR */
+	Taner		= 0xF0,		/* TBI ANER */
+	Tesr		= 0xF4,		/* TBI ESR */
+};
+
+enum {					/* Cr */
+	Txe		= 0x00000001,	/* Transmit Enable */
+	Txd		= 0x00000002,	/* Transmit Disable */
+	Rxe		= 0x00000004,	/* Receiver Enable */
+	Rxd		= 0x00000008,	/* Receiver Disable */
+	Txr		= 0x00000010,	/* Transmitter Reset */
+	Rxr		= 0x00000020,	/* Receiver Reset */
+	Swien		= 0x00000080,	/* Software Interrupt Enable */
+	Rst		= 0x00000100,	/* Reset */
+	TxpriSHFT	= 9,		/* Tx Priority Queue Select */
+	TxpriMASK	= 0x00001E00,
+	RxpriSHFT	= 13,		/* Rx Priority Queue Select */
+	RxpriMASK	= 0x0001E000,
+};
+
+enum {					/* Configuration and Media Status */
+	Bem		= 0x00000001,	/* Big Endian Mode */
+	Ext125		= 0x00000002,	/* External 125MHz reference Select */
+	Bromdis		= 0x00000004,	/* Disable Boot ROM interface */
+	Pesel		= 0x00000008,	/* Parity Error Detection Action */
+	Exd		= 0x00000010,	/* Excessive Deferral Abort */
+	Pow		= 0x00000020,	/* Program Out of Window Timer */
+	Sb		= 0x00000040,	/* Single Back-off */
+	Reqalg		= 0x00000080,	/* PCI Bus Request Algorithm */
+	Extstsen	= 0x00000100,	/* Extended Status Enable */
+	Phydis		= 0x00000200,	/* Disable PHY */
+	Phyrst		= 0x00000400,	/* Reset PHY */
+	M64addren	= 0x00000800,	/* Master 64-bit Addressing Enable */
+	Data64en	= 0x00001000,	/* 64-bit Data Enable */
+	Pci64det	= 0x00002000,	/* PCI 64-bit Bus Detected */
+	T64addren	= 0x00004000,	/* Target 64-bit Addressing Enable */
+	Mwidis		= 0x00008000,	/* MWI Disable */
+	Mrmdis		= 0x00010000,	/* MRM Disable */
+	Tmrtest		= 0x00020000,	/* Timer Test Mode */
+	Spdstsien	= 0x00040000,	/* PHY Spdsts Interrupt Enable */
+	Lnkstsien	= 0x00080000,	/* PHY Lnksts Interrupt Enable */
+	Dupstsien	= 0x00100000,	/* PHY Dupsts Interrupt Enable */
+	Mode1000	= 0x00400000,	/* 1000Mb/s Mode Control */
+	Tbien		= 0x01000000,	/* Ten-Bit Interface Enable */
+	Dupsts		= 0x10000000,	/* Full Duplex Status */
+	Spdsts100	= 0x20000000,	/* SPEED100 Input Pin Status */
+	Spdsts1000	= 0x40000000,	/* SPEED1000 Input Pin Status */
+	Lnksts		= 0x80000000,	/* Link Status */
+};
+
+enum {					/* MII/EEPROM Access */
+	Eedi		= 0x00000001,	/* EEPROM Data In */
+	Eedo		= 0x00000002,	/* EEPROM Data Out */
+	Eeclk		= 0x00000004,	/* EEPROM Serial Clock */
+	Eesel		= 0x00000008,	/* EEPROM Chip Select */
+	Mdio		= 0x00000010,	/* MII Management Data */
+	Mddir		= 0x00000020,	/* MII Management Direction */
+	Mdc		= 0x00000040,	/* MII Management Clock */
+};
+
+enum {					/* Interrupts */
+	Rxok		= 0x00000001,	/* Rx OK */
+	Rxdesc		= 0x00000002,	/* Rx Descriptor */
+	Rxerr		= 0x00000004,	/* Rx Packet Error */
+	Rxearly		= 0x00000008,	/* Rx Early Threshold */
+	Rxidle		= 0x00000010,	/* Rx Idle */
+	Rxorn		= 0x00000020,	/* Rx Overrun */
+	Txok		= 0x00000040,	/* Tx Packet OK */
+	Txdesc		= 0x00000080,	/* Tx Descriptor */
+	Txerr		= 0x00000100,	/* Tx Packet Error */
+	Txidle		= 0x00000200,	/* Tx Idle */
+	Txurn		= 0x00000400,	/* Tx Underrun */
+	Mib		= 0x00000800,	/* MIB Service */
+	Swi		= 0x00001000,	/* Software Interrupt */
+	Pme		= 0x00002000,	/* Power Management Event */
+	Phy		= 0x00004000,	/* PHY Interrupt */
+	Hibint		= 0x00008000,	/* High Bits Interrupt Set */
+	Rxsovr		= 0x00010000,	/* Rx Status FIFO Overrun */
+	Rtabt		= 0x00020000,	/* Received Target Abort */
+	Rmabt		= 0x00040000,	/* Received Master Abort */
+	Sserr		= 0x00080000,	/* Signalled System Error */
+	Dperr		= 0x00100000,	/* Detected Parity Error */
+	Rxrcmp		= 0x00200000,	/* Receive Reset Complete */
+	Txrcmp		= 0x00400000,	/* Transmit Reset Complete */
+	Rxdesc0		= 0x00800000,	/* Rx Descriptor for Priority Queue 0 */
+	Rxdesc1		= 0x01000000,	/* Rx Descriptor for Priority Queue 1 */
+	Rxdesc2		= 0x02000000,	/* Rx Descriptor for Priority Queue 2 */
+	Rxdesc3		= 0x04000000,	/* Rx Descriptor for Priority Queue 3 */
+	Txdesc0		= 0x08000000,	/* Tx Descriptor for Priority Queue 0 */
+	Txdesc1		= 0x10000000,	/* Tx Descriptor for Priority Queue 1 */
+	Txdesc2		= 0x20000000,	/* Tx Descriptor for Priority Queue 2 */
+	Txdesc3		= 0x40000000,	/* Tx Descriptor for Priority Queue 3 */
+};
+
+enum {					/* Interrupt Enable */
+	Ien		= 0x00000001,	/* Interrupt Enable */
+};
+
+enum {					/* Interrupt Holdoff */
+	IhSHFT		= 0,		/* Interrupt Holdoff */
+	IhMASK		= 0x000000FF,
+	Ihctl		= 0x00000100,	/* Interrupt Holdoff Control */
+};
+
+enum {					/* Transmit Configuration */
+	TxdrthSHFT	= 0,		/* Tx Drain Threshold */
+	TxdrthMASK	= 0x000000FF,
+	FlthSHFT	= 16,		/* Tx Fill Threshold */
+	FlthMASK	= 0x0000FF00,
+	Brstdis		= 0x00080000,	/* 1000Mb/s Burst Disable */
+	MxdmaSHFT	= 20,		/* Max Size per Tx DMA Burst */
+	MxdmaMASK	= 0x00700000,
+	Ecretryen	= 0x00800000,	/* Excessive Collision Retry Enable */
+	Atp		= 0x10000000,	/* Automatic Transmit Padding */
+	Mlb		= 0x20000000,	/* MAC Loopback */
+	Hbi		= 0x40000000,	/* Heartbeat Ignore */
+	Csi		= 0x80000000,	/* Carrier Sense Ignore */
+};
+
+enum {					/* Receive Configuration */
+	RxdrthSHFT	= 1,		/* Rx Drain Threshold */
+	RxdrthMASK	= 0x0000003E,
+	Airl		= 0x04000000,	/* Accept In-Range Length Errored */
+	Alp		= 0x08000000,	/* Accept Long Packets */
+	Rxfd		= 0x10000000,	/* Receive Full Duplex */
+	Stripcrc	= 0x20000000,	/* Strip CRC */
+	Arp		= 0x40000000,	/* Accept Runt Packets */
+	Aep		= 0x80000000,	/* Accept Errored Packets */
+};
+
+enum {					/* Priority Queueing Control */
+	Txpqen		= 0x00000001,	/* Transmit Priority Queuing Enable */
+	Txfairen	= 0x00000002,	/* Transmit Fairness Enable */
+	RxpqenSHFT	= 2,		/* Receive Priority Queue Enable */
+	RxpqenMASK	= 0x0000000C,
+};
+
+enum {					/* Pause Control/Status */
+	PscntSHFT	= 0,		/* Pause Counter Value */
+	PscntMASK	= 0x0000FFFF,
+	Pstx		= 0x00020000,	/* Transmit Pause Frame */
+	PsffloSHFT	= 18,		/* Rx Data FIFO Lo Threshold */
+	PsffloMASK	= 0x000C0000,
+	PsffhiSHFT	= 20,		/* Rx Data FIFO Hi Threshold */
+	PsffhiMASK	= 0x00300000,
+	PsstloSHFT	= 22,		/* Rx Stat FIFO Hi Threshold */
+	PsstloMASK	= 0x00C00000,
+	PssthiSHFT	= 24,		/* Rx Stat FIFO Hi Threshold */
+	PssthiMASK	= 0x03000000,
+	Psrcvd		= 0x08000000,	/* Pause Frame Received */
+	Psact		= 0x10000000,	/* Pause Active */
+	Psda		= 0x20000000,	/* Pause on Destination Address */
+	Psmcast		= 0x40000000,	/* Pause on Multicast */
+	Psen		= 0x80000000,	/* Pause Enable */
+};
+
+enum {					/* Receive Filter/Match Control */
+	RfaddrSHFT	= 0,		/* Extended Register Address */
+	RfaddrMASK	= 0x000003FF,
+	Ulm		= 0x00080000,	/* U/L bit mask */
+	Uhen		= 0x00100000,	/* Unicast Hash Enable */
+	Mhen		= 0x00200000,	/* Multicast Hash Enable */
+	Aarp		= 0x00400000,	/* Accept ARP Packets */
+	ApatSHFT	= 23,		/* Accept on Pattern Match */
+	ApatMASK	= 0x07800000,
+	Apm		= 0x08000000,	/* Accept on Perfect Match */
+	Aau		= 0x10000000,	/* Accept All Unicast */
+	Aam		= 0x20000000,	/* Accept All Multicast */
+	Aab		= 0x40000000,	/* Accept All Broadcast */
+	Rfen		= 0x80000000,	/* Rx Filter Enable */
+};
+
+enum {					/* Receive Filter/Match Data */
+	RfdataSHFT	= 0,		/* Receive Filter Data */
+	RfdataMASK	= 0x0000FFFF,
+	BmaskSHFT	= 16,		/* Byte Mask */
+	BmaskMASK	= 0x00030000,
+};
+
+enum {					/* MIB Control */
+	Wrn		= 0x00000001,	/* Warning Test Indicator */
+	Frz		= 0x00000002,	/* Freeze All Counters */
+	Aclr		= 0x00000004,	/* Clear All Counters */
+	Mibs		= 0x00000008,	/* MIB Counter Strobe */
+};
+
+enum {					/* MIB Data */
+	Nmibd		= 11,		/* Number of MIB Data Registers */
+};
+
+enum {					/* VLAN/IP Receive Control */
+	Vtden		= 0x00000001,	/* VLAN Tag Detection Enable */
+	Vtren		= 0x00000002,	/* VLAN Tag Removal Enable */
+	Dvtf		= 0x00000004,	/* Discard VLAN Tagged Frames */
+	Dutf		= 0x00000008,	/* Discard Untagged Frames */
+	Ipen		= 0x00000010,	/* IP Checksum Enable */
+	Ripe		= 0x00000020,	/* Reject IP Checksum Errors */
+	Rtcpe		= 0x00000040,	/* Reject TCP Checksum Errors */
+	Rudpe		= 0x00000080,	/* Reject UDP Checksum Errors */
+};
+
+enum {					/* VLAN/IP Transmit Control */
+	Vgti		= 0x00000001,	/* VLAN Global Tag Insertion */
+	Vppti		= 0x00000002,	/* VLAN Per-Packet Tag Insertion */
+	Gchk		= 0x00000004,	/* Global Checksum Generation */
+	Ppchk		= 0x00000008,	/* Per-Packet Checksum Generation */
+};
+
+enum {					/* VLAN Data */
+	VtypeSHFT	= 0,		/* VLAN Type Field */
+	VtypeMASK	= 0x0000FFFF,
+	VtciSHFT	= 16,		/* VLAN Tag Control Information */
+	VtciMASK	= 0xFFFF0000,
+};
+
+enum {					/* Clockrun Control/Status */
+	Clkrunen	= 0x00000001,	/* CLKRUN Enable */
+	Pmeen		= 0x00000100,	/* PME Enable */
+	Pmests		= 0x00008000,	/* PME Status */
+};
+
+typedef struct {
+	u32	link;			/* Link to the next descriptor */
+	u32	bufptr;			/* pointer to data Buffer */
+	int	cmdsts;			/* Command/Status */
+	int	extsts;			/* optional Extended Status */
+
+	Block*	bp;			/* Block containing bufptr */
+	u32	unused;			/* pad to 64-bit */
+} Desc;
+
+enum {					/* Common cmdsts bits */
+	SizeMASK	= 0x0000FFFF,	/* Descriptor Byte Count */
+	SizeSHFT	= 0,
+	Ok		= 0x08000000,	/* Packet OK */
+	Crc		= 0x10000000,	/* Suppress/Include CRC */
+	Intr		= 0x20000000,	/* Interrupt on ownership transfer */
+	More		= 0x40000000,	/* not last descriptor in a packet */
+	Own		= 0x80000000,	/* Descriptor Ownership */
+};
+
+enum {					/* Transmit cmdsts bits */
+	CcntMASK	= 0x000F0000,	/* Collision Count */
+	CcntSHFT	= 16,
+	Ec		= 0x00100000,	/* Excessive Collisions */
+	Owc		= 0x00200000,	/* Out of Window Collision */
+	Ed		= 0x00400000,	/* Excessive Deferral */
+	Td		= 0x00800000,	/* Transmit Deferred */
+	Crs		= 0x01000000,	/* Carrier Sense Lost */
+	Tfu		= 0x02000000,	/* Transmit FIFO Underrun */
+	Txa		= 0x04000000,	/* Transmit Abort */
+};
+
+enum {					/* Receive cmdsts bits */
+	Irl		= 0x00010000,	/* In-Range Length Error */
+	Lbp		= 0x00020000,	/* Loopback Packet */
+	Fae		= 0x00040000,	/* Frame Alignment Error */
+	Crce		= 0x00080000,	/* CRC Error */
+	Ise		= 0x00100000,	/* Invalid Symbol Error */
+	Runt		= 0x00200000,	/* Runt Packet Received */
+	Long		= 0x00400000,	/* Too Long Packet Received */
+	DestMASK	= 0x01800000,	/* Destination Class */
+	DestSHFT	= 23,
+	Rxo		= 0x02000000,	/* Receive Overrun */
+	Rxa		= 0x04000000,	/* Receive Aborted */
+};
+
+enum {					/* extsts bits */
+	EvtciMASK	= 0x0000FFFF,	/* VLAN Tag Control Information */
+	EvtciSHFT	= 0,
+	Vpkt		= 0x00010000,	/* VLAN Packet */
+	Ippkt		= 0x00020000,	/* IP Packet */
+	Iperr		= 0x00040000,	/* IP Checksum Error */
+	Tcppkt		= 0x00080000,	/* TCP Packet */
+	Tcperr		= 0x00100000,	/* TCP Checksum Error */
+	Udppkt		= 0x00200000,	/* UDP Packet */
+	Udperr		= 0x00400000,	/* UDP Checksum Error */
+};
+
+enum {
+	Nrd		= 32,		/* was 256 */
+	Nrbf		= 4*Nrd,
+	Rbsz		= ROUNDUP(sizeof(Etherpkt)+8, 8),
+	Ntd		= 8,		/* was 128 */
+};
+
+typedef struct Ctlr Ctlr;
+struct Ctlr {
+	int	port;
+	Pcidev*	pcidev;
+	Ctlr*	next;
+	int	active;
+	int	id;
+
+	int	eepromsz;		/* address size in bits */
+	ushort*	eeprom;
+
+	int*	nic;
+	int	cfg;
+	int	imr;
+
+	Lock	alock;			/* attach */
+	Lock	ilock;			/* init */
+	void*	alloc;			/* base of per-Ctlr allocated data */
+
+	Mii*	mii;
+
+	Lock	rdlock;			/* receive */
+	Desc*	rd;
+	int	nrd;
+	int	nrb;
+	int	rdx;
+	int	rxcfg;
+
+	Lock	tlock;			/* transmit */
+	Desc*	td;
+	int	ntd;
+	int	tdh;
+	int	tdt;
+	int	ntq;
+	int	txcfg;
+
+	int	rxidle;
+
+	uint	mibd[Nmibd];
+
+	int	ec;
+	int	owc;
+	int	ed;
+	int	crs;
+	int	tfu;
+	int	txa;
+};
+
+#define csr32r(c, r)	(*((c)->nic+((r)/4)))
+#define csr32w(c, r, v)	(*((c)->nic+((r)/4)) = (v))
+
+static Ctlr* dp83820ctlrhead;
+static Ctlr* dp83820ctlrtail;
+
+static Lock dp83820rblock;		/* free receive Blocks */
+static Block* dp83820rbpool;
+
+static char* dp83820mibs[Nmibd] = {
+	"RXErroredPkts",
+	"RXFCSErrors",
+	"RXMsdPktErrors",
+	"RXFAErrors",
+	"RXSymbolErrors",
+	"RXFrameToLong",
+	"RXIRLErrors",
+	"RXBadOpcodes",
+	"RXPauseFrames",
+	"TXPauseFrames",
+	"TXSQEErrors",
+};
+
+static int
+mdior(Ctlr* ctlr, int n)
+{
+	int data, i, mear, r;
+
+	mear = csr32r(ctlr, Mear);
+	r = ~(Mdc|Mddir) & mear;
+	data = 0;
+	for(i = n-1; i >= 0; i--){
+		if(csr32r(ctlr, Mear) & Mdio)
+			data |= (1<<i);
+		csr32w(ctlr, Mear, Mdc|r);
+		csr32w(ctlr, Mear, r);
+	}
+	csr32w(ctlr, Mear, mear);
+
+	return data;
+}
+
+static void
+mdiow(Ctlr* ctlr, int bits, int n)
+{
+	int i, mear, r;
+
+	mear = csr32r(ctlr, Mear);
+	r = Mddir|(~Mdc & mear);
+	for(i = n-1; i >= 0; i--){
+		if(bits & (1<<i))
+			r |= Mdio;
+		else
+			r &= ~Mdio;
+		csr32w(ctlr, Mear, r);
+		csr32w(ctlr, Mear, Mdc|r);
+	}
+	csr32w(ctlr, Mear, mear);
+}
+
+static int
+dp83820miimir(Mii* mii, int pa, int ra)
+{
+	int data;
+	Ctlr *ctlr;
+
+	ctlr = mii->ctlr;
+
+	/*
+	 * MII Management Interface Read.
+	 *
+	 * Preamble;
+	 * ST+OP+PA+RA;
+	 * LT + 16 data bits.
+	 */
+	mdiow(ctlr, 0xFFFFFFFF, 32);
+	mdiow(ctlr, 0x1800|(pa<<5)|ra, 14);
+	data = mdior(ctlr, 18);
+
+	if(data & 0x10000)
+		return -1;
+
+	return data & 0xFFFF;
+}
+
+static int
+dp83820miimiw(Mii* mii, int pa, int ra, int data)
+{
+	Ctlr *ctlr;
+
+	ctlr = mii->ctlr;
+
+	/*
+	 * MII Management Interface Write.
+	 *
+	 * Preamble;
+	 * ST+OP+PA+RA+LT + 16 data bits;
+	 * Z.
+	 */
+	mdiow(ctlr, 0xFFFFFFFF, 32);
+	data &= 0xFFFF;
+	data |= (0x05<<(5+5+2+16))|(pa<<(5+2+16))|(ra<<(2+16))|(0x02<<16);
+	mdiow(ctlr, data, 32);
+
+	return 0;
+}
+
+static Block *
+dp83820rballoc(Desc* desc)
+{
+	Block *bp;
+
+	if(desc->bp == nil){
+		ilock(&dp83820rblock);
+		if((bp = dp83820rbpool) == nil){
+			iunlock(&dp83820rblock);
+			desc->bp = nil;
+			desc->cmdsts = Own;
+			return nil;
+		}
+		dp83820rbpool = bp->next;
+		bp->next = nil;
+		iunlock(&dp83820rblock);
+	
+		desc->bufptr = PCIWADDR(bp->rp);
+		desc->bp = bp;
+	}
+	else{
+		bp = desc->bp;
+		bp->rp = bp->lim - Rbsz;
+		bp->wp = bp->rp;
+	}
+
+	coherence();
+	desc->cmdsts = Intr|Rbsz;
+
+	return bp;
+}
+
+static void
+dp83820rbfree(Block *bp)
+{
+	bp->rp = bp->lim - Rbsz;
+	bp->wp = bp->rp;
+
+	ilock(&dp83820rblock);
+	bp->next = dp83820rbpool;
+	dp83820rbpool = bp;
+	iunlock(&dp83820rblock);
+}
+
+static void
+dp83820halt(Ctlr* ctlr)
+{
+	int i, timeo;
+
+	ilock(&ctlr->ilock);
+	csr32w(ctlr, Imr, 0);
+	csr32w(ctlr, Ier, 0);
+	csr32w(ctlr, Cr, Rxd|Txd);
+	for(timeo = 0; timeo < 1000; timeo++){
+		if(!(csr32r(ctlr, Cr) & (Rxe|Txe)))
+			break;
+		microdelay(1);
+	}
+	csr32w(ctlr, Mibc, Frz);
+	iunlock(&ctlr->ilock);
+
+	if(ctlr->rd != nil){
+		for(i = 0; i < ctlr->nrd; i++){
+			if(ctlr->rd[i].bp == nil)
+				continue;
+			freeb(ctlr->rd[i].bp);
+			ctlr->rd[i].bp = nil;
+		}
+	}
+	if(ctlr->td != nil){
+		for(i = 0; i < ctlr->ntd; i++){
+			if(ctlr->td[i].bp == nil)
+				continue;
+			freeb(ctlr->td[i].bp);
+			ctlr->td[i].bp = nil;
+		}
+	}
+}
+
+static void
+dp83820cfg(Ctlr* ctlr)
+{
+	int cfg;
+
+	/*
+	 * Don't know how to deal with a TBI yet.
+	 */
+	if(ctlr->mii == nil)
+		return;
+
+	/*
+	 * The polarity of these bits is at the mercy
+	 * of the board designer.
+	 * The correct answer for all speed and duplex questions
+	 * should be to query the phy.
+	 */
+	cfg = csr32r(ctlr, Cfg);
+	if(!(cfg & Dupsts)){
+		ctlr->rxcfg |= Rxfd;
+		ctlr->txcfg |= Csi|Hbi;
+		iprint("83820: full duplex, ");
+	}
+	else{
+		ctlr->rxcfg &= ~Rxfd;
+		ctlr->txcfg &= ~(Csi|Hbi);
+		iprint("83820: half duplex, ");
+	}
+	csr32w(ctlr, Rxcfg, ctlr->rxcfg);
+	csr32w(ctlr, Txcfg, ctlr->txcfg);
+
+	switch(cfg & (Spdsts1000|Spdsts100)){
+	case Spdsts1000:		/* 100Mbps */
+	default:			/* 10Mbps */
+		ctlr->cfg &= ~Mode1000;
+		if((cfg & (Spdsts1000|Spdsts100)) == Spdsts1000)
+			iprint("100Mb/s\n");
+		else
+			iprint("10Mb/s\n");
+		break;
+	case Spdsts100:			/* 1Gbps */
+		ctlr->cfg |= Mode1000;
+		iprint("1Gb/s\n");
+		break;
+	}
+	csr32w(ctlr, Cfg, ctlr->cfg);
+}
+
+static void
+dp83820init(Ether* edev)
+{
+	int i;
+	Ctlr *ctlr;
+	Desc *desc;
+	uchar *alloc;
+
+	ctlr = edev->ctlr;
+
+	dp83820halt(ctlr);
+
+	/*
+	 * Receiver
+	 */
+	alloc = (uchar*)ROUNDUP((ulong)ctlr->alloc, 8);
+	ctlr->rd = (Desc*)alloc;
+	alloc += ctlr->nrd*sizeof(Desc);
+	memset(ctlr->rd, 0, ctlr->nrd*sizeof(Desc));
+	ctlr->rdx = 0;
+	for(i = 0; i < ctlr->nrd; i++){
+		desc = &ctlr->rd[i];
+		desc->link = PCIWADDR(&ctlr->rd[NEXT(i, ctlr->nrd)]);
+		if(dp83820rballoc(desc) == nil)
+			continue;
+	}
+	csr32w(ctlr, Rxdphi, 0);
+	csr32w(ctlr, Rxdp, PCIWADDR(ctlr->rd));
+
+	for(i = 0; i < Eaddrlen; i += 2){
+		csr32w(ctlr, Rfcr, i);
+		csr32w(ctlr, Rfdr, (edev->ea[i+1]<<8)|edev->ea[i]);
+	}
+	csr32w(ctlr, Rfcr, Rfen|Aab|Aam|Apm);
+
+	ctlr->rxcfg = Stripcrc|(((2*(ETHERMINTU+4))/8)<<RxdrthSHFT);
+	ctlr->imr |= Rxorn|Rxidle|Rxearly|Rxdesc|Rxok;
+
+	/*
+	 * Transmitter.
+	 */
+	ctlr->td = (Desc*)alloc;
+	memset(ctlr->td, 0, ctlr->ntd*sizeof(Desc));
+	ctlr->tdh = ctlr->tdt = ctlr->ntq = 0;
+	for(i = 0; i < ctlr->ntd; i++){
+		desc = &ctlr->td[i];
+		desc->link = PCIWADDR(&ctlr->td[NEXT(i, ctlr->ntd)]);
+	}
+	csr32w(ctlr, Txdphi, 0);
+	csr32w(ctlr, Txdp, PCIWADDR(ctlr->td));
+
+	ctlr->txcfg = Atp|(((2*(ETHERMINTU+4))/32)<<FlthSHFT)|((4096/32)<<TxdrthSHFT);
+	ctlr->imr |= Txurn|Txidle|Txdesc|Txok;
+
+	ilock(&ctlr->ilock);
+
+	dp83820cfg(ctlr);
+
+	csr32w(ctlr, Mibc, Aclr);
+	ctlr->imr |= Mib;
+
+	csr32w(ctlr, Imr, ctlr->imr);
+
+	/* try coalescing adjacent interrupts; use hold-off interval of 100µs */
+	csr32w(ctlr, Ihr, Ihctl|(1<<IhSHFT));
+
+	csr32w(ctlr, Ier, Ien);
+	csr32w(ctlr, Cr, Rxe|Txe);
+
+	iunlock(&ctlr->ilock);
+}
+
+static void
+dp83820attach(Ether* edev)
+{
+	Block *bp;
+	Ctlr *ctlr;
+
+	ctlr = edev->ctlr;
+	lock(&ctlr->alock);
+	if(ctlr->alloc != nil){
+		unlock(&ctlr->alock);
+		return;
+	}
+
+	if(waserror()){
+err:
+		if(ctlr->mii != nil){
+			free(ctlr->mii);
+			ctlr->mii = nil;
+		}
+		if(ctlr->alloc != nil){
+			free(ctlr->alloc);
+			ctlr->alloc = nil;
+		}
+		unlock(&ctlr->alock);
+		return;
+	}
+
+	if(!(ctlr->cfg & Tbien)){
+		if((ctlr->mii = malloc(sizeof(Mii))) == nil)
+			goto err;
+		ctlr->mii->ctlr = ctlr;
+		ctlr->mii->mir = dp83820miimir;
+		ctlr->mii->miw = dp83820miimiw;
+		if(mii(ctlr->mii, ~0) == 0)
+			goto err;
+		ctlr->cfg |= Dupstsien|Lnkstsien|Spdstsien;
+		ctlr->imr |= Phy;
+	}
+
+	ctlr->nrd = Nrd;
+	ctlr->nrb = Nrbf;
+	ctlr->ntd = Ntd;
+	ctlr->alloc = mallocz((ctlr->nrd+ctlr->ntd)*sizeof(Desc) + 7, 0);
+	if(ctlr->alloc == nil)
+		goto err;
+
+	/*
+	 * the Bill Paul bsd drivers claim that receive buffers must be aligned
+	 * on 8-byte boundaries.
+	 */
+	for(ctlr->nrb = 0; ctlr->nrb < Nrbf; ctlr->nrb++){
+		if((bp = allocb(Rbsz+8-1)) == nil)
+			break;
+		bp->rp += 8 - (uintptr)bp->rp % 8;
+		bp->wp = bp->rp;
+//		bp->free = dp83820rbfree;	/* TODO: fix */
+		dp83820rbfree(bp);
+	}
+
+	dp83820init(edev);
+
+	unlock(&ctlr->alock);
+	poperror();
+}
+
+/*
+ *  free a list of blocks
+ */
+static void
+freeblist(Block *b)
+{
+	Block *next;
+
+	for(; b != 0; b = next){
+		next = b->next;
+		b->next = 0;
+		freeb(b);
+	}
+}
+
+static void
+toringbuf(Ether *ether, Block *bp)
+{
+	RingBuf *rb = &ether->rb[ether->ri];
+
+	if (rb->owner == Interface) {
+		rb->len = BLEN(bp);
+		memmove(rb->pkt, bp->rp, rb->len);
+		rb->owner = Host;
+		ether->ri = NEXT(ether->ri, ether->nrb);
+	}
+	/* else no one is expecting packets from the network */
+}
+
+static Block *
+fromringbuf(Ether *ether)
+{
+	RingBuf *tb = &ether->tb[ether->ti];
+	Block *bp = allocb(tb->len);
+
+	memmove(bp->wp, tb->pkt, tb->len);
+	memmove(bp->wp+Eaddrlen, ether->ea, Eaddrlen);
+	bp->wp += tb->len;
+	return bp;
+}
+
+static void
+dp83820transmit(Ether* edev)
+{
+	Block *bp;
+	Ctlr *ctlr;
+	Desc *desc;
+	RingBuf *tb;
+	int cmdsts, r, x;
+
+	ctlr = edev->ctlr;
+
+	ilock(&ctlr->tlock);
+
+	bp = nil;
+	for(x = ctlr->tdh; ctlr->ntq; x = NEXT(x, ctlr->ntd)){
+		desc = &ctlr->td[x];
+		if((cmdsts = desc->cmdsts) & Own)
+			break;
+		if(!(cmdsts & Ok)){
+			if(cmdsts & Ec)
+				ctlr->ec++;
+			if(cmdsts & Owc)
+				ctlr->owc++;
+			if(cmdsts & Ed)
+				ctlr->ed++;
+			if(cmdsts & Crs)
+				ctlr->crs++;
+			if(cmdsts & Tfu)
+				ctlr->tfu++;
+			if(cmdsts & Txa)
+				ctlr->txa++;
+		}
+		desc->bp->next = bp;
+		bp = desc->bp;
+		desc->bp = nil;
+
+		ctlr->ntq--;
+	}
+	ctlr->tdh = x;
+	if(bp != nil)
+		freeblist(bp);
+
+	x = ctlr->tdt;
+//	tb = &edev->tb[edev->ti];
+	while(ctlr->ntq < ctlr->ntd - 1 /* && tb->owner == Interface */ ){
+		bp = fromringbuf(edev);
+		if (bp == nil)
+			break;
+
+		/* transmit packet from bp */
+		desc = &ctlr->td[x];
+		desc->bufptr = PCIWADDR(bp->rp);
+		desc->bp = bp;
+		ctlr->ntq++;
+		coherence();
+		desc->cmdsts = Own|Intr|BLEN(bp);	/* kick transmitter */
+//print("t");
+		tb = &edev->tb[edev->ti];
+		tb->owner = Host;		/* give descriptor back */
+		edev->ti = NEXT(edev->ti, edev->ntb);
+
+		x = NEXT(x, ctlr->ntd);
+	}
+	if(x != ctlr->tdt){
+		ctlr->tdt = x;
+		r = csr32r(ctlr, Cr);
+		csr32w(ctlr, Cr, Txe|r);
+	}
+
+	iunlock(&ctlr->tlock);
+}
+
+static void
+dp83820interrupt(Ureg*, void* arg)
+{
+	Block *bp;
+	Ctlr *ctlr;
+	Desc *desc;
+	Ether *edev;
+	int cmdsts, i, isr, r, x;
+
+	edev = arg;
+	ctlr = edev->ctlr;
+
+	for(isr = csr32r(ctlr, Isr); isr & ctlr->imr; isr = csr32r(ctlr, Isr)){
+		if(isr & (Rxorn|Rxidle|Rxearly|Rxerr|Rxdesc|Rxok)){
+			x = ctlr->rdx;
+			desc = &ctlr->rd[x];
+			while((cmdsts = desc->cmdsts) & Own){
+				if((cmdsts & Ok) && desc->bp != nil){
+					/* receive a packet into desc->bp */
+					bp = desc->bp;
+					desc->bp = nil;
+					// bp->rp = desc->bufptr;
+					bp->wp += cmdsts & SizeMASK;
+
+					toringbuf(edev, bp);
+//print("r");
+				}
+				dp83820rballoc(desc);
+
+				x = NEXT(x, ctlr->nrd);
+				desc = &ctlr->rd[x];
+			}
+			ctlr->rdx = x;
+
+			if(isr & Rxidle){
+				r = csr32r(ctlr, Cr);
+				csr32w(ctlr, Cr, Rxe|r);
+				ctlr->rxidle++;
+			}
+
+			isr &= ~(Rxorn|Rxidle|Rxearly|Rxerr|Rxdesc|Rxok);
+		}
+
+		if(isr & Txurn){
+			x = (ctlr->txcfg & TxdrthMASK)>>TxdrthSHFT;
+			r = (ctlr->txcfg & FlthMASK)>>FlthSHFT;
+			if(x < ((TxdrthMASK)>>TxdrthSHFT)
+			&& x < (2048/32 - r)){
+				ctlr->txcfg &= ~TxdrthMASK;
+				x++;
+				ctlr->txcfg |= x<<TxdrthSHFT;
+				csr32w(ctlr, Txcfg, ctlr->txcfg);
+			}
+		}
+
+		if(isr & (Txurn|Txidle|Txdesc|Txok)){
+			dp83820transmit(edev);
+			isr &= ~(Txurn|Txidle|Txdesc|Txok);
+		}
+
+		if(isr & Mib){
+			for(i = 0; i < Nmibd; i++){
+				r = csr32r(ctlr, Mibd+(i*sizeof(int)));
+				ctlr->mibd[i] += r & 0xFFFF;
+			}
+			isr &= ~Mib;
+		}
+
+		if((isr & Phy) && ctlr->mii != nil){
+			ctlr->mii->mir(ctlr->mii, 1, Bmsr);
+			print("phy: cfg %8.8uX bmsr %4.4uX\n",
+				csr32r(ctlr, Cfg),
+				ctlr->mii->mir(ctlr->mii, 1, Bmsr));
+			dp83820cfg(ctlr);
+			isr &= ~Phy;
+		}
+// TODO fix	if(isr)
+// TODO fix		iprint("dp83820: isr %8.8uX\n", isr);
+		USED(isr);
+	}
+}
+
+static int
+dp83820detach(Ctlr* ctlr)
+{
+	/*
+	 * Soft reset the controller.
+	 */
+	csr32w(ctlr, Cr, Rst);
+	delay(1);
+	while(csr32r(ctlr, Cr) & Rst)
+		delay(1);
+	return 0;
+}
+
+static void
+dp83820shutdown(Ether* ether)
+{
+print("dp83820shutdown\n");
+	dp83820detach(ether->ctlr);
+}
+
+static int
+atc93c46r(Ctlr* ctlr, int address)
+{
+	int data, i, mear, r, size;
+
+	/*
+	 * Analog Technology, Inc. ATC93C46
+	 * or equivalent serial EEPROM.
+	 */
+	mear = csr32r(ctlr, Mear);
+	mear &= ~(Eesel|Eeclk|Eedo|Eedi);
+	r = Eesel|mear;
+
+reread:
+	csr32w(ctlr, Mear, r);
+	data = 0x06;
+	for(i = 3-1; i >= 0; i--){
+		if(data & (1<<i))
+			r |= Eedi;
+		else
+			r &= ~Eedi;
+		csr32w(ctlr, Mear, r);
+		csr32w(ctlr, Mear, Eeclk|r);
+		microdelay(1);
+		csr32w(ctlr, Mear, r);
+		microdelay(1);
+	}
+
+	/*
+	 * First time through must work out the EEPROM size.
+	 */
+	if((size = ctlr->eepromsz) == 0)
+		size = 8;
+
+	for(size = size-1; size >= 0; size--){
+		if(address & (1<<size))
+			r |= Eedi;
+		else
+			r &= ~Eedi;
+		csr32w(ctlr, Mear, r);
+		microdelay(1);
+		csr32w(ctlr, Mear, Eeclk|r);
+		microdelay(1);
+		csr32w(ctlr, Mear, r);
+		microdelay(1);
+		if(!(csr32r(ctlr, Mear) & Eedo))
+			break;
+	}
+	r &= ~Eedi;
+
+	data = 0;
+	for(i = 16-1; i >= 0; i--){
+		csr32w(ctlr, Mear, Eeclk|r);
+		microdelay(1);
+		if(csr32r(ctlr, Mear) & Eedo)
+			data |= (1<<i);
+		csr32w(ctlr, Mear, r);
+		microdelay(1);
+	}
+
+	csr32w(ctlr, Mear, mear);
+
+	if(ctlr->eepromsz == 0){
+		ctlr->eepromsz = 8-size;
+		ctlr->eeprom = malloc((1<<ctlr->eepromsz)*sizeof(ushort));
+		goto reread;
+	}
+
+	return data;
+}
+
+static int
+dp83820reset(Ctlr* ctlr)
+{
+	int i, r;
+	unsigned char sum;
+
+	/*
+	 * Soft reset the controller;
+	 * read the EEPROM to get the initial settings
+	 * of the Cfg and Gpior bits which should be cleared by
+	 * the reset.
+	 */
+	csr32w(ctlr, Cr, Rst);
+	delay(1);
+	while(csr32r(ctlr, Cr) & Rst)
+		delay(1);
+
+	atc93c46r(ctlr, 0);
+	if(ctlr->eeprom == nil) {
+		print("dp83820reset: no eeprom\n");
+		return -1;
+	}
+	sum = 0;
+	for(i = 0; i < 0x0E; i++){
+		r = atc93c46r(ctlr, i);
+		ctlr->eeprom[i] = r;
+		sum += r;
+		sum += r>>8;
+	}
+
+	if(sum != 0){
+		print("dp83820reset: bad EEPROM checksum\n");
+		return -1;
+	}
+
+#ifdef notdef
+	csr32w(ctlr, Gpior, ctlr->eeprom[4]);
+
+	cfg = Extstsen|Exd;
+	r = csr32r(ctlr, Cfg);
+	if(ctlr->eeprom[5] & 0x0001)
+		cfg |= Ext125;
+	if(ctlr->eeprom[5] & 0x0002)
+		cfg |= M64addren;
+	if((ctlr->eeprom[5] & 0x0004) && (r & Pci64det))
+		cfg |= Data64en;
+	if(ctlr->eeprom[5] & 0x0008)
+		cfg |= T64addren;
+	if(!(pcicfgr16(ctlr->pcidev, PciPCR) & 0x10))
+		cfg |= Mwidis;
+	if(ctlr->eeprom[5] & 0x0020)
+		cfg |= Mrmdis;
+	if(ctlr->eeprom[5] & 0x0080)
+		cfg |= Mode1000;
+	if(ctlr->eeprom[5] & 0x0200)
+		cfg |= Tbien|Mode1000;
+	/*
+	 * What about RO bits we might have destroyed with Rst?
+	 * What about Exd, Tmrtest, Extstsen, Pintctl?
+	 * Why does it think it has detected a 64-bit bus when
+	 * it hasn't?
+	 */
+#else
+	//r = csr32r(ctlr, Cfg);
+	//r &= ~(Mode1000|T64addren|Data64en|M64addren);
+	//csr32w(ctlr, Cfg, r);
+	//csr32w(ctlr, Cfg, 0x2000);
+#endif /* notdef */
+	ctlr->cfg = csr32r(ctlr, Cfg);
+print("cfg %8.8uX pcicfg %8.8uX\n", ctlr->cfg, pcicfgr32(ctlr->pcidev, PciPCR));
+	ctlr->cfg &= ~(T64addren|Data64en|M64addren);
+	csr32w(ctlr, Cfg, ctlr->cfg);
+	csr32w(ctlr, Mibc, Aclr|Frz);
+
+	return 0;
+}
+
+static void
+dp83820pci(void)
+{
+	int port;
+	Pcidev *p;
+	Ctlr *ctlr;
+
+	p = nil;
+	while(p = pcimatch(p, 0, 0)){
+		if(p->ccrb != 0x02 || p->ccru != 0)
+			continue;
+
+		switch((p->did<<16)|p->vid){
+		default:
+			continue;
+		case (0x0022<<16)|0x100B:	/* DP83820 (Gig-NIC) */
+			break;
+		}
+
+		port = upamalloc(p->mem[1].bar & ~0x0F, p->mem[1].size, 0);
+		if(port == 0){
+			print("dp83820: can't map %d @ 0x%8.8luX\n",
+				p->mem[1].size, p->mem[1].bar);
+			continue;
+		}
+
+		ctlr = malloc(sizeof(Ctlr));
+		ctlr->port = port;
+		ctlr->pcidev = p;
+		ctlr->id = p->did<<16 | p->vid;
+
+		ctlr->nic = KADDR(ctlr->port);
+		if(dp83820reset(ctlr)){
+			free(ctlr);
+			continue;
+		}
+		pcisetbme(p);
+
+		if(dp83820ctlrhead != nil)
+			dp83820ctlrtail->next = ctlr;
+		else
+			dp83820ctlrhead = ctlr;
+		dp83820ctlrtail = ctlr;
+	}
+}
+
+int
+dp83820pnp(Ether* edev)
+{
+	int i;
+	Ctlr *ctlr;
+	uchar ea[Eaddrlen];
+
+	if(dp83820ctlrhead == nil)
+		dp83820pci();
+
+	/*
+	 * Any adapter matches if no edev->port is supplied,
+	 * otherwise the ports must match.
+	 */
+	for(ctlr = dp83820ctlrhead; ctlr != nil; ctlr = ctlr->next){
+		if(ctlr->active)
+			continue;
+		if(edev->port == 0 || edev->port == ctlr->port){
+			ctlr->active = 1;
+			break;
+		}
+	}
+	if(ctlr == nil)
+		return -1;
+
+	edev->ctlr = ctlr;
+	edev->port = ctlr->port;
+	edev->irq = ctlr->pcidev->intl;
+	edev->tbdf = ctlr->pcidev->tbdf;
+
+	/*
+	 * Check if the adapter's station address is to be overridden.
+	 * If not, read it from the EEPROM and set in ether->ea prior to
+	 * loading the station address in the hardware.
+	 */
+	memset(ea, 0, Eaddrlen);
+	if(memcmp(ea, edev->ea, Eaddrlen) == 0)
+		for(i = 0; i < Eaddrlen/2; i++){
+			edev->ea[2*i] = ctlr->eeprom[0x0C-i];
+			edev->ea[2*i+1] = ctlr->eeprom[0x0C-i]>>8;
+		}
+
+	edev->attach = dp83820attach;
+	edev->transmit = dp83820transmit;
+	edev->interrupt = dp83820interrupt;
+	edev->detach = dp83820shutdown;
+	return 0;
+}
--- /dev/null
+++ b/os/boot.original/pc/etherec2t.c
@@ -1,0 +1,155 @@
+/*
+ * Supposed NE2000 PCMCIA clones, see the comments in ether2000.c
+ */
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+#include "etherif.h"
+#include "ether8390.h"
+
+enum {
+	Data		= 0x10,		/* offset from I/O base of data port */
+	Reset		= 0x1F,		/* offset from I/O base of reset port */
+};
+
+static char* ec2tpcmcia[] = {
+	"EC2T",				/* Linksys Combo PCMCIA EthernetCard */
+	"PCMPC100",			/* EtherFast 10/100 PC Card */
+	"EN2216",			/* Accton EtherPair-PCMCIA */
+	"FA410TX",			/* Netgear FA410TX */
+	"Network Everywhere",		/* Linksys NP10T 10BaseT Card */
+	nil,
+};
+
+int
+ec2treset(Ether* ether)
+{
+	ushort buf[16];
+	ulong port;
+	Dp8390 *ctlr;
+	int i, slot;
+	uchar ea[Eaddrlen], sum, x;
+	char *type;
+
+	/*
+	 * Set up the software configuration.
+	 * Use defaults for port, irq, mem and size
+	 * if not specified.
+	 * The manual says 16KB memory, the box
+	 * says 32KB. The manual seems to be correct.
+	 */
+	if(ether->port == 0)
+		ether->port = 0x300;
+	if(ether->irq == 0)
+		ether->irq = 9;
+	if(ether->mem == 0)
+		ether->mem = 0x4000;
+	if(ether->size == 0)
+		ether->size = 16*1024;
+	port = ether->port;
+
+	//if(ioalloc(ether->port, 0x20, 0, "ec2t") < 0)
+	//	return -1;
+	slot = -1;
+	type = nil;
+	for(i = 0; ec2tpcmcia[i] != nil; i++){
+		type = ec2tpcmcia[i];
+		if((slot = pcmspecial(type, ether)) >= 0)
+			break;
+	}
+	if(ec2tpcmcia[i] == nil){
+		for(i = 0; i < ether->nopt; i++){
+			if(cistrncmp(ether->opt[i], "id=", 3))
+				continue;
+			type = &ether->opt[i][3];
+			if((slot = pcmspecial(type, ether)) >= 0)
+				break;
+		}
+	}
+	if(slot < 0){
+	//	iofree(port);
+		return -1;
+	}
+
+	ether->ctlr = malloc(sizeof(Dp8390));
+	ctlr = ether->ctlr;
+	ctlr->width = 2;
+	ctlr->ram = 0;
+
+	ctlr->port = port;
+	ctlr->data = port+Data;
+
+	ctlr->tstart = HOWMANY(ether->mem, Dp8390BufSz);
+	ctlr->pstart = ctlr->tstart + HOWMANY(sizeof(Etherpkt), Dp8390BufSz);
+	ctlr->pstop = ctlr->tstart + HOWMANY(ether->size, Dp8390BufSz);
+
+	ctlr->dummyrr = 0;
+	for(i = 0; i < ether->nopt; i++){
+		if(cistrcmp(ether->opt[i], "nodummyrr") == 0)
+			ctlr->dummyrr = 0;
+		else if(cistrncmp(ether->opt[i], "dummyrr=", 8) == 0)
+			ctlr->dummyrr = strtol(&ether->opt[i][8], nil, 0);
+	}
+
+	/*
+	 * Reset the board. This is done by doing a read
+	 * followed by a write to the Reset address.
+	 */
+	buf[0] = inb(port+Reset);
+	delay(2);
+	outb(port+Reset, buf[0]);
+	delay(2);
+
+	/*
+	 * Init the (possible) chip, then use the (possible)
+	 * chip to read the (possible) PROM for ethernet address
+	 * and a marker byte.
+	 * Could just look at the DP8390 command register after
+	 * initialisation has been tried, but that wouldn't be
+	 * enough, there are other ethernet boards which could
+	 * match.
+	 */
+	dp8390reset(ether);
+	sum = 0;
+	if(cistrcmp(type, "PCMPC100") == 0 || cistrcmp(type, "FA410TX") == 0){
+		/*
+		 * The PCMPC100 has the ethernet address in I/O space.
+		 * There's a checksum over 8 bytes which sums to 0xFF.
+		 */
+		for(i = 0; i < 8; i++){
+			x = inb(port+0x14+i);
+			sum += x;
+			buf[i] = (x<<8)|x;
+		}
+	}
+	else{
+		memset(buf, 0, sizeof(buf));
+		dp8390read(ctlr, buf, 0, sizeof(buf));
+		if((buf[0x0E] & 0xFF) == 0x57 && (buf[0x0F] & 0xFF) == 0x57)
+			sum = 0xFF;
+	}
+	if(sum != 0xFF){
+		pcmspecialclose(slot);
+		//iofree(ether->port);
+		free(ether->ctlr);
+		return -1;
+	}
+
+	/*
+	 * Stupid machine. Shorts were asked for,
+	 * shorts were delivered, although the PROM is a byte array.
+	 * Set the ethernet address.
+	 */
+	memset(ea, 0, Eaddrlen);
+	if(memcmp(ea, ether->ea, Eaddrlen) == 0){
+		for(i = 0; i < sizeof(ether->ea); i++)
+			ether->ea[i] = buf[i];
+	}
+	dp8390setea(ether);
+
+	return 0;
+}
--- /dev/null
+++ b/os/boot.original/pc/etherelnk3.c
@@ -1,0 +1,1897 @@
+/*
+ * Etherlink III, Fast EtherLink and Fast EtherLink XL adapters.
+ * To do:
+ *	check robustness in the face of errors (e.g. busmaster & rxUnderrun);
+ *	RxEarly and busmaster;
+ *	autoSelect;
+ *	PCI latency timer and master enable;
+ *	errata list;
+ *	rewrite all initialisation.
+ *
+ * Product ID:
+ *	9150 ISA	3C509[B]
+ *	9050 ISA	3C509[B]-TP
+ *	9450 ISA	3C509[B]-COMBO
+ *	9550 ISA	3C509[B]-TPO
+ *
+ *	9350 EISA	3C579
+ *	9250 EISA	3C579-TP
+ *
+ *	5920 EISA	3C592-[TP|COMBO|TPO]
+ *	5970 EISA	3C597-TX	Fast Etherlink 10BASE-T/100BASE-TX
+ *	5971 EISA	3C597-T4	Fast Etherlink 10BASE-T/100BASE-T4
+ *	5972 EISA	3C597-MII	Fast Etherlink 10BASE-T/MII
+ *
+ *	5900 PCI	3C590-[TP|COMBO|TPO]
+ *	5950 PCI	3C595-TX	Fast Etherlink Shared 10BASE-T/100BASE-TX
+ *	5951 PCI	3C595-T4	Fast Etherlink Shared 10BASE-T/100BASE-T4
+ *	5952 PCI	3C595-MII	Fast Etherlink 10BASE-T/MII
+ *
+ *	9000 PCI	3C900-TPO	Etherlink III XL PCI 10BASE-T
+ *	9001 PCI	3C900-COMBO	Etherlink III XL PCI 10BASE-T/10BASE-2/AUI
+ *	9005 PCI	3C900B-COMBO	Etherlink III XL PCI 10BASE-T/10BASE-2/AUI
+ *	9050 PCI	3C905-TX	Fast Etherlink XL Shared 10BASE-T/100BASE-TX
+ *	9051 PCI	3C905-T4	Fast Etherlink Shared 10BASE-T/100BASE-T4
+ *	9055 PCI	3C905B-TX	Fast Etherlink Shared 10BASE-T/100BASE-TX
+ *	9200 PCI	3C905C-TX	Fast Etherlink Shared 10BASE-T/100BASE-TX
+ *
+ *	9058 PCMCIA	3C589[B]-[TP|COMBO]
+ *
+ *	627C MCA	3C529
+ *	627D MCA	3C529-TP
+ */
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+#include "etherif.h"
+
+#define XCVRDEBUG		if(0)print
+
+enum {
+	IDport			= 0x0110,	/* anywhere between 0x0100 and 0x01F0 */
+};
+
+enum {						/* all windows */
+	CommandR		= 0x000E,
+	IntStatusR		= 0x000E,
+};
+
+enum {						/* Commands */
+	GlobalReset		= 0x0000,
+	SelectRegisterWindow	= 0x0001,
+	EnableDcConverter	= 0x0002,
+	RxDisable		= 0x0003,
+	RxEnable		= 0x0004,
+	RxReset			= 0x0005,
+	Stall			= 0x0006,	/* 3C90x */
+	TxDone			= 0x0007,
+	RxDiscard		= 0x0008,
+	TxEnable		= 0x0009,
+	TxDisable		= 0x000A,
+	TxReset			= 0x000B,
+	RequestInterrupt	= 0x000C,
+	AcknowledgeInterrupt	= 0x000D,
+	SetInterruptEnable	= 0x000E,
+	SetIndicationEnable	= 0x000F,	/* SetReadZeroMask */
+	SetRxFilter		= 0x0010,
+	SetRxEarlyThresh	= 0x0011,
+	SetTxAvailableThresh	= 0x0012,
+	SetTxStartThresh	= 0x0013,
+	StartDma		= 0x0014,	/* initiate busmaster operation */
+	StatisticsEnable	= 0x0015,
+	StatisticsDisable	= 0x0016,
+	DisableDcConverter	= 0x0017,
+	SetTxReclaimThresh	= 0x0018,	/* PIO-only adapters */
+	PowerUp			= 0x001B,	/* not all adapters */
+	PowerDownFull		= 0x001C,	/* not all adapters */
+	PowerAuto		= 0x001D,	/* not all adapters */
+};
+
+enum {						/* (Global|Rx|Tx)Reset command bits */
+	tpAuiReset		= 0x0001,	/* 10BaseT and AUI transceivers */
+	endecReset		= 0x0002,	/* internal Ethernet encoder/decoder */
+	networkReset		= 0x0004,	/* network interface logic */
+	fifoReset		= 0x0008,	/* FIFO control logic */
+	aismReset		= 0x0010,	/* autoinitialise state-machine logic */
+	hostReset		= 0x0020,	/* bus interface logic */
+	dmaReset		= 0x0040,	/* bus master logic */
+	vcoReset		= 0x0080,	/* on-board 10Mbps VCO */
+	updnReset		= 0x0100,	/* upload/download (Rx/TX) logic */
+
+	resetMask		= 0x01FF,
+};
+
+enum {						/* Stall command bits */
+	upStall			= 0x0000,
+	upUnStall		= 0x0001,
+	dnStall			= 0x0002,
+	dnUnStall		= 0x0003,
+};
+
+enum {						/* SetRxFilter command bits */
+	receiveIndividual	= 0x0001,	/* match station address */
+	receiveMulticast	= 0x0002,
+	receiveBroadcast	= 0x0004,
+	receiveAllFrames	= 0x0008,	/* promiscuous */
+};
+
+enum {						/* StartDma command bits */
+	Upload			= 0x0000,	/* transfer data from adapter to memory */
+	Download		= 0x0001,	/* transfer data from memory to adapter */
+};
+
+enum {						/* IntStatus bits */
+	interruptLatch		= 0x0001,
+	hostError		= 0x0002,	/* Adapter Failure */
+	txComplete		= 0x0004,
+	txAvailable		= 0x0008,
+	rxComplete		= 0x0010,
+	rxEarly			= 0x0020,
+	intRequested		= 0x0040,
+	updateStats		= 0x0080,
+	transferInt		= 0x0100,	/* Bus Master Transfer Complete */
+	dnComplete		= 0x0200,
+	upComplete		= 0x0400,
+	busMasterInProgress	= 0x0800,
+	commandInProgress	= 0x1000,
+
+	interruptMask		= 0x07FE,
+};
+
+#define COMMAND(port, cmd, a)	outs((port)+CommandR, ((cmd)<<11)|(a))
+#define STATUS(port)		ins((port)+IntStatusR)
+
+enum {						/* Window 0 - setup */
+	Wsetup			= 0x0000,
+						/* registers */
+	ManufacturerID		= 0x0000,	/* 3C5[08]*, 3C59[27] */
+	ProductID		= 0x0002,	/* 3C5[08]*, 3C59[27] */
+	ConfigControl		= 0x0004,	/* 3C5[08]*, 3C59[27] */
+	AddressConfig		= 0x0006,	/* 3C5[08]*, 3C59[27] */
+	ResourceConfig		= 0x0008,	/* 3C5[08]*, 3C59[27] */
+	EepromCommand		= 0x000A,
+	EepromData		= 0x000C,
+						/* AddressConfig Bits */
+	autoSelect9		= 0x0080,
+	xcvrMask9		= 0xC000,
+						/* ConfigControl bits */
+	Ena			= 0x0001,
+	base10TAvailable9	= 0x0200,
+	coaxAvailable9		= 0x1000,
+	auiAvailable9		= 0x2000,
+						/* EepromCommand bits */
+	_EepromReadRegister	= 0x0080,
+	_EepromRead8bRegister	= 0x0230,
+	EepromBusy		= 0x8000,
+};
+
+static int EepromReadRegister = _EepromReadRegister;
+
+#define EEPROMCMD(port, cmd, a)	outs((port)+EepromCommand, (cmd)|(a))
+#define EEPROMBUSY(port)	(ins((port)+EepromCommand) & EepromBusy)
+#define EEPROMDATA(port)	ins((port)+EepromData)
+
+enum {						/* Window 1 - operating set */
+	Wop			= 0x0001,
+						/* registers */
+	Fifo			= 0x0000,
+	RxError			= 0x0004,	/* 3C59[0257] only */
+	RxStatus		= 0x0008,
+	Timer			= 0x000A,
+	TxStatus		= 0x000B,
+	TxFree			= 0x000C,
+						/* RxError bits */
+	rxOverrun		= 0x0001,
+	runtFrame		= 0x0002,
+	alignmentError		= 0x0004,	/* Framing */
+	crcError		= 0x0008,
+	oversizedFrame		= 0x0010,
+	dribbleBits		= 0x0080,
+						/* RxStatus bits */
+	rxBytes			= 0x1FFF,	/* 3C59[0257] mask */
+	rxBytes9		= 0x07FF,	/* 3C5[078]9 mask */
+	rxError9		= 0x3800,	/* 3C5[078]9 error mask */
+	rxOverrun9		= 0x0000,
+	oversizedFrame9		= 0x0800,
+	dribbleBits9		= 0x1000,
+	runtFrame9		= 0x1800,
+	alignmentError9		= 0x2000,	/* Framing */
+	crcError9		= 0x2800,
+	rxError			= 0x4000,
+	rxIncomplete		= 0x8000,
+						/* TxStatus Bits */
+	txStatusOverflow	= 0x0004,
+	maxCollisions		= 0x0008,
+	txUnderrun		= 0x0010,
+	txJabber		= 0x0020,
+	interruptRequested	= 0x0040,
+	txStatusComplete	= 0x0080,
+};
+
+enum {						/* Window 2 - station address */
+	Wstation		= 0x0002,
+
+	ResetOp905B		= 0x000C,
+};
+
+enum {						/* Window 3 - FIFO management */
+	Wfifo			= 0x0003,
+						/* registers */
+	InternalConfig		= 0x0000,	/* 3C509B, 3C589, 3C59[0257] */
+	OtherInt		= 0x0004,	/* 3C59[0257] */
+	RomControl		= 0x0006,	/* 3C509B, 3C59[27] */
+	MacControl		= 0x0006,	/* 3C59[0257] */
+	ResetOptions		= 0x0008,	/* 3C59[0257] */
+	MediaOptions		= 0x0008,	/* 3C905B */
+	RxFree			= 0x000A,
+						/* InternalConfig bits */
+	disableBadSsdDetect	= 0x00000100,
+	ramLocation		= 0x00000200,	/* 0 external, 1 internal */
+	ramPartition5to3	= 0x00000000,
+	ramPartition3to1	= 0x00010000,
+	ramPartition1to1	= 0x00020000,
+	ramPartition3to5	= 0x00030000,
+	ramPartitionMask	= 0x00030000,
+	xcvr10BaseT		= 0x00000000,
+	xcvrAui			= 0x00100000,	/* 10BASE5 */
+	xcvr10Base2		= 0x00300000,
+	xcvr100BaseTX		= 0x00400000,
+	xcvr100BaseFX		= 0x00500000,
+	xcvrMii			= 0x00600000,
+	xcvrMask		= 0x00700000,
+	autoSelect		= 0x01000000,
+						/* MacControl bits */
+	deferExtendEnable	= 0x0001,
+	deferTimerSelect	= 0x001E,	/* mask */
+	fullDuplexEnable	= 0x0020,
+	allowLargePackets	= 0x0040,
+	extendAfterCollision	= 0x0080,	/* 3C90xB */
+	flowControlEnable	= 0x0100,	/* 3C90xB */
+	vltEnable		= 0x0200,	/* 3C90xB */
+						/* ResetOptions bits */
+	baseT4Available		= 0x0001,
+	baseTXAvailable		= 0x0002,
+	baseFXAvailable		= 0x0004,
+	base10TAvailable	= 0x0008,
+	coaxAvailable		= 0x0010,
+	auiAvailable		= 0x0020,
+	miiConnector		= 0x0040,
+};
+
+enum {						/* Window 4 - diagnostic */
+	Wdiagnostic		= 0x0004,
+						/* registers */
+	VcoDiagnostic		= 0x0002,
+	FifoDiagnostic		= 0x0004,
+	NetworkDiagnostic	= 0x0006,
+	PhysicalMgmt		= 0x0008,
+	MediaStatus		= 0x000A,
+	BadSSD			= 0x000C,
+	UpperBytesOk		= 0x000D,
+						/* FifoDiagnostic bits */
+	txOverrun		= 0x0400,
+	rxUnderrun		= 0x2000,
+	receiving		= 0x8000,
+						/* PhysicalMgmt bits */
+	mgmtClk			= 0x0001,
+	mgmtData		= 0x0002,
+	mgmtDir			= 0x0004,
+	cat5LinkTestDefeat	= 0x8000,
+						/* MediaStatus bits */
+	dataRate100		= 0x0002,
+	crcStripDisable		= 0x0004,
+	enableSqeStats		= 0x0008,
+	collisionDetect		= 0x0010,
+	carrierSense		= 0x0020,
+	jabberGuardEnable	= 0x0040,
+	linkBeatEnable		= 0x0080,
+	jabberDetect		= 0x0200,
+	polarityReversed	= 0x0400,
+	linkBeatDetect		= 0x0800,
+	txInProg		= 0x1000,
+	dcConverterEnabled	= 0x4000,
+	auiDisable		= 0x8000,	/* 10BaseT transceiver selected */
+};
+
+enum {						/* Window 5 - internal state */
+	Wstate			= 0x0005,
+						/* registers */
+	TxStartThresh		= 0x0000,
+	TxAvailableThresh	= 0x0002,
+	RxEarlyThresh		= 0x0006,
+	RxFilter		= 0x0008,
+	InterruptEnable		= 0x000A,
+	IndicationEnable	= 0x000C,
+};
+
+enum {						/* Window 6 - statistics */
+	Wstatistics		= 0x0006,
+						/* registers */
+	CarrierLost		= 0x0000,
+	SqeErrors		= 0x0001,
+	MultipleColls		= 0x0002,
+	SingleCollFrames	= 0x0003,
+	LateCollisions		= 0x0004,
+	RxOverruns		= 0x0005,
+	FramesXmittedOk		= 0x0006,
+	FramesRcvdOk		= 0x0007,
+	FramesDeferred		= 0x0008,
+	UpperFramesOk		= 0x0009,
+	BytesRcvdOk		= 0x000A,
+	BytesXmittedOk		= 0x000C,
+};
+
+enum {						/* Window 7 - bus master operations */
+	Wmaster			= 0x0007,
+						/* registers */
+	MasterAddress		= 0x0000,
+	MasterLen		= 0x0006,
+	MasterStatus		= 0x000C,
+						/* MasterStatus bits */
+	masterAbort		= 0x0001,
+	targetAbort		= 0x0002,
+	targetRetry		= 0x0004,
+	targetDisc		= 0x0008,
+	masterDownload		= 0x1000,
+	masterUpload		= 0x4000,
+	masterInProgress	= 0x8000,
+
+	masterMask		= 0xD00F,
+};
+
+enum {						/* 3C90x extended register set */
+	Timer905		= 0x001A,	/* 8-bits */
+	TxStatus905		= 0x001B,	/* 8-bits */
+	PktStatus		= 0x0020,	/* 32-bits */
+	DnListPtr		= 0x0024,	/* 32-bits, 8-byte aligned */
+	FragAddr		= 0x0028,	/* 32-bits */
+	FragLen			= 0x002C,	/* 16-bits */
+	ListOffset		= 0x002E,	/* 8-bits */
+	TxFreeThresh		= 0x002F,	/* 8-bits */
+	UpPktStatus		= 0x0030,	/* 32-bits */
+	FreeTimer		= 0x0034,	/* 16-bits */
+	UpListPtr		= 0x0038,	/* 32-bits, 8-byte aligned */
+
+						/* PktStatus bits */
+	fragLast		= 0x00000001,
+	dnCmplReq		= 0x00000002,
+	dnStalled		= 0x00000004,
+	upCompleteX		= 0x00000008,
+	dnCompleteX		= 0x00000010,
+	upRxEarlyEnable		= 0x00000020,
+	armCountdown		= 0x00000040,
+	dnInProg		= 0x00000080,
+	counterSpeed		= 0x00000010,	/* 0 3.2uS, 1 320nS */
+	countdownMode		= 0x00000020,
+						/* UpPktStatus bits (dpd->control) */
+	upPktLenMask		= 0x00001FFF,
+	upStalled		= 0x00002000,
+	upError			= 0x00004000,
+	upPktComplete		= 0x00008000,
+	upOverrun		= 0x00010000,	/* RxError<<16 */
+	upRuntFrame		= 0x00020000,
+	upAlignmentError	= 0x00040000,
+	upCRCError		= 0x00080000,
+	upOversizedFrame	= 0x00100000,
+	upDribbleBits		= 0x00800000,
+	upOverflow		= 0x01000000,
+
+	dnIndicate		= 0x80000000,	/* FrameStartHeader (dpd->control) */
+
+	updnLastFrag		= 0x80000000,	/* (dpd->len) */
+
+	Nup			= 32,
+	Ndn			= 64,
+};
+
+/*
+ * Up/Dn Packet Descriptors.
+ * The hardware info (np, control, addr, len) must be 8-byte aligned
+ * and this structure size must be a multiple of 8.
+ */
+typedef struct Pd Pd;
+typedef struct Pd {
+	ulong	np;				/* next pointer */
+	ulong	control;			/* FSH or UpPktStatus */
+	ulong	addr;
+	ulong	len;
+
+	Pd*	next;
+	void *vaddr;
+} Pd;
+
+typedef struct {
+	Lock	wlock;				/* window access */
+
+	int	attached;
+	int	busmaster;
+	Block*	rbp;				/* receive buffer */
+
+	Block*	txbp;				/* FIFO -based transmission */
+	int	txthreshold;
+	int	txbusy;
+
+	int	nup;				/* full-busmaster -based reception */
+	void*	upbase;
+	Pd*	upr;
+	Pd*	uphead;
+
+	int	ndn;				/* full-busmaster -based transmission */
+	void*	dnbase;
+	Pd*	dnr;
+	Pd*	dnhead;
+	Pd*	dntail;
+	int	dnq;
+
+	long	interrupts;			/* statistics */
+	long	timer[2];
+	long	stats[BytesRcvdOk+3];
+
+	int	upqmax;
+	int	upqmaxhw;
+	ulong	upinterrupts;
+	ulong	upqueued;
+	ulong	upstalls;
+	int	dnqmax;
+	int	dnqmaxhw;
+	ulong	dninterrupts;
+	ulong	dnqueued;
+
+	int	xcvr;				/* transceiver type */
+	int	rxstatus9;			/* old-style RxStatus register */
+	int	rxearly;			/* RxEarlyThreshold */
+	int	ts;				/* threshold shift */
+	int	upenabled;
+	int	dnenabled;
+} Ctlr;
+
+static void
+init905(Ctlr* ctlr)
+{
+	Pd *pd, *prev;
+	uchar *vaddr;
+
+	/*
+	 * Create rings for the receive and transmit sides.
+	 * Take care with alignment:
+	 *	make sure ring base is 8-byte aligned;
+	 *	make sure each entry is 8-byte aligned.
+	 */
+	ctlr->upbase = malloc((ctlr->nup+1)*sizeof(Pd));
+	ctlr->upr = (Pd*)ROUNDUP((ulong)ctlr->upbase, 8);
+	vaddr = ialloc((ctlr->nup+1)*ROUNDUP(sizeof(Etherpkt)+4, 8), 8);
+
+	prev = ctlr->upr;
+	for(pd = &ctlr->upr[ctlr->nup-1]; pd >= ctlr->upr; pd--){
+		pd->np = PADDR(&prev->np);
+		pd->control = 0;
+		pd->vaddr = vaddr;
+		pd->addr = PADDR(vaddr);
+		vaddr += ROUNDUP(sizeof(Etherpkt)+4, 8);
+		pd->len = updnLastFrag|sizeof(Etherpkt);
+
+		pd->next = prev;
+		prev = pd;
+	}
+	ctlr->uphead = ctlr->upr;
+
+	ctlr->dnbase = malloc((ctlr->ndn+1)*sizeof(Pd));
+	ctlr->dnr = (Pd*)ROUNDUP((ulong)ctlr->dnbase, 8);
+	vaddr = ialloc((ctlr->ndn+1)*ROUNDUP(sizeof(Etherpkt)+4, 8), 8); 
+
+	prev = ctlr->dnr;
+	for(pd = &ctlr->dnr[ctlr->ndn-1]; pd >= ctlr->dnr; pd--){
+		pd->next = prev;
+		pd->vaddr = vaddr;								
+		pd->addr = PADDR(vaddr);						
+		vaddr += ROUNDUP(sizeof(Etherpkt)+4, 8);		
+		prev = pd;
+	}
+	ctlr->dnhead = ctlr->dnr;
+	ctlr->dntail = ctlr->dnr;
+	ctlr->dnq = 0;
+}
+
+static Block*
+rbpalloc(Block* (*f)(int))
+{
+	Block *bp;
+	ulong addr;
+
+	/*
+	 * The receive buffers must be on a 32-byte
+	 * boundary for EISA busmastering.
+	 */
+	if(bp = f(ROUNDUP(sizeof(Etherpkt), 4) + 31)){
+		addr = (ulong)bp->base;
+		addr = ROUNDUP(addr, 32);
+		bp->rp = (uchar*)addr;
+	}
+
+	return bp;
+}
+
+static uchar*
+startdma(Ether* ether, ulong address)
+{
+	int port, status, w;
+	uchar *wp;
+
+	port = ether->port;
+
+	w = (STATUS(port)>>13) & 0x07;
+	COMMAND(port, SelectRegisterWindow, Wmaster);
+
+	wp = KADDR(inl(port+MasterAddress));
+	status = ins(port+MasterStatus);
+	if(status & (masterInProgress|targetAbort|masterAbort))
+		print("#l%d: BM status 0x%uX\n", ether->ctlrno, status);
+	outs(port+MasterStatus, masterMask);
+	outl(port+MasterAddress, address);
+	outs(port+MasterLen, sizeof(Etherpkt));
+	COMMAND(port, StartDma, Upload);
+
+	COMMAND(port, SelectRegisterWindow, w);
+	return wp;
+}
+
+/* On the 575B and C, interrupts need to be acknowledged in CardBus memory space */
+static void
+intrack3c575(ulong *cbfns)
+{
+	cbfns[1] = 0x8000;
+}
+
+static void
+attach(Ether* ether)
+{
+	int port, x;
+	Ctlr *ctlr;
+
+	ctlr = ether->ctlr;
+	ilock(&ctlr->wlock);
+	if(ctlr->attached){
+		iunlock(&ctlr->wlock);
+		return;
+	}
+
+	port = ether->port;
+
+	COMMAND(port, SetRxFilter, receiveIndividual|receiveBroadcast);
+	x = interruptMask;
+	if(ctlr->busmaster == 1)
+		x &= ~(rxEarly|rxComplete);
+	else{
+		if(ctlr->dnenabled)
+			x &= ~transferInt;
+		if(ctlr->upenabled)
+			x &= ~(rxEarly|rxComplete);
+	}
+	COMMAND(port, SetIndicationEnable, x);
+	COMMAND(port, SetInterruptEnable, x);
+	COMMAND(port, RxEnable, 0);
+	COMMAND(port, TxEnable, 0);
+
+	if (ether->mem)
+		/* This must be a cardbus card.  Acknowledge the interrupt */
+		intrack3c575(KADDR(ether->mem));
+		
+	/*
+	 * Prime the busmaster channel for receiving directly into a
+	 * receive packet buffer if necessary.
+	 */
+	if(ctlr->busmaster == 1)
+		startdma(ether, PADDR(ctlr->rbp->rp));
+	else{
+		if(ctlr->upenabled)
+			outl(port+UpListPtr, PADDR(&ctlr->uphead->np));
+	}
+
+	ctlr->attached = 1;
+	iunlock(&ctlr->wlock);
+
+}
+
+static void
+statistics(Ether* ether)
+{
+	int port, i, u, w;
+	Ctlr *ctlr;
+
+	port = ether->port;
+	ctlr = ether->ctlr;
+
+	/*
+	 * 3C59[27] require a read between a PIO write and
+	 * reading a statistics register.
+	 */
+	w = (STATUS(port)>>13) & 0x07;
+	COMMAND(port, SelectRegisterWindow, Wstatistics);
+	STATUS(port);
+
+	for(i = 0; i < UpperFramesOk; i++)
+		ctlr->stats[i] += inb(port+i) & 0xFF;
+	u = inb(port+UpperFramesOk) & 0xFF;
+	ctlr->stats[FramesXmittedOk] += (u & 0x30)<<4;
+	ctlr->stats[FramesRcvdOk] += (u & 0x03)<<8;
+	ctlr->stats[BytesRcvdOk] += ins(port+BytesRcvdOk) & 0xFFFF;
+	ctlr->stats[BytesRcvdOk+1] += ins(port+BytesXmittedOk) & 0xFFFF;
+
+	switch(ctlr->xcvr){
+
+	case xcvrMii:
+	case xcvr100BaseTX:
+	case xcvr100BaseFX:
+		COMMAND(port, SelectRegisterWindow, Wdiagnostic);
+		STATUS(port);
+		ctlr->stats[BytesRcvdOk+2] += inb(port+BadSSD);
+		break;
+	}
+
+	COMMAND(port, SelectRegisterWindow, w);
+}
+
+static void
+txstart(Ether* ether)
+{
+	int port, len;
+	Ctlr *ctlr;
+	RingBuf *tb;
+
+	port = ether->port;
+	ctlr = ether->ctlr;
+
+	/*
+	 * Attempt to top-up the transmit FIFO. If there's room simply
+	 * stuff in the packet length (unpadded to a dword boundary), the
+	 * packet data (padded) and remove the packet from the queue.
+	 * If there's no room post an interrupt for when there is.
+	 * This routine is called both from the top level and from interrupt
+	 * level and expects to be called with ctlr->wlock already locked
+	 * and the correct register window (Wop) in place.
+	 */
+	for(tb = &ether->tb[ether->ti]; tb->owner == Interface; tb = &ether->tb[ether->ti]){
+		len = ROUNDUP(tb->len, 4);
+		if(len+4 <= ins(port+TxFree)){
+			outl(port+Fifo, tb->len);
+			outsl(port+Fifo, tb->pkt, len/4);
+			tb->owner = Host;
+			ether->ti = NEXT(ether->ti, ether->ntb);
+		}
+		else{
+			if(ctlr->txbusy == 0){
+				ctlr->txbusy = 1;
+				COMMAND(port, SetTxAvailableThresh, len>>ctlr->ts);
+			}
+			break;
+		}
+	}
+}
+
+static void
+txstart905(Ether* ether)
+{
+	Ctlr *ctlr;
+	int port, stalled, timeo;
+	RingBuf *tb;
+	Pd *pd;
+
+	ctlr = ether->ctlr;
+	port = ether->port;
+
+	/*
+	 * Free any completed packets.
+	 */
+	pd = ctlr->dntail;
+	while(ctlr->dnq){
+		if(PADDR(&pd->np) == inl(port+DnListPtr))
+			break;
+		ctlr->dnq--;
+		pd = pd->next;
+	}
+	ctlr->dntail = pd;
+
+	stalled = 0;
+	while(ctlr->dnq < (ctlr->ndn-1)){
+		tb = &ether->tb[ether->ti];
+		if(tb->owner != Interface)
+			break;
+
+		pd = ctlr->dnhead->next;
+		pd->np = 0;
+		pd->control = dnIndicate|tb->len;
+		memmove(pd->vaddr, tb->pkt, tb->len);
+		pd->len = updnLastFrag|tb->len;
+
+		tb->owner = Host;
+		ether->ti = NEXT(ether->ti, ether->ntb);
+
+		if(stalled == 0 && ctlr->dnq && inl(port+DnListPtr)){
+			COMMAND(port, Stall, dnStall);
+			for(timeo = 100; (STATUS(port) & commandInProgress) && timeo; timeo--)
+				;
+			if(timeo == 0)
+				print("#l%d: dnstall %d\n", ether->ctlrno, timeo);
+			stalled = 1;
+		}
+
+		coherence();
+		ctlr->dnhead->np = PADDR(&pd->np);
+		ctlr->dnhead->control &= ~dnIndicate;
+		ctlr->dnhead = pd;
+		if(ctlr->dnq == 0)
+			ctlr->dntail = pd;
+		ctlr->dnq++;
+
+		ctlr->dnqueued++;
+	}
+
+	if(ctlr->dnq > ctlr->dnqmax)
+		ctlr->dnqmax = ctlr->dnq;
+
+	/*
+	 * If the adapter is not currently processing anything
+	 * and there is something on the queue, start it processing.
+	 */
+	if(inl(port+DnListPtr) == 0 && ctlr->dnq)
+		outl(port+DnListPtr, PADDR(&ctlr->dnhead->np));
+	if(stalled)
+		COMMAND(port, Stall, dnUnStall);
+}
+
+static void
+transmit(Ether* ether)
+{
+	Ctlr *ctlr;
+	int port, w;
+
+	port = ether->port;
+	ctlr = ether->ctlr;
+
+	ilock(&ctlr->wlock);
+	if(ctlr->dnenabled)
+		txstart905(ether);
+	else{
+		w = (STATUS(port)>>13) & 0x07;
+		COMMAND(port, SelectRegisterWindow, Wop);
+		txstart(ether);
+		COMMAND(port, SelectRegisterWindow, w);
+	}
+	iunlock(&ctlr->wlock);
+}
+
+static void
+receive905(Ether* ether)
+{
+	Ctlr *ctlr;
+	int len, port, q;
+	Pd *pd;
+	RingBuf *rb;
+
+	ctlr = ether->ctlr;
+	port = ether->port;
+
+	if(inl(port+UpPktStatus) & upStalled)
+		ctlr->upstalls++;
+	q = 0;
+	for(pd = ctlr->uphead; pd->control & upPktComplete; pd = pd->next){
+		if(!(pd->control & upError)){
+			rb = &ether->rb[ether->ri];
+			if (rb->owner == Interface) {
+				len = pd->control & rxBytes;
+				rb->len = len;
+				memmove(rb->pkt, pd->vaddr, len);
+				rb->owner = Host;
+				ether->ri = NEXT(ether->ri, ether->nrb);
+			}
+		}
+
+		pd->control = 0;
+		COMMAND(port, Stall, upUnStall);
+
+		q++;
+	}
+	ctlr->uphead = pd;
+
+	ctlr->upqueued += q;
+	if(q > ctlr->upqmax)
+		ctlr->upqmax = q;
+}
+
+static void
+receive(Ether* ether)
+{
+	int len, port, rxstatus;
+	RingBuf *rb;
+	Ctlr *ctlr;
+
+	port = ether->port;
+	ctlr = ether->ctlr;
+
+	while(((rxstatus = ins(port+RxStatus)) & rxIncomplete) == 0){
+		if(ctlr->busmaster == 1 && (STATUS(port) & busMasterInProgress))
+			break;
+
+		/*
+		 * If there was an error, log it and continue.
+		 * Unfortunately the 3C5[078]9 has the error info in the status register
+		 * and the 3C59[0257] implement a separate RxError register.
+		 */
+		if((rxstatus & rxError) == 0){
+			/*
+			 * Packet received. Read it into the next free
+			 * ring buffer, if any. Must read len bytes padded
+			 * to a doubleword, can be picked out 32-bits at
+			 * a time. The CRC is already stripped off.
+			 */
+			rb = &ether->rb[ether->ri];
+			if(rb->owner == Interface){
+				len = (rxstatus & rxBytes9);
+				rb->len = len;
+				insl(port+Fifo, rb->pkt, HOWMANY(len, 4));
+
+				rb->owner = Host;
+				ether->ri = NEXT(ether->ri, ether->nrb);
+			}else
+if(debug) print("toss...");
+		}
+else
+if(debug) print("error...");
+
+		/*
+		 * All done, discard the packet.
+		 */
+		COMMAND(port, RxDiscard, 0);
+		while(STATUS(port) & commandInProgress)
+			;
+	}
+}
+
+static void
+interrupt(Ureg*, void* arg)
+{
+	Ether *ether;
+	int port, status, s, txstatus, w, x;
+	Ctlr *ctlr;
+
+	ether = arg;
+	port = ether->port;
+	ctlr = ether->ctlr;
+
+	ilock(&ctlr->wlock);
+	status = STATUS(port);
+	if(!(status & (interruptMask|interruptLatch))){
+		iunlock(&ctlr->wlock);
+		return;
+	}
+	w = (status>>13) & 0x07;
+	COMMAND(port, SelectRegisterWindow, Wop);
+
+	ctlr->interrupts++;
+	if(ctlr->busmaster == 2)
+		ctlr->timer[0] += inb(port+Timer905) & 0xFF;
+	else
+		ctlr->timer[0] += inb(port+Timer) & 0xFF;
+
+	do{
+		if(status & hostError){
+			/*
+			 * Adapter failure, try to find out why, reset if
+			 * necessary. What happens if Tx is active and a reset
+			 * occurs, need to retransmit? This probably isn't right.
+			 */
+			COMMAND(port, SelectRegisterWindow, Wdiagnostic);
+			x = ins(port+FifoDiagnostic);
+			COMMAND(port, SelectRegisterWindow, Wop);
+			print("#l%d: status 0x%uX, diag 0x%uX\n",
+			    ether->ctlrno, status, x);
+
+			if(x & txOverrun){
+				if(ctlr->busmaster == 0)
+					COMMAND(port, TxReset, 0);
+				else
+					COMMAND(port, TxReset, (updnReset|dmaReset));
+				COMMAND(port, TxEnable, 0);
+			}
+
+			if(x & rxUnderrun){
+				/*
+				 * This shouldn't happen...
+				 * Reset the receiver and restore the filter and RxEarly
+				 * threshold before re-enabling.
+				 * Need to restart any busmastering?
+				 */
+				COMMAND(port, SelectRegisterWindow, Wstate);
+				s = (port+RxFilter) & 0x000F;
+				COMMAND(port, SelectRegisterWindow, Wop);
+				COMMAND(port, RxReset, 0);
+				while(STATUS(port) & commandInProgress)
+					;
+				COMMAND(port, SetRxFilter, s);
+				COMMAND(port, SetRxEarlyThresh, ctlr->rxearly>>ctlr->ts);
+				COMMAND(port, RxEnable, 0);
+			}
+
+			status &= ~hostError;
+		}
+
+		if(status & (transferInt|rxComplete)){
+			receive(ether);
+			status &= ~(transferInt|rxComplete);
+		}
+
+		if(status & (upComplete)){
+			COMMAND(port, AcknowledgeInterrupt, upComplete);
+			receive905(ether);
+			status &= ~upComplete;
+			ctlr->upinterrupts++;
+		}
+
+		if(status & txComplete){
+			/*
+			 * Pop the TxStatus stack, accumulating errors.
+			 * Adjust the TX start threshold if there was an underrun.
+			 * If there was a Jabber or Underrun error, reset
+			 * the transmitter, taking care not to reset the dma logic
+			 * as a busmaster receive may be in progress.
+			 * For all conditions enable the transmitter.
+			 */
+			if(ctlr->busmaster == 2)
+				txstatus = port+TxStatus905;
+			else
+				txstatus = port+TxStatus;
+			s = 0;
+			do{
+				if(x = inb(txstatus))
+					outb(txstatus, 0);
+				s |= x;
+			}while(STATUS(port) & txComplete);
+
+			if(s & txUnderrun){
+				if(ctlr->dnenabled){
+					while(inl(port+PktStatus) & dnInProg)
+						;
+				}
+				COMMAND(port, SelectRegisterWindow, Wdiagnostic);
+				while(ins(port+MediaStatus) & txInProg)
+					;
+				COMMAND(port, SelectRegisterWindow, Wop);
+				if(ctlr->txthreshold < ETHERMAXTU)
+					ctlr->txthreshold += ETHERMINTU;
+			}
+
+			/*
+			 * According to the manual, maxCollisions does not require
+			 * a TxReset, merely a TxEnable. However, evidence points to
+			 * it being necessary on the 3C905. The jury is still out.
+			 * On busy or badly configured networks maxCollisions can
+			 * happen frequently enough for messages to be annoying so
+			 * keep quiet about them by popular request.
+			 */
+			if(s & (txJabber|txUnderrun|maxCollisions)){
+				if(ctlr->busmaster == 0)
+					COMMAND(port, TxReset, 0);
+				else
+					COMMAND(port, TxReset, (updnReset|dmaReset));
+				while(STATUS(port) & commandInProgress)
+					;
+				COMMAND(port, SetTxStartThresh, ctlr->txthreshold>>ctlr->ts);
+				if(ctlr->busmaster == 2)
+					outl(port+TxFreeThresh, HOWMANY(ETHERMAXTU, 256));
+				if(ctlr->dnenabled)
+					status |= dnComplete;
+			}
+
+			if(s & ~(txStatusComplete|maxCollisions))
+				print("#l%d: txstatus 0x%uX, threshold %d\n",
+			    		ether->ctlrno, s, ctlr->txthreshold);
+			COMMAND(port, TxEnable, 0);
+			status &= ~txComplete;
+			status |= txAvailable;
+		}
+
+		if(status & txAvailable){
+			COMMAND(port, AcknowledgeInterrupt, txAvailable);
+			ctlr->txbusy = 0;
+			txstart(ether);
+			status &= ~txAvailable;
+		}
+
+		if(status & dnComplete){
+			COMMAND(port, AcknowledgeInterrupt, dnComplete);
+			txstart905(ether);
+			status &= ~dnComplete;
+			ctlr->dninterrupts++;
+		}
+
+		if(status & updateStats){
+			statistics(ether);
+			status &= ~updateStats;
+		}
+
+		/*
+		 * Currently, this shouldn't happen.
+		 */
+		if(status & rxEarly){
+			COMMAND(port, AcknowledgeInterrupt, rxEarly);
+			status &= ~rxEarly;
+		}
+
+		/*
+		 * Panic if there are any interrupts not dealt with.
+		 */
+		if(status & interruptMask)
+			panic("#l%d: interrupt mask 0x%uX\n", ether->ctlrno, status);
+
+		COMMAND(port, AcknowledgeInterrupt, interruptLatch);
+		if (ether->mem) 
+			intrack3c575((ulong *)KADDR(ether->mem));
+
+	}while((status = STATUS(port)) & (interruptMask|interruptLatch));
+
+	if(ctlr->busmaster == 2)
+		ctlr->timer[1] += inb(port+Timer905) & 0xFF;
+	else
+		ctlr->timer[1] += inb(port+Timer) & 0xFF;
+
+	COMMAND(port, SelectRegisterWindow, w);
+	iunlock(&ctlr->wlock);
+}
+
+static void
+txrxreset(int port)
+{
+	COMMAND(port, TxReset, 0);
+	while(STATUS(port) & commandInProgress)
+		;
+	COMMAND(port, RxReset, 0);
+	while(STATUS(port) & commandInProgress)
+		;
+}
+
+typedef struct Adapter {
+	int		port;
+	int		irq;
+	int		tbdf;
+	ulong	cbfns;
+} Adapter;
+static Block* adapter;
+
+static void
+tcmadapter(int port, int irq, int tbdf, ulong cbfns)
+{
+	Block *bp;
+	Adapter *ap;
+
+	bp = allocb(sizeof(Adapter));
+	ap = (Adapter*)bp->rp;
+	ap->port = port;
+	ap->irq = irq;
+	ap->tbdf = tbdf;
+	ap->cbfns = cbfns;
+
+	bp->next = adapter;
+	adapter = bp;
+}
+
+/*
+ * Write two 0 bytes to identify the IDport and then reset the
+ * ID sequence. Then send the ID sequence to the card to get
+ * the card into command state.
+ */
+static void
+idseq(void)
+{
+	int i;
+	uchar al;
+	static int reset, untag;
+
+	/*
+	 * One time only:
+	 *	reset any adapters listening
+	 */
+	if(reset == 0){
+		outb(IDport, 0);
+		outb(IDport, 0);
+		outb(IDport, 0xC0);
+		delay(20);
+		reset = 1;
+	}
+
+	outb(IDport, 0);
+	outb(IDport, 0);
+	for(al = 0xFF, i = 0; i < 255; i++){
+		outb(IDport, al);
+		if(al & 0x80){
+			al <<= 1;
+			al ^= 0xCF;
+		}
+		else
+			al <<= 1;
+	}
+
+	/*
+	 * One time only:
+	 *	write ID sequence to get the attention of all adapters;
+	 *	untag all adapters.
+	 * If a global reset is done here on all adapters it will confuse
+	 * any ISA cards configured for EISA mode.
+	 */
+	if(untag == 0){
+		outb(IDport, 0xD0);
+		untag = 1;
+	}
+}
+
+static ulong
+activate(void)
+{
+	int i;
+	ushort x, acr;
+
+	/*
+	 * Do the little configuration dance:
+	 *
+	 * 2. write the ID sequence to get to command state.
+	 */
+	idseq();
+
+	/*
+	 * 3. Read the Manufacturer ID from the EEPROM.
+	 *    This is done by writing the IDPort with 0x87 (0x80
+	 *    is the 'read EEPROM' command, 0x07 is the offset of
+	 *    the Manufacturer ID field in the EEPROM).
+	 *    The data comes back 1 bit at a time.
+	 *    A delay seems necessary between reading the bits.
+	 *
+	 * If the ID doesn't match, there are no more adapters.
+	 */
+	outb(IDport, 0x87);
+	delay(20);
+	for(x = 0, i = 0; i < 16; i++){
+		delay(20);
+		x <<= 1;
+		x |= inb(IDport) & 0x01;
+	}
+	if(x != 0x6D50)
+		return 0;
+
+	/*
+	 * 3. Read the Address Configuration from the EEPROM.
+	 *    The Address Configuration field is at offset 0x08 in the EEPROM).
+	 */
+	outb(IDport, 0x88);
+	for(acr = 0, i = 0; i < 16; i++){
+		delay(20);
+		acr <<= 1;
+		acr |= inb(IDport) & 0x01;
+	}
+
+	return (acr & 0x1F)*0x10 + 0x200;
+}
+
+static void
+tcm509isa(void)
+{
+	int irq, port;
+
+	/*
+	 * Attempt to activate all adapters. If adapter is set for
+	 * EISA mode (0x3F0), tag it and ignore. Otherwise, activate
+	 * it fully.
+	 */
+	while(port = activate()){
+		/*
+		 * 6. Tag the adapter so it won't respond in future.
+		 */
+		outb(IDport, 0xD1);
+		if(port == 0x3F0)
+			continue;
+
+		/*
+		 * 6. Activate the adapter by writing the Activate command
+		 *    (0xFF).
+		 */
+		outb(IDport, 0xFF);
+		delay(20);
+
+		/*
+		 * 8. Can now talk to the adapter's I/O base addresses.
+		 *    Use the I/O base address from the acr just read.
+		 *
+		 *    Enable the adapter and clear out any lingering status
+		 *    and interrupts.
+		 */
+		while(STATUS(port) & commandInProgress)
+			;
+		COMMAND(port, SelectRegisterWindow, Wsetup);
+		outs(port+ConfigControl, Ena);
+
+		txrxreset(port);
+		COMMAND(port, AcknowledgeInterrupt, 0xFF);
+
+		irq = (ins(port+ResourceConfig)>>12) & 0x0F;
+		tcmadapter(port, irq, BUSUNKNOWN, 0);
+	}
+}
+
+static void
+tcm5XXeisa(void)
+{
+	ushort x;
+	int irq, port, slot;
+
+	/*
+	 * Check if this is an EISA machine.
+	 * If not, nothing to do.
+	 */
+	if(strncmp((char*)KADDR(0xFFFD9), "EISA", 4))
+		return;
+
+	/*
+	 * Continue through the EISA slots looking for a match on both
+	 * 3COM as the manufacturer and 3C579-* or 3C59[27]-* as the product.
+	 * If an adapter is found, select window 0, enable it and clear
+	 * out any lingering status and interrupts.
+	 */
+	for(slot = 1; slot < MaxEISA; slot++){
+		port = slot*0x1000;
+		if(ins(port+0xC80+ManufacturerID) != 0x6D50)
+			continue;
+		x = ins(port+0xC80+ProductID);
+		if((x & 0xF0FF) != 0x9050 && (x & 0xFF00) != 0x5900)
+			continue;
+
+		COMMAND(port, SelectRegisterWindow, Wsetup);
+		outs(port+ConfigControl, Ena);
+
+		txrxreset(port);
+		COMMAND(port, AcknowledgeInterrupt, 0xFF);
+
+		irq = (ins(port+ResourceConfig)>>12) & 0x0F;
+		tcmadapter(port, irq, BUSUNKNOWN, 0);
+	}
+}
+
+static void
+tcm59Xpci(Ether *ether)
+{
+	Pcidev *p;
+	int irq, port;
+	ulong bar;
+
+	p = nil;
+	while(p = pcimatch(p, 0x10B7, 0)){
+		if (p->did == 0x5157) {
+			EepromReadRegister = _EepromRead8bRegister;
+			
+			/* Map the CardBus functions */
+			bar = pcicfgr32(p, PciBAR2);
+			print("ether#%d: CardBus functions at %.8luX\n", ether->ctlrno, bar & ~KZERO);
+		}
+		else
+			bar = 0;
+
+		/*
+		 * Not prepared to deal with memory-mapped
+		 * devices yet.
+		 */
+		if(!(p->mem[0].bar & 0x01))
+			continue;
+		port = p->mem[0].bar & ~0x01;
+		irq = p->intl;
+		COMMAND(port, GlobalReset, 0);
+		while(STATUS(port) & commandInProgress)
+			;
+
+		tcmadapter(port, irq, p->tbdf, bar);
+		pcisetbme(p);
+	}
+}
+
+static char* tcmpcmcia[] = {
+	"3C589",			/* 3COM 589[ABCD] */
+	"3C562",			/* 3COM 562 */
+	"589E",				/* 3COM Megahertz 589E */
+	nil,
+};
+
+static int
+tcm5XXpcmcia(Ether* ether)
+{
+	int i;
+
+	for(i = 0; tcmpcmcia[i] != nil; i++){
+		if(!cistrcmp(ether->type, tcmpcmcia[i])){
+			/*
+			 * No need for an ioalloc here, the 589 reset
+			 * code deals with it.
+			if(ioalloc(ether->port, 0x10, 0, "tcm5XXpcmcia") < 0)
+				return 0;
+			 */
+			return ether->port;
+		}
+	}
+
+	return 0;
+}
+
+static void
+setxcvr(int port, int xcvr, int is9)
+{
+	int x;
+
+	if(is9){
+		COMMAND(port, SelectRegisterWindow, Wsetup);
+		x = ins(port+AddressConfig) & ~xcvrMask9;
+		x |= (xcvr>>20)<<14;
+		outs(port+AddressConfig, x);
+	}
+	else{
+		COMMAND(port, SelectRegisterWindow, Wfifo);
+		x = inl(port+InternalConfig) & ~xcvrMask;
+		x |= xcvr;
+		outl(port+InternalConfig, x);
+	}
+
+	txrxreset(port);
+}
+
+static void
+setfullduplex(int port)
+{
+	int x;
+
+	COMMAND(port, SelectRegisterWindow, Wfifo);
+	x = ins(port+MacControl);
+	outs(port+MacControl, fullDuplexEnable|x);
+
+	txrxreset(port);
+}
+
+static int
+miimdi(int port, int n)
+{
+	int data, i;
+
+	/*
+	 * Read n bits from the MII Management Register.
+	 */
+	data = 0;
+	for(i = n-1; i >= 0; i--){
+		if(ins(port) & mgmtData)
+			data |= (1<<i);
+		microdelay(1);
+		outs(port, mgmtClk);
+		microdelay(1);
+		outs(port, 0);
+		microdelay(1);
+	}
+
+	return data;
+}
+
+static void
+miimdo(int port, int bits, int n)
+{
+	int i, mdo;
+
+	/*
+	 * Write n bits to the MII Management Register.
+	 */
+	for(i = n-1; i >= 0; i--){
+		if(bits & (1<<i))
+			mdo = mgmtDir|mgmtData;
+		else
+			mdo = mgmtDir;
+		outs(port, mdo);
+		microdelay(1);
+		outs(port, mdo|mgmtClk);
+		microdelay(1);
+		outs(port, mdo);
+		microdelay(1);
+	}
+}
+
+static int
+miir(int port, int phyad, int regad)
+{
+	int data, w;
+
+	w = (STATUS(port)>>13) & 0x07;
+	COMMAND(port, SelectRegisterWindow, Wdiagnostic);
+	port += PhysicalMgmt;
+
+	/*
+	 * Preamble;
+	 * ST+OP+PHYAD+REGAD;
+	 * TA + 16 data bits.
+	 */
+	miimdo(port, 0xFFFFFFFF, 32);
+	miimdo(port, 0x1800|(phyad<<5)|regad, 14);
+	data = miimdi(port, 18);
+
+	port -= PhysicalMgmt;
+	COMMAND(port, SelectRegisterWindow, w);
+
+	if(data & 0x10000)
+		return -1;
+
+	return data & 0xFFFF;
+}
+
+static void
+scanphy(int port)
+{
+	int i, x;
+
+	for(i = 0; i < 32; i++){
+		if((x = miir(port, i, 2)) == -1 || x == 0)
+			continue;
+		x <<= 6;
+		x |= miir(port, i, 3)>>10;
+		XCVRDEBUG("phy%d: oui %uX reg1 %uX\n", i, x, miir(port, i, 1));
+		USED(x);
+	}
+}
+
+#ifdef notdef
+static struct xxx {
+	int	available;
+	int	next;
+} xxx[8] = {
+	{ base10TAvailable,	1, },		/* xcvr10BaseT	-> xcvrAui */
+	{ auiAvailable,		3, },		/* xcvrAui	-> xcvr10Base2 */
+	{ 0, -1, },
+	{ coaxAvailable,	-1, },		/* xcvr10Base2	-> nowhere */
+	{ baseTXAvailable,	5, },		/* xcvr100BaseTX-> xcvr100BaseFX */
+	{ baseFXAvailable,	-1, },		/* xcvr100BaseFX-> nowhere */
+	{ miiConnector,		-1, },		/* xcvrMii	-> nowhere */
+	{ 0, -1, },
+};
+#endif /* notdef */
+
+static struct {
+	char *name;
+	int avail;
+	int xcvr;
+} media[] = {
+	"10BaseT",	base10TAvailable,	xcvr10BaseT,
+	"10Base2",	coaxAvailable,		xcvr10Base2,
+	"100BaseTX",	baseTXAvailable,	xcvr100BaseTX,
+	"100BaseFX",	baseFXAvailable,	xcvr100BaseFX,
+	"aui",		auiAvailable,		xcvrAui,
+	"mii",		miiConnector,		xcvrMii
+};
+
+static int
+autoselect(int port, int xcvr, int is9)
+{
+	int media, x;
+	USED(xcvr);
+
+	/*
+	 * Pathetic attempt at automatic media selection.
+	 * Really just to get the Fast Etherlink 10BASE-T/100BASE-TX
+	 * cards operational.
+	 * It's a bonus if it works for anything else.
+	 */
+	if(is9){
+		COMMAND(port, SelectRegisterWindow, Wsetup);
+		x = ins(port+ConfigControl);
+		media = 0;
+		if(x & base10TAvailable9)
+			media |= base10TAvailable;
+		if(x & coaxAvailable9)
+			media |= coaxAvailable;
+		if(x & auiAvailable9)
+			media |= auiAvailable;
+	}
+	else{
+		COMMAND(port, SelectRegisterWindow, Wfifo);
+		media = ins(port+ResetOptions);
+	}
+	XCVRDEBUG("autoselect: media %uX\n", media);
+
+	if(media & miiConnector)
+		return xcvrMii;
+
+	COMMAND(port, SelectRegisterWindow, Wdiagnostic);
+	XCVRDEBUG("autoselect: media status %uX\n", ins(port+MediaStatus));
+
+	if(media & baseTXAvailable){
+		/*
+		 * Must have InternalConfig register.
+		 */
+		setxcvr(port, xcvr100BaseTX, is9);
+
+		COMMAND(port, SelectRegisterWindow, Wdiagnostic);
+		x = ins(port+MediaStatus) & ~(dcConverterEnabled|jabberGuardEnable);
+		outs(port+MediaStatus, linkBeatEnable|x);
+		delay(10);
+
+		if(ins(port+MediaStatus) & linkBeatDetect)
+			return xcvr100BaseTX;
+		outs(port+MediaStatus, x);
+	}
+
+	if(media & base10TAvailable){
+		setxcvr(port, xcvr10BaseT, is9);
+
+		COMMAND(port, SelectRegisterWindow, Wdiagnostic);
+		x = ins(port+MediaStatus) & ~dcConverterEnabled;
+		outs(port+MediaStatus, linkBeatEnable|jabberGuardEnable|x);
+		delay(100);
+
+		XCVRDEBUG("autoselect: 10BaseT media status %uX\n", ins(port+MediaStatus));
+		if(ins(port+MediaStatus) & linkBeatDetect)
+			return xcvr10BaseT;
+		outs(port+MediaStatus, x);
+	}
+
+	/*
+	 * Botch.
+	 */
+	return autoSelect;
+}
+
+static int
+eepromdata(int port, int offset)
+{
+	COMMAND(port, SelectRegisterWindow, Wsetup);
+	while(EEPROMBUSY(port))
+		;
+	EEPROMCMD(port, EepromReadRegister, offset);
+	while(EEPROMBUSY(port))
+		;
+	return EEPROMDATA(port);
+}
+
+int
+elnk3reset(Ether* ether)
+{
+	int anar, anlpar, phyaddr, phystat, timeo, xcvr;
+	int busmaster, did, i, j, port, rxearly, rxstatus9, x;
+	Block *bp, **bpp;
+	Adapter *ap;
+	uchar ea[Eaddrlen];
+	Ctlr *ctlr;
+	static int scandone;
+	char *p;
+
+	/*
+	 * Scan for adapter on PCI, EISA and finally
+	 * using the little ISA configuration dance.
+	 */
+	if(scandone == 0){
+		tcm59Xpci(ether);
+		tcm5XXeisa();
+		tcm509isa();
+		scandone = 1;
+	}
+
+	/*
+	 * Any adapter matches if no ether->port is supplied,
+	 * otherwise the ports must match.
+	 */
+	port = 0;
+	bpp = &adapter;
+	for(bp = *bpp; bp; bp = bp->next){
+		ap = (Adapter*)bp->rp;
+		if(ether->port == 0 || ether->port == ap->port){
+			port = ap->port;
+			ether->irq = ap->irq;
+			ether->tbdf = ap->tbdf;
+			ether->mem = ap->cbfns;	/* Misuse the mem ref for the cardbus functions */
+			*bpp = bp->next;
+			freeb(bp);
+			break;
+		}
+		bpp = &bp->next;
+	}
+	if(port == 0 && (port = tcm5XXpcmcia(ether)) == 0)
+		return -1;
+
+	/*
+	 * Read the DeviceID from the EEPROM, it's at offset 0x03,
+	 * and do something depending on capabilities.
+	 */
+	switch(did = eepromdata(port, 0x03)){
+
+	case 0x5157:		/* 3C575 Cyclone */
+	case 0x4500:		/* 3C450 HomePNA Tornado */
+	case 0x6056:
+	case 0x7646:		/* 3CSOHO100-TX */
+	case 0x9055:		/* 3C905B-TX */
+	case 0x9200:		/* 3C905C-TX */
+		/*FALLTHROUGH*/
+	case 0x9000:		/* 3C900-TPO */
+	case 0x9001:		/* 3C900-COMBO */
+	case 0x9005:		/* 3C900B-COMBO */
+	case 0x9050:		/* 3C905-TX */
+	case 0x9051:		/* 3C905-T4 */
+		if(BUSTYPE(ether->tbdf) != BusPCI)
+			goto buggery;
+		busmaster = 2;
+		goto vortex;
+
+	case 0x5900:		/* 3C590-[TP|COMBO|TPO] */
+	case 0x5920:		/* 3C592-[TP|COMBO|TPO] */
+	case 0x5950:		/* 3C595-TX */
+	case 0x5951:		/* 3C595-T4 */
+	case 0x5952:		/* 3C595-MII */
+	case 0x5970:		/* 3C597-TX */
+	case 0x5971:		/* 3C597-T4 */
+	case 0x5972:		/* 3C597-MII */
+		busmaster = 1;
+	vortex:
+		COMMAND(port, SelectRegisterWindow, Wfifo);
+		xcvr = inl(port+InternalConfig) & (autoSelect|xcvrMask);
+		rxearly = 8188;
+		rxstatus9 = 0;
+		break;
+
+	buggery:
+	default:
+		busmaster = 0;
+		COMMAND(port, SelectRegisterWindow, Wsetup);
+		x = ins(port+AddressConfig);
+		xcvr = ((x & xcvrMask9)>>14)<<20;
+		if(x & autoSelect9)
+			xcvr |= autoSelect;
+		rxearly = 2044;
+		rxstatus9 = 1;
+		break;
+	}
+
+	/*
+	 * Check if the adapter's station address is to be overridden.
+	 * If not, read it from the EEPROM and set in ether->ea prior to
+	 * loading the station address in Wstation.
+	 * The EEPROM returns 16-bits at a time.
+	 */
+	memset(ea, 0, Eaddrlen);
+	if(memcmp(ea, ether->ea, Eaddrlen) == 0){
+		for(i = 0; i < Eaddrlen/2; i++){
+			x = eepromdata(port, i);
+			ether->ea[2*i] = x>>8;
+			ether->ea[2*i+1] = x;
+		}
+	}
+
+	COMMAND(port, SelectRegisterWindow, Wstation);
+	for(i = 0; i < Eaddrlen; i++)
+		outb(port+i, ether->ea[i]);
+
+	/*
+	 * Enable the transceiver if necessary and determine whether
+	 * busmastering can be used. Due to bugs in the first revision
+	 * of the 3C59[05], don't use busmastering at 10Mbps.
+	 */
+	XCVRDEBUG("reset: xcvr %uX\n", xcvr);
+
+	/*
+	 * Allow user to specify desired media in plan9.ini
+	 */
+	for(i = 0; i < ether->nopt; i++){
+		if(cistrncmp(ether->opt[i], "media=", 6) != 0)
+			continue;
+		p = ether->opt[i]+6;
+		for(j = 0; j < nelem(media); j++)
+			if(cistrcmp(p, media[j].name) == 0)
+				xcvr = media[j].xcvr;
+	}
+	
+	/*
+	 * forgive me, but i am weak
+	 */
+	switch(did){
+	default:
+		if(xcvr & autoSelect)
+			xcvr = autoselect(port, xcvr, rxstatus9);
+		break;
+	case 0x4500:
+	case 0x5157:
+	case 0x6056:
+	case 0x7646:
+	case 0x9055:
+	case 0x9200:
+		xcvr = xcvrMii;
+		txrxreset(port);
+		XCVRDEBUG("905[BC] reset ops 0x%uX\n", ins(port+ResetOp905B));
+
+		if (did == 0x5157) {
+			ushort reset_opts;
+
+			COMMAND(port, SelectRegisterWindow, Wstation);
+			reset_opts = ins(port + ResetOp905B);
+			reset_opts |= 0x0010;		/* Invert LED */
+			outs(port + ResetOp905B, reset_opts);
+		}
+		break;
+	}
+	XCVRDEBUG("autoselect returns: xcvr %uX, did 0x%uX\n", xcvr, did);
+
+	switch(xcvr){
+
+	case xcvrMii:
+		/*
+		 * Quick hack.
+		scanphy(port);
+		 */
+		phyaddr = (did == 0x5157)? 0: 24;
+		for(i = 0; i < 7; i++)
+			XCVRDEBUG(" %2.2uX", miir(port, phyaddr, i));
+			XCVRDEBUG("\n");
+
+		for(timeo = 0; timeo < 30; timeo++){
+			phystat = miir(port, phyaddr, 0x01);
+			if(phystat & 0x20)
+				break;
+			XCVRDEBUG(" %2.2uX", phystat);
+			delay(100);
+		}
+		XCVRDEBUG(" %2.2uX", miir(port, phyaddr, 0x01));
+		XCVRDEBUG("\n");
+
+		anar = miir(port, phyaddr, 0x04);
+		anlpar = miir(port, phyaddr, 0x05) & 0x03E0;
+		anar &= anlpar;
+		miir(port, phyaddr, 0x00);
+		XCVRDEBUG("mii an: %uX anlp: %uX r0:%uX r1:%uX\n",
+			anar, anlpar, miir(port, phyaddr, 0x00),
+			miir(port, phyaddr, 0x01));
+		for(i = 0; i < ether->nopt; i++){
+			if(cistrcmp(ether->opt[i], "fullduplex") == 0)
+				anar |= 0x0100;
+			else if(cistrcmp(ether->opt[i], "100BASE-TXFD") == 0)
+				anar |= 0x0100;
+			else if(cistrcmp(ether->opt[i], "force100") == 0)
+				anar |= 0x0080;
+		}
+		XCVRDEBUG("mii anar: %uX\n", anar);
+		if(anar & 0x0100){		/* 100BASE-TXFD */
+			setfullduplex(port);
+		}
+		else if(anar & 0x0200){		/* 100BASE-T4 */
+			/* nothing to do */
+		}
+		else if(anar & 0x0080){		/* 100BASE-TX */
+			/* nothing to do */;
+		}
+		else if(anar & 0x0040)		/* 10BASE-TFD */
+			setfullduplex(port);
+		else{				/* 10BASE-T */
+			/* nothing to do */;
+		}
+		break;
+
+	case xcvr100BaseTX:
+	case xcvr100BaseFX:
+		COMMAND(port, SelectRegisterWindow, Wfifo);
+		x = inl(port+InternalConfig) & ~ramPartitionMask;
+		outl(port+InternalConfig, x|ramPartition1to1);
+
+		COMMAND(port, SelectRegisterWindow, Wdiagnostic);
+		x = ins(port+MediaStatus) & ~(dcConverterEnabled|jabberGuardEnable);
+		x |= linkBeatEnable;
+		outs(port+MediaStatus, x);
+		break;
+
+	case xcvr10BaseT:
+		/*
+		 * Enable Link Beat and Jabber to start the
+		 * transceiver.
+		 */
+		COMMAND(port, SelectRegisterWindow, Wdiagnostic);
+		x = ins(port+MediaStatus) & ~dcConverterEnabled;
+		x |= linkBeatEnable|jabberGuardEnable;
+		outs(port+MediaStatus, x);
+
+		if((did & 0xFF00) == 0x5900)
+			busmaster = 0;
+		break;
+
+	case xcvr10Base2:
+		COMMAND(port, SelectRegisterWindow, Wdiagnostic);
+		x = ins(port+MediaStatus) & ~(linkBeatEnable|jabberGuardEnable);
+		outs(port+MediaStatus, x);
+
+		/*
+		 * Start the DC-DC converter.
+		 * Wait > 800 microseconds.
+		 */
+		COMMAND(port, EnableDcConverter, 0);
+		delay(1);
+		break;
+	}
+
+	/*
+	 * Wop is the normal operating register set.
+	 * The 3C59[0257] adapters allow access to more than one register window
+	 * at a time, but there are situations where switching still needs to be
+	 * done, so just do it.
+	 * Clear out any lingering Tx status.
+	 */
+	COMMAND(port, SelectRegisterWindow, Wop);
+	if(busmaster == 2)
+		x = port+TxStatus905;
+	else
+		x = port+TxStatus;
+	while(inb(x))
+		outb(x, 0);
+
+	/*
+	 * Allocate a controller structure, clear out the
+	 * adapter statistics, clear the statistics logged into ctlr
+	 * and enable statistics collection. Xcvr is needed in order
+	 * to collect the BadSSD statistics.
+	 */
+	ether->ctlr = malloc(sizeof(Ctlr));
+	ctlr = ether->ctlr;
+
+	ilock(&ctlr->wlock);
+	ctlr->xcvr = xcvr;
+	statistics(ether);
+	memset(ctlr->stats, 0, sizeof(ctlr->stats));
+
+	ctlr->busmaster = busmaster;
+	ctlr->xcvr = xcvr;
+	ctlr->rxstatus9 = rxstatus9;
+	ctlr->rxearly = rxearly;
+	if(rxearly >= 2048)
+		ctlr->ts = 2;
+
+	COMMAND(port, StatisticsEnable, 0);
+
+	/*
+	 * Allocate any receive buffers.
+	 */
+	if (ctlr->busmaster == 2) {
+		ctlr->dnenabled = 1;
+
+		/*
+		 * 10MUpldBug.
+		 * Disabling is too severe, can use receive busmastering at
+		 * 100Mbps OK, but how to tell which rate is actually being used -
+		 * the 3c905 always seems to have dataRate100 set?
+		 * Believe the bug doesn't apply if upRxEarlyEnable is set
+		 * and the threshold is set such that uploads won't start
+		 * until the whole packet has been received.
+		 */
+		ctlr->upenabled = 1;
+		x = eepromdata(port, 0x0F);
+		if(!(x & 0x01))
+			outl(port+PktStatus, upRxEarlyEnable);
+
+		ctlr->nup = Nup;
+		ctlr->ndn = Ndn;
+		init905(ctlr);
+		outl(port+TxFreeThresh, HOWMANY(ETHERMAXTU, 256));
+	}
+
+	/*
+	 * Set a base TxStartThresh which will be incremented
+	 * if any txUnderrun errors occur and ensure no RxEarly
+	 * interrupts happen.
+	 */
+	ctlr->txthreshold = ETHERMAXTU/2;
+	COMMAND(port, SetTxStartThresh, ctlr->txthreshold>>ctlr->ts);
+	COMMAND(port, SetRxEarlyThresh, rxearly>>ctlr->ts);
+
+	iunlock(&ctlr->wlock);
+
+	/*
+	 * Linkage to the generic ethernet driver.
+	 */
+	ether->port = port;
+	ether->attach = attach;
+	ether->transmit = transmit;
+	ether->interrupt = interrupt;
+
+	return 0;
+}
--- /dev/null
+++ b/os/boot.original/pc/etherelnk3x.c
@@ -1,0 +1,1074 @@
+/*
+ * Etherlink III and Fast EtherLink adapters.
+ * To do:
+ *	autoSelect;
+ *	busmaster channel;
+ *	PCMCIA;
+ *	PCI latency timer and master enable;
+ *	errata list.
+ *
+ * Product ID:
+ *	9150 ISA	3C509[B]
+ *	9050 ISA	3C509[B]-TP
+ *	9450 ISA	3C509[B]-COMBO
+ *	9550 ISA	3C509[B]-TPO
+ *
+ *	9350 EISA	3C579
+ *	9250 EISA	3C579-TP
+ *
+ *	5920 EISA	3C592-[TP|COMBO|TPO]
+ *	5970 EISA	3C597-TX	Fast Etherlink 10BASE-T/100BASE-TX
+ *	5971 EISA	3C597-T4	Fast Etherlink 10BASE-T/100BASE-T4
+ *	5972 EISA	3C597-MII	Fast Etherlink 10BASE-T/MII
+ *
+ *	5900 PCI	3C590-[TP|COMBO|TPO]
+ *	5950 PCI	3C595-TX	Fast Etherlink Shared 10BASE-T/100BASE-TX
+ *	5951 PCI	3C595-T4	Fast Etherlink Shared 10BASE-T/100BASE-T4
+ *	5952 PCI	3C595-MII	Fast Etherlink 10BASE-T/MII
+ *
+ *	9058 PCMCIA	3C589[B]-[TP|COMBO]
+ *
+ *	627C MCA	3C529
+ *	627D MCA	3C529-TP
+ */
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+#include "etherif.h"
+
+enum {
+	IDport			= 0x0110,	/* anywhere between 0x0100 and 0x01F0 */
+};
+
+enum {						/* all windows */
+	Command			= 0x000E,
+	IntStatus		= 0x000E,
+};
+
+enum {						/* Commands */
+	GlobalReset		= 0x0000,
+	SelectRegisterWindow	= 0x0001,	
+	EnableDcConverter	= 0x0002,
+	RxDisable		= 0x0003,
+	RxEnable		= 0x0004,
+	RxReset			= 0x0005,
+	TxDone			= 0x0007,	
+	RxDiscard		= 0x0008,
+	TxEnable		= 0x0009,
+	TxDisable		= 0x000A,
+	TxReset			= 0x000B,
+	RequestInterrupt	= 0x000C,
+	AcknowledgeInterrupt	= 0x000D,
+	SetInterruptEnable	= 0x000E,
+	SetIndicationEnable	= 0x000F,	/* SetReadZeroMask */
+	SetRxFilter		= 0x0010,
+	SetRxEarlyThresh	= 0x0011,
+	SetTxAvailableThresh	= 0x0012,
+	SetTxStartThresh	= 0x0013,
+	StartDma		= 0x0014,	/* initiate busmaster operation */
+	StatisticsEnable	= 0x0015,
+	StatisticsDisable	= 0x0016,
+	DisableDcConverter	= 0x0017,
+	SetTxReclaimThresh	= 0x0018,	/* PIO-only adapters */
+	PowerUp			= 0x001B,	/* not all adapters */
+	PowerDownFull		= 0x001C,	/* not all adapters */
+	PowerAuto		= 0x001D,	/* not all adapters */
+};
+
+enum {						/* (Global|Rx|Tx)Reset command bits */
+	tpAuiReset		= 0x0001,	/* 10BaseT and AUI transceivers */
+	endecReset		= 0x0002,	/* internal Ethernet encoder/decoder */
+	networkReset		= 0x0004,	/* network interface logic */
+	fifoReset		= 0x0008,	/* FIFO control logic */
+	aismReset		= 0x0010,	/* autoinitialise state-machine logic */
+	hostReset		= 0x0020,	/* bus interface logic */
+	dmaReset		= 0x0040,	/* bus master logic */
+	vcoReset		= 0x0080,	/* on-board 10Mbps VCO */
+
+	resetMask		= 0x00FF,
+};
+
+enum {						/* SetRxFilter command bits */
+	receiveIndividual	= 0x0001,	/* match station address */
+	receiveMulticast	= 0x0002,
+	receiveBroadcast	= 0x0004,
+	receiveAllFrames	= 0x0008,	/* promiscuous */
+};
+
+enum {						/* StartDma command bits */
+	Upload			= 0x0000,	/* transfer data from adapter to memory */
+	Download		= 0x0001,	/* transfer data from memory to adapter */
+};
+
+enum {						/* IntStatus bits */
+	interruptLatch		= 0x0001,
+	hostError		= 0x0002,	/* Adapter Failure */
+	txComplete		= 0x0004,
+	txAvailable		= 0x0008,
+	rxComplete		= 0x0010,
+	rxEarly			= 0x0020,
+	intRequested		= 0x0040,
+	updateStats		= 0x0080,
+	transferInt		= 0x0100,	/* Bus Master Transfer Complete */
+	busMasterInProgress	= 0x0800,
+	commandInProgress	= 0x1000,
+
+	interruptMask		= 0x01FE,
+};
+
+#define COMMAND(port, cmd, a)	outs((port)+Command, ((cmd)<<11)|(a))
+#define STATUS(port)		ins((port)+IntStatus)
+
+enum {						/* Window 0 - setup */
+	Wsetup			= 0x0000,
+						/* registers */
+	ManufacturerID		= 0x0000,	/* 3C5[08]*, 3C59[27] */
+	ProductID		= 0x0002,	/* 3C5[08]*, 3C59[27] */
+	ConfigControl		= 0x0004,	/* 3C5[08]*, 3C59[27] */
+	AddressConfig		= 0x0006,	/* 3C5[08]*, 3C59[27] */
+	ResourceConfig		= 0x0008,	/* 3C5[08]*, 3C59[27] */
+	EepromCommand		= 0x000A,
+	EepromData		= 0x000C,
+						/* AddressConfig Bits */
+	autoSelect9		= 0x0080,
+	xcvrMask9		= 0xC000,
+						/* ConfigControl bits */
+	Ena			= 0x0001,
+						/* EepromCommand bits */
+	EepromReadRegister	= 0x0080,
+	EepromBusy		= 0x8000,
+};
+
+#define EEPROMCMD(port, cmd, a)	outs((port)+EepromCommand, (cmd)|(a))
+#define EEPROMBUSY(port)	(ins((port)+EepromCommand) & EepromBusy)
+#define EEPROMDATA(port)	ins((port)+EepromData)
+
+enum {						/* Window 1 - operating set */
+	Wop			= 0x0001,
+						/* registers */
+	Fifo			= 0x0000,
+	RxError			= 0x0004,	/* 3C59[0257] only */
+	RxStatus		= 0x0008,
+	Timer			= 0x000A,
+	TxStatus		= 0x000B,
+	TxFree			= 0x000C,
+						/* RxError bits */
+	rxOverrun		= 0x0001,
+	runtFrame		= 0x0002,
+	alignmentError		= 0x0004,	/* Framing */
+	crcError		= 0x0008,
+	oversizedFrame		= 0x0010,
+	dribbleBits		= 0x0080,
+						/* RxStatus bits */
+	rxBytes			= 0x1FFF,	/* 3C59[0257] mask */
+	rxBytes9		= 0x07FF,	/* 3C5[078]9 mask */
+	rxError9		= 0x3800,	/* 3C5[078]9 error mask */
+	rxOverrun9		= 0x0000,
+	oversizedFrame9		= 0x0800,
+	dribbleBits9		= 0x1000,
+	runtFrame9		= 0x1800,
+	alignmentError9		= 0x2000,	/* Framing */
+	crcError9		= 0x2800,
+	rxError			= 0x4000,
+	rxIncomplete		= 0x8000,
+						/* TxStatus Bits */
+	txStatusOverflow	= 0x0004,
+	maxCollisions		= 0x0008,
+	txUnderrun		= 0x0010,
+	txJabber		= 0x0020,
+	interruptRequested	= 0x0040,
+	txStatusComplete	= 0x0080,
+};
+
+enum {						/* Window 2 - station address */
+	Wstation		= 0x0002,
+};
+
+enum {						/* Window 3 - FIFO management */
+	Wfifo			= 0x0003,
+						/* registers */
+	InternalConfig		= 0x0000,	/* 3C509B, 3C589, 3C59[0257] */
+	OtherInt		= 0x0004,	/* 3C59[0257] */
+	RomControl		= 0x0006,	/* 3C509B, 3C59[27] */
+	MacControl		= 0x0006,	/* 3C59[0257] */
+	ResetOptions		= 0x0008,	/* 3C59[0257] */
+	RxFree			= 0x000A,
+						/* InternalConfig bits */
+	disableBadSsdDetect	= 0x00000100,
+	ramLocation		= 0x00000200,	/* 0 external, 1 internal */
+	ramPartition5to3	= 0x00000000,
+	ramPartition3to1	= 0x00010000,
+	ramPartition1to1	= 0x00020000,
+	ramPartition3to5	= 0x00030000,
+	ramPartitionMask	= 0x00030000,
+	xcvr10BaseT		= 0x00000000,
+	xcvrAui			= 0x00100000,	/* 10BASE5 */
+	xcvr10Base2		= 0x00300000,
+	xcvr100BaseTX		= 0x00400000,
+	xcvr100BaseFX		= 0x00500000,
+	xcvrMii			= 0x00600000,
+	xcvrMask		= 0x00700000,
+	autoSelect		= 0x01000000,
+						/* MacControl bits */
+	deferExtendEnable	= 0x0001,
+	deferTimerSelect	= 0x001E,	/* mask */
+	fullDuplexEnable	= 0x0020,
+	allowLargePackets	= 0x0040,
+						/* ResetOptions bits */
+	baseT4Available		= 0x0001,
+	baseTXAvailable		= 0x0002,
+	baseFXAvailable		= 0x0004,
+	base10TAvailable	= 0x0008,
+	coaxAvailable		= 0x0010,
+	auiAvailable		= 0x0020,
+	miiConnector		= 0x0040,
+};
+
+enum {						/* Window 4 - diagnostic */
+	Wdiagnostic		= 0x0004,
+						/* registers */
+	VcoDiagnostic		= 0x0002,
+	FifoDiagnostic		= 0x0004,
+	NetworkDiagnostic	= 0x0006,
+	PhysicalMgmt		= 0x0008,
+	MediaStatus		= 0x000A,
+	BadSSD			= 0x000C,
+						/* FifoDiagnostic bits */
+	txOverrun		= 0x0400,
+	rxUnderrun		= 0x2000,
+	receiving		= 0x8000,
+						/* MediaStatus bits */
+	dataRate100		= 0x0002,
+	crcStripDisable		= 0x0004,
+	enableSqeStats		= 0x0008,
+	collisionDetect		= 0x0010,
+	carrierSense		= 0x0020,
+	jabberGuardEnable	= 0x0040,
+	linkBeatEnable		= 0x0080,
+	jabberDetect		= 0x0200,
+	polarityReversed	= 0x0400,
+	linkBeatDetect		= 0x0800,
+	txInProg		= 0x1000,
+	dcConverterEnabled	= 0x4000,
+	auiDisable		= 0x8000,
+};
+
+enum {						/* Window 5 - internal state */
+	Wstate			= 0x0005,
+						/* registers */
+	TxStartThresh		= 0x0000,
+	TxAvalableThresh	= 0x0002,
+	RxEarlyThresh		= 0x0006,
+	RxFilter		= 0x0008,
+	InterruptEnable		= 0x000A,
+	IndicationEnable	= 0x000C,
+};
+
+enum {						/* Window 6 - statistics */
+	Wstatistics		= 0x0006,
+						/* registers */
+	CarrierLost		= 0x0000,
+	SqeErrors		= 0x0001,
+	MultipleColls		= 0x0002,
+	SingleCollFrames	= 0x0003,
+	LateCollisions		= 0x0004,
+	RxOverruns		= 0x0005,
+	FramesXmittedOk		= 0x0006,
+	FramesRcvdOk		= 0x0007,
+	FramesDeferred		= 0x0008,
+	UpperFramesOk		= 0x0009,
+	BytesRcvdOk		= 0x000A,
+	BytesXmittedOk		= 0x000C,
+};
+
+enum {						/* Window 7 - bus master operations */
+	Wmaster			= 0x0007,
+						/* registers */
+	MasterAddress		= 0x0000,
+	MasterLen		= 0x0006,
+	MasterStatus		= 0x000C,
+						/* MasterStatus bits */
+	masterAbort		= 0x0001,
+	targetAbort		= 0x0002,
+	targetRetry		= 0x0004,
+	targetDisc		= 0x0008,
+	masterDownload		= 0x1000,
+	masterUpload		= 0x4000,
+	masterInProgress	= 0x8000,
+
+	masterMask		= 0xD00F,
+};	
+
+typedef struct {
+	int	txthreshold;
+} Ctlr;
+
+static void
+attach(Ether* ether)
+{
+	int port, x;
+
+	port = ether->port;
+
+	/*
+	 * Set the receiver packet filter for this and broadcast addresses,
+	 * set the interrupt masks for all interrupts, enable the receiver
+	 * and transmitter.
+	 */
+	x = receiveBroadcast|receiveIndividual;
+	COMMAND(port, SetRxFilter, x);
+
+	x = interruptMask|interruptLatch;
+	COMMAND(port, SetIndicationEnable, x);
+	COMMAND(port, SetInterruptEnable, x);
+
+	COMMAND(port, RxEnable, 0);
+	COMMAND(port, TxEnable, 0);
+}
+
+static void
+transmit(Ether* ether)
+{
+	int port, len;
+	RingBuf *tb;
+
+	/*
+	 * Attempt to top-up the transmit FIFO. If there's room simply
+	 * stuff in the packet length (unpadded to a dword boundary), the
+	 * packet data (padded) and remove the packet from the queue.
+	 * If there's no room post an interrupt for when there is.
+	 * This routine is called both from the top level and from interrupt
+	 * level.
+	 */
+	port = ether->port;
+	for(tb = &ether->tb[ether->ti]; tb->owner == Interface; tb = &ether->tb[ether->ti]){
+		len = ROUNDUP(tb->len, 4);
+		if(len+4 <= ins(port+TxFree)){
+			outl(port+Fifo, tb->len);
+			outsl(port+Fifo, tb->pkt, len/4);
+			tb->owner = Host;
+			ether->ti = NEXT(ether->ti, ether->ntb);
+		}
+		else{
+			COMMAND(port, SetTxAvailableThresh, len);
+			break;
+		}
+	}
+}
+
+static void
+receive(Ether* ether)
+{
+	int len, port, rxstatus;
+	RingBuf *rb;
+
+	port = ether->port;
+
+	while(((rxstatus = ins(port+RxStatus)) & rxIncomplete) == 0){
+		/*
+		 * If there was an error, throw it away and continue.
+		 * The 3C5[078]9 has the error info in the status register
+		 * and the 3C59[0257] implement a separate RxError register.
+		 */
+		if((rxstatus & rxError) == 0){
+			/*
+			 * Packet received. Read it into the next free
+			 * ring buffer, if any. Must read len bytes padded
+			 * to a doubleword, can be picked out 32-bits at
+			 * a time. The CRC is already stripped off.
+			 */
+			rb = &ether->rb[ether->ri];
+			if(rb->owner == Interface){
+				len = (rxstatus & rxBytes9);
+				rb->len = len;
+				insl(port+Fifo, rb->pkt, HOWMANY(len, 4));
+
+				rb->owner = Host;
+				ether->ri = NEXT(ether->ri, ether->nrb);
+			}
+		}
+
+		/*
+		 * All done, discard the packet.
+		 */
+		COMMAND(port, RxDiscard, 0);
+		while(STATUS(port) & commandInProgress)
+			;
+	}
+}
+
+static void
+statistics(Ether* ether)
+{
+	int i, port, w;
+
+	port = ether->port;
+	w = (STATUS(port)>>13) & 0x07;
+	COMMAND(port, SelectRegisterWindow, Wop);
+	COMMAND(port, SelectRegisterWindow, Wstatistics);
+
+	for(i = 0; i < 0x0A; i++)
+		inb(port+i);
+	ins(port+BytesRcvdOk);
+	ins(port+BytesXmittedOk);
+
+	COMMAND(port, SelectRegisterWindow, w);
+}
+
+static void
+interrupt(Ureg*, void* arg)
+{
+	Ether *ether;
+	int port, status, txstatus, w, x;
+	Ctlr *ctlr;
+
+	ether = arg;
+	port = ether->port;
+	ctlr = ether->ctlr;
+
+	w = (STATUS(port)>>13) & 0x07;
+	COMMAND(port, SelectRegisterWindow, Wop);
+
+	for(;;){
+		/*
+		 * Clear the interrupt latch.
+		 * It's possible to receive a packet and for another
+		 * to become complete before exiting the interrupt
+		 * handler so this must be done first to ensure another
+		 * interrupt will occur.
+		 */
+		COMMAND(port, AcknowledgeInterrupt, interruptLatch);
+		status = STATUS(port);
+		if((status & interruptMask) == 0)
+			break;
+
+		if(status & hostError){
+			/*
+			 * Adapter failure, try to find out why, reset if
+			 * necessary. What happens if Tx is active and a reset
+			 * occurs, need to retransmit? This probably isn't right.
+			 */
+			COMMAND(port, SelectRegisterWindow, Wdiagnostic);
+			x = ins(port+FifoDiagnostic);
+			COMMAND(port, SelectRegisterWindow, Wop);
+			print("elnk3#%d: status 0x%uX, diag 0x%uX\n",
+			    ether->ctlrno, status, x);
+
+			if(x & txOverrun){
+				COMMAND(port, TxReset, 0);
+				COMMAND(port, TxEnable, 0);
+			}
+
+			if(x & rxUnderrun){
+				/*
+				 * This shouldn't happen...
+				 * Need to restart any busmastering?
+				 */
+				COMMAND(port, RxReset, 0);
+				while(STATUS(port) & commandInProgress)
+					;
+				COMMAND(port, RxEnable, 0);
+			}
+
+			status &= ~hostError;
+		}
+
+		if(status & (transferInt|rxComplete)){
+			receive(ether);
+			status &= ~(transferInt|rxComplete);
+		}
+
+		if(status & txComplete){
+			/*
+			 * Pop the TxStatus stack, accumulating errors.
+			 * Adjust the TX start threshold if there was an underrun.
+			 * If there was a Jabber or Underrun error, reset
+			 * the transmitter.
+			 * For all conditions enable the transmitter.
+			 */
+			txstatus = 0;
+			do{
+				if(x = inb(port+TxStatus))
+					outb(port+TxStatus, 0);
+				txstatus |= x;
+			}while(STATUS(port) & txComplete);
+
+			if(txstatus & txUnderrun){
+				COMMAND(port, SelectRegisterWindow, Wdiagnostic);
+				while(ins(port+MediaStatus) & txInProg)
+					;
+				COMMAND(port, SelectRegisterWindow, Wop);
+				if(ctlr->txthreshold < ETHERMAXTU)
+					ctlr->txthreshold += ETHERMINTU;
+			}
+
+			if(txstatus & (txJabber|txUnderrun)){
+				COMMAND(port, TxReset, 0);
+				while(STATUS(port) & commandInProgress)
+					;
+				COMMAND(port, SetTxStartThresh, ctlr->txthreshold);
+			}
+			COMMAND(port, TxEnable, 0);
+			status &= ~txComplete;
+			status |= txAvailable;
+		}
+
+		if(status & txAvailable){
+			COMMAND(port, AcknowledgeInterrupt, txAvailable);
+			transmit(ether);
+			status &= ~txAvailable;
+		}
+
+		if(status & updateStats){
+			statistics(ether);
+			status &= ~updateStats;
+		}
+
+		/*
+		 * Panic if there are any interrupts not dealt with.
+		 */
+		if(status & interruptMask)
+			panic("elnk3#%d: interrupt mask 0x%uX\n", ether->ctlrno, status);
+	}
+
+	COMMAND(port, SelectRegisterWindow, w);
+}
+
+typedef struct Adapter {
+	int	port;
+	int	irq;
+	int	tbdf;
+} Adapter;
+static Block* adapter;
+
+static void
+tcmadapter(int port, int irq, int tbdf)
+{
+	Block *bp;
+	Adapter *ap;
+
+	bp = allocb(sizeof(Adapter));
+	ap = (Adapter*)bp->rp;
+	ap->port = port;
+	ap->irq = irq;
+	ap->tbdf = tbdf;
+
+	bp->next = adapter;
+	adapter = bp;
+}
+
+/*
+ * Write two 0 bytes to identify the IDport and then reset the
+ * ID sequence. Then send the ID sequence to the card to get
+ * the card into command state.
+ */
+static void
+idseq(void)
+{
+	int i;
+	uchar al;
+	static int reset, untag;
+
+	/*
+	 * One time only:
+	 *	reset any adapters listening
+	 */
+	if(reset == 0){
+		outb(IDport, 0);
+		outb(IDport, 0);
+		outb(IDport, 0xC0);
+		delay(20);
+		reset = 1;
+	}
+
+	outb(IDport, 0);
+	outb(IDport, 0);
+	for(al = 0xFF, i = 0; i < 255; i++){
+		outb(IDport, al);
+		if(al & 0x80){
+			al <<= 1;
+			al ^= 0xCF;
+		}
+		else
+			al <<= 1;
+	}
+
+	/*
+	 * One time only:
+	 *	write ID sequence to get the attention of all adapters;
+	 *	untag all adapters.
+	 * If we do a global reset here on all adapters we'll confuse any
+	 * ISA cards configured for EISA mode.
+	 */
+	if(untag == 0){
+		outb(IDport, 0xD0);
+		untag = 1;
+	}
+}
+
+static ulong
+activate(void)
+{
+	int i;
+	ushort x, acr;
+
+	/*
+	 * Do the little configuration dance:
+	 *
+	 * 2. write the ID sequence to get to command state.
+	 */
+	idseq();
+
+	/*
+	 * 3. Read the Manufacturer ID from the EEPROM.
+	 *    This is done by writing the IDPort with 0x87 (0x80
+	 *    is the 'read EEPROM' command, 0x07 is the offset of
+	 *    the Manufacturer ID field in the EEPROM).
+	 *    The data comes back 1 bit at a time.
+	 *    We seem to need a delay here between reading the bits.
+	 *
+	 * If the ID doesn't match, there are no more adapters.
+	 */
+	outb(IDport, 0x87);
+	delay(20);
+	for(x = 0, i = 0; i < 16; i++){
+		delay(20);
+		x <<= 1;
+		x |= inb(IDport) & 0x01;
+	}
+	if(x != 0x6D50)
+		return 0;
+
+	/*
+	 * 3. Read the Address Configuration from the EEPROM.
+	 *    The Address Configuration field is at offset 0x08 in the EEPROM).
+	 */
+	outb(IDport, 0x88);
+	for(acr = 0, i = 0; i < 16; i++){
+		delay(20);
+		acr <<= 1;
+		acr |= inb(IDport) & 0x01;
+	}
+
+	return (acr & 0x1F)*0x10 + 0x200;
+}
+
+#ifdef notjustpcmcia
+static void
+tcm509isa(void)
+{
+	int irq, port;
+
+	/*
+	 * Attempt to activate all adapters. If adapter is set for
+	 * EISA mode (0x3F0), tag it and ignore. Otherwise, activate
+	 * it fully.
+	 */
+	while(port = activate()){
+		/*
+		 * 6. Tag the adapter so it won't respond in future.
+		 */
+		outb(IDport, 0xD1);
+		if(port == 0x3F0)
+			continue;
+
+		/*
+		 * 6. Activate the adapter by writing the Activate command
+		 *    (0xFF).
+		 */
+		outb(IDport, 0xFF);
+		delay(20);
+
+		/*
+		 * 8. Can now talk to the adapter's I/O base addresses.
+		 *    Use the I/O base address from the acr just read.
+		 *
+		 *    Enable the adapter and clear out any lingering status
+		 *    and interrupts.
+		 */
+		while(STATUS(port) & commandInProgress)
+			;
+		COMMAND(port, SelectRegisterWindow, Wsetup);
+		outs(port+ConfigControl, Ena);
+
+		COMMAND(port, TxReset, 0);
+		COMMAND(port, RxReset, 0);
+		COMMAND(port, AcknowledgeInterrupt, 0xFF);
+
+		irq = (ins(port+ResourceConfig)>>12) & 0x0F;
+		tcmadapter(port, irq, BUSUNKNOWN);
+	}
+}
+
+static void
+tcm5XXeisa(void)
+{
+	ushort x;
+	int irq, port, slot;
+
+	/*
+	 * Check if this is an EISA machine.
+	 * If not, nothing to do.
+	 */
+	if(strncmp((char*)(KZERO|0xFFFD9), "EISA", 4))
+		return;
+
+	/*
+	 * Continue through the EISA slots looking for a match on both
+	 * 3COM as the manufacturer and 3C579-* or 3C59[27]-* as the product.
+	 * If an adapter is found, select window 0, enable it and clear
+	 * out any lingering status and interrupts.
+	 */
+	for(slot = 1; slot < MaxEISA; slot++){
+		port = slot*0x1000;
+		if(ins(port+0xC80+ManufacturerID) != 0x6D50)
+			continue;
+		x = ins(port+0xC80+ProductID);
+		if((x & 0xF0FF) != 0x9050 && (x & 0xFF00) != 0x5900)
+			continue;
+
+		COMMAND(port, SelectRegisterWindow, Wsetup);
+		outs(port+ConfigControl, Ena);
+
+		COMMAND(port, TxReset, 0);
+		COMMAND(port, RxReset, 0);
+		COMMAND(port, AcknowledgeInterrupt, 0xFF);
+
+		irq = (ins(port+ResourceConfig)>>12) & 0x0F;
+		tcmadapter(port, irq, BUSUNKNOWN);
+	}
+}
+
+static void
+tcm59Xpci(void)
+{
+	Pcidev *p;
+	int irq, port;
+
+	p = nil;
+	while(p = pcimatch(p, 0x10B7, 0)){
+		port = p->mem[0].bar & ~0x01;
+		irq = p->intl;
+		COMMAND(port, GlobalReset, 0);
+		while(STATUS(port) & commandInProgress)
+			;
+
+		tcmadapter(port, irq, p->tbdf);
+	}
+}
+#endif /* notjustpcmcia */
+
+static char* tcmpcmcia[] = {
+	"3C589",			/* 3COM 589[ABCD] */
+	"3C562",			/* 3COM 562 */
+	"589E",				/* 3COM Megahertz 589E */
+	nil,
+};
+
+static int
+tcm5XXpcmcia(Ether* ether)
+{
+	int i;
+
+	for(i = 0; tcmpcmcia[i] != nil; i++){
+		if(!cistrcmp(ether->type, tcmpcmcia[i]))
+			return ether->port;
+	}
+
+	return 0;
+}
+
+static int
+autoselect(int port, int rxstatus9)
+{
+	int media, x;
+
+	/*
+	 * Pathetic attempt at automatic media selection.
+	 * Really just to get the Fast Etherlink 10BASE-T/100BASE-TX
+	 * cards operational.
+	 */
+	media = auiAvailable|coaxAvailable|base10TAvailable;
+	if(rxstatus9 == 0){
+		COMMAND(port, SelectRegisterWindow, Wfifo);
+		media = ins(port+ResetOptions);
+	}
+
+	if(media & miiConnector)
+		return xcvrMii;
+
+	if(media & baseTXAvailable){
+		/*
+		 * Must have InternalConfig register.
+		 */
+		COMMAND(port, SelectRegisterWindow, Wfifo);
+		x = inl(port+InternalConfig) & ~xcvrMask;
+		x |= xcvr100BaseTX;
+		outl(port+InternalConfig, x);
+		COMMAND(port, TxReset, 0);
+		while(STATUS(port) & commandInProgress)
+			;
+		COMMAND(port, RxReset, 0);
+		while(STATUS(port) & commandInProgress)
+			;
+
+		COMMAND(port, SelectRegisterWindow, Wdiagnostic);
+		x = ins(port+MediaStatus) & ~(dcConverterEnabled|jabberGuardEnable);
+		outs(port+MediaStatus, linkBeatEnable|x);
+		delay(10);
+
+{ int i, v;
+  for(i = 0; i < 10000; i++){
+	v = ins(port+MediaStatus);
+	if(v & linkBeatDetect){
+		print("count %d v %uX\n", i, v);
+		return xcvr100BaseTX;
+	}
+	delay(1);
+  }
+print("count %d v %uX\n", i, ins(port+MediaStatus));
+}
+		if(ins(port+MediaStatus) & linkBeatDetect)
+			return xcvr100BaseTX;
+		outs(port+MediaStatus, x);
+	}
+
+	if(media & base10TAvailable){
+		if(rxstatus9 == 0){
+			COMMAND(port, SelectRegisterWindow, Wfifo);
+			x = inl(port+InternalConfig) & ~xcvrMask;
+			x |= xcvr10BaseT;
+			outl(port+InternalConfig, x);
+		}
+		else{
+			COMMAND(port, SelectRegisterWindow, Wsetup);
+			x = ins(port+AddressConfig) & ~xcvrMask9;
+			x |= (xcvr10BaseT>>20)<<14;
+			outs(port+AddressConfig, x);
+		}
+		COMMAND(port, TxReset, 0);
+		while(STATUS(port) & commandInProgress)
+			;
+		COMMAND(port, RxReset, 0);
+		while(STATUS(port) & commandInProgress)
+			;
+
+		COMMAND(port, SelectRegisterWindow, Wdiagnostic);
+		x = ins(port+MediaStatus) & ~dcConverterEnabled;
+		outs(port+MediaStatus, linkBeatEnable|jabberGuardEnable|x);
+		delay(10);
+
+		if(ins(port+MediaStatus) & linkBeatDetect)
+			return xcvr10BaseT;
+		outs(port+MediaStatus, x);
+	}
+
+	/*
+	 * Botch.
+	 */
+	return autoSelect;
+}
+
+static int
+eepromdata(int port, int offset)
+{
+	COMMAND(port, SelectRegisterWindow, Wsetup);
+	while(EEPROMBUSY(port))
+		;
+	EEPROMCMD(port, EepromReadRegister, offset);
+	while(EEPROMBUSY(port))
+		;
+	return EEPROMDATA(port);
+}
+
+int
+elnk3reset(Ether* ether)
+{
+	int did, i, port, rxstatus9, x, xcvr;
+	Block *bp, **bpp;
+	Adapter *ap;
+	uchar ea[Eaddrlen];
+	Ctlr *ctlr;
+#ifdef notjustpcmcia
+	static int scandone;
+
+	/*
+	 * Scan for adapter on PCI, EISA and finally
+	 * using the little ISA configuration dance.
+	 */
+	if(scandone == 0){
+		tcm59Xpci();
+		tcm5XXeisa();
+		tcm509isa();
+		scandone = 1;
+	}
+#endif /* notjustpcmcia */
+
+	/*
+	 * Any adapter matches if no ether->port is supplied,
+	 * otherwise the ports must match.
+	 */
+	port = 0;
+	bpp = &adapter;
+	for(bp = *bpp; bp; bp = bp->next){
+		ap = (Adapter*)bp->rp;
+		if(ether->port == 0 || ether->port == ap->port){
+			port = ap->port;
+			ether->irq = ap->irq;
+			ether->tbdf = ap->tbdf;
+			*bpp = bp->next;
+			freeb(bp);
+			break;
+		}
+		bpp = &bp->next;
+	}
+	if(port == 0 && (port = tcm5XXpcmcia(ether)) == 0)
+		return -1;
+
+	/*
+	 * Read the DeviceID from the EEPROM, it's at offset 0x03,
+	 * and do something depending on capabilities.
+	 */
+	switch(did = eepromdata(port, 0x03)){
+
+	case 0x9000:
+	case 0x9001:
+	case 0x9050:
+	case 0x9051:
+		if(BUSTYPE(ether->tbdf) != BusPCI)
+			goto buggery;
+		goto vortex;
+
+	case 0x5900:
+	case 0x5920:
+	case 0x5950:
+	case 0x5951:
+	case 0x5952:
+	case 0x5970:
+	case 0x5971:
+	case 0x5972:
+	vortex:
+		COMMAND(port, SelectRegisterWindow, Wfifo);
+		xcvr = inl(port+InternalConfig) & (autoSelect|xcvrMask);
+		rxstatus9 = 0;
+		break;
+
+	buggery:
+	default:
+		COMMAND(port, SelectRegisterWindow, Wsetup);
+		x = ins(port+AddressConfig);
+		xcvr = ((x & xcvrMask9)>>14)<<20;
+		if(x & autoSelect9)
+			xcvr |= autoSelect;
+		rxstatus9 = 1;
+		break;
+	}
+	USED(did);
+
+	/*
+	 * Check if the adapter's station address is to be overridden.
+	 * If not, read it from the EEPROM and set in ether->ea prior to loading the
+	 * station address in Wstation. The EEPROM returns 16-bits at a time.
+	 */
+	memset(ea, 0, Eaddrlen);
+	if(memcmp(ea, ether->ea, Eaddrlen) == 0){
+		for(i = 0; i < Eaddrlen/2; i++){
+			x = eepromdata(port, i);
+			ether->ea[2*i] = x>>8;
+			ether->ea[2*i+1] = x;
+		}
+	}
+
+	COMMAND(port, SelectRegisterWindow, Wstation);
+	for(i = 0; i < Eaddrlen; i++)
+		outb(port+i, ether->ea[i]);
+
+	/*
+	 * Enable the transceiver if necessary.
+	 */
+	if(xcvr & autoSelect)
+		xcvr = autoselect(port, rxstatus9);
+	switch(xcvr){
+
+	case xcvrMii:
+		break;
+
+	case xcvr100BaseTX:
+	case xcvr100BaseFX:
+		COMMAND(port, SelectRegisterWindow, Wfifo);
+		x = inl(port+InternalConfig) & ~ramPartitionMask;
+		outl(port+InternalConfig, x|ramPartition1to1);
+
+		COMMAND(port, SelectRegisterWindow, Wdiagnostic);
+		x = ins(port+MediaStatus) & ~(dcConverterEnabled|jabberGuardEnable);
+		x |= linkBeatEnable;
+		outs(port+MediaStatus, x);
+		break;
+
+	case xcvr10BaseT:
+		/*
+		 * Enable Link Beat and Jabber to start the
+		 * transceiver.
+		 */
+		COMMAND(port, SelectRegisterWindow, Wdiagnostic);
+		x = ins(port+MediaStatus) & ~dcConverterEnabled;
+		x |= linkBeatEnable|jabberGuardEnable;
+		outs(port+MediaStatus, x);
+		break;
+
+	case xcvr10Base2:
+		COMMAND(port, SelectRegisterWindow, Wdiagnostic);
+		x = ins(port+MediaStatus) & ~(linkBeatEnable|jabberGuardEnable);
+		outs(port+MediaStatus, x);
+
+		/*
+		 * Start the DC-DC converter.
+		 * Wait > 800 microseconds.
+		 */
+		COMMAND(port, EnableDcConverter, 0);
+		delay(1);
+		break;
+	}
+
+	/*
+	 * Wop is the normal operating register set.
+	 * The 3C59[0257] adapters allow access to more than one register window
+	 * at a time, but there are situations where switching still needs to be
+	 * done, so just do it.
+	 * Clear out any lingering Tx status.
+	 */
+	COMMAND(port, SelectRegisterWindow, Wop);
+	while(inb(port+TxStatus))
+		outb(port+TxStatus, 0);
+
+	/*
+	 * Allocate a controller structure and start
+	 * to initialise it.
+	 */
+	ether->ctlr = malloc(sizeof(Ctlr));
+	ctlr = ether->ctlr;
+	memset(ctlr, 0, sizeof(Ctlr));
+
+	/*
+	 * Set a base TxStartThresh which will be incremented
+	 * if any txUnderrun errors occur and ensure no RxEarly
+	 * interrupts happen.
+	 */
+	ctlr->txthreshold = ETHERMINTU;
+	COMMAND(port, SetTxStartThresh, ETHERMINTU);
+	COMMAND(port, SetRxEarlyThresh, ETHERMAXTU);
+
+	/*
+	 * Set up the software configuration.
+	 */
+	ether->port = port;
+	ether->attach = attach;
+	ether->transmit = transmit;
+	ether->interrupt = interrupt;
+
+	return 0;
+}
--- /dev/null
+++ b/os/boot.original/pc/etherga620.c
@@ -1,0 +1,1147 @@
+/*
+ * bootstrap driver for
+ * Netgear GA620 Gigabit Ethernet Card.
+ * Specific for the Alteon Tigon 2 and Intel Pentium or later.
+ * To Do:
+ *	cache alignment for PCI Write-and-Invalidate
+ *	mini ring (what size)?
+ *	tune coalescing values
+ *	statistics formatting
+ *	don't update Spi if nothing to send
+ *	receive ring alignment
+ *	watchdog for link management?
+ */
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+#define malign(n)	xspanalloc((n), 32, 0)
+
+#include "etherif.h"
+#include "etherga620fw.h"
+
+enum {
+	Mhc		= 0x0040,	/* Miscellaneous Host Control */
+	Mlc		= 0x0044,	/* Miscellaneous Local Control */
+	Mc		= 0x0050,	/* Miscellaneous Configuration */
+	Ps		= 0x005C,	/* PCI State */
+	Wba		= 0x0068,	/* Window Base Address */
+	Wd		= 0x006C,	/* Window Data */
+
+	DMAas		= 0x011C,	/* DMA Assist State */
+
+	CPUAstate	= 0x0140,	/* CPU A State */
+	CPUApc		= 0x0144,	/* CPU A Programme Counter */
+
+	CPUBstate	= 0x0240,	/* CPU B State */
+
+	Hi		= 0x0504,	/* Host In Interrupt Handler */
+	Cpi		= 0x050C,	/* Command Producer Index */
+	Spi		= 0x0514,	/* Send Producer Index */
+	Rspi		= 0x051C,	/* Receive Standard Producer Index */
+	Rjpi		= 0x0524,	/* Receive Jumbo Producer Index */
+	Rmpi		= 0x052C,	/* Receive Mini Producer Index */
+
+	Mac		= 0x0600,	/* MAC Address */
+	Gip		= 0x0608,	/* General Information Pointer */
+	Om		= 0x0618,	/* Operating Mode */
+	DMArc		= 0x061C,	/* DMA Read Configuration */
+	DMAwc		= 0x0620,	/* DMA Write Configuration */
+	Tbr		= 0x0624,	/* Transmit Buffer Ratio */
+	Eci		= 0x0628,	/* Event Consumer Index */
+	Cci		= 0x062C,	/* Command Consumer Index */
+
+	Rct		= 0x0630,	/* Receive Coalesced Ticks */
+	Sct		= 0x0634,	/* Send Coalesced Ticks */
+	St		= 0x0638,	/* Stat Ticks */
+	SmcBD		= 0x063C,	/* Send Max. Coalesced BDs */
+	RmcBD		= 0x0640,	/* Receive Max. Coalesced BDs */
+	Nt		= 0x0644,	/* NIC Tracing */
+	Gln		= 0x0648,	/* Gigabit Link Negotiation */
+	Fln		= 0x064C,	/* 10/100 Link Negotiation */
+	Ifx		= 0x065C,	/* Interface Index */
+	IfMTU		= 0x0660,	/* Interface MTU */
+	Mi		= 0x0664,	/* Mask Interrupts */
+	Gls		= 0x0668,	/* Gigabit Link State */
+	Fls		= 0x066C,	/* 10/100 Link State */
+
+	Cr		= 0x0700,	/* Command Ring */
+
+	Lmw		= 0x0800,	/* Local Memory Window */
+};
+
+enum {					/* Mhc */
+	Is		= 0x00000001,	/* Interrupt State */
+	Ci		= 0x00000002,	/* Clear Interrupt */
+	Hr		= 0x00000008,	/* Hard Reset */
+	Eebs		= 0x00000010,	/* Enable Endian Byte Swap */
+	Eews		= 0x00000020,	/* Enable Endian Word (64-bit) swap */
+	Mpio		= 0x00000040,	/* Mask PCI Interrupt Output */
+};
+
+enum {					/* Mlc */
+	SRAM512		= 0x00000200,	/* SRAM Bank Size of 512KB */
+	SRAMmask	= 0x00000300,
+	EEclk		= 0x00100000,	/* Serial EEPROM Clock Output */
+	EEdoe		= 0x00200000,	/* Serial EEPROM Data Out Enable */
+	EEdo		= 0x00400000,	/* Serial EEPROM Data Out Value */
+	EEdi		= 0x00800000,	/* Serial EEPROM Data Input */
+};
+
+enum {					/* Mc */
+	SyncSRAM	= 0x00100000,	/* Set Synchronous SRAM Timing */
+};
+
+enum {					/* Ps */
+	PCIwm32		= 0x000000C0,	/* Write Max DMA 32 */
+	PCImrm		= 0x00020000,	/* Use Memory Read Multiple Command */
+	PCI66		= 0x00080000,
+	PCI32		= 0x00100000,
+	PCIrcmd		= 0x06000000,	/* PCI Read Command */
+	PCIwcmd		= 0x70000000,	/* PCI Write Command */
+};
+
+enum {					/* CPUAstate */
+	CPUrf		= 0x00000010,	/* ROM Fail */
+	CPUhalt		= 0x00010000,	/* Halt the internal CPU */
+	CPUhie		= 0x00040000,	/* HALT instruction executed */
+};
+
+enum {					/* Om */
+	BswapBD		= 0x00000002,	/* Byte Swap Buffer Descriptors */
+	WswapBD		= 0x00000004,	/* Word Swap Buffer Descriptors */
+	Warn		= 0x00000008,
+	BswapDMA	= 0x00000010,	/* Byte Swap DMA Data */
+	Only1DMA	= 0x00000040,	/* Only One DMA Active at a time */
+	NoJFrag		= 0x00000200,	/* Don't Fragment Jumbo Frames */
+	Fatal		= 0x40000000,
+};
+
+enum {					/* Lmw */
+	Lmwsz		= 2*1024,	/* Local Memory Window Size */
+
+	/*
+	 * legal values are 0x3800 iff Nsr is 128, 0x3000 iff Nsr is 256,
+	 * or 0x2000 iff Nsr is 512.
+	 */
+	Sr		= 0x3800,	/* Send Ring (accessed via Lmw) */
+};
+
+enum {					/* Link */
+	Lpref		= 0x00008000,	/* Preferred Link */
+	L10MB		= 0x00010000,
+	L100MB		= 0x00020000,
+	L1000MB		= 0x00040000,
+	Lfd		= 0x00080000,	/* Full Duplex */
+	Lhd		= 0x00100000,	/* Half Duplex */
+	Lefc		= 0x00200000,	/* Emit Flow Control Packets */
+	Lofc		= 0x00800000,	/* Obey Flow Control Packets */
+	Lean		= 0x20000000,	/* Enable Autonegotiation/Sensing */
+	Le		= 0x40000000,	/* Link Enable */
+};
+
+typedef struct Host64 {
+	uint	hi;
+	uint	lo;
+} Host64;
+
+typedef struct Ere {			/* Event Ring Element */
+	int	event;			/* event<<24 | code<<12 | index */
+	int	unused;
+} Ere;
+
+typedef int Cmd;			/* cmd<<24 | flags<<12 | index */
+
+typedef struct Rbd {			/* Receive Buffer Descriptor */
+	Host64	addr;
+	int	indexlen;		/* ring-index<<16 | buffer-length */
+	int	flags;			/* only lower 16-bits */
+	int	checksum;		/* ip<<16 |tcp/udp */
+	int	error;			/* only upper 16-bits */
+	int	reserved;
+	void*	opaque;			/* passed to receive return ring */
+} Rbd;
+
+typedef struct Sbd {			/* Send Buffer Descriptor */
+	Host64	addr;
+	int	lenflags;		/* len<<16 |flags */
+	int	reserved;
+} Sbd;
+
+enum {					/* Buffer Descriptor Flags */
+	Fend		= 0x00000004,	/* Frame Ends in this Buffer */
+	Frjr		= 0x00000010,	/* Receive Jumbo Ring Buffer */
+	Funicast	= 0x00000020,	/* Unicast packet (2-bit field) */
+	Fmulticast	= 0x00000040,	/* Multicast packet */
+	Fbroadcast	= 0x00000060,	/* Broadcast packet */
+	Ferror		= 0x00000400,	/* Frame Has Error */
+	Frmr		= 0x00001000,	/* Receive Mini Ring Buffer */
+};
+
+enum {					/* Buffer Error Flags */
+	Ecrc		= 0x00010000,	/* bad CRC */
+	Ecollision	= 0x00020000,	/* collision */
+	Elink		= 0x00040000,	/* link lost */
+	Ephy		= 0x00080000,	/* unspecified PHY frame decode error */
+	Eodd		= 0x00100000,	/* odd number of nibbles */
+	Emac		= 0x00200000,	/* unspecified MAC abort */
+	Elen64		= 0x00400000,	/* short packet */
+	Eresources	= 0x00800000,	/* MAC out of internal resources */
+	Egiant		= 0x01000000,	/* packet too big */
+};
+
+typedef struct Rcb {			/* Ring Control Block */
+	Host64	addr;			/* points to the Rbd ring */
+	int	control;		/* max_len<<16 |flags */
+	int	unused;
+} Rcb;
+
+enum {
+	TcpUdpCksum	= 0x0001,	/* Perform TCP or UDP checksum */
+	IpCksum		= 0x0002,	/* Perform IP checksum */
+	NoPseudoHdrCksum= 0x0008,	/* Don't include the pseudo header */
+	VlanAssist	= 0x0010,	/* Enable VLAN tagging */
+	CoalUpdateOnly	= 0x0020,	/* Coalesce transmit interrupts */
+	HostRing	= 0x0040,	/* Sr in host memory */
+	SnapCksum	= 0x0080,	/* Parse + offload 802.3 SNAP frames */
+	UseExtRxBd	= 0x0100,	/* Extended Rbd for Jumbo frames */
+	RingDisabled	= 0x0200,	/* Jumbo or Mini RCB only */
+};
+
+typedef struct Gib {			/* General Information Block */
+	int	statistics[256];	/* Statistics */
+	Rcb	ercb;			/* Event Ring */
+	Rcb	crcb;			/* Command Ring */
+	Rcb	srcb;			/* Send Ring */
+	Rcb	rsrcb;			/* Receive Standard Ring */
+	Rcb	rjrcb;			/* Receive Jumbo Ring */
+	Rcb	rmrcb;			/* Receive Mini Ring */
+	Rcb	rrrcb;			/* Receive Return Ring */
+	Host64	epp;			/* Event Producer */
+	Host64	rrrpp;			/* Receive Return Ring Producer */
+	Host64	scp;			/* Send Consumer */
+	Host64	rsp;			/* Refresh Stats */
+} Gib;
+
+/*
+ * these sizes are all fixed in the card,
+ * except for Nsr, which has only 3 valid sizes.
+ */
+enum {					/* Host/NIC Interface ring sizes */
+	Ner		= 256,		/* event ring */
+	Ncr		= 64,		/* command ring */
+	Nsr		= 128,		/* send ring: 128, 256 or 512 */
+	Nrsr		= 512,		/* receive standard ring */
+	Nrjr		= 256,		/* receive jumbo ring */
+	Nrmr		= 1024,		/* receive mini ring, optional */
+	Nrrr		= 2048,		/* receive return ring */
+};
+
+enum {
+	NrsrHI		= 72,		/* Fill-level of Rsr (m.b. < Nrsr) */
+	NrsrLO		= 54,		/* Level at which to top-up ring */
+	NrjrHI		= 0,		/* Fill-level of Rjr (m.b. < Nrjr) */
+	NrjrLO		= 0,		/* Level at which to top-up ring */
+	NrmrHI		= 0,		/* Fill-level of Rmr (m.b. < Nrmr) */
+	NrmrLO		= 0,		/* Level at which to top-up ring */
+};
+
+typedef struct Ctlr Ctlr;
+struct Ctlr {
+	int	port;
+	Pcidev*	pcidev;
+	Ctlr*	next;
+	int	active;
+	int	id;
+
+	uchar	ea[Eaddrlen];
+
+	int*	nic;
+	Gib*	gib;
+
+	Ere*	er;
+
+	Lock	srlock;
+	Sbd*	sr;
+	Block**	srb;
+	int	nsr;			/* currently in send ring */
+
+	Rbd*	rsr;
+	int	nrsr;			/* currently in Receive Standard Ring */
+	Rbd*	rjr;
+	int	nrjr;			/* currently in Receive Jumbo Ring */
+	Rbd*	rmr;
+	int	nrmr;			/* currently in Receive Mini Ring */
+	Rbd*	rrr;
+	int	rrrci;			/* Receive Return Ring Consumer Index */
+
+	int	epi[2];			/* Event Producer Index */
+	int	rrrpi[2];		/* Receive Return Ring Producer Index */
+	int	sci[3];			/* Send Consumer Index ([2] is host) */
+
+	int	interrupts;		/* statistics */
+	int	mi;
+	uvlong	ticks;
+
+	int	coalupdateonly;		/* tuning */
+	int	hardwarecksum;
+	int	rct;			/* Receive Coalesce Ticks */
+	int	sct;			/* Send Coalesce Ticks */
+	int	st;			/* Stat Ticks */
+	int	smcbd;			/* Send Max. Coalesced BDs */
+	int	rmcbd;			/* Receive Max. Coalesced BDs */
+};
+
+static Ctlr* ctlrhead;
+static Ctlr* ctlrtail;
+
+#define csr32r(c, r)	(*((c)->nic+((r)/4)))
+#define csr32w(c, r, v)	(*((c)->nic+((r)/4)) = (v))
+
+static void
+sethost64(Host64* host64, void* addr)
+{
+	uvlong uvl;
+
+	uvl = PCIWADDR(addr);
+	host64->hi = uvl>>32;
+	host64->lo = uvl & 0xFFFFFFFFL;
+}
+
+static void
+ga620command(Ctlr* ctlr, int cmd, int flags, int index)
+{
+	int cpi;
+
+	cpi = csr32r(ctlr, Cpi);
+	csr32w(ctlr, Cr+(cpi*4), cmd<<24 | flags<<12 | index);
+	cpi = NEXT(cpi, Ncr);
+	csr32w(ctlr, Cpi, cpi);
+}
+
+static void
+ga620attach(Ether* )
+{
+}
+
+static void
+waitforlink(Ether *edev)
+{
+	int i;
+
+	if (edev->mbps == 0) {
+		print("#l%d: ga620: waiting for link", edev->ctlrno);
+		/* usually takes about 10 seconds */
+		for (i = 0; i < 20 && edev->mbps == 0; i++) {
+			print(".");
+			delay(1000);
+		}
+		print("\n");
+		if (i == 20 && edev->mbps == 0)
+			edev->mbps = 1;			/* buggered */
+	}
+}
+
+static void
+toringbuf(Ether *ether, Block *bp)
+{
+	RingBuf *rb = &ether->rb[ether->ri];
+
+	if (rb->owner == Interface) {
+		rb->len = BLEN(bp);
+		memmove(rb->pkt, bp->rp, rb->len);
+		rb->owner = Host;
+		ether->ri = NEXT(ether->ri, ether->nrb);
+	}
+	/* else no one is expecting packets from the network */
+}
+
+static Block *
+fromringbuf(Ether *ether)
+{
+	RingBuf *tb = &ether->tb[ether->ti];
+	Block *bp = allocb(tb->len);
+
+	if (bp == nil)
+		panic("fromringbuf: nil allocb return");
+	if (bp->wp == nil)
+		panic("fromringbuf: nil bp->wb");
+	memmove(bp->wp, tb->pkt, tb->len);
+	memmove(bp->wp+Eaddrlen, ether->ea, Eaddrlen);
+	bp->wp += tb->len;
+	return bp;
+}
+
+static int
+_ga620transmit(Ether* edev)
+{
+	Sbd *sbd;
+	Block *bp;
+	Ctlr *ctlr;
+	RingBuf *tb;
+	int sci, spi, work;
+
+	/*
+	 * For now there are no smarts here, just empty the
+	 * ring and try to fill it back up. Tuning comes later.
+	 */
+	ctlr = edev->ctlr;
+	waitforlink(edev);
+	ilock(&ctlr->srlock);
+
+	/*
+	 * Free any completed packets.
+	 * Ctlr->sci[0] is where the NIC has got to consuming the ring.
+	 * Ctlr->sci[2] is where the host has got to tidying up after the
+	 * NIC has done with the packets.
+	 */
+	work = 0;
+	for(sci = ctlr->sci[2]; sci != ctlr->sci[0]; sci = NEXT(sci, Nsr)){
+		if(ctlr->srb[sci] == nil)
+			continue;
+		freeb(ctlr->srb[sci]);
+		ctlr->srb[sci] = nil;
+		work++;
+	}
+	ctlr->sci[2] = sci;
+
+	sci = PREV(sci, Nsr);
+
+	tb = &edev->tb[edev->ti];
+	for(spi = csr32r(ctlr, Spi); spi != sci && tb->owner == Interface;
+	    spi = NEXT(spi, Nsr)){
+		bp = fromringbuf(edev);
+
+		sbd = &ctlr->sr[spi];
+		sethost64(&sbd->addr, bp->rp);
+		sbd->lenflags = BLEN(bp)<<16 |Fend;
+
+		ctlr->srb[spi] = bp;
+		work++;
+
+		tb->owner = Host;
+		edev->ti = NEXT(edev->ti, edev->ntb);
+		tb = &edev->tb[edev->ti];
+	}
+	csr32w(ctlr, Spi, spi);
+
+	iunlock(&ctlr->srlock);
+
+	return work;
+}
+
+static void
+ga620transmit(Ether* edev)
+{
+	_ga620transmit(edev);
+}
+
+static void
+ga620replenish(Ctlr* ctlr)
+{
+	Rbd *rbd;
+	int rspi;
+	Block *bp;
+
+	rspi = csr32r(ctlr, Rspi);
+	while(ctlr->nrsr < NrsrHI){
+		if((bp = allocb(ETHERMAXTU+4)) == nil)
+			break;
+		rbd = &ctlr->rsr[rspi];
+		sethost64(&rbd->addr, bp->rp);
+		rbd->indexlen = rspi<<16 | (ETHERMAXTU+4);
+		rbd->flags = 0;
+		rbd->opaque = bp;
+
+		rspi = NEXT(rspi, Nrsr);
+		ctlr->nrsr++;
+	}
+	csr32w(ctlr, Rspi, rspi);
+}
+
+static void
+ga620event(Ether *edev, int eci, int epi)
+{
+	unsigned event, code;
+	Ctlr *ctlr;
+
+	ctlr = edev->ctlr;
+	while(eci != epi){
+		event = ctlr->er[eci].event;
+		code = (event >> 12) & ((1<<12)-1);
+		switch(event>>24){
+		case 0x01:		/* firmware operational */
+			/* host stack (us) is up.  3rd arg of 2 means down. */
+			ga620command(ctlr, 0x01, 0x01, 0x00);
+			/*
+			 * link negotiation: any speed is okay.
+			 * 3rd arg of 1 selects gigabit only; 2 10/100 only.
+			 */
+			ga620command(ctlr, 0x0B, 0x00, 0x00);
+			print("#l%d: ga620: port %8.8uX: firmware is up\n",
+				edev->ctlrno, ctlr->port);
+			break;
+		case 0x04:		/* statistics updated */
+			break;
+		case 0x06:		/* link state changed */
+			switch (code) {
+			case 1:
+				edev->mbps = 1000;
+				break;
+			case 2:
+				print("#l%d: link down\n", edev->ctlrno);
+				break;
+			case 3:
+				edev->mbps = 100;	/* it's 10 or 100 */
+				break;
+			}
+			if (code != 2)
+				print("#l%d: %dMbps link up\n",
+					edev->ctlrno, edev->mbps);
+			break;
+		case 0x07:		/* event error */
+		default:
+			print("#l%d: ga620: er[%d] = %8.8uX\n", edev->ctlrno,
+				eci, event);
+			break;
+		}
+		eci = NEXT(eci, Ner);
+	}
+	csr32w(ctlr, Eci, eci);
+}
+
+static void
+ga620receive(Ether* edev)
+{
+	int len;
+	Rbd *rbd;
+	Block *bp;
+	Ctlr* ctlr;
+
+	ctlr = edev->ctlr;
+	while(ctlr->rrrci != ctlr->rrrpi[0]){
+		rbd = &ctlr->rrr[ctlr->rrrci];
+		/*
+		 * Errors are collected in the statistics block so
+		 * no need to tally them here, let ifstat do the work.
+		 */
+		len = rbd->indexlen & 0xFFFF;
+		if(!(rbd->flags & Ferror) && len != 0){
+			bp = rbd->opaque;
+			bp->wp = bp->rp+len;
+
+			toringbuf(edev, bp);
+		} else
+			freeb(rbd->opaque);
+		rbd->opaque = nil;
+
+		if(rbd->flags & Frjr)
+			ctlr->nrjr--;
+		else if(rbd->flags & Frmr)
+			ctlr->nrmr--;
+		else
+			ctlr->nrsr--;
+
+		ctlr->rrrci = NEXT(ctlr->rrrci, Nrrr);
+	}
+}
+
+static void
+ga620interrupt(Ureg*, void* arg)
+{
+	int csr, ie, work;
+	Ctlr *ctlr;
+	Ether *edev;
+
+	edev = arg;
+	ctlr = edev->ctlr;
+
+	if(!(csr32r(ctlr, Mhc) & Is))
+		return;
+
+	ctlr->interrupts++;
+	csr32w(ctlr, Hi, 1);
+
+	ie = 0;
+	work = 0;
+	while(ie < 2){
+		if(ctlr->rrrci != ctlr->rrrpi[0]){
+			ga620receive(edev);
+			work = 1;
+		}
+
+		if(_ga620transmit(edev) != 0)
+			work = 1;
+
+		csr = csr32r(ctlr, Eci);
+		if(csr != ctlr->epi[0]){
+			ga620event(edev, csr, ctlr->epi[0]);
+			work = 1;
+		}
+
+		if(ctlr->nrsr <= NrsrLO)
+			ga620replenish(ctlr);
+		if(work == 0){
+			if(ie == 0)
+				csr32w(ctlr, Hi, 0);
+			ie++;
+		}
+		work = 0;
+	}
+}
+
+static void
+ga620lmw(Ctlr* ctlr, int addr, int* data, int len)
+{
+	int i, l, lmw, v;
+
+	/*
+	 * Write to or clear ('data' == nil) 'len' bytes of the NIC
+	 * local memory at address 'addr'.
+	 * The destination address and count should be 32-bit aligned.
+	 */
+	v = 0;
+	while(len > 0){
+		/*
+		 * 1) Set the window. The (Lmwsz-1) bits are ignored
+		 *    in Wba when accessing through the local memory window;
+		 * 2) Find the minimum of how many bytes still to
+		 *    transfer and how many left in this window;
+		 * 3) Create the offset into the local memory window in the
+		 *    shared memory space then copy (or zero) the data;
+		 * 4) Bump the counts.
+		 */
+		csr32w(ctlr, Wba, addr);
+
+		l = ROUNDUP(addr+1, Lmwsz) - addr;
+		if(l > len)
+			l = len;
+
+		lmw = Lmw + (addr & (Lmwsz-1));
+		for(i = 0; i < l; i += 4){
+			if(data != nil)
+				v = *data++;
+			csr32w(ctlr, lmw+i, v);
+		}
+
+		len -= l;
+		addr += l;
+	}
+}
+
+static int
+ga620init(Ether* edev)
+{
+	Ctlr *ctlr;
+	Host64 host64;
+	int csr, ea, i, flags;
+
+	ctlr = edev->ctlr;
+
+	/*
+	 * Load the MAC address.
+	 */
+	ea = edev->ea[0]<<8 | edev->ea[1];
+	csr32w(ctlr, Mac, ea);
+	ea = edev->ea[2]<<24 | edev->ea[3]<<16 | edev->ea[4]<<8 | edev->ea[5];
+	csr32w(ctlr, Mac+4, ea);
+
+	/*
+	 * General Information Block.
+	 */
+	ctlr->gib = malloc(sizeof(Gib));
+	sethost64(&host64, ctlr->gib);
+	csr32w(ctlr, Gip, host64.hi);
+	csr32w(ctlr, Gip+4, host64.lo);
+
+	/*
+	 * Event Ring.
+	 * This is located in host memory. Allocate the ring,
+	 * tell the NIC where it is and initialise the indices.
+	 */
+	ctlr->er = malign(sizeof(Ere)*Ner);
+	sethost64(&ctlr->gib->ercb.addr, ctlr->er);
+	sethost64(&ctlr->gib->epp, ctlr->epi);
+	csr32w(ctlr, Eci, 0);
+
+	/*
+	 * Command Ring.
+	 * This is located in the General Communications Region
+	 * and so the value placed in the Rcb is unused, the NIC
+	 * knows where it is. Stick in the value according to
+	 * the datasheet anyway.
+	 * Initialise the ring and indices.
+	 */
+	ctlr->gib->crcb.addr.lo = Cr - 0x400;
+	for(i = 0; i < Ncr*4; i += 4)
+		csr32w(ctlr, Cr+i, 0);
+	csr32w(ctlr, Cpi, 0);
+	csr32w(ctlr, Cci, 0);
+
+	/*
+	 * Send Ring.
+	 * This ring is either in NIC memory at a fixed location depending
+	 * on how big the ring is or it is in host memory. If in NIC
+	 * memory it is accessed via the Local Memory Window; with a send
+	 * ring size of 128 the window covers the whole ring and then need
+	 * only be set once:
+	 *	ctlr->sr = (uchar*)ctlr->nic+Lmw;
+	 *	ga620lmw(ctlr, Sr, nil, sizeof(Sbd)*Nsr);
+	 *	ctlr->gib->srcb.addr.lo = Sr;
+	 * There is nowhere in the Sbd to hold the Block* associated
+	 * with this entry so an external array must be kept.
+	 */
+	ctlr->sr = malign(sizeof(Sbd)*Nsr);
+	sethost64(&ctlr->gib->srcb.addr, ctlr->sr);
+	if(ctlr->hardwarecksum)
+		flags = TcpUdpCksum|NoPseudoHdrCksum|HostRing;
+	else 
+		flags = HostRing;
+	if(ctlr->coalupdateonly) 
+		flags |= CoalUpdateOnly;
+	ctlr->gib->srcb.control = Nsr<<16 | flags;
+	sethost64(&ctlr->gib->scp, ctlr->sci);
+	csr32w(ctlr, Spi, 0);
+	ctlr->srb = malloc(sizeof(Block*)*Nsr);
+
+	/*
+	 * Receive Standard Ring.
+	 */
+	ctlr->rsr = malign(sizeof(Rbd)*Nrsr);
+	sethost64(&ctlr->gib->rsrcb.addr, ctlr->rsr);
+	if(ctlr->hardwarecksum)
+		flags = TcpUdpCksum|NoPseudoHdrCksum;
+	else
+		flags = 0;
+	ctlr->gib->rsrcb.control = (ETHERMAXTU+4)<<16 | flags;
+	csr32w(ctlr, Rspi, 0);
+
+	/*
+	 * Jumbo and Mini Rings. Unused for now.
+	 */
+	ctlr->gib->rjrcb.control = RingDisabled;
+	ctlr->gib->rmrcb.control = RingDisabled;
+
+	/*
+	 * Receive Return Ring.
+	 * This is located in host memory. Allocate the ring,
+	 * tell the NIC where it is and initialise the indices.
+	 */
+	ctlr->rrr = malign(sizeof(Rbd)*Nrrr);
+	sethost64(&ctlr->gib->rrrcb.addr, ctlr->rrr);
+	ctlr->gib->rrrcb.control = Nrrr<<16 | 0;
+	sethost64(&ctlr->gib->rrrpp, ctlr->rrrpi);
+	ctlr->rrrci = 0;
+
+	/*
+	 * Refresh Stats Pointer.
+	 * For now just point it at the existing statistics block.
+	 */
+	sethost64(&ctlr->gib->rsp, ctlr->gib->statistics);
+
+	/*
+	 * DMA configuration.
+	 * Use the recommended values.
+	 */
+	csr32w(ctlr, DMArc, 0x80);
+	csr32w(ctlr, DMAwc, 0x80);
+
+	/*
+	 * Transmit Buffer Ratio.
+	 * Set to 1/3 of available buffer space (units are 1/64ths)
+	 * if using Jumbo packets, ~64KB otherwise (assume 1MB on NIC).
+	 */
+	if(NrjrHI > 0 || Nsr > 128)
+		csr32w(ctlr, Tbr, 64/3);
+	else
+		csr32w(ctlr, Tbr, 4);
+
+	/*
+	 * Tuneable parameters.
+	 * These defaults are based on the tuning hints in the Alteon
+	 * Host/NIC Software Interface Definition and example software.
+	 */
+	ctlr->rct = 1 /*100*/;
+	csr32w(ctlr, Rct, ctlr->rct);
+	ctlr->sct = 0;
+	csr32w(ctlr, Sct, ctlr->sct);
+	ctlr->st = 1000000;
+	csr32w(ctlr, St, ctlr->st);
+	ctlr->smcbd = Nsr/4;
+	csr32w(ctlr, SmcBD, ctlr->smcbd);
+	ctlr->rmcbd = 4 /*6*/;
+	csr32w(ctlr, RmcBD, ctlr->rmcbd);
+
+	/*
+	 * Enable DMA Assist Logic.
+	 */
+	csr = csr32r(ctlr, DMAas) & ~0x03;
+	csr32w(ctlr, DMAas, csr|0x01);
+
+	/*
+	 * Link negotiation.
+	 * The bits are set here but the NIC must be given a command
+	 * once it is running to set negotiation in motion.
+	 */
+	csr32w(ctlr, Gln, Le|Lean|Lofc|Lfd|L1000MB|Lpref);
+	csr32w(ctlr, Fln, Le|Lean|Lhd|Lfd|L100MB|L10MB);
+
+	/*
+	 * A unique index for this controller and the maximum packet
+	 * length expected.
+	 * For now only standard packets are expected.
+	 */
+	csr32w(ctlr, Ifx, 1);
+	csr32w(ctlr, IfMTU, ETHERMAXTU+4);
+
+	/*
+	 * Enable Interrupts.
+	 * There are 3 ways to mask interrupts - a bit in the Mhc (which
+	 * is already cleared), the Mi register and the Hi mailbox.
+	 * Writing to the Hi mailbox has the side-effect of clearing the
+	 * PCI interrupt.
+	 */
+	csr32w(ctlr, Mi, 0);
+	csr32w(ctlr, Hi, 0);
+
+	/*
+	 * Start the firmware.
+	 */
+	csr32w(ctlr, CPUApc, tigon2FwStartAddr);
+	csr = csr32r(ctlr, CPUAstate) & ~CPUhalt;
+	csr32w(ctlr, CPUAstate, csr);
+
+	return 0;
+}
+
+static int
+at24c32io(Ctlr* ctlr, char* op, int data)
+{
+	char *lp, *p;
+	int i, loop, mlc, r;
+
+	mlc = csr32r(ctlr, Mlc);
+
+	r = 0;
+	loop = -1;
+	lp = nil;
+	for(p = op; *p != '\0'; p++){
+		switch(*p){
+		default:
+			return -1;
+		case ' ':
+			continue;
+		case ':':			/* start of 8-bit loop */
+			if(lp != nil)
+				return -1;
+			lp = p;
+			loop = 7;
+			continue;
+		case ';':			/* end of 8-bit loop */
+			if(lp == nil)
+				return -1;
+			loop--;
+			if(loop >= 0)
+				p = lp;
+			else
+				lp = nil;
+			continue;
+		case 'C':			/* assert clock */
+			mlc |= EEclk;
+			break;
+		case 'c':			/* deassert clock */
+			mlc &= ~EEclk;
+			break;
+		case 'D':			/* next bit in 'data' byte */
+			if(loop < 0)
+				return -1;
+			if(data & (1<<loop))
+				mlc |= EEdo;
+			else
+				mlc &= ~EEdo;
+			break;
+		case 'E':			/* enable data output */
+			mlc |= EEdoe;
+			break;
+		case 'e':			/* disable data output */
+			mlc &= ~EEdoe;
+			break;
+		case 'I':			/* input bit */
+			i = (csr32r(ctlr, Mlc) & EEdi) != 0;
+			if(loop >= 0)
+				r |= (i<<loop);
+			else
+				r = i;
+			continue;
+		case 'O':			/* assert data output */
+			mlc |= EEdo;
+			break;
+		case 'o':			/* deassert data output */
+			mlc &= ~EEdo;
+			break;
+		}
+		csr32w(ctlr, Mlc, mlc);
+		microdelay(1);
+	}
+	if(loop >= 0)
+		return -1;
+	return r;
+}
+
+static int
+at24c32r(Ctlr* ctlr, int addr)
+{
+	int data;
+
+	/*
+	 * Read a byte at address 'addr' from the Atmel AT24C32
+	 * Serial EEPROM. The 2-wire EEPROM access is controlled
+	 * by 4 bits in Mlc. See the AT24C32 datasheet for
+	 * protocol details.
+	 */
+	/*
+	 * Start condition - a high to low transition of data
+	 * with the clock high must precede any other command.
+	 */
+	at24c32io(ctlr, "OECoc", 0);
+
+	/*
+	 * Perform a random read at 'addr'. A dummy byte
+	 * write sequence is performed to clock in the device
+	 * and data word addresses (0 and 'addr' respectively).
+	 */
+	data = -1;
+	if(at24c32io(ctlr, "oE :DCc; oeCIc", 0xA0) != 0)
+		goto stop;
+	if(at24c32io(ctlr, "oE :DCc; oeCIc", addr>>8) != 0)
+		goto stop;
+	if(at24c32io(ctlr, "oE :DCc; oeCIc", addr) != 0)
+		goto stop;
+
+	/*
+	 * Now send another start condition followed by a
+	 * request to read the device. The EEPROM responds
+	 * by clocking out the data.
+	 */
+	at24c32io(ctlr, "OECoc", 0);
+	if(at24c32io(ctlr, "oE :DCc; oeCIc", 0xA1) != 0)
+		goto stop;
+	data = at24c32io(ctlr, ":CIc;", 0xA1);
+
+stop:
+	/*
+	 * Stop condition - a low to high transition of data
+	 * with the clock high is a stop condition. After a read
+	 * sequence, the stop command will place the EEPROM in
+	 * a standby power mode.
+	 */
+	at24c32io(ctlr, "oECOc", 0);
+
+	return data;
+}
+
+static int
+ga620detach(Ctlr* ctlr)
+{
+	int timeo;
+
+	/*
+	 * Hard reset (don't know which endian so catch both);
+	 * enable for little-endian mode;
+	 * wait for code to be loaded from serial EEPROM or flash;
+	 * make sure CPU A is halted.
+	 */
+	csr32w(ctlr, Mhc, Hr<<24 | Hr);
+	csr32w(ctlr, Mhc, (Eews|Ci)<<24 | Eews|Ci);
+
+	microdelay(1);
+	for(timeo = 0; timeo < 500000; timeo++){
+		if((csr32r(ctlr, CPUAstate) & (CPUhie|CPUrf)) == CPUhie)
+			break;
+		microdelay(1);
+	}
+	if((csr32r(ctlr, CPUAstate) & (CPUhie|CPUrf)) != CPUhie)
+		return -1;
+	csr32w(ctlr, CPUAstate, CPUhalt);
+
+	/*
+	 * After reset, CPU B seems to be stuck in 'CPUrf'.
+	 * Worry about it later.
+	 */
+	csr32w(ctlr, CPUBstate, CPUhalt);
+
+	return 0;
+}
+
+static void
+ga620shutdown(Ether* ether)
+{
+print("ga620shutdown\n");
+	ga620detach(ether->ctlr);
+}
+
+static int
+ga620reset(Ctlr* ctlr)
+{
+	int cls, csr, i, r;
+
+	if(ga620detach(ctlr) < 0)
+		return -1;
+
+	/*
+	 * Tigon 2 PCI NICs have 512KB SRAM per bank.
+	 * Clear out any lingering serial EEPROM state
+	 * bits.
+	 */
+	csr = csr32r(ctlr, Mlc) & ~(EEdi|EEdo|EEdoe|EEclk|SRAMmask);
+	csr32w(ctlr, Mlc, SRAM512|csr);
+	csr = csr32r(ctlr, Mc);
+	csr32w(ctlr, Mc, SyncSRAM|csr);
+
+	/*
+	 * Initialise PCI State register.
+	 * If PCI Write-and-Invalidate is enabled set the max write DMA
+	 * value to the host cache-line size (32 on Pentium or later).
+	 */
+	csr = csr32r(ctlr, Ps) & (PCI32|PCI66);
+	csr |= PCIwcmd|PCIrcmd|PCImrm;
+	if(ctlr->pcidev->pcr & 0x0010){
+		cls = pcicfgr8(ctlr->pcidev, PciCLS) * 4;
+		if(cls != 32)
+			pcicfgw8(ctlr->pcidev, PciCLS, 32/4);
+		csr |= PCIwm32;
+	}
+	csr32w(ctlr, Ps, csr);
+
+	/*
+	 * Operating Mode.
+	 */
+	csr32w(ctlr, Om, Fatal|NoJFrag|BswapDMA|WswapBD);
+
+	/*
+	 * Snarf the MAC address from the serial EEPROM.
+	 */
+	for(i = 0; i < Eaddrlen; i++){
+		if((r = at24c32r(ctlr, 0x8E+i)) == -1)
+			return -1;
+		ctlr->ea[i] = r;
+	}
+
+	/*
+	 * Load the firmware.
+	 */
+	ga620lmw(ctlr, tigon2FwTextAddr, tigon2FwText, tigon2FwTextLen);
+	ga620lmw(ctlr, tigon2FwRodataAddr, tigon2FwRodata, tigon2FwRodataLen);
+	ga620lmw(ctlr, tigon2FwDataAddr, tigon2FwData, tigon2FwDataLen);
+	ga620lmw(ctlr, tigon2FwSbssAddr, nil, tigon2FwSbssLen);
+	ga620lmw(ctlr, tigon2FwBssAddr, nil, tigon2FwBssLen);
+
+	/*
+	 * we will eventually get events telling us that the firmware is
+	 * up and that the link is up.
+	 */
+	return 0;
+}
+
+static void
+ga620pci(void)
+{
+	int port;
+	Pcidev *p;
+	Ctlr *ctlr;
+
+	p = nil;
+	while(p = pcimatch(p, 0, 0)){
+		if(p->ccrb != 0x02 || p->ccru != 0)
+			continue;
+
+		switch(p->did<<16 | p->vid){
+		default:
+			continue;
+		case 0x620A<<16 | 0x1385:	/* Netgear GA620 fiber */
+		case 0x630A<<16 | 0x1385:	/* Netgear GA620T copper */
+		case 0x0001<<16 | 0x12AE:	/* Alteon Acenic fiber
+						 * and DEC DEGPA-SA */
+		case 0x0002<<16 | 0x12AE:	/* Alteon Acenic copper */
+		case 0x0009<<16 | 0x10A9:	/* SGI Acenic */
+			break;
+		}
+
+		port = upamalloc(p->mem[0].bar & ~0x0F, p->mem[0].size, 0);
+		if(port == 0){
+			print("ga620: can't map %d @ 0x%8.8luX\n",
+				p->mem[0].size, p->mem[0].bar);
+			continue;
+		}
+
+		ctlr = malloc(sizeof(Ctlr));
+		ctlr->port = port;
+		ctlr->pcidev = p;
+		ctlr->id = p->did<<16 | p->vid;
+
+		ctlr->nic = KADDR(ctlr->port);
+		if(ga620reset(ctlr)){
+			free(ctlr);
+			continue;
+		}
+
+		if(ctlrhead != nil)
+			ctlrtail->next = ctlr;
+		else
+			ctlrhead = ctlr;
+		ctlrtail = ctlr;
+	}
+}
+
+int
+ga620pnp(Ether* edev)
+{
+	Ctlr *ctlr;
+	uchar ea[Eaddrlen];
+
+	if(ctlrhead == nil)
+		ga620pci();
+
+	/*
+	 * Any adapter matches if no edev->port is supplied,
+	 * otherwise the ports must match.
+	 */
+	for(ctlr = ctlrhead; ctlr != nil; ctlr = ctlr->next){
+		if(ctlr->active)
+			continue;
+		if(edev->port == 0 || edev->port == ctlr->port){
+			ctlr->active = 1;
+			break;
+		}
+	}
+	if(ctlr == nil)
+		return -1;
+
+	edev->ctlr = ctlr;
+	edev->port = ctlr->port;
+	edev->irq = ctlr->pcidev->intl;
+	edev->tbdf = ctlr->pcidev->tbdf;
+
+	/*
+	 * Check if the adapter's station address is to be overridden.
+	 * If not, read it from the EEPROM and set in ether->ea prior to
+	 * loading the station address in the hardware.
+	 */
+	memset(ea, 0, Eaddrlen);
+	if(memcmp(ea, edev->ea, Eaddrlen) == 0)
+		memmove(edev->ea, ctlr->ea, Eaddrlen);
+
+	ga620init(edev);		/* enables interrupts */
+
+	/*
+	 * Linkage to the generic ethernet driver.
+	 */
+	edev->attach = ga620attach;
+	edev->transmit = ga620transmit;
+	edev->interrupt = ga620interrupt;
+	edev->detach = ga620shutdown;
+	return 0;
+}
--- /dev/null
+++ b/os/boot.original/pc/etherga620fw.h
@@ -1,0 +1,4858 @@
+/* Generated by genfw.c */
+#define tigon2FwReleaseMajor 0xc
+#define tigon2FwReleaseMinor 0x4
+#define tigon2FwReleaseFix 0xb
+#define tigon2FwStartAddr 0x00004000
+#define tigon2FwTextAddr 0x00004000
+#define tigon2FwTextLen 0x11bc0
+#define tigon2FwRodataAddr 0x00015bc0
+#define tigon2FwRodataLen 0x10d0
+#define tigon2FwDataAddr 0x00016cc0
+#define tigon2FwDataLen 0x1c0
+#define tigon2FwSbssAddr 0x00016e80
+#define tigon2FwSbssLen 0xcc
+#define tigon2FwBssAddr 0x00016f50
+#define tigon2FwBssLen 0x20c0
+static int tigon2FwText[/*(MAX_TEXT_LEN/4) + 1*/] = {
+0x0, 
+0x10000003, 0x0, 0xd, 0xd, 
+0x3c1d0001, 0x8fbd6d20, 0x3a0f021, 0x3c100000, 
+0x26104000, 0xc0010c0, 0x0, 0xd, 
+0x3c1d0001, 0x8fbd6d24, 0x3a0f021, 0x3c100000, 
+0x26104000, 0xc0017e0, 0x0, 0xd, 
+0x0, 0x0, 0x0, 0x0, 
+0x0, 0x0, 0x0, 0x0, 
+0x0, 0x0, 0x0, 0x0, 
+0x0, 0x0, 0x0, 0x0, 
+0x0, 0x0, 0x0, 0x0, 
+0x0, 0x0, 0x0, 0x0, 
+0x0, 0x0, 0x0, 0x0, 
+0x0, 0x0, 0x0, 0x0, 
+0x0, 0x0, 0x0, 0x0, 
+0x0, 0x0, 0x0, 0x0, 
+0x0, 0x0, 0x0, 0x2000008, 
+0x0, 0x800172f, 0x3c0a0001, 0x800172f, 
+0x3c0a0002, 0x800172f, 0x0, 0x8002cac, 
+0x0, 0x8002c4f, 0x0, 0x800172f, 
+0x3c0a0004, 0x800328a, 0x0, 0x8001a52, 
+0x0, 0x800394d, 0x0, 0x80038f4, 
+0x0, 0x800172f, 0x3c0a0006, 0x80039bb, 
+0x3c0a0007, 0x800172f, 0x3c0a0008, 0x800172f, 
+0x3c0a0009, 0x8003a13, 0x0, 0x8002ea6, 
+0x0, 0x800172f, 0x3c0a000b, 0x800172f, 
+0x3c0a000c, 0x800172f, 0x3c0a000d, 0x80028fb, 
+0x0, 0x8002890, 0x0, 0x800172f, 
+0x3c0a000e, 0x800208c, 0x0, 0x8001964, 
+0x0, 0x8001a04, 0x0, 0x8003ca6, 
+0x0, 0x8003c94, 0x0, 0x800172f, 
+0x0, 0x800191a, 0x0, 0x800172f, 
+0x0, 0x800172f, 0x3c0a0013, 0x800172f, 
+0x3c0a0014, 0x0, 0x0, 0x0, 
+0x0, 0x0, 0x0, 0x0, 
+0x0, 0x0, 0x0, 0x0, 
+0x0, 0x0, 0x0, 0x0, 
+0x0, 0x0, 0x0, 0x0, 
+0x0, 0x0, 0x0, 0x0, 
+0x0, 0x0, 0x0, 0x0, 
+0x0, 0x0, 0x0, 0x0, 
+0x0, 0x0, 0x0, 0x0, 
+0x0, 0x0, 0x0, 0x0, 
+0x0, 0x0, 0x0, 0x0, 
+0x0, 0x0, 0x0, 0x0, 
+0x0, 0x0, 0x0, 0x0, 
+0x0, 0x0, 0x0, 0x0, 
+0x0, 0x0, 0x0, 0x0, 
+0x0, 0x0, 0x0, 0x27bdffe0, 
+0x3c1cc000, 0xafbf001c, 0xafb00018, 0x8f820140, 
+0x24030003, 0xaf8300ec, 0x34420004, 0xc002b20, 
+0xaf820140, 0x3c0100c0, 0xc001763, 0xac203ffc, 
+0x401821, 0x3c020010, 0x3c010001, 0xac236e9c, 
+0x10620011, 0x43102b, 0x14400002, 0x3c020020, 
+0x3c020008, 0x1062000c, 0x24050100, 0x3c060001, 
+0x8cc66e9c, 0x3c040001, 0x24845c74, 0x3821, 
+0xafa00010, 0xc002b3b, 0xafa00014, 0x3c020020, 
+0x3c010001, 0xac226e9c, 0x24020008, 0x3c010001, 
+0xac226eb4, 0x2402001f, 0x3c010001, 0xac226ec4, 
+0x24020016, 0x3c010001, 0xac226e98, 0x3c05fffe, 
+0x34a56f08, 0x3c020001, 0x8c426e9c, 0x3c030002, 
+0x24639010, 0x3c040001, 0x8c846cc4, 0x431023, 
+0x14800002, 0x458021, 0x2610fa38, 0x2402f000, 
+0x2028024, 0xc001785, 0x2002021, 0x2022823, 
+0x3c040020, 0x821823, 0x651823, 0x247bb000, 
+0x3c03fffe, 0x3463bf08, 0x363b821, 0x3c0600bf, 
+0x34c6f000, 0x3c070001, 0x8ce76cc0, 0x3c0300bf, 
+0x3463e000, 0x852023, 0x3c010001, 0xac246ea8, 
+0x822023, 0x3c010001, 0xac256e90, 0x52842, 
+0x3c010001, 0xac226e84, 0x27620ffc, 0x3c010001, 
+0xac226d20, 0x27621ffc, 0xdb3023, 0x7b1823, 
+0x3c010001, 0xac246e88, 0x3c010001, 0xac256eac, 
+0x3c010001, 0xac226d24, 0xaf860150, 0x10e00011, 
+0xaf830250, 0x3c1d0001, 0x8fbd6ccc, 0x3a0f021, 
+0xc001749, 0x0, 0x3c020001, 0x8c426cd0, 
+0x3c030001, 0x8c636cd4, 0x2442fe00, 0x24630200, 
+0x3c010001, 0xac226cd0, 0x3c010001, 0x10000004, 
+0xac236cd4, 0x3c1d0001, 0x8fbd6d20, 0x3a0f021, 
+0x3c020001, 0x8c426cc4, 0x1040000d, 0x26fafa38, 
+0x3c020001, 0x8c426cd0, 0x3c030001, 0x8c636cd4, 
+0x3c1a0001, 0x8f5a6cd4, 0x2442fa38, 0x246305c8, 
+0x3c010001, 0xac226cd0, 0x3c010001, 0xac236cd4, 
+0x3c020001, 0x8c426cc8, 0x14400003, 0x0, 
+0x3c010001, 0xac206cd0, 0xc001151, 0x0, 
+0x8fbf001c, 0x8fb00018, 0x3e00008, 0x27bd0020, 
+0x3c020001, 0x8c426cd0, 0x3c030001, 0x8c636cd4, 
+0x27bdff98, 0xafb00048, 0x3c100001, 0x8e1066b8, 
+0xafb20050, 0x3c120000, 0x26524100, 0xafbf0060, 
+0xafbe005c, 0xafb50058, 0xafb30054, 0xafb1004c, 
+0xafa20034, 0xafa30030, 0xafa00010, 0xafa00014, 
+0x8f860040, 0x3c040001, 0x24845c80, 0x24050200, 
+0x3c010001, 0xac326e80, 0xc002b3b, 0x2003821, 
+0x8f830040, 0x3c02f000, 0x621824, 0x3c026000, 
+0x1062000b, 0xa3a0003f, 0x240e0001, 0x3c040001, 
+0x24845c88, 0xa3ae003f, 0xafa00010, 0xafa00014, 
+0x8f860040, 0x24050300, 0xc002b3b, 0x2003821, 
+0x8f820240, 0x3c030001, 0x431025, 0xaf820240, 
+0xaf800048, 0x8f820048, 0x14400005, 0x0, 
+0xaf800048, 0x8f820048, 0x10400004, 0x0, 
+0xaf800048, 0x10000003, 0x2e02021, 0xaf80004c, 
+0x2e02021, 0x3c050001, 0xc002ba8, 0x34a540f8, 
+0x3402021, 0xc002ba8, 0x240505c8, 0x3c020001, 
+0x8c426ea8, 0x3c0d0001, 0x8dad6e88, 0x3c030001, 
+0x8c636e84, 0x3c080001, 0x8d086e90, 0x3c090001, 
+0x8d296eac, 0x3c0a0001, 0x8d4a6eb4, 0x3c0b0001, 
+0x8d6b6ec4, 0x3c0c0001, 0x8d8c6e98, 0x3c040001, 
+0x24845c94, 0x24050400, 0xaf42013c, 0x8f42013c, 
+0x24060001, 0x24070001, 0xaf400000, 0xaf4d0138, 
+0xaf430144, 0xaf480148, 0xaf49014c, 0xaf4a0150, 
+0xaf4b0154, 0xaf4c0158, 0x2442ff80, 0xaf420140, 
+0x24020001, 0xafa20010, 0xc002b3b, 0xafa00014, 
+0x8f420138, 0xafa20010, 0x8f42013c, 0xafa20014, 
+0x8f460144, 0x8f470148, 0x3c040001, 0x24845ca0, 
+0xc002b3b, 0x24050500, 0xafb70010, 0xafba0014, 
+0x8f46014c, 0x8f470150, 0x3c040001, 0x24845cac, 
+0xc002b3b, 0x24050600, 0x3c020001, 0x8c426e9c, 
+0x3603821, 0x3c060002, 0x24c69010, 0x2448ffff, 
+0x1061824, 0xe81024, 0x43102b, 0x10400006, 
+0x24050900, 0x3c040001, 0x24845cb8, 0xafa80010, 
+0xc002b3b, 0xafa00014, 0x8f82000c, 0xafa20010, 
+0x8f82003c, 0xafa20014, 0x8f860000, 0x8f870004, 
+0x3c040001, 0x24845cc4, 0xc002b3b, 0x24051000, 
+0x8c020220, 0x8c030224, 0x8c060218, 0x8c07021c, 
+0x3c040001, 0x24845ccc, 0x24051100, 0xafa20010, 
+0xc002b3b, 0xafa30014, 0xaf800054, 0xaf80011c, 
+0x8c020218, 0x30420002, 0x10400009, 0x0, 
+0x8c020220, 0x3c030002, 0x34630004, 0x431025, 
+0xaf42000c, 0x8c02021c, 0x10000008, 0x34420004, 
+0x8c020220, 0x3c030002, 0x34630006, 0x431025, 
+0xaf42000c, 0x8c02021c, 0x34420006, 0xaf420014, 
+0x8c020218, 0x30420010, 0x1040000a, 0x0, 
+0x8c02021c, 0x34420004, 0xaf420010, 0x8c020220, 
+0x3c03000a, 0x34630004, 0x431025, 0x10000009, 
+0xaf420008, 0x8c020220, 0x3c03000a, 0x34630006, 
+0x431025, 0xaf420008, 0x8c02021c, 0x34420006, 
+0xaf420010, 0x24020001, 0xaf8200a0, 0xaf8200b0, 
+0x8f830054, 0x8f820054, 0xaf8000d0, 0xaf8000c0, 
+0x10000002, 0x24630064, 0x8f820054, 0x621023, 
+0x2c420065, 0x1440fffc, 0x0, 0x8c040208, 
+0x8c05020c, 0x26e20028, 0xaee20020, 0x24020490, 
+0xaee20010, 0xaee40008, 0xaee5000c, 0x26e40008, 
+0x8c820000, 0x8c830004, 0xaf820090, 0xaf830094, 
+0x8c820018, 0xaf8200b4, 0x9482000a, 0xaf82009c, 
+0x8f420014, 0xaf8200b0, 0x8f8200b0, 0x30420004, 
+0x1440fffd, 0x0, 0x8f8200b0, 0x3c03ef00, 
+0x431024, 0x10400021, 0x0, 0x8f8200b4, 
+0xafa20010, 0x8f820090, 0x8f830094, 0x3c040001, 
+0x24845cd4, 0xafa30014, 0x8f8600b0, 0x8f87009c, 
+0x3c050001, 0xc002b3b, 0x34a5200d, 0x3c040001, 
+0x24845ce0, 0x240203c0, 0xafa20010, 0xafa00014, 
+0x8f860144, 0x3c070001, 0x24e75ce8, 0xc002b3b, 
+0x3405dead, 0x8f82011c, 0x34420002, 0xaf82011c, 
+0x8f820220, 0x34420004, 0xaf820220, 0x8f820140, 
+0x3c030001, 0x431025, 0xaf820140, 0x96e20472, 
+0x96e60452, 0x96e70462, 0xafa20010, 0x96e20482, 
+0x3c040001, 0x24845d14, 0x24051200, 0xc002b3b, 
+0xafa20014, 0x96f00452, 0x32020001, 0x10400002, 
+0xb021, 0x24160001, 0x32020002, 0x54400001, 
+0x36d60002, 0x32020008, 0x54400001, 0x36d60004, 
+0x32020010, 0x54400001, 0x36d60008, 0x32020020, 
+0x54400001, 0x36d60010, 0x32020040, 0x54400001, 
+0x36d60020, 0x32020080, 0x54400001, 0x36d60040, 
+0x96e60482, 0x30c20200, 0x54400001, 0x36d64000, 
+0x96e30472, 0x30620200, 0x10400003, 0x30620100, 
+0x10000003, 0x36d62000, 0x54400001, 0x36d61000, 
+0x96f00462, 0x32c24000, 0x14400004, 0x3207009b, 
+0x30c2009b, 0x14e20007, 0x240e0001, 0x32c22000, 
+0x1440000d, 0x32020001, 0x3062009b, 0x10e20009, 
+0x240e0001, 0x3c040001, 0x24845d20, 0x24051300, 
+0x2003821, 0xa3ae003f, 0xafa30010, 0xc002b3b, 
+0xafa00014, 0x32020001, 0x54400001, 0x36d60080, 
+0x32020002, 0x54400001, 0x36d60100, 0x32020008, 
+0x54400001, 0x36d60200, 0x32020010, 0x54400001, 
+0x36d60400, 0x32020080, 0x54400001, 0x36d60800, 
+0x8c020218, 0x30420200, 0x10400002, 0x3c020008, 
+0x2c2b025, 0x8c020218, 0x30420800, 0x10400002, 
+0x3c020080, 0x2c2b025, 0x8c020218, 0x30420400, 
+0x10400002, 0x3c020100, 0x2c2b025, 0x8c020218, 
+0x30420100, 0x10400002, 0x3c020200, 0x2c2b025, 
+0x8c020218, 0x30420080, 0x10400002, 0x3c020400, 
+0x2c2b025, 0x8c020218, 0x30422000, 0x10400002, 
+0x3c020010, 0x2c2b025, 0x8c020218, 0x30424000, 
+0x10400002, 0x3c020020, 0x2c2b025, 0x8c020218, 
+0x30421000, 0x10400002, 0x3c020040, 0x2c2b025, 
+0x8ee20498, 0x8ee3049c, 0xaf420160, 0xaf430164, 
+0x8ee204a0, 0x8ee304a4, 0xaf420168, 0xaf43016c, 
+0x8ee204a8, 0x8ee304ac, 0xaf420170, 0xaf430174, 
+0x8ee20428, 0x8ee3042c, 0xaf420178, 0xaf43017c, 
+0x8ee20448, 0x8ee3044c, 0xaf420180, 0xaf430184, 
+0x8ee20458, 0x8ee3045c, 0xaf420188, 0xaf43018c, 
+0x8ee20468, 0x8ee3046c, 0xaf420190, 0xaf430194, 
+0x8ee20478, 0x8ee3047c, 0xaf420198, 0xaf43019c, 
+0x8ee20488, 0x8ee3048c, 0xaf4201a0, 0xaf4301a4, 
+0x8ee204b0, 0x8ee304b4, 0x24040080, 0xaf4201a8, 
+0xaf4301ac, 0xc002ba8, 0x24050080, 0x8c02025c, 
+0x27440224, 0xaf4201f0, 0x8c020260, 0x24050200, 
+0x24060008, 0xc002bbf, 0xaf4201f8, 0x3c043b9a, 
+0x3484ca00, 0x3821, 0x24020006, 0x24030002, 
+0xaf4201f4, 0x240203e8, 0xaf430204, 0xaf430200, 
+0xaf4401fc, 0xaf420294, 0x24020001, 0xaf430290, 
+0xaf42029c, 0x3c030001, 0x671821, 0x90636cd8, 
+0x3471021, 0x24e70001, 0xa043022c, 0x2ce2000f, 
+0x1440fff8, 0x3471821, 0x24e70001, 0x3c080001, 
+0x350840f8, 0x8f820040, 0x3c040001, 0x24845d2c, 
+0x24051400, 0x21702, 0x24420030, 0xa062022c, 
+0x3471021, 0xa040022c, 0x8c070218, 0x2c03021, 
+0x240205c8, 0xafa20010, 0xc002b3b, 0xafa80014, 
+0x3c040001, 0x24845d38, 0x3c050000, 0x24a55c80, 
+0x24060010, 0x27b10030, 0x2203821, 0x27b30034, 
+0xc0017a3, 0xafb30010, 0x3c030001, 0x8c636cc8, 
+0x1060000a, 0x408021, 0x8fa30030, 0x2405ff00, 
+0x8fa20034, 0x246400ff, 0x852024, 0x831823, 
+0x431023, 0xafa20034, 0xafa40030, 0x3c040001, 
+0x24845d44, 0x3c050000, 0x24a54100, 0x24060108, 
+0x2203821, 0xc0017a3, 0xafb30010, 0x409021, 
+0x32c20003, 0x3c010001, 0xac326e80, 0x10400045, 
+0x2203821, 0x8f820050, 0x3c030010, 0x431024, 
+0x10400016, 0x0, 0x8c020218, 0x30420040, 
+0x1040000f, 0x24020001, 0x8f820050, 0x8c030218, 
+0x240e0001, 0x3c040001, 0x24845d50, 0xa3ae003f, 
+0xafa20010, 0xafa30014, 0x8f870040, 0x24051500, 
+0xc002b3b, 0x2c03021, 0x10000004, 0x0, 
+0x3c010001, 0x370821, 0xa02240f4, 0x3c040001, 
+0x24845d5c, 0x3c050001, 0x24a55b40, 0x3c060001, 
+0x24c65bac, 0xc53023, 0x8f420010, 0x27b30030, 
+0x2603821, 0x27b10034, 0x34420a00, 0xaf420010, 
+0xc0017a3, 0xafb10010, 0x3c040001, 0x24845d70, 
+0x3c050001, 0x24a5b714, 0x3c060001, 0x24c6ba90, 
+0xc53023, 0x2603821, 0xaf420108, 0xc0017a3, 
+0xafb10010, 0x3c040001, 0x24845d8c, 0x3c050001, 
+0x24a5be58, 0x3c060001, 0x24c6c900, 0xc53023, 
+0x2603821, 0x3c010001, 0xac226ef4, 0xc0017a3, 
+0xafb10010, 0x3c040001, 0x24845da4, 0x10000024, 
+0x24051600, 0x3c040001, 0x24845dac, 0x3c050001, 
+0x24a5a10c, 0x3c060001, 0x24c6a238, 0xc53023, 
+0xc0017a3, 0xafb30010, 0x3c040001, 0x24845dbc, 
+0x3c050001, 0x24a5b2b0, 0x3c060001, 0x24c6b70c, 
+0xc53023, 0x2203821, 0xaf420108, 0xc0017a3, 
+0xafb30010, 0x3c040001, 0x24845dd0, 0x3c050001, 
+0x24a5ba98, 0x3c060001, 0x24c6be50, 0xc53023, 
+0x2203821, 0x3c010001, 0xac226ef4, 0xc0017a3, 
+0xafb30010, 0x3c040001, 0x24845de4, 0x24051650, 
+0x2c03021, 0x3821, 0x3c010001, 0xac226ef8, 
+0xafa00010, 0xc002b3b, 0xafa00014, 0x32c20020, 
+0x10400021, 0x27a70030, 0x3c040001, 0x24845df0, 
+0x3c050001, 0x24a5b13c, 0x3c060001, 0x24c6b2a8, 
+0xc53023, 0x24022000, 0xaf42001c, 0x27a20034, 
+0xc0017a3, 0xafa20010, 0x21900, 0x31982, 
+0x3c040800, 0x641825, 0xae430028, 0x24030010, 
+0xaf43003c, 0x96e30450, 0xaf430040, 0x8f430040, 
+0x3c040001, 0x24845e04, 0xafa00014, 0xafa30010, 
+0x8f47001c, 0x24051660, 0x3c010001, 0xac226ef0, 
+0x10000025, 0x32c60020, 0x8ee20448, 0x8ee3044c, 
+0xaf43001c, 0x8f42001c, 0x2442e000, 0x2c422001, 
+0x1440000a, 0x240e0001, 0x3c040001, 0x24845e10, 
+0xa3ae003f, 0xafa00010, 0xafa00014, 0x8f46001c, 
+0x24051700, 0xc002b3b, 0x3821, 0x3c020000, 
+0x24425cbc, 0x21100, 0x21182, 0x3c030800, 
+0x431025, 0xae420028, 0x24020008, 0xaf42003c, 
+0x96e20450, 0xaf420040, 0x8f420040, 0x3c040001, 
+0x24845e1c, 0xafa00014, 0xafa20010, 0x8f47001c, 
+0x24051800, 0x32c60020, 0xc002b3b, 0x0, 
+0x3c050fff, 0x3c030001, 0x8c636ef4, 0x34a5ffff, 
+0x2403021, 0x3c020001, 0x8c426ef8, 0x3c040800, 
+0x651824, 0x31882, 0x641825, 0x451024, 
+0x21082, 0x441025, 0xacc20080, 0x32c20180, 
+0x10400056, 0xacc30020, 0x8f82005c, 0x3c030080, 
+0x431024, 0x1040000d, 0x0, 0x8f820050, 
+0xafa20010, 0x8f82005c, 0x240e0001, 0x3c040001, 
+0x24845e28, 0xa3ae003f, 0xafa20014, 0x8f870040, 
+0x24051900, 0xc002b3b, 0x2c03021, 0x8f820050, 
+0x3c030010, 0x431024, 0x10400016, 0x0, 
+0x8c020218, 0x30420040, 0x1040000f, 0x24020001, 
+0x8f820050, 0x8c030218, 0x240e0001, 0x3c040001, 
+0x24845d50, 0xa3ae003f, 0xafa20010, 0xafa30014, 
+0x8f870040, 0x24052000, 0xc002b3b, 0x2c03021, 
+0x10000004, 0x0, 0x3c010001, 0x370821, 
+0xa02240f4, 0x3c040001, 0x24845e34, 0x3c050001, 
+0x24a55ac0, 0x3c060001, 0x24c65b38, 0xc53023, 
+0x8f420008, 0x27b30030, 0x2603821, 0x27b10034, 
+0x34420e00, 0xaf420008, 0xc0017a3, 0xafb10010, 
+0x3c040001, 0x24845e4c, 0x3c050001, 0x24a5d8b4, 
+0x3c060001, 0x24c6e3c8, 0xc53023, 0x2603821, 
+0xaf42010c, 0xc0017a3, 0xafb10010, 0x3c040001, 
+0x24845e64, 0x3c050001, 0x24a5e9ac, 0x3c060001, 
+0x24c6f0f0, 0xc53023, 0x2603821, 0x3c010001, 
+0xac226f04, 0xc0017a3, 0xafb10010, 0x3c040001, 
+0x24845e7c, 0x10000027, 0x24052100, 0x3c040001, 
+0x24845e84, 0x3c050001, 0x24a59fc8, 0x3c060001, 
+0x24c6a104, 0xc53023, 0x27b10030, 0x2203821, 
+0x27b30034, 0xc0017a3, 0xafb30010, 0x3c040001, 
+0x24845e94, 0x3c050001, 0x24a5cad4, 0x3c060001, 
+0x24c6d8ac, 0xc53023, 0x2203821, 0xaf42010c, 
+0xc0017a3, 0xafb30010, 0x3c040001, 0x24845ea4, 
+0x3c050001, 0x24a5e84c, 0x3c060001, 0x24c6e9a4, 
+0xc53023, 0x2203821, 0x3c010001, 0xac226f04, 
+0xc0017a3, 0xafb30010, 0x3c040001, 0x24845eb8, 
+0x24052150, 0x2c03021, 0x3821, 0x3c010001, 
+0xac226f10, 0xafa00010, 0xc002b3b, 0xafa00014, 
+0x3c110fff, 0x3c030001, 0x8c636f04, 0x3631ffff, 
+0x2409821, 0x3c020001, 0x8c426f10, 0x3c0e0800, 
+0x711824, 0x31882, 0x6e1825, 0x511024, 
+0x21082, 0x4e1025, 0xae630038, 0xae620078, 
+0x8c020218, 0x30420040, 0x14400004, 0x24020001, 
+0x3c010001, 0x370821, 0xa02240f4, 0x3c040001, 
+0x24845ec4, 0x3c050001, 0x24a5e3d0, 0x3c060001, 
+0x24c6e52c, 0xc53023, 0x27be0030, 0x3c03821, 
+0x27b50034, 0xc0017a3, 0xafb50010, 0x3c010001, 
+0xac226efc, 0x511024, 0x21082, 0x3c0e0800, 
+0x4e1025, 0xae620050, 0x32c22000, 0x10400006, 
+0x3c03821, 0x3c020000, 0x24425cbc, 0x2221024, 
+0x1000000f, 0x21082, 0x3c040001, 0x24845ed8, 
+0x3c050001, 0x24a5e534, 0x3c060001, 0x24c6e6e4, 
+0xc53023, 0xc0017a3, 0xafb50010, 0x3c010001, 
+0xac226f14, 0x511024, 0x21082, 0x3c0e0800, 
+0x4e1025, 0xae620048, 0x32c24000, 0x10400005, 
+0x27a70030, 0x3c020000, 0x24425cbc, 0x1000000e, 
+0x21100, 0x3c040001, 0x24845ef0, 0x3c050001, 
+0x24a5e6ec, 0x3c060001, 0x24c6e844, 0xc53023, 
+0x27a20034, 0xc0017a3, 0xafa20010, 0x3c010001, 
+0xac226f08, 0x21100, 0x21182, 0x3c030800, 
+0x431025, 0xae420060, 0x3c040001, 0x24845f08, 
+0x3c050001, 0x24a58230, 0x3c060001, 0x24c68650, 
+0xc53023, 0x27b10030, 0x2203821, 0x27b30034, 
+0xc0017a3, 0xafb30010, 0x3c0e0fff, 0x35ceffff, 
+0x3c040001, 0x24845f14, 0x3c050000, 0x24a56468, 
+0x3c060000, 0x24c66588, 0xc53023, 0x2203821, 
+0x240f021, 0x3c010001, 0xac226edc, 0x4e1024, 
+0x21082, 0x3c150800, 0x551025, 0xafae0044, 
+0xafc200b8, 0xc0017a3, 0xafb30010, 0x3c040001, 
+0x24845f20, 0x3c050000, 0x24a56590, 0x3c060000, 
+0x24c66808, 0x8fae0044, 0xc53023, 0x2203821, 
+0x3c010001, 0xac226ed0, 0x4e1024, 0x21082, 
+0x551025, 0xafc200e8, 0xc0017a3, 0xafb30010, 
+0x3c040001, 0x24845f38, 0x3c050000, 0x24a56810, 
+0x3c060000, 0x24c66940, 0x8fae0044, 0xc53023, 
+0x2203821, 0x3c010001, 0xac226ec8, 0x4e1024, 
+0x21082, 0x551025, 0xafc200c0, 0xc0017a3, 
+0xafb30010, 0x3c040001, 0x24845f50, 0x3c050001, 
+0x24a5fad0, 0x3c060001, 0x24c6fba8, 0x8fae0044, 
+0xc53023, 0x2203821, 0x3c010001, 0xac226ed4, 
+0x4e1024, 0x21082, 0x551025, 0xafc200c8, 
+0xc0017a3, 0xafb30010, 0x3c040001, 0x24845f5c, 
+0x3c050001, 0x24a5c93c, 0x3c060001, 0x24c6ca20, 
+0xc53023, 0x2203821, 0xaf420110, 0xc0017a3, 
+0xafb30010, 0x3c040001, 0x24845f6c, 0x3c050001, 
+0x24a5c910, 0x3c060001, 0x24c6c934, 0xc53023, 
+0x2203821, 0xaf420124, 0xc0017a3, 0xafb30010, 
+0x3c040001, 0x24845f7c, 0x3c050001, 0x24a55a80, 
+0x3c060001, 0x24c65aac, 0xc53023, 0x2203821, 
+0xaf420120, 0xaf420114, 0xc0017a3, 0xafb30010, 
+0x3c040001, 0x24845f88, 0x3c050001, 0x24a5f298, 
+0x3c060001, 0x24c6f6b4, 0xc53023, 0x2203821, 
+0xaf420118, 0xc0017a3, 0xafb30010, 0x8fae0044, 
+0x3c010001, 0xac226f18, 0x4e1024, 0x21082, 
+0x551025, 0xc003fc3, 0xafc200d0, 0xc003c40, 
+0x0, 0xc0027a8, 0x0, 0xac000228, 
+0xac00022c, 0x96e20450, 0x2442ffff, 0xaf420038, 
+0x96e20460, 0xaf420080, 0x32c24000, 0x14400003, 
+0x0, 0x96e20480, 0xaf420084, 0x96e70490, 
+0x50e00001, 0x24070800, 0x24e2ffff, 0xaf420088, 
+0xaf42007c, 0x24020800, 0x10e2000f, 0x32c24000, 
+0x10400003, 0x24020400, 0x10e2000b, 0x0, 
+0x240e0001, 0x3c040001, 0x24845f98, 0xa3ae003f, 
+0x96e60490, 0x24052170, 0x2c03821, 0xafa00010, 
+0xc002b3b, 0xafa00014, 0x8f430138, 0x8f440138, 
+0x24020001, 0xa34205c2, 0xaf430094, 0xaf440098, 
+0xafa00010, 0xafa00014, 0x8f460080, 0x8f470084, 
+0x3c040001, 0x24845fa4, 0xc002b3b, 0x24052200, 
+0xc0024a4, 0x3c110800, 0x3c1433d8, 0x3694cb58, 
+0x3c020800, 0x34420080, 0x3c040001, 0x24845fb0, 
+0x3c050000, 0x24a55d00, 0x3c060000, 0x24c65d1c, 
+0xc53023, 0x27a70030, 0xaf820060, 0x2402ffff, 
+0xaf820064, 0x27a20034, 0xc0017a3, 0xafa20010, 
+0x3c010001, 0xac226eb8, 0x21100, 0x21182, 
+0x511025, 0xc0018fc, 0xae420000, 0x8f820240, 
+0x3c030001, 0x431025, 0xaf820240, 0x3c020000, 
+0x24424034, 0xaf820244, 0xaf800240, 0x8f820060, 
+0x511024, 0x14400005, 0x3c030800, 0x8f820060, 
+0x431024, 0x1040fffd, 0x0, 0xc003c4d, 
+0x8821, 0x3c020100, 0xafa20020, 0x8f530018, 
+0x240200ff, 0x56620001, 0x26710001, 0x8c020228, 
+0x1622000e, 0x1330c0, 0x8f42033c, 0x24420001, 
+0xaf42033c, 0x8f42033c, 0x8c020228, 0x3c040001, 
+0x24845c24, 0x3c050009, 0xafa00014, 0xafa20010, 
+0x8fa60020, 0x1000003f, 0x34a50100, 0xd71021, 
+0x8fa30020, 0x8fa40024, 0xac4304c0, 0xac4404c4, 
+0xc01821, 0x8f440178, 0x8f45017c, 0x1021, 
+0x24070004, 0xafa70010, 0xafb10014, 0x8f48000c, 
+0x24c604c0, 0x2e63021, 0xafa80018, 0x8f48010c, 
+0x24070008, 0xa32821, 0xa3482b, 0x822021, 
+0x100f809, 0x892021, 0x1440000b, 0x24070008, 
+0x8f820120, 0xafa20010, 0x8f820124, 0x3c040001, 
+0x24845c2c, 0x3c050009, 0xafa20014, 0x8fa60020, 
+0x1000001c, 0x34a50200, 0x8f440160, 0x8f450164, 
+0x8f43000c, 0xaf510018, 0x8f860120, 0x24020010, 
+0xafa20010, 0xafb10014, 0xafa30018, 0x8f42010c, 
+0x40f809, 0x24c6001c, 0x14400010, 0x0, 
+0x8f420340, 0x24420001, 0xaf420340, 0x8f420340, 
+0x8f820120, 0xafa20010, 0x8f820124, 0x3c040001, 
+0x24845c34, 0x3c050009, 0xafa20014, 0x8fa60020, 
+0x34a50300, 0xc002b3b, 0x2603821, 0x8f4202e4, 
+0x24420001, 0xaf4202e4, 0x8f4202e4, 0x93a2003f, 
+0x10400069, 0x3c020700, 0x34423000, 0xafa20028, 
+0x8f530018, 0x240200ff, 0x12620002, 0x8821, 
+0x26710001, 0x8c020228, 0x1622000e, 0x1330c0, 
+0x8f42033c, 0x24420001, 0xaf42033c, 0x8f42033c, 
+0x8c020228, 0x3c040001, 0x24845c24, 0x3c050009, 
+0xafa00014, 0xafa20010, 0x8fa60028, 0x1000003f, 
+0x34a50100, 0xd71021, 0x8fa30028, 0x8fa4002c, 
+0xac4304c0, 0xac4404c4, 0xc01821, 0x8f440178, 
+0x8f45017c, 0x1021, 0x24070004, 0xafa70010, 
+0xafb10014, 0x8f48000c, 0x24c604c0, 0x2e63021, 
+0xafa80018, 0x8f48010c, 0x24070008, 0xa32821, 
+0xa3482b, 0x822021, 0x100f809, 0x892021, 
+0x1440000b, 0x24070008, 0x8f820120, 0xafa20010, 
+0x8f820124, 0x3c040001, 0x24845c2c, 0x3c050009, 
+0xafa20014, 0x8fa60028, 0x1000001c, 0x34a50200, 
+0x8f440160, 0x8f450164, 0x8f43000c, 0xaf510018, 
+0x8f860120, 0x24020010, 0xafa20010, 0xafb10014, 
+0xafa30018, 0x8f42010c, 0x40f809, 0x24c6001c, 
+0x14400010, 0x0, 0x8f420340, 0x24420001, 
+0xaf420340, 0x8f420340, 0x8f820120, 0xafa20010, 
+0x8f820124, 0x3c040001, 0x24845c34, 0x3c050009, 
+0xafa20014, 0x8fa60028, 0x34a50300, 0xc002b3b, 
+0x2603821, 0x8f4202f0, 0x24420001, 0xaf4202f0, 
+0x8f4202f0, 0x3c040001, 0x24845fc0, 0xafa00010, 
+0xafa00014, 0x8fa60028, 0x24052300, 0xc002b3b, 
+0x3821, 0x10000004, 0x0, 0x8c020264, 
+0x10400005, 0x0, 0x8f8200a0, 0x30420004, 
+0x1440fffa, 0x0, 0x8f820044, 0x34420004, 
+0xaf820044, 0x8f420308, 0x24420001, 0xaf420308, 
+0x8f420308, 0x8f8200d8, 0x8f8300d4, 0x431023, 
+0x2442ff80, 0xaf420090, 0x8f420090, 0x2842ff81, 
+0x10400006, 0x24020001, 0x8f420090, 0x8f430144, 
+0x431021, 0xaf420090, 0x24020001, 0xaf42008c, 
+0x32c20008, 0x10400006, 0x0, 0x8f820214, 
+0x3c038100, 0x3042ffff, 0x431025, 0xaf820214, 
+0x3c030001, 0x8c636d94, 0x30620002, 0x10400009, 
+0x30620001, 0x3c040001, 0x24845fcc, 0x3c050000, 
+0x24a56d50, 0x3c060000, 0x24c671c8, 0x10000012, 
+0xc53023, 0x10400009, 0x0, 0x3c040001, 
+0x24845fdc, 0x3c050000, 0x24a571d0, 0x3c060000, 
+0x24c67678, 0x10000008, 0xc53023, 0x3c040001, 
+0x24845fec, 0x3c050000, 0x24a56948, 0x3c060000, 
+0x24c66d48, 0xc53023, 0x27a70030, 0x27a20034, 
+0xc0017a3, 0xafa20010, 0x3c010001, 0xac226ecc, 
+0x3c020001, 0x8c426ecc, 0x3c030800, 0x21100, 
+0x21182, 0x431025, 0xae420040, 0x8f8200a0, 
+0xafa20010, 0x8f8200b0, 0xafa20014, 0x8f86005c, 
+0x8f87011c, 0x3c040001, 0x24845ffc, 0x3c010001, 
+0xac366ea4, 0x3c010001, 0xac206e94, 0x3c010001, 
+0xac3c6e8c, 0x3c010001, 0xac3b6ebc, 0x3c010001, 
+0xac376ec0, 0x3c010001, 0xac3a6ea0, 0xc002b3b, 
+0x24052400, 0x8f820200, 0xafa20010, 0x8f820220, 
+0xafa20014, 0x8f860044, 0x8f870050, 0x3c040001, 
+0x24846008, 0xc002b3b, 0x24052500, 0x8f830060, 
+0x74100b, 0x242000a, 0x200f821, 0x0, 
+0xd, 0x8fbf0060, 0x8fbe005c, 0x8fb50058, 
+0x8fb30054, 0x8fb20050, 0x8fb1004c, 0x8fb00048, 
+0x3e00008, 0x27bd0068, 0x27bdffe0, 0x3c040001, 
+0x24846014, 0x24052600, 0x3021, 0x3821, 
+0xafbf0018, 0xafa00010, 0xc002b3b, 0xafa00014, 
+0x8fbf0018, 0x3e00008, 0x27bd0020, 0x3e00008, 
+0x0, 0x3e00008, 0x0, 0x0, 
+0x0, 0x0, 0x0, 0x0, 
+0x3e00008, 0x0, 0x3e00008, 0x0, 
+0x27bdfde0, 0x27a50018, 0x3c04dead, 0x3484beef, 
+0xafbf0218, 0x8f820150, 0x3c03001f, 0x3463ffff, 
+0xafa40018, 0xa22823, 0xa32824, 0x8ca20000, 
+0x1044000a, 0x0, 0xafa50010, 0x8ca20000, 
+0xafa20014, 0x8f860150, 0x8f870250, 0x3c040001, 
+0x2484601c, 0xc002b3b, 0x24052700, 0x8fbf0218, 
+0x3e00008, 0x27bd0220, 0x27bdffe0, 0x3c06abba, 
+0x34c6babe, 0xafb00018, 0x3c100004, 0x3c07007f, 
+0x34e7ffff, 0xafbf001c, 0x102840, 0x8e040000, 
+0x8ca30000, 0xaca00000, 0xae060000, 0x8ca20000, 
+0xaca30000, 0x10460005, 0xae040000, 0xa08021, 
+0xf0102b, 0x1040fff5, 0x102840, 0x3c040001, 
+0x24846028, 0x24052800, 0x2003021, 0x3821, 
+0xafa00010, 0xc002b3b, 0xafa00014, 0x2001021, 
+0x8fbf001c, 0x8fb00018, 0x3e00008, 0x27bd0020, 
+0x8c020224, 0x3047003f, 0x10e00010, 0x803021, 
+0x2821, 0x24030020, 0xe31024, 0x10400002, 
+0x63042, 0xa62821, 0x31842, 0x1460fffb, 
+0xe31024, 0x2402f000, 0xa22824, 0x3402ffff, 
+0x45102b, 0x14400003, 0x3c020001, 0x10000008, 
+0x3c020001, 0x3442ffff, 0x851823, 0x43102b, 
+0x14400003, 0xa01021, 0x3c02fffe, 0x821021, 
+0x3e00008, 0x0, 0x27bdffd0, 0xafb50028, 
+0x8fb50040, 0xafb20020, 0xa09021, 0xafb1001c, 
+0x24c60003, 0xafbf002c, 0xafb30024, 0xafb00018, 
+0x8ea20000, 0x2403fffc, 0xc38024, 0x50102b, 
+0x1440001b, 0xe08821, 0x8e330000, 0xafb00010, 
+0x8ea20000, 0xafa20014, 0x8e270000, 0x24053000, 
+0xc002b3b, 0x2403021, 0x8e230000, 0x702021, 
+0x64102b, 0x10400007, 0x2402821, 0x8ca20000, 
+0xac620000, 0x24630004, 0x64102b, 0x1440fffb, 
+0x24a50004, 0x8ea20000, 0x501023, 0xaea20000, 
+0x8e220000, 0x501021, 0x1000000b, 0xae220000, 
+0x2402002d, 0xa0820000, 0xafb00010, 0x8ea20000, 
+0x2409821, 0xafa20014, 0x8e270000, 0x24053100, 
+0xc002b3b, 0x2603021, 0x2601021, 0x8fbf002c, 
+0x8fb50028, 0x8fb30024, 0x8fb20020, 0x8fb1001c, 
+0x8fb00018, 0x3e00008, 0x27bd0030, 0x27bdffe8, 
+0x3c1cc000, 0x3c05fffe, 0x3c030001, 0x8c636e84, 
+0x3c040001, 0x8c846e90, 0x34a5bf08, 0x24021ffc, 
+0x3c010001, 0xac226cd0, 0x3c0200c0, 0x3c010001, 
+0xac226cd4, 0x3c020020, 0xafbf0010, 0x3c0100c0, 
+0xac201ffc, 0x431023, 0x441023, 0x245bb000, 
+0x365b821, 0x3c1d0001, 0x8fbd6ccc, 0x3a0f021, 
+0x3c0400c0, 0x34840200, 0x3c1a00c0, 0x3c0300c0, 
+0x346307c8, 0x24021dfc, 0x3c010001, 0xac226cd0, 
+0x24021834, 0x3c010001, 0xac246cd4, 0x3c010001, 
+0xac226cd0, 0x3c010001, 0xac236cd4, 0xc00180d, 
+0x375a0200, 0x8fbf0010, 0x3e00008, 0x27bd0018, 
+0x27bdffc8, 0x3c040001, 0x24846034, 0x24053200, 
+0x3c020001, 0x8c426cd0, 0x3c030001, 0x8c636cd4, 
+0x3021, 0x3603821, 0xafbf0030, 0xafb3002c, 
+0xafb20028, 0xafb10024, 0xafb00020, 0xafa2001c, 
+0xafa30018, 0xafb70010, 0xc002b3b, 0xafba0014, 
+0xc001916, 0x0, 0x8f820240, 0x34420004, 
+0xaf820240, 0x24020001, 0xaf420000, 0x3c020001, 
+0x571021, 0x904240f4, 0x10400092, 0x2403fffc, 
+0x3c100001, 0x2610ac73, 0x3c120001, 0x2652a84c, 
+0x2121023, 0x438024, 0x8fa3001c, 0x3c040001, 
+0x24846040, 0x70102b, 0x1440001a, 0x27b30018, 
+0x8fb10018, 0x24053000, 0x2403021, 0xafb00010, 
+0xafa30014, 0xc002b3b, 0x2203821, 0x8fa30018, 
+0x702021, 0x64102b, 0x10400007, 0x2403021, 
+0x8cc20000, 0xac620000, 0x24630004, 0x64102b, 
+0x1440fffb, 0x24c60004, 0x8fa2001c, 0x501023, 
+0xafa2001c, 0x8e620000, 0x501021, 0x1000000a, 
+0xae620000, 0x2408821, 0x24053100, 0xafb00010, 
+0xafa30014, 0x8fa70018, 0x2203021, 0x2402002d, 
+0xc002b3b, 0xa0820000, 0x24070020, 0x8fa3001c, 
+0x3c040001, 0x2484605c, 0x24120020, 0x3c010001, 
+0xac316eb0, 0x2c620020, 0x1440001d, 0x27b10018, 
+0x8fb00018, 0x24053000, 0x3c060001, 0x24c66f50, 
+0xafa70010, 0xafa30014, 0xc002b3b, 0x2003821, 
+0x8fa30018, 0x3c040001, 0x24846f50, 0x24650020, 
+0x65102b, 0x10400007, 0x0, 0x8c820000, 
+0xac620000, 0x24630004, 0x65102b, 0x1440fffb, 
+0x24840004, 0x8fa2001c, 0x521023, 0xafa2001c, 
+0x8e220000, 0x521021, 0x1000000b, 0xae220000, 
+0x3c100001, 0x26106f50, 0x24053100, 0xafa70010, 
+0xafa30014, 0x8fa70018, 0x2003021, 0x2402002d, 
+0xc002b3b, 0xa0820000, 0x24070020, 0x3c040001, 
+0x24846070, 0x8fa3001c, 0x24120020, 0x3c010001, 
+0xac306ee4, 0x2c620020, 0x1440001d, 0x27b10018, 
+0x8fb00018, 0x24053000, 0x3c060001, 0x24c66f70, 
+0xafa70010, 0xafa30014, 0xc002b3b, 0x2003821, 
+0x8fa30018, 0x3c040001, 0x24846f70, 0x24650020, 
+0x65102b, 0x10400007, 0x0, 0x8c820000, 
+0xac620000, 0x24630004, 0x65102b, 0x1440fffb, 
+0x24840004, 0x8fa2001c, 0x521023, 0xafa2001c, 
+0x8e220000, 0x521021, 0x1000000b, 0xae220000, 
+0x3c100001, 0x26106f70, 0x24053100, 0xafa70010, 
+0xafa30014, 0x8fa70018, 0x2003021, 0x2402002d, 
+0xc002b3b, 0xa0820000, 0x3c010001, 0x10000031, 
+0xac306ee0, 0x3c100001, 0x2610821f, 0x3c120001, 
+0x2652809c, 0x2121023, 0x438024, 0x8fa3001c, 
+0x3c040001, 0x24846084, 0x70102b, 0x1440001a, 
+0x27b30018, 0x8fb10018, 0x24053000, 0x2403021, 
+0xafb00010, 0xafa30014, 0xc002b3b, 0x2203821, 
+0x8fa30018, 0x702021, 0x64102b, 0x10400007, 
+0x2403021, 0x8cc20000, 0xac620000, 0x24630004, 
+0x64102b, 0x1440fffb, 0x24c60004, 0x8fa2001c, 
+0x501023, 0xafa2001c, 0x8e620000, 0x501021, 
+0x1000000a, 0xae620000, 0x2408821, 0x24053100, 
+0xafb00010, 0xafa30014, 0x8fa70018, 0x2203021, 
+0x2402002d, 0xc002b3b, 0xa0820000, 0x3c010001, 
+0xac316eb0, 0x3c030001, 0x8c636eb0, 0x24020400, 
+0x60f809, 0xaf820070, 0x8fbf0030, 0x8fb3002c, 
+0x8fb20028, 0x8fb10024, 0x8fb00020, 0x3e00008, 
+0x27bd0038, 0x0, 0x0, 0x8f820040, 
+0x3c03f000, 0x431024, 0x3c036000, 0x14430006, 
+0x0, 0x8f820050, 0x2403ff80, 0x431024, 
+0x34420055, 0xaf820050, 0x8f820054, 0x244203e8, 
+0xaf820058, 0x240201f4, 0xaf4200e0, 0x24020004, 
+0xaf4200e8, 0x24020002, 0xaf4001b0, 0xaf4000e4, 
+0xaf4200dc, 0xaf4000d8, 0xaf4000d4, 0x3e00008, 
+0xaf4000d0, 0x8f820054, 0x24420005, 0x3e00008, 
+0xaf820078, 0x27bdffe8, 0xafbf0010, 0x8f820054, 
+0x244203e8, 0xaf820058, 0x3c020800, 0x2c21024, 
+0x10400004, 0x3c02f7ff, 0x3442ffff, 0x2c2b024, 
+0x36940040, 0x3c020001, 0x8c426da8, 0x10400017, 
+0x3c020200, 0x3c030001, 0x8c636f1c, 0x10600016, 
+0x282a025, 0x3c020001, 0x8c426e44, 0x14400012, 
+0x3c020200, 0x3c020001, 0x8c426d94, 0x30420003, 
+0x1440000d, 0x3c020200, 0x8f830224, 0x3c020002, 
+0x8c428fec, 0x10620008, 0x3c020200, 0xc003daf, 
+0x0, 0x10000004, 0x3c020200, 0xc004196, 
+0x0, 0x3c020200, 0x2c21024, 0x10400003, 
+0x0, 0xc001f4b, 0x0, 0x8f4200d8, 
+0x8f4300dc, 0x24420001, 0xaf4200d8, 0x43102b, 
+0x14400003, 0x0, 0xaf4000d8, 0x36940080, 
+0x8c030238, 0x1060000c, 0x0, 0x8f4201b0, 
+0x244203e8, 0xaf4201b0, 0x43102b, 0x14400006, 
+0x0, 0x934205c5, 0x14400003, 0x0, 
+0xc001da0, 0x0, 0x8fbf0010, 0x3e00008, 
+0x27bd0018, 0x3e00008, 0x0, 0x27bdffd8, 
+0xafbf0020, 0x8f43002c, 0x8f420038, 0x10620059, 
+0x0, 0x3c020001, 0x571021, 0x904240f0, 
+0x10400026, 0x24070008, 0x8f440170, 0x8f450174, 
+0x8f48000c, 0x8f860120, 0x24020020, 0xafa20010, 
+0xafa30014, 0xafa80018, 0x8f42010c, 0x40f809, 
+0x24c6001c, 0x14400011, 0x24020001, 0x3c010001, 
+0x370821, 0xa02240f0, 0x8f820124, 0xafa20010, 
+0x8f820128, 0x3c040001, 0x24846128, 0xafa20014, 
+0x8f46002c, 0x8f870120, 0x3c050009, 0xc002b3b, 
+0x34a50900, 0x1000005c, 0x0, 0x8f420300, 
+0x24420001, 0xaf420300, 0x8f420300, 0x8f42002c, 
+0xa34005c1, 0x10000027, 0xaf420038, 0x8f440170, 
+0x8f450174, 0x8f43002c, 0x8f48000c, 0x8f860120, 
+0x24020080, 0xafa20010, 0xafa30014, 0xafa80018, 
+0x8f42010c, 0x40f809, 0x24c6001c, 0x14400011, 
+0x24020001, 0x3c010001, 0x370821, 0xa02240f1, 
+0x8f820124, 0xafa20010, 0x8f820128, 0x3c040001, 
+0x24846134, 0xafa20014, 0x8f46002c, 0x8f870120, 
+0x3c050009, 0xc002b3b, 0x34a51100, 0x10000036, 
+0x0, 0x8f420300, 0x8f43002c, 0x24420001, 
+0xaf420300, 0x8f420300, 0x24020001, 0xa34205c1, 
+0xaf430038, 0x3c010001, 0x370821, 0xa02040f1, 
+0x3c010001, 0x370821, 0xa02040f0, 0x10000026, 
+0xaf400034, 0x934205c1, 0x1040001d, 0x0, 
+0xa34005c1, 0x8f820040, 0x30420001, 0x14400008, 
+0x2021, 0x8c030104, 0x24020001, 0x50620005, 
+0x24040001, 0x8c020264, 0x10400003, 0x801021, 
+0x24040001, 0x801021, 0x10400006, 0x0, 
+0x8f42030c, 0x24420001, 0xaf42030c, 0x10000008, 
+0x8f42030c, 0x8f820044, 0x34420004, 0xaf820044, 
+0x8f420308, 0x24420001, 0xaf420308, 0x8f420308, 
+0x3c010001, 0x370821, 0xa02040f0, 0x3c010001, 
+0x370821, 0xa02040f1, 0x8f420000, 0x10400007, 
+0x0, 0xaf80004c, 0x8f82004c, 0x1040fffd, 
+0x0, 0x10000005, 0x0, 0xaf800048, 
+0x8f820048, 0x1040fffd, 0x0, 0x8f820060, 
+0x3c03ff7f, 0x3463ffff, 0x431024, 0xaf820060, 
+0x8f420000, 0x10400003, 0x0, 0x10000002, 
+0xaf80004c, 0xaf800048, 0x8fbf0020, 0x3e00008, 
+0x27bd0028, 0x3e00008, 0x0, 0x27bdffd8, 
+0xafbf0020, 0x8f430044, 0x8f42007c, 0x10620029, 
+0x24070008, 0x8f440168, 0x8f45016c, 0x8f48000c, 
+0x8f860120, 0x24020040, 0xafa20010, 0xafa30014, 
+0xafa80018, 0x8f42010c, 0x40f809, 0x24c6001c, 
+0x14400011, 0x24020001, 0x3c010001, 0x370821, 
+0xa02240f2, 0x8f820124, 0xafa20010, 0x8f820128, 
+0x3c040001, 0x2484613c, 0xafa20014, 0x8f460044, 
+0x8f870120, 0x3c050009, 0xc002b3b, 0x34a51300, 
+0x1000000f, 0x0, 0x8f420304, 0x24420001, 
+0xaf420304, 0x8f420304, 0x8f420044, 0xaf42007c, 
+0x3c010001, 0x370821, 0xa02040f2, 0x10000004, 
+0xaf400078, 0x3c010001, 0x370821, 0xa02040f2, 
+0x8f420000, 0x10400007, 0x0, 0xaf80004c, 
+0x8f82004c, 0x1040fffd, 0x0, 0x10000005, 
+0x0, 0xaf800048, 0x8f820048, 0x1040fffd, 
+0x0, 0x8f820060, 0x3c03feff, 0x3463ffff, 
+0x431024, 0xaf820060, 0x8f420000, 0x10400003, 
+0x0, 0x10000002, 0xaf80004c, 0xaf800048, 
+0x8fbf0020, 0x3e00008, 0x27bd0028, 0x3e00008, 
+0x0, 0x3c020001, 0x8c426da8, 0x27bdffa8, 
+0xafbf0050, 0xafbe004c, 0xafb50048, 0xafb30044, 
+0xafb20040, 0xafb1003c, 0xafb00038, 0x104000d5, 
+0x8f900044, 0x8f4200d0, 0x24430001, 0x2842000b, 
+0x144000e4, 0xaf4300d0, 0x8f420004, 0x30420002, 
+0x1440009c, 0xaf4000d0, 0x8f420004, 0x3c030001, 
+0x8c636d98, 0x34420002, 0xaf420004, 0x24020001, 
+0x14620003, 0x3c020600, 0x10000002, 0x34423000, 
+0x34421000, 0xafa20020, 0x8f4a0018, 0xafaa0034, 
+0x27aa0020, 0xafaa002c, 0x8faa0034, 0x240200ff, 
+0x11420002, 0x1821, 0x25430001, 0x8c020228, 
+0x609821, 0x1662000e, 0x3c050009, 0x8f42033c, 
+0x24420001, 0xaf42033c, 0x8f42033c, 0x8c020228, 
+0x8fa70034, 0x3c040001, 0x2484610c, 0xafa00014, 
+0xafa20010, 0x8fa60020, 0x10000070, 0x34a50500, 
+0x8faa0034, 0xa38c0, 0xf71021, 0x8fa30020, 
+0x8fa40024, 0xac4304c0, 0xac4404c4, 0x8f830054, 
+0x8f820054, 0x247103e8, 0x2221023, 0x2c4203e9, 
+0x1040001b, 0xa821, 0xe09021, 0x265e04c0, 
+0x8f440178, 0x8f45017c, 0x2401821, 0x240a0004, 
+0xafaa0010, 0xafb30014, 0x8f48000c, 0x1021, 
+0x2fe3021, 0xafa80018, 0x8f48010c, 0x24070008, 
+0xa32821, 0xa3482b, 0x822021, 0x100f809, 
+0x892021, 0x54400006, 0x24150001, 0x8f820054, 
+0x2221023, 0x2c4203e9, 0x1440ffe9, 0x0, 
+0x32a200ff, 0x54400018, 0xaf530018, 0x8f420378, 
+0x24420001, 0xaf420378, 0x8f420378, 0x8f820120, 
+0x8faa002c, 0x8fa70034, 0xafa20010, 0x8f820124, 
+0x3c040001, 0x24846118, 0xafa20014, 0x8d460000, 
+0x3c050009, 0x10000035, 0x34a50600, 0x8f420308, 
+0x24150001, 0x24420001, 0xaf420308, 0x8f420308, 
+0x1000001e, 0x32a200ff, 0x8f830054, 0x8f820054, 
+0x247103e8, 0x2221023, 0x2c4203e9, 0x10400016, 
+0xa821, 0x3c1e0020, 0x24120010, 0x8f42000c, 
+0x8f440160, 0x8f450164, 0x8f860120, 0xafb20010, 
+0xafb30014, 0x5e1025, 0xafa20018, 0x8f42010c, 
+0x24070008, 0x40f809, 0x24c6001c, 0x1440ffe3, 
+0x0, 0x8f820054, 0x2221023, 0x2c4203e9, 
+0x1440ffee, 0x0, 0x32a200ff, 0x14400011, 
+0x3c050009, 0x8f420378, 0x24420001, 0xaf420378, 
+0x8f420378, 0x8f820120, 0x8faa002c, 0x8fa70034, 
+0xafa20010, 0x8f820124, 0x3c040001, 0x24846120, 
+0xafa20014, 0x8d460000, 0x34a50700, 0xc002b3b, 
+0x0, 0x8f4202ec, 0x24420001, 0xaf4202ec, 
+0x8f4202ec, 0x8f420004, 0x30420001, 0x50400029, 
+0x36100040, 0x3c020400, 0x2c21024, 0x10400013, 
+0x2404ffdf, 0x8f420250, 0x8f430254, 0x8f4401b4, 
+0x14640006, 0x36100040, 0x8f420270, 0x8f430274, 
+0x8f4401b8, 0x10640007, 0x2402ffdf, 0x8f420250, 
+0x8f430254, 0x8f440270, 0x8f450274, 0x10000012, 
+0x3a100020, 0x1000002b, 0x2028024, 0x8f420250, 
+0x8f430254, 0x8f4501b4, 0x14650006, 0x2048024, 
+0x8f420270, 0x8f430274, 0x8f4401b8, 0x50640021, 
+0x36100040, 0x8f420250, 0x8f430254, 0x8f440270, 
+0x8f450274, 0x3a100040, 0xaf4301b4, 0x10000019, 
+0xaf4501b8, 0x8f4200d4, 0x24430001, 0x10000011, 
+0x28420033, 0x8f420004, 0x30420001, 0x10400009, 
+0x3c020400, 0x2c21024, 0x10400004, 0x2402ffdf, 
+0x2028024, 0x1000000b, 0x36100040, 0x10000009, 
+0x36100060, 0x8f4200d4, 0x36100040, 0x24430001, 
+0x284201f5, 0x14400003, 0xaf4300d4, 0xaf4000d4, 
+0x3a100020, 0xaf900044, 0x2402ff7f, 0x282a024, 
+0x8fbf0050, 0x8fbe004c, 0x8fb50048, 0x8fb30044, 
+0x8fb20040, 0x8fb1003c, 0x8fb00038, 0x3e00008, 
+0x27bd0058, 0x3e00008, 0x0, 0x3c020001, 
+0x8c426da8, 0x27bdffb0, 0xafbf0048, 0xafbe0044, 
+0xafb50040, 0xafb3003c, 0xafb20038, 0xafb10034, 
+0x104000c7, 0xafb00030, 0x8f4200d0, 0x24430001, 
+0x2842000b, 0x144000da, 0xaf4300d0, 0x8f420004, 
+0x30420002, 0x14400097, 0xaf4000d0, 0x8f420004, 
+0x3c030001, 0x8c636d98, 0x34420002, 0xaf420004, 
+0x24020001, 0x14620003, 0x3c020600, 0x10000002, 
+0x34423000, 0x34421000, 0xafa20020, 0x1821, 
+0x8f5e0018, 0x27aa0020, 0x240200ff, 0x13c20002, 
+0xafaa002c, 0x27c30001, 0x8c020228, 0x609021, 
+0x1642000e, 0x1e38c0, 0x8f42033c, 0x24420001, 
+0xaf42033c, 0x8f42033c, 0x8c020228, 0x3c040001, 
+0x2484610c, 0x3c050009, 0xafa00014, 0xafa20010, 
+0x8fa60020, 0x1000006d, 0x34a50500, 0xf71021, 
+0x8fa30020, 0x8fa40024, 0xac4304c0, 0xac4404c4, 
+0x8f830054, 0x8f820054, 0x247003e8, 0x2021023, 
+0x2c4203e9, 0x1040001b, 0x9821, 0xe08821, 
+0x263504c0, 0x8f440178, 0x8f45017c, 0x2201821, 
+0x240a0004, 0xafaa0010, 0xafb20014, 0x8f48000c, 
+0x1021, 0x2f53021, 0xafa80018, 0x8f48010c, 
+0x24070008, 0xa32821, 0xa3482b, 0x822021, 
+0x100f809, 0x892021, 0x54400006, 0x24130001, 
+0x8f820054, 0x2021023, 0x2c4203e9, 0x1440ffe9, 
+0x0, 0x326200ff, 0x54400017, 0xaf520018, 
+0x8f420378, 0x24420001, 0xaf420378, 0x8f420378, 
+0x8f820120, 0x8faa002c, 0xafa20010, 0x8f820124, 
+0x3c040001, 0x24846118, 0x3c050009, 0xafa20014, 
+0x8d460000, 0x10000035, 0x34a50600, 0x8f420308, 
+0x24130001, 0x24420001, 0xaf420308, 0x8f420308, 
+0x1000001e, 0x326200ff, 0x8f830054, 0x8f820054, 
+0x247003e8, 0x2021023, 0x2c4203e9, 0x10400016, 
+0x9821, 0x3c150020, 0x24110010, 0x8f42000c, 
+0x8f440160, 0x8f450164, 0x8f860120, 0xafb10010, 
+0xafb20014, 0x551025, 0xafa20018, 0x8f42010c, 
+0x24070008, 0x40f809, 0x24c6001c, 0x1440ffe3, 
+0x0, 0x8f820054, 0x2021023, 0x2c4203e9, 
+0x1440ffee, 0x0, 0x326200ff, 0x14400011, 
+0x0, 0x8f420378, 0x24420001, 0xaf420378, 
+0x8f420378, 0x8f820120, 0x8faa002c, 0xafa20010, 
+0x8f820124, 0x3c040001, 0x24846120, 0x3c050009, 
+0xafa20014, 0x8d460000, 0x34a50700, 0xc002b3b, 
+0x3c03821, 0x8f4202ec, 0x24420001, 0xaf4202ec, 
+0x8f4202ec, 0x8f420004, 0x30420001, 0x10400018, 
+0x24040001, 0x8f420250, 0x8f430254, 0x8f4501b4, 
+0x3c010001, 0x14650006, 0xa0246cf1, 0x8f420270, 
+0x8f430274, 0x8f4401b8, 0x10640021, 0x0, 
+0x8f420250, 0x8f430254, 0x3c040001, 0x90846cf0, 
+0x8f460270, 0x8f470274, 0x38840001, 0xaf4301b4, 
+0xaf4701b8, 0x3c010001, 0x10000025, 0xa0246cf0, 
+0x8f4200d4, 0x3c010001, 0xa0206cf0, 0x24430001, 
+0x28420033, 0x1440001e, 0xaf4300d4, 0x3c020001, 
+0x90426cf1, 0xaf4000d4, 0x10000017, 0x38420001, 
+0x8f420004, 0x30420001, 0x10400008, 0x0, 
+0xc00565a, 0x2021, 0x3c010001, 0xa0206cf1, 
+0x3c010001, 0x1000000e, 0xa0206cf0, 0x8f4200d4, 
+0x3c010001, 0xa0206cf0, 0x24430001, 0x284201f5, 
+0x14400007, 0xaf4300d4, 0x3c020001, 0x90426cf1, 
+0xaf4000d4, 0x421026, 0x3c010001, 0xa0226cf1, 
+0x3c030001, 0x8c636d98, 0x24020002, 0x1462000c, 
+0x3c030002, 0x3c030001, 0x90636cf1, 0x24020001, 
+0x5462001f, 0x2021, 0x3c020001, 0x90426cf0, 
+0x1443001b, 0x24040005, 0x10000019, 0x24040006, 
+0x3c020002, 0x8c428ff4, 0x431024, 0x1040000b, 
+0x24020001, 0x3c030001, 0x90636cf1, 0x54620010, 
+0x2021, 0x3c020001, 0x90426cf0, 0x1443000c, 
+0x24040003, 0x1000000a, 0x24040004, 0x3c030001, 
+0x90636cf1, 0x14620006, 0x2021, 0x3c020001, 
+0x90426cf0, 0x24040001, 0x50440001, 0x24040002, 
+0xc00565a, 0x0, 0x2402ff7f, 0x282a024, 
+0x8fbf0048, 0x8fbe0044, 0x8fb50040, 0x8fb3003c, 
+0x8fb20038, 0x8fb10034, 0x8fb00030, 0x3e00008, 
+0x27bd0050, 0x3e00008, 0x0, 0x3c020001, 
+0x8c426da8, 0x27bdffb0, 0xafbf0048, 0xafbe0044, 
+0xafb50040, 0xafb3003c, 0xafb20038, 0xafb10034, 
+0x104000de, 0xafb00030, 0x8f4200d0, 0x3c040001, 
+0x8c846d98, 0x24430001, 0x2842000b, 0xaf4400e8, 
+0x144000fe, 0xaf4300d0, 0x8f420004, 0x30420002, 
+0x14400095, 0xaf4000d0, 0x8f420004, 0x34420002, 
+0xaf420004, 0x24020001, 0x14820003, 0x3c020600, 
+0x10000002, 0x34423000, 0x34421000, 0xafa20020, 
+0x1821, 0x8f5e0018, 0x27aa0020, 0x240200ff, 
+0x13c20002, 0xafaa002c, 0x27c30001, 0x8c020228, 
+0x609021, 0x1642000e, 0x1e38c0, 0x8f42033c, 
+0x24420001, 0xaf42033c, 0x8f42033c, 0x8c020228, 
+0x3c040001, 0x2484610c, 0x3c050009, 0xafa00014, 
+0xafa20010, 0x8fa60020, 0x1000006d, 0x34a50500, 
+0xf71021, 0x8fa30020, 0x8fa40024, 0xac4304c0, 
+0xac4404c4, 0x8f830054, 0x8f820054, 0x247003e8, 
+0x2021023, 0x2c4203e9, 0x1040001b, 0x9821, 
+0xe08821, 0x263504c0, 0x8f440178, 0x8f45017c, 
+0x2201821, 0x240a0004, 0xafaa0010, 0xafb20014, 
+0x8f48000c, 0x1021, 0x2f53021, 0xafa80018, 
+0x8f48010c, 0x24070008, 0xa32821, 0xa3482b, 
+0x822021, 0x100f809, 0x892021, 0x54400006, 
+0x24130001, 0x8f820054, 0x2021023, 0x2c4203e9, 
+0x1440ffe9, 0x0, 0x326200ff, 0x54400017, 
+0xaf520018, 0x8f420378, 0x24420001, 0xaf420378, 
+0x8f420378, 0x8f820120, 0x8faa002c, 0xafa20010, 
+0x8f820124, 0x3c040001, 0x24846118, 0x3c050009, 
+0xafa20014, 0x8d460000, 0x10000035, 0x34a50600, 
+0x8f420308, 0x24130001, 0x24420001, 0xaf420308, 
+0x8f420308, 0x1000001e, 0x326200ff, 0x8f830054, 
+0x8f820054, 0x247003e8, 0x2021023, 0x2c4203e9, 
+0x10400016, 0x9821, 0x3c150020, 0x24110010, 
+0x8f42000c, 0x8f440160, 0x8f450164, 0x8f860120, 
+0xafb10010, 0xafb20014, 0x551025, 0xafa20018, 
+0x8f42010c, 0x24070008, 0x40f809, 0x24c6001c, 
+0x1440ffe3, 0x0, 0x8f820054, 0x2021023, 
+0x2c4203e9, 0x1440ffee, 0x0, 0x326200ff, 
+0x14400011, 0x0, 0x8f420378, 0x24420001, 
+0xaf420378, 0x8f420378, 0x8f820120, 0x8faa002c, 
+0xafa20010, 0x8f820124, 0x3c040001, 0x24846120, 
+0x3c050009, 0xafa20014, 0x8d460000, 0x34a50700, 
+0xc002b3b, 0x3c03821, 0x8f4202ec, 0x24420001, 
+0xaf4202ec, 0x8f4202ec, 0x8f420004, 0x30420001, 
+0x10400033, 0x3c020400, 0x2c21024, 0x10400017, 
+0x0, 0x934205c0, 0x8f440250, 0x8f450254, 
+0x8f4301b4, 0x34420020, 0x14a30006, 0xa34205c0, 
+0x8f420270, 0x8f430274, 0x8f4401b8, 0x10640008, 
+0x0, 0x8f420250, 0x8f430254, 0x934405c0, 
+0x8f460270, 0x8f470274, 0x10000016, 0x38840040, 
+0x934205c0, 0x10000048, 0x304200bf, 0x934205c0, 
+0x8f440250, 0x8f450254, 0x8f4301b4, 0x304200bf, 
+0x14a30006, 0xa34205c0, 0x8f420270, 0x8f430274, 
+0x8f4401b8, 0x1064000b, 0x0, 0x8f420250, 
+0x8f430254, 0x934405c0, 0x8f460270, 0x8f470274, 
+0x38840020, 0xaf4301b4, 0xaf4701b8, 0x10000033, 
+0xa34405c0, 0x934205c0, 0x1000002f, 0x34420020, 
+0x934205c0, 0x8f4300d4, 0x34420020, 0xa34205c0, 
+0x24620001, 0x10000023, 0x28630033, 0x8f4200e4, 
+0x8f4300e0, 0x24420001, 0xaf4200e4, 0x43102a, 
+0x14400006, 0x24030001, 0x8f4200e8, 0x14430002, 
+0xaf4000e4, 0x24030004, 0xaf4300e8, 0x8f420004, 
+0x30420001, 0x1040000d, 0x3c020400, 0x2c21024, 
+0x10400007, 0x0, 0x934205c0, 0x34420040, 
+0xa34205c0, 0x934205c0, 0x1000000f, 0x304200df, 
+0x934205c0, 0x1000000c, 0x34420060, 0x934205c0, 
+0x8f4300d4, 0x34420020, 0xa34205c0, 0x24620001, 
+0x286300fb, 0x14600005, 0xaf4200d4, 0x934205c0, 
+0xaf4000d4, 0x38420040, 0xa34205c0, 0x934205c0, 
+0x8f4300e8, 0x3042007f, 0xa34205c0, 0x24020001, 
+0x14620005, 0x0, 0x934405c0, 0x42102, 
+0x10000003, 0x348400f0, 0x934405c0, 0x3484000f, 
+0xc005640, 0x0, 0x2402ff7f, 0x282a024, 
+0x8fbf0048, 0x8fbe0044, 0x8fb50040, 0x8fb3003c, 
+0x8fb20038, 0x8fb10034, 0x8fb00030, 0x3e00008, 
+0x27bd0050, 0x3e00008, 0x0, 0x27bdffb0, 
+0x274401c0, 0x26e30028, 0x24650400, 0x65102b, 
+0xafbf0048, 0xafbe0044, 0xafb50040, 0xafb3003c, 
+0xafb20038, 0xafb10034, 0x10400007, 0xafb00030, 
+0x8c820000, 0xac620000, 0x24630004, 0x65102b, 
+0x1440fffb, 0x24840004, 0x8c020080, 0xaee20044, 
+0x8c0200c0, 0xaee20040, 0x8c020084, 0xaee20030, 
+0x8c020084, 0xaee2023c, 0x8c020088, 0xaee20240, 
+0x8c02008c, 0xaee20244, 0x8c020090, 0xaee20248, 
+0x8c020094, 0xaee2024c, 0x8c020098, 0xaee20250, 
+0x8c02009c, 0xaee20254, 0x8c0200a0, 0xaee20258, 
+0x8c0200a4, 0xaee2025c, 0x8c0200a8, 0xaee20260, 
+0x8c0200ac, 0xaee20264, 0x8c0200b0, 0xaee20268, 
+0x8c0200b4, 0xaee2026c, 0x8c0200b8, 0xaee20270, 
+0x8c0200bc, 0x24040001, 0xaee20274, 0xaee00034, 
+0x41080, 0x571021, 0x8ee30034, 0x8c42023c, 
+0x24840001, 0x621821, 0x2c82000f, 0xaee30034, 
+0x1440fff8, 0x41080, 0x8c0200cc, 0xaee20048, 
+0x8c0200d0, 0xaee2004c, 0x8c0200e0, 0xaee201f8, 
+0x8c0200e4, 0xaee201fc, 0x8c0200e8, 0xaee20200, 
+0x8c0200ec, 0xaee20204, 0x8c0200f0, 0xaee20208, 
+0x8ee400c0, 0x8ee500c4, 0x8c0200fc, 0x45102b, 
+0x1040000b, 0x0, 0x8ee200c0, 0x8ee300c4, 
+0x24040001, 0x24050000, 0x651821, 0x65302b, 
+0x441021, 0x461021, 0xaee200c0, 0xaee300c4, 
+0x8c0200fc, 0x8ee400c0, 0x8ee500c4, 0x2408ffff, 
+0x24090000, 0x401821, 0x1021, 0x882024, 
+0xa92824, 0x822025, 0xa32825, 0xaee400c0, 
+0xaee500c4, 0x8ee400d0, 0x8ee500d4, 0x8c0200f4, 
+0x45102b, 0x1040000b, 0x0, 0x8ee200d0, 
+0x8ee300d4, 0x24040001, 0x24050000, 0x651821, 
+0x65302b, 0x441021, 0x461021, 0xaee200d0, 
+0xaee300d4, 0x8c0200f4, 0x8ee400d0, 0x8ee500d4, 
+0x401821, 0x1021, 0x882024, 0xa92824, 
+0x822025, 0xa32825, 0xaee400d0, 0xaee500d4, 
+0x8ee400c8, 0x8ee500cc, 0x8c0200f8, 0x45102b, 
+0x1040000b, 0x0, 0x8ee200c8, 0x8ee300cc, 
+0x24040001, 0x24050000, 0x651821, 0x65302b, 
+0x441021, 0x461021, 0xaee200c8, 0xaee300cc, 
+0x8c0200f8, 0x8ee400c8, 0x8ee500cc, 0x401821, 
+0x1021, 0x882024, 0xa92824, 0x822025, 
+0xa32825, 0x24020008, 0xaee400c8, 0xaee500cc, 
+0xafa20010, 0xafa00014, 0x8f42000c, 0x8c040208, 
+0x8c05020c, 0xafa20018, 0x8f42010c, 0x26e60028, 
+0x40f809, 0x24070400, 0x104000f0, 0x3c020400, 
+0xafa20020, 0x934205c6, 0x10400089, 0x1821, 
+0x8f5e0018, 0x27aa0020, 0x240200ff, 0x13c20002, 
+0xafaa002c, 0x27c30001, 0x8c020228, 0x609021, 
+0x1642000e, 0x1e38c0, 0x8f42033c, 0x24420001, 
+0xaf42033c, 0x8f42033c, 0x8c020228, 0x3c040001, 
+0x2484610c, 0x3c050009, 0xafa00014, 0xafa20010, 
+0x8fa60020, 0x1000006b, 0x34a50500, 0xf71021, 
+0x8fa30020, 0x8fa40024, 0xac4304c0, 0xac4404c4, 
+0x8f830054, 0x8f820054, 0x247003e8, 0x2021023, 
+0x2c4203e9, 0x1040001b, 0x9821, 0xe08821, 
+0x263504c0, 0x8f440178, 0x8f45017c, 0x2201821, 
+0x240a0004, 0xafaa0010, 0xafb20014, 0x8f48000c, 
+0x1021, 0x2f53021, 0xafa80018, 0x8f48010c, 
+0x24070008, 0xa32821, 0xa3482b, 0x822021, 
+0x100f809, 0x892021, 0x54400006, 0x24130001, 
+0x8f820054, 0x2021023, 0x2c4203e9, 0x1440ffe9, 
+0x0, 0x326200ff, 0x54400017, 0xaf520018, 
+0x8f420378, 0x24420001, 0xaf420378, 0x8f420378, 
+0x8f820120, 0x8faa002c, 0xafa20010, 0x8f820124, 
+0x3c040001, 0x24846118, 0x3c050009, 0xafa20014, 
+0x8d460000, 0x10000033, 0x34a50600, 0x8f420308, 
+0x24130001, 0x24420001, 0xaf420308, 0x8f420308, 
+0x1000001c, 0x326200ff, 0x8f830054, 0x8f820054, 
+0x247003e8, 0x2021023, 0x2c4203e9, 0x10400014, 
+0x9821, 0x24110010, 0x8f42000c, 0x8f440160, 
+0x8f450164, 0x8f860120, 0xafb10010, 0xafb20014, 
+0xafa20018, 0x8f42010c, 0x24070008, 0x40f809, 
+0x24c6001c, 0x1440ffe5, 0x0, 0x8f820054, 
+0x2021023, 0x2c4203e9, 0x1440ffef, 0x0, 
+0x326200ff, 0x54400012, 0x24020001, 0x8f420378, 
+0x24420001, 0xaf420378, 0x8f420378, 0x8f820120, 
+0x8faa002c, 0xafa20010, 0x8f820124, 0x3c040001, 
+0x24846120, 0x3c050009, 0xafa20014, 0x8d460000, 
+0x34a50700, 0xc002b3b, 0x3c03821, 0x1021, 
+0x1440005b, 0x24020001, 0x10000065, 0x0, 
+0x8f510018, 0x240200ff, 0x12220002, 0x8021, 
+0x26300001, 0x8c020228, 0x1602000e, 0x1130c0, 
+0x8f42033c, 0x24420001, 0xaf42033c, 0x8f42033c, 
+0x8c020228, 0x3c040001, 0x248460f4, 0x3c050009, 
+0xafa00014, 0xafa20010, 0x8fa60020, 0x1000003f, 
+0x34a50100, 0xd71021, 0x8fa30020, 0x8fa40024, 
+0xac4304c0, 0xac4404c4, 0xc01821, 0x8f440178, 
+0x8f45017c, 0x1021, 0x24070004, 0xafa70010, 
+0xafb00014, 0x8f48000c, 0x24c604c0, 0x2e63021, 
+0xafa80018, 0x8f48010c, 0x24070008, 0xa32821, 
+0xa3482b, 0x822021, 0x100f809, 0x892021, 
+0x1440000b, 0x24070008, 0x8f820120, 0xafa20010, 
+0x8f820124, 0x3c040001, 0x248460fc, 0x3c050009, 
+0xafa20014, 0x8fa60020, 0x1000001c, 0x34a50200, 
+0x8f440160, 0x8f450164, 0x8f43000c, 0xaf500018, 
+0x8f860120, 0x24020010, 0xafa20010, 0xafb00014, 
+0xafa30018, 0x8f42010c, 0x40f809, 0x24c6001c, 
+0x54400011, 0x24020001, 0x8f420340, 0x24420001, 
+0xaf420340, 0x8f420340, 0x8f820120, 0xafa20010, 
+0x8f820124, 0x3c040001, 0x24846104, 0x3c050009, 
+0xafa20014, 0x8fa60020, 0x34a50300, 0xc002b3b, 
+0x2203821, 0x1021, 0x1040000d, 0x24020001, 
+0x8f4202e8, 0xa34005c6, 0xaf4001b0, 0x24420001, 
+0xaf4202e8, 0x8f4202e8, 0x8ee20150, 0x24420001, 
+0xaee20150, 0x10000003, 0x8ee20150, 0x24020001, 
+0xa34205c6, 0x8fbf0048, 0x8fbe0044, 0x8fb50040, 
+0x8fb3003c, 0x8fb20038, 0x8fb10034, 0x8fb00030, 
+0x3e00008, 0x27bd0050, 0x27bdffd8, 0xafbf0020, 
+0x8f8200b0, 0x30420004, 0x10400068, 0x0, 
+0x8f430128, 0x8f820104, 0x14620005, 0x0, 
+0x8f430130, 0x8f8200b4, 0x10620006, 0x0, 
+0x8f820104, 0xaf420128, 0x8f8200b4, 0x1000005b, 
+0xaf420130, 0x8f8200b0, 0x3c030080, 0x431024, 
+0x1040000d, 0x0, 0x8f82011c, 0x34420002, 
+0xaf82011c, 0x8f8200b0, 0x2403fffb, 0x431024, 
+0xaf8200b0, 0x8f82011c, 0x2403fffd, 0x431024, 
+0x1000004a, 0xaf82011c, 0x8f430128, 0x8f820104, 
+0x14620005, 0x0, 0x8f430130, 0x8f8200b4, 
+0x10620010, 0x0, 0x8f820104, 0xaf420128, 
+0x8f8200b4, 0x8f430128, 0xaf420130, 0xafa30010, 
+0x8f420130, 0x3c040001, 0x24846144, 0xafa20014, 
+0x8f86011c, 0x8f8700b0, 0x3c050005, 0x10000031, 
+0x34a50900, 0x8f420128, 0xafa20010, 0x8f420130, 
+0x3c040001, 0x24846150, 0xafa20014, 0x8f86011c, 
+0x8f8700b0, 0x3c050005, 0xc002b3b, 0x34a51000, 
+0x8f82011c, 0x34420002, 0xaf82011c, 0x8f830104, 
+0x8f8200b0, 0x34420001, 0xaf8200b0, 0x24020008, 
+0xaf830104, 0xafa20010, 0xafa00014, 0x8f42000c, 
+0x8c040208, 0x8c05020c, 0xafa20018, 0x8f42010c, 
+0x26e60028, 0x40f809, 0x24070400, 0x8f82011c, 
+0x2403fffd, 0x431024, 0xaf82011c, 0x8ee201dc, 
+0x24420001, 0xaee201dc, 0x8ee201dc, 0x8f420128, 
+0xafa20010, 0x8f420130, 0x3c040001, 0x2484615c, 
+0xafa20014, 0x8f86011c, 0x8f8700b0, 0x3c050005, 
+0x34a51100, 0xc002b3b, 0x0, 0x8f8200a0, 
+0x30420004, 0x10400069, 0x0, 0x8f43012c, 
+0x8f820124, 0x14620005, 0x0, 0x8f430134, 
+0x8f8200a4, 0x10620006, 0x0, 0x8f820124, 
+0xaf42012c, 0x8f8200a4, 0x1000005c, 0xaf420134, 
+0x8f8200a0, 0x3c030080, 0x431024, 0x1040000d, 
+0x0, 0x8f82011c, 0x34420002, 0xaf82011c, 
+0x8f8200a0, 0x2403fffb, 0x431024, 0xaf8200a0, 
+0x8f82011c, 0x2403fffd, 0x431024, 0x1000004b, 
+0xaf82011c, 0x8f43012c, 0x8f820124, 0x14620005, 
+0x0, 0x8f430134, 0x8f8200a4, 0x10620010, 
+0x0, 0x8f820124, 0xaf42012c, 0x8f8200a4, 
+0x8f43012c, 0xaf420134, 0xafa30010, 0x8f420134, 
+0x3c040001, 0x24846168, 0xafa20014, 0x8f86011c, 
+0x8f8700a0, 0x3c050005, 0x10000032, 0x34a51200, 
+0x8f42012c, 0xafa20010, 0x8f420134, 0x3c040001, 
+0x24846174, 0xafa20014, 0x8f86011c, 0x8f8700a0, 
+0x3c050005, 0xc002b3b, 0x34a51300, 0x8f82011c, 
+0x34420002, 0xaf82011c, 0x8f830124, 0x8f8200a0, 
+0x34420001, 0xaf8200a0, 0x24020080, 0xaf830124, 
+0xafa20010, 0xafa00014, 0x8f420014, 0x8c040208, 
+0x8c05020c, 0xafa20018, 0x8f420108, 0x3c060001, 
+0x24c66ed8, 0x40f809, 0x24070004, 0x8f82011c, 
+0x2403fffd, 0x431024, 0xaf82011c, 0x8ee201dc, 
+0x24420001, 0xaee201dc, 0x8ee201dc, 0x8f42012c, 
+0xafa20010, 0x8f420134, 0x3c040001, 0x24846180, 
+0xafa20014, 0x8f86011c, 0x8f8700a0, 0x3c050005, 
+0x34a51400, 0xc002b3b, 0x0, 0x8fbf0020, 
+0x3e00008, 0x27bd0028, 0x3c081000, 0x24070001, 
+0x3c060080, 0x3c050100, 0x8f820070, 0x481024, 
+0x1040fffd, 0x0, 0x8f820054, 0x24420005, 
+0xaf820078, 0x8c040234, 0x10800016, 0x1821, 
+0x3c020001, 0x571021, 0x8c4240e8, 0x24420005, 
+0x3c010001, 0x370821, 0xac2240e8, 0x3c020001, 
+0x571021, 0x8c4240e8, 0x44102b, 0x14400009, 
+0x0, 0x3c030080, 0x3c010001, 0x370821, 
+0xac2040e8, 0x3c010001, 0x370821, 0x1000000b, 
+0xa02740f0, 0x3c020001, 0x571021, 0x904240f0, 
+0x54400006, 0x661825, 0x3c020001, 0x571021, 
+0x904240f1, 0x54400001, 0x661825, 0x8c040230, 
+0x10800013, 0x0, 0x3c020001, 0x571021, 
+0x8c4240ec, 0x24420005, 0x3c010001, 0x370821, 
+0xac2240ec, 0x3c020001, 0x571021, 0x8c4240ec, 
+0x44102b, 0x14400006, 0x0, 0x3c010001, 
+0x370821, 0xac2040ec, 0x10000006, 0x651825, 
+0x3c020001, 0x571021, 0x904240f2, 0x54400001, 
+0x651825, 0x1060ffbc, 0x0, 0x8f420000, 
+0x10400007, 0x0, 0xaf80004c, 0x8f82004c, 
+0x1040fffd, 0x0, 0x10000005, 0x0, 
+0xaf800048, 0x8f820048, 0x1040fffd, 0x0, 
+0x8f820060, 0x431025, 0xaf820060, 0x8f420000, 
+0x10400003, 0x0, 0x1000ffa7, 0xaf80004c, 
+0x1000ffa5, 0xaf800048, 0x3e00008, 0x0, 
+0x0, 0x0, 0x0, 0x27bdffe0, 
+0xafbf0018, 0x8f860064, 0x30c20004, 0x10400025, 
+0x24040004, 0x8c020114, 0xaf420020, 0xaf840064, 
+0x8f4202fc, 0x24420001, 0xaf4202fc, 0x8f4202fc, 
+0x8f820064, 0x30420004, 0x14400005, 0x0, 
+0x8c030114, 0x8f420020, 0x1462fff2, 0x0, 
+0x8f420000, 0x10400007, 0x8f43003c, 0xaf80004c, 
+0x8f82004c, 0x1040fffd, 0x0, 0x10000005, 
+0x0, 0xaf800048, 0x8f820048, 0x1040fffd, 
+0x0, 0x8f820060, 0x431025, 0xaf820060, 
+0x8f420000, 0x10400073, 0x0, 0x1000006f, 
+0x0, 0x30c20008, 0x10400020, 0x24040008, 
+0x8c02011c, 0xaf420048, 0xaf840064, 0x8f4202a8, 
+0x24420001, 0xaf4202a8, 0x8f4202a8, 0x8f820064, 
+0x30420008, 0x14400005, 0x0, 0x8c03011c, 
+0x8f420048, 0x1462fff2, 0x0, 0x8f420000, 
+0x10400007, 0x0, 0xaf80004c, 0x8f82004c, 
+0x1040fffd, 0x0, 0x10000005, 0x0, 
+0xaf800048, 0x8f820048, 0x1040fffd, 0x0, 
+0x8f820060, 0x1000ffd9, 0x34420200, 0x30c20020, 
+0x10400023, 0x24040020, 0x8c02012c, 0xaf420068, 
+0xaf840064, 0x8f4202d8, 0x24420001, 0xaf4202d8, 
+0x8f4202d8, 0x8f820064, 0x30420020, 0x14400005, 
+0x32c24000, 0x8c03012c, 0x8f420068, 0x1462fff2, 
+0x32c24000, 0x14400002, 0x3c020001, 0x2c2b025, 
+0x8f420000, 0x10400007, 0x0, 0xaf80004c, 
+0x8f82004c, 0x1040fffd, 0x0, 0x10000005, 
+0x0, 0xaf800048, 0x8f820048, 0x1040fffd, 
+0x0, 0x8f820060, 0x1000ffb4, 0x34420800, 
+0x30c20010, 0x10400029, 0x24040010, 0x8c020124, 
+0xaf420058, 0xaf840064, 0x8f4202d4, 0x24420001, 
+0xaf4202d4, 0x8f4202d4, 0x8f820064, 0x30420010, 
+0x14400005, 0x32c22000, 0x8c030124, 0x8f420058, 
+0x1462fff2, 0x32c22000, 0x50400001, 0x36d68000, 
+0x8f420000, 0x10400007, 0x0, 0xaf80004c, 
+0x8f82004c, 0x1040fffd, 0x0, 0x10000005, 
+0x0, 0xaf800048, 0x8f820048, 0x1040fffd, 
+0x0, 0x8f820060, 0x34420100, 0xaf820060, 
+0x8f420000, 0x10400003, 0x0, 0x1000006c, 
+0xaf80004c, 0x1000006a, 0xaf800048, 0x30c20001, 
+0x10400004, 0x24020001, 0xaf820064, 0x10000064, 
+0x0, 0x30c20002, 0x1440000b, 0x3c050003, 
+0x3c040001, 0x24846244, 0x34a50500, 0x3821, 
+0xafa00010, 0xc002b3b, 0xafa00014, 0x2402ffc0, 
+0x10000057, 0xaf820064, 0x8c05022c, 0x8c02010c, 
+0x10a20048, 0x51080, 0x8c460300, 0x24a20001, 
+0x3045003f, 0x24020003, 0xac05022c, 0x61e02, 
+0x10620005, 0x24020010, 0x1062001d, 0x30c20fff, 
+0x10000039, 0x0, 0x8f4302a8, 0x8f440000, 
+0x30c20fff, 0xaf420048, 0x24630001, 0xaf4302a8, 
+0x10800007, 0x8f4202a8, 0xaf80004c, 0x8f82004c, 
+0x1040fffd, 0x0, 0x10000005, 0x0, 
+0xaf800048, 0x8f820048, 0x1040fffd, 0x0, 
+0x8f820060, 0x34420200, 0xaf820060, 0x8f420000, 
+0x1040001f, 0x0, 0x1000001b, 0x0, 
+0xaf420058, 0x32c22000, 0x50400001, 0x36d68000, 
+0x8f4202d4, 0x8f430000, 0x24420001, 0xaf4202d4, 
+0x10600007, 0x8f4202d4, 0xaf80004c, 0x8f82004c, 
+0x1040fffd, 0x0, 0x10000005, 0x0, 
+0xaf800048, 0x8f820048, 0x1040fffd, 0x0, 
+0x8f820060, 0x34420100, 0xaf820060, 0x8f420000, 
+0x10400003, 0x0, 0x10000006, 0xaf80004c, 
+0x10000004, 0xaf800048, 0xc002196, 0xc02021, 
+0x402821, 0x8c02010c, 0x14a20002, 0x24020002, 
+0xaf820064, 0x8f820064, 0x30420002, 0x14400004, 
+0x0, 0x8c02010c, 0x14a2ffac, 0x0, 
+0x8fbf0018, 0x3e00008, 0x27bd0020, 0x3e00008, 
+0x0, 0x27bdffa0, 0xafb00040, 0x808021, 
+0x101602, 0x2442ffff, 0x304300ff, 0x2c620013, 
+0xafbf0058, 0xafbe0054, 0xafb50050, 0xafb3004c, 
+0xafb20048, 0xafb10044, 0x104001f3, 0xafa50034, 
+0x31080, 0x3c010001, 0x220821, 0x8c226288, 
+0x400008, 0x0, 0x101302, 0x30440fff, 
+0x24020001, 0x10820005, 0x24020002, 0x1082000c, 
+0x2402fffe, 0x10000024, 0x3c050003, 0x8f430004, 
+0x3c020001, 0x8c426f04, 0xaf440200, 0xaf440204, 
+0x3c040001, 0x8c846e80, 0x10000009, 0x34630001, 
+0x8f430004, 0xaf440200, 0xaf440204, 0x3c040001, 
+0x8c846e80, 0x621824, 0x3c020001, 0x2442ca28, 
+0x21100, 0x21182, 0xaf430004, 0x3c030800, 
+0x431025, 0xac820038, 0x8f840054, 0x41442, 
+0x41c82, 0x431021, 0x41cc2, 0x431023, 
+0x41d02, 0x431021, 0x41d42, 0x431023, 
+0x10000009, 0xaf420208, 0x3c040001, 0x24846250, 
+0x34a51000, 0x2003021, 0x3821, 0xafa00010, 
+0xc002b3b, 0xafa00014, 0x8f4202a0, 0x24420001, 
+0xaf4202a0, 0x1000021f, 0x8f4202a0, 0x27b00028, 
+0x2002021, 0x24050210, 0xc002bbf, 0x24060008, 
+0xc002518, 0x2002021, 0x10000216, 0x0, 
+0x8faa0034, 0x27a40028, 0xa1880, 0x25420001, 
+0x3042003f, 0xafa20034, 0x8c650300, 0x8faa0034, 
+0x21080, 0x8c430300, 0x25420001, 0x3042003f, 
+0xafa20034, 0xac02022c, 0xafa50028, 0xc002518, 
+0xafa3002c, 0x10000203, 0x0, 0x27b00028, 
+0x2002021, 0x24050210, 0xc002bbf, 0x24060008, 
+0xc002657, 0x2002021, 0x100001fa, 0x0, 
+0x8faa0034, 0x27a40028, 0xa1880, 0x25420001, 
+0x3042003f, 0xafa20034, 0x8c650300, 0x8faa0034, 
+0x21080, 0x8c430300, 0x25420001, 0x3042003f, 
+0xafa20034, 0xac02022c, 0xafa50028, 0xc002657, 
+0xafa3002c, 0x100001e7, 0x0, 0x101302, 
+0x30430fff, 0x24020001, 0x10620005, 0x24020002, 
+0x1062001e, 0x3c020002, 0x10000033, 0x3c050003, 
+0x3c030002, 0x2c31024, 0x54400037, 0x2c3b025, 
+0x8f820228, 0x3c010001, 0x370821, 0xac2238d8, 
+0x8f82022c, 0x3c010001, 0x370821, 0xac2238dc, 
+0x8f820230, 0x3c010001, 0x370821, 0xac2238e0, 
+0x8f820234, 0x3c010001, 0x370821, 0xac2238e4, 
+0x2402ffff, 0xaf820228, 0xaf82022c, 0xaf820230, 
+0xaf820234, 0x10000020, 0x2c3b025, 0x2c21024, 
+0x10400012, 0x3c02fffd, 0x3c020001, 0x571021, 
+0x8c4238d8, 0xaf820228, 0x3c020001, 0x571021, 
+0x8c4238dc, 0xaf82022c, 0x3c020001, 0x571021, 
+0x8c4238e0, 0xaf820230, 0x3c020001, 0x571021, 
+0x8c4238e4, 0xaf820234, 0x3c02fffd, 0x3442ffff, 
+0x10000009, 0x2c2b024, 0x3c040001, 0x2484625c, 
+0x34a51100, 0x2003021, 0x3821, 0xafa00010, 
+0xc002b3b, 0xafa00014, 0x8f4202cc, 0x24420001, 
+0xaf4202cc, 0x1000019f, 0x8f4202cc, 0x101302, 
+0x30450fff, 0x24020001, 0x10a20005, 0x24020002, 
+0x10a2000d, 0x3c0408ff, 0x10000014, 0x3c050003, 
+0x3c0208ff, 0x3442ffff, 0x8f830220, 0x3c040004, 
+0x2c4b025, 0x621824, 0x34630008, 0xaf830220, 
+0x10000012, 0xaf450298, 0x3484fff7, 0x3c03fffb, 
+0x8f820220, 0x3463ffff, 0x2c3b024, 0x441024, 
+0xaf820220, 0x10000009, 0xaf450298, 0x3c040001, 
+0x24846268, 0x34a51200, 0x2003021, 0x3821, 
+0xafa00010, 0xc002b3b, 0xafa00014, 0x8f4202bc, 
+0x24420001, 0xaf4202bc, 0x10000176, 0x8f4202bc, 
+0x27840208, 0x24050200, 0xc002bbf, 0x24060008, 
+0x27440224, 0x24050200, 0xc002bbf, 0x24060008, 
+0x8f4202c4, 0x24420001, 0xaf4202c4, 0x10000169, 
+0x8f4202c4, 0x101302, 0x30430fff, 0x24020001, 
+0x10620011, 0x28620002, 0x50400005, 0x24020002, 
+0x10600007, 0x0, 0x10000017, 0x0, 
+0x1062000f, 0x0, 0x10000013, 0x0, 
+0x8c060248, 0x2021, 0xc005104, 0x24050004, 
+0x10000007, 0x0, 0x8c060248, 0x2021, 
+0xc005104, 0x24050004, 0x10000010, 0x0, 
+0x8c06024c, 0x2021, 0xc005104, 0x24050001, 
+0x1000000a, 0x0, 0x3c040001, 0x24846274, 
+0x3c050003, 0x34a51300, 0x2003021, 0x3821, 
+0xafa00010, 0xc002b3b, 0xafa00014, 0x8f4202c0, 
+0x24420001, 0xaf4202c0, 0x1000013a, 0x8f4202c0, 
+0xc002426, 0x0, 0x10000136, 0x0, 
+0x24020001, 0xa34205c5, 0x24100100, 0x8f4401a8, 
+0x8f4501ac, 0xafb00010, 0xafa00014, 0x8f420014, 
+0xafa20018, 0x8f420108, 0x26e60028, 0x40f809, 
+0x24070400, 0x1040fff5, 0x0, 0x10000125, 
+0x0, 0x3c03ffff, 0x34637fff, 0x8f420368, 
+0x8f440360, 0x2c3b024, 0x1821, 0xaf400058, 
+0xaf40005c, 0xaf400060, 0xaf400064, 0x441023, 
+0xaf420368, 0x3c020900, 0xaf400360, 0xafa20020, 
+0x8f5e0018, 0x27aa0020, 0x240200ff, 0x13c20002, 
+0xafaa003c, 0x27c30001, 0x8c020228, 0x609021, 
+0x1642000e, 0x1e38c0, 0x8f42033c, 0x24420001, 
+0xaf42033c, 0x8f42033c, 0x8c020228, 0x3c040001, 
+0x2484620c, 0x3c050009, 0xafa00014, 0xafa20010, 
+0x8fa60020, 0x1000006b, 0x34a50500, 0xf71021, 
+0x8fa30020, 0x8fa40024, 0xac4304c0, 0xac4404c4, 
+0x8f830054, 0x8f820054, 0x247003e8, 0x2021023, 
+0x2c4203e9, 0x1040001b, 0x9821, 0xe08821, 
+0x263504c0, 0x8f440178, 0x8f45017c, 0x2201821, 
+0x240a0004, 0xafaa0010, 0xafb20014, 0x8f48000c, 
+0x1021, 0x2f53021, 0xafa80018, 0x8f48010c, 
+0x24070008, 0xa32821, 0xa3482b, 0x822021, 
+0x100f809, 0x892021, 0x54400006, 0x24130001, 
+0x8f820054, 0x2021023, 0x2c4203e9, 0x1440ffe9, 
+0x0, 0x326200ff, 0x54400017, 0xaf520018, 
+0x8f420378, 0x24420001, 0xaf420378, 0x8f420378, 
+0x8f820120, 0x8faa003c, 0xafa20010, 0x8f820124, 
+0x3c040001, 0x24846218, 0x3c050009, 0xafa20014, 
+0x8d460000, 0x10000033, 0x34a50600, 0x8f420308, 
+0x24130001, 0x24420001, 0xaf420308, 0x8f420308, 
+0x1000001c, 0x326200ff, 0x8f830054, 0x8f820054, 
+0x247003e8, 0x2021023, 0x2c4203e9, 0x10400014, 
+0x9821, 0x24110010, 0x8f42000c, 0x8f440160, 
+0x8f450164, 0x8f860120, 0xafb10010, 0xafb20014, 
+0xafa20018, 0x8f42010c, 0x24070008, 0x40f809, 
+0x24c6001c, 0x1440ffe5, 0x0, 0x8f820054, 
+0x2021023, 0x2c4203e9, 0x1440ffef, 0x0, 
+0x326200ff, 0x14400011, 0x0, 0x8f420378, 
+0x24420001, 0xaf420378, 0x8f420378, 0x8f820120, 
+0x8faa003c, 0xafa20010, 0x8f820124, 0x3c040001, 
+0x24846220, 0x3c050009, 0xafa20014, 0x8d460000, 
+0x34a50700, 0xc002b3b, 0x3c03821, 0x8f4202b0, 
+0x24420001, 0xaf4202b0, 0x8f4202b0, 0x8f4202f8, 
+0x24420001, 0xaf4202f8, 0x1000008a, 0x8f4202f8, 
+0x8c02025c, 0x27440224, 0xaf4201f0, 0x8c020260, 
+0x24050200, 0x24060008, 0xc002bbf, 0xaf4201f8, 
+0x8f820220, 0x30420008, 0x14400002, 0x24020001, 
+0x24020002, 0xaf420298, 0x8f4202ac, 0x24420001, 
+0xaf4202ac, 0x10000077, 0x8f4202ac, 0x3c0200ff, 
+0x3442ffff, 0x2021824, 0x32c20180, 0x14400006, 
+0x3402fffb, 0x43102b, 0x14400003, 0x0, 
+0x1000006c, 0xaf4300bc, 0x3c040001, 0x24846280, 
+0x3c050003, 0x34a51500, 0x2003021, 0x3821, 
+0xafa00010, 0xc002b3b, 0xafa00014, 0x3c020700, 
+0x34421000, 0x101e02, 0x621825, 0xafa30020, 
+0x8f510018, 0x240200ff, 0x12220002, 0x8021, 
+0x26300001, 0x8c020228, 0x1602000e, 0x1130c0, 
+0x8f42033c, 0x24420001, 0xaf42033c, 0x8f42033c, 
+0x8c020228, 0x3c040001, 0x248461f4, 0x3c050009, 
+0xafa00014, 0xafa20010, 0x8fa60020, 0x1000003f, 
+0x34a50100, 0xd71021, 0x8fa30020, 0x8fa40024, 
+0xac4304c0, 0xac4404c4, 0xc01821, 0x8f440178, 
+0x8f45017c, 0x1021, 0x24070004, 0xafa70010, 
+0xafb00014, 0x8f48000c, 0x24c604c0, 0x2e63021, 
+0xafa80018, 0x8f48010c, 0x24070008, 0xa32821, 
+0xa3482b, 0x822021, 0x100f809, 0x892021, 
+0x1440000b, 0x24070008, 0x8f820120, 0xafa20010, 
+0x8f820124, 0x3c040001, 0x248461fc, 0x3c050009, 
+0xafa20014, 0x8fa60020, 0x1000001c, 0x34a50200, 
+0x8f440160, 0x8f450164, 0x8f43000c, 0xaf500018, 
+0x8f860120, 0x24020010, 0xafa20010, 0xafb00014, 
+0xafa30018, 0x8f42010c, 0x40f809, 0x24c6001c, 
+0x14400010, 0x0, 0x8f420340, 0x24420001, 
+0xaf420340, 0x8f420340, 0x8f820120, 0xafa20010, 
+0x8f820124, 0x3c040001, 0x24846204, 0x3c050009, 
+0xafa20014, 0x8fa60020, 0x34a50300, 0xc002b3b, 
+0x2203821, 0x8f4202e0, 0x24420001, 0xaf4202e0, 
+0x8f4202e0, 0x8f4202f0, 0x24420001, 0xaf4202f0, 
+0x8f4202f0, 0x8fa20034, 0x8fbf0058, 0x8fbe0054, 
+0x8fb50050, 0x8fb3004c, 0x8fb20048, 0x8fb10044, 
+0x8fb00040, 0x3e00008, 0x27bd0060, 0x27bdfff8, 
+0x2408ffff, 0x10a00014, 0x4821, 0x3c0aedb8, 
+0x354a8320, 0x90870000, 0x24840001, 0x3021, 
+0x1071026, 0x30420001, 0x10400002, 0x81842, 
+0x6a1826, 0x604021, 0x24c60001, 0x2cc20008, 
+0x1440fff7, 0x73842, 0x25290001, 0x125102b, 
+0x1440fff0, 0x0, 0x1001021, 0x3e00008, 
+0x27bd0008, 0x27bdffb0, 0xafbf0048, 0xafbe0044, 
+0xafb50040, 0xafb3003c, 0xafb20038, 0xafb10034, 
+0xafb00030, 0x8f870220, 0xafa70024, 0x8f870200, 
+0xafa7002c, 0x8f820220, 0x3c0308ff, 0x3463ffff, 
+0x431024, 0x34420004, 0xaf820220, 0x8f820200, 
+0x3c03c0ff, 0x3463ffff, 0x431024, 0x34420004, 
+0xaf820200, 0x8f530358, 0x8f55035c, 0x8f5e0360, 
+0x8f470364, 0xafa70014, 0x8f470368, 0xafa7001c, 
+0x8f4202d0, 0x274401c0, 0x24420001, 0xaf4202d0, 
+0x8f5002d0, 0x8f510204, 0x8f520200, 0xc002ba8, 
+0x24050400, 0xaf530358, 0xaf55035c, 0xaf5e0360, 
+0x8fa70014, 0xaf470364, 0x8fa7001c, 0xaf470368, 
+0xaf5002d0, 0xaf510204, 0xaf520200, 0x8c02025c, 
+0x27440224, 0xaf4201f0, 0x8c020260, 0x24050200, 
+0x24060008, 0xaf4201f8, 0x24020006, 0xc002bbf, 
+0xaf4201f4, 0x3c023b9a, 0x3442ca00, 0xaf4201fc, 
+0x240203e8, 0x24040002, 0x24030001, 0xaf420294, 
+0xaf440290, 0xaf43029c, 0x8f820220, 0x30420008, 
+0x10400004, 0x0, 0xaf430298, 0x10000003, 
+0x3021, 0xaf440298, 0x3021, 0x3c030001, 
+0x661821, 0x90636d00, 0x3461021, 0x24c60001, 
+0xa043022c, 0x2cc2000f, 0x1440fff8, 0x3461821, 
+0x24c60001, 0x8f820040, 0x24040080, 0x24050080, 
+0x21702, 0x24420030, 0xa062022c, 0x3461021, 
+0xc002ba8, 0xa040022c, 0x8fa70024, 0x30e20004, 
+0x14400006, 0x0, 0x8f820220, 0x3c0308ff, 
+0x3463fffb, 0x431024, 0xaf820220, 0x8fa7002c, 
+0x30e20004, 0x14400006, 0x0, 0x8f820200, 
+0x3c03c0ff, 0x3463fffb, 0x431024, 0xaf820200, 
+0x8fbf0048, 0x8fbe0044, 0x8fb50040, 0x8fb3003c, 
+0x8fb20038, 0x8fb10034, 0x8fb00030, 0x3e00008, 
+0x27bd0050, 0x0, 0x0, 0xaf400104, 
+0x24040001, 0x410c0, 0x2e21821, 0x24820001, 
+0x3c010001, 0x230821, 0xa42234d0, 0x402021, 
+0x2c820080, 0x1440fff8, 0x410c0, 0x24020001, 
+0x3c010001, 0x370821, 0xa42038d0, 0xaf420100, 
+0xaf800228, 0xaf80022c, 0xaf800230, 0xaf800234, 
+0x3e00008, 0x0, 0x27bdffe8, 0xafbf0014, 
+0xafb00010, 0x8f420104, 0x28420005, 0x10400026, 
+0x808021, 0x3c020001, 0x8f430104, 0x344230d0, 
+0x2e22021, 0x318c0, 0x621821, 0x2e31821, 
+0x83102b, 0x10400015, 0x1021, 0x96070000, 
+0x24840006, 0x24660006, 0x9482fffc, 0x14470009, 
+0x2821, 0x9483fffe, 0x96020002, 0x14620006, 
+0xa01021, 0x94820000, 0x96030004, 0x431026, 
+0x2c450001, 0xa01021, 0x14400009, 0x24840008, 
+0x86102b, 0x1440fff0, 0x1021, 0x304200ff, 
+0x14400030, 0x24020001, 0x1000002e, 0x1021, 
+0x1000fffa, 0x24020001, 0x2002021, 0xc00240c, 
+0x24050006, 0x3042007f, 0x218c0, 0x2e31021, 
+0x3c010001, 0x220821, 0x942230d0, 0x1040fff2, 
+0x2e31021, 0x3c060001, 0xc23021, 0x94c630d0, 
+0x10c0ffed, 0x3c080001, 0x350834d2, 0x96070000, 
+0x610c0, 0x572021, 0x882021, 0x94820000, 
+0x14470009, 0x2821, 0x94830002, 0x96020002, 
+0x14620006, 0xa01021, 0x94820004, 0x96030004, 
+0x431026, 0x2c450001, 0xa01021, 0x14400007, 
+0x610c0, 0x2e21021, 0x3c060001, 0xc23021, 
+0x94c634d0, 0x14c0ffeb, 0x610c0, 0x10c0ffd2, 
+0x24020001, 0x8fbf0014, 0x8fb00010, 0x3e00008, 
+0x27bd0018, 0x3e00008, 0x0, 0x27bdffb0, 
+0x801021, 0xafb00030, 0x24500002, 0x2002021, 
+0x24050006, 0xafb10034, 0x408821, 0xafbf0048, 
+0xafbe0044, 0xafb50040, 0xafb3003c, 0xc00240c, 
+0xafb20038, 0x3047007f, 0x710c0, 0x2e21021, 
+0x3c050001, 0xa22821, 0x94a530d0, 0x50a0001c, 
+0xa03021, 0x3c090001, 0x352934d2, 0x96280002, 
+0x510c0, 0x572021, 0x892021, 0x94820000, 
+0x14480009, 0x3021, 0x94830002, 0x96020002, 
+0x14620006, 0xc01021, 0x94820004, 0x96030004, 
+0x431026, 0x2c460001, 0xc01021, 0x14400007, 
+0x510c0, 0x2e21021, 0x3c050001, 0xa22821, 
+0x94a534d0, 0x14a0ffeb, 0x510c0, 0xa03021, 
+0x10c00014, 0x610c0, 0x571821, 0x3c010001, 
+0x230821, 0x8c2334d0, 0x571021, 0xafa30010, 
+0x3c010001, 0x220821, 0x8c2234d4, 0x3c040001, 
+0x24846394, 0xafa20014, 0x8e260000, 0x8e270004, 
+0x3c050004, 0xc002b3b, 0x34a50400, 0x10000063, 
+0x3c020800, 0x8f450100, 0x10a00006, 0x510c0, 
+0x2e21021, 0x3c010001, 0x220821, 0x942234d0, 
+0xaf420100, 0xa03021, 0x14c00011, 0x628c0, 
+0x710c0, 0x2e21021, 0xafa70010, 0x3c010001, 
+0x220821, 0x942230d0, 0x3c040001, 0x248463a0, 
+0xafa20014, 0x8e260000, 0x8e270004, 0x3c050004, 
+0xc002b3b, 0x34a50500, 0x10000048, 0x3c020800, 
+0xb71821, 0x3c020001, 0x96040000, 0x344234d2, 
+0x621821, 0xa4640000, 0x8e020002, 0x720c0, 
+0xac620002, 0x2e41021, 0x3c030001, 0x621821, 
+0x946330d0, 0x2e51021, 0x3c010001, 0x220821, 
+0xa42334d0, 0x2e41021, 0x3c010001, 0x220821, 
+0xa42630d0, 0x8f420104, 0x24420001, 0x28420080, 
+0x1040000f, 0x3c020002, 0x8f420104, 0x3c040001, 
+0x348430d2, 0x96030000, 0x210c0, 0x571021, 
+0x441021, 0xa4430000, 0x8e030002, 0xac430002, 
+0x8f420104, 0x24420001, 0xaf420104, 0x3c020002, 
+0x2c21024, 0x10400011, 0x72142, 0x3c030001, 
+0x346338d8, 0x24020003, 0x441023, 0x21080, 
+0x572021, 0x832021, 0x571021, 0x431021, 
+0x30e5001f, 0x8c430000, 0x24020001, 0xa21004, 
+0x621825, 0x1000000c, 0xac830000, 0x24020003, 
+0x441023, 0x21080, 0x5c2821, 0x5c1021, 
+0x30e4001f, 0x8c430228, 0x24020001, 0x821004, 
+0x621825, 0xaca30228, 0x3c020800, 0x34421000, 
+0x1821, 0xafa20020, 0x8f5e0018, 0x27aa0020, 
+0x240200ff, 0x13c20002, 0xafaa002c, 0x27c30001, 
+0x8c020228, 0x609021, 0x1642000e, 0x1e38c0, 
+0x8f42033c, 0x24420001, 0xaf42033c, 0x8f42033c, 
+0x8c020228, 0x3c040001, 0x2484635c, 0x3c050009, 
+0xafa00014, 0xafa20010, 0x8fa60020, 0x1000006b, 
+0x34a50500, 0xf71021, 0x8fa30020, 0x8fa40024, 
+0xac4304c0, 0xac4404c4, 0x8f830054, 0x8f820054, 
+0x247003e8, 0x2021023, 0x2c4203e9, 0x1040001b, 
+0x9821, 0xe08821, 0x263504c0, 0x8f440178, 
+0x8f45017c, 0x2201821, 0x240a0004, 0xafaa0010, 
+0xafb20014, 0x8f48000c, 0x1021, 0x2f53021, 
+0xafa80018, 0x8f48010c, 0x24070008, 0xa32821, 
+0xa3482b, 0x822021, 0x100f809, 0x892021, 
+0x54400006, 0x24130001, 0x8f820054, 0x2021023, 
+0x2c4203e9, 0x1440ffe9, 0x0, 0x326200ff, 
+0x54400017, 0xaf520018, 0x8f420378, 0x24420001, 
+0xaf420378, 0x8f420378, 0x8f820120, 0x8faa002c, 
+0xafa20010, 0x8f820124, 0x3c040001, 0x24846368, 
+0x3c050009, 0xafa20014, 0x8d460000, 0x10000033, 
+0x34a50600, 0x8f420308, 0x24130001, 0x24420001, 
+0xaf420308, 0x8f420308, 0x1000001c, 0x326200ff, 
+0x8f830054, 0x8f820054, 0x247003e8, 0x2021023, 
+0x2c4203e9, 0x10400014, 0x9821, 0x24110010, 
+0x8f42000c, 0x8f440160, 0x8f450164, 0x8f860120, 
+0xafb10010, 0xafb20014, 0xafa20018, 0x8f42010c, 
+0x24070008, 0x40f809, 0x24c6001c, 0x1440ffe5, 
+0x0, 0x8f820054, 0x2021023, 0x2c4203e9, 
+0x1440ffef, 0x0, 0x326200ff, 0x14400011, 
+0x0, 0x8f420378, 0x24420001, 0xaf420378, 
+0x8f420378, 0x8f820120, 0x8faa002c, 0xafa20010, 
+0x8f820124, 0x3c040001, 0x24846370, 0x3c050009, 
+0xafa20014, 0x8d460000, 0x34a50700, 0xc002b3b, 
+0x3c03821, 0x8f4202b4, 0x24420001, 0xaf4202b4, 
+0x8f4202b4, 0x8f4202f4, 0x24420001, 0xaf4202f4, 
+0x8f4202f4, 0x8fbf0048, 0x8fbe0044, 0x8fb50040, 
+0x8fb3003c, 0x8fb20038, 0x8fb10034, 0x8fb00030, 
+0x3e00008, 0x27bd0050, 0x27bdffa0, 0x801021, 
+0xafb00040, 0x24500002, 0x2002021, 0x24050006, 
+0xafb10044, 0x408821, 0xafbf0058, 0xafbe0054, 
+0xafb50050, 0xafb3004c, 0xc00240c, 0xafb20048, 
+0x3048007f, 0x810c0, 0x2e21021, 0x3c060001, 
+0xc23021, 0x94c630d0, 0x10c0001c, 0x3821, 
+0x3c0a0001, 0x354a34d2, 0x96290002, 0x610c0, 
+0x572021, 0x8a2021, 0x94820000, 0x14490009, 
+0x2821, 0x94830002, 0x96020002, 0x14620006, 
+0xa01021, 0x94820004, 0x96030004, 0x431026, 
+0x2c450001, 0xa01021, 0x14400008, 0x610c0, 
+0xc03821, 0x2e21021, 0x3c060001, 0xc23021, 
+0x94c634d0, 0x14c0ffea, 0x610c0, 0x14c00011, 
+0xafa70028, 0x810c0, 0x2e21021, 0xafa80010, 
+0x3c010001, 0x220821, 0x942230d0, 0x3c040001, 
+0x248463ac, 0xafa20014, 0x8e260000, 0x8e270004, 
+0x3c050004, 0xc002b3b, 0x34a50900, 0x10000075, 
+0x3c020800, 0x10e0000c, 0x610c0, 0x2e21021, 
+0x3c030001, 0x621821, 0x946334d0, 0x710c0, 
+0x2e21021, 0x3c010001, 0x220821, 0xa42334d0, 
+0x1000000b, 0x3c040001, 0x2e21021, 0x3c030001, 
+0x621821, 0x946334d0, 0x810c0, 0x2e21021, 
+0x3c010001, 0x220821, 0xa42330d0, 0x3c040001, 
+0x348430d0, 0x8f430100, 0x610c0, 0x2e21021, 
+0x3c010001, 0x220821, 0xa42334d0, 0x8f420104, 
+0x2e43821, 0x2821, 0x18400029, 0xaf460100, 
+0x24e60006, 0x94c3fffc, 0x96020000, 0x14620009, 
+0x2021, 0x94c3fffe, 0x96020002, 0x14620006, 
+0x801021, 0x94c20000, 0x96030004, 0x431026, 
+0x2c440001, 0x801021, 0x50400014, 0x24a50001, 
+0x8f420104, 0x2442ffff, 0xa2102a, 0x1040000b, 
+0x24e40004, 0x94820006, 0x8c830008, 0xa482fffe, 
+0xac830000, 0x8f420104, 0x24a50001, 0x2442ffff, 
+0xa2102a, 0x1440fff7, 0x24840008, 0x8f420104, 
+0x2442ffff, 0x10000006, 0xaf420104, 0x8f420104, 
+0x24c60008, 0xa2102a, 0x1440ffda, 0x24e70008, 
+0x810c0, 0x2e21021, 0x3c010001, 0x220821, 
+0x942230d0, 0x14400023, 0x3c020800, 0x3c020002, 
+0x2c21024, 0x10400012, 0x82142, 0x3c030001, 
+0x346338d8, 0x24020003, 0x441023, 0x21080, 
+0x572021, 0x832021, 0x571021, 0x431021, 
+0x3105001f, 0x24030001, 0x8c420000, 0xa31804, 
+0x31827, 0x431024, 0x1000000d, 0xac820000, 
+0x24020003, 0x441023, 0x21080, 0x5c2821, 
+0x5c1021, 0x3104001f, 0x24030001, 0x8c420228, 
+0x831804, 0x31827, 0x431024, 0xaca20228, 
+0x3c020800, 0x34422000, 0x1821, 0xafa20020, 
+0x8f5e0018, 0x27ab0020, 0x240200ff, 0x13c20002, 
+0xafab0034, 0x27c30001, 0x8c020228, 0x609021, 
+0x1642000e, 0x1e38c0, 0x8f42033c, 0x24420001, 
+0xaf42033c, 0x8f42033c, 0x8c020228, 0x3c040001, 
+0x2484635c, 0x3c050009, 0xafa00014, 0xafa20010, 
+0x8fa60020, 0x1000006b, 0x34a50500, 0xf71021, 
+0x8fa30020, 0x8fa40024, 0xac4304c0, 0xac4404c4, 
+0x8f830054, 0x8f820054, 0x247003e8, 0x2021023, 
+0x2c4203e9, 0x1040001b, 0x9821, 0xe08821, 
+0x263504c0, 0x8f440178, 0x8f45017c, 0x2201821, 
+0x240b0004, 0xafab0010, 0xafb20014, 0x8f48000c, 
+0x1021, 0x2f53021, 0xafa80018, 0x8f48010c, 
+0x24070008, 0xa32821, 0xa3482b, 0x822021, 
+0x100f809, 0x892021, 0x54400006, 0x24130001, 
+0x8f820054, 0x2021023, 0x2c4203e9, 0x1440ffe9, 
+0x0, 0x326200ff, 0x54400017, 0xaf520018, 
+0x8f420378, 0x24420001, 0xaf420378, 0x8f420378, 
+0x8f820120, 0x8fab0034, 0xafa20010, 0x8f820124, 
+0x3c040001, 0x24846368, 0x3c050009, 0xafa20014, 
+0x8d660000, 0x10000033, 0x34a50600, 0x8f420308, 
+0x24130001, 0x24420001, 0xaf420308, 0x8f420308, 
+0x1000001c, 0x326200ff, 0x8f830054, 0x8f820054, 
+0x247003e8, 0x2021023, 0x2c4203e9, 0x10400014, 
+0x9821, 0x24110010, 0x8f42000c, 0x8f440160, 
+0x8f450164, 0x8f860120, 0xafb10010, 0xafb20014, 
+0xafa20018, 0x8f42010c, 0x24070008, 0x40f809, 
+0x24c6001c, 0x1440ffe5, 0x0, 0x8f820054, 
+0x2021023, 0x2c4203e9, 0x1440ffef, 0x0, 
+0x326200ff, 0x14400011, 0x0, 0x8f420378, 
+0x24420001, 0xaf420378, 0x8f420378, 0x8f820120, 
+0x8fab0034, 0xafa20010, 0x8f820124, 0x3c040001, 
+0x24846370, 0x3c050009, 0xafa20014, 0x8d660000, 
+0x34a50700, 0xc002b3b, 0x3c03821, 0x8f4202b8, 
+0x24420001, 0xaf4202b8, 0x8f4202b8, 0x8f4202f4, 
+0x24420001, 0xaf4202f4, 0x8f4202f4, 0x8fbf0058, 
+0x8fbe0054, 0x8fb50050, 0x8fb3004c, 0x8fb20048, 
+0x8fb10044, 0x8fb00040, 0x3e00008, 0x27bd0060, 
+0x0, 0x0, 0x0, 0x27bdffe0, 
+0x27644000, 0xafbf0018, 0xc002ba8, 0x24051000, 
+0x3c030001, 0x34632cc0, 0x3c040001, 0x34842ec8, 
+0x24020020, 0xaf82011c, 0x2e31021, 0xaf800100, 
+0xaf800104, 0xaf800108, 0xaf800110, 0xaf800114, 
+0xaf800118, 0xaf800120, 0xaf800124, 0xaf800128, 
+0xaf800130, 0xaf800134, 0xaf800138, 0xaf4200ec, 
+0x2e31021, 0xaf4200f0, 0x2e41021, 0xaf4200f4, 
+0x2e41021, 0xaf4200f8, 0x3c020001, 0x571021, 
+0x904240f4, 0x1440001c, 0x3c050001, 0x8f82011c, 
+0x3c040001, 0x24846470, 0x3c050001, 0x34420001, 
+0xaf82011c, 0xafa00010, 0xafa00014, 0x8f86011c, 
+0x34a50100, 0xc002b3b, 0x3821, 0x8c020218, 
+0x30420040, 0x10400014, 0x0, 0x8f82011c, 
+0x3c040001, 0x2484647c, 0x3c050001, 0x34420004, 
+0xaf82011c, 0xafa00010, 0xafa00014, 0x8f86011c, 
+0x10000007, 0x34a50200, 0x3c040001, 0x24846484, 
+0xafa00010, 0xafa00014, 0x8f86011c, 0x34a50300, 
+0xc002b3b, 0x3821, 0x8fbf0018, 0x3e00008, 
+0x27bd0020, 0x8fa90010, 0x8f83012c, 0x8faa0014, 
+0x8fab0018, 0x1060000a, 0x27624fe0, 0x14620002, 
+0x24680020, 0x27684800, 0x8f820128, 0x11020004, 
+0x0, 0x8f820124, 0x15020007, 0x0, 
+0x8f430334, 0x1021, 0x24630001, 0xaf430334, 
+0x10000039, 0x8f430334, 0xac640000, 0xac650004, 
+0xac660008, 0xa467000e, 0xac690018, 0xac6a001c, 
+0xac6b0010, 0xac620014, 0xaf880120, 0x8f4200fc, 
+0x8f4400f4, 0x2442ffff, 0xaf4200fc, 0x8c820000, 
+0x10490005, 0x3042ff8f, 0x10400019, 0x3122ff8f, 
+0x10400018, 0x3c020001, 0x8c830004, 0x2c620010, 
+0x10400013, 0x3c020001, 0x24630001, 0xac830004, 
+0x8f4300f8, 0x344230c8, 0x2e21021, 0x54620004, 
+0x24620008, 0x3c020001, 0x34422ec8, 0x2e21021, 
+0x14440015, 0x24020001, 0x8f820128, 0x24420020, 
+0xaf820128, 0x8f820128, 0x1000000f, 0x24020001, 
+0x3c020001, 0x344230c8, 0x2e21021, 0x54820004, 
+0x24820008, 0x3c020001, 0x34422ec8, 0x2e21021, 
+0x402021, 0x24020001, 0xaf4400f4, 0xac890000, 
+0xac820004, 0x24020001, 0x3e00008, 0x0, 
+0x3e00008, 0x0, 0x8fa90010, 0x8f83010c, 
+0x8faa0014, 0x8fab0018, 0x1060000a, 0x276247e0, 
+0x14620002, 0x24680020, 0x27684000, 0x8f820108, 
+0x11020004, 0x0, 0x8f820104, 0x15020007, 
+0x0, 0x8f430338, 0x1021, 0x24630001, 
+0xaf430338, 0x10000035, 0x8f430338, 0xac640000, 
+0xac650004, 0xac660008, 0xa467000e, 0xac690018, 
+0xac6a001c, 0xac6b0010, 0xac620014, 0xaf880100, 
+0x8f4400ec, 0x8c820000, 0x30420006, 0x10400019, 
+0x31220006, 0x10400018, 0x3c020001, 0x8c830004, 
+0x2c620010, 0x10400013, 0x3c020001, 0x24630001, 
+0xac830004, 0x8f4300f0, 0x34422ec0, 0x2e21021, 
+0x54620004, 0x24620008, 0x3c020001, 0x34422cc0, 
+0x2e21021, 0x14440015, 0x24020001, 0x8f820108, 
+0x24420020, 0xaf820108, 0x8f820108, 0x1000000f, 
+0x24020001, 0x3c020001, 0x34422ec0, 0x2e21021, 
+0x54820004, 0x24820008, 0x3c020001, 0x34422cc0, 
+0x2e21021, 0x402021, 0x24020001, 0xaf4400ec, 
+0xac890000, 0xac820004, 0x24020001, 0x3e00008, 
+0x0, 0x3e00008, 0x0, 0x27bdffd8, 
+0x3c040001, 0x2484648c, 0x3c050001, 0xafbf0024, 
+0xafb20020, 0xafb1001c, 0xafb00018, 0x8f900104, 
+0x8f9100b0, 0x8f92011c, 0x34a52500, 0x8f820100, 
+0x2403021, 0x2203821, 0xafa20010, 0xc002b3b, 
+0xafb00014, 0x8e020008, 0xafa20010, 0x8e02000c, 
+0x3c040001, 0x24846498, 0xafa20014, 0x8e060000, 
+0x8e070004, 0x3c050001, 0xc002b3b, 0x34a52510, 
+0x8e020018, 0xafa20010, 0x8e02001c, 0x3c040001, 
+0x248464a4, 0xafa20014, 0x8e060010, 0x8e070014, 
+0x3c050001, 0xc002b3b, 0x34a52520, 0x3c027f00, 
+0x2221024, 0x3c030800, 0x54430016, 0x3c030200, 
+0x8f82009c, 0x3042ffff, 0x14400012, 0x3c030200, 
+0x3c040001, 0x248464b0, 0x3c050002, 0x34a5f030, 
+0x3021, 0x3821, 0x36420002, 0xaf82011c, 
+0x36220001, 0xaf8200b0, 0xaf900104, 0xaf92011c, 
+0xafa00010, 0xc002b3b, 0xafa00014, 0x10000024, 
+0x0, 0x2c31024, 0x1040000d, 0x2231024, 
+0x1040000b, 0x36420002, 0xaf82011c, 0x36220001, 
+0xaf8200b0, 0xaf900104, 0xaf92011c, 0x8f420330, 
+0x24420001, 0xaf420330, 0x10000015, 0x8f420330, 
+0x3c040001, 0x248464b8, 0x240202a9, 0xafa20010, 
+0xafa00014, 0x8f860144, 0x3c070001, 0x24e764c0, 
+0xc002b3b, 0x3405dead, 0x8f82011c, 0x34420002, 
+0xaf82011c, 0x8f820220, 0x34420004, 0xaf820220, 
+0x8f820140, 0x3c030001, 0x431025, 0xaf820140, 
+0x8fbf0024, 0x8fb20020, 0x8fb1001c, 0x8fb00018, 
+0x3e00008, 0x27bd0028, 0x27bdffd8, 0x3c040001, 
+0x248464e8, 0x3c050001, 0xafbf0024, 0xafb20020, 
+0xafb1001c, 0xafb00018, 0x8f900124, 0x8f9100a0, 
+0x8f92011c, 0x34a52600, 0x8f820120, 0x2403021, 
+0x2203821, 0xafa20010, 0xc002b3b, 0xafb00014, 
+0x8e020008, 0xafa20010, 0x8e02000c, 0x3c040001, 
+0x248464f4, 0xafa20014, 0x8e060000, 0x8e070004, 
+0x3c050001, 0xc002b3b, 0x34a52610, 0x8e020018, 
+0xafa20010, 0x8e02001c, 0x3c040001, 0x24846500, 
+0xafa20014, 0x8e060010, 0x8e070014, 0x3c050001, 
+0xc002b3b, 0x34a52620, 0x3c027f00, 0x2221024, 
+0x3c030800, 0x54430016, 0x3c030200, 0x8f8200ac, 
+0x3042ffff, 0x14400012, 0x3c030200, 0x3c040001, 
+0x2484650c, 0x3c050001, 0x34a5f030, 0x3021, 
+0x3821, 0x36420002, 0xaf82011c, 0x36220001, 
+0xaf8200a0, 0xaf900124, 0xaf92011c, 0xafa00010, 
+0xc002b3b, 0xafa00014, 0x10000024, 0x0, 
+0x2c31024, 0x1040000d, 0x2231024, 0x1040000b, 
+0x36420002, 0xaf82011c, 0x36220001, 0xaf8200a0, 
+0xaf900124, 0xaf92011c, 0x8f42032c, 0x24420001, 
+0xaf42032c, 0x10000015, 0x8f42032c, 0x3c040001, 
+0x248464b8, 0x240202e2, 0xafa20010, 0xafa00014, 
+0x8f860144, 0x3c070001, 0x24e764c0, 0xc002b3b, 
+0x3405dead, 0x8f82011c, 0x34420002, 0xaf82011c, 
+0x8f820220, 0x34420004, 0xaf820220, 0x8f820140, 
+0x3c030001, 0x431025, 0xaf820140, 0x8fbf0024, 
+0x8fb20020, 0x8fb1001c, 0x8fb00018, 0x3e00008, 
+0x27bd0028, 0x6021, 0x5021, 0x3021, 
+0x2821, 0x6821, 0x4821, 0x7821, 
+0x7021, 0x8f880124, 0x8f870104, 0x1580002e, 
+0x8f8b011c, 0x11a00014, 0x31620800, 0x8f820120, 
+0x10460029, 0x0, 0x3c040001, 0x8c846ee4, 
+0x8cc20000, 0x8cc30004, 0xac820000, 0xac830004, 
+0x8cc20008, 0xac820008, 0x94c2000e, 0xa482000e, 
+0x8cc20010, 0x240c0001, 0xac820010, 0x8cc20014, 
+0x10000012, 0x24c60020, 0x10400017, 0x0, 
+0x3c040001, 0x8c846ee4, 0x8d020000, 0x8d030004, 
+0xac820000, 0xac830004, 0x8d020008, 0xac820008, 
+0x9502000e, 0xa482000e, 0x8d020010, 0x25060020, 
+0xac820010, 0x8d020014, 0x240c0001, 0xc01821, 
+0xac820014, 0x27624fe0, 0x43102b, 0x54400001, 
+0x27634800, 0x603021, 0x1540002f, 0x31620100, 
+0x11200014, 0x31628000, 0x8f820100, 0x1045002a, 
+0x31620100, 0x3c040001, 0x8c846ee0, 0x8ca20000, 
+0x8ca30004, 0xac820000, 0xac830004, 0x8ca20008, 
+0xac820008, 0x94a2000e, 0xa482000e, 0x8ca20010, 
+0x240a0001, 0xac820010, 0x8ca20014, 0x10000012, 
+0x24a50020, 0x10400018, 0x31620100, 0x3c040001, 
+0x8c846ee0, 0x8ce20000, 0x8ce30004, 0xac820000, 
+0xac830004, 0x8ce20008, 0xac820008, 0x94e2000e, 
+0xa482000e, 0x8ce20010, 0x24e50020, 0xac820010, 
+0x8ce20014, 0x240a0001, 0xa01821, 0xac820014, 
+0x276247e0, 0x43102b, 0x54400001, 0x27634000, 
+0x602821, 0x31620100, 0x5440001d, 0x31621000, 
+0x11a00009, 0x31a20800, 0x10400004, 0x25020020, 
+0x8f8200a8, 0xa5e20000, 0x25020020, 0xaf820124, 
+0x8f880124, 0x6821, 0x11800011, 0x31621000, 
+0x3c040001, 0x8c846ee4, 0x8c820000, 0x8c830004, 
+0xaf820080, 0xaf830084, 0x8c820008, 0xaf8200a4, 
+0x9482000e, 0xaf8200ac, 0x8c820010, 0x6021, 
+0xaf8200a0, 0x8c8d0010, 0x8c8f0014, 0x31621000, 
+0x1440ff82, 0x0, 0x1120000f, 0x31220800, 
+0x10400004, 0x3c020002, 0x8f8200b8, 0xa5c20000, 
+0x3c020002, 0x1221024, 0x10400004, 0x24e20020, 
+0x8f8200b4, 0xaf8200d4, 0x24e20020, 0xaf820104, 
+0x8f870104, 0x4821, 0x1140ff70, 0x0, 
+0x3c040001, 0x8c846ee0, 0x8c820000, 0x8c830004, 
+0xaf820090, 0xaf830094, 0x8c820008, 0xaf8200b4, 
+0x9482000e, 0xaf82009c, 0x8c820010, 0x5021, 
+0xaf8200b0, 0x8c890010, 0x1000ff60, 0x8c8e0014, 
+0x3e00008, 0x0, 0x6021, 0x5821, 
+0x3021, 0x2821, 0x6821, 0x5021, 
+0x7821, 0x7021, 0x8f880124, 0x8f870104, 
+0x3c180100, 0x1580002e, 0x8f89011c, 0x11a00014, 
+0x31220800, 0x8f820120, 0x10460029, 0x0, 
+0x3c040001, 0x8c846ee4, 0x8cc20000, 0x8cc30004, 
+0xac820000, 0xac830004, 0x8cc20008, 0xac820008, 
+0x94c2000e, 0xa482000e, 0x8cc20010, 0x240c0001, 
+0xac820010, 0x8cc20014, 0x10000012, 0x24c60020, 
+0x10400017, 0x0, 0x3c040001, 0x8c846ee4, 
+0x8d020000, 0x8d030004, 0xac820000, 0xac830004, 
+0x8d020008, 0xac820008, 0x9502000e, 0xa482000e, 
+0x8d020010, 0x25060020, 0xac820010, 0x8d020014, 
+0x240c0001, 0xc01821, 0xac820014, 0x27624fe0, 
+0x43102b, 0x54400001, 0x27634800, 0x603021, 
+0x1560002f, 0x31220100, 0x11400014, 0x31228000, 
+0x8f820100, 0x1045002a, 0x31220100, 0x3c040001, 
+0x8c846ee0, 0x8ca20000, 0x8ca30004, 0xac820000, 
+0xac830004, 0x8ca20008, 0xac820008, 0x94a2000e, 
+0xa482000e, 0x8ca20010, 0x240b0001, 0xac820010, 
+0x8ca20014, 0x10000012, 0x24a50020, 0x10400018, 
+0x31220100, 0x3c040001, 0x8c846ee0, 0x8ce20000, 
+0x8ce30004, 0xac820000, 0xac830004, 0x8ce20008, 
+0xac820008, 0x94e2000e, 0xa482000e, 0x8ce20010, 
+0x24e50020, 0xac820010, 0x8ce20014, 0x240b0001, 
+0xa01821, 0xac820014, 0x276247e0, 0x43102b, 
+0x54400001, 0x27634000, 0x602821, 0x31220100, 
+0x5440001d, 0x31221000, 0x11a00009, 0x31a20800, 
+0x10400004, 0x25020020, 0x8f8200a8, 0xa5e20000, 
+0x25020020, 0xaf820124, 0x8f880124, 0x6821, 
+0x11800011, 0x31221000, 0x3c040001, 0x8c846ee4, 
+0x8c820000, 0x8c830004, 0xaf820080, 0xaf830084, 
+0x8c820008, 0xaf8200a4, 0x9482000e, 0xaf8200ac, 
+0x8c820010, 0x6021, 0xaf8200a0, 0x8c8d0010, 
+0x8c8f0014, 0x31221000, 0x14400022, 0x0, 
+0x1140000f, 0x31420800, 0x10400004, 0x3c020002, 
+0x8f8200b8, 0xa5c20000, 0x3c020002, 0x1421024, 
+0x10400004, 0x24e20020, 0x8f8200b4, 0xaf8200d4, 
+0x24e20020, 0xaf820104, 0x8f870104, 0x5021, 
+0x11600010, 0x0, 0x3c040001, 0x8c846ee0, 
+0x8c820000, 0x8c830004, 0xaf820090, 0xaf830094, 
+0x8c820008, 0xaf8200b4, 0x9482000e, 0xaf82009c, 
+0x8c820010, 0x5821, 0xaf8200b0, 0x8c8a0010, 
+0x8c8e0014, 0x8f820070, 0x3c031000, 0x431024, 
+0x1040ff5c, 0x0, 0x8f820054, 0x24420005, 
+0xaf820078, 0x8c040234, 0x10800016, 0x1821, 
+0x3c020001, 0x571021, 0x8c4240e8, 0x24420005, 
+0x3c010001, 0x370821, 0xac2240e8, 0x3c020001, 
+0x571021, 0x8c4240e8, 0x44102b, 0x14400009, 
+0x24020001, 0x3c030080, 0x3c010001, 0x370821, 
+0xac2040e8, 0x3c010001, 0x370821, 0x1000000c, 
+0xa02240f0, 0x3c020001, 0x571021, 0x904240f0, 
+0x14400006, 0x3c020080, 0x3c020001, 0x571021, 
+0x904240f1, 0x10400002, 0x3c020080, 0x621825, 
+0x8c040230, 0x10800013, 0x0, 0x3c020001, 
+0x571021, 0x8c4240ec, 0x24420005, 0x3c010001, 
+0x370821, 0xac2240ec, 0x3c020001, 0x571021, 
+0x8c4240ec, 0x44102b, 0x14400006, 0x0, 
+0x3c010001, 0x370821, 0xac2040ec, 0x10000006, 
+0x781825, 0x3c020001, 0x571021, 0x904240f2, 
+0x54400001, 0x781825, 0x1060ff1a, 0x0, 
+0x8f420000, 0x10400007, 0x0, 0xaf80004c, 
+0x8f82004c, 0x1040fffd, 0x0, 0x10000005, 
+0x0, 0xaf800048, 0x8f820048, 0x1040fffd, 
+0x0, 0x8f820060, 0x431025, 0xaf820060, 
+0x8f420000, 0x10400003, 0x0, 0x1000ff05, 
+0xaf80004c, 0x1000ff03, 0xaf800048, 0x3e00008, 
+0x0, 0x0, 0x0, 0x3c020001, 
+0x8c426d28, 0x27bdffe8, 0xafbf0014, 0x14400012, 
+0xafb00010, 0x3c100001, 0x26106f90, 0x2002021, 
+0xc002ba8, 0x24052000, 0x26021fe0, 0x3c010001, 
+0xac226eec, 0x3c010001, 0xac226ee8, 0xac020250, 
+0x24022000, 0xac100254, 0xac020258, 0x24020001, 
+0x3c010001, 0xac226d28, 0x8fbf0014, 0x8fb00010, 
+0x3e00008, 0x27bd0018, 0x3c090001, 0x8d296eec, 
+0x8c820000, 0x8fa30010, 0x8fa80014, 0xad220000, 
+0x8c820004, 0xad250008, 0xad220004, 0x8f820054, 
+0xad260010, 0xad270014, 0xad230018, 0xad28001c, 
+0xad22000c, 0x2529ffe0, 0x3c020001, 0x24426f90, 
+0x122102b, 0x10400003, 0x0, 0x3c090001, 
+0x8d296ee8, 0x3c020001, 0x8c426d10, 0xad220000, 
+0x3c020001, 0x8c426d10, 0x3c010001, 0xac296eec, 
+0xad220004, 0xac090250, 0x3e00008, 0x0, 
+0x27bdffd0, 0xafb00010, 0x3c100001, 0x8e106eec, 
+0x3c020001, 0x8c426d10, 0xafb10014, 0x808821, 
+0xafbe0024, 0x8fbe0040, 0x8fa40048, 0xafb20018, 
+0xa09021, 0xafbf0028, 0xafb50020, 0xafb3001c, 
+0xae020000, 0x3c020001, 0x8c426d10, 0xc09821, 
+0xe0a821, 0x10800006, 0xae020004, 0x26050008, 
+0xc002bb3, 0x24060018, 0x10000005, 0x2610ffe0, 
+0x26040008, 0xc002ba8, 0x24050018, 0x2610ffe0, 
+0x3c030001, 0x24636f90, 0x203102b, 0x10400003, 
+0x0, 0x3c100001, 0x8e106ee8, 0x8e220000, 
+0xae020000, 0x8e220004, 0xae120008, 0xae020004, 
+0x8f820054, 0xae130010, 0xae150014, 0xae1e0018, 
+0x8fa80044, 0xae08001c, 0xae02000c, 0x2610ffe0, 
+0x203102b, 0x10400003, 0x0, 0x3c100001, 
+0x8e106ee8, 0x3c020001, 0x8c426d10, 0xae020000, 
+0x3c020001, 0x8c426d10, 0x3c010001, 0xac306eec, 
+0xae020004, 0xac100250, 0x8fbf0028, 0x8fbe0024, 
+0x8fb50020, 0x8fb3001c, 0x8fb20018, 0x8fb10014, 
+0x8fb00010, 0x3e00008, 0x27bd0030, 0x851821, 
+0x83102b, 0x10400006, 0x0, 0xac800000, 
+0x24840004, 0x83102b, 0x5440fffd, 0xac800000, 
+0x3e00008, 0x0, 0xa61821, 0xa3102b, 
+0x10400007, 0x0, 0x8c820000, 0xaca20000, 
+0x24a50004, 0xa3102b, 0x1440fffb, 0x24840004, 
+0x3e00008, 0x0, 0x861821, 0x83102b, 
+0x10400007, 0x0, 0x8ca20000, 0xac820000, 
+0x24840004, 0x83102b, 0x1440fffb, 0x24a50004, 
+0x3e00008, 0x0, 0x63080, 0x861821, 
+0x83102b, 0x10400006, 0x0, 0xac850000, 
+0x24840004, 0x83102b, 0x5440fffd, 0xac850000, 
+0x3e00008, 0x0, 0x0, 0x26e50028, 
+0xa03021, 0x274301c0, 0x8f4d0358, 0x8f47035c, 
+0x8f480360, 0x8f490364, 0x8f4a0368, 0x8f4b0204, 
+0x8f4c0200, 0x24640400, 0x64102b, 0x10400008, 
+0x3c0208ff, 0x8cc20000, 0xac620000, 0x24630004, 
+0x64102b, 0x1440fffb, 0x24c60004, 0x3c0208ff, 
+0x3442ffff, 0x3c03c0ff, 0xaf4d0358, 0xaf47035c, 
+0xaf480360, 0xaf490364, 0xaf4a0368, 0xaf4b0204, 
+0xaf4c0200, 0x8f840220, 0x3463ffff, 0x8f860200, 
+0x821024, 0x34420004, 0xc31824, 0x34630004, 
+0xaf820220, 0xaf830200, 0x8ca20214, 0xac020084, 
+0x8ca20218, 0xac020088, 0x8ca2021c, 0xac02008c, 
+0x8ca20220, 0xac020090, 0x8ca20224, 0xac020094, 
+0x8ca20228, 0xac020098, 0x8ca2022c, 0xac02009c, 
+0x8ca20230, 0xac0200a0, 0x8ca20234, 0xac0200a4, 
+0x8ca20238, 0xac0200a8, 0x8ca2023c, 0xac0200ac, 
+0x8ca20240, 0xac0200b0, 0x8ca20244, 0xac0200b4, 
+0x8ca20248, 0xac0200b8, 0x8ca2024c, 0xac0200bc, 
+0x8ca2001c, 0xac020080, 0x8ca20018, 0xac0200c0, 
+0x8ca20020, 0xac0200cc, 0x8ca20024, 0xac0200d0, 
+0x8ca201d0, 0xac0200e0, 0x8ca201d4, 0xac0200e4, 
+0x8ca201d8, 0xac0200e8, 0x8ca201dc, 0xac0200ec, 
+0x8ca201e0, 0xac0200f0, 0x8ca20098, 0x8ca3009c, 
+0xac0300fc, 0x8ca200a8, 0x8ca300ac, 0xac0300f4, 
+0x8ca200a0, 0x8ca300a4, 0x30840004, 0xac0300f8, 
+0x14800007, 0x30c20004, 0x8f820220, 0x3c0308ff, 
+0x3463fffb, 0x431024, 0xaf820220, 0x30c20004, 
+0x14400006, 0x0, 0x8f820200, 0x3c03c0ff, 
+0x3463fffb, 0x431024, 0xaf820200, 0x8f4202dc, 
+0xa34005c5, 0x24420001, 0xaf4202dc, 0x8f4202dc, 
+0x3e00008, 0x0, 0x27bdffd8, 0xafbf0024, 
+0xafb00020, 0x8f430024, 0x8f420020, 0x10620038, 
+0x0, 0x8f430020, 0x8f420024, 0x622023, 
+0x4810003, 0x0, 0x8f420040, 0x822021, 
+0x8f430030, 0x8f420024, 0x43102b, 0x14400005, 
+0x0, 0x8f430040, 0x8f420024, 0x10000005, 
+0x621023, 0x8f420030, 0x8f430024, 0x431023, 
+0x2442ffff, 0x406021, 0x8c102a, 0x54400001, 
+0x806021, 0x8f4a0024, 0x8f490040, 0x8f480024, 
+0x8f440180, 0x8f450184, 0x8f460024, 0x8f4b001c, 
+0x24070001, 0xafa70010, 0x84100, 0x1001821, 
+0x14c5021, 0x2529ffff, 0x1498024, 0xafb00014, 
+0x8f470014, 0x1021, 0x63100, 0xafa70018, 
+0xa32821, 0xa3382b, 0x822021, 0x872021, 
+0x8f420108, 0x1663021, 0x40f809, 0xc3900, 
+0x54400001, 0xaf500024, 0x8f430024, 0x8f420020, 
+0x14620018, 0x0, 0x8f420000, 0x10400007, 
+0x0, 0xaf80004c, 0x8f82004c, 0x1040fffd, 
+0x0, 0x10000005, 0x0, 0xaf800048, 
+0x8f820048, 0x1040fffd, 0x0, 0x8f820060, 
+0x2403ffef, 0x431024, 0xaf820060, 0x8f420000, 
+0x10400003, 0x0, 0x10000002, 0xaf80004c, 
+0xaf800048, 0x8fbf0024, 0x8fb00020, 0x3e00008, 
+0x27bd0028, 0x3e00008, 0x0, 0x27bdffc0, 
+0x32c20020, 0xafbf0038, 0xafb30034, 0xafb20030, 
+0xafb1002c, 0x10400004, 0xafb00028, 0x8f530028, 
+0x10000002, 0x0, 0x8f530020, 0x8f420030, 
+0x105300eb, 0x21100, 0x8f43001c, 0x628021, 
+0x8e040000, 0x8e050004, 0x96120008, 0x8f420090, 
+0x9611000a, 0x3246ffff, 0x46102a, 0x10400017, 
+0x0, 0x8f8200d8, 0x8f430098, 0x431023, 
+0x2442dcbe, 0xaf420090, 0x8f420090, 0x2842dcbf, 
+0x10400005, 0x0, 0x8f420090, 0x8f430144, 
+0x431021, 0xaf420090, 0x8f420090, 0x46102a, 
+0x10400006, 0x0, 0x8f420348, 0x24420001, 
+0xaf420348, 0x100000e1, 0x8f420348, 0x8f8200fc, 
+0x14400006, 0x0, 0x8f420344, 0x24420001, 
+0xaf420344, 0x100000d9, 0x8f420344, 0x934205c2, 
+0x1040000b, 0x32c20008, 0x10400008, 0x32220200, 
+0x10400006, 0x3c034000, 0x9602000e, 0xaf4300ac, 
+0x21400, 0x10000002, 0xaf4200b0, 0xaf4000ac, 
+0x32220004, 0x1040007f, 0x32220800, 0x10400003, 
+0x3247ffff, 0x10000002, 0x24020020, 0x24020004, 
+0xafa20010, 0x8f420030, 0xafa20014, 0x8f420010, 
+0x3c030002, 0x431025, 0xafa20018, 0x8f460098, 
+0x8f420108, 0x40f809, 0x0, 0x104000b7, 
+0x0, 0x8f42009c, 0x8f430094, 0x2421021, 
+0xaf42009c, 0xae03000c, 0x8f4200ac, 0x10400008, 
+0x3c034000, 0x8f420094, 0x431025, 0xafa20020, 
+0x8f42009c, 0x8f4300b0, 0x10000004, 0x431025, 
+0x8f420094, 0xafa20020, 0x8f42009c, 0xafa20024, 
+0x8f8200fc, 0x8fa30020, 0x8fa40024, 0xac430000, 
+0xac440004, 0x24420008, 0xaf8200f0, 0x8f42009c, 
+0x8f440270, 0x8f450274, 0x401821, 0x1021, 
+0xa32821, 0xa3302b, 0x822021, 0x862021, 
+0x32230060, 0x24020040, 0xaf440270, 0xaf450274, 
+0x10620017, 0x2c620041, 0x10400005, 0x24020020, 
+0x10620008, 0x24020001, 0x10000026, 0x0, 
+0x24020060, 0x10620019, 0x24020001, 0x10000021, 
+0x0, 0x8f420278, 0x8f43027c, 0x24630001, 
+0x2c640001, 0x441021, 0xaf420278, 0xaf43027c, 
+0x8f420278, 0x8f43027c, 0x10000016, 0x24020001, 
+0x8f420280, 0x8f430284, 0x24630001, 0x2c640001, 
+0x441021, 0xaf420280, 0xaf430284, 0x8f420280, 
+0x8f430284, 0x1000000b, 0x24020001, 0x8f420288, 
+0x8f43028c, 0x24630001, 0x2c640001, 0x441021, 
+0xaf420288, 0xaf43028c, 0x8f420288, 0x8f43028c, 
+0x24020001, 0xa34205c2, 0x8f420098, 0x3244ffff, 
+0x2406fff8, 0x8f45013c, 0x441021, 0x24420007, 
+0x461024, 0x24840007, 0xaf420094, 0x8f420090, 
+0x8f430094, 0x862024, 0x441023, 0x65182b, 
+0x14600005, 0xaf420090, 0x8f420094, 0x8f430144, 
+0x431023, 0xaf420094, 0x8f420094, 0x10000023, 
+0xaf40009c, 0x3247ffff, 0x50e00022, 0x32c20020, 
+0x14400002, 0x24020010, 0x24020002, 0xafa20010, 
+0x8f420030, 0xafa20014, 0x8f420010, 0xafa20018, 
+0x8f460098, 0x8f420108, 0x40f809, 0x0, 
+0x1040003a, 0x3245ffff, 0x8f420098, 0x8f430090, 
+0x8f46013c, 0x451021, 0xaf420098, 0x8f42009c, 
+0x8f440098, 0xa34005c2, 0x651823, 0xaf430090, 
+0x451021, 0x86202b, 0x14800005, 0xaf42009c, 
+0x8f420098, 0x8f430144, 0x431023, 0xaf420098, 
+0x32c20020, 0x10400005, 0x0, 0x8f420358, 
+0x2442ffff, 0xaf420358, 0x8f420358, 0x8f420030, 
+0x8f430040, 0x24420001, 0x2463ffff, 0x431024, 
+0xaf420030, 0x8f420030, 0x14530018, 0x0, 
+0x8f420000, 0x10400007, 0x0, 0xaf80004c, 
+0x8f82004c, 0x1040fffd, 0x0, 0x10000005, 
+0x0, 0xaf800048, 0x8f820048, 0x1040fffd, 
+0x0, 0x8f820060, 0x2403fff7, 0x431024, 
+0xaf820060, 0x8f420000, 0x10400003, 0x0, 
+0x10000002, 0xaf80004c, 0xaf800048, 0x8fbf0038, 
+0x8fb30034, 0x8fb20030, 0x8fb1002c, 0x8fb00028, 
+0x3e00008, 0x27bd0040, 0x3e00008, 0x0, 
+0x27bdffd0, 0x32c20020, 0xafbf002c, 0xafb20028, 
+0xafb10024, 0x10400004, 0xafb00020, 0x8f520028, 
+0x10000002, 0x0, 0x8f520020, 0x8f420030, 
+0x105200b5, 0x21100, 0x8f43001c, 0x628021, 
+0x8e040000, 0x8e050004, 0x96110008, 0x8f420090, 
+0x9607000a, 0x3226ffff, 0x46102a, 0x10400017, 
+0x0, 0x8f8200d8, 0x8f430098, 0x431023, 
+0x2442dc46, 0xaf420090, 0x8f420090, 0x2842dc47, 
+0x10400005, 0x0, 0x8f420090, 0x8f430144, 
+0x431021, 0xaf420090, 0x8f420090, 0x46102a, 
+0x10400006, 0x0, 0x8f420348, 0x24420001, 
+0xaf420348, 0x100000ab, 0x8f420348, 0x8f8600fc, 
+0x10c0000c, 0x0, 0x8f8200f4, 0x2403fff8, 
+0x431024, 0x461023, 0x218c3, 0x58600001, 
+0x24630100, 0x8f42008c, 0x43102b, 0x14400006, 
+0x712c2, 0x8f420344, 0x24420001, 0xaf420344, 
+0x10000098, 0x8f420344, 0x934305c2, 0x1060000f, 
+0x30460001, 0x8f420010, 0x34480400, 0x32c20008, 
+0x10400008, 0x30e20200, 0x10400006, 0x3c034000, 
+0x9602000e, 0xaf4300ac, 0x21400, 0x10000004, 
+0xaf4200b0, 0x10000002, 0xaf4000ac, 0x8f480010, 
+0x30e20004, 0x10400045, 0x3227ffff, 0x8f4900ac, 
+0x11200005, 0x30c200ff, 0x14400006, 0x24020040, 
+0x10000004, 0x24020008, 0x14400002, 0x24020020, 
+0x24020004, 0xafa20010, 0x8f430030, 0x11200004, 
+0xafa30014, 0x8f4200b0, 0x621025, 0xafa20014, 
+0x3c020002, 0x1021025, 0xafa20018, 0x8f460098, 
+0x8f420108, 0x40f809, 0x0, 0x10400069, 
+0x3224ffff, 0x8f42008c, 0x8f430094, 0x24420001, 
+0xaf42008c, 0x24020001, 0xae03000c, 0xa34205c2, 
+0x8f420098, 0x2406fff8, 0x8f45013c, 0x441021, 
+0x24420007, 0x461024, 0x24840007, 0xaf420094, 
+0x8f420090, 0x8f430094, 0x862024, 0x441023, 
+0x65182b, 0x14600005, 0xaf420090, 0x8f420094, 
+0x8f430144, 0x431023, 0xaf420094, 0x8f430094, 
+0x8f420140, 0x43102b, 0x10400009, 0x0, 
+0x8f43013c, 0x8f440094, 0x8f420090, 0x8f450138, 
+0x641823, 0x431023, 0xaf420090, 0xaf450094, 
+0x8f420094, 0x1000001f, 0xaf420098, 0x10e0001d, 
+0x30c200ff, 0x14400002, 0x24020010, 0x24020002, 
+0xafa20010, 0x8f420030, 0xafa80018, 0xafa20014, 
+0x8f460098, 0x8f420108, 0x40f809, 0x0, 
+0x10400030, 0x3225ffff, 0x8f420098, 0x8f44013c, 
+0x451021, 0xaf420098, 0x8f420090, 0x8f430098, 
+0xa34005c2, 0x451023, 0x64182b, 0x14600005, 
+0xaf420090, 0x8f420098, 0x8f430144, 0x431023, 
+0xaf420098, 0x8f420030, 0x8f430040, 0x24420001, 
+0x2463ffff, 0x431024, 0xaf420030, 0x8f420030, 
+0x14520018, 0x0, 0x8f420000, 0x10400007, 
+0x0, 0xaf80004c, 0x8f82004c, 0x1040fffd, 
+0x0, 0x10000005, 0x0, 0xaf800048, 
+0x8f820048, 0x1040fffd, 0x0, 0x8f820060, 
+0x2403fff7, 0x431024, 0xaf820060, 0x8f420000, 
+0x10400003, 0x0, 0x10000002, 0xaf80004c, 
+0xaf800048, 0x8fbf002c, 0x8fb20028, 0x8fb10024, 
+0x8fb00020, 0x3e00008, 0x27bd0030, 0x3e00008, 
+0x0, 0x27bdffd8, 0x3c020001, 0x34422ec0, 
+0xafbf0020, 0x8f4300f0, 0x8f840108, 0x2e21021, 
+0x54620004, 0x24620008, 0x3c020001, 0x34422cc0, 
+0x2e21021, 0x401821, 0xaf4300f0, 0xac600000, 
+0x8f4200ec, 0x8c660004, 0x14620004, 0x3c020001, 
+0x24820020, 0x1000000f, 0xaf820108, 0x8f4300f0, 
+0x34422ec0, 0x2e21021, 0x54620004, 0x24620008, 
+0x3c020001, 0x34422cc0, 0x2e21021, 0x401821, 
+0x8c620004, 0x21140, 0x821021, 0xaf820108, 
+0xac600000, 0x8c850018, 0x30a20036, 0x1040006c, 
+0x30a20001, 0x8c82001c, 0x8f430040, 0x8f440034, 
+0x24420001, 0x2463ffff, 0x431024, 0x862021, 
+0xaf42002c, 0x30a20030, 0x14400006, 0xaf440034, 
+0x8f420034, 0x8c03023c, 0x43102b, 0x144000b4, 
+0x0, 0x32c20010, 0x10400028, 0x24070008, 
+0x8f440170, 0x8f450174, 0x8f43002c, 0x8f48000c, 
+0x8f860120, 0x24020080, 0xafa20010, 0xafa30014, 
+0xafa80018, 0x8f42010c, 0x40f809, 0x24c6001c, 
+0x14400011, 0x24020001, 0x3c010001, 0x370821, 
+0xa02240f1, 0x8f820124, 0xafa20010, 0x8f820128, 
+0x3c040001, 0x248467c4, 0xafa20014, 0x8f46002c, 
+0x8f870120, 0x3c050009, 0xc002b3b, 0x34a51100, 
+0x10000036, 0x0, 0x8f420300, 0x8f43002c, 
+0x24420001, 0xaf420300, 0x8f420300, 0x24020001, 
+0xa34205c1, 0x10000026, 0xaf430038, 0x8f440170, 
+0x8f450174, 0x8f43002c, 0x8f48000c, 0x8f860120, 
+0x24020020, 0xafa20010, 0xafa30014, 0xafa80018, 
+0x8f42010c, 0x40f809, 0x24c6001c, 0x14400011, 
+0x24020001, 0x3c010001, 0x370821, 0xa02240f0, 
+0x8f820124, 0xafa20010, 0x8f820128, 0x3c040001, 
+0x248467b8, 0xafa20014, 0x8f46002c, 0x8f870120, 
+0x3c050009, 0xc002b3b, 0x34a50900, 0x1000000f, 
+0x0, 0x8f420300, 0x24420001, 0xaf420300, 
+0x8f420300, 0x8f42002c, 0xa34005c1, 0xaf420038, 
+0x3c010001, 0x370821, 0xa02040f1, 0x3c010001, 
+0x370821, 0xa02040f0, 0xaf400034, 0x8f420314, 
+0x24420001, 0xaf420314, 0x10000059, 0x8f420314, 
+0x10400022, 0x30a27000, 0x8c85001c, 0x8f420028, 
+0xa22023, 0x4810003, 0x0, 0x8f420040, 
+0x822021, 0x8f420358, 0x8f430000, 0xaf450028, 
+0x441021, 0x10600007, 0xaf420358, 0xaf80004c, 
+0x8f82004c, 0x1040fffd, 0x0, 0x10000005, 
+0x0, 0xaf800048, 0x8f820048, 0x1040fffd, 
+0x0, 0x8f820060, 0x34420008, 0xaf820060, 
+0x8f420000, 0x10400003, 0x0, 0x10000038, 
+0xaf80004c, 0x10000036, 0xaf800048, 0x1040002f, 
+0x30a21000, 0x1040000c, 0x30a24000, 0x8c83001c, 
+0x8f420050, 0x622023, 0x4820001, 0x24840200, 
+0x8f42035c, 0x441021, 0xaf42035c, 0x8f420368, 
+0x1000001a, 0xaf430050, 0x1040000c, 0x32c28000, 
+0x8c83001c, 0x8f420070, 0x622023, 0x4820001, 
+0x24840400, 0x8f420364, 0x441021, 0xaf420364, 
+0x8f420368, 0x1000000d, 0xaf430070, 0x1040000e, 
+0x3c020800, 0x8c83001c, 0x8f420060, 0x622023, 
+0x4820001, 0x24840100, 0x8f420360, 0x441021, 
+0xaf420360, 0x8f420368, 0xaf430060, 0x441021, 
+0xaf420368, 0x3c020800, 0x2c21024, 0x50400008, 
+0x36940040, 0x10000006, 0x0, 0x30a20100, 
+0x10400003, 0x0, 0xc002bd8, 0x0, 
+0x8fbf0020, 0x3e00008, 0x27bd0028, 0x3e00008, 
+0x0, 0x27bdffa8, 0xafbf0050, 0xafbe004c, 
+0xafb50048, 0xafb30044, 0xafb20040, 0xafb1003c, 
+0xafb00038, 0x8f910108, 0x26220020, 0xaf820108, 
+0x8e320018, 0xa821, 0x32420024, 0x104001ba, 
+0xf021, 0x8e26001c, 0x8f43001c, 0x61100, 
+0x621821, 0x8c70000c, 0x9604000c, 0x962d0016, 
+0x9473000a, 0x2c8305dd, 0x38828870, 0x2c420001, 
+0x621825, 0x10600015, 0x2821, 0x32c20040, 
+0x10400015, 0x24020800, 0x96030014, 0x14620012, 
+0x3402aaaa, 0x9603000e, 0x14620007, 0x2021, 
+0x96030010, 0x24020300, 0x14620004, 0x801021, 
+0x96020012, 0x2c440001, 0x801021, 0x54400006, 
+0x24050016, 0x10000004, 0x0, 0x24020800, 
+0x50820001, 0x2405000e, 0x934205c3, 0x14400008, 
+0x5821, 0x240b0001, 0x32620180, 0xaf4500a8, 
+0xaf5000a0, 0x10400002, 0xaf4600a4, 0xa34b05c3, 
+0x10a00085, 0x2054021, 0x91020000, 0x3821, 
+0x3042000f, 0x25080, 0x32c20002, 0x10400012, 
+0x10a1821, 0x32620002, 0x10400010, 0x32c20001, 
+0x1002021, 0x94820000, 0x24840002, 0xe23821, 
+0x83102b, 0x1440fffb, 0x30e2ffff, 0x71c02, 
+0x623821, 0x71c02, 0x30e2ffff, 0x623821, 
+0x71027, 0xa502000a, 0x32c20001, 0x1040006a, 
+0x32620001, 0x10400068, 0x0, 0x8f4200a8, 
+0x10400065, 0x0, 0x8f4200a0, 0x8f4300a8, 
+0x431021, 0x904c0009, 0x318900ff, 0x39230006, 
+0x3182b, 0x39220011, 0x2102b, 0x621824, 
+0x1060000c, 0x3c050006, 0x8f4200a4, 0x3c040001, 
+0x248467d4, 0xafa20010, 0x8f4200a0, 0x34a54600, 
+0x1203821, 0xc002b3b, 0xafa20014, 0x1000004e, 
+0x0, 0x32c20004, 0x14400013, 0x2821, 
+0x316200ff, 0x14400004, 0x0, 0x95020002, 
+0x1000000d, 0x4a2823, 0x9505000c, 0x9502000e, 
+0x95030010, 0xa22821, 0xa32821, 0x95030012, 
+0x91040009, 0x95020002, 0xa32821, 0xa42821, 
+0x4a1023, 0xa22821, 0x2002021, 0x94820000, 
+0x24840002, 0xe23821, 0x88102b, 0x1440fffb, 
+0x71c02, 0x30e2ffff, 0x623821, 0x71c02, 
+0x30e2ffff, 0x623821, 0x1a52821, 0x51c02, 
+0x30a2ffff, 0x622821, 0x51c02, 0x30a2ffff, 
+0x622821, 0xa72823, 0x51402, 0xa22821, 
+0x30a5ffff, 0x50a00001, 0x3405ffff, 0x316200ff, 
+0x14400008, 0x318300ff, 0x8f4300a0, 0x8f4200a8, 
+0x624021, 0x91020000, 0x3042000f, 0x25080, 
+0x318300ff, 0x24020006, 0x14620003, 0x10a1021, 
+0x10000002, 0x24440010, 0x24440006, 0x316200ff, 
+0x14400006, 0x0, 0x94820000, 0xa22821, 
+0x51c02, 0x30a2ffff, 0x622821, 0x934205c3, 
+0x10400003, 0x32620100, 0x50400003, 0xa4850000, 
+0x52827, 0xa4850000, 0x9622000e, 0x8f43009c, 
+0x621821, 0x32a200ff, 0x10400007, 0xaf43009c, 
+0x3c024000, 0x2021025, 0xafa20020, 0x8f42009c, 
+0x10000003, 0x5e1025, 0xafb00020, 0x8f42009c, 
+0xafa20024, 0x32620080, 0x10400010, 0x32620100, 
+0x8f4200b4, 0x24430001, 0x210c0, 0x571021, 
+0xaf4300b4, 0x8fa30020, 0x8fa40024, 0x3c010001, 
+0x220821, 0xac2338e8, 0x3c010001, 0x220821, 
+0xac2438ec, 0x100000a5, 0x32c20020, 0x10400064, 
+0x0, 0x8f4200b4, 0x24430001, 0x210c0, 
+0x571021, 0xaf4300b4, 0x8fa30020, 0x8fa40024, 
+0x3c010001, 0x220821, 0xac2338e8, 0x3c010001, 
+0x220821, 0xac2438ec, 0x8f4200b4, 0x10400051, 
+0x3821, 0x3c090001, 0x352938e8, 0x3c08001f, 
+0x3508ffff, 0x240bffff, 0x340affff, 0x710c0, 
+0x571021, 0x491021, 0x8c430000, 0x8c440004, 
+0xafa30028, 0xafa4002c, 0x8f8200fc, 0x8fa30028, 
+0x8fa4002c, 0xac430000, 0xac440004, 0x24420008, 
+0xaf8200f0, 0x8f42008c, 0x2442ffff, 0xaf42008c, 
+0x97a2002e, 0x8f440270, 0x8f450274, 0x401821, 
+0x1021, 0xa32821, 0xa3302b, 0x822021, 
+0x862021, 0xaf440270, 0xaf450274, 0x8fa20028, 
+0x481024, 0x90430000, 0x30630001, 0x1460000b, 
+0x402021, 0x8f420278, 0x8f43027c, 0x24630001, 
+0x2c640001, 0x441021, 0xaf420278, 0xaf43027c, 
+0x8f420278, 0x1000001a, 0x8f43027c, 0x8c820000, 
+0x144b000e, 0x0, 0x94820004, 0x144a000b, 
+0x0, 0x8f420288, 0x8f43028c, 0x24630001, 
+0x2c640001, 0x441021, 0xaf420288, 0xaf43028c, 
+0x8f420288, 0x1000000a, 0x8f43028c, 0x8f420280, 
+0x8f430284, 0x24630001, 0x2c640001, 0x441021, 
+0xaf420280, 0xaf430284, 0x8f420280, 0x8f430284, 
+0x8f4200b4, 0x24e70001, 0xe2102b, 0x1440ffb8, 
+0x710c0, 0xa34005c3, 0x1000003f, 0xaf4000b4, 
+0x8f8200fc, 0x8fa30020, 0x8fa40024, 0xac430000, 
+0xac440004, 0x24420008, 0xaf8200f0, 0x8f42009c, 
+0x8f46008c, 0x8f440270, 0x8f450274, 0x401821, 
+0x1021, 0x24c6ffff, 0xaf46008c, 0xa32821, 
+0xa3302b, 0x822021, 0x862021, 0xaf440270, 
+0xaf450274, 0x92020000, 0x30420001, 0x1440000c, 
+0x2402ffff, 0x8f420278, 0x8f43027c, 0x24630001, 
+0x2c640001, 0x441021, 0xaf420278, 0xaf43027c, 
+0x8f420278, 0x8f43027c, 0x1000001c, 0x32c20020, 
+0x8e030000, 0x1462000f, 0x3402ffff, 0x96030004, 
+0x1462000c, 0x0, 0x8f420288, 0x8f43028c, 
+0x24630001, 0x2c640001, 0x441021, 0xaf420288, 
+0xaf43028c, 0x8f420288, 0x8f43028c, 0x1000000b, 
+0x32c20020, 0x8f420280, 0x8f430284, 0x24630001, 
+0x2c640001, 0x441021, 0xaf420280, 0xaf430284, 
+0x8f420280, 0x8f430284, 0x32c20020, 0x10400005, 
+0xaf40009c, 0x8f420358, 0x2442ffff, 0xaf420358, 
+0x8f420358, 0x8e22001c, 0x8f430040, 0x24420001, 
+0x2463ffff, 0x431024, 0xaf42002c, 0x32420060, 
+0x14400008, 0x32c20010, 0x8f420034, 0x24420001, 
+0xaf420034, 0x8c03023c, 0x43102b, 0x14400102, 
+0x32c20010, 0x10400018, 0x24070008, 0x8f440170, 
+0x8f450174, 0x8f43002c, 0x8f48000c, 0x8f860120, 
+0x24020080, 0xafa20010, 0xafa30014, 0xafa80018, 
+0x8f42010c, 0x40f809, 0x24c6001c, 0x10400047, 
+0x24020001, 0x8f420300, 0x8f43002c, 0x24420001, 
+0xaf420300, 0x8f420300, 0x24020001, 0xa34205c1, 
+0x1000007c, 0xaf430038, 0x8f440170, 0x8f450174, 
+0x8f43002c, 0x8f48000c, 0x8f860120, 0x24020020, 
+0xafa20010, 0xafa30014, 0xafa80018, 0x8f42010c, 
+0x40f809, 0x24c6001c, 0x10400057, 0x24020001, 
+0x10000065, 0x0, 0x32420012, 0x10400075, 
+0x32420001, 0x9622000e, 0x8f43009c, 0x621821, 
+0x32c20020, 0x10400005, 0xaf43009c, 0x8f420358, 
+0x2442ffff, 0xaf420358, 0x8f420358, 0x8e22001c, 
+0x8f430040, 0x24420001, 0x2463ffff, 0x431024, 
+0xaf42002c, 0x32420010, 0x14400008, 0x32c20010, 
+0x8f420034, 0x24420001, 0xaf420034, 0x8c03023c, 
+0x43102b, 0x144000bc, 0x32c20010, 0x10400028, 
+0x24070008, 0x8f440170, 0x8f450174, 0x8f43002c, 
+0x8f48000c, 0x8f860120, 0x24020080, 0xafa20010, 
+0xafa30014, 0xafa80018, 0x8f42010c, 0x40f809, 
+0x24c6001c, 0x14400011, 0x24020001, 0x3c010001, 
+0x370821, 0xa02240f1, 0x8f820124, 0xafa20010, 
+0x8f820128, 0x3c040001, 0x248467c4, 0xafa20014, 
+0x8f46002c, 0x8f870120, 0x3c050009, 0xc002b3b, 
+0x34a51100, 0x10000036, 0x0, 0x8f420300, 
+0x8f43002c, 0x24420001, 0xaf420300, 0x8f420300, 
+0x24020001, 0xa34205c1, 0x10000026, 0xaf430038, 
+0x8f440170, 0x8f450174, 0x8f43002c, 0x8f48000c, 
+0x8f860120, 0x24020020, 0xafa20010, 0xafa30014, 
+0xafa80018, 0x8f42010c, 0x40f809, 0x24c6001c, 
+0x14400011, 0x24020001, 0x3c010001, 0x370821, 
+0xa02240f0, 0x8f820124, 0xafa20010, 0x8f820128, 
+0x3c040001, 0x248467b8, 0xafa20014, 0x8f46002c, 
+0x8f870120, 0x3c050009, 0xc002b3b, 0x34a50900, 
+0x1000000f, 0x0, 0x8f420300, 0x24420001, 
+0xaf420300, 0x8f420300, 0x8f42002c, 0xa34005c1, 
+0xaf420038, 0x3c010001, 0x370821, 0xa02040f1, 
+0x3c010001, 0x370821, 0xa02040f0, 0xaf400034, 
+0x8f420314, 0x24420001, 0xaf420314, 0x10000062, 
+0x8f420314, 0x10400022, 0x32427000, 0x8e25001c, 
+0x8f420028, 0xa22023, 0x4810003, 0x0, 
+0x8f420040, 0x822021, 0x8f420358, 0x8f430000, 
+0xaf450028, 0x441021, 0x10600007, 0xaf420358, 
+0xaf80004c, 0x8f82004c, 0x1040fffd, 0x0, 
+0x10000005, 0x0, 0xaf800048, 0x8f820048, 
+0x1040fffd, 0x0, 0x8f820060, 0x34420008, 
+0xaf820060, 0x8f420000, 0x10400003, 0x0, 
+0x10000041, 0xaf80004c, 0x1000003f, 0xaf800048, 
+0x1040002f, 0x32421000, 0x1040000c, 0x32424000, 
+0x8e23001c, 0x8f420050, 0x622023, 0x4820001, 
+0x24840200, 0x8f42035c, 0x441021, 0xaf42035c, 
+0x8f420368, 0x1000001a, 0xaf430050, 0x1040000c, 
+0x32c28000, 0x8e23001c, 0x8f420070, 0x622023, 
+0x4820001, 0x24840400, 0x8f420364, 0x441021, 
+0xaf420364, 0x8f420368, 0x1000000d, 0xaf430070, 
+0x1040000e, 0x3c020800, 0x8e23001c, 0x8f420060, 
+0x622023, 0x4820001, 0x24840100, 0x8f420360, 
+0x441021, 0xaf420360, 0x8f420368, 0xaf430060, 
+0x441021, 0xaf420368, 0x3c020800, 0x2c21024, 
+0x50400011, 0x36940040, 0x1000000f, 0x0, 
+0x32420048, 0x10400007, 0x24150001, 0x8e22001c, 
+0x3c03ffff, 0x43f024, 0x3042ffff, 0x1000fd75, 
+0xae22001c, 0x32420100, 0x10400003, 0x0, 
+0xc002bd8, 0x0, 0x8fbf0050, 0x8fbe004c, 
+0x8fb50048, 0x8fb30044, 0x8fb20040, 0x8fb1003c, 
+0x8fb00038, 0x3e00008, 0x27bd0058, 0x3e00008, 
+0x0, 0x0, 0x0, 0x8f8300e4, 
+0x8f8200e0, 0x2404fff8, 0x441024, 0x621026, 
+0x2102b, 0x21023, 0x3e00008, 0x621024, 
+0x3e00008, 0x0, 0x27bdffe0, 0xafbf001c, 
+0xafb00018, 0x8f8600c4, 0x8f8400e0, 0x8f8500e4, 
+0x2402fff8, 0x821824, 0x10a30009, 0x27623ff8, 
+0x14a20002, 0x24a20008, 0x27623000, 0x408021, 
+0x16030005, 0x30820004, 0x10400004, 0xc02021, 
+0x10000022, 0x1021, 0x8e040000, 0x8f42011c, 
+0x14a20003, 0x0, 0x8f420120, 0xaf420114, 
+0x8ca30000, 0x8f420148, 0x831823, 0x43102b, 
+0x10400003, 0x0, 0x8f420148, 0x621821, 
+0x94a20006, 0x24420050, 0x62102b, 0x1440000f, 
+0xa01021, 0xafa40010, 0xafa30014, 0x8ca60000, 
+0x8ca70004, 0x3c040001, 0xc002b3b, 0x24846894, 
+0x8f42020c, 0x24420001, 0xaf42020c, 0x8f42020c, 
+0x1021, 0xaf9000e8, 0xaf9000e4, 0x8fbf001c, 
+0x8fb00018, 0x3e00008, 0x27bd0020, 0x3e00008, 
+0x0, 0x8f8400e0, 0x8f8800c4, 0x8f8300e8, 
+0x2402fff8, 0x823824, 0xe32023, 0x2c821000, 
+0x50400001, 0x24841000, 0x420c2, 0x801821, 
+0x8f440258, 0x8f45025c, 0x1021, 0xa32821, 
+0xa3302b, 0x822021, 0x862021, 0xaf440258, 
+0xaf45025c, 0x8f8300c8, 0x8f420148, 0x1032023, 
+0x82102b, 0x14400004, 0x801821, 0x8f420148, 
+0x822021, 0x801821, 0x8f440250, 0x8f450254, 
+0x1021, 0xa32821, 0xa3302b, 0x822021, 
+0x862021, 0xaf440250, 0xaf450254, 0xaf8800c8, 
+0xaf8700e4, 0xaf8700e8, 0x3e00008, 0x0, 
+0x27bdff30, 0x240a0001, 0xafbf00c8, 0xafbe00c4, 
+0xafb500c0, 0xafb300bc, 0xafb200b8, 0xafb100b4, 
+0xafb000b0, 0xa3a00097, 0xafa00044, 0xafaa005c, 
+0x934205c4, 0xa7a0008e, 0x1040000a, 0xa7a00086, 
+0x8f4b00c4, 0xafab0064, 0x8f4a00c0, 0xafaa006c, 
+0x8f4b00cc, 0xafab0074, 0x8f4a00c8, 0x10000129, 
+0xafaa007c, 0x8f420114, 0x40f809, 0x0, 
+0x403021, 0x10c0034f, 0x0, 0x8cc20000, 
+0x8cc30004, 0xafa20020, 0xafa30024, 0x8fab0024, 
+0x8faa0020, 0x3162ffff, 0x2442fffc, 0xafa2006c, 
+0x3c020006, 0x2c21024, 0xafab007c, 0x14400015, 
+0xafaa0064, 0x91420000, 0x30420001, 0x10400011, 
+0x2402ffff, 0x8d430000, 0x14620004, 0x3402ffff, 
+0x95430004, 0x1062000b, 0x0, 0xc0024bb, 
+0x8fa40064, 0x304200ff, 0x14400006, 0x0, 
+0x8f420118, 0x40f809, 0x0, 0x1000032d, 
+0x0, 0x8fa20024, 0x3c03ffbf, 0x3463ffff, 
+0x431024, 0x3c03ffff, 0x431824, 0x14600003, 
+0xafa20024, 0x10000040, 0x1821, 0x3c020080, 
+0x621024, 0x10400007, 0x0, 0x8f42038c, 
+0x24420001, 0xaf42038c, 0x8f42038c, 0x10000036, 
+0x24030001, 0x8f420210, 0x24420001, 0xaf420210, 
+0x8f420210, 0x3c020001, 0x621024, 0x10400006, 
+0x3c020002, 0x8f4201c4, 0x24420001, 0xaf4201c4, 
+0x8f4201c4, 0x3c020002, 0x621024, 0x10400006, 
+0x3c020004, 0x8f42037c, 0x24420001, 0xaf42037c, 
+0x8f42037c, 0x3c020004, 0x621024, 0x10400006, 
+0x3c020008, 0x8f420380, 0x24420001, 0xaf420380, 
+0x8f420380, 0x3c020008, 0x621024, 0x10400006, 
+0x3c020010, 0x8f420384, 0x24420001, 0xaf420384, 
+0x8f420384, 0x3c020010, 0x621024, 0x10400006, 
+0x3c020020, 0x8f4201c0, 0x24420001, 0xaf4201c0, 
+0x8f4201c0, 0x3c020020, 0x621024, 0x10400006, 
+0x24030001, 0x8f420388, 0x24420001, 0xaf420388, 
+0x8f420388, 0x24030001, 0x8c020260, 0x8fab006c, 
+0x4b102b, 0x10400014, 0x307000ff, 0x8f4201e8, 
+0x24420001, 0xaf4201e8, 0x8f4201e8, 0x8faa007c, 
+0x8f8200e0, 0x354a0100, 0xafaa007c, 0xafa20010, 
+0x8f8200e4, 0x24100001, 0x3c040001, 0x248468a0, 
+0xafa20014, 0x8fa60020, 0x8fa70024, 0x3c050007, 
+0xc002b3b, 0x34a50800, 0x12000010, 0x3c020080, 
+0x2c21024, 0x1440000e, 0x32c20400, 0x8fab007c, 
+0x3c020080, 0x34420100, 0x1621024, 0x10400005, 
+0x0, 0x8f42020c, 0x24420001, 0xaf42020c, 
+0x8f42020c, 0x100002b0, 0x8fa3006c, 0x32c20400, 
+0x10400015, 0x34028100, 0x8faa0064, 0x9543000c, 
+0x14620012, 0x3c020100, 0x240b0200, 0xa7ab008e, 
+0x9542000e, 0x8d430008, 0x8d440004, 0x8d450000, 
+0x8faa006c, 0x8fab0064, 0x254afffc, 0xafaa006c, 
+0xa7a20086, 0xad63000c, 0xad640008, 0xad650004, 
+0x256b0004, 0xafab0064, 0x3c020100, 0x2c21024, 
+0x10400004, 0x0, 0x8faa006c, 0x254a0004, 
+0xafaa006c, 0x8f4200bc, 0x5040000a, 0xafa00074, 
+0x8fab006c, 0x4b102b, 0x50400006, 0xafa00074, 
+0x8f4200bc, 0x1621023, 0xafa20074, 0x8f4a00bc, 
+0xafaa006c, 0x8f420080, 0x8fab006c, 0x4b102b, 
+0x10400056, 0x32c28000, 0x1040005e, 0x240a0003, 
+0x32c21000, 0x1040005b, 0xafaa005c, 0x10000058, 
+0x240b0004, 0x8f420350, 0x2403ffbf, 0x283a024, 
+0x24420001, 0xaf420350, 0x1000024f, 0x8f420350, 
+0x2c2b025, 0x2402ffbf, 0x282a024, 0x8f830128, 
+0x3c040001, 0x248468d0, 0x26620001, 0xafa20014, 
+0xafa30010, 0x8f860120, 0x8f870124, 0x3c050007, 
+0xc002b3b, 0x34a52250, 0x1000023f, 0x0, 
+0x2c2b025, 0x2402ffbf, 0x282a024, 0x8f830128, 
+0x3c040001, 0x248468d0, 0x24020002, 0xafa20014, 
+0xafa30010, 0x8f860120, 0x8f870124, 0x3c050007, 
+0xc002b3b, 0x34a52450, 0x1000022f, 0x0, 
+0x8ea20000, 0x8ea30004, 0x3c040001, 0x248468e8, 
+0xafb00010, 0xafbe0014, 0x8ea70018, 0x34a52800, 
+0xc002b3b, 0x603021, 0x10000223, 0x0, 
+0xa6b1000a, 0x8f820124, 0x3c040001, 0x248468f0, 
+0xafbe0014, 0xafa20010, 0x8f460044, 0x8f870120, 
+0x3c050007, 0xc002b3b, 0x34a53000, 0x10000216, 
+0x0, 0xa6b1000a, 0xa6b2000e, 0x8f820124, 
+0x3c040001, 0x248468fc, 0xafbe0014, 0xafa20010, 
+0x8f460044, 0x8f870120, 0x3c050007, 0xc002b3b, 
+0x34a53200, 0x10000208, 0x0, 0x8f420084, 
+0x8faa006c, 0x4a102b, 0x14400007, 0x3c020001, 
+0x2c21024, 0x10400004, 0x0, 0x240b0002, 
+0xafab005c, 0x8faa006c, 0x1140021b, 0x27ab0020, 
+0xafab00a4, 0x3c0a001f, 0x354affff, 0xafaa009c, 
+0x8fab005c, 0x240a0001, 0x556a0021, 0x240a0002, 
+0x8f430054, 0x8f420050, 0x1062000b, 0x274b0054, 
+0x8f5e0054, 0x3403ecc0, 0xafab004c, 0x27c20001, 
+0x304201ff, 0xafa20054, 0x1e1140, 0x431021, 
+0x1000006b, 0x2e2a821, 0x8f420044, 0x8faa006c, 
+0x3c040001, 0x248468ac, 0xafaa0014, 0xafa20010, 
+0x8f460054, 0x8f470050, 0x3c050007, 0xc002b3b, 
+0x34a51300, 0x8f430350, 0x2402ffbf, 0x282a024, 
+0x24630001, 0xaf430350, 0x100001d3, 0x8f420350, 
+0x156a001d, 0x0, 0x8f430074, 0x8f420070, 
+0x1062000a, 0x274b0074, 0x8f5e0074, 0xafab004c, 
+0x27c20001, 0x304203ff, 0xafa20054, 0x1e1140, 
+0x24426cc0, 0x1000004a, 0x2e2a821, 0x8f420044, 
+0x8faa006c, 0x3c040001, 0x248468b8, 0x3c050007, 
+0xafaa0014, 0xafa20010, 0x8f460074, 0x8f470070, 
+0x34a51500, 0x240b0001, 0xc002b3b, 0xafab005c, 
+0x1000ffc3, 0x0, 0x8f430064, 0x8f420060, 
+0x1062001a, 0x274a0064, 0x8f5e0064, 0x8fab005c, 
+0xafaa004c, 0x27c20001, 0x304200ff, 0xafa20054, 
+0x24020004, 0x1562000e, 0x1e1140, 0x1e1180, 
+0x24420cc0, 0x2e21021, 0xafa20044, 0x9442002a, 
+0x8faa0044, 0x8fab006c, 0x4b102b, 0x10400024, 
+0x25550020, 0x240a0001, 0x10000021, 0xa3aa0097, 
+0x24424cc0, 0x1000001e, 0x2e2a821, 0x8f420044, 
+0x8fab006c, 0x3c040001, 0x248468c4, 0xafab0014, 
+0xafa20010, 0x8f460064, 0x8f470060, 0x3c050007, 
+0xc002b3b, 0x34a51800, 0x3c020008, 0x2c21024, 
+0x1440ff34, 0x0, 0x8f420370, 0x240a0001, 
+0xafaa005c, 0x24420001, 0xaf420370, 0x1000ff90, 
+0x8f420370, 0x27a30036, 0x131040, 0x621821, 
+0x94620000, 0x441021, 0x10000020, 0xa4620000, 
+0x8fab0064, 0xaeab0018, 0x93a20097, 0x10400072, 
+0x9821, 0x8faa0044, 0x8fa4006c, 0x8fa300a4, 
+0x25420020, 0xafa20028, 0x25420008, 0xafa20030, 
+0x25420010, 0xafaa002c, 0xafa20034, 0x9542002a, 
+0xa7a20038, 0x95420018, 0xa7a2003a, 0x9542001a, 
+0xa7a2003c, 0x9542001c, 0xa7a2003e, 0x94620018, 
+0x24630002, 0x822023, 0x1880ffde, 0x26730001, 
+0x2e620004, 0x1440fff9, 0x0, 0x8f4200fc, 
+0x26650001, 0xa2102a, 0x1440002b, 0x24030001, 
+0x8f83012c, 0x10600023, 0x0, 0x8f820124, 
+0x431023, 0x22143, 0x58800001, 0x24840040, 
+0x8f820128, 0x431023, 0x21943, 0x58600001, 
+0x24630040, 0x64102a, 0x54400001, 0x602021, 
+0xaf4400fc, 0x8f4200fc, 0xa2102a, 0x10400011, 
+0x24030001, 0x10000015, 0x306200ff, 0x8fab0064, 
+0x96070018, 0xafab0010, 0x8e220008, 0x3c040001, 
+0x248468dc, 0x8c430004, 0x8c420000, 0x34a52400, 
+0x2403021, 0xc002b3b, 0xafa30014, 0x1000002b, 
+0x0, 0x8f420334, 0x1821, 0x24420001, 
+0xaf420334, 0x8f420334, 0x306200ff, 0x5040fedc, 
+0x3c020800, 0x12600021, 0x9021, 0x8fb100a4, 
+0x2208021, 0x8e220008, 0x96070018, 0x8fa60064, 
+0x8c440000, 0x8c450004, 0x240a0001, 0xafaa0010, 
+0xafbe0014, 0x8f420008, 0xafa20018, 0x8f42010c, 
+0x40f809, 0x0, 0x1040ffd8, 0x3c050007, 
+0x96020018, 0x8fab0064, 0x8faa009c, 0x1625821, 
+0x14b102b, 0x10400004, 0xafab0064, 0x8f420148, 
+0x1625823, 0xafab0064, 0x26100002, 0x26520001, 
+0x253102b, 0x1440ffe3, 0x26310004, 0x8fb0006c, 
+0x10000036, 0x97b10038, 0x8f4200fc, 0x24050002, 
+0xa2102a, 0x1440001b, 0x24030001, 0x8f83012c, 
+0x10600013, 0x0, 0x8f820124, 0x431023, 
+0x22143, 0x58800001, 0x24840040, 0x8f820128, 
+0x431023, 0x21943, 0x58600001, 0x24630040, 
+0x64102a, 0x54400001, 0x602021, 0xaf4400fc, 
+0x8f4200fc, 0xa2102a, 0x14400006, 0x24030001, 
+0x8f420334, 0x1821, 0x24420001, 0xaf420334, 
+0x8f420334, 0x306200ff, 0x1040fea5, 0x3c020800, 
+0x96b1000a, 0x8fb0006c, 0x3223ffff, 0x70102b, 
+0x54400001, 0x608021, 0x8ea40000, 0x8ea50004, 
+0x240b0001, 0xafab0010, 0xafbe0014, 0x8f420008, 
+0x8fa60064, 0xafa20018, 0x8f42010c, 0x40f809, 
+0x2003821, 0x1040fea2, 0x3c050007, 0x96a3000e, 
+0x97aa008e, 0x11400007, 0x609021, 0x934205c4, 
+0x14400004, 0x0, 0x97ab0086, 0x6a1825, 
+0xa6ab0016, 0x8faa007c, 0x3c02ffff, 0x1421024, 
+0x10400003, 0xa1402, 0x34630400, 0xa6a20014, 
+0x8fab006c, 0x560b0072, 0xa6a3000e, 0x34620004, 
+0xa6a2000e, 0x8faa0074, 0x16a1021, 0xa6a2000a, 
+0x8f430044, 0x8f4401a0, 0x8f4501a4, 0x34028000, 
+0xafa20010, 0x8f420044, 0x2a03021, 0x24070020, 
+0xafa20014, 0x8f42000c, 0x31940, 0x604821, 
+0xafa20018, 0x8f42010c, 0x4021, 0xa92821, 
+0xa9182b, 0x882021, 0x40f809, 0x832021, 
+0x5040fe7f, 0xa6b2000e, 0x8f420368, 0xafa0006c, 
+0xa34005c4, 0x2442ffff, 0xaf420368, 0x8fab005c, 
+0x240a0001, 0x8f420368, 0x156a0006, 0x240a0002, 
+0x8f42035c, 0x2442ffff, 0xaf42035c, 0x1000000c, 
+0x8f42035c, 0x156a0006, 0x0, 0x8f420364, 
+0x2442ffff, 0xaf420364, 0x10000005, 0x8f420364, 
+0x8f420360, 0x2442ffff, 0xaf420360, 0x8f420360, 
+0x8faa0054, 0x8fab004c, 0xad6a0000, 0x8f420044, 
+0x8f440088, 0x8f430078, 0x24420001, 0x441024, 
+0x24630001, 0xaf420044, 0xaf430078, 0x8c020240, 
+0x62182b, 0x14600075, 0x24070008, 0x8f440168, 
+0x8f45016c, 0x8f430044, 0x8f48000c, 0x8f860120, 
+0x24020040, 0xafa20010, 0xafa30014, 0xafa80018, 
+0x8f42010c, 0x40f809, 0x24c6001c, 0x14400011, 
+0x240b0001, 0x3c010001, 0x370821, 0xa02b40f2, 
+0x8f820124, 0xafa20010, 0x8f820128, 0x3c040001, 
+0x2484688c, 0xafa20014, 0x8f460044, 0x8f870120, 
+0x3c050009, 0xc002b3b, 0x34a51300, 0x1000000b, 
+0x0, 0x8f420304, 0x24420001, 0xaf420304, 
+0x8f420304, 0x8f420044, 0xaf42007c, 0x3c010001, 
+0x370821, 0xa02040f2, 0xaf400078, 0x8f420318, 
+0x24420001, 0xaf420318, 0x10000048, 0x8f420318, 
+0xa6b0000a, 0x8f430044, 0x8f4401a0, 0x8f4501a4, 
+0x34028000, 0xafa20010, 0x8f420044, 0x2a03021, 
+0x24070020, 0xafa20014, 0x8f42000c, 0x31940, 
+0x604821, 0xafa20018, 0x8f42010c, 0x4021, 
+0xa92821, 0xa9182b, 0x882021, 0x40f809, 
+0x832021, 0x1040fe1f, 0x240a0001, 0xa34a05c4, 
+0x8fab006c, 0x8faa0064, 0x1705823, 0xafab006c, 
+0x8fab009c, 0x1505021, 0x16a102b, 0x10400004, 
+0xafaa0064, 0x8f420148, 0x1425023, 0xafaa0064, 
+0x8f420368, 0x2442ffff, 0xaf420368, 0x8faa005c, 
+0x240b0001, 0x8f420368, 0x154b0006, 0x240b0002, 
+0x8f42035c, 0x2442ffff, 0xaf42035c, 0x1000000c, 
+0x8f42035c, 0x114b0006, 0x0, 0x8f420360, 
+0x2442ffff, 0xaf420360, 0x10000005, 0x8f420360, 
+0x8f420364, 0x2442ffff, 0xaf420364, 0x8f420364, 
+0x8fab0054, 0x8faa004c, 0xad4b0000, 0x8f420044, 
+0x8f440088, 0x8f430078, 0x24420001, 0x441024, 
+0x24630001, 0xaf420044, 0xaf430078, 0x8faa006c, 
+0x1540fe0b, 0x0, 0x8fab006c, 0x1160001e, 
+0x0, 0x934205c4, 0x10400009, 0x0, 
+0x8faa0064, 0xaf4a00c4, 0xaf4b00c0, 0x8fab007c, 
+0xaf4b00c8, 0x8faa0074, 0x1000000e, 0xaf4a00cc, 
+0x97ab008e, 0x1160000b, 0x34038100, 0x8fa20020, 
+0x8c46000c, 0xa443000c, 0x97aa0086, 0x8c440004, 
+0x8c450008, 0xa44a000e, 0xac440000, 0xac450004, 
+0xac460008, 0x8f42034c, 0x24420001, 0xaf42034c, 
+0x10000010, 0x8f42034c, 0x8fab007c, 0x3164ffff, 
+0x2484fffc, 0x801821, 0x8f440250, 0x8f450254, 
+0x8f460118, 0x1021, 0xa32821, 0xa3382b, 
+0x822021, 0x872021, 0xaf440250, 0xc0f809, 
+0xaf450254, 0x8fbf00c8, 0x8fbe00c4, 0x8fb500c0, 
+0x8fb300bc, 0x8fb200b8, 0x8fb100b4, 0x8fb000b0, 
+0x3e00008, 0x27bd00d0, 0x3e00008, 0x0, 
+0x27bdff38, 0x240b0001, 0xafbf00c0, 0xafbe00bc, 
+0xafb500b8, 0xafb300b4, 0xafb200b0, 0xafb100ac, 
+0xafb000a8, 0xa3a00087, 0xafa00044, 0xafab005c, 
+0x934205c4, 0xa7a00076, 0x10400007, 0xa7a0007e, 
+0x8f4c00c0, 0xafac0064, 0x8f4b00c8, 0x8f5e00c4, 
+0x10000130, 0xafab006c, 0x8f420114, 0x40f809, 
+0x0, 0x403021, 0x10c002a1, 0x0, 
+0x8cc20000, 0x8cc30004, 0xafa20020, 0xafa30024, 
+0x8fac0024, 0x8fbe0020, 0x3182ffff, 0x2442fffc, 
+0xafa20064, 0x3c020006, 0x2c21024, 0x14400015, 
+0xafac006c, 0x93c20000, 0x30420001, 0x10400011, 
+0x2402ffff, 0x8fc30000, 0x14620004, 0x3402ffff, 
+0x97c30004, 0x1062000b, 0x0, 0xc0024bb, 
+0x3c02021, 0x304200ff, 0x14400006, 0x0, 
+0x8f420118, 0x40f809, 0x0, 0x10000280, 
+0x0, 0x8fa20024, 0x3c03ffbf, 0x3463ffff, 
+0x431024, 0x3c03ffff, 0x431824, 0x14600003, 
+0xafa20024, 0x10000040, 0x8021, 0x3c020080, 
+0x621024, 0x10400007, 0x0, 0x8f42038c, 
+0x24420001, 0xaf42038c, 0x8f42038c, 0x10000036, 
+0x24100001, 0x8f420210, 0x24420001, 0xaf420210, 
+0x8f420210, 0x3c020001, 0x621024, 0x10400006, 
+0x3c020002, 0x8f4201c4, 0x24420001, 0xaf4201c4, 
+0x8f4201c4, 0x3c020002, 0x621024, 0x10400006, 
+0x3c020004, 0x8f42037c, 0x24420001, 0xaf42037c, 
+0x8f42037c, 0x3c020004, 0x621024, 0x10400006, 
+0x3c020008, 0x8f420380, 0x24420001, 0xaf420380, 
+0x8f420380, 0x3c020008, 0x621024, 0x10400006, 
+0x3c020010, 0x8f420384, 0x24420001, 0xaf420384, 
+0x8f420384, 0x3c020010, 0x621024, 0x10400006, 
+0x3c020020, 0x8f4201c0, 0x24420001, 0xaf4201c0, 
+0x8f4201c0, 0x3c020020, 0x621024, 0x10400006, 
+0x24100001, 0x8f420388, 0x24420001, 0xaf420388, 
+0x8f420388, 0x24100001, 0x8c020260, 0x8fab0064, 
+0x4b102b, 0x10400015, 0x320200ff, 0x8f4201e8, 
+0x24420001, 0xaf4201e8, 0x8f4201e8, 0x8fac006c, 
+0x8f8200e0, 0x358c0100, 0xafac006c, 0xafa20010, 
+0x8f8200e4, 0x24100001, 0x3c040001, 0x248468a0, 
+0xafa20014, 0x8fa60020, 0x8fa70024, 0x3c050007, 
+0xc002b3b, 0x34a53600, 0x320200ff, 0x10400010, 
+0x3c020080, 0x2c21024, 0x1440000e, 0x32c20400, 
+0x8fab006c, 0x3c020080, 0x34420100, 0x1621024, 
+0x10400005, 0x0, 0x8f42020c, 0x24420001, 
+0xaf42020c, 0x8f42020c, 0x10000202, 0x8fa30064, 
+0x32c20400, 0x10400012, 0x34028100, 0x97c3000c, 
+0x1462000f, 0x0, 0x240c0200, 0xa7ac0076, 
+0x97c2000e, 0x8fc30008, 0x8fc40004, 0x8fab0064, 
+0x8fc50000, 0x256bfffc, 0xafab0064, 0xa7a2007e, 
+0xafc3000c, 0xafc40008, 0xafc50004, 0x27de0004, 
+0x8fa70064, 0x320200ff, 0x14400034, 0x3c020100, 
+0x97c4000c, 0x2c8305dd, 0x38828870, 0x2c420001, 
+0x621825, 0x10600015, 0x2821, 0x32c20800, 
+0x10400015, 0x24020800, 0x97c30014, 0x14620012, 
+0x3402aaaa, 0x97c3000e, 0x14620007, 0x2021, 
+0x97c30010, 0x24020300, 0x14620004, 0x801021, 
+0x97c20012, 0x2c440001, 0x801021, 0x54400006, 
+0x24050016, 0x10000004, 0x0, 0x24020800, 
+0x50820001, 0x2405000e, 0x10a00013, 0x3c52021, 
+0x24830009, 0x3c02001f, 0x3442ffff, 0x43102b, 
+0x10400003, 0x0, 0x8f420148, 0x621823, 
+0x90620000, 0x38430006, 0x2c630001, 0x38420011, 
+0x2c420001, 0x621825, 0x10600004, 0x3c020100, 
+0x94820002, 0x453821, 0x3c020100, 0x2c21024, 
+0x5040000e, 0xafa70064, 0x8fac0064, 0x10ec0008, 
+0x3c050007, 0x3c040001, 0x24846908, 0x8fa60064, 
+0x34a54000, 0xafa00010, 0xc002b3b, 0xafa00014, 
+0x8fab0064, 0x256b0004, 0xafab0064, 0x8f420080, 
+0x8fac0064, 0x4c102b, 0x1040002c, 0x32c28000, 
+0x10400034, 0x240b0003, 0x32c21000, 0x10400031, 
+0xafab005c, 0x1000002e, 0x240c0004, 0x8f420350, 
+0x2403ffbf, 0x283a024, 0x24420001, 0xaf420350, 
+0x10000173, 0x8f420350, 0x3c020800, 0x2c2b025, 
+0x2402ffbf, 0x282a024, 0x8f830128, 0x3c040001, 
+0x248468d0, 0x26620001, 0xafa20014, 0xafa30010, 
+0x8f860120, 0x8f870124, 0x3c050007, 0xc002b3b, 
+0x34a55300, 0x10000162, 0x0, 0x8ea20000, 
+0x8ea30004, 0x3c040001, 0x248468e8, 0xafb00010, 
+0xafb10014, 0x8ea70018, 0x34a55900, 0xc002b3b, 
+0x603021, 0x10000156, 0x0, 0x8f420084, 
+0x8fab0064, 0x4b102b, 0x14400007, 0x3c020001, 
+0x2c21024, 0x10400004, 0x0, 0x240c0002, 
+0xafac005c, 0x8fab0064, 0x11600166, 0x27ac0020, 
+0xafac008c, 0x8fab005c, 0x240c0001, 0x556c0021, 
+0x240c0002, 0x8f430054, 0x8f420050, 0x1062000b, 
+0x274b0054, 0x8f510054, 0x3403ecc0, 0xafab004c, 
+0x26220001, 0x304201ff, 0xafa20054, 0x111140, 
+0x431021, 0x1000006b, 0x2e2a821, 0x8f420044, 
+0x8fac0064, 0x3c040001, 0x248468ac, 0xafac0014, 
+0xafa20010, 0x8f460054, 0x8f470050, 0x3c050007, 
+0xc002b3b, 0x34a54300, 0x8f430350, 0x2402ffbf, 
+0x282a024, 0x24630001, 0xaf430350, 0x10000124, 
+0x8f420350, 0x156c001d, 0x0, 0x8f430074, 
+0x8f420070, 0x1062000a, 0x274b0074, 0x8f510074, 
+0xafab004c, 0x26220001, 0x304203ff, 0xafa20054, 
+0x111140, 0x24426cc0, 0x1000004a, 0x2e2a821, 
+0x8f420044, 0x8fac0064, 0x3c040001, 0x248468b8, 
+0x3c050007, 0xafac0014, 0xafa20010, 0x8f460074, 
+0x8f470070, 0x34a54500, 0x240b0001, 0xc002b3b, 
+0xafab005c, 0x1000ffc3, 0x0, 0x8f430064, 
+0x8f420060, 0x1062001a, 0x274c0064, 0x8f510064, 
+0x8fab005c, 0xafac004c, 0x26220001, 0x304200ff, 
+0xafa20054, 0x24020004, 0x1562000e, 0x111140, 
+0x111180, 0x24420cc0, 0x2e21021, 0xafa20044, 
+0x9442002a, 0x8fac0044, 0x8fab0064, 0x4b102b, 
+0x10400024, 0x25950020, 0x240c0001, 0x10000021, 
+0xa3ac0087, 0x24424cc0, 0x1000001e, 0x2e2a821, 
+0x8f420044, 0x8fab0064, 0x3c040001, 0x248468c4, 
+0xafab0014, 0xafa20010, 0x8f460064, 0x8f470060, 
+0x3c050007, 0xc002b3b, 0x34a54800, 0x3c020008, 
+0x2c21024, 0x1440ff61, 0x0, 0x8f420370, 
+0x240c0001, 0xafac005c, 0x24420001, 0xaf420370, 
+0x1000ff90, 0x8f420370, 0x27a30036, 0x131040, 
+0x621821, 0x94620000, 0x441021, 0x1000001f, 
+0xa4620000, 0xaebe0018, 0x93a20087, 0x10400084, 
+0x9821, 0x8fab0044, 0x8fa40064, 0x8fa3008c, 
+0x25620020, 0xafa20028, 0x25620008, 0xafa20030, 
+0x25620010, 0xafab002c, 0xafa20034, 0x9562002a, 
+0xa7a20038, 0x95620018, 0xa7a2003a, 0x9562001a, 
+0xa7a2003c, 0x9562001c, 0xa7a2003e, 0x94620018, 
+0x24630002, 0x822023, 0x1880ffdf, 0x26730001, 
+0x2e620004, 0x1440fff9, 0x0, 0x8f4200fc, 
+0x262102a, 0x14400030, 0x24030001, 0x8f83012c, 
+0x10600028, 0x0, 0x8f820124, 0x431023, 
+0x22143, 0x58800001, 0x24840040, 0x8f820128, 
+0x431023, 0x21943, 0x58600001, 0x24630040, 
+0x64102a, 0x54400001, 0x602021, 0xaf4400fc, 
+0x8f4200fc, 0x262102a, 0x10400016, 0x24030001, 
+0x1000001a, 0x306200ff, 0x8fac008c, 0x101040, 
+0x4c1021, 0x94470018, 0x101080, 0x4c1021, 
+0xafbe0010, 0x8c420008, 0x3c040001, 0x248468dc, 
+0x3c050007, 0x8c430004, 0x8c420000, 0x34a55500, 
+0x2003021, 0xc002b3b, 0xafa30014, 0x10000039, 
+0x0, 0x8f420334, 0x1821, 0x24420001, 
+0xaf420334, 0x8f420334, 0x306200ff, 0x1040ff06, 
+0x8021, 0x8f430008, 0x2402fbff, 0x1260002d, 
+0x625024, 0x3c0b4000, 0x22b4025, 0x8fb1008c, 
+0x2669ffff, 0x2209021, 0x8e420008, 0x96270018, 
+0x8c440000, 0x8c450004, 0x56090004, 0x240b0001, 
+0x240c0002, 0x10000002, 0xafac0010, 0xafab0010, 
+0x16000004, 0xafa80014, 0x8f420008, 0x10000002, 
+0xafa20018, 0xafaa0018, 0x8f42010c, 0x3c03021, 
+0xafa80098, 0xafa9009c, 0x40f809, 0xafaa00a0, 
+0x8fa80098, 0x8fa9009c, 0x8faa00a0, 0x1040ffc2, 
+0x3c02001f, 0x96230018, 0x3442ffff, 0x3c3f021, 
+0x5e102b, 0x10400003, 0x26310002, 0x8f420148, 
+0x3c2f023, 0x26100001, 0x213102b, 0x1440ffda, 
+0x26520004, 0x8fb00064, 0x1000001a, 0x0, 
+0x96a3000a, 0x8fb00064, 0x70102b, 0x54400001, 
+0x608021, 0x8ea40000, 0x8ea50004, 0x8fab005c, 
+0x240c0002, 0xafac0010, 0x934305c4, 0xb1700, 
+0x10600003, 0x2223025, 0x3c020800, 0xc23025, 
+0xafa60014, 0x8f420008, 0xafa20018, 0x8f42010c, 
+0x3c03021, 0x40f809, 0x2003821, 0x1040fecb, 
+0x3c050007, 0x97ac0076, 0x11800007, 0x96a3000e, 
+0x934205c4, 0x14400004, 0x0, 0x97ab007e, 
+0x6c1825, 0xa6ab0016, 0x8fac006c, 0x3c02ffff, 
+0x1821024, 0x10400003, 0xc1402, 0x34630400, 
+0xa6a20014, 0xa6b0000a, 0x8fab0064, 0x560b0006, 
+0x3d0f021, 0x34620004, 0xafa00064, 0xa6a2000e, 
+0x1000000d, 0xa34005c4, 0x8fac0064, 0x3c02001f, 
+0x3442ffff, 0x5e102b, 0x1906023, 0xafac0064, 
+0xa6a3000e, 0x240b0001, 0x10400003, 0xa34b05c4, 
+0x8f420148, 0x3c2f023, 0x8fab0054, 0x8fac004c, 
+0xad8b0000, 0x8fac0064, 0x1580feba, 0x0, 
+0x8fab0064, 0x1160001b, 0x0, 0x934205c4, 
+0x10400006, 0x0, 0xaf5e00c4, 0xaf4b00c0, 
+0x8fac006c, 0x1000000e, 0xaf4c00c8, 0x97ab0076, 
+0x1160000b, 0x34038100, 0x8fa20020, 0x8c46000c, 
+0xa443000c, 0x97ac007e, 0x8c440004, 0x8c450008, 
+0xa44c000e, 0xac440000, 0xac450004, 0xac460008, 
+0x8f42034c, 0x24420001, 0xaf42034c, 0x10000010, 
+0x8f42034c, 0x8fab006c, 0x3164ffff, 0x2484fffc, 
+0x801821, 0x8f440250, 0x8f450254, 0x8f460118, 
+0x1021, 0xa32821, 0xa3382b, 0x822021, 
+0x872021, 0xaf440250, 0xc0f809, 0xaf450254, 
+0x8fbf00c0, 0x8fbe00bc, 0x8fb500b8, 0x8fb300b4, 
+0x8fb200b0, 0x8fb100ac, 0x8fb000a8, 0x3e00008, 
+0x27bd00c8, 0x3e00008, 0x0, 0x27bdffd8, 
+0xafbf0024, 0xafb00020, 0x8f43004c, 0x8f420048, 
+0x10620034, 0x0, 0x8f430048, 0x8f42004c, 
+0x622023, 0x4820001, 0x24840200, 0x8f430054, 
+0x8f42004c, 0x43102b, 0x14400004, 0x24020200, 
+0x8f43004c, 0x10000005, 0x431023, 0x8f420054, 
+0x8f43004c, 0x431023, 0x2442ffff, 0x405021, 
+0x8a102a, 0x54400001, 0x805021, 0x8f49004c, 
+0x8f48004c, 0x8f440188, 0x8f45018c, 0x8f46004c, 
+0x24071000, 0xafa70010, 0x84140, 0x1001821, 
+0x12a4821, 0x313001ff, 0xafb00014, 0x8f470014, 
+0x1021, 0x63140, 0xafa70018, 0xa32821, 
+0xa3382b, 0x822021, 0x872021, 0x3402ecc0, 
+0xc23021, 0x8f420108, 0x2e63021, 0x40f809, 
+0xa3940, 0x54400001, 0xaf50004c, 0x8f43004c, 
+0x8f420048, 0x14620018, 0x0, 0x8f420000, 
+0x10400007, 0x0, 0xaf80004c, 0x8f82004c, 
+0x1040fffd, 0x0, 0x10000005, 0x0, 
+0xaf800048, 0x8f820048, 0x1040fffd, 0x0, 
+0x8f820060, 0x2403fdff, 0x431024, 0xaf820060, 
+0x8f420000, 0x10400003, 0x0, 0x10000002, 
+0xaf80004c, 0xaf800048, 0x8fbf0024, 0x8fb00020, 
+0x3e00008, 0x27bd0028, 0x3e00008, 0x0, 
+0x27bdffd8, 0xafbf0024, 0xafb00020, 0x8f43005c, 
+0x8f420058, 0x10620049, 0x0, 0x8f430058, 
+0x8f42005c, 0x622023, 0x4820001, 0x24840100, 
+0x8f430064, 0x8f42005c, 0x43102b, 0x14400004, 
+0x24020100, 0x8f43005c, 0x10000005, 0x431023, 
+0x8f420064, 0x8f43005c, 0x431023, 0x2442ffff, 
+0x403821, 0x87102a, 0x54400001, 0x803821, 
+0x8f42005c, 0x471021, 0x305000ff, 0x32c21000, 
+0x10400015, 0x24082000, 0x8f49005c, 0x8f440190, 
+0x8f450194, 0x8f46005c, 0x73980, 0xafa80010, 
+0xafb00014, 0x8f480014, 0x94980, 0x1201821, 
+0x1021, 0xa32821, 0xa3482b, 0x822021, 
+0x892021, 0x63180, 0xafa80018, 0x8f420108, 
+0x10000014, 0x24c60cc0, 0x8f49005c, 0x8f440190, 
+0x8f450194, 0x8f46005c, 0x73940, 0xafa80010, 
+0xafb00014, 0x8f480014, 0x94940, 0x1201821, 
+0x1021, 0xa32821, 0xa3482b, 0x822021, 
+0x892021, 0x63140, 0xafa80018, 0x8f420108, 
+0x24c64cc0, 0x40f809, 0x2e63021, 0x54400001, 
+0xaf50005c, 0x8f43005c, 0x8f420058, 0x14620018, 
+0x0, 0x8f420000, 0x10400007, 0x0, 
+0xaf80004c, 0x8f82004c, 0x1040fffd, 0x0, 
+0x10000005, 0x0, 0xaf800048, 0x8f820048, 
+0x1040fffd, 0x0, 0x8f820060, 0x2403feff, 
+0x431024, 0xaf820060, 0x8f420000, 0x10400003, 
+0x0, 0x10000002, 0xaf80004c, 0xaf800048, 
+0x8fbf0024, 0x8fb00020, 0x3e00008, 0x27bd0028, 
+0x3e00008, 0x0, 0x27bdffd8, 0xafbf0024, 
+0xafb00020, 0x8f43006c, 0x8f420068, 0x10620033, 
+0x0, 0x8f430068, 0x8f42006c, 0x622023, 
+0x4820001, 0x24840400, 0x8f430074, 0x8f42006c, 
+0x43102b, 0x14400004, 0x24020400, 0x8f43006c, 
+0x10000005, 0x431023, 0x8f420074, 0x8f43006c, 
+0x431023, 0x2442ffff, 0x405021, 0x8a102a, 
+0x54400001, 0x805021, 0x8f49006c, 0x8f48006c, 
+0x8f440198, 0x8f45019c, 0x8f46006c, 0x24074000, 
+0xafa70010, 0x84140, 0x1001821, 0x12a4821, 
+0x313003ff, 0xafb00014, 0x8f470014, 0x1021, 
+0x63140, 0x24c66cc0, 0xafa70018, 0xa32821, 
+0xa3382b, 0x822021, 0x872021, 0x8f420108, 
+0x2e63021, 0x40f809, 0xa3940, 0x54400001, 
+0xaf50006c, 0x8f43006c, 0x8f420068, 0x14620018, 
+0x0, 0x8f420000, 0x10400007, 0x0, 
+0xaf80004c, 0x8f82004c, 0x1040fffd, 0x0, 
+0x10000005, 0x0, 0xaf800048, 0x8f820048, 
+0x1040fffd, 0x0, 0x8f820060, 0x2403f7ff, 
+0x431024, 0xaf820060, 0x8f420000, 0x10400003, 
+0x0, 0x10000002, 0xaf80004c, 0xaf800048, 
+0x8fbf0024, 0x8fb00020, 0x3e00008, 0x27bd0028, 
+0x3e00008, 0x0, 0x8f4200fc, 0x3c030001, 
+0x8f4400f8, 0x346330c8, 0x24420001, 0xaf4200fc, 
+0x8f850128, 0x2e31021, 0x54820004, 0x24820008, 
+0x3c020001, 0x34422ec8, 0x2e21021, 0x401821, 
+0xaf4300f8, 0xac600000, 0x8f4200f4, 0x14620004, 
+0x3c020001, 0x24a20020, 0x1000000f, 0xaf820128, 
+0x8f4300f8, 0x344230c8, 0x2e21021, 0x54620004, 
+0x24620008, 0x3c020001, 0x34422ec8, 0x2e21021, 
+0x401821, 0x8c620004, 0x21140, 0xa21021, 
+0xaf820128, 0xac600000, 0x8ca30018, 0x30620070, 
+0x1040002d, 0x30620020, 0x10400004, 0x3c020010, 
+0x2c21024, 0x1040000d, 0x0, 0x30620040, 
+0x10400004, 0x3c020020, 0x2c21024, 0x10400007, 
+0x0, 0x30620010, 0x1040001f, 0x3c020040, 
+0x2c21024, 0x1440001c, 0x0, 0x8f820040, 
+0x30420001, 0x14400008, 0x2021, 0x8c030104, 
+0x24020001, 0x50620005, 0x24040001, 0x8c020264, 
+0x10400003, 0x801021, 0x24040001, 0x801021, 
+0x10400006, 0x0, 0x8f42030c, 0x24420001, 
+0xaf42030c, 0x10000008, 0x8f42030c, 0x8f820044, 
+0x34420004, 0xaf820044, 0x8f420308, 0x24420001, 
+0xaf420308, 0x8f420308, 0x3e00008, 0x0, 
+0x3e00008, 0x0, 0x27bdff98, 0xafbf0060, 
+0xafbe005c, 0xafb50058, 0xafb30054, 0xafb20050, 
+0xafb1004c, 0xafb00048, 0x8f4200fc, 0x24420001, 
+0xaf4200fc, 0x8f880128, 0x25020020, 0xaf820128, 
+0x8d030018, 0x30620070, 0x1040002e, 0x30620020, 
+0x10400004, 0x3c020010, 0x2c21024, 0x1040000d, 
+0x0, 0x30620040, 0x10400004, 0x3c020020, 
+0x2c21024, 0x10400007, 0x0, 0x30620010, 
+0x104001a9, 0x3c020040, 0x2c21024, 0x144001a6, 
+0x0, 0x8f820040, 0x30420001, 0x14400008, 
+0x2021, 0x8c030104, 0x24020001, 0x50620005, 
+0x24040001, 0x8c020264, 0x10400003, 0x801021, 
+0x24040001, 0x801021, 0x10400006, 0x0, 
+0x8f42030c, 0x24420001, 0xaf42030c, 0x10000192, 
+0x8f42030c, 0x8f820044, 0x34420004, 0xaf820044, 
+0x8f420308, 0x24420001, 0xaf420308, 0x1000018a, 
+0x8f420308, 0x30620002, 0x1040014b, 0x3c020800, 
+0x8d1e001c, 0x1e5702, 0xafaa0034, 0x950a0016, 
+0x3c22024, 0xafaa0024, 0x8faa0034, 0x24020001, 
+0x15420006, 0x33deffff, 0x1e1140, 0x3403ecc0, 
+0x431021, 0x10000010, 0x2e2a821, 0x24020002, 
+0x15420005, 0x24020003, 0x1e1140, 0x24426cc0, 
+0x10000009, 0x2e2a821, 0x15420005, 0x1e1180, 
+0x1e1140, 0x24424cc0, 0x10000003, 0x2e2a821, 
+0x571021, 0x24550ce0, 0x96a2000e, 0x304afffc, 
+0x30420400, 0x10400003, 0xafaa002c, 0x100000e1, 
+0x8821, 0x10800004, 0x8821, 0x97b10026, 
+0x100000dd, 0xa6b10012, 0x8eb30018, 0x966a000c, 
+0xa7aa003e, 0x97a5003e, 0x2ca305dd, 0x38a28870, 
+0x2c420001, 0x621825, 0x10600015, 0x2021, 
+0x32c20800, 0x10400015, 0x24020800, 0x96630014, 
+0x14620012, 0x3402aaaa, 0x9663000e, 0x14620007, 
+0x2821, 0x96630010, 0x24020300, 0x14620004, 
+0xa01021, 0x96620012, 0x2c450001, 0xa01021, 
+0x54400006, 0x24040016, 0x10000004, 0x0, 
+0x24020800, 0x50a20001, 0x2404000e, 0x108000b9, 
+0x2649021, 0x92420000, 0x3042000f, 0x28080, 
+0x32c20100, 0x10400020, 0x2501821, 0x3c020020, 
+0x43102b, 0x1440000e, 0x2402021, 0x2821, 
+0x94820000, 0x24840002, 0xa22821, 0x83102b, 
+0x1440fffb, 0x30a2ffff, 0x51c02, 0x622821, 
+0x51c02, 0x30a2ffff, 0x10000009, 0x622821, 
+0x8f470148, 0x8f420110, 0x102842, 0x3c060020, 
+0x40f809, 0xafa80040, 0x3045ffff, 0x8fa80040, 
+0x50a00001, 0x3405ffff, 0x8faa002c, 0x354a0002, 
+0x10000002, 0xafaa002c, 0x2821, 0x32c20080, 
+0x10400090, 0xa6a50010, 0x26430009, 0x3c02001f, 
+0x3442ffff, 0x43102b, 0x10400003, 0x0, 
+0x8f420148, 0x621823, 0x90660000, 0x30c200ff, 
+0x38430006, 0x2c630001, 0x38420011, 0x2c420001, 
+0x621825, 0x1060007f, 0x24020800, 0x8821, 
+0x97a3003e, 0x1462000f, 0x2602021, 0x96710000, 
+0x96620002, 0x96630004, 0x96640006, 0x2228821, 
+0x2238821, 0x2248821, 0x96620008, 0x9663000a, 
+0x9664000c, 0x2228821, 0x2238821, 0x10000007, 
+0x2248821, 0x94820000, 0x24840002, 0x2228821, 
+0x92102b, 0x1440fffb, 0x0, 0x111c02, 
+0x3222ffff, 0x628821, 0x111c02, 0x3222ffff, 
+0x628821, 0x32c20200, 0x10400003, 0x26440006, 
+0x1000003e, 0x8021, 0x3c05001f, 0x34a5ffff, 
+0xa4102b, 0x10400003, 0x0, 0x8f420148, 
+0x822023, 0x94820000, 0x30421fff, 0x10400004, 
+0x2644000c, 0x96420002, 0x10000030, 0x508023, 
+0x96420002, 0x26430014, 0x508023, 0x3c020020, 
+0x43102b, 0x1440000a, 0xd08021, 0x9642000c, 
+0x2028021, 0x9642000e, 0x96430010, 0x96440012, 
+0x2028021, 0x2038021, 0x10000020, 0x2048021, 
+0xa4102b, 0x10400003, 0x0, 0x8f420148, 
+0x822023, 0x94820000, 0x24840002, 0x2028021, 
+0xa4102b, 0x10400003, 0x0, 0x8f420148, 
+0x822023, 0x94820000, 0x24840002, 0x2028021, 
+0xa4102b, 0x10400003, 0x0, 0x8f420148, 
+0x822023, 0x94820000, 0x24840002, 0x2028021, 
+0xa4102b, 0x10400003, 0x0, 0x8f420148, 
+0x822023, 0x94820000, 0x2028021, 0x3c020100, 
+0x2c21024, 0x1040000e, 0x0, 0x8faa002c, 
+0x31420004, 0x1040000a, 0x0, 0x9504000e, 
+0x2642021, 0xc003eec, 0x2484fffc, 0x3042ffff, 
+0x2228821, 0x111c02, 0x3222ffff, 0x628821, 
+0x8faa0024, 0x1518823, 0x111402, 0x2228821, 
+0x2308821, 0x111402, 0x2228821, 0x3231ffff, 
+0x52200001, 0x3411ffff, 0x8faa002c, 0x354a0001, 
+0xafaa002c, 0xa6b10012, 0x97aa002e, 0xa6aa000e, 
+0x8faa002c, 0x31420004, 0x10400002, 0x24091000, 
+0x34098000, 0x8f480044, 0x8f4401a0, 0x8f4501a4, 
+0xafa90010, 0x8f490044, 0x84140, 0x1001821, 
+0xafa90014, 0x8f48000c, 0x2a03021, 0x24070020, 
+0xafa80018, 0x8f48010c, 0x1021, 0xa32821, 
+0xa3482b, 0x822021, 0x100f809, 0x892021, 
+0x1440000b, 0x0, 0x8f820128, 0x3c040001, 
+0x24846914, 0xafbe0014, 0xafa20010, 0x8f860124, 
+0x8f870120, 0x3c050007, 0xc002b3b, 0x34a59920, 
+0x8f420368, 0x2442ffff, 0xaf420368, 0x8f420044, 
+0x8f430088, 0x24420001, 0x431024, 0xaf420044, 
+0x8faa0034, 0x8f440368, 0x24020001, 0x15420006, 
+0x24020002, 0x8f42035c, 0x2442ffff, 0xaf42035c, 
+0x10000049, 0x8f42035c, 0x15420006, 0x0, 
+0x8f420364, 0x2442ffff, 0xaf420364, 0x10000042, 
+0x8f420364, 0x8f420360, 0x2442ffff, 0xaf420360, 
+0x1000003d, 0x8f420360, 0x30621000, 0x10400005, 
+0x30628000, 0x8f420078, 0x24420001, 0x10000036, 
+0xaf420078, 0x10400034, 0x0, 0x8f420078, 
+0x24420001, 0xaf420078, 0x8c030240, 0x43102b, 
+0x1440002d, 0x24070008, 0x8f440168, 0x8f45016c, 
+0x8f430044, 0x8f48000c, 0x8f860120, 0x24020040, 
+0xafa20010, 0xafa30014, 0xafa80018, 0x8f42010c, 
+0x40f809, 0x24c6001c, 0x14400011, 0x24020001, 
+0x3c010001, 0x370821, 0xa02240f2, 0x8f820124, 
+0xafa20010, 0x8f820128, 0x3c040001, 0x2484688c, 
+0xafa20014, 0x8f460044, 0x8f870120, 0x3c050009, 
+0xc002b3b, 0x34a51300, 0x1000000b, 0x0, 
+0x8f420304, 0x24420001, 0xaf420304, 0x8f420304, 
+0x8f420044, 0xaf42007c, 0x3c010001, 0x370821, 
+0xa02040f2, 0xaf400078, 0x8f420318, 0x24420001, 
+0xaf420318, 0x8f420318, 0x8fbf0060, 0x8fbe005c, 
+0x8fb50058, 0x8fb30054, 0x8fb20050, 0x8fb1004c, 
+0x8fb00048, 0x3e00008, 0x27bd0068, 0x3e00008, 
+0x0, 0x0, 0x0, 0x8f42013c, 
+0xaf8200c0, 0x8f42013c, 0xaf8200c4, 0x8f42013c, 
+0xaf8200c8, 0x8f420138, 0xaf8200d0, 0x8f420138, 
+0xaf8200d4, 0x8f420138, 0x3e00008, 0xaf8200d8, 
+0x27bdffe0, 0x27840208, 0x24050200, 0xafbf0018, 
+0xc002bbf, 0x24060008, 0x8c020204, 0xc004012, 
+0xaf820210, 0x3c020001, 0x8c426d94, 0x30420002, 
+0x1040000e, 0x2021, 0x8c060248, 0x24020002, 
+0x3c010001, 0xac226d98, 0xc005104, 0x24050002, 
+0x2021, 0x8c060248, 0x24020001, 0x3c010001, 
+0xac226d98, 0x10000011, 0x24050001, 0x8c060248, 
+0x24020004, 0x3c010001, 0xac226d98, 0xc005104, 
+0x24050004, 0x3c020001, 0x8c426d94, 0x30420001, 
+0x10400008, 0x24020001, 0x3c010001, 0xac226d98, 
+0x2021, 0x24050001, 0x3c06601b, 0xc005104, 
+0x0, 0x3c040001, 0x248469d0, 0x8f420150, 
+0x8f430154, 0x3c050008, 0x8f460158, 0x21640, 
+0x31940, 0x34630403, 0x431025, 0x633c0, 
+0x461025, 0xaf82021c, 0xafa00010, 0xafa00014, 
+0x8f86021c, 0x34a50200, 0xc002b3b, 0x3821, 
+0x3c010001, 0xac206d90, 0x3c010001, 0xac206da8, 
+0x8fbf0018, 0x3e00008, 0x27bd0020, 0x27bdffe0, 
+0x3c050008, 0x34a50300, 0xafbf0018, 0xafa00010, 
+0xafa00014, 0x8f860200, 0x3c040001, 0x248469dc, 
+0xc002b3b, 0x3821, 0x8f420410, 0x24420001, 
+0xaf420410, 0x8f420410, 0x8fbf0018, 0x3e00008, 
+0x27bd0020, 0x27bdffd8, 0xafbf0020, 0xafb1001c, 
+0xafb00018, 0x8f4203a4, 0x24420001, 0xaf4203a4, 
+0x8f4203a4, 0x8f900220, 0x8f8200e0, 0xafa20010, 
+0x8f8200e4, 0xafa20014, 0x8f8600c4, 0x8f8700c8, 
+0x3c040001, 0x248469e8, 0xc002b3b, 0x2002821, 
+0x3c044000, 0x2041024, 0x504000b4, 0x3c040100, 
+0x8f4203bc, 0x24420001, 0xaf4203bc, 0x8f4203bc, 
+0x8f8700c4, 0x8f8300c8, 0x8f420148, 0x671823, 
+0x43102b, 0x10400003, 0x0, 0x8f420148, 
+0x621821, 0x10600005, 0x0, 0x8f42014c, 
+0x43102b, 0x1040000b, 0x0, 0x8f8200e0, 
+0x8f430124, 0xaf42011c, 0xaf430114, 0x8f820220, 
+0x3c0308ff, 0x3463fffb, 0x431024, 0x100000ce, 
+0x441025, 0x8f820220, 0x3c0308ff, 0x3463ffff, 
+0x431024, 0x34420004, 0xaf820220, 0x8f8200e0, 
+0x8f430124, 0xaf42011c, 0xaf430114, 0x8f8600c8, 
+0x8f840120, 0x8f830124, 0x10000005, 0x2821, 
+0x14620002, 0x24620020, 0x27624800, 0x401821, 
+0x1064000c, 0x30a200ff, 0x8c620018, 0x30420003, 
+0x1040fff7, 0x27624fe0, 0x8f4203d0, 0x24050001, 
+0x24420001, 0xaf4203d0, 0x8f4203d0, 0x8c660008, 
+0x30a200ff, 0x14400058, 0x0, 0x934205c4, 
+0x14400055, 0x0, 0x8f8700c4, 0x8f8800e0, 
+0x8f8400e4, 0x2402fff8, 0x1024024, 0x1041023, 
+0x218c3, 0x4620001, 0x24630200, 0x10600005, 
+0x24020001, 0x10620009, 0x0, 0x1000001f, 
+0x0, 0x8f4203c0, 0xe03021, 0x24420001, 
+0xaf4203c0, 0x10000040, 0x8f4203c0, 0x8f4203c4, 
+0x24420001, 0xaf4203c4, 0x8c860000, 0x8f420148, 
+0x8f4303c4, 0xe61823, 0x43102b, 0x10400004, 
+0x2c62233f, 0x8f420148, 0x621821, 0x2c62233f, 
+0x14400031, 0x0, 0x8f42020c, 0x24420001, 
+0xaf42020c, 0x8f42020c, 0xe03021, 0x24820008, 
+0xaf8200e4, 0x10000028, 0xaf8200e8, 0x8f4203c8, 
+0x24420001, 0xaf4203c8, 0x8f4203c8, 0x8c850000, 
+0x8f420148, 0xa71823, 0x43102b, 0x10400003, 
+0x0, 0x8f420148, 0x621821, 0x8f42014c, 
+0x43102b, 0x5440000a, 0xa03021, 0x8f42020c, 
+0x24420001, 0xaf42020c, 0x8f42020c, 0x24820008, 
+0xaf8200e4, 0x8f8400e4, 0x1488ffec, 0xaf8400e8, 
+0x1488000d, 0x27623000, 0x14820002, 0x2482fff8, 
+0x27623ff8, 0x94430006, 0x3c02001f, 0x3442ffff, 
+0xc33021, 0x46102b, 0x10400003, 0x0, 
+0x8f420148, 0xc23023, 0xaf8600c8, 0x8f8300c4, 
+0x8f420148, 0xc31823, 0x43102b, 0x10400003, 
+0x0, 0x8f420148, 0x621821, 0x10600005, 
+0x0, 0x8f42014c, 0x43102b, 0x50400008, 
+0x3c02fdff, 0x8f820220, 0x3c0308ff, 0x3463fffb, 
+0x431024, 0x3c034000, 0x1000003f, 0x431025, 
+0x8f4303cc, 0x3442ffff, 0x282a024, 0x24630001, 
+0xaf4303cc, 0x10000039, 0x8f4203cc, 0x2041024, 
+0x1040000e, 0x3c110200, 0x8f4203a8, 0x24420001, 
+0xaf4203a8, 0x8f4203a8, 0x8f820220, 0x3c0308ff, 
+0x3463ffff, 0x431024, 0x441025, 0xc003daf, 
+0xaf820220, 0x10000029, 0x0, 0x2111024, 
+0x50400008, 0x3c110400, 0x8f4203ac, 0x24420001, 
+0xaf4203ac, 0xc003daf, 0x8f4203ac, 0x10000019, 
+0x0, 0x2111024, 0x1040001c, 0x0, 
+0x8f830224, 0x24021402, 0x14620009, 0x3c050008, 
+0x3c040001, 0x248469f4, 0xafa00010, 0xafa00014, 
+0x8f860224, 0x34a50500, 0xc002b3b, 0x3821, 
+0x8f4203b0, 0x24420001, 0xaf4203b0, 0x8f4203b0, 
+0x8f820220, 0x2002021, 0x34420002, 0xc004e9c, 
+0xaf820220, 0x8f820220, 0x3c0308ff, 0x3463ffff, 
+0x431024, 0x511025, 0xaf820220, 0x8fbf0020, 
+0x8fb1001c, 0x8fb00018, 0x3e00008, 0x27bd0028, 
+0x3e00008, 0x0, 0x3c020001, 0x8c426da8, 
+0x27bdffb0, 0xafbf0048, 0xafbe0044, 0xafb50040, 
+0xafb3003c, 0xafb20038, 0xafb10034, 0x1040000f, 
+0xafb00030, 0x3c040001, 0x24846a00, 0x3c050008, 
+0xafa00010, 0xafa00014, 0x8f860220, 0x34a50600, 
+0x24020001, 0x3c010001, 0xac206da8, 0x3c010001, 
+0xac226d9c, 0xc002b3b, 0x3821, 0x3c037fff, 
+0x8c020268, 0x3463ffff, 0x3c04fdff, 0x431024, 
+0xac020268, 0x8f420004, 0x3484ffff, 0x30420002, 
+0x10400092, 0x284a024, 0x3c040600, 0x34842000, 
+0x8f420004, 0x2821, 0x2403fffd, 0x431024, 
+0xaf420004, 0xafa40020, 0x8f5e0018, 0x27aa0020, 
+0x240200ff, 0x13c20002, 0xafaa002c, 0x27c50001, 
+0x8c020228, 0xa09021, 0x1642000e, 0x1e38c0, 
+0x8f42033c, 0x24420001, 0xaf42033c, 0x8f42033c, 
+0x8c020228, 0x3c040001, 0x24846998, 0x3c050009, 
+0xafa00014, 0xafa20010, 0x8fa60020, 0x1000006d, 
+0x34a50500, 0xf71021, 0x8fa30020, 0x8fa40024, 
+0xac4304c0, 0xac4404c4, 0x8f830054, 0x8f820054, 
+0x247003e8, 0x2021023, 0x2c4203e9, 0x1040001b, 
+0x9821, 0xe08821, 0x263504c0, 0x8f440178, 
+0x8f45017c, 0x2201821, 0x240a0004, 0xafaa0010, 
+0xafb20014, 0x8f48000c, 0x1021, 0x2f53021, 
+0xafa80018, 0x8f48010c, 0x24070008, 0xa32821, 
+0xa3482b, 0x822021, 0x100f809, 0x892021, 
+0x54400006, 0x24130001, 0x8f820054, 0x2021023, 
+0x2c4203e9, 0x1440ffe9, 0x0, 0x326200ff, 
+0x54400017, 0xaf520018, 0x8f420378, 0x24420001, 
+0xaf420378, 0x8f420378, 0x8f820120, 0x8faa002c, 
+0xafa20010, 0x8f820124, 0x3c040001, 0x248469a4, 
+0x3c050009, 0xafa20014, 0x8d460000, 0x10000035, 
+0x34a50600, 0x8f420308, 0x24130001, 0x24420001, 
+0xaf420308, 0x8f420308, 0x1000001e, 0x326200ff, 
+0x8f830054, 0x8f820054, 0x247003e8, 0x2021023, 
+0x2c4203e9, 0x10400016, 0x9821, 0x3c150020, 
+0x24110010, 0x8f42000c, 0x8f440160, 0x8f450164, 
+0x8f860120, 0xafb10010, 0xafb20014, 0x551025, 
+0xafa20018, 0x8f42010c, 0x24070008, 0x40f809, 
+0x24c6001c, 0x1440ffe3, 0x0, 0x8f820054, 
+0x2021023, 0x2c4203e9, 0x1440ffee, 0x0, 
+0x326200ff, 0x14400011, 0x0, 0x8f420378, 
+0x24420001, 0xaf420378, 0x8f420378, 0x8f820120, 
+0x8faa002c, 0xafa20010, 0x8f820124, 0x3c040001, 
+0x248469ac, 0x3c050009, 0xafa20014, 0x8d460000, 
+0x34a50700, 0xc002b3b, 0x3c03821, 0x8f4202ec, 
+0x24420001, 0xaf4202ec, 0x8f4202ec, 0x8fbf0048, 
+0x8fbe0044, 0x8fb50040, 0x8fb3003c, 0x8fb20038, 
+0x8fb10034, 0x8fb00030, 0x3e00008, 0x27bd0050, 
+0x3c020001, 0x8c426da8, 0x27bdffe0, 0x1440000d, 
+0xafbf0018, 0x3c040001, 0x24846a0c, 0x3c050008, 
+0xafa00010, 0xafa00014, 0x8f860220, 0x34a50700, 
+0x24020001, 0x3c010001, 0xac226da8, 0xc002b3b, 
+0x3821, 0x3c020004, 0x2c21024, 0x10400007, 
+0x0, 0x8f820220, 0x3c0308ff, 0x3463ffff, 
+0x431024, 0x34420008, 0xaf820220, 0x3c050001, 
+0x8ca56d98, 0x24020001, 0x14a20007, 0x2021, 
+0xc00529b, 0x24050001, 0xac02026c, 0x8c03026c, 
+0x10000006, 0x3c020007, 0xc00529b, 0x2021, 
+0xac020268, 0x8c030268, 0x3c020007, 0x621824, 
+0x3c020002, 0x5062000d, 0x3c0205f5, 0x43102b, 
+0x14400006, 0x3c020004, 0x3c020001, 0x10620009, 
+0x3c020098, 0x1000000b, 0x0, 0x14620009, 
+0x3c023b9a, 0x10000004, 0x3442ca00, 0x10000002, 
+0x3442e100, 0x34429680, 0xaf4201fc, 0x8f4201fc, 
+0xaee20064, 0x8fbf0018, 0x3e00008, 0x27bd0020, 
+0x0, 0x0, 0x0, 0x86102b, 
+0x50400001, 0x872023, 0xc41023, 0x24843, 
+0x125102b, 0x1040001b, 0x91040, 0x824021, 
+0x88102b, 0x10400007, 0x1821, 0x94820000, 
+0x24840002, 0x621821, 0x88102b, 0x1440fffb, 
+0x0, 0x602021, 0xc73023, 0xa91023, 
+0x21040, 0xc22821, 0xc5102b, 0x10400007, 
+0x1821, 0x94c20000, 0x24c60002, 0x621821, 
+0xc5102b, 0x1440fffb, 0x0, 0x1000000d, 
+0x832021, 0x51040, 0x822821, 0x85102b, 
+0x10400007, 0x1821, 0x94820000, 0x24840002, 
+0x621821, 0x85102b, 0x1440fffb, 0x0, 
+0x602021, 0x41c02, 0x3082ffff, 0x622021, 
+0x41c02, 0x3082ffff, 0x622021, 0x3e00008, 
+0x3082ffff, 0x3e00008, 0x0, 0x802821, 
+0x30a20001, 0x1040002b, 0x3c03001f, 0x3463ffff, 
+0x24a20004, 0x62102b, 0x54400007, 0x65102b, 
+0x90a20001, 0x90a40003, 0x90a30000, 0x90a50002, 
+0x1000002a, 0x441021, 0x10400003, 0x0, 
+0x8f420148, 0xa22823, 0x90a40000, 0x24a50001, 
+0x65102b, 0x10400003, 0x0, 0x8f420148, 
+0xa22823, 0x90a20000, 0x24a50001, 0x21200, 
+0x822021, 0x65102b, 0x10400003, 0x0, 
+0x8f420148, 0xa22823, 0x90a20000, 0x24a50001, 
+0x822021, 0x65102b, 0x10400003, 0x0, 
+0x8f420148, 0xa22823, 0x90a20000, 0x1000002d, 
+0x21200, 0x3463ffff, 0x24a20004, 0x62102b, 
+0x5440000a, 0x65102b, 0x90a20000, 0x90a40002, 
+0x90a30001, 0x90a50003, 0x441021, 0x21200, 
+0x651821, 0x10000020, 0x432021, 0x10400003, 
+0x0, 0x8f420148, 0xa22823, 0x90a20000, 
+0x24a50001, 0x22200, 0x65102b, 0x10400003, 
+0x0, 0x8f420148, 0xa22823, 0x90a20000, 
+0x24a50001, 0x822021, 0x65102b, 0x10400003, 
+0x0, 0x8f420148, 0xa22823, 0x90a20000, 
+0x24a50001, 0x21200, 0x822021, 0x65102b, 
+0x10400003, 0x0, 0x8f420148, 0xa22823, 
+0x90a20000, 0x822021, 0x41c02, 0x3082ffff, 
+0x622021, 0x41c02, 0x3082ffff, 0x622021, 
+0x3e00008, 0x3082ffff, 0x0, 0x8f820220, 
+0x34420002, 0xaf820220, 0x3c020002, 0x8c428ff8, 
+0x30424000, 0x10400054, 0x24040001, 0x8f820200, 
+0x24067fff, 0x8f830200, 0x30450002, 0x2402fffd, 
+0x621824, 0xaf830200, 0xaf840204, 0x8f830054, 
+0x8f820054, 0x10000002, 0x24630001, 0x8f820054, 
+0x621023, 0x2c420002, 0x1440fffc, 0x0, 
+0x8f820224, 0x1444004d, 0x42040, 0xc4102b, 
+0x1040fff1, 0x0, 0x8f820200, 0x451025, 
+0xaf820200, 0x8f820220, 0x34428000, 0xaf820220, 
+0x8f830054, 0x8f820054, 0x10000002, 0x24630001, 
+0x8f820054, 0x621023, 0x2c420002, 0x1440fffc, 
+0x0, 0x8f820220, 0x3c030004, 0x431024, 
+0x1440000f, 0x0, 0x8f820220, 0x3c03ffff, 
+0x34637fff, 0x431024, 0xaf820220, 0x8f830054, 
+0x8f820054, 0x10000002, 0x24630001, 0x8f820054, 
+0x621023, 0x2c420002, 0x1440fffc, 0x0, 
+0x8f820220, 0x3c030004, 0x431024, 0x1440000d, 
+0x0, 0x8f820220, 0x34428000, 0xaf820220, 
+0x8f830054, 0x8f820054, 0x10000002, 0x24630001, 
+0x8f820054, 0x621023, 0x2c420002, 0x1440fffc, 
+0x0, 0x8f820220, 0x3c030004, 0x431024, 
+0x1040001b, 0x1021, 0x8f830220, 0x24020001, 
+0x10000015, 0x3c04f700, 0x8f820220, 0x3c04f700, 
+0x441025, 0xaf820220, 0x8f820220, 0x2403fffd, 
+0x431024, 0xaf820220, 0x8f820220, 0x3c030300, 
+0x431024, 0x14400003, 0x0, 0x10000008, 
+0x1021, 0x8f820220, 0x34420002, 0xaf820220, 
+0x8f830220, 0x24020001, 0x641825, 0xaf830220, 
+0x3e00008, 0x0, 0x2021, 0x3c050100, 
+0x24020001, 0xaf80021c, 0xaf820200, 0xaf820220, 
+0x27625000, 0xaf8200c0, 0x27625000, 0xaf8200c4, 
+0x27625000, 0xaf8200c8, 0x27625000, 0xaf8200d0, 
+0x27625000, 0xaf8200d4, 0x27625000, 0xaf8200d8, 
+0x27623000, 0xaf8200e0, 0x27623000, 0xaf8200e4, 
+0x27623000, 0xaf8200e8, 0x27622800, 0xaf8200f0, 
+0x27622800, 0xaf8200f4, 0x27622800, 0xaf8200f8, 
+0x418c0, 0x24840001, 0x3631021, 0xac453004, 
+0x3631021, 0xac403000, 0x28820200, 0x1440fff9, 
+0x418c0, 0x2021, 0x418c0, 0x24840001, 
+0x3631021, 0xac402804, 0x3631021, 0xac402800, 
+0x28820100, 0x1440fff9, 0x418c0, 0xaf80023c, 
+0x24030080, 0x24040100, 0xac600000, 0x24630004, 
+0x64102b, 0x5440fffd, 0xac600000, 0x8f830040, 
+0x3c02f000, 0x621824, 0x3c025000, 0x1062000c, 
+0x43102b, 0x14400006, 0x3c026000, 0x3c024000, 
+0x10620008, 0x24020800, 0x10000008, 0x0, 
+0x10620004, 0x24020800, 0x10000004, 0x0, 
+0x24020700, 0x3c010001, 0xac226dac, 0x3e00008, 
+0x0, 0x3c020001, 0x8c426dbc, 0x27bdffd0, 
+0xafbf002c, 0xafb20028, 0xafb10024, 0xafb00020, 
+0x3c010001, 0x10400005, 0xac206d94, 0xc004d9e, 
+0x0, 0x3c010001, 0xac206dbc, 0x8f830054, 
+0x8f820054, 0x10000002, 0x24630064, 0x8f820054, 
+0x621023, 0x2c420065, 0x1440fffc, 0x0, 
+0xc004db9, 0x0, 0x24040001, 0x2821, 
+0x27a60018, 0x34028000, 0xc0045be, 0xa7a20018, 
+0x8f830054, 0x8f820054, 0x10000002, 0x24630064, 
+0x8f820054, 0x621023, 0x2c420065, 0x1440fffc, 
+0x24040001, 0x24050001, 0xc00457c, 0x27a60018, 
+0x8f830054, 0x8f820054, 0x10000002, 0x24630064, 
+0x8f820054, 0x621023, 0x2c420065, 0x1440fffc, 
+0x24040001, 0x24050001, 0xc00457c, 0x27a60018, 
+0x8f830054, 0x8f820054, 0x10000002, 0x24630064, 
+0x8f820054, 0x621023, 0x2c420065, 0x1440fffc, 
+0x24040001, 0x3c060001, 0x24c66f24, 0xc00457c, 
+0x24050002, 0x8f830054, 0x8f820054, 0x10000002, 
+0x24630064, 0x8f820054, 0x621023, 0x2c420065, 
+0x1440fffc, 0x24040001, 0x24050003, 0x3c100001, 
+0x26106f26, 0xc00457c, 0x2003021, 0x97a60018, 
+0x3c070001, 0x94e76f24, 0x3c040001, 0x24846ae0, 
+0xafa00014, 0x96020000, 0x3c05000d, 0x34a50100, 
+0xc002b3b, 0xafa20010, 0x97a20018, 0x1040004d, 
+0x24036040, 0x96020000, 0x3042fff0, 0x1443000c, 
+0x24020020, 0x3c030001, 0x94636f24, 0x1462000b, 
+0x24027830, 0x24020003, 0x3c010001, 0xac226d94, 
+0x24020005, 0x3c010001, 0x1000003f, 0xac226f34, 
+0x3c030001, 0x94636f24, 0x24027830, 0x1462000c, 
+0x24030010, 0x3c020001, 0x94426f26, 0x3042fff0, 
+0x14430007, 0x24020003, 0x3c010001, 0xac226d94, 
+0x24020006, 0x3c010001, 0x1000002f, 0xac226f34, 
+0x3c020001, 0x8c426d94, 0x3c030001, 0x94636f24, 
+0x34420001, 0x3c010001, 0xac226d94, 0x24020015, 
+0x1462000b, 0x0, 0x3c020001, 0x94426f26, 
+0x3042fff0, 0x3843f420, 0x2c630001, 0x3842f430, 
+0x2c420001, 0x621825, 0x1460001b, 0x24020003, 
+0x3c030001, 0x94636f24, 0x24027810, 0x14620016, 
+0x24020002, 0x3c020001, 0x94426f26, 0x3042fff0, 
+0x14400011, 0x24020002, 0x1000000f, 0x24020004, 
+0x3c020001, 0x8c426d94, 0x34420008, 0x3c010001, 
+0xac226d94, 0x1000005e, 0x24020004, 0x3c020001, 
+0x8c426d94, 0x34420004, 0x3c010001, 0x100000af, 
+0xac226d94, 0x24020001, 0x3c010001, 0xac226f40, 
+0x3c020001, 0x8c426d94, 0x30420002, 0x144000b2, 
+0x3c09fff0, 0x24020e00, 0xaf820238, 0x8f840054, 
+0x8f820054, 0x24030008, 0x3c010001, 0xac236d98, 
+0x10000002, 0x248401f4, 0x8f820054, 0x821023, 
+0x2c4201f5, 0x1440fffc, 0x3c0200c8, 0x344201fb, 
+0xaf820238, 0x8f830054, 0x8f820054, 0x10000002, 
+0x246301f4, 0x8f820054, 0x621023, 0x2c4201f5, 
+0x1440fffc, 0x8021, 0x24120001, 0x24110009, 
+0xc004482, 0x0, 0x3c010001, 0xac326db4, 
+0xc004547, 0x0, 0x3c020001, 0x8c426db4, 
+0x1451fffb, 0x3c0200c8, 0x344201f6, 0xaf820238, 
+0x8f830054, 0x8f820054, 0x10000002, 0x2463000a, 
+0x8f820054, 0x621023, 0x2c42000b, 0x1440fffc, 
+0x0, 0x8f820220, 0x24040001, 0x34420002, 
+0xaf820220, 0x8f830200, 0x24057fff, 0x2402fffd, 
+0x621824, 0xaf830200, 0xaf840204, 0x8f830054, 
+0x8f820054, 0x10000002, 0x24630001, 0x8f820054, 
+0x621023, 0x2c420002, 0x1440fffc, 0x0, 
+0x8f820224, 0x14440005, 0x34028000, 0x42040, 
+0xa4102b, 0x1040fff0, 0x34028000, 0x1082ffa0, 
+0x26100001, 0x2e020014, 0x1440ffcd, 0x24020004, 
+0x3c010001, 0xac226d98, 0x8021, 0x24120009, 
+0x3c11ffff, 0x36313f7f, 0xc004482, 0x0, 
+0x24020001, 0x3c010001, 0xac226db4, 0xc004547, 
+0x0, 0x3c020001, 0x8c426db4, 0x1452fffb, 
+0x0, 0x8f820044, 0x511024, 0x34425080, 
+0xaf820044, 0x8f830054, 0x8f820054, 0x10000002, 
+0x2463000a, 0x8f820054, 0x621023, 0x2c42000b, 
+0x1440fffc, 0x0, 0x8f820044, 0x511024, 
+0x3442f080, 0xaf820044, 0x8f830054, 0x8f820054, 
+0x10000002, 0x2463000a, 0x8f820054, 0x621023, 
+0x2c42000b, 0x1440fffc, 0x0, 0x8f820220, 
+0x3c03f700, 0x431025, 0xaf820220, 0x8f830054, 
+0x8f820054, 0x10000002, 0x24630064, 0x8f820054, 
+0x621023, 0x2c420065, 0x1440fffc, 0x0, 
+0x8f820220, 0x24040001, 0x34420002, 0xaf820220, 
+0x8f830200, 0x24057fff, 0x2402fffd, 0x621824, 
+0xaf830200, 0xaf840204, 0x8f830054, 0x8f820054, 
+0x10000002, 0x24630001, 0x8f820054, 0x621023, 
+0x2c420002, 0x1440fffc, 0x0, 0x8f820224, 
+0x14440005, 0x34028000, 0x42040, 0xa4102b, 
+0x1040fff0, 0x34028000, 0x1082ff50, 0x26100001, 
+0x2e020064, 0x1440ffb0, 0x0, 0x3c020001, 
+0x8c426d94, 0x30420004, 0x14400007, 0x3c09fff0, 
+0x8f820044, 0x3c03ffff, 0x34633f7f, 0x431024, 
+0xaf820044, 0x3c09fff0, 0x3529bdc0, 0x3c060001, 
+0x8cc66d94, 0x3c040001, 0x24846ae0, 0x24020001, 
+0x3c010001, 0xac226d9c, 0x8f820054, 0x3c070001, 
+0x8ce76f40, 0x3c030001, 0x94636f24, 0x3c080001, 
+0x95086f26, 0x3c05000d, 0x34a50100, 0x3c010001, 
+0xac206d98, 0x491021, 0x3c010001, 0xac226f30, 
+0xafa30010, 0xc002b3b, 0xafa80014, 0x8fbf002c, 
+0x8fb20028, 0x8fb10024, 0x8fb00020, 0x3e00008, 
+0x27bd0030, 0x27bdffe8, 0x3c050001, 0x8ca56d98, 
+0x24060004, 0x24020001, 0x14a20014, 0xafbf0010, 
+0x3c020002, 0x8c428ffc, 0x30428000, 0x10400005, 
+0x3c04000f, 0x3c030001, 0x8c636f40, 0x10000005, 
+0x34844240, 0x3c040004, 0x3c030001, 0x8c636f40, 
+0x348493e0, 0x24020005, 0x14620016, 0x0, 
+0x3c04003d, 0x10000013, 0x34840900, 0x3c020002, 
+0x8c428ff8, 0x30428000, 0x10400005, 0x3c04001e, 
+0x3c030001, 0x8c636f40, 0x10000005, 0x34848480, 
+0x3c04000f, 0x3c030001, 0x8c636f40, 0x34844240, 
+0x24020005, 0x14620003, 0x0, 0x3c04007a, 
+0x34841200, 0x3c020001, 0x8c426f30, 0x8f830054, 
+0x441021, 0x431023, 0x44102b, 0x1440004c, 
+0x0, 0x3c020001, 0x8c426da0, 0x14400048, 
+0x0, 0x3c010001, 0x10c00025, 0xac206db0, 
+0x3c090001, 0x8d296d94, 0x24070001, 0x3c044000, 
+0x3c080002, 0x25088ffc, 0x250afffc, 0x52842, 
+0x14a00002, 0x24c6ffff, 0x24050008, 0xa91024, 
+0x10400010, 0x0, 0x14a70008, 0x0, 
+0x8d020000, 0x441024, 0x1040000a, 0x0, 
+0x3c010001, 0x10000007, 0xac256db0, 0x8d420000, 
+0x441024, 0x10400003, 0x0, 0x3c010001, 
+0xac276db0, 0x3c020001, 0x8c426db0, 0x6182b, 
+0x2c420001, 0x431024, 0x5440ffe5, 0x52842, 
+0x8f820054, 0x3c030001, 0x8c636db0, 0x3c010001, 
+0xac226f30, 0x1060003b, 0x24020005, 0x3c030001, 
+0x8c636f40, 0x3c010001, 0xac256d98, 0x14620012, 
+0x24020001, 0x3c020002, 0x8c428ff8, 0x3c032000, 
+0x34635000, 0x431024, 0x14400006, 0x24020001, 
+0x3c010001, 0xac206f1c, 0x3c010001, 0xac226d98, 
+0x24020001, 0x3c010001, 0xac226e24, 0x3c010001, 
+0xac226da4, 0x24020001, 0x3c010001, 0xac226d9c, 
+0x3c020001, 0x8c426db0, 0x1040001e, 0x0, 
+0x3c020001, 0x8c426d9c, 0x10400008, 0x24020001, 
+0x3c010001, 0xac206d9c, 0xaee204b8, 0x3c010001, 
+0xac206e1c, 0x3c010001, 0xac226dd4, 0x8ee304b8, 
+0x24020008, 0x10620005, 0x24020001, 0xc004239, 
+0x0, 0x1000000b, 0x0, 0x3c030001, 
+0x8c636d98, 0x10620007, 0x2402000e, 0x3c030002, 
+0x8c638f90, 0x10620003, 0x0, 0xc004e9c, 
+0x8f840220, 0x8fbf0010, 0x3e00008, 0x27bd0018, 
+0x27bdffe0, 0x3c03fdff, 0x3c040001, 0x8c846d98, 
+0x3c020001, 0x8c426dc0, 0x3463ffff, 0x283a024, 
+0x14820006, 0xafbf0018, 0x8ee304b8, 0x3c020001, 
+0x8c426dc4, 0x10620006, 0x0, 0x8ee204b8, 
+0x3c010001, 0xac246dc0, 0x3c010001, 0xac226dc4, 
+0x3c030001, 0x8c636d98, 0x24020002, 0x1062019c, 
+0x2c620003, 0x10400005, 0x24020001, 0x1062000a, 
+0x0, 0x10000226, 0x0, 0x24020004, 
+0x106200b6, 0x24020008, 0x1062010a, 0x24020001, 
+0x1000021f, 0x0, 0x8ee204b8, 0x2443ffff, 
+0x2c620008, 0x1040021c, 0x31080, 0x3c010001, 
+0x220821, 0x8c226af8, 0x400008, 0x0, 
+0x3c030001, 0x8c636f40, 0x24020005, 0x14620010, 
+0x0, 0x3c020001, 0x8c426da4, 0x10400008, 
+0x24020003, 0xc004482, 0x0, 0x24020002, 
+0xaee204b8, 0x3c010001, 0x10000002, 0xac206da4, 
+0xaee204b8, 0x3c010001, 0x10000203, 0xac206d30, 
+0xc004482, 0x0, 0x3c020001, 0x8c426da4, 
+0x3c010001, 0xac206d30, 0x1440017a, 0x24020002, 
+0x1000019d, 0x24020007, 0x3c030001, 0x8c636f40, 
+0x24020005, 0x14620003, 0x24020001, 0x3c010001, 
+0xac226dd0, 0xc0045ff, 0x0, 0x3c030001, 
+0x8c636dd0, 0x10000174, 0x24020011, 0x3c050001, 
+0x8ca56d98, 0x3c060002, 0x8cc68ffc, 0xc005104, 
+0x2021, 0x24020005, 0x3c010001, 0xac206da4, 
+0x100001e1, 0xaee204b8, 0x3c040001, 0x24846aec, 
+0x3c05000f, 0x34a50100, 0x3021, 0x3821, 
+0xafa00010, 0xc002b3b, 0xafa00014, 0x100001d6, 
+0x0, 0x8f820220, 0x3c030004, 0x431024, 
+0x14400175, 0x24020007, 0x8f830054, 0x3c020001, 
+0x8c426f28, 0x2463d8f0, 0x431023, 0x2c422710, 
+0x14400003, 0x24020001, 0x3c010001, 0xac226d9c, 
+0x3c020002, 0x8c428ffc, 0x30425000, 0x104001c2, 
+0x0, 0x8f820220, 0x30428000, 0x1040017d, 
+0x0, 0x10000175, 0x0, 0x3c050001, 
+0x8ca56d98, 0xc00529b, 0x2021, 0xc00551b, 
+0x2021, 0x3c030002, 0x8c638ff4, 0x46101b0, 
+0x24020001, 0x3c020008, 0x621024, 0x10400006, 
+0x0, 0x8f820214, 0x3c03ffff, 0x431024, 
+0x10000005, 0x3442251f, 0x8f820214, 0x3c03ffff, 
+0x431024, 0x3442241f, 0xaf820214, 0x8f820220, 
+0x3c030200, 0x34420002, 0xaf820220, 0x24020008, 
+0xaee204b8, 0x8f820220, 0x283a025, 0x3c030004, 
+0x431024, 0x14400016, 0x0, 0x3c020002, 
+0x8c428ffc, 0x30425000, 0x1040000d, 0x0, 
+0x8f820220, 0x30428000, 0x10400006, 0x0, 
+0x8f820220, 0x3c03ffff, 0x34637fff, 0x10000003, 
+0x431024, 0x8f820220, 0x34428000, 0xaf820220, 
+0x8f820220, 0x3c03f700, 0x431025, 0xaf820220, 
+0x3c030001, 0x8c636f40, 0x24020005, 0x1462000a, 
+0x0, 0x3c020001, 0x94426f26, 0x24429fbc, 
+0x2c420004, 0x10400004, 0x24040018, 0x24050002, 
+0xc004ddb, 0x24060020, 0xc003e6d, 0x0, 
+0x3c010001, 0x10000170, 0xac206e20, 0x8ee204b8, 
+0x2443ffff, 0x2c620008, 0x1040016b, 0x31080, 
+0x3c010001, 0x220821, 0x8c226b18, 0x400008, 
+0x0, 0xc004547, 0x0, 0x3c030001, 
+0x8c636db4, 0x100000e8, 0x24020009, 0x3c020002, 
+0x8c428ff8, 0x30424000, 0x10400004, 0x0, 
+0x8f820044, 0x10000006, 0x3442f080, 0x8f820044, 
+0x3c03ffff, 0x34633f7f, 0x431024, 0x3442a080, 
+0xaf820044, 0x8f830054, 0x100000ea, 0x24020004, 
+0x8f830054, 0x3c020001, 0x8c426f28, 0x2463d8f0, 
+0x431023, 0x2c422710, 0x14400147, 0x24020005, 
+0x100000d8, 0x0, 0x8f820220, 0x3c03f700, 
+0x431025, 0xaf820220, 0xaf800204, 0x3c010002, 
+0x100000d6, 0xac208fe0, 0x8f830054, 0x3c020001, 
+0x8c426f28, 0x2463fff6, 0x431023, 0x2c42000a, 
+0x14400135, 0x24020007, 0x100000d7, 0x0, 
+0xc003f50, 0x0, 0x1040012d, 0x24020001, 
+0x8f820214, 0x3c03ffff, 0x3c040001, 0x8c846f1c, 
+0x431024, 0x3442251f, 0xaf820214, 0x24020008, 
+0x10800005, 0xaee204b8, 0x3c020001, 0x8c426e44, 
+0x10400064, 0x24020001, 0x8f820220, 0x3c030008, 
+0x431024, 0x1040006a, 0x3c020200, 0x10000078, 
+0x0, 0x8ee204b8, 0x2443ffff, 0x2c620007, 
+0x10400115, 0x31080, 0x3c010001, 0x220821, 
+0x8c226b38, 0x400008, 0x0, 0xc003daf, 
+0x0, 0x3c010001, 0xac206d9c, 0xaf800204, 
+0x3c010002, 0xc004482, 0xac208fe0, 0x24020001, 
+0x3c010001, 0xac226db4, 0x24020002, 0x10000102, 
+0xaee204b8, 0xc004547, 0x0, 0x3c030001, 
+0x8c636db4, 0x10000084, 0x24020009, 0x3c020002, 
+0x8c428ff8, 0x30424000, 0x10400003, 0x3c0200c8, 
+0x10000002, 0x344201f6, 0x344201fe, 0xaf820238, 
+0x8f830054, 0x1000008b, 0x24020004, 0x8f830054, 
+0x3c020001, 0x8c426f28, 0x2463d8f0, 0x431023, 
+0x2c422710, 0x144000e8, 0x24020005, 0x10000079, 
+0x0, 0x8f820220, 0x3c03f700, 0x431025, 
+0xaf820220, 0xaf800204, 0x3c010002, 0x10000077, 
+0xac208fe0, 0x8f830054, 0x3c020001, 0x8c426f28, 
+0x2463fff6, 0x431023, 0x2c42000a, 0x144000d6, 
+0x24020007, 0x10000078, 0x0, 0xc003f50, 
+0x0, 0x104000ce, 0x24020001, 0x8f820214, 
+0x3c03ffff, 0x3c040001, 0x8c846f1c, 0x431024, 
+0x3442251f, 0xaf820214, 0x24020008, 0x1080000f, 
+0xaee204b8, 0x3c020001, 0x8c426e44, 0x1440000b, 
+0x0, 0x8f820220, 0x34420002, 0xaf820220, 
+0x24020001, 0x3c010002, 0xac228f90, 0xc004e9c, 
+0x8f840220, 0x10000016, 0x0, 0x8f820220, 
+0x3c030008, 0x431024, 0x14400011, 0x3c020200, 
+0x282a025, 0x2402000e, 0x3c010002, 0xac228f90, 
+0xc00551b, 0x2021, 0x8f820220, 0x34420002, 
+0xc003e6d, 0xaf820220, 0x3c050001, 0x8ca56d98, 
+0xc00529b, 0x2021, 0x100000a3, 0x0, 
+0x3c020001, 0x8c426e44, 0x1040009f, 0x0, 
+0x3c020001, 0x8c426e40, 0x2442ffff, 0x3c010001, 
+0xac226e40, 0x14400098, 0x24020002, 0x3c010001, 
+0xac206e44, 0x3c010001, 0x10000093, 0xac226e40, 
+0x8ee204b8, 0x2443ffff, 0x2c620007, 0x1040008e, 
+0x31080, 0x3c010001, 0x220821, 0x8c226b58, 
+0x400008, 0x0, 0x3c020001, 0x8c426da4, 
+0x10400018, 0x24020005, 0xc004482, 0x0, 
+0x24020002, 0xaee204b8, 0x3c010001, 0x1000007e, 
+0xac206da4, 0xc004963, 0x0, 0x3c030001, 
+0x8c636dd4, 0x24020006, 0x14620077, 0x24020003, 
+0x10000075, 0xaee204b8, 0x3c050001, 0x8ca56d98, 
+0x3c060002, 0x8cc68ff8, 0xc005104, 0x2021, 
+0x24020005, 0x1000006c, 0xaee204b8, 0x8f820220, 
+0x3c03f700, 0x431025, 0xaf820220, 0x8f830054, 
+0x24020006, 0xaee204b8, 0x3c010001, 0x10000062, 
+0xac236f28, 0x8f820220, 0x3c030004, 0x431024, 
+0x10400003, 0x24020007, 0x1000005b, 0xaee204b8, 
+0x8f830054, 0x3c020001, 0x8c426f28, 0x2463d8f0, 
+0x431023, 0x2c422710, 0x14400003, 0x24020001, 
+0x3c010001, 0xac226d9c, 0x3c020002, 0x8c428ff8, 
+0x30425000, 0x1040004c, 0x0, 0x8f820220, 
+0x30428000, 0x10400007, 0x0, 0x8f820220, 
+0x3c03ffff, 0x34637fff, 0x431024, 0x10000042, 
+0xaf820220, 0x8f820220, 0x34428000, 0x1000003e, 
+0xaf820220, 0x3c050001, 0x8ca56d98, 0xc00529b, 
+0x2021, 0xc00551b, 0x2021, 0x3c020002, 
+0x8c428ff0, 0x4410032, 0x24020001, 0x8f820214, 
+0x3c03ffff, 0x431024, 0x3442251f, 0xaf820214, 
+0x24020008, 0xaee204b8, 0x8f820220, 0x34420002, 
+0xaf820220, 0x8f820220, 0x3c030004, 0x431024, 
+0x14400016, 0x0, 0x3c020002, 0x8c428ff8, 
+0x30425000, 0x1040000d, 0x0, 0x8f820220, 
+0x30428000, 0x10400006, 0x0, 0x8f820220, 
+0x3c03ffff, 0x34637fff, 0x10000003, 0x431024, 
+0x8f820220, 0x34428000, 0xaf820220, 0x8f820220, 
+0x3c03f700, 0x431025, 0xaf820220, 0x3c020001, 
+0x94426f26, 0x24429fbc, 0x2c420004, 0x10400004, 
+0x24040018, 0x24050002, 0xc004ddb, 0x24060020, 
+0xc003e6d, 0x0, 0x10000003, 0x0, 
+0x3c010001, 0xac226d9c, 0x8fbf0018, 0x3e00008, 
+0x27bd0020, 0x8f820200, 0x8f820220, 0x8f820220, 
+0x34420004, 0xaf820220, 0x8f820200, 0x3c050001, 
+0x8ca56d98, 0x34420004, 0xaf820200, 0x24020002, 
+0x10a2004b, 0x2ca20003, 0x10400005, 0x24020001, 
+0x10a2000a, 0x0, 0x100000b1, 0x0, 
+0x24020004, 0x10a20072, 0x24020008, 0x10a20085, 
+0x3c02f0ff, 0x100000aa, 0x0, 0x8f830050, 
+0x3c02f0ff, 0x3442ffff, 0x3c040001, 0x8c846f40, 
+0x621824, 0x3c020700, 0x621825, 0x24020e00, 
+0x2484fffb, 0x2c840002, 0xaf830050, 0xaf850200, 
+0xaf850220, 0x14800006, 0xaf820238, 0x8f820044, 
+0x3c03ffff, 0x34633f7f, 0x431024, 0xaf820044, 
+0x3c030001, 0x8c636f40, 0x24020005, 0x14620004, 
+0x0, 0x8f820044, 0x34425000, 0xaf820044, 
+0x3c020001, 0x8c426d88, 0x3c030001, 0x8c636f40, 
+0x34420022, 0x2463fffc, 0x2c630002, 0x1460000c, 
+0xaf820200, 0x3c020001, 0x8c426dac, 0x3c030001, 
+0x8c636d90, 0x3c040001, 0x8c846d8c, 0x34428000, 
+0x621825, 0x641825, 0x1000000a, 0x34620002, 
+0x3c020001, 0x8c426d90, 0x3c030001, 0x8c636dac, 
+0x3c040001, 0x8c846d8c, 0x431025, 0x441025, 
+0x34420002, 0xaf820220, 0x1000002f, 0x24020001, 
+0x24020e01, 0xaf820238, 0x8f830050, 0x3c02f0ff, 
+0x3442ffff, 0x3c040001, 0x8c846f1c, 0x621824, 
+0x3c020d00, 0x621825, 0x24020001, 0xaf830050, 
+0xaf820200, 0xaf820220, 0x10800005, 0x3c033f00, 
+0x3c020001, 0x8c426d80, 0x10000004, 0x34630070, 
+0x3c020001, 0x8c426d80, 0x34630072, 0x431025, 
+0xaf820200, 0x3c030001, 0x8c636d84, 0x3c02f700, 
+0x621825, 0x3c020001, 0x8c426d90, 0x3c040001, 
+0x8c846dac, 0x3c050001, 0x8ca56f40, 0x431025, 
+0x441025, 0xaf820220, 0x24020005, 0x14a20006, 
+0x24020001, 0x8f820044, 0x2403afff, 0x431024, 
+0xaf820044, 0x24020001, 0x1000003d, 0xaf820238, 
+0x8f830050, 0x3c02f0ff, 0x3442ffff, 0x3c040001, 
+0x8c846f1c, 0x621824, 0x3c020a00, 0x621825, 
+0x24020001, 0xaf830050, 0xaf820200, 0x1080001e, 
+0xaf820220, 0x3c020001, 0x8c426e44, 0x1440001a, 
+0x3c033f00, 0x3c020001, 0x8c426d80, 0x1000001a, 
+0x346300e0, 0x8f830050, 0x3c040001, 0x8c846f1c, 
+0x3442ffff, 0x621824, 0x1080000f, 0xaf830050, 
+0x3c020001, 0x8c426e44, 0x1440000b, 0x3c043f00, 
+0x3c030001, 0x8c636d80, 0x348400e0, 0x24020001, 
+0xaf820200, 0xaf820220, 0x641825, 0xaf830200, 
+0x10000008, 0x3c05f700, 0x3c020001, 0x8c426d80, 
+0x3c033f00, 0x346300e2, 0x431025, 0xaf820200, 
+0x3c05f700, 0x34a58000, 0x3c030001, 0x8c636d84, 
+0x3c020001, 0x8c426d90, 0x3c040001, 0x8c846dac, 
+0x651825, 0x431025, 0x441025, 0xaf820220, 
+0x3e00008, 0x0, 0x3c030001, 0x8c636db4, 
+0x3c020001, 0x8c426db8, 0x10620003, 0x24020002, 
+0x3c010001, 0xac236db8, 0x1062001d, 0x2c620003, 
+0x10400025, 0x24020001, 0x14620023, 0x24020004, 
+0x3c030001, 0x8c636d98, 0x10620006, 0x24020008, 
+0x1462000c, 0x3c0200c8, 0x344201fb, 0x10000009, 
+0xaf820238, 0x24020e01, 0xaf820238, 0x8f820044, 
+0x3c03ffff, 0x34633f7f, 0x431024, 0x34420080, 
+0xaf820044, 0x8f830054, 0x24020002, 0x3c010001, 
+0xac226db4, 0x3c010001, 0x1000000b, 0xac236f2c, 
+0x8f830054, 0x3c020001, 0x8c426f2c, 0x2463d8f0, 
+0x431023, 0x2c422710, 0x14400003, 0x24020009, 
+0x3c010001, 0xac226db4, 0x3e00008, 0x0, 
+0x0, 0x0, 0x0, 0x27bdffd8, 
+0xafb20018, 0x809021, 0xafb3001c, 0xa09821, 
+0xafb10014, 0xc08821, 0xafb00010, 0x8021, 
+0xafbf0020, 0xa6200000, 0xc004d78, 0x24040001, 
+0x26100001, 0x2e020020, 0x1440fffb, 0x0, 
+0xc004d78, 0x2021, 0xc004d78, 0x24040001, 
+0xc004d78, 0x24040001, 0xc004d78, 0x2021, 
+0x24100010, 0x2501024, 0x10400002, 0x2021, 
+0x24040001, 0xc004d78, 0x108042, 0x1600fffa, 
+0x2501024, 0x24100010, 0x2701024, 0x10400002, 
+0x2021, 0x24040001, 0xc004d78, 0x108042, 
+0x1600fffa, 0x2701024, 0xc004db9, 0x34108000, 
+0xc004db9, 0x0, 0xc004d58, 0x0, 
+0x50400005, 0x108042, 0x96220000, 0x501025, 
+0xa6220000, 0x108042, 0x1600fff7, 0x0, 
+0xc004db9, 0x0, 0x8fbf0020, 0x8fb3001c, 
+0x8fb20018, 0x8fb10014, 0x8fb00010, 0x3e00008, 
+0x27bd0028, 0x27bdffd8, 0xafb10014, 0x808821, 
+0xafb20018, 0xa09021, 0xafb3001c, 0xc09821, 
+0xafb00010, 0x8021, 0xafbf0020, 0xc004d78, 
+0x24040001, 0x26100001, 0x2e020020, 0x1440fffb, 
+0x0, 0xc004d78, 0x2021, 0xc004d78, 
+0x24040001, 0xc004d78, 0x2021, 0xc004d78, 
+0x24040001, 0x24100010, 0x2301024, 0x10400002, 
+0x2021, 0x24040001, 0xc004d78, 0x108042, 
+0x1600fffa, 0x2301024, 0x24100010, 0x2501024, 
+0x10400002, 0x2021, 0x24040001, 0xc004d78, 
+0x108042, 0x1600fffa, 0x2501024, 0xc004d78, 
+0x24040001, 0xc004d78, 0x2021, 0x34108000, 
+0x96620000, 0x501024, 0x10400002, 0x2021, 
+0x24040001, 0xc004d78, 0x108042, 0x1600fff8, 
+0x0, 0xc004db9, 0x0, 0x8fbf0020, 
+0x8fb3001c, 0x8fb20018, 0x8fb10014, 0x8fb00010, 
+0x3e00008, 0x27bd0028, 0x3c040001, 0x8c846dd0, 
+0x3c020001, 0x8c426e18, 0x27bdffd8, 0xafbf0020, 
+0xafb1001c, 0x10820003, 0xafb00018, 0x3c010001, 
+0xac246e18, 0x3c030001, 0x8c636f40, 0x24020005, 
+0x14620005, 0x2483ffff, 0xc004963, 0x0, 
+0x1000034c, 0x0, 0x2c620013, 0x10400349, 
+0x31080, 0x3c010001, 0x220821, 0x8c226b80, 
+0x400008, 0x0, 0xc004db9, 0x8021, 
+0x34028000, 0xa7a20010, 0x27b10010, 0xc004d78, 
+0x24040001, 0x26100001, 0x2e020020, 0x1440fffb, 
+0x0, 0xc004d78, 0x2021, 0xc004d78, 
+0x24040001, 0xc004d78, 0x2021, 0xc004d78, 
+0x24040001, 0x24100010, 0x32020001, 0x10400002, 
+0x2021, 0x24040001, 0xc004d78, 0x108042, 
+0x1600fffa, 0x32020001, 0x24100010, 0xc004d78, 
+0x2021, 0x108042, 0x1600fffc, 0x0, 
+0xc004d78, 0x24040001, 0xc004d78, 0x2021, 
+0x34108000, 0x96220000, 0x501024, 0x10400002, 
+0x2021, 0x24040001, 0xc004d78, 0x108042, 
+0x1600fff8, 0x0, 0xc004db9, 0x0, 
+0x1000030e, 0x24020002, 0x27b10010, 0xa7a00010, 
+0x8021, 0xc004d78, 0x24040001, 0x26100001, 
+0x2e020020, 0x1440fffb, 0x0, 0xc004d78, 
+0x2021, 0xc004d78, 0x24040001, 0xc004d78, 
+0x24040001, 0xc004d78, 0x2021, 0x24100010, 
+0x32020001, 0x10400002, 0x2021, 0x24040001, 
+0xc004d78, 0x108042, 0x1600fffa, 0x32020001, 
+0x24100010, 0xc004d78, 0x2021, 0x108042, 
+0x1600fffc, 0x0, 0xc004db9, 0x34108000, 
+0xc004db9, 0x0, 0xc004d58, 0x0, 
+0x50400005, 0x108042, 0x96220000, 0x501025, 
+0xa6220000, 0x108042, 0x1600fff7, 0x0, 
+0xc004db9, 0x0, 0x97a20010, 0x30428000, 
+0x144002dc, 0x24020003, 0x100002d8, 0x0, 
+0x24021200, 0xa7a20010, 0x27b10010, 0x8021, 
+0xc004d78, 0x24040001, 0x26100001, 0x2e020020, 
+0x1440fffb, 0x0, 0xc004d78, 0x2021, 
+0xc004d78, 0x24040001, 0xc004d78, 0x2021, 
+0xc004d78, 0x24040001, 0x24100010, 0x32020001, 
+0x10400002, 0x2021, 0x24040001, 0xc004d78, 
+0x108042, 0x1600fffa, 0x32020001, 0x24100010, 
+0xc004d78, 0x2021, 0x108042, 0x1600fffc, 
+0x0, 0xc004d78, 0x24040001, 0xc004d78, 
+0x2021, 0x34108000, 0x96220000, 0x501024, 
+0x10400002, 0x2021, 0x24040001, 0xc004d78, 
+0x108042, 0x1600fff8, 0x0, 0xc004db9, 
+0x0, 0x8f830054, 0x10000296, 0x24020004, 
+0x8f830054, 0x3c020001, 0x8c426f3c, 0x2463ff9c, 
+0x431023, 0x2c420064, 0x1440029e, 0x24020002, 
+0x3c030001, 0x8c636f40, 0x10620297, 0x2c620003, 
+0x14400296, 0x24020011, 0x24020003, 0x10620005, 
+0x24020004, 0x10620291, 0x2402000f, 0x1000028f, 
+0x24020011, 0x1000028d, 0x24020005, 0x24020014, 
+0xa7a20010, 0x27b10010, 0x8021, 0xc004d78, 
+0x24040001, 0x26100001, 0x2e020020, 0x1440fffb, 
+0x0, 0xc004d78, 0x2021, 0xc004d78, 
+0x24040001, 0xc004d78, 0x2021, 0xc004d78, 
+0x24040001, 0x24100010, 0x32020001, 0x10400002, 
+0x2021, 0x24040001, 0xc004d78, 0x108042, 
+0x1600fffa, 0x32020001, 0x24100010, 0x32020012, 
+0x10400002, 0x2021, 0x24040001, 0xc004d78, 
+0x108042, 0x1600fffa, 0x32020012, 0xc004d78, 
+0x24040001, 0xc004d78, 0x2021, 0x34108000, 
+0x96220000, 0x501024, 0x10400002, 0x2021, 
+0x24040001, 0xc004d78, 0x108042, 0x1600fff8, 
+0x0, 0xc004db9, 0x0, 0x8f830054, 
+0x10000248, 0x24020006, 0x8f830054, 0x3c020001, 
+0x8c426f3c, 0x2463ff9c, 0x431023, 0x2c420064, 
+0x14400250, 0x24020007, 0x1000024c, 0x0, 
+0x24020006, 0xa7a20010, 0x27b10010, 0x8021, 
+0xc004d78, 0x24040001, 0x26100001, 0x2e020020, 
+0x1440fffb, 0x0, 0xc004d78, 0x2021, 
+0xc004d78, 0x24040001, 0xc004d78, 0x2021, 
+0xc004d78, 0x24040001, 0x24100010, 0x32020001, 
+0x10400002, 0x2021, 0x24040001, 0xc004d78, 
+0x108042, 0x1600fffa, 0x32020001, 0x24100010, 
+0x32020013, 0x10400002, 0x2021, 0x24040001, 
+0xc004d78, 0x108042, 0x1600fffa, 0x32020013, 
+0xc004d78, 0x24040001, 0xc004d78, 0x2021, 
+0x34108000, 0x96220000, 0x501024, 0x10400002, 
+0x2021, 0x24040001, 0xc004d78, 0x108042, 
+0x1600fff8, 0x0, 0xc004db9, 0x0, 
+0x8f830054, 0x10000207, 0x24020008, 0x8f830054, 
+0x3c020001, 0x8c426f3c, 0x2463ff9c, 0x431023, 
+0x2c420064, 0x1440020f, 0x24020009, 0x1000020b, 
+0x0, 0x27b10010, 0xa7a00010, 0x8021, 
+0xc004d78, 0x24040001, 0x26100001, 0x2e020020, 
+0x1440fffb, 0x0, 0xc004d78, 0x2021, 
+0xc004d78, 0x24040001, 0xc004d78, 0x24040001, 
+0xc004d78, 0x2021, 0x24100010, 0x32020001, 
+0x10400002, 0x2021, 0x24040001, 0xc004d78, 
+0x108042, 0x1600fffa, 0x32020001, 0x24100010, 
+0x32020018, 0x10400002, 0x2021, 0x24040001, 
+0xc004d78, 0x108042, 0x1600fffa, 0x32020018, 
+0xc004db9, 0x34108000, 0xc004db9, 0x0, 
+0xc004d58, 0x0, 0x50400005, 0x108042, 
+0x96220000, 0x501025, 0xa6220000, 0x108042, 
+0x1600fff7, 0x0, 0xc004db9, 0x8021, 
+0x97a20010, 0x27b10010, 0x34420001, 0xa7a20010, 
+0xc004d78, 0x24040001, 0x26100001, 0x2e020020, 
+0x1440fffb, 0x0, 0xc004d78, 0x2021, 
+0xc004d78, 0x24040001, 0xc004d78, 0x2021, 
+0xc004d78, 0x24040001, 0x24100010, 0x32020001, 
+0x10400002, 0x2021, 0x24040001, 0xc004d78, 
+0x108042, 0x1600fffa, 0x32020001, 0x24100010, 
+0x32020018, 0x10400002, 0x2021, 0x24040001, 
+0xc004d78, 0x108042, 0x1600fffa, 0x32020018, 
+0xc004d78, 0x24040001, 0xc004d78, 0x2021, 
+0x34108000, 0x96220000, 0x501024, 0x10400002, 
+0x2021, 0x24040001, 0xc004d78, 0x108042, 
+0x1600fff8, 0x0, 0xc004db9, 0x0, 
+0x8f830054, 0x10000193, 0x2402000a, 0x8f830054, 
+0x3c020001, 0x8c426f3c, 0x2463ff9c, 0x431023, 
+0x2c420064, 0x1440019b, 0x2402000b, 0x10000197, 
+0x0, 0x27b10010, 0xa7a00010, 0x8021, 
+0xc004d78, 0x24040001, 0x26100001, 0x2e020020, 
+0x1440fffb, 0x0, 0xc004d78, 0x2021, 
+0xc004d78, 0x24040001, 0xc004d78, 0x24040001, 
+0xc004d78, 0x2021, 0x24100010, 0x32020001, 
+0x10400002, 0x2021, 0x24040001, 0xc004d78, 
+0x108042, 0x1600fffa, 0x32020001, 0x24100010, 
+0x32020017, 0x10400002, 0x2021, 0x24040001, 
+0xc004d78, 0x108042, 0x1600fffa, 0x32020017, 
+0xc004db9, 0x34108000, 0xc004db9, 0x0, 
+0xc004d58, 0x0, 0x50400005, 0x108042, 
+0x96220000, 0x501025, 0xa6220000, 0x108042, 
+0x1600fff7, 0x0, 0xc004db9, 0x8021, 
+0x97a20010, 0x27b10010, 0x34420700, 0xa7a20010, 
+0xc004d78, 0x24040001, 0x26100001, 0x2e020020, 
+0x1440fffb, 0x0, 0xc004d78, 0x2021, 
+0xc004d78, 0x24040001, 0xc004d78, 0x2021, 
+0xc004d78, 0x24040001, 0x24100010, 0x32020001, 
+0x10400002, 0x2021, 0x24040001, 0xc004d78, 
+0x108042, 0x1600fffa, 0x32020001, 0x24100010, 
+0x32020017, 0x10400002, 0x2021, 0x24040001, 
+0xc004d78, 0x108042, 0x1600fffa, 0x32020017, 
+0xc004d78, 0x24040001, 0xc004d78, 0x2021, 
+0x34108000, 0x96220000, 0x501024, 0x10400002, 
+0x2021, 0x24040001, 0xc004d78, 0x108042, 
+0x1600fff8, 0x0, 0xc004db9, 0x0, 
+0x8f830054, 0x1000011f, 0x2402000c, 0x8f830054, 
+0x3c020001, 0x8c426f3c, 0x2463ff9c, 0x431023, 
+0x2c420064, 0x14400127, 0x24020012, 0x10000123, 
+0x0, 0x27b10010, 0xa7a00010, 0x8021, 
+0xc004d78, 0x24040001, 0x26100001, 0x2e020020, 
+0x1440fffb, 0x0, 0xc004d78, 0x2021, 
+0xc004d78, 0x24040001, 0xc004d78, 0x24040001, 
+0xc004d78, 0x2021, 0x24100010, 0x32020001, 
+0x10400002, 0x2021, 0x24040001, 0xc004d78, 
+0x108042, 0x1600fffa, 0x32020001, 0x24100010, 
+0x32020014, 0x10400002, 0x2021, 0x24040001, 
+0xc004d78, 0x108042, 0x1600fffa, 0x32020014, 
+0xc004db9, 0x34108000, 0xc004db9, 0x0, 
+0xc004d58, 0x0, 0x50400005, 0x108042, 
+0x96220000, 0x501025, 0xa6220000, 0x108042, 
+0x1600fff7, 0x0, 0xc004db9, 0x8021, 
+0x97a20010, 0x27b10010, 0x34420010, 0xa7a20010, 
+0xc004d78, 0x24040001, 0x26100001, 0x2e020020, 
+0x1440fffb, 0x0, 0xc004d78, 0x2021, 
+0xc004d78, 0x24040001, 0xc004d78, 0x2021, 
+0xc004d78, 0x24040001, 0x24100010, 0x32020001, 
+0x10400002, 0x2021, 0x24040001, 0xc004d78, 
+0x108042, 0x1600fffa, 0x32020001, 0x24100010, 
+0x32020014, 0x10400002, 0x2021, 0x24040001, 
+0xc004d78, 0x108042, 0x1600fffa, 0x32020014, 
+0xc004d78, 0x24040001, 0xc004d78, 0x2021, 
+0x34108000, 0x96220000, 0x501024, 0x10400002, 
+0x2021, 0x24040001, 0xc004d78, 0x108042, 
+0x1600fff8, 0x0, 0xc004db9, 0x0, 
+0x8f830054, 0x100000ab, 0x24020013, 0x8f830054, 
+0x3c020001, 0x8c426f3c, 0x2463ff9c, 0x431023, 
+0x2c420064, 0x144000b3, 0x2402000d, 0x100000af, 
+0x0, 0x27b10010, 0xa7a00010, 0x8021, 
+0xc004d78, 0x24040001, 0x26100001, 0x2e020020, 
+0x1440fffb, 0x0, 0xc004d78, 0x2021, 
+0xc004d78, 0x24040001, 0xc004d78, 0x24040001, 
+0xc004d78, 0x2021, 0x24100010, 0x32020001, 
+0x10400002, 0x2021, 0x24040001, 0xc004d78, 
+0x108042, 0x1600fffa, 0x32020001, 0x24100010, 
+0x32020018, 0x10400002, 0x2021, 0x24040001, 
+0xc004d78, 0x108042, 0x1600fffa, 0x32020018, 
+0xc004db9, 0x34108000, 0xc004db9, 0x0, 
+0xc004d58, 0x0, 0x50400005, 0x108042, 
+0x96220000, 0x501025, 0xa6220000, 0x108042, 
+0x1600fff7, 0x0, 0xc004db9, 0x8021, 
+0x97a20010, 0x27b10010, 0x3042fffe, 0xa7a20010, 
+0xc004d78, 0x24040001, 0x26100001, 0x2e020020, 
+0x1440fffb, 0x0, 0xc004d78, 0x2021, 
+0xc004d78, 0x24040001, 0xc004d78, 0x2021, 
+0xc004d78, 0x24040001, 0x24100010, 0x32020001, 
+0x10400002, 0x2021, 0x24040001, 0xc004d78, 
+0x108042, 0x1600fffa, 0x32020001, 0x24100010, 
+0x32020018, 0x10400002, 0x2021, 0x24040001, 
+0xc004d78, 0x108042, 0x1600fffa, 0x32020018, 
+0xc004d78, 0x24040001, 0xc004d78, 0x2021, 
+0x34108000, 0x96220000, 0x501024, 0x10400002, 
+0x2021, 0x24040001, 0xc004d78, 0x108042, 
+0x1600fff8, 0x0, 0xc004db9, 0x0, 
+0x8f830054, 0x10000037, 0x2402000e, 0x24020840, 
+0xa7a20010, 0x27b10010, 0x8021, 0xc004d78, 
+0x24040001, 0x26100001, 0x2e020020, 0x1440fffb, 
+0x0, 0xc004d78, 0x2021, 0xc004d78, 
+0x24040001, 0xc004d78, 0x2021, 0xc004d78, 
+0x24040001, 0x24100010, 0x32020001, 0x10400002, 
+0x2021, 0x24040001, 0xc004d78, 0x108042, 
+0x1600fffa, 0x32020001, 0x24100010, 0x32020013, 
+0x10400002, 0x2021, 0x24040001, 0xc004d78, 
+0x108042, 0x1600fffa, 0x32020013, 0xc004d78, 
+0x24040001, 0xc004d78, 0x2021, 0x34108000, 
+0x96220000, 0x501024, 0x10400002, 0x2021, 
+0x24040001, 0xc004d78, 0x108042, 0x1600fff8, 
+0x0, 0xc004db9, 0x0, 0x8f830054, 
+0x24020010, 0x3c010001, 0xac226dd0, 0x3c010001, 
+0x1000000c, 0xac236f3c, 0x8f830054, 0x3c020001, 
+0x8c426f3c, 0x2463ff9c, 0x431023, 0x2c420064, 
+0x14400004, 0x0, 0x24020011, 0x3c010001, 
+0xac226dd0, 0x8fbf0020, 0x8fb1001c, 0x8fb00018, 
+0x3e00008, 0x27bd0028, 0x3c030001, 0x8c636d98, 
+0x27bdffc8, 0x24020002, 0xafbf0034, 0xafb20030, 
+0xafb1002c, 0x14620004, 0xafb00028, 0x3c120002, 
+0x10000003, 0x8e528ff8, 0x3c120002, 0x8e528ffc, 
+0x3c030001, 0x8c636dd4, 0x3c020001, 0x8c426e1c, 
+0x50620004, 0x2463ffff, 0x3c010001, 0xac236e1c, 
+0x2463ffff, 0x2c620006, 0x10400377, 0x31080, 
+0x3c010001, 0x220821, 0x8c226bd8, 0x400008, 
+0x0, 0x2021, 0x2821, 0xc004ddb, 
+0x34068000, 0x24040010, 0x24050002, 0x24060002, 
+0x24020002, 0xc004ddb, 0xa7a20018, 0x24020002, 
+0x3c010001, 0x10000364, 0xac226dd4, 0x27b10018, 
+0xa7a00018, 0x8021, 0xc004d78, 0x24040001, 
+0x26100001, 0x2e020020, 0x1440fffb, 0x0, 
+0xc004d78, 0x2021, 0xc004d78, 0x24040001, 
+0xc004d78, 0x24040001, 0xc004d78, 0x2021, 
+0x24100010, 0x32020001, 0x10400002, 0x2021, 
+0x24040001, 0xc004d78, 0x108042, 0x1600fffa, 
+0x32020001, 0x24100010, 0xc004d78, 0x2021, 
+0x108042, 0x1600fffc, 0x0, 0xc004db9, 
+0x34108000, 0xc004db9, 0x0, 0xc004d58, 
+0x0, 0x50400005, 0x108042, 0x96220000, 
+0x501025, 0xa6220000, 0x108042, 0x1600fff7, 
+0x0, 0xc004db9, 0x0, 0x97a20018, 
+0x30428000, 0x14400004, 0x24020003, 0x3c010001, 
+0xac226dd4, 0x24020003, 0x3c010001, 0x1000032a, 
+0xac226dd4, 0x24040010, 0x24050002, 0x24060002, 
+0x24020002, 0xc004ddb, 0xa7a20018, 0x3c030001, 
+0x8c636e20, 0x24020001, 0x146201e1, 0x8021, 
+0x27b10018, 0xa7a00018, 0xc004d78, 0x24040001, 
+0x26100001, 0x2e020020, 0x1440fffb, 0x0, 
+0xc004d78, 0x2021, 0xc004d78, 0x24040001, 
+0xc004d78, 0x24040001, 0xc004d78, 0x2021, 
+0x24100010, 0x32020001, 0x10400002, 0x2021, 
+0x24040001, 0xc004d78, 0x108042, 0x1600fffa, 
+0x32020001, 0x24100010, 0x32020018, 0x10400002, 
+0x2021, 0x24040001, 0xc004d78, 0x108042, 
+0x1600fffa, 0x32020018, 0xc004db9, 0x34108000, 
+0xc004db9, 0x0, 0xc004d58, 0x0, 
+0x50400005, 0x108042, 0x96220000, 0x501025, 
+0xa6220000, 0x108042, 0x1600fff7, 0x0, 
+0xc004db9, 0x8021, 0x27b10018, 0xa7a00018, 
+0xc004d78, 0x24040001, 0x26100001, 0x2e020020, 
+0x1440fffb, 0x0, 0xc004d78, 0x2021, 
+0xc004d78, 0x24040001, 0xc004d78, 0x24040001, 
+0xc004d78, 0x2021, 0x24100010, 0x32020001, 
+0x10400002, 0x2021, 0x24040001, 0xc004d78, 
+0x108042, 0x1600fffa, 0x32020001, 0x24100010, 
+0x32020018, 0x10400002, 0x2021, 0x24040001, 
+0xc004d78, 0x108042, 0x1600fffa, 0x32020018, 
+0xc004db9, 0x34108000, 0xc004db9, 0x0, 
+0xc004d58, 0x0, 0x50400005, 0x108042, 
+0x96220000, 0x501025, 0xa6220000, 0x108042, 
+0x1600fff7, 0x0, 0xc004db9, 0x8021, 
+0x24040018, 0x2821, 0xc004ddb, 0x24060404, 
+0xa7a0001a, 0xc004d78, 0x24040001, 0x26100001, 
+0x2e020020, 0x1440fffb, 0x0, 0xc004d78, 
+0x2021, 0xc004d78, 0x24040001, 0xc004d78, 
+0x24040001, 0xc004d78, 0x2021, 0x24100010, 
+0x32020001, 0x10400002, 0x2021, 0x24040001, 
+0xc004d78, 0x108042, 0x1600fffa, 0x32020001, 
+0x24100010, 0x32020018, 0x10400002, 0x2021, 
+0x24040001, 0xc004d78, 0x108042, 0x1600fffa, 
+0x32020018, 0xc004db9, 0x34108000, 0xc004db9, 
+0x0, 0xc004d58, 0x0, 0x50400005, 
+0x108042, 0x97a2001a, 0x501025, 0xa7a2001a, 
+0x108042, 0x1600fff7, 0x0, 0xc004db9, 
+0x8021, 0xa7a0001a, 0xc004d78, 0x24040001, 
+0x26100001, 0x2e020020, 0x1440fffb, 0x0, 
+0xc004d78, 0x2021, 0xc004d78, 0x24040001, 
+0xc004d78, 0x24040001, 0xc004d78, 0x2021, 
+0x24100010, 0x32020001, 0x10400002, 0x2021, 
+0x24040001, 0xc004d78, 0x108042, 0x1600fffa, 
+0x32020001, 0x24100010, 0x32020018, 0x10400002, 
+0x2021, 0x24040001, 0xc004d78, 0x108042, 
+0x1600fffa, 0x32020018, 0xc004db9, 0x34108000, 
+0xc004db9, 0x0, 0xc004d58, 0x0, 
+0x50400005, 0x108042, 0x97a2001a, 0x501025, 
+0xa7a2001a, 0x108042, 0x1600fff7, 0x0, 
+0xc004db9, 0x8021, 0xa7a0001c, 0xc004d78, 
+0x24040001, 0x26100001, 0x2e020020, 0x1440fffb, 
+0x0, 0xc004d78, 0x2021, 0xc004d78, 
+0x24040001, 0xc004d78, 0x24040001, 0xc004d78, 
+0x2021, 0x24100010, 0xc004d78, 0x2021, 
+0x108042, 0x1600fffc, 0x0, 0x24100010, 
+0x3202001e, 0x10400002, 0x2021, 0x24040001, 
+0xc004d78, 0x108042, 0x1600fffa, 0x3202001e, 
+0xc004db9, 0x34108000, 0xc004db9, 0x0, 
+0xc004d58, 0x0, 0x50400005, 0x108042, 
+0x97a2001c, 0x501025, 0xa7a2001c, 0x108042, 
+0x1600fff7, 0x0, 0xc004db9, 0x8021, 
+0xa7a0001c, 0xc004d78, 0x24040001, 0x26100001, 
+0x2e020020, 0x1440fffb, 0x0, 0xc004d78, 
+0x2021, 0xc004d78, 0x24040001, 0xc004d78, 
+0x24040001, 0xc004d78, 0x2021, 0x24100010, 
+0xc004d78, 0x2021, 0x108042, 0x1600fffc, 
+0x0, 0x24100010, 0x3202001e, 0x10400002, 
+0x2021, 0x24040001, 0xc004d78, 0x108042, 
+0x1600fffa, 0x3202001e, 0xc004db9, 0x34108000, 
+0xc004db9, 0x0, 0xc004d58, 0x0, 
+0x50400005, 0x108042, 0x97a2001c, 0x501025, 
+0xa7a2001c, 0x108042, 0x1600fff7, 0x0, 
+0xc004db9, 0x8021, 0x24020002, 0xa7a2001e, 
+0xc004d78, 0x24040001, 0x26100001, 0x2e020020, 
+0x1440fffb, 0x0, 0xc004d78, 0x2021, 
+0xc004d78, 0x24040001, 0xc004d78, 0x2021, 
+0xc004d78, 0x24040001, 0x24100010, 0xc004d78, 
+0x2021, 0x108042, 0x1600fffc, 0x0, 
+0x24100010, 0x3202001e, 0x10400002, 0x2021, 
+0x24040001, 0xc004d78, 0x108042, 0x1600fffa, 
+0x3202001e, 0xc004d78, 0x24040001, 0xc004d78, 
+0x2021, 0x34108000, 0x97a2001e, 0x501024, 
+0x10400002, 0x2021, 0x24040001, 0xc004d78, 
+0x108042, 0x1600fff8, 0x0, 0xc004db9, 
+0x8021, 0xa7a00020, 0xc004d78, 0x24040001, 
+0x26100001, 0x2e020020, 0x1440fffb, 0x0, 
+0xc004d78, 0x2021, 0xc004d78, 0x24040001, 
+0xc004d78, 0x24040001, 0xc004d78, 0x2021, 
+0x24100010, 0xc004d78, 0x2021, 0x108042, 
+0x1600fffc, 0x0, 0x24100010, 0x3202001e, 
+0x10400002, 0x2021, 0x24040001, 0xc004d78, 
+0x108042, 0x1600fffa, 0x3202001e, 0xc004db9, 
+0x34108000, 0xc004db9, 0x0, 0xc004d58, 
+0x0, 0x50400005, 0x108042, 0x97a20020, 
+0x501025, 0xa7a20020, 0x108042, 0x1600fff7, 
+0x0, 0xc004db9, 0x8021, 0xa7a00020, 
+0xc004d78, 0x24040001, 0x26100001, 0x2e020020, 
+0x1440fffb, 0x0, 0xc004d78, 0x2021, 
+0xc004d78, 0x24040001, 0xc004d78, 0x24040001, 
+0xc004d78, 0x2021, 0x24100010, 0xc004d78, 
+0x2021, 0x108042, 0x1600fffc, 0x0, 
+0x24100010, 0x3202001e, 0x10400002, 0x2021, 
+0x24040001, 0xc004d78, 0x108042, 0x1600fffa, 
+0x3202001e, 0xc004db9, 0x34108000, 0xc004db9, 
+0x0, 0xc004d58, 0x0, 0x50400005, 
+0x108042, 0x97a20020, 0x501025, 0xa7a20020, 
+0x108042, 0x1600fff7, 0x0, 0xc004db9, 
+0x8021, 0xa7a00022, 0xc004d78, 0x24040001, 
+0x26100001, 0x2e020020, 0x1440fffb, 0x0, 
+0xc004d78, 0x2021, 0xc004d78, 0x24040001, 
+0xc004d78, 0x2021, 0xc004d78, 0x24040001, 
+0x24100010, 0xc004d78, 0x2021, 0x108042, 
+0x1600fffc, 0x0, 0x24100010, 0xc004d78, 
+0x2021, 0x108042, 0x1600fffc, 0x0, 
+0xc004d78, 0x24040001, 0xc004d78, 0x2021, 
+0x34108000, 0x97a20022, 0x501024, 0x10400002, 
+0x2021, 0x24040001, 0xc004d78, 0x108042, 
+0x1600fff8, 0x0, 0xc004db9, 0x0, 
+0x24040018, 0x24050002, 0xc004ddb, 0x24060004, 
+0x3c100001, 0x8e106e24, 0x24020001, 0x1602011d, 
+0x0, 0x3c020001, 0x94426f26, 0x3c010001, 
+0xac206e24, 0x24429fbc, 0x2c420004, 0x1040000c, 
+0x24040009, 0x24050001, 0xc004ddb, 0x24060400, 
+0x24040018, 0x24050001, 0xc004ddb, 0x24060020, 
+0x24040018, 0x24050001, 0xc004ddb, 0x24062000, 
+0x3c024000, 0x2421024, 0x10400123, 0x3c022000, 
+0x2421024, 0x10400004, 0x0, 0x3c010001, 
+0x10000003, 0xac306f1c, 0x3c010001, 0xac206f1c, 
+0x3c030001, 0x8c636f34, 0x24020005, 0x146200f9, 
+0x0, 0x3c020001, 0x8c426f1c, 0x10400067, 
+0x3c020004, 0x2421024, 0x10400011, 0xa7a00018, 
+0x3c020008, 0x2421024, 0x10400002, 0x24020200, 
+0xa7a20018, 0x3c020010, 0x2421024, 0x10400004, 
+0x0, 0x97a20018, 0x34420100, 0xa7a20018, 
+0x97a60018, 0x24040009, 0x10000004, 0x2821, 
+0x24040009, 0x2821, 0x3021, 0xc004ddb, 
+0x0, 0x24020001, 0xa7a2001a, 0x3c020008, 
+0x2421024, 0x1040000c, 0x3c020002, 0x2421024, 
+0x10400002, 0x24020101, 0xa7a2001a, 0x3c020001, 
+0x2421024, 0x10400005, 0x3c020010, 0x97a2001a, 
+0x34420040, 0xa7a2001a, 0x3c020010, 0x2421024, 
+0x1040000e, 0x3c020002, 0x2421024, 0x10400005, 
+0x3c020001, 0x97a2001a, 0x34420080, 0xa7a2001a, 
+0x3c020001, 0x2421024, 0x10400005, 0x3c0300a0, 
+0x97a2001a, 0x34420020, 0xa7a2001a, 0x3c0300a0, 
+0x2431024, 0x54430004, 0x3c020020, 0x97a2001a, 
+0x1000000c, 0x34420400, 0x2421024, 0x50400004, 
+0x3c020080, 0x97a2001a, 0x10000006, 0x34420800, 
+0x2421024, 0x10400004, 0x0, 0x97a2001a, 
+0x34420c00, 0xa7a2001a, 0x97a6001a, 0x24040004, 
+0xc004ddb, 0x2821, 0x3c020004, 0x2421024, 
+0x10400004, 0xa7a0001c, 0x32425000, 0x14400004, 
+0x0, 0x32424000, 0x10400005, 0x2021, 
+0xc004cf9, 0x2402021, 0x10000096, 0x0, 
+0x97a6001c, 0x2821, 0x34c61200, 0xc004ddb, 
+0xa7a6001c, 0x1000008f, 0x0, 0x2421024, 
+0x10400004, 0xa7a00018, 0x32425000, 0x14400004, 
+0x0, 0x32424000, 0x10400005, 0x3c020010, 
+0xc004cf9, 0x2402021, 0x10000019, 0xa7a0001a, 
+0x2421024, 0x10400004, 0x0, 0x97a20018, 
+0x10000004, 0xa7a20018, 0x97a20018, 0x34420100, 
+0xa7a20018, 0x3c020001, 0x2421024, 0x10400004, 
+0x0, 0x97a20018, 0x10000004, 0xa7a20018, 
+0x97a20018, 0x34422000, 0xa7a20018, 0x97a60018, 
+0x2021, 0xc004ddb, 0x2821, 0xa7a0001a, 
+0x8021, 0xc004d78, 0x24040001, 0x26100001, 
+0x2e020020, 0x1440fffb, 0x0, 0xc004d78, 
+0x2021, 0xc004d78, 0x24040001, 0xc004d78, 
+0x24040001, 0xc004d78, 0x2021, 0x24100010, 
+0x32020001, 0x10400002, 0x2021, 0x24040001, 
+0xc004d78, 0x108042, 0x1600fffa, 0x32020001, 
+0x24100010, 0xc004d78, 0x2021, 0x108042, 
+0x1600fffc, 0x0, 0xc004db9, 0x34108000, 
+0xc004db9, 0x0, 0xc004d58, 0x0, 
+0x50400005, 0x108042, 0x97a2001a, 0x501025, 
+0xa7a2001a, 0x108042, 0x1600fff7, 0x0, 
+0xc004db9, 0x8021, 0xa7a0001a, 0xc004d78, 
+0x24040001, 0x26100001, 0x2e020020, 0x1440fffb, 
+0x0, 0xc004d78, 0x2021, 0xc004d78, 
+0x24040001, 0xc004d78, 0x24040001, 0xc004d78, 
+0x2021, 0x24100010, 0x32020001, 0x10400002, 
+0x2021, 0x24040001, 0xc004d78, 0x108042, 
+0x1600fffa, 0x32020001, 0x24100010, 0xc004d78, 
+0x2021, 0x108042, 0x1600fffc, 0x0, 
+0xc004db9, 0x34108000, 0xc004db9, 0x0, 
+0xc004d58, 0x0, 0x50400005, 0x108042, 
+0x97a2001a, 0x501025, 0xa7a2001a, 0x108042, 
+0x1600fff7, 0x0, 0xc004db9, 0x0, 
+0x3c040001, 0x24846bcc, 0x97a60018, 0x97a7001a, 
+0x3c020001, 0x8c426d98, 0x3c030001, 0x8c636f1c, 
+0x3c05000d, 0x34a50205, 0xafa20010, 0xc002b3b, 
+0xafa30014, 0x8f830054, 0x24020004, 0x3c010001, 
+0xac226dd4, 0x3c010001, 0x10000017, 0xac236f38, 
+0x8f830054, 0x3c020001, 0x8c426f38, 0x2463ff9c, 
+0x431023, 0x2c420064, 0x1440000f, 0x0, 
+0x8f820220, 0x24030005, 0x3c010001, 0xac236dd4, 
+0x3c03f700, 0x431025, 0x10000007, 0xaf820220, 
+0x24020006, 0x3c010001, 0xac226dd4, 0x24020011, 
+0x3c010001, 0xac226dd0, 0x8fbf0034, 0x8fb20030, 
+0x8fb1002c, 0x8fb00028, 0x3e00008, 0x27bd0038, 
+0x27bdffd8, 0xafb00018, 0x808021, 0xafb1001c, 
+0x8821, 0x32024000, 0x10400013, 0xafbf0020, 
+0x3c020010, 0x2021024, 0x2c420001, 0x21023, 
+0x30434100, 0x3c020001, 0x2021024, 0x14400006, 
+0x34714000, 0x3c020002, 0x2021024, 0x14400002, 
+0x34716000, 0x34714040, 0x2021, 0x2821, 
+0x10000036, 0x2203021, 0x32021000, 0x10400035, 
+0x2021, 0x2821, 0xc004ddb, 0x24060040, 
+0x24040018, 0x2821, 0xc004ddb, 0x24060c00, 
+0x24040017, 0x2821, 0xc004ddb, 0x24060400, 
+0x24040016, 0x2821, 0xc004ddb, 0x24060006, 
+0x24040017, 0x2821, 0xc004ddb, 0x24062500, 
+0x24040016, 0x2821, 0xc004ddb, 0x24060006, 
+0x24040017, 0x2821, 0xc004ddb, 0x24064600, 
+0x24040016, 0x2821, 0xc004ddb, 0x24060006, 
+0x24040017, 0x2821, 0xc004ddb, 0x24066700, 
+0x24040016, 0x2821, 0xc004ddb, 0x24060006, 
+0x2404001f, 0x2821, 0xc004ddb, 0x24060010, 
+0x24040009, 0x2821, 0xc004ddb, 0x24061500, 
+0x24040009, 0x2821, 0x24061d00, 0xc004ddb, 
+0x0, 0x3c040001, 0x24846bf0, 0x3c05000e, 
+0x34a50100, 0x2003021, 0x2203821, 0xafa00010, 
+0xc002b3b, 0xafa00014, 0x8fbf0020, 0x8fb1001c, 
+0x8fb00018, 0x3e00008, 0x27bd0028, 0x8f850044, 
+0x8f820044, 0x3c030001, 0x431025, 0x3c030008, 
+0xaf820044, 0x8f840054, 0x8f820054, 0xa32824, 
+0x10000002, 0x24840001, 0x8f820054, 0x821023, 
+0x2c420002, 0x1440fffc, 0x0, 0x8f820044, 
+0x3c03fffe, 0x3463ffff, 0x431024, 0xaf820044, 
+0x8f830054, 0x8f820054, 0x10000002, 0x24630001, 
+0x8f820054, 0x621023, 0x2c420002, 0x1440fffc, 
+0x0, 0x3e00008, 0xa01021, 0x8f830044, 
+0x3c02fff0, 0x3442ffff, 0x42480, 0x621824, 
+0x3c020002, 0x822025, 0x641825, 0xaf830044, 
+0x8f820044, 0x3c03fffe, 0x3463ffff, 0x431024, 
+0xaf820044, 0x8f830054, 0x8f820054, 0x10000002, 
+0x24630001, 0x8f820054, 0x621023, 0x2c420002, 
+0x1440fffc, 0x0, 0x8f820044, 0x3c030001, 
+0x431025, 0xaf820044, 0x8f830054, 0x8f820054, 
+0x10000002, 0x24630001, 0x8f820054, 0x621023, 
+0x2c420002, 0x1440fffc, 0x0, 0x3e00008, 
+0x0, 0x8f820044, 0x2403ff7f, 0x431024, 
+0xaf820044, 0x8f830054, 0x8f820054, 0x10000002, 
+0x24630001, 0x8f820054, 0x621023, 0x2c420002, 
+0x1440fffc, 0x0, 0x8f820044, 0x34420080, 
+0xaf820044, 0x8f830054, 0x8f820054, 0x10000002, 
+0x24630001, 0x8f820054, 0x621023, 0x2c420002, 
+0x1440fffc, 0x0, 0x3e00008, 0x0, 
+0x8f820044, 0x3c03fff0, 0x3463ffff, 0x431024, 
+0xaf820044, 0x8f820044, 0x3c030001, 0x431025, 
+0xaf820044, 0x8f830054, 0x8f820054, 0x10000002, 
+0x24630001, 0x8f820054, 0x621023, 0x2c420002, 
+0x1440fffc, 0x0, 0x8f820044, 0x3c03fffe, 
+0x3463ffff, 0x431024, 0xaf820044, 0x8f830054, 
+0x8f820054, 0x10000002, 0x24630001, 0x8f820054, 
+0x621023, 0x2c420002, 0x1440fffc, 0x0, 
+0x3e00008, 0x0, 0x27bdffc8, 0xafb30024, 
+0x809821, 0xafbe002c, 0xa0f021, 0xafb20020, 
+0xc09021, 0x33c2ffff, 0xafbf0030, 0xafb50028, 
+0xafb1001c, 0xafb00018, 0x14400034, 0xa7b20010, 
+0x3271ffff, 0x27b20010, 0x8021, 0xc004d78, 
+0x24040001, 0x26100001, 0x2e020020, 0x1440fffb, 
+0x0, 0xc004d78, 0x2021, 0xc004d78, 
+0x24040001, 0xc004d78, 0x2021, 0xc004d78, 
+0x24040001, 0x24100010, 0x32020001, 0x10400002, 
+0x2021, 0x24040001, 0xc004d78, 0x108042, 
+0x1600fffa, 0x32020001, 0x24100010, 0x2301024, 
+0x10400002, 0x2021, 0x24040001, 0xc004d78, 
+0x108042, 0x1600fffa, 0x2301024, 0xc004d78, 
+0x24040001, 0xc004d78, 0x2021, 0x34108000, 
+0x96420000, 0x501024, 0x10400002, 0x2021, 
+0x24040001, 0xc004d78, 0x108042, 0x12000075, 
+0x0, 0x1000fff6, 0x0, 0x3275ffff, 
+0x27b10010, 0xa7a00010, 0x8021, 0xc004d78, 
+0x24040001, 0x26100001, 0x2e020020, 0x1440fffb, 
+0x0, 0xc004d78, 0x2021, 0xc004d78, 
+0x24040001, 0xc004d78, 0x24040001, 0xc004d78, 
+0x2021, 0x24100010, 0x32020001, 0x10400002, 
+0x2021, 0x24040001, 0xc004d78, 0x108042, 
+0x1600fffa, 0x32020001, 0x24100010, 0x2b01024, 
+0x10400002, 0x2021, 0x24040001, 0xc004d78, 
+0x108042, 0x1600fffa, 0x2b01024, 0xc004db9, 
+0x34108000, 0xc004db9, 0x0, 0xc004d58, 
+0x0, 0x50400005, 0x108042, 0x96220000, 
+0x501025, 0xa6220000, 0x108042, 0x1600fff7, 
+0x0, 0xc004db9, 0x0, 0x33c5ffff, 
+0x24020001, 0x54a20004, 0x24020002, 0x97a20010, 
+0x10000006, 0x521025, 0x14a20006, 0x3271ffff, 
+0x97a20010, 0x121827, 0x431024, 0xa7a20010, 
+0x3271ffff, 0x27b20010, 0x8021, 0xc004d78, 
+0x24040001, 0x26100001, 0x2e020020, 0x1440fffb, 
+0x0, 0xc004d78, 0x2021, 0xc004d78, 
+0x24040001, 0xc004d78, 0x2021, 0xc004d78, 
+0x24040001, 0x24100010, 0x32020001, 0x10400002, 
+0x2021, 0x24040001, 0xc004d78, 0x108042, 
+0x1600fffa, 0x32020001, 0x24100010, 0x2301024, 
+0x10400002, 0x2021, 0x24040001, 0xc004d78, 
+0x108042, 0x1600fffa, 0x2301024, 0xc004d78, 
+0x24040001, 0xc004d78, 0x2021, 0x34108000, 
+0x96420000, 0x501024, 0x10400002, 0x2021, 
+0x24040001, 0xc004d78, 0x108042, 0x1600fff8, 
+0x0, 0xc004db9, 0x0, 0x8fbf0030, 
+0x8fbe002c, 0x8fb50028, 0x8fb30024, 0x8fb20020, 
+0x8fb1001c, 0x8fb00018, 0x3e00008, 0x27bd0038, 
+0x0, 0x0, 0x0, 0x27bdffe8, 
+0xafbf0010, 0x8ee304b8, 0x24020008, 0x146201e0, 
+0x0, 0x3c020001, 0x8c426f1c, 0x14400005, 
+0x0, 0xc003daf, 0x8f840224, 0x100001d8, 
+0x0, 0x8f820220, 0x3c030008, 0x431024, 
+0x10400026, 0x24020001, 0x8f840224, 0x8f820220, 
+0x3c030400, 0x431024, 0x10400006, 0x0, 
+0x3c010002, 0xac208fa0, 0x3c010002, 0x1000000b, 
+0xac208fc0, 0x3c030002, 0x24638fa0, 0x8c620000, 
+0x24420001, 0xac620000, 0x2c420002, 0x14400003, 
+0x24020001, 0x3c010002, 0xac228fc0, 0x3c020002, 
+0x8c428fc0, 0x10400006, 0x30820040, 0x10400004, 
+0x24020001, 0x3c010002, 0x10000003, 0xac228fc4, 
+0x3c010002, 0xac208fc4, 0x3c010002, 0xac248f9c, 
+0x3c010002, 0x1000000b, 0xac208fd0, 0x3c010002, 
+0xac228fd0, 0x3c010002, 0xac208fc0, 0x3c010002, 
+0xac208fa0, 0x3c010002, 0xac208fc4, 0x3c010002, 
+0xac208f9c, 0x3c030002, 0x8c638f90, 0x3c020002, 
+0x8c428f94, 0x50620004, 0x2463ffff, 0x3c010002, 
+0xac238f94, 0x2463ffff, 0x2c62000e, 0x10400194, 
+0x31080, 0x3c010001, 0x220821, 0x8c226c00, 
+0x400008, 0x0, 0x24020002, 0x3c010002, 
+0xac208fc0, 0x3c010002, 0xac208fa0, 0x3c010002, 
+0xac208f9c, 0x3c010002, 0xac208fc4, 0x3c010002, 
+0xac208fb8, 0x3c010002, 0xac208fb0, 0xaf800224, 
+0x3c010002, 0xac228f90, 0x3c020002, 0x8c428fd0, 
+0x1440004f, 0x3c02fdff, 0x3442ffff, 0xc003daf, 
+0x282a024, 0xaf800204, 0x8f820200, 0x2403fffd, 
+0x431024, 0xaf820200, 0x3c010002, 0xac208fe0, 
+0x8f830054, 0x3c020002, 0x8c428fb8, 0x24040001, 
+0x3c010002, 0xac248fcc, 0x24420001, 0x3c010002, 
+0xac228fb8, 0x2c420004, 0x3c010002, 0xac238fb4, 
+0x14400006, 0x24020003, 0x3c010001, 0xac246d9c, 
+0x3c010002, 0x1000015e, 0xac208fb8, 0x3c010002, 
+0x1000015b, 0xac228f90, 0x8f830054, 0x3c020002, 
+0x8c428fb4, 0x2463d8f0, 0x431023, 0x2c422710, 
+0x14400003, 0x24020004, 0x3c010002, 0xac228f90, 
+0x3c020002, 0x8c428fd0, 0x14400021, 0x3c02fdff, 
+0x3442ffff, 0x1000014a, 0x282a024, 0x3c040001, 
+0x8c846f20, 0x3c010002, 0xc005084, 0xac208fa8, 
+0x3c020002, 0x8c428fdc, 0xaf820204, 0x3c020002, 
+0x8c428fd0, 0x14400012, 0x3c03fdff, 0x8f820204, 
+0x3463ffff, 0x30420030, 0x1440012f, 0x283a024, 
+0x3c030002, 0x8c638fdc, 0x24020005, 0x3c010002, 
+0xac228f90, 0x3c010002, 0x10000131, 0xac238fe0, 
+0x3c020002, 0x8c428fd0, 0x10400010, 0x3c02fdff, 
+0x3c020001, 0x8c426e3c, 0x24420001, 0x3c010001, 
+0xac226e3c, 0x2c420002, 0x14400125, 0x24020001, 
+0x3c010001, 0xac226e44, 0x3c010001, 0xac206e3c, 
+0x3c010001, 0x1000011e, 0xac226d9c, 0x3c030002, 
+0x8c638fc0, 0x3442ffff, 0x10600119, 0x282a024, 
+0x3c020002, 0x8c428f9c, 0x10400115, 0x0, 
+0x3c010002, 0xac228fc8, 0x24020003, 0x3c010002, 
+0xac228fa0, 0x100000b8, 0x24020006, 0x3c010002, 
+0xac208fa8, 0x8f820204, 0x34420040, 0xaf820204, 
+0x3c020002, 0x8c428fe0, 0x24030007, 0x3c010002, 
+0xac238f90, 0x34420040, 0x3c010002, 0xac228fe0, 
+0x3c020002, 0x8c428fc0, 0x10400005, 0x0, 
+0x3c020002, 0x8c428f9c, 0x104000f0, 0x24020002, 
+0x3c050002, 0x24a58fa0, 0x8ca20000, 0x2c424e21, 
+0x104000ea, 0x24020002, 0x3c020002, 0x8c428fc4, 
+0x104000ef, 0x2404ffbf, 0x3c020002, 0x8c428f9c, 
+0x3c030002, 0x8c638fc8, 0x441024, 0x641824, 
+0x10430004, 0x24020001, 0x3c010002, 0x100000e4, 
+0xac228f90, 0x24020003, 0xaca20000, 0x24020008, 
+0x3c010002, 0xac228f90, 0x3c020002, 0x8c428fcc, 
+0x1040000c, 0x24020001, 0x3c040002, 0xc005091, 
+0x8c848f9c, 0x3c020002, 0x8c428fe8, 0x14400005, 
+0x24020001, 0x3c020002, 0x8c428fe4, 0x10400006, 
+0x24020001, 0x3c010001, 0xac226d9c, 0x3c010002, 
+0x100000cb, 0xac208fb8, 0x3c020002, 0x8c428fb0, 
+0x3c030002, 0x8c638f9c, 0x2c420001, 0x210c0, 
+0x30630008, 0x3c010002, 0xac228fb0, 0x3c010002, 
+0xac238fac, 0x8f830054, 0x24020009, 0x3c010002, 
+0xac228f90, 0x3c010002, 0x100000b9, 0xac238fb4, 
+0x8f830054, 0x3c020002, 0x8c428fb4, 0x2463d8f0, 
+0x431023, 0x2c422710, 0x1440009f, 0x0, 
+0x3c020002, 0x8c428fc0, 0x10400005, 0x0, 
+0x3c020002, 0x8c428f9c, 0x104000a0, 0x24020002, 
+0x3c030002, 0x24638fa0, 0x8c620000, 0x2c424e21, 
+0x1040009a, 0x24020002, 0x3c020002, 0x8c428fcc, 
+0x1040000e, 0x0, 0x3c020002, 0x8c428f9c, 
+0x3c010002, 0xac208fcc, 0x30420080, 0x1040002f, 
+0x2402000c, 0x8f820204, 0x30420080, 0x1440000c, 
+0x24020003, 0x10000029, 0x2402000c, 0x3c020002, 
+0x8c428f9c, 0x30420080, 0x14400005, 0x24020003, 
+0x8f820204, 0x30420080, 0x1040001f, 0x24020003, 
+0xac620000, 0x2402000a, 0x3c010002, 0xac228f90, 
+0x3c040002, 0x24848fd8, 0x8c820000, 0x3c030002, 
+0x8c638fb0, 0x431025, 0xaf820204, 0x8c830000, 
+0x3c040002, 0x8c848fb0, 0x2402000b, 0x3c010002, 
+0xac228f90, 0x641825, 0x3c010002, 0xac238fe0, 
+0x3c050002, 0x24a58fa0, 0x8ca20000, 0x2c424e21, 
+0x10400066, 0x24020002, 0x3c020002, 0x8c428fd0, 
+0x10400005, 0x0, 0x2402000c, 0x3c010002, 
+0x10000067, 0xac228f90, 0x3c020002, 0x8c428fc0, 
+0x10400063, 0x0, 0x3c040002, 0x8c848f9c, 
+0x10800055, 0x30820008, 0x3c030002, 0x8c638fac, 
+0x1062005b, 0x24020003, 0x3c010002, 0xac248fc8, 
+0xaca20000, 0x24020006, 0x3c010002, 0x10000054, 
+0xac228f90, 0x8f820200, 0x34420002, 0xaf820200, 
+0x8f830054, 0x2402000d, 0x3c010002, 0xac228f90, 
+0x3c010002, 0xac238fb4, 0x8f830054, 0x3c020002, 
+0x8c428fb4, 0x2463d8f0, 0x431023, 0x2c422710, 
+0x14400031, 0x0, 0x3c020002, 0x8c428fd0, 
+0x10400020, 0x2402000e, 0x3c030002, 0x8c638fe4, 
+0x3c010002, 0x14600015, 0xac228f90, 0xc003e6d, 
+0x0, 0x3c050001, 0x8ca56d98, 0xc00529b, 
+0x2021, 0x3c030001, 0x8c636d98, 0x24020004, 
+0x14620005, 0x2403fffb, 0x3c020001, 0x8c426d94, 
+0x10000003, 0x2403fff7, 0x3c020001, 0x8c426d94, 
+0x431024, 0x3c010001, 0xac226d94, 0x8f830224, 
+0x3c020200, 0x3c010002, 0xac238fec, 0x10000020, 
+0x282a025, 0x3c020002, 0x8c428fc0, 0x10400005, 
+0x0, 0x3c020002, 0x8c428f9c, 0x1040000f, 
+0x24020002, 0x3c020002, 0x8c428fa0, 0x2c424e21, 
+0x1040000a, 0x24020002, 0x3c020002, 0x8c428fc0, 
+0x1040000f, 0x0, 0x3c020002, 0x8c428f9c, 
+0x1440000b, 0x0, 0x24020002, 0x3c010002, 
+0x10000007, 0xac228f90, 0x3c020002, 0x8c428fc0, 
+0x10400003, 0x0, 0xc003daf, 0x0, 
+0x8f820220, 0x3c03f700, 0x431025, 0xaf820220, 
+0x8fbf0010, 0x3e00008, 0x27bd0018, 0x3c030002, 
+0x24638fe8, 0x8c620000, 0x10400005, 0x34422000, 
+0x3c010002, 0xac228fdc, 0x10000003, 0xac600000, 
+0x3c010002, 0xac248fdc, 0x3e00008, 0x0, 
+0x27bdffe0, 0x30820030, 0xafbf0018, 0x3c010002, 
+0xac228fe4, 0x14400067, 0x3c02ffff, 0x34421f0e, 
+0x821024, 0x14400061, 0x24020030, 0x30822000, 
+0x1040005d, 0x30838000, 0x31a02, 0x30820001, 
+0x21200, 0x3c040001, 0x8c846f20, 0x621825, 
+0x331c2, 0x3c030001, 0x24636e48, 0x30828000, 
+0x21202, 0x30840001, 0x42200, 0x441025, 
+0x239c2, 0x61080, 0x431021, 0x471021, 
+0x90430000, 0x24020001, 0x10620025, 0x0, 
+0x10600007, 0x24020002, 0x10620013, 0x24020003, 
+0x1062002c, 0x3c05000f, 0x10000037, 0x0, 
+0x8f820200, 0x2403feff, 0x431024, 0xaf820200, 
+0x8f820220, 0x3c03fffe, 0x3463ffff, 0x431024, 
+0xaf820220, 0x3c010002, 0xac209004, 0x3c010002, 
+0x10000034, 0xac20900c, 0x8f820200, 0x34420100, 
+0xaf820200, 0x8f820220, 0x3c03fffe, 0x3463ffff, 
+0x431024, 0xaf820220, 0x24020100, 0x3c010002, 
+0xac229004, 0x3c010002, 0x10000026, 0xac20900c, 
+0x8f820200, 0x2403feff, 0x431024, 0xaf820200, 
+0x8f820220, 0x3c030001, 0x431025, 0xaf820220, 
+0x3c010002, 0xac209004, 0x3c010002, 0x10000019, 
+0xac23900c, 0x8f820200, 0x34420100, 0xaf820200, 
+0x8f820220, 0x3c030001, 0x431025, 0xaf820220, 
+0x24020100, 0x3c010002, 0xac229004, 0x3c010002, 
+0x1000000c, 0xac23900c, 0x34a5ffff, 0x3c040001, 
+0x24846c38, 0xafa30010, 0xc002b3b, 0xafa00014, 
+0x10000004, 0x0, 0x24020030, 0x3c010002, 
+0xac228fe8, 0x8fbf0018, 0x3e00008, 0x27bd0020, 
+0x0, 0x0, 0x0, 0x27bdffc8, 
+0xafb20028, 0x809021, 0xafb3002c, 0xa09821, 
+0xafb00020, 0xc08021, 0x3c040001, 0x24846c50, 
+0x3c050009, 0x3c020001, 0x8c426d98, 0x34a59001, 
+0x2403021, 0x2603821, 0xafbf0030, 0xafb10024, 
+0xa7a0001a, 0xafb00014, 0xc002b3b, 0xafa20010, 
+0x24020002, 0x12620083, 0x2e620003, 0x10400005, 
+0x24020001, 0x1262000a, 0x0, 0x10000173, 
+0x0, 0x24020004, 0x126200f8, 0x24020008, 
+0x126200f7, 0x3c02ffec, 0x1000016c, 0x0, 
+0x3c020001, 0x8c426d94, 0x30420002, 0x14400004, 
+0x128940, 0x3c02fffb, 0x3442ffff, 0x2028024, 
+0x3c010002, 0x310821, 0xac308ffc, 0x3c024000, 
+0x2021024, 0x1040004e, 0x1023c2, 0x30840030, 
+0x101382, 0x3042001c, 0x3c030001, 0x24636dd8, 
+0x431021, 0x823821, 0x3c020020, 0x2021024, 
+0x10400006, 0x24020100, 0x3c010002, 0x310821, 
+0xac229000, 0x10000005, 0x3c020080, 0x3c010002, 
+0x310821, 0xac209000, 0x3c020080, 0x2021024, 
+0x10400006, 0x121940, 0x3c020001, 0x3c010002, 
+0x230821, 0x10000005, 0xac229008, 0x121140, 
+0x3c010002, 0x220821, 0xac209008, 0x94e40000, 
+0x3c030001, 0x8c636f40, 0x24020005, 0x10620010, 
+0xa7a40018, 0x32024000, 0x10400002, 0x34824000, 
+0xa7a20018, 0x24040001, 0x94e20002, 0x24050004, 
+0x24e60002, 0x34420001, 0xc0045be, 0xa4e20002, 
+0x24040001, 0x2821, 0xc0045be, 0x27a60018, 
+0x3c020001, 0x8c426d98, 0x24110001, 0x3c010001, 
+0xac316da4, 0x14530004, 0x32028000, 0xc003daf, 
+0x0, 0x32028000, 0x1040011c, 0x0, 
+0xc003daf, 0x0, 0x3c030001, 0x8c636f40, 
+0x24020005, 0x10620115, 0x24020002, 0x3c010001, 
+0xac316d9c, 0x3c010001, 0x10000110, 0xac226d98, 
+0x24040001, 0x24050004, 0x27b0001a, 0xc0045be, 
+0x2003021, 0x24040001, 0x2821, 0xc0045be, 
+0x2003021, 0x3c020002, 0x511021, 0x8c428ff4, 
+0x3c040001, 0x8c846d98, 0x3c03bfff, 0x3463ffff, 
+0x3c010001, 0xac336da4, 0x431024, 0x3c010002, 
+0x310821, 0x109300f7, 0xac228ff4, 0x100000f7, 
+0x0, 0x3c022000, 0x2021024, 0x10400005, 
+0x24020001, 0x3c010001, 0xac226f1c, 0x10000004, 
+0x128940, 0x3c010001, 0xac206f1c, 0x128940, 
+0x3c010002, 0x310821, 0xac308ff8, 0x3c024000, 
+0x2021024, 0x14400014, 0x0, 0x3c020001, 
+0x8c426f1c, 0x10400006, 0x24040004, 0x24050001, 
+0xc004ddb, 0x24062000, 0x24020001, 0xaee204b8, 
+0x3c020002, 0x511021, 0x8c428ff0, 0x3c03bfff, 
+0x3463ffff, 0x431024, 0x3c010002, 0x310821, 
+0x100000d0, 0xac228ff0, 0x3c020001, 0x8c426f1c, 
+0x10400028, 0x3c0300a0, 0x2031024, 0x5443000d, 
+0x3c020020, 0x3c020001, 0x8c426f20, 0x24030100, 
+0x3c010002, 0x310821, 0xac239004, 0x3c030001, 
+0x3c010002, 0x310821, 0xac23900c, 0x10000015, 
+0x34420400, 0x2021024, 0x10400008, 0x24030100, 
+0x3c020001, 0x8c426f20, 0x3c010002, 0x310821, 
+0xac239004, 0x1000000b, 0x34420800, 0x3c020080, 
+0x2021024, 0x1040002e, 0x3c030001, 0x3c020001, 
+0x8c426f20, 0x3c010002, 0x310821, 0xac23900c, 
+0x34420c00, 0x3c010001, 0xac226f20, 0x10000025, 
+0x24040001, 0x3c020020, 0x2021024, 0x10400006, 
+0x24020100, 0x3c010002, 0x310821, 0xac229004, 
+0x10000005, 0x3c020080, 0x3c010002, 0x310821, 
+0xac209004, 0x3c020080, 0x2021024, 0x10400007, 
+0x121940, 0x3c020001, 0x3c010002, 0x230821, 
+0xac22900c, 0x10000006, 0x24040001, 0x121140, 
+0x3c010002, 0x220821, 0xac20900c, 0x24040001, 
+0x2821, 0x27b0001e, 0xc00457c, 0x2003021, 
+0x24040001, 0x2821, 0xc00457c, 0x2003021, 
+0x24040001, 0x24050001, 0x27b0001c, 0xc00457c, 
+0x2003021, 0x24040001, 0x24050001, 0xc00457c, 
+0x2003021, 0x10000077, 0x0, 0x3c02ffec, 
+0x3442ffff, 0x2028024, 0x3c020008, 0x2028025, 
+0x121140, 0x3c010002, 0x220821, 0xac308ff8, 
+0x3c022000, 0x2021024, 0x10400009, 0x0, 
+0x3c020001, 0x8c426e44, 0x14400005, 0x24020001, 
+0x3c010001, 0xac226f1c, 0x10000004, 0x3c024000, 
+0x3c010001, 0xac206f1c, 0x3c024000, 0x2021024, 
+0x1440001d, 0x24020e01, 0x3c030001, 0x8c636f1c, 
+0xaf820238, 0x3c010001, 0xac206db0, 0x10600005, 
+0x24022020, 0x3c010001, 0xac226f20, 0x24020001, 
+0xaee204b8, 0x3c04bfff, 0x121940, 0x3c020002, 
+0x431021, 0x8c428ff0, 0x3c050001, 0x8ca56d98, 
+0x3484ffff, 0x441024, 0x3c010002, 0x230821, 
+0xac228ff0, 0x24020001, 0x10a20044, 0x0, 
+0x10000040, 0x0, 0x3c020001, 0x8c426f1c, 
+0x1040001c, 0x24022000, 0x3c010001, 0xac226f20, 
+0x3c0300a0, 0x2031024, 0x14430005, 0x121140, 
+0x3402a000, 0x3c010001, 0x1000002d, 0xac226f20, 
+0x3c030002, 0x621821, 0x8c638ff8, 0x3c020020, 
+0x621024, 0x10400004, 0x24022001, 0x3c010001, 
+0x10000023, 0xac226f20, 0x3c020080, 0x621024, 
+0x1040001f, 0x3402a001, 0x3c010001, 0x1000001c, 
+0xac226f20, 0x3c020020, 0x2021024, 0x10400007, 
+0x121940, 0x24020100, 0x3c010002, 0x230821, 
+0xac229004, 0x10000006, 0x3c020080, 0x121140, 
+0x3c010002, 0x220821, 0xac209004, 0x3c020080, 
+0x2021024, 0x10400006, 0x121940, 0x3c020001, 
+0x3c010002, 0x230821, 0x10000005, 0xac22900c, 
+0x121140, 0x3c010002, 0x220821, 0xac20900c, 
+0x3c030001, 0x8c636d98, 0x24020001, 0x10620003, 
+0x0, 0xc003daf, 0x0, 0x8fbf0030, 
+0x8fb3002c, 0x8fb20028, 0x8fb10024, 0x8fb00020, 
+0x3e00008, 0x27bd0038, 0x27bdffb0, 0xafb3003c, 
+0x9821, 0xafb50040, 0xa821, 0xafb10034, 
+0x8821, 0x24020002, 0xafbf0048, 0xafbe0044, 
+0xafb20038, 0xafb00030, 0xafa4002c, 0xa7a0001a, 
+0xa7a00018, 0xa7a00020, 0xa7a0001e, 0xa7a00022, 
+0x10a20130, 0xa7a0001c, 0x2ca20003, 0x10400005, 
+0x24020001, 0x10a2000a, 0x3c024000, 0x1000025d, 
+0x2201021, 0x24020004, 0x10a2020a, 0x24020008, 
+0x10a20208, 0x2201021, 0x10000256, 0x0, 
+0x8fa8002c, 0x88140, 0x3c030002, 0x701821, 
+0x8c638ffc, 0x621024, 0x14400009, 0x24040001, 
+0x3c027fff, 0x3442ffff, 0x628824, 0x3c010002, 
+0x300821, 0xac318ff4, 0x10000246, 0x2201021, 
+0x24050001, 0xc00457c, 0x27a60018, 0x24040001, 
+0x24050001, 0xc00457c, 0x27a60018, 0x97a20018, 
+0x30420004, 0x104000d9, 0x3c114000, 0x3c020001, 
+0x8c426f40, 0x2443ffff, 0x2c620006, 0x104000d9, 
+0x31080, 0x3c010001, 0x220821, 0x8c226c68, 
+0x400008, 0x0, 0x24040001, 0x24050011, 
+0x27b0001a, 0xc00457c, 0x2003021, 0x24040001, 
+0x24050011, 0xc00457c, 0x2003021, 0x97a3001a, 
+0x30624000, 0x10400002, 0x3c150010, 0x3c150008, 
+0x30628000, 0x104000aa, 0x3c130001, 0x100000a8, 
+0x3c130002, 0x24040001, 0x24050014, 0x27b0001a, 
+0xc00457c, 0x2003021, 0x24040001, 0x24050014, 
+0xc00457c, 0x2003021, 0x97a3001a, 0x30621000, 
+0x10400002, 0x3c150010, 0x3c150008, 0x30620800, 
+0x10400097, 0x3c130001, 0x10000095, 0x3c130002, 
+0x24040001, 0x24050019, 0x27b0001c, 0xc00457c, 
+0x2003021, 0x24040001, 0x24050019, 0xc00457c, 
+0x2003021, 0x97a2001c, 0x30430700, 0x24020400, 
+0x10620027, 0x28620401, 0x1040000e, 0x24020200, 
+0x1062001f, 0x28620201, 0x10400005, 0x24020100, 
+0x5062001e, 0x3c130001, 0x1000001e, 0x24040001, 
+0x24020300, 0x50620019, 0x3c130002, 0x10000019, 
+0x24040001, 0x24020600, 0x1062000d, 0x28620601, 
+0x10400005, 0x24020500, 0x5062000b, 0x3c130002, 
+0x10000010, 0x24040001, 0x24020700, 0x1462000d, 
+0x24040001, 0x3c130004, 0x1000000a, 0x3c150008, 
+0x10000006, 0x3c130004, 0x10000005, 0x3c150008, 
+0x3c130001, 0x10000002, 0x3c150008, 0x3c150010, 
+0x24040001, 0x24050018, 0x27b0001e, 0xc00457c, 
+0x2003021, 0x24040001, 0x24050018, 0xc00457c, 
+0x2003021, 0x8fa8002c, 0x97a7001e, 0x81140, 
+0x3c060002, 0xc23021, 0x8cc68ff4, 0x97a20022, 
+0x3c100001, 0x26106c5c, 0x2002021, 0xafa20010, 
+0x97a2001c, 0x3c05000c, 0x34a50303, 0xc002b3b, 
+0xafa20014, 0x3c020004, 0x16620010, 0x3c020001, 
+0x8f840054, 0x24030001, 0x24020002, 0x3c010001, 
+0xac236d9c, 0x3c010001, 0xac226d98, 0x3c010001, 
+0xac236da4, 0x3c010001, 0xac236e24, 0x3c010001, 
+0xac246f30, 0x1000004f, 0x2b38825, 0x16620039, 
+0x3c028000, 0x3c020001, 0x8c426e20, 0x1440001e, 
+0x24040018, 0x2021, 0x2821, 0xc004ddb, 
+0x34068000, 0x8f830054, 0x8f820054, 0x2b38825, 
+0x10000002, 0x24630032, 0x8f820054, 0x621023, 
+0x2c420033, 0x1440fffc, 0x0, 0x8f830054, 
+0x24020001, 0x3c010001, 0xac226e20, 0x3c010001, 
+0xac226d9c, 0x3c010001, 0xac226d98, 0x3c010001, 
+0xac226da4, 0x3c010001, 0xac226e24, 0x3c010001, 
+0x1000002c, 0xac236f30, 0x2821, 0xc004ddb, 
+0x24060404, 0x2021, 0x2405001e, 0x27a60018, 
+0x24020002, 0xc0045be, 0xa7a20018, 0x2021, 
+0x2821, 0x27a60018, 0xc0045be, 0xa7a00018, 
+0x24040018, 0x24050002, 0xc004ddb, 0x24060004, 
+0x3c028000, 0x2221025, 0x2b31825, 0x10000015, 
+0x438825, 0x2221025, 0x2751825, 0x438825, 
+0x2002021, 0x97a6001c, 0x3c070001, 0x8ce76d98, 
+0x3c05000c, 0x34a50326, 0xafb30010, 0xc002b3b, 
+0xafb10014, 0x10000007, 0x0, 0x3c110002, 
+0x2308821, 0x8e318ffc, 0x3c027fff, 0x3442ffff, 
+0x2228824, 0x3c020001, 0x8c426da8, 0x1040001e, 
+0x0, 0x3c020001, 0x8c426f1c, 0x10400002, 
+0x3c022000, 0x2228825, 0x8fa8002c, 0x81140, 
+0x3c010002, 0x220821, 0x8c229000, 0x10400003, 
+0x3c020020, 0x10000005, 0x2228825, 0x3c02ffdf, 
+0x3442ffff, 0x2228824, 0x8fa8002c, 0x81140, 
+0x3c010002, 0x220821, 0x8c229008, 0x10400003, 
+0x3c020080, 0x10000004, 0x2228825, 0x3c02ff7f, 
+0x3442ffff, 0x2228824, 0x8fa8002c, 0x81140, 
+0x3c010002, 0x220821, 0xac318ff4, 0x10000135, 
+0x2201021, 0x8fa8002c, 0x8f140, 0x3c030002, 
+0x7e1821, 0x8c638ff8, 0x3c024000, 0x621024, 
+0x14400009, 0x24040001, 0x3c027fff, 0x3442ffff, 
+0x628824, 0x3c010002, 0x3e0821, 0xac318ff0, 
+0x10000124, 0x2201021, 0x2821, 0xc00457c, 
+0x27a60018, 0x24040001, 0x2821, 0xc00457c, 
+0x27a60018, 0x24040001, 0x24050001, 0x27b20020, 
+0xc00457c, 0x2403021, 0x24040001, 0x24050001, 
+0xc00457c, 0x2403021, 0x24040001, 0x24050004, 
+0x27b1001e, 0xc00457c, 0x2203021, 0x24040001, 
+0x24050004, 0xc00457c, 0x2203021, 0x24040001, 
+0x24050005, 0x27b00022, 0xc00457c, 0x2003021, 
+0x24040001, 0x24050005, 0xc00457c, 0x2003021, 
+0x24040001, 0x24050010, 0xc00457c, 0x27a60018, 
+0x24040001, 0x24050010, 0xc00457c, 0x27a60018, 
+0x24040001, 0x2405000a, 0xc00457c, 0x2403021, 
+0x24040001, 0x2405000a, 0xc00457c, 0x2403021, 
+0x24040001, 0x24050018, 0xc00457c, 0x2203021, 
+0x24040001, 0x24050018, 0xc00457c, 0x2203021, 
+0x24040001, 0x24050001, 0xc00457c, 0x27a60018, 
+0x24040001, 0x24050001, 0xc00457c, 0x27a60018, 
+0x97a20018, 0x30420004, 0x10400066, 0x3c114000, 
+0x3c030001, 0x8c636f34, 0x24020005, 0x14620067, 
+0x24040001, 0x24050019, 0x27b0001c, 0xc00457c, 
+0x2003021, 0x24040001, 0x24050019, 0xc00457c, 
+0x2003021, 0x97a2001c, 0x30430700, 0x24020400, 
+0x10620027, 0x28620401, 0x1040000e, 0x24020200, 
+0x1062001f, 0x28620201, 0x10400005, 0x24020100, 
+0x5062001e, 0x3c130001, 0x1000001e, 0x3c020004, 
+0x24020300, 0x50620019, 0x3c130002, 0x10000019, 
+0x3c020004, 0x24020600, 0x1062000d, 0x28620601, 
+0x10400005, 0x24020500, 0x5062000b, 0x3c130002, 
+0x10000010, 0x3c020004, 0x24020700, 0x1462000d, 
+0x3c020004, 0x3c130004, 0x1000000a, 0x3c150008, 
+0x10000006, 0x3c130004, 0x10000005, 0x3c150008, 
+0x3c130001, 0x10000002, 0x3c150008, 0x3c150010, 
+0x3c020004, 0x12620017, 0x3c028000, 0x8f820054, 
+0x24100001, 0x3c010001, 0xac306d9c, 0x3c010001, 
+0xac306d98, 0x3c010001, 0xac306da4, 0x3c010001, 
+0xac306e24, 0x3c010001, 0xac226f30, 0x3c020001, 
+0x16620022, 0x2758825, 0x2021, 0x2821, 
+0xc004ddb, 0x34068000, 0x3c010001, 0x1000001b, 
+0xac306e20, 0x2221025, 0x2b31825, 0x438825, 
+0x97a6001c, 0x3c020001, 0x8c426f1c, 0x3c070001, 
+0x8ce76d98, 0x3c040001, 0x24846c5c, 0xafa20010, 
+0x97a2001e, 0x3c05000c, 0x34a50323, 0x3c010001, 
+0xac206e20, 0xc002b3b, 0xafa20014, 0x10000007, 
+0x0, 0x3c110002, 0x23e8821, 0x8e318ff0, 
+0x3c027fff, 0x3442ffff, 0x2228824, 0x3c020001, 
+0x8c426da8, 0x10400069, 0x0, 0x3c020001, 
+0x8c426f1c, 0x10400002, 0x3c022000, 0x2228825, 
+0x8fa8002c, 0x81140, 0x3c010002, 0x220821, 
+0x8c229004, 0x10400003, 0x3c020020, 0x10000005, 
+0x2228825, 0x3c02ffdf, 0x3442ffff, 0x2228824, 
+0x8fa8002c, 0x81140, 0x3c010002, 0x220821, 
+0x8c22900c, 0x10400003, 0x3c020080, 0x1000004f, 
+0x2228825, 0x3c02ff7f, 0x3442ffff, 0x1000004b, 
+0x2228824, 0x8fa8002c, 0x82940, 0x3c030002, 
+0x651821, 0x8c638ff8, 0x3c024000, 0x621024, 
+0x14400008, 0x3c027fff, 0x3442ffff, 0x628824, 
+0x3c010002, 0x250821, 0xac318ff0, 0x10000041, 
+0x2201021, 0x3c020001, 0x8c426da8, 0x10400034, 
+0x3c11c00c, 0x3c020001, 0x8c426e44, 0x3c04c00c, 
+0x34842000, 0x3c030001, 0x8c636f1c, 0x2102b, 
+0x21023, 0x441024, 0x10600003, 0x518825, 
+0x3c022000, 0x2228825, 0x3c020002, 0x451021, 
+0x8c429004, 0x10400003, 0x3c020020, 0x10000004, 
+0x2228825, 0x3c02ffdf, 0x3442ffff, 0x2228824, 
+0x8fa8002c, 0x81140, 0x3c010002, 0x220821, 
+0x8c22900c, 0x10400003, 0x3c020080, 0x10000004, 
+0x2228825, 0x3c02ff7f, 0x3442ffff, 0x2228824, 
+0x3c020001, 0x8c426e30, 0x10400002, 0x3c020800, 
+0x2228825, 0x3c020001, 0x8c426e34, 0x10400002, 
+0x3c020400, 0x2228825, 0x3c020001, 0x8c426e38, 
+0x10400006, 0x3c020100, 0x10000004, 0x2228825, 
+0x3c027fff, 0x3442ffff, 0x628824, 0x8fa8002c, 
+0x81140, 0x3c010002, 0x220821, 0xac318ff0, 
+0x2201021, 0x8fbf0048, 0x8fbe0044, 0x8fb50040, 
+0x8fb3003c, 0x8fb20038, 0x8fb10034, 0x8fb00030, 
+0x3e00008, 0x27bd0050, 0x27bdffd0, 0xafb20028, 
+0x809021, 0xafbf002c, 0xafb10024, 0xafb00020, 
+0x8f840200, 0x3c100001, 0x8e106d98, 0x8f860220, 
+0x24020002, 0x1202005c, 0x2e020003, 0x10400005, 
+0x24020001, 0x1202000a, 0x121940, 0x1000010c, 
+0x0, 0x24020004, 0x120200bf, 0x24020008, 
+0x120200be, 0x128940, 0x10000105, 0x0, 
+0x3c050002, 0xa32821, 0x8ca58ffc, 0x3c100002, 
+0x2038021, 0x8e108ff4, 0x3c024000, 0xa21024, 
+0x10400038, 0x3c020008, 0x2021024, 0x10400020, 
+0x34840002, 0x3c020002, 0x431021, 0x8c429000, 
+0x10400005, 0x34840020, 0x34840100, 0x3c020020, 
+0x10000006, 0x2028025, 0x2402feff, 0x822024, 
+0x3c02ffdf, 0x3442ffff, 0x2028024, 0x121140, 
+0x3c010002, 0x220821, 0x8c229008, 0x10400005, 
+0x3c020001, 0xc23025, 0x3c020080, 0x10000016, 
+0x2028025, 0x3c02fffe, 0x3442ffff, 0xc23024, 
+0x3c02ff7f, 0x3442ffff, 0x1000000f, 0x2028024, 
+0x2402fedf, 0x822024, 0x3c02fffe, 0x3442ffff, 
+0xc23024, 0x3c02ff5f, 0x3442ffff, 0x2028024, 
+0x3c010002, 0x230821, 0xac209000, 0x3c010002, 
+0x230821, 0xac209008, 0xaf840200, 0xaf860220, 
+0x8f820220, 0x34420002, 0xaf820220, 0x1000000a, 
+0x121140, 0x3c02bfff, 0x3442ffff, 0x8f830200, 
+0x2028024, 0x2402fffd, 0x621824, 0xc003daf, 
+0xaf830200, 0x121140, 0x3c010002, 0x220821, 
+0x100000b7, 0xac308ff4, 0x3c020001, 0x8c426f1c, 
+0x10400069, 0x24050004, 0x24040001, 0xc00457c, 
+0x27a60018, 0x24040001, 0x24050005, 0xc00457c, 
+0x27a6001a, 0x97a30018, 0x97a2001a, 0x3c040001, 
+0x24846e48, 0x30630c00, 0x31a82, 0x30420c00, 
+0x21282, 0xa7a2001a, 0x21080, 0x441021, 
+0x431021, 0xa7a30018, 0x90480000, 0x24020001, 
+0x3103ffff, 0x10620029, 0x28620002, 0x10400005, 
+0x0, 0x10600009, 0x0, 0x1000003d, 
+0x0, 0x10700013, 0x24020003, 0x1062002c, 
+0x0, 0x10000037, 0x0, 0x8f820200, 
+0x2403feff, 0x431024, 0xaf820200, 0x8f820220, 
+0x3c03fffe, 0x3463ffff, 0x431024, 0xaf820220, 
+0x3c010002, 0xac209004, 0x3c010002, 0x10000032, 
+0xac20900c, 0x8f820200, 0x34420100, 0xaf820200, 
+0x8f820220, 0x3c03fffe, 0x3463ffff, 0x431024, 
+0xaf820220, 0x24020100, 0x3c010002, 0xac229004, 
+0x3c010002, 0x10000024, 0xac20900c, 0x8f820200, 
+0x2403feff, 0x431024, 0xaf820200, 0x8f820220, 
+0x3c030001, 0x431025, 0xaf820220, 0x3c010002, 
+0xac209004, 0x3c010002, 0x10000017, 0xac23900c, 
+0x8f820200, 0x34420100, 0xaf820200, 0x8f820220, 
+0x3c030001, 0x431025, 0xaf820220, 0x24020100, 
+0x3c010002, 0xac229004, 0x3c010002, 0x1000000a, 
+0xac23900c, 0x3c040001, 0x24846c80, 0x97a6001a, 
+0x97a70018, 0x3c050001, 0x34a5ffff, 0xafa80010, 
+0xc002b3b, 0xafa00014, 0x8f820200, 0x34420002, 
+0x1000004b, 0xaf820200, 0x128940, 0x3c050002, 
+0xb12821, 0x8ca58ff8, 0x3c100002, 0x2118021, 
+0x8e108ff0, 0x3c024000, 0xa21024, 0x14400010, 
+0x0, 0x3c020001, 0x8c426f1c, 0x14400005, 
+0x3c02bfff, 0x8f820200, 0x34420002, 0xaf820200, 
+0x3c02bfff, 0x3442ffff, 0xc003daf, 0x2028024, 
+0x3c010002, 0x310821, 0x10000031, 0xac308ff0, 
+0x3c020001, 0x8c426f1c, 0x10400005, 0x3c020020, 
+0x3c020001, 0x8c426e44, 0x10400025, 0x3c020020, 
+0xa21024, 0x10400007, 0x34840020, 0x24020100, 
+0x3c010002, 0x310821, 0xac229004, 0x10000006, 
+0x34840100, 0x3c010002, 0x310821, 0xac209004, 
+0x2402feff, 0x822024, 0x3c020080, 0xa21024, 
+0x10400007, 0x121940, 0x3c020001, 0x3c010002, 
+0x230821, 0xac22900c, 0x10000008, 0xc23025, 
+0x121140, 0x3c010002, 0x220821, 0xac20900c, 
+0x3c02fffe, 0x3442ffff, 0xc23024, 0xaf840200, 
+0xaf860220, 0x8f820220, 0x34420002, 0xaf820220, 
+0x121140, 0x3c010002, 0x220821, 0xac308ff0, 
+0x8fbf002c, 0x8fb20028, 0x8fb10024, 0x8fb00020, 
+0x3e00008, 0x27bd0030, 0x0, 0x1821, 
+0x308400ff, 0x2405ffdf, 0x2406ffbf, 0x641007, 
+0x30420001, 0x10400004, 0x0, 0x8f820044, 
+0x10000003, 0x34420040, 0x8f820044, 0x461024, 
+0xaf820044, 0x8f820044, 0x34420020, 0xaf820044, 
+0x8f820044, 0x451024, 0xaf820044, 0x24630001, 
+0x28620008, 0x5440ffee, 0x641007, 0x3e00008, 
+0x0, 0x2c820008, 0x1040001b, 0x0, 
+0x2405ffdf, 0x2406ffbf, 0x41880, 0x3c020001, 
+0x24426e60, 0x621821, 0x24640004, 0x90620000, 
+0x10400004, 0x0, 0x8f820044, 0x10000003, 
+0x34420040, 0x8f820044, 0x461024, 0xaf820044, 
+0x8f820044, 0x34420020, 0xaf820044, 0x8f820044, 
+0x451024, 0xaf820044, 0x24630001, 0x64102b, 
+0x1440ffee, 0x0, 0x3e00008, 0x0, 
+0x0, 0x0, 0x0, 0x8f8400c4, 
+0x8f8600e0, 0x8f8700e4, 0x2402fff8, 0xc22824, 
+0x10e5001a, 0x27623ff8, 0x14e20002, 0x24e80008, 
+0x27683000, 0x55050004, 0x8d0a0000, 0x30c20004, 
+0x14400012, 0x805021, 0x8ce90000, 0x8f42013c, 
+0x1494823, 0x49182b, 0x94eb0006, 0x10600002, 
+0x25630050, 0x494821, 0x123182b, 0x50400003, 
+0x8f4201fc, 0x3e00008, 0xe01021, 0xaf8800e8, 
+0x24420001, 0xaf4201fc, 0xaf8800e4, 0x3e00008, 
+0x1021, 0x3e00008, 0x0, 0x8f8300e4, 
+0x27623ff8, 0x10620004, 0x24620008, 0xaf8200e8, 
+0x3e00008, 0xaf8200e4, 0x27623000, 0xaf8200e8, 
+0x3e00008, 0xaf8200e4, 0x3e00008, 0x0, 
+0x0, 0x0, 0x0, 0x8f880120, 
+0x27624fe0, 0x8f830128, 0x15020002, 0x25090020, 
+0x27694800, 0x11230012, 0x8fa20010, 0xad040000, 
+0xad050004, 0xad060008, 0xa507000e, 0x8fa30014, 
+0xad020018, 0x8fa20018, 0xad03001c, 0x25030016, 
+0xad020010, 0xad030014, 0xaf890120, 0x8f4300fc, 
+0x24020001, 0x2463ffff, 0x3e00008, 0xaf4300fc, 
+0x8f430324, 0x1021, 0x24630001, 0x3e00008, 
+0xaf430324, 0x3e00008, 0x0, 0x8f880100, 
+0x276247e0, 0x8f830108, 0x15020002, 0x25090020, 
+0x27694000, 0x1123000f, 0x8fa20010, 0xad040000, 
+0xad050004, 0xad060008, 0xa507000e, 0x8fa30014, 
+0xad020018, 0x8fa20018, 0xad03001c, 0x25030016, 
+0xad020010, 0xad030014, 0xaf890100, 0x3e00008, 
+0x24020001, 0x8f430328, 0x1021, 0x24630001, 
+0x3e00008, 0xaf430328, 0x3e00008, 0x0, 
+0x0, 0x0, 0x0, 0x0 };
+static int tigon2FwRodata[/*(MAX_RODATA_LEN/4) + 1*/] = {
+0x24486561, 0x6465723a, 0x202f7072, 
+0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765, 
+0x2f2e2f6e, 0x69632f66, 0x77322f63, 0x6f6d6d6f, 
+0x6e2f6677, 0x6d61696e, 0x2e632c76, 0x20312e31, 
+0x2e322e34, 0x35203139, 0x39392f30, 0x312f3234, 
+0x2030303a, 0x31303a35, 0x35207368, 0x75616e67, 
+0x20457870, 0x20240000, 0x65767452, 0x6e674600, 
+0x51657674, 0x46000000, 0x51657674, 0x505f4600, 
+0x4d657674, 0x526e6746, 0x0, 0x4d516576, 
+0x74460000, 0x4d516576, 0x505f4600, 0x5173436f, 
+0x6e495f46, 0x0, 0x5173436f, 0x6e734600, 
+0x51725072, 0x6f644600, 0x6261644d, 0x656d537a, 
+0x0, 0x68775665, 0x72000000, 0x62616448, 
+0x77566572, 0x0, 0x2a2a4441, 0x574e5f41, 
+0x0, 0x74785278, 0x4266537a, 0x0, 
+0x62664174, 0x6e4d726b, 0x0, 0x7265645a, 
+0x6f6e6531, 0x0, 0x70636943, 0x6f6e6600, 
+0x67656e43, 0x6f6e6600, 0x2a646d61, 0x5244666c, 
+0x0, 0x2a50414e, 0x49432a00, 0x2e2e2f2e, 
+0x2e2f2e2e, 0x2f2e2e2f, 0x2e2e2f73, 0x72632f6e, 
+0x69632f66, 0x77322f63, 0x6f6d6d6f, 0x6e2f6677, 
+0x6d61696e, 0x2e630000, 0x72636246, 0x6c616773, 
+0x0, 0x62616452, 0x78526362, 0x0, 
+0x676c6f62, 0x466c6773, 0x0, 0x2b5f6469, 
+0x73705f6c, 0x6f6f7000, 0x2b65765f, 0x68616e64, 
+0x6c657200, 0x63616e74, 0x31446d61, 0x0, 
+0x2b715f64, 0x6d615f74, 0x6f5f6e69, 0x635f636b, 
+0x73756d00, 0x2b685f73, 0x656e645f, 0x64617461, 
+0x5f726561, 0x64795f63, 0x6b73756d, 0x0, 
+0x2b685f64, 0x6d615f72, 0x645f6173, 0x73697374, 
+0x5f636b73, 0x756d0000, 0x74436b73, 0x6d4f6e00, 
+0x2b715f64, 0x6d615f74, 0x6f5f6e69, 0x63000000, 
+0x2b685f73, 0x656e645f, 0x64617461, 0x5f726561, 
+0x64790000, 0x2b685f64, 0x6d615f72, 0x645f6173, 
+0x73697374, 0x0, 0x74436b73, 0x6d4f6666, 
+0x0, 0x2b685f73, 0x656e645f, 0x62645f72, 
+0x65616479, 0x0, 0x68737453, 0x52696e67, 
+0x0, 0x62616453, 0x52696e67, 0x0, 
+0x6e696353, 0x52696e67, 0x0, 0x77446d61, 
+0x416c6c41, 0x0, 0x2b715f64, 0x6d615f74, 
+0x6f5f686f, 0x73745f63, 0x6b73756d, 0x0, 
+0x2b685f6d, 0x61635f72, 0x785f636f, 0x6d705f63, 
+0x6b73756d, 0x0, 0x2b685f64, 0x6d615f77, 
+0x725f6173, 0x73697374, 0x5f636b73, 0x756d0000, 
+0x72436b73, 0x6d4f6e00, 0x2b715f64, 0x6d615f74, 
+0x6f5f686f, 0x73740000, 0x2b685f6d, 0x61635f72, 
+0x785f636f, 0x6d700000, 0x2b685f64, 0x6d615f77, 
+0x725f6173, 0x73697374, 0x0, 0x72436b73, 
+0x6d4f6666, 0x0, 0x2b685f72, 0x6563765f, 
+0x62645f72, 0x65616479, 0x0, 0x2b685f72, 
+0x6563765f, 0x6a756d62, 0x6f5f6264, 0x5f726561, 
+0x64790000, 0x2b685f72, 0x6563765f, 0x6d696e69, 
+0x5f62645f, 0x72656164, 0x79000000, 0x2b6d685f, 
+0x636f6d6d, 0x616e6400, 0x2b685f74, 0x696d6572, 
+0x0, 0x2b685f64, 0x6f5f7570, 0x64617465, 
+0x5f74785f, 0x636f6e73, 0x0, 0x2b685f64, 
+0x6f5f7570, 0x64617465, 0x5f72785f, 0x70726f64, 
+0x0, 0x2b636b73, 0x756d3136, 0x0, 
+0x2b706565, 0x6b5f6d61, 0x635f7278, 0x5f776100, 
+0x2b706565, 0x6b5f6d61, 0x635f7278, 0x0, 
+0x2b646571, 0x5f6d6163, 0x5f727800, 0x2b685f6d, 
+0x61635f72, 0x785f6174, 0x746e0000, 0x62616452, 
+0x6574537a, 0x0, 0x72784264, 0x4266537a, 
+0x0, 0x2b6e756c, 0x6c5f6861, 0x6e646c65, 
+0x72000000, 0x66774f70, 0x4661696c, 0x0, 
+0x2b685f75, 0x70646174, 0x655f6c65, 0x64340000, 
+0x2b685f75, 0x70646174, 0x655f6c65, 0x64360000, 
+0x2b685f75, 0x70646174, 0x655f6c65, 0x64320000, 
+0x696e7453, 0x74617465, 0x0, 0x2a2a696e, 
+0x69744370, 0x0, 0x23736372, 0x65616d00, 
+0x69537461, 0x636b4572, 0x0, 0x70726f62, 
+0x654d656d, 0x0, 0x2a2a4441, 0x574e5f42, 
+0x0, 0x2b73775f, 0x646d615f, 0x61737369, 
+0x73745f70, 0x6c75735f, 0x74696d65, 0x72000000, 
+0x2b267072, 0x656c6f61, 0x645f7772, 0x5f646573, 
+0x63720000, 0x2b267072, 0x656c6f61, 0x645f7264, 
+0x5f646573, 0x63720000, 0x2b685f68, 0x665f7469, 
+0x6d657200, 0x24486561, 0x6465723a, 0x202f7072, 
+0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765, 
+0x2f2e2f6e, 0x69632f66, 0x77322f63, 0x6f6d6d6f, 
+0x6e2f7469, 0x6d65722e, 0x632c7620, 0x312e312e, 
+0x322e3335, 0x20313939, 0x392f3031, 0x2f323720, 
+0x31393a30, 0x393a3530, 0x20686179, 0x65732045, 
+0x78702024, 0x0, 0x65767452, 0x6e674600, 
+0x51657674, 0x46000000, 0x51657674, 0x505f4600, 
+0x4d657674, 0x526e6746, 0x0, 0x4d516576, 
+0x74460000, 0x4d516576, 0x505f4600, 0x5173436f, 
+0x6e495f46, 0x0, 0x5173436f, 0x6e734600, 
+0x51725072, 0x6f644600, 0x542d446d, 0x61526432, 
+0x0, 0x542d446d, 0x61526431, 0x0, 
+0x542d446d, 0x61526442, 0x0, 0x542d446d, 
+0x61577232, 0x0, 0x542d446d, 0x61577231, 
+0x0, 0x542d446d, 0x61577242, 0x0, 
+0x0, 0x24486561, 0x6465723a, 0x202f7072, 
+0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765, 
+0x2f2e2f6e, 0x69632f66, 0x77322f63, 0x6f6d6d6f, 
+0x6e2f636f, 0x6d6d616e, 0x642e632c, 0x7620312e, 
+0x312e322e, 0x32382031, 0x3939392f, 0x30312f32, 
+0x30203139, 0x3a34393a, 0x34392073, 0x6875616e, 
+0x67204578, 0x70202400, 0x65767452, 0x6e674600, 
+0x51657674, 0x46000000, 0x51657674, 0x505f4600, 
+0x4d657674, 0x526e6746, 0x0, 0x4d516576, 
+0x74460000, 0x4d516576, 0x505f4600, 0x5173436f, 
+0x6e495f46, 0x0, 0x5173436f, 0x6e734600, 
+0x51725072, 0x6f644600, 0x3f48636d, 0x644d6278, 
+0x0, 0x3f636d64, 0x48737453, 0x0, 
+0x3f636d64, 0x4d634d64, 0x0, 0x3f636d64, 
+0x50726f6d, 0x0, 0x3f636d64, 0x4c696e6b, 
+0x0, 0x3f636d64, 0x45727200, 0x86ac, 
+0x8e5c, 0x8e5c, 0x8de4, 0x8b78, 
+0x8e30, 0x8e5c, 0x8790, 0x8800, 
+0x8990, 0x8a68, 0x8a34, 0x8e5c, 
+0x8870, 0x8b24, 0x8e5c, 0x8b34, 
+0x87b4, 0x8824, 0x0, 0x0, 
+0x0, 0x24486561, 0x6465723a, 0x202f7072, 
+0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765, 
+0x2f2e2f6e, 0x69632f66, 0x77322f63, 0x6f6d6d6f, 
+0x6e2f6d63, 0x6173742e, 0x632c7620, 0x312e312e, 
+0x322e3820, 0x31393938, 0x2f31322f, 0x30382030, 
+0x323a3336, 0x3a333620, 0x73687561, 0x6e672045, 
+0x78702024, 0x0, 0x65767452, 0x6e674600, 
+0x51657674, 0x46000000, 0x51657674, 0x505f4600, 
+0x4d657674, 0x526e6746, 0x0, 0x4d516576, 
+0x74460000, 0x4d516576, 0x505f4600, 0x5173436f, 
+0x6e495f46, 0x0, 0x5173436f, 0x6e734600, 
+0x51725072, 0x6f644600, 0x6164644d, 0x63447570, 
+0x0, 0x6164644d, 0x6346756c, 0x0, 
+0x64656c4d, 0x634e6f45, 0x0, 0x0, 
+0x0, 0x24486561, 0x6465723a, 0x202f7072, 
+0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765, 
+0x2f2e2f6e, 0x69632f66, 0x77322f63, 0x6f6d6d6f, 
+0x6e2f646d, 0x612e632c, 0x7620312e, 0x312e322e, 
+0x32342031, 0x3939382f, 0x31322f32, 0x31203030, 
+0x3a33333a, 0x30392073, 0x6875616e, 0x67204578, 
+0x70202400, 0x65767452, 0x6e674600, 0x51657674, 
+0x46000000, 0x51657674, 0x505f4600, 0x4d657674, 
+0x526e6746, 0x0, 0x4d516576, 0x74460000, 
+0x4d516576, 0x505f4600, 0x5173436f, 0x6e495f46, 
+0x0, 0x5173436f, 0x6e734600, 0x51725072, 
+0x6f644600, 0x7377446d, 0x614f6666, 0x0, 
+0x31446d61, 0x4f6e0000, 0x7377446d, 0x614f6e00, 
+0x2372446d, 0x6141544e, 0x0, 0x72446d61, 
+0x41544e30, 0x0, 0x72446d61, 0x41544e31, 
+0x0, 0x72446d61, 0x34476200, 0x2a50414e, 
+0x49432a00, 0x2e2e2f2e, 0x2e2f2e2e, 0x2f2e2e2f, 
+0x2e2e2f73, 0x72632f6e, 0x69632f66, 0x77322f63, 
+0x6f6d6d6f, 0x6e2f646d, 0x612e6300, 0x2377446d, 
+0x6141544e, 0x0, 0x77446d61, 0x41544e30, 
+0x0, 0x77446d61, 0x41544e31, 0x0, 
+0x77446d61, 0x34476200, 0x0, 0x0, 
+0x0, 0x24486561, 0x6465723a, 0x202f7072, 
+0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765, 
+0x2f2e2f6e, 0x69632f66, 0x77322f63, 0x6f6d6d6f, 
+0x6e2f7472, 0x6163652e, 0x632c7620, 0x312e312e, 
+0x322e3520, 0x31393938, 0x2f30392f, 0x33302031, 
+0x383a3530, 0x3a323820, 0x73687561, 0x6e672045, 
+0x78702024, 0x0, 0x0, 0x0, 
+0x0, 0x24486561, 0x6465723a, 0x202f7072, 
+0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765, 
+0x2f2e2f6e, 0x69632f66, 0x77322f63, 0x6f6d6d6f, 
+0x6e2f6461, 0x74612e63, 0x2c762031, 0x2e312e32, 
+0x2e313220, 0x31393939, 0x2f30312f, 0x32302031, 
+0x393a3439, 0x3a353120, 0x73687561, 0x6e672045, 
+0x78702024, 0x0, 0x46575f56, 0x45525349, 
+0x4f4e3a20, 0x23312046, 0x72692041, 0x70722037, 
+0x2031373a, 0x35373a35, 0x32205044, 0x54203230, 
+0x30300000, 0x46575f43, 0x4f4d5049, 0x4c455f54, 
+0x494d453a, 0x2031373a, 0x35373a35, 0x32000000, 
+0x46575f43, 0x4f4d5049, 0x4c455f42, 0x593a2064, 
+0x65767263, 0x73000000, 0x46575f43, 0x4f4d5049, 
+0x4c455f48, 0x4f53543a, 0x20636f6d, 0x70757465, 
+0x0, 0x46575f43, 0x4f4d5049, 0x4c455f44, 
+0x4f4d4149, 0x4e3a2065, 0x6e672e61, 0x6374656f, 
+0x6e2e636f, 0x6d000000, 0x46575f43, 0x4f4d5049, 
+0x4c45523a, 0x20676363, 0x20766572, 0x73696f6e, 
+0x20322e37, 0x2e320000, 0x0, 0x12041100, 
+0x0, 0x24486561, 0x6465723a, 0x202f7072, 
+0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765, 
+0x2f2e2f6e, 0x69632f66, 0x77322f63, 0x6f6d6d6f, 
+0x6e2f6d65, 0x6d2e632c, 0x7620312e, 0x312e322e, 
+0x35203139, 0x39382f30, 0x392f3330, 0x2031383a, 
+0x35303a30, 0x38207368, 0x75616e67, 0x20457870, 
+0x20240000, 0x24486561, 0x6465723a, 0x202f7072, 
+0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765, 
+0x2f2e2f6e, 0x69632f66, 0x77322f63, 0x6f6d6d6f, 
+0x6e2f7365, 0x6e642e63, 0x2c762031, 0x2e312e32, 
+0x2e343420, 0x31393938, 0x2f31322f, 0x32312030, 
+0x303a3333, 0x3a313820, 0x73687561, 0x6e672045, 
+0x78702024, 0x0, 0x65767452, 0x6e674600, 
+0x51657674, 0x46000000, 0x51657674, 0x505f4600, 
+0x4d657674, 0x526e6746, 0x0, 0x4d516576, 
+0x74460000, 0x4d516576, 0x505f4600, 0x5173436f, 
+0x6e495f46, 0x0, 0x5173436f, 0x6e734600, 
+0x51725072, 0x6f644600, 0x69736e74, 0x54637055, 
+0x0, 0x24486561, 0x6465723a, 0x202f7072, 
+0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765, 
+0x2f2e2f6e, 0x69632f66, 0x77322f63, 0x6f6d6d6f, 
+0x6e2f7265, 0x63762e63, 0x2c762031, 0x2e312e32, 
+0x2e353320, 0x31393939, 0x2f30312f, 0x31362030, 
+0x323a3535, 0x3a343320, 0x73687561, 0x6e672045, 
+0x78702024, 0x0, 0x65767452, 0x6e674600, 
+0x51657674, 0x46000000, 0x51657674, 0x505f4600, 
+0x4d657674, 0x526e6746, 0x0, 0x4d516576, 
+0x74460000, 0x4d516576, 0x505f4600, 0x5173436f, 
+0x6e495f46, 0x0, 0x5173436f, 0x6e734600, 
+0x51725072, 0x6f644600, 0x724d6163, 0x43686b30, 
+0x0, 0x72784672, 0x6d324c67, 0x0, 
+0x72784e6f, 0x53744264, 0x0, 0x72784e6f, 
+0x4d694264, 0x0, 0x72784e6f, 0x4a6d4264, 
+0x0, 0x7278436b, 0x446d6146, 0x0, 
+0x72785144, 0x6d457846, 0x0, 0x72785144, 
+0x6d614600, 0x72785144, 0x4c426446, 0x0, 
+0x72785144, 0x6d426446, 0x0, 0x72784372, 
+0x63506164, 0x0, 0x72536d51, 0x446d6146, 
+0x0, 0x24486561, 0x6465723a, 0x202f7072, 
+0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765, 
+0x2f2e2f6e, 0x69632f66, 0x77322f63, 0x6f6d6d6f, 
+0x6e2f6d61, 0x632e632c, 0x7620312e, 0x312e322e, 
+0x32322031, 0x3939382f, 0x31322f30, 0x38203032, 
+0x3a33363a, 0x33302073, 0x6875616e, 0x67204578, 
+0x70202400, 0x65767452, 0x6e674600, 0x51657674, 
+0x46000000, 0x51657674, 0x505f4600, 0x4d657674, 
+0x526e6746, 0x0, 0x4d516576, 0x74460000, 
+0x4d516576, 0x505f4600, 0x5173436f, 0x6e495f46, 
+0x0, 0x5173436f, 0x6e734600, 0x51725072, 
+0x6f644600, 0x6d616354, 0x68726573, 0x0, 
+0x23744d61, 0x6341544e, 0x0, 0x23724d61, 
+0x6341544e, 0x0, 0x72656d41, 0x73737274, 
+0x0, 0x6c696e6b, 0x444f574e, 0x0, 
+0x6c696e6b, 0x55500000, 0x0, 0x0, 
+0x0, 0x24486561, 0x6465723a, 0x202f7072, 
+0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765, 
+0x2f2e2f6e, 0x69632f66, 0x77322f63, 0x6f6d6d6f, 
+0x6e2f636b, 0x73756d2e, 0x632c7620, 0x312e312e, 
+0x322e3920, 0x31393939, 0x2f30312f, 0x31342030, 
+0x303a3033, 0x3a343820, 0x73687561, 0x6e672045, 
+0x78702024, 0x0, 0x65767452, 0x6e674600, 
+0x51657674, 0x46000000, 0x51657674, 0x505f4600, 
+0x4d657674, 0x526e6746, 0x0, 0x4d516576, 
+0x74460000, 0x4d516576, 0x505f4600, 0x5173436f, 
+0x6e495f46, 0x0, 0x5173436f, 0x6e734600, 
+0x51725072, 0x6f644600, 0x0, 0x0, 
+0x0, 0x50726f62, 0x65506879, 0x0, 
+0x6c6e6b41, 0x53535254, 0x0, 0x109a4, 
+0x10a1c, 0x10a50, 0x10a7c, 0x11050, 
+0x10aa8, 0x10b10, 0x111fc, 0x10dc0, 
+0x10c68, 0x10c80, 0x10cc4, 0x10cec, 
+0x10d0c, 0x10d34, 0x111fc, 0x10dc0, 
+0x10df8, 0x10e10, 0x10e40, 0x10e68, 
+0x10e88, 0x10eb0, 0x0, 0x10fdc, 
+0x11008, 0x1102c, 0x111fc, 0x11050, 
+0x11078, 0x11108, 0x0, 0x0, 
+0x0, 0x1186c, 0x1193c, 0x11a14, 
+0x11ae4, 0x11b40, 0x11c1c, 0x11c44, 
+0x11d20, 0x11d48, 0x11ef0, 0x11f18, 
+0x120c0, 0x122b8, 0x1254c, 0x12460, 
+0x1254c, 0x12578, 0x120e8, 0x12290, 
+0x7273745f, 0x676d6969, 0x0, 0x12608, 
+0x12640, 0x12728, 0x13374, 0x133b4, 
+0x133cc, 0x7365746c, 0x6f6f7000, 0x0, 
+0x0, 0x13bbc, 0x13bfc, 0x13c8c, 
+0x13cd0, 0x13d34, 0x13dc0, 0x13df4, 
+0x13e7c, 0x13f14, 0x13fe4, 0x14024, 
+0x140a8, 0x140cc, 0x141dc, 0x646f4261, 
+0x73655067, 0x0, 0x0, 0x0, 
+0x0, 0x73746d61, 0x634c4e4b, 0x0, 
+0x6765746d, 0x636c6e6b, 0x0, 0x14ed8, 
+0x14ed8, 0x14b8c, 0x14bd8, 0x14c24, 
+0x14ed8, 0x7365746d, 0x61636163, 0x74000000, 
+0x0, 0x0 };
+static int tigon2FwData[/*(MAX_DATA_LEN/4) + 1*/] = {
+0x1, 
+0x1, 0x1, 0xc001fc, 0x3ffc, 
+0xc00000, 0x416c7465, 0x6f6e2041, 0x63654e49, 
+0x43205600, 0x0, 0x0, 0x0, 
+0x0, 0x0, 0x0, 0x416c7465, 
+0x6f6e2041, 0x63654e49, 0x43205600, 0x42424242, 
+0x0, 0x0, 0x0, 0x1ffffc, 
+0x1fff7c, 0x0, 0x0, 0x0, 
+0x0, 0x0, 0x0, 0x60cf00, 
+0x60, 0xcf000000, 0x0, 0x0, 
+0x0, 0x0, 0x0, 0x0, 
+0x0, 0x0, 0x0, 0x0, 
+0x0, 0x0, 0x0, 0x0, 
+0x0, 0x0, 0x0, 0x0, 
+0x0, 0x0, 0x3, 0x0, 
+0x1, 0x0, 0x0, 0x0, 
+0x1, 0x0, 0x1, 0x0, 
+0x0, 0x0, 0x0, 0x1, 
+0x1, 0x0, 0x0, 0x0, 
+0x0, 0x0, 0x1000000, 0x21000000, 
+0x12000140, 0x0, 0x0, 0x20000000, 
+0x120000a0, 0x0, 0x12000060, 0x12000180, 
+0x120001e0, 0x0, 0x0, 0x0, 
+0x1, 0x0, 0x0, 0x0, 
+0x0, 0x0, 0x0, 0x2, 
+0x0, 0x0, 0x30001, 0x1, 
+0x30201, 0x0, 0x0, 0x1010101, 
+0x1010100, 0x10100, 0x1010001, 0x10001, 
+0x1000101, 0x101, 0x0, 0x0 };
--- /dev/null
+++ b/os/boot.original/pc/etherif.h
@@ -1,0 +1,47 @@
+typedef struct RingBuf {
+	uchar	owner;
+	uchar	unused;
+	ushort	len;
+	uchar	pkt[sizeof(Etherpkt)];
+} RingBuf;
+
+enum {
+	Host		= 0,		/* buffer owned by host */
+	Interface	= 1,		/* buffer owned by card */
+
+	Nrb		= 32,		/* default number of receive buffers */
+	Ntb		= 8,		/* default number of transmit buffers */
+};
+
+typedef struct Ether Ether;
+struct Ether {
+	ISAConf;			/* hardware info */
+	int	ctlrno;
+	int	state;			/* 0: unfound, 1: found, 2: attaching */
+	int	tbdf;
+
+	void	(*attach)(Ether*);	/* filled in by reset routine */
+	void	(*transmit)(Ether*);
+	void	(*interrupt)(Ureg*, void*);
+	void	(*detach)(Ether*);
+	void	*ctlr;
+
+	ushort	nrb;			/* number of software receive buffers */
+	ushort	ntb;			/* number of software transmit buffers */
+	RingBuf *rb;			/* software receive buffers */
+	RingBuf *tb;			/* software transmit buffers */
+
+	ushort	rh;			/* first receive buffer belonging to host */
+	ushort	ri;			/* first receive buffer belonging to card */	
+
+	ushort	th;			/* first transmit buffer belonging to host */	
+	ushort	ti;			/* first transmit buffer belonging to card */
+	int	tbusy;			/* transmitter is busy */
+	int	mbps;			/* zero means link down */	
+};
+
+extern void etherrloop(Ether*, Etherpkt*, long);
+extern void addethercard(char*, int(*)(Ether*));
+
+#define NEXT(x, l)	(((x)+1)%(l))
+#define PREV(x, l)	(((x) == 0) ? (l)-1: (x)-1)
--- /dev/null
+++ b/os/boot.original/pc/etherigbe.c
@@ -1,0 +1,1741 @@
+/*
+ * bootstrap driver for
+ * Intel RS-82543GC Gigabit Ethernet PCI Controllers
+ * as found on the Intel PRO/1000[FT] Server Adapter.
+ * The older non-[FT] cards use the 82542 (LSI L2A1157) chip; no attempt
+ * is made to handle the older chip although it should be possible.
+ *
+ * updated just enough to cope with the
+ * Intel 8254[0347]NN Gigabit Ethernet Controller
+ * as found on the Intel PRO/1000 series of adapters:
+ *	82540EM Intel PRO/1000 MT
+ *	82543GC	Intel PRO/1000 T
+ *	82544EI Intel PRO/1000 XT
+ *	82547EI built-in
+ *
+ * The datasheet is not very clear about running on a big-endian system
+ * and this driver assumes little-endian throughout.
+ * To do:
+ *	GMII/MII
+ *	check recovery from receive no buffers condition
+ *	automatic ett adjustment
+ */
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+#include "etherif.h"
+#include "ethermii.h"
+
+enum {
+	Debug = 0,		/* mostly for X60 debugging */
+};
+enum {
+	i82542     = (0x1000<<16)|0x8086,
+	i82543gc   = (0x1004<<16)|0x8086,
+	i82544ei   = (0x1008<<16)|0x8086,
+	i82540em   = (0x100E<<16)|0x8086,
+	i82546eb   = (0x1010<<16)|0x8086,
+	i82547ei   = (0x1019<<16)|0x8086,
+	i82540eplp = (0x101E<<16)|0x8086,
+	i82547gi   = (0x1075<<16)|0x8086,
+	i82541gi   = (0x1076<<16)|0x8086,
+	i82541gi2  = (0x1077<<16)|0x8086,
+	i82546gb   = (0x1079<<16)|0x8086,
+	i82541pi   = (0x107c<<16)|0x8086,
+};
+
+/* compatibility with cpu kernels */
+#define iallocb allocb
+#ifndef CACHELINESZ
+#define CACHELINESZ	32		/* pentium & later */
+#endif
+
+/* from pci.c */
+enum
+{					/* command register (pcidev->pcr) */
+	IOen		= (1<<0),
+	MEMen		= (1<<1),
+	MASen		= (1<<2),
+	MemWrInv	= (1<<4),
+	PErrEn		= (1<<6),
+	SErrEn		= (1<<8),
+};
+enum {
+	Ctrl		= 0x00000000,	/* Device Control */
+	Status		= 0x00000008,	/* Device Status */
+	Eecd		= 0x00000010,	/* EEPROM/Flash Control/Data */
+	Ctrlext		= 0x00000018,	/* Extended Device Control */
+	Mdic		= 0x00000020,	/* MDI Control */
+	Fcal		= 0x00000028,	/* Flow Control Address Low */
+	Fcah		= 0x0000002C,	/* Flow Control Address High */
+	Fct		= 0x00000030,	/* Flow Control Type */
+	Icr		= 0x000000C0,	/* Interrupt Cause Read */
+	Ics		= 0x000000C8,	/* Interrupt Cause Set */
+	Ims		= 0x000000D0,	/* Interrupt Mask Set/Read */
+	Imc		= 0x000000D8,	/* Interrupt mask Clear */
+	Rctl		= 0x00000100,	/* Receive Control */
+	Fcttv		= 0x00000170,	/* Flow Control Transmit Timer Value */
+	Txcw		= 0x00000178,	/* Transmit Configuration Word */
+	Tctl		= 0x00000400,	/* Transmit Control */
+	Tipg		= 0x00000410,	/* Transmit IPG */
+	Tbt		= 0x00000448,	/* Transmit Burst Timer */
+	Ait		= 0x00000458,	/* Adaptive IFS Throttle */
+	Fcrtl		= 0x00002160,	/* Flow Control RX Threshold Low */
+	Fcrth		= 0x00002168,	/* Flow Control Rx Threshold High */
+	Rdbal		= 0x00002800,	/* Rdesc Base Address Low */
+	Rdbah		= 0x00002804,	/* Rdesc Base Address High */
+	Rdlen		= 0x00002808,	/* Receive Descriptor Length */
+	Rdh		= 0x00002810,	/* Receive Descriptor Head */
+	Rdt		= 0x00002818,	/* Receive Descriptor Tail */
+	Rdtr		= 0x00002820,	/* Receive Descriptor Timer Ring */
+	Rxdctl		= 0x00002828,	/* Receive Descriptor Control */
+	Radv		= 0x0000282C,	/* Receive Interrupt Absolute Delay Timer */
+	Txdmac		= 0x00003000,	/* Transfer DMA Control */
+	Ett		= 0x00003008,	/* Early Transmit Control */
+	Tdbal		= 0x00003800,	/* Tdesc Base Address Low */
+	Tdbah		= 0x00003804,	/* Tdesc Base Address High */
+	Tdlen		= 0x00003808,	/* Transmit Descriptor Length */
+	Tdh		= 0x00003810,	/* Transmit Descriptor Head */
+	Tdt		= 0x00003818,	/* Transmit Descriptor Tail */
+	Tidv		= 0x00003820,	/* Transmit Interrupt Delay Value */
+	Txdctl		= 0x00003828,	/* Transmit Descriptor Control */
+	Tadv		= 0x0000382C,	/* Transmit Interrupt Absolute Delay Timer */
+
+	Statistics	= 0x00004000,	/* Start of Statistics Area */
+	Gorcl		= 0x88/4,	/* Good Octets Received Count */
+	Gotcl		= 0x90/4,	/* Good Octets Transmitted Count */
+	Torl		= 0xC0/4,	/* Total Octets Received */
+	Totl		= 0xC8/4,	/* Total Octets Transmitted */
+	Nstatistics	= 64,
+
+	Rxcsum		= 0x00005000,	/* Receive Checksum Control */
+	Mta		= 0x00005200,	/* Multicast Table Array */
+	Ral		= 0x00005400,	/* Receive Address Low */
+	Rah		= 0x00005404,	/* Receive Address High */
+	Manc		= 0x00005820,	/* Management Control */
+};
+
+enum {					/* Ctrl */
+	Bem		= 0x00000002,	/* Big Endian Mode */
+	Prior		= 0x00000004,	/* Priority on the PCI bus */
+	Lrst		= 0x00000008,	/* Link Reset */
+	Asde		= 0x00000020,	/* Auto-Speed Detection Enable */
+	Slu		= 0x00000040,	/* Set Link Up */
+	Ilos		= 0x00000080,	/* Invert Loss of Signal (LOS) */
+	SspeedMASK	= 0x00000300,	/* Speed Selection */
+	SspeedSHIFT	= 8,
+	Sspeed10	= 0x00000000,	/* 10Mb/s */
+	Sspeed100	= 0x00000100,	/* 100Mb/s */
+	Sspeed1000	= 0x00000200,	/* 1000Mb/s */
+	Frcspd		= 0x00000800,	/* Force Speed */
+	Frcdplx		= 0x00001000,	/* Force Duplex */
+	SwdpinsloMASK	= 0x003C0000,	/* Software Defined Pins - lo nibble */
+	SwdpinsloSHIFT	= 18,
+	SwdpioloMASK	= 0x03C00000,	/* Software Defined Pins - I or O */
+	SwdpioloSHIFT	= 22,
+	Devrst		= 0x04000000,	/* Device Reset */
+	Rfce		= 0x08000000,	/* Receive Flow Control Enable */
+	Tfce		= 0x10000000,	/* Transmit Flow Control Enable */
+	Vme		= 0x40000000,	/* VLAN Mode Enable */
+};
+
+/*
+ * can't find Tckok nor Rbcok in any Intel docs,
+ * but even 82543gc docs define Lanid.
+ */
+enum {					/* Status */
+	Lu		= 0x00000002,	/* Link Up */
+	Lanid		= 0x0000000C,	/* mask for Lan ID. (function id) */
+//	Tckok		= 0x00000004,	/* Transmit clock is running */
+//	Rbcok		= 0x00000008,	/* Receive clock is running */
+	Txoff		= 0x00000010,	/* Transmission Paused */
+	Tbimode		= 0x00000020,	/* TBI Mode Indication */
+	SpeedMASK	= 0x000000C0,
+	Speed10		= 0x00000000,	/* 10Mb/s */
+	Speed100	= 0x00000040,	/* 100Mb/s */
+	Speed1000	= 0x00000080,	/* 1000Mb/s */
+	Mtxckok		= 0x00000400,	/* MTX clock is running */
+	Pci66		= 0x00000800,	/* PCI Bus speed indication */
+	Bus64		= 0x00001000,	/* PCI Bus width indication */
+};
+
+enum {					/* Ctrl and Status */
+	Fd		= 0x00000001,	/* Full-Duplex */
+	AsdvMASK	= 0x00000300,
+	Asdv10		= 0x00000000,	/* 10Mb/s */
+	Asdv100		= 0x00000100,	/* 100Mb/s */
+	Asdv1000	= 0x00000200,	/* 1000Mb/s */
+};
+
+enum {					/* Eecd */
+	Sk		= 0x00000001,	/* Clock input to the EEPROM */
+	Cs		= 0x00000002,	/* Chip Select */
+	Di		= 0x00000004,	/* Data Input to the EEPROM */
+	Do		= 0x00000008,	/* Data Output from the EEPROM */
+	Areq		= 0x00000040,	/* EEPROM Access Request */
+	Agnt		= 0x00000080,	/* EEPROM Access Grant */
+	Eepresent	= 0x00000100,	/* EEPROM Present */
+	Eesz256		= 0x00000200,	/* EEPROM is 256 words not 64 */
+	Eeszaddr	= 0x00000400,	/* EEPROM size for 8254[17] */
+	Spi		= 0x00002000,	/* EEPROM is SPI not Microwire */
+};
+
+enum {					/* Ctrlext */
+	Gpien		= 0x0000000F,	/* General Purpose Interrupt Enables */
+	SwdpinshiMASK	= 0x000000F0,	/* Software Defined Pins - hi nibble */
+	SwdpinshiSHIFT	= 4,
+	SwdpiohiMASK	= 0x00000F00,	/* Software Defined Pins - I or O */
+	SwdpiohiSHIFT	= 8,
+	Asdchk		= 0x00001000,	/* ASD Check */
+	Eerst		= 0x00002000,	/* EEPROM Reset */
+	Ips		= 0x00004000,	/* Invert Power State */
+	Spdbyps		= 0x00008000,	/* Speed Select Bypass */
+};
+
+enum {					/* EEPROM content offsets */
+	Ea		= 0x00,		/* Ethernet Address */
+	Cf		= 0x03,		/* Compatibility Field */
+	Pba		= 0x08,		/* Printed Board Assembly number */
+	Icw1		= 0x0A,		/* Initialization Control Word 1 */
+	Sid		= 0x0B,		/* Subsystem ID */
+	Svid		= 0x0C,		/* Subsystem Vendor ID */
+	Did		= 0x0D,		/* Device ID */
+	Vid		= 0x0E,		/* Vendor ID */
+	Icw2		= 0x0F,		/* Initialization Control Word 2 */
+};
+
+enum {					/* Mdic */
+	MDIdMASK	= 0x0000FFFF,	/* Data */
+	MDIdSHIFT	= 0,
+	MDIrMASK	= 0x001F0000,	/* PHY Register Address */
+	MDIrSHIFT	= 16,
+	MDIpMASK	= 0x03E00000,	/* PHY Address */
+	MDIpSHIFT	= 21,
+	MDIwop		= 0x04000000,	/* Write Operation */
+	MDIrop		= 0x08000000,	/* Read Operation */
+	MDIready	= 0x10000000,	/* End of Transaction */
+	MDIie		= 0x20000000,	/* Interrupt Enable */
+	MDIe		= 0x40000000,	/* Error */
+};
+
+enum {					/* Icr, Ics, Ims, Imc */
+	Txdw		= 0x00000001,	/* Transmit Descriptor Written Back */
+	Txqe		= 0x00000002,	/* Transmit Queue Empty */
+	Lsc		= 0x00000004,	/* Link Status Change */
+	Rxseq		= 0x00000008,	/* Receive Sequence Error */
+	Rxdmt0		= 0x00000010,	/* Rdesc Minimum Threshold Reached */
+	Rxo		= 0x00000040,	/* Receiver Overrun */
+	Rxt0		= 0x00000080,	/* Receiver Timer Interrupt */
+	Mdac		= 0x00000200,	/* MDIO Access Completed */
+	Rxcfg		= 0x00000400,	/* Receiving /C/ ordered sets */
+	Gpi0		= 0x00000800,	/* General Purpose Interrupts */
+	Gpi1		= 0x00001000,
+	Gpi2		= 0x00002000,
+	Gpi3		= 0x00004000,
+};
+
+/*
+ * The Mdic register isn't implemented on the 82543GC,
+ * the software defined pins are used instead.
+ * These definitions work for the Intel PRO/1000 T Server Adapter.
+ * The direction pin bits are read from the EEPROM.
+ */
+enum {
+	Mdd		= ((1<<2)<<SwdpinsloSHIFT),	/* data */
+	Mddo		= ((1<<2)<<SwdpioloSHIFT),	/* pin direction */
+	Mdc		= ((1<<3)<<SwdpinsloSHIFT),	/* clock */
+	Mdco		= ((1<<3)<<SwdpioloSHIFT),	/* pin direction */
+	Mdr		= ((1<<0)<<SwdpinshiSHIFT),	/* reset */
+	Mdro		= ((1<<0)<<SwdpiohiSHIFT),	/* pin direction */
+};
+
+enum {					/* Txcw */
+	TxcwFd		= 0x00000020,	/* Full Duplex */
+	TxcwHd		= 0x00000040,	/* Half Duplex */
+	TxcwPauseMASK	= 0x00000180,	/* Pause */
+	TxcwPauseSHIFT	= 7,
+	TxcwPs		= (1<<TxcwPauseSHIFT),	/* Pause Supported */
+	TxcwAs		= (2<<TxcwPauseSHIFT),	/* Asymmetric FC desired */
+	TxcwRfiMASK	= 0x00003000,	/* Remote Fault Indication */
+	TxcwRfiSHIFT	= 12,
+	TxcwNpr		= 0x00008000,	/* Next Page Request */
+	TxcwConfig	= 0x40000000,	/* Transmit COnfig Control */
+	TxcwAne		= 0x80000000,	/* Auto-Negotiation Enable */
+};
+
+enum {					/* Rctl */
+	Rrst		= 0x00000001,	/* Receiver Software Reset */
+	Ren		= 0x00000002,	/* Receiver Enable */
+	Sbp		= 0x00000004,	/* Store Bad Packets */
+	Upe		= 0x00000008,	/* Unicast Promiscuous Enable */
+	Mpe		= 0x00000010,	/* Multicast Promiscuous Enable */
+	Lpe		= 0x00000020,	/* Long Packet Reception Enable */
+	LbmMASK		= 0x000000C0,	/* Loopback Mode */
+	LbmOFF		= 0x00000000,	/* No Loopback */
+	LbmTBI		= 0x00000040,	/* TBI Loopback */
+	LbmMII		= 0x00000080,	/* GMII/MII Loopback */
+	LbmXCVR		= 0x000000C0,	/* Transceiver Loopback */
+	RdtmsMASK	= 0x00000300,	/* Rdesc Minimum Threshold Size */
+	RdtmsHALF	= 0x00000000,	/* Threshold is 1/2 Rdlen */
+	RdtmsQUARTER	= 0x00000100,	/* Threshold is 1/4 Rdlen */
+	RdtmsEIGHTH	= 0x00000200,	/* Threshold is 1/8 Rdlen */
+	MoMASK		= 0x00003000,	/* Multicast Offset */
+	Bam		= 0x00008000,	/* Broadcast Accept Mode */
+	BsizeMASK	= 0x00030000,	/* Receive Buffer Size */
+	Bsize2048	= 0x00000000,
+	Bsize1024	= 0x00010000,
+	Bsize512	= 0x00020000,
+	Bsize256	= 0x00030000,
+	Vfe		= 0x00040000,	/* VLAN Filter Enable */
+	Cfien		= 0x00080000,	/* Canonical Form Indicator Enable */
+	Cfi		= 0x00100000,	/* Canonical Form Indicator value */
+	Dpf		= 0x00400000,	/* Discard Pause Frames */
+	Pmcf		= 0x00800000,	/* Pass MAC Control Frames */
+	Bsex		= 0x02000000,	/* Buffer Size Extension */
+	Secrc		= 0x04000000,	/* Strip CRC from incoming packet */
+};
+
+enum {					/* Tctl */
+	Trst		= 0x00000001,	/* Transmitter Software Reset */
+	Ten		= 0x00000002,	/* Transmit Enable */
+	Psp		= 0x00000008,	/* Pad Short Packets */
+	CtMASK		= 0x00000FF0,	/* Collision Threshold */
+	CtSHIFT		= 4,
+	ColdMASK	= 0x003FF000,	/* Collision Distance */
+	ColdSHIFT	= 12,
+	Swxoff		= 0x00400000,	/* Sofware XOFF Transmission */
+	Pbe		= 0x00800000,	/* Packet Burst Enable */
+	Rtlc		= 0x01000000,	/* Re-transmit on Late Collision */
+	Nrtu		= 0x02000000,	/* No Re-transmit on Underrrun */
+};
+
+enum {					/* [RT]xdctl */
+	PthreshMASK	= 0x0000003F,	/* Prefetch Threshold */
+	PthreshSHIFT	= 0,
+	HthreshMASK	= 0x00003F00,	/* Host Threshold */
+	HthreshSHIFT	= 8,
+	WthreshMASK	= 0x003F0000,	/* Writebacj Threshold */
+	WthreshSHIFT	= 16,
+	Gran		= 0x01000000,	/* Granularity */
+};
+
+enum {					/* Rxcsum */
+	PcssMASK	= 0x000000FF,	/* Packet Checksum Start */
+	PcssSHIFT	= 0,
+	Ipofl		= 0x00000100,	/* IP Checksum Off-load Enable */
+	Tuofl		= 0x00000200,	/* TCP/UDP Checksum Off-load Enable */
+};
+
+enum {					/* Manc */
+	Arpen		= 0x00002000,	/* Enable ARP Request Filtering */
+};
+
+typedef struct Rdesc {			/* Receive Descriptor */
+	uint	addr[2];
+	ushort	length;
+	ushort	checksum;
+	uchar	status;
+	uchar	errors;
+	ushort	special;
+} Rdesc;
+
+enum {					/* Rdesc status */
+	Rdd		= 0x01,		/* Descriptor Done */
+	Reop		= 0x02,		/* End of Packet */
+	Ixsm		= 0x04,		/* Ignore Checksum Indication */
+	Vp		= 0x08,		/* Packet is 802.1Q (matched VET) */
+	Tcpcs		= 0x20,		/* TCP Checksum Calculated on Packet */
+	Ipcs		= 0x40,		/* IP Checksum Calculated on Packet */
+	Pif		= 0x80,		/* Passed in-exact filter */
+};
+
+enum {					/* Rdesc errors */
+	Ce		= 0x01,		/* CRC Error or Alignment Error */
+	Se		= 0x02,		/* Symbol Error */
+	Seq		= 0x04,		/* Sequence Error */
+	Cxe		= 0x10,		/* Carrier Extension Error */
+	Tcpe		= 0x20,		/* TCP/UDP Checksum Error */
+	Ipe		= 0x40,		/* IP Checksum Error */
+	Rxe		= 0x80,		/* RX Data Error */
+};
+
+typedef struct Tdesc {			/* Legacy+Normal Transmit Descriptor */
+	uint	addr[2];
+	uint	control;		/* varies with descriptor type */
+	uint	status;			/* varies with descriptor type */
+} Tdesc;
+
+enum {					/* Tdesc control */
+	LenMASK		= 0x000FFFFF,	/* Data/Packet Length Field */
+	LenSHIFT	= 0,
+	DtypeCD		= 0x00000000,	/* Data Type 'Context Descriptor' */
+	DtypeDD		= 0x00100000,	/* Data Type 'Data Descriptor' */
+	PtypeTCP	= 0x01000000,	/* TCP/UDP Packet Type (CD) */
+	Teop		= 0x01000000,	/* End of Packet (DD) */
+	PtypeIP		= 0x02000000,	/* IP Packet Type (CD) */
+	Ifcs		= 0x02000000,	/* Insert FCS (DD) */
+	Tse		= 0x04000000,	/* TCP Segmentation Enable */
+	Rs		= 0x08000000,	/* Report Status */
+	Rps		= 0x10000000,	/* Report Status Sent */
+	Dext		= 0x20000000,	/* Descriptor Extension */
+	Vle		= 0x40000000,	/* VLAN Packet Enable */
+	Ide		= 0x80000000,	/* Interrupt Delay Enable */
+};
+
+enum {					/* Tdesc status */
+	Tdd		= 0x00000001,	/* Descriptor Done */
+	Ec		= 0x00000002,	/* Excess Collisions */
+	Lc		= 0x00000004,	/* Late Collision */
+	Tu		= 0x00000008,	/* Transmit Underrun */
+	CssMASK		= 0x0000FF00,	/* Checksum Start Field */
+	CssSHIFT	= 8,
+};
+
+enum {
+	Nrdesc		= 32,		/* multiple of 8 */
+	Ntdesc		= 8,		/* multiple of 8 */
+};
+
+typedef struct Ctlr Ctlr;
+typedef struct Ctlr {
+	int	port;
+	Pcidev*	pcidev;
+	Ctlr*	next;
+	int	active;
+	int	id;
+	int	cls;
+	ushort	eeprom[0x40];
+
+	int*	nic;
+	Lock	imlock;
+	int	im;			/* interrupt mask */
+
+	Mii*	mii;
+
+	Lock	slock;
+	uint	statistics[Nstatistics];
+
+	uchar	ra[Eaddrlen];		/* receive address */
+	ulong	mta[128];		/* multicast table array */
+
+	Rdesc*	rdba;			/* receive descriptor base address */
+	Block**	rb;			/* receive buffers */
+	int	rdh;			/* receive descriptor head */
+	int	rdt;			/* receive descriptor tail */
+
+	Tdesc*	tdba;			/* transmit descriptor base address */
+	Lock	tdlock;
+	Block**	tb;			/* transmit buffers */
+	int	tdh;			/* transmit descriptor head */
+	int	tdt;			/* transmit descriptor tail */
+	int	ett;			/* early transmit threshold */
+
+	int	txcw;
+	int	fcrtl;
+	int	fcrth;
+
+	/* bootstrap goo */
+	Block*	bqhead;	/* transmission queue */
+	Block*	bqtail;
+} Ctlr;
+
+static Ctlr* ctlrhead;
+static Ctlr* ctlrtail;
+
+#define csr32r(c, r)	(*((c)->nic+((r)/4)))
+#define csr32w(c, r, v)	(*((c)->nic+((r)/4)) = (v))
+
+static void
+igbeim(Ctlr* ctlr, int im)
+{
+	ilock(&ctlr->imlock);
+	ctlr->im |= im;
+	csr32w(ctlr, Ims, ctlr->im);
+	iunlock(&ctlr->imlock);
+}
+
+static void
+igbeattach(Ether* edev)
+{
+	int ctl;
+	Ctlr *ctlr;
+
+	/*
+	 * To do here:
+	 *	one-time stuff;
+	 *	start off a kproc for link status change:
+	 *		adjust queue length depending on speed;
+	 *		flow control.
+	 *	more needed here...
+	 */
+	ctlr = edev->ctlr;
+	igbeim(ctlr, 0);
+	ctl = csr32r(ctlr, Rctl)|Ren;
+	csr32w(ctlr, Rctl, ctl);
+	ctl = csr32r(ctlr, Tctl)|Ten;
+	csr32w(ctlr, Tctl, ctl);
+}
+
+static char* statistics[Nstatistics] = {
+	"CRC Error",
+	"Alignment Error",
+	"Symbol Error",
+	"RX Error",
+	"Missed Packets",
+	"Single Collision",
+	"Excessive Collisions",
+	"Multiple Collision",
+	"Late Collisions",
+	nil,
+	"Collision",
+	"Transmit Underrun",
+	"Defer",
+	"Transmit - No CRS",
+	"Sequence Error",
+	"Carrier Extension Error",
+	"Receive Error Length",
+	nil,
+	"XON Received",
+	"XON Transmitted",
+	"XOFF Received",
+	"XOFF Transmitted",
+	"FC Received Unsupported",
+	"Packets Received (64 Bytes)",
+	"Packets Received (65-127 Bytes)",
+	"Packets Received (128-255 Bytes)",
+	"Packets Received (256-511 Bytes)",
+	"Packets Received (512-1023 Bytes)",
+	"Packets Received (1024-1522 Bytes)",
+	"Good Packets Received",
+	"Broadcast Packets Received",
+	"Multicast Packets Received",
+	"Good Packets Transmitted",
+	nil,
+	"Good Octets Received",
+	nil,
+	"Good Octets Transmitted",
+	nil,
+	nil,
+	nil,
+	"Receive No Buffers",
+	"Receive Undersize",
+	"Receive Fragment",
+	"Receive Oversize",
+	"Receive Jabber",
+	nil,
+	nil,
+	nil,
+	"Total Octets Received",
+	nil,
+	"Total Octets Transmitted",
+	nil,
+	"Total Packets Received",
+	"Total Packets Transmitted",
+	"Packets Transmitted (64 Bytes)",
+	"Packets Transmitted (65-127 Bytes)",
+	"Packets Transmitted (128-255 Bytes)",
+	"Packets Transmitted (256-511 Bytes)",
+	"Packets Transmitted (512-1023 Bytes)",
+	"Packets Transmitted (1024-1522 Bytes)",
+	"Multicast Packets Transmitted",
+	"Broadcast Packets Transmitted",
+	"TCP Segmentation Context Transmitted",
+	"TCP Segmentation Context Fail",
+};
+
+static void
+txstart(Ether *edev)
+{
+	int tdh, tdt, len, olen;
+	Ctlr *ctlr = edev->ctlr;
+	Block *bp;
+	Tdesc *tdesc;
+
+	/*
+	 * Try to fill the ring back up, moving buffers from the transmit q.
+	 */
+	tdh = PREV(ctlr->tdh, Ntdesc);
+	for(tdt = ctlr->tdt; tdt != tdh; tdt = NEXT(tdt, Ntdesc)){
+		/* pull off the head of the transmission queue */
+		if((bp = ctlr->bqhead) == nil)		/* was qget(edev->oq) */
+			break;
+		ctlr->bqhead = bp->next;
+		if (ctlr->bqtail == bp)
+			ctlr->bqtail = nil;
+		len = olen = BLEN(bp);
+
+		/*
+		 * if packet is too short, make it longer rather than relying
+		 * on ethernet interface to pad it and complain so the caller
+		 * will get fixed.  I don't think Psp is working right, or it's
+		 * getting cleared.
+		 */
+		if (len < ETHERMINTU) {
+			if (bp->rp + ETHERMINTU <= bp->lim)
+				bp->wp = bp->rp + ETHERMINTU;
+			else
+				bp->wp = bp->lim;
+			len = BLEN(bp);
+			print("txstart: extended short pkt %d -> %d bytes\n",
+				olen, len);
+		}
+
+		/* set up a descriptor for it */
+		tdesc = &ctlr->tdba[tdt];
+		tdesc->addr[0] = PCIWADDR(bp->rp);
+		tdesc->addr[1] = 0;
+		tdesc->control = /* Ide| */ Rs|Dext|Ifcs|Teop|DtypeDD|len;
+		tdesc->status = 0;
+
+		ctlr->tb[tdt] = bp;
+	}
+	ctlr->tdt = tdt;
+	csr32w(ctlr, Tdt, tdt);
+	igbeim(ctlr, Txdw);
+}
+
+static Block *
+fromringbuf(Ether *ether)
+{
+	RingBuf *tb = &ether->tb[ether->ti];
+	Block *bp = allocb(tb->len);
+
+	memmove(bp->wp, tb->pkt, tb->len);
+	memmove(bp->wp+Eaddrlen, ether->ea, Eaddrlen);
+	bp->wp += tb->len;
+	return bp;
+}
+
+static void
+igbetransmit(Ether* edev)
+{
+	Block *bp;
+	Ctlr *ctlr;
+	Tdesc *tdesc;
+	RingBuf *tb;
+	int tdh;
+
+	/*
+	 * For now there are no smarts here. Tuning comes later.
+	 */
+	ctlr = edev->ctlr;
+	ilock(&ctlr->tdlock);
+
+	/*
+	 * Free any completed packets
+	 * - try to get the soft tdh to catch the tdt;
+	 * - if the packet had an underrun bump the threshold
+	 *   - the Tu bit doesn't seem to ever be set, perhaps
+	 *     because Rs mode is used?
+	 */
+	tdh = ctlr->tdh;
+	for(;;){
+		tdesc = &ctlr->tdba[tdh];
+		if(!(tdesc->status & Tdd))
+			break;
+		if(tdesc->status & Tu){
+			ctlr->ett++;
+			csr32w(ctlr, Ett, ctlr->ett);
+		}
+		tdesc->status = 0;
+		if(ctlr->tb[tdh] != nil){
+			freeb(ctlr->tb[tdh]);
+			ctlr->tb[tdh] = nil;
+		}
+		tdh = NEXT(tdh, Ntdesc);
+	}
+	ctlr->tdh = tdh;
+
+	/* copy packets from the software RingBuf to the transmission q */
+	/* from boot ether83815.c */
+	while((tb = &edev->tb[edev->ti])->owner == Interface){
+		bp = fromringbuf(edev);
+
+		/* put the buffer on the transmit queue */
+		if(ctlr->bqhead)
+			ctlr->bqtail->next = bp;
+		else
+			ctlr->bqhead = bp;
+		ctlr->bqtail = bp;
+
+		txstart(edev);		/* kick transmitter */
+		tb->owner = Host;	/* give descriptor back */
+
+		edev->ti = NEXT(edev->ti, edev->ntb);
+	}
+
+	iunlock(&ctlr->tdlock);
+}
+
+static void
+igbereplenish(Ctlr* ctlr)
+{
+	int rdt;
+	Block *bp;
+	Rdesc *rdesc;
+
+	rdt = ctlr->rdt;
+	while(NEXT(rdt, Nrdesc) != ctlr->rdh){
+		rdesc = &ctlr->rdba[rdt];
+		if(ctlr->rb[rdt] != nil){
+			/* nothing to do */
+		}
+		else if((bp = iallocb(2048)) != nil){
+			ctlr->rb[rdt] = bp;
+			rdesc->addr[0] = PCIWADDR(bp->rp);
+			rdesc->addr[1] = 0;
+		}
+		else
+			break;
+		rdesc->status = 0;
+
+		rdt = NEXT(rdt, Nrdesc);
+	}
+	ctlr->rdt = rdt;
+	csr32w(ctlr, Rdt, rdt);
+}
+
+static void
+toringbuf(Ether *ether, Block *bp)
+{
+	RingBuf *rb = &ether->rb[ether->ri];
+
+	if (rb->owner == Interface) {
+		rb->len = BLEN(bp);
+		memmove(rb->pkt, bp->rp, rb->len);
+		rb->owner = Host;
+		ether->ri = NEXT(ether->ri, ether->nrb);
+	}
+	/* else no one is expecting packets from the network */
+}
+
+static void
+igbeinterrupt(Ureg*, void* arg)
+{
+	Block *bp;
+	Ctlr *ctlr;
+	Ether *edev;
+	Rdesc *rdesc;
+	int icr, im, rdh, txdw = 0;
+
+	edev = arg;
+	ctlr = edev->ctlr;
+
+	ilock(&ctlr->imlock);
+	csr32w(ctlr, Imc, ~0);
+	im = ctlr->im;
+
+	for(icr = csr32r(ctlr, Icr); icr & ctlr->im; icr = csr32r(ctlr, Icr)){
+		/*
+		 * Link status changed.
+		 */
+		if(icr & (Rxseq|Lsc)){
+			/*
+			 * should be more here...
+			 */
+		}
+
+		/*
+		 * Process any received packets.
+		 */
+		rdh = ctlr->rdh;
+		for(;;){
+			rdesc = &ctlr->rdba[rdh];
+			if(!(rdesc->status & Rdd))
+				break;
+			if ((rdesc->status & Reop) && rdesc->errors == 0) {
+				bp = ctlr->rb[rdh];
+				ctlr->rb[rdh] = nil;
+				/*
+				 * it appears that the original 82543 needed
+				 * to have the Ethernet CRC excluded, but that
+				 * the newer chips do not?
+				 */
+				bp->wp += rdesc->length /* -4 */;
+				toringbuf(edev, bp);
+				freeb(bp);
+			} else if ((rdesc->status & Reop) && rdesc->errors)
+				print("igbe: input packet error 0x%ux\n",
+					rdesc->errors);
+			rdesc->status = 0;
+			rdh = NEXT(rdh, Nrdesc);
+		}
+		ctlr->rdh = rdh;
+
+		if(icr & Rxdmt0)
+			igbereplenish(ctlr);
+		if(icr & Txdw){
+			im &= ~Txdw;
+			txdw++;
+		}
+	}
+
+	ctlr->im = im;
+	csr32w(ctlr, Ims, im);
+	iunlock(&ctlr->imlock);
+
+	if(txdw)
+		igbetransmit(edev);
+}
+
+static int
+igbeinit(Ether* edev)
+{
+	int csr, i, r, ctrl;
+	MiiPhy *phy;
+	Ctlr *ctlr;
+
+	ctlr = edev->ctlr;
+
+	/*
+	 * Set up the receive addresses.
+	 * There are 16 addresses. The first should be the MAC address.
+	 * The others are cleared and not marked valid (MS bit of Rah).
+	 */
+	csr = (edev->ea[3]<<24)|(edev->ea[2]<<16)|(edev->ea[1]<<8)|edev->ea[0];
+	csr32w(ctlr, Ral, csr);
+	csr = 0x80000000|(edev->ea[5]<<8)|edev->ea[4];
+	csr32w(ctlr, Rah, csr);
+	for(i = 1; i < 16; i++){
+		csr32w(ctlr, Ral+i*8, 0);
+		csr32w(ctlr, Rah+i*8, 0);
+	}
+
+	/*
+	 * Clear the Multicast Table Array.
+	 * It's a 4096 bit vector accessed as 128 32-bit registers.
+	 */
+	for(i = 0; i < 128; i++)
+		csr32w(ctlr, Mta+i*4, 0);
+
+	/*
+	 * Receive initialisation.
+	 * Mostly defaults from the datasheet, will
+	 * need some tuning for performance:
+	 *	Rctl	descriptor mimimum threshold size
+	 *		discard pause frames
+	 *		strip CRC
+	 * 	Rdtr	interrupt delay
+	 * 	Rxdctl	all the thresholds
+	 */
+	csr32w(ctlr, Rctl, 0);
+
+	/*
+	 * Allocate the descriptor ring and load its
+	 * address and length into the NIC.
+	 */
+	ctlr->rdba = xspanalloc(Nrdesc*sizeof(Rdesc), 128 /* was 16 */, 0);
+	csr32w(ctlr, Rdbal, PCIWADDR(ctlr->rdba));
+	csr32w(ctlr, Rdbah, 0);
+	csr32w(ctlr, Rdlen, Nrdesc*sizeof(Rdesc));
+
+	/*
+	 * Initialise the ring head and tail pointers and
+	 * populate the ring with Blocks.
+	 * The datasheet says the tail pointer is set to beyond the last
+	 * descriptor hardware can process, which implies the initial
+	 * condition is Rdh == Rdt. However, experience shows Rdt must
+	 * always be 'behind' Rdh; the replenish routine ensures this.
+	 */
+	ctlr->rdh = 0;
+	csr32w(ctlr, Rdh, ctlr->rdh);
+	ctlr->rdt = 0;
+	csr32w(ctlr, Rdt, ctlr->rdt);
+	ctlr->rb = malloc(sizeof(Block*)*Nrdesc);
+	igbereplenish(ctlr);
+
+	/*
+	 * Set up Rctl but don't enable receiver (yet).
+	 */
+	csr32w(ctlr, Rdtr, 0);
+	switch(ctlr->id){
+	case i82540em:
+	case i82540eplp:
+	case i82541gi:
+	case i82541gi2:
+	case i82541pi:
+	case i82546gb:
+	case i82546eb:
+	case i82547gi:
+		csr32w(ctlr, Radv, 64);
+		break;
+	}
+	csr32w(ctlr, Rxdctl, (8<<WthreshSHIFT)|(8<<HthreshSHIFT)|4);
+	/*
+	 * Enable checksum offload.
+	 */
+	csr32w(ctlr, Rxcsum, Tuofl|Ipofl|(ETHERHDRSIZE<<PcssSHIFT));
+
+	csr32w(ctlr, Rctl, Dpf|Bsize2048|Bam|RdtmsHALF);
+	igbeim(ctlr, Rxt0|Rxo|Rxdmt0|Rxseq);
+
+	/*
+	 * Transmit initialisation.
+	 * Mostly defaults from the datasheet, will
+	 * need some tuning for performance. The normal mode will
+	 * be full-duplex and things to tune for half-duplex are
+	 *	Tctl	re-transmit on late collision
+	 *	Tipg	all IPG times
+	 *	Tbt	burst timer
+	 *	Ait	adaptive IFS throttle
+	 * and in general
+	 *	Txdmac	packet prefetching
+	 *	Ett	transmit early threshold
+	 *	Tidv	interrupt delay value
+	 *	Txdctl	all the thresholds
+	 */
+	csr32w(ctlr, Tctl, (0x0F<<CtSHIFT)|Psp|(66<<ColdSHIFT));	/* Fd */
+	switch(ctlr->id){
+	default:
+		r = 6;
+		break;
+	case i82543gc:
+	case i82544ei:
+	case i82547ei:
+	case i82540em:
+	case i82540eplp:
+	case i82541gi:
+	case i82541gi2:
+	case i82541pi:
+	case i82546gb:
+	case i82546eb:
+	case i82547gi:
+		r = 8;
+		break;
+	}
+	csr32w(ctlr, Tipg, (6<<20)|(8<<10)|r);
+	csr32w(ctlr, Ait, 0);
+	csr32w(ctlr, Txdmac, 0);
+	csr32w(ctlr, Tidv, 128);
+
+	/*
+	 * Allocate the descriptor ring and load its
+	 * address and length into the NIC.
+	 */
+	ctlr->tdba = xspanalloc(Ntdesc*sizeof(Tdesc), 128 /* was 16 */, 0);
+	csr32w(ctlr, Tdbal, PCIWADDR(ctlr->tdba));
+	csr32w(ctlr, Tdbah, 0);
+	csr32w(ctlr, Tdlen, Ntdesc*sizeof(Tdesc));
+
+	/*
+	 * Initialise the ring head and tail pointers.
+	 */
+	ctlr->tdh = 0;
+	csr32w(ctlr, Tdh, ctlr->tdh);
+	ctlr->tdt = 0;
+	csr32w(ctlr, Tdt, ctlr->tdt);
+	ctlr->tb = malloc(sizeof(Block*)*Ntdesc);
+//	ctlr->im |= Txqe|Txdw;
+
+	r = (4<<WthreshSHIFT)|(4<<HthreshSHIFT)|(8<<PthreshSHIFT);
+	switch(ctlr->id){
+	default:
+		break;
+	case i82540em:
+	case i82540eplp:
+	case i82547gi:
+	case i82541pi:
+	case i82546gb:
+	case i82546eb:
+	case i82541gi:
+	case i82541gi2:
+		r = csr32r(ctlr, Txdctl);
+		r &= ~WthreshMASK;
+		r |= Gran|(4<<WthreshSHIFT);
+
+		csr32w(ctlr, Tadv, 64);
+		break;
+	}
+	csr32w(ctlr, Txdctl, r);
+
+	r = csr32r(ctlr, Tctl);
+	r |= Ten;
+	csr32w(ctlr, Tctl, r);
+
+	if(ctlr->mii == nil || ctlr->mii->curphy == nil) {
+		print("igbe: no mii (yet)\n");
+		return 0;
+	}
+	/* wait for the link to come up */
+	if (miistatus(ctlr->mii) < 0)
+		return -1;
+	print("igbe: phy: ");
+	phy = ctlr->mii->curphy;
+	if (phy->fd)
+		print("full duplex");
+	else
+		print("half duplex");
+	print(", %d Mb/s\n", phy->speed);
+
+	/*
+	 * Flow control.
+	 */
+	ctrl = csr32r(ctlr, Ctrl);
+	if(phy->rfc)
+		ctrl |= Rfce;
+	if(phy->tfc)
+		ctrl |= Tfce;
+	csr32w(ctlr, Ctrl, ctrl);
+
+	return 0;
+}
+
+static int
+i82543mdior(Ctlr* ctlr, int n)
+{
+	int ctrl, data, i, r;
+
+	/*
+	 * Read n bits from the Management Data I/O Interface.
+	 */
+	ctrl = csr32r(ctlr, Ctrl);
+	r = (ctrl & ~Mddo)|Mdco;
+	data = 0;
+	for(i = n-1; i >= 0; i--){
+		if(csr32r(ctlr, Ctrl) & Mdd)
+			data |= (1<<i);
+		csr32w(ctlr, Ctrl, Mdc|r);
+		csr32w(ctlr, Ctrl, r);
+	}
+	csr32w(ctlr, Ctrl, ctrl);
+
+	return data;
+}
+
+static int
+i82543mdiow(Ctlr* ctlr, int bits, int n)
+{
+	int ctrl, i, r;
+
+	/*
+	 * Write n bits to the Management Data I/O Interface.
+	 */
+	ctrl = csr32r(ctlr, Ctrl);
+	r = Mdco|Mddo|ctrl;
+	for(i = n-1; i >= 0; i--){
+		if(bits & (1<<i))
+			r |= Mdd;
+		else
+			r &= ~Mdd;
+		csr32w(ctlr, Ctrl, Mdc|r);
+		csr32w(ctlr, Ctrl, r);
+	}
+	csr32w(ctlr, Ctrl, ctrl);
+
+	return 0;
+}
+
+static int
+i82543miimir(Mii* mii, int pa, int ra)
+{
+	int data;
+	Ctlr *ctlr;
+
+	ctlr = mii->ctlr;
+
+	/*
+	 * MII Management Interface Read.
+	 *
+	 * Preamble;
+	 * ST+OP+PHYAD+REGAD;
+	 * TA + 16 data bits.
+	 */
+	i82543mdiow(ctlr, 0xFFFFFFFF, 32);
+	i82543mdiow(ctlr, 0x1800|(pa<<5)|ra, 14);
+	data = i82543mdior(ctlr, 18);
+
+	if(data & 0x10000)
+		return -1;
+
+	return data & 0xFFFF;
+}
+
+static int
+i82543miimiw(Mii* mii, int pa, int ra, int data)
+{
+	Ctlr *ctlr;
+
+	ctlr = mii->ctlr;
+
+	/*
+	 * MII Management Interface Write.
+	 *
+	 * Preamble;
+	 * ST+OP+PHYAD+REGAD+TA + 16 data bits;
+	 * Z.
+	 */
+	i82543mdiow(ctlr, 0xFFFFFFFF, 32);
+	data &= 0xFFFF;
+	data |= (0x05<<(5+5+2+16))|(pa<<(5+2+16))|(ra<<(2+16))|(0x02<<16);
+	i82543mdiow(ctlr, data, 32);
+
+	return 0;
+}
+
+static int
+igbemiimir(Mii* mii, int pa, int ra)
+{
+	Ctlr *ctlr;
+	int mdic, timo;
+
+	ctlr = mii->ctlr;
+
+	csr32w(ctlr, Mdic, MDIrop|(pa<<MDIpSHIFT)|(ra<<MDIrSHIFT));
+	mdic = 0;
+	for(timo = 64; timo; timo--){
+		mdic = csr32r(ctlr, Mdic);
+		if(mdic & (MDIe|MDIready))
+			break;
+		microdelay(1);
+	}
+
+	if((mdic & (MDIe|MDIready)) == MDIready)
+		return mdic & 0xFFFF;
+	return -1;
+}
+
+static int
+igbemiimiw(Mii* mii, int pa, int ra, int data)
+{
+	Ctlr *ctlr;
+	int mdic, timo;
+
+	ctlr = mii->ctlr;
+
+	data &= MDIdMASK;
+	csr32w(ctlr, Mdic, MDIwop|(pa<<MDIpSHIFT)|(ra<<MDIrSHIFT)|data);
+	mdic = 0;
+	for(timo = 64; timo; timo--){
+		mdic = csr32r(ctlr, Mdic);
+		if(mdic & (MDIe|MDIready))
+			break;
+		microdelay(1);
+	}
+	if((mdic & (MDIe|MDIready)) == MDIready)
+		return 0;
+	return -1;
+}
+
+static int
+igbemii(Ctlr* ctlr)
+{
+	MiiPhy *phy = (MiiPhy *)1;
+	int ctrl, p, r;
+
+	USED(phy);
+	r = csr32r(ctlr, Status);
+	if(r & Tbimode)
+		return -1;
+	if((ctlr->mii = malloc(sizeof(Mii))) == nil)
+		return -1;
+	ctlr->mii->ctlr = ctlr;
+
+	ctrl = csr32r(ctlr, Ctrl);
+	ctrl |= Slu;
+
+	switch(ctlr->id){
+	case i82543gc:
+		ctrl |= Frcdplx|Frcspd;
+		csr32w(ctlr, Ctrl, ctrl);
+
+		/*
+		 * The reset pin direction (Mdro) should already
+		 * be set from the EEPROM load.
+		 * If it's not set this configuration is unexpected
+		 * so bail.
+		 */
+		r = csr32r(ctlr, Ctrlext);
+		if(!(r & Mdro))
+			return -1;
+		csr32w(ctlr, Ctrlext, r);
+		delay(20);
+		r = csr32r(ctlr, Ctrlext);
+		r &= ~Mdr;
+		csr32w(ctlr, Ctrlext, r);
+		delay(20);
+		r = csr32r(ctlr, Ctrlext);
+		r |= Mdr;
+		csr32w(ctlr, Ctrlext, r);
+		delay(20);
+
+		ctlr->mii->mir = i82543miimir;
+		ctlr->mii->miw = i82543miimiw;
+		break;
+	case i82544ei:
+	case i82547ei:
+	case i82540em:
+	case i82540eplp:
+	case i82547gi:
+	case i82541gi:
+	case i82541gi2:
+	case i82541pi:
+	case i82546gb:
+	case i82546eb:
+		ctrl &= ~(Frcdplx|Frcspd);
+		csr32w(ctlr, Ctrl, ctrl);
+		ctlr->mii->mir = igbemiimir;
+		ctlr->mii->miw = igbemiimiw;
+		break;
+	default:
+		free(ctlr->mii);
+		ctlr->mii = nil;
+		return -1;
+	}
+
+	if(mii(ctlr->mii, ~0) == 0 || (phy = ctlr->mii->curphy) == nil){
+		if (0)
+			print("phy trouble: phy = 0x%lux\n", (ulong)phy);
+		free(ctlr->mii);
+		ctlr->mii = nil;
+		return -1;
+	}
+	if (Debug)
+		print("oui %X phyno %d\n", phy->oui, phy->phyno);
+	else
+		USED(phy);
+
+	/*
+	 * 8254X-specific PHY registers not in 802.3:
+	 *	0x10	PHY specific control
+	 *	0x14	extended PHY specific control
+	 * Set appropriate values then reset the PHY to have
+	 * changes noted.
+	 */
+	switch(ctlr->id){
+	case i82547gi:
+	case i82541gi:
+	case i82541gi2:
+	case i82541pi:
+	case i82546gb:
+	case i82546eb:
+		break;
+	default:
+		r = miimir(ctlr->mii, 16);
+		r |= 0x0800;			/* assert CRS on Tx */
+		r |= 0x0060;			/* auto-crossover all speeds */
+		r |= 0x0002;			/* polarity reversal enabled */
+		miimiw(ctlr->mii, 16, r);
+
+		r = miimir(ctlr->mii, 20);
+		r |= 0x0070;			/* +25MHz clock */
+		r &= ~0x0F00;
+		r |= 0x0100;			/* 1x downshift */
+		miimiw(ctlr->mii, 20, r);
+
+		miireset(ctlr->mii);
+		break;
+	}
+	p = 0;
+	if(ctlr->txcw & TxcwPs)
+		p |= AnaP;
+	if(ctlr->txcw & TxcwAs)
+		p |= AnaAP;
+	miiane(ctlr->mii, ~0, p, ~0);
+
+	return 0;
+}
+
+static int
+at93c46io(Ctlr* ctlr, char* op, int data)
+{
+	char *lp, *p;
+	int i, loop, eecd, r;
+
+	eecd = csr32r(ctlr, Eecd);
+
+	r = 0;
+	loop = -1;
+	lp = nil;
+	for(p = op; *p != '\0'; p++){
+		switch(*p){
+		default:
+			return -1;
+		case ' ':
+			continue;
+		case ':':			/* start of loop */
+			loop = strtol(p+1, &lp, 0)-1;
+			lp--;
+			if(p == lp)
+				loop = 7;
+			p = lp;
+			continue;
+		case ';':			/* end of loop */
+			if(lp == nil)
+				return -1;
+			loop--;
+			if(loop >= 0)
+				p = lp;
+			else
+				lp = nil;
+			continue;
+		case 'C':			/* assert clock */
+			eecd |= Sk;
+			break;
+		case 'c':			/* deassert clock */
+			eecd &= ~Sk;
+			break;
+		case 'D':			/* next bit in 'data' byte */
+			if(loop < 0)
+				return -1;
+			if(data & (1<<loop))
+				eecd |= Di;
+			else
+				eecd &= ~Di;
+			break;
+		case 'O':			/* collect data output */
+			i = (csr32r(ctlr, Eecd) & Do) != 0;
+			if(loop >= 0)
+				r |= (i<<loop);
+			else
+				r = i;
+			continue;
+		case 'I':			/* assert data input */
+			eecd |= Di;
+			break;
+		case 'i':			/* deassert data input */
+			eecd &= ~Di;
+			break;
+		case 'S':			/* enable chip select */
+			eecd |= Cs;
+			break;
+		case 's':			/* disable chip select */
+			eecd &= ~Cs;
+			break;
+		}
+		csr32w(ctlr, Eecd, eecd);
+		microdelay(50);
+	}
+	if(loop >= 0)
+		return -1;
+	return r;
+}
+
+static int
+at93c46r(Ctlr* ctlr)
+{
+	ushort sum;
+	char rop[20];
+	int addr, areq, bits, data, eecd, i;
+
+	eecd = csr32r(ctlr, Eecd);
+	if(eecd & Spi){
+		print("igbe: SPI EEPROM access not implemented\n");
+		return 0;
+	}
+	if(eecd & (Eeszaddr|Eesz256))
+		bits = 8;
+	else
+		bits = 6;
+	sum = 0;
+
+	switch(ctlr->id){
+	default:
+		areq = 0;
+		break;
+	case i82540em:
+	case i82540eplp:
+	case i82541gi:
+	case i82541gi2:
+	case i82541pi:
+	case i82547gi:
+	case i82546gb:
+	case i82546eb:
+		areq = 1;
+		csr32w(ctlr, Eecd, eecd|Areq);
+		for(i = 0; i < 1000; i++){
+			if((eecd = csr32r(ctlr, Eecd)) & Agnt)
+				break;
+			microdelay(5);
+		}
+		if(!(eecd & Agnt)){
+			print("igbe: not granted EEPROM access\n");
+			goto release;
+		}
+		break;
+	}
+	snprint(rop, sizeof(rop), "S :%dDCc;", bits+3);
+
+	for(addr = 0; addr < 0x40; addr++){
+		/*
+		 * Read a word at address 'addr' from the Atmel AT93C46
+		 * 3-Wire Serial EEPROM or compatible. The EEPROM access is
+		 * controlled by 4 bits in Eecd. See the AT93C46 datasheet
+		 * for protocol details.
+		 */
+		if(at93c46io(ctlr, rop, (0x06<<bits)|addr) != 0){
+			print("igbe: can't set EEPROM address 0x%2.2X\n", addr);
+			goto release;
+		}
+		data = at93c46io(ctlr, ":16COc;", 0);
+		at93c46io(ctlr, "sic", 0);
+		ctlr->eeprom[addr] = data;
+		sum += data;
+		if (Debug) {
+			if(addr && ((addr & 0x07) == 0))
+				print("\n");
+			print(" %4.4ux", data);
+		}
+	}
+	if (Debug)
+		print("\n");
+release:
+	if(areq)
+		csr32w(ctlr, Eecd, eecd & ~Areq);
+	return sum;
+}
+
+static void
+detach(Ctlr *ctlr)
+{
+	int r;
+
+	/*
+	 * Perform a device reset to get the chip back to the
+	 * power-on state, followed by an EEPROM reset to read
+	 * the defaults for some internal registers.
+	 */
+	csr32w(ctlr, Imc, ~0);
+	csr32w(ctlr, Rctl, 0);
+	csr32w(ctlr, Tctl, 0);
+
+	delay(20);
+
+	csr32w(ctlr, Ctrl, Devrst);
+	/* apparently needed on multi-GHz processors to avoid infinite loops */
+	delay(1);
+	while(csr32r(ctlr, Ctrl) & Devrst)
+		;
+
+	csr32w(ctlr, Ctrlext, Eerst | csr32r(ctlr, Ctrlext));
+	delay(1);
+	while(csr32r(ctlr, Ctrlext) & Eerst)
+		;
+
+	switch(ctlr->id){
+	default:
+		break;
+	case i82540em:
+	case i82540eplp:
+	case i82541gi:
+	case i82541gi2:
+	case i82541pi:
+	case i82547gi:
+	case i82546gb:
+	case i82546eb:
+		r = csr32r(ctlr, Manc);
+		r &= ~Arpen;
+		csr32w(ctlr, Manc, r);
+		break;
+	}
+
+	csr32w(ctlr, Imc, ~0);
+	delay(1);
+	while(csr32r(ctlr, Icr))
+		;
+}
+
+static void
+igbedetach(Ether *edev)
+{
+	detach(edev->ctlr);
+}
+
+static void
+igbeshutdown(Ether* ether)
+{
+print("igbeshutdown\n");
+	igbedetach(ether);
+}
+
+static int
+igbereset(Ctlr* ctlr)
+{
+	int ctrl, i, pause, r, swdpio, txcw;
+
+	detach(ctlr);
+
+	/*
+	 * Read the EEPROM, validate the checksum
+	 * then get the device back to a power-on state.
+	 */
+	r = at93c46r(ctlr);
+	/* zero return means no SPI EEPROM access */
+	if (r != 0 && r != 0xBABA){
+		print("igbe: bad EEPROM checksum - 0x%4.4uX\n", r);
+		return -1;
+	}
+
+	/*
+	 * Snarf and set up the receive addresses.
+	 * There are 16 addresses. The first should be the MAC address.
+	 * The others are cleared and not marked valid (MS bit of Rah).
+	 */
+	if ((ctlr->id == i82546gb || ctlr->id == i82546eb) &&
+	    BUSFNO(ctlr->pcidev->tbdf) == 1)
+		ctlr->eeprom[Ea+2] += 0x100;		/* second interface */
+	for(i = Ea; i < Eaddrlen/2; i++){
+		ctlr->ra[2*i]   = ctlr->eeprom[i];
+		ctlr->ra[2*i+1] = ctlr->eeprom[i]>>8;
+	}
+	/* lan id seems to vary on 82543gc; don't use it */
+	if (ctlr->id != i82543gc) {
+		r = (csr32r(ctlr, Status) & Lanid) >> 2;
+		ctlr->ra[5] += r;		/* ea ctlr[1] = ea ctlr[0]+1 */
+	}
+	r = (ctlr->ra[3]<<24)|(ctlr->ra[2]<<16)|(ctlr->ra[1]<<8)|ctlr->ra[0];
+	csr32w(ctlr, Ral, r);
+	r = 0x80000000|(ctlr->ra[5]<<8)|ctlr->ra[4];
+	csr32w(ctlr, Rah, r);
+	for(i = 1; i < 16; i++){
+		csr32w(ctlr, Ral+i*8, 0);
+		csr32w(ctlr, Rah+i*8, 0);
+	}
+
+	/*
+	 * Clear the Multicast Table Array.
+	 * It's a 4096 bit vector accessed as 128 32-bit registers.
+	 */
+	memset(ctlr->mta, 0, sizeof(ctlr->mta));
+	for(i = 0; i < 128; i++)
+		csr32w(ctlr, Mta+i*4, 0);
+
+	/*
+	 * Just in case the Eerst didn't load the defaults
+	 * (doesn't appear to fully on the 8243GC), do it manually.
+	 */
+	if (ctlr->id == i82543gc) {
+		txcw = csr32r(ctlr, Txcw);
+		txcw &= ~(TxcwAne|TxcwPauseMASK|TxcwFd);
+		ctrl = csr32r(ctlr, Ctrl);
+		ctrl &= ~(SwdpioloMASK|Frcspd|Ilos|Lrst|Fd);
+
+		if(ctlr->eeprom[Icw1] & 0x0400){
+			ctrl |= Fd;
+			txcw |= TxcwFd;
+		}
+		if(ctlr->eeprom[Icw1] & 0x0200)
+			ctrl |= Lrst;
+		if(ctlr->eeprom[Icw1] & 0x0010)
+			ctrl |= Ilos;
+		if(ctlr->eeprom[Icw1] & 0x0800)
+			ctrl |= Frcspd;
+		swdpio = (ctlr->eeprom[Icw1] & 0x01E0)>>5;
+		ctrl |= swdpio<<SwdpioloSHIFT;
+		csr32w(ctlr, Ctrl, ctrl);
+
+		ctrl = csr32r(ctlr, Ctrlext);
+		ctrl &= ~(Ips|SwdpiohiMASK);
+		swdpio = (ctlr->eeprom[Icw2] & 0x00F0)>>4;
+		if(ctlr->eeprom[Icw1] & 0x1000)
+			ctrl |= Ips;
+		ctrl |= swdpio<<SwdpiohiSHIFT;
+		csr32w(ctlr, Ctrlext, ctrl);
+
+		if(ctlr->eeprom[Icw2] & 0x0800)
+			txcw |= TxcwAne;
+		pause = (ctlr->eeprom[Icw2] & 0x3000)>>12;
+		txcw |= pause<<TxcwPauseSHIFT;
+		switch(pause){
+		default:
+			ctlr->fcrtl = 0x00002000;
+			ctlr->fcrth = 0x00004000;
+			txcw |= TxcwAs|TxcwPs;
+			break;
+		case 0:
+			ctlr->fcrtl = 0x00002000;
+			ctlr->fcrth = 0x00004000;
+			break;
+		case 2:
+			ctlr->fcrtl = 0;
+			ctlr->fcrth = 0;
+			txcw |= TxcwAs;
+			break;
+		}
+		ctlr->txcw = txcw;
+		csr32w(ctlr, Txcw, txcw);
+	}
+	/*
+	 * Flow control - values from the datasheet.
+	 */
+	csr32w(ctlr, Fcal, 0x00C28001);
+	csr32w(ctlr, Fcah, 0x00000100);
+	csr32w(ctlr, Fct, 0x00008808);
+	csr32w(ctlr, Fcttv, 0x00000100);
+
+	csr32w(ctlr, Fcrtl, ctlr->fcrtl);
+	csr32w(ctlr, Fcrth, ctlr->fcrth);
+
+	ilock(&ctlr->imlock);
+	csr32w(ctlr, Imc, ~0);
+	ctlr->im = 0;		/* was = Lsc, which hangs some controllers */
+	csr32w(ctlr, Ims, ctlr->im);
+	iunlock(&ctlr->imlock);
+
+	if(!(csr32r(ctlr, Status) & Tbimode) && igbemii(ctlr) < 0) {
+		print("igbe: igbemii failed\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+static void
+igbepci(void)
+{
+	int port, cls;
+	Pcidev *p;
+	Ctlr *ctlr;
+	static int first = 1;
+
+	if (first)
+		first = 0;
+	else
+		return;
+
+	p = nil;
+	while(p = pcimatch(p, 0, 0)){
+		if(p->ccrb != 0x02 || p->ccru != 0)
+			continue;
+
+		switch((p->did<<16)|p->vid){
+		case i82542:
+		default:
+			continue;
+
+		case (0x1001<<16)|0x8086:	/* Intel PRO/1000 F */
+			break;
+		case i82543gc:
+		case i82544ei:
+		case i82547ei:
+		case i82540em:
+		case i82540eplp:
+		case i82547gi:
+		case i82541gi:
+		case i82541gi2:
+		case i82541pi:
+		case i82546gb:
+		case i82546eb:
+			break;
+		}
+
+		/* the 82547EI is on the CSA bus, whatever that is */
+		port = upamalloc(p->mem[0].bar & ~0x0F, p->mem[0].size, 0);
+		if(port == 0){
+			print("igbe: can't map %d @ 0x%8.8luX\n",
+				p->mem[0].size, p->mem[0].bar);
+			continue;
+		}
+
+		/*
+		 * from etherga620.c:
+		 * If PCI Write-and-Invalidate is enabled set the max write DMA
+		 * value to the host cache-line size (32 on Pentium or later).
+		 */
+		if(p->pcr & MemWrInv){
+			cls = pcicfgr8(p, PciCLS) * 4;
+			if(cls != CACHELINESZ)
+				pcicfgw8(p, PciCLS, CACHELINESZ/4);
+		}
+
+		cls = pcicfgr8(p, PciCLS);
+		switch(cls){
+			default:
+				print("igbe: unexpected CLS - %d bytes\n",
+					cls*sizeof(long));
+				break;
+			case 0x00:
+			case 0xFF:
+				/* alphapc 164lx returns 0 */
+				print("igbe: unusable PciCLS: %d, using %d longs\n",
+					cls, CACHELINESZ/sizeof(long));
+				cls = CACHELINESZ/sizeof(long);
+				pcicfgw8(p, PciCLS, cls);
+				break;
+			case 0x08:
+			case 0x10:
+				break;
+		}
+
+		ctlr = malloc(sizeof(Ctlr));
+		ctlr->port = port;
+		ctlr->pcidev = p;
+		ctlr->id = (p->did<<16)|p->vid;
+		ctlr->cls = cls*4;
+		ctlr->nic = KADDR(ctlr->port);
+		if (Debug)
+			print("status0 %8.8uX\n", csr32r(ctlr, Status));
+		if(igbereset(ctlr)){
+			free(ctlr);
+			continue;
+		}
+		if (Debug)
+			print("status1 %8.8uX\n", csr32r(ctlr, Status));
+		pcisetbme(p);
+
+		if(ctlrhead != nil)
+			ctlrtail->next = ctlr;
+		else
+			ctlrhead = ctlr;
+		ctlrtail = ctlr;
+	}
+}
+
+int
+igbepnp(Ether* edev)
+{
+	int i;
+	Ctlr *ctlr;
+	uchar ea[Eaddrlen];
+
+	if(ctlrhead == nil)
+		igbepci();
+
+	/*
+	 * Any adapter matches if no edev->port is supplied,
+	 * otherwise the ports must match.
+	 */
+	for(ctlr = ctlrhead; ctlr != nil; ctlr = ctlr->next){
+		if(ctlr->active)
+			continue;
+		if(edev->port == 0 || edev->port == ctlr->port){
+			ctlr->active = 1;
+			break;
+		}
+	}
+	if(ctlr == nil)
+		return -1;
+
+	edev->ctlr = ctlr;
+	edev->port = ctlr->port;
+	edev->irq = ctlr->pcidev->intl;
+	edev->tbdf = ctlr->pcidev->tbdf;
+//	edev->mbps = 1000;
+
+	/*
+	 * Check if the adapter's station address is to be overridden.
+	 * If not, read it from the EEPROM and set in ether->ea prior to
+	 * loading the station address in the hardware.
+	 */
+	memset(ea, 0, Eaddrlen);
+	if(memcmp(ea, edev->ea, Eaddrlen) == 0){
+		for(i = 0; i < Eaddrlen/2; i++){
+			edev->ea[2*i] = ctlr->eeprom[i];
+			edev->ea[2*i+1] = ctlr->eeprom[i]>>8;
+		}
+	}
+	igbeinit(edev);
+
+	/*
+	 * Linkage to the generic ethernet driver.
+	 */
+	edev->attach = igbeattach;
+	edev->transmit = igbetransmit;
+	edev->interrupt = igbeinterrupt;
+	edev->detach = igbedetach;
+
+	return 0;
+}
--- /dev/null
+++ b/os/boot.original/pc/ethermii.c
@@ -1,0 +1,224 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+#include "etherif.h"
+#include "ethermii.h"
+
+int
+mii(Mii* mii, int mask)
+{
+	MiiPhy *miiphy;
+	int bit, phyno, r, rmask;
+
+	/*
+	 * Probe through mii for PHYs in mask;
+	 * return the mask of those found in the current probe.
+	 * If the PHY has not already been probed, update
+	 * the Mii information.
+	 */
+	rmask = 0;
+	for(phyno = 0; phyno < NMiiPhy; phyno++){
+		bit = 1<<phyno;
+		if(!(mask & bit))
+			continue;
+		if(mii->mask & bit){
+			rmask |= bit;
+			continue;
+		}
+		if(mii->mir(mii, phyno, Bmsr) == -1)
+			continue;
+		if((miiphy = malloc(sizeof(MiiPhy))) == nil)
+			continue;
+
+		miiphy->mii = mii;
+		r = mii->mir(mii, phyno, Phyidr1);
+		miiphy->oui = (r & 0x3FFF)<<6;
+		r = mii->mir(mii, phyno, Phyidr2);
+		miiphy->oui |= r>>10;
+		miiphy->phyno = phyno;
+
+		miiphy->anar = ~0;
+		miiphy->fc = ~0;
+		miiphy->mscr = ~0;
+
+		mii->phy[phyno] = miiphy;
+		if(mii->curphy == nil)
+			mii->curphy = miiphy;
+		mii->mask |= bit;
+		mii->nphy++;
+
+		rmask |= bit;
+	}
+	return rmask;
+}
+
+int
+miimir(Mii* mii, int r)
+{
+	if(mii == nil || mii->ctlr == nil || mii->curphy == nil)
+		return -1;
+	return mii->mir(mii, mii->curphy->phyno, r);
+}
+
+int
+miimiw(Mii* mii, int r, int data)
+{
+	if(mii == nil || mii->ctlr == nil || mii->curphy == nil)
+		return -1;
+	return mii->miw(mii, mii->curphy->phyno, r, data);
+}
+
+int
+miireset(Mii* mii)
+{
+	int bmcr;
+
+	if(mii == nil || mii->ctlr == nil || mii->curphy == nil)
+		return -1;
+	bmcr = mii->mir(mii, mii->curphy->phyno, Bmcr);
+	bmcr |= BmcrR;
+	mii->miw(mii, mii->curphy->phyno, Bmcr, bmcr);
+	microdelay(1);
+
+	return 0;
+}
+
+int
+miiane(Mii* mii, int a, int p, int e)
+{
+	int anar, bmsr, mscr, r, phyno;
+
+	if(mii == nil || mii->ctlr == nil || mii->curphy == nil)
+		return -1;
+	phyno = mii->curphy->phyno;
+
+	bmsr = mii->mir(mii, phyno, Bmsr);
+	if(!(bmsr & BmsrAna))
+		return -1;
+
+	if(a != ~0)
+		anar = (AnaTXFD|AnaTXHD|Ana10FD|Ana10HD) & a;
+	else if(mii->curphy->anar != ~0)
+		anar = mii->curphy->anar;
+	else{
+		anar = mii->mir(mii, phyno, Anar);
+		anar &= ~(AnaAP|AnaP|AnaT4|AnaTXFD|AnaTXHD|Ana10FD|Ana10HD);
+		if(bmsr & Bmsr10THD)
+			anar |= Ana10HD;
+		if(bmsr & Bmsr10TFD)
+			anar |= Ana10FD;
+		if(bmsr & Bmsr100TXHD)
+			anar |= AnaTXHD;
+		if(bmsr & Bmsr100TXFD)
+			anar |= AnaTXFD;
+	}
+	mii->curphy->anar = anar;
+
+	if(p != ~0)
+		anar |= (AnaAP|AnaP) & p;
+	else if(mii->curphy->fc != ~0)
+		anar |= mii->curphy->fc;
+	mii->curphy->fc = (AnaAP|AnaP) & anar;
+
+	if(bmsr & BmsrEs){
+		mscr = mii->mir(mii, phyno, Mscr);
+		mscr &= ~(Mscr1000TFD|Mscr1000THD);
+		if(e != ~0)
+			mscr |= (Mscr1000TFD|Mscr1000THD) & e;
+		else if(mii->curphy->mscr != ~0)
+			mscr = mii->curphy->mscr;
+		else{
+			r = mii->mir(mii, phyno, Esr);
+			if(r & Esr1000THD)
+				mscr |= Mscr1000THD;
+			if(r & Esr1000TFD)
+				mscr |= Mscr1000TFD;
+		}
+		mii->curphy->mscr = mscr;
+		mii->miw(mii, phyno, Mscr, mscr);
+	}
+	mii->miw(mii, phyno, Anar, anar);
+
+	r = mii->mir(mii, phyno, Bmcr);
+	if(!(r & BmcrR)){
+		r |= BmcrAne|BmcrRan;
+		mii->miw(mii, phyno, Bmcr, r);
+	}
+
+	return 0;
+}
+
+int
+miistatus(Mii* mii)
+{
+	MiiPhy *phy;
+	int anlpar, bmsr, p, r, phyno;
+
+	if(mii == nil || mii->ctlr == nil || mii->curphy == nil)
+		return -1;
+	phy = mii->curphy;
+	phyno = phy->phyno;
+
+	/*
+	 * Check Auto-Negotiation is complete and link is up.
+	 * (Read status twice as the Ls bit is sticky).
+	 */
+	bmsr = mii->mir(mii, phyno, Bmsr);
+	if(!(bmsr & (BmsrAnc|BmsrAna)))
+		return -1;
+
+	bmsr = mii->mir(mii, phyno, Bmsr);
+	if(!(bmsr & BmsrLs)){
+		phy->link = 0;
+		return -1;
+	}
+
+	phy->speed = phy->fd = phy->rfc = phy->tfc = 0;
+	if(phy->mscr){
+		r = mii->mir(mii, phyno, Mssr);
+		if((phy->mscr & Mscr1000TFD) && (r & Mssr1000TFD)){
+			phy->speed = 1000;
+			phy->fd = 1;
+		}
+		else if((phy->mscr & Mscr1000THD) && (r & Mssr1000THD))
+			phy->speed = 1000;
+	}
+
+	anlpar = mii->mir(mii, phyno, Anlpar);
+	if(phy->speed == 0){
+		r = phy->anar & anlpar;
+		if(r & AnaTXFD){
+			phy->speed = 100;
+			phy->fd = 1;
+		}
+		else if(r & AnaTXHD)
+			phy->speed = 100;
+		else if(r & Ana10FD){
+			phy->speed = 10;
+			phy->fd = 1;
+		}
+		else if(r & Ana10HD)
+			phy->speed = 10;
+	}
+	if(phy->speed == 0)
+		return -1;
+
+	if(phy->fd){
+		p = phy->fc;
+		r = anlpar & (AnaAP|AnaP);
+		if(p == AnaAP && r == (AnaAP|AnaP))
+			phy->tfc = 1;
+		else if(p == (AnaAP|AnaP) && r == AnaAP)
+			phy->rfc = 1;
+		else if((p & AnaP) && (r & AnaP))
+			phy->rfc = phy->tfc = 1;
+	}
+
+	phy->link = 1;
+
+	return 0;
+}
--- /dev/null
+++ b/os/boot.original/pc/ethermii.h
@@ -1,0 +1,116 @@
+typedef struct Mii Mii;
+typedef struct MiiPhy MiiPhy;
+
+enum {					/* registers */
+	Bmcr		= 0x00,		/* Basic Mode Control */
+	Bmsr		= 0x01,		/* Basic Mode Status */
+	Phyidr1		= 0x02,		/* PHY Identifier #1 */
+	Phyidr2		= 0x03,		/* PHY Identifier #2 */
+	Anar		= 0x04,		/* Auto-Negotiation Advertisement */
+	Anlpar		= 0x05,		/* AN Link Partner Ability */
+	Aner		= 0x06,		/* AN Expansion */
+	Annptr		= 0x07,		/* AN Next Page TX */
+	Annprr		= 0x08,		/* AN Next Page RX */
+	Mscr		= 0x09,		/* MASTER-SLAVE Control */
+	Mssr		= 0x0A,		/* MASTER-SLAVE Status */
+	Esr		= 0x0F,		/* Extended Status */
+
+	NMiiPhyr	= 32,
+	NMiiPhy		= 32,
+};
+
+enum {					/* Bmcr */
+	BmcrSs1		= 0x0040,	/* Speed Select[1] */
+	BmcrCte		= 0x0080,	/* Collision Test Enable */
+	BmcrDm		= 0x0100,	/* Duplex Mode */
+	BmcrRan		= 0x0200,	/* Restart Auto-Negotiation */
+	BmcrI		= 0x0400,	/* Isolate */
+	BmcrPd		= 0x0800,	/* Power Down */
+	BmcrAne		= 0x1000,	/* Auto-Negotiation Enable */
+	BmcrSs0		= 0x2000,	/* Speed Select[0] */
+	BmcrLe		= 0x4000,	/* Loopback Enable */
+	BmcrR		= 0x8000,	/* Reset */
+};
+
+enum {					/* Bmsr */
+	BmsrEc		= 0x0001,	/* Extended Capability */
+	BmsrJd		= 0x0002,	/* Jabber Detect */
+	BmsrLs		= 0x0004,	/* Link Status */
+	BmsrAna		= 0x0008,	/* Auto-Negotiation Ability */
+	BmsrRf		= 0x0010,	/* Remote Fault */
+	BmsrAnc		= 0x0020,	/* Auto-Negotiation Complete */
+	BmsrPs		= 0x0040,	/* Preamble Suppression Capable */
+	BmsrEs		= 0x0100,	/* Extended Status */
+	Bmsr100T2HD	= 0x0200,	/* 100BASE-T2 HD Capable */
+	Bmsr100T2FD	= 0x0400,	/* 100BASE-T2 FD Capable */
+	Bmsr10THD	= 0x0800,	/* 100BASE-T HD Capable */
+	Bmsr10TFD	= 0x1000,	/* 10BASE-T FD Capable */
+	Bmsr100TXHD	= 0x2000,	/* 100BASE-TX HD Capable */
+	Bmsr100TXFD	= 0x4000,	/* 100BASE-TX FD Capable */
+	Bmsr100T4	= 0x8000,	/* 100BASE-T4 Capable */
+};
+
+enum {					/* Anar/Anlpar */
+	Ana10HD		= 0x0020,	/* Advertise 10BASE-T */
+	Ana10FD		= 0x0040,	/* Advertise 10BASE-T FD */
+	AnaTXHD		= 0x0080,	/* Advertise 100BASE-TX */
+	AnaTXFD		= 0x0100,	/* Advertise 100BASE-TX FD */
+	AnaT4		= 0x0200,	/* Advertise 100BASE-T4 */
+	AnaP		= 0x0400,	/* Pause */
+	AnaAP		= 0x0800,	/* Asymmetrical Pause */
+	AnaRf		= 0x2000,	/* Remote Fault */
+	AnaAck		= 0x4000,	/* Acknowledge */
+	AnaNp		= 0x8000,	/* Next Page Indication */
+};
+
+enum {					/* Mscr */
+	Mscr1000THD	= 0x0100,	/* Advertise 1000BASE-T HD */
+	Mscr1000TFD	= 0x0200,	/* Advertise 1000BASE-T FD */
+};
+
+enum {					/* Mssr */
+	Mssr1000THD	= 0x0400,	/* Link Partner 1000BASE-T HD able */
+	Mssr1000TFD	= 0x0800,	/* Link Partner 1000BASE-T FD able */
+};
+
+enum {					/* Esr */
+	Esr1000THD	= 0x1000,	/* 1000BASE-T HD Capable */
+	Esr1000TFD	= 0x2000,	/* 1000BASE-T FD Capable */
+	Esr1000XHD	= 0x4000,	/* 1000BASE-X HD Capable */
+	Esr1000XFD	= 0x8000,	/* 1000BASE-X FD Capable */
+};
+
+typedef struct Mii {
+	Lock;
+	int	nphy;
+	int	mask;
+	MiiPhy*	phy[NMiiPhy];
+	MiiPhy*	curphy;
+
+	void*	ctlr;
+	int	(*mir)(Mii*, int, int);
+	int	(*miw)(Mii*, int, int, int);
+} Mii;
+
+typedef struct MiiPhy {
+	Mii*	mii;
+	int	oui;
+	int	phyno;
+
+	int	anar;
+	int	fc;
+	int	mscr;
+
+	int	link;
+	int	speed;
+	int	fd;
+	int	rfc;
+	int	tfc;
+};
+
+extern int mii(Mii*, int);
+extern int miiane(Mii*, int, int, int);
+extern int miimir(Mii*, int);
+extern int miimiw(Mii*, int, int);
+extern int miireset(Mii*);
+extern int miistatus(Mii*);
--- /dev/null
+++ b/os/boot.original/pc/etherrhine.c
@@ -1,0 +1,657 @@
+/*
+	Via Rhine driver, written for VT6102.
+	Uses the ethermii to control PHY.
+
+	Currently always copies on both, tx and rx.
+	rx side could be copy-free, and tx-side might be made
+	(almost) copy-free by using (possibly) two descriptors (if it allows
+	arbitrary tx lengths, which it should..): first for alignment and
+	second for rest of the frame. Rx-part should be worth doing.
+ */
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+typedef struct QLock { int r; } QLock;
+#define qlock(i)	while(0)
+#define qunlock(i)	while(0)
+#define iprint		print
+
+#include "etherif.h"
+#include "ethermii.h"
+
+enum {
+	Ntxd = 4,
+	Nrxd = 4,
+	Nwait = 50,
+	BIGSTR = 8192,
+};
+
+typedef struct Desc Desc;
+typedef struct Ctlr Ctlr;
+
+struct Desc {
+	ulong	stat;
+	ulong	size;
+	ulong	addr;
+	ulong	next;
+	char	*buf;
+	ulong	pad[3];
+};
+
+struct Ctlr {
+	Pcidev	*pci;
+	int	attached;
+	int	txused;
+	int	txhead;
+	int	txtail;
+	int	rxtail;
+	ulong	port;
+
+	Mii	mii;
+
+	Desc	*txd;		/* wants to be aligned on 16-byte boundary */
+	Desc	*rxd;
+
+	QLock	attachlck;
+	Lock	tlock;
+};
+
+#define ior8(c, r)	(inb((c)->port+(r)))
+#define iow8(c, r, b)	(outb((c)->port+(r), (int)(b)))
+#define ior16(c, r)	(ins((c)->port+(r)))
+#define ior32(c, r)	(inl((c)->port+(r)))
+#define iow16(c, r, w)	(outs((c)->port+(r), (ushort)(w)))
+#define iow32(c, r, l)	(outl((c)->port+(r), (ulong)(l)))
+
+/* names used everywhere else */
+#define csr8r ior8
+#define csr8w iow8
+#define csr16r ior16
+#define csr16w iow16
+#define csr32r ior32
+#define csr32w iow32
+
+enum Regs {
+	Eaddr		= 0x0,
+	Rcr		= 0x6,
+	Tcr		= 0x7,
+	Cr		= 0x8,
+	Isr		= 0xc,
+	Imr		= 0xe,
+	McastAddr	= 0x10,
+	RxdAddr		= 0x18,
+	TxdAddr		= 0x1C,
+	Bcr0		= 0x6E,		/* Bus Control */
+	Bcr1		= 0x6F,
+	RhineMiiPhy	= 0x6C,
+	RhineMiiSr	= 0x6D,
+	RhineMiiCr	= 0x70,
+	RhineMiiAddr	= 0x71,
+	RhineMiiData	= 0x72,
+	Eecsr		= 0x74,
+	ConfigB		= 0x79,
+	ConfigD		= 0x7B,
+	MiscCr		= 0x80,
+	HwSticky	= 0x83,
+	MiscIsr		= 0x84,
+	MiscImr		= 0x86,
+	WolCrSet	= 0xA0,
+	WolCfgSet	= 0xA1,
+	WolCgSet	= 0xA3,
+	WolCrClr	= 0xA4,
+	PwrCfgClr	= 0xA5,
+	WolCgClr	= 0xA7,
+};
+
+enum {					/* Rcr */
+	Sep		= 0x01,		/* Accept Error Packets */
+	Ar		= 0x02,		/* Accept Small Packets */
+	Am		= 0x04,		/* Accept Multicast */
+	Ab		= 0x08,		/* Accept Broadcast */
+	RxBcast		= Ab,
+	Prom		= 0x10,		/* Accept Physical Address Packets */
+	RxProm		= Prom,
+	RrftMASK	= 0xE0,		/* Receive FIFO Threshold */
+	RrftSHIFT	= 5,
+	Rrft64		= 0<<RrftSHIFT,
+	Rrft32		= 1<<RrftSHIFT,
+	Rrft128		= 2<<RrftSHIFT,
+	Rrft256		= 3<<RrftSHIFT,
+	Rrft512		= 4<<RrftSHIFT,
+	Rrft768		= 5<<RrftSHIFT,
+	Rrft1024	= 6<<RrftSHIFT,
+	RrftSAF		= 7<<RrftSHIFT,
+};
+
+enum {					/* Tcr */
+	Lb0		= 0x02,		/* Loopback Mode */
+	Lb1		= 0x04,
+	Ofset		= 0x08,		/* Back-off Priority Selection */
+	RtsfMASK	= 0xE0,		/* Transmit FIFO Threshold */
+	RtsfSHIFT	= 5,
+	Rtsf128		= 0<<RtsfSHIFT,
+	Rtsf256		= 1<<RtsfSHIFT,
+	Rtsf512		= 2<<RtsfSHIFT,
+	Rtsf1024	= 3<<RtsfSHIFT,
+	RtsfSAF		= 7<<RtsfSHIFT,
+};
+
+enum Crbits {
+	Init		= 1<<0,
+	Start		= 1<<1,
+	Stop		= 1<<2,
+	RxOn		= 1<<3,
+	TxOn		= 1<<4,
+	Tdmd		= 1<<5,
+	Rdmd		= 1<<6,
+	EarlyRx		= 1<<8,
+	Reserved0	= 1<<9,
+	FullDuplex	= 1<<10,
+	NoAutoPoll	= 1<<11,
+	Reserved1	= 1<<12,
+	Tdmd1		= 1<<13,
+	Rdmd1		= 1<<14,
+	Reset		= 1<<15,
+};
+
+enum Isrbits {
+	RxOk		= 1<<0,
+	TxOk		= 1<<1,
+	RxErr		= 1<<2,
+	TxErr		= 1<<3,
+	TxBufUdf	= 1<<4,
+	RxBufLinkErr	= 1<<5,
+	BusErr		= 1<<6,
+	CrcOvf		= 1<<7,
+	EarlyRxInt	= 1<<8,
+	TxFifoUdf	= 1<<9,
+	RxFifoOvf	= 1<<10,
+	TxPktRace	= 1<<11,
+	NoRxbuf		= 1<<12,
+	TxCollision	= 1<<13,
+	PortCh		= 1<<14,
+	GPInt		= 1<<15,
+};
+
+enum {					/* Bcr0 */
+	DmaMASK		= 0x07,		/* DMA Length */
+	DmaSHIFT	= 0,
+	Dma32		= 0<<DmaSHIFT,
+	Dma64		= 1<<DmaSHIFT,
+	Dma128		= 2<<DmaSHIFT,
+	Dma256		= 3<<DmaSHIFT,
+	Dma512		= 4<<DmaSHIFT,
+	Dma1024		= 5<<DmaSHIFT,
+	DmaSAF		= 7<<DmaSHIFT,
+	CrftMASK	= 0x38,		/* Rx FIFO Threshold */
+	CrftSHIFT	= 3,
+	Crft64		= 1<<CrftSHIFT,
+	Crft128		= 2<<CrftSHIFT,
+	Crft256		= 3<<CrftSHIFT,
+	Crft512		= 4<<CrftSHIFT,
+	Crft1024	= 5<<CrftSHIFT,
+	CrftSAF		= 7<<CrftSHIFT,
+	Extled		= 0x40,		/* Extra LED Support Control */
+	Med2		= 0x80,		/* Medium Select Control */
+};
+
+enum {					/* Bcr1 */
+	PotMASK		= 0x07,		/* Polling Timer Interval */
+	PotSHIFT	= 0,
+	CtftMASK	= 0x38,		/* Tx FIFO Threshold */
+	CtftSHIFT	= 3,
+	Ctft64		= 1<<CtftSHIFT,
+	Ctft128		= 2<<CtftSHIFT,
+	Ctft256		= 3<<CtftSHIFT,
+	Ctft512		= 4<<CtftSHIFT,
+	Ctft1024	= 5<<CtftSHIFT,
+	CtftSAF		= 7<<CtftSHIFT,
+};
+
+
+enum Eecsrbits {
+	EeAutoLoad	= 1<<5,
+};
+
+enum Descbits {
+	OwnNic		= 1<<31,	/* stat */
+	TxAbort		= 1<<8,		/* stat */
+	TxError		= 1<<15,	/* stat */
+	RxChainbuf	= 1<<10,	/* stat */
+	RxChainStart	= 1<<9,		/* stat */
+	RxChainEnd	= 1<<8,		/* stat */
+	Chainbuf	= 1<<15,	/* size rx & tx*/
+	TxDisableCrc	= 1<<16,	/* size */
+	TxChainStart	= 1<<21,	/* size */
+	TxChainEnd	= 1<<22,	/* size */
+	TxInt		= 1<<23,	/* size */
+};
+
+enum RhineMiiCrbits {
+	Mdc	= 1<<0,
+	Mdi	= 1<<1,
+	Mdo	= 1<<2,
+	Mdout	= 1<<3,
+	Mdpm	= 1<<4,
+	Wcmd	= 1<<5,
+	Rcmd	= 1<<6,
+	Mauto	= 1<<7,
+};
+
+static void
+attach(Ether *edev)
+{
+	Ctlr *ctlr;
+	Desc *txd, *rxd, *td, *rd;
+	Mii *mi;
+	MiiPhy *phy;
+	int i, s;
+
+	ctlr = edev->ctlr;
+	qlock(&ctlr->attachlck);
+	if (ctlr->attached == 0) {
+		txd = ctlr->txd;
+		rxd = ctlr->rxd;
+		for (i = 0; i < Ntxd; ++i) {
+			td = &txd[i];
+			td->next = PCIWADDR(&txd[(i+1) % Ntxd]);
+			td->buf = xspanalloc(sizeof(Etherpkt)+4, 4, 0);
+			td->addr = PCIWADDR(td->buf);
+			td->size = 0;
+			coherence();
+			td->stat = 0;
+		}
+		for (i = 0; i < Nrxd; ++i) {
+			rd = &rxd[i];
+			rd->next = PCIWADDR(&rxd[(i+1) % Nrxd]);
+			rd->buf = xspanalloc(sizeof(Etherpkt)+4, 4, 0);
+			rd->addr = PCIWADDR(rd->buf);
+			rd->size = sizeof(Etherpkt)+4;
+			coherence();
+			rd->stat = OwnNic;
+		}
+
+		ctlr->txhead = ctlr->txtail = ctlr->rxtail = 0;
+		mi = &ctlr->mii;
+		miistatus(mi);
+		phy = mi->curphy;
+		s = splhi();
+		iow32(ctlr, TxdAddr, PCIWADDR(&txd[0]));
+		iow32(ctlr, RxdAddr, PCIWADDR(&rxd[0]));
+		iow16(ctlr, Cr, (phy->fd? FullDuplex: 0) | NoAutoPoll | TxOn |
+			RxOn | Start | Rdmd);
+		iow16(ctlr, Isr, 0xFFFF);
+		iow16(ctlr, Imr, 0xFFFF);
+		iow8(ctlr, MiscIsr, 0xFF);
+		iow8(ctlr, MiscImr, ~(3<<5));
+		splx(s);
+		ctlr->attached = 1;
+	}
+	qunlock(&ctlr->attachlck);
+}
+
+static void
+txstart(Ether *edev)
+{
+	Ctlr *ctlr;
+	Desc *txd, *td;
+	int i, txused, n;
+	RingBuf *tb;
+
+	ctlr = edev->ctlr;
+	txd = ctlr->txd;
+	i = ctlr->txhead;
+	n = 0;
+	for (txused = ctlr->txused; txused < Ntxd; txused++) {
+		tb = &edev->tb[edev->ti];
+		if(tb->owner != Interface)
+			break;
+
+		td = &txd[i];
+		memmove(td->buf, tb->pkt, tb->len);
+		/* could reduce number of intrs here */
+		td->size = tb->len | TxChainStart | TxChainEnd | TxInt;
+		coherence();
+		td->stat = OwnNic;
+		i = (i + 1) % Ntxd;
+		n++;
+
+		tb->owner = Host;
+		edev->ti = NEXT(edev->ti, edev->ntb);
+	}
+	if (n)
+		iow16(ctlr, Cr, ior16(ctlr, Cr) | Tdmd);
+
+	ctlr->txhead = i;
+	ctlr->txused = txused;
+}
+
+static void
+transmit(Ether *edev)
+{
+	Ctlr *ctlr;
+
+	ctlr = edev->ctlr;
+	ilock(&ctlr->tlock);
+	txstart(edev);
+	iunlock(&ctlr->tlock);
+}
+
+static void
+txcomplete(Ether *edev)
+{
+	Ctlr *ctlr;
+	Desc *txd, *td;
+	int i, txused;
+	ulong stat;
+
+	ctlr = edev->ctlr;
+ 	txd = ctlr->txd;
+	i = ctlr->txtail;
+	for (txused = ctlr->txused; txused > 0; txused--) {
+		td = &txd[i];
+		stat = td->stat;
+		if (stat & OwnNic)
+			break;
+		i = (i + 1) % Ntxd;
+	}
+	ctlr->txused = txused;
+	ctlr->txtail = i;
+
+	if (txused <= Ntxd/2)
+		txstart(edev);
+}
+
+static void
+interrupt(Ureg *, void *arg)
+{
+	Ether *edev;
+	Ctlr *ctlr;
+	RingBuf *rb;
+	ushort  isr, misr;
+	ulong stat;
+	Desc *rxd, *rd;
+	int i, n, size;
+
+	edev = (Ether*)arg;
+	ctlr = edev->ctlr;
+	iow16(ctlr, Imr, 0);
+	isr = ior16(ctlr, Isr);
+	iow16(ctlr, Isr, 0xFFFF);
+	/* don't care about used defined intrs */
+	misr = ior16(ctlr, MiscIsr) & ~(3<<5);
+
+	if (isr & RxOk) {
+		rxd = ctlr->rxd;
+		i = ctlr->rxtail;
+
+		n = 0;
+		while ((rxd[i].stat & OwnNic) == 0) {
+			rd = &rxd[i];
+			stat = rd->stat;
+			if (stat & 0xFF)
+				iprint("rx: %lux\n", stat & 0xFF);
+			size = ((rd->stat>>16) & (2048-1)) - 4;
+
+			rb = &edev->rb[edev->ri];
+			if(rb->owner == Interface){
+				rb->owner = Host;
+				rb->len = size;
+				memmove(rb->pkt, rd->buf, size);
+				edev->ri = NEXT(edev->ri, edev->nrb);
+			}
+
+			rd->size = sizeof(Etherpkt)+4;
+			coherence();
+			rd->stat = OwnNic;
+			i = (i + 1) % Nrxd;
+			n++;
+		}
+		if (n)
+			iow16(ctlr, Cr, ior16(ctlr, Cr) | Rdmd);
+		ctlr->rxtail = i;
+		isr &= ~RxOk;
+	}
+	if (isr & TxOk) {
+		txcomplete(edev);
+		isr &= ~TxOk;
+	}
+	if (isr | misr)
+		iprint("etherrhine: unhandled irq(s). isr:%x misr:%x\n",
+			isr, misr);
+	iow16(ctlr, Imr, 0xFFFF);
+}
+
+static int
+miiread(Mii *mii, int phy, int reg)
+{
+	Ctlr *ctlr;
+	int n;
+
+	ctlr = mii->ctlr;
+
+	n = Nwait;
+	while (n-- && ior8(ctlr, RhineMiiCr) & (Rcmd | Wcmd))
+		microdelay(1);
+	if (n == Nwait)
+		iprint("etherrhine: miiread: timeout\n");
+
+	iow8(ctlr, RhineMiiCr, 0);
+	iow8(ctlr, RhineMiiPhy, phy);
+	iow8(ctlr, RhineMiiAddr, reg);
+	iow8(ctlr, RhineMiiCr, Rcmd);
+
+	n = Nwait;
+	while (n-- && ior8(ctlr, RhineMiiCr) & Rcmd)
+		microdelay(1);
+	if (n == Nwait)
+		iprint("etherrhine: miiread: timeout\n");
+
+	return ior16(ctlr, RhineMiiData);
+}
+
+static int
+miiwrite(Mii *mii, int phy, int reg, int data)
+{
+	int n;
+	Ctlr *ctlr;
+
+	ctlr = mii->ctlr;
+
+	n = Nwait;
+	while (n-- && ior8(ctlr, RhineMiiCr) & (Rcmd | Wcmd))
+		microdelay(1);
+	if (n == Nwait)
+		iprint("etherrhine: miiwrite: timeout\n");
+
+	iow8(ctlr, RhineMiiCr, 0);
+	iow8(ctlr, RhineMiiPhy, phy);
+	iow8(ctlr, RhineMiiAddr, reg);
+	iow16(ctlr, RhineMiiData, data);
+	iow8(ctlr, RhineMiiCr, Wcmd);
+
+	n = Nwait;
+	while (n-- && ior8(ctlr, RhineMiiCr) & Wcmd)
+		microdelay(1);
+	if (n == Nwait)
+		iprint("etherrhine: miiwrite: timeout\n");
+
+	return 0;
+}
+
+static void
+reset(Ctlr* ctlr)
+{
+	int r, timeo;
+
+	/*
+	 * Soft reset the controller.
+	 */
+	csr16w(ctlr, Cr, Stop);
+	csr16w(ctlr, Cr, Stop|Reset);
+	for(timeo = 0; timeo < 10000; timeo++){
+		if(!(csr16r(ctlr, Cr) & Reset))
+			break;
+		microdelay(1);
+	}
+	if(timeo >= 1000)
+		return;
+
+	/*
+	 * Load the MAC address into the PAR[01]
+	 * registers.
+	 */
+	r = csr8r(ctlr, Eecsr);
+	csr8w(ctlr, Eecsr, EeAutoLoad|r);
+	for(timeo = 0; timeo < 100; timeo++){
+		if(!(csr8r(ctlr, Cr) & EeAutoLoad))
+			break;
+		microdelay(1);
+	}
+	if(timeo >= 100)
+		return;
+
+	/*
+	 * Configure DMA and Rx/Tx thresholds.
+	 * If the Rx/Tx threshold bits in Bcr[01] are 0 then
+	 * the thresholds are determined by Rcr/Tcr.
+	 */
+	r = csr8r(ctlr, Bcr0) & ~(CrftMASK|DmaMASK);
+	csr8w(ctlr, Bcr0, r|Crft64|Dma64);
+	r = csr8r(ctlr, Bcr1) & ~CtftMASK;
+	csr8w(ctlr, Bcr1, r|Ctft64);
+
+	r = csr8r(ctlr, Rcr) & ~(RrftMASK|Prom|Ar|Sep);
+	csr8w(ctlr, Rcr, r|Ab|Am);
+
+	r = csr8r(ctlr, Tcr) & ~(RtsfMASK|Ofset|Lb1|Lb0);
+	csr8w(ctlr, Tcr, r);
+}
+
+static void
+detach(Ether* edev)
+{
+	reset(edev->ctlr);
+}
+
+static void
+init(Ether *edev)
+{
+	Ctlr *ctlr;
+	int i;
+
+	ctlr = edev->ctlr;
+	ilock(&ctlr->tlock);
+
+	pcisetbme(ctlr->pci);
+	reset(ctlr);
+
+	iow8(ctlr, Eecsr, ior8(ctlr, Eecsr) | EeAutoLoad);
+	for (i = 0; i < Nwait; ++i) {
+		if ((ior8(ctlr, Eecsr) & EeAutoLoad) == 0)
+			break;
+		delay(5);
+	}
+	if (i >= Nwait)
+		iprint("etherrhine: eeprom autoload timeout\n");
+
+	for (i = 0; i < Eaddrlen; ++i)
+		edev->ea[i] = ior8(ctlr, Eaddr + i);
+
+	ctlr->mii.mir = miiread;
+	ctlr->mii.miw = miiwrite;
+	ctlr->mii.ctlr = ctlr;
+
+	if(mii(&ctlr->mii, ~0) == 0 || ctlr->mii.curphy == nil){
+		iunlock(&ctlr->tlock);
+		iprint("etherrhine: init mii failure\n");
+		return;
+	}
+	for (i = 0; i < NMiiPhy; ++i)
+		if (ctlr->mii.phy[i])
+			if (ctlr->mii.phy[i]->oui != 0xFFFFF)
+				ctlr->mii.curphy = ctlr->mii.phy[i];
+	miistatus(&ctlr->mii);
+
+	iow16(ctlr, Imr, 0);
+	iow16(ctlr, Cr, ior16(ctlr, Cr) | Stop);
+
+	iunlock(&ctlr->tlock);
+}
+
+static Pcidev *
+rhinematch(ulong)
+{
+	static int nrhines = 0;
+	int nfound = 0;
+	Pcidev *p = nil;
+
+	while(p = pcimatch(p, 0x1106, 0)){
+		if(p->ccrb != Pcibcnet || p->ccru != Pciscether)
+			continue;
+		switch((p->did<<16)|p->vid){
+		default:
+			continue;
+		case (0x3053<<16)|0x1106:	/* Rhine III vt6105m (Soekris) */
+		case (0x3065<<16)|0x1106:	/* Rhine II */
+		case (0x3106<<16)|0x1106:	/* Rhine III */
+			if (++nfound > nrhines) {
+				nrhines++;
+				return p;
+			}
+			break;
+		}
+	}
+	return p;
+}
+
+int
+rhinepnp(Ether *edev)
+{
+	Pcidev *p;
+	Ctlr *ctlr;
+	ulong port;
+
+	if (edev->attach)
+		return 0;
+	p = rhinematch(edev->port);
+	if (p == nil)
+		return -1;
+
+	port = p->mem[0].bar & ~1;
+
+	if ((ctlr = malloc(sizeof(Ctlr))) == nil) {
+		print("etherrhine: couldn't allocate memory for ctlr\n");
+		return -1;
+	}
+	memset(ctlr, 0, sizeof(Ctlr));
+	ctlr->txd = xspanalloc(sizeof(Desc) * Ntxd, 16, 0);
+	ctlr->rxd = xspanalloc(sizeof(Desc) * Nrxd, 16, 0);
+
+	ctlr->pci = p;
+	ctlr->port = port;
+
+	edev->ctlr = ctlr;
+	edev->port = ctlr->port;
+	edev->irq = p->intl;
+	edev->tbdf = p->tbdf;
+
+	init(edev);
+
+	edev->attach = attach;
+	edev->transmit = transmit;
+	edev->interrupt = interrupt;
+	edev->detach = detach;
+
+	return 0;
+}
+
+int
+vt6102pnp(Ether *edev)
+{
+	return rhinepnp(edev);
+}
--- /dev/null
+++ b/os/boot.original/pc/fns.h
@@ -1,0 +1,175 @@
+void	aamloop(int);
+void	addconf(char*, ...);
+Alarm*	alarm(int, void (*)(Alarm*), void*);
+void	alarminit(void);
+Block*	allocb(int);
+void	apminit(void);
+int	biosboot(int dev, char *file, Boot *b);
+void*	biosgetfspart(int i, char *name, int chatty);
+void	biosinitdev(int i, char *name);
+int	biosinit(void);
+void	biosprintbootdevs(int dev);
+void	biosprintdevs(int i);
+int	bootpboot(int, char*, Boot*);
+int	bootpass(Boot*, void*, int);
+void	cancel(Alarm*);
+int	cdinit(void);
+void	check(char*);
+void	cgascreenputs(char*, int);
+int	cistrcmp(char*, char*);
+int	cistrncmp(char*, char*, int);
+void	changeconf(char*, ...);
+void	checkalarms(void);
+void	clockinit(void);
+#define coherence()	mb386()
+void	consdrain(void);
+void	consinit(char*, char*);
+void	consputs(char*, int);
+void	delay(int);
+uchar*	etheraddr(int);
+int	etherinit(void);
+void	etherinitdev(int, char*);
+void	etherprintdevs(int);
+int	etherrxflush(int);
+int	etherrxpkt(int, Etherpkt*, int);
+int	ethertxpkt(int, Etherpkt*, int, int);
+#define	evenaddr(x)		/* 386 doesn't care */
+int	floppyboot(int, char*, Boot*);
+int	floppyinit(void);
+void	floppyinitdev(int, char*);
+void	floppyprintdevs(int);
+void*	floppygetfspart(int, char*, int);
+void	freeb(Block*);
+char*	getconf(char*);
+ulong	getcr0(void);
+ulong	getcr2(void);
+ulong	getcr3(void);
+ulong	getcr4(void);
+int	getfields(char*, char**, int, char);
+int	getstr(char*, char*, int, char*, int);
+int	gunzip(uchar*, int, uchar*, int);
+void	i8042a20(void);
+void	i8042init(void);
+void	i8042reset(void);
+void*	ialloc(ulong, int);
+void	idle(void);
+void	ilock(Lock*);
+int	inb(int);
+ushort	ins(int);
+ulong	inl(int);
+void	insb(int, void*, int);
+void	inss(int, void*, int);
+void	insl(int, void*, int);
+#define ioalloc(addr, len, align, name)	(addr)
+#define iofree(addr)
+void	iunlock(Lock*);
+int	isaconfig(char*, int, ISAConf*);
+void	kbdinit(void);
+void	kbdchar(int);
+void	machinit(void);
+void	mb386(void);
+void	meminit(ulong);
+void	microdelay(int);
+void	mmuinit(void);
+#define	nelem(x)	(sizeof(x)/sizeof(x[0]))
+char*	nextelem(char*, char*);
+uchar	nvramread(int);
+void	outb(int, int);
+void	outs(int, ushort);
+void	outl(int, ulong);
+void	outsb(int, void*, int);
+void	outss(int, void*, int);
+void	outsl(int, void*, int);
+void	panic(char*, ...);
+ulong	pcibarsize(Pcidev*, int);
+int	pcicfgr8(Pcidev*, int);
+int	pcicfgr16(Pcidev*, int);
+int	pcicfgr32(Pcidev*, int);
+void	pcicfgw8(Pcidev*, int, int);
+void	pcicfgw16(Pcidev*, int, int);
+void	pcicfgw32(Pcidev*, int, int);
+void	pciclrbme(Pcidev*);
+void	pciclrioe(Pcidev*);
+void	pciclrmwi(Pcidev*);
+int	pcigetpms(Pcidev*);
+void	pcihinv(Pcidev*);
+Pcidev*	pcimatch(Pcidev*, int, int);
+uchar	pciintl(Pcidev *);
+uchar	pciipin(Pcidev *, uchar);
+void	pcireset(void);
+void	pcisetbme(Pcidev*);
+void	pcisetioe(Pcidev*);
+void	pcisetmwi(Pcidev*);
+int	pcisetpms(Pcidev*, int);
+void	pcmcisread(PCMslot*);
+int	pcmcistuple(int, int, int, void*, int);
+PCMmap*	pcmmap(int, ulong, int, int);
+int	pcmspecial(char*, ISAConf*);
+void	pcmspecialclose(int);
+void	pcmunmap(int, PCMmap*);
+void	ptcheck(char*);
+void	putcr3(ulong);
+void	putidt(Segdesc*, int);
+void*	pxegetfspart(int, char*, int);
+void	qinit(IOQ*);
+void	readlsconf(void);
+void	sdaddconf(int);
+int	sdboot(int, char*, Boot*);
+void	sdcheck(char*);
+void*	sdgetfspart(int, char*, int);
+int	sdinit(void);
+void	sdinitdev(int, char*);
+void	sdprintdevs(int);
+int	sdsetpart(int, char*);
+void	setvec(int, void (*)(Ureg*, void*), void*);
+int	splhi(void);
+int	spllo(void);
+void	splx(int);
+void	trapinit(void);
+void	trapdisable(void);
+void	trapenable(void);
+void	uartdrain(void);
+void	uartspecial(int, void (*)(int), int (*)(void), int);
+void	uartputs(IOQ*, char*, int);
+ulong	umbmalloc(ulong, int, int);
+void	umbfree(ulong, int);
+ulong	umbrwmalloc(ulong, int, int);
+void	upafree(ulong, int);
+ulong	upamalloc(ulong, int, int);
+void	warp86(char*, ulong);
+void	warp9(ulong);
+int	x86cpuid(int*, int*);
+void*	xspanalloc(ulong, int, ulong);
+
+#define malloc(n)	ialloc(n, 0)
+#define mallocz(n, c)	ialloc(n, 0)
+#define free(v)		while(0)
+
+#define	GSHORT(p)	(((p)[1]<<8)|(p)[0])
+#define	GLONG(p)	((GSHORT(p+2)<<16)|GSHORT(p))
+#define	GLSHORT(p)	(((p)[0]<<8)|(p)[1])
+#define	GLLONG(p)	(((ulong)GLSHORT(p)<<16)|GLSHORT(p+2))
+#define	PLLONG(p,v)	(p)[3]=(v);(p)[2]=(v)>>8;(p)[1]=(v)>>16;(p)[0]=(v)>>24
+
+#define KADDR(a)	((void*)((ulong)(a)|KZERO))
+#define PADDR(a)	((ulong)(a)&~0xF0000000)
+
+#define	HOWMANY(x, y)	(((x)+((y)-1))/(y))
+#define ROUNDUP(x, y)	(HOWMANY((x), (y))*(y))
+
+
+#define xalloc(n)	ialloc(n, 0)
+#define xfree(v)	while(0)
+#define lock(l)		if(l){/* nothing to do */;}else{/* nothing to do */;}
+#define unlock(l)	if(l){/* nothing to do */;}else{/* nothing to do */;}
+
+int	dmacount(int);
+int	dmadone(int);
+void	dmaend(int);
+void	dmainit(int);
+long	dmasetup(int, void*, long, int);
+
+extern int (*_pcmspecial)(char *, ISAConf *);
+extern void (*_pcmspecialclose)(int);
+extern void devi82365link(void);
+extern void devpccardlink(void);
--- /dev/null
+++ b/os/boot.original/pc/fs.c
@@ -1,0 +1,94 @@
+#include	"u.h"
+#include	"lib.h"
+#include	"mem.h"
+#include	"dat.h"
+#include	"fns.h"
+#include	"io.h"
+
+#include	"fs.h"
+
+/*
+ *  grab next element from a path, return the pointer to unprocessed portion of
+ *  path.
+ */
+char *
+nextelem(char *path, char *elem)
+{
+	int i;
+
+	while(*path == '/')
+		path++;
+	if(*path==0 || *path==' ')
+		return 0;
+	for(i=0; *path!='\0' && *path!='/' && *path!=' '; i++){
+		if(i==NAMELEN){
+			print("name component too long\n");
+			return 0;
+		}
+		*elem++ = *path++;
+	}
+	*elem = '\0';
+	return path;
+}
+
+int
+fswalk(Fs *fs, char *path, File *f)
+{
+	char element[NAMELEN];
+
+	*f = fs->root;
+	if(BADPTR(fs->walk))
+		panic("fswalk bad pointer fs->walk");
+
+	f->path = path;
+	while(path = nextelem(path, element)){
+		switch(fs->walk(f, element)){
+		case -1:
+			return -1;
+		case 0:
+			return 0;
+		}
+	}
+	return 1;
+}
+
+/*
+ *  boot
+ */
+int
+fsboot(Fs *fs, char *path, Boot *b)
+{
+	File file;
+	long n;
+	static char buf[8192];
+
+	switch(fswalk(fs, path, &file)){
+	case -1:
+		print("error walking to %s\n", path);
+		return -1;
+	case 0:
+		print("%s not found\n", path);
+		return -1;
+	case 1:
+		print("found %s\n", path);
+		break;
+	}
+
+	while((n = fsread(&file, buf, sizeof buf)) > 0) {
+		if(bootpass(b, buf, n) != MORE)
+			break;
+	}
+
+	bootpass(b, nil, 0);	/* tries boot */
+	return -1;
+}
+
+int
+fsread(File *file, void *a, long n)
+{
+	if(BADPTR(file->fs))
+		panic("bad pointer file->fs in fsread");
+	if(BADPTR(file->fs->read))
+		panic("bad pointer file->fs->read in fsread");
+	return file->fs->read(file, a, n);
+}
--- /dev/null
+++ b/os/boot.original/pc/fs.h
@@ -1,0 +1,36 @@
+typedef struct File File;
+typedef struct Fs Fs;
+
+#include "dosfs.h"
+#include "kfs.h"
+
+struct File{
+	union{
+		Dosfile	dos;
+		Kfsfile	kfs;
+		int walked;
+	};
+	Fs	*fs;
+	char	*path;
+};
+
+struct Fs{
+	union {
+		Dos dos;
+		Kfs kfs;
+	};
+	int	dev;				/* device id */
+	long	(*diskread)(Fs*, void*, long);	/* disk read routine */
+	vlong	(*diskseek)(Fs*, vlong);	/* disk seek routine */
+	long	(*read)(File*, void*, long);
+	int	(*walk)(File*, char*);
+	File	root;
+};
+
+extern int chatty;
+extern int dotini(Fs*);
+extern int fswalk(Fs*, char*, File*);
+extern int fsread(File*, void*, long);
+extern int fsboot(Fs*, char*, Boot*);
+
+#define BADPTR(x) ((ulong)x < 0x80000000)
--- /dev/null
+++ b/os/boot.original/pc/getcallerpc.c
@@ -1,0 +1,8 @@
+#include "u.h"
+#include "lib.h"
+
+ulong
+getcallerpc(void *x)
+{
+	return (((ulong*)(x))[-1]);
+}
--- /dev/null
+++ b/os/boot.original/pc/ilock.c
@@ -1,0 +1,24 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+void
+ilock(Lock *lk)
+{
+	if(lk->locked != 0)
+		panic("ilock");
+	lk->spl = splhi();
+	lk->locked = 1;
+}
+
+void
+iunlock(Lock *lk)
+{
+	if(lk->locked != 1)
+		panic("iunlock");
+	lk->locked = 0;
+	splx(lk->spl);
+}
--- /dev/null
+++ b/os/boot.original/pc/inflate.c
@@ -1,0 +1,199 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include <flate.h>
+
+typedef struct Biobuf	Biobuf;
+
+struct Biobuf
+{
+	uchar *bp;
+	uchar *p;
+	uchar *ep;
+};
+
+static int	header(Biobuf*);
+static int	trailer(Biobuf*, Biobuf*);
+static int	getc(void*);
+static ulong	offset(Biobuf*);
+static int	crcwrite(void *out, void *buf, int n);
+static ulong	get4(Biobuf *b);
+static ulong	Boffset(Biobuf *bp);
+
+/* GZIP flags */
+enum {
+	Ftext=		(1<<0),
+	Fhcrc=		(1<<1),
+	Fextra=		(1<<2),
+	Fname=		(1<<3),
+	Fcomment=	(1<<4),
+
+	GZCRCPOLY	= 0xedb88320UL,
+};
+
+static ulong	*crctab;
+static ulong	crc;
+
+extern void diff(char*);	//XXX
+int
+gunzip(uchar *out, int outn, uchar *in, int inn)
+{
+	Biobuf bin, bout;
+	int err;
+
+	crc = 0;
+	crctab = mkcrctab(GZCRCPOLY);
+	err = inflateinit();
+	if(err != FlateOk)
+		print("inflateinit failed: %s\n", flateerr(err));
+
+	bin.bp = bin.p = in;
+	bin.ep = in+inn;
+	bout.bp = bout.p = out;
+	bout.ep = out+outn;
+
+	err = header(&bin);
+	if(err != FlateOk)
+		return err;
+
+	err = inflate(&bout, crcwrite, &bin, getc);
+	if(err != FlateOk)
+		print("inflate failed: %s\n", flateerr(err));
+
+	err = trailer(&bout, &bin);
+	if(err != FlateOk)
+		return err;
+
+	return Boffset(&bout);
+}
+
+static int
+header(Biobuf *bin)
+{
+	int i, flag;
+
+	if(getc(bin) != 0x1f || getc(bin) != 0x8b){
+		print("bad magic\n");
+		return FlateCorrupted;
+	}
+	if(getc(bin) != 8){
+		print("unknown compression type\n");
+		return FlateCorrupted;
+	}
+	
+	flag = getc(bin);
+	
+	/* mod time */
+	get4(bin);
+	
+	/* extra flags */
+	getc(bin);
+	
+	/* OS type */
+	getc(bin);
+
+	if(flag & Fextra)
+		for(i=getc(bin); i>0; i--)
+			getc(bin);
+	
+	/* name */
+	if(flag&Fname)
+		while(getc(bin) != 0)
+			;
+
+	/* comment */
+	if(flag&Fcomment)
+		while(getc(bin) != 0)
+			;
+
+	/* crc16 */
+	if(flag&Fhcrc) {
+		getc(bin);
+		getc(bin);
+	}
+		
+	return FlateOk;
+}
+
+static int
+trailer(Biobuf *bout, Biobuf *bin)
+{
+	/* crc32 */
+	if(crc != get4(bin)){
+		print("crc mismatch\n");
+		return FlateCorrupted;
+	}
+
+	/* length */
+	if(get4(bin) != Boffset(bout)){
+		print("bad output len\n");
+		return FlateCorrupted;
+	}
+	return FlateOk;
+}
+
+static ulong
+get4(Biobuf *b)
+{
+	ulong v;
+	int i, c;
+
+	v = 0;
+	for(i = 0; i < 4; i++){
+		c = getc(b);
+		v |= c << (i * 8);
+	}
+	return v;
+}
+
+static int
+getc(void *in)
+{
+	Biobuf *bp = in;
+
+//	if((bp->p - bp->bp) % 10000 == 0)
+//		print(".");
+	if(bp->p >= bp->ep)
+		return -1;
+	return *bp->p++;
+}
+
+static ulong
+Boffset(Biobuf *bp)
+{
+	return bp->p - bp->bp;
+}
+
+static int
+crcwrite(void *out, void *buf, int n)
+{
+	Biobuf *bp;
+	int nn;
+
+	crc = blockcrc(crctab, crc, buf, n);
+	bp = out;
+	nn = n;
+	if(nn > bp->ep-bp->p)
+		nn = bp->ep-bp->p;
+	if(nn > 0)
+		memmove(bp->p, buf, nn);
+	bp->p += n;
+	return n;
+}
+
+#undef malloc
+#undef free
+
+void *
+malloc(ulong n)
+{
+	return ialloc(n, 8);
+}
+
+void
+free(void *)
+{
+}
--- /dev/null
+++ b/os/boot.original/pc/io.h
@@ -1,0 +1,317 @@
+/*
+ *  programmable interrupt vectors (for the 8259's)
+ */
+enum
+{
+	Bptvec=		3,		/* breakpoints */
+	Mathemuvec=	7,		/* math coprocessor emulation interrupt */
+	Mathovervec=	9,		/* math coprocessor overrun interrupt */
+	Matherr1vec=	16,		/* math coprocessor error interrupt */
+	Faultvec=	14,		/* page fault */
+
+	Syscallvec=	64,
+
+	VectorPIC	= 24,		/* external [A]PIC interrupts */
+	VectorCLOCK	= VectorPIC+0,
+	VectorKBD	= VectorPIC+1,
+	VectorUART1	= VectorPIC+3,
+	VectorUART0	= VectorPIC+4,
+	VectorPCMCIA	= VectorPIC+5,
+	VectorFLOPPY	= VectorPIC+6,
+	VectorLPT	= VectorPIC+7,
+	VectorIRQ7	= VectorPIC+7,
+	VectorAUX	= VectorPIC+12,	/* PS/2 port */
+	VectorIRQ13	= VectorPIC+13,	/* coprocessor on x386 */
+	VectorATA0	= VectorPIC+14,
+	VectorATA1	= VectorPIC+15,
+	MaxVectorPIC	= VectorPIC+15,
+};
+
+enum {
+	BusCBUS		= 0,		/* Corollary CBUS */
+	BusCBUSII,			/* Corollary CBUS II */
+	BusEISA,			/* Extended ISA */
+	BusFUTURE,			/* IEEE Futurebus */
+	BusINTERN,			/* Internal bus */
+	BusISA,				/* Industry Standard Architecture */
+	BusMBI,				/* Multibus I */
+	BusMBII,			/* Multibus II */
+	BusMCA,				/* Micro Channel Architecture */
+	BusMPI,				/* MPI */
+	BusMPSA,			/* MPSA */
+	BusNUBUS,			/* Apple Macintosh NuBus */
+	BusPCI,				/* Peripheral Component Interconnect */
+	BusPCMCIA,			/* PC Memory Card International Association */
+	BusTC,				/* DEC TurboChannel */
+	BusVL,				/* VESA Local bus */
+	BusVME,				/* VMEbus */
+	BusXPRESS,			/* Express System Bus */
+};
+
+#define MKBUS(t,b,d,f)	(((t)<<24)|(((b)&0xFF)<<16)|(((d)&0x1F)<<11)|(((f)&0x07)<<8))
+#define BUSFNO(tbdf)	(((tbdf)>>8)&0x07)
+#define BUSDNO(tbdf)	(((tbdf)>>11)&0x1F)
+#define BUSBNO(tbdf)	(((tbdf)>>16)&0xFF)
+#define BUSTYPE(tbdf)	((tbdf)>>24)
+#define BUSBDF(tbdf)	((tbdf)&0x00FFFF00)
+#define BUSUNKNOWN	(-1)
+
+enum {
+	MaxEISA		= 16,
+	CfgEISA		= 0xC80,
+};
+
+/*
+ * PCI support code.
+ */
+enum {					/* type 0 and type 1 pre-defined header */
+	PciVID		= 0x00,		/* vendor ID */
+	PciDID		= 0x02,		/* device ID */
+	PciPCR		= 0x04,		/* command */
+	PciPSR		= 0x06,		/* status */
+	PciRID		= 0x08,		/* revision ID */
+	PciCCRp		= 0x09,		/* programming interface class code */
+	PciCCRu		= 0x0A,		/* sub-class code */
+	PciCCRb		= 0x0B,		/* base class code */
+	PciCLS		= 0x0C,		/* cache line size */
+	PciLTR		= 0x0D,		/* latency timer */
+	PciHDT		= 0x0E,		/* header type */
+	PciBST		= 0x0F,		/* BIST */
+
+	PciBAR0		= 0x10,		/* base address */
+	PciBAR1		= 0x14,
+
+	PciINTL		= 0x3C,		/* interrupt line */
+	PciINTP		= 0x3D,		/* interrupt pin */
+};
+
+/* ccrb (base class code) values; controller types */
+enum {
+	Pcibcpci1	= 0,		/* pci 1.0; no class codes defined */
+	Pcibcstore	= 1,		/* mass storage */
+	Pcibcnet	= 2,		/* network */
+	Pcibcdisp	= 3,		/* display */
+	Pcibcmmedia	= 4,		/* multimedia */
+	Pcibcmem	= 5,		/* memory */
+	Pcibcbridge	= 6,		/* bridge */
+	Pcibccomm	= 7,		/* simple comms (e.g., serial) */
+	Pcibcbasesys	= 8,		/* base system */
+	Pcibcinput	= 9,		/* input */
+	Pcibcdock	= 0xa,		/* docking stations */
+	Pcibcproc	= 0xb,		/* processors */
+	Pcibcserial	= 0xc,		/* serial bus (e.g., USB) */
+	Pcibcwireless	= 0xd,		/* wireless */
+	Pcibcintell	= 0xe,		/* intelligent i/o */
+	Pcibcsatcom	= 0xf,		/* satellite comms */
+	Pcibccrypto	= 0x10,		/* encryption/decryption */
+	Pcibcdacq	= 0x11,		/* data acquisition & signal proc. */
+};
+
+/* ccru (sub-class code) values; common cases only */
+enum {
+	/* mass storage */
+	Pciscscsi	= 0,		/* SCSI */
+	Pciscide	= 1,		/* IDE (ATA) */
+
+	/* network */
+	Pciscether	= 0,		/* Ethernet */
+
+	/* display */
+	Pciscvga	= 0,		/* VGA */
+	Pciscxga	= 1,		/* XGA */
+	Pcisc3d		= 2,		/* 3D */
+
+	/* bridges */
+	Pcischostpci	= 0,		/* host/pci */
+	Pciscpcicpci	= 1,		/* pci/pci */
+
+	/* simple comms */
+	Pciscserial	= 0,		/* 16450, etc. */
+	Pciscmultiser	= 1,		/* multiport serial */
+
+	/* serial bus */
+	Pciscusb	= 3,		/* USB */
+};
+
+enum {					/* type 0 pre-defined header */
+	PciBAR2		= 0x18,
+	PciBAR3		= 0x1C,
+	PciBAR4		= 0x20,
+	PciBAR5		= 0x24,
+	PciCIS		= 0x28,		/* cardbus CIS pointer */
+	PciSVID		= 0x2C,		/* subsystem vendor ID */
+	PciSID		= 0x2E,		/* cardbus CIS pointer */
+	PciEBAR0	= 0x30,		/* expansion ROM base address */
+	PciMGNT		= 0x3E,		/* burst period length */
+	PciMLT		= 0x3F,		/* maximum latency between bursts */
+};
+
+enum {					/* type 1 pre-defined header */
+	PciPBN		= 0x18,		/* primary bus number */
+	PciSBN		= 0x19,		/* secondary bus number */
+	PciUBN		= 0x1A,		/* subordinate bus number */
+	PciSLTR		= 0x1B,		/* secondary latency timer */
+	PciIBR		= 0x1C,		/* I/O base */
+	PciILR		= 0x1D,		/* I/O limit */
+	PciSPSR		= 0x1E,		/* secondary status */
+	PciMBR		= 0x20,		/* memory base */
+	PciMLR		= 0x22,		/* memory limit */
+	PciPMBR		= 0x24,		/* prefetchable memory base */
+	PciPMLR		= 0x26,		/* prefetchable memory limit */
+	PciPUBR		= 0x28,		/* prefetchable base upper 32 bits */
+	PciPULR		= 0x2C,		/* prefetchable limit upper 32 bits */
+	PciIUBR		= 0x30,		/* I/O base upper 16 bits */
+	PciIULR		= 0x32,		/* I/O limit upper 16 bits */
+	PciEBAR1	= 0x28,		/* expansion ROM base address */
+	PciBCR		= 0x3E,		/* bridge control register */
+};
+
+enum {					/* type 2 pre-defined header */
+	PciCBExCA	= 0x10,
+	PciCBSPSR	= 0x16,
+	PciCBPBN	= 0x18,		/* primary bus number */
+	PciCBSBN	= 0x19,		/* secondary bus number */
+	PciCBUBN	= 0x1A,		/* subordinate bus number */
+	PciCBSLTR	= 0x1B,		/* secondary latency timer */
+	PciCBMBR0	= 0x1C,
+	PciCBMLR0	= 0x20,
+	PciCBMBR1	= 0x24,
+	PciCBMLR1	= 0x28,
+	PciCBIBR0	= 0x2C,		/* I/O base */
+	PciCBILR0	= 0x30,		/* I/O limit */
+	PciCBIBR1	= 0x34,		/* I/O base */
+	PciCBILR1	= 0x38,		/* I/O limit */
+	PciCBBCTL	= 0x3E,		/* Bridge control */
+	PciCBSVID	= 0x40,		/* subsystem vendor ID */
+	PciCBSID	= 0x42,		/* subsystem ID */
+	PciCBLMBAR	= 0x44,		/* legacy mode base address */
+};
+
+typedef struct Pcisiz Pcisiz;
+struct Pcisiz
+{
+	Pcidev*	dev;
+	int	siz;
+	int	bar;
+};
+
+typedef struct Pcidev Pcidev;
+typedef struct Pcidev {
+	int	tbdf;			/* type+bus+device+function */
+	ushort	vid;			/* vendor ID */
+	ushort	did;			/* device ID */
+
+	ushort	pcr;
+
+	uchar	rid;
+	uchar	ccrp;
+	uchar	ccru;
+	uchar	ccrb;
+	uchar	cls;
+	uchar	ltr;
+
+	struct {
+		ulong	bar;		/* base address */
+		int	size;
+	} mem[6];
+
+	struct {
+		ulong	bar;
+		int	size;
+	} rom;
+	uchar	intl;			/* interrupt line */
+
+	Pcidev*	list;
+	Pcidev*	link;			/* next device on this bno */
+
+	Pcidev*	bridge;			/* down a bus */
+	struct {
+		ulong	bar;
+		int	size;
+	} ioa, mema;
+
+	int	pmrb;			/* power management register block */
+};
+
+#define PCIWINDOW	0
+#define PCIWADDR(va)	(PADDR(va)+PCIWINDOW)
+#define ISAWINDOW	0
+#define ISAWADDR(va)	(PADDR(va)+ISAWINDOW)
+
+/*
+ * PCMCIA support code.
+ */
+typedef struct PCMslot		PCMslot;
+typedef struct PCMconftab	PCMconftab;
+
+/*
+ * Map between ISA memory space and PCMCIA card memory space.
+ */
+struct PCMmap {
+	ulong	ca;			/* card address */
+	ulong	cea;			/* card end address */
+	ulong	isa;			/* ISA address */
+	int	len;			/* length of the ISA area */
+	int	attr;			/* attribute memory */
+	int	ref;
+};
+
+/* configuration table entry */
+struct PCMconftab
+{
+	int	index;
+	ushort	irqs;		/* legal irqs */
+	uchar	irqtype;
+	uchar	bit16;		/* true for 16 bit access */
+	struct {
+		ulong	start;
+		ulong	len;
+	} io[16];
+	int	nio;
+	uchar	vpp1;
+	uchar	vpp2;
+	uchar	memwait;
+	ulong	maxwait;
+	ulong	readywait;
+	ulong	otherwait;
+};
+
+/* a card slot */
+struct PCMslot
+{
+	Lock;
+	int	ref;
+
+	void	*cp;		/* controller for this slot */
+	long	memlen;		/* memory length */
+	uchar	base;		/* index register base */
+	uchar	slotno;		/* slot number */
+
+	/* status */
+	uchar	special;	/* in use for a special device */
+	uchar	already;	/* already inited */
+	uchar	occupied;
+	uchar	battery;
+	uchar	wrprot;
+	uchar	powered;
+	uchar	configed;
+	uchar	enabled;
+	uchar	busy;
+
+	/* cis info */
+	ulong	msec;		/* time of last slotinfo call */
+	char	verstr[512];	/* version string */
+	int	ncfg;		/* number of configurations */
+	struct {
+		ushort	cpresent;	/* config registers present */
+		ulong	caddr;		/* relative address of config registers */
+	} cfg[8];
+	int	nctab;		/* number of config table entries */
+	PCMconftab	ctab[8];
+	PCMconftab	*def;	/* default conftab */
+
+	/* memory maps */
+	Lock	mlock;		/* lock down the maps */
+	int	time;
+	PCMmap	mmap[4];	/* maps, last is always for the kernel */
+};
--- /dev/null
+++ b/os/boot.original/pc/ip.h
@@ -1,0 +1,100 @@
+typedef struct Udphdr Udphdr;
+struct Udphdr
+{
+	uchar	d[6];		/* Ethernet destination */
+	uchar	s[6];		/* Ethernet source */
+	uchar	type[2];	/* Ethernet packet type */
+
+	uchar	vihl;		/* Version and header length */
+	uchar	tos;		/* Type of service */
+	uchar	length[2];	/* packet length */
+	uchar	id[2];		/* Identification */
+	uchar	frag[2];	/* Fragment information */
+
+	/* Udp pseudo ip really starts here */
+	uchar	ttl;	
+	uchar	udpproto;	/* Protocol */
+	uchar	udpplen[2];	/* Header plus data length */
+	uchar	udpsrc[4];	/* Ip source */
+	uchar	udpdst[4];	/* Ip destination */
+	uchar	udpsport[2];	/* Source port */
+	uchar	udpdport[2];	/* Destination port */
+	uchar	udplen[2];	/* data length */
+	uchar	udpcksum[2];	/* Checksum */
+};
+
+typedef struct Etherhdr Etherhdr;
+struct Etherhdr
+{
+	uchar	d[6];
+	uchar	s[6];
+	uchar	type[2];
+
+	/* Now we have the ip fields */
+	uchar	vihl;		/* Version and header length */
+	uchar	tos;		/* Type of service */
+	uchar	length[2];	/* packet length */
+	uchar	id[2];		/* Identification */
+	uchar	frag[2];	/* Fragment information */
+	uchar	ttl;		/* Time to live */
+	uchar	proto;		/* Protocol */
+	uchar	cksum[2];	/* Header checksum */
+	uchar	src[4];		/* Ip source */
+	uchar	dst[4];		/* Ip destination */
+};
+
+enum
+{
+	IP_VER		= 0x40,
+	IP_HLEN		= 0x05,			
+ 	UDP_EHSIZE	= 22,
+	UDP_PHDRSIZE	= 12,
+	UDP_HDRSIZE	= 20,
+	ETHER_HDR	= 14,
+	IP_UDPPROTO	= 17,
+	ET_IP		= 0x800,
+	Bcastip		= 0xffffffff,
+	BPportsrc	= 68,
+	BPportdst	= 67,
+	TFTPport	= 69,
+	Timeout		= 5000,	/* milliseconds */
+	Bootrequest 	= 1,
+	Bootreply   	= 2,
+	Tftp_READ	= 1,
+	Tftp_WRITE	= 2,
+	Tftp_DATA	= 3,
+	Tftp_ACK	= 4,
+	Tftp_ERROR	= 5,
+	Segsize		= 512,
+	TFTPSZ		= Segsize+10,
+};
+
+typedef struct Bootp Bootp;
+struct Bootp
+{
+	uchar	op;		/* opcode */
+	uchar	htype;		/* hardware type */
+	uchar	hlen;		/* hardware address len */
+	uchar	hops;		/* hops */
+	uchar	xid[4];		/* a random number */
+	uchar	secs[2];	/* elapsed since client started booting */
+	uchar	pad[2];
+	uchar	ciaddr[4];	/* client IP address (client tells server) */
+	uchar	yiaddr[4];	/* client IP address (server tells client) */
+	uchar	siaddr[4];	/* server IP address */
+	uchar	giaddr[4];	/* gateway IP address */
+	uchar	chaddr[16];	/* client hardware address */
+	char	sname[64];	/* server host name (optional) */
+	char	file[128];	/* boot file name */
+	char	vend[128];	/* vendor-specific goo */
+};
+
+typedef struct Netaddr Netaddr;
+struct Netaddr
+{
+	ulong	ip;
+	ushort	port;
+	char	ea[Eaddrlen];
+};
+
+extern int	eipfmt(Fmt*);
--- /dev/null
+++ b/os/boot.original/pc/kbd.c
@@ -1,0 +1,489 @@
+#include	"u.h"
+#include	"lib.h"
+#include	"mem.h"
+#include	"dat.h"
+#include	"fns.h"
+#include	"io.h"
+
+enum {
+	Data=		0x60,	/* data port */
+
+	Status=		0x64,	/* status port */
+	 Inready=	0x01,	/*  input character ready */
+	 Outbusy=	0x02,	/*  output busy */
+	 Sysflag=	0x04,	/*  system flag */
+	 Cmddata=	0x08,	/*  cmd==0, data==1 */
+	 Inhibit=	0x10,	/*  keyboard/mouse inhibited */
+	 Minready=	0x20,	/*  mouse character ready */
+	 Rtimeout=	0x40,	/*  general timeout */
+	 Parity=	0x80,
+
+	Cmd=		0x64,	/* command port (write only) */
+ 
+	Spec=	0x80,
+
+	PF=	Spec|0x20,	/* num pad function key */
+	View=	Spec|0x00,	/* view (shift window up) */
+	KF=	Spec|0x40,	/* function key */
+	Shift=	Spec|0x60,
+	Break=	Spec|0x61,
+	Ctrl=	Spec|0x62,
+	Latin=	Spec|0x63,
+	Caps=	Spec|0x64,
+	Num=	Spec|0x65,
+	No=	Spec|0x7F,	/* no mapping */
+
+	Home=	KF|13,
+	Up=	KF|14,
+	Pgup=	KF|15,
+	Print=	KF|16,
+	Left=	View,
+	Right=	View,
+	End=	'\r',
+	Down=	View,
+	Pgdown=	View,
+	Ins=	KF|20,
+	Del=	0x7F,
+};
+
+uchar kbtab[] = 
+{
+[0x00]	No,	0x1b,	'1',	'2',	'3',	'4',	'5',	'6',
+[0x08]	'7',	'8',	'9',	'0',	'-',	'=',	'\b',	'\t',
+[0x10]	'q',	'w',	'e',	'r',	't',	'y',	'u',	'i',
+[0x18]	'o',	'p',	'[',	']',	'\n',	Ctrl,	'a',	's',
+[0x20]	'd',	'f',	'g',	'h',	'j',	'k',	'l',	';',
+[0x28]	'\'',	'`',	Shift,	'\\',	'z',	'x',	'c',	'v',
+[0x30]	'b',	'n',	'm',	',',	'.',	'/',	Shift,	No,
+[0x38]	Latin,	' ',	Caps,	KF|1,	KF|2,	KF|3,	KF|4,	KF|5,
+[0x40]	KF|6,	KF|7,	KF|8,	KF|9,	KF|10,	Num,	KF|12,	Home,
+[0x48]	No,	No,	No,	No,	No,	No,	No,	No,
+[0x50]	No,	No,	No,	No,	No,	No,	No,	KF|11,
+[0x58]	KF|12,	No,	No,	No,	No,	No,	No,	No,
+};
+
+uchar kbtabshift[] =
+{
+[0x00]	No,	0x1b,	'!',	'@',	'#',	'$',	'%',	'^',
+[0x08]	'&',	'*',	'(',	')',	'_',	'+',	'\b',	'\t',
+[0x10]	'Q',	'W',	'E',	'R',	'T',	'Y',	'U',	'I',
+[0x18]	'O',	'P',	'{',	'}',	'\n',	Ctrl,	'A',	'S',
+[0x20]	'D',	'F',	'G',	'H',	'J',	'K',	'L',	':',
+[0x28]	'"',	'~',	Shift,	'|',	'Z',	'X',	'C',	'V',
+[0x30]	'B',	'N',	'M',	'<',	'>',	'?',	Shift,	No,
+[0x38]	Latin,	' ',	Caps,	KF|1,	KF|2,	KF|3,	KF|4,	KF|5,
+[0x40]	KF|6,	KF|7,	KF|8,	KF|9,	KF|10,	Num,	KF|12,	Home,
+[0x48]	No,	No,	No,	No,	No,	No,	No,	No,
+[0x50]	No,	No,	No,	No,	No,	No,	No,	KF|11,
+[0x58]	KF|12,	No,	No,	No,	No,	No,	No,	No,
+};
+
+uchar kbtabesc1[] =
+{
+[0x00]	No,	No,	No,	No,	No,	No,	No,	No,
+[0x08]	No,	No,	No,	No,	No,	No,	No,	No,
+[0x10]	No,	No,	No,	No,	No,	No,	No,	No,
+[0x18]	No,	No,	No,	No,	No,	Ctrl,	No,	No,
+[0x20]	No,	No,	No,	No,	No,	No,	No,	No,
+[0x28]	No,	No,	No,	No,	No,	No,	No,	No,
+[0x30]	No,	No,	No,	No,	No,	No,	No,	Print,
+[0x38]	Latin,	No,	No,	No,	No,	No,	No,	No,
+[0x40]	No,	No,	No,	No,	No,	No,	Break,	Home,
+[0x48]	Up,	Pgup,	No,	Down,	No,	Right,	No,	End,
+[0x50]	Left,	Pgdown,	Ins,	Del,	No,	No,	No,	No,
+[0x58]	No,	No,	No,	No,	No,	No,	No,	No,
+};
+
+struct latin
+{
+	uchar	l;
+	char	c[2];
+}latintab[] = {
+	L'¡',	"!!",	/* spanish initial ! */
+	L'¢',	"c|",	/* cent */
+	L'¢',	"c$",	/* cent */
+	L'£',	"l$",	/* pound sterling */
+	L'¤',	"g$",	/* general currency */
+	L'¥',	"y$",	/* yen */
+	L'¥',	"j$",	/* yen */
+	L'¦',	"||",	/* broken vertical bar */
+	L'§',	"SS",	/* section symbol */
+	L'¨',	"\"\"",	/* dieresis */
+	L'©',	"cr",	/* copyright */
+	L'©',	"cO",	/* copyright */
+	L'ª',	"sa",	/* super a, feminine ordinal */
+	L'«',	"<<",	/* left angle quotation */
+	L'¬',	"no",	/* not sign, hooked overbar */
+	L'­',	"--",	/* soft hyphen */
+	L'®',	"rg",	/* registered trademark */
+	L'¯',	"__",	/* macron */
+	L'°',	"s0",	/* degree (sup o) */
+	L'±',	"+-",	/* plus-minus */
+	L'²',	"s2",	/* sup 2 */
+	L'³',	"s3",	/* sup 3 */
+	L'´',	"''",	/* grave accent */
+	L'µ',	"mu",	/* mu */
+	L'¶',	"pg",	/* paragraph (pilcrow) */
+	L'·',	"..",	/* centered . */
+	L'¸',	",,",	/* cedilla */
+	L'¹',	"s1",	/* sup 1 */
+	L'º',	"so",	/* sup o */
+	L'»',	">>",	/* right angle quotation */
+	L'¼',	"14",	/* 1/4 */
+	L'½',	"12",	/* 1/2 */
+	L'¾',	"34",	/* 3/4 */
+	L'¿',	"??",	/* spanish initial ? */
+	L'À',	"A`",	/* A grave */
+	L'Á',	"A'",	/* A acute */
+	L'Â',	"A^",	/* A circumflex */
+	L'Ã',	"A~",	/* A tilde */
+	L'Ä',	"A\"",	/* A dieresis */
+	L'Ä',	"A:",	/* A dieresis */
+	L'Å',	"Ao",	/* A circle */
+	L'Å',	"AO",	/* A circle */
+	L'Æ',	"Ae",	/* AE ligature */
+	L'Æ',	"AE",	/* AE ligature */
+	L'Ç',	"C,",	/* C cedilla */
+	L'È',	"E`",	/* E grave */
+	L'É',	"E'",	/* E acute */
+	L'Ê',	"E^",	/* E circumflex */
+	L'Ë',	"E\"",	/* E dieresis */
+	L'Ë',	"E:",	/* E dieresis */
+	L'Ì',	"I`",	/* I grave */
+	L'Í',	"I'",	/* I acute */
+	L'Î',	"I^",	/* I circumflex */
+	L'Ï',	"I\"",	/* I dieresis */
+	L'Ï',	"I:",	/* I dieresis */
+	L'Ð',	"D-",	/* Eth */
+	L'Ñ',	"N~",	/* N tilde */
+	L'Ò',	"O`",	/* O grave */
+	L'Ó',	"O'",	/* O acute */
+	L'Ô',	"O^",	/* O circumflex */
+	L'Õ',	"O~",	/* O tilde */
+	L'Ö',	"O\"",	/* O dieresis */
+	L'Ö',	"O:",	/* O dieresis */
+	L'Ö',	"OE",	/* O dieresis */
+	L'Ö',	"Oe",	/* O dieresis */
+	L'×',	"xx",	/* times sign */
+	L'Ø',	"O/",	/* O slash */
+	L'Ù',	"U`",	/* U grave */
+	L'Ú',	"U'",	/* U acute */
+	L'Û',	"U^",	/* U circumflex */
+	L'Ü',	"U\"",	/* U dieresis */
+	L'Ü',	"U:",	/* U dieresis */
+	L'Ü',	"UE",	/* U dieresis */
+	L'Ü',	"Ue",	/* U dieresis */
+	L'Ý',	"Y'",	/* Y acute */
+	L'Þ',	"P|",	/* Thorn */
+	L'Þ',	"Th",	/* Thorn */
+	L'Þ',	"TH",	/* Thorn */
+	L'ß',	"ss",	/* sharp s */
+	L'à',	"a`",	/* a grave */
+	L'á',	"a'",	/* a acute */
+	L'â',	"a^",	/* a circumflex */
+	L'ã',	"a~",	/* a tilde */
+	L'ä',	"a\"",	/* a dieresis */
+	L'ä',	"a:",	/* a dieresis */
+	L'å',	"ao",	/* a circle */
+	L'æ',	"ae",	/* ae ligature */
+	L'ç',	"c,",	/* c cedilla */
+	L'è',	"e`",	/* e grave */
+	L'é',	"e'",	/* e acute */
+	L'ê',	"e^",	/* e circumflex */
+	L'ë',	"e\"",	/* e dieresis */
+	L'ë',	"e:",	/* e dieresis */
+	L'ì',	"i`",	/* i grave */
+	L'í',	"i'",	/* i acute */
+	L'î',	"i^",	/* i circumflex */
+	L'ï',	"i\"",	/* i dieresis */
+	L'ï',	"i:",	/* i dieresis */
+	L'ð',	"d-",	/* eth */
+	L'ñ',	"n~",	/* n tilde */
+	L'ò',	"o`",	/* o grave */
+	L'ó',	"o'",	/* o acute */
+	L'ô',	"o^",	/* o circumflex */
+	L'õ',	"o~",	/* o tilde */
+	L'ö',	"o\"",	/* o dieresis */
+	L'ö',	"o:",	/* o dieresis */
+	L'ö',	"oe",	/* o dieresis */
+	L'÷',	"-:",	/* divide sign */
+	L'ø',	"o/",	/* o slash */
+	L'ù',	"u`",	/* u grave */
+	L'ú',	"u'",	/* u acute */
+	L'û',	"u^",	/* u circumflex */
+	L'ü',	"u\"",	/* u dieresis */
+	L'ü',	"u:",	/* u dieresis */
+	L'ü',	"ue",	/* u dieresis */
+	L'ý',	"y'",	/* y acute */
+	L'þ',	"th",	/* thorn */
+	L'þ',	"p|",	/* thorn */
+	L'ÿ',	"y\"",	/* y dieresis */
+	L'ÿ',	"y:",	/* y dieresis */
+	0,	0,
+};
+
+enum
+{
+	/* controller command byte */
+	Cscs1=		(1<<6),		/* scan code set 1 */
+	Cmousedis=	(1<<5),		/* mouse disable */
+	Ckbddis=	(1<<4),		/* kbd disable */
+	Csf=		(1<<2),		/* system flag */
+	Cmouseint=	(1<<1),		/* mouse interrupt enable */
+	Ckbdint=	(1<<0),		/* kbd interrupt enable */
+};
+
+static uchar ccc;
+
+int
+latin1(int k1, int k2)
+{
+	struct latin *l;
+
+	for(l=latintab; l->l; l++)
+		if(k1==l->c[0] && k2==l->c[1])
+			return l->l;
+	return 0;
+}
+
+/*
+ *  wait for output no longer busy
+ */
+static int
+outready(void)
+{
+	int tries;
+
+	for(tries = 0; (inb(Status) & Outbusy); tries++){
+		if(tries > 500)
+			return -1;
+		delay(2);
+	}
+	return 0;
+}
+
+/*
+ *  wait for input
+ */
+static int
+inready(void)
+{
+	int tries;
+
+	for(tries = 0; !(inb(Status) & Inready); tries++){
+		if(tries > 500)
+			return -1;
+		delay(2);
+	}
+	return 0;
+}
+
+/*
+ *  ask 8042 to enable the use of address bit 20
+ */
+void
+i8042a20(void)
+{
+	outready();
+	outb(Cmd, 0xD1);
+	outready();
+	outb(Data, 0xDF);
+	outready();
+}
+
+/*
+ *  ask 8042 to reset the machine
+ */
+void
+i8042reset(void)
+{
+	int i, x;
+#ifdef notdef
+	ushort *s = (ushort*)(KZERO|0x472);
+
+	*s = 0x1234;		/* BIOS warm-boot flag */
+#endif /* notdef */
+
+	outready();
+	outb(Cmd, 0xFE);	/* pulse reset line (means resend on AT&T machines) */
+	outready();
+
+	/*
+	 *  Pulse it by hand (old somewhat reliable)
+	 */
+	x = 0xDF;
+	for(i = 0; i < 5; i++){
+		x ^= 1;
+		outready();
+		outb(Cmd, 0xD1);
+		outready();
+		outb(Data, x);	/* toggle reset */
+		delay(100);
+	}
+}
+
+/*
+ *  keyboard interrupt
+ */
+static void
+i8042intr(Ureg*, void*)
+{
+	int s, c;
+	static int esc1, esc2;
+	static int alt, caps, ctl, num, shift;
+	static int lstate, k1, k2;
+	int keyup;
+
+	/*
+	 *  get status
+	 */
+	s = inb(Status);
+	if(!(s&Inready))
+		return;
+
+	/*
+	 *  get the character
+	 */
+	c = inb(Data);
+
+	/*
+	 *  if it's the aux port...
+	 */
+	if(s & Minready)
+		return;
+
+	/*
+	 *  e0's is the first of a 2 character sequence
+	 */
+	if(c == 0xe0){
+		esc1 = 1;
+		return;
+	} else if(c == 0xe1){
+		esc2 = 2;
+		return;
+	}
+
+	keyup = c&0x80;
+	c &= 0x7f;
+	if(c > sizeof kbtab){
+		c |= keyup;
+		if(c != 0xFF)	/* these come fairly often: CAPSLOCK U Y */
+			print("unknown key %ux\n", c);
+		return;
+	}
+
+	if(esc1){
+		c = kbtabesc1[c];
+		esc1 = 0;
+	} else if(esc2){
+		esc2--;
+		return;
+	} else if(shift)
+		c = kbtabshift[c];
+	else
+		c = kbtab[c];
+
+	if(caps && c<='z' && c>='a')
+		c += 'A' - 'a';
+
+	/*
+	 *  keyup only important for shifts
+	 */
+	if(keyup){
+		switch(c){
+		case Latin:
+			alt = 0;
+			break;
+		case Shift:
+			shift = 0;
+			break;
+		case Ctrl:
+			ctl = 0;
+			break;
+		}
+		return;
+	}
+
+	/*
+ 	 *  normal character
+	 */
+	if(!(c & Spec)){
+		if(ctl){
+			if(alt && c == Del)
+				warp86("\nCtrl-Alt-Del\n", 0);
+			c &= 0x1f;
+		}
+		switch(lstate){
+		case 1:
+			k1 = c;
+			lstate = 2;
+			return;
+		case 2:
+			k2 = c;
+			lstate = 0;
+			c = latin1(k1, k2);
+			if(c == 0){
+				kbdchar(k1);
+				c = k2;
+			}
+			/* fall through */
+		default:
+			break;
+		}
+	} else {
+		switch(c){
+		case Caps:
+			caps ^= 1;
+			return;
+		case Num:
+			num ^= 1;
+			return;
+		case Shift:
+			shift = 1;
+			return;
+		case Latin:
+			alt = 1;
+			lstate = 1;
+			return;
+		case Ctrl:
+			ctl = 1;
+			return;
+		}
+	}
+	kbdchar(c);
+}
+
+static char *initfailed = "kbd init failed\n";
+
+void
+i8042init(void)
+{
+	int c;
+
+	/* wait for a quiescent controller */
+	while((c = inb(Status)) & (Outbusy | Inready))
+		if(c & Inready)
+			inb(Data);
+
+	/* get current controller command byte */
+	outb(Cmd, 0x20);
+	if(inready() < 0){
+		print("kbdinit: can't read ccc\n");
+		ccc = 0;
+	} else
+		ccc = inb(Data);
+
+	/* enable kbd xfers and interrupts */
+	ccc &= ~Ckbddis;
+	ccc |= Csf | Ckbdint | Cscs1;
+	if(outready() < 0)
+		print(initfailed);
+	outb(Cmd, 0x60);
+	if(outready() < 0)
+		print(initfailed);
+	outb(Data, ccc);
+	if(outready() < 0)
+		print(initfailed);
+
+	setvec(VectorKBD, i8042intr, 0);
+}
--- /dev/null
+++ b/os/boot.original/pc/kfs.h
@@ -1,0 +1,57 @@
+typedef struct Qid9p1 Qid9p1;
+typedef struct Dentry Dentry;
+typedef struct Kfsfile Kfsfile;
+typedef struct Kfs Kfs;
+
+/* DONT TOUCH, this is the disk structure */
+struct	Qid9p1
+{
+	long	path;
+	long	version;
+};
+
+//#define	NAMELEN		28		/* size of names */
+#define	NDBLOCK		6		/* number of direct blocks in Dentry */
+
+/* DONT TOUCH, this is the disk structure */
+struct	Dentry
+{
+	char	name[NAMELEN];
+	short	uid;
+	short	gid;
+	ushort	mode;
+/*
+		#define	DALLOC	0x8000
+		#define	DDIR	0x4000
+		#define	DAPND	0x2000
+		#define	DLOCK	0x1000
+		#define	DREAD	0x4
+		#define	DWRITE	0x2
+		#define	DEXEC	0x1
+*/
+	Qid9p1	qid;
+	long	size;
+	long	dblock[NDBLOCK];
+	long	iblock;
+	long	diblock;
+	long	atime;
+	long	mtime;
+};
+
+struct Kfsfile
+{
+	Dentry;
+	long off;
+};
+
+struct Kfs
+{
+	int	RBUFSIZE;
+	int	BUFSIZE;
+	int	DIRPERBUF;
+	int	INDPERBUF;
+	int	INDPERBUF2;
+};
+
+extern int kfsinit(Fs*);
+
--- /dev/null
+++ b/os/boot.original/pc/kfsboot.c
@@ -1,0 +1,256 @@
+#include	"u.h"
+#include	"lib.h"
+#include	"mem.h"
+#include	"dat.h"
+#include	"fns.h"
+#include	"fs.h"
+
+typedef struct Tag Tag;
+
+/*
+ * tags on block
+ */
+enum
+{
+	Tnone		= 0,
+	Tsuper,			/* the super block */
+	Tdir,			/* directory contents */
+	Tind1,			/* points to blocks */
+	Tind2,			/* points to Tind1 */
+	Tfile,			/* file contents */
+	Tfree,			/* in free list */
+	Tbuck,			/* cache fs bucket */
+	Tvirgo,			/* fake worm virgin bits */
+	Tcache,			/* cw cache things */
+	MAXTAG
+};
+
+#define	QPDIR	0x80000000L
+#define	QPNONE	0
+#define	QPROOT	1
+#define	QPSUPER	2
+
+/* DONT TOUCH, this is the disk structure */
+struct	Tag
+{
+	short	pad;
+	short	tag;
+	long	path;
+};
+
+static int thisblock = -1;
+static Fs *thisfs;
+static uchar *block;
+
+/*
+ * we end up reading 2x or 3x the number of blocks we need to read.
+ * this is okay because we need to read so few.  if it wasn't okay, we could
+ * have getblock return a pointer to a block, and keep a cache of the last
+ * three read blocks.  that would get us down to the minimum.
+ * but this is fine.
+ */
+static int
+getblock(Fs *fs, ulong n)
+{
+	if(!block)
+		block = malloc(16384);
+
+	if(thisblock == n && thisfs == fs)
+		return 0;
+	thisblock = -1;
+	if(fs->diskseek(fs, (vlong)n*fs->kfs.RBUFSIZE) < 0)
+		return -1;
+	if(fs->diskread(fs, block, fs->kfs.RBUFSIZE) != fs->kfs.RBUFSIZE)
+		return -1;
+	thisblock = n;
+	thisfs = fs;
+
+	return 1;
+}
+
+static int
+checktag(Fs *fs, uchar *block, int tag, long qpath)
+{
+	Tag *t;
+
+	t = (Tag*)(block+fs->kfs.BUFSIZE);
+	if(t->tag != tag)
+		return -1;
+	if(qpath != QPNONE && (qpath&~QPDIR) != t->path)
+		return -1;
+	return 1;
+}
+
+static int
+getblocktag(Fs *fs, ulong n, int tag, long qpath)
+{
+	if(getblock(fs, n) < 0 || checktag(fs, block, tag, qpath) < 0)
+		return -1;
+	return 1;
+}
+
+static int
+readinfo(Fs *fs)
+{
+	fs->kfs.RBUFSIZE = 512;
+	if(getblock(fs, 0) < 0)
+		return -1;
+
+	if(memcmp(block+256, "kfs wren device\n", 16) != 0)
+		return -1;
+
+	fs->kfs.RBUFSIZE = atoi((char*)block+256+16);
+	if(!fs->kfs.RBUFSIZE || (fs->kfs.RBUFSIZE&(fs->kfs.RBUFSIZE-1)))
+		return -1;
+
+	fs->kfs.BUFSIZE = fs->kfs.RBUFSIZE - sizeof(Tag);
+	fs->kfs.DIRPERBUF = fs->kfs.BUFSIZE / sizeof(Dentry);
+	fs->kfs.INDPERBUF = fs->kfs.BUFSIZE / sizeof(long);
+	fs->kfs.INDPERBUF2 = fs->kfs.INDPERBUF * fs->kfs.INDPERBUF;
+
+	return 1;
+}
+
+static int
+readroot(Fs *fs, Dentry *d)
+{
+	Dentry *d2;
+
+	if(getblocktag(fs, 2, Tdir, QPROOT) < 0)
+		return -1;
+	d2 = (Dentry*)block;
+	if(strcmp(d2->name, "/") != 0)
+		return -1;
+	*d = *(Dentry*)block;
+	return 1;
+}
+
+static long
+indfetch(Fs *fs, long addr, long off, int tag, long path)
+{
+	if(getblocktag(fs, addr, tag, path) < 0)
+		return -1;
+	return ((long*)block)[off];
+}
+
+static long
+rel2abs(Fs *fs, Dentry *d, long a)
+{
+	long addr;
+
+	if(a < NDBLOCK)
+		return d->dblock[a];
+	a -= NDBLOCK;
+	if(a < fs->kfs.INDPERBUF){
+		if(d->iblock == 0)
+			return 0;
+		addr = indfetch(fs, d->iblock, a, Tind1, d->qid.path);
+		if(addr == 0)
+			print("rel2abs indfetch 0 %s %ld\n", d->name, a);
+		return addr;
+	}
+	a -= fs->kfs.INDPERBUF;
+	if(a < fs->kfs.INDPERBUF2){
+		if(d->diblock == 0)
+			return 0;
+		addr = indfetch(fs, d->diblock, a/fs->kfs.INDPERBUF, Tind2, d->qid.path);
+		if(addr == 0){
+			print("rel2abs indfetch 0 %s %ld\n", d->name, a/fs->kfs.INDPERBUF);
+			return 0;
+		}
+		addr = indfetch(fs, addr, a%fs->kfs.INDPERBUF, Tind1, d->qid.path);
+		return addr;
+	}
+	print("rel2abs trip ind %s %ld\n", d->name, a);
+	return -1;
+}
+
+static int
+readdentry(Fs *fs, Dentry *d, int n, Dentry *e)
+{
+	long addr, m;
+
+	m = n/fs->kfs.DIRPERBUF;
+	if((addr = rel2abs(fs, d, m)) <= 0)
+		return addr;
+	if(getblocktag(fs, addr, Tdir, d->qid.path) < 0)
+		return -1;
+	*e = *(Dentry*)(block+(n%fs->kfs.DIRPERBUF)*sizeof(Dentry));
+	return 1;
+}
+
+static int
+getdatablock(Fs *fs, Dentry *d, long a)
+{
+	long addr;
+
+	if((addr = rel2abs(fs, d, a)) == 0)
+		return -1;
+	return getblocktag(fs, addr, Tfile, QPNONE);
+}
+
+static int
+walk(Fs *fs, Dentry *d, char *name, Dentry *e)
+{
+	int i, n;
+	Dentry x;
+
+	for(i=0;; i++){
+		if((n=readdentry(fs, d, i, &x)) <= 0)
+			return n;
+		if(strcmp(x.name, name) == 0){
+			*e = x;
+			return 1;
+		}
+	}
+}
+
+static long
+kfsread(File *f, void *va, long len)
+{
+	uchar *a;
+	long tot, off, o, n;
+	Fs *fs;
+
+	a = va;
+	fs = f->fs;
+	off = f->kfs.off;
+	tot = 0;
+	while(tot < len){
+		if(getdatablock(fs, &f->kfs, off/fs->kfs.BUFSIZE) < 0)
+			return -1;
+		o = off%fs->kfs.BUFSIZE;
+		n = fs->kfs.BUFSIZE - o;
+		if(n > len-tot)
+			n = len-tot;
+		memmove(a+tot, block+o, n);
+		off += n;
+		tot += n;
+	}
+	f->kfs.off = off;
+	return tot;
+}
+
+static int
+kfswalk(File *f, char *name)
+{
+	int n;
+
+	n = walk(f->fs, &f->kfs, name, &f->kfs);
+	if(n < 0)
+		return -1;
+	f->kfs.off = 0;
+	return 1;
+}
+
+int
+kfsinit(Fs *fs)
+{
+	if(readinfo(fs) < 0 || readroot(fs, &fs->root.kfs) < 0)
+		return -1;
+
+	fs->root.fs = fs;
+	fs->read = kfsread;
+	fs->walk = kfswalk;
+	return 0;
+}
--- /dev/null
+++ b/os/boot.original/pc/l.s
@@ -1,0 +1,1084 @@
+#include "x16.h"
+#include "mem.h"
+
+#define WRMSR		BYTE $0x0F; BYTE $0x30	/* WRMSR, argument in AX/DX (lo/hi) */
+#define RDTSC 		BYTE $0x0F; BYTE $0x31	/* RDTSC, result in AX/DX (lo/hi) */
+#define RDMSR		BYTE $0x0F; BYTE $0x32	/* RDMSR, result in AX/DX (lo/hi) */
+
+#ifdef PXE
+#define PDB		0x90000		/* temporary page tables (24KB) */
+#else
+#define PDB		0x08000
+#endif PXE
+
+#define NoScreenBlank	1
+/*#define ResetDiscs	1*/
+
+TEXT origin(SB), $0
+	/*
+	 * This part of l.s is used only in the boot kernel.
+	 * It assumes that we are in real address mode, i.e.,
+	 * that we look like an 8086.
+	 *
+	 * Make sure the segments are reasonable.
+	 * If we were started directly from the BIOS
+	 * (i.e. no MS-DOS) then DS may not be
+	 * right.
+	 */
+	MOVW	CS, AX
+	MOVW	AX, DS
+
+#ifdef NoScreenBlank
+	/*
+	 * Get the current video mode. If it isn't mode 3,
+	 * set text mode 3.
+	 * Well, no. Windows95 won't co-operate here so we have
+	 * to explicitly set mode 3.
+	 */
+	XORL	AX, AX
+	MOVB	$0x0F, AH
+	INT	$0x10			/* get current video mode in AL */
+	CMPB	AL, $03
+	JEQ	sayhello
+#endif /* NoScreenBlank */
+	XORL	AX, AX
+	MOVB	$0x03, AL
+	INT	$0x10			/* set video mode in AL */
+
+sayhello:
+	LWI(hello(SB), rSI)
+	CALL16(biosputs(SB))
+
+#ifdef ResetDiscs
+	XORL	AX, AX			/* reset disc system */
+	XORL	DX, DX
+	MOVB	$0x80, DL
+	INT	$0x13
+#endif /* ResetDiscs */
+
+#ifdef DOTCOM
+/*
+ *	relocate everything to a half meg and jump there
+ *	- looks weird because it is being assembled by a 32 bit
+ *	  assembler for a 16 bit world
+ *
+ *	only b.com does this - not 9load
+ */
+	MOVL	$0,BX
+	INCL	BX
+	SHLL	$15,BX
+	MOVL	BX,CX
+	MOVW	BX,ES
+	MOVL	$0,SI
+	MOVL	SI,DI
+	CLD
+	REP
+	MOVSL
+
+	/*
+	 * Jump to the copied image;
+	 * fix up the DS for the new location.
+	 */
+	FARJUMP16(0x8000, _start8000(SB))
+
+TEXT _start8000(SB), $0
+	MFSR(rCS, rAX)			/* fix up DS, ES (0x8000) */
+	MTSR(rAX, rDS)
+	MTSR(rAX, rES)
+
+	/*
+	 * If we are already in protected mode, have to get back
+	 * to real mode before trying any privileged operations
+	 * (like going into protected mode...).
+	 * Try to reset with a restart vector.
+	 */
+	MFCR(rCR0, rAX)			/* are we in protected mode? */
+	ANDI(0x0001, rAX)
+	JEQ	_real
+
+	CLR(rBX)
+	MTSR(rBX, rES)
+
+	LWI(0x0467, rBX)		/* reset entry point */
+	LWI(_start8000(SB), rAX)	/* offset within segment */
+	BYTE	$0x26
+	BYTE	$0x89
+	BYTE	$0x07			/* MOVW	AX, ES:[BX] */
+	LBI(0x69, rBL)
+	MFSR(rCS, rAX)			/* segment */
+	BYTE	$0x26
+	BYTE	$0x89
+	BYTE	$0x07			/* MOVW	AX, ES:[BX] */
+
+	CLR(rDX)
+	OUTPORTB(0x70, 0x8F)
+	OUTPORTB(0x71, 0x0A)
+
+	FARJUMP16(0xFFFF, 0x0000)		/* reset */
+#endif /* DOTCOM */
+
+_real:
+
+/*
+ *	do things that need to be done in real mode.
+ *	the results get written to CONFADDR (0x1200)
+ *	in a series of <4-byte-magic-number><block-of-data>
+ *	the data length is dependent on the magic number.
+ *
+ *	this gets parsed by conf.c:/^readlsconf
+ *
+ *	N.B. CALL16 kills rDI, so we can't call anything.
+ */
+	LWI(0x0000, rAX)
+	MTSR(rAX, rES)
+	LWI(0x1200, rDI)
+
+/*
+ *	turn off interrupts
+ */
+	CLI
+
+/*
+ *	detect APM1.2 bios support
+ */
+	/* save DI */
+	SW(rDI, rock(SB))
+
+	/* disconnect anyone else */
+	LWI(0x5304, rAX)
+	LWI(0x0000, rBX)
+	INT $0x15
+
+	/* connect */
+	CLC
+	LWI(0x5303, rAX)
+	LWI(0x0000, rBX)
+	INT $0x15
+	CLI	/* apm put interrupts back? */
+
+	JC noapm
+
+	OPSIZE; PUSHR(rSI)
+	OPSIZE; PUSHR(rBX)
+	PUSHR(rDI)
+	PUSHR(rDX)
+	PUSHR(rCX)
+	PUSHR(rAX)
+
+	/* put DI, ES back */
+	LW(rock(SB), rDI)
+	LWI(0x0000, rAX)
+	MTSR(rAX, rES)
+
+	/*
+	 * write APM data.  first four bytes are APM\0.
+	 */
+	LWI(0x5041, rAX)
+	STOSW
+
+	LWI(0x004d, rAX)
+	STOSW
+
+	LWI(8, rCX)
+apmmove:
+	POPR(rAX)
+	STOSW
+	LOOP apmmove
+
+noapm:
+
+/*
+ *	end of real mode hacks: write terminator, put ES back.
+ */
+	LWI(0x0000, rAX)
+	STOSW
+	STOSW
+
+	MFSR(rCS, rAX)			/* fix up ES (0x8000) */
+	MTSR(rAX, rES)
+
+/*
+ * 	goto protected mode
+ */
+/*	MOVL	tgdtptr(SB),GDTR /**/
+	 BYTE	$0x0f
+	 BYTE	$0x01
+	 BYTE	$0x16
+	 WORD	$tgdtptr(SB)
+
+	LWI(1, rAX)
+	/* MOV AX,MSW */
+	BYTE $0x0F; BYTE $0x01; BYTE $0xF0
+
+/*
+ *	clear prefetch queue (weird code to avoid optimizations)
+ */
+	/* JMP .+2 */
+	BYTE $0xEB
+	BYTE $0x00
+
+/*
+ *	set all segs
+ */
+/*	MOVW	$SELECTOR(1, SELGDT, 0),AX	/**/
+	 BYTE	$0xc7
+	 BYTE	$0xc0
+	 WORD	$SELECTOR(1, SELGDT, 0)
+	MOVW	AX,DS
+	MOVW	AX,SS
+	MOVW	AX,ES
+	MOVW	AX,FS
+	MOVW	AX,GS
+
+/*	JMPFAR	SELECTOR(2, SELGDT, 0):$mode32bit(SB) /**/
+	 BYTE	$0x66
+	 BYTE	$0xEA
+	 LONG	$mode32bit-KZERO(SB)
+	 WORD	$SELECTOR(2, SELGDT, 0)
+
+TEXT	mode32bit(SB),$0
+	/*
+	 *  make a bottom level page table page that maps the first
+	 *  16 meg of physical memory
+	 */
+	MOVL	$PDB, DI			/* clear 6 pages for the tables etc. */
+	XORL	AX, AX
+	MOVL	$(6*BY2PG), CX
+	SHRL	$2, CX
+
+	CLD
+	REP;	STOSL
+
+	MOVL	$PDB, AX		/* phys addr of temporary page table */
+	MOVL	$(4*1024),CX		/* pte's per page */
+	MOVL	$((((4*1024)-1)<<PGSHIFT)|PTEVALID|PTEKERNEL|PTEWRITE),BX
+setpte:
+	MOVL	BX,-4(AX)(CX*4)
+	SUBL	$(1<<PGSHIFT),BX
+	LOOP	setpte
+
+	/*
+	 *  make a top level page table page that maps the first
+	 *  16 meg of memory to 0 thru 16meg and to KZERO thru KZERO+16meg
+	 */
+	MOVL	AX,BX
+	ADDL	$(4*BY2PG),AX
+	ADDL	$(PTEVALID|PTEKERNEL|PTEWRITE),BX
+	MOVL	BX,0(AX)
+	MOVL	BX,((((KZERO>>1)&0x7FFFFFFF)>>(2*PGSHIFT-1-4))+0)(AX)
+	ADDL	$BY2PG,BX
+	MOVL	BX,4(AX)
+	MOVL	BX,((((KZERO>>1)&0x7FFFFFFF)>>(2*PGSHIFT-1-4))+4)(AX)
+	ADDL	$BY2PG,BX
+	MOVL	BX,8(AX)
+	MOVL	BX,((((KZERO>>1)&0x7FFFFFFF)>>(2*PGSHIFT-1-4))+8)(AX)
+	ADDL	$BY2PG,BX
+	MOVL	BX,12(AX)
+	MOVL	BX,((((KZERO>>1)&0x7FFFFFFF)>>(2*PGSHIFT-1-4))+12)(AX)
+
+	/*
+	 *  point processor to top level page & turn on paging
+	 *
+	 *  this produces the apparently harmless "VMX|F(125):468 Dis 0x0:0x0"
+	 *  message in the VMware log.
+	 */
+	MOVL	AX,CR3
+	MOVL	CR0,AX
+	ORL	$0X80000000,AX
+	MOVL	AX,CR0
+
+	/*
+	 *  use a jump to an absolute location to get the PC into
+	 *  KZERO.
+	 */
+	LEAL	tokzero(SB),AX
+	JMP*	AX
+
+/*
+ * When we load 9load from DOS, the bootstrap jumps
+ * to the instruction right after `JUMP', which gets
+ * us into kzero.
+ *
+ * The name prevents it from being optimized away.
+ */
+TEXT jumplabel(SB), $0
+	BYTE $'J'; BYTE $'U'; BYTE $'M'; BYTE $'P'
+
+	LEAL	tokzero(SB),AX
+	JMP*	AX
+
+TEXT	tokzero(SB),$0
+	/*
+	 * Clear BSS
+	 */
+	LEAL	edata(SB),SI
+	MOVL	SI,DI
+	ADDL	$4,DI
+	MOVL	$0,AX
+	MOVL	AX,(SI)
+	LEAL	end(SB),CX
+	SUBL	DI,CX
+	SHRL	$2,CX
+	CLD
+	REP
+	MOVSL
+
+	/*
+	 *  stack and mach
+	 */
+	MOVL	$mach0(SB),SP
+	MOVL	SP,m(SB)
+	MOVL	$0,0(SP)
+	ADDL	$(MACHSIZE-4),SP	/* start stack above machine struct */
+
+	CALL	main(SB)
+
+loop:
+	JMP	loop
+
+GLOBL	mach0+0(SB), $MACHSIZE
+GLOBL	m(SB), $4
+
+/*
+ *  gdt to get us to 32-bit/segmented/unpaged mode
+ */
+TEXT	tgdt(SB),$0
+
+	/* null descriptor */
+	LONG	$0
+	LONG	$0
+
+	/* data segment descriptor for 4 gigabytes (PL 0) */
+	LONG	$(0xFFFF)
+	LONG	$(SEGG|SEGB|(0xF<<16)|SEGP|SEGPL(0)|SEGDATA|SEGW)
+
+	/* exec segment descriptor for 4 gigabytes (PL 0) */
+	LONG	$(0xFFFF)
+	LONG	$(SEGG|SEGD|(0xF<<16)|SEGP|SEGPL(0)|SEGEXEC|SEGR)
+
+	/* exec segment descriptor for 4 gigabytes (PL 0) 16-bit */
+	LONG	$(0xFFFF)
+	LONG	$(SEGG|(0xF<<16)|SEGP|SEGPL(0)|SEGEXEC|SEGR)
+
+/*
+ *  pointer to initial gdt
+ */
+TEXT	tgdtptr(SB),$0
+	WORD	$(4*8)
+	LONG	$tgdt-KZERO(SB)
+
+/*
+ * Output a string to the display.
+ * String argument is in rSI.
+ */
+TEXT biosputs(SB), $0
+	PUSHA
+	CLR(rBX)
+_BIOSputs:
+	LODSB
+	ORB(rAL, rAL)
+	JEQ _BIOSputsret
+
+	LBI(0x0E, rAH)
+	BIOSCALL(0x10)
+	JMP _BIOSputs
+
+_BIOSputsret:
+	POPA
+	RET
+
+/*
+ *  input a byte
+ */
+TEXT	inb(SB),$0
+
+	MOVL	p+0(FP),DX
+	XORL	AX,AX
+	INB
+	RET
+
+/*
+ * input a short from a port
+ */
+TEXT	ins(SB), $0
+
+	MOVL	p+0(FP), DX
+	XORL	AX, AX
+	OPSIZE; INL
+	RET
+
+/*
+ * input a long from a port
+ */
+TEXT	inl(SB), $0
+
+	MOVL	p+0(FP), DX
+	XORL	AX, AX
+	INL
+	RET
+
+/*
+ *  output a byte
+ */
+TEXT	outb(SB),$0
+
+	MOVL	p+0(FP),DX
+	MOVL	b+4(FP),AX
+	OUTB
+	RET
+
+/*
+ * output a short to a port
+ */
+TEXT	outs(SB), $0
+	MOVL	p+0(FP), DX
+	MOVL	s+4(FP), AX
+	OPSIZE; OUTL
+	RET
+
+/*
+ * output a long to a port
+ */
+TEXT	outl(SB), $0
+	MOVL	p+0(FP), DX
+	MOVL	s+4(FP), AX
+	OUTL
+	RET
+
+/*
+ *  input a string of bytes from a port
+ */
+TEXT	insb(SB),$0
+
+	MOVL	p+0(FP),DX
+	MOVL	a+4(FP),DI
+	MOVL	c+8(FP),CX
+	CLD; REP; INSB
+	RET
+
+/*
+ *  input a string of shorts from a port
+ */
+TEXT	inss(SB),$0
+	MOVL	p+0(FP),DX
+	MOVL	a+4(FP),DI
+	MOVL	c+8(FP),CX
+	CLD
+	REP; OPSIZE; INSL
+	RET
+
+/*
+ *  output a string of bytes to a port
+ */
+TEXT	outsb(SB),$0
+
+	MOVL	p+0(FP),DX
+	MOVL	a+4(FP),SI
+	MOVL	c+8(FP),CX
+	CLD; REP; OUTSB
+	RET
+
+/*
+ *  output a string of shorts to a port
+ */
+TEXT	outss(SB),$0
+	MOVL	p+0(FP),DX
+	MOVL	a+4(FP),SI
+	MOVL	c+8(FP),CX
+	CLD
+	REP; OPSIZE; OUTSL
+	RET
+
+/*
+ *  input a string of longs from a port
+ */
+TEXT	insl(SB),$0
+
+	MOVL	p+0(FP),DX
+	MOVL	a+4(FP),DI
+	MOVL	c+8(FP),CX
+	CLD; REP; INSL
+	RET
+
+/*
+ *  output a string of longs to a port
+ */
+TEXT	outsl(SB),$0
+
+	MOVL	p+0(FP),DX
+	MOVL	a+4(FP),SI
+	MOVL	c+8(FP),CX
+	CLD; REP; OUTSL
+	RET
+
+/*
+ *  routines to load/read various system registers
+ */
+GLOBL	idtptr(SB),$6
+TEXT	putidt(SB),$0		/* interrupt descriptor table */
+	MOVL	t+0(FP),AX
+	MOVL	AX,idtptr+2(SB)
+	MOVL	l+4(FP),AX
+	MOVW	AX,idtptr(SB)
+	MOVL	idtptr(SB),IDTR
+	RET
+
+TEXT	putcr3(SB),$0		/* top level page table pointer */
+	MOVL	t+0(FP),AX
+	MOVL	AX,CR3
+	RET
+
+TEXT	getcr0(SB),$0		/* coprocessor bits */
+	MOVL	CR0,AX
+	RET
+
+TEXT	getcr2(SB),$0		/* fault address */
+	MOVL	CR2,AX
+	RET
+
+TEXT	getcr3(SB),$0		/* page directory base */
+	MOVL	CR3,AX
+	RET
+
+TEXT	getcr4(SB), $0		/* CR4 - extensions */
+	MOVL	CR4, AX
+	RET
+
+TEXT _cycles(SB), $0				/* time stamp counter */
+	RDTSC
+	MOVL	vlong+0(FP), CX			/* &vlong */
+	MOVL	AX, 0(CX)			/* lo */
+	MOVL	DX, 4(CX)			/* hi */
+	RET
+
+TEXT rdmsr(SB), $0				/* model-specific register */
+	MOVL	index+0(FP), CX
+	RDMSR
+	MOVL	vlong+4(FP), CX			/* &vlong */
+	MOVL	AX, 0(CX)			/* lo */
+	MOVL	DX, 4(CX)			/* hi */
+	RET
+	
+TEXT wrmsr(SB), $0
+	MOVL	index+0(FP), CX
+	MOVL	lo+4(FP), AX
+	MOVL	hi+8(FP), DX
+	WRMSR
+	RET
+
+TEXT mb386(SB), $0
+	POPL	AX				/* return PC */
+	PUSHFL
+	PUSHL	CS
+	PUSHL	AX
+	IRETL
+
+/*
+ *  special traps
+ */
+TEXT	intr0(SB),$0
+	PUSHL	$0
+	PUSHL	$0
+	JMP	intrcommon
+TEXT	intr1(SB),$0
+	PUSHL	$0
+	PUSHL	$1
+	JMP	intrcommon
+TEXT	intr2(SB),$0
+	PUSHL	$0
+	PUSHL	$2
+	JMP	intrcommon
+TEXT	intr3(SB),$0
+	PUSHL	$0
+	PUSHL	$3
+	JMP	intrcommon
+TEXT	intr4(SB),$0
+	PUSHL	$0
+	PUSHL	$4
+	JMP	intrcommon
+TEXT	intr5(SB),$0
+	PUSHL	$0
+	PUSHL	$5
+	JMP	intrcommon
+TEXT	intr6(SB),$0
+	PUSHL	$0
+	PUSHL	$6
+	JMP	intrcommon
+TEXT	intr7(SB),$0
+	PUSHL	$0
+	PUSHL	$7
+	JMP	intrcommon
+TEXT	intr8(SB),$0
+	PUSHL	$8
+	JMP	intrcommon
+TEXT	intr9(SB),$0
+	PUSHL	$0
+	PUSHL	$9
+	JMP	intrcommon
+TEXT	intr10(SB),$0
+	PUSHL	$10
+	JMP	intrcommon
+TEXT	intr11(SB),$0
+	PUSHL	$11
+	JMP	intrcommon
+TEXT	intr12(SB),$0
+	PUSHL	$12
+	JMP	intrcommon
+TEXT	intr13(SB),$0
+	PUSHL	$13
+	JMP	intrcommon
+TEXT	intr14(SB),$0
+	PUSHL	$14
+	JMP	intrcommon
+TEXT	intr15(SB),$0
+	PUSHL	$0
+	PUSHL	$15
+	JMP	intrcommon
+TEXT	intr16(SB),$0
+	PUSHL	$0
+	PUSHL	$16
+	JMP	intrcommon
+TEXT	intr24(SB),$0
+	PUSHL	$0
+	PUSHL	$24
+	JMP	intrcommon
+TEXT	intr25(SB),$0
+	PUSHL	$0
+	PUSHL	$25
+	JMP	intrcommon
+TEXT	intr26(SB),$0
+	PUSHL	$0
+	PUSHL	$26
+	JMP	intrcommon
+TEXT	intr27(SB),$0
+	PUSHL	$0
+	PUSHL	$27
+	JMP	intrcommon
+TEXT	intr28(SB),$0
+	PUSHL	$0
+	PUSHL	$28
+	JMP	intrcommon
+TEXT	intr29(SB),$0
+	PUSHL	$0
+	PUSHL	$29
+	JMP	intrcommon
+TEXT	intr30(SB),$0
+	PUSHL	$0
+	PUSHL	$30
+	JMP	intrcommon
+TEXT	intr31(SB),$0
+	PUSHL	$0
+	PUSHL	$31
+	JMP	intrcommon
+TEXT	intr32(SB),$0
+	PUSHL	$0
+	PUSHL	$32
+	JMP	intrcommon
+TEXT	intr33(SB),$0
+	PUSHL	$0
+	PUSHL	$33
+	JMP	intrcommon
+TEXT	intr34(SB),$0
+	PUSHL	$0
+	PUSHL	$34
+	JMP	intrcommon
+TEXT	intr35(SB),$0
+	PUSHL	$0
+	PUSHL	$35
+	JMP	intrcommon
+TEXT	intr36(SB),$0
+	PUSHL	$0
+	PUSHL	$36
+	JMP	intrcommon
+TEXT	intr37(SB),$0
+	PUSHL	$0
+	PUSHL	$37
+	JMP	intrcommon
+TEXT	intr38(SB),$0
+	PUSHL	$0
+	PUSHL	$38
+	JMP	intrcommon
+TEXT	intr39(SB),$0
+	PUSHL	$0
+	PUSHL	$39
+	JMP	intrcommon
+TEXT	intr64(SB),$0
+	PUSHL	$0
+	PUSHL	$64
+	JMP	intrcommon
+TEXT	intrbad(SB),$0
+	PUSHL	$0
+	PUSHL	$0x1ff
+	JMP	intrcommon
+
+intrcommon:
+	PUSHL	DS
+	PUSHL	ES
+	PUSHL	FS
+	PUSHL	GS
+	PUSHAL
+	MOVL	$(KDSEL),AX
+	MOVW	AX,DS
+	MOVW	AX,ES
+	LEAL	0(SP),AX
+	PUSHL	AX
+	CALL	trap(SB)
+	POPL	AX
+	POPAL
+	POPL	GS
+	POPL	FS
+	POPL	ES
+	POPL	DS
+	ADDL	$8,SP	/* error code and trap type */
+	IRETL
+
+
+/*
+ *  interrupt level is interrupts on or off
+ */
+TEXT	spllo(SB),$0
+	PUSHFL
+	POPL	AX
+	STI
+	RET
+
+TEXT	splhi(SB),$0
+	PUSHFL
+	POPL	AX
+	CLI
+	RET
+
+TEXT	splx(SB),$0
+	MOVL	s+0(FP),AX
+	PUSHL	AX
+	POPFL
+	RET
+
+/*
+ *  do nothing whatsoever till interrupt happens
+ */
+TEXT	idle(SB),$0
+	HLT
+	RET
+
+/*
+ * Try to determine the CPU type which requires fiddling with EFLAGS.
+ * If the Id bit can be toggled then the CPUID instruciton can be used
+ * to determine CPU identity and features. First have to check if it's
+ * a 386 (Ac bit can't be set). If it's not a 386 and the Id bit can't be
+ * toggled then it's an older 486 of some kind.
+ *
+ *	cpuid(id[], &ax, &dx);
+ */
+#define CPUID		BYTE $0x0F; BYTE $0xA2	/* CPUID, argument in AX */
+TEXT cpuid(SB), $0
+	MOVL	$0x240000, AX
+	PUSHL	AX
+	POPFL					/* set Id|Ac */
+
+	PUSHFL
+	POPL	BX				/* retrieve value */
+
+	MOVL	$0, AX
+	PUSHL	AX
+	POPFL					/* clear Id|Ac, EFLAGS initialised */
+
+	PUSHFL
+	POPL	AX				/* retrieve value */
+	XORL	BX, AX
+	TESTL	$0x040000, AX			/* Ac */
+	JZ	_cpu386				/* can't set this bit on 386 */
+	TESTL	$0x200000, AX			/* Id */
+	JZ	_cpu486				/* can't toggle this bit on some 486 */
+
+	MOVL	$0, AX
+	CPUID
+	MOVL	id+0(FP), BP
+	MOVL	BX, 0(BP)			/* "Genu" "Auth" "Cyri" */
+	MOVL	DX, 4(BP)			/* "ineI" "enti" "xIns" */
+	MOVL	CX, 8(BP)			/* "ntel" "cAMD" "tead" */
+
+	MOVL	$1, AX
+	CPUID
+	JMP	_cpuid
+
+_cpu486:
+	MOVL	$0x400, AX
+	MOVL	$0, DX
+	JMP	_cpuid
+
+_cpu386:
+	MOVL	$0x300, AX
+	MOVL	$0, DX
+
+_cpuid:
+	MOVL	ax+4(FP), BP
+	MOVL	AX, 0(BP)
+	MOVL	dx+8(FP), BP
+	MOVL	DX, 0(BP)
+	RET
+
+
+/*
+ *  basic timing loop to determine CPU frequency
+ */
+TEXT	aamloop(SB),$0
+
+	MOVL	c+0(FP),CX
+aaml1:
+	AAM
+	LOOP	aaml1
+	RET
+
+TEXT hello(SB), $0
+	BYTE $'P'; BYTE $'l'; BYTE $'a'; BYTE $'n';
+	BYTE $' '; BYTE $'9'; BYTE $' '; BYTE $'f';
+	BYTE $'r'; BYTE $'o'; BYTE $'m'; BYTE $' ';
+	BYTE $'B'; BYTE $'e'; BYTE $'l'; BYTE $'l';
+	BYTE $' '; BYTE $'L'; BYTE $'a'; BYTE $'b';
+	BYTE $'s'; 
+#ifdef PXE
+	BYTE $' '; BYTE $'b'; BYTE $'y'; BYTE $' ';
+	BYTE $'P'; BYTE $'X'; BYTE $'E';
+#endif
+	BYTE $'\r';
+	BYTE $'\n';
+	BYTE $'\z';
+
+TEXT rock(SB), $0
+	BYTE $0; BYTE $0; BYTE $0; BYTE $0;
+
+GLOBL pxe(SB), $4
+#ifdef PXE
+DATA	pxe+0(SB)/4, $1
+#else
+DATA	pxe+0(SB)/4, $0
+#endif /* PXE */
+
+/*
+ * Save registers.
+ */
+TEXT saveregs(SB), $0
+	/* appease 8l */
+	SUBL $32, SP
+	POPL AX
+	POPL AX
+	POPL AX
+	POPL AX
+	POPL AX
+	POPL AX
+	POPL AX
+	POPL AX
+	
+	PUSHL	AX
+	PUSHL	BX
+	PUSHL	CX
+	PUSHL	DX
+	PUSHL	BP
+	PUSHL	DI
+	PUSHL	SI
+	PUSHFL
+
+	XCHGL	32(SP), AX	/* swap return PC and saved flags */
+	XCHGL	0(SP), AX
+	XCHGL	32(SP), AX
+	RET
+
+TEXT restoreregs(SB), $0
+	/* appease 8l */
+	PUSHL	AX
+	PUSHL	AX
+	PUSHL	AX
+	PUSHL	AX
+	PUSHL	AX
+	PUSHL	AX
+	PUSHL	AX
+	PUSHL	AX
+	ADDL	$32, SP
+	
+	XCHGL	32(SP), AX	/* swap return PC and saved flags */
+	XCHGL	0(SP), AX
+	XCHGL	32(SP), AX
+
+	POPFL
+	POPL	SI
+	POPL	DI
+	POPL	BP
+	POPL	DX
+	POPL	CX
+	POPL	BX
+	POPL	AX
+	RET
+
+/*
+ * Assumed to be in protected mode at time of call.
+ * Switch to real mode, execute an interrupt, and
+ * then switch back to protected mode.  
+ *
+ * Assumes:
+ *
+ *	- no device interrupts are going to come in
+ *	- 0-16MB is identity mapped in page tables
+ *	- can use code segment 0x1000 in real mode
+ *		to get at l.s code
+ */
+TEXT realmodeidtptr(SB), $0
+	WORD	$(4*256-1)
+	LONG	$0
+
+TEXT realmode0(SB), $0
+	CALL	saveregs(SB)
+
+	/* switch to low code address */
+	LEAL	physcode-KZERO(SB), AX
+	JMP *AX
+
+TEXT physcode(SB), $0
+
+	/* switch to low stack */
+	MOVL	SP, AX
+	MOVL	$0x7C00, SP
+	PUSHL	AX
+
+	/* load IDT with real-mode version; GDT already fine */
+	MOVL	realmodeidtptr(SB), IDTR
+
+	/* edit INT $0x00 instruction below */
+	MOVL	realmodeintr(SB), AX
+	MOVB	AX, realmodeintrinst+1(SB)
+
+	/* disable paging */
+	MOVL	CR0, AX
+	ANDL	$0x7FFFFFFF, AX
+	MOVL	AX, CR0
+	/* JMP .+2 to clear prefetch queue*/
+	BYTE $0xEB; BYTE $0x00
+
+	/* jump to 16-bit code segment */
+/*	JMPFAR	SELECTOR(3, SELGDT, 0):$again16bit(SB) /**/
+	 BYTE	$0xEA
+	 LONG	$again16bit-KZERO(SB)
+	 WORD	$SELECTOR(3, SELGDT, 0)
+
+TEXT again16bit(SB), $0
+	/*
+	 * Now in 16-bit compatibility mode.
+	 * These are 32-bit instructions being interpreted
+	 * as 16-bit instructions.  I'm being lazy and
+	 * not using the macros because I know when
+	 * the 16- and 32-bit instructions look the same
+	 * or close enough.
+	 */
+
+	/* disable protected mode and jump to real mode cs */
+	OPSIZE; MOVL CR0, AX
+	OPSIZE; XORL BX, BX
+	OPSIZE; INCL BX
+	OPSIZE; XORL BX, AX
+	OPSIZE; MOVL AX, CR0
+
+	/* JMPFAR 0x1000:now16real */
+	 BYTE $0xEA
+	 WORD	$now16real-KZERO(SB)
+	 WORD	$0x1000
+
+TEXT now16real(SB), $0
+	/* copy the registers for the bios call */
+	LWI(0x1000, rAX)
+	MOVW	AX,SS
+	LWI(realmoderegs(SB), rBP)
+	
+	/* offsets are in Ureg */
+	LXW(44, xBP, rAX)
+	MOVW	AX, DS
+	LXW(40, xBP, rAX)
+	MOVW	AX, ES
+
+	OPSIZE; LXW(0, xBP, rDI)
+	OPSIZE; LXW(4, xBP, rSI)
+	OPSIZE; LXW(16, xBP, rBX)
+	OPSIZE; LXW(20, xBP, rDX)
+	OPSIZE; LXW(24, xBP, rCX)
+	OPSIZE; LXW(28, xBP, rAX)
+
+	CLC
+
+TEXT realmodeintrinst(SB), $0
+	INT $0x00
+
+
+	/* save the registers after the call */
+
+	LWI(0x7bfc, rSP)
+	OPSIZE; PUSHFL
+	OPSIZE; PUSHL AX
+
+	LWI(0x1000, rAX)
+	MOVW	AX,SS
+	LWI(realmoderegs(SB), rBP)
+	
+	OPSIZE; SXW(rDI, 0, xBP)
+	OPSIZE; SXW(rSI, 4, xBP)
+	OPSIZE; SXW(rBX, 16, xBP)
+	OPSIZE; SXW(rDX, 20, xBP)
+	OPSIZE; SXW(rCX, 24, xBP)
+	OPSIZE; POPL AX
+	OPSIZE; SXW(rAX, 28, xBP)
+
+	MOVW	DS, AX
+	OPSIZE; SXW(rAX, 44, xBP)
+	MOVW	ES, AX
+	OPSIZE; SXW(rAX, 40, xBP)
+
+	OPSIZE; POPL AX
+	OPSIZE; SXW(rAX, 64, xBP)	/* flags */
+
+	/* re-enter protected mode and jump to 32-bit code */
+	OPSIZE; MOVL $1, AX
+	OPSIZE; MOVL AX, CR0
+	
+/*	JMPFAR	SELECTOR(2, SELGDT, 0):$again32bit(SB) /**/
+	 OPSIZE
+	 BYTE $0xEA
+	 LONG	$again32bit-KZERO(SB)
+	 WORD	$SELECTOR(2, SELGDT, 0)
+
+TEXT again32bit(SB), $0
+	MOVW	$SELECTOR(1, SELGDT, 0),AX
+	MOVW	AX,DS
+	MOVW	AX,SS
+	MOVW	AX,ES
+	MOVW	AX,FS
+	MOVW	AX,GS
+
+	/* enable paging and jump to kzero-address code */
+	MOVL	CR0, AX
+	ORL	$0x80000000, AX
+	MOVL	AX, CR0
+	LEAL	again32kzero(SB), AX
+	JMP*	AX
+
+TEXT again32kzero(SB), $0
+	/* breathe a sigh of relief - back in 32-bit protected mode */
+
+	/* switch to old stack */	
+	PUSHL	AX	/* match popl below for 8l */
+	MOVL	$0x7BFC, SP
+	POPL	SP
+
+	/* restore idt */
+	MOVL	idtptr(SB),IDTR
+
+	CALL	restoreregs(SB)
+	RET
+
+TEXT realmoderegs(SB), $0
+	LONG $0; LONG $0; LONG $0; LONG $0
+	LONG $0; LONG $0; LONG $0; LONG $0
+	LONG $0; LONG $0; LONG $0; LONG $0
+	LONG $0; LONG $0; LONG $0; LONG $0
+	LONG $0; LONG $0; LONG $0; LONG $0
+
+TEXT realmodeintr(SB), $0
+	LONG $0
+
--- /dev/null
+++ b/os/boot.original/pc/lib.h
@@ -1,0 +1,106 @@
+#define	offsetof(s, m)	(ulong)(&(((s*)0)->m))
+
+/*
+ * functions (possibly) linked in, complete, from libc.
+ */
+
+/*
+ * mem routines
+ */
+extern	void*	memccpy(void*, void*, int, ulong);
+extern	void*	memset(void*, int, ulong);
+extern	int	memcmp(void*, void*, ulong);
+extern	void*	memmove(void*, void*, ulong);
+extern	void*	memchr(void*, int, ulong);
+
+/*
+ * string routines
+ */
+extern	char*	strcat(char*, char*);
+extern	char*	strchr(char*, int);
+extern	int	strcmp(char*, char*);
+extern	char*	strcpy(char*, char*);
+extern	char*	strncat(char*, char*, long);
+extern	char*	strncpy(char*, char*, long);
+extern	int	strncmp(char*, char*, long);
+extern	long	strlen(char*);
+extern	char*	strrchr(char*, char);
+extern	char*	strstr(char*, char*);
+
+
+/*
+ * print routines
+ */
+typedef struct Fmt	Fmt;
+typedef int (*Fmts)(Fmt*);
+struct Fmt{
+	uchar	runes;			/* output buffer is runes or chars? */
+	void	*start;			/* of buffer */
+	void	*to;			/* current place in the buffer */
+	void	*stop;			/* end of the buffer; overwritten if flush fails */
+	int	(*flush)(Fmt *);	/* called when to == stop */
+	void	*farg;			/* to make flush a closure */
+	int	nfmt;			/* num chars formatted so far */
+	va_list	args;			/* args passed to dofmt */
+	int	r;			/* % format Rune */
+	int	width;
+	int	prec;
+	ulong	flags;
+};
+extern	int	print(char*, ...);
+extern	char*	vseprint(char*, char*, char*, va_list);
+extern	int	sprint(char*, char*, ...);
+extern 	int	snprint(char*, int, char*, ...);
+extern	int	fmtinstall(int, int (*)(Fmt*));
+
+#pragma varargck	argpos	addconf 1
+#pragma	varargck	argpos	fmtprint	2
+#pragma	varargck	argpos	print		1
+#pragma	varargck	argpos	seprint		3
+#pragma	varargck	argpos	snprint		3
+#pragma	varargck	argpos	sprint		2
+#pragma varargck	type	"H" void*
+
+#pragma	varargck	type	"lld"	vlong
+#pragma	varargck	type	"llx"	vlong
+#pragma	varargck	type	"lld"	uvlong
+#pragma	varargck	type	"llx"	uvlong
+#pragma	varargck	type	"ld"	long
+#pragma	varargck	type	"lx"	long
+#pragma	varargck	type	"ld"	ulong
+#pragma	varargck	type	"lx"	ulong
+#pragma	varargck	type	"d"	int
+#pragma	varargck	type	"x"	int
+#pragma	varargck	type	"c"	int
+#pragma	varargck	type	"C"	int
+#pragma	varargck	type	"d"	uint
+#pragma	varargck	type	"x"	uint
+#pragma	varargck	type	"c"	uint
+#pragma	varargck	type	"C"	uint
+#pragma	varargck	type	"f"	double
+#pragma	varargck	type	"e"	double
+#pragma	varargck	type	"g"	double
+#pragma	varargck	type	"s"	char*
+#pragma	varargck	type	"q"	char*
+#pragma	varargck	type	"S"	Rune*
+#pragma	varargck	type	"Q"	Rune*
+#pragma	varargck	type	"r"	void
+#pragma	varargck	type	"%"	void
+#pragma	varargck	type	"|"	int
+#pragma	varargck	type	"p"	void*
+#pragma varargck	type	"lux"	void*
+#pragma	varargck	type	"E"	uchar*
+
+#define PRINTSIZE	256
+
+/*
+ * one-of-a-kind
+ */
+extern	int	atoi(char*);
+extern	uintptr	getcallerpc(void*);
+extern	long	strtol(char*, char**, int);
+extern	ulong	strtoul(char*, char**, int);
+extern	uvlong	strtoull(char*, char**, int);
+extern	long	end;
+
+#define	NAMELEN	28
--- /dev/null
+++ b/os/boot.original/pc/load.c
@@ -1,0 +1,627 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "sd.h"
+#include "fs.h"
+
+#ifndef VERBOSE
+#define VERBOSE 0
+#endif
+
+/*
+ * "cache" must be in this list so that 9load will pass the definition of
+ * the cache partition into the kernel so that the disk named by the `cfs'
+ * variable in plan9.ini can be seen in all circumstances before termrc
+ * sets up all the disk partitions.  In particular, if it's on an odd-ball
+ * disk like sd10 rather than sdC0, this is needed.
+ */
+static char *diskparts[] = {
+	"dos", "9fat", "fs", "data", "cdboot", "cache", 0
+};
+static char *etherparts[] = { "*", 0 };
+
+static char *diskinis[] = {
+	"plan9/plan9.ini",
+	"plan9.ini",
+	0
+};
+static char *etherinis[] = {
+	"/cfg/pxe/%E",
+	0
+};
+
+/* ordering: devbios must be called before devsd calls sdbios */
+Type types[] = {
+	{	Tfloppy,
+		Fini|Ffs,
+		floppyinit, floppyinitdev,
+		floppygetfspart, 0, floppyboot,
+		floppyprintdevs,
+		diskparts,
+		diskinis,
+	},
+	{	Tether,
+		Fini|Fbootp,
+		etherinit, etherinitdev,
+		pxegetfspart, 0, bootpboot,
+		etherprintdevs,
+		etherparts,
+		etherinis,
+	},
+	{	Tbios,
+		Fini|Ffs,
+		biosinit, biosinitdev,
+		biosgetfspart, nil, biosboot,
+		biosprintdevs,
+		diskparts,
+		diskinis,
+	},
+	{	Tcd,
+		Fini|Ffs,
+		cdinit, sdinitdev,
+		sdgetfspart, sdaddconf, sdboot,
+		sdprintdevs,
+		diskparts,
+		diskinis,
+	},
+	{	Tsd,
+		Fini|Ffs,
+		sdinit, sdinitdev,
+		sdgetfspart, sdaddconf, sdboot,
+		sdprintdevs,
+		diskparts,
+		diskinis,
+	},
+	{	Tnil,
+		0,
+		nil, nil, nil, nil, nil, nil,
+		nil,
+		nil,
+		0,
+		nil,
+	},
+};
+
+static char *typenm[] = {
+	[Tnil]		"nil",
+	[Tfloppy]	"floppy",
+	[Tsd]		"sd",
+	[Tether]	"ether",
+	[Tcd]		"cd",
+	[Tbios]		"bios",
+};
+
+static char *
+typename(int type)
+{
+	if (type < 0 || type >= nelem(typenm) || typenm[type] == nil)
+		return "**gok**";
+	return typenm[type];
+}
+
+extern SDifc sdataifc;
+extern SDifc sdiahciifc;
+extern SDifc sdaoeifc;
+extern SDifc sdbiosifc;
+
+#ifdef NOSCSI
+
+SDifc* sdifc[] = {
+	&sdataifc,
+	&sdiahciifc,
+	&sdbiosifc,
+	&sdaoeifc,
+	nil,
+};
+
+#else
+
+extern SDifc sdmylexifc;
+extern SDifc sd53c8xxifc;
+
+SDifc* sdifc[] = {
+	&sdataifc,
+	&sdiahciifc,
+	&sdmylexifc,
+	&sd53c8xxifc,
+	&sdbiosifc,
+	&sdaoeifc,
+	nil,
+};
+
+#endif NOSCSI
+
+typedef struct Mode Mode;
+
+enum {
+	Maxdev		= 7,
+	Dany		= -1,
+	Nmedia		= 16,
+	Nini		= 10,
+};
+
+enum {					/* mode */
+	Mauto		= 0x00,
+	Mlocal		= 0x01,
+	Manual		= 0x02,
+	NMode		= 0x03,
+};
+
+typedef struct Medium Medium;
+struct Medium {
+	Type*	type;
+	int	flag;
+	int	dev;
+	char name[NAMELEN];
+
+	Fs *inifs;
+	char *part;
+	char *ini;
+
+	Medium*	next;
+};
+
+typedef struct Mode {
+	char*	name;
+	int	mode;
+} Mode;
+
+static Medium media[Nmedia];
+static Medium *curmedium = media;
+
+static Mode modes[NMode+1] = {
+	[Mauto]		{ "auto",   Mauto,  },
+	[Mlocal]	{ "local",  Mlocal, },
+	[Manual]	{ "manual", Manual, },
+};
+
+char **ini;
+
+int scsi0port;
+char *defaultpartition;
+int iniread;
+
+int debugload;
+
+static Medium*
+parse(char *line, char **file)
+{
+	char *p;
+	Type *tp;
+	Medium *mp;
+
+	if(p = strchr(line, '!')) {
+		*p++ = 0;
+		*file = p;
+	} else
+		*file = "";
+
+	for(tp = types; tp->type != Tnil; tp++)
+		for(mp = tp->media; mp; mp = mp->next)
+			if(strcmp(mp->name, line) == 0)
+				return mp;
+	if(p)
+		*--p = '!';
+	return nil;
+}
+
+static int
+boot(Medium *mp, char *file)
+{
+	Type *tp;
+	Medium *xmp;
+	static int didaddconf;
+	Boot b;
+
+	memset(&b, 0, sizeof b);
+	b.state = INITKERNEL;
+
+	if(didaddconf == 0) {
+		didaddconf = 1;
+		for(tp = types; tp->type != Tnil; tp++)
+			if(tp->addconf)
+				for(xmp = tp->media; xmp; xmp = xmp->next)
+					(*tp->addconf)(xmp->dev);
+	}
+
+	sprint(BOOTLINE, "%s!%s", mp->name, file);
+	print("booting %s!%s\n", mp->name, file);
+	return (*mp->type->boot)(mp->dev, file, &b);
+}
+
+static Medium*
+allocm(Type *tp)
+{
+	Medium **l;
+
+	if(curmedium >= &media[Nmedia])
+		return 0;
+
+	for(l = &tp->media; *l; l = &(*l)->next)
+		;
+	*l = curmedium++;
+	return *l;
+}
+
+Medium*
+probe(int type, int flag, int dev)
+{
+	Type *tp;
+	int i;
+	Medium *mp;
+	File f;
+	Fs *fs;
+	char **partp;
+
+	for(tp = types; tp->type != Tnil; tp++){
+		if(type != Tany && type != tp->type)
+			continue;
+
+		if(flag != Fnone){
+			for(mp = tp->media; mp; mp = mp->next){
+				if((flag & mp->flag) && (dev == Dany || dev == mp->dev))
+					return mp;
+			}
+		}
+		if (debugload)
+			print("probing %s...", typename(tp->type));
+		if((tp->flag & Fprobe) == 0){
+			tp->flag |= Fprobe;
+			tp->mask = (*tp->init)();
+		}
+
+		for(i = 0; tp->mask; i++){
+			if((tp->mask & (1<<i)) == 0)
+				continue;
+			tp->mask &= ~(1<<i);
+
+			if((mp = allocm(tp)) == 0)
+				continue;
+
+			mp->dev = i;
+			mp->flag = tp->flag;
+			mp->type = tp;
+			(*tp->initdev)(i, mp->name);
+
+			if(mp->flag & Fini){
+				mp->flag &= ~Fini;
+				for(partp = tp->parts; *partp; partp++){
+					if((fs = (*tp->getfspart)(i, *partp, 0)) == nil)
+						continue;
+
+					for(ini = tp->inis; *ini; ini++){
+						if(fswalk(fs, *ini, &f) > 0){
+							mp->inifs = fs;
+							mp->part = *partp;
+							mp->ini = f.path;
+							mp->flag |= Fini;
+							goto Break2;
+						}
+					}
+				}
+			}
+		Break2:
+			if((flag & mp->flag) && (dev == Dany || dev == i))
+				return mp;
+		}
+	}
+
+	return 0;
+}
+
+void
+main(void)
+{
+	Medium *mp;
+	int flag, i, mode, tried;
+	char def[2*NAMELEN], line[80], *p, *file;
+	Type *tp;
+
+	i8042a20();
+	memset(m, 0, sizeof(Mach));
+	trapinit();
+	clockinit();
+	alarminit();
+	meminit(0);
+	spllo();
+	consinit("0", "9600");
+	kbdinit();
+	if((ulong)&end > (KZERO|(640*1024)))
+		panic("i'm too big\n");
+
+	readlsconf();
+	print("initial probe, to find plan9.ini...");
+	/* find and read plan9.ini, setting configuration variables */
+	for(tp = types; tp->type != Tnil; tp++){
+		/* skip bios until we have read plan9.ini */
+		if(!pxe && tp->type == Tether || tp->type == Tbios)
+			continue;
+		if (VERBOSE)
+			print("probing %s...", typename(tp->type));
+		if((mp = probe(tp->type, Fini, Dany)) && (mp->flag & Fini)){
+			print("using %s!%s!%s\n", mp->name, mp->part, mp->ini);
+			iniread = !dotini(mp->inifs);
+			break;
+		}
+	}
+	print("\n");
+	apminit();
+
+	debugload = getconf("*debugload") != nil;
+	if((p = getconf("console")) != nil)
+		consinit(p, getconf("baud"));
+
+	devpccardlink();
+	devi82365link();
+
+	/*
+ 	 * Even after we find the ini file, we keep probing disks,
+	 * because we have to collect the partition tables and
+	 * have boot devices for parse.
+	 */
+	probe(Tany, Fnone, Dany);
+	if (debugload)
+		print("end disk probe\n");
+	tried = 0;
+	mode = Mauto;
+
+	p = getconf("bootfile");
+
+	if(p != 0) {
+		mode = Manual;
+		for(i = 0; i < NMode; i++){
+			if(strcmp(p, modes[i].name) == 0){
+				mode = modes[i].mode;
+				goto done;
+			}
+		}
+		if((mp = parse(p, &file)) == nil) {
+			print("Unknown boot device: %s\n", p);
+			goto done;
+		}
+		tried = boot(mp, file);
+	}
+done:
+	if(tried == 0 && mode != Manual){
+		flag = Fany;
+		if(mode == Mlocal)
+			flag &= ~Fbootp;
+		if((mp = probe(Tany, flag, Dany)) && mp->type->type != Tfloppy)
+			boot(mp, "");
+		if (debugload)
+			print("end auto probe\n");
+	}
+
+	def[0] = 0;
+	probe(Tany, Fnone, Dany);
+	if (debugload)
+		print("end final probe\n");
+	if(p = getconf("bootdef"))
+		strcpy(def, p);
+
+	flag = 0;
+	for(tp = types; tp->type != Tnil; tp++){
+		for(mp = tp->media; mp; mp = mp->next){
+			if(flag == 0){
+				flag = 1;
+				print("Boot devices:");
+			}
+			(*tp->printdevs)(mp->dev);
+		}
+	}
+	if(flag)
+		print("\n");
+
+	for(;;){
+		if(getstr("boot from", line, sizeof(line), def, (mode != Manual)*15) >= 0)
+			if(mp = parse(line, &file))
+				boot(mp, file);
+		def[0] = 0;
+	}
+}
+
+int
+getfields(char *lp, char **fields, int n, char sep)
+{
+	int i;
+
+	for(i = 0; lp && *lp && i < n; i++){
+		while(*lp == sep)
+			*lp++ = 0;
+		if(*lp == 0)
+			break;
+		fields[i] = lp;
+		while(*lp && *lp != sep){
+			if(*lp == '\\' && *(lp+1) == '\n')
+				*lp++ = ' ';
+			lp++;
+		}
+	}
+	return i;
+}
+
+int
+cistrcmp(char *a, char *b)
+{
+	int ac, bc;
+
+	for(;;){
+		ac = *a++;
+		bc = *b++;
+
+		if(ac >= 'A' && ac <= 'Z')
+			ac = 'a' + (ac - 'A');
+		if(bc >= 'A' && bc <= 'Z')
+			bc = 'a' + (bc - 'A');
+		ac -= bc;
+		if(ac)
+			return ac;
+		if(bc == 0)
+			break;
+	}
+	return 0;
+}
+
+int
+cistrncmp(char *a, char *b, int n)
+{
+	unsigned ac, bc;
+
+	while(n > 0){
+		ac = *a++;
+		bc = *b++;
+		n--;
+
+		if(ac >= 'A' && ac <= 'Z')
+			ac = 'a' + (ac - 'A');
+		if(bc >= 'A' && bc <= 'Z')
+			bc = 'a' + (bc - 'A');
+
+		ac -= bc;
+		if(ac)
+			return ac;
+		if(bc == 0)
+			break;
+	}
+
+	return 0;
+}
+
+#define PSTART		( 8*1024*1024)
+#define PEND		(16*1024*1024)
+
+ulong palloc = PSTART;
+
+void*
+ialloc(ulong n, int align)
+{
+	ulong p;
+	int a;
+
+	p = palloc;
+	if(align <= 0)
+		align = 4;
+	if(a = n % align)
+		n += align - a;
+	if(a = p % align)
+		p += align - a;
+
+
+	palloc = p+n;
+	if(palloc > PEND)
+		panic("ialloc(%lud, %d) called from %#p\n",
+			n, align, getcallerpc(&n));
+	return memset((void*)(p|KZERO), 0, n);
+}
+
+void*
+xspanalloc(ulong size, int align, ulong span)
+{
+	ulong a, v;
+
+	if((palloc + (size+align+span)) > PEND)
+		panic("xspanalloc(%lud, %d, 0x%lux) called from %#p\n",
+			size, align, span, getcallerpc(&size));
+
+	a = (ulong)ialloc(size+align+span, 0);
+
+	if(span > 2)
+		v = (a + span) & ~(span-1);
+	else
+		v = a;
+
+	if(align > 1)
+		v = (v + align) & ~(align-1);
+
+	return (void*)v;
+}
+
+static Block *allocbp;
+
+Block*
+allocb(int size)
+{
+	Block *bp, **lbp;
+	ulong addr;
+
+	lbp = &allocbp;
+	for(bp = *lbp; bp; bp = bp->next){
+		if((bp->lim - bp->base) >= size){
+			*lbp = bp->next;
+			break;
+		}
+		lbp = &bp->next;
+	}
+	if(bp == 0){
+		if((palloc + (sizeof(Block)+size+64)) > PEND)
+			panic("allocb(%d) called from %#p\n",
+				size, getcallerpc(&size));
+		bp = ialloc(sizeof(Block)+size+64, 0);
+		addr = (ulong)bp;
+		addr = ROUNDUP(addr + sizeof(Block), 8);
+		bp->base = (uchar*)addr;
+		bp->lim = ((uchar*)bp) + sizeof(Block)+size+64;
+	}
+
+	if(bp->flag)
+		panic("allocb reuse\n");
+
+	bp->rp = bp->base;
+	bp->wp = bp->rp;
+	bp->next = 0;
+	bp->flag = 1;
+
+	return bp;
+}
+
+void
+freeb(Block* bp)
+{
+	bp->next = allocbp;
+	allocbp = bp;
+
+	bp->flag = 0;
+}
+
+enum {
+	Paddr=		0x70,	/* address port */
+	Pdata=		0x71,	/* data port */
+};
+
+uchar
+nvramread(int offset)
+{
+	outb(Paddr, offset);
+	return inb(Pdata);
+}
+
+void (*etherdetach)(void);
+void (*floppydetach)(void);
+void (*sddetach)(void);
+
+void
+warp9(ulong entry)
+{
+	if(etherdetach)
+		etherdetach();
+	if(floppydetach)
+		floppydetach();
+	if(sddetach)
+		sddetach();
+	consdrain();
+
+	splhi();
+	trapdisable();
+
+	/*
+	 * This is where to push things on the stack to
+	 * boot *BSD systems, e.g.
+	(*(void(*)(void*, void*, void*, void*, ulong, ulong))(PADDR(entry)))(0, 0, 0, 0, 8196, 640);
+	 * will enable NetBSD boot (the real memory size needs to
+	 * go in the 5th argument).
+	 */
+	(*(void(*)(void))(PADDR(entry)))();
+}
--- /dev/null
+++ b/os/boot.original/pc/mbr.s
@@ -1,0 +1,259 @@
+/*
+ * Hard disc boot block. Loaded at 0x7C00, relocates to 0x0600:
+ *	8a mbr.s; 8l -o mbr -l -H3 -T0x0600 mbr.8
+ */
+#include "x16.h"
+#include "mem.h"
+
+/*#define FLOPPY	1		/* test on a floppy */
+#define TRACE(C)	PUSHA;\
+			CLR(rBX);\
+			MOVB $C, AL;\
+			LBI(0x0E, rAH);\
+			BIOSCALL(0x10);\
+			POPA
+
+/*
+ * We keep data on the stack, indexed by BP.
+ */
+#define Xdap		0x00		/* disc address packet */
+#define Xtable		0x10		/* partition table entry */
+#define Xdrive		0x12		/* starting disc */
+#define Xtotal		0x14		/* sum of allocated data above */
+
+/*
+ * Start: loaded at 0000:7C00, relocate to 0000:0600.
+ * Boot drive is in rDL.
+ */
+TEXT _start(SB), $0
+	CLI
+	CLR(rAX)
+	MTSR(rAX, rSS)			/* 0000 -> rSS */
+	LWI((0x7C00-Xtotal), rSP)	/* 7Bxx -> rSP */
+	MW(rSP, rBP)			/* set the indexed-data pointer */
+
+	MTSR(rAX, rDS)			/* 0000 -> rDS, source segment */
+	LWI(0x7C00, rSI)		/* 7C00 -> rSI, source offset */
+	MTSR(rAX, rES)			/* 0000 -> rES, destination segment */
+	LWI(0x600, rDI)			/* 0600 -> rDI, destination offset */
+	LWI(0x100, rCX)			/* 0100 -> rCX, loop count (words) */
+
+	CLD
+	REP; MOVSL			/* MOV DS:[(E)SI] -> ES:[(E)DI] */
+
+	FARJUMP16(0x0000, _start0600(SB))
+
+TEXT _start0600(SB), $0
+#ifdef FLOPPY
+	LBI(0x80, rDL)
+#else
+	CLRB(rAL)			/* some systems pass 0 */
+	CMPBR(rAL, rDL)
+	JNE _save
+	LBI(0x80, rDL)
+#endif /* FLOPPY */
+_save:
+	SXB(rDL, Xdrive, xBP)		/* save disc */
+
+	LWI(confidence(SB), rSI)	/* for that warm, fuzzy feeling */
+	CALL16(BIOSputs(SB))
+
+	LWI(_start+0x01BE(SB), rSI)	/* address of partition table */
+	LWI(0x04, rCX)			/* 4 entries in table */
+	LBI(0x80, rAH)			/* active entry value */
+	CLRB(rAL)			/* inactive entry value */
+
+_activeloop0:
+	LXB(0x00, xSI, rBL)		/* get active entry from table */
+	CMPBR(rBL, rAH)			/* is this an active entry? */
+	JEQ _active
+
+	CMPBR(rBL, rAL)			/* if not active it should be 0 */
+	JNE _invalidMBR
+
+	ADDI(0x10, rSI)			/* next table entry */
+	DEC(rCX)
+	JNE _activeloop0
+
+	LWI(noentry(SB), rSI)
+	CALL16(buggery(SB))
+
+_active:
+	MW(rSI, rDI)			/* save table address */
+
+_activeloop1:
+	ADDI(0x10, rSI)			/* next table entry */
+	DEC(rCX)
+	JEQ _readsector
+
+	LXB(0x00, xSI, rBL)		/* get active entry from table */
+	CMPBR(rBL, rAH)			/* is this an active entry? */
+	JNE _activeloop1		/* should only be one active */
+
+_invalidMBR:
+	LWI(invalidMBR(SB), rSI)
+	CALL16(buggery(SB))
+
+_readsector:
+	LBI(0x41, rAH)			/* check extensions present */
+	LWI(0x55AA, rBX)
+	LXB(Xdrive, xBP, rDL)		/* drive */
+	BIOSCALL(0x13)			/* CF set on failure */
+	JCS _readsector2
+	CMPI(0xAA55, rBX)
+	JNE _readsector2
+	ANDI(0x0001, rCX)
+	JEQ _readsector2
+
+_readsector42:
+	SBPBI(0x10, Xdap+0)		/* packet size */
+	SBPBI(0x00, Xdap+1)		/* reserved */
+	SBPBI(0x01, Xdap+2)		/* number of blocks to transfer */
+	SBPBI(0x00, Xdap+3)		/* reserved */
+	SBPWI(0x7C00, Xdap+4)		/* transfer buffer :offset */
+	SBPWI(0x0000, Xdap+6)		/* transfer buffer seg: */
+	LXW(0x08, xDI, rAX)		/* LBA (64-bits) */
+	SBPW(rAX, Xdap+8)
+	LXW(0x0A, xDI, rAX)
+	SBPW(rAX, Xdap+10)
+	SBPWI(0x0000, Xdap+12)
+	SBPWI(0x0000, Xdap+14)
+
+	MW(rBP, rSI)			/* disk address packet */
+	LBI(0x42, rAH)			/* extended read */
+	BIOSCALL(0x13)			/* CF set on failure */
+	JCC _readsectorok
+
+	LWI(ioerror(SB), rSI)
+	CALL16(buggery(SB))
+
+/*
+ * Read a sector from a disc using the traditional BIOS call.
+ * For BIOSCALL(0x13/AH=0x02):
+ *   rAH	0x02
+ *   rAL	number of sectors to read (1)
+ *   rCH	low 8 bits of cylinder
+ *   rCL	high 2 bits of cylinder (7-6), sector (5-0)
+ *   rDH	head
+ *   rDL	drive
+ *   rES:rBX	buffer address
+ */
+_readsector2:
+	LXB(0x01, xDI, rDH)		/* head */
+	LXW(0x02, xDI, rCX)		/* save active cylinder/sector */
+
+	LWI(0x0201, rAX)		/* read one sector */
+	LXB(Xdrive, xBP, rDL)		/* drive */
+	LWI(0x7C00, rBX)		/* buffer address (rES already OK) */
+	BIOSCALL(0x13)			/* CF set on failure */
+	JCC _readsectorok
+
+	LWI(ioerror(SB), rSI)
+	CALL16(buggery(SB))
+
+_readsectorok:
+	LWI(0x7C00, rBX)		/* buffer address (rES already OK) */
+	LXW(0x1FE, xBX, rAX)
+	CMPI(0xAA55, rAX)
+	JNE _bbnotok
+
+	/*
+	 * Jump to the loaded PBS.
+	 * rDL and rSI should still contain the drive
+	 * and partition table pointer respectively.
+	 */
+	MW(rDI, rSI)
+	FARJUMP16(0x0000, 0x7C00)
+
+_bbnotok:
+	LWI(invalidPBS(SB), rSI)
+
+TEXT buggery(SB), $0
+	CALL16(BIOSputs(SB))
+	LWI(reboot(SB), rSI)
+	CALL16(BIOSputs(SB))
+
+_wait:
+	CLR(rAX)			/* wait for any key */
+	BIOSCALL(0x16)
+
+_reset:
+	CLR(rBX)			/* set ES segment for BIOS area */
+	MTSR(rBX, rES)
+
+	LWI(0x0472, rBX)		/* warm-start code address */
+	LWI(0x1234, rAX)		/* warm-start code */
+	POKEW				/* MOVW	AX, ES:[BX] */
+
+	FARJUMP16(0xFFFF, 0x0000)	/* reset */
+
+/*
+ * Output a string to the display.
+ * String argument is in rSI.
+ */
+TEXT BIOSputs(SB), $0
+	PUSHA
+	CLR(rBX)
+_BIOSputs:
+	LODSB
+	ORB(rAL, rAL)
+	JEQ _BIOSputsret
+
+	LBI(0x0E, rAH)
+	BIOSCALL(0x10)
+	JMP _BIOSputs
+
+_BIOSputsret:
+	POPA
+	RET
+
+/* "No active entry in MBR" */
+TEXT noentry(SB), $0
+	BYTE $'N'; BYTE $'o'; BYTE $' '; BYTE $'a';
+	BYTE $'c'; BYTE $'t'; BYTE $'i'; BYTE $'v';
+	BYTE $'e'; BYTE $' '; BYTE $'e'; BYTE $'n';
+	BYTE $'t'; BYTE $'r'; BYTE $'y'; BYTE $' ';
+	BYTE $'i'; BYTE $'n'; BYTE $' '; BYTE $'M';
+	BYTE $'B'; BYTE $'R';
+	BYTE $'\z';
+
+/* "Invalid MBR" */
+TEXT invalidMBR(SB), $0
+	BYTE $'I'; BYTE $'n'; BYTE $'v'; BYTE $'a';
+	BYTE $'l'; BYTE $'i'; BYTE $'d'; BYTE $' ';
+	BYTE $'M'; BYTE $'B'; BYTE $'R';
+	BYTE $'\z';
+
+/* "I/O error" */
+TEXT ioerror(SB), $0
+	BYTE $'I'; BYTE $'/'; BYTE $'O'; BYTE $' ';
+	BYTE $'e'; BYTE $'r'; BYTE $'r'; BYTE $'o';
+	BYTE $'r';
+	BYTE $'\z';
+
+/* "Invalid PBS" */
+TEXT invalidPBS(SB), $0
+	BYTE $'I'; BYTE $'n'; BYTE $'v'; BYTE $'a';
+	BYTE $'l'; BYTE $'i'; BYTE $'d'; BYTE $' ';
+	BYTE $'P'; BYTE $'B'; BYTE $'S';
+	BYTE $'\z';
+
+/* "\r\nPress almost any key to reboot..." */
+TEXT reboot(SB), $0
+	BYTE $'\r';BYTE $'\n';
+	BYTE $'P'; BYTE $'r'; BYTE $'e'; BYTE $'s';
+	BYTE $'s'; BYTE $' '; BYTE $'a'; BYTE $'l'; 
+	BYTE $'m'; BYTE $'o'; BYTE $'s'; BYTE $'t';
+	BYTE $' '; BYTE $'a'; BYTE $'n'; BYTE $'y';
+	BYTE $' '; BYTE $'k'; BYTE $'e'; BYTE $'y';
+	BYTE $' '; BYTE $'t'; BYTE $'o'; BYTE $' ';
+	BYTE $'r'; BYTE $'e'; BYTE $'b'; BYTE $'o';
+	BYTE $'o'; BYTE $'t'; BYTE $'.'; BYTE $'.';
+	BYTE $'.';
+	BYTE $'\z';
+
+/* "MBR..." */
+TEXT confidence(SB), $0
+	BYTE $'M'; BYTE $'B'; BYTE $'R'; BYTE $'.';
+	BYTE $'.'; BYTE $'.';
+	BYTE $'\z';
--- /dev/null
+++ b/os/boot.original/pc/mem.h
@@ -1,0 +1,114 @@
+/*
+ * Memory and machine-specific definitions.  Used in C and assembler.
+ */
+
+/*
+ * Sizes
+ */
+#define	BI2BY		8			/* bits per byte */
+#define	BI2WD		32			/* bits per word */
+#define	BY2WD		4			/* bytes per word */
+#define	BY2PG		4096			/* bytes per page */
+#define	WD2PG		(BY2PG/BY2WD)		/* words per page */
+#define	PGSHIFT		12			/* log(BY2PG) */
+#define	PGROUND(s)	(((s)+(BY2PG-1))&~(BY2PG-1))
+
+#define	MAXMACH		1			/* max # cpus system can run */
+
+/*
+ * Time
+ */
+#define	HZ		(100)				/* clock frequency */
+#define	MS2HZ		(1000/HZ)			/* millisec per clock tick */
+#define	TK2SEC(t)	((t)/HZ)			/* ticks to seconds */
+#define	TK2MS(x)	((x)*(1000/HZ))
+#define	MS2TK(t)	((((ulong)(t))*HZ)/1000)	/* milliseconds to ticks */
+
+/*
+ * Fundamental addresses
+ */
+#define IDTADDR		0x80000800		/* idt */
+#define APBOOTSTRAP	0x80001000		/* AP bootstrap code */
+#define CONFADDR	0x80001200		/* info passed from boot loader */
+#define CPU0PDB		0x80002000		/* bootstrap processor PDB */
+#define CPU0PTE		0x80003000		/* bootstrap processor PTE's for 0-4MB */
+#define MACHADDR	0x80004000		/* as seen by current processor */
+#define CPU0MACH	0x80005000		/* Mach for bootstrap processor */
+#define BIOSXCHG	0x80006000		/* To exchange data with the BIOS */
+#define	MACHSIZE	(BY2PG*8)		/* stack size */
+
+/*
+ *  Address spaces
+ *
+ *  Kernel is at 2GB-4GB
+ */
+#define	KZERO		0x80000000		/* base of kernel address space */
+#define	KTZERO		KZERO			/* first address in kernel text */
+#define ROMBIOS		(KZERO|0xF0000)
+
+/*
+ *  known 80386 segments (in GDT) and their selectors
+ */
+#define	NULLSEG	0	/* null segment */
+#define	KDSEG	1	/* kernel data/stack */
+#define	KESEG	2	/* kernel executable */	
+#define	UDSEG	3	/* user data/stack */
+#define	UESEG	4	/* user executable */
+#define	SYSGATE	5	/* system call gate */
+#define TSSSEG	6	/* task segment */
+
+#define SELGDT	(0<<3)	/* selector is in gdt */
+#define	SELLDT	(1<<3)	/* selector is in ldt */
+
+#define SELECTOR(i, t, p)	(((i)<<3) | (t) | (p))
+
+#define NULLSEL	SELECTOR(NULLSEG, SELGDT, 0)
+#define KESEL	SELECTOR(KESEG, SELGDT, 0)
+#define KDSEL	SELECTOR(KDSEG, SELGDT, 0)
+#define UESEL	SELECTOR(UESEG, SELGDT, 3)
+#define UDSEL	SELECTOR(UDSEG, SELGDT, 3)
+#define TSSSEL	SELECTOR(TSSSEG, SELGDT, 0)
+
+/*
+ *  fields in segment descriptors
+ */
+#define SEGDATA	(0x10<<8)	/* data/stack segment */
+#define SEGEXEC	(0x18<<8)	/* executable segment */
+#define	SEGTSS	(0x9<<8)	/* TSS segment */
+#define SEGCG	(0x0C<<8)	/* call gate */
+#define	SEGIG	(0x0E<<8)	/* interrupt gate */
+#define SEGTG	(0x0F<<8)	/* task gate */
+#define SEGTYPE	(0x1F<<8)
+
+#define SEGP	(1<<15)		/* segment present */
+#define SEGPL(x) ((x)<<13)	/* priority level */
+#define SEGB	(1<<22)		/* granularity 1==4k (for expand-down) */
+#define SEGG	(1<<23)		/* granularity 1==4k (for other) */
+#define SEGE	(1<<10)		/* expand down */
+#define SEGW	(1<<9)		/* writable (for data/stack) */
+#define	SEGR	(1<<9)		/* readable (for code) */
+#define SEGD	(1<<22)		/* default 1==32bit (for code) */
+
+/*
+ *  virtual MMU
+ */
+#define PTEMAPMEM	(1024*1024)	/* ??? */	
+#define SEGMAPSIZE	16		/* ??? */
+#define	PTEPERTAB	(PTEMAPMEM/BY2PG)	/* ??? */
+#define PPN(x)		((x)&~(BY2PG-1))
+
+/*
+ *  physical MMU
+ */
+#define	PTEVALID	(1<<0)
+#define	PTEUNCACHED	0		/* everything is uncached */
+#define	PTEWRITE	(1<<1)
+#define	PTERONLY	(0<<1)
+#define	PTEKERNEL	(0<<2)
+#define	PTEUSER		(1<<2)
+#define	PTESIZE		(1<<7)
+
+/*
+ *  flag register bits that we care about
+ */
+#define IFLAG	0x200
--- /dev/null
+++ b/os/boot.original/pc/memory.c
@@ -1,0 +1,504 @@
+/*
+ * Size memory and create the kernel page-tables on the fly while doing so.
+ * Called from main(), this code should only be run by the bootstrap processor.
+ */
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+#define MEMDEBUG	0
+
+#define PDX(va)		((((ulong)(va))>>22) & 0x03FF)
+#define PTX(va)		((((ulong)(va))>>12) & 0x03FF)
+
+enum {
+	MemUPA		= 0,		/* unbacked physical address */
+	MemRAM		= 1,		/* physical memory */
+	MemUMB		= 2,		/* upper memory block (<16MB) */
+	NMemType	= 3,
+
+	KB		= 1024,
+
+	MemMinMB	= 4,		/* minimum physical memory (<=4MB) */
+	MemMaxMB	= 768,		/* maximum physical memory to check */
+
+	NMemBase	= 10,
+};
+
+typedef struct {
+	int	size;
+	ulong	addr;
+} Map;
+
+typedef struct {
+	char*	name;
+	Map*	map;
+	Map*	mapend;
+
+	Lock;
+} RMap;
+
+static Map mapupa[8];
+static RMap rmapupa = {
+	"unallocated unbacked physical memory",
+	mapupa,
+	&mapupa[7],
+};
+
+static Map xmapupa[8];
+static RMap xrmapupa = {
+	"unbacked physical memory",
+	xmapupa,
+	&xmapupa[7],
+};
+
+static Map mapram[8];
+static RMap rmapram = {
+	"physical memory",
+	mapram,
+	&mapram[7],
+};
+
+static Map mapumb[64];
+static RMap rmapumb = {
+	"upper memory block",
+	mapumb,
+	&mapumb[63],
+};
+
+static Map mapumbrw[8];
+static RMap rmapumbrw = {
+	"UMB device memory",
+	mapumbrw,
+	&mapumbrw[7],
+};
+
+void
+memdebug(void)
+{
+	Map *mp;
+	ulong maxpa, maxpa1, maxpa2;
+
+	if(MEMDEBUG == 0)
+		return;
+
+	maxpa = (nvramread(0x18)<<8)|nvramread(0x17);
+	maxpa1 = (nvramread(0x31)<<8)|nvramread(0x30);
+	maxpa2 = (nvramread(0x16)<<8)|nvramread(0x15);
+	print("maxpa = %luX -> %luX, maxpa1 = %luX maxpa2 = %luX\n",
+		maxpa, MB+maxpa*KB, maxpa1, maxpa2);
+
+	for(mp = rmapram.map; mp->size; mp++)
+		print("%8.8luX %8.8luX %8.8luX\n", mp->addr, (ulong)mp->size, mp->addr+mp->size);
+	for(mp = rmapumb.map; mp->size; mp++)
+		print("%8.8luX %8.8luX %8.8luX\n", mp->addr, (ulong)mp->size, mp->addr+mp->size);
+	for(mp = rmapumbrw.map; mp->size; mp++)
+		print("%8.8luX %8.8luX %8.8luX\n", mp->addr, (ulong)mp->size, mp->addr+mp->size);
+	for(mp = rmapupa.map; mp->size; mp++)
+		print("%8.8luX %8.8luX %8.8luX\n", mp->addr, (ulong)mp->size, mp->addr+mp->size);
+}
+
+void
+mapfree(RMap* rmap, ulong addr, ulong size)
+{
+	Map *mp;
+	ulong t;
+
+	if(size == 0)
+		return;
+
+	lock(rmap);
+	for(mp = rmap->map; mp->addr <= addr && mp->size; mp++)
+		;
+
+	if(mp > rmap->map && (mp-1)->addr+(mp-1)->size == addr){
+		(mp-1)->size += size;
+		if(addr+size == mp->addr){
+			(mp-1)->size += mp->size;
+			while(mp->size){
+				mp++;
+				(mp-1)->addr = mp->addr;
+				(mp-1)->size = mp->size;
+			}
+		}
+	}
+	else{
+		if(addr+size == mp->addr && mp->size){
+			mp->addr -= size;
+			mp->size += size;
+		}
+		else do{
+			if(mp >= rmap->mapend){
+				print("mapfree: %s: losing 0x%luX, %lud\n",
+					rmap->name, addr, size);
+				break;
+			}
+			t = mp->addr;
+			mp->addr = addr;
+			addr = t;
+			t = mp->size;
+			mp->size = size;
+			mp++;
+		}while(size = t);
+	}
+	unlock(rmap);
+}
+
+ulong
+mapalloc(RMap* rmap, ulong addr, int size, int align)
+{
+	Map *mp;
+	ulong maddr, oaddr;
+
+	lock(rmap);
+	for(mp = rmap->map; mp->size; mp++){
+		maddr = mp->addr;
+
+		if(addr){
+			/*
+			 * A specific address range has been given:
+			 *   if the current map entry is greater then
+			 *   the address is not in the map;
+			 *   if the current map entry does not overlap
+			 *   the beginning of the requested range then
+			 *   continue on to the next map entry;
+			 *   if the current map entry does not entirely
+			 *   contain the requested range then the range
+			 *   is not in the map.
+			 */
+			if(maddr > addr)
+				break;
+			if(mp->size < addr - maddr)	/* maddr+mp->size < addr, but no overflow */
+				continue;
+			if(addr - maddr > mp->size - size)	/* addr+size > maddr+mp->size, but no overflow */
+				break;
+			maddr = addr;
+		}
+
+		if(align > 0)
+			maddr = ((maddr+align-1)/align)*align;
+		if(mp->addr+mp->size-maddr < size)
+			continue;
+
+		oaddr = mp->addr;
+		mp->addr = maddr+size;
+		mp->size -= maddr-oaddr+size;
+		if(mp->size == 0){
+			do{
+				mp++;
+				(mp-1)->addr = mp->addr;
+			}while((mp-1)->size = mp->size);
+		}
+
+		unlock(rmap);
+		if(oaddr != maddr)
+			mapfree(rmap, oaddr, maddr-oaddr);
+
+		return maddr;
+	}
+	unlock(rmap);
+
+	return 0;
+}
+
+static void
+umbscan(void)
+{
+	uchar *p;
+
+	/*
+	 * Scan the Upper Memory Blocks (0xA0000->0xF0000) for pieces
+	 * which aren't used; they can be used later for devices which
+	 * want to allocate some virtual address space.
+	 * Check for two things:
+	 * 1) device BIOS ROM. This should start with a two-byte header
+	 *    of 0x55 0xAA, followed by a byte giving the size of the ROM
+	 *    in 512-byte chunks. These ROM's must start on a 2KB boundary.
+	 * 2) device memory. This is read-write.
+	 * There are some assumptions: there's VGA memory at 0xA0000 and
+	 * the VGA BIOS ROM is at 0xC0000. Also, if there's no ROM signature
+	 * at 0xE0000 then the whole 64KB up to 0xF0000 is theoretically up
+	 * for grabs; check anyway.
+	 */
+	p = KADDR(0xD0000);	/*RSC: changed from 0xC0000 */
+	while(p < (uchar*)KADDR(0xE0000)){
+		if (p[0] == 0x55 && p[1] == 0xAA) {
+			/* Skip p[2] chunks of 512 bytes.  Test for 0x55 AA before
+			     poking obtrusively, or else the Thinkpad X20 dies when
+			     setting up the cardbus (PB) */
+			p += p[2] * 512;
+			continue;
+		}
+
+		p[0] = 0xCC;
+		p[2*KB-1] = 0xCC;
+		if(p[0] != 0xCC || p[2*KB-1] != 0xCC){
+			p[0] = 0x55;
+			p[1] = 0xAA;
+			p[2] = 4;
+			if(p[0] == 0x55 && p[1] == 0xAA){
+				p += p[2]*512;
+				continue;
+			}
+			if(p[0] == 0xFF && p[1] == 0xFF)
+				mapfree(&rmapumb, PADDR(p), 2*KB);
+		}
+		else
+			mapfree(&rmapumbrw, PADDR(p), 2*KB);
+		p += 2*KB;
+	}
+
+	p = KADDR(0xE0000);
+	if(p[0] != 0x55 || p[1] != 0xAA){
+		p[0] = 0xCC;
+		p[64*KB-1] = 0xCC;
+		if(p[0] != 0xCC && p[64*KB-1] != 0xCC)
+			mapfree(&rmapumb, PADDR(p), 64*KB);
+	}
+}
+
+
+void
+meminit(ulong)
+{
+	/* A hack to initialize unbacked physical memory.  It's assumed PCI space is assigned by 
+	     the BIOS in the 0xF0000000 range and 9load never needs more than 0x2000... to run. These
+	     values leave ample space for memory allocations for uninitialized PCI cards (e.g. cardbus 
+	     cards).  (pb) */
+	ulong maxmem = 0x40000000;
+
+	umbscan();
+	mapfree(&rmapupa, maxmem, 0x00000000-maxmem);
+	if(MEMDEBUG)
+		memdebug();
+}
+
+ulong
+umbmalloc(ulong addr, int size, int align)
+{
+	ulong a;
+
+	if(a = mapalloc(&rmapumb, addr, size, align))
+		return (ulong)KADDR(a);
+
+	return 0;
+}
+
+void
+umbfree(ulong addr, int size)
+{
+	mapfree(&rmapumb, PADDR(addr), size);
+}
+
+ulong
+umbrwmalloc(ulong addr, int size, int align)
+{
+	ulong a;
+	uchar *p;
+
+	if(a = mapalloc(&rmapumbrw, addr, size, align))
+		return(ulong)KADDR(a);
+
+	/*
+	 * Perhaps the memory wasn't visible before
+	 * the interface is initialised, so try again.
+	 */
+	if((a = umbmalloc(addr, size, align)) == 0)
+		return 0;
+	p = (uchar*)a;
+	p[0] = 0xCC;
+	p[size-1] = 0xCC;
+	if(p[0] == 0xCC && p[size-1] == 0xCC)
+		return a;
+	umbfree(a, size);
+
+	return 0;
+}
+
+void
+umbrwfree(ulong addr, int size)
+{
+	mapfree(&rmapumbrw, PADDR(addr), size);
+}
+
+ulong*
+mmuwalk(ulong* pdb, ulong va, int level, int create)
+{
+	ulong pa, *table;
+
+	/*
+	 * Walk the page-table pointed to by pdb and return a pointer
+	 * to the entry for virtual address va at the requested level.
+	 * If the entry is invalid and create isn't requested then bail
+	 * out early. Otherwise, for the 2nd level walk, allocate a new
+	 * page-table page and register it in the 1st level.
+	 */
+	table = &pdb[PDX(va)];
+	if(!(*table & PTEVALID) && create == 0)
+		return 0;
+
+	switch(level){
+
+	default:
+		return 0;
+
+	case 1:
+		return table;
+
+	case 2:
+		if(*table & PTESIZE)
+			panic("mmuwalk2: va 0x%ux entry 0x%ux\n", va, *table);
+		if(!(*table & PTEVALID)){
+			pa = PADDR(ialloc(BY2PG, BY2PG));
+			*table = pa|PTEWRITE|PTEVALID;
+		}
+		table = KADDR(PPN(*table));
+
+		return &table[PTX(va)];
+	}
+}
+
+static Lock mmukmaplock;
+
+ulong
+mmukmap(ulong pa, ulong va, int size)
+{
+	ulong pae, *table, *pdb, pgsz, *pte, x;
+	int pse, sync;
+	extern int cpuidax, cpuiddx;
+
+	pdb = KADDR(getcr3());
+	if((cpuiddx & 0x08) && (getcr4() & 0x10))
+		pse = 1;
+	else
+		pse = 0;
+	sync = 0;
+
+	pa = PPN(pa);
+	if(va == 0)
+		va = (ulong)KADDR(pa);
+	else
+		va = PPN(va);
+
+	pae = pa + size;
+	lock(&mmukmaplock);
+	while(pa < pae){
+		table = &pdb[PDX(va)];
+		/*
+		 * Possibly already mapped.
+		 */
+		if(*table & PTEVALID){
+			if(*table & PTESIZE){
+				/*
+				 * Big page. Does it fit within?
+				 * If it does, adjust pgsz so the correct end can be
+				 * returned and get out.
+				 * If not, adjust pgsz up to the next 4MB boundary
+				 * and continue.
+				 */
+				x = PPN(*table);
+				if(x != pa)
+					panic("mmukmap1: pa 0x%ux  entry 0x%ux\n",
+						pa, *table);
+				x += 4*MB;
+				if(pae <= x){
+					pa = pae;
+					break;
+				}
+				pgsz = x - pa;
+				pa += pgsz;
+				va += pgsz;
+
+				continue;
+			}
+			else{
+				/*
+				 * Little page. Walk to the entry.
+				 * If the entry is valid, set pgsz and continue.
+				 * If not, make it so, set pgsz, sync and continue.
+				 */
+				pte = mmuwalk(pdb, va, 2, 0);
+				if(pte && *pte & PTEVALID){
+					x = PPN(*pte);
+					if(x != pa)
+						panic("mmukmap2: pa 0x%ux entry 0x%ux\n",
+							pa, *pte);
+					pgsz = BY2PG;
+					pa += pgsz;
+					va += pgsz;
+					sync++;
+
+					continue;
+				}
+			}
+		}
+
+		/*
+		 * Not mapped. Check if it can be mapped using a big page -
+		 * starts on a 4MB boundary, size >= 4MB and processor can do it.
+		 * If not a big page, walk the walk, talk the talk.
+		 * Sync is set.
+		 */
+		if(pse && (pa % (4*MB)) == 0 && (pae >= pa+4*MB)){
+			*table = pa|PTESIZE|PTEWRITE|PTEUNCACHED|PTEVALID;
+			pgsz = 4*MB;
+		}
+		else{
+			pte = mmuwalk(pdb, va, 2, 1);
+			*pte = pa|PTEWRITE|PTEUNCACHED|PTEVALID;
+			pgsz = BY2PG;
+		}
+		pa += pgsz;
+		va += pgsz;
+		sync++;
+	}
+	unlock(&mmukmaplock);
+
+	/*
+	 * If something was added
+	 * then need to sync up.
+	 */
+	if(sync)
+		putcr3(PADDR(pdb));
+
+	return pa;
+}
+
+ulong
+upamalloc(ulong addr, int size, int align)
+{
+	ulong ae, a;
+
+	USED(align);
+
+	if((a = mapalloc(&rmapupa, addr, size, align)) == 0){
+		memdebug();
+		return 0;
+	}
+
+	/*
+	 * This is a travesty, but they all are.
+	 */
+	ae = mmukmap(a, 0, size);
+
+	/*
+	 * Should check here that it was all delivered
+	 * and put it back and barf if not.
+	 */
+	USED(ae);
+
+	/*
+	 * Be very careful this returns a PHYSICAL address.
+	 */
+	return a;
+}
+
+void
+upafree(ulong pa, int size)
+{
+	USED(pa, size);
+}
+
--- /dev/null
+++ b/os/boot.original/pc/mkfile
@@ -1,0 +1,250 @@
+<../../../mkconfig
+objtype=386
+SYSTARG=$OSTARG
+OBJTYPE=386
+BIN=$ROOT/Inferno/$OBJTYPE
+LIBDIR=$ROOT/Inferno/$OBJTYPE/lib
+LIBDIRS=../libflate $ROOT/libkern
+LIBS=\
+	libflate\
+	libkern\
+
+LIBFILES=${LIBS:%=$LIBDIR/%.a}
+<$ROOT/mkfiles/mkfile-$SYSTARG-$OBJTYPE
+
+BIN=$ROOT/Inferno/$OBJTYPE
+
+TARG=\
+	9load\
+	9pxeload\
+	9loadlite\
+	9loaddebug\
+	9loadlitedebug\
+	ld.com\
+	mbr\
+	pbs\
+	pbslba\
+
+CORE=\
+	alarm.$O\
+	cga.$O\
+	clock.$O\
+	console.$O\
+	dosboot.$O\
+	devfloppy.$O\
+	dma.$O\
+	fs.$O\
+	ilock.$O\
+	kbd.$O\
+	kfsboot.$O\
+	print.$O\
+	queue.$O\
+	trap.$O\
+	getcallerpc.$O\
+
+LOAD=\
+	8250.$O\
+	apm.$O\
+	boot.$O\
+	cis.$O\
+	conf.$O\
+	devbios.$O\
+	devi82365.$O\
+	devpccard.$O\
+	devsd.$O\
+	inflate.$O\
+	load.$O\
+	memory.$O\
+	part.$O\
+	pci.$O\
+	sdata.$O\
+	sdmylex.$O\
+	sd53c8xx.$O\
+	sdiahci.$O\
+	sdscsi.$O\
+	sdaoe.$O\
+	sdbios.$O\
+
+ETHER=\
+	bootp.$O\
+	eipfmt.$O\
+	ether.$O\
+	ether2114x.$O\
+	ether2000.$O\
+	ether589.$O\
+	ether79c970.$O\
+	ether8003.$O\
+	ether8139.$O\
+	ether8169.$O\
+	ether82563.$O\
+	ether82557.$O\
+	ether83815.$O\
+	ether8390.$O\
+	etherec2t.$O\
+	etherelnk3.$O\
+	etherga620.$O\
+	etherigbe.$O\
+	ethermii.$O\
+	etherrhine.$O\
+	etherdp83820.$O\
+
+BCOM=\
+	bcom.$O\
+	bootld.$O\
+	devsd.$O\
+	memory.$O\
+	part.$O\
+	pci.$O\
+	sdata.$O\
+	sdscsi.$O\
+
+HFILES=\
+	lib.h\
+	mem.h\
+	dat.h\
+	fns.h\
+	io.h\
+	aoe.h\
+
+CFLAGS=-FVTw -I. -I$ROOT/Inferno/$OBJTYPE/include -I$ROOT/include
+
+all:V:	$TARG
+
+9load:	l.$O $CORE $LOAD $ETHER $LIBFILES
+	$LD -o $target -H3 -T0x80010000 -l $prereq
+	ls -l $target
+
+9pxeload:	l.$O $CORE $LOAD $ETHER $LIBFILES
+	$LD -o $target -H3 -T0x80007C00 -l $prereq
+	ls -l $target
+
+9loaddebug:	l.$O $CORE $LOAD $ETHER $LIBFILES
+	$LD -o $target -T0x80010000 -l $prereq
+	ls -l $target
+	# acid $target
+	# map({"text", 0x80010000, 0x80090000, 0x00000020})
+
+9loadlite:	l.$O $CORE $LOAD noether.$O $LIBFILES
+	$LD -o $target -H3 -T0x80010000 -l $prereq
+	ls -l $target
+
+9loadlitedebug:	l.$O $CORE $LOAD noether.$O $LIBFILES
+	$LD -o $target -T0x80010000 -l $prereq
+	ls -l $target
+	# acid $target
+	# map({"text", 0x80010000, 0x80090000, 0x00000020})
+
+ld.com:	ld.$O $CORE $BCOM $LIBFILES
+	$LD -o $target -H3 -T0x80080100 -l $prereq
+	ls -l $target
+
+lddebug:	ld.$O $CORE $BCOM $LIBFILES
+	$LD -o $target -T0x80080100 -l $prereq
+	ls -l $target
+	# acid $target
+	# map({"text", 0x80080100, 0x800B0000, 0x00000020})
+
+ld.$O:	l.s
+	$AS -DDOTCOM -o $target l.s
+
+lpxe.$O:	l.s
+	$AS -DPXE -o $target l.s
+
+%.$O:	%.s
+	$AS $stem.s
+
+%.$O:	%.c
+	$CC $CFLAGS $stem.c
+
+%.$O:	$HFILES
+
+l.$O pbs.$O pbslba.$O mbr.$O:	x16.h
+
+clock.$O floppy.$O trap.$O:	ureg.h
+bcom.$O conf.$O devfloppy.$O devsd.$O dosboot.$O fs.$O \
+	kfsboot.$O load.$O part.$O:	dosfs.h fs.h kfs.h
+ether.$O etherelnk3.$O:	etherif.h
+devsd.$O part.$O sdata.$O sdscsi.$O: sd.h
+bootp.$O:	ip.h
+
+mbr:	mbr.$O
+	$LD -o $target -H3 -T0x0600 -l $prereq
+	ls -l $target
+
+pbs&:	pbs%.$O
+	$LD -o $target -H3 -T0x7C00 -l $prereq
+	ls -l $target
+
+pbs&.debug:	pbs%.$O
+	$LD -o $target -T0x7C00 -l $prereq
+	ls -l $target
+	# acid $target
+	# map({"text", 0x7C00, 0x7E00, 0x00000020})
+	
+# added to cause libflate to be made automatically:
+
+$ROOT/Inferno/$OBJTYPE/lib/lib%.a:Q:	all-$SHELLTYPE
+	#
+
+rc-lib%.a nt-lib%.a:VQ:
+	echo '@{builtin cd ' $ROOT/lib$stem ';mk SHELLTYPE=$SHELLTYPE SYSTARG=$SYSTARG OBJTYPE=$OBJTYPE install}'
+	@{builtin cd  $ROOT/lib$stem ;mk 'SHELLTYPE='$SHELLTYPE 'SYSTARG='$SYSTARG 'OBJTYPE='$OBJTYPE install}
+
+sh-lib%.a:VQ:
+	echo "(cd $ROOT/lib$stem ; mk SHELLTYPE=$SHELLTYPE SYSTARG=$SYSTARG OBJTYPE=$OBJTYPE install)"
+	(cd $ROOT/lib$stem ; mk SHELLTYPE=$SHELLTYPE SYSTARG=$SYSTARG OBJTYPE=$OBJTYPE install)
+
+clean:
+	rm -f *.[$OS] [$OS].out y.tab.? y.debug y.output $TARG 9loaddebug lddebug
+
+install:V:
+	for (i in $TARG)
+		mk $MKFLAGS $i.install
+
+%.install:V:	$BIN/%
+
+$BIN/%:	%
+	cp $stem $BIN/$stem
+
+UPDATE=\
+	mkfile\
+	${CORE:%.$O=%.c}\
+	${LOAD:%.$O=%.c}\
+	${BCOM:%.$O=%.c}\
+	${ETHER:%.$O=%.c}\
+	$HFILES\
+	l.s\
+	noether.c\
+	pbs.s\
+	pbslba.s\
+	mbr.s\
+	x16.h\
+	ureg.h\
+	dosfs.h\
+	fs.h\
+	kfs.h\
+	etherif.h\
+	sd.h\
+	ip.h\
+	devfloppy.h\
+	${TARG:%=/386/%}\
+
+update:V:
+	update $UPDATEFLAGS $UPDATE
+
+
+%-sh:QV:
+		for i in $LIBDIRS
+		do
+			echo "(cd $i ; mk SHELLTYPE=$SHELLTYPE SYSTARG=$SYSTARG OBJTYPE=$OBJTYPE $stem)"
+			(cd $i; mk 'SHELLTYPE='$SHELLTYPE 'SYSTARG='$SYSTARG 'OBJTYPE='$OBJTYPE $stem)
+		done
+
+%-rc %-nt:QV:
+		for (i in $LIBDIRS)
+		{
+			echo '@{cd $i ; mk SHELLTYPE=$SHELLTYPE SYSTARG=$SYSTARG OBJTYPE=$OBJTYPE $stem}'
+			@{cd $i; mk 'SHELLTYPE='$SHELLTYPE 'SYSTARG='$SYSTARG 'OBJTYPE='$OBJTYPE $stem}
+		}
+
+nuke:V:		clean nuke-$SHELLTYPE
--- /dev/null
+++ b/os/boot.original/pc/noether.c
@@ -1,0 +1,46 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+int
+etherinit(void)
+{
+	return -1;
+}
+
+void
+etherinitdev(int, char*)
+{
+}
+
+void
+etherprintdevs(int)
+{
+}
+
+int
+etherrxpkt(int, Etherpkt*, int)
+{
+	return -1;
+}
+
+int
+ethertxpkt(int, Etherpkt*, int, int)
+{
+	return -1;
+}
+
+int
+bootpboot(int, char*, Boot*)
+{
+	return -1;
+}
+
+void*
+pxegetfspart(int, char*, int)
+{
+	return nil;
+}
--- /dev/null
+++ b/os/boot.original/pc/part.c
@@ -1,0 +1,344 @@
+#include	"u.h"
+#include	"lib.h"
+#include	"mem.h"
+#include	"dat.h"
+#include	"fns.h"
+
+#include	"sd.h"
+#include	"fs.h"
+
+enum {
+	Npart = 32
+};
+
+uchar *mbrbuf, *partbuf;
+int nbuf;
+#define trace 0
+
+int
+tsdbio(SDunit *unit, SDpart *part, void *a, vlong off, int mbr)
+{
+	uchar *b;
+
+	if(sdbio(unit, part, a, unit->secsize, off) != unit->secsize){
+		if(trace)
+			print("%s: read %lud at %lld failed\n", unit->name,
+				unit->secsize, (vlong)part->start*unit->secsize+off);
+		return -1;
+	}
+	b = a;
+	if(mbr && (b[0x1FE] != 0x55 || b[0x1FF] != 0xAA)){
+		if(trace)
+			print("%s: bad magic %.2ux %.2ux at %lld\n",
+				unit->name, b[0x1FE], b[0x1FF],
+				(vlong)part->start*unit->secsize+off);
+		return -1;
+	}
+	return 0;
+}
+
+/*
+ *  read partition table.  The partition table is just ascii strings.
+ */
+#define MAGIC "plan9 partitions"
+static void
+oldp9part(SDunit *unit)
+{
+	SDpart *pp;
+	char *field[3], *line[Npart+1];
+	ulong n, start, end;
+	int i;
+
+	/*
+	 *  We have some partitions already.
+	 */
+	pp = &unit->part[unit->npart];
+
+	/*
+	 * We prefer partition tables on the second to last sector,
+	 * but some old disks use the last sector instead.
+	 */
+	strcpy(pp->name, "partition");
+	pp->start = unit->sectors - 2;
+	pp->end = unit->sectors - 1;
+
+	if(tsdbio(unit, pp, partbuf, 0, 0) < 0)
+		return;
+
+	if(strncmp((char*)partbuf, MAGIC, sizeof(MAGIC)-1) != 0) {
+		/* not found on 2nd last sector; look on last sector */
+		pp->start++;
+		pp->end++;
+		if(tsdbio(unit, pp, partbuf, 0, 0) < 0)
+			return;
+		if(strncmp((char*)partbuf, MAGIC, sizeof(MAGIC)-1) != 0)
+			return;
+		print("%s: using old plan9 partition table on last sector\n", unit->name);
+	}else
+		print("%s: using old plan9 partition table on 2nd-to-last sector\n", unit->name);
+
+	/* we found a partition table, so add a partition partition */
+	unit->npart++;
+	partbuf[unit->secsize-1] = '\0';
+
+	/*
+	 * parse partition table
+	 */
+	n = getfields((char*)partbuf, line, Npart+1, '\n');
+	if(n && strncmp(line[0], MAGIC, sizeof(MAGIC)-1) == 0){
+		for(i = 1; i < n && unit->npart < SDnpart; i++){
+			if(getfields(line[i], field, 3, ' ') != 3)
+				break;
+			start = strtoull(field[1], 0, 0);
+			end = strtoull(field[2], 0, 0);
+			if(start >= end || end > unit->sectors)
+				break;
+			sdaddpart(unit, field[0], start, end);
+		}
+	}	
+}
+
+static void
+p9part(SDunit *unit, char *name)
+{
+	SDpart *p;
+	char *field[4], *line[Npart+1];
+	uvlong start, end;
+	int i, n;
+	
+	p = sdfindpart(unit, name);
+	if(p == nil)
+		return;
+
+	if(tsdbio(unit, p, partbuf, unit->secsize, 0) < 0)
+		return;
+	partbuf[unit->secsize-1] = '\0';
+
+	if(strncmp((char*)partbuf, "part ", 5) != 0)
+		return;
+
+	n = getfields((char*)partbuf, line, Npart+1, '\n');
+	if(n == 0)
+		return;
+	for(i = 0; i < n && unit->npart < SDnpart; i++){
+		if(strncmp(line[i], "part ", 5) != 0)
+			break;
+		if(getfields(line[i], field, 4, ' ') != 4)
+			break;
+		start = strtoull(field[2], 0, 0);
+		end = strtoull(field[3], 0, 0);
+		if(start >= end || end > unit->sectors)
+			break;
+		sdaddpart(unit, field[1], p->start+start, p->start+end);
+	}
+}
+
+int
+isdos(int t)
+{
+	return t==FAT12 || t==FAT16 || t==FATHUGE || t==FAT32 || t==FAT32X;
+}
+
+int
+isextend(int t)
+{
+	return t==EXTEND || t==EXTHUGE || t==LEXTEND;
+}
+
+/* 
+ * Fetch the first dos and all plan9 partitions out of the MBR partition table.
+ * We return -1 if we did not find a plan9 partition.
+ */
+static int
+mbrpart(SDunit *unit)
+{
+	Dospart *dp;
+	ulong taboffset, start, end;
+	ulong firstxpart, nxtxpart;
+	int havedos, i, nplan9;
+	char name[10];
+
+	taboffset = 0;
+	dp = (Dospart*)&mbrbuf[0x1BE];
+	if(1) {
+		/* get the MBR (allowing for DMDDO) */
+		if(tsdbio(unit, &unit->part[0], mbrbuf, (vlong)taboffset*unit->secsize, 1) < 0)
+			return -1;
+		for(i=0; i<4; i++)
+			if(dp[i].type == DMDDO) {
+				if(trace)
+					print("DMDDO partition found\n");
+				taboffset = 63;
+				if(tsdbio(unit, &unit->part[0], mbrbuf, (vlong)taboffset*unit->secsize, 1) < 0)
+					return -1;
+				i = -1;	/* start over */
+			}
+	}
+
+	/*
+	 * Read the partitions, first from the MBR and then
+	 * from successive extended partition tables.
+	 */
+	nplan9 = 0;
+	havedos = 0;
+	firstxpart = 0;
+	for(;;) {
+		if(tsdbio(unit, &unit->part[0], mbrbuf, (vlong)taboffset*unit->secsize, 1) < 0)
+			return -1;
+		if(trace) {
+			if(firstxpart)
+				print("%s ext %lud ", unit->name, taboffset);
+			else
+				print("%s mbr ", unit->name);
+		}
+		nxtxpart = 0;
+		for(i=0; i<4; i++) {
+			if(trace)
+				print("dp %d...", dp[i].type);
+			start = taboffset+GLONG(dp[i].start);
+			end = start+GLONG(dp[i].len);
+
+			if(dp[i].type == PLAN9) {
+				if(nplan9 == 0)
+					strcpy(name, "plan9");
+				else
+					sprint(name, "plan9.%d", nplan9);
+				sdaddpart(unit, name, start, end);
+				p9part(unit, name);
+				nplan9++;
+			}
+
+			/*
+			 * We used to take the active partition (and then the first
+			 * when none are active).  We have to take the first here,
+			 * so that the partition we call ``dos'' agrees with the
+			 * partition disk/fdisk calls ``dos''. 
+			 */
+			if(havedos==0 && isdos(dp[i].type)){
+				havedos = 1;
+				sdaddpart(unit, "dos", start, end);
+			}
+
+			/* nxtxpart is relative to firstxpart (or 0), not taboffset */
+			if(isextend(dp[i].type)){
+				nxtxpart = start-taboffset+firstxpart;
+				if(trace)
+					print("link %lud...", nxtxpart);
+			}
+		}
+		if(trace)
+			print("\n");
+
+		if(!nxtxpart)
+			break;
+		if(!firstxpart)
+			firstxpart = nxtxpart;
+		taboffset = nxtxpart;
+	}	
+	return nplan9 ? 0 : -1;
+}
+
+/*
+ * To facilitate booting from CDs, we create a partition for
+ * the boot floppy image embedded in a bootable CD.
+ */
+static int
+part9660(SDunit *unit)
+{
+	uchar buf[2048];
+	ulong a, n;
+	uchar *p;
+
+	if(unit->secsize != 2048)
+		return -1;
+
+	if(sdbio(unit, &unit->part[0], buf, 2048, 17*2048) < 0)
+		return -1;
+
+	if(buf[0] || strcmp((char*)buf+1, "CD001\x01EL TORITO SPECIFICATION") != 0)
+		return -1;
+
+	
+	p = buf+0x47;
+	a = p[0] | (p[1]<<8) | (p[2]<<16) | (p[3]<<24);
+
+	if(sdbio(unit, &unit->part[0], buf, 2048, a*2048) < 0)
+		return -1;
+
+	if(memcmp(buf, "\x01\x00\x00\x00", 4) != 0
+	|| memcmp(buf+30, "\x55\xAA", 2) != 0
+	|| buf[0x20] != 0x88)
+		return -1;
+
+	p = buf+0x28;
+	a = p[0] | (p[1]<<8) | (p[2]<<16) | (p[3]<<24);
+
+	switch(buf[0x21]){
+	case 0x01:
+		n = 1200*1024;
+		break;
+	case 0x02:
+		n = 1440*1024;
+		break;
+	case 0x03:
+		n = 2880*1024;
+		break;
+	default:
+		return -1;
+	}
+	n /= 2048;
+
+	print("found partition %s!cdboot; %lud+%lud\n", unit->name, a, n);
+	sdaddpart(unit, "cdboot", a, a+n);
+	return 0;
+}
+
+enum {
+	NEW = 1<<0,
+	OLD = 1<<1
+};
+
+void
+partition(SDunit *unit)
+{
+	int type;
+	char *p;
+
+	if(unit->part == 0)
+		return;
+
+	if(part9660(unit) == 0)
+		return;
+
+	p = getconf("partition");
+	if(p == nil)
+		p = defaultpartition;
+
+	if(p != nil && strncmp(p, "new", 3) == 0)
+		type = NEW;
+	else if(p != nil && strncmp(p, "old", 3) == 0)
+		type = OLD;
+	else
+		type = NEW|OLD;
+
+	if(nbuf < unit->secsize) {
+		free(mbrbuf);
+		free(partbuf);
+		mbrbuf = malloc(unit->secsize);
+		partbuf = malloc(unit->secsize);
+		if(mbrbuf==nil || partbuf==nil) {
+			free(mbrbuf);
+			free(partbuf);
+			partbuf = mbrbuf = nil;
+			nbuf = 0;
+			return;
+		}
+		nbuf = unit->secsize;
+	}
+
+	if((type & NEW) && mbrpart(unit) >= 0){
+		/* nothing to do */;
+	}
+	else if(type & OLD)
+		oldp9part(unit);
+}
--- /dev/null
+++ b/os/boot.original/pc/pbs.s
@@ -1,0 +1,372 @@
+/*
+ * FAT Partition Boot Sector. Loaded at 0x7C00:
+ *	8a pbs.s; 8l -o pbs -l -H3 -T0x7C00 pbs.8
+ * Will load the target at LOADSEG*16+LOADOFF, so the target
+ * should be probably be loaded with LOADOFF added to the
+ * -Taddress.
+ * If LOADSEG is a multiple of 64KB and LOADOFF is 0 then
+ * targets larger than 64KB can be loaded.
+ *
+ * This code uses the traditional INT13 BIOS interface and can
+ * therefore only access the first 8.4GB of the disc.
+ *
+ * It relies on the _volid field in the FAT header containing
+ * the LBA of the root directory.
+ */
+#include "x16.h"
+#include "mem.h"
+
+#define LOADSEG		(0x10000/16)	/* where to load code (64KB) */
+#define LOADOFF		0
+#define DIROFF		0x0200		/* where to read the root directory */
+
+/*
+ * FAT directory entry.
+ */
+#define Dname		0x00
+#define Dext		0x08
+#define Dattr		0x0B
+#define Dtime		0x16
+#define Ddate		0x18
+#define Dstart		0x1A
+#define Dlengthlo	0x1C
+#define Dlengthhi	0x1E
+
+#define Dirsz		0x20
+
+/*
+ * Data is kept on the stack, indexed by rBP.
+ */
+#define Xdap		0x00		/* disc address packet */
+#define Xrootsz		0x10		/* file data area */
+#define Xdrive		0x12		/* boot drive, passed by BIOS or MBR */
+#define Xtotal		0x14		/* sum of allocated data above */
+
+TEXT _magic(SB), $0
+	BYTE $0xEB; BYTE $0x3C;		/* jmp .+ 0x3C  (_start0x3E) */
+	BYTE $0x90			/* nop */
+TEXT _version(SB), $0
+	BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
+	BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00
+TEXT _sectsize(SB), $0
+	BYTE $0x00; BYTE $0x00
+TEXT _clustsize(SB), $0
+	BYTE $0x00
+TEXT _nresrv(SB), $0
+	BYTE $0x00; BYTE $0x00
+TEXT _nfats(SB), $0
+	BYTE $0x00
+TEXT _rootsize(SB), $0
+	BYTE $0x00; BYTE $0x00
+TEXT _volsize(SB), $0
+	BYTE $0x00; BYTE $0x00
+TEXT _mediadesc(SB), $0
+	BYTE $0x00
+TEXT _fatsize(SB), $0
+	BYTE $0x00; BYTE $0x00
+TEXT _trksize(SB), $0
+	BYTE $0x00; BYTE $0x00
+TEXT _nheads(SB), $0
+	BYTE $0x00; BYTE $0x00
+TEXT _nhiddenlo(SB), $0
+	BYTE $0x00; BYTE $0x00
+TEXT _nhiddenhi(SB), $0
+	BYTE $0x00; BYTE $0x00;
+TEXT _bigvolsize(SB), $0
+	BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
+TEXT _driveno(SB), $0
+	BYTE $0x00
+TEXT _reserved0(SB), $0
+	BYTE $0x00
+TEXT _bootsig(SB), $0
+	BYTE $0x00
+TEXT _volid(SB), $0
+	BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
+TEXT _label(SB), $0
+	BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
+	BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00
+	BYTE $0x00; BYTE $0x00; BYTE $0x00
+TEXT _type(SB), $0
+	BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
+	BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
+
+_start0x3E:
+	CLI
+	CLR(rAX)
+	MTSR(rAX, rSS)			/* 0000 -> rSS */
+	MTSR(rAX, rDS)			/* 0000 -> rDS, source segment */
+	MTSR(rAX, rES)
+	LWI(_magic-Xtotal(SB), rSP)
+	MW(rSP, rBP)			/* set the indexed-data pointer */
+
+	SBPB(rDL, Xdrive)		/* save the boot drive */
+
+	/* booting from a CD starts us at 7C0:0.  Move to 0:7C00 */
+	PUSHR(rAX)
+	LWI(_nxt(SB), rAX)
+	PUSHR(rAX)
+	BYTE $0xCB	/* FAR RET */
+
+TEXT _nxt(SB), $0
+	STI
+
+	LWI(confidence(SB), rSI)	/* for that warm, fuzzy feeling */
+	CALL16(BIOSputs(SB))
+
+	CALL16(dreset(SB))
+
+_jmp00:
+	LW(_volid(SB), rAX)		/* Xrootlo */
+	LW(_volid+2(SB), rDX)		/* Xroothi */
+
+	LWI(_magic+DIROFF(SB), rBX)
+	CALL16(BIOSread(SB))		/* read the root directory */
+
+	LWI((512/Dirsz), rBX)
+
+	LWI(_magic+DIROFF(SB), rDI)	/* compare first directory entry */
+
+_cmp00:
+	PUSHR(rDI)			/* save for later if it matches */
+	LWI(bootfile(SB), rSI)
+	LWI(Dattr, rCX)
+	REP
+	CMPSB
+	POPR(rDI)
+	JEQ _jmp02
+
+	DEC(rBX)
+	JEQ _jmp01
+
+	ADDI(Dirsz, rDI)
+	JMP _cmp00
+_jmp01:
+	CALL16(buggery(SB))
+
+_jmp02:
+	CLR(rBX)			/* a handy value */
+	LW(_rootsize(SB), rAX)		/* calculate and save Xrootsz */
+	LWI(Dirsz, rCX)
+	MUL(rCX)
+	LW(_sectsize(SB), rCX)
+	PUSHR(rCX)
+	DEC(rCX)
+	ADD(rCX, rAX)
+	ADC(rBX, rDX)
+	POPR(rCX)			/* _sectsize(SB) */
+	DIV(rCX)
+	PUSHR(rAX)			/* Xrootsz */
+
+	/*
+	 * rDI points to the matching directory entry.
+	 */
+	LXW(Dstart, xDI, rAX)		/* starting sector address */
+	DEC(rAX)			/* that's just the way it is */
+	DEC(rAX)
+	LB(_clustsize(SB), rCL)
+	CLRB(rCH)
+	MUL(rCX)
+	LW(_volid(SB), rCX)		/* Xrootlo */
+	ADD(rCX, rAX)
+	LW(_volid+2(SB), rCX)		/* Xroothi */
+	ADC(rCX, rDX)
+	POPR(rCX)			/* Xrootsz */
+	ADD(rCX, rAX)
+	ADC(rBX, rDX)
+
+	PUSHR(rAX)			/* calculate how many sectors to read */
+	PUSHR(rDX)
+	LXW(Dlengthlo, xDI, rAX)
+	LXW(Dlengthhi, xDI, rDX)
+	LW(_sectsize(SB), rCX)
+	PUSHR(rCX)
+	DEC(rCX)
+	ADD(rCX, rAX)
+	ADC(rBX, rDX)
+	POPR(rCX)			/* _sectsize(SB) */
+	DIV(rCX)
+	MW(rAX, rCX)
+	POPR(rDX)
+	POPR(rAX)
+
+	LWI(LOADSEG, rBX)		/* address to load into (seg+offset) */
+	MTSR(rBX, rES)			/*  seg */
+	LWI(LOADOFF, rBX)		/*  offset */
+
+_readboot:
+	CALL16(BIOSread(SB))		/* read the sector */
+
+	LW(_sectsize(SB), rDI)		/* bump addresses/counts */
+	ADD(rDI, rBX)
+	JCC _incsecno
+
+	MFSR(rES, rDI)			/* next 64KB segment */
+	ADDI(0x1000, rDI)
+	MTSR(rDI, rES)
+
+_incsecno:
+	CLR(rDI)
+	INC(rAX)
+	ADC(rDI, rDX)
+	LOOP _readboot
+
+	LWI(LOADSEG, rDI)		/* set rDS for loaded code */
+	MTSR(rDI, rDS)
+	FARJUMP16(LOADSEG, LOADOFF)	/* no deposit, no return */
+
+TEXT buggery(SB), $0
+	LWI(error(SB), rSI)
+	CALL16(BIOSputs(SB))
+
+_wait:
+	CLR(rAX)			/* wait for almost any key */
+	BIOSCALL(0x16)
+
+_reset:
+	CLR(rBX)			/* set ES segment for BIOS area */
+	MTSR(rBX, rES)
+
+	LWI(0x0472, rBX)		/* warm-start code address */
+	LWI(0x1234, rAX)		/* warm-start code */
+	POKEW				/* MOVW	AX, ES:[BX] */
+
+	FARJUMP16(0xFFFF, 0x0000)	/* reset */
+
+/*
+ * Read a sector from a disc. On entry:
+ *   rDX:rAX	sector number
+ *   rES:rBX	buffer address
+ * For BIOSCALL(0x13):
+ *   rAH	0x02
+ *   rAL	number of sectors to read (1)
+ *   rCH	low 8 bits of cylinder
+ *   rCL	high 2 bits of cylinder (7-6), sector (5-0)
+ *   rDH	head
+ *   rDL	drive
+ *   rES:rBX	buffer address
+ */
+TEXT BIOSread(SB), $0
+	LWI(5, rDI)			/* retry count (ATAPI ZIPs suck) */
+_retry:
+	PUSHA				/* may be trashed by BIOSCALL */
+	PUSHR(rBX)
+
+	LW(_trksize(SB), rBX)
+	LW(_nheads(SB), rDI)
+	IMUL(rDI, rBX)
+	OR(rBX, rBX)
+	JZ _ioerror
+
+_okay:
+	DIV(rBX)			/* cylinder -> rAX, track,sector -> rDX */
+
+	MW(rAX, rCX)			/* save cylinder */
+	ROLI(0x08, rCX)			/* swap rC[HL] */
+	SHLBI(0x06, rCL)		/* move high bits up */
+
+	MW(rDX, rAX)
+	CLR(rDX)
+	LW(_trksize(SB), rBX)
+
+	DIV(rBX)			/* head -> rAX, sector -> rDX */
+
+	INC(rDX)			/* sector numbers are 1-based */
+	ANDI(0x003F, rDX)		/* should not be necessary */
+	OR(rDX, rCX)
+
+	MW(rAX, rDX)
+	SHLI(0x08, rDX)			/* form head */
+	LBPB(Xdrive, rDL)		/* form drive */
+
+	POPR(rBX)
+	LWI(0x0201, rAX)		/* form command and sectors */
+	BIOSCALL(0x13)			/* CF set on failure */
+	JCC _BIOSreadret
+
+	POPA
+	DEC(rDI)			/* too many retries? */
+	JEQ _ioerror
+
+	CALL16(dreset(SB))
+	JMP _retry
+
+_ioerror:
+	LWI(ioerror(SB), rSI)
+	CALL16(BIOSputs(SB))
+	JMP _wait
+
+_BIOSreadret:
+	POPA
+	RET
+
+TEXT dreset(SB), $0
+	PUSHA
+	CLR(rAX)			/* rAH == 0 == reset disc system */
+	LBPB(Xdrive, rDL)
+	BIOSCALL(0x13)
+	ORB(rAH, rAH)			/* status (0 == success) */
+	POPA
+	JNE _ioerror
+	RET
+
+/*
+ * Output a string to the display.
+ * String argument is in rSI.
+ */
+TEXT BIOSputs(SB), $0
+	PUSHA
+	CLR(rBX)
+_BIOSputs:
+	LODSB
+	ORB(rAL, rAL)
+	JEQ _BIOSputsret
+
+	LBI(0x0E, rAH)
+	BIOSCALL(0x10)
+	JMP _BIOSputs
+
+_BIOSputsret:
+	POPA
+	RET
+
+/* "Bad format or I/O error\r\nPress almost any key to reboot..."*/
+TEXT error(SB), $0
+	BYTE $'B'; BYTE $'a'; BYTE $'d'; BYTE $' ';
+	BYTE $'f'; BYTE $'o'; BYTE $'r'; BYTE $'m';
+	BYTE $'a'; BYTE $'t'; BYTE $' '; BYTE $'o';
+	BYTE $'r'; BYTE $' ';
+/* "I/O error\r\nPress almost any key to reboot..." */
+TEXT ioerror(SB), $0
+	BYTE $'I'; BYTE $'/'; BYTE $'O'; BYTE $' ';
+	BYTE $'e'; BYTE $'r'; BYTE $'r'; BYTE $'o';
+	BYTE $'r'; BYTE $'\r';BYTE $'\n';
+	BYTE $'P'; BYTE $'r'; BYTE $'e'; BYTE $'s';
+	BYTE $'s'; BYTE $' '; BYTE $'a'; BYTE $' ';
+	BYTE $'k'; BYTE $'e'; BYTE $'y';
+	BYTE $' '; BYTE $'t'; BYTE $'o'; BYTE $' ';
+	BYTE $'r'; BYTE $'e'; BYTE $'b'; BYTE $'o';
+	BYTE $'o'; BYTE $'t';
+	BYTE $'.'; BYTE $'.'; BYTE $'.';
+	BYTE $'\z';
+
+#ifdef USEBCOM
+/* "B       COM" */
+TEXT bootfile(SB), $0
+	BYTE $'B'; BYTE $' '; BYTE $' '; BYTE $' ';
+	BYTE $' '; BYTE $' '; BYTE $' '; BYTE $' ';
+	BYTE $'C'; BYTE $'O'; BYTE $'M';
+	BYTE $'\z';
+#else
+/* "9LOAD      " */
+TEXT bootfile(SB), $0
+	BYTE $'9'; BYTE $'L'; BYTE $'O'; BYTE $'A';
+	BYTE $'D'; BYTE $' '; BYTE $' '; BYTE $' ';
+	BYTE $' '; BYTE $' '; BYTE $' ';
+	BYTE $'\z';
+#endif /* USEBCOM */
+
+/* "PBS..." */
+TEXT confidence(SB), $0
+	BYTE $'P'; BYTE $'B'; BYTE $'S'; BYTE $'1'; 
+	BYTE $'.'; BYTE $'.'; BYTE $'.';
+	BYTE $'\z';
binary files /dev/null b/os/boot.original/pc/pbsdisk differ
--- /dev/null
+++ b/os/boot.original/pc/pbsdisk.s
@@ -1,0 +1,344 @@
+/*
+ * Debugging boot sector.  Reads the first directory
+ * sector from disk and displays it.
+ *
+ * It relies on the _volid field in the FAT header containing
+ * the LBA of the root directory.
+ */
+#include "x16.h"
+
+#define DIROFF		0x00200		/* where to read the root directory (offset) */
+#define LOADSEG		(0x10000/16)	/* where to load code (64KB) */
+#define LOADOFF		0
+
+/*
+ * FAT directory entry.
+ */
+#define Dname		0x00
+#define Dext		0x08
+#define Dattr		0x0B
+#define Dtime		0x16
+#define Ddate		0x18
+#define Dstart		0x1A
+#define Dlengthlo	0x1C
+#define Dlengthhi	0x1E
+
+#define Dirsz		0x20
+
+/*
+ * We keep data on the stack, indexed by rBP.
+ */
+#define Xdrive		0x00		/* boot drive, passed by BIOS in rDL */
+#define Xrootlo		0x02		/* offset of root directory */
+#define Xroothi		0x04
+#define Xrootsz		0x06		/* file data area */
+#define Xtotal		0x08		/* sum of allocated data above */
+#define Xdap		0x00		/* disc address packet */
+
+TEXT _magic(SB), $0
+	BYTE $0xEB; BYTE $0x3C;		/* jmp .+ 0x3C  (_start0x3E) */
+	BYTE $0x90			/* nop */
+TEXT _version(SB), $0
+	BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
+	BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00
+TEXT _sectsize(SB), $0
+	BYTE $0x00; BYTE $0x00
+TEXT _clustsize(SB), $0
+	BYTE $0x00
+TEXT _nresrv(SB), $0
+	BYTE $0x00; BYTE $0x00
+TEXT _nfats(SB), $0
+	BYTE $0x00
+TEXT _rootsize(SB), $0
+	BYTE $0x00; BYTE $0x00
+TEXT _volsize(SB), $0
+	BYTE $0x00; BYTE $0x00
+TEXT _mediadesc(SB), $0
+	BYTE $0x00
+TEXT _fatsize(SB), $0
+	BYTE $0x00; BYTE $0x00
+TEXT _trksize(SB), $0
+	BYTE $0x00; BYTE $0x00
+TEXT _nheads(SB), $0
+	BYTE $0x00; BYTE $0x00
+TEXT _nhiddenlo(SB), $0
+	BYTE $0x00; BYTE $0x00
+TEXT _nhiddenhi(SB), $0
+	BYTE $0x00; BYTE $0x00;
+TEXT _bigvolsize(SB), $0
+	BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
+TEXT _driveno(SB), $0
+	BYTE $0x00
+TEXT _reserved0(SB), $0
+	BYTE $0x00
+TEXT _bootsig(SB), $0
+	BYTE $0x00
+TEXT _volid(SB), $0
+	BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
+TEXT _label(SB), $0
+	BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
+	BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00
+	BYTE $0x00; BYTE $0x00; BYTE $0x00
+TEXT _type(SB), $0
+	BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
+	BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
+
+_start0x3E:
+	CLI
+	CLR(rAX)
+	MTSR(rAX, rSS)			/* 0000 -> rSS */
+	MTSR(rAX, rDS)			/* 0000 -> rDS, source segment */
+	MTSR(rAX, rES)
+	LWI(_magic-Xtotal(SB), rSP)
+	MW(rSP, rBP)			/* set the indexed-data pointer */
+	SBPB(rDL, Xdrive)		/* save the boot drive */
+
+	/* VMware starts us at 7C0:0.  Move to 0:7C00 */
+	PUSHR(rAX)
+	LWI(_nxt(SB), rAX)
+	PUSHR(rAX)
+	BYTE $0xCB	/* FAR RET */
+
+TEXT _nxt(SB), $0
+	STI
+	LWI(confidence(SB), rSI)	/* for that warm, fuzzy feeling */
+	CALL16(BIOSputs(SB))
+
+	CALL16(dreset(SB))
+
+_jmp00:
+	LW(_volid(SB), rAX)		/* Xrootlo */
+	LW(_volid+2(SB), rDX)		/* Xroothi */
+
+	LWI(_magic+DIROFF(SB), rBX)
+	CALL16(BIOSread(SB))		/* read the root directory */
+
+	CALL16(printnl(SB))
+	LWI(_magic+DIROFF(SB), rBX)
+	LWI((512/2), rCX)
+	CALL16(printbuf(SB))
+
+xloop:
+	JMP xloop
+
+
+TEXT buggery(SB), $0
+	LWI(error(SB), rSI)
+	CALL16(BIOSputs(SB))
+
+TEXT quietbuggery(SB), $0
+xbuggery:
+	JMP xbuggery
+
+/*
+ * Read a sector from a disc. On entry:
+ *   rDX:rAX	sector number
+ *   rES:rBX	buffer address
+ * For BIOSCALL(0x13):
+ *   rAH	0x02
+ *   rAL	number of sectors to read (1)
+ *   rCH	low 8 bits of cylinder
+ *   rCL	high 2 bits of cylinder (7-6), sector (5-0)
+ *   rDH	head
+ *   rDL	drive
+ *   rES:rBX	buffer address
+ */
+TEXT BIOSread(SB), $0
+	LWI(5, rDI)			/* retry count (ATAPI ZIPs suck) */
+_retry:
+	PUSHA				/* may be trashed by BIOSCALL */
+	PUSHR(rBX)
+
+	LW(_trksize(SB), rBX)
+	LW(_nheads(SB), rDI)
+	IMUL(rDI, rBX)
+	OR(rBX, rBX)
+	JZ _ioerror
+
+_okay:
+	DIV(rBX)			/* cylinder -> rAX, track,sector -> rDX */
+
+	MW(rAX, rCX)			/* save cylinder */
+	ROLI(0x08, rCX)			/* swap rC[HL] */
+	SHLBI(0x06, rCL)		/* move high bits up */
+
+	MW(rDX, rAX)
+	CLR(rDX)
+	LW(_trksize(SB), rBX)
+
+	DIV(rBX)			/* head -> rAX, sector -> rDX */
+
+	INC(rDX)			/* sector numbers are 1-based */
+	ANDI(0x003F, rDX)		/* should not be necessary */
+	OR(rDX, rCX)
+
+	MW(rAX, rDX)
+	SHLI(0x08, rDX)			/* form head */
+	LBPB(Xdrive, rDL)		/* form drive */
+
+	POPR(rBX)
+	LWI(0x0201, rAX)		/* form command and sectors */
+	BIOSCALL(0x13)			/* CF set on failure */
+	JCC _BIOSreadret
+
+	POPA
+	DEC(rDI)			/* too many retries? */
+	JEQ _ioerror
+
+	CALL16(dreset(SB))
+	JMP _retry
+
+_ioerror:
+	LWI(ioerror(SB), rSI)
+	CALL16(BIOSputs(SB))
+	JMP xbuggery
+
+_BIOSreadret:
+	POPA
+	RET
+
+TEXT dreset(SB), $0
+	PUSHA
+	CLR(rAX)			/* rAH == 0 == reset disc system */
+	LBPB(Xdrive, rDL)
+	BIOSCALL(0x13)
+	ORB(rAH, rAH)			/* status (0 == success) */
+	POPA
+	JNE _ioerror
+	RET
+
+TEXT printsharp(SB), $0
+	LWI(sharp(SB), rSI)
+_doprint:
+	CALL16(BIOSputs(SB))
+	RET
+
+TEXT printspace(SB), $0
+	LWI(space(SB), rSI)
+	JMP _doprint
+
+TEXT printnl(SB), $0
+	LWI(nl(SB), rSI)
+	JMP _doprint
+
+/*
+ * Output a string to the display.
+ * String argument is in rSI.
+ */
+TEXT BIOSputs(SB), $0
+	PUSHA
+	CLR(rBX)
+_BIOSputs:
+	LODSB
+	ORB(rAL, rAL)
+	JEQ _BIOSputsret
+
+	LBI(0x0E, rAH)
+	BIOSCALL(0x10)
+	JMP _BIOSputs
+
+_BIOSputsret:
+	POPA
+	RET
+
+/*
+ * Output a register to the display.
+ */
+TEXT printAX(SB), $0
+	PUSHW(rAX)
+	PUSHW(rBX)
+	PUSHW(rCX)
+	PUSHW(rDI)
+
+	LWI(4, rCX)
+	LWI(numbuf+4(SB), rSI)
+
+_nextchar:
+	DEC(rSI)
+	MW(rAX, rBX)
+	ANDI(0x000F, rBX)
+	ADDI(0x30, rBX)	/* 0x30 = '0' */
+	CMPI(0x39, rBX)	/* 0x39 = '9' */
+	JLE _dowrite
+	ADDI(0x07, rBX)	/* 0x07 = 'A'-(1+'9')*/
+
+_dowrite:
+	SXB(rBL, 0, xSI)
+	SHRI(4, rAX)
+
+	DEC(rCX)
+	JNE _nextchar
+
+	LWI(numbuf(SB), rSI)
+	CALL16(BIOSputs(SB))
+
+	POPW(rDI)
+	POPW(rCX)
+	POPW(rBX)
+	POPW(rAX)
+
+	CALL16(printspace(SB))
+	RET
+
+TEXT printDXAX(SB), $0
+	PUSHW(rAX)
+	MW(rDX, rAX)
+	CALL16(printAX(SB))
+	POPW(rAX)
+	CALL16(printAX(SB))
+	RET
+
+TEXT printBX(SB), $0
+	PUSHW(rAX)
+	MW(rBX, rAX)
+	CALL16(printAX(SB))
+	POPW(rAX)
+	RET
+
+/*
+ * Output some number of words to the display
+ * rDS:rDI - buffer
+ * rCX: number of words
+ */
+TEXT printbuf(SB), $0
+	PUSHW(rAX)
+	PUSHW(rBX)
+	PUSHW(rCX)
+
+_nextword:
+	LXW(0, xBX, rAX)
+	CALL16(printAX(SB))
+	INC(rBX)
+	INC(rBX)
+	DEC(rCX)
+	JNE _nextword
+
+	POPW(rCX)
+	POPW(rBX)
+	POPW(rAX)
+	RET
+
+TEXT error(SB), $0
+	BYTE $'E'; 
+
+TEXT ioerror(SB), $0
+	BYTE $'I'; 
+
+TEXT nl(SB), $0
+	BYTE $'\r';
+	BYTE $'\n';
+	BYTE $'\z';
+
+TEXT numbuf(SB), $0
+	BYTE $'X'; BYTE $'X'; BYTE $'X'; BYTE $'X';
+	BYTE $'\z';
+
+TEXT space(SB), $0
+	BYTE $' ';
+	BYTE $'\z';
+
+TEXT sharp(SB), $0
+	BYTE $'#'; BYTE $'\z';
+
+TEXT confidence(SB), $0
+	BYTE $'P'; BYTE $'\z'
binary files /dev/null b/os/boot.original/pc/pbsdisklba differ
--- /dev/null
+++ b/os/boot.original/pc/pbsdisklba.s
@@ -1,0 +1,327 @@
+/*
+ * Debugging boot sector.  Reads the first directory
+ * sector from disk and displays it.
+ *
+ * It relies on the _volid field in the FAT header containing
+ * the LBA of the root directory.
+ */
+#include "x16.h"
+
+#define DIROFF		0x00200		/* where to read the root directory (offset) */
+#define LOADSEG		(0x10000/16)	/* where to load code (64KB) */
+#define LOADOFF		0
+
+/*
+ * FAT directory entry.
+ */
+#define Dname		0x00
+#define Dext		0x08
+#define Dattr		0x0B
+#define Dtime		0x16
+#define Ddate		0x18
+#define Dstart		0x1A
+#define Dlengthlo	0x1C
+#define Dlengthhi	0x1E
+
+#define Dirsz		0x20
+
+/*
+ * We keep data on the stack, indexed by rBP.
+ */
+#define Xdrive		0x00		/* boot drive, passed by BIOS in rDL */
+#define Xrootlo		0x02		/* offset of root directory */
+#define Xroothi		0x04
+#define Xrootsz		0x06		/* file data area */
+#define Xtotal		0x08		/* sum of allocated data above */
+#define Xdap		0x00		/* disc address packet */
+
+TEXT _magic(SB), $0
+	BYTE $0xEB; BYTE $0x3C;		/* jmp .+ 0x3C  (_start0x3E) */
+	BYTE $0x90			/* nop */
+TEXT _version(SB), $0
+	BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
+	BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00
+TEXT _sectsize(SB), $0
+	BYTE $0x00; BYTE $0x00
+TEXT _clustsize(SB), $0
+	BYTE $0x00
+TEXT _nresrv(SB), $0
+	BYTE $0x00; BYTE $0x00
+TEXT _nfats(SB), $0
+	BYTE $0x00
+TEXT _rootsize(SB), $0
+	BYTE $0x00; BYTE $0x00
+TEXT _volsize(SB), $0
+	BYTE $0x00; BYTE $0x00
+TEXT _mediadesc(SB), $0
+	BYTE $0x00
+TEXT _fatsize(SB), $0
+	BYTE $0x00; BYTE $0x00
+TEXT _trksize(SB), $0
+	BYTE $0x00; BYTE $0x00
+TEXT _nheads(SB), $0
+	BYTE $0x00; BYTE $0x00
+TEXT _nhiddenlo(SB), $0
+	BYTE $0x00; BYTE $0x00
+TEXT _nhiddenhi(SB), $0
+	BYTE $0x00; BYTE $0x00;
+TEXT _bigvolsize(SB), $0
+	BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
+TEXT _driveno(SB), $0
+	BYTE $0x00
+TEXT _reserved0(SB), $0
+	BYTE $0x00
+TEXT _bootsig(SB), $0
+	BYTE $0x00
+TEXT _volid(SB), $0
+	BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
+TEXT _label(SB), $0
+	BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
+	BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00
+	BYTE $0x00; BYTE $0x00; BYTE $0x00
+TEXT _type(SB), $0
+	BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
+	BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
+
+_start0x3E:
+	CLI
+	CLR(rAX)
+	MTSR(rAX, rSS)			/* 0000 -> rSS */
+	MTSR(rAX, rDS)			/* 0000 -> rDS, source segment */
+	MTSR(rAX, rES)
+	LWI(_magic-Xtotal(SB), rSP)
+	MW(rSP, rBP)			/* set the indexed-data pointer */
+
+	SBPB(rDL, Xdrive)		/* save the boot drive */
+
+	STI
+
+	LWI(confidence(SB), rSI)	/* for that warm, fuzzy feeling */
+	CALL(BIOSputs(SB))
+
+	LBI(0x41, rAH)			/* check extensions present */
+	LWI(0x55AA, rBX)
+	LXB(Xdrive, xBP, rDL)		/* drive */
+	SYSCALL(0x13)			/* CF set on failure */
+	JCS _jmp01
+	CMPI(0xAA55, rBX)
+	JNE _jmp01
+	ANDI(0x0001, rCX)
+	JEQ _jmp01
+
+					/* rCX contains 0x0001 */
+	SBPWI(0x0010, Xdap+0)		/* reserved + packet size */
+	SBPW(rCX, Xdap+2)		/* reserved + # of blocks to transfer */
+
+	DEC(rCX)
+	SBPW(rCX, Xdap+12)
+	SBPW(rCX, Xdap+14)
+
+/* BIOSread will do this 	CALL(dreset(SB)) */
+
+_jmp00:
+	LW(_volid(SB), rAX)		/* Xrootlo */
+	LW(_volid+2(SB), rDX)		/* Xroothi */
+
+	LWI(_magic+DIROFF(SB), rBX)
+	CALL(BIOSread(SB))		/* read the root directory */
+
+	CALL(printnl(SB))
+	LWI(_magic+DIROFF(SB), rBX)
+	LWI((512/2), rCX)
+	CALL(printbuf(SB))
+
+xloop:
+	JMP xloop
+
+
+_jmp01:
+
+TEXT buggery(SB), $0
+	LWI(error(SB), rSI)
+	CALL(BIOSputs(SB))
+
+xbuggery:
+	JMP xbuggery
+
+/*
+ * Read a sector from a disc. On entry:
+ *   rDX:rAX	sector number
+ *   rES:rBX	buffer address
+ */
+TEXT BIOSread(SB), $0
+	LWI(5, rDI)			/* retry count (ATAPI ZIPs suck) */
+_retry:
+	PUSHA				/* may be trashed by SYSCALL */
+
+	SBPW(rBX, Xdap+4)		/* transfer buffer :offset */
+	MFSR(rES, rDI)			/* transfer buffer seg: */
+	SBPW(rDI, Xdap+6)
+	SBPW(rAX, Xdap+8)		/* LBA (64-bits) */
+	SBPW(rDX, Xdap+10)
+
+	MW(rBP, rSI)			/* disk address packet */
+	LBI(0x42, rAH)			/* extended read */
+	LBPB(Xdrive, rDL)		/* form drive */
+	SYSCALL(0x13)			/* CF set on failure */
+	JCC _BIOSreadret
+
+	POPA
+	DEC(rDI)			/* too many retries? */
+	JEQ _ioerror
+
+	CALL(dreset(SB))
+	JMP _retry
+
+_ioerror:
+	LWI(ioerror(SB), rSI)
+	CALL(BIOSputs(SB))
+	JMP xbuggery
+
+_BIOSreadret:
+	POPA
+	RET
+
+TEXT dreset(SB), $0
+	PUSHA
+	CLR(rAX)			/* rAH == 0 == reset disc system */
+	LBPB(Xdrive, rDL)
+	SYSCALL(0x13)
+	ORB(rAH, rAH)			/* status (0 == success) */
+	POPA
+	JNE _ioerror
+	RET
+
+
+TEXT printsharp(SB), $0
+	LWI(sharp(SB), rSI)
+_doprint:
+	CALL(BIOSputs(SB))
+	RET
+
+TEXT printspace(SB), $0
+	LWI(space(SB), rSI)
+	JMP _doprint
+
+TEXT printnl(SB), $0
+	LWI(nl(SB), rSI)
+	JMP _doprint
+
+/*
+ * Output a string to the display.
+ * String argument is in rSI.
+ */
+TEXT BIOSputs(SB), $0
+	PUSHA
+	CLR(rBX)
+_BIOSputs:
+	LODSB
+	ORB(rAL, rAL)
+	JEQ _BIOSputsret
+
+	LBI(0x0E, rAH)
+	SYSCALL(0x10)
+	JMP _BIOSputs
+
+_BIOSputsret:
+	POPA
+	RET
+
+/*
+ * Output a register to the display.
+ */
+TEXT printAX(SB), $0
+	PUSHW(rAX)
+	PUSHW(rBX)
+	PUSHW(rCX)
+	PUSHW(rDI)
+
+	LWI(4, rCX)
+	LWI(numbuf+4(SB), rSI)
+
+_nextchar:
+	DEC(rSI)
+	MW(rAX, rBX)
+	ANDI(0x000F, rBX)
+	ADDI(0x30, rBX)	/* 0x30 = '0' */
+	CMPI(0x39, rBX)	/* 0x39 = '9' */
+	JLE _dowrite
+	ADDI(0x07, rBX)	/* 0x07 = 'A'-(1+'9')*/
+
+_dowrite:
+	SXB(rBL, 0, xSI)
+	SHRI(4, rAX)
+
+	DEC(rCX)
+	JNE _nextchar
+
+	LWI(numbuf(SB), rSI)
+	CALL(BIOSputs(SB))
+
+	POPW(rDI)
+	POPW(rCX)
+	POPW(rBX)
+	POPW(rAX)
+
+	CALL(printspace(SB))
+	RET
+
+TEXT printDXAX(SB), $0
+	PUSHW(rAX)
+	MW(rDX, rAX)
+	CALL(printAX(SB))
+	POPW(rAX)
+	CALL(printAX(SB))
+	RET
+
+TEXT printBX(SB), $0
+	PUSHW(rAX)
+	MW(rBX, rAX)
+	CALL(printAX(SB))
+	POPW(rAX)
+	RET
+
+/*
+ * Output some number of words to the display
+ * rDS:rDI - buffer
+ * rCX: number of words
+ */
+TEXT printbuf(SB), $0
+	PUSHW(rAX)
+	PUSHW(rBX)
+	PUSHW(rCX)
+
+_nextword:
+	LXW(0, xBX, rAX)
+	CALL(printAX(SB))
+	INC(rBX)
+	INC(rBX)
+	DEC(rCX)
+	JNE _nextword
+
+	POPW(rCX)
+	POPW(rBX)
+	POPW(rAX)
+	RET
+
+TEXT error(SB), $0
+	BYTE $'E'; 
+
+TEXT ioerror(SB), $0
+	BYTE $'I'; 
+
+TEXT nl(SB), $0
+	BYTE $'\r';
+	BYTE $'\n';
+	BYTE $'\z';
+
+TEXT numbuf(SB), $0
+	BYTE $'X'; BYTE $'X'; BYTE $'X'; BYTE $'X';
+	BYTE $'\z';
+
+TEXT space(SB), $0
+	BYTE $' ';
+	BYTE $'\z';
+
+TEXT sharp(SB), $0
+	BYTE $'#'; BYTE $'\z';
--- /dev/null
+++ b/os/boot.original/pc/pbslba.s
@@ -1,0 +1,363 @@
+/*
+ * FAT Partition Boot Sector. Loaded at 0x7C00:
+ *	8a pbslba.s; 8l -o pbslba -l -H3 -T0x7C00 pbslba.8
+ * Will load the target at LOADSEG*16+LOADOFF, so the target
+ * should be probably be loaded with LOADOFF added to the
+ * -Taddress.
+ * If LOADSEG is a multiple of 64KB and LOADOFF is 0 then
+ * targets larger than 64KB can be loaded.
+ *
+ * This code is uses Enhanced BIOS Services for Disc Drives and
+ * can be used with discs up to 137GB in capacity.
+ *
+ * It relies on the _volid field in the FAT header containing
+ * the LBA of the root directory.
+ */
+#include "x16.h"
+#include "mem.h"
+
+#define LOADSEG		(0x10000/16)	/* where to load code (64KB) */
+#define LOADOFF		0
+#define DIROFF		0x0200		/* where to read the root directory */
+
+/*
+ * FAT directory entry.
+ */
+#define Dname		0x00
+#define Dnamesz	0x0B
+#define Dext		0x08
+#define Dattr		0x0B
+#define Dtime		0x16
+#define Ddate		0x18
+#define Dstart		0x1A
+#define Dlengthlo	0x1C
+#define Dlengthhi	0x1E
+
+#define Dirsz		0x20
+
+/*
+ * Data is kept on the stack, indexed by rBP.
+ */
+#define Xdap		0x00		/* disc address packet */
+#define Xrootsz		0x10		/* file data area */
+#define Xdrive		0x12		/* boot drive, passed by BIOS or MBR */
+#define Xtotal		0x14		/* sum of allocated data above */
+
+TEXT _magic(SB), $0
+	BYTE $0xEB; BYTE $0x3C;		/* jmp .+ 0x3C  (_start0x3E) */
+	BYTE $0x90			/* nop */
+TEXT _version(SB), $0
+	BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
+	BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00
+TEXT _sectsize(SB), $0
+	BYTE $0x00; BYTE $0x00
+TEXT _clustsize(SB), $0
+	BYTE $0x00
+TEXT _nresrv(SB), $0
+	BYTE $0x00; BYTE $0x00
+TEXT _nfats(SB), $0
+	BYTE $0x00
+TEXT _rootsize(SB), $0
+	BYTE $0x00; BYTE $0x00
+TEXT _volsize(SB), $0
+	BYTE $0x00; BYTE $0x00
+TEXT _mediadesc(SB), $0
+	BYTE $0x00
+TEXT _fatsize(SB), $0
+	BYTE $0x00; BYTE $0x00
+TEXT _trksize(SB), $0
+	BYTE $0x00; BYTE $0x00
+TEXT _nheads(SB), $0
+	BYTE $0x00; BYTE $0x00
+TEXT _nhiddenlo(SB), $0
+	BYTE $0x00; BYTE $0x00
+TEXT _nhiddenhi(SB), $0
+	BYTE $0x00; BYTE $0x00;
+TEXT _bigvolsize(SB), $0
+	BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
+TEXT _driveno(SB), $0
+	BYTE $0x00
+TEXT _reserved0(SB), $0
+	BYTE $0x00
+TEXT _bootsig(SB), $0
+	BYTE $0x00
+TEXT _volid(SB), $0
+	BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
+TEXT _label(SB), $0
+	BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
+	BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00
+	BYTE $0x00; BYTE $0x00; BYTE $0x00
+TEXT _type(SB), $0
+	BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
+	BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
+
+_start0x3E:
+	CLI
+	CLR(rAX)
+	MTSR(rAX, rSS)			/* 0000 -> rSS */
+	MTSR(rAX, rDS)			/* 0000 -> rDS, source segment */
+	MTSR(rAX, rES)
+	LWI(_magic-Xtotal(SB), rSP)
+	MW(rSP, rBP)			/* set the indexed-data pointer */
+
+	SBPB(rDL, Xdrive)		/* save the boot drive */
+
+	/* booting from a CD starts us at 7C0:0.  Move to 0:7C00 */
+	PUSHR(rAX)
+	LWI(_nxt(SB), rAX)
+	PUSHR(rAX)
+	BYTE $0xCB	/* FAR RET */
+
+TEXT _nxt(SB), $0
+	STI
+
+	LWI(confidence(SB), rSI)	/* for that warm, fuzzy feeling */
+	CALL16(BIOSputs(SB))
+
+	LBI(0x41, rAH)			/* check extensions present */
+	LWI(0x55AA, rBX)
+	LXB(Xdrive, xBP, rDL)		/* drive */
+	BIOSCALL(0x13)			/* CF set on failure */
+	JCS _jmp01
+	CMPI(0xAA55, rBX)
+	JNE _jmp01
+	ANDI(0x0001, rCX)
+	JEQ _jmp01
+
+					/* rCX contains 0x0001 */
+	SBPWI(0x0010, Xdap+0)		/* reserved + packet size */
+	SBPW(rCX, Xdap+2)		/* reserved + # of blocks to transfer */
+
+	DEC(rCX)
+	SBPW(rCX, Xdap+12)
+	SBPW(rCX, Xdap+14)
+
+	CALL16(dreset(SB))
+
+_jmp00:
+	LW(_volid(SB), rAX)		/* Xrootlo */
+	LW(_volid+2(SB), rDX)		/* Xroothi */
+
+	LWI(_magic+DIROFF(SB), rBX)
+	CALL16(BIOSread(SB))		/* read the root directory */
+
+	LWI((512/Dirsz), rBX)
+
+	LWI(_magic+DIROFF(SB), rDI)	/* compare first directory entry */
+
+_cmp00:
+	PUSHR(rDI)			/* save for later if it matches */
+	LWI(bootfile(SB), rSI)
+	LWI(Dnamesz, rCX)
+	REP
+	CMPSB
+	POPR(rDI)
+	JEQ _jmp02
+
+	DEC(rBX)
+	JEQ _jmp01
+
+	ADDI(Dirsz, rDI)
+	JMP _cmp00
+_jmp01:
+	CALL16(buggery(SB))
+
+_jmp02:
+	CLR(rBX)			/* a handy value */
+	LW(_rootsize(SB), rAX)		/* calculate and save Xrootsz */
+	LWI(Dirsz, rCX)
+	MUL(rCX)
+	LW(_sectsize(SB), rCX)
+	PUSHR(rCX)
+	DEC(rCX)
+	ADD(rCX, rAX)
+	ADC(rBX, rDX)
+	POPR(rCX)			/* _sectsize(SB) */
+	DIV(rCX)
+	PUSHR(rAX)			/* Xrootsz */
+
+	/*
+	 * rDI points to the matching directory entry.
+	 */
+	LXW(Dstart, xDI, rAX)		/* starting sector address */
+	DEC(rAX)			/* that's just the way it is */
+	DEC(rAX)
+	LB(_clustsize(SB), rCL)
+	CLRB(rCH)
+	MUL(rCX)
+	LW(_volid(SB), rCX)		/* Xrootlo */
+	ADD(rCX, rAX)
+	LW(_volid+2(SB), rCX)		/* Xroothi */
+	ADC(rCX, rDX)
+	POPR(rCX)			/* Xrootsz */
+	ADD(rCX, rAX)
+	ADC(rBX, rDX)
+
+	PUSHR(rAX)			/* calculate how many sectors to read */
+	PUSHR(rDX)
+	LXW(Dlengthlo, xDI, rAX)
+	LXW(Dlengthhi, xDI, rDX)
+	LW(_sectsize(SB), rCX)
+	PUSHR(rCX)
+	DEC(rCX)
+	ADD(rCX, rAX)
+	ADC(rBX, rDX)
+	POPR(rCX)			/* _sectsize(SB) */
+	DIV(rCX)
+	MW(rAX, rCX)
+	POPR(rDX)
+	POPR(rAX)
+
+	LWI(LOADSEG, rBX)		/* address to load into (seg+offset) */
+	MTSR(rBX, rES)			/*  seg */
+	LWI(LOADOFF, rBX)		/*  offset */
+
+_readboot:
+	CALL16(BIOSread(SB))		/* read the sector */
+
+	LW(_sectsize(SB), rDI)		/* bump addresses/counts */
+	ADD(rDI, rBX)
+	JCC _incsecno
+
+	MFSR(rES, rDI)			/* next 64KB segment */
+	ADDI(0x1000, rDI)
+	MTSR(rDI, rES)
+
+_incsecno:
+	CLR(rDI)
+	INC(rAX)
+	ADC(rDI, rDX)
+	LOOP _readboot
+
+	LWI(LOADSEG, rDI)		/* set rDS for loaded code */
+	MTSR(rDI, rDS)
+	FARJUMP16(LOADSEG, LOADOFF)	/* no deposit, no return */
+
+TEXT buggery(SB), $0
+	LWI(error(SB), rSI)
+	CALL16(BIOSputs(SB))
+
+_wait:
+	CLR(rAX)			/* wait for almost any key */
+	BIOSCALL(0x16)
+
+_reset:
+	CLR(rBX)			/* set ES segment for BIOS area */
+	MTSR(rBX, rES)
+
+	LWI(0x0472, rBX)		/* warm-start code address */
+	LWI(0x1234, rAX)		/* warm-start code */
+	POKEW				/* MOVW	AX, ES:[BX] */
+
+	FARJUMP16(0xFFFF, 0x0000)	/* reset */
+
+
+/*
+ * Read a sector from a disc. On entry:
+ *   rDX:rAX	sector number
+ *   rES:rBX	buffer address
+ */
+TEXT BIOSread(SB), $0
+	LWI(5, rDI)			/* retry count (ATAPI ZIPs suck) */
+_retry:
+	PUSHA				/* may be trashed by BIOSCALL */
+
+	SBPW(rBX, Xdap+4)		/* transfer buffer :offset */
+	MFSR(rES, rDI)			/* transfer buffer seg: */
+	SBPW(rDI, Xdap+6)
+	SBPW(rAX, Xdap+8)		/* LBA (64-bits) */
+	SBPW(rDX, Xdap+10)
+
+	MW(rBP, rSI)			/* disk address packet */
+	LBI(0x42, rAH)			/* extended read */
+	LBPB(Xdrive, rDL)		/* form drive */
+	BIOSCALL(0x13)			/* CF set on failure */
+	JCC _BIOSreadret
+
+	POPA
+	DEC(rDI)			/* too many retries? */
+	JEQ _ioerror
+
+	CALL16(dreset(SB))
+	JMP _retry
+
+_ioerror:
+	LWI(ioerror(SB), rSI)
+	CALL16(BIOSputs(SB))
+	JMP _wait
+
+_BIOSreadret:
+	POPA
+	RET
+
+TEXT dreset(SB), $0
+	PUSHA
+	CLR(rAX)			/* rAH == 0 == reset disc system */
+	LBPB(Xdrive, rDL)
+	BIOSCALL(0x13)
+	ORB(rAH, rAH)			/* status (0 == success) */
+	POPA
+	JNE _ioerror
+	RET
+
+/*
+ * Output a string to the display.
+ * String argument is in rSI.
+ */
+TEXT BIOSputs(SB), $0
+	PUSHA
+	CLR(rBX)
+_BIOSputs:
+	LODSB
+	ORB(rAL, rAL)
+	JEQ _BIOSputsret
+
+	LBI(0x0E, rAH)
+	BIOSCALL(0x10)
+	JMP _BIOSputs
+
+_BIOSputsret:
+	POPA
+	RET
+
+/* "Bad format or I/O error\r\nPress almost any key to reboot..." */
+TEXT error(SB), $0
+	BYTE $'B'; BYTE $'a'; BYTE $'d'; BYTE $' ';
+	BYTE $'f'; BYTE $'o'; BYTE $'r'; BYTE $'m';
+	BYTE $'a'; BYTE $'t'; BYTE $' '; BYTE $'o';
+	BYTE $'r'; BYTE $' ';
+/* "I/O error\r\nPress almost any key to reboot..." */
+TEXT ioerror(SB), $0
+	BYTE $'I'; BYTE $'/'; BYTE $'O'; BYTE $' ';
+	BYTE $'e'; BYTE $'r'; BYTE $'r'; BYTE $'o';
+	BYTE $'r'; BYTE $'\r';BYTE $'\n';
+	BYTE $'P'; BYTE $'r'; BYTE $'e'; BYTE $'s';
+	BYTE $'s'; BYTE $' '; BYTE $'a'; BYTE $' ';
+	BYTE $'k'; BYTE $'e'; BYTE $'y';
+	BYTE $' '; BYTE $'t'; BYTE $'o'; BYTE $' ';
+	BYTE $'r'; BYTE $'e'; BYTE $'b'; BYTE $'o';
+	BYTE $'o'; BYTE $'t';
+	BYTE $'.'; BYTE $'.'; BYTE $'.';
+	BYTE $'\z';
+
+#ifdef USEBCOM
+/* "B       COM" */
+TEXT bootfile(SB), $0
+	BYTE $'B'; BYTE $' '; BYTE $' '; BYTE $' ';
+	BYTE $' '; BYTE $' '; BYTE $' '; BYTE $' ';
+	BYTE $'C'; BYTE $'O'; BYTE $'M';
+	BYTE $'\z';
+#else
+/* "9LOAD      " */
+TEXT bootfile(SB), $0
+	BYTE $'9'; BYTE $'L'; BYTE $'O'; BYTE $'A';
+	BYTE $'D'; BYTE $' '; BYTE $' '; BYTE $' ';
+	BYTE $' '; BYTE $' '; BYTE $' ';
+	BYTE $'\z';
+#endif /* USEBCOM */
+
+/* "PBS..." */
+TEXT confidence(SB), $0
+	BYTE $'P'; BYTE $'B'; BYTE $'S'; BYTE $'2';
+	BYTE $'.'; BYTE $'.'; BYTE $'.';
+	BYTE $'\z';
--- /dev/null
+++ b/os/boot.original/pc/pci.c
@@ -1,0 +1,1002 @@
+/*
+ * PCI support code.
+ * To do:
+ *	initialise bridge mappings if the PCI BIOS didn't.
+ */
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "error.h"
+
+enum {					/* configuration mechanism #1 */
+	PciADDR		= 0xCF8,	/* CONFIG_ADDRESS */
+	PciDATA		= 0xCFC,	/* CONFIG_DATA */
+
+					/* configuration mechanism #2 */
+	PciCSE		= 0xCF8,	/* configuration space enable */
+	PciFORWARD	= 0xCFA,	/* which bus */
+
+	MaxFNO		= 7,
+	MaxUBN		= 255,
+};
+
+enum
+{					/* command register */
+	IOen		= (1<<0),
+	MEMen		= (1<<1),
+	MASen		= (1<<2),
+	MemWrInv	= (1<<4),
+	PErrEn		= (1<<6),
+	SErrEn		= (1<<8),
+};
+
+static Lock pcicfglock;
+static Lock pcicfginitlock;
+static int pcicfgmode = -1;
+static int pcimaxbno = 7;
+static int pcimaxdno;
+static Pcidev* pciroot;
+static Pcidev* pcilist;
+static Pcidev* pcitail;
+
+static int pcicfgrw32(int, int, int, int);
+static int pcicfgrw8(int, int, int, int);
+
+ulong
+pcibarsize(Pcidev *p, int rno)
+{
+	ulong v, size;
+
+	v = pcicfgrw32(p->tbdf, rno, 0, 1);
+	pcicfgrw32(p->tbdf, rno, 0xFFFFFFF0, 0);
+	size = pcicfgrw32(p->tbdf, rno, 0, 1);
+	if(v & 1)
+		size |= 0xFFFF0000;
+	pcicfgrw32(p->tbdf, rno, v, 0);
+
+	return -(size & ~0x0F);
+}
+
+int
+pciscan(int bno, Pcidev** list)
+{
+	Pcidev *p, *head, *tail;
+	int dno, fno, i, hdt, l, maxfno, maxubn, rno, sbn, tbdf, ubn;
+
+	maxubn = bno;
+	head = nil;
+	tail = nil;
+	for(dno = 0; dno <= pcimaxdno; dno++){
+		maxfno = 0;
+		for(fno = 0; fno <= maxfno; fno++){
+			/*
+			 * For this possible device, form the
+			 * bus+device+function triplet needed to address it
+			 * and try to read the vendor and device ID.
+			 * If successful, allocate a device struct and
+			 * start to fill it in with some useful information
+			 * from the device's configuration space.
+			 */
+			tbdf = MKBUS(BusPCI, bno, dno, fno);
+			l = pcicfgrw32(tbdf, PciVID, 0, 1);
+			if(l == 0xFFFFFFFF || l == 0)
+				continue;
+			p = malloc(sizeof(*p));
+			p->tbdf = tbdf;
+			p->vid = l;
+			p->did = l>>16;
+
+			if(pcilist != nil)
+				pcitail->list = p;
+			else
+				pcilist = p;
+			pcitail = p;
+
+			p->rid = pcicfgr8(p, PciRID);
+			p->ccrp = pcicfgr8(p, PciCCRp);
+			p->ccru = pcicfgr8(p, PciCCRu);
+			p->ccrb = pcicfgr8(p, PciCCRb);
+			p->pcr = pcicfgr32(p, PciPCR);
+
+			p->intl = pcicfgr8(p, PciINTL);
+
+			/*
+			 * If the device is a multi-function device adjust the
+			 * loop count so all possible functions are checked.
+			 */
+			hdt = pcicfgr8(p, PciHDT);
+			if(hdt & 0x80)
+				maxfno = MaxFNO;
+
+			/*
+			 * If appropriate, read the base address registers
+			 * and work out the sizes.
+			 */
+			switch(p->ccrb){
+
+			case 0x01:		/* mass storage controller */
+			case 0x02:		/* network controller */
+			case 0x03:		/* display controller */
+			case 0x04:		/* multimedia device */
+			case 0x07:		/* simple comm. controllers */
+			case 0x08:		/* base system peripherals */
+			case 0x09:		/* input devices */
+			case 0x0A:		/* docking stations */
+			case 0x0B:		/* processors */
+			case 0x0C:		/* serial bus controllers */
+				if((hdt & 0x7F) != 0)
+					break;
+				rno = PciBAR0 - 4;
+				for(i = 0; i < nelem(p->mem); i++){
+					rno += 4;
+					p->mem[i].bar = pcicfgr32(p, rno);
+					p->mem[i].size = pcibarsize(p, rno);
+				}
+				break;
+
+			case 0x00:
+			case 0x05:		/* memory controller */
+			case 0x06:		/* bridge device */
+			default:
+				break;
+			}
+
+			if(head != nil)
+				tail->link = p;
+			else
+				head = p;
+			tail = p;
+		}
+	}
+
+	*list = head;
+	for(p = head; p != nil; p = p->link){
+		/*
+		 * Find PCI-PCI and PCI-Cardbus bridges
+		 * and recursively descend the tree.
+		 */
+		if(p->ccrb != 0x06 || p->ccru != 0x04)
+			continue;
+
+		/*
+		 * If the secondary or subordinate bus number is not
+		 * initialised try to do what the PCI BIOS should have
+		 * done and fill in the numbers as the tree is descended.
+		 * On the way down the subordinate bus number is set to
+		 * the maximum as it's not known how many buses are behind
+		 * this one; the final value is set on the way back up.
+		 */
+		ubn = pcicfgr8(p, PciUBN);
+		sbn = pcicfgr8(p, PciSBN);
+
+		if(sbn == 0 || ubn == 0){
+			sbn = maxubn+1;
+			/*
+			 * Make sure memory, I/O and master enables are
+			 * off, set the primary, secondary and subordinate
+			 * bus numbers and clear the secondary status before
+			 * attempting to scan the secondary bus.
+			 *
+			 * Initialisation of the bridge should be done here.
+			 */
+			pcicfgw32(p, PciPCR, 0xFFFF0000);
+			l = (MaxUBN<<16)|(sbn<<8)|bno;
+			pcicfgw32(p, PciPBN, l);
+			pcicfgw16(p, PciSPSR, 0xFFFF);
+			maxubn = pciscan(sbn, &p->bridge);
+			l = (maxubn<<16)|(sbn<<8)|bno;
+
+			pcicfgw32(p, PciPBN, l);
+		}
+		else{
+			/*
+			 * You can't go back.
+			 * This shouldn't be possible, but the
+			 * Iwill DK8-HTX seems to have subordinate
+			 * bus numbers which get smaller on the
+			 * way down. Need to look more closely at
+			 * this.
+			 */
+			if(ubn > maxubn)
+				maxubn = ubn;
+			pciscan(sbn, &p->bridge);
+		}
+	}
+
+	return maxubn;
+}
+
+static uchar
+null_link(Pcidev *, uchar )
+{
+	return 0;
+}
+
+static void
+null_init(Pcidev *, uchar , uchar )
+{
+}
+
+static uchar
+pIIx_link(Pcidev *router, uchar link)
+{
+	uchar pirq;
+
+	/* link should be 0x60, 0x61, 0x62, 0x63 */
+	pirq = pcicfgr8(router, link);
+	return (pirq < 16)? pirq: 0;
+}
+
+static void
+pIIx_init(Pcidev *router, uchar link, uchar irq)
+{
+	pcicfgw8(router, link, irq);
+}
+
+static uchar
+via_link(Pcidev *router, uchar link)
+{
+	uchar pirq;
+
+	/* link should be 1, 2, 3, 5 */
+	pirq = (link < 6)? pcicfgr8(router, 0x55 + (link>>1)): 0;
+
+	return (link & 1)? (pirq >> 4): (pirq & 15);
+}
+
+static void
+via_init(Pcidev *router, uchar link, uchar irq)
+{
+	uchar pirq;
+
+	pirq = pcicfgr8(router, 0x55 + (link >> 1));
+	pirq &= (link & 1)? 0x0f: 0xf0;
+	pirq |= (link & 1)? (irq << 4): (irq & 15);
+	pcicfgw8(router, 0x55 + (link>>1), pirq);
+}
+
+static uchar
+opti_link(Pcidev *router, uchar link)
+{
+	uchar pirq = 0;
+
+	/* link should be 0x02, 0x12, 0x22, 0x32 */
+	if ((link & 0xcf) == 0x02)
+		pirq = pcicfgr8(router, 0xb8 + (link >> 5));
+	return (link & 0x10)? (pirq >> 4): (pirq & 15);
+}
+
+static void
+opti_init(Pcidev *router, uchar link, uchar irq)
+{
+	uchar pirq;
+
+	pirq = pcicfgr8(router, 0xb8 + (link >> 5));
+    	pirq &= (link & 0x10)? 0x0f : 0xf0;
+    	pirq |= (link & 0x10)? (irq << 4): (irq & 15);
+	pcicfgw8(router, 0xb8 + (link >> 5), pirq);
+}
+
+static uchar
+ali_link(Pcidev *router, uchar link)
+{
+	/* No, you're not dreaming */
+	static const uchar map[] = { 0, 9, 3, 10, 4, 5, 7, 6, 1, 11, 0, 12, 0, 14, 0, 15 };
+	uchar pirq;
+
+	/* link should be 0x01..0x08 */
+	pirq = pcicfgr8(router, 0x48 + ((link-1)>>1));
+	return (link & 1)? map[pirq&15]: map[pirq>>4];
+}
+
+static void
+ali_init(Pcidev *router, uchar link, uchar irq)
+{
+	/* Inverse of map in ali_link */
+	static const uchar map[] = { 0, 8, 0, 2, 4, 5, 7, 6, 0, 1, 3, 9, 11, 0, 13, 15 };
+	uchar pirq;
+
+	pirq = pcicfgr8(router, 0x48 + ((link-1)>>1));
+	pirq &= (link & 1)? 0x0f: 0xf0;
+	pirq |= (link & 1)? (map[irq] << 4): (map[irq] & 15);
+	pcicfgw8(router, 0x48 + ((link-1)>>1), pirq);
+}
+
+static uchar
+cyrix_link(Pcidev *router, uchar link)
+{
+	uchar pirq;
+
+	/* link should be 1, 2, 3, 4 */
+	pirq = pcicfgr8(router, 0x5c + ((link-1)>>1));
+	return ((link & 1)? pirq >> 4: pirq & 15);
+}
+
+static void
+cyrix_init(Pcidev *router, uchar link, uchar irq)
+{
+	uchar pirq;
+
+	pirq = pcicfgr8(router, 0x5c + (link>>1));
+	pirq &= (link & 1)? 0x0f: 0xf0;
+	pirq |= (link & 1)? (irq << 4): (irq & 15);
+	pcicfgw8(router, 0x5c + (link>>1), pirq);
+}
+
+typedef struct {
+	ushort	sb_vid, sb_did;
+	uchar	(*sb_translate)(Pcidev *, uchar);
+	void	(*sb_initialize)(Pcidev *, uchar, uchar);
+} bridge_t;
+
+static bridge_t southbridges[] = {
+	{ 0x8086, 0x122e, pIIx_link, pIIx_init },	// Intel 82371FB
+	{ 0x8086, 0x1234, pIIx_link, pIIx_init },	// Intel 82371MX
+	{ 0x8086, 0x7000, pIIx_link, pIIx_init },	// Intel 82371SB
+	{ 0x8086, 0x7110, pIIx_link, pIIx_init },	// Intel 82371AB
+	{ 0x8086, 0x7198, pIIx_link, pIIx_init },	// Intel 82443MX (fn 1)
+	{ 0x8086, 0x2410, pIIx_link, pIIx_init },	// Intel 82801AA
+	{ 0x8086, 0x2420, pIIx_link, pIIx_init },	// Intel 82801AB
+	{ 0x8086, 0x2440, pIIx_link, pIIx_init },	// Intel 82801BA
+	{ 0x8086, 0x244c, pIIx_link, pIIx_init },	// Intel 82801BAM
+	{ 0x8086, 0x2480, pIIx_link, pIIx_init },	// Intel 82801CA
+	{ 0x8086, 0x248c, pIIx_link, pIIx_init },	// Intel 82801CAM
+	{ 0x8086, 0x24c0, pIIx_link, pIIx_init },	// Intel 82801DBL
+	{ 0x8086, 0x24cc, pIIx_link, pIIx_init },	// Intel 82801DBM
+	{ 0x8086, 0x24d0, pIIx_link, pIIx_init },	// Intel 82801EB
+	{ 0x8086, 0x2640, pIIx_link, pIIx_init },	// Intel 82801FB
+	{ 0x8086, 0x27b8, pIIx_link, pIIx_init },	// Intel 82801GB
+	{ 0x8086, 0x27b9, pIIx_link, pIIx_init },	// Intel 82801GBM
+	{ 0x1106, 0x0586, via_link, via_init },		// Viatech 82C586
+	{ 0x1106, 0x0596, via_link, via_init },		// Viatech 82C596
+	{ 0x1106, 0x0686, via_link, via_init },		// Viatech 82C686
+	{ 0x1106, 0x3227, via_link, via_init },		// Viatech VT8237
+	{ 0x1045, 0xc700, opti_link, opti_init },	// Opti 82C700
+	{ 0x10b9, 0x1533, ali_link, ali_init },		// Al M1533
+	{ 0x1039, 0x0008, pIIx_link, pIIx_init },	// SI 503
+	{ 0x1039, 0x0496, pIIx_link, pIIx_init },	// SI 496
+	{ 0x1078, 0x0100, cyrix_link, cyrix_init },	// Cyrix 5530 Legacy
+
+	{ 0x1002, 0x4377, nil, nil },		// ATI Radeon Xpress 200M
+	{ 0x1002, 0x4372, nil, nil },		// ATI SB400
+	{ 0x1022, 0x746B, nil, nil },		// AMD 8111
+	{ 0x10DE, 0x00D1, nil, nil },		// NVIDIA nForce 3
+	{ 0x10DE, 0x00E0, nil, nil },		// NVIDIA nForce 3 250 Series
+	{ 0x1166, 0x0200, nil, nil },		// ServerWorks ServerSet III LE
+};
+
+typedef struct {
+	uchar	e_bus;			// Pci bus number
+	uchar	e_dev;			// Pci device number
+	uchar	e_maps[12];		// Avoid structs!  Link and mask.
+	uchar	e_slot;			// Add-in/built-in slot
+	uchar	e_reserved;
+} slot_t;
+
+typedef struct {
+	uchar	rt_signature[4];	// Routing table signature
+	uchar	rt_version[2];		// Version number
+	uchar	rt_size[2];			// Total table size
+	uchar	rt_bus;			// Interrupt router bus number
+	uchar	rt_devfn;			// Router's devfunc
+	uchar	rt_pciirqs[2];		// Exclusive PCI irqs
+	uchar	rt_compat[4];		// Compatible PCI interrupt router
+	uchar	rt_miniport[4];		// Miniport data
+	uchar	rt_reserved[11];
+	uchar	rt_checksum;
+} router_t;
+
+static ushort pciirqs;			// Exclusive PCI irqs
+static bridge_t *southbridge;	// Which southbridge to use.
+
+static void
+pcirouting(void)
+{
+	uchar *p, pin, irq;
+	ulong tbdf, vdid;
+	ushort vid, did;
+	router_t *r;
+	slot_t *e;
+	int size, i, fn;
+	Pcidev *sbpci, *pci;
+
+	// Peek in the BIOS
+	for (p = (uchar *)KADDR(0xf0000); p < (uchar *)KADDR(0xfffff); p += 16)
+		if (p[0] == '$' && p[1] == 'P' && p[2] == 'I' && p[3] == 'R')
+			break;
+
+	if (p >= (uchar *)KADDR(0xfffff))
+		return;
+
+	r = (router_t *)p;
+
+	// print("PCI interrupt routing table version %d.%d at %.6uX\n",
+	// 	r->rt_version[0], r->rt_version[1], (ulong)r & 0xfffff);
+
+	tbdf = (BusPCI << 24)|(r->rt_bus << 16)|(r->rt_devfn << 8);
+	vdid = pcicfgrw32(tbdf, PciVID, 0, 1);
+	vid = vdid;
+	did = vdid >> 16;
+
+	for (i = 0; i != nelem(southbridges); i++)
+		if (vid == southbridges[i].sb_vid && did == southbridges[i].sb_did)
+			break;
+
+	if (i == nelem(southbridges)) {
+		print("pcirouting: South bridge %.4uX, %.4uX not found\n", vid, did);
+		return;
+	}
+	southbridge = &southbridges[i];
+
+	if ((sbpci = pcimatch(nil, vid, did)) == nil) {
+		print("pcirouting: Cannot match south bridge %.4uX, %.4uX\n",
+			  vid, did);
+		return;
+	}
+
+	pciirqs = (r->rt_pciirqs[1] << 8)|r->rt_pciirqs[0];
+
+	size = (r->rt_size[1] << 8)|r->rt_size[0];
+	for (e = (slot_t *)&r[1]; (uchar *)e < p + size; e++) {
+		// print("%.2uX/%.2uX %.2uX: ", e->e_bus, e->e_dev, e->e_slot);
+		// for (i = 0; i != 4; i++) {
+		// 	uchar *m = &e->e_maps[i * 3];
+		// 	print("[%d] %.2uX %.4uX ",
+		// 		i, m[0], (m[2] << 8)|m[1]);
+		// }
+		// print("\n");
+
+		for (fn = 0; fn != 8; fn++) {
+			uchar *m;
+
+			// Retrieve the did and vid through the devfn before
+			// obtaining the Pcidev structure.
+			tbdf = (BusPCI << 24)|(e->e_bus << 16)|((e->e_dev | fn) << 8);
+			vdid = pcicfgrw32(tbdf, PciVID, 0, 1);
+			if (vdid == 0xFFFFFFFF || vdid == 0)
+				continue;
+
+			vid = vdid;
+			did = vdid >> 16;
+
+			pci = nil;
+			while ((pci = pcimatch(pci, vid, did)) != nil) {
+
+				if (pci->intl != 0 && pci->intl != 0xFF)
+					continue;
+
+				pin = pcicfgr8(pci, PciINTP);
+				if (pin == 0 || pin == 0xff)
+					continue;
+
+				m = &e->e_maps[(pin - 1) * 3];
+				irq = southbridge->sb_translate(sbpci, m[0]);
+				if (irq) {
+					print("pcirouting: %.4uX/%.4uX at pin %d irq %d\n",
+						  vid, did, pin, irq);
+					pcicfgw8(pci, PciINTL, irq);
+					pci->intl = irq;
+				}
+			}
+		}
+	}
+}
+
+static void
+pcicfginit(void)
+{
+	char *p;
+	int bno, n;
+	Pcidev **list;
+
+	lock(&pcicfginitlock);
+	if(pcicfgmode != -1)
+		goto out;
+
+	/*
+	 * Try to determine which PCI configuration mode is implemented.
+	 * Mode2 uses a byte at 0xCF8 and another at 0xCFA; Mode1 uses
+	 * a DWORD at 0xCF8 and another at 0xCFC and will pass through
+	 * any non-DWORD accesses as normal I/O cycles. There shouldn't be
+	 * a device behind these addresses so if Mode1 accesses fail try
+	 * for Mode2 (Mode2 is deprecated).
+	 */
+
+	/*
+	 * Bits [30:24] of PciADDR must be 0,
+	 * according to the spec.
+	 */
+	n = inl(PciADDR);
+	if(!(n & 0x7FF00000)){
+		outl(PciADDR, 0x80000000);
+		outb(PciADDR+3, 0);
+		if(inl(PciADDR) & 0x80000000){
+			pcicfgmode = 1;
+			pcimaxdno = 31;
+		}
+	}
+	outl(PciADDR, n);
+
+	if(pcicfgmode < 0){
+		/*
+		 * The 'key' part of PciCSE should be 0.
+		 */
+		n = inb(PciCSE);
+		if(!(n & 0xF0)){
+			outb(PciCSE, 0x0E);
+			if(inb(PciCSE) == 0x0E){
+				pcicfgmode = 2;
+				pcimaxdno = 15;
+			}
+		}
+		outb(PciCSE, n);
+	}
+
+	if(pcicfgmode < 0)
+		goto out;
+
+
+	if(p = getconf("*pcimaxbno"))
+		pcimaxbno = strtoul(p, 0, 0);
+	if(p = getconf("*pcimaxdno"))
+		pcimaxdno = strtoul(p, 0, 0);
+
+	list = &pciroot;
+	for(bno = 0; bno <= pcimaxbno; bno++) {
+		bno = pciscan(bno, list);
+		while(*list)
+			list = &(*list)->link;
+	}
+
+	pcirouting();
+
+out:
+	unlock(&pcicfginitlock);
+
+	if(getconf("*pcihinv"))
+		pcihinv(nil);
+}
+
+
+static int
+pcicfgrw8(int tbdf, int rno, int data, int read)
+{
+	int o, type, x;
+
+	if(pcicfgmode == -1)
+		pcicfginit();
+
+	if(BUSBNO(tbdf))
+		type = 0x01;
+	else
+		type = 0x00;
+	x = -1;
+	if(BUSDNO(tbdf) > pcimaxdno)
+		return x;
+
+	lock(&pcicfglock);
+	switch(pcicfgmode){
+
+	case 1:
+		o = rno & 0x03;
+		rno &= ~0x03;
+		outl(PciADDR, 0x80000000|BUSBDF(tbdf)|rno|type);
+		if(read)
+			x = inb(PciDATA+o);
+		else
+			outb(PciDATA+o, data);
+		outl(PciADDR, 0);
+		break;
+
+	case 2:
+		outb(PciCSE, 0x80|(BUSFNO(tbdf)<<1));
+		outb(PciFORWARD, BUSBNO(tbdf));
+		if(read)
+			x = inb((0xC000|(BUSDNO(tbdf)<<8)) + rno);
+		else
+			outb((0xC000|(BUSDNO(tbdf)<<8)) + rno, data);
+		outb(PciCSE, 0);
+		break;
+	}
+	unlock(&pcicfglock);
+
+	return x;
+}
+
+int
+pcicfgr8(Pcidev* pcidev, int rno)
+{
+	return pcicfgrw8(pcidev->tbdf, rno, 0, 1);
+}
+
+void
+pcicfgw8(Pcidev* pcidev, int rno, int data)
+{
+	pcicfgrw8(pcidev->tbdf, rno, data, 0);
+}
+
+static int
+pcicfgrw16(int tbdf, int rno, int data, int read)
+{
+	int o, type, x;
+
+	if(pcicfgmode == -1)
+		pcicfginit();
+
+	if(BUSBNO(tbdf))
+		type = 0x01;
+	else
+		type = 0x00;
+	x = -1;
+	if(BUSDNO(tbdf) > pcimaxdno)
+		return x;
+
+	lock(&pcicfglock);
+	switch(pcicfgmode){
+
+	case 1:
+		o = rno & 0x02;
+		rno &= ~0x03;
+		outl(PciADDR, 0x80000000|BUSBDF(tbdf)|rno|type);
+		if(read)
+			x = ins(PciDATA+o);
+		else
+			outs(PciDATA+o, data);
+		outl(PciADDR, 0);
+		break;
+
+	case 2:
+		outb(PciCSE, 0x80|(BUSFNO(tbdf)<<1));
+		outb(PciFORWARD, BUSBNO(tbdf));
+		if(read)
+			x = ins((0xC000|(BUSDNO(tbdf)<<8)) + rno);
+		else
+			outs((0xC000|(BUSDNO(tbdf)<<8)) + rno, data);
+		outb(PciCSE, 0);
+		break;
+	}
+	unlock(&pcicfglock);
+
+	return x;
+}
+
+int
+pcicfgr16(Pcidev* pcidev, int rno)
+{
+	return pcicfgrw16(pcidev->tbdf, rno, 0, 1);
+}
+
+void
+pcicfgw16(Pcidev* pcidev, int rno, int data)
+{
+	pcicfgrw16(pcidev->tbdf, rno, data, 0);
+}
+
+static int
+pcicfgrw32(int tbdf, int rno, int data, int read)
+{
+	int type, x;
+
+	if(pcicfgmode == -1)
+		pcicfginit();
+
+	if(BUSBNO(tbdf))
+		type = 0x01;
+	else
+		type = 0x00;
+	x = -1;
+	if(BUSDNO(tbdf) > pcimaxdno)
+		return x;
+
+	lock(&pcicfglock);
+	switch(pcicfgmode){
+
+	case 1:
+		rno &= ~0x03;
+		outl(PciADDR, 0x80000000|BUSBDF(tbdf)|rno|type);
+		if(read)
+			x = inl(PciDATA);
+		else
+			outl(PciDATA, data);
+		outl(PciADDR, 0);
+		break;
+
+	case 2:
+		outb(PciCSE, 0x80|(BUSFNO(tbdf)<<1));
+		outb(PciFORWARD, BUSBNO(tbdf));
+		if(read)
+			x = inl((0xC000|(BUSDNO(tbdf)<<8)) + rno);
+		else
+			outl((0xC000|(BUSDNO(tbdf)<<8)) + rno, data);
+		outb(PciCSE, 0);
+		break;
+	}
+	unlock(&pcicfglock);
+
+	return x;
+}
+
+int
+pcicfgr32(Pcidev* pcidev, int rno)
+{
+	return pcicfgrw32(pcidev->tbdf, rno, 0, 1);
+}
+
+void
+pcicfgw32(Pcidev* pcidev, int rno, int data)
+{
+	pcicfgrw32(pcidev->tbdf, rno, data, 0);
+}
+
+Pcidev*
+pcimatch(Pcidev* prev, int vid, int did)
+{
+	if(pcicfgmode == -1)
+		pcicfginit();
+
+	if(prev == nil)
+		prev = pcilist;
+	else
+		prev = prev->list;
+
+	while(prev != nil) {
+		if((vid == 0 || prev->vid == vid)
+		&& (did == 0 || prev->did == did))
+			break;
+		prev = prev->list;
+	}
+	return prev;
+}
+
+uchar
+pciipin(Pcidev *pci, uchar pin)
+{
+	if (pci == nil)
+		pci = pcilist;
+
+	while (pci) {
+		uchar intl;
+
+		if (pcicfgr8(pci, PciINTP) == pin && pci->intl != 0 && pci->intl != 0xff)
+			return pci->intl;
+
+		if (pci->bridge && (intl = pciipin(pci->bridge, pin)) != 0)
+			return intl;
+
+		pci = pci->list;
+	}
+	return 0;
+}
+
+static ushort
+pciimask(Pcidev *pci)
+{
+	ushort imask;
+
+	imask = 0;
+	while (pci) {
+		if (pcicfgr8(pci, PciINTP) && pci->intl < 16)
+			imask |= 1 << pci->intl;
+
+		if (pci->bridge)
+			imask |= pciimask(pci->bridge);
+
+		pci = pci->list;
+	}
+	return imask;
+}
+
+uchar
+pciintl(Pcidev *pci)
+{
+	ushort imask;
+	int i;
+
+	if (pci == nil)
+		pci = pcilist;
+
+	imask = pciimask(pci) | 1;
+	for (i = 0; i != 16; i++)
+		if ((imask & (1 << i)) == 0)
+			return i;
+	return 0;
+}
+
+void
+pcihinv(Pcidev* p)
+{
+	int i;
+	Pcidev *t;
+
+	if(pcicfgmode == -1)
+		pcicfginit();
+
+	if(p == nil) {
+		p = pciroot;
+		print("bus dev type vid  did intl memory\n");
+	}
+	for(t = p; t != nil; t = t->link) {
+		print("%d  %2d/%d %.2ux %.2ux %.2ux %.4ux %.4ux %3d  ",
+			BUSBNO(t->tbdf), BUSDNO(t->tbdf), BUSFNO(t->tbdf),
+			t->ccrb, t->ccru, t->ccrp, t->vid, t->did, t->intl);
+
+		for(i = 0; i < nelem(p->mem); i++) {
+			if(t->mem[i].size == 0)
+				continue;
+			print("%d:%.8lux %d ", i,
+				t->mem[i].bar, t->mem[i].size);
+		}
+		print("\n");
+	}
+	while(p != nil) {
+		if(p->bridge != nil)
+			pcihinv(p->bridge);
+		p = p->link;
+	}
+}
+
+void
+pcireset(void)
+{
+	Pcidev *p;
+	int pcr;
+
+	if(pcicfgmode == -1)
+		pcicfginit();
+
+	for(p = pcilist; p != nil; p = p->list){
+		pcr = pcicfgr16(p, PciPSR);
+		pcicfgw16(p, PciPSR, pcr & ~0x04);
+	}
+}
+
+void
+pcisetioe(Pcidev* p)
+{
+	p->pcr |= IOen;
+	pcicfgw16(p, PciPCR, p->pcr);
+}
+
+void
+pciclrioe(Pcidev* p)
+{
+	p->pcr &= ~IOen;
+	pcicfgw16(p, PciPCR, p->pcr);
+}
+
+void
+pcisetbme(Pcidev* p)
+{
+	p->pcr |= MASen;
+	pcicfgw16(p, PciPCR, p->pcr);
+}
+
+void
+pciclrbme(Pcidev* p)
+{
+	p->pcr &= ~MASen;
+	pcicfgw16(p, PciPCR, p->pcr);
+}
+
+void
+pcisetmwi(Pcidev* p)
+{
+	p->pcr |= MemWrInv;
+	pcicfgw16(p, PciPCR, p->pcr);
+}
+
+void
+pciclrmwi(Pcidev* p)
+{
+	p->pcr &= ~MemWrInv;
+	pcicfgw16(p, PciPCR, p->pcr);
+}
+
+static int
+pcigetpmrb(Pcidev* p)
+{
+	int ptr;
+
+	if(p->pmrb != 0)
+		return p->pmrb;
+	p->pmrb = -1;
+
+	/*
+	 * If there are no extended capabilities implemented,
+	 * (bit 4 in the status register) assume there's no standard
+	 * power management method.
+	 * Find the capabilities pointer based on PCI header type.
+	 */
+	if(!(pcicfgr16(p, PciPSR) & 0x0010))
+		return -1;
+	switch(pcicfgr8(p, PciHDT)){
+	default:
+		return -1;
+	case 0:					/* all other */
+	case 1:					/* PCI to PCI bridge */
+		ptr = 0x34;
+		break;
+	case 2:					/* CardBus bridge */
+		ptr = 0x14;
+		break;
+	}
+	ptr = pcicfgr32(p, ptr);
+
+	while(ptr != 0){
+		/*
+		 * Check for validity.
+		 * Can't be in standard header and must be double
+		 * word aligned.
+		 */
+		if(ptr < 0x40 || (ptr & ~0xFC))
+			return -1;
+		if(pcicfgr8(p, ptr) == 0x01){
+			p->pmrb = ptr;
+			return ptr;
+		}
+
+		ptr = pcicfgr8(p, ptr+1);
+	}
+
+	return -1;
+}
+
+int
+pcigetpms(Pcidev* p)
+{
+	int pmcsr, ptr;
+
+	if((ptr = pcigetpmrb(p)) == -1)
+		return -1;
+
+	/*
+	 * Power Management Register Block:
+	 *  offset 0:	Capability ID
+	 *	   1:	next item pointer
+	 *	   2:	capabilities
+	 *	   4:	control/status
+	 *	   6:	bridge support extensions
+	 *	   7:	data
+	 */
+	pmcsr = pcicfgr16(p, ptr+4);
+
+	return pmcsr & 0x0003;
+}
+
+int
+pcisetpms(Pcidev* p, int state)
+{
+	int ostate, pmc, pmcsr, ptr;
+
+	if((ptr = pcigetpmrb(p)) == -1)
+		return -1;
+
+	pmc = pcicfgr16(p, ptr+2);
+	pmcsr = pcicfgr16(p, ptr+4);
+	ostate = pmcsr & 0x0003;
+	pmcsr &= ~0x0003;
+
+	switch(state){
+	default:
+		return -1;
+	case 0:
+		break;
+	case 1:
+		if(!(pmc & 0x0200))
+			return -1;
+		break;
+	case 2:
+		if(!(pmc & 0x0400))
+			return -1;
+		break;
+	case 3:
+		break;
+	}
+	pmcsr |= state;
+	pcicfgw16(p, ptr+4, pmcsr);
+
+	return ostate;
+}
--- /dev/null
+++ b/os/boot.original/pc/print.c
@@ -1,0 +1,31 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+
+static Lock fmtl;
+
+void
+_fmtlock(void)
+{
+	lock(&fmtl);
+}
+
+void
+_fmtunlock(void)
+{
+	unlock(&fmtl);
+}
+
+int
+_efgfmt(Fmt*)
+{
+	return -1;
+}
+
+int
+errfmt(Fmt*)
+{
+	return -1;
+}
--- /dev/null
+++ b/os/boot.original/pc/queue.c
@@ -1,0 +1,44 @@
+#include	"u.h"
+#include	"lib.h"
+#include	"mem.h"
+#include	"dat.h"
+#include	"fns.h"
+#include	"io.h"
+
+int
+qgetc(IOQ *q)
+{
+	int c;
+
+	if(q->in == q->out)
+		return -1;
+	c = *q->out;
+	if(q->out == q->buf+sizeof(q->buf)-1)
+		q->out = q->buf;
+	else
+		q->out++;
+	return c;
+}
+
+static int
+qputc(IOQ *q, int c)
+{
+	uchar *nextin;
+	if(q->in >= &q->buf[sizeof(q->buf)-1])
+		nextin = q->buf;
+	else
+		nextin = q->in+1;
+	if(nextin == q->out)
+		return -1;
+	*q->in = c;
+	q->in = nextin;
+	return 0;
+}
+
+void
+qinit(IOQ *q)
+{
+	q->in = q->out = q->buf;
+	q->getc = qgetc;
+	q->putc = qputc;
+}
--- /dev/null
+++ b/os/boot.original/pc/sd.h
@@ -1,0 +1,126 @@
+/*
+ * Storage Device.
+ */
+typedef struct SDev SDev;
+typedef struct SDifc SDifc;
+typedef struct SDpart SDpart;
+typedef struct SDreq SDreq;
+typedef struct SDunit SDunit;
+
+typedef struct SDpart {
+	uvlong	start;
+	uvlong	end;
+	char	name[NAMELEN];
+	char	user[NAMELEN];
+	ulong	perm;
+	int	valid;
+	void *crud;
+} SDpart;
+
+typedef struct SDunit {
+	SDev*	dev;
+	int	subno;
+	uchar	inquiry[256];		/* format follows SCSI spec */
+	char	name[NAMELEN];
+//	Rendez	rendez;
+
+//	QLock	ctl;
+	uvlong	sectors;
+	ulong	secsize;
+	SDpart*	part;
+	int	npart;			/* of valid partitions */
+	int	changed;
+
+//	QLock	raw;
+	int	state;
+	ulong	pid;
+	SDreq*	req;
+} SDunit;
+
+typedef struct SDev {
+	SDifc*	ifc;			/* pnp/legacy */
+	void	*ctlr;
+	int	idno;
+	int	index;			/* into unit space */
+	int	nunit;
+	SDev*	next;
+
+//	QLock;				/* enable/disable */
+	int	enabled;
+} SDev;
+
+typedef struct SDifc {
+	char*	name;
+
+	SDev*	(*pnp)(void);
+	SDev*	(*legacy)(int, int);
+	SDev*	(*id)(SDev*);
+	int	(*enable)(SDev*);
+	int	(*disable)(SDev*);
+
+	int	(*verify)(SDunit*);
+	int	(*online)(SDunit*);
+	int	(*rio)(SDreq*);
+	int	(*rctl)(SDunit*, char*, int);
+	int	(*wctl)(SDunit*, void*);
+
+	long	(*bio)(SDunit*, int, int, void*, long, long);
+} SDifc;
+
+typedef struct SDreq {
+	SDunit*	unit;
+	int	lun;
+	int	write;
+	uchar	cmd[16];
+	int	clen;
+	void*	data;
+	int	dlen;
+
+	int	flags;
+
+	int	status;
+	long	rlen;
+	uchar	sense[256];
+} SDreq;
+
+enum {
+	SDnosense	= 0x00000001,
+	SDvalidsense	= 0x00010000,
+};
+
+enum {
+	SDmalloc	= -4,
+	SDeio		= -3,
+	SDtimeout	= -2,
+	SDnostatus	= -1,
+
+	SDok		= 0,
+
+	SDcheck		= 0x02,		/* check condition */
+	SDbusy		= 0x08,		/* busy */
+
+	SDmaxio		= 2048*1024,
+	SDnpart		= 16,
+};
+
+/* sdscsi.c */
+extern int scsiverify(SDunit*);
+extern int scsionline(SDunit*);
+extern long scsibio(SDunit*, int, int, void*, long, long);
+extern SDev* scsiid(SDev*, SDifc*);
+
+#define IrqATA0 14
+#define IrqATA1 15
+#define qlock(i)	while(0)
+#define qunlock(i)	while(0)
+
+#define putstrn consputs
+
+void sleep(void*, int(*)(void*), void*);
+void tsleep(void*, int(*)(void*), void*, int);
+#define wakeup(x) while(0)
+extern long sdbio(SDunit *unit, SDpart *pp, void *a, long len, vlong off);
+void	partition(SDunit*);
+SDpart* sdfindpart(SDunit*, char*);
+void	sdaddpart(SDunit*, char*, uvlong, uvlong);
+void*	sdmalloc(void*, ulong);
--- /dev/null
+++ b/os/boot.original/pc/sd53c8xx.c
@@ -1,0 +1,2124 @@
+/*
+ * NCR 53c8xx driver for Plan 9
+ * Nigel Roles (ngr@cotswold.demon.co.uk)
+ *
+ * 08/07/99	Ultra2 fixed. Brazil #ifdefs added. Fixed script error 6 diagnostics.
+ *
+ * 09/06/99	Enhancements to support 895 and 896 correctly. Attempt at Ultra 2 negotiation,
+ *		though no device to test with yet.
+ *		Variant now contains the number of valid chip registers to assist
+ *		dumpncrregs() 
+ *
+ * 06/10/98	Various bug fixes and Brazil compiler inspired changes from jmk
+ *
+ * 05/10/98	Small fix to handle command length being greater than expected by device
+ *
+ * 04/08/98     Added missing locks to interrupt handler. Marked places where 
+ *		multiple controller extensions could go
+ *
+ * 18/05/97	Fixed overestimate in size of local SCRIPT RAM
+ *
+ * 17/05/97	Bug fix to return status
+ *
+ * 06/10/96	Enhanced list of chip IDs. 875 revision 1 has no clock doubler, so assume it
+ *		is shipped with 80MHz crystal. Use bit 3 of the GPREG to recognise differential
+ *		boards. This is Symbios specific, but since they are about the only suppliers of
+ *		differential cards.
+ *
+ * 23/9/96	Wide and Ultra supported. 825A and 860 added to variants. Dual compiling
+ *		version for fileserver and cpu. 80MHz default clock for 860
+ *		
+ * 5/8/96	Waits for an Inquiry message before initiating synchronous negotiation
+ *		in case capabilities byte [7] indicates device does not support it. Devices
+ *		which do target initiated negotiation will typically get in first; a few
+ *		bugs in handling this have been fixed
+ *
+ * 3/8/96	Added differential support (put scsi0=diff in plan9.ini)
+ *		Split exec() into exec() and io(). Exec() is small, and Io() does not
+ *		use any Plan 9 specific data structures, so alternate exec() functions
+ *		may be done for other environments, such as the fileserver
+ *
+ * GENERAL
+ *
+ * Works on 810 and 875
+ * Should work on 815, 825, 810A, 825A, 860A
+ * Uses local RAM, large FIFO, prefetch, burst opcode fetch, and 16 byte synch. offset
+ * where applicable
+ * Supports multi-target, wide, Ultra
+ * Differential mode can be enabled by putting scsi0=diff in plan9.ini
+ * NO SUPPORT FOR tagged queuing (yet)
+ *
+ * Known problems
+ */
+
+#define MAXTARGET	16		/* can be 8 or 16 */
+
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "ureg.h"
+#include "error.h"
+
+#include "sd.h"
+extern SDifc sd53c8xxifc;
+
+#define waserror()	(0)
+#define poperror()
+typedef struct QLock{ int r; } QLock;
+typedef struct Rendez{ int r; } Rendez;
+#define	intrenable(irq, f, c, tbdf, name)	setvec(VectorPIC+(irq), f, c);
+
+/**********************************/
+/* Portable configuration macros  */
+/**********************************/
+
+//#define BOOTDEBUG
+//#define ASYNC_ONLY
+//#define	INTERNAL_SCLK
+//#define ALWAYS_DO_WDTR
+#define WMR_DEBUG
+
+/**********************************/
+/* CPU specific macros            */
+/**********************************/
+
+#ifdef BOOTDEBUG
+
+#define KPRINT oprint
+#define IPRINT intrprint
+#define DEBUG(n) 0
+#define IFLUSH() iflush()
+
+#else
+
+#define KPRINT	if(0)print
+#define IPRINT	if(0)print
+#define DEBUG(n)	(0)
+#define IFLUSH()
+
+#endif /* BOOTDEBUG */
+
+/*******************************/
+/* General                     */
+/*******************************/
+
+#ifndef DMASEG
+#define DMASEG(x) PADDR(x)
+#define legetl(x) (*(ulong*)(x))
+#define lesetl(x,v) (*(ulong*)(x) = (v))
+#define swabl(a,b,c)
+#else
+#endif /*DMASEG */
+#define DMASEG_TO_KADDR(x) KADDR(PADDR(x))
+#define KPTR(x) ((x) == 0 ? 0 : DMASEG_TO_KADDR(x))
+
+#define MEGA 1000000L
+#ifdef INTERNAL_SCLK
+#define	SCLK (33 * MEGA)
+#else
+#define SCLK (40 * MEGA)
+#endif /* INTERNAL_SCLK */
+#define ULTRA_NOCLOCKDOUBLE_SCLK (80 * MEGA)
+
+#define MAXSYNCSCSIRATE (5 * MEGA)
+#define MAXFASTSYNCSCSIRATE (10 * MEGA)
+#define MAXULTRASYNCSCSIRATE (20 * MEGA)
+#define MAXULTRA2SYNCSCSIRATE (40 * MEGA)
+#define MAXASYNCCORERATE (25 * MEGA)
+#define MAXSYNCCORERATE (25 * MEGA)
+#define MAXFASTSYNCCORERATE (50 * MEGA)
+#define MAXULTRASYNCCORERATE (80 * MEGA)
+#define MAXULTRA2SYNCCORERATE (160 * MEGA)
+
+
+#define X_MSG	1
+#define X_MSG_SDTR 1
+#define X_MSG_WDTR 3
+
+struct na_patch {
+	unsigned lwoff;
+	unsigned char type;
+};
+
+typedef struct Ncr {
+	uchar scntl0;	/* 00 */
+	uchar scntl1;
+	uchar scntl2;
+	uchar scntl3;
+
+	uchar scid;	/* 04 */
+	uchar sxfer;
+	uchar sdid;
+	uchar gpreg;
+
+	uchar sfbr;	/* 08 */
+	uchar socl;
+	uchar ssid;
+	uchar sbcl;
+
+	uchar dstat;	/* 0c */
+	uchar sstat0;
+	uchar sstat1;
+	uchar sstat2;
+
+	uchar dsa[4];	/* 10 */
+
+	uchar istat;	/* 14 */
+	uchar istatpad[3];
+
+	uchar ctest0;	/* 18 */
+	uchar ctest1;
+	uchar ctest2;
+	uchar ctest3;
+
+	uchar temp[4];	/* 1c */
+
+	uchar dfifo;	/* 20 */
+	uchar ctest4;
+	uchar ctest5;
+	uchar ctest6;
+
+	uchar dbc[3];	/* 24 */
+	uchar dcmd;	/* 27 */
+
+	uchar dnad[4];	/* 28 */
+	uchar dsp[4];	/* 2c */
+	uchar dsps[4];	/* 30 */
+
+	uchar scratcha[4];	/* 34 */
+
+	uchar dmode;	/* 38 */
+	uchar dien;
+	uchar dwt;
+	uchar dcntl;
+
+	uchar adder[4];	/* 3c */
+
+	uchar sien0;	/* 40 */
+	uchar sien1;
+	uchar sist0;
+	uchar sist1;
+
+	uchar slpar;	/* 44 */
+	uchar slparpad0;
+	uchar macntl;
+	uchar gpcntl;
+
+	uchar stime0;	/* 48 */
+	uchar stime1;
+	uchar respid;
+	uchar respidpad0;
+
+	uchar stest0;	/* 4c */
+	uchar stest1;
+	uchar stest2;
+	uchar stest3;
+
+	uchar sidl;	/* 50 */
+	uchar sidlpad[3];
+
+	uchar sodl;	/* 54 */
+	uchar sodlpad[3];
+
+	uchar sbdl;	/* 58 */
+	uchar sbdlpad[3];
+
+	uchar scratchb[4];	/* 5c */
+} Ncr;
+
+typedef struct Movedata {
+	uchar dbc[4];
+	uchar pa[4];
+} Movedata;
+
+typedef enum NegoState {
+	NeitherDone, WideInit, WideResponse, WideDone,
+	SyncInit, SyncResponse, BothDone
+} NegoState;
+
+typedef enum State {
+	Allocated, Queued, Active, Done
+} State;
+
+typedef struct Dsa {
+	union {
+		uchar state[4];
+		struct {
+			uchar stateb;
+			uchar result;
+			uchar dmablks;
+			uchar flag;	/* setbyte(state,3,...) */
+		};
+	};
+
+	union {
+		ulong dmancr;		/* For block transfer: NCR order (little-endian) */
+		uchar dmaaddr[4];
+	};
+
+	uchar target;			/* Target */
+	uchar pad0[3];
+
+	uchar lun;			/* Logical Unit Number */
+	uchar pad1[3];
+
+	uchar scntl3;
+	uchar sxfer;
+	uchar pad2[2];
+
+	uchar next[4];			/* chaining for SCRIPT (NCR byte order) */
+	struct Dsa *freechain;		/* chaining for freelist */
+	Rendez;
+	uchar scsi_id_buf[4];
+	Movedata msg_out_buf;
+	Movedata cmd_buf;
+	Movedata data_buf;
+	Movedata status_buf;
+	uchar msg_out[10];		/* enough to include SDTR */
+	uchar status;
+	int p9status;
+	uchar parityerror;
+} Dsa;
+
+typedef enum Feature {
+	BigFifo = 1,			/* 536 byte fifo */
+	BurstOpCodeFetch = 2,		/* burst fetch opcodes */
+	Prefetch = 4,			/* prefetch 8 longwords */
+	LocalRAM = 8,			/* 4K longwords of local RAM */
+	Differential = 16,		/* Differential support */
+	Wide = 32,			/* Wide capable */
+	Ultra = 64,			/* Ultra capable */
+	ClockDouble = 128,		/* Has clock doubler */
+	ClockQuad = 256,		/* Has clock quadrupler (same as Ultra2) */
+	Ultra2 = 256,
+} Feature;
+
+typedef enum Burst {
+	Burst2 = 0,
+	Burst4 = 1,
+	Burst8 = 2,
+	Burst16 = 3,
+	Burst32 = 4,
+	Burst64 = 5,
+	Burst128 = 6
+} Burst;
+
+typedef struct Variant {
+	ushort did;
+	uchar maxrid;			/* maximum allowed revision ID */
+	char *name;
+	Burst burst;			/* codings for max burst */
+	uchar maxsyncoff;		/* max synchronous offset */
+	uchar registers;		/* number of 32 bit registers */
+	unsigned feature;
+} Variant;
+
+static unsigned char cf2[] = { 6, 2, 3, 4, 6, 8, 12, 16 };
+#define NULTRA2SCF (sizeof(cf2)/sizeof(cf2[0]))
+#define NULTRASCF (NULTRA2SCF - 2)
+#define NSCF (NULTRASCF - 1)
+
+typedef struct Controller {
+	Lock;
+	struct {
+		uchar scntl3;
+		uchar stest2;
+	} bios;
+	uchar synctab[NULTRA2SCF - 1][8];/* table of legal tpfs */
+	NegoState s[MAXTARGET];
+	uchar scntl3[MAXTARGET];
+	uchar sxfer[MAXTARGET];
+	uchar cap[MAXTARGET];		/* capabilities byte from Identify */
+	ushort capvalid;		/* bit per target for validity of cap[] */
+	ushort wide;			/* bit per target set if wide negotiated */
+	ulong sclk;			/* clock speed of controller */
+	uchar clockmult;		/* set by synctabinit */
+	uchar ccf;			/* CCF bits */
+	uchar tpf;			/* best tpf value for this controller */
+	uchar feature;			/* requested features */
+	int running;			/* is the script processor running? */
+	int ssm;			/* single step mode */
+	Ncr *n;				/* pointer to registers */
+	Variant *v;			/* pointer to variant type */
+	ulong *script;			/* where the real script is */
+	ulong scriptpa;			/* where the real script is */
+	Pcidev* pcidev;
+	SDev*	sdev;
+
+	struct {
+		Lock;
+		uchar head[4];		/* head of free list (NCR byte order) */
+		Dsa	*tail;
+		Dsa	*freechain;
+	} dsalist;
+
+	QLock q[MAXTARGET];		/* queues for each target */
+} Controller;
+
+static Controller controller;
+
+/* ISTAT */
+enum { Abrt = 0x80, Srst = 0x40, Sigp = 0x20, Sem = 0x10, Con = 0x08, Intf = 0x04, Sip = 0x02, Dip = 0x01 };
+
+/* DSTAT */
+enum { Dfe = 0x80, Mdpe = 0x40, Bf = 0x20, Abrted = 0x10, Ssi = 0x08, Sir = 0x04, Iid = 0x01 };
+
+/* SSTAT */
+enum { DataOut, DataIn, Cmd, Status, ReservedOut, ReservedIn, MessageOut, MessageIn };
+
+static void setmovedata(Movedata*, ulong, ulong);
+static void advancedata(Movedata*, long);
+static int bios_set_differential(Controller *c);
+
+static char *phase[] = {
+	"data out", "data in", "command", "status",
+	"reserved out", "reserved in", "message out", "message in"
+};
+
+#ifdef BOOTDEBUG
+#define DEBUGSIZE 10240
+char debugbuf[DEBUGSIZE];
+char *debuglast;
+
+static void
+intrprint(char *format, ...)
+{
+	if (debuglast == 0)
+		debuglast = debugbuf;
+	debuglast = doprint(debuglast, debugbuf + (DEBUGSIZE - 1), format, (&format + 1));
+}
+
+static void
+iflush()
+{
+	int s;
+	char *endp;
+	s = splhi();
+	if (debuglast == 0)
+		debuglast = debugbuf;
+	if (debuglast == debugbuf) {
+		splx(s);
+		return;
+	}
+	endp = debuglast;
+	splx(s);
+	screenputs(debugbuf, endp - debugbuf);
+	s = splhi();
+	memmove(debugbuf, endp, debuglast - endp);
+	debuglast -= endp - debugbuf;
+	splx(s);
+}
+
+static void
+oprint(char *format, ...)
+{
+	int s;
+
+	iflush();
+	s = splhi();
+	if (debuglast == 0)
+		debuglast = debugbuf;
+	debuglast = doprint(debuglast, debugbuf + (DEBUGSIZE - 1), format, (&format + 1));
+	splx(s);
+	iflush();	
+}
+#endif
+
+#include "sd53c8xx.i"
+
+static Dsa *
+dsaalloc(Controller *c, int target, int lun)
+{
+	Dsa *d;
+
+	ilock(&c->dsalist);
+	if ((d = c->dsalist.freechain) == 0) {
+		d = xalloc(sizeof(*d));
+		if (DEBUG(1))
+			KPRINT("sd53c8xx: %d/%d: allocated new dsa %lux\n", target, lun, d);
+		lesetl(d->next, 0);
+		lesetl(d->state, A_STATE_ALLOCATED);
+		if (legetl(c->dsalist.head) == 0)
+			lesetl(c->dsalist.head, DMASEG(d));	/* ATOMIC?!? */
+		else
+			lesetl(c->dsalist.tail->next, DMASEG(d));	/* ATOMIC?!? */
+		c->dsalist.tail = d;
+	}
+	else {
+		if (DEBUG(1))
+			KPRINT("sd53c8xx: %d/%d: reused dsa %lux\n", target, lun, d);
+		c->dsalist.freechain = d->freechain;
+		lesetl(d->state, A_STATE_ALLOCATED);
+	}
+	iunlock(&c->dsalist);
+	d->target = target;
+	d->lun = lun;
+	return d;
+}
+
+static void
+dsafree(Controller *c, Dsa *d)
+{
+	ilock(&c->dsalist);
+	d->freechain = c->dsalist.freechain;
+	c->dsalist.freechain = d;
+	lesetl(d->state, A_STATE_FREE);
+	iunlock(&c->dsalist);
+}
+
+static Dsa *
+dsafind(Controller *c, uchar target, uchar lun, uchar state)
+{
+	Dsa *d;
+	for (d = KPTR(legetl(c->dsalist.head)); d; d = KPTR(legetl(d->next))) {
+		if (d->target != 0xff && d->target != target)
+			continue;
+		if (lun != 0xff && d->lun != lun)
+			continue;
+		if (state != 0xff && d->stateb != state)
+			continue;
+		break;
+	}
+	return d;
+}
+
+static void
+dumpncrregs(Controller *c, int intr)
+{
+	int i;
+	Ncr *n = c->n;
+	int depth = c->v->registers / 4;
+
+	KPRINT("sa = %.8lux\n", c->scriptpa);
+	for (i = 0; i < depth; i++) {
+		int j;
+		for (j = 0; j < 4; j++) {
+			int k = j * depth + i;
+			uchar *p;
+
+			/* display little-endian to make 32-bit values readable */
+			p = (uchar*)n+k*4;
+			if (intr)
+				IPRINT(" %.2x%.2x%.2x%.2x %.2x %.2x", p[3], p[2], p[1], p[0], k * 4, (k * 4) + 0x80);
+			else
+				KPRINT(" %.2x%.2x%.2x%.2x %.2x %.2x", p[3], p[2], p[1], p[0], k * 4, (k * 4) + 0x80);
+			USED(p);
+		}
+		if (intr)
+			IPRINT("\n");
+		else
+			KPRINT("\n");
+	}
+}	
+
+static int
+chooserate(Controller *c, int tpf, int *scfp, int *xferpp)
+{
+	/* find lowest entry >= tpf */
+	int besttpf = 1000;
+	int bestscfi = 0;
+	int bestxferp = 0;
+	int scf, xferp;
+	int maxscf;
+
+	if (c->v->feature & Ultra2)
+		maxscf = NULTRA2SCF;
+	else if (c->v->feature & Ultra)
+		maxscf = NULTRASCF;
+	else
+		maxscf = NSCF;
+
+	/*
+	 * search large clock factors first since this should
+	 * result in more reliable transfers
+	 */
+	for (scf = maxscf; scf >= 1; scf--) {
+		for (xferp = 0; xferp < 8; xferp++) {
+			unsigned char v = c->synctab[scf - 1][xferp];
+			if (v == 0)
+				continue;
+			if (v >= tpf && v < besttpf) {
+				besttpf = v;
+				bestscfi = scf;
+				bestxferp = xferp;
+			}
+		}
+	}
+	if (besttpf == 1000)
+		return 0;
+	if (scfp)
+		*scfp = bestscfi;
+	if (xferpp)
+		*xferpp = bestxferp;
+	return besttpf;
+}
+
+static void
+synctabinit(Controller *c)
+{
+	int scf;
+	unsigned long scsilimit;
+	int xferp;
+	unsigned long cr, sr;
+	int tpf;
+	int fast;
+	int maxscf;
+
+	if (c->v->feature & Ultra2)
+		maxscf = NULTRA2SCF;
+	else if (c->v->feature & Ultra)
+		maxscf = NULTRASCF;
+	else
+		maxscf = NSCF;
+
+	/*
+	 * for chips with no clock doubler, but Ultra capable (e.g. 860, or interestingly the
+	 * first spin of the 875), assume 80MHz
+	 * otherwise use the internal (33 Mhz) or external (40MHz) default
+	 */
+
+	if ((c->v->feature & Ultra) != 0 && (c->v->feature & (ClockDouble | ClockQuad)) == 0)
+		c->sclk = ULTRA_NOCLOCKDOUBLE_SCLK;
+	else
+		c->sclk = SCLK;
+
+	/*
+	 * otherwise, if the chip is Ultra capable, but has a slow(ish) clock,
+	 * invoke the doubler
+	 */
+
+	if (SCLK <= 40000000) {
+		if (c->v->feature & ClockDouble) {
+			c->sclk *= 2;
+			c->clockmult = 1;
+		}
+		else if (c->v->feature & ClockQuad) {
+			c->sclk *= 4;
+			c->clockmult = 1;
+		}
+		else
+			c->clockmult = 0;
+	}
+	else
+		c->clockmult = 0;
+
+	/* derive CCF from sclk */
+	/* woebetide anyone with SCLK < 16.7 or > 80MHz */
+	if (c->sclk <= 25 * MEGA)
+		c->ccf = 1;
+	else if (c->sclk <= 3750000)
+		c->ccf = 2;
+	else if (c->sclk <= 50 * MEGA)
+		c->ccf = 3;
+	else if (c->sclk <= 75 * MEGA)
+		c->ccf = 4;
+	else if ((c->v->feature & ClockDouble) && c->sclk <= 80 * MEGA)
+		c->ccf = 5;
+	else if ((c->v->feature & ClockQuad) && c->sclk <= 120 * MEGA)
+		c->ccf = 6;
+	else if ((c->v->feature & ClockQuad) && c->sclk <= 160 * MEGA)
+		c->ccf = 7;
+
+	for (scf = 1; scf < maxscf; scf++) {
+		/* check for legal core rate */
+		/* round up so we run slower for safety */
+	   	cr = (c->sclk * 2 + cf2[scf] - 1) / cf2[scf];
+		if (cr <= MAXSYNCCORERATE) {
+			scsilimit = MAXSYNCSCSIRATE;
+			fast = 0;
+		}
+		else if (cr <= MAXFASTSYNCCORERATE) {
+			scsilimit = MAXFASTSYNCSCSIRATE;
+			fast = 1;
+		}
+		else if ((c->v->feature & Ultra) && cr <= MAXULTRASYNCCORERATE) {
+			scsilimit = MAXULTRASYNCSCSIRATE;
+			fast = 2;
+		}
+		else if ((c->v->feature & Ultra2) && cr <= MAXULTRA2SYNCCORERATE) {
+			scsilimit = MAXULTRA2SYNCSCSIRATE;
+			fast = 3;
+		}
+		else
+			continue;
+		for (xferp = 11; xferp >= 4; xferp--) {
+			int ok;
+			int tp;
+			/* calculate scsi rate - round up again */
+			/* start from sclk for accuracy */
+			int totaldivide = xferp * cf2[scf];
+			sr = (c->sclk * 2 + totaldivide - 1) / totaldivide;
+			if (sr > scsilimit)
+				break;
+			/*
+			 * now work out transfer period
+			 * round down now so that period is pessimistic
+			 */
+			tp = (MEGA * 1000) / sr;
+			/*
+			 * bounds check it
+			 */
+			if (tp < 25 || tp > 255 * 4)
+				continue;
+			/*
+			 * spot stupid special case for Ultra or Ultra2
+			 * while working out factor
+			 */
+			if (tp == 25)
+				tpf = 10;
+			else if (tp == 50)
+				tpf = 12;
+			else if (tp < 52)
+				continue;
+			else
+				tpf = tp / 4;
+			/*
+			 * now check tpf looks sensible
+			 * given core rate
+			 */
+			switch (fast) {
+			case 0:
+				/* scf must be ccf for SCSI 1 */
+				ok = tpf >= 50 && scf == c->ccf;
+				break;
+			case 1:
+				ok = tpf >= 25 && tpf < 50;
+				break;
+			case 2:
+				/*
+				 * must use xferp of 4, or 5 at a pinch
+				 * for an Ultra transfer
+				 */
+				ok = xferp <= 5 && tpf >= 12 && tpf < 25;
+				break;
+			case 3:
+				ok = xferp == 4 && (tpf == 10 || tpf == 11);
+				break;
+			default:
+				ok = 0;
+			}
+			if (!ok)
+				continue;
+			c->synctab[scf - 1][xferp - 4] = tpf;
+		}
+	}
+
+#ifndef NO_ULTRA2
+	if (c->v->feature & Ultra2)
+		tpf = 10;
+	else
+#endif
+	if (c->v->feature & Ultra)
+		tpf = 12;
+	else
+		tpf = 25;
+	for (; tpf < 256; tpf++) {
+		if (chooserate(c, tpf, &scf, &xferp) == tpf) {
+			unsigned tp = tpf == 10 ? 25 : (tpf == 12 ? 50 : tpf * 4);
+			unsigned long khz = (MEGA + tp - 1) / (tp);
+			KPRINT("sd53c8xx: tpf=%d scf=%d.%.1d xferp=%d mhz=%ld.%.3ld\n",
+			    tpf, cf2[scf] / 2, (cf2[scf] & 1) ? 5 : 0,
+			    xferp + 4, khz / 1000, khz % 1000);
+			USED(khz);
+			if (c->tpf == 0)
+				c->tpf = tpf;	/* note lowest value for controller */
+		}
+	}
+}
+
+static void
+synctodsa(Dsa *dsa, Controller *c)
+{
+/*
+	KPRINT("synctodsa(dsa=%lux, target=%d, scntl3=%.2lx sxfer=%.2x)\n",
+	    dsa, dsa->target, c->scntl3[dsa->target], c->sxfer[dsa->target]);
+*/
+	dsa->scntl3 = c->scntl3[dsa->target];
+	dsa->sxfer = c->sxfer[dsa->target];
+}
+
+static void
+setsync(Dsa *dsa, Controller *c, int target, uchar ultra, uchar scf, uchar xferp, uchar reqack)
+{
+	c->scntl3[target] =
+	    (c->scntl3[target] & 0x08) | (((scf << 4) | c->ccf | (ultra << 7)) & ~0x08);
+	c->sxfer[target] = (xferp << 5) | reqack;
+	c->s[target] = BothDone;
+	if (dsa) {
+		synctodsa(dsa, c);
+		c->n->scntl3 = c->scntl3[target];
+		c->n->sxfer = c->sxfer[target];
+	}
+}
+
+static void
+setasync(Dsa *dsa, Controller *c, int target)
+{
+	setsync(dsa, c, target, 0, c->ccf, 0, 0);
+}
+
+static void
+setwide(Dsa *dsa, Controller *c, int target, uchar wide)
+{
+	c->scntl3[target] = wide ? (1 << 3) : 0;
+	setasync(dsa, c, target);
+	c->s[target] = WideDone;
+}
+
+static int
+buildsdtrmsg(uchar *buf, uchar tpf, uchar offset)
+{
+	*buf++ = X_MSG;
+	*buf++ = 3;
+	*buf++ = X_MSG_SDTR;
+	*buf++ = tpf;
+	*buf = offset;
+	return 5;
+}
+
+static int
+buildwdtrmsg(uchar *buf, uchar expo)
+{
+	*buf++ = X_MSG;
+	*buf++ = 2;
+	*buf++ = X_MSG_WDTR;
+	*buf = expo;
+	return 4;
+}
+
+static void
+start(Controller *c, long entry)
+{
+	ulong p;
+
+	if (c->running)
+		panic("sd53c8xx: start called while running");
+	c->running = 1;
+	p = c->scriptpa + entry;
+	lesetl(c->n->dsp, p);
+	if (c->ssm)
+		c->n->dcntl |= 0x4;		/* start DMA in SSI mode */
+}
+
+static void
+ncrcontinue(Controller *c)
+{
+	if (c->running)
+		panic("sd53c8xx: ncrcontinue called while running");
+	/* set the start DMA bit to continue execution */
+	c->running = 1;
+	c->n->dcntl |= 0x4;
+}
+
+static void
+softreset(Controller *c)
+{
+	Ncr *n = c->n;
+
+	n->istat = Srst;		/* software reset */
+	n->istat = 0;
+	/* general initialisation */
+	n->scid = (1 << 6) | 7;		/* respond to reselect, ID 7 */
+	n->respid = 1 << 7;		/* response ID = 7 */
+
+#ifdef INTERNAL_SCLK
+	n->stest1 = 0x80;		/* disable external scsi clock */
+#else
+	n->stest1 = 0x00;
+#endif
+
+	n->stime0 = 0xdd;		/* about 0.5 second timeout on each device */
+	n->scntl0 |= 0x8;		/* Enable parity checking */
+
+	/* continued setup */
+	n->sien0 = 0x8f;
+	n->sien1 = 0x04;
+	n->dien = 0x7d;
+	n->stest3 = 0x80;		/* TolerANT enable */
+	c->running = 0;
+
+	if (c->v->feature & BigFifo)
+		n->ctest5 = (1 << 5);
+	n->dmode = c->v->burst << 6;	/* set burst length bits */
+	if (c->v->burst & 4)
+		n->ctest5 |= (1 << 2);	/* including overflow into ctest5 bit 2 */
+	if (c->v->feature & Prefetch)
+		n->dcntl |= (1 << 5);	/* prefetch enable */
+	else if (c->v->feature & BurstOpCodeFetch)
+		n->dmode |= (1 << 1);	/* burst opcode fetch */
+	if (c->v->feature & Differential) {
+		/* chip capable */
+		if ((c->feature & Differential) || bios_set_differential(c)) {
+			/* user enabled, or some evidence bios set differential */
+			if (n->sstat2 & (1 << 2))
+				print("sd53c8xx: can't go differential; wrong cable\n");
+			else {
+				n->stest2 = (1 << 5);
+				print("sd53c8xx: differential mode set\n");
+			}
+		}
+	}
+	if (c->clockmult) {
+		n->stest1 |= (1 << 3);	/* power up doubler */
+		delay(2);
+		n->stest3 |= (1 << 5);	/* stop clock */
+		n->stest1 |= (1 << 2);	/* enable doubler */
+		n->stest3 &= ~(1 << 5);	/* start clock */
+		/* pray */
+	}
+}
+
+static void
+msgsm(Dsa *dsa, Controller *c, int msg, int *cont, int *wakeme)
+{
+	uchar histpf, hisreqack;
+	int tpf;
+	int scf, xferp;
+	int len;
+
+	Ncr *n = c->n;
+
+	switch (c->s[dsa->target]) {
+	case SyncInit:
+		switch (msg) {
+		case A_SIR_MSG_SDTR:
+			/* reply to my SDTR */
+			histpf = n->scratcha[2];
+			hisreqack = n->scratcha[3];
+			KPRINT("sd53c8xx: %d: SDTN response %d %d\n",
+			    dsa->target, histpf, hisreqack);
+
+			if (hisreqack == 0)
+				setasync(dsa, c, dsa->target);
+			else {
+				/* hisreqack should be <= c->v->maxsyncoff */
+				tpf = chooserate(c, histpf, &scf, &xferp);
+				KPRINT("sd53c8xx: %d: SDTN: using %d %d\n",
+				    dsa->target, tpf, hisreqack);
+				setsync(dsa, c, dsa->target, tpf < 25, scf, xferp, hisreqack);
+			}
+			*cont = -2;
+			return;
+		case A_SIR_EV_PHASE_SWITCH_AFTER_ID:
+			/* target ignored ATN for message after IDENTIFY - not SCSI-II */
+			KPRINT("sd53c8xx: %d: illegal phase switch after ID message - SCSI-1 device?\n", dsa->target);
+			KPRINT("sd53c8xx: %d: SDTN: async\n", dsa->target);
+			setasync(dsa, c, dsa->target);
+			*cont = E_to_decisions;
+			return;
+		case A_SIR_MSG_REJECT:
+			/* rejection of my SDTR */
+			KPRINT("sd53c8xx: %d: SDTN: rejected SDTR\n", dsa->target);
+		//async:
+			KPRINT("sd53c8xx: %d: SDTN: async\n", dsa->target);
+			setasync(dsa, c, dsa->target);
+			*cont = -2;
+			return;
+		}
+		break;
+	case WideInit:
+		switch (msg) {
+		case A_SIR_MSG_WDTR:
+			/* reply to my WDTR */
+			KPRINT("sd53c8xx: %d: WDTN: response %d\n",
+			    dsa->target, n->scratcha[2]);
+			setwide(dsa, c, dsa->target, n->scratcha[2]);
+			*cont = -2;
+			return;
+		case A_SIR_EV_PHASE_SWITCH_AFTER_ID:
+			/* target ignored ATN for message after IDENTIFY - not SCSI-II */
+			KPRINT("sd53c8xx: %d: illegal phase switch after ID message - SCSI-1 device?\n", dsa->target);
+			setwide(dsa, c, dsa->target, 0);
+			*cont = E_to_decisions;
+			return;
+		case A_SIR_MSG_REJECT:
+			/* rejection of my SDTR */
+			KPRINT("sd53c8xx: %d: WDTN: rejected WDTR\n", dsa->target);
+			setwide(dsa, c, dsa->target, 0);
+			*cont = -2;
+			return;
+		}
+		break;
+
+	case NeitherDone:
+	case WideDone:
+	case BothDone:
+		switch (msg) {
+		case A_SIR_MSG_WDTR: {
+			uchar hiswide, mywide;
+			hiswide = n->scratcha[2];
+			mywide = (c->v->feature & Wide) != 0;
+			KPRINT("sd53c8xx: %d: WDTN: target init %d\n",
+			    dsa->target, hiswide);
+			if (hiswide < mywide)
+				mywide = hiswide;
+			KPRINT("sd53c8xx: %d: WDTN: responding %d\n",
+			    dsa->target, mywide);
+			setwide(dsa, c, dsa->target, mywide);
+			len = buildwdtrmsg(dsa->msg_out, mywide);
+			setmovedata(&dsa->msg_out_buf, DMASEG(dsa->msg_out), len);
+			*cont = E_response;
+			c->s[dsa->target] = WideResponse;
+			return;
+		}
+		case A_SIR_MSG_SDTR:
+#ifdef ASYNC_ONLY
+			*cont = E_reject;
+			return;
+#else
+			/* target decides to renegotiate */
+			histpf = n->scratcha[2];
+			hisreqack = n->scratcha[3];
+			KPRINT("sd53c8xx: %d: SDTN: target init %d %d\n",
+			    dsa->target, histpf, hisreqack);
+			if (hisreqack == 0) {
+				/* he wants asynchronous */
+				setasync(dsa, c, dsa->target);
+				tpf = 0;
+			}
+			else {
+				/* he wants synchronous */
+				tpf = chooserate(c, histpf, &scf, &xferp);
+				if (hisreqack > c->v->maxsyncoff)
+					hisreqack = c->v->maxsyncoff;
+				KPRINT("sd53c8xx: %d: using %d %d\n",
+				    dsa->target, tpf, hisreqack);
+				setsync(dsa, c, dsa->target, tpf < 25, scf, xferp, hisreqack);
+			}
+			/* build my SDTR message */
+			len = buildsdtrmsg(dsa->msg_out, tpf, hisreqack);
+			setmovedata(&dsa->msg_out_buf, DMASEG(dsa->msg_out), len);
+			*cont = E_response;
+			c->s[dsa->target] = SyncResponse;
+			return;
+#endif
+		}
+		break;
+	case WideResponse:
+		switch (msg) {
+		case A_SIR_EV_RESPONSE_OK:
+			c->s[dsa->target] = WideDone;
+			KPRINT("sd53c8xx: %d: WDTN: response accepted\n", dsa->target);
+			*cont = -2;
+			return;
+		case A_SIR_MSG_REJECT:
+			setwide(dsa, c, dsa->target, 0);
+			KPRINT("sd53c8xx: %d: WDTN: response REJECTed\n", dsa->target);
+			*cont = -2;
+			return;
+		}
+		break;
+	case SyncResponse:
+		switch (msg) {
+		case A_SIR_EV_RESPONSE_OK:
+			c->s[dsa->target] = BothDone;
+			KPRINT("sd53c8xx: %d: SDTN: response accepted (%s)\n",
+			    dsa->target, phase[n->sstat1 & 7]);
+			*cont = -2;
+			return;	/* chf */
+		case A_SIR_MSG_REJECT:
+			setasync(dsa, c, dsa->target);
+			KPRINT("sd53c8xx: %d: SDTN: response REJECTed\n", dsa->target);
+			*cont = -2;
+			return;
+		}
+		break;
+	}
+	KPRINT("sd53c8xx: %d: msgsm: state %d msg %d\n",
+	    dsa->target, c->s[dsa->target], msg);
+	*wakeme = 1;
+	return;
+}
+
+static void
+calcblockdma(Dsa *d, ulong base, ulong count)
+{
+	ulong blocks;
+	if (DEBUG(3))
+		blocks = 0;
+	else {
+		blocks = count / A_BSIZE;
+		if (blocks > 255)
+			blocks = 255;
+	}
+	d->dmablks = blocks;
+	d->dmaaddr[0] = base;
+	d->dmaaddr[1] = base >> 8;
+	d->dmaaddr[2] = base >> 16;
+	d->dmaaddr[3] = base >> 24;
+	setmovedata(&d->data_buf, base + blocks * A_BSIZE, count - blocks * A_BSIZE);
+	if (legetl(d->data_buf.dbc) == 0)
+		d->flag = 1;
+}
+
+static ulong
+read_mismatch_recover(Controller *c, Ncr *n, Dsa *dsa)
+{
+	ulong dbc;
+	uchar dfifo = n->dfifo;
+	int inchip;
+
+	dbc = (n->dbc[2]<<16)|(n->dbc[1]<<8)|n->dbc[0];
+	if (n->ctest5 & (1 << 5))
+		inchip = ((dfifo | ((n->ctest5 & 3) << 8)) - (dbc & 0x3ff)) & 0x3ff;
+	else
+		inchip = ((dfifo & 0x7f) - (dbc & 0x7f)) & 0x7f;
+	if (inchip) {
+		IPRINT("sd53c8xx: %d/%d: read_mismatch_recover: DMA FIFO = %d\n",
+		    dsa->target, dsa->lun, inchip);
+	}
+	if (n->sxfer & 0xf) {
+		/* SCSI FIFO */
+		uchar fifo = n->sstat1 >> 4;
+		if (c->v->maxsyncoff > 8)
+			fifo |= (n->sstat2 & (1 << 4));
+		if (fifo) {
+			inchip += fifo;
+			IPRINT("sd53c8xx: %d/%d: read_mismatch_recover: SCSI FIFO = %d\n",
+			    dsa->target, dsa->lun, fifo);
+		}
+	}
+	else {
+		if (n->sstat0 & (1 << 7)) {
+			inchip++;
+			IPRINT("sd53c8xx: %d/%d: read_mismatch_recover: SIDL full\n",
+			    dsa->target, dsa->lun);
+		}
+		if (n->sstat2 & (1 << 7)) {
+			inchip++;
+			IPRINT("sd53c8xx: %d/%d: read_mismatch_recover: SIDL msb full\n",
+			    dsa->target, dsa->lun);
+		}
+	}
+	USED(inchip);
+	return dbc;
+}
+
+static ulong
+write_mismatch_recover(Ncr *n, Dsa *dsa)
+{
+	ulong dbc;
+	uchar dfifo = n->dfifo;
+	int inchip;
+
+	dbc = (n->dbc[2]<<16)|(n->dbc[1]<<8)|n->dbc[0];
+	USED(dsa);
+	if (n->ctest5 & (1 << 5))
+		inchip = ((dfifo | ((n->ctest5 & 3) << 8)) - (dbc & 0x3ff)) & 0x3ff;
+	else
+		inchip = ((dfifo & 0x7f) - (dbc & 0x7f)) & 0x7f;
+#ifdef WMR_DEBUG
+	if (inchip) {
+		IPRINT("sd53c8xx: %d/%d: write_mismatch_recover: DMA FIFO = %d\n",
+		    dsa->target, dsa->lun, inchip);
+	}
+#endif
+	if (n->sstat0 & (1 << 5)) {
+		inchip++;
+#ifdef WMR_DEBUG
+		IPRINT("sd53c8xx: %d/%d: write_mismatch_recover: SODL full\n", dsa->target, dsa->lun);
+#endif
+	}
+	if (n->sstat2 & (1 << 5)) {
+		inchip++;
+#ifdef WMR_DEBUG
+		IPRINT("sd53c8xx: %d/%d: write_mismatch_recover: SODL msb full\n", dsa->target, dsa->lun);
+#endif
+	}
+	if (n->sxfer & 0xf) {
+		/* synchronous SODR */
+		if (n->sstat0 & (1 << 6)) {
+			inchip++;
+#ifdef WMR_DEBUG
+			IPRINT("sd53c8xx: %d/%d: write_mismatch_recover: SODR full\n",
+			    dsa->target, dsa->lun);
+#endif
+		}
+		if (n->sstat2 & (1 << 6)) {
+			inchip++;
+#ifdef WMR_DEBUG
+			IPRINT("sd53c8xx: %d/%d: write_mismatch_recover: SODR msb full\n",
+			    dsa->target, dsa->lun);
+#endif
+		}
+	}
+	/* clear the dma fifo */
+	n->ctest3 |= (1 << 2);
+	/* wait till done */
+	while ((n->dstat & Dfe) == 0)
+		;
+	return dbc + inchip;
+}
+
+static void
+interrupt(Ureg *ur, void *a)
+{
+	uchar istat;
+	ushort sist;
+	uchar dstat;
+	int wakeme = 0;
+	int cont = -1;
+	Dsa *dsa;
+	Controller *c = a;
+	Ncr *n = c->n;
+
+	USED(ur);
+	if (DEBUG(1))
+		IPRINT("sd53c8xx: int\n");
+	ilock(c);
+	istat = n->istat;
+	if (istat & Intf) {
+		Dsa *d;
+		int wokesomething = 0;
+		if (DEBUG(1))
+			IPRINT("sd53c8xx: Intfly\n");
+		n->istat = Intf;
+		/* search for structures in A_STATE_DONE */
+		for (d = KPTR(legetl(c->dsalist.head)); d; d = KPTR(legetl(d->next))) {
+			if (d->stateb == A_STATE_DONE) {
+				d->p9status = d->status;
+				if (DEBUG(1))
+					IPRINT("sd53c8xx: waking up dsa %lux\n", d);
+				wakeup(d);
+				wokesomething = 1;
+			}
+		}
+		if (!wokesomething)
+			IPRINT("sd53c8xx: nothing to wake up\n");
+	}
+
+	if ((istat & (Sip | Dip)) == 0) {
+		if (DEBUG(1))
+			IPRINT("sd53c8xx: int end %x\n", istat);
+		iunlock(c);
+		return;
+	}
+
+	sist = (n->sist1<<8)|n->sist0;	/* BUG? can two-byte read be inconsistent? */
+	dstat = n->dstat;
+	dsa = (Dsa *)DMASEG_TO_KADDR(legetl(n->dsa));
+	c->running = 0;
+	if (istat & Sip) {
+		if (DEBUG(1))
+			IPRINT("sist = %.4x\n", sist);
+		if (sist & 0x80) {
+			ulong addr;
+			ulong sa;
+			ulong dbc;
+			ulong tbc;
+			int dmablks;
+			ulong dmaaddr;
+
+			addr = legetl(n->dsp);
+			sa = addr - c->scriptpa;
+			if (DEBUG(1) || DEBUG(2))
+				IPRINT("sd53c8xx: %d/%d: Phase Mismatch sa=%.8lux\n",
+				    dsa->target, dsa->lun, sa);
+			/*
+			 * now recover
+			 */
+			if (sa == E_data_in_mismatch) {
+				dbc = read_mismatch_recover(c, n, dsa);
+				tbc = legetl(dsa->data_buf.dbc) - dbc;
+				advancedata(&dsa->data_buf, tbc);
+				if (DEBUG(1) || DEBUG(2))
+					IPRINT("sd53c8xx: %d/%d: transferred = %ld residue = %ld\n",
+					    dsa->target, dsa->lun, tbc, legetl(dsa->data_buf.dbc));
+				cont = E_to_decisions;
+			}
+			else if (sa == E_data_in_block_mismatch) {
+				dbc = read_mismatch_recover(c, n, dsa);
+				tbc = A_BSIZE - dbc;
+				/* recover current state from registers */
+				dmablks = n->scratcha[2];
+				dmaaddr = legetl(n->scratchb);
+				/* we have got to dmaaddr + tbc */
+				/* we have dmablks * A_BSIZE - tbc + residue left to do */
+				/* so remaining transfer is */
+				IPRINT("in_block_mismatch: dmaaddr = 0x%lux tbc=%lud dmablks=%d\n",
+				    dmaaddr, tbc, dmablks);
+				calcblockdma(dsa, dmaaddr + tbc,
+				    dmablks * A_BSIZE - tbc + legetl(dsa->data_buf.dbc));
+				/* copy changes into scratch registers */
+				IPRINT("recalc: dmablks %d dmaaddr 0x%lx pa 0x%lx dbc %ld\n",
+				    dsa->dmablks, legetl(dsa->dmaaddr),
+				    legetl(dsa->data_buf.pa), legetl(dsa->data_buf.dbc));
+				n->scratcha[2] = dsa->dmablks;
+				lesetl(n->scratchb, dsa->dmancr);
+				cont = E_data_block_mismatch_recover;
+			}
+			else if (sa == E_data_out_mismatch) {
+				dbc = write_mismatch_recover(n, dsa);
+				tbc = legetl(dsa->data_buf.dbc) - dbc;
+				advancedata(&dsa->data_buf, tbc);
+				if (DEBUG(1) || DEBUG(2))
+					IPRINT("sd53c8xx: %d/%d: transferred = %ld residue = %ld\n",
+					    dsa->target, dsa->lun, tbc, legetl(dsa->data_buf.dbc));
+				cont = E_to_decisions;
+			}
+			else if (sa == E_data_out_block_mismatch) {
+				dbc = write_mismatch_recover(n, dsa);
+				tbc = legetl(dsa->data_buf.dbc) - dbc;
+				/* recover current state from registers */
+				dmablks = n->scratcha[2];
+				dmaaddr = legetl(n->scratchb);
+				/* we have got to dmaaddr + tbc */
+				/* we have dmablks blocks - tbc + residue left to do */
+				/* so remaining transfer is */
+				IPRINT("out_block_mismatch: dmaaddr = %lux tbc=%lud dmablks=%d\n",
+				    dmaaddr, tbc, dmablks);
+				calcblockdma(dsa, dmaaddr + tbc,
+				    dmablks * A_BSIZE - tbc + legetl(dsa->data_buf.dbc));
+				/* copy changes into scratch registers */
+				n->scratcha[2] = dsa->dmablks;
+				lesetl(n->scratchb, dsa->dmancr);
+				cont = E_data_block_mismatch_recover;
+			}
+			else if (sa == E_id_out_mismatch) {
+				/*
+				 * target switched phases while attention held during
+				 * message out. The possibilities are:
+				 * 1. It didn't like the last message. This is indicated
+				 *    by the new phase being message_in. Use script to recover
+				 *
+				 * 2. It's not SCSI-II compliant. The new phase will be other
+				 *    than message_in. We should also indicate that the device
+				 *    is asynchronous, if it's the SDTR that got ignored
+				 * 
+				 * For now, if the phase switch is not to message_in, and
+				 * and it happens after IDENTIFY and before SDTR, we
+				 * notify the negotiation state machine.
+				 */
+				ulong lim = legetl(dsa->msg_out_buf.dbc);
+				uchar p = n->sstat1 & 7;
+				dbc = write_mismatch_recover(n, dsa);
+				tbc = lim - dbc;
+				IPRINT("sd53c8xx: %d/%d: msg_out_mismatch: %lud/%lud sent, phase %s\n",
+				    dsa->target, dsa->lun, tbc, lim, phase[p]);
+				if (p != MessageIn && tbc == 1) {
+					msgsm(dsa, c, A_SIR_EV_PHASE_SWITCH_AFTER_ID, &cont, &wakeme);
+				}
+				else
+					cont = E_id_out_mismatch_recover;
+			}
+			else if (sa == E_cmd_out_mismatch) {
+				/*
+				 * probably the command count is longer than the device wants ...
+				 */
+				ulong lim = legetl(dsa->cmd_buf.dbc);
+				uchar p = n->sstat1 & 7;
+				dbc = write_mismatch_recover(n, dsa);
+				tbc = lim - dbc;
+				IPRINT("sd53c8xx: %d/%d: cmd_out_mismatch: %lud/%lud sent, phase %s\n",
+				    dsa->target, dsa->lun, tbc, lim, phase[p]);
+				USED(p, tbc);
+				cont = E_to_decisions;
+			}
+			else {
+				IPRINT("sd53c8xx: %d/%d: ma sa=%.8lux wanted=%s got=%s\n",
+				    dsa->target, dsa->lun, sa,
+				    phase[n->dcmd & 7],
+				    phase[n->sstat1 & 7]);
+				dumpncrregs(c, 1);
+				dsa->p9status = SDeio;	/* chf */
+				wakeme = 1;
+			}
+		}
+		/*else*/ if (sist & 0x400) {
+			if (DEBUG(0))
+				IPRINT("sd53c8xx: %d/%d Sto\n", dsa->target, dsa->lun);
+			dsa->p9status = SDtimeout;
+			dsa->stateb = A_STATE_DONE;
+			softreset(c);
+			cont = E_issue_check;
+			wakeme = 1;
+		}
+		if (sist & 0x1) {
+			IPRINT("sd53c8xx: %d/%d: parity error\n", dsa->target, dsa->lun);
+			dsa->parityerror = 1;
+		}
+		if (sist & 0x4) {
+			IPRINT("sd53c8xx: %d/%d: unexpected disconnect\n",
+			    dsa->target, dsa->lun);
+			dumpncrregs(c, 1);
+			//wakeme = 1;
+			dsa->p9status = SDeio;
+		}
+	}
+	if (istat & Dip) {
+		if (DEBUG(1))
+			IPRINT("dstat = %.2x\n", dstat);
+		/*else*/ if (dstat & Ssi) {
+			ulong *p = DMASEG_TO_KADDR(legetl(n->dsp));
+			ulong w = (uchar *)p - (uchar *)c->script;
+			IPRINT("[%lux]", w);
+			USED(w);
+			cont = -2;	/* restart */
+		}
+		if (dstat & Sir) {
+			switch (legetl(n->dsps)) {
+			case A_SIR_MSG_IO_COMPLETE:
+				dsa->p9status = dsa->status;
+				wakeme = 1;
+				break;
+			case A_SIR_MSG_SDTR:
+			case A_SIR_MSG_WDTR:
+			case A_SIR_MSG_REJECT:
+			case A_SIR_EV_RESPONSE_OK:
+				msgsm(dsa, c, legetl(n->dsps), &cont, &wakeme);
+				break;
+			case A_SIR_MSG_IGNORE_WIDE_RESIDUE:
+				/* back up one in the data transfer */
+				IPRINT("sd53c8xx: %d/%d: ignore wide residue %d, WSR = %d\n",
+				    dsa->target, dsa->lun, n->scratcha[1], n->scntl2 & 1);
+				if (dsa->dmablks == 0 && dsa->flag)
+					IPRINT("sd53c8xx: %d/%d: transfer over; residue ignored\n",
+					    dsa->target, dsa->lun);
+				else
+					calcblockdma(dsa, legetl(dsa->dmaaddr) - 1,
+					    dsa->dmablks * A_BSIZE + legetl(dsa->data_buf.dbc) + 1);
+				cont = -2;
+				break;
+			case A_SIR_ERROR_NOT_MSG_IN_AFTER_RESELECT:
+				IPRINT("sd53c8xx: %d: not msg_in after reselect (%s)",
+				    n->ssid & 7, phase[n->sstat1 & 7]);
+				dsa = dsafind(c, n->ssid & 7, -1, A_STATE_DISCONNECTED);
+				dumpncrregs(c, 1);
+				wakeme = 1;
+				break;
+			case A_SIR_NOTIFY_MSG_IN:
+				IPRINT("sd53c8xx: %d/%d: msg_in %d\n",
+				    dsa->target, dsa->lun, n->sfbr);
+				cont = -2;
+				break;
+			case A_SIR_NOTIFY_DISC:
+				IPRINT("sd53c8xx: %d/%d: disconnect:", dsa->target, dsa->lun);
+				goto dsadump;
+			case A_SIR_NOTIFY_STATUS:
+				IPRINT("sd53c8xx: %d/%d: status\n", dsa->target, dsa->lun);
+				cont = -2;
+				break;
+			case A_SIR_NOTIFY_COMMAND:
+				IPRINT("sd53c8xx: %d/%d: commands\n", dsa->target, dsa->lun);
+				cont = -2;
+				break;
+			case A_SIR_NOTIFY_DATA_IN:
+				IPRINT("sd53c8xx: %d/%d: data in a %lx b %lx\n",
+				    dsa->target, dsa->lun, legetl(n->scratcha), legetl(n->scratchb));
+				cont = -2;
+				break;
+			case A_SIR_NOTIFY_BLOCK_DATA_IN:
+				IPRINT("sd53c8xx: %d/%d: block data in: a2 %x b %lx\n",
+				    dsa->target, dsa->lun, n->scratcha[2], legetl(n->scratchb));
+				cont = -2;
+				break;
+			case A_SIR_NOTIFY_DATA_OUT:
+				IPRINT("sd53c8xx: %d/%d: data out\n", dsa->target, dsa->lun);
+				cont = -2;
+				break;
+			case A_SIR_NOTIFY_DUMP:
+				IPRINT("sd53c8xx: %d/%d: dump\n", dsa->target, dsa->lun);
+				dumpncrregs(c, 1);
+				cont = -2;
+				break;
+			case A_SIR_NOTIFY_DUMP2:
+				IPRINT("sd53c8xx: %d/%d: dump2:", dsa->target, dsa->lun);
+				IPRINT(" sa %lux", legetl(n->dsp) - c->scriptpa);
+				IPRINT(" dsa %lux", legetl(n->dsa));
+				IPRINT(" sfbr %ux", n->sfbr);
+				IPRINT(" a %lux", n->scratcha);
+				IPRINT(" b %lux", legetl(n->scratchb));
+				IPRINT(" ssid %ux", n->ssid);
+				IPRINT("\n");
+				cont = -2;
+				break;
+			case A_SIR_NOTIFY_WAIT_RESELECT:
+				IPRINT("sd53c8xx: wait reselect\n");
+				cont = -2;
+				break;
+			case A_SIR_NOTIFY_RESELECT:
+				IPRINT("sd53c8xx: reselect: ssid %.2x sfbr %.2x at %ld\n",
+				    n->ssid, n->sfbr, TK2MS(m->ticks));
+				cont = -2;
+				break;
+			case A_SIR_NOTIFY_ISSUE:
+				IPRINT("sd53c8xx: %d/%d: issue:", dsa->target, dsa->lun);
+			dsadump:
+				IPRINT(" tgt=%d", dsa->target);
+				IPRINT(" time=%ld", TK2MS(m->ticks));
+				IPRINT("\n");
+				cont = -2;
+				break;
+			case A_SIR_NOTIFY_ISSUE_CHECK:
+				IPRINT("sd53c8xx: issue check\n");
+				cont = -2;
+				break;
+			case A_SIR_NOTIFY_SIGP:
+				IPRINT("sd53c8xx: responded to SIGP\n");
+				cont = -2;
+				break;
+			case A_SIR_NOTIFY_DUMP_NEXT_CODE: {
+				ulong *dsp = DMASEG_TO_KADDR(legetl(n->dsp));
+				int x;
+				IPRINT("sd53c8xx: code at %lux", dsp - c->script);
+				for (x = 0; x < 6; x++)
+					IPRINT(" %.8lux", dsp[x]);
+				IPRINT("\n");
+				USED(dsp);
+				cont = -2;
+				break;
+			}
+			case A_SIR_NOTIFY_WSR:
+				IPRINT("sd53c8xx: %d/%d: WSR set\n", dsa->target, dsa->lun);
+				cont = -2;
+				break;
+			case A_SIR_NOTIFY_LOAD_SYNC:
+				IPRINT("sd53c8xx: %d/%d: scntl=%.2x sxfer=%.2x\n",
+				    dsa->target, dsa->lun, n->scntl3, n->sxfer);
+				cont = -2;
+				break;
+			case A_SIR_NOTIFY_RESELECTED_ON_SELECT:
+				IPRINT("sd53c8xx: %d/%d: reselected during select\n",
+				    dsa->target, dsa->lun);
+				cont = -2;
+				break;
+			default:
+				IPRINT("sd53c8xx: %d/%d: script error %ld\n",
+					dsa->target, dsa->lun, legetl(n->dsps));
+				dumpncrregs(c, 1);
+				wakeme = 1;
+			}
+		}
+		/*else*/ if (dstat & Iid) {
+			ulong addr = legetl(n->dsp);
+			ulong dbc = (n->dbc[2]<<16)|(n->dbc[1]<<8)|n->dbc[0];
+			IPRINT("sd53c8xx: %d/%d: Iid pa=%.8lux sa=%.8lux dbc=%lux\n",
+			    dsa->target, dsa->lun,
+			    addr, addr - c->scriptpa, dbc);
+			addr = (ulong)DMASEG_TO_KADDR(addr);
+			IPRINT("%.8lux %.8lux %.8lux\n",
+			    *(ulong *)(addr - 12), *(ulong *)(addr - 8), *(ulong *)(addr - 4));
+			USED(addr, dbc);
+			dsa->p9status = SDeio;
+			wakeme = 1;
+		}
+		/*else*/ if (dstat & Bf) {
+			IPRINT("sd53c8xx: %d/%d: Bus Fault\n", dsa->target, dsa->lun);
+			dumpncrregs(c, 1);
+			dsa->p9status = SDeio;
+			wakeme = 1;
+		}
+	}
+	if (cont == -2)
+		ncrcontinue(c);
+	else if (cont >= 0)
+		start(c, cont);
+	if (wakeme){
+		if(dsa->p9status == SDnostatus)
+			dsa->p9status = SDeio;
+		wakeup(dsa);
+	}
+	iunlock(c);
+	if (DEBUG(1)) {
+		IPRINT("sd53c8xx: int end 1\n");
+	}
+}
+
+static int
+done(void *arg)
+{
+	return ((Dsa *)arg)->p9status != SDnostatus;
+}
+
+static void
+setmovedata(Movedata *d, ulong pa, ulong bc)
+{
+	d->pa[0] = pa;
+	d->pa[1] = pa>>8;
+	d->pa[2] = pa>>16;
+	d->pa[3] = pa>>24;
+	d->dbc[0] = bc;
+	d->dbc[1] = bc>>8;
+	d->dbc[2] = bc>>16;
+	d->dbc[3] = bc>>24;
+}
+
+static void
+advancedata(Movedata *d, long v)
+{
+	lesetl(d->pa, legetl(d->pa) + v);
+	lesetl(d->dbc, legetl(d->dbc) - v);
+}
+
+static void
+dumpwritedata(uchar *data, int datalen)
+{
+	int i;
+	uchar *bp;
+	if (!DEBUG(0)){
+		USED(data, datalen);
+		return;
+	}
+
+	if (datalen) {
+		KPRINT("sd53c8xx:write:");
+		for (i = 0, bp = data; i < 50 && i < datalen; i++, bp++)
+			KPRINT("%.2ux", *bp);
+		if (i < datalen) {
+			KPRINT("...");
+		}
+		KPRINT("\n");
+	}
+}
+
+static void
+dumpreaddata(uchar *data, int datalen)
+{
+	int i;
+	uchar *bp;
+	if (!DEBUG(0)){
+		USED(data, datalen);
+		return;
+	}
+
+	if (datalen) {
+		KPRINT("sd53c8xx:read:");
+		for (i = 0, bp = data; i < 50 && i < datalen; i++, bp++)
+			KPRINT("%.2ux", *bp);
+		if (i < datalen) {
+			KPRINT("...");
+		}
+		KPRINT("\n");
+	}
+}
+
+static void
+busreset(Controller *c)
+{
+	int x, ntarget;
+
+	/* bus reset */
+	c->n->scntl1 |= (1 << 3);
+	delay(500);
+	c->n->scntl1 &= ~(1 << 3);
+	if(!(c->v->feature & Wide))
+		ntarget = 8;
+	else
+		ntarget = MAXTARGET;
+	for (x = 0; x < ntarget; x++) {
+		setwide(0, c, x, 0);
+#ifndef ASYNC_ONLY
+		c->s[x] = NeitherDone;
+#endif
+	}
+	c->capvalid = 0;
+}
+
+static void
+reset(Controller *c)
+{
+	/* should wakeup all pending tasks */
+	softreset(c);
+	busreset(c);
+}
+
+static int
+symrio(SDreq* r)
+{
+	Dsa *d;
+	uchar *bp;
+	Controller *c;
+	uchar target_expo, my_expo;
+	int bc, check, status, target;
+
+	if((target = r->unit->subno) == 0x07)
+		return r->status = SDtimeout;	/* assign */
+	c = r->unit->dev->ctlr;
+
+	check = 0;
+	d = dsaalloc(c, target, r->lun);
+
+	qlock(&c->q[target]);			/* obtain access to target */
+docheck:
+	/* load the transfer control stuff */
+	d->scsi_id_buf[0] = 0;
+	d->scsi_id_buf[1] = c->sxfer[target];
+	d->scsi_id_buf[2] = target;
+	d->scsi_id_buf[3] = c->scntl3[target];
+	synctodsa(d, c);
+
+	bc = 0;
+
+	d->msg_out[bc] = 0x80 | r->lun;
+
+#ifndef NO_DISCONNECT
+	d->msg_out[bc] |= (1 << 6);
+#endif
+	bc++;
+
+	/* work out what to do about negotiation */
+	switch (c->s[target]) {
+	default:
+		KPRINT("sd53c8xx: %d: strange nego state %d\n", target, c->s[target]);
+		c->s[target] = NeitherDone;
+		/* fall through */
+	case NeitherDone:
+		if ((c->capvalid & (1 << target)) == 0)
+			break;
+		target_expo = (c->cap[target] >> 5) & 3;
+		my_expo = (c->v->feature & Wide) != 0;
+		if (target_expo < my_expo)
+			my_expo = target_expo;
+#ifdef ALWAYS_DO_WDTR
+		bc += buildwdtrmsg(d->msg_out + bc, my_expo);
+		KPRINT("sd53c8xx: %d: WDTN: initiating expo %d\n", target, my_expo);
+		c->s[target] = WideInit;
+		break;
+#else
+		if (my_expo) {
+			bc += buildwdtrmsg(d->msg_out + bc, (c->v->feature & Wide) ? 1 : 0);
+			KPRINT("sd53c8xx: %d: WDTN: initiating expo %d\n", target, my_expo);
+			c->s[target] = WideInit;
+			break;
+		}
+		KPRINT("sd53c8xx: %d: WDTN: narrow\n", target);
+		/* fall through */
+#endif
+	case WideDone:
+		if (c->cap[target] & (1 << 4)) {
+			KPRINT("sd53c8xx: %d: SDTN: initiating %d %d\n", target, c->tpf, c->v->maxsyncoff);
+			bc += buildsdtrmsg(d->msg_out + bc, c->tpf, c->v->maxsyncoff);
+			c->s[target] = SyncInit;
+			break;
+		}
+		KPRINT("sd53c8xx: %d: SDTN: async only\n", target);
+		c->s[target] = BothDone;
+		break;
+
+	case BothDone:
+		break;
+	}
+
+	setmovedata(&d->msg_out_buf, DMASEG(d->msg_out), bc);
+	setmovedata(&d->cmd_buf, DMASEG(r->cmd), r->clen);
+	calcblockdma(d, DMASEG(r->data), r->dlen);
+
+	if (DEBUG(0)) {
+		KPRINT("sd53c8xx: %d/%d: exec: ", target, r->lun);
+		for (bp = r->cmd; bp < &r->cmd[r->clen]; bp++)
+			KPRINT("%.2ux", *bp);
+		KPRINT("\n");
+		if (!r->write)
+			KPRINT("sd53c8xx: %d/%d: exec: limit=(%d)%ld\n",
+			  target, r->lun, d->dmablks, legetl(d->data_buf.dbc));
+		else
+			dumpwritedata(r->data, r->dlen);
+	}
+
+	setmovedata(&d->status_buf, DMASEG(&d->status), 1);	
+
+	d->p9status = SDnostatus;
+	d->parityerror = 0;
+
+	d->stateb = A_STATE_ISSUE;		/* start operation */
+
+	ilock(c);
+	if (c->ssm)
+		c->n->dcntl |= 0x10;		/* SSI */
+	if (c->running) {
+		c->n->istat |= Sigp;
+	}
+	else {
+		start(c, E_issue_check);
+	}
+	iunlock(c);
+
+	while(waserror())
+		;
+	tsleep(d, done, d, 30 * 1000);
+	poperror();
+
+	if (!done(d)) {
+		KPRINT("sd53c8xx: %d/%d: exec: Timed out\n", target, r->lun);
+		dumpncrregs(c, 0);
+		dsafree(c, d);
+		reset(c);
+		qunlock(&c->q[target]);
+		r->status = SDtimeout;
+		return r->status = SDtimeout;	/* assign */
+	}
+
+	if((status = d->p9status) == SDeio)
+		c->s[target] = NeitherDone;
+	if (d->parityerror) {
+		status = SDeio;
+	}
+
+	/*
+	 * adjust datalen
+	 */
+	r->rlen = r->dlen;
+	if (d->dmablks > 0)
+		r->rlen -= d->dmablks * A_BSIZE;
+	else if (d->flag == 0)
+		r->rlen -= legetl(d->data_buf.dbc);
+	if(!r->write)
+		dumpreaddata(r->data, r->rlen);
+	if (DEBUG(0))
+		KPRINT("53c8xx: %d/%d: exec: p9status=%d status %d rlen %ld\n",
+		    target, r->lun, d->p9status, status, r->rlen);
+	/*
+	 * spot the identify
+	 */
+	if ((c->capvalid & (1 << target)) == 0
+	 && (status == SDok || status == SDcheck)
+	 && r->cmd[0] == 0x12 && r->dlen >= 8) {
+		c->capvalid |= 1 << target;
+		bp = r->data;
+		c->cap[target] = bp[7];
+		KPRINT("sd53c8xx: %d: capabilities %.2x\n", target, bp[7]);
+	}
+	if(!check && status == SDcheck && !(r->flags & SDnosense)){
+		check = 1;
+		r->write = 0;
+		memset(r->cmd, 0, sizeof(r->cmd));
+		r->cmd[0] = 0x03;
+		r->cmd[1] = r->lun<<5;
+		r->cmd[4] = sizeof(r->sense)-1;
+		r->clen = 6;
+		r->data = r->sense;
+		r->dlen = sizeof(r->sense)-1;
+		/*
+		 * Clear out the microcode state
+		 * so the Dsa can be re-used.
+		 */
+		lesetl(d->state, A_STATE_ALLOCATED);
+		goto docheck;
+	}
+	qunlock(&c->q[target]);
+	dsafree(c, d);
+
+	if(status == SDok && check){
+		status = SDcheck;
+		r->flags |= SDvalidsense;
+	}
+	KPRINT("sd53c8xx: %d: r flags %8.8uX status %d rlen %ld\n",
+		target, r->flags, status, r->rlen);
+	return r->status = status;
+}
+
+static void
+cribbios(Controller *c)
+{
+	c->bios.scntl3 = c->n->scntl3;
+	c->bios.stest2 = c->n->stest2;
+	print("sd53c8xx: bios scntl3(%.2x) stest2(%.2x)\n", c->bios.scntl3, c->bios.stest2);
+}
+
+static int
+bios_set_differential(Controller *c)
+{
+	/* Concept lifted from FreeBSD - thanks Gerard */
+	/* basically, if clock conversion factors are set, then there is
+ 	 * evidence the bios had a go at the chip, and if so, it would
+	 * have set the differential enable bit in stest2
+	 */
+	return (c->bios.scntl3 & 7) != 0 && (c->bios.stest2 & 0x20) != 0;
+}
+
+#define NCR_VID 	0x1000
+#define NCR_810_DID 	0x0001
+#define NCR_820_DID	0x0002	/* don't know enough about this one to support it */
+#define NCR_825_DID	0x0003
+#define NCR_815_DID	0x0004
+#define SYM_810AP_DID	0x0005
+#define SYM_860_DID	0x0006
+#define SYM_896_DID	0x000b
+#define SYM_895_DID	0x000c
+#define SYM_885_DID	0x000d	/* ditto */
+#define SYM_875_DID	0x000f	/* ditto */
+#define SYM_1010_DID	0x0020
+#define SYM_1011_DID	0x0021
+#define SYM_875J_DID	0x008f
+
+static Variant variant[] = {
+{ NCR_810_DID,   0x0f, "NCR53C810",	Burst16,   8, 24, 0 },
+{ NCR_810_DID,   0x1f, "SYM53C810ALV",	Burst16,   8, 24, Prefetch },
+{ NCR_810_DID,   0xff, "SYM53C810A",	Burst16,   8, 24, Prefetch },
+{ SYM_810AP_DID, 0xff, "SYM53C810AP",	Burst16,   8, 24, Prefetch },
+{ NCR_815_DID,   0xff, "NCR53C815",	Burst16,   8, 24, BurstOpCodeFetch },
+{ NCR_825_DID,   0x0f, "NCR53C825",	Burst16,   8, 24, Wide|BurstOpCodeFetch|Differential },
+{ NCR_825_DID,   0xff, "SYM53C825A",	Burst128, 16, 24, Prefetch|LocalRAM|BigFifo|Differential|Wide },
+{ SYM_860_DID,   0x0f, "SYM53C860",	Burst16,   8, 24, Prefetch|Ultra },
+{ SYM_860_DID,   0xff, "SYM53C860LV",	Burst16,   8, 24, Prefetch|Ultra },
+{ SYM_875_DID,   0x01, "SYM53C875r1",	Burst128, 16, 24, Prefetch|LocalRAM|BigFifo|Differential|Wide|Ultra },
+{ SYM_875_DID,   0xff, "SYM53C875",	Burst128, 16, 24, Prefetch|LocalRAM|BigFifo|Differential|Wide|Ultra|ClockDouble },
+{ SYM_875J_DID,   0xff, "SYM53C875j",	Burst128, 16, 24, Prefetch|LocalRAM|BigFifo|Differential|Wide|Ultra|ClockDouble },
+{ SYM_885_DID,   0xff, "SYM53C885",	Burst128, 16, 24, Prefetch|LocalRAM|BigFifo|Wide|Ultra|ClockDouble },
+{ SYM_895_DID,   0xff, "SYM53C895",	Burst128, 16, 24, Prefetch|LocalRAM|BigFifo|Wide|Ultra|Ultra2 },
+{ SYM_896_DID,   0xff, "SYM53C896",	Burst128, 16, 64, Prefetch|LocalRAM|BigFifo|Wide|Ultra|Ultra2 },
+{ SYM_1010_DID,   0xff, "SYM53C1010",	Burst128, 16, 64, Prefetch|LocalRAM|BigFifo|Wide|Ultra|Ultra2 },
+{ SYM_1011_DID,   0xff, "SYM53C1010",	Burst128, 16, 64, Prefetch|LocalRAM|BigFifo|Wide|Ultra|Ultra2 },
+};
+
+
+static int
+xfunc(Controller *c, enum na_external x, unsigned long *v)
+{
+	switch (x) {
+	default:
+		print("xfunc: can't find external %d\n", x);
+		return 0;
+	case X_scsi_id_buf:
+		*v = offsetof(Dsa, scsi_id_buf[0]);
+		break;
+	case X_msg_out_buf:
+		*v = offsetof(Dsa, msg_out_buf);
+		break;
+	case X_cmd_buf:
+		*v = offsetof(Dsa, cmd_buf);
+		break;
+	case X_data_buf:
+		*v = offsetof(Dsa, data_buf);
+		break;
+	case X_status_buf:
+		*v = offsetof(Dsa, status_buf);
+		break;
+	case X_dsa_head:
+		*v = DMASEG(&c->dsalist.head[0]);
+		break;
+	}
+	return 1;
+}
+
+static int
+na_fixup(Controller *c, ulong pa_reg,
+    struct na_patch *patch, int patches,
+    int (*externval)(Controller*, int, ulong*))
+{
+	int p;
+	int v;
+	ulong *script, pa_script;
+	unsigned long lw, lv;
+
+	script = c->script;
+	pa_script = c->scriptpa;
+	for (p = 0; p < patches; p++) {
+		switch (patch[p].type) {
+		case 1:
+			/* script relative */
+			script[patch[p].lwoff] += pa_script;
+			break;
+		case 2:
+			/* register i/o relative */
+			script[patch[p].lwoff] += pa_reg;
+			break;
+		case 3:
+			/* data external */
+			lw = script[patch[p].lwoff];
+			v = (lw >> 8) & 0xff;
+			if (!(*externval)(c, v, &lv))
+				return 0;
+			v = lv & 0xff;
+			script[patch[p].lwoff] = (lw & 0xffff00ffL) | (v << 8);
+			break;
+		case 4:
+			/* 32 bit external */
+			lw = script[patch[p].lwoff];
+			if (!(*externval)(c, lw, &lv))
+				return 0;
+			script[patch[p].lwoff] = lv;
+			break;
+		case 5:
+			/* 24 bit external */
+			lw = script[patch[p].lwoff];
+			if (!(*externval)(c, lw & 0xffffff, &lv))
+				return 0;
+			script[patch[p].lwoff] = (lw & 0xff000000L) | (lv & 0xffffffL);
+			break;
+		}
+	}
+	return 1;
+}
+
+static SDev*
+sympnp(void)
+{
+	int ba;
+	Pcidev *p;
+	Variant *v;
+	void *scriptma;
+	Controller *ctlr;
+	SDev *sdev, *head, *tail;
+	ulong regpa, *script, scriptpa;
+
+	p = nil;
+	head = tail = nil;
+	while(p = pcimatch(p, NCR_VID, 0)){
+		for(v = variant; v < &variant[nelem(variant)]; v++){
+			if(p->did == v->did && p->rid <= v->maxrid)
+				break;
+		}
+		if(v >= &variant[nelem(variant)])
+			continue;
+		print("sd53c8xx: %s rev. 0x%2.2x intr=%d command=%4.4uX\n",
+			v->name, p->rid, p->intl, p->pcr);
+
+		regpa = p->mem[1].bar;
+		ba = 2;
+		if(regpa & 0x04){
+			if(p->mem[2].bar)
+				continue;
+			ba++;
+		}
+		regpa = upamalloc(regpa & ~0x0F, p->mem[1].size, 0);
+		if(regpa == 0)
+			continue;
+
+		script = nil;
+		scriptpa = 0;
+		scriptma = nil;
+		if((v->feature & LocalRAM) && sizeof(na_script) <= 4096){
+			scriptpa = p->mem[ba].bar;
+			if((scriptpa & 0x04) && p->mem[ba+1].bar){
+				upafree(regpa, p->mem[1].size);
+				continue;
+			}
+			scriptpa = upamalloc(scriptpa & ~0x0F,
+					p->mem[ba].size, 0);
+			if(scriptpa)
+				script = KADDR(scriptpa);
+		}
+		if(scriptpa == 0){
+			/*
+			 * Either the map failed, or this chip does not have
+			 * local RAM. It will need a copy of the microcode.
+			 */
+			scriptma = malloc(sizeof(na_script));
+			if(scriptma == nil){
+				upafree(regpa, p->mem[1].size);
+				continue;
+			}
+			scriptpa = DMASEG(scriptma);
+			script = scriptma;
+		}
+
+		ctlr = malloc(sizeof(Controller));
+		sdev = malloc(sizeof(SDev));
+		if(ctlr == nil || sdev == nil){
+buggery:
+			if(ctlr)
+				free(ctlr);
+			if(sdev)
+				free(sdev);
+			if(scriptma)
+				free(scriptma);
+			else
+				upafree(scriptpa, p->mem[ba].size);
+			upafree(regpa, p->mem[1].size);
+			continue;
+		}
+
+		ctlr->n = KADDR(regpa);
+		ctlr->v = v;
+		ctlr->script = script;
+		memmove(ctlr->script, na_script, sizeof(na_script));
+		ctlr->scriptpa = scriptpa;
+		if(!na_fixup(ctlr, regpa, na_patches, NA_PATCHES, xfunc)){
+			print("script fixup failed\n");
+			goto buggery;
+		}
+		swabl(ctlr->script, ctlr->script, sizeof(na_script));
+
+		ctlr->dsalist.freechain = 0;
+		lesetl(ctlr->dsalist.head, 0);
+
+		ctlr->pcidev = p;
+
+		sdev->ifc = &sd53c8xxifc;
+		sdev->ctlr = ctlr;
+		if(!(v->feature & Wide))
+			sdev->nunit = 8;
+		else
+			sdev->nunit = MAXTARGET;
+		ctlr->sdev = sdev;
+
+		if(head != nil)
+			tail->next = sdev;
+		else
+			head = sdev;
+		tail = sdev;
+	}
+
+	return head;
+}
+
+static SDev*
+symid(SDev* sdev)
+{
+	return scsiid(sdev, &sd53c8xxifc);
+}
+
+static int
+symenable(SDev* sdev)
+{
+	Pcidev *pcidev;
+	Controller *ctlr;
+	//char name[NAMELEN];
+
+	ctlr = sdev->ctlr;
+	pcidev = ctlr->pcidev;
+
+	pcisetbme(pcidev);
+	//snprint(name, NAMELEN, "%s (%s)", sdev->name, sdev->ifc->name);
+	intrenable(pcidev->intl, interrupt, ctlr, pcidev->tbdf, name);
+
+	ilock(ctlr);
+	synctabinit(ctlr);
+	cribbios(ctlr);
+	reset(ctlr);
+	iunlock(ctlr);
+
+	return 1;
+}
+
+static int
+symdisable(SDev* sdev)
+{
+	Ncr *n;
+	Controller *ctlr;
+
+	ctlr = sdev->ctlr;
+	n = ctlr->n;
+
+	n->istat = Srst;		/* software reset */
+	microdelay(1);
+	n->istat = 0;
+
+	n->scntl1 |= (1 << 3);		/* bus reset */
+	delay(500);
+	n->scntl1 &= ~(1 << 3);
+
+	return 1;
+}
+
+SDifc sd53c8xxifc = {
+	"53c8xx",			/* name */
+
+	sympnp,				/* pnp */
+	nil,				/* legacy */
+	symid,				/* id */
+	symenable,			/* enable */
+	symdisable,			/* disable */
+
+	scsiverify,			/* verify */
+	scsionline,			/* online */
+	symrio,				/* rio */
+	nil,				/* rctl */
+	nil,				/* wctl */
+
+	scsibio,			/* bio */
+};
--- /dev/null
+++ b/os/boot.original/pc/sd53c8xx.i
@@ -1,0 +1,769 @@
+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 */
+			/*	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 */ 0x78370100L, /*		move	1 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 */ 0x78370100L, /*		move	1 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 */ 0x740a0f00L, /*		move	ssid & 15 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 */
+	{ 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 79
+
+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,
+};
+
+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_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
--- /dev/null
+++ b/os/boot.original/pc/sdaoe.c
@@ -1,0 +1,733 @@
+/*
+ * aoe sd bootstrap driver, copyright © 2007 coraid
+ */
+
+#include "u.h"
+#include "mem.h"
+#include "lib.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "sd.h"
+#include "aoe.h"
+
+
+enum {
+	Nctlr	= 4,
+};
+
+enum {
+	/* sync with ahci.h */
+	Dllba 	= 1<<0,
+	Dsmart	= 1<<1,
+	Dpower	= 1<<2,
+	Dnop	= 1<<3,
+	Datapi	= 1<<4,
+	Datapi16= 1<<5,
+};
+
+enum {
+	Tfree	= -1,
+	Tmgmt,
+};
+
+typedef struct Ctlr Ctlr;
+struct Ctlr{
+	Ctlr	*next;
+	SDunit	*unit;
+
+	int	ctlrno;
+	int	major;
+	int	minor;
+	uchar	ea[Eaddrlen];
+	ushort	lasttag;
+
+	ulong	vers;
+	uchar	mediachange;
+	uchar	flag;
+	uchar	smart;
+	uchar	smartrs;
+	uchar	feat;
+
+	uvlong	sectors;
+	char	serial[20+1];
+	char	firmware[8+1];
+	char	model[40+1];
+	char	ident[0x100];
+};
+
+static	Ctlr	*head;
+static	Ctlr	*tail;
+
+static	int	aoeether[10];
+
+SDifc sdaoeifc;
+
+static void
+hnputs(uchar *p, ushort i)
+{
+	p[0] = i >> 8;
+	p[1] = i;
+}
+
+static void
+hnputl(uchar *p, ulong i)
+{
+	p[0] = i >> 24;
+	p[1] = i >> 16;
+	p[2] = i >> 8;
+	p[3] = i;
+}
+
+static ushort
+nhgets(uchar *p)
+{
+	return *p<<8 | p[1];
+}
+
+static ulong
+nhgetl(uchar *p)
+{
+	return p[0]<<24 | p[1]<<16 | p[2]<<8 | p[3];
+}
+
+static int
+newtag(Ctlr *d)
+{
+	int t;
+
+	for(;;){
+		t = ++d->lasttag << 16;
+		t |= m->ticks & 0xffff;
+		switch(t) {
+		case Tfree:
+		case Tmgmt:
+			break;
+		default:
+			return t;
+		}
+	}
+}
+
+static int
+hset(Ctlr *d, Aoehdr *h, int cmd)
+{
+	int tag;
+
+	memmove(h->dst, d->ea, Eaddrlen);
+	hnputs(h->type, Aoetype);
+	h->verflag = Aoever << 4;
+	hnputs(h->major, d->major);
+	h->minor = d->minor;
+	h->cmd = cmd;
+	hnputl(h->tag, tag = newtag(d));
+	return tag;
+}
+
+static void
+idmove(char *p, ushort *a, int n)
+{
+	int i;
+	char *op, *e;
+
+	op = p;
+	for(i = 0; i < n / 2; i++){
+		*p++ = a[i] >> 8;
+		*p++ = a[i];
+	}
+	*p = 0;
+	while(p > op && *--p == ' ')
+		*p = 0;
+	e = p;
+	p = op;
+	while(*p == ' ')
+		p++;
+	memmove(op, p, n - (e - p));
+}
+
+static ushort
+gbit16(void *a)
+{
+	uchar *i;
+
+	i = a;
+	return i[1]<<8 | i[0];
+}
+
+static ulong
+gbit32(void *a)
+{
+	uchar *i;
+	ulong j;
+
+	i = a;
+	j  = i[3] << 24;
+	j |= i[2] << 16;
+	j |= i[1] << 8;
+	j |= i[0];
+	return j;
+}
+
+static uvlong
+gbit64(void *a)
+{
+	uchar *i;
+
+	i = a;
+	return (uvlong)gbit32(i+4) << 32 | gbit32(a);
+}
+
+static int
+ataidentify(Ctlr *c, ushort *id)
+{
+	vlong s;
+	int i;
+
+	i = gbit16(id+83) | gbit16(id+86);
+	if(i & (1 << 10)){
+		c->feat |= Dllba;
+		s = gbit64(id+100);
+	}else
+		s = gbit32(id+60);
+
+	idmove(c->serial, id+10, 20);
+	idmove(c->firmware, id+23, 8);
+	idmove(c->model, id+27, 40);
+
+print("aoe discovers %d.%d: %s %s\n", c->major, c->minor, c->model, c->serial);
+
+	c->sectors = s;
+	c->mediachange = 1;
+	return 0;
+}
+
+static void
+identifydump(Aoeata *a)
+{
+	print("%E %E type=%.4ux verflag=%x error=%x %d.%d cmd=%d tag=%.8lux\n",
+		a->dst, a->src, nhgets(a->type), a->verflag, a->error,
+		nhgets(a->major), a->minor, a->cmd, nhgetl(a->tag));
+	print("   aflag=%x errfeat=%ux scnt=%d cmdstat=%ux, lba=%d? res=%.4ux\n",
+		a->aflag, a->errfeat, a->scnt, a->cmdstat, 0, nhgets(a->res));
+}
+
+static int
+idpkt(Ctlr *c, Aoeata *a)
+{
+	memset(a, 0, sizeof *a);
+	a->cmdstat = Cid;
+	a->scnt = 1;
+	a->lba[3] = 0xa0;
+	return hset(c, a, ACata);
+}
+
+static int
+chktag(int *out, int nout, int tag)
+{
+	int j;
+
+	for(j = 0; j <= nout; j++)
+		if(out[j] == tag)
+			return 0;
+print("wrong tag\n");
+	for(j = 0; j <= nout; j++)
+		print("%.8ux != %.8ux\n", out[j], tag);
+	return -1;
+}
+
+/*
+ * ignore the tag for identify.  better than ignoring
+ * a response to the wrong identify request
+ */
+static int
+identify(Ctlr *c)
+{
+	int tag[5], i, n;
+	Aoeata *a;
+	Etherpkt p;
+
+	memset(&p, 0, sizeof p);
+	a = (Aoeata*)&p;
+	i = 0;
+	do {
+		if(i == 5){
+			print("aoe: identify timeout\n");
+			return -1;
+		}
+		tag[i] = idpkt(c, a);
+		ethertxpkt(c->ctlrno, &p, sizeof *a, 0);
+		memset(&p, 0, sizeof p);
+next:
+		n = etherrxpkt(c->ctlrno, &p, 125);
+		if(n == 0){
+			i++;
+			continue;
+		}
+		if(nhgets(a->type) != Aoetype)
+			goto next;
+		if(nhgets(a->major) != c->major || a->minor != c->minor){
+			print("wrong device %d.%d want %d.%d; %d\n",
+				nhgets(a->major), a->minor,
+				c->major, c->minor, n);
+			goto next;
+		}
+		if(chktag(tag, i, nhgetl(a->tag)) == -1)
+			goto next;
+		if(a->cmdstat & 0xa9){
+			print("aoe: ata error on identify: %2ux\n", a->cmdstat);
+			return -1;
+		}
+	} while (a->scnt != 1);
+
+	c->feat = 0;
+	ataidentify(c, (ushort*)(a+1));
+	return 0;
+}
+
+static Ctlr*
+ctlrlookup(int major, int minor)
+{
+	Ctlr *c;
+
+	for(c = head; c; c = c->next)
+		if(c->major == major && c->minor == minor)
+			break;
+	return c;
+}
+
+static Ctlr*
+newctlr(Etherpkt *p)
+{
+	int major, minor;
+	Aoeqc *q;
+	Ctlr *c;
+
+	q = (Aoeqc*)p;
+	if(nhgets(q->type) != Aoetype)
+		return 0;
+	major = nhgets(q->major);
+	minor = q->minor;
+
+	if(major == 0xffff || minor == 0xff)
+		return 0;
+
+	if(ctlrlookup(major, minor)){
+		print("duplicate shelf.slot\n");
+		return 0;
+	}
+
+	if((c = malloc(sizeof *c)) == 0)
+		return 0;
+	c->major = major;
+	c->minor = minor;
+	memmove(c->ea, q->src, Eaddrlen);
+
+	if(head != 0)
+		tail->next = c;
+	else
+		head = c;
+	tail = c;
+	return c;
+}
+
+static void
+discover(int major, int minor)
+{
+	int i;
+	Aoehdr *h;
+	Etherpkt p;
+
+	for(i = 0; i < nelem(aoeether); i++){
+		if(aoeether[i] == 0)
+			continue;
+		memset(&p, 0, ETHERMINTU);
+		h = (Aoehdr*)&p;
+		memset(h->dst, 0xff, sizeof h->dst);
+		hnputs(h->type, Aoetype);
+		h->verflag = Aoever << 4;
+		hnputs(h->major, major);
+		h->minor = minor;
+		h->cmd = ACconfig;
+		ethertxpkt(i, &p, ETHERMINTU, 0);
+	}
+}
+
+static int
+rxany(Etherpkt *p, int t)
+{
+	int i, n;
+
+	for(i = 0; i < nelem(aoeether); i++){
+		if(aoeether[i] == 0)
+			continue;
+		while ((n = etherrxpkt(i, p, t)) != 0)
+			if(nhgets(p->type) == Aoetype)
+				return n;
+	}
+	return 0;
+}
+
+static int
+aoeprobe(int major, int minor, SDev *s)
+{
+	Ctlr *ctlr;
+	Etherpkt p;
+	int n, i;
+
+	for(i = 0;; i += 200){
+		if(i > 8000)
+			return -1;
+		discover(major, minor);
+again:
+		n = rxany(&p, 100);
+		if(n > 0 && (ctlr = newctlr(&p)))
+			break;
+		if(n > 0)
+			goto again;
+	}
+
+	s->ctlr = ctlr;
+	s->ifc = &sdaoeifc;
+	s->nunit = 1;
+	return 0;
+}
+
+static char 	*probef[32];
+static int 	nprobe;
+
+int
+pnpprobeid(char *s)
+{
+	int id;
+
+	if(strlen(s) < 2)
+		return 0;
+	id = 'e';
+	if(s[1] == '!')
+		id = s[0];
+	return id;
+}
+
+int
+tokenize(char *s, char **args, int maxargs)
+{
+	int nargs;
+
+	for(nargs = 0; nargs < maxargs; nargs++){
+		while(*s != '\0' && strchr("\t\n ", *s) != nil)
+			s++;
+		if(*s == '\0')
+			break;
+		args[nargs] = s;
+		while(*s != '\0' && strchr("\t\n ", *s) == nil)
+			s++;
+		if(*s != '\0')
+			*s++ = 0;
+	}
+	return nargs;
+}
+
+int
+aoepnp0(void)
+{
+	int i;
+	char *p, c;
+
+	if((p = getconf("aoeif")) == nil)
+		return 0;
+print("aoeif = %s\n", p);
+	nprobe = tokenize(p, probef, nelem(probef));
+	for(i = 0; i < nprobe; i++){
+		if(strncmp(probef[i], "ether", 5) != 0)
+			continue;
+		c = probef[i][5];
+		if(c > '9' || c < '0')
+			continue;
+		aoeether[c - '0'] = 1;
+	}
+
+	if((p = getconf("aoedev")) == nil)
+		return 0;
+	return nprobe = tokenize(p, probef, nelem(probef));
+}
+
+int
+probeshelf(char *s, int *shelf, int *slot)
+{
+	int a, b;
+	char *r;
+
+	for(r = s + strlen(s) - 1; r > s; r--)
+		if((*r < '0' || *r > '9') && *r != '.'){
+			r++;
+			break;
+		}
+	a = strtoul(r, &r, 10);
+	if(*r++ != '.')
+		return -1;
+	b = strtoul(r, 0, 10);
+
+	*shelf = a;
+	*slot = b;
+print("  shelf=%d.%d\n", a, b);
+	return 0;
+}
+
+Ctlr*
+pnpprobe(SDev *sd)
+{
+	int shelf, slot;
+	char *p;
+	static int i;
+
+	if(i >= nprobe)
+		return 0;
+	p = probef[i++];
+	if(strlen(p) < 2)
+		return 0;
+	if(p[1] == '!'){
+		sd->idno = p[0];
+		p += 2;
+	}
+	if(probeshelf(p, &shelf, &slot) == -1 ||
+	    aoeprobe(shelf, slot, sd) == -1 ||
+	    identify(sd->ctlr) == -1)
+		return 0;
+	return sd->ctlr;
+}
+
+/*
+ * we may need to pretend we found something
+ */
+
+SDev*
+aoepnp(void)
+{
+	int n, i, id;
+	char *p;
+	SDev *h, *t, *s;
+
+	p = getconf("aoeif");
+	if (p)
+		print("aoepnp: aoeif=%s\n", p);
+
+	if((n = aoepnp0()) == 0)
+		n = 2;
+	t = h = 0;
+	for(i = 0; i < n; i++){
+		id = 'e';
+		s = malloc(sizeof *s);
+		if(s == 0)
+			break;
+		s->ctlr = 0;
+		s->idno = id;
+		s->ifc = &sdaoeifc;
+		s->nunit = 1;
+		pnpprobe(s);
+
+		if(h)
+			t->next = s;
+		else
+			h = s;
+		t = s;
+	}
+	return h;
+}
+
+static int
+aoeverify(SDunit *u)
+{
+	Ctlr *c;
+	SDev *s;
+
+	s = u->dev;
+	c = s->ctlr;
+	if(c == 0){
+		aoepnp0();
+		if((s->ctlr = c = pnpprobe(s)) == nil)
+			return 0;
+	}
+	c->mediachange = 1;
+	return 1;
+}
+
+static int
+aoeonline(SDunit *u)
+{
+	int r;
+	Ctlr *c;
+
+	c = u->dev->ctlr;
+	if(c->mediachange){
+		r = 2;
+		c->mediachange = 0;
+		u->sectors = c->sectors;
+		u->secsize = 512;
+	} else
+		r = 1;
+	return r;
+}
+
+static int
+rio(Ctlr *c, Aoeata *a, int n, int scnt)
+{
+	int i, tag, cmd;
+
+	for(i = 0; i < 5; i++){
+		tag = hset(c, a, ACata);
+		cmd = a->cmdstat;
+		ethertxpkt(c->ctlrno, (Etherpkt*)a, n, 0);
+		memset(a, 0, sizeof *a);
+again:
+		n = etherrxpkt(c->ctlrno, (Etherpkt*)a, 125);
+		if(n == 0)
+			continue;
+		if(nhgets(a->type) != Aoetype || nhgetl(a->tag) != tag ||
+		    nhgets(a->major) != c->major || a->minor != c->minor)
+			goto again;
+		if(a->cmdstat & 0xa9){
+			print("aoe: ata rio error: %2ux\n", a->cmdstat);
+			return 0;
+		}
+		switch(cmd){
+		case Crd:
+		case Crdext:
+			if(n - sizeof *a < scnt * 512){
+				print("aoe: runt expect %d got %d\n",
+					scnt*512 + sizeof *a, n);
+				return 0;
+			}
+			return n - sizeof *a;
+		case Cwr:
+		case Cwrext:
+			return scnt * 512;
+		default:
+print("unknown cmd %ux\n", cmd);
+			break;
+		}
+	}
+	print("aoe: rio timeout\n");
+	return 0;
+}
+
+static void
+putlba(Aoeata *a, vlong lba)
+{
+	uchar *c;
+
+	c = a->lba;
+	c[0] = lba;
+	c[1] = lba >> 8;
+	c[2] = lba >> 16;
+	c[3] = lba >> 24;
+	c[4] = lba >> 32;
+	c[5] = lba >> 40;
+}
+
+/*
+ * you'll need to loop if you want to read more than 2 sectors.  for now
+ * i'm cheeting and not bothering with a loop.
+ */
+static uchar pktbuf[1024 + sizeof(Aoeata)];
+
+static int
+aoebuild(Ctlr *c, uchar *cmd, char *data, vlong lba, int scnt)
+{
+	int n;
+	Aoeata *a;
+
+	memset(pktbuf, 0, sizeof pktbuf);
+	a = (Aoeata*)pktbuf;
+	hset(c, a, ACata);
+	putlba(a, lba);
+
+	a->cmdstat = 0x20;
+	if(c->flag & Dllba){
+		a->aflag |= AAFext;
+		a->cmdstat |= 4;
+	}else{
+		a->lba[3] &= 0xf;
+		a->lba[3] |= 0xe0;		/* LBA bit+obsolete 0xa0 */
+	}
+
+	n = scnt;
+	if(n > 2)
+		n = 2;
+	a->scnt = n;
+
+	switch(*cmd){
+	case 0x2a:
+		a->aflag |= AAFwrite;
+		a->cmdstat |= 10;
+		memmove(a+1, data, n*512);
+		n = sizeof *a + n*512;
+		break;
+	case 0x28:
+		n = sizeof *a;
+		break;
+	default:
+		print("aoe: bad cmd 0x%.2ux\n", cmd[0]);
+		return -1;
+	}
+	return n;
+}
+
+static int
+aoerio(SDreq *r)
+{
+	int size, nsec, n;
+	vlong lba;
+	char *data;
+	uchar *cmd;
+	Aoeata *a;
+	Ctlr *c;
+	SDunit *unit;
+
+	unit = r->unit;
+	c = unit->dev->ctlr;
+	if(r->data == nil)
+		return SDok;
+	cmd = r->cmd;
+
+	lba = cmd[2]<<24 | cmd[3]<<16 | cmd[4]<<8 | cmd[5];	/* sic. */
+	nsec = cmd[7]<<8 | cmd[8];
+	a = (Aoeata*)pktbuf;
+	data = r->data;
+	r->rlen = 0;
+
+	for(; nsec > 0; nsec -= n){
+//		print("aoebuild(%2x, %p, %lld, %d)\n", *cmd, data, lba, nsec);
+		size = aoebuild(c, cmd, data, lba, nsec);
+		if(size < 0){
+			r->status = SDcheck;
+			return SDcheck;
+		}
+		n = a->scnt;
+		r->rlen += rio(c, a, size, n);
+		if(*cmd == 0x28)
+			memmove(r->data, a + 1, n * 512);
+		data += n * 512;
+		lba += n;
+	}
+
+	r->status = SDok;
+	return SDok;
+}
+
+SDifc sdaoeifc = {
+	"aoe",
+
+	aoepnp,
+	nil,		/* legacy */
+	nil,		/* id */
+	nil,		/* enable */
+	nil,		/* disable */
+
+	aoeverify,
+	aoeonline,
+	aoerio,
+	nil,
+	nil,
+
+	scsibio,
+};
--- /dev/null
+++ b/os/boot.original/pc/sdata.c
@@ -1,0 +1,1652 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "ureg.h"
+#include "error.h"
+
+#include "sd.h"
+
+extern SDifc sdataifc;
+
+enum {
+	DbgCONFIG	= 0x0001,	/* detected drive config info */
+	DbgIDENTIFY	= 0x0002,	/* detected drive identify info */
+	DbgSTATE	= 0x0004,	/* dump state on panic */
+	DbgPROBE	= 0x0008,	/* trace device probing */
+	DbgDEBUG	= 0x0080,	/* the current problem... */
+	DbgINL		= 0x0100,	/* That Inil20+ message we hate */
+	Dbg48BIT	= 0x0200,	/* 48-bit LBA */
+	DbgBsy		= 0x0400,	/* interrupt but Bsy (shared IRQ) */
+};
+#define DEBUG		(DbgDEBUG|DbgCONFIG)
+
+enum {					/* I/O ports */
+	Data		= 0,
+	Error		= 1,		/* (read) */
+	Features	= 1,		/* (write) */
+	Count		= 2,		/* sector count<7-0>, sector count<15-8> */
+	Ir		= 2,		/* interrupt reason (PACKET) */
+	Sector		= 3,		/* sector number */
+	Lbalo		= 3,		/* LBA<7-0>, LBA<31-24> */
+	Cyllo		= 4,		/* cylinder low */
+	Bytelo		= 4,		/* byte count low (PACKET) */
+	Lbamid		= 4,		/* LBA<15-8>, LBA<39-32> */
+	Cylhi		= 5,		/* cylinder high */
+	Bytehi		= 5,		/* byte count hi (PACKET) */
+	Lbahi		= 5,		/* LBA<23-16>, LBA<47-40> */
+	Dh		= 6,		/* Device/Head, LBA<32-14> */
+	Status		= 7,		/* (read) */
+	Command		= 7,		/* (write) */
+
+	As		= 2,		/* Alternate Status (read) */
+	Dc		= 2,		/* Device Control (write) */
+};
+
+enum {					/* Error */
+	Med		= 0x01,		/* Media error */
+	Ili		= 0x01,		/* command set specific (PACKET) */
+	Nm		= 0x02,		/* No Media */
+	Eom		= 0x02,		/* command set specific (PACKET) */
+	Abrt		= 0x04,		/* Aborted command */
+	Mcr		= 0x08,		/* Media Change Request */
+	Idnf		= 0x10,		/* no user-accessible address */
+	Mc		= 0x20,		/* Media Change */
+	Unc		= 0x40,		/* Uncorrectable data error */
+	Wp		= 0x40,		/* Write Protect */
+	Icrc		= 0x80,		/* Interface CRC error */
+};
+
+enum {					/* Features */
+	Dma		= 0x01,		/* data transfer via DMA (PACKET) */
+	Ovl		= 0x02,		/* command overlapped (PACKET) */
+};
+
+enum {					/* Interrupt Reason */
+	Cd		= 0x01,		/* Command/Data */
+	Io		= 0x02,		/* I/O direction */
+	Rel		= 0x04,		/* Bus Release */
+};
+
+enum {					/* Device/Head */
+	Dev0		= 0xA0,		/* Master */
+	Dev1		= 0xB0,		/* Slave */
+	Lba		= 0x40,		/* LBA mode */
+};
+
+enum {					/* Status, Alternate Status */
+	Err		= 0x01,		/* Error */
+	Chk		= 0x01,		/* Check error (PACKET) */
+	Drq		= 0x08,		/* Data Request */
+	Dsc		= 0x10,		/* Device Seek Complete */
+	Serv		= 0x10,		/* Service */
+	Df		= 0x20,		/* Device Fault */
+	Dmrd		= 0x20,		/* DMA ready (PACKET) */
+	Drdy		= 0x40,		/* Device Ready */
+	Bsy		= 0x80,		/* Busy */
+};
+
+enum {					/* Command */
+	Cnop		= 0x00,		/* NOP */
+	Cdr		= 0x08,		/* Device Reset */
+	Crs		= 0x20,		/* Read Sectors */
+	Crs48		= 0x24,		/* Read Sectors Ext */
+	Crd48		= 0x25,		/* Read w/ DMA Ext */
+	Crdq48		= 0x26,		/* Read w/ DMA Queued Ext */
+	Crsm48		= 0x29,		/* Read Multiple Ext */
+	Cws		= 0x30,		/* Write Sectors */
+	Cws48		= 0x34,		/* Write Sectors Ext */
+	Cwd48		= 0x35,		/* Write w/ DMA Ext */
+	Cwdq48		= 0x36,		/* Write w/ DMA Queued Ext */
+	Cwsm48		= 0x39,		/* Write Multiple Ext */
+	Cedd		= 0x90,		/* Execute Device Diagnostics */
+	Cpkt		= 0xA0,		/* Packet */
+	Cidpkt		= 0xA1,		/* Identify Packet Device */
+	Crsm		= 0xC4,		/* Read Multiple */
+	Cwsm		= 0xC5,		/* Write Multiple */
+	Csm		= 0xC6,		/* Set Multiple */
+	Crdq		= 0xC7,		/* Read DMA queued */
+	Crd		= 0xC8,		/* Read DMA */
+	Cwd		= 0xCA,		/* Write DMA */
+	Cwdq		= 0xCC,		/* Write DMA queued */
+	Cstandby	= 0xE2,		/* Standby */
+	Cid		= 0xEC,		/* Identify Device */
+	Csf		= 0xEF,		/* Set Features */
+};
+
+enum {					/* Device Control */
+	Nien		= 0x02,		/* (not) Interrupt Enable */
+	Srst		= 0x04,		/* Software Reset */
+};
+
+enum {					/* PCI Configuration Registers */
+	Bmiba		= 0x20,		/* Bus Master Interface Base Address */
+	Idetim		= 0x40,		/* IE Timing */
+	Sidetim		= 0x44,		/* Slave IE Timing */
+	Udmactl		= 0x48,		/* Ultra DMA/33 Control */
+	Udmatim		= 0x4A,		/* Ultra DMA/33 Timing */
+};
+
+enum {					/* Bus Master IDE I/O Ports */
+	Bmicx		= 0,		/* Command */
+	Bmisx		= 2,		/* Status */
+	Bmidtpx		= 4,		/* Descriptor Table Pointer */
+};
+
+enum {					/* Bmicx */
+	Ssbm		= 0x01,		/* Start/Stop Bus Master */
+	Rwcon		= 0x08,		/* Read/Write Control */
+};
+
+enum {					/* Bmisx */
+	Bmidea		= 0x01,		/* Bus Master IDE Active */
+	Idedmae		= 0x02,		/* IDE DMA Error  (R/WC) */
+	Ideints		= 0x04,		/* IDE Interrupt Status (R/WC) */
+	Dma0cap		= 0x20,		/* Drive 0 DMA Capable */
+	Dma1cap		= 0x40,		/* Drive 0 DMA Capable */
+};
+enum {					/* Physical Region Descriptor */
+	PrdEOT		= 0x80000000,	/* Bus Master IDE Active */
+};
+
+enum {					/* offsets into the identify info. */
+	Iconfig		= 0,		/* general configuration */
+	Ilcyl		= 1,		/* logical cylinders */
+	Ilhead		= 3,		/* logical heads */
+	Ilsec		= 6,		/* logical sectors per logical track */
+	Iserial		= 10,		/* serial number */
+	Ifirmware	= 23,		/* firmware revision */
+	Imodel		= 27,		/* model number */
+	Imaxrwm		= 47,		/* max. read/write multiple sectors */
+	Icapabilities	= 49,		/* capabilities */
+	Istandby	= 50,		/* device specific standby timer */
+	Ipiomode	= 51,		/* PIO data transfer mode number */
+	Ivalid		= 53,
+	Iccyl		= 54,		/* cylinders if (valid&0x01) */
+	Ichead		= 55,		/* heads if (valid&0x01) */
+	Icsec		= 56,		/* sectors if (valid&0x01) */
+	Iccap		= 57,		/* capacity if (valid&0x01) */
+	Irwm		= 59,		/* read/write multiple */
+	Ilba		= 60,		/* LBA size */
+	Imwdma		= 63,		/* multiword DMA mode */
+	Iapiomode	= 64,		/* advanced PIO modes supported */
+	Iminmwdma	= 65,		/* min. multiword DMA cycle time */
+	Irecmwdma	= 66,		/* rec. multiword DMA cycle time */
+	Iminpio		= 67,		/* min. PIO cycle w/o flow control */
+	Iminiordy	= 68,		/* min. PIO cycle with IORDY */
+	Ipcktbr		= 71,		/* time from PACKET to bus release */
+	Iserbsy		= 72,		/* time from SERVICE to !Bsy */
+	Iqdepth		= 75,		/* max. queue depth */
+	Imajor		= 80,		/* major version number */
+	Iminor		= 81,		/* minor version number */
+	Icsfs		= 82,		/* command set/feature supported */
+	Icsfe		= 85,		/* command set/feature enabled */
+	Iudma		= 88,		/* ultra DMA mode */
+	Ierase		= 89,		/* time for security erase */
+	Ieerase		= 90,		/* time for enhanced security erase */
+	Ipower		= 91,		/* current advanced power management */
+	Ilba48		= 100,		/* 48-bit LBA size (64 bits in 100-103) */
+	Irmsn		= 127,		/* removable status notification */
+	Isecstat	= 128,		/* security status */
+};
+
+typedef struct Ctlr Ctlr;
+typedef struct Drive Drive;
+
+typedef struct Prd {
+	ulong	pa;			/* Physical Base Address */
+	int	count;
+} Prd;
+
+enum {
+	Nprd		= SDmaxio/(64*1024)+2,
+};
+
+typedef struct Ctlr {
+	int	cmdport;
+	int	ctlport;
+	int	irq;
+	int	tbdf;
+
+	Pcidev*	pcidev;
+	void	(*ienable)(Ctlr*);
+	SDev*	sdev;
+
+	Drive*	drive[2];
+
+	Prd*	prdt;			/* physical region descriptor table */
+
+//	QLock;				/* current command */
+	Drive*	curdrive;
+	int	command;		/* last command issued (debugging) */
+//	Rendez;
+	int	done;
+
+	Lock;				/* register access */
+} Ctlr;
+
+typedef struct Drive {
+	Ctlr*	ctlr;
+
+	int	dev;
+	ushort	info[256];
+	int	c;			/* cylinder */
+	int	h;			/* head */
+	int	s;			/* sector */
+	vlong	sectors;		/* total */
+	int	secsize;		/* sector size */
+
+//	int	dma;			/* DMA R/W possible */
+//	int	dmactl;
+//	int	rwm;			/* read/write multiple possible */
+//	int	rwmctl;
+
+	int	pkt;			/* PACKET device, length of pktcmd */
+	uchar	pktcmd[16];
+//	int	pktdma;			/* this PACKET command using dma */
+
+	uchar	sense[18];
+	uchar	inquiry[48];
+
+//	QLock;				/* drive access */
+	int	command;		/* current command */
+	int	write;
+	uchar*	data;
+	int	dlen;
+	uchar*	limit;
+	int	count;			/* sectors */
+	int	block;			/* R/W bytes per block */
+	int	status;
+	int	error;
+	int	flags;			/* internal flags */
+} Drive;
+
+enum {					/* internal flags */
+	Lba48		= 0x1,		/* LBA48 mode */
+	Lba48always	= 0x2,		/* ... */
+};
+
+static void
+pc87415ienable(Ctlr* ctlr)
+{
+	Pcidev *p;
+	int x;
+
+	p = ctlr->pcidev;
+	if(p == nil)
+		return;
+
+	x = pcicfgr32(p, 0x40);
+	if(ctlr->cmdport == p->mem[0].bar)
+		x &= ~0x00000100;
+	else
+		x &= ~0x00000200;
+	pcicfgw32(p, 0x40, x);
+}
+
+static int
+atadebug(int cmdport, int ctlport, char* fmt, ...)
+{
+	int i, n;
+	va_list arg;
+	char buf[PRINTSIZE];
+
+	if(!(DEBUG & DbgPROBE)){
+		USED(cmdport, ctlport, fmt);
+		return 0;
+	}
+
+	va_start(arg, fmt);
+	n = vseprint(buf, buf+sizeof(buf), fmt, arg) - buf;
+	va_end(arg);
+
+	if(cmdport){
+		if(buf[n-1] == '\n')
+			n--;
+		n += snprint(buf+n, PRINTSIZE-n, " ataregs 0x%uX:",
+			cmdport);
+		for(i = Features; i < Command; i++)
+			n += snprint(buf+n, PRINTSIZE-n, " 0x%2.2uX",
+				inb(cmdport+i));
+		if(ctlport)
+			n += snprint(buf+n, PRINTSIZE-n, " 0x%2.2uX",
+				inb(ctlport+As));
+		n += snprint(buf+n, PRINTSIZE-n, "\n");
+	}
+	putstrn(buf, n);
+
+	return n;
+}
+
+static int
+ataready(int cmdport, int ctlport, int dev, int reset, int ready, int micro)
+{
+	int as;
+
+	atadebug(cmdport, ctlport, "ataready: dev %uX reset %uX ready %uX",
+		dev, reset, ready);
+
+	for(;;){
+		/*
+		 * Wait for the controller to become not busy and
+		 * possibly for a status bit to become true (usually
+		 * Drdy). Must change to the appropriate device
+		 * register set if necessary before testing for ready.
+		 * Always run through the loop at least once so it
+		 * can be used as a test for !Bsy.
+		 */
+		as = inb(ctlport+As);
+		if(as & reset){
+			/* nothing to do */;
+		}
+		else if(dev){
+			outb(cmdport+Dh, dev);
+			dev = 0;
+		}
+		else if(ready == 0 || (as & ready)){
+			atadebug(0, 0, "ataready: %d 0x%2.2uX\n", micro, as);
+			return as;
+		}
+
+		if(micro-- <= 0){
+			atadebug(0, 0, "ataready: %d 0x%2.2uX\n", micro, as);
+			break;
+		}
+		microdelay(1);
+	}
+	atadebug(cmdport, ctlport, "ataready: timeout");
+
+	return -1;
+}
+
+static int
+atacsfenabled(Drive* drive, vlong csf)
+{
+	int cmdset, i, x;
+
+	for(i = 0; i < 3; i++){
+		x = (csf>>(16*i)) & 0xFFFF;
+		if(x == 0)
+			continue;
+		cmdset = drive->info[Icsfe+i];
+		if(cmdset == 0 || cmdset == 0xFFFF)
+			return 0;
+		return cmdset & x;
+	}
+
+	return 0;
+}
+
+/*
+static int
+atasf(int cmdport, int ctlport, int dev, uchar* command)
+{
+	int as, i;
+
+	if(ataready(cmdport, ctlport, dev, Bsy|Drq, Drdy, 108*1000) < 0)
+		return -1;
+
+	for(i = Features; i < Dh; i++)
+		outb(cmdport+i, command[i]);
+	outb(cmdport+Command, Csf);
+	microdelay(100);
+	as = ataready(cmdport, ctlport, 0, Bsy, Drdy|Df|Err, 109*1000);
+	if(as < 0 || (as & (Df|Err)))
+		return -1;
+	return 0;
+}
+ */
+
+static int
+ataidentify(int cmdport, int ctlport, int dev, int pkt, void* info)
+{
+	int as, command, drdy;
+
+	if(pkt){
+		command = Cidpkt;
+		drdy = 0;
+	}
+	else{
+		command = Cid;
+		drdy = Drdy;
+	}
+	as = ataready(cmdport, ctlport, dev, Bsy|Drq, drdy, 103*1000);
+	if(as < 0)
+		return as;
+	outb(cmdport+Command, command);
+	microdelay(1);
+
+	as = ataready(cmdport, ctlport, 0, Bsy, Drq|Err, 400*1000);
+	if(as < 0)
+		return -1;
+	if(as & Err)
+		return as;
+
+	memset(info, 0, 512);
+	inss(cmdport+Data, info, 256);
+	inb(cmdport+Status);
+
+	if(DEBUG & DbgIDENTIFY){
+		int i;
+		ushort *sp;
+
+		sp = (ushort*)info;
+		for(i = 0; i < 256; i++){
+			if(i && (i%16) == 0)
+				print("\n");
+			print(" %4.4uX ", *sp);
+			sp++;
+		}
+		print("\n");
+	}
+
+	return 0;
+}
+
+static Drive*
+atadrive(int cmdport, int ctlport, int dev)
+{
+	Drive *drive;
+	int as, i, pkt;
+	uchar buf[512], *p;
+	ushort iconfig, *sp;
+
+	atadebug(0, 0, "identify: port 0x%uX dev 0x%2.2uX\n", cmdport, dev);
+	pkt = 1;
+retry:
+	as = ataidentify(cmdport, ctlport, dev, pkt, buf);
+	if(as < 0)
+		return nil;
+	if(as & Err){
+		if(pkt == 0)
+			return nil;
+		pkt = 0;
+		goto retry;
+	}
+
+	if((drive = malloc(sizeof(Drive))) == nil)
+		return nil;
+	drive->dev = dev;
+	memmove(drive->info, buf, sizeof(drive->info));
+	drive->sense[0] = 0x70;
+	drive->sense[7] = sizeof(drive->sense)-7;
+
+	drive->inquiry[2] = 2;
+	drive->inquiry[3] = 2;
+	drive->inquiry[4] = sizeof(drive->inquiry)-4;
+	p = &drive->inquiry[8];
+	sp = &drive->info[Imodel];
+	for(i = 0; i < 20; i++){
+		*p++ = *sp>>8;
+		*p++ = *sp++;
+	}
+
+	drive->secsize = 512;
+
+	/*
+	 * Beware the CompactFlash Association feature set.
+	 * Now, why this value in Iconfig just walks all over the bit
+	 * definitions used in the other parts of the ATA/ATAPI standards
+	 * is a mystery and a sign of true stupidity on someone's part.
+	 * Anyway, the standard says if this value is 0x848A then it's
+	 * CompactFlash and it's NOT a packet device.
+	 */
+	iconfig = drive->info[Iconfig];
+	if(iconfig != 0x848A && (iconfig & 0xC000) == 0x8000){
+		if(iconfig & 0x01)
+			drive->pkt = 16;
+		else
+			drive->pkt = 12;
+	}
+	else{
+		if(drive->info[Ivalid] & 0x0001){
+			drive->c = drive->info[Iccyl];
+			drive->h = drive->info[Ichead];
+			drive->s = drive->info[Icsec];
+		}
+		else{
+			drive->c = drive->info[Ilcyl];
+			drive->h = drive->info[Ilhead];
+			drive->s = drive->info[Ilsec];
+		}
+		if(drive->info[Icapabilities] & 0x0200){
+			if(drive->info[Icsfs+1] & 0x0400){
+				drive->sectors = drive->info[Ilba48]
+					|(drive->info[Ilba48+1]<<16)
+					|((vlong)drive->info[Ilba48+2]<<32);
+				drive->flags |= Lba48;
+			}
+			else{
+				drive->sectors = (drive->info[Ilba+1]<<16)
+					 |drive->info[Ilba];
+			}
+			drive->dev |= Lba;
+		}
+		else
+			drive->sectors = drive->c*drive->h*drive->s;
+	//	atarwmmode(drive, cmdport, ctlport, dev);
+	}
+//	atadmamode(drive);	
+
+	if(DEBUG & DbgCONFIG){
+		print("dev %2.2uX port %uX config %4.4uX capabilities %4.4uX",
+			dev, cmdport, iconfig, drive->info[Icapabilities]);
+		print(" mwdma %4.4uX", drive->info[Imwdma]);
+		if(drive->info[Ivalid] & 0x04)
+			print(" udma %4.4uX", drive->info[Iudma]);
+//		print(" dma %8.8uX rwm %ud", drive->dma, drive->rwm);
+		if(drive->flags&Lba48)
+			print("\tLLBA sectors %lld", drive->sectors);
+		print("\n");
+	}
+
+	return drive;
+}
+
+static void
+atasrst(int ctlport)
+{
+	/*
+	 * Srst is a big stick and may cause problems if further
+	 * commands are tried before the drives become ready again.
+	 * Also, there will be problems here if overlapped commands
+	 * are ever supported.
+	 */
+	microdelay(5);
+	outb(ctlport+Dc, Srst);
+	microdelay(5);
+	outb(ctlport+Dc, 0);
+	microdelay(2*1000);
+}
+
+static SDev*
+ataprobe(int cmdport, int ctlport, int irq)
+{
+	Ctlr* ctlr;
+	SDev *sdev;
+	Drive *drive;
+	int dev, error, rhi, rlo;
+
+//	if(ioalloc(cmdport, 8, 0, "atacmd") < 0)
+//		return nil;
+//	if(ioalloc(ctlport+As, 1, 0, "atactl") < 0){
+//		iofree(cmdport);
+//		return nil;
+//	}
+
+	/*
+	 * Try to detect a floating bus.
+	 * Bsy should be cleared. If not, see if the cylinder registers
+	 * are read/write capable.
+	 * If the master fails, try the slave to catch slave-only
+	 * configurations.
+	 * There's no need to restore the tested registers as they will
+	 * be reset on any detected drives by the Cedd command.
+	 * All this indicates is that there is at least one drive on the
+	 * controller; when the non-existent drive is selected in a
+	 * single-drive configuration the registers of the existing drive
+	 * are often seen, only command execution fails.
+	 */
+	dev = Dev0;
+	if(inb(ctlport+As) & Bsy){
+		outb(cmdport+Dh, dev);
+		microdelay(1);
+trydev1:
+		atadebug(cmdport, ctlport, "ataprobe bsy");
+		outb(cmdport+Cyllo, 0xAA);
+		outb(cmdport+Cylhi, 0x55);
+		outb(cmdport+Sector, 0xFF);
+		rlo = inb(cmdport+Cyllo);
+		rhi = inb(cmdport+Cylhi);
+		if(rlo != 0xAA && (rlo == 0xFF || rhi != 0x55)){
+			if(dev == Dev1){
+release:
+			//	iofree(cmdport);
+			//	iofree(ctlport+As);
+				return nil;
+			}
+			dev = Dev1;
+			if(ataready(cmdport, ctlport, dev, Bsy, 0, 20*1000) < 0)
+				goto trydev1;
+		}
+	}
+
+	/*
+	 * Disable interrupts on any detected controllers.
+	 */
+	outb(ctlport+Dc, Nien);
+tryedd1:
+	if(ataready(cmdport, ctlport, dev, Bsy|Drq, 0, 105*1000) < 0){
+		/*
+		 * There's something there, but it didn't come up clean,
+		 * so try hitting it with a big stick. The timing here is
+		 * wrong but this is a last-ditch effort and it sometimes
+		 * gets some marginal hardware back online.
+		 */
+		atasrst(ctlport);
+		if(ataready(cmdport, ctlport, dev, Bsy|Drq, 0, 106*1000) < 0)
+			goto release;
+	}
+
+	/*
+	 * Can only get here if controller is not busy.
+	 * If there are drives Bsy will be set within 400nS,
+	 * must wait 2mS before testing Status.
+	 * Wait for the command to complete (6 seconds max).
+	 */
+	outb(cmdport+Command, Cedd);
+	delay(2);
+	if(ataready(cmdport, ctlport, dev, Bsy|Drq, 0, 6*1000*1000) < 0)
+		goto release;
+
+	/*
+	 * If bit 0 of the error register is set then the selected drive
+	 * exists. This is enough to detect single-drive configurations.
+	 * However, if the master exists there is no way short of executing
+	 * a command to determine if a slave is present.
+	 * It appears possible to get here testing Dev0 although it doesn't
+	 * exist and the EDD won't take, so try again with Dev1.
+	 */
+	error = inb(cmdport+Error);
+	atadebug(cmdport, ctlport, "ataprobe: dev %uX", dev);
+	if((error & ~0x80) != 0x01){
+		if(dev == Dev1)
+			goto release;
+		dev = Dev1;
+		goto tryedd1;
+	}
+
+	/*
+	 * At least one drive is known to exist, try to
+	 * identify it. If that fails, don't bother checking
+	 * any further.
+	 * If the one drive found is Dev0 and the EDD command
+	 * didn't indicate Dev1 doesn't exist, check for it.
+	 */
+	if((drive = atadrive(cmdport, ctlport, dev)) == nil)
+		goto release;
+	if((ctlr = malloc(sizeof(Ctlr))) == nil){
+		free(drive);
+		goto release;
+	}
+	if((sdev = malloc(sizeof(SDev))) == nil){
+		free(ctlr);
+		free(drive);
+		goto release;
+	}
+	drive->ctlr = ctlr;
+	if(dev == Dev0){
+		ctlr->drive[0] = drive;
+		if(!(error & 0x80)){
+			/*
+			 * Always leave Dh pointing to a valid drive,
+			 * otherwise a subsequent call to ataready on
+			 * this controller may try to test a bogus Status.
+			 * Ataprobe is the only place possibly invalid
+			 * drives should be selected.
+			 */
+			drive = atadrive(cmdport, ctlport, Dev1);
+			if(drive != nil){
+				drive->ctlr = ctlr;
+				ctlr->drive[1] = drive;
+			}
+			else{
+				outb(cmdport+Dh, Dev0);
+				microdelay(1);
+			}
+		}
+	}
+	else
+		ctlr->drive[1] = drive;
+
+	ctlr->cmdport = cmdport;
+	ctlr->ctlport = ctlport;
+	ctlr->irq = irq;
+	ctlr->tbdf = BUSUNKNOWN;
+	ctlr->command = Cedd;		/* debugging */
+
+	sdev->ifc = &sdataifc;
+	sdev->ctlr = ctlr;
+	sdev->nunit = 2;
+	ctlr->sdev = sdev;
+
+	return sdev;
+}
+
+static int
+atasetsense(Drive* drive, int status, int key, int asc, int ascq)
+{
+	drive->sense[2] = key;
+	drive->sense[12] = asc;
+	drive->sense[13] = ascq;
+
+	return status;
+}
+
+static int
+atamodesense(Drive* drive, uchar* cmd)
+{
+	int len;
+
+	/*
+	 * Fake a vendor-specific request with page code 0,
+	 * return the drive info.
+	 */
+	if((cmd[2] & 0x3F) != 0 && (cmd[2] & 0x3F) != 0x3F)
+		return atasetsense(drive, SDcheck, 0x05, 0x24, 0);
+	len = (cmd[7]<<8)|cmd[8];
+	if(len == 0)
+		return SDok;
+	if(len < 8+sizeof(drive->info))
+		return atasetsense(drive, SDcheck, 0x05, 0x1A, 0);
+	if(drive->data == nil || drive->dlen < len)
+		return atasetsense(drive, SDcheck, 0x05, 0x20, 1);
+	memset(drive->data, 0, 8);
+	drive->data[0] = sizeof(drive->info)>>8;
+	drive->data[1] = sizeof(drive->info);
+	memmove(drive->data+8, drive->info, sizeof(drive->info));
+	drive->data += 8+sizeof(drive->info);
+
+	return SDok;
+}
+
+static void
+atanop(Drive* drive, int subcommand)
+{
+	Ctlr* ctlr;
+	int as, cmdport, ctlport, timeo;
+
+	/*
+	 * Attempt to abort a command by using NOP.
+	 * In response, the drive is supposed to set Abrt
+	 * in the Error register, set (Drdy|Err) in Status
+	 * and clear Bsy when done. However, some drives
+	 * (e.g. ATAPI Zip) just go Bsy then clear Status
+	 * when done, hence the timeout loop only on Bsy
+	 * and the forced setting of drive->error.
+	 */
+	ctlr = drive->ctlr;
+	cmdport = ctlr->cmdport;
+	outb(cmdport+Features, subcommand);
+	outb(cmdport+Dh, drive->dev);
+	ctlr->command = Cnop;		/* debugging */
+	outb(cmdport+Command, Cnop);
+
+	microdelay(1);
+	ctlport = ctlr->ctlport;
+	for(timeo = 0; timeo < 1000; timeo++){
+		as = inb(ctlport+As);
+		if(!(as & Bsy))
+			break;
+		microdelay(1);
+	}
+	drive->error |= Abrt;
+}
+
+static void
+ataabort(Drive* drive, int dolock)
+{
+	/*
+	 * If NOP is available (packet commands) use it otherwise
+	 * must try a software reset.
+	 */
+	if(dolock)
+		ilock(drive->ctlr);
+	if(atacsfenabled(drive, 0x0000000000004000LL))
+		atanop(drive, 0);
+	else{
+		atasrst(drive->ctlr->ctlport);
+		drive->error |= Abrt;
+	}
+	if(dolock)
+		iunlock(drive->ctlr);
+}
+
+static int
+atapktiodone(void* arg)
+{
+	return ((Ctlr*)arg)->done;
+}
+
+static void
+atapktinterrupt(Drive* drive)
+{
+	Ctlr* ctlr;
+	int cmdport, len;
+
+	ctlr = drive->ctlr;
+	cmdport = ctlr->cmdport;
+	switch(inb(cmdport+Ir) & (/*Rel|*/Io|Cd)){
+	case Cd:
+		outss(cmdport+Data, drive->pktcmd, drive->pkt/2);
+		break;
+
+	case 0:
+		len = (inb(cmdport+Bytehi)<<8)|inb(cmdport+Bytelo);
+		if(drive->data+len > drive->limit){
+			atanop(drive, 0);
+			break;
+		}
+		outss(cmdport+Data, drive->data, len/2);
+		drive->data += len;
+		break;
+
+	case Io:
+		len = (inb(cmdport+Bytehi)<<8)|inb(cmdport+Bytelo);
+		if(drive->data+len > drive->limit){
+			atanop(drive, 0);
+			break;
+		}
+		inss(cmdport+Data, drive->data, len/2);
+		drive->data += len;
+		break;
+
+	case Io|Cd:
+	//	if(drive->pktdma)
+	//		atadmainterrupt(drive, drive->dlen);
+	//	else
+			ctlr->done = 1;
+		break;
+	}
+}
+
+static int
+atapktio(Drive* drive, uchar* cmd, int clen)
+{
+	Ctlr *ctlr;
+	int as, cmdport, ctlport, len, r;
+
+	if(cmd[0] == 0x5A && (cmd[2] & 0x3F) == 0)
+		return atamodesense(drive, cmd);
+
+	r = SDok;
+
+	drive->command = Cpkt;
+	memmove(drive->pktcmd, cmd, clen);
+	memset(drive->pktcmd+clen, 0, drive->pkt-clen);
+	drive->limit = drive->data+drive->dlen;
+
+	ctlr = drive->ctlr;
+	cmdport = ctlr->cmdport;
+	ctlport = ctlr->ctlport;
+
+	qlock(ctlr);
+
+	as = ataready(cmdport, ctlport, drive->dev, Bsy|Drq, 0, 107*1000);
+	if(as < 0 || (as&Chk)){
+		qunlock(ctlr);
+		return -1;
+	}
+
+	ilock(ctlr);
+//	if(drive->dlen && drive->dmactl && !atadmasetup(drive, drive->dlen))
+//		drive->pktdma = Dma;
+//	else
+//		drive->pktdma = 0;
+
+	outb(cmdport+Features, 0/*drive->pktdma*/);
+	outb(cmdport+Count, 0);
+	outb(cmdport+Sector, 0);
+	len = 16*drive->secsize;
+	outb(cmdport+Bytelo, len);
+	outb(cmdport+Bytehi, len>>8);
+	outb(cmdport+Dh, drive->dev);
+	ctlr->done = 0;
+	ctlr->curdrive = drive;
+	ctlr->command = Cpkt;		/* debugging */
+//	if(drive->pktdma)
+//		atadmastart(ctlr, drive->write);
+	outb(cmdport+Command, Cpkt);
+
+	if((drive->info[Iconfig] & 0x0060) != 0x0020){
+		microdelay(1);
+		as = ataready(cmdport, ctlport, 0, Bsy, Drq|Chk, 4*1000);
+		if(as < 0 || (as & (Bsy|Chk))){
+			drive->status = as<0 ? 0 : as;
+			ctlr->curdrive = nil;
+			ctlr->done = 1;
+			r = SDtimeout;
+		}else
+			atapktinterrupt(drive);
+	}
+	iunlock(ctlr);
+
+	sleep(ctlr, atapktiodone, ctlr);
+
+	qunlock(ctlr);
+
+	if(drive->status & Chk)
+		r = SDcheck;
+
+	return r;
+}
+
+static int
+atageniodone(void* arg)
+{
+	return ((Ctlr*)arg)->done;
+}
+
+static uchar cmd48[256] = {
+	[Crs]	Crs48,
+	[Crd]	Crd48,
+	[Crdq]	Crdq48,
+	[Crsm]	Crsm48,
+	[Cws]	Cws48,
+	[Cwd]	Cwd48,
+	[Cwdq]	Cwdq48,
+	[Cwsm]	Cwsm48,
+};
+
+static int
+atageniostart(Drive* drive, vlong lba)
+{
+	Ctlr *ctlr;
+	uchar cmd;
+	int as, c, cmdport, ctlport, h, len, s, use48;
+
+	use48 = 0;
+	if((drive->flags&Lba48always) || (lba>>28) || drive->count > 256){
+		if(!(drive->flags & Lba48))
+			return -1;
+		use48 = 1;
+		c = h = s = 0;
+	}else if(drive->dev & Lba){
+		c = (lba>>8) & 0xFFFF;
+		h = (lba>>24) & 0x0F;
+		s = lba & 0xFF;
+	}
+	else{
+		c = lba/(drive->s*drive->h);
+		h = ((lba/drive->s) % drive->h);
+		s = (lba % drive->s) + 1;
+	}
+
+	ctlr = drive->ctlr;
+	cmdport = ctlr->cmdport;
+	ctlport = ctlr->ctlport;
+	if(ataready(cmdport, ctlport, drive->dev, Bsy|Drq, 0, 101*1000) < 0)
+		return -1;
+
+	ilock(ctlr);
+
+	drive->block = drive->secsize;
+	if(drive->write)
+		drive->command = Cws;
+	else
+		drive->command = Crs;
+
+	drive->limit = drive->data + drive->count*drive->secsize;
+	cmd = drive->command;
+	if(use48){
+		outb(cmdport+Count, (drive->count>>8) & 0xFF);
+		outb(cmdport+Count, drive->count & 0XFF);
+		outb(cmdport+Lbalo, (lba>>24) & 0xFF);
+		outb(cmdport+Lbalo, lba & 0xFF);
+		outb(cmdport+Lbamid, (lba>>32) & 0xFF);
+		outb(cmdport+Lbamid, (lba>>8) & 0xFF);
+		outb(cmdport+Lbahi, (lba>>40) & 0xFF);
+		outb(cmdport+Lbahi, (lba>>16) & 0xFF);
+		outb(cmdport+Dh, drive->dev|Lba);
+		cmd = cmd48[cmd];
+
+		if(DEBUG & Dbg48BIT)
+			print("using 48-bit commands\n");
+	}else{
+		outb(cmdport+Count, drive->count);
+		outb(cmdport+Sector, s);
+		outb(cmdport+Cyllo, c);
+		outb(cmdport+Cylhi, c>>8);
+		outb(cmdport+Dh, drive->dev|h);
+	}
+	ctlr->done = 0;
+	ctlr->curdrive = drive;
+	ctlr->command = drive->command;	/* debugging */
+	outb(cmdport+Command, cmd);
+
+	switch(drive->command){
+	case Cws:
+	case Cwsm:
+		microdelay(1);
+		as = ataready(cmdport, ctlport, 0, Bsy, Drq|Err, 1000);
+		if(as < 0 || (as & Err)){
+			iunlock(ctlr);
+			return -1;
+		}
+		len = drive->block;
+		if(drive->data+len > drive->limit)
+			len = drive->limit-drive->data;
+		outss(cmdport+Data, drive->data, len/2);
+		break;
+
+	case Crd:
+	case Cwd:
+	//	atadmastart(ctlr, drive->write);
+		break;
+	}
+	iunlock(ctlr);
+
+	return 0;
+}
+
+static int
+atagenioretry(Drive* drive)
+{
+	return atasetsense(drive, SDcheck, 4, 8, drive->error);
+}
+
+static int
+atagenio(Drive* drive, uchar* cmd, int)
+{
+	uchar *p;
+	Ctlr *ctlr;
+	int count, max;
+	vlong lba, len;
+
+	/*
+	 * Map SCSI commands into ATA commands for discs.
+	 * Fail any command with a LUN except INQUIRY which
+	 * will return 'logical unit not supported'.
+	 */
+	if((cmd[1]>>5) && cmd[0] != 0x12)
+		return atasetsense(drive, SDcheck, 0x05, 0x25, 0);
+
+	switch(cmd[0]){
+	default:
+		return atasetsense(drive, SDcheck, 0x05, 0x20, 0);
+
+	case 0x00:			/* test unit ready */
+		return SDok;
+
+	case 0x03:			/* request sense */
+		if(cmd[4] < sizeof(drive->sense))
+			len = cmd[4];
+		else
+			len = sizeof(drive->sense);
+		if(drive->data && drive->dlen >= len){
+			memmove(drive->data, drive->sense, len);
+			drive->data += len;
+		}
+		return SDok;
+
+	case 0x12:			/* inquiry */
+		if(cmd[4] < sizeof(drive->inquiry))
+			len = cmd[4];
+		else
+			len = sizeof(drive->inquiry);
+		if(drive->data && drive->dlen >= len){
+			memmove(drive->data, drive->inquiry, len);
+			drive->data += len;
+		}
+		return SDok;
+
+	case 0x1B:			/* start/stop unit */
+		/*
+		 * NOP for now, can use the power management feature
+		 * set later.
+		 */
+		return SDok;
+
+	case 0x25:			/* read capacity */
+		if((cmd[1] & 0x01) || cmd[2] || cmd[3])
+			return atasetsense(drive, SDcheck, 0x05, 0x24, 0);
+		if(drive->data == nil || drive->dlen < 8)
+			return atasetsense(drive, SDcheck, 0x05, 0x20, 1);
+		/*
+		 * Read capacity returns the LBA of the last sector.
+		 */
+		len = drive->sectors-1;
+		p = drive->data;
+		*p++ = len>>24;
+		*p++ = len>>16;
+		*p++ = len>>8;
+		*p++ = len;
+		len = drive->secsize;
+		*p++ = len>>24;
+		*p++ = len>>16;
+		*p++ = len>>8;
+		*p = len;
+		drive->data += 8;
+		return SDok;
+
+	case 0x9E:			/* long read capacity */
+		if((cmd[1] & 0x01) || cmd[2] || cmd[3])
+			return atasetsense(drive, SDcheck, 0x05, 0x24, 0);
+		if(drive->data == nil || drive->dlen < 8)
+			return atasetsense(drive, SDcheck, 0x05, 0x20, 1);
+		/*
+		 * Read capacity returns the LBA of the last sector.
+		 */
+		len = drive->sectors-1;
+		p = drive->data;
+		*p++ = len>>56;
+		*p++ = len>>48;
+		*p++ = len>>40;
+		*p++ = len>>32;
+		*p++ = len>>24;
+		*p++ = len>>16;
+		*p++ = len>>8;
+		*p++ = len;
+		len = drive->secsize;
+		*p++ = len>>24;
+		*p++ = len>>16;
+		*p++ = len>>8;
+		*p = len;
+		drive->data += 8;
+		return SDok;
+
+	case 0x28:			/* read */
+	case 0x2A:			/* write */
+		break;
+
+	case 0x5A:
+		return atamodesense(drive, cmd);
+	}
+
+	ctlr = drive->ctlr;
+	lba = (cmd[2]<<24)|(cmd[3]<<16)|(cmd[4]<<8)|cmd[5];
+	count = (cmd[7]<<8)|cmd[8];
+	if(drive->data == nil)
+		return SDok;
+	if(drive->dlen < count*drive->secsize)
+		count = drive->dlen/drive->secsize;
+	qlock(ctlr);
+	while(count){
+		max = (drive->flags&Lba48) ? 65536 : 256;
+		if(count > max)
+			drive->count = max;
+		else
+			drive->count = count;
+		if(atageniostart(drive, lba)){
+			ilock(ctlr);
+			atanop(drive, 0);
+			iunlock(ctlr);
+			qunlock(ctlr);
+			return atagenioretry(drive);
+		}
+
+		tsleep(ctlr, atageniodone, ctlr, 10*1000);
+		if(!ctlr->done){
+			/*
+			 * What should the above timeout be? In
+			 * standby and sleep modes it could take as
+			 * long as 30 seconds for a drive to respond.
+			 * Very hard to get out of this cleanly.
+			 */
+		//	atadumpstate(drive, cmd, lba, count);
+			ataabort(drive, 1);
+			return atagenioretry(drive);
+		}
+
+		if(drive->status & Err){
+			qunlock(ctlr);
+			return atasetsense(drive, SDcheck, 4, 8, drive->error);
+		}
+		count -= drive->count;
+		lba += drive->count;
+	}
+	qunlock(ctlr);
+
+	return SDok;
+}
+
+static int
+atario(SDreq* r)
+{
+	Ctlr *ctlr;
+	Drive *drive;
+	SDunit *unit;
+	uchar cmd10[10], *cmdp, *p;
+	int clen, reqstatus, status;
+
+	unit = r->unit;
+	if((ctlr = unit->dev->ctlr) == nil || ctlr->drive[unit->subno] == nil){
+		r->status = SDtimeout;
+		return SDtimeout;
+	}
+	drive = ctlr->drive[unit->subno];
+
+	/*
+	 * Most SCSI commands can be passed unchanged except for
+	 * the padding on the end. The few which require munging
+	 * are not used internally. Mode select/sense(6) could be
+	 * converted to the 10-byte form but it's not worth the
+	 * effort. Read/write(6) are easy.
+	 */
+	switch(r->cmd[0]){
+	case 0x08:			/* read */
+	case 0x0A:			/* write */
+		cmdp = cmd10;
+		memset(cmdp, 0, sizeof(cmd10));
+		cmdp[0] = r->cmd[0]|0x20;
+		cmdp[1] = r->cmd[1] & 0xE0;
+		cmdp[5] = r->cmd[3];
+		cmdp[4] = r->cmd[2];
+		cmdp[3] = r->cmd[1] & 0x0F;
+		cmdp[8] = r->cmd[4];
+		clen = sizeof(cmd10);
+		break;
+
+	default:
+		cmdp = r->cmd;
+		clen = r->clen;
+		break;
+	}
+
+	qlock(drive);
+	drive->write = r->write;
+	drive->data = r->data;
+	drive->dlen = r->dlen;
+
+	drive->status = 0;
+	drive->error = 0;
+	if(drive->pkt)
+		status = atapktio(drive, cmdp, clen);
+	else
+		status = atagenio(drive, cmdp, clen);
+	if(status == SDok){
+		atasetsense(drive, SDok, 0, 0, 0);
+		if(drive->data){
+			p = r->data;
+			r->rlen = drive->data - p;
+		}
+		else
+			r->rlen = 0;
+	}
+	else if(status == SDcheck && !(r->flags & SDnosense)){
+		drive->write = 0;
+		memset(cmd10, 0, sizeof(cmd10));
+		cmd10[0] = 0x03;
+		cmd10[1] = r->lun<<5;
+		cmd10[4] = sizeof(r->sense)-1;
+		drive->data = r->sense;
+		drive->dlen = sizeof(r->sense)-1;
+		drive->status = 0;
+		drive->error = 0;
+		if(drive->pkt)
+			reqstatus = atapktio(drive, cmd10, 6);
+		else
+			reqstatus = atagenio(drive, cmd10, 6);
+		if(reqstatus == SDok){
+			r->flags |= SDvalidsense;
+			atasetsense(drive, SDok, 0, 0, 0);
+		}
+	}
+	qunlock(drive);
+	r->status = status;
+	if(status != SDok)
+		return status;
+
+	/*
+	 * Fix up any results.
+	 * Many ATAPI CD-ROMs ignore the LUN field completely and
+	 * return valid INQUIRY data. Patch the response to indicate
+	 * 'logical unit not supported' if the LUN is non-zero.
+	 */
+	switch(cmdp[0]){
+	case 0x12:			/* inquiry */
+		if((p = r->data) == nil)
+			break;
+		if((cmdp[1]>>5) && (!drive->pkt || (p[0] & 0x1F) == 0x05))
+			p[0] = 0x7F;
+		/*FALLTHROUGH*/
+	default:
+		break;
+	}
+
+	return SDok;
+}
+
+static void
+atainterrupt(Ureg*, void* arg)
+{
+	Ctlr *ctlr;
+	Drive *drive;
+	int cmdport, len, status;
+
+	ctlr = arg;
+
+	ilock(ctlr);
+	if(inb(ctlr->ctlport+As) & Bsy){
+		iunlock(ctlr);
+		if(DEBUG & DbgBsy)
+			print("IBsy+");
+		return;
+	}
+	cmdport = ctlr->cmdport;
+	status = inb(cmdport+Status);
+	if((drive = ctlr->curdrive) == nil){
+		iunlock(ctlr);
+		if((DEBUG & DbgINL) && ctlr->command != Cedd)
+			print("Inil%2.2uX+", ctlr->command);
+		return;
+	}
+
+	if(status & Err)
+		drive->error = inb(cmdport+Error);
+	else switch(drive->command){
+	default:
+		drive->error = Abrt;
+		break;
+
+	case Crs:
+	case Crsm:
+		if(!(status & Drq)){
+			drive->error = Abrt;
+			break;
+		}
+		len = drive->block;
+		if(drive->data+len > drive->limit)
+			len = drive->limit-drive->data;
+		inss(cmdport+Data, drive->data, len/2);
+		drive->data += len;
+		if(drive->data >= drive->limit)
+			ctlr->done = 1;
+		break;
+
+	case Cws:
+	case Cwsm:
+		len = drive->block;
+		if(drive->data+len > drive->limit)
+			len = drive->limit-drive->data;
+		drive->data += len;
+		if(drive->data >= drive->limit){
+			ctlr->done = 1;
+			break;
+		}
+		if(!(status & Drq)){
+			drive->error = Abrt;
+			break;
+		}
+		len = drive->block;
+		if(drive->data+len > drive->limit)
+			len = drive->limit-drive->data;
+		outss(cmdport+Data, drive->data, len/2);
+		break;
+
+	case Cpkt:
+		atapktinterrupt(drive);
+		break;
+
+	case Crd:
+	case Cwd:
+	//	atadmainterrupt(drive, drive->count*drive->secsize);
+		break;
+	}
+	iunlock(ctlr);
+
+	if(drive->error){
+		status |= Err;
+		ctlr->done = 1;
+	}
+
+	if(ctlr->done){
+		ctlr->curdrive = nil;
+		drive->status = status;
+		wakeup(ctlr);
+	}
+}
+
+static SDev*
+atapnp(void)
+{
+	Ctlr *ctlr;
+	Pcidev *p;
+	int channel, ispc87415, pi, r;
+	SDev *legacy[2], *sdev, *head, *tail;
+
+	legacy[0] = legacy[1] = head = tail = nil;
+	if(sdev = ataprobe(0x1F0, 0x3F4, IrqATA0)){
+		head = tail = sdev;
+		legacy[0] = sdev;
+	}
+	if(sdev = ataprobe(0x170, 0x374, IrqATA1)){
+		if(head != nil)
+			tail->next = sdev;
+		else
+			head = sdev;
+		tail = sdev;
+		legacy[1] = sdev;
+	}
+
+	p = nil;
+	while(p = pcimatch(p, 0, 0)){
+		/*
+		 * Look for devices with the correct class and sub-class
+		 * code and known device and vendor ID; add native-mode
+		 * channels to the list to be probed, save info for the
+		 * compatibility mode channels.
+		 * Note that the legacy devices should not be considered
+		 * PCI devices by the interrupt controller.
+		 * For both native and legacy, save info for busmastering
+		 * if capable.
+		 * Promise Ultra ATA/66 (PDC20262) appears to
+		 * 1) give a sub-class of 'other mass storage controller'
+		 *    instead of 'IDE controller', regardless of whether it's
+		 *    the only controller or not;
+		 * 2) put 0 in the programming interface byte (probably
+		 *    as a consequence of 1) above).
+		 * Sub-class code 0x04 is 'RAID controller', e.g. VIA VT8237.
+		 */
+		if(p->ccrb != 0x01)
+			continue;
+		if(p->ccru != 0x01 && p->ccru != 0x04 && p->ccru != 0x80)
+			continue;
+		pi = p->ccrp;
+		ispc87415 = 0;
+
+		switch((p->did<<16)|p->vid){
+		default:
+			continue;
+
+		case (0x0002<<16)|0x100B:	/* NS PC87415 */
+			/*
+			 * Disable interrupts on both channels until
+			 * after they are probed for drives.
+			 * This must be called before interrupts are
+			 * enabled because the IRQ may be shared.
+			 */
+			ispc87415 = 1;
+			pcicfgw32(p, 0x40, 0x00000300);
+			break;
+		case (0x1000<<16)|0x1042:	/* PC-Tech RZ1000 */
+			/*
+			 * Turn off prefetch. Overkill, but cheap.
+			 */
+			r = pcicfgr32(p, 0x40);
+			r &= ~0x2000;
+			pcicfgw32(p, 0x40, r);
+			break;
+		case (0x4D38<<16)|0x105A:	/* Promise PDC20262 */
+		case (0x4D30<<16)|0x105A:	/* Promise PDC202xx */
+		case (0x4D68<<16)|0x105A:	/* Promise PDC20268 */
+		case (0x4D69<<16)|0x105A:	/* Promise Ultra/133 TX2 */
+		case (0x3373<<16)|0x105A:	/* Promise 20378 RAID */
+		case (0x3149<<16)|0x1106:	/* VIA VT8237 SATA/RAID */
+		case (0x4379<<16)|0x1002:	/* ATI 4379 SATA*/
+		case (0x3112<<16)|0x1095:	/* SiL 3112 SATA (DMA busted?) */
+		case (0x3114<<16)|0x1095:	/* SiL 3114 SATA/RAID */
+			pi = 0x85;
+			break;
+		case (0x0004<<16)|0x1103:	/* HighPoint HPT-370 */
+			pi = 0x85;
+			/*
+			 * Turn off fast interrupt prediction.
+			 */
+			if((r = pcicfgr8(p, 0x51)) & 0x80)
+				pcicfgw8(p, 0x51, r & ~0x80);
+			if((r = pcicfgr8(p, 0x55)) & 0x80)
+				pcicfgw8(p, 0x55, r & ~0x80);
+			break;
+		case (0x0640<<16)|0x1095:	/* CMD 640B */
+			/*
+			 * Bugfix code here...
+			 */
+			break;
+		case (0x7441<<16)|0x1022:	/* AMD 768 */
+			/*
+			 * Set:
+			 *	0x41	prefetch, postwrite;
+			 *	0x43	FIFO configuration 1/2 and 1/2;
+			 *	0x44	status register read retry;
+			 *	0x46	DMA read and end of sector flush.
+			 */
+			r = pcicfgr8(p, 0x41);
+			pcicfgw8(p, 0x41, r|0xF0);
+			r = pcicfgr8(p, 0x43);
+			pcicfgw8(p, 0x43, (r & 0x90)|0x2A);
+			r = pcicfgr8(p, 0x44);
+			pcicfgw8(p, 0x44, r|0x08);
+			r = pcicfgr8(p, 0x46);
+			pcicfgw8(p, 0x46, (r & 0x0C)|0xF0);
+			/*FALLTHROUGH*/
+		case (0x7469<<16)|0x1022:	/* AMD 3111 */
+			/*
+			 * This can probably be lumped in with the 768 above.
+			 */
+			/*FALLTHROUGH*/
+		case (0x209A<<16)|0x1022:	/* AMD CS5536 */
+		case (0x01BC<<16)|0x10DE:	/* nVidia nForce1 */
+		case (0x0065<<16)|0x10DE:	/* nVidia nForce2 */
+		case (0x0085<<16)|0x10DE:	/* nVidia nForce2 MCP */
+		case (0x00D5<<16)|0x10DE:	/* nVidia nForce3 */
+		case (0x00E5<<16)|0x10DE:	/* nVidia nForce3 Pro */
+		case (0x0035<<16)|0x10DE:	/* nVidia nForce3 MCP */
+		case (0x0053<<16)|0x10DE:	/* nVidia nForce4 */
+		case (0x0054<<16)|0x10DE:	/* nVidia nForce4 SATA */
+		case (0x0055<<16)|0x10DE:	/* nVidia nForce4 SATA */
+			/*
+			 * Ditto, although it may have a different base
+			 * address for the registers (0x50?).
+			 */
+			break;
+		case (0x0646<<16)|0x1095:	/* CMD 646 */
+		case (0x0571<<16)|0x1106:	/* VIA 82C686 */
+		case (0x0211<<16)|0x1166:	/* ServerWorks IB6566 */
+		case (0x1230<<16)|0x8086:	/* 82371FB (PIIX) */
+		case (0x7010<<16)|0x8086:	/* 82371SB (PIIX3) */
+		case (0x7111<<16)|0x8086:	/* 82371[AE]B (PIIX4[E]) */
+		case (0x2411<<16)|0x8086:	/* 82801AA (ICH) */
+		case (0x2421<<16)|0x8086:	/* 82801AB (ICH0) */
+		case (0x244A<<16)|0x8086:	/* 82801BA (ICH2, Mobile) */
+		case (0x244B<<16)|0x8086:	/* 82801BA (ICH2, High-End) */
+		case (0x248A<<16)|0x8086:	/* 82801CA (ICH3, Mobile) */
+		case (0x248B<<16)|0x8086:	/* 82801CA (ICH3, High-End) */
+		case (0x24CA<<16)|0x8086:	/* 82801DBM (ICH4, Mobile) */
+		case (0x24CB<<16)|0x8086:	/* 82801DB (ICH4, High-End) */
+		case (0x24DB<<16)|0x8086:	/* 82801EB (ICH5) */
+		case (0x266F<<16)|0x8086:	/* 82801FB (ICH6) */
+		case (0x27C4<<16)|0x8086:	/* 82801GBM SATA (ICH7) */
+		case (0x27C5<<16)|0x8086:	/* 82801GBM SATA AHCI (ICH7) */
+			break;
+		}
+
+		for(channel = 0; channel < 2; channel++){
+			if(pi & (1<<(2*channel))){
+				sdev = ataprobe(p->mem[0+2*channel].bar & ~0x01,
+						p->mem[1+2*channel].bar & ~0x01,
+						p->intl);
+				if(sdev == nil)
+					continue;
+
+				ctlr = sdev->ctlr;
+				if(ispc87415)
+					ctlr->ienable = pc87415ienable;
+
+				if(head != nil)
+					tail->next = sdev;
+				else
+					head = sdev;
+				tail = sdev;
+				ctlr->tbdf = p->tbdf;
+			}
+			else if((sdev = legacy[channel]) == nil)
+				continue;
+			else
+				ctlr = sdev->ctlr;
+
+			ctlr->pcidev = p;
+		}
+	}
+
+	return head;
+}
+
+static SDev*
+atalegacy(int port, int irq)
+{
+	return ataprobe(port, port+0x204, irq);
+}
+
+static SDev*
+ataid(SDev* sdev)
+{
+	int i;
+	Ctlr *ctlr;
+
+	/*
+	 * Legacy controllers are always 'C' and 'D' and if
+	 * they exist and have drives will be first in the list.
+	 * If there are no active legacy controllers, native
+	 * controllers start at 'C'.
+	 */
+	if(sdev == nil)
+		return nil;
+	ctlr = sdev->ctlr;
+	if(ctlr->cmdport == 0x1F0 || ctlr->cmdport == 0x170)
+		i = 2;
+	else
+		i = 0;
+	while(sdev){
+		if(sdev->ifc == &sdataifc){
+			ctlr = sdev->ctlr;
+			if(ctlr->cmdport == 0x1F0)
+				sdev->idno = 'C';
+			else if(ctlr->cmdport == 0x170)
+				sdev->idno = 'D';
+			else{
+				sdev->idno = 'C'+i;
+				i++;
+			}
+		//	snprint(sdev->name, NAMELEN, "sd%c", sdev->idno);
+		}
+		sdev = sdev->next;
+	}
+
+	return nil;
+}
+
+static int
+ataenable(SDev* sdev)
+{
+	Ctlr *ctlr;
+
+	ctlr = sdev->ctlr;
+
+	setvec(ctlr->irq+VectorPIC, atainterrupt, ctlr);
+	outb(ctlr->ctlport+Dc, 0);
+	if(ctlr->ienable)
+		ctlr->ienable(ctlr);
+
+	return 1;
+}
+
+SDifc sdataifc = {
+	"ata",				/* name */
+
+	atapnp,				/* pnp */
+	atalegacy,			/* legacy */
+	ataid,				/* id */
+	ataenable,			/* enable */
+	nil,				/* disable */
+
+	scsiverify,			/* verify */
+	scsionline,			/* online */
+	atario,				/* rio */
+	nil,			/* rctl */
+	nil,			/* wctl */
+
+	scsibio,			/* bio */
+};
--- /dev/null
+++ b/os/boot.original/pc/sdbios.c
@@ -1,0 +1,165 @@
+/*
+ * boot driver for BIOS devices with partitions
+ * devbios must be called first
+ */
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "ureg.h"
+#include "error.h"
+
+#include "sd.h"
+#include "fs.h"
+
+long	biosread(Fs *, void *, long);
+vlong	biosseek(Fs *fs, vlong off);
+
+extern SDifc sdbiosifc;
+extern int onlybios0, biosinited;
+
+int
+biosverify(SDunit* )
+{
+	if (onlybios0 || !biosinited)
+		return 0;
+	return 1;
+}
+
+int
+biosonline(SDunit* unit)
+{
+	if (onlybios0 || !biosinited || !unit)
+		return 0;
+	unit->sectors = 1UL << 30;	/* a bunch */
+	unit->secsize = 512;		/* conventional */
+	return 1;
+}
+
+static int
+biosrio(SDreq* r)
+{
+	int nb;
+	long got;
+	vlong len, off;
+	uchar *p;
+	Fs fs;			/* just for fs->dev, which is zero */
+
+	if (onlybios0 || !biosinited)
+		return SDeio;
+	/*
+	 * Most SCSI commands can be passed unchanged except for
+	 * the padding on the end. The few which require munging
+	 * are not used internally. Mode select/sense(6) could be
+	 * converted to the 10-byte form but it's not worth the
+	 * effort. Read/write(6) are easy.
+	 */
+	r->rlen = 0;
+	r->status = SDok;
+	switch(r->cmd[0]){
+	case 0x08:			/* read */
+	case 0x28:			/* read */
+		if (r->cmd[0] == 0x08)
+			panic("biosrio: 0x08 read op\n");
+		off = r->cmd[2]<<24 | r->cmd[3]<<16 | r->cmd[4]<<8 | r->cmd[5];
+		nb = r->cmd[7]<<8 | r->cmd[8];	/* often 4 */
+		USED(nb);		/* is nb*512 == r->dlen? */
+		memset(&fs, 0, sizeof fs);
+		biosseek(&fs, off*512);
+		got = biosread(&fs, r->data, r->dlen);
+		if (got < 0)
+			r->status = SDeio;
+		else
+			r->rlen = got;
+		break;
+	case 0x0A:			/* write */
+	case 0x2A:			/* write */
+		r->status = SDeio;	/* boot programs don't write */
+		break;
+	case 0x25:			/* read capacity */
+		/*
+		 * Read capacity returns the LBA of the last sector.
+		 */
+		len = r->unit->sectors - 1;
+		p = r->data;
+		*p++ = len>>24;
+		*p++ = len>>16;
+		*p++ = len>>8;
+		*p++ = len;
+		len = r->unit->secsize;
+		*p++ = len>>24;
+		*p++ = len>>16;
+		*p++ = len>>8;
+		*p = len;
+		r->data = (char *)r->data + 8;
+		return SDok;
+	case 0x9E:			/* long read capacity */
+		/*
+		 * Read capacity returns the LBA of the last sector.
+		 */
+		len = r->unit->sectors - 1;
+		p = r->data;
+		*p++ = len>>56;
+		*p++ = len>>48;
+		*p++ = len>>40;
+		*p++ = len>>32;
+		*p++ = len>>24;
+		*p++ = len>>16;
+		*p++ = len>>8;
+		*p++ = len;
+		len = r->unit->secsize;
+		*p++ = len>>24;
+		*p++ = len>>16;
+		*p++ = len>>8;
+		*p = len;
+		r->data = (char *)r->data + 8;
+		return SDok;
+	/* ignore others */
+	}
+	return r->status;
+}
+
+SDev*
+biosid(SDev* sdev)
+{
+	for (; sdev; sdev = sdev->next)
+		if (sdev->ifc == &sdbiosifc)
+			sdev->idno = 'B';
+	return sdev;
+}
+
+static SDev*
+biospnp(void)
+{
+	SDev *sdev;
+
+	/* 9pxeload can't use bios int 13 calls; they wedge the machine */
+	if (pxe || getconf("*nobiosload") != nil || onlybios0 || !biosinited)
+		return nil;
+	if((sdev = malloc(sizeof(SDev))) != nil) {
+		sdev->ifc = &sdbiosifc;
+		sdev->index = -1;
+		sdev->nunit = 1;
+	}
+	return sdev;
+}
+
+SDifc sdbiosifc = {
+	"bios",				/* name */
+
+	biospnp,			/* pnp */
+	nil,				/* legacy */
+	biosid,				/* id */
+	nil,				/* enable */
+	nil,				/* disable */
+
+	biosverify,			/* verify */
+	biosonline,			/* online */
+	biosrio,			/* rio */
+	nil,				/* rctl */
+	nil,				/* wctl */
+
+	scsibio,			/* bio */
+};
--- /dev/null
+++ b/os/boot.original/pc/sdiahci.c
@@ -1,0 +1,1668 @@
+/*
+ * intel/amd ahci (advanced host controller interface) sata controller
+ * bootstrap driver
+ * copyright © 2007, 2008 coraid, inc.
+ */
+
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "error.h"
+#include "sd.h"
+#include "ahci.h"
+
+#define	dprint	if(debug==0){}else print
+#define	idprint	if(prid==0){}else print
+#define	aprint	if(datapi==0){}else print
+
+enum {
+	NCtlr	= 2,
+	NCtlrdrv= 8,
+	NDrive	= NCtlr*NCtlrdrv,
+
+	Read	= 0,
+	Write
+};
+
+/* pci space configurtion */
+enum {
+	Pmap	= 0x90,
+	Ppcs	= 0x91,
+	Prev	= 0xa8,
+};
+
+enum {
+	Tesb,
+	Tich,
+	Tsb600,
+};
+
+#define Intel(x)	((x) == Tesb  || (x) == Tich)
+
+static char *tname[] = {
+	"63xxesb",
+	"ich",
+	"sb600",
+};
+
+enum {
+	Dnull,
+	Dmissing,
+	Dnew,
+	Dready,
+	Derror,
+	Dreset,
+	Doffline,
+	Dportreset,
+	Dlast
+};
+
+static char *diskstates[Dlast] = {
+	"null",
+	"missing",
+	"new",
+	"ready",
+	"error",
+	"reset",
+	"offline",
+	"portreset",
+};
+
+extern SDifc sdiahciifc;
+typedef struct Ctlr Ctlr;
+
+enum {
+	DMautoneg,
+	DMsatai,
+	DMsataii,
+};
+
+static char *modename[] = {
+	"auto",
+	"satai",
+	"sataii",
+};
+
+typedef struct {
+	Lock;
+
+	Ctlr	*ctlr;
+	SDunit	*unit;
+	char	name[10];
+	Aport	*port;
+	Aportm	portm;
+	Aportc	portc;		/* redundant ptr to port and portm. */
+
+	uchar	mediachange;
+	uchar	state;
+	uchar	smartrs;
+
+	uvlong	sectors;
+	ulong	intick;
+	int	wait;
+	uchar	mode;		/* DMautoneg, satai or sataii. */
+	uchar	active;
+
+	char	serial[20+1];
+	char	firmware[8+1];
+	char	model[40+1];
+
+	ushort	info[0x200];
+
+	int	driveno;	/* ctlr*NCtlrdrv + unit */
+	int	portno;	/* ctlr port # != drive # when not all ports enabled. */
+} Drive;
+
+struct Ctlr {
+	Lock;
+
+	int	type;
+	int	enabled;
+	SDev	*sdev;
+	Pcidev	*pci;
+
+	uchar	*mmio;
+	ulong	*lmmio;
+	Ahba	*hba;
+
+	Drive	rawdrive[NCtlrdrv];
+	Drive*	drive[NCtlrdrv];
+	int	ndrive;
+};
+
+static	Ctlr	iactlr[NCtlr];
+static	SDev	sdevs[NCtlr];
+static	int	niactlr;
+
+static	int	prid = 0;
+static	int	datapi = 0;
+
+static char stab[] = {
+[0]	'i', 'm',
+[8]	't', 'c', 'p', 'e',
+[16]	'N', 'I', 'W', 'B', 'D', 'C', 'H', 'S', 'T', 'F', 'X'
+};
+
+static void
+serrstr(ulong r, char *s, char *e)
+{
+	int i;
+
+	e -= 3;
+	for(i = 0; i < nelem(stab) && s < e; i++)
+		if((r & (1<<i)) && stab[i]){
+			*s++ = stab[i];
+			if(SerrBad & (1<<i))
+				*s++ = '*';
+		}
+	*s = 0;
+}
+
+static char ntab[] = "0123456789abcdef";
+
+static void
+preg(uchar *reg, int n)
+{
+	int i;
+	char buf[25*3+1], *e;
+
+	e = buf;
+	for(i = 0; i < n; i++){
+		*e++ = ntab[reg[i] >> 4];
+		*e++ = ntab[reg[i] & 0xf];
+		*e++ = ' ';
+	}
+	*e++ = '\n';
+	*e = 0;
+	dprint(buf);
+}
+
+static void
+dreg(char *s, Aport *p)
+{
+	dprint("%stask=%lux; cmd=%lux; ci=%lux; is=%lux\n",
+		s, p->task, p->cmd, p->ci, p->isr);
+}
+
+static void
+esleep(int ms)
+{
+	delay(ms);
+}
+
+typedef struct {
+	Aport	*p;
+	int	i;
+} Asleep;
+
+static int
+ahciclear(void *v)
+{
+	Asleep *s;
+
+	s = v;
+	return (s->p->ci & s->i) == 0;
+}
+
+static void
+aesleep(Aportm *, Asleep *a, int ms)
+{
+	ulong start;
+
+	start = m->ticks;
+	while((a->p->ci & a->i) != 0)
+		if(TK2MS(m->ticks-start) >= ms)
+			break;
+}
+
+static int
+ahciwait(Aportc *c, int ms)
+{
+	Aport *p;
+	Asleep as;
+
+	p = c->p;
+	p->ci = 1;
+	as.p = p;
+	as.i = 1;
+	aesleep(c->m, &as, ms);
+	if((p->task & 1) == 0 && p->ci == 0)
+		return 0;
+	dreg("ahciwait timeout ", c->p);
+	return -1;
+}
+
+static int
+setfeatures(Aportc *pc, uchar f)
+{
+	uchar *c;
+	Actab *t;
+	Alist *l;
+
+	t = pc->m->ctab;
+	c = t->cfis;
+
+	memset(c, 0, 0x20);
+	c[0] = 0x27;
+	c[1] = 0x80;
+	c[2] = 0xef;
+	c[3] = f;
+	c[7] = 0xa0;		/* obsolete device bits */
+
+	l = pc->m->list;
+	l->flags = Lwrite|0x5;
+	l->len = 0;
+	l->ctab = PCIWADDR(t);
+	l->ctabhi = 0;
+
+	return ahciwait(pc, 3*1000);
+}
+
+static int
+setudmamode(Aportc *pc, uchar f)
+{
+	uchar *c;
+	Actab *t;
+	Alist *l;
+
+	t = pc->m->ctab;
+	c = t->cfis;
+
+	memset(c, 0, 0x20);
+	c[0] = 0x27;
+	c[1] = 0x80;
+	c[2] = 0xef;
+	c[3] = 3;		/* set transfer mode */
+	c[7] = 0xa0;		/* obsolete device bits */
+	c[12] = 0x40 | f;	/* sector count */
+
+	l = pc->m->list;
+	l->flags = Lwrite | 0x5;
+	l->len = 0;
+	l->ctab = PCIWADDR(t);
+	l->ctabhi = 0;
+
+	return ahciwait(pc, 3*1000);
+}
+
+static void
+asleep(int ms)
+{
+	delay(ms);
+}
+
+static int
+ahciportreset(Aportc *c)
+{
+	ulong *cmd, i;
+	Aport *p;
+
+	p = c->p;
+	cmd = &p->cmd;
+	*cmd &= ~(Afre|Ast);
+	for(i = 0; i < 500; i += 25){
+		if((*cmd & Acr) == 0)
+			break;
+		asleep(25);
+	}
+	p->sctl = 1 | (p->sctl & ~7);
+	delay(1);
+	p->sctl &= ~7;
+	return 0;
+}
+
+static ushort
+gbit16(void *a)
+{
+	uchar *i;
+
+	i = a;
+	return i[1]<<8 | i[0];
+}
+
+static ulong
+gbit32(void *a)
+{
+	ulong j;
+	uchar *i;
+
+	i = a;
+	j  = i[3] << 24;
+	j |= i[2] << 16;
+	j |= i[1] << 8;
+	j |= i[0];
+	return j;
+}
+
+static uvlong
+gbit64(void *a)
+{
+	uchar *i;
+
+	i = a;
+	return (uvlong) gbit32(i+4)<<32 | gbit32(a);
+}
+
+static int
+ahciidentify0(Aportc *pc, void *id, int atapi)
+{
+	uchar *c;
+	Actab *t;
+	Alist *l;
+	Aprdt *p;
+	static uchar tab[] = { 0xec, 0xa1 };
+
+	t = pc->m->ctab;
+	c = t->cfis;
+
+	memset(c, 0, 0x20);
+	c[0] = 0x27;
+	c[1] = 0x80;
+	c[2] = tab[atapi];
+	c[7] = 0xa0;		/* obsolete device bits */
+
+	l = pc->m->list;
+	l->flags = 1<<16 | 0x5;
+	l->len = 0;
+	l->ctab = PCIWADDR(t);
+	l->ctabhi = 0;
+
+	memset(id, 0, 0x100);
+	p = &t->prdt;
+	p->dba = PCIWADDR(id);
+	p->dbahi = 0;
+	p->count = 1<<31 | (0x200-2) | 1;
+
+	return ahciwait(pc, 3*1000);
+}
+
+static vlong
+ahciidentify(Aportc *pc, ushort *id)
+{
+	int i, sig;
+	vlong s;
+	Aportm *m;
+
+	m = pc->m;
+	m->feat = 0;
+	m->smart = 0;
+	i = 0;
+	sig = pc->p->sig >> 16;
+	if(sig == 0xeb14){
+		m->feat |= Datapi;
+		i = 1;
+	}
+	if(ahciidentify0(pc, id, i) == -1)
+		return -1;
+
+	i = gbit16(id+83) | gbit16(id+86);
+	if(i & (1<<10)){
+		m->feat |= Dllba;
+		s = gbit64(id+100);
+	}else
+		s = gbit32(id+60);
+
+	if(m->feat & Datapi){
+		i = gbit16(id+0);
+		if(i & 1)
+			m->feat |= Datapi16;
+	}
+
+	i = gbit16(id+83);
+	if((i>>14) != 1)
+		return s;
+	if(i & (1<<3))
+		m->feat |= Dpower;
+	i = gbit16(id+82);
+	if(i & 1)
+		m->feat |= Dsmart;
+	if(i & (1<<14))
+		m->feat |= Dnop;
+	return s;
+}
+
+static int
+ahciquiet(Aport *a)
+{
+	ulong *p, i;
+
+	p = &a->cmd;
+	*p &= ~Ast;
+	for(i = 0; i < 500; i += 50){
+		if((*p & Acr) == 0)
+			goto stop;
+		asleep(50);
+	}
+	return -1;
+stop:
+	if((a->task & (ASdrq|ASbsy)) == 0){
+		*p |= Ast;
+		return 0;
+	}
+
+	*p |= Aclo;
+	for(i = 0; i < 500; i += 50){
+		if((*p & Aclo) == 0)
+			goto stop1;
+		asleep(50);
+	}
+	return -1;
+stop1:
+	/* extra check */
+	dprint("clo clear %lx\n", a->task);
+	if(a->task & ASbsy)
+		return -1;
+	*p |= Ast;
+	return 0;
+}
+
+static int
+ahciidle(Aport *port)
+{
+	ulong *p, i, r;
+
+	p = &port->cmd;
+	if((*p & Arun) == 0)
+		return 0;
+	*p &= ~Ast;
+	r = 0;
+	for(i = 0; i < 500; i += 25){
+		if((*p & Acr) == 0)
+			goto stop;
+		asleep(25);
+	}
+	r = -1;
+stop:
+	if((*p & Afre) == 0)
+		return r;
+	*p &= ~Afre;
+	for(i = 0; i < 500; i += 25){
+		if((*p & Afre) == 0)
+			return 0;
+		asleep(25);
+	}
+	return -1;
+}
+
+/*
+ * §6.2.2.1  first part; comreset handled by reset disk.
+ *	- remainder is handled by configdisk.
+ *	- ahcirecover is a quick recovery from a failed command.
+ */
+int
+ahciswreset(Aportc *pc)
+{
+	int i;
+
+	i = ahciidle(pc->p);
+	pc->p->cmd |= Afre;
+	if(i == -1)
+		return -1;
+	if(pc->p->task & (ASdrq|ASbsy))
+		return -1;
+	return 0;
+}
+
+int
+ahcirecover(Aportc *pc)
+{
+	ahciswreset(pc);
+	pc->p->cmd |= Ast;
+	if(setudmamode(pc, 5) == -1)
+		return -1;
+	return 0;
+}
+
+static void*
+malign(int size, int align)
+{
+	void *v;
+
+	v = xspanalloc(size, align, 0);
+	memset(v, 0, size);
+	return v;
+}
+
+static void
+setupfis(Afis *f)
+{
+	f->base = malign(0x100, 0x100);
+	f->d = f->base + 0;
+	f->p = f->base + 0x20;
+	f->r = f->base + 0x40;
+	f->u = f->base + 0x60;
+	f->devicebits = (ulong*)(f->base + 0x58);
+}
+
+static void
+ahciwakeup(Aport *p)
+{
+	ushort s;
+
+	s = p->sstatus;
+	if((s & 0x700) != 0x600)
+		return;
+	if((s & 7) != 1){
+		print("ahci: slumbering drive unwakeable %ux\n", s);
+		return;
+	}
+	p->sctl = 3*Aipm | 0*Aspd | Adet;
+	delay(1);
+	p->sctl &= ~7;
+//	iprint("ahci: wake %ux -> %ux\n", s, p->sstatus);
+}
+
+static int
+ahciconfigdrive(Ahba *h, Aportc *c, int mode)
+{
+	Aportm *m;
+	Aport *p;
+
+	p = c->p;
+	m = c->m;
+
+	if(m->list == 0){
+		setupfis(&m->fis);
+		m->list = malign(sizeof *m->list, 1024);
+		m->ctab = malign(sizeof *m->ctab, 128);
+	}
+
+	if(p->sstatus & 3 && h->cap & Hsss){
+		dprint("configdrive:  spinning up ... [%lux]\n", p->sstatus);
+		p->cmd |= Apod|Asud;
+		asleep(1400);
+	}
+
+	p->serror = SerrAll;
+
+	p->list = PCIWADDR(m->list);
+	p->listhi = 0;
+	p->fis = PCIWADDR(m->fis.base);
+	p->fishi = 0;
+	p->cmd |= Afre | Ast;
+
+	if((p->sstatus & 0x707) == 0x601) /* drive coming up in slumbering? */
+		ahciwakeup(p);
+
+	/* disable power managment sequence from book. */
+	p->sctl = (3*Aipm) | (mode*Aspd) | (0*Adet);
+	p->cmd &= ~Aalpe;
+
+	p->ie = IEM;
+
+	return 0;
+}
+
+static int
+ahcienable(Ahba *h)
+{
+	h->ghc |= Hie;
+	return 0;
+}
+
+static int
+ahcidisable(Ahba *h)
+{
+	h->ghc &= ~Hie;
+	return 0;
+}
+
+static int
+countbits(ulong u)
+{
+	int i, n;
+
+	n = 0;
+	for(i = 0; i < 32; i++)
+		if(u & (1<<i))
+			n++;
+	return n;
+}
+
+static int
+ahciconf(Ctlr *c)
+{
+	ulong u;
+	Ahba *h;
+	static int count;
+
+	h = c->hba = (Ahba*)c->mmio;
+	u = h->cap;
+
+	if((u & Hsam) == 0)
+		h->ghc |= Hae;
+
+	print("ahci%d port %#p: hba sss %ld; ncs %ld; coal %ld; mports %ld; "
+		"led %ld; clo %ld; ems %ld;\n", count++, h,
+		(u>>27) & 1, (u>>8) & 0x1f, (u>>7) & 1,	u & 0x1f, (u>>25) & 1,
+		(u>>24) & 1, (u>>6) & 1);
+	return countbits(h->pi);
+}
+
+static int
+ahcihbareset(Ahba *h)
+{
+	int wait;
+
+	h->ghc |= 1;
+	for(wait = 0; wait < 1000; wait += 100){
+		if(h->ghc == 0)
+			return 0;
+		delay(100);
+	}
+	return -1;
+}
+
+static void
+idmove(char *p, ushort *a, int n)
+{
+	int i;
+	char *op, *e;
+
+	op = p;
+	for(i = 0; i < n/2; i++){
+		*p++ = a[i] >> 8;
+		*p++ = a[i];
+	}
+	*p = 0;
+	while(p > op && *--p == ' ')
+		*p = 0;
+	e = p;
+	for (p = op; *p == ' '; p++)
+		;
+	memmove(op, p, n - (e - p));
+}
+
+static int
+identify(Drive *d)
+{
+	ushort *id;
+	vlong osectors, s;
+	uchar oserial[21];
+	SDunit *u;
+
+	id = d->info;
+	s = ahciidentify(&d->portc, id);
+	if(s == -1){
+		d->state = Derror;
+		return -1;
+	}
+	osectors = d->sectors;
+	memmove(oserial, d->serial, sizeof d->serial);
+
+	d->sectors = s;
+	d->smartrs = 0;
+
+	idmove(d->serial, id+10, 20);
+	idmove(d->firmware, id+23, 8);
+	idmove(d->model, id+27, 40);
+
+	u = d->unit;
+	memset(u->inquiry, 0, sizeof u->inquiry);
+	u->inquiry[2] = 2;
+	u->inquiry[3] = 2;
+	u->inquiry[4] = sizeof u->inquiry - 4;
+	memmove(u->inquiry+8, d->model, 40);
+
+	if((osectors == 0 || osectors != s) &&
+	    memcmp(oserial, d->serial, sizeof oserial) != 0){
+		d->mediachange = 1;
+		u->sectors = 0;
+	}
+
+	return 0;
+}
+
+static void
+clearci(Aport *p)
+{
+	if((p->cmd & Ast) == 0)
+		return;
+	p->cmd &= ~Ast;
+	p->cmd |= Ast;
+}
+
+static void
+updatedrive(Drive *d)
+{
+	ulong cause, serr, s0, pr, ewake;
+	char *name;
+	Aport *p;
+	static ulong last;
+
+	pr = 1;
+	ewake = 0;
+	p = d->port;
+	cause = p->isr;
+	serr = p->serror;
+	p->isr = cause;
+	name = "??";
+	if(d->unit && d->unit->name)
+		name = d->unit->name;
+
+	if(p->ci == 0){
+		d->portm.flag |= Fdone;
+		pr = 0;
+	}else if(cause & Adps)
+		pr = 0;
+	if(cause&Ifatal){
+		ewake = 1;
+		dprint("Fatal\n");
+	}
+	if(cause & Adhrs){
+		if(p->task & (32|1)){
+			dprint("Adhrs cause = %lux; serr = %lux; task=%lux\n",
+				cause, serr, p->task);
+			d->portm.flag |= Ferror;
+			ewake = 1;
+		}
+		pr = 0;
+	}
+
+	if(pr)
+		dprint("%s: upd %lux ta %lux\n", name, cause, p->task);
+	if(cause & (Aprcs|Aifs)){
+		s0 = d->state;
+		switch(p->sstatus & 7){
+		case 0:
+			d->state = Dmissing;
+			break;
+		case 1:
+			if((p->sstatus & 0x700) == 0x600)
+				d->state = Dnew;
+			else
+				d->state = Derror;
+			break;
+		case 3:
+			/* power mgnt crap for surprise removal */
+			p->ie |= Aprcs | Apcs;	/* is this required? */
+			d->state = Dreset;
+			break;
+		case 4:
+			d->state = Doffline;
+			break;
+		}
+		dprint("%s: %s → %s [Apcrs] %lux\n", name, diskstates[s0],
+			diskstates[d->state], p->sstatus);
+		if(s0 == Dready && d->state != Dready)
+			idprint("%s: pulled\n", name);
+		if(d->state != Dready)
+			d->portm.flag |= Ferror;
+		ewake = 1;
+	}
+	p->serror = serr;
+	if(ewake)
+		clearci(p);
+	last = cause;
+}
+
+static void
+pstatus(Drive *d, ulong s)
+{
+	/*
+	 * bogus code because the first interrupt is currently dropped.
+	 * likely my fault.  serror may be cleared at the wrong time.
+	 */
+	switch(s){
+	case 0:
+		d->state = Dmissing;
+		break;
+	case 2:			/* should this be missing?  need testcase. */
+		dprint("pstatus 2\n");
+	case 3:
+		d->wait = 0;
+		d->state = Dnew;
+		break;
+	case 4:
+		d->state = Doffline;
+		break;
+	case 6:
+		d->state = Dnew;
+		break;
+	}
+}
+
+static int
+configdrive(Drive *d)
+{
+	if(ahciconfigdrive(d->ctlr->hba, &d->portc, d->mode) == -1)
+		return -1;
+	ilock(d);
+	pstatus(d, d->port->sstatus & 7);
+	iunlock(d);
+	return 0;
+}
+
+static void
+resetdisk(Drive *d)
+{
+	uint state, det, stat;
+	Aport *p;
+
+	p = d->port;
+	det = p->sctl & 7;
+	stat = p->sstatus & 7;
+	state = (p->cmd>>28) & 0xf;
+	dprint("resetdisk: icc %ux  det %d sdet %d\n", state, det, stat);
+	if(stat != 3){
+		ilock(d);
+		d->state = Dportreset;
+		iunlock(d);
+		return;
+	}
+	ilock(d);
+	state = d->state;
+	if(d->state != Dready || d->state != Dnew)
+		d->portm.flag |= Ferror;
+	clearci(p);			/* satisfy sleep condition. */
+	iunlock(d);
+
+	qlock(&d->portm);
+
+	if(p->cmd & Ast && ahciswreset(&d->portc) == -1){
+		ilock(d);
+		d->state = Dportreset;	/* get a bigger stick. */
+		iunlock(d);
+	} else {
+		ilock(d);
+		d->state = Dmissing;
+		iunlock(d);
+
+		configdrive(d);
+	}
+	dprint("resetdisk: %s → %s\n", diskstates[state], diskstates[d->state]);
+	qunlock(&d->portm);
+}
+
+static int
+newdrive(Drive *d)
+{
+	char *name, *s;
+	Aportc *c;
+	Aportm *m;
+
+	c = &d->portc;
+	m = &d->portm;
+
+	name = d->unit->name;
+	if(name == 0)
+		name = "??";
+
+	if(d->port->task == 0x80)
+		return -1;
+	qlock(c->m);
+	if(setudmamode(c, 5) == -1){
+		dprint("%s: can't set udma mode\n", name);
+		goto lose;
+	}
+	if(identify(d) == -1){
+		dprint("%s: identify failure\n", name);
+		goto lose;
+	}
+	if(m->feat & Dpower && setfeatures(c, 0x85) == -1){
+		m->feat &= ~Dpower;
+		if(ahcirecover(c) == -1) {
+			dprint("%s: ahcirecover failed\n", name);
+			goto lose;
+		}
+	}
+
+	ilock(d);
+	d->state = Dready;
+	iunlock(d);
+
+	qunlock(c->m);
+
+	s = "";
+	if(m->feat & Dllba)
+		s = "L";
+	idprint("%s: %sLBA %lld sectors\n", d->unit->name, s, d->sectors);
+	idprint("  %s %s %s %s\n", d->model, d->firmware, d->serial,
+		d->mediachange? "[mediachange]": "");
+
+	return 0;
+
+lose:
+	qunlock(&d->portm);
+	return -1;
+}
+
+enum {
+	Nms		= 256,
+	Mphywait	=  2*1024/Nms - 1,
+	Midwait		= 16*1024/Nms - 1,
+	Mcomrwait	= 64*1024/Nms - 1,
+};
+
+static void
+westerndigitalhung(Drive *d)
+{
+	if((d->portm.feat & Datapi) == 0 && d->active &&
+	    TK2MS(m->ticks - d->intick) > 5000){
+		dprint("%s: drive hung; resetting [%lux] ci=%lx\n",
+			d->unit->name, d->port->task, d->port->ci);
+		d->state = Dreset;
+	}
+}
+
+static ushort olds[NCtlr*NCtlrdrv];
+
+static int
+doportreset(Drive *d)
+{
+	int i;
+
+	i = -1;
+	qlock(&d->portm);
+	if(ahciportreset(&d->portc) == -1)
+		dprint("ahciportreset fails\n");
+	else
+		i = 0;
+	qunlock(&d->portm);
+	dprint("portreset → %s  [task %lux]\n", diskstates[d->state],
+		d->port->task);
+	return i;
+}
+
+static void
+checkdrive(Drive *d, int i)
+{
+	ushort s;
+	char *name;
+
+	ilock(d);
+	name = d->unit->name;
+	s = d->port->sstatus;
+	if(s != olds[i]){
+		dprint("%s: status: %#ux -> %#ux: %s\n", name, olds[i],
+			s, diskstates[d->state]);
+		olds[i] = s;
+		d->wait = 0;
+	}
+	westerndigitalhung(d);
+	switch(d->state){
+	case Dnull:
+		break;
+	case Dmissing:
+	case Dnew:
+		switch(s & 0x107){
+		case 1:
+			ahciwakeup(d->port);
+		case 0:
+			break;
+		default:
+			dprint("%s: unknown status %04ux\n", name, s);
+		case 0x100:
+			if(++d->wait&Mphywait)
+				break;
+reset:
+			if(++d->mode > DMsataii)
+				d->mode = 0;
+			if(d->mode == DMsatai){	/* we tried everything */
+				d->state = Dportreset;
+				goto portreset;
+			}
+			dprint("%s: reset; new mode %s\n", name,
+				modename[d->mode]);
+			iunlock(d);
+			resetdisk(d);
+			ilock(d);
+			break;
+		case 0x103:
+			if((++d->wait&Midwait) == 0){
+				dprint("%s: slow reset %#ux task=%#lux; %d\n",
+					name, s, d->port->task, d->wait);
+				goto reset;
+			}
+			s = d->port->task&0xff;
+			if(s == 0x7f || ((d->port->sig>>16) != 0xeb14 &&
+			    (s & ~0x17) != (1<<6)))
+				break;
+			iunlock(d);
+			newdrive(d);
+			ilock(d);
+			break;
+		}
+		break;
+	case Doffline:
+		if(d->wait++ & Mcomrwait)
+			break;
+	case Derror:
+	case Dreset:
+		dprint("%s: reset [%s]: mode %d; status %#ux\n",
+			name, diskstates[d->state], d->mode, s);
+		iunlock(d);
+		resetdisk(d);
+		ilock(d);
+		break;
+	case Dportreset:
+portreset:
+		if(d->wait++ & 0xff && (s & 0x100) == 0)
+			break;
+		dprint("%s: portreset [%s]: mode %d; status %04ux\n",
+			name, diskstates[d->state], d->mode, s);
+		d->portm.flag |= Ferror;
+		clearci(d->port);
+		if((s & 7) == 0){
+			d->state = Dmissing;
+			break;
+		}
+		iunlock(d);
+		doportreset(d);
+		ilock(d);
+		break;
+	}
+	iunlock(d);
+}
+
+static void
+iainterrupt(Ureg*, void *a)
+{
+	int i;
+	ulong cause, m;
+	Ctlr *c;
+	Drive *d;
+
+	c = a;
+	ilock(c);
+	/* check drive here! */
+	cause = c->hba->isr;
+	for(i = 0; i < c->ndrive; i++){
+		m = 1 << i;
+		if((cause & m) == 0)
+			continue;
+		d = c->rawdrive + i;
+		ilock(d);
+		if(d->port->isr && c->hba->pi & m)
+			updatedrive(d);
+		c->hba->isr = m;
+		iunlock(d);
+	}
+	iunlock(c);
+}
+
+static int
+iaverify(SDunit *u)
+{
+	int i;
+	Ctlr *c;
+	Drive *d;
+
+	c = u->dev->ctlr;
+	d = c->drive[u->subno];
+	ilock(c);
+	ilock(d);
+	d->unit = u;
+	iunlock(d);
+	iunlock(c);
+	for(i = 0; i < 10; i++){
+		checkdrive(d, d->driveno);
+		switch(d->state){
+		case Dmissing:
+			if(i < 4 || d->port->sstatus & 0x733)
+				break;
+			/* fall through */
+		case Dnull:
+		case Dready:
+		case Doffline:
+			print("sdiahci: drive %d in state %s after %d resets\n",
+				d->driveno, diskstates[d->state], i);
+			return 1;
+		}
+		delay(100);
+	}
+	print("sdiahci: drive %d won't come up; in state %s after %d resets\n",
+		d->driveno, diskstates[d->state], i);
+	return 1;
+}
+
+static int
+iaenable(SDev *s)
+{
+	Ctlr *c;
+
+	c = s->ctlr;
+	ilock(c);
+	if(!c->enabled) {
+		if(c->ndrive == 0)
+			panic("iaenable: zero s->ctlr->ndrive");
+		pcisetbme(c->pci);
+		setvec(c->pci->intl+VectorPIC, iainterrupt, c);
+		/* supposed to squelch leftover interrupts here. */
+		ahcienable(c->hba);
+		c->enabled = 1;
+	}
+	iunlock(c);
+	return 1;
+}
+
+static int
+iadisable(SDev *s)
+{
+	Ctlr *c;
+
+	c = s->ctlr;
+	ilock(c);
+	ahcidisable(c->hba);
+//	intrdisable(c->irq, iainterrupt, c, c->tbdf, name);
+	c->enabled = 0;
+	iunlock(c);
+	return 1;
+}
+
+static int
+iaonline(SDunit *unit)
+{
+	int r;
+	Ctlr *c;
+	Drive *d;
+
+	c = unit->dev->ctlr;
+	d = c->drive[unit->subno];
+	r = 0;
+
+	if(d->portm.feat & Datapi && d->mediachange){
+		r = scsionline(unit);
+		if(r > 0)
+			d->mediachange = 0;
+		return r;
+	}
+
+	ilock(d);
+	if(d->mediachange){
+		r = 2;
+		d->mediachange = 0;
+		/* devsd resets this after online is called; why? */
+		unit->sectors = d->sectors;
+		unit->secsize = 512;
+	} else if(d->state == Dready)
+		r = 1;
+	iunlock(d);
+	return r;
+}
+
+/* returns locked list! */
+static Alist*
+ahcibuild(Aportm *m, uchar *cmd, void *data, int n, vlong lba)
+{
+	uchar *c, acmd, dir, llba;
+	Alist *l;
+	Actab *t;
+	Aprdt *p;
+	static uchar tab[2][2] = { 0xc8, 0x25, 0xca, 0x35 };
+
+	dir = *cmd != 0x28;
+	llba = m->feat & Dllba? 1: 0;
+	acmd = tab[dir][llba];
+	qlock(m);
+	l = m->list;
+	t = m->ctab;
+	c = t->cfis;
+
+	c[0] = 0x27;
+	c[1] = 0x80;
+	c[2] = acmd;
+	c[3] = 0;
+
+	c[4] = lba;		/* sector	lba low	7:0 */
+	c[5] = lba >> 8;	/* cylinder low	lba mid	15:8 */
+	c[6] = lba >> 16;	/* cylinder hi	lba hi	23:16 */
+	c[7] = 0xa0 | 0x40;	/* obsolete device bits + lba */
+	if(llba == 0)
+		c[7] |= (lba>>24) & 7;
+
+	c[8] = lba >> 24;	/* sector (exp)		lba 	31:24 */
+	c[9] = lba >> 32;	/* cylinder low (exp)	lba	39:32	 */
+	c[10] = lba >> 48;	/* cylinder hi (exp)	lba	48:40 */
+	c[11] = 0;		/* features (exp); */
+
+	c[12] = n;		/* sector count */
+	c[13] = n >> 8;		/* sector count (exp) */
+	c[14] = 0;		/* r */
+	c[15] = 0;		/* control */
+
+	*(ulong*)(c+16) = 0;
+
+	l->flags = 1<<16 | Lpref | 0x5;	/* Lpref ?? */
+	if(dir == Write)
+		l->flags |= Lwrite;
+	l->len = 0;
+	l->ctab = PCIWADDR(t);
+	l->ctabhi = 0;
+
+	p = &t->prdt;
+	p->dba = PCIWADDR(data);
+	p->dbahi = 0;
+	p->count = 1<<31 | (512*n - 2) | 1;
+
+	return l;
+}
+
+static Alist*
+ahcibuildpkt(Aportm *m, SDreq *r, void *data, int n)
+{
+	int fill, len;
+	uchar *c;
+	Actab *t;
+	Alist *l;
+	Aprdt *p;
+
+	qlock(m);
+	l = m->list;
+	t = m->ctab;
+	c = t->cfis;
+
+	fill = m->feat & Datapi16? 16: 12;
+	if((len = r->clen) > fill)
+		len = fill;
+	memmove(t->atapi, r->cmd, len);
+	memset(t->atapi + len, 0, fill - len);
+
+	c[0] = 0x27;
+	c[1] = 0x80;
+	c[2] = 0xa0;
+	if(n != 0)
+		c[3] = 1;	/* dma */
+	else
+		c[3] = 0;	/* features (exp); */
+
+	c[4] = 0;		/* sector	lba low	7:0 */
+	c[5] = n;		/* cylinder low	lba mid	15:8 */
+	c[6] = n >> 8;		/* cylinder hi	lba hi	23:16 */
+	c[7] = 0xa0;		/* obsolete device bits */
+
+	*(ulong*)(c+8) = 0;
+	*(ulong*)(c+12) = 0;
+	*(ulong*)(c+16) = 0;
+
+	l->flags = 1<<16 | Lpref | Latapi | 0x5;
+	if(r->write != 0 && data)
+		l->flags |= Lwrite;
+	l->len = 0;
+	l->ctab = PCIWADDR(t);
+	l->ctabhi = 0;
+
+	if(data == 0)
+		return l;
+
+	p = &t->prdt;
+	p->dba = PCIWADDR(data);
+	p->dbahi = 0;
+	p->count = 1<<31 | (n - 2) | 1;
+
+	return l;
+}
+
+static int
+waitready(Drive *d)
+{
+	ulong s, t, i;
+
+	for(i = 0; i < 120; i++){
+		ilock(d);
+		s = d->port->sstatus;
+		t = d->port->task;
+		iunlock(d);
+		if((s & 0x100) == 0)
+			return -1;
+		if(d->state == Dready && (s & 7) == 3)
+			return 0;
+		if((i + 1) % 30 == 0)
+			print("%s: waitready: [%s] task=%lux sstat=%lux\n",
+				d->unit->name, diskstates[d->state], t, s);
+		esleep(1000);
+	}
+	print("%s: not responding; offline\n", d->unit->name);
+	ilock(d);
+	d->state = Doffline;
+	iunlock(d);
+	return -1;
+}
+
+static int
+iariopkt(SDreq *r, Drive *d)
+{
+	int n, count, try, max, flag, task;
+	char *name;
+	uchar *cmd, *data;
+	Aport *p;
+	Asleep as;
+
+	cmd = r->cmd;
+	name = d->unit->name;
+	p = d->port;
+
+	aprint("%02ux %02ux %c %d %p\n", cmd[0], cmd[2], "rw"[r->write],
+		r->dlen, r->data);
+//	if(cmd[0] == 0x5a && (cmd[2] & 0x3f) == 0x3f)
+//		return sdmodesense(r, cmd, d->info, sizeof d->info);
+	r->rlen = 0;
+	count = r->dlen;
+	max = 65536;
+
+	try = 0;
+retry:
+	if(waitready(d) == -1)
+		return SDeio;
+	data = r->data;
+	n = count;
+	if(n > max)
+		n = max;
+	d->active++;
+	ahcibuildpkt(&d->portm, r, data, n);
+	ilock(d);
+	d->portm.flag = 0;
+	iunlock(d);
+	p->ci = 1;
+
+	as.p = p;
+	as.i = 1;
+	d->intick = m->ticks;
+
+	while(ahciclear(&as) == 0)
+		;
+
+	ilock(d);
+	flag = d->portm.flag;
+	task = d->port->task;
+	iunlock(d);
+
+	if(task & (Efatal<<8) || task & (ASbsy|ASdrq) && d->state == Dready){
+		d->port->ci = 0;		/* @? */
+		ahcirecover(&d->portc);
+		task = d->port->task;
+	}
+	d->active--;
+	qunlock(&d->portm);
+	if(flag == 0){
+		if(++try == 10){
+			print("%s: bad disk\n", name);
+			r->status = SDcheck;
+			return SDcheck;
+		}
+		print("%s: retry\n", name);
+		esleep(1000);
+		goto retry;
+	}
+	if(flag & Ferror){
+		if((task & Eidnf) == 0)
+			print("%s: i/o error %ux\n", name, task);
+		r->status = SDcheck;
+		return SDcheck;
+	}
+
+	data += n;
+
+	r->rlen = data - (uchar*)r->data;
+	r->status = SDok;
+	return SDok;
+}
+
+static int
+iario(SDreq *r)
+{
+	int n, count, max, flag, task;
+	vlong lba;
+	char *name;
+	uchar *cmd, *data;
+	Aport *p;
+	Asleep as;
+	Ctlr *c;
+	Drive *d;
+	SDunit *unit;
+
+	unit = r->unit;
+	c = unit->dev->ctlr;
+	d = c->drive[unit->subno];
+	if(d->portm.feat & Datapi)
+		return iariopkt(r, d);
+	cmd = r->cmd;
+	name = d->unit->name;
+	p = d->port;
+
+//	if((i = sdfakescsi(r, d->info, sizeof d->info)) != SDnostatus){
+//		r->status = i;
+//		return i;
+//	}
+
+	if(*cmd != 0x28 && *cmd != 0x2a){
+		print("%s: bad cmd 0x%.2ux\n", name, cmd[0]);
+		r->status = SDcheck;
+		return SDcheck;
+	}
+
+	lba   = cmd[2]<<24 | cmd[3]<<16 | cmd[4]<<8 | cmd[5];
+	count = cmd[7]<<8  | cmd[8];
+	if(r->data == nil)
+		return SDok;
+	if(r->dlen < count * unit->secsize)
+		count = r->dlen / unit->secsize;
+	max = 128;
+
+	if(waitready(d) == -1)
+		return SDeio;
+	data = r->data;
+	while(count > 0){
+		n = count;
+		if(n > max)
+			n = max;
+		d->active++;
+		ahcibuild(&d->portm, cmd, data, n, lba);
+		ilock(d);
+		d->portm.flag = 0;
+		iunlock(d);
+		p->ci = 1;
+
+		as.p = p;
+		as.i = 1;
+		d->intick = m->ticks;
+
+		while(ahciclear(&as) == 0)
+			;
+
+		ilock(d);
+		flag = d->portm.flag;
+		task = d->port->task;
+		iunlock(d);
+
+		if(task & (Efatal<<8) ||
+		    task & (ASbsy|ASdrq) && d->state == Dready){
+			d->port->ci = 0;		/* @? */
+			ahcirecover(&d->portc);
+			task = d->port->task;
+		}
+		d->active--;
+		qunlock(&d->portm);
+		if(flag == 0 || flag & Ferror){
+			print("%s: i/o error %ux @%lld\n", name, task, lba);
+			r->status = SDeio;
+			return SDeio;
+		}
+
+		count -= n;
+		lba += n;
+		data += n * unit->secsize;
+	}
+	r->rlen = data - (uchar*)r->data;
+	r->status = SDok;
+	return SDok;
+}
+
+/*
+ * configure drives 0-5 as ahci sata  (c.f. errata)
+ */
+static int
+iaahcimode(Pcidev *p)
+{
+	dprint("iaahcimode %ux %ux %ux\n", pcicfgr8(p, 0x91),
+		pcicfgr8(p, 92), pcicfgr8(p, 93));
+	pcicfgw16(p, 0x92, pcicfgr32(p, 0x92) | 0xf);	/* ports 0-3 */
+//	pcicfgw8(p, 0x93, pcicfgr32(p, 9x93) | 3);	/* ports 4-5 */
+	return 0;
+}
+
+static void
+iasetupahci(Ctlr *c)
+{
+	/* disable cmd block decoding. */
+	pcicfgw16(c->pci, 0x40, pcicfgr16(c->pci, 0x40) & ~(1<<15));
+	pcicfgw16(c->pci, 0x42, pcicfgr16(c->pci, 0x42) & ~(1<<15));
+
+	c->lmmio[0x4/4] |= 1 << 31;	/* enable ahci mode (ghc register) */
+	c->lmmio[0xc/4] = (1<<6) - 1;	/* five ports (supposedly ro pi reg) */
+
+	/* enable ahci mode; from ich9 datasheet */
+	pcicfgw8(c->pci, 0x90, 1<<6 | 1<<5);
+}
+
+static SDev*
+iapnp(void)
+{
+	int i, n, nunit, type;
+	ulong io;
+	Ctlr *c;
+	Drive *d;
+	Pcidev *p;
+	SDev *head, *tail, *s;
+	static int done;
+
+	if (done || getconf("*noahciload") != nil)
+		return nil;
+	done = 1;
+	p = nil;
+	head = tail = nil;
+loop:
+	while((p = pcimatch(p, 0, 0)) != nil){
+		if(p->vid == 0x8086 && (p->did & 0xfffc) == 0x2680)
+			type = Tesb;
+		else if(p->vid == 0x8086 && p->did == 0x27c5)
+			type = Tich;	/* 82801g[bh]m; compat mode fails */
+		else if(p->vid == 0x8086 && (p->did & 0xfeff) == 0x2829)
+			type = Tich;		/* ich8 */
+		else if(p->vid == 0x8086 && (p->did & 0xfffe) == 0x2922)
+			type = Tich;		/* ich8 */
+		else if(p->vid == 0x1002 && p->did == 0x4380)
+			type = Tsb600;
+		else
+			continue;
+		if(niactlr == NCtlr){
+			print("iapnp: %s: too many controllers\n", tname[type]);
+			break;
+		}
+		c = iactlr + niactlr;
+		s = sdevs  + niactlr;
+		memset(c, 0, sizeof *c);
+		memset(s, 0, sizeof *s);
+		c->pci = p;
+		c->type = type;
+		io = p->mem[Abar].bar & ~0xf;
+		io = upamalloc(io, p->mem[Abar].size, 0);
+		if(io == 0){
+			print("%s: address %#lux in use, did %#ux\n",
+				tname[c->type], io, p->did);
+			continue;
+		}
+		/* ugly hack: get this in compatibility mode; see memory.c:271 */
+		if(io == 0x40000000) {
+			print("%s: did %#ux is in non-sata mode.  bar %#lux\n",
+				tname[c->type], p->did, p->mem[Abar].bar);
+			continue;
+		}
+		c->mmio = KADDR(io);
+		c->lmmio = (ulong*)c->mmio;
+		if(Intel(c->type) && p->did != 0x2681)
+			iasetupahci(c);
+		nunit = ahciconf(c);
+//		ahcihbareset((Ahba*)c->mmio);
+		if(Intel(c->type) && iaahcimode(p) == -1)
+			break;
+		if(nunit < 1){
+//			vunmap(c->mmio, p->mem[Abar].size);
+			continue;
+		}
+		niactlr++;
+		i = (c->hba->cap>>21) & 1;
+		print("%s: sata-%s with %d ports\n", tname[c->type],
+			"I\0II"+i*2, nunit);
+		s->ifc = &sdiahciifc;
+		s->ctlr = c;
+		s->nunit = nunit;
+		s->idno = 'E';
+		c->sdev = s;
+		c->ndrive = nunit;
+
+		/* map the drives -- they don't all need to be enabled. */
+		memset(c->rawdrive, 0, sizeof c->rawdrive);
+		n = 0;
+		for(i = 0; i < NCtlrdrv; i++) {
+			d = c->rawdrive+i;
+			d->portno = i;
+			d->driveno = -1;
+			d->sectors = 0;
+			d->ctlr = c;
+			if((c->hba->pi & (1<<i)) == 0)
+				continue;
+//			d->state = Dnew;
+			d->port = (Aport*)(c->mmio + 0x80*i + 0x100);
+			d->portc.p = d->port;
+			d->portc.m = &d->portm;
+			d->driveno = n++;
+			c->drive[d->driveno] = d;
+		}
+		for(i = 0; i < n; i++)
+			if(ahciidle(c->drive[i]->port) == -1){
+				print("%s: port %d wedged; abort\n",
+					tname[c->type], i);
+				goto loop;
+			}
+		for(i = 0; i < n; i++){
+			c->drive[i]->mode = DMsatai;
+			configdrive(c->drive[i]);
+		}
+
+		if(head)
+			tail->next = s;
+		else
+			head = s;
+		tail = s;
+	}
+	return head;
+}
+
+static SDev*
+iaid(SDev* sdev)
+{
+	int i;
+	Ctlr *c;
+
+	for(; sdev; sdev = sdev->next){
+		if(sdev->ifc != &sdiahciifc)
+			continue;
+		c = sdev->ctlr;
+		for(i = 0; i < NCtlr; i++)
+			if(c == iactlr + i)
+				sdev->idno = 'E' + i;
+	}
+	return nil;
+}
+
+SDifc sdiahciifc = {
+	"iahci",
+
+	iapnp,
+	nil,			/* legacy */
+	iaid,
+	iaenable,
+	iadisable,
+
+	iaverify,
+	iaonline,
+	iario,
+	nil,
+	nil,
+
+	scsibio,
+};
--- /dev/null
+++ b/os/boot.original/pc/sdmylex.c
@@ -1,0 +1,1292 @@
+/*
+ * Mylex MultiMaster (Buslogic BT-*) SCSI Host Adapter
+ * in both 24-bit and 32-bit mode.
+ * 24-bit mode works for Adaptec AHA-154xx series too.
+ *
+ * To do:
+ *	allocate more Ccb's as needed, up to NMbox-1;
+ *	add nmbox and nccb to Ctlr struct for the above;
+ *	64-bit LUN/explicit wide support necessary?
+ *
+ */
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "ureg.h"
+#include "error.h"
+
+#include "sd.h"
+
+#define waserror()	(0)
+#define poperror()
+typedef struct QLock{ int r; } QLock;
+typedef struct Rendez{ int r; } Rendez;
+#define	intrenable(irq, f, c, tbdf, name)	setvec(VectorPIC+(irq), f, c);\
+						USED(tbdf);
+
+#define K2BPA(va, tbdf)	PADDR(va)
+#define BPA2K(pa, tbdf)	KADDR(pa)
+
+extern SDifc sdmylexifc;
+
+enum {					/* registers */
+	Rcontrol	= 0x00,		/* WO: control register */
+	Rstatus		= 0x00,		/* RO: status register */
+	Rcpr		= 0x01,		/* WO: command/parameter register */
+	Rdatain		= 0x01,		/* RO: data-in register */
+	Rinterrupt	= 0x02,		/* RO: interrupt register */
+};
+
+enum {					/* Rcontrol */
+	Rsbus		= 0x10,		/* SCSI Bus Reset */
+	Rint		= 0x20,		/* Interrupt Reset */
+	Rsoft		= 0x40,		/* Soft Reset */
+	Rhard		= 0x80,		/* Hard Reset */
+};
+
+enum {					/* Rstatus */
+	Cmdinv		= 0x01,		/* Command Invalid */
+	Dirrdy		= 0x04,		/* Data In Register Ready */
+	Cprbsy		= 0x08,		/* Command/Parameter Register Busy */
+	Hardy		= 0x10,		/* Host Adapter Ready */
+	Inreq		= 0x20,		/* Initialisation Required */
+	Dfail		= 0x40,		/* Diagnostic Failure */
+	Dact		= 0x80,		/* Diagnostic Active */
+};
+
+enum {					/* Rcpr */
+	Cinitialise	= 0x01,		/* Initialise Mailbox */
+	Cstart		= 0x02,		/* Start Mailbox Command */
+	Cinquiry	= 0x04,		/* Adapter Inquiry */
+	Ceombri		= 0x05,		/* Enable OMBR Interrupt */
+	Cinquire	= 0x0B,		/* Inquire Configuration */
+	Cextbios	= 0x28,		/* AHA-1542: extended BIOS info. */
+	Cmbienable	= 0x29,		/* AHA-1542: Mailbox interface enable */
+	Ciem		= 0x81,		/* Initialise Extended Mailbox */
+	Ciesi		= 0x8D,		/* Inquire Extended Setup Information */
+	Cerrm		= 0x8F,		/* Enable strict round-robin mode */
+	Cwide		= 0x96,		/* Wide CCB */
+};
+
+enum {					/* Rinterrupt */
+	Imbl		= 0x01,		/* Incoming Mailbox Loaded */
+	Mbor		= 0x02,		/* Mailbox Out Ready */
+	Cmdc		= 0x04,		/* Command Complete */
+	Rsts		= 0x08,		/* SCSI Reset State */
+	Intv		= 0x80,		/* Interrupt Valid */
+};
+
+typedef struct {
+	uchar	code;			/* action/completion code */
+	uchar	ccb[3];			/* CCB pointer (MSB, ..., LSB) */
+} Mbox24;
+
+typedef struct {
+	uchar	ccb[4];			/* CCB pointer (LSB, ..., MSB) */
+	uchar	btstat;			/* BT-7[45]7[SD] status */
+	uchar	sdstat;			/* SCSI device status */
+	uchar	pad;
+	uchar	code;			/* action/completion code */
+} Mbox32;
+
+enum {					/* mailbox commands */
+	Mbfree		= 0x00,		/* Mailbox not in use */
+
+	Mbostart	= 0x01,		/* Start a mailbox command */
+	Mboabort	= 0x02,		/* Abort a mailbox command */
+
+	Mbiok		= 0x01,		/* CCB completed without error */
+	Mbiabort	= 0x02,		/* CCB aborted at request of host */
+	Mbinx		= 0x03,		/* Aborted CCB not found */
+	Mbierror	= 0x04,		/* CCB completed with error */
+};
+
+typedef struct Ccb24 Ccb24;
+typedef struct Ccb32 Ccb32;
+typedef union Ccb Ccb;
+
+typedef struct Ccb24 {
+	uchar	opcode;			/* Operation code */
+	uchar	datadir;		/* Data direction control */
+	uchar	cdblen;			/* Length of CDB */
+	uchar	senselen;		/* Length of sense area */
+	uchar	datalen[3];		/* Data length (MSB, ..., LSB) */
+	uchar	dataptr[3];		/* Data pointer (MSB, ..., LSB) */
+	uchar	linkptr[3];		/* Link pointer (MSB, ..., LSB) */
+	uchar	linkid;			/* command linking identifier */
+	uchar	btstat;			/* BT-* adapter status */
+	uchar	sdstat;			/* SCSI device status */
+	uchar	reserved[2];		/* */
+	uchar	cs[12+0xFF];		/* Command descriptor block + Sense */
+
+	void*	data;			/* buffer if address > 24-bits */
+
+	Rendez;
+	int	done;			/* command completed */
+
+	Ccb*	ccb;			/* link on free list */
+} Ccb24;
+
+
+typedef struct Ccb32 {
+	uchar	opcode;			/* Operation code */
+	uchar	datadir;		/* Data direction control */
+	uchar	cdblen;			/* Length of CDB */
+	uchar	senselen;		/* Length of sense area */
+	uchar	datalen[4];		/* Data length (LSB, ..., MSB) */
+	uchar	dataptr[4];		/* Data pointer (LSB, ..., MSB) */
+	uchar	reserved[2];
+	uchar	btstat;			/* BT-* adapter status */
+	uchar	sdstat;			/* SCSI device status */
+	uchar	targetid;		/* Target ID */
+	uchar	luntag;			/* LUN & tag */
+	uchar	cdb[12];		/* Command descriptor block */
+	uchar	ccbctl;			/* CCB control */
+	uchar	linkid;			/* command linking identifier */
+	uchar	linkptr[4];		/* Link pointer (LSB, ..., MSB) */
+	uchar	senseptr[4];		/* Sense pointer (LSB, ..., MSB) */
+	uchar	sense[0xFF];		/* Sense bytes */
+
+	Rendez;
+	int	done;			/* command completed */
+
+	Ccb*	ccb;			/* link on free list */
+} Ccb32;
+
+typedef union Ccb {
+	Ccb24;
+	Ccb32;
+} Ccb;
+
+enum {					/* opcode */
+	OInitiator	= 0x00,		/* initiator CCB */
+	Ordl		= 0x03,		/* initiator CCB with
+					 * residual data length returned
+					 */
+};
+
+enum {					/* datadir */
+	CCBdatain	= 0x08,		/* inbound, length is checked */
+	CCBdataout	= 0x10,		/* outbound, length is checked */
+};
+
+enum {					/* btstat */
+	Eok		= 0x00,		/* normal completion with no errors */
+};
+
+enum {					/* luntag */
+	TagEnable	= 0x20,		/* Tag enable */
+	SQTag		= 0x00,		/* Simple Queue Tag */
+	HQTag		= 0x40,		/* Head of Queue Tag */
+	OQTag		= 0x80,		/* Ordered Queue Tag */
+};
+
+enum {					/* CCB control */
+	NoDisc		= 0x08,		/* No disconnect */
+	NoUnd		= 0x10,		/* No underrrun error report */
+	NoData		= 0x20,		/* No data transfer */
+	NoStat		= 0x40,		/* No CCB status if zero */
+	NoIntr		= 0x80,		/* No Interrupts */
+};
+
+typedef struct {
+	int	port;			/* I/O port */
+	int	id;			/* adapter SCSI id */
+	int	bus;			/* 24 or 32 -bit */
+	int	irq;
+	int	wide;
+	Pcidev*	pcidev;
+	SDev*	sdev;
+	int	spurious;
+
+	Lock	issuelock;
+
+	Lock	ccblock;
+	QLock	ccbq;
+	Rendez	ccbr;
+
+	Lock	mboxlock;
+	void*	mb;			/* mailbox out + mailbox in */
+	int	mbox;			/* current mailbox out index into mb */
+	int	mbix;			/* current mailbox in index into mb */
+
+	Lock	cachelock;
+	Ccb*	ccb;			/* list of free Ccb's */
+	Ccb**	cache;			/* last completed Ccb */
+} Ctlr;
+
+/*
+ * The number of mailboxes should be a multiple of 8 (4 for Mbox32)
+ * to ensure the boundary between the out and in mailboxes doesn't
+ * straddle a cache-line boundary.
+ * The number of Ccb's should be less than the number of mailboxes to
+ * ensure no queueing is necessary on mailbox allocation.
+ */
+enum {
+	NMbox		= 8*8,		/* number of Mbox's */
+	NCcb		= NMbox-1,	/* number of Ccb's */
+};
+
+#define PADDR24(a, n)	((PADDR(a)+(n)) <= (1<<24))
+
+static void
+ccbfree(Ctlr* ctlr, Ccb* ccb)
+{
+	lock(&ctlr->ccblock);
+	if(ctlr->bus == 24)
+		((Ccb24*)ccb)->ccb = ctlr->ccb;
+	else
+		((Ccb32*)ccb)->ccb = ctlr->ccb;
+	if(ctlr->ccb == nil)
+		wakeup(&ctlr->ccbr);
+	ctlr->ccb = ccb;
+	unlock(&ctlr->ccblock);
+}
+
+static int
+ccbavailable(void* a)
+{
+	return ((Ctlr*)a)->ccb != nil;
+}
+
+static Ccb*
+ccballoc(Ctlr* ctlr)
+{
+	Ccb *ccb;
+
+	for(;;){
+		lock(&ctlr->ccblock);
+		if((ccb = ctlr->ccb) != nil){
+			if(ctlr->bus == 24)
+				 ctlr->ccb = ((Ccb24*)ccb)->ccb;
+			else
+				 ctlr->ccb = ((Ccb32*)ccb)->ccb;
+			unlock(&ctlr->ccblock);
+			break;
+		}
+
+		unlock(&ctlr->ccblock);
+		qlock(&ctlr->ccbq);
+		if(waserror()){
+			qunlock(&ctlr->ccbq);
+			continue;
+		}
+		sleep(&ctlr->ccbr, ccbavailable, ctlr);
+		qunlock(&ctlr->ccbq);
+		poperror();
+	}
+
+	return ccb;
+}
+
+static int
+done24(void* arg)
+{
+	return ((Ccb24*)arg)->done;
+}
+
+static int
+mylex24rio(SDreq* r)
+{
+	ulong p;
+	Ctlr *ctlr;
+	Ccb24 *ccb;
+	Mbox24 *mb;
+	uchar *data, lun, *sense;
+	int d, n, btstat, sdstat, target;
+
+	ctlr = r->unit->dev->ctlr;
+	target = r->unit->subno;
+	lun = (r->cmd[1]>>5) & 0x07;
+
+	/*
+	 * Ctlr->cache holds the last completed Ccb for this target if it
+	 * returned 'check condition'.
+	 * If this command is a request-sense and there is valid sense data
+	 * from the last completed Ccb, return it immediately.
+	 */
+	lock(&ctlr->cachelock);
+	if((ccb = ctlr->cache[target]) != nil){
+		ctlr->cache[target] = nil;
+		if(r->cmd[0] == 0x03
+		&& ccb->sdstat == SDcheck && lun == ((ccb->cs[1]>>5) & 0x07)){
+			unlock(&ctlr->cachelock);
+			if(r->dlen){
+				sense = &ccb->cs[ccb->cdblen];
+				n = 8+sense[7];
+				if(n > r->dlen)
+					n = r->dlen;
+				memmove(r->data, sense, n);
+				r->rlen = n;
+			}
+			ccbfree(ctlr, (Ccb*)ccb);
+			return SDok;
+		}
+	}
+	unlock(&ctlr->cachelock);
+	if(ccb == nil)
+		ccb = ccballoc(ctlr);
+
+	/*
+	 * Check if the transfer is to memory above the 24-bit limit the
+	 * controller can address. If it is, try to allocate a temporary
+	 * buffer as a staging area.
+	 */
+	n = r->dlen;
+	if(n && !PADDR24(r->data, n)){
+		data = mallocz(n, 0);
+		if(data == nil || !PADDR24(data, n)){
+			if(data != nil){
+				free(data);
+				ccb->data = nil;
+			}
+			ccbfree(ctlr, (Ccb*)ccb);
+			return SDmalloc;
+		}
+		if(r->write)
+			memmove(data, r->data, n);
+		ccb->data = r->data;
+	}
+	else
+		data = r->data;
+
+	/*
+	 * Fill in the ccb.
+	 */
+	ccb->opcode = Ordl;
+
+	ccb->datadir = (target<<5)|lun;
+	if(n == 0)
+		ccb->datadir |= CCBdataout|CCBdatain;
+	else if(!r->write)
+		ccb->datadir |= CCBdatain;
+	else
+		ccb->datadir |= CCBdataout;
+
+	ccb->cdblen = r->clen;
+	ccb->senselen = 0xFF;
+
+	ccb->datalen[0] = n>>16;
+	ccb->datalen[1] = n>>8;
+	ccb->datalen[2] = n;
+	p = PADDR(data);
+	ccb->dataptr[0] = p>>16;
+	ccb->dataptr[1] = p>>8;
+	ccb->dataptr[2] = p;
+
+	ccb->linkptr[0] = ccb->linkptr[1] = ccb->linkptr[2] = 0;
+	ccb->linkid = 0;
+	ccb->btstat = ccb->sdstat = 0;
+	ccb->reserved[0] = ccb->reserved[1] = 0;
+
+	memmove(ccb->cs, r->cmd, r->clen);
+
+	/*
+	 * There's one more mbox than there there is
+	 * ccb so there is always one free.
+	 */
+	lock(&ctlr->mboxlock);
+	mb = ctlr->mb;
+	mb += ctlr->mbox;
+	p = PADDR(ccb);
+	mb->ccb[0] = p>>16;
+	mb->ccb[1] = p>>8;
+	mb->ccb[2] = p;
+	mb->code = Mbostart;
+	ctlr->mbox++;
+	if(ctlr->mbox >= NMbox)
+		ctlr->mbox = 0;
+
+	/*
+	 * This command does not require Hardy
+	 * and doesn't generate a Cmdc interrupt.
+	 */
+	ccb->done = 0;
+	outb(ctlr->port+Rcpr, Cstart);
+	unlock(&ctlr->mboxlock);
+
+	/*
+	 * Wait for the request to complete and return the status.
+	 * Since the buffer is not reference counted cannot return
+	 * until the DMA is done writing into the buffer so the caller
+	 * cannot free the buffer prematurely.
+	 */
+	while(waserror())
+		;
+	tsleep(ccb, done24, ccb, 30*1000);
+	poperror();
+
+	if(!done24(ccb)){
+		print("%s: %d/%d: sd24rio timeout\n",
+			"sdmylex"/*ctlr->sdev->name*/, target, r->lun);
+		if(ccb->data != nil){
+			free(data);
+			ccb->data = nil;
+		}
+		ccbfree(ctlr, (Ccb*)ccb);
+
+		return SDtimeout;
+	}
+
+	/*
+	 * Save the status and patch up the number of
+	 * bytes actually transferred.
+	 * There's a firmware bug on some 956C controllers
+	 * which causes the return count from a successful
+	 * READ CAPACITY not be updated, so fix it here.
+	 */
+	sdstat = ccb->sdstat;
+	btstat = ccb->btstat;
+
+	d = ccb->datalen[0]<<16;
+	d |= ccb->datalen[1]<<8;
+	d |= ccb->datalen[2];
+	if(ccb->cs[0] == 0x25 && sdstat == SDok)
+		d = 0;
+	n -= d;
+	r->rlen = n;
+
+	/*
+	 * Tidy things up if a staging area was used for the data,
+	 */
+	if(ccb->data != nil){
+		if(sdstat == SDok && btstat == 0 && !r->write)
+			memmove(ccb->data, data, n);
+		free(data);
+		ccb->data = nil;
+	}
+
+	/*
+	 * If there was a check-condition, save the
+	 * ccb for a possible request-sense command.
+	 */
+	if(sdstat == SDcheck){
+		if(r->flags & SDnosense){
+			lock(&ctlr->cachelock);
+			if(ctlr->cache[target])
+				ccbfree(ctlr, ctlr->cache[target]);
+			ctlr->cache[target] = (Ccb*)ccb;
+			unlock(&ctlr->cachelock);
+			return SDcheck;
+		}
+		sense = &ccb->cs[ccb->cdblen];
+		n = 8+sense[7];
+		if(n > sizeof(r->sense)-1)
+			n = sizeof(r->sense)-1;
+		memmove(r->sense, sense, n);
+		r->flags |= SDvalidsense;
+	}
+	ccbfree(ctlr, (Ccb*)ccb);
+
+	if(btstat){
+		if(btstat == 0x11)
+			return SDtimeout;
+		return SDeio;
+	}
+	return sdstat;
+}
+
+static void
+mylex24interrupt(Ureg*, void* arg)
+{
+	ulong pa;
+	Ctlr *ctlr;
+	Ccb24 *ccb;
+	Mbox24 *mb, *mbox;
+	int port, rinterrupt, rstatus;
+
+	ctlr = arg;
+	port = ctlr->port;
+
+	/*
+	 * Save and clear the interrupt(s). The only
+	 * interrupts expected are Cmdc, which is ignored,
+	 * and Imbl which means something completed.
+	 * There's one spurious interrupt left over from
+	 * initialisation, ignore it.
+	 */
+	rinterrupt = inb(port+Rinterrupt);
+	rstatus = inb(port+Rstatus);
+	outb(port+Rcontrol, Rint);
+	if((rinterrupt & ~(Cmdc|Imbl)) != Intv && ctlr->spurious++)
+		print("%s: interrupt 0x%2.2ux\n",
+			"sdmylex"/*ctlr->sdev->name*/, rinterrupt);
+	if((rinterrupt & Cmdc) && (rstatus & Cmdinv))
+		print("%s: command invalid\n", "sdmylex"/*ctlr->sdev->name*/);
+
+	/*
+	 * Look for something in the mail.
+	 * If there is, save the status, free the mailbox
+	 * and wakeup whoever.
+	 */
+	mb = ctlr->mb;
+	for(mbox = &mb[ctlr->mbix]; mbox->code; mbox = &mb[ctlr->mbix]){
+		pa = (mbox->ccb[0]<<16)|(mbox->ccb[1]<<8)|mbox->ccb[2];
+		ccb = BPA2K(pa, BUSUNKNOWN);
+		mbox->code = 0;
+		ccb->done = 1;
+		wakeup(ccb);
+
+		ctlr->mbix++;
+		if(ctlr->mbix >= NMbox+NMbox)
+			ctlr->mbix = NMbox;
+	}
+}
+
+static int
+done32(void* arg)
+{
+	return ((Ccb32*)arg)->done;
+}
+
+static int
+mylex32rio(SDreq* r)
+{
+	ulong p;
+	uchar lun;
+	Ctlr *ctlr;
+	Ccb32 *ccb;
+	Mbox32 *mb;
+	int d, n, btstat, sdstat, target;
+
+	ctlr = r->unit->dev->ctlr;
+	target = r->unit->subno;
+	lun = (r->cmd[1]>>5) & 0x07;
+
+	/*
+	 * Ctlr->cache holds the last completed Ccb for this target if it
+	 * returned 'check condition'.
+	 * If this command is a request-sense and there is valid sense data
+	 * from the last completed Ccb, return it immediately.
+	 */
+	lock(&ctlr->cachelock);
+	if((ccb = ctlr->cache[target]) != nil){
+		ctlr->cache[target] = nil;
+		if(r->cmd[0] == 0x03
+		&& ccb->sdstat == SDcheck && lun == (ccb->luntag & 0x07)){
+			unlock(&ctlr->cachelock);
+			if(r->dlen){
+				n = 8+ccb->sense[7];
+				if(n > r->dlen)
+					n = r->dlen;
+				memmove(r->data, ccb->sense, n);
+				r->rlen = n;
+			}
+			ccbfree(ctlr, (Ccb*)ccb);
+			return SDok;
+		}
+	}
+	unlock(&ctlr->cachelock);
+	if(ccb == nil)
+		ccb = ccballoc(ctlr);
+
+	/*
+	 * Fill in the ccb.
+	 */
+	ccb->opcode = Ordl;
+
+	n = r->dlen;
+	if(n == 0)
+		ccb->datadir = CCBdataout|CCBdatain;
+	else if(!r->write)
+		ccb->datadir = CCBdatain;
+	else
+		ccb->datadir = CCBdataout;
+
+	ccb->cdblen = r->clen;
+
+	ccb->datalen[0] = n;
+	ccb->datalen[1] = n>>8;
+	ccb->datalen[2] = n>>16;
+	ccb->datalen[3] = n>>24;
+	p = PADDR(r->data);
+	ccb->dataptr[0] = p;
+	ccb->dataptr[1] = p>>8;
+	ccb->dataptr[2] = p>>16;
+	ccb->dataptr[3] = p>>24;
+
+	ccb->targetid = target;
+	ccb->luntag = lun;
+	if(r->unit->inquiry[7] & 0x02)
+		ccb->luntag |= SQTag|TagEnable;
+	memmove(ccb->cdb, r->cmd, r->clen);
+	ccb->btstat = ccb->sdstat = 0;
+	ccb->ccbctl = 0;
+
+	/*
+	 * There's one more mbox than there there is
+	 * ccb so there is always one free.
+	 */
+	lock(&ctlr->mboxlock);
+	mb = ctlr->mb;
+	mb += ctlr->mbox;
+	p = PADDR(ccb);
+	mb->ccb[0] = p;
+	mb->ccb[1] = p>>8;
+	mb->ccb[2] = p>>16;
+	mb->ccb[3] = p>>24;
+	mb->code = Mbostart;
+	ctlr->mbox++;
+	if(ctlr->mbox >= NMbox)
+		ctlr->mbox = 0;
+
+	/*
+	 * This command does not require Hardy
+	 * and doesn't generate a Cmdc interrupt.
+	 */
+	ccb->done = 0;
+	outb(ctlr->port+Rcpr, Cstart);
+	unlock(&ctlr->mboxlock);
+
+	/*
+	 * Wait for the request to complete and return the status.
+	 * Since the buffer is not reference counted cannot return
+	 * until the DMA is done writing into the buffer so the caller
+	 * cannot free the buffer prematurely.
+	 */
+	while(waserror())
+		;
+	tsleep(ccb, done32, ccb, 30*1000);
+	poperror();
+
+	if(!done32(ccb)){
+		print("%s: %d/%d: sd32rio timeout\n",
+			"sdmylex"/*ctlr->sdev->name*/, target, r->lun);
+		ccbfree(ctlr, (Ccb*)ccb);
+
+		return SDtimeout;
+	}
+
+	/*
+	 * Save the status and patch up the number of
+	 * bytes actually transferred.
+	 * There's a firmware bug on some 956C controllers
+	 * which causes the return count from a successful
+	 * READ CAPACITY not to be updated, so fix it here.
+	 */
+	sdstat = ccb->sdstat;
+	btstat = ccb->btstat;
+
+	d = ccb->datalen[0];
+	d |= (ccb->datalen[1]<<8);
+	d |= (ccb->datalen[2]<<16);
+	d |= (ccb->datalen[3]<<24);
+	if(ccb->cdb[0] == 0x25 && sdstat == SDok)
+		d = 0;
+	n -= d;
+	r->rlen = n;
+
+	/*
+	 * If there was a check-condition, save the
+	 * ccb for a possible request-sense command.
+	 */
+	if(sdstat == SDcheck){
+		if(r->flags & SDnosense){
+			lock(&ctlr->cachelock);
+			if(ctlr->cache[target])
+				ccbfree(ctlr, ctlr->cache[target]);
+			ctlr->cache[target] = (Ccb*)ccb;
+			unlock(&ctlr->cachelock);
+			return SDcheck;
+		}
+		n = 8+ccb->sense[7];
+		if(n > sizeof(r->sense)-1)
+			n = sizeof(r->sense)-1;
+		memmove(r->sense, ccb->sense, n);
+		r->flags |= SDvalidsense;
+	}
+	ccbfree(ctlr, (Ccb*)ccb);
+
+	if(btstat){
+		if(btstat == 0x11)
+			return SDtimeout;
+		return SDeio;
+	}
+	return sdstat;
+}
+
+static void
+mylex32interrupt(Ureg*, void* arg)
+{
+	ulong pa;
+	Ctlr *ctlr;
+	Ccb32 *ccb;
+	Mbox32 *mb, *mbox;
+	int port, rinterrupt, rstatus;
+
+	ctlr = arg;
+	port = ctlr->port;
+
+	/*
+	 * Save and clear the interrupt(s). The only
+	 * interrupts expected are Cmdc, which is ignored,
+	 * and Imbl which means something completed.
+	 * There's one spurious interrupt left over from
+	 * initialisation, ignore it.
+	 */
+	rinterrupt = inb(port+Rinterrupt);
+	rstatus = inb(port+Rstatus);
+	outb(port+Rcontrol, Rint);
+	if((rinterrupt & ~(Cmdc|Imbl)) != Intv && ctlr->spurious++)
+		print("%s: interrupt 0x%2.2ux\n",
+			"sdmylex"/*ctlr->sdev->name*/, rinterrupt);
+	if((rinterrupt & Cmdc) && (rstatus & Cmdinv))
+		print("%s: command invalid\n", "sdmylex"/*ctlr->sdev->name*/);
+
+	/*
+	 * Look for something in the mail.
+	 * If there is, free the mailbox and wakeup whoever.
+	 */
+	mb = ctlr->mb;
+	for(mbox = &mb[ctlr->mbix]; mbox->code; mbox = &mb[ctlr->mbix]){
+		pa = (mbox->ccb[3]<<24)
+		    |(mbox->ccb[2]<<16)
+		    |(mbox->ccb[1]<<8)
+		    |mbox->ccb[0];
+		if(ctlr->pcidev)
+			ccb = BPA2K(pa, ctlr->pcidev->tbdf);
+		else
+			ccb = BPA2K(pa, BUSUNKNOWN);
+		mbox->code = 0;
+		ccb->done = 1;
+		wakeup(ccb);
+
+		ctlr->mbix++;
+		if(ctlr->mbix >= NMbox+NMbox)
+			ctlr->mbix = NMbox;
+	}
+}
+
+static int
+mylexrio(SDreq* r)
+{
+	int subno;
+	Ctlr *ctlr;
+
+	subno = r->unit->subno;
+	ctlr = r->unit->dev->ctlr;
+	if(subno == ctlr->id || (!ctlr->wide && subno >= 8))
+		r->status = SDtimeout;
+	else if(ctlr->bus == 24)
+		r->status = mylex24rio(r);
+	else
+		r->status = mylex32rio(r);
+	return r->status;
+}
+
+/*
+ * Issue a command to a controller. The command and its length is
+ * contained in cmd and cmdlen. If any data is to be
+ * returned, datalen should be non-zero, and the returned data
+ * will be placed in data.
+ * If Cmdc is set, bail out, the invalid command will be handled
+ * when the interrupt is processed.
+ */
+static void
+issueio(int port, uchar* cmd, int cmdlen, uchar* data, int datalen)
+{
+	int len;
+
+	if(cmd[0] != Cstart && cmd[0] != Ceombri){
+		while(!(inb(port+Rstatus) & Hardy))
+			;
+	}
+	outb(port+Rcpr, cmd[0]);
+
+	len = 1;
+	while(len < cmdlen){
+		if(!(inb(port+Rstatus) & Cprbsy)){
+			outb(port+Rcpr, cmd[len]);
+			len++;
+		}
+		if(inb(port+Rinterrupt) & Cmdc)
+			return;
+	}
+
+	if(datalen){
+		len = 0;
+		while(len < datalen){
+			if(inb(port+Rstatus) & Dirrdy){
+				data[len] = inb(port+Rdatain);
+				len++;
+			}
+			if(inb(port+Rinterrupt) & Cmdc)
+				return;
+		}
+	}
+}
+
+/*
+ * Issue a command to a controller, wait for it to complete then
+ * try to reset the interrupt. Should only be called at initialisation.
+ */
+static int
+issue(Ctlr* ctlr, uchar* cmd, int cmdlen, uchar* data, int datalen)
+{
+	int port;
+	uchar rinterrupt, rstatus;
+	static Lock mylexissuelock;
+
+	port = ctlr->port;
+
+	ilock(&ctlr->issuelock);
+	issueio(port, cmd, cmdlen, data, datalen);
+
+	while(!((rinterrupt = inb(port+Rinterrupt)) & Cmdc))
+		;
+
+	rstatus = inb(port+Rstatus);
+	outb(port+Rcontrol, Rint);
+	iunlock(&ctlr->issuelock);
+
+	if((rinterrupt & Cmdc) && (rstatus & Cmdinv))
+		return 0;
+	return 1;
+}
+
+static SDev*
+mylexprobe(int port, int irq)
+{
+	SDev *sdev;
+	Ctlr *ctlr;
+	uchar cmd[6], data[256];
+	int clen, dlen, timeo;
+
+	if(ioalloc(port, 0x3, 0, "mylex") < 0)
+		return nil;
+	ctlr = nil;
+
+	/*
+	 * Attempt to hard-reset the board and reset
+	 * the SCSI bus. If the board state doesn't settle to
+	 * idle with mailbox initialisation required, either
+	 * it isn't a compatible board or it's broken.
+	 * If the controller has SCAM set this can take a while.
+	 */
+	if(getconf("*noscsireset") != nil)
+		outb(port+Rcontrol, Rhard);
+	else
+		outb(port+Rcontrol, Rhard|Rsbus);
+	for(timeo = 0; timeo < 100; timeo++){
+		if(inb(port+Rstatus) == (Inreq|Hardy))
+			break;
+		delay(100);
+	}
+	if(inb(port+Rstatus) != (Inreq|Hardy)){
+buggery:
+		if(ctlr != nil)
+			free(ctlr);
+		iofree(port);
+		return nil;
+	}
+
+	if((ctlr = malloc(sizeof(Ctlr))) == nil)
+		goto buggery;
+	ctlr->port = port;
+	ctlr->irq = irq;
+	ctlr->bus = 24;
+	ctlr->wide = 0;
+
+	/*
+	 * Try to determine if this is a 32-bit MultiMaster controller
+	 * by attempting to obtain the extended inquiry information;
+	 * this command is not implemented on Adaptec 154xx
+	 * controllers. If successful, the first byte of the returned
+	 * data is the host adapter bus type, 'E' for 32-bit EISA,
+	 * PCI and VLB buses.
+	 */
+	cmd[0] = Ciesi;
+	cmd[1] = 14;
+	clen = 2;
+	dlen = 256;
+	if(issue(ctlr, cmd, clen, data, dlen)){
+		if(data[0] == 'E')
+			ctlr->bus = 32;
+		ctlr->wide = data[0x0D] & 0x01;
+	}
+	else{
+		/*
+		 * Inconceivable though it may seem, a hard controller reset
+		 * is necessary here to clear out the command queue. Every
+		 * board seems to lock-up in a different way if you give an
+		 * invalid command and then try to clear out the
+		 * command/parameter and/or data-in register.
+		 * Soft reset doesn't do the job either. Fortunately no
+		 * serious initialisation has been done yet so there's nothing
+		 * to tidy up.
+		 */
+		outb(port+Rcontrol, Rhard);
+		for(timeo = 0; timeo < 100; timeo++){
+			if(inb(port+Rstatus) == (Inreq|Hardy))
+				break;
+			delay(100);
+		}
+		if(inb(port+Rstatus) != (Inreq|Hardy))
+			goto buggery;
+	}
+
+	/*
+	 * If the BIOS is enabled on the AHA-1542C/CF and BIOS options for
+	 * support of drives > 1Gb, dynamic scanning of the SCSI bus or more
+	 * than 2 drives under DOS 5.0 are enabled, the BIOS disables
+	 * accepting Cmbinit to protect against running with drivers which
+	 * don't support those options. In order to unlock the interface it
+	 * is necessary to read a lock-code using Cextbios and write it back
+	 * using Cmbienable; the lock-code is non-zero.
+	 */
+	cmd[0] = Cinquiry;
+	clen = 1;
+	dlen = 4;
+	if(issue(ctlr, cmd, clen, data, dlen) == 0)
+		goto buggery;
+	if(data[0] >= 0x43){
+		cmd[0] = Cextbios;
+		clen = 1;
+		dlen = 2;
+		if(issue(ctlr, cmd, clen, data, dlen) == 0)
+			goto buggery;
+
+		/*
+		 * Lock-code returned in data[1]. If it's non-zero write
+		 * it back along with bit 0 of byte 0 cleared to enable
+		 * mailbox initialisation.
+		 */
+		if(data[1]){
+			cmd[0] = Cmbienable;
+			cmd[1] = 0;
+			cmd[2] = data[1];
+			clen = 3;
+			if(issue(ctlr, cmd, clen, 0, 0) == 0)
+				goto buggery;
+		}
+	}
+
+	/*
+	 * Get the id, DMA and IRQ info from the board. This will
+	 * cause an interrupt which will hopefully not cause any
+	 * trouble because the interrupt number isn't known yet.
+	 * This is necessary as the DMA won't be set up if the
+	 * board has the BIOS disabled.
+	 *
+	 * If the IRQ is already known, this must be a 32-bit PCI
+	 * or EISA card, in which case the returned DMA and IRQ can
+	 * be ignored.
+	 */
+	cmd[0] = Cinquire;
+	clen = 1;
+	dlen = 3;
+	if(issue(ctlr, cmd, clen, data, dlen) == 0)
+		goto buggery;
+
+	ctlr->id = data[2] & 0x07;
+	if(ctlr->irq < 0){
+		switch(data[0]){		/* DMA Arbitration Priority */
+		case 0x80:			/* Channel 7 */
+			outb(0xD6, 0xC3);
+			outb(0xD4, 0x03);
+			break;
+		case 0x40:			/* Channel 6 */
+			outb(0xD6, 0xC2);
+			outb(0xD4, 0x02);
+			break;
+		case 0x20:			/* Channel 5 */
+			outb(0xD6, 0xC1);
+			outb(0xD4, 0x01);
+			break;
+		case 0x01:			/* Channel 0 */
+			outb(0x0B, 0xC0);
+			outb(0x0A, 0x00);
+			break;
+		default:
+			if(ctlr->bus == 24)
+				goto buggery;
+			break;
+		}
+	
+		switch(data[1]){		/* Interrupt Channel */
+		case 0x40:
+			ctlr->irq = 15;
+			break;
+		case 0x20:
+			ctlr->irq = 14;
+			break;
+		case 0x08:
+			ctlr->irq = 12;
+			break;
+		case 0x04:
+			ctlr->irq = 11;
+			break;
+		case 0x02:
+			ctlr->irq = 10;
+			break;
+		case 0x01:
+			ctlr->irq = 9;
+			break;
+		default:
+			goto buggery;
+		}
+	}
+
+	if((sdev = malloc(sizeof(SDev))) == nil)
+		goto buggery;
+	sdev->ifc = &sdmylexifc;
+	sdev->ctlr = ctlr;
+	ctlr->sdev = sdev;
+	if(!ctlr->wide)
+		sdev->nunit = 8;
+	else
+		sdev->nunit = 16;
+
+	return sdev;
+}
+
+static int mylexport[8] = {
+	0x330, 0x334, 0x230, 0x234, 0x130, 0x134, 0x000, 0x000,
+};
+
+static SDev*
+mylexpnp(void)
+{
+	Pcidev *p;
+	Ctlr *ctlr;
+	ISAConf isa;
+	int cfg, ctlrno, i, x;
+	SDev *sdev, *head, *tail;
+
+	p = nil;
+	head = tail = nil;
+	while(p = pcimatch(p, 0x104B, 0)){
+		if((sdev = mylexprobe(p->mem[0].bar & ~0x01, p->intl)) == nil)
+			continue;
+
+		ctlr = sdev->ctlr;
+		ctlr->pcidev = p;
+
+		if(head != nil)
+			tail->next = sdev;
+		else
+			head = sdev;
+		tail = sdev;
+	}
+
+	if(strncmp(KADDR(0xFFFD9), "EISA", 4) == 0){
+		for(cfg = 0x1000; cfg < MaxEISA*0x1000; cfg += 0x1000){
+			x = 0;
+			for(i = 0; i < 4; i++)
+				x |= inb(cfg+CfgEISA+i)<<(i*8);
+			if(x != 0x0142B30A && x != 0x0242B30A)
+				continue;
+	
+			x = inb(cfg+0xC8C);
+			if((sdev = mylexprobe(mylexport[x & 0x07], -1)) == nil)
+				continue;
+	
+			if(head != nil)
+				tail->next = sdev;
+			else
+				head = sdev;
+			tail = sdev;
+		}
+	}
+
+	for(ctlrno = 0; ctlrno < 4; ctlrno++){
+		memset(&isa, 0, sizeof(isa));
+		if(!isaconfig("scsi", ctlrno, &isa))
+			continue;
+		if(strcmp(isa.type, "aha1542"))
+			continue;
+		if((sdev = mylexprobe(isa.port, -1)) == nil)
+			continue;
+
+		if(head != nil)
+			tail->next = sdev;
+		else
+			head = sdev;
+		tail = sdev;
+	}
+
+	return head;
+}
+
+static SDev*
+mylexid(SDev* sdev)
+{
+	return scsiid(sdev, &sdmylexifc);
+}
+
+static int
+mylex24enable(Ctlr* ctlr)
+{
+	ulong p;
+	Ccb24 *ccb, *ccbp;
+	uchar cmd[6], *v;
+	int len;
+
+	len = (sizeof(Mbox24)*NMbox*2)+(sizeof(Ccb24)*NCcb);
+	v = xspanalloc(len, 32, 0);
+
+	if(!PADDR24(ctlr, sizeof(Ctlr)) || !PADDR24(v, len))
+		return 0;
+
+	ctlr->mb = v;
+	v += sizeof(Mbox24)*NMbox*2;
+
+	ccb = (Ccb24*)v;
+	for(ccbp = ccb; ccbp < &ccb[NCcb]; ccbp++){
+		ccbp->ccb = ctlr->ccb;
+		ctlr->ccb = (Ccb*)ccbp;
+	}
+
+	/*
+	 * Initialise the software controller and
+	 * set the board scanning the mailboxes.
+	 */
+	ctlr->mbix = NMbox;
+
+	cmd[0] = Cinitialise;
+	cmd[1] = NMbox;
+	p = K2BPA(ctlr->mb, BUSUNKNOWN);
+	cmd[2] = p>>16;
+	cmd[3] = p>>8;
+	cmd[4] = p;
+
+	return issue(ctlr, cmd, 5, 0, 0);
+}
+
+static int
+mylex32enable(Ctlr* ctlr)
+{
+	ulong p;
+	Ccb32 *ccb, *ccbp;
+	uchar cmd[6], *v;
+
+	v = xspanalloc((sizeof(Mbox32)*NMbox*2)+(sizeof(Ccb32)*NCcb), 32, 0);
+
+	ctlr->mb = v;
+	v += sizeof(Mbox32)*NMbox*2;
+
+	ccb = (Ccb32*)v;
+	for(ccbp = ccb; ccbp < &ccb[NCcb]; ccbp++){
+		/*
+		 * Fill in some stuff that doesn't change.
+		 */
+		ccbp->senselen = sizeof(ccbp->sense);
+		p = PADDR(ccbp->sense);
+		ccbp->senseptr[0] = p;
+		ccbp->senseptr[1] = p>>8;
+		ccbp->senseptr[2] = p>>16;
+		ccbp->senseptr[3] = p>>24;
+
+		ccbp->ccb = ctlr->ccb;
+		ctlr->ccb = (Ccb*)ccbp;
+	}
+
+	/*
+	 * Attempt wide mode setup.
+	 */
+	if(ctlr->wide){
+		cmd[0] = Cwide;
+		cmd[1] = 1;
+		if(!issue(ctlr, cmd, 2, 0, 0))
+			ctlr->wide = 0;
+	}
+
+	/*
+	 * Initialise the software controller and
+	 * set the board scanning the mailboxes.
+	 */
+	ctlr->mbix = NMbox;
+
+	cmd[0] = Ciem;
+	cmd[1] = NMbox;
+	if(ctlr->pcidev)
+		p = K2BPA(ctlr->mb, ctlr->tbdf);
+	else
+		p = K2BPA(ctlr->mb, BUSUNKNOWN);
+	cmd[2] = p;
+	cmd[3] = p>>8;
+	cmd[4] = p>>16;
+	cmd[5] = p>>24;
+
+	return issue(ctlr, cmd, 6, 0, 0);
+}
+
+static int
+mylexenable(SDev* sdev)
+{
+	int tbdf;
+	Ctlr *ctlr;
+	void (*interrupt)(Ureg*, void*);
+	char name[NAMELEN];
+
+	ctlr = sdev->ctlr;
+	if(ctlr->cache == nil){
+		if((ctlr->cache = malloc(sdev->nunit*sizeof(Ccb*))) == nil)
+			return 0;
+	}
+
+	tbdf = BUSUNKNOWN;
+	if(ctlr->bus == 32){
+		if(ctlr->pcidev){
+			tbdf = ctlr->pcidev->tbdf;
+			pcisetbme(ctlr->pcidev);
+		}
+		if(!mylex32enable(ctlr))
+			return 0;
+		interrupt = mylex32interrupt;
+	}
+	else if(mylex24enable(ctlr))
+		interrupt = mylex24interrupt;
+	else
+		return 0;
+
+	snprint(name, NAMELEN, "sd%c (%s)", sdev->idno, sdev->ifc->name);
+	intrenable(ctlr->irq, interrupt, ctlr, tbdf, name);
+
+	return 1;
+}
+
+static int
+mylexdisable(SDev* sdev)
+{
+	Ctlr *ctlr;
+	int port, timeo;
+
+	ctlr = sdev->ctlr;
+	port = ctlr->port;
+
+	if(getconf("*noscsireset") != nil)
+		outb(port+Rcontrol, Rhard);
+	else
+		outb(port+Rcontrol, Rhard|Rsbus);
+	for(timeo = 0; timeo < 100; timeo++){
+		if(inb(port+Rstatus) == (Inreq|Hardy))
+			break;
+		delay(100);
+	}
+	if(inb(port+Rstatus) != (Inreq|Hardy))
+		return 0;
+
+	return 1;
+}
+
+SDifc sdmylexifc = {
+	"mylex",			/* name */
+
+	mylexpnp,			/* pnp */
+	nil,				/* legacy */
+	mylexid,			/* id */
+	mylexenable,			/* enable */
+	mylexdisable,			/* disable */
+
+	scsiverify,			/* verify */
+	scsionline,			/* online */
+	mylexrio,			/* rio */
+	nil,				/* rctl */
+	nil,				/* wctl */
+
+	scsibio,			/* bio */
+};
--- /dev/null
+++ b/os/boot.original/pc/sdscsi.c
@@ -1,0 +1,376 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "ureg.h"
+#include "error.h"
+
+#include "sd.h"
+
+static int
+scsitest(SDreq* r)
+{
+	r->write = 0;
+	memset(r->cmd, 0, sizeof(r->cmd));
+	r->cmd[1] = r->lun<<5;
+	r->clen = 6;
+	r->data = nil;
+	r->dlen = 0;
+	r->flags = 0;
+
+	r->status = ~0;
+
+// cgascreenputs("A", 1);
+	return r->unit->dev->ifc->rio(r);
+}
+
+int
+scsiverify(SDunit* unit)
+{
+	static SDreq *r;
+	int i, status;
+	static uchar *inquiry;
+
+	if((r = sdmalloc(r, sizeof(SDreq))) == nil)
+		return 0;
+
+	if((inquiry = sdmalloc(inquiry, sizeof(unit->inquiry))) == nil)
+		return 0;
+
+	r->unit = unit;
+	r->lun = 0;		/* ??? */
+
+	memset(unit->inquiry, 0, sizeof(unit->inquiry));
+	r->write = 0;
+	r->cmd[0] = 0x12;
+	r->cmd[1] = r->lun<<5;
+	r->cmd[4] = sizeof(unit->inquiry)-1;
+	r->clen = 6;
+	r->data = inquiry;
+	r->dlen = sizeof(unit->inquiry)-1;
+	r->flags = 0;
+
+	r->status = ~0;
+// cgascreenputs("B", 1);
+	if(unit->dev->ifc->rio(r) != SDok){
+		return 0;
+	}
+	memmove(unit->inquiry, inquiry, r->dlen);
+
+	SET(status);
+	for(i = 0; i < 3; i++){
+		while((status = scsitest(r)) == SDbusy)
+			;
+		if(status == SDok || status != SDcheck)
+			break;
+		if(!(r->flags & SDvalidsense))
+			break;
+		if((r->sense[2] & 0x0F) != 0x02)
+			continue;
+
+		/*
+		 * Unit is 'not ready'.
+		 * If it is in the process of becoming ready or needs
+		 * an initialising command, set status so it will be spun-up
+		 * below.
+		 * If there's no medium, that's OK too, but don't
+		 * try to spin it up.
+		 */
+		if(r->sense[12] == 0x04){
+			if(r->sense[13] == 0x02 || r->sense[13] == 0x01){
+				status = SDok;
+				break;
+			}
+		}
+		if(r->sense[12] == 0x3A)
+			break;
+	}
+
+	if(status == SDok){
+		/*
+		 * Try to ensure a direct-access device is spinning.
+		 * Ignore the result.
+		 */
+		if((unit->inquiry[0] & 0x1F) == 0){
+			memset(r->cmd, 0, sizeof(r->cmd));
+			r->write = 0;
+			r->cmd[0] = 0x1B;
+			r->cmd[1] = r->lun<<5;
+			r->cmd[4] = 1;
+			r->clen = 6;
+			r->data = nil;
+			r->dlen = 0;
+			r->flags = 0;
+
+			r->status = ~0;
+			unit->dev->ifc->rio(r);
+		}
+		return 1;
+	}
+	return 0;
+}
+
+int
+return0(void*)
+{
+	return 0;
+}
+
+static int
+scsirio(SDreq* r)
+{
+	/*
+	 * Perform an I/O request, returning
+	 *	-1	failure
+	 *	 0	ok
+	 *	 2	retry
+	 * The contents of r may be altered so the
+	 * caller should re-initialise if necesary.
+	 */
+	r->status = ~0;
+// cgascreenputs("C", 1);
+	switch(r->unit->dev->ifc->rio(r)){
+	default:
+		break;
+	case SDcheck:
+		if(!(r->flags & SDvalidsense))
+			return -1;
+		switch(r->sense[2] & 0x0F){
+		case 0x00:		/* no sense */
+		case 0x01:		/* recovered error */
+			return 2;
+		case 0x06:		/* check condition */
+			/*
+			 * 0x28 - not ready to ready transition,
+			 *	  medium may have changed.
+			 * 0x29 - power on or some type of reset.
+			 */
+			if(r->sense[12] == 0x28 && r->sense[13] == 0)
+				return 2;
+			if(r->sense[12] == 0x29)
+				return 2;
+			break;
+		case 0x02:		/* not ready */
+			/*
+			 * If no medium present, bail out.
+			 * If unit is becoming ready, rather than not
+			 * not ready, wait a little then poke it again. 							 */
+			if(r->sense[12] == 0x3A)
+				return -1;
+			if(r->sense[12] != 0x04 || r->sense[13] != 0x01)
+				return -1;
+
+			tsleep(nil, return0, 0, 500);
+			scsitest(r);
+			return 2;
+		default:
+			break;
+		}
+		break;
+	case SDok:
+		return 0;
+	}
+	return -1;
+}
+
+int
+scsionline(SDunit* unit)
+{
+	int ok;
+	static SDreq *r;
+	static uchar *p;
+
+	if((r = sdmalloc(r, sizeof(SDreq))) == nil)
+		return 0;
+
+	if((p = sdmalloc(p, 8)) == nil)
+		return 0;
+
+	ok = 0;
+
+	r->unit = unit;
+	r->lun = 0;				/* ??? */
+	for(;;){
+		/*
+		 * Read-capacity is mandatory for DA, WORM, CD-ROM and
+		 * MO. It may return 'not ready' if type DA is not
+		 * spun up, type MO or type CD-ROM are not loaded or just
+		 * plain slow getting their act together after a reset.
+		 */
+		r->write = 0;
+		memset(r->cmd, 0, sizeof(r->cmd));
+		r->cmd[0] = 0x25;
+		r->cmd[1] = r->lun<<5;
+		r->clen = 10;
+		r->data = p;
+		r->dlen = 8;
+		r->flags = 0;
+	
+		r->status = ~0;
+// cgascreenputs("F", 1);
+		switch(scsirio(r)){
+		default:
+			break;
+		case 0:
+			unit->sectors = (p[0]<<24)|(p[1]<<16)|(p[2]<<8)|p[3];
+			/*
+			 * Read-capacity returns the LBA of the last sector,
+			 * therefore the number of sectors must be incremented.
+			 */
+			unit->sectors++;
+			unit->secsize = (p[4]<<24)|(p[5]<<16)|(p[6]<<8)|p[7];
+			ok = 1;
+			break;
+		case 2:
+			continue;
+		}
+		break;
+	}
+
+	return ok;
+}
+
+int
+scsiexec(SDunit* unit, int write, uchar* cmd, int clen, void* data, int* dlen)
+{
+	static SDreq *r;
+	int status;
+
+	if((r = sdmalloc(r, sizeof(SDreq))) == nil)
+		return SDmalloc;
+
+	r->unit = unit;
+	r->lun = cmd[1]>>5;		/* ??? */
+	r->write = write;
+	memmove(r->cmd, cmd, clen);
+	r->clen = clen;
+	r->data = data;
+	if(dlen)
+		r->dlen = *dlen;
+	r->flags = 0;
+
+	r->status = ~0;
+
+	/*
+	 * Call the device-specific I/O routine.
+	 * There should be no calls to 'error()' below this
+	 * which percolate back up.
+	 */
+// cgascreenputs("D", 1);
+	switch(status = unit->dev->ifc->rio(r)){
+	case SDok:
+		if(dlen)
+			*dlen = r->rlen;
+		/*FALLTHROUGH*/
+	case SDcheck:
+		/*FALLTHROUGH*/
+	default:
+		/*
+		 * It's more complicated than this. There are conditions
+		 * which are 'ok' but for which the returned status code
+		 * is not 'SDok'.
+		 * Also, not all conditions require a reqsense, might
+		 * need to do a reqsense here and make it available to the
+		 * caller somehow.
+		 *
+		 * Mañana.
+		 */
+		break;
+	}
+
+	return status;
+}
+
+long
+scsibio(SDunit* unit, int lun, int write, void* data, long nb, long bno)
+{
+	static SDreq *r;
+	long rlen;
+
+	if((r = sdmalloc(r, sizeof(SDreq))) == nil)
+		return SDmalloc;
+
+	r->unit = unit;
+	r->lun = lun;
+again:
+	r->write = write;
+	if(write == 0)
+		r->cmd[0] = 0x28;
+	else
+		r->cmd[0] = 0x2A;
+	r->cmd[1] = (lun<<5);
+	r->cmd[2] = bno>>24;
+	r->cmd[3] = bno>>16;
+	r->cmd[4] = bno>>8;
+	r->cmd[5] = bno;
+	r->cmd[6] = 0;
+	r->cmd[7] = nb>>8;
+	r->cmd[8] = nb;
+	r->cmd[9] = 0;
+	r->clen = 10;
+	r->data = data;
+	r->dlen = nb*unit->secsize;
+	r->flags = 0;
+
+	r->status = ~0;
+// cgascreenputs("E", 1);
+	switch(scsirio(r)){
+	default:
+		rlen = -1;
+		break;
+	case 0:
+		rlen = r->rlen;
+		break;
+	case 2:
+		rlen = -1;
+		if(!(r->flags & SDvalidsense))
+			break;
+		switch(r->sense[2] & 0x0F){
+		default:
+			break;
+		case 0x06:		/* check condition */
+			/*
+			 * Check for a removeable media change.
+			 * If so, mark it and zap the geometry info
+			 * to force an online request.
+			 */
+			if(r->sense[12] != 0x28 || r->sense[13] != 0)
+				break;
+			if(unit->inquiry[1] & 0x80){
+				unit->sectors = 0;
+			}
+			break;
+		case 0x02:		/* not ready */
+			/*
+			 * If unit is becoming ready,
+			 * rather than not not ready, try again.
+			 */
+			if(r->sense[12] == 0x04 && r->sense[13] == 0x01)
+				goto again;
+			break;
+		}
+		break;
+	}
+
+	return rlen;
+}
+
+SDev*
+scsiid(SDev* sdev, SDifc* ifc)
+{
+	static char idno[16] = "0123456789abcdef";
+	static char *p = idno;
+
+	while(sdev){
+		if(sdev->ifc == ifc){
+			sdev->idno = *p++;
+			if(p >= &idno[sizeof(idno)])
+				break;
+		}
+		sdev = sdev->next;
+	}
+
+	return nil;
+}
--- /dev/null
+++ b/os/boot.original/pc/trap.c
@@ -1,0 +1,332 @@
+#include	"u.h"
+#include	"lib.h"
+#include	"mem.h"
+#include	"dat.h"
+#include	"fns.h"
+#include	"io.h"
+#include	"ureg.h"
+
+void	intr0(void), intr1(void), intr2(void), intr3(void);
+void	intr4(void), intr5(void), intr6(void), intr7(void);
+void	intr8(void), intr9(void), intr10(void), intr11(void);
+void	intr12(void), intr13(void), intr14(void), intr15(void);
+void	intr16(void);
+void	intr24(void), intr25(void), intr26(void), intr27(void);
+void	intr28(void), intr29(void), intr30(void), intr31(void);
+void	intr32(void), intr33(void), intr34(void), intr35(void);
+void	intr36(void), intr37(void), intr38(void), intr39(void);
+void	intr64(void);
+void	intrbad(void);
+
+/*
+ *  8259 interrupt controllers
+ */
+enum
+{
+	Int0ctl=	0x20,		/* control port (ICW1, OCW2, OCW3) */
+	Int0aux=	0x21,		/* everything else (ICW2, ICW3, ICW4, OCW1) */
+	Int1ctl=	0xA0,		/* control port */
+	Int1aux=	0xA1,		/* everything else (ICW2, ICW3, ICW4, OCW1) */
+
+	Icw1=		0x10,		/* select bit in ctl register */
+	Ocw2=		0x00,
+	Ocw3=		0x08,
+
+	EOI=		0x20,		/* non-specific end of interrupt */
+
+	Elcr1=		0x4D0,		/* Edge/Level Triggered Register */
+	Elcr2=		0x4D1,
+};
+
+int	int0mask = 0xff;	/* interrupts enabled for first 8259 */
+int	int1mask = 0xff;	/* interrupts enabled for second 8259 */
+int i8259elcr;				/* mask of level-triggered interrupts */
+
+/*
+ *  trap/interrupt gates
+ */
+Segdesc ilt[256];
+
+enum 
+{
+	Maxhandler=	32,		/* max number of interrupt handlers */
+};
+
+typedef struct Handler	Handler;
+struct Handler
+{
+	void	(*r)(Ureg*, void*);
+	void	*arg;
+	Handler	*next;
+};
+
+struct
+{
+	Handler	*ivec[256];
+	Handler	h[Maxhandler];
+	int	nextfree;
+} halloc;
+
+void
+sethvec(int v, void (*r)(void), int type, int pri)
+{
+	ilt[v].d0 = ((ulong)r)&0xFFFF|(KESEL<<16);
+	ilt[v].d1 = ((ulong)r)&0xFFFF0000|SEGP|SEGPL(pri)|type;
+}
+
+void
+setvec(int v, void (*r)(Ureg*, void*), void *arg)
+{
+	Handler *h;
+
+	if(halloc.nextfree >= Maxhandler)
+		panic("out of interrupt handlers");
+	h = &halloc.h[halloc.nextfree++];
+	h->next = halloc.ivec[v];
+	h->r = r;
+	h->arg = arg;
+	halloc.ivec[v] = h;
+
+	/*
+	 *  enable corresponding interrupt in 8259
+	 */
+	if((v&~0x7) == VectorPIC){
+		int0mask &= ~(1<<(v&7));
+		outb(Int0aux, int0mask);
+	} else if((v&~0x7) == VectorPIC+8){
+		int1mask &= ~(1<<(v&7));
+		outb(Int1aux, int1mask);
+	}
+}
+
+void
+trapdisable(void)
+{
+	outb(Int0aux, 0xFF);
+	outb(Int1aux, 0xFF);
+}
+
+void
+trapenable(void)
+{
+	outb(Int0aux, int0mask);
+	outb(Int1aux, int1mask);
+}
+
+
+/*
+ *  set up the interrupt/trap gates
+ */
+void
+trapinit(void)
+{
+	int i, x;
+
+	/*
+	 *  set all interrupts to panics
+	 */
+	for(i = 0; i < 256; i++)
+		sethvec(i, intrbad, SEGTG, 0);
+
+	/*
+	 *  80386 processor (and coprocessor) traps
+	 */
+	sethvec(0, intr0, SEGTG, 0);
+	sethvec(1, intr1, SEGTG, 0);
+	sethvec(2, intr2, SEGTG, 0);
+	sethvec(3, intr3, SEGTG, 0);
+	sethvec(4, intr4, SEGTG, 0);
+	sethvec(5, intr5, SEGTG, 0);
+	sethvec(6, intr6, SEGTG, 0);
+	sethvec(7, intr7, SEGTG, 0);
+	sethvec(8, intr8, SEGTG, 0);
+	sethvec(9, intr9, SEGTG, 0);
+	sethvec(10, intr10, SEGTG, 0);
+	sethvec(11, intr11, SEGTG, 0);
+	sethvec(12, intr12, SEGTG, 0);
+	sethvec(13, intr13, SEGTG, 0);
+	sethvec(14, intr14, SEGTG, 0);
+	sethvec(15, intr15, SEGTG, 0);
+	sethvec(16, intr16, SEGTG, 0);
+
+	/*
+	 *  device interrupts
+	 */
+	sethvec(24, intr24, SEGIG, 0);
+	sethvec(25, intr25, SEGIG, 0);
+	sethvec(26, intr26, SEGIG, 0);
+	sethvec(27, intr27, SEGIG, 0);
+	sethvec(28, intr28, SEGIG, 0);
+	sethvec(29, intr29, SEGIG, 0);
+	sethvec(30, intr30, SEGIG, 0);
+	sethvec(31, intr31, SEGIG, 0);
+	sethvec(32, intr32, SEGIG, 0);
+	sethvec(33, intr33, SEGIG, 0);
+	sethvec(34, intr34, SEGIG, 0);
+	sethvec(35, intr35, SEGIG, 0);
+	sethvec(36, intr36, SEGIG, 0);
+	sethvec(37, intr37, SEGIG, 0);
+	sethvec(38, intr38, SEGIG, 0);
+	sethvec(39, intr39, SEGIG, 0);
+
+	/*
+	 *  tell the hardware where the table is (and how long)
+	 */
+	putidt(ilt, sizeof(ilt)-1);
+
+	/*
+	 *  Set up the first 8259 interrupt processor.
+	 *  Make 8259 interrupts start at CPU vector VectorPIC.
+	 *  Set the 8259 as master with edge triggered
+	 *  input with fully nested interrupts.
+	 */
+	outb(Int0ctl, Icw1|0x01);	/* ICW1 - edge triggered, master,
+					   ICW4 will be sent */
+	outb(Int0aux, VectorPIC);	/* ICW2 - interrupt vector offset */
+	outb(Int0aux, 0x04);		/* ICW3 - have slave on level 2 */
+	outb(Int0aux, 0x01);		/* ICW4 - 8086 mode, not buffered */
+
+	/*
+	 *  Set up the second 8259 interrupt processor.
+	 *  Make 8259 interrupts start at CPU vector VectorPIC+8.
+	 *  Set the 8259 as master with edge triggered
+	 *  input with fully nested interrupts.
+	 */
+	outb(Int1ctl, Icw1|0x01);	/* ICW1 - edge triggered, master,
+					   ICW4 will be sent */
+	outb(Int1aux, VectorPIC+8);	/* ICW2 - interrupt vector offset */
+	outb(Int1aux, 0x02);		/* ICW3 - I am a slave on level 2 */
+	outb(Int1aux, 0x01);		/* ICW4 - 8086 mode, not buffered */
+	outb(Int1aux, int1mask);
+
+	/*
+	 *  pass #2 8259 interrupts to #1
+	 */
+	int0mask &= ~0x04;
+	outb(Int0aux, int0mask);
+
+	/*
+	 * Set Ocw3 to return the ISR when ctl read.
+	 */
+	outb(Int0ctl, Ocw3|0x03);
+	outb(Int1ctl, Ocw3|0x03);
+
+	/*
+	 * Check for Edge/Level register.
+	 * This check may not work for all chipsets.
+	 * First try a non-intrusive test - the bits for
+	 * IRQs 13, 8, 2, 1 and 0 must be edge (0). If
+	 * that's OK try a R/W test.
+	 */
+	x = (inb(Elcr2)<<8)|inb(Elcr1);
+	if(!(x & 0x2107)){
+		outb(Elcr1, 0);
+		if(inb(Elcr1) == 0){
+			outb(Elcr1, 0x20);
+			if(inb(Elcr1) == 0x20)
+				i8259elcr = x;
+			outb(Elcr1, x & 0xFF);
+			print("ELCR: %4.4uX\n", i8259elcr);
+		}
+	}
+}
+
+/*
+ *  dump registers
+ */
+static void
+dumpregs(Ureg *ur)
+{
+	print("FLAGS=%lux TRAP=%lux ECODE=%lux PC=%lux\n",
+		ur->flags, ur->trap, ur->ecode, ur->pc);
+	print("  AX %8.8lux  BX %8.8lux  CX %8.8lux  DX %8.8lux\n",
+		ur->ax, ur->bx, ur->cx, ur->dx);
+	print("  SI %8.8lux  DI %8.8lux  BP %8.8lux\n",
+		ur->si, ur->di, ur->bp);
+	print("  CS %4.4lux DS %4.4lux  ES %4.4lux  FS %4.4lux  GS %4.4lux\n",
+		ur->cs & 0xFF, ur->ds & 0xFFFF, ur->es & 0xFFFF, ur->fs & 0xFFFF, ur->gs & 0xFFFF);
+	print("  CR0 %8.8lux CR2 %8.8lux CR3 %8.8lux\n",
+		getcr0(), getcr2(), getcr3());
+}
+
+/*
+ *  All traps
+ */
+void
+trap(Ureg *ur)
+{
+	int v;
+	int c;
+	Handler *h;
+	ushort isr;
+
+	v = ur->trap;
+	/*
+	 *  tell the 8259 that we're done with the
+	 *  highest level interrupt (interrupts are still
+	 *  off at this point)
+	 */
+	c = v&~0x7;
+	isr = 0;
+	if(c==VectorPIC || c==VectorPIC+8){
+		isr = inb(Int0ctl);
+		outb(Int0ctl, EOI);
+		if(c == VectorPIC+8){
+			isr |= inb(Int1ctl)<<8;
+			outb(Int1ctl, EOI);
+		}
+	}
+
+	if(v>=256 || (h = halloc.ivec[v]) == 0){
+		if(v >= VectorPIC && v < VectorPIC+16){
+			v -= VectorPIC;
+			/*
+			 * Check for a default IRQ7. This can happen when
+			 * the IRQ input goes away before the acknowledge.
+			 * In this case, a 'default IRQ7' is generated, but
+			 * the corresponding bit in the ISR isn't set.
+			 * In fact, just ignore all such interrupts.
+			 */
+			if(isr & (1<<v))
+				print("unknown interrupt %d pc=0x%lux\n", v, ur->pc);
+			return;
+		}
+
+		switch(v){
+
+		case 0x02:				/* NMI */
+			print("NMI: nmisc=0x%2.2ux, nmiertc=0x%2.2ux, nmiesc=0x%2.2ux\n",
+				inb(0x61), inb(0x70), inb(0x461));
+			return;
+
+		default:
+			dumpregs(ur);
+			panic("exception/interrupt %d", v);
+			return;
+		}
+	}
+
+	/*
+	 *  call the trap routines
+	 */
+	do {
+		(*h->r)(ur, h->arg);
+		h = h->next;
+	} while(h);
+}
+
+extern void realmode0(void);	/* in l.s */
+
+extern int realmodeintr;
+extern Ureg realmoderegs;
+
+void
+realmode(int intr, Ureg *ureg)
+{
+	realmoderegs = *ureg;
+	realmodeintr = intr;
+	trapdisable();
+	realmode0();
+	trapenable();
+	*ureg = realmoderegs;
+}
--- /dev/null
+++ b/os/boot.original/pc/ureg.h
@@ -1,0 +1,27 @@
+typedef struct Ureg	Ureg;
+
+struct Ureg
+{
+	ulong	di;		/* general registers */
+	ulong	si;		/* ... */
+	ulong	bp;		/* ... */
+	ulong	nsp;
+	ulong	bx;		/* ... */
+	ulong	dx;		/* ... */
+	ulong	cx;		/* ... */
+	ulong	ax;		/* ... */
+	ulong	gs;		/* data segments */
+	ulong	fs;		/* ... */
+	ulong	es;		/* ... */
+	ulong	ds;		/* ... */
+	ulong	trap;		/* trap type */
+	ulong	ecode;		/* error code (or zero) */
+	ulong	pc;		/* pc */
+	ulong	cs;		/* old context */
+	ulong	flags;		/* old flags */
+	union {
+		ulong	usp;
+		ulong	sp;
+	};
+	ulong	ss;		/* old stack segment */
+};
--- /dev/null
+++ b/os/boot.original/pc/x16.h
@@ -1,0 +1,159 @@
+/*
+ * Can't write 16-bit code for 8a without getting into
+ * lots of bother, so define some simple commands and
+ * output the code directly.
+ * 
+ * N.B. CALL16(x) kills DI, so don't expect it to be
+ * saved across calls.
+ */
+#define rAX		0		/* rX  */
+#define rCX		1
+#define rDX		2
+#define rBX		3
+#define rSP		4		/* SP */
+#define rBP		5		/* BP */
+#define rSI		6		/* SI */
+#define rDI		7		/* DI */
+
+#define rAL		0		/* rL  */
+#define rCL		1
+#define rDL		2
+#define rBL		3
+#define rAH		4		/* rH */
+#define rCH		5
+#define rDH		6
+#define rBH		7
+
+#define rES		0		/* rS */
+#define rCS		1
+#define rSS		2
+#define rDS		3
+#define rFS		4
+#define rGS		5
+
+#define xSI		4		/* rI (index) */
+#define xDI		5
+#define xBP		6
+#define xBX		7
+
+#define rCR0		0		/* rC */
+#define rCR2		2
+#define rCR3		3
+#define rCR4		4
+
+#define OP(o, m, ro, rm)	BYTE $o;	/* op + modr/m byte */	\
+			BYTE $(((m)<<6)|((ro)<<3)|(rm))
+#define OPrm(o, r, m)	OP(o, 0x00, r, 0x06);	/* general r <-> m */	\
+			WORD $m;
+#define OPrr(o, r0, r1)	OP(o, 0x03, r0, r1);	/* general r -> r */
+
+#define LW(m, rX)	OPrm(0x8B, rX, m)	/* m -> rX */
+#define LXW(x, rI, r)	OP(0x8B, 0x02, r, rI);	/* x(rI) -> r */	\
+			WORD $x
+#define LBPW(x, r)	OP(0x8B, 0x02, r, xBP);	/* x(rBP) -> r */	\
+			WORD $x
+#define LB(m, rB)	OPrm(0x8A, rB, m)	/* m -> r[HL] */
+#define LXB(x, rI, r)	OP(0x8A, 0x01, r, rI);	/* x(rI) -> r */	\
+			BYTE $x
+#define LBPB(x, r)	OP(0x8A, 0x01, r, xBP);	/* x(rBP) -> r */	\
+			BYTE $x
+#define SW(rX, m)	OPrm(0x89, rX, m)	/* rX -> m */
+#define SXW(r, x, rI)	OP(0x89, 0x02, r, rI);	/* r -> x(rI) */	\
+			WORD $x
+#define SBPW(r, x)	OP(0x89, 0x02, r, xBP);	/* r -> x(rBP) */	\
+			WORD $(x)
+#define SBPWI(i, x)	OP(0xC7, 0x01, 0, xBP);	/* i -> x(rBP) */	\
+			BYTE $(x); WORD $(i)
+#define STB(rB, m)	OPrm(0x88, rB, m)	/* rB -> m */
+#define SXB(r, x, rI)	OP(0x88, 0x01, r, rI);	/* rB -> x(rI) */	\
+			BYTE $x
+#define SBPB(r, x)	OP(0x88, 0x01, r, xBP);	/* r -> x(rBP) */	\
+			BYTE $x
+#define SBPBI(i, x)	OP(0xC6, 0x01, 0, xBP);	/* i -> x(rBP) */	\
+			BYTE $(x); BYTE $(i)
+#define LWI(i, rX)	BYTE $(0xB8+rX);	/* i -> rX */		\
+			WORD $i;
+#define LBI(i, rB)	BYTE $(0xB0+rB);	/* i -> r[HL] */	\
+			BYTE $i
+
+#define MW(r0, r1)	OPrr(0x89, r0, r1)	/* r0 -> r1 */
+#define MFSR(rS, rX)	OPrr(0x8C, rS, rX)	/* rS -> rX */
+#define MTSR(rX, rS)	OPrr(0x8E, rS, rX)	/* rX -> rS */
+#define MFCR(rC, rX)	BYTE $0x0F;		/* rC -> rX */		\
+			OP(0x20, 0x03, rC, rX)
+#define MTCR(rX, rC)	BYTE $0x0F;		/* rX -> rC */		\
+			OP(0x22, 0x03, rC, rX)
+
+#define ADC(r0, r1)	OPrr(0x11, r0, r1)	/* r0 + r1 -> r1 */
+#define ADD(r0, r1)	OPrr(0x01, r0, r1)	/* r0 + r1 -> r1 */
+#define ADDI(i, r)	OP(0x81, 0x03, 0x00, r);/* i+r -> r */		\
+			WORD $i;
+#define AND(r0, r1)	OPrr(0x21, r0, r1)	/* r0&r1 -> r1 */
+#define ANDI(i, r)	OP(0x81, 0x03, 0x04, r);/* i&r -> r */		\
+			WORD $i;
+#define CLR(r)		OPrr(0x31, r, r)	/* r^r -> r */
+#define CLRB(r)		OPrr(0x30, r, r)	/* r^r -> r */
+#define CMP(r0, r1)	OPrr(0x39, r0, r1)	/* r1-r0 -> flags */
+#define CMPI(i, r)	OP(0x81, 0x03, 0x07, r);/* r-i -> flags */	\
+			WORD $i;
+#define CMPBR(r0, r1)	OPrr(0x38, r0, r1)	/* r1-r0 -> flags */
+#define DEC(r)		BYTE $(0x48|r)		/* r-1 -> r */
+#define DIV(r)		OPrr(0xF7, 0x06, r)	/* rDX:rAX/r -> rAX, rDX:rAX%r -> rDX */
+#define INC(r)		BYTE $(0x40|r)		/* r+1 -> r */
+#define MUL(r)		OPrr(0xF7, 0x04, r)	/* r*rAX -> rDX:rAX */
+#define IMUL(r0, r1)	BYTE $0x0F;		/* r0*r1 -> r1 */	\
+			OPrr(0xAF, r1, r0)	/* (signed) */
+#define OR(r0, r1)	OPrr(0x09, r0, r1)	/* r0|r1 -> r1 */
+#define ORB(r0, r1)	OPrr(0x08, r0, r1)	/* r0|r1 -> r1 */
+#define ORI(i, r)	OP(0x81, 0x03, 0x01, r);/* i|r -> r */		\
+			WORD $i;
+#define ROLI(i, r)	OPrr(0xC1, 0x00, r);	/* r<<>>i -> r */	\
+			BYTE $i;
+#define SHLI(i, r)	OPrr(0xC1, 0x04, r);	/* r<<i -> r */		\
+			BYTE $i;
+#define SHLBI(i, r)	OPrr(0xC0, 0x04, r);	/* r<<i -> r */		\
+			BYTE $i;
+#define SHRI(i, r)	OPrr(0xC1, 0x05, r);	/* r>>i -> r */		\
+			BYTE $i;
+#define SHRBI(i, r)	OPrr(0xC0, 0x05, r);	/* r>>i -> r */		\
+			BYTE $i;
+#define SUB(r0, r1)	OPrr(0x29, r0, r1)	/* r1-r0 -> r1 */
+#define SUBI(i, r)	OP(0x81, 0x03, 0x05, r);/* r-i -> r */		\
+			WORD $i;
+
+#define STOSW		STOSL
+
+#define CALL16(f)	LWI(f, rDI);		/* &f -> rDI */		\
+			BYTE $0xFF;		/* (*rDI) */		\
+			BYTE $0xD7;
+#define FARJUMP16(s, o)	BYTE $0xEA;		/* jump to ptr16:16 */	\
+			WORD $o; WORD $s
+#define FARJUMP32(s, o)	BYTE $0x66;		/* jump to ptr32:16 */	\
+			BYTE $0xEA; LONG $o; WORD $s
+#define	DELAY		BYTE $0xEB;		/* jmp .+2 */		\
+			BYTE $0x00
+#define BIOSCALL(b)	INT $b			/* INT $b */
+
+#define PEEKW		BYTE $0x26;		/* MOVW	rES:[rBX], rAX  */	\
+			BYTE $0x8B; BYTE $0x07
+#define POKEW		BYTE $0x26;		/* MOVW	rAX, rES:[rBX] */	\
+			BYTE $0x89; BYTE $0x07
+#define OUTPORTB(p, d)	LBI(d, rAL);		/* d -> I/O port p */	\
+			BYTE $0xE6;					\
+			BYTE $p; DELAY
+#define PUSHA		BYTE $0x60
+#define PUSHR(r)	BYTE $(0x50|r)		/* r  -> (--rSP) */
+#define PUSHS(rS)	BYTE $(0x06|((rS)<<3))	/* rS  -> (--rSP) */
+#define PUSHI(i)	BYTE $0x68; WORD $i;	/* i -> --(rSP) */
+#define POPA		BYTE $0x61
+#define POPR(r)		BYTE $(0x58|r)		/* (rSP++) -> r */
+#define POPS(rS)	BYTE $(0x07|((rS)<<3))	/* (rSP++) -> r */
+#define NOP		BYTE $0x90		/* nop */
+
+#define LGDT(gdtptr)	BYTE $0x0F;		/* LGDT */			\
+			BYTE $0x01; BYTE $0x16;					\
+			WORD $gdtptr
+
+/* operand size switch. */
+#define OPSIZE		BYTE $0x66
+
--- /dev/null
+++ b/os/boot.original/puma/8250.c
@@ -1,0 +1,312 @@
+#include "boot.h"
+
+/*
+ *  INS8250 uart
+ */
+enum
+{
+	/*
+	 *  register numbers
+	 */
+	Data=	0,		/* xmit/rcv buffer */
+	Iena=	1,		/* interrupt enable */
+	 Ircv=	(1<<0),		/*  for char rcv'd */
+	 Ixmt=	(1<<1),		/*  for xmit buffer empty */
+	 Irstat=(1<<2),		/*  for change in rcv'er status */
+	 Imstat=(1<<3),		/*  for change in modem status */
+	Istat=	2,		/* interrupt flag (read) */
+	Tctl=	2,		/* test control (write) */
+	Format=	3,		/* byte format */
+	 Bits8=	(3<<0),		/*  8 bits/byte */
+	 Stop2=	(1<<2),		/*  2 stop bits */
+	 Pena=	(1<<3),		/*  generate parity */
+	 Peven=	(1<<4),		/*  even parity */
+	 Pforce=(1<<5),		/*  force parity */
+	 Break=	(1<<6),		/*  generate a break */
+	 Dra=	(1<<7),		/*  address the divisor */
+	Mctl=	4,		/* modem control */
+	 Dtr=	(1<<0),		/*  data terminal ready */
+	 Rts=	(1<<1),		/*  request to send */
+	 Ri=	(1<<2),		/*  ring */
+	 Inton=	(1<<3),		/*  turn on interrupts */
+	 Loop=	(1<<4),		/*  loop back */
+	Lstat=	5,		/* line status */
+	 Inready=(1<<0),	/*  receive buffer full */
+	 Oerror=(1<<1),		/*  receiver overrun */
+	 Perror=(1<<2),		/*  receiver parity error */
+	 Ferror=(1<<3),		/*  rcv framing error */
+	 Outready=(1<<5),	/*  output buffer empty */
+	Mstat=	6,		/* modem status */
+	 Ctsc=	(1<<0),		/*  clear to send changed */
+	 Dsrc=	(1<<1),		/*  data set ready changed */
+	 Rire=	(1<<2),		/*  rising edge of ring indicator */
+	 Dcdc=	(1<<3),		/*  data carrier detect changed */
+	 Cts=	(1<<4),		/*  complement of clear to send line */
+	 Dsr=	(1<<5),		/*  complement of data set ready line */
+	 Ring=	(1<<6),		/*  complement of ring indicator line */
+	 Dcd=	(1<<7),		/*  complement of data carrier detect line */
+	Scratch=7,		/* scratchpad */
+	Dlsb=	0,		/* divisor lsb */
+	Dmsb=	1,		/* divisor msb */
+
+	Serial=	0,
+	Modem=	1,
+};
+
+typedef struct Uart	Uart;
+struct Uart
+{
+	int	port;
+	int	setup;
+	uchar	sticky[8];	/* sticky write register values */
+	uchar	txbusy;
+
+	Queue	*iq;
+	Queue	*oq;
+	void	(*rx)(Queue *, int);
+
+	ulong	frame;
+	ulong	overrun;
+};
+
+Uart	uart[1];
+
+static	void	uartkick(void*);
+
+
+#define UartFREQ 1843200
+
+#define uartwrreg(u,r,v)	outb((u)->port + r, (u)->sticky[r] | (v))
+#define uartrdreg(u,r)		inb((u)->port + r)
+
+/*
+ *  set the baud rate by calculating and setting the baudrate
+ *  generator constant.  This will work with fairly non-standard
+ *  baud rates.
+ */
+static void
+uartsetbaud(Uart *up, int rate)
+{
+	ulong brconst;
+
+	brconst = (UartFREQ+8*rate-1)/(16*rate);
+
+	uartwrreg(up, Format, Dra);
+	outb(up->port+Dmsb, (brconst>>8) & 0xff);
+	outb(up->port+Dlsb, brconst & 0xff);
+	uartwrreg(up, Format, 0);
+}
+
+/*
+ *  toggle DTR
+ */
+static void
+uartdtr(Uart *up, int n)
+{
+	if(n)
+		up->sticky[Mctl] |= Dtr;
+	else
+		up->sticky[Mctl] &= ~Dtr;
+	uartwrreg(up, Mctl, 0);
+}
+
+/*
+ *  toggle RTS
+ */
+static void
+uartrts(Uart *up, int n)
+{
+	if(n)
+		up->sticky[Mctl] |= Rts;
+	else
+		up->sticky[Mctl] &= ~Rts;
+	uartwrreg(up, Mctl, 0);
+}
+
+static void
+uartintr(Ureg*, void *arg)
+{
+	Uart *up;
+	int ch;
+	int s, l, loops;
+
+	up = arg;
+	for(loops = 0; loops < 1024; loops++){
+		s = uartrdreg(up, Istat);
+		switch(s){
+		case 6:	/* receiver line status */
+			l = uartrdreg(up, Lstat);
+			if(l & Ferror)
+				up->frame++;
+			if(l & Oerror)
+				up->overrun++;
+			break;
+	
+		case 4:	/* received data available */
+		case 12:
+			ch = inb(up->port+Data);
+			if(up->iq)
+				if(up->rx)
+					(*up->rx)(up->iq, ch);
+				else
+					qbputc(up->iq, ch);
+			break;
+	
+		case 2:	/* transmitter empty */
+			ch = -1;
+			if(up->oq)
+				ch = qbgetc(up->oq);
+			if(ch != -1)
+				outb(up->port+Data, ch);
+			else
+				up->txbusy = 0;
+			break;
+	
+		case 0:	/* modem status */
+			uartrdreg(up, Mstat);
+			break;
+	
+		default:
+			if(s&1)
+				return;
+			print("weird modem interrupt #%2.2ux\n", s);
+			break;
+		}
+	}
+	panic("uartintr: 0x%2.2ux\n", uartrdreg(up, Istat));
+}
+
+/*
+ *  turn on a port's interrupts.  set DTR and RTS
+ */
+static void
+uartenable(Uart *up)
+{
+	/*
+ 	 *  turn on interrupts
+	 */
+	up->sticky[Iena] = 0;
+	if(up->oq)
+		up->sticky[Iena] |= Ixmt;
+	if(up->iq)
+		up->sticky[Iena] |= Ircv|Irstat;
+	uartwrreg(up, Iena, 0);
+
+	/*
+	 *  turn on DTR and RTS
+	 */
+	uartdtr(up, 1);
+	uartrts(up, 1);
+}
+
+void
+uartspecial(int port, int baud, Queue **iq, Queue **oq, void (*rx)(Queue *, int))
+{
+	Uart *up = &uart[0];
+
+	if(up->setup)
+		return;
+	up->setup = 1;
+
+	*iq = up->iq = qopen(4*1024, 0, 0, 0);
+	*oq = up->oq = qopen(16*1024, 0, uartkick, up);
+	switch(port){
+
+	case 0:
+		up->port = 0x3F8;
+		setvec(V_COM1, uartintr, up);
+		break;
+
+	case 1:
+		up->port = 0x2F8;
+		setvec(V_COM2, uartintr, up);
+		break;
+
+	default:
+		return;
+	}
+
+	/*
+	 *  set rate to 9600 baud.
+	 *  8 bits/character.
+	 *  1 stop bit.
+	 *  interrupts enabled.
+	 */
+	uartsetbaud(up, 9600);
+	up->sticky[Format] = Bits8;
+	uartwrreg(up, Format, 0);
+	up->sticky[Mctl] |= Inton;
+	uartwrreg(up, Mctl, 0x0);
+
+	up->rx = rx;
+	uartenable(up);
+	if(baud)
+		uartsetbaud(up, baud);
+}
+
+static void
+uartputc(int c)
+{
+	Uart *up = &uart[0];
+	int i;
+
+	for(i = 0; i < 100; i++){
+		if(uartrdreg(up, Lstat) & Outready)
+			break;
+		delay(1);
+	}
+	outb(up->port+Data, c);
+}
+
+void
+uartputs(char *s, int n)
+{
+	Uart *up = &uart[0];
+	Block *b;
+	int nl;
+	char *p;
+
+	nl = 0;
+	for(p = s; p < s+n; p++)
+		if(*p == '\n')
+			nl++;
+	b = iallocb(n+nl);
+	while(n--){
+		if(*s == '\n')
+			*b->wp++ = '\r';
+		*b->wp++ = *s++;
+	}
+	qbwrite(up->oq, b);
+}
+
+/*
+ *  (re)start output
+ */
+static void
+uartkick(void *arg)
+{
+	Uart *up = arg;
+	int x, n, c;
+
+	x = splhi();
+	while(up->txbusy == 0 && (c = qbgetc(up->oq)) != -1) {
+		n = 0;
+		while((uartrdreg(up, Lstat) & Outready) == 0){
+			if(++n > 100000){
+				print("stuck serial line\n");
+				break;
+			}
+		}
+			outb(up->port + Data, c);
+	}
+	splx(x);
+}
+
+void
+uartwait(void)
+{
+	Uart *up = &uart[0];
+
+	while(up->txbusy)
+		;
+}
--- /dev/null
+++ b/os/boot.original/puma/alarm.c
@@ -1,0 +1,123 @@
+#include	"u.h"
+#include	"lib.h"
+#include	"mem.h"
+#include	"dat.h"
+#include	"fns.h"
+#include	"io.h"
+#define	MAXALARM	10
+
+Alarm	alarmtab[MAXALARM];
+
+/*
+ * Insert new into list after where
+ */
+void
+insert(List **head, List *where, List *new)
+{
+	if(where == 0){
+		new->next = *head;
+		*head = new;
+	}else{
+		new->next = where->next;
+		where->next = new;
+	}
+		
+}
+
+/*
+ * Delete old from list.  where->next is known to be old.
+ */
+void
+delete(List **head, List *where, List *old)
+{
+	if(where == 0){
+		*head = old->next;
+		return;
+	}
+	where->next = old->next;
+}
+
+Alarm*
+newalarm(void)
+{
+	int i;
+	Alarm *a;
+
+	for(i=0,a=alarmtab; i < nelem(alarmtab); i++,a++)
+		if(a->busy==0 && a->f==0){
+			a->f = 0;
+			a->arg = 0;
+			a->busy = 1;
+			return a;
+		}
+	panic("newalarm");
+	return 0;	/* not reached */
+}
+
+Alarm*
+alarm(int ms, void (*f)(Alarm*), void *arg)
+{
+	Alarm *a, *w, *pw;
+	ulong s;
+
+	if(ms < 0)
+		ms = 0;
+	s = splhi();
+	a = newalarm();
+	a->dt = MS2TK(ms);
+	a->f = f;
+	a->arg = arg;
+	pw = 0;
+	for(w=m->alarm; w; pw=w, w=w->next){
+		if(w->dt <= a->dt){
+			a->dt -= w->dt;
+			continue;
+		}
+		w->dt -= a->dt;
+		break;
+	}
+	insert(&m->alarm, pw, a);
+	splx(s);
+	return a;
+}
+
+void
+cancel(Alarm *a)
+{
+	a->f = 0;
+}
+
+void
+alarminit(void)
+{
+}
+
+#define NA 10		/* alarms per clock tick */
+void
+checkalarms(void)
+{
+	int i, n, s;
+	Alarm *a;
+	void (*f)(void*);
+	Alarm *alist[NA];
+
+	s = splhi();
+	a = m->alarm;
+	if(a){
+		for(n=0; a && a->dt<=0 && n<NA; n++){
+			alist[n] = a;
+			delete(&m->alarm, 0, a);
+			a = m->alarm;
+		}
+		if(a)
+			a->dt--;
+
+		for(i = 0; i < n; i++){
+			f = alist[i]->f;	/* avoid race with cancel */
+			if(f)
+				(*f)(alist[i]);
+			alist[i]->busy = 0;
+		}
+	}
+	splx(s);
+}
--- /dev/null
+++ b/os/boot.original/puma/armv4.h
@@ -1,0 +1,99 @@
+/*
+ * PSR
+ */
+#define PsrMusr		0x10 	/* mode */
+#define PsrMfiq		0x11 
+#define PsrMirq		0x12
+#define PsrMsvc		0x13
+#define PsrMabt		0x17
+#define PsrMund		0x1B
+#define PsrMsys		0x1F
+#define PsrMask		0x1F
+
+#define PsrDfiq		0x00000040	/* disable FIQ interrupts */
+#define PsrDirq		0x00000080	/* disable IRQ interrupts */
+
+#define PsrV		0x10000000	/* overflow */
+#define PsrC		0x20000000	/* carry/borrow/extend */
+#define PsrZ		0x40000000	/* zero */
+#define PsrN		0x80000000	/* negative/less than */
+
+/*
+ * Internal MMU coprocessor registers
+ */
+#define CpCPUID		0		/* R: */
+#define CpControl	1		/* R: */
+#define CpTTB		2		/* W: translation table base */
+#define CpDAC		3		/* W: domain access control */
+#define CpFSR		5		/* R: fault status */
+#define CpTLBflush	5		/* W: */
+#define CpFAR		6		/* R: fault address */
+#define CpTLBpurge	6		/* W: */
+#define CpCacheCtl	7		/* W: */
+
+#define CpDebug		14		/* R/W: debug registers */
+/*
+ * Coprocessors
+ */
+#define CpMMU		15
+
+/*
+ * Internal MMU coprocessor registers
+ */
+#define CpCmmu		0x00000001	/* M: MMU enable */
+#define CpCalign	0x00000002	/* A: alignment fault enable */
+#define CpCDcache	0x00000004	/* C: instruction/data cache on */
+#define CpCwb		0x00000008	/* W: write buffer turned on */
+#define CpCi32		0x00000010	/* P: 32-bit programme space */
+#define CpCd32		0x00000020	/* D: 32-bit data space */
+#define CpCbe		0x00000080	/* B: big-endian operation */
+#define CpCsystem	0x00000100	/* S: system permission */
+#define CpCrom		0x00000200	/* R: ROM permission */
+#define CpCIcache	0x00001000	/* C: Instruction Cache on */
+
+/*
+ * Debug support internal registers
+ */
+#define CpDBAR	0
+#define CpDBVR	1
+#define CpDBMR	2
+#define CpDBCR	3
+#define CpIBCR	8
+/*
+ * MMU
+ */
+/*
+ * Small pages:
+ *	L1: 12-bit index -> 4096 descriptors -> 16Kb
+ *	L2:  8-bit index ->  256 descriptors ->  1Kb
+ * Each L2 descriptor has access permissions for 4 1Kb sub-pages.
+ *
+ *	TTB + L1Tx gives address of L1 descriptor
+ *	L1 descriptor gives PTBA
+ *	PTBA + L2Tx gives address of L2 descriptor
+ *	L2 descriptor gives PBA
+ */
+#define MmuTTB(pa)	((pa) & ~0x3FFF)	/* translation table base */
+#define MmuL1x(pa)	(((pa)>>20) & 0xFFF)	/* L1 table index */
+#define MmuPTBA(pa)	((pa) & ~0x3FF)		/* page table base address */
+#define MmuL2x(pa)	(((pa)>>12) & 0xFF)	/* L2 table index */
+#define MmuPBA(pa)	((pa) & ~0xFFF)		/* page base address */
+#define MmuSBA(pa)	((pa) & ~0xFFFFF)	/* section base address */
+
+#define MmuL1page	0x011			/* descriptor is for L2 pages */
+#define MmuL1section	0x012			/* descriptor is for section */
+
+#define MmuL2invalid	0x000
+#define MmuL2large	0x001			/* large */
+#define MmuL2small	0x002			/* small */
+#define MmuWB		0x004			/* data goes through write buffer */
+#define MmuIDC		0x008			/* data placed in cache */
+
+#define MmuDAC(d)	(((d) & 0xF)<<5)	/* L1 domain */
+#define MmuAP(i, v)	((v)<<(((i)*2)+4))	/* access permissions */
+#define MmuL1AP(v)	MmuAP(3, (v))
+#define MmuL2AP(v)	MmuAP(3, (v))|MmuAP(2, (v))|MmuAP(1, (v))|MmuAP(0, (v))
+#define MmuAPsro	0			/* supervisor rw */
+#define MmuAPsrw	1			/* supervisor rw */
+#define MmuAPuro	2			/* supervisor rw + user ro */
+#define MmuAPurw	3			/* supervisor rw + user rw */
--- /dev/null
+++ b/os/boot.original/puma/boot.h
@@ -1,0 +1,12 @@
+#include <u.h>
+#include "lib.h"
+
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "ureg.h"
+
+#include "armv4.h"
+#include "puma.h"
+
--- /dev/null
+++ b/os/boot.original/puma/bootp.c
@@ -1,0 +1,502 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+#include "ip.h"
+
+uchar broadcast[Eaddrlen] = {
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+};
+
+static ushort tftpport = 5000;
+static int Id = 1;
+static Netaddr myaddr;
+static Netaddr server;
+
+typedef struct {
+	uchar	header[4];
+	uchar	data[Segsize];
+} Tftp;
+static Tftp tftpb;
+
+static void
+hnputs(uchar *ptr, ushort val)
+{
+	ptr[0] = val>>8;
+	ptr[1] = val;
+}
+
+static void
+hnputl(uchar *ptr, ulong val)
+{
+	ptr[0] = val>>24;
+	ptr[1] = val>>16;
+	ptr[2] = val>>8;
+	ptr[3] = val;
+}
+
+static ulong
+nhgetl(uchar *ptr)
+{
+	return ((ptr[0]<<24) | (ptr[1]<<16) | (ptr[2]<<8) | ptr[3]);
+}
+
+static ushort
+nhgets(uchar *ptr)
+{
+	return ((ptr[0]<<8) | ptr[1]);
+}
+
+static	short	endian	= 1;
+static	char*	aendian	= (char*)&endian;
+#define	LITTLE	*aendian
+
+static ushort
+ptcl_csum(void *a, int len)
+{
+	uchar *addr;
+	ulong t1, t2;
+	ulong losum, hisum, mdsum, x;
+
+	addr = a;
+	losum = 0;
+	hisum = 0;
+	mdsum = 0;
+
+	x = 0;
+	if((ulong)addr & 1) {
+		if(len) {
+			hisum += addr[0];
+			len--;
+			addr++;
+		}
+		x = 1;
+	}
+	while(len >= 16) {
+		t1 = *(ushort*)(addr+0);
+		t2 = *(ushort*)(addr+2);	mdsum += t1;
+		t1 = *(ushort*)(addr+4);	mdsum += t2;
+		t2 = *(ushort*)(addr+6);	mdsum += t1;
+		t1 = *(ushort*)(addr+8);	mdsum += t2;
+		t2 = *(ushort*)(addr+10);	mdsum += t1;
+		t1 = *(ushort*)(addr+12);	mdsum += t2;
+		t2 = *(ushort*)(addr+14);	mdsum += t1;
+		mdsum += t2;
+		len -= 16;
+		addr += 16;
+	}
+	while(len >= 2) {
+		mdsum += *(ushort*)addr;
+		len -= 2;
+		addr += 2;
+	}
+	if(x) {
+		if(len)
+			losum += addr[0];
+		if(LITTLE)
+			losum += mdsum;
+		else
+			hisum += mdsum;
+	} else {
+		if(len)
+			hisum += addr[0];
+		if(LITTLE)
+			hisum += mdsum;
+		else
+			losum += mdsum;
+	}
+
+	losum += hisum >> 8;
+	losum += (hisum & 0xff) << 8;
+	while(hisum = losum>>16)
+		losum = hisum + (losum & 0xffff);
+
+	return ~losum;
+}
+
+static ushort
+ip_csum(uchar *addr)
+{
+	int len;
+	ulong sum = 0;
+
+	len = (addr[0]&0xf)<<2;
+
+	while(len > 0) {
+		sum += addr[0]<<8 | addr[1] ;
+		len -= 2;
+		addr += 2;
+	}
+
+	sum = (sum & 0xffff) + (sum >> 16);
+	sum = (sum & 0xffff) + (sum >> 16);
+	return (sum^0xffff);
+}
+
+static void
+udpsend(int ctlrno, Netaddr *a, void *data, int dlen)
+{
+	Udphdr *uh;
+	Etherhdr *ip;
+	Etherpkt pkt;
+	int len, ptcllen;
+
+
+	uh = (Udphdr*)&pkt;
+
+	memset(uh, 0, sizeof(Etherpkt));
+	memmove(uh->udpcksum+sizeof(uh->udpcksum), data, dlen);
+
+	/*
+	 * UDP portion
+	 */
+	ptcllen = dlen + (UDP_HDRSIZE-UDP_PHDRSIZE);
+	uh->ttl = 0;
+	uh->udpproto = IP_UDPPROTO;
+	uh->frag[0] = 0;
+	uh->frag[1] = 0;
+	hnputs(uh->udpplen, ptcllen);
+	hnputl(uh->udpsrc, myaddr.ip);
+	hnputs(uh->udpsport, myaddr.port);
+	hnputl(uh->udpdst, a->ip);
+	hnputs(uh->udpdport, a->port);
+	hnputs(uh->udplen, ptcllen);
+	uh->udpcksum[0] = 0;
+	uh->udpcksum[1] = 0;
+	dlen = (dlen+1)&~1;
+	hnputs(uh->udpcksum, ptcl_csum(&uh->ttl, dlen+UDP_HDRSIZE));
+
+	/*
+	 * IP portion
+	 */
+	ip = (Etherhdr*)&pkt;
+	len = sizeof(Udphdr)+dlen;
+	ip->vihl = IP_VER|IP_HLEN;
+	ip->tos = 0;
+	ip->ttl = 255;
+	hnputs(ip->length, len-ETHER_HDR);
+	hnputs(ip->id, Id++);
+	ip->frag[0] = 0;
+	ip->frag[1] = 0;
+	ip->cksum[0] = 0;
+	ip->cksum[1] = 0;
+	hnputs(ip->cksum, ip_csum(&ip->vihl));
+
+	/*
+	 * Ethernet MAC portion
+	 */
+	hnputs(ip->type, ET_IP);
+	memmove(ip->d, a->ea, sizeof(ip->d));
+
+	ethertxpkt(ctlrno, &pkt, len, Timeout);
+}
+
+static void
+nak(int ctlrno, Netaddr *a, int code, char *msg, int report)
+{
+	int n;
+	char buf[128];
+
+	buf[0] = 0;
+	buf[1] = Tftp_ERROR;
+	buf[2] = 0;
+	buf[3] = code;
+	strcpy(buf+4, msg);
+	n = strlen(msg) + 4 + 1;
+	udpsend(ctlrno, a, buf, n);
+	if(report)
+		print("\ntftp: error(%d): %s\n", code, msg);
+}
+
+static int
+udprecv(int ctlrno, Netaddr *a, void *data, int dlen)
+{
+	int n, len;
+	ushort csm;
+	Udphdr *h;
+	ulong addr, timo;
+	Etherpkt pkt;
+	static int rxactive;
+
+	if(rxactive == 0)
+		timo = 1000;
+	else
+		timo = Timeout;
+	timo += TK2MS(m->ticks);
+	while(timo > TK2MS(m->ticks)){
+		n = etherrxpkt(ctlrno, &pkt, timo-TK2MS(m->ticks));
+
+		if(n <= 0)
+			continue;
+
+		h = (Udphdr*)&pkt;
+		if(nhgets(h->type) != ET_IP)
+			continue;
+
+		if(ip_csum(&h->vihl)) {
+			print("ip chksum error\n");
+			continue;
+		}
+		if(h->vihl != (IP_VER|IP_HLEN)) {
+			print("ip bad vers/hlen\n");
+			continue;
+		}
+
+		if(h->udpproto != IP_UDPPROTO)
+			continue;
+
+		h->ttl = 0;
+		len = nhgets(h->udplen);
+		hnputs(h->udpplen, len);
+
+		if(nhgets(h->udpcksum)) {
+			csm = ptcl_csum(&h->ttl, len+UDP_PHDRSIZE);
+			if(csm != 0) {
+				print("udp chksum error csum #%4lux len %d\n", csm, n);
+				break;
+			}
+		}
+
+		if(a->port != 0 && nhgets(h->udpsport) != a->port)
+			continue;
+
+		addr = nhgetl(h->udpsrc);
+		if(a->ip != Bcastip && addr != a->ip)
+			continue;
+
+		len -= UDP_HDRSIZE-UDP_PHDRSIZE;
+		if(len > dlen) {
+			print("udp: packet too big\n");
+			continue;
+		}
+
+		memmove(data, h->udpcksum+sizeof(h->udpcksum), len);
+		a->ip = addr;
+		a->port = nhgets(h->udpsport);
+		memmove(a->ea, pkt.s, sizeof(a->ea));
+
+		rxactive = 1;
+		return len;
+	}
+
+	return 0;
+}
+
+static int tftpblockno;
+
+static int
+tftpopen(int ctlrno, Netaddr *a, char *name, Tftp *tftp)
+{
+	int i, len, rlen, oport;
+	char buf[Segsize+2];
+
+	buf[0] = 0;
+	buf[1] = Tftp_READ;
+	len = sprint(buf+2, "%s", name) + 2;
+	len += sprint(buf+len+1, "octet") + 2;
+
+	oport = a->port;
+	for(i = 0; i < 5; i++){
+		a->port = oport;
+		udpsend(ctlrno, a, buf, len);
+		a->port = 0;
+		if((rlen = udprecv(ctlrno, a, tftp, sizeof(Tftp))) < sizeof(tftp->header))
+			continue;
+
+		switch((tftp->header[0]<<8)|tftp->header[1]){
+
+		case Tftp_ERROR:
+			print("tftpopen: error (%d): %s\n",
+				(tftp->header[2]<<8)|tftp->header[3], tftp->data);
+			return -1;
+
+		case Tftp_DATA:
+			tftpblockno = 1;
+			len = (tftp->header[2]<<8)|tftp->header[3];
+			if(len != tftpblockno){
+				print("tftpopen: block error: %d\n", len);
+				nak(ctlrno, a, 1, "block error", 0);
+				return -1;
+			}
+			return rlen-sizeof(tftp->header);
+		}
+	}
+
+	print("tftpopen: failed to connect to server\n");
+	return -1;
+}
+
+static int
+tftpread(int ctlrno, Netaddr *a, Tftp *tftp, int dlen)
+{
+	int blockno, len, retry;
+	uchar buf[4];
+
+	buf[0] = 0;
+	buf[1] = Tftp_ACK;
+	buf[2] = tftpblockno>>8;
+	buf[3] = tftpblockno;
+	tftpblockno++;
+
+	dlen += sizeof(tftp->header);
+
+	retry = 0;
+buggery:
+	udpsend(ctlrno, a, buf, sizeof(buf));
+
+	if((len = udprecv(ctlrno, a, tftp, dlen)) != dlen){
+		print("tftpread: %d != %d\n", len, dlen);
+		nak(ctlrno, a, 2, "short read", 0);
+		if(retry++ < 5)
+			goto buggery;
+		return -1;
+	}
+
+	blockno = (tftp->header[2]<<8)|tftp->header[3];
+	if(blockno != tftpblockno){
+		print("tftpread: block error: %d, expected %d\n", blockno, tftpblockno);
+
+		if(blockno == tftpblockno-1 && retry++ < 5)
+			goto buggery;
+		nak(ctlrno, a, 1, "block error", 0);
+
+		return -1;
+	}
+
+	return len-sizeof(tftp->header);
+}
+
+int
+bootp(int ctlrno, char *file)
+{
+	Bootp req, rep;
+	int i, dlen, segsize, text, data, bss, total;
+	uchar *ea, *addr, *p;
+	ulong entry;
+	Exec *exec;
+	char name[128], *filename, *sysname;
+
+	if((ea = etheraddr(ctlrno)) == 0){
+		print("invalid ctlrno %d\n", ctlrno);
+		return -1;
+	}
+
+	filename = 0;
+	sysname = 0;
+	if(file && *file){
+		strcpy(name, file);
+		if(filename = strchr(name, ':')){
+			if(filename != name && *(filename-1) != '\\'){
+				sysname = name;
+				*filename++ = 0;
+			}
+		}
+		else
+			filename = name;
+	}
+		
+
+	memset(&req, 0, sizeof(req));
+	req.op = Bootrequest;
+	req.htype = 1;			/* ethernet */
+	req.hlen = Eaddrlen;		/* ethernet */
+	memmove(req.chaddr, ea, Eaddrlen);
+
+	myaddr.ip = 0;
+	myaddr.port = BPportsrc;
+	memmove(myaddr.ea, ea, Eaddrlen);
+
+	for(i = 0; i < 10; i++) {
+		server.ip = Bcastip;
+		server.port = BPportdst;
+		memmove(server.ea, broadcast, sizeof(server.ea));
+		udpsend(ctlrno, &server, &req, sizeof(req));
+		if(udprecv(ctlrno, &server, &rep, sizeof(rep)) <= 0)
+			continue;
+		if(memcmp(req.chaddr, rep.chaddr, Eaddrlen))
+			continue;
+		if(rep.htype != 1 || rep.hlen != Eaddrlen)
+			continue;
+		if(sysname == 0 || strcmp(sysname, rep.sname) == 0)
+			break;
+	}
+	if(i >= 10) {
+		print("bootp timed out\n");
+		return -1;
+	}
+
+	if(filename == 0 || *filename == 0)
+		filename = rep.file;
+
+	if(rep.sname[0] != '\0')
+		 print("%s ", rep.sname);
+	print("(%d.%d.%d.%d!%d): %s\n",
+		rep.siaddr[0],
+		rep.siaddr[1],
+		rep.siaddr[2],
+		rep.siaddr[3],
+		server.port,
+		filename);
+
+	myaddr.ip = nhgetl(rep.yiaddr);
+	myaddr.port = tftpport++;
+	server.ip = nhgetl(rep.siaddr);
+	server.port = TFTPport;
+
+	if((dlen = tftpopen(ctlrno, &server, filename, &tftpb)) < 0)
+		return -1;
+
+	exec = (Exec*)(tftpb.data);
+	if(dlen < sizeof(Exec) || GLLONG(exec->magic) != E_MAGIC){
+		nak(ctlrno, &server, 0, "bad magic number", 1);
+		return -1;
+	}
+	text = GLLONG(exec->text);
+	data = GLLONG(exec->data);
+	bss = GLLONG(exec->bss);
+	total = text+data+bss;
+	entry = GLLONG(exec->entry);
+print("load@%8.8lux: ", PADDR(entry));
+	print("%d", text);
+
+	addr = (uchar*)PADDR(entry);
+	p = tftpb.data+sizeof(Exec);
+	dlen -= sizeof(Exec);
+	segsize = text;
+	for(;;){
+		if(dlen == 0){
+			if((dlen = tftpread(ctlrno, &server, &tftpb, sizeof(tftpb.data))) < 0)
+				return -1;
+			p = tftpb.data;
+		}
+		if(segsize <= dlen)
+			i = segsize;
+		else
+			i = dlen;
+		memmove(addr, p, i);
+
+		addr += i;
+		p += i;
+		segsize -= i;
+		dlen -= i;
+
+		if(segsize <= 0){
+			if(data == 0)
+				break;
+			print("+%d", data);
+			segsize = data;
+			data = 0;
+			addr = (uchar*)PGROUND((ulong)addr);
+		}
+	}
+	nak(ctlrno, &server, 3, "ok", 0);		/* tftpclose */
+	print("+%d=%d\n", bss, total);
+	print("entry: 0x%lux\n", entry);
+
+	(*(void(*)(void))(PADDR(entry)))();
+	
+	return 0;
+}
--- /dev/null
+++ b/os/boot.original/puma/cga.c
@@ -1,0 +1,92 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "io.h"
+#include "fns.h"
+
+enum {
+	Width		= 160,
+	Height		= 25,
+
+	Attr		= 7,		/* white on black */
+};
+
+#define CGASCREENBASE	((uchar*)KADDR(0xB8000))
+
+static int pos;
+static int screeninitdone;
+
+static uchar
+cgaregr(int index)
+{
+	outb(0x3D4, index);
+	return inb(0x3D4+1) & 0xFF;
+}
+
+static void
+cgaregw(int index, int data)
+{
+	outb(0x3D4, index);
+	outb(0x3D4+1, data);
+}
+
+static void
+movecursor(void)
+{
+	cgaregw(0x0E, (pos/2>>8) & 0xFF);
+	cgaregw(0x0F, pos/2 & 0xFF);
+	CGASCREENBASE[pos+1] = Attr;
+}
+
+static void
+cgascreenputc(int c)
+{
+	int i;
+
+	if(c == '\n'){
+		pos = pos/Width;
+		pos = (pos+1)*Width;
+	}
+	else if(c == '\t'){
+		i = 8 - ((pos/2)&7);
+		while(i-->0)
+			cgascreenputc(' ');
+	}
+	else if(c == '\b'){
+		if(pos >= 2)
+			pos -= 2;
+		cgascreenputc(' ');
+		pos -= 2;
+	}
+	else{
+		CGASCREENBASE[pos++] = c;
+		CGASCREENBASE[pos++] = Attr;
+	}
+	if(pos >= Width*Height){
+		memmove(CGASCREENBASE, &CGASCREENBASE[Width], Width*(Height-1));
+		memset(&CGASCREENBASE[Width*(Height-1)], 0, Width);
+		pos = Width*(Height-1);
+	}
+	movecursor();
+}
+
+void
+screeninit(void)
+{
+	if(screeninitdone == 0){
+		pos = cgaregr(0x0E)<<8;
+		pos |= cgaregr(0x0F);
+		pos *= 2;
+		screeninitdone = 1;
+	}
+}
+
+void
+cgascreenputs(char* s, int n)
+{
+	if(screeninitdone == 0)
+		screeninit();
+	while(n-- > 0)
+		cgascreenputc(*s++);
+}
--- /dev/null
+++ b/os/boot.original/puma/clock.c
@@ -1,0 +1,154 @@
+#include "boot.h"
+
+ /*
+ * Control Word Read/Write Counter (mode 0)  LSB, MSB
+ */
+#define PIT_RW_COUNTER0  0x30
+#define PIT_RW_COUNTER1  0x70
+#define PIT_RW_COUNTER2  0xB0
+#define PIT_COUNTERLATCH0	0x00
+#define PIT_COUNTERLATCH1	0x40
+#define PIT_COUNTERLATCH2	0x80
+
+#define PIT_MODE_0	0	/* Interrupt on Terminal Count */
+#define PIT_MODE_1	2	/* Hardware Retriggeable One-shot */
+#define PIT_MODE_2	4	/* Rate Generator */
+#define PIT_MODE_3	6	/* Square Wave Mode */
+#define PIT_MODE_4	8	/* Software Triggered Mode */
+#define PIT_MODE_5	10	/* Hardware Triggered Mode (Retriggeable) */
+
+/*
+ * Harris 82C54 Programmable Interval Timer
+ * On the Puma board the PIT is memory mapped
+ * starting at 0xf2000000 and with each of the 8-bit
+ * registers addressed on a consecutive 4-byte boundary.
+ */
+#undef inb
+#undef outb
+#define 	inb(port)			((*(uchar *)(port))&0xff)
+#define 	outb(port, data)	(*(uchar *)(port) = (data))
+enum
+{
+	Cnt0=	0xf2000000,		/* counter locations */
+	Cnt1=	0xf2000004,		/* ... */
+	Cnt2=	0xf2000008,		/* ... */
+	Ctlw=	0xf200000c,		/* control word register*/
+
+	/* commands */
+	Latch0=	0x00,		/* latch counter 0's value */
+	Load0=	0x30,		/* load counter 0 with 2 bytes */
+	Latch1=	0x40,		/* latch counter 1's value */
+	Load1=	0x70,		/* load counter 1 with 2 bytes */
+
+	/* modes */
+	Square=	0x06,		/* periodic square wave */
+	RateGen=	0x04,		/* rate generator */
+
+	Freq=	3686400,	/* Real clock frequency */
+};
+
+static int cpufreq = 233000000;
+static int aalcycles = 14;
+
+static void
+clockintr(Ureg*, void*)
+{
+	m->ticks++;
+	checkalarms();
+}
+
+/*
+ *  delay for l milliseconds more or less.  delayloop is set by
+ *  clockinit() to match the actual CPU speed.
+ */
+void
+delay(int l)
+{
+	l *= m->delayloop;
+	if(l <= 0)
+		l = 1;
+	aamloop(l);
+}
+
+void
+microdelay(int l)
+{
+	l *= m->delayloop;
+	l /= 1000;
+	if(l <= 0)
+		l = 1;
+	aamloop(l);
+}
+
+void
+clockinit(void)
+{
+	int x, y;	/* change in counter */
+	int loops, incr;
+
+	/*
+	 *  set vector for clock interrupts
+	 */
+	setvec(V_TIMER0, clockintr, 0);
+
+	/*
+	 *  set clock for 1/HZ seconds
+	 */
+	outb(Ctlw, Load0|Square);
+	outb(Cnt0, (Freq/HZ));	/* low byte */
+	outb(Cnt0, (Freq/HZ)>>8);	/* high byte */
+
+	/* find biggest loop that doesn't wrap */
+	incr = 16000000/(aalcycles*HZ*2);
+	x = 2000;
+	for(loops = incr; loops < 64*1024; loops += incr) {
+		/*
+		 *  measure time for the loop
+		 *	TEXT aamloop(SB), $-4
+		 *	_aamloop:
+		 *		MOVW	R0, R0
+		 *		MOVW	R0, R0
+		 *		MOVW	R0, R0
+		 *		SUB		$1, R0
+		 *		CMP		$0, R0
+		 *		BNE		_aamloop
+		 *		RET
+		 *
+		 *  the time for the loop should be independent of external
+		 *  cache and memory system since it fits in the execution
+		 *  prefetch buffer.
+		 *
+		 */
+		outb(Ctlw, Latch0);
+		x = inb(Cnt0);
+		x |= inb(Cnt0)<<8;
+		aamloop(loops);
+		outb(Ctlw, Latch0);
+		y = inb(Cnt0);
+		y |= inb(Cnt0)<<8;
+		x -= y;
+	
+		if(x < 0)
+			x += Freq/HZ;
+
+		if(x > Freq/(3*HZ))
+			break;
+	}
+
+	/*
+	 *  counter  goes at twice the frequency, once per transition,
+	 *  i.e., twice per square wave
+	 */
+	x >>= 1;
+
+	/*
+ 	 *  figure out clock frequency and a loop multiplier for delay().
+	 */
+	cpufreq = loops*((aalcycles*Freq)/x);
+	m->delayloop = (cpufreq/1000)/aalcycles;	/* AAMLOOPs for 1 ms */
+
+	/*
+	 *  add in possible .2% error and convert to MHz
+	 */
+	m->speed = (cpufreq + cpufreq/500)/1000000;
+}
--- /dev/null
+++ b/os/boot.original/puma/conf.c
@@ -1,0 +1,181 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+#include "dosfs.h"
+
+static char *confname[MAXCONF];
+static char *confval[MAXCONF];
+static int nconf;
+
+static	char*	defplan9ini =
+	"ether0=type=CS8900\r\n"
+	"vgasize=640x480x8\r\n"
+	"kernelpercent=40\r\n"
+	"console=1\r\nbaud=9600\r\n"
+;
+
+extern char **ini;
+
+char*
+getconf(char *name)
+{
+	int i;
+
+	for(i = 0; i < nconf; i++)
+		if(strcmp(confname[i], name) == 0)
+			return confval[i];
+	return 0;
+}
+
+/*
+ *  read configuration file
+ */
+int
+plan9ini(Dos *dos, char *val)
+{
+	Dosfile rc;
+	int i, n;
+	char *cp, *p, *q, *line[MAXCONF];
+
+	cp = BOOTARGS;
+	if(dos) {
+		if(dosstat(dos, *ini, &rc) <= 0)
+			return -1;
+
+		*cp = 0;
+		n = dosread(&rc, cp, BOOTARGSLEN-1);
+		if(n <= 0)
+			return -1;
+		cp[n] = 0;
+	} else if(val != nil){
+		if(memchr(val, 0, BOOTARGSLEN-1) == nil)
+			return -1;
+		print("Using flash configuration\n");
+		strcpy(cp, val);
+		n = strlen(cp);
+	}else{
+		print("Using default configuration\n");
+		strcpy(cp, defplan9ini);
+		n = strlen(cp);
+	}
+
+	/*
+	 * Make a working copy.
+	 * We could change this to pass the parsed strings
+	 * to the booted programme instead of the raw
+	 * string, then it only gets done once.
+	 */
+	memmove(cp+BOOTARGSLEN, cp, n+1);
+	cp += BOOTARGSLEN;
+
+	/*
+	 * Strip out '\r', change '\t' -> ' '.
+	 */
+	p = cp;
+	for(q = cp; *q; q++){
+		if(*q == '\r')
+			continue;
+		if(*q == '\t')
+			*q = ' ';
+		*p++ = *q;
+	}
+	*p = 0;
+	n = getcfields(cp, line, MAXCONF, "\n");
+	for(i = 0; i < n; i++){
+		cp = strchr(line[i], '=');
+		if(cp == 0)
+			continue;
+		*cp++ = 0;
+		if(cp - line[i] >= NAMELEN+1)
+			*(line[i]+NAMELEN-1) = 0;
+		confname[nconf] = line[i];
+		confval[nconf] = cp;
+		nconf++;
+	}
+	return 0;
+}
+
+static int
+parseether(uchar *to, char *from)
+{
+	char nip[4];
+	char *p;
+	int i;
+
+	p = from;
+	while(*p == ' ')
+		++p;
+	for(i = 0; i < 6; i++){
+		if(*p == 0)
+			return -1;
+		nip[0] = *p++;
+		if(*p == 0)
+			return -1;
+		nip[1] = *p++;
+		nip[2] = 0;
+		to[i] = strtoul(nip, 0, 16);
+		if(*p == ':')
+			p++;
+	}
+	return 0;
+}
+
+int
+isaconfig(char *class, int ctlrno, ISAConf *isa)
+{
+	char cc[NAMELEN], *p, *q, *r;
+	int n;
+
+	sprint(cc, "%s%d", class, ctlrno);
+	for(n = 0; n < nconf; n++){
+		if(strncmp(confname[n], cc, NAMELEN))
+			continue;
+		isa->nopt = 0;
+		p = confval[n];
+		while(*p){
+			while(*p == ' ' || *p == '\t')
+				p++;
+			if(*p == '\0')
+				break;
+			if(strncmp(p, "type=", 5) == 0){
+				p += 5;
+				for(q = isa->type; q < &isa->type[NAMELEN-1]; q++){
+					if(*p == '\0' || *p == ' ' || *p == '\t')
+						break;
+					*q = *p++;
+				}
+				*q = '\0';
+			}
+			else if(strncmp(p, "port=", 5) == 0)
+				isa->port = strtoul(p+5, &p, 0);
+			else if(strncmp(p, "irq=", 4) == 0)
+				isa->irq = strtoul(p+4, &p, 0);
+			else if(strncmp(p, "mem=", 4) == 0)
+				isa->mem = strtoul(p+4, &p, 0);
+			else if(strncmp(p, "size=", 5) == 0)
+				isa->size = strtoul(p+5, &p, 0);
+			else if(strncmp(p, "ea=", 3) == 0){
+				if(parseether(isa->ea, p+3) == -1)
+					memset(isa->ea, 0, 6);
+			}
+			else if(isa->nopt < NISAOPT){
+				r = isa->opt[isa->nopt];
+				while(*p && *p != ' ' && *p != '\t'){
+					*r++ = *p++;
+					if(r-isa->opt[isa->nopt] >= ISAOPTLEN-1)
+						break;
+				}
+				*r = '\0';
+				isa->nopt++;
+			}
+			while(*p && *p != ' ' && *p != '\t')
+				p++;
+		}
+		return 1;
+	}
+	return 0;
+}
--- /dev/null
+++ b/os/boot.original/puma/console.c
@@ -1,0 +1,181 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+static Queue*	consiq;
+static Queue*	consoq;
+
+void
+bothputs(char *s, int n)
+{
+	uartputs(s, n);
+//	cgascreenputs(s, n);
+}
+
+static void (*consputs)(char*, int) =  0;
+
+void
+consinit(void)
+{
+	char *p;
+	int baud, port;
+	static int cgadone;
+
+	if((p = getconf("console")) == 0 || strcmp(p, "lcd") == 0 || strcmp(p, "screen") == 0){
+		consiq = qopen(4*1024, 0, 0, 0);
+		consoq = qopen(8*1024, 0, 0, 0);
+		consputs = uartputs;
+		if(!cgadone) {
+			cgadone = 1;
+			//screeninit();
+			//kbdinit();
+		port = 1;
+		baud = 9600;
+		uartspecial(port, baud, &consiq, &consoq, kbdchar);
+		}
+		return;
+	}
+	if(0 || strstr(p, "lcd") == 0)
+		consputs = bothputs;
+	else
+		consputs = uartputs;
+
+	port = strtoul(p, 0, 0);
+	baud = 0;
+	if(p = getconf("baud"))
+		baud = strtoul(p, 0, 0);
+	if(baud == 0)
+		baud = 9600;
+	uartspecial(port, baud, &consiq, &consoq, kbdchar);
+}
+
+void
+kbdchar(Queue *q, int c)
+{
+	c &= 0x7F;
+	if(c == 0x10)
+		panic("^p");
+	if(q == 0) {
+		if(consiq != 0)
+			qbputc(consiq, c);
+	} else
+		qbputc(q, c);
+}
+
+static int
+getline(char *buf, int size, int dotimeout)
+{
+	int c, i=0;
+	ulong start;
+	char echo;
+
+	for (;;) {
+		start = m->ticks;
+		do{
+			if(dotimeout && ((m->ticks - start) > 5*HZ))
+				return -2;
+			c = qbgetc(consiq);
+		}while(c == -1);
+		if(c == '\r')
+			c = '\n'; 		/* turn carriage return into newline */
+		if(c == '\177')
+			c = '\010';		/* turn delete into backspace */
+		if(c == '\025')
+			echo = '\n';		/* echo ^U as a newline */
+		else
+			echo = c;
+		(*consputs)(&echo, 1);
+
+		if(c == '\010'){
+			if(i > 0)
+				i--; /* bs deletes last character */
+			continue;
+		}
+		/* a newline ends a line */
+		if (c == '\n')
+			break;
+		/* ^U wipes out the line */
+		if (c =='\025')
+			return -1;
+		if(i == size)
+			return size;
+		buf[i++] = c;
+	}
+	buf[i] = 0;
+	return i;
+}
+
+int
+getstr(char *prompt, char *buf, int size, char *def)
+{
+	int len, isdefault;
+
+	buf[0] = 0;
+	isdefault = (def && *def);
+	for (;;) {
+		if(isdefault)
+			print("%s[default==%s]: ", prompt, def);
+		else
+			print("%s: ", prompt);
+		len = getline(buf, size, isdefault);
+		switch(len){
+		case -1:
+			/* ^U typed */
+			continue;
+		case -2:
+			/* timeout, use default */
+			(*consputs)("\n", 1);
+			len = 0;
+			break;
+		default:
+			break;
+		}
+		if(len >= size){
+			print("line too long\n");
+			continue;
+		}
+		break;
+	}
+	if(len == 0 && isdefault)
+		strcpy(buf, def);
+	return 0;
+}
+
+int
+sprint(char *s, char *fmt, ...)
+{
+	return donprint(s, s+PRINTSIZE, fmt, (&fmt+1)) - s;
+}
+
+int
+print(char *fmt, ...)
+{
+	char buf[PRINTSIZE];
+	int n;
+
+	if(consputs == 0)
+		return 0;
+	n = donprint(buf, buf+sizeof(buf), fmt, (&fmt+1)) - buf;
+	(*consputs)(buf, n);
+	return n;
+}
+
+void
+panic(char *fmt, ...)
+{
+	char buf[PRINTSIZE];
+	int n;
+
+	if(consputs){
+		(*consputs)("panic: ", 7);
+		n = donprint(buf, buf+sizeof(buf), fmt, (&fmt+1)) - buf;
+		(*consputs)(buf, n);
+		(*consputs)("\n", 1);
+	}
+	spllo();
+	for(;;)
+		idle();
+}
--- /dev/null
+++ b/os/boot.original/puma/dat.h
@@ -1,0 +1,205 @@
+typedef struct Block Block;
+typedef struct Queue Queue;
+
+typedef struct List {
+	void	*next;
+} List;
+
+typedef struct {
+	int	fake;
+	int	pri;
+} Lock;
+#define	lock(x)
+#define	unlock(x)
+
+typedef struct Alarm {
+	List;
+	int	busy;
+	long	dt;
+	void	(*f)(void*);
+	void	*arg;
+} Alarm;
+
+enum {
+	Eaddrlen	= 6,
+	ETHERMINTU	= 60,		/* minimum transmit size */
+	ETHERMAXTU	= 1514,		/* maximum transmit size */
+	ETHERHDRSIZE	= 14,		/* size of an ethernet header */
+
+	MaxEther	= 2,
+};
+
+typedef struct {
+	uchar	d[Eaddrlen];
+	uchar	s[Eaddrlen];
+	uchar	type[2];
+	uchar	data[1500];
+	uchar	crc[4];
+} Etherpkt;
+
+extern uchar broadcast[Eaddrlen];
+
+enum {
+	Npart		= 20+2,		/* 8 sub partitions, disk, and partition */
+	Maxxfer		= 16*1024,	/* maximum transfer size/cmd */
+};
+
+typedef struct {
+	ulong	start;
+	ulong	end;
+	char	name[NAMELEN+1];
+} Partition;
+
+typedef struct {
+	int	online;
+	int	npart;		/* number of real partitions */
+	Partition p[Npart];
+	ulong	offset;
+	Partition *current;	/* current partition */
+
+	ulong	cap;		/* total bytes */
+	int	bytes;		/* bytes/sector */
+	int	sectors;		/* sectors/track */
+	int	heads;		/* heads/cyl */
+	long	cyl;			/* cylinders/drive */
+
+	char	lba;			/* true if drive has logical block addressing */
+	char	multi;		/* non-zero if drive does multiple block xfers */
+} Disc;
+
+enum {
+	ScsiTestunit	= 0x00,
+	ScsiExtsens	= 0x03,
+	ScsiInquiry	= 0x12,
+	ScsiModesense	= 0x1a,
+	ScsiStartunit	= 0x1B,
+	ScsiStopunit	= 0x1B,
+	ScsiGetcap	= 0x25,
+	ScsiRead	= 0x08,
+	ScsiWrite	= 0x0a,
+	ScsiExtread	= 0x28,
+	ScsiExtwrite	= 0x2a,
+
+	/* data direction */
+	ScsiIn		= 1,
+	ScsiOut		= 0,
+};
+
+typedef struct Scsibuf Scsibuf;
+typedef struct Scsibuf {
+	void*		virt;
+	void*		phys;
+	Scsibuf*	next;
+};
+
+typedef struct Scsidata {
+	uchar*		base;
+	uchar*		lim;
+	uchar*		ptr;
+} Scsidata;
+
+typedef struct Ureg Ureg;
+
+typedef struct Scsi {
+	ulong		pid;
+	ushort		target;
+	ushort		lun;
+	ushort		rflag;
+	ushort		status;
+	Scsidata 	cmd;
+	Scsidata 	data;
+	Scsibuf*	b;
+	uchar*		save;
+	uchar		cmdblk[16];
+} Scsi;
+
+typedef struct Segdesc {
+	ulong	d0;
+	ulong	d1;
+} Segdesc;
+
+typedef struct Mach {
+	ulong	ticks;		/* of the clock since boot time */
+	ulong	delayloop;
+	int		speed;		/* general system clock in MHz */
+	int		oscclk;		/* oscillator frequency in MHz */
+	void*	alarm;		/* alarms bound to this clock */
+} Mach;
+
+extern Mach *m;
+
+#define E_MAGIC		((((4*20)+0)*20)+7)
+
+typedef struct Exec Exec;
+struct	Exec
+{
+	uchar	magic[4];		/* magic number */
+	uchar	text[4];	 	/* size of text segment */
+	uchar	data[4];	 	/* size of initialized data */
+	uchar	bss[4];	  		/* size of uninitialized data */
+	uchar	syms[4];	 	/* size of symbol table */
+	uchar	entry[4];	 	/* entry point */
+	uchar	spsz[4];		/* size of sp/pc offset table */
+	uchar	pcsz[4];		/* size of pc/line number table */
+};
+
+/*
+ *  bootline passed by boot program
+ */
+#define BOOTLINE ((char *)0x18000-150)
+
+/*
+ * Where we leave configuration info.
+ */
+#define BOOTARGS	((char*)(0x18000))
+#define	BOOTARGSLEN	1024
+#define	MAXCONF		32
+
+/*
+ *  a parsed plan9.ini line
+ */
+#define ISAOPTLEN	16
+#define NISAOPT		8
+
+typedef struct  ISAConf {
+	char	type[NAMELEN];
+	ulong	port;
+	ulong	irq;
+	ulong	mem;
+	ulong	size;
+	uchar	ea[6];
+
+	int	nopt;
+	char	opt[NISAOPT][ISAOPTLEN];
+} ISAConf;
+
+typedef struct {
+	int	size;
+	ulong	addr;
+} Map;
+
+typedef struct {
+	char*	name;
+	Map*	map;
+	Map*	mapend;
+
+	Lock;
+} RMap;
+
+typedef struct PCIcfg PCIcfg;
+
+extern	uchar*	vgamem;
+
+struct Block {
+	uchar	*rp;
+	uchar	*wp;
+	uchar	*lim;
+	uchar	*data;
+	Block*	next;
+	ulong	magic;
+};
+#define	BLEN(b)	((b)->wp-(b)->rp)
+
+typedef struct QLock {
+	int	dummy;
+} QLock;
--- /dev/null
+++ b/os/boot.original/puma/div.s
@@ -1,0 +1,122 @@
+/*
+ * Div/Mod taken from the Inferno 2.0 ebsit code
+ */
+
+Q	= 0
+N	= 1
+D	= 2
+CC	= 3
+TMP	= 11
+
+TEXT	save<>(SB), 1, $0
+	MOVW	R(Q), 0(FP)
+	MOVW	R(N), 4(FP)
+	MOVW	R(D), 8(FP)
+	MOVW	R(CC), 12(FP)
+
+	MOVW	R(TMP), R(Q)		/* numerator */
+	MOVW	20(FP), R(D)		/* denominator */
+	CMP	$0, R(D)
+	BNE	s1
+	MOVW	-1(R(D)), R(TMP)	/* divide by zero fault */
+s1:	RET
+
+TEXT	rest<>(SB), 1, $0
+	MOVW	0(FP), R(Q)
+	MOVW	4(FP), R(N)
+	MOVW	8(FP), R(D)
+	MOVW	12(FP), R(CC)
+/*
+ * return to caller
+ * of rest<>
+ */
+	MOVW	0(R13), R14
+	ADD	$20, R13
+	B	(R14)
+
+TEXT	div<>(SB), 1, $0
+	MOVW	$32, R(CC)
+/*
+ * skip zeros 8-at-a-time
+ */
+e1:
+	AND.S	$(0xff<<24),R(Q), R(N)
+	BNE	e2
+	SLL	$8, R(Q)
+	SUB.S	$8, R(CC)
+	BNE	e1
+	RET
+e2:
+	MOVW	$0, R(N)
+
+loop:
+/*
+ * shift R(N||Q) left one
+ */
+	SLL	$1, R(N)
+	CMP	$0, R(Q)
+	ORR.LT	$1, R(N)
+	SLL	$1, R(Q)
+
+/*
+ * compare numerator to denominator
+ * if less, subtract and set quotent bit
+ */
+	CMP	R(D), R(N)
+	ORR.HS	$1, R(Q)
+	SUB.HS	R(D), R(N)
+	SUB.S	$1, R(CC)
+	BNE	loop
+	RET
+
+TEXT	_div(SB), 1, $16
+	BL	save<>(SB)
+	CMP	$0, R(Q)
+	BGE	d1
+	RSB	$0, R(Q), R(Q)
+	CMP	$0, R(D)
+	BGE	d2
+	RSB	$0, R(D), R(D)
+d0:
+	BL	div<>(SB)		/* none/both neg */
+	MOVW	R(Q), R(TMP)
+	B	out
+d1:
+	CMP	$0, R(D)
+	BGE	d0
+	RSB	$0, R(D), R(D)
+d2:
+	BL	div<>(SB)		/* one neg */
+	RSB	$0, R(Q), R(TMP)
+	B	out
+
+TEXT	_mod(SB), 1, $16
+	BL	save<>(SB)
+	CMP	$0, R(D)
+	RSB.LT	$0, R(D), R(D)
+	CMP	$0, R(Q)
+	BGE	m1
+	RSB	$0, R(Q), R(Q)
+	BL	div<>(SB)		/* neg numerator */
+	RSB	$0, R(N), R(TMP)
+	B	out
+m1:
+	BL	div<>(SB)		/* pos numerator */
+	MOVW	R(N), R(TMP)
+	B	out
+
+TEXT	_divu(SB), 1, $16
+	BL	save<>(SB)
+	BL	div<>(SB)
+	MOVW	R(Q), R(TMP)
+	B	out
+
+TEXT	_modu(SB), 1, $16
+	BL	save<>(SB)
+	BL	div<>(SB)
+	MOVW	R(N), R(TMP)
+	B	out
+
+out:
+	BL	rest<>(SB)
+	B	out
--- /dev/null
+++ b/os/boot.original/puma/donprint.c
@@ -1,0 +1,332 @@
+#include	"u.h"
+#include	"lib.h"
+
+#define	PTR	sizeof(char*)
+#define	SHORT	sizeof(int)
+#define	INT	sizeof(int)
+#define	LONG	sizeof(long)
+#define	IDIGIT	30
+#define	MAXCON	30
+
+#define	FLONG	(1<<0)
+#define	FSHORT	(1<<1)
+#define	FUNSIGN	(1<<2)
+
+typedef struct Op	Op;
+struct Op
+{
+	char	*p;
+	char	*ep;
+	void	*argp;
+	int	f1;
+	int	f2;
+	int	f3;
+};
+
+static	int	noconv(Op*);
+static	int	cconv(Op*);
+static	int	dconv(Op*);
+static	int	hconv(Op*);
+static	int	lconv(Op*);
+static	int	oconv(Op*);
+static	int	sconv(Op*);
+static	int	uconv(Op*);
+static	int	xconv(Op*);
+static	int	Xconv(Op*);
+static	int	percent(Op*);
+
+static
+int	(*fmtconv[MAXCON])(Op*) =
+{
+	noconv,
+	cconv, dconv, hconv, lconv,
+	oconv, sconv, uconv, xconv,
+	Xconv, percent,
+};
+static
+char	fmtindex[128] =
+{
+	['c'] 1,
+	['d'] 2,
+	['h'] 3,
+	['l'] 4,
+	['o'] 5,
+	['s'] 6,
+	['u'] 7,
+	['x'] 8,
+	['X'] 9,
+	['%'] 10,
+};
+
+static	int	convcount  = { 11 };
+static	int	ucase;
+
+static void
+PUT(Op *o, int c)
+{
+	static int pos;
+	int opos;
+
+	if(c == '\t'){
+		opos = pos;
+		pos = (opos+8) & ~7;
+		while(opos++ < pos && o->p < o->ep)
+			*o->p++ = ' ';
+		return;
+	}
+	if(o->p < o->ep){
+		*o->p++ = c;
+		pos++;
+	}
+	if(c == '\n')
+		pos = 0;
+}
+
+int
+fmtinstall(char c, int (*f)(Op*))
+{
+
+	c &= 0177;
+	if(fmtindex[c] == 0) {
+		if(convcount >= MAXCON)
+			return 1;
+		fmtindex[c] = convcount++;
+	}
+	fmtconv[fmtindex[c]] = f;
+	return 0;
+}
+
+char*
+donprint(char *p, char *ep, char *fmt, void *argp)
+{
+	int sf1, c;
+	Op o;
+
+	o.p = p;
+	o.ep = ep;
+	o.argp = argp;
+
+loop:
+	c = *fmt++;
+	if(c != '%') {
+		if(c == 0) {
+			if(o.p < o.ep)
+				*o.p = 0;
+			return o.p;
+		}
+		PUT(&o, c);
+		goto loop;
+	}
+	o.f1 = 0;
+	o.f2 = -1;
+	o.f3 = 0;
+	c = *fmt++;
+	sf1 = 0;
+	if(c == '-') {
+		sf1 = 1;
+		c = *fmt++;
+	}
+	while(c >= '0' && c <= '9') {
+		o.f1 = o.f1*10 + c-'0';
+		c = *fmt++;
+	}
+	if(sf1)
+		o.f1 = -o.f1;
+	if(c != '.')
+		goto l1;
+	c = *fmt++;
+	while(c >= '0' && c <= '9') {
+		if(o.f2 < 0)
+			o.f2 = 0;
+		o.f2 = o.f2*10 + c-'0';
+		c = *fmt++;
+	}
+l1:
+	if(c == 0)
+		fmt--;
+	c = (*fmtconv[fmtindex[c&0177]])(&o);
+	if(c < 0) {
+		o.f3 |= -c;
+		c = *fmt++;
+		goto l1;
+	}
+	o.argp = (char*)o.argp + c;
+	goto loop;
+}
+
+void
+strconv(char *o, Op *op, int f1, int f2)
+{
+	int n, c;
+	char *p;
+
+	n = strlen(o);
+	if(f1 >= 0)
+		while(n < f1) {
+			PUT(op, ' ');
+			n++;
+		}
+	for(p=o; c = *p++;)
+		if(f2 != 0) {
+			PUT(op, c);
+			f2--;
+		}
+	if(f1 < 0) {
+		f1 = -f1;
+		while(n < f1) {
+			PUT(op, ' ');
+			n++;
+		}
+	}
+}
+
+int
+numbconv(Op *op, int base)
+{
+	char b[IDIGIT];
+	int i, f, n, r;
+	long v;
+	short h;
+
+	f = 0;
+	switch(op->f3 & (FLONG|FSHORT|FUNSIGN)) {
+	case FLONG:
+		v = *(long*)op->argp;
+		r = LONG;
+		break;
+
+	case FUNSIGN|FLONG:
+		v = *(ulong*)op->argp;
+		r = LONG;
+		break;
+
+	case FSHORT:
+		h = *(int*)op->argp;
+		v = h;
+		r = SHORT;
+		break;
+
+	case FUNSIGN|FSHORT:
+		h = *(int*)op->argp;
+		v = (ushort)h;
+		r = SHORT;
+		break;
+
+	default:
+		v = *(int*)op->argp;
+		r = INT;
+		break;
+
+	case FUNSIGN:
+		v = *(unsigned*)op->argp;
+		r = INT;
+		break;
+	}
+	if(!(op->f3 & FUNSIGN) && v < 0) {
+		v = -v;
+		f = 1;
+	}
+	b[IDIGIT-1] = 0;
+	for(i = IDIGIT-2;; i--) {
+		n = (ulong)v % base;
+		n += '0';
+		if(n > '9'){
+			n += 'a' - ('9'+1);
+			if(ucase)
+				n += 'A'-'a';
+		}
+		b[i] = n;
+		if(i < 2)
+			break;
+		v = (ulong)v / base;
+		if(op->f2 >= 0 && i >= IDIGIT-op->f2)
+			continue;
+		if(v <= 0)
+			break;
+	}
+	if(f)
+		b[--i] = '-';
+	strconv(b+i, op, op->f1, -1);
+	return r;
+}
+
+static	int
+noconv(Op *op)
+{
+
+	strconv("***", op, 0, -1);
+	return 0;
+}
+
+static	int
+cconv(Op *op)
+{
+	char b[2];
+
+	b[0] = *(int*)op->argp;
+	b[1] = 0;
+	strconv(b, op, op->f1, -1);
+	return INT;
+}
+
+static	int
+dconv(Op *op)
+{
+	return numbconv(op, 10);
+}
+
+static	int
+hconv(Op*)
+{
+	return -FSHORT;
+}
+
+static	int
+lconv(Op*)
+{
+	return -FLONG;
+}
+
+static	int
+oconv(Op *op)
+{
+	return numbconv(op, 8);
+}
+
+static	int
+sconv(Op *op)
+{
+	strconv(*(char**)op->argp, op, op->f1, op->f2);
+	return PTR;
+}
+
+static	int
+uconv(Op*)
+{
+	return -FUNSIGN;
+}
+
+static	int
+xconv(Op *op)
+{
+	return numbconv(op, 16);
+}
+
+static	int
+Xconv(Op *op)
+{
+	int r;
+
+	ucase = 1;
+	r = numbconv(op, 16);
+	ucase = 0;
+	return r;
+}
+
+static	int
+percent(Op *op)
+{
+
+	PUT(op, '%');
+	return 0;
+}
--- /dev/null
+++ b/os/boot.original/puma/dosboot.c
@@ -1,0 +1,614 @@
+#include	"u.h"
+#include	"lib.h"
+#include	"mem.h"
+#include	"dat.h"
+#include	"fns.h"
+#include	"dosfs.h"
+
+extern char *premature;
+
+/*
+ *  predeclared
+ */
+static void	bootdump(Dosboot*);
+static void	setname(Dosfile*, char*);
+long		dosreadseg(Dosfile*, long, long);
+
+/*
+ *  debugging
+ */
+#define chatty	1
+#define chat	if(chatty)print
+
+/*
+ *  block io buffers
+ */
+enum
+{
+	Nbio=	16,
+};
+typedef struct	Clustbuf	Clustbuf;
+struct Clustbuf
+{
+	int	age;
+	long	sector;
+	uchar	*iobuf;
+	Dos	*dos;
+	int	size;
+};
+Clustbuf	bio[Nbio];
+
+/*
+ *  get an io block from an io buffer
+ */
+Clustbuf*
+getclust(Dos *dos, long sector)
+{
+	Clustbuf *p, *oldest;
+	int size;
+
+	chat("getclust @ %d\n", sector);
+
+	/*
+	 *  if we have it, just return it
+	 */
+	for(p = bio; p < &bio[Nbio]; p++){
+		if(sector == p->sector && dos == p->dos){
+			p->age = m->ticks;
+			chat("getclust %d in cache\n", sector);
+			return p;
+		}
+	}
+
+	/*
+	 *  otherwise, reuse the oldest entry
+	 */
+	oldest = bio;
+	for(p = &bio[1]; p < &bio[Nbio]; p++){
+		if(p->age <= oldest->age)
+			oldest = p;
+	}
+	p = oldest;
+
+	/*
+	 *  make sure the buffer is big enough
+	 */
+	size = dos->clustsize*dos->sectsize;
+	if(p->iobuf==0 || p->size < size)
+		p->iobuf = ialloc(size, 0);
+	p->size = size;
+
+	/*
+	 *  read in the cluster
+	 */
+	chat("getclust addr %d\n", (sector+dos->start)*dos->sectsize);
+	if((*dos->seek)(dos->dev, (sector+dos->start)*dos->sectsize) < 0){
+		chat("can't seek block\n");
+		return 0;
+	}
+	if((*dos->read)(dos->dev, p->iobuf, size) != size){
+		chat("can't read block\n");
+		return 0;
+	}
+
+	p->age = m->ticks;
+	p->dos = dos;
+	p->sector = sector;
+	chat("getclust %d read\n", sector);
+	return p;
+}
+
+/*
+ *  walk the fat one level ( n is a current cluster number ).
+ *  return the new cluster number or -1 if no more.
+ */
+static long
+fatwalk(Dos *dos, int n)
+{
+	ulong k, sect;
+	Clustbuf *p;
+	int o;
+
+	chat("fatwalk %d\n", n);
+
+	if(n < 2 || n >= dos->fatclusters)
+		return -1;
+
+	switch(dos->fatbits){
+	case 12:
+		k = (3*n)/2; break;
+	case 16:
+		k = 2*n; break;
+	default:
+		return -1;
+	}
+	if(k >= dos->fatsize*dos->sectsize)
+		panic("getfat");
+
+	sect = (k/(dos->sectsize*dos->clustsize))*dos->clustsize + dos->fataddr;
+	o = k%(dos->sectsize*dos->clustsize);
+	p = getclust(dos, sect);
+	k = p->iobuf[o++];
+	if(o >= dos->sectsize*dos->clustsize){
+		p = getclust(dos, sect+dos->clustsize);
+		o = 0;
+	}
+	k |= p->iobuf[o]<<8;
+	if(dos->fatbits == 12){
+		if(n&1)
+			k >>= 4;
+		else
+			k &= 0xfff;
+		if(k >= 0xff8)
+			k |= 0xf000;
+	}
+	k = k < 0xfff8 ? k : -1;
+	chat("fatwalk %d -> %d\n", n, k);
+	return k;
+}
+
+/*
+ *  map a file's logical cluster address to a physical sector address
+ */
+static long
+fileaddr(Dosfile *fp, long ltarget)
+{
+	Dos *dos = fp->dos;
+	long l;
+	long p;
+
+	chat("fileaddr %8.8s %d\n", fp->name, ltarget);
+	/*
+	 *  root directory is contiguous and easy
+	 */
+	if(fp->pstart == 0){
+		if(ltarget*dos->sectsize*dos->clustsize >= dos->rootsize*sizeof(Dosdir))
+			return -1;
+		l = dos->rootaddr + ltarget*dos->clustsize;
+		chat("fileaddr %d -> %d\n", ltarget, l);
+		return l;
+	}
+
+	/*
+	 *  anything else requires a walk through the fat
+	 */
+	if(ltarget >= fp->lcurrent && fp->pcurrent){
+		/* start at the currrent point */
+		l = fp->lcurrent;
+		p = fp->pcurrent;
+	} else {
+		/* go back to the beginning */
+		l = 0;
+		p = fp->pstart;
+	}
+	while(l != ltarget){
+		/* walk the fat */
+		p = fatwalk(dos, p);
+		if(p < 0)
+			return -1;
+		l++;
+	}
+	fp->lcurrent = l;
+	fp->pcurrent = p;
+
+	/*
+	 *  clusters start at 2 instead of 0 (why? - presotto)
+	 */
+	l =  dos->dataaddr + (p-2)*dos->clustsize;
+	chat("fileaddr %d -> %d\n", ltarget, l);
+	return l;
+}
+
+/*
+ *  read from a dos file
+ */
+long
+dosread(Dosfile *fp, void *a, long n)
+{
+	long addr;
+	long rv;
+	int i;
+	int off;
+	Clustbuf *p;
+	uchar *from, *to;
+
+	if((fp->attr & DDIR) == 0){
+		if(fp->offset >= fp->length)
+			return 0;
+		if(fp->offset+n > fp->length)
+			n = fp->length - fp->offset;
+	}
+
+	to = a;
+	for(rv = 0; rv < n; rv+=i){
+		/*
+		 *  read the cluster
+		 */
+		addr = fileaddr(fp, fp->offset/fp->dos->clustbytes);
+		if(addr < 0)
+			return -1;
+		p = getclust(fp->dos, addr);
+		if(p == 0)
+			return -1;
+
+		/*
+		 *  copy the bytes we need
+		 */
+		off = fp->offset % fp->dos->clustbytes;
+		from = &p->iobuf[off];
+		i = n - rv;
+		if(i > fp->dos->clustbytes - off)
+			i = fp->dos->clustbytes - off;
+		memmove(to, from, i);
+		to += i;
+		fp->offset += i;
+	}
+
+	return rv;
+}
+
+/*
+ *  walk a directory returns
+ * 	-1 if something went wrong
+ *	 0 if not found
+ *	 1 if found
+ */
+int
+doswalk(Dosfile *file, char *name)
+{
+	Dosdir d;
+	long n;
+
+	if((file->attr & DDIR) == 0){
+		chat("walking non-directory!\n");
+		return -1;
+	}
+
+	setname(file, name);
+
+	file->offset = 0;	/* start at the beginning */
+	while((n = dosread(file, &d, sizeof(d))) == sizeof(d)){
+		chat("comparing to %8.8s.%3.3s\n", d.name, d.ext);
+		if(memcmp(file->name, d.name, sizeof(d.name)) != 0)
+			continue;
+		if(memcmp(file->ext, d.ext, sizeof(d.ext)) != 0)
+			continue;
+		if(d.attr & DVLABEL){
+			chat("%8.8s.%3.3s is a LABEL\n", d.name, d.ext);
+			continue;
+		}
+		file->attr = d.attr;
+		file->pstart = GSHORT(d.start);
+		file->length = GLONG(d.length);
+		file->pcurrent = 0;
+		file->lcurrent = 0;
+		file->offset = 0;
+		return 1;
+	}
+	return n >= 0 ? 0 : -1;
+}
+
+
+/*
+ *  instructions that boot blocks can start with
+ */
+#define	JMPSHORT	0xeb
+#define JMPNEAR		0xe9
+
+/*
+ *  read dos file system properties
+ */
+int
+dosinit(Dos *dos, int start, int ishard)
+{
+	Dosboot *b;
+	int i;
+	Clustbuf *p;
+	Dospart *dp;
+	ulong mbroffset, offset;
+
+	/* defaults till we know better */
+	dos->start = start;
+	dos->sectsize = 512;
+	dos->clustsize = 1;
+	mbroffset = 0;
+
+dmddo:
+	/* get first sector */
+	p = getclust(dos, mbroffset);
+	if(p == 0){
+		chat("can't read boot block\n");
+		return -1;
+	}
+
+	/*
+	 * If it's a hard disc then look for an MBR and pick either an
+	 * active partition or the FAT with the lowest starting LBA.
+	 * Things are tricky because we could be pointing to, amongst others:
+	 *	1) a floppy BPB;
+	 *	2) a hard disc MBR;
+	 *	3) a hard disc extended partition table;
+	 *	4) a logical drive on a hard disc;
+	 *	5) a disc-manager boot block.
+	 * They all have the same magic at the end of the block.
+	 */
+	if(p->iobuf[0x1FE] != 0x55 || p->iobuf[0x1FF] != 0xAA) {
+		chat("not DOS\n");
+		return -1;
+	}
+	p->dos = 0;
+	b = (Dosboot *)p->iobuf;
+	if(ishard && b->mediadesc != 0xF8){
+		dp = (Dospart*)&p->iobuf[0x1BE];
+		offset = 0xFFFFFFFF;
+		for(i = 0; i < 4; i++, dp++){
+			if(dp->type == DMDDO){
+				mbroffset = 63;
+				goto dmddo;
+			}
+			if(dp->type != FAT12 && dp->type != FAT16 && dp->type != FATHUGE)
+				continue;
+			if(dp->flag & 0x80){
+				offset = GLONG(dp->start);
+				break;
+			}
+			if(GLONG(dp->start) < offset)
+				offset = GLONG(dp->start);
+		}
+		if(i != 4 || offset != 0xFFFFFFFF){
+			dos->start = mbroffset+offset;
+			p = getclust(dos, 0);
+			if(p == 0 || p->iobuf[0x1FE] != 0x55 || p->iobuf[0x1FF] != 0xAA)
+				return -1;
+		}
+		p->dos = 0;
+	}
+
+	b = (Dosboot *)p->iobuf;
+	if(b->magic[0] != JMPNEAR && (b->magic[0] != JMPSHORT || b->magic[2] != 0x90)){
+		chat("no dos file system\n");
+		return -1;
+	}
+
+	if(chatty)
+		bootdump(b);
+
+	/*
+	 *  determine the systems' wondersous properties
+	 */
+	dos->sectsize = GSHORT(b->sectsize);
+	dos->clustsize = b->clustsize;
+	dos->clustbytes = dos->sectsize*dos->clustsize;
+	dos->nresrv = GSHORT(b->nresrv);
+	dos->nfats = b->nfats;
+	dos->rootsize = GSHORT(b->rootsize);
+	dos->volsize = GSHORT(b->volsize);
+	if(dos->volsize == 0)
+		dos->volsize = GLONG(b->bigvolsize);
+	dos->mediadesc = b->mediadesc;
+	dos->fatsize = GSHORT(b->fatsize);
+	dos->fataddr = dos->nresrv;
+	dos->rootaddr = dos->fataddr + dos->nfats*dos->fatsize;
+	i = dos->rootsize*sizeof(Dosdir) + dos->sectsize - 1;
+	i = i/dos->sectsize;
+	dos->dataaddr = dos->rootaddr + i;
+	dos->fatclusters = 2+(dos->volsize - dos->dataaddr)/dos->clustsize;
+	if(dos->fatclusters < 4087)
+		dos->fatbits = 12;
+	else
+		dos->fatbits = 16;
+	dos->freeptr = 2;
+
+	/*
+	 *  set up the root
+	 */
+	dos->root.dos = dos;
+	dos->root.pstart = 0;
+	dos->root.pcurrent = dos->root.lcurrent = 0;
+	dos->root.offset = 0;
+	dos->root.attr = DDIR;
+	dos->root.length = dos->rootsize*sizeof(Dosdir);
+
+	return 0;
+}
+
+static void
+bootdump(Dosboot *b)
+{
+	if(chatty == 0)
+		return;
+	print("magic: 0x%2.2x 0x%2.2x 0x%2.2x\n",
+		b->magic[0], b->magic[1], b->magic[2]);
+	print("version: \"%8.8s\"\n", b->version);
+	print("sectsize: %d\n", GSHORT(b->sectsize));
+	print("allocsize: %d\n", b->clustsize);
+	print("nresrv: %d\n", GSHORT(b->nresrv));
+	print("nfats: %d\n", b->nfats);
+	print("rootsize: %d\n", GSHORT(b->rootsize));
+	print("volsize: %d\n", GSHORT(b->volsize));
+	print("mediadesc: 0x%2.2x\n", b->mediadesc);
+	print("fatsize: %d\n", GSHORT(b->fatsize));
+	print("trksize: %d\n", GSHORT(b->trksize));
+	print("nheads: %d\n", GSHORT(b->nheads));
+	print("nhidden: %d\n", GLONG(b->nhidden));
+	print("bigvolsize: %d\n", GLONG(b->bigvolsize));
+	print("driveno: %d\n", b->driveno);
+	print("reserved0: 0x%2.2x\n", b->reserved0);
+	print("bootsig: 0x%2.2x\n", b->bootsig);
+	print("volid: 0x%8.8x\n", GLONG(b->volid));
+	print("label: \"%11.11s\"\n", b->label);
+}
+
+/*
+ *  grab next element from a path, return the pointer to unprocessed portion of
+ *  path.
+ */
+static char *
+nextelem(char *path, char *elem)
+{
+	int i;
+
+	while(*path == '/')
+		path++;
+	if(*path==0 || *path==' ')
+		return 0;
+	for(i=0; *path!='\0' && *path!='/' && *path!=' '; i++){
+		if(i==28){
+			print("name component too long\n");
+			return 0;
+		}
+		*elem++ = *path++;
+	}
+	*elem = '\0';
+	return path;
+}
+
+int
+dosstat(Dos *dos, char *path, Dosfile *f)
+{
+	char element[NAMELEN];
+
+	*f = dos->root;
+	while(path = nextelem(path, element)){
+		switch(doswalk(f, element)){
+		case -1:
+			return -1;
+		case 0:
+			return 0;
+		}
+	}
+	return 1;
+}
+
+/*
+ *  boot
+ */
+int
+dosboot(Dos *dos, char *path)
+{
+	Dosfile file;
+	long n;
+	long addr;
+	Exec *ep;
+	void (*b)(void);
+
+	switch(dosstat(dos, path, &file)){
+
+	case -1:
+		print("error walking to %s\n", path);
+		return -1;
+	case 0:
+		print("%s not found\n", path);
+		return -1;
+	case 1:
+		print("found %8.8s.%3.3s attr 0x%ux start 0x%lux len %d\n", file.name,
+			file.ext, file.attr, file.pstart, file.length);
+		break;
+	}
+
+	/*
+	 *  read header
+	 */
+	ep = (Exec*)ialloc(sizeof(Exec), 0);
+	n = sizeof(Exec);
+	if(dosreadseg(&file, n, (ulong) ep) != n){
+		print(premature);
+		return -1;
+	}
+	if(GLLONG(ep->magic) != E_MAGIC){
+		print("bad magic 0x%lux not a plan 9 executable!\n", GLLONG(ep->magic));
+		return -1;
+	}
+
+	/*
+	 *  read text
+	 */
+	addr = PADDR(GLLONG(ep->entry));
+	n = GLLONG(ep->text);
+	print("+%d", n);
+	if(dosreadseg(&file, n, addr) != n){
+		print(premature);
+		return -1;
+	}
+
+	/*
+	 *  read data (starts at first page after kernel)
+	 */
+	addr = PGROUND(addr+n);
+	n = GLLONG(ep->data);
+	print("+%d", n);
+	if(dosreadseg(&file, n, addr) != n){
+		print(premature);
+		return -1;
+	}
+
+	/*
+	 *  bss and entry point
+	 */
+	print("+%d\nstart at 0x%lux\n", GLLONG(ep->bss), GLLONG(ep->entry));
+
+	/*
+	 *  Go to new code. It's up to the program to get its PC relocated to
+	 *  the right place.
+	 */
+	b = (void (*)(void))(PADDR(GLLONG(ep->entry)));
+	(*b)();
+	return 0;
+}
+
+/*
+ *  read in a segment
+ */
+long
+dosreadseg(Dosfile *fp, long len, long addr)
+{
+	char *a;
+	long n, sofar;
+
+	a = (char *)addr;
+	for(sofar = 0; sofar < len; sofar += n){
+		n = 8*1024;
+		if(len - sofar < n)
+			n = len - sofar;
+		n = dosread(fp, a + sofar, n);
+		if(n <= 0)
+			break;
+		print(".");
+	}
+	return sofar;
+}
+
+/*
+ *  set up a dos file name
+ */
+static void
+setname(Dosfile *fp, char *from)
+{
+	char *to;
+
+	to = fp->name;
+	for(; *from && to-fp->name < 8; from++, to++){
+		if(*from == '.'){
+			from++;
+			break;
+		}
+		if(*from >= 'a' && *from <= 'z')
+			*to = *from + 'A' - 'a';
+		else
+			*to = *from;
+	}
+	while(to - fp->name < 8)
+		*to++ = ' ';
+	
+	to = fp->ext;
+	for(; *from && to-fp->ext < 3; from++, to++){
+		if(*from >= 'a' && *from <= 'z')
+			*to = *from + 'A' - 'a';
+		else
+			*to = *from;
+	}
+	while(to-fp->ext < 3)
+		*to++ = ' ';
+
+	chat("name is %8.8s %3.3s\n", fp->name, fp->ext);
+}
--- /dev/null
+++ b/os/boot.original/puma/dosfs.h
@@ -1,0 +1,110 @@
+typedef struct Dosboot	Dosboot;
+typedef struct Dos	Dos;
+typedef struct Dosdir	Dosdir;
+typedef struct Dosfile	Dosfile;
+typedef struct Dospart	Dospart;
+
+struct Dospart
+{
+	uchar flag;		/* active flag */
+	uchar shead;		/* starting head */
+	uchar scs[2];		/* starting cylinder/sector */
+	uchar type;		/* partition type */
+	uchar ehead;		/* ending head */
+	uchar ecs[2];		/* ending cylinder/sector */
+	uchar start[4];		/* starting sector */
+	uchar len[4];		/* length in sectors */
+};
+
+#define FAT12	0x01
+#define FAT16	0x04
+#define FATHUGE	0x06
+#define DMDDO	0x54
+
+struct Dosboot{
+	uchar	magic[3];
+	uchar	version[8];
+	uchar	sectsize[2];
+	uchar	clustsize;
+	uchar	nresrv[2];
+	uchar	nfats;
+	uchar	rootsize[2];
+	uchar	volsize[2];
+	uchar	mediadesc;
+	uchar	fatsize[2];
+	uchar	trksize[2];
+	uchar	nheads[2];
+	uchar	nhidden[4];
+	uchar	bigvolsize[4];
+	uchar	driveno;
+	uchar	reserved0;
+	uchar	bootsig;
+	uchar	volid[4];
+	uchar	label[11];
+	uchar	reserved1[8];
+};
+
+struct Dosfile{
+	Dos	*dos;		/* owning dos file system */
+	char	name[8];
+	char	ext[3];
+	uchar	attr;
+	long	length;
+	long	pstart;		/* physical start cluster address */
+	long	pcurrent;	/* physical current cluster address */
+	long	lcurrent;	/* logical current cluster address */
+	long	offset;
+};
+
+struct Dos{
+	int	dev;				/* device id */
+	long	(*read)(int, void*, long);	/* read routine */
+	long	(*seek)(int, long);		/* seek routine */
+
+	int	start;		/* start of file system */
+	int	sectsize;	/* in bytes */
+	int	clustsize;	/* in sectors */
+	int	clustbytes;	/* in bytes */
+	int	nresrv;		/* sectors */
+	int	nfats;		/* usually 2 */
+	int	rootsize;	/* number of entries */
+	int	volsize;	/* in sectors */
+	int	mediadesc;
+	int	fatsize;	/* in sectors */
+	int	fatclusters;
+	int	fatbits;	/* 12 or 16 */
+	long	fataddr;	/* sector number */
+	long	rootaddr;
+	long	dataaddr;
+	long	freeptr;
+
+	Dosfile	root;
+};
+
+struct Dosdir{
+	uchar	name[8];
+	uchar	ext[3];
+	uchar	attr;
+	uchar	reserved[10];
+	uchar	time[2];
+	uchar	date[2];
+	uchar	start[2];
+	uchar	length[4];
+};
+
+#define	DRONLY	0x01
+#define	DHIDDEN	0x02
+#define	DSYSTEM	0x04
+#define	DVLABEL	0x08
+#define	DDIR	0x10
+#define	DARCH	0x20
+
+extern int chatty;
+
+extern int dosboot(Dos*, char*);
+extern int dosinit(Dos*, int, int);
+extern long dosread(Dosfile*, void*, long);
+extern int dosstat(Dos*, char*, Dosfile*);
+extern int doswalk(Dosfile*, char*);
+
+extern int plan9ini(Dos*, char*);
--- /dev/null
+++ b/os/boot.original/puma/ebsit.trap.c
@@ -1,0 +1,206 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "ebsit.h"
+#include "dat.h"
+#include "fns.h"
+
+#include "ureg.h"
+
+int inpanic;
+
+#define CSR ((ushort *) 0x2000000)
+ 
+
+typedef struct Irqctlr {
+	uint	addr;
+  	uint	enabled;
+	struct {
+		void	(*r)(Ureg*, void*);
+		void 	*a;
+	} h[16];
+} Irqctlr;
+
+static Irqctlr irqctlr;  
+
+void 
+csrset( int bit )
+{
+static ushort *csr_val = 0x8c;
+
+	*csr_val ^= (1 << bit);
+	putcsr(*csr_val);
+}
+
+void
+intrinit( void )
+{
+int offset;
+ulong op;
+
+
+	irqctlr.addr = 1;
+	irqctlr.enabled = 0;
+ 
+	/* Reset Exception */
+	offset = ((((ulong) _vsvccall) - 0x0)-8) >> 2;
+	op = ( 0xea << 24 ) | offset;
+	*((ulong *) 0x0) = op;
+
+	/* Undefined Instruction Exception */
+	offset = ((((ulong) _vundcall) - 0x4)-8) >> 2;
+	op = ( 0xea << 24 ) | offset;
+	*((ulong *) 0x4) = op;
+
+	/* SWI Exception */
+	offset = ((((ulong) _vsvccall) - 0x8)-8) >> 2;
+	op = ( 0xea << 24 ) | offset;
+	*((ulong *) 0x8) = op;
+
+	/* Prefetch Abort Exception */
+	offset = ((((ulong) _vpabcall) - 0xc)-8) >> 2;
+	op = ( 0xea << 24 ) | offset;
+	*((ulong *) 0xc) = op;
+
+	/* Data Abort Exception */
+	offset = ((((ulong) _vdabcall) - 0x10)-8) >> 2;
+	op = ( 0xea << 24 ) | offset;
+	*((ulong *) 0x10) = op;
+
+	/* IRQ Exception */
+	offset = ((((ulong) _virqcall) - 0x18)-8) >> 2;
+	op = ( 0xea << 24 ) | offset;
+	*((ulong *) 0x18) = op;
+
+
+}
+
+void
+intrenable(uint addr, int bit, void (*r)(Ureg*, void*), void* a)
+{
+	int i;
+	USED(addr);
+	for(i = 0; i < 16; i++)
+		{
+		if((bit & (1<<i)) == 0)
+			continue;
+		irqctlr.h[i].r = r;
+		irqctlr.h[i].a = a;
+		irqctlr.enabled |= (1<<i); 
+		if (i < 7) 
+			csrset(i);
+		}
+	return;
+}
+
+int lucifer;					/* Global to store the last CSR (eric) */
+
+static void
+interrupt(Ureg* ureg)
+{
+	int i, mask;
+
+ 		mask = *CSR;
+		lucifer = mask;			/* eric */
+		if(irqctlr.enabled == 0){
+		
+			return;
+ 			}
+		for(i = 0; i < 16; i++)
+			{
+
+			if((irqctlr.enabled & (1<<i)) == 0)
+				continue;
+			if(( mask & (1 << i)) == 0)
+				continue;
+			if (!irqctlr.h[i].r)
+				continue;
+			(irqctlr.h[i].r)(ureg, irqctlr.h[i].a);
+			mask &= ~(1 << i);
+			}
+
+		if ((mask) && (mask < 0x90))		/* ignore non-maskable interrupts */
+			{
+			print("unknown or unhandled interrupt\n");
+			panic("unknown or unhandled interrupt: mask=%ux",mask);
+			}
+	
+}
+
+static void
+dumpregs(Ureg* ureg)
+{
+	print("PSR %8.8uX type %2.2uX PC %8.8uX LINK %8.8uX\n",
+		ureg->psr, ureg->type, ureg->pc, ureg->link);
+	print("R14 %8.8uX R13 %8.8uX R12 %8.8uX R11 %8.8uX R10 %8.8uX\n",
+		ureg->r14, ureg->r13, ureg->r12, ureg->r11, ureg->r10);
+	print("R9  %8.8uX R8  %8.8uX R7  %8.8uX R6  %8.8uX R5  %8.8uX\n",
+		ureg->r9, ureg->r8, ureg->r7, ureg->r6, ureg->r5);
+	print("R4  %8.8uX R3  %8.8uX R2  %8.8uX R1  %8.8uX R0  %8.8uX\n",
+		ureg->r4, ureg->r3, ureg->r2, ureg->r1, ureg->r0);
+	print("Last Interrupt's CSR: %8.8uX\n",lucifer);
+	print("CPSR %8.8uX SPSR %8.8uX\n", cpsrr(), spsrr());
+}
+
+void
+dumpstack(void)
+{
+}
+
+void
+exception(Ureg* ureg)
+{
+	static Ureg old_ureg;
+	uint far =0;
+	uint fsr =0;
+
+	static lasttype = 0;
+
+	LOWBAT;	
+	
+	USED(far, fsr);
+
+	lasttype = ureg->type;
+
+	/*
+	 * All interrupts/exceptions should be resumed at ureg->pc-4,
+	 * except for Data Abort which resumes at ureg->pc-8.
+	 */
+
+	if(ureg->type == (PsrMabt+1))
+		ureg->pc -= 8;
+	else
+		ureg->pc -= 4;
+
+	switch(ureg->type){
+
+	case PsrMfiq:				/* (Fast) */
+		print("Fast\n");
+		print("We should never be here\n");
+		while(1);
+
+	case PsrMirq:				/* Interrupt Request */
+		interrupt(ureg);
+		break;
+
+	case PsrMund:				/* Undefined instruction */
+		print("Undefined instruction\n");
+	case PsrMsvc:				/* Jump through 0, SWI or reserved trap */
+		print("SWI/SVC trap\n");
+	case PsrMabt:				/* Prefetch abort */
+		print("Prefetch Abort\n");
+	case PsrMabt+1:				/* Data abort */
+		print("Data Abort\n");
+
+
+	default:
+		dumpregs(ureg);
+		/* panic("exception %uX\n", ureg->type); */
+		break;
+	}
+
+	LOWBAT;				/* Low bat off after interrupt */
+
+	splhi();
+
+}
--- /dev/null
+++ b/os/boot.original/puma/ether.c
@@ -1,0 +1,156 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+#include "ether.h"
+
+static Ctlr ether[MaxEther];
+
+static struct {
+	char	*type;
+	int	(*reset)(Ctlr*);
+} cards[] = {
+	{ "CS8900", cs8900reset, },
+	{ 0, }
+};
+
+int
+etherinit(void)
+{
+	Ctlr *ctlr;
+	int ctlrno, i, mask, n;
+
+	mask = 0;
+	for(ctlrno = 0; ctlrno < MaxEther; ctlrno++){
+		ctlr = &ether[ctlrno];
+		memset(ctlr, 0, sizeof(Ctlr));
+		if(isaconfig("ether", ctlrno, &ctlr->card) == 0)
+			continue;
+		for(n = 0; cards[n].type; n++){
+			if(strcmp(cards[n].type, ctlr->card.type))
+				continue;
+			ctlr->ctlrno = ctlrno;
+			if((*cards[n].reset)(ctlr))
+				break;
+
+			ctlr->iq = qopen(16*1024, 1, 0, 0);
+			ctlr->oq = qopen(16*1024, 1, 0, 0);
+
+			ctlr->present = 1;
+			mask |= 1<<ctlrno;
+
+			print("ether%d: %s: port 0x%luX irq %d",
+				ctlr->ctlrno, ctlr->card.type, ctlr->card.port, ctlr->card.irq);
+			if(ctlr->card.mem)
+				print(" addr 0x%luX", ctlr->card.mem & ~KZERO);
+			if(ctlr->card.size)
+				print(" size 0x%luX", ctlr->card.size);
+			print(":");
+			for(i = 0; i < sizeof(ctlr->card.ea); i++)
+				print(" %2.2uX", ctlr->card.ea[i]);
+			print("\n"); uartwait();
+			setvec(ctlr->card.irq, ctlr->card.intr, ctlr);
+			break;
+		}
+	}
+
+	return mask;
+}
+
+static Ctlr*
+attach(int ctlrno)
+{
+	Ctlr *ctlr;
+
+	if(ctlrno >= MaxEther || ether[ctlrno].present == 0)
+		return 0;
+
+	ctlr = &ether[ctlrno];
+	if(ctlr->present == 1){
+		ctlr->present = 2;
+		(*ctlr->card.attach)(ctlr);
+	}
+
+	return ctlr;
+}
+
+uchar*
+etheraddr(int ctlrno)
+{
+	Ctlr *ctlr;
+
+	if((ctlr = attach(ctlrno)) == 0)
+		return 0;
+
+	return ctlr->card.ea;
+}
+
+int
+etherrxpkt(int ctlrno, Etherpkt *pkt, int timo)
+{
+	int n;
+	Ctlr *ctlr;
+	Block *b;
+	ulong start;
+
+	if((ctlr = attach(ctlrno)) == 0)
+		return 0;
+
+	start = m->ticks;
+	while((b = qget(ctlr->iq)) == 0){
+		if(TK2MS(m->ticks - start) >= timo){
+			/*
+			print("ether%d: rx timeout\n", ctlrno);
+			 */
+			return 0;
+		}
+		//delay(1);
+	}
+
+	n = BLEN(b);
+	memmove(pkt, b->rp, n);
+	freeb(b);
+
+	return n;
+}
+
+int
+etheriq(Ctlr *ctlr, Block *b, int freebp)
+{
+	if(memcmp(((Etherpkt*)b->rp)->d, ctlr->card.ea, Eaddrlen) != 0){
+		if(freebp)
+			freeb(b);
+		return 0;
+	}
+	qbwrite(ctlr->iq, b);
+	return 1;
+}
+
+int
+ethertxpkt(int ctlrno, Etherpkt *pkt, int len, int)
+{
+	Ctlr *ctlr;
+	Block *b;
+	int s;
+
+	if((ctlr = attach(ctlrno)) == 0)
+		return 0;
+
+	if(qlen(ctlr->oq) > 16*1024){
+		print("ether%d: tx queue full\n", ctlrno);
+		return 0;
+	}
+	b = iallocb(sizeof(Etherpkt));
+	memmove(b->wp, pkt, len);
+	memmove(((Etherpkt*)b->wp)->s, ctlr->card.ea, Eaddrlen);
+	b->wp += len;
+	qbwrite(ctlr->oq, b);
+	s = splhi();
+	(*ctlr->card.transmit)(ctlr);
+	splx(s);
+
+	return 1;
+}
--- /dev/null
+++ b/os/boot.original/puma/ether.h
@@ -1,0 +1,82 @@
+/*
+ * All the goo for PC ethernet cards.
+ */
+typedef struct Card Card;
+typedef struct RingBuf RingBuf;
+typedef struct Type Type;
+typedef struct Ctlr Ctlr;
+
+/*
+ * Hardware interface.
+ */
+struct Card {
+	ISAConf;
+
+	int	(*reset)(Ctlr*);
+	void	(*attach)(Ctlr*);
+
+	void	*(*read)(Ctlr*, void*, ulong, ulong);
+	void	*(*write)(Ctlr*, ulong, void*, ulong);
+
+	void	(*receive)(Ctlr*);
+	void	(*transmit)(Ctlr*);
+	void	(*intr)(Ureg*, Ctlr*);
+	void	(*overflow)(Ctlr*);
+
+	uchar	bit16;			/* true if a 16 bit interface */
+	uchar	ram;			/* true if card has shared memory */
+
+	ulong	dp8390;			/* I/O address of 8390 (if any) */
+	ulong	data;			/* I/O data port if no shared memory */
+	uchar	nxtpkt;			/* software bndry */
+	uchar	tstart;			/* 8390 ring addresses */
+	uchar	pstart;
+	uchar	pstop;
+
+	uchar	dummyrr;		/* do dummy remote read */
+};
+
+/*
+ * Software ring buffer.
+ */
+struct RingBuf {
+	uchar	owner;
+	uchar	busy;			/* unused */
+	ushort	len;
+	uchar	pkt[sizeof(Etherpkt)];
+};
+
+enum {
+	Host		= 0,		/* buffer owned by host */
+	Interface	= 1,		/* buffer owned by card */
+
+	Nrb		= 16,		/* default number of receive buffers */
+	Ntb		= 2,		/* default number of transmit buffers */
+};
+
+/*
+ * Software controller.
+ */
+struct Ctlr {
+	Card	card;			/* hardware info */
+	int	ctlrno;
+	int	present;
+
+	Queue*	iq;
+	Queue*	oq;
+
+	int	inpackets;
+	int	outpackets;
+	int	crcs;			/* input crc errors */
+	int	oerrs;			/* output errors */
+	int	frames;			/* framing errors */
+	int	overflows;		/* packet overflows */
+	int	buffs;			/* buffering errors */
+};
+
+#define NEXT(x, l)	(((x)+1)%(l))
+#define	HOWMANY(x, y)	(((x)+((y)-1))/(y))
+#define ROUNDUP(x, y)	(HOWMANY((x), (y))*(y))
+
+extern int cs8900reset(Ctlr*);
+extern int	etheriq(Ctlr*, Block*, int);
--- /dev/null
+++ b/os/boot.original/puma/ether8900.c
@@ -1,0 +1,555 @@
+/*
+ * Crystal CS8900 ethernet controller
+ * Specifically for the Teralogic Puma architecture
+ */
+
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+#include "ether.h"
+#include "puma.h"
+
+/*
+ * On the Puma board the CS8900 can be addressed from either 
+ * ISA I/O space or ISA memory space at the following locations.
+ * The cs8900 address pins are shifted by 1 relative to the CPU.
+ */
+enum {
+	IsaIOBase		= 0xf0000000,
+	IsaMemBase	= 0xe0000000,
+
+	IOBase		= 0x300,
+	MemBase		= 0xc0000,
+};
+
+/* I/O accesses */
+#define	out16(port, val)	(*((ushort *)IsaIOBase + IOBase + (port)) = (val))
+#define	in16(port)			*((ushort *)IsaIOBase + IOBase + (port))
+#define	in8(port)			*((uchar *)IsaIOBase + ((IOBase+(port))<<1))
+#define	regIOw(reg, val)	 do {out16(PpPtr, (reg)|0x3000); out16(PpData, val);} while(0)
+#define	regIOr(reg)		(out16(PpPtr, (reg)|0x3000), in16(PpData))
+#define	regIOr1(reg)		(out16(PpPtr, (reg)|0x3000), in16(PpData1))
+
+/* Memory accesses */
+#define	regw(reg, val)		*((ushort *)IsaMemBase + MemBase + (reg)) = (val)
+#define	regr(reg)			*((ushort *)IsaMemBase + MemBase + (reg))
+
+/* Puma frame copying */
+#define	copyout(src, len)	{ \
+						int _len = (len); \
+						ushort *_src = (ushort *)(src); \
+						ushort *_dst = (ushort *)IsaMemBase + MemBase + TxFrame; \
+						while(_len > 0) { \
+							*_dst++ = *_src++; \
+							_dst++; \
+							_len -= 2; \
+						} \
+					}
+#define	copyoutIO(src, len)	{ \
+						int _len = (len); \
+						ushort *_src = (ushort *)(src); \
+						while(_len > 0) { \
+							out16(RxTxData, *_src); \
+							_src++; \
+							_len -= 2; \
+						} \
+					}
+#define	copyin(dst, len)	{ \
+						int _len = (len), _len2 = (len)&~1; \
+						ushort *_src = (ushort *)IsaMemBase + MemBase + RxFrame; \
+						ushort *_dst = (ushort *)(dst); \
+						while(_len2 > 0) { \
+							*_dst++ = *_src++; \
+							_src++; \
+							_len2 -= 2; \
+						} \
+						if(_len&1) \
+							*(uchar*)_dst = (*_src)&0xff; \
+					}
+#define	copyinIO(dst, len)	{ \
+						int _i, _len = (len), _len2 = (len)&~1; \
+						ushort *_dst = (ushort *)(dst); \
+						_i = in16(RxTxData); USED(_i); /* RxStatus */ \
+						_i = in16(RxTxData); USED(_i); /* RxLen */ \
+						while(_len2 > 0) { \
+							*_dst++ = in16(RxTxData); \
+							_len2 -= 2; \
+						} \
+						if(_len&1) \
+							*(uchar*)_dst = (in16(RxTxData))&0xff; \
+					}
+						
+	
+
+enum {					/* I/O Mode Register Offsets */
+	RxTxData	= 0x00,		/* receive/transmit data - port 0 */
+	TxCmdIO = 0x04,		/* transmit command */
+	TxLenIO	= 0x06,		/* transmit length */
+	IsqIO	= 0x08,		/* Interrupt status queue */
+	PpPtr	= 0x0a,		/* packet page pointer */
+	PpData	= 0x0c,		/* packet page data */
+	PpData1	= 0x0e,		/* packet page data - port 1*/
+};
+
+enum {					/* Memory Mode Register Offsets */
+	/* Bus Interface Registers */
+	Ern		= 0x0000,		/* EISA registration numberion */
+	Pic		= 0x0002,		/* Product identification code */
+	Iob		= 0x0020,		/* I/O base address */
+	Intr		= 0x0022,		/* interrupt number */
+	Mba		= 0x002c,		/* memory base address */
+	
+	Ecr		= 0x0040,		/* EEPROM command register */
+	Edw		= 0x0042,		/* EEPROM data word */
+	Rbc		= 0x0050,		/* receive frame byte counter */
+
+	/* Status and Control Registers */
+	RxCfg	= 0x0102,
+	RxCtl	= 0x0104,
+	TxCfg	= 0x0106,
+	BufCfg	= 0x010a,
+	LineCtl	= 0x0112,
+	SelfCtl	= 0x0114,
+	BusCtl	= 0x0116,
+	TestCtl	= 0x0118,
+	Isq		= 0x0120,
+	RxEvent	= 0x0124,
+	TxEvent	= 0x0128,
+	BufEvent	= 0x012c,
+	RxMISS	= 0x0130,
+	TxCol	= 0x0132,
+	LineSt	= 0x0134,
+	SelfSt	= 0x0136,
+	BusSt	= 0x0138,
+	Tdr		= 0x013c,
+
+	/* Initiate Transmit Registers */
+	TxCmd	= 0x0144,		/* transmit command */
+	TxLen	= 0x0146,		/* transmit length */
+
+	/* Address Filter Registers */
+	IndAddr	= 0x0158,		/* individual address registers */
+
+	/* Frame Location */
+	RxStatus	= 0x0400,		/* receive status */
+	RxLen	= 0x0402,		/* receive length */
+	RxFrame	= 0x0404,		/* receive frame location */
+	TxFrame	= 0x0a00,		/* transmit frame location */
+};
+
+enum {					/* Ecr */
+	Addr			= 0x00ff,		/* EEPROM word address (field) */
+	Opcode		= 0x0300,		/* command opcode (field) */
+};
+
+enum {					/* Isq */
+	Regnum		= 0x003f,		/* register number held by Isq (field) */
+		IsqRxEvent	= 0x04,
+		IsqTxEvent	= 0x08,
+		IsqBufEvent	= 0x0c,
+		IsqRxMiss		= 0x10,
+		IsqTxCol		= 0x12,
+	RegContent 	= 0xffc0,		/* register data contents (field) */
+};
+
+enum {					/* RxCfg */
+	Skip_1		= 0x0040,
+	StreamE		= 0x0080,
+	RxOKiE		= 0x0100,
+	RxDMAonly	= 0x0200,
+	AutoRxDMAE	= 0x0400,
+	BufferCRC		= 0x0800,
+	CRCerroriE	= 0x1000,
+	RuntiE		= 0x2000,
+	ExtradataiE	= 0x4000,
+};
+
+enum {					/* RxEvent */
+	IAHash		= 0x0040,
+	Dribblebits	= 0x0080,
+	RxOK		= 0x0100,
+	Hashed		= 0x0200,
+	IndividualAdr	= 0x0400,
+	Broadcast		= 0x0800,
+	CRCerror		= 0x1000,
+	Runt			= 0x2000,
+	Extradata		= 0x4000,
+};
+
+enum {					/* RxCtl */
+	IAHashA		= 0x0040,
+	PromiscuousA	= 0x0080,
+	RxOKA		= 0x0100,
+	MulticastA	= 0x0200,
+	IndividualA	= 0x0400,
+	BroadcastA	= 0x0800,
+	CRCerrorA	= 0x1000,
+	RuntA		= 0x2000,
+	ExtradataA	= 0x4000,
+};
+
+enum {					/* TxCfg */
+	LossofCRSiE	= 0x0040,
+	SQEerroriE	= 0x0080,
+	TxOKiE		= 0x0100,
+	OutofWindowiE	= 0x0200,
+	JabberiE		= 0x0400,
+	AnycolliE		= 0x0800,
+	Coll16iE		= 0x8000,
+};
+
+enum {					/* TxEvent */
+	LossofCRS	= 0x0040,
+	SQEerror		= 0x0080,
+	TxOK		= 0x0100,
+	OutofWindow	= 0x0200,
+	Jabber		= 0x0400,
+	NTxCols		= 0x7800,		/* number of Tx collisions (field) */
+	coll16		= 0x8000,
+};
+
+enum {					/* BufCfg */
+	SWintX		= 0x0040,
+	RxDMAiE		= 0x0080,
+	Rdy4TxiE		= 0x0100,
+	TxUnderruniE	= 0x0200,
+	RxMissiE		= 0x0400,
+	Rx128iE		= 0x0800,
+	TxColOvfiE	= 0x1000,
+	MissOvfloiE	= 0x2000,
+	RxDestiE		= 0x8000,
+};
+
+enum {					/* BufEvent */
+	SWint		= 0x0040,
+	RxDMAFrame	= 0x0080,
+	Rdy4Tx		= 0x0100,
+	TxUnderrun	= 0x0200,
+	RxMiss		= 0x0400,
+	Rx128		= 0x0800,
+	RxDest		= 0x8000,
+};
+
+enum {					/* RxMiss */
+	MissCount	= 0xffc0,
+};
+
+enum {					/* TxCol */
+	ColCount	= 0xffc0,
+};
+
+enum {					/* LineCtl */
+	SerRxOn		= 0x0040,
+	SerTxOn		= 0x0080,
+	Iface			= 0x0300,		/* (field) 01 - AUI, 00 - 10BASE-T, 10 - Auto select */
+	ModBackoffE	= 0x0800,
+	PolarityDis	= 0x1000,
+	DefDis		= 0x2000,
+	LoRxSquelch	= 0x4000,
+};
+
+enum {					/* LineSt */
+	LinkOK		= 0x0080,
+	AUI			= 0x0100,
+	TenBT		= 0x0200,
+	PolarityOK	= 0x1000,
+	CRS			= 0x4000,
+};
+
+enum {					/* SelfCtl */
+	RESET		= 0x0040,
+	SWSuspend	= 0x0100,
+	HWSleepE		= 0x0200,
+	HWStandbyE	= 0x0400,
+};
+
+enum {					/* SelfSt */
+	INITD		= 0x0080,
+	SIBUSY		= 0x0100,
+	EepromPresent	= 0x0200,
+	EepromOK	= 0x0400,
+	ElPresent		= 0x0800,
+	EeSize		= 0x1000,
+};
+
+enum {					/* BusCtl */
+	ResetRxDMA	= 0x0040,
+	UseSA		= 0x0200,
+	MemoryE		= 0x0400,
+	DMABurst		= 0x0800,
+	EnableIRQ		= 0x8000,
+};
+
+enum {					/* BusST */
+	TxBidErr		= 0x0080,
+	Rdy4TxNOW	= 0x0100,
+};
+
+enum {					/* TestCtl */
+	FDX			= 0x4000,		/* full duplex */
+};
+
+enum {					/* TxCmd */
+	TxStart		= 0x00c0,		/* bytes before transmit starts (field) */
+		TxSt5	= 0x0000,		/* start after 5 bytes */
+		TxSt381	= 0x0040,		/* start after 381 bytes */
+		TxSt1021	= 0x0080,		/* start after 1021 bytes */
+		TxStAll	= 0x00c0,		/* start after the entire frame is in the cs8900 */
+	Force		= 0x0100,
+	Onecoll		= 0x0200,
+	InhibitCRC	= 0x1000,
+	TxPadDis		= 0x2000,
+};
+
+static Queue *pendingTx[MaxEther];
+
+static void
+attach(Ctlr *ctlr)
+{
+	int reg;
+
+	USED(ctlr);
+	/* enable transmit and receive */
+	reg = regr(BusCtl);
+	regw(BusCtl, reg|EnableIRQ);
+	reg = regr(LineCtl);
+	regw(LineCtl, reg|SerRxOn|SerTxOn);
+}
+
+static char pbuf[200];
+int
+sprintx(void *f, char *to, int count)
+{
+	int i, printable;
+	char *start = to;
+	uchar *from = f;
+
+	if(count < 0) {
+		print("BAD DATA COUNT %d\n", count);
+		return 0;
+	}
+	printable = 1;
+	if(count > 40)
+		count = 40;
+	for(i=0; i<count && printable; i++)
+		if((from[i]<32 && from[i] !='\n' && from[i] !='\r' && from[i] !='\b' && from[i] !='\t') || from[i]>127)
+			printable = 0;
+	*to++ = '\'';
+	if(printable){
+		memmove(to, from, count);
+		to += count;
+	}else{
+		for(i=0; i<count; i++){
+			if(i>0 && i%4==0)
+				*to++ = ' ';
+			sprint(to, "%2.2ux", from[i]);
+			to += 2;
+		}
+	}
+	*to++ = '\'';
+	*to = 0;
+	return to - start;
+}
+
+static void
+transmit(Ctlr *ctlr)
+{
+	int len, status;
+	Block *b;
+
+	for(;;){
+		/* is TxCmd pending ? - check */
+		if(qlen(pendingTx[ctlr->ctlrno]) > 0)
+			break;
+		b = qget(ctlr->oq);
+		if(b == 0)
+			break;
+		len = BLEN(b);
+		regw(TxCmd, TxSt381);
+		regw(TxLen, len);
+		status = regr(BusSt);
+		if((status & Rdy4TxNOW) == 0) {
+			qbwrite(pendingTx[ctlr->ctlrno], b);
+			break;
+		}
+		/*
+		 * Copy the packet to the transmit buffer.
+		 */
+		copyout(b->rp, len);
+		freeb(b);
+	}
+}
+
+static void
+interrupt(Ureg*, Ctlr *ctlr)
+{
+	int len, events, status;
+	Block *b;
+	Queue *q;
+
+	while((events = regr(Isq)) != 0) {
+		status = events&RegContent;
+	
+		switch(events&Regnum) {
+
+		case IsqBufEvent:
+			if(status&Rdy4Tx) {
+				if(qlen(pendingTx[ctlr->ctlrno]) > 0)
+					q = pendingTx[ctlr->ctlrno];
+				else
+					q = ctlr->oq;
+				b = qget(q);
+				if(b == 0)
+					break;
+				len = BLEN(b);
+				copyout(b->rp, len);
+				freeb(b);
+			} else
+			if(status&TxUnderrun) {
+				print("TxUnderrun\n");
+			} else
+			if(status&RxMiss) {
+				print("RxMiss\n");
+			} else {
+				print("IsqBufEvent status = %ux\n", status);
+			}
+			break;
+
+		case IsqRxEvent:
+			if(status&RxOK) {
+				len = regr(RxLen);
+				if((b = iallocb(len)) != 0) {
+					copyin(b->wp, len);
+					b->wp += len;
+					etheriq(ctlr, b, 1);
+				}
+			} else {
+				print("IsqRxEvent status = %ux\n", status);
+			}
+			break;
+
+		case IsqTxEvent:
+			if(status&TxOK) {
+				if(qlen(pendingTx[ctlr->ctlrno]) > 0)
+					q = pendingTx[ctlr->ctlrno];
+				else
+					q = ctlr->oq;
+				b = qget(q);
+				if(b == 0)
+					break;
+				len = BLEN(b);
+				regw(TxCmd, TxSt381);
+				regw(TxLen, len);
+if((regr(BusSt) & Rdy4TxNOW) == 0) {
+	print("IsqTxEvent and Rdy4TxNow == 0\n");
+}
+				copyout(b->rp, len);
+				freeb(b);
+			} else {
+				print("IsqTxEvent status = %ux\n", status);
+			}
+			break;
+		case IsqRxMiss:
+			break;
+		case IsqTxCol:
+			break;
+		}
+	}
+}
+
+int
+cs8900reset(Ctlr* ctlr)
+{
+	int i, reg;
+	uchar ea[Eaddrlen];
+
+	ctlr->card.irq = V_ETHERNET;
+	pendingTx[ctlr->ctlrno] = qopen(16*1024, 1, 0, 0);
+
+	/*
+	 * If the Ethernet address is not set in the plan9.ini file
+	 * a) try reading from the Puma board ROM. The ether address is found in
+	 * 	bytes 4-9 of the ROM. The Teralogic Organizational Unique Id (OUI) 
+	 *	is in bytes 4-6 and should be 00 10 8a.
+	 */
+	memset(ea, 0, Eaddrlen);
+	if(memcmp(ea, ctlr->card.ea, Eaddrlen) == 0) {
+		uchar *rom = (uchar *)EPROM_BASE;
+		if(rom[4] != 0x00 || rom[5] != 0x10 || rom[6] != 0x8a)
+			panic("no ether address");
+		memmove(ea, &rom[4], Eaddrlen);
+	}
+	memmove(ctlr->card.ea, ea, Eaddrlen);
+
+	/* 
+	 * Identify the chip by reading the Pic register.
+	 * The EISA registration number is in the low word
+	 * and the product identification code in the high code.
+	 * The ERN for Crystal Semiconductor is 0x630e.
+	 * Bits 0-7 and 13-15 of the Pic should be zero for a CS8900.
+	 */
+	if(regIOr(Ern) != 0x630e || (regIOr(Pic) & 0xe0ff) != 0)
+		panic("no cs8900 found");
+
+	/*
+	 * Reset the chip and ensure 16-bit mode operation
+	 */
+	regIOw(SelfCtl, RESET);
+	delay(10);
+	i=in8(PpPtr); 	USED(i);
+	i=in8(PpPtr+1); USED(i);
+	i=in8(PpPtr); 	USED(i);
+	i=in8(PpPtr+1);	USED(i);
+
+	/*
+	 * Wait for initialisation and EEPROM reads to complete
+	 */
+	i=0;
+	for(;;) {
+		short st = regIOr(SelfSt);
+		if((st&SIBUSY) == 0 && st&INITD)
+			break;
+		if(i++ > 1000000)
+			panic("cs8900: initialisation failed");
+	}
+
+	/*
+	 * Enable memory mode operation.
+	 */
+	regIOw(Mba, MemBase & 0xffff);
+	regIOw(Mba+2, MemBase >> 16);
+	regIOw(BusCtl, MemoryE|UseSA);
+
+	/*
+	 * Enable 10BASE-T half duplex, transmit in interrupt mode
+	 */
+	reg = regr(LineCtl);
+	regw(LineCtl, reg&~Iface);
+	reg = regr(TestCtl);
+	regw(TestCtl, reg&~FDX);
+	regw(BufCfg, Rdy4TxiE|TxUnderruniE|RxMissiE);
+	regw(TxCfg, TxOKiE|JabberiE|Coll16iE);
+	regw(RxCfg, RxOKiE);
+	regw(RxCtl, RxOKA|IndividualA|BroadcastA);
+
+	for(i=0; i<Eaddrlen; i+=2)
+		regw(IndAddr+i, ea[i] | (ea[i+1] << 8));
+
+	/* Puma IRQ tied to INTRQ0 */
+	regw(Intr, 0);
+
+	ctlr->card.reset = cs8900reset;
+	ctlr->card.port = 0x300;
+	ctlr->card.attach = attach;
+	ctlr->card.transmit = transmit;
+	ctlr->card.intr = interrupt;
+
+	print("Ether reset...\n");uartwait();
+
+	return 0;
+}
+
--- /dev/null
+++ b/os/boot.original/puma/flash.c
@@ -1,0 +1,226 @@
+#include "boot.h"
+
+typedef struct Flashdev Flashdev;
+struct Flashdev {
+	uchar*	base;
+	int	size;
+	uchar*	exec;
+	char*	type;
+	char*	config;
+	int	conflen;
+};
+
+enum {
+	FLASHSEG = 256*1024,
+	CONFIGLIM = FLASHSEG,
+	BOOTOFF = FLASHSEG,
+	BOOTLEN = 3*FLASHSEG,	/* third segment might be filsys */
+	/* rest of flash is free */
+};
+
+static Flashdev flash;
+
+/*
+ * configuration data is written between the bootstrap and
+ * the end of region 0. the region ends with allocation descriptors
+ * of the following form:
+ *
+ * byte order is big endian
+ *
+ * the last valid region found that starts with the string "#plan9.ini\n" is plan9.ini
+ */
+typedef struct Flalloc Flalloc;
+struct Flalloc {
+	ulong	check;	/* checksum of data, or ~0 */
+	ulong	base;	/* base of region; ~0 if unallocated, 0 if deleted */
+	uchar	len[3];
+	uchar	tag;		/* see below */
+	uchar	sig[4];
+};
+
+enum {
+	/* tags */
+	Tdead=	0,
+	Tboot=	0x01,	/* space reserved for boot */
+	Tconf=	0x02,	/* configuration data */
+	Tnone=	0xFF,
+
+	Noval=	~0,
+};
+
+static char flashsig[] = {0xF1, 0xA5, 0x5A, 0x1F};
+static char conftag[] = "#plan9.ini\n";
+
+static ulong
+checksum(uchar* p, int n)
+{
+	ulong s;
+
+	for(s=0; --n >= 0;)
+		s += *p++;
+	return s;
+}
+
+static int
+validptr(Flalloc *ap, uchar *p)
+{
+	return p > (uchar*)end && p < (uchar*)ap;
+}
+
+static int
+flashcheck(Flalloc *ap, char **val, int *len)
+{
+	uchar *base;
+	int n;
+
+	if(ap->base == Noval || ap->base >= FLASHSEG || ap->tag == Tnone)
+		return 0;
+	base = flash.base+ap->base;
+	if(!validptr(ap, base))
+		return 0;
+	n = (((ap->len[0]<<8)|ap->len[1])<<8)|ap->len[2];
+	if(n == 0xFFFFFF)
+		n = 0;
+	if(n < 0)
+		return 0;
+	if(n > 0 && !validptr(ap, base+n-1))
+		return 0;
+	if(ap->check != Noval && checksum(base, n) != ap->check){
+		print("flash: bad checksum\n");
+		return 0;
+	}
+	*val = (char*)base;
+	*len = n;
+	return 1;
+}
+
+int
+flashinit(void)
+{
+	int f, n, len;
+	char *type, *val;
+	Flalloc *ap;
+
+	flash.base = 0;
+	flash.exec = 0;
+	flash.type = 0;
+	/* TODO - check for presence and type */
+/*
+ *	if((m->iomem->memc[0].base & 1) == 0){
+ *		print("flash: flash not present or not enabled\n");
+ *		return 0;
+ *	}
+ *	f = (m->bcsr[2]>>28)&0xF;
+ */
+f = 0;
+	switch(f){
+	default:
+			print("flash boot: unknown or no flash\n");
+			return 0;
+	case 4:	n=8; type = "SM732x8"; break;
+	case 5:	n=4; type = "SM732x8"; break;
+	case 6:	n=8; type = "AMD29F0x0"; break;
+	case 7:	n=4; type = "AMD29F0x0"; break;
+	case 8:	n=2; type = "AMD29F0x0"; break;
+	}
+	flash.type = type;
+	flash.size = n*1024*1024;
+	flash.base = KADDR(FLASH_BASE);
+	flash.exec = flash.base + BOOTOFF;
+	flash.config = nil;
+	flash.conflen = 0;
+
+	for(ap = (Flalloc*)(flash.base+CONFIGLIM)-1; memcmp(ap->sig, flashsig, 4) == 0; ap--){
+		if(1)
+			print("conf #%8.8lux: #%x #%6.6lux\n", ap, ap->tag, ap->base);
+		if(ap->tag == Tconf &&
+		   flashcheck(ap, &val, &len) &&
+		   len >= sizeof(conftag)-1 &&
+		   memcmp(val, conftag, sizeof(conftag)-1) == 0){
+			flash.config = val;
+			flash.conflen = len;
+			print("flash: found config %8.8lux(%d):\n%s\n", val, len, val);
+		}
+	}
+	if(flash.config){
+		print("flash config %8.8lux(%d):\n%s\n", flash.config, flash.conflen, flash.config);
+		flash.config = nil;	/* not that daring yet */
+	}else
+		print("flash: no config\n");
+	if(issqueezed(flash.exec) == E_MAGIC){
+		print("flash: squeezed StrongARM kernel installed\n");
+		return 1<<0;
+	}
+	if(GLLONG(flash.exec) == E_MAGIC){
+		print("flash: unsqueezed stringARM kernel installed\n");
+		return 1<<0;
+	}
+	flash.exec = 0;
+	print("flash: no StrongARM kernel in Flash\n");
+	return 0;
+}
+
+char*
+flashconfig(int)
+{
+	return flash.config;
+}
+
+int
+flashbootable(int)
+{
+	return flash.exec != nil && (issqueezed(flash.exec) || GLLONG(flash.exec) == E_MAGIC);
+}
+
+int
+flashboot(int)
+{
+	ulong entry, addr;
+	void (*b)(void);
+	Exec *ep;
+	Block in;
+	long n;
+	uchar *p;
+
+	if(flash.exec == 0)
+		return -1;
+	p = flash.exec;
+	if(GLLONG(p) == E_MAGIC){
+		/* unsqueezed: copy data and perhaps text, then jump to it */
+		ep = (Exec*)p;
+		entry = PADDR(GLLONG(ep->entry));
+		p += sizeof(Exec);
+		addr = entry;
+		n = GLLONG(ep->text);
+		if(addr != (ulong)p){
+			memmove((void*)addr, p, n);
+			print("text: %8.8lux <- %8.8lux [%ld]\n", addr, p, n);
+		}
+		p += n;
+		if(entry >= FLASH_BASE)
+			addr = 3*BY2PG;	/* kernel text is in Flash, data in RAM */
+		else
+			addr = PGROUND(addr+n);
+		n = GLLONG(ep->data);
+		memmove((void*)addr, p, n);
+		print("data: %8.8lux <- %8.8lux [%ld]\n", addr, p, n);
+	}else{
+		in.data = p;
+		in.rp = in.data;
+		in.lim = p+BOOTLEN;
+		in.wp = in.lim;
+		n = unsqueezef(&in, &entry);
+		if(n < 0)
+			return -1;
+	}
+	print("entry=0x%lux\n", entry);
+	uartwait();
+	/* scc2stop(); */
+	/*
+	 *  Go to new code. It's up to the program to get its PC relocated to
+	 *  the right place.
+	 */
+	b = (void (*)(void))KADDR(PADDR(entry));
+	(*b)();
+	return -1;
+}
--- /dev/null
+++ b/os/boot.original/puma/fns.h
@@ -1,0 +1,111 @@
+void	aamloop(int);
+Alarm*	alarm(int, void (*)(Alarm*), void*);
+void	alarminit(void);
+int	bootp(int, char*);
+void	cancel(Alarm*);
+void	checkalarms(void);
+void	clockinit(void);
+void	consinit(void);
+void	delay(int);
+uchar*	etheraddr(int);
+int	etherinit(void);
+int	etherrxpkt(int, Etherpkt*, int);
+int	ethertxpkt(int, Etherpkt*, int, int);
+int	flashboot(int);
+int	flashbootable(int);
+char*	flashconfig(int);
+int	flashinit(void);
+char*	getconf(char*);
+int	getcfields(char*, char**, int, char*);
+int	getstr(char*, char*, int, char*);
+int	hardinit(void);
+long	hardread(int, void*, long);
+long	hardseek(int, long);
+long	hardwrite(int, void*, long);
+void*	ialloc(ulong, int);
+void	idle(void);
+int	isaconfig(char*, int, ISAConf*);
+int	isgzipped(uchar*);
+int	issqueezed(uchar*);
+void	kbdinit(void);
+void	kbdchar(Queue*, int);
+void	machinit(void);
+void	meminit(void);
+void	microdelay(int);
+void	mmuinit(void);
+uchar	nvramread(int);
+void	outb(int, int);
+void	outs(int, ushort);
+void	outl(int, ulong);
+void	outsb(int, void*, int);
+void	outss(int, void*, int);
+void	outsl(int, void*, int);
+void	panic(char*, ...);
+int	optionsw(void);
+int	plan9boot(int, long (*)(int, long), long (*)(int, void*, long));
+Partition*	setflashpart(int, char*);
+Partition* sethardpart(int, char*);
+Partition* setscsipart(int, char*);
+void	setvec(int, void (*)(Ureg*, void*), void*);
+void	screeninit(void);
+void	screenputs(char*, int);
+void setr13(int, void*);
+int	splhi(void);
+int	spllo(void);
+void	splx(int);
+void	trapinit(void);
+void	uartspecial(int, int, Queue**, Queue**, void(*)(Queue*,int));
+void	uartputs(char*, int);
+void	uartwait(void);
+long	unsqueezef(Block*, ulong*);
+
+#define	GSHORT(p)	(((p)[1]<<8)|(p)[0])
+#define	GLONG(p)	((GSHORT(p+2)<<16)|GSHORT(p))
+#define	GLSHORT(p)	(((p)[0]<<8)|(p)[1])
+#define	GLLONG(p)	((GLSHORT(p)<<16)|GLSHORT(p+2))
+
+#define KADDR(a)	((void*)((ulong)(a)|KZERO))
+#define PADDR(a)	((ulong)(a)&~KZERO)
+
+
+void	mapinit(RMap*, Map*, int);
+void	mapfree(RMap*, ulong, int);
+ulong	mapalloc(RMap*, ulong, int, int);
+
+/* IBM bit field order */
+#define	IBFEXT(v,a,b) (((ulong)(v)>>(32-(b)-1)) & ~(~0L<<(((b)-(a)+1))))
+#define	IBIT(b)	((ulong)1<<(31-(b)))
+
+#define	SIBIT(n)	((ushort)1<<(15-(n)))
+
+void*	malloc(ulong);
+void	free(void*);
+
+extern Block*	iallocb(int);
+extern void	freeb(Block*);
+extern Queue*	qopen(int, int, void (*)(void*), void*);
+extern Block*	qget(Queue*);
+extern void	qbwrite(Queue*, Block*);
+extern long	qlen(Queue*);
+#define	qpass	qbwrite
+extern void	qbputc(Queue*, int);
+extern int	qbgetc(Queue*);
+
+int	sio_inb(int);
+void	sio_outb(int, int);
+void	led(int);
+
+extern void _virqcall(void);
+extern void _vfiqcall(void);
+extern void _vundcall(void);
+extern void _vsvccall(void);
+extern void _vpabcall(void);
+extern void _vdabcall(void);
+
+void flushIcache(void);
+void writeBackDC(void);
+void flushDcache(void);
+void flushIcache(void);
+void drainWBuffer(void);
+
+void pumainit(void);
--- /dev/null
+++ b/os/boot.original/puma/hard.c
@@ -1,0 +1,773 @@
+#include	"u.h"
+#include	"lib.h"
+#include	"mem.h"
+#include	"dat.h"
+#include	"fns.h"
+#include	"io.h"
+
+#define DPRINT if(0)print
+
+typedef	struct Drive		Drive;
+typedef	struct Ident		Ident;
+typedef	struct Controller	Controller;
+
+enum
+{
+	/* ports */
+	Pbase0=		0x1F0,	/* primary */
+	Pbase1=		0x170,	/* secondary */
+	Pbase2=		0x1E8,	/* tertiary */
+	Pbase3=		0x168,	/* quaternary */
+	Pdata=		0,	/* data port (16 bits) */
+	Perror=		1,	/* error port (read) */
+	Pprecomp=	1,	/* buffer mode port (write) */
+	Pcount=		2,	/* sector count port */
+	Psector=	3,	/* sector number port */
+	Pcyllsb=	4,	/* least significant byte cylinder # */
+	Pcylmsb=	5,	/* most significant byte cylinder # */
+	Pdh=		6,	/* drive/head port */
+	 DHmagic=	0xA0,
+	 DHslave=	0x10,
+	Pstatus=	7,	/* status port (read) */
+	 Sbusy=		 (1<<7),
+	 Sready=	 (1<<6),
+	 Sdrq=		 (1<<3),
+	 Serr=		 (1<<0),
+	Pcmd=		7,	/* cmd port (write) */
+
+	/* commands */
+	Crecal=		0x10,
+	Cread=		0x20,
+	Cwrite=		0x30,
+	Cident=		0xEC,
+	Cident2=	0xFF,	/* pseudo command for post Cident interrupt */
+	Csetbuf=	0xEF,
+
+	/* file types */
+	Qdir=		0,
+
+	Timeout=	5,		/* seconds to wait for things to complete */
+
+	NCtlr=		4,
+	NDrive=		NCtlr*2,
+};
+
+/*
+ *  ident sector from drive.  this is from ANSI X3.221-1994
+ */
+struct Ident
+{
+	ushort	config;		/* general configuration info */
+	ushort	cyls;		/* # of cylinders (default) */
+	ushort	reserved0;
+	ushort	heads;		/* # of heads (default) */
+	ushort	b2t;		/* unformatted bytes/track */
+	ushort	b2s;		/* unformated bytes/sector */
+	ushort	s2t;		/* sectors/track (default) */
+	ushort	reserved1[3];
+/* 10 */
+	ushort	serial[10];	/* serial number */
+	ushort	type;		/* buffer type */
+	ushort	bsize;		/* buffer size/512 */
+	ushort	ecc;		/* ecc bytes returned by read long */
+	ushort	firm[4];	/* firmware revision */
+	ushort	model[20];	/* model number */
+/* 47 */
+	ushort	s2i;		/* number of sectors/interrupt */
+	ushort	dwtf;		/* double word transfer flag */
+	ushort	capabilities;
+	ushort	reserved2;
+	ushort	piomode;
+	ushort	dmamode;
+	ushort	cvalid;		/* (cvald&1) if next 4 words are valid */
+	ushort	ccyls;		/* current # cylinders */
+	ushort	cheads;		/* current # heads */
+	ushort	cs2t;		/* current sectors/track */
+	ushort	ccap[2];	/* current capacity in sectors */
+	ushort	cs2i;		/* current number of sectors/interrupt */
+/* 60 */
+	ushort	lbasecs[2];	/* # LBA user addressable sectors */
+	ushort	dmasingle;
+	ushort	dmadouble;
+/* 64 */
+	ushort	reserved3[64];
+	ushort	vendor[32];	/* vendor specific */
+	ushort	reserved4[96];
+};
+
+/*
+ *  a hard drive
+ */
+struct Drive
+{
+	Controller *cp;
+	uchar	driveno;
+	uchar	dh;
+
+	Disc;
+};
+
+/*
+ *  a controller for 2 drives
+ */
+struct Controller
+{
+	int	pbase;		/* base port */
+	uchar	ctlrno;
+
+	/*
+	 *  current operation
+	 */
+	int	cmd;		/* current command */
+	char	*buf;		/* xfer buffer */
+	int	tcyl;		/* target cylinder */
+	int	thead;		/* target head */
+	int	tsec;		/* target sector */
+	int	tbyte;		/* target byte */
+	int	nsecs;		/* length of transfer (sectors) */
+	int	sofar;		/* bytes transferred so far */
+	int	status;
+	int	error;
+	Drive	*dp;		/* drive being accessed */
+};
+
+static int atactlrmask;
+static Controller *atactlr[NCtlr];
+static int atadrivemask;
+static Drive *atadrive[NDrive];
+static int pbase[NCtlr] = {
+	Pbase0, Pbase1, Pbase2, Pbase3,
+};
+
+static void	hardintr(Ureg*, void*);
+static long	hardxfer(Drive*, Partition*, int, ulong, long);
+static int	hardident(Drive*);
+static void	hardsetbuf(Drive*, int);
+static void	hardpart(Drive*);
+static int	hardparams(Drive*);
+static void	hardrecal(Drive*);
+static int	hardprobe(Drive*, int, int, int);
+
+static void
+atactlrprobe(int ctlrno, int irq)
+{
+	Controller *ctlr;
+	Drive *drive;
+	int driveno, port;
+
+	if(atactlrmask & (1<<ctlrno))
+		return;
+	atactlrmask |= 1<<ctlrno;
+
+	port = pbase[ctlrno];
+	outb(port+Pdh, DHmagic);
+	delay(1);
+	if((inb(port+Pdh) & 0xFF) != DHmagic){
+		DPRINT("ata%d: DHmagic not ok\n", ctlrno);
+		return;
+	}
+	DPRINT("ata%d: DHmagic ok\n", ctlrno);
+
+	atactlr[ctlrno] = ialloc(sizeof(Controller), 0);
+	ctlr = atactlr[ctlrno];
+	ctlr->pbase = port;
+	ctlr->ctlrno = ctlrno;
+	ctlr->buf = ialloc(Maxxfer, 0);
+	inb(ctlr->pbase+Pstatus);
+	setvec(irq, hardintr, ctlr);
+
+	driveno = ctlrno*2;
+	atadrive[driveno] = ialloc(sizeof(Drive), 0);
+	drive = atadrive[driveno];
+	drive->cp = ctlr;
+	drive->driveno = driveno;
+	drive->dh = DHmagic;
+
+	driveno++;
+	atadrive[driveno] = ialloc(sizeof(Drive), 0);
+	drive = atadrive[driveno];
+	drive->cp = ctlr;
+	drive->driveno = driveno;
+	drive->dh = DHmagic|DHslave;
+}
+
+static Drive*
+atadriveprobe(int driveno)
+{
+	Drive *drive;
+	int ctlrno;
+	ISAConf isa;
+
+	ctlrno = driveno/2;
+	if(atactlr[ctlrno] == 0){
+		if(atactlrmask & (1<<ctlrno))
+			return 0;
+		memset(&isa, 0, sizeof(ISAConf));
+		if(isaconfig("ata", ctlrno, &isa) == 0)
+			return 0;
+		if(ctlrno && isa.irq)
+			atactlrprobe(ctlrno, Int0vec+isa.irq);
+		if(atactlr[ctlrno] == 0)
+			return 0;
+	}
+
+	drive = atadrive[driveno];
+	if(drive->online == 0){
+		if(atadrivemask & (1<<driveno))
+			return 0;
+		atadrivemask |= 1<<driveno;
+		if(hardparams(drive))
+			return 0;
+		if(drive->lba)
+			print("hd%d: LBA %d sectors, %ud bytes\n",
+				drive->driveno, drive->sectors, drive->cap);
+		else
+			print("hd%d: CHS %d/%d/%d %d bytes\n",
+				drive->driveno, drive->cyl, drive->heads,
+				drive->sectors, drive->cap);
+		drive->online = 1;
+		hardpart(drive);
+		hardsetbuf(drive, 1);
+	}
+
+	return drive;
+}
+
+int
+hardinit(void)
+{
+	atactlrprobe(0, ATAvec0);
+	return 0xFF;
+}
+
+long
+hardseek(int driveno, long offset)
+{
+	Drive *drive;
+
+	if((drive = atadriveprobe(driveno)) == 0)
+		return -1;
+	drive->offset = offset;
+	return offset;
+}
+
+/*
+ *  did an interrupt happen?
+ */
+static void
+hardwait(Controller *cp)
+{
+	ulong start;
+	int x;
+
+	x = spllo();
+	for(start = m->ticks; TK2SEC(m->ticks - start) < Timeout && cp->cmd;)
+		if(cp->cmd == Cident2 && TK2SEC(m->ticks - start) >= 1)
+			break;
+	if(TK2SEC(m->ticks - start) >= Timeout){
+		DPRINT("hardwait timed out %ux\n", inb(cp->pbase+Pstatus));
+		hardintr(0, cp);
+	}
+	splx(x);
+}
+
+Partition*
+sethardpart(int driveno, char *p)
+{
+	Partition *pp;
+	Drive *dp;
+
+	if((dp = atadriveprobe(driveno)) == 0)
+		return 0;
+
+	for(pp = dp->p; pp < &dp->p[dp->npart]; pp++)
+		if(strcmp(pp->name, p) == 0){
+			dp->current = pp;
+			return pp;
+		}
+	return 0;
+}
+
+long
+hardread(int driveno, void *a, long n)
+{
+	Drive *dp;
+	long rv, i;
+	int skip;
+	uchar *aa = a;
+	Partition *pp;
+	Controller *cp;
+
+	if((dp = atadriveprobe(driveno)) == 0)
+		return 0;
+
+	pp = dp->current;
+	if(pp == 0)
+		return -1;
+	cp = dp->cp;
+
+	skip = dp->offset % dp->bytes;
+	for(rv = 0; rv < n; rv += i){
+		i = hardxfer(dp, pp, Cread, dp->offset+rv-skip, n-rv+skip);
+		if(i == 0)
+			break;
+		if(i < 0)
+			return -1;
+		i -= skip;
+		if(i > n - rv)
+			i = n - rv;
+		memmove(aa+rv, cp->buf + skip, i);
+		skip = 0;
+	}
+	dp->offset += rv;
+
+	return rv;
+}
+
+/*
+ *  wait for the controller to be ready to accept a command
+ */
+static int
+cmdreadywait(Drive *drive)
+{
+	ulong end;
+	uchar dh, status;
+	Controller *ctlr;
+
+	ctlr = drive->cp;
+	end = m->ticks+MS2TK(10)+1;
+	dh = (inb(ctlr->pbase+Pdh) & DHslave)^(drive->dh & DHslave);
+	
+	status = 0;
+	while(m->ticks < end){
+		status = inb(ctlr->pbase+Pstatus);
+		if(status & Sbusy)
+			continue;
+		if(dh){
+			outb(ctlr->pbase+Pdh, drive->dh);
+			dh = 0;
+			continue;
+		}
+		if(status & Sready)
+			return 0;
+	}
+	USED(status);
+
+	DPRINT("hd%d: cmdreadywait failed %uX\n", drive->driveno, status);
+	outb(ctlr->pbase+Pdh, DHmagic);
+	return -1;
+}
+
+/*
+ *  transfer a number of sectors.  hardintr will perform all the iterative
+ *  parts.
+ */
+static long
+hardxfer(Drive *dp, Partition *pp, int cmd, ulong start, long len)
+{
+	Controller *cp;
+	long lsec;
+
+	if(dp->online == 0){
+		DPRINT("disk not on line\n");
+		return -1;
+	}
+
+	if(cmd == Cwrite)
+		return -1;
+
+	/*
+	 *  cut transfer size down to disk buffer size
+	 */
+	start = start / dp->bytes;
+	if(len > Maxxfer)
+		len = Maxxfer;
+	len = (len + dp->bytes - 1) / dp->bytes;
+
+	/*
+	 *  calculate physical address
+	 */
+	cp = dp->cp;
+	lsec = start + pp->start;
+	if(lsec >= pp->end){
+		DPRINT("read past end of partition\n");
+		return 0;
+	}
+	if(dp->lba){
+		cp->tsec = lsec & 0xff;
+		cp->tcyl = (lsec>>8) & 0xffff;
+		cp->thead = (lsec>>24) & 0xf;
+	} else {
+		cp->tcyl = lsec/(dp->sectors*dp->heads);
+		cp->tsec = (lsec % dp->sectors) + 1;
+		cp->thead = (lsec/dp->sectors) % dp->heads;
+	}
+
+	/*
+	 *  can't xfer past end of disk
+	 */
+	if(lsec+len > pp->end)
+		len = pp->end - lsec;
+	cp->nsecs = len;
+
+	if(cmdreadywait(dp) < 0)
+		return -1;
+
+	/*
+	 *  start the transfer
+	 */
+	cp->cmd = cmd;
+	cp->dp = dp;
+	cp->sofar = 0;
+	cp->status = 0;
+	DPRINT("xfer:\ttcyl %d, tsec %d, thead %d\n", cp->tcyl, cp->tsec, cp->thead);
+	DPRINT("\tnsecs %d, sofar %d\n", cp->nsecs, cp->sofar);
+	outb(cp->pbase+Pcount, cp->nsecs);
+	outb(cp->pbase+Psector, cp->tsec);
+	outb(cp->pbase+Pdh, dp->dh | (dp->lba<<6) | cp->thead);
+	outb(cp->pbase+Pcyllsb, cp->tcyl);
+	outb(cp->pbase+Pcylmsb, cp->tcyl>>8);
+	outb(cp->pbase+Pcmd, cmd);
+
+	hardwait(cp);
+
+	if(cp->status & Serr){
+		DPRINT("hd%d err: status %lux, err %lux\n",
+			dp->driveno, cp->status, cp->error);
+		DPRINT("\ttcyl %d, tsec %d, thead %d\n",
+			cp->tcyl, cp->tsec, cp->thead);
+		DPRINT("\tnsecs %d, sofar %d\n", cp->nsecs, cp->sofar);
+		return -1;
+	}
+
+	return cp->nsecs*dp->bytes;
+}
+
+/*
+ *  set read ahead mode (1 == on, 0 == off)
+ */
+static void
+hardsetbuf(Drive *dp, int on)
+{
+	Controller *cp = dp->cp;
+
+	if(cmdreadywait(dp) < 0)
+		return;
+
+	cp->cmd = Csetbuf;
+	/* BUG: precomp varies by hard drive...this is safari-specific? */
+	outb(cp->pbase+Pprecomp, on ? 0xAA : 0x55);
+	outb(cp->pbase+Pdh, dp->dh);
+	outb(cp->pbase+Pcmd, Csetbuf);
+
+	hardwait(cp);
+}
+
+static int
+isatapi(Drive *drive)
+{
+	Controller *cp;
+
+	cp = drive->cp;
+	outb(cp->pbase+Pdh, drive->dh);
+	microdelay(1);
+	if(inb(cp->pbase+Pstatus))
+		return 0;
+	if(inb(cp->pbase+Pcylmsb) != 0xEB || inb(cp->pbase+Pcyllsb) != 0x14)
+		return 0;
+	return 1;
+}
+
+/*
+ *  get parameters from the drive
+ */
+static int
+hardident(Drive *dp)
+{
+	Controller *cp;
+	Ident *ip;
+
+	dp->bytes = 512;
+	cp = dp->cp;
+
+	if(isatapi(dp) || cmdreadywait(dp) < 0)
+		return -1;
+
+	cp->nsecs = 1;
+	cp->sofar = 0;
+	cp->cmd = Cident;
+	cp->dp = dp;
+	outb(cp->pbase+Pdh, dp->dh);
+	outb(cp->pbase+Pcmd, Cident);
+
+	hardwait(cp);
+
+	if(cp->status & Serr)
+		return -1;
+	
+	hardwait(cp);
+
+	ip = (Ident*)cp->buf;
+	DPRINT("LBA%d: %lud\n",
+		ip->capabilities & (1<<9) == 1, (ip->lbasecs[0]) | (ip->lbasecs[1]<<16));
+	DPRINT("DEF: %ud/%ud/%ud\nMAP %ud/%ud/%ud\n",
+		ip->cyls, ip->heads, ip->s2t,
+		ip->ccyls, ip->cheads, ip->cs2t);
+	if(ip->capabilities & (1<<9)){
+		dp->lba = 1;
+		dp->sectors = (ip->lbasecs[0]) | (ip->lbasecs[1]<<16);
+		dp->cap = dp->bytes * dp->sectors;
+/*print("\nata%d model %s with %d lba sectors\n", dp->driveno, id, dp->sectors);/**/
+	} else {
+		dp->lba = 0;
+
+		/* use default (unformatted) settings */
+		dp->cyl = ip->cyls;
+		dp->heads = ip->heads;
+		dp->sectors = ip->s2t;
+/*print("\nata%d model %s with default %d cyl %d head %d sec\n", dp->driveno,
+			id, dp->cyl, dp->heads, dp->sectors);/**/
+
+		if(ip->cvalid&(1<<0)){
+			/* use current settings */
+			dp->cyl = ip->ccyls;
+			dp->heads = ip->cheads;
+			dp->sectors = ip->cs2t;
+/*print("\tchanged to %d cyl %d head %d sec\n", dp->cyl, dp->heads, dp->sectors);/**/
+		}
+		dp->cap = dp->bytes * dp->cyl * dp->heads * dp->sectors;
+	}
+
+	return 0;
+}
+
+/*
+ *  probe the given sector to see if it exists
+ */
+static int
+hardprobe(Drive *dp, int cyl, int sec, int head)
+{
+	Controller *cp;
+
+	cp = dp->cp;
+	if(cmdreadywait(dp) < 0)
+		return -1;
+
+	/*
+	 *  start the transfer
+	 */
+	cp->cmd = Cread;
+	cp->dp = dp;
+	cp->sofar = 0;
+	cp->nsecs = 1;
+	cp->status = 0;
+	outb(cp->pbase+Pcount, 1);
+	outb(cp->pbase+Psector, sec+1);
+	outb(cp->pbase+Pdh, dp->dh | (dp->lba<<6) | head);
+	outb(cp->pbase+Pcyllsb, cyl);
+	outb(cp->pbase+Pcylmsb, cyl>>8);
+	outb(cp->pbase+Pcmd, Cread);
+
+	hardwait(cp);
+
+	if(cp->status & Serr)
+		return -1;
+
+	return 0;
+}
+
+/*
+ *  figure out the drive parameters
+ */
+static int
+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;
+	if(hardident(dp) < 0)
+		return -1;
+	if(dp->lba){
+		i = dp->sectors - 1;
+		if(hardprobe(dp, (i>>8)&0xffff, (i&0xff)-1, (i>>24)&0xf) == 0)
+			return 0;
+	} else {
+		if(hardprobe(dp, dp->cyl-1, dp->sectors-1, dp->heads-1) == 0)
+			return 0;
+	}
+
+	DPRINT("hardparam: cyl %d sectors %d heads %d\n", dp->cyl, dp->sectors, dp->heads);
+	/*
+	 *  the drive lied, determine parameters by seeing which ones
+	 *  work to read sectors.
+	 */
+	dp->lba = 0;
+	for(i = 0; i < 16; i++)
+		if(hardprobe(dp, 0, 0, i) < 0)
+			break;
+	dp->heads = i;
+	for(i = 0; i < 64; 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;
+
+	if(dp->cyl == 0 || dp->heads == 0 || dp->sectors == 0 || dp->cap == 0)
+		return -1;
+
+	return 0;
+}
+
+/*
+ *  read partition table.  The partition table is just ascii strings.
+ */
+#define MAGIC "plan9 partitions"
+static void
+hardpart(Drive *dp)
+{
+	Partition *pp;
+	Controller *cp;
+	char *field[3], *line[Npart+1], *p, buf[NAMELEN];
+	ulong n;
+	int i;
+
+	cp = dp->cp;
+
+	/*
+	 *  we always have a partition for the whole disk
+	 *  and one for the partition table
+	 */
+	pp = &dp->p[0];
+	strcpy(pp->name, "disk");
+	pp->start = 0;
+	pp->end = dp->cap / dp->bytes;
+	pp++;
+	strcpy(pp->name, "partition");
+	pp->start = dp->p[0].end - 1;
+	pp->end = dp->p[0].end;
+	dp->npart = 2;
+
+	/*
+	 * Check if the partitions are described in plan9.ini.
+	 * If not, read the disc.
+	 */
+	sprint(buf, "hd%dpartition", dp->driveno);
+	if((p = getconf(buf)) == 0){	
+		/*
+		 *  read last sector from disk, null terminate.  This used
+		 *  to be the sector we used for the partition tables.
+		 *  However, this sector is special on some PC's so we've
+		 *  started to use the second last sector as the partition
+		 *  table instead.  To avoid reconfiguring all our old systems
+		 *  we first look to see if there is a valid partition
+		 *  table in the last sector.  If so, we use it.  Otherwise
+		 *  we switch to the second last.
+		 */
+		hardxfer(dp, pp, Cread, 0, dp->bytes);
+		cp->buf[dp->bytes-1] = 0;
+		n = getcfields(cp->buf, line, Npart+1, "\n");
+		if(n == 0 || strncmp(line[0], MAGIC, sizeof(MAGIC)-1)){
+			dp->p[0].end--;
+			dp->p[1].start--;
+			dp->p[1].end--;
+			hardxfer(dp, pp, Cread, 0, dp->bytes);
+			cp->buf[dp->bytes-1] = 0;
+			n = getcfields(cp->buf, line, Npart+1, "\n");
+		}
+	}
+	else{
+		strcpy(cp->buf, p);
+		n = getcfields(cp->buf, line, Npart+1, "\n");
+	}
+
+	/*
+	 *  parse partition table.
+	 */
+	if(n && strncmp(line[0], MAGIC, sizeof(MAGIC)-1) == 0){
+		for(i = 1; i < n; i++){
+			pp++;
+			if(getcfields(line[i], field, 3, " ") != 3)
+				break;
+			strncpy(pp->name, field[0], NAMELEN);
+			pp->start = strtoul(field[1], 0, 0);
+			pp->end = strtoul(field[2], 0, 0);
+			if(pp->start > pp->end || pp->start >= dp->p[0].end)
+				break;
+			dp->npart++;
+		}
+	}
+	return;
+}
+
+/*
+ *  we get an interrupt for every sector transferred
+ */
+static void
+hardintr(Ureg*, void *arg)
+{
+	Controller *cp;
+	Drive *dp;
+	long loop;
+
+	cp = arg;
+	dp = cp->dp;
+
+	loop = 0;
+	while((cp->status = inb(cp->pbase+Pstatus)) & Sbusy)
+		if(++loop > 100000){
+			print("hardintr 0x%lux\n", cp->status);
+			break;
+		}
+	switch(cp->cmd){
+	case Cread:
+	case Cident:
+		if(cp->status & Serr){
+			cp->cmd = 0;
+			cp->error = inb(cp->pbase+Perror);
+			return;
+		}
+		loop = 0;
+		while((inb(cp->pbase+Pstatus) & Sdrq) == 0)
+			if(++loop > 100000){
+				print("hardintr 2 cmd %ux status %ux",
+					cp->cmd, inb(cp->pbase+Pstatus));
+				cp->cmd = 0;
+				return;
+			}
+		inss(cp->pbase+Pdata, &cp->buf[cp->sofar*dp->bytes],
+			dp->bytes/2);
+		cp->sofar++;
+		if(cp->sofar >= cp->nsecs){
+			if(cp->cmd == Cident && (cp->status & Sready) == 0)
+				cp->cmd = Cident2; /* sometimes we get a second intr */
+			else
+				cp->cmd = 0;
+			inb(cp->pbase+Pstatus);
+		}
+		break;
+	case Csetbuf:
+	case Cident2:
+		cp->cmd = 0;
+		break;
+	default:
+		cp->cmd = 0;
+		break;
+	}
+}
--- /dev/null
+++ b/os/boot.original/puma/io.h
@@ -1,0 +1,3 @@
+#define 	inb(port)			sio_inb(port)
+#define 	outb(port, data)	sio_outb(port, data)
+
--- /dev/null
+++ b/os/boot.original/puma/ip.h
@@ -1,0 +1,98 @@
+typedef struct Udphdr Udphdr;
+struct Udphdr
+{
+	uchar	d[6];		/* Ethernet destination */
+	uchar	s[6];		/* Ethernet source */
+	uchar	type[2];	/* Ethernet packet type */
+
+	uchar	vihl;		/* Version and header length */
+	uchar	tos;		/* Type of service */
+	uchar	length[2];	/* packet length */
+	uchar	id[2];		/* Identification */
+	uchar	frag[2];	/* Fragment information */
+
+	/* Udp pseudo ip really starts here */
+	uchar	ttl;	
+	uchar	udpproto;	/* Protocol */
+	uchar	udpplen[2];	/* Header plus data length */
+	uchar	udpsrc[4];	/* Ip source */
+	uchar	udpdst[4];	/* Ip destination */
+	uchar	udpsport[2];	/* Source port */
+	uchar	udpdport[2];	/* Destination port */
+	uchar	udplen[2];	/* data length */
+	uchar	udpcksum[2];	/* Checksum */
+};
+
+typedef struct Etherhdr Etherhdr;
+struct Etherhdr
+{
+	uchar	d[6];
+	uchar	s[6];
+	uchar	type[2];
+
+	/* Now we have the ip fields */
+	uchar	vihl;		/* Version and header length */
+	uchar	tos;		/* Type of service */
+	uchar	length[2];	/* packet length */
+	uchar	id[2];		/* Identification */
+	uchar	frag[2];	/* Fragment information */
+	uchar	ttl;		/* Time to live */
+	uchar	proto;		/* Protocol */
+	uchar	cksum[2];	/* Header checksum */
+	uchar	src[4];		/* Ip source */
+	uchar	dst[4];		/* Ip destination */
+};
+
+enum
+{
+	IP_VER		= 0x40,
+	IP_HLEN		= 0x05,			
+ 	UDP_EHSIZE	= 22,
+	UDP_PHDRSIZE	= 12,
+	UDP_HDRSIZE	= 20,
+	ETHER_HDR	= 14,
+	IP_UDPPROTO	= 17,
+	ET_IP		= 0x800,
+	Bcastip		= 0xffffffff,
+	BPportsrc	= 68,
+	BPportdst	= 67,
+	TFTPport	= 69,
+	Timeout		= 5000,	/* milliseconds */
+	Bootrequest 	= 1,
+	Bootreply   	= 2,
+	Tftp_READ	= 1,
+	Tftp_WRITE	= 2,
+	Tftp_DATA	= 3,
+	Tftp_ACK	= 4,
+	Tftp_ERROR	= 5,
+	Segsize		= 512,
+	TFTPSZ		= Segsize+10,
+};
+
+typedef struct Bootp Bootp;
+struct Bootp
+{
+	uchar	op;		/* opcode */
+	uchar	htype;		/* hardware type */
+	uchar	hlen;		/* hardware address len */
+	uchar	hops;		/* hops */
+	uchar	xid[4];		/* a random number */
+	uchar	secs[2];	/* elapsed snce client started booting */
+	uchar	pad[2];
+	uchar	ciaddr[4];	/* client IP address (client tells server) */
+	uchar	yiaddr[4];	/* client IP address (server tells client) */
+	uchar	siaddr[4];	/* server IP address */
+	uchar	giaddr[4];	/* gateway IP address */
+	uchar	chaddr[16];	/* client hardware address */
+	char	sname[64];	/* server host name (optional) */
+	char	file[128];	/* boot file name */
+	char	vend[128];	/* vendor-specific goo */
+};
+
+typedef struct Netaddr Netaddr;
+struct Netaddr
+{
+	ulong	ip;
+	ushort	port;
+	char	ea[Eaddrlen];
+};
--- /dev/null
+++ b/os/boot.original/puma/kbd.c
@@ -1,0 +1,482 @@
+#include "boot.h"
+
+
+enum {
+	Data=		0x60,	/* data port */
+
+	Status=		0x64,	/* status port */
+	 Inready=	0x01,	/*  input character ready */
+	 Outbusy=	0x02,	/*  output busy */
+	 Sysflag=	0x04,	/*  system flag */
+	 Cmddata=	0x08,	/*  cmd==0, data==1 */
+	 Inhibit=	0x10,	/*  keyboard/mouse inhibited */
+	 Minready=	0x20,	/*  mouse character ready */
+	 Rtimeout=	0x40,	/*  general timeout */
+	 Parity=	0x80,
+
+	Cmd=		0x64,	/* command port (write only) */
+ 
+	Spec=	0x80,
+
+	PF=	Spec|0x20,	/* num pad function key */
+	View=	Spec|0x00,	/* view (shift window up) */
+	KF=	Spec|0x40,	/* function key */
+	Shift=	Spec|0x60,
+	Break=	Spec|0x61,
+	Ctrl=	Spec|0x62,
+	Latin=	Spec|0x63,
+	Caps=	Spec|0x64,
+	Num=	Spec|0x65,
+	No=	Spec|0x7F,	/* no mapping */
+
+	Home=	KF|13,
+	Up=	KF|14,
+	Pgup=	KF|15,
+	Print=	KF|16,
+	Left=	View,
+	Right=	View,
+	End=	'\r',
+	Down=	View,
+	Pgdown=	View,
+	Ins=	KF|20,
+	Del=	0x7F,
+};
+
+uchar kbtab[] = 
+{
+[0x00]	No,	0x1b,	'1',	'2',	'3',	'4',	'5',	'6',
+[0x08]	'7',	'8',	'9',	'0',	'-',	'=',	'\b',	'\t',
+[0x10]	'q',	'w',	'e',	'r',	't',	'y',	'u',	'i',
+[0x18]	'o',	'p',	'[',	']',	'\n',	Ctrl,	'a',	's',
+[0x20]	'd',	'f',	'g',	'h',	'j',	'k',	'l',	';',
+[0x28]	'\'',	'`',	Shift,	'\\',	'z',	'x',	'c',	'v',
+[0x30]	'b',	'n',	'm',	',',	'.',	'/',	Shift,	No,
+[0x38]	Latin,	' ',	Caps,	KF|1,	KF|2,	KF|3,	KF|4,	KF|5,
+[0x40]	KF|6,	KF|7,	KF|8,	KF|9,	KF|10,	Num,	KF|12,	Home,
+[0x48]	No,	No,	No,	No,	No,	No,	No,	No,
+[0x50]	No,	No,	No,	No,	No,	No,	No,	KF|11,
+[0x58]	KF|12,	No,	No,	No,	No,	No,	No,	No,
+};
+
+uchar kbtabshift[] =
+{
+[0x00]	No,	0x1b,	'!',	'@',	'#',	'$',	'%',	'^',
+[0x08]	'&',	'*',	'(',	')',	'_',	'+',	'\b',	'\t',
+[0x10]	'Q',	'W',	'E',	'R',	'T',	'Y',	'U',	'I',
+[0x18]	'O',	'P',	'{',	'}',	'\n',	Ctrl,	'A',	'S',
+[0x20]	'D',	'F',	'G',	'H',	'J',	'K',	'L',	':',
+[0x28]	'"',	'~',	Shift,	'|',	'Z',	'X',	'C',	'V',
+[0x30]	'B',	'N',	'M',	'<',	'>',	'?',	Shift,	No,
+[0x38]	Latin,	' ',	Caps,	KF|1,	KF|2,	KF|3,	KF|4,	KF|5,
+[0x40]	KF|6,	KF|7,	KF|8,	KF|9,	KF|10,	Num,	KF|12,	Home,
+[0x48]	No,	No,	No,	No,	No,	No,	No,	No,
+[0x50]	No,	No,	No,	No,	No,	No,	No,	KF|11,
+[0x58]	KF|12,	No,	No,	No,	No,	No,	No,	No,
+};
+
+uchar kbtabesc1[] =
+{
+[0x00]	No,	No,	No,	No,	No,	No,	No,	No,
+[0x08]	No,	No,	No,	No,	No,	No,	No,	No,
+[0x10]	No,	No,	No,	No,	No,	No,	No,	No,
+[0x18]	No,	No,	No,	No,	No,	Ctrl,	No,	No,
+[0x20]	No,	No,	No,	No,	No,	No,	No,	No,
+[0x28]	No,	No,	No,	No,	No,	No,	No,	No,
+[0x30]	No,	No,	No,	No,	No,	No,	No,	Print,
+[0x38]	Latin,	No,	No,	No,	No,	No,	No,	No,
+[0x40]	No,	No,	No,	No,	No,	No,	Break,	Home,
+[0x48]	Up,	Pgup,	No,	Down,	No,	Right,	No,	End,
+[0x50]	Left,	Pgdown,	Ins,	Del,	No,	No,	No,	No,
+[0x58]	No,	No,	No,	No,	No,	No,	No,	No,
+};
+
+struct latin
+{
+	uchar	l;
+	char	c[2];
+}latintab[] = {
+	L'¡',	"!!",	/* spanish initial ! */
+	L'¢',	"c|",	/* cent */
+	L'¢',	"c$",	/* cent */
+	L'£',	"l$",	/* pound sterling */
+	L'¤',	"g$",	/* general currency */
+	L'¥',	"y$",	/* yen */
+	L'¥',	"j$",	/* yen */
+	L'¦',	"||",	/* broken vertical bar */
+	L'§',	"SS",	/* section symbol */
+	L'¨',	"\"\"",	/* dieresis */
+	L'©',	"cr",	/* copyright */
+	L'©',	"cO",	/* copyright */
+	L'ª',	"sa",	/* super a, feminine ordinal */
+	L'«',	"<<",	/* left angle quotation */
+	L'¬',	"no",	/* not sign, hooked overbar */
+	L'­',	"--",	/* soft hyphen */
+	L'®',	"rg",	/* registered trademark */
+	L'¯',	"__",	/* macron */
+	L'°',	"s0",	/* degree (sup o) */
+	L'±',	"+-",	/* plus-minus */
+	L'²',	"s2",	/* sup 2 */
+	L'³',	"s3",	/* sup 3 */
+	L'´',	"''",	/* grave accent */
+	L'µ',	"mu",	/* mu */
+	L'¶',	"pg",	/* paragraph (pilcrow) */
+	L'·',	"..",	/* centered . */
+	L'¸',	",,",	/* cedilla */
+	L'¹',	"s1",	/* sup 1 */
+	L'º',	"so",	/* sup o */
+	L'»',	">>",	/* right angle quotation */
+	L'¼',	"14",	/* 1/4 */
+	L'½',	"12",	/* 1/2 */
+	L'¾',	"34",	/* 3/4 */
+	L'¿',	"??",	/* spanish initial ? */
+	L'À',	"A`",	/* A grave */
+	L'Á',	"A'",	/* A acute */
+	L'Â',	"A^",	/* A circumflex */
+	L'Ã',	"A~",	/* A tilde */
+	L'Ä',	"A\"",	/* A dieresis */
+	L'Ä',	"A:",	/* A dieresis */
+	L'Å',	"Ao",	/* A circle */
+	L'Å',	"AO",	/* A circle */
+	L'Æ',	"Ae",	/* AE ligature */
+	L'Æ',	"AE",	/* AE ligature */
+	L'Ç',	"C,",	/* C cedilla */
+	L'È',	"E`",	/* E grave */
+	L'É',	"E'",	/* E acute */
+	L'Ê',	"E^",	/* E circumflex */
+	L'Ë',	"E\"",	/* E dieresis */
+	L'Ë',	"E:",	/* E dieresis */
+	L'Ì',	"I`",	/* I grave */
+	L'Í',	"I'",	/* I acute */
+	L'Î',	"I^",	/* I circumflex */
+	L'Ï',	"I\"",	/* I dieresis */
+	L'Ï',	"I:",	/* I dieresis */
+	L'Ð',	"D-",	/* Eth */
+	L'Ñ',	"N~",	/* N tilde */
+	L'Ò',	"O`",	/* O grave */
+	L'Ó',	"O'",	/* O acute */
+	L'Ô',	"O^",	/* O circumflex */
+	L'Õ',	"O~",	/* O tilde */
+	L'Ö',	"O\"",	/* O dieresis */
+	L'Ö',	"O:",	/* O dieresis */
+	L'Ö',	"OE",	/* O dieresis */
+	L'Ö',	"Oe",	/* O dieresis */
+	L'×',	"xx",	/* times sign */
+	L'Ø',	"O/",	/* O slash */
+	L'Ù',	"U`",	/* U grave */
+	L'Ú',	"U'",	/* U acute */
+	L'Û',	"U^",	/* U circumflex */
+	L'Ü',	"U\"",	/* U dieresis */
+	L'Ü',	"U:",	/* U dieresis */
+	L'Ü',	"UE",	/* U dieresis */
+	L'Ü',	"Ue",	/* U dieresis */
+	L'Ý',	"Y'",	/* Y acute */
+	L'Þ',	"P|",	/* Thorn */
+	L'Þ',	"Th",	/* Thorn */
+	L'Þ',	"TH",	/* Thorn */
+	L'ß',	"ss",	/* sharp s */
+	L'à',	"a`",	/* a grave */
+	L'á',	"a'",	/* a acute */
+	L'â',	"a^",	/* a circumflex */
+	L'ã',	"a~",	/* a tilde */
+	L'ä',	"a\"",	/* a dieresis */
+	L'ä',	"a:",	/* a dieresis */
+	L'å',	"ao",	/* a circle */
+	L'æ',	"ae",	/* ae ligature */
+	L'ç',	"c,",	/* c cedilla */
+	L'è',	"e`",	/* e grave */
+	L'é',	"e'",	/* e acute */
+	L'ê',	"e^",	/* e circumflex */
+	L'ë',	"e\"",	/* e dieresis */
+	L'ë',	"e:",	/* e dieresis */
+	L'ì',	"i`",	/* i grave */
+	L'í',	"i'",	/* i acute */
+	L'î',	"i^",	/* i circumflex */
+	L'ï',	"i\"",	/* i dieresis */
+	L'ï',	"i:",	/* i dieresis */
+	L'ð',	"d-",	/* eth */
+	L'ñ',	"n~",	/* n tilde */
+	L'ò',	"o`",	/* o grave */
+	L'ó',	"o'",	/* o acute */
+	L'ô',	"o^",	/* o circumflex */
+	L'õ',	"o~",	/* o tilde */
+	L'ö',	"o\"",	/* o dieresis */
+	L'ö',	"o:",	/* o dieresis */
+	L'ö',	"oe",	/* o dieresis */
+	L'÷',	"-:",	/* divide sign */
+	L'ø',	"o/",	/* o slash */
+	L'ù',	"u`",	/* u grave */
+	L'ú',	"u'",	/* u acute */
+	L'û',	"u^",	/* u circumflex */
+	L'ü',	"u\"",	/* u dieresis */
+	L'ü',	"u:",	/* u dieresis */
+	L'ü',	"ue",	/* u dieresis */
+	L'ý',	"y'",	/* y acute */
+	L'þ',	"th",	/* thorn */
+	L'þ',	"p|",	/* thorn */
+	L'ÿ',	"y\"",	/* y dieresis */
+	L'ÿ',	"y:",	/* y dieresis */
+	0,	0,
+};
+
+enum
+{
+	/* controller command byte */
+	Cscs1=		(1<<6),		/* scan code set 1 */
+	Cmousedis=	(1<<5),		/* mouse disable */
+	Ckbddis=	(1<<4),		/* kbd disable */
+	Csf=		(1<<2),		/* system flag */
+	Cmouseint=	(1<<1),		/* mouse interrupt enable */
+	Ckbdint=	(1<<0),		/* kbd interrupt enable */
+};
+
+static uchar ccc;
+
+int
+latin1(int k1, int k2)
+{
+	struct latin *l;
+
+	for(l=latintab; l->l; l++)
+		if(k1==l->c[0] && k2==l->c[1])
+			return l->l;
+	return 0;
+}
+
+/*
+ *  wait for output no longer busy
+ */
+static int
+outready(void)
+{
+	int tries;
+
+	for(tries = 0; (inb(Status) & Outbusy); tries++){
+		if(tries > 500)
+			return -1;
+		delay(2);
+	}
+	return 0;
+}
+
+/*
+ *  wait for input
+ */
+static int
+inready(void)
+{
+	int tries;
+
+	for(tries = 0; !(inb(Status) & Inready); tries++){
+		if(tries > 500)
+			return -1;
+		delay(2);
+	}
+	return 0;
+}
+
+/*
+ *  ask 8042 to enable the use of address bit 20
+ */
+void
+i8042a20(void)
+{
+	outready();
+	outb(Cmd, 0xD1);
+	outready();
+	outb(Data, 0xDF);
+	outready();
+}
+
+/*
+ *  ask 8042 to reset the machine
+ */
+void
+i8042reset(void)
+{
+	ushort *s = (ushort*)(KZERO|0x472);
+	int i, x;
+
+	*s = 0x1234;		/* BIOS warm-boot flag */
+
+	outready();
+	outb(Cmd, 0xFE);	/* pulse reset line (means resend on AT&T machines) */
+	outready();
+
+	/*
+	 *  Pulse it by hand (old somewhat reliable)
+	 */
+	x = 0xDF;
+	for(i = 0; i < 5; i++){
+		x ^= 1;
+		outready();
+		outb(Cmd, 0xD1);
+		outready();
+		outb(Data, x);	/* toggle reset */
+		delay(100);
+	}
+}
+
+/*
+ *  keyboard interrupt
+ */
+int
+kbdintr0(void)
+{
+	int s, c;
+	static int esc1, esc2;
+	static int shift;
+	static int caps;
+	static int ctl;
+	static int num;
+	static int lstate, k1, k2;
+	int keyup;
+
+	/*
+	 *  get status
+	 */
+	s = inb(Status);
+	if(!(s&Inready))
+		return -1;
+
+	/*
+	 *  get the character
+	 */
+	c = inb(Data);
+
+	/*
+	 *  e0's is the first of a 2 character sequence
+	 */
+	if(c == 0xe0){
+		esc1 = 1;
+		return 0;
+	} else if(c == 0xe1){
+		esc2 = 2;
+		return 0;
+	}
+
+	keyup = c&0x80;
+	c &= 0x7f;
+	if(c > sizeof kbtab){
+		print("unknown key %ux\n", c|keyup);
+		kbdchar(0, k1);
+		return 0;
+	}
+
+	if(esc1){
+		c = kbtabesc1[c];
+		esc1 = 0;
+		kbdchar(0, c);
+		return 0;
+	} else if(esc2){
+		esc2--;
+		return 0;
+	} else if(shift)
+		c = kbtabshift[c];
+	else
+		c = kbtab[c];
+
+	if(caps && c<='z' && c>='a')
+		c += 'A' - 'a';
+
+	/*
+	 *  keyup only important for shifts
+	 */
+	if(keyup){
+		switch(c){
+		case Shift:
+			shift = 0;
+			break;
+		case Ctrl:
+			ctl = 0;
+			break;
+		}
+		return 0;
+	}
+
+	/*
+ 	 *  normal character
+	 */
+	if(!(c & Spec)){
+		if(ctl)
+			c &= 0x1f;
+		switch(lstate){
+		case 1:
+			k1 = c;
+			lstate = 2;
+			return 0;
+		case 2:
+			k2 = c;
+			lstate = 0;
+			c = latin1(k1, k2);
+			if(c == 0){
+				kbdchar(0, k1);
+				c = k2;
+			}
+			/* fall through */
+		default:
+			break;
+		}
+	} else {
+		switch(c){
+		case Caps:
+			caps ^= 1;
+			return 0;
+		case Num:
+			num ^= 1;
+			return 0;
+		case Shift:
+			shift = 1;
+			return 0;
+		case Latin:
+			lstate = 1;
+			return 0;
+		case Ctrl:
+			ctl = 1;
+			return 0;
+		}
+	}
+	kbdchar(0, c);
+	return 0;
+}
+
+static void
+kbdintr(Ureg*, void*)
+{
+	while(kbdintr0() == 0)
+		;
+}
+
+static char *initfailed = "kbd init failed\n";
+
+void
+kbdinit(void)
+{
+	int c;
+
+	/* wait for a quiescent controller */
+	while((c = inb(Status)) & (Outbusy | Inready))
+		if(c & Inready)
+			inb(Data);
+
+	/* get current controller command byte */
+	outb(Cmd, 0x20);
+	if(inready() < 0){
+		print("kbdinit: can't read ccc\n");
+		ccc = 0;
+	} else
+		ccc = inb(Data);
+
+	/* enable kbd xfers and interrupts */
+	ccc &= ~Ckbddis;
+	ccc |= Csf | Ckbdint | Cscs1;
+	if(outready() < 0)
+		print(initfailed);
+	outb(Cmd, 0x60);
+	if(outready() < 0)
+		print(initfailed);
+	outb(Data, ccc);
+	if(outready() < 0)
+		print(initfailed);
+
+	setvec(V_KEYBOARD, kbdintr, 0);
+}
--- /dev/null
+++ b/os/boot.original/puma/l.s
@@ -1,0 +1,427 @@
+/*
+ *	File: 		l.s
+ *	Purpose:
+ *  	Puma Board StrongARM 110 Architecture Specific Assembly
+ *	
+ */
+
+#include "mem.h"
+#include "armv4.h"
+#include "puma.h"
+
+#define	DRAMWAIT	100000		/* 3.125μsec per iteration */
+#define	TL750R(r)	(TL750_BASE+(r)*4)
+
+#define	BOOTBASE	0x00200000
+
+TEXT		_main(SB),1,$-4
+	MOVW	R15, R7	/* save PC on entry */
+
+/*
+ * initialise DRAM controller on the TL750 (SDRAM mode)
+ */
+	MOVW	$DRAMWAIT, R0	/* wait 312 ms after reset before touching DRAM */
+dram1:
+	SUB.S	$1, R0
+	BNE	dram1
+
+	MOVW	$TL750R(0x103), R0	/* DMC_DELAY */
+	MOVW	$0x03333333, R1	/* DRAM timing parameters */
+	MOVW	R1, (R0)
+
+	MOVW	$TL750R(0x101), R0	/* DMC_SDRAM */
+	MOVW	$0x03133011, R1	/* SDRAM parameters for Puma */
+	MOVW	R1, (R0)
+
+	MOVW	$DRAMWAIT, R0	/* wait 312 ms for initialisation */
+dram2:
+	SUB.S	$1, R0
+	BNE	dram2
+
+	MOVW		$setR12(SB),R12
+
+/*
+ * copy bootstrap to final location in DRAM
+ */
+	MOVW	R7, baddr(SB)
+	MOVW	$(BOOTBASE+8), R0
+	CMP	R0, R7
+	BEQ	inplace
+	MOVW	$((128*1024)/4), R6
+copyboot:
+	MOVW.P	4(R7), R5
+	MOVW.P	R5, 4(R0)
+	SUB.S	$1, R6
+	BNE	copyboot
+	MOVW	$bootrel(SB), R7
+	MOVW	R7, R15
+
+TEXT	bootrel(SB), $-4
+
+/*
+ * set C environment and invoke main
+ */
+inplace:
+	MOVW		$mach0(SB),R13
+	MOVW		R13,m(SB)
+	ADD			$(MACHSIZE-12),R13
+
+	/* disable MMU activity */
+	BL			mmuctlregr(SB)
+	BIC			$(CpCmmu|CpCDcache|CpCwb|CpCIcache), R0
+	BL			mmuctlregw(SB)
+		
+	BL			main(SB)
+loop:
+	B			loop
+
+TEXT		idle(SB),$0
+	RET
+
+/*
+ *  basic timing loop to determine CPU frequency
+ */
+TEXT aamloop(SB), $-4				/* 3 */
+_aamloop:
+	MOVW		R0, R0			/* 1 */
+	MOVW		R0, R0			/* 1 */
+	MOVW		R0, R0			/* 1 */
+	SUB			$1, R0			/* 1 */
+	CMP			$0, R0			/* 1 */
+	BNE			_aamloop			/* 3 */
+	RET							/* 3 */
+
+/*
+ * Function: setr13( mode, pointer )
+ * Purpose:
+ *		Sets the stack pointer for a particular mode
+ */
+
+TEXT setr13(SB), $-4
+	MOVW		4(FP), R1
+
+	MOVW		CPSR, R2
+	BIC			$PsrMask, R2, R3
+	ORR			R0, R3
+	MOVW		R3, CPSR
+
+	MOVW		R13, R0
+	MOVW		R1, R13
+
+	MOVW		R2, CPSR
+
+	RET
+
+/*
+ * Function: _vundcall
+ * Purpose:
+ *		Undefined Instruction Trap Handler
+ *
+ */
+
+TEXT _vundcall(SB), $-4			
+_vund:
+	MOVM.DB		[R0-R3], (R13)
+	MOVW		$PsrMund, R0
+	B			_vswitch
+
+/*
+ * Function: _vsvccall
+ * Purpose:
+ *		Reset or SWI Handler
+ *
+ */
+
+TEXT _vsvccall(SB), $-4				
+_vsvc:
+	SUB			$12, R13
+	MOVW		R14, 8(R13)
+	MOVW		CPSR, R14
+	MOVW		R14, 4(R13)
+	MOVW		$PsrMsvc, R14
+	MOVW		R14, (R13)
+	B			_vsaveu
+
+/*
+ * Function: _pabcall
+ * Purpose:
+ *		Prefetch Abort Trap Handler
+ *
+ */
+
+TEXT _vpabcall(SB), $-4			
+_vpab:
+	MOVM.DB		[R0-R3], (R13)
+	MOVW		$PsrMabt, R0
+	B			_vswitch
+
+/*
+ * Function: _vdabcall
+ * Purpose:
+ *		Data Abort Trap Handler
+ *
+ */
+
+TEXT _vdabcall(SB), $-4	
+_vdab:
+	MOVM.DB		[R0-R3], (R13)
+	MOVW		$(PsrMabt+1), R0
+	B			_vswitch
+
+/*
+ * Function: _virqcall
+ * Purpose:
+ *		IRQ Trap Handler 
+ *
+ */
+
+TEXT _virqcall(SB), $-4				/* IRQ */
+_virq:
+	MOVM.DB		[R0-R3], (R13)
+	MOVW		$PsrMirq, R0
+	B			_vswitch
+
+/*
+ * Function: _vfiqcall
+ * Purpose:
+ *		FIQ Trap Handler 
+ *
+ */
+
+TEXT _vfiqcall(SB), $-4				/* FIQ */
+_vfiq:
+	MOVM.DB		[R0-R3], (R13)
+	MOVW		$PsrMfiq, R0
+	/* FALLTHROUGH */
+
+_vswitch:					/* switch to svc mode */
+	MOVW		SPSR, R1
+	MOVW		R14, R2
+	MOVW		R13, R3
+
+	MOVW		CPSR, R14
+	BIC			$PsrMask, R14
+	ORR			$(PsrDirq|PsrDfiq|PsrMsvc), R14
+	MOVW		R14, CPSR
+
+	MOVM.DB.W 	[R0-R2], (R13)
+	MOVM.DB	  	(R3), [R0-R3]
+
+_vsaveu:						/* Save Registers */
+	SUB			$4, R13		/* save link */
+	MOVW		R14, (R13)	/* MOVW.W R14,4(R13)*/
+
+	SUB			$8, R13
+
+	MOVW		R13, R14	/* ur->sp */
+	ADD			$(6*4), R14
+	MOVW		R14, 0(R13)
+
+	MOVW		8(SP), R14			/* ur->link */
+	MOVW		R14, 4(SP)
+
+	MOVM.DB.W 	[R0-R12], (R13)	
+	MOVW		R0, R0				/* gratuitous noop */
+
+	MOVW		$setR12(SB), R12		/* static base (SB) */
+	MOVW		R13, R0				/* argument is ureg */
+	SUB			$8, R13				/* space for arg+lnk*/
+	BL			trap(SB)
+
+
+_vrfe:							/* Restore Regs */
+	MOVW		CPSR, R0			/* splhi on return */
+	ORR			$(PsrDirq|PsrDfiq), R0, R1
+	MOVW		R1, CPSR
+	ADD			$(8+4*15), R13		/* [r0-R14]+argument+link */
+	MOVW		(R13), R14			/* restore link */
+	MOVW		8(R13), R0
+	MOVW		R0, SPSR
+	MOVM.DB.S 	(R13), [R0-R14]		/* restore user registers */
+	MOVW		R0, R0				/* gratuitous nop */
+	ADD			$12, R13		/* skip saved link+type+SPSR*/
+	RFE					/* MOVM.IA.S.W (R13), [R15] */
+
+
+/*
+ * Function: splhi
+ * Purpose:
+ *		Disable Interrupts
+ * Returns:
+ *		Previous interrupt state
+ */
+	
+TEXT splhi(SB), $-4					
+	MOVW		CPSR, R0
+	ORR			$(PsrDirq|PsrDfiq), R0, R1
+	MOVW		R1, CPSR
+	RET
+
+/*
+ * Function: spllo
+ * Purpose:
+ *		Enable Interrupts
+ * Returns:
+ *		Previous interrupt state
+ */
+
+TEXT spllo(SB), $-4
+	MOVW		CPSR, R0
+	BIC			$(PsrDirq), R0, R1
+	MOVW		R1, CPSR
+	RET
+
+/*
+ * Function: splx(level)
+ * Purpose:
+ *		Restore interrupt level
+ */
+
+TEXT splx(SB), $-4
+	MOVW		R0, R1
+	MOVW		CPSR, R0
+	MOVW		R1, CPSR
+	RET
+
+/*
+ * Function: islo
+ * Purpose:
+ *		Check if interrupts are enabled
+ *
+ */
+
+TEXT islo(SB), $-4
+	MOVW		CPSR, R0
+	AND			$(PsrDirq), R0
+	EOR			$(PsrDirq), R0
+	RET
+
+/*
+ * Function: cpsrr
+ * Purpose:
+ *		Returns current program status register
+ *
+ */
+
+TEXT cpsrr(SB), $-4
+	MOVW		CPSR, R0
+	RET
+
+/*
+ * Function: spsrr
+ * Purpose:
+ *		Returns saved program status register
+ *
+ */
+
+TEXT spsrr(SB), $-4
+	MOVW		SPSR, R0
+	RET
+
+/*
+ * MMU Operations
+ */
+TEXT mmuctlregr(SB), $-4
+	MRC		CpMMU, 0, R0, C(CpControl), C(0)
+	RET	
+
+TEXT mmuctlregw(SB), $-4
+	MCR		CpMMU, 0, R0, C(CpControl), C(0)
+	MOVW		R0, R0
+	MOVW		R0, R0
+	RET	
+
+/*
+ * Cache Routines
+ */
+
+/*
+ * Function: flushIcache
+ * Purpose:
+ *		Flushes the *WHOLE* instruction cache
+ */
+
+TEXT flushIcache(SB), $-4
+	MCR	 	CpMMU, 0, R0, C(CpCacheCtl), C(5), 0	
+	MOVW		R0,R0							
+	MOVW		R0,R0
+	MOVW		R0,R0
+	MOVW		R0,R0
+	RET
+
+
+
+/*
+ * Function: flushDentry
+ * Purpose:
+ *		Flushes an entry of the data cache
+ */
+
+TEXT flushDentry(SB), $-4
+	MCR		CpMMU, 0, R0, C(CpCacheCtl), C(6), 1
+	RET
+
+/*
+ * Function: drainWBuffer
+ * Purpose:
+ *		Drains the Write Buffer
+ */
+
+TEXT drainWBuffer(SB), $-4
+	MCR		CpMMU, 0, R0, C(CpCacheCtl), C(10), 4	
+	RET
+
+/*
+ * Function: writeBackDC
+ * Purpose:
+ *		Drains the dcache prior to flush
+ */
+
+TEXT writeBackDC(SB), $-4
+	MOVW		$0xE0000000, R0
+	MOVW		$8192, R1
+	ADD		R0, R1
+
+wbflush:
+	MOVW		(R0), R2
+	ADD		$32, R0
+	CMP		R1,R0
+	BNE		wbflush
+	RET
+
+/*
+ * Function: flushDcache(SB)
+ * Purpose:
+ *		Flush the dcache 
+ */
+
+TEXT flushDcache(SB), $-4
+	MCR		CpMMU, 0, R0, C(CpCacheCtl), C(6), 0	
+	RET
+
+/*
+ * Function: writeBackBDC(SB)
+ * Purpose:
+ *		Write back the Baby D-Cache
+ */
+
+TEXT writeBackBDC(SB), $-4		
+	MOVW		$0xE4000000, R0
+	MOVW		$0x200, R1
+	ADD		R0, R1
+
+wbbflush:
+	MOVW		(R0), R2
+	ADD		$32, R0
+	CMP		R1,R0
+	BNE		wbbflush
+	MCR		CpMMU, 0, R0, C(CpCacheCtl), C(10), 4	
+	MOVW		R0,R0								
+	MOVW		R0,R0
+	MOVW		R0,R0
+	MOVW		R0,R0
+	RET
+
+GLOBL	mach0+0(SB), $MACHSIZE
+GLOBL	m(SB), $4
+GLOBL	baddr(SB), $4
--- /dev/null
+++ b/os/boot.original/puma/lib.h
@@ -1,0 +1,107 @@
+/*
+ * functions (possibly) linked in, complete, from libc.
+ */
+
+/*
+ * mem routines
+ */
+extern	void*	memccpy(void*, void*, int, long);
+extern	void*	memset(void*, int, long);
+extern	int	memcmp(void*, void*, long);
+extern	void*	memmove(void*, void*, long);
+extern	void*	memchr(void*, int, long);
+
+/*
+ * string routines
+ */
+extern	char*	strcat(char*, char*);
+extern	char*	strchr(char*, char);
+extern	int	strcmp(char*, char*);
+extern	char*	strcpy(char*, char*);
+extern	char*	strncat(char*, char*, long);
+extern	char*	strncpy(char*, char*, long);
+extern	int	strncmp(char*, char*, long);
+extern	long	strlen(char*);
+extern	char*	strrchr(char*, char);
+extern	char*	strstr(char*, char*);
+
+/*
+ * print routines
+ * 	Fconv isn't used but is defined to satisfy prototypes in libg.h
+ *	that are never called.
+ */
+typedef	struct Fconv Fconv;
+
+extern	char*	donprint(char*, char*, char*, void*);
+extern	int	sprint(char*, char*, ...);
+extern	int	print(char*, ...);
+
+#define	PRINTSIZE	256
+
+/*
+ * one-of-a-kind
+ */
+extern	int	atoi(char*);
+extern	long	strtol(char*, char**, int);
+extern	ulong	strtoul(char*, char**, int);
+extern	char	end[];
+extern 	char edata[];
+
+/*
+ * Syscall data structures
+ */
+
+#define	MORDER	0x0003	/* mask for bits defining order of mounting */
+#define	MREPL	0x0000	/* mount replaces object */
+#define	MBEFORE	0x0001	/* mount goes before others in union directory */
+#define	MAFTER	0x0002	/* mount goes after others in union directory */
+#define	MCREATE	0x0004	/* permit creation in mounted directory */
+#define	MMASK	0x0007	/* all bits on */
+
+#define	OREAD	0	/* open for read */
+#define	OWRITE	1	/* write */
+#define	ORDWR	2	/* read and write */
+#define	OEXEC	3	/* execute, == read but check execute permission */
+#define	OTRUNC	16	/* or'ed in (except for exec), truncate file first */
+#define	OCEXEC	32	/* or'ed in, close on exec */
+#define	ORCLOSE	64	/* or'ed in, remove on close */
+
+#define	NCONT	0	/* continue after note */
+#define	NDFLT	1	/* terminate after note */
+
+typedef struct Qid	Qid;
+typedef struct Dir	Dir;
+typedef struct Waitmsg	Waitmsg;
+
+#define	ERRLEN	64
+#define	DIRLEN	116
+#define	NAMELEN	28
+
+struct Qid
+{
+	ulong	path;
+	ulong	vers;
+};
+
+struct Dir
+{
+	char	name[NAMELEN];
+	char	uid[NAMELEN];
+	char	gid[NAMELEN];
+	Qid	qid;
+	ulong	mode;
+	long	atime;
+	long	mtime;
+	ulong	length;
+	short	type;
+	short	dev;
+};
+
+struct Waitmsg
+{
+	int	pid;		/* of loved one */
+	int	status;		/* unused; a placeholder */
+	ulong	time[3];	/* of loved one */
+	char	msg[ERRLEN];
+};
+#define	nelem(x)	(sizeof(x)/sizeof((x)[0]))
--- /dev/null
+++ b/os/boot.original/puma/main.c
@@ -1,0 +1,552 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+#include "dosfs.h"
+
+typedef struct Type Type;
+typedef struct Medium Medium;
+typedef struct Mode Mode;
+
+enum {
+	Dany		= -1,
+	Nmedia		= 16,
+
+	/* DS1 switch options */
+	Sflashfs		= 1<<0,	/* take local fs from flash */
+	Snotflash		= 1<<1,	/* don't boot from flash */
+};
+
+enum {					/* type */
+	Tflash,
+	Tether,
+	Thard,
+
+	Tany		= -1,
+};
+
+enum {					/* flag and name */
+	Fnone		= 0x00,
+
+	Fdos		= 0x01,
+	Ndos		= 0x00,
+	Fboot		= 0x02,
+	Nboot		= 0x01,
+	Fbootp		= 0x04,
+	Nbootp		= 0x02,
+	Fflash		= 0x08,
+	NName		= 0x03,
+
+	Fany		= Fbootp|Fboot|Fdos|Fflash,
+
+	Fini		= 0x10,
+	Fprobe		= 0x80,
+};
+
+enum {					/* mode */
+	Mauto		= 0x00,
+	Mlocal		= 0x01,
+	Manual		= 0x02,
+	NMode		= 0x03,
+};
+
+typedef struct Type {
+	int	type;
+	char	*cname;
+	int	flag;
+	int	(*init)(void);
+	long	(*read)(int, void*, long);
+	long	(*seek)(int, long);
+	Partition* (*setpart)(int, char*);
+	char*	name[NName];
+
+	int	mask;
+	Medium*	media;
+} Type;
+
+typedef struct Medium {
+	Type*	type;
+	int	flag;
+	Partition* partition;
+	Dos;
+
+	Medium*	next;
+} Medium;
+
+typedef struct Mode {
+	char*	name;
+	int	mode;
+} Mode;
+
+static Type types[] = {
+	{	Tflash, "flash",
+		Fflash,
+		flashinit, 0, 0, 0,
+		{ 0, "F", 0, }
+	},
+	{	Tether, "ether",
+		Fbootp,
+		etherinit, 0, 0, 0,
+		{ 0, 0, "e", },
+	},
+	{	Thard, "ata",
+		Fini|Fboot|Fdos,
+		0, 0, 0, 0,		/* not used now, will be later with PCMCIA */
+		{ "hd", "h", 0, },
+	},
+	{-1},
+};
+
+static Medium media[Nmedia];
+static Medium *curmedium = media;
+
+static Mode modes[NMode+1] = {
+	[Mauto]		{ "auto",   Mauto,  },
+	[Mlocal]	{ "local",  Mlocal, },
+	[Manual]	{ "manual", Manual, },
+};
+
+static char *inis[] = {
+	"inferno/inferno.ini",
+	"inferno.ini",
+	"plan9/plan9.ini",
+	"plan9.ini",
+	0,
+};
+char **ini;
+void	printversion(void);
+
+static int
+parse(char *line, int *type, int *flag, int *dev, char *file)
+{
+	Type *tp;
+	char buf[2*NAMELEN], *v[4], *p;
+	int i;
+
+	strcpy(buf, line);
+	switch(getcfields(buf, v, 4, "!")){
+
+	case 3:
+		break;
+
+	case 2:
+		v[2] = "";
+		break;
+
+	default:
+		return 0;
+	}
+
+	*flag = 0;
+	for(tp = types; tp->cname; tp++){
+		for(i = 0; i < NName; i++){
+
+			if(tp->name[i] == 0 || strcmp(v[0], tp->name[i]))
+				continue;
+			*type = tp->type;
+			*flag |= 1<<i;
+
+			if((*dev = strtoul(v[1], &p, 0)) == 0 && p == v[1])
+				return 0;
+		
+			strcpy(file, v[2]);
+		
+			return 1;
+		}
+	}
+
+	return 0;
+
+}
+
+static int
+boot(Medium *mp, int flag, char *file)
+{
+	Dosfile df;
+	char ixdos[128], *p;
+
+	if(flag & Fbootp){
+		sprint(BOOTLINE, "%s!%d", mp->type->name[Nbootp], mp->dev);
+		return bootp(mp->dev, file);
+	}
+
+	if(flag & Fflash){
+		if(mp->flag & Fflash && flashbootable(0))
+			flashboot(mp->dev);
+	}
+
+	if(flag & Fboot){
+
+		if(mp->flag & Fini){
+			(*mp->type->setpart)(mp->dev, "disk");
+			plan9ini(mp, nil);
+		}
+		if(file == 0 || *file == 0)
+			file = mp->partition->name;
+		(*mp->type->setpart)(mp->dev, file);
+		sprint(BOOTLINE, "%s!%d!%s", mp->type->name[Nboot], mp->dev, file);
+		return plan9boot(mp->dev, mp->seek, mp->read);
+	}
+
+	if(flag & Fdos){
+		if(mp->type->setpart)
+			(*mp->type->setpart)(mp->dev, "disk");
+		if(mp->flag & Fini)
+			plan9ini(mp, nil);
+		if(file == 0 || *file == 0){
+			strcpy(ixdos, *ini);
+			if(p = strrchr(ixdos, '/'))
+				p++;
+			else
+				p = ixdos;
+			strcpy(p, "infernopuma");
+			if(dosstat(mp, ixdos, &df) <= 0)
+				return -1;
+		}
+		else
+			strcpy(ixdos, file);
+		sprint(BOOTLINE, "%s!%d!%s", mp->type->name[Ndos], mp->dev, ixdos);
+		return dosboot(mp, ixdos);
+	}
+
+	return -1;
+}
+
+static Medium*
+allocm(Type *tp)
+{
+	Medium **l;
+
+	if(curmedium >= &media[Nmedia])
+		return 0;
+
+	for(l = &tp->media; *l; l = &(*l)->next)
+		;
+	*l = curmedium++;
+	return *l;
+}
+
+Medium*
+probe(int type, int flag, int dev)
+{
+	Type *tp;
+	int dombr, i, start;
+	Medium *mp;
+	Dosfile df;
+	Partition *pp;
+
+	for(tp = types; tp->cname; tp++){
+		if(type != Tany && type != tp->type || tp->init == 0)
+			continue;
+
+		if(flag != Fnone){
+			for(mp = tp->media; mp; mp = mp->next){
+				if((flag & mp->flag) && (dev == Dany || dev == mp->dev))
+					return mp;
+			}
+		}
+		if((tp->flag & Fprobe) == 0){
+			tp->flag |= Fprobe;
+			tp->mask = (*tp->init)();
+		}
+
+		for(i = 0; tp->mask; i++){
+			if((tp->mask & (1<<i)) == 0)
+				continue;
+			tp->mask &= ~(1<<i);
+
+			if((mp = allocm(tp)) == 0)
+				continue;
+
+			mp->dev = i;
+			mp->flag = tp->flag;
+			mp->seek = tp->seek;
+			mp->read = tp->read;
+			mp->type = tp;
+
+			if(mp->flag & Fboot){
+				if((mp->partition = (*tp->setpart)(i, "boot")) == 0)
+					mp->flag &= ~Fboot;
+				if((mp->flag & Fflash) == 0)
+					(*tp->setpart)(i, "disk");
+			}
+
+			if(mp->flag & Fdos){
+				start = 0;
+				dombr = 1;
+				if(mp->type->setpart){
+					if(pp = (*mp->type->setpart)(i, "dos")){
+						if(start = pp->start)
+							dombr = 0;
+					}
+					(*tp->setpart)(i, "disk");
+				}
+				if(dosinit(mp, start, dombr) < 0)
+					mp->flag &= ~(Fini|Fdos);
+				else
+					print("dos init failed\n");
+			}
+
+			if(mp->flag & Fini){
+				mp->flag &= ~Fini;
+				for(ini = inis; *ini; ini++){
+					if(dosstat(mp, *ini, &df) <= 0)
+						continue;
+					mp->flag |= Fini;
+					break;
+				}
+			}
+
+			if((flag & mp->flag) && (dev == Dany || dev == i))
+				return mp;
+		}
+	}
+
+	return 0;
+}
+
+static void
+pause(void)
+{
+	long d;
+	for(d=0; d<10000000; d++)
+		;
+	USED(d);
+}
+
+static void
+flash(int n)
+{
+	int i;
+
+	if(n <= 0)
+		return;
+	for(i=0; i<n-1; i++) {
+		led(1);
+		pause();
+		led(0);
+		pause();
+	}
+	led(1);
+	pause();pause();pause();
+	led(0);
+	pause();pause();pause();
+}
+
+void
+main(void)
+{
+	Medium *mp;
+	int dev, flag, i, mode, tried, type, options;
+	char def[2*NAMELEN], file[2*NAMELEN], line[80], *p;
+	Type *tp;
+
+	memset(edata, 0, end-edata );			/* clear the BSS */		
+	pumainit();
+
+	machinit();
+	meminit();
+	trapinit();
+	consinit();	/* screen and keyboard initially */
+//	screeninit();
+	alarminit();
+	clockinit();
+	printversion();
+
+	spllo();
+	options = optionsw();
+
+
+	mp = 0;
+	for(tp = types; tp->cname; tp++){
+		if(tp->type == Tether)
+			continue;
+		if((mp = probe(tp->type, Fini, Dany)) && (mp->flag & Fini)){
+			plan9ini(mp, nil);
+			break;
+		}
+	}
+
+	if(mp == 0 || (mp->flag & Fini) == 0)
+		plan9ini(nil, flashconfig(0));
+
+	//consinit();	/* establish new console location */
+
+	if((options & Snotflash) == 0 && flashbootable(0)){
+		print("Flash boot\n");
+		flashboot(0);
+	}
+
+	tried = 0;
+	mode = Mauto;
+	p = getconf("bootfile");
+	flag = 0;
+
+	if(p != 0) {
+		mode = Manual;
+		for(i = 0; i < NMode; i++){
+			if(strcmp(p, modes[i].name) == 0){
+				mode = modes[i].mode;
+				goto done;
+			}
+		}
+		if(parse(p, &type, &flag, &dev, file) == 0) {
+			print("Bad bootfile syntax: %s\n", p);
+			goto done;
+		}
+		mp = probe(type, flag, dev);
+		if(mp == 0) {
+			print("Cannot access device: %s\n", p);
+			goto done;
+		}
+		tried = boot(mp, flag, file);
+	}
+done:
+	if(tried == 0 && mode != Manual){
+		flag = Fany;
+		if(mode == Mlocal)
+			flag &= ~Fbootp;
+		if(options & Snotflash)
+			flag &= ~Fflash;
+		if((mp = probe(Tany, flag, Dany)) != 0)
+			boot(mp, flag & mp->flag, 0);
+	}
+
+	def[0] = 0;
+	probe(Tany, Fnone, Dany);
+
+	flag = 0;
+	for(tp = types; tp->cname; tp++){
+		for(mp = tp->media; mp; mp = mp->next){
+			if(flag == 0){
+				flag = 1;
+				print("Boot devices:");
+			}
+
+			if(mp->flag & Fbootp)
+				print(" %s!%d", mp->type->name[Nbootp], mp->dev);
+			if(mp->flag & Fdos)
+				print(" %s!%d", mp->type->name[Ndos], mp->dev);
+			if(mp->flag & Fflash || mp->flag & Fboot)
+				print(" %s!%d", mp->type->name[Nboot], mp->dev);
+		}
+	}
+	if(flag)
+		print("\n");
+
+	for(;;){
+		if(getstr("boot from", line, sizeof(line), def) >= 0){
+			if(parse(line, &type, &flag, &dev, file)){
+				if(mp = probe(type, flag, dev))
+					boot(mp, flag, file);
+			}
+		}
+		def[0] = 0;
+	}
+}
+
+void
+machinit(void)
+{
+	memset(m, 0, sizeof(*m));
+	m->delayloop = 20000;
+}
+
+void
+printversion(void)
+{
+	print("StrongARM SA-110 ");
+	print("%d MHz system\n", m->speed);
+	print("\n");
+{extern long baddr; print("%8.8lux\n", baddr);}
+}
+
+int
+optionsw()
+{
+	return 0;
+}
+
+int
+getcfields(char* lp, char** fields, int n, char* sep)
+{
+	int i;
+
+	for(i = 0; lp && *lp && i < n; i++){
+		while(*lp && strchr(sep, *lp) != 0)
+			*lp++ = 0;
+		if(*lp == 0)
+			break;
+		fields[i] = lp;
+		while(*lp && strchr(sep, *lp) == 0){
+			if(*lp == '\\' && *(lp+1) == '\n')
+				*lp++ = ' ';
+			lp++;
+		}
+	}
+
+	return i;
+}
+
+static	Map	memv[512];
+static	RMap	rammap = {"physical memory"};
+
+void
+meminit(void)
+{
+	ulong e;
+
+	mapinit(&rammap, memv, sizeof(memv));
+	e = PADDR(end);
+	mapfree(&rammap, e, 4*1024*1024-e);
+}
+
+void*
+ialloc(ulong n, int align)
+{
+	ulong a;
+	int s;
+
+	if(align <= 0)
+		align = 4;
+	s = splhi();
+	a = mapalloc(&rammap, 0, n, align);
+	splx(s);
+	if(a == 0)
+		panic("ialloc");
+	return memset(KADDR(a), 0, n);
+}
+
+void*
+malloc(ulong n)
+{
+	ulong *p;
+
+	n = ((n+sizeof(int)-1)&~(sizeof(int)-1))+2*sizeof(int);
+	p = ialloc(n, sizeof(int));
+	*p++ = 0xcafebeef;
+	*p++ = n;
+	return p;
+}
+
+void
+free(ulong *p)
+{
+	int s;
+
+	if(p){
+		if(*(p -= 2) != 0xcafebeef)
+			panic("free");
+		s = splhi();
+		mapfree(&rammap, (ulong)p, p[1]);
+		splx(s);
+	}
+}
+
+void
+sched(void)
+{
+}
--- /dev/null
+++ b/os/boot.original/puma/mem.h
@@ -1,0 +1,38 @@
+/*
+ * Memory and machine-specific definitions.  Used in C and assembler.
+ */
+
+/*
+ * Sizes
+ */
+#define	BI2BY		8			/* bits per byte */
+#define	BI2WD		32			/* bits per word */
+#define	BY2WD		4			/* bytes per word */
+#define	BY2PG		4096			/* bytes per page */
+#define	WD2PG		(BY2PG/BY2WD)		/* words per page */
+#define	PGSHIFT		12			/* log(BY2PG) */
+#define	PGROUND(s)	(((s)+(BY2PG-1))&~(BY2PG-1))
+
+#define	MAXMACH		1			/* max # cpus system can run */
+
+/*
+ * Time
+ */
+#define	HZ		(20)				/* clock frequency */
+#define	MS2HZ		(1000/HZ)			/* millisec per clock tick */
+#define	TK2SEC(t)	((t)/HZ)			/* ticks to seconds */
+#define	TK2MS(t)	((((ulong)(t))*1000)/HZ)	/* ticks to milliseconds */
+#define	MS2TK(t)	((((ulong)(t))*HZ)/1000)	/* milliseconds to ticks */
+
+/*
+ * Fundamental addresses
+ */
+
+/*
+ *  Address spaces
+ *
+ *  Kernel is at 0x00008000
+ */
+#define	KZERO		0x00000000		/* base of kernel address space */
+#define	KTZERO		KZERO			/* first address in kernel text */
+#define	MACHSIZE	4096
--- /dev/null
+++ b/os/boot.original/puma/mkfile
@@ -1,0 +1,71 @@
+<../../../mkconfig
+
+SYSTARG=Inferno
+OBJTYPE=arm
+<$ROOT/mkfiles/mkfile-$SYSTARG-$OBJTYPE	#set vars based on target system
+
+TARGET=${O}boot
+OBJ=\
+	l.$O\
+	div.$O\
+	8250.$O\
+	alarm.$O\
+	bootp.$O\
+	clock.$O\
+	console.$O\
+	conf.$O\
+	dosboot.$O\
+	donprint.$O\
+	ether.$O\
+	ether8900.$O\
+	flash.$O\
+	kbd.$O\
+	main.$O\
+	plan9boot.$O\
+	puma.$O\
+	qio.$O\
+	rmap.$O\
+	trap.$O\
+	zqs.$O
+
+HFILES=\
+	lib.h\
+	mem.h\
+	dat.h\
+	fns.h\
+	io.h\
+	boot.h\
+	armv4.h\
+	puma.h\
+
+CFLAGS=-w -I.
+LFLAGS=-H1 -R4 -T0x00200000 -E_main #-a
+#LFLAGS=-H1 -R4 -T0x00008080 -E_main #-a
+#LFLAGS = -H1 -R4 -T0xa00000c0 -E_main #-a
+
+all:V:	$TARGET
+
+$TARGET:	$OBJ
+	$LD -o $target $LFLAGS -l $prereq -lc
+	ls -l $target
+
+installall:V:	install
+install:V:	bb $TARGET
+	cp $TARGET /arm
+
+%.$O:	%.s
+	$AS $stem.s
+
+%.$O:	%.c
+	$CC $CFLAGS $stem.c
+
+%.$O:	$HFILES
+
+clock.$O floppy.$O trap.$O:	ureg.h
+conf.$O dosboot.$O main.$O:	dosfs.h
+ether.$O ether2000.$O ether509.$O ether8003.$O ether8390.$O:	ether.h
+bootp.$O:	ip.h
+
+clean:
+	rm -f *.[$OS] [$OS].out y.tab.? y.debug y.output $TARGET
+
--- /dev/null
+++ b/os/boot.original/puma/outb.c
@@ -1,0 +1,20 @@
+typedef	unsigned short	ushort;
+typedef	unsigned char	uchar;
+
+enum {
+	IsaIOBase		= 0xf0000000,
+	IsaMemBase	= 0xe0000000,
+
+	IOBase		= 0x300,
+	MemBase		= 0xc0000,
+
+	TxFrame		= 0x0a00,
+};
+
+#define	regw(reg, val)		*((ushort *)IsaMemBase + MemBase + (reg)) = (val)
+
+void
+main(void)
+{
+	regw(TxFrame, 0x1234);
+}
--- /dev/null
+++ b/os/boot.original/puma/plan9boot.c
@@ -1,0 +1,93 @@
+#include	"u.h"
+#include	"lib.h"
+#include	"mem.h"
+#include	"dat.h"
+#include	"fns.h"
+
+char *premature = "premature EOF\n";
+
+/*
+ *  read in a segment
+ */
+static long
+readseg(int dev, long (*read)(int, void*, long), long len, long addr)
+{
+	char *a;
+	long n, sofar;
+
+	a = (char *)addr;
+	for(sofar = 0; sofar < len; sofar += n){
+		n = 8*1024;
+		if(len - sofar < n)
+			n = len - sofar;
+		n = (*read)(dev, a + sofar, n);
+		if(n <= 0)
+			break;
+		print(".");
+	}
+	return sofar;
+}
+
+/*
+ *  boot
+ */
+int
+plan9boot(int dev, long (*seek)(int, long), long (*read)(int, void*, long))
+{
+	long n;
+	long addr;
+	void (*b)(void);
+	Exec *ep;
+
+	if((*seek)(dev, 0) < 0)
+		return -1;
+
+	/*
+	 *  read header
+	 */
+	ep = (Exec *) ialloc(sizeof(Exec), 0);
+	n = sizeof(Exec);
+	if(readseg(dev, read, n, (ulong) ep) != n){
+		print(premature);
+		return -1;
+	}
+	if(GLLONG(ep->magic) != E_MAGIC){
+		print("bad magic 0x%lux not a plan 9 executable!\n", GLLONG(ep->magic));
+		return -1;
+	}
+
+	/*
+	 *  read text
+	 */
+	addr = PADDR(GLLONG(ep->entry));
+	n = GLLONG(ep->text);
+	print("%d", n);
+	if(readseg(dev, read, n, addr) != n){
+		print(premature);
+		return -1;
+	}
+
+	/*
+	 *  read data (starts at first page after kernel)
+	 */
+	addr = PGROUND(addr+n);
+	n = GLLONG(ep->data);
+	print("+%d", n);
+	if(readseg(dev, read, n, addr) != n){
+		print(premature);
+		return -1;
+	}
+
+	/*
+	 *  bss and entry point
+	 */
+	print("+%d\nstart at 0x%lux\n", GLLONG(ep->bss), GLLONG(ep->entry)); uartwait();
+
+	/*
+	 *  Go to new code. It's up to the program to get its PC relocated to
+	 *  the right place.
+	 */
+	b = (void (*)(void))(PADDR(GLLONG(ep->entry)));
+	(*b)();
+	return 0;
+}
--- /dev/null
+++ b/os/boot.original/puma/puma.c
@@ -1,0 +1,123 @@
+#include "boot.h"
+
+//#define GPIO1_PORT		0x0078
+//#define GPIO2_PORT		0x0079
+
+#define GPIO2_N_LED1_DIAG	0x10	/* diagnostic led mask */
+
+#define	HARI2_N_LED1		0x01
+#define	HARI2_N_LED2		0x02
+#define	HARI2_N_LED3		0x04
+#define	HARI2_N_LED4		0x08
+
+/*
+ * National Semiconductor PC87306 Super I/O
+ */
+enum {
+	Index=		0x398,	/* sio configuration index register */
+	Data=		0x399,	/* sio configuration data register */
+};
+
+
+// byte flip table for Puma SuperIO port permuted as 76543210 -> 01234567
+unsigned char
+byteflip[] = {
+	0x00,0x80,0x40,0xC0,0x20,0xA0,0x60,0xE0,0x10,0x90,0x50,0xD0,0x30,0xB0,0x70,0xF0,
+	0x08,0x88,0x48,0xC8,0x28,0xA8,0x68,0xE8,0x18,0x98,0x58,0xD8,0x38,0xB8,0x78,0xF8,
+	0x04,0x84,0x44,0xC4,0x24,0xA4,0x64,0xE4,0x14,0x94,0x54,0xD4,0x34,0xB4,0x74,0xF4,
+	0x0C,0x8C,0x4C,0xCC,0x2C,0xAC,0x6C,0xEC,0x1C,0x9C,0x5C,0xDC,0x3C,0xBC,0x7C,0xFC,
+	0x02,0x82,0x42,0xC2,0x22,0xA2,0x62,0xE2,0x12,0x92,0x52,0xD2,0x32,0xB2,0x72,0xF2,
+	0x0A,0x8A,0x4A,0xCA,0x2A,0xAA,0x6A,0xEA,0x1A,0x9A,0x5A,0xDA,0x3A,0xBA,0x7A,0xFA,
+	0x06,0x86,0x46,0xC6,0x26,0xA6,0x66,0xE6,0x16,0x96,0x56,0xD6,0x36,0xB6,0x76,0xF6,
+	0x0E,0x8E,0x4E,0xCE,0x2E,0xAE,0x6E,0xEE,0x1E,0x9E,0x5E,0xDE,0x3E,0xBE,0x7E,0xFE,
+	0x01,0x81,0x41,0xC1,0x21,0xA1,0x61,0xE1,0x11,0x91,0x51,0xD1,0x31,0xB1,0x71,0xF1,
+	0x09,0x89,0x49,0xC9,0x29,0xA9,0x69,0xE9,0x19,0x99,0x59,0xD9,0x39,0xB9,0x79,0xF9,
+	0x05,0x85,0x45,0xC5,0x25,0xA5,0x65,0xE5,0x15,0x95,0x55,0xD5,0x35,0xB5,0x75,0xF5,
+	0x0D,0x8D,0x4D,0xCD,0x2D,0xAD,0x6D,0xED,0x1D,0x9D,0x5D,0xDD,0x3D,0xBD,0x7D,0xFD,
+	0x03,0x83,0x43,0xC3,0x23,0xA3,0x63,0xE3,0x13,0x93,0x53,0xD3,0x33,0xB3,0x73,0xF3,
+	0x0B,0x8B,0x4B,0xCB,0x2B,0xAB,0x6B,0xEB,0x1B,0x9B,0x5B,0xDB,0x3B,0xBB,0x7B,0xFB,
+	0x07,0x87,0x47,0xC7,0x27,0xA7,0x67,0xE7,0x17,0x97,0x57,0xD7,0x37,0xB7,0x77,0xF7,
+	0x0F,0x8F,0x4F,0xCF,0x2F,0xAF,0x6F,0xEF,0x1F,0x9F,0x5F,0xDF,0x3F,0xBF,0x7F,0xFF
+};
+
+int
+sio_inb(int port)
+{
+	unsigned char b = *(uchar *)IOBADDR(port);
+//	b = byteflip[b];
+	return b&0xff;
+}
+
+void
+sio_outb(int port, int data)
+{
+//	data = byteflip[data];
+	*(uchar *)IOBADDR(port) = data;
+}
+
+static void
+siocfg(int r, int v, int rsv)
+{
+	sio_outb(Index, r);
+	if(rsv)
+		v = (sio_inb(Data)&rsv) | (v&~rsv);
+	sio_outb(Data, v);
+	sio_outb(Data, v);	/* ``write data twice'' */
+}
+
+void
+sioinit(void)
+{
+	/* determine which byte flip is required ... */
+
+	siocfg(SIO_CONFIG_FAR, FAR_LPT_LPTA | FAR_UART1_COM1 | FAR_UART2_COM2, 0);
+	siocfg(SIO_CONFIG_FER,	FER_LPT_ENABLE | FER_UART1_ENABLE | FER_UART2_ENABLE | FER_IDE_ENABLE, 0);
+	siocfg(SIO_CONFIG_KRR,	KRR_KBC_ENABLE | KRR_KBC_MUST_BE_1 | KRR_RTC_ENABLE, 0x50);
+	siocfg(SIO_CONFIG_SCF0,SCF0_GPIO_PORT1_ENABLE | SCF0_GPIO_PORT2_ENABLE, 0xC0);
+
+	/* force UART interrupt pins low, not tristate by setting ienable in MCR (!) */
+	sio_outb(COM1_PORT+UART_MCR, sio_inb(COM1_PORT+UART_MCR)|(1<<3));
+	sio_outb(COM2_PORT+UART_MCR, sio_inb(COM2_PORT+UART_MCR)|(1<<3));
+}
+
+void
+led(int on)
+{
+	int gpio, hari, hbits;
+	int s;
+
+	s = splhi();
+
+	gpio = sio_inb(GPIO2_PORT);
+	if (on)
+		gpio &= ~GPIO2_N_LED1_DIAG;
+	else
+		gpio |= GPIO2_N_LED1_DIAG;
+	sio_outb(GPIO2_PORT, gpio);
+
+	hari = HARI2_INIT;
+	hbits = HARI2_N_LED1|HARI2_N_LED2|HARI2_N_LED3|HARI2_N_LED4;
+	if (on)
+		hari &= ~hbits;
+	else
+		hari |= hbits;
+	*(uchar *)HARI2 = hari;
+
+	
+	splx(s);
+
+}
+
+void
+pumainit(void)
+{
+	/*
+	 * Initialise HARI2 for:
+	 * a) Leds off
+	 * b) No Timer2 aborts
+	 * c) Ethernet on IRQ
+	 */
+	*(uchar *)HARI2 = HARI2_INIT|HARI2_N_LED1|HARI2_N_LED2|HARI2_N_LED3|HARI2_N_LED4;
+	sioinit();
+}
+
--- /dev/null
+++ b/os/boot.original/puma/puma.h
@@ -1,0 +1,435 @@
+/*
+ * Teralogic TL750 - Puma Evaluation Board
+ */
+ 
+/*
+ * Puma addresses
+ */
+#define EPROM_BASE	0x80000000	/* EPROM */
+#define FLASH_BASE	0xa0000000	/* Flash */
+#define TL750_BASE	0xc0000000	/* TL750 registers */
+#define ISAMEM_BASE	0xe0000000	/* ISA memory space */
+#define ISAIO_BASE		0xf0000000	/* ISA I/O space */
+
+#define ISAIO_SHIFT	2
+#define IOBADDR(io_port) (ISAIO_BASE + (io_port << ISAIO_SHIFT))
+
+/* Hardware address register for interrupts (HARI) */
+#define HARI1			0xE2000000 /* Interrupt status on read, User interrupt on write */
+#define HARI2			0xE3000000 /* More interrupt status on read, LEDs on write */	
+#define HARI1_FIQ_MASK	0x92	/* FIQ indicator bits in HARI1, others are IRQ */
+#define HARI2_INIT			0x20	/* No timer2 aborts, Ethernet on IRQ */			
+
+
+
+/*
+ * Interrupt Vectors
+ * corresponding to the HARIx_xxx_IRQ/FIQ bits above. 
+ *
+ * HARI1 interrupts 
+ */
+#define V_LPT				0		/* Parallel port interrupt */
+#define V_NM0			1		/* MPEG Decode Interrupt */
+#define V_NM1			2		/* MPEG Decode Interrupt */
+#define V_COM2			3		/* Serial Port 2 Interrupt */
+#define V_COM1			4       	/* Serial Port 1 Interrupt */
+#define V_MOUSE			5		/* Mouse Interrupt */
+#define V_KEYBOARD		6		/* Keyboard Interrupt */
+#define V_ETHERNET		7		/* Ethernet Interrupt */
+/* 
+ * HARI2 interrupts 
+ */
+#define V_TIMER0			8		/* 82C54 Timer 0 Interrupt */
+#define V_TIMER1			9		/* 82C54 Timer 1 Interrupt */
+#define V_TIMER2			10		/* 82C54 Timer 2 Interrupt */
+#define V_SOFTWARE		11		/* Software Interrupt */
+#define V_IDE				12		/* IDE Hard Drive Interrupt */
+#define V_SMARTCARD		13		/* Smart Card Interrupt */
+#define V_TL750			14		/* TL750 Interrupt */
+								/* Nothing in vector 15 for now */
+#define V_MAXNUM     		15
+
+/*
+ * Definitions for National Semiconductor PC87306 SuperIO configuration
+ */
+#define SIO_CONFIG_INDEX		0x398	/* SuperIO configuration index register */
+#define SIO_CONFIG_DATA			0x399	/* SuperIO configuration data register */
+
+#define SIO_CONFIG_RESET_VAL		0x88	/* Value read from first read of sio_config_index reg after reset */
+/*
+ * PC87306 Configuration Registers (The value listed is the configuration space
+ * index.)
+ */
+#define SIO_CONFIG_FER			0x00	/* Function Enable Register */
+
+#define     FER_LPT_ENABLE				0x01	/* Enable Parallel Port */
+#define     FER_UART1_ENABLE				0x02	/* Enable Serial Port 1 */
+#define     FER_UART2_ENABLE				0x04	/* Enable Serial Port 2 */
+#define     FER_FDC_ENABLE				0x08	/* Enable Floppy Controller */
+#define     FER_FDC_4DRIVE_ENCODING			0x10	/* Select Floppy 4 Drive Encoding */
+#define     FER_FDC_ADDR_ENABLE				0x20	/* Select Floppy Secondary Address */
+								/* 0: [0x3F0..0x3F7] */
+								/* 1: [0x370..0x377] */
+#define     FER_IDE_ENABLE				0x40	/* Enable IDE Controller */
+#define     FER_IDE_ADDR_SELECT				0x80	/* Select IDE Secondary Address */
+								/* 0: [0x1F0..0x1F7,0x3F6,0x3F7] */
+								/* 1: [0x170..0x177,0x376,0x377] */
+
+#define SIO_CONFIG_FAR			0x01	/* Function Address Register */
+
+#define     FAR_LPT_ADDR_MASK				0x03	/* Select LPT Address */
+								/* If (PNP0[4] == 0) then: */
+								/*     0: LPTB [0x378..0x37F] IRQ5/7 */
+								/*     1: LPTA [0x3BC..0x3BE] IRQ7 */
+								/*     2: LPTC [0x278..0x27F] IRQ5 */
+								/*     3: Reserved */
+								/* Else ignored. */
+#define	FAR_LPT_LPTB	0	/* 0: LPTB 0x378 irq5/7 */
+#define	FAR_LPT_LPTA	1	/* 1: LPTA 0x3BC irq 7 */
+#define	FAR_LPT_LPTC	2	/* 2: LPTC 0x278 irq5 */
+
+#define     FAR_UART1_ADDR_MASK				0x0C	/* Select Serial Port 1 Address */
+								/* 0: COM1 [0x3F8..0x3FF] */
+								/* 1: COM2 [0x2F8..0x2FF] */
+								/* 2: COM3 (See FAR[7:6]) */
+								/* 3: COM4 (See FAR[7:6]) */
+#define	FAR_UART1_COM1		0x00 
+#define     FAR_UART2_ADDR_MASK				0x30	/* Select Serial Port 2 Address */
+								/* 0: COM1 [0x3F8..0x3FF] */
+								/* 1: COM2 [0x2F8..0x2FF] */
+								/* 2: COM3 (See FAR[7:6]) */
+								/* 3: COM4 (See FAR[7:6]) */
+#define	FAR_UART2_COM2		0x10
+#define     FAR_EXTENDED_UART_ADDR_SELECT		0xC0	/* Extended Address Selects */
+								/*    COM3@IRQ4,  COM4@IRQ3 */
+								/* 0: COM3@0x3E8, COM4@0x2E8 */
+								/* 1: COM3@0x338, COM4@0x238 */
+								/* 2: COM3@0x2E8, COM4@0x2E0 */
+								/* 3: COM3@0x220, COM4@0x228 */
+
+#define SIO_CONFIG_PTR			0x02	/* Power & Test Register */
+
+#define     PTR_POWER_DOWN				0x01	/* Power down all enabled functions */
+#define     PTR_LPT_IRQ_SELECT				0x08	/* Select LPT IRQ if (FAR[1:0] == 0) */
+								/* 0: IRQ5 */
+								/* 1: IRQ7 */
+#define     PTR_UART1_TEST_MODE				0x10	/* Set serial port 1 test mode */
+#define     PTR_UART2_TEST_MODE				0x20	/* Set serial port 2 test mode */
+#define     PTR_LOCK_CONFIGURATION			0x40	/* Prevent all further config writes */
+								/* Only a RESET will reenable writes */
+#define     PTR_LPT_EXTENDED_MODE_SELECT		0x80	/* Select Mode if not EPP/ECP */
+								/* 0: Compatible Mode */
+								/* 1: Extended Mode */
+
+#define SIO_CONFIG_FCR			0x03	/* Function Control Register */
+							/* WARNING: The FCR register must be written */
+							/* using read-modify-write! */
+#define     FCR_TDR_MODE_SELECT				0x01	/* ? (floppy/tape) */
+#define     FCR_IDE_DMA_ENABLE				0x02	/* Enable IDE DMA mode */
+#define     FCR_EPP_ZERO_WAIT_STATE			0x40	/* Enable EPP zero wait state */
+
+#define SIO_CONFIG_PCR			0x04	/* Printer Control Register */
+
+#define     PCR_EPP_ENABLE				0x01	/* Enable parallel port EPP mode */
+#define     PCR_EPP_VERSION_SELECT			0x02	/* Select version of EPP mode */
+								/* 0: Version 1.7 */
+								/* 1: Version 1.9 (IEEE 1284) */
+#define     PCR_ECP_ENABLE				0x04	/* Enable parallel port ECP mode */
+#define     PCR_ECP_POWER_DOWN_CLOCK_ENABLE		0x08	/* Enable clock in power-down state */
+								/* 0: Freeze ECP clock */
+								/* 1: Run ECP clock */
+#define     PCR_ECP_INT_POLARITY_CONTROL		0x20	/* Interrupt polarity control */
+								/* 0: Level high or negative pulse */
+								/* 1: Level low or positive pulse */
+#define     PCR_ECP_INT_IO_CONTROL			0x40	/* Interrupt I/O control */
+								/* WARNING: Slightly safer to choose */
+								/* open drain if you don't know the */
+								/* exact requirements of the circuit */
+								/* 0: Totem-pole output */
+								/* 1: Open drain output */
+#define     PCR_RTC_RAM_WRITE_DISABLE			0x80	/* Disable writes to RTC RAM */
+								/* 0: Enable writes */
+								/* 1: Disable writes */
+
+#define SIO_CONFIG_KRR			0x05	/* Keyboard & RTC Control Register */
+							/* WARNING: The KRR register must be written */
+							/* with a 1 in bit 2, else the KBC will not */
+							/* work! */
+#define     KRR_KBC_ENABLE				0x01	/* Enable keyboard controller */
+#define     KRR_KBC_SPEED_CONTROL			0x02	/* Select clock divisor if !KRR[7] */
+								/* 0: Divide by 3 */
+								/* 1: Divide by 2 */
+#define	    KRR_KBC_MUST_BE_1				0x04	/* Reserved: This bit must be 1! */
+#define     KRR_RTC_ENABLE				0x08	/* Enable real time clock */
+#define     KRR_RTC_RAMSEL				0x20	/* Select RTC RAM bank */
+#define     KRR_KBC_CLOCK_SOURCE_SELECT			0x80	/* Select clock source */
+								/* 0: Use X1 clock source */
+								/* 1: Use SYSCLK clock source */
+
+#define SIO_CONFIG_PMC			0x06	/* Power Management Control Register */
+
+#define     PMC_IDE_TRISTATE_CONTROL			0x01	/* ? (power management) */
+#define     PMC_FDC_TRISTATE_CONTROL			0x02	/* ? (power management) */
+#define     PMC_UART1_TRISTATE_CONTROL			0x04	/* ? (power management) */
+#define     PMC_SELECTIVE_LOCK				0x20	/* ? (power management) */
+#define     PMC_LPT_TRISTATE_CONTROL			0x40	/* ? (power management) */
+
+#define SIO_CONFIG_TUP			0x07	/* Tape, UARTS & Parallel Port Register */
+
+#define     TUP_EPP_TIMEOUT_INT_ENABLE			0x04	/* Enable EPP timeout interrupts */
+
+#define SIO_CONFIG_SID			0x08	/* Super I/O Identification Register */
+
+#define     SID_ID_MASK					0xF8	/* Super I/O ID field */
+#define         SID_ID_PC87306					0x70	/* PC87306 ID value */
+
+#define SIO_CONFIG_ASC			0x09	/* Advanced Super I/O Config Register */
+							/* WARNING: The ASC register must be written */
+							/* with a 0 in bit 3! */
+							/* WARNING: The ASC register resets to 1 in */
+							/* bit 7 (PC/AT mode)! */
+#define     ASC_VLD_MASK				0x03	/* ? (floppy/tape) */
+#define     ASC_ENHANCED_TDR_SUPPORT			0x04	/* ? (floppy/tape) */
+#define     ASC_MUST_BE_0				0x08	/* Reserved: Must be 0 */
+#define     ASC_ECP_CNFGA				0x20	/* ? */
+#define     ASC_DENSEL_POLARITY_BIT			0x40	/* ? (floppy/tape) */
+#define     ASC_SYSTEM_OPERATION_MODE			0x80	/* Select system operation mode */
+								/* 0: PS/2 mode */
+								/* 1: PC/AT mode */
+
+#define SIO_CONFIG_CS0LA			0x0A	/* Chip Select 0 Low Address Register */
+
+#define SIO_CONFIG_CS0CF			0x0B	/* Chip Select 0 Configuration Register */
+							/* WARNING: The CS0CF register must be */
+							/* written with a 1 in bit 7! */
+#define     CS0CF_CS0_DECODE				0x08	/* Select CS0 decode sensitivity */
+								/* 0: Decode full 16-bit address */
+								/* 1: Decode only bits 15 thru 12 */
+#define     CS0CF_CS0_WRITE_ENABLE			0x10	/* Enable CS0 on write cycles */
+#define     CS0CF_CS0_READ_ENABLE			0x20	/* Enable CS0 on read cycles */
+#define     CS0CF_CS0_MUST_BE_1				0x80	/* Reserved: Must be 1 */
+
+#define SIO_CONFIG_CS1LA			0x0C	/* Chip Select 1 Low Address Register */
+
+#define SIO_CONFIG_CS1CF			0x0D	/* Chip Select 1 Configuration Register */
+
+#define     CS1CF_CS1_DECODE				0x08	/* Select CS1 decode sensitivity */
+								/* 0: Decode full 16-bit address */
+								/* 1: Decode only bits 15 thru 12 */
+#define     CS1CF_CS1_WRITE_ENABLE			0x10	/* Enable CS1 on write cycles */
+#define     CS1CF_CS1_READ_ENABLE			0x20	/* Enable CS1 on read cycles */
+
+#define SIO_CONFIG_IRC			0x0E	/* Infrared Configuration Register */
+
+#define     IRC_UART2_INTERFACE_MODE			0x01	/* Select UART2 interface mode */
+								/* 0: Normal (modem) mode */
+								/* 1: IR mode */
+#define     IRC_IR_FULL_DUPLEX				0x02	/* Select IR duplex mode */
+								/* 0: Full duplex mode */
+								/* 1: Half duplex mode */
+#define     IRC_ENCODED_IR_TRANSMITTER_DRIVE		0x10	/* IR transmitter drive control */
+								/* 0: IRTX active for 1.6usec */
+								/* 1: IRTX active for 3/16 baud */
+#define     IRC_ENCODED_IR_MODE				0x20	/* IR encode mode */
+								/* 0: Encoded mode */
+								/* 1: Non-encoded mode */
+
+#define SIO_CONFIG_GPBA			0x0F	/* GP I/O Port Base Address Config Register */
+
+#define SIO_CONFIG_CS0HA			0x10	/* Chip Select 0 High Address Register */
+
+#define SIO_CONFIG_CS1HA			0x11	/* Chip Select 1 High Address Register */
+
+#define SIO_CONFIG_SCF0			0x12	/* Super I/O Configuration Register 0 */
+
+#define     SCF0_RTC_RAM_LOCK				0x01	/* Lock (1) will prevent all further */
+								/* accesses to RTC RAM.  Only RESET */
+								/* return this bit to a 0. */
+#define     SCF0_IRQ1_12_LATCH_ENABLE			0x02	/* Enable IRQ1/IRQ12 latching */
+#define     SCF0_IRQ12_TRISTATE				0x04	/* IRQ12 tri-state control */
+								/* 0: Use quasi-bidirectional buffer */
+								/* 1: Tri-state IRQ12 */
+#define     SCF0_UART2_TRISTATE				0x08	/* Force UART2/IR outputs to */
+								/* tri-state when disabled */
+#define     SCF0_GPIO_PORT1_ENABLE			0x10	/* Enable GPIO port 1 */
+#define     SCF0_GPIO_PORT2_ENABLE			0x20	/* Enable GPIO port 2 */
+
+#define SIO_CONFIG_SCF1			0x18	/* Super I/O Configuration Register 1 */
+
+#define     SCF1_REPORTED_ECP_DMA			0x06	/* Reported ECP DMA number */
+								/* 0: Jumpered 8-bit DMA */
+								/* 1: DMA channel 1 */
+								/* 2: DMA channel 2 */
+								/* 3: DMA channel 3 */
+#define     SCF1_SELECTED_ECP_DMA			0x08	/* Selected ECP DMA pins */
+								/* 0: PDRQ0 & PDACK0 */
+								/* 1: PDRQ1 & PDACK1 */
+#define     SCF1_SCRATCH_BITS				0xC0	/* ? */
+
+#define SIO_CONFIG_LPTBA			0x19	/* LPT Base Address */
+
+#define SIO_CONFIG_PNP0			0x1B	/* Plug & Play Configuration Register 0 */
+
+#define     PNP0_LPT_INT_SELECT_CONTROL			0x10	/* LPT IRQ select control */
+								/* 0: IRQ selected by FAR[1:0] */
+								/* 1: IRQ selected by PNP0[5] */
+#define     PNP0_LPT_INT_MAPPING			0x20	/* LPT IRQ mapping */
+								/* 0: IRQ5 */
+								/* 1: IRQ7 */
+#define     PNP0_LPTA_BASE_ADDR_SELECT			0x40	/* LPTA base address */
+								/* 0: Always 0x3BC */
+								/* 1: Selected by LPTBA[7:0] */
+
+#define SIO_CONFIG_PNP1			0x1C	/* Plug & Play Configuration Register 1 */
+
+#define     PNP1_UARTS_INT_SELECT_CONTROL		0x01	/* UART interrupt select control */
+								/* 0: Use FAR[3:2] & FAR[5:4] */
+								/* 1: Use PNP1[2] & PNP1[6] */
+#define     PNP1_UART1_INT_MAPPING			0x04	/* UART1 interrupt mapping */
+								/* 0: IRQ3 */
+								/* 1: IRQ4 */
+#define     PNP1_UART2_INT_MAPPING			0x40	/* UART2 interrupt mapping */
+								/* 0: IRQ3 */
+								/* 1: IRQ4 */
+/*---------------------------------------------------------------------------*/
+
+/*
+ * Definitions for the SuperIO UART.
+ */
+#define COM1_PORT       0x3f8   
+#define COM2_PORT       0x2f8
+
+/*
+ * Register offsets.
+ */
+#define UART_RX    		0      /* Receive port, read only */
+#define UART_TX         0      /* transmit port, write only */
+#define UART_IER        1      /* Interrupt enable, read/write */
+#define UART_IIR        2      /* Interrupt id, read only */
+#define UART_FIFO_CONTROL 2    /* FIFO control, write only */
+#define UART_LCR        3      /* Line control register */
+#define UART_MCR      	4      /* Modem control register */
+#define UART_LSR        5      /* Line Status register */
+#define UART_MSR        6      /* Modem Status register */
+
+/* with the DLAB bit set, the first two registers contain the baud rate */
+#define UART_DLLSB      0
+#define UART_DLMSB      1
+
+/*
+ * Line control register 
+ */
+#define LCR_DB          3      /* Data bits in transmission (0 = 5, 1 = 6, 2 = 7, 3 = 8) */
+#define LCR_SB          4      /* Stop bit */
+#define LCR_PE          8      /* Parity enable */
+#define LCR_EP          16     /* Even parity */
+#define LCR_SP          32     /* Stick parity */
+#define LCR_BC          64     /* break control */
+#define LCR_DLAB        128    /* Divisor latch access bit */
+
+
+/*
+ *  Modem Control register
+ */
+#define MCR_DTR			1	/* Data Terminal Ready */
+#define MCR_RTS			2	/* Request To Send */
+#define MCR_OUT1		4	/* Out1 (not used) */
+#define MCR_IRQ_ENABLE  8	/* Enable IRQ */
+#define MCR_LOOP		16	/* Loopback mode */
+
+/*
+ * Line status bits.
+ */
+#define    LSR_DR     0x01        /* Data ready                         */
+#define    LSR_OE     0x02        /* Overrun error                      */
+#define    LSR_PE     0x04        /* Parity error                       */
+#define    LSR_FE     0x08        /* Framing error                      */
+#define    LSR_BI     0x10        /* Break interrupt                    */
+#define    LSR_THRE   0x20        /* Transmitter holding register empty */
+#define    LSR_TEMT   0x40        /* Transmitter empty                  */
+#define    LSR_FFE    0x80        /* Receiver FIFO error                */
+
+#define LSR_ERROR       (LSR_OE | LSR_PE | LSR_FE) 
+
+/*
+ * Interrupt Identification register (IIR)
+ */
+#define IIR_IP          1     /* No Interrupt pending */
+#define IIR_RECEIVE_LINE_STATUS	6 /* Overrun, Parity, Framing erros, Break */
+#define IIR_RDA			4     /* Receive data available */
+#define IIR_FIFO_FLAG	8     /* FIFO flag */
+#define IIR_FIFO_TIMEOUT (IIR_RDA+IIR_FIFO_FLAG)  /* Got data some time ago, but FIFO time out */
+#define IIR_THRE		2     /* Transmitter holding register empty. */
+#define IIR_MS			0     /* CTS, DSR, RING, DCD changed */
+#define IIR_HPIP        6     /* Highest priority interrupt pending */
+
+/*
+ * Interrupt enable register (IER)
+ */
+#define IER_RDA         1     /* Received data available */
+#define IER_THRE        2     /* Transmitter holding register empty */
+#define IER_RLS         4     /* Receiver line status */
+#define IER_MS          8     /* Modem status */
+
+/*
+ * PC87306 Parallel I/O Port
+ */
+#define LPT1_PORT		0x03BC
+
+/*
+ * PC87306 General Purpose I/O Ports
+ */
+#define GPIO1_PORT		0x0078
+#define GPIO2_PORT		0x0079
+
+/*
+ * PC87306 IDE Port
+ */
+#define IDE_PORT_1		0x01F0
+#define IDE_PORT_2		0x03F6
+#define IDE_PORT_3		0x03F7
+
+/*
+ * PC87306 Floppy Port
+ */
+#define FDC_PORT		0x03F0
+
+/*
+ * PC87306 Real Time Clock/battery backed up RAM port
+ */
+#define RTC_INDEX_PORT		0x0070
+#define RTC_DATA_PORT		0x0071
+
+/*
+ * Offsets in RTC memory (RAMSEL = 0)
+ */
+#define RTC_SECONDS			0
+#define	RTC_SECONDS_ALARM	1
+#define RTC_MINUTES			2
+#define RTC_MINUTES_ALARM	3
+#define RTC_HOURS			4
+#define RTC_HOURS_ALARM		5
+#define RTC_DAY_OF_WEEK		6
+#define RTC_DAY_OF_MONTH	7
+#define RTC_MONTH			8
+#define RTC_YEAR			9
+#define RTC_CONTROL_A		0xA
+#define RTC_CONTROL_B		0xB
+#define RTC_CONTROL_C		0xC
+#define RTC_CONTROL_D		0xD
+
+#define RTC_NVRAM0_START	0xE
+#define RTC_NVRAM0_SIZE		114
+#define RTC_NVRAM1_START	0
+#define RTC_NVRAM1_SIZE		128
+#define	RTC_NVRAM_SIZE		(RTC_NVRAM0_SIZE+RTC_NVRAM1_SIZE)
+
+#define RTC_PWNVRAM_START	0x38	/* Start of protected NVRAM */
+#define RTC_PWNVRAM_SIZE	8		/* Size of protected NVRAM */
+
+
+/*
+ * PC87306 Keyboard controller ports
+ */
+#define KEYBD_DATA_PORT		0x0060
+#define KEYBD_CTRL_PORT 	0x0064
--- /dev/null
+++ b/os/boot.original/puma/qio.c
@@ -1,0 +1,128 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+struct Queue {
+	Block*	first;
+	Block*	last;
+	void	(*kick)(void*);
+	void*	arg;
+	long	len;
+};
+
+Block *
+iallocb(int n)
+{
+	Block *b;
+
+	b = (Block*)malloc(sizeof(Block)+n);
+	b->data = (uchar*)b + sizeof(Block);
+	b->rp = b->wp = b->data;
+	b->lim = b->data + n;
+	b->next = 0;
+	b->magic = 0xcafebee0;
+	return b;
+}
+
+void
+freeb(Block *b)
+{
+	if(b){
+		if(b->magic != 0xcafebee0)
+			panic("freeb");
+		b->magic = 0;
+		b->next = (Block*)0xdeadbabe;
+		free(b);
+	}
+}
+
+Queue *
+qopen(int limit, int msg, void (*kick)(void*), void *arg)
+{
+	Queue *q;
+
+	USED(limit, msg);
+	q = (Queue*)malloc(sizeof(Queue));
+	q->first = q->last = 0;
+	q->kick = kick;
+	q->arg = arg;
+	q->len = 0;
+	return q;
+}
+
+Block *
+qget(Queue *q)
+{
+	int s;
+	Block *b;
+
+	s = splhi();
+	if((b = q->first) != 0){
+		q->first = b->next;
+		b->next = 0;
+		q->len -= BLEN(b);
+		if(q->len < 0)
+			panic("qget");
+	}
+	splx(s);
+	return b;
+}
+
+void
+qbwrite(Queue *q, Block *b)
+{
+	int s;
+
+	s = splhi();
+	b->next = 0;
+	if(q->first == 0)
+		q->first = b;
+	else
+		q->last->next = b;
+	q->last = b;
+	q->len += BLEN(b);
+	splx(s);
+	if(q->kick)
+		q->kick(q->arg);
+}
+
+long
+qlen(Queue *q)
+{
+	return q->len;
+}
+
+int
+qbgetc(Queue *q)
+{
+	Block *b;
+	int s, c;
+
+	c = -1;
+	s = splhi();
+	while(c < 0 && (b = q->first) != nil){
+		if(b->rp < b->wp){
+			c = *b->rp++;
+			q->len--;
+		}
+		if(b->rp >= b->wp){
+			q->first = b->next;
+			b->next = nil;
+		}
+	}
+	splx(s);
+	return c;
+}
+
+void
+qbputc(Queue *q, int c)
+{
+	Block *b;
+
+	b = iallocb(1);
+	*b->wp++ = c;
+	qbwrite(q, b);
+}
--- /dev/null
+++ b/os/boot.original/puma/rmap.c
@@ -1,0 +1,104 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+
+void
+mapinit(RMap *rmap, Map *map, int size)
+{
+	lock(rmap);
+	rmap->map = map;
+	rmap->mapend = map+(size/sizeof(Map));
+	unlock(rmap);
+}
+
+void
+mapfree(RMap* rmap, ulong addr, int size)
+{
+	Map *mp;
+	ulong t;
+
+	if(size <= 0)
+		return;
+
+	lock(rmap);
+	for(mp = rmap->map; mp->addr <= addr && mp->size; mp++)
+		;
+
+	if(mp > rmap->map && (mp-1)->addr+(mp-1)->size == addr){
+		(mp-1)->size += size;
+		if(addr+size == mp->addr){
+			(mp-1)->size += mp->size;
+			while(mp->size){
+				mp++;
+				(mp-1)->addr = mp->addr;
+				(mp-1)->size = mp->size;
+			}
+		}
+	}
+	else{
+		if(addr+size == mp->addr && mp->size){
+			mp->addr -= size;
+			mp->size += size;
+		}
+		else do{
+			if(mp >= rmap->mapend){
+				print("mapfree: %s: losing 0x%uX, %d\n",
+					rmap->name, addr, size);
+				break;
+			}
+			t = mp->addr;
+			mp->addr = addr;
+			addr = t;
+			t = mp->size;
+			mp->size = size;
+			mp++;
+		}while(size = t);
+	}
+	unlock(rmap);
+}
+
+ulong
+mapalloc(RMap* rmap, ulong addr, int size, int align)
+{
+	Map *mp;
+	ulong maddr, oaddr;
+
+	lock(rmap);
+	for(mp = rmap->map; mp->size; mp++){
+		maddr = mp->addr;
+
+		if(addr){
+			if(maddr > addr)
+				continue;
+			if(addr+size > maddr+mp->size)
+				break;
+			maddr = addr;
+		}
+
+		if(align > 0)
+			maddr = ((maddr+align-1)/align)*align;
+		if(mp->addr+mp->size-maddr < size)
+			continue;
+
+		oaddr = mp->addr;
+		mp->addr = maddr+size;
+		mp->size -= maddr-oaddr+size;
+		if(mp->size == 0){
+			do{
+				mp++;
+				(mp-1)->addr = mp->addr;
+			}while((mp-1)->size = mp->size);
+		}
+
+		unlock(rmap);
+		if(oaddr != maddr)
+			mapfree(rmap, oaddr, maddr-oaddr);
+
+		return maddr;
+	}
+	unlock(rmap);
+
+	return 0;
+}
--- /dev/null
+++ b/os/boot.original/puma/squeeze.h
@@ -1,0 +1,34 @@
+
+/*
+ * squeezed file format:
+ *	Sqhdr
+ *	original Exec header
+ *	two Squeeze tables
+ *	squeezed segment
+ *	unsqueezed segment, if any
+ */
+#define	SQMAGIC	(ulong)0xFEEF0F1E
+
+typedef struct Sqhdr Sqhdr;
+struct Sqhdr {
+	uchar	magic[4];	/* SQMAGIC */
+	uchar	text[4];	/* squeezed length of text (excluding tables) */
+	uchar	data[4];	/* squeezed length of data (excluding tables) */
+	uchar	asis[4];	/* length of unsqueezed segment */
+	uchar	toptxt[4];	/* value for 0 encoding in text */
+	uchar	topdat[4];	/* value for 0 encoding in data */
+	uchar	sum[4];	/* simple checksum of unsqueezed data */
+	uchar	flags[4];
+};
+#define	SQHDRLEN	(8*4)
+
+/*
+ * certain power instruction types are rearranged by sqz
+ * so as to move the variable part of the instruction word to the
+ * low order bits.  note that the mapping is its own inverse.
+ */
+#define	QREMAP(X)\
+	switch((X)>>26){\
+	case 19: case 31: case 59: case 63:\
+		(X) = (((X) & 0xFC00F801) | (((X)>>15)&0x7FE) | (((X)&0x7FE)<<15));\
+	}
--- /dev/null
+++ b/os/boot.original/puma/sum.c
@@ -1,0 +1,13 @@
+int
+sum(int a, int b, int c)
+{
+	return a+b+c;
+}
+
+void
+main(void)
+{
+	int s;
+
+	s = sum(1, 2, 3);
+}
--- /dev/null
+++ b/os/boot.original/puma/trap.c
@@ -1,0 +1,190 @@
+#include "boot.h"
+
+typedef struct IrqEntry {
+		void	(*r)(Ureg*, void*);
+		void 	*a;				
+} IrqEntry;
+
+IrqEntry Irq[V_MAXNUM+1];
+
+static void dumpstk(ulong *);
+void dumpregs(Ureg* ureg);
+
+void
+setvec(int v, void (*f)(Ureg*, void*), void* a)
+{
+	if(v < 0 || v >= V_MAXNUM)
+		panic("setvec: interrupt source %d out of range\n", v);
+	Irq[v].r = f;
+	Irq[v].a = a;
+}
+
+ulong irqstack[64];
+ulong fiqstack[64];
+ulong abtstack[64];
+ulong undstack[64];
+
+static void
+safeintr(Ureg*, void *a)
+{
+	int v = (int)a;
+//	print("spurious interrupt %d\n", v);
+	USED(v);
+}
+
+void
+trapinit(void)
+{
+	int offset;
+	ulong op;
+	int v;
+	int s;
+
+	s = splhi();
+
+	/* set up stacks for various exceptions */ 
+	setr13(PsrMirq, irqstack+nelem(irqstack)-1);
+	setr13(PsrMfiq, fiqstack+nelem(fiqstack)-1);
+	setr13(PsrMabt, abtstack+nelem(abtstack)-1);
+	setr13(PsrMund, undstack+nelem(undstack)-1);
+
+	for(v = 0; v <= V_MAXNUM; v++) {
+		Irq[v].r = safeintr;
+		Irq[v].a = (void *)v;
+	}
+
+	/* Reset Exception */
+	offset = ((((ulong) _vsvccall) - 0x0)-8) >> 2;
+	op = ( 0xea << 24 ) | offset;
+	*((ulong *) 0x0) = op; 
+
+	/* Undefined Instruction Exception */
+	offset = ((((ulong) _vundcall) - 0x4)-8) >> 2;
+	op = ( 0xea << 24 ) | offset;
+	*((ulong *) 0x4) = op;
+
+	/* SWI Exception */
+	offset = ((((ulong) _vsvccall) - 0x8)-8) >> 2;
+	op = ( 0xea << 24 ) | offset;
+	*((ulong *) 0x8) = op;
+
+	/* Prefetch Abort Exception */
+	offset = ((((ulong) _vpabcall) - 0xc)-8) >> 2;
+	op = ( 0xea << 24 ) | offset;
+	*((ulong *) 0xc) = op;
+
+	/* Data Abort Exception */
+	offset = ((((ulong) _vdabcall) - 0x10)-8) >> 2;
+	op = ( 0xea << 24 ) | offset;
+	*((ulong *) 0x10) = op;
+
+	/* IRQ Exception */
+ 	offset = ((((ulong) _virqcall) - 0x18)-8) >> 2;
+	op = ( 0xea << 24 ) | offset;
+	*((ulong *) 0x18) = op;
+
+	/* FIQ Exception */
+ 	offset = ((((ulong) _vfiqcall) - 0x1c)-8) >> 2;
+	op = ( 0xea << 24 ) | offset;
+	*((ulong *) 0x1c) = op;
+
+
+	flushIcache();
+	writeBackDC();
+	flushDcache();
+	flushIcache();
+	drainWBuffer();
+
+	splx(s);
+}
+
+/*
+ *  trap is called splhi().
+ */
+
+void
+trap(Ureg* ureg)
+{
+	ushort mask;
+	IrqEntry *ip;
+
+	/*
+	 * All interrupts/exceptions should be resumed at ureg->pc-4,
+	 * except for Data Abort which resumes at ureg->pc-8.
+	 */
+	ureg->pc -= 4;
+
+	switch(ureg->type) {
+	case PsrMirq:				/* Interrupt Request */
+		mask = *(uchar*)HARI1 | ((*(uchar*)HARI2) << 8);
+		ip = Irq;
+		while (mask != 0) {
+			if(mask&1)
+				ip->r(ureg, ip->a);
+			ip++;
+			mask >>= 1;
+		}
+		break;
+
+	case PsrMfiq:					/* FIQ */
+		mask = *(uchar*)HARI1 & HARI1_FIQ_MASK;
+		ip = Irq;
+		while (mask != 0) {
+			if(mask&1)
+				ip->r(ureg, ip->a);
+			ip++;
+			mask >>= 1;
+		}
+		break;
+
+	case PsrMund:			/* Undefined instruction */
+		dumpregs(ureg);
+		panic("Undefined Instruction Exception\n");
+		break;
+
+	case PsrMsvc:				/* Jump through 0 or SWI  */
+		dumpregs(ureg);
+		panic("SVC/SWI Exception\n");
+		break;
+
+	case PsrMabt:					/* Prefetch abort */
+		ureg->pc -= 4;
+		/* FALLTHROUGH */
+
+	case PsrMabt+1:	{				/* Data abort */
+		uint far =0;
+		uint fsr =0;
+
+		USED(far,fsr);
+		fsr = 0;	/*mmuregr(CpFSR);*/
+		far = 0;	/*mmuregr(CpFAR);	*/
+		if (ureg->type == PsrMabt)
+			print("Prefetch Abort/");
+		print("Data Abort\n");
+		
+		print("Data Abort: FSR %8.8uX FAR %8.8uX\n", fsr, far);
+		/* FALLTHROUGH */
+	}
+	default:
+		dumpregs(ureg);
+		panic("exception %uX\n", ureg->type);
+		break;
+	}
+
+	splhi();
+}
+
+void
+dumpregs(Ureg* ureg)
+{
+	print("PSR %8.8uX type %2.2uX PC %8.8uX LINK %8.8uX\n",
+		ureg->psr, ureg->type, ureg->pc, ureg->link);
+	print("R14 %8.8uX R13 %8.8uX R12 %8.8uX R11 %8.8uX R10 %8.8uX\n",
+		ureg->r14, ureg->r13, ureg->r12, ureg->r11, ureg->r10);
+	print("R9  %8.8uX R8  %8.8uX R7  %8.8uX R6  %8.8uX R5  %8.8uX\n",
+		ureg->r9, ureg->r8, ureg->r7, ureg->r6, ureg->r5);
+	print("R4  %8.8uX R3  %8.8uX R2  %8.8uX R1  %8.8uX R0  %8.8uX\n",
+		ureg->r4, ureg->r3, ureg->r2, ureg->r1, ureg->r0);
+	print("Stack is at: %8.8uX\n", ureg);
+/*	print("CPSR %8.8uX SPSR %8.8uX\n", cpsrr(), spsrr());*/
+}
--- /dev/null
+++ b/os/boot.original/puma/ureg.h
@@ -1,0 +1,22 @@
+typedef struct Ureg {
+	uint	r0;
+	uint	r1;
+	uint	r2;
+	uint	r3;
+	uint	r4;
+	uint	r5;
+	uint	r6;
+	uint	r7;
+	uint	r8;
+	uint	r9;
+	uint	r10;
+	uint	r11;
+	uint	r12;
+	uint	r13;
+	uint	r14;
+	uint	link;
+	uint	type;
+	uint	psr;
+//	uint	sp;
+	uint	pc;
+} Ureg;
--- /dev/null
+++ b/os/boot.original/puma/zqs.c
@@ -1,0 +1,216 @@
+#include "boot.h"
+#include "squeeze.h"
+
+#define	EXECHDRLEN	(8*4)
+
+typedef struct Squeeze Squeeze;
+struct Squeeze {
+	int	n;
+	ulong	tab[7*256];
+};
+
+#define	GET4(p)	(((((((p)[0]<<8)|(p)[1])<<8)|(p)[2])<<8)|(p)[3])
+
+/*
+ * for speed of unsqueezing from Flash, certain checks are
+ * not done inside the loop (as they would be in the unsqueeze program zqs),
+ * but instead the checksum is expected to catch corrupted files.
+ * in fact the Squeeze array bounds can't be exceeded in practice
+ * because the tables are always full for a squeezed kernel.
+ */
+enum {
+	QFLAG = 1,	/* invert powerpc-specific code transformation */
+	CHECK = 0,	/* check precise bounds in Squeeze array (otherwise checksum detects error) */
+};
+
+static	ulong	chksum;
+static	int	rdtab(Block*, Squeeze*, int);
+static	ulong*	unsqueeze(ulong*, uchar*, uchar*, Squeeze*, Squeeze*, ulong);
+static	uchar*	unsqzseg(uchar*, Block*, long, long, char*);
+static	Alarm*	unsqzal;
+
+int
+issqueezed(uchar *b)
+{
+	return GET4(b) == SQMAGIC? GET4(b+SQHDRLEN): 0;
+}
+
+static void
+unsqzdot(void*)
+{
+	unsqzal = alarm(500, unsqzdot, nil);
+	print(".");
+}
+
+long
+unsqueezef(Block *b, ulong *entryp)
+{
+	uchar *loada, *wp;
+	ulong toptxt, topdat, oldsum;
+	long asis, nst, nsd;
+	Sqhdr *sqh;
+	Exec *ex;
+
+	if(BLEN(b) < SQHDRLEN+EXECHDRLEN)
+		return -1;
+	sqh = (Sqhdr*)b->rp;
+	if(GET4(sqh->magic) != SQMAGIC)
+		return -1;
+	chksum = 0;
+	toptxt = GET4(sqh->toptxt);
+	topdat = GET4(sqh->topdat);
+	oldsum = GET4(sqh->sum);
+	asis = GET4(sqh->asis);
+	nst = GET4(sqh->text);
+	nsd = GET4(sqh->data);
+	b->rp += SQHDRLEN;
+	ex = (Exec*)b->rp;
+	if(GET4(ex->magic) != E_MAGIC){
+		print("zqs: not StrongARM executable\n");
+		return -1;
+	}
+	*entryp = GET4(ex->entry);
+	b->rp += EXECHDRLEN;
+	loada = KADDR(PADDR(*entryp));
+	wp = unsqzseg(loada, b, nst, toptxt, "text");
+	if(wp == nil){
+		print("zqs: format error\n");
+		return -1;
+	}
+	if(nsd){
+		wp = (uchar*)PGROUND((ulong)wp);
+		wp = unsqzseg(wp, b, nsd, topdat, "data");
+		if(wp == nil){
+			print("zqs: format error\n");
+			return -1;
+		}
+	}
+	if(asis){
+		memmove(wp, b->rp, asis);
+		wp += asis;
+		b->rp += asis;
+	}
+	if(chksum != oldsum){
+		print("\nsqueezed kernel: checksum error: %8.8lux need %8.8lux\n", chksum, oldsum);
+		return -1;
+	}
+	return wp-loada;
+}
+
+static uchar *
+unsqzseg(uchar *wp, Block *b, long ns, long top, char *what)
+{
+	static Squeeze sq3, sq4;
+
+	print("unpack %s %8.8lux %lud:", what, wp, ns);
+	if(ns == 0)
+		return wp;
+	if(rdtab(b, &sq3, 0) < 0)
+		return nil;
+	if(rdtab(b, &sq4, 8) < 0)
+		return nil;
+	if(BLEN(b) < ns){
+		print(" **size error\n");
+		return nil;
+	}
+	unsqzal = alarm(500, unsqzdot, nil);
+	wp = (uchar*)unsqueeze((ulong*)wp, b->rp, b->rp+ns, &sq3, &sq4, top);
+	cancel(unsqzal);
+	unsqzal = nil;
+	print("\n");
+	if(wp == nil){
+		print("zqs: corrupt squeezed data stream\n");
+		return nil;
+	}
+	b->rp += ns;
+	return wp;
+}
+
+static ulong*
+unsqueeze(ulong *wp, uchar *rp, uchar *ep, Squeeze *sq3, Squeeze *sq4, ulong top)
+{
+	ulong nx, csum;
+	int code, n;
+
+	if(QFLAG){
+		QREMAP(top);	/* adjust top just once, outside the loop */
+	}
+	csum = chksum;
+	while(rp < ep){
+		/* no function calls within this loop for speed */
+		code = *rp;
+		rp++;
+		n = 0;
+		nx = code>>4;
+		do{
+			if(nx == 0){
+				nx = top;
+			}else{
+				if(nx==1){
+					nx = (((((rp[3]<<8)|rp[2])<<8)|rp[1])<<8)|rp[0];
+					rp += 4;
+				}else if(nx <= 8){	/* 2 to 8 */
+					nx = ((nx-2)<<8) | rp[0];
+					if(CHECK && nx >= sq4->n)
+						return nil;	/* corrupted file */
+					nx = sq4->tab[nx] | rp[1];
+					rp += 2;
+				}else{	/* 9 to 15 */
+					nx = ((nx-9)<<8) | rp[0];
+					if(CHECK && nx >= sq3->n)
+						return nil;	/* corrupted file */
+					nx = sq3->tab[nx];
+					rp++;
+				}
+				if(rp > ep)
+					return nil;	/* corrupted file */
+				if(QFLAG){
+					QREMAP(nx);
+				}
+			}
+			*wp = nx;
+			wp++;
+			csum += nx;
+			nx = code & 0xF;
+		}while(++n == 1);
+	}
+	chksum = csum;
+	return wp;
+}
+
+static int
+rdtab(Block *b, Squeeze *sq, int shift)
+{
+	uchar *p, *ep;
+	ulong v, w;
+	int i;
+
+	if(BLEN(b) < 2)
+		return -1;
+	i = (b->rp[0]<<8) | b->rp[1];
+	if(1)
+		print(" T%d", i);
+	b->rp += 2;
+	if((i -= 2) > 0){
+		if(BLEN(b) < i)
+			return -1;
+	}
+	sq->n = 0;
+	p = b->rp;
+	ep = b->rp+i;
+	b->rp += i;
+	v = 0;
+	while(p < ep){
+		w = 0;
+		do{
+			if(p >= ep)
+				return -1;
+			w = (w<<7) | (*p & 0x7F);
+		}while(*p++ & 0x80);
+		v += w;
+		if(0)
+			print("%d %8.8lux %8.8lux\n", sq->n, v, w);
+		sq->tab[sq->n++] = v<<shift;
+	}
+	return 0;
+}
--- /dev/null
+++ b/os/boot.original/rpcg/NOTICE
@@ -1,0 +1,3 @@
+Inferno® Copyright © 1996-1999 Lucent Technologies Inc.  All rights reserved.
+PowerPC support Copyright © 1995-1997 C H Forsyth (forsyth@caldo.demon.co.uk).  All rights reserved.
+MPC8xx Inferno PowerPC port Copyright © 1998-2003 Vita Nuova Holdings Limited.  All rights reserved.
--- /dev/null
+++ b/os/boot.original/rpcg/alarm.c
@@ -1,0 +1,123 @@
+#include	"u.h"
+#include	"lib.h"
+#include	"mem.h"
+#include	"dat.h"
+#include	"fns.h"
+#include	"io.h"
+#define	MAXALARM	10
+
+Alarm	alarmtab[MAXALARM];
+
+/*
+ * Insert new into list after where
+ */
+void
+insert(List **head, List *where, List *new)
+{
+	if(where == 0){
+		new->next = *head;
+		*head = new;
+	}else{
+		new->next = where->next;
+		where->next = new;
+	}
+		
+}
+
+/*
+ * Delete old from list.  where->next is known to be old.
+ */
+void
+delete(List **head, List *where, List *old)
+{
+	if(where == 0){
+		*head = old->next;
+		return;
+	}
+	where->next = old->next;
+}
+
+Alarm*
+newalarm(void)
+{
+	int i;
+	Alarm *a;
+
+	for(i=0,a=alarmtab; i < nelem(alarmtab); i++,a++)
+		if(a->busy==0 && a->f==0){
+			a->f = 0;
+			a->arg = 0;
+			a->busy = 1;
+			return a;
+		}
+	panic("newalarm");
+	return 0;	/* not reached */
+}
+
+Alarm*
+alarm(int ms, void (*f)(Alarm*), void *arg)
+{
+	Alarm *a, *w, *pw;
+	ulong s;
+
+	if(ms < 0)
+		ms = 0;
+	s = splhi();
+	a = newalarm();
+	a->dt = MS2TK(ms);
+	a->f = f;
+	a->arg = arg;
+	pw = 0;
+	for(w=m->alarm; w; pw=w, w=w->next){
+		if(w->dt <= a->dt){
+			a->dt -= w->dt;
+			continue;
+		}
+		w->dt -= a->dt;
+		break;
+	}
+	insert(&m->alarm, pw, a);
+	splx(s);
+	return a;
+}
+
+void
+cancel(Alarm *a)
+{
+	a->f = 0;
+}
+
+void
+alarminit(void)
+{
+}
+
+#define NA 10		/* alarms per clock tick */
+void
+checkalarms(void)
+{
+	int i, n, s;
+	Alarm *a;
+	void (*f)(Alarm*);
+	Alarm *alist[NA];
+
+	s = splhi();
+	a = m->alarm;
+	if(a){
+		for(n=0; a && a->dt<=0 && n<NA; n++){
+			alist[n] = a;
+			delete(&m->alarm, 0, a);
+			a = m->alarm;
+		}
+		if(a)
+			a->dt--;
+
+		for(i = 0; i < n; i++){
+			f = alist[i]->f;	/* avoid race with cancel */
+			if(f)
+				(*f)(alist[i]);
+			alist[i]->busy = 0;
+		}
+	}
+	splx(s);
+}
--- /dev/null
+++ b/os/boot.original/rpcg/all.h
@@ -1,0 +1,6 @@
+#include	"u.h"
+#include	"lib.h"
+#include	"dat.h"
+#include	"fns.h"
+#include	"mem.h"
+#include	"io.h"
--- /dev/null
+++ b/os/boot.original/rpcg/archrpcg.c
@@ -1,0 +1,279 @@
+#include	"u.h"
+#include	"lib.h"
+#include	"mem.h"
+#include	"dat.h"
+#include	"fns.h"
+#include	"io.h"
+
+#include	"archrpcg.h"
+#include "etherif.h"
+
+/*
+ * board-specific support for the RPCG RXLite
+ */
+
+enum {
+	SYSMHZ =	66,	/* target frequency */
+
+	/* sccr */
+	RTSEL = IBIT(8),	/* =0, select main oscillator (OSCM); =1, select external crystal (EXTCLK) */
+	RTDIV = IBIT(7),	/* =0, divide by 4; =1, divide by 512 */
+	CRQEN = IBIT(9),	/* =1, switch to high frequency when CPM active */
+	PRQEN = IBIT(10),	/* =1, switch to high frequency when interrupt pending */
+
+	/* plprcr */
+	CSRC = IBIT(21),	/* =0, clock is DFNH; =1, clock is DFNL */
+};
+
+static	char	flashsig[] = "RPXsignature=1.0\nNAME=qbrpcg\nSTART=FFC20100\nVERSION=1.1\n";
+static	char*	geteeprom(char*);
+
+/*
+ * called early in main.c, after machinit:
+ * using board and architecture specific registers, initialise
+ * 8xx registers that need it and complete initialisation of the Mach structure.
+ */
+void
+archinit(void)
+{
+	IMM *io;
+	int mf, t;
+	ulong v;
+
+	v = getimmr() & 0xFFFF;
+	switch(v>>8){
+	case 0x00:	t = 0x86000; break;
+	case 0x20:	t = 0x82300; break;
+	case 0x21:	t = 0x823a0; break;
+	default:	t = 0; break;
+	}
+	m->cputype = t;
+	m->bcsr = KADDR(BCSRMEM);
+	io = m->iomem;
+	m->clockgen = 8*MHz;
+	mf = (io->plprcr >> 20)+1;	/* use timing set by bootstrap */
+	m->cpuhz = m->clockgen*mf;
+	m->bcsr[0] = DisableColTest | DisableFullDplx | DisableUSB | HighSpdUSB | LedOff;	/* first write enables bcsr regs */
+return;
+	io->plprcrk = KEEP_ALIVE_KEY;
+	io->plprcr &= ~CSRC;	/* general system clock is DFNH */
+/*	io->mptpr = 0x0800;	/* memory prescaler = 8 for refresh */
+	/* use memory refresh time set by RPXLite monitor */
+	io->plprcrk = ~KEEP_ALIVE_KEY;
+}
+
+void
+cpuidprint(void)
+{
+	int t, v;
+
+	print("Inferno bootstrap\n");
+	print("PVR: ");
+	t = getpvr()>>16;
+	switch(t){
+	case 0x01:	print("MPC601"); break;
+	case 0x03:	print("MPC603"); break;
+	case 0x04:	print("MPC604"); break;
+	case 0x06:	print("MPC603e"); break;
+	case 0x07:	print("MPC603e-v7"); break;
+	case 0x50:	print("MPC8xx"); break;
+	default:	print("PowerPC version #%x", t); break;
+	}
+	print(", revision #%lux\n", getpvr()&0xffff);
+	print("IMMR: ");
+	v = getimmr() & 0xFFFF;
+	switch(v>>8){
+	case 0x00:	print("MPC860/821"); break;
+	case 0x20:	print("MPC823"); break;
+	case 0x21:	print("MPC823A"); break;
+	default:	print("Type #%lux", v>>8); break;
+	}
+	print(", mask #%lux\n", v&0xFF);
+	print("options: #%lux\n", archoptionsw());
+	print("bcsr: %8.8lux\n", m->bcsr[0]);
+	print("PLPRCR=%8.8lux SCCR=%8.8lux\n", m->iomem->plprcr, m->iomem->sccr);
+	print("%lud MHz system\n", m->cpuhz/MHz);
+	print("\n");
+//print("%s\n", geteeprom("EA"));
+print("BR0=%8.8lux OR0=%8.8lux\n", m->iomem->memc[0].base, m->iomem->memc[0].option);
+print("MPTPR=%8.8lux\n", m->iomem->mptpr);
+}
+
+static	char*	defplan9ini[2] = {
+	/* 860/821 */
+	"ether0=type=SCC port=1 ea=0010ec000051\r\n"
+	"vgasize=640x480x8\r\n"
+	"kernelpercent=40\r\n"
+	"console=0\r\nbaud=9600\r\n",
+
+	/* 823 */
+	"ether0=type=SCC port=2 ea=0010ec000051\r\n"
+	"vgasize=640x480x8\r\n"
+	"kernelpercent=40\r\n"
+	"console=0\r\nbaud=9600\r\n",
+};
+
+char *
+archconfig(void)
+{
+	print("Using default configuration\n");
+	return defplan9ini[MPCMODEL(m->cputype) == 0x823];
+}
+
+/*
+ * provide value for #r/switch (devrtc.c)
+ */
+int
+archoptionsw(void)
+{
+	return (m->bcsr[0]&DipSwitchMask)>>4;
+}
+
+/*
+ * invoked by clock.c:/^clockintr
+ */
+static void
+twinkle(void)
+{
+	if(m->ticks%MS2TK(1000) == 0)
+		m->bcsr[0] ^= LedOff;
+}
+
+void	(*archclocktick)(void) = twinkle;
+
+/*
+ * for flash.c:/^flashreset
+ * retrieve flash type, virtual base and length and return 0;
+ * return -1 on error (no flash)
+ */
+int
+archflashreset(char *type, void **addr, long *length)
+{
+	if((m->iomem->memc[BOOTCS].base & 1) == 0)
+		return -1;		/* shouldn't happen */
+	strcpy(type, "AMD29F0x0");
+	*addr = KADDR(FLASHMEM);
+	*length = 4*1024*1024;
+	return 0;
+}
+
+int
+archether(int ctlrno, Card *ether)
+{
+	char *ea;
+
+	if(ctlrno > 0)
+		return -1;
+	strcpy(ether->type, "SCC");
+	ether->port = 2;
+	ea = geteeprom("EA");
+	if(ea != nil)
+		parseether(ether->ea, ea);
+	return 1;
+}
+
+/*
+ * enable the clocks for the given SCC ether and reveal them to the caller.
+ * do anything else required to prepare the transceiver (eg, set full-duplex, reset loopback).
+ */
+int
+archetherenable(int cpmid, int *rcs, int *tcs)
+{
+	IMM *io;
+
+	switch(cpmid){
+	default:
+		/* no other SCCs are wired for ether on RPXLite*/
+		return -1;
+
+	case SCC2ID:
+		io = ioplock();
+		m->bcsr[0] |= EnableEnet;
+		io->papar |= SIBIT(6)|SIBIT(4);	/* enable CLK2 and CLK4 */
+		io->padir &= ~(SIBIT(6)|SIBIT(4));
+		*rcs = CLK4;
+		*tcs = CLK2;
+		iopunlock();
+		break;
+	}
+	return 0;
+}
+
+void
+archetherdisable(int id)
+{
+	USED(id);
+	m->bcsr[0] &= ~EnableEnet;
+}
+
+/*
+ * do anything extra required to enable the UART on the given CPM port
+ */
+void
+archenableuart(int id, int irda)
+{
+	USED(id, irda);
+}
+
+/*
+ * do anything extra required to disable the UART on the given CPM port
+ */
+void
+archdisableuart(int id)
+{
+	USED(id);
+}
+
+/*
+ * enable/disable the LCD panel's backlight
+ */
+void
+archbacklight(int on)
+{
+	USED(on);
+}
+
+static char*
+geteeprom(char *s)
+{
+	static int init;
+	static char res[64];
+	static uchar eeprom[257];
+	uchar *l, *p;
+	int i, j;
+
+	if(!init){
+		i2csetup();
+		if(i2crecv(0xa8|1|(0<<8), eeprom, 128) < 0 ||
+		   i2crecv(0xa8|1|(128<<8), eeprom+128, 128) < 0){
+			print("i2c failed\n");
+			return nil;
+		}
+		if(0){
+			print("eeprom:\n");
+			for(i=0; i<16; i++){for(j=0; j<16; j++)print(" %2.2ux[%c]", eeprom[i*16+j], eeprom[i*16+j]); print("\n");}
+		}
+		eeprom[256] = 0xFF;
+		init = 1;
+	}
+	for(l = eeprom; *l != 0xFF && *l != '\n';){
+		p = l;
+		while(*l != '\n' && *l != 0xFF && *l != '=')
+			l++;
+		if(*l == '='){
+			if(l-p == strlen(s) && strncmp(s, (char*)p, strlen(s)) == 0){
+				p = l+1;
+				while(*l != '\n' && *l != 0xFF)
+					l++;
+				memmove(res, p, l-p);
+				res[l-p] = 0;
+				return res;
+			}
+		}
+		while(*l != '\n' && *l != 0xFF)
+			l++;
+		if(*l == '\n')
+			l++;
+	}
+	return nil;
+}
--- /dev/null
+++ b/os/boot.original/rpcg/archrpcg.h
@@ -1,0 +1,48 @@
+/*
+ * values for RPXLite AW
+ */
+enum {
+	/* CS assignment */
+	BOOTCS = 0,
+	DRAM1 = 1,
+	/* CS2 is routed to expansion header */
+	BCSRCS = 3,
+	NVRAMCS = 4,
+	/* CS5 is routed to expansion header */
+	PCMCIA0CS = 6,	/* select even bytes */
+	PCMCIA1CS = 7,	/* select odd bytes */
+};
+
+/*
+ * BCSR bits (there are 4 8-bit registers that we access as ulong)
+ */
+enum {
+	EnableEnet =	IBIT(0),
+	EnableXcrLB=	IBIT(1),
+	DisableColTest=	IBIT(2),
+	DisableFullDplx=IBIT(3),
+	LedOff=		IBIT(4),
+	DisableUSB=	IBIT(5),
+	HighSpdUSB=	IBIT(6),
+	EnableUSBPwr=	IBIT(7),
+	/* 8,9,10 unused */
+	PCCVCCMask=	IBIT(12)|IBIT(13),
+	PCCVPPMask=	IBIT(14)|IBIT(15),
+	PCCVCC0V=	0,
+	PCCVCC5V=	IBIT(13),
+	PCCVCC3V=	IBIT(12),
+	PCCVPP0V=	0,
+	PCCVPP5V=	IBIT(14),
+	PCCVPP12V=	IBIT(15),
+	PCCVPPHiZ=	IBIT(14)|IBIT(15),
+	/* 16-23 NYI */
+	DipSwitchMask=	IBIT(24)|IBIT(25)|IBIT(26)|IBIT(27),
+	DipSwitch0=	IBIT(24),
+	DipSwitch1=	IBIT(25),
+	DipSwitch2=	IBIT(26),
+	DipSwitch3=	IBIT(27),
+	/* bit 28 RESERVED */
+	FlashComplete=	IBIT(29),
+	NVRAMBattGood=	IBIT(30),
+	RTCBattGood=	IBIT(31),
+};
--- /dev/null
+++ b/os/boot.original/rpcg/boot.h
@@ -1,0 +1,8 @@
+#include <u.h>
+#include "lib.h"
+
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "ureg.h"
--- /dev/null
+++ b/os/boot.original/rpcg/bootp.c
@@ -1,0 +1,509 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+#include "ip.h"
+
+#define	XPADDR(a)	((ulong)(a) & ~KSEGM)
+
+enum {
+	CHECKSUM = 1,	/* set zero if trouble booting from Linux */
+};
+
+uchar broadcast[Eaddrlen] = {
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+};
+
+static ushort tftpport = 5000;
+static int Id = 1;
+static Netaddr myaddr;
+static Netaddr server;
+
+typedef struct {
+	uchar	header[4];
+	uchar	data[Segsize];
+} Tftp;
+static Tftp tftpb;
+
+static void
+hnputs(uchar *ptr, ushort val)
+{
+	ptr[0] = val>>8;
+	ptr[1] = val;
+}
+
+static void
+hnputl(uchar *ptr, ulong val)
+{
+	ptr[0] = val>>24;
+	ptr[1] = val>>16;
+	ptr[2] = val>>8;
+	ptr[3] = val;
+}
+
+static ulong
+nhgetl(uchar *ptr)
+{
+	return ((ptr[0]<<24) | (ptr[1]<<16) | (ptr[2]<<8) | ptr[3]);
+}
+
+static ushort
+nhgets(uchar *ptr)
+{
+	return ((ptr[0]<<8) | ptr[1]);
+}
+
+static	short	endian	= 1;
+static	char*	aendian	= (char*)&endian;
+#define	LITTLE	*aendian
+
+static ushort
+ptcl_csum(void *a, int len)
+{
+	uchar *addr;
+	ulong t1, t2;
+	ulong losum, hisum, mdsum, x;
+
+	addr = a;
+	losum = 0;
+	hisum = 0;
+	mdsum = 0;
+
+	x = 0;
+	if((ulong)addr & 1) {
+		if(len) {
+			hisum += addr[0];
+			len--;
+			addr++;
+		}
+		x = 1;
+	}
+	while(len >= 16) {
+		t1 = *(ushort*)(addr+0);
+		t2 = *(ushort*)(addr+2);	mdsum += t1;
+		t1 = *(ushort*)(addr+4);	mdsum += t2;
+		t2 = *(ushort*)(addr+6);	mdsum += t1;
+		t1 = *(ushort*)(addr+8);	mdsum += t2;
+		t2 = *(ushort*)(addr+10);	mdsum += t1;
+		t1 = *(ushort*)(addr+12);	mdsum += t2;
+		t2 = *(ushort*)(addr+14);	mdsum += t1;
+		mdsum += t2;
+		len -= 16;
+		addr += 16;
+	}
+	while(len >= 2) {
+		mdsum += *(ushort*)addr;
+		len -= 2;
+		addr += 2;
+	}
+	if(x) {
+		if(len)
+			losum += addr[0];
+		if(LITTLE)
+			losum += mdsum;
+		else
+			hisum += mdsum;
+	} else {
+		if(len)
+			hisum += addr[0];
+		if(LITTLE)
+			hisum += mdsum;
+		else
+			losum += mdsum;
+	}
+
+	losum += hisum >> 8;
+	losum += (hisum & 0xff) << 8;
+	while(hisum = losum>>16)
+		losum = hisum + (losum & 0xffff);
+
+	return ~losum;
+}
+
+static ushort
+ip_csum(uchar *addr)
+{
+	int len;
+	ulong sum = 0;
+
+	len = (addr[0]&0xf)<<2;
+
+	while(len > 0) {
+		sum += addr[0]<<8 | addr[1] ;
+		len -= 2;
+		addr += 2;
+	}
+
+	sum = (sum & 0xffff) + (sum >> 16);
+	sum = (sum & 0xffff) + (sum >> 16);
+	return (sum^0xffff);
+}
+
+static void
+udpsend(int ctlrno, Netaddr *a, void *data, int dlen)
+{
+	Udphdr *uh;
+	Etherhdr *ip;
+	static Etherpkt pkt;
+	int len, ptcllen;
+
+
+	uh = (Udphdr*)&pkt;
+
+	memset(uh, 0, sizeof(Etherpkt));
+	memmove(uh->udpcksum+sizeof(uh->udpcksum), data, dlen);
+
+	/*
+	 * UDP portion
+	 */
+	ptcllen = dlen + (UDP_HDRSIZE-UDP_PHDRSIZE);
+	uh->ttl = 0;
+	uh->udpproto = IP_UDPPROTO;
+	uh->frag[0] = 0;
+	uh->frag[1] = 0;
+	hnputs(uh->udpplen, ptcllen);
+	hnputl(uh->udpsrc, myaddr.ip);
+	hnputs(uh->udpsport, myaddr.port);
+	hnputl(uh->udpdst, a->ip);
+	hnputs(uh->udpdport, a->port);
+	hnputs(uh->udplen, ptcllen);
+	uh->udpcksum[0] = 0;
+	uh->udpcksum[1] = 0;
+	/*dlen = (dlen+1)&~1; */
+	hnputs(uh->udpcksum, ptcl_csum(&uh->ttl, dlen+UDP_HDRSIZE));
+
+	/*
+	 * IP portion
+	 */
+	ip = (Etherhdr*)&pkt;
+	len = sizeof(Udphdr)+dlen;
+	ip->vihl = IP_VER|IP_HLEN;
+	ip->tos = 0;
+	ip->ttl = 255;
+	hnputs(ip->length, len-ETHER_HDR);
+	hnputs(ip->id, Id++);
+	ip->frag[0] = 0;
+	ip->frag[1] = 0;
+	ip->cksum[0] = 0;
+	ip->cksum[1] = 0;
+	hnputs(ip->cksum, ip_csum(&ip->vihl));
+
+	/*
+	 * Ethernet MAC portion
+	 */
+	hnputs(ip->type, ET_IP);
+	memmove(ip->d, a->ea, sizeof(ip->d));
+
+	ethertxpkt(ctlrno, &pkt, len, Timeout);
+}
+
+static void
+nak(int ctlrno, Netaddr *a, int code, char *msg, int report)
+{
+	int n;
+	char buf[128];
+
+	buf[0] = 0;
+	buf[1] = Tftp_ERROR;
+	buf[2] = 0;
+	buf[3] = code;
+	strcpy(buf+4, msg);
+	n = strlen(msg) + 4 + 1;
+	udpsend(ctlrno, a, buf, n);
+	if(report)
+		print("\ntftp: error(%d): %s\n", code, msg);
+}
+
+static int
+udprecv(int ctlrno, Netaddr *a, void *data, int dlen)
+{
+	int n, len;
+	ushort csm;
+	Udphdr *h;
+	ulong addr, timo;
+	static Etherpkt pkt;
+	static int rxactive;
+
+	if(rxactive == 0)
+		timo = 1000;
+	else
+		timo = Timeout;
+	timo += TK2MS(m->ticks);
+	while(timo > TK2MS(m->ticks)){
+		n = etherrxpkt(ctlrno, &pkt, timo-TK2MS(m->ticks));
+		if(n <= 0)
+			continue;
+
+		h = (Udphdr*)&pkt;
+		if(nhgets(h->type) != ET_IP)
+			continue;
+
+		if(ip_csum(&h->vihl)) {
+			print("ip chksum error\n");
+			continue;
+		}
+		if(h->vihl != (IP_VER|IP_HLEN)) {
+			print("ip bad vers/hlen\n");
+			continue;
+		}
+
+		if(h->udpproto != IP_UDPPROTO)
+			continue;
+
+		h->ttl = 0;
+		len = nhgets(h->udplen);
+		hnputs(h->udpplen, len);
+
+		if(CHECKSUM && nhgets(h->udpcksum)) {
+			csm = ptcl_csum(&h->ttl, len+UDP_PHDRSIZE);
+			if(csm != 0) {
+				print("udp chksum error csum #%4lux len %d\n", csm, n);
+				break;
+			}
+		}
+
+		if(a->port != 0 && nhgets(h->udpsport) != a->port)
+			continue;
+
+		addr = nhgetl(h->udpsrc);
+		if(a->ip != Bcastip && addr != a->ip)
+			continue;
+
+		len -= UDP_HDRSIZE-UDP_PHDRSIZE;
+		if(len > dlen) {
+			print("udp: packet too big\n");
+			continue;
+		}
+
+		memmove(data, h->udpcksum+sizeof(h->udpcksum), len);
+		a->ip = addr;
+		a->port = nhgets(h->udpsport);
+		memmove(a->ea, pkt.s, sizeof(a->ea));
+
+		rxactive = 1;
+		return len;
+	}
+
+	return 0;
+}
+
+static int tftpblockno;
+
+static int
+tftpopen(int ctlrno, Netaddr *a, char *name, Tftp *tftp)
+{
+	int i, len, rlen, oport;
+	char buf[Segsize+2];
+
+	buf[0] = 0;
+	buf[1] = Tftp_READ;
+	len = sprint(buf+2, "%s", name) + 2;
+	len += sprint(buf+len+1, "octet") + 2;
+
+	oport = a->port;
+	for(i = 0; i < 5; i++){
+		a->port = oport;
+		udpsend(ctlrno, a, buf, len);
+		a->port = 0;
+		if((rlen = udprecv(ctlrno, a, tftp, sizeof(Tftp))) < sizeof(tftp->header))
+			continue;
+
+		switch((tftp->header[0]<<8)|tftp->header[1]){
+
+		case Tftp_ERROR:
+			print("tftpopen: error (%d): %s\n",
+				(tftp->header[2]<<8)|tftp->header[3], tftp->data);
+			return -1;
+
+		case Tftp_DATA:
+			tftpblockno = 1;
+			len = (tftp->header[2]<<8)|tftp->header[3];
+			if(len != tftpblockno){
+				print("tftpopen: block error: %d\n", len);
+				nak(ctlrno, a, 1, "block error", 0);
+				return -1;
+			}
+			return rlen-sizeof(tftp->header);
+		}
+	}
+
+	print("tftpopen: failed to connect to server\n");
+	return -1;
+}
+
+static int
+tftpread(int ctlrno, Netaddr *a, Tftp *tftp, int dlen)
+{
+	int blockno, len, retry;
+	uchar buf[4];
+
+	buf[0] = 0;
+	buf[1] = Tftp_ACK;
+	buf[2] = tftpblockno>>8;
+	buf[3] = tftpblockno;
+	tftpblockno++;
+
+	dlen += sizeof(tftp->header);
+
+	retry = 0;
+buggery:
+	udpsend(ctlrno, a, buf, sizeof(buf));
+
+	if((len = udprecv(ctlrno, a, tftp, dlen)) < dlen){
+		print("tftpread: %d != %d\n", len, dlen);
+		nak(ctlrno, a, 2, "short read", 0);
+		if(retry++ < 5)
+			goto buggery;
+		return -1;
+	}
+
+	blockno = (tftp->header[2]<<8)|tftp->header[3];
+	if(blockno != tftpblockno){
+		print("?");
+
+		if(blockno == tftpblockno-1 && retry++ < 8)
+			goto buggery;
+		print("tftpread: block error: %d, expected %d\n", blockno, tftpblockno);
+		nak(ctlrno, a, 1, "block error", 0);
+
+		return -1;
+	}
+
+	return len-sizeof(tftp->header);
+}
+
+int
+bootp(int ctlrno, char *file)
+{
+	Bootp req, rep;
+	int i, dlen, segsize, text, data, bss, total;
+	uchar *ea, *addr, *p;
+	ulong entry;
+	Exec *exec;
+	char name[128], *filename, *sysname;
+
+	if((ea = etheraddr(ctlrno)) == 0){
+		print("invalid ctlrno %d\n", ctlrno);
+		return -1;
+	}
+
+	filename = 0;
+	sysname = 0;
+	if(file && *file){
+		strcpy(name, file);
+		if(filename = strchr(name, ':')){
+			if(filename != name && *(filename-1) != '\\'){
+				sysname = name;
+				*filename++ = 0;
+			}
+		}
+		else
+			filename = name;
+	}
+		
+
+	memset(&req, 0, sizeof(req));
+	req.op = Bootrequest;
+	req.htype = 1;			/* ethernet */
+	req.hlen = Eaddrlen;		/* ethernet */
+	memmove(req.chaddr, ea, Eaddrlen);
+
+	myaddr.ip = 0;
+	myaddr.port = BPportsrc;
+	memmove(myaddr.ea, ea, Eaddrlen);
+
+	for(i = 0; i < 10; i++) {
+		server.ip = Bcastip;
+		server.port = BPportdst;
+		memmove(server.ea, broadcast, sizeof(server.ea));
+		udpsend(ctlrno, &server, &req, sizeof(req));
+		if(udprecv(ctlrno, &server, &rep, sizeof(rep)) <= 0)
+			continue;
+		if(memcmp(req.chaddr, rep.chaddr, Eaddrlen))
+			continue;
+		if(rep.htype != 1 || rep.hlen != Eaddrlen)
+			continue;
+		if(sysname == 0 || strcmp(sysname, rep.sname) == 0)
+			break;
+	}
+	if(i >= 10) {
+		print("bootp timed out\n");
+		return -1;
+	}
+
+	if(filename == 0 || *filename == 0)
+		filename = rep.file;
+
+	if(rep.sname[0] != '\0')
+		 print("%s ", rep.sname);
+	print("(%d.%d.%d.%d!%d): %s\n",
+		rep.siaddr[0],
+		rep.siaddr[1],
+		rep.siaddr[2],
+		rep.siaddr[3],
+		server.port,
+		filename);uartwait();
+
+	myaddr.ip = nhgetl(rep.yiaddr);
+	myaddr.port = tftpport++;
+	server.ip = nhgetl(rep.siaddr);
+	server.port = TFTPport;
+
+	if((dlen = tftpopen(ctlrno, &server, filename, &tftpb)) < 0)
+		return -1;
+	exec = (Exec*)(tftpb.data);
+	if(dlen < sizeof(Exec) || GLLONG(exec->magic) != Q_MAGIC){
+		nak(ctlrno, &server, 0, "bad magic number", 1);
+		return -1;
+	}
+	text = GLLONG(exec->text);
+	data = GLLONG(exec->data);
+	bss = GLLONG(exec->bss);
+	total = text+data+bss;
+	entry = GLLONG(exec->entry);
+print("load@%8.8lux: ", XPADDR(entry));uartwait();
+	print("%d", text);
+
+	addr = (uchar*)XPADDR(entry);
+	p = tftpb.data+sizeof(Exec);
+	dlen -= sizeof(Exec);
+	segsize = text;
+	for(;;){
+		if(dlen == 0){
+			if((dlen = tftpread(ctlrno, &server, &tftpb, sizeof(tftpb.data))) < 0)
+				return -1;
+			p = tftpb.data;
+		}
+		if(segsize <= dlen)
+			i = segsize;
+		else
+			i = dlen;
+		memmove(addr, p, i);
+
+		addr += i;
+		p += i;
+		segsize -= i;
+		dlen -= i;
+
+		if(segsize <= 0){
+			if(data == 0)
+				break;
+			print("+%d", data);
+			segsize = data;
+			data = 0;
+			addr = (uchar*)PGROUND((ulong)addr);
+		}
+	}
+	nak(ctlrno, &server, 3, "ok", 0);		/* tftpclose */
+	print("+%d=%d\n", bss, total);
+	print("entry: 0x%lux\n", entry);
+	uartwait();
+	scc2stop();
+	splhi();
+	(*(void(*)(void))(XPADDR(entry)))();
+	
+	return 0;
+}
--- /dev/null
+++ b/os/boot.original/rpcg/clock.c
@@ -1,0 +1,71 @@
+#include	"u.h"
+#include	"lib.h"
+#include	"mem.h"
+#include	"dat.h"
+#include	"fns.h"
+#include	"io.h"
+#include	"ureg.h"
+
+enum {
+	Timebase = 4,	/* system clock cycles per time base cycle */
+};
+
+void	(*archclocktick)(void);	/* set by arch*.c when desired */
+
+static	ulong	clkreload;
+
+void
+delay(int l)
+{
+	ulong i, j;
+
+	j = m->delayloop;
+	while(l-- > 0)
+		for(i=0; i < j; i++)
+			;
+}
+
+void
+microdelay(int l)
+{
+	ulong i;
+
+	l *= m->delayloop;
+	l /= 1000;
+	if(l <= 0)
+		l = 1;
+	for(i = 0; i < l; i++)
+		;
+}
+
+void
+clockintr(Ureg*, void*)
+{
+	putdec(clkreload);
+	m->ticks++;
+	checkalarms();
+	if(archclocktick != nil)
+		archclocktick();
+}
+
+void
+clockinit(void)
+{
+	long x;
+
+	m->delayloop = m->cpuhz/1000;	/* initial estimate */
+	do {
+		x = gettbl();
+		delay(10);
+		x = gettbl() - x;
+	} while(x < 0);
+
+	/*
+	 *  fix count
+	 */
+	m->delayloop = ((vlong)m->delayloop*(10*m->clockgen/1000))/(x*Timebase);
+	if(m->delayloop == 0)
+		m->delayloop = 1;
+	clkreload = (m->clockgen/Timebase)/HZ-1;
+	putdec(clkreload);
+}
--- /dev/null
+++ b/os/boot.original/rpcg/conf.c
@@ -1,0 +1,173 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+#include "dosfs.h"
+
+static char *confname[MAXCONF];
+static char *confval[MAXCONF];
+static int nconf;
+
+extern char **ini;
+
+char*
+getconf(char *name)
+{
+	int i;
+
+	for(i = 0; i < nconf; i++)
+		if(strcmp(confname[i], name) == 0)
+			return confval[i];
+	return 0;
+}
+
+/*
+ *  read configuration file
+ */
+int
+plan9ini(Dos *dos, char *val)
+{
+	Dosfile rc;
+	int i, n;
+	char *cp, *p, *q, *line[MAXCONF];
+
+	cp = BOOTARGS;
+	if(dos) {
+		if(dosstat(dos, *ini, &rc) <= 0)
+			return -1;
+
+		*cp = 0;
+		n = dosread(&rc, cp, BOOTARGSLEN-1);
+		if(n <= 0)
+			return -1;
+		cp[n] = 0;
+	} else if(val != nil){
+		if(memchr(val, 0, BOOTARGSLEN-1) == nil)
+			return -1;
+		print("Using flash configuration\n");
+		strcpy(cp, val);
+		n = strlen(cp);
+	}else{
+		strcpy(cp, archconfig());
+		n = strlen(cp);
+	}
+
+	/*
+	 * Make a working copy.
+	 * We could change this to pass the parsed strings
+	 * to the booted programme instead of the raw
+	 * string, then it only gets done once.
+	 */
+	memmove(cp+BOOTARGSLEN, cp, n+1);
+	cp += BOOTARGSLEN;
+
+	/*
+	 * Strip out '\r', change '\t' -> ' '.
+	 */
+	p = cp;
+	for(q = cp; *q; q++){
+		if(*q == '\r')
+			continue;
+		if(*q == '\t')
+			*q = ' ';
+		*p++ = *q;
+	}
+	*p = 0;
+	n = getcfields(cp, line, MAXCONF, "\n");
+	for(i = 0; i < n; i++){
+		cp = strchr(line[i], '=');
+		if(cp == 0)
+			continue;
+		*cp++ = 0;
+		if(cp - line[i] >= NAMELEN+1)
+			*(line[i]+NAMELEN-1) = 0;
+		confname[nconf] = line[i];
+		confval[nconf] = cp;
+		nconf++;
+	}
+	return 0;
+}
+
+int
+parseether(uchar *to, char *from)
+{
+	char nip[4];
+	char *p;
+	int i;
+
+	p = from;
+	while(*p == ' ')
+		++p;
+	for(i = 0; i < 6; i++){
+		if(*p == 0)
+			return -1;
+		nip[0] = *p++;
+		if(*p == 0)
+			return -1;
+		nip[1] = *p++;
+		nip[2] = 0;
+		to[i] = strtoul(nip, 0, 16);
+		if(*p == ':')
+			p++;
+	}
+	return 0;
+}
+
+int
+isaconfig(char *class, int ctlrno, ISAConf *isa)
+{
+	char cc[NAMELEN], *p, *q, *r;
+	int n;
+
+	sprint(cc, "%s%d", class, ctlrno);
+	for(n = 0; n < nconf; n++){
+		if(strncmp(confname[n], cc, NAMELEN))
+			continue;
+		isa->nopt = 0;
+		p = confval[n];
+		while(*p){
+			while(*p == ' ' || *p == '\t')
+				p++;
+			if(*p == '\0')
+				break;
+			if(strncmp(p, "type=", 5) == 0){
+				p += 5;
+				for(q = isa->type; q < &isa->type[NAMELEN-1]; q++){
+					if(*p == '\0' || *p == ' ' || *p == '\t')
+						break;
+					*q = *p++;
+				}
+				*q = '\0';
+			}
+			else if(strncmp(p, "port=", 5) == 0)
+				isa->port = strtoul(p+5, &p, 0);
+			else if(strncmp(p, "irq=", 4) == 0)
+				isa->irq = strtoul(p+4, &p, 0);
+			else if(strncmp(p, "mem=", 4) == 0)
+				isa->mem = strtoul(p+4, &p, 0);
+			else if(strncmp(p, "size=", 5) == 0)
+				isa->size = strtoul(p+5, &p, 0);
+			else if(strncmp(p, "ea=", 3) == 0){
+				if(parseether(isa->ea, p+3) == -1)
+					memset(isa->ea, 0, 6);
+			}
+			else if(isa->nopt < NISAOPT){
+				r = isa->opt[isa->nopt];
+				while(*p && *p != ' ' && *p != '\t'){
+					*r++ = *p++;
+					if(r-isa->opt[isa->nopt] >= ISAOPTLEN-1)
+						break;
+				}
+				*r = '\0';
+				isa->nopt++;
+			}
+			while(*p && *p != ' ' && *p != '\t')
+				p++;
+		}
+		return 1;
+	}
+	return 0;
+}
--- /dev/null
+++ b/os/boot.original/rpcg/console.c
@@ -1,0 +1,173 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+static Queue*	consiq;
+static Queue*	consoq;
+
+void
+bothputs(char *s, int n)
+{
+	uartputs(s, n);
+	screenputs(s, n);
+}
+
+static void (*consputs)(char*, int) = bothputs;	/* or screenputs */
+
+void
+consinit(void)
+{
+	char *p;
+	int baud, port;
+	static int cgadone;
+
+	p = getconf("console");
+	if(0)
+	if(p == 0 || strcmp(p, "lcd") == 0 || strcmp(p, "screen") == 0){
+		consiq = qopen(4*1024, 0, 0, 0);
+		consoq = qopen(8*1024, 0, 0, 0);
+		consputs = screenputs;
+		return;
+	}
+	if(p!=0 && strstr(p, "lcd") == 0)
+		consputs = bothputs;
+	else
+		consputs = uartputs;
+//consputs = screenputs;
+	port = 0;
+	if(p)
+		port = strtoul(p, 0, 0);
+	baud = 0;
+	if(p = getconf("baud"))
+		baud = strtoul(p, 0, 0);
+	if(baud == 0)
+		baud = 9600;
+	uartspecial(port, baud, &consiq, &consoq, kbdchar);
+}
+
+void
+kbdchar(Queue *q, int c)
+{
+	c &= 0x7F;
+	if(c == 0x10)
+		panic("^p");
+	qbputc(q, c);
+}
+
+static int
+getline(char *buf, int size, int dotimeout)
+{
+	int c, i=0;
+	ulong start;
+	char echo;
+
+	for (;;) {
+		start = m->ticks;
+		do{
+			if(dotimeout && ((m->ticks - start) > 5*HZ))
+				return -2;
+			c = qbgetc(consiq);
+		}while(c == -1);
+		if(c == '\r')
+			c = '\n'; 		/* turn carriage return into newline */
+		if(c == '\177')
+			c = '\010';		/* turn delete into backspace */
+		if(c == '\025')
+			echo = '\n';		/* echo ^U as a newline */
+		else
+			echo = c;
+		(*consputs)(&echo, 1);
+
+		if(c == '\010'){
+			if(i > 0)
+				i--; /* bs deletes last character */
+			continue;
+		}
+		/* a newline ends a line */
+		if (c == '\n')
+			break;
+		/* ^U wipes out the line */
+		if (c =='\025')
+			return -1;
+		if(i == size)
+			return size;
+		buf[i++] = c;
+	}
+	buf[i] = 0;
+	return i;
+}
+
+int
+getstr(char *prompt, char *buf, int size, char *def)
+{
+	int len, isdefault;
+
+	buf[0] = 0;
+	isdefault = (def && *def);
+	for (;;) {
+		if(isdefault)
+			print("%s[default==%s]: ", prompt, def);
+		else
+			print("%s: ", prompt);
+		len = getline(buf, size, isdefault);
+		switch(len){
+		case -1:
+			/* ^U typed */
+			continue;
+		case -2:
+			/* timeout, use default */
+			(*consputs)("\n", 1);
+			len = 0;
+			break;
+		default:
+			break;
+		}
+		if(len >= size){
+			print("line too long\n");
+			continue;
+		}
+		break;
+	}
+	if(len == 0 && isdefault)
+		strcpy(buf, def);
+	return 0;
+}
+
+int
+sprint(char *s, char *fmt, ...)
+{
+	return donprint(s, s+PRINTSIZE, fmt, (&fmt+1)) - s;
+}
+
+int
+print(char *fmt, ...)
+{
+	char buf[PRINTSIZE];
+	int n;
+
+	if(consputs == 0)
+		return 0;
+	n = donprint(buf, buf+sizeof(buf), fmt, (&fmt+1)) - buf;
+	(*consputs)(buf, n);
+	return n;
+}
+
+void
+panic(char *fmt, ...)
+{
+	char buf[PRINTSIZE];
+	int n;
+
+	if(consputs){
+		(*consputs)("panic: ", 7);
+		n = donprint(buf, buf+sizeof(buf), fmt, (&fmt+1)) - buf;
+		(*consputs)(buf, n);
+		(*consputs)("\n", 1);
+	}
+	spllo();
+	for(;;)
+		idle();
+}
--- /dev/null
+++ b/os/boot.original/rpcg/cpm.c
@@ -1,0 +1,162 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+enum {
+	BDSIZE=	1024,	/* TO DO: check this */
+};
+
+static	Map	bdmapv[BDSIZE/sizeof(BD)];
+static	RMap	bdmap = {"buffer descriptors"};
+
+void
+cpminit(void)
+{
+	IMM *io;
+
+	io = m->iomem;
+	io->sdcr = 1;
+	io->lccr &= ~1;	/* disable LCD */
+	io->pcint = 0;	/* disable all port C interrupts */
+	io->pcso = 0;
+	io->pcdir =0;
+	io->pcpar = 0;
+	io->pcdat = 0;
+	io->papar = 0;
+	io->padir = 0;
+	io->paodr = 0;
+	io->padat = 0;
+	io->pbpar = 0;
+	io->pbdir = 0;
+	io->pbodr = 0;
+	io->pbdat = 0;
+	eieio();
+
+	for(io->cpcr = 0x8001; io->cpcr & 1;)	/* reset all CPM channels */
+		eieio();
+
+	mapinit(&bdmap, bdmapv, sizeof(bdmapv));
+	mapfree(&bdmap, DPBASE, BDSIZE);
+}
+
+void
+cpmop(int op, int cno, int param)
+{
+	IMM *io;
+	int s;
+
+	s = splhi();
+	io = m->iomem;
+	eieio();
+	while(io->cpcr & 1)
+		eieio();
+	io->cpcr = (op<<8)|(cno<<4)|(param<<1)|1;
+	eieio();
+	while(io->cpcr & 1)
+		eieio();
+	splx(s);
+}
+
+/*
+ * connect SCCx clocks in NSMI mode (x=1 for USB)
+ */
+void
+sccnmsi(int x, int rcs, int tcs)
+{
+	IMM *io;
+	ulong v;
+	int sh;
+
+	sh = (x-1)*8;	/* each SCCx field in sicr is 8 bits */
+	v = (((rcs&7)<<3) | (tcs&7)) << sh;
+	io = ioplock();
+	io->sicr = (io->sicr & ~(0xFF<<sh)) | v;
+	iopunlock();
+}
+
+void
+scc2stop(void)
+{
+	SCC *scc;
+
+	scc = IOREGS(0xA20, SCC);
+	if(scc->gsmrl & (3<<4)){
+		cpmop(GracefulStopTx, SCC2ID, 0);
+		cpmop(CloseRxBD, SCC2ID, 0);
+		delay(1);
+		scc->gsmrl &= ~(3<<4);	/* disable current use */
+		archetherdisable(SCC2ID);
+	}
+}
+
+BD *
+bdalloc(int n)
+{
+	ulong a;
+
+	a = mapalloc(&bdmap, 0, n*sizeof(BD), 0);
+	if(a == 0)
+		panic("bdalloc");
+	return KADDR(a);
+}
+
+void
+bdfree(BD *b, int n)
+{
+	if(b){
+		eieio();
+		mapfree(&bdmap, PADDR(b), n*sizeof(BD));
+	}
+}
+
+/*
+ * initialise receive and transmit buffer rings.
+ */
+int
+ioringinit(Ring* r, int nrdre, int ntdre, int bufsize)
+{
+	int i, x;
+
+	/* the ring entries must be aligned on sizeof(BD) boundaries */
+	r->nrdre = nrdre;
+	if(r->rdr == nil)
+		r->rdr = bdalloc(nrdre);
+	/* the buffer size must align with cache lines since the cache doesn't snoop */
+	bufsize = (bufsize+CACHELINESZ-1)&~(CACHELINESZ-1);
+	if(r->rrb == nil)
+		r->rrb = malloc(nrdre*bufsize);
+	if(r->rdr == nil || r->rrb == nil)
+		return -1;
+	dcflush(r->rrb, nrdre*bufsize);
+	x = PADDR(r->rrb);
+	for(i = 0; i < nrdre; i++){
+		r->rdr[i].length = 0;
+		r->rdr[i].addr = x;
+		r->rdr[i].status = BDEmpty|BDInt;
+		x += bufsize;
+	}
+	r->rdr[i-1].status |= BDWrap;
+	r->rdrx = 0;
+
+	r->ntdre = ntdre;
+	if(r->tdr == nil)
+		r->tdr = bdalloc(ntdre);
+	if(r->txb == nil)
+		r->txb = malloc(ntdre*sizeof(Block*));
+	if(r->tdr == nil || r->txb == nil)
+		return -1;
+	for(i = 0; i < ntdre; i++){
+		r->txb[i] = nil;
+		r->tdr[i].addr = 0;
+		r->tdr[i].length = 0;
+		r->tdr[i].status = 0;
+	}
+	r->tdr[i-1].status |= BDWrap;
+	r->tdrh = 0;
+	r->tdri = 0;
+	r->ntq = 0;
+	return 0;
+}
--- /dev/null
+++ b/os/boot.original/rpcg/crc32.c
@@ -1,0 +1,42 @@
+#include "boot.h"
+
+/*
+ * from Rob Warnock
+ */
+static	ulong	crc32tab[256];	/* initialised on first call to crc32 */
+
+enum {
+	CRC32POLY = 0x04c11db7     /* AUTODIN II, Ethernet, & FDDI */
+};
+
+/*
+ * Build auxiliary table for parallel byte-at-a-time CRC-32.
+ */
+static void
+initcrc32(void)
+{
+	int i, j;
+	ulong c;
+
+	for(i = 0; i < 256; i++) {
+		for(c = i << 24, j = 8; j > 0; j--)
+			if(c & (1<<31))
+				c = (c<<1) ^ CRC32POLY;
+			else
+				c <<= 1;
+		crc32tab[i] = c;
+	}
+}
+
+ulong
+crc32(void *buf, int n, ulong crc)
+{
+	uchar *p;
+
+	if(crc32tab[1] == 0)
+		initcrc32();
+	crc = ~crc;
+	for(p = buf; --n >= 0;)
+		crc = (crc << 8) ^ crc32tab[(crc >> 24) ^ *p++];
+	return ~crc;
+}
--- /dev/null
+++ b/os/boot.original/rpcg/dat.h
@@ -1,0 +1,217 @@
+typedef struct Alarm Alarm;
+typedef struct Block Block;
+typedef struct IMM IMM;
+typedef struct Queue Queue;
+
+typedef struct List {
+	void	*next;
+} List;
+
+typedef struct {
+	int	fake;
+	int	pri;
+} Lock;
+#define	lock(x)
+#define	unlock(x)
+
+struct Alarm {
+	List;
+	int	busy;
+	long	dt;
+	void	(*f)(Alarm*);
+	void	*arg;
+};
+
+enum {
+	Eaddrlen	= 6,
+	ETHERMINTU	= 60,		/* minimum transmit size */
+	ETHERMAXTU	= 1514,		/* maximum transmit size */
+	ETHERHDRSIZE	= 14,		/* size of an ethernet header */
+
+	MaxEther	= 4,
+};
+
+typedef struct {
+	uchar	d[Eaddrlen];
+	uchar	s[Eaddrlen];
+	uchar	type[2];
+	uchar	data[1500];
+	uchar	crc[4];
+} Etherpkt;
+
+extern uchar broadcast[Eaddrlen];
+
+enum {
+	Npart		= 20+2,		/* 8 sub partitions, disk, and partition */
+	Maxxfer		= 16*1024,	/* maximum transfer size/cmd */
+};
+
+typedef struct {
+	ulong	start;
+	ulong	end;
+	char	name[NAMELEN+1];
+} Partition;
+
+typedef struct {
+	int	online;
+	int	npart;		/* number of real partitions */
+	Partition p[Npart];
+	ulong	offset;
+	Partition *current;	/* current partition */
+
+	ulong	cap;		/* total bytes */
+	int	bytes;		/* bytes/sector */
+	int	sectors;	/* sectors/track */
+	int	heads;		/* heads/cyl */
+	long	cyl;		/* cylinders/drive */
+
+	char	lba;		/* true if drive has logical block addressing */
+	char	multi;		/* non-zero if drive does multiple block xfers */
+} Disc;
+
+enum {
+	ScsiTestunit	= 0x00,
+	ScsiExtsens	= 0x03,
+	ScsiInquiry	= 0x12,
+	ScsiModesense	= 0x1a,
+	ScsiStartunit	= 0x1B,
+	ScsiStopunit	= 0x1B,
+	ScsiGetcap	= 0x25,
+	ScsiRead	= 0x08,
+	ScsiWrite	= 0x0a,
+	ScsiExtread	= 0x28,
+	ScsiExtwrite	= 0x2a,
+
+	/* data direction */
+	ScsiIn		= 1,
+	ScsiOut		= 0,
+};
+
+typedef struct Scsibuf Scsibuf;
+typedef struct Scsibuf {
+	void*		virt;
+	void*		phys;
+	Scsibuf*	next;
+};
+
+typedef struct Scsidata {
+	uchar*		base;
+	uchar*		lim;
+	uchar*		ptr;
+} Scsidata;
+
+typedef struct Ureg Ureg;
+
+typedef struct Scsi {
+	ulong		pid;
+	ushort		target;
+	ushort		lun;
+	ushort		rflag;
+	ushort		status;
+	Scsidata 	cmd;
+	Scsidata 	data;
+	Scsibuf*	b;
+	uchar*		save;
+	uchar		cmdblk[16];
+} Scsi;
+
+typedef struct Segdesc {
+	ulong	d0;
+	ulong	d1;
+} Segdesc;
+
+typedef struct Mach {
+	ulong	ticks;			/* of the clock since boot time */
+	ulong	delayloop;
+	long	cpuhz;	/* general system clock (cycles) */
+	long	clockgen;	/* clock generator frequency (cycles) */
+	ulong	cpupvr;	/* cpu type in processor version register */
+	ulong	cputype;	/* cpu variant in BCD (eg, 0x823xx) */
+	void*	alarm;			/* alarms bound to this clock */
+	ulong*	bcsr;
+	IMM*	iomem;
+} Mach;
+
+/* Mach.cputype */
+#define MPCREV(x)	((x) & 0xFF)
+#define MPCMODEL(x)	(((x)>>8) & 0xFFF)
+#define MPCFAMILY(x)	(((x)>>24) & 0x0F)
+
+
+extern Mach *m;
+
+#define Q_MAGIC		((((4*21)+0)*21)+7)
+
+typedef struct Exec Exec;
+struct	Exec
+{
+	uchar	magic[4];		/* magic number */
+	uchar	text[4];	 	/* size of text segment */
+	uchar	data[4];	 	/* size of initialized data */
+	uchar	bss[4];	  		/* size of uninitialized data */
+	uchar	syms[4];	 	/* size of symbol table */
+	uchar	entry[4];	 	/* entry point */
+	uchar	spsz[4];		/* size of sp/pc offset table */
+	uchar	pcsz[4];		/* size of pc/line number table */
+};
+
+/*
+ *  bootline passed by boot program
+ */
+#define BOOTLINE ((char *)0x200000-150)
+
+/*
+ * Where we leave configuration info.
+ */
+#define BOOTARGS	((char*)(0x200000))
+#define	BOOTARGSLEN	1024
+#define	MAXCONF		32
+
+/*
+ *  a parsed plan9.ini line
+ */
+#define ISAOPTLEN	16
+#define NISAOPT		8
+
+typedef struct  ISAConf {
+	char	type[NAMELEN];
+	ulong	port;
+	ulong	irq;
+	ulong	mem;
+	ulong	size;
+	uchar	ea[6];
+
+	int	nopt;
+	char	opt[NISAOPT][ISAOPTLEN];
+} ISAConf;
+
+typedef struct {
+	int	size;
+	ulong	addr;
+} Map;
+
+typedef struct {
+	char*	name;
+	Map*	map;
+	Map*	mapend;
+
+	Lock;
+} RMap;
+
+typedef struct PCIcfg PCIcfg;
+
+extern	uchar*	vgamem;
+
+struct Block {
+	uchar	*rp;
+	uchar	*wp;
+	uchar	*lim;
+	uchar	*data;
+	Block*	next;
+	ulong	magic;
+};
+#define	BLEN(b)	((b)->wp-(b)->rp)
+
+typedef struct QLock {
+	int	dummy;
+} QLock;
--- /dev/null
+++ b/os/boot.original/rpcg/defont0.c
@@ -1,0 +1,216 @@
+#include <u.h>
+#include <libc.h>
+#include <libg.h>
+#include <gnot.h>
+
+
+
+static ulong bits0[] = {
+ 0x907070f0,  0xf0f07000,  0xf0888888,  0xf8707070,  0xe0e0e0e0,  0xe09070f0,  0x70f870f0,  0xf870f088, 
+ 0x00000000,  0x00000000,  0x00000000,  0x00000000,  0x00000000,  0x00000000,  0x00000000,  0x00000000, 
+ 0x00000000,  0x00000000,  0x00000000,  0x00000000,  0x00000000,  0x00000000,  0x00000000,  0x00000000, 
+ 0x00000000,  0x00000000,  0x00000000,  0x00000000,  0x00000000,  0x00000000,  0x00000000,  0x000000e0, 
+ 0xd0808080,  0x80808800,  0x8888c888,  0x80888888,  0x90909090,  0x90d08080,  0x80808080,  0x80888888, 
+ 0x00000000,  0x08000000,  0x0c300000,  0x00000006,  0x00000000,  0x00000000,  0x00000000,  0x00000000, 
+ 0x00000000,  0x00000000,  0x00000000,  0x00000000,  0x00000000,  0x00000000,  0x0000003c,  0xc03c0000, 
+ 0x00006000,  0x06001e00,  0x60181860,  0x78000000,  0x00000000,  0x00000000,  0x0000001c,  0x18380090, 
+ 0xb06060e0,  0xe0e0f800,  0xf088a888,  0x80808080,  0x90909090,  0x90b060e0,  0x808060e0,  0x80808888, 
+ 0x00182428,  0x3e707018,  0x18180000,  0x00000006,  0x3c183c3c,  0x1c3e3c7e,  0x3c3c0000,  0x0200403c, 
+ 0x3c187c1e,  0x787e7e1e,  0x663c7c66,  0x6066623c,  0x7c3c7c3c,  0x7e6266c2,  0x66667e30,  0xc00c1000, 
+ 0x08006000,  0x06003000,  0x60181860,  0x18000000,  0x00000000,  0x10000000,  0x00000030,  0x180c0090, 
+ 0x90101080,  0x80808818,  0x88f8a888,  0xe0807070,  0xe0e0e0e0,  0xe0901080,  0x70e01080,  0xe098f088, 
+ 0x00182428,  0x6adad818,  0x18181000,  0x0000000c,  0x66386666,  0x2c3e667e,  0x66660000,  0x06006066, 
+ 0x42186632,  0x6c606032,  0x66181864,  0x60667224,  0x66246666,  0x186262da,  0x62620630,  0x600c3800, 
+ 0x10006000,  0x06003000,  0x60000060,  0x18000000,  0x00000000,  0x30000000,  0x00000030,  0x180c00e0, 
+ 0x00e0e0f0,  0xf0f00018,  0x88889850,  0x80880808,  0x201c1c1c,  0x1c00e0f0,  0x0080e0f0,  0x80888888, 
+ 0x00182428,  0x68dad808,  0x300c5418,  0x0000000c,  0x66580606,  0x2c206002,  0x66661818,  0x0cfe3006, 
+ 0x9e2c6660,  0x66606060,  0x6618186c,  0x60667266,  0x66666660,  0x186262da,  0x36660c30,  0x600c2800, 
+ 0x103c6c3c,  0x3e3c7e3e,  0x6c787866,  0x18d46c3c,  0x6c3e763c,  0x7e6666c2,  0x66667e18,  0x18180000, 
+ 0x44180000,  0x18241c24,  0xf0888820,  0x8070f0f0,  0x20202020,  0x201c243e,  0x1cf8241c,  0x80708870, 
+ 0x0018247c,  0x78745008,  0x300c3818,  0x00000018,  0x66180606,  0x4c206006,  0x76661818,  0x18fe180c, 
+ 0xb62c6660,  0x66606060,  0x66181868,  0x607e5a66,  0x66666470,  0x186266da,  0x34340c30,  0x300c6c00, 
+ 0x18667666,  0x66663066,  0x76181864,  0x18fe7666,  0x76663666,  0x306662da,  0x62620608,  0x1810323c, 
+ 0x44247c7c,  0x24342042,  0x00000000,  0x00000000,  0x20202020,  0x20222408,  0x22002420,  0x00000000, 
+ 0x00180028,  0x3c287610,  0x300cee7e,  0x00fe0018,  0x66180c18,  0x4c3c7c0c,  0x3c3e0000,  0x30000c18, 
+ 0xb62c7c60,  0x667c7c6e,  0x7e181878,  0x605a5a66,  0x6466783c,  0x186234da,  0x18341830,  0x300c4400, 
+ 0x18066660,  0x66663066,  0x66181868,  0x18d66666,  0x66663860,  0x306662da,  0x34620c30,  0x180c5a20, 
+ 0x44241010,  0x242c2042,  0x0e3e103e,  0x3e3c1c3e,  0x3c1c1c1c,  0x1c3e1c08,  0x3e222418,  0x0e0e0e0e, 
+ 0x0008007c,  0x1e5cdc00,  0x300c387e,  0x00fe0030,  0x66181806,  0x7e066618,  0x6e060000,  0x18001818, 
+ 0xb67e6660,  0x66606066,  0x6618186c,  0x605a4e66,  0x78666c0e,  0x1862346c,  0x2c183030,  0x180c4400, 
+ 0x003e6660,  0x667e3066,  0x66181878,  0x18d66666,  0x6666303c,  0x306634da,  0x18341808,  0x18104c38, 
+ 0x3c181010,  0x18241c42,  0x11081008,  0x20222208,  0x00000000,  0x00220408,  0x22361804,  0x11111111, 
+ 0x00000028,  0x16b6cc00,  0x300c5418,  0x00000030,  0x66183006,  0x7e066618,  0x66060000,  0x0cfe3000, 
+ 0x9a466660,  0x66606066,  0x6618186c,  0x605a4e66,  0x60666606,  0x1862346c,  0x6c183030,  0x180c0000, 
+ 0x00666660,  0x66603066,  0x6618186c,  0x18d66666,  0x66663006,  0x3066346c,  0x2c343018,  0x18180020, 
+ 0x00091010,  0x000e0942,  0x10081008,  0x20222208,  0x0f06060f,  0x0a09041e,  0x002a0e38,  0x10101010, 
+ 0x00180028,  0x56b6cc00,  0x300c1018,  0x18001860,  0x66187e66,  0x0c666630,  0x66661818,  0x06fe6018, 
+ 0x40466632,  0x6c606036,  0x66181866,  0x605a4624,  0x60246666,  0x1834186c,  0x46186030,  0x0c0c0000, 
+ 0x006e6666,  0x6e66306e,  0x66181866,  0x18d66666,  0x666e3066,  0x306e186c,  0x46186030,  0x180c003c, 
+ 0x08090909,  0x1f110aff,  0x0e081008,  0x382c2208,  0x08020901,  0x0a0a0911,  0x09220907,  0x0e0e0e0e, 
+ 0x00180028,  0x7c1c7600,  0x18180000,  0x18001860,  0x3c7e7e3c,  0x0c3c3c30,  0x3c3c1818,  0x02004018, 
+ 0x3e467c1e,  0x787e601e,  0x663c1866,  0x7e42463c,  0x603c663c,  0x1818186c,  0x66187e30,  0x0c0c0000, 
+ 0x00367c3c,  0x363c7c36,  0x667e1866,  0x7ed6663c,  0x7c367c3c,  0x1e36186c,  0x66187e30,  0x180c0008, 
+ 0x080f0606,  0x04110c18,  0x01081008,  0x20222208,  0x0e020203,  0x0a0c0d1e,  0x0d220e08,  0x01010101, 
+ 0x00000000,  0x10000000,  0x18180000,  0x080000c0,  0x00000000,  0x00000000,  0x00000008,  0x00000000, 
+ 0x00000000,  0x00000000,  0x00001800,  0x00000000,  0x000c0000,  0x00000000,  0x00000030,  0x060c00fe, 
+ 0x00000000,  0x00000006,  0x00001800,  0x00000000,  0x60060000,  0x00000000,  0x0010001c,  0x18380008, 
+ 0x08090606,  0x040e0a18,  0x11081f08,  0x20221c3e,  0x08020401,  0x0f0a0b11,  0x0b220908,  0x11111111, 
+ 0x00000000,  0x00000000,  0x0c300000,  0x080000c0,  0x00000000,  0x00000000,  0x00000008,  0x00000000, 
+ 0x00000000,  0x00000000,  0x00007000,  0x00000000,  0x00060000,  0x00000000,  0x0000003c,  0x063c0000, 
+ 0x00000000,  0x00000066,  0x00001800,  0x00000000,  0x60060000,  0x00000000,  0x00300000,  0x00000008, 
+ 0x0f090909,  0x04030900,  0x0e000000,  0x00000000,  0x0f0f0f0f,  0x0209091e,  0x09000f07,  0x0e0e0e0e, 
+ 0x00000000,  0x00000000,  0x00000000,  0x10000000,  0x00000000,  0x00000000,  0x00000010,  0x00000000, 
+ 0x00000000,  0x00000000,  0x00000000,  0x00000000,  0x00000000,  0x00000000,  0x00000000,  0x00000000, 
+ 0x00000000,  0x0000003c,  0x00007000,  0x00000000,  0x60060000,  0x00000000,  0x00600000,  0x0000000f, 
+
+};
+
+static GBitmap strike0 = {
+	bits0,
+	0,
+	32,
+	0,
+	{0, 0, 1024, 14},
+	{0, 0, 1024, 14},
+};
+
+static Fontchar info0[] = {
+	{ 0, 0, 14, 0, 8 },
+	{ 8, 0, 14, 0, 8 },
+	{ 16, 0, 14, 0, 8 },
+	{ 24, 0, 14, 0, 8 },
+	{ 32, 0, 14, 0, 8 },
+	{ 40, 0, 14, 0, 8 },
+	{ 48, 0, 14, 0, 8 },
+	{ 56, 0, 14, 0, 8 },
+	{ 64, 0, 14, 0, 8 },
+	{ 72, 0, 14, 0, 8 },
+	{ 80, 0, 14, 0, 8 },
+	{ 88, 0, 14, 0, 8 },
+	{ 96, 0, 14, 0, 8 },
+	{ 104, 0, 14, 0, 8 },
+	{ 112, 0, 14, 0, 8 },
+	{ 120, 0, 14, 0, 8 },
+	{ 128, 0, 14, 0, 8 },
+	{ 136, 0, 14, 0, 8 },
+	{ 144, 0, 14, 0, 8 },
+	{ 152, 0, 14, 0, 8 },
+	{ 160, 0, 14, 0, 8 },
+	{ 168, 0, 14, 0, 8 },
+	{ 176, 0, 14, 0, 8 },
+	{ 184, 0, 14, 0, 8 },
+	{ 192, 0, 14, 0, 8 },
+	{ 200, 0, 14, 0, 8 },
+	{ 208, 0, 14, 0, 8 },
+	{ 216, 0, 14, 0, 8 },
+	{ 224, 0, 14, 0, 8 },
+	{ 232, 0, 14, 0, 8 },
+	{ 240, 0, 14, 0, 8 },
+	{ 248, 0, 14, 0, 8 },
+	{ 256, 0, 0, 0, 8 },
+	{ 264, 2, 11, 0, 8 },
+	{ 272, 2, 6, 0, 8 },
+	{ 280, 2, 11, 0, 8 },
+	{ 288, 1, 12, 0, 8 },
+	{ 296, 2, 11, 0, 8 },
+	{ 304, 2, 11, 0, 8 },
+	{ 312, 2, 7, 0, 8 },
+	{ 320, 1, 13, 0, 8 },
+	{ 328, 1, 13, 0, 8 },
+	{ 336, 3, 10, 0, 8 },
+	{ 344, 4, 10, 0, 8 },
+	{ 352, 9, 14, 0, 8 },
+	{ 360, 6, 8, 0, 8 },
+	{ 368, 9, 11, 0, 8 },
+	{ 376, 1, 13, 0, 8 },
+	{ 384, 2, 11, 0, 8 },
+	{ 392, 2, 11, 0, 8 },
+	{ 400, 2, 11, 0, 8 },
+	{ 408, 2, 11, 0, 8 },
+	{ 416, 2, 11, 0, 8 },
+	{ 424, 2, 11, 0, 8 },
+	{ 432, 2, 11, 0, 8 },
+	{ 440, 2, 11, 0, 8 },
+	{ 448, 2, 11, 0, 8 },
+	{ 456, 2, 11, 0, 8 },
+	{ 464, 4, 11, 0, 8 },
+	{ 472, 4, 14, 0, 8 },
+	{ 480, 2, 11, 0, 8 },
+	{ 488, 4, 10, 0, 8 },
+	{ 496, 2, 11, 0, 8 },
+	{ 504, 2, 11, 0, 8 },
+	{ 512, 2, 11, 0, 8 },
+	{ 520, 2, 11, 0, 8 },
+	{ 528, 2, 11, 0, 8 },
+	{ 536, 2, 11, 0, 8 },
+	{ 544, 2, 11, 0, 8 },
+	{ 552, 2, 11, 0, 8 },
+	{ 560, 2, 11, 0, 8 },
+	{ 568, 2, 11, 0, 8 },
+	{ 576, 2, 11, 0, 8 },
+	{ 584, 2, 11, 0, 8 },
+	{ 592, 2, 13, 0, 8 },
+	{ 600, 2, 11, 0, 8 },
+	{ 608, 2, 11, 0, 8 },
+	{ 616, 2, 11, 0, 8 },
+	{ 624, 2, 11, 0, 8 },
+	{ 632, 2, 11, 0, 8 },
+	{ 640, 2, 11, 0, 8 },
+	{ 648, 2, 13, 0, 8 },
+	{ 656, 2, 11, 0, 8 },
+	{ 664, 2, 11, 0, 8 },
+	{ 672, 2, 11, 0, 8 },
+	{ 680, 2, 11, 0, 8 },
+	{ 688, 2, 11, 0, 8 },
+	{ 696, 2, 11, 0, 8 },
+	{ 704, 2, 11, 0, 8 },
+	{ 712, 2, 11, 0, 8 },
+	{ 720, 2, 11, 0, 8 },
+	{ 728, 1, 13, 0, 8 },
+	{ 736, 1, 13, 0, 8 },
+	{ 744, 1, 13, 0, 8 },
+	{ 752, 2, 8, 0, 8 },
+	{ 760, 11, 12, 0, 8 },
+	{ 768, 2, 7, 0, 8 },
+	{ 776, 4, 11, 0, 8 },
+	{ 784, 1, 11, 0, 8 },
+	{ 792, 4, 11, 0, 8 },
+	{ 800, 1, 11, 0, 8 },
+	{ 808, 4, 11, 0, 8 },
+	{ 816, 1, 11, 0, 8 },
+	{ 824, 4, 14, 0, 8 },
+	{ 832, 1, 11, 0, 8 },
+	{ 840, 1, 11, 0, 8 },
+	{ 848, 1, 14, 0, 8 },
+	{ 856, 1, 11, 0, 8 },
+	{ 864, 1, 11, 0, 8 },
+	{ 872, 4, 11, 0, 8 },
+	{ 880, 4, 11, 0, 8 },
+	{ 888, 4, 11, 0, 8 },
+	{ 896, 4, 14, 0, 8 },
+	{ 904, 4, 14, 0, 8 },
+	{ 912, 4, 11, 0, 8 },
+	{ 920, 4, 11, 0, 8 },
+	{ 928, 2, 11, 0, 8 },
+	{ 936, 4, 11, 0, 8 },
+	{ 944, 4, 11, 0, 8 },
+	{ 952, 4, 11, 0, 8 },
+	{ 960, 4, 11, 0, 8 },
+	{ 968, 4, 14, 0, 8 },
+	{ 976, 4, 11, 0, 8 },
+	{ 984, 1, 12, 0, 8 },
+	{ 992, 1, 12, 0, 8 },
+	{ 1000, 1, 12, 0, 8 },
+	{ 1008, 5, 8, 0, 8 },
+	{ 1016, 0, 14, 0, 8 },
+	{ 1024, 0, 14, 0, 8 },
+	{ 0, 0, 0, 0, 0 }
+};
+
+GSubfont defont0 = {
+	129,
+	14,
+	2,
+	info0,
+	&strike0,
+};
--- /dev/null
+++ b/os/boot.original/rpcg/devether.c
@@ -1,0 +1,157 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+#include "etherif.h"
+
+static Ctlr ether[MaxEther];
+
+static struct {
+	char	*type;
+	int	(*reset)(Ctlr*);
+} cards[] = {
+	{ "SCC", sccethreset, },
+	{ "SCC2", sccethreset, },
+	{ 0, }
+};
+
+int
+etherinit(void)
+{
+	Ctlr *ctlr;
+	int ctlrno, i, mask, n;
+
+	mask = 0;
+	for(ctlrno = 0; ctlrno < MaxEther; ctlrno++){
+		ctlr = &ether[ctlrno];
+		memset(ctlr, 0, sizeof(Ctlr));
+		if(archether(ctlrno, &ctlr->card) <= 0)
+			continue;
+		for(n = 0; cards[n].type; n++){
+			if(strcmp(cards[n].type, ctlr->card.type))
+				continue;
+			ctlr->ctlrno = ctlrno;
+			if((*cards[n].reset)(ctlr))
+				break;
+
+			ctlr->iq = qopen(16*1024, 1, 0, 0);
+			ctlr->oq = qopen(16*1024, 1, 0, 0);
+
+			ctlr->present = 1;
+			mask |= 1<<ctlrno;
+
+			print("ether%d: %s: port 0x%luX irq %d",
+				ctlr->ctlrno, ctlr->card.type, ctlr->card.port, ctlr->card.irq);
+			if(ctlr->card.mem)
+				print(" addr 0x%luX", PADDR(ctlr->card.mem));
+			if(ctlr->card.size)
+				print(" size 0x%luX", ctlr->card.size);
+			print(":");
+			for(i = 0; i < sizeof(ctlr->card.ea); i++)
+				print(" %2.2uX", ctlr->card.ea[i]);
+			print("\n"); uartwait();
+			setvec(VectorPIC + ctlr->card.irq, ctlr->card.intr, ctlr);
+			break;
+		}
+	}
+
+	return mask;
+}
+
+static Ctlr*
+attach(int ctlrno)
+{
+	Ctlr *ctlr;
+
+	if(ctlrno >= MaxEther || ether[ctlrno].present == 0)
+		return 0;
+
+	ctlr = &ether[ctlrno];
+	if(ctlr->present == 1){
+		ctlr->present = 2;
+		(*ctlr->card.attach)(ctlr);
+	}
+
+	return ctlr;
+}
+
+uchar*
+etheraddr(int ctlrno)
+{
+	Ctlr *ctlr;
+
+	if((ctlr = attach(ctlrno)) == 0)
+		return 0;
+
+	return ctlr->card.ea;
+}
+
+int
+etherrxpkt(int ctlrno, Etherpkt *pkt, int timo)
+{
+	int n;
+	Ctlr *ctlr;
+	Block *b;
+	ulong start;
+
+	if((ctlr = attach(ctlrno)) == 0)
+		return 0;
+
+	start = m->ticks;
+	while((b = qget(ctlr->iq)) == 0){
+		if(TK2MS(m->ticks - start) >= timo){
+			/*
+			print("ether%d: rx timeout\n", ctlrno);
+			 */
+			return 0;
+		}
+	}
+
+	n = BLEN(b);
+	memmove(pkt, b->rp, n);
+	freeb(b);
+
+	return n;
+}
+
+int
+etheriq(Ctlr *ctlr, Block *b, int freebp)
+{
+	if(memcmp(((Etherpkt*)b->rp)->d, ctlr->card.ea, Eaddrlen) != 0 &&
+	   memcmp(((Etherpkt*)b->rp)->d, broadcast, Eaddrlen) != 0){
+		if(freebp)
+			freeb(b);
+		return 0;
+	}
+	qbwrite(ctlr->iq, b);
+	return 1;
+}
+
+int
+ethertxpkt(int ctlrno, Etherpkt *pkt, int len, int)
+{
+	Ctlr *ctlr;
+	Block *b;
+	int s;
+
+	if((ctlr = attach(ctlrno)) == 0)
+		return 0;
+
+	if(qlen(ctlr->oq) > 16*1024){
+		print("ether%d: tx queue full\n", ctlrno);
+		return 0;
+	}
+	b = iallocb(sizeof(Etherpkt));
+	memmove(b->wp, pkt, len);
+	memmove(((Etherpkt*)b->wp)->s, ctlr->card.ea, Eaddrlen);
+	b->wp += len;
+	qbwrite(ctlr->oq, b);
+	s = splhi();
+	(*ctlr->card.transmit)(ctlr);
+	splx(s);
+
+	return 1;
+}
--- /dev/null
+++ b/os/boot.original/rpcg/devuart.c
@@ -1,0 +1,230 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+/*
+ *  SMC1 in UART mode
+ */
+
+typedef struct Uartsmc Uartsmc;
+struct Uartsmc {
+	IOCparam;
+	ushort	maxidl;
+	ushort	idlc;
+	ushort	brkln;
+	ushort	brkec;
+	ushort	brkcr;
+	ushort	rmask;
+};
+
+typedef struct Uart	Uart;
+struct Uart
+{
+	int	port;
+	int	setup;
+	uchar	txbusy;
+
+	Queue*	iq;
+	Queue*	oq;
+	void	(*rx)(Queue*, int);
+	void	(*boot)(uchar*, int);
+
+	ulong	frame;
+	ulong	overrun;
+	uchar	rxbuf[128];
+	char	txbuf[16];
+	BD*	rxb;
+	BD*	txb;
+};
+
+Uart	uart[1];
+int	predawn = 1;
+
+static	void	uartintr(Ureg*, void*);
+static	void	uartkick(void*);
+
+static int
+baudgen(int baud)
+{
+	int d;
+
+	d = ((m->cpuhz/baud)+8)>>4;
+	if(d >= (1<<12))
+		return ((d+15)>>3)|1;
+	return d<<1;
+}
+
+static void
+smcsetup(Uart *up, int baud)
+{
+	IMM *io;
+	Uartsmc *p;
+	BD *bd;
+	SMC *smc;
+
+	archenableuart(SMC1ID, 0);
+	io = m->iomem;
+	io->pbpar |= IBIT(24)|IBIT(25);	/* enable SMC1 TX/RX */
+	io->pbdir &= ~(IBIT(24)|IBIT(25));
+	io->brgc1 = baudgen(baud) | BaudEnable;
+	io->simode &= ~0xF000;	/* SMC1 to NMSI mode, Tx/Rx clocks are BRG1 */
+
+	bd = bdalloc(1);
+	p = (Uartsmc*)KADDR(SMC1P);
+	p->rbase = (ushort)bd;
+	up->rxb = bd;
+	bd->status = BDEmpty|BDWrap|BDInt;
+	bd->length = 0;
+	bd->addr = PADDR(up->rxbuf);
+	bd = bdalloc(1);
+	p->tbase = (ushort)bd;
+	up->txb = bd;
+	bd->status = BDWrap|BDInt;
+	bd->length = 0;
+	bd->addr = PADDR(up->txbuf);
+
+	cpmop(InitRxTx, SMC1ID, 0);
+
+	/* protocol parameters */
+	p->rfcr = 0x18;
+	p->tfcr = 0x18;
+	p->mrblr = 1;
+	p->maxidl = 1;
+	p->brkln = 0;
+	p->brkec = 0;
+	p->brkcr = 1;
+	smc = IOREGS(0xA80, SMC);
+	smc->smce = 0xff;	/* clear events */
+	smc->smcm = 0x17;	/* enable all possible interrupts */
+	setvec(VectorCPIC+4, uartintr, up);
+	smc->smcmr = 0x4820;	/* 8-bit mode, no parity, 1 stop bit, UART mode, ... */
+	smc->smcmr |= 3;	/* enable rx/tx */
+}
+
+static void
+uartintr(Ureg*, void *arg)
+{
+	Uart *up;
+	int ch, i;
+	BD *bd;
+	SMC *smc;
+	Block *b;
+
+	up = arg;
+	smc = IOREGS(0xA80, SMC);
+	smc->smce = 0xff;	/* clear all events */
+	if((bd = up->rxb) != nil && (bd->status & BDEmpty) == 0){
+		if(up->iq != nil && bd->length > 0){
+			if(up->boot != nil){
+				up->boot(up->rxbuf, bd->length);
+			}else if(up->rx != nil){
+				for(i=0; i<bd->length; i++){
+					ch = up->rxbuf[i];
+					up->rx(up->iq, ch);
+				}
+			}else{
+				b = iallocb(bd->length);
+				memmove(b->wp, up->rxbuf, bd->length);
+				b->wp += bd->length;
+				qbwrite(up->iq, b);
+			}
+		}
+		bd->status |= BDEmpty|BDInt;
+	} else if((bd = up->txb) != nil && (bd->status & BDReady) == 0){
+		ch = -1;
+		if(up->oq)
+			ch = qbgetc(up->oq);
+		if(ch != -1){
+			up->txbuf[0] = ch;
+			bd->length = 1;
+			bd->status |= BDReady;
+		}else
+			up->txbusy = 0;
+	}
+	/* TO DO: modem status, errors, etc */
+}
+
+static void
+uartkick(void *arg)
+{
+	Uart *up = arg;
+	int s, c, i;
+
+	s = splhi();
+	while(up->txbusy == 0 && (c = qbgetc(up->oq)) != -1){
+		if(predawn){
+			while(up->txb->status & BDReady)
+				;
+		} else {
+			for(i = 0; i < 100; i++){
+				if((up->txb->status & BDReady) == 0)
+					break;
+				delay(1);
+			}
+		}
+		up->txbuf[0] = c;
+		up->txb->length = 1;
+		up->txb->status |= BDReady;
+		up->txbusy = !predawn;
+	}
+	splx(s);
+}
+
+void
+uartspecial(int port, int baud, Queue **iq, Queue **oq, void (*rx)(Queue*,int))
+{
+	Uart *up = &uart[0];
+
+	if(up->setup)
+		return;
+	up->setup = 1;
+
+	*iq = up->iq = qopen(4*1024, 0, 0, 0);
+	*oq = up->oq = qopen(16*1024, 0, uartkick, up);
+	up->rx = rx;
+	USED(port);
+	up->port = SMC1ID;
+	if(baud == 0)
+		baud = 9600;
+	smcsetup(up, baud);
+	/* if using SCCn's UART, would also set DTR and RTS, but SMC doesn't use them */
+}
+
+void
+uartsetboot(void (*f)(uchar*, int))
+{
+	uart[0].boot = f;
+}
+
+void
+uartputs(char *s, int n)
+{
+	Uart *up = &uart[0];
+	Block *b;
+	int nl;
+	char *p;
+
+	nl = 0;
+	for(p = s; p < s+n; p++)
+		if(*p == '\n')
+			nl++;
+	b = iallocb(n+nl);
+	while(n--){
+		if(*s == '\n')
+			*b->wp++ = '\r';
+		*b->wp++ = *s++;
+	}
+	qbwrite(up->oq, b);
+}
+
+void
+uartwait(void)
+{
+	Uart *up = &uart[0];
+
+	while(up->txbusy)
+		;
+}
--- /dev/null
+++ b/os/boot.original/rpcg/dload.c
@@ -1,0 +1,103 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+#include <mach.h>
+
+static	char	*kernelfile = "/power/ipaq";
+ulong	crc32(void *buf, int n, ulong crc);
+
+void
+main(int argc, char **argv)
+{
+	int ifd, n;
+	char buf[64], reply[1];
+	int i, execsize;
+	Fhdr f;
+	ulong csum;
+
+	ARGBEGIN{
+	}ARGEND
+	ifd = open(kernelfile, OREAD);
+	if(ifd < 0){
+		fprint(2, "dload: can't open %s: %r\n", kernelfile);
+		exits("open");
+	}
+	i = 0;
+	if(crackhdr(ifd, &f) == 0){
+		fprint(2, "dload: not an executable file: %r\n");
+		exits("format");
+	}
+	if(f.magic != Q_MAGIC){
+		fprint(2, "dload: not a powerpc executable\n");
+		exits("format");
+	}
+	execsize = f.txtsz + f.datsz + f.txtoff;
+	seek(ifd, 0, 0);
+	csum = ~0;
+	while(execsize > 0 && (n = read(ifd, buf, sizeof(buf))) > 0){
+		if(n > execsize)
+			n = execsize;
+		for(;;){
+			if(write(1, buf, sizeof(buf)) != sizeof(buf)){	/* always writes full buffer */
+				fprint(2, "dload: write error: %r\n");
+				exits("write");
+			}
+			if(read(0, reply, 1) != 1){
+				fprint(2, "dload: bad reply\n");
+				exits("read");
+			}
+			if(reply[0] != 'n')
+				break;
+			fprint(2, "!");
+		}
+		if(reply[0] != 'y'){
+			fprint(2, "dload: bad ack: %c\n", reply[0]);
+			exits("reply");
+		}
+		if(++i%10 == 0)
+			fprint(2, ".");
+		execsize -= n;
+	}
+	exits(0);
+}
+
+/*
+ * from Rob Warnock
+ */
+static	ulong	crc32tab[256];	/* initialised on first call to crc32 */
+
+enum {
+	CRC32POLY = 0x04c11db7     /* AUTODIN II, Ethernet, & FDDI */
+};
+
+/*
+ * Build auxiliary table for parallel byte-at-a-time CRC-32.
+ */
+static void
+initcrc32(void)
+{
+	int i, j;
+	ulong c;
+
+	for(i = 0; i < 256; i++) {
+		for(c = i << 24, j = 8; j > 0; j--)
+			if(c & (1<<31))
+				c = (c<<1) ^ CRC32POLY;
+			else
+				c <<= 1;
+		crc32tab[i] = c;
+	}
+}
+
+ulong
+crc32(void *buf, int n, ulong crc)
+{
+	uchar *p;
+
+	if(crc32tab[1] == 0)
+		initcrc32();
+	crc = ~crc;
+	for(p = buf; --n >= 0;)
+		crc = (crc << 8) ^ crc32tab[(crc >> 24) ^ *p++];
+	return ~crc;
+}
--- /dev/null
+++ b/os/boot.original/rpcg/donprint.c
@@ -1,0 +1,332 @@
+#include	"u.h"
+#include	"lib.h"
+
+#define	PTR	sizeof(char*)
+#define	SHORT	sizeof(int)
+#define	INT	sizeof(int)
+#define	LONG	sizeof(long)
+#define	IDIGIT	30
+#define	MAXCON	30
+
+#define	FLONG	(1<<0)
+#define	FSHORT	(1<<1)
+#define	FUNSIGN	(1<<2)
+
+typedef struct Op	Op;
+struct Op
+{
+	char	*p;
+	char	*ep;
+	void	*argp;
+	int	f1;
+	int	f2;
+	int	f3;
+};
+
+static	int	noconv(Op*);
+static	int	cconv(Op*);
+static	int	dconv(Op*);
+static	int	hconv(Op*);
+static	int	lconv(Op*);
+static	int	oconv(Op*);
+static	int	sconv(Op*);
+static	int	uconv(Op*);
+static	int	xconv(Op*);
+static	int	Xconv(Op*);
+static	int	percent(Op*);
+
+static
+int	(*fmtconv[MAXCON])(Op*) =
+{
+	noconv,
+	cconv, dconv, hconv, lconv,
+	oconv, sconv, uconv, xconv,
+	Xconv, percent,
+};
+static
+char	fmtindex[128] =
+{
+	['c'] 1,
+	['d'] 2,
+	['h'] 3,
+	['l'] 4,
+	['o'] 5,
+	['s'] 6,
+	['u'] 7,
+	['x'] 8,
+	['X'] 9,
+	['%'] 10,
+};
+
+static	int	convcount  = { 11 };
+static	int	ucase;
+
+static void
+PUT(Op *o, int c)
+{
+	static int pos;
+	int opos;
+
+	if(c == '\t'){
+		opos = pos;
+		pos = (opos+8) & ~7;
+		while(opos++ < pos && o->p < o->ep)
+			*o->p++ = ' ';
+		return;
+	}
+	if(o->p < o->ep){
+		*o->p++ = c;
+		pos++;
+	}
+	if(c == '\n')
+		pos = 0;
+}
+
+int
+fmtinstall(char c, int (*f)(Op*))
+{
+
+	c &= 0177;
+	if(fmtindex[c] == 0) {
+		if(convcount >= MAXCON)
+			return 1;
+		fmtindex[c] = convcount++;
+	}
+	fmtconv[fmtindex[c]] = f;
+	return 0;
+}
+
+char*
+donprint(char *p, char *ep, char *fmt, void *argp)
+{
+	int sf1, c;
+	Op o;
+
+	o.p = p;
+	o.ep = ep;
+	o.argp = argp;
+
+loop:
+	c = *fmt++;
+	if(c != '%') {
+		if(c == 0) {
+			if(o.p < o.ep)
+				*o.p = 0;
+			return o.p;
+		}
+		PUT(&o, c);
+		goto loop;
+	}
+	o.f1 = 0;
+	o.f2 = -1;
+	o.f3 = 0;
+	c = *fmt++;
+	sf1 = 0;
+	if(c == '-') {
+		sf1 = 1;
+		c = *fmt++;
+	}
+	while(c >= '0' && c <= '9') {
+		o.f1 = o.f1*10 + c-'0';
+		c = *fmt++;
+	}
+	if(sf1)
+		o.f1 = -o.f1;
+	if(c != '.')
+		goto l1;
+	c = *fmt++;
+	while(c >= '0' && c <= '9') {
+		if(o.f2 < 0)
+			o.f2 = 0;
+		o.f2 = o.f2*10 + c-'0';
+		c = *fmt++;
+	}
+l1:
+	if(c == 0)
+		fmt--;
+	c = (*fmtconv[fmtindex[c&0177]])(&o);
+	if(c < 0) {
+		o.f3 |= -c;
+		c = *fmt++;
+		goto l1;
+	}
+	o.argp = (char*)o.argp + c;
+	goto loop;
+}
+
+void
+strconv(char *o, Op *op, int f1, int f2)
+{
+	int n, c;
+	char *p;
+
+	n = strlen(o);
+	if(f1 >= 0)
+		while(n < f1) {
+			PUT(op, ' ');
+			n++;
+		}
+	for(p=o; c = *p++;)
+		if(f2 != 0) {
+			PUT(op, c);
+			f2--;
+		}
+	if(f1 < 0) {
+		f1 = -f1;
+		while(n < f1) {
+			PUT(op, ' ');
+			n++;
+		}
+	}
+}
+
+int
+numbconv(Op *op, int base)
+{
+	char b[IDIGIT];
+	int i, f, n, r;
+	long v;
+	short h;
+
+	f = 0;
+	switch(op->f3 & (FLONG|FSHORT|FUNSIGN)) {
+	case FLONG:
+		v = *(long*)op->argp;
+		r = LONG;
+		break;
+
+	case FUNSIGN|FLONG:
+		v = *(ulong*)op->argp;
+		r = LONG;
+		break;
+
+	case FSHORT:
+		h = *(int*)op->argp;
+		v = h;
+		r = SHORT;
+		break;
+
+	case FUNSIGN|FSHORT:
+		h = *(int*)op->argp;
+		v = (ushort)h;
+		r = SHORT;
+		break;
+
+	default:
+		v = *(int*)op->argp;
+		r = INT;
+		break;
+
+	case FUNSIGN:
+		v = *(unsigned*)op->argp;
+		r = INT;
+		break;
+	}
+	if(!(op->f3 & FUNSIGN) && v < 0) {
+		v = -v;
+		f = 1;
+	}
+	b[IDIGIT-1] = 0;
+	for(i = IDIGIT-2;; i--) {
+		n = (ulong)v % base;
+		n += '0';
+		if(n > '9'){
+			n += 'a' - ('9'+1);
+			if(ucase)
+				n += 'A'-'a';
+		}
+		b[i] = n;
+		if(i < 2)
+			break;
+		v = (ulong)v / base;
+		if(op->f2 >= 0 && i >= IDIGIT-op->f2)
+			continue;
+		if(v <= 0)
+			break;
+	}
+	if(f)
+		b[--i] = '-';
+	strconv(b+i, op, op->f1, -1);
+	return r;
+}
+
+static	int
+noconv(Op *op)
+{
+
+	strconv("***", op, 0, -1);
+	return 0;
+}
+
+static	int
+cconv(Op *op)
+{
+	char b[2];
+
+	b[0] = *(int*)op->argp;
+	b[1] = 0;
+	strconv(b, op, op->f1, -1);
+	return INT;
+}
+
+static	int
+dconv(Op *op)
+{
+	return numbconv(op, 10);
+}
+
+static	int
+hconv(Op*)
+{
+	return -FSHORT;
+}
+
+static	int
+lconv(Op*)
+{
+	return -FLONG;
+}
+
+static	int
+oconv(Op *op)
+{
+	return numbconv(op, 8);
+}
+
+static	int
+sconv(Op *op)
+{
+	strconv(*(char**)op->argp, op, op->f1, op->f2);
+	return PTR;
+}
+
+static	int
+uconv(Op*)
+{
+	return -FUNSIGN;
+}
+
+static	int
+xconv(Op *op)
+{
+	return numbconv(op, 16);
+}
+
+static	int
+Xconv(Op *op)
+{
+	int r;
+
+	ucase = 1;
+	r = numbconv(op, 16);
+	ucase = 0;
+	return r;
+}
+
+static	int
+percent(Op *op)
+{
+
+	PUT(op, '%');
+	return 0;
+}
--- /dev/null
+++ b/os/boot.original/rpcg/dosboot.c
@@ -1,0 +1,614 @@
+#include	"u.h"
+#include	"lib.h"
+#include	"mem.h"
+#include	"dat.h"
+#include	"fns.h"
+#include	"dosfs.h"
+
+extern char *premature;
+
+/*
+ *  predeclared
+ */
+static void	bootdump(Dosboot*);
+static void	setname(Dosfile*, char*);
+long		dosreadseg(Dosfile*, long, long);
+
+/*
+ *  debugging
+ */
+#define chatty	1
+#define chat	if(chatty)print
+
+/*
+ *  block io buffers
+ */
+enum
+{
+	Nbio=	16,
+};
+typedef struct	Clustbuf	Clustbuf;
+struct Clustbuf
+{
+	int	age;
+	long	sector;
+	uchar	*iobuf;
+	Dos	*dos;
+	int	size;
+};
+Clustbuf	bio[Nbio];
+
+/*
+ *  get an io block from an io buffer
+ */
+Clustbuf*
+getclust(Dos *dos, long sector)
+{
+	Clustbuf *p, *oldest;
+	int size;
+
+	chat("getclust @ %d\n", sector);
+
+	/*
+	 *  if we have it, just return it
+	 */
+	for(p = bio; p < &bio[Nbio]; p++){
+		if(sector == p->sector && dos == p->dos){
+			p->age = m->ticks;
+			chat("getclust %d in cache\n", sector);
+			return p;
+		}
+	}
+
+	/*
+	 *  otherwise, reuse the oldest entry
+	 */
+	oldest = bio;
+	for(p = &bio[1]; p < &bio[Nbio]; p++){
+		if(p->age <= oldest->age)
+			oldest = p;
+	}
+	p = oldest;
+
+	/*
+	 *  make sure the buffer is big enough
+	 */
+	size = dos->clustsize*dos->sectsize;
+	if(p->iobuf==0 || p->size < size)
+		p->iobuf = ialloc(size, 0);
+	p->size = size;
+
+	/*
+	 *  read in the cluster
+	 */
+	chat("getclust addr %d\n", (sector+dos->start)*dos->sectsize);
+	if((*dos->seek)(dos->dev, (sector+dos->start)*dos->sectsize) < 0){
+		chat("can't seek block\n");
+		return 0;
+	}
+	if((*dos->read)(dos->dev, p->iobuf, size) != size){
+		chat("can't read block\n");
+		return 0;
+	}
+
+	p->age = m->ticks;
+	p->dos = dos;
+	p->sector = sector;
+	chat("getclust %d read\n", sector);
+	return p;
+}
+
+/*
+ *  walk the fat one level ( n is a current cluster number ).
+ *  return the new cluster number or -1 if no more.
+ */
+static long
+fatwalk(Dos *dos, int n)
+{
+	ulong k, sect;
+	Clustbuf *p;
+	int o;
+
+	chat("fatwalk %d\n", n);
+
+	if(n < 2 || n >= dos->fatclusters)
+		return -1;
+
+	switch(dos->fatbits){
+	case 12:
+		k = (3*n)/2; break;
+	case 16:
+		k = 2*n; break;
+	default:
+		return -1;
+	}
+	if(k >= dos->fatsize*dos->sectsize)
+		panic("getfat");
+
+	sect = (k/(dos->sectsize*dos->clustsize))*dos->clustsize + dos->fataddr;
+	o = k%(dos->sectsize*dos->clustsize);
+	p = getclust(dos, sect);
+	k = p->iobuf[o++];
+	if(o >= dos->sectsize*dos->clustsize){
+		p = getclust(dos, sect+dos->clustsize);
+		o = 0;
+	}
+	k |= p->iobuf[o]<<8;
+	if(dos->fatbits == 12){
+		if(n&1)
+			k >>= 4;
+		else
+			k &= 0xfff;
+		if(k >= 0xff8)
+			k |= 0xf000;
+	}
+	k = k < 0xfff8 ? k : -1;
+	chat("fatwalk %d -> %d\n", n, k);
+	return k;
+}
+
+/*
+ *  map a file's logical cluster address to a physical sector address
+ */
+static long
+fileaddr(Dosfile *fp, long ltarget)
+{
+	Dos *dos = fp->dos;
+	long l;
+	long p;
+
+	chat("fileaddr %8.8s %d\n", fp->name, ltarget);
+	/*
+	 *  root directory is contiguous and easy
+	 */
+	if(fp->pstart == 0){
+		if(ltarget*dos->sectsize*dos->clustsize >= dos->rootsize*sizeof(Dosdir))
+			return -1;
+		l = dos->rootaddr + ltarget*dos->clustsize;
+		chat("fileaddr %d -> %d\n", ltarget, l);
+		return l;
+	}
+
+	/*
+	 *  anything else requires a walk through the fat
+	 */
+	if(ltarget >= fp->lcurrent && fp->pcurrent){
+		/* start at the currrent point */
+		l = fp->lcurrent;
+		p = fp->pcurrent;
+	} else {
+		/* go back to the beginning */
+		l = 0;
+		p = fp->pstart;
+	}
+	while(l != ltarget){
+		/* walk the fat */
+		p = fatwalk(dos, p);
+		if(p < 0)
+			return -1;
+		l++;
+	}
+	fp->lcurrent = l;
+	fp->pcurrent = p;
+
+	/*
+	 *  clusters start at 2 instead of 0 (why? - presotto)
+	 */
+	l =  dos->dataaddr + (p-2)*dos->clustsize;
+	chat("fileaddr %d -> %d\n", ltarget, l);
+	return l;
+}
+
+/*
+ *  read from a dos file
+ */
+long
+dosread(Dosfile *fp, void *a, long n)
+{
+	long addr;
+	long rv;
+	int i;
+	int off;
+	Clustbuf *p;
+	uchar *from, *to;
+
+	if((fp->attr & DDIR) == 0){
+		if(fp->offset >= fp->length)
+			return 0;
+		if(fp->offset+n > fp->length)
+			n = fp->length - fp->offset;
+	}
+
+	to = a;
+	for(rv = 0; rv < n; rv+=i){
+		/*
+		 *  read the cluster
+		 */
+		addr = fileaddr(fp, fp->offset/fp->dos->clustbytes);
+		if(addr < 0)
+			return -1;
+		p = getclust(fp->dos, addr);
+		if(p == 0)
+			return -1;
+
+		/*
+		 *  copy the bytes we need
+		 */
+		off = fp->offset % fp->dos->clustbytes;
+		from = &p->iobuf[off];
+		i = n - rv;
+		if(i > fp->dos->clustbytes - off)
+			i = fp->dos->clustbytes - off;
+		memmove(to, from, i);
+		to += i;
+		fp->offset += i;
+	}
+
+	return rv;
+}
+
+/*
+ *  walk a directory returns
+ * 	-1 if something went wrong
+ *	 0 if not found
+ *	 1 if found
+ */
+int
+doswalk(Dosfile *file, char *name)
+{
+	Dosdir d;
+	long n;
+
+	if((file->attr & DDIR) == 0){
+		chat("walking non-directory!\n");
+		return -1;
+	}
+
+	setname(file, name);
+
+	file->offset = 0;	/* start at the beginning */
+	while((n = dosread(file, &d, sizeof(d))) == sizeof(d)){
+		chat("comparing to %8.8s.%3.3s\n", d.name, d.ext);
+		if(memcmp(file->name, d.name, sizeof(d.name)) != 0)
+			continue;
+		if(memcmp(file->ext, d.ext, sizeof(d.ext)) != 0)
+			continue;
+		if(d.attr & DVLABEL){
+			chat("%8.8s.%3.3s is a LABEL\n", d.name, d.ext);
+			continue;
+		}
+		file->attr = d.attr;
+		file->pstart = GSHORT(d.start);
+		file->length = GLONG(d.length);
+		file->pcurrent = 0;
+		file->lcurrent = 0;
+		file->offset = 0;
+		return 1;
+	}
+	return n >= 0 ? 0 : -1;
+}
+
+
+/*
+ *  instructions that boot blocks can start with
+ */
+#define	JMPSHORT	0xeb
+#define JMPNEAR		0xe9
+
+/*
+ *  read dos file system properties
+ */
+int
+dosinit(Dos *dos, int start, int ishard)
+{
+	Dosboot *b;
+	int i;
+	Clustbuf *p;
+	Dospart *dp;
+	ulong mbroffset, offset;
+
+	/* defaults till we know better */
+	dos->start = start;
+	dos->sectsize = 512;
+	dos->clustsize = 1;
+	mbroffset = 0;
+
+dmddo:
+	/* get first sector */
+	p = getclust(dos, mbroffset);
+	if(p == 0){
+		chat("can't read boot block\n");
+		return -1;
+	}
+
+	/*
+	 * If it's a hard disc then look for an MBR and pick either an
+	 * active partition or the FAT with the lowest starting LBA.
+	 * Things are tricky because we could be pointing to, amongst others:
+	 *	1) a floppy BPB;
+	 *	2) a hard disc MBR;
+	 *	3) a hard disc extended partition table;
+	 *	4) a logical drive on a hard disc;
+	 *	5) a disc-manager boot block.
+	 * They all have the same magic at the end of the block.
+	 */
+	if(p->iobuf[0x1FE] != 0x55 || p->iobuf[0x1FF] != 0xAA) {
+		chat("not DOS\n");
+		return -1;
+	}
+	p->dos = 0;
+	b = (Dosboot *)p->iobuf;
+	if(ishard && b->mediadesc != 0xF8){
+		dp = (Dospart*)&p->iobuf[0x1BE];
+		offset = 0xFFFFFFFF;
+		for(i = 0; i < 4; i++, dp++){
+			if(dp->type == DMDDO){
+				mbroffset = 63;
+				goto dmddo;
+			}
+			if(dp->type != FAT12 && dp->type != FAT16 && dp->type != FATHUGE)
+				continue;
+			if(dp->flag & 0x80){
+				offset = GLONG(dp->start);
+				break;
+			}
+			if(GLONG(dp->start) < offset)
+				offset = GLONG(dp->start);
+		}
+		if(i != 4 || offset != 0xFFFFFFFF){
+			dos->start = mbroffset+offset;
+			p = getclust(dos, 0);
+			if(p == 0 || p->iobuf[0x1FE] != 0x55 || p->iobuf[0x1FF] != 0xAA)
+				return -1;
+		}
+		p->dos = 0;
+	}
+
+	b = (Dosboot *)p->iobuf;
+	if(b->magic[0] != JMPNEAR && (b->magic[0] != JMPSHORT || b->magic[2] != 0x90)){
+		chat("no dos file system\n");
+		return -1;
+	}
+
+	if(chatty)
+		bootdump(b);
+
+	/*
+	 *  determine the systems' wondersous properties
+	 */
+	dos->sectsize = GSHORT(b->sectsize);
+	dos->clustsize = b->clustsize;
+	dos->clustbytes = dos->sectsize*dos->clustsize;
+	dos->nresrv = GSHORT(b->nresrv);
+	dos->nfats = b->nfats;
+	dos->rootsize = GSHORT(b->rootsize);
+	dos->volsize = GSHORT(b->volsize);
+	if(dos->volsize == 0)
+		dos->volsize = GLONG(b->bigvolsize);
+	dos->mediadesc = b->mediadesc;
+	dos->fatsize = GSHORT(b->fatsize);
+	dos->fataddr = dos->nresrv;
+	dos->rootaddr = dos->fataddr + dos->nfats*dos->fatsize;
+	i = dos->rootsize*sizeof(Dosdir) + dos->sectsize - 1;
+	i = i/dos->sectsize;
+	dos->dataaddr = dos->rootaddr + i;
+	dos->fatclusters = 2+(dos->volsize - dos->dataaddr)/dos->clustsize;
+	if(dos->fatclusters < 4087)
+		dos->fatbits = 12;
+	else
+		dos->fatbits = 16;
+	dos->freeptr = 2;
+
+	/*
+	 *  set up the root
+	 */
+	dos->root.dos = dos;
+	dos->root.pstart = 0;
+	dos->root.pcurrent = dos->root.lcurrent = 0;
+	dos->root.offset = 0;
+	dos->root.attr = DDIR;
+	dos->root.length = dos->rootsize*sizeof(Dosdir);
+
+	return 0;
+}
+
+static void
+bootdump(Dosboot *b)
+{
+	if(chatty == 0)
+		return;
+	print("magic: 0x%2.2x 0x%2.2x 0x%2.2x\n",
+		b->magic[0], b->magic[1], b->magic[2]);
+	print("version: \"%8.8s\"\n", b->version);
+	print("sectsize: %d\n", GSHORT(b->sectsize));
+	print("allocsize: %d\n", b->clustsize);
+	print("nresrv: %d\n", GSHORT(b->nresrv));
+	print("nfats: %d\n", b->nfats);
+	print("rootsize: %d\n", GSHORT(b->rootsize));
+	print("volsize: %d\n", GSHORT(b->volsize));
+	print("mediadesc: 0x%2.2x\n", b->mediadesc);
+	print("fatsize: %d\n", GSHORT(b->fatsize));
+	print("trksize: %d\n", GSHORT(b->trksize));
+	print("nheads: %d\n", GSHORT(b->nheads));
+	print("nhidden: %d\n", GLONG(b->nhidden));
+	print("bigvolsize: %d\n", GLONG(b->bigvolsize));
+	print("driveno: %d\n", b->driveno);
+	print("reserved0: 0x%2.2x\n", b->reserved0);
+	print("bootsig: 0x%2.2x\n", b->bootsig);
+	print("volid: 0x%8.8x\n", GLONG(b->volid));
+	print("label: \"%11.11s\"\n", b->label);
+}
+
+/*
+ *  grab next element from a path, return the pointer to unprocessed portion of
+ *  path.
+ */
+static char *
+nextelem(char *path, char *elem)
+{
+	int i;
+
+	while(*path == '/')
+		path++;
+	if(*path==0 || *path==' ')
+		return 0;
+	for(i=0; *path!='\0' && *path!='/' && *path!=' '; i++){
+		if(i==28){
+			print("name component too long\n");
+			return 0;
+		}
+		*elem++ = *path++;
+	}
+	*elem = '\0';
+	return path;
+}
+
+int
+dosstat(Dos *dos, char *path, Dosfile *f)
+{
+	char element[NAMELEN];
+
+	*f = dos->root;
+	while(path = nextelem(path, element)){
+		switch(doswalk(f, element)){
+		case -1:
+			return -1;
+		case 0:
+			return 0;
+		}
+	}
+	return 1;
+}
+
+/*
+ *  boot
+ */
+int
+dosboot(Dos *dos, char *path)
+{
+	Dosfile file;
+	long n;
+	long addr;
+	Exec *ep;
+	void (*b)(void);
+
+	switch(dosstat(dos, path, &file)){
+
+	case -1:
+		print("error walking to %s\n", path);
+		return -1;
+	case 0:
+		print("%s not found\n", path);
+		return -1;
+	case 1:
+		print("found %8.8s.%3.3s attr 0x%ux start 0x%lux len %d\n", file.name,
+			file.ext, file.attr, file.pstart, file.length);
+		break;
+	}
+
+	/*
+	 *  read header
+	 */
+	ep = (Exec*)ialloc(sizeof(Exec), 0);
+	n = sizeof(Exec);
+	if(dosreadseg(&file, n, (ulong) ep) != n){
+		print(premature);
+		return -1;
+	}
+	if(GLLONG(ep->magic) != Q_MAGIC){
+		print("bad magic 0x%lux not a plan 9 executable!\n", GLLONG(ep->magic));
+		return -1;
+	}
+
+	/*
+	 *  read text
+	 */
+	addr = PADDR(GLLONG(ep->entry));
+	n = GLLONG(ep->text);
+	print("+%d", n);
+	if(dosreadseg(&file, n, addr) != n){
+		print(premature);
+		return -1;
+	}
+
+	/*
+	 *  read data (starts at first page after kernel)
+	 */
+	addr = PGROUND(addr+n);
+	n = GLLONG(ep->data);
+	print("+%d", n);
+	if(dosreadseg(&file, n, addr) != n){
+		print(premature);
+		return -1;
+	}
+
+	/*
+	 *  bss and entry point
+	 */
+	print("+%d\nstart at 0x%lux\n", GLLONG(ep->bss), GLLONG(ep->entry));
+
+	/*
+	 *  Go to new code. It's up to the program to get its PC relocated to
+	 *  the right place.
+	 */
+	b = (void (*)(void))(PADDR(GLLONG(ep->entry)));
+	(*b)();
+	return 0;
+}
+
+/*
+ *  read in a segment
+ */
+long
+dosreadseg(Dosfile *fp, long len, long addr)
+{
+	char *a;
+	long n, sofar;
+
+	a = (char *)addr;
+	for(sofar = 0; sofar < len; sofar += n){
+		n = 8*1024;
+		if(len - sofar < n)
+			n = len - sofar;
+		n = dosread(fp, a + sofar, n);
+		if(n <= 0)
+			break;
+		print(".");
+	}
+	return sofar;
+}
+
+/*
+ *  set up a dos file name
+ */
+static void
+setname(Dosfile *fp, char *from)
+{
+	char *to;
+
+	to = fp->name;
+	for(; *from && to-fp->name < 8; from++, to++){
+		if(*from == '.'){
+			from++;
+			break;
+		}
+		if(*from >= 'a' && *from <= 'z')
+			*to = *from + 'A' - 'a';
+		else
+			*to = *from;
+	}
+	while(to - fp->name < 8)
+		*to++ = ' ';
+	
+	to = fp->ext;
+	for(; *from && to-fp->ext < 3; from++, to++){
+		if(*from >= 'a' && *from <= 'z')
+			*to = *from + 'A' - 'a';
+		else
+			*to = *from;
+	}
+	while(to-fp->ext < 3)
+		*to++ = ' ';
+
+	chat("name is %8.8s %3.3s\n", fp->name, fp->ext);
+}
--- /dev/null
+++ b/os/boot.original/rpcg/dosfs.h
@@ -1,0 +1,110 @@
+typedef struct Dosboot	Dosboot;
+typedef struct Dos	Dos;
+typedef struct Dosdir	Dosdir;
+typedef struct Dosfile	Dosfile;
+typedef struct Dospart	Dospart;
+
+struct Dospart
+{
+	uchar flag;		/* active flag */
+	uchar shead;		/* starting head */
+	uchar scs[2];		/* starting cylinder/sector */
+	uchar type;		/* partition type */
+	uchar ehead;		/* ending head */
+	uchar ecs[2];		/* ending cylinder/sector */
+	uchar start[4];		/* starting sector */
+	uchar len[4];		/* length in sectors */
+};
+
+#define FAT12	0x01
+#define FAT16	0x04
+#define FATHUGE	0x06
+#define DMDDO	0x54
+
+struct Dosboot{
+	uchar	magic[3];
+	uchar	version[8];
+	uchar	sectsize[2];
+	uchar	clustsize;
+	uchar	nresrv[2];
+	uchar	nfats;
+	uchar	rootsize[2];
+	uchar	volsize[2];
+	uchar	mediadesc;
+	uchar	fatsize[2];
+	uchar	trksize[2];
+	uchar	nheads[2];
+	uchar	nhidden[4];
+	uchar	bigvolsize[4];
+	uchar	driveno;
+	uchar	reserved0;
+	uchar	bootsig;
+	uchar	volid[4];
+	uchar	label[11];
+	uchar	reserved1[8];
+};
+
+struct Dosfile{
+	Dos	*dos;		/* owning dos file system */
+	char	name[8];
+	char	ext[3];
+	uchar	attr;
+	long	length;
+	long	pstart;		/* physical start cluster address */
+	long	pcurrent;	/* physical current cluster address */
+	long	lcurrent;	/* logical current cluster address */
+	long	offset;
+};
+
+struct Dos{
+	int	dev;				/* device id */
+	long	(*read)(int, void*, long);	/* read routine */
+	long	(*seek)(int, long);		/* seek routine */
+
+	int	start;		/* start of file system */
+	int	sectsize;	/* in bytes */
+	int	clustsize;	/* in sectors */
+	int	clustbytes;	/* in bytes */
+	int	nresrv;		/* sectors */
+	int	nfats;		/* usually 2 */
+	int	rootsize;	/* number of entries */
+	int	volsize;	/* in sectors */
+	int	mediadesc;
+	int	fatsize;	/* in sectors */
+	int	fatclusters;
+	int	fatbits;	/* 12 or 16 */
+	long	fataddr;	/* sector number */
+	long	rootaddr;
+	long	dataaddr;
+	long	freeptr;
+
+	Dosfile	root;
+};
+
+struct Dosdir{
+	uchar	name[8];
+	uchar	ext[3];
+	uchar	attr;
+	uchar	reserved[10];
+	uchar	time[2];
+	uchar	date[2];
+	uchar	start[2];
+	uchar	length[4];
+};
+
+#define	DRONLY	0x01
+#define	DHIDDEN	0x02
+#define	DSYSTEM	0x04
+#define	DVLABEL	0x08
+#define	DDIR	0x10
+#define	DARCH	0x20
+
+extern int chatty;
+
+extern int dosboot(Dos*, char*);
+extern int dosinit(Dos*, int, int);
+extern long dosread(Dosfile*, void*, long);
+extern int dosstat(Dos*, char*, Dosfile*);
+extern int doswalk(Dosfile*, char*);
+
+extern int plan9ini(Dos*, char*);
--- /dev/null
+++ b/os/boot.original/rpcg/etherif.h
@@ -1,0 +1,59 @@
+/*
+ * All the goo for PC ethernet cards.
+ */
+typedef struct Card Card;
+typedef struct Type Type;
+typedef struct Ctlr Ctlr;
+
+/*
+ * Hardware interface.
+ */
+struct Card {
+	ISAConf;
+
+	int	(*reset)(Ctlr*);
+	void	(*attach)(Ctlr*);
+
+	void	*(*read)(Ctlr*, void*, ulong, ulong);
+	void	*(*write)(Ctlr*, ulong, void*, ulong);
+
+	void	(*receive)(Ctlr*);
+	void	(*transmit)(Ctlr*);
+	void	(*intr)(Ureg*, void*);
+	void	(*overflow)(Ctlr*);
+
+	uchar	bit16;			/* true if a 16 bit interface */
+	uchar	ram;			/* true if card has shared memory */
+
+	ulong	dp8390;			/* I/O address of 8390 (if any) */
+	ulong	data;			/* I/O data port if no shared memory */
+	uchar	nxtpkt;			/* software bndry */
+	uchar	tstart;			/* 8390 ring addresses */
+	uchar	pstart;
+	uchar	pstop;
+
+	uchar	dummyrr;		/* do dummy remote read */
+};
+
+/*
+ * Software controller.
+ */
+struct Ctlr {
+	Card	card;			/* hardware info */
+	int	ctlrno;
+	int	present;
+
+	Queue*	iq;
+	Queue*	oq;
+
+	int	inpackets;
+	int	outpackets;
+	int	crcs;			/* input crc errors */
+	int	oerrs;			/* output errors */
+	int	frames;			/* framing errors */
+	int	overflows;		/* packet overflows */
+	int	buffs;			/* buffering errors */
+};
+
+extern int sccethreset(Ctlr*);
+extern int	etheriq(Ctlr*, Block*, int);
--- /dev/null
+++ b/os/boot.original/rpcg/etherscc.c
@@ -1,0 +1,411 @@
+/*
+ * SCCn ethernet
+ */
+
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+#include "etherif.h"
+
+enum {
+	Nrdre		= 32,	/* receive descriptor ring entries */
+	Ntdre		= 4,	/* transmit descriptor ring entries */
+
+	Rbsize		= ETHERMAXTU+4,		/* ring buffer size (+4 for CRC) */
+	Bufsize		= (Rbsize+7)&~7,	/* aligned */
+};
+
+enum {
+	/* ether-specific Rx BD bits */
+	RxMiss=		1<<8,
+	RxeLG=		1<<5,
+	RxeNO=		1<<4,
+	RxeSH=		1<<3,
+	RxeCR=		1<<2,
+	RxeOV=		1<<1,
+	RxeCL=		1<<0,
+	RxError=		(RxeLG|RxeNO|RxeSH|RxeCR|RxeOV|RxeCL),	/* various error flags */
+
+	/* ether-specific Tx BD bits */
+	TxPad=		1<<14,	/* pad short frames */
+	TxTC=		1<<10,	/* transmit CRC */
+	TxeDEF=		1<<9,
+	TxeHB=		1<<8,
+	TxeLC=		1<<7,
+	TxeRL=		1<<6,
+	TxeUN=		1<<1,
+	TxeCSL=		1<<0,
+
+	/* scce */
+	RXB=	1<<0,
+	TXB=	1<<1,
+	BSY=		1<<2,
+	RXF=		1<<3,
+	TXE=		1<<4,
+
+	/* gsmrl */
+	ENR=	1<<5,
+	ENT=	1<<4,
+
+	/* port A */
+	RXD1=	SIBIT(15),
+	TXD1=	SIBIT(14),
+
+	/* port B */
+	RTS1=	IBIT(19),
+
+	/* port C */
+	CTS1=	SIBIT(11),
+	CD1=	SIBIT(10),
+};
+
+typedef struct Etherparam Etherparam;
+struct Etherparam {
+	SCCparam;
+	ulong	c_pres;		/* preset CRC */
+	ulong	c_mask;		/* constant mask for CRC */
+	ulong	crcec;		/* CRC error counter */
+	ulong	alec;		/* alighnment error counter */
+	ulong	disfc;		/* discard frame counter */
+	ushort	pads;		/* short frame PAD characters */
+	ushort	ret_lim;	/* retry limit threshold */
+	ushort	ret_cnt;	/* retry limit counter */
+	ushort	mflr;		/* maximum frame length reg */
+	ushort	minflr;		/* minimum frame length reg */
+	ushort	maxd1;		/* maximum DMA1 length reg */
+	ushort	maxd2;		/* maximum DMA2 length reg */
+	ushort	maxd;		/* rx max DMA */
+	ushort	dma_cnt;	/* rx dma counter */
+	ushort	max_b;		/* max bd byte count */
+	ushort	gaddr[4];		/* group address filter */
+	ulong	tbuf0_data0;	/* save area 0 - current frm */
+	ulong	tbuf0_data1;	/* save area 1 - current frm */
+	ulong	tbuf0_rba0;
+	ulong	tbuf0_crc;
+	ushort	tbuf0_bcnt;
+	ushort	paddr[3];	/* physical address LSB to MSB increasing */
+	ushort	p_per;		/* persistence */
+	ushort	rfbd_ptr;	/* rx first bd pointer */
+	ushort	tfbd_ptr;	/* tx first bd pointer */
+	ushort	tlbd_ptr;	/* tx last bd pointer */
+	ulong	tbuf1_data0;	/* save area 0 - next frame */
+	ulong	tbuf1_data1;	/* save area 1 - next frame */
+	ulong	tbuf1_rba0;
+	ulong	tbuf1_crc;
+	ushort	tbuf1_bcnt;
+	ushort	tx_len;		/* tx frame length counter */
+	ushort	iaddr[4];		/* individual address filter*/
+	ushort	boff_cnt;	/* back-off counter */
+	ushort	taddr[3];	/* temp address */
+};
+
+typedef struct {
+	SCC*	scc;
+	int	port;
+	int	cpm;
+
+	BD*	rdr;				/* receive descriptor ring */
+	void*	rrb;				/* receive ring buffers */
+	int	rdrx;				/* index into rdr */
+
+	BD*	tdr;				/* transmit descriptor ring */
+	void*	trb;				/* transmit ring buffers */
+	int	tdrx;				/* index into tdr */
+} Mot;
+static Mot mot[MaxEther];
+
+static	int	sccid[] = {-1, SCC1ID, SCC2ID, SCC3ID, SCC4ID};
+static	int	sccparam[] = {-1, SCC1P, SCC2P, SCC3P, SCC4P};
+static	int	sccreg[] = {-1, 0xA00, 0xA20, 0xA40, 0xA60};
+static	int	sccirq[] = {-1, 0x1E, 0x1D, 0x1C, 0x1B};
+
+static void
+attach(Ctlr *ctlr)
+{
+	mot[ctlr->ctlrno].scc->gsmrl |= ENR|ENT;
+	eieio();
+}
+
+static void
+transmit(Ctlr *ctlr)
+{
+	int len;
+	Mot *motp;
+	Block *b;
+	BD *tdre;
+
+	motp = &mot[ctlr->ctlrno];
+	while(((tdre = &motp->tdr[motp->tdrx])->status & BDReady) == 0){
+		b = qget(ctlr->oq);
+		if(b == 0)
+			break;
+
+		/*
+		 * Copy the packet to the transmit buffer.
+		 */
+		len = BLEN(b);
+		memmove(KADDR(tdre->addr), b->rp, len);
+	
+		/*
+		 * Give ownership of the descriptor to the chip, increment the
+		 * software ring descriptor pointer and tell the chip to poll.
+		 */
+		tdre->length = len;
+		eieio();
+		tdre->status = (tdre->status & BDWrap) | BDReady|TxPad|BDInt|BDLast|TxTC;
+		eieio();
+		motp->scc->todr = 1<<15;	/* transmit now */
+		eieio();
+		motp->tdrx = NEXT(motp->tdrx, Ntdre);
+
+		freeb(b);
+	
+	}
+}
+
+static void
+interrupt(Ureg*, void *ap)
+{
+	int len, events, status;
+	Mot *motp;
+	BD *rdre;
+	Block *b;
+	Ctlr *ctlr;
+
+	ctlr = ap;
+	motp = &mot[ctlr->ctlrno];
+
+	/*
+	 * Acknowledge all interrupts and whine about those that shouldn't
+	 * happen.
+	 */
+	events = motp->scc->scce;
+	eieio();
+	motp->scc->scce = events;
+	eieio();
+	if(events & (TXE|BSY|RXB))
+		print("ETHER.SCC#%d: scce = 0x%uX\n", ctlr->ctlrno, events);
+	//print(" %ux|", events);
+	/*
+	 * Receiver interrupt: run round the descriptor ring logging
+	 * errors and passing valid receive data up to the higher levels
+	 * until we encounter a descriptor still owned by the chip.
+	 */
+	if(events & (RXF|RXB) || 1){
+		rdre = &motp->rdr[motp->rdrx];
+		while(((status = rdre->status) & BDEmpty) == 0){
+			if(status & RxError || (status & (BDFirst|BDLast)) != (BDFirst|BDLast)){
+				//if(status & RxBuff)
+				//	ctlr->buffs++;
+				if(status & (1<<2))
+					ctlr->crcs++;
+				if(status & (1<<1))
+					ctlr->overflows++;
+				//print("eth rx: %ux\n", status);
+				if(status & RxError)
+					print("~");
+				else if((status & BDLast) == 0)
+					print("@");
+			}
+			else{
+				/*
+				 * We have a packet. Read it into the next
+				 * free ring buffer, if any.
+				 */
+				len = rdre->length-4;
+				if((b = iallocb(len)) != 0){
+					memmove(b->wp, KADDR(rdre->addr), len);
+					b->wp += len;
+					etheriq(ctlr, b, 1);
+				}
+			}
+
+			/*
+			 * Finished with this descriptor, reinitialise it,
+			 * give it back to the chip, then on to the next...
+			 */
+			rdre->length = 0;
+			rdre->status = (rdre->status & BDWrap) | BDEmpty | BDInt;
+			eieio();
+
+			motp->rdrx = NEXT(motp->rdrx, Nrdre);
+			rdre = &motp->rdr[motp->rdrx];
+		}
+	}
+
+	/*
+	 * Transmitter interrupt: handle anything queued for a free descriptor.
+	 */
+	if(events & TXB)
+		transmit(ctlr);
+	if(events & TXE)
+		cpmop(RestartTx, motp->cpm, 0);
+}
+
+static void
+ringinit(Mot* motp)
+{
+	int i, x;
+
+	/*
+	 * Initialise the receive and transmit buffer rings. The ring
+	 * entries must be aligned on 16-byte boundaries.
+	 */
+	if(motp->rdr == 0)
+		motp->rdr = bdalloc(Nrdre);
+	if(motp->rrb == 0)
+		motp->rrb = ialloc(Nrdre*Bufsize, 0);
+	x = PADDR(motp->rrb);
+	for(i = 0; i < Nrdre; i++){
+		motp->rdr[i].length = 0;
+		motp->rdr[i].addr = x;
+		motp->rdr[i].status = BDEmpty|BDInt;
+		x += Bufsize;
+	}
+	motp->rdr[i-1].status |= BDWrap;
+	motp->rdrx = 0;
+
+	if(motp->tdr == 0)
+		motp->tdr = bdalloc(Ntdre);
+	if(motp->trb == 0)
+		motp->trb = ialloc(Ntdre*Bufsize, 0);
+	x = PADDR(motp->trb);
+	for(i = 0; i < Ntdre; i++){
+		motp->tdr[i].addr = x;
+		motp->tdr[i].length = 0;
+		motp->tdr[i].status = TxPad|BDInt|BDLast|TxTC;
+		x += Bufsize;
+	}
+	motp->tdr[i-1].status |= BDWrap;
+	motp->tdrx = 0;
+}
+
+/*
+ * This follows the MPC823 user guide: section16.9.23.7's initialisation sequence,
+ * except that it sets the right bits for the MPC823ADS board when SCC2 is used,
+ * and those for the 860/821 development board for SCC1.
+ */
+static void
+sccsetup(Mot *ctlr, SCC *scc, uchar *ea)
+{
+	int i, rcs, tcs, w;
+	Etherparam *p;
+	IMM *io;
+
+
+	i = 2*(ctlr->port-1);
+	io = ioplock();
+	w = (TXD1|RXD1)<<i;	/* TXDn and RXDn in port A */
+	io->papar |= w;	/* enable TXDn and RXDn pins */
+	io->padir &= ~w;
+	io->paodr &= ~w;	/* not open drain */
+
+	w = (CD1|CTS1)<<i;	/* CLSN and RENA: CDn and CTSn in port C */
+	io->pcpar &= ~w;	/* enable CLSN (CTSn) and RENA (CDn) */
+	io->pcdir &= ~w;
+	io->pcso |= w;
+	iopunlock();
+
+	/* clocks and transceiver control: details depend on the board's wiring */
+	archetherenable(ctlr->cpm, &rcs, &tcs);
+
+	sccnmsi(ctlr->port, rcs, tcs);	/* connect the clocks */
+
+	p = (Etherparam*)KADDR(sccparam[ctlr->port]);
+	memset(p, 0, sizeof(*p));
+	p->rfcr = 0x18;
+	p->tfcr = 0x18;
+	p->mrblr = Bufsize;
+	p->rbase = PADDR(ctlr->rdr);
+	p->tbase = PADDR(ctlr->tdr);
+
+	cpmop(InitRxTx, ctlr->cpm, 0);
+
+	p->c_pres = ~0;
+	p->c_mask = 0xDEBB20E3;
+	p->crcec = 0;
+	p->alec = 0;
+	p->disfc = 0;
+	p->pads = 0x8888;
+	p->ret_lim = 0xF;
+	p->mflr = Rbsize;
+	p->minflr = ETHERMINTU+4;
+	p->maxd1 = Bufsize;
+	p->maxd2 = Bufsize;
+	p->p_per = 0;	/* only moderate aggression */
+
+	for(i=0; i<Eaddrlen; i+=2)
+		p->paddr[2-i/2] = (ea[i+1]<<8)|ea[i];	/* it's not the obvious byte order */
+
+	scc->psmr = (2<<10)|(5<<1);	/* 32-bit CRC, ignore 22 bits before SFD */
+	scc->dsr = 0xd555;
+	scc->gsmrh = 0;	/* normal operation */
+	scc->gsmrl = (1<<28)|(4<<21)|(1<<19)|0xC;	/* transmit clock invert, 48 bit preamble, repetitive 10 preamble, ethernet */
+	eieio();
+	scc->scce = ~0;	/* clear all events */
+	eieio();
+	scc->sccm = TXE | RXF | TXB;	/* enable interrupts */
+	eieio();
+
+	io = ioplock();
+	w = RTS1<<(ctlr->port-1);	/* enable TENA pin (RTSn) */
+	io->pbpar |= w;
+	io->pbdir |= w;
+	iopunlock();
+
+	/* gsmrl enable is deferred until attach */
+}
+
+/*
+ * Prepare the SCCx ethernet for booting.
+ */
+int
+sccethreset(Ctlr* ctlr)
+{
+	uchar ea[Eaddrlen];
+	Mot *motp;
+	SCC *scc;
+	char line[50], def[50];
+
+	/*
+	 * Since there's no EPROM, insist that the configuration entry
+	 * (see conf.c and flash.c) holds the Ethernet address.
+	 */
+	memset(ea, 0, Eaddrlen);
+	if(memcmp(ea, ctlr->card.ea, Eaddrlen) == 0){
+		print("no preset Ether address\n");
+		for(;;){
+			strcpy(def, "00108bf12900");	/* valid MAC address to be used only for initial configuration */
+			if(getstr("ether MAC address", line, sizeof(line), def) < 0)
+				return -1;
+			if(parseether(ctlr->card.ea, line) >= 0 || ctlr->card.ea[0] == 0xFF)
+				break;
+			print("invalid MAC address\n");
+		}
+	}
+
+	scc = IOREGS(sccreg[ctlr->card.port], SCC);
+	ctlr->card.irq = VectorCPIC+sccirq[ctlr->card.port];
+
+	motp = &mot[ctlr->ctlrno];
+	motp->scc = scc;
+	motp->port = ctlr->card.port;
+	motp->cpm = sccid[ctlr->card.port];
+
+	ringinit(motp);
+
+	sccsetup(motp, scc, ctlr->card.ea);
+
+	/* enable is deferred until attach */
+
+	ctlr->card.reset = sccethreset;
+	ctlr->card.attach = attach;
+	ctlr->card.transmit = transmit;
+	ctlr->card.intr = interrupt;
+
+	return 0;
+}
--- /dev/null
+++ b/os/boot.original/rpcg/fblt.c
@@ -1,0 +1,531 @@
+#include <u.h>
+#include <libc.h>
+#include <libg.h>
+#include <gnot.h>
+
+/*
+ * bitblt operates a 'word' at a time.
+ * WBITS is the number of bits in a word
+ * LWBITS=log2(WBITS),
+ * W2L is the number of words in a long
+ * WMASK has bits set for the low order word of a long
+ * WType is a pointer to a word
+ */
+#ifndef WBITS
+#define WBITS	32
+#define LWBITS	5
+#define	W2L	1
+#define WMASK	~0UL
+typedef ulong	*WType;
+#endif
+
+#define DEBUG 
+
+#ifdef TEST
+/*
+ * globals used for testing
+ */
+int	FORCEFORW;
+int	FORCEBAKW;
+GBitmap	*curdm, *cursm;
+Point	curpt;
+Rectangle curr;
+Fcode	curf;
+void	*mem;
+#endif
+
+static void
+gbitexplode(ulong sw, ulong *buf, int sdep, int x)
+{
+	int j, o, q, n, nw, inc, qinc;
+	ulong s, dw, pix;
+
+	inc = 1 << sdep;
+	pix = (1 << inc) - 1;
+	nw = 1 << x;
+	n = 32 >> x;
+	qinc = (nw << sdep) - inc;
+	for(o = 32 - n; o >= 0; o -= n){
+		dw = 0;
+		s = sw >> o;
+		q = 0;
+		for(j = 0; j < n; j += inc){
+			dw |= (s & (pix << j)) << q;
+			q += qinc;
+		}
+		for(j = 0; j < x; j++)
+			dw |= dw << (inc << j);
+		*buf++ = dw;
+	}
+}
+
+/*
+void
+main(void)
+{
+	ulong buf[128];
+
+	gbitexplode(0x7777, buf, 0, 3);
+	exits(0);
+}
+*/
+
+void
+gbitblt(GBitmap *dm, Point pt, GBitmap *sm, Rectangle r, Fcode fcode)
+{
+	int	width;		/* width in bits of dst */
+	int	wwidth;		/* floor width in words */
+	int	height;		/* height in pixels minus 1 */
+	int	sdep;		/* src ldepth */
+	int 	ddep;		/* dst ldepth */
+	int	deltadep;	/* diff between ldepths */
+	int	sspan;		/* words between scanlines in src */
+	int	dspan;		/* words between scanlines in dst */
+	int	soff;		/* bit offset of src start point */
+	int	sdest;		/* bit offset of src start point that matches doff when expanded */
+	int	doff;		/* bit offset of dst start point */
+	int	delta;		/* amount to shift src by */
+	int	sign;		/* of delta */
+	ulong	*saddr;
+	ulong	*daddr;
+	ulong	*s;
+	ulong	*d;
+	ulong	mask;
+	ulong	tmp;		/* temp storage source word */
+	ulong	sw;		/* source word constructed */
+	ulong	dw;		/* dest word fetched */
+	ulong	lmask;		/* affected pixels in leftmost dst word */
+	ulong	rmask;		/* affected pixels in rightmost dst word */
+	int	i;
+	int	j;
+	ulong	buf[32];	/* for expanding a source */
+	ulong	*p;		/* pointer into buf */
+	int	spare;		/* number of words already converted */
+
+
+#ifdef TEST
+	curdm = dm;
+	cursm = sm;
+	curpt = pt;
+	curr = r;
+	curf = fcode;
+#endif
+
+	gbitbltclip(&dm);
+
+	width = r.max.x - r.min.x;
+	if(width <= 0)
+		return;
+	height = r.max.y - r.min.y - 1;
+	if(height < 0)
+		return;
+
+	ddep = dm->ldepth;
+	pt.x <<= ddep;
+	width <<= ddep;
+
+	sdep = sm->ldepth;
+	r.min.x <<= sdep;
+	r.max.x <<= sdep;
+
+	dspan = dm->width * W2L;
+	sspan = sm->width * W2L;
+
+	daddr = (ulong*)((WType)dm->base
+			+ dm->zero*W2L + pt.y*dspan
+			+ (pt.x >> LWBITS));
+	saddr = (ulong*)((WType)sm->base
+			+ sm->zero*W2L + r.min.y*sspan
+			+ (r.min.x >> LWBITS));
+
+	doff = pt.x & (WBITS - 1);
+	lmask = WMASK >> doff;
+	rmask = (WMASK << (WBITS - ((doff+width) & (WBITS-1))))&WMASK;
+	if(!rmask)
+		rmask = WMASK;
+	soff = r.min.x & (WBITS-1);
+	wwidth = ((pt.x+width-1)>>LWBITS) - (pt.x>>LWBITS);
+
+	if(sm == dm){
+#ifdef TEST
+		if(!FORCEBAKW &&
+		   (FORCEFORW || sm != dm || saddr > daddr ||
+		    (saddr == daddr && soff > doff)))
+			;
+		else{
+			daddr += height * dspan;
+			saddr += height * sspan;
+			sspan -= 2 * W2L * sm->width;
+			dspan -= 2 * W2L * dm->width;
+		}
+#else
+		if(r.min.y < pt.y){	/* bottom to top */
+			daddr += height * dspan;
+			saddr += height * sspan;
+			sspan -= 2 * W2L * sm->width;
+			dspan -= 2 * W2L * dm->width;
+		}else if(r.min.y == pt.y && r.min.x < pt.x)
+			abort()/*goto right*/;
+#endif
+	}
+	if(wwidth == 0)		/* collapse masks for narrow cases */
+		lmask &= rmask;
+	fcode &= F;
+
+	deltadep = ddep - sdep;
+	sdest = doff >> deltadep;
+	delta = soff - sdest;
+	sign = 0;
+	if(delta < 0){
+		sign = 1;
+		delta = -delta;
+	}
+
+	p = 0;
+	for(j = 0; j <= height; j++){
+		d = daddr;
+		s = saddr;
+		mask = lmask;
+		tmp = 0;
+		if(!sign)
+			tmp = *s++;
+		spare = 0;
+		for(i = wwidth; i >= 0; i--){
+			if(spare)
+				sw = *p++;
+			else{
+				if(sign){
+					sw = tmp << (WBITS-delta);
+					tmp = *s++;
+					sw |= tmp >> delta;
+				}else{
+					sw = tmp << delta;
+					tmp = *s++;
+					if(delta)
+						sw |= tmp >> (WBITS-delta);
+				}
+				spare = 1 << deltadep;
+				if(deltadep >= 1){
+					gbitexplode(sw, buf, sdep, deltadep);
+					p = buf;
+					sw = *p++;
+				}
+			}
+
+			dw = *d;
+			switch(fcode){		/* ltor bit aligned */
+			case Zero:	*d = dw & ~mask;		break;
+			case DnorS:	*d = dw ^ ((~sw | dw) & mask);	break;
+			case DandnotS:	*d = dw ^ ((sw & dw) & mask);	break;
+			case notS:	*d = dw ^ ((~sw ^ dw) & mask);	break;
+			case notDandS:	*d = dw ^ ((sw | dw) & mask);	break;
+			case notD:	*d = dw ^ mask;			break;
+			case DxorS:	*d = dw ^ (sw & mask);		break;
+			case DnandS:	*d = dw ^ ((sw | ~dw) & mask);	break;
+			case DandS:	*d = dw ^ ((~sw & dw) & mask);	break;
+			case DxnorS:	*d = dw ^ (~sw & mask);		break;
+			case D:						break;
+			case DornotS:	*d = dw | (~sw & mask);		break;
+			case S:		*d = dw ^ ((sw ^ dw) & mask);	break;
+			case notDorS:	*d = dw ^ (~(sw & dw) & mask);	break;
+			case DorS:	*d = dw | (sw & mask);		break;
+			case F:		*d = dw | mask;			break;
+			}
+			d++;
+
+			mask = WMASK;
+			if(i == 1)
+				mask = rmask;
+			spare--;
+		}
+		saddr += sspan;
+		daddr += dspan;
+	}
+}
+
+#ifdef TEST
+void	prprog(void);
+GBitmap *bb1, *bb2;
+ulong	*src, *dst, *xdst, *xans;
+int	swds, dwds;
+long	ticks;
+int	timeit;
+
+long
+func(int f, long s, int sld, long d, int dld)
+{
+	long a;
+	int sh, i, db, sb;
+
+	db = 1 << dld;
+	sb = 1 << sld;
+	sh = db - sb;
+	if(sh > 0) {
+		a = s;
+		for(i = sb; i<db; i += sb){
+			a <<= sb;
+			s |= a;
+		}
+	} else if(sh < 0)
+		s >>= -sh;
+
+	switch(f){
+	case Zero:	d = 0;			break;
+	case DnorS:	d = ~(d|s);		break;
+	case DandnotS:	d = d & ~s;		break;
+	case notS:	d = ~s;			break;
+	case notDandS:	d = ~d & s;		break;
+	case notD:	d = ~d;			break;
+	case DxorS:	d = d ^ s;		break;
+	case DnandS:	d = ~(d&s);		break;
+	case DandS:	d = d & s;		break;
+	case DxnorS:	d = ~(d^s);		break;
+	case S:		d = s;			break;
+	case DornotS:	d = d | ~s;		break;
+	case D:		d = d;			break;
+	case notDorS:	d = ~d | s;		break;
+	case DorS:	d = d | s;		break;
+	case F:		d = ~0;			break;
+	}
+
+	d &= ((1<<db)-1);
+	return d;
+}
+
+void
+run(int fr, int to, int w, int op)
+{
+	int i, j, f, t, fy, ty;
+	extern long *_clock;
+
+	fr += bb2->r.min.x;
+	to += bb1->r.min.x;
+	fy = bb2->r.min.y + 1;
+	ty = bb1->r.min.y + 1;
+	if(timeit) {
+		memcpy(dst, xdst, dwds * sizeof(long));
+		ticks -= *_clock;
+		gbitblt(bb1, Pt(to,ty), bb2, Rect(fr,fy,fr+w,fy+2), op);
+		ticks += *_clock;
+		return;
+	}
+	f = fr;
+	t = to;
+	memcpy(dst, xdst, dwds * sizeof(long));
+	for(i=0; i<w; i++) {
+		gbitblt(bb1, Pt(t,ty), bb2, Rect(f,fy,f+1,fy+1), op);
+		gbitblt(bb1, Pt(t,ty+1), bb2, Rect(f,fy+1,f+1,fy+2), op);
+		f++;
+		t++;
+	}
+	memcpy(xans, dst, dwds * sizeof(long));
+
+	memcpy(dst, xdst, dwds * sizeof(long));
+	gbitblt(bb1, Pt(to,ty), bb2, Rect(fr,fy,fr+w,fy+2), op);
+
+	if(memcmp(xans, dst, dwds * sizeof(long))) {
+		/*
+		 * print src and dst row offset, width in bits, and forw/back
+		 * then print for each of the four rows: the source (s),
+		 * the dest (d), the good value of the answer (g),
+		 * and the actual bad value of the answer (b)
+		 */
+		print("fr=%d to=%d w=%d fb=%d%d\n",
+			fr, to, w, FORCEFORW, FORCEBAKW);
+		print("dst bitmap b %#lux, z %d, w %d, ld %d, r [%d,%d][%d,%d]\n",
+			bb1->base, bb1->zero, bb1->width, bb1->ldepth,
+			bb1->r.min.x, bb1->r.min.y, bb1->r.max.x, bb1->r.max.y);
+		print("src bitmap b %#lux, z %d, w %d, ld %d, r [%d,%d][%d,%d]\n",
+			bb2->base, bb2->zero, bb2->width, bb2->ldepth,
+			bb2->r.min.x, bb2->r.min.y, bb2->r.max.x, bb2->r.max.y);
+		for(j=0; 7*j < dwds; j++) {
+			print("\ns");
+			for(i=0; i<7 && 7*j+i < dwds; i++)
+				print(" %.8lux", src[7*j + i]);
+			print("\nd");
+			for(i=0; i<7 && 7*j+i < dwds; i++)
+				print(" %.8lux", xdst[7*j + i]);
+			print("\ng");
+			for(i=0; i<7 && 7*j+i < dwds; i++)
+				print(" %.8lux", xans[7*j + i]);
+			print("\nb");
+			for(i=0; i<7 && 7*j+i < dwds; i++)
+				print(" %.8lux", dst[7*j + i]);
+			print("\n");
+		}
+		prprog();
+	}
+}
+
+void
+prprog(void)
+{
+	exits(0);
+}
+
+int
+main(int argc, char *argv[])
+{
+	int f, t, w, i, sld, dld, op, iters, simple;
+	ulong s, d, spix, dpix, apix, fpix, m, *ps, *pd;
+	Point sorg, dorg;
+	GBitmap *bs, *bd;
+	long seed;
+	char *ct;
+
+	sld = 0;
+	dld = 0;
+	timeit = 0;
+	iters = 200;
+	simple = 0;
+	ARGBEGIN {
+	case 'i':
+		iters = atoi(ARGF());
+		break;
+	case 's':
+		simple = 1;
+		break;
+	case 't':
+		timeit = 1;
+		ct = ARGF();
+		if(ct)
+			iters = atoi(ct);
+		break;
+	} ARGEND
+	if(argc > 0)
+		sld = atoi(argv[0]);
+	if(argc > 1)
+		dld = atoi(argv[1]);
+	if(!timeit && !simple) {
+		seed = time(0);
+		print("seed %lux\n", seed); srand(seed);	/**/
+	}
+
+	print("sld %d dld %d\n", sld, dld);
+	op = 1;
+
+	/* bitmaps for 1-bit tests */
+	bd = gballoc(Rect(0,0,32,1), dld);
+	bs = gballoc(Rect(0,0,32,1), sld);
+	for(i=0; i<bs->width; i++)
+		bs->base[i] = lrand();
+
+	/* bitmaps for rect tests */
+	if(simple) {
+		dorg = Pt(0,0);
+		sorg = Pt(0,0);
+	} else {
+		dorg = Pt(nrand(63)-31,nrand(63)-31);
+		sorg = Pt(nrand(63)-31,nrand(63)-31);
+	}
+	bb1 = gballoc(Rpt(dorg,add(dorg,Pt(200,4))), dld);
+	bb2 = gballoc(Rpt(sorg,add(sorg,Pt(200,4))), sld);
+	dwds = bb1->width * Dy(bb1->r);
+	swds = bb2->width * Dy(bb2->r);
+	dst = bb1->base;
+	src = bb2->base;
+	xdst = malloc(dwds * sizeof(long));
+	xans =  malloc(dwds * sizeof(long));
+	for(i=0; i<swds; i++)
+		src[i] = lrand();
+	for(i=0; i<dwds; i++)
+		xdst[i] = lrand();
+
+loop:
+	print("Op %d\n", op);
+	if(!timeit) {
+		print("one pixel\n");
+		ps = bs->base;
+		pd = bd->base;
+		FORCEFORW = 1;
+		FORCEBAKW = 0;
+		for(i=0; i<1000; i++, FORCEFORW = !FORCEFORW, FORCEBAKW = !FORCEBAKW) {
+			f = nrand(32 >> sld);
+			t = nrand(32 >> dld);
+			s = lrand();
+			d = lrand();
+			ps[0] = s;
+			pd[0] = d;
+#ifdef T386
+			spix = (byterev(s) >> (32 - ((f+1)<<sld))) & ((1 << (1<<sld)) - 1);
+			dpix = (byterev(d) >> (32 - ((t+1)<<dld))) & ((1 << (1<<dld)) - 1);
+#else
+			spix = (s >> (32 - ((f+1)<<sld))) & ((1 << (1<<sld)) - 1);
+			dpix = (d >> (32 - ((t+1)<<dld))) & ((1 << (1<<dld)) - 1);
+#endif
+#ifdef T386
+			apix = byterev(func(op, spix, sld, dpix, dld) << (32 - ((t+1)<<dld)));
+#else
+			apix = func(op, spix, sld, dpix, dld) << (32 - ((t+1)<<dld));
+#endif
+			gbitblt(bd, Pt(t,0), bs, Rect(f,0,f+1,1), op);
+			if(ps[0] != s) {
+				print("bb src %.8lux %.8lux %d %d\n", ps[0], s, f, t);
+				exits("error");
+			}
+			m = ((1 << (1<<dld)) - 1) << (32 - ((t+1)<<dld));
+#ifdef T386
+			m = byterev(m);
+#endif
+			if((pd[0] & ~m) != (d & ~m)) {
+					print("bb dst1 %.8lux %.8lux\n",
+						s, d);
+					print("bb      %.8lux %.8lux %d %d\n",
+						ps[0], pd[0], f, t);
+					prprog();
+					exits("error");
+			}
+			if((pd[0] & m) != apix) {
+				spix <<= 32 - ((f+1)<<sld);
+				dpix <<= 32 - ((t+1)<<dld);
+#ifdef T386
+				spix = byterev(spix);
+				dpix = byterev(dpix);
+#endif
+				print("bb dst2 %.8lux %.8lux\n",
+					s, d);
+				print("bb      %.8lux %.8lux %d %d\n",
+					ps[0], pd[0], f, t);
+				print("bb      %.8lux %.8lux %.8lux %.8lux\n",
+					spix, dpix, apix, pd[0] & m);
+				prprog();
+				exits("error");
+			}
+		}
+	}
+
+	print("for\n");
+	FORCEFORW = 1;
+	FORCEBAKW = 0;
+
+	for(i=0; i<iters; i++) {
+		f = nrand(64);
+		t = nrand(64);
+		w = nrand(130);
+		run(f, t, w, op);
+	}
+
+	if(sld == dld) {
+		print("bak\n");
+		FORCEFORW = 0;
+		FORCEBAKW = 1;
+	
+		for(i=0; i<iters; i++) {
+			f = nrand(64);
+			t = nrand(64);
+			w = nrand(130);
+			run(f, t, w, op);
+		}
+	}
+
+	if(op < F) {
+		op++;
+		goto loop;
+	}
+	if(timeit)
+		print("time: %d ticks\n", ticks);
+	exits(0);
+}
+
+
+#endif
--- /dev/null
+++ b/os/boot.original/rpcg/flash.c
@@ -1,0 +1,212 @@
+#include "boot.h"
+
+typedef struct Flashdev Flashdev;
+struct Flashdev {
+	uchar*	base;
+	int	size;
+	uchar*	exec;
+	char*	config;
+	int	conflen;
+};
+
+enum {
+	FLASHSEG = 256*1024,
+	CONFIGLIM = FLASHSEG,
+	BOOTOFF = FLASHSEG,
+	BOOTLEN = 3*FLASHSEG,	/* third segment might be filsys */
+	/* rest of flash is free */
+};
+
+static Flashdev flash;
+
+/*
+ * configuration data is written between the bootstrap and
+ * the end of region 0. the region ends with allocation descriptors
+ * of the following form:
+ *
+ * byte order is big endian
+ *
+ * the last valid region found that starts with the string "#plan9.ini\n" is plan9.ini
+ */
+typedef struct Flalloc Flalloc;
+struct Flalloc {
+	ulong	check;	/* checksum of data, or ~0 */
+	ulong	base;	/* base of region; ~0 if unallocated, 0 if deleted */
+	uchar	len[3];
+	uchar	tag;		/* see below */
+	uchar	sig[4];
+};
+
+enum {
+	/* tags */
+	Tdead=	0,
+	Tboot=	0x01,	/* space reserved for boot */
+	Tconf=	0x02,	/* configuration data */
+	Tnone=	0xFF,
+
+	Noval=	~0,
+};
+
+static char flashsig[] = {0xF1, 0xA5, 0x5A, 0x1F};
+static char conftag[] = "#plan9.ini\n";
+
+static ulong
+checksum(uchar* p, int n)
+{
+	ulong s;
+
+	for(s=0; --n >= 0;)
+		s += *p++;
+	return s;
+}
+
+static int
+validptr(Flalloc *ap, uchar *p)
+{
+	return p > (uchar*)&end && p < (uchar*)ap;
+}
+
+static int
+flashcheck(Flalloc *ap, char **val, int *len)
+{
+	uchar *base;
+	int n;
+
+	if(ap->base == Noval || ap->base >= FLASHSEG || ap->tag == Tnone)
+		return 0;
+	base = flash.base+ap->base;
+	if(!validptr(ap, base))
+		return 0;
+	n = (((ap->len[0]<<8)|ap->len[1])<<8)|ap->len[2];
+	if(n == 0xFFFFFF)
+		n = 0;
+	if(n < 0)
+		return 0;
+	if(n > 0 && !validptr(ap, base+n-1))
+		return 0;
+	if(ap->check != Noval && checksum(base, n) != ap->check){
+		print("flash: bad checksum\n");
+		return 0;
+	}
+	*val = (char*)base;
+	*len = n;
+	return 1;
+}
+
+int
+flashinit(void)
+{
+	int len;
+	char *val;
+	Flalloc *ap;
+	void *addr;
+	long mbytes;
+	char type[20];
+
+	flash.base = 0;
+	flash.exec = 0;
+	flash.size = 0;
+	if(archflashreset(type, &addr, &mbytes) < 0){
+		print("flash: flash not present or not enabled\n");	/* shouldn't happen */
+		return 0;
+	}
+	flash.size = mbytes;
+	flash.base = addr;
+	flash.exec = flash.base + BOOTOFF;
+	flash.config = nil;
+	flash.conflen = 0;
+
+	for(ap = (Flalloc*)(flash.base+CONFIGLIM)-1; memcmp(ap->sig, flashsig, 4) == 0; ap--){
+		if(0)
+			print("conf #%8.8lux: #%x #%6.6lux\n", ap, ap->tag, ap->base);
+		if(ap->tag == Tconf &&
+		   flashcheck(ap, &val, &len) &&
+		   len >= sizeof(conftag)-1 &&
+		   memcmp(val, conftag, sizeof(conftag)-1) == 0){
+			flash.config = val;
+			flash.conflen = len;
+			if(0)
+				print("flash: found config %8.8lux(%d):\n%s\n", val, len, val);
+		}
+	}
+	if(flash.config == nil)
+		print("flash: no config\n");
+	else
+		print("flash config %8.8lux(%d):\n%s\n", flash.config, flash.conflen, flash.config);
+	if(issqueezed(flash.exec) == Q_MAGIC){
+		print("flash: squeezed powerpc kernel installed\n");
+		return 1<<0;
+	}
+	if(GLLONG(flash.exec) == Q_MAGIC){
+		print("flash: unsqueezed powerpc kernel installed\n");
+		return 1<<0;
+	}
+	flash.exec = 0;
+	print("flash: no powerpc kernel in Flash\n");
+	return 0;
+}
+
+char*
+flashconfig(int)
+{
+	return flash.config;
+}
+
+int
+flashbootable(int)
+{
+	return flash.exec != nil && (issqueezed(flash.exec) || GLLONG(flash.exec) == Q_MAGIC);
+}
+
+int
+flashboot(int)
+{
+	ulong entry, addr;
+	void (*b)(void);
+	Exec *ep;
+	Block in;
+	long n;
+	uchar *p;
+
+	if(flash.exec == 0)
+		return -1;
+	p = flash.exec;
+	if(GLLONG(p) == Q_MAGIC){
+		/* unsqueezed: copy data and perhaps text, then jump to it */
+		ep = (Exec*)p;
+		entry = PADDR(GLLONG(ep->entry));
+		p += sizeof(Exec);
+		addr = entry;
+		n = GLLONG(ep->text);
+		if(addr != (ulong)p){
+			memmove((void*)addr, p, n);
+			print("text: %8.8lux <- %8.8lux [%ld]\n", addr, p, n);
+		}
+		p += n;
+		if(entry >= FLASHMEM)
+			addr = 3*BY2PG;	/* kernel text is in Flash, data in RAM */
+		else
+			addr = PGROUND(addr+n);
+		n = GLLONG(ep->data);
+		memmove((void*)addr, p, n);
+		print("data: %8.8lux <- %8.8lux [%ld]\n", addr, p, n);
+	}else{
+		in.data = p;
+		in.rp = in.data;
+		in.lim = p+BOOTLEN;
+		in.wp = in.lim;
+		n = unsqueezef(&in, &entry);
+		if(n < 0)
+			return -1;
+	}
+	print("entry=0x%lux\n", entry);
+	uartwait();
+	scc2stop();
+	/*
+	 *  Go to new code. It's up to the program to get its PC relocated to
+	 *  the right place.
+	 */
+	b = (void (*)(void))KADDR(PADDR(entry));
+	(*b)();
+	return -1;
+}
--- /dev/null
+++ b/os/boot.original/rpcg/fns.h
@@ -1,0 +1,118 @@
+Alarm*	alarm(int, void (*)(Alarm*), void*);
+void	alarminit(void);
+void	archbacklight(int);
+char*	archconfig(void);
+void	archdisableuart(int);
+void	archenableuart(int, int);
+void	archenableusb(int);
+void	archetherdisable(int);
+int	archetherenable(int, int*, int*);
+int	archflashreset(char*, void**, long*);
+void	archinit(void);
+int	archoptionsw(void);
+int	bootp(int, char*);
+void	cancel(Alarm*);
+void	checkalarms(void);
+void	clockinit(void);
+void	clockintr(Ureg*, void*);
+void	consinit(void);
+void	cpminit(void);
+void	cpuidprint(void);
+#define	dcflush(a,b)
+void	delay(int);
+void	eieio(void);
+uchar*	etheraddr(int);
+int	etherinit(void);
+int	etherrxpkt(int, Etherpkt*, int);
+int	ethertxpkt(int, Etherpkt*, int, int);
+void	exception(void);
+int	flashboot(int);
+int	flashbootable(int);
+char*	flashconfig(int);
+int	flashinit(void);
+void	free(void*);
+void	freeb(Block*);
+int	getcfields(char*, char**, int, char*);
+char*	getconf(char*);
+ulong	getdec(void);
+ulong	gethid0(void);
+ulong	getimmr(void);
+ulong	getmsr(void);
+ulong	getpvr(void);
+int	getstr(char*, char*, int, char*);
+ulong	gettbl(void);
+ulong	gettbu(void);
+int	hardinit(void);
+long	hardread(int, void*, long);
+long	hardseek(int, long);
+long	hardwrite(int, void*, long);
+long	i2crecv(int, void*, long);
+long	i2csend(int, void*, long);
+void	i2csetup(void);
+void*	ialloc(ulong, int);
+Block*	iallocb(int);
+void	idle(void);
+int	isaconfig(char*, int, ISAConf*);
+int	issqueezed(uchar*);
+void	kbdchar(Queue*, int);
+void	kbdinit(void);
+void	kbdreset(void);
+void	machinit(void);
+void*	malloc(ulong);
+ulong	mapalloc(RMap*, ulong, int, int);
+void	mapfree(RMap*, ulong, int);
+void	mapinit(RMap*, Map*, int);
+void	meminit(void);
+void	microdelay(int);
+void	mmuinit(void);
+int	optionsw(void);
+void	panic(char*, ...);
+int	parseether(uchar*, char*);
+int	plan9boot(int, long (*)(int, long), long (*)(int, void*, long));
+void	putdec(ulong);
+void	puthid0(ulong);
+void	putmsr(ulong);
+int	qbgetc(Queue*);
+void	qbputc(Queue*, int);
+void	qbwrite(Queue*, Block*);
+Block*	qget(Queue*);
+long	qlen(Queue*);
+Queue*	qopen(int, int, void (*)(void*), void*);
+#define	qpass	qbwrite
+void	scc2stop(void);
+void	sccnmsi(int, int, int);
+void	sched(void);
+void	screeninit(void);
+void	screenputs(char*, int);
+void	sdraminit(ulong);
+Partition*	sethardpart(int, char*);
+Partition*	setscsipart(int, char*);
+void	setvec(int, void (*)(Ureg*, void*), void*);
+int	splhi(void);
+int	spllo(void);
+void	splx(int);
+void	trapinit(void);
+void	uartputs(char*, int);
+void	uartsetboot(void (*f)(uchar*, int));
+void	uartspecial(int, int, Queue**, Queue**, void(*)(Queue*,int));
+void	uartwait(void);
+long	unsqueezef(Block*, ulong*);
+
+#define	GSHORT(p)	(((p)[1]<<8)|(p)[0])
+#define	GLONG(p)	((GSHORT(p+2)<<16)|GSHORT(p))
+#define	GLSHORT(p)	(((p)[0]<<8)|(p)[1])
+#define	GLLONG(p)	((GLSHORT(p)<<16)|GLSHORT(p+2))
+
+#define KADDR(a)	((void*)((ulong)(a)|KZERO))
+#define PADDR(a)	((((ulong)(a)&KSEGM)!=KSEG0)?(ulong)(a):((ulong)(a)&~KZERO))
+
+/* IBM bit field order */
+#define	IBIT(b)	((ulong)1<<(31-(b)))
+#define	SIBIT(n)	((ushort)1<<(15-(n)))
+
+#define IOREGS(x, T)	((T*)((char*)m->iomem+(x)))
+
+int	uartinit(void);
+Partition*	setuartpart(int, char*);
+long	uartread(int, void*, long);
+long	uartseek(int, long);
--- /dev/null
+++ b/os/boot.original/rpcg/g.mx
@@ -1,0 +1,1987 @@
+S0030000FC
+S325000100007C6000A63C800000608480427C632078606310007C0004AC7C6001247C0004AC52
+S325000100204C00012C7C908AA63C800A007C908BA64C00012C3C800C007C908BA64C00012C0A
+S325000100403C8004007C908BA64C00012C7C0004AC7C988AA63C800A007C988BA64C00012C2F
+S325000100603C800C007C988BA64C00012C3C8004007C988BA64C00012C388000077C9E23A6D3
+S325000100807CBE9AA63C80FA207C9E9BA63860FF88906400043C6001016063244090640000DE
+S325000100A0380000003C40001460427FF83C40001460427FF83C60FFC26063D7103882800866
+S325000100C07C0418004182002C38A2A1F87CA4285038A500037CA516707CA903A63884FFFC7B
+S325000100E03863FFFC84A3000494A400044200FFF83C60FFC2606302007C6803A64E80002026
+S325000101003862A1F8388227107C8320514081001C7C8416707C8903A63863FFFC3800000065
+S32500010120940300044200FFFC3822A3C89022801438210FF8380000004800AA01480086F587
+S32500010140480000003D00FA40806800003CA008007C63287890680000480000007C6000A6CC
+S325000101604E8000207C0004AC7C6001247C0004AC4C00012C4E8000207C0006AC4E800020AE
+S325000101804E8000207C6000A6606480007C0004AC7C8001247C0004AC4C00012C4E800020C4
+S325000101A07C6000A65464045E7C0004AC7C8001247C0004AC4C00012C4E8000207C8000A61A
+S325000101C0506404207C0004AC7C8001247C0004AC4C00012C4E8000207C6C42E64E80002062
+S325000101E07C7F42A64E8000207C7E9AA64E8000207C7602A64E8000207C7603A64E800020EE
+S325000102003821FF58BC4100303C40001460427FF87C9142A69081002C7CB042A690A10028B2
+S325000102207CC902A690C100247C8102A6908100207CB342A690A1001C7CD242A690C100187C
+S325000102407C9A02A6908100107CBB02A690A1000C90010008386100087C60092D3800000018
+S325000102604E800020B8410030800100287C1043A6800100247C0903A6800100207C0103A6A8
+S325000102808001001C7C0FF120800100187C1243A6800100107C1A03A68001000C7C1B03A671
+S325000102A08021002C4E8000207C3143A67C0000267C1343A67C0802A64BFFFF4938000000D6
+S325000102C04800AC294BFFFFA17C1242A67C0803A67C1042A64C00012C4C0000647FE802A6C1
+S325000102E097E1FFE84BFFFF05812280147064FFFF5484C23F418200802C0400204182006CA6
+S325000103002C040021418200587C0A0378914900143D00FA409109001C814900203CC0007AEE
+S3250001032060C6120090C9000C80EA028454E7653E394700018089000C7C8451D6908900086D
+S3250001034080E9001C3CC03E0090C7000083E100007FE803A6382100184E8000203D40000828
+S32500010360614A23A04BFFFFA83D400008614A23004BFFFF9C3D400008614A60004BFFFF9076
+S325000103807FE802A697E1FFE038629EC0480035D538629ED3480035CD4BFFFE49546A843E40
+S325000103A02C0A0006418101B4418201A42C0A0001418201902C0A00034182017C2C0A0004DD
+S325000103C04182016838629F0891410008480035954BFFFE117066FFFF90C1001038629F1CDA
+S325000103E081010010910100084800357938629F2E480035714BFFFDF5706AFFFF9141001881
+S325000104007D464671418201182C060020418201042C060021418200F038629F4F7D4846705C
+S32500010420910100084800353D38629F5A80810018708400FF90810008480035294800019D1D
+S325000104409061001038629F6880810010908100084800351138629F7880E2801480E7001C11
+S3250001046080E7000090E10008480034F98142801438629F87808A002080840284908100083C
+S3250001048080CA002080C6028090C1000C480034D538629FA481028014810800083D20000F84
+S325000104A0612942407D084BD691010008480034B538629FB5480034AD8142801438629FB75A
+S325000104C080AA002080A5010090A1000880EA002080E7010490E1000C4800348938629FD0EB
+S325000104E08082801480840020A084017A908100084800347183E100007FE803A638210020A9
+S325000105004E80002038629F47480034594BFFFF1C38629F404800344D4BFFFF1038629F3523
+S32500010520480034414BFFFF0438629EE7480034354BFFFEA038629EE0480034294BFFFE9459
+S3250001054038629ED94800341D4BFFFE8838629EEE480034114BFFFE7C2C0A00074182001C87
+S325000105602C0A0050418200084BFFFE5C38629F01480033F14BFFFE5C38629EF6480033E5A7
+S325000105804BFFFE507FE802A697E1FFF03862A0A7480033D180628014806300145463C23EF5
+S325000105A070630FFF2C03082340820028386000015463103A388283C07C6322148063000080
+S325000105C083E100007FE803A6382100104E8000207C0303784BFFFFDC806280148063001CB5
+S325000105E080630000706300F05463E13E4E8000208102801480C8000038E000327FE63B96AB
+S325000106007FFF39D67CDF30514082001480E8001C80C700006CC6080090C700004E8000204A
+S325000106207FE802A697E1FFF080A2801480A5002080A5010070A50001408200183860FFFF96
+S3250001064083E100007FE803A6382100104E80002038E2A0C490E100084800CDA18081001802
+S325000106603CC0FFC090C4000080E1001C3C800040908700007C03037883E100007FE803A666
+S32500010680382100104E8000207FE802A697E1FFE87C030000408100183860FFFF83E100003C
+S325000106A07FE803A6382100184E800020806100203882A0CE908100084800CD4180C10020CB
+S325000106C0390000029106001C3862A0D2480000CD7C671B787C030000418200148061002037
+S325000106E03863002C90E10008480029053860000183E100007FE803A6382100184E800020D1
+S325000107003821FFF0814280142C030004418200103860FFFF382100104E800020812A002075
+S32500010720810A001C80E8000064E7800090E80000A0E9095260E70A00B0E90952A0E9095055
+S3250001074070E7F5FFB0E9095080A1001838E0000790E500008101001C38A0000590A80000D5
+S325000107607C030378382100104E80002080A2801480A5001C808500003FE07FFF63FFFFFF28
+S325000107807FE42039908500004E8000204E8000204E8000204E8000207FE802A697E1FFD073
+S325000107A09061003480C284247C0600004082006048008929386000A93882C3A89081000806
+S325000107C038C0008090C1000C48008F4D7C0300004180019C3C600000606380A93882C3A88F
+S325000107E0388400809081000838C0008090C1000C48008F257C0300004180017438E000FF00
+S3250001080098E2C4A839000001910284243922C3A888C900002C0600FF4182001088E90000EA
+S325000108202C07000A408200187C03037883E100007FE803A6382100304E80002091210028DB
+S3250001084088A900002C05000A4182001088C900002C0600FF408201009121002C88C90000DE
+S325000108602C06003D40820050806100344800CB5D8121002C810100287C8848507C041800BF
+S3250001088040820034806100344800CB41906100188061003480A1002890A1000880E10018D9
+S325000108A090E1000C4800CAAD8121002C7C03000041820038888900002C04000A418200108F
+S325000108C088A900002C0500FF40820018888900002C04000A4082FF3C392900014BFFFF34AE
+S325000108E0392900014BFFFFD039490001890900002C08000A41820010888900002C0400FF0F
+S325000109004082004C38628048914100089121002C914100287CCA485090C1000C4800C64520
+S3250001092038E2804880A1002C7CE53A14810100287CE83850980700003862804883E10000D7
+S325000109407FE803A6382100304E800020392900014BFFFF9C88E900002C07003D4082000816
+S325000109604BFFFEF8392900014BFFFED83862A0D548002FF17C03037883E100007FE803A6C8
+S32500010980382100304E8000203821FFF080A2801480A500087CA51BD638A500087CA5267000
+S325000109A02C051000418000183865000F7C631E7060630001382100104E80002054A3083CA7
+S325000109C0382100104E8000207FE802A697E1FFD89061002C38600009900100084BFFFDB10C
+S325000109E0810280148128002080A90ABC60A500C090A90ABC9121002480A90AB83FE0FFFF7F
+S32500010A0063FFFF3F7FE5283990A90AB8806100304BFFFF798121002464680001910909F076
+S32500010A2080A90AE03FE0FFFF63FF0FFF7FE5283990A90AE038600001480032B18141002C75
+S32500010A407C691B783CA0FA2060A53E8090A10020B0650000906A00B43C8000006084B000FA
+S32500010A60B0830000B0030002390A00247508E0003CA020007C0828004182011038EA002401
+S32500010A8090E9000438600001480032618141002C7C691B7881010020B0680002906A00B88A
+S32500010AA038C03000B0C30000B003000238AA00A474A5E0003CE020007C053800418200B8F0
+S32500010AC0388A00A4908900047C03037839000009910100089001000C48003085812100205A
+S32500010AE038E0001898E9000438A0001898A9000539000001B109000638C00001B0C9002870
+S32500010B00B009002CB009002E39000001B1090030808280148084002039240A8038C000FF46
+S32500010B2098C9000691210018388000179889000A386000143CA0FFC260A50C9C90A1000854
+S32500010B4080E1002C90E1000C4800A1298121001838E04820B0E90002A0A9000260A500034A
+S32500010B60B0A9000283E100007FE803A6382100284E800020388A00A43FE0FFFF63FFFFFF4D
+S32500010B807FE420394BFFFF4038EA00243FE0FFFF63FFFFFF7FE738394BFFFEE87FE802A630
+S32500010BA097E1FFD08121003880A2801480A5002038A50A8038E000FF98E50006810900B4D3
+S32500010BC0910100207C0800004182001480810020A0840000708480004182009C816900B847
+S32500010BE07C0B00004182001491610020A08B0000708480004182001483E100007FE803A694
+S32500010C00382100304E8000203940FFFF80C900107C0600004182001C9121002C806900104E
+S32500010C2048009409816100208121002C7C6A1B782C0AFFFF4182002C994900A438C00001DD
+S32500010C40B0CB0002A08B000060848000B08B000083E100007FE803A6382100304E8000205B
+S32500010C609809000883E100007FE803A6382100304E80002080A9000C7C050000418200144C
+S32500010C8080810020A08400027C0400404181002481010020A0A8000060A59000B0A8000089
+S32500010CA083E100007FE803A6382100304E80002080A900187C0500004182002438690024D4
+S32500010CC080A10020A0A5000290A1000880E900187CE803A64E8000214BFFFFB89121002CF0
+S32500010CE080C900147C060000418200487C0A037881010020A10800027C0A40404080FF945C
+S32500010D00914100247CCA4A1488C600248069000C90C1000880E900147CE803A64E800021F9
+S32500010D208121002C80A10024394500014BFFFFC480610020A0630002480090E9906100183D
+S32500010D408063000480C1002C38C6002490C1000880810020A08400029081000C4800C2054A
+S32500010D608121001881010020A1080002808900047D044214910900048061002C8063000CE7
+S32500010D80912100084800920D4BFFFF087FE802A697E1FFE09061001C4BFFF4098121001CE2
+S32500010DA090610018888900087C0400004082001C80690010480092758121001C90610014A1
+S32500010DC02C03FFFF4082001C806100184BFFF3F183E100007FE803A6382100204E800020FF
+S32500010DE080C280B47C06000041820064810900B8A108000071088000418200084BFFFFF0E5
+S32500010E0080C1001498C900A480C900B838A00001B0A6000280C900B8A0A6000060A5800073
+S32500010E20B0A600007D284B7880A280B47C0500004082001038A0000198A800084BFFFF6872
+S32500010E407C05037898A800084BFFFF5C7C0A0378914100102C0A00644080FFA880C900B8BD
+S32500010E60A0C6000070C68000408200084BFFFF943860000148001C098121001C80C1001093
+S32500010E80394600014BFFFFCC7FE802A697E1FFE0906100243902C4B080A800047C050000DF
+S32500010EA04182001483E100007FE803A6382100204E8000209101001C38C0000190C8000476
+S32500010EC038601000900100089001000C90010010480090098121001C9069000C8101002C3A
+S32500010EE09068000038604000900100083CE0FFC260E70E8C90E1000C9121001048008FDDD1
+S32500010F00814100288121001C9069001080C100309066000080A1003490A90014388000094F
+S32500010F20908900007C0A000040820008394025807D234B78914100084BFFFA9183E10000AD
+S32500010F407FE803A6382100204E8000209062C4C84E8000207FE802A697E1FFD88181003017
+S32500010F607C6D1B7838C2C4B090C100247C0B03787C6A1B7891A1002C7D0D62147C0A40402C
+S32500010F804080002C88AA00007CA507742C05000A40820008396B0001394A000191A1002C04
+S32500010FA07D0D62147C0A40404180FFDC7C6C5A1448008E71818100308141002C7C6B1B7851
+S32500010FC07D856378398CFFFF7C0500004182005488AA00007CA507742C05000A40820018EF
+S32500010FE080CB000439060001910B00043900000D99060000808B000438C4000190CB00046B
+S325000110007D465378394A000188C6000098C400007D856378398CFFFF7C0500004082FFB477
+S3250001102080610024806300109161000848008F6583E100007FE803A6382100284E80002098
+S325000110403821FFF03902C4B088E800087C070000418200084BFFFFF4382100104E80002038
+S325000110607FE802A697E1FFE0812100289061002438A2C5707C0900004081001490A1001C6E
+S32500011080808500007C0400004082001483E100007FE803A6382100204E8000207D234B78B0
+S325000110A048008D819061001880630004808100249081000880E1002890E1000C4800BEA5F4
+S325000110C08121001880E10028808900047CE43A1490E900048061001C8063000091210008F4
+S325000110E048008EB183E100007FE803A6382100204E800020386000014E8000207FE802A6F1
+S3250001110097E1FFF08061001838A2819890A100084800C3517C0300004182001C8061001889
+S325000111203882819D908100084800C3397C03000040820038900281F83CC0002090C281FC04
+S32500011140386281F83863000838E281A290E100084800C2A9386281F883E100007FE803A6E2
+S32500011160382100104E8000207C03037883E100007FE803A6382100104E8000207FE802A63D
+S3250001118097E1FFE88082C5707C0400004082001C3C600001900100089001000C90010010E0
+S325000111A048008D399062C5708102C5747C080000418200108062C57448008CC19002C57465
+S325000111C0386281A74800279D3C60FFC2606311604BFFFD7D38C0FFFF90C2C5789002C57C8D
+S325000111E09002C5C09002C5C47C03037883E100007FE803A6382100184E8000207FE802A6DA
+S3250001120097E1FFD08181003890610034810100349101001C3942C57080E2801480E70000B0
+S3250001122090E1002C918100387C0C000040810140812A000491410028900A00047C0900006A
+S32500011240408200A0900A0054806A000048008CC981810038814100287C691B787C03000095
+S325000112604082008080C2801480C600008101002C7CC8305054C5083C7CC62A1454C6183850
+S3250001128054A5482C7CC6285038E000327CC63B9628063A984180FFB480EA005438E7000171
+S325000112A090EA00542C07000341800020386281C1480026B17C03037883E100007FE803A6D9
+S325000112C0382100304E800020386281D039000001910100084BFFFC81814100284BFFFF6C6B
+S325000112E080A9000480C900007D4628507C0A6000408100087D8A63788061001C91210020D6
+S3250001130080E9000090E10008914100249141000C4800BC5181610024814100288121002009
+S32500011320808900007CE45A1490E9000080E9000080C900047C073040418000507D234B7839
+S3250001134048008B39816100248141002880E100387D8B385080E1001C7CA75A1490A1001C06
+S32500011360918100387C0C00004181FEC88061001C80E100347C67185083E100007FE803A6BB
+S32500011380382100304E800020912A00044BFFFFC07FE802A697E1FFE0808100289081001C4B
+S325000113A08122C5C07C0900004081005880E1002C7C093800408100088121002C8102C5C077
+S325000113C07CC9405090C2C5C08061001C38E2C57038E7001090E10008912100189121000CDE
+S325000113E04800BB81812100188081001C7CE44A1490E1001C8081002C7CE9205090E1002CA1
+S3250001140080E1002C7C070000408100C83862815038A0004090A100084BFFFDE58141002C56
+S325000114207C691B782C030040408000187C03037883E100007FE803A6382100204E80002011
+S325000114407C035000408100307C8A48509082C5C03862C5703863001038A281507CA55214E4
+S3250001146090A1000880A2C5C090A1000C4800BAF58121002C8061001C38C2815090C1000862
+S32500011480912100189121000C4800BAD9812100188101002C7CC9405090C1002C8101001C8A
+S325000114A07CC84A1490C1001C80C2C57C38C6000190C2C57C386281D2388000019081000842
+S325000114C04BFFFA9580E1002C7C0700004181FF408061001C810100287C68185083E10000C4
+S325000114E07FE803A6382100204E8000203821FFE87C0B03782C0B0100408000545569C00E54
+S32500011500394000087C0A00004081002875248000418200445526083C3FE004C163FF1DB7DB
+S325000115207FE93278394AFFFF7C0A00004181FFE05567103A38A2DC307CE72A1491270000A5
+S32500011540396B00012C0B01004180FFB4382100184E8000205529083C4BFFFFCC7FE802A6EE
+S3250001156097E1FFF081410018906100148082DC347C0400004082000C4BFFFF758141001826
+S3250001158080C1001C3FE0FFFF63FFFFFF7FE8327881210014394AFFFF7C0A00004180003C9F
+S325000115A05505463E7D264B783929000188C600007CA5327854A5103A38C2DC307CA53214B4
+S325000115C080A500005507402E7CE82A78394AFFFF7C0A00004080FFCC3FE0FFFF63FFFFFF00
+S325000115E07FE3427883E100007FE803A6382100104E800020816100088121000C7C0B0000DE
+S32500011600408200148083000090890000912300004E80002080AB000090A90000912B00000F
+S325000116204E800020814100088121000C7C0A00004082001080890000908300004E800020DB
+S3250001164080C9000090CA00004E8000207FE802A697E1FFE87C09037838E2ED382C09000A06
+S325000116604080002C80C700047C0600004082001080A7000C7C0500004182003039290001CE
+S3250001168038E700142C09000A4180FFDC386282D8480023597C03037883E100007FE803A60F
+S325000116A0382100184E8000209007000C9007001038A0000190A700047CE33B7883E10000F0
+S325000116C07FE803A6382100184E8000207FE802A697E1FFD89061002C7C03000040800008D2
+S325000116E09001002C4BFFEABD906100184BFFFF61818280147C6A1B7880C1002C54C5083CA8
+S325000117007CC62A1454C620367CC62A1438E003E87CC63B9690C3000880A1003090A3000C51
+S3250001172080810034908300107C0B0378812C00187C0900004182003480A90008808A0008C4
+S325000117407C0520004181005480A90008808A00087CA5205090AA00087D2B4B7881290000A0
+S325000117607C0900004082FFD4386C001891610008914100249141000C4BFFFE7D8061001800
+S325000117804BFFEA3D8061002483E100007FE803A6382100284E800020808A00088109000845
+S325000117A07C844050908900084BFFFFC09003000C4E8000204E8000207FE802A697E1FFA8BF
+S325000117C04BFFE9E1814280149061004C812A00187C090000418200A47C0B03787C09000024
+S325000117E04182001080E900087C070000408100A47C0900004182001080E9000838E7FFFFD0
+S3250001180090E900087C090378916100507C095800408000685527103A3901001C7CE7421424
+S3250001182080E7000080E7000C7C07000041820028912100545523103A38C1001C7C63321457
+S32500011840806300007CE803A64E80002181610050812100545525103A3881001C7CA522148A
+S3250001186080A500009005000439290001916100507C0958004180FFA08061004C4BFFE94120
+S3250001188083E100007FE803A6382100584E8000202C0B000A418000084BFFFF589161005041
+S325000118A05568103A38C1001C7D08321491280000386A0018900100089121000C4BFFFD69C0
+S325000118C081428014812A001880E10050396700014BFFFF0CA121000A5527043E54E7C23E7B
+S325000118E098E300005526043E98C300014E800020814100085544463E988300005546843E00
+S3250001190098C300015548C23E99030002994300034E8000207C671B78886300005463C00E76
+S32500011920888700015484801E7C63237888A7000254A5402E7C632B7888C700037C633378AA
+S325000119404E8000207C671B78886300005463402E88A700017C632B784E8000203821FFD83C
+S325000119608222809C814100307C691B787C0F03787C0C03787C0B03787C100378706500014E
+S32500011980418200207C0A000041820014888900007D8C2214394AFFFF392900013A00000191
+S325000119A02C0A001041800054A0E90000A08900027D6B3A14A0C900047DAB2214A109000660
+S325000119C07DCD3214A0A900087DCE4214A0E9000A7DCE2A14A089000C7DCE3A14A0C9000E1D
+S325000119E07DAE22147D6D3214394AFFF0392900102C0A00104080FFB42C0A00024180001C9D
+S32500011A00A0C900007D6B3214394AFFFE392900022C0A00024080FFEC7C10000041820070A2
+S32500011A207C0A00004182000C88A900007DEF2A14889100007C8407747C0400004182004850
+S32500011A407DEF5A145588C23E7D2F4214718800FF5508402E7D2942145528843F41820014F0
+S32500011A607127FFFF7D283A145528843F4082FFF43FE0FFFF63FFFFFF7FE34A7838210028BF
+S32500011A804E8000207D8C5A144BFFFFBC7C0A00004182000C88A900007D8C2A1488910000EF
+S32500011AA07C8407747C0400004182000C7D8C5A144BFFFF947DEF5A144BFFFF8C3821FFF00A
+S32500011AC07C691B787C0B037888E3000070E7000F54EA103A7C0A00004081002888C900006C
+S32500011AE054C6402E890900017CC643787D6B3214394AFFFE392900027C0A00004181FFE08E
+S32500011B007168FFFF5566843E7D0832147104FFFF5507843E7C843A146883FFFF382100106E
+S32500011B204E8000207FE802A697E1FFD0906100343862B7C89061002C9001000838E005F059
+S32500011B4090E1000C4800B1E98061002C3863002A80A1003C90A10008810100409101000C57
+S32500011B604800B4018121002C80C1004039460008980900163900001199090017980900141C
+S32500011B80980900153869001891410020914100084BFFFD458061002C3863001A8102822090
+S32500011BA0910100084BFFFD4D8061002C38630022A0E2822490E100084BFFFD1D8061002C14
+S32500011BC03863001E8101003881080000910100084BFFFD218061002C3863002480810038FB
+S32500011BE0A0840004908100084BFFFCED8061002C3863002680E1002090E100084BFFFCD983
+S32500011C008121002C98090028980900293869001680E1004038E7001490E100084BFFFD41D0
+S32500011C205464043E908100188061002C3863002881010018910100084BFFFC9D3922B7C8B9
+S32500011C40810100403948002C390000459909000E9809000F390000FF990900169121002866
+S32500011C60386900109141002438AAFFF290A100084BFFFC6580610028386300128082801CAB
+S32500011C8038E4000190E2801C908100084BFFFC49812100289809001498090015980900187C
+S32500011CA0980900193869000E4BFFFE155468043E91010018806100283863001880810018DA
+S32500011CC0908100084BFFFC11806100283863000C39000800910100084BFFFBFD80610028B7
+S32500011CE080C1003838C6000690C10008388000069081000C4800B26D8061003438E2B7C817
+S32500011D0090E10008808100249081000C38E0138890E100104800471583E100007FE803A6B5
+S32500011D20382100304E8000207FE802A697E1FF60906100A49801001C38A0000598A1001DC2
+S32500011D409801001E80C100AC98C1001F3861001C3863000480C100B090C100084800B69D27
+S32500011D60806100B04800B66538830005806100A4810100A89101000838C1001C90C1000CED
+S32500011D80908100104BFFFDA180C100B47C0600004182001C38629C48810100AC9101000897
+S32500011DA080C100B090C1000C48001BB983E100007FE803A6382100A04E8000207FE802A648
+S32500011DC097E1FFD09061003480A281F47C0500004082029C392003E880828014808400003A
+S32500011DE05485083C7C842A145484183854A5482C7C84285038C000327C8433967C89221446
+S32500011E009081001880A2801480A5000054A6083C7CA5321454A5183854C6482C7CA530509A
+S32500011E2038E000327CA53B96810100187C082840408102288061003438E2BDB890E10008D1
+S32500011E4080828014808400005486083C7C8432145484183854C6482C7C84305038E00032FD
+S32500011E607C843B96810100187C8440509081000C480044319061002C7C0300004181000820
+S32500011E804BFFFF843882BDB8908100203864000C4BFFFAB55466043E2C060800418200086C
+S32500011EA04BFFFF64806100203863000E4BFFFC11812100207C0300004182001038629C5EC5
+S32500011EC048001AA14BFFFF4088E9000E2C0700454182001038629C6F48001A894BFFFF28A4
+S32500011EE0890900172C080011418200084BFFFF1898090016386900264BFFFA4D5466043EB6
+S32500011F00806100203863001890C1002890C100084BFFF9C580610020386300284BFFFA29FB
+S32500011F207C030000408200F480A10038A0A500047C050000418200208061002038630022A1
+S32500011F404BFFFA0581010038A10800047C0340004082FEB4806100203863001A4BFFF9B9E5
+S32500011F60814100389061001C80AA00003880FFFF7C0520004182001080AA00007C0328002E
+S32500011F804082FE8480C100283926FFF880C100407C0930004081001038629CA6480019C52E
+S32500011FA04BFFFE648061003C808100203884002A90810008912100289121000C4800AFA5FD
+S32500011FC080A1003880E1001C90E5000080610020386300224BFFF97181210038B069000446
+S32500011FE03869000638A2BDB838A5000690A1000838E0000690E1000C4800AF693880000114
+S32500012000908281F48061002883E100007FE803A6382100304E80002080610020386300168C
+S32500012020808100283884000C908100084BFFF9315469043E5528043E7C0800004182FEEC2C
+S3250001204038629C815527043E90E1000880E1002C90E1000C4800190D7C03037883E10000B5
+S325000120607FE803A6382100304E800020392013884BFFFD687FE802A697E1FDC89061023CB4
+S325000120809801002638E0000198E10027386100263863000238829CBB9081000880C10244B4
+S325000120A090C1000C48001879390300023861002638630001910102307C681A1438829CBE60
+S325000120C090810008480018598161024038A3000280C102307CA62A1490A10230A08B0004C1
+S325000120E0908102287C090378912102342C0900054080007081010228B10B00048061023CC1
+S325000121009161000838E1002690E1000C80810230908100104BFFFA1181210240B0090004B8
+S325000121208061023C9121000880A1024890A1000C39000204910100104BFFFC858161024047
+S32500012140812102482C0300044080003480C1023439260001912102342C0900054180FF9814
+S3250001216038629D05480017FD3860FFFF83E100007FE803A6382102384E8000208889000024
+S325000121805484402E88C900017C8433782C040003418200482C040005418200084BFFFFB0BE
+S325000121A038629CC488C9000254C6402E890900037CC6437890C1000838A9000490A1000C36
+S325000121C0480017A13860FFFF83E100007FE803A6382102384E8000203960000188890002C0
+S325000121E05484402E88C900037C843378916283E87C0458004182004838629CDE9081000825
+S32500012200480017618061023C80C1024090C10008388000019081000C38C29CF990C1001036
+S32500012220900100144BFFFB053860FFFF83E100007FE803A6382102384E8000203863FFFC87
+S3250001224083E100007FE803A6382102384E8000207FE802A697E1FFD0812283E890610034F9
+S325000122609801002038800004988100217D25467098A100229921002338A9000190A283E899
+S32500012280810100403908000491010040900100248061003480E1003890E1000838A1002089
+S325000122A090A1000C38E0000490E100104BFFF8798061003480E1003890E1000880A1003CFE
+S325000122C090A1000C81010040910100104BFFFAF1816100408141003C7C691B787C035800B2
+S325000122E04080006438629D2C912100089161000C480016718061003480C1003890C10008E2
+S32500012300388000029081000C38C29D4090C10010900100144BFFFA158101002438C8000102
+S3250001232090C100242C080005408000084BFFFF643860FFFF83E100007FE803A638210030E0
+S325000123404E800020890A00025508402E88AA00037D082B789101002C808283E87C082000FC
+S325000123604182007C38629D4B480015F9814283E88121002C38CAFFFF7C09300040820018B4
+S3250001238080A1002439050001910100242C0500084180FF0038629D4D912100089141000CE7
+S325000123A0480015C18061003480E1003890E1000838A0000190A1000C38E29D7590E100100E
+S325000123C0900100144BFFF9653860FFFF83E100007FE803A6382100304E8000203863FFFC92
+S325000123E083E100007FE803A6382100304E8000207FE802A697E1FC48906103BC48003E6981
+S32500012400814103C0906100C07C0300004082002838629D8180A103BC90A1000848001545A3
+S325000124203860FFFF83E100007FE803A6382103B84E8000209001002C900100287C0A00008D
+S325000124404182001488AA00007CA507747C050000408205C03861024C9001000838A0016C03
+S3250001246090A1000C4800A8C938E0000198E1024C390000019901024D388000069881024E35
+S325000124803861024C3863001C80A100C090A10008390000069101000C4800AAC990028220B1
+S325000124A038A00044B0A28224386282203863000680C100C090C10008388000069081000CEF
+S325000124C04800AAA1900100DC808100DC2C04000A4080009038C0FFFF90C2823838E0004331
+S325000124E0B0E2823C3862823838630006390283689101000838A0000690A1000C4800AA655E
+S32500012500806103BC390282389101000838A1024C90A1000C38E0016C90E100104BFFF609D2
+S32500012520806103BC38C2823890C10008390100E09101000C38A0016C90A100104BFFF881E6
+S325000125407C0300004181045C80C100DC38C6000190C100DC808100DC2C04000A4180FF783B
+S3250001256080C100DC2C06000A4180002038629D94480013F13860FFFF83E100007FE803A6F9
+S32500012580382103B84E8000208101002C7C0800004182040080A1002C88A500007CA5077423
+S325000125A07C050000418203EC8901010C7D0807747C0800004182001838629DA538E100E016
+S325000125C038E7002C90E100084800139938629DA9888100F490810008888100F59081000C2B
+S325000125E0888100F690810010888100F790810014A082823C908100188081002C9081001C2C
+S32500012600480013614BFFEA3D386100E0386300104BFFF30590628220A08283A438E4000126
+S32500012620B0E283A4B0828224386100E0386300144BFFF2E59062823838E00045B0E2823C60
+S32500012640806103BC38C2823890C100088121002C9121000C38C2C5C890C100104BFFFA19F5
+S325000126607C030000408000183860FFFF83E100007FE803A6382103B84E8000203882C5C8A9
+S3250001268039440004906100D82C030020418002CC890A00005508402E88CA00017D0833782A
+S325000126A05508801E88EA000254E7402E888A00037CE723787D083B782C0806EB4082029C2B
+S325000126C088EA000454E7402E88AA00057CE72B7854E7801E88CA000654C6402E890A000744
+S325000126E07CC643787CED337888AA000854A5402E890A00097CA5437854A5801E888A000AF6
+S325000127005484402E88CA000B7C8433787CAC2378890A000C5508402E88CA000D7D083378A8
+S325000127205508801E88EA000E54E7402E888A000F7CE723787D083B78910100C8918100CCDF
+S325000127407CC8621491A100D07CC66A1490C100C488AA001454A5402E890A00157CA54378B0
+S3250001276054A5801E888A00165484402E88CA00177C8433787CA5237838629DD090A100B491
+S325000127803FE01FFF63FFFFFF7FE8283991010008480011D14BFFE8AD38629DDF80C100D003
+S325000127A090C10008480011BD808100B43FE01FFF63FFFFFF7FE42039908100BC38E2C5C821
+S325000127C039A70024808100D83944FFE0816100D0916100D47C0A000040820050806103BC09
+S325000127E0388282389081000838E2C5C890E1000C39000200910100104BFFFA59816100D4F1
+S325000128007C6A1B787C030000408000183860FFFF83E100007FE803A6382103B84E800020D5
+S3250001282038C2C5C839A60004914100D87C0B5000418100087D6A5B78806100BC91A100B89B
+S3250001284091A10008914100DC9141000C4800A715818100CC814100DC80A100BC7D05521476
+S32500012860910100BC80A100B87DA5521491A100B880A100D47D6A285080A100D87D4A28502C
+S32500012880914100D8916100D47C0B00004181FF487C0C000040820088806103BC38C282380B
+S325000128A090C10008390000039101000C38A29DE690A10010900100144BFFF47138629DE9CC
+S325000128C080E100C890E1000880A100C490A1000C4800109138629DF1810100B4910100084C
+S325000128E0480010814BFFE75D4800137D4BFFD8B580C100B43FE01FFF63FFFFFF7FE630395B
+S325000129007CC803A64E8000217C03037883E100007FE803A6382103B84E80002038629DE24B
+S32500012920918100084800103D81A100B8814100D8816100CC916100D4900100CC80E100BC7F
+S3250001294038E70FFF3FE0FFFF63FFF0007FE7383990E100BC4BFFFE80806103BC38C28238B4
+S3250001296090C100089001000C39029DBF9101001038A0000190A100144BFFF3B13860FFFF7F
+S3250001298083E100007FE803A6382103B84E80002038C100E038C6006C90C1002C4BFFFC0CA8
+S325000129A03861024C3863001C390100E03908001C9101000838A0000690A1000C4800AB0D46
+S325000129C0814100287C030000418200084BFFFB7C88E100E12C0700014082FB7088C100E225
+S325000129E02C0600064082FB647C0A00004182FB747D435378388100E03884002C908100089A
+S32500012A004800AA617C0300004182FB584BFFFB3C38610030914100084800A9E13861003008
+S32500012A203880003A908100084800A2E17C0300004182004038E100309061002C7C0338001A
+S32500012A404182FA1488A3FFFF7CA507742C05005C408200084BFFFA0038C1003090C100289C
+S32500012A6038C3000190C1002C980300004BFFF9E8390100309101002C4BFFF9DC3821FFF081
+S32500012A807C691B7880A28014814500047D254B783929FFFF7C050000408100187C0703781A
+S32500012AA07C0750404080FFE838E700014BFFFFF4382100104E8000203821FFF08102801442
+S32500012AC0810800047D0341D638A003E87D482BD741810008394000017C0903787C095040E8
+S32500012AE040800010392900017C0950404180FFF8382100104E8000207FE802A697E1FFF002
+S32500012B00806280284BFFD6F580A2801480E5000038E7000190E500004BFFECA18102823053
+S32500012B207C0800004182000C7D0803A64E80002183E100007FE803A6382100104E80002053
+S32500012B407FE802A697E1FFB88142801480CA000838E003E87CC63BD690CA00044BFFD67D36
+S32500012B60906100443860000A4BFFFF154BFFD66D808100447CE4185090E100447C07000047
+S32500012B80408000084BFFFFD83861002881028014810800049101000848009D69386100203F
+S32500012BA0810280148108000C5504103A7D0822145508083C38A003E87D082BD69101000880
+S32500012BC048009D253861003039010008392100288089000080A900049088000090A80004CD
+S32500012BE038A1001038C10020810600008126000491050000912500044800A0DD38610028C4
+S32500012C00810100445508103A9101000848009CD93861003838C10008390100308128000004
+S32500012C208088000491260000908600043881001038A1002880C500008105000490C40000C3
+S32500012C40910400044800935939010004392100388089000080A900049088000090A8000446
+S32500012C6048009DD581428014906A0004810A00047C0800004082000C38800001908A000486
+S32500012C8080AA000C38C000047CA533D638E000327CA53BD63865FFFF906280284BFFD55DA4
+S32500012CA083E100007FE803A6382100484E8000207FE802A697E1FFE89061001C7C0903788F
+S32500012CC080A282347C09280040800060912100145523103A38C226107C6332148063000088
+S32500012CE08101001C910100084800A779812100147C030000408200245523103A38822690E0
+S32500012D007C6322148063000083E100007FE803A6382100184E8000203929000180A28234A6
+S32500012D207C0928004180FFA87C03037883E100007FE803A6382100184E8000207FE802A69B
+S32500012D4097E1FF28816100E03CE0002090E100A87C0300004182021080E280A080E7000079
+S32500012D6090E1000838E100B490E1000C48002AA9814100A87C030000418100183860FFFF15
+S32500012D8083E100007FE803A6382100D84E800020980A0000386100B49141000838A003FFF6
+S32500012DA090A1000C48001FA57C6A1B787C030000418100183860FFFF83E100007FE803A6E7
+S32500012DC0382100D84E80002080A100A87CA51A1498050000806100A838630400810100A8C6
+S32500012DE09101000838CA000190C1000C4800A175808100A8396404007D6A5B787D6C5B78B4
+S32500012E00888A00007C8407747C04000041820028890A00007D0807742C08000D4082011804
+S32500012E20394A0001888A00007C8407747C0400004082FFE0980B00007D83637838E10020A2
+S32500012E4090E10008388000209081000C38C2886B90C1001048005EF1906100AC7C0A03787A
+S32500012E60808100AC7C0A200040800044914100B05543103A38A100207C632A148063000097
+S32500012E8038E0003D90E1000848009E8181828234814100B07C03000040820028394A0001DE
+S32500012EA0808100AC7C0A20004180FFC47C03037883E100007FE803A6382100D84E800020A7
+S32500012EC039630001980300005547103A390100207CE7421480E700007CE758502C07001DF8
+S32500012EE0418000185546103A38A100207CC62A1480C600009806001B5587103A38A226105F
+S32500012F007CE72A145546103A38A100207CC62A1480C6000090C700005588103A38C2269037
+S32500012F207D08321491680000388C0001908282344BFFFF6C888A00007C8407742C040009BE
+S32500012F404082000C38E0002098EA00007D685B78396B0001892A00007D29077499280000F0
+S32500012F604BFFFEC07C0B00004182005C7D635B7890010008388003FF9081000C4800A5BDCF
+S32500012F807C030000408200183860FFFF83E100007FE803A6382100D84E8000203862885036
+S32500012FA0480009C1806100A880E100E090E100084800A449806100A84800A4117C6A1B7881
+S32500012FC04BFFFE144BFFD5C190610018806100A880C1001890C100084800A421806100A8D4
+S32500012FE04800A3E97C6A1B784BFFFDEC7FE802A697E1FFD89061002C8121003088A90000CC
+S325000130007CA507742C050020408200183929000188A900007CA507742C0500204182FFF0AF
+S325000130207C0A03789141001C2C0A0006408000C0888900007C8407747C04000040820018F8
+S325000130403860FFFF83E100007FE803A6382100284E8000203889000188A900007CA5077461
+S3250001306098A10024890400007D0807747C080000408200183860FFFF83E100007FE803A6F7
+S32500013080382100284E8000203904000191010020888400007C840774988100259801002646
+S325000130A03861002490010008388000109081000C48009EB58141001C812100208101002CE5
+S325000130C07D08521498680000890900007D0807742C08003A4082000839290001394A00014D
+S325000130E09141001C2C0A00064180FF487C03037883E100007FE803A6382100284E800020BA
+S325000131007FE802A697E1FFB87C691B783861002C3902886D910100089121000C81010050D3
+S3250001312091010010480007F97C09037880C282347C093000408000489121001C5523103A59
+S3250001314038E226107C633A14806300003881002C9081000838C0001C90C1000C4800A1F5BB
+S325000131608121001C7C030000418200283929000180C282347C0930004180FFC07C03037896
+S3250001318083E100007FE803A6382100484E80002081010054900800345525103A388226904F
+S325000131A07CA5221480A5000090A1002880E1002888E700007CE707747C07000041820040D7
+S325000131C080C1002888C600007CC607742C0600204182035080E1002888E700007CE7077436
+S325000131E02C0700094182033C80C1002888C600007CC607747C060000408200183860000121
+S3250001320083E100007FE803A6382100484E80002080610028388288729081000838C00005D1
+S3250001322090C1000C4800A12D814100547C030000408200D48101002839080005910100283F
+S325000132407D49537838CA001B7C0930404080002C80A1002888A500007CA507747C05000045
+S325000132604182001880C1002888C600007CC607742C0600204082005C9809000080810028BE
+S32500013280888400007C8407747C0400004182FF2081010028890800007D0807742C080020AF
+S325000132A0408200084BFFFF0880810028888400007C8407742C040009408200084BFFFEF001
+S325000132C080A1002838A5000190A100284BFFFFB080E1002888E700007CE707742C0700095C
+S325000132E04182FF9880A10028388500019081002888A500007CA5077498A9000039290001C0
+S325000133004BFFFF448061002838E2887890E10008388000059081000C4800A0397C03000003
+S3250001332040820028806100283863000539010028910100089001000C48009C2D80A10054D4
+S325000133409065001C4BFFFF388061002838A2887E90A1000838E0000490E1000C48009FF53D
+S325000133607C03000040820028806100283863000438C1002890C100089001000C48009BE952
+S3250001338081010054906800204BFFFEF480610028390288839101000838A0000490A1000CFA
+S325000133A048009FB17C03000040820028806100283863000438810028908100089001000CC6
+S325000133C048009BA580C10054906600244BFFFEB08061002838C2888890C10008390000050D
+S325000133E09101000C48009F6D7C03000040820028806100283863000538E1002890E1000808
+S325000134009001000C48009B6180810054906400284BFFFE6C806100283882888E90810008AD
+S3250001342038C0000390C1000C48009F29812100547C0300004082003C3869002C80A1002894
+S3250001344038A5000390A100084BFFFBA52C03FFFF4082FE2C806100543863002C90010008B4
+S32500013460388000069081000C480098C54BFFFE1080C900342C0600084080FE0480A9003497
+S3250001348054A520367CA54A143945003881010028890800007D0807747C0800004182001807
+S325000134A080E1002888E700007CE707742C07002040820018980A000080C9003438C60001E4
+S325000134C090C900344BFFFDB881010028890800007D0807742C080009408200084BFFFFD8F6
+S325000134E07D445378394A000180A10028390500019101002888A500007CA5077498A400006E
+S325000135007CE9505081090034550820367CE8385038E7FFC82C07000F4180FF744BFFFF9805
+S325000135208101002839080001910100284BFFFC947FE802A697E1FFF09061001480C1001830
+S3250001354090C100084BFFDA118061001480A1001890A100084800729183E100007FE803A6B0
+S32500013560382100104E8000207FE802A697E1FFD0386295484BFFF73D7C691B787C090000A5
+S32500013580418200247D234B789121002C38A2955B90A1000848009C7D8121002C7C0300004B
+S325000135A04182009C3C80FFC260841054908282F4900100247C090000418200187D234B78E0
+S325000135C0900100089001000C4800999D90610024900100283862955F4BFFF6D981210028F1
+S325000135E07C03000041820014900100089001000C480099757C691B787C090000408200081B
+S32500013600392025808061002491210008388281909081000C38C281D890C100103D00FFC24C
+S325000136206108374C910100144BFFD86183E100007FE803A6382100304E8000203CE0FFC2A6
+S3250001364060E7363090E282F44BFFFF687FE802A697E1FFF09061001480C1001870C8007F92
+S32500013660910100182C08001040820010386295644800037981010018806100149101000803
+S3250001368048006A4D83E100007FE803A6382100104E8000207FE802A697E1FFE090610024DE
+S325000136A09001001880C2801480C6000090C100148101002C7C0800004182001C80A2801412
+S325000136C080A5000080C100147CA62850280500FA4181010480628190480069517C691B7874
+S325000136E02C03FFFF408200084BFFFFC82C03000D408200083920000A2C09007F40820008D4
+S32500013700392000089121001C2C090015408200C03900000A99010013386100133880000152
+S325000137209081000880C282F47CC803A64E80002181810024816100288141001C812100180D
+S325000137402C0A0008408200187C0900004081FF5838E9FFFF90E100184BFFFF4C2C0A000A30
+S32500013760408200207CEC4A14980700007D234B7883E100007FE803A6382100204E800020BD
+S325000137802C0A0015408200183860FFFF83E100007FE803A6382100204E8000207C095800AF
+S325000137A0408200187D635B7883E100007FE803A6382100204E8000203909000191010018AD
+S325000137C07C8C4A14994400004BFFFEDC992100134BFFFF483860FFFE83E100007FE803A614
+S325000137E0382100204E8000207FE802A697E1FFE090610024808100289804000080E100308A
+S325000138007C0700004182001880810030888400007C8407747C040000408200FC7C06037850
+S3250001382090C10018808100187C040000418200683862956780C1002490C1000880810030CF
+S325000138409081000C4800011D8061002880E1002C90E1000880C1001890C1000C4BFFFE3998
+S325000138607C691B782C03FFFE4182008C2C03FFFF4182FFB48101002C7C0940004180002C4B
+S3250001388038629580480000DD808100187C0400004082FFA03862957980E1002490E10008AD
+S325000138A0480000C14BFFFFA47C0900004082001080E100187C070000408200187C030378E4
+S325000138C083E100007FE803A6382100204E8000208061002880A1003090A1000848009B1D73
+S325000138E07C03037883E100007FE803A6382100204E8000203862957E38800001908100086D
+S3250001390080C282F47CC803A64E8000217C0903784BFFFF6438C000014BFFFF087FE802A606
+S3250001392097E1FFE89061001C38C3010090C10008808100209081000C38E1002038E7000425
+S3250001394090E10010480007F18081001C7C64185083E100007FE803A6382100184E80002067
+S325000139607FE802A697E1FEE09061012480E282F47C070000408200187C03037883E1000032
+S325000139807FE803A6382101204E8000203861002038C1002038C6010090C1000881010124D7
+S325000139A09101000C38C1012438C6000490C1001048000785390100207C881850386100208E
+S325000139C09081001C90810008810282F47D0803A64E8000218061001C83E100007FE803A613
+S325000139E0382101204E8000207FE802A697E1FEE0812282F4906101247C0900004182007408
+S32500013A003862958F38800007908100087D2803A64E8000213861002038A1002038A501003C
+S32500013A2090A1000880E1012490E1000C38A1012438A5000490A10010480006FD38E100209F
+S32500013A407D071850386100209101000880E282F47CE803A64E8000213862959738800001CD
+S32500013A609081000880C282F47CC803A64E8000214BFFC7154BFFC70D4BFFFFFC7FE802A6FA
+S32500013A8097E1FFE0808280148124002038C0000190C90030808908403FE0FFFF63FFFFFE1E
+S32500013AA07FE4203990890840B0090968B0090964B0090960B0090962B0090966B009095210
+S32500013AC0B0090950B0090954B009095690090ABC90090AB8B0090AC29121001C90090AC42B
+S32500013AE04BFFC6998101001C3CA0000060A58001B0A809C080C1001CA0C609C070C6000132
+S32500013B00418200184BFFC67580C1001CA0C609C070C600014082FFF0386281E038E2B3C83A
+S32500013B2090E10008388004009081000C480065E9386281E03CC0FA2060C6240090C10008E2
+S32500013B40390004009101000C480065F183E100007FE803A6382100204E8000207FE802A6FB
+S32500013B6097E1FFE89061001C4BFFC639906100108102801481080020910100144BFFC5FD16
+S32500013B8081010014A10809C071080001418200184BFFC5E981010014A10809C07108000147
+S32500013BA04082FFF08081001C5484402E80A1002054A520367C842B7880C1002454C6083CF4
+S32500013BC07C8433786084000180A10014B08509C04BFFC5A980E10014A0E709C070E7000146
+S32500013BE0418200184BFFC59580E10014A0E709C070E700014082FFF0806100104BFFC5C1B0
+S32500013C0083E100007FE803A6382100184E8000203821FFE85465183838A5FFF8810100200B
+S32500013C20710800075508183880E1002470E700077D083B787D0B283080E280148127002097
+S32500013C4080E90AEC390000FF7D0828307D0840F87CE740387CE75B7890E90AEC382100183B
+S32500013C604E8000207FE802A697E1FFE080E2801480E7002039270A209121001C80E90000AB
+S32500013C8070E70030418200543860000538C0000490C100089001000C4BFFFEC53860000744
+S32500013CA039000004910100089001000C4BFFFEB1386000014BFFEDC980A1001C80E5000055
+S32500013CC03FE0FFFF63FFFFCF7FE7383990E50000386000044BFFCA9983E100007FE803A687
+S32500013CE0382100204E8000207FE802A697E1FFE07C681B78386281E0900100085507183839
+S32500013D0090E1000C90010010480065997C681B789061001C7C030000408200103862833B0B
+S32500013D204BFFFCC98101001C7D03437883E100007FE803A6382100204E8000207FE802A6AA
+S32500013D4097E1FFE89061001C7C030000418200384BFFC4298121001C386281E07528E00009
+S32500013D603CA020007C0828004182002C7D274B7890E1000880810020548418389081000C5F
+S32500013D80480063B983E100007FE803A6382100184E8000203FE0FFFF63FFFFFF7FE7483981
+S32500013DA04BFFFFD07FE802A697E1FFE83E0000006210900081E1002481C100207C6A1B78D4
+S32500013DC091C3000C9061001C80E300007C070000408200247DC373784BFFFF113E000000E0
+S32500013DE06210900081E1002481C100208141001C906A000080C1002838C6000F3FE0FFFF67
+S32500013E0063FFFFF07FED3039808A00047C0400004082002C91A100287C6E69D64800518558
+S32500013E203E0000006210900081E1002481C1002081A100288141001C906A000480CA0000E3
+S32500013E407C060000418201A880AA00047C0500004182019C80AA000474A5E0003CC020001B
+S32500013E607C05300041820174808A00047C8C23787C0B03787C0B700040800044556418389B
+S32500013E8080EA00007C843A14B004000255661838808A00007CC622149186000455651838FB
+S32500013EA0810A00007CA54214B20500007D8C6A14396B00017C0B70004180FFC4556818388E
+S32500013EC080CA00007D083214A0A8FFF860A52000B0A8FFF8900A000891EA0020808A0010BC
+S32500013EE07C040000408200187DE37B784BFFFDFD81E100248141001C906A0010810A0014BD
+S32500013F007C0800004082001855E3103A4800509581E100248141001C906A001480EA0010A1
+S32500013F207C070000418200A080CA00147C060000418200947C0B03787C0B7800408000504C
+S32500013F405567103A80AA00147CE72A14900700005564183880EA00107C843A149004000475
+S32500013F6055661838808A00107CC62214B00600025568183880CA00107D083214B0080000FB
+S32500013F80396B00017C0B78004180FFB855651838810A00107CA54214A0E5FFF860E72000FF
+S32500013FA0B0E5FFF8900A0018900A001C900A00247C03037883E100007FE803A63821001869
+S32500013FC04E8000203860FFFF83E100007FE803A6382100184E800020808A00043FE0FFFF58
+S32500013FE063FFFFFF7FE420394BFFFE843860FFFF83E100007FE803A6382100184E80002069
+S325000140003821FFF0818282D0816100187C6A1B782C0B00094082005C7D8B6378388C00087C
+S325000140203FE0FFFF63FFFFF87FEC20397D675B78396B0001918282D07C07600040800014C7
+S32500014040808A0000810A00047C0440404180000C382100104E80002080EA000039270001D1
+S32500014060912A000038800020988700004BFFFFC080A30000808300047C0520404080001C97
+S325000140808103000039280001912300009968000038AC000190A282D02C0B000A408200080A
+S325000140A0900282D0382100104E800020814283E07C6907747D26077470C6007F7CC90774A5
+S325000140C07D24077438C285A87C843214888400007C8407747C0400004082002C2C0A001E07
+S325000140E04180000C386000014E8000207D26077438E285A87CC63A14390A0001910283E036
+S32500014100994600007D250774390285A87CA5421488A500007CA5077454A5103A38C284D063
+S325000141207CA5321480E1000890E500007C0303784E8000207FE802A697E1FFC890610018F4
+S3250001414080E1004090E1001C80810048908100208141004438EA000190E10044894A0000FF
+S325000141607D4A07742C0A0025418200487C0A00004082003080A1001880E1001C7C05384069
+S325000141804080000C80810018980400008061001883E100007FE803A6382100384E800020AB
+S325000141A038610018914100084BFFFE594BFFFFA49001002438A0FFFF90A100289001002C3E
+S325000141C03967000191610044894700007D4A07747C0C03782C0A002D4082001C39800001F1
+S325000141E07D6A5B78396B000191610044894A00007D4A07742C0A00304180000C2C0A00396C
+S325000142004081010C7C0C00004182001080A100247D050050910100242C0A002E41820084F6
+S325000142207C0A00004082000C38CBFFFF90C100443861001838A285A87146007F7CA5321438
+S3250001424088A500007CA5077454A5103A38C284D07CA5321480A500007CA803A64E800021B5
+S325000142607C0300004080002C7CA300508081002C7C852B7890A1002C81410044396A000185
+S3250001428091610044894A00007D4A07744BFFFF9480E100207CE71A1490E100204BFFFEB450
+S325000142A07D6A5B78396B000191610044894A00007D4A07742C0A00304180FF682C0A003950
+S325000142C0408100084BFFFF5C808100287C040000408000089001002880C1002854C5103A73
+S325000142E07CC62A1454C6083C7CC6521438C6FFD090C100287D6A5B78396B00019161004456
+S32500014300894A00007D4A07744BFFFFAC810100245507103A7D083A145508083C7D085214E1
+S325000143203908FFD0910100247D6A5B78396B000191610044894A00007D4A07744BFFFEB806
+S325000143407FE802A697E1FFE0906100244800907D7C6A1B789061001C80E1002C7C070000F0
+S325000143604180003C9141001C80C1002C7C0A30004080002C80610028388000209081000842
+S325000143804BFFFC8180C1001C394600019141001C80C1002C7C0A30004180FFDC81610024BF
+S325000143A07D665B78396B00019161001488C600007CC607747C0600004182003480E1003080
+S325000143C07C0700004182FFDC8061002890C100084BFFFC31816100148141001C8101003056
+S325000143E03908FFFF910100304BFFFFB880C1002C7C0600004080004880A1002C7D0500509E
+S325000144009101002C9141001C80A1002C7C0A28004080002C80610028390000209101000806
+S325000144204BFFFBE180A1001C394500019141001C80A1002C7C0A28004180FFDC83E10000AA
+S325000144407FE803A6382100204E8000207FE802A697E1FFA881C282E881A100607C6C1B7806
+S325000144607C0F037880C3001470C600072C0600044181015C418201442C060001418201281F
+S325000144802C0600024182010080AC00088145000038E0000490E1002880CC001470C60004D4
+S325000144A04082000C7C0A0000418000D0980100573960001C7FEA6B967FFF69D67CFF505029
+S325000144C0392700302C09003940810014392900277C0E0000418200083929FFE038C1003AB0
+S325000144E07CC65A14992600002C0B0002408000547C0F0000418200183881003A396BFFFFFE
+S325000145007C845A1438A0002D98A400003861003A7C635A149181000880EC000C90E1000CB6
+S3250001452038E0FFFF90E100104BFFFE198061002883E100007FE803A6382100584E80002060
+S325000145407D4A6B96810C00107C0800004180001880EC00103900001E7CE740507C0B38000D
+S32500014560408000107C0A0000418100084BFFFF84396BFFFF4BFFFF407D4A005039E00001EB
+S325000145804BFFFF2C80AC000880A500007CA907347D2407347C8A2378388000049081002874
+S325000145A04BFFFEF8808C00088144000038C0000490C100284BFFFEE4810C000881480000DC
+S325000145C038A0000490A100284BFFFED02C060005418200302C060006418200084BFFFEAC66
+S325000145E080AC000880A500007CA907345524043E7C8A237838800004908100284BFFFE9CC6
+S3250001460080E300088147000038800004908100284BFFFE887FE802A697E1FFE87C671B78B7
+S32500014620386280B890E100089001000C3880FFFF908100104BFFFD0D7C03037883E1000002
+S325000146407FE803A6382100184E8000207FE802A697E1FFE07C681B7880E3000880E7000035
+S3250001466098E1001E9801001F3861001E910100088088000C9081000C3880FFFF908100108B
+S325000146804BFFFCC13860000483E100007FE803A6382100204E8000207FE802A697E1FFF01F
+S325000146A03900000A910100084BFFFDA583E100007FE803A6382100104E8000203860FFFECA
+S325000146C04E8000203860FFFF4E8000207FE802A697E1FFF038E0000890E100084BFFFD719A
+S325000146E083E100007FE803A6382100104E8000207FE802A697E1FFE87C671B788063000819
+S325000147008063000090E100088107000C9101000C81070010910100104BFFFC2938600004BF
+S3250001472083E100007FE803A6382100184E8000203860FFFC4E8000207FE802A697E1FFF0A8
+S3250001474038A0001090A100084BFFFD0583E100007FE803A6382100104E8000207FE802A60B
+S3250001476097E1FFE839000001910282E838C0001090C100084BFFFCD9900282E883E10000BC
+S325000147807FE803A6382100184E8000207FE802A697E1FFF038E0002590E100084BFFF865D0
+S325000147A07C03037883E100007FE803A6382100104E8000207FE802A697E1FFD89061002CB2
+S325000147C03862889880A1003090A100084BFFF19581A100308181002C3942A1F83902A1F856
+S325000147E0390801407C0A40404080003080CA00047C0D30004082001080EA000C7C0C38002B
+S32500014800418201B4394A00143902A1F8390801407C0A40404180FFD83962A1F838C2A1F8C7
+S325000148203946001438C2A1F838C601407C0A30404080002C808A0000810B00007C044000D4
+S32500014840418100087D4B5378394A001438C2A1F838C601407C0A30404180FFDC7D6A5B783F
+S3250001486080CC001480EC00107D6639D69141002480CA00087C0600004182011480AA001087
+S325000148807C055800418001089161001C916A0010386288BD80AC000C7CAD2A14810C00103A
+S325000148A07CA541D690A100084BFFF0B98141002C806A000080EA000C812100307CE93A14BA
+S325000148C080AA00107CE729D690E1000880AA00087CA803A64E8000218141002C7C03000061
+S325000148E040800020386288CF4BFFF0797C03037883E100007FE803A6382100284E80002050
+S32500014900806A00008101002481080008910100088101001C9101000C80CA00047CC803A65E
+S325000149204E800021816100308141002480A1001C7C03280041820020386288E14BFFF02560
+S325000149407C03037883E100007FE803A6382100284E8000208082801480840000908A0000BF
+S3250001496080C1002C90CA000C916A0004386288F3916100084BFFEFED8061002483E10000C0
+S325000149807FE803A6382100284E8000207D635B789161001C90010008480045818161001C2B
+S325000149A08141002481A100308181002C906A00084BFFFED89141002480A2801480A5000097
+S325000149C090AA0000386288A791A100084BFFEF958061002483E100007FE803A638210028CB
+S325000149E04E8000207FE802A697E1FFD89061002C3862890580E1003090E100084BFFEF6577
+S32500014A00816100308141002C2C0B0002418001AC80EA00347C0B3800408001A0810A003867
+S32500014A202C08000C418201802C080010418200183860FFFF83E100007FE803A63821002841
+S32500014A404E800020556B083C810A0030812A00107D0849D6916100247C0B40404180001451
+S32500014A60386289114BFFEF85816100248141002C808A001080EA00147C8439D67C8B2396E2
+S32500014A80810A00147C8441D680EA003C7C843A1480EA0010810A00147CE741D67FEB3B9697
+S32500014AA07FFF39D67CFF585090E100187D43537890810020908100084BFFFCFD8181002C70
+S32500014AC07C6A1B7880C3000881010018396800017CC6421488C6000090C1002480CC001018
+S32500014AE080EC00147CC639D67C0B3000418000287D836378808C001480A100207C852214CB
+S32500014B00908100084BFFFCB18181002C7C6A1B787C0B0378810A00087D085A1489080000BE
+S32500014B205508402E808100247C8A437880EC00382C07000C4082002080C1003070C6000150
+S32500014B404182005C554AE13E280A0FF841800008614AF0003CE0000060E7FFF87C0A38407C
+S32500014B60408000347D4453783862891880A1003090A10008908100249081000C4BFFEDE57B
+S32500014B808061002483E100007FE803A6382100284E8000203880FFFF4BFFFFD0714A0FFF8E
+S32500014BA04BFFFFA85567083C7D0B3A14392000027D684BD64BFFFE943860FFFF83E10000F0
+S32500014BC07FE803A6382100284E8000207FE802A697E1FFD87C691B7881030000910100243F
+S32500014BE03862892A9121002C390900049101000880C1003090C1000C4BFFED6981A1002CE7
+S32500014C008181003081610024808D00147C04000040820070810B00107D0C41D680CB0014E7
+S32500014C207D0831D680AB002454A528347C082800418000183860FFFF83E100007FE803A6AE
+S32500014C40382100284E800020808B004080AB00147CAC29D67C842A143862893D9181000875
+S32500014C60908100209081000C4BFFECF98061002083E100007FE803A6382100284E800020CC
+S32500014C80808D001C7C0C20004180001080AD00187C050000408200A87C0A0378812D001478
+S32500014CA0914100207C0A6000418200507D635B78912100084BFFFD3181A1002C818100309D
+S32500014CC0816100247C691B787C030000408000183860FFFF83E100007FE803A6382100286D
+S32500014CE04E80002080C1002039460001914100207C0A60004082FFB8914D001C912D0018BD
+S32500014D0038E9FFFE80CB00147CE731D680AB00447CE53A14386289509181000890E1002069
+S32500014D2090E1000C4BFFEC3D8061002083E100007FE803A6382100284E800020814D001CAE
+S32500014D40812D00184BFFFF5C7FE802A697E1FFC87C6A1B788903000F7108001040820050E4
+S32500014D60808A0020810A00107C044000418000187C03037883E100007FE803A638210038CF
+S32500014D804E80002080EA0020810100447CE74214808A00107C07200040810014810A0010E8
+S32500014DA0812A00207D09405091010044810100409101001C7C0B03789161003080E10044FC
+S32500014DC07C0B38004080010C7D43537880CA00209141003C80EA000080E700187CC63BD601
+S32500014DE090C100084BFFFDE97C6A1B787C030000408000183860FFFF83E100007FE803A649
+S32500014E00382100384E8000208061003C80630000914100084BFFF9A18181003C7C03000091
+S32500014E20408200183860FFFF83E100007FE803A6382100384E80002080CC002080EC000030
+S32500014E4080E700187FE63BD67FFF39D67D5F3050810300087DA8521480C1004480810030A0
+S32500014E607D64305080EC000080E700187CEA38507C0B380040810010810C00008108001833
+S32500014E807D6A40508061001C91A100089161002C9161000C480080CD8161002C8141003CA0
+S32500014EA080E1001C7CA75A1490A1001C808A00207CE45A1490EA002080E100307D675A141B
+S32500014EC09161003080E100447C0B38004180FEFC7D635B7883E100007FE803A638210038D2
+S32500014EE04E8000207FE802A697E1FFC08883000F7084001040820020386289634BFFEA6558
+S32500014F003860FFFF83E100007FE803A6382100404E8000209061004480C1004890C10008E2
+S32500014F2048000EA981210044900900207D234B78388100209081000838E0002090E1000CC2
+S32500014F404BFFFE092C030020408201103862897B388100209081000838C1002038C6000828
+S32500014F6090C1000C4BFFE9FD806100443863000438A1002090A1000838E0000890E1000C0A
+S32500014F8048008549812100447C030000418200084BFFFF9C3869000C38C1002038C6000813
+S32500014FA090C10008390000039101000C4800851D812100447C030000418200084BFFFF70E4
+S32500014FC088A1002B70A500084182002838628995388100209081000838C1002038C60008A5
+S32500014FE090C1000C4BFFE97D812100444BFFFF4088A1002B98A9000F88E1003B54E7402E3D
+S325000150008901003A7CE7437890E900148881003F5484402E88A1003E7C842B785484801E0C
+S3250001502088A1003D54A5402E88C1003C7CA533787C842B7890890010900900189009001C19
+S32500015040900900203860000183E100007FE803A6382100404E8000207C03000041800018A4
+S325000150607C03037883E100007FE803A6382100404E8000203860FFFF83E100007FE803A62A
+S32500015080382100404E8000207FE802A697E1FFD07C6D1B7880E1003890E3000C38C002009E
+S325000150A090C3001038800001908300147C0903787DA36B7891A100349121001C91210008B5
+S325000150C04BFFF6F581A100347C6A1B787C03000040820020386289AD4BFFE8893860FFFF43
+S325000150E083E100007FE803A6382100304E80002081030008890801FE2C08005540820380D4
+S3250001510080C3000888C601FF2C0600AA408203709003000C8123000880C1003C7C06000094
+S3250001512041820010890900152C0800F8408201E8812A000888A900002C0500E9418200381E
+S3250001514088C900002C0600EB4082001088E900022C07009041820020386289CD4BFFE805C8
+S325000151603860FFFF83E100007FE803A6382100304E8000207D234B789121002C4800031DFE
+S325000151808141002C81210034888A000C5484402E88CA000B7C8433789089001088EA000D30
+S325000151A090E900148089001080A900147C8429D69089001888CA000F54C6402E890A000E4B
+S325000151C07CC6437890C9001C888A00109089002088CA001254C6402E890A00117CC643786E
+S325000151E090C9002488EA001454E7402E888A00137CE7237890E90028810900287C08000002
+S325000152004082003088EA002354E7402E88AA00227CE72B7854E7801E88CA002154C6402E29
+S32500015220890A00207CC643787CE7337890E90028888A00159089002C88CA001754C6402EAB
+S32500015240890A00167CC6437890C900308089001C9089003C8089002080A900307C8429D61D
+S3250001526080A9003C7C8522149089004080C9002454C6283480E900107CC63A143946FFFFC9
+S3250001528080C900107D4A33D680C900407CC6521490C900448089002880A900447C85205001
+S325000152A080A900147C842BD6388400029089003480C900342C060FF74080005038E0000CB5
+S325000152C090E9003839000002910900489129004C9009006090090068900900649009006CF7
+S325000152E038A0001098A9005B81090024550828349109005C7C03037883E100007FE803A658
+S32500015300382100304E80002038A0001090A900384BFFFFB4808A0008392401BE3980FFFFD4
+S325000153207C0B03782C0B000440800064890900042C0800544082000C3920003F4BFFFD74C6
+S3250001534088A900042C0500014182001088C900042C0600044082011889090000710800801B
+S32500015360418200A88889000B5484402E88E9000A7C843B785484801E890900095508402E4F
+S3250001538088A900087D082B787C8C43782C0B0004408200183900FFFF7C0C40004082000C00
+S325000153A0900A000C4BFFFD8C80C1001C7CC6621490CD000C7DA36B78900100084BFFF3F91D
+S325000153C07C6A1B787C0300004182001480E3000888E701FE2C070055418200183860FFFF25
+S325000153E083E100007FE803A6382100304E80002080A3000888A501FF2C0500AA4082FFE0E7
+S32500015400900A000C4BFFFD2C88E9000B54E7402E88A9000A7CE72B7854E7801E88C90009D3
+S3250001542054C6402E890900087CC643787CE733787C0760404080002C88C9000B54C6402E45
+S325000154408889000A7CC6237854C6801E88A9000954A5402E88E900087CA53B787CCC2B78BC
+S32500015460396B0001392900104BFFFEBC88E900042C0700064082FFEC4BFFFEE0386289C4A0
+S325000154804BFFE4E13860FFFF83E100007FE803A6382100304E8000207FE802A697E1FFE807
+S325000154A07C691B78386289E1888900009081000888C9000190C1000C9121001C890900022E
+S325000154C0910100104BFFE49D38628A0180A1001C38A5000390A100084BFFE4898121001C68
+S325000154E038628A138909000C5508402E88A9000B7D082B78910100084BFFE46938628A212B
+S3250001550080E1001C88E7000D90E100084BFFE4558121001C38628A308889000F5484402E17
+S3250001552088C9000E7C843378908100084BFFE43538628A3C8101001C8908001091010008A5
+S325000155404BFFE4218121001C38628A4788A9001254A5402E88E900117CA53B7890A1000893
+S325000155604BFFE4018121001C38628A55888900145484402E88C900137C843378908100082B
+S325000155804BFFE3E138628A628101001C89080015910100084BFFE3CD8121001C38628A7640
+S325000155A088A9001754A5402E88E900167CA53B7890A100084BFFE3AD8121001C38628A8362
+S325000155C0888900195484402E88C900187C843378908100084BFFE38D8121001C38628A90FB
+S325000155E08909001B5508402E88A9001A7D082B78910100084BFFE36D8121001C38628A9C07
+S3250001560088E9001F54E7402E88A9001E7CE72B7854E7801E88C9001D54C6402E8909001C78
+S325000156207CC643787CE7337890E100084BFFE3358121001C38628AA988A9002354A5402E37
+S32500015640890900227CA5437854A5801E888900215484402E88C900207C8433787CA52378CC
+S3250001566090A100084BFFE2FD38628AB98101001C89080024910100084BFFE2E938628AC6F8
+S3250001568080A1001C88A5002590A100084BFFE2D538628ADA80E1001C88E7002690E10008B1
+S325000156A04BFFE2C18121001C38628AEC8889002A5484402E88E900297C843B785484801EE4
+S325000156C0890900285508402E88A900277D082B787C844378908100084BFFE28938628AFC15
+S325000156E080E1001C38E7002B90E100084BFFE27583E100007FE803A6382100184E800020EF
+S325000157007FE802A697E1FFE8816100207C691B7888C900007CC607742C06002F4082001851
+S325000157203929000188C900007CC607742C06002F4182FFF088A900007CA507747C05000090
+S32500015740418200C088C900007CC607742C060020418200B07C0A037888A900007CA507741E
+S325000157607C0500004182001488C900007CC607742C06002F4082001C980B00007D234B7877
+S3250001578083E100007FE803A6382100184E80002088E900007CE707742C0700204082001CAF
+S325000157A0980B00007D234B7883E100007FE803A6382100184E8000202C0A001C40820020D5
+S325000157C038628B0E4BFFE19D7C03037883E100007FE803A6382100184E8000207D655B7845
+S325000157E0396B00017D264B783929000188C600007CC6077498C50000394A00014BFFFF5CA3
+S325000158007C03037883E100007FE803A6382100184E8000207FE802A697E1FFD080E1003CC1
+S325000158207C641B7838C0000380A4004C8104005090A7000080A400549107000490A7000824
+S3250001584038C6FFFF3884000C38E7000C7C0600004181FFD88061003838A1001490A10008F8
+S325000158604BFFFEA1906100387C030000418200508061003C38A1001490A100084BFFF66991
+S325000158802C03FFFF418200247C030000418200084BFFFFC47C03037883E100007FE803A628
+S325000158A0382100304E8000203860FFFF83E100007FE803A6382100304E8000203860000150
+S325000158C083E100007FE803A6382100304E8000207FE802A697E1FFA880E1006090E100086E
+S325000158E038C1003490C1000C4BFFFF2D814100602C03FFFF418204207C030000418203F82E
+S325000159002C030001418203B43860002090010008480036097C6B1B7838A0002038610034BF
+S3250001592090A1003090A10008916100289161000C4800040581410028810100307C03400002
+S3250001594041820020806282CC4BFFE0193860FFFF83E100007FE803A6382100584E80002041
+S3250001596088CA000054C6402E888A00017CC6237854C6801E88AA000254A5402E88EA00038E
+S325000159807CA53B787CC62B782C0606EB4182004C38628B7C890A00005508402E88CA0001C3
+S325000159A07D0833785508801E88EA000254E7402E888A00037CE723787D083B7891010008B3
+S325000159C04BFFDFA13860FFFF83E100007FE803A6382100584E80002088EA001454E7402E1E
+S325000159E088AA00157CE72B7854E7801E890A00165508402E892A00177D084B787CE74378D6
+S32500015A0074E7E0003C8020007C0720004182027488CA001454C6402E88EA00157CC63B7822
+S32500015A2054C6801E890A00165508402E88AA00177D082B787CC6437890C1002C890A0004B1
+S32500015A405508402E88CA00057D0833785508801E88EA000654E7402E888A00077CE72378BA
+S32500015A607D083B7838628BA791010030910100084BFFDEF13861003480A1003090A100084F
+S32500015A808101002C9101000C480002AD81610030814100287C03580041820020806282CCD6
+S32500015AA04BFFDEC13860FFFF83E100007FE803A6382100584E80002080E1002C7C8B3A146B
+S32500015AC038840FFF3FE0FFFF63FFF0007FE420399081002C88AA000854A5402E890A000950
+S32500015AE07CA5437854A5801E888A000A5484402E88CA000B7C8433787CA5237838628BAB36
+S32500015B0090A1003090A100084BFFDE593861003480E1003090E1000880A1002C90A1000C02
+S32500015B204800021581410028810100307C03400041820020806282CC4BFFDE293860FFFFAA
+S32500015B4083E100007FE803A6382100584E80002038628BAF88CA000C54C6402E888A000D52
+S32500015B607CC6237854C6801E88AA000E54A5402E88EA000F7CA53B787CC62B7890C100084F
+S32500015B80888A00145484402E88EA00157C843B785484801E890A00165508402E88AA001725
+S32500015BA07D082B787C8443789081000C4BFFDDB581410028890A00145508402E88CA00153F
+S32500015BC07D0833785508801E892A00165529402E888A00177D2923787D084B787508E000CF
+S32500015BE03CA020007C0828004182004888EA001454E7402E890A00157CE7437854E7801E1D
+S32500015C00888A00165484402E88CA00177C8433787CE723787CE803A64E8000217C03037807
+S32500015C2083E100007FE803A6382100584E80002088EA001454E7402E888A00157CE72378F6
+S32500015C4054E7801E88AA001654A5402E890A00177CA543787CE72B783FE0FFFF63FFFFFFAC
+S32500015C607FE738397CE803A64E8000217C03037883E100007FE803A6382100584E8000203D
+S32500015C8088CA001454C6402E890A00157CC6437854C6801E888A00165484402E88EA0017BB
+S32500015CA07C843B787CC623783FE0FFFF63FFFFFF7FE630394BFFFD8438628B4A38A10034BB
+S32500015CC038A5000490A1000838E1003438E7000C90E1000C888100439081001080810048F8
+S32500015CE09081001480E1004490E100184BFFDC754BFFFC1838628B3C914100084BFFDC658B
+S32500015D003860FFFF83E100007FE803A6382100584E80002038628B27914100084BFFDC4542
+S32500015D203860FFFF83E100007FE803A6382100584E8000207FE802A697E1FFD88161003043
+S32500015D409061002C80E1003490E100247C0A03787C0A580040800044392020007C8A5850EB
+S32500015D607C044800408000087D2A58508061002C808100249141001C7C845214908100089E
+S32500015D809121000C4BFFEFC58141001C906100207C030000418100187D43537883E1000009
+S32500015DA07FE803A6382100284E80002038628BC44BFFDBB1816100308081002080C1001C0E
+S32500015DC07D4622144BFFFF8C7FE802A697E1FFE0812100287C6B1B783943000488E9000053
+S32500015DE07CE707747C070000418200147CCB505038C6FFFC2C060008418001047CAB5050BD
+S32500015E0038A5FFFC2C050008408000247D455378394A000138C0002098C500007CAB505039
+S32500015E2038A5FFFC2C0500084180FFE4394B000C88A900007CA507747C05000041820014F1
+S32500015E407C8B50503884FFF42C0400034180005C7C8B50503884FFF42C0400034080002428
+S32500015E607D445378394A000138A0002098A400007C8B50503884FFF42C0400034180FFE4AA
+S32500015E8038628BC638AB000490A10008390B000C9101000C4BFFDACD83E100007FE803A69D
+S32500015EA0382100204E800020888900007C8407742C0400614180001488A900007CA50774B5
+S32500015EC02C05007A4081001C888900007C840774988A000039290001394A00014BFFFF5401
+S32500015EE0890900007D0807743908FFE0990A000039290001394A00014BFFFF3888C900008D
+S32500015F007CC607742C06002E4082000C392900014BFFFEEC88A900007CA507742C05006199
+S32500015F204180001488C900007CC607742C06007A4081001C88A900007CA5077498AA0000DF
+S32500015F4039290001394A00014BFFFE94888900007C8407743884FFE0988A000039290001CB
+S32500015F60394A00014BFFFE787FE802A697E1FFC8900100287C0A03782C0A00044080006074
+S32500015F8091410030554818387C8A4214548428347C88205038A2D7D07C642A149061003443
+S32500015FA09001000838E0011890E1000C48006D818061003080C1003490C100084BFFA6CDC1
+S32500015FC0816100347C0300004181002880810030394400012C0A00044180FFA880610028E1
+S32500015FE083E100007FE803A6382100384E8000207C0A03785547183838C282807CE7321415
+S3250001600080E700007C0700004182FFC4914100245543183838E282807C633A1480630000FF
+S32500016020916100084800743D81610034814100247C0300004182000C394A00014BFFFFB897
+S3250001604080810030908B00EC7D635B785548183838E282807D083A14810800047D0803A6B7
+S325000160604E8000217C030000418200084BFFFF603860400038A0000190A100089001000CB0
+S325000160809001001048003E5580E10034906700F43860400038C0000190C100089001000C36
+S325000160A09001001048003E3581410034906A00F839000001910A00F03880000180C10030A6
+S325000160C07C843030810100287D0423789081002838629A1180CA00EC90C100089141000CA8
+S325000160E0808A001C90810010808A0020908100144BFFD87181410034808A00247C040000CC
+S325000161004182002C38629A31808A00247484E0003D2020007C04480041820098810A0024CF
+S32500016120910100084BFFD83D8141003480CA00287C0600004182001438629A3E80AA0028DA
+S3250001614090A100084BFFD81D38629A4B4BFFD8157C0A03782C0A00064080003038629A4D5C
+S325000161609141002C80C100347CAA321488A5002C90A100084BFFD7ED80A1002C39450001CD
+S325000161802C0A00064180FFD838629A554BFFD7D54BFFAEB181410034806A0020810A00D0A1
+S325000161A0910100089141000C48004AC94BFFFE20810A00243FE0FFFF63FFFFFF7FE8403991
+S325000161C04BFFFF607FE802A697E1FFE82C03000440800080546618387CA3321454A528346A
+S325000161E07CA6285038C2D7D07CA5321480A500F07C0500004182005C546718387D033A1468
+S32500016200550828347D0740503922D7D07D484A1480AA00F02C0500014082002438C0000259
+S3250001622090CA00F07D43537891410014810A00BC7D0803A64E800021814100147D435378D7
+S3250001624083E100007FE803A6382100184E8000207C03037883E100007FE803A63821001885
+S325000162604E8000207FE802A697E1FFE84BFFFF597C030000408200187C03037883E1000062
+S325000162807FE803A6382100184E8000203863002C83E100007FE803A6382100184E800020EE
+S325000162A07FE802A697E1FFD84BFFFF1D906100207C030000408200187C03037883E100004B
+S325000162C07FE803A6382100284E80002080828014808400009081001880610020806300F49D
+S325000162E048003C357C6A1B787C0300004082005080A2801480A5000080E100187CA72850E5
+S3250001630054A4083C7CA5221454A518385484482C7CA5205038C000327CA5339680C1003434
+S325000163207C0530404180FFB47C03037883E100007FE803A6382100284E800020810300048C
+S32500016340812300007D094050806100309141001C808A000090810008910100249101000C06
+S3250001636048006C018061001C48003B118061002483E100007FE803A6382100284E800020E8
+S325000163807FE802A697E1FFE87C691B7880610020806300009121001C3889002C9081000858
+S325000163A038E0000690E1000C48007121812100207C03000041820028806900003902836826
+S325000163C09101000838A0000690A1000C480070FD812100207C030000408200288061001C24
+S325000163E0806300F49121000848003BA93860000183E100007FE803A6382100184E8000206D
+S3250001640080E100247C0700004182000C7D234B7848003A697C03037883E100007FE803A6E2
+S32500016420382100184E8000207FE802A697E1FFD89061002C4BFFFD917C030000408200184A
+S325000164407C03037883E100007FE803A6382100284E80002090610024806300F848003BC520
+S325000164602C0340004081002838629A5780A1002C90A100084BFFD4ED7C03037883E1000043
+S325000164807FE803A6382100284E800020386005F0480039919061002080630004810100302D
+S325000164A09101000880C1003490C1000C48006AB580610020806300043863000680E10024F4
+S325000164C038E7002C90E1000838A0000690A1000C48006A91812100208081003480C900044F
+S325000164E07C8622149089000480610024806300F89121000848003A9D4BFF9CA98121002432
+S325000165009061001C7D234B78810900CC7D0803A64E8000218061001C4BFF9CA53860000170
+S3250001652083E100007FE803A6382100284E8000207FE802A697E1FFF880A300EC54A7183899
+S325000165407CA53A1454A5103A3902A3387CA5421480A5000080C5000060C6003090C50000E0
+S325000165604BFF9C1983E100007FE803A6382100084E8000207FE802A697E1FFD89061002CD7
+S325000165808081002C808400EC548518387C842A145484103A38C2A3387D24321481090020E8
+S325000165A0550818389121002080C900187D08321491010018A1080000710880004082001CFF
+S325000165C08061002C806300F84800394D7C691B787C0300004082001483E100007FE803A6BD
+S325000165E0382100284E80002080A3000480C300007CA6285080610018806300049121001C73
+S32500016600810900009101000890A1002490A1000C4800695180C1001881010024B106000203
+S325000166204BFF9B5981210018A0A9000070A5200060A5DC00B0A900004BFF9B41808100205C
+S32500016640808400003D00000061088000B104000C4BFF9B298121002080C9002038C6000110
+S3250001666038E000047FE63BD67FFF39D67CDF305090C900208061001C480038018121002060
+S325000166804BFFFF1C7FE802A697E1FFC8808100409081001C80C400EC54C718387CC63A14A7
+S325000166A054C6103A3902A3387CC6421490C1002880A60000A0A5001090A100304BFF9ABDCB
+S325000166C0808100288084000081010030B10400104BFF9AA98181001C8141002881010030C8
+S325000166E0710800154182002438629BD880AC00EC90A1000880A1003090A1000C4BFFD265B1
+S325000167008181001C8141002881010030710800094082000480AA001454A5183880CA000C93
+S325000167207D65321491610024A0AB00007CA92B7870A58000408201247128003F408200C427
+S3250001674071250C002C050C00408200B8A0AB00023865FFFC90610034480036C98161002482
+S325000167607C0300004182004C9061002080630004808B000490810008808100349081000C12
+S32500016780480067E1812100208081003480C900047C862214908900048061001C9121000812
+S325000167A0390000019101000C4BFFFBD981610024B00B0002A08B0000708420006084900066
+S325000167C0B08B00004BFF99B58181001C8141002880AA001438A5000138C000207FE533D636
+S325000167E07FFF31D67CBF285090AA001480EA001454E71838810A000C7D6742144BFFFF28C1
+S32500016800712700044182001080CC010438C6000190CC01047124000241820010810C011049
+S3250001682039080001910C01107126003F4182001438629BF44BFFD12D816100244BFFFF7480
+S32500016840712808004082FF6C38629BF64BFFD115816100244BFFFF5C80E1003070E7000273
+S32500016860418200107D8363784BFFFD0D8141002880A1003070A50010418200183860000636
+S3250001688080EA000890E100089001000C4BFFD2D183E100007FE803A6382100384E80002089
+S325000168A07FE802A697E1FFE03DA0000061AD90007C6A1B78906100248103000C7C0800004E
+S325000168C04082001C386000204BFFD4213DA0000061AD900081410024906A000C80CA00101B
+S325000168E07C060000408200243C6000006063BE0090010008480026253DA0000061AD900065
+S3250001690081410024906A001080AA001074A5E0003CC020007C0530004182015C808A001046
+S325000169207C8C23787C0B03782C0B0020408000445567183880AA000C7CE72A14B0070002B4
+S325000169405564183880EA000C7C843A14918400045568183880CA000C7D083214B1A80000C3
+S32500016960398C05F0396B00012C0B00204180FFC45564183880EA000C7C843A14A0C4FFF8AE
+S3250001698060C62000B0C4FFF8900A001480CA00187C06000040820014386000044BFFD34DD1
+S325000169A081410024906A0018808A001C7C04000040820018386017C0900100084800255D86
+S325000169C081410024906A001C810A001C7508E0003D2020007C0848004182008880EA001C96
+S325000169E07CEC3B787C0B03782C0B00044080004855651838810A00187CA5421491850004F2
+S32500016A005564183880EA00187C843A14B004000255661838808A00187CC6221439005C00A6
+S32500016A20B1060000398C05F0396B00012C0B00044180FFC05567183880AA00187CE72A148F
+S32500016A40A087FFF860842000B087FFF8900A002083E100007FE803A6382100204E8000204A
+S32500016A6080EA001C3FE0FFFF63FFFFFF7FE738394BFFFF70808A00103FE0FFFF63FFFFFFE5
+S32500016A807FE420394BFFFE9C7FE802A697E1FFD080A3000454A5083C3985FFFE80A2801424
+S32500016AA08145002038A000037CAB6030A0CA09527CC75B78B0EA09527D6658F8A0AA0950B1
+S32500016AC07CA63038B0CA09507D6558F8A08A09547C852838B0AA095438E000307CEB603042
+S32500016AE07D6458F8A10A09627D042038B08A09627D6858F8A0EA09607CE84038B10A0960A2
+S32500016B00A0CA09647CC75B78B0EA0964906100348063000838E1002890E1000838810024D3
+S32500016B209081000C4BFF9BDD8061003480630004808100289081000880E1002490E1000C2F
+S32500016B404BFFD0D180A1003480A5000454A5103A38C283A87CA53214806500009061001C04
+S32500016B609001000838A000A490A1000C480061C13D8020008161001C8141003438800018B1
+S32500016B80988B000438E0001898EB000538A005F0B0AB0006810A000C7508E0007C08600009
+S32500016BA04182018480CA000CB0CB000080AA001874A5E0007C05600041820158810A0018DA
+S32500016BC0B10B00027C03037880AA000890A100089001000C4BFFCF8981A100388181003CB4
+S32500016BE08161001C38E0FFFF90EB00303CA0DEBB60A520E390AB0034900B0038900B003C39
+S32500016C00900B00403C80000060848888B08B004438E0000FB0EB004638A005EEB0AB004AEB
+S32500016C2039000040B10B004C38C005F0B0CB004E388005F0B08B0050B00B00787C0A0378AA
+S32500016C402C0A00064080003C7CEA621488E7000154E7402E7D0C5214890800007CE7437862
+S32500016C60392000027D0A4BD65508083C7D085850B0E80076394A00022C0A00064180FFCCE1
+S32500016C803900080AB10D00083CC0000060C6D555B0CD000E900D00043CC0108860C6000C9E
+S32500016CA090CD00004BFF94D580E100383C8000006084FFFFB08700104BFF94C180A1003847
+S32500016CC038E0001AB0E500144BFF94B1810280148168002081010034810800043908FFFFA1
+S32500016CE0392010007D284030808B0ABC7C87437890EB0ABC80CB0AB87CC44378908B0AB85A
+S32500016D0083E100007FE803A6382100304E800020810A00183FE0FFFF63FFFFFF7FE8403981
+S32500016D204BFFFEA080CA000C3FE0FFFF63FFFFFF7FE630394BFFFE747FE802A697E1FF7011
+S32500016D40906100943861008A9001000838A0000690A1000C48005FD93861008A8101009417
+S32500016D603908002C9101000838C0000690C1000C48006759812100947C030000408200909B
+S32500016D8038629BF84BFFCBDD3861001C39029C11910100084800666538629C1E38C1004EE8
+S32500016DA090C10008390000329101000C38C1001C90C100104BFFCA357C0300004080001854
+S32500016DC03860FFFF83E100007FE803A6382100904E800020806100943863002C3881004E88
+S32500016DE0908100084BFFC209812100947C0300004080001C88C9002C2C0600FF418200104C
+S32500016E0038629C304BFFCB5D4BFFFF8080E9001C54E7103A388280887CE7221480E70000FE
+S32500016E2080C2801480C600207D663A1480C9001C54C6103A38E280307CC63A1480C6000075
+S32500016E4038C6001090C9002080E900EC54E818387CE7421454E7103A3882A3387C672214D7
+S32500016E60916100809163000080E9001C90E3000480E9001C54E7103A390283107CE7421418
+S32500016E8080E7000090E30008906100844BFFFA158061008480A1008090A1000881010094E6
+S32500016EA03908002C9101000C4BFFFBE1812100943D00FFC261086E38910900B83CE0FFC228
+S32500016EC060E7663090E900BC3CC0FFC260C6667490C900CC3CA0FFC260A5678490A900D021
+S32500016EE07C03037883E100007FE803A6382100904E8000203821FFD08161003C82810038C5
+S32500016F00824100407C751B7838A000017CAE583038A000017CA570303A65FFFF38A0000148
+S32500016F207CAA903038A000207CAF96307D4558307E2E2850388000207DAF20507C0D000010
+S32500016F40418000787C0A03787EB06C307C0C03787C0B03787C0B7800408000247E665830D2
+S32500016F607E0630387CC660307D4A33787D8C8A147D6B72147C0B78004180FFE47C0B037820
+S32500016F807C0B90004080001C7DC758307D4738307D4A3B78396B00017C0B90004180FFEC1D
+S32500016FA07E88A3783A940004914800007DAF68507C0D00004080FF90382100304E800020CB
+S32500016FC07FE802A697E1FEF89061010C3861010C480006498141011880C101248081011C93
+S32500016FE07CC430514181001483E100007FE803A6382101084E8000208081012880E1012083
+S325000170007C8720503884FFFF908100FC80A100FC7C0500004080001483E100007FE803A649
+S32500017020382101084E80002080E1010C81A7000C808101107C87683090E1011091A100F402
+S325000170407CCB6830836A000C8081011C7C87D83090E1011C936100F8808101247C87D8307D
+S3250001706090E1012480E1010C83470008832A000880E10114934100E87CE7D1D680A1010C14
+S3250001708080A500047CE72A14808101107C842E707CE43A1454E7103A80C1010C80C60000A8
+S325000170A07EE7321492E100CC80C10120932100EC7CC6C9D6808A00047CC622148101011CD7
+S325000170C07D082E707CC8321454C6103A80AA00007EC62A1492C100D080A1011070AC001F5C
+S325000170E03900FFFF7D086430910100B0918100DC7D0C5A147108001F38A000207D08285085
+S3250001710038C0FFFF7CC840303FE0FFFF63FFFFFF7FE84039910100AC810100AC7C08000071
+S325000171204082000C38A0FFFF90A100AC80C1011C70C6001F90C100E4810101107C8B4214EF
+S325000171403884FFFF7C842E7080A101107CA52E707C8520509081010080A1010C7C0A280080
+S325000171604082005880E10120808101147C0720004080046080C100FC7CC6D1D654C6103A05
+S325000171807EF73214808100FC7C84C9D65484103A7ED6221480EA000854E7083C7F27C85036
+S325000171A0932100EC8081010C808400085484083C7F44D050934100E8808101007C040000D1
+S325000171C04082001480C100AC810100B07D06303890C100B080C1012C70C6000F90C1012C96
+S325000171E07E9B68507D85A63080C100E47E6530507C1803787C1300004080000C3B000001B1
+S325000172007E7300507C1003787C15037892A100A480A100FC7C152800418100F892E100CC6D
+S325000172207EECBB7892E100C492C100D07ECFB37881A100B091A100C07C0E03787C1800007B
+S32500017240408200107DE57B7839EF000481C500007C12037882210100922100A87C110000F9
+S325000172604180008C7C1200004182027C7E0783783A10000481670000814C00008101012CB9
+S325000172802C08000841810194418201702C08000441810110418200F87C080000418200D83B
+S325000172A02C080001418200B02C080002418200942C0800034182006C398C0004918100C48D
+S325000172C039A0FFFF91A100C02C1100014082000C81A100AC91A100C03A52FFFF3A31FFFF1F
+S325000172E0922100A87C1100004080FF7C5727103A7ED63A145747103A7EF73A143AB500015F
+S3250001730092A100A480A100FC7C1528004081FF1083E100007FE803A6382101084E80002025
+S325000173203FE0FFFF63FFFFFF7FE65A787CC652787CC668387D46327890CC00004BFFFF7C16
+S325000173407D6750387CE768387D473A7890EC00004BFFFF683FE0FFFF63FFFFFF7FE85A785E
+S325000173607D0853787D0868387D484278910C00004BFFFF483FE0FFFF63FFFFFF7FE56A7821
+S325000173807D45283890AC00004BFFFF307D6553787CA568387D452A7890AC00004BFFFF1C9C
+S325000173A02C080005418200482C080006418200302C080007418200084BFFFF003FE0FFFFE9
+S325000173C063FFFFFF7FE852787D6843787D0868387D484278910C00004BFFFEE07D67683888
+S325000173E07D473A7890EC00004BFFFED07D446A78908C00004BFFFEC43FE0FFFF63FFFFFF34
+S325000174007FE75A787CE750387CE768387D473A7890EC00004BFFFEA42C08000C41810070EF
+S32500017420418200582C080009418200342C08000A4182FE882C08000B418200084BFFFE7CA1
+S325000174403FE0FFFF63FFFFFF7FE75A787CE768387D473B7890EC00004BFFFE603FE0FFFFB5
+S3250001746063FFFFFF7FE65A787CC668387D46327890CC00004BFFFE447D6852787D08683863
+S325000174807D484278910C00004BFFFE302C08000D418200342C08000E4182001C2C08000FB5
+S325000174A0418200084BFFFE147D476B7890EC00004BFFFE087D6668387D46337890CC0000DE
+S325000174C04BFFFDF87D6750383FE0FFFF63FFFFFF7FE73A787CE768387D473A7890EC000070
+S325000174E04BFFFDD8930100D47C180000418200AC38E000207CF338507DC738307DE57B78CB
+S3250001750039EF000491E100C881C5000091C100BC926100D87DC89C307CEB437838E0000193
+S325000175207CF2A0309241001C2C1400014180FD4C7D635B7838A1002490A100089361000CE3
+S32500017540928100F0928100104BFFF9AD836100F8834100E8832100EC830100D482E100CC6F
+S3250001756082C100D082A100A4828100F0826100D88241001C822100A881E100C881C100BC2A
+S3250001758081A100C0818100C4390100243A080004816800004BFFFCE47DCB98307DE77B781E
+S325000175A039EF000491E100C881C7000091C100BC926100D87C1300004182FF6438E0002050
+S325000175C07CF338507DC73C307D6B3B784BFFFF5080C10120810101147C0640004082FBDC75
+S325000175E080A1011C80E101107C053800418000084BFFFBC84800600181A100F4836100F8AA
+S32500017600834100E8832100EC818100DC82E100CC82C100D04BFFFBA43821FFE87C691B7866
+S3250001762080E30018810300107D68385080E3001C810300147D48385080E3000480C30000B9
+S3250001764080C600207C0730004080003080E9000080E70020808900047CE43850810900109B
+S325000176607CC83A1490C9001080A900047D053A14910900047D6758508109000880E90000E6
+S3250001768080E700247C08380040800030810900008108002480A900087D0540508089001415
+S325000176A07CE4421490E9001480C900087C864214908900087D485050808900047C845A14D6
+S325000176C080C9000080C600287C0430004081002480E900047CEB3A1480A9000080A50028BF
+S325000176E07CE53850810900187CE7405090E9001880C900087CC65214810900008108002C3C
+S325000177007C06400040810024808900087C8A221480E9000080E7002C7C87205080A9001CBA
+S325000177207C8428509089001C8109001080E9000C80E700207C0838004080002C8109000CC1
+S325000177408108002080A900107D054050808900047CE4421490E9000480C900107C8642143D
+S3250001776090890010808900148109000C810800247C0440004080002C8089000C8084002490
+S3250001778080C900147C86205080A900087D0522149109000880E900147CA7221490A9001465
+S325000177A080A900188089000C808400287C0520004081001080E9000C80E7002890E9001839
+S325000177C08089001C8109000C8108002C7C0440004081001080C9000C80C6002C90C9001C65
+S325000177E0382100184E8000203821FFF0814100187C691B787C070378394AFFFF7C0A000084
+S32500017800418000207D244B7839290001888400007CE72214394AFFFF7C0A00004080FFE866
+S325000178207CE33B78382100104E80002081210008390227107C0940404081000C7C0918400D
+S325000178404180000C7C0303784E800020386000014E8000207FE802A697E1FFE080C3000438
+S3250001786038A0FFFF7C0628004182001480C300043CA000047C062840418000187C030378C6
+S3250001788083E100007FE803A6382100204E80002088C3000B2C0600FF4182FFE480E3000472
+S325000178A0810282F87D683A14906100249161001C916100084BFFFF79816100247C0300002D
+S325000178C0408200187C03037883E100007FE803A6382100204E80002088AB000854A5402E50
+S325000178E0890B00097CA5437854A5402E888B000A7CAA23783D0000FF6108FFFF7C0A40005A
+S32500017900408200087C0A03787C0A0000408000187C03037883E100007FE803A63821002050
+S325000179204E8000207C0A0000408100307D635B78914100188121001C7CAA4A1438A5FFFF21
+S3250001794090A100084BFFFEE981610024814100187C0300004182007C80CB000038A0FFFFF7
+S325000179607C062800418200288061001C91410018914100084BFFFE758141001880E100248E
+S3250001798080E700007C0338004082002C80A1002880E1001C90E500008081002C9144000097
+S325000179A03860000183E100007FE803A6382100204E80002038628CD04BFFBFA97C030378AA
+S325000179C083E100007FE803A6382100204E8000207C03037883E100007FE803A638210020DE
+S325000179E04E8000207FE802A697E1FFB8900282F890028300900282FC386100203881003879
+S32500017A009081000838C1003490C1000C4BFF8C157C0300004080002038628CE54BFFBF4519
+S32500017A207C03037883E100007FE803A6382100484E80002081010034910282FC80A1003822
+S32500017A4090A282F880E282F83CE7000490E28300900283049002830880A282F83FE0000387
+S32500017A6063FFFFF07D3F2A149121003C3869000C390282F09101000838A0000490A1000CB9
+S32500017A8048005A497C030000408200A080E1003C88E7000B2C070002408200248061003CC4
+S32500017AA038A1004090A1000838E1004490E1000C4BFFFDA57C030000408200108101003C98
+S32500017AC03928FFF04BFFFFA4808100442C04000B408000108101003C3928FFF04BFFFF8C2F
+S32500017AE080610040390280C09101000838A0000B90A1000C480059D57C0300004182001061
+S32500017B008101003C3928FFF04BFFFF6080E1004090E2830480810044908283088101003C6D
+S32500017B203928FFF04BFFFF4480A283047C050000408200B438628D504BFFBE2980628300B4
+S32500017B404800356D2C0306EB4082002038628D804BFFBE113860000183E100007FE803A665
+S32500017B60382100484E80002081028300890800005508402E80C2830088C600017D083378C9
+S32500017B805508801E80E2830088E7000254E7402E80828300888400037CE723787D083B781A
+S32500017BA02C0806EB4082002038628DAA4BFFBDB53860000183E100007FE803A6382100487C
+S32500017BC04E8000209002830038628DD64BFFBD957C03037883E100007FE803A638210048F3
+S32500017BE04E80002038628D6280E2830490E1000880A2830890A1000C81028304910100100F
+S32500017C004BFFBD614BFFFF38806283044E8000207FE802A697E1FFF080C283007C06000060
+S32500017C204182006880628300480034857C0300004082004480A2830088A5000054A5402EEE
+S32500017C4081028300890800017CA5437854A5801E80828300888400025484402E80C2830074
+S32500017C6088C600037C8433787CA523782C0506EB408200183860000183E100007FE803A63C
+S32500017C80382100104E8000207C03037883E100007FE803A6382100104E8000207FE802A6B2
+S32500017CA097E1FFB080E283007C070000408200183860FFFF83E100007FE803A638210050A1
+S32500017CC04E8000208142830088CA000054C6402E888A00017CC6237854C6801E88AA0002B3
+S32500017CE054A5402E88EA00037CA53B787CC62B782C0606EB408202387D49537888CA0014D2
+S32500017D0054C6402E888A00157CC6237854C6801E88EA001654E7402E890A00177CE743781F
+S32500017D207CC63B7874C6E0003D0020007C064000418201C488A9001454A5402E88C9001574
+S32500017D407CA5337854A5801E88E9001654E7402E888900177CE723787CA53B7890A1004C12
+S32500017D60398A00208161004C88E9000454E7402E88A900057CE72B7854E7801E88C9000661
+S32500017D8054C6402E91210040890900077CC643787CEA33787C0B6000418200507D635B780E
+S32500017DA0916100489181002091810008914100249141000C480051AD38628DF980C1004873
+S32500017DC090C10008808100209081000C80E1002490E100104BFFBB8D818100208161004821
+S32500017DE081410024812100407D8C521480A1004C3CE0FFC07C053840418000E439403000B6
+S32500017E0088A9000854A5402E890900097CA5437854A5801E8889000A5484402E88C9000BF0
+S32500017E207C8433787CA523787D43537891410048918100209181000890A1002490A1000C51
+S32500017E404800512138628E1980A1004890A10008810100209101000C80C1002490C1001078
+S32500017E604BFFBB0138628E398081004C908100084BFFBAF14BFF91CD4BFFBDED8101004CCF
+S32500017E807508E0003CA020007C0828004182002480E1004C7CE803A64E8000213860FFFFB0
+S32500017EA083E100007FE803A6382100504E80002080E1004C3FE0FFFF63FFFFFF7FE73839AF
+S32500017EC07CE803A64E8000213860FFFF83E100007FE803A6382100504E8000207C8A5A148A
+S32500017EE038840FFF3FE0FFFF63FFF0007FEA20394BFFFF1088AA001454A5402E88EA0015F3
+S32500017F007CA53B7854A5801E890A00165508402E88CA00177D0833787CA543783FE0FFFFE9
+S32500017F2063FFFFFF7FE528394BFFFE349141003480C1003490C100283D0A000C9101003090
+S32500017F4080C1003090C1002C386100283881004C90810008480032057C0300004080FF0888
+S32500017F603860FFFF83E100007FE803A6382100504E8000207FE802A697E1FF907C691B78CB
+S32500017F803861003491210008480054713861003438C1002490C10008390000049101000C28
+S32500017FA038C29AD590C1001048000D9D2C030002418201482C030003418200187C030378BA
+S32500017FC083E100007FE803A6382100704E8000208101007C9008000039429E0080AA000492
+S32500017FE07C050000418201007C0903782C090003408000E45524103A7C8452148084001C10
+S325000180007C040000418200C4806100249121001C5528103A9141006C7D0852148108001CEA
+S32500018020910100084800543D8141006C8121001C7C0300004082009480C10078810A0000C1
+S32500018040910600008101007C38A000017CA54830808800007C852B7890A800008061002825
+S3250001806038A1002090A100089001000C48004EF981010080906800007C030000408200144C
+S3250001808080A1002080E100287C053800418200288061008480A1002C90A100084800535D88
+S325000180A03860000183E100007FE803A6382100704E8000207C03037883E100007FE803A687
+S325000180C0382100704E800020392900012C0900034180FF24394A003080AA00047C05000001
+S325000180E04082FF087C03037883E100007FE803A6382100704E80002039029AD79101002C21
+S325000181004BFFFED07FE802A697E1FF30906100D47C0303784BFF8E39814100D8812100D4AA
+S3250001812071440004418200503C60001F6063FF6A38C29AD890C10008810900008108002489
+S325000181409101000C80A9000C90A100104BFFB7D1806100D48063000C810100DC9101000896
+S325000181604BFFA29183E100007FE803A6382100D04E800020714600084182002881090004B8
+S32500018180710800084182001C7C0303784BFFFA85814100D8812100D47C03000040820274EE
+S325000181A071460002418200FC8109000471080010418200348069000C38A29ADE90A10008B2
+S325000181C080E9000080E700187CE803A64E800021806100D43863000C900100084BFFAB6169
+S325000181E0812100D4808100DC7C040000418200A480C100DC88C600007CC607747C06000094
+S32500018200418200908069000C80A100DC90A1000881090000810800187D0803A64E80002191
+S32500018220812100D43C60001F6063FF6A38829AE39081000880C9000080C6002090C1000C7E
+S325000182408109000C91010010810100DC910100144BFFB6CD812100D48069000C80A9001466
+S3250001826090A1000880A9001090A1000C480017A5906100247C0303784BFF8CD58061002485
+S3250001828083E100007FE803A6382100D04E80002080E9000838E7000890E100DC4BFFFF68B6
+S325000182A0714700014182015880890000808400187C040000418200248069000C39029AECA0
+S325000182C09101000880A9000080A500187CA803A64E800021812100D480C9000470C60010D2
+S325000182E0418200103869000C900100084BFFAA5180C100DC7C06000041820084810100DCD5
+S32500018300890800007D0807747C080000418200703861002C810100DC91010008480050DDDC
+S325000183203C60001F6063FF6A38C29AF690C10008810100D4810800008108001C9101000C4A
+S3250001834080A100D480A5000C90A1001038A1002C90A100144BFFB5C9806100D43863000C41
+S325000183603901002C910100084BFFD56983E100007FE803A6382100D04E8000203861002C1E
+S32500018380808280A080840000908100084800506D3861002C38C0002F90C1000848004F3D79
+S325000183A07C03000041820050392300017D234B7838A29AF190A1000848005041806100D438
+S325000183C03863000C3881002C9081000838C100AC90C1000C4BFFD4417C0300004181FF440C
+S325000183E03860FFFF83E100007FE803A6382100D04E8000203921002C4BFFFFB43860FFFF3C
+S3250001840083E100007FE803A6382100D04E8000208069000C4BFFF889814100D8812100D4FA
+S325000184204BFFFD803821FFF08142801838C2E53838C608007C0A3040418000107C030378ED
+S32500018440382100104E8000203923002C80E900007C0700004182001880E900003927007C2A
+S3250001846080E900007C0700004082FFF038EA008090E2801891490000806900003821001080
+S325000184804E8000207FE802A697E1FFA89061005C39629E00810B00047C080000418200302C
+S325000184A080E1005C2C07FFFF41820038808B00008101005C7C08200041820028396B003080
+S325000184C0810B00047C0800004082FFD87C03037883E100007FE803A6382100584E800020DB
+S325000184E080AB000C7C0500004182FFD4808100607C0400004182005C814B002C7C0A0000A9
+S3250001850041820050810A0004812100607D2840394182003480A100642C05FFFF4182001410
+S3250001852080EA000C80C100647C063800408200187D43537883E100007FE803A638210058D5
+S325000185404E800020814A007C7C0A00004082FFB8808B0008708400804082002880AB00083C
+S3250001856060A5008090AB000891610054808B000C7C8803A64E80002181610054906B0028DA
+S325000185807C0D0378808B00287C0400004182FF30810B0028392000017D2968307D084839D9
+S325000185A04082000C39AD00014BFFFFDC3880000191A1004C7C8468307C8420F8810B00283F
+S325000185C07D042038908B00287D635B78916100544BFFFE5581A1004C816100547C6A1B78C5
+S325000185E07C0300004082000C39AD00014BFFFF9891A3000C80CB000890C30004810B0014D5
+S325000186009103001480AB001090A300109163000090610044808300047084000241820078CC
+S325000186207DA36B7838C29AFF90C10008812B00187D2803A64E80002181A1004C816100549F
+S3250001864081410044906A00087C0300004082001880EA00043FE0FFFF63FFFFFD7FE73839F2
+S3250001866090EA000480AA000470A50018408200287DA36B7838A29B0490A1000880EB0018F8
+S325000186807CE803A64E80002181A1004C816100548141004480CA000470C60001418200B82D
+S325000186A09001004838A0000190A1005080CA000080C600187C0600004182005C7DA36B7834
+S325000186C038A29B0990A10008810A0000810800187D0803A64E8000217C0300004182001839
+S325000186E080830000908100487C04000041820008900100508061004C38C29B0D90C10008C3
+S3250001870081010054810800187D0803A64E80002181410044386A000C8081004890810008A8
+S32500018720810100509101000C4BFFC96181A1004C81610054814100447C030000408000DC89
+S3250001874080EA00043FE0FFFF63FFFFEE7FE7383990EA000480AA000470A50010418200705D
+S3250001876080CA00043FE0FFFF63FFFFEF7FE6303990CA0004398282B8918280A0808C0000D7
+S325000187807C04000041820048386A000C80AC000090A1000838A1002090A1000C4BFFD0796B
+S325000187A081A1004C81610054814100447C0300004181005880C280A039860004918280A017
+S325000187C0808C00007C0400004082FFC080EA0004810100607D0738394182FDCC808100644F
+S325000187E02C04FFFF4182001080C100647C0668004082FDB47D43537883E100007FE803A670
+S32500018800382100584E800020808A000460840010908A00044BFFFFB838629B124BFFB1450A
+S3250001882081A1004C81610054814100444BFFFF287FE802A697E1FEF8480004C14BFF7AA127
+S32500018840480006654BFFB2394800254D4BFFAD1D4BFF7B314BFF8F614BFFA2E938629B23FE
+S325000188604BFFB101900280B44BFF791D38629B2C4BFFB0F14BFF7D657C6A1B7838629B32F7
+S32500018880914100E8914100084BFFB0D97C0B037839429E0080CA00047C060000418200209C
+S325000188A080AA00002C050002408203FC394A003080CA00047C0600004082FFE87C0B0000E0
+S325000188C0418203C480CB000470C60010418203B880A100E870A50002408200147C03037804
+S325000188E04BFFF3317C03000040820388900100F0900100F438629B4C4BFFA3B990610024F5
+S32500018900900100FC80A100247C0500004182005838E0000290E100F47C0A03782C0A000329
+S32500018920408002BC80610024914100F855451838388283487CA5221480A5000090A10008BF
+S3250001894048004B21814100F87C030000408202845547183838C283487CE7321480E7000416
+S3250001896090E100F4808100F07C0400004082001080C100F42C060002408201D4980100B0FF
+S325000189803860FFFF9001000838C0FFFF90C1000C4BFFFAF5900100FC39029E0091010020FD
+S325000189A081010020810800047C080000418200D480E100208147002C914101047C0A000094
+S325000189C0418200A4808100FC7C0400004082001838C0000190C100FC38629B884BFFAF8551
+S325000189E08141010480EA000470E700044182002438629B9680CA000080C6002490C1000821
+S32500018A00810A000C9101000C4BFFAF5981410104810A0004710800014182002438629B9D3F
+S32500018A2080EA000080E7001C90E10008808A000C9081000C4BFFAF2D81410104808A00049B
+S32500018A4070840018408200E4810A000471080002408200D8814A007C914101047C0A000015
+S32500018A604082FF6480A1002038A5003090A1002081010020810800047C0800004082FF3483
+S32500018A80808100FC7C0400004182000C38629BAB4BFFAED138629BAD38E1002890E100083E
+S32500018AA0388000509081000C38E100B090E100104BFFAD397C0300004180006838610028A7
+S32500018AC0388100EC9081000838C100FC90C1000C392101009121001038A1007890A10014CC
+S32500018AE04BFFF4957C03000041820038806100EC80A100FC90A10008810101009101000CDE
+S32500018B004BFFF9857C03000041820018810100FC9101000838C1007890C1000C4BFFF5E91E
+S32500018B20980100B04BFFFF7038629BA480EA000080E7002090E10008808A000C9081000CB6
+S32500018B404BFFAE21814101044BFFFF0C3900001F910100FC808100F42C04000140820018F3
+S32500018B6080C100FC3FE0FFFF63FFFFFB7FE6303990C100FC808100E8708400024182001863
+S32500018B8080C100FC3FE0FFFF63FFFFF77FE6303990C100FC3860FFFF80C100FC90C10008D5
+S32500018BA038A0FFFF90A1000C4BFFF8DD7C0300004182FDCC81030004812100FC7D2840382E
+S32500018BC0910100089001000C4BFFF53D4BFFFDB0394A00012C0A00034180FD4C8061002418
+S32500018BE038C100EC90C10008390100FC9101000C38A1010090A1001038E1007890E100142B
+S32500018C004BFFF3757C0300004082001838629B5580810024908100084BFFAD494BFFFD48AB
+S32500018C20806100EC808100FC90810008810101009101000C4BFFF8517C030000408200183D
+S32500018C4038629B6E81010024910100084BFFAD154BFFFD14810100FC9101000838E100781A
+S32500018C6090E1000C4BFFF4A1906100F04BFFFCF838629B404BFFACED7C0303784BFFF021C5
+S32500018C804BFFFC6C7C0303784BFFEF81906100187C03037880E1001890E100084BFFA0A1E7
+S32500018CA04BFFFC3091410020806A000038A0001090A1000838C0FFFF90C1000C4BFFF7C9DD
+S32500018CC0814100207C6B1B787C0300004182FBE0808B000470840010408200084BFFFBD022
+S32500018CE091610104386B000C900100084BFFA051816101044BFFFBC87FE802A697E1FFE891
+S32500018D008062801490010008388000249081000C4800401D80C2801439004E209106000487
+S32500018D204BFF74C180E28014906700103CA0FA2090A7002083E100007FE803A6382100187E
+S32500018D404E8000207FE802A697E1FFE87C691B78900100147C0900004182001488E90000C6
+S32500018D607CE707747C070000408200188061001483E100007FE803A6382100184E800020E9
+S32500018D8080C10014810100247C064000418000188061001483E100007FE803A6382100185C
+S32500018DA04E80002088A900007CA507747C05000041820028806100289121001C88C900005D
+S32500018DC07CC6077490C1000848003F418121001C7C030000408200C0890900007D0807745D
+S32500018DE07C080000408200188061001483E100007FE803A6382100184E8000208081001431
+S32500018E005484103A80E100207C843A149124000088C900007CC607747C060000418200282A
+S32500018E20806100289121001C88E900007CE7077490E1000848003ED58121001C7C030000F4
+S32500018E404182001480E1001438E7000190E100144BFFFF04888900007C8407742C04005CB5
+S32500018E604082001488A900017CA507742C05000A4182000C392900014BFFFF987D264B7893
+S32500018E803929000138E0002098E60000392900014BFFFF807D284B7839290001980800001B
+S32500018EA04BFFFF047FE802A697E1FFE03862813838C2C7D090C10008390010009101000CD4
+S32500018EC04800125538C2271074C6E0003CE020007C0638004182003038A227103862813844
+S32500018EE090A100083CE000407CE5385090E1000C4800124983E100007FE803A638210020E0
+S32500018F004E80002038A227103FE0FFFF63FFFFFF7FE528394BFFFFC87FE802A697E1FFD89A
+S32500018F209061002C810100307C0800004181000C38A0000490A100304BFF72699061002096
+S32500018F4038628138900100088081002C9081000C80E1003090E10010480013499061002409
+S32500018F60806100204BFF725980E100247C0700004082000C38629BC74BFFAA718061002498
+S32500018F809001000880A1002C90A1000C48003DA183E100007FE803A6382100284E8000209E
+S32500018FA07FE802A697E1FFE8388300033FE0FFFF63FFFFFC7FE42039386400089061001C97
+S32500018FC038800004908100084BFFFF5138A300043D00CAFE6108BEEF9103000038650004EC
+S32500018FE08121001C9125000083E100007FE803A6382100184E8000207FE802A697E1FFE0BD
+S325000190007C0300004182005038C3FFF890C1001880C600003CE0CAFE60E7BEEF7C06380084
+S325000190204182000C38629BCE4BFFA9C14BFF7175812100189061001C38628138912100089F
+S32500019040810900049101000C480010F18061001C4BFF716D83E100007FE803A63821002082
+S325000190604E8000204E8000207FE802A697E1FFF0808283809081000C390000FF9904001090
+S325000190804BFF70F98081000C88C4000060C6000198C400004BFF70E58081000C38C000177F
+S325000190A098C400144BFF70D583E100007FE803A6382100104E8000203821FFF080E2838032
+S325000190C09807001489070000710800FE99070000382100104E8000207FE802A697E1FFC092
+S325000190E038C2837090C100308106000C7C0800004182001483E100007FE803A63821004000
+S325000191004E800020386283C84BFFA8598141003038800001908A000C3CA0FA2060A50860F6
+S3250001912090A1003890AA00103CA0FA2060A53C8090AA00144BFFFF858121003080A9002C7B
+S325000191407C050000408200283860008438A0000290A100084BFFFDC5812100309069002C6B
+S3250001916080E9002C38E7008490E9002880E900307C0700004082001C3860008438E00002DF
+S3250001918090E100084BFFFD95812100309069003080E900187C0700004082004838600001D1
+S325000191A04BFFAB49812100309069001880C9003074C6E0003CE020007C06380041820248F1
+S325000191C080A9003080E9001890A7000480E90018B007000280C9001838A02000B0A600008A
+S325000191E080C9001C7C06000040820048386000024BFFAAF9812100309069001C80A9002CB4
+S3250001920074A5E0003CC020007C053000418201E48089002C80C9001C9086000480C9001CC0
+S32500019220B006000280A9001C38802800B085000080A280148145002080EA0AB860E70030D6
+S3250001924090EA0AB8A0EA0AC260E70030B0EA0AC280EA0ABC60E7003090EA0ABC81490014D3
+S3250001926080E9001874E7E0003CC020007C0730004182016C80A90018B0AA00008089001C6C
+S325000192807484E0003D0020007C0440004182013C80E9001CB0EA000238C0001898CA00043B
+S325000192A038800018988A000538E00084B0EA0006900A0008900A000CA08A0000B08A0010B8
+S325000192C0B00A0012900A0018A0AA0002B0AA0020900A001CB00A00224BFF6EA181E2801461
+S325000192E03DC0000161CE86A08181003838C0000198CC000C980C0000980C00047DCD7378F0
+S3250001930080EF00087CE773D6388000027CE723D63A07FFFD7C0B03787C0B80004080008087
+S32500019320394000037C0A000041800068808F000838AA00027C842E305567083C38E700067D
+S325000193407C843BD67D247051408000087D2900507C096800408000307D2D4B78996C00087E
+S3250001936088AC00003FE0FFFF63FFFFF97FE52839390000037D0A40505508083C7CA54378A6
+S3250001938098AC0000394AFFFF7C0A00004080FFA0396B00017C0B80004180FF883860002070
+S325000193A03CC0FFC260C6951890C10008390283709101000C480018BD83E100007FE803A660
+S325000193C0382100404E80002080E9001C3FE0FFFF63FFFFFF7FE738394BFFFEBC80A90018E1
+S325000193E03FE0FFFF63FFFFFF7FE528394BFFFE8C8089002C3FE0FFFF63FFFFFF7FE42039E2
+S325000194004BFFFE1480A900303FE0FFFF63FFFFFF7FE528394BFFFDB07FE802A697E1FFE0F1
+S3250001942080A1002890A10018812500109121001488E9001090E1001C4BFF6D418141001837
+S325000194408121001C80810014992400107126001441820034386283D6912100084BFFA50522
+S325000194608121001880C900207C060000418200089009002083E100007FE803A638210020CF
+S325000194804E8000207127000241820018808A00202C0400034082000C38A0000190AA002004
+S325000194A0712600014182FFD0810A00202C0800044082FFC438800001908A002083E10000BC
+S325000194C07FE803A6382100204E800020806300202C0300024080000C386000014E80002087
+S325000194E07C0303784E8000207FE802A697E1FFE89061001C80C1001C900600249001001446
+S325000195008061001C4BFFFFC97C0300004082007480A280B47C0500004182FFE880E100148A
+S3250001952038E7000190E100142C0700644081002C80C1001C39000001910600208081001C90
+S3250001954038C0000190C4002483E100007FE803A6382100184E800020386000014BFF952127
+S325000195607C03037880E1001C90E100084BFFFEAD8061001C4BFFFF597C0300004182FF948B
+S3250001958083E100007FE803A6382100184E8000207FE802A697E1FFD88181003439628370CF
+S325000195A02C0C0080408100183860FFFF83E100007FE803A6382100284E8000203940000120
+S325000195C080CB002C3FE0FFFF63FFFFFE7FE5183998A60000706500014182001480EB002C5A
+S325000195E07C66467098C70001394A000191610024806B002C914100207C63521480A1003033
+S3250001960090A100089181000C48003959812100243900000391090020808900183D000000F8
+S325000196206108B000B104000080A9002C74A5E0003CC020007C053000418200C88089002C7A
+S3250001964080C9001C9086000480C9001C80A10034808100207CA52214B0A600028109001C54
+S325000196603CE0000060E7B800B0E800004BFFF9FD810100248108001038E0008198E8000C8C
+S325000196804BFF6AF9806100244BFFFE614BFFFA2D81610024814B0020808B001CA0840000BA
+S325000196A0708880004082000C70850007418200183860FFFF83E100007FE803A638210028FB
+S325000196C04E8000202C0A0001418200183860FFFF83E100007FE803A6382100284E8000200A
+S325000196E0808B00247C0400004082FFC88061003483E100007FE803A6382100284E80002033
+S325000197008089002C3FE0FFFF63FFFFFF7FE420394BFFFF307FE802A697E1FFD081E1003C67
+S325000197203DC020007C6C1B78394283702C0F0080408100183860FFFF83E100007FE803A67E
+S32500019740382100304E800020808A002C6068000199040000706800014182002480AA0028DD
+S325000197603FE0FFFF63FFFFFE7FE4603998850000808A00287D8846709904000138A00004E6
+S3250001978090AA002080EA003074E7E0007C077000418201D080CA0030810A001890C8000493
+S325000197A0810A00183CE0000060E7B000B0E800007C0D0378816A001CB00B0008718500018F
+S325000197C04182002C810A00287508E0007C0870004182017C80EA002890EB00043880000284
+S325000197E0B08B0002396B000839A0040080AA002C74A5E0007C0570004182013C9141002C5E
+S32500019800808A002C908B000438CF0001B0CB000261A8A800B10B000091A100207C0D00001F
+S325000198204182001480AA001C3C80000060848000B08500004BFFF83580A1002C80A50010B6
+S32500019840388000819885000C4BFF69318061002C4BFFFC994BFFF86581C1003C8141002CBC
+S3250001986081AA0020816A001CA16B000080A100207C0500004182001080EA001CA0E70008D9
+S325000198807D6B3B78818A0018A18C00027C0C7000408100087DCC7378716800074082000C31
+S325000198A071658000418200183860FFFF83E100007FE803A6382100304E8000202C0D0001B5
+S325000198C0418200183860FFFF83E100007FE803A6382100304E800020808A0018A0840000DF
+S325000198E070848000418200183860FFFF83E100007FE803A6382100304E80002080EA002403
+S325000199007C0700004082FFA48061003880EA003090E10008918100189181000C4800364521
+S325000199208061001883E100007FE803A6382100304E8000209141002C808A002C3FE0FFFFEB
+S3250001994063FFFFFF7FE420394BFFFEBC80EA00283FE0FFFF63FFFFFF7FE738394BFFFE7C36
+S3250001996080CA00303FE0FFFF63FFFFFF7FE630394BFFFE287FE802A697E1FFD88161003437
+S325000199809061002C80A1003890A100247C0A03787C0A58004080004C392020007CEA585083
+S325000199A07C074800408000087D2A58508061002C80E100249141001C7CE7521490E10008FC
+S325000199C09121000C80C100307CC803A64E8000218141001C906100207C030000418100182D
+S325000199E07D43537883E100007FE803A6382100284E800020386285574BFF9F698161003414
+S32500019A0080E100208081001C7D443A144BFFFF847FE802A697E1FFD09061003490010008B1
+S32500019A2080A100387CA803A64E8000217C030000408000183860FFFF83E100007FE803A6A9
+S32500019A40382100304E80002038600020900100084BFFF4C97C6B1B783880002080610034C9
+S32500019A6080E1003C90E100089081002C9081000C91610020916100104BFFFEFD8141002034
+S32500019A8080C1002C7C03300041820020806282CC4BFF9ED13860FFFF83E100007FE803A6CD
+S32500019AA0382100304E800020888A00005484402E88EA00017C843B785484801E890A00029F
+S32500019AC05508402E88AA00037D082B787C8443782C0406EB4182004C3862855988CA0000A2
+S32500019AE054C6402E888A00017CC6237854C6801E88AA000254A5402E88EA00037CA53B784B
+S32500019B007CC62B7890C100084BFF9E593860FFFF83E100007FE803A6382100304E8000203E
+S32500019B2088AA001454A5402E890A00157CA5437854A5801E88CA001654C6402E88EA0017DD
+S32500019B407CC63B787CA5337874A5E0003CE020007C05380041820294888A00145484402E8A
+S32500019B6088AA00157C842B785484801E88CA001654C6402E890A00177CC643787C8433783C
+S32500019B809081002888CA000454C6402E888A00057CC6237854C6801E88AA000654A5402E5C
+S32500019BA088EA00077CA53B787CC62B783862858490C1002C90C100084BFF9DA9806100344E
+S32500019BC08081003C908100088101002C9101000C80A1002890A100104BFFFD9D8161002C60
+S32500019BE0814100207C03580041820020806282CC4BFF9D713860FFFF83E100007FE803A630
+S32500019C00382100304E800020808100287CCB221438C60FFF3FE0FFFF63FFF0007FEB3039D2
+S32500019C2088EA000854E7402E88AA00097CE72B7854E7801E88CA000A54C6402E890A000B5E
+S32500019C407CC643787CE733783862858790E1002C90E10008916100289161000C4BFF9D0532
+S32500019C60806100348101003C9101000880E1002C90E1000C80810028908100104BFFFCF9DD
+S32500019C808141002080E1002C7C03380041820020806282CC4BFF9CCD3860FFFF83E10000D7
+S32500019CA07FE803A6382100304E8000203862859388AA000C54A5402E890A000D7CA5437843
+S32500019CC054A5801E888A000E5484402E88CA000F7C8433787CA5237890A10008890A0014D8
+S32500019CE05508402E88CA00157D0833785508801E88EA001654E7402E888A00177CE72378A8
+S32500019D007D083B789101000C4BFF9C594BFF73354BFF9F554BFF648D8141002088EA001454
+S32500019D2054E7402E88AA00157CE72B7854E7801E890A00165508402E892A00177D084B78C7
+S32500019D407CE7437874E7E0003C8020007C0720004182004888CA001454C6402E88EA0015A4
+S32500019D607CC63B7854C6801E890A00165508402E88AA00177D082B787CC643787CC803A660
+S32500019D804E8000217C03037883E100007FE803A6382100304E80002088CA001454C6402EFA
+S32500019DA0890A00157CC6437854C6801E888A00165484402E88EA00177C843B787CC62378B8
+S32500019DC03FE0FFFF63FFFFFF7FE630397CC803A64E8000217C03037883E100007FE803A6E7
+S32500019DE0382100304E800020888A00145484402E88CA00157C8433785484801E88EA001669
+S32500019E0054E7402E88AA00177CE72B787C843B783FE0FFFF63FFFFFF7FE420394BFFFD64AC
+S32500019E207FE802A697E1FFE89061001C386300184BFFF17138A3001890A3000C8103000C7F
+S32500019E40910300049103000080C3000C80E1001C7CC63A1490C30008900300103D00CAFE70
+S32500019E606108BEE09103001483E100007FE803A6382100184E8000207FE802A697E1FFF0E3
+S32500019E807C691B787C0300004182004090610014810300143CE0CAFE60E7BEE07C0838009F
+S32500019EA041820010386281284BFF9B4181210014900900143CE0DEAD60E7BABE90E900100D
+S32500019EC07D234B784BFFF13583E100007FE803A6382100104E8000207FE802A697E1FFE86F
+S32500019EE0386000144BFFF0BD900300049003000080A1002490A30008808100289083000CC6
+S32500019F009003001083E100007FE803A6382100184E8000207FE802A697E1FFE89061001C49
+S32500019F204BFF62818141001C90610014812A0000912100107C0900004182003C80A90010E0
+S32500019F4090AA00009009001080E90004810900007CE83850810A00107CE7405090EA00101C
+S32500019F6080CA00107C0600004080000C3862812E4BFF9A79806100144BFF624580610010B5
+S32500019F8083E100007FE803A6382100184E8000207FE802A697E1FFE89061001C4BFF6205BB
+S32500019FA08141001C812100207C6B1B789009001080EA00007C0700004082005C912A000011
+S32500019FC0912A000480A9000480C900007CA6285080CA00107CA62A1490AA00107D635B78F4
+S32500019FE04BFF61DD8121001C80A900087C050000418200148069000C80E900087CE803A618
+S3250001A0004E80002183E100007FE803A6382100184E80002080AA0004912500104BFFFFA496
+S3250001A020806300104E8000207FE802A697E1FFE09061002438C0FFFF90C100144BFF616552
+S3250001A04081610014814100247C6C1B78916100147C0B000040800010812A00007C09000015
+S3250001A060408200207D8363784BFF61558061001483E100007FE803A6382100204E8000204C
+S3250001A08080E9000080C900047C073040408000208169000038EB000190E90000896B0000B5
+S3250001A0A0808A00103884FFFF908A001080E9000080C900047C0730404180FF9480E9001025
+S3250001A0C090EA0000900900104BFFFF847FE802A697E1FFE89061001C386000014BFFFD45E9
+S3250001A0E07C681B788083000438C4000190C3000480C1002098C400008061001C9101000833
+S3250001A1004BFFFE9183E100007FE803A6382100184E800020812100089123000480C1000CDD
+S3250001A12038A000087CC62BD654C618387CC64A1490C300084E8000207FE802A697E1FFD844
+S3250001A14081810034816100307C6E1B787C0C00004181001483E100007FE803A638210028E0
+S3250001A1604E8000208143000480AA00047C0558404181001080CA00007C0600004082011C5E
+S3250001A18080AE00047C0A28404081001C38CAFFFC80C6000080EAFFF87CC63A147C065800AD
+S3250001A1A0418200A47D0B6214812A00047C0848004082001080EA00007C07000040820060D7
+S3250001A1C0808E00087C0A20404180002C3862829880AE000090A100089161000C9181001054
+S3250001A1E04BFF978183E100007FE803A6382100284E80002081AA0004916A00047DAB6B78DA
+S3250001A20081AA0000918A0000394A00087DAC6B787C0D00004182FFD04BFFFFA880AA000420
+S3250001A2207D0C2850910A000480EA00007CA7621490AA000083E100007FE803A63821002845
+S3250001A2404E80002080CAFFF87C866214908AFFF87C8B621480AA00047C0428004082FF88A3
+S3250001A26080AA0000808AFFF87CA42A1490AAFFF880EA00007C0700004182FF6C394A000877
+S3250001A280388AFFFC80CA000490C40000810A0000910AFFF84BFFFFDC394A00084BFFFECC77
+S3250001A2A07FE802A697E1FFD881E1003081C1003481A100387C701B7881630004810B0000E4
+S3250001A2C07C08000041820028818B00047C0F00004182005C7C0C784040810028396B000879
+S3250001A2E0810B00007C0800004082FFE07C03037883E100007FE803A6382100284E800020C9
+S3250001A3007D0F7214812B00007D2C4A147C084840408100187C03037883E100007FE803A61E
+S3250001A320382100284E8000207DEC7B787C0D0000408100147C8D62143884FFFF7C846B96B3
+S3250001A3407D8469D680CB000080EB00047CC63A147CCC30507C067040408000084BFFFF80E1
+S3250001A36081AB00047CEC721490EB00047D0C72147D0D4050812B00007D084850910B0000AB
+S3250001A38080CB00007C06000040820028396B000838CBFFFC810B00049106000080AB000003
+S3250001A3A090ABFFF87C050000418200084BFFFFE07C0D6000418200207E03837891A100086D
+S3250001A3C0918100207CCD605090C1000C4BFFFD6D818100207D83637883E100007FE803A6C9
+S3250001A3E0382100284E8000207FE802A697E1FFB8388002809081003438A001E090A1003808
+S3250001A40038C0000390C1003C90010040386100344800042180E100407C07000040820014A8
+S3250001A42083E100007FE803A6382100484E800020388000039082825480A1004090A2824812
+S3250001A44038E000A090E28250900282589002825C3900028091028260388001E0908282645C
+S3250001A46038A2824838C2824880E600108106001490E5002091050024810600188086001C4C
+S3250001A480910500289085002C7C0303783880FFFF9081000838C0FFFF90C1000C3900FFFF63
+S3250001A4A09101001048000641386000FF900100089001000C900100104800062D3862824817
+S3250001A4C038A1000890A1002C80E1002C900700008081002C9004000438C2824890C1001029
+S3250001A4E0390100143882824880A4001080C4001490A8000090C8000480C4001880E4001C87
+S3250001A50090C8000890E8000C900100244BFFCAB538E0000890E280A8900280AC8102800C4B
+S3250001A52089080105910280B083E100007FE803A6382100484E8000207FE802A697E1FFB879
+S3250001A5407C691B7880C282487C0600004082001483E100007FE803A6382100484E80002015
+S3250001A5609061004C2C030008418202302C030009418201D02C03000A4182010480A282609A
+S3250001A580810280B07CA8285080C280A87C062800418000103860000A4BFFFFA18121004C06
+S3250001A5A07129007F408100C8A8E280087C093800408000BC5528183880C2800C7D28321421
+S3250001A5C03881003C38A280A880C5000080E5000490C4000090E400043862824838E100087E
+S3250001A5E090E100348081003488C900047CC607748101003C7CC8321490C4000080C1003457
+S3250001A600810100409106000480A2801090A10010390100149101003080A10030A8E90000F1
+S3250001A62090E50000808100309004000480C1003091210044A90900089106000880A10030C4
+S3250001A64088E2800A7CE7077490E5000C38E0000C90E100244BFFC96D808100448884000511
+S3250001A66080C1003C7C843214908280A883E100007FE803A6382100484E8000203900000892
+S3250001A680910280A88882800A7C840774810280AC7C882214908280AC88C2800A7CC6077431
+S3250001A6A080E282647CC63850810280AC7C0830004081000C80A2825C90A280AC386282488F
+S3250001A6C038E1000890E10034808100349004000080C10034810280AC9106000438A2824881
+S3250001A6E090A1001038E1001490E10030808100309004000080C10030810280AC91060004C4
+S3250001A70080A1003080E2826090E500088081003088C2800A7CC6077454C6083C80E280AC72
+S3250001A7207CC63A1490C4000C900100244BFFC89583E100007FE803A6382100484E800020C3
+S3250001A740808280A83884FFF880A280B07C842BD67084000738C000087C84305080E280B0B5
+S3250001A7607C8439D680A280A87C852214908280A880E280A8808282607C0720004180FEF048
+S3250001A7803860000A4BFFFDB583E100007FE803A6382100484E80002080C280B038C6000899
+S3250001A7A0810280A87C0830004180FEC480A280B080E280A87CA5385090A280A83860002019
+S3250001A7C04BFFFD7980A280B080E280A87CA5385090A280A883E100007FE803A638210048BE
+S3250001A7E04E8000207FE802A697E1FFF07C691B788101001838C8FFFF90C100187C080000F1
+S3250001A8004081002038E9000190E10014886900007C6307744BFFFD25812100144BFFFFD41F
+S3250001A82083E100007FE803A6382100104E8000207FE802A697E1FFD87C6A1B7880E2801479
+S3250001A84080E7002090E10024388001E09083000438E0028090E3000038A0000390A3000802
+S3250001A860806300009141002C80EA00047C6339D638A0001090A100084BFFE6A13DA0017D47
+S3250001A88061AD78408181002C81610024906C000C80AC000080CC00047CA531D690AC0010BF
+S3250001A8A0808B00303FE0FFFF63FFFFBF7FE42039908B0030810C000C7508E0003D2020009F
+S3250001A8C07C0848004182020C80EC000C90EB085080EC0000810C00047CE741D654E7183887
+S3250001A8E038E7007F390000807CE743D654E7881C60E70D6690EB084038A000037C050000C6
+S3250001A900418200142C050002418201A02C050003418201687C0A03782C0A00104080001C3F
+S3250001A9205546083C7CC65A14B1460E00394A00012C0A00104180FFEC808C0004548458289E
+S3250001A9403FE0100063FF00217FE42378908B084880CC000054C6502A3FE0010063FF00E48F
+S3250001A9607FE6337890CB084480C28014818600087D4C6BD67CCC53D67C0668004081000806
+S3250001A980394A00019141001C2C0A00104180000C38E0001090E1001CB00B097638E01FFF06
+S3250001A9A0B0EB0972A0AB097270A5FDFFB0AB097238A01FFFB0AB0970810B0ABC61085001F7
+S3250001A9C0910B0ABC810B0AB861085001910B0AB8A10B0AC27108AFFEB10B0AC24BFF579D44
+S3250001A9E080C100243D0055CC6108AA33910603804BFF578981410024808A02803FE0FFFF74
+S3250001AA0063FFFFE07FE4203938A281108101001C7CA5421488A500007C842B78908A028046
+S3250001AA204BFF575980A100243CE0AA3360E755CC90E503804BFF57458102825091028250D7
+S3250001AA4080A1002438E0000798E508584BFF572D8101002480A8084060A5000190A8084044
+S3250001AA60386000014BFF5D3183E100007FE803A6382100284E8000207C0A03782C0A010043
+S3250001AA804080FEB85544402E554520367C842B787C8453785545083C7CA55A14B0850E0024
+S3250001AAA0394A00014BFFFFD87C0A03782C0A00104080FE885546402E554720367CC63B786D
+S3250001AAC07CC65378B0CB0E00394A00014BFFFFE080EC000C3FE0FFFF63FFFFFF7FE7383960
+S3250001AAE04BFFFDEC80810008548B273E80E1000C54EA273E80A1001054A9273E3FE0FFFF0F
+S3250001AB0063FFFFFF7FE81A78710800FF5508083C80C2801480C600207D0832145565402E8D
+S3250001AB20554620367CA533787CA54B78B0A80E00386000014E8000203821FFE83D4055CCA2
+S3250001AB40614AAA333D20FA209149030038C000C3B0C902009149032038E000C1B0E902204B
+S3250001AB603CA0AA3360A555CC90A903209149034038C00082B0C90240382100184E800020E2
+S3250001AB807FE802A697E1FFE081410028906100247145000341820010386287E44BFF8E4D93
+S3250001ABA081410028812100243CC07C1060C643A690C900003C807C08608402A69089000405
+S3250001ABC03CE07C1260E743A690E900087544E0003CC020007C043000418200887D485378D3
+S3250001ABE07D0A437855053E7F4182000C2C05007F408200303FE003FF63FFFFFC7FE5503919
+S3250001AC003FE0480063FF00037FE52B7890A9000C83E100007FE803A6382100204E8000203A
+S3250001AC205544843E64843C009089000C7144FFFF64846000908900103C807C08608403A678
+S3250001AC40908900143CE04E8060E7002190E9001883E100007FE803A6382100204E80002002
+S3250001AC603FE0FFFF63FFFFFF7FE850394BFFFF747FE802A697E1FFE89061001C8082E53011
+S3250001AC802C0400304180000C386287EC4BFF8D5D80C1001C7D4602148082E53039040001B4
+S3250001ACA09102E5305484203638A2E03038A502007D642A145547103A38C2E0307CE7321436
+S3250001ACC080E7000090EB000881010020910B000080E1002490EB00045544103A38E2E03034
+S3250001ACE07C843A149164000080A28014816500202C0A00104180003038EAFFF070E7001F90
+S3250001AD0038C000017CC7383080CB09487CC73B7890EB094883E100007FE803A63821001845
+S3250001AD204E8000202C0A000841800038714800075508083C38E0001F7D08385039200001E8
+S3250001AD407D284030808B00147C884378910B001483E100007FE803A6382100184E80002076
+S3250001AD605544083C608400013900001F7C84405038A000017CA4203080AB00147CA42378DF
+S3250001AD80908B001483E100007FE803A6382100184E8000207FE802A697E1FFE03D4055CCA6
+S3250001ADA0614AAA33810280148128002080A900043FE0FFFF63FFFFF37FE5283990A9000484
+S3250001ADC09009001438E0FFFF90E900189009094038E0FFFF90E90944900909483CE000E173
+S3250001ADE060E79F0090E9094080A9094060A5008090A909409149030039000001B109020058
+S3250001AE0080C9001464C6004090C900149149030C4BFF53693860FFFF4BFF53E17C090378F4
+S3250001AE202C0930004080002C7D234B789121001C3D00FFC2610803A8910100084BFFFD4551
+S3250001AE4080E1001C392701002C0930004180FFDC83E100007FE803A6382100204E80002031
+S3250001AE607FE802A697E1FFD87C6A1B787C0903782C09002840800064386288065526103A86
+S3250001AE8038A284307CC62A1480C6000090C10008810A00009101000C912100245528103A38
+S3250001AEA038E284307D083A1481080004910100109141002080AA000490A100144BFF8AA5DD
+S3250001AEC0810100243928000280C10020394600082C0900284180FFA483E100007FE803A645
+S3250001AEE0382100284E8000207FE802A697E1FFE87C6A1B789061001C80C3000054C9C23E88
+S3250001AF002C090005418200802C0900094182005C38C0000190C280B47C0900004180003C4F
+S3250001AF202C09001540800034386288345524103A390295A07C8442148084000090810008D0
+S3250001AF404BFF8A218061001C4BFFFF19386288424BFF8A11480000003862881B912100080E
+S3250001AF604BFF8A014BFFFFE07D435378900100084BFF7B8983E100007FE803A63821001875
+S3250001AF804E8000204800001583E100007FE803A6382100184E8000207FE802A697E1FFD82E
+S3250001AFA09061002C810280148168002091610018890B001C550CF0BE7D8A0E7091810024C9
+S3250001AFC071880001418200E02C0A00044082002438800001B08B09304BFF51A1818100241E
+S3250001AFE081610018A0AB093054A5AAFE39450010914100205545103A3882E0307CA52214A6
+S3250001B000814500007C0A00004082000848000000808A000C7C0400004182002038A0001F5B
+S3250001B0207CAC285038C000017CC5283080CB00107CC52B7890AB00108061002C80EA0004D2
+S3250001B04090E100089141001C80EA00007CE803A64E80002180C1001C814600087C0A00006A
+S3250001B060418200084BFFFFD480C100202C060010418000248101001880A1002038A5FFF0B2
+S3250001B080392000017D2528308088094C7C852B7890A8094C83E100007FE803A638210028D2
+S3250001B0A04E800020394A00084BFFFF487C691B7888A3000054A5402E888300017CA52378AD
+S3250001B0C054A5402E88C300027CA5337854A5402E88C300037CA533783CE0FEEF60E70F1EEB
+S3250001B0E07C05380040820030886300205463402E88C900217C6333785463402E88E90022BA
+S3250001B1007C633B785463402E890900237C6343784E8000207C0303784E8000207FE802A63D
+S3250001B12097E1FFE8386001F43CA0FFC260A5B21C90A100089001000C4BFF65959062822CF2
+S3250001B14038628BE04BFF881D83E100007FE803A6382100184E8000207FE802A697E1FFB8E3
+S3250001B160818100507C6B1B788083000480A300007C8520502C040040408000183860FFFF83
+S3250001B18083E100007FE803A6382100484E80002081430000890A00005508402E88EA000110
+S3250001B1A07D083B785508402E892A00027D084B785508402E888A00037D0823783CA0FEEFBF
+S3250001B1C060A50F1E7C082800418200183860FFFF83E100007FE803A6382100484E80002016
+S3250001B1E0900282EC88CA001054C6402E88AA00117CC62B7854C6402E88EA00127CC63B7835
+S3250001B20054C6402E88EA00137CCE3B78888A00145484402E890A00157C8443785484402E08
+S3250001B22088AA00167C842B785484402E88AA00177C842B789081003888EA001854E7402E6E
+S3250001B24088CA00197CE7337854E7402E890A001A7CE7437854E7402E890A001B7CE7437885
+S3250001B26090E1003488AA000C54A5402E888A000D7CA5237854A5402E88CA000E7CA533780F
+S3250001B28054A5402E88CA000F7CA5337890A10030890A00045508402E88EA00057D083B78A1
+S3250001B2A05508402E892A00067D084B785508402E888A00077D0D237888CA000854C6402ED0
+S3250001B2C088AA00097CC62B7854C6402E88EA000A7CC63B7854C6402E88EA000B7CC63B7854
+S3250001B2E090C1002880C3000038C6002090C3000081430000888A00005484402E890A00016A
+S3250001B3007C8443785484402E88AA00027C842B785484402E88AA00037C842B782C0406EB0F
+S3250001B3204182002038628BE24BFF86393860FFFF83E100007FE803A6382100484E8000207A
+S3250001B34088CA001454C6402E88AA00157CC62B7854C6402E88EA00167CC63B7854C6402E3F
+S3250001B36088EA00177CC63B7890CC000081030000390800209103000080EC000074E7E000CC
+S3250001B3803D0020007C0740004182015480CC00007CC3337890C100449161004C916100086B
+S3250001B3A091A1000C91C1001038A28BFF90A1001448000141816100287C6A1B787C030000B1
+S3250001B3C04082002038628C044BFF85993860FFFF83E100007FE803A6382100484E80002059
+S3250001B3E07C0B00004182005C38EA0FFF3FE0FFFF63FFF0007FE3383980E1004C90E1000808
+S3250001B4009161000C810100389101001038C28C1790C10014480000DD7C6A1B787C030000AC
+S3250001B4204082002038628C1C4BFF85393860FFFF83E100007FE803A6382100484E80002040
+S3250001B44080C100307C060000418200407D435378914100408081004C8084000090810008E8
+S3250001B460808100309081000C48001AF981610030808100407D445A1480E1004C80C70000A6
+S3250001B4807C865A1490870000808282EC80C100347C0430004182003038628C2F810282EC50
+S3250001B4A09101000880C1003490C1000C4BFF84B53860FFFF83E100007FE803A638210048EB
+S3250001B4C04E80002080C100447C66505083E100007FE803A6382100484E80002080CC000021
+S3250001B4E03FE0FFFF63FFFFFF7FE630394BFFFEA47FE802A697E1FFE07C6A1B7838628C67A2
+S3250001B5008081003490810008914100249141000C80A1002C90A100104BFF84498101002CAF
+S3250001B5207C080000408200188061002483E100007FE803A6382100204E80002080610028BD
+S3250001B5403902EE00910100089001000C480003257C030000408000187C03037883E100005F
+S3250001B5607FE803A6382100204E8000208061002838E20A0890E10008388000089081000CC2
+S3250001B580480002F1814100287C030000408000187C03037883E100007FE803A63821002041
+S3250001B5A04E80002080CA000480EA00007CC7305080A1002C7C0628004080002038628C7F9F
+S3250001B5C04BFF83A17C03037883E100007FE803A6382100204E800020386001F43D00FFC296
+S3250001B5E06108B21C910100089001000C4BFF60E1814100289062822C80610024810A000031
+S3250001B60091010008810A00008121002C7D084A149101000C38E2EE0090E1001039020A08D9
+S3250001B6209101001480A1003090A100184800006D906100248062822C4BFF61759002822C09
+S3250001B64038628C8E4BFF831D814100247C0A00004082002038628C904BFF83097C03037871
+S3250001B66083E100007FE803A6382100204E80002080E100288081002C80C700007C862214B3
+S3250001B680908700007D43537883E100007FE803A6382100204E8000203821FFE8820100243F
+S3250001B6A081610030812100207C6C1B78556536BE2C050013418201942C05001F4182018C4A
+S3250001B6C02C05003B418201842C05003F4182017C81A282EC7C0980404080016088890000F7
+S3250001B6E07C8F2378392900017C0E03787C8A26707C0A00004082002C7D6A5B78914C00008E
+S3250001B700398C00047DAD521471EA000F39CE00012C0E00014082FFC07C0A00004182FFDC77
+S3250001B7202C0A00014082009488E9000354E7402E88C900027CE7337854E7402E89090001BB
+S3250001B7407CE7437854E7402E890900007CEA4378392900047C098040408100107C030378F2
+S3250001B760382100184E800020554736BE2C070013418200202C07001F418200182C07003B0F
+S3250001B780418200102C07003F418200084BFFFF703FE0FC0063FFF8017FE8503955478BFE4E
+S3250001B7A070E707FE7D083B78714407FE548478207D0A23784BFFFF48280A000841810044D1
+S3250001B7C038AAFFFE54A5402E890900007CA5437854A5103A80C1002C7CA5321480A500046E
+S3250001B7E0890900017CAA4378392900027C0980404081FF787C030378382100184E80002094
+S3250001B800390AFFF75508402E88C900007D0833785508103A80E100287D083A1481480004CC
+S3250001B820392900017C0980404081FF407C030378382100184E80002091A282EC7D83637884
+S3250001B840382100184E8000203FE0FC0063FFF8017FE6583955658BFE70A507FE7CC62B78D4
+S3250001B860716707FE54E778207CCB3B784BFFFE647FE802A697E1FFD08083000480A30000EB
+S3250001B8807C8520502C040002408000183860FFFF83E100007FE803A6382100304E800020A5
+S3250001B8A081030000890800005508402E9061003480E3000088E700017D083B7838628CB398
+S3250001B8C09101001C910100084BFF809981C100388161003480CB000038C6000290CB000080
+S3250001B8E08081001C39A4FFFE7C0D00004081002C810B0004812B00007D0940507C08680096
+S3250001B900408000183860FFFF83E100007FE803A6382100304E800020900E0000814B00005D
+S3250001B92080CB00007D866A14810B00007CC86A1490CB00007C0D03787C0A60404080009011
+S3250001B9407C0B03787C0A6040418000183860FFFF83E100007FE803A6382100304E8000205E
+S3250001B9605568383088CA000070C6007F7D0B33787D455378394A000188A5000070A500808E
+S3250001B980418200207C0A60404180FFD83860FFFF83E100007FE803A6382100304E8000207E
+S3250001B9A07DAD5A14808E000038A4000190AE00005484103A7C84721480E1003C7DA53830F0
+S3250001B9C090A400047C0A60404180FF787C03037883E100007FE803A6382100304E800020E5
+S3250001B9E03821FFF07C6B1B7880A1001C810100247D45421480C10018808100207D26221430
+S3250001BA008081001C7C0A20404080000839290001914B0004912B0000382100104E800020FE
+S3250001BA203821FFF07C6B1B788101001C80C100247D4640508081001880E100207D27205039
+S3250001BA4080E1001C7C0A3840408100083929FFFF914B0004912B0000382100104E80002048
+S3250001BA603821FFD8CA2100307C6E1B78DA210020810100203FE0000F63FFFFFF7FE84039CC
+S3250001BA80650C001081A10024810100205508653E710807FF38C004337D2830507C0B037861
+S3250001BAA07C0A03787C090000418000B02C090020408000847C090000408200607DAB6B783D
+S3250001BAC07D8A637880A1002074A580007C050000418200207C0B0000418200287C040378D2
+S3250001BAE07D6B20503FE0FFFF63FFFFFF7FEA5278914E0000916E0004382100284E800020E6
+S3250001BB007C0703787D4A3850914E0000916E0004382100284E8000207DA54C3038C00020CA
+S3250001BB207CC930507D8630307CAB33787D8A4C304BFFFF942C0900204082000C7D8B63789E
+S3250001BB404BFFFF842C0900404080FF7C38C9FFE07D8B34304BFFFF707C0703787D29385030
+S3250001BB602C09000A418100207DAB48307D85483038C000207CC930507DA634307CAA33784E
+S3250001BB804BFFFF44FC80881ED8828020814280244BFFFF347FE802A697E1FFE8C061002062
+S3250001BBA0D86100084BFFFEBD83E100007FE803A6382100184E8000203D20433080E1000430
+S3250001BBC074E780007C0700004182009C808100087C0400004182007C7C0603788101000852
+S3250001BBE07CC8305090C1000880C100043FE0FFFF63FFFFFF7FE6327890C1000480E1000496
+S3250001BC00912280206CE6800090C28024C8228020FC21D828C8828428FC01013280A100080C
+S3250001BC20912280206CA4800090828024C8628020FC63D828FC03E0004080000CC8428428DA
+S3250001BC40FC63102AFC00182AFC1C00284E8000207C04037880C100047C8620509081000411
+S3250001BC604BFFFF9C80A10004912280206CA4800090828024C8628020FC63D828C84284283B
+S3250001BC80FC0300B281010008912280206D07800090E28024C8228020FC21D828FC01E00081
+S3250001BCA04080000CC8428428FC21102AFC00082A4E8000207FE802A697E1FFF038C1000415
+S3250001BCC038E10014810700008087000491060000908600044BFFFEE5FC00001883E1000047
+S3250001BCE07FE803A6382100104E8000203821FFD83DA080008241003C822100408161002C59
+S3250001BD008181003081210034814100387C0A00004082000C7C090000418200F47C0B68405B
+S3250001BD20418000E07C0F03787C0E03787C096840418000147C096800408200307C0A784031
+S3250001BD40408000285525083C55480FFE7CA94378554A083C39CE00017C0968404180FFE8EC
+S3250001BD607C0968004182FFD87C0F03787C0D03787C0E00004180006455E4083C55A70FFEF6
+S3250001BD807C8F3B7855AD083C7C0B4840418100147C0B4800408200287C0C50404180002001
+S3250001BDA07D9063787D8A60507C0C804040810008396BFFFF7D69585061AD00015547F87E7B
+S3250001BDC05525F8007CEA2B785529F87E39CEFFFF7C0E00004080FFA47C1200004182000C9E
+S3250001BDE091B2000491F200007C1100004182000C9191000491710000382100284E8000207F
+S3250001BE007D6D5B787D8F63784BFFFF207D8C53964BFFFF0C7FE802A697E1FFE07C691B78E9
+S3250001BE2080E100287C07000040820010808100307C0400004182005438E1000439010028D6
+S3250001BE408088000080A800049087000090A7000438A1000C38C1003080E600008106000456
+S3250001BE6090E5000091050004912100147C06037890C100184BFFFE7983E100007FE803A64B
+S3250001BE80382100204E8000207C0803789109000080C1002C80A100347CC62B9690C9000479
+S3250001BEA083E100007FE803A6382100204E8000207FE802A697E1FFE07C691B788101002818
+S3250001BEC07C0800004082001080A100307C05000041820054390100043881002880A40000D9
+S3250001BEE080C4000490A8000090C8000438C1000C38E10030810700008087000491060000E7
+S3250001BF00908600047C04037890810014912100184BFFFDDD83E100007FE803A63821002005
+S3250001BF204E8000207C0403789089000080E1002C80C100347FE733967FFF31D67CFF38503F
+S3250001BF4090E9000483E100007FE803A6382100204E800020808300047C0400004082001821
+S3250001BF6080A300007C0603787CA5305090A300004E800020808300047C0503787C8428505D
+S3250001BF8090830004810300003FE0FFFF63FFFFFF7FE84278910300004E8000207FE802A6D0
+S3250001BFA097E1FFD07C691B78906100348081003C7C84FE7080C100387C06200040820018F6
+S3250001BFC0810100447D08FE7080A100407C054000418200AC80E1003854E70FFE90E1002C92
+S3250001BFE07C07000041820010386100384BFFFF698121003480E1004054E70FFE90E1002809
+S3250001C0007C07000041820010386100404BFFFF498121003438E100043901003880880000EB
+S3250001C02080A800049087000090A7000438A1000C38C1004080E600008106000490E50000F7
+S3250001C04091050004912100147C06037890C100184BFFFC9D80E1002C808100287C072000D7
+S3250001C0604182000C806100344BFFFEED83E100007FE803A6382100304E8000208081003C78
+S3250001C080810100447C8443D69089000480E900047CE7FE7090E9000083E100007FE803A672
+S3250001C0A0382100304E8000207FE802A697E1FFD07C6A1B78906100348101003C7D08FE705D
+S3250001C0C080A100387C0540004082001880E100447CE7FE70808100407C043800418200A48F
+S3250001C0E080C1003854C60FFE90C1002C7C06000041820010386100384BFFFE5D814100345B
+S3250001C10080C1004054C60FFE7C06000041820010386100404BFFFE418141003438C10004C6
+S3250001C12038E10038810700008087000491060000908600043881000C38A1004080C5000040
+S3250001C14080E5000490C4000090E400047C07037890E10014914100184BFFFB9580C1002CEF
+S3250001C1607C0600004182000C806100344BFFFDE983E100007FE803A6382100304E80002037
+S3250001C1808101003C80E100447FE83BD67FFF39D67D1F4050910A000480CA00047CC6FE7067
+S3250001C1A090CA000083E100007FE803A6382100304E8000203821FFF081610020814100180F
+S3250001C1C02C0B0020418000387D46FE7090C300002C0B0040418000147D48FE70910300046D
+S3250001C1E0382100104E800020390BFFE07D48463091030004382100104E8000207C0B00000D
+S3250001C200418100189143000080E1001C90E30004382100104E8000207D465E3090C300007A
+S3250001C22038E000207CEB38507D47383080A1001C7CA55C307CE72B7890E3000438210010D4
+S3250001C2404E8000203821FFF081410020816100182C0A0020418000387C05037890A3000047
+S3250001C2602C0A0040418000147C05037890A30004382100104E800020390AFFE07D68443067
+S3250001C28091030004382100104E8000207C0A0000418100189163000080E1001C90E3000460
+S3250001C2A0382100104E8000207D66543090C3000038E000207CEA38507D67383080A1001CB7
+S3250001C2C07CA554307CE72B7890E30004382100104E8000203821FFF0814100208161001CB6
+S3250001C2E02C0A0020418000387C05037890A300042C0A0040418000147C05037890A300003B
+S3250001C300382100104E800020390AFFE07D68403091030000382100104E8000207C0A0000D7
+S3250001C320418100189163000480E1001890E30000382100104E8000207D66503090C3000427
+S3250001C34038E000207CEA38507D673C3080A100187CA550307CE72B7890E3000038210010A4
+S3250001C3604E80002080C1000880A100107CC6283890C300008081000C810100147C8440383E
+S3250001C380908300044E8000208101000880E100107D083B789103000080C1000C80A1001448
+S3250001C3A07CC62B7890C300044E80002080A10008812100107CA54A7890A300008101000CCD
+S3250001C3C080E100147D083A78910300044E8000208121000880E9000090E300008089000491
+S3250001C3E09083000480C9000438C6000190C90004808900047C0400004082001080A90000EE
+S3250001C40038A5000190A900004E8000208121000880C9000090C300008109000491030004A4
+S3250001C420810900047C08000040820010808900003884FFFF90890000808900043884FFFF6E
+S3250001C440908900044E800020812100087C6A1B7880A9000438A5000190A9000481090004D1
+S3250001C4607C0800004082001080890000388400019089000080890000908A000080C9000410
+S3250001C48090CA00044E800020812100087C6A1B7880E900047C0700004082001081090000DA
+S3250001C4A03908FFFF91090000810900043908FFFF9109000481090000910A000080A90004DF
+S3250001C4C090AA00044E8000207FE802A697E1FFD0814100388121003C90610034390100207C
+S3250001C4E08083000080A300049088000090A8000480A100402C0500064181029C4182023CBE
+S3250001C5002C05000341810164418201002C050001418200942C05000241820030480010D915
+S3250001C5208101003438A1002080C5000080E5000490C8000090E8000483E100007FE803A64F
+S3250001C540382100304E80002088AA000090A1002C7C07037890E1002838610020390100083C
+S3250001C5603881002880A4000080C4000490A8000090C8000438C1001038E1004481070000E5
+S3250001C5808087000491060000908600047D2803A64E80002180C100388101002499060000DD
+S3250001C5A04BFFFF8088AA00007CA5077490A1002C80E1002C54E70FFE90E100283861002059
+S3250001C5C038A1000838C1002880E600008106000490E500009105000439010010388100440B
+S3250001C5E080A4000080C4000490A8000090C800047D2803A64E8000218101003880A10024F8
+S3250001C60098A800004BFFFF1CA90A00009101002C80A1002C54A50FFE90A100283861002098
+S3250001C620390100083881002880A4000080C4000490A8000090C8000438C1001038E100446A
+S3250001C640810700008087000491060000908600047D2803A64E80002180C100388101002433
+S3250001C660B10600004BFFFEBC2C050004418200702C050005418200084BFFFEA4808A000099
+S3250001C6809081002C8081002C54840FFE908100283861002038E100083901002880880000C7
+S3250001C6A080A800049087000090A7000438A1001038C1004480E600008106000490E5000069
+S3250001C6C0910500047D2803A64E80002180A1003880E1002490E500004BFFFE48A10A0000EE
+S3250001C6E09101002C7C05037890A100283861002038C1000838E10028810700008087000492
+S3250001C70091060000908600043881001038A1004480C5000080E5000490C4000090E4000401
+S3250001C7207D2803A64E8000218081003880C10024B0C400004BFFFDEC808A00009081002C29
+S3250001C7407C040378908100283861002038A1000838C1002880E600008106000490E500007D
+S3250001C76091050004390100103881004480A4000080C4000490A8000090C800047D2803A683
+S3250001C7804E8000218101003880A1002490A800004BFFFD902C050007418200DC2C05000885
+S3250001C7A0418200D42C0500094182006C2C05000A418200084BFFFD6880CA000090C1002CF6
+S3250001C7C07C06037890C100283861002038E10008390100288088000080A800049087000055
+S3250001C7E090A7000438A1001038C1004480E600008106000490E50000910500047D2803A683
+S3250001C8004E80002180A1003880E1002490E500004BFFFD1080CA000090C1002C80C1002C44
+S3250001C82054C60FFE90C10028386100203881000838A1002880C5000080E5000490C40000D4
+S3250001C84090E4000438E10010390100448088000080A800049087000090A700047D2803A6DE
+S3250001C8604E80002180E1003880810024908700004BFFFCB0386100203881000880AA000053
+S3250001C88080CA000490A4000090C4000438C1001038E1004481070000808700049106000027
+S3250001C8A0908600047D2803A64E80002180C10038390100208088000080A8000490860000FD
+S3250001C8C090A600044BFFFC5C3821FFF081010018910300047C06037890C300003821001042
+S3250001C8E04E8000203821FFF081010018910300047D06FE7090C30000382100104E8000202E
+S3250001C9003821FFF080A1001890A300047C08037891030000382100104E8000203821FFF026
+S3250001C92080A1001890A300047CA8FE7091030000382100104E8000203821FFF080E1001842
+S3250001C94090E300047C05037890A30000382100104E8000203821FFF080E1001854E7801E39
+S3250001C9607CE88670910300047D06FE7090C30000382100104E8000203821FFF080A10018A2
+S3250001C98070A5FFFF90A300047C04037890830000382100104E8000203821FFF080C1001840
+S3250001C9A054C6C00E7CC7C67090E300047CE5FE7090A30000382100104E8000203821FFF0F7
+S3250001C9C080810018708400FF908300047C08037891030000382100104E8000203821FFF0FB
+S3250001C9E080810018708400FF5483C00E7C63C670382100104E80002080610008706300FF58
+S3250001CA004E8000203821FFF0808100187084FFFF5483801E7C638670382100104E8000202D
+S3250001CA20806100087063FFFF4E800020806100084E800020806100084E80002080610008B0
+S3250001CA404E800020806100084E800020810100087C0800004082001880A100047C0500007C
+S3250001CA604082000C7C0303784E800020386000014E80002080E10008808100107C07200055
+S3250001CA804082001480C100048101000C7C0640004182000C7C0303784E80002038600001D4
+S3250001CAA04E80002080A1000880E100107C0538004082001C8081000480C1000C7C0430004E
+S3250001CAC04082000C7C0303784E800020386000014E8000208101000480A1000C7C082800B3
+S3250001CAE04180002480E100048081000C7C0720004082001C80C10008810100107C0640407A
+S3250001CB004080000C386000014E8000207C0303784E80002080A1000480E1000C7C05380088
+S3250001CB20418000248081000480C1000C7C0430004082001C8101000880A100107C08284082
+S3250001CB404181000C386000014E8000207C0303784E80002080E100048081000C7C0720007C
+S3250001CB604181002480C100048101000C7C0640004082001C80A1000880E100107C053840C2
+S3250001CB804081000C386000014E8000207C0303784E8000208081000480C1000C7C04300050
+S3250001CBA0418100248101000480A1000C7C0828004082001C80E10008808100107C072040EE
+S3250001CBC04180000C386000014E8000207C0303784E80002080C100048101000C7C0640403D
+S3250001CBE04180002480A1000480E1000C7C0538004082001C8081000880C100107C043040D6
+S3250001CC004080000C386000014E8000207C0303784E8000208101000480A1000C7C08284033
+S3250001CC204180002480E100048081000C7C0720004082001C80C10008810100107C06404038
+S3250001CC404181000C386000014E8000207C0303784E80002080A1000480E1000C7C05384005
+S3250001CC60418100248081000480C1000C7C0430004082001C8101000880A100107C08284040
+S3250001CC804081000C386000014E8000207C0303784E80002080E100048081000C7C072040FC
+S3250001CCA04181002480C100048101000C7C0640004082001C80A1000880E100107C05384081
+S3250001CCC04180000C386000014E8000207C0303784E8000208121000C814100088081001484
+S3250001CCE080A100107CC921D67CE920167D0451D67CE742147D0549D67CE7421490C3000413
+S3250001CD0090E300004E8000208881000B3863FFFF8CC300017C062000418200107C060000B7
+S3250001CD204082FFF07C0303784E800020906100048081000C7C0400004081007C80A100086B
+S3250001CD4054A5063E50A5442E50A5801E7CA62B787CA72B787CA82B782C04001040810050F2
+S3250001CD607069000741820018212900087D2103A67CA01D2A7C634A147C8920507C892671A7
+S3250001CD804081002C7D2903A690A300003943000890C3000490EA0000386A0008910A00047F
+S3250001CDA04200FFE85484073F4182000C7C8103A67CA01D2A806100044E8000209061000485
+S3250001CDC08121000C7C6A1B787C090000418200A841800184816100082C0900104081008C73
+S3250001CDE07DAB4A147D8A4A147C0A5840418100CC7D67527870E7000340820084714700038C
+S3250001CE004182002020E700047D2748507CE103A67E005C2A7D6B3A147E00552A7D4A3A148F
+S3250001CE207D2E2671408100447DC903A6396BFFFC394AFFFC860B0004960A0004862B0004AA
+S3250001CE40962A0004860B0004960A0004862B0004962A00044200FFE05529073F4182001895
+S3250001CE60396B0004394A00047D2103A67E005C2A7E00552A806100044E8000207D2E26711F
+S3250001CE80408100247DC903A67E0B84AA396B00107E0A85AA394A00104200FFF05529073F0D
+S3250001CEA04182FFD47D2103A67E005C2A7E00552A806100044E8000202C090004418000843C
+S3250001CEC07DA7627870E700034082007871A70003418200188E0DFFFF9E0CFFFF3929FFFF22
+S3250001CEE071A700034082FFF07D2E2671408100347DC903A6860DFFFC960CFFFC862DFFFC60
+S3250001CF00962CFFFC860DFFFC960CFFFC862DFFFC962CFFFC4200FFE05529073F4182FF58B8
+S3250001CF207D2E16714081001C7DC903A6860DFFFC960CFFFC4200FFF8552907BF4182FF384A
+S3250001CF407C0D58404081FF308E0DFFFF9E0CFFFF4BFFFFF090000000806100044E800020DC
+S3250001CF604BFFFE5C3821FFD08281003881C1003C7C731B787C6B1B787C1203787C0D03781C
+S3250001CF807C1003787C0F0378888B00007C8407742C04000C41810268418202502C04000939
+S3250001CFA0418202482C04000A418202402C04000B4182023888CB00007CC607742C06002D77
+S3250001CFC04182020888EB00007CE707742C07002B418201F87C0E00004082001888AB00007B
+S3250001CFE07CA507742C050030418201B039C0000A2C0E0002418000782C0E002441810070B1
+S3250001D0002C0E00104082001488EB00007CE707742C070030418200F07C0D037838A0FFFFA8
+S3250001D0207E25739688CB00007CC607747CCA33787DCC73782C0600304180000C2C0A00396A
+S3250001D040408100BC2C0A00614180000C2C0A007A408100A42C0A00414180000C2C0A005AFF
+S3250001D0604081008C7C0C7000418000547C100000408200087E6B9B787C14000041820008A2
+S3250001D080917400007C0F0000418200103860FFFF382100304E8000207C12000041820014B4
+S3250001D0A07C0303787C6D1850382100304E8000207DA36B78382100304E8000207C0D8840DC
+S3250001D0C04081000839E000017CAD71D67D4562147C0A68404080000839E000017D4D537819
+S3250001D0E0396B00013A1000014BFFFF3C398AFFC94BFFFF74398AFFA94BFFFF6C398AFFD0BA
+S3250001D1004BFFFF64890B00017D0807742C08007841820018888B00017C8407742C04005828
+S3250001D120418200084BFFFEF488AB00027CA507742C0500304180001C88CB00027CC60774C0
+S3250001D1402C0600394181000C396B00024BFFFECC88EB00027CE707742C0700614180001419
+S3250001D160890B00027D0807742C0800664081FFDC888B00027C8407742C0400414180FE9C80
+S3250001D18088AB00027CA507742C0500464181FE8C396B00024BFFFE8439C00008890B0001EC
+S3250001D1A07D0807742C08007841820018888B00017C8407742C040058418200084BFFFE3483
+S3250001D1C039C000104BFFFE2C7D685B78396B0001890800007D0807742C08002D4082FDF8C5
+S3250001D1E03A4000014BFFFDF0396B0001888B00007C8407742C04000C4081FDA02C04000D6C
+S3250001D2004182FFE82C0400204182FFE04BFFFDA87FE802A697E1FFD8814100309061002C0F
+S3250001D22088AA00007CA5077490A100207C0500004082001483E100007FE803A6382100287C
+S3250001D2404E8000207D435378480001819061001C8061002C80A1002090A100084BFFFAADFF
+S3250001D2607C691B787C0900004182005C7D234B789121002480810030908100088101001C6A
+S3250001D2809101000C480000CD812100247C030000408200187D234B7883E100007FE803A6DE
+S3250001D2A0382100284E8000203869000180C1002090C100084BFFFA557C691B787C09000006
+S3250001D2C04082FFAC7C03037883E100007FE803A6382100284E8000207FE802A697E1FFE88F
+S3250001D2E07C691B7880A100207C050000408200247D234B787C080378910100084BFFFA0DBA
+S3250001D30083E100007FE803A6382100184E8000207C040378908100147D234B78810100200E
+S3250001D320910100084BFFF9E57C0300004182001039230001906100144BFFFFE08061001452
+S3250001D34083E100007FE803A6382100184E8000203821FFF081A100188141001C7C6C1B7818
+S3250001D3607C0A0000408100587D896378398C0001892900007D2907747DAB6B7839AD00019B
+S3250001D380896B00007D6B0774394AFFFF7C095800418200247C095840408100103860000163
+S3250001D3A0382100104E8000203860FFFF382100104E8000207C0900004082FFA87C0303783A
+S3250001D3C0382100104E8000207FE802A697E1FFF0906100147C07037890E100084BFFF92D8D
+S3250001D3E0810100147C68185083E100007FE803A6382100104E8000207FE802A697E1FFE013
+S3250001D400814100287C691B789061001C7D234B789121002491410028914100087C0803788A
+S3250001D4209101000C3900271091010010480001617C0300004082001880A100243925271058
+S3250001D44081010028394827104BFFFFC48061001C83E100007FE803A6382100204E8000207E
+S3250001D4603821FFF0818100187C6B1B787D695B78396B0001892900007D2907747D8A6378B6
+S3250001D480398C0001894A00007D4A07747C095000418200247C09504040810010386000016F
+S3250001D4A0382100104E8000203860FFFF382100104E8000207C0900004082FFB47C0303782D
+S3250001D4C0382100104E8000203821FFE8812100247C6D1B78818100207C0900404081005074
+S3250001D4E07DAB6B7839AD0001896B00007D8A6378398C0001894A00007C0B50004182002406
+S3250001D5007C0B50404081001038600001382100184E8000203860FFFF382100184E8000202F
+S3250001D5203929FFFF7C0900404181FFB87C030378382100184E8000203821FFF08121001CE7
+S3250001D5407C6A1B7880E1001870EB00FF7C090040408100307D475378394A000188E7000040
+S3250001D5607C07580040820010386AFFFF382100104E8000203929FFFF7C0900404181FFD842
+S3250001D5807C030378382100104E8000203821FFF0812100207C6A1B78816100188081001C99
+S3250001D5A0708C00FF7C090040408100407D465378394A00017D645B78396B0001888400002C
+S3250001D5C0988600005484063E7C046000408200107D435378382100104E8000203929FFFF16
+S3250001D5E07C0900404181FFC87C030378382100104E8000207C040378808400007C04000006
+S3150001D600418200084BFFFFF04E8000200000000021
+S3250001D61000810E02001415F0001403E80000000000146530000000010000000000000000A0
+S3250001D6300000000000000000FFFFFFFF0000001E0000001D0000001C0000001B0000000065
+S3250001D6500000000000000000000000000000000000000000000000000000000000000000B3
+S3250001D670000000000000000000000000000000000000000000000000000000000000000093
+S3250001D690FFFFFFFF00000A0000000A2000000A4000000A6000140104000000000000000076
+S3250001D6B0000000000000000000000000000000012A2A2A000000000023706C616E392E6936
+S3250001D6D06E690A00000000005250587369676E61747572653D312E300A4E414D453D71627F
+S3250001D6F0727063670A53544152543D46464332303130300A56455253494F4E3D312E310AC9
+S3250001D710000000000001000000000401080205030C06060909070710100000000000000082
+S3250001D7306672656562007167657400000000000000141BAF0000000000000000000000003F
+S3250001D7500000000000000000000000000000000000000000000000000000000000000000B2
+S3250001D770000000000000000000000000000000000000000000000000000000000000000092
+S3250001D79000000000000000000000000000000000626F6F74006469736B00626F6F740075EA
+S3250001D7B06172743A207374617274207472616E736D697373696F6E0A00756172743A2074A5
+S3250001D7D0696D656F75740A006E007900000000000000000000000000001403200000000077
+S3250001D7F0000000000000000000000000000000000000000000000000000000000000000012
+S3250001D8100000000000000000000000000000000000000000000000000000000000000000F1
+S3250001D8300000000000000000FFC206F000000000000000000000000000000000000000001A
+S3250001D8500000000000000000000000000000000000000000000000000000000000000000B1
+S3250001D87000000000000000000000000000000000000000000000000000141A00FFC26E38FC
+S3250001D89000141A04FFC26E3800000000000000006D6170667265653A2025733A206C6F735E
+S3250001D8B0696E672030782575582C2025640A000000141A9300141AA700141AB300141AC312
+S3250001D8D0000000000014054000000000000000006E6577616C61726D000000000000000081
+S3250001D8F00000000000000000F1A55A1FFFC2363000000000000000000000000000000000DB
+S3250001D9100000000000000000FFFFFFFF0000000000000004000000080000000C00000000DC
+S3250001D9306275666665722064657363726970746F7273006264616C6C6F63000000000000B3
+S3250001D95000141A810000000000141A860000000100141A8C00000002000000000000000090
+S3250001D970FFFFFFFFFFFF000000000000000000000000000000000000000000000000000096
+S3250001D9900000000000000000000000000000000000000000000000000000000013880000D5
+S3250001D9B0FFFFFFFFFA203C00FA203D00FA203E00FA203F000000000000141FD70014203B7D
+S3250001D9D06932632073657475702E2E2E0A004932432325780A0000000000000B00000000BA
+S3250001D9F0000000000000000000140E4000000000000000200000000000000000000000008E
+S3250001DA10000004000000000E0000000000000000000004000000000E0000000000000000CB
+S3250001DA3041F0000000000000001407460014074C0014075100140754001407580014075B12
+S3250001DA500014075E0014076200140766001407690014076C0014076F001407720014077586
+S3250001DA70001407780014077B0014077E0014078100140784001407880014078C001407909D
+S3250001DA9000140794001407980014079C001407A0001407A4001407A8001407AC001407B087
+S3250001DAB0001407B4001407B8001407BC001407C0001407C4001407C8001407CC001407D067
+S3250001DAD0001407D4001407D8FFC24714FFC2474CFFC24798FFC247BCFFC247C4FFC247CCD9
+S3250001DAF0FFC247F0FFC24830FFC24838FFC2485CFFC2488C000000000000000000000000A3
+S3250001DB100000000000000000000000000000000000000000000000000000000000000000EE
+S3250001DB300000000000000000000000000000000000000000000000000000000000000000CE
+S3250001DB507072656D617475726520454F460A002E00626164206D61676963203078256C7591
+S3250001DB7078206E6F74206120706C616E20392065786563757461626C65210A002564002BDF
+S3250001DB9025644025382E386C7578002B25640A7374617274206174203078256C75780A0058
+S3250001DBB000000000000000000000000000000000000000000000000000000000000000004E
+S3250001DBD000000000000A000000000000000000000000000000000000000000000000000024
+S3250001DBF0000000000000000000000000000000000000000000000000090000000000000005
+S3250001DC100000000102000000030000000400000500000006000700000800000000000000C9
+S3250001DC30726573657276656420300073797374656D207265736574006D616368696E652040
+S3250001DC50636865636B00646174612061636365737300696E737472756374696F6E206163DD
+S3250001DC70636573730065787465726E616C20696E7465727275707400616C69676E6D656E24
+S3250001DC90740070726F6772616D20657863657074696F6E00666C6F6174696E672D706F6949
+S3250001DCB06E7420756E617661696C61626C650064656372656D656E74657200726573657218
+S3250001DCD0766564204100726573657276656420420073797374656D2063616C6C0074726123
+S3250001DCF06365207472617000666C6F6174696E6720706F696E742061737369737400726542
+S3250001DD10736572766564204600736F66747761726520656D756C6174696F6E0049544C4279
+S3250001DD30206D6973730044544C42206D6973730049544C42206572726F720044544C422033
+S3250001DD506572726F72004341555345005352523100504300474F4B004C52004352005845A5
+S3250001DD7052004354520052300052310052320052330052340052350052360052370052389B
+S3250001DD900052390052313000523131005231320052313300523134005231350052313600E7
+S3250001DDB052313700523138005231390052323000523231005232320052323300523234008D
+S3250001DDD0523235005232360052323700523238005232390052333000523331007365746866
+S3250001DDF0766563006F7574206F6620696E746572727570742068616E646C6572730025736B
+S3250001DE1009252E386C757809257309252E386C75780A00657863657074696F6E2F696E741D
+S3250001DE30657272757074202325780A00657863657074696F6E2025730A005E5020746F20DD
+S3250001DE5072657365740A00005573696E6720666C61736820636F6E66696775726174696F20
+S3250001DE706E0A000A002573256400747970653D00706F72743D006972713D006D656D3D00E2
+S3250001DE9073697A653D0065613D00000000000000676574636C75737420402025640A00678B
+S3250001DEB06574636C75737420256420696E2063616368650A00676574636C75737420616439
+S3250001DED064722025640A0063616E2774207365656B20626C6F636B0A0063616E2774207279
+S3250001DEF065616420626C6F636B0A00676574636C75737420256420726561640A0066617497
+S3250001DF1077616C6B2025640A006765746661740066617477616C6B202564202D3E20256446
+S3250001DF300A0066696C65616464722025382E38732025640A0066696C656164647220256498
+S3250001DF50202D3E2025640A0066696C6561646472202564202D3E2025640A0077616C6B6932
+S3250001DF706E67206E6F6E2D6469726563746F7279210A00636F6D706172696E6720746F203A
+S3250001DF9025382E38732E25332E33730A0025382E38732E25332E33732069732061204C4116
+S3250001DFB042454C0A0063616E2774207265616420626F6F7420626C6F636B0A006E6F74206A
+S3250001DFD0444F530A006E6F20646F732066696C652073797374656D0A006D616769633A200D
+S3250001DFF0307825322E327820307825322E327820307825322E32780A0076657273696F6E35
+S3250001E0103A202225382E3873220A007365637473697A653A2025640A00616C6C6F637369CD
+S3250001E0307A653A2025640A006E72657372763A2025640A006E666174733A2025640A0072F5
+S3250001E0506F6F7473697A653A2025640A00766F6C73697A653A2025640A006D656469616452
+S3250001E0706573633A20307825322E32780A0066617473697A653A2025640A0074726B736903
+S3250001E0907A653A2025640A006E68656164733A2025640A006E68696464656E3A2025640A76
+S3250001E0B000626967766F6C73697A653A2025640A0064726976656E6F3A2025640A00726563
+S3250001E0D0736572766564303A20307825322E32780A00626F6F747369673A20307825322EB7
+S3250001E0F032780A00766F6C69643A20307825382E38780A006C6162656C3A20222531312EBF
+S3250001E110313173220A006E616D6520636F6D706F6E656E7420746F6F206C6F6E670A0065A2
+S3250001E13072726F722077616C6B696E6720746F2025730A002573206E6F7420666F756E64EC
+S3250001E1500A00666F756E642025382E38732E25332E3373206174747220307825757820738A
+S3250001E17074617274203078256C7578206C656E2025640A00626164206D6167696320307865
+S3250001E190256C7578206E6F74206120706C616E20392065786563757461626C65210A002B3C
+S3250001E1B02564002B2564002B25640A7374617274206174203078256C75780A002E006E61DD
+S3250001E1D06D652069732025382E38732025332E33730A0000000000002E007A71733A206E5A
+S3250001E1F06F7420706F77657250432065786563757461626C650A0074657874007A71733A9C
+S3250001E21020666F726D6174206572726F720A0064617461007A71733A20666F726D617420EF
+S3250001E2306572726F720A000A73717565657A6564206B65726E656C3A20636865636B737542
+S3250001E2506D206572726F723A2025382E386C7578206E6565642025382E386C75780A007503
+S3250001E2706E7061636B2025732025382E386C757820256C75643A00202A2A73697A6520650E
+S3250001E29072726F720A000A007A71733A20636F72727570742073717565657A65642064615C
+S3250001E2B074612073747265616D0A00205425640025642025382E386C75782025382E386CAB
+S3250001E2D075780A0000000000666C6173683A2062616420636865636B73756D0A00666C61F1
+S3250001E2F073683A20666C617368206E6F742070726573656E74206F72206E6F7420656E616C
+S3250001E310626C65640A00636F6E66202325382E386C75783A20232578202325362E366C7543
+S3250001E330780A00666C6173683A20666F756E6420636F6E6669672025382E386C75782825A1
+S3250001E35064293A0A25730A00666C6173683A206E6F20636F6E6669670A00666C6173682020
+S3250001E370636F6E6669672025382E386C7578282564293A0A25730A00666C6173683A207339
+S3250001E390717565657A656420706F7765727063206B65726E656C20696E7374616C6C6564D2
+S3250001E3B00A00666C6173683A20756E73717565657A656420706F7765727063206B65726E9B
+S3250001E3D0656C20696E7374616C6C65640A00666C6173683A206E6F20706F776572706320E6
+S3250001E3F06B65726E656C20696E20466C6173680A00746578743A2025382E386C7578203CDF
+S3250001E4102D2025382E386C7578205B256C645D0A00646174613A2025382E386C7578203C39
+S3250001E4302D2025382E386C7578205B256C645D0A00656E7472793D3078256C75780A0000E6
+S3250001E450907070F0F0F07000F0888888F8707070E0E0E0E0E09070F070F870F0F870F0882D
+S3250001E470000000000000000000000000000000000000000000000000000000000000000085
+S3250001E490000000000000000000000000000000000000000000000000000000000000000065
+S3250001E4B000000000000000000000000000000000000000000000000000000000000000E065
+S3250001E4D0D0808080808088008888C888808888889090909090D0808080808080808888881D
+S3250001E4F000000000080000000C3000000000000600000000000000000000000000000000BB
+S3250001E5100000000000000000000000000000000000000000000000000000003CC03C0000AC
+S3250001E5300000600006001E00601818607800000000000000000000000000001C18380090DC
+S3250001E550B06060E0E0E0F800F088A888808080809090909090B060E0808060E080808888E4
+S3250001E570001824283E70701818180000000000063C183C3C1C3E3C7E3C3C00000200403CDE
+S3250001E5903C187C1E787E7E1E663C7C666066623C7C3C7C3C7E6266C266667E30C00C10002E
+S3250001E5B008006000060030006018186018000000000000001000000000000030180C0090AA
+S3250001E5D0901010808080881888F8A888E0807070E0E0E0E0E090108070E01080E098F08814
+S3250001E5F0001824286ADAD818181810000000000C663866662C3E667E6666000006006066D0
+S3250001E610421866326C606032661818646066722466246666186262DA62620630600C380093
+S3250001E63010006000060030006000006018000000000000003000000000000030180C00E0E1
+S3250001E65000E0E0F0F0F000188888985080880808201C1C1C1C00E0F00080E0F08088888823
+S3250001E6700018242868DAD808300C54180000000C665806062C206002666618180CFE300695
+S3250001E6909E2C6660666060606618186C6066726666666660186262DA36660C30600C2800F9
+S3250001E6B0103C6C3C3E3C7E3E6C78786618D46C3C6C3E763C7E6666C266667E1818180000C9
+S3250001E6D04418000018241C24F08888208070F0F020202020201C243E1CF8241C8070887001
+S3250001E6F00018247C78745008300C381800000018661806064C2060067666181818FE180CC1
+S3250001E710B62C66606660606066181868607E5A6666666470186266DA34340C30300C6C0072
+S3250001E73018667666666630667618186418FE766676663666306662DA626206081810323C58
+S3250001E75044247C7C2434204200000000000000002020202020222408220024200000000034
+S3250001E770001800283C287610300CEE7E00FE001866180C184C3C7C0C3C3E000030000C181A
+S3250001E790B62C7C60667C7C6E7E181878605A5A666466783C186234DA18341830300C44001E
+S3250001E7B018066660666630666618186818D6666666663860306662DA34620C30180C5A209E
+S3250001E7D044241010242C20420E3E103E3E3C1C3E3C1C1C1C1C3E1C083E2224180E0E0E0E98
+S3250001E7F00008007C1E5CDC00300C387E00FE0030661818067E0666186E06000018001818AE
+S3250001E810B67E6660666060666618186C605A4E6678666C0E1862346C2C183030180C44006D
+S3250001E830003E6660667E30666618187818D666666666303C306634DA1834180818104C3887
+S3250001E8503C18101018241C4211081008202222080000000000220408223618041111111110
+S3250001E8700000002816B6CC00300C541800000030661830067E066618660600000CFE30008D
+S3250001E8909A466660666060666618186C605A4E66606666061862346C6C183030180C00006B
+S3250001E8B000666660666030666618186C18D66666666630063066346C2C34301818180020CD
+S3250001E8D000091010000E094210081008202222080F06060F0A09041E002A0E3810101010F4
+S3250001E8F00018002856B6CC00300C10181800186066187E660C6666306666181806FE601813
+S3250001E910404666326C60603666181866605A4624602466661834186C461860300C0C00001A
+S3250001E930006E66666E66306E6618186618D66666666E3066306E186C46186030180C003C84
+S3250001E950080909091F110AFF0E081008382C2208080209010A0A0911092209070E0E0E0ED3
+S3250001E970001800287C1C760018180000180018603C7E7E3C0C3C3C303C3C18180200401848
+S3250001E9903E467C1E787E601E663C18667E42463C603C663C1818186C66187E300C0C000036
+S3250001E9B000367C3C363C7C36667E18667ED6663C7C367C3C1E36186C66187E30180C00083C
+S3250001E9D0080F060604110C1801081008202222080E0202030A0C0D1E0D220E080101010198
+S3250001E9F0000000001000000018180000080000C000000000000000000000000800000000F0
+S3250001EA1000000000000000000000180000000000000C00000000000000000030060C00FE7B
+S3250001EA300000000000000006000018000000000060060000000000000010001C18380008B7
+S3250001EA5008090606040E0A1811081F0820221C3E080204010F0A0B110B22090811111111AC
+S3250001EA7000000000000000000C300000080000C00000000000000000000000080000000073
+S3250001EA900000000000000000000070000000000000060000000000000000003C063C00006B
+S3250001EAB0000000000000006600001800000000006006000000000000003000000000000823
+S3250001EAD00F090909040309000E000000000000000F0F0F0F0209091E09000F070E0E0E0E12
+S3250001EAF00000000000000000000000001000000000000000000000000000001000000000DF
+S3250001EB100000000000000000000000000000000000000000000000000000000000000000DE
+S3250001EB30000000000000003C00007000000000006006000000000000006000000000000F3D
+S3250001EB50636F6E736F6C65006C63640073637265656E006C63640062617564005E70002536
+S3250001EB70735B64656661756C743D3D25735D3A200025733A20000A006C696E6520746F6FEC
+S3250001EB90206C6F6E670A0070616E69633A20000A0000000000000000001406200014062B96
+S3250001EBB000140638001406460014065200140665001406780014068200140694001406AFFC
+S3250001EBD0001406BB001406C6001406D1001406DD001406E8001406FE001407090014071C12
+S3250001EBF000140726001407300014073B000000000000000E000800000008000E00080000E8
+S3250001EC100010000E000800000018000E000800000020000E000800000028000E0008000015
+S3250001EC300030000E000800000038000E000800000040000E000800000048000E0008000075
+S3250001EC500050000E000800000058000E000800000060000E000800000068000E00080000D5
+S3250001EC700070000E000800000078000E000800000080000E000800000088000E0008000035
+S3250001EC900090000E000800000098000E0008000000A0000E0008000000A8000E0008000095
+S3250001ECB000B0000E0008000000B8000E0008000000C0000E0008000000C8000E00080000F5
+S3250001ECD000D0000E0008000000D8000E0008000000E0000E0008000000E8000E0008000055
+S3250001ECF000F0000E0008000000F8000E0008000001000000000800000108020B00080000C2
+S3250001ED1001100206000800000118020B000800000120010C000800000128020B0008000019
+S3250001ED300130020B0008000001380207000800000140010D000800000148010D0008000076
+S3250001ED500150030A000800000158040A000800000160090E000800000168060800080000C8
+S3250001ED700170090B000800000178010D000800000180020B000800000188020B000800002C
+S3250001ED900190020B000800000198020B0008000001A0020B0008000001A8020B0008000094
+S3250001EDB001B0020B0008000001B8020B0008000001C0020B0008000001C8020B00080000F4
+S3250001EDD001D0040B0008000001D8040E0008000001E0020B0008000001E8040A000800004C
+S3250001EDF001F0020B0008000001F8020B000800000200020B000800000208020B00080000B2
+S3250001EE100210020B000800000218020B000800000220020B000800000228020B000800000F
+S3250001EE300230020B000800000238020B000800000240020B000800000248020B000800006F
+S3250001EE500250020D000800000258020B000800000260020B000800000268020B00080000CD
+S3250001EE700270020B000800000278020B000800000280020B000800000288020D000800002D
+S3250001EE900290020B000800000298020B0008000002A0020B0008000002A8020B000800008F
+S3250001EEB002B0020B0008000002B8020B0008000002C0020B0008000002C8020B00080000EF
+S3250001EED002D0020B0008000002D8010D0008000002E0010D0008000002E8010D000800004C
+S3250001EEF002F002080008000002F80B0C0008000003000207000800000308040B00080000A8
+S3250001EF100310010B000800000318040B000800000320010B000800000328040B0008000008
+S3250001EF300330010B000800000338040E000800000340010B000800000348010B0008000068
+S3250001EF500350010E000800000358010B000800000360010B000800000368040B00080000C8
+S3250001EF700370040B000800000378040B000800000380040E000800000388040E000800001C
+S3250001EF900390040B000800000398040B0008000003A0020B0008000003A8040B0008000084
+S3250001EFB003B0040B0008000003B8040B0008000003C0040B0008000003C8040E00080000DF
+S3250001EFD003D0040B0008000003D8010C0008000003E0010C0008000003E8010C0008000048
+S3250001EFF003F005080008000003F8000E000800000400000E000800000000000000000000C7
+S3250001F010534343005343433200657468657225643A2025733A20706F7274203078256C7575
+S3250001F0305820697271202564002061646472203078256C7558002073697A65203078256C37
+S3250001F0507558003A002025322E327558000A00657468657225643A207478207175657565B8
+S3250001F0702066756C6C0A0000666C6173680046006574686572006500617461006864006861
+S3250001F090006175746F006C6F63616C006D616E75616C00696E6665726E6F2F696E666572E3
+S3250001F0B06E6F2E696E6900696E6665726E6F2E696E6900706C616E392F706C616E392E6901
+S3250001F0D06E6900706C616E392E696E69002100002573212564006469736B002573212564A0
+S3250001F0F0212573006469736B00696D706300257321256421257300626F6F74006469736B92
+S3250001F11000646F73006469736B00646F7320696E6974206661696C65640A00707265646132
+S3250001F130776E0A006461776E0A006F7074696F6E733D232575780A00466C61736820626FAE
+S3250001F1506F740A00626F6F7466696C650042616420626F6F7466696C652073796E74617815
+S3250001F1703A2025730A0043616E6E6F7420616363657373206465766963653A2025730A00FB
+S3250001F190426F6F7420646576696365733A00202573212564002025732125640020257321EA
+S3250001F1B02564000A00626F6F742066726F6D00706879736963616C206D656D6F727900699E
+S3250001F1D0616C6C6F63006672656500000000000045544845522E5343432325643A20736310
+S3250001F1F06365203D2030782575580A007E0040006E6F207072657365742045746865722089
+S3250001F210616464726573730A00303031303862663132393030006574686572204D41432001
+S3250001F2306164647265737300696E76616C6964204D414320616464726573730A00000000E9
+S3250001F2500A746674703A206572726F72282564293A2025730A0069702063686B73756D20D1
+S3250001F2706572726F720A0069702062616420766572732F686C656E0A007564702063686BC4
+S3250001F29073756D206572726F72206373756D202325346C7578206C656E2025640A00756400
+S3250001F2B0703A207061636B657420746F6F206269670A002573006F637465740074667470B2
+S3250001F2D06F70656E3A206572726F7220282564293A2025730A00746674706F70656E3A2021
+S3250001F2F0626C6F636B206572726F723A2025640A00626C6F636B206572726F720074667412
+S3250001F310706F70656E3A206661696C656420746F20636F6E6E65637420746F207365727605
+S3250001F33065720A0074667470726561643A20256420213D2025640A0073686F727420726540
+S3250001F3506164003F0074667470726561643A20626C6F636B206572726F723A2025642C205A
+S3250001F37065787065637465642025640A00626C6F636B206572726F7200696E76616C696435
+S3250001F3902063746C726E6F2025640A00626F6F74702074696D6564206F75740A0025732060
+S3250001F3B0002825642E25642E25642E2564212564293A2025730A00626164206D6167696349
+S3250001F3D0206E756D626572006C6F61644025382E386C75783A20002564002B2564006F6B00
+S3250001F3F0002B25643D25640A00656E7472793A203078256C75780A000000000000141A6820
+S3250001F41000000008FFC27AE40000000000000000000000000000000000141A6E0000000012
+S3250001F43000000000000000000000000200141A7000000004FFC26068000000000000000088
+S3250001F45000000000000000000000000000141A7600000000000000000000000300141A7848
+S3250001F470000000130000000000000000000000000000000000141A7C00141A7F000000000B
+S3250001F4900000000000000000FFFFFFFF000000000000000000000000000000000000000059
+S3250001F4B0000000000000000000000000000000000000000000000000496E6665726E6F2044
+S3250001F4D0626F6F7473747261700A005056523A20004D5043363031004D5043363033004D9E
+S3250001F4F05043363034004D504336303365004D5043363033652D7637004D5043387878002A
+S3250001F510506F77657250432076657273696F6E20232578002C207265766973696F6E202330
+S3250001F530256C75780A00494D4D523A20004D50433836302F383231004D5043383233004D8B
+S3250001F55050433832334100547970652023256C7578002C206D61736B2023256C75780A00FD
+S3250001F5706F7074696F6E733A2023256C75780A00626373723A2025382E386C75780A0050E9
+S3250001F5904C505243523D25382E386C757820534343523D25382E386C75780A00256C756460
+S3250001F5B0204D487A2073797374656D0A000A004252303D25382E386C7578204F52303D25BC
+S3250001F5D0382E386C75780A004D505450523D25382E386C75780A006574686572303D7479AB
+S3250001F5F070653D53434320706F72743D312065613D3030313065633030303035310D0A7657
+S3250001F610676173697A653D3634307834383078380D0A6B65726E656C70657263656E743DEF
+S3250001F63034300D0A636F6E736F6C653D300D0A626175643D393630300D0A006574686572EA
+S3250001F650303D747970653D53434320706F72743D322065613D303031306563303030303559
+S3250001F670310D0A76676173697A653D3634307834383078380D0A6B65726E656C7065726355
+S3250001F690656E743D34300D0A636F6E736F6C653D300D0A626175643D393630300D0A0055C9
+S3250001F6B073696E672064656661756C7420636F6E66696775726174696F6E0A00414D4432D7
+S3250001F6D039463078300053434300454100693263206661696C65640A00656570726F6D3A0E
+S3250001F6F00A002025322E3275785B25635D000A00CFFFCC240FFFCC040CAFCC0403AFCC082E
+S3250001F7103FBFCC27FFFFCC25FFFFCC25FFFFCC25CFFFCC240FFFCC040CAFCC8403AFCC8867
+S3250001F7303FBFCC27FFFFCC25FFFFCC25FFFFCC25FFFFCC25FFFFCC25FFFFCC25FFFFCC2538
+S3250001F750FFFFCC25FFFFCC25FFFFCC25FFFFCC25CFFFCC240FFFCC040CFFCC0403FFCC0091
+S3250001F7703FFFCC27FFFFCC25FFFFCC25FFFFCC25CFFFCC240FFFCC040CFFCC8403FFCC842B
+S3250001F7900CFFCC0033FFCC27FFFFCC25FFFFCC25FFFFCC25FFFFCC25FFFFCC25FFFFCC25BC
+S3250001F7B0FFFFCC25FFFFCC25FFFFCC25FFFFCC25C0FFCC2403FFCC240FFFCC240FFFCC24D9
+S3250001F7D03FFFCC27FFFFCC25FFFFCC25FFFFCC25FFFFCC25FFFFCC25FFFFCC25FFFFCC2558
+S3150001F7F0FFFFCC25FFFFCC25FFFFCC25FFFFCC2546
+S700000100FE
--- /dev/null
+++ b/os/boot.original/rpcg/gbitbltclip.c
@@ -1,0 +1,52 @@
+#include <u.h>
+#include <libc.h>
+#include <libg.h>
+#include <gnot.h>
+
+void
+gbitbltclip(void *vp)
+{
+	int dx, dy;
+	int i;
+	struct{
+		GBitmap *dm;
+		Point p;
+		GBitmap *sm;
+		Rectangle r;
+		Fcode f;
+	}*bp;
+
+	bp = vp;
+	dx = Dx(bp->r);
+	dy = Dy(bp->r);
+	if(bp->p.x < bp->dm->clipr.min.x){
+		i = bp->dm->clipr.min.x-bp->p.x;
+		bp->r.min.x += i;
+		bp->p.x += i;
+		dx -= i;
+	}
+	if(bp->p.y < bp->dm->clipr.min.y){
+		i = bp->dm->clipr.min.y-bp->p.y;
+		bp->r.min.y += i;
+		bp->p.y += i;
+		dy -= i;
+	}
+	if(bp->p.x+dx > bp->dm->clipr.max.x)
+		bp->r.max.x -= bp->p.x+dx-bp->dm->clipr.max.x;
+	if(bp->p.y+dy > bp->dm->clipr.max.y)
+		bp->r.max.y -= bp->p.y+dy-bp->dm->clipr.max.y;
+	if(bp->r.min.x < bp->sm->clipr.min.x){
+		i = bp->sm->clipr.min.x-bp->r.min.x;
+		bp->p.x += i;
+		bp->r.min.x += i;
+	}
+	if(bp->r.min.y < bp->sm->clipr.min.y){
+		i = bp->sm->clipr.min.y-bp->r.min.y;
+		bp->p.y += i;
+		bp->r.min.y += i;
+	}
+	if(bp->r.max.x > bp->sm->clipr.max.x)
+		bp->r.max.x = bp->sm->clipr.max.x;
+	if(bp->r.max.y > bp->sm->clipr.max.y)
+		bp->r.max.y = bp->sm->clipr.max.y;
+}
--- /dev/null
+++ b/os/boot.original/rpcg/gnot.h
@@ -1,0 +1,71 @@
+
+extern void	*bbmalloc(int);
+extern void	bbfree(void *, int);
+extern int	bbonstack(void);
+extern void	bbexec(void(*)(void), int, int);
+
+/*
+ * Graphics types
+ */
+
+typedef	struct	GBitmap		GBitmap;
+typedef struct	GFont		GFont;
+typedef struct	GSubfont	GSubfont;
+typedef struct	GCacheinfo	GCacheinfo;
+
+struct	GBitmap
+{
+	ulong	*base;		/* pointer to start of data */
+	long	zero;		/* base+zero=&word containing (0,0) */
+	ulong	width;		/* width in 32 bit words of total data area */
+	int	ldepth;		/* log base 2 of number of bits per pixel */
+	Rectangle r;		/* rectangle in data area, local coords */
+	Rectangle clipr;	/* clipping region */
+	GBitmap	*cache;		/* zero; distinguishes bitmap from layer */
+};
+
+
+/*
+ * GFont etc. are not used in the library, only in devbit.c.
+ * GSubfont is only barely used.
+ */
+struct	GSubfont
+{
+	short	n;		/* number of chars in font */
+	char	height;		/* height of bitmap */
+	char	ascent;		/* top of bitmap to baseline */
+	Fontchar *info;		/* n+1 character descriptors */
+	GBitmap	*bits;		/* where the characters are */
+};
+struct GCacheinfo
+{
+	ulong		xright;	/* right edge of bits */
+	Fontchar;
+};
+
+struct GFont
+{
+	uchar		height;	/* max height of bitmap, interline spacing */
+	char		ascent;	/* top of bitmap to baseline */
+	char		width;	/* widest so far; used in caching only */	
+	char		ldepth;	/* of images */
+	short		id;	/* of font */
+	int		ncache;	/* number of entries in cache */
+	GCacheinfo	*cache;	/* cached characters */
+	GBitmap		*b;	/* cached images */
+};
+
+extern ulong	 *gaddr(GBitmap*, Point);
+extern uchar	 *gbaddr(GBitmap*, Point);
+extern void	 gbitblt(GBitmap*, Point, GBitmap*, Rectangle, Fcode);
+extern void	 gbitbltclip(void*);
+extern void	 gtexture(GBitmap*, Rectangle, GBitmap*, Fcode);
+extern Point	 gsubfstrsize(GSubfont*, char*);
+extern int	 gsubfstrwidth(GSubfont*, char*);
+extern Point	 gsubfstring(GBitmap*, Point, GSubfont*, char*, Fcode);
+extern Point	 gbitbltstring(GBitmap*, Point, GSubfont*, char*, Fcode);
+extern void	 gsegment(GBitmap*, Point, Point, int, Fcode);
+extern void	 gpoint(GBitmap*, Point, int, Fcode);
+extern void	 gflushcpucache(void);
+extern GBitmap*	 gballoc(Rectangle, int);
+extern void	 gbfree(GBitmap*);
--- /dev/null
+++ b/os/boot.original/rpcg/i2c.c
@@ -1,0 +1,360 @@
+#include "boot.h"
+
+/*
+ * basic read/write interface to mpc8xx I2C bus (master mode)
+ */
+
+typedef struct I2C I2C;
+
+struct I2C {
+	uchar	i2mod;
+	uchar	rsv12a[3];
+	uchar	i2add;
+	uchar	rsv12b[3];
+	uchar	i2brg;
+	uchar	rsv12c[3];
+	uchar	i2com;
+	uchar	rsv12d[3];
+	uchar	i2cer;
+	uchar	rsv12e[3];
+	uchar	i2cmr;
+};
+
+enum {
+	/* i2c-specific BD flags */
+	RxeOV=		1<<1,	/* overrun */
+	TxS=			1<<10,	/* transmit start condition */
+	TxeNAK=		1<<2,	/* last transmitted byte not acknowledged */
+	TxeUN=		1<<1,	/* underflow */
+	TxeCL=		1<<0,	/* collision */
+	TxERR=		(TxeNAK|TxeUN|TxeCL),
+
+	/* i2cmod */
+	REVD=	1<<5,	/* =1, LSB first */
+	GCD=	1<<4,	/* =1, general call address disabled */
+	FLT=		1<<3,	/* =0, not filtered; =1, filtered */
+	PDIV=	3<<1,	/* predivisor field */
+	EN=		1<<0,	/* enable */
+
+	/* i2com */
+	STR=		1<<7,	/* start transmit */
+	I2CM=	1<<0,	/* master */
+	I2CS=	0<<0,	/* slave */
+
+	/* i2cer */
+	TXE =	1<<4,
+	BSY =	1<<2,
+	TXB =	1<<1,
+	RXB =	1<<0,
+
+	/* port B bits */
+	I2CSDA =	IBIT(27),
+	I2CSCL = IBIT(26),
+
+	Rbit =	1<<0,	/* bit in address byte denoting read */
+
+	/* maximum I2C I/O (can change) */
+	MaxIO=	128,
+	Bufsize =	MaxIO+4,	/* extra space for address/clock bytes and alignment */
+	Freq =	100000,
+	I2CTimeout = 250,	/* msec */
+};
+
+/* data cache needn't be flushed if buffers allocated in uncached INTMEM */
+#define	DCFLUSH(a,n)
+
+/*
+ * I2C software structures
+ */
+
+struct Ctlr {
+	Lock;
+	QLock	io;
+	int	init;
+	I2C*	i2c;
+	IOCparam*	sp;
+
+	BD*	rd;
+	BD*	td;
+	int	phase;
+	int	timeout;
+	char*	addr;
+	char*	txbuf;
+	char*	rxbuf;
+};
+typedef struct Ctlr Ctlr;
+
+static	Ctlr	i2ctlr[1];
+extern	int	predawn;
+
+static	void	interrupt(Ureg*, void*);
+
+static void
+enable(void)
+{
+	I2C *i2c;
+
+	i2c = i2ctlr->i2c;
+	i2c->i2cer = ~0;	/* clear events */
+	eieio();
+	i2c->i2mod |= EN;
+	eieio();
+	i2c->i2cmr = TXE|BSY|TXB|RXB;	/* enable all interrupts */
+	eieio();
+}
+
+static void
+disable(void)
+{
+	I2C *i2c;
+
+	i2c = i2ctlr->i2c;
+	i2c->i2cmr = 0;	/* mask all interrupts */
+	i2c->i2mod &= ~EN;
+}
+
+/*
+ * called by the reset routine of any driver using the I2C
+ */
+void
+i2csetup(void)
+{
+	IMM *io;
+	I2C *i2c;
+	IOCparam *sp;
+	Ctlr *ctlr;
+	long f, e, emin;
+	int p, d, dmax;
+
+	ctlr = i2ctlr;
+	if(ctlr->init)
+		return;
+	print("i2c setup...\n");
+	ctlr->init = 1;
+	i2c = KADDR(INTMEM+0x860);
+	ctlr->i2c = i2c;
+	sp = KADDR(INTMEM+0x3c80);
+	ctlr->sp = sp;
+	disable();
+
+	if(ctlr->txbuf == nil){
+		ctlr->txbuf = ialloc(Bufsize, 2);
+		ctlr->addr = ctlr->txbuf+Bufsize;
+	}
+	if(ctlr->rxbuf == nil)
+		ctlr->rxbuf = ialloc(Bufsize, 2);
+	if(ctlr->rd == nil){
+		ctlr->rd = bdalloc(1);
+		ctlr->rd->addr = PADDR(ctlr->rxbuf);
+		ctlr->rd->length = 0;
+		ctlr->rd->status = BDWrap;
+	}
+	if(ctlr->td == nil){
+		ctlr->td = bdalloc(2);
+		ctlr->td->addr = PADDR(ctlr->txbuf);
+		ctlr->td->length = 0;
+		ctlr->td->status = BDWrap|BDLast;
+	}
+
+	/* select port pins */
+	io = ioplock();
+	io->pbdir |= I2CSDA | I2CSCL;
+	io->pbodr |= I2CSDA | I2CSCL;
+	io->pbpar |= I2CSDA | I2CSCL;
+	iopunlock();
+
+	/* explicitly initialise parameters, because InitRxTx can't be used (see i2c/spi relocation errata) */
+	sp = ctlr->sp;
+	sp->rbase = PADDR(ctlr->rd);
+	sp->tbase = PADDR(ctlr->td);
+	sp->rfcr = 0x18;
+	sp->tfcr = 0x18;
+	sp->mrblr = Bufsize;
+	sp->rstate = 0;
+	sp->rptr = 0;
+	sp->rbptr = sp->rbase;
+	sp->rcnt = 0;
+	sp->tstate = 0;
+	sp->tbptr = sp->tbase;
+	sp->tptr = 0;
+	sp->tcnt = 0;
+	eieio();
+
+	i2c->i2com = I2CM;
+	i2c->i2mod = 0;	/* normal mode */
+	i2c->i2add = 0;
+
+	emin = Freq;
+	dmax = (m->cpuhz/Freq)/2-3;
+	for(d=0; d < dmax; d++){
+		for(p=3; p>=0; p--){
+			f = (m->cpuhz>>(p+2))/(2*(d+3));
+			e = Freq - f;
+			if(e < 0)
+				e = -e;
+			if(e < emin){
+				emin = e;
+				i2c->i2brg = d;
+				i2c->i2mod = (i2c->i2mod&~PDIV)|((3-p)<<1); /* set PDIV */
+			}
+		}
+	}
+	//print("i2brg=%d i2mod=#%2.2ux\n", i2c->i2brg, i2c->i2mod);
+	setvec(VectorCPIC+0x10, interrupt, i2ctlr);
+}
+
+enum {
+	Idling,
+	Done,
+	Busy,
+		Sending,
+		Recving,
+};
+
+static void
+interrupt(Ureg*, void *arg)
+{
+	int events;
+	Ctlr *ctlr;
+	I2C *i2c;
+
+	ctlr = arg;
+	i2c = ctlr->i2c;
+	events = i2c->i2cer;
+	eieio();
+	i2c->i2cer = events;
+	if(events & (BSY|TXE)){
+		print("I2C#%x\n", events);
+		if(ctlr->phase != Idling){
+			ctlr->phase = Idling;
+		}
+	}else{
+		if(events & TXB){
+			//print("i2c: xmt %d %4.4ux %4.4ux\n", ctlr->phase, ctlr->td->status, ctlr->td[1].status);
+			if(ctlr->phase == Sending){
+				ctlr->phase = Done;
+			}
+		}
+		if(events & RXB){
+			//print("i2c: rcv %d %4.4ux %d\n", ctlr->phase, ctlr->rd->status, ctlr->rd->length);
+			if(ctlr->phase == Recving){
+				ctlr->phase = Done;
+			}
+		}
+	}
+}
+
+static int
+done(void *a)
+{
+	return ((Ctlr*)a)->phase < Busy;
+}
+
+static void
+i2cwait(Ctlr *ctlr)
+{
+	int i;
+
+	ctlr->timeout = 0;
+	i = 0;
+	while(!done(ctlr)){
+		if(predawn){
+			if(++i > 100){
+				ctlr->phase = Done;
+				ctlr->timeout = 1;
+				return;
+			}
+			delay(1);
+			interrupt(nil, ctlr);
+		}
+	}
+}
+
+long
+i2csend(int addr, void *buf, long n)
+{
+	Ctlr *ctlr;
+	int i, p, s;
+
+	ctlr = i2ctlr;
+	if(n > MaxIO)
+		return -1;
+	i = 1;
+	ctlr->txbuf[0] = addr & ~1;
+	if(addr & 1){
+		ctlr->txbuf[1] = addr>>8;
+		i++;
+	}
+	memmove(ctlr->txbuf+i, buf, n);
+	DCFLUSH(ctlr->txbuf, Bufsize);
+	ctlr->phase = Sending;
+	ctlr->rd->status = BDEmpty|BDWrap|BDInt;
+	ctlr->td->addr = PADDR(ctlr->txbuf);
+	ctlr->td->length = n+i;
+	ctlr->td->status = BDReady|BDWrap|BDLast|BDInt;
+	enable();
+	ctlr->i2c->i2com = STR|I2CM;
+	eieio();
+	i2cwait(ctlr);
+	disable();
+	p = ctlr->phase;
+	s = ctlr->td->status;
+	if(s & BDReady || s & TxERR || p != Done || ctlr->timeout)
+		return -1;
+	return n;
+}
+
+long
+i2crecv(int addr, void *buf, long n)
+{
+	Ctlr *ctlr;
+	int p, s, flag;
+	BD *td;
+	long nr;
+
+	ctlr = i2ctlr;
+	if(n > MaxIO)
+		return -1;
+	ctlr->txbuf[0] = addr|Rbit;
+	if(addr & 1){	/* special select sequence */
+		ctlr->addr[0] = addr &~ 1;
+		ctlr->addr[1] = addr>>8;
+	}
+	DCFLUSH(ctlr->txbuf, Bufsize);
+	DCFLUSH(ctlr->rxbuf, Bufsize);
+	ctlr->phase = Recving;
+	ctlr->rd->addr = PADDR(ctlr->rxbuf);
+	ctlr->rd->status = BDEmpty|BDWrap|BDInt;
+	flag = 0;
+	td = ctlr->td;
+	td[1].status = 0;
+	if(addr & 1){
+		/* special select sequence */
+		td->addr = PADDR(ctlr->addr);
+		td->length = 2;
+		/* td->status made BDReady below */
+		td++;
+		flag = TxS;
+	}
+	td->addr = PADDR(ctlr->txbuf);
+	td->length = n+1;
+	td->status = BDReady|BDWrap|BDLast | flag;	/* not BDInt: leave that to receive */
+	if(flag)
+		ctlr->td->status = BDReady;
+	enable();
+	ctlr->i2c->i2com = STR|I2CM;
+	eieio();
+	i2cwait(ctlr);
+	disable();
+	p = ctlr->phase;
+	s = ctlr->td->status;
+	if(flag)
+		s |= ctlr->td[1].status;
+	nr = ctlr->rd->length;
+	if(nr > n)
+		nr = n;	/* shouldn't happen */
+	if(s & TxERR || s & BDReady || p != Done || ctlr->rd->status & BDEmpty || ctlr->timeout)
+		return -1;
+	memmove(buf, ctlr->rxbuf, nr);
+	return nr;
+}
--- /dev/null
+++ b/os/boot.original/rpcg/initfads.c
@@ -1,0 +1,187 @@
+/*
+ * Called from l.s in EPROM to set up a minimal working environment.
+ * Since there is no DRAM yet, and therefore no stack, no function
+ * calls may be made from sysinit0, and values can't be stored,
+ * except to INTMEM.  Global values are accessed by offset from SB,
+ * which has been set by l.s to point into EPROM.
+ *
+ * This is FADS-specific in CS assignment and access of the FADS BCSR
+ * to discover memory size and speed.
+ */
+
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+#include "archfads.h"
+
+#define	MB	(1024*1024)
+
+enum {
+	UPMSIZE = 64,	/* memory controller instruction RAM */
+	SPEED = 50,	/* maximum memory clock in MHz */
+	SDRAMSIZE = 4*MB,
+
+	/* mcr */
+	WriteRAM = 0<<30,
+	ReadRAM = 1<<30,
+	ExecRAM = 2<<30,
+
+	SelUPMA = 0<<23,
+	SelUPMB = 1<<23,
+
+	Once = 1<<8,
+};
+
+/*
+ * mpc8bug uses the following for 60ns EDO DRAMs 32-50MHz
+ */
+static ulong upma50[UPMSIZE] = {
+	0x8FFFEC24,	0xFFFEC04,	0xCFFEC04,	0xFFEC04,       
+	0xFFEC00,	0x37FFEC47,	0xFFFFFFFF,	0xFFFFFFFF,
+	0x8FFFEC24,	0xFFFEC04,	0x8FFEC04,	0xFFEC0C,
+	0x3FFEC00,	0xFFEC44,	0xFFCC08,	0xCFFCC44,
+	0xFFEC0C,	0x3FFEC00,	0xFFEC44,	0xFFCC00,
+	0x3FFFC847,	0x3FFFEC47,	0xFFFFFFFF,	0xFFFFFFFF,
+	0x8FAFCC24,	0xFAFCC04,	0xCAFCC00,	0x11BFCC47,
+	0xC0FFCC84,	0xFFFFFFFF,	0xFFFFFFFF,	0xFFFFFFFF,
+	0x8FAFCC24,	0xFAFCC04,	0xCAFCC00,	0x3AFCC4C,
+	0xCAFCC00,	0x3AFCC4C,	0xCAFCC00,	0x3AFCC4C,
+	0xCAFCC00,	0x33BFCC4F,	0xFFFFFFFF,	0xFFFFFFFF,
+	0xFFFFFFFF,	0xFFFFFFFF,	0xFFFFFFFF,	0xFFFFFFFF,
+	0xC0FFCC84,	0xFFCC04,	0x7FFCC04,	0x3FFFCC06,
+	0xFFFFCC85,	0xFFFFCC05,	0xFFFFCC05,	0xFFFFFFFF,
+	0xFFFFFFFF,	0xFFFFFFFF,	0xFFFFFFFF,	0xFFFFFFFF,
+	0x33FFCC07,	0xFFFFFFFF,	0xFFFFFFFF,	0xFFFFFFFF,
+};
+
+/*
+ * the FADS manual table 3-7 suggests the following for 60ns EDO DRAMs at 20MHz
+ */
+static ulong upma20[UPMSIZE] = {
+	0x8FFFCC04, 0x08FFCC00, 0x33FFCC47, ~0, ~0, ~0, ~0, ~0,
+	[0x08]	0x8FFFCC04, 0x08FFCC08, 0x08FFCC08, 0x08FFCC08, 0x08FFCC00, 0x3FFFCC47, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0,
+	[0x18]	0x8FEFCC00, 0x39BFCC47, ~0, ~0, ~0, ~0, ~0, ~0,
+	[0x20]	0x8FEFCC00, 0x09AFCC48, 0x09AFCC48, 0x08AFCC48, 0x39BFCC47, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0,
+	[0x30]	0x80FFCC84, 0x17FFCC04, 0xFFFFCC86, 0xFFFFCC05, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0,
+	[0x3C]	0x33FFCC07, ~0, ~0, ~0,
+};
+
+void
+sysinit0(int inrom)
+{
+	ulong *upm, *bcsr;
+	IMM *io;
+	int i, mb;
+
+	io = (IMM*)INTMEM;		/* running before maps, no KADDR */
+
+	/* system interface unit initialisation, FADS manual table 3-2, except as noted */
+	io->siumcr = 0x01012440;
+	io->sypcr = 0xFFFFFF88;
+	io->tbscrk = KEEP_ALIVE_KEY;
+	io->tbscr = 0xC3;	/* time base enabled */
+	io->rtcsck = KEEP_ALIVE_KEY;
+	io->rtcsc = 0xC1;	/* don't FRZ, real-time clock enabled */
+	io->rtcsck = ~KEEP_ALIVE_KEY;
+	io->piscrk = KEEP_ALIVE_KEY;
+	io->piscr = 0x82;
+
+	io->memc[BCSRCS].option = 0xFFFF8110;	/* 32k block, all types access, CS early negate, 1 ws */
+	io->memc[BCSRCS].base = BCSRMEM | 1;	/* base, 32-bit port, no parity, GPCM */
+
+	io->memc[BOOTCS].base = FLASHMEM | 1;
+	io->memc[BOOTCS].option = 0xFF800D54;
+
+	if(!inrom)
+		return;	/* can't initialise DRAM controller from DRAM */
+
+	bcsr = (ulong*)BCSRMEM;
+//	bcsr[1] &= ~DisableDRAM;
+	/* could check DRAM speed here; assume 60ns */
+	switch((bcsr[2]>>23)&3){
+	default:	return;	/* can't happen; for the compiler */
+	case 0:	mb = 4; break;
+	case 1:	mb = 32; break;
+	case 2:	mb = 16; break;
+	case 3:	mb = 8; break;
+	}
+
+	upm = upma50;
+	for(i=0; i<UPMSIZE; i++){
+		io->mdr = upm[i];
+		io->mcr = WriteRAM | SelUPMA | i;
+	}
+	io->mptpr = 0x0400;
+	if(SPEED >= 32)
+		io->mamr = (0x9C<<24) | 0xA21114;	/* 50MHz BRGCLK; FADS manual says 0xC0, mpc8bug sets 0x9C */
+	else if(SPEED >= 20)
+		io->mamr = (0x60<<24) | 0xA21114;	/* 25MHz BRGCLK */
+	else
+		io->mamr = (0x40<<24) | 0xA21114;	/* 16.67MHz BRGCLK */
+	io->memc[DRAM1].option = ~((mb<<20)-1)|0x0800;	/* address mask, SAM=1 */
+	io->memc[DRAM1].base = 0 | 0x81;	/* base at 0, 32-bit port size, no parity, UPMA */
+}
+
+/*
+ * the FADS manual table 3-9's suggestion for MB811171622A-100 32+MHz-50MHz
+ */
+static ulong upmb50[UPMSIZE] = {
+	[0x00]	0x1F07FC04, 0xEEAEFC04, 0x11ADFC04, 0xEFBBBC00, 0x1FF77C47,
+	[0x05]	0x1FF77C34, 0xEFEABC34, 0x1FB57C35,
+	[0x08]	0x1F07FC04, 0xEEAEFC04, 0x10ADFC04, 0xF0AFFC00, 0xF0AFFC00, 0xF1AFFC00, 0xEFBBBC00, 0x1FF77C47, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0,
+	[0x18]	0x1F27FC04, 0xEEAEBC00, 0x01B93C04, 0x1FF77C47, ~0, ~0, ~0, ~0,
+	[0x20]	0x1F07FC04, 0xEEAEBC00, 0x10AD7C00, 0xF0AFFC00, 0xF0AFFC00, 0xE1BBBC04, 0x1FF77C47, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0,
+	[0x30] 	0x1FF5FC84, 0xFFFFFC04, 0xFFFFFC04, 0xFFFFFC04, 0xFFFFFC84, 0xFFFFFC07, ~0, ~0, ~0, ~0, ~0, ~0,
+	[0x3C]	0x7FFFFC07, ~0, ~0, ~0,
+};
+
+/*
+ * the FADS manual table 3-8's suggestion for MB811171622A-100 up to 32MHz
+ */
+static	ulong	upmb32[UPMSIZE] = {
+	[0x00]	0x126CC04, 0xFB98C00, 0x1FF74C45, ~0, ~0,
+	[0x05]	0x1FE77C34, 0xEFAABC34, 0x1FA57C35,
+	[0x08]	0x0026FC04, 0x10ADFC00, 0xF0AFFC00, 0xF1AFFC00, 0xEFBBBC00, 0x1FF77C45, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0,
+	[0x18]	0x0E26BC04, 0x01B93C00, 0x1FF77C45, ~0, ~0, ~0, ~0, ~0,
+	[0x20]	0x0E26BC00, 0x10AD7C00, 0xF0AFFC00, 0xF0AFFC00, 0xE1BBBC04, 0x1FF77C45, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0,
+	[0x30]	0x1FF5FC84, 0xFFFFFC04, 0xFFFFFC84, 0xFFFFFC05, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0,
+	[0x3C]	0x7FFFFC07, ~0, ~0, ~0,
+};
+
+/*
+ * optionally called by archfads.c:/^archinit to initialise access to SDRAM
+ */
+void
+sdraminit(ulong base)
+{
+	ulong *upm;
+	IMM *io;
+	int i;
+
+	io = (IMM*)INTMEM;		/* running before maps, no KADDR */
+	if(SPEED > 32)
+		upm = upmb50;
+	else
+		upm = upmb32;
+	for(i=0; i<UPMSIZE; i++){
+		io->mdr = upm[i];
+		io->mcr = WriteRAM | SelUPMB | i;
+	}
+	io->memc[SDRAM].option = ~(SDRAMSIZE-1)|0x0A00;	/* address mask, SAM=1, G5LS=1 */
+	io->memc[SDRAM].base = base | 0xC1;
+	if(SPEED > 32){
+		io->mbmr = 0xD0802114;	/* 50MHz BRGCLK */
+		io->mar = 0x88;
+	}else{
+		io->mbmr = 0x80802114;	/* 32MHz BRGCLK */
+		io->mar = 0x48;
+	}
+	io->mcr = ExecRAM | SelUPMB | (SDRAM<<13) | Once | 5;	/* run MRS command in locations 5-8 of UPMB */
+	io->mbmr = (io->mbmr & ~0xF) | 8;
+	io->mcr = ExecRAM | SelUPMB | (SDRAM<<13) | Once | 0x30;	/* run refresh sequence */
+	io->mbmr = (io->mbmr & ~0xF) | 4;	/* 4-beat refresh bursts */
+}
--- /dev/null
+++ b/os/boot.original/rpcg/initpaq.c
@@ -1,0 +1,101 @@
+/*
+ * Called from l.s in EPROM to set up a minimal working environment.
+ * Since there is no DRAM yet, and therefore no stack, no function
+ * calls may be made from sysinit0, and values can't be stored,
+ * except to INTMEM.  Global values are accessed by offset from SB,
+ * which has been set by l.s to point into EPROM.
+ *
+ * This is PowerPAQ-specific:
+ *	- assumes 8mbytes
+ *	- powerpaq CS assignment
+ */
+
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+#include "archpaq.h"
+
+#define	MB	(1024*1024)
+
+enum {
+	DRAMSIZE = 8*MB,
+	FLASHSIZE = 8*MB,
+
+	UPMSIZE = 64,	/* memory controller instruction RAM */
+	SPEED = 50,	/* maximum memory clock in MHz */
+
+	/* mcr */
+	WriteRAM = 0<<30,
+	ReadRAM = 1<<30,
+	ExecRAM = 2<<30,
+
+	SelUPMA = 0<<23,
+	SelUPMB = 1<<23,
+
+	Once = 1<<8,
+};
+
+/*
+ * mpc8bug uses the following for 60ns EDO DRAMs 32-50MHz
+ */
+static ulong upmb50[UPMSIZE] = {
+	0x8FFFEC24,	0xFFFEC04,	0xCFFEC04,	0xFFEC04,       
+	0xFFEC00,	0x37FFEC47,	0xFFFFFFFF,	0xFFFFFFFF,
+	0x8FFFEC24,	0xFFFEC04,	0x8FFEC04,	0xFFEC0C,
+	0x3FFEC00,	0xFFEC44,	0xFFCC08,	0xCFFCC44,
+	0xFFEC0C,	0x3FFEC00,	0xFFEC44,	0xFFCC00,
+	0x3FFFC847,	0x3FFFEC47,	0xFFFFFFFF,	0xFFFFFFFF,
+	0x8FAFCC24,	0xFAFCC04,	0xCAFCC00,	0x11BFCC47,
+	0xC0FFCC84,	0xFFFFFFFF,	0xFFFFFFFF,	0xFFFFFFFF,
+	0x8FAFCC24,	0xFAFCC04,	0xCAFCC00,	0x3AFCC4C,
+	0xCAFCC00,	0x3AFCC4C,	0xCAFCC00,	0x3AFCC4C,
+	0xCAFCC00,	0x33BFCC4F,	0xFFFFFFFF,	0xFFFFFFFF,
+	0xFFFFFFFF,	0xFFFFFFFF,	0xFFFFFFFF,	0xFFFFFFFF,
+	0xC0FFCC84,	0xFFCC04,	0x7FFCC04,	0x3FFFCC06,
+	0xFFFFCC85,	0xFFFFCC05,	0xFFFFCC05,	0xFFFFFFFF,
+	0xFFFFFFFF,	0xFFFFFFFF,	0xFFFFFFFF,	0xFFFFFFFF,
+	0x33FFCC07,	0xFFFFFFFF,	0xFFFFFFFF,	0xFFFFFFFF,
+};
+
+void
+sysinit0(int inrom)
+{
+	ulong *upm;
+	IMM *io;
+	int i;
+
+	io = (IMM*)INTMEM;		/* running before maps, no KADDR */
+
+	/* system interface unit initialisation, FADS manual table 3-2, except as noted */
+	io->siumcr = 0x01012440;
+	io->sypcr = 0xFFFFFF88;
+	io->tbscrk = KEEP_ALIVE_KEY;
+	io->tbscr = 0xC3;	/* time base enabled */
+	io->rtcsck = KEEP_ALIVE_KEY;
+	io->rtcsc = 0xC1;	/* don't FRZ, real-time clock enabled */
+	io->rtcsck = ~KEEP_ALIVE_KEY;
+	io->piscrk = KEEP_ALIVE_KEY;
+	io->piscr = 0x82;
+
+	io->memc[BOOTCS].base = FLASHMEM | 1;
+	io->memc[BOOTCS].option = ~(FLASHSIZE-1)|(1<<8)|(2<<4);	/* mask, BIH, 2 wait states */
+
+	if(!inrom)
+		return;	/* can't initialise DRAM controller from DRAM */
+
+	/* could check DRAM speed here; assume 60ns */
+	/* could probe DRAM for size here; assume DRAMSIZE */
+	io->mptpr = 0x400;	/* powerpaq flash has 0x1000 */
+	io->mbmr = (0xC0<<24) | 0xA21114;	/* 50MHz BRGCLK */
+	upm = upmb50;
+	for(i=0; i<UPMSIZE; i++){
+		io->mdr = upm[i];
+		io->mcr = WriteRAM | SelUPMB | i;
+	}
+	io->memc[DRAM1].option = ~(DRAMSIZE-1)|0x0800;	/* address mask, SAM=1 */
+	io->memc[DRAM1].base = 0 | 0xC1;	/* base at 0, 32-bit port size, no parity, UPMB */
+}
--- /dev/null
+++ b/os/boot.original/rpcg/initrpcg.c
@@ -1,0 +1,91 @@
+
+/*
+ * Called from l.s in EPROM to set up a minimal working environment.
+ * Since there is no DRAM yet, and therefore no stack, no function
+ * calls may be made from sysinit, and values can't be stored,
+ * except to INTMEM.  Global values are accessed by offset from SB,
+ * which has been set by l.s to point into EPROM.
+ */
+
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+#include	"archrpcg.h"
+
+#define	MB	(1024*1024)
+
+enum {
+	UPMSIZE = 64,	/* memory controller instruction RAM */
+	DRAMSIZE = 16*MB,
+	FLASHSIZE = 4*MB,
+
+	WriteRAM = 0<<30,
+	ReadRAM = 1<<30,
+	ExecRAM = 2<<30,
+
+	SelUPMA = 0<<23,
+	SelUPMB = 1<<23,
+};
+/* RPCG values for RPXLite AW */
+static	ulong	upma50[UPMSIZE] = {
+	0xCFFFCC24,	0x0FFFCC04,	0x0CAFCC04,	0x03AFCC08,       
+	0x3FBFCC27,	0xFFFFCC25,	0xFFFFCC25,	0xFFFFCC25,
+	0xCFFFCC24,	0x0FFFCC04,	0x0CAFCC84,	0x03AFCC88,
+	0x3FBFCC27,	0xFFFFCC25,	0xFFFFCC25,	0xFFFFCC25,
+	0xFFFFCC25,	0xFFFFCC25,	0xFFFFCC25,	0xFFFFCC25,
+	0xFFFFCC25,	0xFFFFCC25,	0xFFFFCC25,	0xFFFFCC25,
+	0xCFFFCC24,	0x0FFFCC04,	0x0CFFCC04,	0x03FFCC00,
+	0x3FFFCC27,	0xFFFFCC25,	0xFFFFCC25,	0xFFFFCC25,
+	0xCFFFCC24,	0x0FFFCC04,	0x0CFFCC84,	0x03FFCC84,
+	0x0CFFCC00,	0x33FFCC27,	0xFFFFCC25,	0xFFFFCC25,
+	0xFFFFCC25,	0xFFFFCC25,	0xFFFFCC25,	0xFFFFCC25,
+	0xFFFFCC25,	0xFFFFCC25,	0xFFFFCC25,	0xFFFFCC25,
+	0xC0FFCC24,	0x03FFCC24,	0x0FFFCC24,	0x0FFFCC24,
+	0x3FFFCC27,	0xFFFFCC25,	0xFFFFCC25,	0xFFFFCC25,
+	0xFFFFCC25,	0xFFFFCC25,	0xFFFFCC25,	0xFFFFCC25,
+	0xFFFFCC25,	0xFFFFCC25,	0xFFFFCC25,	0xFFFFCC25,
+};
+
+void
+sysinit0(int inrom)
+{
+	ulong *upm;
+	IMM *io;
+	int i;
+
+	io = (IMM*)INTMEM;		/* running before maps, no KADDR */
+//	io->siumcr = 0x01012440;
+//	io->sypcr = 0xFFFFFF88;
+	io->tbscrk = KEEP_ALIVE_KEY;
+	io->tbscr = 0xC3;
+	io->rtcsck = KEEP_ALIVE_KEY;
+	io->rtcsc = 0xC1;
+	io->rtcsck = ~KEEP_ALIVE_KEY;
+	io->piscrk = KEEP_ALIVE_KEY;
+	io->piscr = 0x82;
+return;
+	io->memc[BCSRCS].option = 0xFFFF8910;	/* 32k block, all types access, CSNT, CS early negate, burst inhibit, 1 ws */
+	io->memc[BCSRCS].base = BCSRMEM | 1;	/* base, 32-bit port, no parity, GPCM */
+
+//	io->memc[BOOTCS].base = FLASHMEM | 0x801; /* base, 16 bit port */
+//	io->memc[BOOTCS].option = ~(FLASHSIZE-1)|(1<<8)|(4<<4);	/* mask, BIH, 4 wait states */
+
+	if(1||!inrom)
+		return;	/* can't initialise DRAM controller from DRAM */
+
+	/* TO DO: could check DRAM size and speed now */
+
+	upm = upma50;
+	for(i=0; i<nelem(upma50); i++){
+		io->mdr = upm[i];
+		io->mcr = WriteRAM | SelUPMA | i;
+	}
+	io->mptpr = 0x0800;	/* divide by 8 */
+	io->mamr = (0x58<<24) | 0xA01430;	/* 40MHz BRGCLK */
+	io->memc[DRAM1].option = ~(DRAMSIZE-1)|0x0E00;	/* address mask, SAM=1, G5LA/S=3 */
+	io->memc[DRAM1].base = 0 | 0x81;	/* base at 0, 32-bit port size, no parity, UPMA */
+}
--- /dev/null
+++ b/os/boot.original/rpcg/io.h
@@ -1,0 +1,463 @@
+enum
+{
+	/* software interrupt vectors (SIU and CPM) */
+	VectorPIC= 0,	/* level 0 to level 7, assigned by software */
+		CPIClevel=	4,
+	VectorIRQ=	VectorPIC+8,	/* IRQ0 to IRQ7 */
+	VectorCPIC=	VectorIRQ+8,	/* 32 CPM interrupts: 0 (error) to 0x1F (PC15) */
+};
+
+enum
+{
+	BUSUNKNOWN = 0,
+};
+
+/*
+ * Buffer Descriptors and IO Rings
+ */
+
+typedef struct BD BD;
+struct BD {
+	ushort	status;
+	ushort	length;
+	ulong	addr;
+};
+
+BD*	bdalloc(int);
+void	bdfree(BD*, int);
+
+enum {
+	/* Rx BDs, bits common to all protocols */
+	BDEmpty=	1<<15,
+	BDWrap=		1<<13,
+	BDInt=		1<<12,
+	BDLast=		1<<11,
+	BDFirst=		1<<10,
+
+	/* Tx BDs */
+	BDReady=		1<<15,
+	/* BDWrap, BDInt, BDLast */
+};
+
+typedef struct Ring Ring;
+struct Ring {
+	BD*	rdr;				/* receive descriptor ring */
+	void*	rrb;				/* receive ring buffers */
+	int	rdrx;				/* index into rdr */
+	int	nrdre;			/* length of rdr */
+
+	BD*	tdr;				/* transmit descriptor ring */
+	Block**	txb;				/* corresponding transmit ring buffers */
+	int	tdrh;				/* host index into tdr */
+	int	tdri;				/* interface index into tdr */
+	int	ntdre;			/* length of tdr */
+	int	ntq;				/* pending transmit requests */
+};
+
+#define NEXT(x, l)	(((x)+1)%(l))
+#define PREV(x, l)	(((x) == 0) ? (l)-1: (x)-1)
+#define	HOWMANY(x, y)	(((x)+((y)-1))/(y))
+#define ROUNDUP(x, y)	(HOWMANY((x), (y))*(y))
+
+int	ioringinit(Ring*, int, int, int);
+
+/*
+ * CPM
+ */
+enum {
+	/* commands */
+	InitRxTx =	0,
+	InitRx =		1,
+	InitTx =		2,
+	EnterHunt=	3,
+	StopTx=		4,
+	GracefulStopTx = 5,
+	InitIDMA =	5,
+	RestartTx =	6,
+	CloseRxBD =	7,
+	SetGroupAddr = 8,
+	SetTimer =	8,
+	GCITimeout =	9,
+	GCIAbort =	10,
+	StopIDMA =	11,
+	StartDSP = 	12,
+	ArmIDMA =	13,
+	InitDSP =		13,
+	USBCmd =	15,
+
+	/* channel IDs */
+	SCC1ID=	0,
+	USBID=	0,
+	I2CID=	1,
+	IDMA1ID= 1,
+	SCC2ID=	4,
+	SPIID=	5,
+	IDMA2ID= 5,
+	TIMERID=	5,
+	SCC3ID=	8,
+	SMC1ID=	9,
+	DSP1ID=9,
+	SCC4ID=	12,
+	SMC2ID=	13,
+	DSP2ID=	13,
+
+	BaudEnable = 1<<16,
+
+	/* sicr */
+	CLK1 = 4,		/* SCC1,2 */
+	CLK2 = 5,
+	CLK3 = 6,
+	CLK4 = 7,
+	CLK5 = CLK1,	/* SCC3,4 */
+	CLK6 = CLK2,
+	CLK7 = CLK3,
+	CLK8 = CLK4,
+};
+
+void	cpmop(int, int, int);
+#define	ioplock()	(m->iomem)
+#define	iopunlock()
+
+/*
+ * the structures below follow hardware/firmware layouts in the 8xx manuals:
+ * mind the data types, offsets and alignment
+ */
+
+/*
+ * basic IO controller parameters (SMC and SCC)
+ */
+typedef struct IOCparam IOCparam;
+struct IOCparam {
+	ushort	rbase;
+	ushort	tbase;
+	uchar	rfcr;
+	uchar	tfcr;
+	ushort	mrblr;
+	ulong	rstate;
+	ulong	rptr;
+	ushort	rbptr;
+	ushort	rcnt;
+	ulong	rtmp;
+	ulong	tstate;
+	ulong	tptr;
+	ushort	tbptr;
+	ushort	tcnt;
+	ulong	ttmp;
+};
+
+typedef struct SCCparam SCCparam;
+struct SCCparam {
+	IOCparam;
+	ulong	rcrc;
+	ulong	tcrc;
+};
+
+typedef struct SCC SCC;
+struct SCC {
+	ulong	gsmrl;
+	ulong	gsmrh;
+	ushort	psmr;
+	uchar	rsvscc0[2];
+	ushort	todr;
+	ushort	dsr;
+	ushort	scce;
+	uchar	rsvscc1[2];
+	ushort	sccm;
+	uchar	rsvscc3;
+	uchar	sccs;
+	ushort	irmode;
+	ushort	irsip;
+};
+
+typedef struct SMC SMC;
+struct SMC {
+	uchar	pad1[2];
+	ushort	smcmr;
+	uchar	pad2[2];
+	uchar	smce;
+	uchar	pad3[3];
+	uchar	smcm;
+	uchar	pad4[5];
+};
+
+typedef struct SPI SPI;
+struct SPI {
+	ushort	spmode;
+	uchar	res1[4];
+	uchar	spie;
+	uchar	res2[3];
+	uchar	spim;
+	uchar	res3[2];
+	uchar	spcom;
+	uchar	res4[10];
+};
+
+typedef struct USB USB;
+struct USB {	/* 823 only */
+	uchar	usmod;
+	uchar	usadr;
+	uchar	uscom;
+	uchar	rsvu1;
+	ushort	usep[4];
+	uchar	rsvu2[4];
+	ushort	usber;
+	uchar	rsvu3[2];
+	ushort	usbmr;
+	uchar	rsvu4;
+	uchar	usbs;
+	uchar	rsvu5[8];
+};
+
+typedef struct IMM IMM;
+struct IMM {
+	struct {	/* general SIU */
+		ulong	siumcr;
+		ulong	sypcr;
+		uchar	rsv0[0xE-0x8];
+		ushort	swsr;
+		ulong	sipend;
+		ulong	simask;
+		ulong	siel;
+		uchar	sivec;
+		uchar	padv[3];
+		ulong	tesr;
+		uchar	rsv1[0x30-0x24];
+		ulong	sdcr;
+		uchar	rsv2[0x80-0x34];
+	};
+	struct {	/* PCMCIA */
+		struct {
+			ulong	base;
+			ulong	option;
+		} pcmr[8];
+		uchar	rsv3[0xe0-0xc0];
+		ulong	pgcra;
+		ulong	pgcrb;
+		ulong	pscr;
+		uchar	rsv4[0xf0-0xec];
+		ulong	pipr;
+		uchar	rsv5[4];
+		ulong	per;
+		uchar	rsv6[4];
+	};
+	struct {	/* MEMC */
+		struct {
+			ulong	base;
+			ulong	option;
+		} memc[8];
+		uchar	rsv7a[0x24];
+		ulong	mar;
+		ulong	mcr;
+		uchar	rsv7b[4];
+		ulong	mamr;
+		ulong	mbmr;
+		ushort	mstat;
+		ushort	mptpr;
+		ulong	mdr;
+		uchar	rsv7c[0x80];
+	};
+	struct {	/* system integration timers */
+		ushort	tbscr;
+		uchar	rsv8a[2];
+		ulong	tbrefu;
+		ulong	tbrefl;
+		uchar	rsv8b[0x14];
+		ushort	rtcsc;
+		uchar	rsv8c[2];
+		ulong	rtc;
+		ulong	rtsec;
+		ulong	rtcal;
+		uchar	rsv8d[0x10];
+		ushort	piscr;
+		ushort	rsv8e;
+		ulong	pitc;
+		ulong	pitr;
+		uchar	rsv8f[0x34];
+	};
+	struct {	/* 280: clocks and resets */
+		ulong	sccr;
+		ulong	plprcr;
+		ulong	rsr;
+		uchar	rsv9[0x300-0x28c];
+	};
+	struct {	/* 300: system integration timers keys */
+		ulong	tbscrk;
+		ulong	tbrefuk;
+		ulong	tbreflk;
+		ulong	tbk;
+		uchar	rsv10a[0x10];
+		ulong	rtcsck;
+		ulong	rtck;
+		ulong	rtseck;
+		ulong	rtcalk;
+		uchar	rsv10b[0x10];
+		ulong	piscrk;
+		ulong	pitck;
+		uchar	rsv10c[0x38];
+	};
+	struct {	/* 380: clocks and resets keys */
+		ulong	sccrk;
+		ulong	plprcrk;
+		ulong	rsrk;
+		uchar	rsv11[0x800-0x38C];
+	};
+	struct {	/* 800: video controller */
+		ushort	vccr;
+		ushort	pad11a;
+		uchar	vsr;
+		uchar	pad11b;
+		uchar	vcmr;
+		uchar	pad11c;
+		ulong	vbcb;
+		ulong	pad11d;
+		ulong	vfcr0;
+		ulong	vfaa0;
+		ulong	vfba0;
+		ulong	vfcr1;
+		ulong	vfaa1;
+		ulong	vfba1;
+		uchar	rsv11a[0x840-0x828];
+	};
+	struct {	/* 840: LCD */
+		ulong	lccr;
+		ulong	lchcr;
+		ulong	lcvcr;
+		ulong	rsv11b;
+		ulong	lcfaa;
+		ulong	lcfba;
+		uchar	lcsr;
+		uchar	rsv11c[0x860-0x859];
+	};
+	struct {	/* 860: I2C */
+		uchar	i2mod;
+		uchar	rsv12a[3];
+		uchar	i2add;
+		uchar	rsv12b[3];
+		uchar	i2brg;
+		uchar	rsv12c[3];
+		uchar	i2com;
+		uchar	rsv12d[3];
+		uchar	i2cer;
+		uchar	rsv12e[3];
+		uchar	i2cmr;
+		uchar	rsv12[0x900-0x875];
+	};
+	struct {	/* 900: DMA */
+		uchar	rsv13[4];
+		ulong	sdar;
+		uchar	sdsr;
+		uchar	pad1[3];
+		uchar	sdmr;
+		uchar	pad2[3];
+		uchar	idsr1;
+		uchar	pad3[3];
+		uchar	idmr1;
+		uchar	pad4[3];
+		uchar	idsr2;
+		uchar	pad5[3];
+		uchar	idmr2;
+		uchar	pad6[0x930-0x91D];
+	};
+	struct {	/* CPM interrupt control */
+		ushort	civr;
+		uchar	pad7[0x940-0x932];
+		ulong	cicr;
+		ulong	cipr;
+		ulong	cimr;
+		ulong	cisr;
+	};
+	struct {	/* input/output port */
+		ushort	padir;
+		ushort	papar;
+		ushort	paodr;
+		ushort	padat;
+		uchar	pad8[8];
+		ushort	pcdir;
+		ushort	pcpar;
+		ushort	pcso;
+		ushort	pcdat;
+		ushort	pcint;
+		uchar	pad9[6];
+		ushort	pddir;
+		ushort	pdpar;
+		ushort	rsv14a;
+		ushort	pddat;
+		uchar	rsv14[0x980-0x978];
+	};
+	struct {	/* CPM timers */
+		ushort	tgcr;
+		uchar	rsv15a[0x990-0x982];
+		ushort	tmr1;
+		ushort	tmr2;
+		ushort	trr1;
+		ushort	trr2;
+		ushort	tcr1;
+		ushort	tcr2;
+		ushort	tcn1;
+		ushort	tcn2;
+		ushort	tmr3;
+		ushort	tmr4;
+		ushort	trr3;
+		ushort	trr4;
+		ushort	tcr3;
+		ushort	tcr4;
+		ushort	tcn3;
+		ushort	tcn4;
+		ushort	ter1;
+		ushort	ter2;
+		ushort	ter3;
+		ushort	ter4;
+		uchar	rsv15[0x9C0-0x9B8];
+	};
+	struct {	/* CPM */
+		ushort	cpcr;
+		uchar	res0[2];
+		ushort	rccr;
+		uchar	res1;
+		uchar	rmds;
+		uchar	res2a[4];
+		ushort	rctr1;
+		ushort	rctr2;
+		ushort	rctr3;
+		ushort	rctr4;
+		uchar	res2[2];
+		ushort	rter;
+		uchar	res3[2];
+		ushort	rtmr;
+		uchar	rsv16[0x9F0-0x9DC];
+	};
+	union {	/* BRG */
+		struct {
+			ulong	brgc1;
+			ulong	brgc2;
+			ulong	brgc3;
+			ulong	brgc4;
+		};
+		ulong	brgc[4];
+	};
+	uchar	skip0[0xAB2-0xA00];	/* USB, SCC, SMC, SPI: address using cpmdev(CP...)->regs */
+	struct {	/* PIP */
+		ushort	pipc;		/* not 823 */
+		ushort	ptpr;		/* not 823 */
+		ulong	pbdir;
+		ulong	pbpar;
+		uchar	pad10[2];
+		ushort	pbodr;
+		ulong	pbdat;
+		uchar	pad11[0xAE0-0xAC8];
+	};
+	struct {	/* SI */
+		ulong	simode;
+		uchar	sigmr;
+		uchar	pad12;
+		uchar	sistr;
+		uchar	sicmr;
+		uchar	pad13[4];
+		ulong	sicr;
+		ulong	sirp;
+		uchar	pad14[0xB00-0xAF4];
+	};
+	ulong	vcram[64];
+	ushort	siram[256];
+	ushort	lcdmap[256];
+};
--- /dev/null
+++ b/os/boot.original/rpcg/ip.h
@@ -1,0 +1,98 @@
+typedef struct Udphdr Udphdr;
+struct Udphdr
+{
+	uchar	d[6];		/* Ethernet destination */
+	uchar	s[6];		/* Ethernet source */
+	uchar	type[2];	/* Ethernet packet type */
+
+	uchar	vihl;		/* Version and header length */
+	uchar	tos;		/* Type of service */
+	uchar	length[2];	/* packet length */
+	uchar	id[2];		/* Identification */
+	uchar	frag[2];	/* Fragment information */
+
+	/* Udp pseudo ip really starts here */
+	uchar	ttl;	
+	uchar	udpproto;	/* Protocol */
+	uchar	udpplen[2];	/* Header plus data length */
+	uchar	udpsrc[4];	/* Ip source */
+	uchar	udpdst[4];	/* Ip destination */
+	uchar	udpsport[2];	/* Source port */
+	uchar	udpdport[2];	/* Destination port */
+	uchar	udplen[2];	/* data length */
+	uchar	udpcksum[2];	/* Checksum */
+};
+
+typedef struct Etherhdr Etherhdr;
+struct Etherhdr
+{
+	uchar	d[6];
+	uchar	s[6];
+	uchar	type[2];
+
+	/* Now we have the ip fields */
+	uchar	vihl;		/* Version and header length */
+	uchar	tos;		/* Type of service */
+	uchar	length[2];	/* packet length */
+	uchar	id[2];		/* Identification */
+	uchar	frag[2];	/* Fragment information */
+	uchar	ttl;		/* Time to live */
+	uchar	proto;		/* Protocol */
+	uchar	cksum[2];	/* Header checksum */
+	uchar	src[4];		/* Ip source */
+	uchar	dst[4];		/* Ip destination */
+};
+
+enum
+{
+	IP_VER		= 0x40,
+	IP_HLEN		= 0x05,			
+ 	UDP_EHSIZE	= 22,
+	UDP_PHDRSIZE	= 12,
+	UDP_HDRSIZE	= 20,
+	ETHER_HDR	= 14,
+	IP_UDPPROTO	= 17,
+	ET_IP		= 0x800,
+	Bcastip		= 0xffffffff,
+	BPportsrc	= 68,
+	BPportdst	= 67,
+	TFTPport	= 69,
+	Timeout		= 5000,	/* milliseconds */
+	Bootrequest 	= 1,
+	Bootreply   	= 2,
+	Tftp_READ	= 1,
+	Tftp_WRITE	= 2,
+	Tftp_DATA	= 3,
+	Tftp_ACK	= 4,
+	Tftp_ERROR	= 5,
+	Segsize		= 512,
+	TFTPSZ		= Segsize+10,
+};
+
+typedef struct Bootp Bootp;
+struct Bootp
+{
+	uchar	op;		/* opcode */
+	uchar	htype;		/* hardware type */
+	uchar	hlen;		/* hardware address len */
+	uchar	hops;		/* hops */
+	uchar	xid[4];		/* a random number */
+	uchar	secs[2];	/* elapsed snce client started booting */
+	uchar	pad[2];
+	uchar	ciaddr[4];	/* client IP address (client tells server) */
+	uchar	yiaddr[4];	/* client IP address (server tells client) */
+	uchar	siaddr[4];	/* server IP address */
+	uchar	giaddr[4];	/* gateway IP address */
+	uchar	chaddr[16];	/* client hardware address */
+	char	sname[64];	/* server host name (optional) */
+	char	file[128];	/* boot file name */
+	char	vend[128];	/* vendor-specific goo */
+};
+
+typedef struct Netaddr Netaddr;
+struct Netaddr
+{
+	ulong	ip;
+	ushort	port;
+	char	ea[Eaddrlen];
+};
--- /dev/null
+++ b/os/boot.original/rpcg/l.s
@@ -1,0 +1,388 @@
+#include "mem.h"
+
+/* special instruction definitions */
+#define	BDNE	BC	0,2,
+#define	BDNZ	BC	16,0,
+#define	NOOP	OR	R0,R0,R0
+
+/*
+ * common ppc special purpose registers
+ */
+#define DSISR	18
+#define DAR	19	/* Data Address Register */
+#define DEC	22	/* Decrementer */
+#define SRR0	26	/* Saved Registers (exception) */
+#define SRR1	27
+#define SPRG0	272	/* Supervisor Private Registers */
+#define SPRG1	273
+#define SPRG2	274
+#define SPRG3	275
+#define TBRU	269	/* Time base Upper/Lower (Reading) */
+#define TBRL	268
+#define TBWU	285	/* Time base Upper/Lower (Writing) */
+#define TBWL	284
+#define PVR	287	/* Processor Version */
+
+/*
+ * mpc82x-specific special purpose registers of interest here
+ */
+#define EIE	80
+#define EID	81
+#define NRI	82
+#define IMMR	638
+#define IC_CST	560
+#define IC_ADR	561
+#define IC_DAT	562
+#define DC_CST	568
+#define DC_ADR	569
+#define DC_DAT	570
+#define MI_CTR	784
+#define MI_AP	786
+#define MI_EPN	787
+#define MI_TWC	789
+#define MI_RPN	790
+#define MI_DBCAM	816
+#define MI_DBRAM0	817
+#define MI_DBRAM1	818
+#define MD_CTR	792
+#define M_CASID	793
+#define MD_AP	794
+#define MD_EPN	795
+#define M_TWB	796
+#define MD_TWC	797
+#define MD_RPN	798
+#define	M_TW	799
+#define	MD_DBCAM	824
+#define	MD_DBRAM0	825
+#define	MD_DBRAM1	826
+
+/* as on 603e, apparently mtmsr needs help in some chip revisions */
+#define	WAITMSR	SYNC; ISYNC
+
+/* use of SPRG registers in save/restore */
+#define	SAVER0	SPRG0
+#define	SAVER1	SPRG1
+#define	SAVELR	SPRG2
+#define	SAVECR	SPRG3
+
+#define	UREGSIZE	((8+32)*4)
+#define	UREGSPACE	(UREGSIZE+8)	/* allow for arg to trap, and align */
+
+/*
+ * This code is loaded by the ROM loader at location 0x3000,
+ * or lives in flash memory at FLASHMEM+0x100
+ * Move it to high memory so that it can load the kernel at 0x0000.
+ */
+
+#define LOADCODEBASE	0x3000	/* when downloaded in S records */
+#define FLASHCODEBASE	(FLASHMEM+0x20000+0x100)	/* when in flash */
+
+	TEXT	start(SB), $-4
+	MOVW	MSR, R3
+	MOVW	$(EE|IP|RI), R4
+	ANDN	R4, R3
+	OR	$ME, R3
+	SYNC
+	MOVW	R3, MSR	/* turn off interrupts but enable traps */
+	WAITMSR
+
+/*
+ * reset the caches and disable them for now
+ */
+	MOVW	SPR(IC_CST), R4	/* read and clear */
+	MOVW	$(5<<25), R4
+	MOVW	R4, SPR(IC_CST)	/* unlock all */
+	ISYNC
+	MOVW	$(6<<25), R4
+	MOVW	R4, SPR(IC_CST)	/* invalidate all */
+	ISYNC
+	MOVW	$(2<<25), R4
+	MOVW	R4, SPR(IC_CST)	/* disable i-cache */
+	ISYNC
+
+	SYNC
+	MOVW	SPR(DC_CST), R4	/* read and clear */
+	MOVW	$(10<<24), R4
+	MOVW	R4, SPR(DC_CST)	/* unlock all */
+	ISYNC
+	MOVW	$(12<<24), R4
+	MOVW	R4, SPR(DC_CST)	/* invalidate all */
+	ISYNC
+	MOVW	$(4<<24), R4
+	MOVW	R4, SPR(DC_CST)	/* disable i-cache */
+	ISYNC
+
+	MOVW	$7, R4
+	MOVW	R4, SPR(158)		/* cancel `show cycle' for normal instruction execution */
+
+/*
+ * set other system configuration values
+ */
+	MOVW	SPR(IMMR), R5		/* save initial space pointer */
+	MOVW	$INTMEM, R4
+	MOVW	R4, SPR(IMMR)		/* set internal memory base */
+	MOVW	$0xFFFFFF88, R3
+	MOVW	R3, 4(R4)	/* disable watchdog in sypcr */
+	MOVW	$0x01012440, R3
+	MOVW	R3, 0(R4)	/* siumcr */
+
+/*
+ * system initialisation (init and map DRAM)
+ */
+	MOVW	$0, R0
+	MOVW	$setSB(SB), R2
+#ifndef confrpcg
+	MOVW	$(0xF000<<16), R3
+/*MOVW R0, R3*/
+	ANDCC	R5, R3	/* initial space is high? */
+	BEQ	notrom
+	MOVW	$FLASHCODEBASE, R5	/* where $start(SB) actually is now */
+	MOVW	$start(SB), R4	/* logical start address */
+	SUB	R4, R5, R6	/* text relocation value */
+	MOVW	$etext(SB), R7
+	SUB	R4, R7
+	ADD	R5, R7	/* data address in ROM */
+	MOVW	$bdata(SB), R8
+	SUB	R8, R2
+	ADD	R7, R2	/* relocate SB: SB' = romdata+(SB-bdata) */
+	MOVW	$sysinit0(SB), R4
+	ADD	R6, R4	/* relocate sysinit0's address */
+	MOVW	R4, CTR
+	MOVW	$inmem(SB), R4
+	ADD	R6, R4
+	MOVW	R4, LR	/* and the return address */
+	BR	(CTR)	/* call sysinit0 */
+	TEXT	inmem(SB), $-4
+	MOVW	$FLASHCODEBASE, R3
+	BR	cpu0
+notrom:
+	MOVW	$start(SB), R6
+	SUB	R6, R2
+	ADD	$LOADCODEBASE, R2
+	BL	sysinit0(SB)
+	MOVW	$LOADCODEBASE, R3
+#endif
+
+/*
+ * cpu 0
+ *	relocate bootstrap to our link addresses for text and data
+ *	set new PC
+ */
+cpu0:
+	MOVW	$setSB(SB), R2	/* set correct static base register */
+#ifndef confrpcg
+	MOVW	$start(SB), R4
+	MOVW	$etext(SB), R5
+	SUB	R4, R5
+	CMP	R4, R3	/* already there? */
+	BNE	copytext
+	ADD	R5, R3	/* start of data image */
+#else
+	MOVW	$etext(SB), R3
+#endif
+	BR	copydata
+
+copytext:
+	ADD	$3, R5
+	SRAW	$2, R5
+	MOVW	R5, CTR
+	SUB	$4, R4
+	SUB	$4, R3
+copyt:			/* copy text */
+	MOVWU	4(R3), R5
+	MOVWU	R5, 4(R4)
+	BDNZ	copyt
+	ADD	$4, R3
+
+copydata:
+	/* copy data */
+	MOVW	$bdata(SB), R4
+	CMP	R4, R3	/* already there? */
+	BEQ	loadkpc
+	MOVW	$edata(SB), R5
+	SUB	R4, R5
+	ADD	$3, R5
+	SRAW	$2, R5
+	MOVW	R5, CTR
+	SUB	$4, R4
+	SUB	$4, R3
+copyd:
+	MOVWU	4(R3), R5
+	MOVWU	R5, 4(R4)
+	BDNZ	copyd
+#endif
+
+	/* load correct PC */
+loadkpc:
+	MOVW	$start1(SB), R3
+	MOVW	R3, LR
+	BR	(LR)
+TEXT start1(SB), $-4
+	MOVW	$edata(SB), R3
+	MOVW	$end(SB), R4
+	SUBCC	R3, R4
+	BLE	skipz
+	SRAW	$2, R4
+	MOVW	R4, CTR
+	SUB	$4, R3
+	MOVW	$0, R0
+zero:
+	MOVWU	R0, 4(R3)
+	BDNZ	zero
+skipz:
+	MOVW	$mach0(SB), R1
+	MOVW	R1, m(SB)
+	ADD	$(MACHSIZE-8), R1
+	MOVW	$0, R0
+
+	BL	sysinit0(SB)
+
+	BL	main(SB)
+	BR	0(PC)
+
+TEXT ledx(SB), $0
+
+	MOVW	$BCSRMEM, R8
+	MOVW	0(R8), R3
+	MOVW	$(0x0800<<16), R5
+	ANDN	R5, R3, R3
+	MOVW	R3, 0(R8)
+	BR	0(PC)
+
+TEXT	getmsr(SB), $0
+	MOVW	MSR, R3
+	RETURN
+
+TEXT	putmsr(SB), $0
+	SYNC
+	MOVW	R3, MSR
+	WAITMSR
+	RETURN
+
+TEXT	eieio(SB), $0
+	EIEIO
+	RETURN
+
+TEXT	idle(SB), $0
+	RETURN
+
+TEXT	spllo(SB), $0
+	MOVW	MSR, R3
+	OR	$EE, R3, R4
+	SYNC
+	MOVW	R4, MSR
+	WAITMSR
+	RETURN
+
+TEXT	splhi(SB), $0
+	MOVW	MSR, R3
+	RLWNM	$0, R3, $~EE, R4
+	SYNC
+	MOVW	R4, MSR
+	WAITMSR
+	RETURN
+
+TEXT	splx(SB), $0
+	MOVW	MSR, R4
+	RLWMI	$0, R3, $EE, R4
+	SYNC
+	MOVW	R4, MSR
+	WAITMSR
+	RETURN
+
+TEXT	gettbl(SB), $0
+/*	MOVW	SPR(TBRL), R3	*/
+	WORD	$0x7c6c42e6	/* mftbl on 8xx series */
+	RETURN
+
+TEXT	getpvr(SB), $0
+	MOVW	SPR(PVR), R3
+	RETURN
+
+TEXT	getimmr(SB), $0
+	MOVW	SPR(IMMR), R3
+	RETURN
+
+TEXT	getdec(SB), $0
+	MOVW	SPR(DEC), R3
+	RETURN
+
+TEXT	putdec(SB), $0
+	MOVW	R3, SPR(DEC)
+	RETURN
+
+/*
+ * save state in Ureg on kernel stack.
+ * enter with R0 giving the PC from the call to `exception' from the vector.
+ * on return, SB (R2) has been set, and R3 has the Ureg*
+ */
+TEXT saveureg(SB), $-4
+	SUB	$UREGSPACE, R1
+	MOVMW	R2, 48(R1)	/* r2:r31 */
+	MOVW	$setSB(SB), R2
+	MOVW	SPR(SAVER1), R4
+	MOVW	R4, 44(R1)
+	MOVW	SPR(SAVER0), R5
+	MOVW	R5, 40(R1)
+	MOVW	CTR, R6
+	MOVW	R6, 36(R1)
+	MOVW	XER, R4
+	MOVW	R4, 32(R1)
+	MOVW	SPR(SAVECR), R5	/* CR */
+	MOVW	R5, 28(R1)
+	MOVW	SPR(SAVELR), R6	/* LR */
+	MOVW	R6, 24(R1)
+	/* pad at 20(R1) */
+	MOVW	SPR(SRR0), R4
+	MOVW	R4, 16(R1)	/* old PC */
+	MOVW	SPR(SRR1), R5
+	MOVW	R5, 12(R1)
+	MOVW	R0, 8(R1)	/* cause/vector, encoded in LR from vector */
+	ADD	$8, R1, R3	/* Ureg* */
+	STWCCC	R3, (R1)	/* break any pending reservations */
+	MOVW	$0, R0	/* R0ISZERO */
+	BR	(LR)
+
+/*
+ * restore state from Ureg
+ * SB (R2) is unusable on return
+ */
+TEXT restoreureg(SB), $-4
+	MOVMW	48(R1), R2	/* r2:r31 */
+	/* defer R1 */
+	MOVW	40(R1), R0
+	MOVW	R0, SPR(SAVER0)
+	MOVW	36(R1), R0
+	MOVW	R0, CTR
+	MOVW	32(R1), R0
+	MOVW	R0, XER
+	MOVW	28(R1), R0
+	MOVW	R0, CR	/* CR */
+	MOVW	24(R1), R0
+	MOVW	R0, SPR(SAVELR)	/* LR */
+	/* pad, skip */
+	MOVW	16(R1), R0
+	MOVW	R0, SPR(SRR0)	/* old PC */
+	MOVW	12(R1), R0
+	MOVW	R0, SPR(SRR1)	/* old MSR */
+	/* cause, skip */
+	MOVW	44(R1), R1	/* old SP */
+	BR	(LR)
+
+TEXT	exception(SB), $-4
+	MOVW	R1, SPR(SAVER1)
+	MOVW	CR, R0
+	MOVW	R0, SPR(SAVECR)
+	MOVW	LR, R0
+	BL	saveureg(SB)
+	MOVW	$0, R0
+	BL	trap(SB)
+	BL	restoreureg(SB)
+	MOVW	SPR(SAVELR), R0
+	MOVW	R0, LR
+	MOVW	SPR(SAVER0), R0
+	ISYNC
+	RFI
+
+GLOBL	mach0+0(SB), $MACHSIZE
+GLOBL	m(SB), $4
--- /dev/null
+++ b/os/boot.original/rpcg/lib.h
@@ -1,0 +1,106 @@
+/*
+ * functions (possibly) linked in, complete, from libc.
+ */
+
+/*
+ * mem routines
+ */
+extern	void*	memccpy(void*, void*, int, long);
+extern	void*	memset(void*, int, long);
+extern	int	memcmp(void*, void*, long);
+extern	void*	memmove(void*, void*, long);
+extern	void*	memchr(void*, int, long);
+
+/*
+ * string routines
+ */
+extern	char*	strcat(char*, char*);
+extern	char*	strchr(char*, char);
+extern	int	strcmp(char*, char*);
+extern	char*	strcpy(char*, char*);
+extern	char*	strncat(char*, char*, long);
+extern	char*	strncpy(char*, char*, long);
+extern	int	strncmp(char*, char*, long);
+extern	long	strlen(char*);
+extern	char*	strrchr(char*, char);
+extern	char*	strstr(char*, char*);
+
+/*
+ * print routines
+ * 	Fconv isn't used but is defined to satisfy prototypes in libg.h
+ *	that are never called.
+ */
+typedef	struct Fconv Fconv;
+
+extern	char*	donprint(char*, char*, char*, void*);
+extern	int	sprint(char*, char*, ...);
+extern	int	print(char*, ...);
+
+#define	PRINTSIZE	256
+
+/*
+ * one-of-a-kind
+ */
+extern	int	atoi(char*);
+extern	long	strtol(char*, char**, int);
+extern	ulong	strtoul(char*, char**, int);
+extern	long	end;
+
+/*
+ * Syscall data structures
+ */
+
+#define	MORDER	0x0003	/* mask for bits defining order of mounting */
+#define	MREPL	0x0000	/* mount replaces object */
+#define	MBEFORE	0x0001	/* mount goes before others in union directory */
+#define	MAFTER	0x0002	/* mount goes after others in union directory */
+#define	MCREATE	0x0004	/* permit creation in mounted directory */
+#define	MMASK	0x0007	/* all bits on */
+
+#define	OREAD	0	/* open for read */
+#define	OWRITE	1	/* write */
+#define	ORDWR	2	/* read and write */
+#define	OEXEC	3	/* execute, == read but check execute permission */
+#define	OTRUNC	16	/* or'ed in (except for exec), truncate file first */
+#define	OCEXEC	32	/* or'ed in, close on exec */
+#define	ORCLOSE	64	/* or'ed in, remove on close */
+
+#define	NCONT	0	/* continue after note */
+#define	NDFLT	1	/* terminate after note */
+
+typedef struct Qid	Qid;
+typedef struct Dir	Dir;
+typedef struct Waitmsg	Waitmsg;
+
+#define	ERRLEN	64
+#define	DIRLEN	116
+#define	NAMELEN	28
+
+struct Qid
+{
+	ulong	path;
+	ulong	vers;
+};
+
+struct Dir
+{
+	char	name[NAMELEN];
+	char	uid[NAMELEN];
+	char	gid[NAMELEN];
+	Qid	qid;
+	ulong	mode;
+	long	atime;
+	long	mtime;
+	vlong	length;
+	short	type;
+	short	dev;
+};
+
+struct Waitmsg
+{
+	int	pid;		/* of loved one */
+	int	status;		/* unused; a placeholder */
+	ulong	time[3];	/* of loved one */
+	char	msg[ERRLEN];
+};
+#define	nelem(x)	(sizeof(x)/sizeof((x)[0]))
--- /dev/null
+++ b/os/boot.original/rpcg/libg.h
@@ -1,0 +1,418 @@
+#pragma	src	"/sys/src/libg"
+#pragma	lib	"libg.a"
+
+enum	/* constants for I/O to devgraphics */
+{
+	Tilehdr = 40,
+	Tilesize = 8000
+};
+
+/*
+ *  you may think it's a blit, but it's gnot
+ */
+enum
+{
+	EMAXMSG = 128+8192,	/* size of 9p header+data */
+};
+
+/*
+ * Types
+ */
+
+typedef struct	Bitmap		Bitmap;
+typedef struct	Display	Display;
+typedef struct	Point		Point;
+typedef struct	Rectangle 	Rectangle;
+typedef struct	Cursor		Cursor;
+typedef struct	Mouse		Mouse;
+typedef struct	Menu		Menu;
+typedef struct	Font		Font;
+typedef struct	Fontchar	Fontchar;
+typedef struct	Subfont		Subfont;
+typedef struct	Cachefont	Cachefont;
+typedef struct	Cacheinfo	Cacheinfo;
+typedef struct	Cachesubf	Cachesubf;
+typedef struct	Event		Event;
+typedef struct	Slave		Slave;
+typedef struct	Ebuf		Ebuf;
+typedef struct	RGB		RGB;
+typedef struct	Linedesc	Linedesc;
+typedef struct	DRefret	DRefret;
+
+struct DRefret
+{
+	int		n;	/* number of bytes */
+	int		dy;	/* number of lines */
+	uchar	*dp;	/* pointer to data */
+};
+
+struct	Point
+{
+	int	x;
+	int	y;
+};
+
+struct Rectangle
+{
+	Point min;
+	Point max;
+};
+
+typedef	DRefret DRefresh(Display*, int, Rectangle, uchar*, uchar*, int);
+
+struct	Bitmap
+{
+	Rectangle		r;		/* rectangle in data area, local coords */
+	Rectangle 	clipr;		/* clipping region */
+	int			ldepth;	/* log base 2 of number of bits per pixel */
+	ulong		*base;	/* pointer to start of data */
+	int			zero;		/* base+zero=&word containing (0,0) */
+	ulong		width;	/* width in words of total data area */
+	Display		*display;	/* if present */
+};
+
+struct	Display
+{
+	uchar		*data;	/* transfer buffer */
+	Rectangle		r;
+	int			ldepth;
+	Rectangle		bb;		/* bounding box of changes */
+	int			waste;	/* unused part of bb */
+	Rectangle		bound;	/* memory for boundin/boundout */
+	Bitmap		*image;	/* owner */
+	int			id;
+	int			fd;
+	int			ctlfd;
+	int			local;
+	int			bytewidth;
+	void			*drdata1;	/* storage for drefresh() */
+	void			*drdata2;	/* storage for drefresh() */
+	DRefresh		*drefresh;
+};
+
+
+struct	Mouse
+{
+	int	buttons;	/* bit array: LMR=124 */
+	Point	xy;
+	ulong	msec;
+};
+
+struct	Cursor
+{
+	Point	offset;
+	uchar	clr[2*16];
+	uchar	set[2*16];
+};
+
+struct Menu
+{
+	char	**item;
+	char	*(*gen)(int);
+	int	lasthit;
+};
+
+struct Linedesc
+{
+	int	x0;
+	int	y0;
+	char	xmajor;
+	char	slopeneg;
+	long	dminor;
+	long	dmajor;
+};
+
+/*
+ * Subfonts
+ *
+ * given char c, Subfont *f, Fontchar *i, and Point p, one says
+ *	i = f->info+c;
+ *	bitblt(b, Pt(p.x+i->left,p.y+i->top),
+ *		bitmap, Rect(i->x,i->top,(i+1)->x,i->bottom),
+ *		fc);
+ *	p.x += i->width;
+ * where bitmap b is the repository of the images.
+ *
+ */
+
+struct	Fontchar
+{
+	short	x;		/* left edge of bits */
+	uchar	top;		/* first non-zero scan-line */
+	uchar	bottom;		/* last non-zero scan-line + 1 */
+	char	left;		/* offset of baseline */
+	uchar	width;		/* width of baseline */
+};
+
+struct	Subfont
+{
+	short	n;		/* number of chars in font */
+	uchar	height;		/* height of bitmap */
+	char	ascent;		/* top of bitmap to baseline */
+	Fontchar *info;		/* n+1 character descriptors */
+	Bitmap	*bits;		/* of font */
+};
+
+enum
+{
+	/* starting values */
+	LOG2NFCACHE =	6,
+	NFCACHE =	(1<<LOG2NFCACHE),	/* #chars cached */
+	NFLOOK =	5,			/* #chars to scan in cache */
+	NFSUBF =	2,			/* #subfonts to cache */
+	/* max value */
+	MAXFCACHE =	2048+NFLOOK,		/* generous upper limit */
+	MAXSUBF =	50,			/* generous upper limit */
+	/* deltas */
+	DSUBF = 	4,
+	/* expiry ages */
+	SUBFAGE	=	10000,
+	CACHEAGE =	10000,
+};
+
+struct Cachefont
+{
+	Rune	min;	/* lowest rune value to be taken from subfont */
+	Rune	max;	/* highest rune value+1 to be taken from subfont */
+	int	offset;	/* position in subfont of character at min */
+	int	abs;	/* name has been made absolute */
+	char	*name;
+};
+
+struct Cacheinfo
+{
+	Rune		value;	/* value of character at this slot in cache */
+	ushort		age;
+	ulong		xright;	/* right edge of bits */
+	Fontchar;
+};
+
+struct Cachesubf
+{
+	ulong		age;	/* for replacement */
+	Cachefont	*cf;	/* font info that owns us */
+	Subfont		*f;	/* attached subfont */
+};
+
+struct Font
+{
+	char		*name;
+	short		height;	/* max height of bitmap, interline spacing */
+	short		ascent;	/* top of bitmap to baseline */
+	int			maxldepth;	/* over all loaded subfonts */
+	short		width;	/* widest so far; used in caching only */	
+	short		ldepth;	/* of images */
+	short		nsub;	/* number of subfonts */
+	ulong		age;	/* increasing counter; used for LRU */
+	int		ncache;	/* size of cache */
+	int		nsubf;	/* size of subfont list */
+	Cacheinfo	*cache;
+	Cachesubf	*subf;
+	Cachefont	**sub;	/* as read from file */
+	Bitmap	*cacheimage;
+};
+
+struct	Event
+{
+	int	kbdc;
+	Mouse	mouse;
+	int	n;		/* number of characters in mesage */
+	uchar	data[EMAXMSG];	/* message from an arbitrary file descriptor */
+};
+
+struct Slave{
+	int	pid;
+	Ebuf	*head;		/* queue of messages for this descriptor */
+	Ebuf	*tail;
+};
+
+struct Ebuf{
+	Ebuf	*next;
+	int	n;		/* number of bytes in buf */
+	uchar	buf[EMAXMSG];
+};
+
+struct RGB
+{
+	ulong	red;
+	ulong	green;
+	ulong	blue;
+};
+
+/*
+ * Codes for bitblt etc.
+ *
+ *	       D
+ *	     0   1
+ *         ---------
+ *	 0 | 1 | 2 |
+ *     S   |---|---|
+ * 	 1 | 4 | 8 |
+ *         ---------
+ *
+ *	Usually used as D|S; DorS is so tracebacks are readable.
+ */
+typedef
+enum	Fcode
+{
+	Zero		= 0x0,
+	DnorS		= 0x1,
+	DandnotS	= 0x2,
+	notS		= 0x3,
+	notDandS	= 0x4,
+	notD		= 0x5,
+	DxorS		= 0x6,
+	DnandS		= 0x7,
+	DandS		= 0x8,
+	DxnorS		= 0x9,
+	D		= 0xA,
+	DornotS		= 0xB,
+	S		= 0xC,
+	notDorS		= 0xD,
+	DorS		= 0xE,
+	F		= 0xF,
+} Fcode;
+
+/*
+ * Miscellany
+ */
+
+extern Point	 add(Point, Point), sub(Point, Point);
+extern Point	 mul(Point, int), div(Point, int);
+extern Rectangle rsubp(Rectangle, Point), raddp(Rectangle, Point), inset(Rectangle, int);
+extern Rectangle rmul(Rectangle, int), rdiv(Rectangle, int);
+extern Rectangle rshift(Rectangle, int), rcanon(Rectangle);
+extern Bitmap*	 balloc(Rectangle, int);
+extern Bitmap*	 ballocnomem(Rectangle, int);
+extern Bitmap*	 brealloc(Bitmap*, Rectangle, int);
+extern Bitmap*	 breallocnomem(Bitmap*, Rectangle, int);
+extern int		bbytewidth(Bitmap*, int*, int*);
+extern void	 bfree(Bitmap*);
+extern void	 bfreemem(Bitmap*);
+extern int	 rectclip(Rectangle*, Rectangle);
+extern void	 binit(void(*)(char*), char*, char*);
+extern void	 binit1(void(*)(char*), char*, char*, int);
+extern void	 bclose(void);
+extern void	 berror(char*);
+extern void	 bitblt(Bitmap*, Point, Bitmap*, Rectangle, Fcode);
+extern int	 bitbltclip(void*);
+extern Font*	 rdfontfile(char*, int);
+extern void	 ffree(Font*);
+extern void	fminldepth(Font*);
+extern Font*	 mkfont(Subfont*, Rune);
+extern Subfont*	 subfalloc(int, int, int, Fontchar*, Bitmap*);
+extern void	 subffree(Subfont*);
+extern int	 cachechars(Font*, char**, ushort*, int, int*);
+extern Point	 string(Bitmap*, Point, Font*, char*, Fcode);
+extern Point	 subfstring(Bitmap*, Point, Subfont*, char*, Fcode);
+extern void	 segment(Bitmap*, Point, Point, int, Fcode);
+extern void	 point(Bitmap*, Point, int, Fcode);
+extern void	 arc(Bitmap*, Point, Point, Point, int, Fcode);
+extern void	 circle(Bitmap*, Point, int, int, Fcode);
+extern void	 disc(Bitmap*, Point, int, int, Fcode);
+extern void	 ellipse(Bitmap*, Point, int, int, int, Fcode);
+extern long	 strwidth(Font*, char*);
+extern void	 agefont(Font*);
+extern int	 loadchar(Font*, Rune, Cacheinfo*, int, int);
+extern Point	 strsize(Font*, char*);
+extern long	 charwidth(Font*, Rune);
+extern void	 texture(Bitmap*, Rectangle, Bitmap*, Fcode);
+extern void	 wrbitmap(Bitmap*, int, int, uchar*);
+extern void	 rdbitmap(Bitmap*, int, int, uchar*);
+extern void	 wrbitmapfile(int, Bitmap*);
+extern Bitmap*	 rdbitmapfile(int);
+extern void	 wrsubfontfile(int, Subfont*);
+extern void	 wrcolmap(Bitmap*, RGB*);
+extern void	 rdcolmap(Bitmap*, RGB*);
+extern Subfont*	 rdsubfontfile(int, Bitmap*);
+extern void	_unpackinfo(Fontchar*, uchar*, int);
+
+extern int	 ptinrect(Point, Rectangle), rectinrect(Rectangle, Rectangle);
+extern int	 rectXrect(Rectangle, Rectangle);
+extern int	 eqpt(Point, Point), eqrect(Rectangle, Rectangle);
+extern void	 border(Bitmap*, Rectangle, int, Fcode);
+extern void	 cursorswitch(Cursor*);
+extern void	 cursorset(Point);
+extern Rectangle bscreenrect(Rectangle*);
+extern void	 bflush(void);
+extern void	 bexit(void);
+extern int	 _clipline(Rectangle, Point*, Point*, Linedesc*);
+extern int	 clipline(Rectangle, Point*, Point*);
+extern int	 clipr(Bitmap*, Rectangle);
+
+extern void	 einit(ulong);
+extern ulong	 estart(ulong, int, int);
+extern ulong	 etimer(ulong, int);
+extern ulong	 event(Event*);
+extern ulong	 eread(ulong, Event*);
+extern Ebuf*	 ebread(Slave*);
+extern Mouse	 emouse(void);
+extern int	 ekbd(void);
+extern int	 ecanread(ulong);
+extern int	 ecanmouse(void);
+extern int	 ecankbd(void);
+extern void	 ereshaped(Rectangle);	/* supplied by user */
+extern int	 menuhit(int, Mouse*, Menu*);
+extern Rectangle getrect(int, Mouse*);
+extern ulong	 rgbpix(Bitmap*, RGB);
+extern int	_gminor(long, Linedesc*);
+
+enum{
+	Emouse		= 1,
+	Ekeyboard	= 2,
+};
+
+enum
+{
+	MAXSLAVE = 32,
+};
+
+#define	Pt(x, y)		((Point){(x), (y)})
+#define	Rect(x1, y1, x2, y2)	((Rectangle){Pt(x1, y1), Pt(x2, y2)})
+#define	Rpt(p1, p2)		((Rectangle){(p1), (p2)})
+
+
+#define	Dx(r)	((r).max.x-(r).min.x)
+#define	Dy(r)	((r).max.y-(r).min.y)
+
+extern	Bitmap	screen;
+extern	Font	*font;
+extern	uchar	_btmp[8192];
+
+extern	int	_mousefd;
+extern	int	_cursorfd;
+
+#define	BGSHORT(p)		(((p)[0]<<0) | ((p)[1]<<8))
+#define	BG32INT(p)		((s32int)((BGSHORT(p)<<0) | (BGSHORT(p+2)<<16)))
+#define	BPSHORT(p, v)		((p)[0]=(v), (p)[1]=((v)>>8))
+#define	BP32INT(p, v)		(BPSHORT(p, ((s32int)v)), BPSHORT(p+2, ((s32int)v)>>16))
+
+ulong	*wordaddr(Bitmap*, Point);
+uchar	*byteaddr(Bitmap*, Point);
+int		dfree(Display*);
+int		dwritectl(Display*, char*, int);
+int		dreadctl(Display*, char*, int);
+int		dinfo(Display*, int, int*, Rectangle*);
+void*	dinit(Display*, Bitmap*, int, int);
+int		ddelete(Display*);
+void		dfreemem(Display*);
+int		dreadctl(Display*, char*, int);
+int		dwritectl(Display*, char*, int);
+void	dbound(Display*, Rectangle);
+void	bload(Bitmap*, Rectangle, uchar*);
+ulong	bunload(Bitmap*, Rectangle, uchar*);
+void		drefresh(Display*, Rectangle);
+Display	*dopen(char*, int, DRefresh*);
+Bitmap*	dbitmap(Display*, DRefresh*, int);
+void		dclose(Display*);
+void		dflush(Display*);
+void		_bltinit(void);
+Bitmap*	battach(Bitmap*, int, int);
+int		readmouse(Mouse*);
+int		atomouse(Mouse*, char*, int);
+
+/*
+ * Refresh functions
+ */
+DRefresh	drtexture;
+DRefresh	drbackstore;
--- /dev/null
+++ b/os/boot.original/rpcg/main.c
@@ -1,0 +1,527 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+#include "dosfs.h"
+
+typedef struct Type Type;
+typedef struct Medium Medium;
+typedef struct Mode Mode;
+
+enum {
+	Dany		= -1,
+	Nmedia		= 16,
+
+	/* DS1 switch options */
+	Sflashfs		= 1<<0,	/* take local fs from flash */
+	Snotflash		= 1<<1,	/* don't boot from flash */
+};
+
+enum {					/* type */
+	Tflash,
+	Tuart,
+	Tether,
+	Thard,
+
+	Tany		= -1,
+};
+
+enum {					/* flag and name */
+	Fnone		= 0x00,
+
+	Fdos		= 0x01,
+	Ndos		= 0x00,
+	Fboot		= 0x02,
+	Nboot		= 0x01,
+	Fbootp		= 0x04,
+	Nbootp		= 0x02,
+	Fflash		= 0x08,
+	Fuart		= 0x10,
+	NName		= 0x03,
+
+	Fany		= Fbootp|Fboot|Fdos|Fflash|Fuart,
+
+	Fini		= 0x10,
+	Fprobe		= 0x80,
+};
+
+enum {					/* mode */
+	Mauto		= 0x00,
+	Mlocal		= 0x01,
+	Manual		= 0x02,
+	NMode		= 0x03,
+};
+
+typedef struct Type {
+	int	type;
+	char	*cname;
+	int	flag;
+	int	(*init)(void);
+	long	(*read)(int, void*, long);
+	long	(*seek)(int, long);
+	Partition* (*setpart)(int, char*);
+	char*	name[NName];
+
+	int	mask;
+	Medium*	media;
+} Type;
+
+typedef struct Medium {
+	Type*	type;
+	int	flag;
+	Partition* partition;
+	Dos;
+
+	Medium*	next;
+} Medium;
+
+typedef struct Mode {
+	char*	name;
+	int	mode;
+} Mode;
+
+static Type types[] = {
+	{	Tflash, "flash",
+		Fflash,
+		flashinit, 0, 0, 0,
+		{ 0, "F", 0, }
+	},
+/*
+	{	Tuart, "uart",
+		Fuart|Fboot,
+		uartinit, uartread, uartseek, setuartpart,
+		{ 0, "u", 0, }
+	},
+*/
+	{	Tether, "ether",
+		Fbootp,
+		etherinit, 0, 0, 0,
+		{ 0, 0, "e", },
+	},
+	{	Thard, "ata",
+		Fini|Fboot|Fdos,
+		0, 0, 0, 0,		/* not used now, will be later with PCMCIA */
+		{ "hd", "h", 0, },
+	},
+	{-1},
+};
+
+static Medium media[Nmedia];
+static Medium *curmedium = media;
+
+static Mode modes[NMode+1] = {
+	[Mauto]		{ "auto",   Mauto,  },
+	[Mlocal]	{ "local",  Mlocal, },
+	[Manual]	{ "manual", Manual, },
+};
+
+static char *inis[] = {
+	"inferno/inferno.ini",
+	"inferno.ini",
+	"plan9/plan9.ini",
+	"plan9.ini",
+	0,
+};
+char **ini;
+int	predawn;
+
+static int
+parse(char *line, int *type, int *flag, int *dev, char *file)
+{
+	Type *tp;
+	char buf[2*NAMELEN], *v[4], *p;
+	int i;
+
+	strcpy(buf, line);
+	switch(getcfields(buf, v, 4, "!")){
+
+	case 3:
+		break;
+
+	case 2:
+		v[2] = "";
+		break;
+
+	default:
+		return 0;
+	}
+
+	*flag = 0;
+	for(tp = types; tp->cname; tp++){
+		for(i = 0; i < NName; i++){
+
+			if(tp->name[i] == 0 || strcmp(v[0], tp->name[i]))
+				continue;
+			*type = tp->type;
+			*flag |= 1<<i;
+
+			if((*dev = strtoul(v[1], &p, 0)) == 0 && p == v[1])
+				return 0;
+		
+			strcpy(file, v[2]);
+		
+			return 1;
+		}
+	}
+
+	return 0;
+
+}
+
+static int
+boot(Medium *mp, int flag, char *file)
+{
+	Dosfile df;
+	char ixdos[128], *p;
+	int r;
+
+	uartsetboot(0);
+	if(flag & Fbootp){
+		sprint(BOOTLINE, "%s!%d", mp->type->name[Nbootp], mp->dev);
+		return bootp(mp->dev, file);
+	}
+
+	if(flag & Fflash){
+		if(mp->flag & Fflash && flashbootable(0))
+			flashboot(mp->dev);
+	}
+
+	if(flag & Fboot){
+
+		if(mp->flag & Fini){
+			(*mp->type->setpart)(mp->dev, "disk");
+			plan9ini(mp, nil);
+		}
+		if(file == 0 || *file == 0)
+			file = mp->partition->name;
+		(*mp->type->setpart)(mp->dev, file);
+		sprint(BOOTLINE, "%s!%d!%s", mp->type->name[Nboot], mp->dev, file);
+		r = plan9boot(mp->dev, mp->seek, mp->read);
+		uartsetboot(0);
+		return r;
+	}
+
+	if(flag & Fdos){
+		if(mp->type->setpart)
+			(*mp->type->setpart)(mp->dev, "disk");
+		if(mp->flag & Fini)
+			plan9ini(mp, nil);
+		if(file == 0 || *file == 0){
+			strcpy(ixdos, *ini);
+			if(p = strrchr(ixdos, '/'))
+				p++;
+			else
+				p = ixdos;
+			strcpy(p, "impc");
+			if(dosstat(mp, ixdos, &df) <= 0)
+				return -1;
+		}
+		else
+			strcpy(ixdos, file);
+		sprint(BOOTLINE, "%s!%d!%s", mp->type->name[Ndos], mp->dev, ixdos);
+		return dosboot(mp, ixdos);
+	}
+
+	return -1;
+}
+
+static Medium*
+allocm(Type *tp)
+{
+	Medium **l;
+
+	if(curmedium >= &media[Nmedia])
+		return 0;
+
+	for(l = &tp->media; *l; l = &(*l)->next)
+		;
+	*l = curmedium++;
+	return *l;
+}
+
+Medium*
+probe(int type, int flag, int dev)
+{
+	Type *tp;
+	int dombr, i, start;
+	Medium *mp;
+	Dosfile df;
+	Partition *pp;
+
+	for(tp = types; tp->cname; tp++){
+		if(type != Tany && type != tp->type || tp->init == 0)
+			continue;
+
+		if(flag != Fnone){
+			for(mp = tp->media; mp; mp = mp->next){
+				if((flag & mp->flag) && (dev == Dany || dev == mp->dev))
+					return mp;
+			}
+		}
+		if((tp->flag & Fprobe) == 0){
+			tp->flag |= Fprobe;
+			tp->mask = (*tp->init)();
+		}
+
+		for(i = 0; tp->mask; i++){
+			if((tp->mask & (1<<i)) == 0)
+				continue;
+			tp->mask &= ~(1<<i);
+
+			if((mp = allocm(tp)) == 0)
+				continue;
+
+			mp->dev = i;
+			mp->flag = tp->flag;
+			mp->seek = tp->seek;
+			mp->read = tp->read;
+			mp->type = tp;
+
+			if(mp->flag & Fboot){
+				if((mp->partition = (*tp->setpart)(i, "boot")) == 0)
+					mp->flag &= ~Fboot;
+				if((mp->flag & (Fflash|Fuart)) == 0)
+					(*tp->setpart)(i, "disk");
+			}
+
+			if(mp->flag & Fdos){
+				start = 0;
+				dombr = 1;
+				if(mp->type->setpart){
+					if(pp = (*mp->type->setpart)(i, "dos")){
+						if(start = pp->start)
+							dombr = 0;
+					}
+					(*tp->setpart)(i, "disk");
+				}
+				if(dosinit(mp, start, dombr) < 0)
+					mp->flag &= ~(Fini|Fdos);
+				else
+					print("dos init failed\n");
+			}
+
+			if(mp->flag & Fini){
+				mp->flag &= ~Fini;
+				for(ini = inis; *ini; ini++){
+					if(dosstat(mp, *ini, &df) <= 0)
+						continue;
+					mp->flag |= Fini;
+					break;
+				}
+			}
+
+			if((flag & mp->flag) && (dev == Dany || dev == i))
+				return mp;
+		}
+	}
+
+	return 0;
+}
+
+void
+main(void)
+{
+	Medium *mp;
+	int dev, flag, i, mode, tried, type, options;
+	char def[2*NAMELEN], file[2*NAMELEN], line[80], *p;
+	Type *tp;
+
+	machinit();
+	archinit();
+	meminit();
+	cpminit();
+	trapinit();
+	consinit();	/* screen and keyboard initially */
+/*	screeninit();	*/
+	cpuidprint();
+	alarminit();
+	clockinit();
+print("predawn\n");
+	predawn = 0;
+	spllo();
+print("dawn\n");
+	options = archoptionsw();
+print("options=#%ux\n", options);
+
+	mp = 0;
+	for(tp = types; tp->cname; tp++){
+		if(tp->type == Tether)
+			continue;
+		if((mp = probe(tp->type, Fini, Dany)) && (mp->flag & Fini)){
+			plan9ini(mp, nil);
+			break;
+		}
+	}
+
+	if(mp == 0 || (mp->flag & Fini) == 0)
+		plan9ini(nil, flashconfig(0));
+
+	//consinit();	/* establish new console location */
+
+	if((options & Snotflash) == 0 && flashbootable(0)){
+		print("Flash boot\n");
+		flashboot(0);
+	}
+
+	tried = 0;
+	mode = Mauto;
+	p = getconf("bootfile");
+	flag = 0;
+
+	if(p != 0) {
+		mode = Manual;
+		for(i = 0; i < NMode; i++){
+			if(strcmp(p, modes[i].name) == 0){
+				mode = modes[i].mode;
+				goto done;
+			}
+		}
+		if(parse(p, &type, &flag, &dev, file) == 0) {
+			print("Bad bootfile syntax: %s\n", p);
+			goto done;
+		}
+		mp = probe(type, flag, dev);
+		if(mp == 0) {
+			print("Cannot access device: %s\n", p);
+			goto done;
+		}
+		tried = boot(mp, flag, file);
+	}
+done:
+	if(tried == 0 && mode != Manual){
+		flag = Fany;
+		if(mode == Mlocal)
+			flag &= ~Fbootp;
+		if(options & Snotflash)
+			flag &= ~Fflash;
+		if((mp = probe(Tany, flag, Dany)) != 0)
+			boot(mp, flag & mp->flag, 0);
+	}
+
+	def[0] = 0;
+	probe(Tany, Fnone, Dany);
+
+	flag = 0;
+	for(tp = types; tp->cname; tp++){
+		for(mp = tp->media; mp; mp = mp->next){
+			if(flag == 0){
+				flag = 1;
+				print("Boot devices:");
+			}
+
+			if(mp->flag & Fbootp)
+				print(" %s!%d", mp->type->name[Nbootp], mp->dev);
+			if(mp->flag & Fdos)
+				print(" %s!%d", mp->type->name[Ndos], mp->dev);
+			if(mp->flag & (Fflash|Fuart) || mp->flag & Fboot)
+				print(" %s!%d", mp->type->name[Nboot], mp->dev);
+		}
+	}
+	if(flag)
+		print("\n");
+
+	for(;;){
+		if(getstr("boot from", line, sizeof(line), def) >= 0){
+			if(parse(line, &type, &flag, &dev, file)){
+				if(mp = probe(type, flag, dev))
+					boot(mp, flag, file);
+			}
+		}
+		def[0] = 0;
+	}
+}
+
+void
+machinit(void)
+{
+	memset(m, 0, sizeof(*m));
+	m->delayloop = 20000;
+	m->cpupvr = getpvr();
+	m->iomem = KADDR(INTMEM);
+}
+
+int
+getcfields(char* lp, char** fields, int n, char* sep)
+{
+	int i;
+
+	for(i = 0; lp && *lp && i < n; i++){
+		while(*lp && strchr(sep, *lp) != 0)
+			*lp++ = 0;
+		if(*lp == 0)
+			break;
+		fields[i] = lp;
+		while(*lp && strchr(sep, *lp) == 0){
+			if(*lp == '\\' && *(lp+1) == '\n')
+				*lp++ = ' ';
+			lp++;
+		}
+	}
+
+	return i;
+}
+
+static	Map	memv[512];
+static	RMap	rammap = {"physical memory"};
+
+void
+meminit(void)
+{
+	ulong e;
+
+	mapinit(&rammap, memv, sizeof(memv));
+	e = PADDR(&end);
+	mapfree(&rammap, e, 4*1024*1024-e);	/* fixed 4Mbytes is plenty for bootstrap */
+}
+
+void*
+ialloc(ulong n, int align)
+{
+	ulong a;
+	int s;
+
+	if(align <= 0)
+		align = 4;
+	s = splhi();
+	a = mapalloc(&rammap, 0, n, align);
+	splx(s);
+	if(a == 0)
+		panic("ialloc");
+	return memset(KADDR(a), 0, n);
+}
+
+void*
+malloc(ulong n)
+{
+	ulong *p;
+
+	n = ((n+sizeof(int)-1)&~(sizeof(int)-1))+2*sizeof(int);
+	p = ialloc(n, sizeof(int));
+	*p++ = 0xcafebeef;
+	*p++ = n;
+	return p;
+}
+
+void
+free(void *ap)
+{
+	int s;
+	ulong *p;
+
+	p = ap;
+	if(p){
+		if(*(p -= 2) != 0xcafebeef)
+			panic("free");
+		s = splhi();
+		mapfree(&rammap, (ulong)p, p[1]);
+		splx(s);
+	}
+}
+
+void
+sched(void)
+{
+}
--- /dev/null
+++ b/os/boot.original/rpcg/mem.h
@@ -1,0 +1,94 @@
+/*
+ * Memory and machine-specific definitions.  Used in C and assembler.
+ */
+
+/*
+ * Sizes
+ */
+#define	BI2BY		8			/* bits per byte */
+#define BI2WD		32			/* bits per word */
+#define	BY2WD		4			/* bytes per word */
+#define	BY2PG		4096			/* bytes per page */
+#define	WD2PG		(BY2PG/BY2WD)		/* words per page */
+#define	PGSHIFT		12			/* log(BY2PG) */
+#define PGROUND(s)	(((s)+(BY2PG-1))&~(BY2PG-1))
+
+#define	MAXMACH		1			/* max # cpus system can run */
+#define	CACHELINELOG	4
+#define CACHELINESZ	(1<<CACHELINELOG)
+
+/*
+ * Time
+ */
+#define	HZ		(50)				/* clock frequency */
+#define	MS2HZ		(1000/HZ)			/* millisec per clock tick */
+#define	TK2SEC(t)	((t)/HZ)			/* ticks to seconds */
+#define	TK2MS(t)	((((ulong)(t))*1000)/HZ)	/* ticks to milliseconds */
+#define	MS2TK(t)	((((ulong)(t))*HZ)/1000)	/* milliseconds to ticks */
+#define	MHz	1000000
+
+/*
+ * Fundamental values
+ */
+
+#define	KZERO	0	/* bootstrap runs in real mode */
+#define	MACHSIZE	4096
+
+/*
+ *  physical MMU
+ */
+#define KSEG0	0x20000000
+#define	KSEGM	0xE0000000	/* mask to check which seg */
+
+/*
+ * MSR bits
+ */
+
+#define	POW	0x40000	/* enable power mgmt */
+#define	TGPR	0x20000	/* GPR0-3 remapped; 603/603e specific */
+#define	ILE	0x10000	/* interrupts little endian */
+#define	EE	0x08000	/* enable external/decrementer interrupts */
+#define	PR	0x04000	/* =1, user mode */
+#define	FPE	0x02000	/* enable floating point */
+#define	ME	0x01000	/* enable machine check exceptions */
+#define	FE0	0x00800
+#define	SE	0x00400	/* single-step trace */
+#define	BE	0x00200	/* branch trace */
+#define	FE1	0x00100
+#define	IP	0x00040	/* =0, vector to nnnnn; =1, vector to FFFnnnnn */
+#define	IR	0x00020	/* enable instruction address translation */
+#define	DR	0x00010	/* enable data address translation */
+#define	RI	0x00002	/* exception is recoverable */
+#define	LE	0x00001	/* little endian mode */
+
+#define	KMSR	(ME|FE0|FE1|FPE)
+#define	UMSR	(KMSR|PR|EE|IR|DR)
+
+/*
+ * MPC82x addresses
+ */
+#define	BCSRMEM	0xFA400000
+#define	FLASHMEM	0xFFC00000
+#define	INTMEM	0xFA200000
+
+#define	DPRAM	(INTMEM+0x2000)
+#define	DPLEN1	0x400
+#define	DPLEN2	0x200
+#define	DPLEN3	0x100
+#define	DPBASE	(DPRAM+DPLEN1)
+
+#define	SCC1P	(INTMEM+0x3C00)
+#define	I2CP	(INTMEM+0x3C80)
+#define	MISCP	(INTMEM+0x3CB0)
+#define	IDMA1P	(INTMEM+0x3CC0)
+#define	SCC2P	(INTMEM+0x3D00)
+#define	SCC3P	(INTMEM+0x3E00)
+#define	SCC4P	(INTMEM+0x3F00)
+#define	SPIP	(INTMEM+0x3D80)
+#define	TIMERP	(INTMEM+0x3DB0)
+#define	SMC1P	(INTMEM+0x3E80)
+#define	DSP1P	(INTMEM+0x3EC0)
+#define	SMC2P	(INTMEM+0x3F80)
+#define	DSP2P	(INTMEM+0x3FC0)
+
+#define KEEP_ALIVE_KEY 0x55ccaa33	/* clock and rtc register key */
--- /dev/null
+++ b/os/boot.original/rpcg/mkfile
@@ -1,0 +1,120 @@
+objtype=power
+OBJTYPE=power	# always
+<../../../mkconfig
+SYSTARG=$OSTARG	# always
+<$ROOT/mkfiles/mkfile-$SYSTARG-$OBJTYPE
+INSTALLDIR=$ROOT/Inferno/$OBJTYPE/bin	#path of directory where kernel is installed
+CONF=rpcg	# selects board dependent code
+TARG=qb$CONF
+OFILES=\
+	l.$O\
+	arch$CONF.$O\
+	devuart.$O\
+	uartboot.$O\
+	alarm.$O\
+	bootp.$O\
+	clock.$O\
+	conf.$O\
+	console.$O\
+	cpm.$O\
+	defont0.$O\
+	donprint.$O\
+	dosboot.$O\
+	devether.$O\
+	etherscc.$O\
+	fblt.$O\
+	gbitbltclip.$O\
+	flash.$O\
+	main.$O\
+	i2c.$O\
+	plan9boot.$O\
+	qio.$O\
+	rmap.$O\
+	screen.$O\
+	init$CONF.$O\
+	trap.$O\
+	zqs.$O\
+
+HFILES=\
+	boot.h\
+	dat.h\
+	fns.h\
+	io.h\
+	lib.h\
+	mem.h\
+	squeeze.h\
+	gnot.h\
+	arch$CONF.h\
+
+LIBS=\
+	kern\
+
+LIBDIRS=$LIBS
+LIBNAMES=${LIBS:%=lib%.a}
+LIBFILES=${LIBS:%=$ROOT/$TARGMODEL/$OBJTYPE/lib/lib%.a}
+
+#all:NV:	$TARG k.mx f.mx
+all:NV:	$TARG
+install:V: 	$INSTALLDIR/$TARG
+installall:V: 	$INSTALLDIR/$TARG
+
+$INSTALLDIR/%: %
+	rm -f $INSTALLDIR/$stem && cp $stem $INSTALLDIR/$stem
+
+$TARG: $OFILES $LIBNAMES
+	$LD -o $target -l  -T0x140000 -R4 $OFILES $LIBFILES
+	ls -l $target
+
+qbrom$CONF:	$OFILES $LIBNAMES
+	$LD -o $target -l -T0xFFC20100 -R0 -D0x140000 $OFILES $LIBFILES
+
+k.mx:	$TARG
+	ms2 -S 0x100 -a 0x140000 -3 -p 4 $TARG >$target
+
+f.mx:	qbrom$CONF
+	ms2 -S 0x100 -a 0xFFC20100 -3 -p 4 $prereq >$target
+
+g.mx:	qbrom$CONF
+	ms2 -S 0x100 -a 0x10000 -3 -p 4 $prereq >$target
+
+%.$O:	%.s
+	$AS -Dconf$CONF $stem.s
+
+%.$O:	%.c
+	$CC $CFLAGS $stem.c
+
+%.$O:	$HFILES
+
+lib%.a:V:	$SHELLTYPE-lib%.a
+
+rc-lib%.a nt-lib%.a:VQ:
+	echo '@{builtin cd ' $ROOT/lib$stem ';mk SHELLTYPE=$SHELLTYPE SYSTARG=$SYSTARG OBJTYPE=$OBJTYPE install}'
+	@{builtin cd  $ROOT/lib$stem ;mk 'SHELLTYPE='$SHELLTYPE 'SYSTARG='$SYSTARG 'OBJTYPE='$OBJTYPE install}
+
+sh-lib%.a:VQ:
+	echo "(cd $ROOT/lib$stem ; mk SHELLTYPE=$SHELLTYPE SYSTARG=$SYSTARG OBJTYPE=$OBJTYPE install)"
+	(cd $ROOT/lib$stem ; mk SHELLTYPE=$SHELLTYPE SYSTARG=$SYSTARG OBJTYPE=$OBJTYPE install)
+
+clock.$O floppy.$O trap.$O:	ureg.h
+conf.$O dosboot.$O main.$O:	dosfs.h
+ether.$O etherscc.$O:	etherif.h
+bootp.$O:	ip.h
+
+clean:V:
+	rm -f *.[$OS] [$OS].out y.tab.? y.debug y.output $TARG qboot k.mx f.mx romboot
+
+nuke-sh:QV:
+		for i in $LIBDIRS
+		do
+			echo "(cd $ROOT/lib$i ; mk SHELLTYPE=$SHELLTYPE SYSTARG=$SYSTARG OBJTYPE=$OBJTYPE nuke)"
+			(cd $ROOT/lib$i; mk 'SHELLTYPE='$SHELLTYPE 'SYSTARG='$SYSTARG 'OBJTYPE='$OBJTYPE nuke)
+		done
+
+nuke-rc nuke-nt:QV:
+		for (i in $LIBDIRS)
+		{
+			echo '@{cd $ROOT/lib$i ; mk SHELLTYPE=$SHELLTYPE SYSTARG=$SYSTARG OBJTYPE=$OBJTYPE nuke}'
+			@{cd $ROOT/lib$i; mk 'SHELLTYPE='$SHELLTYPE 'SYSTARG='$SYSTARG 'OBJTYPE='$OBJTYPE nuke}
+		}
+
+nuke:V:		clean nuke-$SHELLTYPE
--- /dev/null
+++ b/os/boot.original/rpcg/ms2.c
@@ -1,0 +1,179 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+#include <mach.h>
+
+void	record(uchar*, int);
+void	usage(void);
+void	dosegment(long, int);
+void trailer(ulong);
+
+enum
+{
+	Recordsize = 32,
+};
+
+int	dsegonly;
+int	supressend;
+int	binary;
+int	addr4;
+ulong	addr;
+ulong 	psize = 4096;
+ulong	startaddr = 0x030000;
+Biobuf 	stdout;
+Biobuf	bio;
+
+void
+main(int argc, char **argv)
+{
+	Dir dir;
+	Fhdr f;
+	int fd;
+
+	ARGBEGIN{
+	case 'd':
+		dsegonly++;
+		break;
+	case 's':
+		supressend++;
+		break;
+	case 'a':
+		addr = strtoul(ARGF(), 0, 0);
+		break;
+	case 'p':
+		psize = strtoul(ARGF(), 0, 0);
+		break;
+	case 'b':
+		binary++;
+		break;
+	case 'S':
+		startaddr = strtoul(ARGF(), 0, 0);
+		break;
+	case '4':
+		addr4++;
+		break;
+	default:
+		usage();
+	}ARGEND
+
+	if(argc != 1)
+		usage();
+
+	Binit(&stdout, 1, OWRITE);
+
+	fd = open(argv[0], OREAD);
+	if(fd < 0) {
+		fprint(2, "ms2: open %s: %r\n", argv[0]);
+		exits("open");
+	}
+
+	if(binary) {
+		if(dirfstat(fd, &dir) < 0) {
+			fprint(2, "ms2: stat failed %r");
+			exits("dirfstat");
+		}
+		Binit(&bio, fd, OREAD);
+		dosegment(0, dir.length);
+		if(supressend == 0)
+			trailer(startaddr);
+		Bterm(&stdout);
+		Bterm(&bio);
+		exits(0);
+	}
+
+	if(crackhdr(fd, &f) == 0){
+		fprint(2, "ms2: bad magic: %r\n");
+		exits("magic");
+	}
+	seek(fd, 0, 0);
+
+	Binit(&bio, fd, OREAD);
+
+	if(dsegonly)
+		dosegment(f.datoff, f.datsz);
+	else {
+		dosegment(f.txtoff, f.txtsz);
+		addr = (addr+(psize-1))&~(psize-1);
+		dosegment(f.datoff, f.datsz);
+	}
+
+	if(supressend == 0)
+		trailer(startaddr);
+
+	Bterm(&stdout);
+	Bterm(&bio);
+	exits(0);
+}
+
+void
+dosegment(long foff, int len)
+{
+	int l, n;
+	uchar buf[2*Recordsize];
+
+	Bseek(&bio, foff, 0);
+	for(;;) {
+		l = len;
+		if(l > Recordsize)
+			l = Recordsize;
+		n = Bread(&bio, buf, l);
+		if(n == 0)
+			break;
+		if(n < 0) {
+			fprint(2, "ms2: read error: %r\n");
+			exits("read");
+		}
+		record(buf, l);
+		len -= l;
+	}
+}
+
+void
+record(uchar *s, int l)
+{
+	int i;
+	ulong cksum;
+
+	if(addr4 || addr & (0xFF<<24)){
+		Bprint(&stdout, "S3%.2X%.8luX", l+5, addr);
+		cksum = l+5;
+		cksum += (addr>>24)&0xff;
+	}else{
+		Bprint(&stdout, "S2%.2X%.6X", l+4, addr);
+		cksum = l+4;
+	}
+	cksum += addr&0xff;
+	cksum += (addr>>8)&0xff;
+	cksum += (addr>>16)&0xff;
+
+	for(i = 0; i < l; i++) {
+		cksum += *s;
+		Bprint(&stdout, "%.2X", *s++);
+	}
+	Bprint(&stdout, "%.2X\n", (~cksum)&0xff);
+	addr += l;
+}
+
+void
+trailer(ulong a)
+{
+	ulong cksum;
+
+	cksum = 0;
+	if(addr4 || a & (0xFF<<24)){
+		Bprint(&stdout, "S7%.8luX", a);
+		cksum += (a>>24)&0xff;
+	}else
+		Bprint(&stdout, "S9%.6X", a);
+	cksum += a&0xff;
+	cksum += (a>>8)&0xff;
+	cksum += (a>>16)&0xff;
+	Bprint(&stdout, "%.2X\n", (~cksum)&0xff);
+}
+
+void
+usage(void)
+{
+	fprint(2, "usage: ms2 [-ds] [-a address] [-p pagesize] ?.out\n");
+	exits("usage");
+}
--- /dev/null
+++ b/os/boot.original/rpcg/plan9boot.c
@@ -1,0 +1,96 @@
+#include	"u.h"
+#include	"lib.h"
+#include	"mem.h"
+#include	"dat.h"
+#include	"fns.h"
+
+char *premature = "premature EOF\n";
+
+/*
+ *  read in a segment
+ */
+static long
+readseg(int dev, long (*read)(int, void*, long), long len, long addr)
+{
+	char *a;
+	long n, sofar;
+
+	a = (char *)addr;
+	for(sofar = 0; sofar < len; sofar += n){
+		n = 8*1024;
+		if(len - sofar < n)
+			n = len - sofar;
+		n = (*read)(dev, a + sofar, n);
+		if(n <= 0)
+			break;
+		print(".");
+	}
+	return sofar;
+}
+
+/*
+ *  boot
+ */
+int
+plan9boot(int dev, long (*seek)(int, long), long (*read)(int, void*, long))
+{
+	long n;
+	long addr;
+	void (*b)(void);
+	Exec *ep;
+
+	if((*seek)(dev, 0) < 0)
+		return -1;
+
+	/*
+	 *  read header
+	 */
+	ep = (Exec *) ialloc(sizeof(Exec), 0);
+	n = sizeof(Exec);
+	if(readseg(dev, read, n, (long) ep) != n){
+		print(premature);
+		return -1;
+	}
+	if(GLLONG(ep->magic) != Q_MAGIC){
+		print("bad magic 0x%lux not a plan 9 executable!\n", GLLONG(ep->magic));
+		return -1;
+	}
+
+	/*
+	 *  read text
+	 */
+	addr = PADDR(GLLONG(ep->entry));
+	n = GLLONG(ep->text);
+	print("%d", n);
+	if(readseg(dev, read, n, addr) != n){
+		print(premature);
+		return -1;
+	}
+
+	/*
+	 *  read data (starts at first page after kernel)
+	 */
+	addr = PGROUND(addr+n);
+	n = GLLONG(ep->data);
+	print("+%d@%8.8lux", n, addr);
+	if(readseg(dev, read, n, addr) != n){
+		print(premature);
+		return -1;
+	}
+
+	/*
+	 *  bss and entry point
+	 */
+	print("+%d\nstart at 0x%lux\n", GLLONG(ep->bss), GLLONG(ep->entry));
+	uartwait();
+	scc2stop();
+	splhi();
+
+	/*
+	 *  Go to new code. It's up to the program to get its PC relocated to
+	 *  the right place.
+	 */
+	b = (void (*)(void))(PADDR(GLLONG(ep->entry)));
+	(*b)();
+	return 0;
+}
binary files /dev/null b/os/boot.original/rpcg/qbromrpcg differ
--- /dev/null
+++ b/os/boot.original/rpcg/qio.c
@@ -1,0 +1,128 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+struct Queue {
+	Block*	first;
+	Block*	last;
+	void	(*kick)(void*);
+	void*	arg;
+	long	len;
+};
+
+Block *
+iallocb(int n)
+{
+	Block *b;
+
+	b = (Block*)malloc(sizeof(Block)+n);
+	b->data = (uchar*)b + sizeof(Block);
+	b->rp = b->wp = b->data;
+	b->lim = b->data + n;
+	b->next = 0;
+	b->magic = 0xcafebee0;
+	return b;
+}
+
+void
+freeb(Block *b)
+{
+	if(b){
+		if(b->magic != 0xcafebee0)
+			panic("freeb");
+		b->magic = 0;
+		b->next = (Block*)0xdeadbabe;
+		free(b);
+	}
+}
+
+Queue *
+qopen(int limit, int msg, void (*kick)(void*), void *arg)
+{
+	Queue *q;
+
+	USED(limit, msg);
+	q = (Queue*)malloc(sizeof(Queue));
+	q->first = q->last = 0;
+	q->kick = kick;
+	q->arg = arg;
+	q->len = 0;
+	return q;
+}
+
+Block *
+qget(Queue *q)
+{
+	int s;
+	Block *b;
+
+	s = splhi();
+	if((b = q->first) != 0){
+		q->first = b->next;
+		b->next = 0;
+		q->len -= BLEN(b);
+		if(q->len < 0)
+			panic("qget");
+	}
+	splx(s);
+	return b;
+}
+
+void
+qbwrite(Queue *q, Block *b)
+{
+	int s;
+
+	s = splhi();
+	b->next = 0;
+	if(q->first == 0)
+		q->first = b;
+	else
+		q->last->next = b;
+	q->last = b;
+	q->len += BLEN(b);
+	splx(s);
+	if(q->kick)
+		q->kick(q->arg);
+}
+
+long
+qlen(Queue *q)
+{
+	return q->len;
+}
+
+int
+qbgetc(Queue *q)
+{
+	Block *b;
+	int s, c;
+
+	c = -1;
+	s = splhi();
+	while(c < 0 && (b = q->first) != nil){
+		if(b->rp < b->wp){
+			c = *b->rp++;
+			q->len--;
+		}
+		if(b->rp >= b->wp){
+			q->first = b->next;
+			b->next = nil;
+		}
+	}
+	splx(s);
+	return c;
+}
+
+void
+qbputc(Queue *q, int c)
+{
+	Block *b;
+
+	b = iallocb(1);
+	*b->wp++ = c;
+	qbwrite(q, b);
+}
--- /dev/null
+++ b/os/boot.original/rpcg/rmap.c
@@ -1,0 +1,104 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+
+void
+mapinit(RMap *rmap, Map *map, int size)
+{
+	lock(rmap);
+	rmap->map = map;
+	rmap->mapend = map+(size/sizeof(Map));
+	unlock(rmap);
+}
+
+void
+mapfree(RMap* rmap, ulong addr, int size)
+{
+	Map *mp;
+	ulong t;
+
+	if(size <= 0)
+		return;
+
+	lock(rmap);
+	for(mp = rmap->map; mp->addr <= addr && mp->size; mp++)
+		;
+
+	if(mp > rmap->map && (mp-1)->addr+(mp-1)->size == addr){
+		(mp-1)->size += size;
+		if(addr+size == mp->addr){
+			(mp-1)->size += mp->size;
+			while(mp->size){
+				mp++;
+				(mp-1)->addr = mp->addr;
+				(mp-1)->size = mp->size;
+			}
+		}
+	}
+	else{
+		if(addr+size == mp->addr && mp->size){
+			mp->addr -= size;
+			mp->size += size;
+		}
+		else do{
+			if(mp >= rmap->mapend){
+				print("mapfree: %s: losing 0x%uX, %d\n",
+					rmap->name, addr, size);
+				break;
+			}
+			t = mp->addr;
+			mp->addr = addr;
+			addr = t;
+			t = mp->size;
+			mp->size = size;
+			mp++;
+		}while(size = t);
+	}
+	unlock(rmap);
+}
+
+ulong
+mapalloc(RMap* rmap, ulong addr, int size, int align)
+{
+	Map *mp;
+	ulong maddr, oaddr;
+
+	lock(rmap);
+	for(mp = rmap->map; mp->size; mp++){
+		maddr = mp->addr;
+
+		if(addr){
+			if(maddr > addr)
+				continue;
+			if(addr+size > maddr+mp->size)
+				break;
+			maddr = addr;
+		}
+
+		if(align > 0)
+			maddr = ((maddr+align-1)/align)*align;
+		if(mp->addr+mp->size-maddr < size)
+			continue;
+
+		oaddr = mp->addr;
+		mp->addr = maddr+size;
+		mp->size -= maddr-oaddr+size;
+		if(mp->size == 0){
+			do{
+				mp++;
+				(mp-1)->addr = mp->addr;
+			}while((mp-1)->size = mp->size);
+		}
+
+		unlock(rmap);
+		if(oaddr != maddr)
+			mapfree(rmap, oaddr, maddr-oaddr);
+
+		return maddr;
+	}
+	unlock(rmap);
+
+	return 0;
+}
--- /dev/null
+++ b/os/boot.original/rpcg/screen.c
@@ -1,0 +1,242 @@
+#include	"all.h"
+#include	<libg.h>
+#include	<gnot.h>
+
+enum {
+	Colldepth		= 3,
+	Colmaxx		= 640,
+	Colmaxxvis	= 640,
+	Colmaxy		= 480,
+};
+
+#define	MINX	8
+
+extern	GSubfont	defont0;
+
+struct{
+	Point	pos;
+	int	bwid;
+}out;
+
+typedef struct Mode Mode;
+struct Mode {
+	int	x;
+	int	y;
+	int	d;
+	char*	aperture;
+	int	apsize;
+};
+
+GBitmap	gscreen;
+Point	gchar(GBitmap*, Point, GFont*, int, Fcode);
+int	setcolor(ulong, ulong, ulong, ulong);
+static	void	lcdinit(Mode*);
+
+void
+screeninit(void)
+{
+	Mode m;
+
+	m.x = Colmaxx;
+	m.y = Colmaxy;
+	m.d = Colldepth;
+	m.aperture = 0;
+	lcdinit(&m);
+	if(m.aperture == 0)
+		return;
+	gscreen.ldepth = 3;
+	gscreen.base = (ulong*)m.aperture;
+	gscreen.width = Colmaxx/BY2WD;
+	gscreen.r = Rect(0, 0, Colmaxxvis, Colmaxy);
+	gscreen.clipr = gscreen.r;
+	/*
+	 * For now, just use a fixed colormap:
+	 * 0 == white and 255 == black
+	 */
+	setcolor(0, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF);
+	setcolor(255, 0x00000000, 0x00000000, 0x00000000);
+
+	gbitblt(&gscreen, Pt(0, 0), &gscreen, gscreen.r, Zero);
+	out.pos.x = MINX;
+	out.pos.y = 0;
+	out.bwid = defont0.info[' '].width;
+}
+
+void
+screenputc(int c)
+{
+	Fontchar *i;
+	Point p;
+
+	if(gscreen.base == nil)
+		return;
+	switch(c){
+	case '\n':
+		out.pos.x = MINX;
+		out.pos.y += defont0.height;
+		if(out.pos.y > gscreen.r.max.y-defont0.height)
+			out.pos.y = gscreen.r.min.y;
+		gbitblt(&gscreen, Pt(0, out.pos.y), &gscreen,
+		  Rect(0, out.pos.y, gscreen.r.max.x, out.pos.y+2*defont0.height),
+		  Zero);
+		break;
+	case '\t':
+		out.pos.x += (8-((out.pos.x-MINX)/out.bwid&7))*out.bwid;
+		if(out.pos.x >= gscreen.r.max.x)
+			screenputc('\n');
+		break;
+	case '\b':
+		if(out.pos.x >= out.bwid+MINX){
+			out.pos.x -= out.bwid;
+			screenputc(' ');
+			out.pos.x -= out.bwid;
+		}
+		break;
+	default:
+		if(out.pos.x >= gscreen.r.max.x-out.bwid)
+			screenputc('\n');
+		c &= 0x7f;
+		if(c <= 0 || c >= defont0.n)
+			break;
+		i = defont0.info + c;
+		p = out.pos;
+		gbitblt(&gscreen, Pt(p.x+i->left, p.y), defont0.bits,
+			Rect(i[0].x, 0, i[1].x, defont0.height),
+			S);
+		out.pos.x = p.x + i->width;
+		break;
+	}
+}
+
+void
+screenputs(char *s, int n)
+{
+	while(n-- > 0)
+		screenputc(*s++);
+}
+
+/*
+ * See section 5.2.1 (page 5-6) of the MPC823 manual
+ */
+static uchar lcdclock[17] = {	/* (a<<2)|b => divisor of (1<<a)*((b<<1)+1) */
+	0, 0, (1<<2), 1,
+	(2<<2), 2, (1<<2)|1, 3,
+	(3<<2), (1<<2)|2, (1<<2)|2, (2<<2)|1,
+	(2<<2)|1, (1<<2)|3, (1<<2)|3, (4<<2),
+	(4<<2)
+};
+	
+/*
+ * support for the Sharp LQ64D341 TFT colour display
+ */
+
+enum {
+	COLS = 640,
+	ROWS = 480,
+	LDEPTH = 3,	/* screen depth */
+	LCDFREQ = 25000000,
+
+	/* lccr */
+	ClockLow = 1<<11,
+	OELow = 1<<10,
+	HsyncLow = 1<<9,
+	VsyncLow = 1<<8,
+	DataLow = 1<<7,
+	Passive8 = 1<<4,
+	DualScan = 1<<3,
+	IsColour = 1<<2,
+	IsTFT = 1<<1,
+	Enable = 1<<0,
+
+	/* lchcr */
+	BigEndian = 1<<24,
+	AT7 = 7<<21,	/* access type */
+
+	/* sdcr */
+	LAM = 1<<6,	/* ``LCD aggressive mode'' */
+};
+
+/*
+ * TO DO: most of the data could come from a table
+ */
+static void
+lcdinit(Mode *mode)
+{
+	IMM *io;
+	int i, d;
+	long hz;
+
+	io = m->iomem;
+	mode->y = ROWS;
+	mode->x = COLS;
+	mode->d = LDEPTH;
+	mode->aperture = ialloc(mode->x*mode->y, 16);
+	mode->apsize = mode->x*mode->y;
+
+	io->sdcr &= ~LAM;	/* MPC823 errata: turn off LAM before disabling controller */
+	io->lcfaa = PADDR(mode->aperture);
+	io->lccr = (((mode->x*mode->y*(1<<LDEPTH)+127)/128) << 17) | (LDEPTH << 5) | IsColour | IsTFT | OELow | VsyncLow | ClockLow;
+
+	switch(LDEPTH){
+	default:
+	case 0:
+		/* monochrome/greyscale identity map */
+		for(i=0; i<16; i++)
+			io->lcdmap[i] = i;
+		break;
+	case 2:
+		/* 4-bit grey scale map */
+		for(i=0; i<16; i++)
+			io->lcdmap[0] = (i<<8)|(i<<4)|i;
+		break;
+	case 3:
+		/* 8-bit linear map */
+		for(i=0; i<256; i++)
+			io->lcdmap[i] = (i<<8)|(i<<4)|i;
+		break;
+	}
+
+	io->lcvcr = (mode->y << 11) | (1<<28) | 33;	/* 2 line vsync pulse, 34 line wait between frames */
+	io->lchcr = (mode->x<<10) | BigEndian | 228;	/* clock cycles between lines */
+
+	hz = m->cpuhz;
+	d = hz/LCDFREQ;
+	if(hz/d > LCDFREQ)
+		d++;
+	if(d >= 16)
+		d = 16;
+
+	/*
+	 * enable LCD outputs
+	 */
+	io->pddat = 0;
+	io->pdpar = 0x1fff;
+io->pdpar &= ~SIBIT(6);	/* 823 bug fix? */
+	io->pddir = 0x1fff;
+	io->pbpar |= IBIT(31) | IBIT(19) | IBIT(17);
+	io->pbdir |= IBIT(31) | IBIT(19) | IBIT(17);
+	io->pbodr &= ~(IBIT(31) | IBIT(19) | IBIT(17));
+
+	eieio();
+	io->sccrk = KEEP_ALIVE_KEY;
+	eieio();
+	io->sccr  = (io->sccr & ~0x1F) | lcdclock[d];
+	eieio();
+	io->sccrk = ~KEEP_ALIVE_KEY;
+	eieio();
+	gscreen.width = gscreen.width;	/* access external memory before enabling (mpc823 errata) */
+	io->lcsr = 7;	/* clear status */
+	eieio();
+	io->lccr |= Enable;
+	archbacklight(1);
+}
+
+int
+setcolor(ulong p, ulong r, ulong g, ulong b)
+{
+	r >>= 28;
+	g >>= 28;
+	b >>= 28;
+	m->iomem->lcdmap[~p&0xFF] = (r<<8) | (g<<4) | b;	/* TO DO: it's a function of the ldepth */
+	return 1;
+}
binary files /dev/null b/os/boot.original/rpcg/sload differ
--- /dev/null
+++ b/os/boot.original/rpcg/sload.c
@@ -1,0 +1,71 @@
+/*
+ * send S records to rpcg
+ */
+
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+
+static	int	dbg;
+static	char	buf[2048];
+static	int	run=1;
+static	void	stuffbym(char*, int, int);
+static	void	getdot(void);
+
+void
+main(int argc, char **argv)
+{
+	int n;
+	char *l;
+	Biobuf *f;
+	static int p;
+
+	ARGBEGIN{
+	case 'd': dbg++; break;
+	case 'n': run=0; break;
+	}ARGEND
+
+	f = Bopen(*argv? *argv: "k.mx", OREAD);
+	if(f == 0) {
+		fprint(2, "sload: cannot open k.mx: %r\n");
+		exits("sload");
+	}
+	getdot();
+	while((l = Brdline(f, '\n')) != 0) {
+		l[Blinelen(f)-1] = '\r';
+		stuffbym(l, Blinelen(f), 16);
+		getdot();
+		if(++p % 25 == 0)
+			write(2, ".", 1);
+	}
+	exits(0);
+}
+
+static void
+stuffbym(char *l, int n, int m)
+{
+	int nr, ns;
+
+	while(n > 0) {
+		ns = n;
+		if(ns > m)
+			ns = m;
+		write(1, l, ns);
+		l += ns;
+		n -= ns;
+	}
+}
+
+static void
+getdot(void)
+{
+	char c;
+
+	for(;;){
+		if(read(0, &c, 1) != 1)
+			exits("bang");
+		write(2, &c, 1);
+		if(c == '.')
+			break;
+	}
+}
--- /dev/null
+++ b/os/boot.original/rpcg/squeeze.h
@@ -1,0 +1,34 @@
+
+/*
+ * squeezed file format:
+ *	Sqhdr
+ *	original Exec header
+ *	two Squeeze tables
+ *	squeezed segment
+ *	unsqueezed segment, if any
+ */
+#define	SQMAGIC	(ulong)0xFEEF0F1E
+
+typedef struct Sqhdr Sqhdr;
+struct Sqhdr {
+	uchar	magic[4];	/* SQMAGIC */
+	uchar	text[4];	/* squeezed length of text (excluding tables) */
+	uchar	data[4];	/* squeezed length of data (excluding tables) */
+	uchar	asis[4];	/* length of unsqueezed segment */
+	uchar	toptxt[4];	/* value for 0 encoding in text */
+	uchar	topdat[4];	/* value for 0 encoding in data */
+	uchar	sum[4];	/* simple checksum of unsqueezed data */
+	uchar	flags[4];
+};
+#define	SQHDRLEN	(8*4)
+
+/*
+ * certain power instruction types are rearranged by sqz
+ * so as to move the variable part of the instruction word to the
+ * low order bits.  note that the mapping is its own inverse.
+ */
+#define	QREMAP(X)\
+	switch((X)>>26){\
+	case 19: case 31: case 59: case 63:\
+		(X) = (((X) & 0xFC00F801) | (((X)>>15)&0x7FE) | (((X)&0x7FE)<<15));\
+	}
--- /dev/null
+++ b/os/boot.original/rpcg/trap.c
@@ -1,0 +1,233 @@
+#include "boot.h"
+
+enum 
+{
+	Maxhandler=	32+16,		/* max number of interrupt handlers */
+};
+
+typedef struct Handler	Handler;
+struct Handler
+{
+	void	(*r)(Ureg*, void*);
+	void	*arg;
+	Handler	*next;
+	int	edge;
+};
+
+struct
+{
+	Handler	*ivec[128];
+	Handler	h[Maxhandler];
+	int	free;
+} halloc;
+
+char	*excname[] = {
+	"reserved 0",
+	"system reset",
+	"machine check",
+	"data access",
+	"instruction access",
+	"external interrupt",
+	"alignment",
+	"program exception",
+	"floating-point unavailable",
+	"decrementer",
+	"reserved A",
+	"reserved B",
+	"system call",
+	"trace trap",
+	"floating point assist",
+	"reserved F",
+	"software emulation",
+	"ITLB miss",
+	"DTLB miss",
+	"ITLB error",
+	"DTLB error",
+};
+
+char *regname[]={
+	"CAUSE",	"SRR1",
+	"PC",		"GOK",
+	"LR",		"CR",
+	"XER",	"CTR",
+	"R0",		"R1",
+	"R2",		"R3",
+	"R4",		"R5",
+	"R6",		"R7",
+	"R8",		"R9",
+	"R10",	"R11",
+	"R12",	"R13",
+	"R14",	"R15",
+	"R16",	"R17",
+	"R18",	"R19",
+	"R20",	"R21",
+	"R22",	"R23",
+	"R24",	"R25",
+	"R26",	"R27",
+	"R28",	"R29",
+	"R30",	"R31",
+};
+
+static	void	intr(Ureg*);
+
+void
+sethvec(int v, void (*r)(void))
+{
+	ulong *vp, pa, o;
+
+	if((ulong)r & 3)
+		panic("sethvec");
+	vp = (ulong*)KADDR(v);
+	vp[0] = 0x7c1043a6;	/* MOVW R0, SPR(SPRG0) */
+	vp[1] = 0x7c0802a6;	/* MOVW LR, R0 */
+	vp[2] = 0x7c1243a6;	/* MOVW R0, SPR(SPRG2) */
+	pa = PADDR(r);
+	o = pa >> 25;
+	if(o != 0 && o != 0x7F){
+		/* a branch too far: running from ROM */
+		vp[3] = (15<<26)|(pa>>16);	/* MOVW $r&~0xFFFF, R0 */
+		vp[4] = (24<<26)|(pa&0xFFFF);	/* OR $r&0xFFFF, R0 */
+		vp[5] = 0x7c0803a6;	/* MOVW	R0, LR */
+		vp[6] = 0x4e800021;	/* BL (LR) */
+	}else
+		vp[3] = (18<<26)|(pa&0x3FFFFFC)|3;	/* bla */
+}
+
+#define	LEV(n)	(((n)<<1)|1)
+#define	IRQ(n)	(((n)<<1)|0)
+
+void
+setvec(int v, void (*r)(Ureg*, void*), void *arg)
+{
+	Handler *h;
+	IMM *io;
+
+	if(halloc.free >= Maxhandler)
+		panic("out of interrupt handlers");
+	v -= VectorPIC;
+	h = &halloc.h[halloc.free++];
+	h->next = halloc.ivec[v];
+	h->r = r;
+	h->arg = arg;
+	halloc.ivec[v] = h;
+
+	/*
+	 * enable corresponding interrupt in SIU/CPM
+	 */
+
+	io = m->iomem;
+	if(v >= VectorCPIC){
+		v -= VectorCPIC;
+		io->cimr |= 1<<(v&0x1F);
+	}
+	else if(v >= VectorIRQ)
+		io->simask |= 1<<(31-IRQ(v&7));
+	else
+		io->simask |= 1<<(31-LEV(v));
+}
+
+void
+trapinit(void)
+{
+	int i;
+	IMM *io;
+
+	io = m->iomem;
+	io->sypcr &= ~(3<<2);	/* disable watchdog (821/823) */
+	io->simask = 0;	/* mask all */
+	io->siel = ~0;	/* edge sensitive, wake on all */
+	io->cicr = 0;	/* disable CPM interrupts */
+	io->cipr = ~0;	/* clear all interrupts */
+	io->cimr = 0;	/* mask all events */
+	io->cicr = (0xE1<<16)|(CPIClevel<<13)|(0x1F<<8);
+	io->cicr |= 1 << 7;	/* enable */
+	io->tbscrk = KEEP_ALIVE_KEY;
+	io->tbscr = 1;	/* TBE */
+	io->simask |= 1<<(31-LEV(CPIClevel));	/* CPM's level */
+	io->tbk = KEEP_ALIVE_KEY;
+	eieio();
+	putdec(~0);
+
+	/*
+	 * set all exceptions to trap
+	 */
+	for(i = 0x0; i < 0x3000; i += 0x100)
+		sethvec(i, exception);
+}
+
+void
+dumpregs(Ureg *ur)
+{
+	int i;
+	ulong *l;
+	l = &ur->cause;
+	for(i=0; i<sizeof regname/sizeof(char*); i+=2, l+=2)
+		print("%s\t%.8lux\t%s\t%.8lux\n", regname[i], l[0], regname[i+1], l[1]);
+}
+
+void
+trap(Ureg *ur)
+{
+	int c;
+
+	c = ur->cause >> 8;
+	switch(c){
+	default:
+		{extern int predawn; predawn = 1;}
+		if(c < 0 || c >= nelem(excname))
+			print("exception/interrupt #%x\n", c);
+		else
+			print("exception %s\n", excname[c]);
+		dumpregs(ur);
+		/* spllo(); */
+		print("^P to reset\n");
+		for(;;)
+			;
+
+	case 0x09:	/* decrementer */
+		clockintr(ur, 0);
+		return;
+
+	case 0x05:	/* external interrupt */
+		intr(ur);
+		break;
+	}
+}
+
+static void
+intr(Ureg *ur)
+{
+	int b, v;
+	Handler *h;
+	IMM *io;
+
+	io = m->iomem;
+	b = io->sivec>>2;
+	v = b>>1;
+	if(b & 1) {
+		if(v == CPIClevel){
+			io->civr = 1;
+			eieio();
+			v = VectorCPIC+(io->civr>>11);
+		}
+	}else
+		v += VectorIRQ;
+	h = halloc.ivec[v];
+	if(h == nil){
+		for(;;)
+			;
+		//print("unknown interrupt %d pc=0x%lux\n", v, ur->pc);
+		return;
+	}
+	if(h->edge)
+		io->sipend |= 1<<(31-b);
+	/*
+	 *  call the interrupt handlers
+	 */
+	do {
+		(*h->r)(ur, h->arg);
+		h = h->next;
+	} while(h != nil);
+	if(v >= VectorCPIC)
+		io->cisr |= 1<<(v-VectorCPIC);
+}
--- /dev/null
+++ b/os/boot.original/rpcg/uartboot.c
@@ -1,0 +1,189 @@
+#include "boot.h"
+
+/*
+ * this doesn't yet use the crc
+ */
+
+typedef struct Uboot Uboot;
+struct Uboot {
+	Queue*	iq;
+	Block*	partial;
+	ulong	csum;
+	long	bno;
+	uchar	buf[64];
+	int	nleft;
+	int	ntimeout;
+};
+
+static	Uboot	uboot;
+ulong	crc32(void *buf, int n, ulong crc);
+
+static void
+uartbrecv(uchar *p, int n)
+{
+	Uboot *ub;
+	Block *b;
+
+	ub = &uboot;
+	if(n > 0 && ub->iq != nil){
+		b = iallocb(n);
+		memmove(b->wp, p, n);
+		b->wp += n;
+		qbwrite(ub->iq, b);
+	}
+}
+
+int
+uartinit(void)
+{
+	return 1<<0;
+}
+
+Partition*
+setuartpart(int, char *s)
+{
+	static Partition pp[1];
+
+	if(strcmp(s, "boot") != 0 && strcmp(s, "disk") != 0)
+		return 0;
+	pp[0].start = 0;
+	pp[0].end = 2*1024*1024;
+	strcpy(pp[0].name, "boot");
+	return pp;
+}
+
+long
+uartseek(int, long)
+{
+	/* start the boot */
+	if(uboot.iq == nil)
+		uboot.iq = qopen(64*1024, 0, 0, 0);
+	if(uboot.partial){
+		freeb(uboot.partial);
+		uboot.partial = 0;
+	}
+	print("uart: start transmission\n");
+	uartsetboot(uartbrecv);
+	uboot.csum = ~0;
+	uboot.bno = 0;
+	uboot.nleft = 0;
+	uboot.ntimeout = 0;
+	return 0;
+}
+
+static long
+uartreadn(void *buf, int nb)
+{
+	ulong start;
+	Uboot *ub;
+	int l;
+	Block *b;
+	uchar *p;
+
+	p = buf;
+	ub = &uboot;
+	start = m->ticks;
+	while(nb > 0){
+		b = ub->partial;
+		ub->partial = nil;
+		if(b == nil){
+			ub->ntimeout = 0;
+			while((b = qget(ub->iq)) == 0){
+				if(TK2MS(m->ticks - start) >= 15*1000){
+					if(++ub->ntimeout >= 3){
+						print("uart: timeout\n");
+						return 0;
+					}
+					uartputs("n", 1);
+				}
+			}
+		}
+		l = BLEN(b);
+		if(l > nb)
+			l = nb;
+		memmove(p, b->rp, l);
+		b->rp += l;
+		if(b->rp >= b->wp)
+			freeb(b);
+		else
+			ub->partial = b;
+		nb -= l;
+		p += l;
+	}
+	return p-(uchar*)buf;
+}
+
+long
+uartread(int, void *buf, long n)
+{
+	uchar *p;
+	int l;
+	static uchar lbuf[64];
+
+	p = buf;
+	if((l = uboot.nleft) > 0){
+		if(l > n)
+			l = n;
+		uboot.nleft -= l;
+		memmove(p, uboot.buf, l);
+		p += l;
+		n -= l;
+	}
+	while(n > 0){
+		l = uartreadn(lbuf, sizeof(lbuf));
+		if(l < sizeof(lbuf))
+			return 0;
+		if(l > n){
+			uboot.nleft = l-n;
+			memmove(uboot.buf, lbuf+n, uboot.nleft);
+			l = n;
+		}
+		memmove(p, lbuf, l);
+		n -= l;
+		p += l;
+		uboot.bno++;
+		uartputs("y", 1);
+	}
+	return p-(uchar*)buf;
+}
+
+/*
+ * from Rob Warnock
+ */
+static	ulong	crc32tab[256];	/* initialised on first call to crc32 */
+
+enum {
+	CRC32POLY = 0x04c11db7     /* AUTODIN II, Ethernet, & FDDI */
+};
+
+/*
+ * Build auxiliary table for parallel byte-at-a-time CRC-32.
+ */
+static void
+initcrc32(void)
+{
+	int i, j;
+	ulong c;
+
+	for(i = 0; i < 256; i++) {
+		for(c = i << 24, j = 8; j > 0; j--)
+			if(c & (1<<31))
+				c = (c<<1) ^ CRC32POLY;
+			else
+				c <<= 1;
+		crc32tab[i] = c;
+	}
+}
+
+ulong
+crc32(void *buf, int n, ulong crc)
+{
+	uchar *p;
+
+	if(crc32tab[1] == 0)
+		initcrc32();
+	crc = ~crc;
+	for(p = buf; --n >= 0;)
+		crc = (crc << 8) ^ crc32tab[(crc >> 24) ^ *p++];
+	return ~crc;
+}
--- /dev/null
+++ b/os/boot.original/rpcg/ureg.h
@@ -1,0 +1,43 @@
+struct Ureg
+{
+	ulong	cause;
+	union { ulong	srr1; ulong status;};
+	ulong	pc;	/* SRR0 */
+	ulong	pad;
+	ulong	lr;
+	ulong	cr;
+	ulong	xer;
+	ulong	ctr;
+	ulong	r0;
+	union{ ulong r1;	ulong	sp;	ulong	usp; };
+	ulong	r2;
+	ulong	r3;
+	ulong	r4;
+	ulong	r5;
+	ulong	r6;
+	ulong	r7;
+	ulong	r8;
+	ulong	r9;
+	ulong	r10;
+	ulong	r11;
+	ulong	r12;
+	ulong	r13;
+	ulong	r14;
+	ulong	r15;
+	ulong	r16;
+	ulong	r17;
+	ulong	r18;
+	ulong	r19;
+	ulong	r20;
+	ulong	r21;
+	ulong	r22;
+	ulong	r23;
+	ulong	r24;
+	ulong	r25;
+	ulong	r26;
+	ulong	r27;
+	ulong	r28;
+	ulong	r29;
+	ulong	r30;
+	ulong	r31;
+};
--- /dev/null
+++ b/os/boot.original/rpcg/zqs.c
@@ -1,0 +1,234 @@
+#include "boot.h"
+#include "squeeze.h"
+
+/*
+ * for details of `unsqueeze' see:
+ *
+ * %A Mark Taunton
+ * %T Compressed Executables: An Exercise in Thinking Small
+ * %P 385-404
+ * %I USENIX
+ * %B USENIX Conference Proceedings
+ * %D Summer 1991
+ * %C Nashville, TN
+ *
+ * several of the unimplemented improvements described in the paper
+ * have been implemented here
+ *
+ * there is a further transformation on the powerpc (QFLAG!=0) to shuffle bits
+ * in certain instructions so as to push the fixed bits to the top of the word.
+ */
+
+#define	EXECHDRLEN	(8*4)
+
+typedef struct Squeeze Squeeze;
+struct Squeeze {
+	int	n;
+	ulong	tab[7*256];
+};
+
+#define	GET4(p)	(((((((p)[0]<<8)|(p)[1])<<8)|(p)[2])<<8)|(p)[3])
+
+/*
+ * for speed of unsqueezing from Flash, certain checks are
+ * not done inside the loop (as they would be in the unsqueeze program zqs),
+ * but instead the checksum is expected to catch corrupted files.
+ * in fact the Squeeze array bounds can't be exceeded in practice
+ * because the tables are always full for a squeezed kernel.
+ */
+enum {
+	QFLAG = 1,	/* invert powerpc-specific code transformation */
+	CHECK = 0,	/* check precise bounds in Squeeze array (otherwise checksum detects error) */
+};
+
+static	ulong	chksum;
+static	int	rdtab(Block*, Squeeze*, int);
+static	ulong*	unsqueeze(ulong*, uchar*, uchar*, Squeeze*, Squeeze*, ulong);
+static	uchar*	unsqzseg(uchar*, Block*, long, long, char*);
+static	Alarm*	unsqzal;
+
+int
+issqueezed(uchar *b)
+{
+	return GET4(b) == SQMAGIC? GET4(b+SQHDRLEN): 0;
+}
+
+static void
+unsqzdot(Alarm*)
+{
+	unsqzal = alarm(500, unsqzdot, nil);
+	print(".");
+}
+
+long
+unsqueezef(Block *b, ulong *entryp)
+{
+	uchar *loada, *wp;
+	ulong toptxt, topdat, oldsum;
+	long asis, nst, nsd;
+	Sqhdr *sqh;
+	Exec *ex;
+
+	if(BLEN(b) < SQHDRLEN+EXECHDRLEN)
+		return -1;
+	sqh = (Sqhdr*)b->rp;
+	if(GET4(sqh->magic) != SQMAGIC)
+		return -1;
+	chksum = 0;
+	toptxt = GET4(sqh->toptxt);
+	topdat = GET4(sqh->topdat);
+	oldsum = GET4(sqh->sum);
+	asis = GET4(sqh->asis);
+	nst = GET4(sqh->text);
+	nsd = GET4(sqh->data);
+	b->rp += SQHDRLEN;
+	ex = (Exec*)b->rp;
+	if(GET4(ex->magic) != Q_MAGIC){
+		print("zqs: not powerPC executable\n");
+		return -1;
+	}
+	*entryp = GET4(ex->entry);
+	b->rp += EXECHDRLEN;
+	loada = KADDR(PADDR(*entryp));
+	wp = unsqzseg(loada, b, nst, toptxt, "text");
+	if(wp == nil){
+		print("zqs: format error\n");
+		return -1;
+	}
+	if(nsd){
+		wp = (uchar*)PGROUND((ulong)wp);
+		wp = unsqzseg(wp, b, nsd, topdat, "data");
+		if(wp == nil){
+			print("zqs: format error\n");
+			return -1;
+		}
+	}
+	if(asis){
+		memmove(wp, b->rp, asis);
+		wp += asis;
+		b->rp += asis;
+	}
+	if(chksum != oldsum){
+		print("\nsqueezed kernel: checksum error: %8.8lux need %8.8lux\n", chksum, oldsum);
+		return -1;
+	}
+	return wp-loada;
+}
+
+static uchar *
+unsqzseg(uchar *wp, Block *b, long ns, long top, char *what)
+{
+	static Squeeze sq3, sq4;
+
+	print("unpack %s %8.8lux %lud:", what, wp, ns);
+	if(ns == 0)
+		return wp;
+	if(rdtab(b, &sq3, 0) < 0)
+		return nil;
+	if(rdtab(b, &sq4, 8) < 0)
+		return nil;
+	if(BLEN(b) < ns){
+		print(" **size error\n");
+		return nil;
+	}
+	unsqzal = alarm(500, unsqzdot, nil);
+	wp = (uchar*)unsqueeze((ulong*)wp, b->rp, b->rp+ns, &sq3, &sq4, top);
+	cancel(unsqzal);
+	unsqzal = nil;
+	print("\n");
+	if(wp == nil){
+		print("zqs: corrupt squeezed data stream\n");
+		return nil;
+	}
+	b->rp += ns;
+	return wp;
+}
+
+static ulong*
+unsqueeze(ulong *wp, uchar *rp, uchar *ep, Squeeze *sq3, Squeeze *sq4, ulong top)
+{
+	ulong nx, csum;
+	int code, n;
+
+	if(QFLAG){
+		QREMAP(top);	/* adjust top just once, outside the loop */
+	}
+	csum = chksum;
+	while(rp < ep){
+		/* no function calls within this loop for speed */
+		code = *rp;
+		rp++;
+		n = 0;
+		nx = code>>4;
+		do{
+			if(nx == 0){
+				nx = top;
+			}else{
+				if(nx==1){
+					nx = (((((rp[3]<<8)|rp[2])<<8)|rp[1])<<8)|rp[0];
+					rp += 4;
+				}else if(nx <= 8){	/* 2 to 8 */
+					nx = ((nx-2)<<8) | rp[0];
+					if(CHECK && nx >= sq4->n)
+						return nil;	/* corrupted file */
+					nx = sq4->tab[nx] | rp[1];
+					rp += 2;
+				}else{	/* 9 to 15 */
+					nx = ((nx-9)<<8) | rp[0];
+					if(CHECK && nx >= sq3->n)
+						return nil;	/* corrupted file */
+					nx = sq3->tab[nx];
+					rp++;
+				}
+				if(rp > ep)
+					return nil;	/* corrupted file */
+				if(QFLAG){
+					QREMAP(nx);
+				}
+			}
+			*wp = nx;
+			wp++;
+			csum += nx;
+			nx = code & 0xF;
+		}while(++n == 1);
+	}
+	chksum = csum;
+	return wp;
+}
+
+static int
+rdtab(Block *b, Squeeze *sq, int shift)
+{
+	uchar *p, *ep;
+	ulong v, w;
+	int i;
+
+	if(BLEN(b) < 2)
+		return -1;
+	i = (b->rp[0]<<8) | b->rp[1];
+	if(1)
+		print(" T%d", i);
+	b->rp += 2;
+	if((i -= 2) > 0){
+		if(BLEN(b) < i)
+			return -1;
+	}
+	sq->n = 0;
+	p = b->rp;
+	ep = b->rp+i;
+	b->rp += i;
+	v = 0;
+	while(p < ep){
+		w = 0;
+		do{
+			if(p >= ep)
+				return -1;
+			w = (w<<7) | (*p & 0x7F);
+		}while(*p++ & 0x80);
+		v += w;
+		if(0)
+			print("%d %8.8lux %8.8lux\n", sq->n, v, w);
+		sq->tab[sq->n++] = v<<shift;
+	}
+	return 0;
+}