#ifndef __CANO_PHASE_DVFS_LKM_H__
#define __CANO_PHASE_DVFS_LKM_H__

#include <asm/msr.h>  /*for macros IA32 constant and fast macros rdtsc/rdpmc*/

#define MAX_SYSCALLS 16
#define FIRST_SYSCALL 227
/* DVFS */
#define DVFS_MAX_SYSCALLS 16
#define DVFS_FIRST_SYSCALL 244


#define SYSCALL_NO_sys_readpmu       (FIRST_SYSCALL + 0)
#define SYSCALL_NO_sys_wr_msr_32     (FIRST_SYSCALL + 1)
#define SYSCALL_NO_sys_wr_msr_40     (FIRST_SYSCALL + 2)
#define SYSCALL_NO_sys_wr_msr_bit    (FIRST_SYSCALL + 3)
#define SYSCALL_NO_sys_rd_msr        (FIRST_SYSCALL + 4)
#define SYSCALL_NO_sys_copy_sample_log              (FIRST_SYSCALL + 5) /* CANO-2005 */
#define SYSCALL_NO_sys_kernel_PMU_log_on_off        (FIRST_SYSCALL + 6) /* CANO-2005 */
#define SYSCALL_NO_sys_set_delta_ins                (FIRST_SYSCALL + 7) /* CANO-2005 */

#define SYSCALL_NO_sys_flagComponent (FIRST_SYSCALL + 8) // 8 for compatibility

/* DVFS */
#define SYSCALL_NO_sys_set_target_f      (DVFS_FIRST_SYSCALL + 0)
#define SYSCALL_NO_sys_get_current_f_V   (DVFS_FIRST_SYSCALL + 1)
#define SYSCALL_NO_sys_get_target_f_V    (DVFS_FIRST_SYSCALL + 2)
#define SYSCALL_NO_sys_write_paraport    (DVFS_FIRST_SYSCALL + 3)

/* specific regs etc for DVFS (qiang's) */
#define MSR_IA32_MISC_ENABLE  0x1a0
#define MSR_IA32_PERF_STATUS  0x198
#define MSR_IA32_PERF_CTL  0x199
/* THESE ARE FOR CONVERSIONS: */
#define MSRVALUE(mhz, mv) (  ( ((mhz)/100)<<8 ) | ( ((mv) -700)/16 )   )
#define MSR2MHZ(msr)  (   ( ((msr)>>8) &0xff ) *100  )
#define MSR2MV(msr)   (   ((msr)& 0xff)*16 + 700   )


#define readpmu(POINTER)                                                \
__asm__ __volatile__ ("movl %0, %%eax\n\t"                              \
                      "movl %1, %%ebx\n\t"                              \
                      "int $0x80\n\t"                                   \
        :                                                               \
	: "i"(SYSCALL_NO_sys_readpmu),"mi"((long)(POINTER))             \
	: "eax","ebx", "ecx")



#define wr_msr_bit(MSR, BIT_POS, VALUE)                 \
__asm__ __volatile__ ("movl %0, %%eax\n\t"                             \
                      "movl %1, %%ebx\n\t"                             \
                      "movl %2, %%ecx\n\t"                             \
                      "movl %3, %%edx\n\t"                             \
                      "int $0x80\n\t"                                  \
        :                                                          \
	: "i" (SYSCALL_NO_sys_wr_msr_bit),"mi" ((long)(MSR)),"mi" ((long)(BIT_POS)), \
		  "mi" ((long)(VALUE))) 

#define wr_msr_32(MSR, VALUE)                           \
__asm__ __volatile__ ("movl %0, %%eax\n\t"                             \
                      "movl %1, %%ebx\n\t"                             \
                      "movl %2, %%ecx\n\t"                             \
                      "int $0x80\n\t"                                  \
        :                                                              \
	: "i" (SYSCALL_NO_sys_wr_msr_32),"mi" ((long)(MSR)),"mi" ((long)(VALUE))  \
	: "eax","ebx","ecx")

#define wr_msr_40(MSR, VALUE)                            \
__asm__ __volatile__ ("movl %0, %%eax\n\t"                             \
                      "movl %1, %%ebx\n\t"                             \
                      "movl %2, %%ecx\n\t"                             \
                      "int $0x80\n\t"                                  \
        :                                                              \
	: "i" (SYSCALL_NO_sys_wr_msr_40),"mi" ((long)(MSR)),"mi" ((long)(VALUE))  \
        : "eax","ebx","ecx")  

#define rd_msr(MSR, POINTER)                                           \
__asm__ __volatile__ ("movl %0, %%eax\n\t"                             \
                      "movl %1, %%ebx\n\t"                             \
                      "movl %2, %%ecx\n\t"                             \
                      "int $0x80\n\t"                                  \
        :                                                              \
	: "i" (SYSCALL_NO_sys_rd_msr),"mi" ((long)(MSR)),"mi" ((long)(POINTER))  \
        : "eax","ebx","ecx")  

