FreeBSD/Linux Kernel Cross Reference
sys/chips/mc_clock.c
1 /*
2 * Mach Operating System
3 * Copyright (c) 1993,1992,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 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: mc_clock.c,v $
29 * Revision 2.16 93/11/17 16:12:25 dbg
30 * Added autoconfiguration structures for PS2.
31 * [93/09/09 dbg]
32 * Fixed setting CLOCK_RESOLUTION: mc_setstat was passing an
33 * uninitialized variable to log2. Changed mc_setstat to
34 * pick the available resolution closest to the one requested,
35 * not just the next higher power of 2.
36 * [93/08/30 dbg]
37 *
38 * Probe routine now sets the clock address for all machines.
39 * [93/07/15 dbg]
40 *
41 * Century is in a different place on the PS2.
42 * [93/07/13 dbg]
43 *
44 * Update clock->check_seconds when reading clock at initialization.
45 * [93/06/18 dbg]
46 *
47 * Use routines from device/clock_dev.c.
48 * [93/06/02 dbg]
49 *
50 * Changed mmap routines to return physical address instead of
51 * physical page number.
52 * [93/05/24 dbg]
53 *
54 * Adapted for new Mach clocks and timers, based on Stefan Savage's
55 * code. Generalized to be usable for i386 machines, also.
56 * [93/05/21 dbg]
57 *
58 * Revision 2.15 93/05/17 15:11:48 rvb
59 * Type casts, etc to quiet gcc 2.3.3 warnings
60 * [93/05/17 rvb]
61 *
62 * Revision 2.14 93/05/15 19:37:12 mrt
63 * machparam.h -> machspl.h
64 *
65 * Revision 2.13 93/05/10 20:08:19 rvb
66 * Fixed types. Define what is exported and what not.
67 * [93/05/06 09:57:45 af]
68 *
69 * Revision 2.12 93/02/05 08:05:43 danner
70 * Heavy cosmetic changes to make it look like a device after all.
71 * Flamingo uses it too.
72 * [93/02/04 01:30:53 af]
73 *
74 * Proper spl typing.
75 * [92/11/30 af]
76 *
77 * Revision 2.11 92/02/19 16:45:57 elf
78 * Wait for uip before stopping the chip, too.
79 * [92/01/22 af]
80 *
81 * Revision 2.10 91/08/24 11:52:28 af
82 * Fixed spl munging, for 3min.
83 * [91/08/02 01:49:09 af]
84 *
85 * Revision 2.9 91/06/25 20:54:18 rpd
86 * Tweaks to make gcc happy.
87 *
88 * Revision 2.8 91/06/19 11:53:54 rvb
89 * mips->DECSTATION; vax->VAXSTATION
90 * [91/06/12 14:01:54 rvb]
91 *
92 * File moved here from mips/PMAX since it tries to be generic;
93 * it is used on the PMAX and could be used on the Vax3100.
94 * It would need a few ifdef vax & ifdef mips for the latter.
95 * [91/06/04 rvb]
96 *
97 * Revision 2.7 91/05/14 17:24:22 mrt
98 * Correcting copyright
99 *
100 * Revision 2.6 91/02/14 14:34:41 mrt
101 * Factored out delay() function, and made it box-indep.
102 * Added accurate_config_delay() which calls delay()'s
103 * configuration code. Modified ackrtclock() to
104 * invoke it on first call.
105 * Tell the user what the CPU clock speed loks like,
106 * distinguish between DS3100 and DS2100 based on clock speed.
107 * [91/02/12 13:03:16 af]
108 *
109 * Revision 2.5 91/02/05 17:42:35 mrt
110 * Added author notices
111 * [91/02/04 11:15:06 mrt]
112 *
113 * Changed to use new Mach copyright
114 * [91/02/02 12:13:45 mrt]
115 *
116 * Revision 2.4 90/12/05 23:32:39 af
117 *
118 *
119 * Revision 2.3 90/12/05 20:47:31 af
120 * Made file conditional.
121 * [90/12/03 23:28:03 af]
122 *
123 * Revision 2.2 90/08/27 22:06:05 dbg
124 * Initialized cpu_speed to a non-zero value. Apparently,
125 * we need delays much earlier than we can possibly know
126 * what this machine looks like. I know this will bite back.
127 * [90/08/21 af]
128 * Made apparent who is resetting the clock back to 1972.
129 * [90/08/20 10:30:19 af]
130 *
131 * Created, from Motorola's MC146818 specs.
132 * [90/08/17 af]
133 *
134 */
135 /*
136 * File: mc_clock.c
137 * Author: Alessandro Forin
138 * Date: 8/90
139 *
140 * Driver for the MC146818 Clock
141 */
142
143 #include <mc.h>
144 #if NMC > 0
145 #include <platforms.h>
146
147 #include <mach/boolean.h>
148 #include <mach/time_spec.h>
149 #include <mach/machine/vm_types.h>
150
151 #include <kern/clock.h>
152 #include <kern/kern_io.h>
153
154 #ifdef PS2
155 #include <i386ps2/bus.h> /* PS2 autoconf */
156 #else
157 #include <chips/busses.h> /* standard autoconf */
158 #endif
159 #include <device/device_types.h>
160 #include <device/clock_status.h>
161 #include <device/clock_dev.h>
162
163 #include <machine/machspl.h>
164
165 #define private static
166 #define public
167
168 /*
169 * Real-Time Clock plus non-volatile RAM (MC146818)
170 */
171
172 /*
173 * Registers are accessed by number.
174 */
175 #define MC_SECOND 0x00
176 #define MC_ALARM_SECOND 0x01
177 #define MC_MINUTE 0x02
178 #define MC_ALARM_MINUTE 0x03
179 #define MC_HOUR 0x04
180 #define MC_ALARM_HOUR 0x05
181 #define MC_DAY_OF_WEEK 0x06 /* range 1..7 */
182 #define MC_DAY_OF_MONTH 0x07 /* range 1..31 */
183 #define MC_MONTH 0x08
184 #define MC_YEAR 0x09
185 #define MC_REG_A 0x0a
186 #define MC_REG_B 0x0b
187 #define MC_REG_C 0x0c
188 #define MC_REG_D 0x0d
189
190 /*
191 * Register A defines (read/write)
192 */
193
194 #define MC_REG_A_RS 0x0f /* Interrupt rate (and SQwave) select */
195 #define MC_REG_A_DV 0x70 /* Divider select */
196 #define MC_REG_A_UIP 0x80 /* Update In Progress (read-only bit) */
197
198 /* Time base configuration */
199 #define MC_BASE_4_MHz 0x00
200 #define MC_BASE_1_MHz 0x10
201 #define MC_BASE_32_KHz 0x20
202 #define MC_BASE_NONE 0x60 /* actually, both of these reset */
203 #define MC_BASE_RESET 0x70
204
205 /* Interrupt rate table */
206 #define MC_RATE_NONE 0x0 /* disabled */
207 #define MC_RATE_1 0x1 /* 256Hz if MC_BASE_32_KHz,
208 else 32768Hz */
209 #define MC_RATE_2 0x2 /* 128Hz if MC_BASE_32_KHz,
210 else 16384Hz */
211 #define MC_RATE_8192_Hz 0x3 /* Tpi: 122.070 usecs */
212 #define MC_RATE_4096_Hz 0x4 /* Tpi: 244.141 usecs */
213 #define MC_RATE_2048_Hz 0x5 /* Tpi: 488.281 usecs */
214 #define MC_RATE_1024_Hz 0x6 /* Tpi: 976.562 usecs */
215 #define MC_RATE_512_Hz 0x7 /* Tpi: 1.953125 ms */
216 #define MC_RATE_256_Hz 0x8 /* Tpi: 3.90625 ms */
217 #define MC_RATE_128_Hz 0x9 /* Tpi: 7.8125 ms */
218 #define MC_RATE_64_Hz 0xa /* Tpi: 15.625 ms */
219 #define MC_RATE_32_Hz 0xb /* Tpi: 31.25 ms */
220 #define MC_RATE_16_Hz 0xc /* Tpi: 62.5 ms */
221 #define MC_RATE_8_Hz 0xd /* Tpi: 125 ms */
222 #define MC_RATE_4_Hz 0xe /* Tpi: 250 ms */
223 #define MC_RATE_2_Hz 0xf /* Tpi: 500 ms */
224
225 /* Update cycle time */
226 #define MC_UPD_4_MHz 248 /* usecs */
227 #define MC_UPD_1_MHz 248 /* usecs */
228 #define MC_UPD_32_KHz 1984 /* usecs */
229 #define MC_UPD_MINIMUM 244 /* usecs, guaranteed if UIP=0 */
230
231 /*
232 * Register B defines (read/write)
233 */
234
235 #define MC_REG_B_DSE 0x01 /* obsolete (Daylight Savings Enable) */
236 #define MC_REG_B_24HM 0x02 /* 24/12 Hour Mode */
237 #define MC_REG_B_DM 0x04 /* Data Mode, 1=Binary 0=BCD */
238 #define MC_REG_B_SQWE 0x08 /* Square Wave Enable */
239 #define MC_REG_B_UIE 0x10 /* Update-ended Interrupt Enable */
240 #define MC_REG_B_AIE 0x20 /* Alarm Interrupt Enable */
241 #define MC_REG_B_PIE 0x40 /* Periodic Interrupt Enable */
242 #define MC_REG_B_SET 0x80 /* Set NVram info, e.g.
243 update time or ..*/
244 #define MC_REG_B_STOP MC_REG_B_SET /* Stop updating the timing info */
245
246 /*
247 * Register C defines (read-only)
248 */
249
250 #define MC_REG_C_ZEROES 0x0f /* Reads as zero bits */
251 #define MC_REG_C_UF 0x10 /* Update-ended interrupt flag */
252 #define MC_REG_C_AF 0x20 /* Alarm interrupt flag */
253 #define MC_REG_C_PF 0x40 /* Periodic interrupt flag */
254 #define MC_REG_C_IRQF 0x80 /* Interrupt request flag */
255
256 /*
257 * Register D defines (read-only)
258 */
259
260 #define MC_REG_D_ZEROES 0x7f /* Reads as zero bits */
261 #define MC_REG_D_VRT 0x80 /* Valid RAM and Time */
262
263 /*
264 * Different machines map the chip registers in different
265 * ways.
266 */
267
268 #ifdef DECSTATION
269 #include <mips/mips_cpu.h>
270
271 #define MC_DEFAULT_ADDRESS PHYS_TO_K1SEG(0x1d000000)
272 #define MC_DOES_DELAYS 1
273
274 /*
275 * Both the Pmax and the 3max implementations of the chip map
276 * bytes of the chip's RAM to 32 bit words (low byte).
277 * For convenience, we redefine here the chip's RAM layout
278 * making padding explicit.
279 */
280
281 typedef struct {
282 struct {
283 volatile unsigned char real_reg;
284 char pad[3];
285 } regs[64];
286 } * mc_clock_t;
287
288 #define mc_read(clock, reg) (clock->regs[reg].real_reg)
289 #define mc_write(clock, reg, data) \
290 (clock->regs[reg].real_reg = (data))
291
292 #endif /* DECSTATION */
293
294 #ifdef FLAMINGO
295 #define MC_DEFAULT_ADDRESS 0L
296
297 /*
298 * Clock is not padded
299 */
300 typedef struct {
301 volatile unsigned char regs[64];
302 } * mc_clock_t;
303
304 #define mc_read(clock, reg) (clock->regs[reg])
305 #define mc_write(clock, reg, data) \
306 (clock->regs[reg] = (data))
307
308 #endif /* FLAMINGO */
309
310 #if defined(AT386) || defined(PS2)
311
312 #include <i386/pio.h>
313 #define wbflush()
314
315 /*
316 * The RTC is accessed through IO ports.
317 */
318 #define MC_ADDR 0x70 /* high bit is NMI enable! */
319 #define MC_DATA 0x71
320
321 /*
322 * Delay is needed between outb and inb.
323 */
324 #ifdef __GNUC__
325 #define spin() asm volatile(" jmp 0f; 0: ")
326 #endif
327
328 #define mc_read(clock, reg) \
329 ({ outb(MC_ADDR, reg); spin(); inb(MC_DATA);})
330
331 #define mc_write(clock, reg, data) \
332 ({ outb(MC_ADDR, reg); spin(); outb(MC_DATA, data); (void)0;})
333
334 /*
335 * Need typedef anyway.
336 */
337 typedef volatile unsigned char* mc_clock_t;
338
339 #define MC_DEFAULT_ADDRESS MC_ADDR
340
341 /*
342 * We keep time in BCD
343 */
344 #define MC_CLOCK_BCD 1
345
346 /*
347 * And there is a place to put the century (!)
348 */
349 #ifdef AT386
350 #define MC_CENTURY 0x32
351 #endif
352 #ifdef PS2
353 #define MC_CENTURY 0x37
354 #endif
355
356 #endif /* AT386 || PS2 */
357
358 /*
359 * We configure the clock to run in 24 hour mode,
360 * and to deliver periodic interrupts that we
361 * use as clock interrupts.
362 * If some other OS wants time to be kept in BCD,
363 * we do that to.
364 * But we keep time in UTC, not local time.
365 */
366
367 #ifdef MC_CLOCK_BCD
368 #define MC_REG_B_CONFIGURE (MC_REG_B_24HM)
369 #else
370 #define MC_REG_B_CONFIGURE (MC_REG_B_24HM | MC_REG_B_DM)
371 #endif
372
373 /*
374 * Minimum and maximum resolution for clock.
375 */
376 #define MC_CLOCK_DEFAULT_RESOLUTION (NANOSEC_PER_SEC/128)
377 #define MC_CLOCK_MAX_RESOLUTION (16000000)
378 #define MC_CLOCK_MIN_RESOLUTION (125000)
379
380 /*
381 * We have only one per machine.
382 */
383 mach_clock_data_t mc_clock0;
384
385 mach_clock_t mc_clock[] = {&mc_clock0};
386
387 void mc_clock_setresolution(mach_clock_t); /* forward */
388 void mc_clock_write(mach_clock_t, time_spec_t);
389 void mc_clock_enable_interrupts(mach_clock_t);
390 time_spec_t mc_clock_read(mach_clock_t);
391 void mc_wait_for_uip(mc_clock_t clock);
392
393 struct clock_ops mc_clock_ops = {
394 mc_clock_setresolution,
395 mc_clock_write,
396 mc_clock_enable_interrupts
397 };
398
399 #ifdef PS2
400 /*
401 * PS2 autoconf
402 */
403 int mc_probe(), mc_attach();
404 extern mc_intr();
405
406 char * mc_std[] = { (char *) 0x70, 0 };
407
408 struct i386_dev *mc_info[NMC];
409 struct i386_driver mcdriver =
410 /* probe slave attach dname dinfo mname minfo */
411 { mc_probe, 0, mc_attach, "mc", mc_info, 0, 0 };
412 int (*mcintrs[])() = {mc_intr, 0};
413
414 #else /* PS2 */
415 /*
416 * Standard Configuration
417 */
418 boolean_t mc_probe(
419 vm_offset_t addr,
420 struct bus_device *dev);
421 void mc_attach(
422 struct bus_device *dev);
423
424 static vm_offset_t mc_std[] = { MC_DEFAULT_ADDRESS, 0 };
425 static struct bus_device *mc_info[NMC];
426
427 struct bus_driver mc_driver = {
428 mc_probe, 0, mc_attach, 0, mc_std, "mc",
429 mc_info, 0, 0, 0};
430
431 #endif /* PS2 */
432
433 #if defined(AT386) || defined(PS2)
434 extern mc_sysintr(); /* MC system clock interrupt */
435 #endif
436
437 /*
438 * Where is the chip`s RAM mapped?
439 */
440 mc_clock_t rt_clock = (mc_clock_t) MC_DEFAULT_ADDRESS;
441
442 /*
443 * status
444 */
445 int mc_interrupt_enabled = 0; /* OR with reg B */
446 boolean_t mc_new_century = FALSE; /* patch after Dec 31, 1999 */
447
448 /*
449 * Probe to see whether the device exists.
450 */
451 #ifdef PS2
452 int mc_probe(addr, dev)
453 vm_offset_t addr;
454 struct i386_dev *dev;
455 #else
456 boolean_t mc_probe(
457 vm_offset_t addr,
458 struct bus_device *dev)
459 #endif
460 {
461 #ifdef PS2
462 int unit = dev->dev_unit;
463 #else
464 int unit = dev->unit;
465 #endif
466
467 if (unit < 0 || unit >= NMC) {
468 printf("mc%d out of range\n", unit);
469 return FALSE;
470 }
471
472 /*
473 * We assume that we always have exactly one
474 * clock chip.
475 *
476 * Set the clock`s address.
477 */
478 rt_clock = (mc_clock_t) addr;
479 return TRUE;
480 }
481
482 /*
483 * Attach the clock device:
484 * set up the clock structure and read
485 * the current time from the hardware.
486 */
487 #ifdef PS2
488 mc_attach(dev)
489 struct i386_dev *dev;
490 #else
491 void mc_attach(
492 struct bus_device *dev)
493 #endif
494 {
495 #ifdef PS2
496 int unit = dev->dev_unit;
497 #else
498 int unit = dev->unit;
499 #endif
500 mach_clock_t clock = mc_clock[unit];
501 time_spec_t cur_time;
502
503 printf(": MC146818 (or the like) Time-of-Year chip");
504
505 clock_init(clock, &mc_clock_ops);
506
507 clock->resolution = MC_CLOCK_DEFAULT_RESOLUTION; /* @128 hz */
508 mc_clock_setresolution(clock);
509
510 printf(", resolution = %u nsecs", clock->resolution);
511
512 if (sys_clock == 0) {
513 /*
514 * If no system clock already, use this as system clock.
515 */
516 sys_clock = &mc_clock0;
517 #if defined(AT386) || defined(PS2)
518 #ifdef PS2
519 mcintrs[0] = mc_sysintr;
520 #else
521 dev->intr = mc_sysintr; /* use system clock interrupt */
522 #endif
523 dev_change_indirect("clock_priv", "mc", unit);
524 /* set generic clock device */
525 set_clock_unpriv(); /* and 'unprivileged' clock */
526 #endif
527 }
528
529 #ifdef AT386
530 take_dev_irq(mc_info[0]); /* XXX */
531 #endif
532 #ifdef PS2
533 take_dev_irq(dev);
534 #endif
535
536 /*
537 * Read the current time from the chip
538 */
539 cur_time = mc_clock_read(clock);
540 if (!time_spec_valid(cur_time)) {
541 /*
542 * Battery dead - no time
543 */
544 printf("\n*** Dead Battery *** Time Unknown ***");
545 clock->check_seconds = 0;
546 clock->time.nanoseconds = 0;
547 clock->time.seconds = 0;
548 }
549 else {
550 clock->check_seconds = cur_time.seconds;
551 clock->time.nanoseconds = cur_time.nanoseconds;
552 clock->time.seconds = cur_time.seconds;
553
554 /*
555 * If the year is less than 1990, someone
556 * has clobbered the clock.
557 */
558 if (clock->time.seconds < (60*60*24*365) * (1990 - 1970))
559 printf("\n*** The PROM has clobbered the clock ***");
560 }
561 }
562
563 /*
564 * Enable interrupts from MC clock chip
565 */
566 void mc_clock_enable_interrupts(
567 mach_clock_t clock)
568 {
569 mc_interrupt_enabled = MC_REG_B_PIE;
570 mc_clock_setresolution(clock); /* turns on interrupts */
571 }
572
573 io_return_t mc_open(
574 int dev)
575 {
576 if (dev < 0 || dev >= NMC)
577 return D_NO_SUCH_DEVICE;
578
579 return clock_open(mc_clock[dev]);
580 }
581
582 io_return_t mc_close(
583 int dev)
584 {
585 return D_SUCCESS;
586 }
587
588 io_return_t mc_getstat(
589 int dev,
590 int flavor,
591 dev_status_t stat,
592 natural_t *count)
593 {
594 return clock_getstat(mc_clock[dev], flavor, stat, count);
595 }
596
597 io_return_t mc_setstat(
598 int dev,
599 int flavor,
600 dev_status_t stat,
601 natural_t count)
602 {
603 mach_clock_t clock = mc_clock[dev];
604 unsigned int res_request;
605 unsigned int res_ceiling, res_floor, res_closest;
606 int diff_ceiling, diff_floor, diff_closest;
607 spl_t s;
608
609 switch (flavor) {
610 case CLOCK_RESOLUTION:
611 {
612 clock_resolution_t request;
613
614 if (count < CLOCK_RESOLUTION_COUNT)
615 return D_INVALID_SIZE;
616
617 /*
618 * Clock can only interrupt at frequencies of
619 * 2**n hz, 1 <= n <= 13.
620 */
621
622 request = (clock_resolution_t)stat;
623 res_request = request->resolution;
624
625 if (res_request < MC_CLOCK_MIN_RESOLUTION ||
626 res_request > MC_CLOCK_MAX_RESOLUTION)
627 {
628 return D_INVALID_SIZE;
629 }
630
631 /*
632 * Find the first available resolution
633 * (NANOSEC_PER_SEC / 2**n) smaller than
634 * the requested resolution. We already
635 * checked that resolution is above the
636 * hardware`s minimum.
637 */
638 for (res_floor = NANOSEC_PER_SEC;
639 res_floor >= res_request;
640 res_floor >>= 1)
641 continue;
642
643 /*
644 * Calculate the next possible resolution
645 * above the request.
646 */
647 res_ceiling = res_floor << 1;
648
649 /*
650 * Find the difference between the requested
651 * resolution and the available resolutions
652 * that bracket it, and pick the smaller one.
653 */
654
655 diff_floor = (int) res_floor - (int) res_request;
656 if (diff_floor < 0)
657 diff_floor = -diff_floor;
658
659 diff_ceiling = (int) res_ceiling - (int) res_request;
660 if (diff_ceiling < 0)
661 diff_ceiling = -diff_floor;
662
663 if (diff_floor < diff_ceiling) {
664 res_closest = res_floor;
665 diff_closest = diff_floor;
666 }
667 else {
668 res_closest = res_ceiling;
669 diff_closest = diff_ceiling;
670 }
671
672 /*
673 * If the closer value is still outside
674 * the tolerance ('skew'), reject the request.
675 */
676 if (diff_closest > request->skew)
677 return D_INVALID_SIZE;
678
679 /*
680 * Now we have the new resolution to set.
681 * Save it to take effect at the next
682 * clock interrupt.
683 */
684 s = splsched();
685 clock_queue_lock(clock);
686
687 clock->new_resolution = res_closest;
688 clock->new_skew = diff_closest;
689
690 clock_queue_unlock(clock);
691 splx(s);
692
693 return D_SUCCESS;
694 }
695
696 default:
697 return clock_setstat(clock, flavor, stat, count);
698 }
699 }
700
701
702 vm_offset_t mc_mmap(
703 int dev,
704 vm_offset_t off,
705 vm_prot_t prot)
706 {
707 return clock_map_page(mc_clock[dev], off, prot);
708 }
709
710 io_return_t mc_devinfo(
711 int dev,
712 int flavor,
713 mach_clock_t *info)
714 {
715 if (flavor == D_INFO_CLOCK) {
716 *info = mc_clock[dev];
717 return D_SUCCESS;
718 }
719 else {
720 return D_INVALID_OPERATION;
721 }
722 }
723
724 void mc_clock_setresolution(
725 mach_clock_t clock)
726 {
727 int index, temp;
728 unsigned int resolution, res;
729
730 /*
731 * Convert the resolution to a rate index
732 * for the chip.
733 */
734 resolution = clock->resolution;
735 for (res = NANOSEC_PER_SEC/2, index = MC_RATE_2_Hz;
736 res > resolution && index > MC_RATE_8192_Hz;
737 res >>=1, index--)
738 continue;
739
740
741 /*
742 * Stop updates while we fix it
743 */
744 while (mc_read(rt_clock, MC_REG_A) & MC_REG_A_UIP)
745 delay(MC_UPD_MINIMUM >> 2);
746 mc_write(rt_clock, MC_REG_B, MC_REG_B_STOP);
747 wbflush();
748
749 /*
750 * Ack any pending interrupts
751 */
752 temp = mc_read(rt_clock, MC_REG_C);
753
754 /*
755 * Reset the frequency divider, in case we are changing it.
756 */
757 mc_write(rt_clock, MC_REG_A, MC_BASE_RESET);
758
759 /*
760 * Spec says the VRT bit can be validated, but does not say how. I
761 * assume it is via reading the register.
762 */
763 temp = mc_read(rt_clock, MC_REG_D);
764
765 /*
766 * Reconfigure the chip and get it started again
767 */
768 mc_write(rt_clock, MC_REG_A,
769 MC_BASE_32_KHz | index);
770 mc_write(rt_clock, MC_REG_B,
771 MC_REG_B_CONFIGURE | mc_interrupt_enabled);
772 }
773
774 #ifdef MC_CLOCK_BCD
775 int bcd_to_int(int bcd)
776 {
777 return (bcd >> 4) * 10 + (bcd & 0xf);
778 }
779
780 int int_to_bcd(int intval)
781 {
782 return ((intval / 10) << 4) + (intval % 10);
783 }
784 #endif
785
786 /*
787 * Read time from clock chip. If battery was dead,
788 * return an invalid time_spec.
789 */
790 time_spec_t mc_clock_read(
791 mach_clock_t clock)
792 {
793 unsigned int years, months, days, hours, minutes, seconds;
794 #ifdef MC_CENTURY
795 unsigned int century;
796 #endif
797 time_spec_t clock_time;
798 spl_t s;
799
800 /*
801 * Check the battery.
802 */
803 if ((mc_read(rt_clock, MC_REG_D) && MC_REG_D_VRT) == 0) {
804 /*
805 * No time.
806 */
807 clock_time.seconds = 0;
808 clock_time.nanoseconds = NANOSEC_PER_SEC + 1; /* invalid */
809 return clock_time;
810 }
811
812 /*
813 * Wait for update to finish
814 */
815 s = splhigh();
816
817 while (mc_read(rt_clock, MC_REG_A) & MC_REG_A_UIP)
818 delay(MC_UPD_MINIMUM >> 2);
819
820 /*
821 * Grab the date and time
822 */
823 #ifdef MC_CENTURY
824 century = mc_read(rt_clock, MC_CENTURY);
825 #endif
826 years = mc_read(rt_clock, MC_YEAR);
827 months = mc_read(rt_clock, MC_MONTH);
828 days = mc_read(rt_clock, MC_DAY_OF_MONTH);
829 hours = mc_read(rt_clock, MC_HOUR);
830 minutes = mc_read(rt_clock, MC_MINUTE);
831 seconds = mc_read(rt_clock, MC_SECOND);
832
833 splx(s);
834
835 #ifdef MC_CLOCK_BCD
836 /*
837 * Convert the numbers from BCD to binary.
838 */
839 #ifdef MC_CENTURY
840 century = bcd_to_int(century);
841 #endif
842 years = bcd_to_int(years);
843 months = bcd_to_int(months);
844 days = bcd_to_int(days);
845 hours = bcd_to_int(hours);
846 minutes = bcd_to_int(minutes);
847 seconds = bcd_to_int(seconds);
848 #endif
849
850 /*
851 * Convert to seconds from 1970.
852 */
853 #ifdef MC_CENTURY
854 years += century * 100;
855 #else
856 if (years < 70 || mc_new_century)
857 years += 2000; /* it`s coming soon... */
858 else
859 years += 1900;
860 #endif
861
862 clock_time.seconds = ymd_to_seconds(
863 years, months, days, hours, minutes, seconds);
864 clock_time.nanoseconds = 0;
865
866 return clock_time;
867 }
868
869 /*
870 * Set real-time-clock-chip from supplied time.
871 * Clock has already been updated.
872 */
873 void mc_clock_write(
874 mach_clock_t clock,
875 time_spec_t new_time)
876 {
877 unsigned int years, months, days, hours, minutes, seconds;
878 unsigned int day_of_week, temp;
879 #ifdef MC_CENTURY
880 unsigned int century;
881 #endif
882 spl_t s;
883
884 /*
885 * Update hardware, to nearest second
886 */
887 seconds_to_ymd(new_time.seconds,
888 &years, &months, &days, &hours, &minutes, &seconds,
889 &day_of_week);
890
891 #ifdef MC_CENTURY
892 /*
893 * Keep track of century
894 */
895 century = years / 100;
896 #endif
897 years %= 100;
898
899 /*
900 * Check for "hot dates" (chip bugs)
901 */
902 if (days >= 28 && days <= 30 &&
903 hours == 23 && minutes == 59 &&
904 seconds >= 58)
905 seconds = 57;
906
907 #if MC_CLOCK_BCD
908 /*
909 * DOS keeps the time in BCD. Convert numbers from decimal.
910 */
911 #ifdef MC_CENTURY
912 century = int_to_bcd(century);
913 #endif
914 years = int_to_bcd(years);
915 months = int_to_bcd(months);
916 days = int_to_bcd(days);
917 hours = int_to_bcd(hours);
918 minutes = int_to_bcd(minutes);
919 seconds = int_to_bcd(seconds);
920 #endif
921
922 /*
923 * Stop updates while we change the time
924 */
925 s = splhigh();
926
927 while (mc_read(rt_clock, MC_REG_A) & MC_REG_A_UIP)
928 delay(MC_UPD_MINIMUM >> 2);
929
930 mc_write(rt_clock, MC_REG_B, MC_REG_B_STOP);
931
932 /*
933 * Ack any pending interrupts
934 */
935 temp = mc_read(rt_clock, MC_REG_C);
936
937 /*
938 * Update the time
939 */
940 #ifdef MC_CENTURY
941 mc_write(rt_clock, MC_CENTURY, century);
942 #endif
943 mc_write(rt_clock, MC_YEAR, years);
944 mc_write(rt_clock, MC_MONTH, months);
945 mc_write(rt_clock, MC_DAY_OF_MONTH, days);
946 mc_write(rt_clock, MC_HOUR, hours);
947 mc_write(rt_clock, MC_MINUTE, minutes);
948 mc_write(rt_clock, MC_SECOND, seconds);
949
950 mc_write(rt_clock, MC_DAY_OF_WEEK, day_of_week+1); /* 1..7 */
951
952 /*
953 * Restart the chip
954 */
955 mc_write(rt_clock, MC_REG_B, MC_REG_B_CONFIGURE | mc_interrupt_enabled);
956
957 splx(s);
958 }
959
960 /****************************************************************/
961
962 #if defined(DECSTATION) || defined(FLAMINGO)
963 /*
964 * Interrupt routines
965 */
966
967 #if MC_DOES_DELAYS
968
969 #ifdef DECSTATION
970
971 #include <kern/machine.h>
972 #define MC_DELAY_PMAX 8
973 #define MC_DELAY_3MAX 12
974
975 #endif
976
977 /*
978 * Timed delays
979 */
980
981 static int config_step = 0; /* configure when clock
982 interrupts are first
983 enabled */
984 static volatile int had_intr;
985
986 extern unsigned int cpu_speed;
987
988 void
989 config_delay(unsigned int speed)
990 {
991 /*
992 * This is just an initial estimate, later on with the clock
993 * running we'll tune it more accurately.
994 */
995 cpu_speed = speed;
996 }
997
998 void accurate_config_delay(
999 spl_t spllevel)
1000 {
1001 register unsigned int i;
1002 register spl_t s;
1003 int inner_loop_count;
1004 int clock_ticks_per_second;
1005
1006 #ifdef mips
1007 /* find "spllevel - 1" */
1008 s = spllevel | ((spllevel >> 1) & SR_INT_MASK);
1009 splx(s);
1010 #else
1011 #endif
1012
1013 /* wait till we have an interrupt pending */
1014 had_intr = 0;
1015 while (!had_intr)
1016 continue;
1017
1018 had_intr = 0;
1019 i = delay_timing_function(1, &had_intr, &inner_loop_count);
1020
1021 splx(spllevel);
1022
1023 /* split calculation to avoid overflow */
1024 clock_ticks_per_second = (NANOSEC_PER_SEC / mc_clock0.resolution);
1025 i *= clock_ticks_per_second;
1026
1027 cpu_speed = i / (inner_loop_count * 1000000);
1028
1029 /* roundup clock speed */
1030 i /= 100000;
1031 if ((i % 10) >= 5)
1032 i += 5;
1033 printf("Estimating CPU clock at %d Mhz\n", i / 10);
1034 if (isa_pmax() && cpu_speed != MC_DELAY_PMAX) {
1035 printf("%s\n", "This machine looks like a DEC 2100");
1036 machine_slot[cpu_number()].cpu_subtype = CPU_SUBTYPE_MIPS_R2000;
1037 }
1038 }
1039
1040 int mc_intr(
1041 spl_t spllevel)
1042 {
1043 /*
1044 * Interrupt flags are read-to-clear.
1045 */
1046 if (config_step > 2)
1047 return (mc_read(rt_clock,MC_REG_C) & MC_REG_C_IRQF);
1048 had_intr = (mc_read(rt_clock,MC_REG_C) & MC_REG_C_IRQF) ? 1 : 0;
1049 if (config_step++ == 0)
1050 accurate_config_delay(spllevel);
1051 return had_intr;
1052 }
1053
1054 #else /* MC_DOES_DELAYS */
1055
1056 int mc_intr(spl_t spllevel)
1057 {
1058 return mc_read(rt_clock, MC_REG_C); /* clear intr */
1059 }
1060
1061 #endif /* MC_DOES_DELAYS */
1062
1063
1064 #endif /* defined(DECSTATION) || defined(FLAMINGO) */
1065
1066 #endif /* NMC > 0 */
Cache object: 1a2fc1c7dc5e98c59c694aaf89e3e1e3
|