No interrupts being received from PIC

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
ryukoposting
Posts: 11
Joined: Thu Nov 07, 2019 2:17 pm
Libera.chat IRC: ryukoposting

No interrupts being received from PIC

Post by ryukoposting »

I have been trying to get the PS/2 keyboard interrupt and/or the PIT interrupt to fire, but I cannot get either to work. My other interrupts work properly (I have tested GP fault, page fault, breakpoint, and divide-by-zero and all work as expected). I can also get to ring 3 and perform a system call using int $0x80.

I am following the PIC guide on the wiki, but instead of restoring whatever masks were being used originally, I set PIC1's mask to 0xF8 and PIC2's mask to 0xFF. Here's the code for that:

Code: Select all

void pic_remap(int offset1, int offset2)
{
  outb(PIC1_COMMAND, ICW1_INIT | ICW1_ICW4); // starts the initialization sequence (in cascade mode)
  waitb();
  outb(PIC2_COMMAND, ICW1_INIT | ICW1_ICW4);
  waitb();
  outb(PIC1_DATA, offset1); // ICW2: Master PIC vector offset
  waitb();
  outb(PIC2_DATA, offset2); // ICW2: Slave PIC vector offset
  waitb();
  outb(PIC1_DATA, 4); // ICW3: tell Master PIC that there is a slave PIC at IRQ2 (0000 0100)
  waitb();
  outb(PIC2_DATA, 2); // ICW3: tell Slave PIC its cascade identity (0000 0010)
  waitb();
 
  outb(PIC1_DATA, ICW4_8086);
  waitb();
  outb(PIC2_DATA, ICW4_8086);
  waitb();
  
  // enable PIT, keyboard, and PIC2 connection. all others disabled.
  outb(PIC1_DATA, 0xF8);
  outb(PIC2_DATA, 0xFF);
}
where inb and outb are implemented exactly as they are in the wiki, and waitb is just io_wait with a different name.

init_idt is where my IDT gets configured:
https://gitlab.com/ryukoposting/rios/bl ... i686/idt.c

My kernel_main is at the bottom of this file, it's a bit ugly at the moment but should be fairly easy to follow. This is where the PIT setup happens:
https://gitlab.com/ryukoposting/rios/bl ... 6/kernel.c

This is the PIC stuff:
https://gitlab.com/ryukoposting/rios/bl ... i686/pic.c

I expect exception_0x21_handler to get called when a key is pressed, and I expect exception_0x20_handler to get called when the PIT counter rolls over.

Like I said, I know the EXCEPTION_ENTRY macro is working as expected, seeing as other interrupts using it are working fine.

I am using qemu-system-i386. My understanding is that it automatically maps they keyboard and mouse to the PS/2 inputs in the emulator.
User avatar
bzt
Member
Member
Posts: 1584
Joined: Thu Oct 13, 2016 4:55 pm
Contact:

Re: No interrupts being received from PIC

Post by bzt »

I think the best is to run your code in bochs. The bochs debugger is capable of dumping IDT entires, PIC, PIT and keyboard controller registers, so that you can see what they are doing actually.

Because your exception handlers and system interrupt are working, it's safe to say you've initialized the IDT correctly. Use bochs debugger to double check your timer and keyboard IDT entries, "info idt 32" for example. Then check the PIC if IRQs are actually enabled and routed to int 32 - int 48. If so, put an "xchg bx,bx" in your interrupt handler. It could be that everything is working fine, but you don't issue EOI properly, so all interrupts are fired just once. If that's the case, bochs will stop at the first timer interrupt with a debugger prompt. Just a guess.

This is how I do it, and it's known to work. Remapping and disabling PIC IRQs by default:

Code: Select all

    movb	$0x11, %al
    outb	%al, $PIC_MASTER
    outb	%al, $PIC_SLAVE
    movb	$0x20, %al
    outb	%al, $PIC_MASTER_DATA
    movb	$0x28, %al
    outb	%al, $PIC_SLAVE_DATA
    movb	$0x4, %al
    outb	%al, $PIC_MASTER_DATA
    movb	$0x2, %al
    outb	%al, $PIC_SLAVE_DATA
    movb	$0x1, %al
    outb	%al, $PIC_MASTER_DATA
    outb	%al, $PIC_SLAVE_DATA
Then enabling one IRQ:

Code: Select all

