PS/2 keyboard doesn't respond properly to "Get scancode set" command

25 views Asked by At

I'm developing a simple OS and have a problem with ps/2 keyboard initialization. The initialization strategy for both keyboard controller and ps/2 controller are taken from Ben Lunt "FYSOS: Input and Output Devices".

It works nice in Bochs and on one of my test hardware - HP Elite Book with Intel Core i5. But on another laptop - HP Pavilion, Inter Core i5 - the "get scancode set" command runs into a problem: reading the 0x60 port first two times returns two acknowledge bytes, and reading it the third time (expecting the set number) does a timeout.

Is something wrong with my code or is it a bug in the hardware?

The source code below is for the keyboard controller initialization (omitting the steps supposed to go after the problematic fragment, also omitting the code of some obvious subroutines).


;the subroutine kernel_write_ps2 takes byte to write in AL and port address in DX, returns result code in EAX
;the subroutine kernel_read_ps2 (reads the 0x60 port), returns result code in EAX and the read byte in BL
;both subroutines timeout is 100 msec

dk_init:

call dk_set_ps2_for_init

;deactivating both ps/2 channels
mov al, 0xf5
call dk_send_command_wait_acknowledge
cmp eax, G_SYSTEM_ERROR_OK
jnz .exit

mov al, 0xf5
call dk_send_command_wait_acknowledge2
cmp eax, G_SYSTEM_ERROR_OK
jnz .exit

;keyboard reset
mov al, 0xff
call dk_send_command_wait_acknowledge
cmp eax, G_SYSTEM_ERROR_OK
jnz .exit

mov eax, 750
call kernel_mdelay_pcc                      ;750 msec delay


call kernel_read_ps2                        ;wait for output buffer and read
cmp eax, G_SYSTEM_ERROR_OK
jnz .exit

cmp bl, 0xaa
jz .echo
mov eax, G_SYSTEM_ERROR_KB_SELFTEST
jmp .exit


;echo-test
.echo:
mov dx, 0x60
mov al, 0xee
call kernel_write_ps2                       ;wait for input buffer and write
cmp eax, G_SYSTEM_ERROR_OK
jnz .exit

call kernel_read_ps2
cmp eax, G_SYSTEM_ERROR_OK
jnz .exit
 
cmp bl, 0xee
jz .identify

mov eax, G_SYSTEM_ERROR_KB_ECHO
jmp .exit

;getting the keyboard id
.identify:
mov al, 0xf2
call dk_send_command_wait_acknowledge
cmp eax, G_SYSTEM_ERROR_OK
jnz .exit

call kernel_read_ps2
cmp eax, G_SYSTEM_ERROR_OK
jnz .exit

cmp bl, 0xab
jz .identify1

mov eax, G_SYSTEM_ERROR_KB_TYPE
jmp .exit

.identify1:
call kernel_read_ps2
cmp eax, G_SYSTEM_ERROR_OK
jnz .exit

call dk_get_scancode_set

;TODO: reenable things...

.exit:
ret

;--------------

dk_send_command_wait_acknowledge:
push ebx
push edx


mov dx, 0x60
call kernel_write_ps2
cmp eax, G_SYSTEM_ERROR_OK
jnz .exit

call kernel_read_ps2
cmp eax, G_SYSTEM_ERROR_OK
jnz .exit

cmp bl, 0xfa
jnz .error
mov eax, G_SYSTEM_ERROR_OK
jmp .exit

.error:
mov eax, G_SYSTEM_ERROR_KB_COMMAND_NOT_ACK

.exit:
pop edx
pop ebx
ret

;-------------

dk_send_command_wait_acknowledge2:              ;for the second channel
push ebx
push edx

mov bl, al
mov dx, 0x64
mov al, 0xd4
call kernel_write_ps2
cmp eax, G_SYSTEM_ERROR_OK
jnz .exit

mov al, bl
mov dx, 0x60
call kernel_write_ps2
cmp eax, G_SYSTEM_ERROR_OK
jnz .exit

call kernel_read_ps2
cmp eax, G_SYSTEM_ERROR_OK
jnz .exit

cmp bl, 0xfa
jnz .error
mov eax, G_SYSTEM_ERROR_OK
jmp .exit

.error:
mov eax, G_SYSTEM_ERROR_KB_COMMAND_NOT_ACK

.exit:
pop edx
pop ebx
ret


;----------------

;disabling the interrupts for both channels and disabling translation
dk_set_ps2_for_init:
push ebx
push edx


mov dx, 0x64
mov al, 0x20
call kernel_write_ps2
cmp eax, G_SYSTEM_ERROR_OK
jnz .exit

call kernel_read_ps2
cmp eax, G_SYSTEM_ERROR_OK
jnz .exit

.change_config:
and bl, ~((1 << 6) | (1 << 1) | 1)

mov dx, 0x64
mov al, G_PS2_COMMAND_WRITE_RAM_0
call kernel_write_ps2
cmp eax, G_SYSTEM_ERROR_OK
jnz .exit

mov dx, 0x60
mov al, bl
call kernel_write_ps2
cmp eax, G_SYSTEM_ERROR_OK
jnz .exit

.exit:
pop edx
pop ebx
ret

;-------------

dk_get_scancode_set:
mov dx, 0x60
mov al, 0xf0
call kernel_write_ps2
cmp eax, G_SYSTEM_ERROR_OK
jnz .exit

mov dx, 0x60
mov al, 0
call kernel_write_ps2
cmp eax, G_SYSTEM_ERROR_OK
jnz .exit

call kernel_read_ps2
cmp eax, G_SYSTEM_ERROR_OK
jnz .exit

push eax
mov al, bl
call kernel_print_byte_hex      ;printing for debugging purposes
pop eax

call kernel_read_ps2
cmp eax, G_SYSTEM_ERROR_OK
jnz .exit

push eax
mov al, bl
call kernel_print_byte_hex      ;printing for debugging purposes
pop eax

call kernel_read_ps2
cmp eax, G_SYSTEM_ERROR_OK
jnz .exit

push eax
mov al, bl
call kernel_print_byte_hex      ;printing for debugging purposes
pop eax

.exit:
ret
0

There are 0 answers