]> git.dujemihanovic.xyz Git - nameless-os.git/blobdiff - boot/x86/a20.s
Enable A20 gate
[nameless-os.git] / boot / x86 / a20.s
index f6a292ba6bd23bbf2e24564b1351d530836930ae..b1c86cee6fb9521693c5e91ce146f78e585f3748 100644 (file)
@@ -1,42 +1,45 @@
 ; Some routines for managing the A20 line
 
 ; Check if A20 is enabled
-; Based on <https://wiki.osdev.org/A20_Line#Testing_the_A20_line>, slightly modified
-check_a20
-       pushf ; save EFLAGS
-       ; save segment and index registers
-       push ds 
+; Based on <https://wiki.osdev.org/A20_Line#Testing_the_A20_line>
+check_a20:
+       pushf
+       push ds
        push es
        push di
        push si
 
-       cli ; disable interrupts
-       xor ax, ax ; ax = 0
-       mov es, ax ; es = 0
+       cli
+
+       xor ax, ax
+       mov es, ax
 
-       not ax ; ax = FFFFh
-       mov ds, ax ; ds = FFFFh
+       not ax
+       mov ds, ax
 
        mov di, 500h
        mov si, 510h
 
-       mov al, [es:di] ; preserve contents of 0:500h
-       mov ah, [ds:si] ; preserve contents of FFFFh:510h
-       push ax ; push all that to stack
+       mov al, byte [es:di]
+       push ax
+
+       mov al, byte [ds:si]
+       push ax
 
-       mov byte [es:di], 0 ; set 0:500h to 0
-       mov byte [ds:si], 0FFh ; set FFFFh:510h to FFh
+       mov byte [es:di], 0
+       mov byte [ds:si], 0FFh
 
-       cmp byte [es:di], 0FFh ; compare 0:500h with FFh
-                                         ; if A20 is enabled, this will not be equal, but if A20 is disabled it will be
+       cmp byte [es:di], 0FFh
 
-       pop ax ; pop old contents of the 2 addresses
-       mov [ds:si], ah ; restore contents of FFFFh:510h
-       mov [es:di], al ; restore contents of 0:500h
+       pop ax
+       mov byte [ds:si], al
+       
+       pop ax
+       mov byte [es:di], al
 
-       xor ax, ax ; clear ax
-       je .exit ; if A20 is disabled, return 0
-       mov ax, 1 ; otherwise return 1
+       mov ax, 0
+       je .exit
+       mov ax, 1
 
 .exit
        pop si
@@ -44,6 +47,67 @@ check_a20
        pop es
        pop ds
        popf
-       sti
        ret
 
+a20_i8042_wait
+       in al, 64h
+       test al, 2
+       jnz a20_i8042_wait
+       ret
+
+a20_i8042_wait2
+       in al, 64h
+       test al, 1
+       jnz a20_i8042_wait2
+       ret
+
+enable_a20
+       mov ax, 2401h
+       int 15h
+       call check_a20
+       cmp ax, 1
+       jne .fail
+.success
+       ret
+.fail
+       cli ; disable interrupts
+
+       call a20_i8042_wait
+       mov al, 0ADh ; disable 1st PS/2 port
+       out 64h, al
+
+       call a20_i8042_wait
+       mov al, 0D0h ; read controller output port
+       out 64h, al
+
+       call a20_i8042_wait2
+       in al, 60h ; do the actual read
+       push ax ; save the register
+
+       call a20_i8042_wait
+       mov al, 0D1h ; write byte to output port
+       out 64h, al
+
+       call a20_i8042_wait
+       pop ax ; restore the register
+       or al, 2 ; toggle A20 bit
+       out 60h, al
+
+       call a20_i8042_wait
+       mov al, 0AEh ; reenable 1st PS/2 port
+       out 64h, al
+
+       call a20_i8042_wait
+       sti ; enable interrupts
+       ret
+
+       call check_a20
+       cmp ax, 1
+       jne .fail2
+       ret
+.fail2
+       mov si, A20_FAIL
+       call print
+       jmp $
+
+A20_FAIL db "A20 enable fail, not booting!", 0