svn commit: r265055 - in head: share/man/man4 sys/dev/proto sys/modules sys/modules/proto

Marcel Moolenaar marcel at FreeBSD.org
Mon Apr 28 17:58:42 UTC 2014


Author: marcel
Date: Mon Apr 28 17:58:40 2014
New Revision: 265055
URL: http://svnweb.freebsd.org/changeset/base/265055

Log:
  Add proto(4): A driver for prototyping and diagnostics.
  It exposes I/O resources to user space, so that programs can peek
  and poke at the hardware. It does not itself have knowledge about
  the hardware device it attaches to.
  
  Sponsored by:	Juniper Networks, Inc.

Added:
  head/share/man/man4/proto.4   (contents, props changed)
  head/sys/dev/proto/
  head/sys/dev/proto/proto.h   (contents, props changed)
  head/sys/dev/proto/proto_bus_pci.c   (contents, props changed)
  head/sys/dev/proto/proto_core.c   (contents, props changed)
  head/sys/dev/proto/proto_dev.h   (contents, props changed)
  head/sys/modules/proto/
  head/sys/modules/proto/Makefile   (contents, props changed)
Modified:
  head/share/man/man4/Makefile
  head/sys/modules/Makefile

Modified: head/share/man/man4/Makefile
==============================================================================
--- head/share/man/man4/Makefile	Mon Apr 28 15:03:52 2014	(r265054)
+++ head/share/man/man4/Makefile	Mon Apr 28 17:58:40 2014	(r265055)
@@ -378,6 +378,7 @@ MAN=	aac.4 \
 	ppc.4 \
 	ppi.4 \
 	procdesc.4 \
+	proto.4 \
 	psm.4 \
 	pst.4 \
 	pt.4 \

Added: head/share/man/man4/proto.4
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/share/man/man4/proto.4	Mon Apr 28 17:58:40 2014	(r265055)
@@ -0,0 +1,121 @@
+.\"
+.\" Copyright (c) 2014 Marcel Moolenaar
+.\" 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 ``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 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 April 21, 2014
+.Dt PROTO 4
+.Os
+.\"
+.Sh NAME
+.Nm proto
+.Nd Driver for prototyping and H/W diagnostics
+.\"
+.Sh SYNOPSIS
+.Cd "device proto"
+.\"
+.Sh DESCRIPTION
+The
+.Nm
+device driver attaches to PCI devices when no other device drivers are
+present and creates device special files for all resources associated
+with the device.
+The driver itself has no knowledge of the device it attaches to.
+Programs can open these device special files and peform register-level
+reads and writes.
+As such, the
+.Nm
+device driver is nothing but a conduit or gateway between user space
+programs and the hardware device.
+.Pp
+Examples for why this is useful include hardware diagnostics and prototyping.
+In both these use cases, it's far more convenient to develop and run the
+logic in user space.
+Especially hardware diagnostics requires a somewhat user-friendly interface
+and adequate reporting.
+Neither is done easily as kernel code.
+.\"
+.Sh FILES
+All device special files corresponding to a PCI device are located under
+.Pa /dev/proto/pci<d>:<b>:<s>:<f>
+with
+.Pa pci<d>:<b>:<s>:<f>
+representing the location of the PCI device in the PCI hierarchy.
+A location includes:
+.Bl -tag -width XXXXXX -compact
+.It <d>
+The PCI domain number
+.It <b>
+The PCI bus number
+.It <s>
+The PCI slot or device number
+.It <f>
+The PCI function number
+.El
+.Pp
+Every PCI device has a device special file called
+.Pa pcicfg .
+This device special file gives access to the PCI configuration space.
+For each valid base address register (BAR), a device special file is created
+that contains the BAR offset and the resource type.
+A resource type can be either
+.Pa io
+or
+.Pa mem
+representing I/O port or memory mapped I/O space (resp.)
+.\"
+.Sh EXAMPLES
+A single function PCI device in domain 0, on bus 1, in slot 2 and having a
+single memory mapped I/O region will have the following device special files:
+.Bl -tag -compact
+.It Pa /dev/proto/pci0:1:2:0/10.mem
+.It Pa /dev/proto/pci0:1:2:0/pcicfg
+.El
+.\" 
+.Sh SECURITY CONSIDERATIONS
+Because programs have direct access to the hardware, the
+.Nm
+driver is inherently insecure.
+It is not advisable to use this driver on a production machine.
+.\"
+.Sh MISSING FUNCTIONALITY
+The
+.Nm
+driver does not yet support interrupts.
+Since interrupts cannot be handled by the driver itself, they must be converted
+into signals and delivered to the program that has registered for interrupts.
+.Pp
+In order to test the transmission or reception of data, some means of doing
+direct memory access (DMA) by the device must be possible. This too much be
+under the control of the program. The details of how a program can setup and
+initiate DMA still need to be fleshed out.
+.Pp
+Support for non-PCI devices has not been implemented yet.
+.\"
+.Sh AUTHORS
+The
+.Nm
+device driver and this manual page were written by
+.An Marcel Moolenaar Aq marcel at xcllnt.net .

