Adolfo,

I am enclosing one of the drivers from RTiC-Lab
(http://www.rtic-lab.sourceforge.net).  I think that you would be most
interested at looking at the RTiC_init_AD_card function for your purposes.
This function queries the PCI bus until it finds both the PCI vendor number
and function number for the card that I am looking for.  You can actually
see both of these numbers for your card by typing "cat /proc/pci" and
looking for your card.

A second source of information is the pci.txt file that is included in the
Documentation directory in your linux kernel  source tree..

A third (and slightly dated) source is the "Linux Device Drivers" book by
Alessandro Rubini.

I hope that this helps.

-Edgar

Adolf Ahmad MS wrote:

> Dear All,
>
> I want to know "How to read/write data and interrupt handling through PCI
> bus using RTLinux ??".
>
> Adolfo
> -- [rtl] ---
> To unsubscribe:
> echo "unsubscribe rtl" | mail [EMAIL PROTECTED] OR
> echo "unsubscribe rtl <Your_email>" | mail [EMAIL PROTECTED]
> ---
> For more information on Real-Time Linux see:
> http://www.rtlinux.org/rtlinux/
/* RTiC Device driver for the Computer Boards DAS1200/JR */

/* Written by Edgar F. Hilton, Copyright 2000 */

#include <linux/pci.h>
#include "main.h"

/**********************************************************************\
             Some formal declarations and definitions 
\**********************************************************************/
#ifndef PCI_VENDOR_ID_CBOARDS
#define PCI_VENDOR_ID_CBOARDS  (0x1307) /* unique identifier for
                                           CBoards, already defined in
                                           linux/pci.h */
#endif

#define PCI_DEVICE_ID_DAS1200  (0x19)  /* unique identifier for board */
#define NUM_AD_PCI_DEVS        (8)     /* number of PCI devices to
                                          loop through*/
#define AD_GAIN                (2.5)   /* volts, software selectable
                                          via (AD_badr1+2) */
#define AD_DELAY_IOPORT                (0x80)  /* used to generate a 10us delay */   
#define AD_STARTUP_DELAY          (10)    /* number of microseconds to
                                          delay after initialization */

unsigned char adc_irq_line;    /* Interrupt line */
unsigned int AD_badr0; /* PCI control address, see DAS1200 manual */
unsigned int AD_badr1; /* DAS control address, see DAS1200 manual */
unsigned int AD_badr2; /* Data address, see DAS1200 manual */
unsigned int AD_badr3; /* FIFO, etc. control address, see DAS1200 manual */

/****************************************************************************\
      Initialize PCI-DAS1200 12 bit ADC device to desired operational
                                       mode.
\****************************************************************************/

int 
RTiC_init_AD_card(void)
{
  int index, config_word;
  int pci_index;
  unsigned char pci_bus,pci_device_fn,latency_timer,pci_irq_pin;
  unsigned short int data;
  static FLAG PCI_found=FALSE;  /* have we already found the card? */

  /* Locate the PCI device */
  if (pcibios_present() && (!PCI_found))
    {
      /* loop through all devices until we find our card */
      for (pci_index=0;pci_index<NUM_AD_PCI_DEVS;pci_index++)
        {
          printk("RTiC-Lab: Checking PCI Device %i\n",pci_index);
          /* do not do anything until we are certain that we are
             dealing with our card of interest */
          if (pcibios_find_device(PCI_VENDOR_ID_CBOARDS,
                                  PCI_DEVICE_ID_DAS1200,
                                  pci_index,&pci_bus,
                                  &pci_device_fn) 
              != PCIBIOS_SUCCESSFUL)
            {
              break;
            }
          printk("RTiC-Lab: Found DAS1200/jr as Device #%i\n",pci_index);


          /* 
             EXTRACT INTERRUPT INFOMATION, IN CASE WE EVER NEED IT
          */
          pcibios_read_config_byte(pci_bus,pci_device_fn,
                                   PCI_INTERRUPT_LINE,
                                   &adc_irq_line);
          pcibios_read_config_byte(pci_bus,pci_device_fn,
                                   PCI_INTERRUPT_PIN,
                                   &pci_irq_pin);
          pcibios_read_config_byte(pci_bus,pci_device_fn,
                                   PCI_LATENCY_TIMER,
                                   &latency_timer);
          if (latency_timer<32) 
              pcibios_write_config_byte(pci_bus,pci_device_fn,
                                        PCI_LATENCY_TIMER,32);

          /* 
             EXTRACT IO ADDRESSES
          */

          /* first extract the address of the PCI controller operation
             registers */
          pcibios_read_config_dword(pci_bus,pci_device_fn,
                                    PCI_BASE_ADDRESS_0,
                                    &AD_badr0);
          AD_badr0&=PCI_BASE_ADDRESS_IO_MASK;
          printk("RTiC: PCI AD control address = 0x%x\n",
                 AD_badr0);

          /* second, extract the address of the general control/status
             registers */
          pcibios_read_config_dword(pci_bus,pci_device_fn,
                                    PCI_BASE_ADDRESS_1,
                                    &AD_badr1);
          AD_badr1&=PCI_BASE_ADDRESS_IO_MASK;
          printk("RTiC: PCI AD General control address = 0x%x\n",
                 AD_badr1);
          
          /* third, extract the address of the ADC data, and FIFO
             clear registers */
          pcibios_read_config_dword(pci_bus,pci_device_fn,
                                    PCI_BASE_ADDRESS_2,
                                    &AD_badr2);
          AD_badr2&=PCI_BASE_ADDRESS_IO_MASK;
          printk("RTiC: PCI AD Data, FIFO Clear Register addresss = 0x%x\n",
                 AD_badr2);
          
          /* finally, extract the base address to the Pacer,
             Counter/Timer and DIO registers */
          pcibios_read_config_dword(pci_bus,pci_device_fn,
                                    PCI_BASE_ADDRESS_3,
                                    &AD_badr3);
          AD_badr3&=PCI_BASE_ADDRESS_IO_MASK;
          printk("RTiC: PCI AD Pacer, counter and DIO regs address = 0x%x\n",
                 AD_badr3);
          
          /* 
             FLAG OUR SUCCESS
          */
          PCI_found = TRUE;
          RTiC_message("(INIT) Found AD PCI board",RESET_STAT,SUPER_REG);
        }
    }

  /* OK, we have found our card.  Let's initialize it so that it
     behaves the way we want it to behave */
  if (PCI_found)
    {
      RTiC_message("(INIT) Testing AD PCI board",RESET_STAT,SUPER_REG);
      /*
        TEST STATUS 
      */
      data=INW(AD_badr1);
      if (data != 0x8000) 
        {
          RTiC_message("ADC-DAS1200/jr needs to be reset: please cycle power",
                       RESET_STAT,SUPER_REG);
        }

      data=INW(AD_badr1+2);
      if ((data&0x4000)==0) 
        {
          RTiC_message("ADC-DAS1200/JR is busy",
                       RESET_STAT,SUPER_REG);
        }
      
      /* 
         INITIALIZE THE DESIRED AD FEATURES
      */
      RTiC_message("(INIT) Configuring AD PCI board",RESET_STAT,SUPER_REG);
      OUTW(0x0000,AD_badr1+0); /* disable all ADC interrupts */
      OUTW(0x0000,AD_badr1+6); /* send zero to autocal register */
      OUTW(0x2001,AD_badr1+4); /* softw.trig+internal pacing */
      OUTW(0x0000,AD_badr2+2); /* Clear ADC FIFO */

      /* set the pacer source, bipolar mode, differential mode, 2.5V
         range, and high and low channels */
      config_word = 0x0200; /* sets bipolar, differential, 2.5V range */
      config_word 
        |= (NUM_CONTROL_INPUTS-1)<<4; /* sets the high channels,
                                         assuming low channel is zero */
      OUTW(config_word,AD_badr1+2); /* 2.5V bipolar inputs, SW convert */
      
      /* 
         DELAY DOING ANYTHING ELSE UNTIL A/D IS READY
      */
      for (index=0;index<AD_STARTUP_DELAY;index++)
        INB(AD_DELAY_IOPORT);  
    }


  return(RTIC_SUCCESS);
}


/****************************************************************************\
  Starts the conversion, wait till done, and return the latest adc value.
\****************************************************************************/
unsigned short int 
single_adc_sample(void)
{
  unsigned short int res;
  int timeout=100;
  int loop;
  
  OUTW(0x0000,AD_badr2);       
  for (loop=0;loop<timeout;loop++)
    {
      res=INW(AD_badr1+2);
      res=res&0x4000;
      if (res != 0) 
        {
          break;
        }
      if (loop==timeout-1)
        {
          if (!IO_DEBUG)  /* print stuff only when we are not doing I/O */
            printk("ADC conversion error.\n");
        }
    }
  res=INW(AD_badr2);
  return(res);
}

/****************************************************************************\
         Sample the voltages on the first NUM_CONTROL_INPUTS channels
         of the adc board.
\****************************************************************************/
void 
RTiC_AD2_run(void)
{
  int index2;
  for (index2=0;index2<NUM_CONTROL_INPUTS;index2++)
    *(RTiC_sensor+index2) = 
      ((float) single_adc_sample()/32768.0-1.0)*AD_GAIN;
}


/****************************************************************************\
                        Trigger AD conversions
\****************************************************************************/
void 
RTiC_AD1_run(void)
{
  /* do nothing for now */
}


/****************************************************************************\
                        Stop AD card
\****************************************************************************/
int RTiC_stop_AD_card(void)
{
  /* nothing special to do here */
  return(RTIC_SUCCESS);
}



Reply via email to