ref: dd16eef8365cb0b9e4805c23291aadcaa596dd87
dir: /os/mpc/pit.c/
/*
* programmable interrupt timer
*/
#include "u.h"
#include "../port/lib.h"
#include "mem.h"
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "ureg.h"
enum {
/* piscr */
PTE = 1<<0,
PITF = 1<<1,
PIE = 1<<2,
PS = 1<<7,
};
static void
pitinterrupt(Ureg*, void*)
{
IMM *io;
io = m->iomem;
if(io->piscr & PS){
io->piscr |= PS; /* clear by writing 1 */
/* do whatever is required */
}
}
static void
pitreset(void)
{
IMM *io;
io = ioplock();
io->piscrk = KEEP_ALIVE_KEY;
io->piscr = (PITlevel<<8) | PS | PITF;
if(0)
io->piscrk = ~KEEP_ALIVE_KEY;
/* piscrk is left unlocked for interrupt routine */
iopunlock();
intrenable(PITlevel, pitinterrupt, nil, BUSUNKNOWN, "pit");
}
static ulong
pitload(ulong usec)
{
IMM *io;
ulong v;
v = ((usec*m->oscclk)/512);
if(v == 0 || v >= (1<<16))
return 0; /* can't do */
io = ioplock();
io->pitck = KEEP_ALIVE_KEY;
io->pitc = (v-1)<<16;
io->pitck = ~KEEP_ALIVE_KEY;
io->piscrk = KEEP_ALIVE_KEY;
io->piscr = (PITlevel<<8) | PS | PIE | PITF | PTE;
if(0)
io->piscrk = ~KEEP_ALIVE_KEY;
/* piscrk is left unlocked for interrupt routine */
iopunlock();
return (v*512)/m->oscclk;
}