svn commit: r290414 - in head: share/man/man9 sys/dev/pci

John Baldwin jhb at FreeBSD.org
Thu Nov 5 21:26:08 UTC 2015


Author: jhb
Date: Thu Nov  5 21:26:06 2015
New Revision: 290414
URL: https://svnweb.freebsd.org/changeset/base/290414

Log:
  Add helper routines for PCI device drivers to read, write, and modify
  PCI-Express capability registers (that is, PCI config registers in the
  standard PCI config space belonging to the PCI-Express capability
  register set).
  
  Note that all of the current PCI-e registers are either 16 or 32-bits,
  so only widths of 2 or 4 bytes are supported.
  
  Reviewed by:	imp
  MFC after:	1 week
  Sponsored by:	Chelsio
  Differential Revision:	https://reviews.freebsd.org/D4088

Modified:
  head/share/man/man9/Makefile
  head/share/man/man9/pci.9
  head/sys/dev/pci/pci.c
  head/sys/dev/pci/pcivar.h

Modified: head/share/man/man9/Makefile
==============================================================================
--- head/share/man/man9/Makefile	Thu Nov  5 21:22:23 2015	(r290413)
+++ head/share/man/man9/Makefile	Thu Nov  5 21:26:06 2015	(r290414)
@@ -1290,7 +1290,10 @@ MLINKS+=pci.9 pci_alloc_msi.9 \
 	pci.9 pci_save_state.9 \
 	pci.9 pci_set_powerstate.9 \
 	pci.9 pci_set_max_read_req.9 \
-	pci.9 pci_write_config.9
+	pci.9 pci_write_config.9 \
+	pci.9 pcie_adjust_config.9 \
+	pci.9 pcie_read_config.9 \
+	pci.9 pcie_write_config.9 \
 MLINKS+=pci_iov_schema.9 pci_iov_schema_alloc_node.9 \
 	pci_iov_schema.9 pci_iov_schema_add_bool.9 \
 	pci_iov_schema.9 pci_iov_schema_add_string.9 \

Modified: head/share/man/man9/pci.9
==============================================================================
--- head/share/man/man9/pci.9	Thu Nov  5 21:22:23 2015	(r290413)
+++ head/share/man/man9/pci.9	Thu Nov  5 21:26:06 2015	(r290414)
@@ -25,7 +25,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd July 8, 2015
+.Dd November 5, 2015
 .Dt PCI 9
 .Os
 .Sh NAME
@@ -58,7 +58,10 @@
 .Nm pci_save_state ,
 .Nm pci_set_max_read_req ,
 .Nm pci_set_powerstate ,
-.Nm pci_write_config
+.Nm pci_write_config ,
+.Nm pcie_adjust_config ,
+.Nm pcie_read_config ,
+.Nm pcie_write_config
 .Nd PCI bus interface
 .Sh SYNOPSIS
 .In sys/bus.h
@@ -118,6 +121,18 @@
 .Fn pci_set_powerstate "device_t dev" "int state"
 .Ft void
 .Fn pci_write_config "device_t dev" "int reg" "uint32_t val" "int width"
+.Ft uint32_t
+.Fo pcie_adjust_config
+.Fa "device_t dev"
+.Fa "int reg"
+.Fa "uint32_t mask"
+.Fa "uint32_t val"
+.Fa "int width"
+.Fc
+.Ft uint32_t
+.Fn pcie_read_config "device_t dev" "int reg" "int width"
+.Ft void
+.Fn pcie_write_config "device_t dev" "int reg" "uint32_t val" "int width"
 .In dev/pci/pci_iov.h
 .Ft int
 .Fn pci_iov_attach "device_t dev" "nvlist_t *pf_schema" "nvlist_t *vf_schema"
@@ -159,6 +174,48 @@ with
 .Fa width
 specifying the size of the access.
 .Pp
