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

📄 8253.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
字号:
#include "all.h"#include "mem.h"#include "ureg.h"#include "io.h"/* *  8253 timer */enum{	T0cntr	= 0x40,		/* counter ports */	T1cntr	= 0x41,		/* ... */	T2cntr	= 0x42,		/* ... */	Tmode	= 0x43,		/* mode port */	/* commands */	Latch0	= 0x00,		/* latch counter 0's value */	Load0	= 0x30,		/* load counter 0 with 2 bytes */	/* modes */	Square	= 0x36,		/* periodic square wave */	Trigger	= 0x30,		/* interrupt on terminal count */	Freq	= 1193182,	/* Real clock frequency */};static uvlong cpufreq	= 66000000;static uvlong cpuhz;static int cpumhz	= 66;static int loopconst	= 100;/*static*/ int cpuidax, cpuiddx;static char cpuidid[16];static int havetsc;static voidclockintr(Ureg *ur, void *v){	USED(v);	clock(0, ur->pc);}#define STEPPING(x)	((x)&0xf)#define MODEL(x)	(((x)>>4)&0xf)#define FAMILY(x)	(((x)>>8)&0xf)enum{	/* flags */	CpuidFPU	= 0x001,	/* on-chip floating point unit */	CpuidMCE	= 0x080,	/* machine check exception */	CpuidCX8	= 0x100,	/* CMPXCHG8B instruction */};typedef struct{	int family;	int model;	int aalcycles;	char *name;} X86type;static X86type x86intel[] ={	{ 4,	0,	22,	"486DX", },	/* known chips */	{ 4,	1,	22,	"486DX50", },	{ 4,	2,	22,	"486SX", },	{ 4,	3,	22,	"486DX2", },	{ 4,	4,	22,	"486SL", },	{ 4,	5,	22,	"486SX2", },	{ 4,	7,	22,	"DX2WB", },	/* P24D */	{ 4,	8,	22,	"DX4", },	/* P24C */	{ 4,	9,	22,	"DX4WB", },	/* P24CT */	{ 5,	0,	23,	"P5", },	{ 5,	1,	23,	"P5", },	{ 5,	2,	23,	"P54C", },	{ 5,	3,	23,	"P24T", },	{ 5,	4,	23,	"P55C MMX", },	{ 5,	7,	23,	"P54C VRT", },	{ 6,	1,	16,	"PentiumPro", },/* trial and error */	{ 6,	3,	16,	"PentiumII", },	{ 6,	5,	16,	"PentiumII/Xeon", },	{ 6,	6,	16,	"Celeron", },	{ 6,	7,	16,	"PentiumIII/Xeon", },	{ 6,	8,	16,	"PentiumIII/Xeon", },	{ 6,	0xB,	16,	"PentiumIII/Xeon", },	{ 0xF,	1,	16,	"P4", },	/* P4 */	{ 0xF,	2,	16,	"PentiumIV/Xeon", },	{ 3,	-1,	32,	"386", },	/* family defaults */	{ 4,	-1,	22,	"486", },	{ 5,	-1,	23,	"P5", },	{ 6,	-1,	16,	"P6", },	{ 0xF,	-1,	16,	"P4", },	/* P4 */	{ -1,	-1,	16,	"unknown", },	/* total default */};/* * The AMD processors all implement the CPUID instruction. * The later ones also return the processor name via functions * 0x80000002, 0x80000003 and 0x80000004 in registers AX, BX, CX * and DX: *	K5	"AMD-K5(tm) Processor" *	K6	"AMD-K6tm w/ multimedia extensions" *	K6 3D	"AMD-K6(tm) 3D processor" *	K6 3D+	? */static X86type x86amd[] ={	{ 5,	0,	23,	"AMD-K5", },	/* guesswork */	{ 5,	1,	23,	"AMD-K5", },	/* guesswork */	{ 5,	2,	23,	"AMD-K5", },	/* guesswork */	{ 5,	3,	23,	"AMD-K5", },	/* guesswork */	{ 5,	6,	11,	"AMD-K6", },	/* trial and error */	{ 5,	7,	11,	"AMD-K6", },	/* trial and error */	{ 5,	8,	11,	"AMD-K6-2", },	/* trial and error */	{ 5,	9,	11,	"AMD-K6-III", },/* trial and error */	{ 6,	1,	11,	"AMD-Athlon", },/* trial and error */	{ 6,	2,	11,	"AMD-Athlon", },/* trial and error */	{ 4,	-1,	22,	"Am486", },	/* guesswork */	{ 5,	-1,	23,	"AMD-K5/K6", },	/* guesswork */	{ 6,	-1,	11,	"AMD-Athlon", },/* guesswork */	{ 0xF,	-1,	11,	"AMD64", },	/* guesswork */	{ -1,	-1,	23,	"unknown", },	/* total default */};/* * WinChip 240MHz */static X86type x86winchip[] ={	{5,	4,	23,	"Winchip",},	/* guesswork */	{6,	7,	23,	"Via C3 Samuel 2 or Ezra",},	{6,	8,	23,	"Via C3 Ezra-T",},	{ -1,	-1,	23,	"unknown", },	/* total default */};/* * SiS 55x */static X86type x86sis[] ={	{5,	0,	23,	"SiS 55x",},	/* guesswork */	{ -1,	-1,	23,	"unknown", },	/* total default */};static X86type	*cputype;static voidsimplecycles(uvlong*x){	*x = m->ticks;}void	(*cycles)(uvlong*) = simplecycles;void	_cycles(uvlong*);	/* in l.s */static voidnop(void){}void (*coherence)(void) = nop;/* *  delay for l milliseconds more or less.  delayloop is set by *  clockinit() to match the actual CPU speed. */voiddelay(int l){	l *= loopconst;	if(l <= 0)		l = 1;	aamloop(l);}/* *  microsecond delay */voidmicrodelay(int l){	l *= loopconst;	l /= 1000;	if(l <= 0)		l = 1;	aamloop(l);}voidprintcpufreq(void){	int i;	char buf[128];	i = sprint(buf, "cpu%d: %dMHz ", 0, cpumhz);	if(cpuidid[0])		i += sprint(buf+i, "%s ", cpuidid);	sprint(buf+i, "%s (cpuid: AX 0x%4.4ux DX 0x%4.4ux)\n",		cputype->name, cpuidax, cpuiddx);	print(buf);}voidclockinit(void){	int x, y;	/* change in counter */	int family, model, loops, incr;	X86type *t;	uvlong a, b;	/*	 *  set vector for clock interrupts	 */	setvec(Clockvec, clockintr, 0);	/*	 *  figure out what we are	 */	cpuid(cpuidid, &cpuidax, &cpuiddx);	if(strncmp(cpuidid, "AuthenticAMD", 12) == 0)		t = x86amd;	else if(strncmp(cpuidid, "CentaurHauls", 12) == 0)		t = x86winchip;	else if(strncmp(cpuidid, "SiS SiS SiS ", 12) == 0)		t = x86sis;	else		t = x86intel;	family = FAMILY(cpuidax);	model = MODEL(cpuidax);	while(t->name){		if((t->family == family && t->model == model)		|| (t->family == family && t->model == -1)		|| (t->family == -1))			break;		t++;	}	cputype = t;	if(family >= 5)		coherence = wbflush;	/*	 *  if there is one, set tsc to a known value	 */	if(cpuiddx & 0x10){		havetsc = 1;		cycles = _cycles;		if(cpuiddx & 0x20)			wrmsr(0x10, 0);	}	/*	 *  set clock for 1/HZ seconds	 */	outb(Tmode, Load0|Square);	outb(T0cntr, (Freq/HZ));	/* low byte */	outb(T0cntr, (Freq/HZ)>>8);	/* high byte */	/*	 * Introduce a little delay to make sure the count is	 * latched and the timer is counting down; with a fast	 * enough processor this may not be the case.	 * The i8254 (which this probably is) has a read-back	 * command which can be used to make sure the counting	 * register has been written into the counting element.	 */	x = (Freq/HZ);	for(loops = 0; loops < 100000 && x >= (Freq/HZ); loops++){		outb(Tmode, Latch0);		x = inb(T0cntr);		x |= inb(T0cntr)<<8;	}	/* find biggest loop that doesn't wrap */	incr = 16000000/(t->aalcycles*HZ*2);	x = 2000;	for(loops = incr; loops < 64*1024; loops += incr) {		/*		 *  measure time for the loop		 *		 *			MOVL	loops,CX		 *	aaml1:	 	AAM		 *			LOOP	aaml1		 *		 *  the time for the loop should be independent of external		 *  cache and memory system since it fits in the execution		 *  prefetch buffer.		 *		 */		outb(Tmode, Latch0);		cycles(&a);		x = inb(T0cntr);		x |= inb(T0cntr)<<8;		aamloop(loops);		outb(Tmode, Latch0);		cycles(&b);		y = inb(T0cntr);		y |= inb(T0cntr)<<8;		x -= y;		if(x < 0)			x += Freq/HZ;		if(x > Freq/(3*HZ))			break;	}	/* 	 *  figure out clock frequency and a loop multiplier for delay().	 *  n.b. counter goes up by 2*Freq	 */	cpufreq = (vlong)loops*((t->aalcycles*2*Freq)/x);	loopconst = (cpufreq/1000)/t->aalcycles;	/* AAM+LOOP's for 1 ms */	if (0)		print("loops %d x %d cpufreq %,lld loopconst %d\n", loops, x, cpufreq, loopconst);	if(havetsc){		/* counter goes up by 2*Freq */		b = (b-a)<<1;		b *= Freq;		b /= x;		/*		 *  round to the nearest megahz		 */		cpumhz = (b+500000)/1000000L;		cpuhz = b;	} else {		/*		 *  add in possible 0.5% error and convert to MHz		 */		cpumhz = (cpufreq + cpufreq/200)/1000000;		cpuhz = cpufreq;	}	if (0) {		print("cpuhz %,lld cpumhz %d\n", cpuhz, cpumhz);		delay(10*1000);	}}voidclockreload(Timet n){	USED(n);}

⌨️ 快捷键说明

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