OSDev.org

The Place to Start for Operating System Developers
It is currently Thu Apr 18, 2024 10:07 pm

All times are UTC - 6 hours




Post new topic Reply to topic  [ 24 posts ]  Go to page 1, 2  Next
Author Message
 Post subject: Cannot get keyboard interrupt handler working
PostPosted: Mon Mar 04, 2019 8:27 am 
Offline

Joined: Tue Jan 08, 2019 7:20 am
Posts: 20
Hello everyone! I succeeded into adding interrupts to my kernel but the interrupts are not working (followed the interrupts tutorial on the wiki).
My interrupt handling:
Code:
void irq1_handler(void) {
        // TODO: Add a keyboard handler right here
        register int i;
        int keycode;

        printf("key pressed/released\n");

        keycode = inb(0x60);

        i = inb(0x61);
        outb(0x61, i|0x80);
        outb(0x61, i);

        send_eoi(i);
}

send_eoi:
Code:
void send_eoi(int irq)
{
   if (irq > 7)
      outb(0xA0, 0x20);
   outb(0x20, 0x20);
}


What's wrong?

_________________
Hello world!


Top
 Profile  
 
 Post subject: Re: Cannot get keyboard interrupt handler working
PostPosted: Mon Mar 04, 2019 8:42 am 
Offline
Member
Member

Joined: Sat Mar 10, 2018 10:16 am
Posts: 296
Hello!
Code:
        i = inb(0x61);
        outb(0x61, i|0x80);
        outb(0x61, i);

        send_eoi(i);


You should detele this and replace it with EOI (as in interrupt tutorial):
Code:
//EOI
outb(0x20, 0x20);


Sending EOI by reading port 0x61 is wrong because it is port of PC SPEAKER.

_________________
https://github.com/VendelinSlezak/BleskOS


Top
 Profile  
 
 Post subject: Re: Cannot get keyboard interrupt handler working
PostPosted: Mon Mar 04, 2019 8:47 am 
Offline

Joined: Tue Jan 08, 2019 7:20 am
Posts: 20
Klakap wrote:
Hello!
Code:
        i = inb(0x61);
        outb(0x61, i|0x80);
        outb(0x61, i);

        send_eoi(i);


You should detele this and replace it with EOI (as in interrupt tutorial):
Code:
//EOI
outb(0x20, 0x20);


Sending EOI by reading port 0x61 is wrong because it is port of PC SPEAKER.

For some reason it still doesn't work...

_________________
Hello world!


Top
 Profile  
 
 Post subject: Re: Cannot get keyboard interrupt handler working
PostPosted: Mon Mar 04, 2019 8:54 am 
Offline
Member
Member

Joined: Sat Mar 10, 2018 10:16 am
Posts: 296
Hm. How you are set IDT for irq1(post code)? And how are you write assemblers methods? Is any other irq work? Try handle irq0, it is timer irq and it is firing forever. If it isnt fire, you make something wrong with setting interrupts.

_________________
https://github.com/VendelinSlezak/BleskOS


Top
 Profile  
 
 Post subject: Re: Cannot get keyboard interrupt handler working
PostPosted: Mon Mar 04, 2019 8:57 am 
Offline

Joined: Tue Jan 08, 2019 7:20 am
Posts: 20
Klakap wrote:
Hm. How you are set IDT for irq1(post code)? And how are you write assemblers methods? Is any other irq work? Try handle irq0, it is timer irq and it is firing forever. If it isnt fire, you make something wrong with setting interrupts.


It doesn't spam me at all...
Here is my kernel.c:

Code:
#include <stdio.h>
#include <stdbool.h>
#include <interrupts.h>
#include <ioaccess.h>
#include <pic.h>

#include <kernel/tty.h>

#define PIC_MASTER_COMMAND 0x20
#define PIC_MASTER_DATA 0x21
#define PIC_MASTER_IMR 0x21
#define PIC_SLAVE_COMMAND 0xA0
#define PIC_SLAVE_DATA 0xA1
#define PIC_SLAVE_IMR 0xA1

#define EOI 0x20

