1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
|
; functions to handle A20 address line status and switching
; returns 0 if notA20_ENABLED, 1 ifA20_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_VIA_BIOS:
mov al, 'B'
call print_char
mov ax, 0x2401
int 0x15
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
jmp A20_FAST_SPECIAL_PORT
A20_ENABLE_KBD_OUT:
mov al, 'k'
call print_char
cli
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
popa
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_ENABLED:
ret
|