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

📄 vganeomagic.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"typedef struct CursorNM CursorNM;struct CursorNM {	int	enable;	int	x;	int	y;	int	colour1;	int	colour2;	int	addr;};static voidneomagicenable(VGAscr* scr){	Pcidev *p;	int curoff, vmsize;	ulong ioaddr;	ulong iosize;	/*	 * scr->mmio holds the virtual address of the cursor registers	 * in the MMIO space. This may need to change for older chips	 * which have the MMIO space offset in the framebuffer region.	 *	 * scr->io holds the offset into mmio of the CursorNM struct.	 */	if(scr->mmio)		return;	if(p = pcimatch(nil, 0x10C8, 0)){		switch(p->did){		case 0x0003:		/* MagicGraph 128ZV */			curoff = 0x100;			vmsize = 1152*1024;			ioaddr = (p->mem[0].bar & ~0x0F) + 0x200000;			iosize = 0x200000;			break;		case 0x0083:		/* MagicGraph 128ZV+ */			curoff = 0x100;			vmsize = 1152*1024;			ioaddr = p->mem[1].bar & ~0x0F;			iosize = p->mem[1].size;			break;		case 0x0004:		/* MagicGraph 128XD */			curoff = 0x100;			vmsize = 2048*1024;			ioaddr = p->mem[1].bar & ~0x0F;			iosize = p->mem[1].size;			break;		case 0x0005:		/* MagicMedia 256AV */			curoff = 0x1000;			vmsize = 2560*1024;			ioaddr = p->mem[1].bar & ~0x0F;			iosize = p->mem[1].size;			break;		case 0x0006:		/* MagicMedia 256ZX */			curoff = 0x1000;			vmsize = 4096*1024;			ioaddr = p->mem[1].bar & ~0x0F;			iosize = p->mem[1].size;			break;		default:			return;		}	}	else		return;	scr->pci = p;	scr->mmio = vmap(ioaddr, iosize);	if(scr->mmio == nil)		return;	addvgaseg("neomagicmmio", ioaddr, iosize);	/*	 * Find a place for the cursor data in display memory.	 * 2 cursor images might be needed, 1KB each so use the	 * last 2KB of the framebuffer.	 */	scr->storage = vmsize-2*1024;	scr->io = curoff;	vgalinearpci(scr);	if(scr->paddr)		addvgaseg("neomagicscreen", scr->paddr, scr->apsize);}static voidneomagiccurdisable(VGAscr* scr){	CursorNM *cursornm;	if(scr->mmio == 0)		return;	cursornm = (void*)((char*)scr->mmio + scr->io);	cursornm->enable = 0;}static voidneomagicinitcursor(VGAscr* scr, int xo, int yo, int index){	uchar *p;	uint p0, p1;	int x, y;	p = (uchar*)scr->vaddr;	p += scr->storage + index*1024;	for(y = yo; y < 16; y++){		p0 = scr->set[2*y];		p1 = scr->set[2*y+1];		if(xo){			p0 = (p0<<xo)|(p1>>(8-xo));			p1 <<= xo;		}		*p++ = p0;		*p++ = p1;		for(x = 16; x < 64; x += 8)			*p++ = 0x00;		p0 = scr->clr[2*y]|scr->set[2*y];		p1 = scr->clr[2*y+1]|scr->set[2*y+1];		if(xo){			p0 = (p0<<xo)|(p1>>(8-xo));			p1 <<= xo;		}		*p++ = p0;		*p++ = p1;		for(x = 16; x < 64; x += 8)			*p++ = 0x00;	}	while(y < 64+yo){		for(x = 0; x < 64; x += 8){			*p++ = 0x00;			*p++ = 0x00;		}		y++;	}}static voidneomagiccurload(VGAscr* scr, Cursor* curs){	CursorNM *cursornm;	if(scr->mmio == 0)		return;	cursornm = (void*)((char*)scr->mmio + scr->io);	cursornm->enable = 0;	memmove(&scr->Cursor, curs, sizeof(Cursor));	neomagicinitcursor(scr, 0, 0, 0);	cursornm->enable = 1;}static intneomagiccurmove(VGAscr* scr, Point p){	CursorNM *cursornm;	int addr, index, x, xo, y, yo;	if(scr->mmio == 0)		return 1;	cursornm = (void*)((char*)scr->mmio + scr->io);	index = 0;	if((x = p.x+scr->offset.x) < 0){		xo = -x;		x = 0;	}	else		xo = 0;	if((y = p.y+scr->offset.y) < 0){		yo = -y;		y = 0;	}	else		yo = 0;	if(xo || yo){		index = 1;		neomagicinitcursor(scr, xo, yo, index);	}	addr = ((scr->storage+(1024*index))>>10) & 0xFFF;	addr = ((addr & 0x00F)<<8)|((addr>>4) & 0xFF);	if(cursornm->addr != addr)		cursornm->addr = addr;	cursornm->x = x;	cursornm->y = y;	return 0;}static voidneomagiccurenable(VGAscr* scr){	CursorNM *cursornm;	neomagicenable(scr);	if(scr->mmio == 0)		return;	cursornm = (void*)((char*)scr->mmio + scr->io);	cursornm->enable = 0;	/*	 * Cursor colours.	 */	cursornm->colour1 = (Pblack<<16)|(Pblack<<8)|Pblack;	cursornm->colour2 = (Pwhite<<16)|(Pwhite<<8)|Pwhite;	/*	 * Load, locate and enable the 64x64 cursor.	 */	neomagiccurload(scr, &arrow);	neomagiccurmove(scr, ZP);	cursornm->enable = 1;}static int neomagicbltflags;/* registers */enum {	BltStat = 0,	BltCntl = 1,	XPColor = 2,	FGColor = 3,	BGColor = 4,	Pitch = 5,	ClipLT = 6,	ClipRB = 7,	SrcBitOff = 8,	SrcStartOff = 9,	DstStartOff = 11,	XYExt = 12,	PageCntl = 20,	PageBase,	PostBase,	PostPtr,	DataPtr,};/* flags */enum {	NEO_BS0_BLT_BUSY =	0x00000001,	NEO_BS0_FIFO_AVAIL =	0x00000002,	NEO_BS0_FIFO_PEND =	0x00000004,	NEO_BC0_DST_Y_DEC =	0x00000001,	NEO_BC0_X_DEC =		0x00000002,	NEO_BC0_SRC_TRANS =	0x00000004,	NEO_BC0_SRC_IS_FG =	0x00000008,	NEO_BC0_SRC_Y_DEC =	0x00000010,	NEO_BC0_FILL_PAT =	0x00000020,	NEO_BC0_SRC_MONO =	0x00000040,	NEO_BC0_SYS_TO_VID =	0x00000080,	NEO_BC1_DEPTH8 =	0x00000100,	NEO_BC1_DEPTH16 =	0x00000200,	NEO_BC1_DEPTH24 =	0x00000300,	NEO_BC1_X_320 =		0x00000400,	NEO_BC1_X_640 =		0x00000800,	NEO_BC1_X_800 =		0x00000c00,	NEO_BC1_X_1024 =	0x00001000,	NEO_BC1_X_1152 =	0x00001400,	NEO_BC1_X_1280 =	0x00001800,	NEO_BC1_X_1600 =	0x00001c00,	NEO_BC1_DST_TRANS =	0x00002000,	NEO_BC1_MSTR_BLT =	0x00004000,	NEO_BC1_FILTER_Z =	0x00008000,	NEO_BC2_WR_TR_DST =	0x00800000,	NEO_BC3_SRC_XY_ADDR =	0x01000000,	NEO_BC3_DST_XY_ADDR =	0x02000000,	NEO_BC3_CLIP_ON =	0x04000000,	NEO_BC3_FIFO_EN =	0x08000000,	NEO_BC3_BLT_ON_ADDR =	0x10000000,	NEO_BC3_SKIP_MAPPING =	0x80000000,	NEO_MODE1_DEPTH8 =	0x0100,	NEO_MODE1_DEPTH16 =	0x0200,	NEO_MODE1_DEPTH24 =	0x0300,	NEO_MODE1_X_320 =	0x0400,	NEO_MODE1_X_640 =	0x0800,	NEO_MODE1_X_800 =	0x0c00,	NEO_MODE1_X_1024 =	0x1000,	NEO_MODE1_X_1152 =	0x1400,	NEO_MODE1_X_1280 =	0x1800,	NEO_MODE1_X_1600 =	0x1c00,	NEO_MODE1_BLT_ON_ADDR =	0x2000,};/* Raster Operations */enum {	GXclear =		0x000000,	/* 0x0000 */	GXand =			0x080000,	/* 0x1000 */	GXandReverse =		0x040000,	/* 0x0100 */	GXcopy =		0x0c0000,	/* 0x1100 */	GXandInvert =		0x020000,	/* 0x0010 */	GXnoop =		0x0a0000,	/* 0x1010 */	GXxor =			0x060000,	/* 0x0110 */	GXor =			0x0e0000,	/* 0x1110 */	GXnor =			0x010000,	/* 0x0001 */	GXequiv =		0x090000,	/* 0x1001 */	GXinvert =		0x050000,	/* 0x0101 */	GXorReverse =		0x0d0000,	/* 0x1101 */	GXcopyInvert =		0x030000,	/* 0x0011 */	GXorInverted =		0x0b0000,	/* 0x1011 */	GXnand =		0x070000,	/* 0x0111 */	GXset =			0x0f0000,	/* 0x1111 */};static voidwaitforidle(VGAscr *scr){	ulong *mmio;	long x;	mmio = scr->mmio;	x = 0;	while((mmio[BltStat] & NEO_BS0_BLT_BUSY) && x++ < 1000000)		;	//if(x >= 1000000)	//	iprint("idle stat %lud scrmmio %.8lux scr %p pc %luX\n", mmio[BltStat], scr->mmio, scr, getcallerpc(&scr));}static voidwaitforfifo(VGAscr *scr, int entries){	ulong *mmio;	long x;	mmio = scr->mmio;	x = 0;	while(((mmio[BltStat]>>8) < entries) && x++ < 1000000)		;	//if(x >= 1000000)	//	iprint("fifo stat %d scrmmio %.8lux scr %p pc %luX\n", mmio[BltStat]>>8, scr->mmio, scr, getcallerpc(&scr));	/* DirectFB says the above doesn't work.  if so... */	/* waitforidle(scr); */}static intneomagichwfill(VGAscr *scr, Rectangle r, ulong sval){	ulong *mmio;	mmio = scr->mmio;	waitforfifo(scr, 1);	mmio[FGColor] = sval;	waitforfifo(scr, 3);	mmio[BltCntl] = neomagicbltflags		| NEO_BC3_FIFO_EN		| NEO_BC0_SRC_IS_FG		| NEO_BC3_SKIP_MAPPING		| GXcopy;	mmio[DstStartOff] = scr->paddr		+ r.min.y*scr->gscreen->width*BY2WD		+ r.min.x*scr->gscreen->depth/BI2BY;	mmio[XYExt] = (Dy(r) << 16) | (Dx(r) & 0xffff);	waitforidle(scr);	return 1;}static intneomagichwscroll(VGAscr *scr, Rectangle r, Rectangle sr){	ulong *mmio;	int pitch, pixel;	mmio = scr->mmio;	pitch = scr->gscreen->width*BY2WD;	pixel = scr->gscreen->depth/BI2BY;	waitforfifo(scr, 4);	if (r.min.y < sr.min.y || (r.min.y == sr.min.y && r.min.x < sr.min.x)) {		/* start from upper-left */		mmio[BltCntl] = neomagicbltflags			| NEO_BC3_FIFO_EN			| NEO_BC3_SKIP_MAPPING			| GXcopy;		mmio[SrcStartOff] = scr->paddr			+ sr.min.y*pitch + sr.min.x*pixel;		mmio[DstStartOff] = scr->paddr			+ r.min.y*pitch + r.min.x*pixel;	} else {		/* start from lower-right */		mmio[BltCntl] = neomagicbltflags			| NEO_BC0_X_DEC			| NEO_BC0_DST_Y_DEC			| NEO_BC0_SRC_Y_DEC			| NEO_BC3_FIFO_EN			| NEO_BC3_SKIP_MAPPING			| GXcopy;		mmio[SrcStartOff] = scr->paddr			+ (sr.max.y-1)*pitch + (sr.max.x-1)*pixel;		mmio[DstStartOff] = scr->paddr			+ (r.max.y-1)*pitch + (r.max.x-1)*pixel;	}	mmio[XYExt] = (Dy(r) << 16) | (Dx(r) & 0xffff);	waitforidle(scr);	return 1;}static voidneomagicdrawinit(VGAscr *scr){	ulong *mmio;	uint bltmode, pitch;	mmio = scr->mmio;	pitch = scr->gscreen->width*BY2WD;	neomagicbltflags = bltmode = 0;	switch(scr->gscreen->depth) {	case 8:		bltmode |= NEO_MODE1_DEPTH8;		neomagicbltflags |= NEO_BC1_DEPTH8;		break;	case 16:		bltmode |= NEO_MODE1_DEPTH16;		neomagicbltflags |= NEO_BC1_DEPTH16;		break;	case 24:	/* I can't get it to work, and XFree86 doesn't either. */	default:	/* give up */		return;	}	switch(Dx(scr->gscreen->r)) {	case 320:		bltmode |= NEO_MODE1_X_320;		neomagicbltflags |= NEO_BC1_X_320;		break;	case 640:		bltmode |= NEO_MODE1_X_640;		neomagicbltflags |= NEO_BC1_X_640;		break;	case 800:		bltmode |= NEO_MODE1_X_800;		neomagicbltflags |= NEO_BC1_X_800;		break;	case 1024:		bltmode |= NEO_MODE1_X_1024;		neomagicbltflags |= NEO_BC1_X_1024;		break;	case 1152:		bltmode |= NEO_MODE1_X_1152;		neomagicbltflags |= NEO_BC1_X_1152;		break;	case 1280:		bltmode |= NEO_MODE1_X_1280;		neomagicbltflags |= NEO_BC1_X_1280;		break;	case 1600:		bltmode |= NEO_MODE1_X_1600;		neomagicbltflags |= NEO_BC1_X_1600;		break;	default:		/* don't worry about it */		break;	}	waitforidle(scr);	mmio[BltStat] = bltmode << 16;	mmio[Pitch] = (pitch << 16) | (pitch & 0xffff);	scr->fill = neomagichwfill;	scr->scroll = neomagichwscroll;}VGAdev vganeomagicdev = {	"neomagic",	neomagicenable,	nil,	nil,	nil,	neomagicdrawinit,};VGAcur vganeomagiccur = {	"neomagichwgc",	neomagiccurenable,	neomagiccurdisable,	neomagiccurload,	neomagiccurmove,};

⌨️ 快捷键说明

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