]> git.lizzy.rs Git - plan9front.git/blob - sys/src/9/sgi/clock.c
merge
[plan9front.git] / sys / src / 9 / sgi / clock.c
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
8 #include        "ureg.h"
9
10 enum {
11         Cyccntres       = 2, /* counter advances at ½ clock rate */
12         Basetickfreq    = 150*Mhz / Cyccntres,  /* sgi/indy */
13
14         Instrs          = 10*Mhz,
15 };
16
17 static long
18 issue1loop(void)
19 {
20         register int i;
21         long st;
22
23         i = Instrs;
24         st = perfticks();
25         do {
26                 --i; --i; --i; --i; --i; --i; --i; --i; --i; --i;
27                 --i; --i; --i; --i; --i; --i; --i; --i; --i; --i;
28                 --i; --i; --i; --i; --i; --i; --i; --i; --i; --i;
29                 --i; --i; --i; --i; --i; --i; --i; --i; --i; --i;
30                 --i; --i; --i; --i; --i; --i; --i; --i; --i; --i;
31                 --i; --i; --i; --i; --i; --i; --i; --i; --i; --i;
32                 --i; --i; --i; --i; --i; --i; --i; --i; --i; --i;
33                 --i; --i; --i; --i; --i; --i; --i; --i; --i; --i;
34                 --i; --i; --i; --i; --i; --i; --i; --i; --i; --i;
35                 --i; --i; --i; --i; --i;
36                 /* omit 3 (--i) to account for conditional branch, nop & jump */
37                 i -= 1+3;        /* --i plus 3 omitted (--i) instructions */
38         } while(--i >= 0);
39         return perfticks() - st;
40 }
41
42 /* estimate instructions/s. */
43 static int
44 guessmips(long (*loop)(void), char *)
45 {
46         int s;
47         long cyc;
48
49         do {
50                 s = splhi();
51                 cyc = loop();
52                 splx(s);
53                 if (cyc < 0)
54                         iprint("again...");
55         } while (cyc < 0);
56         /*
57          * Instrs instructions took cyc cycles @ Basetickfreq Hz.
58          * round the result.
59          */
60         return (((vlong)Basetickfreq * Instrs) / cyc + Mhz/2) / Mhz;
61 }
62
63 void
64 clockinit(void)
65 {
66         int mips;
67
68         /*
69          * calibrate fastclock
70          */
71         mips = guessmips(issue1loop, "single");
72
73         /*
74          * m->delayloop should be the number of delay loop iterations
75          * needed to consume 1 ms, assuming 2 instr'ns in the delay loop.
76          */
77         m->delayloop = mips*Mhz / (1000 * 2);
78         if(m->delayloop == 0)
79                 m->delayloop = 1;
80
81         m->speed = mips;
82         m->hz = m->speed*Mhz;
83
84         m->maxperiod = Basetickfreq / HZ;
85         m->minperiod = Basetickfreq / (100*HZ);
86         wrcompare(rdcount()+m->maxperiod);
87
88         intron(INTR7);
89 }
90
91 void
92 clock(Ureg *ur)
93 {
94         wrcompare(rdcount()+m->maxperiod);      /* side-effect: dismiss intr */
95         timerintr(ur, 0);
96 }
97
98 void
99 microdelay(int n)
100 {
101         ulong now;
102         now = µs();
103         while(µs() - now < n);
104 }
105
106 void
107 delay(int n)
108 {
109         while(--n >= 0)
110                 microdelay(1000);
111 }
112
113 ulong
114 µs(void)
115 {
116         return fastticks2us(fastticks(nil));
117 }
118
119 uvlong
120 fastticks(uvlong *hz)
121 {
122         int x;
123         ulong delta, count;
124
125         if(hz)
126                 *hz = Basetickfreq;
127
128         /* avoid reentry on interrupt or trap, to prevent recursion */
129         x = splhi();
130         count = rdcount();
131         if(rdcompare() - count > m->maxperiod)
132                 wrcompare(count+m->maxperiod);
133         if (count < m->lastcount)               /* wrapped around? */
134                 delta = count + ((1ull<<32) - m->lastcount);
135         else
136                 delta = count - m->lastcount;
137         m->lastcount = count;
138         m->fastticks += delta;
139         splx(x);
140
141         return m->fastticks;
142 }
143
144 ulong
145 perfticks(void)
146 {
147         return rdcount();
148 }
149
150 void
151 timerset(Tval next)
152 {
153         int x;
154         long period;
155
156         if(next == 0)
157                 return;
158         x = splhi();                    /* don't let us get scheduled */
159         period = next - fastticks(nil);
160         if(period > m->maxperiod - m->minperiod)
161                 period = m->maxperiod;
162         else if(period < m->minperiod)
163                 period = m->minperiod;
164         wrcompare(rdcount()+period);
165         splx(x);
166
167 }