~kris/9p

9hist

4db08b02a6b8a1ee615e521a080eb82e11d11e76 — David du Colombier 32 years ago a6502d5
Plan 9 from Bell Labs 1994-06-24
M carrera/screen.c => carrera/screen.c +2 -1
@@ 441,7 441,7 @@ setcursor(Cursor *curs)
	free(hwcursor.base);
}

void
int
cursoron(int dolock)
{
	Dac *d;


@@ 465,6 465,7 @@ cursoron(int dolock)

	if(dolock)
		unlock(&cursor);
	return 0;
}

int

M carrera/screen.h => carrera/screen.h +1 -1
@@ 9,7 9,7 @@ struct Cursorinfo
extern Cursorinfo	cursor;

extern void	mouseupdate(int);
extern void	cursoron(int);
extern int	cursoron(int);
#define		cursoroff(x)
#define		mousectl(s)
extern Point	mousexy(void);

M pc/devvga.c => pc/devvga.c +314 -257
@@ 8,28 8,7 @@

#include	<libg.h>
#include	"screen.h"

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 */
};
#include	"vga.h"

enum
{


@@ 47,6 26,7 @@ Bitmap	gscreen;
static	Lock	screenlock;
static	Lock	loadlock;
static	ulong	colormap[256][3];
Lock pallettelock;

/* cga screen */
static	int	cga = 1;		/* true if in cga mode */


@@ 59,9 39,6 @@ static	Point	curpos;
/*
 *  screen dimensions
 */
#define	MINX	8
#define MAXX	640
#define MAXY	480
#define	CGAWIDTH	160
#define	CGAHEIGHT	24



@@ 79,7 56,6 @@ struct Vgacard
{
	char	*name;
	void	(*setpage)(int);	/* routine to page though display memory */
	void	(*mvcursor)(Point);	/* routine to move hardware cursor */
};

enum


@@ 93,25 69,34 @@ enum
	Generic,
};

static void	nopage(int), tsengpage(int), tridentpage(int), parapage(int);
static void	nopage(int), tsengpage(int), tridentpage(int);
static void	atipage(int), cirruspage(int), s3page(int);

static void	nomvcursor(Point);

Vgacard vgachips[] =
{
[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, },
[Ati]		{ "ati", atipage, },
[Pvga1a]	{ "pvga1a", cirruspage, },
[Trident]	{ "trident", tridentpage, },
[Tseng]		{ "tseng", tsengpage, },
[Cirrus]	{ "cirrus", cirruspage, },
[S3]		{ "s3", s3page, },
[Generic]	{ "generic", nopage, },
		{ 0, 0, },
};

Vgacard	*vgacard;	/* current vga card */
int hwcursor;

extern Hwgc tvp3020hwgc;
extern Hwgc bt485hwgc;

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

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

/*
 *  work areas for bitblting screen characters, scrolling, and cursor redraw


@@ 122,12 107,6 @@ Bitmap cursorwork;

/* 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	cgascreenputc(int);
static void	cgascreenputs(char*, int);
static void	screenputc(char*);


@@ 141,53 120,23 @@ static void	cursorunlock(void);

extern int	graphicssubtile(uchar*, int, int, Rectangle, Rectangle, uchar**);


/*
 *  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);
}

/*
 *  vga device
 */
enum
{
	Qdir=		0,
	Qvgasize=	1,
	Qvgatype=	2,
	Qvgaport=	3,
	Qvgaportw=	4,
	Qvgaportl=	5,
	Qvgactl=	6,
	Nvga=		6,
	Qdir		= 0,
	Qvgaiob		= 1,
	Qvgaiow		= 2,
	Qvgaiol		= 3,
	Qvgactl		= 4,
	Nvga		= Qvgactl,
};
Dirtab vgadir[]={
	"vgasize",	{Qvgasize},	0,		0666,
	"vgatype",	{Qvgatype},	0,		0666,
	"vgaport",	{Qvgaport},	0,		0666,
	"vgaportw",	{Qvgaportw},	0,		0666,
	"vgaportl",	{Qvgaportl},	0,		0666,
	"vgactl",	{Qvgactl},	0,		0666,
	"vgaiob",	{ Qvgaiob },	0,	0666,
	"vgaiow",	{ Qvgaiow },	0,	0666,
	"vgaiol",	{ Qvgaiol },	0,	0666,
	"vgactl",	{ Qvgactl },	0,	0666,
};

