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

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