~kris/9p

9hist

5062c11bb3bca04a2a4982e45130ca93685822f3 — David du Colombier 31 years ago 6c0be79
Plan 9 from Bell Labs 1994-12-01
4 files changed, 315 insertions(+), 55 deletions(-)

M carrera/trap.c
M pc/clock.c
M pc/devvga.c
A pc/vgaet4000.c
M carrera/trap.c => carrera/trap.c +10 -9
@@ 320,7 320,7 @@ intr(Ureg *ur)
{
	static uchar devint;
	ulong cause = ur->cause;
	ulong isr, vec;
	ulong isr;

	m->intr++;
	cause &= INTR7|INTR6|INTR5|INTR4|INTR3|INTR2|INTR1|INTR0;


@@ 351,21 351,22 @@ intr(Ureg *ur)
		cause &= ~INTR3;
	}

	if(cause & INTR5)
		panic("EISA NMI\n");

	if(cause & INTR2) {
		isr = IO(ulong, R4030Isr);
		if(isr) {
			iprint("R4030 Interrupt\n");
			iprint(" ISR #%lux\n", IO(ulong, R4030Isr));
			iprint(" ET  #%lux\n", IO(ulong, R4030Et));
			iprint(" RFA #%lux\n", IO(ulong, R4030Rfa));
			iprint(" MFA #%lux\n", IO(ulong, R4030Mfa));
			print("R4030 Interrupt PC %lux R31 %lux\n", ur->pc, ur->r31);
			print(" ISR #%lux\n", IO(ulong, R4030Isr));
			print(" ET  #%lux\n", IO(ulong, R4030Et));
			print(" RFA #%lux\n", IO(ulong, R4030Rfa));
			print(" MFA #%lux\n", IO(ulong, R4030Mfa));
		}
		cause &= ~INTR2;
	}

	if(cause & INTR5)
		panic("EISA NMI\n");


	if(cause & INTR4) {
		devint = IO(uchar, I386ack);
		switch(devint) {

M pc/clock.c => pc/clock.c +33 -31
@@ 142,7 142,7 @@ void
clockinit(void)
{
	int x, y;	/* change in counter */
	int family, model, loops;
	int family, model, loops, incr;
	X86type *t;

	/*


@@ 170,35 170,37 @@ clockinit(void)
	outb(T0cntr, (Freq/HZ));	/* low byte */
	outb(T0cntr, (Freq/HZ)>>8);	/* high byte */

	/* use biggest loop that works */
	if(t->family == 3)
		loops = 10000;
	else
		loops = 30000;
	/* find biggest loop that doesn't wrap */
	incr = 16000000/(t->aalcycles*HZ*2);
	for(loops = incr; loops < 64*1024; loops += incr) {
	
		/*
		 *  measure time for the loop
		 *
		 *			MOVL	loops,CX
		 *	aaml1:	 	AAM
		 *			LOOP	aaml1
		 *
		 *  the time for the loop should be independent of external
		 *  cache and memory system since it fits in the execution
		 *  prefetch buffer.
		 *
		 */
		outb(Tmode, Latch0);
		x = inb(T0cntr);
		x |= inb(T0cntr)<<8;
		aamloop(loops);
		outb(Tmode, Latch0);
		y = inb(T0cntr);
		y |= inb(T0cntr)<<8;
		x -= y;
	
		if(x < 0)
			x += Freq/HZ;

	/*
	 *  measure time for the loop
	 *
	 *			MOVL	loops,CX
	 *	aaml1:	 	AAM
	 *			LOOP	aaml1
	 *
	 *  the time for the loop should be independent of external
	 *  cache and memory system since it fits in the execution
	 *  prefetch buffer.
	 *
	 */
	outb(Tmode, Latch0);
	x = inb(T0cntr);
	x |= inb(T0cntr)<<8;
	aamloop(loops);
	outb(Tmode, Latch0);
	y = inb(T0cntr);
	y |= inb(T0cntr)<<8;
	x -= y;

	if(x < 0)
		x += 2^16;
		if(x > Freq/(3*HZ))
			break;
	}

	/*
	 *  counter  goes at twice the frequency, once per transition,


@@ 213,7 215,7 @@ clockinit(void)
	loopconst = (cpufreq/1000)/t->aalcycles;	/* AAM+LOOP's for 1 ms */

	/*
	 *  add in possible .1% error and convert to MHz
	 *  add in possible .2% error and convert to MHz
	 */
	cpumhz = (cpufreq + cpufreq/1000)/1000000;
	cpumhz = (cpufreq + cpufreq/500)/1000000;
}

M pc/devvga.c => pc/devvga.c +3 -15
@@ 60,7 60,7 @@ struct Vgacard

static void	nopage(int);
static void	cirruspage(int);
static void	et4000page(int);
extern void	et4000page(int);
extern void	s3page(int);

Vgacard vgachips[] =


@@ 75,11 75,13 @@ Vgacard vgachips[] =
Vgacard	*vgacard = &vgachips[0];	/* current vga card */

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

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


@@ 1072,20 1074,6 @@ nopage(int page)
}

static void
et4000page(int page)
{
	uchar p;

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

	p = (page & 0x30);
	p |= p>>4;
	outb(0x3CB, p);
}

static void
cirruspage(int page)
{
	vgaxo(Grx, 0x09, page<<4);

A pc/vgaet4000.c => pc/vgaet4000.c +269 -0
@@ 0,0 1,269 @@
#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"

extern Bitmap gscreen;
extern Cursor curcursor;

static Lock et4000pagelock;
static ulong storage;
static Point hotpoint;

static void
setet4000page(int page)
{
	uchar p;

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

	p = (page & 0x30);
	p |= p>>4;
	outb(0x3CB, p);
}

static void
disable(void)
{
	uchar imaF7;

	outb(0x217A, 0xF7);
	imaF7 = inb(0x217B) & ~0x80;
	outb(0x217B, imaF7);
}

static void
enable(void)
{
	uchar imaF7;

	disable();

	/*
	 * Configure CRTCB for Sprite, 64x64,
	 * CRTC pixel overlay.
	 */
	outb(0x217A, 0xEF);
	outb(0x217B, 0x02);

	/*
	 * Cursor goes in the top left corner
	 * of the Sprite area, so the horizontal and
	 * vertical presets are 0.
	 */
	outb(0x217A, 0xE2);
	outb(0x217B, 0x00);
	outb(0x217A, 0xE3);
	outb(0x217B, 0x00);

	outb(0x217A, 0xE6);
	outb(0x217B, 0x00);
	outb(0x217A, 0xE7);
	outb(0x217B, 0x00);

	/*
	 * Find a place for the cursor data in display memory.
	 * Must be on a "doubleword" boundary, but put it on a
	 * 1024-byte boundary so that there's no danger of it
	 * crossing a page.
	 */
	storage = (gscreen.width*BY2WD*gscreen.r.max.y+1023)/1024;
	storage *= 1024/4;
	outb(0x217A, 0xE8);
	outb(0x217B, storage & 0xFF);
	outb(0x217A, 0xE9);
	outb(0x217B, (storage>>8) & 0xFF);
	outb(0x217A, 0xEA);
	outb(0x217B, (storage>>16) & 0x0F);
	storage *= 4;

	/*
	 * Row offset in "quadwords". Must be 2 for Sprite.
	 * Bag the pixel-panning.
	 * Colour depth, must be 2 for Sprite.
	 */
	outb(0x217A, 0xEB);
	outb(0x217B, 0x02);
	outb(0x217A, 0xEC);
	outb(0x217B, 0x00);

	outb(0x217A, 0xED);
	outb(0x217B, 0x00);

	outb(0x217A, 0xEE);
	if(gscreen.ldepth == 3)
		outb(0x217B, 0x01);
	else
		outb(0x217B, 0x00);

	/*
	 * Enable the CRTCB/Sprite.
	 */
	outb(0x217A, 0xF7);
	imaF7 = inb(0x217B);
	outb(0x217B, 0x80|imaF7);
}

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

	/*
	 * Lock the display memory so we can update the
	 * cursor bitmap if necessary.
	 */
	lock(&et4000pagelock);
	if(memcmp(c, &curcursor, sizeof(Cursor)) == 0){
		outb(0x217A, 0xF7);
		p0 = inb(0x217B);
		outb(0x217B, 0x80|p0);
		unlock(&et4000pagelock);
		return;
	}
	memmove(&curcursor, c, sizeof(Cursor));

	/*
	 * Disable the cursor.
	 * Set the display page (do we need to restore
	 * the current contents when done?) and the
	 * pointer to the two planes. What if this crosses
	 * into a new page?
	 */
	disable();

	setet4000page(storage>>16);
	mem = ((uchar*)gscreen.base) + (storage & 0xFFFF);

	/*
	 * 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 mode gives the following truth table:
	 *	p1 p0	colour
	 *	 0  0	Sprite Colour 0 (defined as 0x00)
	 *	 0  1	Sprite Colour 1 (defined as 0xFF)
	 *	 1  0	Transparent (allow CRTC pixel pass through)
	 *	 1  1	Invert (allow CRTC pixel invert through)
	 * 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 = 0x0000;
				for(i = 0; i < 8; i++){
					if(p0 & (1<<(7-i)))
						;
					else if(p1 & (1<<(7-i)))
						p |= 0x01<<(2*i);
					else
						p |= 0x02<<(2*i);
				}
				*mem++ = p & 0xFF;
				*mem++ = (p>>8) & 0xFF;
			}
			else {
				*mem++ = 0xAA;
				*mem++ = 0xAA;
			}
		}
	}

	/*
	 * Set the cursor hotpoint and enable the cursor.
	 */
	hotpoint = c->offset;
	outb(0x217A, 0xF7);
	p = inb(0x217B)|0x80;
	outb(0x217B, p);

	unlock(&et4000pagelock);
}

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

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

	/*
	 * Mustn't position the cursor offscreen even partially,
	 * or it disappears. Therefore, if x or y is -ve, adjust the
	 * cursor presets instead.
	 */
	if((x = p.x+hotpoint.x) < 0){
		xo = -x;
		x = 0;
	}
	else
		xo = 0;
	if((y = p.y+hotpoint.y) < 0){
		yo = -y;
		y = 0;
	}
	else
		yo = 0;

	/*
	 * The cursor image is jerky if we don't do this.
	 * The cursor information is probably fetched from
	 * display memory during the horizontal blank active
	 * time and it doesn't like it if the coordinates
	 * are changed underneath.
	 */
	while((vgai(Status1) & 0x08) == 0)
		;

	outb(0x217A, 0xE2);
	outb(0x217B, xo);

	outb(0x217A, 0xE6);
	outb(0x217B, yo);

	outb(0x217A, 0xE1);
	outb(0x217B, (x>>8) & 0xFF);
	outb(0x217A, 0xE0);
	outb(0x217B, x & 0xFF);
	outb(0x217A, 0xE5);
	outb(0x217B, (y>>8) & 0xFF);
	outb(0x217A, 0xE4);
	outb(0x217B, y & 0xFF);

	unlock(&et4000pagelock);
	return 0;
}

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

void
et4000page(int page)
{
	if(hwgc == &et4000hwgc){
		lock(&et4000pagelock);
		setet4000page(page);
		unlock(&et4000pagelock);
	}
	else
		setet4000page(page);
}