~kris/9p

9hist

fa4ed298cf5a88e21d1aedeed74f2ea2c6e920b5 — David du Colombier 32 years ago a9d668a
Plan 9 from Bell Labs 1994-08-03
3 files changed, 201 insertions(+), 29 deletions(-)

M pc/devvga.c
M pc/vga.h
A pc/vgas3.c
M pc/devvga.c => pc/devvga.c +7 -29
@@ 58,7 58,8 @@ struct Vgacard
};

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

Vgacard vgachips[] =
{


@@ 75,16 76,18 @@ Vgacard vgachips[] =

Vgacard	*vgacard = &vgachips[0];	/* current vga card */

extern Hwgc tvp3020hwgc;
extern Hwgc bt485hwgc;
extern Hwgc s3hwgc;
extern Hwgc tvp3020hwgc;

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

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

/*


@@ 1109,31 1112,6 @@ cirruspage(int page)
{
	vgaxo(Grx, 0x09, page<<4);
}
static void
s3page(int page)
{
	uchar crt51;

	/*
	 * I don't understand why these are different.
	 */
	if(gscreen.ldepth == 3){
		/*
		 * The S3 registers need to be unlocked for this.
		 * Let's hope they are already:
		 *	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>.
		 */
		vgaxo(Crtx, 0x35, page & 0x0F);
		crt51 = vgaxi(Crtx, 0x51) & 0xF3;
		vgaxo(Crtx, 0x51, crt51|((page & 0x30)>>2));
	}
	else
		vgaxo(Crtx, 0x35, (page<<2) & 0x0C);
}

/*
 *  character mode console

M pc/vga.h => pc/vga.h +2 -0
@@ 46,4 46,6 @@ typedef struct Hwgc {
	void	(*disable)(void);
} Hwgc;

extern Hwgc *hwgc;

extern Lock palettelock;

A pc/vgas3.c => pc/vgas3.c +192 -0
@@ 0,0 1,192 @@
#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
 * generic S3 chipset.
 * Assume we're in enhanced mode.
 */
static Lock s3pagelock;
static ulong storage;

extern Bitmap gscreen;

static void
sets3page(int page)
{
	uchar crt51;

	/*
	 * I don't understand why these are different.
	 */
	if(gscreen.ldepth == 3){
		/*
		 * The S3 registers need to be unlocked for this.
		 * Let's hope they are already:
		 *	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>.
		 */
		vgaxo(Crtx, 0x35, page & 0x0F);
		crt51 = vgaxi(Crtx, 0x51) & 0xF3;
		vgaxo(Crtx, 0x51, crt51|((page & 0x30)>>2));
	}
	else
		vgaxo(Crtx, 0x35, (page<<2) & 0x0C);
}

static void
vsyncactive(void)
{
	/*
	 * Hardware cursor information is fetched from display memory
	 * during the horizontal blank active time. The 80x chips may hang
	 * if the cursor is turned on or off during this period.
	 */
	while((vgai(Status1) & 0x08) == 0)
		;
}

static void
disable(void)
{
	uchar crt45;

	/*
	 * Turn cursor off.
	 */
	crt45 = vgaxi(Crtx, 0x45) & 0xFE;
	vsyncactive();
	vgaxo(Crtx, 0x45, crt45);
}

static void
enable(void)
{
	int i;

	disable();

	/*
	 * Cursor colours. Set both the CR0[EF] and the colour
	 * stack in case we are using a 16-bit RAMDAC.
	 */
	vgaxo(Crtx, 0x0E, 0x00);
	vgaxo(Crtx, 0x0F, 0xFF);
	vgaxi(Crtx, 0x45);
	for(i = 0; i < 4; i++)
		vgaxo(Crtx, 0x4A, 0x00);
	vgaxi(Crtx, 0x45);
	for(i = 0; i < 4; i++)
		vgaxo(Crtx, 0x4B, 0xFF);

	/*
	 * Find a place for the cursor data in display memory.
	 * Must be on a 1024-byte boundary.
	 */
	storage = (gscreen.width*BY2WD*gscreen.r.max.y+1023)/1024;
	vgaxo(Crtx, 0x4C, (storage>>8) & 0x0F);
	vgaxo(Crtx, 0x4D, storage & 0xFF);
	storage *= 1024;

	/*
	 * Enable the cursor in X11 mode.
	 */
	vgaxo(Crtx, 0x55, vgaxi(Crtx, 0x55)|0x10);
	vsyncactive();
	vgaxo(Crtx, 0x45, 0x01);
}

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

	/*
	 * Disable the cursor and lock the display
	 * memory so we can update the cursor bitmap.
	 * Set the display page (do we need to restore
	 * the current contents when done?) and the
	 * pointers to the two planes.
	 */
	disable();
	lock(&s3pagelock);

	sets3page(storage>>16);
	and = ((uchar*)gscreen.base) + (storage & 0xFFFF);
	xor = and + 512;

	/*
	 * The cursor is set in X11 mode which gives the following
	 * truth table:
	 *	and xor	colour
	 *	 0   0	underlying pixel colour
	 *	 0   1	underlying pixel colour
	 *	 1   0	background colour
	 *	 1   1	foreground colour
	 * Put the cursor into the top-left of the 64x64 array.
	 */
	for(y = 0; y < 64; y++){
		for(x = 0; x < 8; x++){
			if(y < 16 && x < 2){
				and[8*y + x] = c->clr[2*y + x]^c->set[2*y + x];
				xor[8*y + x] = c->set[2*y + x];
			}
			else {
				and[8*y + x] = 0;
				xor[8*y + x] = 0;
			}
		}
	}
	unlock(&s3pagelock);

	/*
	 * Set the cursor offset and enable the cursor.
	 */
	vgaxo(Crtx, 0x4E, -c->offset.x);
	vgaxo(Crtx, 0x4F, -c->offset.y);
	vsyncactive();
	vgaxo(Crtx, 0x45, 0x01);
}

static int
move(Point p)
{
	vgaxo(Crtx, 0x46, (p.x>>8) & 0x07);
	vgaxo(Crtx, 0x47, p.x & 0xFF);
	vgaxo(Crtx, 0x49, p.y & 0xFF);
	vgaxo(Crtx, 0x48, (p.y>>8) & 0x07);

	return 0;
}

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

void
s3page(int page)
{
	if(hwgc == &s3hwgc){
		lock(&s3pagelock);
		sets3page(page);
		unlock(&s3pagelock);
	}
	else
		sets3page(page);
}