root/kernel/time.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. mktime
  2. time_init
  3. sys_time
  4. sys_stime
  5. do_gettimeoffset
  6. do_gettimeofday
  7. sys_gettimeofday
  8. warp_clock
  9. sys_settimeofday
  10. sys_adjtimex
  11. set_rtc_mmss

   1 /*
   2  *  linux/kernel/time.c
   3  *
   4  *  Copyright (C) 1991, 1992  Linus Torvalds
   5  *
   6  *  This file contains the interface functions for the various
   7  *  time related system calls: time, stime, gettimeofday, settimeofday,
   8  *                             adjtime
   9  */
  10 /*
  11  * Modification history kernel/time.c
  12  * 
  13  * 02 Sep 93    Philip Gladstone
  14  *      Created file with time related functions from sched.c and adjtimex() 
  15  * 08 Oct 93    Torsten Duwe
  16  *      adjtime interface update and CMOS clock write code
  17  * 02 Jul 94    Alan Modra
  18  *      fixed set_rtc_mmss, fixed time.year for >= 2000, new mktime
  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 /* converts date to days since 1/1/1970
  35  * assumes year,mon,day in normal date format
  36  * ie. 1/1/1970 => year=1970, mon=1, day=1
  37  *
  38  * For the Julian calendar (which was used in Russia before 1917,
  39  * Britain & colonies before 1752, anywhere else before 1582,
  40  * and is still in use by some communities) leave out the
  41  * -year/100+year/400 terms, and add 10.
  42  *
  43  * This algorithm was first published by Gauss (I think).
  44  */
  45 static inline unsigned long mktime(unsigned int year, unsigned int mon,
     /* [previous][next][first][last][top][bottom][index][help] */
  46         unsigned int day, unsigned int hour,
  47         unsigned int min, unsigned int sec)
  48 {
  49         if (0 >= (int) (mon -= 2)) {    /* 1..12 -> 11,12,1..10 */
  50                 mon += 12;      /* Puts Feb last since it has leap day */
  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 /* now have hours */
  57            )*60 + min /* now have minutes */
  58           )*60 + sec; /* finally seconds */
  59 }
  60 
  61 void time_init(void)
     /* [previous][next][first][last][top][bottom][index][help] */
  62 {
  63         unsigned int year, mon, day, hour, min, sec;
  64         int i;
  65 
  66         /* checking for Update-In-Progress could be done more elegantly
  67          * (using the "update finished"-interrupt for example), but that
  68          * would require excessive testing. promise I'll do that when I find
  69          * the time.                    - Torsten
  70          */
  71         /* read RTC exactly on falling edge of update flag */
  72         for (i = 0 ; i < 1000000 ; i++) /* may take up to 1 second... */
  73                 if (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP)
  74                         break;
  75         for (i = 0 ; i < 1000000 ; i++) /* must try at least 2.228 ms*/
  76                 if (!(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP))
  77                         break;
  78         do { /* Isn't this overkill ? UIP above should guarantee consistency */
  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  * The timezone where the local system is located.  Used as a default by some
 102  * programs who obtain this value by using gettimeofday.
 103  */
 104 struct timezone sys_tz = { 0, 0};
 105 
 106 asmlinkage int sys_time(long * tloc)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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 /* This function must be called with interrupts disabled 
 142  * It was inspired by Steve McCanne's microtime-i386 for BSD.  -- jrs
 143  * 
 144  * However, the pc-audio speaker driver changes the divisor so that
 145  * it gets interrupted rather more often - it loads 64 into the
 146  * counter rather than 11932! This has an adverse impact on
 147  * do_gettimeoffset() -- it stops working! What is also not
 148  * good is that the interval that our timer function gets called
 149  * is no longer 10.0002 msecs, but 9.9767 msec. To get around this
 150  * would require using a different timing source. Maybe someone
 151  * could use the RTC - I know that this can interrupt at frequencies
 152  * ranging from 8192Hz to 2Hz. If I had the energy, I'd somehow fix
 153  * it so that at startup, the timer code in sched.c would select
 154  * using either the RTC or the 8253 timer. The decision would be
 155  * based on whether there was any other device around that needed
 156  * to trample on the 8253. I'd set up the RTC to interrupt at 1024Hz,
 157  * and then do some jiggery to have a version of do_timer that 
 158  * advanced the clock by 1/1024 sec. Every time that reached over 1/100
 159  * of a second, then do all the old code. If the time was kept correct
 160  * then do_gettimeoffset could just return 0 - there is no low order
 161  * divider that can be accessed.
 162  *
 163  * Ideally, you would be able to use the RTC for the speaker driver,
 164  * but it appears that the speaker driver really needs interrupt more
 165  * often than every 120us or so.
 166  *
 167  * Anyway, this needs more thought....          pjsg (28 Aug 93)
 168  * 
 169  * If you are really that interested, you should be reading
 170  * comp.protocols.time.ntp!
 171  */
 172 
 173 #define TICK_SIZE tick
 174 
 175 static inline unsigned long do_gettimeoffset(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 176 {
 177         int count;
 178         unsigned long offset = 0;
 179 
 180         /* timer count may underflow right here */
 181         outb_p(0x00, 0x43);     /* latch the count ASAP */
 182         count = inb_p(0x40);    /* read the latched count */
 183         count |= inb(0x40) << 8;
 184         /* we know probability of underflow is always MUCH less than 1% */
 185         if (count > (LATCH - LATCH/100)) {
 186                 /* check for pending timer interrupt */
 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  * This version of gettimeofday has near microsecond resolution.
 198  */
 199 void do_gettimeofday(struct timeval *tv)
     /* [previous][next][first][last][top][bottom][index][help] */
 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 /* !defined (__i386__) && !defined (__mips__) */
 214         cli();
 215         *tv = xtime;
 216         sti();
 217 #endif /* !defined (__i386__) && !defined (__mips__) */
 218         restore_flags(flags);
 219 }
 220 
 221 asmlinkage int sys_gettimeofday(struct timeval *tv, struct timezone *tz)
     /* [previous][next][first][last][top][bottom][index][help] */
 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  * Adjust the time obtained from the CMOS to be GMT time instead of
 246  * local time.
 247  * 
 248  * This is ugly, but preferable to the alternatives.  Otherwise we
 249  * would either need to write a program to do it in /etc/rc (and risk
 250  * confusion if the program gets run more than once; it would also be 
 251  * hard to make the program warp the clock precisely n hours)  or
 252  * compile in the timezone information into the kernel.  Bad, bad....
 253  *
 254  * XXX Currently does not adjust for daylight savings time.  May not
 255  * need to do anything, depending on how smart (dumb?) the BIOS
 256  * is.  Blast it all.... the best thing to do not depend on the CMOS
 257  * clock at all, but get the time via NTP or timed if you're on a 
 258  * network....                          - TYT, 1/1/92
 259  */
 260 inline static void warp_clock(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 261 {
 262         cli();
 263         xtime.tv_sec += sys_tz.tz_minuteswest * 60;
 264         sti();
 265 }
 266 
 267 /*
 268  * The first time we set the timezone, we will warp the clock so that
 269  * it is ticking GMT time instead of local time.  Presumably, 
 270  * if someone is setting the timezone then we are running in an
 271  * environment where the programs understand about timezones.
 272  * This should be done at boot time in the /etc/rc script, as
 273  * soon as possible, so that the clock can be set right.  Otherwise,
 274  * various programs will get confused when the clock gets warped.
 275  */
 276 asmlinkage int sys_settimeofday(struct timeval *tv, struct timezone *tz)
     /* [previous][next][first][last][top][bottom][index][help] */
 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                 /* This is revolting. We need to set the xtime.tv_usec
 307                  * correctly. However, the value in this location is
 308                  * is value at the last tick.
 309                  * Discover what correction gettimeofday
 310                  * would have done, and then undo it!
 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 /* adjtimex mainly allows reading (and writing, if superuser) of
 329  * kernel time-keeping variables. used by xntpd.
 330  */
 331 asmlinkage int sys_adjtimex(struct timex *txc_p)
     /* [previous][next][first][last][top][bottom][index][help] */
 332 {
 333         long ltemp, mtemp, save_adjust;
 334         int error;
 335 
 336         /* Local copy of parameter */
 337         struct timex txc;
 338 
 339         error = verify_area(VERIFY_WRITE, txc_p, sizeof(struct timex));
 340         if (error)
 341           return error;
 342 
 343         /* Copy the user data space into the kernel copy
 344          * structure. But bear in mind that the structures
 345          * may change
 346          */
 347         memcpy_fromfs(&txc, txc_p, sizeof(struct timex));
 348 
 349         /* In order to modify anything, you gotta be super-user! */
 350         if (txc.mode && !suser())
 351                 return -EPERM;
 352 
 353         /* Now we validate the data before disabling interrupts
 354          */
 355 
 356         if (txc.mode != ADJ_OFFSET_SINGLESHOT && (txc.mode & ADJ_OFFSET))
 357           /* Microsec field limited to -131000 .. 131000 usecs */
 358           if (txc.offset <= -(1 << (31 - SHIFT_UPDATE))
 359               || txc.offset >= (1 << (31 - SHIFT_UPDATE)))
 360             return -EINVAL;
 361 
 362         /* time_status must be in a fairly small range */
 363         if (txc.mode & ADJ_STATUS)
 364           if (txc.status < TIME_OK || txc.status > TIME_BAD)
 365             return -EINVAL;
 366 
 367         /* if the quartz is off by more than 10% something is VERY wrong ! */
 368         if (txc.mode & ADJ_TICK)
 369           if (txc.tick < 900000/HZ || txc.tick > 1100000/HZ)
 370             return -EINVAL;
 371 
 372         cli();
 373 
 374         /* Save for later - semantics of adjtime is to return old value */
 375         save_adjust = time_adjust;
 376 
 377         /* If there are input parameters, then process them */
 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 /* XXX should give an error if other bits set */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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); /* tell the clock it's being set */
 453   CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL);
 454 
 455   save_freq_select = CMOS_READ(RTC_FREQ_SELECT); /* stop and reset prescaler */
 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   /* since we're only adjusting minutes and seconds,
 463    * don't interfere with hour overflow. This avoids
 464    * messing with unknown time zones but requires your
 465    * RTC not to be off by more than 15 minutes
 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;         /* correct for half hour time zone */
 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 }

/* [previous][next][first][last][top][bottom][index][help] */