windows-nt/Source/XPSP1/NT/base/boot/detect/i386/keybda.asm
2020-09-26 16:20:57 +08:00

480 lines
9.8 KiB
NASM
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

title "Keyboard Detection"
;++
;
; Copyright (c) 1989 Microsoft Corporation
;
; Module Name:
;
; cpu.asm
;
; Abstract:
;
; This module implements the assembley code necessary to determine
; keyboard.
;
; Author:
;
; Shie-Lin Tzong (shielint) 16-Dec-1991. Most of the code is extracted
; from Win31 Setup.
;
; Environment:
;
; 80x86 Real Mode.
;
; Revision History:
;
;
;--
extrn _READ_PORT_UCHAR:proc
;
; Now define the needed equates.
;
TRUE equ -1
FALSE equ 0
;
; equates for ports -- these are used in the keyboard detection module.
;
ack_port equ 20h ; 8259 acknowledge port
eoi equ 20h ; 8259 end of interrupt
kb_data equ 60h
kb_ctl equ 61h
kb_command equ 64h ;
kb_status equ 64h ; status port -- bit 1: ok to write
ENABLE_KEYBOARD_COMMAND EQU 0AEH
DISABLE_KEYBOARD_COMMAND EQU 0ADH
.386
_TEXT SEGMENT PARA USE16 PUBLIC 'CODE'
ASSUME CS: _TEXT, DS:NOTHING, SS:NOTHING
;++
;
; BOOLEAN
; IsEnhancedKeyboard (
; VOID
; )
;
; Routine Description:
;
; Function looks at bios data area 40:96 to see if an enhanced keyboard
; is present.
;
; Arguments:
;
; None.
;
; Return Value:
;
; TRUE if Enhanced keyboard is present. Else a value of FALSE is returned.
;
;--
Public _IsEnhancedKeyboard
_IsEnhancedKeyboard proc near
push es
mov ax,40h
mov es,ax
xor ax,ax
mov al,byte ptr es:[96h]
and al,00010000b
pop es
ret
_IsEnhancedKeyboard endp
;++
;
; SHORT
; GetKeyboardIdBytes (
; PCHAR IdBuffer,
; SHORT Length
; )
;
; Routine Description:
;
; This routine returns keyboard identification bytes.
;
; Note that this function accepts one argument. The arg is a pointer to a
; character buffer allocated to hold five (five) bytes. Upon return from
; this function the buffer will contain between 1 and 5 bytes of keyboard
; ID information. The number of valid ID bytes in the buffer is returned
; in AX as a C proc return value.
;
; Arguments:
;
; None.
;
; Return Value:
;
; Id bytes are stored in IdBuffer and the length of Id bytes is returned.
;
;--
KeybID EQU [bp + 4] ; parameters
ReqByte EQU [bp + 6]
nKeyID EQU [bp - 2] ; Local variables
AckByte EQU [bp - 3]
public _GetKeyboardIdBytes
_GetKeyboardIdBytes proc near
push bp
mov bp, sp
sub sp, 4 ; space for local variables
push bx
push es
;
; First I initialize needed local vars. Next I find out if machine is AT
; type or non AT type for the purpose of selecting proper acknowledgement
; byte so I can talk to the interrupt controler.
;
mov bx, KeybID ; Initialize base pointer to buffer.
mov word ptr nKeyID, 0 ; Initialize count to zero.
mov byte ptr AckByte, 20h ; for all but AT-like. acknowledge for
; interrupt controller. 61h for AT's.
mov ax, 0fff0h ; look into 0FFF0:0FE location.
mov es, ax ; this is where the model byte is.
mov al, byte ptr es:[0feh]
cmp al, 0fch ; is it AT-like?
jne UnlikeAT
mov byte ptr AckByte, 61h
call _Empty8042
if 0
;
; Disable keyboard is a right thing to do. But, it turned out
; this causes some keyboards to fail GetId.
;
call DisableKeyboard
endif
UnlikeAT:
;
; Now, let's see if we can get some ID bytes from the keyboard controler.
;
mov ah, ReqByte ; AT: send second command.
mov dx, 60h ; write to data port
call Write8042 ; Output command byte to keyboard, bytes in AH
call ReadKeyboard ; Get byte from keyboard, byte in AL if No CF
jc gotNoByte
mov [bx], al ; save a byte. remember bx is pointer.
inc word ptr nKeyID
call ReadKeyboard ; Get byte from keyboard, byte in AL if No CF
jc gotNoByte
mov [bx]+1, al ; save a byte. remember bx is pointer.
inc word ptr nKeyID
call ReadKeyboard ; check for extra bytes.
jc gotNoByte
mov [bx]+2, al ; save a byte. remember bx is pointer.
inc word ptr nKeyID
gotNoByte:
mov al, AckByte
out ack_port, al
call EnableKeyboard
call _Empty8042
mov ax, nKeyID ; Return number of valid ID bytes obtained.
pop es
pop bx
mov sp, bp
pop bp
ret
_GetKeyboardIdBytes endp
;++
;
; UCHAR
; ReadKeyboard (
; VOID
; )
;
; Routine Description:
;
; This routine reads character from keyboard.
;
; It is assumed that a command (05H or 0F2H) has been set to request
; that the keyboard send an identification byte.
; It is also assumed that interrupts are disabled.
;
; Arguments:
;
; None.
;
; Return Value:
;
; If a character is returned, the carry bit is reset.
; If no character is returned, the carry bit is set.
;
;--
public ReadKeyboard
ReadKeyboard proc near
push cx
push bx
mov bx, 2 ; set outer timeout for double nested.
cli
inner_timeout:
xor cx, cx ; set inner timeout for double nested.
kbiwait:
in al, kb_status ; wait for port ready
test al, 1 ; ready?
jnz kbiAvailable
loop kbiwait
dec bx ; decrement outer timeout loop.
jnz inner_timeout ; zero out inner loop again.
stc
jmp short no_byte
kbiAvailable: ; we received a byte.
mov cx,100
;
; We need to let some time elapse before we try to read the data
; because of a problem running this code in the DOS box under
; OS/2.
;
wait_for_data:
loop wait_for_data
in al, kb_data ; get data byte.
clc
no_byte:
sti
pop bx
pop cx
ret
ReadKeyboard endp
;++
;
; UCHAR
; Write8042 (
; USHORT Port,
; UCHAR Command
; )
;
; Routine Description:
;
; This routine writes command byte to keyboard.
;
; It is assumed that a command (05H or 0F2H) has been set to request
; that the keyboard send an identification byte.
; It is also assumed that interrupts are disabled.
;
; Arguments:
;
; Port (dx) - Port to write data to
; Command (ah) - to be written to keyboard.
;
; Return Value:
;
; None.
;
;--
public Write8042
Write8042 proc near
push cx
push bx
mov bx, 4 ; set outer timeout for double nested.
cli
reset_inner:
xor cx, cx ; set inner timeout for double dested.
koutwait:
in al, kb_status ; get 8042 status
test al, 10b ; can we output a byte?
jz ok_to_send
loop koutwait
dec bx ; decrement outer timeout loop.
jnz reset_inner ; zero out inner loop again.
jmp short nosiree ; timeout expired, don't try to send.
ok_to_send:
call _Empty8042
mov al, ah ; ok, send the byte
out dx, al
nosiree:
sti
pop bx
pop cx
ret
Write8042 endp
;++
;
; UCHAR
; GetKeyboardFlags (
; VOID
; )
;
; Routine Description:
;
; This routine returns the ROM BIOS flags byte that describes the state
; of the various keyboard toggles and shift keys.
;
; Arguments:
;
; None.
;
; Return Value:
;
; Keyboard ROM BIOS Flags byte.
;
;--
public _GetKeyboardFlags
_GetKeyboardFlags proc near
mov ah, 02
int 16h
ret
_GetKeyboardFlags endp
;++
;
; VOID
; EnableKeyboard (
; VOID
; )
;
; Routine Description:
;
; This routine enables 8042 keyboard interface.
;
; Arguments:
;
; None.
;
; Return Value:
;
; None.
;
;--
public EnableKeyboard
EnableKeyboard proc near
mov ah, ENABLE_KEYBOARD_COMMAND
mov dx, kb_command
call Write8042
ret
EnableKeyboard endp
;++
;
; VOID
; DisableKeyboard (
; VOID
; )
;
; Routine Description:
;
; This routine disables 8042 keyboard interface.
;
; Arguments:
;
; None.
;
; Return Value:
;
; None.
;
;--
public DisableKeyboard
DisableKeyboard proc near
mov ah, DISABLE_KEYBOARD_COMMAND
mov dx, kb_command
call Write8042
ret
DisableKeyboard endp
;++
;
; VOID
; Empty8042 (
; VOID
; )
;
; Routine Description:
;
; This routine drains the i8042 controller's output buffer. This gets
; rid of stale data that may have resulted from the user hitting a key
; or moving the mouse, prior to the execution of keyboard initialization.
;
; Arguments:
;
; None.
;
; Return Value:
;
; None.
;
;--
public _Empty8042
_Empty8042 proc near
push ax
push dx
pushf
cli
E8Check:
in al, kb_status ; wait for port ready
test al, 1 ; ready?
jz E8Exit
mov dx, kb_data
push dx
call _READ_PORT_UCHAR ; use this call to delay I/O
add sp, 2
jmp E8Check
E8Exit:
popf
pop dx
pop ax
ret
_Empty8042 endp
_TEXT ends
END