summaryrefslogtreecommitdiffstats
path: root/sys/dev/netfpga10g
diff options
context:
space:
mode:
authorbz <bz@FreeBSD.org>2014-08-16 14:30:46 +0000
committerbz <bz@FreeBSD.org>2014-08-16 14:30:46 +0000
commitfe69d82910f112704db79bb351d48aa316c11807 (patch)
tree2e9e4d8baaaca117b28843cb22304f8d0646dea9 /sys/dev/netfpga10g
parent919a83705802c08fe80c350615ad98cee21c3fc6 (diff)
downloadFreeBSD-src-fe69d82910f112704db79bb351d48aa316c11807.zip
FreeBSD-src-fe69d82910f112704db79bb351d48aa316c11807.tar.gz
MFC r264601,264646,265766,267918,267919,267920:
Merge if_nf10bmac(4), a driver to support an NetFPGA-10G Embedded CPU Ethernet Core. The current version operates on a simple PIO based interface connected to a NetFPGA-10G port. To avoid confusion: this driver operates on a CPU running on the FPGA, e.g. BERI/mips, and is not suited for the PCI host interface. Adjust the register layout to allow for 64bit registers in the future for nf10bmac(4). Also, add support for and enable RX interrupts. Allow switching between 32bit and 64bit bus width data access at compile time by setting NF10BMAC_64BIT and using a REGWTYPE #define to set correct variable and return value widths. Adjust comments to indicate the 32 or 64bit register widths. Relnotes: yes Sponsored by: DARPA/AFRL
Diffstat (limited to 'sys/dev/netfpga10g')
-rw-r--r--sys/dev/netfpga10g/nf10bmac/if_nf10bmac.c969
-rw-r--r--sys/dev/netfpga10g/nf10bmac/if_nf10bmac_fdt.c203
-rw-r--r--sys/dev/netfpga10g/nf10bmac/if_nf10bmacreg.h72
3 files changed, 1244 insertions, 0 deletions
diff --git a/sys/dev/netfpga10g/nf10bmac/if_nf10bmac.c b/sys/dev/netfpga10g/nf10bmac/if_nf10bmac.c
new file mode 100644
index 0000000..a5aebba
--- /dev/null
+++ b/sys/dev/netfpga10g/nf10bmac/if_nf10bmac.c
@@ -0,0 +1,969 @@
+/*-
+ * Copyright (c) 2012-2014 Bjoern A. Zeeb
+ * All rights reserved.
+ *
+ * This software was developed by SRI International and the University of
+ * Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249
+ * ("MRC2"), as part of the DARPA MRC 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.
+ *
+ * This driver is modelled after atse(4). We need to seriously reduce the
+ * per-driver code we have to write^wcopy & paste.
+ *
+ * TODO:
+ * - figure out on the HW side why some data is LE and some is BE.
+ * - general set of improvements possible (e.g., reduce times of copying,
+ * do on-the-copy checksum calculations)
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "opt_device_polling.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/bus.h>
+#include <sys/endian.h>
+#include <sys/lock.h>
+#include <sys/module.h>
+#include <sys/mutex.h>
+#include <sys/proc.h>
+#include <sys/socket.h>
+#include <sys/sockio.h>
+#include <sys/types.h>
+
+#include <net/ethernet.h>
+#include <net/if.h>
+#include <net/if_var.h>
+#include <net/if_dl.h>
+#include <net/if_media.h>
+#include <net/if_types.h>
+#include <net/if_vlan_var.h>
+
+#include <net/bpf.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+#include <sys/rman.h>
+
+#include "if_nf10bmacreg.h"
+
+#ifndef NF10BMAC_MAX_PKTS
+/*
+ * We have a 4k buffer in HW, so do not try to send more than 3 packets.
+ * At the time of writing HW is orders of magnitude faster than we can
+ * enqueue so it would not matter but need an escape.
+ */
+#define NF10BMAC_MAX_PKTS 3
+#endif
+
+#ifndef NF10BMAC_WATCHDOG_TIME
+#define NF10BMAC_WATCHDOG_TIME 5 /* seconds */
+#endif
+
+#ifdef DEVICE_POLLING
+static poll_handler_t nf10bmac_poll;
+#endif
+
+#define NF10BMAC_LOCK(_sc) mtx_lock(&(_sc)->nf10bmac_mtx)
+#define NF10BMAC_UNLOCK(_sc) mtx_unlock(&(_sc)->nf10bmac_mtx)
+#define NF10BMAC_LOCK_ASSERT(_sc) \
+ mtx_assert(&(_sc)->nf10bmac_mtx, MA_OWNED)
+
+#define NF10BMAC_CTRL0 0x00
+#define NF10BMAC_TX_DATA 0x00
+#define NF10BMAC_TX_META 0x08
+#define NF10BMAC_TX_LEN 0x10
+#define NF10BMAC_RX_DATA 0x00
+#define NF10BMAC_RX_META 0x08
+#define NF10BMAC_RX_LEN 0x10
+#define NF10BMAC_INTR_CLEAR_DIS 0x00
+#define NF10BMAC_INTR_CTRL 0x08
+
+#define NF10BMAC_TUSER_MAC0 (1 << 0)
+#define NF10BMAC_TUSER_CPU0 (1 << 1)
+#define NF10BMAC_TUSER_MAC1 (1 << 2)
+#define NF10BMAC_TUSER_CPU1 (1 << 3)
+#define NF10BMAC_TUSER_MAC2 (1 << 4)
+#define NF10BMAC_TUSER_CPU2 (1 << 5)
+#define NF10BMAC_TUSER_MAC3 (1 << 6)
+#define NF10BMAC_TUSER_CPU3 (1 << 7)
+
+#define NF10BMAC_DATA_LEN_MASK 0x0000ffff
+#define NF10BMAC_DATA_DPORT_MASK 0xff000000
+#define NF10BMAC_DATA_DPORT_SHIFT 24
+#define NF10BMAC_DATA_SPORT_MASK 0x00ff0000
+#define NF10BMAC_DATA_SPORT_SHIFT 16
+#define NF10BMAC_DATA_LAST 0x00008000
+#ifdef NF10BMAC_64BIT
+#define NF10BMAC_DATA_STRB 0x000000ff
+#define REGWTYPE uint64_t
+#else
+#define NF10BMAC_DATA_STRB 0x0000000f
+#define REGWTYPE uint32_t
+#endif
+
+
+static inline void
+nf10bmac_write(struct resource *res, REGWTYPE reg, REGWTYPE val,
+ const char *f __unused, const int l __unused)
+{
+
+#ifdef NF10BMAC_64BIT
+ bus_write_8(res, reg, htole64(val));
+#else
+ bus_write_4(res, reg, htole32(val));
+#endif
+}
+
+static inline REGWTYPE
+nf10bmac_read(struct resource *res, REGWTYPE reg,
+ const char *f __unused, const int l __unused)
+{
+
+#ifdef NF10BMAC_64BIT
+ return (le64toh(bus_read_8(res, reg)));
+#else
+ return (le32toh(bus_read_4(res, reg)));
+#endif
+}
+
+static inline void
+nf10bmac_write_be(struct resource *res, REGWTYPE reg, REGWTYPE val,
+ const char *f __unused, const int l __unused)
+{
+
+#ifdef NF10BMAC_64BIT
+ bus_write_8(res, reg, htobe64(val));
+#else
+ bus_write_4(res, reg, htobe32(val));
+#endif
+}
+
+
+static inline REGWTYPE
+nf10bmac_read_be(struct resource *res, REGWTYPE reg,
+ const char *f __unused, const int l __unused)
+{
+
+#ifdef NF10BMAC_64BIT
+ return (be64toh(bus_read_8(res, reg)));
+#else
+ return (be32toh(bus_read_4(res, reg)));
+#endif
+}
+
+#define NF10BMAC_WRITE_CTRL(sc, reg, val) \
+ nf10bmac_write((sc)->nf10bmac_ctrl_res, (reg), (val), \
+ __func__, __LINE__)
+#define NF10BMAC_WRITE(sc, reg, val) \
+ nf10bmac_write((sc)->nf10bmac_tx_mem_res, (reg), (val), \
+ __func__, __LINE__)
+#define NF10BMAC_READ(sc, reg) \
+ nf10bmac_read((sc)->nf10bmac_rx_mem_res, (reg), \
+ __func__, __LINE__)
+#define NF10BMAC_WRITE_BE(sc, reg, val) \
+ nf10bmac_write_be((sc)->nf10bmac_tx_mem_res, (reg), (val), \
+ __func__, __LINE__)
+#define NF10BMAC_READ_BE(sc, reg) \
+ nf10bmac_read_be((sc)->nf10bmac_rx_mem_res, (reg), \
+ __func__, __LINE__)
+
+#define NF10BMAC_WRITE_INTR(sc, reg, val, _f, _l) \
+ nf10bmac_write((sc)->nf10bmac_intr_res, (reg), (val), \
+ (_f), (_l))
+
+#define NF10BMAC_RX_INTR_CLEAR_DIS(sc) \
+ NF10BMAC_WRITE_INTR((sc), NF10BMAC_INTR_CLEAR_DIS, 1, \
+ __func__, __LINE__)
+#define NF10BMAC_RX_INTR_ENABLE(sc) \
+ NF10BMAC_WRITE_INTR((sc), NF10BMAC_INTR_CTRL, 1, \
+ __func__, __LINE__)
+#define NF10BMAC_RX_INTR_DISABLE(sc) \
+ NF10BMAC_WRITE_INTR((sc), NF10BMAC_INTR_CTRL, 0, \
+ __func__, __LINE__)
+
+
+#ifdef ENABLE_WATCHDOG
+static void nf10bmac_tick(void *);
+#endif
+static int nf10bmac_detach(device_t);
+
+devclass_t nf10bmac_devclass;
+
+
+static int
+nf10bmac_tx_locked(struct nf10bmac_softc *sc, struct mbuf *m)
+{
+ int32_t len, l, ml;
+ REGWTYPE md, val;
+
+ NF10BMAC_LOCK_ASSERT(sc);
+
+ KASSERT(m != NULL, ("%s: m is null: sc=%p", __func__, sc));
+ KASSERT(m->m_flags & M_PKTHDR, ("%s: not a pkthdr: m=%p", __func__, m));
+ /*
+ * Copy to buffer to minimize our pain as we can only store
+ * double words which, after the first mbuf gets out of alignment
+ * quite quickly.
+ */
+ m_copydata(m, 0, m->m_pkthdr.len, sc->nf10bmac_tx_buf);
+ len = m->m_pkthdr.len;
+
+ /* Write the length at start of packet. */
+ NF10BMAC_WRITE(sc, NF10BMAC_TX_LEN, len);
+
+ /* Write the meta data and data. */
+ ml = len / sizeof(val);
+ len -= (ml * sizeof(val));
+ for (l = 0; l <= ml; l++) {
+ int32_t cl;
+
+ cl = sizeof(val);
+ md = (NF10BMAC_TUSER_CPU0 << NF10BMAC_DATA_SPORT_SHIFT);
+ if (l == ml || (len == 0 && l == (ml - 1))) {
+ if (l == ml && len == 0) {
+ break;
+ } else {
+ uint8_t s;
+ int sl;
+
+ if (l == (ml - 1))
+ len = sizeof(val);
+ cl = len;
+
+ for (s = 0, sl = len; sl > 0; sl--)
+ s |= (1 << (sl - 1));
+ md |= (s & NF10BMAC_DATA_STRB);
+ md |= NF10BMAC_DATA_LAST;
+ }
+ } else {
+ md |= NF10BMAC_DATA_STRB;
+ }
+ NF10BMAC_WRITE(sc, NF10BMAC_TX_META, md);
+ bcopy(&sc->nf10bmac_tx_buf[l*sizeof(val)], &val, cl);
+ NF10BMAC_WRITE_BE(sc, NF10BMAC_TX_DATA, val);
+ }
+
+ /* If anyone is interested give them a copy. */
+ BPF_MTAP(sc->nf10bmac_ifp, m);
+
+ m_freem(m);
+
+ return (0);
+}
+
+static void
+nf10bmac_start_locked(struct ifnet *ifp)
+{
+ struct nf10bmac_softc *sc;
+ int count, error;
+
+ sc = ifp->if_softc;
+ NF10BMAC_LOCK_ASSERT(sc);
+
+ if ((ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) !=
+ IFF_DRV_RUNNING || (sc->nf10bmac_flags & NF10BMAC_FLAGS_LINK) == 0)
+ return;
+
+#ifdef ENABLE_WATCHDOG
+ /*
+ * Disable the watchdog while sending, we are batching packets.
+ * Though we should never reach 5 seconds, and are holding the lock,
+ * but who knows.
+ */
+ sc->nf10bmac_watchdog_timer = 0;
+#endif
+
+ /* Send up to MAX_PKTS_PER_TX_LOOP packets. */
+ for (count = 0; !IFQ_DRV_IS_EMPTY(&ifp->if_snd) &&
+ count < NF10BMAC_MAX_PKTS; count++) {
+ struct mbuf *m;
+
+ IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
+ if (m == NULL)
+ break;
+ error = nf10bmac_tx_locked(sc, m);
+ if (error != 0)
+ break;
+ }
+
+#ifdef ENABLE_WATCHDOG
+done:
+ /* If the IP core walks into Nekromanteion try to bail out. */
+ /* XXX-BZ useless until we have direct FIFO fill status feedback. */
+ if (count > 0)
+ sc->nf10bmac_watchdog_timer = NF10BMAC_WATCHDOG_TIME;
+#endif
+}
+
+static void
+nf10bmac_start(struct ifnet *ifp)
+{
+ struct nf10bmac_softc *sc;
+
+ sc = ifp->if_softc;
+ NF10BMAC_LOCK(sc);
+ nf10bmac_start_locked(ifp);
+ NF10BMAC_UNLOCK(sc);
+}
+
+static void
+nf10bmac_eat_packet_munch_munch(struct nf10bmac_softc *sc)
+{
+ REGWTYPE md, val;
+
+ do {
+ md = NF10BMAC_READ_BE(sc, NF10BMAC_RX_META);
+ if ((md & NF10BMAC_DATA_STRB) != 0)
+ val = NF10BMAC_READ_BE(sc, NF10BMAC_RX_DATA);
+ } while ((md & NF10BMAC_DATA_STRB) != 0 &&
+ (md & NF10BMAC_DATA_LAST) == 0);
+}
+
+static int
+nf10bmac_rx_locked(struct nf10bmac_softc *sc)
+{
+ struct ifnet *ifp;
+ struct mbuf *m;
+ REGWTYPE md, val;
+ int32_t len, l;
+
+ /*
+ * General problem here in case we need to sync ourselves to the
+ * beginning of a packet. Length will only be set for the first
+ * read, and together with strb we can detect the begining (or
+ * skip to tlast).
+ */
+
+ len = NF10BMAC_READ(sc, NF10BMAC_RX_LEN) & NF10BMAC_DATA_LEN_MASK;
+ if (len > (MCLBYTES - ETHER_ALIGN)) {
+ nf10bmac_eat_packet_munch_munch(sc);
+ return (0);
+ }
+
+ md = NF10BMAC_READ(sc, NF10BMAC_RX_META);
+ if (len == 0 && (md & NF10BMAC_DATA_STRB) == 0) {
+ /* No packet data available. */
+ return (0);
+ } else if (len == 0 && (md & NF10BMAC_DATA_STRB) != 0) {
+ /* We are in the middle of a packet. */
+ nf10bmac_eat_packet_munch_munch(sc);
+ return (0);
+ } else if ((md & NF10BMAC_DATA_STRB) == 0) {
+ /* Invalid length "hint". */
+ device_printf(sc->nf10bmac_dev,
+ "Unexpected length %d on zero strb\n", len);
+ return (0);
+ }
+
+ /* Assume at this point that we have data and a full packet. */
+ if ((len + ETHER_ALIGN) >= MINCLSIZE) {
+ /* Get a cluster. */
+ m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
+ if (m == NULL)
+ return (0);
+ m->m_len = m->m_pkthdr.len = MCLBYTES;
+ } else {
+ /* Hey this still fits into the mbuf+pkthdr. */
+ m = m_gethdr(M_NOWAIT, MT_DATA);
+ if (m == NULL)
+ return (0);
+ m->m_len = m->m_pkthdr.len = MHLEN;
+ }
+ /* Make sure upper layers will be aligned. */
+ m_adj(m, ETHER_ALIGN);
+
+ ifp = sc->nf10bmac_ifp;
+ l = 0;
+/*
+ while ((md & NF10BMAC_DATA_STRB) != 0 && l < len) {
+*/
+ while (l < len) {
+ size_t cl;
+
+ if ((md & NF10BMAC_DATA_LAST) == 0 &&
+ (len - l) < sizeof(val)) {
+ /*
+ * Our length and LAST disagree. We have a valid STRB.
+ * We could continue until we fill the mbuf and just
+ * log the invlid length "hint". For now drop the
+ * packet on the floor and count the error.
+ */
+ nf10bmac_eat_packet_munch_munch(sc);
+ ifp->if_ierrors++;
+ m_freem(m);
+ return (0);
+ } else if ((len - l) <= sizeof(val)) {
+ cl = len - l;
+ } else {
+ cl = sizeof(val);
+ }
+
+ /* Read the first bytes of data as well. */
+ val = NF10BMAC_READ_BE(sc, NF10BMAC_RX_DATA);
+ bcopy(&val, (uint8_t *)(m->m_data + l), cl);
+ l += cl;
+
+ if ((md & NF10BMAC_DATA_LAST) != 0 || l >= len)
+ break;
+ else {
+ DELAY(50);
+ md = NF10BMAC_READ(sc, NF10BMAC_RX_META);
+ }
+
+ cl = 10;
+ while ((md & NF10BMAC_DATA_STRB) == 0 && cl-- > 0) {
+ DELAY(10);
+ md = NF10BMAC_READ(sc, NF10BMAC_RX_META);
+ }
+ }
+ /* We should get out of this loop with tlast and tsrb. */
+ if ((md & NF10BMAC_DATA_LAST) == 0 || (md & NF10BMAC_DATA_STRB) == 0) {
+ device_printf(sc->nf10bmac_dev, "Unexpected rx loop end state: "
+ "md=0x%08jx len=%d l=%d\n", (uintmax_t)md, len, l);
+ ifp->if_ierrors++;
+ m_freem(m);
+ return (0);
+ }
+
+ m->m_pkthdr.len = m->m_len = len;
+ m->m_pkthdr.rcvif = ifp;
+ ifp->if_ipackets++;
+
+ NF10BMAC_UNLOCK(sc);
+ (*ifp->if_input)(ifp, m);
+ NF10BMAC_LOCK(sc);
+
+ return (1);
+}
+
+
+static int
+nf10bmac_stop_locked(struct nf10bmac_softc *sc)
+{
+ struct ifnet *ifp;
+
+ NF10BMAC_LOCK_ASSERT(sc);
+
+#ifdef ENABLE_WATCHDOG
+ sc->nf10bmac_watchdog_timer = 0;
+ callout_stop(&sc->nf10bmac_tick);
+#endif
+
+ ifp = sc->nf10bmac_ifp;
+ ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
+ NF10BMAC_RX_INTR_CLEAR_DIS(sc);
+
+ sc->nf10bmac_flags &= ~NF10BMAC_FLAGS_LINK;
+ if_link_state_change(ifp, LINK_STATE_DOWN);
+
+ return (0);
+}
+
+static int
+nf10bmac_reset(struct nf10bmac_softc *sc)
+{
+
+ /*
+ * If we do not have an ether address set, initialize to the same
+ * OUI as NetFPGA-10G Linux driver does (which luckily seems
+ * unallocated). We just change the NIC specific part from
+ * the slightly long "\0NF10C0" to "\0NFBSD".
+ * Oh and we keep the way of setting it from a string as they do.
+ * It's an amazing way to hide it.
+ * XXX-BZ If NetFPGA gets their own OUI we should fix this.
+ */
+ if (sc->nf10bmac_eth_addr[0] == 0x00 &&
+ sc->nf10bmac_eth_addr[1] == 0x00 &&
+ sc->nf10bmac_eth_addr[2] == 0x00 &&
+ sc->nf10bmac_eth_addr[3] == 0x00 &&
+ sc->nf10bmac_eth_addr[4] == 0x00 &&
+ sc->nf10bmac_eth_addr[5] == 0x00) {
+ memcpy(&sc->nf10bmac_eth_addr, "\0NFBSD", ETHER_ADDR_LEN);
+ sc->nf10bmac_eth_addr[5] += sc->nf10bmac_unit;
+ }
+
+ return (0);
+}
+
+static void
+nf10bmac_init_locked(struct nf10bmac_softc *sc)
+{
+ struct ifnet *ifp;
+ uint8_t *eaddr;
+
+ NF10BMAC_LOCK_ASSERT(sc);
+ ifp = sc->nf10bmac_ifp;
+
+ if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0)
+ return;
+
+ /*
+ * Must update the ether address if changed. Given we do not handle
+ * in nf10bmac_ioctl() but it's in the general framework, just always
+ * do it here before nf10bmac_reset().
+ */
+ eaddr = IF_LLADDR(sc->nf10bmac_ifp);
+ bcopy(eaddr, &sc->nf10bmac_eth_addr, ETHER_ADDR_LEN);
+ /* XXX-BZ we do not have any way to tell the NIC our ether address. */
+
+ /* Make things frind to halt, cleanup, ... */
+ nf10bmac_stop_locked(sc);
+ /* ... reset, ... */
+ nf10bmac_reset(sc);
+
+ /* Memory rings? DMA engine? MC filter? MII? */
+ /* Instead drain the FIFO; or at least a possible first packet.. */
+ nf10bmac_eat_packet_munch_munch(sc);
+
+#ifdef DEVICE_POLLING
+ /* Only enable interrupts if we are not polling. */
+ if (ifp->if_capenable & IFCAP_POLLING) {
+ NF10BMAC_RX_INTR_CLEAR_DIS(sc);
+ } else
+#endif
+ {
+ NF10BMAC_RX_INTR_ENABLE(sc);
+ }
+
+ ifp->if_drv_flags |= IFF_DRV_RUNNING;
+ ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
+
+ /* We have no underlying media, fake link state. */
+ sc->nf10bmac_flags = NF10BMAC_FLAGS_LINK; /* Always up. */
+ if_link_state_change(sc->nf10bmac_ifp, LINK_STATE_UP);
+
+#ifdef ENABLE_WATCHDOG
+ callout_reset(&sc->nf10bmac_tick, hz, nf10bmac_tick, sc);
+#endif
+}
+
+static void
+nf10bmac_init(void *xsc)
+{
+ struct nf10bmac_softc *sc;
+
+ sc = (struct nf10bmac_softc *)xsc;
+ NF10BMAC_LOCK(sc);
+ nf10bmac_init_locked(sc);
+ NF10BMAC_UNLOCK(sc);
+}
+
+#ifdef ENABLE_WATCHDOG
+static void
+nf10bmac_watchdog(struct nf10bmac_softc *sc)
+{
+
+ NF10BMAC_LOCK_ASSERT(sc);
+
+ if (sc->nf10bmac_watchdog_timer == 0 || --sc->nf10bmac_watchdog_timer > 0)
+ return;
+
+ device_printf(sc->nf10bmac_dev, "watchdog timeout\n");
+ sc->nf10bmac_ifp->if_oerrors++;
+
+ sc->nf10bmac_ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
+ nf10bmac_init_locked(sc);
+
+ if (!IFQ_DRV_IS_EMPTY(&sc->nf10bmac_ifp->if_snd))
+ nf10bmac_start_locked(sc->nf10bmac_ifp);
+}
+
+static void
+nf10bmac_tick(void *xsc)
+{
+ struct nf10bmac_softc *sc;
+ struct ifnet *ifp;
+
+ sc = (struct nf10bmac_softc *)xsc;
+ NF10BMAC_LOCK_ASSERT(sc);
+ ifp = sc->nf10bmac_ifp;
+
+ nf10bmac_watchdog(sc);
+ callout_reset(&sc->nf10bmac_tick, hz, nf10bmac_tick, sc);
+}
+#endif
+
+static void
+nf10bmac_intr(void *arg)
+{
+ struct nf10bmac_softc *sc;
+ struct ifnet *ifp;
+ int rx_npkts;
+
+ sc = (struct nf10bmac_softc *)arg;
+ ifp = sc->nf10bmac_ifp;
+
+ NF10BMAC_LOCK(sc);
+#ifdef DEVICE_POLLING
+ if (ifp->if_capenable & IFCAP_POLLING) {
+ NF10BMAC_UNLOCK(sc);
+ return;
+ }
+#endif
+
+ /* NF10BMAC_RX_INTR_DISABLE(sc); */
+ NF10BMAC_RX_INTR_CLEAR_DIS(sc);
+
+ /* We only have an RX interrupt and no status information. */
+ rx_npkts = 0;
+ while (rx_npkts < NF10BMAC_MAX_PKTS) {
+ int c;
+
+ c = nf10bmac_rx_locked(sc);
+ rx_npkts += c;
+ if (c == 0)
+ break;
+ }
+
+ if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
+ /* Re-enable interrupts. */
+ NF10BMAC_RX_INTR_ENABLE(sc);
+
+ if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
+ nf10bmac_start_locked(ifp);
+ }
+ NF10BMAC_UNLOCK(sc);
+}
+
+
+#ifdef DEVICE_POLLING
+static int
+nf10bmac_poll(struct ifnet *ifp, enum poll_cmd cmd, int count)
+{
+ struct nf10bmac_softc *sc;
+ int rx_npkts = 0;
+
+ sc = ifp->if_softc;
+ NF10BMAC_LOCK(sc);
+ if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
+ NF10BMAC_UNLOCK(sc);
+ return (rx_npkts);
+ }
+
+ while (rx_npkts < count) {
+ int c;
+
+ c = nf10bmac_rx_locked(sc);
+ rx_npkts += c;
+ if (c == 0)
+ break;
+ }
+ nf10bmac_start_locked(ifp);
+
+ if (rx_npkts > 0 || cmd == POLL_AND_CHECK_STATUS) {
+ /* We currently cannot do much. */
+ ;
+ }
+
+ NF10BMAC_UNLOCK(sc);
+ return (rx_npkts);
+}
+#else
+#error We only support polling mode
+#endif /* DEVICE_POLLING */
+
+static int
+nf10bmac_media_change(struct ifnet *ifp __unused)
+{
+
+ /* Do nothing. */
+ return (0);
+}
+
+static void
+nf10bmac_media_status(struct ifnet *ifp __unused, struct ifmediareq *imr)
+{
+
+ imr->ifm_status = IFM_AVALID | IFM_ACTIVE;
+ imr->ifm_active = IFM_ETHER | IFM_10G_T | IFM_FDX;
+}
+
+static int
+nf10bmac_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
+{
+ struct nf10bmac_softc *sc;
+ struct ifreq *ifr;
+ int error, mask;
+
+ error = 0;
+ sc = ifp->if_softc;
+ ifr = (struct ifreq *)data;
+
+ switch (command) {
+ case SIOCSIFFLAGS:
+ NF10BMAC_LOCK(sc);
+ if (ifp->if_flags & IFF_UP) {
+ if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0 &&
+ ((ifp->if_flags ^ sc->nf10bmac_if_flags) &
+ (IFF_PROMISC | IFF_ALLMULTI)) != 0)
+ /* Nothing we can do. */ ;
+ else
+ nf10bmac_init_locked(sc);
+ } else if (ifp->if_drv_flags & IFF_DRV_RUNNING)
+ nf10bmac_stop_locked(sc);
+ sc->nf10bmac_if_flags = ifp->if_flags;
+ NF10BMAC_UNLOCK(sc);
+ break;
+ case SIOCSIFCAP:
+ NF10BMAC_LOCK(sc);
+ mask = ifr->ifr_reqcap ^ ifp->if_capenable;
+#ifdef DEVICE_POLLING
+ if ((mask & IFCAP_POLLING) != 0 &&
+ (IFCAP_POLLING & ifp->if_capabilities) != 0) {
+ ifp->if_capenable ^= IFCAP_POLLING;
+ if ((IFCAP_POLLING & ifp->if_capenable) != 0) {
+
+ error = ether_poll_register(nf10bmac_poll, ifp);
+ if (error != 0) {
+ NF10BMAC_UNLOCK(sc);
+ break;
+ }
+
+ NF10BMAC_RX_INTR_CLEAR_DIS(sc);
+
+ /*
+ * Do not allow disabling of polling if we do
+ * not have interrupts.
+ */
+ } else if (sc->nf10bmac_rx_irq_res != NULL) {
+ error = ether_poll_deregister(ifp);
+ /* Enable interrupts. */
+ NF10BMAC_RX_INTR_ENABLE(sc);
+ } else {
+ ifp->if_capenable ^= IFCAP_POLLING;
+ error = EINVAL;
+ }
+ }
+#endif /* DEVICE_POLLING */
+ NF10BMAC_UNLOCK(sc);
+ break;
+ case SIOCGIFMEDIA:
+ case SIOCSIFMEDIA:
+ error = ifmedia_ioctl(ifp, ifr, &sc->nf10bmac_media, command);
+ break;
+ default:
+ error = ether_ioctl(ifp, command, data);
+ break;
+ }
+
+ return (error);
+}
+
+/*
+ * Generic device handling routines.
+ */
+int
+nf10bmac_attach(device_t dev)
+{
+ struct nf10bmac_softc *sc;
+ struct ifnet *ifp;
+ int error;
+
+ sc = device_get_softc(dev);
+
+ mtx_init(&sc->nf10bmac_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK,
+ MTX_DEF);
+
+#ifdef ENABLE_WATCHDOG
+ callout_init_mtx(&sc->nf10bmac_tick, &sc->nf10bmac_mtx, 0);
+#endif
+
+ sc->nf10bmac_tx_buf = malloc(ETHER_MAX_LEN_JUMBO, M_DEVBUF, M_WAITOK);
+
+ /* Reset the adapter. */
+ nf10bmac_reset(sc);
+
+ /* Setup interface. */
+ ifp = sc->nf10bmac_ifp = if_alloc(IFT_ETHER);
+ if (ifp == NULL) {
+ device_printf(dev, "if_alloc() failed\n");
+ error = ENOSPC;
+ goto err;
+ }
+ ifp->if_softc = sc;
+ if_initname(ifp, device_get_name(dev), device_get_unit(dev));
+ ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX; /* | IFF_MULTICAST; */
+ ifp->if_ioctl = nf10bmac_ioctl;
+ ifp->if_start = nf10bmac_start;
+ ifp->if_init = nf10bmac_init;
+ IFQ_SET_MAXLEN(&ifp->if_snd, NF10BMAC_MAX_PKTS - 1);
+ ifp->if_snd.ifq_drv_maxlen = NF10BMAC_MAX_PKTS - 1;
+ IFQ_SET_READY(&ifp->if_snd);
+
+ /* Call media-indepedent attach routine. */
+ ether_ifattach(ifp, sc->nf10bmac_eth_addr);
+
+ /* Tell the upper layer(s) about vlan mtu support. */
+ ifp->if_data.ifi_hdrlen = sizeof(struct ether_vlan_header);
+ ifp->if_capabilities |= IFCAP_VLAN_MTU;
+ ifp->if_capenable = ifp->if_capabilities;
+#ifdef DEVICE_POLLING
+ /* We will enable polling by default if no irqs available. See below. */
+ ifp->if_capabilities |= IFCAP_POLLING;
+#endif
+
+ /* We need more media attention. Fake it! */
+ ifmedia_init(&sc->nf10bmac_media, 0, nf10bmac_media_change,
+ nf10bmac_media_status);
+ ifmedia_add(&sc->nf10bmac_media, IFM_ETHER | IFM_10G_T, 0, NULL);
+ ifmedia_set(&sc->nf10bmac_media, IFM_ETHER | IFM_10G_T);
+
+ /* Initialise. */
+ error = 0;
+
+ /* Hook up interrupts. Well the one. */
+ if (sc->nf10bmac_rx_irq_res != NULL) {
+ error = bus_setup_intr(dev, sc->nf10bmac_rx_irq_res,
+ INTR_TYPE_NET | INTR_MPSAFE, NULL, nf10bmac_intr,
+ sc, &sc->nf10bmac_rx_intrhand);
+ if (error != 0) {
+ device_printf(dev, "enabling RX IRQ failed\n");
+ ether_ifdetach(ifp);
+ goto err;
+ }
+ }
+
+ if ((ifp->if_capenable & IFCAP_POLLING) != 0 ||
+ sc->nf10bmac_rx_irq_res == NULL) {
+#ifdef DEVICE_POLLING
+ /* If not on and no IRQs force it on. */
+ if (sc->nf10bmac_rx_irq_res == NULL) {
+ ifp->if_capenable |= IFCAP_POLLING;
+ device_printf(dev,
+ "forcing to polling due to no interrupts\n");
+ }
+ error = ether_poll_register(nf10bmac_poll, ifp);
+ if (error != 0)
+ goto err;
+#else
+ device_printf(dev, "no DEVICE_POLLING in kernel and no IRQs\n");
+ error = ENXIO;
+#endif
+ } else {
+ NF10BMAC_RX_INTR_ENABLE(sc);
+ }
+
+err:
+ if (error != 0)
+ nf10bmac_detach(dev);
+
+ return (error);
+}
+
+static int
+nf10bmac_detach(device_t dev)
+{
+ struct nf10bmac_softc *sc;
+ struct ifnet *ifp;
+
+ sc = device_get_softc(dev);
+ KASSERT(mtx_initialized(&sc->nf10bmac_mtx),
+ ("%s: mutex not initialized", device_get_nameunit(dev)));
+ ifp = sc->nf10bmac_ifp;
+
+#ifdef DEVICE_POLLING
+ if (ifp->if_capenable & IFCAP_POLLING)
+ ether_poll_deregister(ifp);
+#endif
+
+ /* Only cleanup if attach succeeded. */
+ if (device_is_attached(dev)) {
+ NF10BMAC_LOCK(sc);
+ nf10bmac_stop_locked(sc);
+ NF10BMAC_UNLOCK(sc);
+#ifdef ENABLE_WATCHDOG
+ callout_drain(&sc->nf10bmac_tick);
+#endif
+ ether_ifdetach(ifp);
+ }
+
+ if (sc->nf10bmac_rx_intrhand)
+ bus_teardown_intr(dev, sc->nf10bmac_rx_irq_res,
+ sc->nf10bmac_rx_intrhand);
+
+ if (ifp != NULL)
+ if_free(ifp);
+ ifmedia_removeall(&sc->nf10bmac_media);
+
+ mtx_destroy(&sc->nf10bmac_mtx);
+
+ return (0);
+}
+
+/* Shared with the attachment specific (e.g., fdt) implementation. */
+void
+nf10bmac_detach_resources(device_t dev)
+{
+ struct nf10bmac_softc *sc;
+
+ sc = device_get_softc(dev);
+
+ if (sc->nf10bmac_rx_irq_res != NULL) {
+ bus_release_resource(dev, SYS_RES_IRQ, sc->nf10bmac_rx_irq_rid,
+ sc->nf10bmac_rx_irq_res);
+ sc->nf10bmac_rx_irq_res = NULL;
+ }
+ if (sc->nf10bmac_intr_res != NULL) {
+ bus_release_resource(dev, SYS_RES_MEMORY,
+ sc->nf10bmac_intr_rid, sc->nf10bmac_intr_res);
+ sc->nf10bmac_intr_res = NULL;
+ }
+ if (sc->nf10bmac_rx_mem_res != NULL) {
+ bus_release_resource(dev, SYS_RES_MEMORY,
+ sc->nf10bmac_rx_mem_rid, sc->nf10bmac_rx_mem_res);
+ sc->nf10bmac_rx_mem_res = NULL;
+ }
+ if (sc->nf10bmac_tx_mem_res != NULL) {
+ bus_release_resource(dev, SYS_RES_MEMORY,
+ sc->nf10bmac_tx_mem_rid, sc->nf10bmac_tx_mem_res);
+ sc->nf10bmac_tx_mem_res = NULL;
+ }
+ if (sc->nf10bmac_ctrl_res != NULL) {
+ bus_release_resource(dev, SYS_RES_MEMORY,
+ sc->nf10bmac_ctrl_rid, sc->nf10bmac_ctrl_res);
+ sc->nf10bmac_ctrl_res = NULL;
+ }
+}
+
+int
+nf10bmac_detach_dev(device_t dev)
+{
+ int error;
+
+ error = nf10bmac_detach(dev);
+ if (error) {
+ /* We are basically in undefined state now. */
+ device_printf(dev, "nf10bmac_detach() failed: %d\n", error);
+ return (error);
+ }
+
+ nf10bmac_detach_resources(dev);
+
+ return (0);
+}
+
+/* end */
diff --git a/sys/dev/netfpga10g/nf10bmac/if_nf10bmac_fdt.c b/sys/dev/netfpga10g/nf10bmac/if_nf10bmac_fdt.c
new file mode 100644
index 0000000..ef903c6
--- /dev/null
+++ b/sys/dev/netfpga10g/nf10bmac/if_nf10bmac_fdt.c
@@ -0,0 +1,203 @@
+/*-
+ * Copyright (c) 2013-2014 Bjoern A. Zeeb
+ * All rights reserved.
+ *
+ * This software was developed by SRI International and the University of
+ * Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249
+ * ("MRC2"), as part of the DARPA MRC 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.
+ *
+ * This driver is modelled after atse(4). We need to seriously reduce the
+ * per-driver code we have to write^wcopy & paste.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/rman.h>
+#include <sys/socket.h>
+#include <sys/systm.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+
+#include <net/ethernet.h>
+#include <net/if.h>
+#include <net/if_media.h>
+#include <net/if_var.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 "if_nf10bmacreg.h"
+
+static int
+nf10bmac_probe_fdt(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (ofw_bus_is_compatible(dev, "netfpag10g,nf10bmac")) {
+ device_set_desc(dev, "NetFPGA-10G Embedded CPU Ethernet Core");
+ return (BUS_PROBE_DEFAULT);
+ }
+
+ return (ENXIO);
+}
+
+static int
+nf10bmac_attach_fdt(device_t dev)
+{
+ struct nf10bmac_softc *sc;
+ int error;
+
+ sc = device_get_softc(dev);
+ sc->nf10bmac_dev = dev;
+ sc->nf10bmac_unit = device_get_unit(dev);
+
+ /*
+ * FDT lists our resources. For convenience we use three different
+ * mappings. We need to attach them in the oder specified in .dts:
+ * LOOP (size 0x1f), TX (0x2f), RX (0x2f), INTR (0xf).
+ */
+
+ /*
+ * LOOP memory region (this could be a general control region).
+ * 0x00: 32/64bit register to enable a Y-"lopback".
+ */
+ sc->nf10bmac_ctrl_rid = 0;
+ sc->nf10bmac_ctrl_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
+ &sc->nf10bmac_ctrl_rid, RF_ACTIVE);
+ if (sc->nf10bmac_ctrl_res == NULL) {
+ device_printf(dev, "failed to map memory for CTRL region\n");
+ error = ENXIO;
+ goto err;
+ }
+ if (bootverbose)
+ device_printf(sc->nf10bmac_dev, "CTRL region at mem %p-%p\n",
+ (void *)rman_get_start(sc->nf10bmac_ctrl_res),
+ (void *)(rman_get_start(sc->nf10bmac_ctrl_res) +
+ rman_get_size(sc->nf10bmac_ctrl_res)));
+
+ /*
+ * TX and TX metadata FIFO memory region.
+ * 0x00: 32/64bit FIFO data,
+ * 0x08: 32/64bit FIFO metadata,
+ * 0x10: 32/64bit packet length.
+ */
+ sc->nf10bmac_tx_mem_rid = 1;
+ sc->nf10bmac_tx_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
+ &sc->nf10bmac_tx_mem_rid, RF_ACTIVE);
+ if (sc->nf10bmac_tx_mem_res == NULL) {
+ device_printf(dev, "failed to map memory for TX FIFO\n");
+ error = ENXIO;
+ goto err;
+ }
+ if (bootverbose)
+ device_printf(sc->nf10bmac_dev, "TX FIFO at mem %p-%p\n",
+ (void *)rman_get_start(sc->nf10bmac_tx_mem_res),
+ (void *)(rman_get_start(sc->nf10bmac_tx_mem_res) +
+ rman_get_size(sc->nf10bmac_tx_mem_res)));
+
+ /*
+ * RX and RXC metadata FIFO memory region.
+ * 0x00: 32/64bit FIFO data,
+ * 0x08: 32/64bit FIFO metadata,
+ * 0x10: 32/64bit packet length.
+ */
+ sc->nf10bmac_rx_mem_rid = 2;
+ sc->nf10bmac_rx_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
+ &sc->nf10bmac_rx_mem_rid, RF_ACTIVE);
+ if (sc->nf10bmac_rx_mem_res == NULL) {
+ device_printf(dev, "failed to map memory for RX FIFO\n");
+ error = ENXIO;
+ goto err;
+ }
+ if (bootverbose)
+ device_printf(sc->nf10bmac_dev, "RX FIFO at mem %p-%p\n",
+ (void *)rman_get_start(sc->nf10bmac_rx_mem_res),
+ (void *)(rman_get_start(sc->nf10bmac_rx_mem_res) +
+ rman_get_size(sc->nf10bmac_rx_mem_res)));
+
+ /*
+ * Interrupt handling registers.
+ * 0x00: 32/64bit register to clear (and disable) the RX interrupt.
+ * 0x08: 32/64bit register to enable or disable the RX interrupt.
+ */
+ sc->nf10bmac_intr_rid = 3;
+ sc->nf10bmac_intr_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
+ &sc->nf10bmac_intr_rid, RF_ACTIVE);
+ if (sc->nf10bmac_intr_res == NULL) {
+ device_printf(dev, "failed to map memory for INTR region\n");
+ error = ENXIO;
+ goto err;
+ }
+ if (bootverbose)
+ device_printf(sc->nf10bmac_dev, "INTR region at mem %p-%p\n",
+ (void *)rman_get_start(sc->nf10bmac_intr_res),
+ (void *)(rman_get_start(sc->nf10bmac_intr_res) +
+ rman_get_size(sc->nf10bmac_intr_res)));
+
+ /* (Optional) RX and TX IRQ. */
+ sc->nf10bmac_rx_irq_rid = 0;
+ sc->nf10bmac_rx_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ,
+ &sc->nf10bmac_rx_irq_rid, RF_ACTIVE | RF_SHAREABLE);
+
+ error = nf10bmac_attach(dev);
+ if (error)
+ goto err;
+
+ return (0);
+
+err:
+ /* Cleanup. */
+ nf10bmac_detach_resources(dev);
+
+ return (error);
+}
+
+static device_method_t nf10bmac_methods_fdt[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, nf10bmac_probe_fdt),
+ DEVMETHOD(device_attach, nf10bmac_attach_fdt),
+ DEVMETHOD(device_detach, nf10bmac_detach_dev),
+
+ DEVMETHOD_END
+};
+
+static driver_t nf10bmac_driver_fdt = {
+ "nf10bmac",
+ nf10bmac_methods_fdt,
+ sizeof(struct nf10bmac_softc)
+};
+
+DRIVER_MODULE(nf10bmac, simplebus, nf10bmac_driver_fdt, nf10bmac_devclass, 0,0);
+
+/* end */
diff --git a/sys/dev/netfpga10g/nf10bmac/if_nf10bmacreg.h b/sys/dev/netfpga10g/nf10bmac/if_nf10bmacreg.h
new file mode 100644
index 0000000..fa58116
--- /dev/null
+++ b/sys/dev/netfpga10g/nf10bmac/if_nf10bmacreg.h
@@ -0,0 +1,72 @@
+/*-
+ * Copyright (c) 2014 Bjoern A. Zeeb
+ * All rights reserved.
+ *
+ * This software was developed by SRI International and the University of
+ * Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249
+ * ("MRC2"), as part of the DARPA MRC 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$
+ */
+
+#ifndef _DEV_IF_NF10BMACREG_H
+#define _DEV_IF_NF10BMACREG_H
+
+struct nf10bmac_softc {
+ struct ifnet *nf10bmac_ifp;
+ struct resource *nf10bmac_ctrl_res;
+ struct resource *nf10bmac_tx_mem_res;
+ struct resource *nf10bmac_rx_mem_res;
+ struct resource *nf10bmac_intr_res;
+ struct resource *nf10bmac_rx_irq_res;
+ void *nf10bmac_rx_intrhand;
+ uint8_t *nf10bmac_tx_buf;
+ device_t nf10bmac_dev;
+ int nf10bmac_unit;
+ int nf10bmac_ctrl_rid;
+ int nf10bmac_tx_mem_rid;
+ int nf10bmac_rx_mem_rid;
+ int nf10bmac_intr_rid;
+ int nf10bmac_rx_irq_rid;
+ int nf10bmac_if_flags;
+ uint32_t nf10bmac_flags;
+#define NF10BMAC_FLAGS_LINK 0x00000001
+ uint8_t nf10bmac_eth_addr[ETHER_ADDR_LEN];
+#ifdef ENABLE_WATCHDOG
+ uint16_t nf10bmac_watchdog_timer;
+ struct callout nf10bmac_tick;
+#endif
+ struct ifmedia nf10bmac_media; /* to fake it. */
+ struct mtx nf10bmac_mtx;
+};
+
+int nf10bmac_attach(device_t);
+int nf10bmac_detach_dev(device_t);
+void nf10bmac_detach_resources(device_t);
+
+extern devclass_t nf10bmac_devclass;
+
+#endif /* _DEV_IF_NF10BMACREG_H */
+
+/* end */
OpenPOWER on IntegriCloud