~kris/9p

9hist

8783251074b7b09db581532c376675e4990e4cd8 — David du Colombier 26 years ago 7dbdedb
Plan 9 from Bell Labs 2000-04-01
M alphapc/arch164.c => alphapc/arch164.c +15 -90
@@ 164,100 164,26 @@ pcimem2117x(int addr, int len)
	return kmapio(0x88, addr, len);
}

/*
 *	interrupts -- adapted from PC, needs work.
 */

static Lock irqctllock;
static Irqctl *irqctl[256];
static char irqmask[3];

static void
intr164(Ureg *ur)
static int
intrenable164(Vctl *v)
{
	int i, v;
	Irqctl *ctl;
	Irq *irq;
	Mach *mach;

	v = (ulong)ur->a1>>4;
	if (v < 0x80) {
		iprint("unknown device intr v %d\n", v);
		return;
	}
	v -= 0x80;
	if(v < 256 && (ctl = irqctl[v])){
		if(ctl->isintr){
			m->intr++;
			if(ctl->isr)
				ctl->isr(v);
/*				if(v >= VectorPIC && v <= MaxVectorPIC)
				m->lastintr = v-VectorPIC; */
		}

		for(irq = ctl->irq; irq; irq = irq->next)
			irq->f(ur, irq->a);

		if(ctl->eoi)
			ctl->eoi(v);
	}
	else if(v >= VectorPIC && v <= MaxVectorPIC){
		/*
		 * An unknown interrupt.
		 * Check for a default IRQ7. This can happen when
		 * the IRQ input goes away before the acknowledge.
		 * In this case, a 'default IRQ7' is generated, but
		 * the corresponding bit in the ISR isn't set.
		 * In fact, just ignore all such interrupts.
		 */
		iprint("cpu%d: spurious interrupt %d, last %d",
			m->machno, v-VectorPIC, 0 /*m->lastintr*/);
		for(i = 0; i < 32; i++){
			if(!(active.machs & (1<<i)))
				continue;
			mach = MACHP(i);
			if(m->machno == mach->machno)
				continue;
			iprint(": cpu%d: last %d", mach->machno, 0 /*mach->lastintr*/);
		}
		iprint("\n");
/*			m->spuriousintr++; */
		return;
	int vec, irq;

	irq = v->irq;
	if(irq > MaxIrqPIC) {
		print("intrenable: irq %d out of range\n", v->irq);
		return -1;
	}
	else{
		dumpregs(ur);
		panic("unknown intr: %d\n", v); /* */
	if(BUSTYPE(v->tbdf) == BusPCI) {
		vec = irq+VectorPCI;
		cserve(52, irq);
	}
}

static int
intrenable164(int v, void (*f)(Ureg*, void*), void*a, int tbdf)
{
	Irq * irq;
	Irqctl *ctl;

	lock(&irqctllock);
	if(irqctl[v] == 0){
		ctl = xalloc(sizeof(Irqctl));
/* this is all wrong; FIXME! */
		if(BUSTYPE(tbdf) == BusPCI)
			cserve(52, v-VectorPCI);
		else if(v >= VectorPIC && i8259enable(v, tbdf, ctl) == -1){
			unlock(&irqctllock);
			iprint("intrenable: didn't find v %d, tbdf 0x%uX\n", v, tbdf);
			xfree(ctl);
	else {
		vec = irq+VectorPIC;
		if(i8259enable(irq, v->tbdf, v) == -1)
			return -1;
		}
		irqctl[v] = ctl;
	}
	ctl = irqctl[v];
	irq = xalloc(sizeof(Irq));
	irq->f = f;
	irq->a = a;
	irq->next = ctl->irq;
	ctl->irq = irq;
	unlock(&irqctllock);
	return 0;
	return vec;
}

/*


@@ 405,7 331,6 @@ PCArch arch164 = {
	coredetach,
	pcicfg2117x,
	pcimem2117x,
	intr164,
	intrenable164,

	inb2117x,

M alphapc/audio.h => alphapc/audio.h +2 -2
@@ 12,5 12,5 @@ enum
#define UNCACHED(type, v)	(type*)((ulong)(v))
#define dcflush(a, b)

#define Int0vec			VectorPIC
#define setvec(v, f, a)		intrenable(v, f, a, BUSUNKNOWN)
#define Int0vec
#define setvec(v, f, a)		intrenable(v, f, a, BUSUNKNOWN, "audio")

M alphapc/dat.h => alphapc/dat.h +5 -7
@@ 1,7 1,5 @@
typedef struct Conf	Conf;
typedef struct FPsave	FPsave;
typedef struct Irq	Irq;
typedef struct Irqctl	Irqctl;
typedef struct ISAConf	ISAConf;
typedef struct Label	Label;
typedef struct Lock	Lock;


@@ 12,9 10,10 @@ typedef struct PCArch	PCArch;
typedef struct PCB	PCB;
typedef struct Pcidev	Pcidev;
typedef struct PMMU	PMMU;
typedef struct Proc	Proc;
typedef struct Sys	Sys;
typedef struct Ureg	Ureg;
typedef struct Proc	Proc;
typedef struct Vctl	Vctl;

/*
 *  parameters for sysproc.c


@@ 72,8 71,6 @@ struct Conf
	ulong	nswap;		/* number of swap pages */
	int	nswppo;		/* max # of pageouts per segment pass */
	ulong	copymode;	/* 0 is copy on write, 1 is copy on reference */
	ulong	ptebase;
	ulong	mbytes;
	int	monitor;		/* has display? */
	ulong	ialloc;		/* bytes available for interrupt time allocation */
	ulong	pipeqsize;	/* size in bytes of pipe queues */


@@ 144,6 141,7 @@ struct Mach
	Page	*ufreeme;		/* address of upage of exited process */
	int	nrdy;
	ulong	fairness;		/* for runproc */
	int	lastintr;

	ulong	cpuhz;			/* hwrpb->cfreq */
	ulong	pcclast;


@@ 155,6 153,7 @@ struct Mach
	int	syscall;
	int	load;
	int	intr;
	int	spuriousintr;
	int	flushmmu;		/* make current proc flush it's mmu state */

	PCB;


@@ 185,8 184,7 @@ struct PCArch
	void	(*coredetach)(void);		/* restore core logic before return to console */
	void	*(*pcicfg)(int, int);		/* map and point to PCI cfg space */
	void	*(*pcimem)(int, int);		/* map and point to PCI memory space */
	void	(*intr)(Ureg*);
	int	(*intrenable)(int, void (*)(Ureg*, void*), void*, int);
	int	(*intrenable)(Vctl*);

	int		(*_inb)(int);
	ushort	(*_ins)(int);

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

typedef struct IOMap IOMap;
struct IOMap
{
	IOMap	*next;
	char	tag[13];
	ulong	start;
	ulong	end;
};

static struct
{
	Lock;
	IOMap	*m;
	IOMap	*free;
	IOMap	maps[32];		// some initial free maps

	QLock	ql;			// lock for reading map
} iomap;

enum {
	Qdir,
	Qcputype,
	Qioalloc,
	Qiob,
	Qiow,
	Qiol,
	Qirqalloc,
};

static Dirtab ioallocdir[] = {
	"cputype",	{ Qcputype, 0 },	0,	0444,
	"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,
};

void
ioinit(void)
{
	int i;

	for(i = 0; i < nelem(iomap.maps)-1; i++)
		iomap.maps[i].next = &iomap.maps[i+1];
	iomap.maps[i].next = nil;
	iomap.free = iomap.maps;

	// a dummy entry at 2^16
	ioalloc(0x10000, 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.
//
int
ioalloc(int port, int size, int align, char *tag)
{
	IOMap *m, **l;
	int i;

	lock(&iomap);
	if(port < 0){
		// find a free port above 0x400 and below 0x1000
		port = 0x400;
		for(l = &iomap.m; *l; l = &(*l)->next){
			m = *l;
			i = m->start - port;
			if(i > size)
				break;
			if(align > 0)
				port = ((port+align-1)/align)*align;
			else
				port = m->end;
		}
		if(*l == nil){
			unlock(&iomap);
			return -1;
		}
	} else {
		// see if the space clashes with previously allocated ports
		for(l = &iomap.m; *l; l = &(*l)->next){
			m = *l;
			if(m->end <= port)
				continue;
			if(m->start >= port+size)
				break;
			unlock(&iomap);
			return -1;
		}
	}
	m = iomap.free;
	if(m == nil){
		print("ioalloc: out of maps");
		unlock(&iomap);
		return port;
	}
	iomap.free = m->next;
	m->next = *l;
	m->start = port;
	m->end = port + size;
	strncpy(m->tag, tag, sizeof(m->tag));
	m->tag[sizeof(m->tag)-1] = 0;
	*l = m;

	ioallocdir[0].qid.vers++;

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

void
iofree(int port)
{
	IOMap *m, **l;

	lock(&iomap);
	for(l = &iomap.m; *l; l = &(*l)->next){
		if((*l)->start == port){
			m = *l;
			*l = m->next;
			m->next = iomap.free;
			iomap.free = m;
			break;
		}
		if((*l)->start > port)
			break;
	}
	ioallocdir[0].qid.vers++;
	unlock(&iomap);
}

int
iounused(int start, int end)
{
	IOMap *m;

	for(m = iomap.m; m; m = m->next){
		if(start >= m->start && start < m->end
		|| start <= m->start && end > m->start)
			return 0; 
	}
	return 1;
}

static void
checkport(int start, int end)
{
	/* standard vga regs are OK */
	if(start >= 0x2b0 && end <= 0x2df+1)
		return;
	if(start >= 0x3c0 && end <= 0x3da+1)
		return;

	if(iounused(start, end))
		return;
	error(Eperm);
}

static Chan*
archattach(char* spec)
{
	return devattach('P', spec);
}

int
archwalk(Chan* c, char* name)
{
	return devwalk(c, name, ioallocdir, nelem(ioallocdir), devgen);
}

static void
archstat(Chan* c, char* dp)
{
	devstat(c, dp, ioallocdir, nelem(ioallocdir), devgen);
}

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

static void
archclose(Chan*)
{
}

enum
{
	Linelen= 31,
};

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

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

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

	case Qiob:
		port = offset;
		checkport(offset, offset+n);
		for(p = a; port < offset+n; port++)
			*p++ = inb(port);
		return n;

	case Qiow:
		if((n & 0x01) || (offset & 0x01))
			error(Ebadarg);
		checkport(offset, offset+n+1);
		n /= 2;
		sp = a;
		for(port = offset; port < offset+n; port += 2)
			*sp++ = ins(port);
		return n*2;

	case Qiol:
		if((n & 0x03) || (offset & 0x03))
			error(Ebadarg);
		checkport(offset, offset+n+3);
		n /= 4;
		lp = a;
		for(port = offset; port < offset+n; port += 4)
			*lp++ = inl(port);
		return n*4;

	case Qioalloc:
		break;

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

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

	default:
		error(Eperm);
		break;
	}

	offset = offset/Linelen;
	n = n/Linelen;
	p = a;
	lock(&iomap);
	for(m = iomap.m; n > 0 && m != nil; m = m->next){
		if(offset-- > 0)
			continue;
		if(strcmp(m->tag, "dummy") == 0)
			break;
		sprint(buf, "%8lux %8lux %-12.12s\n", m->start, m->end-1, m->tag);
		memmove(p, buf, Linelen);
		p += Linelen;
		n--;
	}
	unlock(&iomap);

	return p - (char*)a;
}

static long
archwrite(Chan *c, void *a, long n, vlong offset)
{
	int port;
	ushort *sp;
	ulong *lp;
	char *p;

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

	case Qiob:
		p = a;
		checkport(offset, offset+n);
		for(port = offset; port < offset+n; port++)
			outb(port, *p++);
		return n;

	case Qiow:
		if((n & 01) || (offset & 01))
			error(Ebadarg);
		checkport(offset, offset+n+1);
		n /= 2;
		sp = a;
		for(port = offset; port < offset+n; port += 2)
			outs(port, *sp++);
		return n*2;

	case Qiol:
		if((n & 0x03) || (offset & 0x03))
			error(Ebadarg);
		checkport(offset, offset+n+3);
		n /= 4;
		lp = a;
		for(port = offset; port < offset+n; port += 4)
			outl(port, *lp++);
		return n*4;

	default:
		error(Eperm);
		break;
	}
	return 0;
}

Dev archdevtab = {
	'P',
	"arch",

	devreset,
	devinit,
	archattach,
	devclone,
	archwalk,
	archstat,
	archopen,
	devcreate,
	archclose,
	archread,
	devbread,
	archwrite,
	devbwrite,
	devremove,
	devwstat,
};

PCArch* arch;
extern PCArch* knownarch[];

PCArch archgeneric = {
	"generic",				/* id */
	0,					/* ident */

	0,					/* coreinit */
	0,					/* coredetach */
};

static char	*sysnames[] =
{
// [26]		"EB164",
[26]		"AlphaPC 164",
};

static char	*cpunames[] =
{
[7]		"21164A",
};

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;
	Hwcpu *cpu;
	Hwdsr *dsr;
	char *s;

	print("\n");

	if (hwrpb->rev >= 6) {
		dsr = (Hwdsr*)((ulong)hwrpb + hwrpb->dsroff);

		s = (char*)dsr + dsr->sysnameoff + 8;
		print("%s\n", s);
	}
	else {
		s = "<unknown>";
		if (hwrpb->systype < nelem(sysnames))
			s = sysnames[hwrpb->systype];
		print("DEC %s (%llux, %llux, %llux)\n", s, hwrpb->systype, hwrpb->sysvar, hwrpb->sysrev);
	}

	for (i = 0; i < hwrpb->ncpu; i++) {
		cpu = (Hwcpu*) ((ulong)hwrpb + hwrpb->cpuoff + i*hwrpb->cpulen);
		s = "<unknown>";
		maj = (ulong)cpu->cputype;
		min = (ulong)(cpu->cputype>>32);
		if (maj < nelem(cpunames))
			s = cpunames[maj];
		print("cpu%d: %s-%d (%d.%d, %llux, %llux)\n",
			i, s, min, maj, min, cpu->cpuvar, cpu->cpurev);
	}

	print("\n");
}

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

	mhz = (m->cpuhz+999999)/1000000;
	cpu = (Hwcpu*) ((ulong)hwrpb + hwrpb->cpuoff);
	cputype = "unknown";
	maj = (ulong)cpu->cputype;
	if (maj < nelem(cpunames))
		cputype = cpunames[maj];

	snprint(str, sizeof(str), "%s %lud\n", cputype, mhz);
	return readstr(offset, a, n, str);
}

M alphapc/devether.c => alphapc/devether.c +30 -16
@@ 130,11 130,11 @@ etherrtrace(Netfile* f, Etherpkt* pkt, int len)
}

