plan 9 kernel history: overview | file list | diff list

2000/0623/pc/i8253.c (diff list | history)

2000/0622/sys/src/9/pc/i8253.c:14,192000/0623/sys/src/9/pc/i8253.c:14,20 (short | long | prev | next)
1997/0327    
	T1cntr=	0x41,		/* ... */ 
	T2cntr=	0x42,		/* ... */ 
2000/0622    
	Tmode=	0x43,		/* mode port (control word register) */ 
2000/0623    
	T2ctl=	0x61,		/* counter 2 control port */ 
1997/0327    
 
	/* commands */ 
	Latch0=	0x00,		/* latch counter 0's value */ 
2000/0622/sys/src/9/pc/i8253.c:20,342000/0623/sys/src/9/pc/i8253.c:21,62
2000/0622    
	Load0l=	0x10,		/* load counter 0's lsb */ 
	Load0m=	0x20,		/* load counter 0's msb */ 
1997/0327    
	Load0=	0x30,		/* load counter 0 with 2 bytes */ 
2000/0623    
	Latch2=	0x80,		/* latch counter 2's value */ 
	Load2l=	0x90,		/* load counter 2's lsb */ 
	Load2m=	0xa0,		/* load counter 2's msb */ 
	Load2=	0xb0,		/* load counter 2 with 2 bytes */ 
1997/0327    
 
2000/0623    
	/* 8254 read-back command: everything > pc-at has an 8254 */ 
	Rdback=	0xc0,		/* readback counters & status */ 
	Rdnstat=0x10,		/* don't read status */ 
	Rdncnt=	0x20,		/* don't read counter value */ 
	Rd0cntr=0x02,		/* read back for which counter */ 
	Rd1cntr=0x04, 
	Rd2cntr=0x08, 
 
1997/0327    
	/* modes */ 
2000/0623    
	ModeMsk=0xe, 
2000/0622    
	Square=	0x6,		/* periodic square wave */ 
	Trigger= 0x0,		/* interrupt on terminal count */ 
2000/0623    
	Trigger=0x0,		/* interrupt on terminal count */ 
	Sstrobe=0x8,		/* software triggered strobe */ 
1997/0327    
 
2000/0623    
	/* counter 2 controls */ 
	C2gate=	0x1, 
	C2speak=0x2, 
	C2out=	0x10, 
 
1997/0327    
	Freq=	1193182,	/* Real clock frequency */ 
2000/0623    
 
	FreqMul=16,		/* extra accuracy in fastticks/Freq calculation; ok up to ~8ghz */ 
1997/0327    
}; 
 
2000/0622    
static Lock	i8253lock; 
2000/0623    
static struct 
{ 
	Lock	lock; 
	vlong	when;		/* next fastticks a clock interrupt should occur */ 
	long	fastperiod;	/* fastticks/hz */ 
	long	fast2freq;	/* fastticks*FreqMul/Freq */ 
}i8253; 
2000/0622    
 
1997/0327    
void 
1999/0131    
i8253init(int aalcycles, int havecycleclock) 
2000/0622/sys/src/9/pc/i8253.c:40,452000/0623/sys/src/9/pc/i8253.c:68,75
1997/0327    
	if(initialised == 0){ 
		initialised = 1; 
1999/0714    
		ioalloc(T0cntr, 4, 0, "i8253"); 
2000/0623    
		ioalloc(T2ctl, 1, 0, "i8253.cntr2ctl"); 
 
1997/0327    
		/* 
		 *  set clock for 1/HZ seconds 
		 */ 
2000/0622/sys/src/9/pc/i8253.c:126,1442000/0623/sys/src/9/pc/i8253.c:156,239
1999/0131    
		m->cpumhz = (cpufreq + cpufreq/200)/1000000; 
		m->cpuhz = cpufreq; 
	} 
2000/0623    
 
outb(Tmode, Load0|Trigger); 
outb(T0cntr, (Freq/HZ));	/* low byte */ 
outb(T0cntr, (Freq/HZ)>>8);	/* high byte */ 
1997/0327    
} 
 