void pic_remap(int interrupt_num) {
   char buffer[20];
   itoa(interrupt_num, buffer, 10);
   printf ("Interrupt number: %s\n", buffer);
   
   outb (PIC_MASTER_COMMAND, 0x11);
   outb (PIC_SLAVE_COMMAND, 0x11);
   
   outb (PIC_MASTER_DATA, interrupt_num);
   outb (PIC_SLAVE_DATA, interrupt_num + 8);
   
   outb (PIC_MASTER_DATA, 0x04);
   outb (PIC_SLAVE_DATA, 2);
   
   outb (PIC_MASTER_DATA, 0x01);
   outb (PIC_SLAVE_DATA, 0x01);
}

void pic_masc_irqs (uint16_t mask) {
   outb (PIC_MASTER_IMR, (uint8_t) mask);
   outb (PIC_SLAVE_IMR, (uint8_t) (mask >> 8));
}

void pic_send_eoi (int irq_num) {
   outb (PIC_MASTER_COMMAND, EOI);
   if (irq_num > 7) { // If the IRQs are over 7 years old, we must send an EOI both to the master and slave
      outb (PIC_SLAVE_COMMAND, EOI);
   }
}

// IDT Table

struct IDT_entry{
   unsigned short int offset_lowerbits;
   unsigned short int selector;
   unsigned char zero;
   unsigned char type_attr;
   unsigned short int offset_higherbits;
};

struct IDT_entry IDT[286];

// Im too lazy so stfu

