+++ /dev/null
-/*
- * Copyright (c) 2000-2008 Apple Inc. All rights reserved.
- *
- * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. The rights granted to you under the License
- * may not be used to create, or enable the creation or redistribution of,
- * unlawful or unlicensed copies of an Apple operating system, or to
- * circumvent, violate, or enable the circumvention or violation of, any
- * terms of an Apple operating system software license agreement.
- *
- * Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
- */
-/*
- * @OSF_COPYRIGHT@
- */
-/*
- * @APPLE_FREE_COPYRIGHT@
- */
-/*
- * File: rtclock.c
- * Purpose: Routines for handling the machine dependent
- * real-time clock.
- */
-
-#include <mach/mach_types.h>
-
-#include <kern/clock.h>
-#include <kern/thread.h>
-#include <kern/processor.h>
-#include <kern/macro_help.h>
-#include <kern/spl.h>
-#include <kern/pms.h>
-
-#include <machine/commpage.h>
-#include <machine/machine_routines.h>
-#include <ppc/exception.h>
-#include <ppc/proc_reg.h>
-#include <ppc/rtclock.h>
-
-#include <sys/kdebug.h>
-
-int rtclock_config(void);
-
-int rtclock_init(void);
-
-#define NSEC_PER_HZ (NSEC_PER_SEC / 100)
-
-static uint32_t rtclock_sec_divisor;
-
-static mach_timebase_info_data_t rtclock_timebase_const;
-
-static boolean_t rtclock_timebase_initialized;
-
-decl_simple_lock_data(static,rtclock_lock)
-
-/*
- * 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
-
-static void
-timebase_callback(
- struct timebase_freq_t *freq)
-{
- uint32_t numer, denom;
- spl_t s;
-
- if ( freq->timebase_den < 1 || freq->timebase_den > 4 ||
- freq->timebase_num < freq->timebase_den )
- panic("rtclock timebase_callback: invalid constant %lu / %lu",
- freq->timebase_num, freq->timebase_den);
-
- denom = freq->timebase_num;
- numer = freq->timebase_den * NSEC_PER_SEC;
-
- LOCK_RTC(s);
- if (!rtclock_timebase_initialized) {
- commpage_set_timestamp(0,0,0);
-
- rtclock_timebase_const.numer = numer;
- rtclock_timebase_const.denom = denom;
- rtclock_sec_divisor = freq->timebase_num / freq->timebase_den;
-
- ml_init_lock_timeout();
- }
- else {
- UNLOCK_RTC(s);
- printf("rtclock timebase_callback: late old %d / %d new %d / %d\n",
- rtclock_timebase_const.numer, rtclock_timebase_const.denom,
- numer, denom);
- return;
- }
- UNLOCK_RTC(s);
-
- clock_timebase_init();
-}
-
-/*
- * Configure the system clock device.
- */
-int
-rtclock_config(void)
-{
- simple_lock_init(&rtclock_lock, 0);
-
- PE_register_timebase_callback(timebase_callback);
-
- return (1);
-}
-
-/*
- * Initialize the system clock device.
- */
-int
-rtclock_init(void)
-{
- etimer_resync_deadlines(); /* Start the timers going */
-
- return (1);
-}
-
-void
-clock_get_system_microtime(
- uint32_t *secs,
- uint32_t *microsecs)
-{
- uint64_t now, t64;
- uint32_t divisor;
-
- now = mach_absolute_time();
-
- *secs = t64 = now / (divisor = rtclock_sec_divisor);
- now -= (t64 * divisor);
- *microsecs = (now * USEC_PER_SEC) / divisor;
-}
-
-void
-clock_get_system_nanotime(
- uint32_t *secs,
- uint32_t *nanosecs)
-{
- uint64_t now, t64;
- uint32_t divisor;
-
- now = mach_absolute_time();
-
- *secs = t64 = now / (divisor = rtclock_sec_divisor);
- now -= (t64 * divisor);
- *nanosecs = (now * NSEC_PER_SEC) / divisor;
-}
-
-void
-clock_gettimeofday_set_commpage(
- uint64_t abstime,
- uint64_t epoch,
- uint64_t offset,
- uint32_t *secs,
- uint32_t *microsecs)
-{
- uint64_t t64, now = abstime;
-
- simple_lock(&rtclock_lock);
-
- now += offset;
-
- *secs = t64 = now / rtclock_sec_divisor;
- now -= (t64 * rtclock_sec_divisor);
- *microsecs = (now * USEC_PER_SEC) / rtclock_sec_divisor;
-
- *secs += epoch;
-
- commpage_set_timestamp(abstime - now, *secs, rtclock_sec_divisor);
-
- simple_unlock(&rtclock_lock);
-}
-
-void
-clock_timebase_info(
- mach_timebase_info_t info)
-{
- spl_t s;
-
- LOCK_RTC(s);
- *info = rtclock_timebase_const;
- rtclock_timebase_initialized = TRUE;
- UNLOCK_RTC(s);
-}
-
-void
-clock_interval_to_absolutetime_interval(
- uint32_t interval,
- uint32_t scale_factor,
- uint64_t *result)
-{
- uint64_t nanosecs = (uint64_t)interval * scale_factor;
- uint64_t t64;
- uint32_t divisor;
-
- *result = (t64 = nanosecs / NSEC_PER_SEC) *
- (divisor = rtclock_sec_divisor);
- nanosecs -= (t64 * NSEC_PER_SEC);
- *result += (nanosecs * divisor) / NSEC_PER_SEC;
-}
-
-void
-absolutetime_to_microtime(
- uint64_t abstime,
- uint32_t *secs,
- uint32_t *microsecs)
-{
- uint64_t t64;
- uint32_t divisor;
-
- *secs = t64 = abstime / (divisor = rtclock_sec_divisor);
- abstime -= (t64 * divisor);
- *microsecs = (abstime * USEC_PER_SEC) / divisor;
-}
-
-void
-absolutetime_to_nanotime(
- uint64_t abstime,
- uint32_t *secs,
- uint32_t *nanosecs)
-{
- uint64_t t64;
- uint32_t divisor;
-
- *secs = t64 = abstime / (divisor = rtclock_sec_divisor);
- abstime -= (t64 * divisor);
- *nanosecs = (abstime * NSEC_PER_SEC) / divisor;
-}
-
-void
-nanotime_to_absolutetime(
- uint32_t secs,
- uint32_t nanosecs,
- uint64_t *result)
-{
- uint32_t divisor = rtclock_sec_divisor;
-
- *result = ((uint64_t)secs * divisor) +
- ((uint64_t)nanosecs * divisor) / NSEC_PER_SEC;
-}
-
-void
-absolutetime_to_nanoseconds(
- uint64_t abstime,
- uint64_t *result)
-{
- uint64_t t64;
- uint32_t divisor;
-
- *result = (t64 = abstime / (divisor = rtclock_sec_divisor)) * NSEC_PER_SEC;
- abstime -= (t64 * divisor);
- *result += (abstime * NSEC_PER_SEC) / divisor;
-}
-
-void
-nanoseconds_to_absolutetime(
- uint64_t nanosecs,
- uint64_t *result)
-{
- uint64_t t64;
- uint32_t divisor;
-
- *result = (t64 = nanosecs / NSEC_PER_SEC) *
- (divisor = rtclock_sec_divisor);
- nanosecs -= (t64 * NSEC_PER_SEC);
- *result += (nanosecs * divisor) / NSEC_PER_SEC;
-}
-
-void
-machine_delay_until(
- uint64_t deadline)
-{
- uint64_t now;
-
- do {
- now = mach_absolute_time();
- } while (now < deadline);
-}