2024-01-11 22:03:52 +02:00
|
|
|
.code16
|
|
|
|
.section .stage2
|
|
|
|
|
|
|
|
# checks whether A20 line is enabled or disabled
|
|
|
|
# return
|
|
|
|
# ax: 1 if enabled, 0 otherwise
|
|
|
|
check_a20:
|
|
|
|
pushf
|
|
|
|
pushw %si
|
|
|
|
pushw %di
|
|
|
|
pushw %ds
|
|
|
|
pushw %es
|
|
|
|
|
|
|
|
cli
|
|
|
|
|
|
|
|
xorw %ax, %ax
|
|
|
|
movw %ax, %es
|
|
|
|
notw %ax
|
|
|
|
movw %ax, %ds
|
|
|
|
|
|
|
|
movw $0x0500, %di
|
|
|
|
movw $0x0510, %si
|
|
|
|
|
|
|
|
movb %es:(%di), %al
|
|
|
|
pushw %ax
|
|
|
|
|
|
|
|
movb %ds:(%si), %al
|
|
|
|
pushw %ax
|
|
|
|
|
|
|
|
movb $0x00, %es:(%di)
|
|
|
|
movb $0xFF, %ds:(%si)
|
|
|
|
|
|
|
|
cmpb $0xFF, %es:(%di)
|
|
|
|
|
|
|
|
pop %ax
|
|
|
|
movb %al, %ds:(%si)
|
|
|
|
|
|
|
|
pop %ax
|
|
|
|
movb %al, %es:(%di)
|
|
|
|
|
|
|
|
movw $0, %ax
|
|
|
|
je .check_a20_done
|
|
|
|
|
|
|
|
movw $1, %ax
|
|
|
|
|
|
|
|
.check_a20_done:
|
|
|
|
popw %es
|
|
|
|
popw %ds
|
|
|
|
popw %di
|
|
|
|
popw %si
|
|
|
|
popf
|
|
|
|
ret
|
|
|
|
|
|
|
|
|
|
|
|
# Try to enable A20 using PS2 controller
|
|
|
|
enable_a20_ps2:
|
|
|
|
pushf
|
|
|
|
pushw %ax
|
|
|
|
|
|
|
|
cli
|
|
|
|
|
|
|
|
# disable first port
|
|
|
|
call .enable_a20_ps2_wait1
|
|
|
|
movb $0xAD, %al
|
|
|
|
outb %al, $0x64
|
|
|
|
|
|
|
|
# read controller output
|
|
|
|
call .enable_a20_ps2_wait1
|
|
|
|
movb $0xD0, %al
|
|
|
|
outb %al, $0x64
|
|
|
|
|
|
|
|
call .enable_a20_ps2_wait2
|
|
|
|
inb $0x60, %al
|
|
|
|
pushw %ax
|
|
|
|
|
|
|
|
# write controller output
|
|
|
|
call .enable_a20_ps2_wait1
|
|
|
|
movb $0xD1, %al
|
|
|
|
outb %al, $0x64
|
|
|
|
|
|
|
|
call .enable_a20_ps2_wait1
|
|
|
|
popw %ax
|
|
|
|
orw $2, %ax
|
|
|
|
outb %al, $0x60
|
|
|
|
|
|
|
|
# enable first port
|
|
|
|
call .enable_a20_ps2_wait1
|
|
|
|
movb $0xAE, %al
|
|
|
|
outb %al, $0x64
|
|
|
|
|
|
|
|
call .enable_a20_ps2_wait1
|
|
|
|
|
|
|
|
popw %ax
|
|
|
|
popf
|
|
|
|
ret
|
|
|
|
|
|
|
|
.enable_a20_ps2_wait1:
|
|
|
|
inb $0x64, %al
|
|
|
|
test $2, %al
|
|
|
|
jnz .enable_a20_ps2_wait1
|
|
|
|
ret
|
|
|
|
|
|
|
|
.enable_a20_ps2_wait2:
|
|
|
|
inb $0x64, %al
|
|
|
|
test $1, %al
|
|
|
|
jnz .enable_a20_ps2_wait1
|
|
|
|
ret
|
|
|
|
|
|
|
|
|
|
|
|
# Check if A20 line is disabled. If it is, try to enable it
|
|
|
|
.global enable_a20
|
|
|
|
enable_a20:
|
|
|
|
pushw %ax
|
|
|
|
pushw %si
|
|
|
|
|
|
|
|
call check_a20
|
|
|
|
testw %ax, %ax
|
|
|
|
jnz .enable_a20_done
|
|
|
|
|
|
|
|
movw $a20_line_disabled_msg, %si
|
|
|
|
call puts; call print_newline
|
|
|
|
|
|
|
|
# Try to enable A20 line using bios interrupt
|
|
|
|
movw $0x2401, %ax
|
|
|
|
int $0x15
|
|
|
|
call check_a20
|
|
|
|
testw %ax, %ax
|
|
|
|
jnz .enable_a20_done
|
|
|
|
|
|
|
|
# Try to enable A20 line using ps2 controller
|
|
|
|
call enable_a20_ps2
|
|
|
|
call check_a20
|
|
|
|
testw %ax, %ax
|
|
|
|
jnz .enable_a20_done
|
|
|
|
|
|
|
|
# Try to enable A20 line using fast A20 gate
|
|
|
|
inb $0x92, %al
|
|
|
|
testb $2, %al
|
|
|
|
jnz .enable_a20_fast_done
|
|
|
|
orb $2, %al
|
|
|
|
outb %al, $0x92
|
|
|
|
.enable_a20_fast_done:
|
|
|
|
|
|
|
|
call check_a20
|
|
|
|
testw %ax, %ax
|
|
|
|
jnz .enable_a20_done
|
|
|
|
|
|
|
|
movw $a20_could_not_enable_msg, %si
|
|
|
|
call print_and_halt
|
|
|
|
|
|
|
|
.enable_a20_done:
|
|
|
|
movw $a20_line_enabled_msg, %si
|
|
|
|
call puts; call print_newline
|
|
|
|
|
|
|
|
popw %si
|
|
|
|
popw %ax
|
|
|
|
ret
|
|
|
|
|
2024-01-12 19:25:07 +02:00
|
|
|
.section .data
|
|
|
|
|
2024-01-11 22:03:52 +02:00
|
|
|
a20_line_disabled_msg:
|
|
|
|
.asciz "A20 line disabled. Trying to enable it"
|
|
|
|
|
|
|
|
a20_line_enabled_msg:
|
|
|
|
.asciz "A20 line enabled"
|
|
|
|
|
|
|
|
a20_could_not_enable_msg:
|
|
|
|
.asciz "Could not enable A20 line"
|