| 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,19 – 2000/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,34 – 2000/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 */ | |
| 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 |
| |
| 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,45 – 2000/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,144 – 2000/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 | |
| 2000/0623 | i8253readcnt(int cntr) | |
| 2000/0622 | { | |
| 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 |
| |
| 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,150 – 2000/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 | ||