Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

x86 pci interrupt sharing

236 views
Skip to first unread message

Matthew Peltzer

unread,
Oct 7, 2002, 9:31:05 PM10/7/02
to
Greetings,

I am developing a device driver for custom PCI hardware under vxWorks
5.4/Tornado 2.0.2, and am experiencing difficulties in handling interrupts.

I have no problem when the two devices are on their own interrupts, and I
have no problem when using a shared interrupt independently. I am not able
to have two threads at the same time listen to the same interrupt.

According to the manual page for pciIntConnect(), I should not have to care
about shared interrupts:

DESCRIPTION
This routine connects an interrupt handler to the PCI
interrupt line(A - D). Link list is created if multiple
handlers are assigned to the single PCI interrupt.

To me this says that every time I call pciIntConnect(), my function and
parameter will be added to a list that when the interrupt vector is
triggered, each of my functions will be called with the appropriate
parameter. Unfortunately, this is not what I am experiencing, although I am
not 100% sure of what I am experiencing. It seems as though the second call
to pciIntConnect() effectively wipes out the first parameter, for as soon as
an interrupt is generated on this irq, my system deadlocks. I can only
guess that this is because I am not turning off the interrupt on the correct
card because my parameter is not what I expect it to be.

My solution to this is to do my own isr chaining. I call pciIntConnect()
and sysIntEnablePIC() only when no other connection has been made for this
irq. pciIntDisconnect() and sysIntDisablePIC() are called only when no
other device is listening to the irq. This setup has the same flaw as the
previous: vxWorks reboots when two tasks are run that listen to a separate
PCI card, yet share the same irq.

I do not know if my callbacks are being called. the first operation in my
callback is a logMsg(), but I am not seeing this. I also have some
logMsg()s to tell me if each interrupt is being caught or ignored, which is
decided by looking at the interrupt line on the hardware device as specified
in the parameter passed into the isr by the system. I have yet to see an
interrupt be ignored.


This is the code I am using to enable interrupts:

pciIntConnect(INUM_TO_IVEC((pci->irq + 0x20)), myDummyISR, list[pci->irq]);
sysIntEnablePIC(pci->irq);


'pci' is a structure that among other things contains the irq number as read
from the pci configuration space with:

pciConfigInByte(pci->busNum, pci->devNum, pci->fncNum, 0x3c, &(pci->irq));


Is there anything that I am missing for irq sharing to work in vxWorks?
Has anyone had any luck/mis-luck with similar methods?


Matthew Peltzer
goo...@spu.edu

Khac Tri VU

unread,
Oct 8, 2002, 4:06:53 AM10/8/02
to
Hi, Matthew
I think that you need to save the address of the current ISR linked to the
IRQ somewhere before registering the second ISR(check intVecGet).
In the second ISR, you will have to call the first ISR if needed.
logMsg() in a ISR is not a good practise since ISR may have been executed,
but nothing is printed out.
Cheers,
Tri.


"Matthew Peltzer" <mat...@ballardtech.com> wrote in message
news:antf51$pr2$1...@overload.lbl.gov...

Michael Lawnick

unread,
Oct 8, 2002, 9:19:29 AM10/8/02
to
Hi Matthew,

sounds you are using PC arch.
Did you call pciIntLibInit with the correct number of interrupts that should
be shared?
If not, your symptoms are as expected.
Check your handler tables, you've got the sources in src/drv.
It's just some debugging work.

HTH
Michael

"Matthew Peltzer" <mat...@ballardtech.com> schrieb im Newsbeitrag
news:antf51$pr2$1...@overload.lbl.gov...

Matthew Peltzer

unread,
Oct 9, 2002, 4:18:59 PM10/9/02
to
"Michael Lawnick" <lawnick@no_spam.softec.de> wrote in message news:<anum10$g4p$1...@snoopy.bndlg.de>...

> Hi Matthew,
>
> sounds you are using PC arch.
Indeed. I am using a PentiumPro, but my BSP is based off of
'PENTIUM'.