void


@@ 245,6 194,16 @@ vgaclose(Chan *c)
	USED(c);
}

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;
}

long
vgaread(Chan *c, void *buf, long n, ulong offset)
{


@@ 257,24 216,31 @@ vgaread(Chan *c, void *buf, long n, ulong offset)
	switch(c->qid.path&~CHDIR){
	case Qdir:
		return devdirread(c, buf, n, vgadir, Nvga, devgen);
	case Qvgasize:
		sprint(cbuf, "%dx%dx%d", gscreen.r.max.x, gscreen.r.max.y,
			1<<gscreen.ldepth);
	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");
		return readstr(offset, buf, n, cbuf);
	case Qvgatype:
		return readstr(offset, buf, n, vgacard->name);
	case Qvgaport:
		for (cp = buf, port=offset; port<offset+n; port++)
			*cp++ = inb(port);
	case Qvgaiob:
		port = offset;
		if(checkvgaport(port, n))
			error(Eperm);
		for(cp = buf; port < offset+n; port++)
			*cp++ = vgai(port);
		return n;
	case Qvgaportw:
	case Qvgaiow:
		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;
	case Qvgaportl:
	case Qvgaiol:
		if((n & 03) || (offset & 03))
			error(Ebadarg);
		n /= 4;


@@ 286,87 252,108 @@ vgaread(Chan *c, void *buf, long n, ulong offset)
	return 0;
}

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);
}

long
vgawrite(Chan *c, void *buf, long n, ulong offset)
{
	char cbuf[64], *cp;
	Vgacard *vp;
	int port, maxx, maxy, ldepth;
	int port;
	uchar *cp;
	char cbuf[64];
	ushort *sp;
	ulong *lp;

	switch(c->qid.path&~CHDIR){
	case Qdir:
		error(Eperm);
	case Qvgatype:
		if(offset != 0 || n >= sizeof(cbuf) || n < 1)
			error(Ebadarg);
		memmove(cbuf, buf, n);
		cbuf[n] = 0;
		if(cp = strchr(cbuf, '\n'))
			*cp = 0;
		for(vp = vgachips; vp->name; vp++)
			if(strcmp(cbuf, vp->name) == 0){
				vgacard = vp;
				return n;
			}
		error(Ebadarg);
	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;
	case Qvgasize:
		if(offset != 0 || n >= sizeof(cbuf))
			error(Ebadarg);
		memmove(cbuf, buf, n);
		cbuf[n] = 0;
		cp = cbuf;
		maxx = strtoul(cp, &cp, 0);
		if(*cp!=0)
			cp++;
		maxy = strtoul(cp, &cp, 0);
		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 > 1600 || maxy > 1280
		|| ldepth > 3 || ldepth < 0)
			error(Ebadarg);
		cursoroff(1);
		setscreen(maxx, maxy, ldepth);
		cursoron(1);
		vgactl(cbuf);
		return n;
	case Qvgaport:
		for (cp = buf, port=offset; port<offset+n; port++)
			outb(port, *cp++);
	case Qvgaiob:
		port = offset;
		if(checkvgaport(port, n))
			error(Eperm);
		for(cp = buf; port < offset+n; port++)
			vgao(port, *cp++);
		return n;
	case Qvgaportw:
	case Qvgaiow:
		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;
	case Qvgaportl:
	case Qvgaiol:
		if((n & 03) || (offset & 03))
			error(Ebadarg);
		n /= 4;


@@ 392,53 379,111 @@ vgawstat(Chan *c, char *dp)
	error(Eperm);
}

/*
 *  accessing card registers
 */
static uchar
srin(int i) {
	outb(SRX, i);
	return inb(SR);
}
static void
genout(int reg, int val)
{
	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)
int
vgaxi(long port, uchar index)
{
	outb(GRX, reg);
	outb(GR, val);
	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;
}
static void
arout(int reg, int val)

int
vgaxo(long port, uchar index, uchar data)
{
	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);
	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;
	}

	return 0;
}
static void
crout(int reg, int val)

/*
 *  start the screen in CGA mode.  Create the fonts for VGA.  Called by
 *  main().
 */
void
screeninit(void)
{
	outb(CRX, reg);
	outb(CR, val);
	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);
}

