Hi,guys,I'm coding PS/2 mouse driver for my OS.
When my OS booted,my kernel initialize the mouse and enable IRQ12,it is successfully. The question takes place in my IRQ12 stage:
I read the port 0x60,then save 3 bytes mouse data to the buffer,it seems OK,but the order of package IRQ12 received was different on VPC and twoOStwo:
the button info byte is the FIRST one When my OS runs on Connectix VPC and VMware,but the same byte was place to the THIRD on twoOStwo and my PC.
As I know,the first byte should be the mouse button info and sign the second is X,the third is Y,but twoOStwo and my computer order them as: X,Y,button
Why?
Regards,
E-mean
[email protected]
[Need Help] My PS/2 Mouse Driver
RE:[Need Help] My PS/2 Mouse Driver
Hi E-mean,
to me it looks like you lost synchronsation and now receive X and Y of packet x and button of packet x+1. Something similar happen to me some while ago and as far as I can remember it was because I didn't wait for the buffer full flags correctly. If you could post your code I'll have a look at it.
regards,
gaf
ps:
I you don't want to post your code for some reason you can of course also sent me an e-mail:
gaffi AT haefft DOT de
to me it looks like you lost synchronsation and now receive X and Y of packet x and button of packet x+1. Something similar happen to me some while ago and as far as I can remember it was because I didn't wait for the buffer full flags correctly. If you could post your code I'll have a look at it.
regards,
gaf
ps:
I you don't want to post your code for some reason you can of course also sent me an e-mail:
gaffi AT haefft DOT de
RE:[Need Help] My PS/2 Mouse Driver
; I'd like to post my code of course;)
kb_read:
push ecx
push edx
mov ecx,0xffff
kr_loop:
in al,0x64
test al,1
jnz kr_ready
loop kr_loop
mov ah,1
jmp kr_exit
kr_ready:
push ecx
mov ecx,32
kr_delay:
loop kr_delay
pop ecx
in al,0x60
xor ah,ah
kr_exit:
pop edx
pop ecx
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ps2_mouse
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
ps2_mouse_type db 0 ; a flag for Microsoft Intellimouse,no use yet
temp_counter db 0 ;
ps2_mouse:
pusha
xor ecx,ecx
xor eax,eax
call kb_read ; call keyboard read,return in al
; in al,0x60 ; I use this before
; the following code print EAX value to screen
mov cl,[temp_counter] ; text position on screen ,row
mov edx,72 ; column
call printreg32 ; print EAX
inc byte [temp_counter] ;
cmp [temp_counter],byte 3 ; 3 bytes package
jnz .x
mov [temp_counter],byte 0
.x:
mov al,20h ; ready for next IRQ
out 020h,al
out 0A0h,al
popa
ret
kb_read:
push ecx
push edx
mov ecx,0xffff
kr_loop:
in al,0x64
test al,1
jnz kr_ready
loop kr_loop
mov ah,1
jmp kr_exit
kr_ready:
push ecx
mov ecx,32
kr_delay:
loop kr_delay
pop ecx
in al,0x60
xor ah,ah
kr_exit:
pop edx
pop ecx
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ps2_mouse
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
ps2_mouse_type db 0 ; a flag for Microsoft Intellimouse,no use yet
temp_counter db 0 ;
ps2_mouse:
pusha
xor ecx,ecx
xor eax,eax
call kb_read ; call keyboard read,return in al
; in al,0x60 ; I use this before
; the following code print EAX value to screen
mov cl,[temp_counter] ; text position on screen ,row
mov edx,72 ; column
call printreg32 ; print EAX
inc byte [temp_counter] ;
cmp [temp_counter],byte 3 ; 3 bytes package
jnz .x
mov [temp_counter],byte 0
.x:
mov al,20h ; ready for next IRQ
out 020h,al
out 0A0h,al
popa
ret
RE:[Need Help] My PS/2 Mouse Driver
Hi E-mean,
try to change kbd_read so that it waits for MOBF (dec 32) too. MOBF tells you where the data came from:
OBF MOBF
0 0 No data in 0x60
0 1 No data in 0x60
1 0 Data from the keyboard in 0x60
1 1 Data from the mouse in 0x60
It is possible that your mouse driver got confused because of some unexpected data that was sent by the kbd.
If you know C++ the following code may be of use to you:
enum ps2_status_register
{
output_buffer = 1,
input_buffer = 2,
sys_flag = 4,
a2_address_line = 8,
kbd_inhibit = 16,
mouse_buffer = 32,
general_timeout = 64,
parity_error = 128
};
uchar ps2mouse::GetData()
{
while(!(Port::ReadByte(0x64) &output_buffer + mouse_buffer));
return Port::ReadByte(0x60);
}
If your driver works correctly you also shouldn't have to wait before accessing 0x60 so you can delete kr_delay.
regards,
gaf
try to change kbd_read so that it waits for MOBF (dec 32) too. MOBF tells you where the data came from:
OBF MOBF
0 0 No data in 0x60
0 1 No data in 0x60
1 0 Data from the keyboard in 0x60
1 1 Data from the mouse in 0x60
It is possible that your mouse driver got confused because of some unexpected data that was sent by the kbd.
If you know C++ the following code may be of use to you:
enum ps2_status_register
{
output_buffer = 1,
input_buffer = 2,
sys_flag = 4,
a2_address_line = 8,
kbd_inhibit = 16,
mouse_buffer = 32,
general_timeout = 64,
parity_error = 128
};
uchar ps2mouse::GetData()
{
while(!(Port::ReadByte(0x64) &output_buffer + mouse_buffer));
return Port::ReadByte(0x60);
}
If your driver works correctly you also shouldn't have to wait before accessing 0x60 so you can delete kr_delay.
regards,
gaf
RE:[Need Help] My PS/2 Mouse Driver
; Thanks,gaf. It still confuse me,I tried the following codes,
; it's useless+,is the code right?
; I found the same question on SolarOS;the same code " in al,0x60 " appears on
; MenuetOS's IRQ12 service, witout a MOBF test,but MenuetOS works well
;
kr_mouse:
push ecx
mov ecx,0xFFFF
.krm_loop:
in al,0x64
test al,00100001b ; test OBF and MOBF
jnz .mouse_ready ;
loop .krm_loop
mov ah,1
jmp .krm_x
.mouse_ready:
in al,0x60
xor ah,ah
.krm_x:
pop ecx
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ps2_mouse
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
temp_counter db 0
ps2_mouse:
pusha
xor eax,eax
call kr_mouse
cmp ah,1 ;
jz .x
movzx ecx,byte [temp_counter]
mov edx,72
call printreg32
inc byte [temp_counter]
cmp [temp_counter],byte 3
jnz .x
mov [temp_counter],byte 0
.x:
mov al,20h
out 020h,al
out 0A0h,al
popa
ret
; it's useless+,is the code right?
; I found the same question on SolarOS;the same code " in al,0x60 " appears on
; MenuetOS's IRQ12 service, witout a MOBF test,but MenuetOS works well
;
kr_mouse:
push ecx
mov ecx,0xFFFF
.krm_loop:
in al,0x64
test al,00100001b ; test OBF and MOBF
jnz .mouse_ready ;
loop .krm_loop
mov ah,1
jmp .krm_x
.mouse_ready:
in al,0x60
xor ah,ah
.krm_x:
pop ecx
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ps2_mouse
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
temp_counter db 0
ps2_mouse:
pusha
xor eax,eax
call kr_mouse
cmp ah,1 ;
jz .x
movzx ecx,byte [temp_counter]
mov edx,72
call printreg32
inc byte [temp_counter]
cmp [temp_counter],byte 3
jnz .x
mov [temp_counter],byte 0
.x:
mov al,20h
out 020h,al
out 0A0h,al
popa
ret
RE:[Need Help] My PS/2 Mouse Driver
;I also code "kr_mouse" proc as following,but failed to
kr_mouse:
push ecx
push edx
mov ecx,0xffff
kr_loop:
in al,0x64
test al,1
jnz kr_ready
loop kr_loop
mov ah,1
jmp kr_exit
kr_ready:
mov ecx,0xffff
kr_loop2:
in al,0x64
test al,00100001b
jnz kr_ready2
mov ah,2
jmp kr_exit
kr_ready2:
push ecx
mov ecx,32
kr_delay:
loop kr_delay
pop ecx
in al,0x60
xor ah,ah
kr_exit:
pop edx
pop ecx
ret
kr_mouse:
push ecx
push edx
mov ecx,0xffff
kr_loop:
in al,0x64
test al,1
jnz kr_ready
loop kr_loop
mov ah,1
jmp kr_exit
kr_ready:
mov ecx,0xffff
kr_loop2:
in al,0x64
test al,00100001b
jnz kr_ready2
mov ah,2
jmp kr_exit
kr_ready2:
push ecx
mov ecx,32
kr_delay:
loop kr_delay
pop ecx
in al,0x60
xor ah,ah
kr_exit:
pop edx
pop ecx
ret
RE:[Need Help] My PS/2 Mouse Driver
Hi E-mean,
another possibility is that you don't wait for the mouse's responds on earlier commands correctly. The ACKs will then come in at some later point so that OBF and MOBF flag get set which might then confuse your interrrupt handler.
What is the very first byte your handler receives ?
If it's 0xFA you may try to run some empty loop right after your mouse ini-code:
while(counter < 0xfffff)
{
GetByteFrom0x60();
}
If this loop 'solves' your problem you should check the way you send commands to the mouse. The logs at the bottom of http://panda.cs.ndsu.nodak.edu/~achapwe ... mouse.html may help you.
Here's how I sent commands to the mouse:
void ps2mouse::Command(uchar command, uchar* parameters, int pNum, uchar* ret, int rNum)
{
SpinLock lock(Mutex());
uchar tmp;
// Tell the controller to send the parameters to the mouse
while(Port::ReadByte(0x64) &input_buffer);
Port::WriteByte(0x64, 0xD4);
// Send the command
while(Port::ReadByte(0x64) &input_buffer);
Port::WriteByte(0x60, command);
while((Port::ReadByte(0x64) &output_buffer + mouse_buffer) != (output_buffer + mouse_buffer));
if(Port::ReadByte(0x60) != 0xFA)
console() << "HAL::ps2keyboard::Command ACK invalid\n";
// Send parameters
for(int i = 0; i < pNum; i++)
{
while(Port::ReadByte(0x64) &input_buffer);
Port::WriteByte(0x60, parameters[i]);
while((Port::ReadByte(0x64) &output_buffer + mouse_buffer) != (output_buffer + mouse_buffer));
if(Port::ReadByte(0x60) != 0xFA)
console() << "HAL::ps2keyboard::Command ACK invalid\n";
}
// Get returned data
for(int j = 0; j < rNum; j++)
{
while(!(Port::ReadByte(0x64) &output_buffer + mouse_buffer) != (output_buffer + mouse_buffer));
ret[j] = (uchar) Port::ReadByte(0x60);
}
}
regards,
gaf
another possibility is that you don't wait for the mouse's responds on earlier commands correctly. The ACKs will then come in at some later point so that OBF and MOBF flag get set which might then confuse your interrrupt handler.
What is the very first byte your handler receives ?
If it's 0xFA you may try to run some empty loop right after your mouse ini-code:
while(counter < 0xfffff)
{
GetByteFrom0x60();
}
If this loop 'solves' your problem you should check the way you send commands to the mouse. The logs at the bottom of http://panda.cs.ndsu.nodak.edu/~achapwe ... mouse.html may help you.
Here's how I sent commands to the mouse:
void ps2mouse::Command(uchar command, uchar* parameters, int pNum, uchar* ret, int rNum)
{
SpinLock lock(Mutex());
uchar tmp;
// Tell the controller to send the parameters to the mouse
while(Port::ReadByte(0x64) &input_buffer);
Port::WriteByte(0x64, 0xD4);
// Send the command
while(Port::ReadByte(0x64) &input_buffer);
Port::WriteByte(0x60, command);
while((Port::ReadByte(0x64) &output_buffer + mouse_buffer) != (output_buffer + mouse_buffer));
if(Port::ReadByte(0x60) != 0xFA)
console() << "HAL::ps2keyboard::Command ACK invalid\n";
// Send parameters
for(int i = 0; i < pNum; i++)
{
while(Port::ReadByte(0x64) &input_buffer);
Port::WriteByte(0x60, parameters[i]);
while((Port::ReadByte(0x64) &output_buffer + mouse_buffer) != (output_buffer + mouse_buffer));
if(Port::ReadByte(0x60) != 0xFA)
console() << "HAL::ps2keyboard::Command ACK invalid\n";
}
// Get returned data
for(int j = 0; j < rNum; j++)
{
while(!(Port::ReadByte(0x64) &output_buffer + mouse_buffer) != (output_buffer + mouse_buffer));
ret[j] = (uchar) Port::ReadByte(0x60);
}
}
regards,
gaf
RE:[Need Help] My PS/2 Mouse Driver
I'm in appreciation of your warmly help,gaf.
Thax for your code,I'll try to translate it to ASM later(my os writen in ASM ,I'm a sophomore,need to do some preparations for the coming exams.
Did you mind i mail you if there is any problems in the current stage?
Sorry for my poor English.
Regards,
E-mean
Thax for your code,I'll try to translate it to ASM later(my os writen in ASM ,I'm a sophomore,need to do some preparations for the coming exams.
Did you mind i mail you if there is any problems in the current stage?
Sorry for my poor English.
Regards,
E-mean