diff options
Diffstat (limited to 'clock/kd.c')
-rw-r--r-- | clock/kd.c | 149 |
1 files changed, 149 insertions, 0 deletions
diff --git a/clock/kd.c b/clock/kd.c new file mode 100644 index 000000000..9ec91f005 --- /dev/null +++ b/clock/kd.c @@ -0,0 +1,149 @@ +/* kd.c - KDGHWCLK stuff, possibly m68k only */ +#include <unistd.h> /* for close() */ +#include <fcntl.h> /* for O_RDONLY */ +#include <sys/ioctl.h> + +#include "clock.h" +#include "nls.h" + +static int con_fd = -1; /* opened by probe_for_kd_clock() */ + /* never closed */ + +/* Get defines for KDGHWCLK and KDSHWCLK (m68k) */ +#include <linux/kd.h> +#ifndef KDGHWCLK +#define KDGHWCLK 0x4B50 /* get hardware clock */ +#define KDSHWCLK 0x4B51 /* set hardware clock */ +struct hwclk_time { + unsigned sec; /* 0..59 */ + unsigned min; /* 0..59 */ + unsigned hour; /* 0..23 */ + unsigned day; /* 1..31 */ + unsigned mon; /* 0..11 */ + unsigned year; /* 70... */ + int wday; /* 0..6, 0 is Sunday, -1 means unknown/don't set */ +}; +#endif + +static int +synchronize_to_clock_tick_kd(void) { +/*---------------------------------------------------------------------------- + Wait for the top of a clock tick by calling KDGHWCLK in a busy loop until + we see it. +-----------------------------------------------------------------------------*/ + int i; + + /* The time when we were called (and started waiting) */ + struct hwclk_time start_time, nowtime; + + if (debug) + printf(_("Waiting in loop for time from KDGHWCLK to change\n")); + + if (ioctl(con_fd, KDGHWCLK, &start_time) == -1) { + outsyserr(_("KDGHWCLK ioctl to read time failed")); + return 3; + } + + i = 0; + do { + if (i++ >= 1000000) { + fprintf(stderr, _("Timed out waiting for time change.\n")); + return 2; + } + if (ioctl(con_fd, KDGHWCLK, &nowtime) == -1) { + outsyserr(_("KDGHWCLK ioctl to read time failed in loop")); + return 3; + } + } while (start_time.sec == nowtime.sec); + + return 0; +} + + +static int +read_hardware_clock_kd(struct tm *tm) { +/*---------------------------------------------------------------------------- + Read the hardware clock and return the current time via <tm> + argument. Use ioctls to /dev/tty1 on what we assume is an m68k + machine. + + Note that we don't use /dev/console here. That might be a serial + console. +-----------------------------------------------------------------------------*/ + struct hwclk_time t; + + if (ioctl(con_fd, KDGHWCLK, &t) == -1) { + outsyserr(_("ioctl() failed to read time from /dev/tty1")); + exit(5); + } + + tm->tm_sec = t.sec; + tm->tm_min = t.min; + tm->tm_hour = t.hour; + tm->tm_mday = t.day; + tm->tm_mon = t.mon; + tm->tm_year = t.year; + tm->tm_wday = t.wday; + tm->tm_isdst = -1; /* Don't know if it's Daylight Savings Time */ + + return 0; +} + + +static int +set_hardware_clock_kd(const struct tm *new_broken_time) { +/*---------------------------------------------------------------------------- + Set the Hardware Clock to the time <new_broken_time>. Use ioctls to + /dev/tty1 on what we assume is an m68k machine. + + Note that we don't use /dev/console here. That might be a serial console. +----------------------------------------------------------------------------*/ + struct hwclk_time t; + + t.sec = new_broken_time->tm_sec; + t.min = new_broken_time->tm_min; + t.hour = new_broken_time->tm_hour; + t.day = new_broken_time->tm_mday; + t.mon = new_broken_time->tm_mon; + t.year = new_broken_time->tm_year; + t.wday = new_broken_time->tm_wday; + + if (ioctl(con_fd, KDSHWCLK, &t ) == -1) { + outsyserr(_("ioctl() to open /dev/tty1 failed")); + exit(1); + } + return 0; +} + +static int +get_permissions_kd(void) { + return 0; +} + +static struct clock_ops kd = { + "KDGHWCLK interface to m68k clock", + get_permissions_kd, + read_hardware_clock_kd, + set_hardware_clock_kd, + synchronize_to_clock_tick_kd, +}; + +/* return &kd if KDGHWCLK works, NULL otherwise */ +struct clock_ops * +probe_for_kd_clock() { + struct clock_ops *ret = NULL; + struct hwclk_time t; + + if (con_fd < 0) + con_fd = open("/dev/tty1", O_RDONLY); + if (con_fd >= 0) { + if (ioctl( con_fd, KDGHWCLK, &t ) == -1) { + if (errno != EINVAL) + outsyserr(_("KDGHWCLK ioctl failed")); + } else + ret = &kd; + } else { + outsyserr(_("Can't open /dev/tty1")); + } + return ret; +} |