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

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