libpciaccess problem with new IO interface
mcree at orcon.net.nz
Thu Feb 18 00:58:19 PST 2010
On 16/02/10 05:57, Adam Jackson wrote:
> On Sat, 2010-02-13 at 16:23 +1300, Michael Cree wrote:
>> The trouble with this implementation is that reading and writing the PCI
>> resource files in the Linux sysfs does not appear to be supported by the
>> kernel. Only memory mapping the resource files is supported.
> It depends on the architecture and the resource type.
> On x86, for I/O resources, only read/write are supported.
> On x86, for memory resources, only mmap() is currently supported.
Thanks for that. That explains quite a bit. Maybe I should step back to
explain what I am trying to solve which, in short, is to get the Xserver
going on old Alpha architectures that cannot do byte and word accesses
to I/O ports via dense memory. There's a special sparse mapping to
Now a specific example of that problem: The ati radeon video driver
memory maps the PCI resource at bar 2. It's a memory resource however
the way the radeon driver uses it it is quite clear that it is in fact
I/O ports. Writing to a location in that memory resource, for example,
does not guarantee a read will return the same value that was just
written. The radeon driver memory maps the resource using
pci_device_map_range() if libcpiaccess is available otherwise the old
xf86MapPciMem() interface is used. Then it uses the Xserver's
MMIO_IN/OUT routines defined in compiler.h for all accesses to the
memory mapped resource.
In the Xserver's xf86MapPciMem() routine on older Alpha architecture it
does two memory mappings - a dense one and a sparse one. The sparse map
lands at a fixed offset in memory from the dense one, and the
MMIO_IN/OUT routines use the dense mapping for longword or quadword
accesses, and the sparse mapping for word and byte accesses. The fixed
offset from the dense mapping to the sparse mapping is hard programmed
into the MMIO_IN/OUT routines so only the address of the dense mapping
is passed to them.
The libpciaccess's pci_device_map_range() routine doesn't do the dense
and sparse mappings. As a test I modified it so it would do both
mappings, and return only the dense mapping address to the caller.
Unfortunately, the sparse mapping done via the Linux sysfs is at a
different location to that which occurs with the old xf86MapPciMem()
interface. Hence when the radeon driver uses the old MMIO_IN/OUT
routines on the memory map it fails because there is nothing mapped at
the location where they expect to find the sparse map.
I wondered whether I could use the new pci_device_open_io() routines in
libpciaccess, but with my testing, and your description of the PCI
resources on the x86, it is clear that this is not going to work. The
resource at bar 2 on a radeon card, despite being used as "I/O ports",
is in fact a memory resource, and has to be memory mapped.
It's easy enough to get pci_device_map_range() to map both the dense and
the sparse mapping on the older Alphas (I have already implemented
that). The problem is getting the location of the sparse map, in
addition to the location of the dense map, returned back to the calling
video driver as pci_device_map_range() returns only one address and an
error code. Somehow the address of the sparse mapping has to be made
available to the Xserver's MMIO_IN/OUT routines. Any suggestions how?
One thought is to add an extra routine to libpciaccess that returns the
address of the sparse mapping of a previously mapped resource and NULL
if the sparce map doesn't exist. And in the video drivers that matter
for the older Alphas add, maybe within a #ifdef __alpha__ section, after
the call to pci_device_map_range(), a call to the new routine to get
the sparse mapping address and pass it to the Xserver to use with the
MMIO_IN/OUT routines. Thus the extra work to libpciaccess is minimal,
and the current interface is not broken in anyway, and only a couple or
so extra lines of code need to be added to video drivers of interest.
(Some minor modification to the Alpha specific code in the MMIO_IN/OUT
routines will also be needed.)
Thoughts? Other suggestions?
More information about the xorg-devel