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

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

1.1       nbrk        1: /*     $OpenBSD: clock.c,v 1.24 2007/07/14 19:06:48 miod Exp $ */
                      2: /*     $NetBSD: clock.c,v 1.39 1999/11/05 19:14:56 scottr Exp $        */
                      3:
                      4: /*
                      5:  * Copyright (c) 1988 University of Utah.
                      6:  * Copyright (c) 1982, 1990 The Regents of the University of California.
                      7:  * 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.
                     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: /*-
                     38:  * Copyright (C) 1993  Allen K. Briggs, Chris P. Caputo,
                     39:  *                     Michael L. Finch, Bradley A. Grantham, and
                     40:  *                     Lawrence A. Kesteloot
                     41:  * All rights reserved.
                     42:  *
                     43:  * Redistribution and use in source and binary forms, with or without
                     44:  * modification, are permitted provided that the following conditions
                     45:  * are met:
                     46:  * 1. Redistributions of source code must retain the above copyright
                     47:  *    notice, this list of conditions and the following disclaimer.
                     48:  * 2. Redistributions in binary form must reproduce the above copyright
                     49:  *    notice, this list of conditions and the following disclaimer in the
                     50:  *    documentation and/or other materials provided with the distribution.
                     51:  * 3. All advertising materials mentioning features or use of this software
                     52:  *    must display the following acknowledgement:
                     53:  *     This product includes software developed by the Alice Group.
                     54:  * 4. The names of the Alice Group or any of its members may not be used
                     55:  *    to endorse or promote products derived from this software without
                     56:  *    specific prior written permission.
                     57:  *
                     58:  * THIS SOFTWARE IS PROVIDED BY THE ALICE GROUP ``AS IS'' AND ANY EXPRESS OR
                     59:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
                     60:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
                     61:  * IN NO EVENT SHALL THE ALICE GROUP BE LIABLE FOR ANY DIRECT, INDIRECT,
                     62:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
                     63:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
                     64:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
                     65:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
                     66:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
                     67:  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                     68:  *
                     69:  */
                     70: /*
                     71:  *
                     72:  * from: Utah $Hdr: clock.c 1.18 91/01/21$
                     73:  *
                     74:  *     @(#)clock.c   7.6 (Berkeley) 5/7/91
                     75:  */
                     76:
                     77: /*
                     78:  * Mac II machine-dependent clock routines.
                     79:  */
                     80:
                     81: #include <sys/param.h>
                     82: #include <sys/device.h>
                     83: #include <sys/limits.h>
                     84: #include <sys/kernel.h>
                     85: #include <sys/systm.h>
                     86:
                     87: #include <machine/autoconf.h>
                     88: #include <machine/psl.h>
                     89: #include <machine/cpu.h>
                     90:
                     91: #include <mac68k/mac68k/pram.h>
                     92: #include <machine/viareg.h>
                     93:
                     94: #include <dev/clock_subr.h>
                     95:
                     96: #ifdef DEBUG
                     97: int    clock_debug = 0;
                     98: #endif
                     99:
                    100: int    rtclock_intr(void *);
                    101:
                    102: u_int          clk_interval;
                    103: u_int8_t       clk_inth, clk_intl;
                    104:
                    105: #define        DIFF19041970    2082844800
                    106:
                    107: /*
                    108:  * The Macintosh timers decrement once every 1.2766 microseconds.
                    109:  * MGFH2, p. 180
                    110:  */
                    111: #define        CLK_RATE        12766
                    112:
                    113: /*
                    114:  * Start the real-time clock; i.e. set timer latches and boot timer.
                    115:  *
                    116:  * We use VIA1 timer 1.
                    117:  */
                    118: void
                    119: startrtclock()
                    120: {
                    121: #ifndef HZ
                    122:        /*
                    123:         * By default, if HZ is not specified, use 60 Hz, unless we are
                    124:         * using A/UX style interrupts. We then need to readjust values
                    125:         * based on a 100Hz value in param.c.
                    126:         */
                    127:        if (mac68k_machine.aux_interrupts == 0) {
                    128: #define        HZ_60 60
                    129:                hz = HZ_60;
                    130:                tick = 1000000 / HZ_60;
                    131:                tickadj = 240000 / (60 * HZ_60);/* can adjust 240ms in 60s */
                    132:        }
                    133: #endif
                    134:
                    135:        /*
                    136:         * Calculate clocks needed to hit hz ticks/sec.
                    137:         *
                    138:         * The VIA clock speed is 1.2766us, so the timer value needed is:
                    139:         *
                    140:         *                    1       1,000,000us     1
                    141:         *  CLK_INTERVAL = -------- * ----------- * ------
                    142:         e                 1.2766us       1s          hz
                    143:         *
                    144:         * While it may be tempting to simplify the following further,
                    145:         * we can run into integer overflow problems.
                    146:         * Also note:  do *not* define HZ to be less than 12; overflow
                    147:         * will occur, yielding invalid results.
                    148:         */
                    149:        clk_interval = ((100000000UL / hz) * 100) / 12766;
                    150:        clk_inth = ((clk_interval >> 8) & 0xff);
                    151:        clk_intl = (clk_interval & 0xff);
                    152:
                    153:        /* be certain clock interrupts are off */
                    154:        via_reg(VIA1, vIER) = V1IF_T1;
                    155:
                    156:        /* set timer latch */
                    157:        via_reg(VIA1, vACR) |= ACR_T1LATCH;
                    158:
                    159:        /* set VIA timer 1 latch to ``hz'' Hz */
                    160:        via_reg(VIA1, vT1L) = clk_intl;
                    161:        via_reg(VIA1, vT1LH) = clk_inth;
                    162:
                    163:        /* set VIA timer 1 counter started for ``hz'' Hz */
                    164:        via_reg(VIA1, vT1C) = clk_intl;
                    165:        via_reg(VIA1, vT1CH) = clk_inth;
                    166: }
                    167:
                    168: void
                    169: cpu_initclocks()
                    170: {
                    171:        tickfix = 1000000 - (hz * tick);
                    172:        if (tickfix != 0) {
                    173:                int ftp;
                    174:
                    175:                ftp = min(ffs(tickfix), ffs(hz));
                    176:                tickfix >>= (ftp - 1);
                    177:                tickfixinterval = hz >> (ftp - 1);
                    178:        }
                    179:
                    180:        /* clear then enable clock interrupt. */
                    181:        via_reg(VIA1, vIFR) |= V1IF_T1;
                    182:        via_reg(VIA1, vIER) = 0x80 | V1IF_T1;
                    183: }
                    184:
                    185: void
                    186: setstatclockrate(rateinhz)
                    187:        int rateinhz;
                    188: {
                    189: }
                    190:
                    191: /*
                    192:  * Returns number of usec since last clock tick/interrupt.
                    193:  *
                    194:  * Check high byte twice to prevent missing a roll-over.
                    195:  * (race condition?)
                    196:  */
                    197: u_long
                    198: clkread()
                    199: {
                    200:        int high, high2, low;
                    201:
                    202:        high = via_reg(VIA1, vT1CH);
                    203:        low = via_reg(VIA1, vT1C);
                    204:
                    205:        high2 = via_reg(VIA1, vT1CH);
                    206:        if (high != high2)
                    207:                high = high2;
                    208:
                    209:        /* return count left in timer / 1.27 */
                    210:        return ((clk_interval - (high << 8) - low) * 10000 / CLK_RATE);
                    211: }
                    212:
                    213: static u_long  ugmt_2_pramt(u_long);
                    214: static u_long  pramt_2_ugmt(u_long);
                    215:
                    216: /*
                    217:  * Convert GMT to Mac PRAM time, using rtc_offset
                    218:  * GMT bias adjustment is done elsewhere.
                    219:  */
                    220: static u_long
                    221: ugmt_2_pramt(t)
                    222:        u_long t;
                    223: {
                    224:        /* don't know how to open a file properly. */
                    225:        /* assume compiled timezone is correct. */
                    226:
                    227:        return (t + DIFF19041970 - 60 * tz.tz_minuteswest);
                    228: }
                    229:
                    230: /*
                    231:  * Convert a Mac PRAM time value to GMT, using rtc_offset
                    232:  * GMT bias adjustment is done elsewhere.
                    233:  */
                    234: static u_long
                    235: pramt_2_ugmt(t)
                    236:        u_long t;
                    237: {
                    238:        return (t - DIFF19041970 + 60 * tz.tz_minuteswest);
                    239: }
                    240:
                    241: /*
                    242:  * Time from the booter.
                    243:  */
                    244: u_long macos_boottime;
                    245:
                    246: /*
                    247:  * Bias in minutes east from GMT (also from booter).
                    248:  */
                    249: long   macos_gmtbias;
                    250:
                    251: /*
                    252:  * Flag for whether or not we can trust the PRAM.  If we don't
                    253:  * trust it, we don't write to it, and we take the MacOS value
                    254:  * that is passed from the booter (which will only be a second
                    255:  * or two off by now).
                    256:  */
                    257: int    mac68k_trust_pram = 1;
                    258:
                    259: /*
                    260:  * Set global GMT time register, using a file system time base for comparison
                    261:  * and sanity checking.
                    262:  */
                    263: void
                    264: inittodr(base)
                    265:        time_t base;
                    266: {
                    267:        u_long timbuf;
                    268:
                    269:        timbuf = pram_readtime();
                    270:        if (timbuf == 0) {
                    271:                /* We don't know how to access PRAM on this hardware. */
                    272:                timbuf = macos_boottime;
                    273:                mac68k_trust_pram = 0;
                    274:        } else {
                    275:                timbuf = pramt_2_ugmt(pram_readtime());
                    276:                if ((timbuf - (macos_boottime + 60 * tz.tz_minuteswest)) >
                    277:                    10 * 60) {
                    278: #ifdef DIAGNOSTIC
                    279:                        printf("PRAM time does not appear"
                    280:                            " to have been read correctly.\n");
                    281:                        printf("PRAM: 0x%lx, macos_boottime: 0x%lx.\n",
                    282:                            timbuf, macos_boottime + 60 * tz.tz_minuteswest);
                    283: #endif
                    284:                        timbuf = macos_boottime;
                    285:                        mac68k_trust_pram = 0;
                    286:                }
                    287: #ifdef DEBUG
                    288:                else
                    289:                        printf("PRAM: 0x%lx, macos_boottime: 0x%lx.\n",
                    290:                            timbuf, macos_boottime);
                    291: #endif
                    292:        }
                    293:
                    294:        /*
                    295:         * GMT bias is passed in from Booter
                    296:         * To get GMT, *subtract* GMTBIAS from *our* time
                    297:         * (gmtbias is in minutes, mult by 60)
                    298:         */
                    299:        timbuf -= macos_gmtbias * 60;
                    300:
                    301:        if (base < 5 * SECYR) {
                    302:                printf("WARNING: file system time earlier than 1975\n");
                    303:                printf(" -- CHECK AND RESET THE DATE!\n");
                    304:                base = 36 * SECYR;      /* Last update here in 2006... */
                    305:        }
                    306:        if (timbuf < base) {
                    307:                printf(
                    308:                    "WARNING: Battery clock has earlier time than UNIX fs.\n");
                    309:                timbuf = base;
                    310:        }
                    311:        time.tv_sec = timbuf;
                    312:        time.tv_usec = 0;
                    313: }
                    314:
                    315: /*
                    316:  * Set battery backed clock to a new time, presumably after someone has
                    317:  * changed system time.
                    318:  */
                    319: void
                    320: resettodr()
                    321: {
                    322:        if (mac68k_trust_pram)
                    323:                /*
                    324:                 * GMT bias is passed in from the Booter.
                    325:                 * To get *our* time, add GMTBIAS to GMT.
                    326:                 * (gmtbias is in minutes, multiply by 60).
                    327:                 */
                    328:                pram_settime(ugmt_2_pramt(time.tv_sec + macos_gmtbias * 60));
                    329: }
                    330:
                    331: #define        DELAY_CALIBRATE (0xffffff << 7) /* Large value for calibration */
                    332:
                    333: u_int          delay_factor = DELAY_CALIBRATE;
                    334: volatile int   delay_flag = 1;
                    335:
                    336: int            _delay(u_int);
                    337: static int     delay_timer1_irq(void *);
                    338:
                    339: static int
                    340: delay_timer1_irq(dummy)
                    341:        void *dummy;
                    342: {
                    343:        delay_flag = 0;
                    344:        return (1);
                    345: }
                    346:
                    347: /*
                    348:  * Calibrate delay_factor with VIA1 timer T1.
                    349:  */
                    350: void
                    351: mac68k_calibrate_delay()
                    352: {
                    353:        u_int sum, n;
                    354:
                    355:        /* Disable VIA1 timer 1 interrupts and set up service routine */
                    356:        via_reg(VIA1, vIER) = V1IF_T1;
                    357:        via1_register_irq(VIA1_T1, delay_timer1_irq, NULL, NULL);
                    358:
                    359:        /* Set the timer for one-shot mode, then clear and enable interrupts */
                    360:        via_reg(VIA1, vACR) &= ~ACR_T1LATCH;
                    361:        via_reg(VIA1, vIFR) = V1IF_T1;  /* (this is needed for IIsi) */
                    362:        via_reg(VIA1, vIER) = 0x80 | V1IF_T1;
                    363:
                    364: #ifdef DEBUG
                    365:        if (clock_debug)
                    366:                printf("mac68k_calibrate_delay(): entering timing loop\n");
                    367: #endif
                    368:
                    369:        (void)_spl(IPLTOPSL(mac68k_machine.via1_ipl) - 1);
                    370:
                    371:        for (sum = 0, n = 8; n > 0; n--) {
                    372:                delay_flag = 1;
                    373:                via_reg(VIA1, vT1C) = 0;        /* 1024 clock ticks */
                    374:                via_reg(VIA1, vT1CH) = 4;       /* (approx 1.3 msec) */
                    375:                sum += ((delay_factor >> 7) - _delay(1));
                    376:        }
                    377:
                    378:        (void)splhigh();
                    379:
                    380:        /* Disable timer interrupts and reset service routine */
                    381:        via_reg(VIA1, vIER) = V1IF_T1;
                    382:        via1_register_irq(VIA1_T1, rtclock_intr, NULL, NULL);
                    383:
                    384:        /*
                    385:         * If this weren't integer math, the following would look
                    386:         * a lot prettier.  It should really be something like
                    387:         * this:
                    388:         *      delay_factor = ((sum / 8) / (1024 * 1.2766)) * 128;
                    389:         * That is, average the sum, divide by the number of usec,
                    390:         * and multiply by a scale factor of 128.
                    391:         *
                    392:         * We can accomplish the same thing by simplifying and using
                    393:         * shifts, being careful to avoid as much loss of precision
                    394:         * as possible.  (If the sum exceeds UINT_MAX/10000, we need
                    395:         * to rearrange the calculation slightly to do this.)
                    396:         */
                    397:        if (sum > (UINT_MAX / 10000))   /* This is a _fast_ machine! */
                    398:                delay_factor = (((sum >> 3) * 10000) / CLK_RATE) >> 3;
                    399:        else
                    400:                delay_factor = (((sum * 10000) >> 3) / CLK_RATE) >> 3;
                    401:
                    402:        /* Reset the delay_flag for normal use */
                    403:        delay_flag = 1;
                    404:
                    405: #ifdef DEBUG
                    406:        if (clock_debug)
                    407:                printf("mac68k_calibrate_delay(): delay_factor calibrated\n");
                    408: #endif
                    409: }

CVSweb