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