1 /* rtc.c - Use /dev/rtc for clock access */
2 #include <unistd.h> /* for close() */
3 #include <fcntl.h> /* for O_RDONLY */
7 #include <sys/time.h> /* for struct timeval */
13 * Get defines for rtc stuff.
15 * Getting the rtc defines is nontrivial.
16 * The obvious way is by including <linux/mc146818rtc.h>
17 * but that again includes <asm/io.h> which again includes ...
18 * and on sparc and alpha this gives compilation errors for
19 * many kernel versions. So, we give the defines ourselves here.
20 * Moreover, some Sparc person decided to be incompatible, and
21 * used a struct rtc_time different from that used in mc146818rtc.h.
24 /* On Sparcs, there is a <asm/rtc.h> that defines different ioctls
25 (that are required on my machine). However, this include file
26 does not exist on other architectures. */
32 /* The following is roughly equivalent */
35 int sec; /* Seconds (0-59) */
36 int min; /* Minutes (0-59) */
37 int hour; /* Hour (0-23) */
38 int dow; /* Day of the week (1-7) */
39 int dom; /* Day of the month (1-31) */
40 int month; /* Month of year (1-12) */
41 int year; /* Year (0-99) */
44 #define RTCGET _IOR('p', 20, struct sparc_rtc_time)
45 #define RTCSET _IOW('p', 21, struct sparc_rtc_time)
50 #include <linux/version.h>
51 /* Check if the /dev/rtc interface is available in this version of
52 the system headers. 131072 is linux 2.0.0. */
53 #if LINUX_VERSION_CODE >= 131072
54 #include <linux/mc146818rtc.h>
58 /* struct rtc_time is present since 1.3.99 */
59 /* Earlier (since 1.3.89), a struct tm was used. */
60 struct linux_rtc_time {
72 /* RTC_RD_TIME etc have this definition since 1.99.9 (pre2.0-9) */
74 #define RTC_RD_TIME _IOR('p', 0x09, struct linux_rtc_time)
75 #define RTC_SET_TIME _IOW('p', 0x0a, struct linux_rtc_time)
76 #define RTC_UIE_ON _IO('p', 0x03) /* Update int. enable on */
77 #define RTC_UIE_OFF _IO('p', 0x04) /* Update int. enable off */
79 /* RTC_EPOCH_READ and RTC_EPOCH_SET are present since 2.0.34 and 2.1.89 */
80 #ifndef RTC_EPOCH_READ
81 #define RTC_EPOCH_READ _IOR('p', 0x0d, unsigned long) /* Read epoch */
82 #define RTC_EPOCH_SET _IOW('p', 0x0e, unsigned long) /* Set epoch */
85 /* /dev/rtc is conventionally chardev 10/135
86 * ia64 uses /dev/efirtc, chardev 10/136
87 * devfs (obsolete) used /dev/misc/... for miscdev
88 * new RTC framework + udev uses dynamic major and /dev/rtc0.../dev/rtcN
89 * ... so we need an overridable default
92 /* default or user defined dev (by hwclock --rtc=<path>) */
95 static int rtc_dev_fd = -1;
118 if (rtc_dev_fd != -1)
121 /* --rtc option has been given */
123 rtc_dev_fd = open(rtc_dev_name, O_RDONLY);
125 for (p=fls; *p; ++p) {
126 rtc_dev_fd = open(*p, O_RDONLY);
128 if (rtc_dev_fd < 0 && (errno == ENOENT || errno == ENODEV))
134 rtc_dev_name = *fls; /* default for error messages */
143 open_rtc_or_exit(void) {
144 int rtc_fd = open_rtc();
147 outsyserr(_("open() of %s failed"), rtc_dev_name);
148 hwclock_exit(EX_OSFILE);
154 do_rtc_read_ioctl(int rtc_fd, struct tm *tm) {
159 /* some but not all sparcs use a different ioctl and struct */
160 struct sparc_rtc_time stm;
162 ioctlname = "RTCGET";
163 rc = ioctl(rtc_fd, RTCGET, &stm);
165 tm->tm_sec = stm.sec;
166 tm->tm_min = stm.min;
167 tm->tm_hour = stm.hour;
168 tm->tm_mday = stm.dom;
169 tm->tm_mon = stm.month - 1;
170 tm->tm_year = stm.year - 1900;
171 tm->tm_wday = stm.dow - 1;
172 tm->tm_yday = -1; /* day in the year */
175 if (rc == -1) { /* no sparc, or RTCGET failed */
176 ioctlname = "RTC_RD_TIME";
177 rc = ioctl(rtc_fd, RTC_RD_TIME, tm);
181 fprintf(stderr, _("ioctl() to %s to read the time failed.\n"),
186 tm->tm_isdst = -1; /* don't know whether it's dst */
191 busywait_for_rtc_clock_tick(const int rtc_fd) {
192 /*----------------------------------------------------------------------------
193 Wait for the top of a clock tick by reading /dev/rtc in a busy loop until
195 -----------------------------------------------------------------------------*/
196 struct tm start_time;
197 /* The time when we were called (and started waiting) */
200 struct timeval begin, now;
203 printf(_("Waiting in loop for time from %s to change\n"),
206 rc = do_rtc_read_ioctl(rtc_fd, &start_time);
210 /* Wait for change. Should be within a second, but in case something
211 * weird happens, we have a time limit (1.5s) on this loop to reduce the
212 * impact of this failure.
214 gettimeofday(&begin, NULL);
216 rc = do_rtc_read_ioctl(rtc_fd, &nowtime);
217 if (rc || start_time.tm_sec != nowtime.tm_sec)
219 gettimeofday(&now, NULL);
220 if (time_diff(now, begin) > 1.5) {
221 fprintf(stderr, _("Timed out waiting for time change.\n"));
232 synchronize_to_clock_tick_rtc(void) {
233 /*----------------------------------------------------------------------------
234 Same as synchronize_to_clock_tick(), but just for /dev/rtc.
235 -----------------------------------------------------------------------------*/
236 int rtc_fd; /* File descriptor of /dev/rtc */
241 outsyserr(_("open() of %s failed"), rtc_dev_name);
244 int rc; /* Return code from ioctl */
245 /* Turn on update interrupts (one per second) */
246 #if defined(__alpha__) || defined(__sparc__)
247 /* Not all alpha kernels reject RTC_UIE_ON, but probably they should. */
251 rc = ioctl(rtc_fd, RTC_UIE_ON, 0);
253 if (rc == -1 && (errno == ENOTTY || errno == EINVAL)) {
254 /* This rtc device doesn't have interrupt functions. This is typical
255 on an Alpha, where the Hardware Clock interrupts are used by the
256 kernel for the system clock, so aren't at the user's disposal.
259 printf(_("%s does not have interrupt functions. "),
261 ret = busywait_for_rtc_clock_tick(rtc_fd);
262 } else if (rc == 0) {
263 #ifdef Wait_until_update_interrupt
266 /* this blocks until the next update interrupt */
267 rc = read(rtc_fd, &dummy, sizeof(dummy));
270 outsyserr(_("read() to %s to wait for clock tick failed"),
275 /* Just reading rtc_fd fails on broken hardware: no update
276 interrupt comes and a bootscript with a hwclock call hangs */
280 /* Wait up to five seconds for the next update interrupt */
282 FD_SET(rtc_fd, &rfds);
285 rc = select(rtc_fd + 1, &rfds, NULL, NULL, &tv);
288 outsyserr(_("select() to %s to wait for clock tick failed"),
291 fprintf(stderr, _("select() to %s to wait for clock tick timed out\n"),
297 /* Turn off update interrupts */
298 rc = ioctl(rtc_fd, RTC_UIE_OFF, 0);
300 outsyserr(_("ioctl() to %s to turn off update interrupts failed"),
303 outsyserr(_("ioctl() to %s to turn on update interrupts "
304 "failed unexpectedly"), rtc_dev_name);
313 read_hardware_clock_rtc(struct tm *tm) {
316 rtc_fd = open_rtc_or_exit();
318 /* Read the RTC time/date, return answer via tm */
319 rc = do_rtc_read_ioctl(rtc_fd, tm);
326 set_hardware_clock_rtc(const struct tm *new_broken_time) {
327 /*-------------------------------------------------------------------------
328 Set the Hardware Clock to the broken down time <new_broken_time>.
329 Use ioctls to "rtc" device /dev/rtc.
330 -------------------------------------------------------------------------*/
335 rtc_fd = open_rtc_or_exit();
339 struct sparc_rtc_time stm;
341 stm.sec = new_broken_time->tm_sec;
342 stm.min = new_broken_time->tm_min;
343 stm.hour = new_broken_time->tm_hour;
344 stm.dom = new_broken_time->tm_mday;
345 stm.month = new_broken_time->tm_mon + 1;
346 stm.year = new_broken_time->tm_year + 1900;
347 stm.dow = new_broken_time->tm_wday + 1;
349 ioctlname = "RTCSET";
350 rc = ioctl(rtc_fd, RTCSET, &stm);
353 if (rc == -1) { /* no sparc, or RTCSET failed */
354 ioctlname = "RTC_SET_TIME";
355 rc = ioctl(rtc_fd, RTC_SET_TIME, new_broken_time);
360 fprintf(stderr, _("ioctl() to %s to set the time failed.\n"),
362 hwclock_exit(EX_IOERR);
366 printf(_("ioctl(%s) was successful.\n"), ioctlname);
373 get_permissions_rtc(void) {
377 static struct clock_ops rtc = {
378 "/dev interface to clock",
380 read_hardware_clock_rtc,
381 set_hardware_clock_rtc,
382 synchronize_to_clock_tick_rtc,
385 /* return &rtc if /dev/rtc can be opened, NULL otherwise */
387 probe_for_rtc_clock(){
388 int rtc_fd = open_rtc();
392 outsyserr(_("Open of %s failed"), rtc_dev_name);
399 get_epoch_rtc(unsigned long *epoch_p, int silent) {
400 /*----------------------------------------------------------------------------
401 Get the Hardware Clock epoch setting from the kernel.
402 ----------------------------------------------------------------------------*/
410 "To manipulate the epoch value in the kernel, we must "
411 "access the Linux 'rtc' device driver via the device special "
412 "file %s. This file does not exist on this system.\n"),
415 outsyserr(_("Unable to open %s"), rtc_dev_name);
420 if (ioctl(rtc_fd, RTC_EPOCH_READ, epoch_p) == -1) {
422 outsyserr(_("ioctl(RTC_EPOCH_READ) to %s failed"), rtc_dev_name);
427 printf(_("we have read epoch %ld from %s "
428 "with RTC_EPOCH_READ ioctl.\n"), *epoch_p, rtc_dev_name);
436 set_epoch_rtc(unsigned long epoch) {
437 /*----------------------------------------------------------------------------
438 Set the Hardware Clock epoch in the kernel.
439 ----------------------------------------------------------------------------*/
443 /* kernel would not accept this epoch value */
444 /* Hmm - bad habit, deciding not to do what the user asks
445 just because one believes that the kernel might not like it. */
446 fprintf(stderr, _("The epoch value may not be less than 1900. "
447 "You requested %ld\n"), epoch);
454 fprintf(stderr, _("To manipulate the epoch value in the kernel, we must "
455 "access the Linux 'rtc' device driver via the device special "
456 "file %s. This file does not exist on this system.\n"),
459 outsyserr(_("Unable to open %s"), rtc_dev_name);
464 printf(_("setting epoch to %ld "
465 "with RTC_EPOCH_SET ioctl to %s.\n"), epoch, rtc_dev_name);
467 if (ioctl(rtc_fd, RTC_EPOCH_SET, epoch) == -1) {
469 fprintf(stderr, _("The kernel device driver for %s "
470 "does not have the RTC_EPOCH_SET ioctl.\n"), rtc_dev_name);
472 outsyserr(_("ioctl(RTC_EPOCH_SET) to %s failed"), rtc_dev_name);