Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 17 Mar 2010 08:40:57 -0400
From:      John Baldwin <jhb@freebsd.org>
To:        freebsd-arch@freebsd.org
Cc:        Cole <cole@opteqint.net>
Subject:   Re: PCI and Resouce question
Message-ID:  <201003170840.57911.jhb@freebsd.org>
In-Reply-To: <9f206d1a1003170250r2727a55ajb636a0bdf1a2f137@mail.gmail.com>
References:  <9f206d1a1003170250r2727a55ajb636a0bdf1a2f137@mail.gmail.com>

next in thread | previous in thread | raw e-mail | index | archive | help
On Wednesday 17 March 2010 5:50:14 am Cole wrote:
> Hi.
> 
> Sorry if this is not the correct list, I have tried posting to
> freebsd-hackers, and didnt get a response. Maybe im being stupid and
> not connecting something, or just not understanding, in which case
> sorry again.
> 
> What im trying to achieve is writing to a few registers/memory
> addresses for the memory location of BAR 0 for a pci card. I do not
> want to modify the drivers source code, since it might become
> unavailable sometime in the future. So what im looking to do is write
> another kernel module, that can obtain the cards device_t structure,
> as well as the resource structure of the card. My aim is to obtain the
> resource structure so that I can then obtain the bus_tag and
> bus_handle, and use those to write to the BAR 0 memory space.
> 
> My understanding is that I would use pci_find_device to obtain the
> device_t, then I think I can use bus_alloc_resource_any to obtain the
> resource, I see there used to be a bus_get_resource, but the man page
> for that no longer seems to exist, and references to it seem to have
> been removed. If there is another way or better way of doing this,
> please let me know. Also im not familiar with the specifics of
> bus_alloc_resouce_any, and I dont know if calling this function from
> another kernel module will give me the already allocated memory for
> this pci card, or will it create a new one and assign it to the BAR 0
> register on the card?

The PCI bus expects that only the driver calls bus_alloc_resource_any(), and 
that it only does this once.  bus_get_resource() does not return the actual 
'struct resource *r', so it will not do you any good.  If you know for certain 
that the existing driver has not called 'bus_alloc_resource_any()', then you 
can call it from your module.  Note that if the device driver is unloaded, the 
PCI bus may unmap the resource out from under your module (the PCI bus assumes 
that only the child device_t uses the resources, so it cleans up allocated 
resources when a driver unloads).

Really, the clean way to handle something like this is to have your new code 
to share the device_t with the other driver.  You can do this by using an 
approach similar to the vga_pci driver and changing the existing driver to 
attach to your device instead.  So long as you propogate/emulate the proper 
PCI and bus methods, the child device driver can work fine with only a one-
line change to add a new DRIVER_MODULE() that attaches to your device as the 
bus instead of pci.  For, example, if your driver creates 'foo0' devices and 
the existing driver is called 'bar', you would create a new line:

DRIVER_MODULE(bar, foo, ...);

where the rest of the fields are copied from the existing 'DRIVER_MODULE(bar, 
pci)' line.  Your foo driver will have to have a higher probe priority than 
the real driver, and you will have to load your driver before the real driver.  

Another alternative would be to make the real driver become the proxy driver.  
Attach your driver as a child of it.  You will have to add bus and PCI methods 
to the real driver to satisfy the needs of your device.  Mostly you just want 
this driver to have a custom methods for allocating resources where it shares 
a resource it has already allocated with your driver.

-- 
John Baldwin



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201003170840.57911.jhb>