+The
+.Fn pcie_adjust_config
+function is used to modify the value of a register in the PCI-express
+capability register set of device
+.Fa dev .
+The offset
+.Fa reg
+specifies a relative offset in the register set with
+.Fa width
+specifying the size of the access.
+The new value of the register is computed by modifying bits set in
+.Fa mask
+to the value in
+.Fa val .
+Any bits not specified in
+.Fa mask
+are preserved.
+The previous value of the register is returned.
+.Pp
+The
+.Fn pcie_read_config
+function is used to read the value of a register in the PCI-express
+capability register set of device
+.Fa dev .
+The offset
+.Fa reg
+specifies a relative offset in the register set with
+.Fa width
+specifying the size of the access.
+.Pp
+The
+.Fn pcie_write_config
+function is used to write the value
+.Fa val
+to a register in the PCI-express capability register set of device
+.Fa dev .
+The offset
+.Fa reg
+specifies a relative offset in the register set with
+.Fa width
+specifying the size of the access.
+.Pp
 .Em NOTE :
 Device drivers should only use these functions for functionality that
 is not available via another

Modified: head/sys/dev/pci/pci.c
==============================================================================
--- head/sys/dev/pci/pci.c	Thu Nov  5 21:22:23 2015	(r290413)
+++ head/sys/dev/pci/pci.c	Thu Nov  5 21:26:06 2015	(r290414)
@@ -1917,6 +1917,63 @@ pci_set_max_read_req(device_t dev, int s
 	return (size);
 }
 
+uint32_t
+pcie_read_config(device_t dev, int reg, int width)
+{
+	struct pci_devinfo *dinfo = device_get_ivars(dev);
+	int cap;
+
+	cap = dinfo->cfg.pcie.pcie_location;
+	if (cap == 0) {
+		if (width == 2)
+			return (0xffff);
+		return (0xffffffff);
+	}
+
+	return (pci_read_config(dev, cap + reg, width));
+}
+
+void
+pcie_write_config(device_t dev, int reg, uint32_t value, int width)
+{
+	struct pci_devinfo *dinfo = device_get_ivars(dev);
+	int cap;
+
+	cap = dinfo->cfg.pcie.pcie_location;
+	if (cap == 0)
+		return;
+	pci_write_config(dev, cap + reg, value, width);
+}
+
+/*
+ * Adjusts a PCI-e capability register by clearing the bits in mask
+ * and setting the bits in (value & mask).  Bits not set in mask are
+ * not adjusted.
+ *
+ * Returns the old value on success or all ones on failure.
+ */
+uint32_t
+pcie_adjust_config(device_t dev, int reg, uint32_t mask, uint32_t value,
+    int width)
+{
+	struct pci_devinfo *dinfo = device_get_ivars(dev);
+	uint32_t old, new;
+	int cap;
+
+	cap = dinfo->cfg.pcie.pcie_location;
+	if (cap == 0) {
+		if (width == 2)
+			return (0xffff);
+		return (0xffffffff);
+	}
+
+	old = pci_read_config(dev, cap + reg, width);
+	new = old & ~mask;
+	new |= (value & mask);
+	pci_write_config(dev, cap + reg, new, width);
+	return (old);
+}
+
 /*
  * Support for MSI message signalled interrupts.
  */

Modified: head/sys/dev/pci/pcivar.h
==============================================================================
--- head/sys/dev/pci/pcivar.h	Thu Nov  5 21:22:23 2015	(r290413)
+++ head/sys/dev/pci/pcivar.h	Thu Nov  5 21:26:06 2015	(r290414)
@@ -551,6 +551,10 @@ int	pci_get_max_read_req(device_t dev);
 void	pci_restore_state(device_t dev);
 void	pci_save_state(device_t dev);
 int	pci_set_max_read_req(device_t dev, int size);
+uint32_t pcie_read_config(device_t dev, int reg, int width);
+void	pcie_write_config(device_t dev, int reg, uint32_t value, int width);
+uint32_t pcie_adjust_config(device_t dev, int reg, uint32_t mask,
+	    uint32_t value, int width);
 
 
 #ifdef BUS_SPACE_MAXADDR


More information about the svn-src-head mailing list