Plan 9 from Bell Labs’s /usr/web/sources/extra/9hist/pc/devvga.c

Copyright © 2021 Plan 9 Foundation.
Distributed under the MIT License.
Download the Plan 9 distribution.


## diffname pc/devvga.c 1992/0527
## diff -e /dev/null /n/bootesdump/1992/0527/sys/src/9/safari/devvga.c
0a
#include	"u.h"
#include	"../port/lib.h"
#include	"mem.h"
#include	"dat.h"
#include	"fns.h"
#include	"io.h"
#include	"../port/error.h"

#include	"devtab.h"

/*
 *  Driver for various VGA cards
 */

char	monitor[NAMELEN];	/* monitor name and type */
char	vgacard[NAMELEN];	/* vga card type */
struct screeninfo {
	int	maxx, maxy;	/* current bits per screen */
	int	packed;		/* 0=planar, 1=packed */
	int	interlaced;	/* != 0 if interlaced */
} screeninfo;

enum {
	Qdir=		0,
	Qvgamonitor=	1,
	Qvgasize=	2,
	Qvgatype=	3,
	Qvgaportio=	4,
	Nvga=		4,
};

Dirtab vgadir[]={
	"vgamonitor",	{Qvgamonitor},	0,		0666,
	"vgatype",	{Qvgatype},	0,		0666,
	"vgasize",	{Qvgasize},	0,		0666,
	"vgaportio",	{Qvgaportio},	0,		0666,
};

/* a routine from ../port/devcons.c */
extern	int readstr(ulong, char *, ulong, char *);

void
vgasetup(void) {
}

void
vgareset(void) {
	strcpy(monitor, "generic");
	strcpy(vgacard, "generic");
	screeninfo.maxx = 640;
	screeninfo.maxy = 480;
	screeninfo.packed = 0;
	screeninfo.interlaced = 0;
}

void
vgainit(void)
{
}

Chan*
vgaattach(char *upec)
{
	return devattach('v', upec);
}

Chan*
vgaclone(Chan *c, Chan *nc)
{
	return devclone(c, nc);
}

int
vgawalk(Chan *c, char *name)
{
	return devwalk(c, name, vgadir, Nvga, devgen);
}

void
vgastat(Chan *c, char *dp)
{
	switch(c->qid.path){
	default:
		devstat(c, dp, vgadir, Nvga, devgen);
		break;
	}
}

Chan*
vgaopen(Chan *c, int omode)
{
	switch(c->qid.path){
	case Qvgamonitor:
	case Qvgatype:
	case Qvgasize:
	case Qvgaportio:
		break;
	}

	return devopen(c, omode, vgadir, Nvga, devgen);
}

void
vgacreate(Chan *c, char *name, int omode, ulong perm)
{
	error(Eperm);
}

void
vgaclose(Chan *c)
{
}

long
vgaread(Chan *c, void *buf, long n, ulong offset)
{
	char obuf[60];
	switch(c->qid.path&~CHDIR){
	case Qdir:
		return devdirread(c, buf, n, vgadir, Nvga, devgen);
	case Qvgamonitor:
		return readstr(offset, buf, n, monitor);
	case Qvgatype:
		return readstr(offset, buf, n, vgacard);
	case Qvgasize:
		sprint(obuf, "%dx%d%x%d %s",
			screeninfo.maxx, screeninfo.maxy,
			screeninfo.packed ? 16 : 256,
			screeninfo.interlaced ? "interlaced" : "non-interlaced");
		return readstr(offset, buf, n, obuf);
	case Qvgaportio:
		return 0;
	}
}

long
vgawrite(Chan *c, void *va, long n, ulong offset)
{
	if(offset != 0)
		error(Ebadarg);
	switch(c->qid.path&~CHDIR){
	case Qdir:
		error(Eperm);
	case Qvgamonitor:
	case Qvgatype:
	case Qvgasize:
	case Qvgaportio:
		return 0;
	}
}

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

void
vgawstat(Chan *c, char *dp)
{
	error(Eperm);
}
.
## diffname pc/devvga.c 1992/0528
## diff -e /n/bootesdump/1992/0527/sys/src/9/safari/devvga.c /n/bootesdump/1992/0528/sys/src/9/safari/devvga.c
147,148c
		if(offset != 0)
			error(Ebadarg);
		error(Eperm);
	case Qvgaport:
		if (offset + n >= 0x8000)
			error(Ebadarg);
		for (port=offset; port<offset+n; port++)
			outb(port, *cp++);
		return n;
	case Qvgaiport:
		port = offset / 256;
		switch (port) {
		case EMISCW:	outfunc = genout;	break;
		case SRX:	outfunc = srout;	break;
		case GRX:	outfunc = grout;	break;
		case ARW:	outfunc = arout;	break;
		case CRX:	outfunc = crout;	break;
		default:
			error(Ebadarg);
		}
		for (i = offset%256; i < (offset%256) + n; i++)
			outfunc(i, *cp++);
		return n;
.
145a
		if(offset != 0)
			error(Ebadarg);
		error(Eperm);
.
144a
		if(offset != 0)
			error(Ebadarg);
		error(Eperm);
.
139,140c
	uchar *cp = buf;
	void (*outfunc)(int, int);
	int port, i;

.
137c
vgawrite(Chan *c, void *buf, long n, ulong offset)
.
131,132c
	case Qvgaport:
		if (offset + n >= 0x8000)
			error(Ebadarg);
		for (port=offset; port<offset+n; port++)
			*cp++ = inb(port);
		return n;
	case Qvgaiport:
		error(Eio);
.
128,129c
			(screeninfo.packed == 0) ? 256 : 16,
			(screeninfo.interlaced != 0) ? "interlaced" : "non-interlaced");
.
117a
	int port, i;
	uchar *cp = buf;
	void *outfunc(int, int);

.
96c
	case Qvgaport:
.
36c
	"vgaport",	{Qvgaport},	0,		0666,
	"vgaiport",	{Qvgaiport},	0,		0666,
.
28,29c
	Qvgaport=	4,
	Qvgaiport=	5,
	Nvga=		5,
.
9a
#include	"vga.h"
.
## diffname pc/devvga.c 1992/0529
## diff -e /n/bootesdump/1992/0528/sys/src/9/safari/devvga.c /n/bootesdump/1992/0529/sys/src/9/safari/devvga.c
176,189d
144,145d
39d
30,31c
	Nvga=		4,
.
## diffname pc/devvga.c 1992/0603
## diff -e /n/bootesdump/1992/0529/sys/src/9/safari/devvga.c /n/bootesdump/1992/0603/sys/src/9/safari/devvga.c
171a
		}
.
170c
		for (port=offset; port<offset+n; port++) {
.
167a
		cp = buf;
.
166c
		if(n >= sizeof cbuf)
			n = sizeof cbuf - 1;
		memmove(cbuf, buf, n);
		cbuf[n-1] = 0;
		cp = cbuf;
		maxx = strtoul(cp, &cp, 0);
		maxy = strtoul(cp, &cp, 0);
		if (maxx == 0 || maxy == 0 ||
		    maxx > 1280 || maxy > 1024)
			error(Ebadarg);
		setscreen(maxx, maxy, 1);
		return n;
.
148,150c
	char cbuf[20], *cp;
	int port, i, maxx, maxy;
.
140a
		}
