On Tue, 2008-03-11 at 22:30 +0100, Mark Kettenis wrote: > Here are the OpenBSD-specific bits for libpciaccess. As discussed > earlier on this list, there is a bit of a problem with xserver and > libpciaccess both needing to open /dev/xf86, which can only be opened > once. I implemented pci_system_init_dev_mem() like Ian suggested. > This requires some minor changes to the BSD-specific os-support code. > Since pci_system_init_dev_mem() is a no-op on FreeBSD this should be > no problem. Here are the xserver bits (the libpciaccess bits folow > below). > > > diff --git a/hw/xfree86/os-support/bsd/i386_video.c b/hw/xfree86/os-support/bsd/i386_video.c > index 0dcff66..7e4a4d2 100644 > --- a/hw/xfree86/os-support/bsd/i386_video.c > +++ b/hw/xfree86/os-support/bsd/i386_video.c > @@ -212,6 +212,9 @@ xf86OSInitVidMem(VidMemInfoPtr pVidMem) > pVidMem->mapMem = mapVidMem; > pVidMem->unmapMem = unmapVidMem; > > + if (useDevMem) > + pci_system_init_dev_mem(devMemFd); > + The changeset looks great, though I'd like to slip this hunk under #ifdef __OpenBSD__ or a version check so that non-OpenBSD doesn't have to catch up to libpciaccess from git to build. > #ifdef HAS_MTRR_SUPPORT > if (useDevMem) { > if (cleanMTRR()) { > diff --git a/hw/xfree86/os-support/bus/bsd_pci.c b/hw/xfree86/os-support/bus/bsd_pci.c > index bceb108..57ad09b 100644 > --- a/hw/xfree86/os-support/bus/bsd_pci.c > +++ b/hw/xfree86/os-support/bus/bsd_pci.c > @@ -81,4 +81,6 @@ bsdPciInit(void) > { > pciNumBuses = 1; > pciBusInfo[0] = &bsd_pci; > + > + xf86InitVidMem(); > } > diff --git a/hw/xfree86/utils/ioport/Makefile.am b/hw/xfree86/utils/ioport/Makefile.am > index c1f9453..12f8613 100644 > --- a/hw/xfree86/utils/ioport/Makefile.am > +++ b/hw/xfree86/utils/ioport/Makefile.am > @@ -37,7 +37,7 @@ ioport_CFLAGS = $(DIX_CFLAGS) $(XORG_CFLAGS) > ioport_LDADD = \ > ../../os-support/libxorgos.la \ > ../../dummylib/libdummy-nonserver.a \ > - ${UTILS_SYS_LIBS} > + ${UTILS_SYS_LIBS} ${PCIACCESS_LIBS} > > > ioport_SOURCES = \ > > > > Here are the libpciaccess bits. OpenBSD needs <sys/types.h to be > included before <sys/mman.h>. This should be no problem on any > POSIX-like system. Also, the endian-ness conversion macros on OpenBSD > are different than on FreeBSD. > > > diff --git a/configure.ac b/configure.ac > index 8f4e55d..6163577 100644 > --- a/configure.ac > +++ b/configure.ac > @@ -77,6 +77,9 @@ case $host_os in > *linux*) > linux=yes > ;; > + *openbsd*) > + openbsd=yes > + ;; > *solaris*) > solaris=yes > PCIACCESS_LIBS="$PCIACCESS_LIBS -ldevinfo" > @@ -85,6 +88,7 @@ esac > > AM_CONDITIONAL(LINUX, [test "x$linux" = xyes]) > AM_CONDITIONAL(FREEBSD, [test "x$freebsd" = xyes]) > +AM_CONDITIONAL(OPENBSD, [test "x$openbsd" = xyes]) > AM_CONDITIONAL(SOLARIS, [test "x$solaris" = xyes]) > > AC_CHECK_FILE([/usr/include/asm/mtrr.h], > diff --git a/include/pciaccess.h b/include/pciaccess.h > index dcc0122..3138877 100644 > --- a/include/pciaccess.h > +++ b/include/pciaccess.h > @@ -81,6 +81,8 @@ int pci_device_get_bridge_buses(struct pci_device *dev, int *primary_bus, > > int pci_system_init(void); > > +void pci_system_init_dev_mem(int fd); > + > void pci_system_cleanup(void); > > struct pci_device_iterator *pci_slot_match_iterator_create( > diff --git a/src/Makefile.am b/src/Makefile.am > index f370920..f60ccbd 100644 > --- a/src/Makefile.am > +++ b/src/Makefile.am > @@ -33,6 +33,10 @@ if FREEBSD > OS_SUPPORT = freebsd_pci.c > endif > > +if OPENBSD > +OS_SUPPORT = openbsd_pci.c > +endif > + > if SOLARIS > OS_SUPPORT = solx_devfs.c pci_tools.h > endif > diff --git a/src/common_init.c b/src/common_init.c > index 1092faf..7429518 100644 > --- a/src/common_init.c > +++ b/src/common_init.c > @@ -56,13 +56,22 @@ pci_system_init( void ) > err = pci_system_linux_sysfs_create(); > #elif defined(__FreeBSD__) > err = pci_system_freebsd_create(); > +#elif defined(__OpenBSD__) > + err = pci_system_openbsd_create(); > #elif defined(__sun) > - err = pci_system_solx_devfs_create(); > + err = pci_system_solx_devfs_create(); > #endif > > return err; > } > > +void > +pci_system_init_dev_mem(int fd) > +{ > +#ifdef __OpenBSD__ > + pci_system_openbsd_init_dev_mem(fd); > +#endif > +} > > /** > * Shutdown all access to the PCI subsystem. > diff --git a/src/common_interface.c b/src/common_interface.c > index 7fae277..d7e4b62 100644 > --- a/src/common_interface.c > +++ b/src/common_interface.c > @@ -61,11 +61,17 @@ > > #include <sys/endian.h> > > -#define LETOH_16(x) le16toh(x) > #define HTOLE_16(x) htole16(x) > -#define LETOH_32(x) le32toh(x) > #define HTOLE_32(x) htole32(x) > > +#ifdef __FreeBSD__ > +#define LETOH_16(x) le16toh(x) > +#define LETOH_32(x) le32toh(x) > +#else > +#define LETOH_16(x) letoh16(x) > +#define LETOH_32(x) letoh32(x) > +#endif > + > #endif /* others */ > > /** > diff --git a/src/common_map.c b/src/common_map.c > index ac1c668..8757151 100644 > --- a/src/common_map.c > +++ b/src/common_map.c > @@ -22,6 +22,7 @@ > * DEALINGS IN THE SOFTWARE. > */ > > +#include <sys/types.h> > #include <sys/mman.h> > #include <errno.h> > > diff --git a/src/openbsd_pci.c b/src/openbsd_pci.c > new file mode 100644 > index 0000000..5c06b47 > --- /dev/null > +++ b/src/openbsd_pci.c > @@ -0,0 +1,406 @@ > +/* > + * Copyright (c) 2008 Mark Kettenis > + * > + * Permission to use, copy, modify, and distribute this software for any > + * purpose with or without fee is hereby granted, provided that the above > + * copyright notice and this permission notice appear in all copies. > + * > + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES > + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF > + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR > + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES > + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN > + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF > + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. > + */ > + > +#include <sys/param.h> > +#include <sys/ioctl.h> > +#include <sys/memrange.h> > +#include <sys/mman.h> > +#include <sys/pciio.h> > + > +#include <dev/pci/pcireg.h> > +#include <dev/pci/pcidevs.h> > + > +#include <errno.h> > +#include <fcntl.h> > +#include <stdio.h> > +#include <stdlib.h> > +#include <string.h> > +#include <unistd.h> > + > +#include "pciaccess.h" > +#include "pciaccess_private.h" > + > +static int pcifd; > +static int aperturefd = -1; > + > +static int > +pci_read(int bus, int dev, int func, uint32_t reg, uint32_t *val) > +{ > + struct pci_io io; > + int err; > + > + bzero(&io, sizeof(io)); > + io.pi_sel.pc_bus = bus; > + io.pi_sel.pc_dev = dev; > + io.pi_sel.pc_func = func; > + io.pi_reg = reg; > + io.pi_width = 4; > + > + err = ioctl(pcifd, PCIOCREAD, &io); > + if (err) > + return (err); > + > + *val = io.pi_data; > + > + return (0); > +} > + > +static int > +pci_write(int bus, int dev, int func, uint32_t reg, uint32_t val) > +{ > + struct pci_io io; > + > + bzero(&io, sizeof(io)); > + io.pi_sel.pc_bus = bus; > + io.pi_sel.pc_dev = dev; > + io.pi_sel.pc_func = func; > + io.pi_reg = reg; > + io.pi_width = 4; > + io.pi_data = val; > + > + return ioctl(pcifd, PCIOCWRITE, &io); > +} > + > +static int > +pci_nfuncs(int bus, int dev) > +{ > + uint32_t hdr; > + > + if (pci_read(bus, dev, 0, PCI_BHLC_REG, &hdr) != 0) > + return -1; > + > + return (PCI_HDRTYPE_MULTIFN(hdr) ? 8 : 1); > +} > + > +static int > +pci_device_openbsd_map_range(struct pci_device *dev, > + struct pci_device_mapping *map) > +{ > + struct mem_range_desc mr; > + struct mem_range_op mo; > + int prot = PROT_READ; > + > + if (map->flags & PCI_DEV_MAP_FLAG_WRITABLE) > + prot |= PROT_WRITE; > + > + map->memory = mmap(NULL, map->size, prot, MAP_SHARED, aperturefd, > + map->base); > + if (map->memory == MAP_FAILED) > + return errno; > + > + /* No need to set an MTRR if it's the default mode. */ > + if ((map->flags & PCI_DEV_MAP_FLAG_CACHABLE) || > + (map->flags & PCI_DEV_MAP_FLAG_WRITE_COMBINE)) { > + mr.mr_base = map->base; > + mr.mr_len = map->size; > + mr.mr_flags = 0; > + if (map->flags & PCI_DEV_MAP_FLAG_CACHABLE) > + mr.mr_flags |= MDF_WRITEBACK; > + if (map->flags & PCI_DEV_MAP_FLAG_WRITE_COMBINE) > + mr.mr_flags |= MDF_WRITECOMBINE; > + strlcpy(mr.mr_owner, "pciaccess", sizeof(mr.mr_owner)); > + > + mo.mo_desc = &mr; > + mo.mo_arg[0] = MEMRANGE_SET_UPDATE; > + > + if (ioctl(aperturefd, MEMRANGE_SET, &mo)) > + return errno; > + } > + > + return 0; > +} > + > +static int > +pci_device_openbsd_unmap_range(struct pci_device *dev, > + struct pci_device_mapping *map) > +{ > + struct mem_range_desc mr; > + struct mem_range_op mo; > + > + if ((map->flags & PCI_DEV_MAP_FLAG_CACHABLE) || > + (map->flags & PCI_DEV_MAP_FLAG_WRITE_COMBINE)) { > + mr.mr_base = map->base; > + mr.mr_len = map->size; > + mr.mr_flags = MDF_UNCACHEABLE; > + strlcpy(mr.mr_owner, "pciaccess", sizeof(mr.mr_owner)); > + > + mo.mo_desc = &mr; > + mo.mo_arg[0] = MEMRANGE_SET_REMOVE; > + > + (void)ioctl(aperturefd, MEMRANGE_SET, &mo); > + } > + > + return pci_device_generic_unmap_range(dev, map); > +} > + > +static int > +pci_device_openbsd_read(struct pci_device *dev, void *data, > + pciaddr_t offset, pciaddr_t size, pciaddr_t *bytes_read) > +{ > + struct pci_io io; > + > + io.pi_sel.pc_bus = dev->bus; > + io.pi_sel.pc_dev = dev->dev; > + io.pi_sel.pc_func = dev->func; > + > + *bytes_read = 0; > + while (size > 0) { > + int toread = MIN(size, 4 - (offset & 0x3)); > + > + io.pi_reg = (offset & ~0x3); > + io.pi_width = 4; > + > + if (ioctl(pcifd, PCIOCREAD, &io) == -1) > + return errno; > + > + io.pi_data = htole32(io.pi_data); > + io.pi_data >>= ((offset & 0x3) * 8); > + > + memcpy(data, &io.pi_data, toread); > + > + offset += toread; > + data = (char *)data + toread; > + size -= toread; > + *bytes_read += toread; > + } > + > + return 0; > +} > + > +static int > +pci_device_openbsd_write(struct pci_device *dev, const void *data, > + pciaddr_t offset, pciaddr_t size, pciaddr_t *bytes_written) > +{ > + struct pci_io io; > + > + if ((offset % 4) == 0 || (size % 4) == 0) > + return EINVAL; > + > + io.pi_sel.pc_bus = dev->bus; > + io.pi_sel.pc_dev = dev->dev; > + io.pi_sel.pc_func = dev->func; > + > + *bytes_written = 0; > + while (size > 0) { > + io.pi_reg = offset; > + io.pi_width = 4; > + memcpy(&io.pi_data, data, 4); > + > + if (ioctl(pcifd, PCIOCWRITE, &io) == -1) > + return errno; > + > + offset += 4; > + data = (char *)data + 4; > + size -= 4; > + *bytes_written += 4; > + } > + > + return 0; > +} > + > +static void > +pci_system_openbsd_destroy(void) > +{ > + close(aperturefd); > + close(pcifd); > + free(pci_sys); > + pci_sys = NULL; > +} > + > +static int > +pci_device_openbsd_probe(struct pci_device *device) > +{ > + struct pci_device_private *priv = (struct pci_device_private *)device; > + struct pci_mem_region *region; > + uint64_t reg64, size64; > + uint32_t bar, reg, size; > + int bus, dev, func, err; > + > + bus = device->bus; > + dev = device->dev; > + func = device->func; > + > + err = pci_read(bus, dev, func, PCI_BHLC_REG, ®); > + if (err) > + return err; > + > + priv->header_type = PCI_HDRTYPE_TYPE(reg); > + if (priv->header_type != 0) > + return 0; > + > + region = device->regions; > + for (bar = PCI_MAPREG_START; bar < PCI_MAPREG_END; > + bar += sizeof(uint32_t), region++) { > + err = pci_read(bus, dev, func, bar, ®); > + if (err) > + return err; > + > + /* Probe the size of the region. */ > + err = pci_write(bus, dev, func, bar, ~0); > + if (err) > + return err; > + pci_read(bus, dev, func, bar, &size); > + pci_write(bus, dev, func, bar, reg); > + > + if (PCI_MAPREG_TYPE(reg) == PCI_MAPREG_TYPE_IO) { > + region->is_IO = 1; > + region->base_addr = PCI_MAPREG_IO_ADDR(reg); > + region->size = PCI_MAPREG_IO_SIZE(size); > + } else { > + if (PCI_MAPREG_MEM_PREFETCHABLE(reg)) > + region->is_prefetchable = 1; > + switch(PCI_MAPREG_MEM_TYPE(reg)) { > + case PCI_MAPREG_MEM_TYPE_32BIT: > + case PCI_MAPREG_MEM_TYPE_32BIT_1M: > + region->base_addr = PCI_MAPREG_MEM_ADDR(reg); > + region->size = PCI_MAPREG_MEM_SIZE(size); > + break; > + case PCI_MAPREG_MEM_TYPE_64BIT: > + region->is_64 = 1; > + > + reg64 = reg; > + size64 = size; > + > + bar += sizeof(uint32_t); > + > + err = pci_read(bus, dev, func, bar, ®); > + if (err) > + return err; > + reg64 |= (uint64_t)reg << 32; > + > + err = pci_write(bus, dev, func, bar, ~0); > + if (err) > + return err; > + pci_read(bus, dev, func, bar, &size); > + pci_write(bus, dev, func, bar, reg64 >> 32); > + size64 |= (uint64_t)size << 32; > + > + region->base_addr = PCI_MAPREG_MEM64_ADDR(reg64); > + region->size = PCI_MAPREG_MEM64_SIZE(size64); > + region++; > + break; > + } > + } > + } > + > + return 0; > +} > + > +static const struct pci_system_methods openbsd_pci_methods = { > + pci_system_openbsd_destroy, > + NULL, > + NULL, > + pci_device_openbsd_probe, > + pci_device_openbsd_map_range, > + pci_device_openbsd_unmap_range, > + pci_device_openbsd_read, > + pci_device_openbsd_write, > + pci_fill_capabilities_generic > +}; > + > +int > +pci_system_openbsd_create(void) > +{ > + struct pci_device_private *device; > + int bus, dev, func, ndevs, nfuncs; > + uint32_t reg; > + > + pcifd = open("/dev/pci", O_RDWR); > + if (pcifd == -1) > + return ENXIO; > + > + pci_sys = calloc(1, sizeof(struct pci_system)); > + if (pci_sys == NULL) { > + close(aperturefd); > + close(pcifd); > + return ENOMEM; > + } > + > + pci_sys->methods = &openbsd_pci_methods; > + > + ndevs = 0; > + for (bus = 0; bus < 256; bus++) { > + for (dev = 0; dev < 32; dev++) { > + nfuncs = pci_nfuncs(bus, dev); > + for (func = 0; func < nfuncs; func++) { > + if (pci_read(bus, dev, func, PCI_ID_REG, > + ®) != 0) > + continue; > + if (PCI_VENDOR(reg) == PCI_VENDOR_INVALID || > + PCI_VENDOR(reg) == 0) > + continue; > + > + ndevs++; > + } > + } > + } > + > + pci_sys->num_devices = ndevs; > + pci_sys->devices = calloc(ndevs, sizeof(struct pci_device_private)); > + if (pci_sys->devices == NULL) { > + 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 (func = 0; func < nfuncs; func++) { > + if (pci_read(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.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) > + continue; > + > + device->base.device_class = > + PCI_INTERFACE(reg) | PCI_CLASS(reg) << 16 | > + PCI_SUBCLASS(reg) << 8; > + device->base.revision = PCI_REVISION(reg); > + > + if (pci_read(bus, dev, func, PCI_SUBVEND_0, > + ®) != 0) > + continue; > + > + device->base.subvendor_id = PCI_VENDOR(reg); > + device->base.subdevice_id = PCI_PRODUCT(reg); > + > + device++; > + } > + } > + } > + > + return 0; > +} > + > +void > +pci_system_openbsd_init_dev_mem(int fd) > +{ > + aperturefd = fd; > +} > diff --git a/src/pciaccess_private.h b/src/pciaccess_private.h > index c8a483e..94b12bd 100644 > --- a/src/pciaccess_private.h > +++ b/src/pciaccess_private.h > @@ -135,3 +135,5 @@ extern struct pci_system * pci_sys; > > extern int pci_system_linux_sysfs_create( void ); > extern int pci_system_freebsd_create( void ); > +extern int pci_system_openbsd_create( void ); > +extern void pci_system_openbsd_init_dev_mem( int ); > _______________________________________________ > xorg mailing list > xorg@xxxxxxxxxxxxxxxxxxxxx > http://lists.freedesktop.org/mailman/listinfo/xorg -- Eric Anholt anholt@xxxxxxxxxxx eric@xxxxxxxxxx eric.anholt@xxxxxxxxx
Attachment:
signature.asc
Description: This is a digitally signed message part
_______________________________________________ xorg mailing list xorg@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/xorg