]>
git.saurik.com Git - apple/xnu.git/blob - osfmk/i386/AT386/bbclock.c
9bad06a133c93dc80cee1cd892559c07e927d093
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>
55 #include <i386/AT386/rtc.h>
56 #include <i386/AT386/bbclock_entries.h>
59 static int month
[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
61 extern char dectohexdec(
63 extern int hexdectodec(
68 struct rtc_st
* regs
);
70 struct rtc_st
* regs
);
72 #define LOCK_BBC() splclock()
73 #define UNLOCK_BBC(s) splx(s)
76 * Configure battery-backed clock.
84 #if NCPUS > 1 && AT386
85 mp_disable_preemption();
86 if (cpu_number() != master_cpu
) {
87 mp_enable_preemption();
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
);
100 * Probe the device by trying to read it.
102 BbcFlag
= (rtcget(&rtclk
) ? 0 : 1);
104 printf("battery clock configured\n");
106 printf("WARNING: Battery Clock Failure!\n");
107 #if NCPUS > 1 && AT386
108 mp_enable_preemption();
114 * Get the current clock time.
118 mach_timespec_t
*cur_time
) /* OUT */
122 int sec
, min
, hr
, dom
, mon
, yr
;
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);
135 mp_enable_preemption();
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)
152 for (i
= mon
- 2; i
>= 0; i
--)
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;
162 #if NCPUS > 1 && AT386
163 if (thread
!= THREAD_NULL
)
164 thread_bind(thread
, PROCESSOR_NULL
);
166 return (KERN_SUCCESS
);
170 * Set the current clock time.
174 mach_timespec_t
*new_time
)
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);
190 mp_enable_preemption();
197 n
= (new_time
->tv_sec
- diff
) % (3600 * 24); /* hrs+mins+secs */
198 rtclk
.rtc_sec
= dectohexdec(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
++)
206 rtclk
.rtc_yr
= dectohexdec(j
% 100);
207 if (yeartoday(j
) == 366)
209 for (i
= 0; n
>= month
[i
]; i
++)
212 rtclk
.rtc_mon
= dectohexdec(++i
);
213 rtclk
.rtc_dom
= dectohexdec(++n
);
217 #if NCPUS > 1 && AT386
218 if (thread
!= THREAD_NULL
)
219 thread_bind(current_thread(), PROCESSOR_NULL
);
221 return (KERN_SUCCESS
);
225 * Get clock device attributes.
229 clock_flavor_t flavor
,
230 clock_attr_t attr
, /* OUT */
231 mach_msg_type_number_t
*count
) /* IN/OUT */
234 return (KERN_FAILURE
);
237 case CLOCK_GET_TIME_RES
: /* >0 res */
238 *(clock_res_t
*) attr
= NSEC_PER_SEC
;
241 case CLOCK_ALARM_CURRES
: /* =0 no alarm */
242 case CLOCK_ALARM_MINRES
:
243 case CLOCK_ALARM_MAXRES
:
244 *(clock_res_t
*) attr
= 0;
248 return (KERN_INVALID_VALUE
);
250 return (KERN_SUCCESS
);
254 /* DEVICE SPECIFIC ROUTINES */
258 struct rtc_st
* regs
)
260 outb(RTC_ADDR
, RTC_D
);
261 if (inb(RTC_DATA
) & RTC_VRT
== 0)
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
);
272 struct rtc_st
* regs
)
274 register unsigned char x
;
276 outb(RTC_ADDR
, RTC_B
);
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
);
290 return((year
% 4) ? 365 :
291 ((year
% 100) ? 366 : ((year
% 400) ? 365: 366)));
298 return ((((n
>> 4) & 0x0F) * 10) + (n
& 0x0F));
305 return ((char)(((n
/ 10) << 4) & 0xF0) | ((n
% 10) & 0x0F));