/*


@@ 447,7 492,7 @@ crout(int reg, int val)
typedef struct VGAmode	VGAmode;
struct VGAmode
{
	uchar	general[2];
	uchar	misc;
	uchar	sequencer[5];
	uchar	crt[0x19];
	uchar	graphics[9];


@@ 460,7 505,7 @@ struct VGAmode
VGAmode mode12 = 
{
	/* general */
	0xe7, 0x00,
	0xe7,
	/* sequence */
	0x03, 0x01, 0x0f, 0x00, 0x06,
	/* crt */


@@ 483,7 528,7 @@ VGAmode mode12 =
VGAmode mode13 = 
{
	/* general */
	0x63, 0x00,
	0x63,
	/* sequence */
	0x03, 0x01, 0x0f, 0x00, 0x0e,
	/* crt */


@@ 501,34 546,47 @@ VGAmode mode13 =
};

static void
setmode(VGAmode *v)
setmode(VGAmode *vga)
{
	int i;

	/* turn screen off (to avoid damage) */
	srout(1, 0x21);
	/*
	 * 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);

	vgaxo(Seqx, 0x00, 0x00);

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

	for(i = 0; i < sizeof(v->sequencer); i++)
	for(i = 1; i < NSeqx; i++){
		if(i == 1)
			srout(i, v->sequencer[i]|0x20);		/* avoid enabling screen */
		else
			srout(i, v->sequencer[i]);
			continue;
		vgaxo(Seqx, i, vga->sequencer[i]);
	}
	vgaxo(Seqx, 0x00, 0x03);

	crout(Cvre, 0);	/* allow writes to CRT registers 0-7 */
	for(i = 0; i < sizeof(v->crt); i++)
		crout(i, v->crt[i]);
	vgaxo(Crtx, 0x11, vga->crt[0x11] & ~0x80);
	for(i = 0; i < NCrtx; i++)
		vgaxo(Crtx, i, vga->crt[i]);

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

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

	/* turn screen on */
	srout(1, v->sequencer[1]);
	vgaxo(Seqx, 0x01, vga->sequencer[1]);
}

/*


@@ 709,7 767,7 @@ screenload(Rectangle r, uchar *data, int tl, int l, int dolock)
	if(!rectclip(&r, gscreen.r) || tl<=0)
		return;

	if(dolock && hwcursor == 0)
	if(dolock && hwgc == 0)
		cursorlock(r);
	lock(&loadlock);



@@ 792,7 850,7 @@ screenload(Rectangle r, uchar *data, int tl, int l, int dolock)
		}

	unlock(&loadlock);
	if(dolock && hwcursor == 0)
	if(dolock && hwgc == 0)
		cursorunlock();
}



@@ 865,7 923,7 @@ screenunload(Rectangle r, uchar *data, int tl, int l, int dolock)
	if(!rectclip(&r, gscreen.r) || tl<=0)
		return;

	if(dolock && hwcursor == 0)
	if(dolock && hwgc == 0)
		cursorlock(r);
	lock(&loadlock);



@@ 948,7 1006,7 @@ screenunload(Rectangle r, uchar *data, int tl, int l, int dolock)
		}

	unlock(&loadlock);
	if(dolock && hwcursor == 0)
	if(dolock && hwgc == 0)
		cursorunlock();
}



@@ 1048,7 1106,10 @@ atipage(int page)
static void
tridentpage(int page)
{
	srout(0xe, (srin(0xe)&0xf0) | page^0x2);
	uchar seq0E;

	seq0E = vgaxi(Seqx, 0x0E) & 0xF0;
	vgaxo(Seqx, 0x0E, seq0E|(page^0x02));
}
static void
tsengpage(int page)


@@ 1058,12 1119,7 @@ tsengpage(int page)
static void
cirruspage(int page)
{
	grout(0x9, page<<4);
}
static void
parapage(int page)
{
	grout(0x9, page<<4);
	vgaxo(Grx, 0x09, page<<4);
}
static void
s3page(int page)


@@ 1077,28 1133,18 @@ s3page(int page)
		/*
		 * The S3 registers need to be unlocked for this.
		 * Let's hope they are already:
		 *	crout(0x38, 0x48);
		 *	crout(0x39, 0xA0);
		 *	vgaxo(Crtx, 0x38, 0x48);
		 *	vgaxo(Crtx, 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);
		vgaxo(Crtx, 0x35, page & 0x0F);
		crt51 = vgaxi(Crtx, 0x51) & 0xF3;
		vgaxo(Crtx, 0x51, crt51|((page & 0x30)>>2));
	}
	else
		crout(0x35, (page<<2) & 0x0C);
}

/*
 *  hardware cursor routines
 */
