simple question about accessing pci io registers

Prashant Shah pshah.mumbai at gmail.com
Tue May 17 02:46:30 EDT 2011


Hi,

I am trying to interface a PCI Data Acquisition card with Linux.
Vendor has been kind enough to provided us the internal register
specification which is very simple.

It uses two IO Address Spaces

The first address space is for reading and writing analog input (base
address register 2)

READ :
base + offset 0 : analog in conversion data
base + offset 1 : analog in conversion data
base + offset 2 : not used
base + offset 3 : not used

WRITE :
base + offset 0 : analog out conversion data
base + offset 1 : analog out conversion data
base + offset 2 : bit level : X X (2 bit select uni polar or bi polar)
(4 bit channel selection)
base + offset 3 : trigger

all transfers are 16 bit.

Sequence of operation is :
1. write to (WRITE + offset 2) = 0000
2. read from (READ + offset 0)

I am not able to get the reading from the device. It always shows 0x8000

I tried the same thing under windows using a PCI testing/sniffer tool
it works properly.

Please check the function  dyna_pci1050_read_proc

I dont know what I am doing wrong here. Is this the write way to
access PCI IO Ports ?


-------- CODE ----------

#include <linux/interrupt.h>
#include <linux/sched.h>
#include <linux/proc_fs.h>
#include <linux/pci.h>
#include <linux/delay.h>

#define PCI_VENDOR_ID_DYNALOG		0x10b5
#define PCI_DEVICE_ID_DYNALOG_PCI_1050	0x1050
#define DRV_NAME			"dyna_pci1050"

unsigned long iobase0, iobase1, iobase2, iobase3, iobase4, iobase5;

static int dyna_pci1050_read_proc(char *page, char **start, off_t
offset, int count, int *eof, void *data)
{
	u16 data16;

	printk(KERN_INFO "comedi: dyna_pci1050: %s\n", __func__);

	data16 = 0x0000;
	outw(iobase2 + 2, data16);
	mb(); udelay(100);
	data16 = inw(iobase2);
	printk(KERN_INFO "reading data from 0x%4lx : %x\n", iobase2, data16);
	return 0;
}

/************************* CONFIG FUNCTIONS ***********************************/

static int dyna_pci1050_probe(struct pci_dev *dev, const struct
pci_device_id *id)
{
	int counter = 0;
	unsigned long pci_resource;
	
	printk(KERN_INFO "comedi: dyna_pci1050: %s\n", __func__);

	pci_enable_device(dev);

	/* deivce related information */
        printk(KERN_ERR "comedi: dyna_pci1050: bus number %d\n",
dev->bus->number);
        printk(KERN_ERR "comedi: dyna_pci1050: device id %x\n", dev->device);
        printk(KERN_ERR "comedi: dyna_pci1050: vendor id %x\n", dev->vendor);
        printk(KERN_ERR "comedi: dyna_pci1050: slot number %d\n",
PCI_SLOT(dev->devfn));
        printk(KERN_ERR "comedi: dyna_pci1050: function number %d\n",
PCI_FUNC(dev->devfn));

	for (counter = 0; counter < 6; counter++) {
		pci_resource = pci_resource_start(dev, counter);
		printk(KERN_INFO "comedi: dyna_pci1050 : pci_resource_start : %d :
%016lX\n", counter, pci_resource);
		pci_resource = pci_resource_end(dev, counter);
		printk(KERN_INFO "comedi: dyna_pci1050 : pci_resource_end : %d :
%016lX\n", counter, pci_resource);
		pci_resource = pci_resource_flags(dev, counter);
		printk(KERN_INFO "comedi: dyna_pci1050 : pci_resource_flags : %d :
%016lX\n", counter, pci_resource);
	}

	iobase0 = pci_resource_start(dev, 0);
	iobase1 = pci_resource_start(dev, 1);
	iobase2 = pci_resource_start(dev, 2);
	iobase3 = pci_resource_start(dev, 3);
	iobase4 = pci_resource_start(dev, 4);
	iobase5 = pci_resource_start(dev, 5);

	printk(KERN_INFO "comedi: dyna_pci1050: iobase 0x%4lx : 0x%4lx :
0x%4lx : 0x%4lx : 0x%4lx : 0x%4lx\n",
		iobase0, iobase1, iobase2, iobase3, iobase4, iobase5);

	if (request_region(iobase1, 4, DRV_NAME))
		printk(KERN_INFO "comedi: dyna_pci1050: acquired iobase1 0x%4lx\n", iobase1);
	else
		printk(KERN_INFO "comedi: dyna_pci1050: failed acquiring iobase1
0x%4lx\n", iobase1);

	if (request_region(iobase2, 4, DRV_NAME))
		printk(KERN_INFO "comedi: dyna_pci1050: acquired iobase2 0x%4lx\n", iobase2);
	else
		printk(KERN_INFO "comedi: dyna_pci1050: failed acquiring iobase2
0x%4lx\n", iobase2);

	if (request_region(iobase3, 4, DRV_NAME))
		printk(KERN_INFO "comedi: dyna_pci1050: acquired iobase3 0x%4lx\n", iobase3);
	else
		printk(KERN_INFO "comedi: dyna_pci1050: failed acquiring iobase3
0x%4lx\n", iobase3);

	create_proc_read_entry("dynalog", 0, NULL, dyna_pci1050_read_proc, NULL);
	return 0;
}

static void dyna_pci1050_remove(struct pci_dev *dev)
{
	printk(KERN_INFO "comedi: dyna_pci1050: %s\n", __func__);

	release_region(iobase1, 4);
	release_region(iobase2, 4);
	release_region(iobase3, 4);

	remove_proc_entry("dynalog", NULL);
}

static struct pci_device_id ids[] = {
	{ PCI_DEVICE(PCI_VENDOR_ID_DYNALOG, PCI_DEVICE_ID_DYNALOG_PCI_1050) },
	{ 0, },
};

MODULE_DEVICE_TABLE(pci, dyna_pci1050_driver);

struct pci_driver dyna_pci1050_driver = {
	.name		= DRV_NAME,
	.probe		= dyna_pci1050_probe,
	.remove		= dyna_pci1050_remove,
	.id_table	= ids,
};

static int __init dyna_pci1050_init(void)
{
	printk(KERN_INFO "comedi: dyna_pci1050: %s\n", __func__);
	pci_register_driver(&dyna_pci1050_driver);
	return 0;
}

static void __exit dyna_pci1050_exit(void)
{
	printk(KERN_INFO "comedi: dyna_pci1050: %s\n", __func__);
	pci_unregister_driver(&dyna_pci1050_driver);
}

module_init(dyna_pci1050_init);
module_exit(dyna_pci1050_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Prashant Shah");



More information about the Kernelnewbies mailing list