svn commit: r273278 - in head/sys: arm/altera/socfpga arm/conf boot/fdt/dts/arm dev/beri

Ruslan Bukin br at FreeBSD.org
Sun Oct 19 16:26:51 UTC 2014


Author: br
Date: Sun Oct 19 16:26:49 2014
New Revision: 273278
URL: https://svnweb.freebsd.org/changeset/base/273278

Log:
  Add driver for BERI soft processor 'ring buffer' device.
  Ring device provides a way for communicate to BERI
  peripherals such as BERI debug unit and console.
  
  Sponsored by:	DARPA, AFRL

Added:
  head/sys/arm/conf/SOCKIT-BERI   (contents, props changed)
  head/sys/boot/fdt/dts/arm/socfpga-sockit-beri.dts   (contents, props changed)
  head/sys/dev/beri/
  head/sys/dev/beri/beri_ring.c   (contents, props changed)
Modified:
  head/sys/arm/altera/socfpga/files.socfpga

Modified: head/sys/arm/altera/socfpga/files.socfpga
==============================================================================
--- head/sys/arm/altera/socfpga/files.socfpga	Sun Oct 19 12:11:25 2014	(r273277)
+++ head/sys/arm/altera/socfpga/files.socfpga	Sun Oct 19 16:26:49 2014	(r273278)
@@ -21,3 +21,4 @@ arm/altera/socfpga/socfpga_mp.c			option
 
 dev/dwc/if_dwc.c				optional dwc
 dev/mmc/host/dwmmc.c				optional dwmmc
+dev/beri/beri_ring.c				optional beri_ring