static void
nomvcursor(Point p)
{
	USED(p.x);
		vgaxo(Crtx, 0x35, (page<<2) & 0x0C);
}

/*


@@ 1245,11 1291,11 @@ getcolor(ulong p, ulong *pr, ulong *pg, ulong *pb)
	}
	p &= x;
	p ^= x;
	lock(&screenlock);
	lock(&pallettelock);
	*pr = colormap[p][0];
	*pg = colormap[p][1];
	*pb = colormap[p][2];
	unlock(&screenlock);
	unlock(&pallettelock);
}

int


@@ 1267,20 1313,21 @@ setcolor(ulong p, ulong r, ulong g, ulong b)
	}
	p &= x;
	p ^= x;
	lock(&screenlock);
	lock(&pallettelock);
	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(&screenlock);
	vgao(DACWx, p);
	vgao(DACData, r>>(32-6));
	vgao(DACData, g>>(32-6));
	vgao(DACData, b>>(32-6));
	unlock(&pallettelock);
	return ~0;
}

/*
 *  software cursor
 *  and hacks for hardware cursor
 */

/*


@@ 1340,7 1387,9 @@ setcursor(Cursor *curs)
	uchar *p;
	int i;

	for(i=0; i<16; i++){
	if(hwgc)
		(*hwgc->load)(curs);
	else for(i=0; i<16; i++){
		p = (uchar*)&set.base[i];
		*p = curs->set[2*i];
		*(p+1) = curs->set[2*i+1];


@@ 1350,10 1399,10 @@ setcursor(Cursor *curs)
	}
}

void
int
cursoron(int dolock)
{
	int xoff, yoff;
	int xoff, yoff, s, ret;
	Rectangle r;
	uchar *a;
	struct {


@@ 1365,12 1414,16 @@ cursoron(int dolock)
	} xx;

	if(cursor.disable)
		return;
	if(dolock)
		return 0;
	if(dolock){
		s = 0;		/* to avoid compiler warning */
		lock(&cursor);
	} else
		s = spllo();	/* to avoid freezing out the eia ports */

	if(hwcursor)
		(*vgacard->mvcursor)(mousexy());
	ret = 0;
	if(hwgc)
		ret = (*hwgc->move)(mousexy());
	else if(cursor.visible++ == 0){
		cursor.r.min = mousexy();
		cursor.r.max = add(cursor.r.min, Pt(16, 16));


@@ 1419,12 1472,16 @@ cursoron(int dolock)

	if(dolock)
		unlock(&cursor);
	else
		splx(s);

	return ret;
}

void
cursoroff(int dolock)
{
	if(hwcursor)
	if(hwgc)
		return;
	if(cursor.disable)
		return;

M pc/screen.h => pc/screen.h +1 -1
@@ 14,7 14,7 @@ struct Cursorinfo
};

Cursorinfo	cursor;
extern void	cursoron(int);
extern int	cursoron(int);
extern void	cursoroff(int);
extern Point	mousexy(void);
extern void	cursorinit(void);

M pc/vga.h => pc/vga.h +46 -26
@@ 1,29 1,49 @@
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 */
/*
 * Generic VGA registers.
 */
enum {
	MiscW		= 0x03C2,	/* Miscellaneous Output (W) */
	MiscR		= 0x03CC,	/* Miscellaneous Output (R) */
	Status0		= 0x03C2,	/* Input status 0 (R) */
	Status1		= 0x03DA,	/* Input Status 1 (R) */
	FeatureR	= 0x03CA,	/* Feature Control (R) */
	FeatureW	= 0x03DA,	/* Feature Control (W) */

	Seqx		= 0x03C4,	/* Sequencer Index, Data at Seqx+1 */
	NSeqx		= 0x05,

	Crtx		= 0x03D4,	/* CRT Controller Index, Data at Crtx+1 */
	NCrtx		= 0x19,

	Grx		= 0x03CE,	/* Graphics Controller Index, Data at Grx+1 */
	NGrax		= 0x09,

	Attrx		= 0x03C0,	/* Attribute Controller Index and Data */
	NAttrx		= 0x15,

