Source code of Windows XP (NT5)
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.

279 lines
9.2 KiB

  1. ; NOTICE
  2. ; This was taken from the os2 bios sources and was slightly modified to
  3. ; enable the a20 line. There's still some work to do and much clean-up to
  4. ; bring the file upto coding standards. I'll do this when time permits.
  5. ; TomP
  6. ;* _EnableA20
  7. ;* Description: *
  8. ;* This routine enables and disables the A20 address line, depending on *
  9. ;* the value in ax *
  10. ;* *
  11. ;* In general when in real mode we want the A20 line disabled, *
  12. ;* when in protected mode enabled. However if there is no high *
  13. ;* memory installed we can optimise out unnecessary switching *
  14. ;* of the A20 line. Unfortunately the PC/AT ROM does not allow *
  15. ;* us to completely decouple mode switching the 286 from gating *
  16. ;* the A20 line. *
  17. ;* *
  18. ;* In real mode we would want A20 enabled if we need to access *
  19. ;* high memory, for example in a device driver. We want it *
  20. ;* disabled while running arbitrary applications because they *
  21. ;* may rely on the 1 meg address wrap feature which having the *
  22. ;* A20 line off provides. *
  23. ;* *
  24. ;* This code is largely duplicated from the PC/AT ROM BIOS. *
  25. ;* See Module "BIOS1" on page 5-155 of the PC/AT tech ref. *
  26. ;* *
  27. ;* WARNING: *
  28. ;* *
  29. ;* The performance characteristics of these routines *
  30. ;* are not well understood. There may be worst case *
  31. ;* scenarios where the routine could take a relatively *
  32. ;* long time to complete. *
  33. ;* *
  34. ;* Linkage: *
  35. ;* far call *
  36. ;* *
  37. ;* Input: *
  38. ;* *
  39. ;* Exit: *
  40. ;* A20 line enabled/disabled *
  41. ;* *
  42. ;* Uses: *
  43. ;* ax *
  44. ;* *
  45. ;* Internal References: *
  46. ;* empty_8042 -- waits for 8042 input buffer to drain *
  47. .386p
  48. include su.inc
  49. IODelay macro
  50. jmp $+2
  51. endm
  52. extrn _puts:near
  53. extrn _Empty_8042Failed:near
  54. ; Equates for cmos
  55. CMOS_DATA equ 71h ; I/O word for cmos chip
  56. SHUT_ADDR equ 8fh ; shutdown byte address in cmos
  57. SHUT_CODE equ 9 ; block copy return code we use
  58. ; equates for 8042
  59. STATUS_PORT equ 64h ; 8042 com port
  60. PORT_A equ 60h ; 8042 data port
  61. BUF_FULL equ 2 ; 8042 busy bit
  62. SHUT_CMD equ 0feh ; RESET 286 command
  63. MSW_VIRTUAL equ 1 ; protected mode bit of MSW
  64. MASTER_IMR equ 21h ; mask port for master 8259
  65. ;CONST SEGMENT WORD USE16 PUBLIC 'CONST'
  66. ;CONST ENDS
  67. ;_BSS SEGMENT WORD USE16 PUBLIC 'BSS'
  68. ;_BSS ENDS
  69. ;DGROUP GROUP CONST, _BSS, _DATA
  70. ; ASSUME CS: _TEXT, DS: DGROUP, SS: DGROUP
  71. _TEXT segment para use16 public 'CODE'
  72. ASSUME CS: _TEXT, DS: DGROUP, SS: DGROUP
  73. ;++
  74. ;
  75. ;VOID
  76. ;EnableA20(
  77. ; VOID
  78. ; )
  79. ;
  80. ;Routine Description:
  81. ;
  82. ; Enables the A20 line for any machine.
  83. ;
  84. ;Arguments:
  85. ;
  86. ; None
  87. ;
  88. ;Return Value:
  89. ;
  90. ; None.
  91. ;
  92. ; The A20 line is enabled.
  93. ;
  94. ;--
  95. public _EnableA20
  96. _EnableA20 proc near
  97. ; Check if empty_8042 has failed before
  98. ; If so, skip this function. This would occur
  99. ; on legacy free systems.
  100. mov di,offset DGROUP:_Empty_8042Failed
  101. cmp byte ptr [di],1
  102. jz EA2
  103. ; cmp byte ptr [di],0
  104. call empty_8042 ; ensure 8042 input buffer empty
  105. jnz EA2 ; 8042 error return
  106. ; Enable or disable the A20 line
  107. mov al,0d1h ; 8042 cmd to write output port
  108. out STATUS_PORT,al ; send cmd to 8042
  109. call empty_8042 ; wait for 8042 to accept cmd
  110. jnz EA2 ; 8042 error return
  111. mov al,0dfh ; 8042 port data
  112. out PORT_A,al ; output port data to 8042
  113. call empty_8042
  114. ; We must wait for the a20 line to settle down, which (on an AT)
  115. ; may not happen until up to 20 usec after the 8042 has accepted
  116. ; the command. We make use of the fact that the 8042 will not
  117. ; accept another command until it is finished with the last one.
  118. ; The 0FFh command does a NULL 'Pulse Output Port'. Total execution
  119. ; time is on the order of 30 usec, easily satisfying the IBM 8042
  120. ; settling requirement. (Thanks, CW!)
  121. mov al,0FFh ;* Pulse Output Port (pulse no lines)
  122. out STATUS_PORT,al ;* send cmd to 8042
  123. call empty_8042 ;* wait for 8042 to accept cmd
  124. EA2:
  125. ret
  126. _EnableA20 endp
  127. ;++
  128. ;
  129. ;VOID
  130. ;DisableA20(
  131. ; VOID
  132. ; )
  133. ;
  134. ;Routine Description:
  135. ;
  136. ; Disables the A20 line for any machine.
  137. ;
  138. ;Arguments:
  139. ;
  140. ; None
  141. ;
  142. ;Return Value:
  143. ;
  144. ; None.
  145. ;
  146. ; The A20 line is disabled.
  147. ;
  148. ;--
  149. public _DisableA20
  150. _DisableA20 proc near
  151. ; Check if empty_8042 has failed before
  152. ; If so, skip this function. This would occur
  153. ; on legacy free systems.
  154. mov di,offset DGROUP:_Empty_8042Failed
  155. cmp byte ptr [di],1
  156. jz EA2
  157. cmp byte ptr [di],0
  158. DA1:
  159. call empty_8042 ; ensure 8042 input buffer empty
  160. jnz DA2 ; 8042 error return
  161. ; Disable the A20 line
  162. mov al,0d1h ; 8042 cmd to write output port
  163. out STATUS_PORT,al ; send cmd to 8042
  164. call empty_8042 ; wait for 8042 to accept cmd
  165. jnz DA2 ; 8042 error return
  166. mov al,0ddh ; 8042 port data
  167. out PORT_A,al ; output port data to 8042
  168. call empty_8042
  169. ; We must wait for the a20 line to settle down, which (on an AT)
  170. ; may not happen until up to 20 usec after the 8042 has accepted
  171. ; the command. We make use of the fact that the 8042 will not
  172. ; accept another command until it is finished with the last one.
  173. ; The 0FFh command does a NULL 'Pulse Output Port'. Total execution
  174. ; time is on the order of 30 usec, easily satisfying the IBM 8042
  175. ; settling requirement. (Thanks, CW!)
  176. mov al,0FFh ;* Pulse Output Port (pulse no lines)
  177. out STATUS_PORT,al ;* send cmd to 8042
  178. call empty_8042 ;* wait for 8042 to accept cmd
  179. DA2:
  180. ret
  181. _DisableA20 endp
  182. ;**
  183. ; empty_8042 -- wait for 8042 input buffer to drain
  184. ;
  185. ; Input:
  186. ; interrupts disabled
  187. ;
  188. ; Exit:
  189. ; al=0, z=0 => 8042 input buffer empty
  190. ;
  191. ; Uses:
  192. ; ax, flags
  193. public Empty8042
  194. Empty8042 proc near
  195. empty_8042:
  196. sub cx,cx ; cx = 0, timeout loop counter
  197. emp1: in al,STATUS_PORT ; read 8042 status port
  198. IODelay
  199. IODelay
  200. IODelay
  201. IODelay
  202. and al,BUF_FULL ; test buffer full bit
  203. loopnz emp1
  204. cmp cx,0 ; see if buffer is full
  205. jnz emp2
  206. ; if we reached this point this indicates an error
  207. mov di,offset DGROUP:_Empty_8042Failed
  208. mov byte ptr [di],1
  209. ; mov [_Empty_8042Failed],1 ; set Empty_8042Failed global to "TRUE"
  210. ; mov _Empty_8042Failed,1 ; set Empty_8042Failed global to "TRUE"
  211. ; mov cx, offset _Empty_8042Failed
  212. ; mov [cx],ah
  213. emp2:
  214. and al,BUF_FULL ; reset the Z flag
  215. ret
  216. Empty8042 endp
  217. _TEXT ends
  218. end