|
|
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.