plan 9 kernel history: overview | file list | diff list

2002/0409/pc/vganvidia.c (diff list | history)

pc/vganvidia.c on 2001/0404
2001/0404    
#include "u.h" 
#include "../port/lib.h" 
#include "mem.h" 
#include "dat.h" 
#include "fns.h" 
#include "io.h" 
#include "../port/error.h" 
 
#define	Image	IMAGE 
#include <draw.h> 
#include <memdraw.h> 
#include <cursor.h> 
#include "screen.h" 
 
enum { 
	Pramin = 0x00710000, 
2001/0824    
	Pramdac = 0x00680000, 
	Fifo = 0x00800000, 
	Pgraph = 0x00400000 
2001/0404    
}; 
 
enum { 
	hwCurPos = Pramdac + 0x0300, 
	hwCurImage = Pramin + (0x00010000 - 0x0800), 
}; 
 
static ushort nvidiadid[] = { 
	0x0020,		/* Riva TNT */ 
	0x0028,		/* Riva TNT2 */ 
	0x0029,		/* Riva TNT2 (Ultra)*/ 
	0x002C,		/* Riva TNT2 (Vanta) */ 
	0x002D,		/* Riva TNT2 M64 */ 
	0x00A0,		/* Riva TNT2 (Integrated) */ 
	0x0100,		/* GeForce 256 */ 
	0x0101,		/* GeForce DDR */ 
	0x0103,		/* Quadro */ 
	0x0110,		/* GeForce2 MX */ 
	0x0111,		/* GeForce2 MX DDR */ 
	0x0112,		/* GeForce 2 Go */ 
	0x0113,		/* Quadro 2 MXR */ 
	0x0150,		/* GeForce2 GTS */ 
	0x0151,		/* GeForce2 GTS (rev 1) */ 
	0x0152,		/* GeForce2 Ultra */ 
	0x0153,		/* Quadro 2 Pro */ 
2002/0409    
	0x0200,		/* GeForce3 */ 
2001/0404    
	0, 
}; 
 
static Pcidev* 
nvidiapci(void) 
{ 
	Pcidev *p; 
	ushort *did; 
 
	if((p = pcimatch(nil, 0x10DE, 0)) == nil) 
		return nil; 
	for(did = nvidiadid; *did; did++){ 
		if(*did == p->did) 
			return p; 
	} 
 
	return nil; 
} 
 
 
static ulong 
nvidialinear(VGAscr* scr, int* size, int* align) 
{ 
	Pcidev *p; 
	int oapsize, wasupamem; 
	ulong aperture, oaperture; 
 
	oaperture = scr->aperture; 
	oapsize = scr->apsize; 
	wasupamem = scr->isupamem; 
 
	aperture = 0; 
	if(p = nvidiapci()){ 
		aperture = p->mem[1].bar & ~0x0F; 
		*size = p->mem[1].size; 
	} 
 
	if(wasupamem) { 
		if(oaperture == aperture) 
			return oaperture; 
		upafree(oaperture, oapsize); 
	} 
	scr->isupamem = 0; 
 
	aperture = upamalloc(aperture, *size, *align); 
	if(aperture == 0){ 
		if(wasupamem && upamalloc(oaperture, oapsize, 0)){ 
			aperture = oaperture; 
			scr->isupamem = 1; 
		} 
		else 
			scr->isupamem = 0; 
	} 
	else 
		scr->isupamem = 1; 
 
	return aperture; 
} 
 
static void 
nvidiaenable(VGAscr* scr) 
{ 
	Pcidev *p; 
	ulong aperture; 
	int align, size; 
 
	/* 
	 * Only once, can't be disabled for now. 
	 * scr->io holds the physical address of 
	 * the MMIO registers. 
	 */ 
	if(scr->io) 
		return; 
	p = nvidiapci(); 
	if(p == nil) 
		return; 
 
	scr->io = upamalloc(p->mem[0].bar & ~0x0F, p->mem[0].size, 0); 
	if (scr->io == 0) 
		return; 
2001/0908    
	addvgaseg("nvidiammio", scr->io, p->mem[0].size); 
2001/0404    
 
	size = p->mem[1].size; 
	align = 0; 
	aperture = nvidialinear(scr, &size, &align); 
	if(aperture) { 
		scr->aperture = aperture; 
		scr->apsize = size; 
2001/0908    
		addvgaseg("nvidiascreen", aperture, size); 
2001/0404    
	} 
} 
 
