Hi,
XCHG wrote:Could somebody tell me what I am doing wrong?
The keyboard controller documentation *seems* backwards. Data from the CPU goes into the keyboard controller's input buffer, and data ready to go out of the keyboard controller is put in the keyboard controller's output buffer.
Basically, you're waiting until the keyboard controller's input buffer is full (i.e. waiting until the keyboard controller has recieved input from the CPU), when you should be waiting until the keyboard controller's output buffer is full (i.e. waiting until the keyboard controller is ready to output a byte to the CPU).
All you need to do use use Bit #0 of the status register instead of Bit #1 (and Bit #1 instead of Bit #0). For example:
Code: Select all
__KeyboardDisable:
PUSH EAX
;Send "get keyboard controller command byte"
MOV AL , 0x20
OUT 0x64 , AL
;Read the keyboard controller's command byte (hopefully)
.Wait1:
IN AL , 0x64
TEST AL , 0x01 ;Is keyboard controller ready to output data to the CPU?
JE .Wait1 ; no, wait
IN AL , 0x60 ;al = keyboard controller's command byte
;Set the "disable first PS/2 port's clock" flag
OR AL , 0x10 ;Set "disable first PS/2 port's clock" flag
MOV AH , AL ;ah = keyboard controller's command byte with first PS/2 port's clock disabled
;Send "set keyboard controller command byte"
MOV AL , 0x60
OUT 0x64 , AL
;Set the new keyboard controller command byte
.Wait2:
IN AL , 0x64
TEST AL , 0x02 ;Is keyboard controller ready to receive input data from the CPU?
JNZ .Wait2 ; no, wait
MOV AL , AH ;al = keyboard controller's command byte with first PS/2 port's clock disabled
OUT 0x60 , AL
POP EAX
RET
BTW, unless the keyboard is disabled the keyboard controller could receive data from the keyboard at any time. This means the user can press a key immediately before you send the "get keyboard controller command byte" and what you read from the data port will be the scan code for the key they pressed and not the keyboard controller command byte that you're expecting - it's an unfixable race condition.
Instead you should do this:
Code: Select all
__KeyboardDisable:
PUSH EAX
;Send "disable keyboard feature" to the keyboard controller
MOV AL , 0xAD
OUT 0x64 , AL
POP EAX
RET
This does exactly the same as your code (disables the clock line for the first PS/2 ports serial interface), except there is no unfixable race condition (and it's shorter/faster).
Also, I probably should mention that the first time I saw this post I thought I'd be able to find the problem fairly quickly/easily. Then I saw the code (one slab of assembly with no comments), got lazy and decided someone else would be able spend 15 minutes digging through the keyboard controller docuementation to decipher it (and then find the problem fairly quickly/easily). If the original code had comments I would've replied a few days ago instead of being lazy (not that I'm always lazy, it's just that sometimes my mind is on other things).
Cheers,
Brendan