summaryrefslogtreecommitdiff
path: root/kernel/timer.s
blob: e6da428f9930a9b385692c55a4cc4159156357d7 (plain)
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
global ticked
global ticks
global timer_init
extern check_signals
extern register_isr
extern sched_tick

ticked: dd 0
ticks: dd 0

tick_handler:
  pusha
  ; save the data segment selectors
  mov ax, ds
  push ax
  ; switch to kernel data segments
  mov ax, 0x10
  mov ds, ax
  mov es, ax
  mov fs, ax
  mov gs, ax
  ; save a pointer to the state information
  mov ebx, esp
  ; handle the timer tick
  mov dword [ticked], 1
  inc dword [ticks]
  mov al, 0x20
  out 0x20, al
  ; check that the user isn't executing in kernel space
  mov eax, [esp+38]
  test eax, 0x03
  jz .end
  ; if it isn't, call the scheduler
  call sched_tick
  ; handle any pending signals before returning to normal execution
  push ebx
  call check_signals
  add esp, 4
.end:
  ; restore the data segment selectors
  pop ax
  mov ds, ax
  mov es, ax
  mov fs, ax
  mov gs, ax
  popa
  iret

timer_init:
  push ebp
  mov ebp, esp
  ; register the tick_handler
  push tick_handler
  push dword 0
  push dword 0x20
  call register_isr
  add esp, 12
  ; initialize the PIT
  mov ax, 0x36
  out 0x43, al
  mov ax, 0x2E9C ; 10ms tick interval
  out 0x40, al
  mov al, ah
  out 0x40, al
  in al, 0x21
  and al, 0xFE
  out 0x21, al
  pop ebp
  ret