~kris/9p

9hist

c7b71a77642fd47c18c232a5087ad5d2591dc550 — David du Colombier 25 years ago accfae2
Plan 9 from Bell Labs 2001-07-27
M alphapc/clock.c => alphapc/clock.c +5 -68
@@ 5,36 5,8 @@
#include	"fns.h"
#include	"io.h"
#include	"axp.h"

#include	"ureg.h"

void (*kproftimer)(ulong);

typedef struct Clock0link Clock0link;
typedef struct Clock0link {
	void		(*clock)(void);
	Clock0link*	link;
} Clock0link;

static Clock0link *clock0link;
static Lock clock0lock;

void
addclock0link(void (*clock)(void))
{
	Clock0link *lp;

	if((lp = malloc(sizeof(Clock0link))) == 0){
		print("addclock0link: too many links\n");
		return;
	}
	ilock(&clock0lock);
	lp->clock = clock;
	lp->link = clock0link;
	clock0link = lp;
	iunlock(&clock0lock);
}

void
clockinit(void)
{


@@ 97,58 69,23 @@ microdelay(int us)
}

void
/*milli*/delay(int ms)
delay(int millisecs)
{
	microdelay(ms*1000);
	microdelay(millisecs*1000);
}

void
clock(Ureg *ur)
clock(Ureg *ureg)
{
	Clock0link *lp;
	static int count;

	cycletimer();

	/* HZ == 100, timer == 1024Hz.  error < 1ms */
	count += 100;
	if (count < 1024)
		return;
	count -= 1024;

	m->ticks++;
	if(m->proc)
		m->proc->pc = ur->pc;

	accounttime();

	if(kproftimer != nil)
		kproftimer(ur->pc);

	if((active.machs&(1<<m->machno)) == 0)
		return;

	if(active.exiting && (active.machs & (1<<m->machno))) {
		print("someone's exiting\n");
		exit(0);
	}

	checkalarms();
	if(m->machno == 0){
		lock(&clock0lock);
		for(lp = clock0link; lp; lp = lp->link)
			lp->clock();
		unlock(&clock0lock);
	}

	if(up == 0 || up->state != Running)
		return;

	if(anyready())
		sched();

	/* user profiling clock */
	if(ur->status & UMODE) {
		(*(ulong*)(USTKTOP-BY2WD)) += TK2MS(1);
		segclock(ur->pc);
	}
	portclock(ureg);
}

M alphapc/dat.h => alphapc/dat.h +10 -9
@@ 132,30 132,32 @@ struct Mach
	Proc	*proc;			/* current process on this processor */

	/* ordering from here on irrelevant */
	int	tlbfault;		/* only used by devproc; no access to tlb */
	int	tlbpurge;		/* ... */

	ulong	ticks;			/* of the clock since boot time */
	Label	sched;			/* scheduler wakeup */
	Lock	alarmlock;		/* access to alarm list */
	void	*alarm;			/* alarms bound to this clock */
	Page	*ufreeme;		/* address of upage of exited process */
	int	nrdy;
	int	inclockintr;

	ulong	fairness;		/* for runproc */
	int	lastintr;

	ulong	cpuhz;			/* hwrpb->cfreq */
	ulong	pcclast;
	uvlong	fastclock;
	vlong	intrts;			/* time stamp of last interrupt */

	int	tlbfault;		/* only used by devproc; no access to tlb */
	int	tlbpurge;		/* ... */
	int	pfault;
	int	cs;
	int	syscall;
	int	load;
	int	intr;
	int	spuriousintr;
	int	flushmmu;		/* make current proc flush it's mmu state */

	ulong	spuriousintr;
	int	lastintr;

	PCB;

	/* MUST BE LAST */


@@ 203,11 205,10 @@ struct PCArch
/*
 *  a parsed plan9.ini line
 */
#define ISAOPTLEN	16
#define NISAOPT		8

struct ISAConf {
	char	type[NAMELEN];
	char		*type;
	ulong	port;
	ulong	irq;
	ulong	dma;


@@ 216,7 217,7 @@ struct ISAConf {
	ulong	freq;

	int	nopt;
	char	opt[NISAOPT][ISAOPTLEN];
	char	*opt[NISAOPT];
};

extern PCArch	*arch;

M alphapc/devarch.c => alphapc/devarch.c +93 -49
@@ 27,23 27,69 @@ static struct
} iomap;

enum {
	Qdir,
	Qcputype,
	Qioalloc,
	Qdir = 0,
	Qioalloc = 1,
	Qiob,
	Qiow,
	Qiol,
	Qirqalloc,
	Qbase,

	Qmax = 16,
};

static Dirtab ioallocdir[] = {
	"cputype",	{ Qcputype, 0 },	0,	0444,
typedef long Rdwrfn(Chan*, void*, long, vlong);

static Rdwrfn *readfn[Qmax];
static Rdwrfn *writefn[Qmax];

static Dirtab archdir[] = {
	".",	{ Qdir, 0, QTDIR },	0,	0555,
	"ioalloc",	{ Qioalloc, 0 },	0,	0444,
	"iob",		{ Qiob, 0 },		0,	0660,
	"iow",		{ Qiow, 0 },		0,	0660,
	"iol",		{ Qiol, 0 },		0,	0660,
	"irqalloc",	{ Qirqalloc, 0},	0,	0444,
};
Lock archwlock;	/* the lock is only for changing archdir */
int narchdir = Qbase;

/*
 * Add a file to the #P listing.  Once added, you can't delete it.
 * You can't add a file with the same name as one already there,
 * and you get a pointer to the Dirtab entry so you can do things
 * like change the Qid version.  Changing the Qid path is disallowed.
 */
Dirtab*
addarchfile(char *name, int perm, Rdwrfn *rdfn, Rdwrfn *wrfn)
{
	int i;
	Dirtab d;
	Dirtab *dp;

	memset(&d, 0, sizeof d);
	strcpy(d.name, name);
	d.perm = perm;

	lock(&archwlock);
	if(narchdir >= Qmax){
		unlock(&archwlock);
		return nil;
	}

	for(i=0; i<narchdir; i++)
		if(strcmp(archdir[i].name, name) == 0){
			unlock(&archwlock);
			return nil;
		}

	d.qid.path = narchdir;
	archdir[narchdir] = d;
	readfn[narchdir] = rdfn;
	writefn[narchdir] = wrfn;
	dp = &archdir[narchdir++];
	unlock(&archwlock);

	return dp;
}

void
ioinit(void)


@@ 59,8 105,6 @@ ioinit(void)
	ioalloc(0x20000, 1, 0, "dummy");
}

static long cputyperead(char*, int, ulong);

//
//	alloc some io port space and remember who it was
//	alloced to.  if port < 0, find a free region.


@@ 115,7 159,7 @@ ioalloc(int port, int size, int align, char *tag)
	m->tag[sizeof(m->tag)-1] = 0;
	*l = m;

	ioallocdir[0].qid.vers++;
	archdir[0].qid.vers++;

	unlock(&iomap);
	return m->start;


@@ 138,7 182,7 @@ iofree(int port)
		if((*l)->start > port)
			break;
	}
	ioallocdir[0].qid.vers++;
	archdir[0].qid.vers++;
	unlock(&iomap);
}



