#ifndef __RTL_ARCH_TIME_H__
#define __RTL_ARCH_TIME_H__

/*
 * rtl_time.h
 *
 * x86 hardware clock interface
 *
 * Copyright (C) 1999 Michael Barabanov
 * Released under the terms of the GPL
 *
 */

/* begin of what each arch should declare */

typedef long long hrtime_t; /* high-resolution time type (signed 64-bit) */


extern inline hrtime_t timespec_to_ns (const struct timespec *ts)
{
	long long t;

	__asm__("imull %%edx\n"
		"add %%ebx, %%eax\n\t"
		"adc $0, %%edx\n\t"
		:"=A" (t)
		: "a" (ts->tv_sec), "d" (NSECS_PER_SEC), "b" (ts->tv_nsec)
		);
	return t;
}

extern inline struct timespec timespec_from_ns (hrtime_t t)
{
	struct timespec ts;
	__asm__("idivl %%ecx\n\t"
		:"=a" (ts.tv_sec), "=d" (ts.tv_nsec)
		: "A" (t), "c" (NSECS_PER_SEC)
		);
	if (ts.tv_nsec < 0) {
		ts.tv_nsec += NSECS_PER_SEC;
		ts.tv_sec --;
	}
	return ts;
}

#ifdef __KERNEL__
#include <linux/time.h>
#include <linux/tasks.h>
#include <asm/ptrace.h>
#include <asm/smp.h>

extern hrtime_t gethrtime(void); /* time in nanoseconds since bootup */
extern hrtime_t gethrtimeres(void); /* resolution of gethrtime() in ns */

struct rtl_clock_arch {
	int istimerset;
	int count_irqs;
	int apic_cpu;
	hrtime_t linux_time;
};

#define RTL_CLOCK_ARCH_INITIALIZER { 0, 0, 0, 0 }


/* end of public arch declarations */



extern struct rtl_clock _i8254_clock __attribute__ ((aligned (64)));
#define CLOCK_8254 (&_i8254_clock)

#ifdef __SMP__
extern struct rtl_clock _apic_clock[NR_CPUS] __attribute__ ((aligned (64)));
#define CLOCK_APIC (&_apic_clock[rtl_getcpuid()])
#endif


/* TODO
extern clockid_t CLOCK_RTC;
 */


#define DECLARE_CPUID(cpu_id)   unsigned int cpu_id = rtl_getcpuid()

#include <linux/delay.h>

extern __inline__ unsigned long muldiv(unsigned long a, unsigned long mul, unsigned long div)
{
	int temp;
       __asm__("mull %2 ; divl %3"
               :"=a" (a), "=d" (temp)
               :"1" (mul),
                "c" (div),
                "0" (a)
               );
       return a;
}

extern long rtl_delay_mult;

/*
static inline void rtl_delay(long nanoseconds)
{
	__asm__("mull %0"
		:"=d" (nanoseconds)
		:"a" (nanoseconds),"0" (rtl_delay_mult)
		:"ax");
		
	__delay(nanoseconds);
}
*/

static inline void rtl_delay(long nanoseconds)
{
	int d0;
	__asm__("mull %0"
		:"=d" (nanoseconds), "=&a" (d0)
		:"1" (nanoseconds), "0" (rtl_delay_mult));

	__delay(nanoseconds);
}


extern int I8253_channel2_free(void);

#endif


#endif