2000/0623    
static vlong lastfast; 
 
2000/0622    
int 
i8253readcnt(void) 
2000/0623    
i8253readcnt(int cntr) 
2000/0622    
{ 
	ilock(&i8253lock); 
	iunlock(&i8253lock); 
2000/0623    
	int v; 
 
	ilock(&i8253.lock); 
	if(cntr == 2){ 
		outb(Tmode, Rdback|Rd2cntr); 
		v = inb(T2cntr) << 16; 
		v |= inb(T2cntr); 
		v |= inb(T2cntr) << 8; 
	}else if(cntr == 0){ 
		outb(Tmode, Rdback|Rd0cntr); 
		v = inb(T0cntr) << 16; 
		v |= inb(T0cntr); 
		v |= inb(T0cntr) << 8; 
	}else if(cntr == 3){ 
		vlong nf = fastticks(nil); 
		long set; 
 
		set = (long)(nf - lastfast) * 100 / (long)((vlong)m->cpuhz * 100 / Freq); 
		set = (Freq/HZ) - set; 
		set -= 3 - 1;	/* outb, outb, wait - outb(mode) */ 
		outb(Tmode, Rdback|Rdnstat|Rd0cntr); 
		v = inb(T0cntr); 
		v |= inb(T0cntr) << 8; 
		v = set - v; 
	}else if(cntr == 4){ 
		vlong nf = fastticks(nil); 
		long set; 
 
		set = (long)(nf - lastfast) * 16 / (long)((vlong)m->cpuhz * 16 / Freq); 
		set = (Freq/HZ) - set; 
		set -= 3 - 1;	/* outb, outb, wait - outb(mode) */ 
		outb(Tmode, Rdback|Rdnstat|Rd0cntr); 
		v = inb(T0cntr); 
		v |= inb(T0cntr) << 8; 
		v = set - v; 
	}else{ 
		vlong nf = fastticks(nil); 
		long set; 
 
		set = (nf - lastfast) * Freq / m->cpuhz; 
		set = (Freq/HZ) - set; 
		set -= 3 - 1;	/* outb, outb, wait - outb(mode) */ 
		outb(Tmode, Rdback|Rdnstat|Rd0cntr); 
		v = inb(T0cntr); 
		v |= inb(T0cntr) << 8; 
		v = set - v; 
	} 
	iunlock(&i8253.lock); 
	return v; 
2000/0622    
} 
 
2000/0621    
static void 
clockintr0(Ureg* ureg, void *v) 
{ 
2000/0622    
	loopbackintr(ureg); 
2000/0623    
	vlong now; 
	long set; 
 
	now = fastticks(nil); 
	while(i8253.when < now) 
		i8253.when += i8253.fastperiod; 
	set = (long)(i8253.when - now) * FreqMul / i8253.fast2freq; 
	set -= 3;	/* three cycles for the count to take effect: outb, outb, wait */ 
lastfast = now; 
	outb(T0cntr, set);	/* low byte */ 
	outb(T0cntr, set>>8);	/* high byte */ 
 
	checkcycintr(ureg, v); 
2000/0621    
	clockintr(ureg, v); 
} 
 
2000/0622/sys/src/9/pc/i8253.c:145,1502000/0623/sys/src/9/pc/i8253.c:240,248
1997/0327    
void 
i8253enable(void) 
{ 
2000/0623    
	i8253.when = fastticks(nil); 
	i8253.fastperiod = (m->cpuhz + HZ/2) / HZ; 
	i8253.fast2freq = (vlong)m->cpuhz * FreqMul / Freq; 
2000/0621    
	intrenable(IrqCLOCK, clockintr0, 0, BUSUNKNOWN, "clock"); 
1997/0327    
} 
1998/0710    
 


source code copyright © 1990-2005 Lucent Technologies; see license
Plan 9 distribution
comments to russ cox (rsc@swtch.com)