.
139c
		for (port=offset; port<offset+n; port++) {
.
131,134c
		sprint(obuf, "%d %d",
			gscreen.r.max.x, gscreen.r.max.y);
.
8a
#include	<libg.h>
#include	<gnot.h>
.
## diffname pc/devvga.c 1992/0604
## diff -e /n/bootesdump/1992/0603/sys/src/9/safari/devvga.c /n/bootesdump/1992/0604/sys/src/9/safari/devvga.c
184a
		return n;
	case Qvgamem:
		if (offset + n > 0x10000)
			error(Ebadarg);
		memmove((void *)(SCREENMEM+offset), buf, n);
.
169c
		cbuf[n] = 0;
.
166,167c
		if(n >= sizeof(cbuf))
			n = sizeof(cbuf) - 1;
.
142a
	case Qvgamem:
		if (offset > 0x10000)
			return 0;
		if (offset + n > 0x10000)
			n = 0x10000 - offset;
		memmove(cp, (void *)(SCREENMEM+offset), n);
		return n;
.
141d
139c
		for (port=offset; port<offset+n; port++)
.
121a
	uchar *mem;
.
102d
99a
	case Qvgamem:
.
39a
	"vgamem",	{Qvgamem},	0,		0666,
.
32c
	Qvgamem=	5,
	Nvga=		5,
.
## diffname pc/devvga.c 1992/0711
## diff -e /n/bootesdump/1992/0604/sys/src/9/safari/devvga.c /n/bootesdump/1992/0711/sys/src/9/safari/devvga.c
211a
	USED(c, dp);
.
205a
	USED(c);
.
159c
	int port, maxx, maxy;
.
123,124c
	int port;
.
116a
	USED(c);
.
110a
	USED(c, name, omode, perm);
.
## diffname pc/devvga.c 1992/1119
## diff -e /n/bootesdump/1992/0808/sys/src/9/safari/devvga.c /n/bootesdump/1992/1119/sys/src/9/pc/devvga.c
216a

void
genout(int reg, int val)
{
	if(reg == 0)
		outb(EMISCW, val);
	else if (reg == 1)
		outb(EFCW, val);
}
void
srout(int reg, int val)
{
	outb(SRX, reg);
	outb(SR, val);
}
void
grout(int reg, int val)
{
	outb(GRX, reg);
	outb(GR, val);
}
void
arout(int reg, int val)
{
	inb(0x3DA);
	if (reg <= 0xf) {
		outb(ARW, reg | 0x0);
		outb(ARW, val);
		inb(0x3DA);
		outb(ARW, reg | 0x20);
	} else {
		outb(ARW, reg | 0x20);
		outb(ARW, val);
	}
}

void
crout(int reg, int val)
{
	outb(CRX, reg);
	outb(CR, val);
}

void
setmode(VGAmode *v)
{
	int i;

	/* turn screen off (to avoid damage) */
	srout(1, 0x21);

	for(i = 0; i < sizeof(v->general); i++)
		genout(i, v->general[i]);

	for(i = 0; i < sizeof(v->sequencer); i++)
		if(i == 1)
			srout(i, v->sequencer[i]|0x20);		/* avoid enabling screen */
		else
			srout(i, v->sequencer[i]);

	crout(Cvre, 0);	/* allow writes to CRT registers 0-7 */
	for(i = 0; i < sizeof(v->crt); i++)
		crout(i, v->crt[i]);

	for(i = 0; i < sizeof(v->graphics); i++)
		grout(i, v->graphics[i]);

	for(i = 0; i < sizeof(v->attribute); i++)
		arout(i, v->attribute[i]);

	/* turn screen on */
	srout(1, v->sequencer[1]);
}

void
getmode(VGAmode *v) {
	int i;
	v->general[0] = inb(0x3cc);
	v->general[1] = inb(0x3ca);
	for(i = 0; i < sizeof(v->sequencer); i++) {
		outb(SRX, i);
		v->sequencer[i] = inb(SR);
	}
	for(i = 0; i < sizeof(v->crt); i++) {
		outb(CRX, i);
		v->crt[i] = inb(CR);
	}
	for(i = 0; i < sizeof(v->graphics); i++) {
		outb(GRX, i);
		v->graphics[i] = inb(GR);
	}
	for(i = 0; i < sizeof(v->attribute); i++) {
		inb(0x3DA);
		outb(ARW, i | 0x20);
		v->attribute[i] = inb(ARR);
	}
}

void
printmode(VGAmode *v) {
	int i;
	print("g %2.2x %2x\n",
		v->general[0], v->general[1]);

	print("s ");
	for(i = 0; i < sizeof(v->sequencer); i++) {
		print(" %2.2x", v->sequencer[i]);
	}

	print("\nc ");
	for(i = 0; i < sizeof(v->crt); i++) {
		print(" %2.2x", v->crt[i]);
	}

	print("\ng ");
	for(i = 0; i < sizeof(v->graphics); i++) {
		print(" %2.2x", v->graphics[i]);
	}

	print("\na ");
	for(i = 0; i < sizeof(v->attribute); i++) {
		print(" %2.2x", v->attribute[i]);
	}
	print("\n");
}

/*
 *  expand 3 and 6 bits of color to 32
 */
static ulong
x3to32(uchar x)
{
	ulong y;

	x = x&7;
	x= (x<<3)|x;
	y = (x<<(32-6))|(x<<(32-12))|(x<<(32-18))|(x<<(32-24))|(x<<(32-30));
	return y;
}
static ulong
x6to32(uchar x)
{
	ulong y;

	x = x&0x3f;
	y = (x<<(32-6))|(x<<(32-12))|(x<<(32-18))|(x<<(32-24))|(x<<(32-30));
	return y;
}

void
setscreen(int maxx, int maxy, int ldepth)
{
	int len, vgamaxy, width, i, x;
	uchar *p;

	if(ldepth == 3)
		setmode(&mode13);
	else
		setmode(&mode12);

	/* allocate a new soft bitmap area */
	width = (maxx*(1<<ldepth))/32;
	len = width * BY2WD * maxy;
	p = xalloc(len);
	if(p == 0)
		panic("can't alloc screen bitmap");
	mbb = NULLMBB;

	/*
	 *  zero hard screen and setup a bitmap for the new size
	 */
	if(ldepth == 3)
		vgascreen.ldepth = 3;
	else
		vgascreen.ldepth = 0;
	vgascreen.width = (maxx*(1<<vgascreen.ldepth))/32;
	if(maxy > (64*1024)/(vgascreen.width*BY2WD))
		vgamaxy = (64*1024)/(vgascreen.width*BY2WD);
	else
		vgamaxy = maxy;
	vgascreen.base = (void*)SCREENMEM;
	vgascreen.r.min = Pt(0, 0);
	vgascreen.r.max = Pt(maxx, vgamaxy);
	vgascreen.clipr = vgascreen.r;
	memset(vgascreen.base, 0xff, vgascreen.width * BY2WD * vgamaxy);

	/*
	 *  setup new soft screen, free memory for old screen
	 */
	if(gscreen.base)
		xfree(gscreen.base);
	gscreen.ldepth = ldepth;
	gscreen.width = width;
	gscreen.r.min = Pt(0, 0);
	gscreen.r.max = Pt(maxx, maxy);
	gscreen.clipr = gscreen.r;
	gscreen.base = (ulong*)p;
	memset(gscreen.base, 0xff, len);

	/*
	 *  set depth of cursor backup area
	 */
	bitdepth();

	/*
	 *  set string pointer to upper left
	 */
	out.pos.x = MINX;
	out.pos.y = 0;
	out.bwid = defont0.info[' '].width;

	/*
	 *  default color map
	 */
	switch(ldepth){
	case 3:
		for(i = 0; i < 256; i++)
			setcolor(i, x3to32(i>>5), x3to32(i>>2), x3to32(i<<1));
		break;
	case 2:
	case 1:
	case 0:
		gscreen.ldepth = 3;
		for(i = 0; i < 16; i++){
			x = x6to32((i*63)/15);
			setcolor(i, x, x, x);
		}
		gscreen.ldepth = ldepth;
		break;
	}
	cga = 0;
}

void
screeninit(void)
{
	int i;
	ulong *l;

	/*
	 *  arrow is defined as a big endian
	 */
	pixreverse(arrow.set, 2*16, 0);
	pixreverse(arrow.clr, 2*16, 0);

	/*
	 *  swizzle the font longs.  we do both byte and bit swizzling
	 *  since the font is initialized with big endian longs.
	 */
	defont = &defont0;
	l = defont->bits->base;
	for(i = defont->bits->width*Dy(defont->bits->r); i > 0; i--, l++)
		*l = (*l<<24) | ((*l>>8)&0x0000ff00) | ((*l<<8)&0x00ff0000) | (*l>>24);
	pixreverse((uchar*)defont->bits->base,
		defont->bits->width*BY2WD*Dy(defont->bits->r), 0);

	cga = 1;
	crout(0x0a, 0xff);		/* turn off cursor */
	memset(CGASCREEN, 0, CGAWIDTH*CGAHEIGHT);
}

/*
 *  collect changes to the 'soft' screen
 */
void
mbbrect(Rectangle r)
{
	if (r.min.x < mbb.min.x)
		mbb.min.x = r.min.x;
	if (r.min.y < mbb.min.y)
		mbb.min.y = r.min.y;
	if (r.max.x > mbb.max.x)
		mbb.max.x = r.max.x;
	if (r.max.y > mbb.max.y)
		mbb.max.y = r.max.y;
	if (Dy(mbb) > 32 || Dx(mbb) > 32)
		mousescreenupdate();
}

void
mbbpt(Point p)
{
	if (p.x < mbb.min.x)
		mbb.min.x = p.x;
	if (p.y < mbb.min.y)
		mbb.min.y = p.y;
	if (p.x >= mbb.max.x)
		mbb.max.x = p.x+1;
	if (p.y >= mbb.max.y)
		mbb.max.y = p.y+1;
}

/*
 *  paging routines for different cards
 */
static void
nopage(int page)
{
	USED(page);
}
static void
tsengpage(int page)
{
	outb(0x3cd, (page<<4)|page);
}

/*
 *  copy litte endian soft screen to big endian hard screen
 */
static void
vgaupdate(void)
{
	uchar *sp, *hp, *edisp;
	int y, len, incs, inch, off, page;
	Rectangle r;
	void* (*f)(void*, void*, long);

	r = mbb;
	mbb = NULLMBB;

	if(Dy(r) < 0)
		return;

	if(r.min.x < 0)
		r.min.x = 0;
	if(r.min.y < 0)
		r.min.y = 0;
	if(r.max.x > gscreen.r.max.x)
		r.max.x = gscreen.r.max.x;
	if(r.max.y > gscreen.r.max.y)
		r.max.y = gscreen.r.max.y;

	incs = gscreen.width * BY2WD;
	inch = vgascreen.width * BY2WD;

	switch(gscreen.ldepth){
	case 0:
		r.min.x &= ~15;		/* 16 bit allignment for l0update() */
		f = l0update;
		len = (r.max.x + 7)/8 - r.min.x/8;
		if(len & 1)
			len++;		/* 16 bit allignment for l0update() */
		break;
	case 1:
		r.min.x &= ~15;		/* 16 bit allignment for l1update() */
		f = l1update;
		len = (r.max.x + 7)/8 - r.min.x/8;
		if(len & 1)
			len++;		/* 16 bit allignment for l1update() */
		break;
	case 2:
		f = l2update;
		len = (r.max.x + 7)/8 - r.min.x/8;
		break;
	case 3:
		f = memmove;
		len = r.max.x - r.min.x;
		break;
	default:
		return;
	}
	if(len < 1)
		return;

	off = r.min.y * vgascreen.width * BY2WD + (r.min.x>>(3 - vgascreen.ldepth));
	page = off>>16;
	off &= (1<<16)-1;
	hp = ((uchar*)vgascreen.base) + off;
	off = r.min.y * gscreen.width * BY2WD + (r.min.x>>(3 - gscreen.ldepth));
	sp = ((uchar*)gscreen.base) + off;

	edisp = ((uchar*)vgascreen.base) + 64*1024;
	vgacard->setpage(page);
	for(y = r.min.y; y < r.max.y; y++){
		if(hp + inch < edisp){
			f(hp, sp, len);
			sp += incs;
			hp += inch;
		} else {
			off = edisp - hp;
			if(off <= len){
				if(off > 0)
					f(hp, sp, off);
				vgacard->setpage(++page);
				if(len - off > 0)
					f(vgascreen.base, sp+off, len - off);
			} else {
				f(hp, sp, len);
				vgacard->setpage(++page);
			}
			sp += incs;
			hp += inch - 64*1024;
		}
	}
}

void
screenupdate(void)
{
	lock(&vgalock);
	vgaupdate();
	unlock(&vgalock);
}

void
mousescreenupdate(void)
{
	if(canlock(&vgalock)){
		vgaupdate();
		unlock(&vgalock);
	}
}

static void
cgascreenputc(int c)
{
	int i;
	static int color;
	static int pos;

	if(c == '\n'){
		pos = pos/CGAWIDTH;
		pos = (pos+1)*CGAWIDTH;
	} else if(c == '\t'){
		i = 8 - ((pos/2)&7);
		while(i-->0)
			cgascreenputc(' ');
	} else if(c == '\b'){
		if(pos >= 2)
			pos -= 2;
		cgascreenputc(' ');
		pos -= 2;
	} else {
		CGASCREEN[pos++] = c;
		CGASCREEN[pos++] = 2;	/* green on black */
	}
	if(pos >= CGAWIDTH*CGAHEIGHT){
		memmove(CGASCREEN, &CGASCREEN[CGAWIDTH], CGAWIDTH*(CGAHEIGHT-1));
		memset(&CGASCREEN[CGAWIDTH*(CGAHEIGHT-1)], 0, CGAWIDTH);
		pos = CGAWIDTH*(CGAHEIGHT-1);
	}
}

void
cgascreenputs(char *s, int n)
{
	while(n-- > 0)
		cgascreenputc(*s++);
}

void
screenputnl(void)
{
	Rectangle r;

	out.pos.x = MINX;
	out.pos.y += defont0.height;
	if(out.pos.y > gscreen.r.max.y-defont0.height){
		vgaupdate();
		out.pos.y = gscreen.r.min.y;
	}
	r = Rect(0, out.pos.y, gscreen.r.max.x, out.pos.y+2*defont0.height);
	gbitblt(&gscreen, r.min, &gscreen, r, flipD[0]);
	mbbrect(r);
	vgaupdate();
}

void
screenputs(char *s, int n)
{
	Rune r;
	int i;
	char buf[4];
	Rectangle rect;

	if(cga) {
		cgascreenputs(s, n);
		return;
	}

	while(n > 0){
		i = chartorune(&r, s);
		if(i == 0){
			s++;
			--n;
			continue;
		}
		memmove(buf, s, i);
		buf[i] = 0;
		n -= i;
		s += i;
		if(r == '\n')
			screenputnl();
		else if(r == '\t'){
			out.pos.x += (8-((out.pos.x-MINX)/out.bwid&7))*out.bwid;
			if(out.pos.x >= gscreen.r.max.x)
				screenputnl();
		}else if(r == '\b'){
			if(out.pos.x >= out.bwid+MINX){
				out.pos.x -= out.bwid;
				gsubfstring(&gscreen, out.pos, defont, " ", flipD[S]);
			}
			rect.min = Pt(out.pos.x, out.pos.y);
			rect.max = Pt(out.pos.x+out.bwid, out.pos.y+defont0.height);
			mbbrect(rect);
		}else{
			if(out.pos.x >= gscreen.r.max.x-out.bwid)
				screenputnl();
			rect.min = Pt(out.pos.x, out.pos.y);
			rect.max = Pt(out.pos.x+out.bwid, out.pos.y+defont0.height);
			out.pos = gsubfstring(&gscreen, out.pos, defont, buf, flipD[S]);
			mbbrect(rect);
		}
	}
	vgaupdate();
}

int
screenbits(void)
{
	return 1<<gscreen.ldepth;	/* bits per pixel */
}

void
getcolor(ulong p, ulong *pr, ulong *pg, ulong *pb)
{
	p &= (1<<(1<<gscreen.ldepth))-1;
	lock(&vgalock);
	*pr = colormap[p][0];
	*pg = colormap[p][1];
	*pb = colormap[p][2];
	unlock(&vgalock);
}

int
setcolor(ulong p, ulong r, ulong g, ulong b)
{
	p &= (1<<(1<<gscreen.ldepth))-1;
	lock(&vgalock);
	colormap[p][0] = r;
	colormap[p][1] = g;
	colormap[p][2] = b;
	outb(CMWX, p);
	outb(CM, r>>(32-6));
	outb(CM, g>>(32-6));
	outb(CM, b>>(32-6));
	unlock(&vgalock);
	return ~0;
}

int
hwcursset(uchar *s, uchar *c, int ox, int oy)
{
	USED(s, c, ox, oy);
	return 0;
}

int
hwcursmove(int x, int y)
{
	USED(x, y);
	return 0;
}

void
mouseclock(void)
{
	spllo();	/* so we don't cause lost chars on the uart */
	mouseupdate(1);
}

/*
 *  a fatter than usual cursor for the safari
 */
Cursor fatarrow = {
	{ -1, -1 },
	{
		0xff, 0xff, 0x80, 0x01, 0x80, 0x02, 0x80, 0x0c, 
		0x80, 0x10, 0x80, 0x10, 0x80, 0x08, 0x80, 0x04, 
		0x80, 0x02, 0x80, 0x01, 0x80, 0x02, 0x8c, 0x04, 
		0x92, 0x08, 0x91, 0x10, 0xa0, 0xa0, 0xc0, 0x40, 
	},
	{
		0x00, 0x00, 0x7f, 0xfe, 0x7f, 0xfc, 0x7f, 0xf0, 
		0x7f, 0xe0, 0x7f, 0xe0, 0x7f, 0xf0, 0x7f, 0xf8, 
		0x7f, 0xfc, 0x7f, 0xfe, 0x7f, 0xfc, 0x73, 0xf8, 
		0x61, 0xf0, 0x60, 0xe0, 0x40, 0x40, 0x00, 0x00, 
	},
};

void
bigcursor(void)
{
	memmove(&arrow, &fatarrow, sizeof(fatarrow));
	pixreverse(arrow.set, 2*16, 0);
	pixreverse(arrow.clr, 2*16, 0);
}

/*
 *  Table for separating and reversing bits in a ldepth 1 bitmap.
 *  This aids in coverting a little endian ldepth 1 bitmap into the
 *  2 big-endian ldepth 0 bitmaps used for the VGA bit planes.
 *
 *	if the bits in uchar x are labeled
 *		76543210
 *	then l1revsep[x] yields a ushort with bits
 *		________1357________0246
 *	where _ represents a bit whose value is 0.
 *
 *  This table is used by l1update() in l.s.  l1update is implemented
 *  in assembler for speed.
 *
 */
ulong l1revsep[] = {
 0x00000, 0x00008, 0x80000, 0x80008, 0x00004, 0x0000c, 0x80004, 0x8000c,
 0x40000, 0x40008, 0xc0000, 0xc0008, 0x40004, 0x4000c, 0xc0004, 0xc000c,
 0x00002, 0x0000a, 0x80002, 0x8000a, 0x00006, 0x0000e, 0x80006, 0x8000e,
 0x40002, 0x4000a, 0xc0002, 0xc000a, 0x40006, 0x4000e, 0xc0006, 0xc000e,
 0x20000, 0x20008, 0xa0000, 0xa0008, 0x20004, 0x2000c, 0xa0004, 0xa000c,
 0x60000, 0x60008, 0xe0000, 0xe0008, 0x60004, 0x6000c, 0xe0004, 0xe000c,
 0x20002, 0x2000a, 0xa0002, 0xa000a, 0x20006, 0x2000e, 0xa0006, 0xa000e,
 0x60002, 0x6000a, 0xe0002, 0xe000a, 0x60006, 0x6000e, 0xe0006, 0xe000e,
 0x00001, 0x00009, 0x80001, 0x80009, 0x00005, 0x0000d, 0x80005, 0x8000d,
 0x40001, 0x40009, 0xc0001, 0xc0009, 0x40005, 0x4000d, 0xc0005, 0xc000d,
 0x00003, 0x0000b, 0x80003, 0x8000b, 0x00007, 0x0000f, 0x80007, 0x8000f,
 0x40003, 0x4000b, 0xc0003, 0xc000b, 0x40007, 0x4000f, 0xc0007, 0xc000f,
 0x20001, 0x20009, 0xa0001, 0xa0009, 0x20005, 0x2000d, 0xa0005, 0xa000d,
 0x60001, 0x60009, 0xe0001, 0xe0009, 0x60005, 0x6000d, 0xe0005, 0xe000d,
 0x20003, 0x2000b, 0xa0003, 0xa000b, 0x20007, 0x2000f, 0xa0007, 0xa000f,
 0x60003, 0x6000b, 0xe0003, 0xe000b, 0x60007, 0x6000f, 0xe0007, 0xe000f,
 0x10000, 0x10008, 0x90000, 0x90008, 0x10004, 0x1000c, 0x90004, 0x9000c,
 0x50000, 0x50008, 0xd0000, 0xd0008, 0x50004, 0x5000c, 0xd0004, 0xd000c,
 0x10002, 0x1000a, 0x90002, 0x9000a, 0x10006, 0x1000e, 0x90006, 0x9000e,
 0x50002, 0x5000a, 0xd0002, 0xd000a, 0x50006, 0x5000e, 0xd0006, 0xd000e,
 0x30000, 0x30008, 0xb0000, 0xb0008, 0x30004, 0x3000c, 0xb0004, 0xb000c,
 0x70000, 0x70008, 0xf0000, 0xf0008, 0x70004, 0x7000c, 0xf0004, 0xf000c,
 0x30002, 0x3000a, 0xb0002, 0xb000a, 0x30006, 0x3000e, 0xb0006, 0xb000e,
 0x70002, 0x7000a, 0xf0002, 0xf000a, 0x70006, 0x7000e, 0xf0006, 0xf000e,
 0x10001, 0x10009, 0x90001, 0x90009, 0x10005, 0x1000d, 0x90005, 0x9000d,
 0x50001, 0x50009, 0xd0001, 0xd0009, 0x50005, 0x5000d, 0xd0005, 0xd000d,
 0x10003, 0x1000b, 0x90003, 0x9000b, 0x10007, 0x1000f, 0x90007, 0x9000f,
 0x50003, 0x5000b, 0xd0003, 0xd000b, 0x50007, 0x5000f, 0xd0007, 0xd000f,
 0x30001, 0x30009, 0xb0001, 0xb0009, 0x30005, 0x3000d, 0xb0005, 0xb000d,
 0x70001, 0x70009, 0xf0001, 0xf0009, 0x70005, 0x7000d, 0xf0005, 0xf000d,
 0x30003, 0x3000b, 0xb0003, 0xb000b, 0x30007, 0x3000f, 0xb0007, 0xb000f,
 0x70003, 0x7000b, 0xf0003, 0xf000b, 0x70007, 0x7000f, 0xf0007, 0xf000f,
};

/*
 *  Table for separating and reversing bits in a ldepth 2 bitmap.
 *  This aids in coverting a little endian ldepth 1 bitmap into the
 *  4 big-endian ldepth 0 bitmaps used for the VGA bit planes.
 *
 *	if the bits in uchar x are labeled
 *		76543210
 *	then l1revsep[x] yields a ushort with bits
 *		______37______26______15______04
 *	where _ represents a bit whose value is 0.
 *
 *  This table is used by l2update() in l.s.  l2update is implemented
 *  in assembler for speed.
 *
 */
ulong l2revsep[] = {
 0x0000000, 0x0000002, 0x0000200, 0x0000202, 0x0020000, 0x0020002, 0x0020200, 0x0020202,
 0x2000000, 0x2000002, 0x2000200, 0x2000202, 0x2020000, 0x2020002, 0x2020200, 0x2020202,
 0x0000001, 0x0000003, 0x0000201, 0x0000203, 0x0020001, 0x0020003, 0x0020201, 0x0020203,
 0x2000001, 0x2000003, 0x2000201, 0x2000203, 0x2020001, 0x2020003, 0x2020201, 0x2020203,
 0x0000100, 0x0000102, 0x0000300, 0x0000302, 0x0020100, 0x0020102, 0x0020300, 0x0020302,
 0x2000100, 0x2000102, 0x2000300, 0x2000302, 0x2020100, 0x2020102, 0x2020300, 0x2020302,
 0x0000101, 0x0000103, 0x0000301, 0x0000303, 0x0020101, 0x0020103, 0x0020301, 0x0020303,
 0x2000101, 0x2000103, 0x2000301, 0x2000303, 0x2020101, 0x2020103, 0x2020301, 0x2020303,
 0x0010000, 0x0010002, 0x0010200, 0x0010202, 0x0030000, 0x0030002, 0x0030200, 0x0030202,
 0x2010000, 0x2010002, 0x2010200, 0x2010202, 0x2030000, 0x2030002, 0x2030200, 0x2030202,
 0x0010001, 0x0010003, 0x0010201, 0x0010203, 0x0030001, 0x0030003, 0x0030201, 0x0030203,
 0x2010001, 0x2010003, 0x2010201, 0x2010203, 0x2030001, 0x2030003, 0x2030201, 0x2030203,
 0x0010100, 0x0010102, 0x0010300, 0x0010302, 0x0030100, 0x0030102, 0x0030300, 0x0030302,
 0x2010100, 0x2010102, 0x2010300, 0x2010302, 0x2030100, 0x2030102, 0x2030300, 0x2030302,
 0x0010101, 0x0010103, 0x0010301, 0x0010303, 0x0030101, 0x0030103, 0x0030301, 0x0030303,
 0x2010101, 0x2010103, 0x2010301, 0x2010303, 0x2030101, 0x2030103, 0x2030301, 0x2030303,
 0x1000000, 0x1000002, 0x1000200, 0x1000202, 0x1020000, 0x1020002, 0x1020200, 0x1020202,
 0x3000000, 0x3000002, 0x3000200, 0x3000202, 0x3020000, 0x3020002, 0x3020200, 0x3020202,
 0x1000001, 0x1000003, 0x1000201, 0x1000203, 0x1020001, 0x1020003, 0x1020201, 0x1020203,
 0x3000001, 0x3000003, 0x3000201, 0x3000203, 0x3020001, 0x3020003, 0x3020201, 0x3020203,
 0x1000100, 0x1000102, 0x1000300, 0x1000302, 0x1020100, 0x1020102, 0x1020300, 0x1020302,
 0x3000100, 0x3000102, 0x3000300, 0x3000302, 0x3020100, 0x3020102, 0x3020300, 0x3020302,
 0x1000101, 0x1000103, 0x1000301, 0x1000303, 0x1020101, 0x1020103, 0x1020301, 0x1020303,
 0x3000101, 0x3000103, 0x3000301, 0x3000303, 0x3020101, 0x3020103, 0x3020301, 0x3020303,
 0x1010000, 0x1010002, 0x1010200, 0x1010202, 0x1030000, 0x1030002, 0x1030200, 0x1030202,
 0x3010000, 0x3010002, 0x3010200, 0x3010202, 0x3030000, 0x3030002, 0x3030200, 0x3030202,
 0x1010001, 0x1010003, 0x1010201, 0x1010203, 0x1030001, 0x1030003, 0x1030201, 0x1030203,
 0x3010001, 0x3010003, 0x3010201, 0x3010203, 0x3030001, 0x3030003, 0x3030201, 0x3030203,
 0x1010100, 0x1010102, 0x1010300, 0x1010302, 0x1030100, 0x1030102, 0x1030300, 0x1030302,
 0x3010100, 0x3010102, 0x3010300, 0x3010302, 0x3030100, 0x3030102, 0x3030300, 0x3030302,
 0x1010101, 0x1010103, 0x1010301, 0x1010303, 0x1030101, 0x1030103, 0x1030301, 0x1030303,
 0x3010101, 0x3010103, 0x3010301, 0x3010303, 0x3030101, 0x3030103, 0x3030301, 0x3030303,
};
.
201a
	error(Eperm);
	return 0;
.
196,200d
190c
		if (offset + n >= 0x8000 || offset < 0x300)
.
186c
		setscreen(maxx, maxy, ldepth);
.
183,184c
		if(*cp!=0)
			cp++;
		switch(strtoul(cp, &cp, 0)){
		case 1:
			ldepth = 0;
			break;
		case 2:
			ldepth = 1;
			break;
		case 4:
			ldepth = 2;
			break;
		case 8:
			ldepth = 3;
			break;
		default:
			ldepth = -1;
		}
		if(maxx == 0 || maxy == 0
		|| maxx > 1280 || maxy > 1024
		|| ldepth > 3 || ldepth < 0)
.
181a
		if(*cp!=0)
			cp++;
.
176,177d
174c
		if(offset != 0 || n >= sizeof(cbuf))
.
172c
		memmove(cbuf, buf, n);
		cbuf[n] = 0;
		if(cp = strchr(cbuf, '\n'))
			*cp = 0;
		for(vp = vgacards; vp->name; vp++)
			if(strcmp(cbuf, vp->name) == 0){
				vgacard = vp;
				return n;
			}
		error(Ebadarg);
.
170c
		if(offset != 0 || n >= sizeof(cbuf) || n < 1)
.
165,168d
159,160c
	char cbuf[64], *cp;
	Vgacard *vp;
	int port, maxx, maxy, ldepth;
.
153a
	error(Eperm);
	return 0;
.
146,152d
141c
		if (offset + n >= 0x8000 || offset < 0x300)
.
137,139c
		sprint(cbuf, "%dx%dx%d", gscreen.r.max.x, gscreen.r.max.y,
			1<<gscreen.ldepth);
		return readstr(offset, buf, n, cbuf);
	case Qvgatype:
		return readstr(offset, buf, n, vgacard->name);
.
132,135d
127c
	char cbuf[64];
.
124d
97,104d
87,91c
	devstat(c, dp, vgadir, Nvga, devgen);
.
52,61d
48c
vgareset(void)
{
	vgacard = &vgacards[Generic];
.
44,46d
41d
39a
	"vgatype",	{Qvgatype},	0,		0666,
.
37,38d
35a
/*
 *  640x480 display, 1, 2, or 4 bit color.
 */
VGAmode mode12 = 
{
	/* general */
	0xe7, 0x00,
	/* sequence */
	0x03, 0x01, 0x0f, 0x00, 0x06,
	/* crt */
	0x65, 0x4f, 0x50, 0x88, 0x55, 0x9a, 0x09, 0x3e,
	0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0xe8, 0x8b, 0xdf, 0x28, 0x00, 0xe7, 0x04, 0xe3,
	0xff,
	/* graphics */
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0f,
	0xff,
	/* attribute */
	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
	0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
	0x01, 0x10, 0x0f, 0x00, 0x00,
};

/*
 *  320x200 display, 8 bit color.
 */
VGAmode mode13 = 
{
	/* general */
	0x63, 0x00,
	/* sequence */
	0x03, 0x01, 0x0f, 0x00, 0x0e,
	/* crt */
	0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80, 0xbf, 0x1f,
	0x00, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28,
	0x9c, 0x8e, 0x8f, 0x28, 0x40, 0x96, 0xb9, 0xa3,
	0xff,
	/* graphics */
	0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0f,
	0xff,
	/* attribute */
	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
	0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
	0x41, 0x10, 0x0f, 0x00, 0x00,
};

static	Rectangle mbb;
static	Rectangle NULLMBB = {10000, 10000, -10000, -10000};
static	void nopage(int), tsengpage(int);;

/*
 *  definitions of known cards
 */
typedef struct Vgacard	Vgacard;
struct Vgacard
{
	char	*name;
	void	(*setpage)(int);
};

enum
{
	Tseng,		/* tseng labs te4000 */
	Generic,
};

Vgacard vgacards[] =
{
[Tseng]		{ "tseng", tsengpage, },
[Generic]	{ "generic", nopage, },
		{ 0, 0, },
};

Vgacard	*vgacard;	/* current vga card */

/*
 *  vga device directory
 */
enum
{
	Qdir=		0,
	Qvgasize=	1,
	Qvgatype=	2,
	Qvgaport=	3,
	Nvga=		4,
};
.
26,33c
typedef struct VGAmode	VGAmode;
struct VGAmode
{
	uchar	general[2];
	uchar	sequencer[5];
	uchar	crt[0x19];
	uchar	graphics[9];
	uchar	attribute[0x15];
.
18,24c
/*
 *  'soft' screen bitmap
 */
.
16a
#define MAXX	640
#define MAXY	480
.
15c
 *  screen dimensions
.
13a
#define	MINX	8

struct{
	Point	pos;
	int	bwid;
}out;

/* imported */
extern	GSubfont defont0;
extern	Cursor arrow;
extern	GBitmap cursorback;

/* exported */
GSubfont *defont;
int islittle = 1;		/* little endian bit ordering in bytes */
GBitmap	gscreen;

/* local */
static	Lock vgalock;
static	GBitmap	vgascreen;
static	ulong colormap[256][3];
static	int cga = 1;		/* true if in cga mode */

.
11c
#include	"screen.h"
.
## diffname pc/devvga.c 1992/1121
## diff -e /n/bootesdump/1992/1119/sys/src/9/pc/devvga.c /n/bootesdump/1992/1121/sys/src/9/pc/devvga.c
681c
	off = r.min.y * gscreen.width * BY2WD
		+ (r.min.x>>(3 - gscreen.ldepth));
.
663a
		r.min.x &= ~7;		/* 8 pixel allignment for l2update() */
.
661c
			len++;		/* 8 pixel allignment for l1update() */
.
657c
		r.min.x &= ~15;		/* 8 pixel allignment for l1update() */
.
650c
		r.min.x &= ~15;		/* 16 pixel allignment for l0update() */
.
## diffname pc/devvga.c 1992/1124
## diff -e /n/bootesdump/1992/1121/sys/src/9/pc/devvga.c /n/bootesdump/1992/1124/sys/src/9/pc/devvga.c
616a
}
static void
parapage(int page)
{
	grout(9, page<<4);
.
124a
[Pvga1a]	{ "pvga1a", parapage, },
.
119a
	Pvga1a,		/* paradise */
.
105c
static	void nopage(int), tsengpage(int), parapage(int);
.
## diffname pc/devvga.c 1992/1209
## diff -e /n/bootesdump/1992/1124/sys/src/9/pc/devvga.c /n/bootesdump/1992/1209/sys/src/9/pc/devvga.c
590,591c
	mousescreenupdate();
.
## diffname pc/devvga.c 1992/1215
## diff -e /n/bootesdump/1992/1209/sys/src/9/pc/devvga.c /n/bootesdump/1992/1215/sys/src/9/pc/devvga.c
127a
[Ati]		{ "ati", nopage, },
.
120a
	Ati,
.
## diffname pc/devvga.c 1992/1216
## diff -e /n/bootesdump/1992/1215/sys/src/9/pc/devvga.c /n/bootesdump/1992/1216/sys/src/9/pc/devvga.c
614a
}
static void
tridentpage(int page)
{
	srout(0x0e, page^0x02);	/* yes, the page bit needs to be toggled! */
.
547a

	/*
	 * clear screen
	 */
	mbb = gscreen.r;
	vgaupdate();
.
501d
289a
		cursoron(1);
.
288a
		cursoroff(1);
.
225a
		*/
.
223a
		/* at the moment, I need freedom for the ATI card - ches
.
129d
127a
[Trident]	{ "trident", tridentpage, },
.
126a
[Ati]		{ "ati", nopage, },
.
121c
	Trident,	/* Trident 8900 */
	Tseng,		/* tseng labs te4000 */
.
119c
	Ati,		/* ATI */
.
105c
static	void nopage(int), tsengpage(int), tridentpage(int), parapage(int);
static	void vgaupdate(void);
.
## diffname pc/devvga.c 1992/1217
## diff -e /n/bootesdump/1992/1216/sys/src/9/pc/devvga.c /n/bootesdump/1992/1217/sys/src/9/pc/devvga.c
301a
		*/
.
299a
		/*
.
## diffname pc/devvga.c 1993/0102
## diff -e /n/bootesdump/1992/1217/sys/src/9/pc/devvga.c /n/bootesdump/1993/0102/sys/src/9/pc/devvga.c
522c
	splx(s);
	if(oldp)
		xfree(oldp);
.
514,515c
	oldp = gscreen.base;
	s = splhi();
.
491c
		error(Enobitstore);
.
478,479c
	int len, vgamaxy, width, i, x, s;
	uchar *p, *oldp;
.
## diffname pc/devvga.c 1993/0103
## diff -e /n/bootesdump/1993/0102/sys/src/9/pc/devvga.c /n/bootesdump/1993/0103/sys/src/9/pc/devvga.c
521c
	gscreen.base = p;
.
479c
	ulong *p, *oldp;
.
## diffname pc/devvga.c 1993/0106
## diff -e /n/bootesdump/1993/0103/sys/src/9/pc/devvga.c /n/bootesdump/1993/0106/sys/src/9/pc/devvga.c
635c
	srout(0x0e, page^0x02);
.
632a
atipage(int page)
{
	/* the ext register is in the ATI ROM at a fixed address */
	ushort extreg = *((ushort *)0x800C0010);
	uchar v;

	outb(extreg, 0xb2);
	v = (inb(extreg+1) & 0xe1) | (page<<1);
	outb(extreg, 0xb2);
	outb(extreg+1, v);
}
static void
.
631a
/*
 * The following code is unproven: we haven't got the
 * ATI stuff to work yet.
 */
.
256c
		for(vp = vgachips; vp->name; vp++)
.
159c
	vgacard = &vgachips[Generic];
.
148c
	Nvga=		3,
.
129c
[Ati]		{ "ati", atipage, },
.
127c
Vgacard vgachips[] =
.
105a
static	void atipage(int);
.
## diffname pc/devvga.c 1993/0108
## diff -e /n/bootesdump/1993/0106/sys/src/9/pc/devvga.c /n/bootesdump/1993/0108/sys/src/9/pc/devvga.c
652c
	srout(0x0e, (srin(0xe)&0xf0) | page^0x02);
.
327a
uchar
srin(int i) {
	outb(SRX, i);
	return inb(SR);
}
.
## diffname pc/devvga.c 1993/0115
## diff -e /n/bootesdump/1993/0108/sys/src/9/pc/devvga.c /n/bootesdump/1993/0115/sys/src/9/pc/devvga.c
497a
	memset(p, 0xff, len);
.
## diffname pc/devvga.c 1993/0206
## diff -e /n/bootesdump/1993/0115/sys/src/9/pc/devvga.c /n/bootesdump/1993/0206/sys/src/9/pc/devvga.c
658c
	srout(0x0e, (srin(0x0e)&0xf0) | page^0x02);
.
654a
/*
 * The following assumes that the new mode registers have been selected.
 */
.
## diffname pc/devvga.c 1993/0226
## diff -e /n/bootesdump/1993/0206/sys/src/9/pc/devvga.c /n/bootesdump/1993/0226/sys/src/9/pc/devvga.c
934,940d
## diffname pc/devvga.c 1993/0402
## diff -e /n/bootesdump/1993/0226/sys/src/9/pc/devvga.c /n/bootesdump/1993/0402/sys/src/9/pc/devvga.c
295a
		bbinit();
.
## diffname pc/devvga.c 1993/0409
## diff -e /n/bootesdump/1993/0402/sys/src/9/pc/devvga.c /n/bootesdump/1993/0409/sys/src/9/pc/devvga.c
564a
	bbinit();
.
296d
## diffname pc/devvga.c 1993/0915
## diff -e /n/bootesdump/1993/0409/sys/src/9/pc/devvga.c /n/fornaxdump/1993/0915/sys/src/brazil/pc/devvga.c
932d
928c
void
.
925d
921,922c
void
hwcursset(ulong *s, ulong *c, int ox, int oy)
.
672c
	grout(0x9, page<<4);
.
669a
cirruspage(int page)
{
	grout(0x9, page<<4);
}
static void
.
662c
	srout(0xe, (srin(0xe)&0xf0) | page^0x2);
.
133a
[Cirrus]	{ "cirrus", cirruspage, },
.
124a
	Cirrus,		/* Cirrus CLGD542X */
.
106c
static	void atipage(int), cirruspage(int);
.
## diffname pc/devvga.c 1993/1116
## diff -e /n/fornaxdump/1993/0915/sys/src/brazil/pc/devvga.c /n/fornaxdump/1993/1116/sys/src/brazil/pc/devvga.c
1065a

/*
 *  reverse pixels into little endian order
 */
uchar revtab0[] = {
 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff,
};
uchar revtab1[] = {
 0x00, 0x40, 0x80, 0xc0, 0x10, 0x50, 0x90, 0xd0,
 0x20, 0x60, 0xa0, 0xe0, 0x30, 0x70, 0xb0, 0xf0,
 0x04, 0x44, 0x84, 0xc4, 0x14, 0x54, 0x94, 0xd4,
 0x24, 0x64, 0xa4, 0xe4, 0x34, 0x74, 0xb4, 0xf4,
 0x08, 0x48, 0x88, 0xc8, 0x18, 0x58, 0x98, 0xd8,
 0x28, 0x68, 0xa8, 0xe8, 0x38, 0x78, 0xb8, 0xf8,
 0x0c, 0x4c, 0x8c, 0xcc, 0x1c, 0x5c, 0x9c, 0xdc,
 0x2c, 0x6c, 0xac, 0xec, 0x3c, 0x7c, 0xbc, 0xfc,
 0x01, 0x41, 0x81, 0xc1, 0x11, 0x51, 0x91, 0xd1,
 0x21, 0x61, 0xa1, 0xe1, 0x31, 0x71, 0xb1, 0xf1,
 0x05, 0x45, 0x85, 0xc5, 0x15, 0x55, 0x95, 0xd5,
 0x25, 0x65, 0xa5, 0xe5, 0x35, 0x75, 0xb5, 0xf5,
 0x09, 0x49, 0x89, 0xc9, 0x19, 0x59, 0x99, 0xd9,
 0x29, 0x69, 0xa9, 0xe9, 0x39, 0x79, 0xb9, 0xf9,
 0x0d, 0x4d, 0x8d, 0xcd, 0x1d, 0x5d, 0x9d, 0xdd,
 0x2d, 0x6d, 0xad, 0xed, 0x3d, 0x7d, 0xbd, 0xfd,
 0x02, 0x42, 0x82, 0xc2, 0x12, 0x52, 0x92, 0xd2,
 0x22, 0x62, 0xa2, 0xe2, 0x32, 0x72, 0xb2, 0xf2,
 0x06, 0x46, 0x86, 0xc6, 0x16, 0x56, 0x96, 0xd6,
 0x26, 0x66, 0xa6, 0xe6, 0x36, 0x76, 0xb6, 0xf6,
 0x0a, 0x4a, 0x8a, 0xca, 0x1a, 0x5a, 0x9a, 0xda,
 0x2a, 0x6a, 0xaa, 0xea, 0x3a, 0x7a, 0xba, 0xfa,
 0x0e, 0x4e, 0x8e, 0xce, 0x1e, 0x5e, 0x9e, 0xde,
 0x2e, 0x6e, 0xae, 0xee, 0x3e, 0x7e, 0xbe, 0xfe,
 0x03, 0x43, 0x83, 0xc3, 0x13, 0x53, 0x93, 0xd3,
 0x23, 0x63, 0xa3, 0xe3, 0x33, 0x73, 0xb3, 0xf3,
 0x07, 0x47, 0x87, 0xc7, 0x17, 0x57, 0x97, 0xd7,
 0x27, 0x67, 0xa7, 0xe7, 0x37, 0x77, 0xb7, 0xf7,
 0x0b, 0x4b, 0x8b, 0xcb, 0x1b, 0x5b, 0x9b, 0xdb,
 0x2b, 0x6b, 0xab, 0xeb, 0x3b, 0x7b, 0xbb, 0xfb,
 0x0f, 0x4f, 0x8f, 0xcf, 0x1f, 0x5f, 0x9f, 0xdf,
 0x2f, 0x6f, 0xaf, 0xef, 0x3f, 0x7f, 0xbf, 0xff,
};
uchar revtab2[] = {
 0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70,
 0x80, 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0,
 0x01, 0x11, 0x21, 0x31, 0x41, 0x51, 0x61, 0x71,
 0x81, 0x91, 0xa1, 0xb1, 0xc1, 0xd1, 0xe1, 0xf1,
 0x02, 0x12, 0x22, 0x32, 0x42, 0x52, 0x62, 0x72,
 0x82, 0x92, 0xa2, 0xb2, 0xc2, 0xd2, 0xe2, 0xf2,
 0x03, 0x13, 0x23, 0x33, 0x43, 0x53, 0x63, 0x73,
 0x83, 0x93, 0xa3, 0xb3, 0xc3, 0xd3, 0xe3, 0xf3,
 0x04, 0x14, 0x24, 0x34, 0x44, 0x54, 0x64, 0x74,
 0x84, 0x94, 0xa4, 0xb4, 0xc4, 0xd4, 0xe4, 0xf4,
 0x05, 0x15, 0x25, 0x35, 0x45, 0x55, 0x65, 0x75,
 0x85, 0x95, 0xa5, 0xb5, 0xc5, 0xd5, 0xe5, 0xf5,
 0x06, 0x16, 0x26, 0x36, 0x46, 0x56, 0x66, 0x76,
 0x86, 0x96, 0xa6, 0xb6, 0xc6, 0xd6, 0xe6, 0xf6,
 0x07, 0x17, 0x27, 0x37, 0x47, 0x57, 0x67, 0x77,
 0x87, 0x97, 0xa7, 0xb7, 0xc7, 0xd7, 0xe7, 0xf7,
 0x08, 0x18, 0x28, 0x38, 0x48, 0x58, 0x68, 0x78,
 0x88, 0x98, 0xa8, 0xb8, 0xc8, 0xd8, 0xe8, 0xf8,
 0x09, 0x19, 0x29, 0x39, 0x49, 0x59, 0x69, 0x79,
 0x89, 0x99, 0xa9, 0xb9, 0xc9, 0xd9, 0xe9, 0xf9,
 0x0a, 0x1a, 0x2a, 0x3a, 0x4a, 0x5a, 0x6a, 0x7a,
 0x8a, 0x9a, 0xaa, 0xba, 0xca, 0xda, 0xea, 0xfa,
 0x0b, 0x1b, 0x2b, 0x3b, 0x4b, 0x5b, 0x6b, 0x7b,
 0x8b, 0x9b, 0xab, 0xbb, 0xcb, 0xdb, 0xeb, 0xfb,
 0x0c, 0x1c, 0x2c, 0x3c, 0x4c, 0x5c, 0x6c, 0x7c,
 0x8c, 0x9c, 0xac, 0xbc, 0xcc, 0xdc, 0xec, 0xfc,
 0x0d, 0x1d, 0x2d, 0x3d, 0x4d, 0x5d, 0x6d, 0x7d,
 0x8d, 0x9d, 0xad, 0xbd, 0xcd, 0xdd, 0xed, 0xfd,
 0x0e, 0x1e, 0x2e, 0x3e, 0x4e, 0x5e, 0x6e, 0x7e,
 0x8e, 0x9e, 0xae, 0xbe, 0xce, 0xde, 0xee, 0xfe,
 0x0f, 0x1f, 0x2f, 0x3f, 0x4f, 0x5f, 0x6f, 0x7f,
 0x8f, 0x9f, 0xaf, 0xbf, 0xcf, 0xdf, 0xef, 0xff,
};

void
pixreverse(uchar *p, int len, int ldepth)
{
	uchar *e;
	uchar *tab;

	switch(ldepth){
	case 0:
		tab = revtab0;
		break;
	case 1:
		tab = revtab1;
		break;
	case 2:
		tab = revtab2;
		break;
	default:
		return;
	}

	for(e = p + len; p < e; p++)
		*p = tab[*p];
}
.
941,967d
928,939d
924c
	unlock(&screenlock);
.
916c
	lock(&screenlock);
.
909c
	unlock(&screenlock);
.
905c
	lock(&screenlock);
.
892c
	mbbpt(Pt(cursor.x, cursor.y+h));
.
858,890c
		cursor = gsubfstring(&gscreen, cursor, &defont0, buf, S);
.
853,856c
	mbbpt(cursor);
	switch(buf[0]) {
	case '\n':
		if(cursor.y+h >= window.max.y)
			scroll();
		cursor.y += h;
		screenputc("\r");
		break;
	case '\r':
		cursor.x = window.min.x;
		break;
	case '\t':
		pos = (cursor.x-window.min.x)/w;
		pos = 8-(pos%8);
		cursor.x += pos*w;
		break;
	case '\b':
		if(cursor.x-w >= window.min.x)
			cursor.x -= w;
		break;
	default:
		if(cursor.x >= window.max.x-w)
			screenputc("\n");
.
848,851c
	int pos;
.
845,846c
static void
screenputc(char *buf)
.
833,842c
	o = 5*h;
	r = Rpt(Pt(window.min.x, window.min.y+o), window.max);
	gbitblt(&gscreen, window.min, &gscreen, r, S);
	r = Rpt(Pt(window.min.x, window.max.y-o), window.max);
	gbitblt(&gscreen, r.min, &gscreen, r, Zero);
	cursor.y -= o;
	isscroll = 1;
.
830a
	int o;
.
828,829c
static void
scroll(void)
.
821c
static void
.
774,790d
699,771c
	screenupdate();
	unlock(&screenlock);
.
688,696c
	if(canlock(&screenlock) == 0)
.
682,686c
void
mousescreenupdate(void)
.
657a

.
653,656c
	outb(extreg, 0xAE);
	v = (inb(extreg+1) & 0xFC)|((page>>4) & 0x03);
	outs(extreg, (v<<8)|0xAE);

	outb(extreg, 0xB2);
	v = (inb(extreg+1) & 0xE1)|((page & 0x0F)<<1);
	outs(extreg, (v<<8)|0xB2);
.
643,644c
 * Extended registers can be read with inb(), but must be
 * written with outs(). The index must be written each time
 * before the register is accessed.
 * The page bits are spread across registers 0xAE and 0xB2.
 * This can go away when we use the memory aperture.
.
641a

.
618d
579,601c
	USED(x, y);
.
577c
hwcursmove(int x, int y)
.
486,573c
	USED(s, c, ox, oy);
.
484c
hwcursset(ulong *s, ulong *c, int ox, int oy)
.
482a
/*
 *  just in case we have one
 */
.
432,433c
static void
printmode(VGAmode *v)
{
.
408,409c
static void
getmode(VGAmode *v)
{
.
377c
static void
.
369,370c
static void
.
355c
static void
.
349c
static void
.
343c
static void
.
335c
static void
.
330c
/*
 *  start the screen in CGA mode.  Create the fonts for VGA.
 */
void
screeninit(void)
{
	int i;
	ulong *l;

	/*
	 *  swizzle the font longs.  we do both byte and bit swizzling
	 *  since the font is initialized with big endian longs.
	 */
	defont = &defont0;
	l = defont->bits->base;
	for(i = defont->bits->width*Dy(defont->bits->r); i > 0; i--, l++)
		*l = (*l<<24) | ((*l>>8)&0x0000ff00) | ((*l<<8)&0x00ff0000) | (*l>>24);
	pixreverse((uchar*)defont->bits->base,
		defont->bits->width*BY2WD*Dy(defont->bits->r), 0);

	/*
	 *  start in CGA mode
	 */
	cga = 1;
	crout(0x0a, 0xff);		/* turn off cursor */
	memset(CGASCREEN, 0, CGAWIDTH*CGAHEIGHT);
}

/*
 *  reconfigure screen shape
 */
static void
setscreen(int maxx, int maxy, int ldepth)
{
	int len, vgamaxy, width, i, x, s;
	ulong *p, *oldp;

	if(ldepth == 3)
		setmode(&mode13);
	else
		setmode(&mode12);

	/* allocate a new soft bitmap area */
	width = (maxx*(1<<ldepth))/32;
	len = width * BY2WD * maxy;
	p = xalloc(len);
	if(p == 0)
		error(Enobitstore);
	memset(p, 0xff, len);
	mbb = NULLMBB;

	/*
	 *  zero hard screen and setup a bitmap for the new size
	 */
	if(ldepth == 3)
		vgascreen.ldepth = 3;
	else
		vgascreen.ldepth = 0;
	vgascreen.width = (maxx*(1<<vgascreen.ldepth))/32;
	if(maxy > (64*1024)/(vgascreen.width*BY2WD))
		vgamaxy = (64*1024)/(vgascreen.width*BY2WD);
	else
		vgamaxy = maxy;
	vgascreen.base = (void*)SCREENMEM;
	vgascreen.r.min = Pt(0, 0);
	vgascreen.r.max = Pt(maxx, vgamaxy);
	vgascreen.clipr = vgascreen.r;

	/*
	 *  setup new soft screen, free memory for old screen
	 */
	oldp = gscreen.base;
	s = splhi();
	gscreen.ldepth = ldepth;
	gscreen.width = width;
	gscreen.r.min = Pt(0, 0);
	gscreen.r.max = Pt(maxx, maxy);
	gscreen.clipr = gscreen.r;
	gscreen.base = p;
	splx(s);
	if(oldp)
		xfree(oldp);

	/*
	 *  default color map
	 */
	switch(ldepth){
	case 3:
		for(i = 0; i < 256; i++)
			setcolor(i, x3to32(i>>5), x3to32(i>>2), x3to32(i<<1));
		break;
	case 2:
	case 1:
	case 0:
		gscreen.ldepth = 3;
		for(i = 0; i < 16; i++){
			x = x6to32((i*63)/15);
			setcolor(i, x, x, x);
		}
		gscreen.ldepth = ldepth;
		break;
	}
	cga = 0;

	/*
	 * display white window
	 */
	mbb = gscreen.r;
	screenupdate();

	/*
	 *  set up inset system window
	 */
	h = defont0.height;
	w = defont0.info[' '].width;

	window.min = Pt(50, 50);
	window.max = add(window.min, Pt(10+w*64, 10+h*24));

	gbitblt(&gscreen, window.min, &gscreen, window, Zero);
	window = inset(window, 5);
	cursor = window.min;
	window.max.y = window.min.y+((window.max.y-window.min.y)/h)*h;
	hwcurs = 0;

	mbb = gscreen.r;
	screenupdate();
}

/*
 * paste tile into soft screen.
 * tile is at location r, first pixel in *data.  tl is length of scan line to insert,
 * l is amount to advance data after each scan line.
 */
void
screenload(Rectangle r, uchar *data, int tl, int l)
{
	int y, lpart, rpart, mx, m, mr;
	uchar *q;
	extern void cursorlock(Rectangle);
	extern void cursorunlock(void);

	if(!rectclip(&r, gscreen.r) || tl<=0)
		return;
	lock(&screenlock);
	cursorlock(r);
	screenupdate();
	q = gbaddr(&gscreen, r.min);
	mx = 7>>gscreen.ldepth;
	lpart = (r.min.x & mx) << gscreen.ldepth;
	rpart = (r.max.x & mx) << gscreen.ldepth;
	m = 0xFF >> lpart;
	mr = 0xFF ^ (0xFF >> rpart);
	/* may need to do bit insertion on edges */
	if(l == 1){	/* all in one byte */
		if(rpart)
			m ^= 0xFF >> rpart;
		for(y=r.min.y; y<r.max.y; y++){
			*q ^= (*data^*q) & m;
			q += gscreen.width*sizeof(ulong);
			data += l;
		}
	}else if(lpart==0 && rpart==0){	/* easy case */
		for(y=r.min.y; y<r.max.y; y++){
			memmove(q, data, tl);
			q += gscreen.width*sizeof(ulong);
			data += l;
		}
	}else if(rpart==0){
		for(y=r.min.y; y<r.max.y; y++){
			*q ^= (*data^*q) & m;
			if(tl > 1)
				memmove(q+1, data+1, tl-1);
			q += gscreen.width*sizeof(ulong);
			data += l;
		}
	}else if(lpart == 0){
		for(y=r.min.y; y<r.max.y; y++){
			if(tl > 1)
				memmove(q, data, tl-1);
			q[tl-1] ^= (data[tl-1]^q[tl-1]) & mr;
			q += gscreen.width*sizeof(ulong);
			data += l;
		}
	}else for(y=r.min.y; y<r.max.y; y++){
			*q ^= (*data^*q) & m;
			if(l > 2)
				memmove(q+1, data+1, tl-2);
			q[tl-1] ^= (data[tl-1]^q[l-1]) & mr;
			q += gscreen.width*sizeof(ulong);
			data += l;
		}
	mbbrect(r);
	screenupdate();
	cursorunlock();
	screenupdate();
	unlock(&screenlock);
}

/*
 *  copy litte endian soft screen to big endian hard screen
 */
void
screenupdate(void)
{
	uchar *sp, *hp, *edisp;
	int y, len, incs, inch, off, page;
	Rectangle r;
	void* (*f)(void*, void*, long);

	r = mbb;
	mbb = NULLMBB;

	if(Dy(r) < 0)
		return;

	if(r.min.x < 0)
		r.min.x = 0;
	if(r.min.y < 0)
		r.min.y = 0;
	if(r.max.x > gscreen.r.max.x)
		r.max.x = gscreen.r.max.x;
	if(r.max.y > gscreen.r.max.y)
		r.max.y = gscreen.r.max.y;

	incs = gscreen.width * BY2WD;
	inch = vgascreen.width * BY2WD;

	switch(gscreen.ldepth){
	case 0:
		r.min.x &= ~15;		/* 16 pixel allignment for l0update() */
		f = l0update;
		len = (r.max.x + 7)/8 - r.min.x/8;
		if(len & 1)
			len++;		/* 16 bit allignment for l0update() */
		break;
	case 1:
		r.min.x &= ~15;		/* 8 pixel allignment for l1update() */
		f = l1update;
		len = (r.max.x + 7)/8 - r.min.x/8;
		if(len & 1)
			len++;		/* 8 pixel allignment for l1update() */
		break;
	case 2:
		r.min.x &= ~7;		/* 8 pixel allignment for l2update() */
		f = l2update;
		len = (r.max.x + 7)/8 - r.min.x/8;
		break;
	case 3:
		f = memmove;
		len = r.max.x - r.min.x;
		break;
	default:
		return;
	}
	if(len < 1)
		return;

	off = r.min.y * vgascreen.width * BY2WD + (r.min.x>>(3 - vgascreen.ldepth));
	page = off>>16;
	off &= (1<<16)-1;
	hp = ((uchar*)vgascreen.base) + off;
	off = r.min.y * gscreen.width * BY2WD
		+ (r.min.x>>(3 - gscreen.ldepth));
	sp = ((uchar*)gscreen.base) + off;

	edisp = ((uchar*)vgascreen.base) + 64*1024;
	vgacard->setpage(page);
	for(y = r.min.y; y < r.max.y; y++){
		if(hp + inch < edisp){
			f(hp, sp, len);
			sp += incs;
			hp += inch;
		} else {
			off = edisp - hp;
			if(off <= len){
				if(off > 0)
					f(hp, sp, off);
				vgacard->setpage(++page);
				if(len - off > 0)
					f(vgascreen.base, sp+off, len - off);
			} else {
				f(hp, sp, len);
				vgacard->setpage(++page);
			}
			sp += incs;
			hp += inch - 64*1024;
		}
	}
}

void
screenputs(char *s, int n)
{
	int i;
	Rune r;
	char buf[4];

	if(cga) {
		cgascreenputs(s, n);
		return;
	}

	if((getstatus() & IFLAG) == 0) {
		/* don't deadlock trying to print in interrupt */
		if(!canlock(&screenlock))
			return;	
	} else
		lock(&screenlock);

	while(n > 0) {
		i = chartorune(&r, s);
		if(i == 0){
			s++;
			--n;
			continue;
		}
		memmove(buf, s, i);
		buf[i] = 0;
		n -= i;
		s += i;
		screenputc(buf);
	}
	if(isscroll) {
		mbb = window;
		isscroll = 0;
	}

	screenupdate();
	unlock(&screenlock);
}

/*
 *  accessing registers
 */
static uchar
.
310a
	case Qvgaportw:
		if((n & 01) || (offset & 01))
			error(Ebadarg);
		n /= 2;
		for (sp = buf, port=offset; port<offset+n; port+=2)
			outs(port, *sp++);
		return n*2;
.
309d
302,307c
		for (cp = buf, port=offset; port<offset+n; port++)
.
299d
297d
247a
	ushort *sp;
.
236a
	case Qvgaportw:
		if((n & 01) || (offset & 01))
			error(Ebadarg);
		n /= 2;
		for (sp = buf, port=offset; port<offset+n; port+=2)
			*sp++ = ins(port);
		return n*2;
.
230,234c
		for (cp = buf, port=offset; port<offset+n; port++)
.
218a
	ushort *sp;
.
217c
	uchar *cp;
.
156a
	"vgaportw",	{Qvgaportw},	0,		0666,
.
151c
	Qvgaportw=	4,
	Nvga=		4,
.
143c
 *  vga device
.
141a
/* predefined for the stupid compiler */
static void	setscreen(int, int, int);
static uchar	srin(int);
static void	genout(int, int);
static void	srout(int, int);
static void	grout(int, int);
static void	arout(int, int);
static void	crout(int, int);
static void	setmode(VGAmode*);
static void	getmode(VGAmode*);
static void	printmode(VGAmode*);
static void	cgascreenputc(int);
static void	cgascreenputs(char*, int);
static void	screenputc(char*);
static void	scroll(void);
static ulong	x3to32(uchar);
static ulong	x6to32(uchar);
void	screenupdate(void);
void	pixreverse(uchar*, int, int);
void	mbbrect(Rectangle);

.
128a
static void	nopage(int), tsengpage(int), tridentpage(int), parapage(int);
static void	atipage(int), cirruspage(int);

.
116c
	void	(*setpage)(int);	/* routine to page though display memory */
.
103,108d
46a
/*
 *  VGA modes
 */
.
45a
#define SCREENMEM	(0xA0000 | KZERO)
#define CGASCREEN	((uchar*)(0xB8000 | KZERO))
.
44c
 *  screen memory addresses
.
41a
#define	CGAWIDTH	160
#define	CGAHEIGHT	24
.
39a
#define	MINX	8
.
36a
/* cga screen */
static	int	cga = 1;		/* true if in cga mode */

/* system window */
static	int	isscroll;
static	Rectangle window;
static	int	h, w;
static	Point	cursor;

.
34,35c
static	ulong	colormap[256][3];
static	Rectangle mbb;
static	Rectangle NULLMBB = {10000, 10000, -10000, -10000};
.
31,32c
/* vga screen */
static	Lock	screenlock;
.
28d
23,24d
16,20d
14c
enum
{
	EMISCR=		0x3CC,		/* control sync polarity */
	EMISCW=		0x3C2,
	EFCW=		0x3DA,		/* feature control */
	EFCR=		0x3CA,
	GRX=		0x3CE,		/* index to graphics registers */
	GR=		0x3CF,		/* graphics registers */
	 Grms=		 0x04,		/*  read map select register */
	SRX=		0x3C4,		/* index to sequence registers */
	SR=		0x3C5,		/* sequence registers */
	 Smmask=	 0x02,		/*  map mask */
	CRX=		0x3D4,		/* index to crt registers */
	CR=		0x3D5,		/* crt registers */
	 Cvre=		 0x11,		/*  vertical retrace end */
	ARW=		0x3C0,		/* attribute registers (writing) */
	ARR=		0x3C1,		/* attribute registers (reading) */
	CMRX=		0x3C7,		/* color map read index */
	CMWX=		0x3C8,		/* color map write index */
	CM=		0x3C9,		/* color map data reg */
};
.
11,12d
## diffname pc/devvga.c 1993/1117
## diff -e /n/fornaxdump/1993/1116/sys/src/brazil/pc/devvga.c /n/fornaxdump/1993/1117/sys/src/brazil/pc/devvga.c
1201c
 *  reverse pixels into little endian order (also used by l0update)
.
1157c
 *	then l1revsep[x] yields a ulongt with bits
.
1107c
 *	then l1revsep[x] yields a ulong with bits
.
391a
	 *  arrow is defined as a big endian
	 */
	pixreverse(arrow.set, 2*16, 0);
	pixreverse(arrow.clr, 2*16, 0);

	/*
.
350a
		cursoron(1);
.
349a
		cursoroff(1);
.
35a
extern Cursor arrow;
.
## diffname pc/devvga.c 1993/1217
## diff -e /n/fornaxdump/1993/1117/sys/src/brazil/pc/devvga.c /n/fornaxdump/1993/1217/sys/src/brazil/pc/devvga.c
591c
 *  copy little endian soft screen to big endian hard screen
.
521,523c
 *   paste tile into soft screen.
 *   tile is at location r, first pixel in *data.  tl is length of scan line to insert,
 *   l is amount to advance data after each scan line.
.
## diffname pc/devvga.c 1993/1221
## diff -e /n/fornaxdump/1993/1217/sys/src/brazil/pc/devvga.c /n/fornaxdump/1993/1221/sys/src/brazil/pc/devvga.c
1209,1337d
1174,1206c
ulong l2septab[] = {
 0x0000000, 0x0000001, 0x0000100, 0x0000101, 0x0010000, 0x0010001, 0x0010100, 0x0010101,
 0x1000000, 0x1000001, 0x1000100, 0x1000101, 0x1010000, 0x1010001, 0x1010100, 0x1010101,
 0x0000002, 0x0000003, 0x0000102, 0x0000103, 0x0010002, 0x0010003, 0x0010102, 0x0010103,
 0x1000002, 0x1000003, 0x1000102, 0x1000103, 0x1010002, 0x1010003, 0x1010102, 0x1010103,
 0x0000200, 0x0000201, 0x0000300, 0x0000301, 0x0010200, 0x0010201, 0x0010300, 0x0010301,
 0x1000200, 0x1000201, 0x1000300, 0x1000301, 0x1010200, 0x1010201, 0x1010300, 0x1010301,
 0x0000202, 0x0000203, 0x0000302, 0x0000303, 0x0010202, 0x0010203, 0x0010302, 0x0010303,
 0x1000202, 0x1000203, 0x1000302, 0x1000303, 0x1010202, 0x1010203, 0x1010302, 0x1010303,
 0x0020000, 0x0020001, 0x0020100, 0x0020101, 0x0030000, 0x0030001, 0x0030100, 0x0030101,
 0x1020000, 0x1020001, 0x1020100, 0x1020101, 0x1030000, 0x1030001, 0x1030100, 0x1030101,
 0x0020002, 0x0020003, 0x0020102, 0x0020103, 0x0030002, 0x0030003, 0x0030102, 0x0030103,
 0x1020002, 0x1020003, 0x1020102, 0x1020103, 0x1030002, 0x1030003, 0x1030102, 0x1030103,
 0x0020200, 0x0020201, 0x0020300, 0x0020301, 0x0030200, 0x0030201, 0x0030300, 0x0030301,
 0x1020200, 0x1020201, 0x1020300, 0x1020301, 0x1030200, 0x1030201, 0x1030300, 0x1030301,
 0x0020202, 0x0020203, 0x0020302, 0x0020303, 0x0030202, 0x0030203, 0x0030302, 0x0030303,
 0x1020202, 0x1020203, 0x1020302, 0x1020303, 0x1030202, 0x1030203, 0x1030302, 0x1030303,
 0x2000000, 0x2000001, 0x2000100, 0x2000101, 0x2010000, 0x2010001, 0x2010100, 0x2010101,
 0x3000000, 0x3000001, 0x3000100, 0x3000101, 0x3010000, 0x3010001, 0x3010100, 0x3010101,
 0x2000002, 0x2000003, 0x2000102, 0x2000103, 0x2010002, 0x2010003, 0x2010102, 0x2010103,
 0x3000002, 0x3000003, 0x3000102, 0x3000103, 0x3010002, 0x3010003, 0x3010102, 0x3010103,
 0x2000200, 0x2000201, 0x2000300, 0x2000301, 0x2010200, 0x2010201, 0x2010300, 0x2010301,
 0x3000200, 0x3000201, 0x3000300, 0x3000301, 0x3010200, 0x3010201, 0x3010300, 0x3010301,
 0x2000202, 0x2000203, 0x2000302, 0x2000303, 0x2010202, 0x2010203, 0x2010302, 0x2010303,
 0x3000202, 0x3000203, 0x3000302, 0x3000303, 0x3010202, 0x3010203, 0x3010302, 0x3010303,
 0x2020000, 0x2020001, 0x2020100, 0x2020101, 0x2030000, 0x2030001, 0x2030100, 0x2030101,
 0x3020000, 0x3020001, 0x3020100, 0x3020101, 0x3030000, 0x3030001, 0x3030100, 0x3030101,
 0x2020002, 0x2020003, 0x2020102, 0x2020103, 0x2030002, 0x2030003, 0x2030102, 0x2030103,
 0x3020002, 0x3020003, 0x3020102, 0x3020103, 0x3030002, 0x3030003, 0x3030102, 0x3030103,
 0x2020200, 0x2020201, 0x2020300, 0x2020301, 0x2030200, 0x2030201, 0x2030300, 0x2030301,
 0x3020200, 0x3020201, 0x3020300, 0x3020301, 0x3030200, 0x3030201, 0x3030300, 0x3030301,
 0x2020202, 0x2020203, 0x2020302, 0x2020303, 0x2030202, 0x2030203, 0x2030302, 0x2030303,
 0x3020202, 0x3020203, 0x3020302, 0x3020303, 0x3030202, 0x3030203, 0x3030302, 0x3030303,
.
1166,1167c
 *	then l1septab[x] yields a ulongt with bits
 *		______73______62______51______40
.
1124,1156c
ulong l1septab[] = {
 0x00000, 0x00001, 0x10000, 0x10001, 0x00002, 0x00003, 0x10002, 0x10003,
 0x20000, 0x20001, 0x30000, 0x30001, 0x20002, 0x20003, 0x30002, 0x30003,
 0x00004, 0x00005, 0x10004, 0x10005, 0x00006, 0x00007, 0x10006, 0x10007,
 0x20004, 0x20005, 0x30004, 0x30005, 0x20006, 0x20007, 0x30006, 0x30007,
 0x40000, 0x40001, 0x50000, 0x50001, 0x40002, 0x40003, 0x50002, 0x50003,
 0x60000, 0x60001, 0x70000, 0x70001, 0x60002, 0x60003, 0x70002, 0x70003,
 0x40004, 0x40005, 0x50004, 0x50005, 0x40006, 0x40007, 0x50006, 0x50007,
 0x60004, 0x60005, 0x70004, 0x70005, 0x60006, 0x60007, 0x70006, 0x70007,
 0x00008, 0x00009, 0x10008, 0x10009, 0x0000a, 0x0000b, 0x1000a, 0x1000b,
 0x20008, 0x20009, 0x30008, 0x30009, 0x2000a, 0x2000b, 0x3000a, 0x3000b,
 0x0000c, 0x0000d, 0x1000c, 0x1000d, 0x0000e, 0x0000f, 0x1000e, 0x1000f,
 0x2000c, 0x2000d, 0x3000c, 0x3000d, 0x2000e, 0x2000f, 0x3000e, 0x3000f,
 0x40008, 0x40009, 0x50008, 0x50009, 0x4000a, 0x4000b, 0x5000a, 0x5000b,
 0x60008, 0x60009, 0x70008, 0x70009, 0x6000a, 0x6000b, 0x7000a, 0x7000b,
 0x4000c, 0x4000d, 0x5000c, 0x5000d, 0x4000e, 0x4000f, 0x5000e, 0x5000f,
 0x6000c, 0x6000d, 0x7000c, 0x7000d, 0x6000e, 0x6000f, 0x7000e, 0x7000f,
 0x80000, 0x80001, 0x90000, 0x90001, 0x80002, 0x80003, 0x90002, 0x90003,
 0xa0000, 0xa0001, 0xb0000, 0xb0001, 0xa0002, 0xa0003, 0xb0002, 0xb0003,
 0x80004, 0x80005, 0x90004, 0x90005, 0x80006, 0x80007, 0x90006, 0x90007,
 0xa0004, 0xa0005, 0xb0004, 0xb0005, 0xa0006, 0xa0007, 0xb0006, 0xb0007,
 0xc0000, 0xc0001, 0xd0000, 0xd0001, 0xc0002, 0xc0003, 0xd0002, 0xd0003,
 0xe0000, 0xe0001, 0xf0000, 0xf0001, 0xe0002, 0xe0003, 0xf0002, 0xf0003,
 0xc0004, 0xc0005, 0xd0004, 0xd0005, 0xc0006, 0xc0007, 0xd0006, 0xd0007,
 0xe0004, 0xe0005, 0xf0004, 0xf0005, 0xe0006, 0xe0007, 0xf0006, 0xf0007,
 0x80008, 0x80009, 0x90008, 0x90009, 0x8000a, 0x8000b, 0x9000a, 0x9000b,
 0xa0008, 0xa0009, 0xb0008, 0xb0009, 0xa000a, 0xa000b, 0xb000a, 0xb000b,
 0x8000c, 0x8000d, 0x9000c, 0x9000d, 0x8000e, 0x8000f, 0x9000e, 0x9000f,
 0xa000c, 0xa000d, 0xb000c, 0xb000d, 0xa000e, 0xa000f, 0xb000e, 0xb000f,
 0xc0008, 0xc0009, 0xd0008, 0xd0009, 0xc000a, 0xc000b, 0xd000a, 0xd000b,
 0xe0008, 0xe0009, 0xf0008, 0xf0009, 0xe000a, 0xe000b, 0xf000a, 0xf000b,
 0xc000c, 0xc000d, 0xd000c, 0xd000d, 0xc000e, 0xc000f, 0xd000e, 0xd000f,
 0xe000c, 0xe000d, 0xf000c, 0xf000d, 0xe000e, 0xe000f, 0xf000e, 0xf000f,
.
1116,1117c
 *	then l1septab[x] yields a ulong with bits
 *		________7531________6420
.
1110,1111c
 *  Table for separating bits in a ldepth 1 bitmap.
 *  This aids in coverting a big-endian ldepth 1 bitmap into the
.
635c
		r.min.x &= ~7;		/* 8 pixel alignment for l2update() */
.
632c
			len++;		/* 8 pixel alignment for l1update() */
.
628c
		r.min.x &= ~15;		/* 8 pixel alignment for l1update() */
.
625c
			len++;		/* 16 bit alignment for l0update() */
.
621,622c
		r.min.x &= ~15;		/* 16 pixel alignment for l0update() */
		f = memmove;
.
577c
			if(tl > 2)
.
547c
			m &= mr;
.
408,410d
397,403d
395c
	 *  swizzle the font longs.
.
186d
## diffname pc/devvga.c 1993/1225
## diff -e /n/fornaxdump/1993/1221/sys/src/brazil/pc/devvga.c /n/fornaxdump/1993/1225/sys/src/brazil/pc/devvga.c
568c
			q[tl-1] ^= (data[tl-1]^q[tl-1]) & mr;
.
## diffname pc/devvga.c 1993/1229
## diff -e /n/fornaxdump/1993/1225/sys/src/brazil/pc/devvga.c /n/fornaxdump/1993/1229/sys/src/brazil/pc/devvga.c
611c
		f = l0update;
.
## diffname pc/devvga.c 1993/1230
## diff -e /n/fornaxdump/1993/1229/sys/src/brazil/pc/devvga.c /n/fornaxdump/1993/1230/sys/src/brazil/pc/devvga.c
1085c
	ulong x;

	switch(gscreen.ldepth){
	default:
		x = 0xf;
		break;
	case 3:
		x = 0xff;
		break;
	}
	p &= x;
	p ^= x;
.
1074c
	ulong x;

	switch(gscreen.ldepth){
	default:
		x = 0xf;
		break;
	case 3:
		x = 0xff;
		break;
	}
	p &= x;
	p ^= x;
.
611c
		f = memmove;
.
479d
474d
## diffname pc/devvga.c 1994/0311
## diff -e /n/fornaxdump/1993/1230/sys/src/brazil/pc/devvga.c /n/fornaxdump/1994/0311/sys/src/brazil/pc/devvga.c
964a
}
static void
s3page(int page)
{
#ifdef notdef
	uchar crt51;

	/*
	 * The S3 registers need to be unlocked for this.
	 * Let's hope they are already:
	 *	crout(0x38, 0x48);
	 *	crout(0x39, 0xA0);
	 *
	 * The page is 6 bits, the lower 4 bits in Crt35<3:0>,
	 * the upper 2 in Crt51<3:2>.
	 */
	crout(0x35, page & 0x0F);
	outb(CRX, 0x51);
	crt51 = (0xF3 & inb(CR))|((page & 0x30)>>2);
	outb(CR, crt51);
{
uchar crt35;
outb(CRX, 0x35);
crt35 = inb(CR);
print("page #%ux, crt51=#%ux, crt35=#%ux\n", page, crt51, crt35);
}
#else
	crout(0x35, (page<<2) & 0x0f);
#endif /* notdef
.
161a
[S3]		{ "s3", s3page, },
.
153c
static void	atipage(int), cirruspage(int), s3page(int);
.
148a
	S3,
.
## diffname pc/devvga.c 1994/0317
## diff -e /n/fornaxdump/1994/0311/sys/src/brazil/pc/devvga.c /n/fornaxdump/1994/0317/sys/src/brazil/pc/devvga.c
987,995d
971d
## diffname pc/devvga.c 1994/0323
## diff -e /n/fornaxdump/1994/0317/sys/src/brazil/pc/devvga.c /n/fornaxdump/1994/0323/sys/src/brazil/pc/devvga.c
982,985c
	if(vgascreen.ldepth == 3){
		/*
		 * The S3 registers need to be unlocked for this.
		 * Let's hope they are already:
		 *	crout(0x38, 0x48);
		 *	crout(0x39, 0xA0);
		 *
		 * The page is 6 bits, the lower 4 bits in Crt35<3:0>,
		 * the upper 2 in Crt51<3:2>.
		 */
		crout(0x35, page & 0x0F);
		outb(CRX, 0x51);
		crt51 = (0xF3 & inb(CR))|((page & 0x30)>>2);
		outb(CR, crt51);
	}
	else
		crout(0x35, (page<<2) & 0x0C);
.
974,980c
	 * I don't understand why these are different.
.
## diffname pc/devvga.c 1994/0407
## diff -e /n/fornaxdump/1994/0323/sys/src/brazil/pc/devvga.c /n/fornaxdump/1994/0407/sys/src/brazil/pc/devvga.c
558,559c
			memmove(q, data, tl-1);
.
551,552c
			memmove(q+1, data+1, tl-1);
.
534c
	if(tl <= 0){
		;
	}else if(tl == 1){	/* all in one byte */
.
## diffname pc/devvga.c 1994/0409
## diff -e /n/fornaxdump/1994/0407/sys/src/brazil/pc/devvga.c /n/fornaxdump/1994/0409/sys/src/brazil/pc/devvga.c
629a
		r.min.x &= ~3;
		r.max.x = ROUND(r.max.x, 4);
.
## diffname pc/devvga.c 1994/0412
## diff -e /n/fornaxdump/1994/0409/sys/src/brazil/pc/devvga.c /n/fornaxdump/1994/0412/sys/src/brazil/pc/devvga.c
1147,1247d
1090d
1064d
1056d
1050,1051c
	vgacard->setpage(0);
	r = Rpt(Pt(window.min.x, window.max.y+h), window.max);
.
997,1006d
978c
	if(gscreen.ldepth == 3){
.
887,915d
763,847d
710d
705,708d
672a
/*
 *  write a string to the screen
 */
.
670c
	}else if(lpart == 0){
		for(y=r.min.y; y<r.max.y; y++){
			if(q + tl <= e){
				memmove(data, q, tl-1);
				data[tl-1] ^= (q[tl-1]^data[tl-1]) & mr;
			} else {	/* new page */
				q += lineunload(q, data, tl-1, &page, e);
				q += byteunload(q+tl-1, data+tl-1, mr, &page, e);
			}
			q += sw;
			data += l;
		}
	}else for(y=r.min.y; y<r.max.y; y++){
			if(q + tl <= e){
				*data ^= (*q^*data) & m;
				if(tl > 2)
					memmove(data+1, q+1, tl-2);
				data[tl-1] ^= (q[tl-1]^data[tl-1]) & mr;
			} else {	/* new page */
				q += byteunload(q, data, m, &page, e);
				if(tl > 2)
					q += lineunload(q+1, data+1, tl-2, &page, e);
				q += byteunload(q+tl-1, data+tl-1, mr, &page, e);
			}
			q += sw;
			data += l;
		}

	unlock(&screenlock);
	if(dolock)
		cursorunlock();
.
667,668c
			q += sw;
			data += l;
.
664,665c
				q += byteunload(q, data, m, &page, e);
				q += lineunload(q+1, data+1, tl-1, &page, e);
.
650,662c
	q = ((uchar*)gscreen.base) + (off&(Footprint-1));

	sw = gscreen.width*sizeof(ulong);
	e = ((uchar*)gscreen.base) + Footprint;

	/* may need to do bit insertion on edges */
	if(tl <= 0){
		;
	}else if(tl == 1){	/* all in one byte */
		if(rpart)
			m &= mr;
		for(y=r.min.y; y<r.max.y; y++){
			if(q < e)
				*data ^= (*q^*data) & m;
			else
				q += byteunload(q, data, m, &page, e);
			q += sw;
			data += l;
		}
	}else if(lpart==0 && rpart==0){	/* easy case */
		for(y=r.min.y; y<r.max.y; y++){
			if(q + tl <= e)
				memmove(data, q, tl);
			else
				q += lineunload(q, data, tl, &page, e);
			q += sw;
			data += l;
		}
	}else if(rpart==0){
		for(y=r.min.y; y<r.max.y; y++){
			if(q + tl <= e){
				*data ^= (*q^*data) & m;
				memmove(data+1, q+1, tl-1);
.
648c
	q = gbaddr(&gscreen, r.min);
	mx = 7>>gscreen.ldepth;
	lpart = (r.min.x & mx) << gscreen.ldepth;
	rpart = (r.max.x & mx) << gscreen.ldepth;
	m = 0xFF >> lpart;
	mr = 0xFF ^ (0xFF >> rpart);

	off = q - (uchar*)gscreen.base;
	page = off>>Footshift;
.
640,646c
	if(dolock)
		cursorlock(r);
	lock(&screenlock);
.
636,638d
608,634c
	if(rem < len){
		memmove(data, q, rem);
		pg = ++*page;
		vgacard->setpage(pg);
		q -= Footprint;
		diff -= Footprint;
		memmove(data+rem, q+rem, len-rem);
	} else
		memmove(data, q, len);

	return diff;
}

/*
 *   paste tile into hard screen.
 *   tile is at location r, first pixel in *data.  tl is length of scan line to insert,
 *   l is amount to advance data after each scan line.
 */
void
screenunload(Rectangle r, uchar *data, int tl, int l, int dolock)
{
	int y, lpart, rpart, mx, m, mr, page, sw;
	ulong off;
	uchar *q, *e;
	extern void cursorlock(Rectangle);
	extern void cursorunlock(void);

	if(!rectclip(&r, gscreen.r) || tl<=0)
.
605,606c
	rem = e - q;
.
596,603c
	diff = 0;
	if(q >= e){
		pg = ++*page;
		vgacard->setpage(pg);
		q -= Footprint;
		diff -= Footprint;
	}
.
593,594c
/*
 *  Get a vector of bytes from screen memory.  Assume that if the page
 *  is wrong we just need to increment it.
 */
static int
lineunload(uchar *q, uchar *data, int len, int *page, uchar *e)
{
	int rem, pg;
	int diff;
.
590,591c
	diff = 0;
	if(q >= e){
		pg = ++*page;
		vgacard->setpage(pg);
		q -= Footprint;
		diff -= Footprint;
	}
	*data ^= (*q^*data) & m;
	return diff;
}
.
585,588c
	int pg;
	int diff;
.
582,583c
static int
byteunload(uchar *q, uchar *data, int m, int *page, uchar *e)
.
580c
 *  Get a byte from screen memory.  Assume that if the page
 *  is wrong we just need to increment it.
.
576a
	if(dolock)
		cursorunlock();
.
572,575c

.
565,569c
			if(q + tl <= e){
				*q ^= (*data^*q) & m;
				if(tl > 2)
					memmove(q+1, data+1, tl-2);
				q[tl-1] ^= (data[tl-1]^q[tl-1]) & mr;
			} else {	/* new page */
				q += byteload(q, data, m, &page, e);
				if(tl > 2)
					q += lineload(q+1, data+1, tl-2, &page, e);
				q += byteload(q+tl-1, data+tl-1, mr, &page, e);
			}
			q += sw;
.
559,561c
			if(q + tl <= e){
				memmove(q, data, tl-1);
				q[tl-1] ^= (data[tl-1]^q[tl-1]) & mr;
			} else {	/* new page */
				q += lineload(q, data, tl-1, &page, e);
				q += byteload(q+tl-1, data+tl-1, mr, &page, e);
			}
			q += sw;
.
552,554c
			if(q + tl <= e){
				*q ^= (*data^*q) & m;
				memmove(q+1, data+1, tl-1);
			} else {
				q += byteload(q, data, m, &page, e);
				q += lineload(q+1, data+1, tl-1, &page, e);
			}
			q += sw;
.
546,547c
			if(q + tl <= e)
				memmove(q, data, tl);
			else
				q += lineload(q, data, tl, &page, e);
			q += sw;
.
540,541c
			if(q < e)
				*q ^= (*data^*q) & m;
			else
				q += byteload(q, data, m, &page, e);
			q += sw;
.
532a

	off = q - (uchar*)gscreen.base;
	page = off>>Footshift;
	vgacard->setpage(page);
	q = ((uchar*)gscreen.base) + (off&(Footprint-1));

	sw = gscreen.width*sizeof(ulong);
	e = ((uchar*)gscreen.base) + Footprint;

.
525,526c

.
523a

	if(dolock)
		cursorlock(r);
.
517,518c
	int y, lpart, rpart, mx, m, mr, page, sw;
	ulong off;
	uchar *q, *e;
.
515c
screenload(Rectangle r, uchar *data, int tl, int l, int dolock)
.
510c
 *  Load adjacent bytes into a screen memory.  Assume that if the page
 *  is wrong we just need to increment it.
 */
static int
lineload(uchar *q, uchar *data, int len, int *page, uchar *e)
{
	int rem, pg;
	int diff;

	diff = 0;
	if(q >= e){
		pg = ++*page;
		vgacard->setpage(pg);
		q -= Footprint;
		diff -= Footprint;
	}

	rem = e - q;

	if(rem < len){
		memmove(q, data, rem);
		pg = ++*page;
		vgacard->setpage(pg);
		q -= Footprint;
		diff -= Footprint;
		memmove(q+rem, data+rem, len-rem);
	} else
		memmove(q, data, len);

	return diff;
}

/*
 *   paste tile into hard screen.
.
505,506c
/*
 *  Load a byte into screen memory.  Assume that if the page
 *  is wrong we just need to increment it.
 */
static int
byteload(uchar *q, uchar *data, int m, int *page, uchar *e)
{
	int pg;
	int diff;

	diff = 0;
	if(q >= e){
		pg = ++*page;
		vgacard->setpage(pg);
		q -= Footprint;
		diff -= Footprint;
	}
	*q ^= (*data^*q) & m;
	return diff;
.
503a
}
.
498a
	vgacard->setpage(0);
.
497c
	window.max = add(window.min, Pt(10+w*64, Footprint/(BY2WD*gscreen.width)));
.
485,490d
460,463c
	for(i = 0; i < gscreen.width*BY2WD*maxy; i += Footprint){
		vgacard->setpage(i>>Footshift);
		memset(gscreen.base, 0, Footprint);
	}
.
456c
	gscreen.width = (maxx*(1<<gscreen.ldepth))/32;
	gscreen.base = (void*)SCREENMEM;
.
436,454d
434c
	 *  setup a bitmap for the new size
.
424,432d
422a
		break;
	case 3:
		setmode(&mode13);
		break;
	default:
		error(Ebadarg);
	}
.
419,421c
	switch(ldepth){
	case 0:
.
416,417c
	int i, x;
.
409a
static void
setmode(VGAmode *v)
{
	int i;

	/* turn screen off (to avoid damage) */
	srout(1, 0x21);

	for(i = 0; i < sizeof(v->general); i++)
		genout(i, v->general[i]);

	for(i = 0; i < sizeof(v->sequencer); i++)
		if(i == 1)
			srout(i, v->sequencer[i]|0x20);		/* avoid enabling screen */
		else
			srout(i, v->sequencer[i]);

	crout(Cvre, 0);	/* allow writes to CRT registers 0-7 */
	for(i = 0; i < sizeof(v->crt); i++)
		crout(i, v->crt[i]);

	for(i = 0; i < sizeof(v->graphics); i++)
		grout(i, v->graphics[i]);

	for(i = 0; i < sizeof(v->attribute); i++)
		arout(i, v->attribute[i]);

	/* turn screen on */
	srout(1, v->sequencer[1]);
}

.
401a

.
187,188d
178,180d
53d
46,47d
44d
33a
enum
{
	Footshift=	16,
	Footprint=	1<<Footshift,
};

.
## diffname pc/devvga.c 1994/0413
## diff -e /n/fornaxdump/1994/0412/sys/src/brazil/pc/devvga.c /n/fornaxdump/1994/0413/sys/src/brazil/pc/devvga.c
1111c
		curpos = subfstring(&gscreen, curpos, &defont0, buf, S);
.
1108c
		if(curpos.x >= window.max.x-w)
.
1104,1105c
		if(curpos.x-w >= window.min.x)
			curpos.x -= w;
.
1101c
		curpos.x += pos*w;
.
1099c
		pos = (curpos.x-window.min.x)/w;
.
1096c
		curpos.x = window.min.x;
.
1092c
		curpos.y += h;
.
1090c
		if(curpos.y+h >= window.max.y)
.
1079,1080c
	bitblt(&gscreen, r.min, &gscreen, r, Zero);
	curpos.y -= o;
.
1076,1077c
	r = Rpt(Pt(window.min.x, window.min.y+o), window.max);
	bitblt(&gscreen, window.min, &gscreen, r, S);
.
1074a
	o = 2*h;
.
741c
	q = byteaddr(&gscreen, r.min);
.
731,732d
583c
	q = byteaddr(&gscreen, r.min);
.
573,574d
503c
	curpos = window.min;
.
501c
	bitblt(&gscreen, window.min, &gscreen, window, Zero);
.
395,397c
	l = defont0.bits->base;
	for(i = defont0.bits->width*Dy(defont0.bits->r); i > 0; i--, l++)
.
186a
extern void cursorlock(Rectangle);
extern void cursorunlock(void);

.
58c
static	Point	curpos;
.
45,46c
Subfont *defont;
Bitmap	gscreen;
.
41c
extern	Subfont defont0;
.
10d
## diffname pc/devvga.c 1994/0414
## diff -e /n/fornaxdump/1994/0413/sys/src/brazil/pc/devvga.c /n/fornaxdump/1994/0414/sys/src/brazil/pc/devvga.c
1165a
}


/*
 *  software cursor
 */

ulong backbits[16*5];
ulong workbits[16*5];
Bitmap cursorwork =
{
	{0, 0, 16+8, 16},
	{0, 0, 16+8, 16},
	0,
	workbits,
	0,
	1,
};

Bitmap	clr =
{
	{0, 0, 16, 16},
	{0, 0, 16, 16},
	0,
	0,
	0,
	1,
};

Bitmap	set =
{
	{0, 0, 16, 16},
	{0, 0, 16, 16},
	0,
	0,
	0,
	1,
};

void
cursorinit(void)
{
	static int already;

	lock(&cursor);

	cursorwork.ldepth = gscreen.ldepth;
	cursorwork.width = ((cursorwork.r.max.x << gscreen.ldepth) + 31) >> 5;
	cursor.l = cursorwork.width*BY2WD;

	if(!already){
		cursor.disable--;
		already = 1;
	}

	unlock(&cursor);
}

void
setcursor(ulong *setbits, ulong *clrbits, int offx, int offy)
{
	USED(offx, offy);
	set.base = setbits;
	clr.base = clrbits;
}

void
cursoron(int dolock)
{
	int off;
	Rectangle r;
	uchar *a;
	struct {
		Bitmap *dm;
		Point p;
		Bitmap *sm;
		Rectangle r;
		Fcode f;
	} xx;
	extern int graphicssubtile(uchar*, int, int, Rectangle, Rectangle, uchar**);

	if(cursor.disable)
		return;
	if(dolock)
		lock(&cursor);

	if(cursor.visible++ == 0){
		cursor.r.min = mousexy();
		cursor.r.max = add(cursor.r.min, Pt(16, 16));
		cursor.r = raddp(cursor.r, cursor.offset);
	
		/* bit offset into backup area */
		if(cursor.r.min.x < 0)
			off = cursor.r.min.x;
		else
			off = ((1<<gscreen.ldepth)*cursor.r.min.x) & 7;
	
		/* clip the cursor rectangle */
		xx.dm = &cursorwork;
		xx.p = Pt(off, 0);
		xx.sm = &gscreen;
		xx.r = cursor.r;
		bitbltclip(&xx);
	
		/* tile width */
		cursor.tl = graphicssubtile(0, cursor.l, gscreen.ldepth,
				gscreen.r, xx.r, &a);
		if(cursor.tl > 0){
			/* get tile */
			screenunload(xx.r, (uchar*)workbits, cursor.tl, cursor.l, 0);
	
			/* save for cursoroff */
			memmove(backbits, workbits, cursor.l*16);
	
			/* add mouse into work area */
			r = Rect(0, 0, Dx(xx.r), Dy(xx.r));
			bitblt(&cursorwork, xx.p, &clr, r, S|D);
			bitblt(&cursorwork, xx.p, &set, r, D&~S);
	
			/* put back tile */
			cursor.clipr = xx.r;
			screenload(xx.r, (uchar*)workbits, cursor.tl, cursor.l, 0);
		}
	}

	if(dolock)
		unlock(&cursor);
}

void
cursoroff(int dolock)
{
	if(cursor.disable)
		return;
	if(dolock)
		lock(&cursor);
	if(--cursor.visible == 0 && cursor.tl > 0)
		screenload(cursor.clipr, (uchar*)backbits, cursor.tl, cursor.l, 0);
	if(dolock)
		unlock(&cursor);
}

void
cursorlock(Rectangle r)
{
	lock(&cursor);
	if(rectXrect(cursor.r, r)){
		cursoroff(0);
		cursor.frozen = 1;
	}
	cursor.disable++;
	unlock(&cursor);
}

void
cursorunlock(void)
{
	lock(&cursor);
	cursor.disable--;
	if(cursor.frozen)
		cursoron(0);
	cursor.frozen = 0;
	unlock(&cursor);
.
506c

	cursorinit();
.
499a
	if(window.max.y >= gscreen.r.max.y)
		window.max.y = gscreen.r.max.y;
	if(window.max.x >= gscreen.r.max.x)
		window.max.x = gscreen.r.max.x;
.
458a
	lock(&screenlock);

.
221a
	print("visible %d disable %d frozen %d\n", cursor.visible, cursor.disable, cursor.frozen);
.
211a
	cursor.disable++;
.
9a
#include	"screen.h"
.
## diffname pc/devvga.c 1994/0415
## diff -e /n/fornaxdump/1994/0414/sys/src/brazil/pc/devvga.c /n/fornaxdump/1994/0415/sys/src/brazil/pc/devvga.c
1330c
static void
.
1318c
static void
.
1297c
			screenload(xx.r, (uchar*)cursorwork.base, cursor.tl, cursor.l, 0);
.
1292,1293c
			bitblt(&cursorwork, xx.p, &clr, r, D&~S);
			bitblt(&cursorwork, xx.p, &set, r, S|D);
.
1288c
			memmove(backbits, cursorwork.base, cursor.l*16);
.
1285c
			screenunload(xx.r, (uchar*)cursorwork.base, cursor.tl, cursor.l, 0);
.
1255d
1222,1223c
	workinit(&cursorwork, 16, 16);
.
1204a
/*
 *  the black center of the cursor
 */
.
1194a
/*
 *  the white border around the cursor
 */
.
1183,1193c
/*
 *  area to store the bits that are behind the cursor
 */
ulong backbits[16*4];
.
1178d
1119c
		/* tile width */
		r.min = curpos;
		r.max = add(r.min, Pt(w, h));
		off = ((1<<gscreen.ldepth)*r.min.x) & 7;
		l = chwork.width*BY2WD;
		tl = graphicssubtile(0, l, gscreen.ldepth, gscreen.r, r, &a);

		/* add char into work area */
		subfstring(&chwork, Pt(off, 0), &defont0, buf, S);

		/* move work area to screen */
		screenload(r, (uchar*)chwork.base, tl, l, 0);

		curpos.x += w;
.
1113a
			screenputc(" ");
			curpos.x -= w;
		}
.
1112c
		if(curpos.x-w >= window.min.x){
.
1094c
	int pos, l, tl, off;
	uchar *a;
	Rectangle r;
.
1082,1088c
	l = gscreen.width * BY2WD;
	tl = graphicssubtile(0, l, gscreen.ldepth, gscreen.r, window, &a);

	from = window.min.y + LINE2SCROLL*h;
	to = window.min.y;
	for(; from < window.max.y; from++){
		r = Rpt(Pt(window.min.x, from), Pt(window.max.x, from + 1));
		screenunload(r, (uchar*)scrollwork.base, tl, l, 1);
		r = Rpt(Pt(window.min.x, to), Pt(window.max.x, to+1));
		screenload(r, (uchar*)scrollwork.base, tl, l, 1);
	}
		
	curpos.y -= LINE2SCROLL*h;
.
1079c
	int from, to, tl, l;
	uchar *a;
.
1075a
/*
 *  graphics mode console
 */
#define LINE2SCROLL 4
.
1038a
/*
 *  character mode console
 */
.
943,957d
826c
	unlock(&loadlock);
.
746c
	lock(&loadlock);
.
670c
	unlock(&loadlock);
.
590c
	lock(&loadlock);
.
497,516c
/*
 *  init a bitblt work area
 */
static void
workinit(Bitmap *bm, int maxx, int maxy)
{
	bm->ldepth = gscreen.ldepth;
	bm->r = Rect(0, 0, maxx, maxy);
	if(gscreen.ldepth != 3)
		bm->r.max.x += 1<<(3-gscreen.ldepth);
	bm->clipr = bm->r;
	bm->width = ((bm->r.max.x << gscreen.ldepth) + 31) >> 5;
	if(bm->base == 0)
		bm->base = xalloc(maxx*maxy);
.
495a
}
.
494a

	/* stop character mode changes */
.
480a
	h = defont0.height;
	w = defont0.info[' '].width;

	window.min = Pt(48, 48);
	window.max = add(window.min, Pt(10+w*64, 36*h));
	if(window.max.y >= gscreen.r.max.y)
		window.max.y = gscreen.r.max.y-1;
	if(window.max.x >= gscreen.r.max.x)
		window.max.x = gscreen.r.max.x-1;

	vgacard->setpage(0);
	window.max.y = window.min.y+((window.max.y-window.min.y)/h)*h;
	bitblt(&gscreen, window.min, &gscreen, window, Zero);
	curpos = window.min;

	/* work areas */
	workinit(&chwork, w, h);
	workinit(&scrollwork, 64*w, 1);
	cursorinit();

	unlock(&screenlock);
	poperror();

	/*
	 *  default color map (has to be outside the lock)
	 */
.
479c
	 *  set up inset system window
.
475c
		memset(gscreen.base, 0xff, Footprint);
.
468c
	gscreen.width = (maxx*(1<<gscreen.ldepth)+31)/32;
.
462,463d
450a
	if(waserror()){
		unlock(&screenlock);
		nexterror();
	}
	lock(&screenlock);

.
224d
187,188c
static void cursorlock(Rectangle);
static void cursorunlock(void);
extern int graphicssubtile(uchar*, int, int, Rectangle, Rectangle, uchar**);
.
185a
static void	workinit(Bitmap*, int, int);
.
171a
/*
 *  work areas for bitblting screen characters, scrolling, and cursor redraw
 */
Bitmap chwork;
Bitmap scrollwork;
Bitmap cursorwork;

.
49a
static	Lock	loadlock;
.
## diffname pc/devvga.c 1994/0416
## diff -e /n/fornaxdump/1994/0415/sys/src/brazil/pc/devvga.c /n/fornaxdump/1994/0416/sys/src/brazil/pc/devvga.c
1340d
1324c
		xx.p = Pt(xoff, yoff);
.
1316,1320c
		/* offsets into backup area and clr/set bitmaps */
		r.min = Pt(0, 0);
		if(cursor.r.min.x < 0){
			xoff = cursor.r.min.x;
			r.min.x = -xoff;
		} else
			xoff = ((1<<gscreen.ldepth)*cursor.r.min.x) & 7;
		if(cursor.r.min.y < 0){
			yoff = cursor.r.min.y;
			r.min.y = -yoff;
		} else
			yoff = 0;
		r.max = add(r.min, Pt(16, 16));
.
1295c
	int xoff, yoff;
.
1122,1123c

	/* clear bottom */
	memset(scrollwork.base, 0, l);
	for(from = window.max.y - diff; from < window.max.y; from++){
		r = Rect(window.min.x, from, window.max.x, from + 1);
		screenload(r, (uchar*)scrollwork.base, tl, l, 1);
	}
	
	curpos.y -= diff;
.
1119c
		r = Rect(window.min.x, from - diff, window.max.x, from - diff + 1);
.
1114,1117c
	/* move lines up */
	for(from = window.min.y + diff; from < window.max.y; from++){
		r = Rect(window.min.x, from, window.max.x, from + 1);
.
1111c
	diff = h*LINE2SCROLL;
	l = scrollwork.width * BY2WD;
.
1107c
	int from, tl, l, diff;
.
906,953d
535c
	/* switch software to graphics mode */
.
517,519c
	/* default color map (has to be outside the lock) */
.
513a
	/* clear the system window */
	l = scrollwork.width * BY2WD;
	memset(scrollwork.base, 0, l);
	tl = graphicssubtile(0, l, gscreen.ldepth, gscreen.r, window, &a);
	for(i = window.min.y; i < window.max.y; i++){
		r = Rect(window.min.x, i, window.max.x, i + 1);
		screenload(r, (uchar*)scrollwork.base, tl, l, 1);
	}

.
511a
	workinit(&scrollwork, Dx(window), 1);
.
509c
	/* work areas change when dimensions change */
.
506d
503,504d
496d
491,493c
	/* get size for a system window */
.
477,479c
	/* setup a bitmap for the new size */
.
465a
	/* set default mode, a user program sets more complicated ones */
.
458c
	int i, x, l, tl;
	uchar *a;
	Rectangle r;
.
420a
/*
 *  320x200 display, 8 bit color.
 */
VGAmode mode13 = 
{
	/* general */
	0x63, 0x00,
	/* sequence */
	0x03, 0x01, 0x0f, 0x00, 0x0e,
	/* crt */
	0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80, 0xbf, 0x1f,
	0x00, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28,
	0x9c, 0x8e, 0x8f, 0x28, 0x40, 0x96, 0xb9, 0xa3,
	0xff,
	/* graphics */
	0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0f,
	0xff,
	/* attribute */
	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
	0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
	0x41, 0x10, 0x0f, 0x00, 0x00,
};

.
413,419c
/*
 *  640x480 display, 1, 2, or 4 bit color.
 */
VGAmode mode12 = 
{
	/* general */
	0xe7, 0x00,
	/* sequence */
	0x03, 0x01, 0x0f, 0x00, 0x06,
	/* crt */
	0x65, 0x4f, 0x50, 0x88, 0x55, 0x9a, 0x09, 0x3e,
	0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0xe8, 0x8b, 0xdf, 0x28, 0x00, 0xe7, 0x04, 0xe3,
	0xff,
	/* graphics */
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0f,
	0xff,
	/* attribute */
	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
	0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
	0x01, 0x10, 0x0f, 0x00, 0x00,
};
.
406,411c
/*
 *  a few well known VGA modes and the code to set them
 */
typedef struct VGAmode	VGAmode;
struct VGAmode
{
	uchar	general[2];
	uchar	sequencer[5];
	uchar	crt[0x19];
	uchar	graphics[9];
	uchar	attribute[0x15];
};
.
403,404c
	if(reg == 0)
		outb(EMISCW, val);
	else if (reg == 1)
		outb(EFCW, val);
}
static void
srout(int reg, int val)
{
	outb(SRX, reg);
	outb(SR, val);
}
static void
grout(int reg, int val)
{
	outb(GRX, reg);
	outb(GR, val);
}
static void
arout(int reg, int val)
{
	inb(0x3DA);
	if (reg <= 0xf) {
		outb(ARW, reg | 0x0);
		outb(ARW, val);
		inb(0x3DA);
		outb(ARW, reg | 0x20);
	} else {
		outb(ARW, reg | 0x20);
		outb(ARW, val);
	}
}
static void
crout(int reg, int val)
{
	outb(CRX, reg);
	outb(CR, val);
}
.
400,401c
static uchar
srin(int i) {
	outb(SRX, i);
	return inb(SR);
}
static void
genout(int reg, int val)
.
398c
 *  accessing card registers
.
200a
 *  start the screen in CGA mode.  Create the fonts for VGA.  Called by
 *  main().
 */
void
screeninit(void)
{
	int i;
	ulong *l;

	/*
	 *  swizzle the font longs.
	 */
	l = defont0.bits->base;
	for(i = defont0.bits->width*Dy(defont0.bits->r); i > 0; i--, l++)
		*l = (*l<<24) | ((*l>>8)&0x0000ff00) | ((*l<<8)&0x00ff0000) | (*l>>24);

	/*
	 *  start in CGA mode
	 */
	cga = 1;
	crout(0x0a, 0xff);		/* turn off cursor */
	memset(CGASCREEN, 0, CGAWIDTH*CGAHEIGHT);
}

/*
.
199a

.
196,198c
extern int	graphicssubtile(uchar*, int, int, Rectangle, Rectangle, uchar**);
.
194a
extern void	screenload(Rectangle, uchar*, int, int, int);
extern void	screenunload(Rectangle, uchar*, int, int, int);
static void	cursorlock(Rectangle);
static void	cursorunlock(void);
.
77,135d
45d
42d
## diffname pc/devvga.c 1994/0421
## diff -e /n/fornaxdump/1994/0416/sys/src/brazil/pc/devvga.c /n/fornaxdump/1994/0421/sys/src/brazil/pc/devvga.c
327c
		|| maxx > 1600 || maxy > 1200
.
## diffname pc/devvga.c 1994/0422
## diff -e /n/fornaxdump/1994/0421/sys/src/brazil/pc/devvga.c /n/fornaxdump/1994/0422/sys/src/brazil/pc/devvga.c
327c
		|| maxx > 1600 || maxy > 1280
.
## diffname pc/devvga.c 1994/0503
## diff -e /n/fornaxdump/1994/0422/sys/src/brazil/pc/devvga.c /n/fornaxdump/1994/0503/sys/src/brazil/pc/devvga.c
1376a
	if(hwcursor)
		return;
.
1324c
	if(hwcursor)
		(*vgacard->mvcursor)(mousexy());
	else if(cursor.visible++ == 0){
.
1066a
 *  hardware cursor routines
 */
static void
nomvcursor(Point p)
{
	USED(p.x);
}

/*
.
917c
	if(dolock && hwcursor == 0)
.
834c
	if(dolock && hwcursor == 0)
.
761c
	if(dolock && hwcursor == 0)
.
678c
	if(dolock && hwcursor == 0)
.
297a
	case Qvgactl:
		if(offset != 0 || n >= sizeof(cbuf))
			error(Ebadarg);
		memmove(cbuf, buf, n);
		cbuf[n] = 0;
		if(strncmp(cbuf, "hwcursor", 8) == 0)
			hwcursor = 1;
		break;
.
183a
	"vgactl",	{Qvgactl},	0,		0666,
.
177c
	Qvgactl=	5,
	Nvga=		5,
.
110a
static int hwcursor;
.
100,106c
[Ati]		{ "ati", atipage, nomvcursor, },
[Pvga1a]	{ "pvga1a", parapage, nomvcursor, },
[Trident]	{ "trident", tridentpage, nomvcursor, },
[Tseng]		{ "tseng", tsengpage, nomvcursor, },
[Cirrus]	{ "cirrus", cirruspage, nomvcursor, },
[S3]		{ "s3", s3page, nomvcursor, },
[Generic]	{ "generic", nopage, nomvcursor, },
.
97a
static void	nomvcursor(Point);

.
81a
	void	(*mvcursor)(Point);	/* routine to move hardware cursor */
.
## diffname pc/devvga.c 1994/0506
## diff -e /n/fornaxdump/1994/0503/sys/src/brazil/pc/devvga.c /n/fornaxdump/1994/0506/sys/src/brazil/pc/devvga.c
995a
}
static ulong
x8to32(uchar x)
{
	ulong y;

	x = x&0xff;
	y = (x<<(32-8))|(x<<(32-16))|(x<<(32-24))|x;
	return y;
}
static void
greyscale(void)
{
	int i;
	ulong x;

	/* default color map (has to be outside the lock) */
	switch(gscreen.ldepth){
	case 3:
		for(i = 0; i < 256; i++){
			x = x8to32(i);
			setcolor(i, x, x, x);
		}
		break;
	case 2:
	case 1:
	case 0:
		for(i = 0; i < 16; i++){
			x = x6to32((i*63)/15);
			setcolor(i, x, x, x);
		}
		break;
	}
.
591c
			setcolor(i, x3to32(i>>5), x3to32(i>>2), x3to32(i|(i<<1)));
.
310a
		else if(strncmp(cbuf, "grey", 4) == 0)
			greyscale();
.
136a
static void	greyscale(void);
.
## diffname pc/devvga.c 1994/0507
## diff -e /n/fornaxdump/1994/0506/sys/src/brazil/pc/devvga.c /n/fornaxdump/1994/0507/sys/src/brazil/pc/devvga.c
1447a
	else
		splx(s);
.
1443a
	} else
		s = spllo();	/* to avoid freezing out the eia ports */
.
1442c
	if(dolock){
		s = 0;		/* to avoid a compiler warning */
.
1437a
	int s;

.
1432a
	else
		splx(s);
.
1381a
	} else
		s = spllo();	/* to avoid freezing out the eia ports */
.
1380c
	if(dolock){
		s = 0;		/* to avoid compiler warning */
.
1367c
	int xoff, yoff, s;
.
996,1033d
991,994d
986,988c
	x &= (1<<n)-1;
	y = 0;
	for(s = 32 - n; s > 0; s -= n)
		y |= x<<s;
	if(s < 0)
		y |= x>>(-s);
.
983a
	int s;
.
982c
xnto32(uchar x, int n)
.
979c
 *  expand n bits of color to 32
.
600c
			x = xnto32((i*63)/15, 6);
.
594c
			setcolor(i, xnto32(i>>5, 3), xnto32(i>>2, 3), xnto32(i<<1, 2));
		setcolor(0x55, xnto32(0x15, 6), xnto32(0x15, 6), xnto32(0x15, 6));
		setcolor(0xaa, xnto32(0x2a, 6), xnto32(0x2a, 6), xnto32(0x2a, 6));
		setcolor(0xff, xnto32(0x3f, 6), xnto32(0x3f, 6), xnto32(0x3f, 6));
.
312,313d
135,137c
static ulong	xnto32(uchar, int);
.
## diffname pc/devvga.c 1994/0510
## diff -e /n/fornaxdump/1994/0507/sys/src/brazil/pc/devvga.c /n/fornaxdump/1994/0510/sys/src/brazil/pc/devvga.c
1419,1420d
1416a

.
1413,1414c

.
1410,1411c
	if(dolock)
.
1404,1405d
1397,1398d
1344,1345d
1341,1342c
	if(dolock)
.
1328c
	int xoff, yoff;
.
114c
int hwcursor;
.
## diffname pc/devvga.c 1994/0520
## diff -e /n/fornaxdump/1994/0510/sys/src/brazil/pc/devvga.c /n/fornaxdump/1994/0520/sys/src/brazil/pc/devvga.c
1320,1322c
	uchar *p;
	int i;

	for(i=0; i<16; i++){
		p = (uchar*)&set.base[i];
		*p = curs->set[2*i];
		*(p+1) = curs->set[2*i+1];
		p = (uchar*)&clr.base[i];
		*p = curs->clr[2*i];
		*(p+1) = curs->clr[2*i+1];
	}
.
1318c
setcursor(Cursor *curs)
.
1309a
		set.base = malloc(16*sizeof(ulong));
		clr.base = malloc(16*sizeof(ulong));
		if(set.base == 0 || clr.base == 0)
			panic("cursorinit");
.
## diffname pc/devvga.c 1994/0521
## diff -e /n/fornaxdump/1994/0520/sys/src/brazil/pc/devvga.c /n/fornaxdump/1994/0521/sys/src/brazil/pc/devvga.c
1310,1313d
1295d
1293a
	setbits,
.
1282d
1280a
	clrbits,
.
1271c
static ulong backbits[16*4];
static ulong clrbits[16];
static ulong setbits[16];
.
## diffname pc/devvga.c 1994/0528
## diff -e /n/fornaxdump/1994/0521/sys/src/brazil/pc/devvga.c /n/fornaxdump/1994/0528/sys/src/brazil/pc/devvga.c
590c
			setcolor(i, xnto32(i>>5, 3), xnto32(i>>2, 3), xnto32(i, 2));
.
## diffname pc/devvga.c 1994/0603
## diff -e /n/fornaxdump/1994/0528/sys/src/brazil/pc/devvga.c /n/fornaxdump/1994/0603/sys/src/brazil/pc/devvga.c
357a
	case Qvgaportl:
		if((n & 03) || (offset & 03))
			error(Ebadarg);
		n /= 4;
		for (lp = buf, port=offset; port<offset+n; port+=4)
			outl(port, *lp++);
		return n*4;
.
285a
	ulong *lp;
.
273a
	case Qvgaportl:
		if((n & 03) || (offset & 03))
			error(Ebadarg);
		n /= 4;
		for (lp = buf, port=offset; port<offset+n; port+=4)
			*lp++ = inl(port);
		return n*4;
.
252a
	ulong *lp;
.
187a
	"vgaportl",	{Qvgaportl},	0,		0666,
.
180,181c
	Qvgaportl=	5,
	Qvgactl=	6,
	Nvga=		6,
.
## diffname pc/devvga.c 1994/0624
## diff -e /n/fornaxdump/1994/0603/sys/src/brazil/pc/devvga.c /n/fornaxdump/1994/0624/sys/src/brazil/pc/devvga.c
1427c
	if(hwgc)
.
1421a
	else
		splx(s);

	return ret;
.
1372,1373c
	ret = 0;
	if(hwgc)
		ret = (*hwgc->move)(mousexy());
.
1370a
	} else
		s = spllo();	/* to avoid freezing out the eia ports */
.
1368,1369c
		return 0;
	if(dolock){
		s = 0;		/* to avoid compiler warning */
.
1356c
	int xoff, yoff, s, ret;
.
1353c
int
.
1343c
	if(hwgc)
		(*hwgc->load)(curs);
	else for(i=0; i<16; i++){
.
1283a
 *  and hacks for hardware cursor
.
1274,1278c
	vgao(DACWx, p);
	vgao(DACData, r>>(32-6));
	vgao(DACData, g>>(32-6));
	vgao(DACData, b>>(32-6));
	unlock(&pallettelock);
.
1270c
	lock(&pallettelock);
.
1252c
	unlock(&pallettelock);
.
1248c
	lock(&pallettelock);
.
1096,1104d
1092c
		vgaxo(Crtx, 0x35, (page<<2) & 0x0C);
.
1086,1089c
		vgaxo(Crtx, 0x35, page & 0x0F);
		crt51 = vgaxi(Crtx, 0x51) & 0xF3;
		vgaxo(Crtx, 0x51, crt51|((page & 0x30)>>2));
.
1080,1081c
		 *	vgaxo(Crtx, 0x38, 0x48);
		 *	vgaxo(Crtx, 0x39, 0xA0);
.
1064,1068d
1061c
	vgaxo(Grx, 0x09, page<<4);
.
1051c
	uchar seq0E;

	seq0E = vgaxi(Seqx, 0x0E) & 0xF0;
	vgaxo(Seqx, 0x0E, seq0E|(page^0x02));
.
951c
	if(dolock && hwgc == 0)
.
868c
	if(dolock && hwgc == 0)
.
795c
	if(dolock && hwgc == 0)
.
712c
	if(dolock && hwgc == 0)
.
530,531c
	vgaxo(Seqx, 0x01, vga->sequencer[1]);
.
527,528c
	for(i = 0; i < NAttrx; i++)
		vgaxo(Attrx, i, vga->attribute[i]);
.
524,525c
	for(i = 0; i < NGrax; i++)
		vgaxo(Grx, i, vga->graphics[i]);
.
520,522c
	vgaxo(Crtx, 0x11, vga->crt[0x11] & ~0x80);
	for(i = 0; i < NCrtx; i++)
		vgaxo(Crtx, i, vga->crt[i]);
.
516,518c
			continue;
		vgaxo(Seqx, i, vga->sequencer[i]);
	}
	vgaxo(Seqx, 0x00, 0x03);
.
514c
	vgao(MiscW, vga->misc);

	for(i = 1; i < NSeqx; i++){
.
511,512c
	vgaxo(Seqx, 0x00, 0x00);
.
508,509c
	/*
	 * Turn off the screen and
	 * reset the sequencer and leave it off.
	 * Load the generic VGA registers:
	 *	misc;
	 *	sequencer;
	 *	take the sequencer out of reset;
	 *	take off write-protect on crt[0x00-0x07];
	 *	crt;
	 *	graphics;
	 *	attribute;
	 * Turn on the screen.
	 */
	vgaxo(Seqx, 0x01, 0x21);
.
504c
setmode(VGAmode *vga)
.
486c
	0x63,
.
463c
	0xe7,
.
450c
	uchar	misc;
.
440,441c
	int i;
	ulong *l;

	/*
	 *  swizzle the font longs.
	 */
	l = defont0.bits->base;
	for(i = defont0.bits->width*Dy(defont0.bits->r); i > 0; i--, l++)
		*l = (*l<<24) | ((*l>>8)&0x0000ff00) | ((*l<<8)&0x00ff0000) | (*l>>24);

	/*
	 *  start in CGA mode
	 */
	cga = 1;
	vgaxo(Crtx, 0x0A, 0xFF);		/* turn off cursor */
	memset(CGASCREEN, 0, CGAWIDTH*CGAHEIGHT);
.
437,438c

/*
 *  start the screen in CGA mode.  Create the fonts for VGA.  Called by
 *  main().
 */
void
screeninit(void)
.
435a

	return 0;
.
414,434c
	switch(port){

	case Seqx:
	case Crtx:
	case Grx:
		/*
		 * We could use an outport here, but some chips
		 * (e.g. 86C928) have trouble with that for some
		 * registers.
		 */
		outb(port, index);
		outb(port+1, data);
		break;

	case Attrx:
		inb(Status1);
		if(index < 0x10){
			outb(Attrx, index);
			outb(Attrx, data);
			inb(Status1);
			outb(Attrx, 0x20|index);
		}
		else{
			outb(Attrx, 0x20|index);
			outb(Attrx, data);
		}
		break;

	default:
		return -1;
.
411,412c

int
vgaxo(long port, uchar index, uchar data)
.
406,409c
	uchar data;

	switch(port){

	case Seqx:
	case Crtx:
	case Grx:
		outb(port, index);
		data = inb(port+1);
		break;

	case Attrx:
		/*
		 * Allow processor access to the colour
		 * palette registers. Writes to Attrx must
		 * be preceded by a read from Status1 to
		 * initialise the register to point to the
		 * index register and not the data register.
		 * Processor access is allowed by turning
		 * off bit 0x20.
		 */
		inb(Status1);
		if(index < 0x10){
			outb(Attrx, index);
			data = inb(Attrx+1);
			inb(Status1);
			outb(Attrx, 0x20|index);
		}
		else{
			outb(Attrx, 0x20|index);
			data = inb(Attrx+1);
		}
		break;

	default:
		return -1;
	}

	return data & 0xFF;
.
395,404c
int
vgaxi(long port, uchar index)
.
369c
	case Qvgaiol:
.
362c
	case Qvgaiow:
.
358,360c
	case Qvgaiob:
		port = offset;
		if(checkvgaport(port, n))
			error(Eperm);
		for(cp = buf; port < offset+n; port++)
			vgao(port, *cp++);
.
319,356c
		vgactl(cbuf);
.
301,313d
292,294c
	int port;
	uchar *cp;
	char cbuf[64];
.
288a
static void
vgactl(char *arg)
{
	int i, x, y, z;
	char *cp, *field[3];

	if(getfields(arg, field, 3, ' ') != 2)
		error(Ebadarg);

	if(strcmp(field[0], "hwgc") == 0){
		if(strcmp(field[1], "off") == 0){
			if(hwgc){
				(*hwgc->disable)();
				hwgc = 0;
				cursoron(1);
			}
			return;
		}

		for(i = 0; hwcursor[i]; i++){
			if(strcmp(field[1], hwcursor[i]->name) == 0){
				if(hwgc)
					(*hwgc->disable)();
				else
					cursoroff(1);
				hwgc = hwcursor[i];
				(*hwgc->enable)();
				setcursor(&curs);
				cursoron(1);
				return;
			}
		}
	}
	else if(strcmp(field[0], "type") == 0){
		for(i = 0; vgachips[i].name; i++){
			if(strcmp(field[1], vgachips[i].name) == 0){
				vgacard = &vgachips[i];
				return;
			}
		}
	}
	else if(strcmp(field[0], "size") == 0){
		if((x = strtoul(field[1], &cp, 0)) == 0 || x > 2048)
			error(Ebadarg);

		if(*cp)
			cp++;
		if((y = strtoul(cp, &cp, 0)) == 0 || y > 1280)
			error(Ebadarg);

		if(*cp)
			cp++;
		if((z = strtoul(cp, &cp, 0)) == 1)
			z = 0;
		else if(z == 8)
			z = 3;
		else
			error(Ebadarg);

		cursoroff(1);
		setscreen(x, y, z);
		cursoron(1);
		return;
	}

	error(Ebadarg);
}

.
277c
	case Qvgaiol:
.
270c
	case Qvgaiow:
.
264,268c
	case Qvgaiob:
		port = offset;
		if(checkvgaport(port, n))
			error(Eperm);
		for(cp = buf; port < offset+n; port++)
			*cp++ = vgai(port);
.
260,262c
	case Qvgactl:
		port = sprint(cbuf, "type: %s\n", vgacard->name);
		port += sprint(cbuf+port, "size: %dx%dx%d\n",
			gscreen.r.max.x, gscreen.r.max.y, 1<<gscreen.ldepth);
		port += sprint(cbuf+port, "hwgc: ");
		if(hwgc)
			sprint(cbuf+port, "%s\n", hwgc->name);
		else
			sprint(cbuf+port, "off\n");
.
247a
static int
checkvgaport(int port, int len)
{
	if((port == 0x102 || port == 0x46E8) && len == 1)
		return 0;
	if(port >= 0x3B0 && port+len < 0x3E0)
		return 0;
	return -1;
}

.
185,190c
	"vgaiob",	{ Qvgaiob },	0,	0666,
	"vgaiow",	{ Qvgaiow },	0,	0666,
	"vgaiol",	{ Qvgaiol },	0,	0666,
	"vgactl",	{ Qvgactl },	0,	0666,
.
175,182c
	Qdir		= 0,
	Qvgaiob		= 1,
	Qvgaiow		= 2,
	Qvgaiol		= 3,
	Qvgactl		= 4,
	Nvga		= Qvgactl,
.
146,170d
144d
125,130d
115a
extern Hwgc tvp3020hwgc;
extern Hwgc bt485hwgc;

static Hwgc *hwcursor[] = {
	&tvp3020hwgc,
	&bt485hwgc,
	0,
};

static Hwgc *hwgc;
extern Cursor curs;		/* barf */

.
114d
103,109c
[Ati]		{ "ati", atipage, },
[Pvga1a]	{ "pvga1a", cirruspage, },
[Trident]	{ "trident", tridentpage, },
[Tseng]		{ "tseng", tsengpage, },
[Cirrus]	{ "cirrus", cirruspage, },
[S3]		{ "s3", s3page, },
[Generic]	{ "generic", nopage, },
.
99,100d
96c
static void	nopage(int), tsengpage(int), tridentpage(int);
.
82d
62,64d
49a
Lock pallettelock;
.
14,35d
10a
#include	"vga.h"
.
## diffname pc/devvga.c 1994/0630
## diff -e /n/fornaxdump/1994/0624/sys/src/brazil/pc/devvga.c /n/fornaxdump/1994/0630/sys/src/brazil/pc/devvga.c
145d
87c
Vgacard	*vgacard = &vgachips[0];	/* current vga card */
.
77,84c
	{ "generic", nopage, },
	{ "ati", atipage, },
	{ "cirrus", cirruspage, },
	{ "clgd542x", cirruspage, },
	{ "pvga1a", cirruspage, },
	{ "s3", s3page, },
	{ "trident", tridentpage, },
	{ "tseng", tsengpage, },
	{ 0, 0, },
.
61,71d
## diffname pc/devvga.c 1994/0702
## diff -e /n/fornaxdump/1994/0630/sys/src/brazil/pc/devvga.c /n/fornaxdump/1994/0702/sys/src/brazil/pc/devvga.c
333,334c
		/*if(checkvgaport(port, n))
			error(Eperm);*/
.
220,221c
		/*if(checkvgaport(port, n))
			error(Eperm);*/
.
## diffname pc/devvga.c 1994/0715
## diff -e /n/fornaxdump/1994/0702/sys/src/brazil/pc/devvga.c /n/fornaxdump/1994/0715/sys/src/brazil/pc/devvga.c
997c
	unlock(&pallettelock);
.
917c
	lock(&pallettelock);
.
841c
	unlock(&pallettelock);
.
761c
	lock(&pallettelock);
.
27d
## diffname pc/devvga.c 1994/0729
## diff -e /n/fornaxdump/1994/0715/sys/src/brazil/pc/devvga.c /n/fornaxdump/1994/0729/sys/src/brazil/pc/devvga.c
1312c
	unlock(&palettelock);
.
1304c
	lock(&palettelock);
.
1286c
	unlock(&palettelock);
.
1282c
	lock(&palettelock);
.
996c
	unlock(&palettelock);
.
916c
	lock(&palettelock);
.
840c
	unlock(&palettelock);
.
760c
	lock(&palettelock);
.
28c
Lock palettelock;
.
## diffname pc/devvga.c 1994/0803
## diff -e /n/fornaxdump/1994/0729/sys/src/brazil/pc/devvga.c /n/fornaxdump/1994/0803/sys/src/brazil/pc/devvga.c
1111,1135d
87c
Hwgc *hwgc;
.
83a
	&s3hwgc,
	&tvp3020hwgc,
.
82d
79a
extern Hwgc s3hwgc;
extern Hwgc tvp3020hwgc;
.
78d
61c
static void	atipage(int), cirruspage(int);
extern void	s3page(int);
.
## diffname pc/devvga.c 1994/0809
## diff -e /n/fornaxdump/1994/0803/sys/src/brazil/pc/devvga.c /n/fornaxdump/1994/0809/sys/src/brazil/pc/devvga.c
997a
		q += sw;
		data += l;
	}
.
984,996c
		if(q + tl <= e){
			*data ^= (*q^*data) & m;
			if(tl > 2)
				memmove(data+1, q+1, tl-2);
			data[tl-1] ^= (q[tl-1]^data[tl-1]) & mr;
		} else {	/* new page */
			q += byteunload(q, data, m, &page, e);
			if(tl > 2)
				q += lineunload(q+1, data+1, tl-2, &page, e);
			q += byteunload(q+tl-1, data+tl-1, mr, &page, e);
.
903,905c
 * get a tile from screen memory.
 * tile is at location r, first pixel in *data. 
 * tl is length of scan line to insert,
 * l is amount to advance data after each scan line.
.
841a
		q += sw;
		data += l;
	}
.
828,840c
		if(q + tl <= e){
			*q ^= (*data^*q) & m;
			if(tl > 2)
				memmove(q+1, data+1, tl-2);
			q[tl-1] ^= (data[tl-1]^q[tl-1]) & mr;
		} else {	/* new page */
			q += byteload(q, data, m, &page, e);
			if(tl > 2)
				q += lineload(q+1, data+1, tl-2, &page, e);
			q += byteload(q+tl-1, data+tl-1, mr, &page, e);
.
## diffname pc/devvga.c 1994/0810
## diff -e /n/fornaxdump/1994/0809/sys/src/brazil/pc/devvga.c /n/fornaxdump/1994/0810/sys/src/brazil/pc/devvga.c
28d
23a
Lock palettelock;			/* access to DAC registers */
Cursor curcursor;			/* current cursor */
.
## diffname pc/devvga.c 1994/0812
## diff -e /n/fornaxdump/1994/0810/sys/src/brazil/pc/devvga.c /n/fornaxdump/1994/0812/sys/src/brazil/pc/devvga.c
638c
	workinit(&scrollwork, 80*w, 1);
.
628c
	window.max = add(window.min, Pt(10+w*80, 50*h));
.
## diffname pc/devvga.c 1994/0909
## diff -e /n/fornaxdump/1994/0812/sys/src/brazil/pc/devvga.c /n/fornaxdump/1994/0909/sys/src/brazil/pc/devvga.c
1108c
et4000page(int page)
.
74c
	{ "et4000", et4000page, },
	{ "tseng", et4000page, },
.
61c
static void	nopage(int), et4000page(int), tridentpage(int);
.
## diffname pc/devvga.c 1994/0910
## diff -e /n/fornaxdump/1994/0909/sys/src/brazil/pc/devvga.c /n/fornaxdump/1994/0910/sys/src/brazil/pc/devvga.c
1111c
	uchar p;

	p = page & 0x0F;
	p |= p<<4;
	outb(0x3CD, p);

	p = (page & 0x30);
	p |= p>>4;
	outb(0x3CB, p);
.
## diffname pc/devvga.c 1994/0930
## diff -e /n/fornaxdump/1994/0910/sys/src/brazil/pc/devvga.c /n/fornaxdump/1994/0930/sys/src/brazil/pc/devvga.c
305a
		interlaced[0] = *cp;
.
214,215c
		port += sprint(cbuf+port, "size: %dx%dx%d%s\n",
			gscreen.r.max.x, gscreen.r.max.y,
			1<<gscreen.ldepth, interlaced);
.
93a
static char interlaced[2];
.
## diffname pc/devvga.c 1994/1029
## diff -e /n/fornaxdump/1994/0930/sys/src/brazil/pc/devvga.c /n/fornaxdump/1994/1029/sys/src/brazil/pc/devvga.c
1053,1067d
1049d
587a
static ulong
xnto32(uchar x, int n)
{
	int s;
	ulong y;

	x &= (1<<n)-1;
	y = 0;
	for(s = 32 - n; s > 0; s -= n)
		y |= x<<s;
	if(s < 0)
		y |= x>>(-s);
	return y;
}

.
109d
## diffname pc/devvga.c 1994/1103
## diff -e /n/fornaxdump/1994/1029/sys/src/brazil/pc/devvga.c /n/fornaxdump/1994/1103/sys/src/brazil/pc/devvga.c
75c
	{ "s3", s3page, },
.
71,73d
67,69c
	{ "vga", nopage, },
.
## diffname pc/devvga.c 1994/1117
## diff -e /n/fornaxdump/1994/1103/sys/src/brazil/pc/devvga.c /n/fornaxdump/1994/1117/sys/src/brazil/pc/devvga.c
1116a

.
1078,1104d
1070,1076d
61,62c
static void	nopage(int);
static void	cirruspage(int);
static void	et4000page(int);
.
## diffname pc/devvga.c 1994/1119
## diff -e /n/fornaxdump/1994/1117/sys/src/brazil/pc/devvga.c /n/fornaxdump/1994/1119/sys/src/brazil/pc/devvga.c
580c
	vgaxo(Seqx, 0x01, seq01);
.
568c
	vgaxo(Seqx, 0x00, seq00);
.
560a
	seq01 = vgaxi(Seqx, 0x01);
	vgaxo(Seqx, 0x01, seq01|0x20);

.
557,558c
	seq00 = vgaxi(Seqx, 0x00);
.
555c
	 * Restore the screen state.
.
550c
	 *	restore the sequencer reset state;
.
541a
	uchar seq00, seq01;
.
## diffname pc/devvga.c 1994/1201
## diff -e /n/fornaxdump/1994/1119/sys/src/brazil/pc/devvga.c /n/fornaxdump/1994/1201/sys/src/brazil/pc/devvga.c
1072,1085d
82a
	&et4000hwgc,
.
77a
extern Hwgc et4000hwgc;
.
63c
extern void	et4000page(int);
.
## diffname pc/devvga.c 1995/0108
## diff -e /n/fornaxdump/1994/1201/sys/src/brazil/pc/devvga.c /n/fornaxdump/1995/0108/sys/src/brazil/pc/devvga.c
358a
}

long
vgabwrite(Chan *c, Block *bp, ulong offset)
{
	return devbwrite(c, bp, offset);
.
246a
Block*
vgabread(Chan *c, long n, ulong offset)
{
	return devbread(c, n, offset);
}

.
## diffname pc/devvga.c 1995/0117
## diff -e /n/fornaxdump/1995/0108/sys/src/brazil/pc/devvga.c /n/fornaxdump/1995/0117/sys/src/brazil/pc/devvga.c
259c
	if(getfields(arg, field, 3, " ") != 2)
.
## diffname pc/devvga.c 1995/0126
## diff -e /n/fornaxdump/1995/0117/sys/src/brazil/pc/devvga.c /n/fornaxdump/1995/0126/sys/src/brazil/pc/devvga.c
1462a
}

void
addhwgclink(Hwgc *hwgcp)
{
	hwgcp->link = hwgctlr;
	hwgctlr = hwgcp;
}

void
addvgaclink(Vgac *vgacp)
{
	vgacp->link = vgactlr;
	vgactlr = vgacp;
.
1261,1267c
	colormap[p][Pred] = r;
	colormap[p][Pgreen] = g;
	colormap[p][Pblue] = b;
	vgao(PaddrW, p);
	vgao(Pdata, r>>(32-6));
	vgao(Pdata, g>>(32-6));
	vgao(Pdata, b>>(32-6));
.
1255c
		x = 0xFF;
.
1252c
		x = 0xF;
.
1239,1241c
	*pr = colormap[p][Pred];
	*pg = colormap[p][Pgreen];
	*pb = colormap[p][Pblue];
.
1233c
		x = 0xFF;
.
1230c
		x = 0xF;
.
1077,1079d
963c
	vgac->page(page);
.
924c
		vgac->page(pg);
.
914c
		vgac->page(pg);
.
893c
		vgac->page(pg);
.
806c
	vgac->page(page);
.
768c
		vgac->page(pg);
.
758c
		vgac->page(pg);
.
737c
		vgac->page(pg);
.
688c
		for(i = 0; i < Pcolours; i++)
.
651c
		vgac->page(i>>Footshift);
.
594c
	for(i = 0; i < sizeof(vga->attribute); i++)
.
591c
	for(i = 0; i < sizeof(vga->graphics); i++)
.
588c
	for(i = 0; i < sizeof(vga->crt); i++)
.
584d
580,582c
	for(i = 2; i < sizeof(vga->sequencer); i++)
.
287,289c
		for(vgacp = vgactlr; vgacp; vgacp = vgacp->link){
			if(strcmp(field[1], vgacp->name) == 0){
				vgac = vgacp;
.
278c
				hwgc = hwgcp;
.
272,273c
		for(hwgcp = hwgctlr; hwgcp; hwgcp = hwgcp->link){
			if(strcmp(field[1], hwgcp->name) == 0){
.
257a
	Hwgc *hwgcp;
	Vgac *vgacp;
.
256c
	int x, y, z;
.
211c
		if(vgac == 0)
			vgacp = &vga;
		else
			vgacp = vgac;
		port = sprint(cbuf, "type: %s\n", vgacp->name);
.
205a
	Vgac *vgacp;
.
90,91c
static Vgac *vgactlr = &vga;			/* available VGA ctlrs */
static Vgac *vgac;				/* current VGA ctlr */
static Hwgc *hwgctlr;				/* available HWGC's */
Hwgc *hwgc;					/* current HWGC */

.
66,86d
61,64c
static Vgac vga = {
	"vga",
	nopage,
.
51,59c
static void nopage(int);
.
29c
static	ulong	colormap[Pcolours][3];
.
20a
extern Cursor curs;			/* barf */
.
## diffname pc/devvga.c 1995/02021
## diff -e /n/fornaxdump/1995/0126/sys/src/brazil/pc/devvga.c /n/fornaxdump/1995/02021/sys/src/brazil/pc/devvga.c
1061,1066d
1054,1056d
## diffname pc/devvga.c 1995/0204
## diff -e /n/fornaxdump/1995/02021/sys/src/brazil/pc/devvga.c /n/fornaxdump/1995/0204/sys/src/brazil/pc/devvga.c
294c
		if(cga == 0)
			cursoroff(1);
.
186,189c
		if(cga)
			return readstr(offset, buf, n, "type: cga\n");
		vgacp = vgac;
.
62c
static Vgac *vgac = &vga;			/* current VGA ctlr */
.
## diffname pc/devvga.c 1995/0206
## diff -e /n/fornaxdump/1995/0204/sys/src/brazil/pc/devvga.c /n/fornaxdump/1995/0206/sys/src/brazil/pc/devvga.c
925c
	if(cga || !rectclip(&r, gscreen.r) || tl<=0)
.
768c
	if(cga || !rectclip(&r, gscreen.r) || tl<=0)
.
293,294c
		cursoroff(1);
.
290a
		}
.
285,289c
		switch(strtoul(cp, &cp, 0)){
		case 8:
			z = 3; break;
		case 1:
			z = 0; break;
		default:
.
280c
		y = strtoul(cp, &cp, 0);
		if(y == 0 || y > 1280)
.
275c
		x = strtoul(field[1], &cp, 0);
		if(x == 0 || x > 2048)
.
## diffname pc/devvga.c 1995/0207
## diff -e /n/fornaxdump/1995/0206/sys/src/brazil/pc/devvga.c /n/fornaxdump/1995/0207/sys/src/brazil/pc/devvga.c
292a
			z = 0;
.
## diffname pc/devvga.c 1995/0228
## diff -e /n/fornaxdump/1995/0207/sys/src/brazil/pc/devvga.c /n/fornaxdump/1995/0228/sys/src/brazil/pc/devvga.c
560c
	seq01 = vgaxi(Seqx, 0x01)|0x01;
.
## diffname pc/devvga.c 1995/0406
## diff -e /n/fornaxdump/1995/0228/sys/src/brazil/pc/devvga.c /n/fornaxdump/1995/0406/sys/src/brazil/pc/devvga.c
949c
	e = ((uchar*)gscreen.base) + footprint;
.
946c
	q = ((uchar*)gscreen.base) + (off&(footprint-1));
.
944c
	page = off>>footshift;
.
929c
	if(screendisabled || cga || !rectclip(&r, gscreen.r) || tl<=0)
.
907,908c
		q -= footprint;
		diff -= footprint;
.
897,898c
		q -= footprint;
		diff -= footprint;
.
876,877c
		q -= footprint;
		diff -= footprint;
.
792c
	e = ((uchar*)gscreen.base) + footprint;
.
789c
	q = ((uchar*)gscreen.base) + (off&(footprint-1));
.
787c
	page = off>>footshift;
.
772c
	if(screendisabled || cga || !rectclip(&r, gscreen.r) || tl<=0)
.
751,752c
		q -= footprint;
		diff -= footprint;
.
741,742c
		q -= footprint;
		diff -= footprint;
.
720,721c
		q -= footprint;
		diff -= footprint;
.
632,634c
	for(i = 0; i < gscreen.width*BY2WD*maxy; i += footprint){
		vgac->page(i>>footshift);
		memset(gscreen.base, 0xff, footprint);
.
628c
	gscreen.base = (void*)screenmem;
.
613,624d
479,581d
303a
		/* see if it fits in the usual place */
		if(x <= 2*Footprint){
			screenmem = SCREENMEM;
			if(x == 0)
				footprint = Footprint;
			else
				footprint = x;
			gscreen.base = (void*)screenmem;
			return;
		}

		/* grab new space */
		if(y == 0){
			if(footprint >= x)
				return;
		} else {
			int s, e;

			s = screenmem & ~KZERO;
			e = s + footprint;
			s = ROUND(s, y);
			if(e > s + x)
				return;
		}
		y = getspace(x, y);
		if(y == 0)
			error("not enough free address space");
		screenmem = y;
		gscreen.base = (void*)y;
		footprint = x;
		return;
	}

.
302a
	else if(strcmp(field[0], "linear") == 0){
		if(n < 2)
			error(Ebadarg);
		x = strtoul(field[1], 0, 0);
		if(n < 3)
			y = 0;
		else
			y = strtoul(field[2], 0, 0);
.
274a
		if(n < 2)
			error(Ebadarg);
.
266a
		if(n < 2)
			error(Ebadarg);
.
242c
	if(strcmp(field[0], "disable") == 0){
		screendisabled = 1;
	}
	else if(strcmp(field[0], "enable") == 0){
		screendisabled = 0;
	}
	else if(strcmp(field[0], "hwgc") == 0){
		if(n < 2)
			error(Ebadarg);
.
239c
	n = getfields(arg, field, 4, " ");
	if(n < 2)
.
234,235c
	int n;
	ulong x, y, z;
	char *cp, *field[4];
.
197c
			port += sprint(cbuf+port, "off\n");
		sprint(cbuf+port, "addr: 0x%lux\n", screenmem&~KZERO);
.
195c
			port += sprint(cbuf+port, "%s\n", hwgc->name);
.
177c
	char cbuf[128];
.
40,51d
18a
	/*  CGA screen dimensions */
	CGAWIDTH=	160,
	CGAHEIGHT=	24,
}; 
/*
 *  screen memory addresses
 */
#define SCREENMEM	(0xA0000 | KZERO)
#define CGASCREEN	((uchar*)(0xB8000 | KZERO))

static	ulong	screenmem = SCREENMEM;
static	int	footprint = Footprint;
static	int	footshift = Footshift;
static	int	screendisabled;

.
17d
14a
	/* default footprint is 64k */
.
## diffname pc/devvga.c 1995/0407
## diff -e /n/fornaxdump/1995/0406/sys/src/brazil/pc/devvga.c /n/fornaxdump/1995/0407/sys/src/brazil/pc/devvga.c
359a
		for(n = 0; n < 31; n++)
			if((1<<n) >= footprint)
				break;
		footshift = n;
.
336a
				for(n = 0; n < 31; n++)
					if((1<<n) >= footprint)
						break;
				footshift = n;
			}
.
335c
				footshift = Footshift;
			} else {
.
333c
			if(x == 0){
.
331c
		if(x <= Footprint){
.
## diffname pc/devvga.c 1995/0508
## diff -e /n/fornaxdump/1995/0407/sys/src/brazil/pc/devvga.c /n/fornaxdump/1995/0508/sys/src/brazil/pc/devvga.c
415a
	case Qvgaiosl:
		if((n & 03) || (offset & 03))
			error(Ebadarg);
		outsl(offset, buf, n/4);
		return n;
.
107a
	"vgaiosl",	{ Qvgaiosl },	0,	0666,	/* Debugging: philw */
.
102c
	Qvgaiosl	= 5,
	Nvga		= Qvgaiosl,
.
## diffname pc/devvga.c 1995/0624
## diff -e /n/fornaxdump/1995/0508/sys/src/brazil/pc/devvga.c /n/fornaxdump/1995/0624/sys/src/brazil/pc/devvga.c
359c
			if(e >= s + x)
.
## diffname pc/devvga.c 1995/0726
## diff -e /n/fornaxdump/1995/0624/sys/src/brazil/pc/devvga.c /n/fornaxdump/1995/0726/sys/src/brazil/pc/devvga.c
157d
155c
vgacreate(Chan*, char*, int, ulong)
.
## diffname pc/devvga.c 1995/0812
## diff -e /n/fornaxdump/1995/0726/sys/src/brazil/pc/devvga.c /n/fornaxdump/1995/0812/sys/src/brazil/pc/devvga.c
1198c
	iunlock(&palettelock);
.
1190c
	ilock(&palettelock);
.
1172c
	iunlock(&palettelock);
.
1168c
	ilock(&palettelock);
.
974c
	iunlock(&palettelock);
.
894c
	ilock(&palettelock);
.
817c
	iunlock(&palettelock);
.
737c
	ilock(&palettelock);
.
## diffname pc/devvga.c 1995/0815
## diff -e /n/fornaxdump/1995/0812/sys/src/brazil/pc/devvga.c /n/fornaxdump/1995/0815/sys/src/brazil/pc/devvga.c
1198c
	unlock(&palettelock);
.
1190c
	lock(&palettelock);
.
1172c
	unlock(&palettelock);
.
1168c
	lock(&palettelock);
.
974c
	unlock(&palettelock);
.
894c
	lock(&palettelock);
.
817c
	unlock(&palettelock);
.
737c
	lock(&palettelock);
.
## diffname pc/devvga.c 1995/1227
## diff -e /n/fornaxdump/1995/0815/sys/src/brazil/pc/devvga.c /n/fornaxdump/1995/1227/sys/src/brazil/pc/devvga.c
1054a
	movecursor();
.
1032d
1027a
cgaregw(uchar index, uchar data)
{
	outb(0x03D4, index);
	outb(0x03D4+1, data);
}

static void
movecursor(void)
{
	cgaregw(0x0E, (pos/2>>8) & 0xFF);
	cgaregw(0x0F, pos/2 & 0xFF);
	CGASCREEN[pos+1] = 2;
}

static void
.
1024,1026c
static int pos;

.
550d
## diffname pc/devvga.c 1996/0216
## diff -e /n/fornaxdump/1995/1227/sys/src/brazil/pc/devvga.c /n/fornaxdump/1996/0216/sys/src/brazil/pc/devvga.c
629,633c
		graphicscmap(0);
.
## diffname pc/devvga.c 1996/0315
## diff -e /n/fornaxdump/1996/0216/sys/src/brazil/pc/devvga.c /n/fornaxdump/1996/0315/sys/src/brazil/pc/devvga.c
245c
	n = parsefields(arg, field, 4, " ");
.
## diffname pc/devvga.c 1996/0418
## diff -e /n/fornaxdump/1996/0315/sys/src/brazil/pc/devvga.c /n/fornaxdump/1996/0418/sys/src/brazil/pc/devvga.c
1016d
1014c
nopage(int)
.
443d
441c
vgawstat(Chan*, char*)
.
436d
434c
vgaremove(Chan*)
.
364,366c
		screenmem = mem;
		gscreen.base = (void*)screenmem;
		footprint = size;
.
361,362c

		mem = 0;
		if(vgac->linear)
			(*vgac->linear)(&mem, &size, &align);
		else
			mem = getspace(size, align);
		if(mem == 0)
.
357,358c
			s = ROUND(s, align);
			if(e >= s + size)
.
349,350c
		if(align == 0){
			if(footprint >= size)
.
338c
				footprint = size;
.
334c
			if(size == 0){
.
332c
		if(size <= Footprint){
.
329c
			align = strtoul(field[2], 0, 0);
.
327c
			align = 0;
.
325c
		size = strtoul(field[1], 0, 0);
.
243a
	ulong mem, size, align;
.
163d
161c
vgaclose(Chan*)
.
## diffname pc/devvga.c 1997/0327
## diff -e /n/fornaxdump/1996/0418/sys/src/brazil/pc/devvga.c /n/emeliedump/1997/0327/sys/src/brazil/pc/devvga.c
1360,1361c
	/*else
		splx(s);*/
.
1311c
		ret = hwgc->move(mousexy());
.
1306c
	} /*else
.
1276c
		hwgc->load(curs);
.
1251c
static void
.
1152c
		screenload(r, (uchar*)chwork.base, tl, l, 1);
.
1021,1074d
977,1015d
972c
	unlock(&myscreenlock);
.
893a
	lock(&myscreenlock);
.
892d
887c
	if(screendisabled || vgascreenputc == nil || !rectclip(&r, gscreen.r) || tl<=0)
.
815c
	unlock(&myscreenlock);
.
736a
	lock(&myscreenlock);
.
735d
730c
	if(screendisabled || vgascreenputc == nil || !rectclip(&r, gscreen.r) || tl<=0)
.
643,645d
626c
	/* switch software to graphics mode */
	if(vgascreenputc == nil)
		vgascreenputc = screenputc;

	qunlock(&screenlock);
.
586a
	qlock(&screenlock);

.
585d
582c
		qunlock(&screenlock);
.
532,555d
438,449d
432,436c
Dev vgadevtab = {
	vgareset,
	vgainit,
	vgaattach,
	devclone,
	vgawalk,
	vgastat,
	vgaopen,
	devcreate,
	vgaclose,
	vgaread,
	devbread,
	vgawrite,
	devbwrite,
	devremove,
	devwstat,
};
.
422,426d
382c
static long
.
366c
			mem = upamalloc(0, size, align);
.
364c
			vgac->linear(&mem, &size, &align);
.
274c
				hwgc->enable();
.
270c
					hwgc->disable();
.
260c
				hwgc->disable();
.
229,234d
189c
		if(vgascreenputc == nil)
.
187c
		return devdirread(c, buf, n, vgadir, nelem(vgadir), devgen);
.
175c
static long
.
154,160c
static void
.
151c
	return devopen(c, omode, vgadir, nelem(vgadir), devgen);
.
148c
static Chan*
.
145c
	devstat(c, dp, vgadir, nelem(vgadir), devgen);
.
142c
static void
.
139c
	return devwalk(c, name, vgadir, nelem(vgadir), devgen);
.
133c
	if(*spec && strcmp(spec, "0"))
		error(Eio);
	return devattach('v', spec);
.
130,131c
static Chan*
vgaattach(char *spec)
.
124,127c
	/*
	 *  swizzle the font longs.
	 */
	l = defont0.bits->base;
	for(i = defont0.bits->width*Dy(defont0.bits->r); i > 0; i--, l++)
		*l = (*l<<24) | ((*l>>8)&0x0000ff00) | ((*l<<8)&0x00ff0000) | (*l>>24);
.
122c
	int i;
	ulong *l;
.
119c
static void
.
116a
	conf.monitor = 1;
.
113c
static void
.
109d
102,103d
89a
extern void	(*vgascreenputc)(char*);
.
88a
static void	cursorinit(void);
.
80,81d
47,49d
45a
static	Lock	myscreenlock;
.
44c
extern	QLock	screenlock;
.
27d
18,21d
## diffname pc/devvga.c 1997/0401
## diff -e /n/emeliedump/1997/0327/sys/src/brazil/pc/devvga.c /n/emeliedump/1997/0401/sys/src/brazil/pc/devvga.c
506a
	iunlock(&vgaxlock);
.
504a
		iunlock(&vgaxlock);
.
475a
	ilock(&vgaxlock);
.
468a
	iunlock(&vgaxlock);
.
466a
		iunlock(&vgaxlock);
.
433a
	ilock(&vgaxlock);
.
36a
static Lock vgaxlock;			/* access to index registers */
.
## diffname pc/devvga.c 1997/0408
## diff -e /n/emeliedump/1997/0401/sys/src/brazil/pc/devvga.c /n/emeliedump/1997/0408/sys/src/brazil/pc/devvga.c
412a
	'v',
	"vga",

.
## diffname pc/devvga.c 1997/0531
## diff -e /n/emeliedump/1997/0408/sys/src/brazil/pc/devvga.c /n/emeliedump/1997/0531/sys/src/brazil/pc/devvga.c
334c
		if(align == 0 || (screenmem % (align-1)) == 0){
.
## diffname pc/devvga.c 1997/0611
## diff -e /n/emeliedump/1997/0531/sys/src/brazil/pc/devvga.c /n/emeliedump/1997/0611/sys/src/brazil/pc/devvga.c
353a

		if(screenmem != SCREENMEM)
			upafree(screenmem, footprint);
.
317a
			if(screenmem != SCREENMEM)
				upafree(screenmem, footprint);
.
## diffname pc/devvga.c 1997/0613
## diff -e /n/emeliedump/1997/0611/sys/src/brazil/pc/devvga.c /n/emeliedump/1997/0613/sys/src/brazil/pc/devvga.c
286c
		if(y == 0 || y > 2048)
.
## diffname pc/devvga.c 1997/1011
## diff -e /n/emeliedump/1997/0613/sys/src/brazil/pc/devvga.c /n/emeliedump/1997/1011/sys/src/brazil/pc/devvga.c
359c
		screenmem = (ulong)KADDR(mem);
.
356a
		/*
		 * Be very careful here, upamalloc now returns a
		 * PHYSICAL address. This won't work once devices
		 * start mapping PCI framebuffers at the address
		 * the BIOS sets, but that hopefully will be after
		 * conversion to the Draw kernel.
		 */
.
## diffname pc/devvga.c 1997/1101
## diff -e /n/emeliedump/1997/1011/sys/src/brazil/pc/devvga.c /n/emeliedump/1997/1101/sys/src/brazil/pc/devvga.c
444,1304d
429c
	devinit,
.
420c

.
418a

	default:
		error(Egreg);
		break;
.
416c
		lp = a;
		for(port = offset; port < offset+n; port += 4)
.
413c
		if((n & 0x03) || (offset & 0x03))
.
411a

.
409c
		sp = a;
		for(port = offset; port < offset+n; port += 2)
.
404a

.
399,403c
		p = a;
		for(port = offset; port < offset+n; port++)
			outb(port, *p++);
.
397a

.
394,396c
		p = malloc(READSTR);
		if(waserror()){
			free(p);
			nexterror();
		}
		memmove(p, a, n);
		p[n] = 0;
		vgactl(p);
		poperror();
		free(p);
.
392c
		if(offset || n >= READSTR)
.
390a

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

.
383,384c
	char *p;
.
380c
vgawrite(Chan* c, void* a, long n, ulong offset)
.
356,372d
315,354c
		if(screenaperture(size, align))
.
309a

.
303c
		if(screensize(x, y, z))
			error(Egreg);
		vgascreenwin(scr);
.
300d
293,295c
			z = 3;
			break;

.
289,291c
		switch(strtoul(p, &p, 0)){
.
287a
		if(*p)
			p++;
.
283,285c
		y = strtoul(p, &p, 0);
.
281a
		if(*p)
			p++;
.
279c
		x = strtoul(field[1], &p, 0);
.
269,273c

		for(i = 0; vgadev[i]; i++){
			if(strcmp(field[1], vgadev[i]->name))
				continue;
			if(scr->dev && scr->dev->disable)
				scr->dev->disable(scr);
			scr->dev = vgadev[i];
			if(scr->dev->enable)
				scr->dev->enable(scr);
			return;
.
252,263c
		for(i = 0; vgacur[i]; i++){
			if(strcmp(field[1], vgacur[i]->name))
				continue;
			lock(&cursor);
			if(scr->cur && scr->cur->disable)
				scr->cur->disable(scr);
			scr->cur = vgacur[i];
			if(scr->cur->enable)
				scr->cur->enable(scr);
			unlock(&cursor);
			return;
.
248a
			unlock(&cursor);
.
244,247c
			lock(&cursor);
			if(scr->cur){
				if(scr->cur->disable)
					scr->cur->disable(scr);
				scr->cur = nil;
.
234,240c
	scr = &vgascreen[0];
	if(strcmp(field[0], "hwgc") == 0){
.
230c
	n = parsefields(a, field, 4, " ");
.
223,228c
	int align, i, n, size, x, y, z;
	char *field[4], *p;
	VGAscr *scr;
	extern VGAdev *vgadev[];
	extern VGAcur *vgacur[];
.
221c
vgactl(char* a)
.
216c

.
214a

	default:
		error(Egreg);
		break;
.
212c
		lp = a;
		for(port = offset; port < offset+n; port += 4)
.
209c
		if((n & 0x03) || (offset & 0x03))
.
207a

.
205c
		sp = a;
		for(port = offset; port < offset+n; port += 2)
.
202c
		if((n & 0x01) || (offset & 0x01))
.
200a

.
196,199c
		for(p = a; port < offset+n; port++)
			*p++ = inb(port);
.
191,193c
			s = "cga";
		len = snprint(p, READSTR, "type: %s\n", s);
		if(scr->gscreen)
			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);
		if(scr->cur)
			s = scr->cur->name;
		else
			s = "off";
		len += snprint(p+len, READSTR-len, "hwgc: %s\n", s);
		snprint(p+len, READSTR-len, "addr: 0x%lux\n", scr->aperture);

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

		return n;

.
180,189c
		scr = &vgascreen[0];

		p = malloc(READSTR);
		if(waserror()){
			free(p);
			nexterror();
		}
		if(scr->dev)
			s = scr->dev->name;
.
178c
		return devdirread(c, a, n, vgadir, nelem(vgadir), devgen);

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

.
174c
	VGAscr *scr;
.
169,171c
	int len, port;
	char *p, *s;
.
167c
vgaread(Chan* c, void* a, long n, ulong offset)
.
156,165d
146c
vgaopen(Chan* c, int omode)
.
140c
vgastat(Chan* c, char* dp)
.
134c
vgawalk(Chan* c, char* name)
.
126c
vgaattach(char* spec)
.
111,124d
107d
97,102d
58,95c
static Dirtab vgadir[] = {
	"vgaiob",	{ Qvgaiob, 0 },		0,	0660,
	"vgaiow",	{ Qvgaiow, 0 },		0,	0660,
	"vgaiol",	{ Qvgaiol, 0 },		0,	0660,
	"vgactl",	{ Qvgactl, 0 },		0,	0660,
.
29,55c
enum {
	Qdir,
	Qvgaiob,
	Qvgaiow,
	Qvgaiol,
	Qvgactl,
.
24,27c
#define	Image	IMAGE
#include <draw.h>
#include <memdraw.h>
#include "screen.h"
.
22c
#include "u.h"
#include "../port/lib.h"
#include "mem.h"
#include "dat.h"
#include "fns.h"
#include "../port/error.h"
.
20d
1,18d
## diffname pc/devvga.c 1998/0319
## diff -e /n/emeliedump/1997/1101/sys/src/brazil/pc/devvga.c /n/emeliedump/1998/0319/sys/src/brazil/pc/devvga.c
254a
	ulong offset = off;
.
249c
vgawrite(Chan* c, void* a, long n, vlong off)
.
74a
	ulong offset = off;
.
68c
vgaread(Chan* c, void* a, long n, vlong off)
.
## diffname pc/devvga.c 1999/0119
## diff -e /n/emeliedump/1998/0319/sys/src/brazil/pc/devvga.c /n/emeliedump/1999/0119/sys/src/brazil/pc/devvga.c
12a
#include <cursor.h>
.
## diffname pc/devvga.c 1999/0714
## diff -e /n/emeliedump/1999/0119/sys/src/brazil/pc/devvga.c /n/emeliedump/1999/0714/sys/src/brazil/pc/devvga.c
296a
		checkport(offset, offset+n+3);
.
287a
		checkport(offset, offset+n+1);
.
280a
		checkport(offset, offset+n);
.
130a
		checkport(offset, offset+n+3);
.
121a
		checkport(offset, offset+n+1);
.
114a
		checkport(offset, offset+n);
.
67a
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);
}

.
33a
	/* 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"); 
.
## diffname pc/devvga.c 1999/1005
## diff -e /n/emeliedump/1999/0714/sys/src/brazil/pc/devvga.c /n/emeliedump/1999/1005/sys/src/brazil/pc/devvga.c
300,326d
277,278d
275d
267a
/*	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], "hwacceloff") == 0){
		scr->fill = nil;
		scr->scroll = nil;
		return;
	}
.
254a
	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){
		if(scr && scr->dev && scr->dev->drawinit)
			scr->dev->drawinit(scr);
		return;
	}
.
249c
		deletescreenimage();
		if(screensize(x, y, z, chan))
.
247a
		if(chantodepth(chan) != z)
			error("depth, channel do not match");

.
243,246c
		chanstr = field[2];
		if((chan = strtochan(chanstr)) == 0)
			error("bad channel");
.
238,241c
		z = strtoul(p, &p, 0);
.
224c
		if(n < 3)
.
183a

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

.
176,177c
	n = parsefields(a, field, nelem(field), " ");
	if(n < 1)
.
174a
	Rectangle r;
.
171c
	char *chanstr, *field[6], *p;
	ulong chan;
.
132,158d
118c
				scr->gscreen->depth);
.
92,93d
90c
	int len;
.
25,27d
18,20d
## diffname pc/devvga.c 1999/1006
## diff -e /n/emeliedump/1999/1005/sys/src/brazil/pc/devvga.c /n/emeliedump/1999/1006/sys/src/brazil/pc/devvga.c
297,299c
	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;
.
## diffname pc/devvga.c 1999/1009
## diff -e /n/emeliedump/1999/1006/sys/src/brazil/pc/devvga.c /n/emeliedump/1999/1009/sys/src/brazil/pc/devvga.c
268a
		*/

.
266a
		/*
		 * 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.
		 */

		/*
.
197a
		if(drawhasclients())
			error(Ebusy);

.
131a
static char Ebusy[] = "vga already configured";

.
## diffname pc/devvga.c 2000/0308
## diff -e /n/emeliedump/1999/1009/sys/src/brazil/pc/devvga.c /n/emeliedump/2000/0308/sys/src/9/pc/devvga.c
145c
	n = getfields(a, field, nelem(field), 1, " ");
.
## diffname pc/devvga.c 2000/0326
## diff -e /n/emeliedump/2000/0308/sys/src/9/pc/devvga.c /n/emeliedump/2000/0326/sys/src/9/pc/devvga.c
317a
		return;
	}
	else if(strcmp(field[0], "hwblank") == 0){
		if(n < 2)
			error(Ebadarg);
		if(strcmp(field[1], "on") == 0)
			hwblank = 1;
		else if(strcmp(field[1], "off") == 0)
			hwblank = 0;
.
281,282d
272,278d
154,157d
1a
 * VGA controller
.
## diffname pc/devvga.c 2000/0330
## diff -e /n/emeliedump/2000/0326/sys/src/9/pc/devvga.c /n/emeliedump/2000/0330/sys/src/9/pc/devvga.c
296c
		drawblankscreen(1);
.
294c
		if(n < 1)
.
118a
			if(Dx(scr->gscreen->r) != Dx(physgscreenr) 
			|| Dy(scr->gscreen->r) != Dy(physgscreenr))
				len += snprint(p+len, READSTR-len, "actualsize %dx%d\n",
					physgscreenr.max.x, physgscreenr.max.y);
		}

		len += snprint(p+len, READSTR-len, "hwaccel %s\n", hwaccel ? "on" : "off");
		len += snprint(p+len, READSTR-len, "hwblank %s\n", hwblank ? "on" : "off");
		snprint(p+len, READSTR-len, "addr 0x%lux\n", scr->aperture);
.
111,117c
				scr->gscreen->depth, chantostr(chbuf, scr->gscreen->chan));
.
107,109c
		len += snprint(p+len, READSTR-len, "type %s\n", s);

		if(scr->gscreen) {
			len += snprint(p+len, READSTR-len, "size %dx%dx%d %s\n",
.
102a

		len = 0;

.
88a
	char chbuf[30];
.
## diffname pc/devvga.c 2000/0522
## diff -e /n/emeliedump/2000/0330/sys/src/9/pc/devvga.c /n/emeliedump/2000/0522/sys/src/9/pc/devvga.c
305a
	}
	else if(strcmp(field[0], "blanktime") == 0){
		if(n < 2)
			error(Ebadarg);
		blanktime = strtoul(field[1], 0, 0);
.
123a
		len += snprint(p+len, READSTR-len, "blanktime %lud\n", blanktime);
.
## diffname pc/devvga.c 2000/0530
## diff -e /n/emeliedump/2000/0522/sys/src/9/pc/devvga.c /n/emeliedump/2000/0530/sys/src/9/pc/devvga.c
311a
		return;
.
## diffname pc/devvga.c 2000/0607
## diff -e /n/emeliedump/2000/0530/sys/src/9/pc/devvga.c /n/emeliedump/2000/0607/sys/src/9/pc/devvga.c
329a
		else
			error(Ebadarg);
.
320a
		else
			error(Ebadarg);
.
155c
	n = getfields(a, field, nelem(field), 1, " \t\n");
.
## diffname pc/devvga.c 2001/0426
## diff -e /n/emeliedump/2000/0607/sys/src/9/pc/devvga.c /n/emeliedump/2001/0426/sys/src/9/pc/devvga.c
364a

	case Qvgaovl:
		scr = &vgascreen[0];
		pprint("vgawrite: Qvgaovl %d (%s)\n", Qvgaovl, scr->dev->name);
		return 0;

	case Qvgaovlctl:
		scr = &vgascreen[0];
		if (scr->dev->ovlctl == nil) {
			error(Enooverlay);
			break;
		}
		return scr->dev->ovlctl(scr, a, n);
.
344a
	VGAscr *scr;
.
339a
char Enooverlay[] = "No overlay support";

.
133a
	case Qvgaovl:
	case Qvgaovlctl:
		error(Ebadusefd);
		break;

.
23c
	"vgactl",		{ Qvgactl, 0 },		0,	0660,
	"vgaovl",		{ Qvgaovl, 0 },		0,	0660,
	"vgaovlctl",	{ Qvgaovlctl, 0 },	0, 	0660,
.
19a
	Qvgaovl,
	Qvgaovlctl,
.
## diffname pc/devvga.c 2001/0427
## diff -e /n/emeliedump/2001/0426/sys/src/9/pc/devvga.c /n/emeliedump/2001/0427/sys/src/9/pc/devvga.c
388a
		pprint("vgawrite: Calling ovlctl (%p) (%s)\n", scr->dev->ovlctl, a);
.
68,69c
vgaclose(Chan*c)
{		
	VGAscr *scr;

	pprint("vgaclose: pid %d, %d, %p\n", up->pid, c->ref, c);
	scr = &vgascreen[0];
	if (scr && scr->dev && scr->dev->ovlctl) {
		static char *disable = "disable\n";
		pprint("vgaclose: Calling ovlctl (%p) %p\n", scr->dev->ovlctl, disable);
		scr->dev->ovlctl(scr, disable, strlen(disable));
	}
.
63a
	pprint("vgaopen: pid %d, %d %p\n", up->pid, c->ref, c);
.
## diffname pc/devvga.c 2001/0428
## diff -e /n/emeliedump/2001/0427/sys/src/9/pc/devvga.c /n/emeliedump/2001/0428/sys/src/9/pc/devvga.c
390,391c
		if (scr->dev->ovlwrite == nil) {
			error(Enooverlay);
			break;
		}
		return scr->dev->ovlwrite(scr, a, n, off);
.
76,77c
		static char disable[] = "disable\n"; 

.
64d
## diffname pc/devvga.c 2001/0430
## diff -e /n/emeliedump/2001/0428/sys/src/9/pc/devvga.c /n/emeliedump/2001/0430/sys/src/9/pc/devvga.c
72d
68c
vgaclose(Chan*)
.
## diffname pc/devvga.c 2001/0501
## diff -e /n/emeliedump/2001/0430/sys/src/9/pc/devvga.c /n/emeliedump/2001/0501/sys/src/9/pc/devvga.c
400,401c
		scr->dev->ovlctl(scr, c, a, n);
		return n;
.
73,76c
	if ((c->qid.path & ~CHDIR) == Qvgaovlctl) {
		if (scr->dev->ovlctl)
			scr->dev->ovlctl(scr, c, closectl, strlen(closectl));
		else 
			error(Enonexist);
.
70a
	static char *closectl = "closectl\n";
.
68c
vgaclose(Chan* c)
.
63a
	VGAscr *scr;
	static char *openctl = "openctl\n";

	scr = &vgascreen[0];
	if ((c->qid.path & ~CHDIR) == Qvgaovlctl) {
		if (scr->dev->ovlctl)
			scr->dev->ovlctl(scr, c, openctl, strlen(openctl));
		else 
			error(Enonexist);
	}
.
## diffname pc/devvga.c 2001/0503
## diff -e /n/emeliedump/2001/0501/sys/src/9/pc/devvga.c /n/emeliedump/2001/0503/sys/src/9/pc/devvga.c
87,88c
			poperror();
		}
.
85c
		if (scr->dev->ovlctl){
			if(waserror())
				return;
.
## diffname pc/devvga.c 2001/0527
## diff -e /n/emeliedump/2001/0503/sys/src/9/pc/devvga.c /n/emeliedump/2001/0527/sys/src/9/pc/devvga.c
432d
400,416d
380c
	switch((ulong)c->qid.path){
.
378d
371,372d
160,164d
117c
	switch((ulong)c->qid.path){
.
78,91c
vgaclose(Chan*)
{
.
64,73d
58c
	return devstat(c, dp, n, vgadir, nelem(vgadir), devgen);
.
55,56c
static int
vgastat(Chan* c, uchar* dp, int n)
.
52c
	return devwalk(c, nc, name, nname, vgadir, nelem(vgadir), devgen);
.
49,50c
Walkqid*
vgawalk(Chan* c, Chan *nc, char** name, int nname)
.
25,27c
	".",	{ Qdir, 0, QTDIR },		0,	0550,
	"vgactl",	{ Qvgactl, 0 },		0,	0660,
.
20,21d
## diffname pc/devvga.c 2001/0822
## diff -e /n/emeliedump/2001/0527/sys/src/9/pc/devvga.c /n/emeliedump/2001/0822/sys/src/9/pc/devvga.c
278a
		memimagedraw(scr->gscreen, scr->gscreen->r, memblack, ZP, nil, ZP);
.
## diffname pc/devvga.c 2001/1005
## diff -e /n/emeliedump/2001/0822/sys/src/9/pc/devvga.c /n/emeliedump/2001/1005/sys/src/9/pc/devvga.c
365a
		return n;

	case Qvgaovl:
		scr = &vgascreen[0];
		if (scr->dev->ovlwrite == nil) {
			error(Enooverlay);
			break;
		}
		return scr->dev->ovlwrite(scr, a, n, off);

	case Qvgaovlctl:
		scr = &vgascreen[0];
		if (scr->dev->ovlctl == nil) {
			error(Enooverlay);
			break;
		}
		scr->dev->ovlctl(scr, c, a, n);
.
346a
	VGAscr *scr;
.
341a
char Enooverlay[] = "No overlay support";

.
134a
	case Qvgaovl:
	case Qvgaovlctl:
		error(Ebadusefd);
		break;

.
66a
	VGAscr *scr;
	static char *closectl = "closectl\n";

	scr = &vgascreen[0];
	if ((ulong)c->qid.path == Qvgaovlctl) {
		if (scr->dev->ovlctl){
			if(waserror())
				return;
			scr->dev->ovlctl(scr, c, closectl, strlen(closectl));
			poperror();
		}
	}
.
65c
vgaclose(Chan* c)
.
60a
	VGAscr *scr;
	static char *openctl = "openctl\n";

	scr = &vgascreen[0];
	if ((ulong)c->qid.path == Qvgaovlctl) {
		if (scr->dev->ovlctl)
			scr->dev->ovlctl(scr, c, openctl, strlen(openctl));
		else 
			error(Enonexist);
	}
.
24c
	"vgactl",		{ Qvgactl, 0 },		0,	0660,
	"vgaovl",		{ Qvgaovl, 0 },		0,	0660,
	"vgaovlctl",	{ Qvgaovlctl, 0 },	0, 	0660,
.
19a
	Qvgaovl,
	Qvgaovlctl,
.
## diffname pc/devvga.c 2001/1015
## diff -e /n/emeliedump/2001/1005/sys/src/9/pc/devvga.c /n/emeliedump/2001/1015/sys/src/9/pc/devvga.c
344a
		return;
	}
	else if(strcmp(field[0], "panning") == 0){
		if(n < 2)
			error(Ebadarg);
		if(strcmp(field[1], "on") == 0){
			if(scr == nil || scr->cur == nil)
				error("set screen first");
			if(!scr->cur->doespanning)
				error("panning not supported");
			scr->gscreen->clipr = scr->gscreen->r;
			panning = 1;
		}
		else if(strcmp(field[1], "off") == 0){
			scr->gscreen->clipr = physgscreenr;
			panning = 0;
		}else
			error(Ebadarg);
.
289,295c
		physgscreenr = Rect(0,0,x,y);
		scr->gscreen->clipr = physgscreenr;
.
185d
153a
		len += snprint(p+len, READSTR-len, "panning %s\n", panning ? "on" : "off");
.
## diffname pc/devvga.c 2001/1117
## diff -e /n/emeliedump/2001/1015/sys/src/9/pc/devvga.c /n/emeliedump/2001/1117/sys/src/9/pc/devvga.c
187c
	n = tokenize(a, field, nelem(field));
.
## diffname pc/devvga.c 2001/1120
## diff -e /n/emeliedump/2001/1117/sys/src/9/pc/devvga.c /n/emeliedump/2001/1120/sys/src/9/pc/devvga.c
412c
		free(cb);
.
408,410c
		vgactl(cb);
.
405c
			free(cb);
.
403c
		cb = parsecmd(a, n);
.
392a
	Cmdbuf *cb;
.
391d
383c
	cmderror(cb, "bad VGA control message");
.
379c
			break;
.
376c
		else if(strcmp(cb->f[1], "off") == 0)
.
370,374c
	
	case CMhwblank:
		if(strcmp(cb->f[1], "on") == 0)
.
368c
			break;
.
365c
		else if(strcmp(cb->f[1], "off") == 0)
.
359,363c

	case CMhwaccel:
		if(strcmp(cb->f[1], "on") == 0)
.
357c
			break;
.
353c
		else if(strcmp(cb->f[1], "off") == 0){
.
341,345c

	case CMpanning:
		if(strcmp(cb->f[1], "on") == 0){
.
335,339c
	
	case CMblanktime:
		blanktime = strtoul(cb->f[1], 0, 0);
.
330,332c

	case CMblank:
.
328d
322,326c
/*	
	case CMmemset:
		memset((void*)strtoul(cb->f[1], 0, 0), atoi(cb->f[2]), atoi(cb->f[3]));
.
318c
			align = strtoul(cb->f[2], 0, 0);
.
313,315c
		size = strtoul(cb->f[1], 0, 0);
		if(cb->nf == 2)
.
309,311c
	
	case CMlinear:
		if(cb->nf!=2 && cb->nf!=3)
.
303,304c

	case CMdrawinit:
.
292,297c
	
	case CMpalettedepth:
		x = strtoul(cb->f[1], &p, 0);
.
274,276c
		x = strtoul(cb->f[1], &p, 0);
.
269,270c

	case CMactualsize:
.
255c
		chanstr = cb->f[2];
.
241c
		x = strtoul(cb->f[1], &p, 0);
.
234,237c
		break;

	case CMsize:
.
225c
			if(strcmp(cb->f[1], vgadev[i]->name))
.
223a
	case CMtype:
.
219,222c
		break;
.
208c
			if(strcmp(cb->f[1], vgacur[i]->name))
.
192,196c
	ct = lookupcmd(cb, vgactlmsg, nelem(vgactlmsg));
	switch(ct->index){
	case CMhwgc:
		if(strcmp(cb->f[1], "off") == 0){
.
187,190d
182a
	Cmdtab *ct;
.
180,181c
	int align, i, size, x, y, z;
	char *chanstr, *p;
.
178c
vgactl(Cmdbuf *cb)
.
30a
enum {
	CMactualsize,
	CMblank,
	CMblanktime,
	CMdrawinit,
	CMhwaccel,
	CMhwblank,
	CMhwgc,
	CMlinear,
	CMpalettedepth,
	CMpanning,
	CMsize,
	CMtype,
};

static Cmdtab vgactlmsg[] = {
	CMactualsize,	"actualsize",	2,
	CMblank,	"blank",	1,
	CMblanktime,	"blanktime",	2,
	CMdrawinit,	"drawinit",	1,
	CMhwaccel,	"hwaccel",	2,
	CMhwblank,	"hwblank",	2,
	CMhwgc,		"hwgc",		2,
	CMlinear,	"linear",	0,
	CMpalettedepth,	"palettedepth",	2,
	CMpanning,	"panning",	2,
	CMsize,		"size",		3,
	CMtype,		"type",		2,
};

.
## diffname pc/devvga.c 2001/1204
## diff -e /n/emeliedump/2001/1120/sys/src/9/pc/devvga.c /n/emeliedump/2001/1204/sys/src/9/pc/devvga.c
122d
118a
			}
.
115,117c
	if((ulong)c->qid.path == Qvgaovlctl)
		if(scr->dev->ovlctl){
			if(waserror()){
				print("ovlctl error: %s\n", up->errstr);
.
## diffname pc/devvga.c 2002/0109
## diff -e /n/emeliedump/2001/1204/sys/src/9/pc/devvga.c /n/emeliedump/2002/0109/sys/src/9/pc/devvga.c
449a
	devshutdown,
.
## diffname pc/devvga.c 2002/0430
## diff -e /n/emeliedump/2002/0109/sys/src/9/pc/devvga.c /n/emeliedump/2002/0430/sys/src/9/pc/devvga.c
429c
		if (scr->dev == nil || scr->dev->ovlctl == nil) {
.
421c
		if (scr->dev == nil || scr->dev->ovlwrite == nil) {
.
116c
		if(scr->dev && scr->dev->ovlctl){
.
100c
		if (scr->dev && scr->dev->ovlctl)
.
## diffname pc/devvga.c 2002/1201
## diff -e /n/emeliedump/2002/0430/sys/src/9/pc/devvga.c /n/emeliedump/2002/1201/sys/src/9/pc/devvga.c
182c
		len += snprint(p+len, READSTR-len, "blank time %lud idle %d state %s\n",
			blanktime, drawidletime(), scr->isblank ? "off" : "on");
.
## diffname pc/devvga.c 2002/1205
## diff -e /n/emeliedump/2002/1201/sys/src/9/pc/devvga.c /n/emeliedump/2002/1205/sys/src/9/pc/devvga.c
325c
		memimagedraw(scr->gscreen, scr->gscreen->r, memblack, ZP, nil, ZP, S);
.

Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to [email protected].