PS/2 Mouse

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
HBPHiL

PS/2 Mouse

Post by HBPHiL »

I've looked at every post on this message board concerning programming the PS/2 mouse; they are what got me started, but I'm having trouble and no other threads seem to help me.

Please consider this:

---CODE START---
#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.
Put_Number(Read_Byte(0x60));

// Signal EOI.
Write_Byte(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((Read_Byte(0x64) & 0x02) == 0)
{
// Yes, write the byte then break out of loop.
Write_Byte(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 = Read_Byte(0x64);

// Loop until PS/2 output buffer is full.
if((status & 0x01) != 0)
{
// Read data from output buffer.
data = Read_Byte(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)
{
asm("cli");

// Send reset command.
PS2_Write(0x64, 0xD4);
PS2_Write(0x60, 0xFF);
Put_Number(PS2_Read());
Put_Number(PS2_Read());
Put_Number(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);
Put_Number(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);

// Enable interrupts.
asm("sti");

return 0;
}
---CODE END---

Put_Number() simply takes in a number as a parameter and prints it to the screen.
Read_Byte() is my equivalent of the inportb() routine.
Write_Byte() is my equivalent of the outportb() routine.

Anyway, when I run Init_PS2Mouse() in my kernel, it sets up and communicates with the mouse marvelously. It prints this to the screen:

250 // ACK
170 // BAT passed
0 // Device ID
250 // ACK

So far so good. Then when I click my left mouse button it prints a 9 to the screen. Marvelous! However if I click again or move the mouse, it no longer calls the interrupt handler. (It behaves almost exactly like a keyboard does when you don't read port 0x60 after each interrupt: future interrupts are no longer generated. The only difference here is that I *am* reading from port 0x60 after each interrupt!!)

I've been hacking at this for two days, and my brain is fried. Does anyone have any suggestions at all?

PS. Sorry it's so long. :)
HBPHiL

RE:PS/2 Mouse FIXED IT

Post by HBPHiL »

Over at the Mega Tokyo forums, Code Slasher pointed out to me that I was missing this line of code in the interrupt handler:

Write_Byte(0xA0, 0x20);

to signal an EOI to the *slave* PIC, not the master.
Post Reply