libpciaccess problem with new IO interface

Michael Cree mcree at
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 
achieve that.

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 mailing list