diff options
Diffstat (limited to 'src/boot/stage2_a20.asm')
-rw-r--r-- | src/boot/stage2_a20.asm | 157 |
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 |