|
|
1.1 ! root 1: #include "u.h" ! 2: #include "../port/lib.h" ! 3: #include "mem.h" ! 4: #include "dat.h" ! 5: #include "fns.h" ! 6: #include "io.h" ! 7: #include "ureg.h" ! 8: ! 9: /* ! 10: * 8253 timer ! 11: */ ! 12: enum ! 13: { ! 14: T0cntr= 0x40, /* counter ports */ ! 15: T1cntr= 0x41, /* ... */ ! 16: T2cntr= 0x42, /* ... */ ! 17: Tmode= 0x43, /* mode port */ ! 18: ! 19: /* commands */ ! 20: Latch0= 0x00, /* latch counter 0's value */ ! 21: Load0= 0x30, /* load counter 0 with 2 bytes */ ! 22: ! 23: /* modes */ ! 24: Square= 0x36, /* perioic square wave */ ! 25: Trigger= 0x30, /* interrupt on terminal count */ ! 26: ! 27: Freq= 1193182, /* Real clock frequency */ ! 28: }; ! 29: ! 30: static int cpufreq = 66000000; ! 31: static int cpumhz = 66; ! 32: static int loopconst = 100; ! 33: static int cpuidax, cpuiddx; ! 34: ! 35: static void ! 36: clock(Ureg *ur, void *arg) ! 37: { ! 38: Proc *p; ! 39: int nrun = 0; ! 40: ! 41: USED(arg); ! 42: ! 43: m->ticks++; ! 44: ! 45: checkalarms(); ! 46: uartclock(); ! 47: hardclock(); ! 48: ! 49: /* ! 50: * process time accounting ! 51: */ ! 52: p = m->proc; ! 53: if(p){ ! 54: nrun = 1; ! 55: p->pc = ur->pc; ! 56: if (p->state==Running) ! 57: p->time[p->insyscall]++; ! 58: } ! 59: nrun = (nrdy+nrun)*1000; ! 60: MACHP(0)->load = (MACHP(0)->load*19+nrun)/20; ! 61: ! 62: if(u && p && p->state==Running){ ! 63: /* ! 64: * preemption ! 65: */ ! 66: if(anyready()){ ! 67: if(p->hasspin) ! 68: p->hasspin = 0; ! 69: else ! 70: sched(); ! 71: } ! 72: if((ur->cs&0xffff) == UESEL){ ! 73: spllo(); /* in case we fault */ ! 74: (*(ulong*)(USTKTOP-BY2WD)) += TK2MS(1); /* profiling clock */ ! 75: splhi(); ! 76: } ! 77: } ! 78: ! 79: /* last because it goes spllo() */ ! 80: mouseclock(); ! 81: } ! 82: ! 83: #define STEPPING(x) ((x)&0xf) ! 84: #define MODEL(x) (((x)>>4)&0xf) ! 85: #define FAMILY(x) (((x)>>8)&0xf) ! 86: ! 87: enum ! 88: { ! 89: /* flags */ ! 90: CpuidFPU = 0x001, /* on-chip floating point unit */ ! 91: CpuidMCE = 0x080, /* machine check exception */ ! 92: CpuidCX8 = 0x100, /* CMPXCHG8B instruction */ ! 93: }; ! 94: ! 95: typedef struct ! 96: { ! 97: int family; ! 98: int model; ! 99: int aalcycles; ! 100: char *name; ! 101: } X86type; ! 102: ! 103: X86type x86type[] = ! 104: { ! 105: /* from the cpuid instruction */ ! 106: { 4, 0, 22, "Intel486DX", }, ! 107: { 4, 1, 22, "Intel486DX", }, ! 108: { 4, 2, 22, "Intel486SX", }, ! 109: { 4, 3, 22, "Intel486DX2", }, ! 110: { 4, 4, 22, "Intel486DX2", }, ! 111: { 4, 5, 22, "Intel486SL", }, ! 112: { 4, 8, 22, "IntelDX4", }, ! 113: { 5, 1, 23, "Pentium510", }, ! 114: { 5, 2, 23, "Pentium735", }, ! 115: ! 116: /* family defaults */ ! 117: { 3, -1, 32, "Intel386", }, ! 118: { 4, -1, 22, "Intel486", }, ! 119: { 5, -1, 23, "Pentium", }, ! 120: ! 121: /* total default */ ! 122: { -1, -1, 23, "unknown", }, ! 123: }; ! 124: ! 125: static X86type *cputype; ! 126: ! 127: /* ! 128: * delay for l milliseconds more or less. delayloop is set by ! 129: * clockinit() to match the actual CPU speed. ! 130: */ ! 131: void ! 132: delay(int l) ! 133: { ! 134: l *= loopconst; ! 135: if(l <= 0) ! 136: l = 1; ! 137: aamloop(l); ! 138: } ! 139: ! 140: /* ! 141: * microsecond delay ! 142: */ ! 143: void ! 144: microdelay(int l) ! 145: { ! 146: l *= loopconst; ! 147: l /= 1000; ! 148: if(l <= 0) ! 149: l = 1; ! 150: aamloop(l); ! 151: } ! 152: ! 153: void ! 154: printcpufreq(void) ! 155: { ! 156: print("CPU is a %d MHz %s (cpuid: ax %lux dx %lux)\n", ! 157: cpumhz, cputype->name, cpuidax, cpuiddx); ! 158: } ! 159: ! 160: int ! 161: x86(void) ! 162: { ! 163: return cputype->family; ! 164: } ! 165: ! 166: void ! 167: clockinit(void) ! 168: { ! 169: int x, y; /* change in counter */ ! 170: int family, model, loops, incr; ! 171: X86type *t; ! 172: ! 173: /* ! 174: * set vector for clock interrupts ! 175: */ ! 176: setvec(Clockvec, clock, 0); ! 177: ! 178: /* ! 179: * figure out what we are ! 180: */ ! 181: x86cpuid(&cpuidax, &cpuiddx); ! 182: family = FAMILY(cpuidax); ! 183: model = MODEL(cpuidax); ! 184: for(t = x86type; t->name; t++) ! 185: if((t->family == family && t->model == model) ! 186: || (t->family == family && t->model == -1) ! 187: || (t->family == -1)) ! 188: break; ! 189: cputype = t; ! 190: ! 191: /* ! 192: * set clock for 1/HZ seconds ! 193: */ ! 194: outb(Tmode, Load0|Square); ! 195: outb(T0cntr, (Freq/HZ)); /* low byte */ ! 196: outb(T0cntr, (Freq/HZ)>>8); /* high byte */ ! 197: ! 198: /* find biggest loop that doesn't wrap */ ! 199: incr = 16000000/(t->aalcycles*HZ*2); ! 200: x = 2000; ! 201: for(loops = incr; loops < 64*1024; loops += incr) { ! 202: ! 203: /* ! 204: * measure time for the loop ! 205: * ! 206: * MOVL loops,CX ! 207: * aaml1: AAM ! 208: * LOOP aaml1 ! 209: * ! 210: * the time for the loop should be independent of external ! 211: * cache and memory system since it fits in the execution ! 212: * prefetch buffer. ! 213: * ! 214: */ ! 215: outb(Tmode, Latch0); ! 216: x = inb(T0cntr); ! 217: x |= inb(T0cntr)<<8; ! 218: aamloop(loops); ! 219: outb(Tmode, Latch0); ! 220: y = inb(T0cntr); ! 221: y |= inb(T0cntr)<<8; ! 222: x -= y; ! 223: ! 224: if(x < 0) ! 225: x += Freq/HZ; ! 226: ! 227: if(x > Freq/(3*HZ)) ! 228: break; ! 229: } ! 230: ! 231: /* ! 232: * counter goes at twice the frequency, once per transition, ! 233: * i.e., twice per square wave ! 234: */ ! 235: x >>= 1; ! 236: ! 237: /* ! 238: * figure out clock frequency and a loop multiplier for delay(). ! 239: */ ! 240: cpufreq = loops*((t->aalcycles*Freq)/x); ! 241: loopconst = (cpufreq/1000)/t->aalcycles; /* AAM+LOOP's for 1 ms */ ! 242: ! 243: /* ! 244: * add in possible .2% error and convert to MHz ! 245: */ ! 246: cpumhz = (cpufreq + cpufreq/500)/1000000; ! 247: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.