Files
30dayMakeOS/13_day/timer.c
2016-04-20 14:26:18 +08:00

133 lines
2.9 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* 定时器 */
#include "bootpack.h"
#define PIT_CTRL 0x0043
#define PIT_CNT0 0x0040
struct TIMERCTL timerctl;
#define TIMER_FLAGS_ALLOC 1 /* 已配置状态 */
#define TIMER_FLAGS_USING 2 /* 定时器运行中 */
void init_pit(void)
{
int i;
io_out8(PIT_CTRL, 0x34);
io_out8(PIT_CNT0, 0x9c);
io_out8(PIT_CNT0, 0x2e);
timerctl.count = 0;
timerctl.next = 0xffffffff; /* 因为最初没有正在运行的定时器 */
timerctl.using = 0;
for (i = 0; i < MAX_TIMER; i++) {
timerctl.timers0[i].flags = 0; /* 未使用 */
}
return;
}
struct TIMER *timer_alloc(void)
{
int i;
for (i = 0; i < MAX_TIMER; i++) {
if (timerctl.timers0[i].flags == 0) {
timerctl.timers0[i].flags = TIMER_FLAGS_ALLOC;
return &timerctl.timers0[i];
}
}
return 0; /* 没找到 */
}
void timer_free(struct TIMER *timer)
{
timer->flags = 0; /* 未使用 */
return;
}
void timer_init(struct TIMER *timer, struct FIFO32 *fifo, int data)
{
timer->fifo = fifo;
timer->data = data;
return;
}
void timer_settime(struct TIMER *timer, unsigned int timeout)
{
int e;
struct TIMER *t, *s;
timer->timeout = timeout + timerctl.count;
timer->flags = TIMER_FLAGS_USING;
e = io_load_eflags();
io_cli();
timerctl.using++;
if (timerctl.using == 1) {
/* 处于运行状态的定时器只有这一个时 */
timerctl.t0 = timer;
timer->next = 0; /* 没有下一个 */
timerctl.next = timer->timeout;
io_store_eflags(e);
return;
}
t = timerctl.t0;
if (timer->timeout <= t->timeout) {
/* 插入最前面的情况下 */
timerctl.t0 = timer;
timer->next = t; /* 下面是t */
timerctl.next = timer->timeout;
io_store_eflags(e);
return;
}
/* 搜寻插入位置 */
for (;;) {
s = t;
t = t->next;
if (t == 0) {
break; /* 最后面*/
}
if (timer->timeout <= t->timeout) {
/* 插入到s和t之间时 */
s->next = timer; /* s的下一个是timer */
timer->next = t; /* timer的下一个是t */
io_store_eflags(e);
return;
}
}
/* 插入最后面的情况下 */
s->next = timer;
timer->next = 0;
io_store_eflags(e);
return;
}
void inthandler20(int *esp)
{
int i;
struct TIMER *timer;
io_out8(PIC0_OCW2, 0x60); /* 把IRQ-00信号接收完了的信息通知给PIC */
timerctl.count++;
if (timerctl.next > timerctl.count) {
return; /* 还不到下一个时刻,所以结束*/
}
timer = timerctl.t0; /* 首先把最前面的地址赋给timer */
for (i = 0; i < timerctl.using; i++) {
/* 因为timers的定时器都处于运行状态所以不确认flags */
if (timer->timeout > timerctl.count) {
break;
}
/* 超时*/
timer->flags = TIMER_FLAGS_ALLOC;
fifo32_put(timer->fifo, timer->data);
timer = timer->next; /* 下一定时器的地址赋给timer */
}
/* 正好有i个定时器超时了。其余的进行移位。 */
timerctl.using -= i;
/* 新移位 */
timerctl.t0 = timer;
/* timerctl.next的设定 */
if (timerctl.using > 0) {
timerctl.next = timerctl.t0->timeout;
} else {
timerctl.next = 0xffffffff;
}
return;
}