[7150f00f] | 1 | /*-------------------------------------------------------------------------+ |
---|
| 2 | | rtc.c v1.1 - PC386 BSP - 1997/08/07 |
---|
| 3 | +--------------------------------------------------------------------------+ |
---|
| 4 | | This file contains the real time clock manipulation package for the |
---|
| 5 | | PC386 board. |
---|
| 6 | +--------------------------------------------------------------------------+ |
---|
| 7 | | (C) Copyright 1997 - |
---|
| 8 | | - NavIST Group - Real-Time Distributed Systems and Industrial Automation |
---|
| 9 | | |
---|
| 10 | | http://pandora.ist.utl.pt |
---|
| 11 | | |
---|
| 12 | | Instituto Superior Tecnico * Lisboa * PORTUGAL |
---|
| 13 | +--------------------------------------------------------------------------+ |
---|
| 14 | | Disclaimer: |
---|
| 15 | | |
---|
| 16 | | This file is provided "AS IS" without warranty of any kind, either |
---|
| 17 | | expressed or implied. |
---|
| 18 | +--------------------------------------------------------------------------+ |
---|
| 19 | | This code is based on: |
---|
| 20 | | rtc.c,v 1.4 1995/12/19 20:07:15 joel Exp - go32 BSP |
---|
| 21 | | With the following copyright notice: |
---|
| 22 | | ************************************************************************** |
---|
[08311cc3] | 23 | | * COPYRIGHT (c) 1989-1999. |
---|
[6f9c75c3] | 24 | | * On-Line Applications Research Corporation (OAR). |
---|
| 25 | | * |
---|
| 26 | | * The license and distribution terms for this file may be |
---|
[ba64905] | 27 | | * found in the file LICENSE in this distribution or at |
---|
[c499856] | 28 | | * http://www.rtems.org/license/LICENSE. |
---|
[7150f00f] | 29 | | ************************************************************************** |
---|
| 30 | +--------------------------------------------------------------------------*/ |
---|
| 31 | |
---|
| 32 | #include <string.h> |
---|
| 33 | |
---|
| 34 | #include <bsp.h> |
---|
| 35 | |
---|
| 36 | /*-------------------------------------------------------------------------+ |
---|
| 37 | | Constants |
---|
| 38 | +--------------------------------------------------------------------------*/ |
---|
| 39 | #define IO_RTC 0x70 /* RTC */ |
---|
| 40 | |
---|
| 41 | #define RTC_SEC 0x00 /* seconds */ |
---|
| 42 | #define RTC_SECALRM 0x01 /* seconds alarm */ |
---|
| 43 | #define RTC_MIN 0x02 /* minutes */ |
---|
| 44 | #define RTC_MINALRM 0x03 /* minutes alarm */ |
---|
| 45 | #define RTC_HRS 0x04 /* hours */ |
---|
| 46 | #define RTC_HRSALRM 0x05 /* hours alarm */ |
---|
| 47 | #define RTC_WDAY 0x06 /* week day */ |
---|
| 48 | #define RTC_DAY 0x07 /* day of month */ |
---|
| 49 | #define RTC_MONTH 0x08 /* month of year */ |
---|
| 50 | #define RTC_YEAR 0x09 /* month of year */ |
---|
| 51 | #define RTC_STATUSA 0x0a /* status register A */ |
---|
| 52 | #define RTCSA_TUP 0x80 /* time update, don't look now */ |
---|
| 53 | |
---|
| 54 | #define RTC_STATUSB 0x0b /* status register B */ |
---|
| 55 | |
---|
| 56 | #define RTC_INTR 0x0c /* status register C (R) interrupt source */ |
---|
| 57 | #define RTCIR_UPDATE 0x10 /* update intr */ |
---|
| 58 | #define RTCIR_ALARM 0x20 /* alarm intr */ |
---|
| 59 | #define RTCIR_PERIOD 0x40 /* periodic intr */ |
---|
| 60 | #define RTCIR_INT 0x80 /* interrupt output signal */ |
---|
| 61 | |
---|
| 62 | #define RTC_STATUSD 0x0d /* status register D (R) Lost Power */ |
---|
| 63 | #define RTCSD_PWR 0x80 /* clock lost power */ |
---|
| 64 | |
---|
| 65 | #define RTC_DIAG 0x0e /* status register E - bios diagnostic */ |
---|
| 66 | #define RTCDG_BITS "\020\010clock_battery\007ROM_cksum\006config_unit\005memory_size\004fixed_disk\003invalid_time" |
---|
| 67 | |
---|
| 68 | #define RTC_CENTURY 0x32 /* current century - increment in Dec99 */ |
---|
| 69 | |
---|
| 70 | /*-------------------------------------------------------------------------+ |
---|
| 71 | | Auxiliary Functions |
---|
| 72 | +--------------------------------------------------------------------------*/ |
---|
| 73 | /*-------------------------------------------------------------------------+ |
---|
| 74 | | Function: bcd |
---|
| 75 | | Description: Convert 2 digit number to its BCD representation. |
---|
| 76 | | Global Variables: None. |
---|
| 77 | | Arguments: i - Number to convert. |
---|
[6128a4a] | 78 | | Returns: BCD representation of number. |
---|
[7150f00f] | 79 | +--------------------------------------------------------------------------*/ |
---|
[6128a4a] | 80 | static inline uint8_t |
---|
[6fda59f] | 81 | bcd(uint8_t i) |
---|
[7150f00f] | 82 | { |
---|
| 83 | return ((i / 16) * 10 + (i % 16)); |
---|
| 84 | } /* bcd */ |
---|
| 85 | |
---|
| 86 | #define QUICK_READ /* Quick read of the RTC: don't return number of seconds. */ |
---|
| 87 | |
---|
| 88 | #ifndef QUICK_READ |
---|
| 89 | |
---|
| 90 | #define SECS_PER_DAY (24 * 60 * 60) |
---|
| 91 | #define SECS_PER_REG_YEAR (365 * SECS_PER_DAY) |
---|
| 92 | |
---|
| 93 | /*-------------------------------------------------------------------------+ |
---|
| 94 | | Function: ytos |
---|
| 95 | | Description: Convert years to seconds (since 1970). |
---|
| 96 | | Global Variables: None. |
---|
| 97 | | Arguments: y - year to convert (1970 <= y <= 2100). |
---|
[6128a4a] | 98 | | Returns: number of seconds since 1970. |
---|
[7150f00f] | 99 | +--------------------------------------------------------------------------*/ |
---|
[6128a4a] | 100 | static inline uint32_t |
---|
[6fda59f] | 101 | ytos(uint16_t y) |
---|
[7150f00f] | 102 | { /* v NUM LEAP YEARS v */ |
---|
| 103 | return ((y - 1970) * SECS_PER_REG_YEAR + (y - 1970 + 1) / 4 * SECS_PER_DAY); |
---|
| 104 | } /* ytos */ |
---|
| 105 | |
---|
| 106 | /*-------------------------------------------------------------------------+ |
---|
| 107 | | Function: mtos |
---|
| 108 | | Description: Convert months to seconds since January. |
---|
| 109 | | Global Variables: None. |
---|
| 110 | | Arguments: m - month to convert, leap - is this a month of a leap year. |
---|
[6128a4a] | 111 | | Returns: number of seconds since January. |
---|
[7150f00f] | 112 | +--------------------------------------------------------------------------*/ |
---|
[6128a4a] | 113 | static inline uint32_t |
---|
[78b05d3] | 114 | mtos(uint8_t m, bool leap) |
---|
[7150f00f] | 115 | { |
---|
[6fda59f] | 116 | static uint16_t daysMonth[] = { 0, 0, 31, 59, 90, 120, 151, 181, |
---|
[7150f00f] | 117 | 212, 243, 273, 304, 334, 365 }; |
---|
| 118 | /* Days since beginning of year until beginning of month. */ |
---|
| 119 | |
---|
| 120 | return ((daysMonth[m] + (leap ? 1 : 0)) * SECS_PER_DAY); |
---|
| 121 | } /* mtos */ |
---|
| 122 | |
---|
| 123 | #endif /* QUICK_READ */ |
---|
| 124 | |
---|
| 125 | /*-------------------------------------------------------------------------+ |
---|
| 126 | | Function: rtcin |
---|
| 127 | | Description: Perform action on RTC and return its result. |
---|
| 128 | | Global Variables: None. |
---|
| 129 | | Arguments: what - what to write to RTC port (what to do). |
---|
[6128a4a] | 130 | | Returns: result received from RTC port after action performed. |
---|
[7150f00f] | 131 | +--------------------------------------------------------------------------*/ |
---|
[6128a4a] | 132 | static inline uint8_t |
---|
[6fda59f] | 133 | rtcin(uint8_t what) |
---|
[7150f00f] | 134 | { |
---|
[6fda59f] | 135 | uint8_t r; |
---|
[7150f00f] | 136 | |
---|
| 137 | outport_byte(IO_RTC, what); |
---|
| 138 | inport_byte (IO_RTC+1, r); |
---|
| 139 | return r; |
---|
| 140 | } /* rtcin */ |
---|
| 141 | |
---|
| 142 | /*-------------------------------------------------------------------------+ |
---|
| 143 | | Functions |
---|
| 144 | +--------------------------------------------------------------------------*/ |
---|
| 145 | /*-------------------------------------------------------------------------+ |
---|
| 146 | | Function: init_rtc |
---|
| 147 | | Description: Initialize real-time clock (RTC). |
---|
| 148 | | Global Variables: None. |
---|
| 149 | | Arguments: None. |
---|
[6128a4a] | 150 | | Returns: Nothing. |
---|
[7150f00f] | 151 | +--------------------------------------------------------------------------*/ |
---|
| 152 | void |
---|
| 153 | init_rtc(void) |
---|
| 154 | { |
---|
[6fda59f] | 155 | uint8_t s; |
---|
[7150f00f] | 156 | |
---|
| 157 | /* initialize brain-dead battery powered clock */ |
---|
| 158 | outport_byte(IO_RTC, RTC_STATUSA); |
---|
| 159 | outport_byte(IO_RTC+1, 0x26); |
---|
| 160 | outport_byte(IO_RTC, RTC_STATUSB); |
---|
| 161 | outport_byte(IO_RTC+1, 2); |
---|
| 162 | |
---|
| 163 | outport_byte(IO_RTC, RTC_DIAG); |
---|
| 164 | inport_byte (IO_RTC+1, s); |
---|
| 165 | if (s) |
---|
| 166 | printk("RTC BIOS diagnostic error %b\n", s); |
---|
| 167 | |
---|
| 168 | /* FIXME: This was last line's original version. How was it supposed to work? |
---|
| 169 | printf("RTC BIOS diagnostic error %b\n", s, RTCDG_BITS); */ |
---|
| 170 | } /* init_rtc */ |
---|
| 171 | |
---|
| 172 | /*-------------------------------------------------------------------------+ |
---|
| 173 | | Function: rtc_read |
---|
| 174 | | Description: Read present time from RTC and return it. |
---|
| 175 | | Global Variables: None. |
---|
| 176 | | Arguments: tod - to return present time in 'rtems_time_of_day' format. |
---|
[6128a4a] | 177 | | Returns: number of seconds from 1970/01/01 corresponding to 'tod'. |
---|
[7150f00f] | 178 | +--------------------------------------------------------------------------*/ |
---|
| 179 | long int |
---|
| 180 | rtc_read(rtems_time_of_day *tod) |
---|
| 181 | { |
---|
[6fda59f] | 182 | uint8_t sa; |
---|
| 183 | uint32_t sec = 0; |
---|
[7150f00f] | 184 | |
---|
| 185 | memset(tod, 0, sizeof *tod); /* zero tod structure */ |
---|
| 186 | |
---|
| 187 | /* do we have a realtime clock present? (otherwise we loop below) */ |
---|
| 188 | sa = rtcin(RTC_STATUSA); |
---|
| 189 | if (sa == 0xff || sa == 0) |
---|
| 190 | return -1; |
---|
| 191 | |
---|
| 192 | /* ready for a read? */ |
---|
| 193 | while ((sa&RTCSA_TUP) == RTCSA_TUP) |
---|
| 194 | sa = rtcin(RTC_STATUSA); |
---|
| 195 | |
---|
| 196 | tod->year = bcd(rtcin(RTC_YEAR)) + 1900; /* year */ |
---|
[6128a4a] | 197 | if (tod->year < 1970) tod->year += 100; |
---|
[7150f00f] | 198 | tod->month = bcd(rtcin(RTC_MONTH)); /* month */ |
---|
| 199 | tod->day = bcd(rtcin(RTC_DAY)); /* day */ |
---|
| 200 | (void) bcd(rtcin(RTC_WDAY)); /* weekday */ |
---|
| 201 | tod->hour = bcd(rtcin(RTC_HRS)); /* hour */ |
---|
| 202 | tod->minute = bcd(rtcin(RTC_MIN)); /* minutes */ |
---|
| 203 | tod->second = bcd(rtcin(RTC_SEC)); /* seconds */ |
---|
| 204 | tod->ticks = 0; |
---|
| 205 | |
---|
| 206 | #ifndef QUICK_READ /* Quick read of the RTC: don't return number of seconds. */ |
---|
| 207 | sec = ytos(tod->year); |
---|
| 208 | sec += mtos(tod->month, (tod->year % 4) == 0); |
---|
| 209 | sec += tod->day * SECS_PER_DAY; |
---|
| 210 | sec += tod->hour * 60 * 60; /* hour */ |
---|
| 211 | sec += tod->minute * 60; /* minutes */ |
---|
| 212 | sec += tod->second; /* seconds */ |
---|
| 213 | #endif /* QUICK_READ */ |
---|
| 214 | |
---|
| 215 | return (long int)sec; |
---|
| 216 | } /* rtc_read */ |
---|