diff options
author | Kenji Aoyama <aoyama@cvs.openbsd.org> | 2023-02-23 13:28:39 +0000 |
---|---|---|
committer | Kenji Aoyama <aoyama@cvs.openbsd.org> | 2023-02-23 13:28:39 +0000 |
commit | 994cfede9919b3f61a36ae283a65490800fdef5d (patch) | |
tree | 8ca4b39054423b353b1cd7a238b17213ff343986 /sys/arch | |
parent | f019ba181914c9ddda4efbfc04768c6bab12dead (diff) |
Make bootloader 'time' command work correctly on luna88k.
Now the correct date is displayed instead of January 1, 1970.
Tested on LUNA-88K2 and nono emulator by me.
"make sense" miod@
Diffstat (limited to 'sys/arch')
-rw-r--r-- | sys/arch/luna88k/stand/boot/getsecs.c | 134 |
1 files changed, 99 insertions, 35 deletions
diff --git a/sys/arch/luna88k/stand/boot/getsecs.c b/sys/arch/luna88k/stand/boot/getsecs.c index c61b979b9be..32a9c12b56c 100644 --- a/sys/arch/luna88k/stand/boot/getsecs.c +++ b/sys/arch/luna88k/stand/boot/getsecs.c @@ -1,4 +1,4 @@ -/* $OpenBSD: getsecs.c,v 1.4 2023/01/10 17:10:57 miod Exp $ */ +/* $OpenBSD: getsecs.c,v 1.5 2023/02/23 13:28:38 aoyama Exp $ */ /* $NetBSD: getsecs.c,v 1.1 2013/01/13 14:10:55 tsutsui Exp $ */ /*- @@ -37,7 +37,7 @@ #define _DS_GET(off, data) \ do { *chiptime = (off); (data) = (*chipdata); } while (0) #define _DS_SET(off, data) \ - do { *chiptime = (off); *chipdata = (u_int8_t)(data); } while (0) + do { *chiptime = (off); *chipdata = (uint8_t)(data); } while (0) /* * Convert a single byte between (unsigned) packed bcd and binary. @@ -50,45 +50,109 @@ bcdtobin(unsigned int bcd) return (((bcd >> 4) & 0x0f) * 10 + (bcd & 0x0f)); } +typedef struct { + uint Year; + uint Month; + uint Day; + uint Hour; + uint Minute; + uint Second; +} rtc_time; + +#define MK_YEAR0 1970 /* year offset of MK */ +#define DS_YEAR0 1990 /* year offset of DS */ + +static void +mk_gettime(rtc_time *t) { + volatile uint32_t *mclock = + (volatile uint32_t *)(NVRAM_ADDR + MK_NVRAM_SPACE); + mclock[MK_CSR] |= MK_CSR_READ << 24; + t->Second = bcdtobin(mclock[MK_SEC] >> 24); + t->Minute = bcdtobin(mclock[MK_MIN] >> 24); + t->Hour = bcdtobin(mclock[MK_HOUR] >> 24); + t->Day = bcdtobin(mclock[MK_DOM] >> 24); + t->Month = bcdtobin(mclock[MK_MONTH] >> 24); + t->Year = bcdtobin(mclock[MK_YEAR] >> 24); + mclock[MK_CSR] &= ~(MK_CSR_READ << 24); + + /* UniOS-Mach doesn't set the correct BCD year after Y2K */ + if (t->Year > 100) t->Year -= (MK_YEAR0 % 100); + + t->Year += MK_YEAR0; + + return; +} + +static void +ds_gettime(rtc_time *t) { + volatile uint8_t *chiptime = (volatile uint8_t *)NVRAM_ADDR; + volatile uint8_t *chipdata = chiptime + 1; + + uint8_t c; + + /* specify 24hr and BCD mode */ + _DS_GET(DS_REGB, c); + c |= DS_REGB_24HR; + c &= ~DS_REGB_BINARY; + _DS_SET(DS_REGB, c); + + /* update in progress; spin loop */ + for (;;) { + *chiptime = DS_REGA; + if ((*chipdata & DS_REGA_UIP) == 0) + break; + } + + *chiptime = DS_SEC; + t->Second = bcdtobin(*chipdata); + *chiptime = DS_MIN; + t->Minute = bcdtobin(*chipdata); + *chiptime = DS_HOUR; + t->Hour = bcdtobin(*chipdata); + *chiptime = DS_DOM; + t->Day = bcdtobin(*chipdata); + *chiptime = DS_MONTH; + t->Month = bcdtobin(*chipdata); + *chiptime = DS_YEAR; + t->Year = bcdtobin(*chipdata); + + /* UniOS-Mach doesn't set the correct BCD year after Y2K */ + if (t->Year > 100) t->Year -= (DS_YEAR0 % 100); + + t->Year += DS_YEAR0; + + return; +} + time_t getsecs(void) { - u_int t; + rtc_time t; + time_t r = 0; + int y = 0; + const int daytab[][14] = { + { 0, -1, 30, 58, 89, 119, 150, 180, 211, 242, 272, 303, 333, 364 }, + { 0, -1, 30, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 }, + }; +#define isleap(_y) (((_y) % 4) == 0 && (((_y) % 100) != 0 || ((_y) % 400) == 0)) if (machtype == LUNA_88K) { - volatile uint32_t *mclock = - (volatile uint32_t *)(NVRAM_ADDR + MK_NVRAM_SPACE); - mclock[MK_CSR] |= MK_CSR_READ << 24; - t = bcdtobin(mclock[MK_SEC] >> 24); - t += bcdtobin(mclock[MK_MIN] >> 24) * 60; - t += bcdtobin(mclock[MK_HOUR] >> 24) * 60 * 60; - mclock[MK_CSR] &= ~(MK_CSR_READ << 24); + mk_gettime(&t); } else { - volatile uint8_t *chiptime = (volatile uint8_t *)NVRAM_ADDR; - volatile u_int8_t *chipdata = chiptime + 1; - - uint8_t c; - - /* specify 24hr and BCD mode */ - _DS_GET(DS_REGB, c); - c |= DS_REGB_24HR; - c &= ~DS_REGB_BINARY; - _DS_SET(DS_REGB, c); - - /* update in progress; spin loop */ - for (;;) { - *chiptime = DS_REGA; - if ((*chipdata & DS_REGA_UIP) == 0) - break; - } - - *chiptime = DS_SEC; - t = bcdtobin(*chipdata); - *chiptime = DS_MIN; - t += bcdtobin(*chipdata) * 60; - *chiptime = DS_HOUR; - t += bcdtobin(*chipdata) * 60 * 60; + ds_gettime(&t); } - return (time_t)t; + /* Calc days from UNIX epoch */ + r = (t.Year - 1970) * 365; + for (y = 1970; y < t.Year; y++) { + if (isleap(y)) + r++; + } + r += daytab[isleap(t.Year)? 1 : 0][t.Month] + t.Day; + + /* Calc secs */ + r *= 60 * 60 * 24; + r += ((t.Hour * 60) + t.Minute) * 60 + t.Second; + + return (r); } |