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.7KB

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