I've mapped my IRQs to 0x20 using PIC. Then I set up an interrupt for IRQ(0) timer and also set up counter0 of PIT (+pit command word). When I run my OS, messages before and after interrupt setting are printed, but there is no IRQ0 handler message.
Because of this I decided to test if my IDT is correct by causing division by zero error. Division by zero exception works. Then I tried to print ISR and IRR of pit. In ISR output I can see that IRQ0 is acknowledged but it hasn't received EOI. Therefore I tried to debug handler, but I can see no handler call when debugging. I also tried to call interrupt manually (int 0x20) and it works. It works until it comes to iret instruction - when iret is executed, VM jumps to 0xfffffff0 (reboots?). And here the problem probably is. I found that SP(before_call) - SP(in_handler) = 4. Shouldn't it be 8 or 10 bytes? How can EFLAGS and EIP fit in four bytes?
So questions I have: is it only problem of manual interrupt (using int), or it's problem of my handler (it has Interrupt Trap Gate 32(0xE) flag set)?
Does anybody have any idea why the timer sets IRQ, but my interrupt is not called?
I'm posting here part of my PIT code:
Code: Select all
void pit_default_handler();
unsigned long long int _default_pit_ticks = 0;
void pit_init() {
idt_register(IRQ0, (void*)&pit_default_handler, INTFLAG_MINRING_0+INTFLAG_TYPE_INTGATE32);
pit_setcounter(0, 1000, PIT_MODE_RATEGEN+PIT_BINARY);
}
void pit_setcounter(unsigned char counter, unsigned int hzFreq, unsigned char flags) {
unsigned short port = 0;
if(counter > 2)
return;
hzFreq = 1193181 / hzFreq;
if(counter==0)
port = PIT_REG_COUNT0;
else if(counter==1)
port = PIT_REG_COUNT1;
else port = PIT_REG_COUNT2;
//writing OCW to 0x43
outb(PIT_REG_CONTROL, flags | (counter << 6) | PIT_LOAD_LSBMSB);
//writing COUNT to port
outb(port, (unsigned char)hzFreq);
outb(port, (unsigned char)(hzFreq >> 8));
}
void __declspec(naked) pit_default_handler() {
cli();
_default_pit_ticks++;
if(_default_pit_ticks == 1000) {
println("Second...");
_default_pit_ticks = 0;
}
sti();
hw_eoi(0);
iret();
}