|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.