NetBSD Problem Report #8824

Received: (qmail 21813 invoked from network); 19 Nov 1999 03:42:35 -0000
Message-Id: <199911190342.UAA15137@loop.home>
Date: Thu, 18 Nov 1999 20:42:23 -0700 (MST)
From: Steve Peurifoy <swp@alumni.rice.edu>
Reply-To: swp@alumni.rice.edu
To: gnats-bugs@gnats.netbsd.org
Subject: year 2000 problem with battery backed clock
X-Send-Pr-Version: 3.95

>Number:         8824
>Category:       port-hp300
>Synopsis:       battery backed clock fails across year 2000 boundary
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    port-hp300-maintainer
>State:          closed
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Thu Nov 18 19:45:01 +0000 1999
>Closed-Date:    Sat Nov 10 19:52:29 +0000 2001
>Last-Modified:  Sat Nov 10 19:52:29 +0000 2001
>Originator:     
>Release:        1.4K (1999/10/02 sources)
>Organization:
>Environment:
System: NetBSD loop 1.4K NetBSD 1.4K (loop) #1: Thu Nov 18 16:10:13 MST 1999 root@loop:/usr/obj/sys/arch/hp300/compile/loop hp300


>Description:
	An hp300 that is powered down during the transition from 1999/12/31
	to 2000/01/01 (UTC) will have an incorrect system time when it is
	next booted.
>How-To-Repeat:
	TZ=UTC date -n 199912312345
	/sbin/halt
	power down system
	wait > 15 minutes
	power up system - it will complain about a bad date in battery backed
		clock and will set time from root fs superblock.
>Fix:
	The following patch works for me.  Note that the problem will not
	manifest itself if the system is left up during the transition.
	The decade register in the bbc can be set to the value 0xa
	but it will not roll to 0xa from 9.

	This patch also changes a couple of comments apparently written by
	someone who never read the bbc's datasheet and fixes one spelling
	nit.

	The line numbers in this patch won't match up with the file
	in the tree due to some local modifications but there should
	be sufficient context.

Index: clock.c
===================================================================
RCS file: /cvs/src/sys/arch/hp300/hp300/clock.c,v
retrieving revision 1.2
diff -c -r1.2 clock.c
*** clock.c	1999/02/20 03:28:22	1.2
--- clock.c	1999/11/19 02:49:03
***************
*** 470,479 ****
  	decimal_to_bbc(9, 10, tmptr->tm_mon);
  	decimal_to_bbc(11, 12, tmptr->tm_year);

! 	/* 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])) {
--- 470,479 ----
  	decimal_to_bbc(9, 10, tmptr->tm_mon);
  	decimal_to_bbc(11, 12, tmptr->tm_year);

! 	/* Set MSB of reg 5 to specify 24 hour mode */
  	bbc_registers[5] = ((tmptr->tm_hour / 10) & 0x03) + 8;

! 	write_bbc_reg(15, 13);	/* reset prescaler */

  	for (i = 0; i <= NUM_BBC_REGS; i++)
  	  	if (bbc_registers[i] != write_bbc_reg(i, bbc_registers[i])) {
***************
*** 499,507 ****
  	rt.tm_sec  = (hms % 3600) % 60;

  	/* 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))
--- 499,514 ----
  	rt.tm_sec  = (hms % 3600) % 60;

  	/* Number of years in days */
+ 	/*
+ 	 * Note that although one can successfully write any 4 bit
+ 	 * number including 0xa..0xf into reg 12 of the bbc, it
+ 	 * will not roll from 0x9 to 0xa.  Better to just treat
+ 	 * anything greater than 9 as invalid, so disallow year > 100
+ 	 * and compensate when reading out in bbc_to_gmt().
+ 	 */
  	for (i = STARTOFTIME - 1900; day >= days_in_year(i); i++)
  	  	day -= days_in_year(i);
! 	rt.tm_year = (i < 100) ? i : (i - 100);

  	/* Number of months in days left */
  	if (leapyear(rt.tm_year))
***************
*** 531,547 ****
  	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;

  	range_test(hour, 0, 23);
  	range_test(day, 1, 31);
  	range_test(month, 1, 12);
! 	range_test(year, STARTOFTIME, 2000);

  	tmp = 0;

--- 538,556 ----
  	min = bbc_to_decimal(3, 2);

  	/*
! 	 * Upper two bits of reg 5 specify 12/24 hr mode and AM/PM.
  	 */
  	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;
+ 	if (year < STARTOFTIME)
+ 		year += 100;

  	range_test(hour, 0, 23);
  	range_test(day, 1, 31);
  	range_test(month, 1, 12);
! 	range_test(year, STARTOFTIME, 2037);

  	tmp = 0;

>Release-Note:
>Audit-Trail:
State-Changed-From-To: open->closed 
State-Changed-By: tsutsui 
State-Changed-When: Sat Nov 10 11:48:29 PST 2001 
State-Changed-Why:  
Similar fixed were applied in clock.c rev. 1.22 and 1.23. 
Sorry for late response.. 
>Unformatted:

NetBSD Home
NetBSD PR Database Search

(Contact us) $NetBSD: query-full-pr,v 1.39 2013/11/01 18:47:49 spz Exp $
$NetBSD: gnats_config.sh,v 1.8 2006/05/07 09:23:38 tsutsui Exp $
Copyright © 1994-2007 The NetBSD Foundation, Inc. ALL RIGHTS RESERVED.