Annotation of lucent/sys/src/9/pc/clock.c, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.