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

📄 clock.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
字号:
#include	"u.h"#include	"lib.h"#include	"mem.h"#include	"dat.h"#include	"fns.h"#include	"io.h"#include	"ureg.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,		/* perioic square wave */	Freq=	1193182,	/* Real clock frequency */};static uvlong cpuhz = 66000000;static int cpumhz = 66;static int loopconst = 100;int cpuidax, cpuiddx;int havetsc;extern void _cycles(uvlong*);		/* in l.s */extern void wrmsr(int, vlong);static voidclockintr(Ureg*, void*){	m->ticks++;	checkalarms();}#define STEPPING(x)	((x)&0xf)#define X86MODEL(x)	(((x)>>4)&0xf)#define X86FAMILY(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;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,	11,	"unknown", },	/* total default */};static X86type	*cputype;voiddelay(int millisecs){	millisecs *= loopconst;	if(millisecs <= 0)		millisecs = 1;	aamloop(millisecs);}voidmicrodelay(int microsecs){	microsecs *= loopconst;	microsecs /= 1000;	if(microsecs <= 0)		microsecs = 1;	aamloop(microsecs);}extern void cpuid(char*, int*, int*);X86type*cpuidentify(void){	int family, model;	X86type *t;	char cpuidid[16];	int cpuidax, cpuiddx;	cpuid(cpuidid, &cpuidax, &cpuiddx);	if(strncmp(cpuidid, "AuthenticAMD", 12) == 0)		t = x86amd;	else		t = x86intel;	family = X86FAMILY(cpuidax);	model = X86MODEL(cpuidax);	if (0)		print("cpuidentify: cpuidax 0x%ux cpuiddx 0x%ux\n",			cpuidax, cpuiddx);	while(t->name){		if((t->family == family && t->model == model)		|| (t->family == family && t->model == -1)		|| (t->family == -1))			break;		t++;	}	if(t->name == nil)		panic("cpuidentify");	if(cpuiddx & 0x10){		havetsc = 1;		if(cpuiddx & 0x20)			wrmsr(0x10, 0);	}	return t;}voidclockinit(void){	uvlong a, b, cpufreq;	int loops, incr, x, y;	X86type *t;	/*	 *  set vector for clock interrupts	 */	setvec(VectorCLOCK, clockintr, 0);	t = cpuidentify();	/*	 *  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);		if(havetsc)			_cycles(&a);		x = inb(T0cntr);		x |= inb(T0cntr)<<8;		aamloop(loops);		outb(Tmode, Latch0);		if(havetsc)			_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().	 *  counter  goes at twice the frequency, once per transition,	 *  i.e., twice per square wave	 */	cpufreq = (vlong)loops*((t->aalcycles*2*Freq)/x);	loopconst = (cpufreq/1000)/t->aalcycles;	/* AAM+LOOP's for 1 ms */	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 .5% error and convert to MHz		 */		cpumhz = (cpufreq + cpufreq/200)/1000000;		cpuhz = cpufreq;	}	if(debug){		int timeo;		print("%dMHz %s loop %d\n", cpumhz, t->name, loopconst);		print("tick...");		for(timeo = 0; timeo < 10; timeo++)			delay(1000);		print("tock...\n");	}}

⌨️ 快捷键说明

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