Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 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 "../port/error.h"
8
#include "msaturn.h"
9
 
10
enum {
11
	Timer_ctrl = Saturn + 0x0106,
12
	Timer0_load = Saturn + 0x0200,
13
	Timer0_cnt = Saturn + 0x0204,
14
	Timer1_load = Saturn + 0x0300,
15
	Timer1_cnt = Saturn + 0x0304,
16
 
17
	T0_event = RBIT(13, ushort),
18
	T0_ie = RBIT(14, ushort),
19
	T0_cen = RBIT(15, ushort),
20
	T1_event = RBIT(5, ushort),
21
	T1_ie = RBIT(6, ushort),
22
	T1_cen = RBIT(7, ushort),
23
};
24
 
25
static ulong ticks;
26
static Lock tlock;
27
static ushort timer_ctl;
28
 
29
ulong multiplier;
30
 
31
ulong
32
µs(void)
33
{
34
	uvlong x;
35
 
36
	if(multiplier == 0){
37
		multiplier = (uvlong)(1000000LL << 16) / m->cyclefreq;
38
		print("µs: multiplier %ld, cyclefreq %lld, shifter %d\n", multiplier, m->cyclefreq, 16);
39
	}
40
	cycles(&x);
41
	return (x*multiplier) >> 16;
42
}
43
 
44
void
45
saturntimerintr(Ureg *u, void*)
46
{
47
	ushort ctl = *(ushort*)Timer_ctrl, v = 0;
48
 
49
	if(ctl&T1_event){
50
		v = T1_event;
51
		ticks++;
52
	}
53
 
54
	*(ushort*)Timer_ctrl = timer_ctl|T0_event|v;
55
	intack();
56
	timerintr(u, 0);
57
}
58
 
59
void
60
timerinit(void)
61
{
62
	*(ushort*)Timer_ctrl = 0;
63
	*(ulong*)Timer0_load = m->bushz  / HZ;
64
	*(ulong*)Timer0_cnt = m->bushz / HZ;
65
	*(ulong*)Timer1_load = m->bushz;
66
	*(ulong*)Timer1_cnt = m->bushz;
67
 
68
	intrenable(Vectimer0, saturntimerintr, nil, "timer");
69
 
70
	timer_ctl = T0_cen|T0_ie|T1_cen;
71
	*(ushort*)Timer_ctrl = timer_ctl;
72
}
73
 
74
uvlong
75
fastticks(uvlong *hz)
76
{
77
	assert(*(ushort*)Timer_ctrl&T1_cen);
78
	if(*(ushort*)Timer_ctrl&T1_event){
79
		*(ushort*)Timer_ctrl = timer_ctl|T1_event;
80
		ticks++;
81
	}
82
 
83
	if (hz)
84
		*hz = m->bushz;
85
 
86
	return (uvlong)ticks*m->bushz+(uvlong)(m->bushz-*(ulong*)Timer1_cnt);
87
}
88
 
89
void
90
timerset(Tval next)
91
{
92
	ulong offset;
93
	uvlong now;
94
 
95
	ilock(&tlock);
96
	*(ushort*)Timer_ctrl = T1_cen;
97
 
98
	now = fastticks(nil);
99
	offset = next - now;
100
	if((long)offset < 10000)
101
		offset = 10000;
102
	else if(offset > m->bushz)
103
		offset = m->bushz;
104
 
105
	*(ulong*)Timer0_cnt = offset;
106
	*(ushort*)Timer_ctrl = timer_ctl;
107
	assert(*(ushort*)Timer_ctrl & T1_cen);
108
	iunlock(&tlock);
109
}
110