Porting PCI driver in linux to QNX

Good point, no the code isn’t doing that.

Thanks! I couldn’t figure out how to decode a rar (you can tell I don’t pirate stuff :slight_smile:

Hi ,

I don’t understand what you have noticed in my code? Which part is wrong? What do you mean by loop checking and checking for new sources?

master(as I see you) given below is the code if you couldnt open the zipped file.

[code]int main (int argc, char *argv[])
{
Uint32 count = 1;

ThreadCtl(_NTO_TCTL_IO,0); //request I/O privileage;thread is permitted to I/O ports
/* Initialise the PCI driver */

printf("Find PCI Devices\n");
PCI_FindPciDevices () ;

delay(100);
printf("Reading Bar\n");
PCI_readBAR () ;

	  
/* Thread for Interrupt handling from DSP -> Host i.e QNX */
pthread_create(NULL, NULL, PCI_isrThread, NULL);


/* Host to DSP interrupt*/
HAL_PciEnableHostInterrupt(); //interrupt DSP 
delay(100);


while(1) //this is to keep the program live for long time.
{
	int m=0;
	m++;
	m--;
}

/* Disconnect the PCI */
remove_pci();

return EXIT_SUCCESS;

}

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

  • @func HAL_CheckPciInterrupt

  • @desc This function check whether interrupt is generated by DM642 or not.

  • @modif None.

  • ============================================================================
    */
    Uint32
    HAL_CheckPciInterrupt (void)
    {
    volatile DM6437PCI_pciRegs * pciRegs = (DM6437PCI_pciRegs *) ((Uint32) regVirt + (DM6437PCI_PCIREG_BASE - 0x01C00000)) ;
    Uint32 status = 0 ;

    if ( (pciRegs->PCICSRMIR & DM6437PCI_INTSTATUS_MASK) == (DM6437PCI_INTSTATUS_MASK))
    {
    status = 1 ;
    }
    printf(“HAL_CheckPciInterrupt status = %d\n”, status);

    if ( (pciRegs->PCIHINTCLR & DM6437PCI_SOFTINT0_MASK ) == (DM6437PCI_SOFTINT0_MASK))
    {
    printf(" %s: Interrupt from DSP\n",FUNCTION);
    //status = 1 ;
    }
    else
    {
    printf(" %s: Error in reading PCIHINTCLR register\n",FUNCTION);
    }

    return status ;
    }

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

  • @func HAL_PciClearDspInterrupt

  • @desc Clear pending interrupt from DSP to Host.

  • @modif None.

  • ============================================================================
    */
    Uint32
    HAL_PciClearDspInterrupt (Void)
    {
    volatile DM6437PCI_pciRegs * pciRegs = (DM6437PCI_pciRegs *) ((Uint32) regVirt + (DM6437PCI_PCIREG_BASE - 0x01C00000)) ;

    //pciRegs->PCISTATCLR |= DM6437PCI_SOFTINT0_MASK ;
    pciRegs->PCIHINTCLR |= DM6437PCI_SOFTINT0_MASK ; //this clears the interrupt
    }

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

  • @func HAL_PciEnableHostInterrupt

  • @desc Generate interrupts to the DSP.

  • @modif None.

  • ============================================================================
    */
    Void
    HAL_PciEnableHostInterrupt (Void)
    {
    volatile DM6437PCI_pciRegs * pciRegs = (DM6437PCI_pciRegs *) ((Uint32) regVirt + (DM6437PCI_PCIREG_BASE - 0x01C00000)) ;

    pciRegs->PCIBINTSET |= DM6437PCI_SOFTINT0_MASK ;
    pciRegs->PCISTATSET |= DM6437PCI_SOFTINT0_MASK ;
    }

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

  • @func PCI_isrThread
  • @desc thread to service PCI ISR.
  • @modif None.
  • ============================================================================
    */

void * PCI_isrThread(void *arg)
{

Uint32 privity_err;
Uint32 loop=1;
Uint32 status;
struct sigevent event;

/* Tell the kernel to attach an interrupt signal event to this thread */
memset(&event,0,sizeof(event));
event.sigev_notify = SIGEV_INTR;

/* Give this thread root permissions to access the hardware */
privity_err = ThreadCtl(_NTO_TCTL_IO, 0 );
if ( privity_err == -1 )
{
	printf( "Can't get root permissions\n" );
	return -1;
}


IntrId = InterruptAttachEvent( inf.Irq, &event, _NTO_INTR_FLAGS_TRK_MSK );
		
if ( IntrId == -1 )
{
	printf( "Couldn't attach event to IRQ %d\n", inf.Irq );
	return EXIT_FAILURE;
}

while (1)
{
	/* Sleep until the next interrupt */
	InterruptWait( 0, NULL );
	//printf("<<Interrupt>>\n");
	//look at the hardware to check whether interrupt is generated     

	HAL_CheckPciInterrupt();
	HAL_PciClearDspInterrupt();

	/* Reenable this interrupt */
	InterruptUnmask( inf.Irq, IntrId );
	loop=0;

}

// Detach interrupt
 if( InterruptDetach( IntrId ) == -1 )
 {
    printf("%s: Interrupt detach failed <%s>", __FUNCTION__, strerror(errno));
 }

}[/code]

Thanks
Rama.

The code calls the function HAL_CheckPciInterrupt() but it’s useless since it does nothing with the result.

You should only call HAL_PciClearDSPInterrupt and InterruptUnmask if the source of the interrupt is the DSP Card.

Also once you processed and cleared the interrupt you should call HAL_PciCheckPciInterrupt() again to check if another interrupt is pending. And while you are at it you can add some logic to check if something is going wrong with the card. For example if there is 10 interrupts back to back well something must be wrong and you can then disable the card all together.

What mario said, and I’d add. Do not use an interrupt event but a pulse. An interrupt event can not convey priority, and you can only wait on an interrupt event with InterruptWait. A design that uses pulses and MsgReceive is far more flexible and debuggable (for example it is a trivial matter to write a utility that can inject synthetic interrupts by sending a pulse).

Hi,

After a long try, When we changed the PCI slot for the board, the same code started working!!

Thanks for all.

Rama.

The message receive stuff works but it does add latency… I dont have any current benchmarks but I’m developing on a 700 mhz target platform. wont the message passing make the system ‘unusable’?