-#define DISPLAYENTER(x) printf("[RTCLOCK] entering " #x "\n");
-#define DISPLAYEXIT(x) printf("[RTCLOCK] leaving " #x "\n");
-#define DISPLAYVALUE(x,y) printf("[RTCLOCK] " #x ":" #y " = 0x%08x \n",y);
-
-int sysclk_config(void);
-
-int sysclk_init(void);
-
-kern_return_t sysclk_gettime(
- mach_timespec_t *cur_time);
-
-kern_return_t sysclk_getattr(
- clock_flavor_t flavor,
- clock_attr_t attr,
- mach_msg_type_number_t *count);
-
-kern_return_t sysclk_setattr(
- clock_flavor_t flavor,
- clock_attr_t attr,
- mach_msg_type_number_t count);
-
-void sysclk_setalarm(
- mach_timespec_t *alarm_time);
-
-extern void (*IOKitRegisterInterruptHook)(void *, int irq, int isclock);
-
-/*
- * Lists of clock routines.
- */
-struct clock_ops sysclk_ops = {
- sysclk_config, sysclk_init,
- sysclk_gettime, 0,
- sysclk_getattr, sysclk_setattr,
- sysclk_setalarm,
-};
-
-int calend_config(void);
-
-int calend_init(void);
-
-kern_return_t calend_gettime(
- mach_timespec_t *cur_time);
-
-kern_return_t calend_getattr(
- clock_flavor_t flavor,
- clock_attr_t attr,
- mach_msg_type_number_t *count);
-
-struct clock_ops calend_ops = {
- calend_config, calend_init,
- calend_gettime, 0,
- calend_getattr, 0,
- 0,
-};
-
-/* local data declarations */
-mach_timespec_t *RtcTime = (mach_timespec_t *)0;
-mach_timespec_t *RtcAlrm;
-clock_res_t RtcDelt;
-
-/* global data declarations */
-struct {
- uint64_t abstime;
-
- mach_timespec_t time;
- mach_timespec_t alarm_time; /* time of next alarm */
-
- mach_timespec_t calend_offset;
- boolean_t calend_is_set;
-
- int64_t calend_adjtotal;
- int32_t calend_adjdelta;
-
- uint64_t timer_deadline;
- boolean_t timer_is_set;
- clock_timer_func_t timer_expire;
-
- clock_res_t new_ires; /* pending new resolution (nano ) */
- clock_res_t intr_nsec; /* interrupt resolution (nano) */
- mach_timebase_info_data_t timebase_const;
-
- decl_simple_lock_data(,lock) /* real-time clock device lock */
-} rtclock;
-
-unsigned int clknum; /* clks per second */
-unsigned int new_clknum; /* pending clknum */
-unsigned int time_per_clk; /* time per clk in ZHZ */
-unsigned int clks_per_int; /* clks per interrupt */
-unsigned int clks_per_int_99;
-int rtc_intr_count; /* interrupt counter */
-int rtc_intr_hertz; /* interrupts per HZ */
-int rtc_intr_freq; /* interrupt frequency */
-int rtc_print_lost_tick; /* print lost tick */
-
-uint32_t rtc_cyc_per_sec; /* processor cycles per seconds */
-uint32_t rtc_quant_scale; /* used internally to convert clocks to nanos */
-
-/*
- * Macros to lock/unlock real-time clock device.
- */
-#define LOCK_RTC(s) \
-MACRO_BEGIN \
- (s) = splclock(); \
- simple_lock(&rtclock.lock); \
-MACRO_END
-
-#define UNLOCK_RTC(s) \
-MACRO_BEGIN \
- simple_unlock(&rtclock.lock); \
- splx(s); \
-MACRO_END
-
-/*
- * i8254 control. ** MONUMENT **
- *
- * The i8254 is a traditional PC device with some arbitrary characteristics.
- * Basically, it is a register that counts at a fixed rate and can be
- * programmed to generate an interrupt every N counts. The count rate is
- * clknum counts per second (see pit.h), historically 1193167 we believe.
- * Various constants are computed based on this value, and we calculate
- * them at init time for execution efficiency. To obtain sufficient
- * accuracy, some of the calculation are most easily done in floating
- * point and then converted to int.
- *
- * We want an interrupt every 10 milliseconds, approximately. The count
- * which will do that is clks_per_int. However, that many counts is not
- * *exactly* 10 milliseconds; it is a bit more or less depending on
- * roundoff. The actual time per tick is calculated and saved in
- * rtclock.intr_nsec, and it is that value which is added to the time
- * register on each tick.
- *
- * The i8254 counter can be read between interrupts in order to determine
- * the time more accurately. The counter counts down from the preset value
- * toward 0, and we have to handle the case where the counter has been
- * reset just before being read and before the interrupt has been serviced.
- * Given a count since the last interrupt, the time since then is given
- * by (count * time_per_clk). In order to minimize integer truncation,
- * we perform this calculation in an arbitrary unit of time which maintains
- * the maximum precision, i.e. such that one tick is 1.0e9 of these units,
- * or close to the precision of a 32-bit int. We then divide by this unit
- * (which doesn't lose precision) to get nanoseconds. For notation
- * purposes, this unit is defined as ZHZ = zanoseconds per nanosecond.
- *
- * This sequence to do all this is in sysclk_gettime. For efficiency, this
- * sequence also needs the value that the counter will have if it has just
- * overflowed, so we precompute that also.
- *
- * The fix for certain really old certain platforms has been removed
- * (specifically the DEC XL5100) have been observed to have problem
- * with latching the counter, and they occasionally (say, one out of
- * 100,000 times) return a bogus value. Hence, the present code reads
- * the counter twice and checks for a consistent pair of values.
- * the code was:
- * do {
- * READ_8254(val);
- * READ_8254(val2);
- * } while ( val2 > val || val2 < val - 10 );
- *
- *
- * Some attributes of the rt clock can be changed, including the
- * interrupt resolution. We default to the minimum resolution (10 ms),
- * but allow a finer resolution to be requested. The assumed frequency
- * of the clock can also be set since it appears that the actual
- * frequency of real-world hardware can vary from the nominal by
- * 200 ppm or more. When the frequency is set, the values above are
- * recomputed and we continue without resetting or changing anything else.
- */
-#define RTC_MINRES (NSEC_PER_SEC / HZ) /* nsec per tick */
-#define RTC_MAXRES (RTC_MINRES / 20) /* nsec per tick */
-#define ZANO (1000000000)
-#define ZHZ (ZANO / (NSEC_PER_SEC / HZ))
-#define READ_8254(val) { \
- outb(PITCTL_PORT, PIT_C0); \
- (val) = inb(PITCTR0_PORT); \
- (val) |= inb(PITCTR0_PORT) << 8 ; }