diff options
-rw-r--r-- | share/man/man4/Makefile | 2 | ||||
-rw-r--r-- | share/man/man4/netfpga10g_nf10bmac.4 | 70 | ||||
-rw-r--r-- | sys/boot/fdt/dts/mips/beri-netfpga.dts | 14 | ||||
-rw-r--r-- | sys/dev/netfpga10g/nf10bmac/if_nf10bmac.c | 969 | ||||
-rw-r--r-- | sys/dev/netfpga10g/nf10bmac/if_nf10bmac_fdt.c | 203 | ||||
-rw-r--r-- | sys/dev/netfpga10g/nf10bmac/if_nf10bmacreg.h | 72 | ||||
-rw-r--r-- | sys/mips/beri/files.beri | 2 | ||||
-rw-r--r-- | sys/mips/conf/BERI_NETFPGA_MDROOT | 5 | ||||
-rw-r--r-- | sys/modules/Makefile | 1 | ||||
-rw-r--r-- | sys/modules/netfpga10g/Makefile | 12 | ||||
-rw-r--r-- | sys/modules/netfpga10g/nf10bmac/Makefile | 16 |
11 files changed, 1365 insertions, 1 deletions
diff --git a/share/man/man4/Makefile b/share/man/man4/Makefile index 3a9af12..45e8dbf 100644 --- a/share/man/man4/Makefile +++ b/share/man/man4/Makefile @@ -282,6 +282,7 @@ MAN= aac.4 \ ncv.4 \ ${_ndis.4} \ net80211.4 \ + netfpga10g_nf10bmac.4 \ netgraph.4 \ netintro.4 \ netmap.4 \ @@ -678,6 +679,7 @@ MLINKS+=mwl.4 if_mwl.4 MLINKS+=mxge.4 if_mxge.4 MLINKS+=my.4 if_my.4 MLINKS+=${_ndis.4} ${_if_ndis.4} +MLINKS+=netfpga10g_nf10bmac.4 if_nf10bmac.4 MLINKS+=netintro.4 net.4 \ netintro.4 networking.4 MLINKS+=${_nfe.4} ${_if_nfe.4} diff --git a/share/man/man4/netfpga10g_nf10bmac.4 b/share/man/man4/netfpga10g_nf10bmac.4 new file mode 100644 index 0000000..a2ee787 --- /dev/null +++ b/share/man/man4/netfpga10g_nf10bmac.4 @@ -0,0 +1,70 @@ +.\"- +.\" 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$ +.\" +.Dd April 17, 2014 +.Dt NETFPGA10G_NF10BMAC 4 +.Os +.Sh NAME +.Nm netfpga10g_nf10bmac +.Nd driver for the NetFPGA-10G Embedded CPU Ethernet Core +.Sh SYNOPSIS +.Cd "device netfpga10g_nf10bmac" +.Sh DESCRIPTION +The +.Nm +device driver provides support for the NetFPGA-10G Embedded CPU Ethernet +Core. +.Sh HARDWARE +The current version of the +.Nm +driver works with one PIO mode interface of the +NetFPGA-10G Embedded CPU Ethernet Core version 1.00a. +.Sh SEE ALSO +.Xr netintro 4 , +.Xr ifconfig 8 +.Rs +.%T NetFPGA-10G Wiki +.%U https://github.com/NetFPGA/NetFPGA-public/wiki +.Re +.Sh HISTORY +The +.Nm +device driver first appeared in +.Fx 11.0 . +.Sh AUTHORS +This software and this manual page were +developed by SRI International and the University of Cambridge Computer +Laboratory under DARPA/AFRL contract +.Pq FA8750-11-C-0249 +.Pq Do MRC2 Dc , +as part of the DARPA MRC research programme. +The device driver was written by +.An Bjoern A. Zeeb . diff --git a/sys/boot/fdt/dts/mips/beri-netfpga.dts b/sys/boot/fdt/dts/mips/beri-netfpga.dts index 509d387..9064257 100644 --- a/sys/boot/fdt/dts/mips/beri-netfpga.dts +++ b/sys/boot/fdt/dts/mips/beri-netfpga.dts @@ -1,7 +1,7 @@ /*- * Copyright (c) 2012-2013 Robert N. M. Watson * Copyright (c) 2013 SRI International - * Copyright (c) 2013 Bjoern A. Zeeb + * Copyright (c) 2013-2014 Bjoern A. Zeeb * All rights reserved. * * This software was developed by SRI International and the University of @@ -130,6 +130,18 @@ interrupt-parent = <&beripic>; }; */ + + ethernet@7f005000 { + compatible = "netfpag10g,nf10bmac"; + // LOOP, TX, RX, INTR + reg = <0x7f005000 0x20 + 0x7f005020 0x30 + 0x7f005050 0x30 + 0x7f005100 0x10>; + // RX + interrupts = <1>; + interrupt-parent = <&beripic>; + }; }; aliases { 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 */ diff --git a/sys/mips/beri/files.beri b/sys/mips/beri/files.beri index de7ccc3..ffd70fe 100644 --- a/sys/mips/beri/files.beri +++ b/sys/mips/beri/files.beri @@ -6,6 +6,8 @@ dev/altera/jtag_uart/altera_jtag_uart_cons.c optional altera_jtag_uart dev/altera/jtag_uart/altera_jtag_uart_tty.c optional altera_jtag_uart dev/altera/jtag_uart/altera_jtag_uart_fdt.c optional altera_jtag_uart fdt dev/altera/jtag_uart/altera_jtag_uart_nexus.c optional altera_jtag_uart +dev/netfpga10g/nf10bmac/if_nf10bmac_fdt.c optional netfpga10g_nf10bmac fdt +dev/netfpga10g/nf10bmac/if_nf10bmac.c optional netfpga10g_nf10bmac dev/terasic/de4led/terasic_de4led.c optional terasic_de4led dev/terasic/de4led/terasic_de4led_fdt.c optional terasic_de4led fdt dev/terasic/de4led/terasic_de4led_nexus.c optional terasic_de4led diff --git a/sys/mips/conf/BERI_NETFPGA_MDROOT b/sys/mips/conf/BERI_NETFPGA_MDROOT index bd7b3a4..2ba4917 100644 --- a/sys/mips/conf/BERI_NETFPGA_MDROOT +++ b/sys/mips/conf/BERI_NETFPGA_MDROOT @@ -19,6 +19,11 @@ makeoptions FDT_DTS_FILE=beri-netfpga.dts #device uart device altera_jtag_uart +device bpf + +options DEVICE_POLLING +device netfpga10g_nf10bmac + # # This kernel configuration uses an embedded memory root file system. # Adjust the following path and size based on local requirements. diff --git a/sys/modules/Makefile b/sys/modules/Makefile index 3f06e9b..1e26093 100644 --- a/sys/modules/Makefile +++ b/sys/modules/Makefile @@ -239,6 +239,7 @@ SUBDIR= \ ${_ncp} \ ${_ncv} \ ${_ndis} \ + netfpga10g \ ${_netgraph} \ ${_nfe} \ nfs_common \ diff --git a/sys/modules/netfpga10g/Makefile b/sys/modules/netfpga10g/Makefile new file mode 100644 index 0000000..1ebdf8c --- /dev/null +++ b/sys/modules/netfpga10g/Makefile @@ -0,0 +1,12 @@ +# +# $FreeBSD$ +# + +SUBDIR= +SUBDIR+= ${_nf10bmac} + +.if ${MACHINE_CPUARCH} == "mips" +_nf10bmac= nf10bmac +.endif + +.include <bsd.subdir.mk> diff --git a/sys/modules/netfpga10g/nf10bmac/Makefile b/sys/modules/netfpga10g/nf10bmac/Makefile new file mode 100644 index 0000000..06636d9 --- /dev/null +++ b/sys/modules/netfpga10g/nf10bmac/Makefile @@ -0,0 +1,16 @@ +# $FreeBSD$ + +.PATH: ${.CURDIR}/../../../dev/netfpga10g/nf10bmac + +KMOD= if_nf10bmac +SRCS= if_nf10bmac.c +SRCS+= device_if.h bus_if.h pci_if.h +SRCS+= opt_device_polling.h + +.if ${MACHINE_CPUARCH} == "mips" +SRCS+= if_nf10bmac_fdt.c ofw_bus_if.h +.endif + +CFLAGS+= -DDEVICE_POLLING + +.include <bsd.kmod.mk> |