Module Name:    src
Committed By:   snj
Date:           Fri Jun 19 21:22:11 UTC 2009

Modified Files:
        src/sys/arch/amd64/conf [netbsd-5]: files.amd64
        src/sys/arch/i386/conf [netbsd-5]: files.i386
        src/sys/arch/x86/isa [netbsd-5]: clock.c
        src/sys/arch/xen/conf [netbsd-5]: files.xen
        src/sys/arch/xen/xen [netbsd-5]: clock.c
Added Files:
        src/sys/arch/x86/include [netbsd-5]: rtc.h
        src/sys/arch/x86/isa [netbsd-5]: rtc.c

Log Message:
Pull up following revision(s) (requested by bouyer in ticket #816):
        sys/arch/amd64/conf/files.amd64: revision 1.68
        sys/arch/i386/conf/files.i386: revision 1.350
        sys/arch/x86/include/rtc.h: revision 1.1
        sys/arch/x86/isa/clock.c: revision 1.33
        sys/arch/x86/isa/rtc.c: revision 1.1
        sys/arch/xen/conf/files.xen: revision 1.100
        sys/arch/xen/xen/clock.c: revision 1.50 via patch
Split mc146818-related functions from clock.c into rtc.c.
Call rtc_set_ymdhms() from xen/xen/clock.c:xen_rtc_set() for xen3 dom0
kernels as the Xen3 hypervisor doesn't write the new date/time to the CMOS
by itself.
Now a XEN3_DOM0 kernel properly updates the CMOS time.


To generate a diff of this commit:
cvs rdiff -u -r1.60 -r1.60.8.1 src/sys/arch/amd64/conf/files.amd64
cvs rdiff -u -r1.338.6.2 -r1.338.6.3 src/sys/arch/i386/conf/files.i386
cvs rdiff -u -r0 -r1.1.2.2 src/sys/arch/x86/include/rtc.h
cvs rdiff -u -r1.30 -r1.30.8.1 src/sys/arch/x86/isa/clock.c
cvs rdiff -u -r0 -r1.1.2.2 src/sys/arch/x86/isa/rtc.c
cvs rdiff -u -r1.88.4.3 -r1.88.4.4 src/sys/arch/xen/conf/files.xen
cvs rdiff -u -r1.47 -r1.47.4.1 src/sys/arch/xen/xen/clock.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/arch/amd64/conf/files.amd64
diff -u src/sys/arch/amd64/conf/files.amd64:1.60 src/sys/arch/amd64/conf/files.amd64:1.60.8.1
--- src/sys/arch/amd64/conf/files.amd64:1.60	Sun May 11 14:44:53 2008
+++ src/sys/arch/amd64/conf/files.amd64	Fri Jun 19 21:22:10 2009
@@ -1,4 +1,4 @@
-#	$NetBSD: files.amd64,v 1.60 2008/05/11 14:44:53 ad Exp $
+#	$NetBSD: files.amd64,v 1.60.8.1 2009/06/19 21:22:10 snj Exp $
 #
 # new style config file for amd64 architecture
 #
@@ -112,6 +112,7 @@
 
 # PC clock
 file 	arch/x86/isa/clock.c 			isa
+file	arch/x86/isa/rtc.c			isa
 
 # TSC timecounter support
 file	arch/x86/x86/tsc.c

Index: src/sys/arch/i386/conf/files.i386
diff -u src/sys/arch/i386/conf/files.i386:1.338.6.2 src/sys/arch/i386/conf/files.i386:1.338.6.3
--- src/sys/arch/i386/conf/files.i386:1.338.6.2	Mon Feb 16 03:03:36 2009
+++ src/sys/arch/i386/conf/files.i386	Fri Jun 19 21:22:10 2009
@@ -1,4 +1,4 @@
-#	$NetBSD: files.i386,v 1.338.6.2 2009/02/16 03:03:36 snj Exp $
+#	$NetBSD: files.i386,v 1.338.6.3 2009/06/19 21:22:10 snj Exp $
 #
 # new style config file for i386 architecture
 #
@@ -248,6 +248,7 @@
 
 # PC clock
 file	arch/x86/isa/clock.c		isa
+file	arch/x86/isa/rtc.c		isa
 
 # TSC support
 file	arch/x86/x86/tsc.c

Index: src/sys/arch/x86/isa/clock.c
diff -u src/sys/arch/x86/isa/clock.c:1.30 src/sys/arch/x86/isa/clock.c:1.30.8.1
--- src/sys/arch/x86/isa/clock.c:1.30	Sun May 11 22:18:08 2008
+++ src/sys/arch/x86/isa/clock.c	Fri Jun 19 21:22:10 2009
@@ -1,4 +1,4 @@
-/*	$NetBSD: clock.c,v 1.30 2008/05/11 22:18:08 ad Exp $	*/
+/*	$NetBSD: clock.c,v 1.30.8.1 2009/06/19 21:22:10 snj Exp $	*/
 
 /*-
  * Copyright (c) 1990 The Regents of the University of California.
@@ -121,7 +121,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: clock.c,v 1.30 2008/05/11 22:18:08 ad Exp $");
+__KERNEL_RCSID(0, "$NetBSD: clock.c,v 1.30.8.1 2009/06/19 21:22:10 snj Exp $");
 
 /* #define CLOCKDEBUG */
 /* #define CLOCK_PARANOIA */
@@ -150,8 +150,8 @@
 #include <i386/isa/nvram.h>
 #include <x86/x86/tsc.h>
 #include <x86/lock.h>
-#include <dev/clock_subr.h>
 #include <machine/specialreg.h> 
+#include <x86/rtc.h>
 
 #ifndef __x86_64__
 #include "mca.h"
@@ -188,13 +188,7 @@
 static void     tickle_tc(void);
 
 static int	clockintr(void *, struct intrframe *);
-static void	rtcinit(void);
-static int	rtcget(mc_todregs *);
-static void	rtcput(mc_todregs *);
 
-static int	cmoscheck(void);
-
-static int	clock_expandyear(int);
 int 		sysbeepdetach(device_t, int);
 
 static unsigned int	gettick_broken_latch(void);
@@ -206,11 +200,7 @@
 /* to protect TC timer variables */
 static __cpu_simple_lock_t tmr_lock = __SIMPLELOCK_UNLOCKED;
 
-inline u_int mc146818_read(void *, u_int);
-inline void mc146818_write(void *, u_int, u_int);
-
 u_int i8254_get_timecount(struct timecounter *);
-static void rtc_register(void);
 
 static struct timecounter i8254_timecounter = {
 	i8254_get_timecount,	/* get_timecount */
@@ -223,24 +213,6 @@
 	NULL,			/* next */
 };
 
-/* XXX use sc? */
-inline u_int
-mc146818_read(void *sc, u_int reg)
-{
-
-	outb(IO_RTC, reg);
-	return (inb(IO_RTC+1));
-}
-
-/* XXX use sc? */
-inline void
-mc146818_write(void *sc, u_int reg, u_int datum)
-{
-
-	outb(IO_RTC, reg);
-	outb(IO_RTC+1, datum);
-}
-
 u_long rtclock_tval;		/* i8254 reload value for countdown */
 int    rtclock_init = 0;
 
@@ -584,214 +556,6 @@
 	    (int (*)(void *))clockintr, 0);
 }
 
