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); +} +