void idt_init(void) {
        extern int load_idt();
        extern int irq0();
        extern int irq1();
        extern int irq2();
        extern int irq3();
        extern int irq4();
        extern int irq5();
        extern int irq6();
        extern int irq7();
        extern int irq8();
        extern int irq9();
        extern int irq10();
        extern int irq11();
        extern int irq12();
        extern int irq13();
        extern int irq14();
        extern int irq15();

   unsigned long irq0_address;
        unsigned long irq1_address;
        unsigned long irq2_address;
        unsigned long irq3_address;
        unsigned long irq4_address;
        unsigned long irq5_address;
        unsigned long irq6_address;
        unsigned long irq7_address;
        unsigned long irq8_address;
        unsigned long irq9_address;
        unsigned long irq10_address;
        unsigned long irq11_address;
        unsigned long irq12_address;
        unsigned long irq13_address;
        unsigned long irq14_address;
        unsigned long irq15_address;
   unsigned long idt_address;
   unsigned long idt_ptr[2];

        /* remapping the PIC */
   outb(0x20, 0x11);
        outb(0xA0, 0x11);
        outb(0x21, 0x20);
        outb(0xA1, 40);
        outb(0x21, 0x04);
        outb(0xA1, 0x02);
        outb(0x21, 0x01);
        outb(0xA1, 0x01);
        outb(0x21, 0x0);
        outb(0xA1, 0x0);

   irq0_address = (unsigned long)irq0;
   IDT[32].offset_lowerbits = irq0_address & 0xffff;
   IDT[32].selector = 0x08; /* KERNEL_CODE_SEGMENT_OFFSET */
   IDT[32].zero = 0;
   IDT[32].type_attr = 0x8e; /* INTERRUPT_GATE */
   IDT[32].offset_higherbits = (irq0_address & 0xffff0000) >> 16;

   irq1_address = (unsigned long)irq1;
   IDT[33].offset_lowerbits = irq1_address & 0xffff;
   IDT[33].selector = 0x08; /* KERNEL_CODE_SEGMENT_OFFSET */
   IDT[33].zero = 0;
   IDT[33].type_attr = 0x8e; /* INTERRUPT_GATE */
   IDT[33].offset_higherbits = (irq1_address & 0xffff0000) >> 16;

   irq2_address = (unsigned long)irq2;
   IDT[34].offset_lowerbits = irq2_address & 0xffff;
   IDT[34].selector = 0x08; /* KERNEL_CODE_SEGMENT_OFFSET */
   IDT[34].zero = 0;
   IDT[34].type_attr = 0x8e; /* INTERRUPT_GATE */
   IDT[34].offset_higherbits = (irq2_address & 0xffff0000) >> 16;

   irq3_address = (unsigned long)irq3;
   IDT[35].offset_lowerbits = irq3_address & 0xffff;
   IDT[35].selector = 0x08; /* KERNEL_CODE_SEGMENT_OFFSET */
   IDT[35].zero = 0;
   IDT[35].type_attr = 0x8e; /* INTERRUPT_GATE */
   IDT[35].offset_higherbits = (irq3_address & 0xffff0000) >> 16;

   irq4_address = (unsigned long)irq4;
   IDT[36].offset_lowerbits = irq4_address & 0xffff;
   IDT[36].selector = 0x08; /* KERNEL_CODE_SEGMENT_OFFSET */
   IDT[36].zero = 0;
   IDT[36].type_attr = 0x8e; /* INTERRUPT_GATE */
   IDT[36].offset_higherbits = (irq4_address & 0xffff0000) >> 16;

   irq5_address = (unsigned long)irq5;
   IDT[37].offset_lowerbits = irq5_address & 0xffff;
   IDT[37].selector = 0x08; /* KERNEL_CODE_SEGMENT_OFFSET */
   IDT[37].zero = 0;
   IDT[37].type_attr = 0x8e; /* INTERRUPT_GATE */
   IDT[37].offset_higherbits = (irq5_address & 0xffff0000) >> 16;

   irq6_address = (unsigned long)irq6;
   IDT[38].offset_lowerbits = irq6_address & 0xffff;
   IDT[38].selector = 0x08; /* KERNEL_CODE_SEGMENT_OFFSET */
   IDT[38].zero = 0;
   IDT[38].type_attr = 0x8e; /* INTERRUPT_GATE */
   IDT[38].offset_higherbits = (irq6_address & 0xffff0000) >> 16;

   irq7_address = (unsigned long)irq7;
   IDT[39].offset_lowerbits = irq7_address & 0xffff;
   IDT[39].selector = 0x08; /* KERNEL_CODE_SEGMENT_OFFSET */
   IDT[39].zero = 0;
   IDT[39].type_attr = 0x8e; /* INTERRUPT_GATE */
   IDT[39].offset_higherbits = (irq7_address & 0xffff0000) >> 16;

   irq8_address = (unsigned long)irq8;
   IDT[40].offset_lowerbits = irq8_address & 0xffff;
   IDT[40].selector = 0x08; /* KERNEL_CODE_SEGMENT_OFFSET */
   IDT[40].zero = 0;
   IDT[40].type_attr = 0x8e; /* INTERRUPT_GATE */
   IDT[40].offset_higherbits = (irq8_address & 0xffff0000) >> 16;

   irq9_address = (unsigned long)irq9;
   IDT[41].offset_lowerbits = irq9_address & 0xffff;
   IDT[41].selector = 0x08; /* KERNEL_CODE_SEGMENT_OFFSET */
   IDT[41].zero = 0;
   IDT[41].type_attr = 0x8e; /* INTERRUPT_GATE */
   IDT[41].offset_higherbits = (irq9_address & 0xffff0000) >> 16;

   irq10_address = (unsigned long)irq10;
   IDT[42].offset_lowerbits = irq10_address & 0xffff;
   IDT[42].selector = 0x08; /* KERNEL_CODE_SEGMENT_OFFSET */
   IDT[42].zero = 0;
   IDT[42].type_attr = 0x8e; /* INTERRUPT_GATE */
   IDT[42].offset_higherbits = (irq10_address & 0xffff0000) >> 16;

   irq11_address = (unsigned long)irq11;
   IDT[43].offset_lowerbits = irq11_address & 0xffff;
   IDT[43].selector = 0x08; /* KERNEL_CODE_SEGMENT_OFFSET */
   IDT[43].zero = 0;
   IDT[43].type_attr = 0x8e; /* INTERRUPT_GATE */
   IDT[43].offset_higherbits = (irq11_address & 0xffff0000) >> 16;

   irq12_address = (unsigned long)irq12;
   IDT[44].offset_lowerbits = irq12_address & 0xffff;
   IDT[44].selector = 0x08; /* KERNEL_CODE_SEGMENT_OFFSET */
   IDT[44].zero = 0;
   IDT[44].type_attr = 0x8e; /* INTERRUPT_GATE */
   IDT[44].offset_higherbits = (irq12_address & 0xffff0000) >> 16;

   irq13_address = (unsigned long)irq13;
   IDT[45].offset_lowerbits = irq13_address & 0xffff;
   IDT[45].selector = 0x08; /* KERNEL_CODE_SEGMENT_OFFSET */
   IDT[45].zero = 0;
   IDT[45].type_attr = 0x8e; /* INTERRUPT_GATE */
   IDT[45].offset_higherbits = (irq13_address & 0xffff0000) >> 16;

   irq14_address = (unsigned long)irq14;
   IDT[46].offset_lowerbits = irq14_address & 0xffff;
   IDT[46].selector = 0x08; /* KERNEL_CODE_SEGMENT_OFFSET */
   IDT[46].zero = 0;
   IDT[46].type_attr = 0x8e; /* INTERRUPT_GATE */
   IDT[46].offset_higherbits = (irq14_address & 0xffff0000) >> 16;

        irq15_address = (unsigned long)irq15;
   IDT[47].offset_lowerbits = irq15_address & 0xffff;
   IDT[47].selector = 0x08; /* KERNEL_CODE_SEGMENT_OFFSET */
   IDT[47].zero = 0;
   IDT[47].type_attr = 0x8e; /* INTERRUPT_GATE */
   IDT[47].offset_higherbits = (irq15_address & 0xffff0000) >> 16;

   /* fill the IDT descriptor */
   idt_address = (unsigned long)IDT ;
   idt_ptr[0] = (sizeof (struct IDT_entry) * 286) + ((idt_address & 0xffff) << 16);
   idt_ptr[1] = idt_address >> 16 ;

   load_idt(idt_ptr);
}

