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

📄 vgamach64xx.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 2 页
字号:
	iow32(scr, CurHVposn, (0<<16)|0);	iow32(scr, CurHVoff, ((64-16)<<16)|(64-16));	/*	 * Load, locate and enable the 64x64 cursor.	 */	mach64xxcurload(scr, &arrow);	mach64xxcurmove(scr, ZP);	iow32(scr, GenTestCntl, 0x80|r);}static voidwaitforfifo(VGAscr *scr, int entries){	int x;	x = 0;	while((ior32(scr, FifoStat)&0xFF) > (0x8000>>entries) && x++ < 1000000)		;	if(x >= 1000000)		iprint("fifo %d stat %.8lux %.8lux scrio %.8lux mmio %p scr %p pc %luX\n", entries, ior32(scr, FifoStat), scr->mmio[mmoffset[FifoStat]], scr->io, scr->mmio, scr, getcallerpc(&scr));}static voidwaitforidle(VGAscr *scr){	int x;	waitforfifo(scr, 16);	x = 0;	while((ior32(scr, GuiStat)&1) && x++ < 1000000)		;	if(x >= 1000000)		iprint("idle stat %.8lux %.8lux scrio %.8lux mmio %p scr %p pc %luX\n", ior32(scr, GuiStat), scr->mmio[mmoffset[GuiStat]], scr->io, scr->mmio, scr, getcallerpc(&scr));}static voidresetengine(VGAscr *scr){	ulong x;	x = ior32(scr, GenTestCntl);	iow32(scr, GenTestCntl, x&~0x100);	iow32(scr, GenTestCntl, x|0x100);	iow32(scr, BusCntl, ior32(scr, BusCntl)|0x00A00000);}static voidinit_overlayclock(VGAscr *scr){	uchar *cc, save, pll_ref_div, pll_vclk_cntl, vclk_post_div, 			vclk_fb_div, ecp_div;	int i;	ulong dotclock;	/* Taken from GLX */	/* Get monitor dotclock, check for Overlay Scaler clock limit */ 	cc = (uchar *)&scr->mmio[mmoffset[ClockCntl]];  	save = cc[1]; i = cc[0] & 3;  	cc[1] = 2<<2; pll_ref_div = cc[2];  	cc[1] = 5<<2; pll_vclk_cntl = cc[2];  	cc[1] = 6<<2; vclk_post_div = (cc[2]>>(i+i)) & 3;  	cc[1] = (7+i)<<2; vclk_fb_div = cc[2];	dotclock = 2 * mach64refclock * vclk_fb_div / 			(pll_ref_div * (1 << vclk_post_div));	/* ecp_div: 0=dotclock, 1=dotclock/2, 2=dotclock/4 */  	ecp_div = dotclock / mach64type->m64_ovlclock;  	if (ecp_div>2) ecp_div = 2;  	/* Force a scaler clock factor of 1 if refclock *   	  * is unknown (VCLK_SRC not PLLVCLK)  */  	if ((pll_vclk_cntl & 0x03) != 0x03) 		ecp_div = 0;  	if ((pll_vclk_cntl & 0x30) != ecp_div<<4) {    		cc[1] = (5<<2)|2;    		cc[2] = (pll_vclk_cntl&0xCF) | (ecp_div<<4);	}  	/* Restore PLL Register Index */  	cc[1] = save;}static voidinitengine(VGAscr *scr){	ulong pitch;	uchar *bios;	ushort table;	pitch = Dx(scr->gscreen->r)/8;	if(scr->gscreen->depth == 24)		pitch *= 3;	resetengine(scr);	waitforfifo(scr, 14);	iow32(scr, ContextMask, ~0);	iow32(scr, DstOffPitch, pitch<<22);	iow32(scr, DstYX, 0);	iow32(scr, DstHeight, 0);	iow32(scr, DstBresErr, 0);	iow32(scr, DstBresInc, 0);	iow32(scr, DstBresDec, 0);	iow32(scr, DstCntl, 0x23);	iow32(scr, SrcOffPitch, pitch<<22);	iow32(scr, SrcYX, 0);	iow32(scr, SrcHeight1Width1, 1);	iow32(scr, SrcYXstart, 0);	iow32(scr, SrcHeight2Width2, 1);	iow32(scr, SrcCntl, 0x01);	waitforfifo(scr, 13);	iow32(scr, HostCntl, 0);	iow32(scr, PatReg0, 0);	iow32(scr, PatReg1, 0);	iow32(scr, PatCntl, 0);	iow32(scr, ScLeft, 0);	iow32(scr, ScTop, 0);	iow32(scr, ScBottom, 0xFFFF);	iow32(scr, ScRight, 0xFFFF);	iow32(scr, DpBkgdClr, 0);	iow32(scr, DpFrgdClr, ~0);	iow32(scr, DpWriteMask, ~0);	iow32(scr, DpMix, 0x70003);	iow32(scr, DpSrc, 0x00010100);	waitforfifo(scr, 3);	iow32(scr, ClrCmpClr, 0);	iow32(scr, ClrCmpMask, ~0);	iow32(scr, ClrCmpCntl, 0);	waitforfifo(scr, 2);	switch(scr->gscreen->depth){	case 8:	case 24:	/* [sic] */		iow32(scr, DpPixWidth, 0x00020202);		iow32(scr, DpChainMask, 0x8080);		break;	case 16:		iow32(scr, DpPixWidth, 0x00040404);		iow32(scr, DpChainMask, 0x8410);		break;	case 32:		iow32(scr, DpPixWidth, 0x00060606);		iow32(scr, DpChainMask, 0x8080);		break;	}	/* Get the base freq from the BIOS */	bios  = kaddr(0xC000);	table = *(ushort *)(bios + 0x48);	table = *(ushort *)(bios + table + 0x10);	switch (*(ushort *)(bios + table + 0x08)) {      	case 2700: 		mach64refclock = 270000; 		break;      	case 2863:       	case 2864: 		mach64refclock = 286363; 		break;      	case 2950: 		mach64refclock = 294989; 		break;    	case 1432: 	default:		mach64refclock = 143181; 		break ;		}		/* Figure out which revision this chip is */	switch ((scr->mmio[mmoffset[ConfigChipId]] >> 24) & 0xFF) {	case VTGTB1S1:	case GTB1U1:	case GTB1S2:	case GTB2U1:	case GTB2U2:	case GTB2U3:	case GTBC:	case GTIIIC1U1:	case GTIIIC1U2:	case GTIIIC2U1:	case GTIIIC2U2: 	case GTIIIC2U3: 	case LTPRO:			mach64revb = 1;			break;	default: 			mach64revb = 0;			break;	}	waitforidle(scr);}static intmach64hwfill(VGAscr *scr, Rectangle r, ulong sval){	ulong pitch;	ulong ctl;if(drawdebug)	iprint("hwfill %R val %lux...\n", r, sval);	/* shouldn't happen */	if(scr->io == 0x2EC || scr->io == 0x1C8 || scr->io == 0)		return 0;	pitch = Dx(scr->gscreen->r)/8;	ctl = 1|2;	/* left-to-right, top-to-bottom */	if(scr->gscreen->depth == 24){		r.min.x *= 3;		r.max.x *= 3;		pitch *= 3;		ctl |= (1<<7)|(((r.min.x/4)%6)<<8);	}	waitforfifo(scr, 11);	iow32(scr, DpFrgdClr, sval);	iow32(scr, DpWriteMask, 0xFFFFFFFF);	iow32(scr, DpMix, 0x00070003);	iow32(scr, DpSrc, 0x00000111);	iow32(scr, ClrCmpCntl, 0x00000000);	iow32(scr, ScLeftRight, 0x1FFF0000);	iow32(scr, ScTopBottom, 0x1FFF0000);	iow32(scr, DstOffPitch, pitch<<22);	iow32(scr, DstCntl, ctl);	iow32(scr, DstYX, (r.min.x<<16)|r.min.y);	iow32(scr, DstHeightWidth, (Dx(r)<<16)|Dy(r));	waitforidle(scr);	return 1;}static intmach64hwscroll(VGAscr *scr, Rectangle r, Rectangle sr){	ulong pitch;	Point dp, sp;	ulong ctl;	int dx, dy;	dx = Dx(r);	dy = Dy(r);	pitch = Dx(scr->gscreen->r)/8;	if(scr->gscreen->depth == 24){		dx *= 3;		pitch *= 3;		r.min.x *= 3;		sr.min.x *= 3;	}	ctl = 0;	if(r.min.x <= sr.min.x){		ctl |= 1;		dp.x = r.min.x;		sp.x = sr.min.x;	}else{		dp.x = r.min.x+dx-1;		sp.x = sr.min.x+dx-1;	}	if(r.min.y <= sr.min.y){		ctl |= 2;		dp.y = r.min.y;		sp.y = sr.min.y;	}else{		dp.y = r.min.y+dy-1;		sp.y = sr.min.y+dy-1;	}	if(scr->gscreen->depth == 24)		ctl |= (1<<7)|(((dp.x/4)%6)<<8);	waitforfifo(scr, 6);	iow32(scr, ScLeftRight, 0x1FFF0000);	iow32(scr, ScTopBottom, 0x1FFF0000);	iow32(scr, DpWriteMask, 0xFFFFFFFF);	iow32(scr, DpMix, 0x00070003);	iow32(scr, DpSrc, 0x00000300);	iow32(scr, ClrCmpCntl, 0x00000000);	waitforfifo(scr, 8);	iow32(scr, SrcOffPitch, pitch<<22);	iow32(scr, SrcCntl, 0x00000000);	iow32(scr, SrcYX, (sp.x<<16)|sp.y);	iow32(scr, SrcWidth1, dx);	iow32(scr, DstOffPitch, pitch<<22);	iow32(scr, DstCntl, ctl);	iow32(scr, DstYX, (dp.x<<16)|dp.y);	iow32(scr, DstHeightWidth, (dx<<16)|dy);	waitforidle(scr);	return 1;}/* * This should work, but doesn't. * It messes up the screen timings for some reason. */static voidmach64blank(VGAscr *scr, int blank){	ulong ctl;	ctl = ior32(scr, CrtcGenCtl) & ~(CrtcHsyncDis|CrtcVsyncDis);	if(blank)		ctl |= CrtcHsyncDis|CrtcVsyncDis;	iow32(scr, CrtcGenCtl, ctl);}/* * We squirrel away whether the LCD and/or CRT were * on when we were called to blank the screen, and * restore the old state.  If we are called to blank the * screen when it is already blank, we don't update the state. * Such a call sequence should not happen, though. * * We could try forcing the chip into power management * mode instead, but I'm not sure how that would interact * with screen updates going on while the screen is blanked. */static voidmach64lcdblank(VGAscr *scr, int blank){	static int crtlcd;	ulong x;	if(blank) {		x = lcdr32(scr, LCD_GenCtrl);		if(x & 3) {			crtlcd = x & 3;			lcdw32(scr, LCD_GenCtrl,  x&~3);		}	} else {		if(crtlcd == 0)			crtlcd = 2;	/* lcd only */		x = lcdr32(scr, LCD_GenCtrl);		lcdw32(scr, LCD_GenCtrl, x | crtlcd);	}}static voidmach64xxdrawinit(VGAscr *scr){	if(scr->io > 0x2FF){		initengine(scr);		scr->fill = mach64hwfill;		scr->scroll = mach64hwscroll;	}/*	scr->blank = mach64blank; */	switch(scr->id){	default:		break;	case ('L'<<8)|'B':		/* 4C42: Rage 3D LTPro */	case ('L'<<8)|'I':		/* 4C49: Rage 3D LTPro */	case ('L'<<8)|'M':		/* 4C4D: Rage Mobility */	case ('L'<<8)|'P':		/* 4C50: Rage 3D LTPro */		scr->blank = mach64lcdblank;		hwblank = 1;		break;	}}static voidovl_configure(VGAscr *scr, Chan *c, char **field){	int w, h;	char *format;	w = (int)strtol(field[1], nil, 0);	h = (int)strtol(field[2], nil, 0);	format = field[3];	if (c != ovl_chan) 		error(Einuse);	if (strcmp(format, "YUYV"))		error(Eunsupportedformat);		ovl_width  = w;	ovl_height = h;	ovl_fib       = w * h * sizeof(ushort);	waitforidle(scr);	scr->mmio[mmoffset[BusCntl]] |= 0x08000000;	/* Enable regblock 1 */	scr->mmio[mmoffset[OverlayScaleCntl]] = 		SCALE_ZERO_EXTEND|SCALE_RED_TEMP_6500K|		SCALE_HORZ_BLEND|SCALE_VERT_BLEND;	scr->mmio[mmoffset[!mach64revb? Buf0Pitch: ScalerBuf0Pitch]] = w;	scr->mmio[mmoffset[CaptureConfig]] = 		SCALER_FRAME_READ_MODE_FULL|		SCALER_BUF_MODE_SINGLE|		SCALER_BUF_NEXT_0;	scr->mmio[mmoffset[OverlayKeyCntl]] = !mach64revb?		OVERLAY_MIX_ALWAYS_V|(OVERLAY_EXCLUSIVE_NORMAL << 28): 		0x011;	if (mach64type->m64_pro) {		waitforfifo(scr, 6);		/* set the scaler co-efficient registers */		scr->mmio[mmoffset[ScalerColourCntl]] = 			(0x00) | (0x10 << 8) | (0x10 << 16);		scr->mmio[mmoffset[ScalerHCoef0]] = 			(0x00) | (0x20 << 8);		scr->mmio[mmoffset[ScalerHCoef1]] = 			(0x0D) | (0x20 << 8) | (0x06 << 16) | (0x0D << 24);		scr->mmio[mmoffset[ScalerHCoef2]] = 			(0x0D) | (0x1C << 8) | (0x0A << 16) | (0x0D << 24);		scr->mmio[mmoffset[ScalerHCoef3]] = 			(0x0C) | (0x1A << 8) | (0x0E << 16) | (0x0C << 24);		scr->mmio[mmoffset[ScalerHCoef4]] = 			(0x0C) | (0x14 << 8) | (0x14 << 16) | (0x0C << 24);	}		waitforfifo(scr, 3);	scr->mmio[mmoffset[VideoFormat]] = SCALE_IN_YVYU422 |		(!mach64revb? 0xC: 0);	if (mach64overlay == 0)		mach64overlay = scr->storage + 64 * 64 * sizeof(uchar);	scr->mmio[mmoffset[!mach64revb? Buf0Offset: ScalerBuf0Offset]] = 		mach64overlay;}static voidovl_enable(VGAscr *scr, Chan *c, char **field){	int x, y, w, h;	long h_inc, v_inc;	x = (int)strtol(field[1], nil, 0);	y = (int)strtol(field[2], nil, 0);	w = (int)strtol(field[3], nil, 0);	h = (int)strtol(field[4], nil, 0);	if (x < 0 || x + w > physgscreenr.max.x ||	     y < 0 || y + h > physgscreenr.max.y)		error(Ebadarg);	if (c != ovl_chan) 		error(Einuse);	if (scr->mmio[mmoffset[CrtcGenCntl]] & 1) {	/* double scan enable */		y *= 2;		h *= 2;	}	waitforfifo(scr, 2);	scr->mmio[mmoffset[OverlayYX]] = 			((x & 0xFFFF) << 16) | (y & 0xFFFF);	scr->mmio[mmoffset[OverlayYXEnd]] = 			(((x + w) & 0xFFFF) << 16) | ((y + h) & 0xFFFF);	h_inc = (ovl_width << 12) / (w >> 1);  /* ??? */	v_inc = (ovl_height << 12) / h;	waitforfifo(scr, 2);	scr->mmio[mmoffset[OverlayScaleInc]] = 			((h_inc & 0xFFFF) << 16) | (v_inc & 0xFFFF);	scr->mmio[mmoffset[ScalerHeightWidth]] = 			((ovl_width & 0xFFFF) << 16) | (ovl_height & 0xFFFF);	waitforidle(scr);	scr->mmio[mmoffset[OverlayScaleCntl]] |= 			(SCALE_ENABLE|OVERLAY_ENABLE);}static voidovl_status(VGAscr *scr, Chan *, char **field){	pprint("%s: %s %.4uX, VT/GT %s, PRO %s, ovlclock %d, rev B %s, refclock %ld\n",		   scr->dev->name, field[0], mach64type->m64_id,		   mach64type->m64_vtgt? "yes": "no",		   mach64type->m64_pro? "yes": "no",		   mach64type->m64_ovlclock,		   mach64revb? "yes": "no",		   mach64refclock);	pprint("%s: storage @%.8luX, aperture @%8.ulX, ovl buf @%.8ulX\n",		   scr->dev->name, scr->storage, scr->paddr,		   mach64overlay);}	static voidovl_openctl(VGAscr *, Chan *c, char **){	if (ovl_chan) 		error(Einuse);	ovl_chan = c;}static voidovl_closectl(VGAscr *scr, Chan *c, char **){	if (c != ovl_chan) return;	waitforidle(scr);	scr->mmio[mmoffset[OverlayScaleCntl]] &=			~(SCALE_ENABLE|OVERLAY_ENABLE);	ovl_chan = nil;	ovl_width = ovl_height = ovl_fib = 0;}enum{	CMclosectl,	CMconfigure,	CMenable,	CMopenctl,	CMstatus,};static void (*ovl_cmds[])(VGAscr *, Chan *, char **) ={	[CMclosectl]	ovl_closectl,	[CMconfigure]	ovl_configure,	[CMenable]	ovl_enable,	[CMopenctl]	ovl_openctl,	[CMstatus]	ovl_status,};static Cmdtab mach64xxcmd[] ={	CMclosectl,	"closectl",	1,	CMconfigure,	"configure",	4,	CMenable,	"enable",	5,	CMopenctl,	"openctl",	1,	CMstatus,	"status",	1,};static voidmach64xxovlctl(VGAscr *scr, Chan *c, void *a, int n){	Cmdbuf *cb;	Cmdtab *ct;	if(!mach64type->m64_vtgt) 		error(Enodev);	if(!scr->overlayinit){		scr->overlayinit = 1;		init_overlayclock(scr);	}	cb = parsecmd(a, n);	if(waserror()){		free(cb);		nexterror();	}	ct = lookupcmd(cb, mach64xxcmd, nelem(mach64xxcmd));	ovl_cmds[ct->index](scr, c, cb->f);	poperror();	free(cb);}static intmach64xxovlwrite(VGAscr *scr, void *a, int len, vlong offs){	uchar *src;	int _len;	if (ovl_chan == nil) return len;	/* Acts as a /dev/null */		/* Calculate the destination address */	_len = len;	src   = (uchar *)a;	while (len > 0) {		ulong _offs;		int nb;		_offs = (ulong)(offs % ovl_fib);		nb     = (_offs + len > ovl_fib)? ovl_fib - _offs: len;		memmove((uchar *)scr->vaddr + mach64overlay + _offs, 				  src, nb);		offs += nb;		src  += nb;		len  -= nb;	}	return _len;}VGAdev vgamach64xxdev = {	"mach64xx",	mach64xxenable,			/* enable */	0,				/* disable */	0,				/* page */	mach64xxlinear,			/* linear */	mach64xxdrawinit,	/* drawinit */	0,	mach64xxovlctl,	/* overlay control */	mach64xxovlwrite,	/* write the overlay */};VGAcur vgamach64xxcur = {	"mach64xxhwgc",	mach64xxcurenable,		/* enable */	mach64xxcurdisable,		/* disable */	mach64xxcurload,		/* load */	mach64xxcurmove,		/* move */	1					/* doespanning */};

⌨️ 快捷键说明

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