-
Notifications
You must be signed in to change notification settings - Fork 110
/
clock.c
80 lines (67 loc) · 1.59 KB
/
clock.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
/*
Copyright (C) 2015-2019 The University of Notre Dame
This software is distributed under the GNU General Public License.
See the file LICENSE for details.
*/
#include "interrupt.h"
#include "clock.h"
#include "ioports.h"
#include "process.h"
// Minimum PIT frequency is 18.2Hz.
#define CLICKS_PER_SECOND 20
#define TIMER0 0x40
#define TIMER_MODE 0x43
#define SQUARE_WAVE 0x36
#define TIMER_FREQ 1193182
#define TIMER_COUNT (((unsigned)TIMER_FREQ)/CLICKS_PER_SECOND)
static uint32_t clicks = 0;
static uint32_t seconds = 0;
static struct list queue = { 0, 0 };
static void clock_interrupt(int i, int code)
{
clicks++;
process_wakeup_all(&queue);
if(clicks >= CLICKS_PER_SECOND) {
clicks = 0;
seconds++;
process_preempt();
}
}
clock_t clock_read()
{
clock_t result;
result.seconds = seconds;
result.millis = 1000 * clicks / CLICKS_PER_SECOND;
return result;
}
clock_t clock_diff(clock_t start, clock_t stop)
{
clock_t result;
if(stop.millis < start.millis) {
stop.millis += 1000;
stop.seconds -= 1;
}
result.seconds = stop.seconds - start.seconds;
result.millis = stop.millis - start.millis;
return result;
}
void clock_wait(uint32_t millis)
{
clock_t start, elapsed;
uint32_t total;
start = clock_read();
do {
process_wait(&queue);
elapsed = clock_diff(start, clock_read());
total = elapsed.millis + elapsed.seconds * 1000;
} while(total < millis);
}
void clock_init()
{
outb(SQUARE_WAVE, TIMER_MODE);
outb((TIMER_COUNT & 0xff), TIMER0);
outb((TIMER_COUNT >> 8) & 0xff, TIMER0);
interrupt_register(32, clock_interrupt);
interrupt_enable(32);
printf("clock: ticking\n");
}