00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include "src/common/shared.hpp"
00018 #include "src/common/kmalloc.hpp"
00019 #include "src/arch/x86/gdt.hpp"
00020 #include "src/memory/memset.hpp"
00021 #include "src/memory/heap.hpp"
00022 #include "src/ipc/lock.hpp"
00023 #include "src/common/io.hpp"
00024 #include "src/common/blist.hpp"
00025 #include "src/common/blistsort.hpp"
00026 #include "src/thread/scheduler.hpp"
00027 #include "src/arch/x86/interr.hpp"
00028 #include "src/arch/x86/except_c.hpp"
00029 #include "src/arch/x86/irq.hpp"
00030 #include "src/arch/x86/rtc.hpp"
00031
00032
00033
00034
00035
00036
00037
00038 namespace Arch {
00039 namespace x86 {
00041 namespace RTC {
00042
00043
00044
00045 uint64 volatile up_time = 0;
00046 uint32 rtc_id;
00047 blist_t rtc_funcs;
00048 class IPC::Lock::lock_t rtc_lock("rtc");
00049
00050
00051 void init()
00052 {
00053 memset(&rtc_funcs, 0, sizeof(rtc_funcs));
00054 memset(&rtc_lock, 0, sizeof(rtc_lock));
00055
00056 rtc_id = Arch::x86::Interr::kernel_pic.install_irq(DEF_RTC_IRQ, &rtc_handler, GDT::code_sel_kernel);
00057
00058 ack_rtc();
00059
00060 enable_rtc();
00061 }
00062
00063
00064 void done()
00065 {
00066
00067
00068 rtc_id = 0;
00069
00070 disable_rtc();
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081 }
00082
00083
00084 void enable_rtc()
00085 {
00086
00087 IOPorts::outb(DEF_RTC_BASE, DEF_RTC_ST_B);
00088
00089 IOPorts::outb(DEF_RTC_BASE + 1, IOPorts::inb(DEF_RTC_BASE + 1) | DEF_RTC_PERIODIC);
00090 }
00091
00092
00093 void disable_rtc()
00094 {
00095
00096 IOPorts::outb(DEF_RTC_BASE, DEF_RTC_ST_B);
00097
00098 IOPorts::outb(DEF_RTC_BASE + 1, IOPorts::inb(DEF_RTC_BASE + 1) & DEF_RTC_NO_PERIODIC);
00099 }
00100
00101
00102 uint8 ack_rtc()
00103 {
00104 IOPorts::outb(DEF_RTC_BASE, DEF_RTC_ST_C);
00105 return IOPorts::inb(DEF_RTC_BASE+1);
00106 }
00107
00108
00110 rtc_handle add_proc(RTC_proc proc, uint32 ticks_def, bool one_shot, int arg1, int arg2)
00111 {
00112 blist_s *obj;
00113 rtc_list *item;
00114 uint64 boom=up_time+ticks_def;
00115
00116 item=(rtc_list*) Memory::Heap::heap0.malloc(sizeof(rtc_list), 1, "rtc item", NULL);
00117 item->proc=proc;
00118 item->boom=boom;
00119 item->one_shot=one_shot;
00120 item->arg1=arg1;
00121 item->arg2=arg2;
00122 item->ticks_def=ticks_def;
00123
00124 obj=(blist_s*) Memory::Heap::heap0.malloc(sizeof(blist_s), 1, "rtc blist_s", NULL);
00125 obj->size=sizeof(rtc_list);
00126 obj->data=item;
00127
00128 return (rtc_handle) blistsort_link(&rtc_funcs, obj, &rtccompar);
00129 }
00130
00131
00132 int rtccompar(const void *a, const void *b)
00133 {
00134 uint64 A, B;
00135 A= bli_dt(a,rtc_list*)->boom;
00136 B= bli_dt(b,rtc_list*)->boom;
00137 if (A > B)
00138 return 1;
00139 if (A < B)
00140 return -1;
00141 return 0;
00142 }
00143
00144
00145 int del_proc(blist_s *item) {
00146 rtc_lock.lock();
00150
00151
00152 if (item->prev)
00153 item->prev->next=item->next;
00154 else
00155 rtc_funcs.head=item->next;
00156
00157 if (item->next)
00158 item->next->prev=item->prev;
00159 else
00160 rtc_funcs.tail=item->prev;
00161 rtc_lock.ulock();
00162 return 1;
00163 }
00164
00165 int del_proc(rtc_handle handle)
00166 {
00167 return del_proc(reinterpret_cast<blist_s*>(handle));
00168 }
00169
00170
00171 int rtc_handler(Interr::except2_t *code)
00172 {
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182 static int halted=0;
00183
00184 IOPorts::outb(DEF_RTC_BASE, DEF_RTC_ST_C);
00185
00186
00187 if ((IOPorts::inb(DEF_RTC_BASE+1) & DEF_RTC_PERIOD_INT) == 0)
00188 return EINVAL;
00189
00190 up_time++; halted++;
00191 ::Thread::wake_threads();
00192
00193 if (rtc_lock.locked() == true)
00194 return ESUCCESS;
00195
00196
00197 blist_s *item,*nxt;
00198 rtc_list *li;
00199 int n;
00200 rtc_lock.lock();
00201 for (n=0; n<halted;n++)
00202
00203 item = rtc_funcs.head;
00204 while (item)
00205 {
00206 nxt=item->next;
00207 li=(rtc_list*)item->data;
00208 if (li->boom > (up_time - halted + n + 1))
00209 break;
00210 li->proc(li->arg1, li->arg2);
00211
00212 if (!li->one_shot) {
00213
00214 rtc_funcs.unlink(item);
00215 li->boom=li->ticks_def+(up_time - halted + n + 1);
00216 rtc_lock.ulock();
00217 blistsort_link(&rtc_funcs, item, &rtccompar);
00218 rtc_lock.lock();
00219 } else {
00220
00221 #if 1
00222
00223 del_proc(item);
00224 #else
00225 rtc_funcs.del(item);
00226 #endif
00227 }
00228 item=nxt;
00229 }
00230
00231 halted=0;
00232 rtc_lock.ulock();
00233 return ESUCCESS;
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281 }
00282
00283
00284 void tdelay(uint32 ticks)
00285 {
00286 uint32 x;
00287 uint32 fl;
00288 asm volatile ("pushf\npopl %0\nsti" : "=g" (fl) :);
00289 x = up_time + ticks;
00290 while (up_time < x) ;
00291 asm volatile ("pushl %0\npopf" : : "g" (fl));
00292 }
00293
00294
00295 };
00296 };
00297 };
00298
00299
00300
00301
00302
00303
00304