|
|
1.1 root 1: /*
2: * Copyright (C) 2010 Michael Brown <[email protected]>.
3: *
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.
8: *
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.
13: *
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., 675 Mass Ave, Cambridge, MA 02139, USA.
17: *
18: */
19:
20: FILE_LICENCE ( GPL2_OR_LATER )
21:
22: .arch i386
23:
24: /****************************************************************************
25: * test_a20_short, test_a20_long
26: *
27: * Check to see if A20 line is enabled
28: *
29: * Parameters:
30: * none
31: * Returns:
32: * CF set if A20 line is not enabled
33: * Corrupts:
34: * none
35: ****************************************************************************
36: */
37: #define TEST_A20_SHORT_MAX_RETRIES 0x20
38: #define TEST_A20_LONG_MAX_RETRIES 0x200000
39: .section ".text16.early", "awx", @progbits
40: .code16
41: test_a20_short:
42: pushl %ecx
43: movl $TEST_A20_SHORT_MAX_RETRIES, %ecx
44: jmp 1f
45: .size test_a20_short, . - test_a20_short
46: test_a20_long:
47: pushl %ecx
48: movl $TEST_A20_LONG_MAX_RETRIES, %ecx
49: 1: pushw %ax
50: pushw %ds
51: pushw %es
52:
53: /* Set up segment registers for access across the 1MB boundary */
54: xorw %ax, %ax
55: movw %ax, %ds
56: decw %ax
57: movw %ax, %es
58:
59: 2: /* Modify and check test pattern; succeed if we see a difference */
60: pushfw
61: cli
62: xchgw %ds:0, %cx
63: movw %es:0x10, %ax
64: xchgw %ds:0, %cx
65: popfw
66: cmpw %ax, %cx
67: clc
68: jnz 99f
69:
70: /* Delay and retry */
71: outb %al, $0x80
72: addr32 loop 2b
73: stc
74:
75: 99: /* Restore registers and return */
76: popw %es
77: popw %ds
78: popw %ax
79: popl %ecx
80: ret
81: .size test_a20_long, . - test_a20_long
82:
83: /****************************************************************************
84: * enable_a20_bios
85: *
86: * Try enabling A20 line via BIOS
87: *
88: * Parameters:
89: * none
90: * Returns:
91: * CF set if A20 line is not enabled
92: * Corrupts:
93: * none
94: ****************************************************************************
95: */
96: .section ".text16.early", "awx", @progbits
97: .code16
98: enable_a20_bios:
99: /* Preserve registers */
100: pushw %ax
101:
102: /* Attempt INT 15,2401 */
103: movw $0x2401, %ax
104: int $0x15
105: jc 99f
106:
107: /* Check that success was really successful */
108: call test_a20_short
109:
110: 99: /* Restore registers and return */
111: popw %ax
112: ret
113: .size enable_a20_bios, . - enable_a20_bios
114:
115: /****************************************************************************
116: * enable_a20_kbc
117: *
118: * Try enabling A20 line via keyboard controller
119: *
120: * Parameters:
121: * none
122: * Returns:
123: * CF set if A20 line is not enabled
124: * Corrupts:
125: * none
126: ****************************************************************************
127: */
128: #define KC_RDWR 0x60
129: #define KC_RDWR_SET_A20 0xdf
130: #define KC_CMD 0x64
131: #define KC_CMD_WOUT 0xd1
132: #define KC_CMD_NULL 0xff
133: #define KC_STATUS 0x64
134: #define KC_STATUS_OBUF_FULL 0x01
135: #define KC_STATUS_IBUF_FULL 0x02
136: #define KC_MAX_RETRIES 100000
137: .section ".text16.early", "awx", @progbits
138: .code16
139: enable_a20_kbc:
140: /* Preserve registers */
141: pushw %ax
142:
143: /* Try keyboard controller */
144: call empty_kbc
145: movb $KC_CMD_WOUT, %al
146: outb %al, $KC_CMD
147: call empty_kbc
148: movb $KC_RDWR_SET_A20, %al
149: outb %al, $KC_RDWR
150: call empty_kbc
151: movb $KC_CMD_NULL, %al
152: outb %al, $KC_CMD
153: call empty_kbc
154:
155: /* Check to see if it worked */
156: call test_a20_long
157:
158: /* Restore registers and return */
159: popw %ax
160: ret
161: .size enable_a20_kbc, . - enable_a20_kbc
162:
163: .section ".text16.early", "awx", @progbits
164: .code16
165: empty_kbc:
166: /* Preserve registers */
167: pushl %ecx
168: pushw %ax
169:
170: /* Wait for KBC to become empty */
171: movl $KC_MAX_RETRIES, %ecx
172: 1: outb %al, $0x80
173: inb $KC_STATUS, %al
174: testb $( KC_STATUS_OBUF_FULL | KC_STATUS_IBUF_FULL ), %al
175: jz 99f
176: testb $KC_STATUS_OBUF_FULL, %al
177: jz 2f
178: outb %al, $0x80
179: inb $KC_RDWR, %al
180: 2: addr32 loop 1b
181:
182: 99: /* Restore registers and return */
183: popw %ax
184: popl %ecx
185: ret
186: .size empty_kbc, . - empty_kbc
187:
188: /****************************************************************************
189: * enable_a20_fast
190: *
191: * Try enabling A20 line via "Fast Gate A20"
192: *
193: * Parameters:
194: * none
195: * Returns:
196: * CF set if A20 line is not enabled
197: * Corrupts:
198: * none
199: ****************************************************************************
200: */
201: #define SCP_A 0x92
202: .section ".text16.early", "awx", @progbits
203: .code16
204: enable_a20_fast:
205: /* Preserve registers */
206: pushw %ax
207:
208: /* Try "Fast Gate A20" */
209: inb $SCP_A, %al
210: orb $0x02, %al
211: andb $~0x01, %al
212: outb %al, $SCP_A
213:
214: /* Check to see if it worked */
215: call test_a20_long
216:
217: /* Restore registers and return */
218: popw %ax
219: ret
220: .size enable_a20_fast, . - enable_a20_fast
221:
222: /****************************************************************************
223: * enable_a20
224: *
225: * Try enabling A20 line via any available method
226: *
227: * Parameters:
228: * none
229: * Returns:
230: * CF set if A20 line is not enabled
231: * Corrupts:
232: * none
233: ****************************************************************************
234: */
235: #define ENABLE_A20_RETRIES 255
236: .section ".text16.early", "awx", @progbits
237: .code16
238: .globl enable_a20
239: enable_a20:
240: /* Preserve registers */
241: pushl %ecx
242: pushw %ax
243:
244: /* Check to see if A20 is already enabled */
245: call test_a20_short
246: jnc 99f
247:
248: /* Use known working method, if we have one */
249: movw %cs:enable_a20_method, %ax
250: testw %ax, %ax
251: jz 1f
252: call *%ax
253: jmp 99f
254: 1:
255: /* Try all methods in turn until one works */
256: movl $ENABLE_A20_RETRIES, %ecx
257: 2: movw $enable_a20_bios, %ax
258: movw %ax, %cs:enable_a20_method
259: call *%ax
260: jnc 99f
261: movw $enable_a20_kbc, %ax
262: movw %ax, %cs:enable_a20_method
263: call *%ax
264: jnc 99f
265: movw $enable_a20_fast, %ax
266: movw %ax, %cs:enable_a20_method
267: call *%ax
268: jnc 99f
269: addr32 loop 2b
270: /* Failure; exit with carry set */
271: movw $0, %cs:enable_a20_method
272: stc
273:
274: 99: /* Restore registers and return */
275: popw %ax
276: popl %ecx
277: ret
278:
279: .section ".text16.early.data", "aw", @progbits
280: .align 2
281: enable_a20_method:
282: .word 0
283: .size enable_a20_method, . - enable_a20_method
284:
285: /****************************************************************************
286: * access_highmem (real mode far call)
287: *
288: * Open up access to high memory with A20 enabled
289: *
290: * Parameters:
291: * none
292: * Returns:
293: * CF set if high memory could not be accessed
294: * Corrupts:
295: * none
296: ****************************************************************************
297: */
298: .section ".text16.early", "awx", @progbits
299: .code16
300: .globl access_highmem
301: access_highmem:
302: /* Enable A20 line */
303: call enable_a20
304: lret
305: .size access_highmem, . - access_highmem
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.