2 * Copyright (C) 2010 Michael Brown <mbrown@fensystems.co.uk>.
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or any later version.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 FILE_LICENCE ( GPL2_OR_LATER )
25 /****************************************************************************
26 * test_a20_short, test_a20_long
28 * Check to see if A20 line is enabled
33 * CF set if A20 line is not enabled
36 ****************************************************************************
38 #define TEST_A20_SHORT_MAX_RETRIES 0x20
39 #define TEST_A20_LONG_MAX_RETRIES 0x200000
40 .section ".text16.early", "awx", @progbits
44 movl $TEST_A20_SHORT_MAX_RETRIES, %ecx
46 .size test_a20_short, . - test_a20_short
49 movl $TEST_A20_LONG_MAX_RETRIES, %ecx
54 /* Set up segment registers for access across the 1MB boundary */
60 2: /* Modify and check test pattern; succeed if we see a difference */
76 99: /* Restore registers and return */
82 .size test_a20_long, . - test_a20_long
84 /****************************************************************************
87 * Try enabling A20 line via BIOS
92 * CF set if A20 line is not enabled
95 ****************************************************************************
97 .section ".text16.early", "awx", @progbits
101 /* Preserve registers. Be very paranoid, since some BIOSes
102 * are reported to clobber %ebx
106 /* Attempt INT 15,2401 */
111 /* Check that success was really successful */
114 99: /* Restore registers and return */
117 .size enable_a20_bios, . - enable_a20_bios
119 /****************************************************************************
122 * Try enabling A20 line via keyboard controller
127 * CF set if A20 line is not enabled
130 ****************************************************************************
133 #define KC_RDWR_SET_A20 0xdf
135 #define KC_CMD_WOUT 0xd1
136 #define KC_CMD_NULL 0xff
137 #define KC_STATUS 0x64
138 #define KC_STATUS_OBUF_FULL 0x01
139 #define KC_STATUS_IBUF_FULL 0x02
140 #define KC_MAX_RETRIES 100000
141 .section ".text16.early", "awx", @progbits
144 /* Preserve registers */
147 /* Try keyboard controller */
149 movb $KC_CMD_WOUT, %al
152 movb $KC_RDWR_SET_A20, %al
155 movb $KC_CMD_NULL, %al
159 /* Check to see if it worked */
162 /* Restore registers and return */
165 .size enable_a20_kbc, . - enable_a20_kbc
167 .section ".text16.early", "awx", @progbits
170 /* Preserve registers */
174 /* Wait for KBC to become empty */
175 movl $KC_MAX_RETRIES, %ecx
178 testb $( KC_STATUS_OBUF_FULL | KC_STATUS_IBUF_FULL ), %al
180 testb $KC_STATUS_OBUF_FULL, %al
186 99: /* Restore registers and return */
190 .size empty_kbc, . - empty_kbc
192 /****************************************************************************
195 * Try enabling A20 line via "Fast Gate A20"
200 * CF set if A20 line is not enabled
203 ****************************************************************************
206 .section ".text16.early", "awx", @progbits
209 /* Preserve registers */
212 /* Try "Fast Gate A20" */
218 /* Check to see if it worked */
221 /* Restore registers and return */
224 .size enable_a20_fast, . - enable_a20_fast
226 /****************************************************************************
229 * Try enabling A20 line via any available method
234 * CF set if A20 line is not enabled
237 ****************************************************************************
239 #define ENABLE_A20_RETRIES 255
240 .section ".text16.early", "awx", @progbits
244 /* Preserve registers */
248 /* Check to see if A20 is already enabled */
252 /* Use known working method, if we have one */
253 movw %cs:enable_a20_method, %ax
259 /* Try all methods in turn until one works */
260 movl $ENABLE_A20_RETRIES, %ecx
261 2: movw $enable_a20_bios, %ax
262 movw %ax, %cs:enable_a20_method
265 movw $enable_a20_kbc, %ax
266 movw %ax, %cs:enable_a20_method
269 movw $enable_a20_fast, %ax
270 movw %ax, %cs:enable_a20_method
274 /* Failure; exit with carry set */
275 movw $0, %cs:enable_a20_method
278 99: /* Restore registers and return */
283 .section ".text16.early.data", "aw", @progbits
287 .size enable_a20_method, . - enable_a20_method
289 /****************************************************************************
290 * access_highmem (real mode far call)
292 * Open up access to high memory with A20 enabled
297 * CF set if high memory could not be accessed
300 ****************************************************************************
302 .section ".text16.early", "awx", @progbits
304 .globl access_highmem
306 /* Enable A20 line */
309 .size access_highmem, . - access_highmem