1

Everyone! I just finished writing my Keyboard Driver. Right now the problem is that my PS/2 MOUSE IRQ won't fire(IRQ 12). I tested this by this code:

    #include "irq.h"

    #define PIC_MASTER_CONTROL 0x20
    #define PIC_MASTER_MASK 0x21
    #define PIC_SLAVE_CONTROL 0xa0
    #define PIC_SLAVE_MASK 0xa1


    typedef void(*regs_func)(struct regs *r);


    /*Get all irq's*/
    extern "C" void irq0(void);
    extern "C" void irq1(void);
    extern "C" void irq2(void);
    extern "C" void irq3(void);
    extern "C" void irq4(void);
    extern "C" void irq5(void);
    extern "C" void irq6(void);
    extern "C" void irq7(void);
    extern "C" void irq8(void);
    extern "C" void irq9(void);
    extern "C" void irq10(void);
    extern "C" void irq11(void);
    extern "C" void irq12(void);
    extern "C" void irq13(void);
    extern "C" void irq14(void);
    extern "C" void irq15(void);


    extern void panic(const char* exception);

    regs_func irq_routines[16] = {
        0,0,0,0,0,0,0,0
       ,0,0,0,0,0,0,0,0
    };

    static PORT::Port8Bits p8b_irq;
    static SerialPort sp_irq;

    //Basically a declaration of IDT_ENTRY in 
    //idt.c++
    struct idt_entry {
        uint16_t base_lo;
        uint16_t sel; // Kernel segment goes here.
        uint8_t always0;
        uint8_t flags; // Set using the table.
        uint16_t base_hi;
    }__attribute__((packed));

    //Get the Exact IDT array from idt.c++
    extern struct idt_entry idt[256];

    static inline void idt_set_gate(uint8_t num, void(*handler)(void), uint16_t sel,
                 uint8_t flags) 
    {
        idt[num].base_lo = (uintptr_t)handler >> 0 & 0xFFFF;
        idt[num].base_hi = (uintptr_t)handler >> 16 & 0xffff;
        idt[num].always0 = 0;
        idt[num].sel = sel;
        idt[num].flags = flags;
    }

    IRQ::IRQ(){}; 
    IRQ::~IRQ(){};

    /* Normally, IRQs 0 to 7 are mapped to entries 8 to 15. This
    *  is a problem in protected mode, because IDT entry 8 is a
    *  Double Fault! Without remapping, every time IRQ0 fires,
    *  you get a Double Fault Exception, which is NOT actually
    *  what's happening. We send commands to the Programmable
    *  Interrupt Controller (PICs - also called the 8259's) in
    *  order to make IRQ0 to 15 be remapped to IDT entries 32 to
    *  47 */
    void IRQ::irq_remap()
    {

            // ICW1 - begin initialization
        p8b_irq.out(0x11,PIC_MASTER_CONTROL);
        p8b_irq.out(0x11,PIC_SLAVE_CONTROL);

        // Remap interrupts beyond 0x20 because the first 32 are cpu exceptions
        p8b_irq.out(0x20,PIC_MASTER_MASK);
        p8b_irq.out(0x27,PIC_SLAVE_MASK);

        // ICW3 - setup cascading
        p8b_irq.out(0x04,PIC_MASTER_MASK);
        p8b_irq.out(0x02,PIC_SLAVE_MASK);

        // ICW4 - environment info
        p8b_irq.out(0x01,PIC_MASTER_MASK);
        p8b_irq.out(0x01,PIC_SLAVE_MASK);

        // mask interrupts
        p8b_irq.out(0x00,PIC_MASTER_MASK);
        p8b_irq.out(0x00,PIC_SLAVE_MASK);
    }

    void install_handler_irq(int irq, regs_func handler)
    {
        printf(" \n Installer IRQ %d \n ", irq);
       irq_routines[irq] = handler;
    }

    void uninstall_handler_irq(int irq)
    {
       irq_routines[irq] = 0;
    } 




    /* First remap the interrupt controllers, and then we install
    *  the appropriate ISRs to the correct entries in the IDT. This
    *  is just like installing the exception handlers */

    void IRQ::install_irqs()
    {
       this->irq_remap();
        idt_set_gate(32, irq0, 0x08, 0x8E);
        idt_set_gate(33, irq1, 0x08, 0x8E);
        idt_set_gate(34, irq2, 0x08, 0x8E);
        idt_set_gate(35, irq3, 0x08, 0x8E);
        idt_set_gate(36, irq4, 0x08, 0x8E);
        idt_set_gate(37, irq5, 0x08, 0x8E);
        idt_set_gate(38, irq6, 0x08, 0x8E);
        idt_set_gate(39, irq7, 0x08, 0x8E);
        idt_set_gate(40, irq8, 0x08, 0x8E);
        idt_set_gate(41, irq9, 0x08, 0x8E);
        idt_set_gate(42, irq10, 0x08, 0x8E);
        idt_set_gate(43, irq11, 0x08, 0x8E);
        idt_set_gate(44, irq12, 0x08, 0x8E);
        idt_set_gate(45, irq13, 0x08, 0x8E);
        idt_set_gate(46, irq14, 0x08, 0x8E);    
        idt_set_gate(47, irq15, 0x08, 0x8E);
    }

    /* Each of the IRQ ISRs point to this function, rather than
    *  the 'fault_handler' in 'isrs.c'. The IRQ Controllers need
    *  to be told when you are done servicing them, so you need
    *  to send them an "End of Interrupt" command (0x20). There
    *  are two 8259 chips: The first exists at 0x20, the second
    *  exists at 0xA0. If the second controller (an IRQ from 8 to
    *  15) gets an interrupt, you need to acknowledge the
    *  interrupt at BOTH controllers, otherwise, you only send
    *  an EOI command to the first controller. If you don't send
    *  an EOI, you won't raise any more IRQs */
    extern "C" void irq_handler(struct regs *r)
    {
         /* This is a blank function pointer */
        regs_func handler;

        /* Find out if we have a custom handler to run for this
        *  IRQ, and then finally, run it */
        handler = irq_routines[r->int_no];
        if (handler)
        {


    handler(r);
    }

    /* If the IDT entry that was invoked was greater than 40


 *  (meaning IRQ8 - 15), then we need to send an EOI to
    *  the slave controller */
    if (r->int_no >= 8)
    {
        p8b_irq.out(0x20,0xA0);
    }

    /* In either case, we need to send an EOI to the master
    *  interrupt controller too */
    p8b_irq.out(0x20, 0x20);
}

