Re: PCI Driver - Read/Write to Base Address



elliotng.ee@xxxxxxxxx wrote:
I am trying to read and write to a PCI Base Address. Right now, I have:

static int rpm_probe(struct pci_dev *dev, const struct pci_device_id
*id)
{
pci_enable_device(dev);

u32 BaseAddress0;
pci_read_config_dword(dev, PCI_BASE_ADDRESS_0, &BaseAddress0);
printk(KERN_ALERT "PCI_BASE_ADDRESS_0: %x\n", BaseAddress0);
}


To read/write to that particular base address, do we just need to add
the following lines:
u32 BaseAddress0data;
pci_read_config_dword(dev, BaseAddress0, &BaseAddress0data);
pci_write_config_dword(dev, BaseAddress0, 0xFF000000);

or is there another pci function that I should use?

No, that's not correct, if I understand what you're doing.

First, you should get the base address value (for memory-mapped I/O
region 0) with:
int BarNumber = 0;
pci_request_region(dev, BarNumber, "MyDriverName");
BaseAddress0 = pci_resource_start(dev, BarNumber);
BarLen = pci_resource_len(dev, BarNumber);

This marks you as the owner of the region and returns to you its base
(physical) address and length.

Second, when you actually read or write the memory-mapped I/O in your
device, you don't use pci_read_config* / pci_write_config* -- those are
only used when you are reading / writing the device's *configuration
space registers*. Reading the memory-mapped I/O region is done
something like this:

char * Region0 = ioremap_nocache(BaseAddress0, BarLen);
Data = readl(Region0 + offsetToRead);
writel(DataToWrite, Region0 + offsetToRead);

ioremap_nocache creates a virtual-to-physical mapping in kernel address
space that you can use to access the device memory.

readl() and writel() are arch-specific macros that typically boil down
to something like this (however, you should still use them since there
may be slight variations between architectures):
unsigned long readl(void * addr) { return *((volatile unsigned long
*)addr)); }
void writel(unsigned long value, void * addr) { *((volatile unsigned
long *)addr) = value; }

You might want to check out the book "Linux Device Drivers, version 3"
which is available for free online. It has a chapter on PCI Drivers as
well as info on kernel memory management.

Also, check out the skeleton network driver in
/usr/src/linux/drivers/net/pci-skeleton.c for some sample code.

GH

.