Exemple #1
0
int
get_epoch_rtc(unsigned long *epoch_p, int silent) {
/*----------------------------------------------------------------------------
  Get the Hardware Clock epoch setting from the kernel.
----------------------------------------------------------------------------*/
  int rtc_fd;

  rtc_fd = open_rtc();
  if (rtc_fd < 0) {
    if (!silent) {
      if (errno == ENOENT)
        fprintf(stderr, _(
		"To manipulate the epoch value in the kernel, we must "
                "access the Linux 'rtc' device driver via the device special "
                "file %s.  This file does not exist on this system.\n"),
		rtc_dev_name);
      else
        outsyserr(_("Unable to open %s"), rtc_dev_name);
    }
    return 1;
  }

  if (ioctl(rtc_fd, RTC_EPOCH_READ, epoch_p) == -1) {
    if (!silent)
      outsyserr(_("ioctl(RTC_EPOCH_READ) to %s failed"), rtc_dev_name);
    return 1;
  }

  if (debug)
	  printf(_("we have read epoch %ld from %s "
		 "with RTC_EPOCH_READ ioctl.\n"), *epoch_p, rtc_dev_name);

  return 0;
}
Exemple #2
0
/* 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) {	/* first time here */
		con_fd_filename = "/dev/tty1";
		con_fd = open(con_fd_filename, O_RDONLY);
	}
	if (con_fd < 0) {
		/* perhaps they are using devfs? */
		con_fd_filename = "/dev/vc/1";
		con_fd = open(con_fd_filename, O_RDONLY);
	}
	if (con_fd < 0) {
		/* probably KDGHWCLK exists on m68k only */
		outsyserr(_("Can't open /dev/tty1 or /dev/vc/1"));
	} else {
		if (ioctl(con_fd, KDGHWCLK, &t) == -1) {
			if (errno != EINVAL)
				outsyserr(_("KDGHWCLK ioctl failed"));
		} else
			ret = &kd;
	}
	return ret;
}
Exemple #3
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 %s"), con_fd_filename);
    exit(EX_IOERR);
  }

  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;
}
Exemple #4
0
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 {
    /* Added by Roman Hodek <*****@*****.**> */
    /* "The culprit is the fast loop with KDGHWCLK ioctls. It seems
       the kernel gets confused by those on Amigas with A2000 RTCs
       and simply hangs after some time. Inserting a nanosleep helps." */
    /* Christian T. Steigies: 1 instead of 1000000 is still sufficient
       to keep the machine from freezing. */

#ifdef HAVE_nanosleep
    struct timespec xsleep = { 0, 1 };
    nanosleep( &xsleep, NULL );
#else
    usleep(1);
#endif

    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;
}
Exemple #5
0
/* return &rtc if /dev/rtc can be opened, NULL otherwise */
struct clock_ops *
probe_for_rtc_clock(){
	int rtc_fd = open_rtc();
	if (rtc_fd >= 0)
		return &rtc;
	if (debug)
		outsyserr(_("Open of %s failed"), rtc_dev_name);
	return NULL;
}
Exemple #6
0
int
set_epoch_rtc(unsigned long epoch) {
/*----------------------------------------------------------------------------
  Set the Hardware Clock epoch in the kernel.
----------------------------------------------------------------------------*/
  int rtc_fd;

  if (epoch < 1900) {
    /* kernel would not accept this epoch value */
    /* Hmm - bad habit, deciding not to do what the user asks
       just because one believes that the kernel might not like it. */
    fprintf(stderr, _("The epoch value may not be less than 1900.  "
            "You requested %ld\n"), epoch);
    return 1;
  }

  rtc_fd = open_rtc();
  if (rtc_fd < 0) {
    if (errno == ENOENT)
      fprintf(stderr, _("To manipulate the epoch value in the kernel, we must "
              "access the Linux 'rtc' device driver via the device special "
              "file %s.  This file does not exist on this system.\n"),
	      rtc_dev_name);
    else
      outsyserr(_("Unable to open %s"), rtc_dev_name);
    return 1;
  }

  if (debug)
    printf(_("setting epoch to %ld "
	   "with RTC_EPOCH_SET ioctl to %s.\n"), epoch, rtc_dev_name);

  if (ioctl(rtc_fd, RTC_EPOCH_SET, epoch) == -1) {
    if (errno == EINVAL)
      fprintf(stderr, _("The kernel device driver for %s "
	      "does not have the RTC_EPOCH_SET ioctl.\n"), rtc_dev_name);
    else
      outsyserr(_("ioctl(RTC_EPOCH_SET) to %s failed"), rtc_dev_name);
    return 1;
  }

  return 0;
}
Exemple #7
0
static int
open_rtc_or_exit(void) {
	int rtc_fd = open_rtc();

	if (rtc_fd < 0) {
		outsyserr(_("open() of %s failed"), rtc_dev_name);
		hwclock_exit(EX_OSFILE);
	}
	return rtc_fd;
}
Exemple #8
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 KDSHWCLK failed"));
    exit(1);
  }
  return 0;
}
Exemple #9
0
static int
synchronize_to_clock_tick_rtc(void) {
/*----------------------------------------------------------------------------
  Same as synchronize_to_clock_tick(), but just for /dev/rtc.
-----------------------------------------------------------------------------*/
int rtc_fd;  /* File descriptor of /dev/rtc */
int ret;

  rtc_fd = open_rtc();
  if (rtc_fd == -1) {
    outsyserr(_("open() of %s failed"), rtc_dev_name);
    ret = 1;
  } else {
    int rc;  /* Return code from ioctl */
    /* Turn on update interrupts (one per second) */
#if defined(__alpha__) || defined(__sparc__)
    /* Not all alpha kernels reject RTC_UIE_ON, but probably they should. */
    rc = -1;
    errno = EINVAL;
#else
    rc = ioctl(rtc_fd, RTC_UIE_ON, 0);
#endif
    if (rc == -1 && (errno == ENOTTY || errno == EINVAL)) {
      /* This rtc device doesn't have interrupt functions.  This is typical
         on an Alpha, where the Hardware Clock interrupts are used by the
         kernel for the system clock, so aren't at the user's disposal.
         */
      if (debug)
	      printf(_("%s does not have interrupt functions. "),
		     rtc_dev_name);
      ret = busywait_for_rtc_clock_tick(rtc_fd);
    } else if (rc == 0) {
#ifdef Wait_until_update_interrupt
      unsigned long dummy;

      /* this blocks until the next update interrupt */
      rc = read(rtc_fd, &dummy, sizeof(dummy));
      ret = 1;
      if (rc == -1)
        outsyserr(_("read() to %s to wait for clock tick failed"),
		  rtc_dev_name);
      else
        ret = 0;
#else
      /* Just reading rtc_fd fails on broken hardware: no update
	 interrupt comes and a bootscript with a hwclock call hangs */
      fd_set rfds;
      struct timeval tv;

      /* Wait up to five seconds for the next update interrupt */
      FD_ZERO(&rfds);
      FD_SET(rtc_fd, &rfds);
      tv.tv_sec = 5;
      tv.tv_usec = 0;
      rc = select(rtc_fd + 1, &rfds, NULL, NULL, &tv);
      ret = 1;
      if (rc == -1)
        outsyserr(_("select() to %s to wait for clock tick failed"),
		  rtc_dev_name);
      else if (rc == 0)
	fprintf(stderr, _("select() to %s to wait for clock tick timed out\n"),
			  rtc_dev_name);
      else
        ret = 0;
#endif

      /* Turn off update interrupts */
      rc = ioctl(rtc_fd, RTC_UIE_OFF, 0);
      if (rc == -1)
        outsyserr(_("ioctl() to %s to turn off update interrupts failed"),
		  rtc_dev_name);
    } else {
      outsyserr(_("ioctl() to %s to turn on update interrupts "
		"failed unexpectedly"), rtc_dev_name);
      ret = 1;
    }
  }
  return ret;
}