summaryrefslogtreecommitdiff
path: root/src/boot/stage2_a20.asm
diff options
context:
space:
mode:
Diffstat (limited to 'src/boot/stage2_a20.asm')
-rw-r--r--src/boot/stage2_a20.asm157
1 files changed, 157 insertions, 0 deletions
diff --git a/src/boot/stage2_a20.asm b/src/boot/stage2_a20.asm
new file mode 100644
index 0000000..c0951ad
--- /dev/null
+++ b/src/boot/stage2_a20.asm
@@ -0,0 +1,157 @@
+; 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