Im not convinced that the bit 5 thing is supported, at least not in all real systems, and as you say the SMM bios code is likely to be dodgy.
I see your point about using that for a polling model, which I certainly wouldn't be using. Both kybd and mouse code are using their respective irq's and handlers.
I removed the bit 5 check totally and the whole thing still works beautifully in both bochs and qemu, still have the issue on real h/w that when both are active - neither work, but disable on or the other and the other works perfectly on it's own. So I know the kybd code is "right", and the mouse code is "right", but something about having them on together isn't happy. I happen to do the kybd init first, then the mouse init.
Code: Select all
init_kybd_driver:
; Perform full keyboard diagnostics / self-test.
call kybd_ctrl_self_test
test al,al
jz short kybd_ok0
ret
kybd_ok0:
call kybd_ctrl_interface_test
test al,al
jz short kybd_ok1
ret
kybd_ok1:
; Install our customer IRQ1 ISR.
INSTALL_IRQ_HANDLER 1,ps2_kybd_handler
; Ensure the keyboard controller is enabled and the output buffer is empty.
; -> This will allow IRQ1 to fire, as it won't with a full buffer.
call kybd_enable
call wait_kybd_out_empty
; Ensure all LEDs are off and the states are stored.
call kybd_clear_leds
mov [_ps2_numlock],0
mov [_ps2_capslock],0
mov [_ps2_scrolllock],0
mov [ps2_led_states],0
xor al,al
ret
and then
Code: Select all
init_ps2_mouse_driver:
call wait_mouse_in_empty
mov al,0a8h
out 64h,al
call wait_mouse_in_empty
mov al,020h ; Read Command (compaq status byte).
out 64h,al
call wait_mouse_out_full
in al,60h
or al,00000010b ; Enable IRQ12 (bit 1).
mov bl,al
call wait_mouse_in_empty
mov al,060h ; Write Command (compaq status byte).
out 64h,al
call wait_mouse_in_empty
mov al,bl
out 60h,al
mov bl,0f6h ; Tell the mouse to use default settings.
call ps2_mouse_write
call ps2_mouse_read
mov bl,0f4h ; Enable the mouse.
call ps2_mouse_write
call ps2_mouse_read
; Install our PS2 (IRQ12) Mouse Handler.
INSTALL_IRQ_HANDLER 12,ps2_mouse_handler
ret
I don't see anything in the init code that could cause a conflict.. and assuming that when the IRQ1 or 12 is fired the byte read from 60h doesn't need to be checked to see if it's a mouse or kybd byte then this should all be 100%.
MOUSE HANDLER CODE: (note it has some non reentrant stuff and some excessive things just for testing related to screen pos etc)
Code: Select all
ps2_mouse_handler:
push rsi
in al,64h
test al,01h ; Wait for the output buffer to be full with data.
jz no_mouse_byte
in al,60h ; Read a data byte.
mov rsi,offset mouse_packet
xor rbx,rbx
mov bl,[mouse_cycle]
add rsi,rbx
mov [rsi],al
add [mouse_cycle],1
cmp byte [mouse_cycle],3 ; Only if we've had all 3 data bytes should we do anything.
jne no_mouse_byte
; We now have the full data-packet, let's process it.
mov [mouse_cycle],0 ; Reset the cycle value.
mov rsi,offset mouse_packet
mov bl,[rsi] ; Read the flags byte.
test bl,80h
jnz no_mouse_byte ; Ignore Y Overflow.
test bl,40h
jnz no_mouse_byte ; Ignore X Overflow.
; Obtain the Mouse Deltas.
xor eax,eax
mov al,[rsi+2] ; Y-Delta
test bl,20h ; Is the Y-Delta Negative Flag Set?
jz short no_neg_y
or eax,0ffffff00h
no_neg_y:
mov [mouse_delta_y],eax
xor eax,eax
mov al,[rsi+1] ; X-Delta
test bl,10h ; Is the X-Delta Negative Flag Set?
jz short no_neg_x
or eax,0ffffff00h
no_neg_x:
mov [mouse_delta_x],eax
mov byte [mouse_button0_state],0
mov byte [mouse_button1_state],0
mov byte [mouse_button2_state],0
; Update the primary 3 button states.
test bl,04h
jz no_middle_button_press
mov byte [mouse_button2_state],1
push rbx
MONITOR_WRITE k_mouse0,000044ffh
pop rbx
no_middle_button_press:
test bl,02h
jz no_right_button_press
mov byte [mouse_button1_state],1
push rbx
MONITOR_WRITE k_mouse1,000044ffh
pop rbx
no_right_button_press:
test bl,01h
jz no_button_press
mov byte [mouse_button0_state],1
push rbx
MONITOR_WRITE k_mouse2,000044ffh
pop rbx
no_button_press:
; Update the Mouse/Screen Coordinates.
mov eax,[mouse_delta_x]
add [mouse_x],eax
mov eax,[mouse_delta_y]
sub [mouse_y],eax
cmp [mouse_x],799
jl cx0
mov [mouse_x],0
jmp m_pos_constrainedx
cx0:
cmp [mouse_x],0
jge m_pos_constrainedx
mov [mouse_x],799
m_pos_constrainedx:
cmp [mouse_y],599
jl cy0
mov [mouse_y],0
jmp m_pos_constrainedy
cy0:
cmp [mouse_y],0
jge m_pos_constrainedy
mov [mouse_y],599
m_pos_constrainedy:
; Draw test pixels.
push rdi
mov rdi,[kmonitor_view_addr]
xor rax,rax
mov eax,[mouse_y]
imul eax,(800*4)
add rdi,rax
xor rax,rax
mov eax,[mouse_x]
shl eax,2
add rdi,rax
mov eax,0025ff9fh
mov [rdi],eax
pop rdi
no_mouse_byte:
pop rsi
ret
and kybd handler:
Code: Select all
ps2_kybd_handler:
; Wait for full buffer and read scan-code.
;----------------------------------------------------
in al,KYBD_CTRL_STATUS_REG
test al,KYBD_CTRL_STATUS_MASK_OUT_BUF
jz ps2_buffer_not_full_yet
call kybd_enc_read_buffer ; Read the scan-code into AL.
mov [_ps2_scancode],al ; Store it.
; Check for extended scan-codes.
;----------------------------------------------------
mov byte [_ps2_extended],0 ; Set extended scan-code state to default.
check_ext_scan0:
cmp al,0e0h
jne short check_ext_scan1
mov byte [_ps2_extended],1 ; Store that it is an extended scancode.
jmp handle_ext_codes
check_ext_scan1:
cmp al,0e1h
jne short check_ext_done
mov byte [_ps2_extended],1 ; Store that it is an extended scancode.
jmp handle_ext_codes
check_ext_done:
; Handle LED Modifier Toggle Keys.
;----------------------------------------------------
cmp al,SCANCODES0_CAPS_MAKE
jne short scan0_01
cmp [_ps2_capslock],0
jne short scan0_00
mov byte [_ps2_capslock],1
mov bh,[ps2_led_states]
or bh,00000100b
mov [ps2_led_states],bh
call kybd_set_leds
jmp scancodes_done
scan0_00:
mov byte [_ps2_capslock],0
mov bh,[ps2_led_states]
and bh,11111011b
mov [ps2_led_states],bh
call kybd_set_leds
jmp scancodes_done
scan0_01:
cmp al,SCANCODES0_NUMLOCK_MAKE
jne short scan0_03
cmp [_ps2_numlock],0
jne short scan0_02
mov byte [_ps2_numlock],1
mov bh,[ps2_led_states]
or bh,00000010b
mov [ps2_led_states],bh
call kybd_set_leds
jmp scancodes_done
scan0_02:
mov byte [_ps2_numlock],0
mov bh,[ps2_led_states]
and bh,11111101b
mov [ps2_led_states],bh
call kybd_set_leds
jmp scancodes_done
scan0_03:
cmp al,SCANCODES0_SCROLLLOCK_MAKE
jne short scan0_05
cmp [_ps2_scrolllock],0
jne short scan0_04
mov byte [_ps2_scrolllock],1
mov bh,[ps2_led_states]
or bh,00000001b
mov [ps2_led_states],bh
call kybd_set_leds
jmp scancodes_done
scan0_04:
mov byte [_ps2_scrolllock],0
mov bh,[ps2_led_states]
and bh,11111110b
mov [ps2_led_states],bh
call kybd_set_leds
jmp scancodes_done
scan0_05:
cmp al,0fah ; ignore keyboard cmd ack in buffer?
je short ps2_buffer_not_full_yet
; Set corresponding key to on for a make code.
xor ebx,ebx
mov bl,al
mov byte [key_states+ebx],1
; Set the key to off for a break code.
xor ebx,ebx
mov bl,al
mov byte [key_states+ebx],0
scancodes_done:
call ps2_kybd_get_ascii
xor ah,ah
call generic_kybd_handler
MONITOR_WRITE_BYTE [_ps2_scancode],00ff0000h
handle_ext_codes:
ps2_buffer_not_full_yet:
ret