bus_alloc_resource question

M. Warner Losh imp at bsdimp.com
Mon Jul 26 20:55:34 PDT 2004


In message: <20040727015923.GA63284 at cre85086tuf.rose.agilent.com>
            Chuck Tuffli <chuck_tuffli at agilent.com> writes:
: I'm having some trouble adding a bus resource and am hoping someone
: can point out where I goofed.
: 
: The host bus to a new x86 chipset has a memory mapped region in PCI
: space that provides access to status and control registers. For a
: driver to get access to this region, I figured it should call
: bus_alloc_resource() the same as for any other memory mapped region.
: This currently doesn't "just work" as the region is not a part of any
: device's BARs. To add this region as a resource, I used
: bus_set_resource()
: 
:     device_t dev;
:     uint32_t e_mem = 0xe0000000;
:     struct resource *ecfg_res;
: 
:     dev = pci_find_device(PCI_VENDOR_INTEL, ...);
:     bus_set_resource(dev, SYS_RES_MEMORY, e_mem, 0xe0000000, 0x10000000);
: 
: but a subsequent call to bus_alloc_resource() returns NULL
: 
:     ecfg_res = bus_alloc_resource(dev, SYS_RES_MEMORY, &e_mem,
:             0, ~0, 1, RF_ACTIVE | RF_SHAREABLE);
: 
: A call to bus_get_resource() shows that the resource did get set as
: the call returns the correct starting address and count. Is there
: something else that needs to happen between the set and the alloc? Is
: this even the correct approach? Thanks in advance!

Generally, one doesn't need to set the resource value.  Doing so
usually indicates the presence of some bug in the system.  Also, just
because you set a value doesn't mean that it will be honored.  It is
entirely possible that you picked a bogus resource and the system
can't give it to you.  The reasons for this are many: it could be in
use by another device, it could be that it exceeds the range of the
resource, it could be that it failed sanity checks.  On the PCI bus,
these sanity checks include 'can the address make it through the
bridges between it and the host bridge'.  If the answer is no, you'll
not be able to allocate things.  I'd just remove the bus_set_resource
entirely.  It is almost never needed for pci drivers.

There is a bug in your code however:

:     uint32_t e_mem = 0xe0000000;
:     ecfg_res = bus_alloc_resource(dev, SYS_RES_MEMORY, &e_mem,
:             0, ~0, 1, RF_ACTIVE | RF_SHAREABLE);

The third argument is the rid.  For the PCI bus, this is the offset in
the config space of the BAR you wish to map/allocate.  0xe0000000 is
not a valid offset into the config space.  Numbers like 0x10 and 0x14
are valid offsets.  Chances are this is the source of your problems.
You may wish to remove the RF_SHAREABLE as well, since most device
drivers aren't designed to share access to their hardware with other
devices.

Warner



More information about the freebsd-hackers mailing list