FreeBSD/Linux Kernel Cross Reference
sys/i386at/rtc.c
1 /*
2 * Mach Operating System
3 * Copyright (c) 1991,1990,1989 Carnegie Mellon University
4 * All Rights Reserved.
5 *
6 * Permission to use, copy, modify and distribute this software and its
7 * documentation is hereby granted, provided that both the copyright
8 * notice and this permission notice appear in all copies of the
9 * software, derivative works or modified versions, and any portions
10 * thereof, and that both notices appear in supporting documentation.
11 *
12 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
13 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
14 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
15 *
16 * Carnegie Mellon requests users of this software to return to
17 *
18 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
19 * School of Computer Science
20 * Carnegie Mellon University
21 * Pittsburgh PA 15213-3890
22 *
23 * any improvements or extensions that they make and grant Carnegie Mellon
24 * the rights to redistribute these changes.
25 */
26 /*
27 * HISTORY
28 * $Log: rtc.c,v $
29 * Revision 2.10 93/05/15 19:32:50 mrt
30 * machparam.h -> machspl.h
31 *
32 * Revision 2.9 93/05/10 17:47:35 rvb
33 * Let's not use time_t in the kernel.
34 * [93/05/04 17:37:13 rvb]
35 *
36 * Revision 2.8 93/01/14 17:31:46 danner
37 * Proper spl typing.
38 * [92/11/30 af]
39 *
40 * Revision 2.7 92/03/04 10:50:21 rpd
41 * Well, writetodc() is broken for after leapday on leapyears,
42 * till Jan 1 the next year.
43 * [92/03/03 rvb]
44 *
45 * Revision 2.6 91/05/14 16:29:48 mrt
46 * Correcting copyright
47 *
48 * Revision 2.5 91/02/05 17:20:21 mrt
49 * Changed to new Mach copyright
50 * [91/02/01 17:47:09 mrt]
51 *
52 * Revision 2.4 90/11/26 14:51:00 rvb
53 * jsb bet me to XMK34, sigh ...
54 * [90/11/26 rvb]
55 * Synched 2.5 & 3.0 at I386q (r1.5.1.3) & XMK35 (r2.4)
56 * [90/11/15 rvb]
57 *
58 * Revision 1.5.1.2 90/07/27 11:27:01 rvb
59 * Fix Intel Copyright as per B. Davies authorization.
60 * [90/07/27 rvb]
61 *
62 * Revision 2.2 90/05/03 15:46:00 dbg
63 * Converted for pure kernel.
64 * [90/02/20 dbg]
65 *
66 * Revision 1.5.1.1 90/01/08 13:29:51 rvb
67 * Add Intel copyright.
68 * [90/01/08 rvb]
69 *
70 * Revision 1.5 89/09/25 12:27:28 rvb
71 * File was provided by Intel 9/18/89.
72 * [89/09/23 rvb]
73 *
74 */
75
76 /*
77 Copyright 1988, 1989 by Intel Corporation, Santa Clara, California.
78
79 All Rights Reserved
80
81 Permission to use, copy, modify, and distribute this software and
82 its documentation for any purpose and without fee is hereby
83 granted, provided that the above copyright notice appears in all
84 copies and that both the copyright notice and this permission notice
85 appear in supporting documentation, and that the name of Intel
86 not be used in advertising or publicity pertaining to distribution
87 of the software without specific, written prior permission.
88
89 INTEL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
90 INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
91 IN NO EVENT SHALL INTEL BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
92 CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
93 LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
94 NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
95 WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
96 */
97
98 #include <sys/types.h>
99 #ifdef MACH_KERNEL
100 #include <kern/time_out.h>
101 #include <sys/time.h>
102 #else MACH_KERNEL
103 #include <sys/param.h>
104 #include <sys/kernel.h>
105 #endif MACH_KERNEL
106 #include <i386/machspl.h>
107 #include <i386at/rtc.h>
108
109 static unsigned char rtc[RTC_NREG];
110 static int first_rtcopen_ever = 1;
111
112 rtcinit()
113 {
114 outb(RTC_ADDR, RTC_A);
115 outb(RTC_DATA, RTC_DIV2 | RTC_RATE6);
116 outb(RTC_ADDR, RTC_B);
117 outb(RTC_DATA, RTC_HM);
118 }
119
120
121 int
122 rtcget(regs)
123 unsigned char *regs;
124 {
125 if (first_rtcopen_ever) {
126 rtcinit();
127 first_rtcopen_ever = 0;
128 }
129 outb(RTC_ADDR, RTC_D);
130 if (inb(RTC_DATA) & RTC_VRT == 0) return(-1);
131 outb(RTC_ADDR, RTC_A);
132 while (inb(RTC_DATA) & RTC_UIP) /* busy wait */
133 outb(RTC_ADDR, RTC_A);
134 load_rtc(regs);
135 return(0);
136 }
137
138 rtcput(regs)
139 unsigned char *regs;
140 {
141 register unsigned char x;
142
143 if (first_rtcopen_ever) {
144 rtcinit();
145 first_rtcopen_ever = 0;
146 }
147 outb(RTC_ADDR, RTC_B);
148 x = inb(RTC_DATA);
149 outb(RTC_ADDR, RTC_B);
150 outb(RTC_DATA, x | RTC_SET);
151 save_rtc(regs);
152 outb(RTC_ADDR, RTC_B);
153 outb(RTC_DATA, x & ~RTC_SET);
154 }
155
156
157 extern struct timeval time;
158 extern struct timezone tz;
159
160 static int month[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
161
162 yeartoday(year)
163 int year;
164 {
165 return((year%4) ? 365 : 366);
166 }
167
168 hexdectodec(n)
169 char n;
170 {
171 return(((n>>4)&0x0F)*10 + (n&0x0F));
172 }
173
174 char
175 dectohexdec(n)
176 int n;
177 {
178 return((char)(((n/10)<<4)&0xF0) | ((n%10)&0x0F));
179 }
180
181
182 readtodc(tp)
183 u_int *tp;
184 {
185 struct rtc_st rtclk;
186 time_t n;
187 int sec, min, hr, dom, mon, yr;
188 int i, days = 0;
189 spl_t ospl;
190
191 #ifdef MACH_KERNEL
192 ospl = splclock();
193 #else MACH_KERNEL
194 ospl = spl5();
195 #endif MACH_KERNEL
196 if (rtcget(&rtclk)) {
197 splx(ospl);
198 return(-1);
199 }
200 splx (ospl);
201
202 sec = hexdectodec(rtclk.rtc_sec);
203 min = hexdectodec(rtclk.rtc_min);
204 hr = hexdectodec(rtclk.rtc_hr);
205 dom = hexdectodec(rtclk.rtc_dom);
206 mon = hexdectodec(rtclk.rtc_mon);
207 yr = hexdectodec(rtclk.rtc_yr);
208 yr = (yr < 70) ? yr+100 : yr;
209
210 n = sec + 60 * min + 3600 * hr;
211 n += (dom - 1) * 3600 * 24;
212
213 if (yeartoday(yr) == 366)
214 month[1] = 29;
215 for (i = mon - 2; i >= 0; i--)
216 days += month[i];
217 month[1] = 28;
218 for (i = 70; i < yr; i++)
219 days += yeartoday(i);
220 n += days * 3600 * 24;
221
222 #ifdef MACH_KERNEL
223 #else MACH_KERNEL
224 n += tz.tz_minuteswest * 60;
225 if (tz.tz_dsttime)
226 n -= 3600;
227 #endif MACH_KERNEL
228
229 *tp = n;
230
231 return(0);
232 }
233
234 writetodc()
235 {
236 struct rtc_st rtclk;
237 time_t n;
238 int diff, i, j;
239 spl_t ospl;
240
241 #ifdef MACH_KERNEL
242 ospl = splclock();
243 #else MACH_KERNEL
244 ospl = spl5();
245 #endif MACH_KERNEL
246 if (rtcget(&rtclk)) {
247 splx(ospl);
248 return(-1);
249 }
250 splx(ospl);
251
252 #ifdef MACH_KERNEL
253 diff = 0;
254 #else MACH_KERNEL
255 diff = tz.tz_minuteswest * 60;
256 if (tz.tz_dsttime)
257 diff -= 3600;
258 #endif MACH_KERNEL
259 n = (time.tv_sec - diff) % (3600 * 24); /* hrs+mins+secs */
260 rtclk.rtc_sec = dectohexdec(n%60);
261 n /= 60;
262 rtclk.rtc_min = dectohexdec(n%60);
263 rtclk.rtc_hr = dectohexdec(n/60);
264
265 n = (time.tv_sec - diff) / (3600 * 24); /* days */
266 rtclk.rtc_dow = (n + 4) % 7; /* 1/1/70 is Thursday */
267
268 for (j = 1970, i = yeartoday(j); n >= i; j++, i = yeartoday(j))
269 n -= i;
270
271 rtclk.rtc_yr = dectohexdec(j - 1900);
272
273 if (i == 366)
274 month[1] = 29;
275 for (i = 0; n >= month[i]; i++)
276 n -= month[i];
277 month[1] = 28;
278 rtclk.rtc_mon = dectohexdec(++i);
279
280 rtclk.rtc_dom = dectohexdec(++n);
281
282 #ifdef MACH_KERNEL
283 ospl = splclock();
284 #else MACH_KERNEL
285 ospl = spl5();
286 #endif MACH_KERNEL
287 rtcput(&rtclk);
288 splx(ospl);
289
290 return(0);
291 }
Cache object: c967c80fc157c7c7a5c81fefa35ed371
|