> Did you call pciIntLibInit with the correct number of interrupts that should
> be shared?
> If not, your symptoms are as expected.
> Check your handler tables, you've got the sources in src/drv.
> It's just some debugging work.
>
> HTH
> Michael
>

handler tables? you mean pciIntList[]?

As far as I can tell, pciIntLibInit is prototyped as:

STATUS pciIntLibInit (void);

And there does not seem to be anything useful in the near vincinity,
with the exception of this comment:

"Shared PCI interrupt are supported by three functions: pciInt(),
pciIntConnect(), pciIntDisconnect(). pciIntConnect() adds the
specified interrupt handler to the link list and pciIntDisconnect()
removes it from the link list. Master interrupt handler pciInt()
executes these interrupt handlers in the link list for a PCI
interrupt. Each interrupt handler must check the device dependent
interrupt status bit to determine the source of the interrupt, since
it simply execute all interrupt handlers in the link list. pciInt()
should be attached by intConnect() function in the BSP initialization
with its parameter. The parameter is an IRQ associated to the PCI
interrupt."


After reading this, I have devised this algorithm:

1) upon driver/vxWorks initialization, connect & enable the hardware's
irq:
intConnect(INUM_TO_IVEC(pci->irq), pciInt, pci->irq);
intEnable(pci->irq);

2) when the user wants to listen to interrupts generated by the
hardware, add my ISR to the list:
pciIntConnect(INUM_TO_IVEC(pci->irq), myISR, pci);

The only thing stopping me from doing this is that I have not seen
anything like this in all the user manuals or newsgroups that I have
searched. But I see no reason, per the comment, that nothing other
than this is the correct code.

Your thoughts?


Matthew Peltzer

Varndell Engineering

unread,
Oct 9, 2002, 5:12:01 PM10/9/02
to

You didn't answer the question as to whether or not you've called
pciIntLibInit(). If your BSP is not calling it, in sysHwInit(), then
you need to add a call to it. You are correct that it takes no
parameters, but that doesn't mean you needn't call it.
After that, simply call pciIntConnect just as you would intConnect.
And don't forget to add INT_NUM_IRQ0 to the irq number when you do.
You don't need to do the intConnect for pciIntLib. It will do that
itself. You do need to explicitly enable the IRQ, and you also need
to be aware that the IRQ will stay enabled even after you've
pciIntDisconnected all ISRs from it. You also need to be aware that
when/if you temporarily mask a given IRQ, you are possibly disabling
an IRQ that more than device is relying on.
Finally, despite it's name, there is nothing PCI about pciIntLib.
It's just a generic IRQ sharing utility.

Regards,
George Varndell
--
Varndell Engineering, LLC Embedded Systems Expertise
Need a vxWorks END driver for SiS900? Contact us.
http://www.varndellengineering.com


-----------== Posted via Newsfeed.Com - Uncensored Usenet News ==----------
http://www.newsfeed.com The #1 Newsgroup Service in the World!
-----= Over 100,000 Newsgroups - Unlimited Fast Downloads - 19 Servers =-----

Matthew Peltzer

unread,
Oct 10, 2002, 7:34:05 PM10/10/02
to
George,

Thanks for your help.
It took a lot of mucking around in the vxWorks sources, but I have
managed to solve my problems.

To answer your question (finally, sorry), pciIntLibInit() is being
called from within sysHwInit().

My problems turned out to be on the uninstall side of things, not the
install. I had unconsciously made the assumption that the ISR
chaining was done on a device basis, rather than a driver basis. So,
I could install my ISR routine twice, but when I tried to uninstall
either routine, only the first would be removed. I can only attribute
vxWorks crashing & rebooting to the stale entry that was never getting
called. My guess is that when the second card raised its interrupt
line, vxWorks ended up in something that is not a function.

My solution to all this is to keep a table of all the devices
listening to interrups, and connect/enable on the first of each irq,
and disable/disconnect on the last of each irq. My parameter to the
ISR is the irq for the isr. Since the device table is global, I can
iterate through each slot and see which device raised the interrupt
for that irq.


Again, thanks.


Matthew Peltzer

0 new messages