]>
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 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
23 * @APPLE_LICENSE_HEADER_END@
29 Copyright 1988, 1989 by Intel Corporation, Santa Clara, California.
33 Permission to use, copy, modify, and distribute this software and
34 its documentation for any purpose and without fee is hereby
35 granted, provided that the above copyright notice appears in all
36 copies and that both the copyright notice and this permission notice
37 appear in supporting documentation, and that the name of Intel
38 not be used in advertising or publicity pertaining to distribution
39 of the software without specific, written prior permission.
41 INTEL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
42 INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
43 IN NO EVENT SHALL INTEL BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
44 CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
45 LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
46 NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
47 WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
51 #include <mach/message.h>
52 #include <kern/thread.h>
53 #include <kern/clock.h>
55 #include <kern/processor.h>
56 #include <kern/misc_protos.h>
58 #include <i386/AT386/rtc.h>
59 #include <i386/AT386/bbclock_entries.h>
62 static int month
[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
64 extern char dectohexdec(
66 extern int hexdectodec(
71 struct rtc_st
* regs
);
73 struct rtc_st
* regs
);
75 #define LOCK_BBC() splclock()
76 #define UNLOCK_BBC(s) splx(s)
79 * Configure battery-backed clock.
87 #if NCPUS > 1 && AT386
88 mp_disable_preemption();
89 if (cpu_number() != master_cpu
) {
90 mp_enable_preemption();
97 outb(RTC_ADDR
, RTC_A
);
98 outb(RTC_DATA
, RTC_DIV2
| RTC_RATE6
);
99 outb(RTC_ADDR
, RTC_B
);
100 outb(RTC_DATA
, RTC_HM
);
103 * Probe the device by trying to read it.
105 BbcFlag
= (rtcget(&rtclk
) ? 0 : 1);
107 printf("battery clock configured\n");
109 printf("WARNING: Battery Clock Failure!\n");
110 #if NCPUS > 1 && AT386
111 mp_enable_preemption();
117 * Get the current clock time.
121 mach_timespec_t
*cur_time
) /* OUT */
125 int sec
, min
, hr
, dom
, mon
, yr
;
130 #if NCPUS > 1 && AT386
131 if ((thread
= current_thread()) != THREAD_NULL
) {
132 thread_bind(thread
, master_processor
);
133 mp_disable_preemption();
134 if (current_processor() != master_processor
) {
135 mp_enable_preemption();
136 thread_block(THREAD_CONTINUE_NULL
);
138 mp_enable_preemption();
144 sec
= hexdectodec(rtclk
.rtc_sec
);
145 min
= hexdectodec(rtclk
.rtc_min
);
146 hr
= hexdectodec(rtclk
.rtc_hr
);
147 dom
= hexdectodec(rtclk
.rtc_dom
);
148 mon
= hexdectodec(rtclk
.rtc_mon
);
149 yr
= hexdectodec(rtclk
.rtc_yr
);
150 yr
= (yr
< 70) ? yr
+100 : yr
;
151 n
= sec
+ 60 * min
+ 3600 * hr
;
152 n
+= (dom
- 1) * 3600 * 24;
153 if (yeartoday(yr
) == 366)
155 for (i
= mon
- 2; i
>= 0; i
--)
158 for (i
= 70; i
< yr
; i
++)
159 days
+= yeartoday(i
);
160 n
+= days
* 3600 * 24;
161 cur_time
->tv_sec
= n
;
162 cur_time
->tv_nsec
= 0;
165 #if NCPUS > 1 && AT386
166 if (thread
!= THREAD_NULL
)
167 thread_bind(thread
, PROCESSOR_NULL
);
169 return (KERN_SUCCESS
);
173 * Set the current clock time.
177 mach_timespec_t
*new_time
)
185 #if NCPUS > 1 && AT386
186 if ((thread
= current_thread()) != THREAD_NULL
) {
187 thread_bind(thread
, master_processor
);
188 mp_disable_preemption();
189 if (current_processor() != master_processor
) {
190 mp_enable_preemption();
191 thread_block(THREAD_CONTINUE_NULL
);
193 mp_enable_preemption();
200 n
= (new_time
->tv_sec
- diff
) % (3600 * 24); /* hrs+mins+secs */
201 rtclk
.rtc_sec
= dectohexdec(n%60
);
203 rtclk
.rtc_min
= dectohexdec(n%60
);
204 rtclk
.rtc_hr
= dectohexdec(n
/60);
205 n
= (new_time
->tv_sec
- diff
) / (3600 * 24); /* days */
206 rtclk
.rtc_dow
= (n
+ 4) % 7; /* 1/1/70 is Thursday */
207 for (j
= 1970; n
>= (i
= yeartoday(j
)); j
++)
209 rtclk
.rtc_yr
= dectohexdec(j
% 100);
210 if (yeartoday(j
) == 366)
212 for (i
= 0; n
>= month
[i
]; i
++)
215 rtclk
.rtc_mon
= dectohexdec(++i
);
216 rtclk
.rtc_dom
= dectohexdec(++n
);
220 #if NCPUS > 1 && AT386
221 if (thread
!= THREAD_NULL
)
222 thread_bind(current_thread(), PROCESSOR_NULL
);
224 return (KERN_SUCCESS
);
228 * Get clock device attributes.
232 clock_flavor_t flavor
,
233 clock_attr_t attr
, /* OUT */
234 mach_msg_type_number_t
*count
) /* IN/OUT */
237 return (KERN_FAILURE
);
240 case CLOCK_GET_TIME_RES
: /* >0 res */
241 *(clock_res_t
*) attr
= NSEC_PER_SEC
;
244 case CLOCK_ALARM_CURRES
: /* =0 no alarm */
245 case CLOCK_ALARM_MINRES
:
246 case CLOCK_ALARM_MAXRES
:
247 *(clock_res_t
*) attr
= 0;
251 return (KERN_INVALID_VALUE
);
253 return (KERN_SUCCESS
);
257 /* DEVICE SPECIFIC ROUTINES */
261 struct rtc_st
* regs
)
263 outb(RTC_ADDR
, RTC_D
);
264 if (inb(RTC_DATA
) & RTC_VRT
== 0)
266 outb(RTC_ADDR
, RTC_A
);
267 while (inb(RTC_DATA
) & RTC_UIP
) /* busy wait */
268 outb(RTC_ADDR
, RTC_A
);
269 load_rtc((unsigned char *)regs
);
275 struct rtc_st
* regs
)
277 register unsigned char x
;
279 outb(RTC_ADDR
, RTC_B
);
281 outb(RTC_ADDR
, RTC_B
);
282 outb(RTC_DATA
, x
| RTC_SET
);
283 save_rtc((unsigned char *)regs
);
284 outb(RTC_ADDR
, RTC_B
);
285 outb(RTC_DATA
, x
& ~RTC_SET
);
293 return((year
% 4) ? 365 :
294 ((year
% 100) ? 366 : ((year
% 400) ? 365: 366)));
301 return ((((n
>> 4) & 0x0F) * 10) + (n
& 0x0F));
308 return ((char)(((n
/ 10) << 4) & 0xF0) | ((n
% 10) & 0x0F));