Make bootloader 'time' command work correctly on luna88k.
authoraoyama <aoyama@openbsd.org>
Thu, 23 Feb 2023 13:28:38 +0000 (13:28 +0000)
committeraoyama <aoyama@openbsd.org>
Thu, 23 Feb 2023 13:28:38 +0000 (13:28 +0000)
Now the correct date is displayed instead of January 1, 1970.

Tested on LUNA-88K2 and nono emulator by me.

"make sense" miod@

sys/arch/luna88k/stand/boot/getsecs.c

index c61b979..32a9c12 100644 (file)
@@ -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);
 }