static void 
nvidiacurdisable(VGAscr* scr) 
{ 
	if(scr->io == 0) 
		return; 
 
	vgaxo(Crtx, 0x31, vgaxi(Crtx, 0x31) & ~0x01); 
} 
 
static void 
nvidiacurload(VGAscr* scr, Cursor* curs) 
{ 
	ulong*	p; 
	int		i,j; 
	ushort	c,s; 
	ulong	tmp; 
 
	if(scr->io == 0) 
		return; 
 
	vgaxo(Crtx, 0x31, vgaxi(Crtx, 0x31) & ~0x01); 
 
	p = KADDR(scr->io + hwCurImage); 
 
	for (i=0; i<16; i++) { 
		c = (curs->clr[2 * i] << 8) | curs->clr[2 * i+1]; 
		s = (curs->set[2 * i] << 8) | curs->set[2 * i+1]; 
		tmp = 0; 
		for (j=0; j<16; j++) { 
			if(s&0x8000) 
				tmp |= 0x80000000; 
			else if(c&0x8000) 
				tmp |= 0xFFFF0000; 
			if (j&0x1) { 
				*p++ = tmp; 
				tmp = 0; 
			} else { 
				tmp>>=16; 
			} 
			c<<=1; 
			s<<=1; 
		} 
		for (j=0; j<8; j++) 
			*p++ = 0; 
	} 
	for (i=0; i<256; i++) 
		*p++ = 0; 
 
	scr->offset = curs->offset; 
	vgaxo(Crtx, 0x31, vgaxi(Crtx, 0x31) | 0x01); 
 
	return; 
} 
 
static int 
nvidiacurmove(VGAscr* scr, Point p) 
{ 
	ulong*	cursorpos; 
 
	if(scr->io == 0) 
		return 1; 
 
	cursorpos = KADDR(scr->io + hwCurPos); 
	*cursorpos = ((p.y+scr->offset.y)<<16)|((p.x+scr->offset.x) & 0xFFFF); 
 
	return 0; 
} 
 
static void 
nvidiacurenable(VGAscr* scr) 
{ 
	nvidiaenable(scr); 
	if(scr->io == 0) 
		return; 
 
	vgaxo(Crtx, 0x1F, 0x57); 
 
	nvidiacurload(scr, &arrow); 
	nvidiacurmove(scr, ZP); 
 
	vgaxo(Crtx, 0x31, vgaxi(Crtx, 0x31) | 0x01); 
} 
 
2001/0824    
enum { 
	RopFifo = 0x00000000,  
	ClipFifo = 0x00002000, 
	PattFifo = 0x00004000, 
	BltFifo = 0x00008000, 
	BitmapFifo = 0x0000A000, 
}; 
 
enum { 
	RopRop3 = RopFifo + 0x300, 
 
	ClipTopLeft = ClipFifo + 0x300, 
	ClipWidthHeight = ClipFifo + 0x304, 
 
	PattShape = PattFifo + 0x0308, 
	PattColor0 = PattFifo + 0x0310, 
	PattColor1 = PattFifo + 0x0314, 
	PattMonochrome0 = PattFifo + 0x0318, 
	PattMonochrome1 = PattFifo + 0x031C, 
 
	BltTopLeftSrc = BltFifo + 0x0300, 
	BltTopLeftDst = BltFifo + 0x0304, 
	BltWidthHeight = BltFifo + 0x0308, 
 
	BitmapColor1A = BitmapFifo + 0x03FC, 
	BitmapURect0TopLeft = BitmapFifo + 0x0400, 
	BitmapURect0WidthHeight = BitmapFifo + 0x0404, 
}; 
 
static void 
waitforidle(VGAscr *scr) 
{ 
	ulong*	pgraph; 
	int x; 
 
	pgraph = KADDR(scr->io + Pgraph); 
 
	x = 0; 
	while (pgraph[0x00000700/4] & 0x01 && x++ < 1000000) 
		; 
 
	if(x >= 1000000) 
2001/0901    
		iprint("idle stat %lud scrio %.8lux scr %p pc %luX\n", *pgraph, scr->io, scr, getcallerpc(&scr)); 
2001/0824    
} 
 
