OSDev.org
https://forum.osdev.org/

Timer IRQ doesn't work but keyboard does? [SOLVED]
https://forum.osdev.org/viewtopic.php?f=1&t=56832
Page 1 of 1

Author:  nyaruhodo [ Sun Apr 30, 2023 11:01 am ]
Post subject:  Timer IRQ doesn't work but keyboard does? [SOLVED]

EDIT: solved, i messed up the registers struct, entirely forgetting ebx


I've been trying to get IRQs working following this https://github.com/cfenollosa/os-tutorial (based on James Molloy) and I've encountered some strange errors. I got the IDT set up and remapped PIC to spaces 32-47, and i also have an assembly routine which handles IRQ and ISR requests. Im using a pointer to a struct to represent the register state as the tutorial suggests.

Code:
irq_common_stub:
   pusha

   mov ax,ds
   push eax

   mov ax,0x10
   mov ds,ax
   mov es,ax
   mov fs,ax
   mov gs,ax

   push esp
   cld

   call irq_handler
   pop ebx
   pop ebx
   mov ds,bx
   mov es,bx
   mov fs,bx
   mov gs,bx
   popa
   add esp, 8
   iret

; ......
irq0:   
   push byte 0
   push byte 32
   jmp irq_common_stub
; etc ...



And a similar thing for ISRs and for irq/isr codes. And the actual handler is as follows:
Code:
extern "C" void irq_handler(registers_t *r){
   // send end of interrupt to pics after each interrupt
   // or they wont send another one
   //kprint("recevied irq\n");
   if(r->int_no > 33){
      kprint("error: ");
      char st[3];
      int_to_ascii(r->int_no,st);
      kprint(st);
      kprint("\n");
      return;
   }

   if(r->int_no >= 40) port_byte_out(0xA0, 0x20); //slave
   port_byte_out(0x20,0x20); //master

   if(interrupt_handlers[r->int_no] != 0){
      isr_t handler = interrupt_handlers[r->int_no];
      handler(r);
   }
}


Currently I just have it print an error if it attempts to access anything beside keyboard or timer. If I initialize the keyboard like this:

Code:
void init_keyboard(){
   register_interrupt_handler(IRQ1, keyboard_callback);
}


Where IRQ1 is just "#define IRQ1 33", and then the appropriate function. This works flawlessly. But if I try to do a similar thing for the timer:

Code:
void init_timer(uint32_t freq){
   //register handler
   register_interrupt_handler(IRQ0, timer_callback);

   //get the PIT value, hardware clock is 1193180 Hz
   uint32_t divisor = 1193180 / freq;
   uint8_t low = (uint8_t) (divisor & 0xFF);
   uint8_t high = (uint8_t)( (divisor >> 8) & 0xFF);
   //send the command
   port_byte_out(0x43, 0x36);
   port_byte_out(0x40,low);
   port_byte_out(0x40,high);

   //port_byte_out(0x20,0x20);
}


I get "error 93" printed to the window, which I tried looking up, but it seems like a garbage value to me. If I uncommented the last line in "init_timer", essentially sending EOI twice, I still get the same error but immediately afterwards the PIT starts working (I set up a print utility which prints each new tick). However this workaround breaks if I enable both the keyboard and timer, giving the same error code, the keyboard works fine.
The tutorial I'm following is aware of the "irq_common_stub" problem in Molloy's code and tries to fix it, but I can't tell if it's successful in doing that. I read https://wiki.osdev.org/James_Molloy's_Tutorial_Known_Bugs to see for myself but I was unsuccesful.

Page 1 of 1 All times are UTC - 6 hours
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
http://www.phpbb.com/