1*74a4d8c2SCharles.Forsyth #include "u.h" 2*74a4d8c2SCharles.Forsyth #include "../port/lib.h" 3*74a4d8c2SCharles.Forsyth #include "mem.h" 4*74a4d8c2SCharles.Forsyth #include "dat.h" 5*74a4d8c2SCharles.Forsyth #include "fns.h" 6*74a4d8c2SCharles.Forsyth #include "io.h" 7*74a4d8c2SCharles.Forsyth #include "ureg.h" 8*74a4d8c2SCharles.Forsyth 9*74a4d8c2SCharles.Forsyth #include <isa.h> 10*74a4d8c2SCharles.Forsyth #include <interp.h> 11*74a4d8c2SCharles.Forsyth 12*74a4d8c2SCharles.Forsyth typedef struct Clock0link Clock0link; 13*74a4d8c2SCharles.Forsyth typedef struct Clock0link { 14*74a4d8c2SCharles.Forsyth void (*clock)(void); 15*74a4d8c2SCharles.Forsyth Clock0link* link; 16*74a4d8c2SCharles.Forsyth } Clock0link; 17*74a4d8c2SCharles.Forsyth 18*74a4d8c2SCharles.Forsyth static Clock0link *clock0link; 19*74a4d8c2SCharles.Forsyth static Lock clock0lock; 20*74a4d8c2SCharles.Forsyth ulong clkrelinq; 21*74a4d8c2SCharles.Forsyth void (*kproftick)(ulong); /* set by devkprof.c when active */ 22*74a4d8c2SCharles.Forsyth void (*archclocktick)(void); /* set by arch*.c when desired */ 23*74a4d8c2SCharles.Forsyth 24*74a4d8c2SCharles.Forsyth Timer* addclock0link(void (* clock)(void),int)25*74a4d8c2SCharles.Forsythaddclock0link(void (*clock)(void), int) 26*74a4d8c2SCharles.Forsyth { 27*74a4d8c2SCharles.Forsyth Clock0link *lp; 28*74a4d8c2SCharles.Forsyth 29*74a4d8c2SCharles.Forsyth if((lp = malloc(sizeof(Clock0link))) == 0){ 30*74a4d8c2SCharles.Forsyth print("addclock0link: too many links\n"); 31*74a4d8c2SCharles.Forsyth return nil; 32*74a4d8c2SCharles.Forsyth } 33*74a4d8c2SCharles.Forsyth ilock(&clock0lock); 34*74a4d8c2SCharles.Forsyth lp->clock = clock; 35*74a4d8c2SCharles.Forsyth lp->link = clock0link; 36*74a4d8c2SCharles.Forsyth clock0link = lp; 37*74a4d8c2SCharles.Forsyth iunlock(&clock0lock); 38*74a4d8c2SCharles.Forsyth return nil; 39*74a4d8c2SCharles.Forsyth } 40*74a4d8c2SCharles.Forsyth 41*74a4d8c2SCharles.Forsyth void delay(int l)42*74a4d8c2SCharles.Forsythdelay(int l) 43*74a4d8c2SCharles.Forsyth { 44*74a4d8c2SCharles.Forsyth ulong i, j; 45*74a4d8c2SCharles.Forsyth 46*74a4d8c2SCharles.Forsyth j = m->delayloop; 47*74a4d8c2SCharles.Forsyth while(l-- > 0) 48*74a4d8c2SCharles.Forsyth for(i=0; i < j; i++) 49*74a4d8c2SCharles.Forsyth ; 50*74a4d8c2SCharles.Forsyth } 51*74a4d8c2SCharles.Forsyth 52*74a4d8c2SCharles.Forsyth void microdelay(int l)53*74a4d8c2SCharles.Forsythmicrodelay(int l) 54*74a4d8c2SCharles.Forsyth { 55*74a4d8c2SCharles.Forsyth ulong i; 56*74a4d8c2SCharles.Forsyth 57*74a4d8c2SCharles.Forsyth l *= m->delayloop; 58*74a4d8c2SCharles.Forsyth l /= 1000; 59*74a4d8c2SCharles.Forsyth if(l <= 0) 60*74a4d8c2SCharles.Forsyth l = 1; 61*74a4d8c2SCharles.Forsyth for(i = 0; i < l; i++) 62*74a4d8c2SCharles.Forsyth ; 63*74a4d8c2SCharles.Forsyth } 64*74a4d8c2SCharles.Forsyth 65*74a4d8c2SCharles.Forsyth enum { 66*74a4d8c2SCharles.Forsyth Timebase = 4, /* system clock cycles per time base cycle */ 67*74a4d8c2SCharles.Forsyth }; 68*74a4d8c2SCharles.Forsyth 69*74a4d8c2SCharles.Forsyth static ulong clkreload; 70*74a4d8c2SCharles.Forsyth 71*74a4d8c2SCharles.Forsyth void clockinit(void)72*74a4d8c2SCharles.Forsythclockinit(void) 73*74a4d8c2SCharles.Forsyth { 74*74a4d8c2SCharles.Forsyth long x; 75*74a4d8c2SCharles.Forsyth 76*74a4d8c2SCharles.Forsyth m->delayloop = m->cpuhz/1000; /* initial estimate */ 77*74a4d8c2SCharles.Forsyth do { 78*74a4d8c2SCharles.Forsyth x = gettbl(); 79*74a4d8c2SCharles.Forsyth delay(10); 80*74a4d8c2SCharles.Forsyth x = gettbl() - x; 81*74a4d8c2SCharles.Forsyth } while(x < 0); 82*74a4d8c2SCharles.Forsyth 83*74a4d8c2SCharles.Forsyth /* 84*74a4d8c2SCharles.Forsyth * fix count 85*74a4d8c2SCharles.Forsyth */ 86*74a4d8c2SCharles.Forsyth m->delayloop = ((vlong)m->delayloop*(10*m->clockgen/1000))/(x*Timebase); 87*74a4d8c2SCharles.Forsyth if(m->delayloop == 0) 88*74a4d8c2SCharles.Forsyth m->delayloop = 1; 89*74a4d8c2SCharles.Forsyth 90*74a4d8c2SCharles.Forsyth clkreload = (m->clockgen/Timebase)/HZ-1; 91*74a4d8c2SCharles.Forsyth putdec(clkreload); 92*74a4d8c2SCharles.Forsyth } 93*74a4d8c2SCharles.Forsyth 94*74a4d8c2SCharles.Forsyth void clockintr(Ureg * ur)95*74a4d8c2SCharles.Forsythclockintr(Ureg *ur) 96*74a4d8c2SCharles.Forsyth { 97*74a4d8c2SCharles.Forsyth Clock0link *lp; 98*74a4d8c2SCharles.Forsyth long v; 99*74a4d8c2SCharles.Forsyth 100*74a4d8c2SCharles.Forsyth v = -getdec(); 101*74a4d8c2SCharles.Forsyth if(v > clkreload/2){ 102*74a4d8c2SCharles.Forsyth if(v > clkreload) 103*74a4d8c2SCharles.Forsyth m->ticks += v/clkreload; 104*74a4d8c2SCharles.Forsyth v = 0; 105*74a4d8c2SCharles.Forsyth } 106*74a4d8c2SCharles.Forsyth putdec(clkreload-v); 107*74a4d8c2SCharles.Forsyth 108*74a4d8c2SCharles.Forsyth /* watchdog */ 109*74a4d8c2SCharles.Forsyth if(m->iomem->sypcr & (1<<2)){ 110*74a4d8c2SCharles.Forsyth m->iomem->swsr = 0x556c; 111*74a4d8c2SCharles.Forsyth m->iomem->swsr = 0xaa39; 112*74a4d8c2SCharles.Forsyth } 113*74a4d8c2SCharles.Forsyth 114*74a4d8c2SCharles.Forsyth m->ticks++; 115*74a4d8c2SCharles.Forsyth if(archclocktick != nil) 116*74a4d8c2SCharles.Forsyth archclocktick(); 117*74a4d8c2SCharles.Forsyth 118*74a4d8c2SCharles.Forsyth if(up) 119*74a4d8c2SCharles.Forsyth up->pc = ur->pc; 120*74a4d8c2SCharles.Forsyth 121*74a4d8c2SCharles.Forsyth checkalarms(); 122*74a4d8c2SCharles.Forsyth if(m->machno == 0) { 123*74a4d8c2SCharles.Forsyth if(kproftick != nil) 124*74a4d8c2SCharles.Forsyth (*kproftick)(ur->pc); 125*74a4d8c2SCharles.Forsyth if(canlock(&clock0lock)){ 126*74a4d8c2SCharles.Forsyth for(lp = clock0link; lp; lp = lp->link) 127*74a4d8c2SCharles.Forsyth lp->clock(); 128*74a4d8c2SCharles.Forsyth unlock(&clock0lock); 129*74a4d8c2SCharles.Forsyth } 130*74a4d8c2SCharles.Forsyth } 131*74a4d8c2SCharles.Forsyth 132*74a4d8c2SCharles.Forsyth if(up && up->state == Running){ 133*74a4d8c2SCharles.Forsyth if(cflag && up->type == Interp && tready(nil)) 134*74a4d8c2SCharles.Forsyth ur->cr |= 1; /* set flag in condition register for ../../libinterp/comp-power.c:/^schedcheck */ 135*74a4d8c2SCharles.Forsyth } 136*74a4d8c2SCharles.Forsyth /* other preemption checks are done by trap.c */ 137*74a4d8c2SCharles.Forsyth } 138*74a4d8c2SCharles.Forsyth 139*74a4d8c2SCharles.Forsyth uvlong fastticks(uvlong * hz)140*74a4d8c2SCharles.Forsythfastticks(uvlong *hz) 141*74a4d8c2SCharles.Forsyth { 142*74a4d8c2SCharles.Forsyth if(hz) 143*74a4d8c2SCharles.Forsyth *hz = HZ; 144*74a4d8c2SCharles.Forsyth return m->ticks; 145*74a4d8c2SCharles.Forsyth } 146