	DACMask		= 0x03C6,	/* DAC Mask */
	DACRx		= 0x03C7,	/* DAC Read Index (W) */
	DACSts		= 0x03C7,	/* DAC Status (R) */
	DACWx		= 0x03C8,	/* DAC Write Index */
	DACData		= 0x03C9,	/* DAC Data */
	NDACx		= 0x100,
};

#define SCREENMEM	(0xA0000 | KZERO)
#define CGASCREEN	((uchar*)(0xB8000 | KZERO))
#define	CGAWIDTH	160
#define	CGAHEIGHT	24
#define vgai(port)		inb(port)
#define vgao(port, data)	outb(port, data)

extern int vgaxi(long, uchar);
extern int vgaxo(long, uchar, uchar);

/*
 * Definitions of known hardware graphics cursors.
 */
typedef struct Hwgc {
	char	*name;
	void	(*enable)(void);
	void	(*load)(Cursor*);
	int	(*move)(Point);
	void	(*disable)(void);
} Hwgc;

extern	void setscreen(int, int, int);
extern	struct GBitmap	gscreen;
extern Lock pallettelock;

A pc/vgabt485.c => pc/vgabt485.c +259 -0
@@ 0,0 1,259 @@
#include "u.h"
#include "../port/lib.h"
#include "mem.h"
#include "dat.h"
#include "fns.h"
#include "../port/error.h"

#include <libg.h>
#include "screen.h"
#include "vga.h"

/*
 * Hardware graphics cursor support for
 * Brooktree Bt485 Monolithic True-Color RAMDAC.
 * Assumes hooked up to an S3 86C928.
 *
 * BUGS:
 *	64x64x2 cursor always used;
 *	no support for interlaced mode.
 */
enum {
	AddrW		= 0x00,		/* Address register; palette/cursor RAM write */
	Palette		= 0x01,		/* 6/8-bit color palette data */
	Pmask		= 0x02,		/* Pixel mask register */
	AddrR		= 0x03,		/* Address register; palette/cursor RAM read */
	ColorW		= 0x04,		/* Address register; cursor/overscan color write */
	Color		= 0x05,		/* Cursor/overscan color data */
	Cmd0		= 0x06,		/* Command register 0 */
	ColorR		= 0x07,		/* Address register; cursor/overscan color read */
	Cmd1		= 0x08,		/* Command register 1 */
	Cmd2		= 0x09,		/* Command register 2 */
	Status		= 0x0A,		/* Status */
	Cmd3		= 0x1A,		/* Command register 3 */
	Cram		= 0x0B,		/* Cursor RAM array data */
	Cxlr		= 0x0C,		/* Cursor x-low register */
	Cxhr		= 0x0D,		/* Cursor x-high register */
	Cylr		= 0x0E,		/* Cursor y-low register */
	Cyhr		= 0x0F,		/* Cursor y-high register */

	Nreg		= 0x10,
};

/*
 * Lower 2-bits of indirect DAC register
 * addressing.
 */
static ushort dacxreg[4] = {
	DACWx, DACData, DACMask, DACSts
};

static uchar
bt485io(uchar reg)
{
	uchar crt55, cr0;

	crt55 = vgaxi(Crtx, 0x55) & 0xFC;
	if((reg & 0x0F) == Status){
		/*
		 * 1,2: Set indirect addressing for Status or
		 *      Cmd3 - set bit7 of Cr0.
		 */
		vgaxo(Crtx, 0x55, crt55|((Cmd0>>2) & 0x03));
		cr0 = vgai(dacxreg[Cmd0 & 0x03])|0x80;
		vgao(dacxreg[Cmd0 & 0x03], cr0);

		/*
		 * 3,4: Set the index into the Write register,
		 *      index == 0x00 for Status, 0x01 for Cmd3.
		 */
		vgaxo(Crtx, 0x55, crt55|((AddrW>>2) & 0x03));
		vgao(dacxreg[AddrW & 0x03], (reg == Status) ? 0x00: 0x01);

		/*
		 * 5,6: Get the contents of the appropriate
		 *      register at 0x0A.
		 */
	}

	return crt55;
}

static uchar
bt485i(uchar reg)
{
	uchar crt55, r;

	crt55 = bt485io(reg);
	vgaxo(Crtx, 0x55, crt55|((reg>>2) & 0x03));
	r = vgai(dacxreg[reg & 0x03]);
	vgaxo(Crtx, 0x55, crt55);

	return r;
}

