patch-1.3.45 linux/arch/sparc/kernel/time.c

Next file: linux/arch/sparc/mm/sun4c.c
Previous file: linux/arch/sparc/kernel/sunos_ioctl.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v1.3.44/linux/arch/sparc/kernel/time.c linux/arch/sparc/kernel/time.c
@@ -1,4 +1,4 @@
-/* $Id: time.c,v 1.3 1995/11/25 00:58:45 davem Exp $
+/* $Id: time.c,v 1.4 1995/11/25 03:29:31 davem Exp $
  * linux/arch/sparc/kernel/time.c
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -13,8 +13,10 @@
 #include <linux/mm.h>
 #include <linux/timex.h>
 
+#include <asm/oplib.h>
 #include <asm/segment.h>
 #include <asm/timer.h>
+#include <asm/mostek.h>
 
 #define TIMER_IRQ  10    /* Also at level 14, but we ignore that one. */
 
@@ -45,9 +47,66 @@
 	    last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */
 }
 
+/* Converts Gregorian date to seconds since 1970-01-01 00:00:00.
+ * Assumes input in normal date format, i.e. 1980-12-31 23:59:59
+ * => year=1980, mon=12, day=31, hour=23, min=59, sec=59.
+ *
+ * [For the Julian calendar (which was used in Russia before 1917,
+ * Britain & colonies before 1752, anywhere else before 1582,
+ * and is still in use by some communities) leave out the
+ * -year/100+year/400 terms, and add 10.]
+ *
+ * This algorithm was first published by Gauss (I think).
+ *
+ * WARNING: this function will overflow on 2106-02-07 06:28:16 on
+ * machines were long is 32-bit! (However, as time_t is signed, we
+ * will already get problems at other places on 2038-01-19 03:14:08)
+ */
+static inline unsigned long mktime(unsigned int year, unsigned int mon,
+	unsigned int day, unsigned int hour,
+	unsigned int min, unsigned int sec)
+{
+	if (0 >= (int) (mon -= 2)) {	/* 1..12 -> 11,12,1..10 */
+		mon += 12;	/* Puts Feb last since it has leap day */
+		year -= 1;
+	}
+	return (((
+	    (unsigned long)(year/4 - year/100 + year/400 + 367*mon/12 + day) +
+	      year*365 - 719499
+	    )*24 + hour /* now have hours */
+	   )*60 + min /* now have minutes */
+	  )*60 + sec; /* finally seconds */
+}
+
+#ifndef BCD_TO_BIN
+#define BCD_TO_BIN(val) (((val)&15) + ((val)>>4)*10)
+#endif
+
+#ifndef BIN_TO_BCD
+#define BIN_TO_BCD(val) ((((val)/10)<<4) + (val)%10)
+#endif
+
 void time_init(void)
 {
+	unsigned int year, mon, day, hour, min, sec;
+	struct mostek48t02 *mregs;
+
 	request_irq(TIMER_IRQ, timer_interrupt, SA_INTERRUPT, "timer");
+	mregs = mstk48t02_regs;
+	if(!mregs) {
+		prom_printf("Something wrong, clock regs not mapped yet.\n");
+		prom_halt();
+	}		
+	mregs->creg |= MSTK_CREG_READ;
+	sec = BCD_TO_BIN(mregs->sec);
+	min = BCD_TO_BIN(mregs->min);
+	hour = BCD_TO_BIN(mregs->hour);
+	day = BCD_TO_BIN(mregs->dom);
+	mon = BCD_TO_BIN(mregs->mnth);
+	year = (BCD_TO_BIN(mregs->yr) + MSTK_YR_ZERO);
+	xtime.tv_sec = mktime(year, mon, day, hour, min, sec);
+	xtime.tv_usec = 0;
+	mregs->creg &= ~MSTK_CREG_READ;
 	return;
 }
 /* Nothing fancy on the Sparc yet. */
@@ -71,9 +130,32 @@
 	sti();
 }
 
-/* XXX Mostek RTC code needs to be written XXX */
 static int set_rtc_mmss(unsigned long nowtime)
 {
-	/* Just say we succeeded for now. */
-	return 0;
+	int retval = 0;
+	int real_seconds, real_minutes, mostek_minutes;
+	struct mostek48t02 *mregs = mstk48t02_regs;
+
+	if(!mregs)
+		retval = -1;
+	else {
+		mregs->creg |= MSTK_CREG_READ;
+		mostek_minutes = BCD_TO_BIN(mregs->min);
+		mregs->creg &= ~MSTK_CREG_READ;
+
+		real_seconds = nowtime % 60;
+		real_minutes = nowtime / 60;
+		if (((abs(real_minutes - mostek_minutes) + 15)/30) & 1)
+			real_minutes += 30;
+		real_minutes %= 60;
+		if (abs(real_minutes - mostek_minutes) < 30) {
+			mregs->creg |= MSTK_CREG_WRITE;
+			mregs->sec = real_seconds;
+			mregs->min = real_minutes;
+			mregs->creg &= ~MSTK_CREG_WRITE;
+		} else
+			retval = -1;
+	}
+
+	return retval;
 }

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov with Sam's (original) version
of this