OSDev.org
https://forum.osdev.org/

xHCI interrupt handler fires only one time
https://forum.osdev.org/viewtopic.php?f=1&t=33768
Page 1 of 1

Author:  iman [ Mon Jul 15, 2019 3:53 am ]
Post subject:  xHCI interrupt handler fires only one time

Hi.

I started to implement a driver for my physical hardware xHCI controller. So basically whatever I report here is entirely on a physical hardware and not any emulator.

I am making my driver by rummaging xHCI spec by Intel, chapters 9, 10, and 14 of the wonderful book by Ben Lunt, and searching through the nice PrettyOs source code in Sourceforge.

Scanning through the PCI, I got my xHCI base address, then set up all the registers, implemented all the necessary scratchpad buffers, command ring, event ring, primary interrupter all by the porper alignment and boundary values (no doubt about them, I have already checked them out more than 100 times). The controller has been successfully reset working properly.

From the PCI configuration space, I got interrupt line = 11 and interrupt pin = INTA. By the way the bit 10 of the command register of the PCI function is clear (i.e. interrupts are not disabled) and bit 3 of the status register is set. Everything work just fine.

After that to start the schedule, I made a noop command, wrote it on the command ring, rang the doorbell, and wait for the event ring completion. The problem is that my interrupt handler gets called while the value of UsbStatus is still zero. Besides the IP flag of the IMAN field of the primary interrupter is also zero. So basically the noop command has not been executed well. To make things a bit cleaner, I deleted the noop command and instead used my USB stick to see if upon attachment, I get any interrupt. It works for the first time you insert it while again the UsbStatus register is zero and IP is zero as well! Once you detach the stick and any other attachment of the stick would not create any other interrupt firing.
Of course this is not my only interrupt handler and I had so far PIT and keyboard and PS/2 mouse all installed on my IDT, so the master and slave acknowledgement had been implemented properly.


The solutions I have already tried:
1- changing the IRQ number from 11 to many more numbers between 0 and 255, but even the first interrupt firing was also stopped. It means as long as the interrupt line is PCI config space is 11, I have only an interrupt once.
2- implementing MSI instead of pin.
I found the message address and message data registers by finding the 5th capability ID on PCI config space, and activated the LAPIC by finding the lapic_base value from CPU_MSR. Again once the interrupt handler is registered on 11th (i.e. 11 + 32) IDT entry, it works only one time and changing to any other numbers fail to generate interrupts.

I really stuck here and have no more clue how to proceed. Therefore any other suggestions are welcome.

Best regards.
Iman.

Author:  thomtl [ Mon Jul 15, 2019 9:05 am ]
Post subject:  Re: xHCI interrupt handler fires only one time

A few thoughts:
- Are you sending an EOI to the lapic
- Are you routing the PCI irq correctly with the help of the AML _PRT methods?

Author:  iman [ Mon Jul 15, 2019 9:23 am ]
Post subject:  Re: xHCI interrupt handler fires only one time

thomtl wrote:
A few thoughts:
- Are you sending an EOI to the lapic

Yes, I sent it to the lapic
Quote:
- Are you routing the PCI irq correctly with the help of the AML _PRT methods?

I am not sure about this.
Since my priority was (still is) to get the xhci handler worked by the PIC provided interrupt line 11 and interrupt pin INTA, I have not dug too much into it.

Author:  thomtl [ Mon Jul 15, 2019 9:30 am ]
Post subject:  Re: xHCI interrupt handler fires only one time

Well if you're still using PIC IRQ11 you should send the EOI to the PIC

Author:  iman [ Mon Jul 15, 2019 9:54 am ]
Post subject:  Re: xHCI interrupt handler fires only one time

thomtl wrote:
Well if you're still using PIC IRQ11 you should send the EOI to the PIC

In my original post, I mentioned that I send the EOI to the PIC (if the IRQ number is greater than 8, then to both master and slave PICs).

Author:  BenLunt [ Tue Jul 16, 2019 7:47 am ]
Post subject:  Re: xHCI interrupt handler fires only one time

Hi guys,

iman and I have been exchanging emails back and forth and he has been very patient with me. Unfortunately, I have had very little time to help.

With what I have seen, his interrupt code is correct and working. I believe the problem is with the xHCI itself.

Here are my suggestions, which some of them I have already suggested to him and he has investigated.

- The xHC_OPS_USBStatus register must be written to as the first register written within your handler.
- After the Status register has been written, read the xHC_INTERRUPTER_IMAN register.
- If the bottom two bits are set, write it back, and then do the Handler's work.
- Remember that you have to advanced the xHC_INTERRUPTER_DEQUEUE register to the next location, which by doing so, clears the "busy" bit.

After checking this, check that you are actually writing the next TRB to the correct place. Your interrupts may be perfectly correct, you might just be incorrectly adding TRBs to the list.

Again, sorry for my absence. I have been quite busy with other things.

Ben
- http://www.fysnet.net/osdesign_book_series.htm

Author:  iman [ Wed Jul 17, 2019 3:33 am ]
Post subject:  Re: xHCI interrupt handler fires only one time

Hi again Ben. Thanks for replying.
BenLunt wrote:
- The xHC_OPS_USBStatus register must be written to as the first register written within your handler.

Indeed it is the first register in my handler which is read and write.
BenLunt wrote:
- After the Status register has been written, read the xHC_INTERRUPTER_IMAN register.
- If the bottom two bits are set, write it back, and then do the Handler's work.

As I mentioned earlier the xHC_IMAN_IP bit (i.e. bit zero of the register) has been never set to let me acknowledge it.
BenLunt wrote:
- Remember that you have to advanced the xHC_INTERRUPTER_DEQUEUE register to the next location, which by doing so, clears the "busy" bit.

I checked it. I should work in the right way.

Cheers.
Iman.

Author:  BenLunt [ Thu Jul 18, 2019 9:53 pm ]
Post subject:  Re: xHCI interrupt handler fires only one time

iman,

I sent you an email with more detail along with a few other suggestions, but after looking over your code, I think you have missed one tiny, but major, item.

In your interrupt handler, you never clear bit 0 of the IMAN register. i.e.: you write to bit 1, but not to bit 0. Bit 0 is a Write/Clear bit. Meaning, you must write a 1 to it to clear it.

This is the Interrupt Pending bit. If you never clear it, the controller won't fire again because it already thinks there is an interrupt pending.

At the bottom of your interrupt handler, change:

iman |= (xHC_IMAN_IE);

to

iman |= (xHC_IMAN_IE | xHC_IMAN_IP);

This should make it work, of course making sure to write the value of 'iman' back to the (interrupter) register.

Ben
- http://www.fysnet.net/the_universal_serial_bus.htm

Page 1 of 1 All times are UTC - 6 hours
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
http://www.phpbb.com/