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.

479 lines
9.8 KiB

  1. title "Keyboard Detection"
  2. ;++
  3. ;
  4. ; Copyright (c) 1989 Microsoft Corporation
  5. ;
  6. ; Module Name:
  7. ;
  8. ; cpu.asm
  9. ;
  10. ; Abstract:
  11. ;
  12. ; This module implements the assembley code necessary to determine
  13. ; keyboard.
  14. ;
  15. ; Author:
  16. ;
  17. ; Shie-Lin Tzong (shielint) 16-Dec-1991. Most of the code is extracted
  18. ; from Win31 Setup.
  19. ;
  20. ; Environment:
  21. ;
  22. ; 80x86 Real Mode.
  23. ;
  24. ; Revision History:
  25. ;
  26. ;
  27. ;--
  28. extrn _READ_PORT_UCHAR:proc
  29. ;
  30. ; Now define the needed equates.
  31. ;
  32. TRUE equ -1
  33. FALSE equ 0
  34. ;
  35. ; equates for ports -- these are used in the keyboard detection module.
  36. ;
  37. ack_port equ 20h ; 8259 acknowledge port
  38. eoi equ 20h ; 8259 end of interrupt
  39. kb_data equ 60h
  40. kb_ctl equ 61h
  41. kb_command equ 64h ;
  42. kb_status equ 64h ; status port -- bit 1: ok to write
  43. ENABLE_KEYBOARD_COMMAND EQU 0AEH
  44. DISABLE_KEYBOARD_COMMAND EQU 0ADH
  45. .386
  46. _TEXT SEGMENT PARA USE16 PUBLIC 'CODE'
  47. ASSUME CS: _TEXT, DS:NOTHING, SS:NOTHING
  48. ;++
  49. ;
  50. ; BOOLEAN
  51. ; IsEnhancedKeyboard (
  52. ; VOID
  53. ; )
  54. ;
  55. ; Routine Description:
  56. ;
  57. ; Function looks at bios data area 40:96 to see if an enhanced keyboard
  58. ; is present.
  59. ;
  60. ; Arguments:
  61. ;
  62. ; None.
  63. ;
  64. ; Return Value:
  65. ;
  66. ; TRUE if Enhanced keyboard is present. Else a value of FALSE is returned.
  67. ;
  68. ;--
  69. Public _IsEnhancedKeyboard
  70. _IsEnhancedKeyboard proc near
  71. push es
  72. mov ax,40h
  73. mov es,ax
  74. xor ax,ax
  75. mov al,byte ptr es:[96h]
  76. and al,00010000b
  77. pop es
  78. ret
  79. _IsEnhancedKeyboard endp
  80. ;++
  81. ;
  82. ; SHORT
  83. ; GetKeyboardIdBytes (
  84. ; PCHAR IdBuffer,
  85. ; SHORT Length
  86. ; )
  87. ;
  88. ; Routine Description:
  89. ;
  90. ; This routine returns keyboard identification bytes.
  91. ;
  92. ; Note that this function accepts one argument. The arg is a pointer to a
  93. ; character buffer allocated to hold five (five) bytes. Upon return from
  94. ; this function the buffer will contain between 1 and 5 bytes of keyboard
  95. ; ID information. The number of valid ID bytes in the buffer is returned
  96. ; in AX as a C proc return value.
  97. ;
  98. ; Arguments:
  99. ;
  100. ; None.
  101. ;
  102. ; Return Value:
  103. ;
  104. ; Id bytes are stored in IdBuffer and the length of Id bytes is returned.
  105. ;
  106. ;--
  107. KeybID EQU [bp + 4] ; parameters
  108. ReqByte EQU [bp + 6]
  109. nKeyID EQU [bp - 2] ; Local variables
  110. AckByte EQU [bp - 3]
  111. public _GetKeyboardIdBytes
  112. _GetKeyboardIdBytes proc near
  113. push bp
  114. mov bp, sp
  115. sub sp, 4 ; space for local variables
  116. push bx
  117. push es
  118. ;
  119. ; First I initialize needed local vars. Next I find out if machine is AT
  120. ; type or non AT type for the purpose of selecting proper acknowledgement
  121. ; byte so I can talk to the interrupt controler.
  122. ;
  123. mov bx, KeybID ; Initialize base pointer to buffer.
  124. mov word ptr nKeyID, 0 ; Initialize count to zero.
  125. mov byte ptr AckByte, 20h ; for all but AT-like. acknowledge for
  126. ; interrupt controller. 61h for AT's.
  127. mov ax, 0fff0h ; look into 0FFF0:0FE location.
  128. mov es, ax ; this is where the model byte is.
  129. mov al, byte ptr es:[0feh]
  130. cmp al, 0fch ; is it AT-like?
  131. jne UnlikeAT
  132. mov byte ptr AckByte, 61h
  133. call _Empty8042
  134. if 0
  135. ;
  136. ; Disable keyboard is a right thing to do. But, it turned out
  137. ; this causes some keyboards to fail GetId.
  138. ;
  139. call DisableKeyboard
  140. endif
  141. UnlikeAT:
  142. ;
  143. ; Now, let's see if we can get some ID bytes from the keyboard controler.
  144. ;
  145. mov ah, ReqByte ; AT: send second command.
  146. mov dx, 60h ; write to data port
  147. call Write8042 ; Output command byte to keyboard, bytes in AH
  148. call ReadKeyboard ; Get byte from keyboard, byte in AL if No CF
  149. jc gotNoByte
  150. mov [bx], al ; save a byte. remember bx is pointer.
  151. inc word ptr nKeyID
  152. call ReadKeyboard ; Get byte from keyboard, byte in AL if No CF
  153. jc gotNoByte
  154. mov [bx]+1, al ; save a byte. remember bx is pointer.
  155. inc word ptr nKeyID
  156. call ReadKeyboard ; check for extra bytes.
  157. jc gotNoByte
  158. mov [bx]+2, al ; save a byte. remember bx is pointer.
  159. inc word ptr nKeyID
  160. gotNoByte:
  161. mov al, AckByte
  162. out ack_port, al
  163. call EnableKeyboard
  164. call _Empty8042
  165. mov ax, nKeyID ; Return number of valid ID bytes obtained.
  166. pop es
  167. pop bx
  168. mov sp, bp
  169. pop bp
  170. ret
  171. _GetKeyboardIdBytes endp
  172. ;++
  173. ;
  174. ; UCHAR
  175. ; ReadKeyboard (
  176. ; VOID
  177. ; )
  178. ;
  179. ; Routine Description:
  180. ;
  181. ; This routine reads character from keyboard.
  182. ;
  183. ; It is assumed that a command (05H or 0F2H) has been set to request
  184. ; that the keyboard send an identification byte.
  185. ; It is also assumed that interrupts are disabled.
  186. ;
  187. ; Arguments:
  188. ;
  189. ; None.
  190. ;
  191. ; Return Value:
  192. ;
  193. ; If a character is returned, the carry bit is reset.
  194. ; If no character is returned, the carry bit is set.
  195. ;
  196. ;--
  197. public ReadKeyboard
  198. ReadKeyboard proc near
  199. push cx
  200. push bx
  201. mov bx, 2 ; set outer timeout for double nested.
  202. cli
  203. inner_timeout:
  204. xor cx, cx ; set inner timeout for double nested.
  205. kbiwait:
  206. in al, kb_status ; wait for port ready
  207. test al, 1 ; ready?
  208. jnz kbiAvailable
  209. loop kbiwait
  210. dec bx ; decrement outer timeout loop.
  211. jnz inner_timeout ; zero out inner loop again.
  212. stc
  213. jmp short no_byte
  214. kbiAvailable: ; we received a byte.
  215. mov cx,100
  216. ;
  217. ; We need to let some time elapse before we try to read the data
  218. ; because of a problem running this code in the DOS box under
  219. ; OS/2.
  220. ;
  221. wait_for_data:
  222. loop wait_for_data
  223. in al, kb_data ; get data byte.
  224. clc
  225. no_byte:
  226. sti
  227. pop bx
  228. pop cx
  229. ret
  230. ReadKeyboard endp
  231. ;++
  232. ;
  233. ; UCHAR
  234. ; Write8042 (
  235. ; USHORT Port,
  236. ; UCHAR Command
  237. ; )
  238. ;
  239. ; Routine Description:
  240. ;
  241. ; This routine writes command byte to keyboard.
  242. ;
  243. ; It is assumed that a command (05H or 0F2H) has been set to request
  244. ; that the keyboard send an identification byte.
  245. ; It is also assumed that interrupts are disabled.
  246. ;
  247. ; Arguments:
  248. ;
  249. ; Port (dx) - Port to write data to
  250. ; Command (ah) - to be written to keyboard.
  251. ;
  252. ; Return Value:
  253. ;
  254. ; None.
  255. ;
  256. ;--
  257. public Write8042
  258. Write8042 proc near
  259. push cx
  260. push bx
  261. mov bx, 4 ; set outer timeout for double nested.
  262. cli
  263. reset_inner:
  264. xor cx, cx ; set inner timeout for double dested.
  265. koutwait:
  266. in al, kb_status ; get 8042 status
  267. test al, 10b ; can we output a byte?
  268. jz ok_to_send
  269. loop koutwait
  270. dec bx ; decrement outer timeout loop.
  271. jnz reset_inner ; zero out inner loop again.
  272. jmp short nosiree ; timeout expired, don't try to send.
  273. ok_to_send:
  274. call _Empty8042
  275. mov al, ah ; ok, send the byte
  276. out dx, al
  277. nosiree:
  278. sti
  279. pop bx
  280. pop cx
  281. ret
  282. Write8042 endp
  283. ;++
  284. ;
  285. ; UCHAR
  286. ; GetKeyboardFlags (
  287. ; VOID
  288. ; )
  289. ;
  290. ; Routine Description:
  291. ;
  292. ; This routine returns the ROM BIOS flags byte that describes the state
  293. ; of the various keyboard toggles and shift keys.
  294. ;
  295. ; Arguments:
  296. ;
  297. ; None.
  298. ;
  299. ; Return Value:
  300. ;
  301. ; Keyboard ROM BIOS Flags byte.
  302. ;
  303. ;--
  304. public _GetKeyboardFlags
  305. _GetKeyboardFlags proc near
  306. mov ah, 02
  307. int 16h
  308. ret
  309. _GetKeyboardFlags endp
  310. ;++
  311. ;
  312. ; VOID
  313. ; EnableKeyboard (
  314. ; VOID
  315. ; )
  316. ;
  317. ; Routine Description:
  318. ;
  319. ; This routine enables 8042 keyboard interface.
  320. ;
  321. ; Arguments:
  322. ;
  323. ; None.
  324. ;
  325. ; Return Value:
  326. ;
  327. ; None.
  328. ;
  329. ;--
  330. public EnableKeyboard
  331. EnableKeyboard proc near
  332. mov ah, ENABLE_KEYBOARD_COMMAND
  333. mov dx, kb_command
  334. call Write8042
  335. ret
  336. EnableKeyboard endp
  337. ;++
  338. ;
  339. ; VOID
  340. ; DisableKeyboard (
  341. ; VOID
  342. ; )
  343. ;
  344. ; Routine Description:
  345. ;
  346. ; This routine disables 8042 keyboard interface.
  347. ;
  348. ; Arguments:
  349. ;
  350. ; None.
  351. ;
  352. ; Return Value:
  353. ;
  354. ; None.
  355. ;
  356. ;--
  357. public DisableKeyboard
  358. DisableKeyboard proc near
  359. mov ah, DISABLE_KEYBOARD_COMMAND
  360. mov dx, kb_command
  361. call Write8042
  362. ret
  363. DisableKeyboard endp
  364. ;++
  365. ;
  366. ; VOID
  367. ; Empty8042 (
  368. ; VOID
  369. ; )
  370. ;
  371. ; Routine Description:
  372. ;
  373. ; This routine drains the i8042 controller's output buffer. This gets
  374. ; rid of stale data that may have resulted from the user hitting a key
  375. ; or moving the mouse, prior to the execution of keyboard initialization.
  376. ;
  377. ; Arguments:
  378. ;
  379. ; None.
  380. ;
  381. ; Return Value:
  382. ;
  383. ; None.
  384. ;
  385. ;--
  386. public _Empty8042
  387. _Empty8042 proc near
  388. push ax
  389. push dx
  390. pushf
  391. cli
  392. E8Check:
  393. in al, kb_status ; wait for port ready
  394. test al, 1 ; ready?
  395. jz E8Exit
  396. mov dx, kb_data
  397. push dx
  398. call _READ_PORT_UCHAR ; use this call to delay I/O
  399. add sp, 2
  400. jmp E8Check
  401. E8Exit:
  402. popf
  403. pop dx
  404. pop ax
  405. ret
  406. _Empty8042 endp
  407. _TEXT ends
  408. END