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

📄 mach64.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
字号:
#include <u.h>#include <libc.h>#include <bio.h>#include "pci.h"#include "vga.h"/* * ATI Mach64. Some hope. Kind of like a Mach32. * No support for accelerator so can only do up to 1024x768. * * All ATI Extended Registers are addressed using the modified index *	index = (0x02<<6)|(index & 0x3F); * so registers 0x00->0x3F map to 0x80->0xBF, but we will only ever * look at a few in the range 0xA0->0xBF. In this way we can stash * them in the vga->crt[] array. */enum {	Configcntl	= 0x6AEC,	/* Configuration control */	Configstat	= 0x72EC,	/* Configuration status */	Memcntl		= 0x52EC,	/* Memory control */	Scratch1	= 0x46EC,	/* Scratch Register (BIOS info) */};typedef struct {	ulong	configcntl;	ulong	configstat;	ulong	memcntl;	ulong	scratch1;} Mach64;/* * There are a number of possible clock generator chips for these * boards. We can divide any frequency by 2 (bit<6> of b8). */typedef struct {	ulong	frequency;	uchar	be;			/* <4> - bit<3> of frequency index */	uchar	b9;			/* <1> - bit<2> of frequency index */	uchar	genmo;			/* <3:2> - bits <1:0> of frequency index */} Pclk;enum {	Npclkx		= 16,		/* number of clock entries per table */};/* * ATI18811-0 */static Pclk ati188110[Npclkx] = {	{  42950000, 0x00, 0x00, 0x00 },	{  48770000, 0x00, 0x00, 0x04 },	{  92400000, 0x00, 0x00, 0x08 },	{  36000000, 0x00, 0x00, 0x0C },	{  50350000, 0x00, 0x02, 0x00 },	{  56640000, 0x00, 0x02, 0x04 },	{ 	  0, 0x00, 0x02, 0x08 },	{  44900000, 0x00, 0x02, 0x0C },	{  30240000, 0x10, 0x00, 0x00 },	{  32000000, 0x10, 0x00, 0x04 },	{ 110000000, 0x10, 0x00, 0x08 },	{  80000000, 0x10, 0x00, 0x0C },	{  39910000, 0x10, 0x02, 0x00 },	{  44900000, 0x10, 0x02, 0x04 },	{  75000000, 0x10, 0x02, 0x08 },	{  65000000, 0x10, 0x02, 0x0C },};/* * ATI18811-1, ATI18811-2 * PCLK_TABLE = 0 in Mach64 speak. */static Pclk ati188111[Npclkx] = {	{ 100000000, 0x00, 0x00, 0x00 },	{ 126000000, 0x00, 0x00, 0x04 },	{  92400000, 0x00, 0x00, 0x08 },	{  36000000, 0x00, 0x00, 0x0C },	{  50350000, 0x00, 0x02, 0x00 },	{  56640000, 0x00, 0x02, 0x04 },	{ 	  0, 0x00, 0x02, 0x08 },	{  44900000, 0x00, 0x02, 0x0C },	{ 135000000, 0x10, 0x00, 0x00 },	{  32000000, 0x10, 0x00, 0x04 },	{ 110000000, 0x10, 0x00, 0x08 },	{  80000000, 0x10, 0x00, 0x0C },	{  39910000, 0x10, 0x02, 0x00 },	{  44900000, 0x10, 0x02, 0x04 },	{  75000000, 0x10, 0x02, 0x08 },	{  65000000, 0x10, 0x02, 0x0C },};/* * ATI18818 * The first four entries are programmable and the default * settings are either those below or those below divided by 2 * (PCLK_TABLE = 1 and PCLK_TABLE = 2 respectively in Mach64 * speak). */static Pclk ati18818[Npclkx] = {	{  50350000, 0x00, 0x00, 0x00 },	{  56640000, 0x00, 0x00, 0x04 },	{  63000000, 0x00, 0x00, 0x08 },	{  72000000, 0x00, 0x00, 0x0C },	{  40000000, 0x00, 0x02, 0x00 },	{  44900000, 0x00, 0x02, 0x04 },	{  49500000, 0x00, 0x02, 0x08 },	{  50000000, 0x00, 0x02, 0x0C },	{ 	  0, 0x10, 0x00, 0x00 },	{ 110000000, 0x10, 0x00, 0x04 },	{ 126000000, 0x10, 0x00, 0x08 },	{ 135000000, 0x10, 0x00, 0x0C },	{ 	  0, 0x10, 0x02, 0x00 },	{  80000000, 0x10, 0x02, 0x04 },	{  75000000, 0x10, 0x02, 0x08 },	{  65000000, 0x10, 0x02, 0x0C },};static Pclk *pclkp;			/* which clock chip we are using */static ulong atix;			/* index to extended regsiters */static ucharatixi(uchar index){	outportb(atix, index);	return inportb(atix+1);}static voidatixo(uchar index, uchar data){	outportw(atix, (data<<8)|index);}static voidatixinit(Vga* vga, Ctlr*){	uchar b;	/*	 * Set the I/O address and offset for the ATI	 * extended registers to something we know about.	 */	if(atix == 0){		outportw(Grx, (0xCE<<8)|0x50);		outportw(Grx, (0x81<<8)|0x51);		atix = 0x1CE;	}	/*	 * Unlock the ATI Extended Registers.	 * We leave them unlocked from now on.	 * Why does this chip have so many	 * lock bits?	 */	if((b = atixi(0xB8)) & 0x3F)		atixo(0xB8, b & 0xC0);	b = atixi(0xAB);	atixo(0xAB, b & ~0x18);	atixo(0xB4, 0x00);	b = atixi(0xB9);	atixo(0xB9, b & ~0x80);	b = atixi(0xBE);	atixo(0xBE, b|0x09);	if(vga->private == 0)		vga->private = alloc(sizeof(Mach64));}static voidsnarf(Vga* vga, Ctlr* ctlr){	int i;	Mach64 *mach64;	atixinit(vga, ctlr);	for(i = 0xA0; i < 0xC0; i++)		vga->crt[i] = atixi(i);	mach64 = vga->private;	mach64->configcntl = inportl(Configcntl);	mach64->configstat = inportl(Configstat);	mach64->memcntl = inportl(Memcntl);	mach64->scratch1 = inportl(Scratch1);	/*	 * Memory size.	 */	switch(mach64->memcntl & 0x07){	case 0:		vga->vmz = 512*1024;		break;	case 1:		vga->vmz = 1024*1024;		break;	case 2:		vga->vmz = 2*1024*1024;		break;	case 3:		vga->vmz = 4*1024*1024;		break;	case 4:		vga->vmz = 6*1024*1024;		break;	case 5:		vga->vmz = 8*1024*1024;		break;	}	ctlr->flag |= Fsnarf;}static voidinit(Vga* vga, Ctlr* ctlr){	Mode *mode;	int f, divisor, index;	mode = vga->mode;	/*	 * Must somehow determine which clock chip to use here.	 * For now, punt and assume ATI18818.	 */	pclkp = ati18818;	if(pclkp == 0)		error("%s: can't determine clock chip\n", ctlr->name);	if(vga->f[0] == 0)		vga->f[0] = vga->mode->frequency;	/*	 * Find a clock frequency close to what we want.	 * 'Close' is within 1MHz.	 */	for(divisor = 0, index = 0; index < Npclkx; index++, divisor = 0){		divisor = 1;		f = pclkp[index].frequency/divisor;		if(f < vga->f[0]+1000000 && f >= vga->f[0]-1000000)			break;		divisor = 2;		f /= divisor;		if(f < vga->f[0]+1000000 && f >= vga->f[0]-1000000)			break;	}	if(divisor == 0)		error("%s: no suitable clock for %lud\n",			ctlr->name, vga->f[0]);	vga->d[0] = divisor;	vga->i[0] = index;	vga->crt[0xB0] &= 0xDA;	vga->crt[0xB1] &= 0x87;	vga->crt[0xB5] &= 0x7E;	vga->crt[0xB6] &= 0xE2;	vga->crt[0xB3] &= 0xAF;	vga->crt[0xA6] &= 0xFE;	vga->crt[0xA7] &= 0xF4;	/*	 * 256-colour linear addressing.	 */	if(mode->z == 8){		vga->graphics[0x05] = 0x00;		vga->attribute[0x10] &= ~0x40;		vga->crt[0x13] = (mode->x/8)/2;		vga->crt[0x14] = 0x00;		vga->crt[0x17] = 0xE3;		vga->crt[0xB0] |= 0x20;		vga->crt[0xB6] |= 0x04;	}	vga->attribute[0x11] = 0x00;	vga->crt[0xB6] |= 0x01;	vga->crt[0xBE] &= ~0x04;	/*	 * Do the clock index bits.	 */	vga->crt[0xB8] &= 0x3F;	vga->crt[0xB9] &= 0xFD;	vga->crt[0xBE] &= 0xE5;	if(vga->d[0] == 2)		vga->crt[0xB8] |= 0x40;	vga->crt[0xB9] |= pclkp[vga->i[0]].b9;	vga->crt[0xBE] |= pclkp[vga->i[0]].be;	vga->misc |= pclkp[vga->i[0]].genmo;	if(vga->mode->interlace == 'v')		vga->crt[0xBE] |= 0x02;	/*	 * Turn off 128Kb CPU address bit so	 * we only have a 64Kb aperture at 0xA0000.	 */	vga->crt[0xBD] &= ~0x04;	ctlr->type = mach32.name;	/*	 * The Mach64 can only address 1Mb in VGA mode	 */	vga->vmz = 1*1024*1024;	ctlr->flag |= Finit;}static voidload(Vga* vga, Ctlr* ctlr){	/*	 * We should probably do something here to make sure we that we	 * have access to all the video memory through the 64Kb VGA aperture	 * by disabling and linear aperture and memory boundary and then	 * enabling the VGA controller.	 * But for now, let's just assume it's ok, the Mach64 documentation	 * is just as clear as the Mach32 documentation.	 */	atixo(0xB0, vga->crt[0xB0]);	atixo(0xB1, vga->crt[0xB1]);	atixo(0xB5, vga->crt[0xB5]);	atixo(0xB6, vga->crt[0xB6]);	atixo(0xB3, vga->crt[0xB3]);	atixo(0xA6, vga->crt[0xA6]);	atixo(0xA7, vga->crt[0xA7]);	atixo(0xB8, vga->crt[0xB8]);	atixo(0xB9, vga->crt[0xB9]);	atixo(0xBE, vga->crt[0xBE]);	vgao(MiscW, vga->misc);	ctlr->flag |= Fload;}static voiddump(Vga* vga, Ctlr* ctlr){	int i;	Mach64 *mach64;	printitem(ctlr->name, "ATIX");	for(i = 0xA0; i < 0xC0; i++)		printreg(vga->crt[i]);	if((mach64 = vga->private) == 0)		return;	printitem(ctlr->name, "CONFIGCNTL");	Bprint(&stdout, "%.8lux\n", mach64->configcntl);	printitem(ctlr->name, "CONFIGSTAT");	Bprint(&stdout, "%.8lux\n", mach64->configstat);	printitem(ctlr->name, "MEMCNTL");	Bprint(&stdout, "%.8lux\n", mach64->memcntl);	printitem(ctlr->name, "SCRATCH1");	Bprint(&stdout, "%.8lux\n", mach64->scratch1);}Ctlr mach64 = {	"mach64",			/* name */	snarf,				/* snarf */	0,				/* options */	init,				/* init */	load,				/* load */	dump,				/* dump */};

⌨️ 快捷键说明

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