// XtratuM
// version: 0.1
//
// (c) 2004, Miguel Masmano <mimastel@doctor.upv.es>
// Released under the terms of GPL License v2

#ifndef XtratuM_TIMER_H_
#define XtratuM_TIMER_H_

#include <arch/XtratuM_timer_arch.h>

#define PERIODIC_MODE 0x0
#define ONESHOOT_MODE 0x1

#define NS_PER_S 1000000000

// xm_timer_info_t is the structure used to send 
// to the domain the features of each timer
typedef struct xm_timer_info_struct {
  hwtime_t freq;
  int timer_event;
} xm_timer_info_t;

// Following structure is used for each domain to know the
// state of each enabled timer
typedef struct xm_timer_param_struct {
  hwtime_t hwtime;
  hwtime_t period;
} xm_timer_param_t;

#include <heap.h>

// Following structure allows to manage each existing timer
// the timers are defined in the architecture directory
typedef struct xm_arch_timer_struct {
  hwtime_t freq; 
  hwtime_t overhead;
  hwtime_t safe_longest_timer_interval;
  int compulsory_timer_reprogramming;
  int timer_event;
  int xm_timer_param_pos;
  int (*init_hwtimer) (void);
  void (*uninit_hwtimer) (void);
  hwtime_t (*read_hwtimer) (void);
  void (*write_hwtimer) (hwtime_t time);
  heap_t heap;
} xm_arch_timer_t;

static inline duration_t hwtime2nsec (hwtime_t th, hwtime_t xm_timer_freq) {
  duration_t s = th / xm_timer_freq;
  
  return s * NS_PER_S + ((th - s * xm_timer_freq)*NS_PER_S)/ xm_timer_freq;
}

static inline hwtime_t nsec2hwtime (duration_t d, hwtime_t xm_timer_freq) {
  hwtime_t s = d / NS_PER_S;
  return s * xm_timer_freq + ((d - s * NS_PER_S) * xm_timer_freq) / NS_PER_S;
}
/*
static inline duration_t hwtime2nsec (hwtime_t th, hwtime_t xm_timer_freq) {
  return (th * NS_PER_S) / xm_timer_freq;
}

static inline hwtime_t nsec2hwtime (duration_t d, hwtime_t xm_timer_freq) {
  return (d * xm_timer_freq) / NS_PER_S;
  }*/

extern xm_arch_timer_t *xm_getbestclock(void);
extern void xm_get_timer_info (xm_arch_timer_t *timer, 
			       xm_timer_info_t *timer_info);
extern void xm_getcpufreq(hwtime_t *freq);
extern void xm_gethwtime (xm_arch_timer_t *timer, hwtime_t *time);
extern void xm_sethwtimer (int mode, hwtime_t time, 
			   xm_arch_timer_t *timer);
extern void xm_timer_handler (int event, xm_arch_timer_t *timer);
extern void xm_remove_domain_from_timers (struct xm_domain_struct *d);
extern void xm_init_timers (void);
extern void xm_uninit_timers (void);

#endif
