summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorjhb <jhb@FreeBSD.org>2008-09-16 19:52:02 +0000
committerjhb <jhb@FreeBSD.org>2008-09-16 19:52:02 +0000
commit423433a5d70cff819e78878338a17388f3542e0c (patch)
tree61641ead618322c6f56f47ec24ef988df846e182 /sys
parent5657e9d778c13979b015b15f469fb25d7aa4b393 (diff)
downloadFreeBSD-src-423433a5d70cff819e78878338a17388f3542e0c.zip
FreeBSD-src-423433a5d70cff819e78878338a17388f3542e0c.tar.gz
Allow child devices of vgapci(4) to query VPD strings and use MSI/MSI-X
interrupts. For the MSI/MSI-X case, we only allow 1 child device to use MSI or MSI-X at a time. Tested by: rnoland
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/pci/vga_pci.c100
1 files changed, 99 insertions, 1 deletions
diff --git a/sys/dev/pci/vga_pci.c b/sys/dev/pci/vga_pci.c
index 54424a2..bc929de 100644
--- a/sys/dev/pci/vga_pci.c
+++ b/sys/dev/pci/vga_pci.c
@@ -46,6 +46,10 @@ __FBSDID("$FreeBSD$");
#include <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>
+struct vga_pci_softc {
+ device_t vga_msi_child; /* Child driver using MSI. */
+};
+
static int
vga_pci_probe(device_t dev)
{
@@ -176,6 +180,21 @@ vga_pci_disable_io(device_t dev, device_t child, int space)
}
static int
+vga_pci_get_vpd_ident(device_t dev, device_t child, const char **identptr)
+{
+
+ return (pci_get_vpd_ident(dev, identptr));
+}
+
+static int
+vga_pci_get_vpd_readonly(device_t dev, device_t child, const char *kw,
+ const char **vptr)
+{
+
+ return (pci_get_vpd_readonly(dev, kw, vptr));
+}
+
+static int
vga_pci_set_powerstate(device_t dev, device_t child, int state)
{
@@ -210,6 +229,77 @@ vga_pci_find_extcap(device_t dev, device_t child, int capability,
return (pci_find_extcap(dev, capability, capreg));
}
+static int
+vga_pci_alloc_msi(device_t dev, device_t child, int *count)
+{
+ struct vga_pci_softc *sc;
+ int error;
+
+ sc = device_get_softc(dev);
+ if (sc->vga_msi_child != NULL)
+ return (EBUSY);
+ error = pci_alloc_msi(dev, count);
+ if (error == 0)
+ sc->vga_msi_child = child;
+ return (error);
+}
+
+static int
+vga_pci_alloc_msix(device_t dev, device_t child, int *count)
+{
+ struct vga_pci_softc *sc;
+ int error;
+
+ sc = device_get_softc(dev);
+ if (sc->vga_msi_child != NULL)
+ return (EBUSY);
+ error = pci_alloc_msix(dev, count);
+ if (error == 0)
+ sc->vga_msi_child = child;
+ return (error);
+}
+
+static int
+vga_pci_remap_msix(device_t dev, device_t child, int count,
+ const u_int *vectors)
+{
+ struct vga_pci_softc *sc;
+
+ sc = device_get_softc(dev);
+ if (sc->vga_msi_child != child)
+ return (ENXIO);
+ return (pci_remap_msix(dev, count, vectors));
+}
+
+static int
+vga_pci_release_msi(device_t dev, device_t child)
+{
+ struct vga_pci_softc *sc;
+ int error;
+
+ sc = device_get_softc(dev);
+ if (sc->vga_msi_child != child)
+ return (ENXIO);
+ error = pci_release_msi(dev);
+ if (error == 0)
+ sc->vga_msi_child = NULL;
+ return (error);
+}
+
+static int
+vga_pci_msi_count(device_t dev, device_t child)
+{
+
+ return (pci_msi_count(dev));
+}
+
+static int
+vga_pci_msix_count(device_t dev, device_t child)
+{
+
+ return (pci_msix_count(dev));
+}
+
static device_method_t vga_pci_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, vga_pci_probe),
@@ -236,10 +326,18 @@ static device_method_t vga_pci_methods[] = {
DEVMETHOD(pci_disable_busmaster, vga_pci_disable_busmaster),
DEVMETHOD(pci_enable_io, vga_pci_enable_io),
DEVMETHOD(pci_disable_io, vga_pci_disable_io),
+ DEVMETHOD(pci_get_vpd_ident, vga_pci_get_vpd_ident),
+ DEVMETHOD(pci_get_vpd_readonly, vga_pci_get_vpd_readonly),
DEVMETHOD(pci_get_powerstate, vga_pci_get_powerstate),
DEVMETHOD(pci_set_powerstate, vga_pci_set_powerstate),
DEVMETHOD(pci_assign_interrupt, vga_pci_assign_interrupt),
DEVMETHOD(pci_find_extcap, vga_pci_find_extcap),
+ DEVMETHOD(pci_alloc_msi, vga_pci_alloc_msi),
+ DEVMETHOD(pci_alloc_msix, vga_pci_alloc_msix),
+ DEVMETHOD(pci_remap_msix, vga_pci_remap_msix),
+ DEVMETHOD(pci_release_msi, vga_pci_release_msi),
+ DEVMETHOD(pci_msi_count, vga_pci_msi_count),
+ DEVMETHOD(pci_msix_count, vga_pci_msix_count),
{ 0, 0 }
};
@@ -247,7 +345,7 @@ static device_method_t vga_pci_methods[] = {
static driver_t vga_pci_driver = {
"vgapci",
vga_pci_methods,
- 1,
+ sizeof(struct vga_pci_softc),
};
static devclass_t vga_devclass;
OpenPOWER on IntegriCloud