@@ 175,22 219,22 @@ archattach(char* spec)
	return devattach('P', spec);
}

int
archwalk(Chan* c, char* name)
Walkqid*
archwalk(Chan* c, Chan *nc, char** name, int nname)
{
	return devwalk(c, name, ioallocdir, nelem(ioallocdir), devgen);
	return devwalk(c, nc, name, nname, archdir, narchdir, devgen);
}

static void
archstat(Chan* c, char* dp)
static int
archstat(Chan* c, uchar* dp, int n)
{
	devstat(c, dp, ioallocdir, nelem(ioallocdir), devgen);
	return devstat(c, dp, n, archdir, narchdir, devgen);
}

static Chan*
archopen(Chan* c, int omode)
{
	return devopen(c, omode, ioallocdir, nelem(ioallocdir), devgen);
	return devopen(c, omode, archdir, nelem(archdir), devgen);
}

static void


@@ 206,17 250,17 @@ enum
static long
archread(Chan *c, void *a, long n, vlong offset)
{
	char *p;
	IOMap *m;
	char buf[Linelen+1];
	char buf[Linelen+1], *p;
	int port;
	ushort *sp;
	ulong *lp;
	IOMap *m;
	Rdwrfn *fn;

	switch(c->qid.path & ~CHDIR){
	switch((ulong)c->qid.path){

	case Qdir:
		return devdirread(c, a, n, ioallocdir, nelem(ioallocdir), devgen);
		return devdirread(c, a, n, archdir, nelem(archdir), devgen);

	case Qiob:
		port = offset;


@@ 248,13 292,9 @@ archread(Chan *c, void *a, long n, vlong offset)
	case Qioalloc:
		break;

	case Qirqalloc:
		return irqallocread(a, n, offset);

	case Qcputype:
		return cputyperead(a, n, offset);

	default:
		if(c->qid.path < narchdir && (fn = readfn[c->qid.path]))
			return fn(c, a, n, offset);
		error(Eperm);
		break;
	}


@@ 281,12 321,13 @@ archread(Chan *c, void *a, long n, vlong offset)
static long
archwrite(Chan *c, void *a, long n, vlong offset)
{
	char *p;
	int port;
	ushort *sp;
	ulong *lp;
	char *p;
	Rdwrfn *fn;

	switch(c->qid.path & ~CHDIR){
	switch((ulong)c->qid.path){

	case Qiob:
		p = a;


@@ 316,6 357,8 @@ archwrite(Chan *c, void *a, long n, vlong offset)
		return n*4;

	default:
		if(c->qid.path < narchdir && (fn = writefn[c->qid.path]))
			return fn(c, a, n, offset);
		error(Eperm);
		break;
	}


@@ 329,7 372,6 @@ Dev archdevtab = {
	devreset,
	devinit,
	archattach,
	devclone,
	archwalk,
	archstat,
	archopen,


@@ 366,22 408,6 @@ static char	*cpunames[] =
};

void
archinit(void)
{
	PCArch **p;

	arch = 0;
	for(p = knownarch; *p; p++){
		if((*p)->ident && (*p)->ident() == 0){
			arch = *p;
			break;
		}
	}
	if(arch == 0)
		arch = &archgeneric;
}

void
cpuidprint(void)
{
	int i, maj, min;


@@ 419,7 445,7 @@ cpuidprint(void)
}

static long
cputyperead(char *a, int n, ulong offset)
cputyperead(Chan*, void *a, long n, vlong offset)
{
	char str[32], *cputype;
	ulong mhz, maj;


@@ 435,3 461,21 @@ cputyperead(char *a, int n, ulong offset)
	snprint(str, sizeof(str), "%s %lud\n", cputype, mhz);
	return readstr(offset, a, n, str);
}

void
archinit(void)
{
	PCArch **p;

	arch = 0;
	for(p = knownarch; *p; p++){
		if((*p)->ident && (*p)->ident() == 0){
			arch = *p;
			break;
		}
	}
	if(arch == 0)
		arch = &archgeneric;

	addarchfile("cputype", 0444, cputyperead, nil);
}

M alphapc/devether.c => alphapc/devether.c +13 -12
@@ 35,16 35,16 @@ etherattach(char* spec)
	return chan;
}

static int
etherwalk(Chan* chan, char* name)
static Walkqid*
etherwalk(Chan* chan, Chan* nchan, char** name, int nname)
{
	return netifwalk(etherxx[chan->dev], chan, name);
	return netifwalk(etherxx[chan->dev], chan, nchan, name, nname);
}

static void
etherstat(Chan* chan, char* dp)
static int
etherstat(Chan* chan, uchar* dp, int n)
{
	netifstat(etherxx[chan->dev], chan, dp);
	return netifstat(etherxx[chan->dev], chan, dp, n);
}

static Chan*


@@ 71,7 71,7 @@ etherread(Chan* chan, void* buf, long n, vlong off)
	ulong offset = off;

	ether = etherxx[chan->dev];
	if((chan->qid.path & CHDIR) == 0 && ether->ifstat){
	if((chan->qid.type & QTDIR) == 0 && ether->ifstat){
		/*
		 * With some controllers it is necessary to reach
		 * into the chip to extract statistics.


@@ 96,10 96,10 @@ etherremove(Chan*)
{
}

static void
etherwstat(Chan* chan, char* dp)
static int
etherwstat(Chan* chan, uchar* dp, int n)
{
	netifwstat(etherxx[chan->dev], chan, dp);
	return netifwstat(etherxx[chan->dev], chan, dp, n);
}

static void


@@ 338,7 338,7 @@ etherreset(void)
{
	Ether *ether;
	int i, n, ctlrno;
	char name[NAMELEN], buf[128];
	char name[32], buf[128];

	for(ether = 0, ctlrno = 0; ctlrno < MaxEther; ctlrno++){
		if(ether == 0)


@@ 347,6 347,8 @@ etherreset(void)
		ether->ctlrno = ctlrno;
		ether->tbdf = BUSUNKNOWN;
		ether->mbps = 10;
		ether->minmtu = ETHERMINTU;
		ether->maxmtu = ETHERMAXTU;
		if(isaconfig("ether", ctlrno, ether) == 0)
			continue;
		for(n = 0; cards[n].type; n++){


@@ 435,7 437,6 @@ Dev etherdevtab = {
	etherreset,
	devinit,
	etherattach,
	devclone,
	etherwalk,
	etherstat,
	etheropen,

M alphapc/devfloppy.c => alphapc/devfloppy.c +13 -14
@@ 104,7 104,7 @@ static void	floppywait(void);
static long	floppyxfer(FDrive*, int, void*, long, long);

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


@@ 134,7 134,7 @@ floppysetdef(FDrive *dp)
	for(t = floppytype; t < &floppytype[nelem(floppytype)]; t++)
		if(dp->dt == t->dt){
			dp->t = t;
			floppydir[NFDIR*dp->dev].length = dp->t->cap;
			floppydir[1+NFDIR*dp->dev].length = dp->t->cap;
			break;
		}
}


@@ 212,22 212,22 @@ floppyattach(char *spec)
	return devattach('f', spec);
}

static int
floppywalk(Chan *c, char *name)
static Walkqid*
floppywalk(Chan *c, Chan *nc, char **name, int nname)
{
	return devwalk(c, name, floppydir, fl.ndrive*NFDIR, devgen);
	return devwalk(c, nc, name, nname, floppydir, 1+fl.ndrive*NFDIR, devgen);
}

static void
floppystat(Chan *c, char *dp)
static int
floppystat(Chan *c, uchar *dp, int n)
{
	devstat(c, dp, floppydir, fl.ndrive*NFDIR, devgen);
	return devstat(c, dp, n, floppydir, 1+fl.ndrive*NFDIR, devgen);
}

static Chan*
floppyopen(Chan *c, int omode)
{
	return devopen(c, omode, floppydir, fl.ndrive*NFDIR, devgen);
	return devopen(c, omode, floppydir, 1+fl.ndrive*NFDIR, devgen);
}

static void


@@ 280,7 280,7 @@ changed(Chan *c, FDrive *dp)
				if(dp->dt == dp->t->dt)
					break;
			}
			floppydir[NFDIR*dp->dev].length = dp->t->cap;
			floppydir[1+NFDIR*dp->dev].length = dp->t->cap;
			floppyon(dp);
			DPRINT("changed: trying %s\n", dp->t->name);
			fldump();


@@ 328,8 328,8 @@ floppyread(Chan *c, void *a, long n, vlong off)
	uchar *aa;
	ulong offset = off;

	if(c->qid.path == CHDIR)
		return devdirread(c, a, n, floppydir, fl.ndrive*NFDIR, devgen);
	if(c->qid.type & QTDIR)
		return devdirread(c, a, n, floppydir, 1+fl.ndrive*NFDIR, devgen);

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


@@ 915,7 915,7 @@ floppyformat(FDrive *dp, char *params)
		for(t = floppytype; t < &floppytype[nelem(floppytype)]; t++){
			if(strcmp(f[1], t->name)==0 && t->dt==dp->dt){
				dp->t = t;
				floppydir[NFDIR*dp->dev].length = dp->t->cap;
				floppydir[1+NFDIR*dp->dev].length = dp->t->cap;
				break;
			}
		}


@@ 1043,7 1043,6 @@ Dev floppydevtab = {
	floppyreset,
	devinit,
	floppyattach,
	devclone,
	floppywalk,
	floppystat,
	floppyopen,

M alphapc/devvga.c => alphapc/devvga.c +9 -9
@@ 24,6 24,7 @@ enum {
};

static Dirtab vgadir[] = {
	".",	{ Qdir, 0, QTDIR },		0,	0550,
	"vgactl",	{ Qvgactl, 0 },		0,	0660,
	"vgabios",	{ Qvgabios, 0 },		0x10000,	0440,
};


@@ 47,16 48,16 @@ vgaattach(char* spec)
	return devattach('v', spec);
}

int
vgawalk(Chan* c, char* name)
Walkqid*
vgawalk(Chan* c, Chan *nc, char** name, int nname)
{
	return devwalk(c, name, vgadir, nelem(vgadir), devgen);
	return devwalk(c, nc, name, nname, vgadir, nelem(vgadir), devgen);
}

static void
vgastat(Chan* c, char* dp)
static int
vgastat(Chan* c, uchar* dp, int n)
{
	devstat(c, dp, vgadir, nelem(vgadir), devgen);
	return devstat(c, dp, n, vgadir, nelem(vgadir), devgen);
}

static Chan*


@@ 93,7 94,7 @@ vgaread(Chan* c, void* a, long n, vlong off)
	ulong offset = off;
	char chbuf[30];

	switch(c->qid.path & ~CHDIR){
	switch((ulong)c->qid.path){

	case Qdir:
		return devdirread(c, a, n, vgadir, nelem(vgadir), devgen);


@@ 359,7 360,7 @@ vgawrite(Chan* c, void* a, long n, vlong off)
	char *p;
	ulong offset = off;

	switch(c->qid.path & ~CHDIR){
	switch((ulong)c->qid.path){

	case Qdir:
		error(Eperm);


@@ 394,7 395,6 @@ Dev vgadevtab = {
	vgareset,
	devinit,
	vgaattach,
	devclone,
	vgawalk,
	vgastat,
	vgaopen,

M alphapc/ether2114x.c => alphapc/ether2114x.c +1 -1
@@ 19,7 19,7 @@

#include "etherif.h"

#define DEBUG		(1)
#define DEBUG		(0)
#define debug		if(DEBUG)print

enum {

M alphapc/etherif.h => alphapc/etherif.h +4 -0
@@ 10,12 10,16 @@ struct Ether {
	int	ctlrno;
	int	tbdf;			/* type+busno+devno+funcno */
	int	mbps;			/* Mbps */
	int	minmtu;
	int 	maxmtu;
	uchar	ea[Eaddrlen];
	int	encry;

	void	(*attach)(Ether*);	/* filled in by reset routine */
	void	(*transmit)(Ether*);
	void	(*interrupt)(Ureg*, void*);
	long	(*ifstat)(Ether*, void*, long, ulong);
	long 	(*ctl)(Ether*, void*, long); /* custom ctl messages */
	void	*ctlr;

	Queue*	oq;

M alphapc/faultalpha.c => alphapc/faultalpha.c +3 -5
@@ 15,7 15,7 @@ faultalpha(Ureg *ur)
{
	ulong addr, cause;
	int read, user;
	char buf[ERRLEN];
	char buf[ERRMAX];
	uvlong x;

	x = ur->a0&0xffffffff80000000LL;


@@ 42,10 42,8 @@ faultalpha(Ureg *ur)
	}

	iprint("kernel %s vaddr=0x%lux\n", read? (cause != 0) ? "ifetch" : "read" : "write", (ulong)ur->a0);
iprint("ptbr %lux up %lux\n", (ulong)m->ptbr, up);
if(up) iprint("top %lux lvl2 %lux\n", up->mmutop->va, up->mmulvl2->va);
if(up) iprint("top[N-1] %lux\n", ((uvlong *)up->mmutop->va)[PTE2PG-1]);
	iprint("st=0x%lux pc=0x%lux sp=0x%lux\n", (ulong)ur->status, (ulong)ur->pc, (ulong)ur->sp);
	if(0)
		mmudump();
	dumpregs(ur);
	panic("fault");
}

M alphapc/fns.h => alphapc/fns.h +5 -1
@@ 1,6 1,6 @@
#include "../port/portfns.h"

void		addclock0link(void (*)(void));
Dirtab*	addarchfile(char*, int, long(*)(Chan*,void*,long,vlong), long(*)(Chan*,void*,long,vlong));
void		archinit(void);
void		arginit(void);
void		arith(void);


@@ 34,6 34,7 @@ void		gotopc(ulong);
int		i8042auxcmd(int);
void		i8042auxenable(void (*)(int, int));
void		i8042reset(void);
void	i8250console(void);
void		i8259init(void);
int		i8259enable(int, int, Vctl*);
#define	idlehands()			/* nothing to do in the runproc */


@@ 49,6 50,7 @@ int		iprint(char*, ...);
int		irqallocread(char*, long, vlong);
int		isaconfig(char*, int, ISAConf*);
void		kbdinit(void);
#define	kmapinval()
void		*kmapv(uvlong, int);
int		kprint(char*, ...);
void		launchinit(void);


@@ 57,6 59,7 @@ void		links(void);
void		mb(void);
void 		memholes(void);
ulong 	meminit(void);
void		mmudump(void);
void		mmuinit(void);
#define	mmunewpage(x)
void		mntdump(void);


@@ 95,6 98,7 @@ void	upafree(ulong, int);
#define		userureg(ur) ((ur)->status & UMODE)
void		wrent(int, void*);
void		wrvptptr(uvlong);
ulong	TK2MS(ulong);				/* ticks to milliseconds */

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

M alphapc/fptrap.c => alphapc/fptrap.c +1 -1
@@ 21,7 21,7 @@ char	*fpexcname(Ureg*, ulong, char*);
void
fptrap(Ureg *ur)
{
	char buf[ERRLEN];
	char buf[ERRMAX];
	int i;
	ulong reason;


M alphapc/io.h => alphapc/io.h +1 -7
@@ 1,10 1,4 @@
enum {
	Uart0		= 0x3F8,
	Uart1		= 0x2F8,
	  UartFREQ	= 1843200,
};

enum {
	IrqCLOCK	= 0,
	IrqKBD		= 1,
	IrqUART1	= 3,


@@ 27,7 21,7 @@ enum {
typedef struct Vctl {
	Vctl*	next;			/* handlers on this vector */

	char	name[NAMELEN];	/* of driver */
	char	name[KNAMELEN];	/* of driver */
	int	isintr;			/* interrupt or fault/trap */
	int	irq;
	int	tbdf;

M alphapc/main.c => alphapc/main.c +40 -52
@@ 26,23 26,34 @@ int	nconf;
static void
options(void)
{
	char *cp, *line[MAXCONF];
	int i, n;
	long i, n;
	char *cp, *line[MAXCONF], *p, *q;

	cp = bootconf->bootargs;
	cp[BOOTARGSLEN-1] = 0;
	strcpy(bootargs, cp);

	n = getcfields(bootargs, line, MAXCONF, "\n");
	/*
	 * Strip out '\r', change '\t' -> ' '.
	 */
	p = cp;
	for(q = cp; *q; q++){
		if(*q == '\r')
			continue;
		if(*q == '\t')
			*q = ' ';
		*p++ = *q;
	}
	*p = 0;

	n = getfields(cp, line, MAXCONF, 1, "\n");
	for(i = 0; i < n; i++){
		if(*line[i] == '#')
			continue;
		cp = strchr(line[i], '=');
		if(cp == 0)
		if(cp == nil)
			continue;
		*cp++ = 0;
		if(cp - line[i] >= NAMELEN+1)
			*(line[i]+NAMELEN-1) = 0;
		*cp++ = '\0';
		confname[nconf] = line[i];
		confval[nconf] = cp;
		nconf++;


@@ 56,8 67,8 @@ main(void)
	hwrpb = (Hwrpb*)(KZERO|hwrpb->phys);
	arginit();
	machinit();
	ioinit();
	options();
	ioinit();
	clockinit();
	confinit();
	archinit();


@@ 69,11 80,9 @@ main(void)
	trapinit();
	screeninit();
	printinit();

	/* console */
	ns16552install();
	ns16552special(0, 9600, 0, &printq, kbdcr2nl);
	kbdinit();
	i8250console();
	print("\nPlan 9\n");

	cpuidprint();
	if(arch->corehello)


@@ 123,7 132,9 @@ void
init0(void)
{
	int i;
	char buf[2*NAMELEN];
	char tstr[32];

	up->nerrlab = 0;

	spllo();



@@ 134,15 145,14 @@ init0(void)
	up->slash = namec("#/", Atodir, 0, 0);
	cnameclose(up->slash->name);
	up->slash->name = newcname("/");
	up->dot = cclone(up->slash, 0);
	up->dot = cclone(up->slash);

	chandevinit();

	if(!waserror()){
		ksetenv("cputype", "alpha");
		sprint(buf, "alpha %s alphapc", conffile);
		ksetenv("terminal", buf);
		ksetenv("sysname", sysname);
		sprint(tstr, "alpha %s alphapc", conffile);
		ksetenv("terminal", tstr);
		if(cpuserver)
			ksetenv("service", "cpu");
		else


@@ 174,8 184,9 @@ userinit(void)
	p->rgrp = newrgrp();
	p->procmode = 0640;

	strcpy(p->text, "*init*");
	strcpy(p->user, eve);
	kstrdup(&eve, "");
	kstrdup(&p->text, "*init*");
	kstrdup(&p->user, eve);

	procsetup(p);



@@ 398,7 409,7 @@ confinit(void)
		imagmem->maxsize = kpages;
	}

	conf.monitor = 1;	/* BUG */
//	conf.monitor = 1;	/* BUG */
}

void


@@ 454,29 465,18 @@ getconf(char *name)
int
isaconfig(char *class, int ctlrno, ISAConf *isa)
{
	char cc[NAMELEN], *p, *q, *r;
	int n;
	char cc[32], *p;
	int i, n;

	sprint(cc, "%s%d", class, ctlrno);
	snprint(cc, sizeof cc, "%s%d", class, ctlrno);
	for(n = 0; n < nconf; n++){
		if(cistrncmp(confname[n], cc, NAMELEN))
		if(cistrcmp(confname[n], cc) != 0)
			continue;
		isa->nopt = 0;
		p = confval[n];
		while(*p){
			while(*p == ' ' || *p == '\t')
				p++;
			if(*p == '\0')
				break;
			if(cistrncmp(p, "type=", 5) == 0){
				p += 5;
				for(q = isa->type; q < &isa->type[NAMELEN-1]; q++){
					if(*p == '\0' || *p == ' ' || *p == '\t')
						break;
					*q = *p++;
				}
				*q = '\0';
			}
		isa->nopt = tokenize(confval[n], isa->opt, NISAOPT);
		for(i = 0; i < isa->nopt; i++){
			p = isa->opt[i];
			if(cistrncmp(p, "type=", 5) == 0)
				isa->type = p + 5;
			else if(cistrncmp(p, "port=", 5) == 0)
				isa->port = strtoul(p+5, &p, 0);
			else if(cistrncmp(p, "irq=", 4) == 0)


@@ 489,18 489,6 @@ isaconfig(char *class, int ctlrno, ISAConf *isa)
				isa->size = strtoul(p+5, &p, 0);
			else if(cistrncmp(p, "freq=", 5) == 0)
				isa->freq = strtoul(p+5, &p, 0);
			else if(isa->nopt < NISAOPT){
				r = isa->opt[isa->nopt];
				while(*p && *p != ' ' && *p != '\t'){
					*r++ = *p++;
					if(r-isa->opt[isa->nopt] >= ISAOPTLEN-1)
						break;
				}
				*r = '\0';
				isa->nopt++;
			}
			while(*p && *p != ' ' && *p != '\t')
				p++;
		}
		return 1;
	}

M alphapc/mem.h => alphapc/mem.h +0 -1
@@ 29,7 29,6 @@
#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 */

/*

M alphapc/mmu.c => alphapc/mmu.c +16 -0
@@ 254,3 254,19 @@ upafree(ulong, int)
{
	print("upafree: virtual mapping not freed\n");
}

void
mmudump(void)
{
	Page *top, *lvl2;

	iprint("ptbr %lux up %lux\n", (ulong)m->ptbr, up);
	if(up) {
		top = up->mmutop;
		if(top != nil)
			iprint("top %lux top[N-1] %lux\n", top->va, ((uvlong *)top->va)[PTE2PG-1]);
		lvl2 = up->mmulvl2;
		if(lvl2 != nil)
			iprint("lvl2 %lux\n", lvl2->va);
	}
}

M alphapc/mouse.c => alphapc/mouse.c +9 -3
@@ 29,6 29,7 @@ static int mousetype;
static void
serialmouse(int port, char *type, int setspeed)
{
#ifdef notdef
	if(mousetype == Mouseserial)
		error(Emouseset);



@@ 39,10 40,15 @@ serialmouse(int port, char *type, int setspeed)
	if(setspeed)
		setspeed = 1200;
	if(type && *type == 'M')
		ns16552special(port, setspeed, 0, 0, m3mouseputc);
		uartspecial(port, setspeed, 0, 0, m3mouseputc);
	else
		ns16552special(port, setspeed, 0, 0, mouseputc);
		uartspecial(port, setspeed, 0, 0, mouseputc);
	mousetype = Mouseserial;
	packetsize = 3;
#else
	error("serial mouse not supported yet");
	USED(port, type, setspeed);
#endif /* notdef */
}

/*


@@ 79,7 85,7 @@ ps2mouseputc(int c, int shift)
		buttons = b[(msg[0]&7) | (shift ? 8 : 0)];
		dx = msg[1];
		dy = -msg[2];
		mousetrack(buttons, dx, dy);
		mousetrack(buttons, dx, dy, TK2MS(MACHP(0)->ticks));
	}
	return;
}

M alphapc/screen.h => alphapc/screen.h +2 -1
@@ 6,7 6,7 @@ struct Cursorinfo {
};

/* devmouse.c */
extern void mousetrack(int, int, int);
extern void mousetrack(int, int, int, int);
extern Point mousexy(void);

extern void mouseaccelerate(int);


@@ 127,6 127,7 @@ extern void mousectl(char*[], int);
/* screen.c */
extern int		hwaccel;	/* use hw acceleration; default on */
extern int		hwblank;	/* use hw blanking; default on */
extern uchar* attachscreen(Rectangle*, ulong*, int*, int*, int*);
extern void	flushmemscreen(Rectangle);
extern int	cursoron(int);
extern void	cursoroff(int);

M alphapc/sd53c8xx.c => alphapc/sd53c8xx.c +2 -2
@@ 2030,13 2030,13 @@ symenable(SDev* sdev)
{
	Pcidev *pcidev;
	Controller *ctlr;
	char name[NAMELEN];
	char name[32];

	ctlr = sdev->ctlr;
	pcidev = ctlr->pcidev;

	pcisetbme(pcidev);
	snprint(name, NAMELEN, "%s (%s)", sdev->name, sdev->ifc->name);
	snprint(name, sizeof(name), "%s (%s)", sdev->name, sdev->ifc->name);
	intrenable(pcidev->intl, interrupt, ctlr, pcidev->tbdf, name);

	ilock(ctlr);

M alphapc/trap.c => alphapc/trap.c +12 -12
@@ 44,8 44,8 @@ intrenable(int irq, void (*f)(Ureg*, void*), void* a, int tbdf, char *name)
	v->tbdf = tbdf;
	v->f = f;
	v->a = a;
	strncpy(v->name, name, NAMELEN-1);
	v->name[NAMELEN-1] = 0;
	strncpy(v->name, name, KNAMELEN-1);
	v->name[KNAMELEN-1] = 0;

	ilock(&vctllock);
	vno = arch->intrenable(v);


@@ 79,7 79,7 @@ irqallocread(char *buf, long n, vlong offset)
	int vno;
	Vctl *v;
	long oldn;
	char str[11+1+NAMELEN+1], *p;
	char str[11+1+KNAMELEN+1], *p;
	int m;

	if(n < 0 || offset < 0)


@@ 88,7 88,7 @@ irqallocread(char *buf, long n, vlong offset)
	oldn = n;
	for(vno=0; vno<nelem(vctl); vno++){
		for(v=vctl[vno]; v; v=v->next){
			m = snprint(str, sizeof str, "%11d %11d %.*s\n", vno, v->irq, NAMELEN, v->name);
			m = snprint(str, sizeof str, "%11d %11d %.*s\n", vno, v->irq, KNAMELEN, v->name);
			if(m <= offset)	/* if do not want this, skip entry */
				offset -= m;
			else{


@@ 252,7 252,7 @@ intr(Ureg *ur)
void
trap(Ureg *ur)
{
	char buf[ERRLEN];
	char buf[ERRMAX];
	int user, x;

	m->intrts = fastticks(nil);


@@ 335,7 335,7 @@ trapinit(void)
void
fataltrap(Ureg *ur, char *reason)
{
	char buf[ERRLEN];
	char buf[ERRMAX];

	if(ur->status&UMODE) {
		spllo();


@@ 474,8 474,8 @@ notify(Ureg *ur)
	n = &up->note[0];
	if(strncmp(n->msg, "sys:", 4) == 0) {
		l = strlen(n->msg);
		if(l > ERRLEN-15)	/* " pc=0x12345678\0" */
			l = ERRLEN-15;
		if(l > ERRMAX-15)	/* " pc=0x12345678\0" */
			l = ERRMAX-15;

		sprint(n->msg+l, " pc=0x%lux", (ulong)ur->pc);
	}


@@ 501,7 501,7 @@ notify(Ureg *ur)
	sp -= sizeof(Ureg);

	if(!okaddr((ulong)up->notify, BY2WD, 0)
	|| !okaddr(sp-ERRLEN-6*BY2WD, sizeof(Ureg)+ERRLEN-6*BY2WD, 1)) {
	|| !okaddr(sp-ERRMAX-6*BY2WD, sizeof(Ureg)+ERRMAX-6*BY2WD, 1)) {
		pprint("suicide: bad address or sp in notify\n");
print("suicide: bad address or sp in notify\n");
		qunlock(&up->debug);


@@ 511,8 511,8 @@ print("suicide: bad address or sp in notify\n");
	memmove((Ureg*)sp, ur, sizeof(Ureg));
	*(Ureg**)(sp-BY2WD) = up->ureg;	/* word under Ureg is old up->ureg */
	up->ureg = (void*)sp;
	sp -= 2*BY2WD+ERRLEN;
	memmove((char*)sp, up->note[0].msg, ERRLEN);
	sp -= 2*BY2WD+ERRMAX;
	memmove((char*)sp, up->note[0].msg, ERRMAX);
	sp -= 4*BY2WD;
	*(ulong*)(sp+3*BY2WD) = sp+4*BY2WD;	/* arg 2 is string */
	ur->r0 = (ulong)up->ureg;		/* arg 1 (R0) is ureg* */


@@ 603,7 603,7 @@ print("suicide: trap in noted\n");
			pexit("Suicide", 0);
		}
		qunlock(&up->debug);
		sp = oureg-4*BY2WD-ERRLEN;
		sp = oureg-4*BY2WD-ERRMAX;
		splhi();
		(*urp)->sp = sp;
		((ulong*)sp)[1] = oureg;	/* arg 1 0(FP) is ureg* */

A alphapc/uarti8250.c => alphapc/uarti8250.c +648 -0
@@ 0,0 1,648 @@
#include "u.h"
#include "../port/lib.h"
#include "mem.h"
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "../port/error.h"

/*
 * 8250 UART and compatibles.
 */
enum {
	Uart0		= 0x3F8,	/* COM1 */
	Uart0IRQ	= 4,
	Uart1		= 0x2F8,	/* COM2 */
	Uart1IRQ	= 3,

	UartFREQ	= 1843200,
};

enum {					/* I/O ports */
	Rbr		= 0,		/* Receiver Buffer (RO) */
	Thr		= 0,		/* Transmitter Holding (WO) */
	Ier		= 1,		/* Interrupt Enable */
	Iir		= 2,		/* Interrupt Identification (RO) */
	Fcr		= 2,		/* FIFO Control (WO) */
	Lcr		= 3,		/* Line Control */
	Mcr		= 4,		/* Modem Control */
	Lsr		= 5,		/* Line Status */
	Msr		= 6,		/* Modem Status */
	Scr		= 7,		/* Scratch Pad */
	Dll		= 0,		/* Divisor Latch LSB */
	Dlm		= 1,		/* Divisor Latch MSB */
};

enum {					/* Ier */
	Erda		= 0x01,		/* Enable Received Data Available */
	Ethre		= 0x02,		/* Enable Thr Empty */
	Erls		= 0x04,		/* Enable Receiver Line Status */
	Ems		= 0x08,		/* Enable Modem Status */
};

enum {					/* Iir */
	Ims		= 0x00,		/* Ms interrupt */
	Ip		= 0x01,		/* Interrupt Pending (not) */
	Ithre		= 0x02,		/* Thr Empty */
	Irda		= 0x04,		/* Received Data Available */
	Irls		= 0x06,		/* Receiver Line Status */
	Ictoi		= 0x0C,		/* Character Time-out Indication */
	IirMASK		= 0x3F,
	Ife		= 0xC0,		/* FIFOs enabled */
};

enum {					/* Fcr */
	FIFOena		= 0x01,		/* FIFO enable */
	FIFOrclr	= 0x02,		/* clear Rx FIFO */
	FIFOtclr	= 0x04,		/* clear Tx FIFO */
	FIFO1		= 0x00,		/* Rx FIFO trigger level 1 byte */
	FIFO4		= 0x40,		/*	4 bytes */
	FIFO8		= 0x80,		/*	8 bytes */
	FIFO14		= 0xC0,		/*	14 bytes */
};

enum {					/* Lcr */
	Wls5		= 0x00,		/* Word Length Select 5 bits/byte */
	Wls6		= 0x01,		/*	6 bits/byte */
	Wls7		= 0x02,		/*	7 bits/byte */
	Wls8		= 0x03,		/*	8 bits/byte */
	WlsMASK		= 0x03,
	Stb		= 0x04,		/* 2 stop bits */
	Pen		= 0x08,		/* Parity Enable */
	Eps		= 0x10,		/* Even Parity Select */
	Stp		= 0x20,		/* Stick Parity */
	Brk		= 0x40,		/* Break */
	Dlab		= 0x80,		/* Divisor Latch Access Bit */
};

enum {					/* Mcr */
	Dtr		= 0x01,		/* Data Terminal Ready */
	Rts		= 0x02,		/* Ready To Send */
	Out1		= 0x04,		/* no longer in use */
	Ie		= 0x08,		/* IRQ Enable */
	Dm		= 0x10,		/* Diagnostic Mode loopback */
};

enum {					/* Lsr */
	Dr		= 0x01,		/* Data Ready */
	Oe		= 0x02,		/* Overrun Error */
	Pe		= 0x04,		/* Parity Error */
	Fe		= 0x08,		/* Framing Error */
	Bi		= 0x10,		/* Break Interrupt */
	Thre		= 0x20,		/* Thr Empty */
	Temt		= 0x40,		/* Tramsmitter Empty */
	FIFOerr		= 0x80,		/* error in receiver FIFO */
};

enum {					/* Msr */
	Dcts		= 0x01,		/* Delta Cts */
	Ddsr		= 0x02,		/* Delta Dsr */
	Teri		= 0x04,		/* Trailing Edge of Ri */
	Ddcd		= 0x08,		/* Delta Dcd */
	Cts		= 0x10,		/* Clear To Send */
	Dsr		= 0x20,		/* Data Set Ready */
	Ri		= 0x40,		/* Ring Indicator */
	Dcd		= 0x80,		/* Data Set Ready */
};

typedef struct Ctlr {
	int	io;
	int	irq;
	int	tbdf;
	int	iena;

	uchar	sticky[8];

	Lock;
	int	fifo;
	int	fena;
} Ctlr;

extern PhysUart i8250physuart;

static Ctlr i8250ctlr[2] = {
{	.io	= Uart0,
	.irq	= Uart0IRQ,
	.tbdf	= BUSUNKNOWN, },

{	.io	= Uart1,
	.irq	= Uart1IRQ,
	.tbdf	= BUSUNKNOWN, },
};

static Uart i8250uart[2] = {
{	.regs	= &i8250ctlr[0],
	.name	= "COM1",
	.freq	= UartFREQ,
	.phys	= &i8250physuart,
	.special=0,
	.next	= &i8250uart[1], },

{	.regs	= &i8250ctlr[1],
	.name	= "COM2",
	.freq	= UartFREQ,
	.phys	= &i8250physuart,
	.special=0,
	.next	= nil, },
};

static Uart* consuart;

#define csr8r(c, r)	inb((c)->io+(r))
#define csr8w(c, r, v)	outb((c)->io+(r), (c)->sticky[(r)]|(v))

static long
i8250status(Uart* uart, void* buf, long n, long offset)
{
	char *p;
	Ctlr *ctlr;
	uchar ier, lcr, mcr, msr;

	ctlr = uart->regs;
	p = malloc(READSTR);
	mcr = ctlr->sticky[Mcr];
	msr = csr8r(ctlr, Msr);
	ier = ctlr->sticky[Ier];
	lcr = ctlr->sticky[Lcr];
	snprint(p, READSTR,
		"b%d c%d d%d e%d l%d m%d p%c r%d s%d i%d\n"
		"dev(%d) type(%d) framing(%d) overruns(%d)%s%s%s%s\n",

		uart->baud,
		uart->hup_dcd, 
		(msr & Dsr) != 0,
		uart->hup_dsr,
		(lcr & WlsMASK) + 5,
		(ier & Ems) != 0, 
		(lcr & Pen) ? ((lcr & Eps) ? 'e': 'o'): 'n',
		(mcr & Rts) != 0,
		(lcr & Stb) ? 2: 1,
		ctlr->fena,

		uart->dev,
		uart->type,
		uart->ferr,
		uart->oerr, 
		(msr & Cts) ? " cts": "",
		(msr & Dsr) ? " dsr": "",
		(msr & Dcd) ? " dcd": "",
		(msr & Ri) ? " ring": ""
	);
	n = readstr(offset, buf, n, p);
	free(p);

	return n;
}

static void
i8250fifo(Uart* uart, int on)
{
	int i;
	Ctlr *ctlr;

	/*
	 * Toggle FIFOs:
	 * if none, do nothing;
	 * reset the Rx and Tx FIFOs;
	 * empty the Rx buffer and clear any interrupt conditions;
	 * if enabling, try to turn them on.
	 */
	ctlr = uart->regs;

	ilock(ctlr);
	if(!ctlr->fifo){
		csr8w(ctlr, Fcr, FIFOtclr|FIFOrclr);
		for(i = 0; i < 16; i++){
			csr8r(ctlr, Iir);
			csr8r(ctlr, Rbr);
		}
  
		ctlr->fena = 0;
		if(on){
			csr8w(ctlr, Fcr, FIFO4|FIFOena);
			if(!(csr8r(ctlr, Iir) & Ife))
				ctlr->fifo = 1;
			ctlr->fena = 1;
		}
	}
	iunlock(ctlr);
}

static void
i8250dtr(Uart* uart, int on)
{
	Ctlr *ctlr;

	/*
	 * Toggle DTR.
	 */
	ctlr = uart->regs;
	if(on)
		ctlr->sticky[Mcr] |= Dtr;
	else
		ctlr->sticky[Mcr] &= ~Dtr;
	csr8w(ctlr, Mcr, 0);
}

static void
i8250rts(Uart* uart, int on)
{
	Ctlr *ctlr;

	/*
	 * Toggle RTS.
	 */
	ctlr = uart->regs;
	if(on)
		ctlr->sticky[Mcr] |= Rts;
	else
		ctlr->sticky[Mcr] &= ~Rts;
	csr8w(ctlr, Mcr, 0);
}

static void
i8250modemctl(Uart* uart, int on)
{
	Ctlr *ctlr;

	ctlr = uart->regs;
	ilock(&uart->tlock);
	if(on){
		ctlr->sticky[Ier] |= Ems;
		csr8w(ctlr, Ier, 0);
		uart->modem = 1;
		uart->cts = csr8r(ctlr, Msr) & Cts;
	}
	else{
		ctlr->sticky[Ier] &= ~Ems;
		csr8w(ctlr, Ier, 0);
		uart->modem = 0;
		uart->cts = 1;
	}
	iunlock(&uart->tlock);

	/* modem needs fifo */
	(*uart->phys->fifo)(uart, on);
}

static int
i8250parity(Uart* uart, int parity)
{
	int lcr;
	Ctlr *ctlr;

	ctlr = uart->regs;
	lcr = ctlr->sticky[Lcr] & ~(Eps|Pen);

	switch(parity){
	case 'e':
		lcr |= Eps|Pen;
		break;
	case 'o':
		lcr |= Pen;
		break;
	case 'n':
	default:
		break;
	}
	ctlr->sticky[Lcr] = lcr;
	csr8w(ctlr, Lcr, 0);

	uart->parity = parity;

	return 0;
}

static int
i8250stop(Uart* uart, int stop)
{
	int lcr;
	Ctlr *ctlr;

	ctlr = uart->regs;
	lcr = ctlr->sticky[Lcr] & ~Stb;

	switch(stop){
	case 1:
		break;
	case 2:
		lcr |= Stb;
		break;
	default:
		return -1;
	}
	ctlr->sticky[Lcr] = lcr;
	csr8w(ctlr, Lcr, 0);

	uart->stop = stop;

	return 0;
}

static int
i8250bits(Uart* uart, int bits)
{
	int lcr;
	Ctlr *ctlr;

	ctlr = uart->regs;
	lcr = ctlr->sticky[Lcr] & ~WlsMASK;

	switch(bits){
	case 5:
		lcr |= Wls5;
		break;
	case 6:
		lcr |= Wls6;
		break;
	case 7:
		lcr |= Wls7;
		break;
	case 8:
		lcr |= Wls8;
		break;
	default:
		return -1;
	}
	ctlr->sticky[Lcr] = lcr;
	csr8w(ctlr, Lcr, 0);

	uart->bits = bits;

	return 0;
}

static int
i8250baud(Uart* uart, int baud)
{
	ulong bgc;
	Ctlr *ctlr;

	/*
	 * Set the Baud rate by calculating and setting the Baud rate
	 * Generator Constant. This will work with fairly non-standard
	 * Baud rates.
	 */
	if(uart->freq == 0 || baud <= 0)
		return -1;
	bgc = (uart->freq+8*baud-1)/(16*baud);

	ctlr = uart->regs;
	csr8w(ctlr, Lcr, Dlab);
	outb(ctlr->io+Dlm, bgc>>8);
	outb(ctlr->io+Dll, bgc);
	csr8w(ctlr, Lcr, 0);

	uart->baud = baud;

	return 0;
}

static void
i8250break(Uart* uart, int ms)
{
	Ctlr *ctlr;

	/*
	 * Send a break.
	 */
	if(ms == 0)
		ms = 200;

	ctlr = uart->regs;
	csr8w(ctlr, Lcr, Brk);
	tsleep(&up->sleep, return0, 0, ms);
	csr8w(ctlr, Lcr, 0);
}

static void
i8250kick(Uart* uart)
{
	int i;
	Ctlr *ctlr;

	if(uart->cts == 0 || uart->blocked)
		return;

	/*
	 *  128 here is an arbitrary limit to make sure
	 *  we don't stay in this loop too long.  If the
	 *  chip's output queue is longer than 128, too
	 *  bad -- presotto
	 */
	ctlr = uart->regs;
	for(i = 0; i < 128; i++){
		if(!(csr8r(ctlr, Lsr) & Thre))
			break;
		if(uart->op >= uart->oe && uartstageoutput(uart) == 0)
			break;
		outb(ctlr->io+Thr, *(uart->op++));
	}
}

static void
i8250interrupt(Ureg*, void* arg)
{
	Ctlr *ctlr;
	Uart *uart;
	int iir, lsr, old, r;

	uart = arg;

	ctlr = uart->regs;
	for(iir = csr8r(ctlr, Iir); !(iir & Ip); iir = csr8r(ctlr, Iir)){
		switch(iir & IirMASK){
		case Ims:		/* Ms interrupt */
			r = csr8r(ctlr, Msr);
			if(r & Dcts){
				ilock(&uart->tlock);
				old = uart->cts;
				uart->cts = r & Cts;
				if(old == 0 && uart->cts)
					uart->ctsbackoff = 2;
				iunlock(&uart->tlock);
			}
		 	if(r & Ddsr){
				old = r & Dsr;
				if(uart->hup_dsr && uart->dsr && !old)
					uart->dohup = 1;
				uart->dsr = old;
			}
		 	if(r & Ddcd){
				old = r & Dcd;
				if(uart->hup_dcd && uart->dcd && !old)
					uart->dohup = 1;
				uart->dcd = old;
			}
			break;
		case Ithre:		/* Thr Empty */
			uartkick(uart);
			break;
		case Irda:		/* Received Data Available */
		case Ictoi:		/* Character Time-out Indication */
			/*
			 * Consume any received data.
			 * If the received byte came in with a break,
			 * parity or framing error, throw it away;
			 * overrun is an indication that something has
			 * already been tossed.
			 */
			while((lsr = csr8r(ctlr, Lsr)) & Dr){
				if(lsr & Oe)
					uart->oerr++;
				if(lsr & Pe)
					uart->perr++;
				if(lsr & Fe)
					uart->ferr++;
				r = csr8r(ctlr, Rbr);
				if(!(lsr & (Bi|Fe|Pe)))
					uartrecv(uart, r);
			}
			break;
		default:
			iprint("weird uart interrupt 0x%2.2uX\n", iir);
			break;
		}
	}
}

static void
i8250disable(Uart* uart)
{
	Ctlr *ctlr;

	/*
 	 * Turn off DTR and RTS, disable interrupts and fifos.
	 */
	(*uart->phys->dtr)(uart, 0);
	(*uart->phys->rts)(uart, 0);
	(*uart->phys->fifo)(uart, 0);

	ctlr = uart->regs;
	ctlr->sticky[Ier] = 0;
	csr8w(ctlr, Ier, 0);
}

static void
i8250enable(Uart* uart, int ie)
{
	Ctlr *ctlr;

	/*
 	 * Enable interrupts and turn on DTR and RTS.
	 * Be careful if this is called to set up a polled serial line
	 * early on not to try to enable interrupts as interrupt-
	 * -enabling mechanisms might not be set up yet.
	 */
	ctlr = uart->regs;
	if(ie){
		if(ctlr->iena == 0){
			intrenable(ctlr->irq, i8250interrupt, uart, ctlr->tbdf, uart->name);
			ctlr->iena = 1;
		}
		ctlr->sticky[Ier] = Ethre|Erda;
		ctlr->sticky[Mcr] |= Ie;
	}
	else{
		ctlr->sticky[Ier] = 0;
		ctlr->sticky[Mcr] = 0;
	}
	csr8w(ctlr, Ier, ctlr->sticky[Ier]);
	csr8w(ctlr, Mcr, ctlr->sticky[Mcr]);

	(*uart->phys->dtr)(uart, 1);
	(*uart->phys->rts)(uart, 1);
}

static Uart*
i8250pnp(void)
{
	return i8250uart;
}

PhysUart i8250physuart = {
	.name		= "i8250",
	.pnp		= i8250pnp,
	.enable		= i8250enable,
	.disable	= i8250disable,
	.kick		= i8250kick,
	.dobreak	= i8250break,
	.baud		= i8250baud,
	.bits		= i8250bits,
	.stop		= i8250stop,
	.parity		= i8250parity,
	.modemctl	= i8250modemctl,
	.rts		= i8250rts,
	.dtr		= i8250dtr,
	.status		= i8250status,
	.fifo		= i8250fifo,
};

int
serialgetc(void)
{
	return -1;
}

static void
i8250putc(Ctlr* ctlr, int c)
{
	int i;

	for(i = 0; i < 128; i++){
		if(csr8r(ctlr, Lsr) & Thre)
			break;
		delay(1);
	}
	outb(ctlr->io+Thr, c);
}

static void
i8250puts(char* s, int n)
{
	Ctlr *ctlr;
	Uart *uart;

	if((uart = consuart) == nil)
		return;

	ctlr = uart->regs;
	while(n--){
		if(*s == '\n')
			i8250putc(ctlr, '\r');
		i8250putc(ctlr, *s++);
	}
}

void
i8250console(void)
{
	Uart *uart;
	int n;
	char *cmd, *p;

	if((p = getconf("console")) == nil)
		return;
	n = strtoul(p, &cmd, 0);
	if(p == cmd)
		return;
	switch(n){
	default:
		return;
	case 0:
		uart = &i8250uart[0];
		break;
	case 1:
		uart = &i8250uart[1];
		break;	
	}

	if(*cmd == 0)
		cmd = "b9600 l8 pn s1";
	uartctl(uart, cmd);
	(*uart->phys->enable)(uart, 0);

	consuart = uart;
	serialputs = i8250puts;
	uart->console = 1;
} 

M pc/sdata.c => pc/sdata.c +14 -4
@@ 531,10 531,10 @@ ataidentify(int cmdport, int ctlport, int dev, int pkt, void* info)
static Drive*
atadrive(int cmdport, int ctlport, int dev)
{
	ushort *sp;
	Drive *drive;
	int as, i, pkt;
	uchar buf[512], *p;
	ushort iconfig, *sp;

	atadebug(0, 0, "identify: port 0x%uX dev 0x%2.2uX\n", cmdport, dev);
	pkt = 1;


@@ 567,8 567,18 @@ retry:
	}

	drive->secsize = 512;
	if((drive->info[Iconfig] & 0xC000) == 0x8000){
		if(drive->info[Iconfig] & 0x01)

	/*
	 * Beware the CompactFlash Association feature set.
	 * Now, why this value in Iconfig just walks all over the bit
	 * definitions used in the other parts of the ATA/ATAPI standards
	 * is a mystery and a sign of true stupidity on someone's part.
	 * Anyway, the standard says if this value is 0x848A then it's
	 * CompactFlash and it's NOT a packet device.
	 */
	iconfig = drive->info[Iconfig];
	if(iconfig != 0x848A && (iconfig & 0xC000) == 0x8000){
		if(iconfig & 0x01)
			drive->pkt = 16;
		else
			drive->pkt = 12;


@@ 598,7 608,7 @@ retry:
	if(DEBUG & DbgCONFIG){
		print("dev %2.2uX port %uX config %4.4uX capabilities %4.4uX",
			dev, cmdport,
			drive->info[Iconfig], drive->info[Icapabilities]);
			iconfig, drive->info[Icapabilities]);
		print(" mwdma %4.4uX", drive->info[Imwdma]);
		if(drive->info[Ivalid] & 0x04)
			print(" udma %4.4uX", drive->info[Iudma]);

M port/sysfile.c => port/sysfile.c +16 -18
@@ 414,18 414,17 @@ sys_read(ulong *arg)
long
syspread(ulong *arg)
{
	union {
		uvlong v;
		ulong u[2];
	} o;
	uvlong v;
	va_list list;

	if(arg[3]==~0UL && arg[4]==~0UL)
		return read(arg, nil);
	va_start(list, arg[2]);
	v = va_arg(list, uvlong);
	va_end(list);

	o.u[0] = arg[3];
	o.u[1] = arg[4];
	if(v ==~0ULL)
		return read(arg, nil);

	return read(arg, &o.v);
	return read(arg, &v);
}

static long


@@ 487,18 486,17 @@ sys_write(ulong *arg)
long
syspwrite(ulong *arg)
{
	union {
		uvlong v;
		ulong u[2];
	} o;
	uvlong v;
	va_list list;

	if(arg[3]==~0UL && arg[4]==~0UL)
		return write(arg, nil);
	va_start(list, arg[2]);
	v = va_arg(list, uvlong);
	va_end(list);

	o.u[0] = arg[3];
	o.u[1] = arg[4];
	if(v ==~0ULL)
		return write(arg, nil);

	return write(arg, &o.v);
	return write(arg, &v);
}

static void