[SOLVED] Mouse Interrupt not firing

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
elrond06
Posts: 4
Joined: Thu Aug 05, 2021 10:36 am

[SOLVED] Mouse Interrupt not firing

Post 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!
Last edited by elrond06 on Fri Aug 06, 2021 12:25 pm, edited 1 time in total.
Octocontrabass
Member
Member
Posts: 5563
Joined: Mon Mar 25, 2013 7:01 pm

Re: Mouse Interrupt not firing

Post 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?
elrond06
Posts: 4
Joined: Thu Aug 05, 2021 10:36 am

Re: Mouse Interrupt not firing

Post 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.
elrond06
Posts: 4
Joined: Thu Aug 05, 2021 10:36 am

Re: Mouse Interrupt not firing

Post by elrond06 »

The jmp $ in the handler for isr12 assembly is deliberately to see if the code enters that function.
Octocontrabass
Member
Member
Posts: 5563
Joined: Mon Mar 25, 2013 7:01 pm

Re: Mouse Interrupt not firing

Post 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.)
elrond06
Posts: 4
Joined: Thu Aug 05, 2021 10:36 am

Re: Mouse Interrupt not firing

Post 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?
nexos
Member
Member
Posts: 1081
Joined: Tue Feb 18, 2020 3:29 pm
Libera.chat IRC: nexos

Re: Mouse Interrupt not firing

Post by nexos »

You can prefix the title of the first post with [SOLVED]
"How did you do this?"
"It's very simple — you read the protocol and write the code." - Bill Joy
Projects: NexNix | libnex | nnpkg
Post Reply