Please consider the following code:
Code: Select all
#include "ps2mouse.h"
#include "idt.h"
#include "gdt.h"
void PS2Mouse_Handler(void)
{
// Print out what the auxiliary device (mouse) sent us, in decimal form.
printf(inportb(0x60));
// Signal EOI.
outportb(0x20, 0x20);
}
void PS2_Write(unsigned short int port, unsigned char value)
{
unsigned long int timeout;
for(timeout = 0; timeout < 500000L; timeout++)
{
// Is the PS/2 input buffer empty?
if((inportb(0x64) & 0x02) == 0)
{
// Yes, write the byte then break out of loop.
outportb(port, value);
break;
}
}
}
unsigned char PS2_Read()
{
unsigned long int timeout;
unsigned char status, data;
for(timeout = 0; timeout < 50000L; timeout++)
{
// Read status from status register.
status = inportb(0x64);
// Loop until PS/2 output buffer is full.
if((status & 0x01) != 0)
{
// Read data from output buffer.
data = inportb(0x60);
// Return data read from output buffer if
// there's no parity error; otherwise,
// continue to loop.
if((status & 0xC0) == 0)
{
// Return data.
return data;
}
}
}
return 0;
}
signed char Init_PS2Mouse(void)
{
// Disable interrupts while we initialize the mouse.
asm("cli");
// Reset PS/2 auxiliary device.
PS2_Write(0x64, 0xD4);
PS2_Write(0x60, 0xFF);
printf(PS2_Read());
printf(PS2_Read());
printf(PS2_Read());
// Set the PS/2 auxiliary IBF interrupt bit
// in the Command Byte so that we get an interrupt
// when the mouse has information for us.
PS2_Write(0x64, 0x60);
PS2_Write(0x60, 0x02);
// Enable data reporting.
PS2_Write(0x64, 0xD4);
PS2_Write(0x60, 0xF4);
printf(PS2_Read());
// Program the PS/2 auxiliary ISR.
Set_Vector(PS2Mouse_ISR, 44, D_PRESENT + D_INT + D_DPL3);
// Enable the PS/2 auxiliary IRQ.
Enable_IRQ(12);
// Re-enable interrupts.
asm("sti");
return 0;
}
After racking my brain trying to understand the PS/2 protocol, I managed to write this source code. It's based off of my perfectly-functioning keyboard code, so the problem shouldn't be in the basic interrupt code routines (Set_Vector, Enable_IRQ, etc.).
Now, the problem is very simple but it's driving me mad. When Init_PS2Mouse() is called by the kernel, everything goes absolutely fine. It communicates with the mouse marvelously. In case you'd like to know, the verbatim output from the function is as follows:
If you notice the printf()'s, you'll find this is exactly what should be printed (based on the various PS/2 technical docs circulating the Web).2501700250
Once this is printed, I test the code out by clicking the left mouse button. Considering the mouse handler I set up, everything works fine when a '9' is printed to the screen. The problem is that's the last I hear from our friend, the mouse.
If you've messed around with the keyboard, you know it will only continue to fire IRQ1's when you read from port 0x60 each time. If you don't read from port 0x60 each time, it blocks future IRQs from happening. This is basically what it seems is happening in this case; what's driving me mad is the fact that I am reading from port 0x60 each time an IRQ12 fires!!
Does ANYONE see ANYTHING that would have ANYTHING to do with this code not working as intended? If so, I should owe you immense gratitude.
P.S. Sorry the message is so long!