-/* $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 $ */
/*-
#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.
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);
}