diff options
Diffstat (limited to 'os/manga/clock.c')
| -rw-r--r-- | os/manga/clock.c | 166 |
1 files changed, 166 insertions, 0 deletions
diff --git a/os/manga/clock.c b/os/manga/clock.c new file mode 100644 index 00000000..282f32d6 --- /dev/null +++ b/os/manga/clock.c @@ -0,0 +1,166 @@ +#include "u.h" +#include "../port/lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "io.h" + +#include "ureg.h" + +enum { + Mclk= 25000000 +}; + +typedef struct Clock0link Clock0link; +typedef struct Clock0link { + void (*clock)(void); + Clock0link* link; +} Clock0link; + +static Clock0link *clock0link; +static Lock clock0lock; +static void (*prof_fcn)(Ureg *, int); + +Timer* +addclock0link(void (*clock)(void), int) +{ + Clock0link *lp; + + if((lp = malloc(sizeof(Clock0link))) == 0){ + print("addclock0link: too many links\n"); + return nil; + } + ilock(&clock0lock); + lp->clock = clock; + lp->link = clock0link; + clock0link = lp; + iunlock(&clock0lock); + return nil; +} + +static void +profintr(Ureg *, void*) +{ + /* TO DO: watchdog, profile on Timer 0 */ +} + +static void +clockintr(Ureg*, void*) +{ + Clock0link *lp; + static int blip, led; + + if(++blip >= HZ){ + blip = 0; + ledset(led ^= 1); + } + m->ticks++; + + checkalarms(); + + if(canlock(&clock0lock)){ + for(lp = clock0link; lp; lp = lp->link) + if(lp->clock) + lp->clock(); + unlock(&clock0lock); + } + + /* round robin time slice is done by trap.c and proc.c */ +} + +void +installprof(void (*pf)(Ureg *, int)) +{ + USED(pf); +} + +void +clockinit(void) +{ + TimerReg *tr; + IntrReg *ir; + ulong l, u; + + m->ticks = 0; + tr = TIMERREG; + tr->enable = 0; + tr->pulse1 = 1; + + /* first tune the delay loop parameter (using a search because the counter doesn't decrement) */ + ir = INTRREG; + tr->count1 = Mclk/1000 - tr->pulse1; /* millisecond */ + u = m->cpuhz/(2*1000); /* over-large estimate for a millisecond */ + l = 10000; + while(l+1 < u){ + m->delayloop = l + (u-l)/2; + ir->st = 1<<IRQtm1; /* reset edge */ + tr->enable = 1<<1; + delay(1); + tr->enable = 0; + if(ir->st & (1<<IRQtm1)) + u = m->delayloop; + else + l = m->delayloop; + } + + intrenable(IRQ, IRQtm1, clockintr, nil, "timer.1"); + tr->count1 = Mclk/HZ - tr->pulse1; + tr->enable = 1<<1; /* enable only Timer 1 */ +} + +void +clockpoll(void) +{ +} + +void +clockcheck(void) +{ +} + +uvlong +fastticks(uvlong *hz) +{ + if(hz) + *hz = HZ; + return m->ticks; +} + +void +microdelay(int l) +{ + int i; + + l *= m->delayloop; + l /= 1000; + if(l <= 0) + l = 1; + for(i = 0; i < l; i++) + ; +} + +void +delay(int l) +{ + ulong i, j; + + j = m->delayloop; + while(l-- > 0) + for(i=0; i < j; i++) + ; +} + +/* + * for devkprof.c + */ +long +archkprofmicrosecondspertick(void) +{ + return MS2HZ*1000; +} + +void +archkprofenable(int) +{ + /* TO DO */ +} |
