⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vgas3.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
字号:
#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 {	PCIS3		= 0x5333,		/* PCI VID */	SAVAGE3D	= 0x8A20,		/* PCI DID */	SAVAGE3DMV	= 0x8A21,	SAVAGE4		= 0x8A22,	PROSAVAGEP	= 0x8A25,	PROSAVAGEK	= 0x8A26,	PROSAVAGE8	= 0x8D04,	SAVAGEMXMV	= 0x8C10,	SAVAGEMX	= 0x8C11,	SAVAGEIXMV	= 0x8C12,	SAVAGEIX	= 0x8C13,	SUPERSAVAGEIXC16 = 0x8C2E,	SAVAGE2000	= 0x9102,	VIRGE		= 0x5631,	VIRGEGX2	= 0x8A10,	VIRGEDXGX	= 0x8A01,	VIRGEVX		= 0x883D,	VIRGEMX		= 0x8C01,	VIRGEMXP	= 0x8C03,	VIRTUALPC2004	= 0x8810,	AURORA64VPLUS	= 0x8812,};static ints3pageset(VGAscr* scr, int page){	uchar crt35, crt51;	int opage;	crt35 = vgaxi(Crtx, 0x35);	if(scr->gscreen->depth >= 8){		/*		 * 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);		vgaxo(Crtx, 0x51, (crt51 & ~0x0C)|((page & 0x30)>>2));		opage = ((crt51 & 0x0C)<<2)|(crt35 & 0x0F);	}	else{		vgaxo(Crtx, 0x35, (page<<2) & 0x0C);		opage = (crt35>>2) & 0x03;	}	return opage;}static voids3page(VGAscr* scr, int page){	int id;	id = (vgaxi(Crtx, 0x2D)<<8)|vgaxi(Crtx, 0x2E);	switch(id){	case VIRGEGX2:		break;	default:		lock(&scr->devlock);		s3pageset(scr, page);		unlock(&scr->devlock);		break;	}}static voids3linear(VGAscr* scr, int, int){	int id, j;	ulong mmiobase, mmiosize;	Pcidev *p;		vgalinearpciid(scr, PCIS3, 0);	p = scr->pci;	if(scr->paddr == 0 || p == nil)		return;			addvgaseg("s3screen", scr->paddr, scr->apsize);		id = (vgaxi(Crtx, 0x2D)<<8)|vgaxi(Crtx, 0x2E);	switch(id){			/* find mmio */	case SAVAGE4:	case PROSAVAGEP:	case PROSAVAGEK:	case PROSAVAGE8:	case SUPERSAVAGEIXC16:		/*		 * 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((p->mem[j].bar&~0x0F) != scr->paddr)			if(p->mem[j].size==512*1024 || p->mem[j].size==16*1024*1024){				mmiobase = p->mem[j].bar & ~0x0F;				mmiosize = 512*1024;				scr->mmio = vmap(mmiobase, mmiosize);				if(scr->mmio == nil)					return;				addvgaseg("savagemmio", mmiobase, mmiosize);				break;			}		}	}}static voids3vsyncactive(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 voids3disable(VGAscr*){	uchar crt45;	/*	 * Turn cursor off.	 */	crt45 = vgaxi(Crtx, 0x45) & 0xFE;	s3vsyncactive();	vgaxo(Crtx, 0x45, crt45);}static voids3load(VGAscr* scr, Cursor* curs){	uchar *p;	int id, dolock, opage, x, y;	/*	 * Disable the cursor and	 * set the pointer to the two planes.	 */	s3disable(scr);	opage = 0;	p = scr->vaddr;	id = (vgaxi(Crtx, 0x2D)<<8)|vgaxi(Crtx, 0x2E);	switch(id){	case VIRTUALPC2004:	case VIRGE:	case VIRGEDXGX:	case VIRGEGX2:	case VIRGEVX:		case SAVAGEMXMV:	case SAVAGEIXMV:	case SAVAGE4:	case PROSAVAGEP:	case PROSAVAGEK:	case PROSAVAGE8:	case SUPERSAVAGEIXC16:		dolock = 0;		p += scr->storage;		break;	default:		dolock = 1;		lock(&scr->devlock);		opage = s3pageset(scr, scr->storage>>16);		p += (scr->storage & 0xFFFF);		break;	}	/*	 * The cursor is set in Microsoft Windows format (the ViRGE/GX2 doesn't	 * support the X11 format) which gives the following truth table:	 *	and xor	colour	 *	 0   0	background colour	 *	 0   1	foreground colour	 *	 1   0	current screen pixel	 *	 1   1	NOT current screen pixel	 * Put the cursor into the top-left of the 64x64 array.	 *	 * The cursor pattern in memory is interleaved words of	 * AND and XOR patterns.	 */	for(y = 0; y < 64; y++){		for(x = 0; x < 64/8; x += 2){			if(x < 16/8 && y < 16){				*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];			}			else {				*p++ = 0xFF;				*p++ = 0xFF;				*p++ = 0x00;				*p++ = 0x00;			}		}	}	if(dolock){		s3pageset(scr, opage);		unlock(&scr->devlock);	}	/*	 * Save the cursor hotpoint and enable the cursor.	 */	scr->offset = curs->offset;	s3vsyncactive();	vgaxo(Crtx, 0x45, 0x01);}static ints3move(VGAscr* scr, Point p){	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.	 * 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.	 */	if((x = p.x+scr->offset.x) < 0){		xo = -x;		xo = ((xo+1)/2)*2;		x = 0;	}	else		xo = 0;	if((y = p.y+scr->offset.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);	return 0;}static voids3enable(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);}/* * 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;	ulong lineartimeout;	ulong fifotimeout;	ulong idletimeout;} waitcount;static voidwaitforlinearfifo(VGAscr *scr){	ulong *mmio;	long x;	static ulong nwaitforlinearfifo;	ulong mask, val;	switch(scr->id){	default:		panic("unknown scr->id in s3 waitforlinearfifo");	case 0x8A01:	/* ViRGE/[DG]X.  XFree86 says no waiting necessary */		return;	case 0x5631:	/* ViRGE */	case 0x883D:	/* ViRGE/VX */		mask = 0x0F<<6;		val = 0x08<<6;		break;	case 0x8A10:	/* ViRGE/GX2 */		mask = 0x1F<<6;		val = 0x10<<6;		break;	}	mmio = scr->mmio;	x = 0;	while((mmio[FifoStat]&mask) != val && x++ < Maxloop)		waitcount.linear++;	if(x >= Maxloop)		waitcount.lineartimeout++;}static voidwaitforfifo(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++;	if(x >= Maxloop)		waitcount.fifotimeout++;}static voidwaitforidle(VGAscr *scr){	ulong *mmio;	long x;	mmio = scr->mmio;	x = 0;	while((mmio[SubStat]&0x3F00) != 0x3000 && x++ < Maxloop)		waitcount.idle++;	if(x >= Maxloop)		waitcount.idletimeout++;}static inthwscroll(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->paddr;	mmio[DstBase] = scr->paddr;	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 inthwfill(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->paddr;	mmio[DstBase] = scr->paddr;	mmio[DstBase] = scr->paddr;	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;}enum {	CursorSyncCtl = 0x0D,	/* in Seqx */	VsyncHi = 0x80,	VsyncLo = 0x40,	HsyncHi = 0x20,	HsyncLo = 0x10,};static voids3blank(VGAscr*, int blank){	uchar x;	x = vgaxi(Seqx, CursorSyncCtl);	x &= ~0xF0;	if(blank)		x |= VsyncLo | HsyncLo;	vgaxo(Seqx, CursorSyncCtl, x);}static voids3drawinit(VGAscr *scr){	extern void savageinit(VGAscr*);	/* vgasavage.c */	ulong id;	id = (vgaxi(Crtx, 0x2D)<<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.	 */	scr->blank = s3blank;	/* hwblank = 1;		not known to work well */	switch(id){	case VIRGE:	case VIRGEVX:	case VIRGEGX2:		scr->mmio = (ulong*)((char*)scr->vaddr+0x1000000);		scr->fill = hwfill;		scr->scroll = hwscroll;		break;	case SAVAGEMXMV:	case SAVAGEIXMV:		scr->mmio = (ulong*)((char*)scr->vaddr+0x1000000);		savageinit(scr);			break;	case SUPERSAVAGEIXC16:	case SAVAGE4:	case PROSAVAGEP:	case PROSAVAGE8:	case PROSAVAGEK:		/* scr->mmio is set by s3linear */		savageinit(scr);		break;	}}VGAdev vgas3dev = {	"s3",	0,	0,	s3page,	s3linear,	s3drawinit,};VGAcur vgas3cur = {	"s3hwgc",	s3enable,	s3disable,	s3load,	s3move,};

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -