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

2000/0820/pc/vgas3.c (diff list | history)

1994/0803/sys/src/9/pc/vgas3.c:16,211994/0804/sys/src/9/pc/vgas3.c:16,22 (short | long)
1994/0803    
 */ 
static Lock s3pagelock; 
static ulong storage; 
1994/0804    
static Point hotpoint; 
1994/0803    
 
extern Bitmap gscreen; 
 
1994/0803/sys/src/9/pc/vgas3.c:80,941994/0804/sys/src/9/pc/vgas3.c:81,96
1994/0803    
	/* 
	 * Cursor colours. Set both the CR0[EF] and the colour 
	 * stack in case we are using a 16-bit RAMDAC. 
1994/0804    
	 * Why are these colours reversed? 
1994/0803    
	 */ 
	vgaxo(Crtx, 0x0E, 0x00); 
	vgaxo(Crtx, 0x0F, 0xFF); 
1994/0804    
	vgaxo(Crtx, 0x0E, 0xFF); 
	vgaxo(Crtx, 0x0F, 0x00); 
1994/0803    
	vgaxi(Crtx, 0x45); 
	for(i = 0; i < 4; i++) 
		vgaxo(Crtx, 0x4A, 0x00); 
1994/0804    
		vgaxo(Crtx, 0x4A, 0xFF); 
1994/0803    
	vgaxi(Crtx, 0x45); 
	for(i = 0; i < 4; i++) 
		vgaxo(Crtx, 0x4B, 0xFF); 
1994/0804    
		vgaxo(Crtx, 0x4B, 0x00); 
1994/0803    
 
	/* 
	 * Find a place for the cursor data in display memory. 
1994/0803/sys/src/9/pc/vgas3.c:110,1161994/0804/sys/src/9/pc/vgas3.c:112,118
1994/0803    
static void 
load(Cursor *c) 
{ 
	uchar *and, *xor; 
1994/0804    
	uchar *p; 
1994/0803    
	int x, y; 
 
	/* 
1994/0803/sys/src/9/pc/vgas3.c:118,1311994/0804/sys/src/9/pc/vgas3.c:120,133
1994/0803    
	 * 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. 
1994/0804    
	 * pointer to the two planes. What if this crosses 
	 * into a new page? 
1994/0803    
	 */ 
	disable(); 
	lock(&s3pagelock); 
 
	sets3page(storage>>16); 
	and = ((uchar*)gscreen.base) + (storage & 0xFFFF); 
	xor = and + 512; 
1994/0804    
	p = ((uchar*)gscreen.base) + (storage & 0xFFFF); 
1994/0803    
 
	/* 
	 * The cursor is set in X11 mode which gives the following 
1994/0803/sys/src/9/pc/vgas3.c:138,1511994/0804/sys/src/9/pc/vgas3.c:140,157
1994/0803    
	 * 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]; 
1994/0804    
		for(x = 0; x < 64/8; x += 2){ 
			if(x < 16/8 && y < 16){ 
				*p++ = c->clr[2*y + x]|c->set[2*y + x]; 
				*p++ = c->clr[2*y + x+1]|c->set[2*y + x+1]; 
				*p++ = c->set[2*y + x]; 
				*p++ = c->set[2*y + x+1]; 
1994/0803    
			} 
			else { 
				and[8*y + x] = 0; 
				xor[8*y + x] = 0; 
1994/0804    
				*p++ = 0x00; 
				*p++ = 0x00; 
				*p++ = 0x00; 
				*p++ = 0x00; 
1994/0803    
			} 
		} 
	} 
1994/0803/sys/src/9/pc/vgas3.c:152,1611994/0804/sys/src/9/pc/vgas3.c:158,166
1994/0803    
	unlock(&s3pagelock); 
 
	/* 
	 * Set the cursor offset and enable the cursor. 
1994/0804    
	 * Set the cursor hotpoint and enable the cursor. 
1994/0803    
	 */ 
	vgaxo(Crtx, 0x4E, -c->offset.x); 
	vgaxo(Crtx, 0x4F, -c->offset.y); 
1994/0804    
	hotpoint = c->offset; 
1994/0803    
	vsyncactive(); 
	vgaxo(Crtx, 0x45, 0x01); 
} 
1994/0803/sys/src/9/pc/vgas3.c:163,1721994/0804/sys/src/9/pc/vgas3.c:168,200
1994/0803    
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); 
1994/0804    
	int x, xo, y, yo; 
 
	/* 
	 * Mustn't position the cursor offscreen even partially, 
	 * or it disappears. Therefore, if x or y is -ve, adjust the 
	 * cursor offset instead. 
	 */ 
	if((x = p.x+hotpoint.x) < 0){ 
		xo = -x; 
		xo = ((xo+1)/2)*2; 
		x = 0; 
	} 
	else 
		xo = 0; 
	if((y = p.y+hotpoint.y) < 0){ 
		yo = -y; 
		y = 0; 
	} 
	else 
		yo = 0; 
 
	vgaxo(Crtx, 0x46, (x>>8) & 0x07); 
	vgaxo(Crtx, 0x47, x & 0xFF); 
	vgaxo(Crtx, 0x49, y & 0xFF); 
	vgaxo(Crtx, 0x4E, xo); 
	vgaxo(Crtx, 0x4F, yo); 
	vgaxo(Crtx, 0x48, (y>>8) & 0x07); 
1994/0803    
 
	return 0; 
} 
1994/0804/sys/src/9/pc/vgas3.c:17,221994/0809/sys/src/9/pc/vgas3.c:17,23 (short | long)
1994/0803    
static Lock s3pagelock; 
static ulong storage; 
1994/0804    
static Point hotpoint; 
1994/0809    
static Cursor loaded; 
1994/0803    
 
extern Bitmap gscreen; 
 
1994/0804/sys/src/9/pc/vgas3.c:116,1231994/0809/sys/src/9/pc/vgas3.c:117,138
1994/0803    
	int x, y; 
 
	/* 
	 * Disable the cursor and lock the display 
	 * memory so we can update the cursor bitmap. 
1994/0809    
	 * Lock the display memory so we can update the 
	 * cursor bitmap if necessary. 
	 * If it's the same as the last cursor we loaded, 
	 * just make sure it's enabled. 
	 */ 
	lock(&s3pagelock); 
	if(memcmp(c, &loaded, sizeof(Cursor)) == 0){ 
		vsyncactive(); 
		vgaxo(Crtx, 0x45, 0x01); 
		unlock(&s3pagelock); 
		return; 
	} 
	memmove(&loaded, c, sizeof(Cursor)); 
 
	/* 
	 * Disable the cursor. 
1994/0803    
	 * Set the display page (do we need to restore 
	 * the current contents when done?) and the 
1994/0804    
	 * pointer to the two planes. What if this crosses 
1994/0804/sys/src/9/pc/vgas3.c:124,1301994/0809/sys/src/9/pc/vgas3.c:139,144
1994/0804    
	 * into a new page? 
1994/0803    
	 */ 
	disable(); 
	lock(&s3pagelock); 
 
	sets3page(storage>>16); 
1994/0804    
	p = ((uchar*)gscreen.base) + (storage & 0xFFFF); 
1994/0804/sys/src/9/pc/vgas3.c:138,1431994/0809/sys/src/9/pc/vgas3.c:152,160
1994/0803    
	 *	 1   0	background colour 
	 *	 1   1	foreground colour 
	 * Put the cursor into the top-left of the 64x64 array. 
1994/0809    
	 * 
	 * The cursor pattern in memory is interleaved words of 
	 * AND and XOR patterns. 
1994/0803    
	 */ 
	for(y = 0; y < 64; y++){ 
1994/0804    
		for(x = 0; x < 64/8; x += 2){ 
1994/0804/sys/src/9/pc/vgas3.c:155,1611994/0809/sys/src/9/pc/vgas3.c:172,177
1994/0803    
			} 
		} 
	} 
	unlock(&s3pagelock); 
 
	/* 
1994/0804    
	 * Set the cursor hotpoint and enable the cursor. 
1994/0804/sys/src/9/pc/vgas3.c:163,1681994/0809/sys/src/9/pc/vgas3.c:179,186
1994/0804    
	hotpoint = c->offset; 
1994/0803    
	vsyncactive(); 
	vgaxo(Crtx, 0x45, 0x01); 
1994/0809    
 
	unlock(&s3pagelock); 
1994/0803    
} 
 
static int 
1994/0804/sys/src/9/pc/vgas3.c:170,1791994/0809/sys/src/9/pc/vgas3.c:188,203
1994/0803    
{ 
1994/0804    
	int x, xo, y, yo; 
 
1994/0809    
	if(canlock(&s3pagelock) == 0) 
		return -1; 
 
1994/0804    
	/* 
	 * Mustn't position the cursor offscreen even partially, 
	 * or it disappears. Therefore, if x or y is -ve, adjust the 
	 * cursor offset instead. 
1994/0809    
	 * There seems to be a bug in that if the offset is 1, the 
	 * cursor doesn't disappear off the left edge properly, so 
	 * round it up to be even. 
1994/0804    
	 */ 
	if((x = p.x+hotpoint.x) < 0){ 
		xo = -x; 
1994/0804/sys/src/9/pc/vgas3.c:196,2011994/0809/sys/src/9/pc/vgas3.c:220,226
1994/0804    
	vgaxo(Crtx, 0x4F, yo); 
	vgaxo(Crtx, 0x48, (y>>8) & 0x07); 
1994/0803    
 
1994/0809    
	unlock(&s3pagelock); 
1994/0803    
	return 0; 
} 
 
1994/0809/sys/src/9/pc/vgas3.c:17,251994/0810/sys/src/9/pc/vgas3.c:17,25 (short | long)
1994/0803    
static Lock s3pagelock; 
static ulong storage; 
1994/0804    
static Point hotpoint; 
1994/0809    
static Cursor loaded; 
1994/0803    
 
extern Bitmap gscreen; 
1994/0810    
extern Cursor curcursor; 
1994/0803    
 
