Timer IRQ doesn't work but keyboard does? [SOLVED]

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
nyaruhodo
Posts: 1
Joined: Sun Apr 30, 2023 10:37 am

Timer IRQ doesn't work but keyboard does? [SOLVED]

Post by nyaruhodo »

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: Select all

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: Select all

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: Select all

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: Select all

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_T ... Known_Bugs to see for myself but I was unsuccesful.
Post Reply