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

📄 mga4xx.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 3 页
字号:
	for (i = 0; i < n; i++) {		k = (2*i+1)*Meg;		p[k] = 0;		p[k] = i+1;		*(mga->mmio + CACHEFLUSH) = 0;		x[i] = p[k];		trace("x[%d]=%d\n", i, x[i]);	}	for(i = 1; i < n; i++)		if(x[i] != i+1)			break;	vga->vmz = mga->fbsize = 2*i*Meg;	trace("probe found %d megabytes\n", 2*i);	crtcextset(mga, 3, crtcext3, 0xff);	ctlr->flag |= Fsnarf;}static voidoptions(Vga* vga, Ctlr* ctlr){	if(vga->virtx & 127)		vga->virtx = (vga->virtx+127)&~127;	ctlr->flag |= Foptions;}/* ************************************************************ */static void G450ApplyPFactor(Mga*, uchar ucP, ulong *pulFIn){	if(!(ucP & 0x40))	{		*pulFIn = *pulFIn / (2L << (ucP & 3));	}}static void G450RemovePFactor(Mga*, uchar ucP, ulong *pulFIn){	if(!(ucP & 0x40))	{		*pulFIn = *pulFIn * (2L << (ucP & 3));	}}static void G450CalculVCO(Mga*, ulong ulMNP, ulong *pulF){	uchar ucM, ucN;	ucM = (uchar)((ulMNP >> 16) & 0xff);	ucN = (uchar)((ulMNP >>  8) & 0xff);	*pulF = (27000 * (2 * (ucN + 2)) + ((ucM + 1) >> 1)) / (ucM + 1);	trace("G450CalculVCO: ulMNP %lx, pulF %ld\n", ulMNP, *pulF);}static void G450CalculDeltaFreq(Mga*, ulong ulF1, ulong ulF2, ulong *pulDelta){	if(ulF2 < ulF1)	{		*pulDelta = ((ulF1 - ulF2) * 1000) / ulF1;	}	else	{		*pulDelta = ((ulF2 - ulF1) * 1000) / ulF1;	}	trace("G450CalculDeltaFreq: ulF1 %ld, ulF2 %ld, pulDelta %ld\n", ulF1, ulF2, *pulDelta);}static void G450FindNextPLLParam(Mga* mga, ulong ulFout, ulong *pulPLLMNP){	uchar ucM, ucN, ucP, ucS;	ulong ulVCO, ulVCOMin;	ucM = (uchar)((*pulPLLMNP >> 16) & 0xff);	/* ucN = (uchar)((*pulPLLMNP >>  8) & 0xff); */	ucP = (uchar)(*pulPLLMNP &  0x43);	ulVCOMin = 256000;	if(ulVCOMin >= (255L * 8000))	{		ulVCOMin = 230000;	}	if((ucM == 9) && (ucP & 0x40))	{		*pulPLLMNP = 0xffffffff;	} else if (ucM == 9)	{		if(ucP)		{			ucP--;		}		else		{			ucP = 0x40;		}		ucM = 0;	}	else	{		ucM++;	}	ulVCO = ulFout;	G450RemovePFactor(mga, ucP, &ulVCO);	if(ulVCO < ulVCOMin)	{		*pulPLLMNP = 0xffffffff;	}	if(*pulPLLMNP != 0xffffffff)	{		ucN = (uchar)(((ulVCO * (ucM+1) + 27000)/(27000 * 2)) - 2);		ucS = 5;		if(ulVCO < 1300000) ucS = 4;		if(ulVCO < 1100000) ucS = 3;		if(ulVCO <  900000) ucS = 2;		if(ulVCO <  700000) ucS = 1;		if(ulVCO <  550000) ucS = 0;		ucP |= (uchar)(ucS << 3);		*pulPLLMNP &= 0xff000000;		*pulPLLMNP |= (ulong)ucM << 16;		*pulPLLMNP |= (ulong)ucN << 8;		*pulPLLMNP |= (ulong)ucP;	}}static void G450FindFirstPLLParam(Mga* mga, ulong ulFout, ulong *pulPLLMNP){	uchar ucP;	ulong ulVCO;	ulong ulVCOMax;	/* Default value */	ulVCOMax = 1300000;	if(ulFout > (ulVCOMax/2))	{		ucP = 0x40;		ulVCO = ulFout;	}	else	{		ucP = 3;		ulVCO = ulFout;		G450RemovePFactor(mga, ucP, &ulVCO);		while(ucP && (ulVCO > ulVCOMax))		{			ucP--;			ulVCO = ulFout;			G450RemovePFactor(mga, ucP, &ulVCO);		}	}	if(ulVCO > ulVCOMax)	{		*pulPLLMNP = 0xffffffff;	}	else	{		/* Pixel clock: 1 */		*pulPLLMNP = (1 << 24) + 0xff0000 + ucP;		G450FindNextPLLParam(mga, ulFout, pulPLLMNP);	}}static void G450WriteMNP(Mga* mga, ulong ulMNP){	if (0) trace("G450WriteMNP : 0x%lx\n", ulMNP);	dacset(mga, Dac_Xpixpllcm, (uchar)(ulMNP >> 16), 0xff);	dacset(mga, Dac_Xpixpllcn, (uchar)(ulMNP >>  8), 0xff);   	dacset(mga, Dac_Xpixpllcp, (uchar)ulMNP, 0xff);   }static void G450CompareMNP(Mga* mga, ulong ulFout, ulong ulMNP1,			    ulong ulMNP2, long *pulResult){	ulong ulFreq, ulDelta1, ulDelta2;	G450CalculVCO(mga, ulMNP1, &ulFreq);	G450ApplyPFactor(mga, (uchar) ulMNP1, &ulFreq);	G450CalculDeltaFreq(mga, ulFout, ulFreq, &ulDelta1);	G450CalculVCO(mga, ulMNP2, &ulFreq);	G450ApplyPFactor(mga, (uchar) ulMNP2, &ulFreq);	G450CalculDeltaFreq(mga, ulFout, ulFreq, &ulDelta2);	if(ulDelta1 < ulDelta2)	{		*pulResult = -1;	}	else if(ulDelta1 > ulDelta2)	{		*pulResult = 1;	}	else	{		*pulResult = 0;	}	if((ulDelta1 <= 5) && (ulDelta2 <= 5))	{		if((ulMNP1 & 0xff0000) < (ulMNP2 & 0xff0000))		{			*pulResult = -1;		}		else if((ulMNP1 & 0xff0000) > (ulMNP2 & 0xff0000))		{			*pulResult = 1;		}	}}static void G450IsPllLocked(Mga* mga, int *lpbLocked){	ulong ulFallBackCounter, ulLockCount, ulCount;	uchar  ucPLLStatus;	/* Pixel PLL */	mgawrite8(mga, 0x3c00, 0x4f);    	ulFallBackCounter = 0;	do 	{		ucPLLStatus = mgaread8(mga, 0x3c0a);		if (0) trace("ucPLLStatus[1] : 0x%x\n", ucPLLStatus);		ulFallBackCounter++;	} while(!(ucPLLStatus & 0x40) && (ulFallBackCounter < 1000));	ulLockCount = 0;	if(ulFallBackCounter < 1000)	{		for(ulCount = 0; ulCount < 100; ulCount++)		{			ucPLLStatus = mgaread8(mga, 0x3c0a);			if (0) trace("ucPLLStatus[2] : 0x%x\n", ucPLLStatus);			if(ucPLLStatus & 0x40)			{				ulLockCount++;			}		}	}	*lpbLocked = ulLockCount >= 90;}static void G450SetPLLFreq(Mga* mga, long f_out) {	int bFoundValidPLL;	int bLocked;	ulong ulMaxIndex;	ulong ulMNP;	ulong ulMNPTable[MNP_TABLE_SIZE];	ulong ulIndex;	ulong ulTryMNP;	long lCompareResult;	trace("f_out : %ld\n", f_out);	G450FindFirstPLLParam(mga, f_out, &ulMNP);	ulMNPTable[0] = ulMNP;	G450FindNextPLLParam(mga, f_out, &ulMNP);	ulMaxIndex = 1;	while(ulMNP != 0xffffffff)	{		int ulIndex;		int bSkipValue;		bSkipValue = FALSE;		if(ulMaxIndex == MNP_TABLE_SIZE)		{			G450CompareMNP(mga, f_out, ulMNP, ulMNPTable[MNP_TABLE_SIZE - 1],				       &lCompareResult);			if(lCompareResult > 0)			{				bSkipValue = TRUE;			}			else			{				ulMaxIndex--;			}		}		if(!bSkipValue)		{			for(ulIndex = ulMaxIndex; !bSkipValue && (ulIndex > 0); ulIndex--)			{				G450CompareMNP(mga, f_out, ulMNP, ulMNPTable[ulIndex - 1],					       &lCompareResult);				if(lCompareResult < 0)				{					ulMNPTable[ulIndex] = ulMNPTable[ulIndex - 1];				}				else				{					break;				}			}			ulMNPTable[ulIndex] = ulMNP;			ulMaxIndex++;		}		G450FindNextPLLParam(mga, f_out, &ulMNP);	}	bFoundValidPLL = FALSE;	ulMNP = 0;	for(ulIndex = 0; !bFoundValidPLL && (ulIndex < ulMaxIndex); ulIndex++)	{		ulTryMNP = ulMNPTable[ulIndex];		{			bLocked = TRUE;			if((ulMNPTable[ulIndex] & 0xff00) < 0x300 ||			   (ulMNPTable[ulIndex] & 0xff00) > 0x7a00)			{				bLocked = FALSE;			}			if(bLocked)			{				G450WriteMNP(mga, ulTryMNP - 0x300);				G450IsPllLocked(mga, &bLocked);			}     			if(bLocked)			{				G450WriteMNP(mga, ulTryMNP + 0x300);				G450IsPllLocked(mga, &bLocked);			}     			if(bLocked)			{				G450WriteMNP(mga, ulTryMNP - 0x200);				G450IsPllLocked(mga, &bLocked);			}     			if(bLocked)			{				G450WriteMNP(mga, ulTryMNP + 0x200);				G450IsPllLocked(mga, &bLocked);			}     			if(bLocked)			{				G450WriteMNP(mga, ulTryMNP - 0x100);				G450IsPllLocked(mga, &bLocked);			}     			if(bLocked)			{				G450WriteMNP(mga, ulTryMNP + 0x100);				G450IsPllLocked(mga, &bLocked);			}     			if(bLocked)			{				G450WriteMNP(mga, ulTryMNP);				G450IsPllLocked(mga, &bLocked);			}     			else if(!ulMNP)			{				G450WriteMNP(mga, ulTryMNP);				G450IsPllLocked(mga, &bLocked);				if(bLocked)				{					ulMNP = ulMNPTable[ulIndex]; 				}				bLocked = FALSE;			}			if(bLocked)			{				bFoundValidPLL = TRUE;			}		}	}	if(!bFoundValidPLL)	{		if(ulMNP)		{			G450WriteMNP(mga, ulMNP);		}		else		{			G450WriteMNP(mga, ulMNPTable[0]);		}	}}/* ************************************************************ *//*	calcclock - Calculate the PLL settings (m, n, p, s).*/static doubleg400_calcclock(Mga* mga, long Fneeded){	double	Fpll;	double	Fvco;	double 	Fref;	int		pixpll_m_min;	int		pixpll_m_max;	int		pixpll_n_min;	int		pixpll_n_max;	int		pixpll_p_max;	double 	Ferr, Fcalc;	int		m, n, p;		if (mga->devid == MGA4XX || mga->devid == MGA550) {		/* These values are taken from Matrox G400 Specification - p 4-91 */		Fref     		= 27000000.0;		pixpll_n_min 	= 7;		pixpll_n_max 	= 127;		pixpll_m_min	= 1;		pixpll_m_max	= 31;		pixpll_p_max 	= 7;	} else { 				/* MGA200 */		/* These values are taken from Matrox G200 Specification - p 4-77 */		//Fref     		= 14318180.0;		Fref     		= 27050500.0;		pixpll_n_min 	= 7;		pixpll_n_max 	= 127;		pixpll_m_min	= 1;		pixpll_m_max	= 6;		pixpll_p_max 	= 7;	}	Fvco = ( double ) Fneeded;	for (p = 0;  p <= pixpll_p_max && Fvco < mga->maxpclk; p = p * 2 + 1, Fvco *= 2.0)		;	mga->pixpll_p = p;	Ferr = Fneeded;	for ( m = pixpll_m_min ; m <= pixpll_m_max ; m++ )		for ( n = pixpll_n_min; n <= pixpll_n_max; n++ )		{ 			Fcalc = Fref * (n + 1) / (m + 1) ;			/*			 * Pick the closest frequency.			 */			if ( labs(Fcalc - Fvco) < Ferr ) {				Ferr = abs(Fcalc - Fvco);				mga->pixpll_m = m;				mga->pixpll_n = n;			}		}		Fvco = Fref * (mga->pixpll_n + 1) / (mga->pixpll_m + 1);	if (mga->devid == MGA4XX || mga->devid == MGA550) {		if ( (50000000.0 <= Fvco) && (Fvco < 110000000.0) )			mga->pixpll_p |= 0;			if ( (110000000.0 <= Fvco) && (Fvco < 170000000.0) )			mga->pixpll_p |= (1<<3);			if ( (170000000.0 <= Fvco) && (Fvco < 240000000.0) )			mga->pixpll_p |= (2<<3);			if ( (300000000.0 <= Fvco) )			mga->pixpll_p |= (3<<3);		} else {		if ( (50000000.0 <= Fvco) && (Fvco < 100000000.0) )			mga->pixpll_p |= 0;			if ( (100000000.0 <= Fvco) && (Fvco < 140000000.0) )			mga->pixpll_p |= (1<<3);			if ( (140000000.0 <= Fvco) && (Fvco < 180000000.0) )			mga->pixpll_p |= (2<<3);			if ( (250000000.0 <= Fvco) )			mga->pixpll_p |= (3<<3);		}		Fpll = Fvco / (p + 1);	return Fpll;}/* ************************************************************ */static voidinit(Vga* vga, Ctlr* ctlr){	Mode*	mode;	Mga*	mga;	double	Fpll;	Ctlr*	c;	int	i;	ulong	t;	int     bppShift;	mga = vga->private;	mode = vga->mode;	trace("mga mmio at %#p\n", mga->mmio);	ctlr->flag |= Ulinear;	/*	 * Set the right bppShitf based on depth	 */	switch(mode->z) {	case 8: 		bppShift = 0;		break;	case 16:		bppShift = 1;		break;	case 24:		bppShift = 0;		break;	case 32:		bppShift = 2;		break;	default:		bppShift = 0;		error("depth %d not supported !\n", mode->z);	}	if (mode->interlace)		error("interlaced mode not supported !\n");	trace("%s: Initializing mode %dx%dx%d on %s\n", ctlr->name, mode->x, mode->y, mode->z, mode->type);	trace("%s: Suggested Dot Clock : %d\n", 	ctlr->name, mode->frequency);	trace("%s: Horizontal Total = %d\n", 		ctlr->name, mode->ht);	trace("%s: Start Horizontal Blank = %d\n", ctlr->name, mode->shb);	trace("%s: End Horizontal Blank = %d\n", 	ctlr->name, mode->ehb);	trace("%s: Vertical Total = %d\n", 		ctlr->name, mode->vt);	trace("%s: Vertical Retrace Start = %d\n", 	ctlr->name, mode->vrs);	trace("%s: Vertical Retrace End = %d\n", 	ctlr->name, mode->vre);	trace("%s: Start Horizontal Sync = %d\n", 	ctlr->name, mode->shs);	trace("%s: End Horizontal Sync = %d\n", 	ctlr->name, mode->ehs);

⌨️ 快捷键说明

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