~kris/9p

9hist

762e05f5f297c3c149b665464826d9647df31652 — David du Colombier 35 years ago d723d10
Plan 9 from Bell Labs 1991-09-24
4 files changed, 1366 insertions(+), 1138 deletions(-)

M pc/devfloppy.c
M port/devmnt.c
M power/boot.h
M power/devrtc.c
M pc/devfloppy.c => pc/devfloppy.c +350 -325
@@ 6,35 6,41 @@
#include	"io.h"
#include	"errno.h"

/* NEC PD765A (8272A compatible) floppy controller */
/* Intel 82077A (8272A compatible) floppy controller */

typedef	struct Drive		Drive;
typedef	struct Controller	Controller;
typedef struct Type		Type;

/* bits in the registers */
enum
{
	Fmotor=		0x3f2,	/* motor port */
	 Fintena=	 0x4,	/* enable floppy interrupt */
	 Fena=		 0x8,	/* 0 == reset controller */

	Fstatus=	0x3f4,	/* controller main status port */
	 Fready=	 0x80,	/* ready to be touched */
	 Ffrom=		 0x40,	/* data from controller */
	 Fbusy=		 0x10,	/* operation not over */

	Fdata=		0x3f5,	/* controller data port */
	 Frecal=	 0x7,	/* recalibrate cmd */
	 Fseek=		 0xf,	/* seek cmd */
	 Fsense=	 0x8,	/* sense cmd */
	 Fread=		 0x66,	/* read cmd */
	 Fwrite=	 0x45,	/* write cmd */
	 Fmulti=	 0x80,	/* or'd with Fread or Fwrite for multi-head */

	Fchanged=	0x3F7,	/* disk changed register */
	 Fchange=	 0x80,	/* disk has changed */

	DMAchan=	2,	/* floppy dma channel */
	/* 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 */
	Fbusy=		0x10,	/* operation not over */

	/* data register */
	Pdata=		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 */
	Fmulti=		0x80,	/* or'd with Fread or Fwrite for multi-head */
	Fdumpreg=	0x0e,	/* dump internal registers */

	/* digital input register */
	Pdir=		0x3F7,	/* disk changed port */
	Fchange=	0x80,	/* disk has changed */

	/* status 0 byte */
	Drivemask=	3<<0,


@@ 46,6 52,8 @@ enum
	Qdata=		(1<<2),
	Qctl=		(2<<2),
	Qmask=		(3<<2),

	DMAchan=	2,	/* floppy dma channel */
};

/*


@@ 68,11 76,13 @@ struct Type
	 */
	int	bcode;		/* coded version of bytes for the controller */
	long	cap;		/* drive capacity in bytes */
	long	tsize;		/* track size in bytes */
};
Type floppytype[] =
{
	{ "MF2HD",	512,	18,	2,	1,	80,	0x1B,	0x54, },
	{ "MF2DD",	512,	9,	2,	1,	80,	0x1B,	0x54, },
	{ "MF1DD",	512,	9,	2,	1,	80,	0x1B,	0x54, },
	{ "MF4HD",	1024,	18,	2,	1,	80,	0x1B,	0x54, },
	{ "F2HD",	512,	15,	2,	1,	80,	0x2A,	0x50, },
	{ "F2DD",	512,	8,	2,	2,	40,	0x2A,	0x50, },
	{ "F1DD",	512,	8,	1,	2,	40,	0x2A,	0x50, },


@@ 111,57 121,60 @@ struct Drive

	ulong	lasttouched;	/* time last touched */
	int	cyl;		/* current cylinder */
	int	confused;	/* needs to be recalibrated (or worse) */
	int	confused;	/* needs to be recalibrated */

	int	tcyl;		/* target cylinder */
	int	thead;		/* target head */
	int	tsec;		/* target sector */
	long	len;		/* size of xfer */

	Rendez	r;		/* waiting here for motor to spin up */
	uchar	*cache;	/* track cache */
	int	ccyl;
	int	chead;

	uchar	*ccache;	/* cylinder cache (always read a whole cyl) */
	int	ccyl;		/* number of cached cylinder */
	Rendez	r;		/* waiting here for motor to spin up */
};

/*
 *  NEC PD765A controller for 4 floppys
 *  controller for 4 floppys
 */
struct Controller
{
	QLock;			/* exclusive access to the contoller */

	Drive	*d;		/* the floppy drives */
	uchar	stat[8];	/* status of an operation */
	int	confused;
	int	intr;		/* true if interrupt occured */
	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;

	int	motor;		/* bit mask of spinning disks */
	Rendez	kr;		/* for motor watcher */
};

Controller	floppy;
Controller	fl;

#define MOTORBIT(i)	(1<<((i)+4))

/*
 *  predeclared
 */
static void	motoron(Drive*);
static void	motoroff(Drive*);
static int	floppycmd(void);
static void	floppyeject(Drive*);
static void	floppykproc(void*);
static int	floppysend(int);
static int	floppyrcv(void);
static int	floppyresult(int);
static void	floppyon(Drive*);
static void	floppyoff(Drive*);
static void	floppypos(Drive*,long);
static int	floppysense(Drive*);
static int	interrupted(void*);
static int	floppyrecal(Drive*);
static int	floppyresult(void);
static void	floppyrevive(void);
static long	floppyseek(Drive*);
static long	floppyseek(Drive*, long);
static int	floppysense(void);
static void	floppywait(void);
static long	floppyxfer(Drive*, int, void*, long, long);
static void	floppyintr(Ureg*);
static int	cmddone(void*);
void Xdelay(int);

