Hi Carlos,
You can re-map the IRQ, however only if the BIOS supports it. Here is
an example that shows how to do this.
E.
/*=============================================================================
The pci_map_irq() function call can sometimes work, however it depends
on if the BIOS supports this function call. There is no guarantee that
all BIOS’s will support this.
Erick Muis
=============================================================================*/
#include <stdio.h>
#include <hw/pci.h>
#include <stdlib.h>
#include <stddef.h>
#include <sys/neutrino.h>
#define USB_CLASS_UHCI 0x0c0300
int enumerate_usb();
int main()
{
ThreadCtl(_NTO_TCTL_IO, 0);
enumerate_usb(USB_CLASS_UHCI);
return(0);
}
int enumerate_usb(_uint32 Class)
{
struct pci_dev_info usb_info;
int usb_pci_index = 0, new_irq = 15, status;
void *handle;
memset(&usb_info, 0, sizeof(usb_info));
usb_info.Class = Class;
if (pci_attach(0) == -1)
{
fprintf(stderr, “Unable to open the pci server.\n”);
exit(EXIT_FAILURE);
}
while ((handle = pci_attach_device (NULL, PCI_SEARCH_CLASS, usb_pci_index, &usb_info)) != NULL)
{
fprintf(stderr, “Found a controller. Current IRQ is %d.\n”, usb_info.Irq);
while (((status = pci_map_irq(usb_info.BusNumber, usb_info.DevFunc, new_irq, 0x0D))
!= PCI_SUCCESS) && (new_irq))
{
switch (status)
{
case PCI_UNSUPPORTED_FUNCT:
{
fprintf(stderr, “This function isn’t supported by the BIOS.\n”);
break;
}
case PCI_SET_FAILED:
{
new_irq–;
fprintf(stderr, “The PCI server was unable to map the intno/intpin. Trying %d.\n”,
new_irq);
break;
}
default:
{
fprintf(stderr, “You haven’t called pci_attach(), or the call to it failed.\n”);
}
}
}
pci_write_config (handle, offsetof(struct _pci_config_regs, Interrupt_Line), 1,
sizeof(new_irq), &new_irq);
pci_detach_device(handle);
usb_pci_index++;
}
return(0);
}
Carlos Beltran <cbeltran@dist.unige.it> wrote:
One problem with sharing an IRQ with a network card, is that you receive
many ‘interrupt events’ or ISR executions even though you’re hardware
isn’t
triggering it. The rate of interrupts has to do with the amount of
traffic
the NIC is receiving. Sharing the IRQ line with one ‘fast’ interrupt
producer and one ‘slow’ producer isn’t a great idea. On top of that,
you’re
using the interrupt event mechanism, and that means for every network
interrupt, you’re unblocked, dispatched, executing, ‘doing nothing’ and
then
reblocking. It would be best to use your own IRQ line, or at least not
share with the NIC.
Uhmm. Thanks for the info. I see. But, is there a way to chose the Irq
channel within Qnx? I was trying to do so…also with the BIOS setup and I
could not. The only solution was to change physically the cards to another
PCI slot…
And the other issue where you’re exiting the thread if after unblocking,
your hardware says it didn’t trigger the IRQ is wrong. You can unblock
from
InterruptWait() from an interrupt event (even if your particular hardware
didn’t generate the IRQ) or a signal being dropped on you. In addition,
when you InterruptAttachEvent(), the corresponding InterruptWait() must
occur in that particular thread (unless you use the
_NTO_INTR_FLAGS_PROCESS
flag).
I am doing the InterruptAttachEvent in the same thread without the
_NTO_INTR_FLAGS_PROCESS, so this should be ok if I understand correctly…
So the only thing that it is wrong is that I don’t control the return from
the InterruptWait()…therefore, if I am right you mean I should do
something like this:
void * InterruptEvent()
{
…
…
int _waitreturn;.
…
ThreadCtl( _NTO_TCTL_IO, 0 );
SIGEV_INTR_INIT(&event);
btv->id =InterruptAttachEvent(btv->irq, &event,_NTO_INTR_FLAGS_END
|_NTO_INTR_FLAGS_TRK_MSK);
while (!m_exit) //this while runs forever until I change the m_exit from
the main program
{
_waitreturn = InterruptWait(0,NULL);
if ( _waitreturn == -1)
continue;
//If I am here is because I got an interrupt from my card or another card
sharing the interrupt, ok?
InterruptUnmask(btv->irq, btv->id); //This should be done in any case
(the interrupt being from my hardware or from another hardware, right?
if (!astat) // Now I know the interrupt is not from my hardware
continue; //loop to the next iteration
…
…
…
}
–
Erick Muis
Hardware Group
QNX Software Systems Ltd.
Email: emuis at qnx.com