Print this page
8680 Time of Day clock error

Split Close
Expand all
Collapse all
          --- old/usr/src/uts/i86pc/io/todpc_subr.c
          +++ new/usr/src/uts/i86pc/io/todpc_subr.c
↓ open down ↓ 11 lines elided ↑ open up ↑
  12   12   *
  13   13   * When distributing Covered Code, include this CDDL HEADER in each
  14   14   * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15   15   * If applicable, add the following below this CDDL HEADER, with the
  16   16   * fields enclosed by brackets "[]" replaced with your own identifying
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  /*
       22 + * Copyright 2018 Gary Mills
  22   23   * Copyright 2012 Nexenta Systems, Inc.  All rights reserved.
  23   24   */
  24   25  /*
  25   26   * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  26   27   * Use is subject to license terms.
  27   28   */
  28   29  
  29   30  /*      Copyright (c) 1990, 1991 UNIX System Laboratories, Inc. */
  30   31  /*      Copyright (c) 1984, 1986, 1987, 1988, 1989, 1990 AT&T   */
  31   32  /*        All Rights Reserved   */
↓ open down ↓ 7 lines elided ↑ open up ↑
  39   40  
  40   41  #include <sys/cpuvar.h>
  41   42  #include <sys/clock.h>
  42   43  #include <sys/debug.h>
  43   44  #include <sys/rtc.h>
  44   45  #include <sys/archsystm.h>
  45   46  #include <sys/sysmacros.h>
  46   47  #include <sys/lockstat.h>
  47   48  #include <sys/stat.h>
  48   49  #include <sys/sunddi.h>
       50 +#include <sys/ddi.h>
  49   51  
  50   52  #include <sys/acpi/acpi.h>
  51   53  #include <sys/acpica.h>
  52   54  
  53   55  static int todpc_rtcget(unsigned char *buf);
  54   56  static void todpc_rtcput(unsigned char *buf);
  55   57  
  56   58  #define CLOCK_RES       1000            /* 1 microsec in nanosecs */
  57   59  
  58   60  int clock_res = CLOCK_RES;
↓ open down ↓ 264 lines elided ↑ open up ↑
 323  325  {
 324  326          mutex_enter(&tod_lock);
 325  327          todpc_setalarm(top, 0);
 326  328          mutex_exit(&tod_lock);
 327  329  }
 328  330  
 329  331  /*
 330  332   * Routine to read contents of real time clock to the specified buffer.
 331  333   * Returns ENXIO if clock not valid, or EAGAIN if clock data cannot be read
 332  334   * else 0.
 333      - * The routine will busy wait for the Update-In-Progress flag to clear.
      335 + * Some RTC hardware is very slow at asserting the validity flag on
      336 + * startup.  The routine will busy wait for the RTC to become valid.
      337 + * The routine will also busy wait for the Update-In-Progress flag to clear.
 334  338   * On completion of the reads the Seconds register is re-read and the
 335  339   * UIP flag is rechecked to confirm that an clock update did not occur
 336  340   * during the accesses.  Routine will error exit after 256 attempts.
 337  341   * (See bugid 1158298.)
 338  342   * Routine returns RTC_NREG (which is 15) bytes of data, as given in the
 339  343   * technical reference.  This data includes both time and status registers.
 340  344   */
 341  345  
 342  346  static int
 343  347  todpc_rtcget(unsigned char *buf)
 344  348  {
 345  349          unsigned char   reg;
 346  350          int             i;
 347      -        int             retries = 256;
      351 +        int             uip_try = 256;
      352 +        int             vrt_try = 512;
 348  353          unsigned char   *rawp;
 349  354          unsigned char   century = RTC_CENTURY;
 350  355          unsigned char   day_alrm;
 351  356          unsigned char   mon_alrm;
 352  357  
 353  358          ASSERT(MUTEX_HELD(&tod_lock));
 354  359  
 355  360          day_alrm = pc_rtc_offset.day_alrm;
 356  361          mon_alrm = pc_rtc_offset.mon_alrm;
 357  362          if (pc_rtc_offset.century != 0) {
 358  363                  century = pc_rtc_offset.century;
 359  364          }
 360  365  
 361      -        outb(RTC_ADDR, RTC_D);          /* check if clock valid */
 362      -        reg = inb(RTC_DATA);
 363      -        if ((reg & RTC_VRT) == 0)
 364      -                return (ENXIO);
      366 +        for (;;) {
      367 +                if (vrt_try-- < 0)
      368 +                        return (ENXIO);
      369 +                outb(RTC_ADDR, RTC_D);          /* check if clock valid */
      370 +                reg = inb(RTC_DATA);
      371 +                if ((reg & RTC_VRT) != 0)
      372 +                        break;
      373 +                drv_usecwait(5000);             /* Delay for 5000 us */
      374 +        }
 365  375  
      376 +
 366  377  checkuip:
 367      -        if (retries-- < 0)
      378 +        if (uip_try-- < 0)
 368  379                  return (EAGAIN);
 369  380          outb(RTC_ADDR, RTC_A);          /* check if update in progress */
 370  381          reg = inb(RTC_DATA);
 371  382          if (reg & RTC_UIP) {
 372  383                  tenmicrosec();
 373  384                  goto checkuip;
 374  385          }
 375  386  
 376  387          for (i = 0, rawp = buf; i < RTC_NREG; i++) {
 377  388                  outb(RTC_ADDR, i);
↓ open down ↓ 89 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX