lkml.org 
[lkml]   [1999]   [May]   [27]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patches in this message
/
Date
From
Subject[PATCH] * RTC problem ???
Hi All.

>>>> IMHO, a simple command parameter giving the offset in hours
>>>> (half-hours?) from UTC to the kernel is fine...

>>> At most half-hours (Adelaide, South Australia has a half-hour
>>> timezone).

>> My understanding is that there's two or three countries in Asia
>> with timezones on quarter hour boundaries as well, so at least
>> that level of granularity would be needed.

> Well, we could go down to a one minute resolution or more,
> that's not really a problem. But what about daylight savings,
> is it univesally on the same day and by exactly one hour
> everywhere? I'm sure there are even more gory details like
> leap-seconds and such. The zoneinfo database handles all the
> special cases nicely and is very flexible. I don't think we
> want to duplicate all that inside the kernel.

If my reading of the situation is correct, then those details are all
irrelevant anyway. All the kernel cares about is the state of the RTC
on the system, and few (if any) RTC chips go into that sort of detail.
Looking at it from that point of view, just TWO kernel variables will
deal with all cases of interest. Have a look at the specs for the
various RTC chips in use, and you'll generally find that they deal
with dates and times as follows:

1. All days are considered to consist of exactly 86,400 seconds,
which comprise 24 hours, each containing 60 minutes, and each
of those minutes comprises exactly 60 seconds.

2. There is NO indication as to the timezone in which the chip
is set. This information is presumed to be set by an external
source whenever the chip is initialised.

3. There is a flag bit somewhere in the chip which indicates if
the datestamp read from the RTC is DST or non-DST time. The
value read from this chip when the said flag bit indicates
non-DST time is the actual time stored in the various counters
in the chip.

4. I understand that there are RTC chips which have a register
to indicate the offset to be applied for DST, but most RTC
chips (including the one used in IBM PC clones) always use
an offset of +60 minutes when returning DST datestamps.

Based on the above specification, the following patch (against 2.2.9)
would perform the basic requirements of such an algorithm, providing
most of the key features required. Comments inserted between the
various hunks as relevant.

--- linux-2.2.9/arch/i386/config.in~ Mon Apr 26 21:49:17 1999
+++ linux-2.2.9/arch/i386/config.in Tue May 25 00:18:18 1999
@@ -50,6 +50,7 @@
mainmenu_option next_comment
comment 'General setup'

+bool 'RTC stores UTC times' CONFIG_RTC_IS_UTC
bool 'Networking support' CONFIG_NET
bool 'PCI support' CONFIG_PCI
if [ "$CONFIG_PCI" = "y" ]; then
--- linux-2.2.9/arch/i386/defconfig~ Mon Apr 12 21:12:57 1999
+++ linux-2.2.9/arch/i386/defconfig Tue May 25 00:18:57 1999
@@ -35,6 +35,7 @@
#
# General setup
#
+CONFIG_RTC_IS_UTC=y
CONFIG_NET=y
CONFIG_PCI=y
# CONFIG_PCI_GOBIOS is not set
The above two hunks add the necessary configuration option, and set it
to default to the RTC storing UTC times. Put it wherever you think
best fits, I'm not worried about that.

--- linux-2.2.9/scripts/rtctz~ Tue May 25 00:58:34 1999
+++ linux-2.2.9/scripts/rtctz Tue May 25 01:02:02 1999
@@ -0,0 +1,2 @@
+#!/bin/bash
+echo $[`date +%H*60+%M-720 -d "12:00:00 UTC"`]
The above hunk creates a new script file containing the command needed
to determine the correct default timezone for the case where the RTC
is not storing times in UTC. This command should rightly be part of
the Makefile (next hunk), but I don't know how to insert it in the
right place, hence my use of a separate script file.

--- linux-2.2.9/arch/i386/kernel/Makefile~ Wed Jan 20 18:18:53 1999
+++ linux-2.2.9/arch/i386/kernel/Makefile Tue May 25 00:59:26 1999
@@ -18,6 +18,8 @@
OX_OBJS := i386_ksyms.o
MX_OBJS :=