Added: head/sys/dev/proto/proto.h
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sys/dev/proto/proto.h	Mon Apr 28 17:58:40 2014	(r265055)
@@ -0,0 +1,63 @@
+/*-
+ * Copyright (c) 2014 Marcel Moolenaar
+ * 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 ``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 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$
+ */
+
+#ifndef _DEV_PROTO_H_
+#define _DEV_PROTO_H_
+
+#define	PROTO_RES_MAX	16
+
+#define	PROTO_RES_UNUSED	0
+#define	PROTO_RES_PCICFG	10
+
+struct proto_res {
+	int		r_type;
+	int		r_rid;
+	struct resource *r_res;
+	u_long		r_size;
+	union {
+		void		*cookie;
+		struct cdev	*cdev;
+	} r_u;
+	uintptr_t	r_opened;
+};
+
+struct proto_softc {
+	device_t	sc_dev;
+	struct proto_res sc_res[PROTO_RES_MAX];
+	int		sc_rescnt;
+};
+
+extern devclass_t proto_devclass;
+extern char proto_driver_name[];
+
+int proto_add_resource(struct proto_softc *, int, int, struct resource *);
+
+int proto_attach(device_t dev);
+int proto_detach(device_t dev);
+
+#endif /* _DEV_PROTO_H_ */

Added: head/sys/dev/proto/proto_bus_pci.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sys/dev/proto/proto_bus_pci.c	Mon Apr 28 17:58:40 2014	(r265055)
@@ -0,0 +1,112 @@
+/*-
+ * Copyright (c) 2014 Marcel Moolenaar
+ * 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 ``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 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.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/conf.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <machine/bus.h>
+#include <sys/rman.h>
+#include <machine/resource.h>
+#include <sys/sbuf.h>
+
+#include <dev/pci/pcireg.h>
+#include <dev/pci/pcivar.h>
+
+#include <dev/proto/proto.h>
+
+static int proto_pci_probe(device_t dev);
+static int proto_pci_attach(device_t dev);
+
+static device_method_t proto_pci_methods[] = {
+	/* Device interface */
+	DEVMETHOD(device_probe,		proto_pci_probe),
+	DEVMETHOD(device_attach,	proto_pci_attach),
+	DEVMETHOD(device_detach,	proto_detach),
+	DEVMETHOD_END
+};
+
+static driver_t proto_pci_driver = {
+	proto_driver_name,
+	proto_pci_methods,
+	sizeof(struct proto_softc),
+};
+
+static int
+proto_pci_probe(device_t dev)
+{
+	struct sbuf *sb;
+
+	/* For now we only attach to function 0 devices. */
+	if (pci_get_function(dev) != 0)
+		return (ENXIO);
+
+	sb = sbuf_new_auto();
+	sbuf_printf(sb, "pci%d:%d:%d:%d", pci_get_domain(dev),
+	    pci_get_bus(dev), pci_get_slot(dev), pci_get_function(dev));
+	sbuf_finish(sb);
+	device_set_desc_copy(dev, sbuf_data(sb));
+	sbuf_delete(sb);
+	return (BUS_PROBE_HOOVER);
+}
+
+static int
+proto_pci_attach(device_t dev)
+{
+	struct proto_softc *sc;
+	struct resource *res;
+	int bar, rid, type;
+
+	sc = device_get_softc(dev);
+
+	proto_add_resource(sc, PROTO_RES_PCICFG, 0, NULL);
+
+	for (bar = 0; bar < PCIR_MAX_BAR_0; bar++) {
+		rid = PCIR_BAR(bar);
+		type = SYS_RES_MEMORY;
+		res = bus_alloc_resource_any(dev, type, &rid, RF_ACTIVE);
+		if (res == NULL) {
+			type = SYS_RES_IOPORT;
+			res = bus_alloc_resource_any(dev, type, &rid,
+			    RF_ACTIVE);
+		}
+		if (res != NULL)
+			proto_add_resource(sc, type, rid, res);
+	}
+
+	rid = 0;
+	type = SYS_RES_IRQ;
+	res = bus_alloc_resource_any(dev, type, &rid, RF_ACTIVE | RF_SHAREABLE);
+	if (res != NULL)
+		proto_add_resource(sc, type, rid, res);
+	return (proto_attach(dev));
+}
+
+DRIVER_MODULE(proto, pci, proto_pci_driver, proto_devclass, NULL, NULL);

