Page 1 of 1

[SOLVED] Mouse Interrupt not firing

Posted: Thu Aug 05, 2021 10:44 am
by elrond06
Hi.

This is my first post here so I apologise in advance if I break any protocols.

I have an issue that I have spent the better part of the past three days trying to resolve. I have searched a lot on the internet and tried a lot of solutions on similar questions but still I have not resolved this issue.

The issue is as follows:
I have switched successfully to protected mode, loaded GDT and set up an IDT. The issue is that the mouse interrupt (12) never fires. The keyboard interrupt is working and I have double checked this on a real device.

The IDT is setup correctly as my mouse interrupt handler is called when I manually initiate a software interrupt (int 12). However, no matter what I do with the mouse, I do not get a hardware interrupt both on QEMU and a real pc.

This leads me to believe that the issue is with my mouse setup. Here is the code for my mouse setup:

Code: Select all

void InitialiseMouse() {
    unsigned char _status;  //unsigned char

    // Enable the auxiliary mouse device
    MouseWait(1);
    outportb(0x64, 0xA8);
    
    //Enable the interrupts
    MouseWait(1);
    outportb(0x64, 0x20);
    MouseWait(0);
    _status=(inportb(0x60) | 2);
    MouseWait(1);
    outportb(0x64, 0x60);
    MouseWait(1);
    outportb(0x60, _status);
    
    MouseWrite(0xFF);
    MouseRead(); 
    //Tell the mouse to use default settings
    MouseWrite(0xF6);
    MouseRead();  //Acknowledge
    
    //Enable the mouse
    MouseWrite(0xF4);
    MouseRead();

    init_mouse_interrupt();
}

void MouseWrite(unsigned char data) {
    MouseWait(1);
    outportb(0x64, 0xd4);

    MouseWait(1);
    outportb(0x60, data);
}

unsigned char MouseRead() {
    MouseWait(0);
    return inportb(0x60);
}

void MouseWait(unsigned char type) {
    int time_out = 100000;

    if (type == 0) {
        while (time_out--) {
            if ((inportb(0x64) & 1) == 1)
                return;
        }
        return;
    }
    else {
        while (time_out--) {
            if ((inportb(0x64) & 2) == 0)
                return;
        } 
        return;
    }
}
Can you see what is wrong with this code? Thanks in advance for your help!

Re: Mouse Interrupt not firing

Posted: Thu Aug 05, 2021 8:39 pm
by Octocontrabass
elrond06 wrote:Here is the code for my mouse setup:
That can't be all of it. Where is the code to enable mouse IRQs in the interrupt controller?

Re: Mouse Interrupt not firing

Posted: Fri Aug 06, 2021 12:06 am
by elrond06
Apologies, here is the rest of the code.

This is the code to setup the interrupts (base and base12 are pointers to function addresses for interrupt handler functions):

Code: Select all

void InitialiseIDT() {
    _idt[1].lower = (base & 0xffff);
    _idt[1].higher = (base >> 16) & 0xffff;
    _idt[1].selector = 0x08;
    _idt[1].zero = 0;
    _idt[1].flags = 0x8e;

    _idt[12].lower = (base12 & 0xffff);
    _idt[12].higher = (base12 >> 16) & 0xffff;
    _idt[12].selector = 0x08;
    _idt[12].zero = 0;
    _idt[12].flags = 0x8e;

    RemapPIC();

    outportb(0x21, 0xfd);
    outportb(0xa1, 0xff);

    LoadIDT();
}

This is the code to remap pic:

Code: Select all

#define PIC1_C 0x20
#define PIC1_D 0x21
#define PIC2_C 0xa0
#define PIC2_D 0xa1

#define ICW1_DEF 0x10
#define ICW1_ICW4 0x01
#define ICW4_x86 0x01

void RemapPIC() {
    unsigned char a, b;
    a = inportb(PIC1_D);
    b = inportb(PIC2_D);

    outportb(PIC1_C, ICW1_DEF | ICW1_ICW4);
    outportb(PIC2_C, ICW1_DEF | ICW1_ICW4);

    outportb(PIC1_D, 0);
    outportb(PIC2_D, 8);

    outportb(PIC1_D, 4);
    outportb(PIC2_D, 2);

    outportb(PIC1_D, ICW4_x86);
    outportb(PIC2_D, ICW4_x86);

    outportb(PIC1_D, a);
    outportb(PIC2_D, b);
}

And this is the assembly code:

Code: Select all

extern _idt
extern HandleISR1, HandleISR12, mouse_handler, initialise_mouse
global isr1, isr12
global LoadIDT, mouse_init

IDTDesc:
    dw 2048
    dd _idt

isr1:
    pusha
    call HandleISR1
    popa
    iret

isr12:
    jmp $
    pusha
    call HandleISR12
    popa
    iret

LoadIDT:
    lidt[IDTDesc]
    sti
    ret
Like I said if I call int 12 manually in assembly, the interrupt handler 12 function is called. Basically hardware is not generating interrupts.

Re: Mouse Interrupt not firing

Posted: Fri Aug 06, 2021 12:49 am
by elrond06
The jmp $ in the handler for isr12 assembly is deliberately to see if the code enters that function.

Re: Mouse Interrupt not firing

Posted: Fri Aug 06, 2021 8:46 am
by Octocontrabass
elrond06 wrote:

Code: Select all

    outportb(0x21, 0xfd);
    outportb(0xa1, 0xff);
IRQ2 and IRQ12 are masked. You'll never receive any mouse interrupts if you don't unmask both of those.
elrond06 wrote:

Code: Select all

    outportb(PIC1_D, 0);
    outportb(PIC2_D, 8);
Interrupt vectors 0 through 31 are reserved for CPU exceptions. You must choose different interrupt vectors. (For example, you could use 32 for the primary PIC and 40 for the secondary PIC. If you use those vectors, IRQ1 will be interrupt 33 and IRQ12 will be interrupt 44.)

Re: Mouse Interrupt not firing

Posted: Fri Aug 06, 2021 10:43 am
by elrond06
Thank you very very very much! I cannot thank you enough.

The issue is now resolved and I can confirm that mouse is working on both QEMU and real hardware.

Also is there a process to close this message? I.e. to help people in the future and let them know this issue was resolved?

Re: Mouse Interrupt not firing

Posted: Fri Aug 06, 2021 11:52 am
by nexos
You can prefix the title of the first post with [SOLVED]