[BACK]Return to clock.c CVS log [TXT][DIR] Up to [local] / sys / arch / alpha / alpha

Annotation of sys/arch/alpha/alpha/clock.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: clock.c,v 1.18 2007/04/30 04:35:05 miod Exp $ */
                      2: /*     $NetBSD: clock.c,v 1.29 2000/06/05 21:47:10 thorpej Exp $       */
                      3:
                      4: /*
                      5:  * Copyright (c) 1988 University of Utah.
                      6:  * Copyright (c) 1992, 1993
                      7:  *     The Regents of the University of California.  All rights reserved.
                      8:  *
                      9:  * This code is derived from software contributed to Berkeley by
                     10:  * the Systems Programming Group of the University of Utah Computer
                     11:  * Science Department and Ralph Campbell.
                     12:  *
                     13:  * Redistribution and use in source and binary forms, with or without
                     14:  * modification, are permitted provided that the following conditions
                     15:  * are met:
                     16:  * 1. Redistributions of source code must retain the above copyright
                     17:  *    notice, this list of conditions and the following disclaimer.
                     18:  * 2. Redistributions in binary form must reproduce the above copyright
                     19:  *    notice, this list of conditions and the following disclaimer in the
                     20:  *    documentation and/or other materials provided with the distribution.
                     21:  * 3. Neither the name of the University nor the names of its contributors
                     22:  *    may be used to endorse or promote products derived from this software
                     23:  *    without specific prior written permission.
                     24:  *
                     25:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     26:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     27:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     28:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     29:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     30:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     31:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     32:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     33:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     34:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     35:  * SUCH DAMAGE.
                     36:  *
                     37:  * from: Utah Hdr: clock.c 1.18 91/01/21
                     38:  *
                     39:  *     @(#)clock.c     8.1 (Berkeley) 6/10/93
                     40:  */
                     41:
                     42: #include <sys/param.h>
                     43: #include <sys/kernel.h>
                     44: #include <sys/systm.h>
                     45: #include <sys/device.h>
                     46: #include <sys/evcount.h>
                     47: #include <sys/timetc.h>
                     48:
                     49: #include <dev/clock_subr.h>
                     50:
                     51: #include <machine/rpb.h>
                     52: #include <machine/autoconf.h>
                     53: #include <machine/cpuconf.h>
                     54:
                     55: #include <alpha/alpha/clockvar.h>
                     56:
                     57: #define MINYEAR 1998 /* "today" */
                     58: #ifdef CLOCK_COMPAT_OSF1
                     59: /*
                     60:  * According to OSF/1's /usr/sys/include/arch/alpha/clock.h,
                     61:  * the console adjusts the RTC years 13..19 to 93..99 and
                     62:  * 20..40 to 00..20. (historical reasons?)
                     63:  * DEC Unix uses an offset to the year to stay outside
                     64:  * the dangerous area for the next couple of years.
                     65:  */
                     66: #define UNIX_YEAR_OFFSET 52 /* 41=>1993, 12=>2064 */
                     67: #else
                     68: #define UNIX_YEAR_OFFSET 0
                     69: #endif
                     70:
                     71: extern int schedhz;
                     72:
                     73: struct device *clockdev;
                     74: const struct clockfns *clockfns;
                     75: int clockinitted;
                     76: struct evcount clk_count;
                     77: int clk_irq = 0;
                     78:
                     79: u_int rpcc_get_timecount(struct timecounter *);
                     80: struct timecounter rpcc_timecounter = {
                     81:        rpcc_get_timecount, NULL, ~0u, 0, "rpcc", 0, NULL
                     82: };
                     83:
                     84: void
                     85: clockattach(dev, fns)
                     86:        struct device *dev;
                     87:        const struct clockfns *fns;
                     88: {
                     89:
                     90:        /*
                     91:         * Just bookkeeping.
                     92:         */
                     93:        printf("\n");
                     94:
                     95:        if (clockfns != NULL)
                     96:                panic("clockattach: multiple clocks");
                     97:        clockdev = dev;
                     98:        clockfns = fns;
                     99: }
                    100:
                    101: /*
                    102:  * Machine-dependent clock routines.
                    103:  *
                    104:  * Startrtclock restarts the real-time clock, which provides
                    105:  * hardclock interrupts to kern_clock.c.
                    106:  *
                    107:  * Inittodr initializes the time of day hardware which provides
                    108:  * date functions.  Its primary function is to use some file
                    109:  * system information in case the hardware clock lost state.
                    110:  *
                    111:  * Resettodr restores the time of day hardware after a time change.
                    112:  */
                    113:
                    114: /*
                    115:  * Start the real-time and statistics clocks. Leave stathz 0 since there
                    116:  * are no other timers available.
                    117:  */
                    118: void
                    119: cpu_initclocks(void)
                    120: {
                    121:        u_int32_t cycles_per_sec;
                    122:        struct clocktime ct;
                    123:        u_int32_t first_rpcc, second_rpcc; /* only lower 32 bits are valid */
                    124:        int first_sec;
                    125:
                    126:        if (clockfns == NULL)
                    127:                panic("cpu_initclocks: no clock attached");
                    128:
                    129:        tick = 1000000 / hz;    /* number of microseconds between interrupts */
                    130:
                    131:        /*
                    132:         * Establish the clock interrupt; it's a special case.
                    133:         *
                    134:         * We establish the clock interrupt this late because if
                    135:         * we do it at clock attach time, we may have never been at
                    136:         * spl0() since taking over the system.  Some versions of
                    137:         * PALcode save a clock interrupt, which would get delivered
                    138:         * when we spl0() in autoconf.c.  If established the clock
                    139:         * interrupt handler earlier, that interrupt would go to
                    140:         * hardclock, which would then fall over because p->p_stats
                    141:         * isn't set at that time.
                    142:         */
                    143:        platform.clockintr = hardclock;
                    144:        schedhz = 16;
                    145:
                    146:        evcount_attach(&clk_count, "clock", (void *)&clk_irq, &evcount_intr);
                    147:
                    148:        /*
                    149:         * Get the clock started.
                    150:         */
                    151:        (*clockfns->cf_init)(clockdev);
                    152:
                    153:        /*
                    154:         * Calibrate the cycle counter frequency.
                    155:         */
                    156:        (*clockfns->cf_get)(clockdev, 0, &ct);
                    157:        first_sec = ct.sec;
                    158:
                    159:        /* Let the clock tick one second. */
                    160:        do {
                    161:                first_rpcc = alpha_rpcc();
                    162:                (*clockfns->cf_get)(clockdev, 0, &ct);
                    163:        } while (ct.sec == first_sec);
                    164:        first_sec = ct.sec;
                    165:        /* Let the clock tick one more second. */
                    166:        do {
                    167:                second_rpcc = alpha_rpcc();
                    168:                (*clockfns->cf_get)(clockdev, 0, &ct);
                    169:        } while (ct.sec == first_sec);
                    170:
                    171:        cycles_per_sec = second_rpcc - first_rpcc;
                    172:
                    173:        rpcc_timecounter.tc_frequency = cycles_per_sec;
                    174:
                    175:        tc_init(&rpcc_timecounter);
                    176: }
                    177:
                    178: /*
                    179:  * We assume newhz is either stathz or profhz, and that neither will
                    180:  * change after being set up above.  Could recalculate intervals here
                    181:  * but that would be a drag.
                    182:  */
                    183: void
                    184: setstatclockrate(newhz)
                    185:        int newhz;
                    186: {
                    187:
                    188:        /* nothing we can do */
                    189: }
                    190:
                    191: /*
                    192:  * Initialize the time of day register, based on the time base which is, e.g.
                    193:  * from a filesystem.  Base provides the time to within six months,
                    194:  * and the time of year clock (if any) provides the rest.
                    195:  */
                    196: void
                    197: inittodr(time_t base)
                    198: {
                    199:        struct clocktime ct;
                    200:        int year;
                    201:        struct clock_ymdhms dt;
                    202:        time_t deltat;
                    203:        int badbase;
                    204:        struct timespec ts;
                    205:
                    206:        ts.tv_sec = ts.tv_nsec = 0;
                    207:
                    208:        if (base < (MINYEAR-1970)*SECYR) {
                    209:                printf("WARNING: preposterous time in file system");
                    210:                /* read the system clock anyway */
                    211:                base = (MINYEAR-1970)*SECYR;
                    212:                badbase = 1;
                    213:        } else
                    214:                badbase = 0;
                    215:
                    216:        (*clockfns->cf_get)(clockdev, base, &ct);
                    217: #ifdef DEBUG
                    218:        printf("readclock: %d/%d/%d/%d/%d/%d", ct.year, ct.mon, ct.day,
                    219:               ct.hour, ct.min, ct.sec);
                    220: #endif
                    221:        clockinitted = 1;
                    222:
                    223:        year = 1900 + UNIX_YEAR_OFFSET + ct.year;
                    224:        if (year < 1970)
                    225:                year += 100;
                    226:        /* simple sanity checks (2037 = time_t overflow) */
                    227:        if (year < MINYEAR || year > 2037 ||
                    228:            ct.mon < 1 || ct.mon > 12 || ct.day < 1 ||
                    229:            ct.day > 31 || ct.hour > 23 || ct.min > 59 || ct.sec > 59) {
                    230:                /*
                    231:                 * Believe the time in the file system for lack of
                    232:                 * anything better, resetting the TODR.
                    233:                 */
                    234:                ts.tv_sec = base;
                    235:                if (!badbase) {
                    236:                        printf("WARNING: preposterous clock chip time\n");
                    237:                        resettodr();
                    238:                }
                    239:                goto bad;
                    240:        }
                    241:
                    242:        dt.dt_year = year;
                    243:        dt.dt_mon = ct.mon;
                    244:        dt.dt_day = ct.day;
                    245:        dt.dt_hour = ct.hour;
                    246:        dt.dt_min = ct.min;
                    247:        dt.dt_sec = ct.sec;
                    248:        ts.tv_sec = clock_ymdhms_to_secs(&dt);
                    249: #ifdef DEBUG
                    250:        printf("=>%ld (%d)\n", ts.tv_sec, base);
                    251: #endif
                    252:
                    253:        if (!badbase) {
                    254:                /*
                    255:                 * See if we gained/lost two or more days;
                    256:                 * if so, assume something is amiss.
                    257:                 */
                    258:                deltat = ts.tv_sec - base;
                    259:                if (deltat < 0)
                    260:                        deltat = -deltat;
                    261:                if (deltat < 2 * SECDAY) {
                    262:                        tc_setclock(&ts);
                    263:                        return;
                    264:                }
                    265:                printf("WARNING: clock %s %ld days",
                    266:                    ts.tv_sec < base ? "lost" : "gained",
                    267:                    (long)deltat / SECDAY);
                    268:        }
                    269: bad:
                    270:        tc_setclock(&ts);
                    271:        printf(" -- CHECK AND RESET THE DATE!\n");
                    272: }
                    273:
                    274: /*
                    275:  * Reset the TODR based on the time value; used when the TODR
                    276:  * has a preposterous value and also when the time is reset
                    277:  * by the stime system call.  Also called when the TODR goes past
                    278:  * TODRZERO + 100*(SECYEAR+2*SECDAY) (e.g. on Jan 2 just after midnight)
                    279:  * to wrap the TODR around.
                    280:  */
                    281: void
                    282: resettodr()
                    283: {
                    284:        struct clock_ymdhms dt;
                    285:        struct clocktime ct;
                    286:
                    287:        if (!clockinitted)
                    288:                return;
                    289:
                    290:        clock_secs_to_ymdhms(time_second, &dt);
                    291:
                    292:        /* rt clock wants 2 digits */
                    293:        ct.year = (dt.dt_year - UNIX_YEAR_OFFSET) % 100;
                    294:        ct.mon = dt.dt_mon;
                    295:        ct.day = dt.dt_day;
                    296:        ct.hour = dt.dt_hour;
                    297:        ct.min = dt.dt_min;
                    298:        ct.sec = dt.dt_sec;
                    299:        ct.dow = dt.dt_wday;
                    300: #ifdef DEBUG
                    301:        printf("setclock: %d/%d/%d/%d/%d/%d\n", ct.year, ct.mon, ct.day,
                    302:               ct.hour, ct.min, ct.sec);
                    303: #endif
                    304:
                    305:        (*clockfns->cf_set)(clockdev, &ct);
                    306: }
                    307:
                    308: u_int
                    309: rpcc_get_timecount(struct timecounter *tc)
                    310: {
                    311:        return alpha_rpcc();
                    312: }

CVSweb