-static void
-rtcinit(void)
-{
-	static int first_rtcopen_ever = 1;
-
-	if (!first_rtcopen_ever)
-		return;
-	first_rtcopen_ever = 0;
-
-	mc146818_write(NULL, MC_REGA,			/* XXX softc */
-	    MC_BASE_32_KHz | MC_RATE_1024_Hz);
-	mc146818_write(NULL, MC_REGB, MC_REGB_24HR);	/* XXX softc */
-}
-
-static int
-rtcget(mc_todregs *regs)
-{
-
-	rtcinit();
-	if ((mc146818_read(NULL, MC_REGD) & MC_REGD_VRT) == 0) /* XXX softc */
-		return (-1);
-	MC146818_GETTOD(NULL, regs);			/* XXX softc */
-	return (0);
-}	
-
-static void
-rtcput(mc_todregs *regs)
-{
-
-	rtcinit();
-	MC146818_PUTTOD(NULL, regs);			/* XXX softc */
-}
-
-/*
- * check whether the CMOS layout is "standard"-like (ie, not PS/2-like),
- * to be called at splclock()
- */
-static int
-cmoscheck(void)
-{
-	int i;
-	unsigned short cksum = 0;
-
-	for (i = 0x10; i <= 0x2d; i++)
-		cksum += mc146818_read(NULL, i); /* XXX softc */
-
-	return (cksum == (mc146818_read(NULL, 0x2e) << 8)
-			  + mc146818_read(NULL, 0x2f));
-}
-
-#if NMCA > 0
-/*
- * Check whether the CMOS layout is PS/2 like, to be called at splclock().
- */
-static int cmoscheckps2(void);
-static int
-cmoscheckps2(void)
-{
-#if 0
-	/* Disabled until I find out the CRC checksum algorithm IBM uses */
-	int i;
-	unsigned short cksum = 0;
-
-	for (i = 0x10; i <= 0x31; i++)
-		cksum += mc146818_read(NULL, i); /* XXX softc */
-
-	return (cksum == (mc146818_read(NULL, 0x32) << 8)
-			  + mc146818_read(NULL, 0x33));
-#else
-	/* Check 'incorrect checksum' bit of IBM PS/2 Diagnostic Status Byte */
-	return ((mc146818_read(NULL, NVRAM_DIAG) & (1<<6)) == 0);
-#endif
-}
-#endif /* NMCA > 0 */
-
-/*
- * patchable to control century byte handling:
- * 1: always update
- * -1: never touch
- * 0: try to figure out itself
- */
-int rtc_update_century = 0;
-
-/*
- * Expand a two-digit year as read from the clock chip
- * into full width.
- * Being here, deal with the CMOS century byte.
- */
-static int centb = NVRAM_CENTURY;
-static int
-clock_expandyear(int clockyear)
-{
-	int s, clockcentury, cmoscentury;
-
-	clockcentury = (clockyear < 70) ? 20 : 19;
-	clockyear += 100 * clockcentury;
-
-	if (rtc_update_century < 0)
-		return (clockyear);
-
-	s = splclock();
-	if (cmoscheck())
-		cmoscentury = mc146818_read(NULL, NVRAM_CENTURY);
-#if NMCA > 0
-	else if (MCA_system && cmoscheckps2())
-		cmoscentury = mc146818_read(NULL, (centb = 0x37));
-#endif
-	else
-		cmoscentury = 0;
-	splx(s);
-	if (!cmoscentury) {
-#ifdef DIAGNOSTIC
-		printf("clock: unknown CMOS layout\n");
-#endif
-		return (clockyear);
-	}
-	cmoscentury = bcdtobin(cmoscentury);
-
-	if (cmoscentury != clockcentury) {
-		/* XXX note: saying "century is 20" might confuse the naive. */
-		printf("WARNING: NVRAM century is %d but RTC year is %d\n",
-		       cmoscentury, clockyear);
-
-		/* Kludge to roll over century. */
-		if ((rtc_update_century > 0) ||
-		    ((cmoscentury == 19) && (clockcentury == 20) &&
-		     (clockyear == 2000))) {
-			printf("WARNING: Setting NVRAM century to %d\n",
-			       clockcentury);
-			s = splclock();
-			mc146818_write(NULL, centb, bintobcd(clockcentury));
-			splx(s);
-		}
-	} else if (cmoscentury == 19 && rtc_update_century == 0)
-		rtc_update_century = 1; /* will update later in resettodr() */
-
-	return (clockyear);
-}
-
-static int
-rtc_get_ymdhms(todr_chip_handle_t tch, struct clock_ymdhms *dt)
-{
-	int s;
-	mc_todregs rtclk;
-
-	s = splclock();
-	if (rtcget(&rtclk)) {
-		splx(s);
-		return -1;
-	}
-	splx(s);
-
-	dt->dt_sec = bcdtobin(rtclk[MC_SEC]);
-	dt->dt_min = bcdtobin(rtclk[MC_MIN]);
-	dt->dt_hour = bcdtobin(rtclk[MC_HOUR]);
-	dt->dt_day = bcdtobin(rtclk[MC_DOM]);
-	dt->dt_mon = bcdtobin(rtclk[MC_MONTH]);
-	dt->dt_year = clock_expandyear(bcdtobin(rtclk[MC_YEAR]));
-
-	return 0;
-}
-
-static int
-rtc_set_ymdhms(todr_chip_handle_t tch, struct clock_ymdhms *dt)
-{
-	mc_todregs rtclk;
-	int century;
-	int s;
-
-	s = splclock();
-	if (rtcget(&rtclk))
-		memset(&rtclk, 0, sizeof(rtclk));
-	splx(s);
-
-	rtclk[MC_SEC] = bintobcd(dt->dt_sec);
-	rtclk[MC_MIN] = bintobcd(dt->dt_min);
-	rtclk[MC_HOUR] = bintobcd(dt->dt_hour);
-	rtclk[MC_DOW] = dt->dt_wday + 1;
-	rtclk[MC_YEAR] = bintobcd(dt->dt_year % 100);
-	rtclk[MC_MONTH] = bintobcd(dt->dt_mon);
-	rtclk[MC_DOM] = bintobcd(dt->dt_day);
-
-#ifdef DEBUG_CLOCK
-	printf("setclock: %x/%x/%x %x:%x:%x\n", rtclk[MC_YEAR], rtclk[MC_MONTH],
-	   rtclk[MC_DOM], rtclk[MC_HOUR], rtclk[MC_MIN], rtclk[MC_SEC]);
-#endif
-	s = splclock();
-	rtcput(&rtclk);
-	if (rtc_update_century > 0) {
-		century = bintobcd(dt->dt_year / 100);
-		mc146818_write(NULL, centb, century); /* XXX softc */
-	}
-	splx(s);
-	return 0;
-
-}
-
-static void
-rtc_register(void)
-{
-	static struct todr_chip_handle	tch;
-	tch.todr_gettime_ymdhms = rtc_get_ymdhms;
-	tch.todr_settime_ymdhms = rtc_set_ymdhms;
-	tch.todr_setwen = NULL;
-
-	todr_attach(&tch);
-}
-
 void
 setstatclockrate(int arg)
 {

Index: src/sys/arch/xen/conf/files.xen
diff -u src/sys/arch/xen/conf/files.xen:1.88.4.3 src/sys/arch/xen/conf/files.xen:1.88.4.4
--- src/sys/arch/xen/conf/files.xen:1.88.4.3	Tue Jun 16 02:20:41 2009
+++ src/sys/arch/xen/conf/files.xen	Fri Jun 19 21:22:11 2009
@@ -1,4 +1,4 @@
-#	$NetBSD: files.xen,v 1.88.4.3 2009/06/16 02:20:41 snj Exp $
+#	$NetBSD: files.xen,v 1.88.4.4 2009/06/19 21:22:11 snj Exp $
 #	NetBSD: files.x86,v 1.10 2003/10/08 17:30:00 bouyer Exp 
 #	NetBSD: files.i386,v 1.254 2004/03/25 23:32:10 jmc Exp 
 
@@ -103,6 +103,7 @@
 file	arch/xen/xen/xen_debug.c
 
 file	arch/xen/xen/clock.c
+file	arch/x86/isa/rtc.c		xen3 & dom0ops
 file	arch/xen/xen/evtchn.c
 file	arch/xen/xen/ctrl_if.c			!xen3
 

Index: src/sys/arch/xen/xen/clock.c
diff -u src/sys/arch/xen/xen/clock.c:1.47 src/sys/arch/xen/xen/clock.c:1.47.4.1
--- src/sys/arch/xen/xen/clock.c:1.47	Tue Oct 21 15:46:32 2008
+++ src/sys/arch/xen/xen/clock.c	Fri Jun 19 21:22:11 2009
@@ -1,4 +1,4 @@
-/*	$NetBSD: clock.c,v 1.47 2008/10/21 15:46:32 cegger Exp $	*/
+/*	$NetBSD: clock.c,v 1.47.4.1 2009/06/19 21:22:11 snj Exp $	*/
 
 /*
  *
@@ -34,7 +34,7 @@
 #include "opt_xen.h"
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: clock.c,v 1.47 2008/10/21 15:46:32 cegger Exp $");
+__KERNEL_RCSID(0, "$NetBSD: clock.c,v 1.47.4.1 2009/06/19 21:22:11 snj Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -51,6 +51,7 @@
 #include <machine/cpu_counter.h>
 
 #include <dev/clock_subr.h>
+#include <x86/rtc.h>
 
 static int xen_timer_handler(void *, struct intrframe *);
 
@@ -312,6 +313,13 @@
 	int s;
 
 	if (xendomain_is_privileged()) {
+#ifdef XEN3
+		/* needs to set the RTC chip too */
+		struct clock_ymdhms dt;
+		clock_secs_to_ymdhms(tvp->tv_sec, &dt);
+		rtc_set_ymdhms(NULL, &dt);
+#endif
+
 		op.cmd = DOM0_SETTIME;
 		/* XXX is rtc_offset handled correctly everywhere? */
 		op.u.settime.secs	 = tvp->tv_sec;
@@ -323,7 +331,7 @@
 		s = splhigh();
 		op.u.settime.system_time = get_system_time();
 		splx(s);
-		HYPERVISOR_dom0_op(&op);
+		return HYPERVISOR_dom0_op(&op);
 	}
 #endif
 

