Charles.Forsyth20060303644188019 years agoHistory
154 lines · 3.2 KB · C
RawDownload
#include "boot.h"  /* * Control Word Read/Write Counter (mode 0)  LSB, MSB */#define PIT_RW_COUNTER0  0x30#define PIT_RW_COUNTER1  0x70#define PIT_RW_COUNTER2  0xB0#define PIT_COUNTERLATCH0	0x00#define PIT_COUNTERLATCH1	0x40#define PIT_COUNTERLATCH2	0x80 #define PIT_MODE_0	0	/* Interrupt on Terminal Count */#define PIT_MODE_1	2	/* Hardware Retriggeable One-shot */#define PIT_MODE_2	4	/* Rate Generator */#define PIT_MODE_3	6	/* Square Wave Mode */#define PIT_MODE_4	8	/* Software Triggered Mode */#define PIT_MODE_5	10	/* Hardware Triggered Mode (Retriggeable) */ /* * Harris 82C54 Programmable Interval Timer * On the Puma board the PIT is memory mapped * starting at 0xf2000000 and with each of the 8-bit * registers addressed on a consecutive 4-byte boundary. */#undef inb#undef outb#define 	inb(port)			((*(uchar *)(port))&0xff)#define 	outb(port, data)	(*(uchar *)(port) = (data))enum{	Cnt0=	0xf2000000,		/* counter locations */	Cnt1=	0xf2000004,		/* ... */	Cnt2=	0xf2000008,		/* ... */	Ctlw=	0xf200000c,		/* control word register*/ 	/* commands */	Latch0=	0x00,		/* latch counter 0's value */	Load0=	0x30,		/* load counter 0 with 2 bytes */	Latch1=	0x40,		/* latch counter 1's value */	Load1=	0x70,		/* load counter 1 with 2 bytes */ 	/* modes */	Square=	0x06,		/* periodic square wave */	RateGen=	0x04,		/* rate generator */ 	Freq=	3686400,	/* Real clock frequency */}; static int cpufreq = 233000000;static int aalcycles = 14; static voidclockintr(Ureg*, void*){	m->ticks++;	checkalarms();} /* *  delay for l milliseconds more or less.  delayloop is set by *  clockinit() to match the actual CPU speed. */voiddelay(int l){	l *= m->delayloop;	if(l <= 0)		l = 1;	aamloop(l);} voidmicrodelay(int l){	l *= m->delayloop;	l /= 1000;	if(l <= 0)		l = 1;	aamloop(l);} voidclockinit(void){	int x, y;	/* change in counter */	int loops, incr; 	/*	 *  set vector for clock interrupts	 */	setvec(V_TIMER0, clockintr, 0); 	/*	 *  set clock for 1/HZ seconds	 */	outb(Ctlw, Load0|Square);	outb(Cnt0, (Freq/HZ));	/* low byte */	outb(Cnt0, (Freq/HZ)>>8);	/* high byte */ 	/* find biggest loop that doesn't wrap */	incr = 16000000/(aalcycles*HZ*2);	x = 2000;	for(loops = incr; loops < 64*1024; loops += incr) {		/*		 *  measure time for the loop		 *	TEXT aamloop(SB), $-4		 *	_aamloop:		 *		MOVW	R0, R0		 *		MOVW	R0, R0		 *		MOVW	R0, R0		 *		SUB		$1, R0		 *		CMP		$0, R0		 *		BNE		_aamloop		 *		RET		 *		 *  the time for the loop should be independent of external		 *  cache and memory system since it fits in the execution		 *  prefetch buffer.		 *		 */		outb(Ctlw, Latch0);		x = inb(Cnt0);		x |= inb(Cnt0)<<8;		aamloop(loops);		outb(Ctlw, Latch0);		y = inb(Cnt0);		y |= inb(Cnt0)<<8;		x -= y;			if(x < 0)			x += Freq/HZ; 		if(x > Freq/(3*HZ))			break;	} 	/*	 *  counter  goes at twice the frequency, once per transition,	 *  i.e., twice per square wave	 */	x >>= 1; 	/* 	 *  figure out clock frequency and a loop multiplier for delay().	 */	cpufreq = loops*((aalcycles*Freq)/x);	m->delayloop = (cpufreq/1000)/aalcycles;	/* AAMLOOPs for 1 ms */ 	/*	 *  add in possible .2% error and convert to MHz	 */	m->speed = (cpufreq + cpufreq/500)/1000000;}