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

📄 mach64xx.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 2 页
字号:
	 *	 * For some reason, x gets stretched out if LCD stretching	 * is turned on. 	 */	x = ((double)memclk*640000.0) /		((double)vga->mode->frequency * (double)vga->mode->z);	if(mp->lcd[LCD_HorzStretch] & (1<<31))		x *= 4096.0 / (double)(mp->lcd[LCD_HorzStretch] & 0xFFFF);	trace("memclk %d... x %f...", memclk, x);	/*	 * We have 14 bits to specify x in.  Decide where to	 * put the decimal (err, binary) point by counting how	 * many significant bits are in the integer portion of x.	 */	t = x;	for(i=31; i>=0; i--)		if(t & (1<<i))			break;	xprec = i+1;	trace("t %lud... xprec %d...", t, xprec);	/*	 * The maximum FIFO size is the number of XCLKs per QWORD	 * multiplied by 32, for some reason.  We have 11 bits to	 * specify fifosz.	 */	fifosz = x * 32.0;	trace("fifosz %f...", fifosz);	t = fifosz;	for(i=31; i>=0; i--)		if(t & (1<<i))			break;	fprec = i+1;	trace("fprec %d...", fprec);	/*	 * Precision is specified as 3 less than the number of bits	 * in the integer part of x, and 5 less than the number of bits	 * in the integer part of fifosz.	 *	 * It is bounded by zero and seven.	 */	prec = (xprec-3 > fprec-5) ? xprec-3 : fprec-5;	if(prec < 0)		prec = 0;	if(prec > 7)		prec = 7;	xprec = prec+3;	fprec = prec+5;	trace("prec %d...", prec);	/*	 * Actual fifo size	 */	afifosz = (1<<fprec) / x;	if(afifosz > 32)		afifosz = 32;	fifooff = ceil(x*(afifosz-1));	/*	 * I am suspicious of this table, lifted from ATI docs,	 * because it doesn't agree with the Windows drivers.	 * We always get 0x0A for lat+2 while Windows uses 0x08.	 */	lat = looplatencytab[memtyp > 1][vga->vmz > 1*1024*1024];	trace("afifosz %d...fifooff %f...", afifosz, fifooff);	/*	 * Page fault clock	 */	t = mp->reg[MemCntl];	mem->trp = (t>>8)&3;	/* RAS precharge time */	mem->trcd = (t>>10)&3;	/* RAS to CAS delay */	mem->tcrd = (t>>12)&1;	/* CAS to RAS delay */	mem->tras = (t>>16)&7;	/* RAS low minimum pulse width */	pfc = mem->trp + 1 + mem->trcd + 1 + mem->tcrd;	trace("pfc %d...", pfc);	/*	 * Maximum random access cycle clock.	 */	ncycle = cyclesperqwordtab[memtyp > 1][vga->vmz > 1*1024*1024];	rcc = mem->trp + 1 + mem->tras + 1;	if(rcc < pfc+ncycle)		rcc = pfc+ncycle;	trace("rcc %d...", rcc);	fifoon = (rcc > floor(x)) ? rcc : floor(x);	fifoon += (3.0 * rcc) - 1 + pfc + ncycle;	trace("fifoon %f...\n", fifoon);	/*	 * Now finally put the bits together.	 * x is stored in a 14 bit field with xprec bits of integer.	 */	pw = x * (1<<(14-xprec));	mp->reg[DspConfig] = (ulong)pw | (((lat+2)&0xF)<<16) | ((prec&7)<<20);	/*	 * These are stored in an 11 bit field with fprec bits of integer.	 */	dspon  = (ushort)fifoon << (11-fprec);	dspoff = (ushort)fifooff << (11-fprec);	mp->reg[DspOnOff] = ((dspon&0x7ff) << 16) | (dspoff&0x7ff);}static voidinit(Vga* vga, Ctlr* ctlr){	Mode *mode;	Mach64xx *mp;	int p, x, y;	mode = vga->mode;	if((mode->x > 640 || mode->y > 480) && mode->z == 1)		error("%s: no support for 1-bit mode other than 640x480x1\n",			ctlr->name);	mp = vga->private;	if(mode->z > 8 && mp->pci == nil)		error("%s: no support for >8-bit color without PCI\n",			ctlr->name);	/*	 * Check for Rage chip	 */	switch (mp->reg[ConfigChipId]&0xffff) {		case ('G'<<8)|'B':	/* 4742: 264GT PRO */		case ('G'<<8)|'D':	/* 4744: 264GT PRO */		case ('G'<<8)|'I':	/* 4749: 264GT PRO */		case ('G'<<8)|'M':	/* 474D: Rage XL */		case ('G'<<8)|'P':	/* 4750: 264GT PRO */		case ('G'<<8)|'Q':	/* 4751: 264GT PRO */		case ('G'<<8)|'R':	/* 4752: */		case ('G'<<8)|'U':	/* 4755: 264GT DVD */		case ('G'<<8)|'V':	/* 4756: Rage2C */		case ('G'<<8)|'Z':	/* 475A: Rage2C */		case ('V'<<8)|'U':	/* 5655: 264VT3 */		case ('V'<<8)|'V':	/* 5656: 264VT4 */		case ('G'<<8)|'T':	/* 4754: 264GT[B] */		case ('V'<<8)|'T':	/* 5654: 264VT/GT/VTB */		case ('L'<<8)|'B':	/* 4C42: Rage LTPro AGP */		case ('L'<<8)|'I':	/* 4C49: 264LT PRO */		case ('L'<<8)|'M':	/* 4C4D: Rage Mobility */		case ('L'<<8)|'P':	/* 4C50: 264LT PRO */			ctlr->flag |= Uenhanced;			break;	}	/*	 * Always use VCLK2.	 */	clock(vga, ctlr);	mp->pll[PLLn2] = vga->n[0];	mp->pll[PLLp] &= ~(0x03<<(2*2));	switch(vga->p[0]){	case 1:	case 3:		p = 0;		break;	case 2:		p = 1;		break;	case 4:	case 6:		p = 2;		break;	case 8:	case 12:		p = 3;		break;	default:		p = 3;		break;	}	mp->pll[PLLp] |= p<<(2*2);	if ((1<<p) != vga->p[0])		mp->pll[PLLx] |= 1<<(4+2);	else		mp->pll[PLLx] &= ~(1<<(4+2));	mp->reg[ClockCntl] = 2;	mp->reg[ConfigCntl] = 0;	mp->reg[CrtcGenCntl] = 0x02000000|(mp->reg[CrtcGenCntl] & ~0x01400700);	switch(mode->z){	default:	case 1:		mp->reg[CrtcGenCntl] |= 0x00000100;		mp->reg[DpPixWidth] = 0x00000000;		break;	case 8:		mp->reg[CrtcGenCntl] |= 0x01000200;		mp->reg[DpPixWidth] = 0x00020202;		break;	case 15:		mp->reg[CrtcGenCntl] |= 0x01000300;		mp->reg[DpPixWidth] = 0x00030303;		break;	case 16:		mp->reg[CrtcGenCntl] |= 0x01000400;		mp->reg[DpPixWidth] = 0x00040404;		break;	case 24:		mp->reg[CrtcGenCntl] |= 0x01000500;		mp->reg[DpPixWidth] = 0x00050505;		break;	case 32:		mp->reg[CrtcGenCntl] |= 0x01000600;		mp->reg[DpPixWidth] = 0x00060606;		break;	}	mp->reg[HTotalDisp] = (((mode->x>>3)-1)<<16)|((mode->ht>>3)-1);	mp->reg[HSyncStrtWid] = (((mode->ehs - mode->shs)>>3)<<16)				|((mode->shs>>3)-1);	if(mode->hsync == '-')		mp->reg[HSyncStrtWid] |= 0x00200000;	mp->reg[VTotalDisp] = ((mode->y-1)<<16)|(mode->vt-1);	mp->reg[VSyncStrtWid] = ((mode->vre - mode->vrs)<<16)|(mode->vrs-1);	if(mode->vsync == '-')		mp->reg[VSyncStrtWid] |= 0x00200000;	mp->reg[IntCntl] = 0;	/*	 * This used to set it to (mode->x/(8*2))<<22 for depths < 8,	 * but from the manual that seems wrong to me.  -rsc	 */	mp->reg[OffPitch] = (vga->virtx/8)<<22;	mp->reg[OvrClr] = Pblack;	if(vga->linear && mode->z != 1)		ctlr->flag |= Ulinear;	/*	 * Heuristic fiddling on LT PRO.	 * Do this before setdsp so the stretching is right.	 */	if(mp->lcdon){		/* use non-shadowed registers */		mp->lcd[LCD_GenCtrl] &= ~0x00000404;		mp->lcd[LCD_ConfigPanel] |= 0x00004000;		mp->lcd[LCD_VertStretch] = 0;		y = ((mp->lcd[LCD_ExtVertStretch]>>11) & 0x7FF)+1;		if(mode->y < y){			x = (mode->y*1024)/y;			mp->lcd[LCD_VertStretch] = 0xC0000000|x;		}		mp->lcd[LCD_ExtVertStretch] &= ~0x00400400;		/*		 * The x value doesn't seem to be available on all		 * chips so intuit it from the y value which seems to		 * be reliable.		 */		mp->lcd[LCD_HorzStretch] &= ~0xC00000FF;		x = (mp->lcd[LCD_HorzStretch]>>20) & 0xFF;		if(x == 0){			switch(y){			default:				break;			case 480:				x = 640;				break;			case 600:				x = 800;				break;			case 768:				x = 1024;				break;			case 1024:				x = 1280;				break;			}		}		else			x = (x+1)*8;		if(mode->x < x){			x = (mode->x*4096)/x;			mp->lcd[LCD_HorzStretch] |= 0xC0000000|x;		}	}	if(ctlr->flag&Uenhanced)		setdsp(vga, ctlr);	ctlr->flag |= Finit;}static voidload(Vga* vga, Ctlr* ctlr){	Mach64xx *mp;	int i;	mp = vga->private;	/*	 * Unlock the CRTC and LCD registers.	 */	mp->iow32(mp, CrtcGenCntl, mp->ior32(mp, CrtcGenCntl)&~0x00400000);	if(mp->lcdon)		lcdw32(mp, LCD_GenCtrl, mp->lcd[LCD_GenCtrl]|0x80000000);	/*	 * Always use an aperture on a 16Mb boundary.	 */	if(ctlr->flag & Ulinear)		mp->reg[ConfigCntl] = ((vga->vmb/(4*1024*1024))<<4)|0x02;	mp->iow32(mp, ConfigCntl, mp->reg[ConfigCntl]);	mp->iow32(mp, GenTestCntl, 0);	mp->iow32(mp, GenTestCntl, 0x100);	if((ctlr->flag&Uenhanced) == 0)	  mp->iow32(mp, MemCntl, mp->reg[MemCntl] & ~0x70000);	mp->iow32(mp, BusCntl, mp->reg[BusCntl]);	mp->iow32(mp, HTotalDisp, mp->reg[HTotalDisp]);	mp->iow32(mp, HSyncStrtWid, mp->reg[HSyncStrtWid]);	mp->iow32(mp, VTotalDisp, mp->reg[VTotalDisp]);	mp->iow32(mp, VSyncStrtWid, mp->reg[VSyncStrtWid]);	mp->iow32(mp, IntCntl, mp->reg[IntCntl]);	mp->iow32(mp, OffPitch, mp->reg[OffPitch]);	if(mp->lcdon){		for(i=0; i<Nlcd; i++)			lcdw32(mp, i, mp->lcd[i]);	}	mp->iow32(mp, GenTestCntl, mp->reg[GenTestCntl]);	mp->iow32(mp, ConfigCntl, mp->reg[ConfigCntl]);	mp->iow32(mp, CrtcGenCntl, mp->reg[CrtcGenCntl]);	mp->iow32(mp, OvrClr, mp->reg[OvrClr]);	mp->iow32(mp, OvrWidLR, mp->reg[OvrWidLR]);	mp->iow32(mp, OvrWidTB, mp->reg[OvrWidTB]);	if(ctlr->flag&Uenhanced){	  mp->iow32(mp, DacRegs, mp->reg[DacRegs]);	  mp->iow32(mp, DacCntl, mp->reg[DacCntl]);	  mp->iow32(mp, CrtcGenCntl, mp->reg[CrtcGenCntl]&~0x02000000);	  mp->iow32(mp, DspOnOff, mp->reg[DspOnOff]);	  mp->iow32(mp, DspConfig, mp->reg[DspConfig]);	  mp->iow32(mp, CrtcGenCntl, mp->reg[CrtcGenCntl]);	  pllw(mp, PLLx, mp->pll[PLLx]);	}	pllw(mp, PLLn2, mp->pll[PLLn2]);	pllw(mp, PLLp, mp->pll[PLLp]);	pllw(mp, PLLn3, mp->pll[PLLn3]);	mp->iow32(mp, ClockCntl, mp->reg[ClockCntl]);	mp->iow32(mp, ClockCntl, 0x40|mp->reg[ClockCntl]);	mp->iow32(mp, DpPixWidth, mp->reg[DpPixWidth]);	if(vga->mode->z > 8){		int sh, i;		/*		 * We need to initialize the palette, since the DACs use it		 * in true color modes.  First see if the card supports an		 * 8-bit DAC.		 */		mp->iow32(mp, DacCntl, mp->reg[DacCntl] | 0x100);		if(mp->ior32(mp, DacCntl)&0x100){			/* card appears to support it */			vgactlw("palettedepth", "8");			mp->reg[DacCntl] |= 0x100;		}		if(mp->reg[DacCntl] & 0x100)			sh = 0;	/* 8-bit DAC */		else			sh = 2;	/* 6-bit DAC */		for(i=0; i<256; i++)			setpalette(i, i>>sh, i>>sh, i>>sh);	}	ctlr->flag |= Fload;}static voidpixelclock(Vga* vga, Ctlr* ctlr){	Mach64xx *mp;	ushort table, s;	int memclk, ref_freq, ref_divider, min_freq, max_freq;	int feedback, nmult, pd, post, value;	int clock;	/*	 * Find the pixel clock from the BIOS and current	 * settings. Lifted from the ATI-supplied example code.	 * The clocks stored in the BIOS table are in kHz/10.	 *	 * This is the clock LCDs use in vgadb to set the DSP	 * values.	 */	mp = vga->private;	/*	 * GetPLLInfo()	 */	table = *(ushort*)readbios(sizeof table, 0xc0048);	trace("rom table offset %uX\n", table);	table = *(ushort*)readbios(sizeof table, 0xc0000+table+16);	trace("freq table offset %uX\n", table);	s = *(ushort*)readbios(sizeof s, 0xc0000+table+18);	memclk = s*10000;	trace("memclk %ud\n", memclk);	s = *(ushort*)readbios(sizeof s, 0xc0000+table+8);	ref_freq = s*10000;	trace("ref_freq %ud\n", ref_freq);	s = *(ushort*)readbios(sizeof s, 0xc0000+table+10);	ref_divider = s;	trace("ref_divider %ud\n", ref_divider);	s = *(ushort*)readbios(sizeof s, 0xc0000+table+2);	min_freq = s*10000;	trace("min_freq %ud\n", min_freq);	s = *(ushort*)readbios(sizeof s, 0xc0000+table+4);	max_freq = s*10000;	trace("max_freq %ud\n", max_freq);	/*	 * GetDivider()	 */	pd = mp->pll[PLLp] & 0x03;	value = (mp->pll[PLLx] & 0x10)>>2;	trace("pd %uX value %uX (|%d)\n", pd, value, value|pd);	value |= pd;	post = 0;	switch(value){	case 0:		post = 1;		break;	case 1:		post = 2;		break;	case 2:		post = 4;		break;	case 3:		post = 8;		break;	case 4:		post = 3;		break;	case 5:		post = 0;		break;	case 6:		post = 6;		break;	case 7:		post = 12;		break;	}	trace("post = %d\n", post);	feedback = mp->pll[PLLn0];	if(mp->pll[PLLx] & 0x08)		nmult = 4;	else		nmult = 2;	clock = (ref_freq/10000)*nmult*feedback;	clock /= ref_divider*post;	clock *= 10000;	Bprint(&stdout, "%s pixel clock = %ud\n", ctlr->name, clock);}static void dumpmach64bios(Mach64xx*);static voiddump(Vga* vga, Ctlr* ctlr){	Mach64xx *mp;	int i, m, n, p;	double f;	static int first = 1;	if((mp = vga->private) == 0)		return;	Bprint(&stdout, "%s pci %p io %lux %s\n", ctlr->name,		mp->pci, mp->io, mp->ior32 == pciior32 ? "pciregs" : "ioregs");	if(mp->pci)		Bprint(&stdout, "%s ccru %ux\n", ctlr->name, mp->pci->ccru);	for(i = 0; i < Nreg; i++)		Bprint(&stdout, "%s %-*s%.8luX\n",			ctlr->name, 20, iorname[i], mp->reg[i]);	printitem(ctlr->name, "PLL");	for(i = 0; i < Npll; i++)		printreg(mp->pll[i]);	Bprint(&stdout, "\n");	switch(mp->reg[ConfigChipId] & 0xFFFF){	default:		break;	case ('L'<<8)|'B':		/* 4C42: Rage LTPro AGP */	case ('L'<<8)|'I':		/* 4C49: Rage 3D LTPro */	case ('L'<<8)|'M':		/* 4C4D: Rage Mobility */	case ('L'<<8)|'P':		/* 4C50: Rage 3D LTPro */		for(i = 0; i < Nlcd; i++)			Bprint(&stdout, "%s %-*s%.8luX\n",				ctlr->name, 20, lcdname[i], mp->lcd[i]);		break;	}	/*	 *     (2*r*n)	 * f = -------	 *	(m*p)	 */	m = mp->pll[2];	for(i = 0; i < 4; i++){		n = mp->pll[7+i];		p = (mp->pll[6]>>(i*2)) & 0x03;		p |= (mp->pll[11]>>(2+i)) & 0x04;		switch(p){		case 0:		case 1:		case 2:		case 3:			p = 1<<p;			break;		case 4+0:			p = 3;			break;		case 4+2:			p = 6;			break;		case 4+3:			p = 12;			break;		default:		case 4+1:			p = -1;			break;		}		if(m*p == 0)			Bprint(&stdout, "unknown VCLK%d\n", i);		else {			f = (2.0*RefFreq*n)/(m*p) + 0.5;			Bprint(&stdout, "%s VCLK%d\t%ud\n", ctlr->name, i, (int)f);		}	}	pixelclock(vga, ctlr);	if(first) {		first = 0;		dumpmach64bios(mp);	}}enum {	ClockFixed=0,	ClockIcs2595,	ClockStg1703,	ClockCh8398,	ClockInternal,	ClockAtt20c408,	ClockIbmrgb514};/* * mostly derived from the xfree86 probe routines. */static void dumpmach64bios(Mach64xx *mp){	int i, romtable, clocktable, freqtable, lcdtable, lcdpanel;	uchar bios[0x10000];	memmove(bios, readbios(sizeof bios, 0xC0000), sizeof bios);	/* find magic string */	for(i=0; i<1024; i++)		if(strncmp((char*)bios+i, " 761295520", 10) == 0)			break;	if(i==1024) {		Bprint(&stdout, "no ATI bios found\n");		return;	}	/* this is horribly endian dependent.  sorry. */	romtable = *(ushort*)(bios+0x48);	if(romtable+0x12 > sizeof(bios)) {		Bprint(&stdout, "couldn't find ATI rom table\n");		return;	}	clocktable = *(ushort*)(bios+romtable+0x10);	if(clocktable+0x0C > sizeof(bios)) {		Bprint(&stdout, "couldn't find ATI clock table\n");		return;	}	freqtable = *(ushort*)(bios+clocktable-2);	if(freqtable+0x20 > sizeof(bios)) {		Bprint(&stdout, "couldn't find ATI frequency table\n");		return;	}	Bprint(&stdout, "ATI BIOS rom 0x%x freq 0x%x clock 0x%x\n", romtable, freqtable, clocktable);	Bprint(&stdout, "clocks:");	for(i=0; i<16; i++)		Bprint(&stdout, " %d", *(ushort*)(bios+freqtable+2*i));	Bprint(&stdout, "\n");	Bprint(&stdout, "programmable clock: %d\n", bios[clocktable]);	Bprint(&stdout, "clock to program: %d\n", bios[clocktable+6]);	if(*(ushort*)(bios+clocktable+8) != 1430) {		Bprint(&stdout, "reference numerator: %d\n", *(ushort*)(bios+clocktable+8)*10);		Bprint(&stdout, "reference denominator: 1\n");	} else {		Bprint(&stdout, "default reference numerator: 157500\n");		Bprint(&stdout, "default reference denominator: 11\n");	}	switch(bios[clocktable]) {	case ClockIcs2595:		Bprint(&stdout, "ics2595\n");		Bprint(&stdout, "reference divider: %d\n", *(ushort*)(bios+clocktable+0x0A));		break;	case ClockStg1703:		Bprint(&stdout, "stg1703\n");		break;	case ClockCh8398:		Bprint(&stdout, "ch8398\n");		break;	case ClockInternal:		Bprint(&stdout, "internal clock\n");		Bprint(&stdout, "reference divider in plls\n");		break;	case ClockAtt20c408:		Bprint(&stdout, "att 20c408\n");		break;	case ClockIbmrgb514:		Bprint(&stdout, "ibm rgb514\n");		Bprint(&stdout, "clock to program = 7\n");		break;	default:		Bprint(&stdout, "unknown clock\n");		break;	}	USED(mp);	if(1 || mp->lcdpanelid) {		lcdtable = *(ushort*)(bios+0x78);		if(lcdtable+5 > sizeof bios || lcdtable+bios[lcdtable+5] > sizeof bios) {			Bprint(&stdout, "can't find lcd bios table\n");			goto NoLcd;		}		lcdpanel = *(ushort*)(bios+lcdtable+0x0A);		if(lcdpanel+0x1D > sizeof bios /*|| bios[lcdpanel] != mp->lcdpanelid*/) {			Bprint(&stdout, "can't find lcd bios table0\n");			goto NoLcd;		}		Bprint(&stdout, "panelid %d x %d y %d\n", bios[lcdpanel], *(ushort*)(bios+lcdpanel+0x19), *(ushort*)(bios+lcdpanel+0x1B));	}NoLcd:;}Ctlr mach64xx = {	"mach64xx",			/* name */	snarf,				/* snarf */	0,				/* options */	init,				/* init */	load,				/* load */	dump,				/* dump */};Ctlr mach64xxhwgc = {	"mach64xxhwgc",			/* name */	0,				/* snarf */	0,				/* options */	0,				/* init */	0,				/* load */	0,				/* dump */};

⌨️ 快捷键说明

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