This commit is contained in:
2025-05-28 14:41:02 -05:00
commit 6d366537dd
73 changed files with 4448 additions and 0 deletions

132
pit.asm Normal file
View File

@ -0,0 +1,132 @@
; NOTE: the code in this section is mostly copied from the OSDev wiki. (wiki.osdev.org) {though osdev.org/osdev.com works just fine.}
section .bss
system_timer_fractions: resd 1 ; Fractions of 1 ms since timer initialized
system_timer_ms: resd 1 ; Number of whole ms since timer initialized
IRQ0_fractions: resd 1 ; Fractions of 1 ms between IRQs
IRQ0_ms: resd 1 ; Number of whole ms between IRQs
IRQ0_frequency: resd 1 ; Actual frequency of PIT
PIT_reload_value: resw 1 ; Current PIT reload value
section .text
global IRQ0_handler
global init_PIT
IRQ0_handler:
push eax
push ebx
mov eax, [IRQ0_fractions]
mov ebx, [IRQ0_ms] ; eax.ebx = amount of time between IRQs
add [system_timer_fractions], eax ; Update system timer tick fractions
adc [system_timer_ms], ebx ; Update system timer tick milli-seconds
mov al, 0x20
out 0x20, al ; Send the EOI to the PIC
pop ebx
pop eax
iretd
;Input
; ebx Desired PIT frequency in Hz
init_PIT:
pushad
; Do some checking
mov eax,0x10000 ;eax = reload value for slowest possible frequency (65536)
cmp ebx,18 ;Is the requested frequency too low?
jbe .gotReloadValue ; yes, use slowest possible frequency
mov eax,1 ;ax = reload value for fastest possible frequency (1)
cmp ebx,1193181 ;Is the requested frequency too high?
jae .gotReloadValue ; yes, use fastest possible frequency
; Calculate the reload value
mov eax,3579545
mov edx,0 ;edx:eax = 3579545
div ebx ;eax = 3579545 / frequency, edx = remainder
cmp edx,3579545 / 2 ;Is the remainder more than half?
jb .l1 ; no, round down
inc eax ; yes, round up
.l1:
mov ebx,3
mov edx,0 ;edx:eax = 3579545 * 256 / frequency
div ebx ;eax = (3579545 * 256 / 3 * 256) / frequency
cmp edx,3 / 2 ;Is the remainder more than half?
jb .l2 ; no, round down
inc eax ; yes, round up
.l2:
; Store the reload value and calculate the actual frequency
.gotReloadValue:
push eax ;Store reload_value for later
mov [PIT_reload_value],ax ;Store the reload value for later
mov ebx,eax ;ebx = reload value
mov eax,3579545
mov edx,0 ;edx:eax = 3579545
div ebx ;eax = 3579545 / reload_value, edx = remainder
cmp edx,3579545 / 2 ;Is the remainder more than half?
jb .l3 ; no, round down
inc eax ; yes, round up
.l3:
mov ebx,3
mov edx,0 ;edx:eax = 3579545 / reload_value
div ebx ;eax = (3579545 / 3) / frequency
cmp edx,3 / 2 ;Is the remainder more than half?
jb .l4 ; no, round down
inc eax ; yes, round up
.l4:
mov [IRQ0_frequency],eax ;Store the actual frequency for displaying later
; Calculate the amount of time between IRQs in 32.32 fixed point
;
; Note: The basic formula is:
; time in ms = reload_value / (3579545 / 3) * 1000
; This can be rearranged in the following way:
; time in ms = reload_value * 3000 / 3579545
; time in ms = reload_value * 3000 / 3579545 * (2^42)/(2^42)
; time in ms = reload_value * 3000 * (2^42) / 3579545 / (2^42)
; time in ms * 2^32 = reload_value * 3000 * (2^42) / 3579545 / (2^42) * (2^32)
; time in ms * 2^32 = reload_value * 3000 * (2^42) / 3579545 / (2^10)
pop ebx ;ebx = reload_value
mov eax,0xDBB3A062 ;eax = 3000 * (2^42) / 3579545
mul ebx ;edx:eax = reload_value * 3000 * (2^42) / 3579545
shrd eax,edx,10
shr edx,10 ;edx:eax = reload_value * 3000 * (2^42) / 3579545 / (2^10)
mov [IRQ0_ms],edx ;Set whole ms between IRQs
mov [IRQ0_fractions],eax ;Set fractions of 1 ms between IRQs
; Program the PIT channel
pushfd
cli ;Disabled interrupts (just in case)
mov al,00110100b ;channel 0, lobyte/hibyte, rate generator
out 0x43, al
mov ax,[PIT_reload_value] ;ax = 16 bit reload value
out 0x40,al ;Set low byte of PIT reload value
mov al,ah ;ax = high 8 bits of reload value
out 0x40,al ;Set high byte of PIT reload value
popfd
popad
ret