~kris/9p

9hist

1bc73021fc88971aa64b8581412de207a4c8ac14 — David du Colombier 24 years ago 84fb6f8
Plan 9 from Bell Labs 2001-11-22
12 files changed, 530 insertions(+), 112 deletions(-)

M alphapc/devfloppy.c
M alphapc/floppy.h
M ip/icmp.c
M mtx/dat.h
M mtx/fns.h
M mtx/l.s
M mtx/mem.h
A mtx/mmu.c
A mtx/random.c
M mtx/trap.c
M pc/devusb.c
M port/portdat.h
M alphapc/devfloppy.c => alphapc/devfloppy.c +88 -69
@@ 92,7 92,7 @@ FController	fl;
 *  predeclared
 */
static int	cmddone(void*);
static void	floppyformat(FDrive*, char*);
static void	floppyformat(FDrive*, Cmdbuf*);
static void	floppykproc(void*);
static void	floppypos(FDrive*,long);
static int	floppyrecal(FDrive*);


@@ 100,12 100,12 @@ static int	floppyresult(void);
static void	floppyrevive(void);
static long	floppyseek(FDrive*, long);
static int	floppysense(void);
static void	floppywait(void);
static void	floppywait(int);
static long	floppyxfer(FDrive*, int, void*, long, long);

Dirtab floppydir[]={
	".",		{Qdir, 0, QTDIR},	0,	0550,
	"fd0disk",		{Qdata + 0},	0,	0666,
	"fd0disk",		{Qdata + 0},	0,	0660,
	"fd0ctl",		{Qctl + 0},	0,	0660,
	"fd1disk",		{Qdata + 1},	0,	0660,
	"fd1ctl",		{Qctl + 1},	0,	0660,


@@ 116,6 116,22 @@ Dirtab floppydir[]={
};
#define NFDIR	2	/* directory entries/drive */

enum
{
	CMdebug,
	CMeject,
	CMformat,
	CMreset,
};

static Cmdtab floppyctlmsg[] =
{
	CMdebug,	"debug",	1,
	CMeject,	"eject",	1,
	CMformat,	"format",	0,
	CMreset,	"reset",	1,
};

static void
fldump(void)
{


@@ 147,6 163,8 @@ floppyreset(void)
	ulong maxtsize;
	
	floppysetup0(&fl);
	if(fl.ndrive == 0)
		return;

	/*
	 *  init dependent parameters


@@ 202,6 220,9 @@ floppyattach(char *spec)
{
	static int kstarted;

	if(fl.ndrive == 0)
		error(Enodev);

	if(kstarted == 0){
		/*
		 *  watchdog to turn off the motors


@@ 268,12 289,24 @@ changed(Chan *c, FDrive *dp)
		DPRINT("changed\n");
		fldump();
		dp->vers++;
		floppysetdef(dp);
		start = dp->t;
		dp->maxtries = 3;	/* limit it when we're probing */

		/* floppyon will fail if there's a controller but no drive */
		dp->confused = 1;	/* make floppyon recal */
		floppyon(dp);
		if(floppyon(dp) < 0)
			error(Eio);

		/* seek to the first track */
		floppyseek(dp, dp->t->heads*dp->t->tsize);
		while(waserror()){
			/*
			 *  if first attempt doesn't reset changed bit, there's
			 *  no floppy there
			 */
			if(inb(Pdir)&Fchange)
				nexterror();

			while(++dp->t){
				if(dp->t == &floppytype[nelem(floppytype)])
					dp->t = floppytype;


@@ 281,14 314,21 @@ changed(Chan *c, FDrive *dp)
					break;
			}
			floppydir[1+NFDIR*dp->dev].length = dp->t->cap;
			floppyon(dp);

			/* floppyon will fail if there's a controller but no drive */
			if(floppyon(dp) < 0)
				error(Eio);

			DPRINT("changed: trying %s\n", dp->t->name);
			fldump();
			if(dp->t == start)
				nexterror();
		}

		/* if the read succeeds, we've got the density right */
		floppyxfer(dp, Fread, dp->cache, 0, dp->t->tsize);
		poperror();
		dp->maxtries = 20;
	}

	old = c->qid.vers;


@@ 372,14 412,14 @@ floppyread(Chan *c, void *a, long n, vlong off)
	return rv;
}

