Subversion Repositories shark

Rev

Rev 333 | Blame | Compare with Previous | Last modification | View Log | RSS feed

/* Project:     OSLib
 * Description: The OS Construction Kit
 * Date:                1.6.2000
 * Idea by:             Luca Abeni & Gerardo Lamastra
 *
 * OSLib is an SO project aimed at developing a common, easy-to-use
 * low-level infrastructure for developing OS kernels and Embedded
 * Applications; it partially derives from the HARTIK project but it
 * currently is independently developed.
 *
 * OSLib is distributed under GPL License, and some of its code has
 * been derived from the Linux kernel source; also some important
 * ideas come from studying the DJGPP go32 extender.
 *
 * We acknowledge the Linux Community, Free Software Foundation,
 * D.J. Delorie and all the other developers who believe in the
 * freedom of software and ideas.
 *
 * For legalese, check out the included GPL license.
 */


/*      Advanced Timer
 *      Date: 8.4.2003
 *      Author: Giacomo Guidi <giacomo@gandalf.sssup.it>
 *
 */


#ifndef __ADVTIMER_H__
#define __ADVTIMER_H__

#include <ll/i386/defs.h>
BEGIN_DEF

#include <ll/sys/ll/time.h>

/* TSC */

#define rdtsc(low,high) \
     __asm__ __volatile__("xorl %%eax,%%eax\n\t" \
                          "cpuid\n\t"            \
                          "rdtsc\n\t"            \
                          : "=a" (low), "=d" (high) \
                          :: "ebx", "ecx")


#define rdtscll(val) \
     __asm__ __volatile__("xorl %%eax,%%eax\n\t" \
                          "cpuid\n\t"            \
                          "rdtsc\n\t"            \
                          : "=A" (val)           \
                          :: "ebx","ecx")


#ifdef __O1000__
  #define ll_read_timespec ll_read_timespec_1000
#else
  #ifdef __02000__
    #define ll_read_timespec ll_read_timespec_2000
  #else
    #ifdef __O4000__
      #define ll_read_timespec ll_read_timespec_4000
    #else
      #define ll_read_timespec ll_read_timespec_8000
    #endif
  #endif
#endif

//Low level time read function: Optimized for CPU < 1 GHz
extern __inline__ void ll_read_timespec_1000(struct timespec *tspec)
{
    extern unsigned int clk_opt_1,clk_opt_2;
    extern unsigned long long *ptr_init_tsc;
                 
   if (clk_opt_1 == 0) {
            NULL_TIMESPEC(tspec);
            return;
    }
                                                                                                           
    __asm__("rdtsc\n\t"
            "subl (%%edi),%%eax\n\t"
            "sbbl 4(%%edi),%%edx\n\t"
            "divl %%ebx\n\t"
            "movl %%eax,%%ebx\n\t"
            "xorl %%eax,%%eax\n\t"
            "divl %%ecx\n\t"
            : "=a" (tspec->tv_nsec), "=b" (tspec->tv_sec)
            : "D" (ptr_init_tsc) , "b" (clk_opt_1), "c" (clk_opt_2)
            : "edx" );            

}

//Low level time read function: Optimized for CPU < 2 GHz
extern __inline__ void ll_read_timespec_2000(struct timespec *tspec)
{
    extern unsigned int clk_opt_1,clk_opt_3;
    extern unsigned long long *ptr_init_tsc;
               
    if (clk_opt_1 == 0) {
            NULL_TIMESPEC(tspec);
            return;
    }
                                                                                                             
    __asm__("rdtsc\n\t"
            "subl (%%edi),%%eax\n\t"
            "sbbl 4(%%edi),%%edx\n\t"
            "divl %%ebx\n\t"
            "movl %%eax,%%ebx\n\t"
            "xorl %%eax,%%eax\n\t"
            "shrdl $1,%%edx,%%eax\n\t"
            "shrl %%edx\n\t"
            "divl %%ecx\n\t"
            : "=a" (tspec->tv_nsec), "=b" (tspec->tv_sec)
            : "D" (ptr_init_tsc) , "b" (clk_opt_1), "c" (clk_opt_3)
            : "edx" );
                                                                                                                             
}

//Low level time read function: Optimized for CPU < 4 GHz
extern __inline__ void ll_read_timespec_4000(struct timespec *tspec)
{
    extern unsigned int clk_opt_1,clk_opt_4;
    extern unsigned long long *ptr_init_tsc;
           
    if (clk_opt_1 == 0) {
            NULL_TIMESPEC(tspec);
            return;
    }
                                                                                                                 
    __asm__("rdtsc\n\t"
            "subl (%%edi),%%eax\n\t"
            "sbbl 4(%%edi),%%edx\n\t"
            "divl %%ebx\n\t"
            "movl %%eax,%%ebx\n\t"
            "xorl %%eax,%%eax\n\t"
            "shrdl $2,%%edx,%%eax\n\t"
            "shrl $2,%%edx\n\t"
            "divl %%ecx\n\t"
            : "=a" (tspec->tv_nsec), "=b" (tspec->tv_sec)
            : "D" (ptr_init_tsc) , "b" (clk_opt_1), "c" (clk_opt_4)
            : "edx" );
                                                                                                                             
}

//Low level time read function
extern __inline__ void ll_read_timespec_8000(struct timespec *tspec)
{
    extern unsigned int clk_opt_0,clk_opt_5;
    extern unsigned long long *ptr_init_tsc;

    if (clk_opt_0 == 0) {
            NULL_TIMESPEC(tspec);
            return;
    }

    __asm__("rdtsc\n\t"
            "subl (%%edi),%%eax\n\t"
            "sbbl 4(%%edi),%%edx\n\t"
            "shrdl $1,%%edx,%%eax\n\t"
            "shrl %%edx\n\t"
            "divl %%ebx\n\t"
            "movl %%eax,%%ebx\n\t"
            "xorl %%eax,%%eax\n\t"
            "shrdl $2,%%edx,%%eax\n\t"
            "shrl $2,%%edx\n\t"
            "divl %%ecx\n\t"
            : "=b" (tspec->tv_sec), "=a" (tspec->tv_nsec)
            : "D" (ptr_init_tsc), "b" (clk_opt_0), "c" (clk_opt_5)
            : "edx");
             
}

#define rdmsr(msr,val1,val2) \
     __asm__ __volatile__("rdmsr" \
                          : "=a" (val1), "=d" (val2) \
                          : "c" (msr))

                                                                                                                             
#define wrmsr(msr,val1,val2) \
     __asm__ __volatile__("wrmsr" \
                          : /* no outputs */ \
                          : "c" (msr), "a" (val1), "d" (val2))


/* RTC */

#define RTC_PORT(x)     (0x70 + (x))

#define CMOS_READ(addr,val)     \
{                               \
outp(RTC_PORT(0),(addr));       \
val = inp(RTC_PORT(1));         \
}


#define CMOS_WRITE(addr,val)    \
{                               \
outp(RTC_PORT(0),(addr));       \
outp(RTC_PORT(1),(val));        \
}


#define RTC_IRQ 8

void ll_init_advtimer(void);
void ll_restore_adv(void);

END_DEF
#endif