This source file includes following definitions.
- mktime
- time_init
- sys_time
- sys_stime
- do_gettimeoffset
- do_gettimeofday
- sys_gettimeofday
- warp_clock
- sys_settimeofday
- sys_adjtimex
- set_rtc_mmss
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
28 #include <asm/segment.h>
29 #include <asm/io.h>
30
31 #include <linux/mc146818rtc.h>
32 #include <linux/timex.h>
33
34
35
36
37
38
39
40
41
42
43
44
45 static inline unsigned long mktime(unsigned int year, unsigned int mon,
46 unsigned int day, unsigned int hour,
47 unsigned int min, unsigned int sec)
48 {
49 if (0 >= (int) (mon -= 2)) {
50 mon += 12;
51 year -= 1;
52 }
53 return (((
54 (unsigned long)(year/4 - year/100 + year/400 + 367*mon/12 + day) +
55 year*365 - 719499
56 )*24 + hour
57 )*60 + min
58 )*60 + sec;
59 }
60
61 void time_init(void)
62 {
63 unsigned int year, mon, day, hour, min, sec;
64 int i;
65
66
67
68
69
70
71
72 for (i = 0 ; i < 1000000 ; i++)
73 if (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP)
74 break;
75 for (i = 0 ; i < 1000000 ; i++)
76 if (!(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP))
77 break;
78 do {
79 sec = CMOS_READ(RTC_SECONDS);
80 min = CMOS_READ(RTC_MINUTES);
81 hour = CMOS_READ(RTC_HOURS);
82 day = CMOS_READ(RTC_DAY_OF_MONTH);
83 mon = CMOS_READ(RTC_MONTH);
84 year = CMOS_READ(RTC_YEAR);
85 } while (sec != CMOS_READ(RTC_SECONDS));
86 if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
87 {
88 BCD_TO_BIN(sec);
89 BCD_TO_BIN(min);
90 BCD_TO_BIN(hour);
91 BCD_TO_BIN(day);
92 BCD_TO_BIN(mon);
93 BCD_TO_BIN(year);
94 }
95 if ((year += 1900) < 1970)
96 year += 100;
97 xtime.tv_sec = mktime(year, mon, day, hour, min, sec);
98 xtime.tv_usec = 0;
99 }
100
101
102
103
104 struct timezone sys_tz = { 0, 0};
105
106 asmlinkage int sys_time(long * tloc)
107 {
108 int i, error;
109
110 i = CURRENT_TIME;
111 if (tloc) {
112 error = verify_area(VERIFY_WRITE, tloc, 4);
113 if (error)
114 return error;
115 put_fs_long(i,(unsigned long *)tloc);
116 }
117 return i;
118 }
119
120 asmlinkage int sys_stime(unsigned long * tptr)
121 {
122 int error;
123 unsigned long value;
124
125 if (!suser())
126 return -EPERM;
127 error = verify_area(VERIFY_READ, tptr, sizeof(*tptr));
128 if (error)
129 return error;
130 value = get_fs_long(tptr);
131 cli();
132 xtime.tv_sec = value;
133 xtime.tv_usec = 0;
134 time_status = TIME_BAD;
135 time_maxerror = 0x70000000;
136 time_esterror = 0x70000000;
137 sti();
138 return 0;
139 }
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173 #define TICK_SIZE tick
174
175 static inline unsigned long do_gettimeoffset(void)
176 {
177 int count;
178 unsigned long offset = 0;
179
180
181 outb_p(0x00, 0x43);
182 count = inb_p(0x40);
183 count |= inb(0x40) << 8;
184
185 if (count > (LATCH - LATCH/100)) {
186
187 outb_p(0x0a, 0x20);
188 if (inb(0x20) & 1)
189 offset = TICK_SIZE;
190 }
191 count = ((LATCH-1) - count) * TICK_SIZE;
192 count = (count + LATCH/2) / LATCH;
193 return offset + count;
194 }
195
196
197
198
199 void do_gettimeofday(struct timeval *tv)
200 {
201 unsigned long flags;
202
203 save_flags(flags);
204 cli();
205 #if defined (__i386__) || defined (__mips__)
206 *tv = xtime;
207 tv->tv_usec += do_gettimeoffset();
208 if (tv->tv_usec >= 1000000) {
209 tv->tv_usec -= 1000000;
210 tv->tv_sec++;
211 }
212 sti();
213 #else
214 cli();
215 *tv = xtime;
216 sti();
217 #endif
218 restore_flags(flags);
219 }
220
221 asmlinkage int sys_gettimeofday(struct timeval *tv, struct timezone *tz)
222 {
223 int error;
224
225 if (tv) {
226 struct timeval ktv;
227 error = verify_area(VERIFY_WRITE, tv, sizeof *tv);
228 if (error)
229 return error;
230 do_gettimeofday(&ktv);
231 put_fs_long(ktv.tv_sec, (unsigned long *) &tv->tv_sec);
232 put_fs_long(ktv.tv_usec, (unsigned long *) &tv->tv_usec);
233 }
234 if (tz) {
235 error = verify_area(VERIFY_WRITE, tz, sizeof *tz);
236 if (error)
237 return error;
238 put_fs_long(sys_tz.tz_minuteswest, (unsigned long *) tz);
239 put_fs_long(sys_tz.tz_dsttime, ((unsigned long *) tz)+1);
240 }
241 return 0;
242 }
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260 inline static void warp_clock(void)
261 {
262 cli();
263 xtime.tv_sec += sys_tz.tz_minuteswest * 60;
264 sti();
265 }
266
267
268
269
270
271
272
273
274
275
276 asmlinkage int sys_settimeofday(struct timeval *tv, struct timezone *tz)
277 {
278 static int firsttime = 1;
279 struct timeval new_tv;
280 struct timezone new_tz;
281
282 if (!suser())
283 return -EPERM;
284 if (tv) {
285 int error = verify_area(VERIFY_READ, tv, sizeof(*tv));
286 if (error)
287 return error;
288 memcpy_fromfs(&new_tv, tv, sizeof(*tv));
289 }
290 if (tz) {
291 int error = verify_area(VERIFY_READ, tz, sizeof(*tz));
292 if (error)
293 return error;
294 memcpy_fromfs(&new_tz, tz, sizeof(*tz));
295 }
296 if (tz) {
297 sys_tz = new_tz;
298 if (firsttime) {
299 firsttime = 0;
300 if (!tv)
301 warp_clock();
302 }
303 }
304 if (tv) {
305 cli();
306
307
308
309
310
311
312 new_tv.tv_usec -= do_gettimeoffset();
313
314 if (new_tv.tv_usec < 0) {
315 new_tv.tv_usec += 1000000;
316 new_tv.tv_sec--;
317 }
318
319 xtime = new_tv;
320 time_status = TIME_BAD;
321 time_maxerror = 0x70000000;
322 time_esterror = 0x70000000;
323 sti();
324 }
325 return 0;
326 }
327
328
329
330
331 asmlinkage int sys_adjtimex(struct timex *txc_p)
332 {
333 long ltemp, mtemp, save_adjust;
334 int error;
335
336
337 struct timex txc;
338
339 error = verify_area(VERIFY_WRITE, txc_p, sizeof(struct timex));
340 if (error)
341 return error;
342
343
344
345
346
347 memcpy_fromfs(&txc, txc_p, sizeof(struct timex));
348
349
350 if (txc.mode && !suser())
351 return -EPERM;
352
353
354
355
356 if (txc.mode != ADJ_OFFSET_SINGLESHOT && (txc.mode & ADJ_OFFSET))
357
358 if (txc.offset <= -(1 << (31 - SHIFT_UPDATE))
359 || txc.offset >= (1 << (31 - SHIFT_UPDATE)))
360 return -EINVAL;
361
362
363 if (txc.mode & ADJ_STATUS)
364 if (txc.status < TIME_OK || txc.status > TIME_BAD)
365 return -EINVAL;
366
367
368 if (txc.mode & ADJ_TICK)
369 if (txc.tick < 900000/HZ || txc.tick > 1100000/HZ)
370 return -EINVAL;
371
372 cli();
373
374
375 save_adjust = time_adjust;
376
377
378 if (txc.mode)
379 {
380 if (time_status == TIME_BAD)
381 time_status = TIME_OK;
382
383 if (txc.mode & ADJ_STATUS)
384 time_status = txc.status;
385
386 if (txc.mode & ADJ_FREQUENCY)
387 time_freq = txc.frequency << (SHIFT_KF - 16);
388
389 if (txc.mode & ADJ_MAXERROR)
390 time_maxerror = txc.maxerror;
391
392 if (txc.mode & ADJ_ESTERROR)
393 time_esterror = txc.esterror;
394
395 if (txc.mode & ADJ_TIMECONST)
396 time_constant = txc.time_constant;
397
398 if (txc.mode & ADJ_OFFSET)
399 if (txc.mode == ADJ_OFFSET_SINGLESHOT)
400 {
401 time_adjust = txc.offset;
402 }
403 else
404 {
405 time_offset = txc.offset << SHIFT_UPDATE;
406 mtemp = xtime.tv_sec - time_reftime;
407 time_reftime = xtime.tv_sec;
408 if (mtemp > (MAXSEC+2) || mtemp < 0)
409 mtemp = 0;
410
411 if (txc.offset < 0)
412 time_freq -= (-txc.offset * mtemp) >>
413 (time_constant + time_constant);
414 else
415 time_freq += (txc.offset * mtemp) >>
416 (time_constant + time_constant);
417
418 ltemp = time_tolerance << SHIFT_KF;
419
420 if (time_freq > ltemp)
421 time_freq = ltemp;
422 else if (time_freq < -ltemp)
423 time_freq = -ltemp;
424 }
425 if (txc.mode & ADJ_TICK)
426 tick = txc.tick;
427
428 }
429 txc.offset = save_adjust;
430 txc.frequency = ((time_freq+1) >> (SHIFT_KF - 16));
431 txc.maxerror = time_maxerror;
432 txc.esterror = time_esterror;
433 txc.status = time_status;
434 txc.time_constant = time_constant;
435 txc.precision = time_precision;
436 txc.tolerance = time_tolerance;
437 txc.time = xtime;
438 txc.tick = tick;
439
440 sti();
441
442 memcpy_tofs(txc_p, &txc, sizeof(struct timex));
443 return time_status;
444 }
445
446 int set_rtc_mmss(unsigned long nowtime)
447 {
448 int retval = 0;
449 int real_seconds, real_minutes, cmos_minutes;
450 unsigned char save_control, save_freq_select;
451
452 save_control = CMOS_READ(RTC_CONTROL);
453 CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL);
454
455 save_freq_select = CMOS_READ(RTC_FREQ_SELECT);
456 CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT);
457
458 cmos_minutes = CMOS_READ(RTC_MINUTES);
459 if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
460 BCD_TO_BIN(cmos_minutes);
461
462
463
464
465
466
467 real_seconds = nowtime % 60;
468 real_minutes = nowtime / 60;
469 if (((abs(real_minutes - cmos_minutes) + 15)/30) & 1)
470 real_minutes += 30;
471 real_minutes %= 60;
472
473 if (abs(real_minutes - cmos_minutes) < 30)
474 {
475 if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
476 {
477 BIN_TO_BCD(real_seconds);
478 BIN_TO_BCD(real_minutes);
479 }
480 CMOS_WRITE(real_seconds,RTC_SECONDS);
481 CMOS_WRITE(real_minutes,RTC_MINUTES);
482 }
483 else
484 retval = -1;
485
486 CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT);
487 CMOS_WRITE(save_control, RTC_CONTROL);
488 return retval;
489 }