Module Name: xsrc
Committed By: macallan
Date: Thu Jul 9 19:27:08 UTC 2009
Modified Files:
xsrc/external/mit/libpciaccess/dist/src: netbsd_pci.c
Log Message:
teack libpciaccess how to discover and map PCI devices on machines with
more than one host bridge. While there get rid of some local (re)defines
if PCI-related constants.
With this Xorg should be able to use any PCI graphics device, no matter
if it's console or not.
TODO:
- cleanup
- deal with IO spaces
- fix Xorg -configure
To generate a diff of this commit:
cvs rdiff -u -r1.3 -r1.4 xsrc/external/mit/libpciaccess/dist/src/netbsd_pci.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: xsrc/external/mit/libpciaccess/dist/src/netbsd_pci.c
diff -u xsrc/external/mit/libpciaccess/dist/src/netbsd_pci.c:1.3 xsrc/external/mit/libpciaccess/dist/src/netbsd_pci.c:1.4
--- xsrc/external/mit/libpciaccess/dist/src/netbsd_pci.c:1.3 Fri Jul 3 21:03:50 2009
+++ xsrc/external/mit/libpciaccess/dist/src/netbsd_pci.c Thu Jul 9 19:27:08 2009
@@ -1,6 +1,7 @@
/*
* Copyright (c) 2008 Juan Romero Pardines
* Copyright (c) 2008 Mark Kettenis
+ * Copyright (c) 2009 Michael Lorenz
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -43,22 +44,50 @@
#include "pciaccess.h"
#include "pciaccess_private.h"
-#define PCIR_COMMAND 0x04
-#define PCIM_CMD_PORTEN 0x0001
-#define PCIM_CMD_MEMEN 0x0002
-#define PCIR_BIOS 0x30
-#define PCIM_BIOS_ENABLE 0x01
-#define PCIM_BIOS_ADDR_MASK 0xfffff800
-
-static int pcifd;
+typedef struct _pcibus {
+ int fd; /* /dev/pci* */
+ int num; /* bus number */
+ int maxdevs; /* maximum number of devices */
+} PciBus;
+
+static PciBus buses[32]; /* indexed by pci_device.domain */
+static int nbuses = 0; /* number of buses found */
+
+/*
+ * NetBSD's userland has a /dev/pci* entry for each bus but userland has no way
+ * to tell if a bus is a subordinate of another one or if it's on a different
+ * host bridge. On some architectures ( macppc for example ) all root buses have
+ * bus number 0 but on sparc64 for example the two roots in an Ultra60 have
+ * different bus numbers - one is 0 and the other 128.
+ * With each /dev/pci* we can map everything on the same root and we can also
+ * see all devices on the same root, trying to do that causes problems though:
+ * - since we can't tell which /dev/pci* is a subordinate we would find some
+ * devices more than once
+ * - we would have to guess subordinate bus numbers which is a waste of time
+ * since we can ask each /dev/pci* for its bus number so we can scan only the
+ * buses we know exist, not all 256 which may exist in each domain.
+ * - some bus_space_mmap() methods may limit mappings to address ranges which
+ * belong to known devices on that bus only.
+ * Each host bridge may or may not have its own IO range, to avoid guesswork
+ * here each /dev/pci* will let userland map its appropriate IO range at
+ * PCI_MAGIC_IO_RANGE if defined in <machine/param.h>
+ * With all this we should be able to use any PCI graphics device on any PCI
+ * bus on any architecture as long as Xorg has a driver, without allowing
+ * arbitrary mappings via /dev/mem and without userland having to know or care
+ * about translating bus addresses to physical addresses or the other way
+ * around.
+ */
static int
-pci_read(int bus, int dev, int func, uint32_t reg, uint32_t *val)
+pci_read(int domain, int bus, int dev, int func, uint32_t reg, uint32_t *val)
{
uint32_t rval;
- if (pcibus_conf_read(pcifd, (unsigned int)bus, (unsigned int)dev,
- (unsigned int)func, reg, &rval) == -1)
+ if ((domain < 0) || (domain > nbuses))
+ return -1;
+
+ if (pcibus_conf_read(buses[domain].fd, (unsigned int)bus,
+ (unsigned int)dev, (unsigned int)func, reg, &rval) == -1)
return (-1);
*val = rval;
@@ -67,18 +96,25 @@
}
static int
-pci_write(int bus, int dev, int func, uint32_t reg, uint32_t val)
+pci_write(int domain, int bus, int dev, int func, uint32_t reg, uint32_t val)
{
- return pcibus_conf_write(pcifd, (unsigned int)bus, (unsigned int)dev,
- (unsigned int)func, reg, val);
+
+ if ((domain < 0) || (domain > nbuses))
+ return -1;
+
+ return pcibus_conf_write(buses[domain].fd, (unsigned int)bus,
+ (unsigned int)dev, (unsigned int)func, reg, val);
}
static int
-pci_nfuncs(int bus, int dev)
+pci_nfuncs(int domain, int bus, int dev)
{
uint32_t hdr;
- if (pci_read(bus, dev, 0, PCI_BHLC_REG, &hdr) != 0)
+ if ((domain < 0) || (domain > nbuses))
+ return -1;
+
+ if (pci_read(domain, bus, dev, 0, PCI_BHLC_REG, &hdr) != 0)
return -1;
return (PCI_HDRTYPE_MULTIFN(hdr) ? 8 : 1);
@@ -93,18 +129,14 @@
struct mtrr m;
int n = 1;
#endif
- int prot, fd, ret = 0;
+ int prot, ret = 0;
prot = PROT_READ;
if (map->flags & PCI_DEV_MAP_FLAG_WRITABLE)
prot |= PROT_WRITE;
-
- fd = open("/dev/mem", O_RDWR);
- if (fd == -1)
- return errno;
- map->memory = mmap(NULL, map->size, prot, MAP_SHARED, fd,
- (off_t)map->base);
+ map->memory = mmap(NULL, map->size, prot, MAP_SHARED,
+ buses[dev->domain].fd, (off_t)map->base);
if (map->memory == MAP_FAILED)
return errno;
@@ -128,8 +160,6 @@
}
#endif
- close(fd);
-
return ret;
}
@@ -168,9 +198,9 @@
reg = (u_int)(offset & ~0x3);
- if ((pcibus_conf_read(pcifd, (unsigned int)dev->bus,
- (unsigned int)dev->dev, (unsigned int)dev->func,
- reg, &rval)) == -1)
+ if ((pcibus_conf_read(buses[dev->domain].fd,
+ (unsigned int)dev->bus, (unsigned int)dev->dev,
+ (unsigned int)dev->func, reg, &rval)) == -1)
return errno;
rval = htole32(rval);
@@ -201,9 +231,9 @@
reg = (u_int)offset;
memcpy(&val, data, 4);
- if ((pcibus_conf_write(pcifd, (unsigned int)dev->bus,
- (unsigned int)dev->dev, (unsigned int)dev->func,
- reg, val)) == -1)
+ if ((pcibus_conf_write(buses[dev->domain].fd,
+ (unsigned int)dev->bus, (unsigned int)dev->dev,
+ (unsigned int)dev->func, reg, val)) == -1)
return errno;
offset += 4;
@@ -218,7 +248,11 @@
static void
pci_system_netbsd_destroy(void)
{
- close(pcifd);
+ int i;
+
+ for (i = 0; i < nbuses; i++) {
+ close(buses[i].fd);
+ }
free(pci_sys);
pci_sys = NULL;
}
@@ -231,13 +265,14 @@
struct pci_mem_region *region;
uint64_t reg64, size64;
uint32_t bar, reg, size;
- int bus, dev, func, err;
+ int bus, dev, func, err, domain;
+ domain = device->domain;
bus = device->bus;
dev = device->dev;
func = device->func;
- err = pci_read(bus, dev, func, PCI_BHLC_REG, ®);
+ err = pci_read(domain, bus, dev, func, PCI_BHLC_REG, ®);
if (err)
return err;
@@ -248,16 +283,16 @@
region = device->regions;
for (bar = PCI_MAPREG_START; bar < PCI_MAPREG_END;
bar += sizeof(uint32_t), region++) {
- err = pci_read(bus, dev, func, bar, ®);
+ err = pci_read(domain, bus, dev, func, bar, ®);
if (err)
return err;
/* Probe the size of the region. */
- err = pci_write(bus, dev, func, bar, (unsigned int)~0);
+ err = pci_write(domain, bus, dev, func, bar, (unsigned int)~0);
if (err)
return err;
- pci_read(bus, dev, func, bar, &size);
- pci_write(bus, dev, func, bar, reg);
+ pci_read(domain, bus, dev, func, bar, &size);
+ pci_write(domain, bus, dev, func, bar, reg);
if (PCI_MAPREG_TYPE(reg) == PCI_MAPREG_TYPE_IO) {
region->is_IO = 1;
@@ -280,17 +315,17 @@
bar += sizeof(uint32_t);
- err = pci_read(bus, dev, func, bar, ®);
+ err = pci_read(domain, bus, dev, func, bar, ®);
if (err)
return err;
reg64 |= (uint64_t)reg << 32;
- err = pci_write(bus, dev, func, bar,
+ err = pci_write(domain, bus, dev, func, bar,
(unsigned int)~0);
if (err)
return err;
- pci_read(bus, dev, func, bar, &size);
- pci_write(bus, dev, func, bar,
+ pci_read(domain, bus, dev, func, bar, &size);
+ pci_write(domain, bus, dev, func, bar,
(unsigned int)(reg64 >> 32));
size64 |= (uint64_t)size << 32;
@@ -339,24 +374,26 @@
rom_base = priv->rom_base;
rom_size = dev->rom_size;
pci_rom = 1;
- if ((pcibus_conf_read(pcifd, (unsigned int)dev->bus,
+ if ((pcibus_conf_read(buses[dev->domain].fd, (unsigned int)dev->bus,
(unsigned int)dev->dev, (unsigned int)dev->func,
- PCIR_COMMAND, &command_val)) == -1)
+ PCI_COMMAND_STATUS_REG, &command_val)) == -1)
return errno;
- if ((command_val & PCIM_CMD_MEMEN) == 0) {
- if ((pcibus_conf_write(pcifd, (unsigned int)dev->bus,
- (unsigned int)dev->dev, (unsigned int)dev->func,
- PCIR_COMMAND, command_val | PCIM_CMD_MEMEN)) == -1)
+ if ((command_val & PCI_COMMAND_MEM_ENABLE) == 0) {
+ if ((pcibus_conf_write(buses[dev->domain].fd,
+ (unsigned int)dev->bus, (unsigned int)dev->dev,
+ (unsigned int)dev->func, PCI_COMMAND_STATUS_REG,
+ command_val | PCI_COMMAND_MEM_ENABLE)) == -1)
return errno;
}
- if ((pcibus_conf_read(pcifd, (unsigned int)dev->bus,
+ if ((pcibus_conf_read(buses[dev->domain].fd, (unsigned int)dev->bus,
(unsigned int)dev->dev, (unsigned int)dev->func,
- PCIR_BIOS, &bios_val)) == -1)
+ PCI_MAPREG_ROM, &bios_val)) == -1)
return errno;
- if ((bios_val & PCIM_BIOS_ENABLE) == 0) {
- if ((pcibus_conf_write(pcifd, (unsigned int)dev->bus,
+ if ((bios_val & PCI_MAPREG_ROM_ENABLE) == 0) {
+ if ((pcibus_conf_write(buses[dev->domain].fd,
+ (unsigned int)dev->bus,
(unsigned int)dev->dev, (unsigned int)dev->func,
- PCIR_BIOS, bios_val | PCIM_BIOS_ENABLE)) == -1)
+ PCI_MAPREG_ROM, bios_val | PCI_MAPREG_ROM_ENABLE)) == -1)
return errno;
}
}
@@ -380,16 +417,18 @@
close(memfd);
if (pci_rom) {
- if ((command_val & PCIM_CMD_MEMEN) == 0) {
- if ((pcibus_conf_write(pcifd, (unsigned int)dev->bus,
+ if ((command_val & PCI_COMMAND_MEM_ENABLE) == 0) {
+ if ((pcibus_conf_write(buses[dev->domain].fd,
+ (unsigned int)dev->bus,
(unsigned int)dev->dev, (unsigned int)dev->func,
- PCIR_COMMAND, command_val)) == -1)
+ PCI_COMMAND_STATUS_REG, command_val)) == -1)
return errno;
}
- if ((bios_val & PCIM_BIOS_ENABLE) == 0) {
- if ((pcibus_conf_write(pcifd, (unsigned int)dev->bus,
+ if ((bios_val & PCI_MAPREG_ROM_ENABLE) == 0) {
+ if ((pcibus_conf_write(buses[dev->domain].fd,
+ (unsigned int)dev->bus,
(unsigned int)dev->dev, (unsigned int)dev->func,
- PCIR_BIOS, bios_val)) == -1)
+ PCI_MAPREG_ROM, bios_val)) == -1)
return errno;
}
}
@@ -413,27 +452,30 @@
pci_system_netbsd_create(void)
{
struct pci_device_private *device;
- int bus, dev, func, ndevs, nfuncs;
+ int bus, dev, func, ndevs, nfuncs, domain, pcifd;
uint32_t reg;
-
- pcifd = open("/dev/pci0", O_RDWR);
- if (pcifd == -1)
- return ENXIO;
+ char devname[32];
+ struct pciio_businfo businfo;
pci_sys = calloc(1, sizeof(struct pci_system));
- if (pci_sys == NULL) {
- close(pcifd);
- return ENOMEM;
- }
pci_sys->methods = &netbsd_pci_methods;
ndevs = 0;
- for (bus = 0; bus < 256; bus++) {
- for (dev = 0; dev < 32; dev++) {
- nfuncs = pci_nfuncs(bus, dev);
+ nbuses = 0;
+ snprintf(devname, 32, "/dev/pci%d", nbuses);
+ pcifd = open(devname, O_RDWR);
+ while (pcifd > 0) {
+ ioctl(pcifd, PCI_IOC_BUSINFO, &businfo);
+ buses[nbuses].fd = pcifd;
+ buses[nbuses].num = bus = businfo.busno;
+ buses[nbuses].maxdevs = businfo.maxdevs;
+ domain = nbuses;
+ nbuses++;
+ for (dev = 0; dev < businfo.maxdevs; dev++) {
+ nfuncs = pci_nfuncs(domain, bus, dev);
for (func = 0; func < nfuncs; func++) {
- if (pci_read(bus, dev, func, PCI_ID_REG,
+ if (pci_read(domain, bus, dev, func, PCI_ID_REG,
®) != 0)
continue;
if (PCI_VENDOR(reg) == PCI_VENDOR_INVALID ||
@@ -443,37 +485,43 @@
ndevs++;
}
}
+ snprintf(devname, 32, "/dev/pci%d", nbuses);
+ pcifd = open(devname, O_RDWR);
}
pci_sys->num_devices = ndevs;
pci_sys->devices = calloc(ndevs, sizeof(struct pci_device_private));
if (pci_sys->devices == NULL) {
+ int i;
+
+ for (i = 0; i < nbuses; i++)
+ close(buses[i].fd);
free(pci_sys);
- close(pcifd);
return ENOMEM;
}
device = pci_sys->devices;
- for (bus = 0; bus < 256; bus++) {
- for (dev = 0; dev < 32; dev++) {
- nfuncs = pci_nfuncs(bus, dev);
+ for (domain = 0; domain < nbuses; domain++) {
+ bus = buses[domain].num;
+ for (dev = 0; dev < buses[domain].maxdevs; dev++) {
+ nfuncs = pci_nfuncs(domain, bus, dev);
for (func = 0; func < nfuncs; func++) {
- if (pci_read(bus, dev, func, PCI_ID_REG,
- ®) != 0)
+ if (pci_read(domain, bus, dev, func,
+ PCI_ID_REG, ®) != 0)
continue;
if (PCI_VENDOR(reg) == PCI_VENDOR_INVALID ||
PCI_VENDOR(reg) == 0)
continue;
- device->base.domain = 0;
+ device->base.domain = domain;
device->base.bus = bus;
device->base.dev = dev;
device->base.func = func;
device->base.vendor_id = PCI_VENDOR(reg);
device->base.device_id = PCI_PRODUCT(reg);
- if (pci_read(bus, dev, func, PCI_CLASS_REG,
- ®) != 0)
+ if (pci_read(domain, bus, dev, func,
+ PCI_CLASS_REG, ®) != 0)
continue;
device->base.device_class =
@@ -481,8 +529,8 @@
PCI_SUBCLASS(reg) << 8;
device->base.revision = PCI_REVISION(reg);
- if (pci_read(bus, dev, func, PCI_SUBSYS_ID_REG,
- ®) != 0)
+ if (pci_read(domain, bus, dev, func,
+ PCI_SUBSYS_ID_REG, ®) != 0)
continue;
device->base.subvendor_id = PCI_VENDOR(reg);