/* void isr_enableirq(uint32_t irq) */
isr_enableirq:
    movl	%edi, %ecx
    andw	$0xF, %cx
    cmpb	$8, %cl
    jae	 1f
    inb	 $PIC_MASTER_DATA, %al
    btrw	%cx, %ax
    outb	%al, $PIC_MASTER_DATA
    ret
1:  subb	$8, %cl
    inb	 $PIC_SLAVE_DATA, %al
    btrw	%cx, %ax
    outb	%al, $PIC_SLAVE_DATA
    ret
It is better to initialize the PIC with all IRQs masked, and call isr_enable() from the corresponding driver's initialization code.

Cheers,
bzt
User avatar
iansjack
Member
Member
Posts: 4704
Joined: Sat Mar 31, 2012 3:07 am
Location: Chichester, UK

Re: No interrupts being received from PIC

Post by iansjack »

Silly question, but - you do enable interrupts somewhere in your code?
ryukoposting
Posts: 11
Joined: Thu Nov 07, 2019 2:17 pm
Libera.chat IRC: ryukoposting

Re: No interrupts being received from PIC

Post by ryukoposting »

iansjack wrote:Silly question, but - you do enable interrupts somewhere in your code?
I set up the IDT and GDT, and I clear the mask bits for IRQs 0-2 (0x20-0x22 when remapped). My other interrupts work fine (syscall, divide-by-zero, page fault, and all those). Is there another step of "enabling" I need to do for IRQs?
bzt wrote:...
Thanks! I didn't know much about Bochs, besides it being "like QEMU, but not." I'll check it out.

On the masking/EOI stuff: I'm using the exact same EOI-sending code that's shown on the wiki. I'll try leaving everything masked, then unmask them one at a time to see if things work better.

Edit: quick update, I have checked the IRR and ISR values and it looks like no requests are being made, and no requests are being serviced, at least not immediately. I can also see that I am able to set and unset masks, then read the changes back from the PIC correctly. Have not tried Bochs yet since I'm going to need to create a proper img file for it.
Last edited by ryukoposting on Wed Nov 20, 2019 10:55 am, edited 1 time in total.
User avatar
iansjack
Member
Member
Posts: 4704
Joined: Sat Mar 31, 2012 3:07 am
Location: Chichester, UK

Re: No interrupts being received from PIC

Post by iansjack »

Don't confuse exceptions, software interrupts, and hardware interrupts.

Somewhere, after you have set up the PIC and created the IDT, you need a "sti" instruction to enable hardware interrupts.
ryukoposting
Posts: 11
Joined: Thu Nov 07, 2019 2:17 pm
Libera.chat IRC: ryukoposting

Re: No interrupts being received from PIC

Post by ryukoposting »

iansjack wrote:Don't confuse exceptions, software interrupts, and hardware interrupts.

Somewhere, after you have set up the PIC and created the IDT, you need a "sti" instruction to enable hardware interrupts.
Whoops, that fixed it. The PIT fires repeatedly, but the keyboard ISR is only firing on the first keypress (I am sending EOI in both interrupts). I haven't added any code yet for reading they keycodes, though, so I can only assume that's the problem.
Octocontrabass
Member
Member
Posts: 5580
Joined: Mon Mar 25, 2013 7:01 pm

Re: No interrupts being received from PIC

Post by Octocontrabass »

You're correct: the keyboard controller can't raise any more IRQs until you read the byte in its buffer.
User avatar
bzt
Member
Member
Posts: 1584
Joined: Thu Oct 13, 2016 4:55 pm
Contact:

Re: No interrupts being received from PIC

Post by bzt »

Hi,

Well done! Congrats you got the IRQs working!
ryukoposting wrote:Have not tried Bochs yet since I'm going to need to create a proper img file for it.
You don't need a special image. I boot exactly the same image in both bochs and qemu. In the boch.rc, I have (Note that I do not use CHS, so those values are just ad-hoc.):

Code: Select all

ata0-master: type=disk, path="bin/disk.dd", mode=flat, cylinders=2, heads=16, spt=63, model="Generic 1234", biosdetect=auto, translation=auto
and with qemu:

Code: Select all

qemu-system-x86_64 -drive file=bin/disk.dd,format=raw
My disk image is just a disk dump of sectors, something that you can write to an USB-stick with the "dd" utility as-is. Just a side note, with qemu "-hda bin/disk.dd" works too, but gives warnings about geometry not specified, hence the "-drive format=raw".

Cheers,
bzt
Post Reply