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);
}