00001 /*! \file drivers/ata/IdeTimer.c 00002 * \brief IDE driver::Timing. 00003 * \author Luca Giovacchini 00004 * \date Last update: 2003-11-07 00005 * \note Copyright (©) 2003 Luca Giovacchini 00006 * 00007 * This driver is based on Atadrv by Hale Landis 00008 * but it is completely rearranged for the minirighi32. 00009 * \n 00010 * <b>IMPORTANT!!!</b>\n 00011 * Here you can find all subs regarding waiting and timing. 00012 * Look at the specific sub comment. 00013 */ 00014 00015 #include <arch/i386.h> // for Enable() Disable() 00016 00017 #include <kernel/clock.h> // for Ticks 00018 #include <kernel/console.h> // for kprintf 00019 #include <kernel/IdeTimer.h> 00020 #include <kernel/IdeLow.h> 00021 #include <kernel/Ide.h> 00022 #include <kernel/keyboard.h> 00023 #include <kernel/task.h> // for Idle() 00024 00025 extern dword ticks; 00026 extern IdeChannel_Struct * CurrentChannel; 00027 00028 // ************************* Idle *************************** 00029 // TODO: we can move the Get_If Set_If in the caller sub 00030 // it will be more efficient 00031 // ********************************************************** 00032 void GoIdle() 00033 { 00034 dword IF = GET_IF(); 00035 // Auto-sleep // 00036 enable(); 00037 idle(); 00038 SET_IF(IF); 00039 } 00040 00041 // ************************ Delay *************************** 00042 // Start a timer 00043 // ********************************************************** 00044 void Delay(dword ms) 00045 { 00046 00047 dword Start=ticks; 00048 // we work with integer and not float, we have resolution greater than 1 ms 00049 // so we must trunc at the tick higher expected 00050 dword Stop; 00051 byte Cross; 00052 if ( (ms*HZ)%1000 == 0 ) 00053 // We can wait exactely ms 00054 Stop=Start+ms*HZ/1000; 00055 else 00056 // We must wait little more than ms because our 00057 // timer resolution can't permit to wait exactely ms 00058 Stop=(Start+ms*HZ/1000)+1; 00059 00060 Cross=(Stop<Start); 00061 // need to pay attention while waiting 00062 // for overflow of ticks and overflow of Stop 00063 while ( Cross ? (ticks >= Start) || (ticks < Stop) : (ticks>=Start) && (ticks<Stop) ) 00064 GoIdle(); 00065 00066 } 00067 00068 // ********************** TimerStart ************************ 00069 // Start a timer (filling a timer struct) 00070 // ********************************************************** 00071 Timer_Struct TimerStart(dword ms) 00072 { 00073 Timer_Struct Timer; 00074 Timer.Start=ticks; 00075 00076 if ( ms*HZ % 1000 == 0 ) 00077 // We can wait exactely ms 00078 Timer.Stop=Timer.Start+ms*HZ/1000; 00079 else 00080 // We must wait little more than ms because our 00081 // timer resolution can't permit to wait exactely ms 00082 Timer.Stop=(Timer.Start+ms*HZ/1000)+1; 00083 Timer.Cross=(Timer.Stop<Timer.Start); 00084 return Timer; 00085 } 00086 00087 // ********************* TimerElapsed *********************** 00088 // Check if timer is elapsed 00089 // ********************************************************** 00090 int TimerElapsed(Timer_Struct Timer) 00091 { 00092 // need to pay attention for overflow of ticks while waiting 00093 // and overflow of Stop 00094 return ( Timer.Cross ? (ticks < Timer.Start) && (ticks >= Timer.Stop) : (ticks<Timer.Start) || (ticks>=Timer.Stop) ); 00095 } 00096 00097 00098 // ********************** WaitForInt ************************ 00099 // Wait for interrupt 00100 // The Timer MUST be started previously or this code will 00101 // wait an undefined period of time 00102 // ********************************************************** 00103 int WaitForInt(Timer_Struct Timer) 00104 { 00105 while (TRUE) 00106 { 00107 if (CurrentChannel->IntDone == TRUE) 00108 { 00109 // reset interrupt flag; 00110 CurrentChannel->IntDone=FALSE; 00111 return FALSE; 00112 } 00113 00114 if ( TimerElapsed(Timer) ) 00115 return TRUE; 00116 00117 GoIdle(); 00118 } 00119 } 00120 00121 // ********************** WaitForBsy ************************ 00122 // Wait for BSY = 0 00123 // The Timer MUST be started previously or this code will 00124 // wait an undefined period of time 00125 // ********************************************************** 00126 int WaitForBsy(Timer_Struct Timer,word Port) 00127 { 00128 byte Status=0; 00129 00130 while (TRUE) 00131 { 00132 Status = InPortAta( Port ); // poll for not busy 00133 if ( ( Status & HDC_STAT_BSY ) == 0 ) 00134 return FALSE; 00135 00136 if ( TimerElapsed(Timer) ) // time out yet ? 00137 return TRUE; 00138 00139 GoIdle(); 00140 } 00141 } 00142 00143 // ********************** AtapiDelay ************************ 00144 // Execute a delay only for atapi device 00145 // ********************************************************** 00146 void AtapiDelay(int Dev) 00147 { 00148 if ( CurrentChannel->Device[Dev].Type == CC_DEVTYPE_ATAPI ) 00149 delay(HDC_ATAPIDELAY); 00150 } 00151 00152 // ********************** WaitKeyPress ********************** 00153 // Wait user press a key 00154 // is for shell ide command and visualization 00155 // ********************************************************** 00156 void WaitKeyPress(char * Message) 00157 { 00158 int Tmp; 00159 if (Message) 00160 kprintf("\n\r%s\n\r",Message); 00161 Tmp=kgetchar(); 00162 } 00163 00164 00165