Index: linus/include/linux/mmtimer.h =================================================================== --- linus.orig/include/linux/mmtimer.h 2004-09-27 12:19:27.000000000 -0700 +++ linus/include/linux/mmtimer.h 2004-09-30 13:11:43.000000000 -0700 @@ -53,4 +53,5 @@ #define MMTIMER_MMAPAVAIL _IO(MMTIMER_IOCTL_BASE, 6) #define MMTIMER_GETCOUNTER _IOR(MMTIMER_IOCTL_BASE, 9, unsigned long) +#define CLOCK_SGI_CYCLE 10 #endif /* _LINUX_MMTIMER_H */ Index: linus/include/linux/time.h =================================================================== --- linus.orig/include/linux/time.h 2004-09-30 13:07:33.000000000 -0700 +++ linus/include/linux/time.h 2004-09-30 13:11:31.000000000 -0700 @@ -415,7 +415,7 @@ #define CLOCK_REALTIME_HR 4 #define CLOCK_MONOTONIC_HR 5 -#define MAX_CLOCKS 6 +#define MAX_CLOCKS 16 #define CLOCKS_MASK (CLOCK_REALTIME | CLOCK_MONOTONIC | \ CLOCK_REALTIME_HR | CLOCK_MONOTONIC_HR) #define CLOCKS_MONO (CLOCK_MONOTONIC & CLOCK_MONOTONIC_HR) Index: linus/drivers/char/mmtimer.c =================================================================== --- linus.orig/drivers/char/mmtimer.c 2004-09-27 12:19:27.000000000 -0700 +++ linus/drivers/char/mmtimer.c 2004-09-30 13:45:54.000000000 -0700 @@ -28,6 +28,7 @@ #include #include #include +#include MODULE_AUTHOR("Jesse Barnes "); MODULE_DESCRIPTION("Multimedia timer support"); @@ -177,6 +178,44 @@ &mmtimer_fops }; +struct timespec sgi_clock_offset; + +int sgi_clock_get(struct timespec *tp) { + u64 nsec; + + nsec = *(u64 *) RTC_COUNTER_ADDR * sn_rtc_cycles_per_second + + sgi_clock_offset.tv_nsec; + tp->tv_sec = div_long_long_rem(nsec, NSEC_PER_SEC, &tp->tv_nsec) + + sgi_clock_offset.tv_sec; + return 0; +}; + +int sgi_clock_set(struct timespec *tp) { + + u64 nsec; + u64 rem; + + nsec = *(u64 *)RTC_COUNTER_ADDR * sn_rtc_cycles_per_second; + + sgi_clock_offset.tv_sec = tp->tv_sec - div_long_long_rem(nsec, NSEC_PER_SEC, &rem); + + if (rem <= tp->tv_nsec) + sgi_clock_offset.tv_nsec = tp->tv_sec - rem; + else { + sgi_clock_offset.tv_nsec = tp->tv_sec + NSEC_PER_SEC - rem; + sgi_clock_offset.tv_sec--; + } + return 0; +} + +static struct k_clock sgi_clock = { + .res = 0, + .clock_set = sgi_clock_set, + .clock_get = sgi_clock_get, + .timer_create = do_posix_clock_notimer_create, + .nsleep = do_posix_clock_nonanosleep +}; + /** * mmtimer_init - device initialization routine * @@ -206,6 +245,9 @@ return -1; } + sgi_clock.res = sn_rtc_cycles_per_second; + register_posix_clock(CLOCK_SGI_CYCLE, &sgi_clock); + printk(KERN_INFO "%s: v%s, %ld MHz\n", MMTIMER_DESC, MMTIMER_VERSION, sn_rtc_cycles_per_second/(unsigned long)1E6);