summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortnn <tnn>2010-04-09 08:09:11 +0000
committertnn <tnn>2010-04-09 08:09:11 +0000
commit2b94a172dadb7eb1f65c24f93600476e8e7079de (patch)
treeb63c8a1f2039533455413d617da5c9a0ac3a430b
parent5c1e044d851661ac6797f5b8fbc360d9951adf67 (diff)
downloadpkgsrc-2b94a172dadb7eb1f65c24f93600476e8e7079de.tar.gz
Update to libpciaccess-0.11.
Synced the netbsd support patch from xsrc HEAD, with a minor tweak: Now we first try to map memory in the newfangled /dev/pciN way. If that fails, then we fall back to /dev/mem. We need to do this to deal with netbsd-5 and earlier. Add NetBSD/sparc64 to the list of supported platforms. Upstream changes: 0.11.0: Add pci_device_get_parent_bridge() I/O port access routines Fix pci_device_open_io() to actually return something useful Fix I/O handle array allocator to work for devices past the first libpciaccess 0.11.0 .gitignore: use common defaults with custom section # 24239 Makefile.am: ChangeLog not required: EXTRA_DIST or *CLEANFILES #24432 Deploy the new XORG_DEFAULT_OPTIONS #24242 INSTALL, NEWS, README or AUTHORS files are missing/incorrect #24206 Makefile.am: add ChangeLog and INSTALL on MAINTAINERCLEANFILES 0.10.9: vgaarb: check pci_sys exists before initing vga arb shutup stupid gcc warning, strtok_r ignores the first parameter Free return value from scandir instead of leaking it. vgaarb: check for fd before close it vgaarb: fix newbie typo
-rw-r--r--sysutils/libpciaccess/Makefile5
-rw-r--r--sysutils/libpciaccess/distinfo12
-rw-r--r--sysutils/libpciaccess/patches/patch-aa13
-rw-r--r--sysutils/libpciaccess/patches/patch-ac523
4 files changed, 477 insertions, 76 deletions
diff --git a/sysutils/libpciaccess/Makefile b/sysutils/libpciaccess/Makefile
index 940202d45e4..f48edf364bc 100644
--- a/sysutils/libpciaccess/Makefile
+++ b/sysutils/libpciaccess/Makefile
@@ -1,7 +1,7 @@
-# $NetBSD: Makefile,v 1.6 2009/08/31 07:48:22 wiz Exp $
+# $NetBSD: Makefile,v 1.7 2010/04/09 08:09:11 tnn Exp $
#
-DISTNAME= libpciaccess-0.10.8
+DISTNAME= libpciaccess-0.11.0
CATEGORIES= sysutils x11
MASTER_SITES= ${MASTER_SITE_XORG:=lib/}
EXTRACT_SUFX= .tar.bz2
@@ -18,6 +18,7 @@ ONLY_FOR_PLATFORM= FreeBSD-*-i386 NetBSD-*-i386 OpenBSD-*-i386
ONLY_FOR_PLATFORM+= FreeBSD-*-x86_64 NetBSD-*-x86_64 OpenBSD-*-x86_64
ONLY_FOR_PLATFORM+= DragonFly-*-i386 DragonFly-*-x86_64
ONLY_FOR_PLATFORM+= Linux-*-* SunOS-*-*
+ONLY_FOR_PLATFORM+= NetBSD-*-sparc64
GNU_CONFIGURE= yes
USE_LIBTOOL= yes
diff --git a/sysutils/libpciaccess/distinfo b/sysutils/libpciaccess/distinfo
index 79737aaa033..58831ecf214 100644
--- a/sysutils/libpciaccess/distinfo
+++ b/sysutils/libpciaccess/distinfo
@@ -1,7 +1,7 @@
-$NetBSD: distinfo,v 1.7 2009/08/31 07:48:22 wiz Exp $
+$NetBSD: distinfo,v 1.8 2010/04/09 08:09:11 tnn Exp $
-SHA1 (libpciaccess-0.10.8.tar.bz2) = 0fa152811e121b4e97eb5f53c14d7896685f79a6
-RMD160 (libpciaccess-0.10.8.tar.bz2) = dd3d329a6c20fec44add9a205af0e7f6216190ac
-Size (libpciaccess-0.10.8.tar.bz2) = 281625 bytes
-SHA1 (patch-aa) = baa96a3b85bb30d818e130c32bf5b295eefeb18f
-SHA1 (patch-ac) = d3157dee96bcd6e743a0f4a8b27b5e03a27cc79e
+SHA1 (libpciaccess-0.11.0.tar.bz2) = bcebba8b8441af151b59b63e8e91e66133b64158
+RMD160 (libpciaccess-0.11.0.tar.bz2) = 7d579f024e543c97cceb47c204d395e4097becf2
+Size (libpciaccess-0.11.0.tar.bz2) = 295639 bytes
+SHA1 (patch-aa) = d9ac3a766693fa56e036fda8810e9769b3c07060
+SHA1 (patch-ac) = 3f0fb3c84f2c2cab78a9c57d844b71941efccea6
diff --git a/sysutils/libpciaccess/patches/patch-aa b/sysutils/libpciaccess/patches/patch-aa
index 315a30e32d7..449cd4d5015 100644
--- a/sysutils/libpciaccess/patches/patch-aa
+++ b/sysutils/libpciaccess/patches/patch-aa
@@ -1,8 +1,8 @@
-$NetBSD: patch-aa,v 1.3 2009/05/18 19:09:01 hasso Exp $
+$NetBSD: patch-aa,v 1.4 2010/04/09 08:09:11 tnn Exp $
---- configure.ac.orig 2009-04-25 02:19:43 +0300
-+++ configure.ac 2009-05-18 08:34:40 +0300
-@@ -66,10 +66,10 @@ case $host_os in
+--- configure.ac.orig 2009-12-14 21:35:07.000000000 +0000
++++ configure.ac
+@@ -75,10 +75,10 @@ case $host_os in
*netbsd*)
case $host in
*i386*)
@@ -15,7 +15,7 @@ $NetBSD: patch-aa,v 1.3 2009/05/18 19:09:01 hasso Exp $
;;
esac
netbsd=yes
-@@ -91,7 +91,21 @@ AM_CONDITIONAL(SOLARIS, [test "x$solaris
+@@ -100,7 +100,20 @@ AM_CONDITIONAL(SOLARIS, [test "x$solaris
AC_SYS_LARGEFILE
@@ -23,8 +23,7 @@ $NetBSD: patch-aa,v 1.3 2009/05/18 19:09:01 hasso Exp $
+AC_CHECK_LIB([pci], [pcibus_conf_read],
+ [PCIACCESS_LIBS="-lpci $PCIACCESS_LIBS"],
+ [AC_MSG_ERROR(check for libpci failed.)])
-+AC_CHECK_HEADERS([machine/sysarch.h], [],
-+ [AC_MSG_ERROR(sysarch.h not found)])
++AC_CHECK_HEADERS([machine/sysarch.h])
+AC_CHECK_HEADERS([machine/mtrr.h], [have_mtrr_h="yes"], [have_mtrr_h="no"],
+[#ifdef HAVE_MACHINE_SYSARCH_H
+#include <sys/types.h>
diff --git a/sysutils/libpciaccess/patches/patch-ac b/sysutils/libpciaccess/patches/patch-ac
index 8472348d84e..9201a1ebebb 100644
--- a/sysutils/libpciaccess/patches/patch-ac
+++ b/sysutils/libpciaccess/patches/patch-ac
@@ -1,8 +1,16 @@
-$NetBSD: patch-ac,v 1.5 2009/05/25 20:11:05 drochner Exp $
+$NetBSD: patch-ac,v 1.6 2010/04/09 08:09:11 tnn Exp $
---- src/netbsd_pci.c.orig 2008-12-20 04:21:22.000000000 +0100
+--- src/netbsd_pci.c.orig 2009-02-17 00:10:20.000000000 +0000
+++ src/netbsd_pci.c
-@@ -20,12 +20,15 @@
+@@ -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
+@@ -20,12 +21,15 @@
#include <sys/mman.h>
#include <sys/types.h>
@@ -19,7 +27,7 @@ $NetBSD: patch-ac,v 1.5 2009/05/25 20:11:05 drochner Exp $
#include <errno.h>
#include <fcntl.h>
-@@ -35,6 +38,8 @@
+@@ -35,126 +39,160 @@
#include <unistd.h>
@@ -28,24 +36,62 @@ $NetBSD: patch-ac,v 1.5 2009/05/25 20:11:05 drochner Exp $
#include "pciaccess.h"
#include "pciaccess_private.h"
-@@ -43,20 +48,12 @@ static int pcifd;
+-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 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)
{
- struct pciio_bdf_cfgreg io;
- int err;
--
++ uint32_t rval;
+
- bzero(&io, sizeof(io));
- io.bus = bus;
- io.device = dev;
- io.function = func;
- io.cfgreg.reg = reg;
-+ uint32_t rval;
++ if ((domain < 0) || (domain > nbuses))
++ return -1;
- err = ioctl(pcifd, PCI_IOC_BDF_CFGREAD, &io);
- if (err)
- return (err);
-+ if (pcibus_conf_read(pcifd, bus, dev, func, reg, &rval) == -1)
++ if (pcibus_conf_read(buses[domain].fd, (unsigned int)bus,
++ (unsigned int)dev, (unsigned int)func, reg, &rval) == -1)
+ return (-1);
- *val = io.cfgreg.val;
@@ -53,25 +99,45 @@ $NetBSD: patch-ac,v 1.5 2009/05/25 20:11:05 drochner Exp $
return 0;
}
-@@ -64,16 +61,7 @@ pci_read(int bus, int dev, int func, uin
+
static int
- pci_write(int bus, int dev, int func, uint32_t reg, uint32_t val)
+-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)
{
- struct pciio_bdf_cfgreg io;
--
+
- bzero(&io, sizeof(io));
- io.bus = bus;
- io.device = dev;
- io.function = func;
- io.cfgreg.reg = reg;
- io.cfgreg.val = val;
--
++ if ((domain < 0) || (domain > nbuses))
++ return -1;
+
- return ioctl(pcifd, PCI_IOC_BDF_CFGWRITE, &io);
-+ return pcibus_conf_write(pcifd, bus, dev, func, reg, val);
++ return pcibus_conf_write(buses[domain].fd, (unsigned int)bus,
++ (unsigned int)dev, (unsigned int)func, reg, val);
}
static int
-@@ -91,70 +79,68 @@ 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);
+ }
+
++/*ARGSUSED*/
+ static int
pci_device_netbsd_map_range(struct pci_device *dev,
struct pci_device_mapping *map)
{
@@ -89,19 +155,29 @@ $NetBSD: patch-ac,v 1.5 2009/05/25 20:11:05 drochner Exp $
if (map->flags & PCI_DEV_MAP_FLAG_WRITABLE)
prot |= PROT_WRITE;
-
-- map->memory = mmap(NULL, map->size, prot, MAP_SHARED,
+-
+ map->memory = mmap(NULL, map->size, prot, MAP_SHARED,
- fd, map->base);
-+ fd = open("/dev/mem", O_RDWR);
-+ if (fd == -1)
-+ return errno;
-+ map->memory = mmap(NULL, map->size, prot, MAP_SHARED, fd, map->base);
- if (map->memory == MAP_FAILED)
- return errno;
-
+- if (map->memory == MAP_FAILED)
+- return errno;
++ buses[dev->domain].fd, (off_t)map->base);
++ if (map->memory == MAP_FAILED) {
++ 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);
++ if (map->memory == MAP_FAILED) {
++ ret = errno;
++ close(fd);
++ return ret;
++ }
++ close(fd);
++ }
++
+#ifdef HAVE_MTRR
+ memset(&m, 0, sizeof(m));
-+
+
/* 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)) {
@@ -129,15 +205,15 @@ $NetBSD: patch-ac,v 1.5 2009/05/25 20:11:05 drochner Exp $
- close(fd);
- return errno;
- }
+- }
+ m.type = MTRR_TYPE_WC;
-+
+
+- close(fd);
+ if ((netbsd_set_mtrr(&m, &n)) == -1)
+ ret = errno;
- }
++ }
+#endif
- close(fd);
-
- return 0;
+ return ret;
}
@@ -178,7 +254,7 @@ $NetBSD: patch-ac,v 1.5 2009/05/25 20:11:05 drochner Exp $
return pci_device_generic_unmap_range(dev, map);
}
-@@ -163,25 +149,22 @@ static int
+@@ -163,25 +201,23 @@ static int
pci_device_netbsd_read(struct pci_device *dev, void *data,
pciaddr_t offset, pciaddr_t size, pciaddr_t *bytes_read)
{
@@ -191,14 +267,16 @@ $NetBSD: patch-ac,v 1.5 2009/05/25 20:11:05 drochner Exp $
*bytes_read = 0;
while (size > 0) {
- int toread = MIN(size, 4 - (offset & 0x3));
+- int toread = MIN(size, 4 - (offset & 0x3));
++ size_t toread = MIN(size, 4 - (offset & 0x3));
- io.cfgreg.reg = (offset & ~0x3);
-+ reg = (offset & ~0x3);
++ reg = (u_int)(offset & ~0x3);
- if (ioctl(pcifd, PCI_IOC_BDF_CFGREAD, &io) == -1)
-+ if ((pcibus_conf_read(pcifd, dev->bus, dev->dev, 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;
- io.cfgreg.val = htole32(io.cfgreg.val);
@@ -211,7 +289,7 @@ $NetBSD: patch-ac,v 1.5 2009/05/25 20:11:05 drochner Exp $
offset += toread;
data = (char *)data + toread;
-@@ -196,21 +179,18 @@ static int
+@@ -196,25 +232,23 @@ static int
pci_device_netbsd_write(struct pci_device *dev, const void *data,
pciaddr_t offset, pciaddr_t size, pciaddr_t *bytes_written)
{
@@ -229,48 +307,371 @@ $NetBSD: patch-ac,v 1.5 2009/05/25 20:11:05 drochner Exp $
while (size > 0) {
- io.cfgreg.reg = offset;
- memcpy(&io.cfgreg.val, data, 4);
-+ reg = offset;
++ reg = (u_int)offset;
+ memcpy(&val, data, 4);
- if (ioctl(pcifd, PCI_IOC_BDF_CFGWRITE, &io) == -1)
-+ if ((pcibus_conf_write(pcifd, dev->bus, dev->dev, 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;
-@@ -222,6 +202,26 @@ pci_device_netbsd_write(struct pci_devic
+- data = (char *)data + 4;
++ data = (const char *)data + 4;
+ size -= 4;
+ *bytes_written += 4;
+ }
+@@ -225,7 +259,11 @@ pci_device_netbsd_write(struct pci_devic
+ 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;
+ }
+@@ -233,17 +271,34 @@ pci_system_netbsd_destroy(void)
+ static int
+ pci_device_netbsd_probe(struct pci_device *device)
+ {
+- struct pci_device_private *priv = (struct pci_device_private *)device;
++ struct pci_device_private *priv =
++ (struct pci_device_private *)(void *)device;
+ 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, &reg);
++ /* Enable the device if necessary */
++ err = pci_read(domain, bus, dev, func, PCI_COMMAND_STATUS_REG, &reg);
++ if (err)
++ return err;
++ if ((reg & (PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE | PCI_COMMAND_MASTER_ENABLE)) !=
++ (PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE | PCI_COMMAND_MASTER_ENABLE)) {
++ reg |= PCI_COMMAND_IO_ENABLE |
++ PCI_COMMAND_MEM_ENABLE |
++ PCI_COMMAND_MASTER_ENABLE;
++ err = pci_write(domain, bus, dev, func, PCI_COMMAND_STATUS_REG,
++ reg);
++ if (err)
++ return err;
++ }
++
++ err = pci_read(domain, bus, dev, func, PCI_BHLC_REG, &reg);
+ if (err)
+ return err;
+
+@@ -254,16 +309,16 @@ pci_device_netbsd_probe(struct pci_devic
+ region = device->regions;
+ for (bar = PCI_MAPREG_START; bar < PCI_MAPREG_END;
+ bar += sizeof(uint32_t), region++) {
+- err = pci_read(bus, dev, func, bar, &reg);
++ err = pci_read(domain, bus, dev, func, bar, &reg);
+ if (err)
+ return err;
+
+ /* Probe the size of the region. */
+- err = pci_write(bus, dev, func, bar, ~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;
+@@ -286,66 +341,188 @@ pci_device_netbsd_probe(struct pci_devic
+
+ bar += sizeof(uint32_t);
+
+- err = pci_read(bus, dev, func, bar, &reg);
++ err = pci_read(domain, bus, dev, func, bar, &reg);
+ if (err)
+ return err;
+ reg64 |= (uint64_t)reg << 32;
+
+- err = pci_write(bus, dev, func, bar, ~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, reg64 >> 32);
++ pci_read(domain, bus, dev, func, bar, &size);
++ pci_write(domain, bus, dev, func, bar,
++ (unsigned int)(reg64 >> 32));
+ size64 |= (uint64_t)size << 32;
+
+- region->base_addr = PCI_MAPREG_MEM64_ADDR(reg64);
+- region->size = PCI_MAPREG_MEM64_SIZE(size64);
++ region->base_addr =
++ (unsigned long)PCI_MAPREG_MEM64_ADDR(reg64);
++ region->size =
++ (unsigned long)PCI_MAPREG_MEM64_SIZE(size64);
+ region++;
+ break;
+ }
+ }
+ }
+
++ /* Probe expansion ROM if present */
++ err = pci_read(domain, bus, dev, func, PCI_MAPREG_ROM, &reg);
++ if (err)
++ return err;
++ if (reg != 0) {
++ err = pci_write(domain, bus, dev, func, PCI_MAPREG_ROM,
++ (uint32_t)(~PCI_MAPREG_ROM_ENABLE));
++ if (err)
++ return err;
++ pci_read(domain, bus, dev, func, PCI_MAPREG_ROM, &size);
++ pci_write(domain, bus, dev, func, PCI_MAPREG_ROM, reg);
++ if ((reg & PCI_MAPREG_MEM_ADDR_MASK) != 0) {
++ priv->rom_base = reg & PCI_MAPREG_MEM_ADDR_MASK;
++ device->rom_size = -(size & PCI_MAPREG_MEM_ADDR_MASK);
++ }
++ }
++
return 0;
}
++/**
++ * Read a VGA rom using the 0xc0000 mapping.
++ *
++ * This function should be extended to handle access through PCI resources,
++ * which should be more reliable when available.
++ */
+static int
-+pci_device_netbsd_read_rom(struct pci_device *device, void *buf)
++pci_device_netbsd_read_rom(struct pci_device *dev, void *buffer)
+{
-+ int fd, res, err;
++ struct pci_device_private *priv = (struct pci_device_private *)(void *)dev;
++ void *bios;
++ pciaddr_t rom_base;
++ size_t rom_size;
++ uint32_t bios_val, command_val;
++ int pci_rom, memfd;
+
-+ fd = open("/dev/mem", O_RDONLY, 0);
-+ if (fd < 0)
++ if (((priv->base.device_class >> 16) & 0xff) != PCI_CLASS_DISPLAY ||
++ ((priv->base.device_class >> 8) & 0xff) != PCI_SUBCLASS_DISPLAY_VGA)
++ return ENOSYS;
++
++ if (priv->rom_base == 0) {
++#if defined(__amd64__) || defined(__i386__)
++ /*
++ * We need a way to detect when this isn't the console and reject
++ * this request outright.
++ */
++ rom_base = 0xc0000;
++ rom_size = 0x10000;
++ pci_rom = 0;
++#else
++ return ENOSYS;
++#endif
++ } else {
++ rom_base = priv->rom_base;
++ rom_size = dev->rom_size;
++ pci_rom = 1;
++ if ((pcibus_conf_read(buses[dev->domain].fd, (unsigned int)dev->bus,
++ (unsigned int)dev->dev, (unsigned int)dev->func,
++ PCI_COMMAND_STATUS_REG, &command_val)) == -1)
++ return errno;
++ 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(buses[dev->domain].fd, (unsigned int)dev->bus,
++ (unsigned int)dev->dev, (unsigned int)dev->func,
++ PCI_MAPREG_ROM, &bios_val)) == -1)
++ return errno;
++ 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,
++ PCI_MAPREG_ROM, bios_val | PCI_MAPREG_ROM_ENABLE)) == -1)
+ return errno;
++ }
++ }
+
-+ lseek(fd, 0xc0000, SEEK_SET);
-+ res = read(fd, buf, 64*1024);
-+ if (res < 0) {
-+ err = errno;
-+ close(fd);
-+ return err;
++ fprintf(stderr, "Using rom_base = 0x%lx (pci_rom=%d)\n", (long)rom_base,
++ pci_rom);
++ memfd = open("/dev/mem", O_RDONLY);
++ if (memfd == -1)
++ return errno;
++
++ bios = mmap(NULL, rom_size, PROT_READ, MAP_SHARED, memfd, (off_t)rom_base);
++ if (bios == MAP_FAILED) {
++ int serrno = errno;
++ close(memfd);
++ return serrno;
++ }
++
++ memcpy(buffer, bios, rom_size);
++
++ munmap(bios, rom_size);
++ close(memfd);
++
++ if (pci_rom) {
++ 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)) == -1)
++ return errno;
+ }
-+ close(fd);
-+ return 0;
++ 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,
++ PCI_MAPREG_ROM, bios_val)) == -1)
++ return errno;
++ }
++ }
++
++ return 0;
+}
+
- static void
- pci_system_netbsd_destroy(void)
- {
-@@ -312,7 +312,7 @@ pci_device_netbsd_probe(struct pci_devic
static const struct pci_system_methods netbsd_pci_methods = {
- pci_system_netbsd_destroy,
- NULL,
+- pci_system_netbsd_destroy,
- NULL,
-+ pci_device_netbsd_read_rom,
- pci_device_netbsd_probe,
- pci_device_netbsd_map_range,
- pci_device_netbsd_unmap_range,
+- NULL,
+- pci_device_netbsd_probe,
+- pci_device_netbsd_map_range,
+- pci_device_netbsd_unmap_range,
+- pci_device_netbsd_read,
+- pci_device_netbsd_write,
+- pci_fill_capabilities_generic
++ .destroy = pci_system_netbsd_destroy,
++ .destroy_device = NULL,
++ .read_rom = pci_device_netbsd_read_rom,
++ .probe = pci_device_netbsd_probe,
++ .map_range = pci_device_netbsd_map_range,
++ .unmap_range = pci_device_netbsd_unmap_range,
++ .read = pci_device_netbsd_read,
++ .write = pci_device_netbsd_write,
++ .fill_capabilities = pci_fill_capabilities_generic
+ };
+
+ int
+ 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 netbsd_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(netbsd_devname, 32, "/dev/pci%d", nbuses);
++ pcifd = open(netbsd_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,
+ &reg) != 0)
+ continue;
+ if (PCI_VENDOR(reg) == PCI_VENDOR_INVALID ||
+@@ -355,37 +532,43 @@ pci_system_netbsd_create(void)
+ ndevs++;
+ }
+ }
++ snprintf(netbsd_devname, 32, "/dev/pci%d", nbuses);
++ pcifd = open(netbsd_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,
+- &reg) != 0)
++ if (pci_read(domain, bus, dev, func,
++ PCI_ID_REG, &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,
+- &reg) != 0)
++ if (pci_read(domain, bus, dev, func,
++ PCI_CLASS_REG, &reg) != 0)
+ continue;
+
+ device->base.device_class =
+@@ -393,8 +576,8 @@ pci_system_netbsd_create(void)
+ PCI_SUBCLASS(reg) << 8;
+ device->base.revision = PCI_REVISION(reg);
+
+- if (pci_read(bus, dev, func, PCI_SUBSYS_ID_REG,
+- &reg) != 0)
++ if (pci_read(domain, bus, dev, func,
++ PCI_SUBSYS_ID_REG, &reg) != 0)
+ continue;
+
+ device->base.subvendor_id = PCI_VENDOR(reg);