Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/arch/hp300/hp300 Cleanup TOD clock functions:



details:   https://anonhg.NetBSD.org/src/rev/41148692e8af
branches:  trunk
changeset: 515972:41148692e8af
user:      tsutsui <tsutsui%NetBSD.org@localhost>
date:      Thu Oct 11 15:02:07 2001 +0000

description:
Cleanup TOD clock functions:
 - Adapt MI functions/structures in sys/dev/clock_subr.[ch]
 - Fix year-2001 problem

XXX Maybe TOD clock should be attached as an independent device.

diffstat:

 sys/arch/hp300/hp300/clock.c    |  343 ++++++++++++++++++++++-----------------
 sys/arch/hp300/hp300/clockreg.h |   35 +---
 2 files changed, 195 insertions(+), 183 deletions(-)

diffs (truncated from 481 to 300 lines):

diff -r ee3c14b6420b -r 41148692e8af sys/arch/hp300/hp300/clock.c
--- a/sys/arch/hp300/hp300/clock.c      Thu Oct 11 14:31:58 2001 +0000
+++ b/sys/arch/hp300/hp300/clock.c      Thu Oct 11 15:02:07 2001 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: clock.c,v 1.21 1997/10/12 18:37:56 thorpej Exp $       */
+/*     $NetBSD: clock.c,v 1.22 2001/10/11 15:02:07 tsutsui Exp $       */
 
 /*
  * Copyright (c) 1988 University of Utah.
@@ -53,8 +53,11 @@
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/kernel.h>
+#include <sys/malloc.h>
 #include <sys/tty.h>
 
+#include <dev/clock_subr.h>
+
 #include <machine/psl.h>
 #include <machine/cpu.h>
 #include <machine/hp300spu.h>
@@ -85,19 +88,17 @@
 static int timer3min;          /* current, from above choices */
 static int statprev;           /* previous value in stat timer */
 
-static int month_days[12] = {
-       31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
-};
-u_char bbc_registers[13];
-struct hil_dev *bbcaddr = NULL;
-
 void   statintr __P((struct clockframe *));
 
-struct bbc_tm *gmt_to_bbc __P((long));
-int    bbc_to_gmt __P((u_long *));
-void   read_bbc __P((void));
-u_char read_bbc_reg __P((int));
-u_char write_bbc_reg __P((int, u_int));
+static todr_chip_handle_t todr_handle;
+
+void bbc_init __P((void));
+int bbc_settime __P((todr_chip_handle_t, struct timeval *));
+int bbc_gettime __P((todr_chip_handle_t, struct timeval *));
+int bbc_getcal __P((todr_chip_handle_t, int *));
+int bbc_setcal __P((todr_chip_handle_t, int));
+static u_int8_t read_bbc_reg __P((struct hil_dev *, int));
+static u_int8_t write_bbc_reg __P((struct hil_dev *, int, u_int));
 
 /*
  * Machine-dependent clock routines.
@@ -148,7 +149,7 @@
                /* Enable the timer */
                clk->clk_cr2 = CLK_CR1;
                clk->clk_cr1 = CLK_IENAB;
-               
+
                delay(10000);
 
                /* Timer1 interrupt flag high? */
@@ -202,6 +203,9 @@
        volatile struct clkreg *clk;
        int intvl, statint, profint, minint;
 
+       /* XXX TOD clock should be attached as a normal device */
+       bbc_init();
+
        clkstd[0] = IIOV(0x5F8000);             /* XXX grot */
        clk = (volatile struct clkreg *)clkstd[0];
 
