xref: /inferno-os/os/mpc/pit.c (revision d0e1d143ef6f03c75c008c7ec648859dd260cbab)
1 /*
2  * programmable interrupt timer
3  */
4 
5 #include	"u.h"
6 #include	"../port/lib.h"
7 #include	"mem.h"
8 #include	"dat.h"
9 #include	"fns.h"
10 #include	"io.h"
11 #include	"ureg.h"
12 
13 enum {
14 	/* piscr */
15 	PTE =	1<<0,
16 	PITF =	1<<1,
17 	PIE =	1<<2,
18 	PS =	1<<7,
19 };
20 
21 static void
22 pitinterrupt(Ureg*, void*)
23 {
24 	IMM *io;
25 
26 	io = m->iomem;
27 	if(io->piscr & PS){
28 		io->piscr |= PS;	/* clear by writing 1 */
29 		/* do whatever is required */
30 	}
31 }
32 
33 static void
34 pitreset(void)
35 {
36 	IMM *io;
37 
38 	io = ioplock();
39 	io->piscrk = KEEP_ALIVE_KEY;
40 	io->piscr = (PITlevel<<8) | PS | PITF;
41 	if(0)
42 		io->piscrk = ~KEEP_ALIVE_KEY;
43 	/* piscrk is left unlocked for interrupt routine */
44 	iopunlock();
45 	intrenable(PITlevel, pitinterrupt, nil, BUSUNKNOWN, "pit");
46 }
47 
48 static ulong
49 pitload(ulong usec)
50 {
51 	IMM *io;
52 	ulong v;
53 
54 	v = ((usec*m->oscclk)/512);
55 	if(v == 0 || v >= (1<<16))
56 		return 0;	/* can't do */
57 	io = ioplock();
58 	io->pitck = KEEP_ALIVE_KEY;
59 	io->pitc = (v-1)<<16;
60 	io->pitck = ~KEEP_ALIVE_KEY;
61 	io->piscrk = KEEP_ALIVE_KEY;
62 	io->piscr = (PITlevel<<8) | PS | PIE | PITF | PTE;
63 	if(0)
64 		io->piscrk = ~KEEP_ALIVE_KEY;
65 	/* piscrk is left unlocked for interrupt routine */
66 	iopunlock();
67 	return (v*512)/m->oscclk;
68 }
69