root/drivers/char/rtc.c

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

DEFINITIONS

This source file includes following definitions.
  1. rtc_interrupt
  2. rtc_lseek
  3. rtc_read
  4. rtc_ioctl
  5. rtc_open
  6. rtc_release
  7. rtc_select
  8. rtc_init
  9. get_rtc_status
  10. rtc_is_updating
  11. get_rtc_time
  12. get_rtc_alm_time
  13. mask_rtc_irq_bit
  14. set_rtc_irq_bit

   1 /*
   2  *      Real Time Clock interface for Linux     
   3  *
   4  *      Copyright (C) 1996 Paul Gortmaker
   5  *
   6  *      This driver allows use of the real time clock (built into
   7  *      nearly all computers) from user space. It exports the /dev/rtc
   8  *      interface supporting various ioctl() and also the /proc/rtc
   9  *      pseudo-file for status information.
  10  *
  11  *      The ioctls can be used to set the interrupt behaviour and
  12  *      generation rate from the RTC via IRQ 8. Then the /dev/rtc
  13  *      interface can be used to make use of these timer interrupts,
  14  *      be they interval or alarm based.
  15  *
  16  *      The /dev/rtc interface will block on reads until an interrupt
  17  *      has been received. If a RTC interrupt has already happened,
  18  *      it will output an unsigned long and then block. The output value
  19  *      contains the interrupt status in the low byte and the number of
  20  *      interrupts since the last read in the remaining high bytes. The 
  21  *      /dev/rtc interface can also be used with the select(2) call.
  22  *
  23  *      This program is free software; you can redistribute it and/or
  24  *      modify it under the terms of the GNU General Public License
  25  *      as published by the Free Software Foundation; either version
  26  *      2 of the License, or (at your option) any later version.
  27  *
  28  *      Based on other minimal char device drivers, like Alan's
  29  *      watchdog, Ted's random, etc. etc.
  30  *
  31  */
  32 
  33 #define RTC_VERSION             "1.04"
  34 
  35 #define RTC_IRQ         8       /* Can't see this changing soon.        */
  36 #define RTC_IO_BASE     0x70    /* Or this...                           */
  37 #define RTC_IO_EXTENT   0x10    /* Only really 0x70 to 0x71, but...     */
  38 
  39 /*
  40  *      Note that *all* calls to CMOS_READ and CMOS_WRITE are done with
  41  *      interrupts disabled. Due to the index-port/data-port (0x70/0x71)
  42  *      design of the RTC, we don't want two different things trying to
  43  *      get to it at once. (e.g. the periodic 11 min sync from time.c vs.
  44  *      this driver.)
  45  */
  46 
  47 #include <linux/types.h>
  48 #include <linux/errno.h>
  49 #include <linux/miscdevice.h>
  50 #include <linux/malloc.h>
  51 #include <linux/ioport.h>
  52 #include <linux/fcntl.h>
  53 #include <linux/mc146818rtc.h>
  54 
  55 #include <asm/io.h>
  56 #include <asm/segment.h>
  57 #include <asm/system.h>
  58 
  59 #include <time.h>
  60 
  61 /*
  62  *      We sponge a minor off of the misc major. No need slurping
  63  *      up another valuable major dev number for this.
  64  */
  65 
  66 #define RTC_MINOR       135
  67 
  68 static struct wait_queue *rtc_wait;
  69 
  70 static int rtc_lseek(struct inode *inode, struct file *file, off_t offset,
  71                         int origin);
  72 
  73 static int rtc_read(struct inode *inode, struct file *file,
  74                         char *buf, int count);
  75 
  76 static int rtc_ioctl(struct inode *inode, struct file *file,
  77                         unsigned int cmd, unsigned long arg);
  78 
  79 static int rtc_select(struct inode *inode, struct file *file,
  80                         int sel_type, select_table *wait);
  81 
  82 void get_rtc_time (struct tm *rtc_tm);
  83 void get_rtc_alm_time (struct tm *alm_tm);
  84 
  85 inline void set_rtc_irq_bit(unsigned char bit);
  86 inline void mask_rtc_irq_bit(unsigned char bit);
  87 
  88 unsigned char rtc_is_updating(void);
  89 
  90 /*
  91  *      Bits in rtc_status. (7 bits of room for future expansion)
  92  */
  93 
  94 #define RTC_IS_OPEN             0x01    /* means /dev/rtc is in use     */
  95 
  96 unsigned char rtc_status = 0;           /* bitmapped status byte.       */
  97 unsigned long rtc_irq_data = 0;         /* our output to the world      */
  98 
  99 unsigned char days_in_mo[] = 
 100                 {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
 101 
 102 /*
 103  *      A very tiny interrupt handler. It runs with SA_INTERRUPT set,
 104  *      so that there is no possibility of conflicting with the
 105  *      set_rtc_mmss() call that happens during some timer interrupts.
 106  *      (See ./arch/XXXX/kernel/time.c for the set_rtc_mmss() function.)
 107  */
 108 
 109 static void rtc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
     /* [previous][next][first][last][top][bottom][index][help] */
 110 {
 111         /*
 112          *      Can be an alarm interrupt, update complete interrupt,
 113          *      or a periodic interrupt. We store the status in the
 114          *      low byte and the number of interrupts received since
 115          *      the last read in the remainder of rtc_irq_data.
 116          */
 117 
 118         rtc_irq_data += 0x100;
 119         rtc_irq_data &= ~0xff;
 120         rtc_irq_data |= (CMOS_READ(RTC_INTR_FLAGS) & 0xF0);
 121         wake_up_interruptible(&rtc_wait);       
 122 }
 123 
 124 /*
 125  *      Now all the various file operations that we export.
 126  */
 127 
 128 static int rtc_lseek(struct inode *inode, struct file *file, off_t offset,
     /* [previous][next][first][last][top][bottom][index][help] */
 129         int origin)
 130 {
 131         return -ESPIPE;
 132 }
 133 
 134 static int rtc_read(struct inode *inode, struct file *file, char *buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 135 {
 136         struct wait_queue wait = { current, NULL };
 137         int retval;
 138         
 139         if (count < sizeof(unsigned long))
 140                 return -EINVAL;
 141 
 142         retval = verify_area(VERIFY_WRITE, buf, sizeof(unsigned long));
 143         if (retval)
 144                 return retval;
 145 
 146         add_wait_queue(&rtc_wait, &wait);
 147 
 148         current->state = TASK_INTERRUPTIBLE;
 149                 
 150         while (rtc_irq_data == 0) {
 151                 if (file->f_flags & O_NONBLOCK) {
 152                         retval = -EAGAIN;
 153                         break;
 154                 }
 155                 if (current->signal & ~current->blocked) {
 156                         retval = -ERESTARTSYS;
 157                         break;
 158                 }
 159                 schedule();
 160                 continue;
 161         }
 162 
 163         if (retval == 0) {
 164                 memcpy_tofs(buf, &rtc_irq_data, sizeof(unsigned long));
 165                 rtc_irq_data = 0;
 166                 retval = sizeof(unsigned long);
 167         }
 168 
 169         current->state = TASK_RUNNING;
 170         remove_wait_queue(&rtc_wait, &wait);
 171 
 172         return retval;
 173 }
 174 
 175 static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
     /* [previous][next][first][last][top][bottom][index][help] */
 176         unsigned long arg)
 177 {
 178 
 179         unsigned long flags;
 180 
 181         switch (cmd) {
 182                 case RTC_AIE_OFF:       /* Mask alarm int. enab. bit    */
 183                 {
 184                         mask_rtc_irq_bit(RTC_AIE);
 185                         return 0;
 186                 }
 187                 case RTC_AIE_ON:        /* Allow alarm interrupts.      */
 188                 {
 189                         set_rtc_irq_bit(RTC_AIE);
 190                         return 0;
 191                 }
 192                 case RTC_PIE_OFF:       /* Mask periodic int. enab. bit */
 193                 {
 194                         mask_rtc_irq_bit(RTC_PIE);
 195                         return 0;
 196                 }
 197                 case RTC_PIE_ON:        /* Allow periodic ints          */
 198                 {
 199                         unsigned int hz;
 200                         unsigned char tmp;
 201 
 202                         save_flags(flags);
 203                         cli();
 204                         tmp = CMOS_READ(RTC_FREQ_SELECT) & 0x0f;
 205                         restore_flags(flags);
 206 
 207                         hz = (tmp ? (65536/(1<<tmp)) : 0);
 208 
 209                         /*
 210                          * We don't really want Joe User enabling more
 211                          * than 64Hz of interrupts on a multi-user machine.
 212                          */
 213                         if ((hz > 64) && (!suser()))
 214                                 return -EPERM;
 215 
 216                         set_rtc_irq_bit(RTC_PIE);
 217                         return 0;
 218                 }
 219                 case RTC_UIE_OFF:       /* Mask ints from RTC updates.  */
 220                 {
 221                         mask_rtc_irq_bit(RTC_UIE);
 222                         return 0;
 223                 }
 224                 case RTC_UIE_ON:        /* Allow ints for RTC updates.  */
 225                 {
 226                         set_rtc_irq_bit(RTC_UIE);
 227                         return 0;
 228                 }
 229                 case RTC_ALM_READ:      /* Read the present alarm time */
 230                 {
 231                         /*
 232                          * This returns a struct tm. Reading >= 0xc0 means
 233                          * "don't care" or "match all". Only the tm_hour,
 234                          * tm_min, and tm_sec values are filled in.
 235                          */
 236                         int retval;
 237                         struct tm alm_tm;
 238 
 239                         retval = verify_area(VERIFY_WRITE, (struct tm*)arg, sizeof(struct tm));
 240                         if (retval != 0 )
 241                                 return retval;
 242 
 243                         get_rtc_alm_time(&alm_tm);
 244 
 245                         memcpy_tofs((struct tm*)arg, &alm_tm, sizeof(struct tm));
 246                         
 247                         return 0;
 248                 }
 249                 case RTC_ALM_SET:       /* Store a time into the alarm */
 250                 {
 251                         /*
 252                          * This expects a struct tm. Writing 0xff means
 253                          * "don't care" or "match all". Only the tm_hour,
 254                          * tm_min and tm_sec are used.
 255                          */
 256                         int retval;
 257                         unsigned char hrs, min, sec;
 258                         struct tm alm_tm;
 259 
 260                         retval = verify_area(VERIFY_READ, (struct tm*)arg, sizeof(struct tm));
 261                         if (retval != 0 )
 262                                 return retval;
 263 
 264                         memcpy_fromfs(&alm_tm, (struct tm*)arg, sizeof(struct tm));
 265 
 266                         hrs = alm_tm.tm_hour;
 267                         min = alm_tm.tm_min;
 268                         sec = alm_tm.tm_sec;
 269 
 270                         if (hrs >= 24)
 271                                 hrs = 0xff;
 272 
 273                         if (min >= 60)
 274                                 min = 0xff;
 275 
 276                         if (sec >= 60)
 277                                 sec = 0xff;
 278 
 279                         save_flags(flags);
 280                         cli();
 281                         if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) ||
 282                                                         RTC_ALWAYS_BCD)
 283                         {
 284                                 BIN_TO_BCD(sec);
 285                                 BIN_TO_BCD(min);
 286                                 BIN_TO_BCD(hrs);
 287                         }
 288                         CMOS_WRITE(hrs, RTC_HOURS_ALARM);
 289                         CMOS_WRITE(min, RTC_MINUTES_ALARM);
 290                         CMOS_WRITE(sec, RTC_SECONDS_ALARM);
 291                         restore_flags(flags);
 292 
 293                         return 0;
 294                 }
 295                 case RTC_RD_TIME:       /* Read the time/date from RTC  */
 296                 {
 297                         int retval;
 298                         struct tm rtc_tm;
 299                         
 300                         retval = verify_area(VERIFY_WRITE, (struct tm*)arg, sizeof(struct tm));
 301                         if (retval !=0 )
 302                                 return retval;
 303 
 304                         get_rtc_time(&rtc_tm);
 305                         memcpy_tofs((struct tm*)arg, &rtc_tm, sizeof(struct tm));
 306                         return 0;
 307                 }
 308                 case RTC_SET_TIME:      /* Set the RTC */
 309                 {
 310                         int retval;
 311                         struct tm rtc_tm;
 312                         unsigned char mon, day, hrs, min, sec, leap_yr;
 313                         unsigned char save_control, save_freq_select;
 314                         unsigned int yrs;
 315                         unsigned long flags;
 316                         
 317                         if (!suser())
 318                                 return -EPERM;
 319 
 320                         retval = verify_area(VERIFY_READ, (struct tm*)arg, sizeof(struct tm));
 321                         if (retval !=0 )
 322                                 return retval;
 323 
 324                         memcpy_fromfs(&rtc_tm, (struct tm*)arg, sizeof(struct tm));
 325 
 326                         yrs = rtc_tm.tm_year + 1900;
 327                         mon = rtc_tm.tm_mon + 1;   /* tm_mon starts at zero */
 328                         day = rtc_tm.tm_mday;
 329                         hrs = rtc_tm.tm_hour;
 330                         min = rtc_tm.tm_min;
 331                         sec = rtc_tm.tm_sec;
 332 
 333                         if ((yrs < 1970) || (yrs > 2069))
 334                                 return -EINVAL;
 335 
 336                         leap_yr = ((!(yrs % 4) && (yrs % 100)) || !(yrs % 400));
 337 
 338                         if ((mon > 12) || (day == 0))
 339                                 return -EINVAL;
 340 
 341                         if (day > (days_in_mo[mon] + ((mon == 2) && leap_yr)))
 342                                 return -EINVAL;
 343                         
 344                         if ((hrs >= 24) || (min >= 60) || (sec >= 60))
 345                                 return -EINVAL;
 346 
 347                         if (yrs >= 2000)
 348                                 yrs -= 2000;    /* RTC (0, 1, ... 69) */
 349                         else
 350                                 yrs -= 1900;    /* RTC (70, 71, ... 99) */
 351 
 352                         save_flags(flags);
 353                         cli();
 354                         if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) ||
 355                                                         RTC_ALWAYS_BCD)
 356                         {
 357                                 BIN_TO_BCD(sec);
 358                                 BIN_TO_BCD(min);
 359                                 BIN_TO_BCD(hrs);
 360                                 BIN_TO_BCD(day);
 361                                 BIN_TO_BCD(mon);
 362                                 BIN_TO_BCD(yrs);
 363                         }
 364 
 365                         save_control = CMOS_READ(RTC_CONTROL);
 366                         CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL);
 367                         save_freq_select = CMOS_READ(RTC_FREQ_SELECT);
 368                         CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT);
 369 
 370                         CMOS_WRITE(yrs, RTC_YEAR);
 371                         CMOS_WRITE(mon, RTC_MONTH);
 372                         CMOS_WRITE(day, RTC_DAY_OF_MONTH);
 373                         CMOS_WRITE(hrs, RTC_HOURS);
 374                         CMOS_WRITE(min, RTC_MINUTES);
 375                         CMOS_WRITE(sec, RTC_SECONDS);
 376 
 377                         CMOS_WRITE(save_control, RTC_CONTROL);
 378                         CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT);
 379 
 380                         restore_flags(flags);
 381                         return 0;
 382                 }
 383                 case RTC_IRQP_READ:     /* Read the periodic IRQ rate.  */
 384                 {
 385                         unsigned long hz;
 386                         int retval;
 387 
 388                         retval = verify_area(VERIFY_WRITE, (unsigned long*)arg, sizeof(unsigned long));
 389                         if (retval != 0)
 390                                 return retval;
 391 
 392                         save_flags(flags);
 393                         cli();
 394                         retval = CMOS_READ(RTC_FREQ_SELECT) & 0x0f;
 395                         restore_flags(flags);
 396                         hz = (retval ? (65536/(1<<retval)) : 0);
 397                         memcpy_tofs((unsigned long*)arg, &hz, sizeof(unsigned long));
 398                         return 0;
 399                 }
 400                 case RTC_IRQP_SET:      /* Set periodic IRQ rate.       */
 401                 {
 402                         int tmp = 0;
 403                         unsigned char val;
 404 
 405                         /* 
 406                          * The max we can do is 8192Hz.
 407                          */
 408                         if (arg > 8192)
 409                                 return -EINVAL;
 410                         /*
 411                          * We don't really want Joe User generating more
 412                          * than 64Hz of interrupts on a multi-user machine.
 413                          */
 414                         if ((arg > 64) && (!suser()))
 415                                 return -EPERM;
 416 
 417                         while (arg > (1<<tmp))
 418                                 tmp++;
 419 
 420                         /*
 421                          * Check that the input was really a power of 2.
 422                          */
 423                         if ((arg != 0) && (arg != (1<<tmp)))
 424                                 return -EINVAL;
 425 
 426                         save_flags(flags);
 427                         cli();
 428                         val = CMOS_READ(RTC_FREQ_SELECT) & 0xf0;
 429 
 430                         if (arg == 0) {
 431                                 CMOS_WRITE(val, RTC_FREQ_SELECT);
 432                                 restore_flags(flags);
 433                                 return 0;
 434                         }
 435 
 436                         val |= (16 - tmp);
 437                         CMOS_WRITE(val, RTC_FREQ_SELECT);
 438                         restore_flags(flags);
 439                         return 0;
 440                 }
 441                 default:
 442                         return -EINVAL;
 443         }
 444 }
 445 
 446 /*
 447  *      We enforce only one user at a time here with the open/close.
 448  *      Also clear the previous interrupt data on an open, and clean
 449  *      up things on a close.
 450  */
 451 
 452 static int rtc_open(struct inode *inode, struct file *file)
     /* [previous][next][first][last][top][bottom][index][help] */
 453 {
 454 
 455         if(rtc_status & RTC_IS_OPEN)
 456                 return -EBUSY;
 457 
 458         rtc_status |= RTC_IS_OPEN;
 459         rtc_irq_data = 0;
 460         return 0;
 461 }
 462 
 463 static void rtc_release(struct inode *inode, struct file *file)
     /* [previous][next][first][last][top][bottom][index][help] */
 464 {
 465 
 466         /*
 467          * Turn off all interrupts once the device is no longer
 468          * in use, and clear the data.
 469          */
 470 
 471         unsigned char tmp;
 472         unsigned long flags;
 473 
 474         save_flags(flags);
 475         cli();
 476         tmp = CMOS_READ(RTC_CONTROL);
 477         tmp &=  ~RTC_PIE;
 478         tmp &=  ~RTC_AIE;
 479         tmp &=  ~RTC_UIE;
 480         CMOS_WRITE(tmp, RTC_CONTROL);
 481         CMOS_READ(RTC_INTR_FLAGS);
 482         restore_flags(flags);
 483         rtc_irq_data = 0;
 484         rtc_status &= ~RTC_IS_OPEN;
 485 }
 486 
 487 static int rtc_select(struct inode *inode, struct file *file,
     /* [previous][next][first][last][top][bottom][index][help] */
 488                         int sel_type, select_table *wait)
 489 {
 490         if (sel_type == SEL_IN) {
 491                 if (rtc_irq_data != 0)
 492                         return 1;
 493                 select_wait(&rtc_wait, wait);
 494         }
 495         return 0;
 496 }
 497 
 498 /*
 499  *      The various file operations we support.
 500  */
 501 
 502 static struct file_operations rtc_fops = {
 503         rtc_lseek,
 504         rtc_read,
 505         NULL,           /* No write */
 506         NULL,           /* No readdir */
 507         rtc_select,
 508         rtc_ioctl,
 509         NULL,           /* No mmap */
 510         rtc_open,
 511         rtc_release
 512 };
 513 
 514 static struct miscdevice rtc_dev=
 515 {
 516         RTC_MINOR,
 517         "rtc",
 518         &rtc_fops
 519 };
 520 
 521 int rtc_init(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 522 {
 523         printk("Real Time Clock Driver v%s\n", RTC_VERSION);
 524         if(request_irq(RTC_IRQ, rtc_interrupt, SA_INTERRUPT, "rtc", NULL))
 525         {
 526                 /* Yeah right, seeing as irq 8 doesn't even hit the bus. */
 527                 printk("rtc: IRQ %d is not free.\n", RTC_IRQ);
 528                 return -EIO;
 529         }
 530         misc_register(&rtc_dev);
 531         /* Check region? Naaah! Just snarf it up. */
 532         request_region(RTC_IO_BASE, RTC_IO_EXTENT, "rtc");
 533         rtc_wait = NULL;
 534         return 0;
 535 }
 536 
 537 /*
 538  *      Info exported via "/proc/rtc".
 539  */
 540 
 541 int get_rtc_status(char *buf)
     /* [previous][next][first][last][top][bottom][index][help] */
 542 {
 543         char *p;
 544         struct tm tm;
 545         unsigned char freq, batt, ctrl;
 546         unsigned long flags;
 547 
 548         save_flags(flags);
 549         freq = CMOS_READ(RTC_FREQ_SELECT) & 0x0F;
 550         batt = CMOS_READ(RTC_VALID) & RTC_VRT;
 551         ctrl = CMOS_READ(RTC_CONTROL);
 552         restore_flags(flags);
 553 
 554         p = buf;
 555         p += sprintf(p, "Real Time Clock Status:\n");
 556 
 557         get_rtc_time(&tm);
 558 
 559         /*
 560          * There is no way to tell if the luser has the RTC set for local
 561          * time or for Universal Standard Time (GMT). Probably local though.
 562          */
 563         p += sprintf(p, "\tRTC reports %02d:%02d:%02d of %d-%d-%d.\n",
 564                 tm.tm_hour, tm.tm_min, tm.tm_sec, tm.tm_mday, 
 565                 tm.tm_mon + 1, tm.tm_year + 1900);
 566 
 567         get_rtc_alm_time(&tm);
 568 
 569         /*
 570          * We implicitly assume 24hr mode here. Alarm values >= 0xc0 will
 571          * match any value for that particular field. Values that are
 572          * greater than a valid time, but less than 0xc0 shouldn't appear.
 573          */
 574         p += sprintf(p, "\tAlarm set to match: ");
 575         if (tm.tm_hour <= 24)
 576                 p += sprintf(p, "hour=%d, ", tm.tm_hour);
 577         else
 578                 p += sprintf(p, "hour=any, ");
 579         if (tm.tm_min <= 59)
 580                 p += sprintf(p, "min=%d, ", tm.tm_min);
 581         else
 582                 p += sprintf(p, "min=any, ");
 583         if (tm.tm_sec <= 59)
 584                 p += sprintf(p, "sec=%d.\n", tm.tm_sec);
 585         else
 586                 p += sprintf(p, "sec=any.\n");
 587 
 588         p += sprintf(p, "\tMisc. settings: daylight=%s; BCD=%s; 24hr=%s; Sq-Wave=%s.\n",
 589                 ((ctrl & RTC_DST_EN) ? "yes" : "no" ),
 590                 ((ctrl & RTC_DM_BINARY) ? "no" : "yes" ),
 591                 ((ctrl & RTC_24H) ? "yes" : "no" ),
 592                 ((ctrl & RTC_SQWE) ? "yes" : "no" ));
 593 
 594         p += sprintf(p, "\tInterrupt for: alarm=%s; update=%s; periodic=%s.\n",
 595                 ((ctrl & RTC_AIE) ? "yes" : "no" ),
 596                 ((ctrl & RTC_UIE) ? "yes" : "no" ),
 597                 ((ctrl & RTC_PIE) ? "yes" : "no" ));
 598 
 599         p += sprintf(p, "\tPeriodic interrupt rate set to %dHz.\n",
 600                 (freq ? (65536/(1<<freq)) : 0));
 601 
 602         p += sprintf(p, "\tRTC reports that CMOS battery is %s.\n",
 603                 (batt ? "okay" : "dead"));
 604 
 605         return  p - buf;
 606 }
 607 
 608 /*
 609  * Returns true if a clock update is in progress
 610  */
 611 inline unsigned char rtc_is_updating(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 612 {
 613         unsigned long flags;
 614         unsigned char uip;
 615 
 616         save_flags(flags);
 617         uip = (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP);
 618         restore_flags(flags);
 619         return uip;
 620 }
 621 
 622 void get_rtc_time(struct tm *rtc_tm)
     /* [previous][next][first][last][top][bottom][index][help] */
 623 {
 624 
 625         unsigned long flags, uip_watchdog = jiffies;
 626         unsigned char ctrl;
 627 
 628         /*
 629          * read RTC once any update in progress is done. The update
 630          * can take just over 2ms. We wait 10 to 20ms. There is no need to
 631          * to poll-wait (up to 1s - eeccch) for the falling edge of RTC_UIP.
 632          * If you need to know *exactly* when a second has started, enable
 633          * periodic update complete interrupts, (via ioctl) and then 
 634          * immediately read /dev/rtc which will block until you get the IRQ.
 635          * Once the read clears, read the RTC time (again via ioctl). Easy.
 636          */
 637 
 638         if (rtc_is_updating() != 0)
 639                 while (jiffies - uip_watchdog < 2*HZ/100)
 640                         barrier();
 641 
 642         /*
 643          * Only the values that we read from the RTC are set. We leave
 644          * tm_wday, tm_yday and tm_isdst untouched. Even though the
 645          * RTC has RTC_DAY_OF_WEEK, we ignore it, as it is only updated
 646          * by the RTC when initially set to a non-zero value.
 647          */
 648         save_flags(flags);
 649         cli();
 650         rtc_tm->tm_sec = CMOS_READ(RTC_SECONDS);
 651         rtc_tm->tm_min = CMOS_READ(RTC_MINUTES);
 652         rtc_tm->tm_hour = CMOS_READ(RTC_HOURS);
 653         rtc_tm->tm_mday = CMOS_READ(RTC_DAY_OF_MONTH);
 654         rtc_tm->tm_mon = CMOS_READ(RTC_MONTH);
 655         rtc_tm->tm_year = CMOS_READ(RTC_YEAR);
 656         ctrl = CMOS_READ(RTC_CONTROL);
 657         restore_flags(flags);
 658 
 659         if (!(ctrl & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
 660         {
 661                 BCD_TO_BIN(rtc_tm->tm_sec);
 662                 BCD_TO_BIN(rtc_tm->tm_min);
 663                 BCD_TO_BIN(rtc_tm->tm_hour);
 664                 BCD_TO_BIN(rtc_tm->tm_mday);
 665                 BCD_TO_BIN(rtc_tm->tm_mon);
 666                 BCD_TO_BIN(rtc_tm->tm_year);
 667         }
 668 
 669         /*
 670          * Account for differences between how the RTC uses the values
 671          * and how they are defined in a struct tm;
 672          */
 673         if (rtc_tm->tm_year <= 69)
 674                 rtc_tm->tm_year += 100;
 675 
 676         rtc_tm->tm_mon--;
 677 }
 678 
 679 void get_rtc_alm_time(struct tm *alm_tm)
     /* [previous][next][first][last][top][bottom][index][help] */
 680 {
 681         unsigned long flags;
 682         unsigned char ctrl;
 683 
 684         /*
 685          * Only the values that we read from the RTC are set. That
 686          * means only tm_hour, tm_min, and tm_sec.
 687          */
 688         save_flags(flags);
 689         cli();
 690         alm_tm->tm_sec = CMOS_READ(RTC_SECONDS_ALARM);
 691         alm_tm->tm_min = CMOS_READ(RTC_MINUTES_ALARM);
 692         alm_tm->tm_hour = CMOS_READ(RTC_HOURS_ALARM);
 693         ctrl = CMOS_READ(RTC_CONTROL);
 694         restore_flags(flags);
 695 
 696         if (!(ctrl & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
 697         {
 698                 BCD_TO_BIN(alm_tm->tm_sec);
 699                 BCD_TO_BIN(alm_tm->tm_min);
 700                 BCD_TO_BIN(alm_tm->tm_hour);
 701         }
 702 }
 703 
 704 /*
 705  * Used to disable/enable interrupts for any one of UIE, AIE, PIE.
 706  * Rumour has it that if you frob the interrupt enable/disable
 707  * bits in RTC_CONTROL, you should read RTC_INTR_FLAGS, to
 708  * ensure you actually start getting interrupts. Probably for
 709  * compatibility with older/broken chipset RTC implementations.
 710  * We also clear out any old irq data after an ioctl() that
 711  * meddles the interrupt enable/disable bits.
 712  */
 713 inline void mask_rtc_irq_bit(unsigned char bit)
     /* [previous][next][first][last][top][bottom][index][help] */
 714 {
 715         unsigned char val;
 716         unsigned long flags;
 717 
 718         save_flags(flags);
 719         cli();
 720         val = CMOS_READ(RTC_CONTROL);
 721         val &=  ~bit;
 722         CMOS_WRITE(val, RTC_CONTROL);
 723         CMOS_READ(RTC_INTR_FLAGS);
 724         restore_flags(flags);
 725         rtc_irq_data = 0;
 726 }
 727 
 728 inline void set_rtc_irq_bit(unsigned char bit)
     /* [previous][next][first][last][top][bottom][index][help] */
 729 {
 730         unsigned char val;
 731         unsigned long flags;
 732 
 733         save_flags(flags);
 734         cli();
 735         val = CMOS_READ(RTC_CONTROL);
 736         val |= bit;
 737         CMOS_WRITE(val, RTC_CONTROL);
 738         CMOS_READ(RTC_INTR_FLAGS);
 739         restore_flags(flags);
 740         rtc_irq_data = 0;
 741 }
 742 

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