3C905CX-TX-M network card supported?

Hello,

Is this 3Com network card supported by 6.2.1?? The card seems to work with
devn-el900 but it seems to create problems when sharing the interrupt line
with other devices. The effect is that the processor use jumps to 100%. The
problem disapears when the network card is unplugged from the network cable.
Has anyone experience similar problems??

Carlos.

Hi Carlos,

I haven’t seen this before and I have used lots of these cards. Check
the nicinfo output to make sure that there are no errors, and also if possible
try another nic card of the same chipset, just to ensure that its not the
hardware that is flakey.

Also does it matter what device shares the IRQ for this to act like this?

Regards,

Erick

Carlos Beltran <cbeltran@dist.unige.it> wrote:

Hello,

Is this 3Com network card supported by 6.2.1?? The card seems to work with
devn-el900 but it seems to create problems when sharing the interrupt line
with other devices. The effect is that the processor use jumps to 100%. The
problem disapears when the network card is unplugged from the network cable.
Has anyone experience similar problems??

Carlos.

Erick Muis
Hardware Group
QNX Software Systems Ltd.
Email: emuis at qnx.com

“Carlos Beltran” <cbeltran@dist.unige.it> wrote in message
news:buh424$qln$1@inn.qnx.com

Hello,

Is this 3Com network card supported by 6.2.1?? The card seems to work with
devn-el900 but it seems to create problems when sharing the interrupt line
with other devices. The effect is that the processor use jumps to 100%.
The
problem disapears when the network card is unplugged from the network
cable.
Has anyone experience similar problems??

What are the ‘other devices’. Are they also being driven with driver
software (ie. also have an interrupt handler attached) or are they just
sitting on the PCI bus doing nothing?


Cheers,
Adam

QNX Software Systems Ltd.
[ amallory@qnx.com ]

With a PC, I always felt limited by the software available.
On Unix, I am limited only by my knowledge.
–Peter J. Schoenster <pschon@baste.magibox.net>

Thank you very much for your replays!!
Yes, actually the other device driver is a home made driver :slight_smile:. Therefore,
surelly it is my driver to create problems!, I asked because that network
card is not listed in the supported hardware (the CX I mean).
I confirmed the problem yesterday when I changed the network card (into a
matrox - dev-tulip.so) and the problem continues to be there.
It is strange since this driver has shared the interruption with other
devices (i.e. video card) and had no problems…
Any way, here it is the thread being used to wait for the interrupt . The
regbase[65] and regbase[64] are just interrupt registers in the chip.
This is being called from the main program using:
“pthread_create(NULL,&attr,&InterruptEvent,NULL);”.
I think this is the correct way to do the things, but something is out of my
look because it is creating problems when sharing the interrupt with the
network card…
Ah, another thing, when the problem appears, this thread seems to wait for
ever in the InterruptWait()…

void * InterruptEvent()
{
uint32_t stat,astat;
uint32_t dstat;
struct bttv * btv = &bttvs[0];
int res = 0;
struct sigevent event;
int error;

printf(“bttvx: Interrupt thread activated\n”);
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)
{
InterruptWait(0,NULL);

/* get/clear interrupt status bits */
stat = regbase[64];
astat = stat & regbase[65];
//Write same data back, clears the pending intrs.
regbase[64] = stat;

InterruptUnmask(btv->irq, btv->id);

if (!astat) //How the hell where we triggerd, we got no interrupt
pending! :slight_smile:
return;

/* get device status bits */
dstat=btread(BT848_DSTATUS);

//This interrupt called when the RISC program has finished
if (astat & BT848_INT_RISCI)
{
//pthread_mutex_lock(&buf_mutex);
res = pthread_mutex_trylock(&buf_mutex );
switch(flag)
{
case 1:
if (res == EOK)
memcpy(btv->image_buffer,btv->imagebuf_1, widthheightdeep);
flag = 2;
break;
case 2:
if (res == EOK)
memcpy(btv->image_buffer,btv->imagebuf_2, widthheightdeep);
flag = 3;
break;
case 3:
if (res == EOK)
memcpy(btv->image_buffer,btv->imagebuf_3, widthheightdeep);
flag = 1;
break;
};
if (res == EOK)
{
pthread_mutex_unlock(&buf_mutex);
pthread_cond_signal(&condvar);
}
else
printf(“bttvx:Lost a frame\n”);
}

if (astat & BT848_INT_VPRES)
{
printf(“bttvx: Lost conection:%d\n”,btv->field_count);
fflush(stdout);
//pthread_cond_signal(&condvar);
}

if (astat & BT848_INT_VSYNC)
{
btv->field_count++;
//pthread_cond_signal(&condvar);
}
if(astat & BT848_INT_FMTCHG) //Change of video input
{
btv->win.norm &= (dstat & BT848_DSTATUS_NUML) ? (~1) : (~0);
bt848_cap(btv,0);
bt848_set_size(btv);
bt848_cap(btv,1);
printf(“bttvx: Changed input format”);
}
if(astat & BT848_INT_SCERR) //Error, reset capture.
{
printf(“Error\n”);
fflush(stdout);
bt848_cap(btv,0);
bt848_cap(btv,1);
}
}
error = InterruptDetach(btv->id);
if (error)
printf(“bttvx: error detaching interrupt %d\n”,error);

}


