Re: PCI Driver - Read/Write to Base Address
- From: "gil_hamilton@xxxxxxxxxxx" <gil_hamilton@xxxxxxxxxxx>
- Date: 23 Aug 2006 04:26:41 -0700
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
.
- Follow-Ups:
- Re: PCI Driver - Read/Write to Base Address
- From: elliotng . ee
- Re: PCI Driver - Read/Write to Base Address
- References:
- PCI Driver - Read/Write to Base Address
- From: elliotng . ee
- PCI Driver - Read/Write to Base Address
- Prev by Date: booting 2.6.13 kernel on ixp425 machine
- Next by Date: Re: PCI Driver - Read/Write to Base Address
- Previous by thread: PCI Driver - Read/Write to Base Address
- Next by thread: Re: PCI Driver - Read/Write to Base Address
- Index(es):