Added files:

Index: src/sys/arch/x86/include/rtc.h
diff -u /dev/null src/sys/arch/x86/include/rtc.h:1.1.2.2
--- /dev/null	Fri Jun 19 21:22:11 2009
+++ src/sys/arch/x86/include/rtc.h	Fri Jun 19 21:22:10 2009
@@ -0,0 +1,7 @@
+/*      $NetBSD: rtc.h,v 1.1.2.2 2009/06/19 21:22:10 snj Exp $    */
+
+#include <dev/clock_subr.h>
+
+void rtc_register(void);
+int  rtc_get_ymdhms(todr_chip_handle_t, struct clock_ymdhms *);
+int  rtc_set_ymdhms(todr_chip_handle_t, struct clock_ymdhms *);

Index: src/sys/arch/x86/isa/rtc.c
diff -u /dev/null src/sys/arch/x86/isa/rtc.c:1.1.2.2
--- /dev/null	Fri Jun 19 21:22:11 2009
+++ src/sys/arch/x86/isa/rtc.c	Fri Jun 19 21:22:11 2009
@@ -0,0 +1,378 @@
+/*	$NetBSD: rtc.c,v 1.1.2.2 2009/06/19 21:22:11 snj Exp $	*/
+
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * William Jolitz and Don Ahn.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)clock.c	7.2 (Berkeley) 5/12/91
+ */
+/*-
+ * Copyright (c) 1993, 1994 Charles M. Hannum.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * William Jolitz and Don Ahn.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)clock.c	7.2 (Berkeley) 5/12/91
+ */
+/* 
+ * Mach Operating System
+ * Copyright (c) 1991,1990,1989 Carnegie Mellon University
+ * All Rights Reserved.
+ * 
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ * 
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ * 
+ * Carnegie Mellon requests users of this software to return to
+ * 
+ *  Software Distribution Coordinator  or  software.distribut...@cs.cmu.edu
+ *  School of Computer Science
+ *  Carnegie Mellon University
+ *  Pittsburgh PA 15213-3890
+ * 
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+  Copyright 1988, 1989 by Intel Corporation, Santa Clara, California.
+
+		All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and
+its documentation for any purpose and without fee is hereby
+granted, provided that the above copyright notice appears in all
+copies and that both the copyright notice and this permission notice
+appear in supporting documentation, and that the name of Intel
+not be used in advertising or publicity pertaining to distribution
+of the software without specific, written prior permission.
+
+INTEL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
+IN NO EVENT SHALL INTEL BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
+CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
+NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+
+/*
+ * Primitive RTC chip routines.
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: rtc.c,v 1.1.2.2 2009/06/19 21:22:11 snj Exp $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/time.h>
+#include <sys/timetc.h>
+#include <sys/kernel.h>
+
+#include <dev/isa/isareg.h>
+#include <dev/isa/isavar.h>
+#include <i386/isa/nvram.h>
+
+#include <machine/pio.h>
+
+#include <dev/ic/mc146818reg.h>
+#include <x86/rtc.h>
+
+#ifndef __x86_64__
+#include "mca.h"
+#endif
+#if NMCA > 0
+#include <machine/mca_machdep.h>	/* for MCA_system */
+#endif
+
+static void	rtcinit(void);
+static int	rtcget(mc_todregs *);
+static void	rtcput(mc_todregs *);
+static int	cmoscheck(void);
+static int	clock_expandyear(int);
+
+/* XXX use sc? */
+u_int
+mc146818_read(void *sc, u_int reg)
+{
+
+	outb(IO_RTC, reg);
+	return (inb(IO_RTC+1));
+}
+
+void
+mc146818_write(void *sc, u_int reg, u_int datum)
+{
+
+	outb(IO_RTC, reg);
+	outb(IO_RTC+1, datum);
+}
+
+static void
+rtcinit(void)
+{
+	static int first_rtcopen_ever = 1;
+
+	if (!first_rtcopen_ever)
+		return;
+	first_rtcopen_ever = 0;
+
+	mc146818_write(NULL, MC_REGA,			/* XXX softc */
+	    MC_BASE_32_KHz | MC_RATE_1024_Hz);
+	mc146818_write(NULL, MC_REGB, MC_REGB_24HR);	/* XXX softc */
+}
+
+static int
+rtcget(mc_todregs *regs)
+{
+
+	rtcinit();
+	if ((mc146818_read(NULL, MC_REGD) & MC_REGD_VRT) == 0) /* XXX softc */
+		return (-1);
+	MC146818_GETTOD(NULL, regs);			/* XXX softc */
+	return (0);
+}	
+
+static void
+rtcput(mc_todregs *regs)
+{
+
+	rtcinit();
+	MC146818_PUTTOD(NULL, regs);			/* XXX softc */
+}
+
+/*
+ * check whether the CMOS layout is "standard"-like (ie, not PS/2-like),
+ * to be called at splclock()
+ */
+static int
+cmoscheck(void)
+{
+	int i;
+	unsigned short cksum = 0;
+
+	for (i = 0x10; i <= 0x2d; i++)
+		cksum += mc146818_read(NULL, i); /* XXX softc */
+
+	return (cksum == (mc146818_read(NULL, 0x2e) << 8)
+			  + mc146818_read(NULL, 0x2f));
+}
+
+#if NMCA > 0
+/*
+ * Check whether the CMOS layout is PS/2 like, to be called at splclock().
+ */
+static int cmoscheckps2(void);
+static int
+cmoscheckps2(void)
+{
+#if 0
+	/* Disabled until I find out the CRC checksum algorithm IBM uses */
+	int i;
+	unsigned short cksum = 0;
+
+	for (i = 0x10; i <= 0x31; i++)
+		cksum += mc146818_read(NULL, i); /* XXX softc */
+
+	return (cksum == (mc146818_read(NULL, 0x32) << 8)
+			  + mc146818_read(NULL, 0x33));
+#else
+	/* Check 'incorrect checksum' bit of IBM PS/2 Diagnostic Status Byte */
+	return ((mc146818_read(NULL, NVRAM_DIAG) & (1<<6)) == 0);
+#endif
+}
+#endif /* NMCA > 0 */
+
+/*
+ * patchable to control century byte handling:
+ * 1: always update
+ * -1: never touch
+ * 0: try to figure out itself
+ */
+int rtc_update_century = 0;
+
+/*
+ * Expand a two-digit year as read from the clock chip
+ * into full width.
+ * Being here, deal with the CMOS century byte.
+ */
+static int centb = NVRAM_CENTURY;
+static int
+clock_expandyear(int clockyear)
+{
+	int s, clockcentury, cmoscentury;
+
+	clockcentury = (clockyear < 70) ? 20 : 19;
+	clockyear += 100 * clockcentury;
+
+	if (rtc_update_century < 0)
+		return (clockyear);
+
+	s = splclock();
+	if (cmoscheck())
+		cmoscentury = mc146818_read(NULL, NVRAM_CENTURY);
+#if NMCA > 0
+	else if (MCA_system && cmoscheckps2())
+		cmoscentury = mc146818_read(NULL, (centb = 0x37));
+#endif
+	else
+		cmoscentury = 0;
+	splx(s);
+	if (!cmoscentury) {
+#ifdef DIAGNOSTIC
+		printf("clock: unknown CMOS layout\n");
+#endif
+		return (clockyear);
+	}
+	cmoscentury = bcdtobin(cmoscentury);
+
+	if (cmoscentury != clockcentury) {
+		/* XXX note: saying "century is 20" might confuse the naive. */
+		printf("WARNING: NVRAM century is %d but RTC year is %d\n",
+		       cmoscentury, clockyear);
+
+		/* Kludge to roll over century. */
+		if ((rtc_update_century > 0) ||
+		    ((cmoscentury == 19) && (clockcentury == 20) &&
+		     (clockyear == 2000))) {
+			printf("WARNING: Setting NVRAM century to %d\n",
+			       clockcentury);
+			s = splclock();
+			mc146818_write(NULL, centb, bintobcd(clockcentury));
+			splx(s);
+		}
+	} else if (cmoscentury == 19 && rtc_update_century == 0)
+		rtc_update_century = 1; /* will update later in resettodr() */
+
+	return (clockyear);
+}
+
+int
+rtc_get_ymdhms(todr_chip_handle_t tch, struct clock_ymdhms *dt)
+{
+	int s;
+	mc_todregs rtclk;
+
+	s = splclock();
+	if (rtcget(&rtclk)) {
+		splx(s);
+		return -1;
+	}
+	splx(s);
+
+	dt->dt_sec = bcdtobin(rtclk[MC_SEC]);
+	dt->dt_min = bcdtobin(rtclk[MC_MIN]);
+	dt->dt_hour = bcdtobin(rtclk[MC_HOUR]);
+	dt->dt_day = bcdtobin(rtclk[MC_DOM]);
+	dt->dt_mon = bcdtobin(rtclk[MC_MONTH]);
+	dt->dt_year = clock_expandyear(bcdtobin(rtclk[MC_YEAR]));
+
+	return 0;
+}
+
+int
+rtc_set_ymdhms(todr_chip_handle_t tch, struct clock_ymdhms *dt)
+{
+	mc_todregs rtclk;
+	int century;
+	int s;
+
+	s = splclock();
+	if (rtcget(&rtclk))
+		memset(&rtclk, 0, sizeof(rtclk));
+	splx(s);
+
+	rtclk[MC_SEC] = bintobcd(dt->dt_sec);
+	rtclk[MC_MIN] = bintobcd(dt->dt_min);
+	rtclk[MC_HOUR] = bintobcd(dt->dt_hour);
+	rtclk[MC_DOW] = dt->dt_wday + 1;
+	rtclk[MC_YEAR] = bintobcd(dt->dt_year % 100);
+	rtclk[MC_MONTH] = bintobcd(dt->dt_mon);
+	rtclk[MC_DOM] = bintobcd(dt->dt_day);
+
+#ifdef DEBUG_CLOCK
+	printf("setclock: %x/%x/%x %x:%x:%x\n", rtclk[MC_YEAR], rtclk[MC_MONTH],
+	   rtclk[MC_DOM], rtclk[MC_HOUR], rtclk[MC_MIN], rtclk[MC_SEC]);
+#endif
+	s = splclock();
+	rtcput(&rtclk);
+	if (rtc_update_century > 0) {
+		century = bintobcd(dt->dt_year / 100);
+		mc146818_write(NULL, centb, century); /* XXX softc */
+	}
+	splx(s);
+	return 0;
+
+}
+
+void
+rtc_register(void)
+{
+	static struct todr_chip_handle	tch;
+	tch.todr_gettime_ymdhms = rtc_get_ymdhms;
+	tch.todr_settime_ymdhms = rtc_set_ymdhms;
+	tch.todr_setwen = NULL;
+
+	todr_attach(&tch);
+}
+

Reply via email to