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
|