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@
30 * File: i386/rtclock.c
31 * Purpose: Routines for handling the machine dependent
32 * real-time clock. This clock is generated by
33 * the Intel 8254 Programmable Interval Timer.
37 #include <platforms.h>
40 #include <kern/cpu_number.h>
41 #include <kern/cpu_data.h>
42 #include <kern/clock.h>
43 #include <kern/macro_help.h>
44 #include <kern/misc_protos.h>
46 #include <machine/mach_param.h> /* HZ */
47 #include <mach/vm_prot.h>
49 #include <vm/vm_kern.h> /* for kernel_map */
53 #include <i386/misc_protos.h>
54 #include <i386/rtclock_entries.h>
55 #include <i386/hardclock_entries.h>
57 int sysclk_config(void);
59 int sysclk_init(void);
61 kern_return_t
sysclk_gettime(
62 mach_timespec_t
*cur_time
);
64 kern_return_t
sysclk_getattr(
65 clock_flavor_t flavor
,
67 mach_msg_type_number_t
*count
);
69 kern_return_t
sysclk_setattr(
70 clock_flavor_t flavor
,
72 mach_msg_type_number_t count
);
75 mach_timespec_t
*alarm_time
);
77 extern void (*IOKitRegisterInterruptHook
)(void *, int irq
, int isclock
);
80 * Inlines to get timestamp counter value.
83 static inline void rdtsc_hilo(uint32_t *hi
, uint32_t *lo
) {
84 asm volatile("rdtsc": "=a" (*lo
), "=d" (*hi
));
87 static inline uint64_t rdtsc_64(void) {
89 asm volatile("rdtsc": "=A" (result
));
94 * Lists of clock routines.
96 struct clock_ops sysclk_ops
= {
97 sysclk_config
, sysclk_init
,
99 sysclk_getattr
, sysclk_setattr
,
103 int calend_config(void);
105 int calend_init(void);
107 kern_return_t
calend_gettime(
108 mach_timespec_t
*cur_time
);
110 kern_return_t
calend_settime(
111 mach_timespec_t
*cur_time
);
113 kern_return_t
calend_getattr(
114 clock_flavor_t flavor
,
116 mach_msg_type_number_t
*count
);
118 struct clock_ops calend_ops
= {
119 calend_config
, calend_init
,
120 calend_gettime
, calend_settime
,
125 /* local data declarations */
126 mach_timespec_t
*RtcTime
= (mach_timespec_t
*)0;
127 mach_timespec_t
*RtcAlrm
;
130 /* global data declarations */
134 mach_timespec_t time
;
135 mach_timespec_t alarm_time
; /* time of next alarm */
137 mach_timespec_t calend_offset
;
138 boolean_t calend_is_set
;
140 uint64_t timer_deadline
;
141 boolean_t timer_is_set
;
142 clock_timer_func_t timer_expire
;
144 clock_res_t new_ires
; /* pending new resolution (nano ) */
145 clock_res_t intr_nsec
; /* interrupt resolution (nano) */
147 decl_simple_lock_data(,lock
) /* real-time clock device lock */
150 unsigned int clknum
; /* clks per second */
151 unsigned int new_clknum
; /* pending clknum */
152 unsigned int time_per_clk
; /* time per clk in ZHZ */
153 unsigned int clks_per_int
; /* clks per interrupt */
154 unsigned int clks_per_int_99
;
155 int rtc_intr_count
; /* interrupt counter */
156 int rtc_intr_hertz
; /* interrupts per HZ */
157 int rtc_intr_freq
; /* interrupt frequency */
158 int rtc_print_lost_tick
; /* print lost tick */
160 uint32_t rtc_cyc_per_sec
; /* processor cycles per seconds */
161 uint32_t rtc_last_int_tsc_lo
; /* tsc values saved per interupt */
162 uint32_t rtc_last_int_tsc_hi
;
165 * Macros to lock/unlock real-time clock device.
167 #define LOCK_RTC(s) \
170 simple_lock(&rtclock.lock); \
173 #define UNLOCK_RTC(s) \
175 simple_unlock(&rtclock.lock); \
180 * i8254 control. ** MONUMENT **
182 * The i8254 is a traditional PC device with some arbitrary characteristics.
183 * Basically, it is a register that counts at a fixed rate and can be
184 * programmed to generate an interrupt every N counts. The count rate is
185 * clknum counts per second (see pit.h), historically 1193167 we believe.
186 * Various constants are computed based on this value, and we calculate
187 * them at init time for execution efficiency. To obtain sufficient
188 * accuracy, some of the calculation are most easily done in floating
189 * point and then converted to int.
191 * We want an interrupt every 10 milliseconds, approximately. The count
192 * which will do that is clks_per_int. However, that many counts is not
193 * *exactly* 10 milliseconds; it is a bit more or less depending on
194 * roundoff. The actual time per tick is calculated and saved in
195 * rtclock.intr_nsec, and it is that value which is added to the time
196 * register on each tick.
198 * The i8254 counter can be read between interrupts in order to determine
199 * the time more accurately. The counter counts down from the preset value
200 * toward 0, and we have to handle the case where the counter has been
201 * reset just before being read and before the interrupt has been serviced.
202 * Given a count since the last interrupt, the time since then is given
203 * by (count * time_per_clk). In order to minimize integer truncation,
204 * we perform this calculation in an arbitrary unit of time which maintains
205 * the maximum precision, i.e. such that one tick is 1.0e9 of these units,
206 * or close to the precision of a 32-bit int. We then divide by this unit
207 * (which doesn't lose precision) to get nanoseconds. For notation
208 * purposes, this unit is defined as ZHZ = zanoseconds per nanosecond.
210 * This sequence to do all this is in sysclk_gettime. For efficiency, this
211 * sequence also needs the value that the counter will have if it has just
212 * overflowed, so we precompute that also. ALSO, certain platforms
213 * (specifically the DEC XL5100) have been observed to have problem
214 * with latching the counter, and they occasionally (say, one out of
215 * 100,000 times) return a bogus value. Hence, the present code reads
216 * the counter twice and checks for a consistent pair of values.
218 * Some attributes of the rt clock can be changed, including the
219 * interrupt resolution. We default to the minimum resolution (10 ms),
220 * but allow a finer resolution to be requested. The assumed frequency
221 * of the clock can also be set since it appears that the actual
222 * frequency of real-world hardware can vary from the nominal by
223 * 200 ppm or more. When the frequency is set, the values above are
224 * recomputed and we continue without resetting or changing anything else.
226 #define RTC_MINRES (NSEC_PER_SEC / HZ) /* nsec per tick */
227 #define RTC_MAXRES (RTC_MINRES / 20) /* nsec per tick */
228 #define ZANO (1000000000)
229 #define ZHZ (ZANO / (NSEC_PER_SEC / HZ))
230 #define READ_8254(val) { \
231 outb(PITCTL_PORT, PIT_C0); \
232 (val) = inb(PITCTR0_PORT); \
233 (val) |= inb(PITCTR0_PORT) << 8 ; }
236 * Calibration delay counts.
238 unsigned int delaycount
= 100;
239 unsigned int microdata
= 50;
245 extern int measure_delay(int us
);
246 void rtc_setvals( unsigned int, clock_res_t
);
248 static void rtc_set_cyc_per_sec();
251 * Initialize non-zero clock structure values.
255 unsigned int new_clknum
,
259 unsigned int timeperclk
;
265 rtc_intr_freq
= (NSEC_PER_SEC
/ new_ires
);
266 rtc_intr_hertz
= rtc_intr_freq
/ HZ
;
267 clks_per_int
= (clknum
+ (rtc_intr_freq
/ 2)) / rtc_intr_freq
;
268 clks_per_int_99
= clks_per_int
- clks_per_int
/100;
271 * The following calculations are done with scaling integer operations
272 * in order that the integer results are accurate to the lsb.
274 timeperclk
= div_scale(ZANO
, clknum
, &scale0
); /* 838.105647 nsec */
276 time_per_clk
= mul_scale(ZHZ
, timeperclk
, &scale1
); /* 83810 */
278 time_per_clk
>>= (scale0
- scale1
);
279 else if (scale0
< scale1
)
280 panic("rtc_clock: time_per_clk overflow\n");
283 * Notice that rtclock.intr_nsec is signed ==> use unsigned int res
285 res
= mul_scale(clks_per_int
, timeperclk
, &scale1
); /* 10000276 */
287 rtclock
.intr_nsec
= res
>> (scale0
- scale1
);
289 panic("rtc_clock: rtclock.intr_nsec overflow\n");
292 RtcDelt
= rtclock
.intr_nsec
/2;
296 * Configure the real-time clock device. Return success (1)
307 mp_disable_preemption();
308 if (cpu_number() != master_cpu
) {
309 mp_enable_preemption();
312 mp_enable_preemption();
319 extern boolean_t mp_v1_1_initialized
;
320 if (mp_v1_1_initialized
)
326 pic
= 0; /* FIXME .. interrupt registration moved to AppleIntelClock */
331 * We should attempt to test the real-time clock
332 * device here. If it were to fail, we should panic
335 RtcFlag
= /* test device */1;
336 printf("realtime clock configured\n");
338 simple_lock_init(&rtclock
.lock
, ETAP_NO_TRACE
);
343 * Initialize the real-time clock device. Return success (1)
344 * or failure (0). Since the real-time clock is required to
345 * provide canonical mapped time, we allocate a page to keep
346 * the clock time value. In addition, various variables used
347 * to support the clock are initialized. Note: the clock is
348 * not started until rtclock_reset is called.
355 mp_disable_preemption();
356 if (cpu_number() != master_cpu
) {
357 mp_enable_preemption();
360 mp_enable_preemption();
363 RtcTime
= &rtclock
.time
;
364 rtc_setvals( CLKNUM
, RTC_MINRES
); /* compute constants */
365 rtc_set_cyc_per_sec(); /* compute number of tsc beats per second */
369 static volatile unsigned int last_ival
= 0;
372 * Get the clock device time. This routine is responsible
373 * for converting the device's machine dependent time value
374 * into a canonical mach_timespec_t value.
378 mach_timespec_t
*cur_time
) /* OUT */
380 mach_timespec_t itime
= {0, 0};
381 unsigned int val
, val2
;
386 cur_time
->tv_nsec
= 0;
387 cur_time
->tv_sec
= 0;
388 return (KERN_SUCCESS
);
392 * Inhibit interrupts. Determine the incremental
393 * time since the last interrupt. (This could be
394 * done in assembler for a bit more speed).
398 READ_8254(val
); /* read clock */
399 READ_8254(val2
); /* read clock */
400 } while ( val2
> val
|| val2
< val
- 10 );
401 if ( val
> clks_per_int_99
) {
402 outb( 0x0a, 0x20 ); /* see if interrupt pending */
403 if ( inb( 0x20 ) & 1 )
404 itime
.tv_nsec
= rtclock
.intr_nsec
; /* yes, add a tick */
406 itime
.tv_nsec
+= ((clks_per_int
- val
) * time_per_clk
) / ZHZ
;
407 if ( itime
.tv_nsec
< last_ival
) {
408 if (rtc_print_lost_tick
)
409 printf( "rtclock: missed clock interrupt.\n" );
411 last_ival
= itime
.tv_nsec
;
412 cur_time
->tv_sec
= rtclock
.time
.tv_sec
;
413 cur_time
->tv_nsec
= rtclock
.time
.tv_nsec
;
415 ADD_MACH_TIMESPEC(cur_time
, ((mach_timespec_t
*)&itime
));
416 return (KERN_SUCCESS
);
420 sysclk_gettime_internal(
421 mach_timespec_t
*cur_time
) /* OUT */
423 mach_timespec_t itime
= {0, 0};
424 unsigned int val
, val2
;
428 cur_time
->tv_nsec
= 0;
429 cur_time
->tv_sec
= 0;
430 return (KERN_SUCCESS
);
434 * Inhibit interrupts. Determine the incremental
435 * time since the last interrupt. (This could be
436 * done in assembler for a bit more speed).
439 READ_8254(val
); /* read clock */
440 READ_8254(val2
); /* read clock */
441 } while ( val2
> val
|| val2
< val
- 10 );
442 if ( val
> clks_per_int_99
) {
443 outb( 0x0a, 0x20 ); /* see if interrupt pending */
444 if ( inb( 0x20 ) & 1 )
445 itime
.tv_nsec
= rtclock
.intr_nsec
; /* yes, add a tick */
447 itime
.tv_nsec
+= ((clks_per_int
- val
) * time_per_clk
) / ZHZ
;
448 if ( itime
.tv_nsec
< last_ival
) {
449 if (rtc_print_lost_tick
)
450 printf( "rtclock: missed clock interrupt.\n" );
452 last_ival
= itime
.tv_nsec
;
453 cur_time
->tv_sec
= rtclock
.time
.tv_sec
;
454 cur_time
->tv_nsec
= rtclock
.time
.tv_nsec
;
455 ADD_MACH_TIMESPEC(cur_time
, ((mach_timespec_t
*)&itime
));
456 return (KERN_SUCCESS
);
460 * Get the clock device time when ALL interrupts are already disabled.
461 * Same as above except for turning interrupts off and on.
462 * This routine is responsible for converting the device's machine dependent
463 * time value into a canonical mach_timespec_t value.
466 sysclk_gettime_interrupts_disabled(
467 mach_timespec_t
*cur_time
) /* OUT */
469 mach_timespec_t itime
= {0, 0};
474 cur_time
->tv_nsec
= 0;
475 cur_time
->tv_sec
= 0;
479 simple_lock(&rtclock
.lock
);
482 * Copy the current time knowing that we cant be interrupted
483 * between the two longwords and so dont need to use MTS_TO_TS
485 READ_8254(val
); /* read clock */
486 if ( val
> clks_per_int_99
) {
487 outb( 0x0a, 0x20 ); /* see if interrupt pending */
488 if ( inb( 0x20 ) & 1 )
489 itime
.tv_nsec
= rtclock
.intr_nsec
; /* yes, add a tick */
491 itime
.tv_nsec
+= ((clks_per_int
- val
) * time_per_clk
) / ZHZ
;
492 if ( itime
.tv_nsec
< last_ival
) {
493 if (rtc_print_lost_tick
)
494 printf( "rtclock: missed clock interrupt.\n" );
496 last_ival
= itime
.tv_nsec
;
497 cur_time
->tv_sec
= rtclock
.time
.tv_sec
;
498 cur_time
->tv_nsec
= rtclock
.time
.tv_nsec
;
499 ADD_MACH_TIMESPEC(cur_time
, ((mach_timespec_t
*)&itime
));
501 simple_unlock(&rtclock
.lock
);
505 // Code to calculate how many processor cycles are in a second...
508 rtc_set_cyc_per_sec()
513 uint32_t c
[15]; // array for holding sampled cycle counts
514 mach_timespec_t tst
[15]; // array for holding time values. NOTE for some reason tv_sec not work
516 for (x
=0; x
<15; x
++) { // quick sample 15 times
519 sysclk_gettime_internal(&tst
[x
]);
520 rdtsc_hilo(&y
, &c
[x
]);
524 for (x
=0; x
<14; x
++) {
525 // simple formula really. calculate the numerator as the number of elapsed processor
526 // cycles * 1000 to adjust for the resolution we want. The denominator is the
527 // elapsed "real" time in nano-seconds. The result will be the processor speed in
528 // Mhz. any overflows will be discarded before they are added
529 if ((c
[x
+1] > c
[x
]) && (tst
[x
+1].tv_nsec
> tst
[x
].tv_nsec
)) {
530 cycles
+= ((uint64_t)(c
[x
+1]-c
[x
]) * NSEC_PER_SEC
) / (uint64_t)(tst
[x
+1].tv_nsec
- tst
[x
].tv_nsec
); // elapsed nsecs
534 if (y
>0) { // we got more than 1 valid sample. This also takes care of the case of if the clock isn't running
535 cycles
= cycles
/ y
; // calc our average
537 rtc_cyc_per_sec
= cycles
;
538 rdtsc_hilo(&rtc_last_int_tsc_hi
, &rtc_last_int_tsc_lo
);
543 get_uptime_cycles(void)
545 // get the time since the last interupt based on the processors TSC ignoring the
548 uint32_t a
,d
,intermediate_lo
,intermediate_hi
,result
;
552 if (d
!= rtc_last_int_tsc_hi
) {
553 newTime
= d
-rtc_last_int_tsc_hi
;
554 newTime
= (newTime
<<32) + (a
-rtc_last_int_tsc_lo
);
557 result
= a
-rtc_last_int_tsc_lo
;
559 __asm__
volatile ( " mul %3 ": "=eax" (intermediate_lo
), "=edx" (intermediate_hi
): "a"(result
), "d"(NSEC_PER_SEC
) );
560 __asm__
volatile ( " div %3": "=eax" (result
): "eax"(intermediate_lo
), "edx" (intermediate_hi
), "ecx" (rtc_cyc_per_sec
) );
566 * Get clock device attributes.
570 clock_flavor_t flavor
,
571 clock_attr_t attr
, /* OUT */
572 mach_msg_type_number_t
*count
) /* IN/OUT */
577 return (KERN_FAILURE
);
580 case CLOCK_GET_TIME_RES
: /* >0 res */
581 #if (NCPUS == 1 || (MP_V1_1 && 0))
583 *(clock_res_t
*) attr
= 1000;
586 #endif /* (NCPUS == 1 || (MP_V1_1 && 0)) && AT386 */
587 case CLOCK_ALARM_CURRES
: /* =0 no alarm */
589 *(clock_res_t
*) attr
= rtclock
.intr_nsec
;
593 case CLOCK_ALARM_MAXRES
:
594 *(clock_res_t
*) attr
= RTC_MAXRES
;
597 case CLOCK_ALARM_MINRES
:
598 *(clock_res_t
*) attr
= RTC_MINRES
;
602 return (KERN_INVALID_VALUE
);
604 return (KERN_SUCCESS
);
608 * Set clock device attributes.
612 clock_flavor_t flavor
,
613 clock_attr_t attr
, /* IN */
614 mach_msg_type_number_t count
) /* IN */
619 clock_res_t new_ires
;
622 return (KERN_FAILURE
);
625 case CLOCK_GET_TIME_RES
:
626 case CLOCK_ALARM_MAXRES
:
627 case CLOCK_ALARM_MINRES
:
628 return (KERN_FAILURE
);
630 case CLOCK_ALARM_CURRES
:
631 new_ires
= *(clock_res_t
*) attr
;
634 * The new resolution must be within the predetermined
635 * range. If the desired resolution cannot be achieved
636 * to within 0.1%, an error is returned.
638 if (new_ires
< RTC_MAXRES
|| new_ires
> RTC_MINRES
)
639 return (KERN_INVALID_VALUE
);
640 freq
= (NSEC_PER_SEC
/ new_ires
);
641 adj
= (((clknum
% freq
) * new_ires
) / clknum
);
642 if (adj
> (new_ires
/ 1000))
643 return (KERN_INVALID_VALUE
);
645 * Record the new alarm resolution which will take effect
646 * on the next HZ aligned clock tick.
649 if ( freq
!= rtc_intr_freq
) {
650 rtclock
.new_ires
= new_ires
;
654 return (KERN_SUCCESS
);
657 return (KERN_INVALID_VALUE
);
662 * Set next alarm time for the clock device. This call
663 * always resets the time to deliver an alarm for the
668 mach_timespec_t
*alarm_time
)
673 rtclock
.alarm_time
= *alarm_time
;
674 RtcAlrm
= &rtclock
.alarm_time
;
679 * Configure the calendar clock.
688 * Initialize calendar clock.
697 * Get the current clock time.
701 mach_timespec_t
*cur_time
) /* OUT */
706 if (!rtclock
.calend_is_set
) {
708 return (KERN_FAILURE
);
711 (void) sysclk_gettime_internal(cur_time
);
712 ADD_MACH_TIMESPEC(cur_time
, &rtclock
.calend_offset
);
715 return (KERN_SUCCESS
);
719 * Set the current clock time.
723 mach_timespec_t
*new_time
)
725 mach_timespec_t curr_time
;
729 (void) sysclk_gettime_internal(&curr_time
);
730 rtclock
.calend_offset
= *new_time
;
731 SUB_MACH_TIMESPEC(&rtclock
.calend_offset
, &curr_time
);
732 rtclock
.calend_is_set
= TRUE
;
735 (void) bbc_settime(new_time
);
737 return (KERN_SUCCESS
);
741 * Get clock device attributes.
745 clock_flavor_t flavor
,
746 clock_attr_t attr
, /* OUT */
747 mach_msg_type_number_t
*count
) /* IN/OUT */
752 return (KERN_FAILURE
);
755 case CLOCK_GET_TIME_RES
: /* >0 res */
756 #if (NCPUS == 1 || (MP_V1_1 && 0))
758 *(clock_res_t
*) attr
= 1000;
761 #else /* (NCPUS == 1 || (MP_V1_1 && 0)) && AT386 */
763 *(clock_res_t
*) attr
= rtclock
.intr_nsec
;
766 #endif /* (NCPUS == 1 || (MP_V1_1 && 0)) && AT386 */
768 case CLOCK_ALARM_CURRES
: /* =0 no alarm */
769 case CLOCK_ALARM_MINRES
:
770 case CLOCK_ALARM_MAXRES
:
771 *(clock_res_t
*) attr
= 0;
775 return (KERN_INVALID_VALUE
);
777 return (KERN_SUCCESS
);
781 clock_adjust_calendar(
787 if (rtclock
.calend_is_set
)
788 ADD_MACH_TIMESPEC_NSEC(&rtclock
.calend_offset
, nsec
);
793 clock_initialize_calendar(void)
795 mach_timespec_t bbc_time
, curr_time
;
798 if (bbc_gettime(&bbc_time
) != KERN_SUCCESS
)
802 if (!rtclock
.calend_is_set
) {
803 (void) sysclk_gettime_internal(&curr_time
);
804 rtclock
.calend_offset
= bbc_time
;
805 SUB_MACH_TIMESPEC(&rtclock
.calend_offset
, &curr_time
);
806 rtclock
.calend_is_set
= TRUE
;
812 clock_get_calendar_offset(void)
814 mach_timespec_t result
= MACH_TIMESPEC_ZERO
;
818 if (rtclock
.calend_is_set
)
819 result
= rtclock
.calend_offset
;
827 mach_timebase_info_t info
)
832 info
->numer
= info
->denom
= 1;
837 clock_set_timer_deadline(
843 rtclock
.timer_deadline
= deadline
;
844 rtclock
.timer_is_set
= TRUE
;
849 clock_set_timer_func(
850 clock_timer_func_t func
)
855 if (rtclock
.timer_expire
== NULL
)
856 rtclock
.timer_expire
= func
;
863 * Load the count register and start the clock.
865 #define RTCLOCK_RESET() { \
866 outb(PITCTL_PORT, PIT_C0|PIT_NDIVMODE|PIT_READMODE); \
867 outb(PITCTR0_PORT, (clks_per_int & 0xff)); \
868 outb(PITCTR0_PORT, (clks_per_int >> 8)); \
872 * Reset the clock device. This causes the realtime clock
873 * device to reload its mode and count value (frequency).
874 * Note: the CPU should be calibrated
875 * before starting the clock for the first time.
883 #if NCPUS > 1 && !(MP_V1_1 && 0)
884 mp_disable_preemption();
885 if (cpu_number() != master_cpu
) {
886 mp_enable_preemption();
889 mp_enable_preemption();
890 #endif /* NCPUS > 1 && AT386 && !MP_V1_1 */
897 * Real-time clock device interrupt. Called only on the
898 * master processor. Updates the clock time and upcalls
899 * into the higher level clock code to deliver alarms.
905 mach_timespec_t clock_time
;
910 * Update clock time. Do the update so that the macro
911 * MTS_TO_TS() for reading the mapped time works (e.g.
912 * update in order: mtv_csec, mtv_time.tv_nsec, mtv_time.tv_sec).
915 rdtsc_hilo(&rtc_last_int_tsc_hi
, &rtc_last_int_tsc_lo
);
916 i
= rtclock
.time
.tv_nsec
+ rtclock
.intr_nsec
;
917 if (i
< NSEC_PER_SEC
)
918 rtclock
.time
.tv_nsec
= i
;
920 rtclock
.time
.tv_nsec
= i
- NSEC_PER_SEC
;
921 rtclock
.time
.tv_sec
++;
923 /* note time now up to date */
926 rtclock
.abstime
+= rtclock
.intr_nsec
;
927 abstime
= rtclock
.abstime
;
928 if ( rtclock
.timer_is_set
&&
929 rtclock
.timer_deadline
<= abstime
) {
930 rtclock
.timer_is_set
= FALSE
;
933 (*rtclock
.timer_expire
)(abstime
);
939 * Perform alarm clock processing if needed. The time
940 * passed up is incremented by a half-interrupt tick
941 * to trigger alarms closest to their desired times.
942 * The clock_alarm_intr() routine calls sysclk_setalrm()
943 * before returning if later alarms are pending.
946 if (RtcAlrm
&& (RtcAlrm
->tv_sec
< RtcTime
->tv_sec
||
947 (RtcAlrm
->tv_sec
== RtcTime
->tv_sec
&&
948 RtcDelt
>= RtcAlrm
->tv_nsec
- RtcTime
->tv_nsec
))) {
949 clock_time
.tv_sec
= 0;
950 clock_time
.tv_nsec
= RtcDelt
;
951 ADD_MACH_TIMESPEC (&clock_time
, RtcTime
);
955 * Call clock_alarm_intr() without RTC-lock.
956 * The lock ordering is always CLOCK-lock
959 clock_alarm_intr(SYSTEM_CLOCK
, &clock_time
);
964 * On a HZ-tick boundary: return 0 and adjust the clock
965 * alarm resolution (if requested). Otherwise return a
968 if ((i
= --rtc_intr_count
) == 0) {
969 if (rtclock
.new_ires
) {
970 rtc_setvals(new_clknum
, rtclock
.new_ires
);
971 RTCLOCK_RESET(); /* lock clock register */
972 rtclock
.new_ires
= 0;
974 rtc_intr_count
= rtc_intr_hertz
;
988 ticks
= get_uptime_cycles();
989 *result
= rtclock
.abstime
;
996 clock_interval_to_deadline(
998 uint32_t scale_factor
,
1003 clock_get_uptime(result
);
1005 clock_interval_to_absolutetime_interval(interval
, scale_factor
, &abstime
);
1011 clock_interval_to_absolutetime_interval(
1013 uint32_t scale_factor
,
1016 *result
= (uint64_t)interval
* scale_factor
;
1020 clock_absolutetime_interval_to_deadline(
1024 clock_get_uptime(result
);
1030 absolutetime_to_nanoseconds(
1038 nanoseconds_to_absolutetime(
1039 uint64_t nanoseconds
,
1042 *result
= nanoseconds
;
1046 * measure_delay(microseconds)
1048 * Measure elapsed time for delay calls
1049 * Returns microseconds.
1051 * Microseconds must not be too large since the counter (short)
1052 * will roll over. Max is about 13 ms. Values smaller than 1 ms are ok.
1053 * This uses the assumed frequency of the rt clock which is emperically
1054 * accurate to only about 200 ppm.
1061 unsigned int lsb
, val
;
1063 outb(PITCTL_PORT
, PIT_C0
|PIT_NDIVMODE
|PIT_READMODE
);
1064 outb(PITCTR0_PORT
, 0xff); /* set counter to max value */
1065 outb(PITCTR0_PORT
, 0xff);
1067 outb(PITCTL_PORT
, PIT_C0
);
1068 lsb
= inb(PITCTR0_PORT
);
1069 val
= (inb(PITCTR0_PORT
) << 8) | lsb
;
1077 * calibrate_delay(void)
1079 * Adjust delaycount. Called from startup before clock is started
1080 * for normal interrupt generation.
1084 calibrate_delay(void)
1090 printf("adjusting delay count: %d", delaycount
);
1091 for (i
=0; i
<10; i
++) {
1094 * microdata must not be too large since measure_timer
1095 * will not return accurate values if the counter (short)
1098 val
= measure_delay(microdata
);
1102 delaycount
*= microdata
;
1103 delaycount
+= val
-1; /* round up to upper us */
1106 if (delaycount
<= 0)
1108 if (delaycount
!= prev
)
1109 printf(" %d", delaycount
);
1123 for (i
= 0; i
< 10; i
++)
1124 printf("%d, %d\n", i
, measure_delay(i
));
1125 for (i
= 10; i
<= 100; i
+=10)
1126 printf("%d, %d\n", i
, measure_delay(i
));
1128 #endif /* MACH_KDB */