You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

liba20.S 6.9KB

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