pci: Port xf86MapLegacyIO to pciaccess

Per-domain I/O is now something drivers must manually request, and must
keep track of within their own state rather than in the ScrnInfoRec.
It's not really possible to split that into two steps without an
additional intermediate ABI break, so don't even try.  Drivers that want
source compatibility should ifdef on the presence of xf86UnmapLegacyIO.

As a fringe benefit, domain-aware I/O is now OS-independent, relying
only on support in pciaccess.  Simplify OS PCI setup to reflect this.

The IOADDRESS type is kept around to help drivers through the API
transition and will be removed at some point in the future.

Reviewed-by: Jeremy Huddleston <jeremyhu@apple.com>
Tested-by: Jeremy Huddleston <jeremyhu@apple.com>
Signed-off-by: Adam Jackson <ajax@redhat.com>
Reviewed-by: Jamey Sharp <jamey@minilop.net>
This commit is contained in:
Adam Jackson 2011-09-16 13:33:04 -04:00 committed by Jeremy Huddleston
parent 6d9efdce0d
commit 858fbbb40d
9 changed files with 22 additions and 157 deletions

View File

@ -308,7 +308,6 @@ xf86AddEntityToScreen(ScrnInfoPtr pScrn, int entityIndex)
pScrn->entityInstanceList = xnfrealloc(pScrn->entityInstanceList,
pScrn->numEntities * sizeof(int));
pScrn->entityInstanceList[pScrn->numEntities - 1] = 0;
pScrn->domainIOBase = xf86Entities[entityIndex]->domainIO;
}
void

View File

@ -58,7 +58,6 @@ typedef struct {
DevUnion * entityPrivates;
int numInstances;
GDevPtr * devices;
IOADDRESS domainIO;
} EntityRec, *EntityPtr;
#define ACCEL_IS_SHARABLE 0x100

View File

@ -235,11 +235,6 @@ xf86ClaimPciSlot(struct pci_device * d, DriverPtr drvp,
xf86AddDevToEntity(num, dev);
pciSlotClaimed = TRUE;
if (active) {
/* Map in this domain's I/O space */
p->domainIO = xf86MapLegacyIO(d);
}
return num;
} else
return -1;
@ -1357,3 +1352,15 @@ xf86PciConfigureNewDev(void *busData, struct pci_device *pVideo,
if (*chipset < 0)
*chipset = (pVideo->vendor_id << 16) | pVideo->device_id;
}
struct pci_io_handle *
xf86MapLegacyIO(struct pci_device *dev)
{
return pci_legacy_open_io(dev, 0, 64 * 1024);
}
void
xf86UnmapLegacyIO(struct pci_device *dev, struct pci_io_handle *handle)
{
pci_device_close_io(dev, handle);
}

View File

@ -742,7 +742,6 @@ typedef struct _ScrnInfoRec {
unsigned long biosBase; /* Base address of video BIOS */
unsigned long memPhysBase; /* Physical address of FB */
unsigned long fbOffset; /* Offset of FB in the above */
IOADDRESS domainIOBase; /* Domain I/O base address */
int memClk; /* memory clock */
int textClockFreq; /* clock of text mode */
Bool flipPixels; /* swap default black/white */

View File

@ -140,7 +140,7 @@ xf86scanpci(void)
success = (pci_system_init() == 0);
/* choose correct platform/OS specific PCI init routine */
ARCH_PCI_INIT();
osPciInit();
return success;
}

View File

@ -137,20 +137,14 @@
#define PCI_BUS_NO_DOMAIN(bus) ((bus) & 0xffu)
#define PCI_TAG_NO_DOMAIN(tag) ((tag) & 0x00ffff00u)
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || \
#if defined(linux)
#define osPciInit(x) do {} while (0)
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || \
defined(__OpenBSD__) || defined(__NetBSD__) || \
defined(__DragonFly__) || defined(__sun) || defined(__GNU__)
#define ARCH_PCI_INIT bsdPciInit
#endif
#if defined(linux)
#define ARCH_PCI_INIT linuxPciInit
#endif /* defined(linux) */
#ifndef ARCH_PCI_INIT
extern void osPciInit(void);
#else
#error No PCI support available for this architecture/OS combination
#endif
extern void ARCH_PCI_INIT(void);
#endif /* _PCI_H */

View File

@ -55,15 +55,8 @@ xf86MapDomainMemory(int ScreenNum, int Flags, struct pci_device *dev,
return xf86MapVidMem(ScreenNum, Flags, Base, Size);
}
IOADDRESS
xf86MapLegacyIO(struct pci_device *dev)
{
(void)dev;
return 0;
}
void
bsdPciInit(void)
osPciInit(void)
{
xf86InitVidMem();
}

View File