void kernel_main(void) {
   terminal_initialize();
   
   // outb('a', 0xE9);
   
   puts("Kernel joined the game.");
   
   // puts("Remapping PIC: IRQ=1 (Keyboard interrupt)");
   
   // pic_remap(1);
   
   puts("Remaping the PIC and initializing idt");
   
   idt_init();
   
   puts ("Checking if interrupts are enabled.");
   
   bool a = are_interrupts_enabled();
   
   if (a == true) {
      puts("Interrups are enabled");
   } else {
      puts("Interrupts are disabled");
   }
   
   puts ("Nothing left to do. The kernel is now sleeping.");
}

_________________
Hello world!


Top
 Profile  
 
 Post subject: Re: Cannot get keyboard interrupt handler working
PostPosted: Mon Mar 04, 2019 9:05 am 
Offline
Member
Member

Joined: Sat Mar 10, 2018 10:16 am
Posts: 296
You use method load_idt(). This method *must* be write in assembler, no in C. If you haven`t it, I think that it is error.

_________________
https://github.com/VendelinSlezak/BleskOS


Top
 Profile  
 
 Post subject: Re: Cannot get keyboard interrupt handler working
PostPosted: Mon Mar 04, 2019 10:15 am 
Offline

Joined: Tue Jan 08, 2019 7:20 am
Posts: 20
Klakap wrote:
You use method load_idt(). This method *must* be write in assembler, no in C. If you haven`t it, I think that it is error.

Why so? Interrupts are enabled properly.

https://imgur.com/a/MJ7jYpl

_________________
Hello world!


Top
 Profile  
 
 Post subject: Re: Cannot get keyboard interrupt handler working
PostPosted: Mon Mar 04, 2019 10:24 am 
Offline
Member
Member

Joined: Sat Mar 10, 2018 10:16 am
Posts: 296
How is your load_idt() method look? It should be:
Code:
load_idt:
   mov edx, [esp + 4]    ;get IDT adress
   lidt [edx]    ;load IDT
   sti    ;enable interrupts
   ret    ;return


in assembler. No in C. I don`t now how your OS detecting whether is interrupts set, but load_idt() should look as I post.

_________________
https://github.com/VendelinSlezak/BleskOS


Top
 Profile  
 
 Post subject: Re: Cannot get keyboard interrupt handler working
PostPosted: Mon Mar 04, 2019 10:31 am 
Offline

Joined: Tue Jan 08, 2019 7:20 am
Posts: 20
Klakap wrote:
How is your load_idt() method look? It should be:
Code:
load_idt:
   mov edx, [esp + 4]    ;get IDT adress
   lidt [edx]    ;load IDT
   sti    ;enable interrupts
   ret    ;return


in assembler. No in C. I don`t now how your OS detecting whether is interrupts set, but load_idt() should look as I post.


You can look at the project on github

_________________
Hello world!


Top
 Profile  
 
 Post subject: Re: Cannot get keyboard interrupt handler working
PostPosted: Mon Mar 04, 2019 10:35 am 
Offline
Member
Member

Joined: Sat Mar 10, 2018 10:16 am
Posts: 296
Please in which file is load_idt()? I cant found it.

