00001 /*! \file kernel/clock.c 00002 * \brief The system clock manager. 00003 * \author Andrea Righi <drizzt@inwind.it> 00004 * \date Last update: 2003-08-23 00005 * \note Copyright (©) 2003 Andrea Righi 00006 */ 00007 00008 #include <const.h> 00009 00010 #include <arch/i386.h> 00011 00012 #include <kernel/floppy.h> 00013 #include <kernel/task.h> 00014 00015 #include <kernel/clock.h> 00016 00017 //! System ticks. 00018 volatile dword ticks = 0; 00019 00020 //! \brief Initialize channel 0 of the 8253A timer 00021 void init_clock() 00022 { 00023 dword IF = GET_IF(); 00024 00025 disable(); 00026 00027 outportb(TIMER_MODE, SQUARE_WAVE); // set timer on 00028 outportb(TIMER0, TIMER_COUNT & 0xFF); // timer low byte 00029 outportb(TIMER0, TIMER_COUNT >> 8); // timer high byte 00030 00031 SET_IF(IF); 00032 } 00033 00034 //! \brief Reset the clock for rebooting 00035 void stop_clock() 00036 { 00037 dword IF = GET_IF(); 00038 00039 00040 disable(); 00041 00042 outportb(TIMER_MODE, SQUARE_WAVE); // set timer on 00043 outportb(TIMER0, 0); // timer low byte 00044 outportb(TIMER0, 0); // timer high byte 00045 00046 SET_IF(IF); 00047 } 00048 00049 //! \brief Delay some milliseconds 00050 //! \param millisec How many milliseconds you want to delay. 00051 void delay(dword millisec) 00052 { 00053 dword count, elapsed; 00054 dword IF = GET_IF(); 00055 00056 // Start timer // 00057 elapsed = 0; 00058 00059 while (elapsed < millisec) 00060 { 00061 // Poll ticks in memory // 00062 count = ticks; 00063 00064 // Auto-sleep // 00065 enable(); 00066 idle(); 00067 00068 // Update elapsed time // 00069 elapsed += (ticks - count)*1000/HZ; 00070 } 00071 00072 SET_IF(IF); 00073 } 00074 00075 //! \brief Initialize a timeout variable. 00076 //! \param t The timeout variable. 00077 //! \param millisec 00078 //! How many milliseconds have to elapse before the timeout occurs. 00079 void set_timeout(timeout_t *t, unsigned int millisec) 00080 { 00081 t->start_ticks = ticks; 00082 t->ticks_to_wait = millisec * HZ / 1000; 00083 } 00084 00085 //! \brief Check if a timeout has been elapsed. 00086 //! \param t The timeout variable. 00087 bool is_timeout(timeout_t *t) 00088 { 00089 // Check if a timeout has gone // 00090 uint32_t elapsed; 00091 elapsed = ticks - t->start_ticks; 00092 return( elapsed >= t->ticks_to_wait ); 00093 } 00094 00095 //! \brief Return the system ticks. 00096 //! \return The system ticks. 00097 dword sys_get_ticks() 00098 { 00099 return(ticks); 00100 } 00101 00102 //! \brief This is a task that occurs at every clock tick. 00103 /*! 00104 * Into this routine you can put every periodical task.\n 00105 * You can change the frequency of the ticks changing the value 00106 * of the #HZ definition.\n 00107 * This thread is invoked at every clock tick by the dispatcher(). 00108 */ 00109 void clock_thread() 00110 { 00111 ticks++; 00112 floppy_thread(); 00113 }