Writing device drivers: How to access a specific memory area?
Andre Albsmeier
Andre.Albsmeier at siemens.com
Sun Dec 28 02:54:04 PST 2008
On Thu, 25-Dec-2008 at 13:57:00 +0000, Rui Paulo wrote:
>
> On 25 Dec 2008, at 09:53, Andre Albsmeier wrote:
>
> > Hello all,
> >
> > I am writing a driver which needs to access memory at a
> > specific location. The location depends on what the BIOS
> > has configured into the host bridge. For example, my
> > current machine uses an Intel 975X chipset and the memory
> > location I am interested in has been set to 0xFED14000 and
> > is 16KB in size (this is MCHBAR of the 975X memory hub).
>
> You probably just need to do something like:
>
> rid = PCI_BAR(number);
> res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE);
The problem was, that this memory belongs to acpi0
so I couldn't read it from my driver which has no
resources assigned to it. But, I found a way, see below...
>
> And then,
> bus_read_4(res, offset from specified PCI BAR);
>
> >
> >
> > I have no idea how to access this space from my driver.
> > I have played around with bus_alloc_resource() but this
> > only gives me back NULL.
> >
> > However, a devinfo -r gives me:
> >
> > nexus0
> > npx0
> > acpi0
> > Interrupt request lines:
> > 9
> > I/O ports:
> > 0x10-0x1f
> > ...
> > 0x800-0x87f
> > I/O memory addresses:
> > 0x0-0x9ffff
> > 0xc0000-0xdffff
> > 0xe0000-0xfffff
> > 0x100000-0x7fffffff
> > 0xf0000000-0xf3ffffff
> > 0xfec00000-0xfec00fff
> > 0xfed13000-0xfed19fff <---
> > 0xfed1c000-0xfed1ffff
> > 0xfed20000-0xfed3ffff
> > 0xfed50000-0xfed8ffff
> > 0xfee00000-0xfee00fff
> > 0xffb00000-0xffbfffff
> > 0xfff00000-0xffffffff
> > cpu0
> > ...
> >
> > The line marked with <--- shows the range which includes
> > the location I am interested in. It is probably assigned
> > to the acpi0 device.
> >
> > How do I proceed from this? Do I have to hack around in
> > the ACPI-Code? I don't hope so ;-)
>
> You'll probably need to create a fake ACPI child driver to access it.
>
>
> Create your identify routine with something like:
>
> static void mydriver_identify(driver_t *driver, device_t parent)
> {
> if (device_find_child(parent, "mydriver", -1) == NULL &&
> mydriver_match(parent))
> device_add_child(parent, "mydriver", -1);
> }
>
> mydriver_match() should check if you were given the acpi0 device.
Found something easier: I just do a bus_set_resource() followed
by bus_alloc_resource_any(), access my host bridge registers,
and free things with bus_release_resource() followed by
bus_delete_resource().
>
>
> >
> >
> > I only need access to this memory location during the
> > probe of my driver to read some configuration data.
>
> Is this pci configuration space ? If so, pci_read_config (man 9 pci)
Unfortunately not. As I wrote, it is a 16k memory window
where the 975x maps a part of its config registers. The
address of this window can be read by pci_read_config( dev, 0x44, 4 ).
Then you can access the bridge's cXdrcY registers through
this memory window which I needed to determine the
machines RAM layout.
Thanks anyway for your help,
-Andre
More information about the freebsd-hackers
mailing list