. removed readclock command and cmos driver.
. replaced by a readclock 'driver' that runs once, a re-imported version of the minix 2.0.4 readclock command. . this has also restored cmos writing. . readclock wrapper script calls service command to run /bin/readclock.drv once.
This commit is contained in:
parent
f65b3b8fbf
commit
f47aa04a30
12 changed files with 435 additions and 550 deletions
|
@ -20,7 +20,6 @@ ALL = \
|
||||||
partition \
|
partition \
|
||||||
playwave \
|
playwave \
|
||||||
postmort \
|
postmort \
|
||||||
readclock \
|
|
||||||
recwave \
|
recwave \
|
||||||
repartition \
|
repartition \
|
||||||
screendump \
|
screendump \
|
||||||
|
@ -76,10 +75,6 @@ postmort: postmort.c
|
||||||
$(CCLD) -o $@ $?
|
$(CCLD) -o $@ $?
|
||||||
install -S 4kw $@
|
install -S 4kw $@
|
||||||
|
|
||||||
readclock: readclock.c
|
|
||||||
$(CCLD) -o $@ $?
|
|
||||||
install -S 4kw $@
|
|
||||||
|
|
||||||
recwave: recwave.c
|
recwave: recwave.c
|
||||||
$(CCLD) -o $@ $?
|
$(CCLD) -o $@ $?
|
||||||
install -S 16kw $@
|
install -S 16kw $@
|
||||||
|
@ -111,13 +106,11 @@ install: \
|
||||||
/usr/bin/partition \
|
/usr/bin/partition \
|
||||||
/usr/bin/playwave \
|
/usr/bin/playwave \
|
||||||
/usr/bin/postmort \
|
/usr/bin/postmort \
|
||||||
/usr/bin/readclock \
|
|
||||||
/usr/bin/recwave \
|
/usr/bin/recwave \
|
||||||
/usr/bin/repartition \
|
/usr/bin/repartition \
|
||||||
/usr/bin/screendump \
|
/usr/bin/screendump \
|
||||||
/usr/bin/sdump \
|
/usr/bin/sdump \
|
||||||
/bin/loadkeys \
|
/bin/loadkeys \
|
||||||
/bin/readclock \
|
|
||||||
|
|
||||||
/usr/bin/atnormalize: atnormalize
|
/usr/bin/atnormalize: atnormalize
|
||||||
install -cs -o bin $? $@
|
install -cs -o bin $? $@
|
||||||
|
@ -158,9 +151,6 @@ install: \
|
||||||
/usr/bin/postmort: postmort
|
/usr/bin/postmort: postmort
|
||||||
install -cs -o bin $? $@
|
install -cs -o bin $? $@
|
||||||
|
|
||||||
/usr/bin/readclock: readclock
|
|
||||||
install -cs -o bin $? $@
|
|
||||||
|
|
||||||
/usr/bin/recwave: recwave
|
/usr/bin/recwave: recwave
|
||||||
install -cs -o bin $? $@
|
install -cs -o bin $? $@
|
||||||
|
|
||||||
|
@ -176,8 +166,5 @@ install: \
|
||||||
/bin/loadkeys: /usr/bin/loadkeys
|
/bin/loadkeys: /usr/bin/loadkeys
|
||||||
install -lcs $? $@
|
install -lcs $? $@
|
||||||
|
|
||||||
/bin/readclock: /usr/bin/readclock
|
|
||||||
install -lcs $? $@
|
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -rf $(ALL) a.out core
|
rm -rf $(ALL) a.out core
|
||||||
|
|
|
@ -1,226 +0,0 @@
|
||||||
/* setime - set the system time from the real time clock
|
|
||||||
Authors: T. Holm & E. Froese
|
|
||||||
Adapted by: Jorrit .N. Herder */
|
|
||||||
|
|
||||||
/************************************************************************/
|
|
||||||
/* Readclock was updated for security reasons: openeing /dev/mem no */
|
|
||||||
/* longer automatically grants I/O privileges to the calling process */
|
|
||||||
/* so that the CMOS' clock could not be read from this program. The */
|
|
||||||
/* new approach is to rely on the FS to do the CMOS I/O, via the new */
|
|
||||||
/* system call CMOSTIME (which only reads the current clock value and */
|
|
||||||
/* cannot update the CMOS clock). */
|
|
||||||
/* The original readclock.c is still available under backup.c. */
|
|
||||||
/************************************************************************/
|
|
||||||
/* */
|
|
||||||
/* readclock.c */
|
|
||||||
/* */
|
|
||||||
/* Read the clock value from the 64 byte CMOS RAM */
|
|
||||||
/* area, then set system time. */
|
|
||||||
/* */
|
|
||||||
/* If the machine ID byte is 0xFC or 0xF8, the device */
|
|
||||||
/* /dev/mem exists and can be opened for reading, */
|
|
||||||
/* and no errors in the CMOS RAM are reported by the */
|
|
||||||
/* RTC, then the time is read from the clock RAM */
|
|
||||||
/* area maintained by the RTC. */
|
|
||||||
/* */
|
|
||||||
/* The clock RAM values are decoded and fed to mktime */
|
|
||||||
/* to make a time_t value, then stime(2) is called. */
|
|
||||||
/* */
|
|
||||||
/* This fails if: */
|
|
||||||
/* */
|
|
||||||
/* If the machine ID does not match 0xFC or 0xF8 (no */
|
|
||||||
/* error message.) */
|
|
||||||
/* */
|
|
||||||
/* If the machine ID is 0xFC or 0xF8 and /dev/mem */
|
|
||||||
/* is missing, or cannot be accessed. */
|
|
||||||
/* */
|
|
||||||
/* If the RTC reports errors in the CMOS RAM. */
|
|
||||||
/* */
|
|
||||||
/************************************************************************/
|
|
||||||
/* origination 1987-Dec-29 efth */
|
|
||||||
/* robustness 1990-Oct-06 C. Sylvain */
|
|
||||||
/* incorp. B. Evans ideas 1991-Jul-06 C. Sylvain */
|
|
||||||
/* set time & calibrate 1992-Dec-17 Kees J. Bot */
|
|
||||||
/* clock timezone 1993-Oct-10 Kees J. Bot */
|
|
||||||
/* set CMOS clock 1994-Jun-12 Kees J. Bot */
|
|
||||||
/* removed set CMOS 2004-Sep-06 Jorrit N. Herder */
|
|
||||||
/************************************************************************/
|
|
||||||
|
|
||||||
#include <minix/callnr.h>
|
|
||||||
#include <minix/config.h>
|
|
||||||
#include <minix/type.h>
|
|
||||||
#include <minix/const.h>
|
|
||||||
#include <minix/com.h>
|
|
||||||
#include <minix/syslib.h>
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <sys/ioc_cmos.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <time.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <signal.h>
|
|
||||||
#include <minix/portio.h>
|
|
||||||
#include <ibm/cmos.h>
|
|
||||||
#include <sys/svrctl.h>
|
|
||||||
|
|
||||||
#define MAX_RETRIES 1
|
|
||||||
|
|
||||||
int nflag = 0; /* Tell what, but don't do it. */
|
|
||||||
int y2kflag = 0; /* Interpret 1980 as 2000 for clock with Y2K bug. */
|
|
||||||
|
|
||||||
char clocktz[128]; /* Timezone of the clock. */
|
|
||||||
|
|
||||||
#define MACH_ID_ADDR 0xFFFFE /* BIOS Machine ID at FFFF:000E */
|
|
||||||
|
|
||||||
#define PC_AT 0xFC /* Machine ID byte for PC/AT,
|
|
||||||
PC/XT286, and PS/2 Models 50, 60 */
|
|
||||||
#define PS_386 0xF8 /* Machine ID byte for PS/2 Model 80 */
|
|
||||||
|
|
||||||
/* Manufacturers usually use the ID value of the IBM model they emulate.
|
|
||||||
* However some manufacturers, notably HP and COMPAQ, have had different
|
|
||||||
* ideas in the past.
|
|
||||||
*
|
|
||||||
* Machine ID byte information source:
|
|
||||||
* _The Programmer's PC Sourcebook_ by Thom Hogan,
|
|
||||||
* published by Microsoft Press
|
|
||||||
*/
|
|
||||||
|
|
||||||
void errmsg(char *s);
|
|
||||||
int bcd_to_dec(int n);
|
|
||||||
int dec_to_bcd(int n);
|
|
||||||
void usage(void);
|
|
||||||
|
|
||||||
#define CMOS_DEV "/dev/cmos"
|
|
||||||
|
|
||||||
PUBLIC int main(int argc, char **argv)
|
|
||||||
{
|
|
||||||
int fd;
|
|
||||||
struct tm time1;
|
|
||||||
struct tm time2;
|
|
||||||
struct tm tmnow;
|
|
||||||
char date[64];
|
|
||||||
time_t now, rtc;
|
|
||||||
int i, s, mem;
|
|
||||||
unsigned char mach_id, cmos_state;
|
|
||||||
struct sysgetenv sysgetenv;
|
|
||||||
message m;
|
|
||||||
int request;
|
|
||||||
|
|
||||||
|
|
||||||
/* Process options. */
|
|
||||||
while (argc > 1) {
|
|
||||||
char *p = *++argv;
|
|
||||||
|
|
||||||
if (*p++ != '-') usage();
|
|
||||||
|
|
||||||
while (*p != 0) {
|
|
||||||
switch (*p++) {
|
|
||||||
case 'n': nflag = 1; break;
|
|
||||||
case '2': y2kflag = 1; break;
|
|
||||||
default: usage();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
argc--;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if DEAD_CODE
|
|
||||||
/* The hardware clock may run in a different time zone, likely GMT or
|
|
||||||
* winter time. Select that time zone.
|
|
||||||
*/
|
|
||||||
strcpy(clocktz, "TZ=");
|
|
||||||
sysgetenv.key = "TZ";
|
|
||||||
sysgetenv.keylen = 2+1;
|
|
||||||
sysgetenv.val = clocktz+3;
|
|
||||||
sysgetenv.vallen = sizeof(clocktz)-3;
|
|
||||||
if (svrctl(SYSGETENV, &sysgetenv) == 0) {
|
|
||||||
putenv(clocktz);
|
|
||||||
tzset();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Read the CMOS real time clock. */
|
|
||||||
for (i = 0; i < MAX_RETRIES; i++) {
|
|
||||||
|
|
||||||
/* sleep, unless first iteration */
|
|
||||||
if (i > 0) sleep(5);
|
|
||||||
|
|
||||||
/* Open the CMOS device to read the system time. */
|
|
||||||
if ((fd = open(CMOS_DEV, O_RDONLY)) < 0) {
|
|
||||||
perror(CMOS_DEV);
|
|
||||||
fprintf(stderr, "Couldn't open CMOS device.\n");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
request = (y2kflag) ? CIOCGETTIME : CIOCGETTIMEY2K;
|
|
||||||
if ((s=ioctl(fd, request, (void *) &time1)) < 0) {
|
|
||||||
perror("ioctl");
|
|
||||||
fprintf(stderr, "Couldn't do CMOS ioctl.\n");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
close(fd);
|
|
||||||
|
|
||||||
now = time(NULL);
|
|
||||||
|
|
||||||
time1.tm_isdst = -1; /* Do timezone calculations. */
|
|
||||||
time2 = time1;
|
|
||||||
|
|
||||||
rtc= mktime(&time1); /* Transform to a time_t. */
|
|
||||||
if (rtc != -1) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
fprintf(stderr,
|
|
||||||
"readclock: Invalid time read from CMOS RTC: %d-%02d-%02d %02d:%02d:%02d\n",
|
|
||||||
time2.tm_year+1900, time2.tm_mon+1, time2.tm_mday,
|
|
||||||
time2.tm_hour, time2.tm_min, time2.tm_sec);
|
|
||||||
}
|
|
||||||
if (i >= MAX_RETRIES) exit(1);
|
|
||||||
|
|
||||||
/* Now set system time. */
|
|
||||||
if (nflag) {
|
|
||||||
printf("stime(%lu)\n", (unsigned long) rtc);
|
|
||||||
} else {
|
|
||||||
if (stime(&rtc) < 0) {
|
|
||||||
errmsg( "Not allowed to set time." );
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
tmnow = *localtime(&rtc);
|
|
||||||
if (strftime(date, sizeof(date),
|
|
||||||
"%a %b %d %H:%M:%S %Z %Y", &tmnow) != 0) {
|
|
||||||
if (date[8] == '0') date[8]= ' ';
|
|
||||||
#if 0
|
|
||||||
printf("%s [CMOS read via FS, see command/ibm/readclock.c]\n", date);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void errmsg(char *s)
|
|
||||||
{
|
|
||||||
static char *prompt = "readclock: ";
|
|
||||||
|
|
||||||
fprintf(stderr, "%s%s\n", prompt, s);
|
|
||||||
prompt = "";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int bcd_to_dec(int n)
|
|
||||||
{
|
|
||||||
return ((n >> 4) & 0x0F) * 10 + (n & 0x0F);
|
|
||||||
}
|
|
||||||
|
|
||||||
int dec_to_bcd(int n)
|
|
||||||
{
|
|
||||||
return ((n / 10) << 4) | (n % 10);
|
|
||||||
}
|
|
||||||
|
|
||||||
void usage(void)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "Usage: settime [-n2]\n");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
|
@ -19,7 +19,7 @@ case $#:$1 in
|
||||||
ttypa ttypb ttypc ttypd ttype ttypf \
|
ttypa ttypb ttypc ttypd ttype ttypf \
|
||||||
ttyq0 ttyq1 ttyq2 ttyq3 ttyq4 ttyq5 ttyq6 ttyq7 ttyq8 ttyq9 \
|
ttyq0 ttyq1 ttyq2 ttyq3 ttyq4 ttyq5 ttyq6 ttyq7 ttyq8 ttyq9 \
|
||||||
ttyqa ttyqb ttyqc ttyqd ttyqe ttyqf \
|
ttyqa ttyqb ttyqc ttyqd ttyqe ttyqf \
|
||||||
eth klog random cmos rescue
|
eth klog random rescue
|
||||||
;;
|
;;
|
||||||
0:|1:-\?)
|
0:|1:-\?)
|
||||||
cat >&2 <<EOF
|
cat >&2 <<EOF
|
||||||
|
@ -41,7 +41,6 @@ Where key is one of the following:
|
||||||
audio mixer # Make audio devices
|
audio mixer # Make audio devices
|
||||||
klog # Make /dev/klog
|
klog # Make /dev/klog
|
||||||
random # Make /dev/random, /dev/urandom
|
random # Make /dev/random, /dev/urandom
|
||||||
cmos # Make /dev/cmos
|
|
||||||
kbd # Make /dev/kbd
|
kbd # Make /dev/kbd
|
||||||
kbdaux # Make /dev/kbdaux
|
kbdaux # Make /dev/kbdaux
|
||||||
rescue # Make /dev/rescue
|
rescue # Make /dev/rescue
|
||||||
|
@ -243,11 +242,6 @@ do
|
||||||
$e mknod urandom c 16 0; $e chmod 644 urandom
|
$e mknod urandom c 16 0; $e chmod 644 urandom
|
||||||
$e chgrp operator random urandom
|
$e chgrp operator random urandom
|
||||||
;;
|
;;
|
||||||
cmos)
|
|
||||||
# cmos device (set/get system time).
|
|
||||||
$e mknod cmos c 17 0
|
|
||||||
$e chmod 600 cmos
|
|
||||||
;;
|
|
||||||
rescue)
|
rescue)
|
||||||
# rescue device
|
# rescue device
|
||||||
$e mknod rescue b 9 0
|
$e mknod rescue b 9 0
|
||||||
|
|
|
@ -38,6 +38,7 @@ usr: \
|
||||||
/usr/bin/makewhatis \
|
/usr/bin/makewhatis \
|
||||||
/usr/bin/mkdep \
|
/usr/bin/mkdep \
|
||||||
/usr/bin/mkdist \
|
/usr/bin/mkdist \
|
||||||
|
/bin/readclock \
|
||||||
/bin/setup \
|
/bin/setup \
|
||||||
/usr/bin/binsizes \
|
/usr/bin/binsizes \
|
||||||
/usr/bin/rotate \
|
/usr/bin/rotate \
|
||||||
|
@ -133,6 +134,9 @@ clean:
|
||||||
/usr/bin/rotate: rotate.sh
|
/usr/bin/rotate: rotate.sh
|
||||||
install -m 755 -c -o bin $? $@
|
install -m 755 -c -o bin $? $@
|
||||||
|
|
||||||
|
/bin/readclock: readclock.sh
|
||||||
|
install -m 755 -c -o bin $? $@
|
||||||
|
|
||||||
/bin/setup: setup.sh
|
/bin/setup: setup.sh
|
||||||
install -m 755 -c -o bin $? $@
|
install -m 755 -c -o bin $? $@
|
||||||
|
|
||||||
|
|
5
commands/scripts/readclock.sh
Normal file
5
commands/scripts/readclock.sh
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
#!/bin/sh
|
||||||
|
if [ $# -gt 0 ]
|
||||||
|
then ARGS="-args $@"
|
||||||
|
fi
|
||||||
|
/bin/service up /sbin/readclock.drv -config /etc/drivers.conf -script /etc/rs.single $ARGS
|
|
@ -25,8 +25,8 @@ all install depend clean:
|
||||||
cd ./dpeth && $(MAKE) $@
|
cd ./dpeth && $(MAKE) $@
|
||||||
cd ./log && $(MAKE) $@
|
cd ./log && $(MAKE) $@
|
||||||
cd ./bios_wini && $(MAKE) $@
|
cd ./bios_wini && $(MAKE) $@
|
||||||
cd ./cmos && $(MAKE) $@
|
|
||||||
cd ./random && $(MAKE) $@
|
cd ./random && $(MAKE) $@
|
||||||
|
cd ./readclock && $(MAKE) $@
|
||||||
cd ./dp8390 && $(MAKE) $@
|
cd ./dp8390 && $(MAKE) $@
|
||||||
cd ./sb16 && $(MAKE) $@
|
cd ./sb16 && $(MAKE) $@
|
||||||
cd ./lance && $(MAKE) $@
|
cd ./lance && $(MAKE) $@
|
||||||
|
|
|
@ -1,283 +0,0 @@
|
||||||
/* This file contains a device driver that can access the CMOS chip to
|
|
||||||
* get or set the system time. It drives the special file:
|
|
||||||
*
|
|
||||||
* /dev/cmos - CMOS chip
|
|
||||||
*
|
|
||||||
* Changes:
|
|
||||||
* Aug 04, 2005 Created. Read CMOS time. (Jorrit N. Herder)
|
|
||||||
*
|
|
||||||
* Manufacturers usually use the ID value of the IBM model they emulate.
|
|
||||||
* However some manufacturers, notably HP and COMPAQ, have had different
|
|
||||||
* ideas in the past.
|
|
||||||
*
|
|
||||||
* Machine ID byte information source:
|
|
||||||
* _The Programmer's PC Sourcebook_ by Thom Hogan,
|
|
||||||
* published by Microsoft Press
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "../drivers.h"
|
|
||||||
#include <sys/ioc_cmos.h>
|
|
||||||
#include <time.h>
|
|
||||||
#include <ibm/cmos.h>
|
|
||||||
#include <ibm/bios.h>
|
|
||||||
#include <minix/safecopies.h>
|
|
||||||
|
|
||||||
extern int errno; /* error number for PM calls */
|
|
||||||
|
|
||||||
FORWARD _PROTOTYPE( int gettime, (int who, int y2kflag, vir_bytes dst_time, int safe));
|
|
||||||
FORWARD _PROTOTYPE( void reply, (int reply, int replyee, int proc, cp_grant_id_t, int s));
|
|
||||||
|
|
||||||
FORWARD _PROTOTYPE( int read_register, (int register_address));
|
|
||||||
FORWARD _PROTOTYPE( int get_cmostime, (struct tm *tmp, int y2kflag));
|
|
||||||
FORWARD _PROTOTYPE( int dec_to_bcd, (int dec));
|
|
||||||
FORWARD _PROTOTYPE( int bcd_to_dec, (int bcd));
|
|
||||||
|
|
||||||
/*===========================================================================*
|
|
||||||
* main *
|
|
||||||
*===========================================================================*/
|
|
||||||
PUBLIC void main(void)
|
|
||||||
{
|
|
||||||
message m;
|
|
||||||
int y2kflag;
|
|
||||||
int result;
|
|
||||||
int suspended = NONE;
|
|
||||||
cp_grant_id_t susp_grant = GRANT_INVALID;
|
|
||||||
int s;
|
|
||||||
|
|
||||||
while(TRUE) {
|
|
||||||
int safe = 0;
|
|
||||||
|
|
||||||
/* Get work. */
|
|
||||||
if (OK != (s=receive(ANY, &m)))
|
|
||||||
panic("CMOS", "attempt to receive work failed", s);
|
|
||||||
|
|
||||||
/* Handle request. */
|
|
||||||
switch(m.m_type) {
|
|
||||||
|
|
||||||
case DEV_OPEN:
|
|
||||||
case DEV_CLOSE:
|
|
||||||
case CANCEL:
|
|
||||||
reply(TASK_REPLY, m.m_source, m.IO_ENDPT, GRANT_INVALID, OK);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DEV_PING:
|
|
||||||
notify(m.m_source);
|
|
||||||
break;
|
|
||||||
case DEV_IOCTL_S:
|
|
||||||
safe=1;
|
|
||||||
/* Fall through. */
|
|
||||||
case DEV_IOCTL:
|
|
||||||
|
|
||||||
/* Probably best to SUSPEND the caller, CMOS I/O has nasty timeouts.
|
|
||||||
* This way we don't block the rest of the system. First check if
|
|
||||||
* another process is already suspended. We cannot handle multiple
|
|
||||||
* requests at a time.
|
|
||||||
*/
|
|
||||||
if (suspended != NONE) {
|
|
||||||
reply(TASK_REPLY, m.m_source, m.IO_ENDPT, GRANT_INVALID, EBUSY);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
suspended = m.IO_ENDPT;
|
|
||||||
susp_grant = (cp_grant_id_t) m.IO_GRANT;
|
|
||||||
reply(TASK_REPLY, m.m_source, m.IO_ENDPT, susp_grant, SUSPEND);
|
|
||||||
|
|
||||||
switch(m.REQUEST) {
|
|
||||||
case CIOCGETTIME: /* get CMOS time */
|
|
||||||
case CIOCGETTIMEY2K:
|
|
||||||
y2kflag = (m.REQUEST == CIOCGETTIME) ? 0 : 1;
|
|
||||||
result = gettime(m.IO_ENDPT, y2kflag, (vir_bytes) m.ADDRESS, safe);
|
|
||||||
break;
|
|
||||||
case CIOCSETTIME:
|
|
||||||
case CIOCSETTIMEY2K:
|
|
||||||
default: /* unsupported ioctl */
|
|
||||||
result = ENOSYS;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Request completed. Tell the caller to check our status. */
|
|
||||||
notify(m.m_source);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DEV_STATUS:
|
|
||||||
|
|
||||||
/* The FS calls back to get our status. Revive the suspended
|
|
||||||
* processes and return the status of reading the CMOS.
|
|
||||||
*/
|
|
||||||
if (suspended == NONE)
|
|
||||||
reply(DEV_NO_STATUS, m.m_source, NONE, GRANT_INVALID, OK);
|
|
||||||
else
|
|
||||||
reply(DEV_REVIVE, m.m_source, suspended, susp_grant, result);
|
|
||||||
suspended = NONE;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SYN_ALARM: /* shouldn't happen */
|
|
||||||
case SYS_SIG: /* ignore system events */
|
|
||||||
continue;
|
|
||||||
|
|
||||||
default:
|
|
||||||
reply(TASK_REPLY, m.m_source, m.IO_ENDPT, GRANT_INVALID, EINVAL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*===========================================================================*
|
|
||||||
* reply *
|
|
||||||
*===========================================================================*/
|
|
||||||
PRIVATE void reply(int code, int replyee, int process, cp_grant_id_t grantid, int status)
|
|
||||||
{
|
|
||||||
message m;
|
|
||||||
int s;
|
|
||||||
|
|
||||||
m.m_type = code; /* TASK_REPLY or REVIVE */
|
|
||||||
m.REP_STATUS = status; /* result of device operation */
|
|
||||||
m.REP_ENDPT = process; /* which user made the request */
|
|
||||||
m.REP_IO_GRANT = grantid; /* I/O grant on which to unSUSPEND */
|
|
||||||
if (OK != (s=send(replyee, &m)))
|
|
||||||
panic("CMOS", "sending reply failed", s);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*===========================================================================*
|
|
||||||
* gettime *
|
|
||||||
*===========================================================================*/
|
|
||||||
PRIVATE int gettime(int who, int y2kflag, vir_bytes dst_time, int safe)
|
|
||||||
{
|
|
||||||
unsigned char mach_id, cmos_state;
|
|
||||||
struct tm time1;
|
|
||||||
int i, s;
|
|
||||||
|
|
||||||
/* First obtain the machine ID to see if we can read the CMOS clock. Only
|
|
||||||
* for PS_386 and PC_AT this is possible. Otherwise, return an error.
|
|
||||||
*/
|
|
||||||
s = sys_readbios( MACHINE_ID_ADDR, &mach_id, MACHINE_ID_SIZE);
|
|
||||||
if (s != 0) {
|
|
||||||
printf("gettime: sys_readbios failed: %d\n", s);
|
|
||||||
return EINVAL;
|
|
||||||
}
|
|
||||||
if (mach_id != PS_386_MACHINE && mach_id != PC_AT_MACHINE) {
|
|
||||||
printf("gettime: machine ID unknown. ID byte = %02x.\n", mach_id);
|
|
||||||
return(EFAULT);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Now check the CMOS' state to see if we can read a proper time from it.
|
|
||||||
* If the state is crappy, return an error.
|
|
||||||
*/
|
|
||||||
cmos_state = read_register(CMOS_STATUS);
|
|
||||||
if (cmos_state & (CS_LOST_POWER | CS_BAD_CHKSUM | CS_BAD_TIME)) {
|
|
||||||
printf( "IS: CMOS RAM error(s) found. State = 0x%02x\n", cmos_state );
|
|
||||||
if (cmos_state & CS_LOST_POWER)
|
|
||||||
printf("IS: RTC lost power. Reset CMOS RAM with SETUP." );
|
|
||||||
if (cmos_state & CS_BAD_CHKSUM)
|
|
||||||
printf("IS: CMOS RAM checksum is bad. Run SETUP." );
|
|
||||||
if (cmos_state & CS_BAD_TIME)
|
|
||||||
printf("IS: Time invalid in CMOS RAM. Reset clock." );
|
|
||||||
return(EFAULT);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Everything seems to be OK. Read the CMOS real time clock and copy the
|
|
||||||
* result back to the caller.
|
|
||||||
*/
|
|
||||||
if (get_cmostime(&time1, y2kflag) != 0)
|
|
||||||
return(EFAULT);
|
|
||||||
|
|
||||||
/* Copy result back, safely or not. */
|
|
||||||
if(safe) {
|
|
||||||
sys_safecopyto(who, dst_time, 0, (vir_bytes) &time1,
|
|
||||||
sizeof(struct tm), D);
|
|
||||||
} else {
|
|
||||||
sys_datacopy(SELF, (vir_bytes) &time1,
|
|
||||||
who, dst_time, sizeof(struct tm));
|
|
||||||
}
|
|
||||||
|
|
||||||
return(OK);
|
|
||||||
}
|
|
||||||
|
|
||||||
PRIVATE int get_cmostime(struct tm *t, int y2kflag)
|
|
||||||
{
|
|
||||||
/* Update the structure pointed to by time with the current time as read
|
|
||||||
* from CMOS RAM of the RTC. If necessary, the time is converted into a
|
|
||||||
* binary format before being stored in the structure.
|
|
||||||
*/
|
|
||||||
int osec, n;
|
|
||||||
unsigned long i;
|
|
||||||
clock_t t0,t1;
|
|
||||||
|
|
||||||
/* Start a timer to keep us from getting stuck on a dead clock. */
|
|
||||||
getuptime(&t0);
|
|
||||||
do {
|
|
||||||
osec = -1;
|
|
||||||
n = 0;
|
|
||||||
do {
|
|
||||||
getuptime(&t1);
|
|
||||||
if (t1-t0 > 5*HZ) {
|
|
||||||
printf("readclock: CMOS clock appears dead\n");
|
|
||||||
return(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Clock update in progress? */
|
|
||||||
if (read_register(RTC_REG_A) & RTC_A_UIP) continue;
|
|
||||||
|
|
||||||
t->tm_sec = read_register(RTC_SEC);
|
|
||||||
if (t->tm_sec != osec) {
|
|
||||||
/* Seconds changed. First from -1, then because the
|
|
||||||
* clock ticked, which is what we're waiting for to
|
|
||||||
* get a precise reading.
|
|
||||||
*/
|
|
||||||
osec = t->tm_sec;
|
|
||||||
n++;
|
|
||||||
}
|
|
||||||
} while (n < 2);
|
|
||||||
|
|
||||||
/* Read the other registers. */
|
|
||||||
t->tm_min = read_register(RTC_MIN);
|
|
||||||
t->tm_hour = read_register(RTC_HOUR);
|
|
||||||
t->tm_mday = read_register(RTC_MDAY);
|
|
||||||
t->tm_mon = read_register(RTC_MONTH);
|
|
||||||
t->tm_year = read_register(RTC_YEAR);
|
|
||||||
|
|
||||||
/* Time stable? */
|
|
||||||
} while (read_register(RTC_SEC) != t->tm_sec
|
|
||||||
|| read_register(RTC_MIN) != t->tm_min
|
|
||||||
|| read_register(RTC_HOUR) != t->tm_hour
|
|
||||||
|| read_register(RTC_MDAY) != t->tm_mday
|
|
||||||
|| read_register(RTC_MONTH) != t->tm_mon
|
|
||||||
|| read_register(RTC_YEAR) != t->tm_year);
|
|
||||||
|
|
||||||
if ((read_register(RTC_REG_B) & RTC_B_DM_BCD) == 0) {
|
|
||||||
/* Convert BCD to binary (default RTC mode). */
|
|
||||||
t->tm_year = bcd_to_dec(t->tm_year);
|
|
||||||
t->tm_mon = bcd_to_dec(t->tm_mon);
|
|
||||||
t->tm_mday = bcd_to_dec(t->tm_mday);
|
|
||||||
t->tm_hour = bcd_to_dec(t->tm_hour);
|
|
||||||
t->tm_min = bcd_to_dec(t->tm_min);
|
|
||||||
t->tm_sec = bcd_to_dec(t->tm_sec);
|
|
||||||
}
|
|
||||||
t->tm_mon--; /* Counts from 0. */
|
|
||||||
|
|
||||||
/* Correct the year, good until 2080. */
|
|
||||||
if (t->tm_year < 80) t->tm_year += 100;
|
|
||||||
|
|
||||||
if (y2kflag) {
|
|
||||||
/* Clock with Y2K bug, interpret 1980 as 2000, good until 2020. */
|
|
||||||
if (t->tm_year < 100) t->tm_year += 20;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
PRIVATE int read_register(int reg_addr)
|
|
||||||
{
|
|
||||||
/* Read a single CMOS register value. */
|
|
||||||
unsigned long r;
|
|
||||||
sys_outb(RTC_INDEX, reg_addr);
|
|
||||||
sys_inb(RTC_IO, &r);
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
PRIVATE int bcd_to_dec(int n)
|
|
||||||
{
|
|
||||||
return ((n >> 4) & 0x0F) * 10 + (n & 0x0F);
|
|
||||||
}
|
|
||||||
|
|
||||||
PRIVATE int dec_to_bcd(int n)
|
|
||||||
{
|
|
||||||
return ((n / 10) << 4) | (n % 10);
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,22 +1,14 @@
|
||||||
# Makefile for the CMOS driver
|
# Makefile for readclock 'driver'
|
||||||
DRIVER = cmos
|
DRIVER = readclock.drv
|
||||||
|
|
||||||
# directories
|
|
||||||
u = /usr
|
|
||||||
i = $u/include
|
|
||||||
s = $i/sys
|
|
||||||
m = $i/minix
|
|
||||||
b = $i/ibm
|
|
||||||
d = ..
|
|
||||||
|
|
||||||
# programs, flags, etc.
|
# programs, flags, etc.
|
||||||
MAKE = exec make
|
MAKE = exec make
|
||||||
CC = exec cc
|
CC = exec cc
|
||||||
CFLAGS = -I$i $(CPROFILE)
|
CFLAGS=-D_MINIX=1 -D_POSIX_SOURCE=1 -D_SYSTEM=1
|
||||||
LDFLAGS = -i -L../libdriver
|
LDFLAGS = -i
|
||||||
LIBS = -lsysutil -lsys -ldriver
|
LIBS = -lsysutil -lsys
|
||||||
|
|
||||||
OBJ = cmos.o
|
OBJ = readclock.o
|
||||||
|
|
||||||
# build local binary
|
# build local binary
|
||||||
all build: $(DRIVER)
|
all build: $(DRIVER)
|
||||||
|
@ -33,9 +25,8 @@ install: /sbin/$(DRIVER)
|
||||||
clean:
|
clean:
|
||||||
rm -f $(DRIVER) *.o *.bak
|
rm -f $(DRIVER) *.o *.bak
|
||||||
|
|
||||||
|
|
||||||
depend:
|
depend:
|
||||||
/usr/bin/mkdep "$(CC) -E $(CPPFLAGS)" *.c ../libdriver/*.c > .depend
|
/usr/bin/mkdep "$(CC) -E $(CPPFLAGS)" *.c > .depend
|
||||||
|
|
||||||
# Include generated dependencies.
|
# Include generated dependencies.
|
||||||
include .depend
|
include .depend
|
412
drivers/readclock/readclock.c
Normal file
412
drivers/readclock/readclock.c
Normal file
|
@ -0,0 +1,412 @@
|
||||||
|
/* readclock - read the real time clock Authors: T. Holm & E. Froese
|
||||||
|
*
|
||||||
|
* Changed to be user-space driver.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/************************************************************************/
|
||||||
|
/* */
|
||||||
|
/* readclock.c */
|
||||||
|
/* */
|
||||||
|
/* Read the clock value from the 64 byte CMOS RAM */
|
||||||
|
/* area, then set system time. */
|
||||||
|
/* */
|
||||||
|
/* If the machine ID byte is 0xFC or 0xF8, the device */
|
||||||
|
/* /dev/mem exists and can be opened for reading, */
|
||||||
|
/* and no errors in the CMOS RAM are reported by the */
|
||||||
|
/* RTC, then the time is read from the clock RAM */
|
||||||
|
/* area maintained by the RTC. */
|
||||||
|
/* */
|
||||||
|
/* The clock RAM values are decoded and fed to mktime */
|
||||||
|
/* to make a time_t value, then stime(2) is called. */
|
||||||
|
/* */
|
||||||
|
/* This fails if: */
|
||||||
|
/* */
|
||||||
|
/* If the machine ID does not match 0xFC or 0xF8 (no */
|
||||||
|
/* error message.) */
|
||||||
|
/* */
|
||||||
|
/* If the machine ID is 0xFC or 0xF8 and /dev/mem */
|
||||||
|
/* is missing, or cannot be accessed. */
|
||||||
|
/* */
|
||||||
|
/* If the RTC reports errors in the CMOS RAM. */
|
||||||
|
/* */
|
||||||
|
/************************************************************************/
|
||||||
|
/* origination 1987-Dec-29 efth */
|
||||||
|
/* robustness 1990-Oct-06 C. Sylvain */
|
||||||
|
/* incorp. B. Evans ideas 1991-Jul-06 C. Sylvain */
|
||||||
|
/* set time & calibrate 1992-Dec-17 Kees J. Bot */
|
||||||
|
/* clock timezone 1993-Oct-10 Kees J. Bot */
|
||||||
|
/* set CMOS clock 1994-Jun-12 Kees J. Bot */
|
||||||
|
/************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <minix/type.h>
|
||||||
|
#include <minix/syslib.h>
|
||||||
|
#include <minix/com.h>
|
||||||
|
#include <minix/portio.h>
|
||||||
|
#include <ibm/cmos.h>
|
||||||
|
#include <sys/svrctl.h>
|
||||||
|
|
||||||
|
int nflag = 0; /* Tell what, but don't do it. */
|
||||||
|
int wflag = 0; /* Set the CMOS clock. */
|
||||||
|
int Wflag = 0; /* Also set the CMOS clock register bits. */
|
||||||
|
int y2kflag = 0; /* Interpret 1980 as 2000 for clock with Y2K bug. */
|
||||||
|
|
||||||
|
char clocktz[128]; /* Timezone of the clock. */
|
||||||
|
|
||||||
|
#define MACH_ID_ADDR 0xFFFFE /* BIOS Machine ID at FFFF:000E */
|
||||||
|
|
||||||
|
#define PC_AT 0xFC /* Machine ID byte for PC/AT,
|
||||||
|
PC/XT286, and PS/2 Models 50, 60 */
|
||||||
|
#define PS_386 0xF8 /* Machine ID byte for PS/2 Model 80 */
|
||||||
|
|
||||||
|
/* Manufacturers usually use the ID value of the IBM model they emulate.
|
||||||
|
* However some manufacturers, notably HP and COMPAQ, have had different
|
||||||
|
* ideas in the past.
|
||||||
|
*
|
||||||
|
* Machine ID byte information source:
|
||||||
|
* _The Programmer's PC Sourcebook_ by Thom Hogan,
|
||||||
|
* published by Microsoft Press
|
||||||
|
*/
|
||||||
|
|
||||||
|
void errmsg(char *s);
|
||||||
|
void get_time(struct tm *t);
|
||||||
|
int read_register(int reg_addr);
|
||||||
|
void set_time(struct tm *t);
|
||||||
|
void write_register(int reg_addr, int value);
|
||||||
|
int bcd_to_dec(int n);
|
||||||
|
int dec_to_bcd(int n);
|
||||||
|
void usage(void);
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
struct tm time1;
|
||||||
|
struct tm time2;
|
||||||
|
struct tm tmnow;
|
||||||
|
char date[64];
|
||||||
|
time_t now, rtc;
|
||||||
|
int i, s;
|
||||||
|
unsigned char mach_id, cmos_state;
|
||||||
|
struct sysgetenv sysgetenv;
|
||||||
|
|
||||||
|
if((s=sys_readbios(MACH_ID_ADDR, &mach_id, sizeof(mach_id))) != OK) {
|
||||||
|
printf("readclock: sys_readbios failed: %d.\n", s);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mach_id != PS_386 && mach_id != PC_AT) {
|
||||||
|
errmsg("Machine ID unknown." );
|
||||||
|
printf("Machine ID byte = %02x\n", mach_id );
|
||||||
|
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
cmos_state = read_register(CMOS_STATUS);
|
||||||
|
|
||||||
|
if (cmos_state & (CS_LOST_POWER | CS_BAD_CHKSUM | CS_BAD_TIME)) {
|
||||||
|
errmsg( "CMOS RAM error(s) found..." );
|
||||||
|
printf("CMOS state = 0x%02x\n", cmos_state );
|
||||||
|
|
||||||
|
if (cmos_state & CS_LOST_POWER)
|
||||||
|
errmsg( "RTC lost power. Reset CMOS RAM with SETUP." );
|
||||||
|
if (cmos_state & CS_BAD_CHKSUM)
|
||||||
|
errmsg( "CMOS RAM checksum is bad. Run SETUP." );
|
||||||
|
if (cmos_state & CS_BAD_TIME)
|
||||||
|
errmsg( "Time invalid in CMOS RAM. Reset clock." );
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Process options. */
|
||||||
|
while (argc > 1) {
|
||||||
|
char *p = *++argv;
|
||||||
|
|
||||||
|
if (*p++ != '-') usage();
|
||||||
|
|
||||||
|
while (*p != 0) {
|
||||||
|
switch (*p++) {
|
||||||
|
case 'n': nflag = 1; break;
|
||||||
|
case 'w': wflag = 1; break;
|
||||||
|
case 'W': Wflag = 1; break;
|
||||||
|
case '2': y2kflag = 1; break;
|
||||||
|
default: usage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
argc--;
|
||||||
|
}
|
||||||
|
if (Wflag) wflag = 1; /* -W implies -w */
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
/* The hardware clock may run in a different time zone, likely GMT or
|
||||||
|
* winter time. Select that time zone.
|
||||||
|
*/
|
||||||
|
strcpy(clocktz, "TZ=");
|
||||||
|
sysgetenv.key = "TZ";
|
||||||
|
sysgetenv.keylen = 2+1;
|
||||||
|
sysgetenv.val = clocktz+3;
|
||||||
|
sysgetenv.vallen = sizeof(clocktz)-3;
|
||||||
|
if (svrctl(SYSGETENV, &sysgetenv) == 0) {
|
||||||
|
putenv(clocktz);
|
||||||
|
tzset();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Read the CMOS real time clock. */
|
||||||
|
for (i = 0; i < 10; i++) {
|
||||||
|
get_time(&time1);
|
||||||
|
now = time(NULL);
|
||||||
|
|
||||||
|
time1.tm_isdst = -1; /* Do timezone calculations. */
|
||||||
|
time2 = time1;
|
||||||
|
|
||||||
|
rtc= mktime(&time1); /* Transform to a time_t. */
|
||||||
|
if (rtc != -1) break;
|
||||||
|
|
||||||
|
printf(
|
||||||
|
"readclock: Invalid time read from CMOS RTC: %d-%02d-%02d %02d:%02d:%02d\n",
|
||||||
|
time2.tm_year+1900, time2.tm_mon+1, time2.tm_mday,
|
||||||
|
time2.tm_hour, time2.tm_min, time2.tm_sec);
|
||||||
|
sleep(5);
|
||||||
|
}
|
||||||
|
if (i == 10) exit(1);
|
||||||
|
|
||||||
|
if (!wflag) {
|
||||||
|
/* Set system time. */
|
||||||
|
if (nflag) {
|
||||||
|
printf("stime(%lu)\n", (unsigned long) rtc);
|
||||||
|
} else {
|
||||||
|
if (stime(&rtc) < 0) {
|
||||||
|
errmsg( "Not allowed to set time." );
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tmnow = *localtime(&rtc);
|
||||||
|
if (strftime(date, sizeof(date),
|
||||||
|
"%a %b %d %H:%M:%S %Z %Y", &tmnow) != 0) {
|
||||||
|
if (date[8] == '0') date[8]= ' ';
|
||||||
|
printf("%s\n", date);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* Set the CMOS clock to the system time. */
|
||||||
|
tmnow = *localtime(&now);
|
||||||
|
if (nflag) {
|
||||||
|
printf("%04d-%02d-%02d %02d:%02d:%02d\n",
|
||||||
|
tmnow.tm_year + 1900,
|
||||||
|
tmnow.tm_mon + 1,
|
||||||
|
tmnow.tm_mday,
|
||||||
|
tmnow.tm_hour,
|
||||||
|
tmnow.tm_min,
|
||||||
|
tmnow.tm_sec);
|
||||||
|
} else {
|
||||||
|
set_time(&tmnow);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void errmsg(char *s)
|
||||||
|
{
|
||||||
|
static char *prompt = "readclock: ";
|
||||||
|
|
||||||
|
printf("%s%s\n", prompt, s);
|
||||||
|
prompt = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************/
|
||||||
|
/* */
|
||||||
|
/* get_time( time ) */
|
||||||
|
/* */
|
||||||
|
/* Update the structure pointed to by time with the current time */
|
||||||
|
/* as read from CMOS RAM of the RTC. */
|
||||||
|
/* If necessary, the time is converted into a binary format before */
|
||||||
|
/* being stored in the structure. */
|
||||||
|
/* */
|
||||||
|
/***********************************************************************/
|
||||||
|
|
||||||
|
int dead;
|
||||||
|
void timeout(int sig) { dead= 1; }
|
||||||
|
|
||||||
|
void get_time(struct tm *t)
|
||||||
|
{
|
||||||
|
int osec, n;
|
||||||
|
unsigned long i;
|
||||||
|
struct sigaction sa;
|
||||||
|
|
||||||
|
/* Start a timer to keep us from getting stuck on a dead clock. */
|
||||||
|
sigemptyset(&sa.sa_mask);
|
||||||
|
sa.sa_flags = 0;
|
||||||
|
sa.sa_handler = timeout;
|
||||||
|
sigaction(SIGALRM, &sa, NULL);
|
||||||
|
dead = 0;
|
||||||
|
alarm(5);
|
||||||
|
|
||||||
|
do {
|
||||||
|
osec = -1;
|
||||||
|
n = 0;
|
||||||
|
do {
|
||||||
|
if (dead) {
|
||||||
|
printf("readclock: CMOS clock appears dead\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Clock update in progress? */
|
||||||
|
if (read_register(RTC_REG_A) & RTC_A_UIP) continue;
|
||||||
|
|
||||||
|
t->tm_sec = read_register(RTC_SEC);
|
||||||
|
if (t->tm_sec != osec) {
|
||||||
|
/* Seconds changed. First from -1, then because the
|
||||||
|
* clock ticked, which is what we're waiting for to
|
||||||
|
* get a precise reading.
|
||||||
|
*/
|
||||||
|
osec = t->tm_sec;
|
||||||
|
n++;
|
||||||
|
}
|
||||||
|
} while (n < 2);
|
||||||
|
|
||||||
|
/* Read the other registers. */
|
||||||
|
t->tm_min = read_register(RTC_MIN);
|
||||||
|
t->tm_hour = read_register(RTC_HOUR);
|
||||||
|
t->tm_mday = read_register(RTC_MDAY);
|
||||||
|
t->tm_mon = read_register(RTC_MONTH);
|
||||||
|
t->tm_year = read_register(RTC_YEAR);
|
||||||
|
|
||||||
|
/* Time stable? */
|
||||||
|
} while (read_register(RTC_SEC) != t->tm_sec
|
||||||
|
|| read_register(RTC_MIN) != t->tm_min
|
||||||
|
|| read_register(RTC_HOUR) != t->tm_hour
|
||||||
|
|| read_register(RTC_MDAY) != t->tm_mday
|
||||||
|
|| read_register(RTC_MONTH) != t->tm_mon
|
||||||
|
|| read_register(RTC_YEAR) != t->tm_year);
|
||||||
|
|
||||||
|
if ((read_register(RTC_REG_B) & RTC_B_DM_BCD) == 0) {
|
||||||
|
/* Convert BCD to binary (default RTC mode). */
|
||||||
|
t->tm_year = bcd_to_dec(t->tm_year);
|
||||||
|
t->tm_mon = bcd_to_dec(t->tm_mon);
|
||||||
|
t->tm_mday = bcd_to_dec(t->tm_mday);
|
||||||
|
t->tm_hour = bcd_to_dec(t->tm_hour);
|
||||||
|
t->tm_min = bcd_to_dec(t->tm_min);
|
||||||
|
t->tm_sec = bcd_to_dec(t->tm_sec);
|
||||||
|
}
|
||||||
|
t->tm_mon--; /* Counts from 0. */
|
||||||
|
|
||||||
|
/* Correct the year, good until 2080. */
|
||||||
|
if (t->tm_year < 80) t->tm_year += 100;
|
||||||
|
|
||||||
|
if (y2kflag) {
|
||||||
|
/* Clock with Y2K bug, interpret 1980 as 2000, good until 2020. */
|
||||||
|
if (t->tm_year < 100) t->tm_year += 20;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int read_register(int reg_addr)
|
||||||
|
{
|
||||||
|
u32_t r;
|
||||||
|
|
||||||
|
if(sys_outb(RTC_INDEX, reg_addr) != OK) {
|
||||||
|
printf("cmos: outb failed of %x\n", RTC_INDEX);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
if(sys_inb(RTC_IO, &r) != OK) {
|
||||||
|
printf("cmos: inb failed of %x (index %x) failed\n", RTC_IO, reg_addr);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************/
|
||||||
|
/* */
|
||||||
|
/* set_time( time ) */
|
||||||
|
/* */
|
||||||
|
/* Set the CMOS RTC to the time found in the structure. */
|
||||||
|
/* */
|
||||||
|
/***********************************************************************/
|
||||||
|
|
||||||
|
void set_time(struct tm *t)
|
||||||
|
{
|
||||||
|
int regA, regB;
|
||||||
|
|
||||||
|
if (Wflag) {
|
||||||
|
/* Set A and B registers to their proper values according to the AT
|
||||||
|
* reference manual. (For if it gets messed up, but the BIOS doesn't
|
||||||
|
* repair it.)
|
||||||
|
*/
|
||||||
|
write_register(RTC_REG_A, RTC_A_DV_OK | RTC_A_RS_DEF);
|
||||||
|
write_register(RTC_REG_B, RTC_B_24);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Inhibit updates. */
|
||||||
|
regB= read_register(RTC_REG_B);
|
||||||
|
write_register(RTC_REG_B, regB | RTC_B_SET);
|
||||||
|
|
||||||
|
t->tm_mon++; /* Counts from 1. */
|
||||||
|
|
||||||
|
if (y2kflag) {
|
||||||
|
/* Set the clock back 20 years to avoid Y2K bug, good until 2020. */
|
||||||
|
if (t->tm_year >= 100) t->tm_year -= 20;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((regB & 0x04) == 0) {
|
||||||
|
/* Convert binary to BCD (default RTC mode) */
|
||||||
|
t->tm_year = dec_to_bcd(t->tm_year % 100);
|
||||||
|
t->tm_mon = dec_to_bcd(t->tm_mon);
|
||||||
|
t->tm_mday = dec_to_bcd(t->tm_mday);
|
||||||
|
t->tm_hour = dec_to_bcd(t->tm_hour);
|
||||||
|
t->tm_min = dec_to_bcd(t->tm_min);
|
||||||
|
t->tm_sec = dec_to_bcd(t->tm_sec);
|
||||||
|
}
|
||||||
|
write_register(RTC_YEAR, t->tm_year);
|
||||||
|
write_register(RTC_MONTH, t->tm_mon);
|
||||||
|
write_register(RTC_MDAY, t->tm_mday);
|
||||||
|
write_register(RTC_HOUR, t->tm_hour);
|
||||||
|
write_register(RTC_MIN, t->tm_min);
|
||||||
|
write_register(RTC_SEC, t->tm_sec);
|
||||||
|
|
||||||
|
/* Stop the clock. */
|
||||||
|
regA= read_register(RTC_REG_A);
|
||||||
|
write_register(RTC_REG_A, regA | RTC_A_DV_STOP);
|
||||||
|
|
||||||
|
/* Allow updates and restart the clock. */
|
||||||
|
write_register(RTC_REG_B, regB);
|
||||||
|
write_register(RTC_REG_A, regA);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void write_register(int reg_addr, int value)
|
||||||
|
{
|
||||||
|
if(sys_outb(RTC_INDEX, reg_addr) != OK) {
|
||||||
|
printf("cmos: outb failed of %x\n", RTC_INDEX);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
if(sys_outb(RTC_IO, value) != OK) {
|
||||||
|
printf("cmos: outb failed of %x (index %x)\n", RTC_IO, reg_addr);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int bcd_to_dec(int n)
|
||||||
|
{
|
||||||
|
return ((n >> 4) & 0x0F) * 10 + (n & 0x0F);
|
||||||
|
}
|
||||||
|
|
||||||
|
int dec_to_bcd(int n)
|
||||||
|
{
|
||||||
|
return ((n / 10) << 4) | (n % 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
void usage(void)
|
||||||
|
{
|
||||||
|
printf("Usage: readclock [-nwW2]\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
|
@ -1,7 +1,7 @@
|
||||||
|
|
||||||
ETC=/etc/
|
ETC=/etc/
|
||||||
USRETC=/usr/etc/
|
USRETC=/usr/etc/
|
||||||
FILES1=fstab group hostname.file inet.conf motd.install mtab passwd profile protocols rc services termcap ttytab utmp rc.cd binary_sizes binary_sizes.big binary_sizes.xxl rc.rescue syslog.conf rc.daemons.dist rs.single make.conf
|
FILES1=fstab group hostname.file inet.conf motd.install mtab passwd profile protocols rc services termcap ttytab utmp rc.cd binary_sizes binary_sizes.big binary_sizes.xxl rc.rescue syslog.conf rc.daemons.dist rs.single make.conf drivers.conf
|
||||||
FILES2=shadow
|
FILES2=shadow
|
||||||
FILES3=daily dhcptags.conf rc
|
FILES3=daily dhcptags.conf rc
|
||||||
|
|
||||||
|
|
|
@ -73,16 +73,18 @@ driver random
|
||||||
;
|
;
|
||||||
};
|
};
|
||||||
|
|
||||||
driver cmos
|
driver readclock.drv
|
||||||
{
|
{
|
||||||
io 70:2;
|
io 70:2;
|
||||||
system
|
system
|
||||||
DEVIO # 21
|
DEVIO # 21
|
||||||
TIMES # 25
|
TIMES # 25
|
||||||
SAFECOPYTO # 32
|
SAFECOPYTO # 32
|
||||||
|
SAFECOPYFROM # 32
|
||||||
SETGRANT # 34
|
SETGRANT # 34
|
||||||
READBIOS # 35
|
READBIOS # 35
|
||||||
;
|
;
|
||||||
|
uid 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
driver is
|
driver is
|
||||||
|
|
1
etc/rc
1
etc/rc
|
@ -49,7 +49,6 @@ start)
|
||||||
test -f /etc/keymap && loadkeys /etc/keymap
|
test -f /etc/keymap && loadkeys /etc/keymap
|
||||||
|
|
||||||
up is -period 5HZ
|
up is -period 5HZ
|
||||||
up cmos -dev /dev/cmos -period 5HZ
|
|
||||||
echo .
|
echo .
|
||||||
|
|
||||||
# Set timezone.
|
# Set timezone.
|
||||||
|
|
Loading…
Reference in a new issue