Dirtab floppydir[]={
	"fd0disk",		{Qdata + 0},	0,	0600,


@@ 175,13 188,14 @@ Dirtab floppydir[]={
};
#define NFDIR	2	/* directory entries/drive */

#define k64(x) (((ulong)(x))>>16)
void
floppyreset(void)
{
	Drive *dp;
	Type *t;
	int n;
	ulong p;
	long l;

	/*
	 *  init dependent parameters


@@ 189,36 203,38 @@ floppyreset(void)
	for(t = floppytype; t < &floppytype[NTYPES]; t++){
		t->cap = t->bytes * t->heads * t->sectors * t->tracks;
		t->bcode = b2c[t->bytes/128];
		t->tsize = t->bytes * t->sectors;
	}

	/*
	 *  allocate the drive storage
	 */
	floppy.d = ialloc(conf.nfloppy*sizeof(Drive), 0);
	fl.d = ialloc(conf.nfloppy*sizeof(Drive), 0);

	/*
	 *  stop the motors
	 */
	for(dp = floppy.d; dp < &floppy.d[conf.nfloppy]; dp++){
		dp->dev = dp - floppy.d;
	fl.motor = 0;
	delay(10);
	outb(Pdor, fl.motor | Fintena | Fena);
	delay(10);

	/*
	 *  init drives
	 */
	for(dp = fl.d; dp < &fl.d[conf.nfloppy]; dp++){
		dp->dev = dp - fl.d;
		dp->t = &floppytype[0];		/* default type */
		floppydir[NFDIR*dp->dev].length = dp->t->cap;
		floppy.motor |= MOTORBIT(dp->dev);
		dp->cyl = -1;		/* because we don't know */
		motoroff(dp);
		dp->cache = (uchar*)ialloc(dp->t->tsize, 1);
		dp->ccyl = -1;
	}

	/*
	 *  allocate cylinder caches that don't cross 64k boundaries
	 *  first operation will recalibrate
	 */
	for(dp = floppy.d; dp < &floppy.d[conf.nfloppy]; dp++){
		do {
			n = 512 * 18 * 2;	/* MF2HD cylinder size */
			dp->ccache = ialloc(n, 1);
		} while(k64(dp->ccache) != k64(dp->ccache+n));
		dp->ccyl = -1;
	}
	setvec(Floppyvec, floppyintr);
	fl.confused = 1;
}

void


@@ 288,93 304,116 @@ floppywstat(Chan *c, char *dp)
	error(Eperm);
}

/*
 *  look for a floppy change
 */
void
floppychanged(Drive *dp)
{
	if((inb(Fchanged) & Fchange) == 0)
		return;

	print("floppy has changed\n");
}

/*
 *  the floppy is so slow, we always read a cylinder
 *  at a time and cache the extra bytes.
 */
long
floppyread(Chan *c, void *a, long n)
{
	Drive *dp;
	long rv, nn, len, cyl;
	int sec;
	uchar *aa = a;
	long rv, i;
	int nn, sec, head, cyl;
	long len;
	long noff;
	uchar *aa;

	if(c->qid.path == CHDIR)
		return devdirread(c, a, n, floppydir, conf.nfloppy*NFDIR, devgen);

	rv = 0;
	dp = &floppy.d[c->qid.path & ~Qmask];
	dp = &fl.d[c->qid.path & ~Qmask];

	switch ((int)(c->qid.path & Qmask)) {
	case Qdata:
		floppychanged(dp);
		if(c->offset % dp->t->bytes)
			errors("bad offset");
		if(n % dp->t->bytes)
			errors("bad len");
		nn = dp->t->bytes * dp->t->sectors * dp->t->heads;
		aa = a;
		nn = dp->t->tsize;
		for(rv = 0; rv < n; rv += len){
			/*
			 *  truncate xfer at cylinder boundary
			 *  truncate xfer at track boundary
			 */
			dp->len = n - rv;
			floppypos(dp, c->offset+rv);
			cyl = dp->tcyl;
			head = dp->thead;
			len = dp->len;
			sec = dp->tsec + dp->thead * dp->t->sectors;
			sec = dp->tsec;

			/*
			 *  read the cylinder
			 *  read the track
			 */
			if(dp->ccyl != cyl){
			if(dp->ccyl!=cyl || dp->chead!=head){
				dp->ccyl = -1;
				if(floppyxfer(dp, Fread, dp->ccache, cyl * nn, nn) != nn)
				i = floppyxfer(dp, Fread, dp->cache,
					(cyl*dp->t->heads+head)*nn, nn);
				if(i != nn){
					if(i == 0)
						break;
					errors("floppy read err");
				}
				dp->ccyl = cyl;
				dp->chead = head;
			}
			memmove(aa+rv, dp->ccache + (sec-1)*dp->t->bytes, len);
			memmove(aa+rv, dp->cache + (sec-1)*dp->t->bytes, len);
		}
		break;
	case Qctl:
		break;
	default:
		panic("floppyread: bad qid");
	}

	return rv;
}

#define SNCMP(a, b) strncmp(a, b, sizeof(b)-1)
long
floppywrite(Chan *c, void *a, long n)
{
	Drive *dp;
	long rv, i;
	uchar *aa = a;
	char *aa = a;
	int dev;

	rv = 0;
	dp = &floppy.d[c->qid.path & ~Qmask];
	dp = &fl.d[c->qid.path & ~Qmask];

	switch ((int)(c->qid.path & Qmask)) {
	case Qdata:
		floppychanged(dp);
		dp->ccyl = -1;
		if(c->offset % dp->t->bytes)
			errors("bad offset");
		if(n % dp->t->bytes)
			errors("bad len");
		for(rv = 0; rv < n; rv += i){
			i = floppyxfer(dp, Fwrite, aa+rv, c->offset+rv, n-rv);
			floppypos(dp, c->offset+rv);
			if(dp->tcyl == dp->ccyl)
				dp->ccyl = -1;
			i = floppyxfer(dp, Fwrite, aa+rv, c->offset+rv,
				n-rv);
			if(i <= 0)
				break;
		}
		break;
	case Qctl:
		if(SNCMP(aa, "eject") == 0){
			floppyeject(dp);
		} else if(SNCMP(aa, "seek") == 0){
			aa += 5;
			floppyseek(dp, strtoul(aa, 0, 0));
		} else if(SNCMP(aa, "den") == 0){
			aa += 4;
			i = strtoul(aa, 0, 0);
			USED(i);
/*			devp->dsr = i;
			devp->ccr = i;/**/
		} else if(SNCMP(aa, "reset") == 0){
			floppyon(dp);
		}
		break;
	default:
		panic("floppywrite: bad qid");
	}

	return rv;
}



@@ 382,53 421,53 @@ static void
floppykproc(void *a)
{
	Drive *dp;
	int disp = 0;
int i;
static int last;

	while(waserror())
		;
	for(;;){
		for(dp = floppy.d; dp < &floppy.d[conf.nfloppy]; dp++){
			if((floppy.motor&MOTORBIT(dp->dev))
i = inb(Pdir) & 0x80;
if(i != last)
	print("fromn %d to %d\n", last, i);
last = i;
		for(dp = fl.d; dp < &fl.d[conf.nfloppy]; dp++){
			if((fl.motor&MOTORBIT(dp->dev))
			&& TK2SEC(m->ticks - dp->lasttouched) > 5
			&& canqlock(dp)){
				if(TK2SEC(m->ticks - dp->lasttouched) > 5)
					motoroff(dp);
					floppyoff(dp);
				qunlock(dp);
			}
		}
		disp++;
		tsleep(&floppy.kr, return0, 0, 5*1000);
		
		tsleep(&fl.kr, return0, 0, 5*100);
	}
}

static void
driveselect(Drive *dp)
{
	int cmd;

	cmd = floppy.motor | Fintena | Fena | dp->dev;
	outb(Fmotor, cmd);
}

/*
 *  start a floppy drive's motor.  set an alarm for .75 second later to
 *  mark it as started (we get no interrupt to tell us).
 *
 *  assume the caller qlocked the drive.
 *
 *  this also selects the drive for subsequent operations
 *  start a floppy drive's motor.
 */
static void
motoron(Drive *dp)
floppyon(Drive *dp)
{
	int alreadyon;
	int tries;

	if(fl.confused)
		floppyrevive();

	alreadyon = floppy.motor & MOTORBIT(dp->dev);
	floppy.motor |= MOTORBIT(dp->dev);
	driveselect(dp);
	/* start motor and select drive */
	alreadyon = fl.motor & MOTORBIT(dp->dev);
	fl.motor |= MOTORBIT(dp->dev);
	outb(Pdor, fl.motor | Fintena | Fena | dp->dev);
	if(!alreadyon)
		tsleep(&dp->r, return0, 0, 750);

	/* get drive to a known cylinder */
	if(dp->confused)
		for(tries = 0; tries < 4; tries++)
			if(floppyrecal(dp) >= 0)
				break;
	dp->lasttouched = m->ticks;
}



@@ 436,149 475,139 @@ motoron(Drive *dp)
 *  stop the floppy if it hasn't been used in 5 seconds
 */
static void
motoroff(Drive *dp)
floppyoff(Drive *dp)
{
	floppy.motor &= ~MOTORBIT(dp->dev);
	driveselect(dp);
	fl.motor &= ~MOTORBIT(dp->dev);
	outb(Pdor, fl.motor | Fintena | Fena | dp->dev);
}

/*
 *  send a byte to the floppy
 *  eject disk ( unknown on safari )
 */
static int
floppysend(int data)
static void
floppyeject(Drive *dp)
{
	int tries;
	uchar c;

	for(tries = 0; tries < 100; tries++){
		/*
		 *  see if its ready for data
		 */
		c = inb(Fstatus);
		if((c&(Ffrom|Fready)) != Fready)
			continue;

		/*
		 *  send the data
		 */
		outb(Fdata, data);
		return 0;
	}
	return -1;
	floppyon(dp);
	floppyoff(dp);
}

/*
 *  get a byte from the floppy
 *  send a command to the floppy
 */
static int
floppyrcv(void)
floppycmd(void)
{
	int i;
	int tries;
	uchar c;

	for(tries = 0; tries < 100; tries++){
		/*
		 *  see if its ready for data
		 */
		c = inb(Fstatus);
		if((c&(Ffrom|Fready)) != (Ffrom|Fready))
			continue;

		/*
		 *  get data
		 */
		return inb(Fdata)&0xff;
	for(i = 0; i < fl.ncmd; i++){
		for(tries = 0; ; tries++){
			if(tries > 1000){
print("cmd %ux can't be sent (%d %ux)\n", fl.cmd[0], i, inb(Pmsr));
				fl.confused = 1;
				return -1;
			}
			if((inb(Pmsr)&(Ffrom|Fready)) == Fready)
				break;
		}
		outb(Pdata, fl.cmd[i]);
	}
	return -1;
	return 0;
}

/*
 *  read a command result message from the floppy
 *  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(int n)
floppyresult(void)
{
	int i;
	int c;
	int i, s;
	int tries;

	for(i = 0; i < n; i++){
		c = floppyrcv();
		if(c < 0)
			return -1;
		floppy.stat[i] = c;
	for(i = 0; i < sizeof(fl.stat); i++){
		for(tries = 0; ; tries++){
			if(tries > 1000){
				fl.confused = 1;
				return -1;
			}
			s = inb(Pmsr)&(Ffrom|Fready);
			if(s == Fready){
				fl.nstat = i;
				return i;
			}
			if(s == (Ffrom|Fready))
				break;
		}
		fl.stat[i] = inb(Pdata);
	}
	return 0;
	fl.nstat = i;
	return i;
}

/*
 *  calculate physical address of a logical byte offset into the disk
 *
 *  truncate dp->length if it crosses a cylinder boundary
 *  truncate dp->length if it crosses a track boundary
 */
static void
floppypos(Drive *dp, long off)
{
	int lsec;
	int ltrack;
	int end;
	int cyl;
	int track;

	lsec = off/dp->t->bytes;
	dp->tcyl = lsec/(dp->t->sectors*dp->t->heads);
	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 cylinder boundaries.
	 *  can't read across track boundaries.
	 *  if so, decrement the bytes to be read.
	 */
	lsec = (off+dp->len)/dp->t->bytes;
	cyl = lsec/(dp->t->sectors*dp->t->heads);
	if(cyl != dp->tcyl){
		dp->len -= (lsec % dp->t->sectors)*dp->t->bytes;
		dp->len -= ((lsec/dp->t->sectors) % dp->t->heads)*dp->t->bytes
				*dp->t->sectors;
	}
	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.  we need to do this
 *  after seeks and recalibrations since they don't return results.
 *  get the interrupt cause from the floppy.
 */
static int
floppysense(Drive *dp)
floppysense(void)
{
	/*
	 *  ask for floppy status
	 */
	if(floppysend(Fsense) < 0){
		floppy.confused = 1;
	fl.ncmd = 0;
	fl.cmd[fl.ncmd++] = Fsense;
	if(floppycmd() < 0)
		return -1;
	}
	if(floppyresult(2) < 0){
		floppy.confused = 1;
		dp->confused = 1;
		return -1;
	}

	/*
	 *  make sure it's the right drive
	 */
	if((floppy.stat[0] & Drivemask) != dp->dev){
		print("sense failed\n");
		dp->confused = 1;
	if(floppyresult() < 2){
print("can't read sense response\n");
		fl.confused = 1;
		return -1;
	}
	return 0;
}

static int
cmddone(void *a)
{
	return fl.ncmd == 0;
}

/*
 *  return true if interrupt occurred
 *  wait for a floppy interrupt
 */
static int
interrupted(void *a)
static void
floppywait(void)
{
	return floppy.intr;
	tsleep(&fl.r, cmddone, 0, 2000);
}

/*


@@ 587,35 616,26 @@ interrupted(void *a)
static int
floppyrecal(Drive *dp)
{
	floppy.intr = 0;
	if(floppysend(Frecal) < 0
	|| floppysend(dp - floppy.d) < 0){
		floppy.confused = 0;
		return -1;
	}
	sleep(&floppy.r, interrupted, 0);
	int type;

	/*
	 *  get return values
	 */
	if(floppysense(dp) < 0)
		return -1;
	dp->ccyl = -1;

	/*
	 *  see if it worked
	 */
	if((floppy.stat[0] & (Codemask|Seekend)) != Seekend){
		print("recalibrate failed\n");
	fl.ncmd = 0;
	fl.cmd[fl.ncmd++] = Frecal;
	fl.cmd[fl.ncmd++] = dp->dev;
	if(floppycmd() < 0)
		return -1;
	floppywait();
	if(fl.nstat < 2){
		fl.confused = 1;
		return -1;
	}
	if((fl.stat[0] & (Codemask|Seekend)) != Seekend){
		dp->confused = 1;
		return -1;
	}

	/*
	 *  see what cylinder we got to
	 */
	dp->tcyl = 0;
	dp->cyl = floppy.stat[1]/dp->t->steps;
	if(dp->cyl != dp->tcyl){
	dp->cyl = fl.stat[1]/dp->t->steps;
	if(dp->cyl != 0){
		print("recalibrate went to wrong cylinder %d\n", dp->cyl);
		dp->confused = 1;
		return -1;


@@ 635,80 655,60 @@ floppyrevive(void)
	Drive *dp;

	/*
	 *  reset the floppy if it's confused
	 *  reset the controller if it's confused
	 */
	if(floppy.confused){
	if(fl.confused){
		/* reset controller and turn all motors off */
		floppy.intr = 0;
		splhi();
		outb(Fmotor, 0);
		fl.cmd[0] = 0;
		outb(Pdor, 0);
		delay(1);
		outb(Fmotor, Fintena|Fena);
		outb(Pdor, Fintena|Fena);
		spllo();
		for(dp = floppy.d; dp < &floppy.d[conf.nfloppy]; dp++){
		for(dp = fl.d; dp < &fl.d[conf.nfloppy]; dp++)
			dp->confused = 1;
		}
		floppy.motor = 0;
		sleep(&floppy.r, interrupted, 0);
		floppy.confused = 0;
	}

	/*
	 *  recalibrate any confused drives
	 */
	for(dp = floppy.d; floppy.confused == 0 && dp < &floppy.d[conf.nfloppy]; dp++){
		if(dp->confused == 0)
			floppyrecal(dp);

		fl.motor = 0;
		floppywait();
		fl.confused = 0;
/*		devp->dsr = 0;
		devp->ccr = 0; /**/
	}

}

/*
 *  seek to the target cylinder
 *
 *	interrupt, no results
 */
static long
floppyseek(Drive *dp)
floppyseek(Drive *dp, long off)
{
	floppyon(dp);
	floppypos(dp, off);
	if(dp->cyl == dp->tcyl)
		return dp->cyl;

	/*
	 *  tell floppy to seek
	 */
	floppy.intr = 0;
	dp->cyl = -1;	/* once the seek starts it could end anywhere */
	if(floppysend(Fseek) < 0
	|| floppysend((dp->thead<<2) | dp->dev) < 0
	|| floppysend(dp->tcyl * dp->t->steps) < 0){
/* print("seeking tcyl %d, thead %d\n", dp->tcyl, dp->thead); /**/
	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){
		print("seek cmd failed\n");
		floppy.confused = 1;
		return -1;
	}
	sleep(&floppy.r, interrupted, 0);

	/*
	 *  get floppy status
	 */
	if(floppysense(dp) < 0)
		return -1;

	/*
 	 *  see if it worked
	 */
	if((floppy.stat[0] & (Codemask|Seekend)) != Seekend){
		print("seek failed\n");
		dp->confused = 1;
	floppywait();
	if(fl.nstat < 2){
		fl.confused = 1;
		return -1;
	}

	/*
	 *  see what cylinder we got to
	 */
	dp->cyl = floppy.stat[1]/dp->t->steps;
	if(dp->cyl != dp->tcyl){
		print("seek went to wrong cylinder %d instead of %d\n", dp->cyl, dp->tcyl);
	if((fl.stat[0] & (Codemask|Seekend)) != Seekend){
		print("seek failed\n");
		dp->confused = 1;
		return -1;
	}

	dp->cyl = dp->tcyl;
	return dp->cyl;
}



@@ 716,95 716,120 @@ static long
floppyxfer(Drive *dp, int cmd, void *a, long off, long n)
{
	long offset;
	ulong up;

	if(off >= dp->t->cap)
		return 0;
	if(off + n > dp->t->cap)
		n = dp->t->cap - off;

	qlock(&floppy);
	qlock(&fl);
	qlock(dp);
	if(waserror()){
		qunlock(&floppy);
		dmaend(DMAchan);
		qunlock(&fl);
		qunlock(dp);
		fl.confused = 1;
		nexterror();
	}

	/*
	 *  get floppy reset and spinning
	 */
	if(floppy.confused || dp->confused)
		floppyrevive();
	motoron(dp);

	/*
	 *  calculate new position and seek to it (dp->len may be trimmed)
	 */
	dp->len = n;
	floppypos(dp, off);
	if(floppyseek(dp) < 0)
	if(floppyseek(dp, off) < 0)
		errors("seeking floppy");

	
/*print("tcyl %d, thead %d, tsec %d, addr %lux, n %d\n",
		dp->tcyl, dp->thead, dp->tsec, a, n);/**/
	dp->tcyl, dp->thead, dp->tsec, a, dp->len);/**/

	/*
	 *  set up the dma (dp->len may be trimmed)
	 */
	dp->len = dmasetup(2, a, dp->len, cmd==Fread);
	dp->len = dmasetup(DMAchan, a, dp->len, cmd==Fread);

	/*
	 *  start operation
	 */
	floppy.intr = 0;
	cmd = cmd | (dp->t->heads > 1 ? Fmulti : 0);
	if(floppysend(cmd) < 0
	|| floppysend((dp->thead<<2) | dp->dev) < 0
	|| floppysend(dp->tcyl * dp->t->steps) < 0
	|| floppysend(dp->thead) < 0
	|| floppysend(dp->tsec) < 0
	|| floppysend(dp->t->bcode) < 0
	|| floppysend(dp->t->sectors) < 0
	|| floppysend(dp->t->gpl) < 0
	|| floppysend(0xFF) < 0){
/*	cmd = cmd | (dp->t->heads > 1 ? Fmulti : 0);/**/
	fl.ncmd = 0;
	fl.cmd[fl.ncmd++] = cmd;
	fl.cmd[fl.ncmd++] = (dp->thead<<2) | dp->dev;
	fl.cmd[fl.ncmd++] = dp->tcyl * dp->t->steps;
	fl.cmd[fl.ncmd++] = dp->thead;
	fl.cmd[fl.ncmd++] = dp->tsec;
	fl.cmd[fl.ncmd++] = dp->t->bcode;
	fl.cmd[fl.ncmd++] = dp->tsec + dp->len/dp->t->bytes - 1;
	fl.cmd[fl.ncmd++] = dp->t->gpl;
	fl.cmd[fl.ncmd++] = 0xFF;
	if(floppycmd() < 0){
		spllo();
		print("xfer cmd failed\n");
		floppy.confused = 1;
		errors("floppy command failed");
	}
	sleep(&floppy.r, interrupted, 0);

	/*
	 *  get status
 	 */
	if(floppyresult(7) < 0){
print("xfer status failed\n");
		floppy.confused = 1;
	 *  give bus to DMA, floppyintr() will read result
	 */
	floppywait();
	dmaend(DMAchan);

	/*
	 *  check for errors
	 */
	if(fl.nstat < 7){
		print("xfer result failed %lux\n", inb(Pmsr));
		fl.confused = 1;
		errors("floppy result failed");
	}

	if((floppy.stat[0] & Codemask)!=0 || floppy.stat[1] || floppy.stat[2]){
print("xfer failed %lux %lux %lux\n", floppy.stat[0],
			floppy.stat[1], floppy.stat[2]);
		dp->confused = 1;
		errors("floppy drive lost");
	if((fl.stat[0] & Codemask)!=0 || fl.stat[1] || fl.stat[2]){
		if(fl.stat[1] != 0x80){
			print("xfer failed %lux %lux %lux\n", fl.stat[0],
				fl.stat[1], fl.stat[2]);
			print("offset %lud len %d\n", off, dp->len);
			dp->confused = 1;
			errors("floppy drive lost");
		} else
			fl.stat[5]++;
	}

	offset = (floppy.stat[3]/dp->t->steps) * dp->t->heads + floppy.stat[4];
	offset = offset*dp->t->sectors + floppy.stat[5] - 1;
	offset = offset * c2b[floppy.stat[6]];
	/*
	 *  check for correct cylinder
	 */
	offset = (fl.stat[3]/dp->t->steps) * 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){
print("new offset %d instead of %d\n", offset, off+dp->len);
		print("new offset %d instead of %d\n", offset, off+dp->len);
		dp->confused = 1;
		errors("floppy drive lost");
	}

	dp->lasttouched = m->ticks;
	qunlock(&floppy);
	qunlock(&fl);
	qunlock(dp);
	poperror();

	return dp->len;
}

static void
floppyintr(Ureg *ur)
void
floppyintr(void)
{
/*print("floppy intr\n");/**/
	floppy.intr = 1;
	wakeup(&floppy.r);
	switch(fl.cmd[0]&~Fmulti){
	case Fread:
	case Fwrite:
		floppyresult();
		break;
	case Freadid:
		floppyresult();
		break;
	case Fseek:
	case Frecal:
	default:
		floppysense();	/* to clear interrupt */
		break;
	}
	fl.ncmd = 0;
	wakeup(&fl.r);
}

M port/devmnt.c => port/devmnt.c +1 -1
@@ 351,7 351,6 @@ mntclunk(Chan *c, int t)
	m = mntchk(c);
	r = mntralloc();
	if(waserror()){
		mntfree(r);
		if(decref(m) == 0) {
			for(q = m->queue; q; q = r) {
				r = q->list;


@@ 365,6 364,7 @@ mntclunk(Chan *c, int t)
			mntalloc.mntfree = m;
			unlock(&mntalloc);
		}
		mntfree(r);
		return;
	}


M power/boot.h => power/boot.h +823 -703
@@ 1,6 1,6 @@
ulong bootcode[]={
	0x000000407,
	0x0000054d0,
	0x0000056b0,
	0x000000740,
	0x000001290,
	0x000000000,


@@ 638,7 638,7 @@ ulong bootcode[]={
	0x023c29842,
	0x0afa20004,
	0x023c48842,
	0x00c000df3,
	0x00c000e27,
	0x0afa40008,
	0x08fa30024,
	0x023c48842,


@@ 757,7 757,7 @@ ulong bootcode[]={
	0x023c39842,
	0x0afa30004,
	0x023c48842,
	0x00c000df3,
	0x00c000e27,
	0x0afa40008,
	0x08fa20024,
	0x023c48842,


@@ 1393,7 1393,7 @@ ulong bootcode[]={
	0x023a41020,
	0x0afa3000c,
	0x024840004,
	0x00c0011ed,
	0x00c001266,
	0x0afa40010,
	0x023a6001c,
	0x020020001,


@@ 1430,7 1430,7 @@ ulong bootcode[]={
	0x023a41024,
	0x0afa3000c,
	0x024840004,
	0x00c0011ed,
	0x00c001266,
	0x0afa40010,
	0x08fa21020,
	0x023a6001c,


@@ 1469,7 1469,7 @@ ulong bootcode[]={
	0x023a40024,
	0x0afa2000c,
	0x024840004,
	0x00c0011ed,
	0x00c001266,
	0x0afa40010,
	0x08fa20014,
	0x000000027,


@@ 1600,7 1600,7 @@ ulong bootcode[]={
	0x08fa20010,
	0x000000027,
	0x0afa20004,
	0x00c001785,
	0x00c0017fe,
	0x0afa00008,
	0x08fa30010,
	0x08fa20000,


@@ 1684,7 1684,7 @@ ulong bootcode[]={
	0x0afa50010,
	0x0afa50008,
	0x02003001c,
	0x00c001838,
	0x00c0018b1,
	0x0afa3000c,
	0x08fa20010,
	0x08fa3001c,


@@ 1694,7 1694,7 @@ ulong bootcode[]={
	0x0afa50010,
	0x0afa50008,
	0x02003001c,
	0x00c001838,
	0x00c0018b1,
	0x0afa3000c,
	0x08fa20010,
	0x08fa3001c,


@@ 1704,7 1704,7 @@ ulong bootcode[]={
	0x0afa50010,
	0x0afa50008,
	0x02003001c,
	0x00c001838,
	0x00c0018b1,
	0x0afa3000c,
	0x08fa5001c,
	0x08fa20010,


@@ 1845,31 1845,34 @@ ulong bootcode[]={
	0x000621825,
	0x0a4c30004,
	0x080c30000,
	0x020020042,
	0x020020043,
	0x00043202a,
	0x01480016b,
	0x014800197,
	0x000000027,
	0x010620142,
	0x01062016c,
	0x000000027,
	0x02002003a,
	0x02002003b,
	0x00043202a,
	0x01480006b,
	0x014800097,
	0x000000027,
	0x010620043,
	0x01062006c,
	0x000000027,
	0x020020035,
	0x020020037,
	0x00043202a,
	0x01480001f,
	0x01480002c,
	0x000000027,
	0x01062000e,
	0x010620020,
	0x000000027,
	0x020020032,
	0x01062000b,
	0x01062000e,
	0x000000027,
	0x020020033,
	0x010620008,
	0x01062000b,
	0x000000027,
	0x020020034,
	0x010620008,
	0x000000027,
	0x020020035,
	0x010620005,
	0x000000027,
	0x08fa20000,


@@ 1891,38 1894,29 @@ ulong bootcode[]={
	0x023bd0014,
	0x000400008,
	0x000000825,
	0x020020037,
	0x010620014,
	0x000000027,
	0x020020038,
	0x010620008,
	0x000000027,
	0x020020039,
	0x01062ffe9,
	0x000000027,
	0x08fa20000,
	0x023bd0014,
	0x000400008,
	0x000000825,
	0x090a30000,
	0x090a20001,
	0x0306300ff,
	0x0304200ff,
	0x000021200,
	0x000621825,
	0x024a50002,
	0x008000b55,
	0x0a4c30008,
	0x024c20008,
	0x0afa20004,
	0x0afa50010,
	0x0afa50008,
	0x020020040,
	0x00c001838,
	0x00c0018b1,
	0x0afa2000c,
	0x08fa30010,
	0x008000b55,
	0x008000b58,
	0x024650040,
	0x020020038,
	0x010620031,
	0x000000027,
	0x020020039,
	0x01062ffe2,
	0x000000027,
	0x02002003a,
	0x010620005,
	0x000000027,
	0x08fa20000,
	0x023bd0014,
	0x000400008,
	0x000000825,
	0x090a30000,
	0x090a20001,
	0x0306300ff,


@@ 1936,7 1930,7 @@ ulong bootcode[]={
	0x0afa50010,
	0x0afa50008,
	0x02003001c,
	0x00c001838,
	0x00c0018b1,
	0x0afa3000c,
	0x08fa20010,
	0x08fa3001c,


@@ 1946,7 1940,7 @@ ulong bootcode[]={
	0x0afa50010,
	0x0afa50008,
	0x02003001c,
	0x00c001838,
	0x00c0018b1,
	0x0afa3000c,
	0x08fa20010,
	0x08fa3001c,


@@ 1956,30 1950,98 @@ ulong bootcode[]={
	0x0afa50010,
	0x0afa50008,
	0x02003001c,
	0x00c001838,
	0x00c0018b1,
	0x0afa3000c,
	0x08fa20010,
	0x008000b55,
	0x008000b58,
	0x02445001c,
	0x02002003e,
	0x090a30000,
	0x090a20001,
	0x0306300ff,
	0x0304200ff,
	0x000021200,
	0x000621825,
	0x024a50002,
	0x008000b58,
	0x0a4c30008,
	0x090a20000,
	0x090a30001,
	0x0304200ff,
	0x0306300ff,
	0x000031a00,
	0x000431025,
	0x0a4c20002,
	0x024a50002,
	0x090a20000,
	0x090a30001,
	0x0304200ff,
	0x0306300ff,
	0x000031a00,
	0x090a40002,
	0x000431025,
	0x0308400ff,
	0x000042400,
	0x090a30003,
	0x000441025,
	0x0306300ff,
	0x000031e00,
	0x000431025,
	0x0acc2000c,
	0x024a50004,
	0x090a20000,
	0x090a30001,
	0x0304200ff,
	0x0306300ff,
	0x000031a00,
	0x090a40002,
	0x000431025,
	0x0308400ff,
	0x000042400,
	0x090a30003,
	0x000441025,
	0x0306300ff,
	0x000031e00,
	0x000431025,
	0x024a50004,
	0x008000b58,
	0x0acc20010,
	0x02002003f,
	0x00043202a,
	0x014800065,
	0x000000027,
	0x010620051,
	0x000000027,
	0x02002003b,
	0x010620025,
	0x01062003a,
	0x000000027,
	0x02002003c,
	0x010620011,
	0x010620026,
	0x000000027,
	0x02002003d,
	0x01062001a,
	0x000000027,
	0x02002003e,
	0x010620005,
	0x000000027,
	0x08fa20000,
	0x023bd0014,
	0x000400008,
	0x000000825,
	0x090a30000,
	0x090a20001,
	0x0306300ff,
	0x0304200ff,
	0x000021200,
	0x000621825,
	0x0a4c30002,
	0x024a50002,
	0x024c3000e,
	0x0afa30004,
	0x0afa50010,
	0x0afa50008,
	0x02003001c,
	0x00c0018b1,
	0x0afa3000c,
	0x08fa20010,
	0x008000b58,
	0x02445001c,
	0x090a20000,
	0x090a30001,
	0x0304200ff,


@@ 1987,7 2049,7 @@ ulong bootcode[]={
	0x000031a00,
	0x000431025,
	0x024a50002,
	0x008000b55,
	0x008000b58,
	0x0a4c20002,
	0x090a30000,
	0x090a20001,


@@ 2004,7 2066,7 @@ ulong bootcode[]={
	0x000021200,
	0x000621825,
	0x024a50002,
	0x008000b55,
	0x008000b58,
	0x0a4c3000c,
	0x090a20000,
	0x090a30001,


@@ 2045,8 2107,21 @@ ulong bootcode[]={
	0x000031e00,
	0x000431025,
	0x024a50004,
	0x008000b55,
	0x008000b58,
	0x0acc20010,
	0x020020040,
	0x01062005b,
	0x000000027,
	0x020020041,
	0x01062002f,
	0x000000027,
	0x020020042,
	0x010620005,
	0x000000027,
	0x08fa20000,
	0x023bd0014,
	0x000400008,
	0x000000825,
	0x090a30000,
	0x090a20001,
	0x0306300ff,


@@ 2060,24 2135,32 @@ ulong bootcode[]={
	0x0afa50010,
	0x0afa50008,
	0x02003001c,
	0x00c001838,
	0x00c0018b1,
	0x0afa3000c,
	0x08fa6001c,
	0x08fa20010,
	0x008000b55,
	0x02445001c,
	0x02002003f,
	0x010620040,
	0x000000027,
	0x020020040,
	0x010620031,
	0x000000027,
	0x020020041,
	0x010620005,
	0x000000027,
	0x08fa20000,
	0x023bd0014,
	0x000400008,
	0x000000825,
	0x02445001c,
	0x090a30000,
	0x090a20001,
	0x0306300ff,
	0x0304200ff,
	0x000021200,
	0x090a40002,
	0x000621825,
	0x0308400ff,
	0x000042400,
	0x090a20003,
	0x000641825,
	0x0304200ff,
	0x000021600,
	0x000621825,
	0x0acc30008,
	0x024a20004,
	0x024450001,
	0x080420000,
	0x008000b58,
	0x0a0c2002a,
	0x090a20000,
	0x090a30001,
	0x0304200ff,


@@ 2117,7 2200,7 @@ ulong bootcode[]={
	0x000031e00,
	0x000431025,
	0x024a50004,
	0x008000b55,
	0x008000b58,
	0x0acc20010,
	0x090a30000,
	0x090a20001,


@@ 2129,7 2212,7 @@ ulong bootcode[]={
	0x024a20002,
	0x024450001,
	0x080420000,
	0x008000b55,
	0x008000b58,
	0x0a0c2002a,
	0x090a20000,
	0x090a30001,


@@ 2170,8 2253,53 @@ ulong bootcode[]={
	0x000031e00,
	0x000431025,
	0x024a50004,
	0x008000b55,
	0x008000b58,
	0x0acc20010,
	0x02002004c,
	0x00043202a,
	0x0148000bf,
	0x000000027,
	0x0106200b4,
	0x000000027,
	0x020020048,
	0x00043202a,
	0x014800088,
	0x000000027,
	0x01062007d,
	0x000000027,
	0x020020044,
	0x010620059,
	0x000000027,
	0x020020045,
	0x010620041,
	0x000000027,
	0x020020046,
	0x010620019,
	0x000000027,
	0x020020047,
	0x010620005,
	0x000000027,
	0x08fa20000,
	0x023bd0014,
	0x000400008,
	0x000000825,
	0x090a30000,
	0x090a20001,
	0x0306300ff,
	0x0304200ff,
	0x000021200,
	0x000621825,
	0x0a4c30002,
	0x024a50002,
	0x090a30000,
	0x090a20001,
	0x0306300ff,
	0x0304200ff,
	0x000021200,
	0x000621825,
	0x024a50002,
	0x008000b58,
	0x0acc3000c,
	0x090a30000,
	0x090a20001,
	0x0306300ff,


@@ 2180,17 2308,6 @@ ulong bootcode[]={
	0x000621825,
	0x0a4c30002,
	0x024a50002,
	0x024c3000e,
	0x0afa30004,
	0x0afa50010,
	0x0afa50008,
	0x02003001c,
	0x00c001838,
	0x0afa3000c,
	0x08fa6001c,
	0x08fa20010,
	0x000000027,
	0x02445001c,
	0x090a30000,
	0x090a20001,
	0x0306300ff,


@@ 2206,36 2323,20 @@ ulong bootcode[]={
	0x000021600,
	0x000621825,
	0x0acc30008,
	0x024a20004,
	0x024a50008,
	0x090a30000,
	0x090a20001,
	0x0306300ff,
	0x0304200ff,
	0x000021200,
	0x000621825,
	0x0acc3000c,
	0x024a20002,
	0x024450001,
	0x080420000,
	0x008000b55,
	0x0a0c2002a,
	0x02002004a,
	0x00043202a,
	0x0148000d3,
	0x000000027,
	0x0106200c8,
	0x000000027,
	0x020020046,
	0x00043202a,
	0x014800094,
	0x000000027,
	0x01062006d,
	0x000000027,
	0x020020043,
	0x010620041,
	0x000000027,
	0x020020044,
	0x01062001d,
	0x000000027,
	0x020020045,
	0x010620005,
	0x000000027,
	0x08fa20000,
	0x023bd0014,
	0x000400008,
	0x000000825,
	0x0acc50010,
	0x08cc2000c,
	0x008000b58,
	0x000a22821,
	0x090a20000,
	0x090a30001,
	0x0304200ff,


@@ 2255,7 2356,7 @@ ulong bootcode[]={
	0x024650001,
	0x0acc50010,
	0x08cc3000c,
	0x008000b55,
	0x008000b58,
	0x000a32821,
	0x090a30000,
	0x090a20001,


@@ 2288,7 2389,7 @@ ulong bootcode[]={
	0x000021200,
	0x000621825,
	0x024a50002,
	0x008000b55,
	0x008000b58,
	0x0acc3000c,
	0x090a20000,
	0x090a30001,


@@ 2296,85 2397,16 @@ ulong bootcode[]={
	0x0306300ff,
	0x000031a00,
	0x000431025,
	0x0a4c20002,
	0x024a50002,
	0x090a20000,
	0x090a30001,
	0x0304200ff,
	0x0306300ff,
	0x000031a00,
	0x090a40002,
	0x000431025,
	0x0308400ff,
	0x000042400,
	0x090a30003,
	0x000441025,
	0x0306300ff,
	0x000031e00,
	0x000431025,
	0x0acc2000c,
	0x024a50004,
	0x090a20000,
	0x090a30001,
	0x0304200ff,
	0x0306300ff,
	0x000031a00,
	0x090a40002,
	0x000431025,
	0x0308400ff,
	0x000042400,
	0x090a30003,
	0x000441025,
	0x0306300ff,
	0x000031e00,
	0x000431025,
	0x024a50004,
	0x008000b55,
	0x0acc20010,
	0x090a30000,
	0x090a20001,
	0x0306300ff,
	0x0304200ff,
	0x000021200,
	0x000621825,
	0x0a4c30002,
	0x024a50002,
	0x090a30000,
	0x090a20001,
	0x0306300ff,
	0x0304200ff,
	0x000021200,
	0x090a40002,
	0x000621825,
	0x0308400ff,
	0x000042400,
	0x090a20003,
	0x000641825,
	0x0304200ff,
	0x000021600,
	0x000621825,
	0x0acc30008,
	0x024a50008,
	0x090a30000,
	0x090a20001,
	0x0306300ff,
	0x0304200ff,
	0x000021200,
	0x000621825,
	0x0acc3000c,
	0x024a20002,
	0x024450001,
	0x0acc50010,
	0x08cc2000c,
	0x008000b55,
	0x000a22821,
	0x020020047,
	0x008000b58,
	0x0a4c20002,
	0x020020049,
	0x01062001d,
	0x000000027,
	0x020020048,
	0x02002004a,
	0x010620011,
	0x000000027,
	0x020020049,
	0x02002004b,
	0x010620005,
	0x000000027,
	0x08fa20000,


@@ 2388,7 2420,7 @@ ulong bootcode[]={
	0x000021200,
	0x000621825,
	0x024a50002,
	0x008000b55,
	0x008000b58,
	0x0a4c30002,
	0x090a20000,
	0x090a30001,


@@ 2397,7 2429,7 @@ ulong bootcode[]={
	0x000031a00,
	0x000431025,
	0x024a50002,
	0x008000b55,
	0x008000b58,
	0x0a4c20002,
	0x090a30000,
	0x090a20001,


@@ 2405,17 2437,9 @@ ulong bootcode[]={
	0x0304200ff,
	0x000021200,
	0x000621825,
	0x0a4c30002,
	0x024a50002,
	0x090a30000,
	0x090a20001,
	0x0306300ff,
	0x0304200ff,
	0x000021200,
	0x000621825,
	0x024a50002,
	0x008000b55,
	0x0acc3000c,
	0x008000b58,
	0x0a4c30002,
	0x090a20000,
	0x090a30001,
	0x0304200ff,


@@ 2423,21 2447,21 @@ ulong bootcode[]={
	0x000031a00,
	0x000431025,
	0x024a50002,
	0x008000b55,
	0x008000b58,
	0x0a4c20002,
	0x02002004e,
	0x020020050,
	0x00043202a,
	0x014800046,
	0x014800057,
	0x000000027,
	0x010620032,
	0x01062003b,
	0x000000027,
	0x02002004b,
	0x02002004d,
	0x010620026,
	0x000000027,
	0x02002004c,
	0x01062001a,
	0x02002004e,
	0x010620011,
	0x000000027,
	0x02002004d,
	0x02002004f,
	0x010620005,
	0x000000027,
	0x08fa20000,


@@ 2450,6 2474,33 @@ ulong bootcode[]={
	0x0304200ff,
	0x000021200,
	0x000621825,
	0x024a50002,
	0x008000b58,
	0x0a4c30002,
	0x090a20000,
	0x090a30001,
	0x0304200ff,
	0x0306300ff,
	0x000031a00,
	0x000431025,
	0x0a4c20002,
	0x024a50002,
	0x024c20008,
	0x0afa20004,
	0x0afa50010,
	0x0afa50008,
	0x020020074,
	0x00c0018b1,
	0x0afa2000c,
	0x08fa30010,
	0x008000b58,
	0x024650074,
	0x090a30000,
	0x090a20001,
	0x0306300ff,
	0x0304200ff,
	0x000021200,
	0x000621825,
	0x0a4c30002,
	0x024a50002,
	0x024c30008,


@@ 2457,10 2508,10 @@ ulong bootcode[]={
	0x0afa50010,
	0x0afa50008,
	0x020030074,
	0x00c001838,
	0x00c0018b1,
	0x0afa3000c,
	0x08fa20010,
	0x008000b55,
	0x008000b58,
	0x024450074,
	0x090a20000,
	0x090a30001,


@@ 2468,44 2519,34 @@ ulong bootcode[]={
	0x0306300ff,
	0x000031a00,
	0x000431025,
	0x024a50002,
	0x008000b55,
	0x0a4c20002,
	0x090a30000,
	0x090a20001,
	0x0306300ff,
	0x0304200ff,
	0x000021200,
	0x000621825,
	0x024a50002,
	0x008000b55,
	0x0a4c30002,
	0x090a20000,
	0x090a30001,
	0x0304200ff,
	0x0306300ff,
	0x000031a00,
	0x000431025,
	0x0a4c20002,
	0x0a4c2000c,
	0x024a50002,
	0x024c20008,
	0x024c2000e,
	0x0afa20004,
	0x0afa50010,
	0x0afa50008,
	0x020020074,
	0x00c001838,
	0x02002001c,
	0x00c0018b1,
	0x0afa2000c,
	0x08fa30010,
	0x008000b55,
	0x024650074,
	0x02002004f,
	0x010620025,
	0x008000b58,
	0x02465001c,
	0x020020051,
	0x01062fe27,
	0x000000027,
	0x020020050,
	0x010620008,
	0x020020052,
	0x01062001a,
	0x000000027,
	0x020020051,
	0x01062fe89,
	0x020020053,
	0x010620005,
	0x000000027,
	0x08fa20000,
	0x023bd0014,


@@ 2519,33 2560,44 @@ ulong bootcode[]={
	0x000431025,
	0x0a4c20002,
	0x024a50002,
	0x090a20000,
	0x090a30001,
	0x0304200ff,
	0x0306300ff,
	0x000031a00,
	0x000431025,
	0x0a4c2000c,
	0x024a50002,
	0x024c2000e,
	0x024c20024,
	0x0afa20004,
	0x0afa50010,
	0x0afa50008,
	0x02002001c,
	0x00c001838,
	0x02002001e,
	0x00c0018b1,
	0x0afa2000c,
	0x08fa30010,
	0x008000b55,
	0x02465001c,
	0x008000b58,
	0x02465001e,
	0x090a30000,
	0x090a20001,
	0x0306300ff,
	0x0304200ff,
	0x000021200,
	0x000621825,
	0x024a50002,
	0x008000b55,
	0x0a4c30002,
	0x024a50002,
	0x024c30008,
	0x0afa30004,
	0x0afa50010,
	0x0afa50008,
	0x02003001c,
	0x00c0018b1,
	0x0afa3000c,
	0x08fa20010,
	0x08fa3001c,
	0x02445001c,
	0x024630024,
	0x0afa30004,
	0x0afa50010,
	0x0afa50008,
	0x020030024,
	0x00c0018b1,
	0x0afa3000c,
	0x08fa20010,
	0x008000b58,
	0x024450024,
	0x023bdffec,
	0x0afbf0000,
	0x08fa50018,


@@ 2554,75 2606,50 @@ ulong bootcode[]={
	0x024660001,
	0x0a0640000,
	0x094a30004,
	0x020020042,
	0x000000027,
	0x0a0c30000,
	0x094a30004,
	0x000000027,
	0x03063ffff,
	0x000031a02,
	0x0a0c30001,
	0x080a30000,
	0x000000027,
	0x00043202a,
	0x0148001ab,
	0x080a20000,
	0x020030043,
	0x00062202a,
	0x0148001de,
	0x024c60002,
	0x01062017b,
	0x000000027,
	0x02002003a,
	0x00043202a,
	0x014800078,
	0x000000027,
	0x010620046,
	0x0104301ae,
	0x000000027,
	0x020020035,
	0x00043202a,
	0x014800017,
	0x000000027,
	0x01062000e,
	0x000000027,
	0x020020032,
	0x01062000b,
	0x02003003b,
	0x00062202a,
	0x0148000a9,
	0x000000027,
	0x020020033,
	0x010620008,
	0x010430079,
	0x000000027,
	0x020020034,
	0x010620005,
	0x020030037,
	0x00062202a,
	0x014800029,
	0x000000027,
	0x08fa20000,
	0x023bd0014,
	0x000400008,
	0x000000825,
	0x08fa2001c,
	0x010430018,
	0x000000027,
	0x000c20823,
	0x08fa20000,
	0x020030032,
	0x01043000e,
	0x000000027,
	0x000400008,
	0x023bd0014,
	0x020020037,
	0x01062001a,
	0x020030033,
	0x01043000b,
	0x000000027,
	0x020020038,
	0x010620008,
	0x020030034,
	0x010430008,
	0x000000027,
	0x020020039,
	0x01062fff1,
	0x020030035,
	0x010430005,
	0x000000027,
	0x08fa20000,
	0x023bd0014,
	0x000400008,
	0x000000825,
	0x094a20008,
	0x000000027,
	0x0a0c20000,
	0x094a20008,
	0x000000027,
	0x03042ffff,
	0x000021202,
	0x0a0c20001,
	0x08fa2001c,
	0x024c60002,
	0x000000027,
	0x000c20823,
	0x08fa20000,
	0x000000027,


@@ 2633,7 2660,7 @@ ulong bootcode[]={
	0x024a30008,
	0x0afa30008,
	0x020020040,
	0x00c001838,
	0x00c0018b1,
	0x0afa2000c,
	0x08fa30010,
	0x08fa2001c,


@@ 2643,6 2670,19 @@ ulong bootcode[]={
	0x000000027,
	0x000400008,
	0x023bd0014,
	0x020030038,
	0x01043003b,
	0x000000027,
	0x020030039,
	0x01043ffe5,
	0x000000027,
	0x02003003a,
	0x010430005,
	0x000000027,
	0x08fa20000,
	0x023bd0014,
	0x000400008,
	0x000000825,
	0x084a30002,
	0x024c20002,
	0x0a0c30000,


@@ 2657,7 2697,7 @@ ulong bootcode[]={
	0x024a20008,
	0x0afa20008,
	0x02003001c,
	0x00c001838,
	0x00c0018b1,
	0x0afa3000c,
	0x08fa20010,
	0x02003001c,


@@ 2668,7 2708,7 @@ ulong bootcode[]={
	0x000000027,
	0x024420024,
	0x0afa20008,
	0x00c001838,
	0x00c0018b1,
	0x0afa3000c,
	0x08fa20010,
	0x02003001c,


@@ 2679,7 2719,7 @@ ulong bootcode[]={
	0x000000027,
	0x024420040,
	0x0afa20008,
	0x00c001838,
	0x00c0018b1,
	0x0afa3000c,
	0x08fa20010,
	0x000000027,


@@ 2691,33 2731,13 @@ ulong bootcode[]={
	0x000000027,
	0x000400008,
	0x023bd0014,
	0x02002003e,
	0x00043202a,
	0x01480007f,
	0x000000027,
	0x010620065,
	0x000000027,
	0x02002003b,
	0x010620034,
	0x000000027,
	0x02002003c,
	0x010620018,
	0x000000027,
	0x02002003d,
	0x010620005,
	0x000000027,
	0x08fa20000,
	0x023bd0014,
	0x000400008,
	0x000000825,
	0x084a20002,
	0x094a20008,
	0x000000027,
	0x0a0c20000,
	0x084a20002,
	0x094a20008,
	0x000000027,
	0x000021400,
	0x000021403,
	0x000021203,
	0x03042ffff,
	0x000021202,
	0x0a0c20001,
	0x08fa2001c,
	0x024c60002,


@@ 2726,32 2746,7 @@ ulong bootcode[]={
	0x000000027,
	0x000400008,
	0x023bd0014,
	0x084a20002,
	0x000000027,
	0x0a0c20000,
	0x084a20002,
	0x000000027,
	0x000021400,
	0x000021403,
	0x000021203,
	0x0a0c20001,
	0x084a3000c,
	0x024c60002,
	0x0a0c30000,
	0x084a3000c,
	0x000000027,
	0x000031c00,
	0x000031c03,
	0x000031a03,
	0x0a0c30001,
	0x08fa2001c,
	0x024c60002,
	0x000c20823,
	0x08fa20000,
	0x000000027,
	0x000400008,
	0x023bd0014,
	0x084a30002,
	0x084a30002,
	0x000000027,
	0x0a0c30000,
	0x084a30002,


@@ 2797,43 2792,92 @@ ulong bootcode[]={
	0x000000027,
	0x000400008,
	0x023bd0014,
	0x084a20002,
	0x024c30002,
	0x0a0c20000,
	0x084a20002,
	0x02003003f,
	0x00062202a,
	0x014800081,
	0x000000027,
	0x000021400,
	0x000021403,
	0x000021203,
	0x0a0c20001,
	0x0afa30010,
	0x0afa30004,
	0x024a3000e,
	0x0afa30008,
	0x02002001c,
	0x00c001838,
	0x0afa2000c,
	0x08fa30010,
	0x010430051,
	0x000000027,
	0x02003003c,
	0x010430035,
	0x000000027,
	0x02003003d,
	0x010430022,
	0x000000027,
	0x02003003e,
	0x010430005,
	0x000000027,
	0x08fa20000,
	0x023bd0014,
	0x000400008,
	0x000000825,
	0x084a30002,
	0x024c20002,
	0x0a0c30000,
	0x084a30002,
	0x000000027,
	0x000031c00,
	0x000031c03,
	0x000031a03,
	0x0a0c30001,
	0x0afa20010,
	0x0afa20004,
	0x024a2000e,
	0x0afa20008,
	0x02003001c,
	0x00c0018b1,
	0x0afa3000c,
	0x08fa20010,
	0x000000027,
	0x02446001c,
	0x08fa2001c,
	0x02466001c,
	0x000000027,
	0x000c20823,
	0x08fa20000,
	0x000000027,
	0x000400008,
	0x023bd0014,
	0x02002003f,
	0x01062004d,
	0x000000027,
	0x020020040,
	0x010620036,
	0x084a30002,
	0x000000027,
	0x020020041,
	0x010620005,
	0x0a0c30000,
	0x084a30002,
	0x000000027,
	0x000031c00,
	0x000031c03,
	0x000031a03,
	0x0a0c30001,
	0x08fa2001c,
	0x024c60002,
	0x000c20823,
	0x08fa20000,
	0x000000027,
	0x000400008,
	0x023bd0014,
	0x084a30002,
	0x000000027,
	0x0a0c30000,
	0x084a30002,
	0x000000027,
	0x000031c00,
	0x000031c03,
	0x000031a03,
	0x0a0c30001,
	0x084a2000c,
	0x024c60002,
	0x0a0c20000,
	0x084a2000c,
	0x000000027,
	0x000021400,
	0x000021403,
	0x000021203,
	0x0a0c20001,
	0x08fa2001c,
	0x024c60002,
	0x000c20823,
	0x08fa20000,
	0x000000027,
	0x000400008,
	0x000000825,
	0x023bd0014,
	0x084a20002,
	0x000000027,
	0x0a0c20000,


@@ 2880,8 2924,21 @@ ulong bootcode[]={
	0x000000027,
	0x000400008,
	0x023bd0014,
	0x084a30002,
	0x020030040,
	0x010430067,
	0x000000027,
	0x020030041,
	0x010430036,
	0x000000027,
	0x020030042,
	0x010430005,
	0x000000027,
	0x08fa20000,
	0x023bd0014,
	0x000400008,
	0x000000825,
	0x084a30002,
	0x024c20002,
	0x0a0c30000,
	0x084a30002,
	0x000000027,


@@ 2889,10 2946,36 @@ ulong bootcode[]={
	0x000031c03,
	0x000031a03,
	0x0a0c30001,
	0x024c30002,
	0x090a4002a,
	0x024660001,
	0x0a0640000,
	0x0afa20010,
	0x0afa20004,
	0x024a2000e,
	0x0afa20008,
	0x02003001c,
	0x00c0018b1,
	0x0afa3000c,
	0x08fa70018,
	0x08fa20010,
	0x000000027,
	0x02445001c,
	0x08ce20008,
	0x000000027,
	0x0a0a20000,
	0x08ce20008,
	0x000000027,
	0x000021203,
	0x0a0a20001,
	0x08ce20008,
	0x000000027,
	0x000021403,
	0x0a0a20002,
	0x08ce20008,
	0x000000027,
	0x000021603,
	0x0a0a20003,
	0x024a20004,
	0x090e4002a,
	0x024460001,
	0x0a0440000,
	0x08fa2001c,
	0x000000027,
	0x000c20823,


@@ 2946,77 3029,123 @@ ulong bootcode[]={
	0x000000027,
	0x000400008,
	0x023bd0014,
	0x084a30002,
	0x084a20002,
	0x000000027,
	0x0a0c20000,
	0x084a20002,
	0x000000027,
	0x000021400,
	0x000021403,
	0x000021203,
	0x0a0c20001,
	0x024c20002,
	0x090a4002a,
	0x024460001,
	0x0a0440000,
	0x08fa2001c,
	0x000000027,
	0x000c20823,
	0x08fa20000,
	0x000000027,
	0x000400008,
	0x023bd0014,
	0x084a20002,
	0x000000027,
	0x0a0c20000,
	0x084a20002,
	0x000000027,
	0x000021400,
	0x000021403,
	0x000021203,
	0x0a0c20001,
	0x08ca3000c,
	0x024c60002,
	0x0a0c30000,
	0x084a30002,
	0x08ca3000c,
	0x000000027,
	0x000031c00,
	0x000031c03,
	0x000031a03,
	0x000031a02,
	0x0a0c30001,
	0x0afa20010,
	0x0afa20004,
	0x024a2000e,
	0x0afa20008,
	0x02003001c,
	0x00c001838,
	0x0afa3000c,
	0x08fa70018,
	0x08fa20010,
	0x08ca3000c,
	0x000000027,
	0x02445001c,
	0x08ce20008,
	0x000031c02,
	0x0a0c30002,
	0x08ca3000c,
	0x000000027,
	0x0a0a20000,
	0x08ce20008,
	0x000031e02,
	0x0a0c30003,
	0x08ca20010,
	0x024c60004,
	0x0a0c20000,
	0x08ca20010,
	0x000000027,
	0x000021203,
	0x0a0a20001,
	0x08ce20008,
	0x000021202,
	0x0a0c20001,
	0x08ca20010,
	0x000000027,
	0x000021403,
	0x0a0a20002,
	0x08ce20008,
	0x000021402,
	0x0a0c20002,
	0x08ca20010,
	0x000000027,
	0x000021603,
	0x0a0a20003,
	0x024a20004,
	0x090e4002a,
	0x024460001,
	0x0a0440000,
	0x000021602,
	0x0a0c20003,
	0x08fa2001c,
	0x000000027,
	0x024c60004,
	0x000c20823,
	0x08fa20000,
	0x000000027,
	0x000400008,
	0x023bd0014,
	0x02002004a,
	0x00043202a,
	0x01480011f,
	0x02003004c,
	0x00062202a,
	0x014800114,
	0x000000027,
	0x01062010d,
	0x010430102,
	0x000000027,
	0x020020046,
	0x00043202a,
	0x0148000c5,
	0x020030048,
	0x00062202a,
	0x0148000c1,
	0x000000027,
	0x01062008b,
	0x0104300af,
	0x000000027,
	0x020020043,
	0x01062005a,
	0x020030044,
	0x010430082,
	0x000000027,
	0x020020044,
	0x01062002d,
	0x020030045,
	0x01043005a,
	0x000000027,
	0x020020045,
	0x010620005,
	0x020030046,
	0x01043001f,
	0x000000027,
	0x020030047,
	0x010430005,
	0x000000027,
	0x08fa20000,
	0x023bd0014,
	0x000400008,
	0x000000825,
	0x084a30002,
	0x000000027,
	0x0a0c30000,
	0x084a30002,
	0x000000027,
	0x000031c00,
	0x000031c03,
	0x000031a03,
	0x0a0c30001,
	0x08ca2000c,
	0x024c60002,
	0x0a0c20000,
	0x08ca2000c,
	0x000000027,
	0x000021203,
	0x0a0c20001,
	0x08fa2001c,
	0x024c60002,
	0x000c20823,
	0x08fa20000,
	0x000000027,
	0x000400008,
	0x023bd0014,
	0x084a20002,
	0x000000027,
	0x0a0c20000,


@@ 3026,27 3155,83 @@ ulong bootcode[]={
	0x000021403,
	0x000021203,
	0x0a0c20001,
	0x08ca3000c,
	0x08ca30008,
	0x024c60002,
	0x0a0c30000,
	0x08ca30008,
	0x000000027,
	0x000031a03,
	0x0a0c30001,
	0x08ca30008,
	0x000000027,
	0x000031c03,
	0x0a0c30002,
	0x08ca30008,
	0x000000027,
	0x000031e03,
	0x0a0c30003,
	0x0a0c00004,
	0x0a0c00005,
	0x0a0c00006,
	0x0a0c00007,
	0x08ca2000c,
	0x024c60008,
	0x0a0c20000,
	0x08ca2000c,
	0x024c30002,
	0x000021203,
	0x0a0c20001,
	0x024620001,
	0x0afa20010,
	0x0afa20004,
	0x08ca20010,
	0x000000027,
	0x0afa20008,
	0x08ca3000c,
	0x024c20002,
	0x00c0018b1,
	0x0afa3000c,
	0x08fa20018,
	0x08fa30010,
	0x08c42000c,
	0x000000027,
	0x000623021,
	0x08fa2001c,
	0x000000027,
	0x000c20823,
	0x08fa20000,
	0x000000027,
	0x000400008,
	0x023bd0014,
	0x084a30002,
	0x000000027,
	0x0a0c30000,
	0x084a30002,
	0x000000027,
	0x000031c00,
	0x000031c03,
	0x000031a03,
	0x0a0c30001,
	0x024430001,
	0x0afa30010,
	0x0afa30004,
	0x08ca30010,
	0x000000027,
	0x0afa30008,
	0x08ca2000c,
	0x00c001838,
	0x0afa2000c,
	0x08fa30018,
	0x08fa20010,
	0x08c63000c,
	0x024c60002,
	0x0a0c20000,
	0x08ca2000c,
	0x024c30002,
	0x000021203,
	0x0a0c20001,
	0x024620001,
	0x0afa20010,
	0x0afa20004,
	0x08ca20010,
	0x000000027,
	0x0afa20008,
	0x08ca3000c,
	0x00c0018b1,
	0x0afa3000c,
	0x08fa20018,
	0x08fa30010,
	0x08c42000c,
	0x000000027,
	0x000433021,
	0x000623021,
	0x08fa2001c,
	0x000000027,
	0x000c20823,


@@ 3105,43 3290,26 @@ ulong bootcode[]={
	0x000031c03,
	0x000031a03,
	0x0a0c30001,
	0x08ca2000c,
	0x08fa2001c,
	0x024c60002,
	0x0a0c20000,
	0x08ca2000c,
	0x000000027,
	0x000021202,
	0x0a0c20001,
	0x08ca2000c,
	0x000000027,
	0x000021402,
	0x0a0c20002,
	0x08ca2000c,
	0x000c20823,
	0x08fa20000,
	0x000000027,
	0x000021602,
	0x0a0c20003,
	0x08ca30010,
	0x024c60004,
	0x0a0c30000,
	0x08ca30010,
	0x000400008,
	0x023bd0014,
	0x020030049,
	0x01043002b,
	0x000000027,
	0x000031a02,
	0x0a0c30001,
	0x08ca30010,
	0x02003004a,
	0x010430018,
	0x000000027,
	0x000031c02,
	0x0a0c30002,
	0x08ca30010,
	0x02003004b,
	0x010430005,
	0x000000027,
	0x000031e02,
	0x0a0c30003,
	0x08fa2001c,
	0x024c60004,
	0x000c20823,
	0x08fa20000,
	0x000000027,
	0x000400008,
	0x023bd0014,
	0x000400008,
	0x000000825,
	0x084a20002,
	0x000000027,
	0x0a0c20000,


@@ 3151,66 3319,13 @@ ulong bootcode[]={
	0x000021403,
	0x000021203,
	0x0a0c20001,
	0x08ca30008,
	0x024c60002,
	0x0a0c30000,
	0x08ca30008,
	0x000000027,
	0x000031a03,
	0x0a0c30001,
	0x08ca30008,
	0x000000027,
	0x000031c03,
	0x0a0c30002,
	0x08ca30008,
	0x000000027,
	0x000031e03,
	0x0a0c30003,
	0x0a0c00004,
	0x0a0c00005,
	0x0a0c00006,
	0x0a0c00007,
	0x08ca2000c,
	0x024c60008,
	0x0a0c20000,
	0x08ca2000c,
	0x024c30002,
	0x000021203,
	0x0a0c20001,
	0x024620001,
	0x0afa20010,
	0x0afa20004,
	0x08ca20010,
	0x000000027,
	0x0afa20008,
	0x08ca3000c,
	0x00c001838,
	0x0afa3000c,
	0x08fa20018,
	0x08fa30010,
	0x08c42000c,
	0x000000027,
	0x000623021,
	0x08fa2001c,
	0x000000027,
	0x024c60002,
	0x000c20823,
	0x08fa20000,
	0x000000027,
	0x000400008,
	0x023bd0014,
	0x020020047,
	0x01062002b,
	0x000000027,
	0x020020048,
	0x010620018,
	0x000000027,
	0x020020049,
	0x010620005,
	0x000000027,
	0x08fa20000,
	0x023bd0014,
	0x000400008,
	0x000000825,
	0x084a20002,
	0x000000027,
	0x0a0c20000,


@@ 3243,20 3358,13 @@ ulong bootcode[]={
	0x000000027,
	0x000400008,
	0x023bd0014,
	0x084a20002,
	0x000000027,
	0x0a0c20000,
	0x084a20002,
	0x084a30002,
	0x000000027,
	0x000021400,
	0x000021403,
	0x000021203,
	0x0a0c20001,
	0x08ca3000c,
	0x024c60002,
	0x0a0c30000,
	0x08ca3000c,
	0x084a30002,
	0x000000027,
	0x000031c00,
	0x000031c03,
	0x000031a03,
	0x0a0c30001,
	0x08fa2001c,


@@ 3266,6 3374,25 @@ ulong bootcode[]={
	0x000000027,
	0x000400008,
	0x023bd0014,
	0x020030050,
	0x00062202a,
	0x014800073,
	0x000000027,
	0x010430050,
	0x000000027,
	0x02003004d,
	0x010430033,
	0x000000027,
	0x02003004e,
	0x010430018,
	0x000000027,
	0x02003004f,
	0x010430005,
	0x000000027,
	0x08fa20000,
	0x023bd0014,
	0x000400008,
	0x000000825,
	0x084a20002,
	0x000000027,
	0x0a0c20000,


@@ 3282,25 3409,6 @@ ulong bootcode[]={
	0x000000027,
	0x000400008,
	0x023bd0014,
	0x02002004e,
	0x00043202a,
	0x014800060,
	0x000000027,
	0x010620046,
	0x000000027,
	0x02002004b,
	0x010620033,
	0x000000027,
	0x02002004c,
	0x010620020,
	0x000000027,
	0x02002004d,
	0x010620005,
	0x000000027,
	0x08fa20000,
	0x023bd0014,
	0x000400008,
	0x000000825,
	0x084a20002,
	0x024c30002,
	0x0a0c20000,


@@ 3315,7 3423,7 @@ ulong bootcode[]={
	0x024a30008,
	0x0afa30008,
	0x020020074,
	0x00c001838,
	0x00c0018b1,
	0x0afa2000c,
	0x08fa30010,
	0x08fa2001c,


@@ 3326,7 3434,7 @@ ulong bootcode[]={
	0x000400008,
	0x023bd0014,
	0x084a30002,
	0x000000027,
	0x024c20002,
	0x0a0c30000,
	0x084a30002,
	0x000000027,


@@ 3334,8 3442,18 @@ ulong bootcode[]={
	0x000031c03,
	0x000031a03,
	0x0a0c30001,
	0x0afa20010,
	0x0afa20004,
	0x024a20008,
	0x0afa20008,
	0x020030074,
	0x00c0018b1,
	0x0afa3000c,
	0x08fa20010,
	0x000000027,
	0x024460074,
	0x08fa2001c,
	0x024c60002,
	0x000000027,
	0x000c20823,
	0x08fa20000,
	0x000000027,


@@ 3350,94 3468,97 @@ ulong bootcode[]={
	0x000031c03,
	0x000031a03,
	0x0a0c30001,
	0x08fa2001c,
	0x084a2000c,
	0x024c60002,
	0x000c20823,
	0x08fa20000,
	0x000000027,
	0x000400008,
	0x023bd0014,
	0x084a20002,
	0x024c30002,
	0x0a0c20000,
	0x084a20002,
	0x000000027,
	0x084a2000c,
	0x024c30002,
	0x000021400,
	0x000021403,
	0x000021203,
	0x0a0c20001,
	0x0afa30010,
	0x0afa30004,
	0x024a30008,
	0x024a3000e,
	0x0afa30008,
	0x020020074,
	0x00c001838,
	0x02002001c,
	0x00c0018b1,
	0x0afa2000c,
	0x08fa30010,
	0x08fa2001c,
	0x024660074,
	0x02466001c,
	0x000c20823,
	0x08fa20000,
	0x000000027,
	0x000400008,
	0x023bd0014,
	0x02002004f,
	0x01062002c,
	0x020030051,
	0x01043fd98,
	0x000000027,
	0x020020050,
	0x010620008,
	0x020030052,
	0x010430020,
	0x000000027,
	0x020020051,
	0x01062fe17,
	0x020030053,
	0x010430005,
	0x000000027,
	0x08fa20000,
	0x023bd0014,
	0x000400008,
	0x000000825,
	0x084a30002,
	0x000000027,
	0x0a0c30000,
	0x084a30002,
	0x000000027,
	0x000031c00,
	0x000031c03,
	0x000031a03,
	0x0a0c30001,
	0x084a2000c,
	0x024c60002,
	0x0a0c20000,
	0x084a2000c,
	0x084a20002,
	0x024c30002,
	0x0a0c20000,
	0x084a20002,
	0x000000027,
	0x000021400,
	0x000021403,
	0x000021203,
	0x0a0c20001,
	0x0afa30010,
	0x0afa30004,
	0x024a3000e,
	0x024a30024,
	0x0afa30008,
	0x02002001c,
	0x00c001838,
	0x02002001e,
	0x00c0018b1,
	0x0afa2000c,
	0x08fa30010,
	0x08fa2001c,
	0x02466001c,
	0x02466001e,
	0x000c20823,
	0x08fa20000,
	0x000000027,
	0x000400008,
	0x023bd0014,
	0x084a30002,
	0x084a20002,
	0x024c30002,
	0x0a0c20000,
	0x084a20002,
	0x000000027,
	0x0a0c30000,
	0x084a30002,
	0x000021400,
	0x000021403,
	0x000021203,
	0x0a0c20001,
	0x0afa30010,
	0x0afa30004,
	0x024a30008,
	0x0afa30008,
	0x02002001c,
	0x00c0018b1,
	0x0afa2000c,
	0x08fa30010,
	0x020020024,
	0x02463001c,
	0x0afa30010,
	0x0afa30004,
	0x08fa30018,
	0x000000027,
	0x000031c00,
	0x000031c03,
	0x000031a03,
	0x0a0c30001,
	0x024630024,
	0x0afa30008,
	0x00c0018b1,
	0x0afa2000c,
	0x08fa30010,
	0x08fa2001c,
	0x024c60002,
	0x024660024,
	0x000c20823,
	0x08fa20000,
	0x000000027,


@@ 3446,7 3567,7 @@ ulong bootcode[]={
	0x023bdfff0,
	0x0afbf0000,
	0x03c020000,
	0x0344251e0,
	0x0344253c4,
	0x0afc2810e,
	0x020030001,
	0x0a3c3876d,


@@ 3461,7 3582,7 @@ ulong bootcode[]={
	0x020020001,
	0x0a3c287b7,
	0x03c030000,
	0x034634b4c,
	0x034634d30,
	0x0afc38112,
	0x020020002,
	0x0a3c287a6,


@@ 3472,7 3593,7 @@ ulong bootcode[]={
	0x020030002,
	0x0a3c3879a,
	0x03c020000,
	0x034425294,
	0x034425478,
	0x0afc28116,
	0x020030003,
	0x0a3c387a7,


@@ 3485,17 3606,17 @@ ulong bootcode[]={
	0x020030003,
	0x0a3c38789,
	0x03c020000,
	0x034425118,
	0x0344252fc,
	0x0afc2811a,
	0x020030004,
	0x0a3c387a5,
	0x03c020000,
	0x034425160,
	0x034425344,
	0x0afc2811e,
	0x020030005,
	0x0a3c387b5,
	0x03c020000,
	0x0344251b0,
	0x034425394,
	0x0afc28122,
	0x020030006,
	0x0a3c38767,


@@ 3506,7 3627,7 @@ ulong bootcode[]={
	0x020020001,
	0x0afa20008,
	0x020030080,
	0x00c0018a6,
	0x00c00191f,
	0x0afa3000c,
	0x0a3c087c2,
	0x0a3c087cb,


@@ 3522,7 3643,7 @@ ulong bootcode[]={
	0x000000027,
	0x014c00005,
	0x000000027,
	0x00c001174,
	0x00c0011ed,
	0x000000027,
	0x08fc680c6,
	0x000000027,


@@ 3638,7 3759,7 @@ ulong bootcode[]={
	0x02002000a,
	0x014a20003,
	0x0254a0001,
	0x0080011fd,
	0x008001276,
	0x000005025,
	0x020020009,
	0x014a2ffc2,


@@ 3646,7 3767,7 @@ ulong bootcode[]={
	0x025430007,
	0x0201cfff8,
	0x0007c5024,
	0x0080011fd,
	0x008001276,
	0x000000027,
	0x02008fc18,
	0x0200dfc18,


@@ 3660,7 3781,7 @@ ulong bootcode[]={
	0x000052e03,
	0x014a00003,
	0x000000027,
	0x0080011fd,
	0x008001276,
	0x024c6ffff,
	0x02002002e,
	0x014a20007,


@@ 3669,7 3790,7 @@ ulong bootcode[]={
	0x015020002,
	0x000000027,
	0x000004025,
	0x008001244,
	0x0080012bd,
	0x000006825,
	0x028a20031,
	0x014400025,


@@ 3691,11 3812,11 @@ ulong bootcode[]={
	0x000000027,
	0x014a0ffe4,
	0x000094025,
	0x0080011fd,
	0x008001276,
	0x024c6ffff,
	0x014a0ffe0,
	0x000096825,
	0x0080011fd,
	0x008001276,
	0x024c6ffff,
	0x02002000a,
	0x001220018,


@@ 3708,7 3829,7 @@ ulong bootcode[]={
	0x000000027,
	0x000052e00,
	0x000052e03,
	0x008001260,
	0x0080012d9,
	0x02469ffd0,
	0x020030030,
	0x014a30006,


@@ 3716,7 3837,7 @@ ulong bootcode[]={
	0x02003fc18,
	0x011030003,
	0x000000027,
	0x00800125f,
	0x0080012d8,
	0x000000027,
	0x02002002a,
	0x014a20009,


@@ 3725,9 3846,9 @@ ulong bootcode[]={
	0x02002fc18,
	0x015020003,
	0x0256b0004,
	0x008001244,
	0x0080012bd,
	0x000054025,
	0x008001244,
	0x0080012bd,
	0x000056825,
	0x030a5007f,
	0x0afab0044,


@@ 3762,13 3883,13 @@ ulong bootcode[]={
	0x023ce87c2,
	0x08fa40028,
	0x000011023,
	0x008001244,
	0x0080012bd,
	0x000826025,
	0x0080011fd,
	0x008001276,
	0x001615821,
	0x000e51021,
	0x024a50001,
	0x008001200,
	0x008001279,
	0x0a0480000,
	0x023bdfff0,
	0x0afbf0000,


@@ 3786,13 3907,13 @@ ulong bootcode[]={
	0x0afa30004,
	0x0afa40008,
	0x08fa3001c,
	0x00c0013ae,
	0x00c001427,
	0x0afa3000c,
	0x08fa20000,
	0x000000027,
	0x000400008,
	0x023bd0010,
	0x0080012c6,
	0x00800133f,
	0x000042023,
	0x023bdffa8,
	0x0afbf0000,


@@ 3885,7 4006,7 @@ ulong bootcode[]={
	0x02002fc18,
	0x0afa30008,
	0x0afa2000c,
	0x00c0012bb,
	0x00c001334,
	0x0afa70010,
	0x08fa10028,
	0x08fa20000,


@@ 3904,12 4025,12 @@ ulong bootcode[]={
	0x024a5ffff,
	0x001651021,
	0x020040030,
	0x008001322,
	0x00800139b,
	0x0a0440000,
	0x024a5ffff,
	0x001651021,
	0x020040078,
	0x00800133e,
	0x0080013b7,
	0x0a0440000,
	0x030e30040,
	0x01060001e,


@@ 3931,27 4052,27 @@ ulong bootcode[]={
	0x000000027,
	0x01d200003,
	0x000000027,
	0x008001313,
	0x00800138c,
	0x000000027,
	0x01d000003,
	0x000000027,
	0x008001313,
	0x00800138c,
	0x000000027,
	0x030e20040,
	0x01440ffa0,
	0x024a5ffff,
	0x0010a001b,
	0x008001308,
	0x008001381,
	0x000003010,
	0x0010a001b,
	0x00800134f,
	0x0080013c8,
	0x000004012,
	0x0200d0001,
	0x008001300,
	0x008001379,
	0x000084023,
	0x08ca80000,
	0x020030004,
	0x0080012fb,
	0x008001374,
	0x0afa30028,
	0x08ca20000,
	0x000000027,


@@ 3963,15 4084,15 @@ ulong bootcode[]={
	0x000031c03,
	0x020020004,
	0x0afa20028,
	0x0080012fb,
	0x008001374,
	0x000034025,
	0x08ca80000,
	0x020030004,
	0x0080012fb,
	0x008001374,
	0x0afa30028,
	0x08ca80000,
	0x020030004,
	0x0080012fb,
	0x008001374,
	0x0afa30028,
	0x020030030,
	0x01043000a,


@@ 3979,11 4100,11 @@ ulong bootcode[]={
	0x020030048,
	0x010430003,
	0x000000027,
	0x0080012f8,
	0x008001371,
	0x000000027,
	0x08ca90000,
	0x020030004,
	0x0080012fb,
	0x008001374,
	0x0afa30028,
	0x08ca30000,
	0x000000027,


@@ 3993,14 4114,14 @@ ulong bootcode[]={
	0x03042ffff,
	0x020030004,
	0x0afa30028,
	0x0080012fb,
	0x008001374,
	0x000024025,
	0x0080012e8,
	0x008001361,
	0x0200a000a,
	0x0200e0001,
	0x0080012e8,
	0x008001361,
	0x0200a0010,
	0x0080012e8,
	0x008001361,
	0x0200a0008,
	0x020030075,
	0x011430006,


@@ 4008,10 4129,10 @@ ulong bootcode[]={
	0x020030078,
	0x01143fff7,
	0x000000027,
	0x0080012e8,
	0x008001361,
	0x000000027,
	0x0200a000a,
	0x0080012e8,
	0x008001361,
	0x034e70020,
	0x023bdfff0,
	0x0afbf0000,


@@ 4041,7 4162,7 @@ ulong bootcode[]={
	0x000000027,
	0x01ce00003,
	0x000000027,
	0x0080013be,
	0x008001437,
	0x000000027,
	0x000c9202b,
	0x010800005,


@@ 4059,7 4180,7 @@ ulong bootcode[]={
	0x02003fc18,
	0x010e3ffe3,
	0x000000027,
	0x0080013be,
	0x008001437,
	0x024e7ffff,
	0x020020009,
	0x01562fff9,


@@ 4070,7 4191,7 @@ ulong bootcode[]={
	0x02003fc18,
	0x010e3ffd8,
	0x0afc880f2,
	0x0080013be,
	0x008001437,
	0x024e7ffff,
	0x02002fc18,
	0x011420003,


@@ 4095,7 4216,7 @@ ulong bootcode[]={
	0x0a0640000,
	0x025080001,
	0x024a50001,
	0x0080013f3,
	0x00800146c,
	0x0afc880f2,
	0x000aa202a,
	0x01080ffba,


@@ 4110,7 4231,7 @@ ulong bootcode[]={
	0x0a0440000,
	0x025080001,
	0x024a50001,
	0x008001402,
	0x00800147b,
	0x0afc880f2,
	0x023bdffe4,
	0x0afbf0000,


@@ 4118,7 4239,7 @@ ulong bootcode[]={
	0x000000027,
	0x01440001f,
	0x000000027,
	0x00c001174,
	0x00c0011ed,
	0x000000027,
	0x08fa40030,
	0x08fa30020,


@@ 4159,7 4280,7 @@ ulong bootcode[]={
	0x0afa30004,
	0x0afa00008,
	0x02002fc18,
	0x00c0013ae,
	0x00c001427,
	0x0afa2000c,
	0x08fa20000,
	0x023bd001c,


@@ 4177,7 4298,7 @@ ulong bootcode[]={
	0x08fa3001c,
	0x02002fc18,
	0x0afa30008,
	0x00c0013ae,
	0x00c001427,
	0x0afa2000c,
	0x08fa20000,
	0x023bd0014,


@@ 4197,7 4318,7 @@ ulong bootcode[]={
	0x000000027,
	0x0afa3000c,
	0x08fa20024,
	0x00c0012bb,
	0x00c001334,
	0x0afa20010,
	0x08fa20000,
	0x023bd0014,


@@ 4271,7 4392,7 @@ ulong bootcode[]={
	0x0e7a6004c,
	0x0e7a70004,
	0x0e7a60008,
	0x00c0018e2,
	0x00c00195b,
	0x000000027,
	0x01020000e,
	0x000000027,


@@ 4282,7 4403,7 @@ ulong bootcode[]={
	0x0afa30008,
	0x0afa2000c,
	0x08fa300b0,
	0x00c0012bb,
	0x00c001334,
	0x0afa30010,
	0x08fa20000,
	0x023bd00a0,


@@ 4293,7 4414,7 @@ ulong bootcode[]={
	0x020030001,
	0x0e7a10004,
	0x0e7a00008,
	0x00c001912,
	0x00c00198b,
	0x0afa3000c,
	0x01020000e,
	0x000000027,


@@ 4304,7 4425,7 @@ ulong bootcode[]={
	0x0afa30008,
	0x0afa2000c,
	0x08fa300b0,
	0x00c0012bb,
	0x00c001334,
	0x0afa30010,
	0x08fa20000,
	0x023bd00a0,


@@ 4315,7 4436,7 @@ ulong bootcode[]={
	0x02003ffff,
	0x0e7a10004,
	0x0e7a00008,
	0x00c001912,
	0x00c00198b,
	0x0afa3000c,
	0x08fad00b4,
	0x08fac00ac,


@@ 4329,7 4450,7 @@ ulong bootcode[]={
	0x0afa30008,
	0x0afa2000c,
	0x08fa300b0,
	0x00c0012bb,
	0x00c001334,
	0x0afa30010,
	0x08fa20000,
	0x023bd00a0,


@@ 4373,7 4494,7 @@ ulong bootcode[]={
	0x023a20034,
	0x0e7a10004,
	0x0e7a00008,
	0x00c0017b1,
	0x00c00182a,
	0x0afa2000c,
	0x08fa20034,
	0x04444f800,


@@ 4397,7 4518,7 @@ ulong bootcode[]={
	0x000023043,
	0x0afa60030,
	0x000061023,
	0x00c00175c,
	0x00c0017d5,
	0x0afa20004,
	0x0c7a30048,
	0x0c7a2004c,


@@ 4409,7 4530,7 @@ ulong bootcode[]={
	0x08fa30034,
	0x000000027,
	0x000431023,
	0x00c00175c,
	0x00c0017d5,
	0x0afa20004,
	0x08fad00b4,
	0x023ae0078,


@@ 4432,7 4553,7 @@ ulong bootcode[]={
	0x08fa30034,
	0x000000027,
	0x000431023,
	0x00c00175c,
	0x00c0017d5,
	0x0afa20004,
	0x08fad00b4,
	0x08fac00ac,


@@ 4441,7 4562,7 @@ ulong bootcode[]={
	0x0c7a2003c,
	0x000000027,
	0x046201182,
	0x008001545,
	0x0080015be,
	0x023ae0078,
	0x0c7c180f6,
	0x0c7c080fa,


@@ 4458,7 4579,7 @@ ulong bootcode[]={
	0x08fa30034,
	0x000000027,
	0x000431023,
	0x00c00175c,
	0x00c0017d5,
	0x0afa20004,
	0x08fad00b4,
	0x08fac00ac,


@@ 4467,7 4588,7 @@ ulong bootcode[]={
	0x0c7a2003c,
	0x000000027,
	0x046201182,
	0x00800155c,
	0x0080015d5,
	0x023ae0078,
	0x02003fc18,
	0x015830002,


@@ 4502,7 4623,7 @@ ulong bootcode[]={
	0x0200cffff,
	0x0afac00ac,
	0x0200d0065,
	0x008001509,
	0x008001582,
	0x0afad00b4,
	0x0c7a70048,
	0x0c7a6004c,


@@ 4516,7 4637,7 @@ ulong bootcode[]={
	0x08fa30034,
	0x02002ffff,
	0x000431023,
	0x00c00175c,
	0x00c0017d5,
	0x0afa20004,
	0x08fad00b4,
	0x023ae0078,


@@ 4538,7 4659,7 @@ ulong bootcode[]={
	0x000671823,
	0x004600134,
	0x0afa7002c,
	0x00c00175c,
	0x00c0017d5,
	0x0afa30004,
	0x0c7a30040,
	0x0c7a20044,


@@ 4547,7 4668,7 @@ ulong bootcode[]={
	0x046201083,
	0x0e7a30004,
	0x0e7a20008,
	0x00c00171a,
	0x00c001793,
	0x000000027,
	0x08fad00b4,
	0x023ae0078,


@@ 4605,7 4726,7 @@ ulong bootcode[]={
	0x024e70001,
	0x02484fff6,
	0x0a0440001,
	0x0080015ec,
	0x008001665,
	0x024c6ffff,
	0x010e00007,
	0x0200b0001,


@@ 4673,7 4794,7 @@ ulong bootcode[]={
	0x020030030,
	0x0a0430000,
	0x024e7ffff,
	0x008001633,
	0x0080016ac,
	0x024c60001,
	0x019000013,
	0x000000027,


@@ 4693,7 4814,7 @@ ulong bootcode[]={
	0x0256b0001,
	0x0a0430000,
	0x02508ffff,
	0x008001644,
	0x0080016bd,
	0x024c60001,
	0x08fa300b0,
	0x000000027,


@@ 4722,7 4843,7 @@ ulong bootcode[]={
	0x0afa30008,
	0x0afa2000c,
	0x08fa300b0,
	0x00c0012bb,
	0x00c001334,
	0x0afa30010,
	0x08fa20000,
	0x023bd00a0,


@@ 4778,19 4899,19 @@ ulong bootcode[]={
	0x000001810,
	0x024630030,
	0x0a0430000,
	0x00800166b,
	0x0080016e4,
	0x024c60001,
	0x000061825,
	0x001231021,
	0x02003002b,
	0x0a0430000,
	0x00800168c,
	0x008001705,
	0x024c60001,
	0x000061025,
	0x001221821,
	0x020020065,
	0x0a0620000,
	0x008001682,
	0x0080016fb,
	0x024c60001,
	0x020030067,
	0x011a30006,


@@ 4798,7 4919,7 @@ ulong bootcode[]={
	0x020030068,
	0x011a30003,
	0x000000027,
	0x008001665,
	0x0080016de,
	0x000000027,
	0x024c7ffff,
	0x004e00006,


@@ 4818,11 4939,11 @@ ulong bootcode[]={
	0x000000027,
	0x01107ff93,
	0x000073025,
	0x008001665,
	0x0080016de,
	0x024c60001,
	0x0080016ca,
	0x008001743,
	0x02508ffff,
	0x0080016c2,
	0x00800173b,
	0x024e7ffff,
	0x08fa30034,
	0x02002ffff,


@@ 4832,7 4953,7 @@ ulong bootcode[]={
	0x000003825,
	0x08fa30034,
	0x0200d0068,
	0x008001620,
	0x008001699,
	0x001835023,
	0x08fa200b0,
	0x000000027,


@@ 4843,7 4964,7 @@ ulong bootcode[]={
	0x001221821,
	0x02002002b,
	0x0a0620000,
	0x008001611,
	0x00800168a,
	0x024c60001,
	0x0c7c180f6,
	0x0c7c080fa,


@@ 4853,7 4974,7 @@ ulong bootcode[]={
	0x0e7a60044,
	0x0e7a70004,
	0x0e7a60008,
	0x00c00171a,
	0x00c001793,
	0x000000027,
	0x08fad00b4,
	0x023ae0078,


@@ 4880,14 5001,14 @@ ulong bootcode[]={
	0x046222181,
	0x0e7a70040,
	0x0e7a60044,
	0x0080015e3,
	0x00800165c,
	0x000000027,
	0x00800157f,
	0x0080015f8,
	0x0258cffff,
	0x020020001,
	0x0afa20014,
	0x025ad0020,
	0x008001509,
	0x008001582,
	0x0afad00b4,
	0x023bdffe8,
	0x0afbf0000,


@@ 4904,7 5025,7 @@ ulong bootcode[]={
	0x04624c081,
	0x0e7a30004,
	0x0e7a20008,
	0x00c0017ff,
	0x00c001878,
	0x0afa2000c,
	0x04620c032,
	0x000000027,


@@ 4933,7 5054,7 @@ ulong bootcode[]={
	0x023a2001c,
	0x0e7a30004,
	0x0e7a20008,
	0x00c0017ff,
	0x00c001878,
	0x0afa2000c,
	0x0c7a1001c,
	0x0c7a00020,


@@ 4949,7 5070,7 @@ ulong bootcode[]={
	0x04624c081,
	0x0e7a30004,
	0x0e7a20008,
	0x00c00171a,
	0x00c001793,
	0x000000027,
	0x08fa20000,
	0x023bd000c,


@@ 4962,7 5083,7 @@ ulong bootcode[]={
	0x004810008,
	0x000000027,
	0x000041023,
	0x00c00175c,
	0x00c0017d5,
	0x0afa20004,
	0x08fa20000,
	0x023bd0014,


@@ 4983,12 5104,12 @@ ulong bootcode[]={
	0x000042843,
	0x0afa50010,
	0x000851823,
	0x00c00175c,
	0x00c0017d5,
	0x0afa30004,
	0x0e7a10008,
	0x0e7a0000c,
	0x08fa20010,
	0x00c00175c,
	0x00c0017d5,
	0x0afa20004,
	0x0c7a30008,
	0x0c7a2000c,


@@ 5173,7 5294,7 @@ ulong bootcode[]={
	0x08fa4000c,
	0x000000027,
	0x000821024,
	0x008001820,
	0x008001899,
	0x0afa2000c,
	0x08fa3000c,
	0x08fa40004,


@@ 5283,7 5404,7 @@ ulong bootcode[]={
	0x000000027,
	0x0a0c8ffff,
	0x024c6ffff,
	0x00800189e,
	0x008001917,
	0x024e7ffff,
	0x023bdfff0,
	0x08fa3001c,


@@ 5364,7 5485,7 @@ ulong bootcode[]={
	0x000000825,
	0x0e7a50004,
	0x0e7a40008,
	0x00c001912,
	0x00c00198b,
	0x0afa0000c,
	0x014200005,
	0x000000027,


@@ 5436,7 5557,6 @@ ulong bootcode[]={
	0x000000825,
	0x000000000,
	0x000000000,
	0x000000000,
	0x07072696e,
	0x074206572,
	0x0726f7273,


@@ 5501,7 5621,7 @@ ulong bootcode[]={
	0x000000000,
	0x0001fffff,
	0x07fffffff,
	0x000005044,
	0x000005228,
	0x000000000,
	0x000000000,
	0x000000000,


@@ 5899,8 6019,8 @@ ulong bootcode[]={
	0x073652072,
	0x065626f6f,
	0x074000000,
	0x00005c30,
	0x00005e10,
	0x0,
	0x00005c30,
	0x00005e10,
	0x0,
};

M power/devrtc.c => power/devrtc.c +192 -109
@@ 9,9 9,25 @@
#include	"io.h"

typedef struct Rtc	Rtc;
typedef struct Nvram	Nvram;

enum {
	Nbcd = 8	/* number of bcd bytes in the clock */
/*
 * length of nvram is 2048
 * the last addresses are reserved by convention for
 * a checksum and setting the real time clock
 */
enum{
	NVLEN	= 2046,
	NVCKSUM = 2046,
	NVRTC	= 2047,
	Nbcd = 8,	/* number of bcd bytes in the clock */
	Qrtc = 1,
	Qnvram,
};

struct Nvram{
	uchar	val;
	uchar	pad[7];
};

struct Rtc


@@ 24,52 40,25 @@ struct Rtc
	int	year;
};

QLock rtclock;	/* mutex on clock operations */
QLock	rtclock;		/* mutex on nvram operations */

#define	NRTC	1
static Dirtab rtcdir[]={
	"rtc",		{1, 0},	0,	0600,
	"rtc",		{Qrtc, 0},	0,	0644,
/*	"nvram",	{Qnvram, 0},	0,	0644,/**/
};
#define	NRTC	(sizeof(rtcdir)/sizeof(rtcdir[0]))

static uchar pattern[] =
{
	0xc5, 0x3a, 0xa3, 0x5c, 0xc5, 0x3a, 0xa3, 0x5c
};

ulong rtc2sec(Rtc*);
void sec2rtc(ulong, Rtc*);
int *yrsize(int);

/*
 *  issue pattern recognition bits to nv ram to address the
 *  real time clock
 */
rtcpattern(void)
{
	uchar *nv;
	uchar ch;
	int i, j;

	nv = RTC;

	/*
	 *  read the pattern sequence pointer to reset it
	 */
	ch = *nv;
	USED(ch);

	/*
	 *  stuff the pattern recognition codes one bit at
	 *  a time into *nv.
	 */
	for(i = 0; i < Nbcd; i++){
		ch = pattern[i];
		for (j = 0; j < 8; j++){
			*nv = ch & 0x1;
			ch >>= 1;
		}
	}
}
ulong	rtc2sec(Rtc*);
void	sec2rtc(ulong, Rtc*);
int	*yrsize(int);
void	setrtc(Rtc*);
long	rtctime(void);
void	nvcksum(void);

void
rtcreset(void)


@@ 126,6 115,159 @@ rtcclose(Chan *c)
{
}

long	 
rtcread(Chan *c, void *buf, long n, ulong offset)
{
	Nvram *nv;
	char *p;
	ulong t, ot;
	int i;

	if(c->qid.path & CHDIR)
		return devdirread(c, buf, n, rtcdir, NRTC, devgen);

	switch(c->qid.path){
	case Qrtc:
		qlock(&rtclock);
		t = rtctime();
		do{
			ot = t;
			t = rtctime();	/* make sure there's no skew */
		}while(t != ot);
		qunlock(&rtclock);
		n = readnum(offset, buf, n, t, 12);
		return n;
	case Qnvram:
		if(offset > NVLEN)
			return 0;
		if(n > NVLEN - offset)
			n = NVLEN - offset;
		nv = (Nvram *)NVRAM;
		p = buf;
		qlock(&rtclock);
		for(i = 0; i < n; i++)
			p[i] = nv[i+offset].val;
		qunlock(&rtclock);
		return n;
	}
	error(Egreg);
}

long	 
rtcwrite(Chan *c, void *buf, long n, ulong offset)
{
	Nvram *nv;
	Rtc rtc;
	ulong secs;
	char *cp, *ep;
	int i;

	switch(c->qid.path){
	case Qrtc:
		if(offset!=0)
			error(Ebadarg);
		/*
		 *  read the time
		 */
		cp = ep = buf;
		ep += n;
		while(cp < ep){
			if(*cp>='0' && *cp<='9')
				break;
			cp++;
		}
		secs = strtoul(cp, 0, 0);
		/*
		 *  convert to bcd
		 */
		sec2rtc(secs, &rtc);
		/*
		 * write it
		 */
		qlock(&rtclock);
		setrtc(&rtc);
		qunlock(&rtclock);
		return n;
	case Qnvram:
		if(offset > NVLEN)
			return 0;
		if(n > NVLEN - offset)
			n = NVLEN - offset;
		nv = (Nvram *)NVRAM;
		qlock(&rtclock);
		for(i = 0; i < n; i++)
			nv[i+offset].val = ((char*)buf)[i];
		nvcksum();
		qunlock(&rtclock);
		return n;
	}
	error(Egreg);
}

void	 
rtcremove(Chan *c)
{
	error(Eperm);
}

void	 
rtcwstat(Chan *c, char *dp)
{
	error(Eperm);
}

void
nvcksum(void)
{
	Nvram *nv;
	uchar cksum;
	int i;

	/*
	 * Seed the checksum so all-zeroes (all-ones) nvram doesn't have a zero
	 * (all-ones) checksum.
	 */
	cksum = 0xa5;
	nv = (Nvram *)NVRAM;
	for(i = 0; i < NVLEN; i++){
		cksum ^= nv[i].val;
		cksum = (cksum << 1) | ((cksum >> 7) & 1);
	}
	nv[NVCKSUM].val = cksum;
}

/*
 *  issue pattern recognition bits to nv ram to address the
 *  real time clock
 */
void
rtcpattern(void)
{
	uchar *nv;
	uchar ch;
	int i, j;

	nv = &((Nvram*)NVRAM)[NVRTC].val;

	/*
	 *  read the pattern sequence pointer to reset it
	 */
	ch = *nv;
	USED(ch);

	/*
	 *  stuff the pattern recognition codes one bit at
	 *  a time into *nv.
	 */
	for(i = 0; i < Nbcd; i++){
		ch = pattern[i];
		for (j = 0; j < 8; j++){
			*nv = ch & 0x1;
			ch >>= 1;
		}
	}
}

#define GETBCD(o) ((bcdclock[o]&0xf) + 10*(bcdclock[o]>>4))

long	 


@@ 138,7 280,7 @@ rtctime(void)
	char atime[64];
	Rtc rtc;

	nv = RTC;
	nv = &((Nvram*)NVRAM)[NVRTC].val;

	/*
	 *  set up the pattern for the clock


@@ 154,7 296,6 @@ rtctime(void)
			ch |= ((*nv & 0x1) << j);
		bcdclock[i] = ch;
	}
	qunlock(&rtclock);

	/*
	 *  see if the clock oscillator is on


@@ 182,76 323,33 @@ rtctime(void)
	return rtc2sec(&rtc);
}

long	 
rtcread(Chan *c, void *buf, long n, ulong offset)
{
	ulong t, ot;

	if(c->qid.path & CHDIR)
		return devdirread(c, buf, n, rtcdir, NRTC, devgen);

	qlock(&rtclock);
	t = rtctime();
	do{
		ot = t;
		t = rtctime();	/* make sure there's no skew */
	}while(t != ot);
	qunlock(&rtclock);
	n = readnum(offset, buf, n, t, 12);
	return n;

}

#define PUTBCD(n,o) bcdclock[o] = (n % 10) | (((n / 10) % 10)<<4)

long	 
rtcwrite(Chan *c, void *buf, long n, ulong offset)
void
setrtc(Rtc *rtc)
{
	Rtc rtc;
	ulong secs;
	int i,j;
	int i, j;
	uchar ch;
	uchar bcdclock[Nbcd];
	uchar *nv;
	char *cp, *ep;

	if(offset!=0)
		error(Ebadarg);

	/*
	 *  read the time
	 */
	cp = ep = buf;
	ep += n;
	while(cp < ep){
		if(*cp>='0' && *cp<='9')
			break;
		cp++;
	}
	secs = strtoul(cp, 0, 0);

	/*
	 *  convert to bcd
	 */
	sec2rtc(secs, &rtc);
	bcdclock[0] = bcdclock[4] = 0;
	PUTBCD(rtc.sec, 1);
	PUTBCD(rtc.min, 2);
	PUTBCD(rtc.hour, 3);
	PUTBCD(rtc.mday, 5);
	PUTBCD(rtc.mon, 6);
	PUTBCD(rtc.year, 7);
	PUTBCD(rtc->sec, 1);
	PUTBCD(rtc->min, 2);
	PUTBCD(rtc->hour, 3);
	PUTBCD(rtc->mday, 5);
	PUTBCD(rtc->mon, 6);
	PUTBCD(rtc->year, 7);

	/*
	 *  set up the pattern for the clock
	 */
	qlock(&rtclock);
	rtcpattern();

	/*
	 *  write the clock one bit at a time
	 */
	nv = RTC;
	nv = &((Nvram*)NVRAM)[NVRTC].val;
	for (i = 0; i < Nbcd; i++){
		ch = bcdclock[i];
		for (j = 0; j < 8; j++){


@@ 259,21 357,6 @@ rtcwrite(Chan *c, void *buf, long n, ulong offset)
			ch >>= 1;
		}
	}
	qunlock(&rtclock);

	return n;
}

void	 
rtcremove(Chan *c)
{
	error(Eperm);
}

void	 
rtcwstat(Chan *c, char *dp)
{
	error(Eperm);
}

#define SEC2MIN 60L