diff options
Diffstat (limited to 'c/src/lib/libbsp/i386/go32/clock/rtc.c')
-rw-r--r-- | c/src/lib/libbsp/i386/go32/clock/rtc.c | 213 |
1 files changed, 213 insertions, 0 deletions
diff --git a/c/src/lib/libbsp/i386/go32/clock/rtc.c b/c/src/lib/libbsp/i386/go32/clock/rtc.c new file mode 100644 index 0000000000..3dd2cb8f07 --- /dev/null +++ b/c/src/lib/libbsp/i386/go32/clock/rtc.c @@ -0,0 +1,213 @@ +/* + * $Id$ + */ + +#define IO_RTC 0x70 /* RTC */ + +#define RTC_SEC 0x00 /* seconds */ +#define RTC_SECALRM 0x01 /* seconds alarm */ +#define RTC_MIN 0x02 /* minutes */ +#define RTC_MINALRM 0x03 /* minutes alarm */ +#define RTC_HRS 0x04 /* hours */ +#define RTC_HRSALRM 0x05 /* hours alarm */ +#define RTC_WDAY 0x06 /* week day */ +#define RTC_DAY 0x07 /* day of month */ +#define RTC_MONTH 0x08 /* month of year */ +#define RTC_YEAR 0x09 /* month of year */ +#define RTC_STATUSA 0x0a /* status register A */ +#define RTCSA_TUP 0x80 /* time update, don't look now */ + +#define RTC_STATUSB 0x0b /* status register B */ + +#define RTC_INTR 0x0c /* status register C (R) interrupt source */ +#define RTCIR_UPDATE 0x10 /* update intr */ +#define RTCIR_ALARM 0x20 /* alarm intr */ +#define RTCIR_PERIOD 0x40 /* periodic intr */ +#define RTCIR_INT 0x80 /* interrupt output signal */ + +#define RTC_STATUSD 0x0d /* status register D (R) Lost Power */ +#define RTCSD_PWR 0x80 /* clock lost power */ + +#define RTC_DIAG 0x0e /* status register E - bios diagnostic */ +#define RTCDG_BITS "\020\010clock_battery\007ROM_cksum\006config_unit\005memory_size\004fixed_disk\003invalid_time" + +#define RTC_CENTURY 0x32 /* current century - increment in Dec99 */ + + + +#include <rtems.h> +#include <cpu.h> +#include <memory.h> + +void init_rtc( void ) +{ + int s; + + /* initialize brain-dead battery powered clock */ + outport_byte( IO_RTC, RTC_STATUSA ); + outport_byte( IO_RTC+1, 0x26 ); + outport_byte( IO_RTC, RTC_STATUSB ); + outport_byte( IO_RTC+1, 2 ); + + outport_byte( IO_RTC, RTC_DIAG ); + inport_byte( IO_RTC+1, s ); +#if 0 + if (s) printf("RTC BIOS diagnostic error %b\n", s, RTCDG_BITS); +#endif +} + + +/* convert 2 digit BCD number */ +static int bcd( unsigned int i ) +{ + return ((i/16)*10 + (i%16)); +} + +/* convert years to seconds (from 1970) */ +static unsigned long ytos( int y ) +{ + int i; + unsigned long ret; + + ret = 0; + for(i = 1970; i < y; i++) { + if (i % 4) ret += 365*24*60*60; + else ret += 366*24*60*60; + } + return ret; +} + +/* convert months to seconds */ +static unsigned long mtos( int m, int leap ) +{ + int i; + unsigned long ret; + + ret = 0; + for(i=1;i<m;i++) { + switch(i){ + case 1: case 3: case 5: case 7: case 8: case 10: case 12: + ret += 31*24*60*60; + break; + case 4: case 6: case 9: case 11: + ret += 30*24*60*60; + break; + case 2: + if (leap) + ret += 29*24*60*60; + else + ret += 28*24*60*60; + } + } + return ret; +} + + +static inline unsigned int rtcin( unsigned int what ) +{ + unsigned int r; + outport_byte( IO_RTC, what ); + inport_byte( IO_RTC+1, r ); + return r; +} + + +/* + * Initialize the time of day register, based on the time base which is, e.g. + * from a filesystem. + */ +long rtc_read( rtems_time_of_day * tod ) +{ + int sa; + unsigned long sec = 0; + + memset( tod, 0, sizeof *tod ); + + /* do we have a realtime clock present? (otherwise we loop below) */ + sa = rtcin(RTC_STATUSA); + if (sa == 0xff || sa == 0) + return -1; + + /* ready for a read? */ + while ((sa&RTCSA_TUP) == RTCSA_TUP) + sa = rtcin(RTC_STATUSA); + + tod->year = bcd(rtcin(RTC_YEAR)) + 1900; /* year */ + if (tod->year < 1970) tod->year += 100; + tod->month = bcd(rtcin(RTC_MONTH)); /* month */ + tod->day = bcd(rtcin(RTC_DAY)); /* day */ + (void) bcd(rtcin(RTC_WDAY)); /* weekday */ + tod->hour = bcd(rtcin(RTC_HRS)); /* hour */ + tod->minute = bcd(rtcin(RTC_MIN)); /* minutes */ + tod->second = bcd(rtcin(RTC_SEC)); /* seconds */ + tod->ticks = 0; +#if 0 + sec = ytos( tod->year ); + sec += mtos( tod->month, tod->year % 4 == 0 ); + sec += tod->day * 24*60*60; + sec += tod->hour * 60*60; /* hour */ + sec += tod->minute * 60; /* minutes */ + sec += tod->second; /* seconds */ +#else + sec = 0; +#endif + return sec; +} + + + +/* from djgpp: include before rtems.h to avoid conflicts */ +#undef delay +#include <dos.h> + +void rtc_set_dos_date( void ) +{ + int s; + struct date date; + struct time time; + + /* initialize brain-dead battery powered clock */ + outport_byte( IO_RTC, RTC_STATUSA ); + outport_byte( IO_RTC+1, 0x26 ); + outport_byte( IO_RTC, RTC_STATUSB ); + outport_byte( IO_RTC+1, 2 ); + + outport_byte( IO_RTC, RTC_DIAG ); + inport_byte( IO_RTC+1, s ); + if (s) { +#if 0 + printf("RTC BIOS diagnostic error %b\n", s, RTCDG_BITS); +#else + return; +#endif + } + + /* check for presence of clock */ + s = rtcin(RTC_STATUSA); + if ( s == 0xff || s == 0 ) { +#if 0 + printf( "Real-time clock not found\n" ); +#endif + return; + } + + /* ready for a read? */ + while ((s & RTCSA_TUP) == RTCSA_TUP) + s = rtcin(RTC_STATUSA); + + date.da_year = bcd(rtcin(RTC_YEAR)) + 1900; /* year */ + if ( date.da_year < 1970) date.da_year += 100; + date.da_year -= 1980; + date.da_mon = bcd(rtcin(RTC_MONTH)); /* month */ + date.da_day = bcd(rtcin(RTC_DAY)); /* day */ + + (void)bcd(rtcin(RTC_WDAY)); /* weekday */ + + time.ti_hour = bcd(rtcin(RTC_HRS)); /* hour */ + time.ti_min = bcd(rtcin(RTC_MIN)); /* minutes */ + time.ti_sec = bcd(rtcin(RTC_SEC)); /* seconds */ + time.ti_hund = 0; + + setdate( & date ); + settime( & time ); +} |