Added: head/sys/arm/conf/SOCKIT-BERI
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sys/arm/conf/SOCKIT-BERI	Sun Oct 19 16:26:49 2014	(r273278)
@@ -0,0 +1,140 @@
+# Kernel configuration for Terasic SoCKit (Altera Cyclone V SoC).
+#
+# For more information on this file, please read the config(5) manual page,
+# and/or the handbook section on Kernel Configuration Files:
+#
+#    http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html
+#
+# The handbook is also available locally in /usr/share/doc/handbook
+# if you've installed the doc distribution, otherwise always see the
+# FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the
+# latest information.
+#
+# An exhaustive list of options and more detailed explanations of the
+# device lines is also present in the ../../conf/NOTES and NOTES files.
+# If you are in doubt as to the purpose or necessity of a line, check first
+# in NOTES.
+#
+# $FreeBSD$
+
+ident		SOCKIT-BERI
+include 	"../altera/socfpga/std.socfpga"
+
+makeoptions	MODULES_OVERRIDE=""
+
+makeoptions	DEBUG=-g		# Build kernel with gdb(1) debug symbols
+makeoptions	WERROR="-Werror"
+
+options 	HZ=100
+options 	SCHED_4BSD		# 4BSD scheduler
+options 	INET			# InterNETworking
+options 	INET6			# IPv6 communications protocols
+options 	GEOM_PART_BSD		# BSD partition scheme
+options 	GEOM_PART_MBR		# MBR partition scheme
+options 	GEOM_PART_GPT		# GUID partition tables
+options 	TMPFS			# Efficient memory filesystem
+options 	FFS			# Berkeley Fast Filesystem
+options 	SOFTUPDATES
+options 	UFS_ACL			# Support for access control lists
+options 	UFS_DIRHASH		# Improve performance on big directories
+options 	MSDOSFS			# MSDOS Filesystem
+options 	CD9660			# ISO 9660 Filesystem
+options 	PROCFS			# Process filesystem (requires PSEUDOFS)
+options 	PSEUDOFS		# Pseudo-filesystem framework
+options 	COMPAT_43		# Compatible with BSD 4.3 [KEEP THIS!]
+options 	SCSI_DELAY=5000		# Delay (in ms) before probing SCSI
+options 	KTRACE
+options 	SYSVSHM			# SYSV-style shared memory
+options 	SYSVMSG			# SYSV-style message queues
+options 	SYSVSEM			# SYSV-style semaphores
+options 	_KPOSIX_PRIORITY_SCHEDULING # Posix P1003_1B real-time extensions
+options 	KBD_INSTALL_CDEV
+options 	PREEMPTION
+options 	FREEBSD_BOOT_LOADER
+options 	VFP			# vfp/neon
+
+options 	SMP
+
+# Debugging
+makeoptions	DEBUG=-g		# Build kernel with gdb(1) debug symbols
+options 	BREAK_TO_DEBUGGER
+#options 	VERBOSE_SYSINIT		# Enable verbose sysinit messages
+options 	KDB
+options 	DDB			# Enable the kernel debugger
+options 	INVARIANTS		# Enable calls of extra sanity checking
+options 	INVARIANT_SUPPORT	# Extra sanity checks of internal structures, required by INVARIANTS
+#options 	WITNESS			# Enable checks to detect deadlocks and cycles
+#options 	WITNESS_SKIPSPIN	# Don't run witness on spinlocks for speed
+#options 	DIAGNOSTIC
+
+# NFS support
+options 	NFSCL			# Network Filesystem Client
+options 	NFSLOCKD		# Network Lock Manager
+options 	NFS_ROOT		# NFS usable as /, requires NFSCLIENT
+
+# Uncomment this for NFS root
+#options 	NFS_ROOT		# NFS usable as /, requires NFSCL
+#options 	BOOTP_NFSROOT
+#options 	BOOTP_COMPAT
+#options 	BOOTP
+#options 	BOOTP_NFSV3
+#options 	BOOTP_WIRED_TO=ue0
+
+device		mmc			# mmc/sd bus
+device		mmcsd			# mmc/sd flash cards
+device		dwmmc
+
+options 	ROOTDEVNAME=\"ufs:/dev/mmcsd0s4\"
+
+# Pseudo devices
+
+device		loop
+device		random
+device		pty
+device		md
+device		gpio
+
+# USB support
+options 	USB_HOST_ALIGN=64	# Align usb buffers to cache line size.
+device		usb
+options 	USB_DEBUG
+#options 	USB_REQ_DEBUG
+#options 	USB_VERBOSE
+#device		musb
+device		dwcotg
+
+device		umass
+device		scbus			# SCSI bus (required for ATA/SCSI)
+device		da			# Direct Access (disks)
+device		pass
+
+# Serial ports
+device		uart
+device		uart_ns8250
+
+# I2C (TWSI)
+device		iic
+device		iicbus
+
+# SPI
+device		spibus
+
+# BERI specific
+device		beri_ring
+
+# Ethernet
+device		ether
+device		mii
+device		smsc
+device		smscphy
+device		dwc
+
+# USB ethernet support, requires miibus
+device		miibus
+device		axe			# ASIX Electronics USB Ethernet
+device		bpf			# Berkeley packet filter
+
+#FDT
+options 	FDT
+options 	FDT_DTB_STATIC
+makeoptions	FDT_DTS_FILE=socfpga-sockit-beri.dts

