xHCI interrupt handler fires only one time
Posted: Mon Jul 15, 2019 3:53 am
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.
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.