#define SNCMP(a, b) strncmp(a, b, sizeof(b)-1)
static long
floppywrite(Chan *c, void *a, long n, vlong off)
{
	FDrive *dp;
	long rv, i;
	char *aa = a;
	char ctlmsg[64];
	Cmdbuf *cb;
	Cmdtab *ct;
	ulong offset = off;

	rv = 0;


@@ 409,28 449,36 @@ floppywrite(Chan *c, void *a, long n, vlong off)
		break;
	case Qctl:
		rv = n;
		cb = parsecmd(a, n);
		if(waserror()){
			free(cb);
			nexterror();
		}
		qlock(&fl);
		if(waserror()){
			qunlock(&fl);
			nexterror();
		}
		if(n >= sizeof(ctlmsg))
			n = sizeof(ctlmsg) - 1;
		memmove(ctlmsg, aa, n);
		ctlmsg[n] = 0;
		if(SNCMP(ctlmsg, "eject") == 0){
		ct = lookupcmd(cb, floppyctlmsg, nelem(floppyctlmsg));
		switch(ct->index){
		case CMeject:
			floppyeject(dp);
		} else if(SNCMP(ctlmsg, "reset") == 0){
			break;
		case CMformat:
			floppyformat(dp, cb);
			break;
		case CMreset:
			fl.confused = 1;
			floppyon(dp);
		} else if(SNCMP(ctlmsg, "format") == 0){
			floppyformat(dp, ctlmsg);
		} else if(SNCMP(ctlmsg, "debug") == 0){
			break;
		case CMdebug:
			floppydebug = 1;
		} else
			error(Ebadctl);
			break;
		}
		poperror();
		qunlock(&fl);
		poperror();
		free(cb);
		break;
	default:
		panic("floppywrite: bad qid");


@@ 463,7 511,7 @@ floppykproc(void *)
/*
 *  start a floppy drive's motor.
 */
static void
static int
floppyon(FDrive *dp)
{
	int alreadyon;


@@ 497,6 545,11 @@ floppyon(FDrive *dp)
				break;
	dp->lasttouched = m->ticks;
	fl.selected = dp;

	/* return -1 if this didn't work */
	if(dp->confused)
		return -1;
	return 0;
}

/*


@@ 635,9 688,9 @@ cmddone(void *)
 *  routine to try to clear any conditions.
 */
static void
floppywait(void)
floppywait(int slow)
{
	tsleep(&fl.r, cmddone, 0, 5000);
	tsleep(&fl.r, cmddone, 0, slow ? 5000 : 1000);
	if(!cmddone(0)){
		floppyintr(0);
		fl.confused = 1;


@@ 658,7 711,7 @@ floppyrecal(FDrive *dp)
	fl.cmd[fl.ncmd++] = dp->dev;
	if(floppycmd() < 0)
		return -1;
	floppywait();
	floppywait(1);
	if(fl.nstat < 2){
		DPRINT("recalibrate: confused %ux\n", inb(Pmsr));
		fl.confused = 1;


@@ 681,39 734,6 @@ floppyrecal(FDrive *dp)
	return 0;
}

static void
dumpreg(void)
{
	int i;

	fl.ncmd = 0;
	fl.cmd[fl.ncmd++] = Fdumpreg;
	if(floppycmd() < 0)
		return;
	floppywait();
	if(fl.nstat < 0){
		print("dumpreg bad %d\n", fl.nstat);
		fldump();
		return;
	}
	for(i = 0; i < fl.nstat; i++)
		print(" %2.2uX", fl.stat[i]);
	print("\n");
}

static void
specify(void)
{
	fl.ncmd = 0;
	fl.cmd[fl.ncmd++] = Fspec;
	fl.cmd[fl.ncmd++] = 0;
	fl.cmd[fl.ncmd++] = 1;
	if(floppycmd() < 0)
		return;
	floppywait();
	fldump();
}

/*
 *  if the controller or a specific drive is in a confused state,
 *  reset it and get back to a known state


@@ 741,7 761,7 @@ floppyrevive(void)
		spllo();
		fl.motor = 0;
		fl.confused = 0;
		floppywait();
		floppywait(0);

		/* mark all drives in an unknown state */
		for(dp = fl.d; dp < &fl.d[fl.ndrive]; dp++)


@@ 775,7 795,7 @@ floppyseek(FDrive *dp, long off)
	fl.cmd[fl.ncmd++] = dp->tcyl * dp->t->steps;
	if(floppycmd() < 0)
		return -1;
	floppywait();
	floppywait(1);
	if(fl.nstat < 2){
		DPRINT("seek: confused\n");
		fl.confused = 1;


@@ 804,16 824,13 @@ floppyxfer(FDrive *dp, int cmd, void *a, long off, long n)
		return 0;
	if(off + n > dp->t->cap)
		n = dp->t->cap - off;
if(cmd == Fread)
    memset(a, 0x55, n);

	/* retry on error (until it gets ridiculous) */
	tries = 0;
	while(waserror()){
		if(tries++ > 20)
		if(tries++ >= dp->maxtries)
			nexterror();
		DPRINT("floppyxfer: retrying\n");
		/*floppyon(dp);*/
	}

	dp->len = n;


@@ 856,7 873,7 @@ if(cmd == Fread)
	/*
	 *  give bus to DMA, floppyintr() will read result
	 */
	floppywait();
	floppywait(0);
	dmaend(DMAchan);
	poperror();



@@ 900,20 917,19 @@ if(cmd == Fread)
 *  format a track
 */
static void
floppyformat(FDrive *dp, char *params)
floppyformat(FDrive *dp, Cmdbuf *cb)
{
 	int cyl, h, sec;
	ulong track;
	uchar *buf, *bp;
	FType *t;
	char *f[3];

	/*
	 *  set the type
	 */
	if(tokenize(params, f, 3) > 1){
	if(cb->nf == 2){
		for(t = floppytype; t < &floppytype[nelem(floppytype)]; t++){
			if(strcmp(f[1], t->name)==0 && t->dt==dp->dt){
			if(strcmp(cb->f[1], t->name)==0 && t->dt==dp->dt){
				dp->t = t;
				floppydir[1+NFDIR*dp->dev].length = dp->t->cap;
				break;


@@ 921,9 937,12 @@ floppyformat(FDrive *dp, char *params)
		}
		if(t >= &floppytype[nelem(floppytype)])
			error(Ebadarg);
	} else {
	} else if(cb->nf == 1){
		floppysetdef(dp);
		t = dp->t;
	} else {
		cmderror(cb, "invalid floppy format command");
		SET(t);
	}

	/*


@@ 992,7 1011,7 @@ floppyformat(FDrive *dp, char *params)
		/*
		 *  give bus to DMA, floppyintr() will read result
		 */
		floppywait();
		floppywait(1);
		dmaend(DMAchan);
		poperror();


M alphapc/floppy.h => alphapc/floppy.h +2 -1
@@ 3,7 3,7 @@ typedef	struct FDrive FDrive;
typedef struct FType FType;

static void floppyintr(Ureg*);
static void floppyon(FDrive*);
static int floppyon(FDrive*);
static void floppyoff(FDrive*);
static void floppysetdef(FDrive*);



@@ 20,6 20,7 @@ struct FDrive
	int	cyl;		/* current arm position */
	int	confused;	/* needs to be recalibrated */
	int	vers;
	int	maxtries;	/* max read attempts before Eio */

	int	tcyl;		/* target cylinder */
	int	thead;		/* target head */

M ip/icmp.c => ip/icmp.c +2 -0
@@ 350,6 350,7 @@ icmpiput(Proto *icmp, Ipifc*, Block *bp)
		break;
	case Unreachable:
		code = p->code;
		x = 0;
		switch(code){
		default:
			msg = unreachcode[1];


@@ 401,6 402,7 @@ icmpiput(Proto *icmp, Ipifc*, Block *bp)
				(*pr->advise)(pr, bp, m2);
				return;
			}
			bp->rp -= ICMP_IPSIZE+ICMP_HDRSIZE;
		}

		goticmpkt(icmp, bp);

M mtx/dat.h => mtx/dat.h +4 -3
@@ 79,9 79,10 @@ struct Conf
/*
 *  mmu goo in the Proc structure
 */
#define NCOLOR 1
struct PMMU
{
int dummy;
	int	pidonmach[MAXMACH];
};

/*


@@ 219,8 220,8 @@ struct ISAConf {

extern PCArch	*arch;

#define	MACHP(n)	((Mach *)((int)&mach0+n*BY2PG))
extern Mach		mach0;
//#define	MACHP(n)	((Mach *)((int)&mach0+n*BY2PG))
//extern Mach		mach0;

extern register Mach	*m;
extern register Proc	*up;

M mtx/fns.h => mtx/fns.h +2 -1
@@ 61,6 61,7 @@ int	isaconfig(char*, int, ISAConf*);
void	kbdinit(void);
void	kbdreset(void);
void	kernelmmu(void);
#define	kmapinval()
void	links(void);
void	mathinit(void);
void	mmuinit(void);


@@ 98,7 99,7 @@ void	tlbflushall(void);
void	uartinstall(void);
void	uartwait(void);	/* debugging */
int unsac(uchar *dst, uchar *src, int n, int nsrc);
#define	userureg(ur) ((ur)->status & KUSER)
#define	userureg(ur) (((ur)->status & MSR_PR) != 0)
void	wbflush(void);

#define	waserror()	(up->nerrlab++, setlabel(&up->errlab[up->nerrlab-1]))

M mtx/l.s => mtx/l.s +0 -1
@@ 1,5 1,4 @@
#include	"mem.h"
#include	"mpc60x.h"

#define	BDNZ	BC	16,0,
#define	BDNE	BC	0,2,

M mtx/mem.h => mtx/mem.h +106 -14
@@ 1,5 1,3 @@
/* none of this is meant to be correct yet */

/*
 * Memory and machine-specific definitions.  Used in C and assembler.
 */


@@ 12,17 10,22 @@
#define	BI2WD		32			/* bits per word */
#define	BY2WD		4			/* bytes per word */
#define 	BY2V		8			/* bytes per vlong */
#define	BY2PG		8192		/* bytes per page */
#define	BY2PG		4096		/* bytes per page */
#define	WD2PG		(BY2PG/BY2WD)	/* words per page */
#define	PGSHIFT		13			/* log(BY2PG) */
#define	PGSHIFT		12			/* log(BY2PG) */
#define 	ROUND(s, sz)	(((s)+(sz-1))&~(sz-1))
#define 	PGROUND(s)	ROUND(s, BY2PG)
#define BLOCKALIGN	8
#define	CACHELINELOG	4
#define CACHELINESZ	(1<<CACHELINELOG)
#define BLOCKALIGN	CACHELINESZ

#define	MHz	1000000

#define	BY2PTE		8			/* bytes per pte entry */
#define	PTE2PG		(BY2PG/BY2PTE)	/* pte entries per page */
//#define	BY2PTE		8			/* bytes per pte entry */
//#define	PTE2PG		(BY2PG/BY2PTE)	/* pte entries per page */

#define	MAXMACH		1			/* max # cpus system can run */
#define	MACHSIZE	BY2PG
#define	KSTACK		4096			/* Size of kernel stack */

/*


@@ 31,8 34,51 @@
#define	HZ		100			/* clock frequency */
#define	MS2HZ	(1000/HZ)
#define	TK2SEC(t)	((t)/HZ)		/* ticks to seconds */
#define	TK2MS(t)	((t)*MS2HZ)		/* ticks to milliseconds */
#define	MS2TK(t)	(((t)*HZ+500)/1000)	/* milliseconds to closest tick */

/* Bit encodings for Machine State Register (MSR) */
#define MSR_POW		(1<<18)		/* Enable Power Management */
#define MSR_TGPR	(1<<17)		/* TLB Update registers in use */
#define MSR_ILE		(1<<16)		/* Interrupt Little-Endian enable */
#define MSR_EE		(1<<15)		/* External Interrupt enable */
#define MSR_PR		(1<<14)		/* Supervisor/User privelege */
#define MSR_FP		(1<<13)		/* Floating Point enable */
#define MSR_ME		(1<<12)		/* Machine Check enable */
#define MSR_FE0		(1<<11)		/* Floating Exception mode 0 */
#define MSR_SE		(1<<10)		/* Single Step */
#define MSR_BE		(1<<9)		/* Branch Trace */
#define MSR_FE1		(1<<8)		/* Floating Exception mode 1 */
#define MSR_IP		(1<<6)		/* Exception prefix 0x000/0xFFF */
#define MSR_IR		(1<<5)		/* Instruction MMU enable */
#define MSR_DR		(1<<4)		/* Data MMU enable */
#define MSR_RI		(1<<1)		/* Recoverable Exception */
#define MSR_LE		(1<<0)		/* Little-Endian enable */

#define MSR_		MSR_FP|MSR_FE0|MSR_FE1|MSR_ME

/*
 * Exception codes (trap vectors)
 */
#define	CRESET	0x01
#define	CMCHECK 0x02
#define	CDSI	0x03
#define	CISI	0x04
#define	CEI	0x05
#define	CALIGN	0x06
#define	CPROG	0x07
#define	CFPU	0x08
#define	CDEC	0x09
#define	CSYSCALL 0x0C
#define	CTRACE	0x0D
// #define	CFPA	0x0E
/* rest are power-implementation dependent */
#define	CIMISS	0x10
#define	CDLMISS	0x11
#define	CDSMISS	0x12
#define	CIBREAK	0x13
#define	CSMI	0x14

/*
 * Magic registers
 */


@@ 42,14 88,24 @@


/*
 *  virtual MMU
 */
#define PTEMAPMEM	(1024*1024)	
#define	PTEPERTAB	(PTEMAPMEM/BY2PG)
#define SEGMAPSIZE	1984
#define SSEGMAPSIZE	16
#define PPN(x)		((x)&~(BY2PG-1))

/*
 * Fundamental addresses
 */
#define	MACHADDR	(KTZERO-MAXMACH*MACHSIZE)
#define	MACHP(n)	((Mach *)(MACHADDR+(n)*MACHSIZE))

#define	UREGSIZE	((8+32)*4)

/*
 * MMU
 *
 */

/* L1 table entry and Mx_TWC flags */


@@ 64,18 120,36 @@
#define PTECI		(1<<1)	/*  cache inhibit */
#define PTESH		(1<<2)	/* page is shared; ASID ignored */
#define PTELPS		(1<<3)	/* large page size */
#define PTEWRITE	0x9F0
//#define PTEWRITE	0x9F0

#define	PTEKERNEL	(0<<2)
#define	PTEUSER		(1<<2)
#define PTESIZE		(1<<7)

#define	NTLBPID		16
#define	TLBPID(n)	((n)&(NTLBPID-1))

/* soft tlb */
#define	STLBLOG		12
#define	STLBSIZE	(1<<STLBLOG)

/*
 *  portable MMU bits for fault.c - though still machine specific
 */
//#define PTEVALID	(MMUPP|MMUV)
#define PTEWRITE	(2<<10)
#define	PTERONLY	(3<<10)
#define	PTEUNCACHED	(1<<4)

/*
 * physical MMU bits
 */

/* TLB and MxEPN flag */
#define	TLBVALID	(1<<9)

#define	TLBSETS	32	/* number of tlb sets (603/603e) */

#define	PTEMAPMEM	(1024*1024)	
#define	PTEPERTAB	(PTEMAPMEM/BY2PG)
#define	SEGMAPSIZE	512
#define SSEGMAPSIZE	16

/*
 * Address spaces
 */


@@ 99,3 173,21 @@
#define	FLASHAorB	0xfff00000

#define isphys(x) (((ulong)x&KZERO)!=0)

/*
 * standard 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	284	/* Time base Upper/Lower (Writing) */
#define TBWL	285
#define PVR	287	/* Processor Version */

A mtx/mmu.c => mtx/mmu.c +172 -0
@@ 0,0 1,172 @@
#include	"u.h"
#include	"../port/lib.h"
#include	"mem.h"
#include	"dat.h"
#include	"fns.h"
#include	"io.h"

#define TLBINVLAID	KZERO

void
mmuinit(void)
{
	int i;

	print("mmuinit\n");
	for(i=0; i<STLBSIZE; i++)
		m->stb[i].virt = TLBINVLAID;
}

void
flushmmu(void)
{
	int x;

if(0)print("flushmmu(%ld)\n", up->pid);
	x = splhi();
	up->newtlb = 1;
	mmuswitch(up);
	splx(x);
}

/*
 * called with splhi
 */
void
mmuswitch(Proc *p)
{
	int tp;

if(0)print("mmuswitch()\n");
	if(p->newtlb) {
		memset(p->pidonmach, 0, sizeof p->pidonmach);
		p->newtlb = 0;
	}
	tp = p->pidonmach[m->machno];
	putcasid(tp);
}

void
mmurelease(Proc* p)
{
if(0)print("mmurelease(%ld)\n", p->pid);
	memset(p->pidonmach, 0, sizeof p->pidonmach);
}

void
purgetlb(int pid)
{
	int i, mno;
	Proc *sp, **pidproc;
	Softtlb *entry, *etab;

if(0)print("purgetlb: pid = %d\n", pid);
	m->tlbpurge++;
	/*
	 * find all pid entries that are no longer used by processes
	 */
	mno = m->machno;
	pidproc = m->pidproc;
	for(i=1; i<NTLBPID; i++) {
		sp = pidproc[i];
		if(sp && sp->pidonmach[mno] != i)
			pidproc[i] = 0;
	}

	/*
	 * shoot down the one we want
	 */
	sp = pidproc[pid];
	if(sp != 0)
		sp->pidonmach[mno] = 0;
	pidproc[pid] = 0;

	/*
	 * clean out all dead pids from the stlb;
	 */
	entry = m->stb;
	for(etab = &entry[STLBSIZE]; entry < etab; entry++)
		if(pidproc[TLBPID(entry->virt)] == 0)
			entry->virt = TLBINVLAID;

	/*
	 * clean up the hardware
	 */
	tlbflushall();
}

int
newtlbpid(Proc *p)
{
	int i, s;
	Proc **h;

	i = m->lastpid;
	h = m->pidproc;
	for(s = 0; s < NTLBPID; s++) {
		i++;
		if(i >= NTLBPID)
			i = 1;
		if(h[i] == 0)
			break;
	}

	if(h[i]) {
		i = m->purgepid+1;
		if(i >= NTLBPID)
			i = 1;
		 m->purgepid = i;
		purgetlb(i);
	}

	if(h[i] != 0)
		panic("newtlb");

	m->pidproc[i] = p;
	p->pidonmach[m->machno] = i;
	m->lastpid = i;
if(0)print("newtlbpid: pid=%ld = tlbpid = %d\n", p->pid, i);
	return i;
}

void
putmmu(ulong va, ulong pa, Page *pg)
{
	char *ctl;
	int tp;
	ulong h;

	qlock(&m->stlblk);

	tp = up->pidonmach[m->machno];
	if(tp == 0) {
		tp = newtlbpid(up);
		putcasid(tp);
	}

	h = ((va>>12)^(va>>24)^(tp<<8)) & 0xfff;
	m->stb[h].virt = va|tp;
	m->stb[h].phys = pa;
	tlbflush(va);

	qunlock(&m->stlblk);

	ctl = &pg->cachectl[m->machno];
if(0)print("putmmu tp=%d h=%ld va=%lux pa=%lux ctl=%x\n", tp, h,va, pa, *ctl);
	switch(*ctl) {
	default:
		panic("putmmu: %d\n", *ctl);
		break;
	case PG_NOFLUSH:
		break;
	case PG_TXTFLUSH:
		dcflush((void*)pg->va, BY2PG);
		icflush((void*)pg->va, BY2PG);
		*ctl = PG_NOFLUSH;
		break;
	case PG_NEWCOL:
print("PG_NEWCOL!!\n");
		*ctl = PG_NOFLUSH;
		break;
	}
}

A mtx/random.c => mtx/random.c +138 -0
@@ 0,0 1,138 @@
#include	"u.h"
#include	"../port/lib.h"
#include	"mem.h"
#include	"dat.h"
#include	"fns.h"
#include	"../port/error.h"


struct Rb
{
	QLock;
	Rendez	producer;
	Rendez	consumer;
	ulong	randomcount;
	uchar	buf[1024];
	uchar	*ep;
	uchar	*rp;
	uchar	*wp;
	uchar	next;
	uchar	wakeme;
	ushort	bits;
	ulong	randn;
} rb;

static int
rbnotfull(void*)
{
	int i;

	i = rb.rp - rb.wp;
	return i != 1 && i != (1 - sizeof(rb.buf));
}

static int
rbnotempty(void*)
{
	return rb.wp != rb.rp;
}

static void
genrandom(void*)
{
	up->basepri = PriNormal;
	up->priority = up->basepri;

	for(;;){
		for(;;)
			if(++rb.randomcount > 100000)
				break;
		if(anyhigher())
			sched();
		if(!rbnotfull(0))
			sleep(&rb.producer, rbnotfull, 0);
	}
}

/*
 *  produce random bits in a circular buffer
 */
static void
randomclock(void)
{
	if(rb.randomcount == 0 || !rbnotfull(0))
		return;

	rb.bits = (rb.bits<<2) ^ rb.randomcount;
	rb.randomcount = 0;

	rb.next++;
	if(rb.next != 8/2)
		return;
	rb.next = 0;

	*rb.wp ^= rb.bits;
	if(rb.wp+1 == rb.ep)
		rb.wp = rb.buf;
	else
		rb.wp = rb.wp+1;

	if(rb.wakeme)
		wakeup(&rb.consumer);
}

void
randominit(void)
{
	addclock0link(randomclock);
	rb.ep = rb.buf + sizeof(rb.buf);
	rb.rp = rb.wp = rb.buf;
	kproc("genrandom", genrandom, 0);
}

/*
 *  consume random bytes from a circular buffer
 */
ulong
randomread(void *xp, ulong n)
{
	uchar *e, *p;
	ulong x;

	p = xp;

	if(waserror()){
		qunlock(&rb);
		nexterror();
	}

	qlock(&rb);
	for(e = p + n; p < e; ){
		if(rb.wp == rb.rp){
			rb.wakeme = 1;
			wakeup(&rb.producer);
			sleep(&rb.consumer, rbnotempty, 0);
			rb.wakeme = 0;
			continue;
		}

		/*
		 *  beating clocks will be precictable if
		 *  they are synchronized.  Use a cheap pseudo
		 *  random number generator to obscure any cycles.
		 */
		x = rb.randn*1103515245 ^ *rb.rp;
		*p++ = rb.randn = x;

		if(rb.rp+1 == rb.ep)
			rb.rp = rb.buf;
		else
			rb.rp = rb.rp+1;
	}
	qunlock(&rb);
	poperror();

	wakeup(&rb.producer);

	return n;
}

M mtx/trap.c => mtx/trap.c +7 -12
@@ 157,9 157,9 @@ trap(Ureg *ur)

	m->intrts = fastticks(nil);
	ecode = (ur->cause >> 8) & 0xff;
//	user = (ur->srr1 & MSR_PR) != 0;
	user = (ur->srr1 & MSR_PR) != 0;

/* if(ur->status & MSR_RI == 0)
if(ur->status & MSR_RI == 0)
print("double fault?: ecode = %d\n", ecode);
	switch(ecode){
	case CEI:


@@ 169,6 169,7 @@ print("double fault?: ecode = %d\n", ecode);
	case CDEC:
		clockintr(ur);
		break;
/*
	case CIMISS:
		faultpower(ur, ur->pc, 1);
		break;


@@ 182,12 183,7 @@ if(0) print("CDMISS: %lux %lux\n", m->epn, m->cmp1);
	case CDTLBE:
		faultpower(ur, m->dar, !(m->dsisr & (1<<25)));
		break;

	case CEMU:
		print("CEMU: pc=#%lux op=#%8.8lux\n", ur->pc, *(ulong*)ur->pc);
		sprint(buf, "sys: trap: illegal op addr=0x%lux", ur->pc);
		postnote(up, 1, buf, NDebug);
		break;
*/

	case CSYSCALL:
		syscall(ur);


@@ 214,7 210,6 @@ if(0) print("CDMISS: %lux %lux\n", m->epn, m->cmp1);
		delay(100);
		reset();
	}
*/
	splhi();
	if(user)
		notify(ur);


@@ 226,7 221,7 @@ faultpower(Ureg *ureg, ulong addr, int read)
	int user, insyscall, n;
	char buf[ERRMAX];

//	user = (ureg->srr1 & MSR_PR) != 0;
	user = (ureg->srr1 & MSR_PR) != 0;
if(0)print("fault: pid=%ld pc = %lux, addr = %lux read = %d user = %d stack=%ulx\n", up->pid, ureg->pc, addr, read, user, &ureg);
	insyscall = up->insyscall;
	up->insyscall = 1;


@@ 633,8 628,8 @@ syscall(Ureg* ureg)
	long	ret;
	int	i, scallnr;

//	if((ureg->srr1 & MSR_PR) == 0)
//		panic("syscall: srr1 0x%4.4uX\n", ureg->srr1);
	if((ureg->srr1 & MSR_PR) == 0)
		panic("syscall: srr1 0x%4.4uX\n", ureg->srr1);

	m->syscall++;
	up->insyscall = 1;

M pc/devusb.c => pc/devusb.c +8 -8
@@ 1351,14 1351,14 @@ usbreset(void)
		 */
		if(cfg->ccrb != 0x0C || cfg->ccru != 0x03)
			continue;
		switch(cfg->vid | cfg->did<<16){
		default:
			continue;
		case 0x8086 | 0x7112<<16:	/* 82371[AE]B (PIIX4[E]) */
		case 0x8086 | 0x719A<<16:	/* 82443MX */
		case 0x0586 | 0x1106<<16:	/* VIA 82C586 */
			break;
		}
// 		switch(cfg->vid | cfg->did<<16){
// 		default:
// 			continue;
// 		case 0x8086 | 0x7112<<16:	/* 82371[AE]B (PIIX4[E]) */
// 		case 0x8086 | 0x719A<<16:	/* 82443MX */
// 		case 0x0586 | 0x1106<<16:	/* VIA 82C586 */
// 			break;
// 		}
		if((cfg->mem[4].bar & ~0x0F) != 0)
			break;
	}

M port/portdat.h => port/portdat.h +1 -3
@@ 4,7 4,6 @@ typedef struct Chan	Chan;
typedef struct Cmdbuf	Cmdbuf;
typedef struct Cmdtab	Cmdtab;
typedef struct Cname	Cname;
typedef struct Crypt	Crypt;
typedef struct Dev	Dev;
typedef struct Dirtab	Dirtab;
typedef struct Egrp	Egrp;


@@ 41,10 40,9 @@ typedef struct Sargs	Sargs;
typedef struct Segment	Segment;
typedef struct Session	Session;
typedef struct Talarm	Talarm;
typedef struct Target	Target;
typedef struct Uart	Uart;
typedef struct Waitq	Waitq;
typedef struct Walkqid Walkqid;
typedef struct Walkqid	Walkqid;
typedef int    Devgen(Chan*, char*, Dirtab*, int, int, Dir*);