as you can see at the bottom, where my irq_handler is, for each irq i tell it to print the irq_number. Well i have set up my PIT So i get a 0 every second, and then since i set up my keyboard i get a 1 every time i press a key. a 4 at beggining because i enable COM1. BUT , when i move my mouse , i dont get a 12 For some reason... My Mouse Driver is just as follows:

mouse.c++:

#include "mouse.h"


typedef void(*regs_func)(struct regs *r);

extern void install_handler_irq(int irq, regs_func handler);

static PORT::Port8Bits p8b_mouse_drv;


void mouse_ps2_handler(struct regs *r)
{
  printf("IRQ 12 \n ");
}
void mouse_wait(unsigned char type)
{
  unsigned int _time_out=100000;
  if(type==0)
  {
    while(_time_out--) //Data
    {
      if((p8b_mouse_drv.in(0x64) & 1)==1)
      {
        return;
      }
    }
    return;
  }
  else
  {
    while(_time_out--) //Signal
    {
      if((p8b_mouse_drv.in(0x64) & 2)==0)
      {
        return;
      }
    }
    return;
  }
}

unsigned char mouse_read()
{
//Get response from mouse
mouse_wait(0);
return p8b_mouse_drv.in(0x60);
}


void mouse_write(unsigned char a_write)
{
//Wait to be able to send a command
mouse_wait(1);
//Tell the mouse we are sending a command
p8b_mouse_drv.out(0xD4,0x64);
//Wait for the final part
mouse_wait(1);
//Finally write
p8b_mouse_drv.out(a_write,0x60);
}

void MOUSE::install_mouse_driver()
{
   mouse_wait(1);
   p8b_mouse_drv.out(0xA8,0x64);

   mouse_wait(1);
    p8b_mouse_drv.out(0x20,0x64);

    unsigned char status_byte;
    mouse_wait(0);
    status_byte = (p8b_mouse_drv.in(0x60) | 2);


    mouse_wait(1);
    p8b_mouse_drv.out(0x60,0x64);


    mouse_wait(1);
    p8b_mouse_drv.out(status_byte,0x60);


    mouse_write(0xF6);
    mouse_read();

    mouse_write(0xF4);
    mouse_read();

    install_handler_irq(12, mouse_ps2_handler);
}