_________________
https://github.com/VendelinSlezak/BleskOS


Top
 Profile  
 
 Post subject: Re: Cannot get keyboard interrupt handler working
PostPosted: Mon Mar 04, 2019 10:37 am 
Offline

Joined: Tue Jan 08, 2019 7:20 am
Posts: 20
Klakap wrote:
Please in which file is load_idt()? I cant found it.

https://github.com/xslendix/RaduOS/blob ... i386/irq.S

_________________
Hello world!


Top
 Profile  
 
 Post subject: Re: Cannot get keyboard interrupt handler working
PostPosted: Mon Mar 04, 2019 10:54 am 
Offline
Member
Member

Joined: Sat Mar 10, 2018 10:16 am
Posts: 296
Thank you.
See my comments:

_start:
movl $stack_top, %esp

;For get interrupts work in GRUB, you must load GDT. I recommended make it here. Look at interrupts tutorial in to part Interrupts in GRUB

# Call the global constructors.
call _init

# Transfer control to the main kernel.
call kernel_main

# Hang if kernel_main unexpectedly returns.
cli ;HERE IS PROBLEM This is disable interrupts!!! Delete it.
1: hlt ;You can`t use hlt if you are use interrupts. replace this with jmp $
jmp 1b

_________________
https://github.com/VendelinSlezak/BleskOS


Top
 Profile  
 
 Post subject: Re: Cannot get keyboard interrupt handler working
PostPosted: Mon Mar 04, 2019 11:33 am 
Offline
Member
Member

Joined: Wed Aug 30, 2017 8:24 am
Posts: 1604
Klakap wrote:
# Hang if kernel_main unexpectedly returns.
cli ;HERE IS PROBLEM This is disable interrupts!!! Delete it.
1: hlt ;You can`t use hlt if you are use interrupts. replace this with jmp $
jmp 1b


Erm, no, this is the stuff after the kernel_main. That is, this is code that only runs if kernel_main returned, which it shouldn't.

Oh, so there's the problem. kernel_main() does return. And then you CLI and then you wait for interrupts. No wonder it isn't working. You either need an infinite loop in kernel_main() or you need to loose the CLI.

However, Klakap, hlt is perfectly usable with interrupts. It will disable the CPU until the next interrupt comes in. Just the CLI before that prevents the CPU from recognizing the interrupt.

_________________
Carpe diem!


Top
 Profile  
 
 Post subject: Re: Cannot get keyboard interrupt handler working
PostPosted: Mon Mar 04, 2019 11:43 am 
Offline
Member
Member

Joined: Sat Mar 10, 2018 10:16 am
Posts: 296
nullplan wrote:
However, Klakap, hlt is perfectly usable with interrupts. It will disable the CPU until the next interrupt comes in. Just the CLI before that prevents the CPU from recognizing the interrupt.


Yes? I have problem with hlt beacuse if I use it, after get irq, system was reboot. But I am agree, kernel_main() is return and it causes error.

_________________
https://github.com/VendelinSlezak/BleskOS


Top
 Profile  
 
 Post subject: Re: Cannot get keyboard interrupt handler working
PostPosted: Mon Mar 04, 2019 11:54 am 
Offline

Joined: Tue Jan 08, 2019 7:20 am
Posts: 20
nullplan wrote:
Klakap wrote:
# Hang if kernel_main unexpectedly returns.
cli ;HERE IS PROBLEM This is disable interrupts!!! Delete it.
1: hlt ;You can`t use hlt if you are use interrupts. replace this with jmp $
jmp 1b


Erm, no, this is the stuff after the kernel_main. That is, this is code that only runs if kernel_main returned, which it shouldn't.

Oh, so there's the problem. kernel_main() does return. And then you CLI and then you wait for interrupts. No wonder it isn't working. You either need an infinite loop in kernel_main() or you need to loose the CLI.

However, Klakap, hlt is perfectly usable with interrupts. It will disable the CPU until the next interrupt comes in. Just the CLI before that prevents the CPU from recognizing the interrupt.


When I put a loop in kernel_main() i get exited from my OS back to GRUB, same thing when i remove the cli

_________________
Hello world!


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 24 posts ]  Go to page 1, 2  Next

All times are UTC - 6 hours


Who is online

Users browsing this forum: Google [Bot] and 101 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group