summaryrefslogtreecommitdiff
path: root/ldlinux.asm
diff options
context:
space:
mode:
Diffstat (limited to 'ldlinux.asm')
-rw-r--r--ldlinux.asm34
1 files changed, 26 insertions, 8 deletions
diff --git a/ldlinux.asm b/ldlinux.asm
index c15e9b19..9185bec2 100644
--- a/ldlinux.asm
+++ b/ldlinux.asm
@@ -341,6 +341,7 @@ InitRDCNameLen resw 1 ; Length of unmangled initrd name
NextCharJump resw 1 ; Routine to interpret next print char
SetupSecs resw 1 ; Number of setup sectors
SavedSP resw 1 ; Our SP while running a COMBOOT image
+A20test resw 1 ; Counter for testing status of A20
TextAttrBX equ $
TextAttribute resb 1 ; Text attribute for message file
TextPage resb 1 ; Active display page
@@ -2300,8 +2301,8 @@ bcopy:
;
; We typically toggle A20 twice for every 64K transferred.
;
-%define io_delay out 080h,al ; Invalid port (we hope)
-%define delaytime 1024 ; ISA bus cycles (1.5 µs)
+%define io_delay times 4 out 0EDh,al ; Invalid port (we hope)
+%define delaytime 256 ; 4 x ISA bus cycles (@ 1.5 µs)
enable_a20:
call empty_8042
@@ -2310,12 +2311,21 @@ enable_a20:
call empty_8042
mov al,0DFh ; A20 on
out 060h, al
-kbc_delay: call empty_8042
- push cx
- mov cx, delaytime
-.delayloop: io_delay
- loop .delayloop
- pop cx
+ call kbc_delay
+ ; Verify that A20 actually is enabled. Do that by
+ ; observing a word in low memory and the same word in
+ ; the HMA until they are no longer coherent. Note that
+ ; we don't do the same check in the disable case, because
+ ; we don't want to *require* A20 masking (SYSLINUX should
+ ; work fine without it, if the BIOS does.)
+ push es
+ mov ax,0FFFFh ; HMA
+ mov es,ax
+.a20_wait: inc word [ss:A20test]
+ mov ax,[es:A20test+10h]
+ cmp ax,[ss:A20test]
+ je .a20_wait
+ pop es
ret
disable_a20:
@@ -2327,6 +2337,14 @@ disable_a20:
out 060h, al
jmp short kbc_delay
+kbc_delay: call empty_8042
+ push cx
+ mov cx, delaytime
+.delayloop: io_delay
+ loop .delayloop
+ pop cx
+ ret
+
empty_8042:
io_delay
in al, 064h ; Status port