]>
git.saurik.com Git - apple/xnu.git/blob - osfmk/i386/AT386/bbclock.c
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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.
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
20 * @APPLE_LICENSE_HEADER_END@
26 Copyright 1988, 1989 by Intel Corporation, Santa Clara, California.
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.
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.
48 #include <mach/message.h>
49 #include <kern/thread.h>
50 #include <kern/clock.h>
52 #include <kern/processor.h>
53 #include <kern/misc_protos.h>
54 #include <i386/cpu_data.h>
55 #include <i386/cpu_number.h>
57 #include <i386/AT386/rtc.h>
58 #include <i386/AT386/bbclock_entries.h>
61 static int month
[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
63 extern char dectohexdec(
65 extern int hexdectodec(
70 struct rtc_st
* regs
);
72 struct rtc_st
* regs
);
74 #define LOCK_BBC() splclock()
75 #define UNLOCK_BBC(s) splx(s)
78 * Configure battery-backed clock.
86 mp_disable_preemption();
87 if (cpu_number() != master_cpu
) {
88 mp_enable_preemption();
95 outb(RTC_ADDR
, RTC_A
);
96 outb(RTC_DATA
, RTC_DIV2
| RTC_RATE6
);
97 outb(RTC_ADDR
, RTC_B
);
98 outb(RTC_DATA
, RTC_HM
);
101 * Probe the device by trying to read it.
103 BbcFlag
= (rtcget(&rtclk
) ? 0 : 1);
105 printf("battery clock configured\n");
107 printf("WARNING: Battery Clock Failure!\n");
108 mp_enable_preemption();
113 * Get the current clock time.
117 mach_timespec_t
*cur_time
) /* OUT */
121 int sec
, min
, hr
, dom
, mon
, yr
;
126 if ((thread
= current_thread()) != THREAD_NULL
) {
127 thread_bind(thread
, master_processor
);
128 mp_disable_preemption();
129 if (current_processor() != master_processor
) {
130 mp_enable_preemption();
131 thread_block(THREAD_CONTINUE_NULL
);
133 mp_enable_preemption();
139 sec
= hexdectodec(rtclk
.rtc_sec
);
140 min
= hexdectodec(rtclk
.rtc_min
);
141 hr
= hexdectodec(rtclk
.rtc_hr
);
142 dom
= hexdectodec(rtclk
.rtc_dom
);
143 mon
= hexdectodec(rtclk
.rtc_mon
);
144 yr
= hexdectodec(rtclk
.rtc_yr
);
145 yr
= (yr
< 70) ? yr
+100 : yr
;
146 n
= sec
+ 60 * min
+ 3600 * hr
;
147 n
+= (dom
- 1) * 3600 * 24;
148 if (yeartoday(yr
) == 366)
150 for (i
= mon
- 2; i
>= 0; i
--)
153 for (i
= 70; i
< yr
; i
++)
154 days
+= yeartoday(i
);
155 n
+= days
* 3600 * 24;
156 cur_time
->tv_sec
= n
;
157 cur_time
->tv_nsec
= 0;
160 if (thread
!= THREAD_NULL
)
161 thread_bind(thread
, PROCESSOR_NULL
);
162 return (KERN_SUCCESS
);
166 * Set the current clock time.
170 mach_timespec_t
*new_time
)
178 if ((thread
= current_thread()) != THREAD_NULL
) {
179 thread_bind(thread
, master_processor
);
180 mp_disable_preemption();
181 if (current_processor() != master_processor
) {
182 mp_enable_preemption();
183 thread_block(THREAD_CONTINUE_NULL
);
185 mp_enable_preemption();
192 n
= (new_time
->tv_sec
- diff
) % (3600 * 24); /* hrs+mins+secs */
193 rtclk
.rtc_sec
= dectohexdec(n%60
);
195 rtclk
.rtc_min
= dectohexdec(n%60
);
196 rtclk
.rtc_hr
= dectohexdec(n
/60);
197 n
= (new_time
->tv_sec
- diff
) / (3600 * 24); /* days */
198 rtclk
.rtc_dow
= (n
+ 4) % 7; /* 1/1/70 is Thursday */
199 for (j
= 70; n
>= (i
= yeartoday(j
)); j
++)
201 rtclk
.rtc_yr
= dectohexdec(j
% 100);
202 if (yeartoday(j
) == 366)
204 for (i
= 0; n
>= month
[i
]; i
++)
207 rtclk
.rtc_mon
= dectohexdec(++i
);
208 rtclk
.rtc_dom
= dectohexdec(++n
);
212 if (thread
!= THREAD_NULL
)
213 thread_bind(current_thread(), PROCESSOR_NULL
);
215 return (KERN_SUCCESS
);
219 /* DEVICE SPECIFIC ROUTINES */
223 struct rtc_st
* regs
)
225 outb(RTC_ADDR
, RTC_D
);
226 if ((inb(RTC_DATA
) & RTC_VRT
) == 0)
228 outb(RTC_ADDR
, RTC_A
);
229 while (inb(RTC_DATA
) & RTC_UIP
) /* busy wait */
230 outb(RTC_ADDR
, RTC_A
);
231 load_rtc((unsigned char *)regs
);
237 struct rtc_st
* regs
)
239 register unsigned char x
;
241 outb(RTC_ADDR
, RTC_B
);
243 outb(RTC_ADDR
, RTC_B
);
244 outb(RTC_DATA
, x
| RTC_SET
);
245 save_rtc((unsigned char *)regs
);
246 outb(RTC_ADDR
, RTC_B
);
247 outb(RTC_DATA
, x
& ~RTC_SET
);
255 return((year
% 4) ? 365 :
256 ((year
% 100) ? 366 : ((year
% 400) ? 365: 366)));
263 return ((((n
>> 4) & 0x0F) * 10) + (n
& 0x0F));
270 return ((char)(((n
/ 10) << 4) & 0xF0) | ((n
% 10) & 0x0F));