Annotation of researchv9/sys/sun3/rtclock.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1985 by Sun Microsystems, Inc.
                      3:  */
                      4: 
                      5: #include "../h/param.h"
                      6: #include "../h/systm.h"
                      7: #include "../machine/clock.h"
                      8: #include "../machine/interreg.h"
                      9: 
                     10: /*
                     11:  * Machine-dependent clock routines.
                     12:  *
                     13:  * Clockstart restarts the real-time clock, which provides
                     14:  * hardclock interrupts to clock.c.
                     15:  *
                     16:  * Clkinit initializes the time of day hardware which provides
                     17:  * date functions.  Its primary function is to use some file
                     18:  * system information in case the hardware clock lost state.
                     19:  *
                     20:  * Clkset restores the time of day hardware after a time change.
                     21:  */
                     22: 
                     23: /*
                     24:  * Start the real-time clock.
                     25:  */
                     26: clkstart()
                     27: {
                     28: 
                     29:        /*
                     30:         * We will set things up to interrupt every 1/100 of a second.
                     31:         * locore.s currently only calls hardclock every other clock
                     32:         * interrupt, thus assuming 50 hz operation.
                     33:         */
                     34:        if (hz != 50)
                     35:                panic("clkstart");
                     36: 
                     37:        CLKADDR->clk_intrreg = CLK_INT_HSEC;    /* set 1/100 sec clock intr */
                     38:        set_clk_mode(IR_ENA_CLK5, 0);           /* turn on level 5 clock intr */
                     39: }
                     40: 
                     41: /*
                     42:  * Set and/or clear the desired clock bits in the interrupt
                     43:  * register.  We have to be extremely careful that we do it
                     44:  * in such a manner that we don't get ourselves lost.
                     45:  */
                     46: set_clk_mode(on, off)
                     47:        u_char on, off;
                     48: {
                     49:        register u_char interreg, dummy;
                     50: 
                     51:        /*
                     52:         * make sure that we are only playing w/ 
                     53:         * clock interrupt register bits
                     54:         */
                     55:        on &= (IR_ENA_CLK7 | IR_ENA_CLK5);
                     56:        off &= (IR_ENA_CLK7 | IR_ENA_CLK5);
                     57: 
                     58:        /*
                     59:         * Get a copy of current interrupt register,
                     60:         * turning off any undesired bits (aka `off')
                     61:         */
                     62:        interreg = *INTERREG & ~(off | IR_ENA_INT);
                     63:        *INTERREG &= ~IR_ENA_INT;
                     64: 
                     65:        /*
                     66:         * Next we turns off the CLK5 and CLK7 bits to clear
                     67:         * the flip-flops, then we disable clock interrupts.
                     68:         * Now we can read the clock's interrupt register
                     69:         * to clear any pending signals there.
                     70:         */
                     71:        *INTERREG &= ~(IR_ENA_CLK7 | IR_ENA_CLK5);
                     72:        CLKADDR->clk_cmd = (CLK_CMD_NORMAL & ~CLK_CMD_INTRENA);
                     73:        dummy = CLKADDR->clk_intrreg;                   /* clear clock */
                     74: #ifdef lint
                     75:        dummy = dummy;
                     76: #endif
                     77: 
                     78:        /*
                     79:         * Now we set all the desired bits
                     80:         * in the interrupt register, then
                     81:         * we turn the clock back on and
                     82:         * finally we can enable all interrupts.
                     83:         */
                     84:        *INTERREG |= (interreg | on);                   /* enable flip-flops */
                     85:        CLKADDR->clk_cmd = CLK_CMD_NORMAL;              /* enable clock intr */
                     86:        *INTERREG |= IR_ENA_INT;                        /* enable interrupts */
                     87: }
                     88: 
                     89: #define ABS(x) ((x) < 0? -(x) : (x))
                     90: 
                     91: /*
                     92:  * Initialize the system time, based on the time base which is, e.g.
                     93:  * from a filesystem.
                     94:  */
                     95: clkinit(base)
                     96:        time_t base;
                     97: {
                     98:        register unsigned todr;
                     99:        register long deltat;
                    100:        int ticks;
                    101:        int s;
                    102: 
                    103:        if (base < (85 - YRREF) * SECYR) {      /* ~1985 */
                    104:                printf("WARNING: preposterous time in file system");
                    105:                goto check;
                    106:        }
                    107:        s = splclock();
                    108:        time = todget(&ticks);
                    109:        (void) splx(s);
                    110:        if (time < SECYR) {
                    111:                time = base;
                    112:                printf("WARNING: TOD clock not initialized");
                    113:                clkset();
                    114:                goto check;
                    115:        }
                    116:        deltat = time - base;
                    117:        if (deltat < 0)
                    118:                deltat = -deltat;
                    119:        if (deltat < 2*SECDAY)
                    120:                return;
                    121:        printf("WARNING: clock %s %d days",
                    122:            time < base ? "lost" : "gained", deltat / SECDAY);
                    123: check:
                    124:        printf(" -- CHECK AND RESET THE DATE!\n");
                    125: }
                    126: 
                    127: /*
                    128:  * Dummy routine for version 9 compatability
                    129:  */
                    130: clkwrap()
                    131: {
                    132:        return(0);
                    133: }
                    134: 
                    135: clktrim()
                    136: {
                    137:        int ticks, sec;
                    138:        int s = splclock();
                    139: 
                    140:        /*
                    141:         * Sync the software clock with the hardware clock
                    142:         */
                    143:        sec = todget(&ticks);
                    144:        lbolt += hz * (sec - time) + (ticks - lbolt);
                    145:        (void) splx(s);
                    146: }
                    147: 
                    148: /*
                    149:  * Reset the TODR based on the time value; used when the TODR
                    150:  * has a preposterous value and also when the time is reset
                    151:  * by the settimeofday system call.  We call tod_set at splclock()
                    152:  * to avoid synctodr() from running and getting confused.
                    153:  */
                    154: clkset()
                    155: {
                    156:        int s;
                    157: 
                    158:        s = splclock();
                    159:        todset();
                    160:        (void) splx(s);
                    161: }
                    162: 
                    163: /*
                    164:  * For Sun-3, we use the Intersil ICM7170 for both the
                    165:  * real time clock and the time-of-day device.
                    166:  */
                    167: 
                    168: static u_int monthsec[12] = {
                    169:        31 * SECDAY,    /* Jan */
                    170:        28 * SECDAY,    /* Feb */
                    171:        31 * SECDAY,    /* Mar */
                    172:        30 * SECDAY,    /* Apr */
                    173:        31 * SECDAY,    /* May */
                    174:        30 * SECDAY,    /* Jun */
                    175:        31 * SECDAY,    /* Jul */
                    176:        31 * SECDAY,    /* Aug */
                    177:        30 * SECDAY,    /* Sep */
                    178:        31 * SECDAY,    /* Oct */
                    179:        30 * SECDAY,    /* Nov */
                    180:        31 * SECDAY     /* Dec */
                    181: };
                    182: 
                    183: #define        MONTHSEC(mon, yr)       \
                    184:        (((((yr) % 4) == 0) && ((mon) == 2))? 29*SECDAY : monthsec[(mon) - 1])
                    185: 
                    186: /*
                    187:  * Set the TOD based on the argument value; used when the TOD
                    188:  * has a preposterous value and also when the time is reset
                    189:  * by the settimeofday system call.
                    190:  */
                    191: todset()
                    192: {
                    193:        register int t = time;
                    194:        u_short hsec, sec, min, hour, day, mon, weekday, year;
                    195: 
                    196:        /*
                    197:         * Figure out the (adjusted) year
                    198:         */
                    199:        for (year = (YRREF - YRBASE); t > SECYEAR(year); year++)
                    200:                t -= SECYEAR(year);
                    201: 
                    202:        /*
                    203:         * Figure out what month this is by subtracting off
                    204:         * time per month, adjust for leap year if appropriate.
                    205:         */
                    206:        for (mon = 1; t >= 0; mon++)
                    207:                t -= MONTHSEC(mon, year);
                    208: 
                    209:        t += MONTHSEC(--mon, year);     /* back off one month */
                    210: 
                    211:        sec = t % 60;                   /* seconds */
                    212:        t /= 60;
                    213:        min = t % 60;                   /* minutes */
                    214:        t /= 60;
                    215:        hour = t % 24;                  /* hours (24 hour format) */
                    216:        day = t / 24;                   /* day of the month */
                    217:        day++;                          /* adjust to start at 1 */
                    218:        weekday = day % 7;              /* not right, but it doesn't matter */
                    219: 
                    220:        hsec = 0;
                    221: 
                    222:        CLKADDR->clk_cmd = (CLK_CMD_NORMAL & ~CLK_CMD_RUN);
                    223:        CLKADDR->clk_weekday = weekday;
                    224:        CLKADDR->clk_year = year;
                    225:        CLKADDR->clk_mon = mon;
                    226:        CLKADDR->clk_day = day;
                    227:        CLKADDR->clk_hour = hour;
                    228:        CLKADDR->clk_min = min;
                    229:        CLKADDR->clk_sec = sec;
                    230:        CLKADDR->clk_hsec = hsec;
                    231:        CLKADDR->clk_cmd = CLK_CMD_NORMAL;
                    232: }
                    233: 
                    234: /*
                    235:  * Read the current time from the clock chip and convert to UNIX form.
                    236:  * Assumes that the year in the counter chip is valid.
                    237:  */
                    238: todget(ticks)
                    239: int *ticks;
                    240: {
                    241:        u_char now[CLK_WEEKDAY];
                    242:        register int i;
                    243:        register u_char *cp = (u_char *)CLKADDR;
                    244:        register u_int t = 0;
                    245:        u_short year;
                    246: 
                    247:        for (i = CLK_HSEC; i < CLK_WEEKDAY; i++)        /* read counters */
                    248:                now[i] = *cp++;
                    249: 
                    250:        /*
                    251:         * Add the number of seconds for each year onto our time t.
                    252:         * We start at YRBASE, and count up to the year value given
                    253:         * by the chip.  If the year is greater/equal to the difference
                    254:         * between YRREF and YRBASE, then that time is added into
                    255:         * the Unix time value we are calculating.
                    256:         */
                    257:        for (year = 0; year < now[CLK_YEAR]; year++)
                    258:                if (year >= (YRREF - YRBASE))
                    259:                        t += SECYEAR(year);
                    260: 
                    261:        /*
                    262:         * Now add in the seconds for each month that has gone
                    263:         * by this year, adjusting for leap year if appropriate.
                    264:         */
                    265:        for (i = 1; i < now[CLK_MON]; i++)
                    266:                t += MONTHSEC(i, year);
                    267: 
                    268:        t += (now[CLK_DAY] - 1) * SECDAY;
                    269:        t += now[CLK_HOUR] * (60*60);
                    270:        t += now[CLK_MIN] * 60;
                    271:        t += now[CLK_SEC];
                    272: 
                    273:        *ticks = now[CLK_HSEC] * hz / 100;
                    274:        return (t);
                    275: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.