Annotation of researchv9/sys/sun3/rtclock.c, revision 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.