static void 
waitforfifo(VGAscr *scr, int fifo, int entries) 
{ 
	ushort* fifofree; 
	int x; 
 
	x = 0; 
	fifofree = KADDR(scr->io + Fifo + fifo + 0x10); 
 
	while (((*fifofree >> 2) < entries) && x++ < 1000000) 
		; 
 
	if(x >= 1000000) 
		iprint("fifo stat %d scrio %.8lux scr %p pc %luX\n", *fifofree, scr->io, scr, getcallerpc(&scr)); 
} 
 
static int 
nvidiahwfill(VGAscr *scr, Rectangle r, ulong sval) 
{ 
	ulong*	fifo; 
 
	fifo = KADDR(scr->io + Fifo); 
 
	waitforfifo(scr, BitmapFifo, 1); 
 
	fifo[BitmapColor1A/4] = sval; 
 
	waitforfifo(scr, BitmapFifo, 2); 
 
	fifo[BitmapURect0TopLeft/4] = (r.min.x << 16) | r.min.y; 
	fifo[BitmapURect0WidthHeight/4] = (Dx(r) << 16) | Dy(r); 
 
	waitforidle(scr); 
 
	return 1; 
} 
 
static int 
nvidiahwscroll(VGAscr *scr, Rectangle r, Rectangle sr) 
{ 
	ulong*	fifo; 
 
	fifo = KADDR(scr->io + Fifo); 
 
	waitforfifo(scr, BltFifo, 3); 
 
	fifo[BltTopLeftSrc/4] = (sr.min.y << 16) | sr.min.x; 
	fifo[BltTopLeftDst/4] = (r.min.y << 16) | r.min.x; 
	fifo[BltWidthHeight/4] = (Dy(r) << 16) | Dx(r); 
 
	waitforidle(scr); 
 
	return 1; 
} 
 
void 
nvidiablank(VGAscr*, int blank) 
{ 
	uchar seq1, crtc1A; 
 
	seq1 = vgaxi(Seqx, 1) & ~0x20; 
	crtc1A = vgaxi(Crtx, 0x1A) & ~0xC0; 
 
	if(blank) { 
		seq1 |= 0x20; 
2001/0901    
//		crtc1A |= 0xC0; 
		crtc1A |= 0x80; 
2001/0824    
	} 
 
	vgaxo(Seqx, 1, seq1); 
	vgaxo(Crtx, 0x1A, crtc1A); 
} 
 
static void 
nvidiadrawinit(VGAscr *scr) 
{ 
	ulong*	fifo; 
 
	fifo = KADDR(scr->io + Fifo); 
 
	waitforfifo(scr, ClipFifo, 2); 
 
	fifo[ClipTopLeft/4] = 0x0; 
	fifo[ClipWidthHeight/4] = 0x80008000; 
 
	waitforfifo(scr, PattFifo, 5); 
 
	fifo[PattShape/4] = 0; 
	fifo[PattColor0/4] = 0xffffffff; 
	fifo[PattColor1/4] = 0xffffffff; 
	fifo[PattMonochrome0/4] = 0xffffffff; 
	fifo[PattMonochrome1/4] = 0xffffffff; 
 
	waitforfifo(scr, RopFifo, 1); 
 
	fifo[RopRop3/4] = 0xCC; 
 
	waitforidle(scr); 
 
	scr->blank = nvidiablank; 
2001/1015    
	hwblank = 1; 
2001/0824    
	scr->fill = nvidiahwfill; 
	scr->scroll = nvidiahwscroll; 
} 
 
2001/0404    
VGAdev vganvidiadev = { 
	"nvidia", 
 
	nvidiaenable, 
	nil, 
	nil, 
	nvidialinear, 
2001/0824    
	nvidiadrawinit, 
2001/0404    
}; 
 
VGAcur vganvidiacur = { 
	"nvidiahwgc", 
 
	nvidiacurenable, 
	nvidiacurdisable, 
	nvidiacurload, 
	nvidiacurmove, 
}; 


source code copyright © 1990-2005 Lucent Technologies; see license
Plan 9 distribution
comments to russ cox (rsc@swtch.com)