|
|
1.1 root 1: /*
2: * Mach Operating System
3: * Copyright (c) 1991,1990 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 [email protected]
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: * File: mc_clock.c
28: * Author: Alessandro Forin
29: * Date: 8/90
30: *
31: * Driver for the MC146818 Clock
32: */
33:
34: #include <mc.h>
35: #if NMC > 0
36: #include <platforms.h>
37:
38: #include <mach/std_types.h>
39: #include <machine/machspl.h> /* spl definitions */
40: #include <chips/busses.h>
41:
42: #include <sys/time.h>
43: #include <kern/time_out.h>
44: #include <chips/mc_clock.h>
45:
46: #ifdef DECSTATION
47: #include <mips/mips_cpu.h>
48: #include <mips/clock.h>
49: #endif /*DECSTATION*/
50:
51: #ifdef FLAMINGO
52: #include <alpha/clock.h>
53: #endif /*FLAMINGO*/
54:
55: #define private static
56: #define public
57:
58:
59: /* Architecture-specific defines */
60:
61: #ifdef DECSTATION
62:
63: #define MC_DEFAULT_ADDRESS (mc_clock_ram_t *)PHYS_TO_K1SEG(0x1d000000)
64: #define MC_DOES_DELAYS 1
65:
66: /*
67: * Both the Pmax and the 3max implementations of the chip map
68: * bytes of the chip's RAM to 32 bit words (low byte).
69: * For convenience, we redefine here the chip's RAM layout
70: * making padding explicit.
71: */
72:
73: typedef struct {
74: volatile unsigned char mc_second;
75: char pad0[3];
76: volatile unsigned char mc_alarm_second;
77: char pad1[3];
78: volatile unsigned char mc_minute;
79: char pad2[3];
80: volatile unsigned char mc_alarm_minute;
81: char pad3[3];
82: volatile unsigned char mc_hour;
83: char pad4[3];
84: volatile unsigned char mc_alarm_hour;
85: char pad5[3];
86: volatile unsigned char mc_day_of_week;
87: char pad6[3];
88: volatile unsigned char mc_day_of_month;
89: char pad7[3];
90: volatile unsigned char mc_month;
91: char pad8[3];
92: volatile unsigned char mc_year;
93: char pad9[3];
94: volatile unsigned char mc_register_A;
95: char pad10[3];
96: volatile unsigned char mc_register_B;
97: char pad11[3];
98: volatile unsigned char mc_register_C;
99: char pad12[3];
100: volatile unsigned char mc_register_D;
101: char pad13[3];
102: unsigned char mc_non_volatile_ram[50 * 4]; /* unused */
103: } mc_clock_ram_t;
104:
105: #define MC_CLOCK_PADDED 1
106:
107: #endif /*DECSTATION*/
108:
109:
110: #ifdef FLAMINGO
111: #define MC_DEFAULT_ADDRESS 0L
112:
113: /* padded, later */
114:
115: #endif /* FLAMINGO */
116:
117:
118:
119: #ifndef MC_CLOCK_PADDED
120: typedef mc_clock_t mc_clock_ram_t; /* No padding needed */
121: #endif
122:
123: /*
124: * Functions provided herein
125: */
126: int mc_probe( vm_offset_t addr, struct bus_ctlr * );
127: private void mc_attach();
128:
129: int mc_intr();
130:
131: void mc_open(), mc_close(), mc_write();
132: private unsigned int mc_read();
133:
134: private void mc_wait_for_uip( mc_clock_ram_t *clock );
135:
136:
137: /*
138: * Status
139: */
140: boolean_t mc_running = FALSE;
141: boolean_t mc_new_century = FALSE; /* "year" info overfloweth */
142:
143: private int days_per_month[12] = {
144: 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
145: };
146:
147: private unsigned int mc_read(); /* forward */
148: private void mc_wait_for_uip();
149:
150: /*
151: * Where is the chip's RAM mapped
152: */
153: private mc_clock_ram_t *rt_clock = MC_DEFAULT_ADDRESS;
154:
155: /*
156: * (Auto?)Configuration
157: */
158: private vm_offset_t mc_std[NMC] = { 0 };
159: private struct bus_device *mc_info[NMC];
160:
161: struct bus_driver mc_driver =
162: { mc_probe, 0, mc_attach, 0, mc_std, "mc", mc_info, };
163:
164:
165: mc_probe(vm_offset_t addr, struct bus_ctlr *ui)
166: {
167: rt_clock = (mc_clock_ram_t *)addr;
168: return 1;
169: }
170:
171: private void
172: mc_attach()
173: {
174: printf(": MC146818 or like Time-Of-Year chip");
175: }
176:
177: /*
178: * Interrupt routine
179: */
180: #if MC_DOES_DELAYS
181:
182: private int config_step = 3;
183: private volatile int had_intr;
184:
185: mc_intr(spllevel)
186: spl_t spllevel;
187: {
188: /*
189: * Interrupt flags are read-to-clear.
190: */
191: if (config_step > 2)
192: return (rt_clock->mc_register_C & MC_REG_C_IRQF);
193: had_intr = (rt_clock->mc_register_C & MC_REG_C_IRQF) ? 1 : 0;
194: if (config_step++ == 0)
195: accurate_config_delay(spllevel);
196: return had_intr;
197: }
198: #else /* MC_DOES_DELAYS */
199:
200: mc_intr()
201: {
202: return (rt_clock->mc_register_C); /* clear intr */
203: }
204:
205: #endif /* MC_DOES_DELAYS */
206:
207: /*
208: * Start real-time clock.
209: */
210: void
211: mc_open()
212: {
213: /*
214: * All we should need to do is to enable interrupts, but
215: * since we do not know what OS last ran on this box
216: * we'll reset it all over again. Just kidding..
217: */
218: unsigned unix_seconds_now;
219:
220: /*
221: * Check for battery backup power. If we do not have it,
222: * warn the user. Time will be bogus only after power up.
223: */
224: if ((rt_clock->mc_register_D & MC_REG_D_VRT) == 0)
225: printf("WARNING: clock batteries are low\n");
226:
227: /*
228: * Read the current time settings, check if the year info
229: * has been screwed up.
230: */
231: unix_seconds_now = mc_read();
232:
233: if (unix_seconds_now < (SECYR * (1990 - YRREF)))
234: printf("The prom has clobbered the clock\n");
235:
236: time.tv_sec = (long)unix_seconds_now;
237: mc_write();
238:
239: mc_running = TRUE;
240: }
241:
242: void
243: mc_close()
244: {
245: /*
246: * Disable interrupts, but keep the chip running.
247: * Note we are called at splhigh and an interrupt
248: * might be pending already.
249: */
250:
251: mc_intr(0);
252: rt_clock->mc_register_B &= ~(MC_REG_B_UIE|MC_REG_B_AIE|MC_REG_B_PIE);
253: mc_running = FALSE;
254: #if MC_DOES_DELAYS
255: config_step = 0;
256: #endif
257: }
258:
259:
260: /*
261: * Set time-of-day. Must be called at splhigh()
262: */
263: void
264: mc_write()
265: {
266: register mc_clock_ram_t *clock = rt_clock;
267: register unsigned years, months, days, hours, minutes, seconds;
268: register unsigned unix_seconds = time.tv_sec;
269: int frequence_selector, temp;
270: int bogus_hz = 0;
271:
272: /*
273: * Convert U*x time into absolute time
274: */
275:
276: years = YRREF;
277: while (1) {
278: seconds = SECYR;
279: if (LEAPYEAR(years))
280: seconds += SECDAY;
281: if (unix_seconds < seconds)
282: break;
283: unix_seconds -= seconds;
284: years++;
285: }
286:
287: months = 0;
288: while (1) {
289: seconds = days_per_month[months++] * SECDAY;
290: if (months == 2 /* February */ && LEAPYEAR(years))
291: seconds += SECDAY;
292: if (unix_seconds < seconds)
293: break;
294: unix_seconds -= seconds;
295: }
296:
297: days = unix_seconds / SECDAY;
298: unix_seconds -= SECDAY * days++;
299:
300: hours = unix_seconds / SECHOUR;
301: unix_seconds -= SECHOUR * hours;
302:
303: minutes = unix_seconds / SECMIN;
304: unix_seconds -= SECMIN * minutes;
305:
306: seconds = unix_seconds;
307:
308: /*
309: * Trim years into 0-99 range.
310: */
311: if ((years -= 1900) > 99) {
312: years -= 100;
313: mc_new_century = TRUE;
314: }
315:
316: /*
317: * Check for "hot dates"
318: */
319: if (days >= 28 && days <= 30 &&
320: hours == 23 && minutes == 59 &&
321: seconds >= 58)
322: seconds = 57;
323:
324: /*
325: * Select the interrupt frequency based on system params
326: */
327: switch (hz) {
328: case 1024:
329: frequence_selector = MC_BASE_32_KHz | MC_RATE_1024_Hz;
330: break;
331: case 512:
332: frequence_selector = MC_BASE_32_KHz | MC_RATE_512_Hz;
333: break;
334: case 256:
335: frequence_selector = MC_BASE_32_KHz | MC_RATE_256_Hz;
336: break;
337: case 128:
338: frequence_selector = MC_BASE_32_KHz | MC_RATE_128_Hz;
339: break;
340: case 64:
341: default_frequence:
342: frequence_selector = MC_BASE_32_KHz | MC_RATE_64_Hz;
343: break;
344: default:
345: bogus_hz = hz;
346: hz = 64;
347: tick = 1000000 / 64;
348: goto default_frequence;
349: }
350:
351: /*
352: * Stop updates while we fix it
353: */
354: mc_wait_for_uip(clock);
355: clock->mc_register_B = MC_REG_B_STOP;
356: wbflush();
357:
358: /*
359: * Ack any pending interrupts
360: */
361: temp = clock->mc_register_C;
362:
363: /*
364: * Reset the frequency divider, in case we are changing it.
365: */
366: clock->mc_register_A = MC_BASE_RESET;
367:
368: /*
369: * Now update the time
370: */
371: clock->mc_second = seconds;
372: clock->mc_minute = minutes;
373: clock->mc_hour = hours;
374: clock->mc_day_of_month = days;
375: clock->mc_month = months;
376: clock->mc_year = years;
377:
378: /*
379: * Spec says the VRT bit can be validated, but does not say how. I
380: * assume it is via reading the register.
381: */
382: temp = clock->mc_register_D;
383:
384: /*
385: * Reconfigure the chip and get it started again
386: */
387: clock->mc_register_A = frequence_selector;
388: clock->mc_register_B = MC_REG_B_24HM | MC_REG_B_DM | MC_REG_B_PIE;
389:
390: /*
391: * Print warnings, if we have to
392: */
393: if (bogus_hz != 0)
394: printf("Unacceptable value (%d Hz) for hz, reset to %d Hz\n",
395: bogus_hz, hz);
396: }
397:
398:
399: /*
400: * Internal functions
401: */
402:
403: private void
404: mc_wait_for_uip(clock)
405: mc_clock_ram_t *clock;
406: {
407: while (clock->mc_register_A & MC_REG_A_UIP)
408: delay(MC_UPD_MINIMUM >> 2);
409: }
410:
411: private unsigned int
412: mc_read()
413: {
414: /*
415: * Note we only do this at boot time
416: */
417: register unsigned years, months, days, hours, minutes, seconds;
418: register mc_clock_ram_t *clock = rt_clock;;
419:
420: /*
421: * If the chip is updating, wait
422: */
423: mc_wait_for_uip(clock);
424:
425: years = clock->mc_year;
426: months = clock->mc_month;
427: days = clock->mc_day_of_month;
428: hours = clock->mc_hour;
429: minutes = clock->mc_minute;
430: seconds = clock->mc_second;
431:
432: /*
433: * Convert to Unix time
434: */
435: seconds += minutes * SECMIN;
436: seconds += hours * SECHOUR;
437: seconds += (days - 1) * SECDAY;
438: if (months > 2 /* February */ && LEAPYEAR(years))
439: seconds += SECDAY;
440: while (months > 1)
441: seconds += days_per_month[--months - 1];
442:
443: /*
444: * Note that in ten years from today (Aug,1990) the new century will
445: * cause the trouble that mc_new_century attempts to avoid.
446: */
447: if (mc_new_century)
448: years += 100;
449: years += 1900; /* chip base year in YRREF's century */
450:
451: for (--years; years >= YRREF; years--) {
452: seconds += SECYR;
453: if (LEAPYEAR(years))
454: seconds += SECDAY;
455: }
456:
457: return seconds;
458: }
459:
460: #ifdef MC_DOES_DELAYS
461:
462: /*
463: * Timed delays
464: */
465: extern unsigned int cpu_speed;
466:
467: void
468: config_delay(speed)
469: {
470: /*
471: * This is just an initial estimate, later on with the clock
472: * running we'll tune it more accurately.
473: */
474: cpu_speed = speed;
475: }
476:
477: accurate_config_delay(spllevel)
478: spl_t spllevel;
479: {
480: register unsigned int i;
481: register spl_t s;
482: int inner_loop_count;
483:
484: #ifdef mips
485: /* find "spllevel - 1" */
486: s = spllevel | ((spllevel >> 1) & SR_INT_MASK);
487: splx(s);
488: #else
489: #endif
490:
491: /* wait till we have an interrupt pending */
492: had_intr = 0;
493: while (!had_intr)
494: continue;
495:
496: had_intr = 0;
497: i = delay_timing_function(1, &had_intr, &inner_loop_count);
498:
499: splx(spllevel);
500:
501: i *= hz;
502: cpu_speed = i / (inner_loop_count * 1000000);
503:
504: /* roundup clock speed */
505: i /= 100000;
506: if ((i % 10) >= 5)
507: i += 5;
508: printf("Estimating CPU clock at %d Mhz\n", i / 10);
509: if (isa_pmax() && cpu_speed != MC_DELAY_PMAX) {
510: printf("%s\n", "This machine looks like a DEC 2100");
511: machine_slot[cpu_number()].cpu_subtype = CPU_SUBTYPE_MIPS_R2000;
512: }
513: }
514: #endif /* MC_DOES_DELAYS */
515:
516: #endif NMC > 0
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.