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
19 * You can also choose to distribute this program under the terms of
20 * the Unmodified Binary Distribution Licence (as given in the file
21 * COPYING.UBDL), provided that you have satisfied its requirements.
25 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
29 /****************************************************************************
30 * test_a20_short, test_a20_long
32 * Check to see if A20 line is enabled
37 * CF set if A20 line is not enabled
40 ****************************************************************************
42 #define TEST_A20_SHORT_MAX_RETRIES 0x20
43 #define TEST_A20_LONG_MAX_RETRIES 0x200000
44 .section ".text16.early", "awx", @progbits
48 movl $TEST_A20_SHORT_MAX_RETRIES, %ecx
50 .size test_a20_short, . - test_a20_short
53 movl $TEST_A20_LONG_MAX_RETRIES, %ecx
58 /* Set up segment registers for access across the 1MB boundary */
64 2: /* Modify and check test pattern; succeed if we see a difference */
80 99: /* Restore registers and return */
86 .size test_a20_long, . - test_a20_long
88 /****************************************************************************
91 * Try enabling A20 line via BIOS
96 * CF set if A20 line is not enabled
99 ****************************************************************************
101 .section ".text16.early", "awx", @progbits
105 /* Preserve registers. Be very paranoid, since some BIOSes
106 * are reported to clobber %ebx
110 /* Attempt INT 15,2401 */
115 /* Check that success was really successful */
118 99: /* Restore registers and return */
121 .size enable_a20_bios, . - enable_a20_bios
123 /****************************************************************************
126 * Try enabling A20 line via keyboard controller
131 * CF set if A20 line is not enabled
134 ****************************************************************************
137 #define KC_RDWR_SET_A20 0xdf
139 #define KC_CMD_WOUT 0xd1
140 #define KC_CMD_NULL 0xff
141 #define KC_STATUS 0x64
142 #define KC_STATUS_OBUF_FULL 0x01
143 #define KC_STATUS_IBUF_FULL 0x02
144 #define KC_MAX_RETRIES 100000
145 .section ".text16.early", "awx", @progbits
148 /* Preserve registers */
151 /* Try keyboard controller */
153 movb $KC_CMD_WOUT, %al
156 movb $KC_RDWR_SET_A20, %al
159 movb $KC_CMD_NULL, %al
163 /* Check to see if it worked */
166 /* Restore registers and return */
169 .size enable_a20_kbc, . - enable_a20_kbc
171 .section ".text16.early", "awx", @progbits
174 /* Preserve registers */
178 /* Wait for KBC to become empty */
179 movl $KC_MAX_RETRIES, %ecx
182 testb $( KC_STATUS_OBUF_FULL | KC_STATUS_IBUF_FULL ), %al
184 testb $KC_STATUS_OBUF_FULL, %al
190 99: /* Restore registers and return */
194 .size empty_kbc, . - empty_kbc
196 /****************************************************************************
199 * Try enabling A20 line via "Fast Gate A20"
204 * CF set if A20 line is not enabled
207 ****************************************************************************
210 .section ".text16.early", "awx", @progbits
213 /* Preserve registers */
216 /* Try "Fast Gate A20" */
222 /* Check to see if it worked */
225 /* Restore registers and return */
228 .size enable_a20_fast, . - enable_a20_fast
230 /****************************************************************************
233 * Try enabling A20 line via any available method
238 * CF set if A20 line is not enabled
241 ****************************************************************************
243 #define ENABLE_A20_RETRIES 255
244 .section ".text16.early", "awx", @progbits
248 /* Preserve registers */
252 /* Check to see if A20 is already enabled */
256 /* Use known working method, if we have one */
257 movw %cs:enable_a20_method, %ax
263 /* Try all methods in turn until one works */
264 movl $ENABLE_A20_RETRIES, %ecx
265 2: movw $enable_a20_bios, %ax
266 movw %ax, %cs:enable_a20_method
269 movw $enable_a20_kbc, %ax
270 movw %ax, %cs:enable_a20_method
273 movw $enable_a20_fast, %ax
274 movw %ax, %cs:enable_a20_method
278 /* Failure; exit with carry set */
279 movw $0, %cs:enable_a20_method
282 99: /* Restore registers and return */
287 .section ".text16.early.data", "aw", @progbits
291 .size enable_a20_method, . - enable_a20_method
293 /****************************************************************************
294 * access_highmem (real mode far call)
296 * Open up access to high memory with A20 enabled
301 * CF set if high memory could not be accessed
304 ****************************************************************************
306 .section ".text16.early", "awx", @progbits
308 .globl access_highmem
310 /* Enable A20 line */
313 .size access_highmem, . - access_highmem