static void 
sets3page(int page) 
1994/0809/sys/src/9/pc/vgas3.c:123,1351994/0810/sys/src/9/pc/vgas3.c:123,135
1994/0809    
	 * just make sure it's enabled. 
	 */ 
	lock(&s3pagelock); 
	if(memcmp(c, &loaded, sizeof(Cursor)) == 0){ 
1994/0810    
	if(memcmp(c, &curcursor, sizeof(Cursor)) == 0){ 
1994/0809    
		vsyncactive(); 
		vgaxo(Crtx, 0x45, 0x01); 
		unlock(&s3pagelock); 
		return; 
	} 
	memmove(&loaded, c, sizeof(Cursor)); 
1994/0810    
	memmove(&curcursor, c, sizeof(Cursor)); 
1994/0809    
 
	/* 
	 * Disable the cursor. 
1994/0809/sys/src/9/pc/vgas3.c:189,1951994/0810/sys/src/9/pc/vgas3.c:189,195
1994/0804    
	int x, xo, y, yo; 
 
1994/0809    
	if(canlock(&s3pagelock) == 0) 
		return -1; 
1994/0810    
		return 1; 
1994/0809    
 
1994/0804    
	/* 
	 * Mustn't position the cursor offscreen even partially, 
1994/0810/sys/src/9/pc/vgas3.c:26,341995/0126/sys/src/9/pc/vgas3.c:26,31 (short | long)
1994/0803    
{ 
	uchar crt51; 
 
	/* 
	 * I don't understand why these are different. 
	 */ 
	if(gscreen.ldepth == 3){ 
		/* 
		 * The S3 registers need to be unlocked for this. 
1994/0810/sys/src/9/pc/vgas3.c:84,971995/0126/sys/src/9/pc/vgas3.c:81,94
1994/0803    
	 * stack in case we are using a 16-bit RAMDAC. 
1994/0804    
	 * Why are these colours reversed? 
1994/0803    
	 */ 
1994/0804    
	vgaxo(Crtx, 0x0E, 0xFF); 
	vgaxo(Crtx, 0x0F, 0x00); 
1995/0126    
	vgaxo(Crtx, 0x0E, Pwhite); 
	vgaxo(Crtx, 0x0F, Pblack); 
1994/0803    
	vgaxi(Crtx, 0x45); 
	for(i = 0; i < 4; i++) 
1994/0804    
		vgaxo(Crtx, 0x4A, 0xFF); 
1995/0126    
		vgaxo(Crtx, 0x4A, Pwhite); 
1994/0803    
	vgaxi(Crtx, 0x45); 
	for(i = 0; i < 4; i++) 
1994/0804    
		vgaxo(Crtx, 0x4B, 0x00); 
1995/0126    
		vgaxo(Crtx, 0x4B, Pblack); 
1994/0803    
 
	/* 
	 * Find a place for the cursor data in display memory. 
1994/0810/sys/src/9/pc/vgas3.c:230,2351995/0126/sys/src/9/pc/vgas3.c:227,234
1994/0803    
	load, 
	move, 
	disable, 
1995/0126    
 
	0, 
1994/0803    
}; 
 
void 
1994/0810/sys/src/9/pc/vgas3.c:242,2451995/0126/sys/src/9/pc/vgas3.c:241,258
1994/0803    
	} 
	else 
		sets3page(page); 
1995/0126    
} 
 
static Vgac s3 = { 
	"s3", 
	s3page, 
 
	0, 
}; 
 
void 
vgas3link(void) 
{ 
	addvgaclink(&s3); 
	addhwgclink(&s3hwgc); 
1994/0803    
} 
1995/0126/sys/src/9/pc/vgas3.c:231,2371995/02021/sys/src/9/pc/vgas3.c:231,237 (short | long)
1995/0126    
	0, 
1994/0803    
}; 
 
void 
1995/02021    
static void 
1994/0803    
s3page(int page) 
{ 
	if(hwgc == &s3hwgc){ 
1995/02021/sys/src/9/pc/vgas3.c:14,201997/0327/sys/src/9/pc/vgas3.c:14,20 (short | long)
1994/0803    
 * generic S3 chipset. 
 * Assume we're in enhanced mode. 
 */ 
static Lock s3pagelock; 
1997/0327    
static Lock s3lock; 
1994/0803    
static ulong storage; 
1994/0804    
static Point hotpoint; 
1994/0803    
 
1995/02021/sys/src/9/pc/vgas3.c:57,631997/0327/sys/src/9/pc/vgas3.c:57,63
1994/0803    
} 
 
static void 
disable(void) 
1997/0327    
_disable(void) 
1994/0803    
{ 
	uchar crt45; 
 
1995/02021/sys/src/9/pc/vgas3.c:70,811997/0327/sys/src/9/pc/vgas3.c:70,91
1994/0803    
} 
 
static void 
1997/0327    
disable(void) 
{ 
	lock(&s3lock); 
	_disable(); 
	unlock(&s3lock); 
} 
 
static void 
1994/0803    
enable(void) 
{ 
	int i; 
 
	disable(); 
1997/0327    
	lock(&s3lock); 
1994/0803    
 
1997/0327    
	_disable(); 
 
1994/0803    
	/* 
	 * Cursor colours. Set both the CR0[EF] and the colour 
	 * stack in case we are using a 16-bit RAMDAC. 
1995/02021/sys/src/9/pc/vgas3.c:105,1101997/0327/sys/src/9/pc/vgas3.c:115,122
1994/0803    
	vgaxo(Crtx, 0x55, vgaxi(Crtx, 0x55)|0x10); 
	vsyncactive(); 
	vgaxo(Crtx, 0x45, 0x01); 
1997/0327    
 
	unlock(&s3lock); 
1994/0803    
} 
 
static void 
1995/02021/sys/src/9/pc/vgas3.c:119,1291997/0327/sys/src/9/pc/vgas3.c:131,141
1994/0809    
	 * If it's the same as the last cursor we loaded, 
	 * just make sure it's enabled. 
	 */ 
	lock(&s3pagelock); 
1997/0327    
	lock(&s3lock); 
1994/0810    
	if(memcmp(c, &curcursor, sizeof(Cursor)) == 0){ 
1994/0809    
		vsyncactive(); 
		vgaxo(Crtx, 0x45, 0x01); 
		unlock(&s3pagelock); 
1997/0327    
		unlock(&s3lock); 
1994/0809    
		return; 
	} 
1994/0810    
	memmove(&curcursor, c, sizeof(Cursor)); 
1995/02021/sys/src/9/pc/vgas3.c:135,1411997/0327/sys/src/9/pc/vgas3.c:147,153
1994/0804    
	 * pointer to the two planes. What if this crosses 
	 * into a new page? 
1994/0803    
	 */ 
	disable(); 
1997/0327    
	_disable(); 
1994/0803    
 
	sets3page(storage>>16); 
1994/0804    
	p = ((uchar*)gscreen.base) + (storage & 0xFFFF); 
1995/02021/sys/src/9/pc/vgas3.c:177,1831997/0327/sys/src/9/pc/vgas3.c:189,195
1994/0803    
	vsyncactive(); 
	vgaxo(Crtx, 0x45, 0x01); 
1994/0809    
 
	unlock(&s3pagelock); 
1997/0327    
	unlock(&s3lock); 
1994/0803    
} 
 
static int 
1995/02021/sys/src/9/pc/vgas3.c:185,1911997/0327/sys/src/9/pc/vgas3.c:197,203
1994/0803    
{ 
1994/0804    
	int x, xo, y, yo; 
 
1994/0809    
	if(canlock(&s3pagelock) == 0) 
1997/0327    
	if(canlock(&s3lock) == 0) 
1994/0810    
		return 1; 
1994/0809    
 
1994/0804    
	/* 
1995/02021/sys/src/9/pc/vgas3.c:217,2231997/0327/sys/src/9/pc/vgas3.c:229,235
1994/0804    
	vgaxo(Crtx, 0x4F, yo); 
	vgaxo(Crtx, 0x48, (y>>8) & 0x07); 
1994/0803    
 
1994/0809    
	unlock(&s3pagelock); 
1997/0327    
	unlock(&s3lock); 
1994/0803    
	return 0; 
} 
 
1995/02021/sys/src/9/pc/vgas3.c:234,2461997/0327/sys/src/9/pc/vgas3.c:246,254
1995/02021    
static void 
1994/0803    
s3page(int page) 
{ 
	if(hwgc == &s3hwgc){ 
		lock(&s3pagelock); 
		sets3page(page); 
		unlock(&s3pagelock); 
	} 
	else 
		sets3page(page); 
1997/0327    
	lock(&s3lock); 
	sets3page(page); 
	unlock(&s3lock); 
1995/0126    
} 
 
static Vgac s3 = { 
1997/0327/sys/src/9/pc/vgas3.c:3,321997/1101/sys/src/9/pc/vgas3.c:3,24 (short | long)
1994/0803    
#include "mem.h" 
#include "dat.h" 
#include "fns.h" 
1997/1101    
#include "io.h" 
1994/0803    
#include "../port/error.h" 
 
#include <libg.h> 
1997/1101    
#define	Image	IMAGE 
#include <draw.h> 
#include <memdraw.h> 
1994/0803    
#include "screen.h" 
#include "vga.h" 
 
/* 
 * Hardware graphics cursor support for 
 * generic S3 chipset. 
 * Assume we're in enhanced mode. 
 */ 
1997/0327    
static Lock s3lock; 
1994/0803    
static ulong storage; 
1994/0804    
static Point hotpoint; 
1994/0803    
                 
extern Bitmap gscreen; 
1994/0810    
extern Cursor curcursor; 
1994/0803    
                 
static void 
sets3page(int page) 
1997/1101    
static int 
s3pageset(VGAscr* scr, int page) 
1994/0803    
{ 
	uchar crt51; 
1997/1101    
	uchar crt35, crt51; 
	int opage; 
1994/0803    
 
	if(gscreen.ldepth == 3){ 
1997/1101    
	crt35 = vgaxi(Crtx, 0x35); 
	if(scr->gscreen->ldepth == 3){ 
1994/0803    
		/* 
		 * The S3 registers need to be unlocked for this. 
		 * Let's hope they are already: 
1997/0327/sys/src/9/pc/vgas3.c:37,521997/1101/sys/src/9/pc/vgas3.c:29,89
1994/0803    
		 * the upper 2 in Crt51<3:2>. 
		 */ 
		vgaxo(Crtx, 0x35, page & 0x0F); 
		crt51 = vgaxi(Crtx, 0x51) & 0xF3; 
		vgaxo(Crtx, 0x51, crt51|((page & 0x30)>>2)); 
1997/1101    
		crt51 = vgaxi(Crtx, 0x51); 
		vgaxo(Crtx, 0x51, (crt51 & ~0x0C)|((page & 0x30)>>2)); 
		opage = ((crt51 & 0x0C)<<2)|(crt35 & 0x0F); 
1994/0803    
	} 
	else 
1997/1101    
	else{ 
1994/0803    
		vgaxo(Crtx, 0x35, (page<<2) & 0x0C); 
1997/1101    
		opage = (crt35>>2) & 0x03; 
	} 
 
	return opage; 
1994/0803    
} 
 
static void 
vsyncactive(void) 
1997/1101    
s3page(VGAscr* scr, int page) 
1994/0803    
{ 
1997/1101    
	lock(&scr->devlock); 
	s3pageset(scr, page); 
	unlock(&scr->devlock); 
} 
 
static ulong 
s3linear(VGAscr* scr, int* size, int* align) 
{ 
	ulong aperture, oaperture; 
	int oapsize, wasupamem; 
	Pcidev *p; 
 
	oaperture = scr->aperture; 
	oapsize = scr->apsize; 
	wasupamem = scr->isupamem; 
	if(wasupamem) 
		upafree(oaperture, oapsize); 
	scr->isupamem = 0; 
 
	if(p = pcimatch(nil, 0x5333, 0)){ 
		aperture = p->mem[0].bar & ~0x0F; 
		*size = p->mem[0].size; 
	} 
	else 
		aperture = 0; 
 
	aperture = upamalloc(aperture, *size, *align); 
	if(aperture == 0){ 
		if(wasupamem && upamalloc(oaperture, oapsize, 0)) 
			scr->isupamem = 1; 
	} 
	else 
		scr->isupamem = 1; 
 
	return aperture; 
} 
 
static void 
s3vsyncactive(void) 
{ 
1994/0803    
	/* 
	 * Hardware cursor information is fetched from display memory 
	 * during the horizontal blank active time. The 80x chips may hang 
1997/0327/sys/src/9/pc/vgas3.c:57,631997/1101/sys/src/9/pc/vgas3.c:94,100
1994/0803    
} 
 
static void 
1997/0327    
_disable(void) 
1997/1101    
s3disable(VGAscr*) 
1994/0803    
{ 
	uchar crt45; 
 
1997/0327/sys/src/9/pc/vgas3.c:65,911997/1101/sys/src/9/pc/vgas3.c:102,119
1994/0803    
	 * Turn cursor off. 
	 */ 
	crt45 = vgaxi(Crtx, 0x45) & 0xFE; 
	vsyncactive(); 
1997/1101    
	s3vsyncactive(); 
1994/0803    
	vgaxo(Crtx, 0x45, crt45); 
} 
 
static void 
1997/0327    
disable(void) 
1997/1101    
s3enable(VGAscr* scr) 
1997/0327    
{ 
	lock(&s3lock); 
	_disable(); 
	unlock(&s3lock); 
} 
                 
static void 
1994/0803    
enable(void) 
{ 
	int i; 
1997/1101    
	ulong storage; 
1994/0803    
 
1997/0327    
	lock(&s3lock); 
1997/1101    
	s3disable(scr); 
1994/0803    
 
1997/0327    
	_disable(); 
                 
1994/0803    
	/* 
	 * Cursor colours. Set both the CR0[EF] and the colour 
	 * stack in case we are using a 16-bit RAMDAC. 
1997/0327/sys/src/9/pc/vgas3.c:104,1571997/1101/sys/src/9/pc/vgas3.c:132,170
1994/0803    
	 * 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; 
1997/1101    
	storage = (scr->gscreen->width*BY2WD*scr->gscreen->r.max.y+1023)/1024; 
1994/0803    
	vgaxo(Crtx, 0x4C, (storage>>8) & 0x0F); 
	vgaxo(Crtx, 0x4D, storage & 0xFF); 
	storage *= 1024; 
1997/1101    
	scr->storage = storage; 
1994/0803    
 
	/* 
	 * Enable the cursor in X11 mode. 
	 */ 
	vgaxo(Crtx, 0x55, vgaxi(Crtx, 0x55)|0x10); 
	vsyncactive(); 
1997/1101    
	s3vsyncactive(); 
1994/0803    
	vgaxo(Crtx, 0x45, 0x01); 
1997/0327    
                 
	unlock(&s3lock); 
1994/0803    
} 
 
static void 
load(Cursor *c) 
1997/1101    
s3load(VGAscr* scr, Cursor* curs) 
1994/0803    
{ 
1994/0804    
	uchar *p; 
1994/0803    
	int x, y; 
1997/1101    
	int opage, x, y; 
1994/0803    
 
	/* 
1994/0809    
	 * Lock the display memory so we can update the 
	 * cursor bitmap if necessary. 
	 * If it's the same as the last cursor we loaded, 
	 * just make sure it's enabled. 
1997/1101    
	 * Disable the cursor and 
	 * set the pointer to the two planes. 
	 * Is linear addressing turned on? This will determine 
	 * how we access the cursor storage. 
1994/0809    
	 */ 
1997/0327    
	lock(&s3lock); 
1994/0810    
	if(memcmp(c, &curcursor, sizeof(Cursor)) == 0){ 
1994/0809    
		vsyncactive(); 
		vgaxo(Crtx, 0x45, 0x01); 
1997/0327    
		unlock(&s3lock); 
1994/0809    
		return; 
	} 
1994/0810    
	memmove(&curcursor, c, sizeof(Cursor)); 
1997/1101    
	s3disable(scr); 
1994/0809    
 
	/* 
	 * Disable the cursor. 
1994/0803    
	 * Set the display page (do we need to restore 
	 * the current contents when done?) and the 
1994/0804    
	 * pointer to the two planes. What if this crosses 
	 * into a new page? 
1994/0803    
	 */ 
1997/0327    
	_disable(); 
1997/1101    
	p = KADDR(scr->aperture); 
	lock(&scr->devlock); 
	opage = s3pageset(scr, scr->storage>>16); 
	p += (scr->storage & 0xFFFF); 
1994/0803    
 
	sets3page(storage>>16); 
1994/0804    
	p = ((uchar*)gscreen.base) + (storage & 0xFFFF); 
1994/0803    
                 
	/* 
	 * The cursor is set in X11 mode which gives the following 
	 * truth table: 
1997/0327/sys/src/9/pc/vgas3.c:168,1771997/1101/sys/src/9/pc/vgas3.c:181,190
1994/0803    
	for(y = 0; y < 64; y++){ 
1994/0804    
		for(x = 0; x < 64/8; x += 2){ 
			if(x < 16/8 && y < 16){ 
				*p++ = c->clr[2*y + x]|c->set[2*y + x]; 
				*p++ = c->clr[2*y + x+1]|c->set[2*y + x+1]; 
				*p++ = c->set[2*y + x]; 
				*p++ = c->set[2*y + x+1]; 
1997/1101    
				*p++ = curs->clr[2*y + x]|curs->set[2*y + x]; 
				*p++ = curs->clr[2*y + x+1]|curs->set[2*y + x+1]; 
				*p++ = curs->set[2*y + x]; 
				*p++ = curs->set[2*y + x+1]; 
1994/0803    
			} 
			else { 
1994/0804    
				*p++ = 0x00; 
1997/0327/sys/src/9/pc/vgas3.c:182,2051997/1101/sys/src/9/pc/vgas3.c:195,216
1994/0803    
		} 
	} 
 
1997/1101    
	s3pageset(scr, opage); 
	unlock(&scr->devlock); 
 
1994/0803    
	/* 
1994/0804    
	 * Set the cursor hotpoint and enable the cursor. 
1997/1101    
	 * Save the cursor hotpoint and enable the cursor. 
1994/0803    
	 */ 
1994/0804    
	hotpoint = c->offset; 
1994/0803    
	vsyncactive(); 
1997/1101    
	scr->offset = curs->offset; 
	s3vsyncactive(); 
1994/0803    
	vgaxo(Crtx, 0x45, 0x01); 
1994/0809    
                 
1997/0327    
	unlock(&s3lock); 
1994/0803    
} 
 
static int 
move(Point p) 
1997/1101    
s3move(VGAscr* scr, Point p) 
1994/0803    
{ 
1994/0804    
	int x, xo, y, yo; 
 
1997/0327    
	if(canlock(&s3lock) == 0) 
1994/0810    
		return 1; 
1994/0809    
                 
1994/0804    
	/* 
	 * Mustn't position the cursor offscreen even partially, 
	 * or it disappears. Therefore, if x or y is -ve, adjust the 
1997/0327/sys/src/9/pc/vgas3.c:208,2141997/1101/sys/src/9/pc/vgas3.c:219,225
1994/0809    
	 * cursor doesn't disappear off the left edge properly, so 
	 * round it up to be even. 
1994/0804    
	 */ 
	if((x = p.x+hotpoint.x) < 0){ 
1997/1101    
	if((x = p.x+scr->offset.x) < 0){ 
1994/0804    
		xo = -x; 
		xo = ((xo+1)/2)*2; 
		x = 0; 
1997/0327/sys/src/9/pc/vgas3.c:215,2211997/1101/sys/src/9/pc/vgas3.c:226,232
1994/0804    
	} 
	else 
		xo = 0; 
	if((y = p.y+hotpoint.y) < 0){ 
1997/1101    
	if((y = p.y+scr->offset.y) < 0){ 
1994/0804    
		yo = -y; 
		y = 0; 
	} 
1997/0327/sys/src/9/pc/vgas3.c:229,2661997/1101/sys/src/9/pc/vgas3.c:240,262
1994/0804    
	vgaxo(Crtx, 0x4F, yo); 
	vgaxo(Crtx, 0x48, (y>>8) & 0x07); 
1994/0803    
 
1997/0327    
	unlock(&s3lock); 
1994/0803    
	return 0; 
} 
 
Hwgc s3hwgc = { 
	"s3hwgc", 
	enable, 
	load, 
	move, 
	disable, 
1997/1101    
VGAdev vgas3dev = { 
	"s3", 
1995/0126    
 
	0, 
1997/1101    
	0, 
	s3page, 
	s3linear, 
1994/0803    
}; 
 
1995/02021    
static void 
1994/0803    
s3page(int page) 
{ 
1997/0327    
	lock(&s3lock); 
	sets3page(page); 
	unlock(&s3lock); 
1995/0126    
} 
1997/1101    
VGAcur vgas3cur = { 
	"s3hwgc", 
1995/0126    
 
static Vgac s3 = { 
	"s3", 
	s3page, 
                 
	0, 
1997/1101    
	s3enable, 
	s3disable, 
	s3load, 
	s3move, 
1995/0126    
}; 
                 
void 
vgas3link(void) 
{ 
	addvgaclink(&s3); 
	addhwgclink(&s3hwgc); 
1994/0803    
} 
1997/1101/sys/src/9/pc/vgas3.c:44,521998/0116/sys/src/9/pc/vgas3.c:44,63 (short | long)
1994/0803    
static void 
1997/1101    
s3page(VGAscr* scr, int page) 
1994/0803    
{ 
1997/1101    
	lock(&scr->devlock); 
	s3pageset(scr, page); 
	unlock(&scr->devlock); 
1998/0116    
	int id; 
 
	id = (vgaxi(Crtx, 0x30)<<8)|vgaxi(Crtx, 0x2E); 
	switch(id){ 
 
	case 0xE110:				/* ViRGE/GX2 */ 
		break; 
 
	default: 
		lock(&scr->devlock); 
		s3pageset(scr, page); 
		unlock(&scr->devlock); 
		break; 
	} 
1997/1101    
} 
 
static ulong 
1997/1101/sys/src/9/pc/vgas3.c:109,1151998/0116/sys/src/9/pc/vgas3.c:120,126
1994/0803    
static void 
1997/1101    
s3enable(VGAscr* scr) 
1997/0327    
{ 
1994/0803    
	int i; 
1998/0116    
	int i, id; 
1997/1101    
	ulong storage; 
1994/0803    
 
1997/1101    
	s3disable(scr); 
1997/1101/sys/src/9/pc/vgas3.c:117,1331998/0116/sys/src/9/pc/vgas3.c:128,158
1994/0803    
	/* 
	 * Cursor colours. Set both the CR0[EF] and the colour 
	 * stack in case we are using a 16-bit RAMDAC. 
1994/0804    
	 * Why are these colours reversed? 
1998/0116    
	 * This stuff is just a mystery for the ViRGE/GX2. 
1994/0803    
	 */ 
1995/0126    
	vgaxo(Crtx, 0x0E, Pwhite); 
	vgaxo(Crtx, 0x0F, Pblack); 
1994/0803    
	vgaxi(Crtx, 0x45); 
	for(i = 0; i < 4; i++) 
1995/0126    
		vgaxo(Crtx, 0x4A, Pwhite); 
1994/0803    
	vgaxi(Crtx, 0x45); 
	for(i = 0; i < 4; i++) 
1995/0126    
		vgaxo(Crtx, 0x4B, Pblack); 
1998/0116    
	id = (vgaxi(Crtx, 0x30)<<8)|vgaxi(Crtx, 0x2E); 
	switch(id){ 
1994/0803    
 
1998/0116    
	case 0xE110:				/* ViRGE/GX2 */ 
		for(i = 0; i < 3; i++) 
			vgaxo(Crtx, 0x4A, Pblack); 
		vgaxi(Crtx, 0x45); 
		for(i = 0; i < 3; i++) 
			vgaxo(Crtx, 0x4B, Pwhite); 
		break; 
 
	default: 
		for(i = 0; i < 3; i++) 
			vgaxo(Crtx, 0x4A, Pwhite); 
		vgaxi(Crtx, 0x45); 
		for(i = 0; i < 3; i++) 
			vgaxo(Crtx, 0x4B, Pblack); 
		break; 
	} 
 
1994/0803    
	/* 
	 * Find a place for the cursor data in display memory. 
	 * Must be on a 1024-byte boundary. 
1997/1101/sys/src/9/pc/vgas3.c:139,1471998/0116/sys/src/9/pc/vgas3.c:164,172
1997/1101    
	scr->storage = storage; 
1994/0803    
 
	/* 
	 * Enable the cursor in X11 mode. 
1998/0116    
	 * Enable the cursor in Microsoft Windows format. 
1994/0803    
	 */ 
	vgaxo(Crtx, 0x55, vgaxi(Crtx, 0x55)|0x10); 
1998/0116    
	vgaxo(Crtx, 0x55, vgaxi(Crtx, 0x55) & ~0x10); 
1997/1101    
	s3vsyncactive(); 
1994/0803    
	vgaxo(Crtx, 0x45, 0x01); 
} 
1997/1101/sys/src/9/pc/vgas3.c:150,1781998/0116/sys/src/9/pc/vgas3.c:175,212
1997/1101    
s3load(VGAscr* scr, Cursor* curs) 
1994/0803    
{ 
1994/0804    
	uchar *p; 
1997/1101    
	int opage, x, y; 
1998/0116    
	int id, opage, x, y; 
1994/0803    
 
	/* 
1997/1101    
	 * Disable the cursor and 
	 * set the pointer to the two planes. 
	 * Is linear addressing turned on? This will determine 
	 * how we access the cursor storage. 
1994/0809    
	 */ 
1997/1101    
	s3disable(scr); 
1994/0809    
 
1998/0116    
	opage = 0; 
1997/1101    
	p = KADDR(scr->aperture); 
	lock(&scr->devlock); 
	opage = s3pageset(scr, scr->storage>>16); 
	p += (scr->storage & 0xFFFF); 
1998/0116    
	id = (vgaxi(Crtx, 0x30)<<8)|vgaxi(Crtx, 0x2E); 
	switch(id){ 
1994/0803    
 
1998/0116    
	case 0xE110:				/* ViRGE/GX2 */ 
		p += scr->storage; 
		break; 
 
	default: 
		lock(&scr->devlock); 
		opage = s3pageset(scr, scr->storage>>16); 
		p += (scr->storage & 0xFFFF); 
		break; 
	} 
 
1994/0803    
	/* 
	 * The cursor is set in X11 mode which gives the following 
	 * truth table: 
1998/0116    
	 * The cursor is set in Microsoft Windows format (the ViRGE/GX2 no 
	 * longer supports the X11 format) which gives the following truth table: 
1994/0803    
	 *	and xor	colour 
	 *	 0   0	underlying pixel colour 
	 *	 0   1	underlying pixel colour 
	 *	 1   0	background colour 
	 *	 1   1	foreground colour 
1998/0116    
	 *	 0   0	background colour 
	 *	 0   1	foreground colour 
	 *	 1   0	current screen pixel 
	 *	 1   1	NOT current screen pixel 
1994/0803    
	 * Put the cursor into the top-left of the 64x64 array. 
1994/0809    
	 * 
	 * The cursor pattern in memory is interleaved words of 
1997/1101/sys/src/9/pc/vgas3.c:181,2021998/0116/sys/src/9/pc/vgas3.c:215,244
1994/0803    
	for(y = 0; y < 64; y++){ 
1994/0804    
		for(x = 0; x < 64/8; x += 2){ 
			if(x < 16/8 && y < 16){ 
1997/1101    
				*p++ = curs->clr[2*y + x]|curs->set[2*y + x]; 
				*p++ = curs->clr[2*y + x+1]|curs->set[2*y + x+1]; 
1998/0116    
				*p++ = ~(curs->clr[2*y + x]|curs->set[2*y + x]); 
				*p++ = ~(curs->clr[2*y + x+1]|curs->set[2*y + x+1]); 
1997/1101    
				*p++ = curs->set[2*y + x]; 
				*p++ = curs->set[2*y + x+1]; 
1994/0803    
			} 
			else { 
1998/0116    
				*p++ = 0xFF; 
				*p++ = 0xFF; 
1994/0804    
				*p++ = 0x00; 
				*p++ = 0x00; 
				*p++ = 0x00; 
				*p++ = 0x00; 
1994/0803    
			} 
		} 
	} 
 
1997/1101    
	s3pageset(scr, opage); 
	unlock(&scr->devlock); 
1998/0116    
	switch(id){ 
 
	case 0xE110:				/* ViRGE/GX2 */ 
		break; 
 
	default: 
		s3pageset(scr, opage); 
		unlock(&scr->devlock); 
		break; 
	} 
1997/1101    
 
1994/0803    
	/* 
1997/1101    
	 * Save the cursor hotpoint and enable the cursor. 
1998/0116/sys/src/9/pc/vgas3.c:9,141999/0119/sys/src/9/pc/vgas3.c:9,15 (short | long)
1997/1101    
#define	Image	IMAGE 
#include <draw.h> 
#include <memdraw.h> 
1999/0119    
#include <cursor.h> 
1994/0803    
#include "screen.h" 
 
1997/1101    
static int 
1999/0119/sys/src/9/pc/vgas3.c:64,751999/0716/sys/src/9/pc/vgas3.c:64,77 (short | long)
1997/1101    
static ulong 
s3linear(VGAscr* scr, int* size, int* align) 
{ 
	ulong aperture, oaperture; 
1999/0716    
	ulong aperture, oaperture, osize; 
1997/1101    
	int oapsize, wasupamem; 
	Pcidev *p; 
1999/0716    
	Physseg seg; 
1997/1101    
 
	oaperture = scr->aperture; 
	oapsize = scr->apsize; 
1999/0716    
	osize = *size; 
1997/1101    
	wasupamem = scr->isupamem; 
	if(wasupamem) 
		upafree(oaperture, oapsize); 
1999/0119/sys/src/9/pc/vgas3.c:90,951999/0716/sys/src/9/pc/vgas3.c:92,104
1997/1101    
	else 
		scr->isupamem = 1; 
 
1999/0716    
	memset(&seg, 0, sizeof(seg)); 
	seg.attr = SG_PHYSICAL; 
	seg.name = smalloc(NAMELEN); 
	snprint(seg.name, NAMELEN, "s3screen"); 
	seg.pa = aperture; 
	seg.size = osize; 
	addphysseg(&seg); 
1997/1101    
	return aperture; 
} 
 
1999/0716/sys/src/9/pc/vgas3.c:199,2041999/0821/sys/src/9/pc/vgas3.c:199,205 (short | long)
1998/0116    
	switch(id){ 
1994/0803    
 
1998/0116    
	case 0xE110:				/* ViRGE/GX2 */ 
1999/0821    
	case 0xE131:				/* ViRGE */ 
1998/0116    
		p += scr->storage; 
		break; 
 
1999/0716/sys/src/9/pc/vgas3.c:242,2471999/0821/sys/src/9/pc/vgas3.c:243,249
1998/0116    
	switch(id){ 
 
	case 0xE110:				/* ViRGE/GX2 */ 
1999/0821    
	case 0xE131:				/* ViRGE */ 
1998/0116    
		break; 
 
	default: 
1999/0821/sys/src/9/pc/vgas3.c:19,251999/1005/sys/src/9/pc/vgas3.c:19,25 (short | long)
1997/1101    
	int opage; 
1994/0803    
 
1997/1101    
	crt35 = vgaxi(Crtx, 0x35); 
	if(scr->gscreen->ldepth == 3){ 
1999/1005    
	if(scr->gscreen->depth >= 8){ 
1994/0803    
		/* 
		 * The S3 registers need to be unlocked for this. 
		 * Let's hope they are already: 
1999/0821/sys/src/9/pc/vgas3.c:64,771999/1005/sys/src/9/pc/vgas3.c:64,77
1997/1101    
static ulong 
s3linear(VGAscr* scr, int* size, int* align) 
{ 
1999/0716    
	ulong aperture, oaperture, osize; 
1997/1101    
	int oapsize, wasupamem; 
1999/1005    
	ulong aperture, oaperture; 
	int osize, oapsize, wasupamem; 
1997/1101    
	Pcidev *p; 
1999/0716    
	Physseg seg; 
1997/1101    
 
1999/1005    
	osize = *size; 
1997/1101    
	oaperture = scr->aperture; 
	oapsize = scr->apsize; 
1999/0716    
	osize = *size; 
1997/1101    
	wasupamem = scr->isupamem; 
	if(wasupamem) 
		upafree(oaperture, oapsize); 
1999/0821/sys/src/9/pc/vgas3.c:92,971999/1005/sys/src/9/pc/vgas3.c:92,99
1997/1101    
	else 
		scr->isupamem = 1; 
 
1999/1005    
	if(oaperture) 
		print("warning (BUG): redefinition of aperture does not change s3screen segment\n"); 
1999/0716    
	memset(&seg, 0, sizeof(seg)); 
	seg.attr = SG_PHYSICAL; 
	seg.name = smalloc(NAMELEN); 
1999/0821/sys/src/9/pc/vgas3.c:99,1041999/1005/sys/src/9/pc/vgas3.c:101,107
1999/0716    
	seg.pa = aperture; 
	seg.size = osize; 
	addphysseg(&seg); 
1999/1005    
 
1997/1101    
	return aperture; 
} 
 
1999/0821/sys/src/9/pc/vgas3.c:130,1361999/1005/sys/src/9/pc/vgas3.c:133,139
1994/0803    
static void 
1997/1101    
s3enable(VGAscr* scr) 
1997/0327    
{ 
1998/0116    
	int i, id; 
1999/1005    
	int i; 
1997/1101    
	ulong storage; 
1994/0803    
 
1997/1101    
	s3disable(scr); 
1999/0821/sys/src/9/pc/vgas3.c:138,1681999/1005/sys/src/9/pc/vgas3.c:141,157
1994/0803    
	/* 
	 * Cursor colours. Set both the CR0[EF] and the colour 
	 * stack in case we are using a 16-bit RAMDAC. 
1998/0116    
	 * This stuff is just a mystery for the ViRGE/GX2. 
1994/0803    
	 */ 
1995/0126    
	vgaxo(Crtx, 0x0E, Pwhite); 
	vgaxo(Crtx, 0x0F, Pblack); 
1994/0803    
	vgaxi(Crtx, 0x45); 
1998/0116    
	id = (vgaxi(Crtx, 0x30)<<8)|vgaxi(Crtx, 0x2E); 
	switch(id){ 
1994/0803    
 
1998/0116    
	case 0xE110:				/* ViRGE/GX2 */ 
		for(i = 0; i < 3; i++) 
			vgaxo(Crtx, 0x4A, Pblack); 
		vgaxi(Crtx, 0x45); 
		for(i = 0; i < 3; i++) 
			vgaxo(Crtx, 0x4B, Pwhite); 
		break; 
1999/1005    
	for(i = 0; i < 3; i++) 
		vgaxo(Crtx, 0x4A, Pblack); 
	vgaxi(Crtx, 0x45); 
	for(i = 0; i < 3; i++) 
		vgaxo(Crtx, 0x4B, Pwhite); 
1998/0116    
 
	default: 
		for(i = 0; i < 3; i++) 
			vgaxo(Crtx, 0x4A, Pwhite); 
		vgaxi(Crtx, 0x45); 
		for(i = 0; i < 3; i++) 
			vgaxo(Crtx, 0x4B, Pblack); 
		break; 
	} 
                 
1994/0803    
	/* 
	 * Find a place for the cursor data in display memory. 
	 * Must be on a 1024-byte boundary. 
1999/0821/sys/src/9/pc/vgas3.c:198,2051999/1005/sys/src/9/pc/vgas3.c:187,196
1998/0116    
	id = (vgaxi(Crtx, 0x30)<<8)|vgaxi(Crtx, 0x2E); 
	switch(id){ 
1994/0803    
 
1998/0116    
	case 0xE110:				/* ViRGE/GX2 */ 
1999/0821    
	case 0xE131:				/* ViRGE */ 
1999/1005    
	case 0xE18A:				/* ViRGE/[DG]X */ 
	case 0xE110:				/* ViRGE/GX2 */ 
	case 0xE13D:				/* ViRGE/VX */ 
1998/0116    
		p += scr->storage; 
		break; 
 
1999/0821/sys/src/9/pc/vgas3.c:242,2491999/1005/sys/src/9/pc/vgas3.c:233,242
1994/0803    
 
1998/0116    
	switch(id){ 
 
	case 0xE110:				/* ViRGE/GX2 */ 
1999/0821    
	case 0xE131:				/* ViRGE */ 
1999/1005    
	case 0xE18A:				/* ViRGE/[DG]X */ 
	case 0xE110:				/* ViRGE/GX2 */ 
	case 0xE13D:				/* ViRGE/VX */ 
1998/0116    
		break; 
 
	default: 
1999/0821/sys/src/9/pc/vgas3.c:297,3021999/1005/sys/src/9/pc/vgas3.c:290,471
1994/0803    
	return 0; 
} 
 
1999/1005    
/* 
 * The manual gives byte offsets, but we want ulong offsets, hence /4. 
 */ 
enum { 
	SrcBase = 0xA4D4/4, 
	DstBase = 0xA4D8/4, 
	Stride = 0xA4E4/4, 
	FgrdData = 0xA4F4/4, 
	WidthHeight = 0xA504/4, 
	SrcXY = 0xA508/4, 
	DestXY = 0xA50C/4, 
	Command = 0xA500/4, 
	SubStat = 0x8504/4, 
	FifoStat = 0x850C/4, 
}; 
 
/* 
 * Wait for writes to VGA memory via linear aperture to flush. 
 */ 
enum {Maxloop = 1<<24}; 
struct { 
	ulong linear; 
	ulong fifo; 
	ulong idle; 
} waitcount; 
 
static void 
waitforlinearfifo(VGAscr *scr) 
{ 
	ulong *mmio; 
	long x; 
	static ulong nwaitforlinearfifo; 
	ulong mask, val; 
 
	switch(scr->id){ 
	default: 
		panic("unknown scr->id in s3 waitforlinearfifo"); 
	case 0xE131:	/* ViRGE */ 
	case 0xE13D:	/* ViRGE/VX */ 
		mask = 0x0F<<6; 
		val = 0x08<<6; 
		break; 
	case 0xE110:	/* ViRGE/GX2 */ 
		mask = 0x1F<<6; 
		val = 0x10<<6; 
		break; 
	} 
	mmio = scr->mmio; 
	x = 0; 
	while((mmio[FifoStat]&mask) != val && x++ < Maxloop) 
		waitcount.linear++; 
} 
 
static void 
waitforfifo(VGAscr *scr, int entries) 
{ 
	ulong *mmio; 
	long x; 
	static ulong nwaitforfifo; 
 
	mmio = scr->mmio; 
	x = 0; 
	while((mmio[SubStat]&0x1F00) < ((entries+2)<<8) && x++ < Maxloop) 
		waitcount.fifo++; 
} 
 
static void 
waitforidle(VGAscr *scr) 
{ 
	ulong *mmio; 
	long x; 
 
	mmio = scr->mmio; 
	x = 0; 
	while((mmio[SubStat]&0x3F00) != 0x3000 && x++ < Maxloop) 
		waitcount.idle++; 
} 
 
static int 
hwscroll(VGAscr *scr, Rectangle r, Rectangle sr) 
{ 
	enum { Bitbltop = 0xCC };	/* copy source */ 
	ulong *mmio; 
	ulong cmd, stride; 
	Point dp, sp; 
	int did, d; 
 
	d = scr->gscreen->depth; 
	did = (d-8)/8; 
	cmd = 0x00000020|(Bitbltop<<17)|(did<<2); 
	stride = Dx(scr->gscreen->r)*d/8; 
 
	if(r.min.x <= sr.min.x){ 
		cmd |= 1<<25; 
		dp.x = r.min.x; 
		sp.x = sr.min.x; 
	}else{ 
		dp.x = r.max.x-1; 
		sp.x = sr.max.x-1; 
	} 
 
	if(r.min.y <= sr.min.y){ 
		cmd |= 1<<26; 
		dp.y = r.min.y; 
		sp.y = sr.min.y; 
	}else{ 
		dp.y = r.max.y-1; 
		sp.y = sr.max.y-1; 
	} 
 
	mmio = scr->mmio; 
	waitforlinearfifo(scr); 
	waitforfifo(scr, 7); 
	mmio[SrcBase] = scr->aperture; 
	mmio[DstBase] = scr->aperture; 
	mmio[Stride] = (stride<<16)|stride; 
	mmio[WidthHeight] = ((Dx(r)-1)<<16)|Dy(r); 
	mmio[SrcXY] = (sp.x<<16)|sp.y; 
	mmio[DestXY] = (dp.x<<16)|dp.y; 
	mmio[Command] = cmd; 
	waitforidle(scr); 
	return 1; 
} 
 
static int 
hwfill(VGAscr *scr, Rectangle r, ulong sval) 
{ 
	enum { Bitbltop = 0xCC };	/* copy source */ 
	ulong *mmio; 
	ulong cmd, stride; 
	int did, d; 
 
	d = scr->gscreen->depth; 
	did = (d-8)/8; 
	cmd = 0x16000120|(Bitbltop<<17)|(did<<2); 
	stride = Dx(scr->gscreen->r)*d/8; 
	mmio = scr->mmio; 
	waitforlinearfifo(scr); 
	waitforfifo(scr, 8); 
	mmio[SrcBase] = scr->aperture; 
	mmio[DstBase] = scr->aperture; 
	mmio[DstBase] = scr->aperture; 
	mmio[Stride] = (stride<<16)|stride; 
	mmio[FgrdData] = sval; 
	mmio[WidthHeight] = ((Dx(r)-1)<<16)|Dy(r); 
	mmio[DestXY] = (r.min.x<<16)|r.min.y; 
	mmio[Command] = cmd; 
	waitforidle(scr); 
	return 1; 
} 
 
static void 
s3drawinit(VGAscr *scr) 
{ 
	ulong id; 
 
	id = (vgaxi(Crtx, 0x30)<<8)|vgaxi(Crtx, 0x2E); 
	scr->id = id; 
 
	/* 
	 * It's highly likely that other ViRGEs will work without 
	 * change to the driver, with the exception of the size of 
	 * the linear aperture memory write FIFO.  Since we don't 
	 * know that size, I'm not turning them on.  See waitforlinearfifo 
	 * above. 
	 */ 
	switch(id){ 
	case 0xE131:				/* ViRGE */ 
	case 0xE13D:				/* ViRGE/VX */ 
	case 0xE110:				/* ViRGE/GX2 */ 
		scr->mmio = (ulong*)(scr->aperture+0x1000000); 
		scr->fill = hwfill; 
		scr->scroll = hwscroll; 
	} 
} 
 
1997/1101    
VGAdev vgas3dev = { 
	"s3", 
1995/0126    
 
1999/0821/sys/src/9/pc/vgas3.c:304,3091999/1005/sys/src/9/pc/vgas3.c:473,479
1997/1101    
	0, 
	s3page, 
	s3linear, 
1999/1005    
	s3drawinit, 
1994/0803    
}; 
 
1997/1101    
VGAcur vgas3cur = { 
1999/1005/sys/src/9/pc/vgas3.c:441,4472000/0326/sys/src/9/pc/vgas3.c:441,467 (short | long)
1999/1005    
	return 1; 
} 
 
2000/0326    
enum { 
	CursorSyncCtl = 0x0D,	/* in Seqx */ 
	VsyncHi = 0x80, 
	VsyncLo = 0x40, 
	HsyncHi = 0x20, 
	HsyncLo = 0x10, 
}; 
 
1999/1005    
static void 
2000/0326    
s3blank(int blank) 
{ 
	uchar x; 
 
	x = vgaxi(Seqx, CursorSyncCtl); 
	x &= ~0xF0; 
	if(blank) 
		x |= VsyncLo | HsyncLo; 
	vgaxo(Seqx, CursorSyncCtl, x); 
} 
 
static void 
1999/1005    
s3drawinit(VGAscr *scr) 
{ 
	ulong id; 
1999/1005/sys/src/9/pc/vgas3.c:463,4682000/0326/sys/src/9/pc/vgas3.c:483,489
1999/1005    
		scr->mmio = (ulong*)(scr->aperture+0x1000000); 
		scr->fill = hwfill; 
		scr->scroll = hwscroll; 
2000/0326    
		/* scr->blank = hwblank; */ 
1999/1005    
	} 
} 
 
2000/0326/sys/src/9/pc/vgas3.c:65,712000/0611/sys/src/9/pc/vgas3.c:65,71 (short | long)
1997/1101    
s3linear(VGAscr* scr, int* size, int* align) 
{ 
1999/1005    
	ulong aperture, oaperture; 
	int osize, oapsize, wasupamem; 
2000/0611    
	int i, osize, oapsize, wasupamem; 
1997/1101    
	Pcidev *p; 
1999/0716    
	Physseg seg; 
1997/1101    
 
2000/0326/sys/src/9/pc/vgas3.c:73,892000/0611/sys/src/9/pc/vgas3.c:73,98
1997/1101    
	oaperture = scr->aperture; 
	oapsize = scr->apsize; 
	wasupamem = scr->isupamem; 
	if(wasupamem) 
		upafree(oaperture, oapsize); 
	scr->isupamem = 0; 
 
	if(p = pcimatch(nil, 0x5333, 0)){ 
		aperture = p->mem[0].bar & ~0x0F; 
		*size = p->mem[0].size; 
	} 
	else 
2000/0611    
		for(i=0; i<nelem(p->mem); i++){ 
			if(p->mem[i].size >= *size 
			&& ((p->mem[i].bar & ~0x0F) & (*align-1)) == 0) 
				break; 
		} 
		if(i >= nelem(p->mem)){ 
			print("vgas3: aperture not found\n"); 
			return 0; 
		} 
		aperture = p->mem[i].bar & ~0x0F; 
		*size = p->mem[i].size; 
	}else 
1997/1101    
		aperture = 0; 
 
2000/0611    
	if(wasupamem) 
		upafree(oaperture, oapsize); 
	scr->isupamem = 0; 
 
1997/1101    
	aperture = upamalloc(aperture, *size, *align); 
	if(aperture == 0){ 
		if(wasupamem && upamalloc(oaperture, oapsize, 0)) 
2000/0326/sys/src/9/pc/vgas3.c:191,1962000/0611/sys/src/9/pc/vgas3.c:200,206
1999/1005    
	case 0xE18A:				/* ViRGE/[DG]X */ 
	case 0xE110:				/* ViRGE/GX2 */ 
	case 0xE13D:				/* ViRGE/VX */ 
2000/0611    
	case 0xE122:				/* Savage4 */ 
1998/0116    
		p += scr->storage; 
		break; 
 
2000/0326/sys/src/9/pc/vgas3.c:237,2422000/0611/sys/src/9/pc/vgas3.c:247,253
1999/1005    
	case 0xE18A:				/* ViRGE/[DG]X */ 
	case 0xE110:				/* ViRGE/GX2 */ 
	case 0xE13D:				/* ViRGE/VX */ 
2000/0611    
	case 0xE122:				/* Savage4 */ 
1998/0116    
		break; 
 
	default: 
2000/0611/sys/src/9/pc/vgas3.c:64,712000/0612/sys/src/9/pc/vgas3.c:64,72 (short | long)
1997/1101    
static ulong 
s3linear(VGAscr* scr, int* size, int* align) 
{ 
1999/1005    
	ulong aperture, oaperture; 
2000/0611    
	int i, osize, oapsize, wasupamem; 
2000/0612    
	char *mmioname; 
	ulong aperture, oaperture, mmiobase, mmiosize; 
	int i, id, j, osize, oapsize, wasupamem; 
1997/1101    
	Pcidev *p; 
1999/0716    
	Physseg seg; 
1997/1101    
 
2000/0611/sys/src/9/pc/vgas3.c:74,792000/0612/sys/src/9/pc/vgas3.c:75,83
1997/1101    
	oapsize = scr->apsize; 
	wasupamem = scr->isupamem; 
 
2000/0612    
	mmiosize = 0; 
	mmiobase = 0; 
	mmioname = nil; 
1997/1101    
	if(p = pcimatch(nil, 0x5333, 0)){ 
2000/0611    
		for(i=0; i<nelem(p->mem); i++){ 
			if(p->mem[i].size >= *size 
2000/0611/sys/src/9/pc/vgas3.c:86,912000/0612/sys/src/9/pc/vgas3.c:90,122
2000/0611    
		} 
		aperture = p->mem[i].bar & ~0x0F; 
		*size = p->mem[i].size; 
2000/0612    
 
		id = (vgaxi(Crtx, 0x30)<<8)|vgaxi(Crtx, 0x2E); 
		if(id == 0xE122){		/* find Savage4 mmio */ 
			/* 
			 * We could assume that the MMIO registers 
			 * will be in the screen segment and just use 
			 * that, but PCI software is allowed to move them 
			 * if it feels like it, so we look for an aperture of 
			 * the right size; only the first 512k actually means 
			 * anything.  The S3 engineers overestimated how 
			 * much space they would need in the first design. 
			 */ 
			for(j=0; j<nelem(p->mem); j++){ 
				if(i == j) 
					continue; 
				if(p->mem[j].size==512*1024 || p->mem[j].size==16*1024*1024){ 
					mmiobase = p->mem[j].bar & ~0x0F; 
					mmiosize = 512*1024; 
					mmioname = "savage4mmio"; 
					break; 
				} 
			} 
			if(mmiosize == 0){ 
				print("savage4: mmio not found\n"); 
				return 0; 
			} 
		} 
2000/0611    
	}else 
1997/1101    
		aperture = 0; 
 
2000/0611/sys/src/9/pc/vgas3.c:111,1162000/0612/sys/src/9/pc/vgas3.c:142,156
1999/0716    
	seg.size = osize; 
	addphysseg(&seg); 
1999/1005    
 
2000/0612    
	if(mmiosize){ 
		memset(&seg, 0, sizeof(seg)); 
		seg.attr = SG_PHYSICAL; 
		seg.name = smalloc(NAMELEN); 
		snprint(seg.name, NAMELEN, mmioname); 
		seg.pa = mmiobase; 
		seg.size = mmiosize; 
		addphysseg(&seg); 
	} 
1997/1101    
	return aperture; 
} 
 
2000/0611/sys/src/9/pc/vgas3.c:166,1722000/0612/sys/src/9/pc/vgas3.c:206,212
1994/0803    
	 * Must be on a 1024-byte boundary. 
	 */ 
1997/1101    
	storage = (scr->gscreen->width*BY2WD*scr->gscreen->r.max.y+1023)/1024; 
1994/0803    
	vgaxo(Crtx, 0x4C, (storage>>8) & 0x0F); 
2000/0612    
	vgaxo(Crtx, 0x4C, storage>>8); 
1994/0803    
	vgaxo(Crtx, 0x4D, storage & 0xFF); 
	storage *= 1024; 
1997/1101    
	scr->storage = storage; 
2000/0611/sys/src/9/pc/vgas3.c:325,3302000/0612/sys/src/9/pc/vgas3.c:365,373
1999/1005    
	ulong linear; 
	ulong fifo; 
	ulong idle; 
2000/0612    
	ulong lineartimeout; 
	ulong fifotimeout; 
	ulong idletimeout; 
1999/1005    
} waitcount; 
 
static void 
2000/0611/sys/src/9/pc/vgas3.c:352,3572000/0612/sys/src/9/pc/vgas3.c:395,402
1999/1005    
	x = 0; 
	while((mmio[FifoStat]&mask) != val && x++ < Maxloop) 
		waitcount.linear++; 
2000/0612    
	if(x >= Maxloop) 
		waitcount.lineartimeout++; 
1999/1005    
} 
 
static void 
2000/0611/sys/src/9/pc/vgas3.c:365,3702000/0612/sys/src/9/pc/vgas3.c:410,417
1999/1005    
	x = 0; 
	while((mmio[SubStat]&0x1F00) < ((entries+2)<<8) && x++ < Maxloop) 
		waitcount.fifo++; 
2000/0612    
	if(x >= Maxloop) 
		waitcount.fifotimeout++; 
1999/1005    
} 
 
static void 
2000/0611/sys/src/9/pc/vgas3.c:377,3822000/0612/sys/src/9/pc/vgas3.c:424,431
1999/1005    
	x = 0; 
	while((mmio[SubStat]&0x3F00) != 0x3000 && x++ < Maxloop) 
		waitcount.idle++; 
2000/0612    
	if(x >= Maxloop) 
		waitcount.idletimeout++; 
1999/1005    
} 
 
static int 
2000/0612/sys/src/9/pc/vgas3.c:240,2452000/0701/sys/src/9/pc/vgas3.c:240,246 (short | long)
1999/1005    
	case 0xE18A:				/* ViRGE/[DG]X */ 
	case 0xE110:				/* ViRGE/GX2 */ 
	case 0xE13D:				/* ViRGE/VX */ 
2000/0701    
	case 0xE112:				/* Savage4/MX */ 
2000/0611    
	case 0xE122:				/* Savage4 */ 
1998/0116    
		p += scr->storage; 
		break; 
2000/0612/sys/src/9/pc/vgas3.c:287,2922000/0701/sys/src/9/pc/vgas3.c:288,294
1999/1005    
	case 0xE18A:				/* ViRGE/[DG]X */ 
	case 0xE110:				/* ViRGE/GX2 */ 
	case 0xE13D:				/* ViRGE/VX */ 
2000/0701    
	case 0xE112:				/* Savage4/MX */ 
2000/0611    
	case 0xE122:				/* Savage4 */ 
1998/0116    
		break; 
 
2000/0701/sys/src/9/pc/vgas3.c:180,2252000/0708/sys/src/9/pc/vgas3.c:180,185 (short | long)
1994/0803    
} 
 
static void 
1997/1101    
s3enable(VGAscr* scr) 
1997/0327    
{ 
1999/1005    
	int i; 
1997/1101    
	ulong storage; 
1994/0803    
                 
1997/1101    
	s3disable(scr); 
1994/0803    
                 
	/* 
	 * Cursor colours. Set both the CR0[EF] and the colour 
	 * stack in case we are using a 16-bit RAMDAC. 
	 */ 
1995/0126    
	vgaxo(Crtx, 0x0E, Pwhite); 
	vgaxo(Crtx, 0x0F, Pblack); 
1994/0803    
	vgaxi(Crtx, 0x45); 
                 
1999/1005    
	for(i = 0; i < 3; i++) 
		vgaxo(Crtx, 0x4A, Pblack); 
	vgaxi(Crtx, 0x45); 
	for(i = 0; i < 3; i++) 
		vgaxo(Crtx, 0x4B, Pwhite); 
1998/0116    
                 
1994/0803    
	/* 
	 * Find a place for the cursor data in display memory. 
	 * Must be on a 1024-byte boundary. 
	 */ 
1997/1101    
	storage = (scr->gscreen->width*BY2WD*scr->gscreen->r.max.y+1023)/1024; 
2000/0612    
	vgaxo(Crtx, 0x4C, storage>>8); 
1994/0803    
	vgaxo(Crtx, 0x4D, storage & 0xFF); 
	storage *= 1024; 
1997/1101    
	scr->storage = storage; 
1994/0803    
                 
	/* 
1998/0116    
	 * Enable the cursor in Microsoft Windows format. 
1994/0803    
	 */ 
1998/0116    
	vgaxo(Crtx, 0x55, vgaxi(Crtx, 0x55) & ~0x10); 
1997/1101    
	s3vsyncactive(); 
1994/0803    
	vgaxo(Crtx, 0x45, 0x01); 
} 
                 
static void 
1997/1101    
s3load(VGAscr* scr, Cursor* curs) 
1994/0803    
{ 
1994/0804    
	uchar *p; 
2000/0701/sys/src/9/pc/vgas3.c:240,2462000/0708/sys/src/9/pc/vgas3.c:200,206
1999/1005    
	case 0xE18A:				/* ViRGE/[DG]X */ 
	case 0xE110:				/* ViRGE/GX2 */ 
	case 0xE13D:				/* ViRGE/VX */ 
2000/0701    
	case 0xE112:				/* Savage4/MX */ 
2000/0708    
	case 0xE112:				/* Savage4/IX-MV */ 
2000/0611    
	case 0xE122:				/* Savage4 */ 
1998/0116    
		p += scr->storage; 
		break; 
2000/0701/sys/src/9/pc/vgas3.c:288,2942000/0708/sys/src/9/pc/vgas3.c:248,254
1999/1005    
	case 0xE18A:				/* ViRGE/[DG]X */ 
	case 0xE110:				/* ViRGE/GX2 */ 
	case 0xE13D:				/* ViRGE/VX */ 
2000/0701    
	case 0xE112:				/* Savage4/MX */ 
2000/0708    
	case 0xE112:				/* Savage4/IX-MV */ 
2000/0611    
	case 0xE122:				/* Savage4 */ 
1998/0116    
		break; 
 
2000/0701/sys/src/9/pc/vgas3.c:341,3462000/0708/sys/src/9/pc/vgas3.c:301,349
1994/0804    
	vgaxo(Crtx, 0x48, (y>>8) & 0x07); 
1994/0803    
 
	return 0; 
2000/0708    
} 
 
static void 
s3enable(VGAscr* scr) 
{ 
	int i; 
	ulong storage; 
 
	s3disable(scr); 
 
	/* 
	 * Cursor colours. Set both the CR0[EF] and the colour 
	 * stack in case we are using a 16-bit RAMDAC. 
	 */ 
	vgaxo(Crtx, 0x0E, Pwhite); 
	vgaxo(Crtx, 0x0F, Pblack); 
	vgaxi(Crtx, 0x45); 
 
	for(i = 0; i < 3; i++) 
		vgaxo(Crtx, 0x4A, Pblack); 
	vgaxi(Crtx, 0x45); 
	for(i = 0; i < 3; i++) 
		vgaxo(Crtx, 0x4B, Pwhite); 
 
	/* 
	 * Find a place for the cursor data in display memory. 
	 * Must be on a 1024-byte boundary. 
	 */ 
	storage = (scr->gscreen->width*BY2WD*scr->gscreen->r.max.y+1023)/1024; 
	vgaxo(Crtx, 0x4C, storage>>8); 
	vgaxo(Crtx, 0x4D, storage & 0xFF); 
	storage *= 1024; 
	scr->storage = storage; 
 
	/* 
	 * Load, locate and enable the cursor 
	 * in Microsoft Windows format. 
	 */ 
	s3load(scr, &arrow); 
	s3move(scr, ZP); 
	vgaxo(Crtx, 0x55, vgaxi(Crtx, 0x55) & ~0x10); 
	s3vsyncactive(); 
	vgaxo(Crtx, 0x45, 0x01); 
1994/0803    
} 
 
1999/1005    
/* 
2000/0708/sys/src/9/pc/vgas3.c:197,2032000/0721/sys/src/9/pc/vgas3.c:197,203 (short | long)
1998/0116    
	switch(id){ 
1994/0803    
 
1999/0821    
	case 0xE131:				/* ViRGE */ 
1999/1005    
	case 0xE18A:				/* ViRGE/[DG]X */ 
2000/0721    
	case 0xE101:				/* ViRGE/[DG]X */ 
1999/1005    
	case 0xE110:				/* ViRGE/GX2 */ 
	case 0xE13D:				/* ViRGE/VX */ 
2000/0708    
	case 0xE112:				/* Savage4/IX-MV */ 
2000/0708/sys/src/9/pc/vgas3.c:213,2202000/0721/sys/src/9/pc/vgas3.c:213,220
1998/0116    
	} 
 
1994/0803    
	/* 
1998/0116    
	 * The cursor is set in Microsoft Windows format (the ViRGE/GX2 no 
	 * longer supports the X11 format) which gives the following truth table: 
2000/0721    
	 * The cursor is set in Microsoft Windows format (the ViRGE/GX2 doesn't 
	 * support the X11 format) which gives the following truth table: 
1994/0803    
	 *	and xor	colour 
1998/0116    
	 *	 0   0	background colour 
	 *	 0   1	foreground colour 
2000/0708/sys/src/9/pc/vgas3.c:245,2512000/0721/sys/src/9/pc/vgas3.c:245,251
1998/0116    
	switch(id){ 
 
1999/0821    
	case 0xE131:				/* ViRGE */ 
1999/1005    
	case 0xE18A:				/* ViRGE/[DG]X */ 
2000/0721    
	case 0xE101:				/* ViRGE/[DG]X */ 
1999/1005    
	case 0xE110:				/* ViRGE/GX2 */ 
	case 0xE13D:				/* ViRGE/VX */ 
2000/0708    
	case 0xE112:				/* Savage4/IX-MV */ 
2000/0721/sys/src/9/pc/vgas3.c:47,562000/0803/sys/src/9/pc/vgas3.c:47,56 (short | long)
1994/0803    
{ 
1998/0116    
	int id; 
 
	id = (vgaxi(Crtx, 0x30)<<8)|vgaxi(Crtx, 0x2E); 
2000/0803    
	id = (vgaxi(Crtx, 0x2D)<<8)|vgaxi(Crtx, 0x2E); 
1998/0116    
	switch(id){ 
 
	case 0xE110:				/* ViRGE/GX2 */ 
2000/0803    
	case 0x8A10:				/* ViRGE/GX2 */ 
1998/0116    
		break; 
 
	default: 
2000/0721/sys/src/9/pc/vgas3.c:91,982000/0803/sys/src/9/pc/vgas3.c:91,98
2000/0611    
		aperture = p->mem[i].bar & ~0x0F; 
		*size = p->mem[i].size; 
2000/0612    
 
		id = (vgaxi(Crtx, 0x30)<<8)|vgaxi(Crtx, 0x2E); 
		if(id == 0xE122){		/* find Savage4 mmio */ 
2000/0803    
		id = (vgaxi(Crtx, 0x2D)<<8)|vgaxi(Crtx, 0x2E); 
		if(id == 0x8A22){		/* find Savage4 mmio */ 
2000/0612    
			/* 
			 * We could assume that the MMIO registers 
			 * will be in the screen segment and just use 
2000/0721/sys/src/9/pc/vgas3.c:196,2072000/0803/sys/src/9/pc/vgas3.c:196,207
1998/0116    
	id = (vgaxi(Crtx, 0x30)<<8)|vgaxi(Crtx, 0x2E); 
	switch(id){ 
1994/0803    
 
1999/0821    
	case 0xE131:				/* ViRGE */ 
2000/0721    
	case 0xE101:				/* ViRGE/[DG]X */ 
1999/1005    
	case 0xE110:				/* ViRGE/GX2 */ 
	case 0xE13D:				/* ViRGE/VX */ 
2000/0708    
	case 0xE112:				/* Savage4/IX-MV */ 
2000/0611    
	case 0xE122:				/* Savage4 */ 
2000/0803    
	case 0x5631:				/* ViRGE */ 
	case 0x8A01:				/* ViRGE/[DG]X */ 
	case 0x8A10:				/* ViRGE/GX2 */ 
	case 0x883D:				/* ViRGE/VX */ 
	case 0x8A12:				/* Savage4/IX-MV */ 
	case 0x8A22:				/* Savage4 */ 
1998/0116    
		p += scr->storage; 
		break; 
 
2000/0721/sys/src/9/pc/vgas3.c:244,2552000/0803/sys/src/9/pc/vgas3.c:244,255
1994/0803    
 
1998/0116    
	switch(id){ 
 
1999/0821    
	case 0xE131:				/* ViRGE */ 
2000/0721    
	case 0xE101:				/* ViRGE/[DG]X */ 
1999/1005    
	case 0xE110:				/* ViRGE/GX2 */ 
	case 0xE13D:				/* ViRGE/VX */ 
2000/0708    
	case 0xE112:				/* Savage4/IX-MV */ 
2000/0611    
	case 0xE122:				/* Savage4 */ 
2000/0803    
	case 0x5631:				/* ViRGE */ 
	case 0x8A01:				/* ViRGE/[DG]X */ 
	case 0x8A10:				/* ViRGE/GX2 */ 
	case 0x883D:				/* ViRGE/VX */ 
	case 0x8A12:				/* Savage4/IX-MV */ 
	case 0x8A22:				/* Savage4 */ 
1998/0116    
		break; 
 
	default: 
2000/0721/sys/src/9/pc/vgas3.c:386,3972000/0803/sys/src/9/pc/vgas3.c:386,397
1999/1005    
	switch(scr->id){ 
	default: 
		panic("unknown scr->id in s3 waitforlinearfifo"); 
	case 0xE131:	/* ViRGE */ 
	case 0xE13D:	/* ViRGE/VX */ 
2000/0803    
	case 0x5631:	/* ViRGE */ 
	case 0x883D:	/* ViRGE/VX */ 
1999/1005    
		mask = 0x0F<<6; 
		val = 0x08<<6; 
		break; 
	case 0xE110:	/* ViRGE/GX2 */ 
2000/0803    
	case 0x8A10:	/* ViRGE/GX2 */ 
1999/1005    
		mask = 0x1F<<6; 
		val = 0x10<<6; 
		break; 
2000/0721/sys/src/9/pc/vgas3.c:542,5502000/0803/sys/src/9/pc/vgas3.c:542,550
1999/1005    
	 * above. 
	 */ 
	switch(id){ 
	case 0xE131:				/* ViRGE */ 
	case 0xE13D:				/* ViRGE/VX */ 
	case 0xE110:				/* ViRGE/GX2 */ 
2000/0803    
	case 0x5631:				/* ViRGE */ 
	case 0x883D:				/* ViRGE/VX */ 
	case 0x8A10:				/* ViRGE/GX2 */ 
1999/1005    
		scr->mmio = (ulong*)(scr->aperture+0x1000000); 
		scr->fill = hwfill; 
		scr->scroll = hwscroll; 
2000/0803/sys/src/9/pc/vgas3.c:193,1992000/0809/sys/src/9/pc/vgas3.c:193,199 (short | long)
1994/0809    
 
1998/0116    
	opage = 0; 
1997/1101    
	p = KADDR(scr->aperture); 
1998/0116    
	id = (vgaxi(Crtx, 0x30)<<8)|vgaxi(Crtx, 0x2E); 
2000/0809    
	id = (vgaxi(Crtx, 0x2D)<<8)|vgaxi(Crtx, 0x2E); 
1998/0116    
	switch(id){ 
1994/0803    
 
2000/0803    
	case 0x5631:				/* ViRGE */ 
2000/0803/sys/src/9/pc/vgas3.c:531,5372000/0809/sys/src/9/pc/vgas3.c:531,537
1999/1005    
{ 
	ulong id; 
 
	id = (vgaxi(Crtx, 0x30)<<8)|vgaxi(Crtx, 0x2E); 
2000/0809    
	id = (vgaxi(Crtx, 0x2D)<<8)|vgaxi(Crtx, 0x2E); 
1999/1005    
	scr->id = id; 
 
	/* 
2000/0809/sys/src/9/pc/vgas3.c:200,2062000/0820/sys/src/9/pc/vgas3.c:200,206 (short | long)
2000/0803    
	case 0x8A01:				/* ViRGE/[DG]X */ 
	case 0x8A10:				/* ViRGE/GX2 */ 
	case 0x883D:				/* ViRGE/VX */ 
	case 0x8A12:				/* Savage4/IX-MV */ 
2000/0820    
	case 0x8C12:				/* Savage4/IX-MV */ 
2000/0803    
	case 0x8A22:				/* Savage4 */ 
1998/0116    
		p += scr->storage; 
		break; 
2000/0809/sys/src/9/pc/vgas3.c:248,2542000/0820/sys/src/9/pc/vgas3.c:248,254
2000/0803    
	case 0x8A01:				/* ViRGE/[DG]X */ 
	case 0x8A10:				/* ViRGE/GX2 */ 
	case 0x883D:				/* ViRGE/VX */ 
	case 0x8A12:				/* Savage4/IX-MV */ 
2000/0820    
	case 0x8C12:				/* Savage4/IX-MV */ 
2000/0803    
	case 0x8A22:				/* Savage4 */ 
1998/0116    
		break; 
 
2000/0820/sys/src/9/pc/vgas3.c:12,172000/0903/sys/src/9/pc/vgas3.c:12,39 (short | long)
1999/0119    
#include <cursor.h> 
1994/0803    
#include "screen.h" 
 
2000/0903    
enum { 
	PCIS3		= 0x5333,		/* PCI VID */ 
 
	SAVAGE3D	= 0x8A20,	/* PCI DID */ 
	SAVAGE3DMV	= 0x8A21, 
	SAVAGE4		= 0x8A22, 
	SAVAGEMXMV	= 0x8C10, 
	SAVAGEMX	= 0x8C11, 
	SAVAGEIXMV	= 0x8C12, 
	SAVAGEIX	= 0x8C13, 
	SAVAGE2000	= 0x9102, 
 
	VIRGE		= 0x5631, 
	VIRGEGX2	= 0x8A10, 
	VIRGEDXGX	= 0x8A01, 
	VIRGEVX		= 0x883D, 
	VIRGEMX		= 0x8C01, 
	VIRGEMXP	= 0x8C03, 
 
	AURORA64VPLUS	= 0x8812, 
}; 
 
1997/1101    
static int 
s3pageset(VGAscr* scr, int page) 
1994/0803    
{ 
2000/0820/sys/src/9/pc/vgas3.c:50,562000/0903/sys/src/9/pc/vgas3.c:72,78
2000/0803    
	id = (vgaxi(Crtx, 0x2D)<<8)|vgaxi(Crtx, 0x2E); 
1998/0116    
	switch(id){ 
 
2000/0803    
	case 0x8A10:				/* ViRGE/GX2 */ 
2000/0903    
	case VIRGEGX2: 
1998/0116    
		break; 
 
	default: 
2000/0820/sys/src/9/pc/vgas3.c:78,842000/0903/sys/src/9/pc/vgas3.c:100,106
2000/0612    
	mmiosize = 0; 
	mmiobase = 0; 
	mmioname = nil; 
1997/1101    
	if(p = pcimatch(nil, 0x5333, 0)){ 
2000/0903    
	if(p = pcimatch(nil, PCIS3, 0)){ 
2000/0611    
		for(i=0; i<nelem(p->mem); i++){ 
			if(p->mem[i].size >= *size 
			&& ((p->mem[i].bar & ~0x0F) & (*align-1)) == 0) 
2000/0820/sys/src/9/pc/vgas3.c:92,982000/0903/sys/src/9/pc/vgas3.c:114,120
2000/0611    
		*size = p->mem[i].size; 
2000/0612    
 
2000/0803    
		id = (vgaxi(Crtx, 0x2D)<<8)|vgaxi(Crtx, 0x2E); 
		if(id == 0x8A22){		/* find Savage4 mmio */ 
2000/0903    
		if(id == SAVAGE4){		/* find Savage4 mmio */ 
2000/0612    
			/* 
			 * We could assume that the MMIO registers 
			 * will be in the screen segment and just use 
2000/0820/sys/src/9/pc/vgas3.c:108,1132000/0903/sys/src/9/pc/vgas3.c:130,136
2000/0612    
				if(p->mem[j].size==512*1024 || p->mem[j].size==16*1024*1024){ 
					mmiobase = p->mem[j].bar & ~0x0F; 
					mmiosize = 512*1024; 
2000/0903    
					scr->mmio = (ulong*)upamalloc(mmiobase, mmiosize, 16*1024*1024); 
2000/0612    
					mmioname = "savage4mmio"; 
					break; 
				} 
2000/0820/sys/src/9/pc/vgas3.c:196,2072000/0903/sys/src/9/pc/vgas3.c:219,230
2000/0809    
	id = (vgaxi(Crtx, 0x2D)<<8)|vgaxi(Crtx, 0x2E); 
1998/0116    
	switch(id){ 
1994/0803    
 
2000/0803    
	case 0x5631:				/* ViRGE */ 
	case 0x8A01:				/* ViRGE/[DG]X */ 
	case 0x8A10:				/* ViRGE/GX2 */ 
	case 0x883D:				/* ViRGE/VX */ 
2000/0820    
	case 0x8C12:				/* Savage4/IX-MV */ 
2000/0803    
	case 0x8A22:				/* Savage4 */ 
2000/0903    
	case VIRGE: 
	case VIRGEDXGX: 
	case VIRGEGX2: 
	case VIRGEVX:	 
	case SAVAGEIXMV: 
	case SAVAGE4: 
1998/0116    
		p += scr->storage; 
		break; 
 
2000/0820/sys/src/9/pc/vgas3.c:244,2552000/0903/sys/src/9/pc/vgas3.c:267,278
1994/0803    
 
1998/0116    
	switch(id){ 
 
2000/0803    
	case 0x5631:				/* ViRGE */ 
	case 0x8A01:				/* ViRGE/[DG]X */ 
	case 0x8A10:				/* ViRGE/GX2 */ 
	case 0x883D:				/* ViRGE/VX */ 
2000/0820    
	case 0x8C12:				/* Savage4/IX-MV */ 
2000/0803    
	case 0x8A22:				/* Savage4 */ 
2000/0903    
	case VIRGE: 
	case VIRGEDXGX: 
	case VIRGEGX2: 
	case VIRGEVX:	 
	case SAVAGEIXMV: 
	case SAVAGE4: 
1998/0116    
		break; 
 
	default: 
2000/0820/sys/src/9/pc/vgas3.c:526,5342000/0903/sys/src/9/pc/vgas3.c:549,559
2000/0326    
	vgaxo(Seqx, CursorSyncCtl, x); 
} 
 
2000/0903    
 
2000/0326    
static void 
1999/1005    
s3drawinit(VGAscr *scr) 
{ 
2000/0903    
	extern void savageinit(VGAscr*);	/* vgasavage.c */ 
1999/1005    
	ulong id; 
 
2000/0809    
	id = (vgaxi(Crtx, 0x2D)<<8)|vgaxi(Crtx, 0x2E); 
2000/0820/sys/src/9/pc/vgas3.c:542,5542000/0903/sys/src/9/pc/vgas3.c:567,583
1999/1005    
	 * above. 
	 */ 
	switch(id){ 
2000/0803    
	case 0x5631:				/* ViRGE */ 
	case 0x883D:				/* ViRGE/VX */ 
	case 0x8A10:				/* ViRGE/GX2 */ 
2000/0903    
	case VIRGE:				/* ViRGE */ 
	case VIRGEVX:				/* ViRGE/VX */ 
	case VIRGEGX2:				/* ViRGE/GX2 */ 
1999/1005    
		scr->mmio = (ulong*)(scr->aperture+0x1000000); 
		scr->fill = hwfill; 
		scr->scroll = hwscroll; 
2000/0326    
		/* scr->blank = hwblank; */ 
2000/0903    
		break; 
	case SAVAGE4: 
		savageinit(scr); 
		break; 
1999/1005    
	} 
} 
 
2000/0903/sys/src/9/pc/vgas3.c:567,5812000/0904/sys/src/9/pc/vgas3.c:567,586 (short | long)
1999/1005    
	 * above. 
	 */ 
	switch(id){ 
2000/0903    
	case VIRGE:				/* ViRGE */ 
	case VIRGEVX:				/* ViRGE/VX */ 
	case VIRGEGX2:				/* ViRGE/GX2 */ 
2000/0904    
	case VIRGE: 
	case VIRGEVX: 
	case VIRGEGX2: 
1999/1005    
		scr->mmio = (ulong*)(scr->aperture+0x1000000); 
		scr->fill = hwfill; 
		scr->scroll = hwscroll; 
2000/0326    
		/* scr->blank = hwblank; */ 
2000/0903    
		break; 
2000/0904    
	case SAVAGEIXMV: 
		scr->mmio = (ulong*)(scr->aperture+0x1000000); 
		savageinit(scr);	 
		break; 
2000/0903    
	case SAVAGE4: 
2000/0904    
		/* scr->mmio is set by s3linear */ 
2000/0903    
		savageinit(scr); 
		break; 
1999/1005    
	} 
2000/0904/sys/src/9/pc/vgas3.c:100,1062001/0405/sys/src/9/pc/vgas3.c:100,117 (short | long)
2000/0612    
	mmiosize = 0; 
	mmiobase = 0; 
	mmioname = nil; 
2000/0903    
	if(p = pcimatch(nil, PCIS3, 0)){ 
2001/0405    
 
	/* 
	 * S3 makes cards other than display controllers, so 
	 * look for the first S3 display controller (device class 3) 
	 * and not one of their sound cards. 
	 */ 
	p = nil; 
	while(p = pcimatch(p, PCIS3, 0)){ 
		if(p->ccrb == 0x03) 
			break; 
	} 
	if(p != nil){ 
2000/0611    
		for(i=0; i<nelem(p->mem); i++){ 
			if(p->mem[i].size >= *size 
			&& ((p->mem[i].bar & ~0x0F) & (*align-1)) == 0) 
2001/0405/sys/src/9/pc/vgas3.c:100,1172001/0527/sys/src/9/pc/vgas3.c:100,106 (short | long)
2000/0612    
	mmiosize = 0; 
	mmiobase = 0; 
	mmioname = nil; 
2001/0405    
                 
	/* 
	 * S3 makes cards other than display controllers, so 
	 * look for the first S3 display controller (device class 3) 
	 * and not one of their sound cards. 
	 */ 
	p = nil; 
	while(p = pcimatch(p, PCIS3, 0)){ 
		if(p->ccrb == 0x03) 
			break; 
	} 
	if(p != nil){ 
2001/0527    
	if(p = pcimatch(nil, PCIS3, 0)){ 
2000/0611    
		for(i=0; i<nelem(p->mem); i++){ 
			if(p->mem[i].size >= *size 
			&& ((p->mem[i].bar & ~0x0F) & (*align-1)) == 0) 
2001/0405/sys/src/9/pc/vgas3.c:170,1772001/0527/sys/src/9/pc/vgas3.c:159,165
1999/1005    
		print("warning (BUG): redefinition of aperture does not change s3screen segment\n"); 
1999/0716    
	memset(&seg, 0, sizeof(seg)); 
	seg.attr = SG_PHYSICAL; 
	seg.name = smalloc(NAMELEN); 
	snprint(seg.name, NAMELEN, "s3screen"); 
2001/0527    
	kstrdup(&seg.name, "s3screen"); 
1999/0716    
	seg.pa = aperture; 
	seg.size = osize; 
	addphysseg(&seg); 
2001/0405/sys/src/9/pc/vgas3.c:179,1862001/0527/sys/src/9/pc/vgas3.c:167,173
2000/0612    
	if(mmiosize){ 
		memset(&seg, 0, sizeof(seg)); 
		seg.attr = SG_PHYSICAL; 
		seg.name = smalloc(NAMELEN); 
		snprint(seg.name, NAMELEN, mmioname); 
2001/0527    
		kstrdup(&seg.name, mmioname); 
2000/0612    
		seg.pa = mmiobase; 
		seg.size = mmiosize; 
		addphysseg(&seg); 
Too many diffs (26 > 25). Stopping.


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