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