“Carlos Beltran” <cbeltran@dist.unige.it> wrote in message
news:buh424$qln$1@inn.qnx.com

Hello,

Is this 3Com network card supported by 6.2.1?? The card seems to work with
devn-el900 but it seems to create problems when sharing the interrupt line
with other devices. The effect is that the processor use jumps to 100%.
The
problem disapears when the network card is unplugged from the network
cable.
Has anyone experience similar problems??

Carlos.

Ohhh. What stupid! I just get it. I should not return when I am triggered
from the other card!! Just a continue should go here to jump to the next
interation. However it is still obscure why this was working sharing the
interrupt with the video card…

if (!astat) //How the hell where we triggerd, we got no interrupt
return;

Ok, ok…so let me understand if I am right.
My thread was exiting when there was an interrupt from the network card,
ok?. But Qnx didn’t know that the thread was not there anymore, so it was
“masking” the interrupt. My thread was not there to unmask it so this
creating the problem in the network card driver. Am i right?

Thanks

Carlos.

“Carlos Beltran” <cbeltran@dist.unige.it> wrote in message
news:buoebf$pfk$1@inn.qnx.com

Ohhh. What stupid! I just get it. I should not return when I am triggered
from the other card!! Just a continue should go here to jump to the next
interation. However it is still obscure why this was working sharing the
interrupt with the video card…

if (!astat) //How the hell where we triggerd, we got no interrupt
return;

I think you’re on the right track.

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.

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).

Hope that helps.

-Adam


Cheers,
Adam

QNX Software Systems Ltd.
[ amallory@qnx.com ]

With a PC, I always felt limited by the software available.
On Unix, I am limited only by my knowledge.
–Peter J. Schoenster <pschon@baste.magibox.net>

“Carlos Beltran” <cbeltran@dist.unige.it> wrote in message
news:buoepv$ppl$1@inn.qnx.com

Ok, ok…so let me understand if I am right.
My thread was exiting when there was an interrupt from the network card,
ok?. But Qnx didn’t know that the thread was not there anymore, so it was
“masking” the interrupt. My thread was not there to unmask it so this
creating the problem in the network card driver. Am i right?

Thanks

Carlos.

“Carlos Beltran” <> cbeltran@dist.unige.it> > wrote in message
news:buoebf$pfk$> 1@inn.qnx.com> …
Ohhh. What stupid! I just get it. I should not return when I am
triggered
from the other card!! Just a continue should go here to jump to the next
interation. However it is still obscure why this was working sharing the
interrupt with the video card…

if (!astat) //How the hell where we triggerd, we got no interrupt
return;

\

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



}

Ok, perfect! Thank you for your fast help Adam!.

Cheers from Italy,

Carlos

“Carlos Beltran” <cbeltran@dist.unige.it> wrote in message
news:buor22$4vi$1@inn.qnx.com

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…

If it’s pre-configured from the BIOS (ie. PnP stuff already done) and the
BIOS doesn’t let you change the IRQ assignments I believe you could
reconfigure the device via the pci_* API. It might be easier to just pick a
different slot :slight_smile:

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:
snip

Yes.


Cheers,
Adam

QNX Software Systems Ltd.
[ amallory@qnx.com ]

With a PC, I always felt limited by the software available.
On Unix, I am limited only by my knowledge.
–Peter J. Schoenster <pschon@baste.magibox.net>

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

In article <bv67aj$sr3$2@inn.qnx.com>, emuis@node55.ott.qnx.com says…

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.

Hi Erick,

Thanks for example. Does it suggest that pci_map_irq() is not just a
wrapper for PCI BIOS service (INT 1Ah), but it also take care about PIC
and will program interrupt line to work in level trigged mode if it was
in edge trigged mode?

Eduard.

/*=============================================================================

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