.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 .section .data 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"