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