Added: head/sys/dev/proto/proto_core.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sys/dev/proto/proto_core.c	Mon Apr 28 17:58:40 2014	(r265055)
@@ -0,0 +1,384 @@
+/*-
+ * Copyright (c) 2014 Marcel Moolenaar
+ * 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 ``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 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.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/conf.h>
+#include <sys/cons.h>
+#include <sys/fcntl.h>
+#include <sys/interrupt.h>
+#include <sys/kdb.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/mman.h>
+#include <sys/proc.h>
+#include <sys/queue.h>
+#include <sys/reboot.h>
+#include <machine/bus.h>
+#include <sys/rman.h>
+#include <sys/uio.h>
+#include <machine/resource.h>
+#include <machine/stdarg.h>
+
+#include <dev/pci/pcivar.h>
+
+#include <dev/proto/proto.h>
+#include <dev/proto/proto_dev.h>
+
+CTASSERT(SYS_RES_IRQ != PROTO_RES_UNUSED &&
+    SYS_RES_MEMORY != PROTO_RES_UNUSED &&
+    SYS_RES_IOPORT != PROTO_RES_UNUSED);
+CTASSERT(SYS_RES_IRQ != PROTO_RES_PCICFG &&
+    SYS_RES_MEMORY != PROTO_RES_PCICFG &&
+    SYS_RES_IOPORT != PROTO_RES_PCICFG);
+
+devclass_t proto_devclass;
+char proto_driver_name[] = "proto";
+
+static d_open_t proto_open;
+static d_close_t proto_close;
+static d_read_t proto_read;
+static d_write_t proto_write;
+static d_ioctl_t proto_ioctl;
+static d_mmap_t proto_mmap;
+
+struct cdevsw proto_devsw = {
+	.d_version = D_VERSION,
+	.d_flags = 0,
+	.d_name = proto_driver_name,
+	.d_open = proto_open,
+	.d_close = proto_close,
+	.d_read = proto_read,
+	.d_write = proto_write,
+	.d_ioctl = proto_ioctl,
+	.d_mmap = proto_mmap,
+};
+
+static MALLOC_DEFINE(M_PROTO, "PROTO", "PROTO driver");
+
+int
+proto_add_resource(struct proto_softc *sc, int type, int rid,
+    struct resource *res)
+{
+	struct proto_res *r;
+
+	if (type == PROTO_RES_UNUSED)
+		return (EINVAL);
+	if (sc->sc_rescnt == PROTO_RES_MAX)
+		return (ENOSPC);
+
+	r = sc->sc_res + sc->sc_rescnt++;
+	r->r_type = type;
+	r->r_rid = rid;
+	r->r_res = res;
+	return (0);
+}
+
+#ifdef notyet
+static int
+proto_intr(void *arg)
+{
+	struct proto_softc *sc = arg;
+
+	/* XXX TODO */
+	return (FILTER_HANDLED);
+}
+#endif
+
+int
+proto_attach(device_t dev)
+{
+	struct proto_softc *sc;
+	struct proto_res *r;
+	u_int res;
+
+	sc = device_get_softc(dev);
+	sc->sc_dev = dev;
+
+	for (res = 0; res < sc->sc_rescnt; res++) {
+		r = sc->sc_res + res;
+		switch (r->r_type) {
+		case SYS_RES_IRQ:
+			/* XXX TODO */
+			break;
+		case SYS_RES_MEMORY:
+		case SYS_RES_IOPORT:
+			r->r_size = rman_get_size(r->r_res);
+			r->r_u.cdev = make_dev(&proto_devsw, res, 0, 0, 0666,
+			    "proto/%s/%02x.%s", device_get_desc(dev), r->r_rid,
+			    (r->r_type == SYS_RES_IOPORT) ? "io" : "mem");
+			r->r_u.cdev->si_drv1 = sc;
+			r->r_u.cdev->si_drv2 = r;
+			break;
+		case PROTO_RES_PCICFG:
+			r->r_size = 4096;
+			r->r_u.cdev = make_dev(&proto_devsw, res, 0, 0, 0666,
+			    "proto/%s/pcicfg", device_get_desc(dev));
+			r->r_u.cdev->si_drv1 = sc;
+			r->r_u.cdev->si_drv2 = r;
+			break;
+		}
+	}
+	return (0);
+}
+
+int
+proto_detach(device_t dev)
+{
+	struct proto_softc *sc;
+	struct proto_res *r;
+	u_int res;
+
+	sc = device_get_softc(dev);
+
+	/* Don't detach if we have open device filess. */
+	for (res = 0; res < sc->sc_rescnt; res++) {
+		r = sc->sc_res + res;
+		if (r->r_opened)
+			return (EBUSY);
+	}
+
+	for (res = 0; res < sc->sc_rescnt; res++) {
+		r = sc->sc_res + res;
+		switch (r->r_type) {
+		case SYS_RES_IRQ:
+			/* XXX TODO */
+			break;
+		case SYS_RES_MEMORY:
+		case SYS_RES_IOPORT:
+		case PROTO_RES_PCICFG:
+			destroy_dev(r->r_u.cdev);
+			break;
+		}
+		if (r->r_res != NULL) {
+			bus_release_resource(dev, r->r_type, r->r_rid,
+			    r->r_res);
+			r->r_res = NULL;
+		}
+		r->r_type = PROTO_RES_UNUSED;
+	}
+	sc->sc_rescnt = 0;
+	return (0);
+}
+
+/*
+ * Device functions
+ */
+
+static int
+proto_open(struct cdev *cdev, int oflags, int devtype, struct thread *td)
+{
+	struct proto_res *r;
+
+	r = cdev->si_drv2;
+	if (!atomic_cmpset_acq_ptr(&r->r_opened, 0UL, (uintptr_t)td->td_proc))
+		return (EBUSY);
+	return (0);
+}
+
+static int
+proto_close(struct cdev *cdev, int fflag, int devtype, struct thread *td)
+{
+	struct proto_res *r;
+
+	r = cdev->si_drv2;
+	if (!atomic_cmpset_acq_ptr(&r->r_opened, (uintptr_t)td->td_proc, 0UL))
+		return (ENXIO);
+	return (0);
+}
+
+static int
+proto_read(struct cdev *cdev, struct uio *uio, int ioflag)
+{
+	union {
+		uint8_t	x1[8];
+		uint16_t x2[4];
+		uint32_t x4[2];
+		uint64_t x8[1];
+	} buf;
+	struct proto_softc *sc;
+	struct proto_res *r;
+	device_t dev;
+	off_t ofs;
+	u_long width;
+	int error;
+
+	sc = cdev->si_drv1;
+	dev = sc->sc_dev;
+	r = cdev->si_drv2;
+
+	width = uio->uio_resid;
+	if (width < 1 || width > 8 || bitcount16(width) > 1)
+		return (EIO);
+	ofs = uio->uio_offset;
+	if (ofs + width > r->r_size)
+		return (EIO);
+
+	switch (width) {
+	case 1:
+		buf.x1[0] = (r->r_type == PROTO_RES_PCICFG) ?
+		    pci_read_config(dev, ofs, 1) : bus_read_1(r->r_res, ofs);
+		break;
+	case 2:
+		buf.x2[0] = (r->r_type == PROTO_RES_PCICFG) ?
+		    pci_read_config(dev, ofs, 2) : bus_read_2(r->r_res, ofs);
+		break;
+	case 4:
+		buf.x4[0] = (r->r_type == PROTO_RES_PCICFG) ?
+		    pci_read_config(dev, ofs, 4) : bus_read_4(r->r_res, ofs);
+		break;
+#ifndef __i386__
+	case 8:
+		if (r->r_type == PROTO_RES_PCICFG)
+			return (EINVAL);
+		buf.x8[0] = bus_read_8(r->r_res, ofs);
+		break;
+#endif
+	default:
+		return (EIO);
+	}
+
+	error = uiomove(&buf, width, uio);
+	return (error);
+}
+
+static int
+proto_write(struct cdev *cdev, struct uio *uio, int ioflag)
+{
+	union {
+		uint8_t	x1[8];
+		uint16_t x2[4];
+		uint32_t x4[2];
+		uint64_t x8[1];
+	} buf;
+	struct proto_softc *sc;
+	struct proto_res *r;
+	device_t dev;
+	off_t ofs;
+	u_long width;
+	int error;
+
+	sc = cdev->si_drv1;
+	dev = sc->sc_dev;
+	r = cdev->si_drv2;
+
+	width = uio->uio_resid;
+	if (width < 1 || width > 8 || bitcount16(width) > 1)
+		return (EIO);
+	ofs = uio->uio_offset;
+	if (ofs + width > r->r_size)
+		return (EIO);
+
+	error = uiomove(&buf, width, uio);
+	if (error)
+		return (error);
+
+	switch (width) {
+	case 1:
+		if (r->r_type == PROTO_RES_PCICFG)
+			pci_write_config(dev, ofs, buf.x1[0], 1);
+		else
+			bus_write_1(r->r_res, ofs, buf.x1[0]);
+		break;
+	case 2:
+		if (r->r_type == PROTO_RES_PCICFG)
+			pci_write_config(dev, ofs, buf.x2[0], 2);
+		else
+			bus_write_2(r->r_res, ofs, buf.x2[0]);
+		break;
+	case 4:
+		if (r->r_type == PROTO_RES_PCICFG)
+			pci_write_config(dev, ofs, buf.x4[0], 4);
+		else
+			bus_write_4(r->r_res, ofs, buf.x4[0]);
+		break;
+#ifndef __i386__
+	case 8:
+		if (r->r_type == PROTO_RES_PCICFG)
+			return (EINVAL);
+		bus_write_8(r->r_res, ofs, buf.x8[0]);
+		break;
+#endif
+	default:
+		return (EIO);
+	}
+
+	return (0);
+}
+
+static int
+proto_ioctl(struct cdev *cdev, u_long cmd, caddr_t data, int fflag,
+    struct thread *td)
+{
+	struct proto_ioc_region *region;
+	struct proto_res *r;
+	int error;
+
+	r = cdev->si_drv2;
+
+	error = 0;
+	switch (cmd) {
+	case PROTO_IOC_REGION:
+		region = (struct proto_ioc_region *)data;
+		region->size = r->r_size;
+		if (r->r_type == PROTO_RES_PCICFG)
+			region->address = 0;
+		else
+			region->address = rman_get_start(r->r_res);
+		break;
+	default:
+		error = ENOIOCTL;
+		break;
+	}
+	return (error);
+}
+
+static int
+proto_mmap(struct cdev *cdev, vm_ooffset_t offset, vm_paddr_t *paddr,
+    int prot, vm_memattr_t *memattr)
+{
+	struct proto_res *r;
+
+	r = cdev->si_drv2;
+
+	if (r->r_type != SYS_RES_MEMORY)
+		return (ENXIO);
+	if (offset & PAGE_MASK)
+		return (EINVAL);
+	if (prot & PROT_EXEC)
+		return (EACCES);
+	if (offset >= r->r_size)
+		return (EINVAL);
+	*paddr = rman_get_start(r->r_res) + offset;
+#ifndef __sparc64__
+	*memattr = VM_MEMATTR_UNCACHEABLE;
+#endif
+	return (0);
+}