Block*
etheriq(Ether* ether, Block* bp, int freebp)
etheriq(Ether* ether, Block* bp, int fromwire)
{
	Etherpkt *pkt;
	ushort type;
	int len;
	int len, multi, tome, fromme;
	Netfile **ep, *f, **fp, *fx;
	Block *xbp;



@@ 146,10 146,11 @@ etheriq(Ether* ether, Block* bp, int freebp)
	fx = 0;
	ep = &ether->f[Ntypes];

	multi = pkt->d[0] & 1;
	/* check for valid multcast addresses */
	if((pkt->d[0] & 1) && memcmp(pkt->d, ether->bcast, sizeof(pkt->d)) && ether->prom == 0){
	if(multi && memcmp(pkt->d, ether->bcast, sizeof(pkt->d)) && ether->prom == 0){
		if(!activemulti(ether, pkt->d, sizeof(pkt->d))){
			if(freebp){
			if(fromwire){
				freeb(bp);
				bp = 0;
			}


@@ 157,16 158,25 @@ etheriq(Ether* ether, Block* bp, int freebp)
		}
	}

	/* is it for me? */
	tome = memcmp(pkt->d, ether->ea, sizeof(pkt->d)) == 0;
	fromme = memcmp(pkt->s, ether->ea, sizeof(pkt->s)) == 0;

	/*
	 * Multiplex the packet to all the connections which want it.
	 * If the packet is not to be used subsequently (freebp != 0),
	 * If the packet is not to be used subsequently (fromwire != 0),
	 * attempt to simply pass it into one of the connections, thereby
	 * saving a copy of the data (usual case hopefully).
	 */
	for(fp = ether->f; fp < ep; fp++){
		if((f = *fp) && (f->type == type || f->type < 0)){
			if(f->type > -2){
				if(freebp && fx == 0)
		if(f = *fp)
		if(f->type == type || f->type < 0)
		if(tome || multi || f->prom){
			/* Don't want to hear bridged packets */
			if(f->bridge && !fromwire && !fromme)
				continue;
			if(!f->headersonly){
				if(fromwire && fx == 0)
					fx = f;
				else if(xbp = iallocb(len)){
					memmove(xbp->wp, pkt, len);


@@ 182,10 192,11 @@ etheriq(Ether* ether, Block* bp, int freebp)
	}

	if(fx){
		qpass(fx->in, bp);
		if(qpass(fx->in, bp) < 0)
			ether->soverflows++;
		return 0;
	}
	if(freebp){
	if(fromwire){
		freeb(bp);
		return 0;
	}


@@ 207,20 218,23 @@ etheroq(Ether* ether, Block* bp)
	 * in promiscuous mode.
	 * If it's a loopback packet indicate to etheriq that the data isn't
	 * needed and return, etheriq will pass-on or free the block.
	 * To enable bridging to work, only packets that were originated
	 * by this interface are fed back.
	 */
	pkt = (Etherpkt*)bp->rp;
	len = BLEN(bp);
	loopback = (memcmp(pkt->d, ether->ea, sizeof(pkt->d)) == 0);
	loopback = memcmp(pkt->d, ether->ea, sizeof(pkt->d)) == 0;
	if(loopback || memcmp(pkt->d, ether->bcast, sizeof(pkt->d)) == 0 || ether->prom){
		s = splhi();
		etheriq(ether, bp, loopback);
		etheriq(ether, bp, 0);
		splx(s);
	}

	if(!loopback){
		qbwrite(ether->oq, bp);
		ether->transmit(ether);
	}
	} else
		freeb(bp);

	return len;
}


@@ 354,9 368,10 @@ etherreset(void)
			 */
			if(ether->irq == 2)
				ether->irq = 9;
			intrenable(VectorPCI+ether->irq, ether->interrupt, ether, ether->tbdf);
			snprint(name, sizeof(name), "ether%d", ctlrno);
			intrenable(ether->irq, ether->interrupt, ether, ether->tbdf, name);

			i = sprint(buf, "#l%d: %s: %dMbps port 0x%luX irq %ld",
			i = sprint(buf, "#l%d: %s: %dMbps port 0x%luX irq %lud",
				ctlrno, ether->type, ether->mbps, ether->port, ether->irq);
			if(ether->mem)
				i += sprint(buf+i, " addr 0x%luX", PADDR(ether->mem));


@@ 368,7 383,6 @@ etherreset(void)
			sprint(buf+i, "\n");
			print(buf);

			snprint(name, sizeof(name), "ether%d", ctlrno);
			if(ether->mbps == 100){
				netifinit(ether, name, Ntypes, 256*1024);
				if(ether->oq == 0)

M alphapc/devvga.c => alphapc/devvga.c +126 -77
@@ 14,24 14,27 @@
#include <cursor.h>
#include "screen.h"

extern uchar	*vgabios;

enum {
	Qdir,
	Qvgaiob,
	Qvgaiow,
	Qvgaiol,
	Qvgactl,
	Qvgabios,
};

static Dirtab vgadir[] = {
	"vgaiob",	{ Qvgaiob, 0 },		0,	0660,
	"vgaiow",	{ Qvgaiow, 0 },		0,	0660,
	"vgaiol",	{ Qvgaiol, 0 },		0,	0660,
	"vgactl",	{ Qvgactl, 0 },		0,	0660,
	"vgabios",	{ Qvgabios, 0 },		0x10000,	0440,
};

static void
vgareset(void)
{
	/* reserve the 'standard' vga registers */
	if(ioalloc(0x2b0, 0x2df-0x2b0+1, 0, "vga") < 0)
		panic("vga ports already allocated"); 
	if(ioalloc(0x3c0, 0x3da-0x3c0+1, 0, "vga") < 0)
		panic("vga ports already allocated"); 
	conf.monitor = 1;
}



@@ 69,10 72,8 @@ vgaclose(Chan*)
static long
vgaread(Chan* c, void* a, long n, vlong off)
{
	int len, port;
	int len;
	char *p, *s;
	ushort *sp;
	ulong *lp;
	VGAscr *scr;
	ulong offset = off;



@@ 93,21 94,21 @@ vgaread(Chan* c, void* a, long n, vlong off)
			s = scr->dev->name;
		else
			s = "cga";
		len = snprint(p, READSTR, "type %s\n", s);
		len = snprint(p, READSTR, "type: %s\n", s);
		if(scr->gscreen)
			len += snprint(p+len, READSTR-len, "size %dx%dx%d\n",
			len += snprint(p+len, READSTR-len, "size: %dx%dx%d\n",
				scr->gscreen->r.max.x, scr->gscreen->r.max.y,
				1<<scr->gscreen->ldepth);
				scr->gscreen->depth);
		if(scr->cur)
			s = scr->cur->name;
		else
			s = "off";
		len += snprint(p+len, READSTR-len, "hwgc %s\n", s);
		len += snprint(p+len, READSTR-len, "hwgc: %s\n", s);
		if(scr->pciaddr)
			snprint(p+len, READSTR-len, "addr 0x%lux\n",
			snprint(p+len, READSTR-len, "addr: 0x%lux\n",
				scr->pciaddr);
		else
			snprint(p+len, READSTR-len, "addr 0x%lux\n",
			snprint(p+len, READSTR-len, "addr: 0x%lux\n",
				scr->aperture);

		n = readstr(offset, a, n, p);


@@ 116,30 117,18 @@ vgaread(Chan* c, void* a, long n, vlong off)

		return n;

	case Qvgaiob:
		port = offset;
		for(p = a; port < offset+n; port++)
			*p++ = inb(port);
	case Qvgabios:
		if(vgabios == nil)
			error(Egreg);
		if(offset&0x80000000)
			offset &= ~0x800E0000;
		if(offset+n > 0x10000)
			n = 0x10000-offset;
		if(n < 0)
			return 0;
		memmove(a, vgabios+offset, n);
		return n;

	case Qvgaiow:
		if((n & 0x01) || (offset & 0x01))
			error(Ebadarg);
		n /= 2;
		sp = a;
		for(port = offset; port < offset+n; port += 2)
			*sp++ = ins(port);
		return n*2;

	case Qvgaiol:
		if((n & 0x03) || (offset & 0x03))
			error(Ebadarg);
		n /= 4;
		lp = a;
		for(port = offset; port < offset+n; port += 4)
			*lp++ = inl(port);
		return n*4;

	default:
		error(Egreg);
		break;


@@ 148,23 137,32 @@ vgaread(Chan* c, void* a, long n, vlong off)
	return 0;
}

static char Ebusy[] = "vga already configured";

static void
vgactl(char* a)
{
	int align, i, n, size, x, y, z;
	char *field[4], *p;
	char *chanstr, *field[6], *p;
	ulong chan;
	VGAscr *scr;
	extern VGAdev *vgadev[];
	extern VGAcur *vgacur[];
	Rectangle r;

	n = getfields(a, field, 4, 1, " ");
	if(n < 2)
	n = getfields(a, field, nelem(field), 1, " ");
	if(n < 1)
		error(Ebadarg);

	scr = &vgascreen[0];
	if(strcmp(field[0], "hwgc") == 0){
		if(n < 2)
			error(Ebadarg);

		/* BUG: drawinit should become a different message rather than piggybacking */
		if(scr && scr->dev && scr->dev->drawinit)
			scr->dev->drawinit(scr);

		if(strcmp(field[1], "off") == 0){
			lock(&cursor);
			if(scr->cur){


@@ 205,8 203,11 @@ vgactl(char* a)
		}
	}
	else if(strcmp(field[0], "size") == 0){
		if(n < 2)
		if(n < 3)
			error(Ebadarg);
		if(drawhasclients())
			error(Ebusy);

		x = strtoul(field[1], &p, 0);
		if(x == 0 || x > 2048)
			error(Ebadarg);


@@ 219,23 220,76 @@ vgactl(char* a)
		if(*p)
			p++;

		switch(strtoul(p, &p, 0)){
		case 8:
			z = 3;
			break;
		z = strtoul(p, &p, 0);

		default:
			z = 0;
			error(Ebadarg);
		}
		chanstr = field[2];
		if((chan = strtochan(chanstr)) == 0)
			error("bad channel");

		if(chantodepth(chan) != z)
			error("depth, channel do not match");

		cursoroff(1);
		if(screensize(x, y, z))
		deletescreenimage();
		if(screensize(x, y, z, chan))
			error(Egreg);
		vgascreenwin(scr);
		cursoron(1);
		return;
	}
	else if(strcmp(field[0], "actualsize") == 0){
		if(scr->gscreen == nil)
			error("set the screen size first");

		if(n < 2)
			error(Ebadarg);
		x = strtoul(field[1], &p, 0);
		if(x == 0 || x > 2048)
			error(Ebadarg);
		if(*p)
			p++;

		y = strtoul(p, nil, 0);
		if(y == 0 || y > 2048)
			error(Ebadarg);

		if(x > scr->gscreen->r.max.x || y > scr->gscreen->r.max.y)
			error("physical screen bigger than virtual");

		r = Rect(0,0,x,y);
		if(!eqrect(r, scr->gscreen->r)){
			if(scr->cur == nil || scr->cur->doespanning == 0)
				error("virtual screen not supported");
		}

		physgscreenr = r;
		return;
	}
	else if(strcmp(field[0], "palettedepth") == 0){
		if(n < 2)
			error(Ebadarg);

		x = strtoul(field[1], &p, 0);
		if(x != 8 && x != 6)
			error(Ebadarg);

		scr->palettedepth = x;
		return;
	}
	else if(strcmp(field[0], "drawinit") == 0){
		/*
		 * This is a separate message, but first we need to make
		 * aux/vga send it; once everyone has the new vga, we
		 * can take the drawinit stuff out of hwgc.
		 */

		/*
		if(scr && scr->dev && scr->dev->drawinit)
			scr->dev->drawinit(scr);
		*/

		return;
	}
	else if(strcmp(field[0], "linear") == 0){
		if(n < 2)
			error(Ebadarg);


@@ 249,6 303,28 @@ vgactl(char* a)
			error("not enough free address space");
		return;
	}
/*	else if(strcmp(field[0], "memset") == 0){
		if(n < 4)
			error(Ebadarg);
		memset((void*)strtoul(field[1], 0, 0), atoi(field[2]), atoi(field[3]));
		return;
	}
*/
	else if(strcmp(field[0], "blank") == 0){
		if(n < 2)
			error(Ebadarg);
		drawblankscreen(atoi(field[1]));
		return;
	}
	else if(strcmp(field[0], "hwaccel") == 0){
		if(n < 2)
			error(Ebadarg);
		if(strcmp(field[1], "on") == 0)
			hwaccel = 1;
		else if(strcmp(field[1], "off") == 0)
			hwaccel = 0;
		return;
	}

	error(Ebadarg);
}


@@ 256,10 332,7 @@ vgactl(char* a)
static long
vgawrite(Chan* c, void* a, long n, vlong off)
{
	int port;
	char *p;
	ushort *sp;
	ulong *lp;
	ulong offset = off;

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


@@ 282,30 355,6 @@ vgawrite(Chan* c, void* a, long n, vlong off)
		free(p);
		return n;

	case Qvgaiob:
		p = a;
		for(port = offset; port < offset+n; port++)
			outb(port, *p++);
		return n;

	case Qvgaiow:
		if((n & 01) || (offset & 01))
			error(Ebadarg);
		n /= 2;
		sp = a;
		for(port = offset; port < offset+n; port += 2)
			outs(port, *sp++);
		return n*2;

	case Qvgaiol:
		if((n & 0x03) || (offset & 0x03))
			error(Ebadarg);
		n /= 4;
		lp = a;
		for(port = offset; port < offset+n; port += 4)
			outl(port, *lp++);
		return n*4;

	default:
		error(Egreg);
		break;

M alphapc/dma.c => alphapc/dma.c +4 -0
@@ 96,6 96,10 @@ dmainit(int chan, int maxtransfer)
	static int once;

	if(once == 0){
		if(ioalloc(0x00, 0x10, 0, "dma") < 0
		|| ioalloc(0x80, 0x10, 0, "dma") < 0
		|| ioalloc(0xd0, 0x10, 0, "dma") < 0)
			panic("dmainit");
		outb(dma[0].mc, 0);
		outb(dma[1].mc, 0);
		outb(dma[0].cmask, 0);

M alphapc/ether2114x.c => alphapc/ether2114x.c +6 -1
@@ 1297,6 1297,12 @@ dec2114xpci(void)
		ctlr->port = p->mem[0].bar & ~0x01;
		ctlr->pcidev = p;

		if(ioalloc(ctlr->port, p->mem[0].size, 0, "dec2114x") < 0){
			print("dec2114x: port %d in use\n", ctlr->port);
			free(ctlr);
			continue;
		}

		/*
		 * Some cards (e.g. ANA-6910FX) seem to need the Ps bit
		 * set or they don't always work right after a hardware


@@ 1326,7 1332,6 @@ reset(Ether* ether)
	uchar ea[Eaddrlen];
	static int scandone;

pcihinv(nil);
	if(scandone == 0){
		dec2114xpci();
		scandone = 1;

M alphapc/floppy.h => alphapc/floppy.h +8 -1
@@ 136,6 136,13 @@ pcfloppyintr(Ureg *ur, void *a)
void
floppysetup0(FController *fl)
{
	fl->ndrive = 0;
	if(ioalloc(Psra, 6, 0, "floppy") < 0)
		return;
	if(ioalloc(Pdir, 1, 0, "floppy") < 0){
		iofree(Psra);
		return;
	}
	fl->ndrive = 1;
}



@@ 151,7 158,7 @@ floppysetup1(FController *fl)
		floppysetdef(&fl->d[1]);
	}

	intrenable(VectorPIC+IrqFLOPPY, pcfloppyintr, fl, BUSUNKNOWN);
	intrenable(IrqFLOPPY, pcfloppyintr, fl, BUSUNKNOWN, "floppy");
}

/*

M alphapc/fns.h => alphapc/fns.h +10 -2
@@ 26,6 26,7 @@ void		firmware(void);
#define	flushpage(s)	icflush()
void		fpenab(int);
void		fptrap(Ureg*);
int		getcfields(char*, char**, int, char*);
char		*getconf(char*);
ulong	getfcr(void);
ulong	getstatus(void);


@@ 34,13 35,17 @@ int		i8042auxcmd(int);
void		i8042auxenable(void (*)(int, int));
void		i8042reset(void);
void		i8259init(void);
int		i8259enable(int, int, Irqctl*);
int		i8259enable(int, int, Vctl*);
#define	idlehands()			/* nothing to do in the runproc */
void		icflush(void);
void		illegal0(void);
void		intr0(void);
void		intrenable(int, void (*)(Ureg*, void*), void*, int);
void		intrenable(int, void (*)(Ureg*, void*), void*, int, char*);
int		ioalloc(int, int, int, char*);
void		iofree(int);
void		ioinit(void);
int		iprint(char*, ...);
int		irqallocread(char*, long, vlong);
int		isaconfig(char*, int, ISAConf*);
void		kbdinit(void);
void		*kmapv(uvlong, int);


@@ 49,6 54,7 @@ void		launchinit(void);
void		launch(int);
void		links(void);
void		mb(void);
void 		memholes(void);
ulong 	meminit(void);
void		mmuinit(void);
#define	mmunewpage(x)


@@ 83,6 89,8 @@ void		tlbflush(int, ulong);
void		touser(void*);
void		trapinit(void);
void		unaligned(void);
ulong	upamalloc(ulong, int, int);
void	upafree(ulong, int);
void		wrent(int, void*);
void		wrvptptr(uvlong);


M alphapc/i8259.c => alphapc/i8259.c +8 -7
@@ 35,6 35,8 @@ i8259init(void)
{
	int /*elcr1, */ x;

	ioalloc(Int0ctl, 2, 0, "i8259.0");
	ioalloc(Int1ctl, 2, 0, "i8259.1");
	int0mask = 0xFF;
	int1mask = 0xFF;



@@ 121,13 123,12 @@ i8259isr(int v)
}

int
i8259enable(int v, int, Irqctl* irqctl)
i8259enable(int v, int, Vctl* vctl)
{
	if(v < VectorPIC || v > MaxVectorPIC){
		iprint("i8259enable: vector %d out of range\n", v);
	if(v > MaxIrqPIC){
		print("i8259enable: vector %d out of range\n", v);
		return -1;
	}
	v -= VectorPIC;

	/*
	 *  enable corresponding interrupt in 8259


@@ 142,10 143,10 @@ i8259enable(int v, int, Irqctl* irqctl)
	}

	if(elcr & (1<<v))
		irqctl->eoi = i8259isr;
		vctl->eoi = i8259isr;
	else
		irqctl->isr = i8259isr;
	irqctl->isintr = 1;
		vctl->isr = i8259isr;
	vctl->isintr = 1;

	return v;
}

M alphapc/io.h => alphapc/io.h +12 -25
@@ 5,7 5,6 @@ enum {
};

enum {
/*	VectorPIC	= 32,		/* external i8259 interrupts */
	IrqCLOCK	= 0,
	IrqKBD		= 1,
	IrqUART1	= 3,


@@ 19,37 18,24 @@ enum {
	IrqATA0		= 14,
	MaxIrqPIC	= 15,

/* deprecated: */
	VectorPIC	= 128,		/* external [A]PIC interrupts */
	VectorCLOCK	= VectorPIC+0,
	VectorKBD	= VectorPIC+1,
	VectorUART1	= VectorPIC+3,
	VectorUART0	= VectorPIC+4,
	VectorPCMCIA	= VectorPIC+5,
	VectorFLOPPY	= VectorPIC+6,
	VectorLPT	= VectorPIC+7,
	VectorIRQ7	= VectorPIC+7,
	VectorAUX	= VectorPIC+12,	/* PS/2 port */
	VectorIRQ13	= VectorPIC+13,	/* coprocessor on x386 */
	VectorATA0	= VectorPIC+14,
	MaxVectorPIC	= VectorPIC+15,
	VectorPIC	= 64,
	MaxVectorPIC	= VectorPIC+MaxIrqPIC,
	VectorPCI	= 16,		/* PCI bus (PLD) */
};

typedef struct Irq {
	void	(*f)(Ureg*, void*);	/* handler to call */
	void*	a;			/* argument to call it with */

	Irq*	next;			/* link to next handler */
} Irq;
typedef struct Vctl {
	Vctl*	next;			/* handlers on this vector */

typedef struct Irqctl {
	char	name[NAMELEN];	/* of driver */
	int	isintr;			/* interrupt or fault/trap */
	int	irq;
	int	tbdf;
	int	(*isr)(int);		/* get isr bit for this irq */
	int	(*eoi)(int);		/* eoi */
	int	isintr;

	Irq*	irq;			/* handlers on this IRQ */
} Irqctl;
	void	(*f)(Ureg*, void*);	/* handler to call */
	void*	a;			/* argument to call it with */
} Vctl;

enum {
	BusCBUS		= 0,		/* Corollary CBUS */


@@ 105,6 91,7 @@ enum {					/* type 0 and type 1 pre-defined header */

	PciBAR0		= 0x10,		/* base address */
	PciBAR1		= 0x14,
	PciROM		= 0x30,

	PciINTL		= 0x3C,		/* interrupt line */
	PciINTP		= 0x3D,		/* interrupt pin */

M alphapc/kbd.c => alphapc/kbd.c +26 -2
@@ 389,10 389,30 @@ i8042auxenable(void (*putc)(int, int))
		return;
	}
	auxputc = putc;
	intrenable(VectorAUX, i8042intr, 0, BUSUNKNOWN);
	intrenable(IrqAUX, i8042intr, 0, BUSUNKNOWN, "kbdaux");
	iunlock(&i8042lock);
}

static void
setscan(int code)
{
	char *err = "setscan: set scan code failed\n";

	outb(Data, 0xF0);
	if(inready() < 0 || inb(Data) != 0xFA || outready() < 0) {
		print(err);
		return;
	}
	outb(Data, code);
	if(inready() < 0) {
		print(err);
		return;
	}
	inb(Data);
	if(outready() < 0)
		print(err);
}

void
kbdinit(void)
{


@@ 403,7 423,10 @@ kbdinit(void)
		panic("kbdinit");
	qnoblock(kbdq, 1);

	intrenable(VectorKBD, i8042intr, 0, BUSUNKNOWN);
	ioalloc(Data, 1, 0, "kbd");
	ioalloc(Cmd, 1, 0, "kbd");

	intrenable(IrqKBD, i8042intr, 0, BUSUNKNOWN, "kbd");

	/* wait for a quiescent controller */
	while((c = inb(Status)) & (Outbusy | Inready))


@@ 429,4 452,5 @@ kbdinit(void)
		print("kbd init failed\n");
	outb(Data, ccc);
	outready();
	setscan(0x02);
}

M alphapc/main.c => alphapc/main.c +181 -49
@@ 17,6 17,37 @@ Conf	conf;
FPsave	initfp;
uvlong initfpcr = 0x2800800000000000LL;

char bootargs[BOOTARGSLEN];
char *confname[MAXCONF];
char *confval[MAXCONF];
int	nconf;

static void
options(void)
{
	char *cp, *line[MAXCONF];
	int i, n;

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

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

void
main(void)
{


@@ 24,12 55,15 @@ main(void)
	hwrpb = (Hwrpb*)(KZERO|hwrpb->phys);
	arginit();
	machinit();
	ioinit();
	options();
	clockinit();
	confinit();
	archinit();
	mmuinit();
	xinit();
	if (arch->coreinit)
	memholes();
	mmuinit();
	if(arch->coreinit)
		arch->coreinit();
	trapinit();
	screeninit();


@@ 41,7 75,7 @@ main(void)
	kbdinit();

	cpuidprint();
	if (arch->corehello)
	if(arch->corehello)
		arch->corehello();

#ifdef	NEVER


@@ 87,6 121,7 @@ machinit(void)
void
init0(void)
{
	int i;
	char buf[2*NAMELEN];

	spllo();


@@ 102,9 137,16 @@ init0(void)

	if(!waserror()){
		ksetenv("cputype", "alpha");
		sprint(buf, "alpha %s axp", conffile);
		sprint(buf, "alpha %s alphapc", conffile);
		ksetenv("terminal", buf);
		ksetenv("sysname", sysname);
		if(cpuserver)
			ksetenv("service", "cpu");
		else
			ksetenv("service", "terminal");
		for(i = 0; i < nconf; i++)
			if(confname[i] && confname[i][0] != '*')
				ksetenv(confname[i], confval[i]);
		poperror();
	}



@@ 223,7 265,7 @@ exit(int)

	splhi();
	delay(1000);	/* give serial fifo time to finish flushing */
	if (arch->coredetach)
	if(arch->coredetach)
		arch->coredetach();
	firmware();
}


@@ 231,55 273,145 @@ exit(int)
void
confinit(void)
{
	long mbytes;
	int mul;
	ulong ktop;
	ulong ktop, kpages;
	Bank *b, *eb;
	extern void _main(void);
	int userpcnt;
	char *p;

	if(p = getconf("*kernelpercent"))
		userpcnt = 100 - strtol(p, 0, 0);
	else
		userpcnt = 0;

	mbytes = 50;	/* BUG FIXME */
	/*
	 * The console firmware divides memory into 1 or more banks.
	 * FInd the bank with the kernel in it.
	 */
	b = bootconf->bank;
	eb = b+bootconf->nbank;
	ktop = PGROUND((ulong)end);
	ktop = PADDR(ktop);
	while(b < eb) {
		if(b->min < ktop && ktop < b->max)
			break;
		b++;
	}
	if(b == eb)
		panic("confinit");

	/*
	 * This split of memory into 2 banks fools the allocator into
	 * allocating low memory pages from bank 0 for the ethernet since
	 * it has only a 24bit address counter.
	 * Note that the rom monitor has the bottom 2 megs
	 * Split the bank of memory into 2 banks to fool the allocator into
	 * allocating low memory pages from bank 0 for any peripherals
	 * which only have a 24bit address counter.
	 */
	conf.npage0 = (8*1024*1024)/BY2PG;
	conf.base0 = 0;

	conf.npage1 = (mbytes-8)*1024/8;
	conf.npage1 = (b->max-8*1024*1024)/BY2PG;
	conf.base1 = 8*1024*1024;

	conf.npage = conf.npage0+conf.npage1;
	conf.upages = (conf.npage*70)/100;

	ktop = PGROUND((ulong)end);
	conf.ptebase = ktop;
	ktop = PADDR(ktop);
	ktop += ((mbytes+7)/8 + 2)*BY2PG;		/* space for kernel ptes */
	conf.npage0 -= ktop/BY2PG;
	conf.base0 += ktop;
	conf.mbytes = mbytes;
	conf.ialloc = ((conf.npage-conf.upages)/2)*BY2PG;

	mul = (mbytes+11)/12;
	if(mul > 2)
		mul = 2;
	/*
	 * Fix up the bank we found to be the remnant, below the kernel.
	 * This, and the other banks, will be passed to xhole() later.
	 * BUG: conf.upages needs to be adjusted, but how?  In practice,
	 * we only have 1 bank, and the remnant is small.
	 */
	b->max = (uvlong)_main & ~(BY2PG-1);

	conf.nmach = 1;
	conf.nproc = 20 + 50*mul;
	conf.nproc = 100 + ((conf.npage*BY2PG)/MB)*5;
	if(cpuserver)
		conf.nproc *= 3;
	if(conf.nproc > 2000)
		conf.nproc = 2000;
	conf.nimage = 200;
	conf.nswap = conf.nproc*80;
	conf.nimage = 50;
	conf.nswppo = 4096;
	conf.copymode = 0;			/* copy on write */

	if(cpuserver)
		conf.nproc = 500;
	if(cpuserver) {
		if(userpcnt < 10)
			userpcnt = 70;
		kpages = conf.npage - (conf.npage*userpcnt)/100;

		/*
		 * Hack for the big boys. Only good while physmem < 4GB.
		 * Give the kernel a max. of 16MB + enough to allocate the
		 * page pool.
		 * This is an overestimate as conf.upages < conf.npages.
		 * The patch of nimage is a band-aid, scanning the whole
		 * page list in imagereclaim just takes too long.
		 */
		if(kpages > (16*MB + conf.npage*sizeof(Page))/BY2PG){
			kpages = (16*MB + conf.npage*sizeof(Page))/BY2PG;
			conf.nimage = 2000;
			kpages += (conf.nproc*KSTACK)/BY2PG;
		}
	} else {
		if(userpcnt < 10) {
			if(conf.npage*BY2PG < 16*MB)
				userpcnt = 40;
			else
				userpcnt = 60;
		}
		kpages = conf.npage - (conf.npage*userpcnt)/100;

		/*
		 * Make sure terminals with low memory get at least
		 * 4MB on the first Image chunk allocation.
		 */
		if(conf.npage*BY2PG < 16*MB)
			imagmem->minarena = 4*1024*1024;
	}
	conf.upages = conf.npage - kpages;
	conf.ialloc = (kpages/2)*BY2PG;

	/*
	 * Guess how much is taken by the large permanent
	 * datastructures. Mntcache and Mntrpc are not accounted for
	 * (probably ~300KB).
	 */
	kpages *= BY2PG;
	kpages -= conf.upages*sizeof(Page)
		+ conf.nproc*sizeof(Proc)
		+ conf.nimage*sizeof(Image)
		+ conf.nswap
		+ conf.nswppo*sizeof(Page);
	mainmem->maxsize = kpages;
	if(!cpuserver){
		/*
		 * give terminals lots of image memory, too; the dynamic
		 * allocation will balance the load properly, hopefully.
		 * be careful with 32-bit overflow.
		 */
		imagmem->maxsize = kpages;
	}

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

void
lights(int l)
memholes(void)
{
	USED(l);
	Bank *b, *eb;
	
	b = bootconf->bank;
	eb = b+bootconf->nbank;
	while(b < eb) {
		if(b->min < (1LL<<32) && b->max < (1LL<<32))
			xhole(b->min, b->max-b->min);
		b++;
	}
}

char *sp;

char *


@@ 304,27 436,6 @@ arginit(void)
	*av = 0;
}

/*
 * Q&D fake-out of plan9.ini until we resolve the booting issues
 */
char *confname[] =
{
	"ether0",
	"scsi0",
	"audio0",
	"ether1",
};

char *confval[] =
{
	"type=2114x",
	"type=ata",
	"type=sb16",
	"type=2114x",
};

int	nconf = nelem(confname);

char *
getconf(char *name)
{


@@ 439,3 550,24 @@ cistrncmp(char *a, char *b, int n)

	return 0;
}

int
getcfields(char* lp, char** fields, int n, char* sep)
{
	int i;

	for(i = 0; lp && *lp && i < n; i++){
		while(*lp && strchr(sep, *lp) != 0)
			*lp++ = 0;
		if(*lp == 0)
			break;
		fields[i] = lp;
		while(*lp && strchr(sep, *lp) == 0){
			if(*lp == '\\' && *(lp+1) == '\n')
				*lp++ = ' ';
			lp++;
		}
	}

	return i;
}

M alphapc/mmu.c => alphapc/mmu.c +2 -2
@@ 250,7 250,7 @@ upamalloc(ulong pa, int size, int align)
}

void
upafree(...)
upafree(ulong, int)
{
	panic("upafree");
	print("upafree: virtual mapping not freed\n");
}

M alphapc/ns16552.h => alphapc/ns16552.h +6 -2
@@ 25,10 25,14 @@ ns16552install(void)
		return;
	already = 1;

	if(ioalloc(Uart0, 8, 0, "eia0") < 0)
		print("eia0: port %d in use\n", Uart0);
	ns16552setup(Uart0, UartFREQ, "eia0", Ns550);
	intrenable(VectorUART0, ns16552intrx, (void*)0, BUSUNKNOWN);
	intrenable(IrqUART0, ns16552intrx, (void*)0, BUSUNKNOWN, "eia0");
	if(ioalloc(Uart1, 8, 0, "eia1") < 0)
		print("eia1: port %d in use\n", Uart1);
	ns16552setup(Uart1, UartFREQ, "eia1", Ns550);
	intrenable(VectorUART1, ns16552intrx, (void*)0, BUSUNKNOWN);
	intrenable(IrqUART1, ns16552intrx, (void*)0, BUSUNKNOWN, "eia1");
	addclock0link(uartclock);
}


M alphapc/pci.c => alphapc/pci.c +10 -1
@@ 26,6 26,8 @@ static Pcidev* pcitail;

static int pcicfgrw32(int, int, int, int);

uchar	*vgabios;

static int
pciscan(int bno, Pcidev** list)
{


@@ 89,9 91,16 @@ pciscan(int bno, Pcidev** list)
			 */
			switch(p->ccrb){

			case 0x03:		/* display controller */
				if(vgabios == nil) {
					v = pcicfgr32(p, PciROM);
					pcicfgw32(p, PciROM, v|1);	/* enable decode */
					vgabios = kmapv(((uvlong)0x88<<32LL)|(v&~0xffff), 0x10000);
					// print("VGA BIOS %lux -> %lux\n", v, vgabios);
				}
				/* fall through */
			case 0x01:		/* mass storage controller */
			case 0x02:		/* network controller */
			case 0x03:		/* display controller */
			case 0x04:		/* multimedia device */
			case 0x07:		/* simple communication controllers */
			case 0x08:		/* base system peripherals */

M alphapc/screen.c => alphapc/screen.c +264 -63
@@ 13,26 13,14 @@
#include <cursor.h>
#include "screen.h"

static ulong onesbits = ~0;
static Memdata onesdata = {
	nil,
	&onesbits,
};
static Memimage xones = {
	{ 0, 0, 1, 1 },
	{ -100000, -100000, 100000, 100000 },
	3,
	1,
	&onesdata,
	0,
	1
};
Memimage *memones = &xones;
#define RGB2K(r,g,b)	((156763*(r)+307758*(g)+59769*(b))>>19)

Point ZP = {0, 0};

Rectangle physgscreenr;

Memdata gscreendata;
Memimage gscreen;
Memimage *gscreen;

VGAscr vgascreen[1];



@@ 51,10 39,11 @@ Cursor	arrow = {
};

int
screensize(int x, int y, int z)
screensize(int x, int y, int z, ulong chan)
{
	VGAscr *scr;

	memimageinit();
	scr = &vgascreen[0];

	/*


@@ 64,34 53,32 @@ screensize(int x, int y, int z)
	if(scr->aperture == 0){
		int width = (x*(1<<z))/BI2WD;

		gscreendata.data = xalloc(width*BY2WD*y);
		if(gscreendata.data == 0)
		gscreendata.bdata = xalloc(width*BY2WD*y);
		if(gscreendata.bdata == 0)
			error("screensize: vga soft memory");
		memset(gscreendata.data, Backgnd, width*BY2WD*y);
		memset(gscreendata.bdata, Backgnd, width*BY2WD*y);
		scr->useflush = 1;

		scr->aperture = PADDR(arch->pcimem(0xA0000, 1<<16));
		scr->apsize = 1<<16;
	}
	else
		gscreendata.data = KADDR(scr->aperture);
		gscreendata.bdata = KADDR(scr->aperture);

	gscreen.data = &gscreendata;
	gscreen.ldepth = z;
	gscreen.width = (x*(1<<gscreen.ldepth)+31)/32;
	gscreen.r.min = ZP;
	gscreen.r.max = Pt(x, y);
	gscreen.clipr = gscreen.r;
	gscreen.repl = 0;
	if(gscreen)
		freememimage(gscreen);

	scr->gscreendata = gscreen.data;
	scr->memdefont = getmemdefont();
	scr->gscreen = &gscreen;

//	memset(gscreen.data->data, Backgnd, scr->apsize);
	gscreen = allocmemimaged(Rect(0,0,x,y), chan, &gscreendata);
	vgaimageinit(chan);
	if(gscreen == nil)
		return -1;

	drawcmap(0);
	scr->palettedepth = 6;	/* default */
	scr->gscreendata = &gscreendata;
	scr->memdefont = getmemdefont();
	scr->gscreen = gscreen;

	drawcmap();
	return 0;
}



@@ 131,8 118,8 @@ screenaperture(int size, int align)
	return 0;
}

ulong*
attachscreen(Rectangle* r, int* ld, int* width, int *softscreen)
uchar*
attachscreen(Rectangle* r, ulong* chan, int* d, int* width, int *softscreen)
{
	VGAscr *scr;



@@ 141,13 128,17 @@ attachscreen(Rectangle* r, int* ld, int* width, int *softscreen)
		return nil;

	*r = scr->gscreen->r;
	*ld = scr->gscreen->ldepth;
	*chan = scr->gscreen->chan;
	*d = scr->gscreen->depth;
	*width = scr->gscreen->width;
	*softscreen = scr->useflush;

	return scr->gscreendata->data;
	return scr->gscreendata->bdata;
}

/*
 * It would be fair to say that this doesn't work for >8-bit screens.
 */
void
flushmemscreen(Rectangle r)
{


@@ 166,27 157,28 @@ flushmemscreen(Rectangle r)

	incs = scr->gscreen->width * BY2WD;

	switch(scr->gscreen->ldepth){
	switch(scr->gscreen->depth){
	default:
		len = 0;
		panic("flushmemscreen: ldepth\n");
		panic("flushmemscreen: depth\n");
		break;
	case 3:
	case 8:
		len = Dx(r);
		break;
	}
	if(len < 1)
		return;

	off = r.min.y*scr->gscreen->width*BY2WD+(r.min.x>>(3-scr->gscreen->ldepth));
	off = r.min.y*scr->gscreen->width*BY2WD+(r.min.x*scr->gscreen->depth)/8;
	page = off/scr->apsize;
	off %= scr->apsize;
	disp = KADDR(scr->aperture);
	sdisp = disp+off;
	edisp = disp+scr->apsize;

	off = r.min.y*scr->gscreen->width*BY2WD+(r.min.x>>(3-scr->gscreen->ldepth));
	sp = ((uchar*)scr->gscreendata->data) + off;
	off = r.min.y*scr->gscreen->width*BY2WD+(r.min.x*scr->gscreen->depth)/8;

	sp = scr->gscreendata->bdata + off;

	scr->dev->page(scr, page);
	for(y = r.min.y; y < r.max.y; y++) {


@@ 225,16 217,15 @@ getcolor(ulong p, ulong* pr, ulong* pg, ulong* pb)
	if(scr->gscreen == nil)
		return;

	switch(scr->gscreen->ldepth){
	switch(scr->gscreen->depth){
	default:
		x = 0x0F;
		break;
	case 3:
	case 8:
		x = 0xFF;
		break;
	}
	p &= x;
	p ^= x;

	lock(&cursor);
	*pr = scr->colormap[p][0];


@@ 244,37 235,57 @@ getcolor(ulong p, ulong* pr, ulong* pg, ulong* pb)
}

int
setpalette(ulong p, ulong r, ulong g, ulong b)
{
	VGAscr *scr;
	int d;

	scr = &vgascreen[0];
	d = scr->palettedepth;

	lock(&cursor);
	scr->colormap[p][0] = r;
	scr->colormap[p][1] = g;
	scr->colormap[p][2] = b;
	vgao(PaddrW, p);
	vgao(Pdata, r>>(32-d));
	vgao(Pdata, g>>(32-d));
	vgao(Pdata, b>>(32-d));
	unlock(&cursor);

	return ~0;
}

/*
 * On some video cards (e.g. Mach64), the palette is used as the 
 * DAC registers for >8-bit modes.  We don't want to set them when the user
 * is trying to set a colormap and the card is in one of these modes.
 */
int
setcolor(ulong p, ulong r, ulong g, ulong b)
{
	VGAscr *scr;
	ulong x;
	int x;

	scr = &vgascreen[0];
	if(scr->gscreen == nil)
		return 0;

	switch(scr->gscreen->ldepth){
	default:
	switch(scr->gscreen->depth){
	case 1:
	case 2:
	case 4:
		x = 0x0F;
		break;
	case 3:
	case 8:
		x = 0xFF;
		break;
	default:
		return 0;
	}
	p &= x;
	p ^= x;

	lock(&cursor);
	scr->colormap[p][0] = r;
	scr->colormap[p][1] = g;
	scr->colormap[p][2] = b;
	vgao(PaddrW, p);
	vgao(Pdata, r>>(32-6));
	vgao(Pdata, g>>(32-6));
	vgao(Pdata, b>>(32-6));
	unlock(&cursor);

	return ~0;
	return setpalette(p, r, g, b);
}

int


@@ 312,3 323,193 @@ setcursor(Cursor* curs)

	scr->cur->load(scr, curs);
}

static ulong
pixelbits(Memimage *i, Point pt)
{
	uchar *p;
	ulong val;
	int off, bpp, npack;

	val = 0;
	p = byteaddr(i, pt);
	switch(bpp=i->depth){
	case 1:
	case 2:
	case 4:
		npack = 8/bpp;
		off = pt.x%npack;
		val = p[0] >> bpp*(npack-1-off);
		val &= (1<<bpp)-1;
		break;
	case 8:
		val = p[0];
		break;
	case 16:
		val = p[0]|(p[1]<<8);
		break;
	case 24:
		val = p[0]|(p[1]<<8)|(p[2]<<16);
		break;
	case 32:
		val = p[0]|(p[1]<<8)|(p[2]<<16)|(p[3]<<24);
		break;
	}
	while(bpp<32){
		val |= val<<bpp;
		bpp *= 2;
	}
	return val;
}


static ulong
imgtorgba(Memimage *img, ulong val)
{
	uchar r, g, b, a;
	int nb, ov, v;
	ulong chan;
	uchar *p;

	a = 0xFF;
	r = g = b = 0xAA;	/* garbage */
	for(chan=img->chan; chan; chan>>=8){
		nb = NBITS(chan);
		ov = v = val&((1<<nb)-1);
		val >>= nb;

		while(nb < 8){
			v |= v<<nb;
			nb *= 2;
		}
		v >>= (nb-8);

		switch(TYPE(chan)){
		case CRed:
			r = v;
			break;
		case CGreen:
			g = v;
			break;
		case CBlue:
			b = v;
			break;
		case CAlpha:
			a = v;
			break;
		case CGrey:
			r = g = b = v;
			break;
		case CMap:
			p = img->cmap->cmap2rgb+3*ov;
			r = *p++;
			g = *p++;	
			b = *p;
			break;
		}
	}
	return (r<<24)|(g<<16)|(b<<8)|a;	
}

static ulong
rgbatoimg(Memimage *img, ulong rgba)
{
	ulong chan;
	int d, nb;
	ulong v;
	uchar *p, r, g, b, a, m;

	v = 0;
	r = rgba>>24;
	g = rgba>>16;
	b = rgba>>8;
	a = rgba;
	d = 0;
	for(chan=img->chan; chan; chan>>=8){
		nb = NBITS(chan);
		switch(TYPE(chan)){
		case CRed:
			v |= (r>>(8-nb))<<d;
			break;
		case CGreen:
			v |= (g>>(8-nb))<<d;
			break;
		case CBlue:
			v |= (b>>(8-nb))<<d;
			break;
		case CAlpha:
			v |= (a>>(8-nb))<<d;
			break;
		case CMap:
			p = img->cmap->rgb2cmap;
			m = p[(r>>4)*256+(g>>4)*16+(b>>4)];
			v |= m<<d;
			break;
		case CGrey:
			m = RGB2K(r,g,b);
			v |= m<<d;
			break;
		}
		d += nb;
	}
//	print("rgba2img %.8lux = %.*lux\n", rgba, 2*d/8, v);
	return v;
}

Memimage *lastbadi;
Memdata *lastbad;
Memimage *lastbadsrc, *lastbaddst;
int hwaccel = 1;

int
hwdraw(Memdrawparam *par)
{
	VGAscr *scr;
	Memimage *dst, *src;

	if(hwaccel == 0)
		return 0;

	dst = par->dst;
	scr = &vgascreen[0];
	if(dst == nil || dst->data == nil)
		return 0;

	if(dst->data->bdata != gscreendata.bdata)
		return 0;

//	if(dst->data != &gscreendata){
//		lastbad = dst->data;
//		lastbadi = dst;
//		return 0;
//	}

	if(scr->fill==nil && scr->scroll==nil)
		return 0;

	/*
	 * If we have an opaque mask and source is one opaque
	 * pixel we can convert to the destination format and just
	 * replicate with memset.
	 */
	if(scr->fill && (par->state&(Simplemask|Simplesrc|Fullmask))==(Simplemask|Simplesrc|Fullmask))
		return scr->fill(scr, par->r, par->sdval);

	/*
	 * If no source alpha, an opaque mask, we can just copy the
	 * source onto the destination.  If the channels are the same and
	 * the source is not replicated, memmove suffices.
	 */
	src = par->src;
	if(scr->scroll && src->data->bdata==dst->data->bdata && !(src->flags&Falpha)
	&& (par->state&(Simplemask|Fullmask))==(Simplemask|Fullmask)){
//		if(src->zero != dst->zero){
//			lastbadsrc = src;
//			lastbaddst = dst;
//			iprint("#");
//		}
		return scr->scroll(scr, par->r, par->sr);
	}

	return 0;	
}

M alphapc/screen.h => alphapc/screen.h +21 -2
@@ 66,6 66,9 @@ struct VGAdev {
	void	(*disable)(VGAscr*);
	void	(*page)(VGAscr*, int);
	ulong	(*linear)(VGAscr*, int*, int*);
	void	(*drawinit)(VGAscr*);
	int	(*fill)(VGAscr*, Rectangle, ulong);

};

struct VGAcur {


@@ 75,6 78,8 @@ struct VGAcur {
	void	(*disable)(VGAscr*);
	void	(*load)(VGAscr*, Cursor*);
	int	(*move)(VGAscr*, Point);

	int	doespanning;
};

/*


@@ 97,27 102,41 @@ struct VGAscr {
	ulong	io;				/* device specific registers */

	ulong	colormap[Pcolours][3];
	int	palettedepth;

	Memimage* gscreen;
	Memdata* gscreendata;
	Memsubfont* memdefont;

	int	(*fill)(VGAscr*, Rectangle, ulong);
	int	(*scroll)(VGAscr*, Rectangle, Rectangle);
	ulong	id;	/* internal identifier for driver use */
};
extern VGAscr vgascreen[];

enum {
	Backgnd		= Pwhite,
	Backgnd		= 0,	/* black */
};

/* mouse.c */
extern void mousectl(char*[], int);

/* screen.c */
extern int		hwaccel;	/* use hw acceleration; default on */
extern void	flushmemscreen(Rectangle);
extern int	cursoron(int);
extern void	cursoroff(int);
extern void	setcursor(Cursor*);
extern int	screensize(int, int, int);
extern int	screensize(int, int, int, ulong);
extern int	screenaperture(int, int);
extern Rectangle physgscreenr;	/* actual monitor size */

/* devdraw.c */
extern void	deletescreenimage(void);
extern int		drawhasclients(void);

/* vga.c */
extern void	vgascreenwin(VGAscr*);
extern void	vgaimageinit(ulong);

extern void	drawblankscreen(int);

M alphapc/trap.c => alphapc/trap.c +153 -19
@@ 29,10 29,87 @@ char *regname[]={
	"R18",
};

static Lock vctllock;
static Vctl *vctl[256];

void
intrenable(int irq, void (*f)(Ureg*, void*), void* a, int tbdf)
intrenable(int irq, void (*f)(Ureg*, void*), void* a, int tbdf, char *name)
{
	int vno;
	Vctl *v, *p;

	v = xalloc(sizeof(Vctl));
	v->isintr = 1;
	v->irq = irq;
	v->tbdf = tbdf;
	v->f = f;
	v->a = a;
	strncpy(v->name, name, NAMELEN-1);
	v->name[NAMELEN-1] = 0;

	ilock(&vctllock);
	vno = arch->intrenable(v);
	if(vno == -1){
		iunlock(&vctllock);
		print("intrenable: couldn't enable irq %d, tbdf 0x%uX for %s\n",
			irq, tbdf, v->name);
		if(p=vctl[vno]){
			print("intrenable: irq %d is already used by", irq);
			for(; p; p=p->next)
				print(" %s", p->name);
			print("\n");
		}
		xfree(v);
		return;
	}
	if(vctl[vno]){
		if(vctl[vno]->isr != v->isr || vctl[vno]->eoi != v->eoi)
			panic("intrenable: handler: %s %s %luX %luX %luX %luX\n",
				vctl[vno]->name, v->name,
				vctl[vno]->isr, v->isr, vctl[vno]->eoi, v->eoi);
		v->next = vctl[vno];
	}
	vctl[vno] = v;
	iunlock(&vctllock);
}

int
irqallocread(char *buf, long n, vlong offset)
{
	arch->intrenable(irq, f, a, tbdf);
	int vno;
	Vctl *v;
	long oldn;
	char str[11+1+NAMELEN+1], *p;
	int m;

	if(n < 0 || offset < 0)
		error(Ebadarg);

	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);
			if(m <= offset)	/* if do not want this, skip entry */
				offset -= m;
			else{
				/* skip offset bytes */
				m -= offset;
				p = str+offset;
				offset = 0;

				/* write at most max(n,m) bytes */
				if(m > n)
					m = n;
				memmove(buf, p, m);
				n -= m;
				buf += m;

				if(n == 0)
					return oldn;
			}	
		}
	}
	return oldn - n;
}

typedef struct Mcheck Mcheck;


@@ 100,6 177,79 @@ mcheck(void *x)
}

void
intr(Ureg *ur)
{
	int i, vno;
	Vctl *ctl, *v;
	Mach *mach;

	vno = (ulong)ur->a1>>4;
	vno -= 0x80;
	if(vno < nelem(vctl) && (ctl = vctl[vno])){
		if(ctl->isintr){
			m->intr++;
			if(vno >= VectorPIC && vno <= MaxVectorPIC)
				m->lastintr = vno-VectorPIC;
		}

		if(ctl->isr)
			ctl->isr(vno);
		for(v = ctl; v != nil; v = v->next) {
			if(v->f)
				v->f(ur, v->a);
		}

		if(ctl->eoi)
			ctl->eoi(vno);

		/* 
		 *  preemptive scheduling.  to limit stack depth,
		 *  make sure process has a chance to return from
		 *  the current interrupt before being preempted a
		 *  second time.
		 */
		if(ctl->isintr)
		if(up && up->state == Running)
		if(anyhigher())
		if(up->preempted == 0)
		if(!active.exiting){
			up->preempted = 1;
			sched();
			splhi();
			up->preempted = 0;
			return;
		}
	}
	else if(vno >= VectorPIC && vno <= MaxVectorPIC){
		/*
		 * An unknown interrupt.
		 * Check for a default IRQ7. This can happen when
		 * the IRQ input goes away before the acknowledge.
		 * In this case, a 'default IRQ7' is generated, but
		 * the corresponding bit in the ISR isn't set.
		 * In fact, just ignore all such interrupts.
		 */
		iprint("cpu%d: spurious interrupt %d, last %d",
			m->machno, vno-VectorPIC, m->lastintr);
		for(i = 0; i < 32; i++){
			if(!(active.machs & (1<<i)))
				continue;
			mach = MACHP(i);
			if(m->machno == mach->machno)
				continue;
			iprint(": cpu%d: last %d", mach->machno, mach->lastintr);
		}
		iprint("\n");
		m->spuriousintr++;
		return;
	}
	else{
		dumpregs(ur);
		panic("unknown intr: %d\n", vno); /* */
	}
}

void
trap(Ureg *ur)
{
	char buf[ERRLEN];


@@ 133,23 283,7 @@ trap(Ureg *ur)
			mcheck((void*)(KZERO|(ulong)ur->a2));
			break;
		case 3:	/* device */
			arch->intr(ur);
			/* 
			 *  preemptive scheduling.  to limit stack depth,
			 *  make sure process has a chance to return from
			 *  the current interrupt before being preempted a
			 *  second time.
			 */
			if(up && up->state == Running)
			if(anyhigher())
			if(up->preempted == 0)
			if(!active.exiting){
				up->preempted = 1;
				sched();
				splhi();
				up->preempted = 0;
				return;
			}
			intr(ur);
			break;
		case 4:	/* perf counter */
			panic("perf count");

M alphapc/vga.c => alphapc/vga.c +36 -39
@@ 11,42 11,37 @@
#include <cursor.h>
#include "screen.h"

static ulong backbits = (Backgnd<<24)|(Backgnd<<16)|(Backgnd<<8)|Backgnd;
static Memdata backdata = {
	nil,
	&backbits
};
static Memimage xback = {
	{ 0, 0, 1, 1 },
	{ -100000, -100000, 100000, 100000 },
	3,
	1,
	&backdata,
	0,
	1
};
static Memimage* back = &xback;

static ulong consbits = 0;
static Memdata consdata = {
	nil,
	&consbits
};
static Memimage conscol = {
	{ 0, 0, 1, 1 },
	{ -100000, -100000, 100000, 100000 },
	3,
	1,
	&consdata,
	0,
	1
};
static Memimage* back;
static Memimage *conscol;

static Point curpos;
static Rectangle window;
static int *xp;
static int xbuf[256];
static Lock vgascreenlock;
int drawdebug;

void
vgaimageinit(ulong chan)
{
	if(back == nil){
		back = allocmemimage(Rect(0,0,1,1), chan);	/* RSC BUG */
		if(back == nil)
			panic("back alloc");		/* RSC BUG */
		back->flags |= Frepl;
		back->clipr = Rect(-0x3FFFFFF, -0x3FFFFFF, 0x3FFFFFF, 0x3FFFFFF);
		memfillcolor(back, DBlack);
	}

	if(conscol == nil){
		conscol = allocmemimage(Rect(0,0,1,1), chan);	/* RSC BUG */
		if(conscol == nil)
			panic("conscol alloc");	/* RSC BUG */
		conscol->flags |= Frepl;
		conscol->clipr = Rect(-0x3FFFFFF, -0x3FFFFFF, 0x3FFFFFF, 0x3FFFFFF);
		memfillcolor(conscol, DWhite);
	}
}

static void
vgascroll(VGAscr* scr)


@@ 59,9 54,9 @@ vgascroll(VGAscr* scr)
	o = 8*h;
	r = Rpt(window.min, Pt(window.max.x, window.max.y-o));
	p = Pt(window.min.x, window.min.y+o);
	memimagedraw(scr->gscreen, r, scr->gscreen, p, memones, p);
	memimagedraw(scr->gscreen, r, scr->gscreen, p, nil, p);
	r = Rpt(Pt(window.min.x, window.max.y-o), window.max);
	memimagedraw(scr->gscreen, r, back, ZP, memones, ZP);
	memimagedraw(scr->gscreen, r, back, ZP, nil, ZP);

	curpos.y -= o;
}


@@ 73,6 68,7 @@ vgascreenputc(VGAscr* scr, char* buf, Rectangle *flushr)
	int h, w, pos;
	Rectangle r;

//	drawdebug = 1;
	if(xp < xbuf || xp >= &xbuf[sizeof(xbuf)])
		xp = xbuf;



@@ 100,8 96,8 @@ vgascreenputc(VGAscr* scr, char* buf, Rectangle *flushr)
		pos = (curpos.x-window.min.x)/w;
		pos = 4-(pos%4);
		r = Rect(curpos.x, curpos.y, curpos.x+pos*w, curpos.y+h);
		memimagedraw(scr->gscreen, r, back, back->r.min, memones, back->r.min);
		bbox(flushr, r);
		memimagedraw(scr->gscreen, r, back, back->r.min, nil, ZP);
		combinerect(flushr, r);
		curpos.x += pos*w;
		break;



@@ 110,8 106,8 @@ vgascreenputc(VGAscr* scr, char* buf, Rectangle *flushr)
			break;
		xp--;
		r = Rect(*xp, curpos.y, curpos.x, curpos.y+h);
		memimagedraw(scr->gscreen, r, back, back->r.min, memones, back->r.min);
		bbox(flushr, r);
		memimagedraw(scr->gscreen, r, back, back->r.min, nil, ZP);
		combinerect(flushr, r);
		curpos.x = *xp;
		break;



@@ 124,11 120,12 @@ vgascreenputc(VGAscr* scr, char* buf, Rectangle *flushr)

		*xp++ = curpos.x;
		r = Rect(curpos.x, curpos.y, curpos.x+w, curpos.y+h);
		memimagedraw(scr->gscreen, r, back, back->r.min, memones, back->r.min);
		memimagestring(scr->gscreen, curpos, &conscol, scr->memdefont, buf);
		bbox(flushr, r);
		memimagedraw(scr->gscreen, r, back, back->r.min, nil, back->r.min);
		memimagestring(scr->gscreen, curpos, conscol, ZP, scr->memdefont, buf);
		combinerect(flushr, r);
		curpos.x += w;
	}
//	drawdebug = 0;
}

static void

M alphapc/vgas3.c => alphapc/vgas3.c +13 -21
@@ 19,7 19,7 @@ s3pageset(VGAscr* scr, int page)
	int opage;

	crt35 = vgaxi(Crtx, 0x35);
	if(scr->gscreen->ldepth == 3){
	if(scr->gscreen->depth >= 8){
		/*
		 * The S3 registers need to be unlocked for this.
		 * Let's hope they are already:


@@ 127,7 127,7 @@ s3disable(VGAscr*)
static void
s3enable(VGAscr* scr)
{
	int i, id;
	int i;
	ulong storage;

	s3disable(scr);


@@ 135,30 135,16 @@ s3enable(VGAscr* scr)
	/*
	 * Cursor colours. Set both the CR0[EF] and the colour
	 * stack in case we are using a 16-bit RAMDAC.
	 * This stuff is just a mystery for the ViRGE/GX2.
	 */
	vgaxo(Crtx, 0x0E, Pwhite);
	vgaxo(Crtx, 0x0F, Pblack);
	vgaxi(Crtx, 0x45);
	id = (vgaxi(Crtx, 0x30)<<8)|vgaxi(Crtx, 0x2E);
	switch(id){

	case 0xE110:				/* ViRGE/GX2 */
		for(i = 0; i < 3; i++)
			vgaxo(Crtx, 0x4A, Pblack);
		vgaxi(Crtx, 0x45);
		for(i = 0; i < 3; i++)
			vgaxo(Crtx, 0x4B, Pwhite);
		break;

	default:
		for(i = 0; i < 3; i++)
			vgaxo(Crtx, 0x4A, Pwhite);
		vgaxi(Crtx, 0x45);
		for(i = 0; i < 3; i++)
			vgaxo(Crtx, 0x4B, Pblack);
		break;
	}
	for(i = 0; i < 3; i++)
		vgaxo(Crtx, 0x4A, Pblack);
	vgaxi(Crtx, 0x45);
	for(i = 0; i < 3; i++)
		vgaxo(Crtx, 0x4B, Pwhite);

	/*
	 * Find a place for the cursor data in display memory.


@@ 195,7 181,10 @@ s3load(VGAscr* scr, Cursor* curs)
	id = (vgaxi(Crtx, 0x30)<<8)|vgaxi(Crtx, 0x2E);
	switch(id){

	case 0xE131:				/* ViRGE */
	case 0xE18A:				/* ViRGE/[DG]X */
	case 0xE110:				/* ViRGE/GX2 */
	case 0xE13D:				/* ViRGE/VX */
		p += scr->storage;
		break;



@@ 238,7 227,10 @@ s3load(VGAscr* scr, Cursor* curs)

	switch(id){

	case 0xE131:				/* ViRGE */
	case 0xE18A:				/* ViRGE/[DG]X */
	case 0xE110:				/* ViRGE/GX2 */
	case 0xE13D:				/* ViRGE/VX */
		break;

	default:

M boot/key.c => boot/key.c +1 -4
@@ 37,7 37,7 @@ key(int islocal, Method *mp)
	if(strcmp(cputype, "sparc") == 0){
		fd = open("#r/nvram", ORDWR);
		safeoff = 1024+850;
	} else if(strcmp(cputype, "386") == 0){
	} else if(strcmp(cputype, "386") == 0 || strcmp(cputype, "alpha") == 0){
		fd = open("#H/hd0nvram", ORDWR);
		if(fd < 0)
			fd = open("#w/sd0nvram", ORDWR);


@@ 83,9 83,6 @@ key(int islocal, Method *mp)
	}
	close(fd);

//fprint(2, "hostowner = %s\n", safe->authid);
//fprint(2, "hostdomain = %s\n", safe->authdom);

	/* set host's key */
	if(writefile("#c/key", safe->machkey, DESKEYLEN) < 0)
		fatal("#c/key");