Annotation of XNU/osfmk/i386/AT386/bbclock.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
                      3:  *
                      4:  * @APPLE_LICENSE_HEADER_START@
                      5:  * 
                      6:  * The contents of this file constitute Original Code as defined in and
                      7:  * are subject to the Apple Public Source License Version 1.1 (the
                      8:  * "License").  You may not use this file except in compliance with the
                      9:  * License.  Please obtain a copy of the License at
                     10:  * http://www.apple.com/publicsource and read it before using this file.
                     11:  * 
                     12:  * This Original Code and all software distributed under the License are
                     13:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
                     14:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
                     15:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
                     16:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
                     17:  * License for the specific language governing rights and limitations
                     18:  * under the License.
                     19:  * 
                     20:  * @APPLE_LICENSE_HEADER_END@
                     21:  */
                     22: /*
                     23:  * @OSF_COPYRIGHT@
                     24:  */
                     25: /*
                     26:   Copyright 1988, 1989 by Intel Corporation, Santa Clara, California.
                     27: 
                     28:                All Rights Reserved
                     29: 
                     30: Permission to use, copy, modify, and distribute this software and
                     31: its documentation for any purpose and without fee is hereby
                     32: granted, provided that the above copyright notice appears in all
                     33: copies and that both the copyright notice and this permission notice
                     34: appear in supporting documentation, and that the name of Intel
                     35: not be used in advertising or publicity pertaining to distribution
                     36: of the software without specific, written prior permission.
                     37: 
                     38: INTEL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
                     39: INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
                     40: IN NO EVENT SHALL INTEL BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
                     41: CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
                     42: LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
                     43: NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
                     44: WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
                     45: */
                     46: 
                     47: #include <types.h>
                     48: #include <mach/message.h>
                     49: #include <kern/thread.h>
                     50: #include <kern/clock.h>
                     51: #include <kern/spl.h>
                     52: #include <kern/processor.h>
                     53: #include <kern/misc_protos.h>
                     54: #include <i386/pio.h>
                     55: #include <i386/AT386/rtc.h>
                     56: #include <i386/AT386/bbclock_entries.h>
                     57: 
                     58: /* local data */
                     59: static int     month[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
                     60: 
                     61: extern char    dectohexdec(
                     62:                        int                     n);
                     63: extern int     hexdectodec(
                     64:                        char                    c);
                     65: extern int     yeartoday(
                     66:                        int                     yr);
                     67: extern void    rtcput(
                     68:                        struct rtc_st           * regs);
                     69: extern int     rtcget(
                     70:                        struct rtc_st           * regs);
                     71: 
                     72: #define        LOCK_BBC()      splclock()
                     73: #define        UNLOCK_BBC(s)   splx(s)
                     74: 
                     75: /*
                     76:  * Configure battery-backed clock.
                     77:  */
                     78: int
                     79: bbc_config(void)
                     80: {
                     81:        int             BbcFlag;
                     82:        struct rtc_st   rtclk;
                     83: 
                     84: #if    NCPUS > 1 && AT386
                     85:        mp_disable_preemption();
                     86:        if (cpu_number() != master_cpu) {
                     87:                mp_enable_preemption();
                     88:                return(1);
                     89:        }
                     90: #endif
                     91:        /*
                     92:         * Setup device.
                     93:         */
                     94:        outb(RTC_ADDR, RTC_A);
                     95:        outb(RTC_DATA, RTC_DIV2 | RTC_RATE6);
                     96:        outb(RTC_ADDR, RTC_B);
                     97:        outb(RTC_DATA, RTC_HM);
                     98: 
                     99:        /*
                    100:         * Probe the device by trying to read it.
                    101:         */
                    102:        BbcFlag = (rtcget(&rtclk) ? 0 : 1);
                    103:        if (BbcFlag)
                    104:                printf("battery clock configured\n");
                    105:        else
                    106:                printf("WARNING: Battery Clock Failure!\n");
                    107: #if    NCPUS > 1 && AT386
                    108:        mp_enable_preemption();
                    109: #endif
                    110:        return (BbcFlag);
                    111: }
                    112: 
                    113: /*
                    114:  * Get the current clock time.
                    115:  */
                    116: kern_return_t
                    117: bbc_gettime(
                    118:        mach_timespec_t *cur_time)      /* OUT */
                    119: {
                    120:        struct rtc_st   rtclk;
                    121:        time_t          n;
                    122:        int             sec, min, hr, dom, mon, yr;
                    123:        int             i, days = 0;
                    124:        spl_t           s;
                    125:        thread_t        thread;
                    126: 
                    127: #if    NCPUS > 1 && AT386
                    128:        if ((thread = current_thread()) != THREAD_NULL) {
                    129:                thread_bind(thread, master_processor);
                    130:                mp_disable_preemption();
                    131:                if (current_processor() != master_processor) {
                    132:                        mp_enable_preemption();
                    133:                        thread_block((void (*)) 0);
                    134:                } else {
                    135:                        mp_enable_preemption();
                    136:                }
                    137:        }
                    138: #endif
                    139:        s = LOCK_BBC();
                    140:        rtcget(&rtclk);
                    141:        sec = hexdectodec(rtclk.rtc_sec);
                    142:        min = hexdectodec(rtclk.rtc_min);
                    143:        hr = hexdectodec(rtclk.rtc_hr);
                    144:        dom = hexdectodec(rtclk.rtc_dom);
                    145:        mon = hexdectodec(rtclk.rtc_mon);
                    146:        yr = hexdectodec(rtclk.rtc_yr);
                    147:        yr = (yr < 70) ? yr+100 : yr;
                    148:        n = sec + 60 * min + 3600 * hr;
                    149:        n += (dom - 1) * 3600 * 24;
                    150:        if (yeartoday(yr) == 366)
                    151:                month[1] = 29;
                    152:        for (i = mon - 2; i >= 0; i--)
                    153:                days += month[i];
                    154:        month[1] = 28;
                    155:        for (i = 70; i < yr; i++)
                    156:                days += yeartoday(i);
                    157:        n += days * 3600 * 24;
                    158:        cur_time->tv_sec  = n;
                    159:        cur_time->tv_nsec = 0;
                    160:        UNLOCK_BBC(s);
                    161: 
                    162: #if    NCPUS > 1 && AT386
                    163:        if (thread != THREAD_NULL)
                    164:                thread_bind(thread, PROCESSOR_NULL);
                    165: #endif
                    166:        return (KERN_SUCCESS);
                    167: }
                    168: 
                    169: /*
                    170:  * Set the current clock time.
                    171:  */
                    172: kern_return_t
                    173: bbc_settime(
                    174:        mach_timespec_t *new_time)
                    175: {
                    176:        struct rtc_st   rtclk;
                    177:        time_t          n;
                    178:        int             diff, i, j;
                    179:        spl_t           s;
                    180:        thread_t        thread;
                    181: 
                    182: #if    NCPUS > 1 && AT386
                    183:        if ((thread = current_thread()) != THREAD_NULL) {
                    184:                thread_bind(thread, master_processor);
                    185:                mp_disable_preemption();
                    186:                if (current_processor() != master_processor) {
                    187:                        mp_enable_preemption();
                    188:                        thread_block((void (*)) 0);
                    189:                } else { 
                    190:                        mp_enable_preemption();
                    191:                }
                    192:        }
                    193: #endif
                    194:        s = LOCK_BBC();
                    195:        rtcget(&rtclk);
                    196:        diff = 0;
                    197:        n = (new_time->tv_sec - diff) % (3600 * 24);   /* hrs+mins+secs */
                    198:        rtclk.rtc_sec = dectohexdec(n%60);
                    199:        n /= 60;
                    200:        rtclk.rtc_min = dectohexdec(n%60);
                    201:        rtclk.rtc_hr = dectohexdec(n/60);
                    202:        n = (new_time->tv_sec - diff) / (3600 * 24);    /* days */
                    203:        rtclk.rtc_dow = (n + 4) % 7;  /* 1/1/70 is Thursday */
                    204:        for (j = 1970; n >= (i = yeartoday(j)); j++)
                    205:                n -= i;
                    206:        rtclk.rtc_yr = dectohexdec(j % 100);
                    207:        if (yeartoday(j) == 366)
                    208:                month[1] = 29;
                    209:        for (i = 0; n >= month[i]; i++)
                    210:                n -= month[i];
                    211:        month[1] = 28;
                    212:        rtclk.rtc_mon = dectohexdec(++i);
                    213:        rtclk.rtc_dom = dectohexdec(++n);
                    214:        rtcput(&rtclk);
                    215:        UNLOCK_BBC(s);
                    216: 
                    217: #if    NCPUS > 1 && AT386
                    218:        if (thread != THREAD_NULL)
                    219:                thread_bind(current_thread(), PROCESSOR_NULL);
                    220: #endif
                    221:        return (KERN_SUCCESS);
                    222: }
                    223: 
                    224: /*
                    225:  * Get clock device attributes.
                    226:  */
                    227: kern_return_t
                    228: bbc_getattr(
                    229:        clock_flavor_t          flavor,
                    230:        clock_attr_t            attr,           /* OUT */
                    231:        mach_msg_type_number_t  *count)         /* IN/OUT */
                    232: {
                    233:        if (*count != 1)
                    234:                return (KERN_FAILURE);
                    235:        switch (flavor) {
                    236: 
                    237:        case CLOCK_GET_TIME_RES:        /* >0 res */
                    238:                *(clock_res_t *) attr = NSEC_PER_SEC;
                    239:                break;
                    240: 
                    241:        case CLOCK_ALARM_CURRES:        /* =0 no alarm */
                    242:        case CLOCK_ALARM_MINRES:
                    243:        case CLOCK_ALARM_MAXRES:
                    244:                *(clock_res_t *) attr = 0;
                    245:                break;
                    246: 
                    247:        default:
                    248:                return (KERN_INVALID_VALUE);
                    249:        }
                    250:        return (KERN_SUCCESS);
                    251: }
                    252: 
                    253: 
                    254: /* DEVICE SPECIFIC ROUTINES */
                    255: 
                    256: int
                    257: rtcget(
                    258:        struct rtc_st   * regs)
                    259: {
                    260:        outb(RTC_ADDR, RTC_D); 
                    261:        if (inb(RTC_DATA) & RTC_VRT == 0)
                    262:                return (-1);
                    263:        outb(RTC_ADDR, RTC_A);  
                    264:        while (inb(RTC_DATA) & RTC_UIP)         /* busy wait */
                    265:                outb(RTC_ADDR, RTC_A);  
                    266:        load_rtc((unsigned char *)regs);
                    267:        return (0);
                    268: }      
                    269: 
                    270: void
                    271: rtcput(
                    272:        struct rtc_st   * regs)
                    273: {
                    274:        register unsigned char  x;
                    275: 
                    276:        outb(RTC_ADDR, RTC_B);
                    277:        x = inb(RTC_DATA);
                    278:        outb(RTC_ADDR, RTC_B);
                    279:        outb(RTC_DATA, x | RTC_SET);    
                    280:        save_rtc((unsigned char *)regs);
                    281:        outb(RTC_ADDR, RTC_B);
                    282:        outb(RTC_DATA, x & ~RTC_SET); 
                    283: }
                    284: 
                    285: int
                    286: yeartoday(
                    287:        int     year)
                    288: {
                    289:        return((year % 4) ? 365 :
                    290:               ((year % 100) ? 366 : ((year % 400) ? 365: 366)));
                    291: }
                    292: 
                    293: int
                    294: hexdectodec(
                    295:        char    n)
                    296: {
                    297:        return ((((n >> 4) & 0x0F) * 10) + (n & 0x0F));
                    298: }
                    299: 
                    300: char
                    301: dectohexdec(
                    302:        int     n)
                    303: {
                    304:        return ((char)(((n / 10) << 4) & 0xF0) | ((n % 10) & 0x0F));
                    305: }

unix.superglobalmegacorp.com

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