Added: head/sys/dev/proto/proto_dev.h
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sys/dev/proto/proto_dev.h	Mon Apr 28 17:58:40 2014	(r265055)
@@ -0,0 +1,43 @@
+/*-
+ * Copyright (c) 2014 Marcel Moolenaar
+ * 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 ``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 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$
+ */
+
+#ifndef _DEV_PROTO_DEV_H_
+#define _DEV_PROTO_DEV_H_
+
+#include <sys/ioccom.h>
+
+#define	PROTO_IOC_CLASS	'h'
+
+struct proto_ioc_region {
+	unsigned long	address;
+	unsigned long	size;
+};
+
+#define PROTO_IOC_REGION _IOWR(PROTO_IOC_CLASS, 1, struct proto_ioc_region)
+
+#endif /* _DEV_PROTO_H_ */

Modified: head/sys/modules/Makefile
==============================================================================
--- head/sys/modules/Makefile	Mon Apr 28 15:03:52 2014	(r265054)
+++ head/sys/modules/Makefile	Mon Apr 28 17:58:40 2014	(r265055)
@@ -272,6 +272,7 @@ SUBDIR=	\
 	ppi \
 	pps \
 	procfs \
+	proto \
 	pseudofs \
 	${_pst} \
 	pty  \

Added: head/sys/modules/proto/Makefile
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sys/modules/proto/Makefile	Mon Apr 28 17:58:40 2014	(r265055)
@@ -0,0 +1,20 @@
+# $FreeBSD$
+
+.PATH: ${.CURDIR}/../../dev/proto
+
+KMOD=	proto
+SRCS=	\
+	proto_bus_pci.c \
+	proto_core.c
+
+SRCS+=	\
+	bus_if.h \
+	device_if.h \
+	pci_if.h \
+
+MFILES=	\
+	dev/pci/pci_if.m \
+	kern/bus_if.m \
+	kern/device_if.m
+
+.include <bsd.kmod.mk>


More information about the svn-src-all mailing list