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

📄 vga.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
字号:
#include <u.h>#include <libc.h>#include <bio.h>#include "pci.h"#include "vga.h"enum {	NSeqx		= 0x05,	NCrtx		= 0x19,	NGrx		= 0x09,	NAttrx		= 0x15,};ucharvgai(long port){	uchar data;	switch(port){	case MiscR:	case Status0:	case Status1:	case FeatureR:	case PaddrW:	case Pdata:	case Pixmask:	case Pstatus:		data = inportb(port);		break;	default:		error("vgai(0x%4.4lX): unknown port\n", port);		/*NOTREACHED*/		data = 0xFF;		break;	}	return data;}ucharvgaxi(long port, uchar index){	uchar data;	switch(port){	case Seqx:	case Crtx:	case Grx:		outportb(port, index);		data = inportb(port+1);		break;	case Attrx:		/*		 * Allow processor access to the colour		 * palette registers. Writes to Attrx must		 * be preceded by a read from Status1 to		 * initialise the register to point to the		 * index register and not the data register.		 * Processor access is allowed by turning		 * off bit 0x20.		 */		inportb(Status1);		if(index < 0x10){			outportb(Attrx, index);			data = inportb(Attrx+1);			inportb(Status1);			outportb(Attrx, 0x20|index);		}		else{			outportb(Attrx, 0x20|index);			data = inportb(Attrx+1);		}		break;	default:		error("vgaxi(0x%4.4lx, 0x%2.2uX): unknown port\n", port, index);		/*NOTREACHED*/		data = 0xFF;		break;	}	return data;}voidvgao(long port, uchar data){	switch(port){	case MiscW:	case FeatureW:	case PaddrW:	case Pdata:	case Pixmask:	case PaddrR:		outportb(port, data);		break;	default:		error("vgao(0x%4.4lX, 0x%2.2uX): unknown port\n", port, data);		/*NOTREACHED*/		break;	}}voidvgaxo(long port, uchar index, uchar data){	switch(port){	case Seqx:	case Crtx:	case Grx:		/*		 * We could use an outport here, but some chips		 * (e.g. 86C928) have trouble with that for some		 * registers.		 */		outportb(port, index);		outportb(port+1, data);		break;	case Attrx:		inportb(Status1);		if(index < 0x10){			outportb(Attrx, index);			outportb(Attrx, data);			inportb(Status1);			outportb(Attrx, 0x20|index);		}		else{			outportb(Attrx, 0x20|index);			outportb(Attrx, data);		}		break;	default:		error("vgaxo(0x%4.4lX, 0x%2.2uX, 0x%2.2uX): unknown port\n",			port, index, data);		break;	}}static voidsnarf(Vga* vga, Ctlr* ctlr){	int i;	/*	 * Generic VGA registers:	 * 	misc, feature;	 *	sequencer;	 *	crt;	 *	graphics;	 *	attribute;	 *	palette.	 */	vga->misc = vgai(MiscR);	vga->feature = vgai(FeatureR);	for(i = 0; i < NSeqx; i++)		vga->sequencer[i] = vgaxi(Seqx, i);	for(i = 0; i < NCrtx; i++)		vga->crt[i] = vgaxi(Crtx, i);	for(i = 0; i < NGrx; i++)		vga->graphics[i] = vgaxi(Grx, i);	for(i = 0; i < NAttrx; i++)		vga->attribute[i] = vgaxi(Attrx, i);	if(dflag)		palette.snarf(vga, ctlr);	ctlr->flag |= Fsnarf;}static voidinit(Vga* vga, Ctlr* ctlr){	Mode *mode;	int vt, vde, vrs, vre;	ulong tmp;	mode = vga->mode;	memset(vga->sequencer, 0, NSeqx*sizeof(vga->sequencer[0]));	memset(vga->crt, 0, NCrtx*sizeof(vga->crt[0]));	memset(vga->graphics, 0, NGrx*sizeof(vga->graphics[0]));	memset(vga->attribute, 0, NAttrx*sizeof(vga->attribute[0]));	if(dflag)		memset(vga->palette, 0, sizeof(vga->palette));	/*	 * Misc. If both the horizontal and vertical sync polarity	 * options are set, use them. Otherwise use the defaults for	 * the given vertical size.	 */	vga->misc = 0x23;	if(mode->frequency == VgaFreq1)		vga->misc |= 0x04;	if(mode->hsync && mode->vsync){		if(mode->hsync == '-')			vga->misc |= 0x40;		if(mode->vsync == '-')			vga->misc |= 0x80;	}	else{		if(mode->y < 480)			vga->misc |= 0x40;		else if(mode->y < 400)			vga->misc |= 0x80;		else if(mode->y < 768)			vga->misc |= 0xC0;	}	/*	 * Sequencer	 */	vga->sequencer[0x00] = 0x03;	vga->sequencer[0x01] = 0x01;	vga->sequencer[0x02] = 0x0F;	vga->sequencer[0x03] = 0x00;	if(mode->z >= 8)		vga->sequencer[0x04] = 0x0A;	else		vga->sequencer[0x04] = 0x06;	/*	 * Crt. Most of the work here is in dealing	 * with field overflow.	 */	memset(vga->crt, 0, NCrtx);	vga->crt[0x00] = (mode->ht>>3)-5;	vga->crt[0x01] = (mode->x>>3)-1;	vga->crt[0x02] = (mode->shb>>3)-1;	/*	 * End Horizontal Blank is a 6-bit field, 5-bits	 * in Crt3, high bit in Crt5.	 */	tmp = mode->ehb>>3;	vga->crt[0x03] = 0x80|(tmp & 0x1F);	if(tmp & 0x20)		vga->crt[0x05] |= 0x80;	if(mode->shs == 0)		mode->shs = mode->shb;	vga->crt[0x04] = mode->shs>>3;	if(mode->ehs == 0)		mode->ehs = mode->ehb;	vga->crt[0x05] |= ((mode->ehs>>3) & 0x1F);	/*	 * Vertical Total is 10-bits, 8 in Crt6, the high	 * two bits in Crt7. What if vt is >= 1024? We hope	 * the specific controller has some more overflow	 * bits.	 *	 * Interlace: if 'v',  divide the vertical timing	 * values by 2.	 */	vt = mode->vt;	vde = mode->y;	vrs = mode->vrs;	vre = mode->vre;	if(mode->interlace == 'v'){		vt /= 2;		vde /= 2;		vrs /= 2;		vre /= 2;	}	tmp = vt-2;	vga->crt[0x06] = tmp;	if(tmp & 0x100)		vga->crt[0x07] |= 0x01;	if(tmp & 0x200)		vga->crt[0x07] |= 0x20;	tmp = vrs;	vga->crt[0x10] = tmp;	if(tmp & 0x100)		vga->crt[0x07] |= 0x04;	if(tmp & 0x200)		vga->crt[0x07] |= 0x80;	vga->crt[0x11] = 0x20|(vre & 0x0F);	tmp = vde-1;	vga->crt[0x12] = tmp;	if(tmp & 0x100)		vga->crt[0x07] |= 0x02;	if(tmp & 0x200)		vga->crt[0x07] |= 0x40;	vga->crt[0x15] = vrs;	if(vrs & 0x100)		vga->crt[0x07] |= 0x08;	if(vrs & 0x200)		vga->crt[0x09] |= 0x20;	vga->crt[0x16] = (vrs+1);	vga->crt[0x17] = 0x83;	tmp = ((vga->virtx*mode->z)/8);	if(tmp >= 512){		vga->crt[0x14] |= 0x60;		tmp /= 8;	}	else if(tmp >= 256){		vga->crt[0x17] |= 0x08;		tmp /= 4;	}	else{		vga->crt[0x17] |= 0x40;		tmp /= 2;	}	vga->crt[0x13] = tmp;	if(mode->x*mode->y*mode->z/8 > 64*1024)		vga->crt[0x17] |= 0x20;	vga->crt[0x18] = 0x7FF;	if(vga->crt[0x18] & 0x100)		vga->crt[0x07] |= 0x10;	if(vga->crt[0x18] & 0x200)		vga->crt[0x09] |= 0x40;	/*	 * Graphics	 */	memset(vga->graphics, 0, NGrx);	if((vga->sequencer[0x04] & 0x04) == 0)		vga->graphics[0x05] |= 0x10;	if(mode->z >= 8)		vga->graphics[0x05] |= 0x40;	vga->graphics[0x06] = 0x05;	vga->graphics[0x07] = 0x0F;	vga->graphics[0x08] = 0xFF;	/*	 * Attribute	 */	memset(vga->attribute, 0, NAttrx);	for(tmp = 0; tmp < 0x10; tmp++)		vga->attribute[tmp] = tmp;	vga->attribute[0x10] = 0x01;	if(mode->z >= 8)		vga->attribute[0x10] |= 0x40;	vga->attribute[0x11] = 0xFF;	vga->attribute[0x12] = 0x0F;	/*	 * Palette	 */	if(dflag)		palette.init(vga, ctlr);	ctlr->flag |= Finit;}static voidload(Vga* vga, Ctlr* ctlr){	int i;	/*	 * Reset the sequencer and leave it off.	 * Load the generic VGA registers:	 *	misc;	 *	sequencer (but not seq01, display enable);	 *	take the sequencer out of reset;	 *	take off write-protect on crt[0x00-0x07];	 *	crt;	 *	graphics;	 *	attribute;	 *	palette.	vgaxo(Seqx, 0x00, 0x00);	 */	vgao(MiscW, vga->misc);	for(i = 2; i < NSeqx; i++)		vgaxo(Seqx, i, vga->sequencer[i]);	/*vgaxo(Seqx, 0x00, 0x03);*/	vgaxo(Crtx, 0x11, vga->crt[0x11] & ~0x80);	for(i = 0; i < NCrtx; i++)		vgaxo(Crtx, i, vga->crt[i]);	for(i = 0; i < NGrx; i++)		vgaxo(Grx, i, vga->graphics[i]);	for(i = 0; i < NAttrx; i++)		vgaxo(Attrx, i, vga->attribute[i]);	if(dflag)		palette.load(vga, ctlr);	ctlr->flag |= Fload;}static voiddump(Vga* vga, Ctlr* ctlr){	int i;	printitem(ctlr->name, "misc");	printreg(vga->misc);	printitem(ctlr->name, "feature");	printreg(vga->feature);	printitem(ctlr->name, "sequencer");	for(i = 0; i < NSeqx; i++)		printreg(vga->sequencer[i]);	printitem(ctlr->name, "crt");	for(i = 0; i < NCrtx; i++)		printreg(vga->crt[i]);	printitem(ctlr->name, "graphics");	for(i = 0; i < NGrx; i++)		printreg(vga->graphics[i]);	printitem(ctlr->name, "attribute");	for(i = 0; i < NAttrx; i++)		printreg(vga->attribute[i]);	if(dflag)		palette.dump(vga, ctlr);	printitem(ctlr->name, "virtual");	Bprint(&stdout, "%ld %ld\n", vga->virtx, vga->virty);	printitem(ctlr->name, "panning");	Bprint(&stdout, "%s\n", vga->panning ? "on" : "off");	if(vga->f[0]){		printitem(ctlr->name, "clock[0] f");		Bprint(&stdout, "%9ld\n", vga->f[0]);		printitem(ctlr->name, "clock[0] d i m");		Bprint(&stdout, "%9ld %8ld       - %8ld\n",			vga->d[0], vga->i[0], vga->m[0]);		printitem(ctlr->name, "clock[0] n p q r");		Bprint(&stdout, "%9ld %8ld       - %8ld %8ld\n",			vga->n[0], vga->p[0], vga->q[0], vga->r[0]);	}	if(vga->f[1]){		printitem(ctlr->name, "clock[1] f");		Bprint(&stdout, "%9ld\n", vga->f[1]);		printitem(ctlr->name, "clock[1] d i m");		Bprint(&stdout, "%9ld %8ld       - %8ld\n",			vga->d[1], vga->i[1], vga->m[1]);		printitem(ctlr->name, "clock[1] n p q r");		Bprint(&stdout, "%9ld %8ld       - %8ld %8ld\n",			vga->n[1], vga->p[1], vga->q[1], vga->r[1]);	}	if(vga->vma || vga->vmb){		printitem(ctlr->name, "vm a b");		Bprint(&stdout, "%9lud %8lud\n", vga->vma, vga->vmb);	}	if(vga->vmz){		printitem(ctlr->name, "vmz");		Bprint(&stdout, "%9lud\n", vga->vmz);	}	printitem(ctlr->name, "apz");	Bprint(&stdout, "%9lud\n", vga->apz);	printitem(ctlr->name, "linear");	Bprint(&stdout, "%9d\n", vga->linear);}Ctlr generic = {	"vga",				/* name */	snarf,				/* snarf */	0,				/* options */	init,				/* init */	load,				/* load */	dump,				/* dump */};

⌨️ 快捷键说明

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