Added: head/sys/boot/fdt/dts/arm/socfpga-sockit-beri.dts
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sys/boot/fdt/dts/arm/socfpga-sockit-beri.dts	Sun Oct 19 16:26:49 2014	(r273278)
@@ -0,0 +1,109 @@
+/*-
+ * Copyright (c) 2014 Ruslan Bukin <br at bsdpad.com>
+ * All rights reserved.
+ *
+ * This software was developed by SRI International and the University of
+ * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
+ * ("CTSRD"), as part of the DARPA CRASH research programme.
+ *
+ * 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$
+ */
+
+/dts-v1/;
+
+/include/ "socfpga.dtsi"
+
+/ {
+	model = "Terasic SoCKit";
+	compatible = "altr,socfpga-cyclone5", "altr,socfpga";
+
+	/* Reserve first page for secondary CPU trampoline code */
+	memreserve = < 0x00000000 0x1000 >;
+
+	memory {
+		device_type = "memory";
+		reg = < 0x00000000 0x40000000 >;	/* 1G RAM */
+	};
+
+	SOC: socfpga {
+		serial0: serial at ffc02000 {
+			status = "okay";
+		};
+
+		usb1: usb at ffb40000 {
+			status = "okay";
+		};
+
+		gmac1: ethernet at ff702000 {
+			status = "okay";
+		};
+
+		mmc: dwmmc at ff704000 {
+			status = "okay";
+			num-slots = <1>;
+			supports-highspeed;
+			broken-cd;
+			bus-frequency = <25000000>;
+
+			slot at 0 {
+				reg = <0>;
+				bus-width = <4>;
+			};	
+		};
+
+		beri_debug: ring at c0000000 {
+			compatible = "sri-cambridge,beri-ring";
+			reg = <0xc0000000 0x3000>;
+			interrupts = < 72 73 >;
+			interrupt-parent = <&GIC>;
+			device_name = "beri_debug";
+			data_size = <0x1000>;
+			data_read = <0x0>;
+			data_write = <0x1000>;
+			control_read = <0x2000>;
+			control_write = <0x2010>;
+			status = "okay";
+		};
+
+		beri_console: ring at c0004000 {
+			compatible = "sri-cambridge,beri-ring";
+			reg = <0xc0004000 0x3000>;
+			interrupts = < 74 75 >;
+			interrupt-parent = <&GIC>;
+			device_name = "beri_console";
+			data_size = <0x1000>;
+			data_read = <0x0>;
+			data_write = <0x1000>;
+			control_read = <0x2000>;
+			control_write = <0x2010>;
+			status = "okay";
+		};
+	};
+
+	chosen {
+		bootargs = "-v";
+		stdin = "serial0";
+		stdout = "serial0";
+	};
+};

