mirror of
https://github.com/stevenhowes/wbios.git
synced 2026-05-27 00:03:32 +01:00
d410ad0acb
Original source https://www.pcengines.ch/file/wbios111s.zip
399 lines
7.6 KiB
Plaintext
399 lines
7.6 KiB
Plaintext
;
|
|
; Miscellaneous interrupts
|
|
;
|
|
; (C)1997-2001 Pascal Dornier / PC Engines; All rights reserved.
|
|
; This file is licensed pursuant to the COMMON PUBLIC LICENSE 0.5.
|
|
;
|
|
; Limitations:
|
|
;
|
|
; - INT15 support is very limited.
|
|
;
|
|
; pd 050206 add Int15 E820, change to d_exmem
|
|
; pd 020215 add NO_RTC option
|
|
; pd 991127 add PS/2 mouse hook
|
|
|
|
;
|
|
; Dummy interrupts -> IRET
|
|
;
|
|
intdummy:
|
|
int00: ;divide by zero
|
|
int01: ;single step
|
|
int03: ;breakpoint
|
|
int04: ;overflow
|
|
int06: ;invalid opcode
|
|
int07: ;coprocessor not available
|
|
int1b: ;keyboard break
|
|
int1c: ;user timer tick
|
|
|
|
iret
|
|
|
|
;
|
|
; NMI
|
|
;
|
|
nmi: push ax
|
|
in al,port61 ;check type of NMI
|
|
#if ! def NO_NMI
|
|
shl al,1
|
|
jb nmi1 ;$80 set: parity error
|
|
shl al,1
|
|
jb nmi2 ;$40 set: I/O check
|
|
#else
|
|
mov al,33h ;display POST code on NMI
|
|
out post,al
|
|
#endif
|
|
mov al,0dh ;read CMOS register -> clear NMI
|
|
out cm_idx,al
|
|
out iowait,al
|
|
in al,cm_dat
|
|
pop ax
|
|
iret
|
|
|
|
#if ! def NO_NMI
|
|
|
|
; display error message
|
|
|
|
nmi1: mov si,offset msg_parit
|
|
jmp short nmi3
|
|
|
|
nmi2: mov si,offset msg_iochk
|
|
|
|
nmi3: mov ax,7 ;set video mode
|
|
int 10h
|
|
call v_msg ;display message
|
|
mov si,offset msg_halt
|
|
call v_msg ;"system halted"
|
|
cli ;hang system
|
|
hlt
|
|
#endif
|
|
;
|
|
; end of interrupt, primary controller
|
|
;
|
|
inteoi: push ax
|
|
mov al,eoi
|
|
out pic0,al
|
|
pop ax
|
|
iret
|
|
;
|
|
; end of interrupt, secondary controller
|
|
;
|
|
inteoi2: push ax
|
|
mov al,eoi
|
|
out pic1,al
|
|
out pic0,al
|
|
pop ax
|
|
iret
|
|
;
|
|
; INT 5: print screen
|
|
;
|
|
int05: push ax
|
|
push ds
|
|
xor ax,ax
|
|
mov ds,ax
|
|
mov byte [m_prtsc],0ffh ;error
|
|
pop ds
|
|
pop ax
|
|
iret
|
|
;
|
|
; INT 11 entry: equipment flag
|
|
;
|
|
int11: push ds
|
|
xor ax,ax
|
|
mov ds,ax
|
|
mov ax,[m_devflg]
|
|
pop ds
|
|
iret
|
|
;
|
|
; INT12 entry: memory size
|
|
;
|
|
int12: push ds
|
|
xor ax,ax
|
|
mov ds,ax
|
|
mov ax,[m_lomem]
|
|
pop ds
|
|
iret
|
|
;
|
|
; AH=87: block move
|
|
;
|
|
; This assumes that A20 gate is always open (preferably using
|
|
; port 92), and uses "unreal mode". Interrupts are disabled during
|
|
; block move, which can add considerably to interrupt latency.
|
|
;
|
|
; Note we don't close the A20 gate on return.
|
|
;
|
|
int1587: push ax
|
|
push bx
|
|
push si
|
|
push di
|
|
push ds
|
|
push es
|
|
call cs_a20on ;enable A20 gate
|
|
cld
|
|
and ecx,0000ffffh
|
|
mov edi,[es:si+1ah] ;24 bit destination address
|
|
and edi,00ffffffh ;mask high bits
|
|
mov esi,[es:si+12h] ;24 bit destination address
|
|
and esi,00ffffffh ;mask high bits
|
|
|
|
; enter unreal mode
|
|
|
|
cli ;disable interrupts
|
|
lgdt [cs:gdt] ;load GDT
|
|
mov eax,cr0
|
|
or al,1 ;enable protected mode
|
|
mov cr0,eax
|
|
jmp short int15872 ;flush queue
|
|
int15872: mov bx,8 ;selector
|
|
mov ds,bx
|
|
mov es,bx
|
|
and al,0feh ;exit protected mode
|
|
mov cr0,eax
|
|
|
|
shr cx,1 ;convert to 32 bit words
|
|
a4 rep movsd ;do the block move
|
|
jnb int15873
|
|
a4 movsw ;move a 16 bit "orphan"
|
|
int15873: pop es
|
|
pop ds
|
|
sti ;now interrupts are ok again
|
|
pop di
|
|
pop si
|
|
pop bx
|
|
pop ax
|
|
mov ah,0 ;ok return
|
|
clc
|
|
retf 2
|
|
;
|
|
; INT15 function 86: wait
|
|
;
|
|
int1586: pusha
|
|
mov bx,dx ;microseconds / 1024 -> BX
|
|
shr bx,10
|
|
shl cx,6
|
|
or bx,cx
|
|
call cs_waitbx ;do the delay
|
|
popa
|
|
clc ;return ok status
|
|
retf 2
|
|
;
|
|
; INT15 entry: multiplex interrupt
|
|
;
|
|
int15: sti
|
|
|
|
;& push ax ;display command code
|
|
;& mov al,ah
|
|
;& call diaghex
|
|
;& pop ax
|
|
|
|
cmp ah,87h ;block move ?
|
|
jz int1587
|
|
#if def PS2MOUSE
|
|
cmp ah,0c2h ;PS/2 mouse ?
|
|
jnz int15nc2
|
|
jmp int15c2
|
|
int15nc2:
|
|
#endif
|
|
cmp ah,88h ;memory size determine ?
|
|
jz int1588
|
|
cmp ah,0c0h ;configuration table ?
|
|
jz int15c0
|
|
cmp ah,86h ;wait ?
|
|
jz int1586
|
|
cmp ax,0e801h ;big memory size ?
|
|
jz int15e8
|
|
cmp ax,0e820h ;system memory map ?
|
|
jz inte820
|
|
|
|
#if def INT15_24
|
|
cmp ax,02400
|
|
jz int1524
|
|
cmp ax,02401
|
|
jz int1524
|
|
#endif
|
|
|
|
#if def CLE266
|
|
cmp ah,05f ;VIA VGA API ?
|
|
jnz int15ex ;:yes
|
|
jmp int15_cle
|
|
#endif
|
|
|
|
int15ex: mov ah,86h ;bad command
|
|
stc
|
|
retf 2 ;return
|
|
|
|
#if def INT15_24
|
|
|
|
; Function 24xx is supposed to control the A20 gate.
|
|
; This is added to keep GRUB from using the keyboard
|
|
; controller on legacy free systems.
|
|
|
|
int1524: mov ah,00 ;A20 gate "support" - we just lie
|
|
clc ;and say we did it... tinyBIOS always
|
|
retf 2 ;leaves A20 gate open
|
|
#endif
|
|
;
|
|
; AH=88: determine extended memory size
|
|
;
|
|
int1588:
|
|
#if def NO_RTC
|
|
mov eax,dword [cs:d_exmem] ;get extended memory size
|
|
shr eax,10 ;convert to KB
|
|
cmp eax,63*1024 ;limit to 64MB
|
|
jb >l1
|
|
mov eax,63*1024
|
|
l1:
|
|
#else
|
|
push bx
|
|
mov ah,cm_exh ;read high memory size
|
|
call rtc_read
|
|
mov bh,al
|
|
mov ah,cm_exl ;read low memory size
|
|
call rtc_read
|
|
mov ah,bh
|
|
pop bx
|
|
#endif
|
|
iret
|
|
;
|
|
; AH=C0: configuration table
|
|
;
|
|
int15c0: mov bx,offset conf_tab ;ES:BX = @configuration table
|
|
push cs
|
|
pop es
|
|
mov ah,0
|
|
clc
|
|
retf 2
|
|
;
|
|
; AH=E8: extended memory size
|
|
;
|
|
int15e8: mov eax,dword [cs:d_exmem] ;get extended memory size
|
|
mov ebx,eax
|
|
shr eax,10 ;convert -> 1KB blocks
|
|
cmp eax,15*1024
|
|
jb >l1
|
|
mov ax,15*1024 ;AX = memory 1MB to 16MB in 1KB blocks
|
|
l1: mov cx,ax ;configured = actual memory
|
|
|
|
shr ebx,16 ;convert -> 64KB blocks
|
|
sub bx,16*16 ;subtract low 16MB
|
|
jnb >l2 ;:ok
|
|
xor bx,bx ;return 0 if less than 16MB
|
|
l2: mov dx,bx ;configured = actual memory
|
|
clc
|
|
retf 2
|
|
;
|
|
; Int15 E820: get system memory map
|
|
;
|
|
inte820: push si
|
|
cmp edx,0534d4150 ;check cookie
|
|
jnz e820_err
|
|
mov si,offset e820map ;pointer to map
|
|
inc ebx ;point to next entry
|
|
mov eax,ebx ;index -> eax
|
|
e820_1: dec eax
|
|
jz e820_2 ;:got the right si
|
|
add si,20
|
|
cmp si,e820mape ;end of map ?
|
|
jb e820_1
|
|
e820_err: mov ah,086 ;error code
|
|
stc
|
|
pop si
|
|
retf 2
|
|
|
|
e820_2: mov cx,5 ;we always copy 20 bytes
|
|
cld
|
|
push di
|
|
cs: rep movsd
|
|
pop di
|
|
mov cx,20 ;say 20 bytes
|
|
mov eax,edx ;cookie to eax
|
|
cmp si,e820mape ;end of table ?
|
|
jnz e820_3 ;:no
|
|
xor bx,bx ;clear BX = end of table
|
|
e820_3: clc
|
|
pop si
|
|
retf 2 ;ok exit
|
|
;
|
|
; configuration table
|
|
;
|
|
conf_tab: dw 8 ;length
|
|
db 0fch ;model byte
|
|
db 01 ;sub model
|
|
db 00 ;BIOS level
|
|
db 70h ;cascaded interrupt 2, RTC, keyboard
|
|
;scan hook 1A
|
|
db 0,0,0,0 ;reserved
|
|
|
|
;
|
|
; INT18 entry: expansion ROM
|
|
;
|
|
#if ! def int18 ;if not defined by user code
|
|
int18: mov si,msg_noboot ;display message "No boot device..."
|
|
call v_msg
|
|
mov ah,0 ;get a keystroke
|
|
int 16h
|
|
iret
|
|
#endif
|
|
;
|
|
; INT19 entry: boot operating system
|
|
;
|
|
int19: mov byte [m_fdcnt],36 ;spin down drive A: after 2 seconds
|
|
|
|
#if def BOOT_AC
|
|
mov dl,0 ;drive A:
|
|
mov cx,1 ;retry count
|
|
call bootdrv ;try to boot
|
|
test ah,80h ;time out ?
|
|
jnz int19_1 ;yes: probably no disk
|
|
mov dl,0 ;drive A:
|
|
mov cx,2 ;retry count
|
|
call bootdrv ;try to boot
|
|
int19_1: mov dl,80h ;drive C:
|
|
mov cx,3 ;retry count
|
|
call bootdrv ;try to boot
|
|
#else
|
|
mov dl,80h ;drive C:
|
|
mov cx,3 ;retry count
|
|
call bootdrv ;try to boot
|
|
mov dl,0 ;drive A:
|
|
mov cx,3 ;retry count
|
|
call bootdrv ;try to boot
|
|
#endif
|
|
int 18h ;display message / expansion ROM
|
|
jmp int19
|
|
;
|
|
; Try to boot operating system from drive DL, CX retries
|
|
;
|
|
bootdrv: push cx
|
|
xor ax,ax ;$0000:$7c00 = destination address
|
|
mov es,ax
|
|
mov bx,7c00h
|
|
mov ax,0201h ;read, 1 sector
|
|
mov cx,0001 ;cylinder 0, sector 1
|
|
mov dh,0 ;head 0
|
|
int 13h ;try to read boot sector
|
|
pop cx
|
|
jnb bootdrv2 ;:ok
|
|
push ax
|
|
mov ah,0 ;reset disk system
|
|
int 13h
|
|
pop ax ;restore status
|
|
loop bootdrv ;try 3 times
|
|
bootdrv9: ret ;return, didn't work
|
|
|
|
; check boot sector signature
|
|
|
|
bootdrv2: cmp word [es:7dfeh],0aa55h
|
|
jnz bootdrv9 ;:no
|
|
jmp far 0:7c00h ;jump to boot sector
|
|
;
|
|
; IRQ13: coprocessor error
|
|
;
|
|
irq13: push ax
|
|
mov al,0 ;clear error
|
|
out 0f0h,al
|
|
mov al,eoi ;end of interrupt
|
|
out pic1,al
|
|
out pic0,al
|
|
pop ax
|
|
int 2 ;NMI -> further handling
|
|
iret
|