; functions to handle A20 address line status and switching ; returns 0 if not A20_ENABLED, 1 if A20_ENABLED in AX check_A20_enabled: pushf push ds push es push di push si cli xor ax, ax mov es, ax mov di, 0x0500 ; es:di = 0000:0500 mov ax, 0xffff mov ds, ax mov si, 0x0510 ; ds:si = ffff:0510 mov al, byte [es:di] ; preserve values in memory push ax ; on stack mov al, byte [ds:si] push ax mov byte [es:di], 0x00 ; now the test: write 0x00 to 0000:0500 mov byte [ds:si], 0xFF ; write 0xff to ffff:0510 cmp byte [es:di], 0xFF ; memory wrap? A20 notA20_ENABLED pop ax ; restore original memory contents mov byte [ds:si], al pop ax mov byte [es:di], al je .enabled jmp .disabled .enabled: mov al, '+' call print_char mov ax, 1 ; not wrapped around jmp .exit .disabled: mov al, '-' call print_char mov ax, 0 ; wrapped around (last cmp) jmp .exit .exit: pop si pop di pop es pop ds popf ret check_and_enable_A20: call check_A20_enabled cmp ax, 1 je A20_ENABLED A20_ENABLE_KBD_PORT: mov al, 'K' call print_char mov al, 0xdd out 0x64, al call check_A20_enabled cmp ax, 1 je A20_ENABLED A20_ENABLE_KBD_OUT: mov al, 'k' call print_char cli ; disable interrupts, we talk directly to the keyboard ports call .wait_input mov al,0xAD out 0x64,al ; disable keyboard call .wait_input mov al,0xD0 out 0x64,al ; tell controller to read output port call .wait_output in al,0x60 push eax ; get output port data and store it call .wait_input mov al,0xD1 out 0x64,al ; tell controller to write output port call .wait_input pop eax or al,2 ; set bit 1 (enable a20) out 0x60,al ; write out data back to the output port call .wait_input mov al,0xAE ; enable keyboard out 0x64,al call .wait_input sti jmp .retest ; wait for input buffer to be clear .wait_input: in al,0x64 test al,2 jnz .wait_input ret ; wait for output buffer to be clear .wait_output: in al,0x64 test al,1 jz .wait_output ret .retest: call check_A20_enabled cmp ax, 1 je A20_ENABLED A20_FAST_SPECIAL_PORT: mov al, 'F' call print_char in al, 0x92 or al, 2 out 0x92, al call check_A20_enabled cmp ax, 1 je A20_ENABLED ret A20_ENABLE_VIA_BIOS: mov al, 'B' call print_char mov ax, 0x2401 int 0x15 call check_A20_enabled cmp ax, 1 je A20_ENABLED A20_ENABLED: ret