Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F109301915
D31307.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
4 KB
Referenced Files
None
Subscribers
None
D31307.diff
View Options
diff --git a/share/man/man4/pci.4 b/share/man/man4/pci.4
--- a/share/man/man4/pci.4
+++ b/share/man/man4/pci.4
@@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd July 27, 2021
+.Dd August 13, 2021
.Dt PCI 4
.Os
.Sh NAME
@@ -430,6 +430,40 @@
of mapping.
Currently attempt to mmap an inactive BAR results in error.
.El
+.It PCIOCBARIO
+This
+.Xr ioctl 2
+command allows users to read from and write to BARs.
+The I/O request parameters are passed in a
+.Va struct pci_bar_ioreq
+structure, which has the following fields:
+.Bl -tag
+.It Vt struct pcisel pbi_sel
+Describes the device to operate on.
+.It Vt int pbi_op
+The operation to perform.
+Currently supported values are
+.Dv PCIBARIO_READ
+and
+.Dv PCIBARIO_WRITE .
+.It Vt uint32_t pbi_bar
+The index of the BAR on which to operate.
+.It Vt uint32_t pbi_offset
+The offset into the BAR at which to operate.
+.It Vt uint32_t pbi_width
+The size, in bytes, of the I/O operation.
+1-byte, 2-byte, 4-byte and 8-byte perations are supported.
+.It Vt uint32_t pbi_value
+For reads, the value is returned in this field.
+For writes, the caller specifies the value to be written in this field.
+.Pp
+Note that this operation maps and unmaps the corresponding resource and
+so is relatively expensive for memory BARs.
+The
+.Va PCIOCBARMMAP
+.Xr ioctl 2
+can be used to create a persistent userspace mapping for such BARs instead.
+.El
.El
.Sh LOADER TUNABLES
Tunables can be set at the
diff --git a/sys/dev/pci/pci_user.c b/sys/dev/pci/pci_user.c
--- a/sys/dev/pci/pci_user.c
+++ b/sys/dev/pci/pci_user.c
@@ -923,6 +923,92 @@
return (error);
}
+static int
+pci_bar_io(device_t pcidev, struct pci_bar_ioreq *pbi)
+{
+ struct pci_map *pm;
+ struct resource *res;
+ uint32_t offset, width;
+ int bar, error, type;
+
+ if (pbi->pbi_op != PCIBARIO_READ &&
+ pbi->pbi_op != PCIBARIO_WRITE)
+ return (EINVAL);
+
+ bar = PCIR_BAR(pbi->pbi_bar);
+ pm = pci_find_bar(pcidev, bar);
+ if (pm == NULL)
+ return (EINVAL);
+
+ offset = pbi->pbi_offset;
+ width = pbi->pbi_width;
+
+ if (offset + width < offset ||
+ ((pci_addr_t)1 << pm->pm_size) < offset + width)
+ return (EINVAL);
+
+ type = PCI_BAR_MEM(pm->pm_value) ? SYS_RES_MEMORY : SYS_RES_IOPORT;
+
+ /*
+ * This will fail if a driver has allocated the resource. This could be
+ * worked around by detecting that case and using bus_map_resource() to
+ * populate the handle, but so far this is not needed.
+ */
+ res = bus_alloc_resource_any(pcidev, type, &bar, RF_ACTIVE);
+ if (res == NULL)
+ return (ENOENT);
+
+ error = 0;
+ switch (pbi->pbi_op) {
+ case PCIBARIO_READ:
+ switch (pbi->pbi_width) {
+ case 1:
+ pbi->pbi_value = bus_read_1(res, offset);
+ break;
+ case 2:
+ pbi->pbi_value = bus_read_2(res, offset);
+ break;
+ case 4:
+ pbi->pbi_value = bus_read_4(res, offset);
+ break;
+#ifndef __i386__
+ case 8:
+ pbi->pbi_value = bus_read_8(res, offset);
+ break;
+#endif
+ default:
+ error = EINVAL;
+ break;
+ }
+ break;
+ case PCIBARIO_WRITE:
+ switch (pbi->pbi_width) {
+ case 1:
+ bus_write_1(res, offset, pbi->pbi_value);
+ break;
+ case 2:
+ bus_write_2(res, offset, pbi->pbi_value);
+ break;
+ case 4:
+ bus_write_4(res, offset, pbi->pbi_value);
+ break;
+#ifndef __i386__
+ case 8:
+ bus_write_8(res, offset, pbi->pbi_value);
+ break;
+#endif
+ default:
+ error = EINVAL;
+ break;
+ }
+ break;
+ }
+
+ bus_release_resource(pcidev, type, bar, res);
+
+ return (error);
+}
+
static int
pci_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *td)
{
@@ -932,6 +1018,7 @@
struct pci_conf_io *cio = NULL;
struct pci_devinfo *dinfo;
struct pci_io *io;
+ struct pci_bar_ioreq *pbi;
struct pci_bar_io *bio;
struct pci_list_vpd_io *lvio;
struct pci_match_conf *pattern_buf;
@@ -1307,6 +1394,19 @@
error = pcidev == NULL ? ENODEV : pci_bar_mmap(pcidev, pbm);
break;
+ case PCIOCBARIO:
+ pbi = (struct pci_bar_ioreq *)data;
+
+ pcidev = pci_find_dbsf(pbi->pbi_sel.pc_domain,
+ pbi->pbi_sel.pc_bus, pbi->pbi_sel.pc_dev,
+ pbi->pbi_sel.pc_func);
+ if (pcidev == NULL) {
+ error = ENODEV;
+ break;
+ }
+ error = pci_bar_io(pcidev, pbi);
+ break;
+
default:
error = ENOTTY;
break;
diff --git a/sys/sys/pciio.h b/sys/sys/pciio.h
--- a/sys/sys/pciio.h
+++ b/sys/sys/pciio.h
@@ -151,6 +151,17 @@
int pbm_memattr;
};
+struct pci_bar_ioreq {
+ struct pcisel pbi_sel; /* device to operate on */
+#define PCIBARIO_READ 0x1
+#define PCIBARIO_WRITE 0x2
+ int pbi_op;
+ uint32_t pbi_bar;
+ uint32_t pbi_offset;
+ uint32_t pbi_width;
+ uint32_t pbi_value;
+};
+
#define PCIIO_BAR_MMAP_FIXED 0x01
#define PCIIO_BAR_MMAP_EXCL 0x02
#define PCIIO_BAR_MMAP_RW 0x04
@@ -163,5 +174,6 @@
#define PCIOCGETBAR _IOWR('p', 6, struct pci_bar_io)
#define PCIOCLISTVPD _IOWR('p', 7, struct pci_list_vpd_io)
#define PCIOCBARMMAP _IOWR('p', 8, struct pci_bar_mmap)
+#define PCIOCBARIO _IOWR('p', 9, struct pci_bar_ioreq)
#endif /* !_SYS_PCIIO_H_ */
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Tue, Feb 4, 7:05 AM (20 h, 54 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
16449593
Default Alt Text
D31307.diff (4 KB)
Attached To
Mode
D31307: pci: Add ioctls to perform I/O to I/O port BARs
Attached
Detach File
Event Timeline
Log In to Comment