I test me operating system on 4 devices, where 3 of them have EFI and on two virtual machines: QEMU and VBox
I have two methods for loading the operating system: via EFI and via Grub2.
If I boot the operatingsystem via Grub2, the PIT does send interrupts but if I boot the operating system via EFI the interrupt is not fired.
This is how I initialise the interrupts:
Code: Select all
void initialise_interrupts(){
uint8_t oldpic1 = inportb(PIC1_DATA);
uint8_t oldpic2 = inportb(PIC2_DATA);
outportb(PIC1, 0x11);
outportb(PIC2, 0x11);
outportb(PIC1_DATA, PIC_OFFSET);
outportb(PIC2_DATA, PIC_OFFSET + 8);
outportb(PIC1_DATA, ICW1_INTERVAL4);
outportb(PIC2_DATA, ICW1_SINGLE);
outportb(PIC1_DATA, ICW1_ICW4);
outportb(PIC2_DATA, ICW1_ICW4);
outportb(PIC1_DATA, 0x0);
outportb(PIC2_DATA, 0x0);
outportb(PIC1_DATA,oldpic1);
outportb(PIC2_DATA,oldpic2);
idtr.Offset = (uintptr_t)&idt[0];
idtr.Limit = (uint16_t)sizeof(IDTDescEntry) * IDT_MAX_DESCRIPTORS - 1;
IDTDescEntry *idtentries = (IDTDescEntry*) idtr.Offset;
for(uint16_t i = 0 ; i < idtr.Limit ; i++){
setRawInterrupt(i,NakedInterruptHandler);
}
for(uint16_t i = 0 ; i < PIC_OFFSET ; i++){
setRawInterrupt(i,GeneralFault_Handler);
}
asm volatile ("lidt %0" : : "m"(idtr));
asm volatile ("sti");
}
Code: Select all
void interrupt_set_offset(IDTDescEntry* int_PageFault,uint64_t offset){
int_PageFault->offset0 = (uint16_t)(offset & 0x000000000000ffff);
int_PageFault->offset1 = (uint16_t)((offset & 0x00000000ffff0000) >> 16);
int_PageFault->offset2 = (uint32_t)((offset & 0xffffffff00000000) >> 32);
}
void setInterrupt(int offset,void *fun){
IDTDescEntry* int_PageFault = (IDTDescEntry*)(idtr.Offset + ((offset+PIC_OFFSET) * sizeof(IDTDescEntry)));
interrupt_set_offset(int_PageFault,(uint64_t)fun);
int_PageFault->type_attr = IDT_TA_InterruptGate;
int_PageFault->selector = GDT_CODE_SEGMENT;
IRQ_clear_mask(offset + PIC_OFFSET);
}
void setRawInterrupt(int offset,void *fun){
IDTDescEntry* int_PageFault = (IDTDescEntry*)(idtr.Offset + ((offset) * sizeof(IDTDescEntry)));
interrupt_set_offset(int_PageFault,(uint64_t)fun);
int_PageFault->type_attr = IDT_TA_TrapGate;
int_PageFault->selector = GDT_CODE_SEGMENT;
}
Code: Select all
void initialise_timer(){
int divisor = 1193180 / 100; /* Calculate our divisor */
outportb(0x43, 0x36); /* Set our command byte 0x36 */
outportb(0x40, divisor & 0xFF); /* Set low byte of divisor */
outportb(0x40, divisor >> 8); /* Set high byte of divisor */
setInterrupt (0, timer_int);
outportb(0xA0,0x20);
outportb(0x20,0x20);
}