static void
bt485o(uchar reg, uchar data)
{
	uchar crt55;

	crt55 = bt485io(reg);
	vgaxo(Crtx, 0x55, crt55|((reg>>2) & 0x03));
	vgao(dacxreg[reg & 0x03], data);
	vgaxo(Crtx, 0x55, crt55);
}

static Point hotpoint;

static void
load(Cursor *c)
{
	uchar r;
	int x, y;


	lock(&pallettelock);

	/*
	 * Turn cursor off;
	 * put cursor into 64x64x2 mode and clear MSBs of address;
	 * clear LSBs of address;
	 */
	r = bt485i(Cmd2) & 0xFC;
	bt485o(Cmd2, r);

	r = (bt485i(Cmd3) & 0xFC)|0x04;
	bt485o(Cmd3, r);

	bt485o(AddrW, 0x00);

	/*
	 * Now load the cursor RAM array, both planes.
	 * The cursor is 16x16, the array 64x64; put
	 * the cursor in the top left. The 0,0 cursor
	 * point is bottom-right, so positioning will
	 * have to take that into account.
	 */
	for(y = 0; y < 64; y++){
		for(x = 0; x < 64/8; x++){
			if(x < 16/8 && y < 16)
				bt485o(Cram, c->clr[x+y*2]);
			else
				bt485o(Cram, 0x00);
		}
	}
	for(y = 0; y < 64; y++){
		for(x = 0; x < 64/8; x++){
			if(x < 16/8 && y < 16)
				bt485o(Cram, c->set[x+y*2]);
			else
				bt485o(Cram, 0x00);
		}
	}

	/*
	 * Initialise the cursor hot-point
	 * and enable the cursor.
	 */
	hotpoint.x = 64+c->offset.x;
	hotpoint.y = 64+c->offset.y;

	r = (bt485i(Cmd2) & 0xFC)|0x01;
	bt485o(Cmd2, r);

	unlock(&pallettelock);
}

static void
enable(void)
{
	uchar r;

	lock(&pallettelock);

	/*
	 * Turn cursor off.
	 */
	r = bt485i(Cmd2) & 0xFC;
	bt485o(Cmd2, r);

	/*
	 * Overscan colour,
	 * cursor colour 1 (white),
	 * cursor colour 2, 3 (black).
	 */
	bt485o(ColorW, 0x00);
	bt485o(Color, 0xFF); bt485o(Color, 0xFF); bt485o(Color, 0xFF);

	bt485o(Color, 0xFF); bt485o(Color, 0xFF); bt485o(Color, 0xFF);

	bt485o(Color, 0x00); bt485o(Color, 0x00); bt485o(Color, 0x00);
	bt485o(Color, 0x00); bt485o(Color, 0x00); bt485o(Color, 0x00);

	unlock(&pallettelock);

	/*
	 * Finally, enable
	 *	the hardware cursor external operation mode;
	 *	cursor control enable for Bt485 DAC.
	 * The #9GXE cards seem to need the 86C928 Bt485 support
	 * enabled in order to work at all in enhanced mode.
	 */

	r = vgaxi(Crtx, 0x55)|0x20;
	vgaxo(Crtx, 0x55, r);

	r = vgaxi(Crtx, 0x45)|0x20;
	vgaxo(Crtx, 0x45, r);
}

static int
move(Point p)
{
	int x, y;

	if(canlock(&pallettelock) == 0)
		return 1;

	x = p.x+hotpoint.x;
	y = p.y+hotpoint.y;

	bt485o(Cxlr, x & 0xFF);
	bt485o(Cxhr, (x>>8) & 0x0F);
	bt485o(Cylr, y & 0xFF);
	bt485o(Cyhr, (y>>8) & 0x0F);

	unlock(&pallettelock);
	return 0;
}

static void
disable(void)
{
	uchar r;

	/*
	 * Disable 
	 *	cursor mode 3;
	 *	cursor control enable for Bt485 DAC;
	 *	the hardware cursor external operation mode.
	 */
	lock(&pallettelock);
	r = bt485i(Cmd2) & ~0x03;
	bt485o(Cmd2, r);
	unlock(&pallettelock);

	r = vgaxi(Crtx, 0x45) & ~0x20;
	vgaxo(Crtx, 0x45, r);

	r = vgaxi(Crtx, 0x55) & ~0x20;
	vgaxo(Crtx, 0x55, r);
}

Hwgc bt485hwgc = {
	"bt485hwgc",
	enable,
	load,
	move,
	disable,
};

