I'm currently attempting some sort of microkernel-ish design, and the current situation puts me with a PS/2 driver in userspace. The way things are set up, the "control flow" is like this:
Code: Select all
irq_handler {
sendEOI();
signal_driver();
}
scheduler {
if(driver_is_signalled) {
switch_to_driver();
}
}
driver {
signal_handler {
inb(0x60);
}
}
I hope that was understandable; basically, when I get an IRQ, the handler sets up some stuff to signal the driver process, before sending the EOI to the interrupt controller and doing the IRET. Note that control flow doesn't jump to the driver immediately, that happens the next time the driver is scheduled. This puts some time latency between sending of the EOI/receiving the IRQ and actually reading the data from the io port.
Once the driver is scheduled, then it will read data from the PS/2 data port (0x60). The problem I am facing here is that I get repeated IRQs, and by extension repeated bytes when I read from the port. I'm not sure what to suspect here, but it might be related to reading the port very late after sending the EOI (i'll explain this suspicion below).
Basically, if I type something like "ok" in quick succession, I get the following IRQs and bytes (scancode set 2):
Code: Select all
0x44 (O - down)
0x42 (K - down)
0xF0
0x44 (O - up)
0xF0
0x42 (K - up)
0x42 (??)
0x42 (??)
0x42 (??)
On to my suspicion: if, instead of waiting for the driver to read from the data byte, I read the byte inside the irq handler (before or after sending the EOI doesn't matter), it works completely fine, and I get no repeats. I don't really want to do this, since this couples the kernel with the driver...
More context: I'm running with an IOAPIC and LAPIC setup, but with only one CPU running. Of note is that if I use the "normal" PIC to handle stuff, instead of repeated bytes I get skipped bytes.
I have no clue what's going on here, and the nice people on IRC haven't been able to help either.