aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--share/man/man4/Makefile8
-rw-r--r--share/man/man4/if_ntb.412
-rw-r--r--share/man/man4/ntb.491
-rw-r--r--share/man/man4/ntb_hw_intel.4 (renamed from share/man/man4/ntb_hw.4)66
-rw-r--r--share/man/man4/ntb_hw_plx.4118
-rw-r--r--share/man/man4/ntb_transport.435
-rw-r--r--sys/amd64/conf/NOTES11
-rw-r--r--sys/conf/files.amd649
-rw-r--r--sys/conf/files.i3869
-rw-r--r--sys/dev/ntb/ntb_hw/ntb_hw_intel.c (renamed from sys/dev/ntb/ntb_hw/ntb_hw.c)8
-rw-r--r--sys/dev/ntb/ntb_hw/ntb_hw_intel.h (renamed from sys/dev/ntb/ntb_hw/ntb_regs.h)0
-rw-r--r--sys/dev/ntb/ntb_hw/ntb_hw_plx.c945
-rw-r--r--sys/i386/conf/NOTES9
-rw-r--r--sys/modules/ntb/Makefile2
-rw-r--r--sys/modules/ntb/ntb_hw_intel/Makefile9
-rw-r--r--sys/modules/ntb/ntb_hw_plx/Makefile (renamed from sys/modules/ntb/ntb_hw/Makefile)4
16 files changed, 1261 insertions, 75 deletions
diff --git a/share/man/man4/Makefile b/share/man/man4/Makefile
index c03f24a90015..ad8c5b494ebf 100644
--- a/share/man/man4/Makefile
+++ b/share/man/man4/Makefile
@@ -373,7 +373,9 @@ MAN= aac.4 \
ng_vlan.4 \
nmdm.4 \
nsp.4 \
- ${_ntb_hw.4} \
+ ${_ntb.4} \
+ ${_ntb_hw_intel.4} \
+ ${_ntb_hw_plx.4} \
${_ntb_transport.4} \
${_if_ntb.4} \
null.4 \
@@ -686,7 +688,6 @@ MLINKS+=netintro.4 net.4 \
netintro.4 networking.4
MLINKS+=${_nfe.4} ${_if_nfe.4}
MLINKS+=nge.4 if_nge.4
-MLINKS+=${_ntb_hw.4} ${_ntb.4}
MLINKS+=${_nxge.4} ${_if_nxge.4}
MLINKS+=ow.4 onewire.4
MLINKS+=pccbb.4 cbb.4
@@ -834,7 +835,8 @@ _xnb.4= xnb.4
_if_ntb.4= if_ntb.4
_ioat.4= ioat.4
_ntb.4= ntb.4
-_ntb_hw.4= ntb_hw.4
+_ntb_hw_intel.4= ntb_hw_intel.4
+_ntb_hw_plx.4= ntb_hw_plx.4
_ntb_transport.4=ntb_transport.4
_qlxge.4= qlxge.4
_qlxgb.4= qlxgb.4
diff --git a/share/man/man4/if_ntb.4 b/share/man/man4/if_ntb.4
index 6f52d7774264..78211b0b3549 100644
--- a/share/man/man4/if_ntb.4
+++ b/share/man/man4/if_ntb.4
@@ -25,7 +25,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd July 29, 2016
+.Dd August 30, 2017
.Dt IF_NTB 4
.Os
.Sh NAME
@@ -35,6 +35,8 @@
To compile this driver into your kernel,
place the following lines in your kernel configuration file:
.Bd -ragged -offset indent
+.Cd "device ntb"
+.Cd "device ntb_transport"
.Cd "device if_ntb"
.Ed
.Pp
@@ -56,11 +58,11 @@ The
.Nm
driver attaches on top of the
.Xr ntb_transport 4
-driver to utilize its resources to create virtual Ethernet interface between
-the systems.
-Interface capabilities depend on the underlying transport.
+driver to utilize its resources to create virtual Ethernet network interface
+between the systems.
+It supports as many tx/rx queues as provided by underlying
+.Xr ntb_transport 4 .
Typical MTU is about 64KB to reduce overhead.
-By default one queue is used, but more may be configured.
The MAC address for interface is randomly generated.
.Pp
The
diff --git a/share/man/man4/ntb.4 b/share/man/man4/ntb.4
new file mode 100644
index 000000000000..d45d1bd756b5
--- /dev/null
+++ b/share/man/man4/ntb.4
@@ -0,0 +1,91 @@
+.\"
+.\" Copyright (c) 2017 Alexander Motin <mav@FreeBSD.org>
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd August 30, 2017
+.Dt NTB 4
+.Os
+.Sh NAME
+.Nm ntb
+.Nd Non-Transparent Bridge subsystem
+.Sh SYNOPSIS
+To compile it into your kernel,
+place the following lines in your kernel configuration file:
+.Bd -ragged -offset indent
+.Cd "device ntb"
+.Ed
+.Pp
+Or, to load it as a module at boot, place the following line in
+.Xr loader.conf 5 :
+.Bd -literal -offset indent
+ntb_load="YES"
+.Ed
+.Pp
+The following tunables are settable from the
+.Xr loader 8 :
+.Bl -ohang
+.It Va hw.ntb.debug_level
+Driver debug level.
+The default value is 0, higher means more verbose.
+.It Va hint.ntb_hw. Ns Ar X Ns Va .config
+Configures NTB resources split between several consumer devices.
+Configuration of multiple consumer devices separated by commas.
+Each device can be configured as: "[<name>][:<mw>[:<spad>[:<db>]]]", where:
+.Va name
+is a name of the driver which should attach the device (empty means any),
+.Va mw
+is a number of memory windows to allocate (empty means all available),
+.Va spad
+is a number of scratchpad registers to allocate (empty means all available),
+.Va db
+is a number of doorbells to allocate (empty means all available).
+The default configuration is empty string, which means single device
+with all available resources allowing any driver attachment.
+.El
+.Sh DESCRIPTION
+Non-Transparent Bridges allow to connect two computer systems with PCIe
+link(s), providing each of them limited access to others memory space,
+scratchpad registers and interrupts.
+The
+.Nm
+subsystem uses those resources provided in generic way by hardware drivers
+and splits them between multiple consumer drivers, according to specified
+configuration.
+.Sh SEE ALSO
+.Xr if_ntb 4 ,
+.Xr ntb_transport 4 ,
+.Xr ntb_hw_intel 4 ,
+.Xr ntb_hw_plx 4
+.Sh AUTHORS
+.An -nosplit
+The
+.Nm
+subsystem was developed by Intel and originally written by
+.An Carl Delsey Aq Mt carl@FreeBSD.org .
+Later improvements were done by
+.An Conrad E. Meyer Aq Mt cem@FreeBSD.org
+and
+.An Alexander Motin Aq Mt mav@FreeBSD.org .
diff --git a/share/man/man4/ntb_hw.4 b/share/man/man4/ntb_hw_intel.4
index 6bc11ba3f2ef..423dc9650785 100644
--- a/share/man/man4/ntb_hw.4
+++ b/share/man/man4/ntb_hw_intel.4
@@ -1,5 +1,5 @@
.\"
-.\" Copyright (c) 2016 Alexander Motin <mav@FreeBSD.org>
+.\" Copyright (c) 2016-2017 Alexander Motin <mav@FreeBSD.org>
.\" All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
@@ -25,66 +25,45 @@
.\"
.\" $FreeBSD$
.\"
-.Dd July 28, 2016
-.Dt NTB_HW 4
+.Dd August 30, 2017
+.Dt NTB_HW_INTEL 4
.Os
.Sh NAME
-.Nm ntb ,
-.Nm ntb_hw
+.Nm ntb_hw_intel
.Nd Intel(R) Non-Transparent Bridge driver
.Sh SYNOPSIS
To compile this driver into your kernel,
place the following lines in your kernel configuration file:
.Bd -ragged -offset indent
-.Cd "device ntb_hw"
+.Cd "device ntb"
+.Cd "device ntb_hw_intel"
.Ed
.Pp
Or, to load the driver as a module at boot, place the following line in
.Xr loader.conf 5 :
.Bd -literal -offset indent
-ntb_hw_load="YES"
+ntb_hw_intel_load="YES"
.Ed
-.Pp
-The following tunables are settable from the
-.Xr loader 8 :
-.Bl -ohang
-.It Va hw.ntb.debug_level
-Driver debug level.
-The default value is 0, higher means more verbose.
-.It Va hint.ntb_hw. Ns Ar X Ns Va .config
-Configures NTB resources split between several consumer devices.
-Configuration of multiple consumer devices separated by commas.
-Each device can be configured as: "<name>[:<mw>[:<spad>[:<db>]]]", where:
-.Va name
-is a name of the driver which should attach the device (empty means any),
-.Va mw
-is a number of memory windows to allocate (empty means all available),
-.Va spad
-is a number of scratchpad registers to allocate (empty means all available),
-.Va db
-is a number of doorbells to allocate (empty means all available).
-The default configuration is empty string, which means single device
-with all available resources allowing any driver attachment.
-.El
.Sh DESCRIPTION
-The NTB allows you to connect two computer systems using a PCIe link if they
-have the correct equipment and connectors.
-The
-.Nm ntb_hw
-driver provides support for the Non-Transparent Bridge (NTB) in the Intel S1200
-and Xeon E3/E5 processor families.
The
-.Nm
-driver hides hardware details, exposing memory windows, scratchpads and
-doorbells via hardware independent KPI.
+.Nm ntb_hw_intel
+driver provides support for the Non-Transparent Bridge (NTB) hardware in
+Intel Xeon E3/E5 and S1200 processor families, which allow one of their PCIe
+ports to be switched from transparent to non-transparent bridge mode.
+In this mode bridge looks not as a PCI bridge, but as PCI endpoint device.
+The driver hides hardware details, exposing memory windows, scratchpads
+and doorbells of the other side via hardware independent KPI to
+.Xr ntb 4
+subsystem.
.Pp
-The hardware provides 2-3 memory windows to the other system's memory,
-16 scratchpad registers and 14/34 doorbells to interrupt the other system.
+The hardware provides 2 or 3 memory windows to the other system's memory,
+16 scratchpad registers and 14 or 34 doorbells to interrupt the other system.
On Xeon processors one of memory windows is typically consumed by the driver
-to workaround multiple hardware erratas.
+itself to workaround multiple hardware erratas.
.Sh CONFIGURATION
The NTB configuration should be set by BIOS.
-It includes enabling NTB, choosing between NTB-to-NTB or NTB-to-Root Port mode,
+It includes enabling NTB, choosing between NTB-to-NTB (back-to-back) or
+NTB-to-Root Port mode,
enabling split BAR mode (one of two 64-bit BARs can be split into two 32-bit
ones) and configuring BAR sizes in bits (from 12 to 29/39) for both NTB sides.
.Pp
@@ -93,7 +72,8 @@ all BAR sizes are set to 20 (1 MiB).
This needs to be done on both systems.
.Sh SEE ALSO
.Xr if_ntb 4 ,
-.Xr ntb_transport 4
+.Xr ntb_transport 4 ,
+.Xr ntb 4 ,
.Sh AUTHORS
.An -nosplit
The
diff --git a/share/man/man4/ntb_hw_plx.4 b/share/man/man4/ntb_hw_plx.4
new file mode 100644
index 000000000000..54500a11a9a3
--- /dev/null
+++ b/share/man/man4/ntb_hw_plx.4
@@ -0,0 +1,118 @@
+.\"
+.\" Copyright (c) 2017 Alexander Motin <mav@FreeBSD.org>
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd August 30, 2017
+.Dt NTB_HW_PLX 4
+.Os
+.Sh NAME
+.Nm ntb_hw_plx
+.Nd PLX/Avago/Broadcom Non-Transparent Bridge driver
+.Sh SYNOPSIS
+To compile this driver into your kernel,
+place the following lines in your kernel configuration file:
+.Bd -ragged -offset indent
+.Cd "device ntb"
+.Cd "device ntb_hw_plx"
+.Ed
+.Pp
+Or, to load the driver as a module at boot, place the following line in
+.Xr loader.conf 5 :
+.Bd -literal -offset indent
+ntb_hw_plx_load="YES"
+.Ed
+.Pp
+The following tunables are settable from the
+.Xr loader 8 :
+.Bl -ohang
+.It Va hint.ntb_hw. Ns Ar X Ns Va .b2b
+Being set to 1 (default) tells the driver attached to Virtual Interface of the
+NTB that it works in NTB-to-NTB (back-to-back) mode, 0 -- NTB-to-Root Port.
+Driver attached to Link Interface (visible from Root Port side) switches to
+NTB-to-Root Port mode automatically, but one attached to Virtual Interface
+can't detect what is on the other side and require external knowledge.
+.El
+.Sh DESCRIPTION
+The
+.Nm
+driver provides support for the Non-Transparent Bridge (NTB) hardware in
+PLX PCIe bridge chips, which allow up to two of their PCIe ports to be
+switched from transparent to non-transparent bridge mode.
+In this mode bridge looks not as a PCI bridge, but as PCI endpoint device.
+The driver hides hardware details, exposing memory windows, scratchpads
+and doorbells of the other side via hardware independent KPI to
+.Xr ntb 4
+subsystem.
+.Pp
+Each PLX NTB provides up to 2 64-bit or 4 32-bit memory windows to the
+other system's memory, 6 or 12 scratchpad registers and 16 doorbells to
+interrupt the other system.
+In NTB-to-NTB mode one of memory windows (or half of it, if bigger then 1MB)
+is consumed by the driver itself to access scratchpad and doorbell registers
+of the other side.
+.Sh HARDWARE
+The following PLX/Avago/Broadcom chips are supported by the
+.Nm
+driver:
+.Pp
+.Bl -bullet -compact
+.It
+PEX 8713
+.It
+PEX 8717
+.It
+PEX 8725
+.It
+PEX 8733
+.It
+PEX 8749
+.El
+.Pp
+, but it may also work with other compatible ones.
+.Sh CONFIGURATION
+The basic chip configuration should be done by serial EEPROM or via i2c.
+It includes enabling NTB on one or both sides (choosing between NTB-to-NTB
+(back-to-back) and NTB-to-Root Port modes) and configuring BARs sizes.
+.Pp
+The recommended mode is NTB-to-NTB mode, since while NTB-to-Root Port is
+generally supported by the driver, it require PCI hotplug handling on the
+Root Port, that may be difficult or cause different kinds of problems.
+.Sh SEE ALSO
+.Xr if_ntb 4 ,
+.Xr ntb_transport 4 ,
+.Xr ntb 4 ,
+.Sh AUTHORS
+.An -nosplit
+The
+.Nm
+driver was written by
+.An Alexander Motin Aq Mt mav@FreeBSD.org .
+.Sh BUGS
+There is no way to protect your system from malicious behavior on the other
+system once the link is brought up.
+Anyone with root or kernel access on the other system can read or write to
+any location on your system.
+In other words, only connect two systems that completely trust each other.
diff --git a/share/man/man4/ntb_transport.4 b/share/man/man4/ntb_transport.4
index 43b412cd8f5f..1a4fc3efba21 100644
--- a/share/man/man4/ntb_transport.4
+++ b/share/man/man4/ntb_transport.4
@@ -1,5 +1,5 @@
.\"
-.\" Copyright (c) 2016 Alexander Motin <mav@FreeBSD.org>
+.\" Copyright (c) 2016-2017 Alexander Motin <mav@FreeBSD.org>
.\" All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
@@ -25,14 +25,21 @@
.\"
.\" $FreeBSD$
.\"
-.Dd July 29, 2016
+.Dd August 30, 2017
.Dt NTB_TRANSPORT 4
.Os
.Sh NAME
.Nm ntb_transport
.Nd Packet-oriented transport for Non-Transparent Bridges
.Sh SYNOPSIS
-To load the driver as a module at boot, place the following line in
+To compile this driver into your kernel,
+place the following lines in your kernel configuration file:
+.Bd -ragged -offset indent
+.Cd "device ntb"
+.Cd "device ntb_transport"
+.Ed
+.Pp
+Or, to load the driver as a module at boot, place the following line in
.Xr loader.conf 5 :
.Bd -literal -offset indent
ntb_transport_load="YES"
@@ -46,11 +53,11 @@ Driver debug level.
The default value is 0, higher means more verbose.
.It Va hint.ntb_transport. Ns Ar X Ns Va .config
Configures queues allocation for consumer devices, separated by commas.
-Each device can be configured as: "<name>[:<queues>]", where:
+Each device can be configured as: "[<name>][:<queues>]", where:
.Va name
is a name of the driver which should attach the device (empty means any),
.Va queues
-is a number of queues to allocate (empty means automatic),
+is a number of queues to allocate (empty means automatic).
The default configuration is empty string, which means single device
with one queue per memory window allowing any driver attachment.
.El
@@ -64,9 +71,25 @@ delivering packets between the systems.
The primary purpose of this is to be used by
.Nm if_ntb
network interface, but other consumers may also be developed using KPI.
+.Pp
+Each
+.Nm
+require from underlying
+.Nm ntb
+instance:
+.Bl -bullet -compact
+.It
+1 or more memory windows;
+.It
+6 scratchpads, plus 2 more for each additional memory window;
+.It
+1 doorbell for each memory window or configured queue.
+.El
.Sh SEE ALSO
.Xr if_ntb 4 ,
-.Xr ntb_hw 4
+.Xr ntb 4 ,
+.Xr ntb_hw_intel 4 ,
+.Xr ntb_hw_plx 4
.Sh AUTHORS
.An -nosplit
The
diff --git a/sys/amd64/conf/NOTES b/sys/amd64/conf/NOTES
index 346c20a5be1b..5b7e1155bb0b 100644
--- a/sys/amd64/conf/NOTES
+++ b/sys/amd64/conf/NOTES
@@ -395,9 +395,14 @@ device iwn6000g2bfw
device iwn6050fw
device wpifw
-# Intel Non-Transparent Bridge (NTB) hardware
-device ntb_hw # Hardware Abstraction Layer for the NTB
-device if_ntb # Simulated ethernet device using the NTB
+#
+# Non-Transparent Bridge (NTB) drivers
+#
+device if_ntb # Virtual NTB network interface
+device ntb_transport # NTB packet transport driver
+device ntb # NTB hardware interface
+device ntb_hw_intel # Intel NTB hardware driver
+device ntb_hw_plx # PLX NTB hardware driver
#
#XXX this stores pointers in a 32bit field that is defined by the hardware
diff --git a/sys/conf/files.amd64 b/sys/conf/files.amd64
index a9b926f83c97..aae4765eaff7 100644
--- a/sys/conf/files.amd64
+++ b/sys/conf/files.amd64
@@ -330,10 +330,11 @@ dev/hyperv/vmbus/amd64/vmbus_vector.S optional hyperv
dev/nctgpio/nctgpio.c optional nctgpio
dev/nfe/if_nfe.c optional nfe pci
dev/ntb/if_ntb/if_ntb.c optional if_ntb
-dev/ntb/ntb_transport.c optional if_ntb
-dev/ntb/ntb.c optional if_ntb | ntb_hw
-dev/ntb/ntb_if.m optional if_ntb | ntb_hw
-dev/ntb/ntb_hw/ntb_hw.c optional ntb_hw
+dev/ntb/ntb_transport.c optional ntb_transport | if_ntb
+dev/ntb/ntb.c optional ntb | ntb_transport | if_ntb | ntb_hw_intel | ntb_hw_plx | ntb_hw
+dev/ntb/ntb_if.m optional ntb | ntb_transport | if_ntb | ntb_hw_intel | ntb_hw_plx | ntb_hw
+dev/ntb/ntb_hw/ntb_hw_intel.c optional ntb_hw_intel | ntb_hw
+dev/ntb/ntb_hw/ntb_hw_plx.c optional ntb_hw_plx | ntb_hw
dev/nvd/nvd.c optional nvd nvme
dev/nvme/nvme.c optional nvme
dev/nvme/nvme_ctrlr.c optional nvme
diff --git a/sys/conf/files.i386 b/sys/conf/files.i386
index 294379d000c4..c0ec01b5fcde 100644
--- a/sys/conf/files.i386
+++ b/sys/conf/files.i386
@@ -271,10 +271,11 @@ dev/mse/mse_isa.c optional mse isa
dev/nctgpio/nctgpio.c optional nctgpio
dev/nfe/if_nfe.c optional nfe pci
dev/ntb/if_ntb/if_ntb.c optional if_ntb
-dev/ntb/ntb_transport.c optional if_ntb
-dev/ntb/ntb.c optional if_ntb | ntb_hw
-dev/ntb/ntb_if.m optional if_ntb | ntb_hw
-dev/ntb/ntb_hw/ntb_hw.c optional ntb_hw
+dev/ntb/ntb_transport.c optional ntb_transport | if_ntb
+dev/ntb/ntb.c optional ntb | ntb_transport | if_ntb | ntb_hw_intel | ntb_hw_plx
+dev/ntb/ntb_if.m optional ntb | ntb_transport | if_ntb | ntb_hw_intel | ntb_hw_plx
+dev/ntb/ntb_hw/ntb_hw_intel.c optional ntb_hw_intel
+dev/ntb/ntb_hw/ntb_hw_plx.c optional ntb_hw_plx
dev/nvd/nvd.c optional nvd nvme
dev/nvme/nvme.c optional nvme
dev/nvme/nvme_ctrlr.c optional nvme
diff --git a/sys/dev/ntb/ntb_hw/ntb_hw.c b/sys/dev/ntb/ntb_hw/ntb_hw_intel.c
index 9c8314f5a089..2375fb8005e4 100644
--- a/sys/dev/ntb/ntb_hw/ntb_hw.c
+++ b/sys/dev/ntb/ntb_hw/ntb_hw_intel.c
@@ -61,7 +61,7 @@ __FBSDID("$FreeBSD$");
#include <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>
-#include "ntb_regs.h"
+#include "ntb_hw_intel.h"
#include "../ntb.h"
#define MAX_MSIX_INTERRUPTS MAX(XEON_DB_COUNT, ATOM_DB_COUNT)
@@ -3116,6 +3116,6 @@ static device_method_t ntb_intel_methods[] = {
static DEFINE_CLASS_0(ntb_hw, ntb_intel_driver, ntb_intel_methods,
sizeof(struct ntb_softc));
-DRIVER_MODULE(ntb_intel, pci, ntb_intel_driver, ntb_hw_devclass, NULL, NULL);
-MODULE_DEPEND(ntb_intel, ntb, 1, 1, 1);
-MODULE_VERSION(ntb_intel, 1);
+DRIVER_MODULE(ntb_hw_intel, pci, ntb_intel_driver, ntb_hw_devclass, NULL, NULL);
+MODULE_DEPEND(ntb_hw_intel, ntb, 1, 1, 1);
+MODULE_VERSION(ntb_hw_intel, 1);
diff --git a/sys/dev/ntb/ntb_hw/ntb_regs.h b/sys/dev/ntb/ntb_hw/ntb_hw_intel.h
index a03773627aa3..a03773627aa3 100644
--- a/sys/dev/ntb/ntb_hw/ntb_regs.h
+++ b/sys/dev/ntb/ntb_hw/ntb_hw_intel.h
diff --git a/sys/dev/ntb/ntb_hw/ntb_hw_plx.c b/sys/dev/ntb/ntb_hw/ntb_hw_plx.c
new file mode 100644
index 000000000000..8b7eb356ba11
--- /dev/null
+++ b/sys/dev/ntb/ntb_hw/ntb_hw_plx.c
@@ -0,0 +1,945 @@
+/*-
+ * Copyright (c) 2017 Alexander Motin <mav@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * The Non-Transparent Bridge (NTB) is a device that allows you to connect
+ * two or more systems using a PCI-e links, providing remote memory access.
+ *
+ * This module contains a driver for NTBs in PLX/Avago/Broadcom PCIe bridges.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/interrupt.h>
+#include <sys/module.h>
+#include <sys/rman.h>
+#include <sys/sysctl.h>
+#include <vm/vm.h>
+#include <vm/pmap.h>
+#include <machine/bus.h>
+#include <machine/intr_machdep.h>
+#include <machine/resource.h>
+#include <dev/pci/pcireg.h>
+#include <dev/pci/pcivar.h>
+
+#include "../ntb.h"
+
+#define PLX_MAX_BARS 4 /* There are at most 4 data BARs. */
+#define PLX_NUM_SPAD 8 /* There are 8 scratchpads. */
+#define PLX_NUM_SPAD_PATT 4 /* Use test pattern as 4 more. */
+#define PLX_NUM_DB 16 /* There are 16 doorbells. */
+
+struct ntb_plx_mw_info {
+ int mw_bar;
+ int mw_64bit;
+ int mw_rid;
+ struct resource *mw_res;
+ vm_paddr_t mw_pbase;
+ caddr_t mw_vbase;
+ vm_size_t mw_size;
+ vm_memattr_t mw_map_mode;
+ bus_addr_t mw_xlat_addr;
+ size_t mw_xlat_size;
+};
+
+struct ntb_plx_softc {
+ /* ntb.c context. Do not move! Must go first! */
+ void *ntb_store;
+
+ device_t dev;
+ struct resource *conf_res;
+ int conf_rid;
+ u_int ntx; /* NTx number within chip. */
+ u_int link; /* Link v/s Virtual side. */
+ u_int port; /* Port number within chip. */
+
+ int int_rid;
+ struct resource *int_res;
+ void *int_tag;
+
+ struct ntb_plx_mw_info mw_info[PLX_MAX_BARS];
+ int mw_count; /* Number of memory windows. */
+
+ int spad_count1; /* Number of standard spads. */
+ int spad_count2; /* Number of extra spads. */
+ uint32_t spad_off1; /* Offset of our spads. */
+ uint32_t spad_off2; /* Offset of our extra spads. */
+ uint32_t spad_offp1; /* Offset of peer spads. */
+ uint32_t spad_offp2; /* Offset of peer extra spads. */
+
+ /* Parameters of window shared with peer config access in B2B mode. */
+ int b2b_mw; /* Shared window number. */
+ uint64_t b2b_off; /* Offset in shared window. */
+};
+
+#define PLX_NT0_BASE 0x3E000
+#define PLX_NT1_BASE 0x3C000
+#define PLX_NTX_BASE(sc) ((sc)->ntx ? PLX_NT1_BASE : PLX_NT0_BASE)
+#define PLX_NTX_LINK_OFFSET 0x01000
+
+/* Bases of NTx our/peer interface registers */
+#define PLX_NTX_OUR(sc) \
+ (PLX_NTX_BASE(sc) + ((sc)->link ? PLX_NTX_LINK_OFFSET : 0))
+#define PLX_NTX_PEER(sc) \
+ (PLX_NTX_BASE(sc) + ((sc)->link ? 0 : PLX_NTX_LINK_OFFSET))
+
+/* Read/write NTx our interface registers */
+#define NTX_READ(sc, reg) \
+ bus_read_4((sc)->conf_res, PLX_NTX_OUR(sc) + (reg))
+#define NTX_WRITE(sc, reg, val) \
+ bus_write_4((sc)->conf_res, PLX_NTX_OUR(sc) + (reg), (val))
+
+/* Read/write NTx peer interface registers */
+#define PNTX_READ(sc, reg) \
+ bus_read_4((sc)->conf_res, PLX_NTX_PEER(sc) + (reg))
+#define PNTX_WRITE(sc, reg, val) \
+ bus_write_4((sc)->conf_res, PLX_NTX_PEER(sc) + (reg), (val))
+
+/* Read/write B2B NTx registers */
+#define BNTX_READ(sc, reg) \
+ bus_read_4((sc)->mw_info[(sc)->b2b_mw].mw_res, \
+ PLX_NTX_BASE(sc) + (reg))
+#define BNTX_WRITE(sc, reg, val) \
+ bus_write_4((sc)->mw_info[(sc)->b2b_mw].mw_res, \
+ PLX_NTX_BASE(sc) + (reg), (val))
+
+static int ntb_plx_init(device_t dev);
+static int ntb_plx_detach(device_t dev);
+static int ntb_plx_mw_set_trans_internal(device_t dev, unsigned mw_idx);
+
+static int
+ntb_plx_probe(device_t dev)
+{
+
+ switch (pci_get_devid(dev)) {
+ case 0x87a010b5:
+ device_set_desc(dev, "PLX Non-Transparent Bridge NT0 Link");
+ return (BUS_PROBE_DEFAULT);
+ case 0x87a110b5:
+ device_set_desc(dev, "PLX Non-Transparent Bridge NT1 Link");
+ return (BUS_PROBE_DEFAULT);
+ case 0x87b010b5:
+ device_set_desc(dev, "PLX Non-Transparent Bridge NT0 Virtual");
+ return (BUS_PROBE_DEFAULT);
+ case 0x87b110b5:
+ device_set_desc(dev, "PLX Non-Transparent Bridge NT1 Virtual");
+ return (BUS_PROBE_DEFAULT);
+ }
+ return (ENXIO);
+}
+
+static int
+ntb_plx_init(device_t dev)
+{
+ struct ntb_plx_softc *sc = device_get_softc(dev);
+ struct ntb_plx_mw_info *mw;
+ uint64_t val64;
+ int i;
+ uint32_t val;
+
+ if (sc->b2b_mw >= 0) {
+ /* Set peer BAR0/1 size and address for B2B NTx access. */
+ mw = &sc->mw_info[sc->b2b_mw];
+ if (mw->mw_64bit) {
+ PNTX_WRITE(sc, 0xe4, 0x3); /* 64-bit */
+ val64 = 0x2000000000000000 * mw->mw_bar | 0x4;
+ PNTX_WRITE(sc, PCIR_BAR(0), val64);
+ PNTX_WRITE(sc, PCIR_BAR(0) + 4, val64 >> 32);
+ } else {
+ PNTX_WRITE(sc, 0xe4, 0x2); /* 32-bit */
+ val = 0x20000000 * mw->mw_bar;
+ PNTX_WRITE(sc, PCIR_BAR(0), val);
+ }
+
+ /* Set Virtual to Link address translation for B2B. */
+ for (i = 0; i < sc->mw_count; i++) {
+ mw = &sc->mw_info[i];
+ if (mw->mw_64bit) {
+ val64 = 0x2000000000000000 * mw->mw_bar;
+ NTX_WRITE(sc, 0xc3c + (mw->mw_bar - 2) * 4, val64);
+ NTX_WRITE(sc, 0xc3c + (mw->mw_bar - 2) * 4 + 4, val64 >> 32);
+ } else {
+ val = 0x20000000 * mw->mw_bar;
+ NTX_WRITE(sc, 0xc3c + (mw->mw_bar - 2) * 4, val);
+ }
+ }
+
+ /* Enable Link Interface LUT entry 0 for 0:0.0. */
+ PNTX_WRITE(sc, 0xdb4, 1);
+ }
+
+ /*
+ * Enable Virtual Interface LUT entry 0 for 0:0.0 and
+ * entry 1 for our Requester ID reported by chip.
+ */
+ val = (NTX_READ(sc, 0xc90) << 16) | 0x00010001;
+ NTX_WRITE(sc, sc->link ? 0xdb4 : 0xd94, val);
+
+ /* Set Link to Virtual address translation. */
+ for (i = 0; i < sc->mw_count; i++) {
+ mw = &sc->mw_info[i];
+ if (mw->mw_xlat_size != 0)
+ ntb_plx_mw_set_trans_internal(dev, i);
+ }
+
+ pci_enable_busmaster(dev);
+ if (sc->b2b_mw >= 0)
+ PNTX_WRITE(sc, PCIR_COMMAND, PCIM_CMD_MEMEN | PCIM_CMD_BUSMASTEREN);
+
+ return (0);
+}
+
+static void
+ntb_plx_isr(void *arg)
+{
+ device_t dev = arg;
+ struct ntb_plx_softc *sc = device_get_softc(dev);
+ uint32_t val;
+
+ ntb_db_event((device_t)arg, 0);
+
+ val = NTX_READ(sc, 0xfe0);
+ if (val == 0)
+ return;
+ NTX_WRITE(sc, 0xfe0, val);
+ if (val & 1)
+ device_printf(dev, "Correctable Error\n");
+ if (val & 2)
+ device_printf(dev, "Uncorrectable Error\n");
+ if (val & 4) {
+ /* DL_Down resets link side registers, have to reinit. */
+ ntb_plx_init(dev);
+ ntb_link_event(dev);
+ }
+ if (val & 8)
+ device_printf(dev, "Uncorrectable Error Message Drop\n");
+}
+
+static int
+ntb_plx_setup_intr(device_t dev)
+{
+ struct ntb_plx_softc *sc = device_get_softc(dev);
+ int error;
+
+ /*
+ * XXX: This hardware supports MSI, but I found it unusable.
+ * It generates new MSI only when doorbell register goes from
+ * zero, but does not generate it when another bit is set or on
+ * partial clear. It makes operation very racy and unreliable.
+ * The data book mentions some mask juggling magic to workaround
+ * that, but I failed to make it work.
+ */
+ sc->int_rid = 0;
+ sc->int_res = bus_alloc_resource_any(dev, SYS_RES_IRQ,
+ &sc->int_rid, RF_SHAREABLE|RF_ACTIVE);
+ if (sc->int_res == NULL) {
+ device_printf(dev, "bus_alloc_resource failed\n");
+ return (ENOMEM);
+ }
+ error = bus_setup_intr(dev, sc->int_res, INTR_MPSAFE | INTR_TYPE_MISC,
+ NULL, ntb_plx_isr, dev, &sc->int_tag);
+ if (error != 0) {
+ device_printf(dev, "bus_setup_intr failed: %d\n", error);
+ return (error);
+ }
+ NTX_WRITE(sc, 0xfe0, 0xf); /* Clear link interrupts. */
+ NTX_WRITE(sc, 0xfe4, 0x0); /* Unmask link interrupts. */
+ return (0);
+}
+
+static void
+ntb_plx_teardown_intr(device_t dev)
+{
+ struct ntb_plx_softc *sc = device_get_softc(dev);
+
+ NTX_WRITE(sc, 0xfe4, 0xf); /* Mask link interrupts. */
+ if (sc->int_res) {
+ bus_teardown_intr(dev, sc->int_res, sc->int_tag);
+ bus_release_resource(dev, SYS_RES_IRQ, sc->int_rid,
+ sc->int_res);
+ }
+}
+
+static int
+ntb_plx_attach(device_t dev)
+{
+ struct ntb_plx_softc *sc = device_get_softc(dev);
+ struct ntb_plx_mw_info *mw;
+ int error = 0, i;
+ uint32_t val;
+ char buf[32];
+
+ /* Identify what we are (what side of what NTx). */
+ sc->dev = dev;
+ val = pci_read_config(dev, 0xc8c, 4);
+ sc->ntx = (val & 1) != 0;
+ sc->link = (val & 0x80000000) != 0;
+
+ /* Get access to whole 256KB of chip configuration space via BAR0/1. */
+ sc->conf_rid = PCIR_BAR(0);
+ sc->conf_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
+ &sc->conf_rid, RF_ACTIVE);
+ if (sc->conf_res == NULL) {
+ device_printf(dev, "Can't allocate configuration BAR.\n");
+ return (ENXIO);
+ }
+ pmap_change_attr((vm_offset_t)rman_get_start(sc->conf_res),
+ rman_get_size(sc->conf_res), VM_MEMATTR_UNCACHEABLE);
+
+ /* Identify chip port we are connected to. */
+ val = bus_read_4(sc->conf_res, 0x360);
+ sc->port = (val >> ((sc->ntx == 0) ? 8 : 16)) & 0x1f;
+
+ /* Find configured memory windows at BAR2-5. */
+ sc->mw_count = 0;
+ for (i = 2; i <= 5; i++) {
+ mw = &sc->mw_info[sc->mw_count];
+ mw->mw_bar = i;
+ mw->mw_rid = PCIR_BAR(mw->mw_bar);
+ mw->mw_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
+ &mw->mw_rid, RF_ACTIVE);
+ if (mw->mw_res == NULL)
+ continue;
+ mw->mw_pbase = rman_get_start(mw->mw_res);
+ mw->mw_size = rman_get_size(mw->mw_res);
+ mw->mw_vbase = rman_get_virtual(mw->mw_res);
+ mw->mw_map_mode = VM_MEMATTR_UNCACHEABLE;
+ pmap_change_attr((vm_offset_t)mw->mw_vbase, mw->mw_size,
+ mw->mw_map_mode);
+ sc->mw_count++;
+
+ /* Skip over adjacent BAR for 64-bit BARs. */
+ val = pci_read_config(dev, PCIR_BAR(mw->mw_bar), 4);
+ if ((val & PCIM_BAR_MEM_TYPE) == PCIM_BAR_MEM_64) {
+ mw->mw_64bit = 1;
+ i++;
+ }
+ }
+
+ /* Try to identify B2B mode. */
+ i = 1;
+ snprintf(buf, sizeof(buf), "hint.%s.%d.b2b", device_get_name(dev),
+ device_get_unit(dev));
+ TUNABLE_INT_FETCH(buf, &i);
+ if (sc->link) {
+ device_printf(dev, "NTB-to-Root Port mode (Link Interface)\n");
+ sc->b2b_mw = -1;
+ } else if (i == 0) {
+ device_printf(dev, "NTB-to-Root Port mode (Virtual Interface)\n");
+ sc->b2b_mw = -1;
+ } else {
+ device_printf(dev, "NTB-to-NTB (back-to-back) mode\n");
+
+ /* We need at least one memory window for B2B peer access. */
+ if (sc->mw_count == 0) {
+ device_printf(dev, "No memory window BARs enabled.\n");
+ error = ENXIO;
+ goto out;
+ }
+ sc->b2b_mw = sc->mw_count - 1;
+
+ /* Use half of the window for B2B, but no less then 1MB. */
+ mw = &sc->mw_info[sc->b2b_mw];
+ if (mw->mw_size >= 2 * 1024 * 1024)
+ sc->b2b_off = mw->mw_size / 2;
+ else
+ sc->b2b_off = 0;
+ }
+
+ /*
+ * Use Physical Layer User Test Pattern as additional scratchpad.
+ * Make sure they are present and enabled by writing to them.
+ * XXX: Its a hack, but standard 8 registers are not enough.
+ */
+ if (sc->b2b_mw >= 0) {
+ sc->spad_count1 = PLX_NUM_SPAD;
+ sc->spad_off1 = PLX_NTX_OUR(sc) + 0xc6c;
+ sc->spad_off2 = (sc->ntx == 0) ? 0x0020c : 0x0820c;
+ sc->spad_offp1 = sc->spad_off1;
+ sc->spad_offp2 = sc->spad_off2;
+ bus_write_4(sc->conf_res, sc->spad_off2, 0x12345678);
+ if (bus_read_4(sc->conf_res, sc->spad_off2) == 0x12345678)
+ sc->spad_count2 = PLX_NUM_SPAD_PATT;
+ } else {
+ sc->spad_count1 = PLX_NUM_SPAD / 2;
+ sc->spad_off1 = PLX_NTX_OUR(sc) + 0xc6c;
+ sc->spad_off2 = (sc->ntx == 0) ? 0x0020c : 0x0820c;
+ sc->spad_offp1 = sc->spad_off1;
+ sc->spad_offp2 = sc->spad_off2;
+ if (sc->link) {
+ sc->spad_off1 += PLX_NUM_SPAD / 2 * 4;
+ sc->spad_off2 += PLX_NUM_SPAD_PATT / 2 * 4;
+ } else {
+ sc->spad_offp1 += PLX_NUM_SPAD / 2 * 4;
+ sc->spad_offp2 += PLX_NUM_SPAD_PATT / 2 * 4;
+ }
+ bus_write_4(sc->conf_res, sc->spad_off2, 0x12345678);
+ if (bus_read_4(sc->conf_res, sc->spad_off2) == 0x12345678)
+ sc->spad_count2 = PLX_NUM_SPAD_PATT / 2;
+ }
+
+ /* Apply static part of NTB configuration. */
+ ntb_plx_init(dev);
+
+ /* Allocate and setup interrupts. */
+ error = ntb_plx_setup_intr(dev);
+ if (error)
+ goto out;
+
+ /* Attach children to this controller */
+ error = ntb_register_device(dev);
+
+out:
+ if (error != 0)
+ ntb_plx_detach(dev);
+ return (error);
+}
+
+static int
+ntb_plx_detach(device_t dev)
+{
+ struct ntb_plx_softc *sc = device_get_softc(dev);
+ struct ntb_plx_mw_info *mw;
+ int i;
+
+ /* Detach & delete all children */
+ ntb_unregister_device(dev);
+
+ /* Disable and free interrupts. */
+ ntb_plx_teardown_intr(dev);
+
+ /* Free memory resources. */
+ for (i = 0; i < sc->mw_count; i++) {
+ mw = &sc->mw_info[i];
+ bus_release_resource(dev, SYS_RES_MEMORY, mw->mw_rid,
+ mw->mw_res);
+ }
+ bus_release_resource(dev, SYS_RES_MEMORY, sc->conf_rid, sc->conf_res);
+ return (0);
+}
+
+
+static bool
+ntb_plx_link_is_up(device_t dev, enum ntb_speed *speed, enum ntb_width *width)
+{
+ uint16_t link;
+
+ link = pcie_read_config(dev, PCIER_LINK_STA, 2);
+ if (speed != NULL)
+ *speed = (link & PCIEM_LINK_STA_SPEED);
+ if (width != NULL)
+ *width = (link & PCIEM_LINK_STA_WIDTH) >> 4;
+ return ((link & PCIEM_LINK_STA_WIDTH) != 0);
+}
+
+static int
+ntb_plx_link_enable(device_t dev, enum ntb_speed speed __unused,
+ enum ntb_width width __unused)
+{
+ struct ntb_plx_softc *sc = device_get_softc(dev);
+ uint32_t reg, val;
+
+ /* The fact that we see the Link Interface means link is enabled. */
+ if (sc->link) {
+ ntb_link_event(dev);
+ return (0);
+ }
+
+ reg = (sc->port < 8) ? 0x00208 : 0x08208;
+ val = bus_read_4(sc->conf_res, reg);
+ if ((val & (1 << (sc->port & 7))) == 0) {
+ /* If already enabled, generate fake link event and exit. */
+ ntb_link_event(dev);
+ return (0);
+ }
+ val &= ~(1 << (sc->port & 7));
+ bus_write_4(sc->conf_res, reg, val);
+ return (0);
+}
+
+static int
+ntb_plx_link_disable(device_t dev)
+{
+ struct ntb_plx_softc *sc = device_get_softc(dev);
+ uint32_t reg, val;
+
+ /* Link disable for Link Interface would be suicidal. */
+ if (sc->link)
+ return (0);
+
+ reg = (sc->port < 8) ? 0x00208 : 0x08208;
+ val = bus_read_4(sc->conf_res, reg);
+ val |= (1 << (sc->port & 7));
+ bus_write_4(sc->conf_res, reg, val);
+ return (0);
+}
+
+static bool
+ntb_plx_link_enabled(device_t dev)
+{
+ struct ntb_plx_softc *sc = device_get_softc(dev);
+ uint32_t reg, val;
+
+ /* The fact that we see the Link Interface means link is enabled. */
+ if (sc->link)
+ return (TRUE);
+
+ reg = (sc->port < 8) ? 0x00208 : 0x08208;
+ val = bus_read_4(sc->conf_res, reg);
+ return ((val & (1 << (sc->port & 7))) == 0);
+}
+
+static uint8_t
+ntb_plx_mw_count(device_t dev)
+{
+ struct ntb_plx_softc *sc = device_get_softc(dev);
+
+ if (sc->b2b_mw >= 0 && sc->b2b_off == 0)
+ return (sc->mw_count - 1); /* B2B consumed whole window. */
+ return (sc->mw_count);
+}
+
+static int
+ntb_plx_mw_get_range(device_t dev, unsigned mw_idx, vm_paddr_t *base,
+ caddr_t *vbase, size_t *size, size_t *align, size_t *align_size,
+ bus_addr_t *plimit)
+{
+ struct ntb_plx_softc *sc = device_get_softc(dev);
+ struct ntb_plx_mw_info *mw;
+ size_t off;
+
+ if (mw_idx >= sc->mw_count)
+ return (EINVAL);
+ off = 0;
+ if (mw_idx == sc->b2b_mw) {
+ KASSERT(sc->b2b_off != 0,
+ ("user shouldn't get non-shared b2b mw"));
+ off = sc->b2b_off;
+ }
+ mw = &sc->mw_info[mw_idx];
+
+ /* Local to remote memory window parameters. */
+ if (base != NULL)
+ *base = mw->mw_pbase + off;
+ if (vbase != NULL)
+ *vbase = mw->mw_vbase + off;
+ if (size != NULL)
+ *size = mw->mw_size - off;
+
+ /*
+ * Remote to local memory window translation address alignment.
+ * XXX: In B2B mode we can change window size (and so alignmet)
+ * live, but there is no way to report it, so report safe value.
+ */
+ if (align != NULL)
+ *align = mw->mw_size - off;
+
+ /*
+ * Remote to local memory window size alignment.
+ * XXX: The chip has no limit registers. In B2B case size must be
+ * power of 2 (since we can reprogram BAR size), but there is no way
+ * to report it, so report 1MB -- minimal BAR size. In non-B2B case
+ * there is no control at all, so report the precofigured BAR size.
+ */
+ if (align_size != NULL) {
+ if (sc->b2b_mw >= 0)
+ *align_size = 1024 * 1024;
+ else
+ *align_size = mw->mw_size - off;
+ }
+
+ /* Remote to local memory window translation address upper limit. */
+ if (plimit != NULL)
+ *plimit = mw->mw_64bit ? BUS_SPACE_MAXADDR :
+ BUS_SPACE_MAXADDR_32BIT;
+ return (0);
+}
+
+static int
+ntb_plx_mw_set_trans_internal(device_t dev, unsigned mw_idx)
+{
+ struct ntb_plx_softc *sc = device_get_softc(dev);
+ struct ntb_plx_mw_info *mw;
+ uint64_t addr, off, size, val64;
+ uint32_t val;
+
+ mw = &sc->mw_info[mw_idx];
+ addr = mw->mw_xlat_addr;
+ size = mw->mw_xlat_size;
+ off = 0;
+ if (mw_idx == sc->b2b_mw) {
+ off = sc->b2b_off;
+ KASSERT(off != 0, ("user shouldn't get non-shared b2b mw"));
+
+ /*
+ * While generally we can set any BAR size on link side,
+ * for B2B shared window we can't go above preconfigured
+ * size due to BAR address alignment requirements.
+ */
+ if (size > mw->mw_size - off)
+ return (EINVAL);
+ }
+
+ if (size > 0) {
+ /* Round BAR size to next power of 2 or at least 1MB. */
+ if (!powerof2(size))
+ size = 1LL << flsll(size);
+ if (size < 1024 * 1024)
+ size = 1024 * 1024;
+
+ /* Hardware requires addr aligned to BAR size. */
+ if ((addr & (size - 1)) != 0)
+ return (EINVAL);
+ }
+
+ if (mw->mw_64bit) {
+ if (sc->b2b_mw >= 0) {
+ /* Set Link Interface BAR size and enable/disable it. */
+ val64 = 0;
+ if (size > 0)
+ val64 = (~(size - 1) & ~0xfffff);
+ val64 |= 0x4;
+ PNTX_WRITE(sc, 0xe8 + (mw->mw_bar - 2) * 4, val64);
+ PNTX_WRITE(sc, 0xe8 + (mw->mw_bar - 2) * 4 + 4, val64 >> 32);
+
+ /* Set Link Interface BAR address. */
+ val64 = 0x2000000000000000 * mw->mw_bar + off;
+ val64 |= 0x4;
+ PNTX_WRITE(sc, PCIR_BAR(mw->mw_bar), val64);
+ PNTX_WRITE(sc, PCIR_BAR(mw->mw_bar) + 4, val64 >> 32);
+ }
+
+ /* Set Virtual Interface BARs address translation */
+ PNTX_WRITE(sc, 0xc3c + (mw->mw_bar - 2) * 4, addr);
+ PNTX_WRITE(sc, 0xc3c + (mw->mw_bar - 2) * 4 + 4, addr >> 32);
+ } else {
+ /* Make sure we fit into 32-bit address space. */
+ if ((addr & UINT32_MAX) != addr)
+ return (ERANGE);
+ if (((addr + size) & UINT32_MAX) != (addr + size))
+ return (ERANGE);
+
+ if (sc->b2b_mw >= 0) {
+ /* Set Link Interface BAR size and enable/disable it. */
+ val = 0;
+ if (size > 0)
+ val = (~(size - 1) & ~0xfffff);
+ PNTX_WRITE(sc, 0xe8 + (mw->mw_bar - 2) * 4, val);
+
+ /* Set Link Interface BAR address. */
+ val64 = 0x20000000 * mw->mw_bar + off;
+ PNTX_WRITE(sc, PCIR_BAR(mw->mw_bar), val64);
+ }
+
+ /* Set Virtual Interface BARs address translation */
+ PNTX_WRITE(sc, 0xc3c + (mw->mw_bar - 2) * 4, addr);
+ }
+ return (0);
+}
+
+static int
+ntb_plx_mw_set_trans(device_t dev, unsigned mw_idx, bus_addr_t addr, size_t size)
+{
+ struct ntb_plx_softc *sc = device_get_softc(dev);
+ struct ntb_plx_mw_info *mw;
+
+ if (mw_idx >= sc->mw_count)
+ return (EINVAL);
+ mw = &sc->mw_info[mw_idx];
+ mw->mw_xlat_addr = addr;
+ mw->mw_xlat_size = size;
+ return (ntb_plx_mw_set_trans_internal(dev, mw_idx));
+}
+
+static int
+ntb_plx_mw_clear_trans(device_t dev, unsigned mw_idx)
+{
+
+ return (ntb_plx_mw_set_trans(dev, mw_idx, 0, 0));
+}
+
+static int
+ntb_plx_mw_get_wc(device_t dev, unsigned idx, vm_memattr_t *mode)
+{
+ struct ntb_plx_softc *sc = device_get_softc(dev);
+ struct ntb_plx_mw_info *mw;
+
+ if (idx >= sc->mw_count)
+ return (EINVAL);
+ mw = &sc->mw_info[idx];
+ *mode = mw->mw_map_mode;
+ return (0);
+}
+
+static int
+ntb_plx_mw_set_wc(device_t dev, unsigned idx, vm_memattr_t mode)
+{
+ struct ntb_plx_softc *sc = device_get_softc(dev);
+ struct ntb_plx_mw_info *mw;
+ uint64_t off;
+ int rc;
+
+ if (idx >= sc->mw_count)
+ return (EINVAL);
+ mw = &sc->mw_info[idx];
+ if (mw->mw_map_mode == mode)
+ return (0);
+
+ off = 0;
+ if (idx == sc->b2b_mw) {
+ KASSERT(sc->b2b_off != 0,
+ ("user shouldn't get non-shared b2b mw"));
+ off = sc->b2b_off;
+ }
+
+ rc = pmap_change_attr((vm_offset_t)mw->mw_vbase + off,
+ mw->mw_size - off, mode);
+ if (rc == 0)
+ mw->mw_map_mode = mode;
+ return (rc);
+}
+
+static uint8_t
+ntb_plx_spad_count(device_t dev)
+{
+ struct ntb_plx_softc *sc = device_get_softc(dev);
+
+ return (sc->spad_count1 + sc->spad_count2);
+}
+
+static int
+ntb_plx_spad_write(device_t dev, unsigned int idx, uint32_t val)
+{
+ struct ntb_plx_softc *sc = device_get_softc(dev);
+ u_int off;
+
+ if (idx >= sc->spad_count1 + sc->spad_count2)
+ return (EINVAL);
+
+ if (idx < sc->spad_count1)
+ off = sc->spad_off1 + idx * 4;
+ else
+ off = sc->spad_off2 + (idx - sc->spad_count1) * 4;
+ bus_write_4(sc->conf_res, off, val);
+ return (0);
+}
+
+static void
+ntb_plx_spad_clear(device_t dev)
+{
+ struct ntb_plx_softc *sc = device_get_softc(dev);
+ int i;
+
+ for (i = 0; i < sc->spad_count1 + sc->spad_count2; i++)
+ ntb_plx_spad_write(dev, i, 0);
+}
+
+static int
+ntb_plx_spad_read(device_t dev, unsigned int idx, uint32_t *val)
+{
+ struct ntb_plx_softc *sc = device_get_softc(dev);
+ u_int off;
+
+ if (idx >= sc->spad_count1 + sc->spad_count2)
+ return (EINVAL);
+
+ if (idx < sc->spad_count1)
+ off = sc->spad_off1 + idx * 4;
+ else
+ off = sc->spad_off2 + (idx - sc->spad_count1) * 4;
+ *val = bus_read_4(sc->conf_res, off);
+ return (0);
+}
+
+static int
+ntb_plx_peer_spad_write(device_t dev, unsigned int idx, uint32_t val)
+{
+ struct ntb_plx_softc *sc = device_get_softc(dev);
+ u_int off;
+
+ if (idx >= sc->spad_count1 + sc->spad_count2)
+ return (EINVAL);
+
+ if (idx < sc->spad_count1)
+ off = sc->spad_offp1 + idx * 4;
+ else
+ off = sc->spad_offp2 + (idx - sc->spad_count1) * 4;
+ if (sc->b2b_mw >= 0)
+ bus_write_4(sc->mw_info[sc->b2b_mw].mw_res, off, val);
+ else
+ bus_write_4(sc->conf_res, off, val);
+ return (0);
+}
+
+static int
+ntb_plx_peer_spad_read(device_t dev, unsigned int idx, uint32_t *val)
+{
+ struct ntb_plx_softc *sc = device_get_softc(dev);
+ u_int off;
+
+ if (idx >= sc->spad_count1 + sc->spad_count2)
+ return (EINVAL);
+
+ if (idx < sc->spad_count1)
+ off = sc->spad_offp1 + idx * 4;
+ else
+ off = sc->spad_offp2 + (idx - sc->spad_count1) * 4;
+ if (sc->b2b_mw >= 0)
+ *val = bus_read_4(sc->mw_info[sc->b2b_mw].mw_res, off);
+ else
+ *val = bus_read_4(sc->conf_res, off);
+ return (0);
+}
+
+static uint64_t
+ntb_plx_db_valid_mask(device_t dev)
+{
+
+ return ((1LL << PLX_NUM_DB) - 1);
+}
+
+static int
+ntb_plx_db_vector_count(device_t dev)
+{
+
+ return (1);
+}
+
+static uint64_t
+ntb_plx_db_vector_mask(device_t dev, uint32_t vector)
+{
+
+ if (vector > 0)
+ return (0);
+ return ((1LL << PLX_NUM_DB) - 1);
+}
+
+static void
+ntb_plx_db_clear(device_t dev, uint64_t bits)
+{
+ struct ntb_plx_softc *sc = device_get_softc(dev);
+
+ NTX_WRITE(sc, sc->link ? 0xc60 : 0xc50, bits);
+}
+
+static void
+ntb_plx_db_clear_mask(device_t dev, uint64_t bits)
+{
+ struct ntb_plx_softc *sc = device_get_softc(dev);
+
+ NTX_WRITE(sc, sc->link ? 0xc68 : 0xc58, bits);
+}
+
+static uint64_t
+ntb_plx_db_read(device_t dev)
+{
+ struct ntb_plx_softc *sc = device_get_softc(dev);
+
+ return (NTX_READ(sc, sc->link ? 0xc5c : 0xc4c));
+}
+
+static void
+ntb_plx_db_set_mask(device_t dev, uint64_t bits)
+{
+ struct ntb_plx_softc *sc = device_get_softc(dev);
+
+ NTX_WRITE(sc, sc->link ? 0xc64 : 0xc54, bits);
+}
+
+static int
+ntb_plx_peer_db_addr(device_t dev, bus_addr_t *db_addr, vm_size_t *db_size)
+{
+ struct ntb_plx_softc *sc = device_get_softc(dev);
+ struct ntb_plx_mw_info *mw;
+
+ KASSERT((db_addr != NULL && db_size != NULL), ("must be non-NULL"));
+
+ if (sc->b2b_mw >= 0) {
+ mw = &sc->mw_info[sc->b2b_mw];
+ *db_addr = (uint64_t)mw->mw_pbase + PLX_NTX_BASE(sc) + 0xc4c;
+ } else {
+ *db_addr = rman_get_start(sc->conf_res) + PLX_NTX_BASE(sc);
+ *db_addr += sc->link ? 0xc4c : 0xc5c;
+ }
+ *db_size = 4;
+ return (0);
+}
+
+static void
+ntb_plx_peer_db_set(device_t dev, uint64_t bit)
+{
+ struct ntb_plx_softc *sc = device_get_softc(dev);
+
+ if (sc->b2b_mw >= 0)
+ BNTX_WRITE(sc, 0xc4c, bit);
+ else
+ NTX_WRITE(sc, sc->link ? 0xc4c : 0xc5c, bit);
+}
+
+static device_method_t ntb_plx_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, ntb_plx_probe),
+ DEVMETHOD(device_attach, ntb_plx_attach),
+ DEVMETHOD(device_detach, ntb_plx_detach),
+ /* NTB interface */
+ DEVMETHOD(ntb_link_is_up, ntb_plx_link_is_up),
+ DEVMETHOD(ntb_link_enable, ntb_plx_link_enable),
+ DEVMETHOD(ntb_link_disable, ntb_plx_link_disable),
+ DEVMETHOD(ntb_link_enabled, ntb_plx_link_enabled),
+ DEVMETHOD(ntb_mw_count, ntb_plx_mw_count),
+ DEVMETHOD(ntb_mw_get_range, ntb_plx_mw_get_range),
+ DEVMETHOD(ntb_mw_set_trans, ntb_plx_mw_set_trans),
+ DEVMETHOD(ntb_mw_clear_trans, ntb_plx_mw_clear_trans),
+ DEVMETHOD(ntb_mw_get_wc, ntb_plx_mw_get_wc),
+ DEVMETHOD(ntb_mw_set_wc, ntb_plx_mw_set_wc),
+ DEVMETHOD(ntb_spad_count, ntb_plx_spad_count),
+ DEVMETHOD(ntb_spad_clear, ntb_plx_spad_clear),
+ DEVMETHOD(ntb_spad_write, ntb_plx_spad_write),
+ DEVMETHOD(ntb_spad_read, ntb_plx_spad_read),
+ DEVMETHOD(ntb_peer_spad_write, ntb_plx_peer_spad_write),
+ DEVMETHOD(ntb_peer_spad_read, ntb_plx_peer_spad_read),
+ DEVMETHOD(ntb_db_valid_mask, ntb_plx_db_valid_mask),
+ DEVMETHOD(ntb_db_vector_count, ntb_plx_db_vector_count),
+ DEVMETHOD(ntb_db_vector_mask, ntb_plx_db_vector_mask),
+ DEVMETHOD(ntb_db_clear, ntb_plx_db_clear),
+ DEVMETHOD(ntb_db_clear_mask, ntb_plx_db_clear_mask),
+ DEVMETHOD(ntb_db_read, ntb_plx_db_read),
+ DEVMETHOD(ntb_db_set_mask, ntb_plx_db_set_mask),
+ DEVMETHOD(ntb_peer_db_addr, ntb_plx_peer_db_addr),
+ DEVMETHOD(ntb_peer_db_set, ntb_plx_peer_db_set),
+ DEVMETHOD_END
+};
+
+static DEFINE_CLASS_0(ntb_hw, ntb_plx_driver, ntb_plx_methods,
+ sizeof(struct ntb_plx_softc));
+DRIVER_MODULE(ntb_hw_plx, pci, ntb_plx_driver, ntb_hw_devclass, NULL, NULL);
+MODULE_DEPEND(ntb_hw_plx, ntb, 1, 1, 1);
+MODULE_VERSION(ntb_hw_plx, 1);
diff --git a/sys/i386/conf/NOTES b/sys/i386/conf/NOTES
index ce64f83b03f3..20a1c7db3789 100644
--- a/sys/i386/conf/NOTES
+++ b/sys/i386/conf/NOTES
@@ -658,6 +658,15 @@ device iwn6050fw
device wpifw
#
+# Non-Transparent Bridge (NTB) drivers
+#
+device if_ntb # Virtual NTB network interface
+device ntb_transport # NTB packet transport driver
+device ntb # NTB hardware interface
+device ntb_hw_intel # Intel NTB hardware driver
+device ntb_hw_plx # PLX NTB hardware driver
+
+#
# ATA raid adapters
#
device pst
diff --git a/sys/modules/ntb/Makefile b/sys/modules/ntb/Makefile
index 3eaf7516a779..f71ef09d9b35 100644
--- a/sys/modules/ntb/Makefile
+++ b/sys/modules/ntb/Makefile
@@ -1,5 +1,5 @@
# $FreeBSD$
-SUBDIR= ntb ntb_hw ntb_transport if_ntb
+SUBDIR= ntb ntb_hw_intel ntb_hw_plx ntb_transport if_ntb
.include <bsd.subdir.mk>
diff --git a/sys/modules/ntb/ntb_hw_intel/Makefile b/sys/modules/ntb/ntb_hw_intel/Makefile
new file mode 100644
index 000000000000..720cb16c5216
--- /dev/null
+++ b/sys/modules/ntb/ntb_hw_intel/Makefile
@@ -0,0 +1,9 @@
+# $FreeBSD$
+
+.PATH: ${SRCTOP}/sys/dev/ntb/ntb_hw
+
+KMOD = ntb_hw_intel
+SRCS = ntb_hw_intel.c
+SRCS += device_if.h bus_if.h pci_if.h ntb_if.h
+
+.include <bsd.kmod.mk>
diff --git a/sys/modules/ntb/ntb_hw/Makefile b/sys/modules/ntb/ntb_hw_plx/Makefile
index ad77e97cc935..4852e7a30fe6 100644
--- a/sys/modules/ntb/ntb_hw/Makefile
+++ b/sys/modules/ntb/ntb_hw_plx/Makefile
@@ -2,8 +2,8 @@
.PATH: ${SRCTOP}/sys/dev/ntb/ntb_hw
-KMOD = ntb_hw
-SRCS = ntb_hw.c
+KMOD = ntb_hw_plx
+SRCS = ntb_hw_plx.c
SRCS += device_if.h bus_if.h pci_if.h ntb_if.h
.include <bsd.kmod.mk>