Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:23:40

0001 /*-------------------------------------------------------------------------+
0002 | rtc.c v1.1 - PC386 BSP - 1997/08/07
0003 +--------------------------------------------------------------------------+
0004 | This file contains the real time clock manipulation package for the
0005 | PC386 board.
0006 +--------------------------------------------------------------------------+
0007 | (C) Copyright 1997 -
0008 | - NavIST Group - Real-Time Distributed Systems and Industrial Automation
0009 |
0010 | http://pandora.ist.utl.pt
0011 |
0012 | Instituto Superior Tecnico * Lisboa * PORTUGAL
0013 +--------------------------------------------------------------------------+
0014 | Disclaimer:
0015 |
0016 | This file is provided "AS IS" without warranty of any kind, either
0017 | expressed or implied.
0018 +--------------------------------------------------------------------------+
0019 | This code is based on:
0020 |   rtc.c,v 1.4 1995/12/19 20:07:15 joel Exp - go32 BSP
0021 | With the following copyright notice:
0022 | **************************************************************************
0023 | *  COPYRIGHT (c) 1989-1999.
0024 | *  On-Line Applications Research Corporation (OAR).
0025 | *
0026 | *  The license and distribution terms for this file may be
0027 | *  found in the file LICENSE in this distribution or at
0028 | *  http://www.rtems.org/license/LICENSE.
0029 | **************************************************************************
0030 +--------------------------------------------------------------------------*/
0031 
0032 #include <string.h>
0033 
0034 #include <bsp.h>
0035 
0036 /*-------------------------------------------------------------------------+
0037 | Constants
0038 +--------------------------------------------------------------------------*/
0039 #define IO_RTC         0x70  /* RTC                                    */
0040 
0041 #define RTC_SEC        0x00  /* seconds                                */
0042 #define RTC_SECALRM    0x01  /* seconds alarm                          */
0043 #define RTC_MIN        0x02  /* minutes                                */
0044 #define RTC_MINALRM    0x03  /* minutes alarm                          */
0045 #define RTC_HRS        0x04  /* hours                                  */
0046 #define RTC_HRSALRM    0x05  /* hours alarm                            */
0047 #define RTC_WDAY       0x06  /* week day                               */
0048 #define RTC_DAY        0x07  /* day of month                           */
0049 #define RTC_MONTH      0x08  /* month of year                          */
0050 #define RTC_YEAR       0x09  /* month of year                          */
0051 #define RTC_STATUSA    0x0a  /* status register A                      */
0052 #define  RTCSA_TUP     0x80  /* time update, don't look now            */
0053 
0054 #define RTC_STATUSB    0x0b  /* status register B                      */
0055 
0056 #define RTC_INTR       0x0c  /* status register C (R) interrupt source */
0057 #define  RTCIR_UPDATE  0x10  /* update intr                            */
0058 #define  RTCIR_ALARM   0x20  /* alarm intr                             */
0059 #define  RTCIR_PERIOD  0x40  /* periodic intr                          */
0060 #define  RTCIR_INT     0x80  /* interrupt output signal                */
0061 
0062 #define RTC_STATUSD    0x0d  /* status register D (R) Lost Power       */
0063 #define  RTCSD_PWR     0x80  /* clock lost power                       */
0064 
0065 #define RTC_DIAG       0x0e  /* status register E - bios diagnostic    */
0066 #define RTCDG_BITS     "\020\010clock_battery\007ROM_cksum\006config_unit\005memory_size\004fixed_disk\003invalid_time"
0067 
0068 #define RTC_CENTURY    0x32  /* current century - increment in Dec99   */
0069 
0070 /*-------------------------------------------------------------------------+
0071 | Auxiliary Functions
0072 +--------------------------------------------------------------------------*/
0073 /*-------------------------------------------------------------------------+
0074 |         Function: bcd
0075 |      Description: Convert 2 digit number to its BCD representation.
0076 | Global Variables: None.
0077 |        Arguments: i - Number to convert.
0078 |          Returns: BCD representation of number.
0079 +--------------------------------------------------------------------------*/
0080 static inline uint8_t
0081 bcd(uint8_t         i)
0082 {
0083   return ((i / 16) * 10 + (i % 16));
0084 } /* bcd */
0085 
0086 #define QUICK_READ  /* Quick read of the RTC: don't return number of seconds. */
0087 
0088 #ifndef QUICK_READ
0089 
0090 #define SECS_PER_DAY      (24 * 60 * 60)
0091 #define SECS_PER_REG_YEAR (365 * SECS_PER_DAY)
0092 
0093 /*-------------------------------------------------------------------------+
0094 |         Function: ytos
0095 |      Description: Convert years to seconds (since 1970).
0096 | Global Variables: None.
0097 |        Arguments: y - year to convert (1970 <= y <= 2100).
0098 |          Returns: number of seconds since 1970.
0099 +--------------------------------------------------------------------------*/
0100 static inline uint32_t
0101 ytos(uint16_t         y)
0102 {                                       /* v NUM LEAP YEARS v */
0103   return ((y - 1970) * SECS_PER_REG_YEAR + (y - 1970 + 1) / 4 * SECS_PER_DAY);
0104 } /* ytos */
0105 
0106 /*-------------------------------------------------------------------------+
0107 |         Function: mtos
0108 |      Description: Convert months to seconds since January.
0109 | Global Variables: None.
0110 |        Arguments: m - month to convert, leap - is this a month of a leap year.
0111 |          Returns: number of seconds since January.
0112 +--------------------------------------------------------------------------*/
0113 static inline uint32_t
0114 mtos(uint8_t         m, bool leap)
0115 {
0116   static uint16_t         daysMonth[] = { 0, 0, 31,  59,  90, 120, 151, 181,
0117                                212, 243, 273, 304, 334, 365 };
0118     /* Days since beginning of year until beginning of month. */
0119 
0120   return ((daysMonth[m] + (leap ? 1 : 0)) * SECS_PER_DAY);
0121 } /* mtos */
0122 
0123 #endif /* QUICK_READ */
0124 
0125 /*-------------------------------------------------------------------------+
0126 |         Function: rtcin
0127 |      Description: Perform action on RTC and return its result.
0128 | Global Variables: None.
0129 |        Arguments: what - what to write to RTC port (what to do).
0130 |          Returns: result received from RTC port after action performed.
0131 +--------------------------------------------------------------------------*/
0132 static inline uint8_t
0133 rtcin(uint8_t         what)
0134 {
0135     uint8_t         r;
0136 
0137     outport_byte(IO_RTC,   what);
0138     inport_byte (IO_RTC+1, r);
0139     return r;
0140 } /* rtcin */
0141 
0142 /*-------------------------------------------------------------------------+
0143 | Functions
0144 +--------------------------------------------------------------------------*/
0145 /*-------------------------------------------------------------------------+
0146 |         Function: init_rtc
0147 |      Description: Initialize real-time clock (RTC).
0148 | Global Variables: None.
0149 |        Arguments: None.
0150 |          Returns: Nothing.
0151 +--------------------------------------------------------------------------*/
0152 void
0153 init_rtc(void)
0154 {
0155   uint8_t         s;
0156 
0157   /* initialize brain-dead battery powered clock */
0158   outport_byte(IO_RTC,   RTC_STATUSA);
0159   outport_byte(IO_RTC+1, 0x26);
0160   outport_byte(IO_RTC,   RTC_STATUSB);
0161   outport_byte(IO_RTC+1, 2);
0162 
0163   outport_byte(IO_RTC,   RTC_DIAG);
0164   inport_byte (IO_RTC+1, s);
0165   if (s)
0166     printk("RTC BIOS diagnostic error %b\n", s);
0167 
0168   /* FIXME: This was last line's original version. How was it supposed to work?
0169        printf("RTC BIOS diagnostic error %b\n", s, RTCDG_BITS); */
0170 } /* init_rtc */
0171 
0172 /*-------------------------------------------------------------------------+
0173 |         Function: rtc_read
0174 |      Description: Read present time from RTC and return it.
0175 | Global Variables: None.
0176 |        Arguments: tod - to return present time in 'rtems_time_of_day' format.
0177 |          Returns: number of seconds from 1970/01/01 corresponding to 'tod'.
0178 +--------------------------------------------------------------------------*/
0179 long int
0180 rtc_read(rtems_time_of_day *tod)
0181 {
0182   uint8_t          sa;
0183   uint32_t         sec = 0;
0184 
0185   memset(tod, 0, sizeof *tod); /* zero tod structure */
0186 
0187   /* do we have a realtime clock present? (otherwise we loop below) */
0188   sa = rtcin(RTC_STATUSA);
0189   if (sa == 0xff || sa == 0)
0190     return -1;
0191 
0192   /* ready for a read? */
0193   while ((sa&RTCSA_TUP) == RTCSA_TUP)
0194     sa = rtcin(RTC_STATUSA);
0195 
0196   tod->year = bcd(rtcin(RTC_YEAR)) + 1900;  /* year    */
0197   if (tod->year < 1970) tod->year += 100;
0198   tod->month    = bcd(rtcin(RTC_MONTH));        /* month   */
0199   tod->day  = bcd(rtcin(RTC_DAY));          /* day     */
0200   (void)          bcd(rtcin(RTC_WDAY));         /* weekday */
0201   tod->hour = bcd(rtcin(RTC_HRS));          /* hour    */
0202   tod->minute   = bcd(rtcin(RTC_MIN));          /* minutes */
0203   tod->second   = bcd(rtcin(RTC_SEC));          /* seconds */
0204   tod->ticks    = 0;
0205 
0206 #ifndef QUICK_READ  /* Quick read of the RTC: don't return number of seconds. */
0207   sec =  ytos(tod->year);
0208   sec += mtos(tod->month, (tod->year % 4) == 0);
0209   sec += tod->day * SECS_PER_DAY;
0210   sec += tod->hour * 60 * 60;                     /* hour    */
0211   sec += tod->minute * 60;                        /* minutes */
0212   sec += tod->second;                             /* seconds */
0213 #endif /* QUICK_READ */
0214 
0215   return (long int)sec;
0216 } /* rtc_read */