Added: head/sys/dev/beri/beri_ring.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sys/dev/beri/beri_ring.c	Sun Oct 19 16:26:49 2014	(r273278)
@@ -0,0 +1,529 @@
+/*-
+ * Copyright (c) 2014 Ruslan Bukin <br at bsdpad.com>
+ * All rights reserved.
+ *
+ * This software was developed by SRI International and the University of
+ * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
+ * ("CTSRD"), as part of the DARPA CRASH research programme.
+ *
+ * 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.
+ */
+
+/*
+ * SRI-Cambridge BERI soft processor <-> ARM core ring buffer.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/malloc.h>
+#include <sys/rman.h>
+#include <sys/timeet.h>
+#include <sys/timetc.h>
+#include <sys/conf.h>
+#include <sys/uio.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/event.h>
+#include <sys/selinfo.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <machine/bus.h>
+#include <machine/fdt.h>
+#include <machine/cpu.h>
+#include <machine/intr.h>
+
+#define READ4(_sc, _reg) \
+	bus_read_4((_sc)->res[0], _reg)
+#define WRITE4(_sc, _reg, _val) \
+	bus_write_4((_sc)->res[0], _reg, _val)
+
+#define CDES_INT_EN		(1 << 15)
+#define CDES_CAUSE_MASK		0x3
+#define CDES_CAUSE_SHIFT	13
+#define DEVNAME_MAXLEN		256
+
+typedef struct
+{
+	uint16_t cdes;
+	uint16_t interrupt_level;
+	uint16_t in;
+	uint16_t out;
+} control_reg_t;
+
+struct beri_softc {
+	struct resource		*res[3];
+	bus_space_tag_t		bst;
+	bus_space_handle_t	bsh;
+	struct cdev		*cdev;
+	device_t		dev;
+	void			*read_ih;
+	void			*write_ih;
+	struct selinfo		beri_rsel;
+	struct mtx		beri_mtx;
+	int			opened;
+
+	char			devname[DEVNAME_MAXLEN];
+	int			control_read;
+	int			control_write;
+	int			data_read;
+	int			data_write;
+	int			data_size;
+};
+
+static struct resource_spec beri_spec[] = {
+	{ SYS_RES_MEMORY,	0,	RF_ACTIVE },
+	{ SYS_RES_IRQ,		0,	RF_ACTIVE },
+	{ SYS_RES_IRQ,		1,	RF_ACTIVE },
+	{ -1, 0 }
+};
+
+static control_reg_t
+get_control_reg(struct beri_softc *sc, int dir)
+{
+	uint32_t offset;
+	uint16_t dst[4];
+	control_reg_t c;
+	uint16_t *cp;
+	int i;
+
+	cp = (uint16_t *)&c;
+
+	offset = dir ? sc->control_write : sc->control_read;
+	((uint32_t *)dst)[0] = READ4(sc, offset);
+	((uint32_t *)dst)[1] = READ4(sc, offset + 4);
+
+	for (i = 0; i < 4; i++)
+		cp[i] = dst[3 - i];
+
+	return (c);
+}
+
+static void
+set_control_reg(struct beri_softc *sc, int dir, control_reg_t *c)
+{
+	uint32_t offset;
+	uint16_t src[4];
+	uint16_t *cp;
+	int i;
+
+	cp = (uint16_t *)c;
+
+	for (i = 0; i < 4; i++)
+		src[3 - i] = cp[i];
+
+	offset = dir ? sc->control_write : sc->control_read;
+	WRITE4(sc, offset + 0, ((uint32_t *)src)[0]);
+	WRITE4(sc, offset + 4, ((uint32_t *)src)[1]);
+}
+
+static int
+get_stock(struct beri_softc *sc, int dir, control_reg_t *c)
+{
+	uint32_t fill;
+
+	fill = (c->in - c->out + sc->data_size) % sc->data_size;
+
+	if (dir)
+		return (sc->data_size - fill - 1);
+	else
+		return (fill);
+}
+
+static void
+beri_intr_write(void *arg)
+{
+	struct beri_softc *sc;
+	control_reg_t c;
+
+	sc = arg;
+
+	c = get_control_reg(sc, 1);
+	if (c.cdes & CDES_INT_EN) {
+		c.cdes &= ~(CDES_INT_EN);
+		set_control_reg(sc, 1, &c);
+	}
+
+	mtx_lock(&sc->beri_mtx);
+	selwakeuppri(&sc->beri_rsel, PZERO + 1);
+	KNOTE_LOCKED(&sc->beri_rsel.si_note, 0);
+	mtx_unlock(&sc->beri_mtx);
+}
+
+static void
+beri_intr_read(void *arg)
+{
+	struct beri_softc *sc;
+	control_reg_t c;
+
+	sc = arg;
+
+	c = get_control_reg(sc, 0);
+	if (c.cdes & CDES_INT_EN) {
+		c.cdes &= ~(CDES_INT_EN);
+		set_control_reg(sc, 0, &c);
+	}
+
+	mtx_lock(&sc->beri_mtx);
+	selwakeuppri(&sc->beri_rsel, PZERO + 1);
+	KNOTE_LOCKED(&sc->beri_rsel.si_note, 0);
+	mtx_unlock(&sc->beri_mtx);
+}
+
+static int
+beri_open(struct cdev *dev, int flags __unused,
+    int fmt __unused, struct thread *td __unused)
+{
+	struct beri_softc *sc;
+	control_reg_t c;
+
+	sc = dev->si_drv1;
+
+	if (sc->opened)
+		return (1);
+
+	/* Setup interrupt handlers */
+	if (bus_setup_intr(sc->dev, sc->res[1], INTR_TYPE_BIO | INTR_MPSAFE,
+		NULL, beri_intr_read, sc, &sc->read_ih)) {
+		device_printf(sc->dev, "Unable to setup read intr\n");
+		return (1);
+	}
+	if (bus_setup_intr(sc->dev, sc->res[2], INTR_TYPE_BIO | INTR_MPSAFE,
+		NULL, beri_intr_write, sc, &sc->write_ih)) {
+		device_printf(sc->dev, "Unable to setup write intr\n");
+		return (1);
+	}
+
+	sc->opened = 1;
+
+	/* Clear write buffer */
+	c = get_control_reg(sc, 1);
+	c.in = c.out;
+	c.cdes = 0;
+	set_control_reg(sc, 1, &c);
+
+	/* Clear read buffer */
+	c = get_control_reg(sc, 0);
+	c.out = c.in;
+	c.cdes = 0;
+	set_control_reg(sc, 0, &c);
+
+	return (0);
+}
+
+static int
+beri_close(struct cdev *dev, int flags __unused,
+    int fmt __unused, struct thread *td __unused)
+{
+	struct beri_softc *sc;
+
+	sc = dev->si_drv1;
+
+	if (sc->opened) {
+		sc->opened = 0;
+
+		/* Unsetup interrupt handlers */
+		bus_teardown_intr(sc->dev, sc->res[1], sc->read_ih);
+		bus_teardown_intr(sc->dev, sc->res[2], sc->write_ih);
+	}
+
+	return (0);
+}
+
+static int
+beri_rdwr(struct cdev *dev, struct uio *uio, int ioflag)
+{
+	struct beri_softc *sc;
+	uint32_t offset;
+	control_reg_t c;
+	uint16_t *ptr;
+	uint8_t *dst;
+	int stock;
+	int dir;
+	int amount;
+	int count;
+
+	sc = dev->si_drv1;
+
+	dir = uio->uio_rw ? 1 : 0;
+
+	c = get_control_reg(sc, dir);
+	stock = get_stock(sc, dir, &c);
+	if (stock < uio->uio_resid) {
+		device_printf(sc->dev, "Err: no data/space available\n");
+		return (1);
+	}
+
+	amount = uio->uio_resid;
+	ptr = dir ? &c.in : &c.out;
+	count = (sc->data_size - *ptr);
+
+	offset = dir ? sc->data_write : sc->data_read;
+	dst = (uint8_t *)(sc->bsh + offset);
+
+	if (amount <= count) {
+		uiomove(dst + *ptr, amount, uio);
+	} else {
+		uiomove(dst + *ptr, count, uio);
+		uiomove(dst, (amount - count), uio);
+	}
+
+	*ptr = (*ptr + amount) % sc->data_size;
+	set_control_reg(sc, dir, &c);
+
+	return (0);
+}
+
+static int
+beri_kqread(struct knote *kn, long hint)
+{
+	struct beri_softc *sc;
+	control_reg_t c;
+	int stock;
+
+	sc = kn->kn_hook;
+
+	c = get_control_reg(sc, 0);
+	stock = get_stock(sc, 0, &c);
+	if (stock) {
+		kn->kn_data = stock;
+		return (1);
+	}
+
+	kn->kn_data = 0;
+
+	/* Wait at least one new byte in buffer */
+	c.interrupt_level = 1;
+
+	/* Enable interrupts */
+	c.cdes |= (CDES_INT_EN);
+	set_control_reg(sc, 0, &c);
+
+	return (0);
+}
+
+static int
+beri_kqwrite(struct knote *kn, long hint)
+{
+	struct beri_softc *sc;
+	control_reg_t c;
+	int stock;
+
+	sc = kn->kn_hook;
+
+	c = get_control_reg(sc, 1);
+	stock = get_stock(sc, 1, &c);
+	if (stock) {
+		kn->kn_data = stock;
+		return (1);
+	}
+
+	kn->kn_data = 0;
+
+	/* Wait at least one free position in buffer */
+	c.interrupt_level = sc->data_size - 2;
+
+	/* Enable interrupts */
+	c.cdes |= (CDES_INT_EN);
+	set_control_reg(sc, 1, &c);
+
+	return (0);
+}
+
+static void
+beri_kqdetach(struct knote *kn)
+{
+	struct beri_softc *sc;
+
+	sc = kn->kn_hook;
+
+	knlist_remove(&sc->beri_rsel.si_note, kn, 0);
+}
+
+static struct filterops beri_read_filterops = {
+	.f_isfd =       1,
+	.f_attach =     NULL,
+	.f_detach =     beri_kqdetach,
+	.f_event =      beri_kqread,
+};
+
+static struct filterops beri_write_filterops = {
+	.f_isfd =       1,
+	.f_attach =     NULL,
+	.f_detach =     beri_kqdetach,
+	.f_event =      beri_kqwrite,
+};
+
+static int
+beri_kqfilter(struct cdev *dev, struct knote *kn)
+{
+	struct beri_softc *sc;
+
+	sc = dev->si_drv1;
+
+	switch(kn->kn_filter) {
+	case EVFILT_READ:
+		kn->kn_fop = &beri_read_filterops;
+		break;
+	case EVFILT_WRITE:
+		kn->kn_fop = &beri_write_filterops;
+		break;
+	default:
+		return(EINVAL);
+	}
+
+	kn->kn_hook = sc;
+	knlist_add(&sc->beri_rsel.si_note, kn, 0);
+
+	return (0);
+}
+
+static struct cdevsw beri_cdevsw = {
+	.d_version =	D_VERSION,
+	.d_open =	beri_open,
+	.d_close =	beri_close,
+	.d_write =	beri_rdwr,
+	.d_read =	beri_rdwr,
+	.d_kqfilter =	beri_kqfilter,
+	.d_name =	"beri ring buffer",
+};
+
+static int
+parse_fdt(struct beri_softc *sc)
+{
+	pcell_t dts_value[0];
+	phandle_t node;
+	int len;
+
+	if ((node = ofw_bus_get_node(sc->dev)) == -1)
+		return (ENXIO);
+
+	/* get device name */
+	if (OF_getprop(ofw_bus_get_node(sc->dev), "device_name",
+		&sc->devname, sizeof(sc->devname)) <= 0) {
+		device_printf(sc->dev, "Can't get device_name\n");
+		return (ENXIO);
+	}
+
+	if ((len = OF_getproplen(node, "data_size")) <= 0)
+		return (ENXIO);
+	OF_getencprop(node, "data_size", dts_value, len);
+	sc->data_size = dts_value[0];
+
+	if ((len = OF_getproplen(node, "data_read")) <= 0)
+		return (ENXIO);
+	OF_getencprop(node, "data_read", dts_value, len);
+	sc->data_read = dts_value[0];
+
+	if ((len = OF_getproplen(node, "data_write")) <= 0)
+		return (ENXIO);
+	OF_getencprop(node, "data_write", dts_value, len);
+	sc->data_write = dts_value[0];
+
+	if ((len = OF_getproplen(node, "control_read")) <= 0)
+		return (ENXIO);
+	OF_getencprop(node, "control_read", dts_value, len);
+	sc->control_read = dts_value[0];
+
+	if ((len = OF_getproplen(node, "control_write")) <= 0)
+		return (ENXIO);
+	OF_getencprop(node, "control_write", dts_value, len);
+	sc->control_write = dts_value[0];
+
+	return (0);
+}
+
+static int
+beri_probe(device_t dev)
+{
+
+	if (!ofw_bus_status_okay(dev))
+		return (ENXIO);
+
+	if (!ofw_bus_is_compatible(dev, "sri-cambridge,beri-ring"))
+		return (ENXIO);
+
+	device_set_desc(dev, "SRI-Cambridge BERI ring buffer");
+	return (BUS_PROBE_DEFAULT);
+}
+
+static int
+beri_attach(device_t dev)
+{
+	struct beri_softc *sc;
+
+	sc = device_get_softc(dev);
+	sc->dev = dev;
+
+	if (bus_alloc_resources(dev, beri_spec, sc->res)) {
+		device_printf(dev, "could not allocate resources\n");
+		return (ENXIO);
+	}
+
+	/* Memory interface */
+	sc->bst = rman_get_bustag(sc->res[0]);
+	sc->bsh = rman_get_bushandle(sc->res[0]);
+
+	if (parse_fdt(sc)) {
+		device_printf(sc->dev, "Can't get FDT values\n");
+		return (ENXIO);
+	}
+
+	sc->cdev = make_dev(&beri_cdevsw, 0, UID_ROOT, GID_WHEEL,
+	    S_IRWXU, "%s", sc->devname);
+	if (sc->cdev == NULL) {
+		device_printf(dev, "Failed to create character device.\n");
+		return (ENXIO);
+	}
+
+	sc->cdev->si_drv1 = sc;
+
+	mtx_init(&sc->beri_mtx, "beri_mtx", NULL, MTX_DEF);
+	knlist_init_mtx(&sc->beri_rsel.si_note, &sc->beri_mtx);
+
+	return (0);
+}
+
+static device_method_t beri_methods[] = {
+	DEVMETHOD(device_probe,		beri_probe),
+	DEVMETHOD(device_attach,	beri_attach),
+	{ 0, 0 }
+};
+
+static driver_t beri_driver = {
+	"beri_ring",
+	beri_methods,
+	sizeof(struct beri_softc),
+};
+
+static devclass_t beri_devclass;
+
+DRIVER_MODULE(beri_ring, simplebus, beri_driver, beri_devclass, 0, 0);


More information about the svn-src-all mailing list