foxdos/src/int21.s

129 lines
1.9 KiB
ArmAsm

int21:
push ds
push cs
pop ds
; your handler goes here
; you could maybe make a jump table that takes ah as input?
pop ds
iret
retcode: dw 0
verify: db 0
get_retcode:; ah=4dh
mov ax, [retcode]
retf
get_version:; ah=30h
mov ax, 8 ; if it is not zero indexed this indicates windows ME
xor bx, bx ; update: what does that comment mean
mov cx, bx
retf
getverify:; ah=54h
mov al, [verify]
retf
setverify:; ah=2eh
mov [verify], al
retf
getint:; ah=35h
push ds
push di
push ax
xor ah, ah
shl ax, 2
mov di, ax
xor ax, ax
mov ds, ax
pop ax
mov word bx, [di]
mov word es, [di+2]
pop di
pop ds
retf
setint:; ah=25h
pusha
xor ah, ah
shl ax, 2
mov di, ax
xor ax, ax
push ds
mov ds, ax
mov word [di], dx
mov word [di+2], ds
pop ds
popa
retf
rdcmos:; input in al. TODO handle bcd here to abstractt it from the kernel
cli
cmp al, 9 ; not rtc register, do not wait. if this function bugs out
jg .rd ; on a century boundary thats not on me. stop using dos
xchg al, ah
.wait: mov al, 0xA ; msb specifies if rtc update is in progress
out 0x70, al ; TODO https://wiki.osdev.org/CMOS#RTC_Update_In_Progress
in al, 0x71
shl al, 1
jc .wait
xchg al, ah
.rd: out 0x70, al
in al, 0x71
sti
ret
wrcmos:; register in bh, value in bl
cli
push ax
mov al, bh
or al, 0x80 ; nmi always on
out 0x70, al
mov al, bl
out 0x71, al
pop ax
sti
ret
gettime:; ah=2ch
push ax
xor dl, dl
mov al, dl ; seconds
call rdcmos
mov dh, al
mov al, 2h ; minutes
call rdcmos
mov cl, al
mov al, 4h ; hours
call rdcmos
mov ch, al
shl al, 1 ; adjust for 12 hour time
jnc .end
add ch, 12
.end: pop ax
retf
settime:; ah=2dh
push bx
mov bl, ch
mov bh, 0x4
call wrcmos
mov bl, cl
shr bh, 1
call wrcmos
mov bl, dh
cmp dl, 50 ; rtc cannot hold hundredths of a second so we round
jng .f
inc bl
.f: xor bh, bh
call wrcmos
xor al, al ; it probably succeeded, its fine. TODO am i missing return codes anywhere else
pop bx
iret