@ -52,21 +52,6 @@
#include "xf86_OSlib.h"
#include "Pci.h"
static const struct pci_id_match match_host_bridge = {
PCI_MATCH_ANY, PCI_MATCH_ANY, PCI_MATCH_ANY, PCI_MATCH_ANY,
(PCI_CLASS_BRIDGE << 16) | (PCI_SUBCLASS_BRIDGE_HOST << 8),
0x0000ffff00, 0
};
#define MAX_DOMAINS 257
static pointer DomainMmappedIO[MAX_DOMAINS];
void
linuxPciInit(void)
{
memset(DomainMmappedIO, 0, sizeof(DomainMmappedIO));
}
/**
* \bug
* The generation of the procfs file name for the domain != 0 case may not be
@ -153,15 +138,6 @@ linuxPciOpenFile(struct pci_device *dev, Bool write)
* functionality is almost, but not quite there yet. Alpha and other kernel
* ports to multi-domain architectures still need to implement this.
*
* This scheme is also predicated on the use of an IOADDRESS compatible type to
* designate I/O addresses. Although IOADDRESS is defined as an unsigned
* integral type, it is actually the virtual address of, i.e. a pointer to, the
* I/O port to access. And so, the inX/outX macros in "compiler.h" need to be
* #define'd appropriately (as is done on SPARC's).
*
* Another requirement to port this scheme to another multi-domain architecture
* is to add the appropriate entries in the pciControllerSizes array below.
*
* TO DO: Address the deleterious reaction some host bridges have to master
* aborts. This is already done for secondary PCI buses, but not yet
* for accesses to primary buses (except for the SPARC port, where
@ -223,67 +199,6 @@ get_parent_bridge(struct pci_device *dev)
return bridge;
}
/*
* This is ugly, but until I can extract this information from the kernel,
* it'll have to do. The default I/O space size is 64K, and 4G for memory.
* Anything else needs to go in this table. (PowerPC folk take note.)
*
* Note that Linux/SPARC userland is 32-bit, so 4G overflows to zero here.
*
* Please keep this table in ascending vendor/device order.
*/
static const struct pciSizes {
unsigned short vendor, device;
unsigned long io_size, mem_size;
} pciControllerSizes[] = {
{
PCI_VENDOR_SUN, PCI_CHIP_PSYCHO,
1U << 16, 1U << 31
},
{
PCI_VENDOR_SUN, PCI_CHIP_SCHIZO,
1U << 24, 1U << 31 /* ??? */
},
{
PCI_VENDOR_SUN, PCI_CHIP_SABRE,
1U << 24, (unsigned long)(1ULL << 32)
},
{
PCI_VENDOR_SUN, PCI_CHIP_HUMMINGBIRD,
1U << 24, (unsigned long)(1ULL << 32)
}
};
#define NUM_SIZES (sizeof(pciControllerSizes) / sizeof(pciControllerSizes[0]))
static const struct pciSizes *
linuxGetSizesStruct(const struct pci_device *dev)
{
static const struct pciSizes default_size = {
0, 0, 1U << 16, (unsigned long)(1ULL << 32)
};
int i;
/* Look up vendor/device */
if (dev != NULL) {
for (i = 0; i < NUM_SIZES; i++) {
if ((dev->vendor_id == pciControllerSizes[i].vendor)
&& (dev->device_id == pciControllerSizes[i].device)) {
return & pciControllerSizes[i];
}
}
}
/* Default to 64KB I/O and 4GB memory. */
return & default_size;
}
static __inline__ unsigned long
linuxGetIOSize(const struct pci_device *dev)
{
const struct pciSizes * const sizes = linuxGetSizesStruct(dev);
return sizes->io_size;
}
static pointer
linuxMapPci(int ScreenNum, int Flags, struct pci_device *dev,
ADDRESS Base, unsigned long Size, int mmap_ioctl)
@ -406,45 +321,3 @@ xf86MapDomainMemory(int ScreenNum, int Flags, struct pci_device *dev,
}
return addr;
}
/**
* Map I/O space in this domain
*
* Each domain has a legacy ISA I/O space. This routine will try to
* map it using the Linux sysfs legacy_io interface. If that fails,
* it'll fall back to using /proc/bus/pci.
*
* If the legacy_io interface \b does exist, the file descriptor (\c fd below)
* will be saved in the \c DomainMmappedIO array in the upper bits of the
* pointer. Callers will do I/O with small port numbers (<64k values), so
* the platform I/O code can extract the port number and the \c fd, \c lseek
* to the port number in the legacy_io file, and issue the read or write.
*
* This has no means of returning failure, so all errors are fatal
*/
IOADDRESS
xf86MapLegacyIO(struct pci_device *dev)
{
const int domain = dev->domain;
struct pci_device *bridge = get_parent_bridge(dev);
int fd;
if (domain >= MAX_DOMAINS)
FatalError("xf86MapLegacyIO(): domain out of range\n");
if (DomainMmappedIO[domain] == NULL) {
/* Permanently map all of I/O space */
fd = linuxOpenLegacy(bridge, "legacy_io");
if (fd < 0) {
DomainMmappedIO[domain] = linuxMapPci(-1, VIDMEM_MMIO, bridge,
0, linuxGetIOSize(bridge),
PCIIOC_MMAP_IS_IO);
}
else { /* legacy_io file exists, encode fd */
DomainMmappedIO[domain] = (pointer)(intptr_t)(fd << 24);
}
}
return (IOADDRESS)DomainMmappedIO[domain];
}

View File

@ -235,7 +235,7 @@
/* Primitive Types */
typedef unsigned long ADDRESS; /* Memory/PCI address */
typedef unsigned long IOADDRESS; /* Must be large enough for a pointer */
typedef unsigned long IOADDRESS _X_DEPRECATED; /* Must be large enough for a pointer */
typedef unsigned long PCITAG;
typedef enum {
@ -257,6 +257,7 @@ extern _X_EXPORT Bool xf86scanpci(void);
/* Domain access functions. Some of these probably shouldn't be public */
extern _X_EXPORT pointer xf86MapDomainMemory(int ScreenNum, int Flags, struct pci_device *dev,
ADDRESS Base, unsigned long Size);
extern _X_EXPORT IOADDRESS xf86MapLegacyIO(struct pci_device *dev);
extern _X_EXPORT struct pci_io_handle *xf86MapLegacyIO(struct pci_device *dev);
extern _X_EXPORT void xf86UnmapLegacyIO(struct pci_device *, struct pci_io_handle *);
#endif /* _XF86PCI_H */