@@ -358,188 +362,229 @@
 inittodr(base)
        time_t base;
 {
-       u_long timbuf = base;   /* assume no battery clock exists */
-       static int bbcinited = 0;
+       int badbase = 0, waszero = (base == 0);
 
-       /* XXX */
-       if (!bbcinited) {
-               if (badbaddr((caddr_t)&BBCADDR->hil_stat))
-                       printf("WARNING: no battery clock\n");
-               else
-                       bbcaddr = BBCADDR;
-               bbcinited = 1;
+       if (base < 5 * SECYR) {
+               /*
+                * If base is 0, assume filesystem time is just unknown
+                * in stead of preposterous. Don't bark.
+                */
+               if (base != 0)
+                       printf("WARNING: preposterous time in file system\n");
+               /* not going to use it anyway, if the chip is readable */
+               /* 1991/07/01   12:00:00 */
+               base = 21*SECYR + 186*SECDAY + SECDAY/2;
+               badbase = 1;
        }
 
-       /*
-        * bbc_to_gmt converts and stores the gmt in timbuf.
-        * If an error is detected in bbc_to_gmt, or if the filesystem
-        * time is more recent than the gmt time in the clock,
-        * then use the filesystem time and warn the user.
-        */
-       if (!bbc_to_gmt(&timbuf) || timbuf < base) {
-               printf("WARNING: bad date in battery clock\n");
-               timbuf = base;
+       if (todr_gettime(todr_handle, (struct timeval *)&time) != 0 ||
+           time.tv_sec == 0) {
+               printf("WARNING: bad date in battery clock");
+               /*
+                * Believe the time in the file system for lack of
+                * anything better, resetting the clock.
+                */
+               time.tv_sec = base;
+               if (!badbase)
+                       resettodr();
+       } else {
+               int deltat = time.tv_sec - base;
+
+               if (deltat < 0)
+                       deltat = -deltat;
+               if (waszero || deltat < 2 * SECDAY)
+                       return;
+               printf("WARNING: clock %s %d days",
+                   time.tv_sec < base ? "lost" : "gained", deltat / SECDAY);
        }
-       if (base < 5*SECYR) {
-               printf("WARNING: preposterous time in file system");
-               timbuf = 6*SECYR + 186*SECDAY + SECDAY/2;
-               printf(" -- CHECK AND RESET THE DATE!\n");
-       }
-       
-       /* Battery clock does not store usec's, so forget about it. */
-       time.tv_sec = timbuf;
+       printf(" -- CHECK AND RESET THE DATE!\n");
 }
 
 /*
- * Restore the time of day hardware after a time change.
+ * Reset the clock based on the current time.
+ * Used when the current clock is preposterous, when the time is changed,
+ * and when rebooting.  Do nothing if the time is not yet known, e.g.,
+ * when crashing during autoconfig.
  */
 void
 resettodr()
 {
-       int i;
-       struct bbc_tm *tmptr;
-
-       tmptr = gmt_to_bbc(time.tv_sec);
 
-       decimal_to_bbc(0, 1,  tmptr->tm_sec);
-       decimal_to_bbc(2, 3,  tmptr->tm_min);
-       decimal_to_bbc(4, 5,  tmptr->tm_hour);
-       decimal_to_bbc(7, 8,  tmptr->tm_mday);
-       decimal_to_bbc(9, 10, tmptr->tm_mon);
-       decimal_to_bbc(11, 12, tmptr->tm_year);
+       if (time.tv_sec == 0)
+               return;
 
-       /* Some bogusness to deal with seemingly broken hardware. Nonsense */
-       bbc_registers[5] = ((tmptr->tm_hour / 10) & 0x03) + 8;
-
-       write_bbc_reg(15, 13);  /* reset prescalar */
-
-       for (i = 0; i <= NUM_BBC_REGS; i++)
-               if (bbc_registers[i] != write_bbc_reg(i, bbc_registers[i])) {
-                       printf("Cannot set battery backed clock\n");
-                       break;
-               }
+       if (todr_settime(todr_handle, (struct timeval *)&time) != 0)
+               printf("resettodr: cannot set time in time-of-day clock\n");
 }
 
-struct bbc_tm *
-gmt_to_bbc(tim)
-       long tim;
-{
-       int i;
-       long hms, day;
-       static struct bbc_tm rt;
+/*
+ * functions for HP300 battery-backed clock
+ */
+#define BBC_SET_REG    0xe0
+#define BBC_WRITE_REG  0xc2
+#define BBC_READ_REG   0xc3
+#define NUM_BBC_REGS   13
+#define BBC_BASE_YEAR  1900
 
-       day = tim / SECDAY;
-       hms = tim % SECDAY;
-
-       /* Hours, minutes, seconds are easy */
-       rt.tm_hour = hms / 3600;
-       rt.tm_min  = (hms % 3600) / 60;
-       rt.tm_sec  = (hms % 3600) % 60;
+void
+bbc_init(void)
+{
+       struct hil_dev *bbcaddr;
 
-       /* Number of years in days */
-       for (i = STARTOFTIME - 1900; day >= days_in_year(i); i++)
-               day -= days_in_year(i);
-       rt.tm_year = i;
-       
-       /* Number of months in days left */
-       if (leapyear(rt.tm_year))
-               days_in_month(FEBRUARY) = 29;
-       for (i = 1; day >= days_in_month(i); i++)
-               day -= days_in_month(i);
-       days_in_month(FEBRUARY) = 28;
-       rt.tm_mon = i;
+       bbcaddr = BBCADDR; /* XXX */
+       if (badbaddr((caddr_t)&bbcaddr->hil_stat)) {
+               printf("WARNING: no battery clock\n");
+               bbcaddr = NULL;
+       }
+       todr_handle = malloc(sizeof(struct todr_chip_handle),
+           M_DEVBUF, M_NOWAIT);
 
-       /* Days are what is left over (+1) from all that. */
-       rt.tm_mday = day + 1;  
-       
-       return(&rt);
+       todr_handle->cookie = bbcaddr;
+       todr_handle->todr_gettime = bbc_gettime;
+       todr_handle->todr_settime = bbc_settime;
+       todr_handle->todr_getcal = bbc_getcal;
+       todr_handle->todr_setcal = bbc_setcal;
+       todr_handle->todr_setwen = NULL;
 }
 
 int
-bbc_to_gmt(timbuf)
-       u_long *timbuf;
+bbc_gettime(handle, tv)
+       todr_chip_handle_t handle;
+       struct timeval *tv;
 {
-       int i;
-       u_long tmp;
-       int year, month, day, hour, min, sec;
-
-       read_bbc();
-
-       sec = bbc_to_decimal(1, 0);
-       min = bbc_to_decimal(3, 2);
-
-       /*
-        * Hours are different for some reason. Makes no sense really.
-        */
-       hour  = ((bbc_registers[5] & 0x03) * 10) + bbc_registers[4];
-       day   = bbc_to_decimal(8, 7);
-       month = bbc_to_decimal(10, 9);
-       year  = bbc_to_decimal(12, 11) + 1900;
+       int i, read_okay, year;
+       struct clock_ymdhms dt;
+       struct hil_dev *bbcaddr = handle->cookie;
+       u_int8_t bbc_registers[NUM_BBC_REGS];
 
-       range_test(hour, 0, 23);
-       range_test(day, 1, 31);
-       range_test(month, 1, 12);
-       range_test(year, STARTOFTIME, 2000);
-
-       tmp = 0;
-
-       for (i = STARTOFTIME; i < year; i++)
-               tmp += days_in_year(i);
-       if (leapyear(year) && month > FEBRUARY)
-               tmp++;
-
-       for (i = 1; i < month; i++)
-               tmp += days_in_month(i);
-       
-       tmp += (day - 1);
-       tmp = ((tmp * 24 + hour) * 60 + min) * 60 + sec;
-
-       *timbuf = tmp;
-       return(1);
-}
-
-void
-read_bbc()
-{
-       int i, read_okay;
-
+       /* read bbc registers */
        read_okay = 0;
        while (!read_okay) {
                read_okay = 1;
-               for (i = 0; i <= NUM_BBC_REGS; i++)
-                       bbc_registers[i] = read_bbc_reg(i);
-               for (i = 0; i <= NUM_BBC_REGS; i++)
-                       if (bbc_registers[i] != read_bbc_reg(i))
+               for (i = 0; i < NUM_BBC_REGS; i++)
+                       bbc_registers[i] = read_bbc_reg(bbcaddr, i);



Home | Main Index | Thread Index | Old Index