add directory study
This commit is contained in:
195
study/sabre/os/files/Booting/enableA20.s
Normal file
195
study/sabre/os/files/Booting/enableA20.s
Normal file
@@ -0,0 +1,195 @@
|
||||
;;
|
||||
;; enableA20.s (adapted from Visopsys OS-loader)
|
||||
;;
|
||||
;; Copyright (c) 2000, J. Andrew McLaughlin
|
||||
;; You're free to use this code in any manner you like, as long as this
|
||||
;; notice is included (and you give credit where it is due), and as long
|
||||
;; as you understand and accept that it comes with NO WARRANTY OF ANY KIND.
|
||||
;; Contact me at jamesamc@yahoo.com about any bugs or problems.
|
||||
;;
|
||||
|
||||
enableA20:
|
||||
;; This subroutine will enable the A20 address line in the keyboard
|
||||
;; controller. Takes no arguments. Returns 0 in EAX on success,
|
||||
;; -1 on failure. Written for use in 16-bit code, see lines marked
|
||||
;; with 32-BIT for use in 32-bit code.
|
||||
|
||||
pusha
|
||||
|
||||
;; Make sure interrupts are disabled
|
||||
cli
|
||||
|
||||
;; Keep a counter so that we can make up to 5 attempts to turn
|
||||
;; on A20 if necessary
|
||||
mov CX, 5
|
||||
|
||||
.startAttempt1:
|
||||
;; Wait for the controller to be ready for a command
|
||||
.commandWait1:
|
||||
xor AX, AX
|
||||
in AL, 64h
|
||||
bt AX, 1
|
||||
jc .commandWait1
|
||||
|
||||
;; Tell the controller we want to read the current status.
|
||||
;; Send the command D0h: read output port.
|
||||
mov AL, 0D0h
|
||||
out 64h, AL
|
||||
|
||||
;; Wait for the controller to be ready with a byte of data
|
||||
.dataWait1:
|
||||
xor AX, AX
|
||||
in AL, 64h
|
||||
bt AX, 0
|
||||
jnc .dataWait1
|
||||
|
||||
;; Read the current port status from port 60h
|
||||
xor AX, AX
|
||||
in AL, 60h
|
||||
|
||||
;; Save the current value of (E)AX
|
||||
push AX ; 16-BIT
|
||||
;; push EAX ; 32-BIT
|
||||
|
||||
;; Wait for the controller to be ready for a command
|
||||
.commandWait2:
|
||||
in AL, 64h
|
||||
bt AX, 1
|
||||
jc .commandWait2
|
||||
|
||||
;; Tell the controller we want to write the status byte again
|
||||
mov AL, 0D1h
|
||||
out 64h, AL
|
||||
|
||||
;; Wait for the controller to be ready for the data
|
||||
.commandWait3:
|
||||
xor AX, AX
|
||||
in AL, 64h
|
||||
bt AX, 1
|
||||
jc .commandWait3
|
||||
|
||||
;; Write the new value to port 60h. Remember we saved the old
|
||||
;; value on the stack
|
||||
pop AX ; 16-BIT
|
||||
;; pop EAX ; 32-BIT
|
||||
|
||||
;; Turn on the A20 enable bit
|
||||
or AL, 00000010b
|
||||
out 60h, AL
|
||||
|
||||
;; Finally, we will attempt to read back the A20 status
|
||||
;; to ensure it was enabled.
|
||||
|
||||
;; Wait for the controller to be ready for a command
|
||||
.commandWait4:
|
||||
xor AX, AX
|
||||
in AL, 64h
|
||||
bt AX, 1
|
||||
jc .commandWait4
|
||||
|
||||
;; Send the command D0h: read output port.
|
||||
mov AL, 0D0h
|
||||
out 64h, AL
|
||||
|
||||
;; Wait for the controller to be ready with a byte of data
|
||||
.dataWait2:
|
||||
xor AX, AX
|
||||
in AL, 64h
|
||||
bt AX, 0
|
||||
jnc .dataWait2
|
||||
|
||||
;; Read the current port status from port 60h
|
||||
xor AX, AX
|
||||
in AL, 60h
|
||||
|
||||
;; Is A20 enabled?
|
||||
bt AX, 1
|
||||
|
||||
;; Check the result. If carry is on, A20 is on.
|
||||
jc .success
|
||||
|
||||
;; Should we retry the operation? If the counter value in ECX
|
||||
;; has not reached zero, we will retry
|
||||
loop .startAttempt1
|
||||
|
||||
|
||||
;; Well, our initial attempt to set A20 has failed. Now we will
|
||||
;; try a backup method (which is supposedly not supported on many
|
||||
;; chipsets, but which seems to be the only method that works on
|
||||
;; other chipsets).
|
||||
|
||||
|
||||
;; Keep a counter so that we can make up to 5 attempts to turn
|
||||
;; on A20 if necessary
|
||||
mov CX, 5
|
||||
|
||||
.startAttempt2:
|
||||
;; Wait for the keyboard to be ready for another command
|
||||
.commandWait6:
|
||||
xor AX, AX
|
||||
in AL, 64h
|
||||
bt AX, 1
|
||||
jc .commandWait6
|
||||
|
||||
;; Tell the controller we want to turn on A20
|
||||
mov AL, 0DFh
|
||||
out 64h, AL
|
||||
|
||||
;; Again, we will attempt to read back the A20 status
|
||||
;; to ensure it was enabled.
|
||||
|
||||
;; Wait for the controller to be ready for a command
|
||||
.commandWait7:
|
||||
xor AX, AX
|
||||
in AL, 64h
|
||||
bt AX, 1
|
||||
jc .commandWait7
|
||||
|
||||
;; Send the command D0h: read output port.
|
||||
mov AL, 0D0h
|
||||
out 64h, AL
|
||||
|
||||
;; Wait for the controller to be ready with a byte of data
|
||||
.dataWait3:
|
||||
xor AX, AX
|
||||
in AL, 64h
|
||||
bt AX, 0
|
||||
jnc .dataWait3
|
||||
|
||||
;; Read the current port status from port 60h
|
||||
xor AX, AX
|
||||
in AL, 60h
|
||||
|
||||
;; Is A20 enabled?
|
||||
bt AX, 1
|
||||
|
||||
;; Check the result. If carry is on, A20 is on, but we might warn
|
||||
;; that we had to use this alternate method
|
||||
jc .warn
|
||||
|
||||
;; Should we retry the operation? If the counter value in ECX
|
||||
;; has not reached zero, we will retry
|
||||
loop .startAttempt2
|
||||
|
||||
|
||||
;; OK, we weren't able to set the A20 address line. Do you want
|
||||
;; to put an error message here?
|
||||
jmp .fail
|
||||
|
||||
|
||||
.warn:
|
||||
;; Here you may or may not want to print a warning message about
|
||||
;; the fact that we had to use the nonstandard alternate enabling
|
||||
;; method
|
||||
|
||||
.success:
|
||||
sti
|
||||
popa
|
||||
xor EAX, EAX
|
||||
ret
|
||||
|
||||
.fail:
|
||||
sti
|
||||
popa
|
||||
mov EAX, -1
|
||||
ret
|
||||
Reference in New Issue
Block a user