A pc/vgatvp3020.c => pc/vgatvp3020.c +232 -0
@@ 0,0 1,232 @@
#include "u.h"
#include "../port/lib.h"
#include "mem.h"
#include "dat.h"
#include "fns.h"
#include "../port/error.h"

#include <libg.h>
#include "screen.h"
#include "vga.h"

/*
 * TVP3020 Viewpoint Video Interface Pallette.
 * Assumes hooked up to an S3 86C928.
 */
enum {
	AddrW		= 0x00,		/* Palette address register - write mode */
	Palette		= 0x01,		/* Color palette holding register */
	Pmask		= 0x02,		/* Pixel read mask */
	AddrR		= 0x03,		/* Palette address register - read mode */

	Index		= 0x06,		/* Index register */
	Data		= 0x07,		/* Data register */
};

/*
 * Lower 2-bits of indirect DAC register
 * addressing.
 */
static ushort dacxreg[4] = {
	DACWx, DACData, DACMask, DACSts
};

static uchar
tvp3020io(uchar reg, uchar data)
{
	uchar crt55;

	crt55 = vgaxi(Crtx, 0x55) & 0xFC;
	vgaxo(Crtx, 0x55, crt55|((reg>>2) & 0x03));
	vgao(dacxreg[reg & 0x03], data);

	return crt55;
}

static void
tvp3020xo(uchar index, uchar data)
{
	uchar crt55;

	crt55 = tvp3020io(Index, index);
	vgao(dacxreg[Data & 0x03], data);
	vgaxo(Crtx, 0x55, crt55);
}

static void
load(Cursor *c)
{
	uchar p, p0, p1;
	int x, y;

	lock(&pallettelock);

	/*
	 * Make sure cursor is off by initialising the cursor
	 * control to defaults + X-Windows cursor mode.
	 */
	tvp3020xo(0x06, 0x10);				/* Cursor Control Register */

	/*
	 * Initialise the cursor RAM LS and MS address
	 * (LS must be first).
	 */
	tvp3020xo(0x08, 0x00);				/* Cursor RAM LS Address */
	tvp3020xo(0x09, 0x00);				/* Cursor RAM MS Address */

	/*
	 * Initialise the 64x64 cursor RAM array. There are 2 planes,
	 * p0 and p1. Data is written 4 pixels per byte, with p1 the
	 * MS bit of each pixel.
	 * The cursor is set in X-Windows mode which gives the following
	 * truth table:
	 *	p1 p0	colour
	 *	 0  0	underlying pixel colour
	 *	 0  1	underlying pixel colour
	 *	 1  0	cursor colour 1
	 *	 1  1	cursor colour 2
	 * Put the cursor into the top-left of the 64x64 array.
	 */
	for(y = 0; y < 64; y++){
		for(x = 0; x < 64/8; x++){
			if(x < 16/8 && y < 16){
				p0 = c->clr[x+y*2];
				p1 = c->set[x+y*2];

				p = 0x00;
				if(p1 & 0x10)
					p |= 0x03;
				else if(p0 & 0x10)
					p |= 0x02;
				if(p1 & 0x20)
					p |= 0x0C;
				else if(p0 & 0x20)
					p |= 0x08;
				if(p1 & 0x40)
					p |= 0x30;
				else if(p0 & 0x40)
					p |= 0x20;
				if(p1 & 0x80)
					p |= 0xC0;
				else if(p0 & 0x80)
					p |= 0x80;
				tvp3020xo(0x0A, p);	/* Cursor RAM Data */

				p = 0x00;
				if(p1 & 0x01)
					p |= 0x03;
				else if(p0 & 0x01)
					p |= 0x02;
				if(p1 & 0x02)
					p |= 0x0C;
				else if(p0 & 0x02)
					p |= 0x08;
				if(p1 & 0x04)
					p |= 0x30;
				else if(p0 & 0x04)
					p |= 0x20;
				if(p1 & 0x08)
					p |= 0xC0;
				else if(p0 & 0x08)
					p |= 0x80;
				tvp3020xo(0x0A, p);	/* Cursor RAM Data */
			}
			else{
				tvp3020xo(0x0A, 0x00);	/* Cursor RAM Data */
				tvp3020xo(0x0A, 0x00);
			}
		}
	}

	/*
	 * Initialise the cursor hot-point
	 * and enable the cursor.
	 */
	tvp3020xo(0x04, -c->offset.x);			/* Sprite Origin X */
	tvp3020xo(0x05, -c->offset.y);			/* Sprite Origin Y */

	tvp3020xo(0x06, 0x40|0x10);			/* Cursor Control Register */

	unlock(&pallettelock);
}

