00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include <agnix/agnix.h>
00015 #include <agnix/irq.h>
00016 #include <agnix/tasks.h>
00017 #include <agnix/timer.h>
00018 #include <agnix/memory.h>
00019 #include <agnix/adi/adi.h>
00020 #include <agnix/spinlock.h>
00021 #include <agnix/timers.h>
00022 #include <agnix/counters.h>
00023 #include <agnix/console.h>
00024
00025 #define TIMER_INC_VAL (1e6 / TIMER_HZ)
00026 #define USEC_IN_SEC 1000000
00027
00028 struct timeval_s current_time;
00029 extern struct chip_s rtc_chip;
00030 extern struct chip_s i8254_chip;
00031 extern int counter_jiffies_desc;
00032
00033 spinlock_t current_time_lock;
00034
00035 void timer_usec_overflow(void)
00036 {
00037 do {
00038 current_time.tv_usec -= USEC_IN_SEC;
00039 current_time.tv_sec++;
00040 } while (current_time.tv_usec > USEC_IN_SEC);
00041 }
00042
00043 void timer_actualize(void)
00044 {
00045 current_time.tv_usec += TIMER_INC_VAL;
00046
00047 if (current_time.tv_usec > USEC_IN_SEC)
00048 timer_usec_overflow();
00049 }
00050
00051 void timer_irq(u32 i)
00052 {
00053 if (--current_task->t_count <= 0) {
00054 current_task->t_resched = 1;
00055 }
00056 else
00057 current_task->t_resched = 0;
00058
00059 timer_actualize();
00060 counter_inc(counter_jiffies_desc);
00061 run_timers();
00062 }
00063
00064 struct irq_routine_s irq_timer = { timer_irq, 0, 0, };
00065
00066 int __init timer_init(void)
00067 {
00068 spin_lock_init(¤t_time_lock);
00069
00070 rtc_ops(&rtc_chip)->gettime(&rtc_chip, ¤t_time);
00071 install_irq(0, &irq_timer);
00072
00073 return 0;
00074 }
00075
00076 int timer_gettimeofday(struct timeval_s *tv)
00077 {
00078 u16 count;
00079 u32 flags;
00080
00081 spin_lock_irqsave(¤t_time_lock, flags);
00082
00083 memcpy(tv, ¤t_time, sizeof(struct timeval_s));
00084 count = pit_ops(&i8254_chip)->read_count(&i8254_chip, 0);
00085 tv->tv_usec += (int)(count);
00086
00087 spin_unlock_irqrestore(¤t_time_lock, flags);
00088
00089 return 0;
00090 }
00091
00092 int timer_settimeofday(struct timeval_s *tv)
00093 {
00094 u16 count;
00095 u32 flags;
00096
00097 spin_lock_irqsave(¤t_time_lock, flags);
00098
00099 memcpy(¤t_time, tv, sizeof(struct timeval_s));
00100 count = (u16)(tv->tv_usec % 1000);
00101 pit_ops(&i8254_chip)->write_count(&i8254_chip, 0, count);
00102
00103 spin_unlock_irqrestore(¤t_time_lock, flags);
00104
00105 return 0;
00106 }