1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21#include <linux/errno.h>
22#include <linux/sched.h>
23#include <linux/kernel.h>
24#include <linux/param.h>
25#include <linux/string.h>
26#include <linux/mm.h>
27#include <linux/timex.h>
28#include <linux/smp.h>
29#include <linux/smp_lock.h>
30
31#include <asm/uaccess.h>
32
33
34
35
36
37struct timezone sys_tz = { 0, 0};
38
39static void do_normal_gettime(struct timeval * tm)
40{
41 *tm=xtime;
42}
43
44void (*do_get_fast_time)(struct timeval *) = do_normal_gettime;
45
46
47
48
49
50
51
52void get_fast_time(struct timeval * t)
53{
54 do_get_fast_time(t);
55}
56
57#ifndef __alpha__
58
59
60
61
62
63
64
65asmlinkage int sys_time(int * tloc)
66{
67 int i;
68
69
70
71 i = CURRENT_TIME;
72 if (tloc) {
73 if (put_user(i,tloc))
74 i = -EFAULT;
75 }
76 return i;
77}
78
79
80
81
82
83
84
85
86asmlinkage int sys_stime(int * tptr)
87{
88 int value;
89
90 if (!suser())
91 return -EPERM;
92 if (get_user(value, tptr))
93 return -EFAULT;
94 cli();
95 xtime.tv_sec = value;
96 xtime.tv_usec = 0;
97 time_state = TIME_ERROR;
98 time_maxerror = MAXPHASE;
99 time_esterror = MAXPHASE;
100 sti();
101 return 0;
102}
103
104#endif
105
106asmlinkage int sys_gettimeofday(struct timeval *tv, struct timezone *tz)
107{
108 if (tv) {
109 struct timeval ktv;
110 do_gettimeofday(&ktv);
111 if (copy_to_user(tv, &ktv, sizeof(ktv)))
112 return -EFAULT;
113 }
114 if (tz) {
115 if (copy_to_user(tz, &sys_tz, sizeof(sys_tz)))
116 return -EFAULT;
117 }
118 return 0;
119}
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137inline static void warp_clock(void)
138{
139 cli();
140 xtime.tv_sec += sys_tz.tz_minuteswest * 60;
141 sti();
142}
143
144
145
146
147
148
149
150
151
152
153
154asmlinkage int sys_settimeofday(struct timeval *tv, struct timezone *tz)
155{
156 static int firsttime = 1;
157 struct timeval new_tv;
158 struct timezone new_tz;
159
160 if (!suser())
161 return -EPERM;
162
163 if (tv) {
164 if (copy_from_user(&new_tv, tv, sizeof(*tv)))
165 return -EFAULT;
166 }
167 if (tz) {
168 if (copy_from_user(&new_tz, tz, sizeof(*tz)))
169 return -EFAULT;
170
171
172 sys_tz = new_tz;
173 if (firsttime) {
174 firsttime = 0;
175 if (!tv)
176 warp_clock();
177 }
178 }
179 if (tv)
180 {
181
182
183
184 do_settimeofday(&new_tv);
185 }
186 return 0;
187}
188
189long pps_offset = 0;
190long pps_jitter = MAXTIME;
191
192long pps_freq = 0;
193long pps_stabil = MAXFREQ;
194
195long pps_valid = PPS_VALID;
196
197int pps_shift = PPS_SHIFT;
198
199long pps_jitcnt = 0;
200long pps_calcnt = 0;
201long pps_errcnt = 0;
202long pps_stbcnt = 0;
203
204
205void (*hardpps_ptr)(struct timeval *) = (void (*)(struct timeval *))0;
206
207
208
209
210asmlinkage int sys_adjtimex(struct timex *txc_p)
211{
212 long ltemp, mtemp, save_adjust;
213 struct timex txc;
214
215
216
217
218
219 if(copy_from_user(&txc, txc_p, sizeof(struct timex)))
220 return -EFAULT;
221
222
223 if (txc.modes && !suser())
224 return -EPERM;
225
226
227
228 if (txc.modes != ADJ_OFFSET_SINGLESHOT && (txc.modes & ADJ_OFFSET))
229
230 if (txc.offset <= - MAXPHASE || txc.offset >= MAXPHASE )
231 return -EINVAL;
232
233
234 if (txc.modes & ADJ_TICK)
235 if (txc.tick < 900000/HZ || txc.tick > 1100000/HZ)
236 return -EINVAL;
237
238 cli();
239
240
241 save_adjust = time_adjust;
242
243
244 if (txc.modes)
245 {
246 if (time_state == TIME_BAD)
247 time_state = TIME_OK;
248
249 if (txc.modes & ADJ_STATUS)
250 time_status = txc.status;
251
252 if (txc.modes & ADJ_FREQUENCY)
253 time_freq = txc.freq;
254
255 if (txc.modes & ADJ_MAXERROR)
256 time_maxerror = txc.maxerror;
257
258 if (txc.modes & ADJ_ESTERROR)
259 time_esterror = txc.esterror;
260
261 if (txc.modes & ADJ_TIMECONST)
262 time_constant = txc.constant;
263
264 if (txc.modes & ADJ_OFFSET)
265 if ((txc.modes == ADJ_OFFSET_SINGLESHOT)
266 || !(time_status & STA_PLL))
267 {
268 time_adjust = txc.offset;
269 }
270 else if ((time_status & STA_PLL)||(time_status & STA_PPSTIME))
271 {
272 ltemp = (time_status & STA_PPSTIME &&
273 time_status & STA_PPSSIGNAL) ?
274 pps_offset : txc.offset;
275
276
277
278
279
280 if (ltemp > MAXPHASE)
281 time_offset = MAXPHASE << SHIFT_UPDATE;
282 else if (ltemp < -MAXPHASE)
283 time_offset = -(MAXPHASE << SHIFT_UPDATE);
284 else
285 time_offset = ltemp << SHIFT_UPDATE;
286
287
288
289
290
291
292
293 if (time_status & STA_FREQHOLD || time_reftime == 0)
294 time_reftime = xtime.tv_sec;
295 mtemp = xtime.tv_sec - time_reftime;
296 time_reftime = xtime.tv_sec;
297 if (time_status & STA_FLL)
298 {
299 if (mtemp >= MINSEC)
300 {
301 ltemp = ((time_offset / mtemp) << (SHIFT_USEC -
302 SHIFT_UPDATE));
303 if (ltemp < 0)
304 time_freq -= -ltemp >> SHIFT_KH;
305 else
306 time_freq += ltemp >> SHIFT_KH;
307 }
308 }
309 else
310 {
311 if (mtemp < MAXSEC)
312 {
313 ltemp *= mtemp;
314 if (ltemp < 0)
315 time_freq -= -ltemp >> (time_constant +
316 time_constant + SHIFT_KF -
317 SHIFT_USEC);
318 else
319 time_freq += ltemp >> (time_constant +
320 time_constant + SHIFT_KF -
321 SHIFT_USEC);
322 }
323 }
324 if (time_freq > time_tolerance)
325 time_freq = time_tolerance;
326 else if (time_freq < -time_tolerance)
327 time_freq = -time_tolerance;
328 }
329 if (txc.modes & ADJ_TICK)
330 tick = txc.tick;
331
332 }
333 txc.offset = save_adjust;
334 txc.freq = time_freq;
335 txc.maxerror = time_maxerror;
336 txc.esterror = time_esterror;
337 txc.status = time_status;
338 txc.constant = time_constant;
339 txc.precision = time_precision;
340 txc.tolerance = time_tolerance;
341 txc.time = xtime;
342 txc.tick = tick;
343 txc.ppsfreq = pps_freq;
344 txc.jitter = pps_jitter;
345 txc.shift = pps_shift;
346 txc.stabil = pps_stabil;
347 txc.jitcnt = pps_jitcnt;
348 txc.calcnt = pps_calcnt;
349 txc.errcnt = pps_errcnt;
350 txc.stbcnt = pps_stbcnt;
351
352 sti();
353
354 return copy_to_user(txc_p, &txc, sizeof(struct timex)) ? -EFAULT : time_state;
355}
356