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

📄 3dfx.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
字号:
#include <u.h>#include <libc.h>#include <bio.h>#include "pci.h"#include "vga.h"/* * 3Dfx. */enum {	dramInit0		= 0x018/4,	dramInit1		= 0x01C/4,	vgaInit0		= 0x028/4,	pllCtrl0		= 0x040/4,	pllCtrl1		= 0x044/4,	pllCtrl2		= 0x048/4,	dacMode			= 0x04C/4,	vidProcCfg		= 0x05C/4,	vidScreenSize		= 0x098/4,	vidDesktopOverlayStride	= 0x0E8/4,	Nior			= 0x100/4,};typedef struct Tdfx {	ulong	io;	Pcidev*	pci;	ulong	r[Nior];} Tdfx;static ulongio32r(Tdfx* tdfx, int r){	return inportl(tdfx->io+(r*4));}static voidio32w(Tdfx* tdfx, int r, ulong l){	outportl(tdfx->io+(r*4), l);}static voidsnarf(Vga* vga, Ctlr* ctlr){	int i;	ulong v;	Tdfx *tdfx;	if(vga->private == nil){		tdfx = alloc(sizeof(Tdfx));		tdfx->pci = pcimatch(0, 0x121A, 0);		if(tdfx->pci == nil)			error("%s: not found\n", ctlr->name);		switch(tdfx->pci->did){		default:			error("%s: unknown chip - DID %4.4uX\n",				ctlr->name, tdfx->pci->did);			break;		case 0x0003:		/* Banshee */			vga->f[1] = 270000000;			break;		case 0x0005:		/* Avenger (a.k.a. Voodoo3) */			vga->f[1] = 300000000;			break;		case 0x0009:		/* Voodoo5 */			vga->f[1] = 350000000;			break;		}		/*		 * Frequency output of PLL's is given by		 *	fout = RefFreq*(n+2)/((m+2)*2^p)		 * where there are 6 bits for m, 8 bits for n		 * and 2 bits for p (k).		 */		vga->m[1] = 64;		vga->n[1] = 256;		vga->p[1] = 4;		if((v = (tdfx->pci->mem[2].bar & ~0x3)) == 0)			error("%s: I/O not mapped\n", ctlr->name);		tdfx->io = v;		vga->private = tdfx;	}	tdfx = vga->private;	vga->crt[0x1A] = vgaxi(Crtx, 0x1A);	vga->crt[0x1B] = vgaxi(Crtx, 0x1B);	for(i = 0; i < Nior; i++)		tdfx->r[i] = io32r(tdfx, i);	/*	 * If SDRAM then there's 16MB memory else it's SGRAM	 * and can count it based on the power-on straps -	 * chip size can be 8Mb or 16Mb, and there can be 4 or	 * 8 of them.	 */	vga->vma = tdfx->pci->mem[1].size;	if(tdfx->r[dramInit1] & 0x40000000)		vga->vmz = 16*1024*1024;	else{		if(tdfx->r[dramInit0] & 0x08000000)			i = 16*1024*1024/8;		else			i = 8*1024*1024/8;		if(tdfx->r[dramInit0] & 0x04000000)			i *= 8;		else			i *= 4;		vga->vmz = i;	}	ctlr->flag |= Fsnarf;}static voidoptions(Vga*, Ctlr* ctlr){	ctlr->flag |= Hlinear|Hclk2|Foptions;}static voidtdfxclock(Vga* vga, Ctlr*){	int d, dmin;	uint f, m, n, p;	dmin = vga->f[0];	for(m = 1; m < vga->m[1]; m++){		for(n = 1; n < vga->n[1]; n++){			f = (RefFreq*(n+2))/(m+2);			for(p = 0; p < vga->p[1]; p++){				d = vga->f[0] - (f/(1<<p));				if(d < 0)					d = -d;				if(d >= dmin)					continue;				dmin = d;				vga->m[0] = m;				vga->n[0] = n;				vga->p[0] = p;			}		}	}}static voidinit(Vga* vga, Ctlr* ctlr){	int x;	Mode *mode;	Tdfx *tdfx;	mode = vga->mode;	tdfx = vga->private;	if(vga->linear && (ctlr->flag & Hlinear))		ctlr->flag |= Ulinear;	/*	 * Clock bits. If the desired video clock is	 * one of the two standard VGA clocks or 50MHz it can just be	 * set using bits <3:2> of vga->misc, otherwise we	 * need to programme the PLL.	 */	if(vga->f[0] == 0)		vga->f[0] = mode->frequency;	vga->misc &= ~0x0C;	if(vga->f[0] == VgaFreq0){		/* nothing to do */;	}	else if(vga->f[0] == VgaFreq1)		vga->misc |= 0x04;	else if(vga->f[0] == 50000000)		vga->misc |= 0x08;	else{		if(vga->f[0] > vga->f[1])			error("%s: invalid pclk - %lud\n",				ctlr->name, vga->f[0]);		if(vga->f[0] > 135000000 && (ctlr->flag & Hclk2)){			if(mode->x%16)				error("%s: f > 135MHz requires (x%%16) == 0\n",					ctlr->name);			ctlr->flag |= Uclk2;		}		tdfxclock(vga, ctlr);		tdfx->r[pllCtrl0] = (vga->n[0]<<8)|(vga->m[0]<<2)|vga->p[0];		vga->misc |= 0x0C;	}	/*	 * Pixel format and memory stride.	 */	tdfx->r[vidScreenSize] = (mode->y<<12)|mode->x;	tdfx->r[vidProcCfg] = 0x00000081;	switch(mode->z){	default:		error("%s: %d-bit mode not supported\n", ctlr->name, mode->z);		break;	case 8:		tdfx->r[vidDesktopOverlayStride] = mode->x;		break;	case 16:		tdfx->r[vidDesktopOverlayStride] = mode->x*2;		tdfx->r[vidProcCfg] |= 0x00040400;		break;	case 32:		tdfx->r[vidDesktopOverlayStride] = mode->x*4;		tdfx->r[vidProcCfg] |= 0x000C0400;		break;	}	tdfx->r[vgaInit0] = 0x140;	/*	 * Adjust horizontal timing if doing two screen pixels per clock.	 */	tdfx->r[dacMode] = 0;	if(ctlr->flag & Uclk2){		vga->crt[0x00] = ((mode->ht/2)>>3)-5;		vga->crt[0x01] = ((mode->x/2)>>3)-1;		vga->crt[0x02] = ((mode->shb/2)>>3)-1;			x = (mode->ehb/2)>>3;		vga->crt[0x03] = 0x80|(x & 0x1F);		vga->crt[0x04] = (mode->shs/2)>>3;		vga->crt[0x05] = ((mode->ehs/2)>>3) & 0x1F;		if(x & 0x20)			vga->crt[0x05] |= 0x80;		tdfx->r[dacMode] |= 0x01;		tdfx->r[vidProcCfg] |= 0x04000000;	}	/*	 * Overflow.	 */	vga->crt[0x1A] = 0x00;	if(vga->crt[0x00] & 0x100)		vga->crt[0x1A] |= 0x01;	if(vga->crt[0x01] & 0x100)		vga->crt[0x1A] |= 0x04;	if(vga->crt[0x03] & 0x100)		vga->crt[0x1A] |= 0x10;	x = mode->ehb;	if(ctlr->flag & Uclk2)		x /= 2;	if((x>>3) & 0x40)		vga->crt[0x1A] |= 0x20;	if(vga->crt[0x04] & 0x100)		vga->crt[0x1A] |= 0x40;	x = mode->ehs;	if(ctlr->flag & Uclk2)		x /= 2;	if((x>>3) & 0x20)		vga->crt[0x1A] |= 0x80;	vga->crt[0x1B] = 0x00;	if(vga->crt[0x06] & 0x400)		vga->crt[0x1B] |= 0x01;	if(vga->crt[0x12] & 0x400)		vga->crt[0x1B] |= 0x04;	if(vga->crt[0x15] & 0x400)		vga->crt[0x1B] |= 0x10;	if(vga->crt[0x10] & 0x400)		vga->crt[0x1B] |= 0x40;	vga->attribute[0x11] = Pblack;	ctlr->flag |= Finit;}static voidload(Vga* vga, Ctlr* ctlr){	Tdfx *tdfx;	vgaxo(Crtx, 0x1A, vga->crt[0x1A]);	vgaxo(Crtx, 0x1B, vga->crt[0x1B]);	tdfx = vga->private;	io32w(tdfx, dacMode, tdfx->r[dacMode]);	io32w(tdfx, vidScreenSize, tdfx->r[vidScreenSize]);	io32w(tdfx, vidDesktopOverlayStride, tdfx->r[vidDesktopOverlayStride]);	io32w(tdfx, vidProcCfg, tdfx->r[vidProcCfg]);	io32w(tdfx, vgaInit0, tdfx->r[vgaInit0]);	if((vga->misc & 0x0C) == 0x0C)		io32w(tdfx, pllCtrl0, tdfx->r[pllCtrl0]);	ctlr->flag |= Fload;}static uintpllctrl(Tdfx* tdfx, int pll){	uint k, m, n, r;	r = tdfx->r[pllCtrl0+pll];	k = r & 0x03;	m = (r>>2) & 0x3F;	n = (r>>8) & 0xFF;	return (RefFreq*(n+2))/((m+2)*(1<<k));}static voiddump(Vga* vga, Ctlr* ctlr){	int i;	Tdfx *tdfx;	if((tdfx = vga->private) == nil)		return;	printitem(ctlr->name, "Crt1A");	printreg(vga->crt[0x1A]);	printreg(vga->crt[0x1B]);	Bprint(&stdout, "\n");	for(i = 0; i < Nior; i++)		Bprint(&stdout, "%s %2.2uX\t%.8luX\n",			ctlr->name, i*4, tdfx->r[i]);	printitem(ctlr->name, "pllCtrl");	Bprint(&stdout, "%9ud %8ud\n", pllctrl(tdfx, 0), pllctrl(tdfx, 1));}Ctlr tdfx = {	"3dfx",				/* name */	snarf,				/* snarf */	options,			/* options */	init,				/* init */	load,				/* load */	dump,				/* dump */};Ctlr tdfxhwgc = {	"3dfxhwgc",			/* name */	0,				/* snarf */	0,				/* options */	0,				/* init */	0,				/* load */	0,				/* dump */};

⌨️ 快捷键说明

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