File: pit.S

package info (click to toggle)
faumachine 20180503-4
  • links: PTS
  • area: main
  • in suites: buster
  • size: 61,272 kB
  • sloc: ansic: 272,290; makefile: 6,199; asm: 4,251; sh: 3,022; perl: 886; xml: 563; pascal: 311; lex: 214; vhdl: 204
file content (114 lines) | stat: -rw-r--r-- 2,149 bytes parent folder | download
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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
/*
 * Copyright (C) 2009 FAUmachine Team <info@faumachine.org>.
 * This program is free software. You can redistribute it and/or modify it
 * under the terms of the GNU General Public License, either version 2 of
 * the License, or (at your option) any later version. See COPYING.
 */

/*
 * Program the PIT (connected to irq 0) as well as provide utility 
 * sleep functions.
 */

.text

/* keyboard controller is irq0
 * io: 0x0040,41,42
 */

.globl setup_pit
setup_pit:
	/* only counter 0 */
	/* control word counter 0 (2 b)
	 * write both high/low byte, (2 b)
	 * select mode 2, (3b)
	 * don't use bcd (1b)
	 */
	movb $0b00110100, %al
	outb %al, $0x43

	/* get interrupts every 0.01 s:
	 * PIT frequency: 1.193182 MHz
	 * counter = 1.193182 * 10^6 * 0.01 s / s
	 *         = 1.193182 * 10^4 * 1
	 *         = 11931.82 
	 *         -> 11932
	 */
	movl $11932, %eax
	/* fist LSB */
	outb %al, $0x40
	/* then MSB */
	movb %ah, %al
	outb %al, $0x40

	/* all right, interrupts shall come */
	ret


.globl handle_pit_irq
handle_pit_irq:
	incl pit_counter_100th_sec
	cmpb $0, pit_callback
	jne _check_timer
	ret
_check_timer:
	pushl %eax
	movl pit_counter_100th_sec_wake, %eax
	cmpl pit_counter_100th_sec, %eax
	jbe _wake_timer
	popl %eax
	ret
_wake_timer:
	popl %eax
	pusha
	call *pit_callback
	popa
	movl $0, pit_callback
	ret

/* Call a callback (pointer in %edx) after %eax seconds
 * have passed.
 * Only one callback is supported, calling time_call_after 
 * again will overwrite the set counter.
 */
.globl time_call_after
time_call_after:
	movl %edx, pit_callback
	pushl %edx
	movl $100, %edx
	mull %edx
	addl pit_counter_100th_sec, %eax
	movl %eax, pit_counter_100th_sec_wake
	popl %edx
	ret

/* delay for %eax 1/100 seconds. */
.globl delay
delay:
	addl pit_counter_100th_sec, %eax
_delay_loop:
	hlt
	cmpl pit_counter_100th_sec, %eax
	ja _delay_loop
	ret

.globl rand6
rand6:
	movl pit_counter_100th_sec, %eax
	andl $0x7, %eax
	cmpb $6, %eax
	jb _rand6_out
	/* that's why the bank always wins :) */
	shrl $1, %eax
_rand6_out:
	incl %eax
	ret


.data
pit_counter_100th_sec:
	.long 0
pit_callback:
	.long 0
pit_counter_100th_sec_wake:
	.long 0