kernel.c++:

#include "types.h"
#include "gdt.h"
#include "stdio.h"
#include "serial.h"
#include "mem.h"
#include "idt.h"
#include "timer.h"
#include "isr.h"
#include "kbd.h"
#include "mouse.h"
#include "irq.h"




//Call all class constructor
//for global objects before
//calling the kernel
typedef void (*constructor)();
extern "C" constructor start_ctors;
extern "C" constructor end_ctors;
extern "C" void callConstructors()
{
    for(constructor* i = &start_ctors; i != &end_ctors; i++)
        (*i)();
}



extern "C" void kernelMain(void* multiboot_structure,uint32_t magicnumber)
{
   cls();
   gdt gt;
   IDT idt;
   ISR isr;
   IRQ irq;
   SerialPort sp;
   isr.install_isrs();
   irq.install_irqs();
    Timer timer;
    timer.install_timer();  
    KBD kbd;
    kbd.install_kbd_driver();

    MOUSE mouse;
    mouse.install_mouse_driver();
    __asm__ __volatile__ ("sti");

//  int x = 5/0;
   while(1);    
   err:
       while(1);
}

If you want to see my whole project you can go to learning repo: https://github.com/amanuel2/OS_Mirror . I want the IRQ12 to fire so i can start working on my mouse driver. Help would be appreciated.

Michael Petch
  • 46,082
  • 8
  • 107
  • 198
amanuel2
  • 4,508
  • 4
  • 36
  • 67
  • Have you enabled interrupts for the mouse via the PS2 controller configuration byte? http://wiki.osdev.org/%228042%22_PS/2_Controller#Interrupts – Michael Petch Aug 10 '16 at 15:30
  • @MichaelPetch well i tried to do it at first but that didnt work either – amanuel2 Aug 10 '16 at 16:52
  • @MichaelPetch updated to my latest Mouse.c++ but still dosent work :/ – amanuel2 Aug 10 '16 at 17:53
  • `p8b_irq.out(0x27,PIC_SLAVE_MASK);` or should that be `p8b_irq.out(0x28,PIC_SLAVE_MASK);` ? Seems the way you mapped them you have overlapped the two ranges of IRQs. – Michael Petch Aug 11 '16 at 01:19
  • That dosent help @MichaelPetch . – amanuel2 Aug 11 '16 at 01:34
  • Well I'm pretty sure that without the change from 0x27 to x28 you'll have the wrong interrupt handler called since IRQ7 and IRQ8 would be mapped to the same IVT entry and all interrupts above IRQ8 would map to the IVT entry one below what you expect. The only other thing I can suggest (on top of change above) is that you use your `mouse_read()` inside your mouse interrupt handler. If you don't do the read from port 0x60 in your mouse interrupt handle, then the next interrupt will not be sent. – Michael Petch Aug 11 '16 at 01:47
  • you want me to do a mouse_read(0x60); Inside the handler? @MichaelPetch – amanuel2 Aug 11 '16 at 01:48
  • Just anything that reads port 0x60 in the mouse interrupt handler. You can throw away the value you get as a test. I'm also assuming you have hooked Int 12 interrupt handler. – Michael Petch Aug 11 '16 at 01:49
  • @MichaelPetch the mouse_read() dosent do it... hooked the int 12 interrupt handler? you mean this? `install_handler_irq(12, mouse_ps2_handler);` – amanuel2 Aug 11 '16 at 01:51
  • Well from your code I assume you do something like `MOUSE mouse; mouse.install_mouse_driver();` which in turn does `install_handler_irq(12, mouse_ps2_handler);` . I noticed in your github code that those lines were commented out in your kernel.c++ file. – Michael Petch Aug 11 '16 at 01:53
  • 1
    @MichaelPetch Oh my god you are a genius.. Ofcourse Commenting out stuff ruins my mouse.. Thanks a lot Micheal!!!! – amanuel2 Aug 11 '16 at 01:56

0 Answers0