--- /dev/null
+\r
+#include "core.h"\r
+\r
+UI_TimerControl timerctrl;\r
+\r
+void Initialise_ProgrammableIntervalTimer(void)\r
+{\r
+ UI_Timer *watch;\r
+\r
+ IO_Out8(PIT_CTRL, 0x34);\r
+ IO_Out8(PIT_CNT0, 0x9c);\r
+ IO_Out8(PIT_CNT0, 0x2e);\r
+ System_GateDescriptor_Set(0x20, (uint)asm_InterruptHandler20, 0x02, AR_INTGATE32);\r
+ IO_Out8(PIC0_IMR, IO_In8(PIC0_IMR) & 0xfe);\r
+ timerctrl.count = 0;\r
+ watch = Timer_Get(0, 0);\r
+ watch->timeout = 0xFFFFFFFF;\r
+ watch->count = 0xFFFFFFFF;\r
+ watch->state = inuse;\r
+ timerctrl.next = watch;\r
+ timerctrl.ts = 0;\r
+\r
+ return;\r
+}\r
+\r
+void InterruptHandler20(int *esp)\r
+{\r
+ UI_Timer *tree, *old;\r
+ bool taskswitch;\r
+\r
+ IO_Out8(PIC0_OCW2, 0x60); /* IRQ-00\8eó\95t\8a®\97¹\82ðPIC\82É\92Ê\92m \81B0x60+\94Ô\8d\86\81B*/\r
+ timerctrl.count++;\r
+ taskswitch = false;\r
+\r
+ if(timerctrl.count == timerctrl.next->timeout){ //\8e\9e\8aÔ\82É\82È\82Á\82½\r
+ tree = timerctrl.next;\r
+ timerctrl.next = timerctrl.next->next;\r
+ for(;;){ //\93¯\88ê\83^\83C\83\80\83A\83E\83g\82ð\92T\82·\81B\r
+ if(tree->fifo != 0){ //FIFO\82Ì\91\97\90M\90æ\82ª\97L\8cø\82©\83`\83F\83b\83N\r
+ FIFO32_Put(tree->fifo, tree->data);\r
+ } else if(tree == timerctrl.ts){\r
+ taskswitch = true;\r
+ }\r
+ old = tree;\r
+ tree = old->tree;\r
+ old->tree = 0; //\93¯\88ê\83^\83C\83\80\83A\83E\83g\82È\82µ\r
+ old->state = configured; //\90Ý\92è\8dÏ\82Ý\r
+ if(old->mode == interval){ //\8cJ\82è\95Ô\82·\82È\82ç\r
+ Timer_Run(old);\r
+ }\r
+ if(tree == 0){ //\82à\82¤\93¯\88ê\83^\83C\83\80\83A\83E\83g\82Í\82È\82¢\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ if(taskswitch){\r
+ MultiTask_TaskSwitch();\r
+ }\r
+ return;\r
+}\r
+\r
+uint Timer_Get_Tick(void)\r
+{\r
+ return timerctrl.count;\r
+}\r
+\r
+UI_Timer *Timer_Get(DATA_FIFO *fifo, uint data)\r
+{\r
+ UI_Timer *timer;\r
+\r
+ timer = MemoryBlock_Allocate_System(sizeof(UI_Timer));\r
+ MemoryBlock_Write_Description(timer, "UI_Timer");\r
+\r
+ timer->next = 0;\r
+ timer->tree = 0;\r
+ timer->timeout = 0;\r
+ timer->count = 0;\r
+ timer->fifo = fifo;\r
+ timer->data = data;\r
+ timer->state = initialized;\r
+ return timer;\r
+}\r
+\r
+void Timer_Set(UI_Timer *timer, uint count, timer_mode mode)\r
+{\r
+ timer->count = count;\r
+ timer->mode = mode;\r
+ timer->state = configured;\r
+ return;\r
+}\r
+\r
+void Timer_Run(UI_Timer *timer)\r
+{\r
+ UI_Timer **target;\r
+ uint eflags;\r
+\r
+ if(timer->count == 0){\r
+ return;\r
+ }\r
+\r
+ if(timer->state == inuse){\r
+ return;\r
+ }\r
+\r
+ eflags = IO_Load_EFlags();\r
+ IO_CLI();\r
+\r
+ timer->timeout = timer->count + timerctrl.count;\r
+ target = &timerctrl.next;\r
+ for(;;){\r
+ if((*target)->timeout > timer->timeout){\r
+ timer->next = *target; //\8e©\95ª\82Ì\8e\9f\82Ì\83^\83C\83}\81[\82ð\8ew\82·\r
+ *target = timer; //\8e©\95ª\82ð\91O\82Ì\83^\83C\83}\81[\82É\98A\8c\8b\r
+ timer->tree = 0; //\8e©\95ª\82ªroot\r
+ timer->state = inuse; //\93®\8dì\92\86\r
+ break;\r
+ }\r
+ if((*target)->timeout == timer->timeout){\r
+ target = &(*target)->tree;\r
+ for(;;){\r
+ if(*target == 0){\r
+ break; //\93¯\8e\9e\8d\8f\82Ì\8dÅ\8cã\82ð\92T\82·\r
+ }\r
+ target = &(*target)->tree;\r
+ }\r
+ timer->next = 0; //\8fí\82É0\r
+ *target = timer;//\8e©\95ª\82ð\91O\82Ì\83^\83C\83}\81[\82É\98A\8c\8b\r
+ timer->tree = 0; //\8e©\95ª\82ª\8fI\92[\r
+ timer->state = inuse; //\93®\8dì\92\86\r
+ break;\r
+ }\r
+ target = &(*target)->next;\r
+ }\r
+ IO_Store_EFlags(eflags);\r
+ return;\r
+}\r
+\r
+void Timer_Cancel(UI_Timer *timer)\r
+{\r
+ UI_Timer **root, **tree;\r
+ uint eflags;\r
+\r
+ eflags = IO_Load_EFlags();\r
+ IO_CLI();\r
+\r
+ root = &timerctrl.next;\r
+\r
+ for(;;){\r
+ if((*root) == 0){ /*\83\8b\81[\83g\82Ì\8fI\92[*/\r
+ return;\r
+ }\r
+ if((*root) == timer){ /*\83\8b\81[\83g\83^\83C\83}\81[\82ð\83L\83\83\83\93\83Z\83\8b*/\r
+ if((*root)->tree == 0){ /*\83c\83\8a\81[\82È\82µ*/\r
+ *root = timer->next;\r
+ } else{ /*\83c\83\8a\81[\82 \82è*/\r
+ *root = timer->tree;\r
+ timer->tree->next = timer->next;\r
+ }\r
+ goto cancel;\r
+ } else{\r
+ tree = &(*root)->tree;\r
+ for(;;){\r
+ if((*tree) == 0){ /*\83c\83\8a\81[\82Ì\8fI\92[*/\r
+ break;\r
+ }\r
+ if((*tree) == timer){ /*\83c\83\8a\81[\83^\83C\83}\81[\82ð\83L\83\83\83\93\83Z\83\8b*/\r
+ *tree = timer->tree;\r
+ goto cancel;\r
+ }\r
+ tree = &(*tree)->tree;\r
+ }\r
+ }\r
+ root = &(*root)->next;\r
+ }\r
+\r
+cancel:\r
+ timer->next = 0;\r
+ timer->tree = 0;\r
+ timer->timeout = 0;\r
+ timer->state = configured;\r
+\r
+ IO_Store_EFlags(eflags);\r
+ return;\r
+}\r
+\r
+void Timer_TaskSwitch_Set(UI_Timer *ts)\r
+{\r
+ timerctrl.ts = ts;\r
+ return;\r
+}\r