#define flagComponent(TYPE, FLAG)                                       \
__asm__ __volatile__ ("movl %0, %%eax\n\t"                              \
                      "movl %1, %%ebx\n\t"                              \
                      "movl %2, %%ecx\n\t"                              \
                      "int $0x80\n\t"                                   \
        :                                                               \
	: "i"(SYSCALL_NO_sys_flagComponent),"mi"((long)(TYPE)) ,"mi" ((long)(FLAG))     \
	: "eax","ebx", "ecx")

/* CANO-2005 */
#define copy_sample_log(LOG_PTR, NUM_SAMPLES_PTR)                                 \
__asm__ __volatile__ ("movl %0, %%eax\n\t"                             \
                      "movl %1, %%ebx\n\t"                             \
                      "movl %2, %%ecx\n\t"                             \
                      "int $0x80\n\t"                                  \
        :                                                              \
	: "i" (SYSCALL_NO_sys_copy_sample_log),"mi" ((unsigned long long **)(LOG_PTR)),"mi" ((int *)(NUM_SAMPLES_PTR))  \
        : "eax","ebx","ecx")  

#define kernel_PMU_log_on_off(ON_OFF)                                 \
__asm__ __volatile__ ("movl %0, %%eax\n\t"                             \
                      "movl %1, %%ebx\n\t"                             \
                      "int $0x80\n\t"                                  \
        :                                                              \
	: "i" (SYSCALL_NO_sys_kernel_PMU_log_on_off),"mi" ((int)(ON_OFF))  \
        : "eax","ebx","ecx")  

#define set_delta_ins(VAL)                                 \
__asm__ __volatile__ ("movl %0, %%eax\n\t"                             \
                      "movl %1, %%ebx\n\t"                             \
                      "int $0x80\n\t"                                  \
        :                                                              \
	: "i" (SYSCALL_NO_sys_set_delta_ins),"mi" ((int)(VAL))  \
        : "eax","ebx","ecx")  

/* DVFS */
#define set_target_f(freq)                                                \
__asm__ __volatile__ ("movl %0, %%eax\n\t"                              \
                      "movl %1, %%ebx\n\t"                              \
                      "int $0x80\n\t"                                   \
        :                                                               \
	: "i"(SYSCALL_NO_sys_set_target_f),"mi"((unsigned)(freq))             \
	: "eax","ebx", "ecx")

#define get_current_f_V(f_ptr, V_ptr)                                                \
__asm__ __volatile__ ("movl %0, %%eax\n\t"                              \
                      "movl %1, %%ebx\n\t"                              \
                      "movl %2, %%ecx\n\t"                              \
                      "int $0x80\n\t"                                   \
        :                                                               \
	: "i"(SYSCALL_NO_sys_get_current_f_V),"mi"((unsigned int *)(f_ptr)),"mi"((unsigned int *)(V_ptr))  \
	: "eax","ebx", "ecx")

#define get_target_f_V(f_ptr, V_ptr)                                                \
__asm__ __volatile__ ("movl %0, %%eax\n\t"                              \
                      "movl %1, %%ebx\n\t"                              \
                      "movl %2, %%ecx\n\t"                              \
                      "int $0x80\n\t"                                   \
        :                                                               \
	: "i"(SYSCALL_NO_sys_get_target_f_V),"mi"((unsigned int *)(f_ptr)),"mi"((unsigned int *)(V_ptr))  \
	: "eax","ebx", "ecx")

#define write_paraport(PPORT_VAL)                                 \
__asm__ __volatile__ ("movl %0, %%eax\n\t"                             \
                      "movl %1, %%ebx\n\t"                             \
                      "int $0x80\n\t"                                  \
        :                                                              \
	: "i" (SYSCALL_NO_sys_write_paraport),"mi" ((char)(PPORT_VAL))  \
        : "eax","ebx","ecx")  


#define reset_event_counter(counter)  \
    wr_msr_40(MSR_P6_PERFCTR##counter, 0)

#define reset_both_event_counters()  \
    reset_event_counter(0);  reset_event_counter(1)

#define start_both_event_counters()     \
    wr_msr_bit(MSR_P6_EVNTSEL0, 22, 1)

#define stop_both_event_counters()      \
    wr_msr_bit(MSR_P6_EVNTSEL0, 22, 0)

#define enable_interrupt() \
    wr_msr_bit(MSR_P6_EVNTSEL0, 20, 1)

#define disable_interrupt() \
    wr_msr_bit(MSR_P6_EVNTSEL0, 20, 0) /* CANO-2005 */

#define select_count_event(counter, event)   \
    wr_msr_32(MSR_P6_EVNTSEL##counter, (event))

#define enable_kernel_PMU_log()  \
    kernel_PMU_log_on_off(1) /* CANO-2005 */

#define disable_kernel_PMU_log()  \
    kernel_PMU_log_on_off(0) /* CANO-2005 */

   
typedef struct {
  unsigned long long counter0;
  unsigned long long counter1;
  unsigned long long clock;
} counters_t;

/* column Indices for samples logs *//* CANO-2005 */
enum { CNTR0_ind = 0, CNTR1_ind =1, TSC_ind = 2, real_PHASE_ind=3, pred_PHASE_ind=4};
#define NUM_ind 5

#define MAX_SAMPLES 10000

/* GPHT PARMS */
#define PHT_entries 128
#define GPHR_depth  8

#endif
