Page 1 of 1
Mouse randomly stops sending data
Posted: Fri Apr 16, 2021 8:31 am
by max
Hey guys,
didn't work on this for a very long time so I might have forgotten quite some things..
So I'm having the issue that my kernel randomly stops receiving IRQ12 for the mouse input. I'm using the LAPIC to receive interrupts and there might be a problem with the sequence I'm doing, but I'm a little stuck here...
For initialization I do this:
- Driver (task) registers a function as an interrupt handler
- Set the Compaq status byte to enable IRQ12
- Then I set the mouse to "default settings" and enable packet streaming
Then my routine when an IRQ 1 or 12 comes in is this:
- Kernel receives the interrupt, the handling task is interrupted and I set the task state to continue within its interrupt handler
- I immediately write APIC_REGISTER_EOI to 0 to acknowledge the interrupt
- Next time the driver is scheduled, it reads the status byte 0x64 and then the value from 0x60 as long as there is data
Is it okay that I directly acknowledge the interrupt once it is there? Or
must the data be read from the IO ports before acknowledging it? Is there anything else except for writing the APIC_REGISTER_EOI that needs to be done in this case?
It happens very randomly, it works for a while and at some point I simply don't get any IRQ 12 anymore...
Thanks in advance!
Re: Mouse randomly stops sending data
Posted: Fri Apr 16, 2021 8:53 am
by Octocontrabass
max wrote:Next time the driver is scheduled, it reads the status byte 0x64 and then the value from 0x60 as long as there is data
How is this synchronized with the IRQ handler? Why are you reading 0x64 at all when each IRQ tells you that one byte is available?
Re: Mouse randomly stops sending data
Posted: Fri Apr 16, 2021 9:04 am
by max
Octocontrabass wrote:max wrote:Next time the driver is scheduled, it reads the status byte 0x64 and then the value from 0x60 as long as there is data
How is this synchronized with the IRQ handler? Why are you reading 0x64 at all when each IRQ tells you that one byte is available?
Well it is not really synchronized at the moment, hence I was thinking it would be a good idea to read data as long as the status says there is data.
When an interrupt occurs, I don't directly jump into the driver code that handles the interrupt, but I store the threads current state, then set the interrupt handler function as the current EIP of the task, and then the task will be executed by the scheduler as normal. Like this I tried to avoid that a long-running IRQ handler could block the system. But the idea sounds worse and worse the longer I look at it.
Re: Mouse randomly stops sending data
Posted: Fri Apr 16, 2021 9:26 am
by 8infy
max wrote:Octocontrabass wrote:max wrote:Next time the driver is scheduled, it reads the status byte 0x64 and then the value from 0x60 as long as there is data
How is this synchronized with the IRQ handler? Why are you reading 0x64 at all when each IRQ tells you that one byte is available?
Well it is not really synchronized at the moment, hence I was thinking it would be a good idea to read data as long as the status says there is data.
When an interrupt occurs, I don't directly jump into the driver code that handles the interrupt, but I store the threads current state, then set the interrupt handler function as the current EIP of the task, and then the task will be executed by the scheduler as normal. Like this I tried to avoid that a long-running IRQ handler could block the system. But the idea sounds worse and worse the longer I look at it.
Sounds like an overcomplication to set the thread's instruction pointer to the interrupt handler, instead why not make it unblock the thread that's doing ps2 handling in a while loop and each time calls wait_for_irq(2) or something? Other than that it's a great idea to not run irq handler code directly in ISRs.
Re: Mouse randomly stops sending data
Posted: Fri Apr 16, 2021 9:38 am
by Octocontrabass
max wrote:Well it is not really synchronized at the moment, hence I was thinking it would be a good idea to read data as long as the status says there is data.
So if an IRQ arrives after reading 0x64 to see that no more data is available, but before the driver thread puts itself back to sleep, will the driver thread ever wake up to check again?
Re: Mouse randomly stops sending data
Posted: Fri Apr 16, 2021 9:46 am
by max
8infy wrote:Sounds like an overcomplication to set the thread's instruction pointer to the interrupt handler, instead why not make it unblock the thread that's doing ps2 handling in a while loop and each time calls wait_for_irq(2) or something? Other than that it's a great idea to not run irq handler code directly in ISRs.
It is, indeed. I implemented this back then because like this, the driver can use syscalls within the interrupt handler (which would in turn be interrupts again) without problems. But I think it definitely is an overcomplication.
Octocontrabass wrote:So if an IRQ arrives after reading 0x64 to see that no more data is available, but before the driver thread puts itself back to sleep, will the driver thread ever wake up to check again?
Could indeed be a timing issue. I have to rethink my solution.
This indeed brings up the question to me - how do you solve the using of syscalls within an interrupt handler routine? Do you simply not allow it? Or do you directly call the kernel function responsible for it?
Re: Mouse randomly stops sending data
Posted: Fri Apr 16, 2021 11:16 am
by thewrongchristian
max wrote:
Octocontrabass wrote:So if an IRQ arrives after reading 0x64 to see that no more data is available, but before the driver thread puts itself back to sleep, will the driver thread ever wake up to check again?
Could indeed be a timing issue. I have to rethink my solution.
This indeed brings up the question to me - how do you solve the using of syscalls within an interrupt handler routine? Do you simply not allow it? Or do you directly call the kernel function responsible for it?
What syscalls are you using?
ISR should be quick, read whatever state they need, and get the hell out of dodge as quickly as possible.
As the PS2 controller will have little if any buffering, you're probably best off reading the port 60h contents in the ISR, and posting the resulting value to a FIFO. In fact, you must do it this way, as the only way you can determine which PS2 port the data is read from is by whether you're handling IRQ 1 or 12. How can you otherwise determine this outside of the IRQ, without scheduling races between the respective keyboard and mouse threads?
Writing to a FIFO can be quick, can be easily protected from race conditions, and can easily detect buffer overflow if nothing is reading from the other end of the FIFO (if, for example, your keyboard or mouse driver is hung.) You can have a FIFO each for the keyboard and mouse, which the respective threads read from when data is available.
Re: Mouse randomly stops sending data
Posted: Fri Apr 16, 2021 8:27 pm
by Octocontrabass
max wrote:Could indeed be a timing issue. I have to rethink my solution.
A semaphore can solve this easily: the IRQ sets the semaphore, and waking the driver thread clears it. If the driver thread tries to sleep while the semaphore is set, it wakes immediately and the semaphore is cleared.
max wrote:This indeed brings up the question to me - how do you solve the using of syscalls within an interrupt handler routine? Do you simply not allow it? Or do you directly call the kernel function responsible for it?
I like to have drivers in userspace, so they make syscalls the same way any other userspace program does.
thewrongchristian wrote:How can you otherwise determine this outside of the IRQ, without scheduling races between the respective keyboard and mouse threads?
Reading the byte from port 0x60 acknowledges the IRQ, so if each driver reads only a single byte each time it's awakened, the two drivers will never compete to read port 0x60. You might want to use a FIFO anyway, but you don't need it for scheduling.