+EXTRA_CFLAGS := -DRTCTZ=$(shell $(TOPDIR)/scripts/rtctz)
+
ifdef CONFIG_PCI
O_OBJS += bios32.o
endif
The above hunk causes the output from the shell script in the previous
hunk to be assigned to a variable passed as a parameter to the C files
in this directory, and in particular to the file time.c when it is
compiled.

--- linux-2.2.9/arch/i386/kernel/time.c~ Thu Apr 29 19:53:41 1999
+++ linux-2.2.9/arch/i386/kernel/time.c Tue May 25 00:45:15 1999
@@ -61,6 +61,12 @@
*/
#include "irq.h"

+#ifdef CONFIG_RTC_IS_UTC
+__s16 rtctz = +0;
+#else
+__s16 rtctz = RTCTZ;
+#endif
+#define RTCDST 60

unsigned long cpu_hz; /* Detected as we calibrate the TSC */

@@ -496,7 +502,7 @@
/* not static: needed by APM */
unsigned long get_cmos_time(void)
{
- unsigned int year, mon, day, hour, min, sec;
+ unsigned int year, mon, day, hour, min, sec, dst;
int i;

/* The Linux interpretation of the CMOS clock register contents:
@@ -518,6 +524,7 @@
day = CMOS_READ(RTC_DAY_OF_MONTH);
mon = CMOS_READ(RTC_MONTH);
year = CMOS_READ(RTC_YEAR);
+ dst = 0;
} while (sec != CMOS_READ(RTC_SECONDS));
if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
{
@@ -528,6 +535,17 @@
BCD_TO_BIN(mon);
BCD_TO_BIN(year);
}
+
+ /* Note that mktime correctly handles what would normally
+ * be out of range values in the fields passed to it, so
+ * we do not need to handle them ourself.
+ */
+
+ min -= rtctz;
+ if (dst) {
+ min -= RTCDST;
+ }
+
if ((year += 1900) < 1970)
year += 100;
return mktime(year, mon, day, hour, min, sec);
This last group of four hunks add the relevant code to implement the
functions as defined, with the following exception: I do not have the
spec sheet for the RTC chip, so can't insert the correct line to read
the value of the "Using DST" flag bit. This patch therefore assumes
that the said flag is always clear. To correct this, change the line
in the third of the above four hunks that currently reads "dst=0" to
set the variable dst to nonzero if the flag indicates "Using DST" and
zero if it indicates "Not using DST".

> As another note, I have looked more into the fsck vs. hwclock
> who's-first debate. There is a problem with running hwclock
> before /usr/lib/zoneinfo is mounted (not just before fsck'ing
> root). Hwclock expects the timezone database to be available
> when it runs (it uses the C-library mktime() which reads
> zoneinfo), so running it very early won't work by default.

> The solution is simple enough and can still be handled in
> userspace. Copy the relevant entry from the terminfo database
> to /etc/localtime, and set the TZ environment variable to point
> to it, or give all the timezone details in the variable itself
> (man tzset). Then call hwclock very early from your boot
> scripts (/ still mounted ro, and un-fscked).

> I have looked at the code from both hwclock and glibc2.1 and it
> seems either aproach above should work painlessly, although I
> have tested neither (I run my RTC in UTC ;) Again, Redhat nor
> Debian do this, but it would IMHO be the right thing(tm).

I have two systems that run the RTC in local time and one that runs it
in UTC, so can check both sides of this story. I haven't yet checked
the above patch though, and still have to do so.

Best wishes from Riley.

+----------------------------------------------------------------------+
| There is something frustrating about the quality and speed of Linux |
| development, ie., the quality is too high and the speed is too high, |
| in other words, I can implement this XXXX feature, but I bet someone |
| else has already done so and is just about to release their patch. |
+----------------------------------------------------------------------+
* ftp://ftp.MemAlpha.cx/pub/rhw/Linux
* http://www.MemAlpha.cx/kernel.versions.html

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/

\
 
 \ /
  Last update: 2005-03-22 13:51    [W:0.082 / U:0.444 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site