static void
enable(void)
{
	uchar r;

	lock(&pallettelock);

	/*
	 * Make sure cursor is off by initialising the cursor
	 * control to defaults + X-Windows cursor mode.
	 */
	tvp3020xo(0x06, 0x10);				/* Cursor Control Register */

	/*
	 * Overscan colour,
	 * cursor colour 1 (white),
	 * cursor colour 2 (black).
	 */
	tvp3020xo(0x20, 0xFF); tvp3020xo(0x21, 0xFF); tvp3020xo(0x22, 0xFF);
	tvp3020xo(0x23, 0xFF); tvp3020xo(0x24, 0xFF); tvp3020xo(0x25, 0xFF);
	tvp3020xo(0x26, 0x00); tvp3020xo(0x27, 0x00); tvp3020xo(0x28, 0x00);

	unlock(&pallettelock);

	/*
	 * Finally, enable
	 *	the hardware cursor external operation mode;
	 *	cursor control enable for Bt485 DAC (!).
	 */
	r = vgaxi(Crtx, 0x55)|0x20;
	vgaxo(Crtx, 0x55, r);

	r = vgaxi(Crtx, 0x45)|0x20;
	vgaxo(Crtx, 0x45, r);
}

static int
move(Point p)
{
	if(canlock(&pallettelock) == 0)
		return 1;

	tvp3020xo(0x00, p.x & 0xFF);			/* Cursor Position X LSB */
	tvp3020xo(0x01, (p.x>>8) & 0x0F);		/* Cursor Position X MSB */
	tvp3020xo(0x02, p.y & 0xFF);			/* Cursor Position Y LSB */
	tvp3020xo(0x03, (p.y>>8) & 0x0F);		/* Cursor Position Y MSB */

	unlock(&pallettelock);
	return 0;
}

static void
disable(void)
{
	uchar r;

	/*
	 * Disable 
	 *	cursor;
	 *	cursor control enable for Bt485 DAC (!);
	 *	the hardware cursor external operation mode.
	 */
	lock(&pallettelock);
	tvp3020xo(0x06, 0x10);				/* Cursor Control Register */
	unlock(&pallettelock);

	r = vgaxi(Crtx, 0x45) & ~0x20;
	vgaxo(Crtx, 0x45, r);

	r = vgaxi(Crtx, 0x55) & ~0x20;
	vgaxo(Crtx, 0x55, r);
}

Hwgc tvp3020hwgc = {
	"tvp3020hwgc",
	enable,
	load,
	move,
	disable,
};

M port/alarm.c => port/alarm.c +0 -1
@@ 3,7 3,6 @@
#include	"mem.h"
#include	"dat.h"
#include	"fns.h"
#include	"io.h"

Alarms	alarms;
Rendez	alarmr;

M port/auth.c => port/auth.c +0 -1
@@ 3,7 3,6 @@
#include	"mem.h"
#include	"dat.h"
#include	"fns.h"
#include	"io.h"
#include	"../port/error.h"

typedef struct Crypt	Crypt;

M port/devcons.c => port/devcons.c +0 -1
@@ 3,7 3,6 @@
#include	"mem.h"
#include	"dat.h"
#include	"fns.h"
#include	"io.h"
#include	"../port/error.h"

#include	"devtab.h"

M port/devlance.c => port/devlance.c +0 -1
@@ 3,7 3,6 @@
#include	"mem.h"
#include	"dat.h"
#include	"fns.h"
#include	"io.h"
#include	"../port/error.h"
#include	"../port/netif.h"


M port/devmouse.c => port/devmouse.c +1 -1
@@ 321,7 321,7 @@ mouseclock(void)
	if(mouse.redraw && canlock(&cursor)){
		mouse.redraw = 0;
		cursoroff(0);
		cursoron(0);
		mouse.redraw = cursoron(0);
		unlock(&cursor);
	}
}

M port/netif.c => port/netif.c +0 -1
@@ 3,7 3,6 @@
#include	"mem.h"
#include	"dat.h"
#include	"fns.h"
#include	"io.h"
#include	"../port/error.h"
#include	"../port/netif.h"