Index: head/sys/dev/altera/atse/if_atse.c
===================================================================
--- head/sys/dev/altera/atse/if_atse.c (revision 332473)
+++ head/sys/dev/altera/atse/if_atse.c (revision 332474)
@@ -1,2099 +1,1603 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2012, 2013 Bjoern A. Zeeb
* Copyright (c) 2014 Robert N. M. Watson
+ * Copyright (c) 2016-2017 Ruslan Bukin
* 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.
*/
/*
* Altera Triple-Speed Ethernet MegaCore, Function User Guide
* UG-01008-3.0, Software Version: 12.0, June 2012.
* Available at the time of writing at:
* http://www.altera.com/literature/ug/ug_ethernet.pdf
*
* We are using an Marvell E1111 (Alaska) PHY on the DE4. See mii/e1000phy.c.
*/
/*
* XXX-BZ NOTES:
* - ifOutBroadcastPkts are only counted if both ether dst and src are all-1s;
* seems an IP core bug, they count ether broadcasts as multicast. Is this
* still the case?
* - figure out why the TX FIFO fill status and intr did not work as expected.
* - test 100Mbit/s and 10Mbit/s
* - blacklist the one special factory programmed ethernet address (for now
* hardcoded, later from loader?)
* - resolve all XXX, left as reminders to shake out details later
* - Jumbo frame support
*/
#include
__FBSDID("$FreeBSD$");
#include "opt_device_polling.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
-#include
+#include
-MODULE_DEPEND(atse, ether, 1, 1, 1);
-MODULE_DEPEND(atse, miibus, 1, 1, 1);
+#define RX_QUEUE_SIZE 4096
+#define TX_QUEUE_SIZE 4096
+#define NUM_RX_MBUF 512
+#define BUFRING_SIZE 8192
+#include
-#define ATSE_WATCHDOG_TIME 5
-
-#ifdef DEVICE_POLLING
-static poll_handler_t atse_poll;
-#endif
-
/* XXX once we'd do parallel attach, we need a global lock for this. */
#define ATSE_ETHERNET_OPTION_BITS_UNDEF 0
#define ATSE_ETHERNET_OPTION_BITS_READ 1
static int atse_ethernet_option_bits_flag = ATSE_ETHERNET_OPTION_BITS_UNDEF;
static uint8_t atse_ethernet_option_bits[ALTERA_ETHERNET_OPTION_BITS_LEN];
-static int atse_intr_debug_enable = 0;
-SYSCTL_INT(_debug, OID_AUTO, atse_intr_debug_enable, CTLFLAG_RW,
- &atse_intr_debug_enable, 0,
- "Extra debugging output for atse interrupts");
-
/*
* Softc and critical resource locking.
*/
#define ATSE_LOCK(_sc) mtx_lock(&(_sc)->atse_mtx)
#define ATSE_UNLOCK(_sc) mtx_unlock(&(_sc)->atse_mtx)
#define ATSE_LOCK_ASSERT(_sc) mtx_assert(&(_sc)->atse_mtx, MA_OWNED)
-#define ATSE_TX_PENDING(sc) (sc->atse_tx_m != NULL || \
- !IFQ_DRV_IS_EMPTY(&ifp->if_snd))
+#define ATSE_DEBUG
+#undef ATSE_DEBUG
-#ifdef DEBUG
+#ifdef ATSE_DEBUG
#define DPRINTF(format, ...) printf(format, __VA_ARGS__)
#else
#define DPRINTF(format, ...)
#endif
-/* a_api.c functions; factor out? */
-static inline void
-a_onchip_fifo_mem_core_write(struct resource *res, uint32_t off,
- uint32_t val4, const char *desc, const char *f, const int l)
-{
-
- val4 = htole32(val4);
- DPRINTF("[%s:%d] FIFOW %s 0x%08x = 0x%08x\n", f, l, desc, off, val4);
- bus_write_4(res, off, val4);
-}
-
-static inline uint32_t
-a_onchip_fifo_mem_core_read(struct resource *res, uint32_t off,
- const char *desc, const char *f, const int l)
-{
- uint32_t val4;
-
- val4 = le32toh(bus_read_4(res, off));
- DPRINTF("[%s:%d] FIFOR %s 0x%08x = 0x%08x\n", f, l, desc, off, val4);
-
- return (val4);
-}
-
-/* The FIFO does an endian conversion, so we must not do it as well. */
-/* XXX-BZ in fact we should do a htobe32 so le would be fine as well? */
-#define ATSE_TX_DATA_WRITE(sc, val4) \
- bus_write_4((sc)->atse_tx_mem_res, A_ONCHIP_FIFO_MEM_CORE_DATA, val4)
-
-#define ATSE_TX_META_WRITE(sc, val4) \
- a_onchip_fifo_mem_core_write((sc)->atse_tx_mem_res, \
- A_ONCHIP_FIFO_MEM_CORE_METADATA, \
- (val4), "TXM", __func__, __LINE__)
-#define ATSE_TX_META_READ(sc) \
- a_onchip_fifo_mem_core_read((sc)->atse_tx_mem_res, \
- A_ONCHIP_FIFO_MEM_CORE_METADATA, \
- "TXM", __func__, __LINE__)
-
-#define ATSE_TX_READ_FILL_LEVEL(sc) \
- a_onchip_fifo_mem_core_read((sc)->atse_txc_mem_res, \
- A_ONCHIP_FIFO_MEM_CORE_STATUS_REG_FILL_LEVEL, \
- "TX_FILL", __func__, __LINE__)
-#define ATSE_RX_READ_FILL_LEVEL(sc) \
- a_onchip_fifo_mem_core_read((sc)->atse_rxc_mem_res, \
- A_ONCHIP_FIFO_MEM_CORE_STATUS_REG_FILL_LEVEL, \
- "RX_FILL", __func__, __LINE__)
-
-/* The FIFO does an endian conversion, so we must not do it as well. */
-/* XXX-BZ in fact we should do a htobe32 so le would be fine as well? */
-#define ATSE_RX_DATA_READ(sc) \
- bus_read_4((sc)->atse_rx_mem_res, A_ONCHIP_FIFO_MEM_CORE_DATA)
-#define ATSE_RX_META_READ(sc) \
- a_onchip_fifo_mem_core_read((sc)->atse_rx_mem_res, \
- A_ONCHIP_FIFO_MEM_CORE_METADATA, \
- "RXM", __func__, __LINE__)
-
-#define ATSE_RX_STATUS_READ(sc) \
- a_onchip_fifo_mem_core_read((sc)->atse_rxc_mem_res, \
- A_ONCHIP_FIFO_MEM_CORE_STATUS_REG_I_STATUS, \
- "RX_EVENT", __func__, __LINE__)
-
-#define ATSE_TX_STATUS_READ(sc) \
- a_onchip_fifo_mem_core_read((sc)->atse_txc_mem_res, \
- A_ONCHIP_FIFO_MEM_CORE_STATUS_REG_I_STATUS, \
- "TX_EVENT", __func__, __LINE__)
-
-#define ATSE_RX_EVENT_READ(sc) \
- a_onchip_fifo_mem_core_read((sc)->atse_rxc_mem_res, \
- A_ONCHIP_FIFO_MEM_CORE_STATUS_REG_EVENT, \
- "RX_EVENT", __func__, __LINE__)
-
-#define ATSE_TX_EVENT_READ(sc) \
- a_onchip_fifo_mem_core_read((sc)->atse_txc_mem_res, \
- A_ONCHIP_FIFO_MEM_CORE_STATUS_REG_EVENT, \
- "TX_EVENT", __func__, __LINE__)
-
-#define ATSE_RX_EVENT_CLEAR(sc) \
- do { \
- uint32_t val4; \
- \
- val4 = a_onchip_fifo_mem_core_read( \
- (sc)->atse_rxc_mem_res, \
- A_ONCHIP_FIFO_MEM_CORE_STATUS_REG_EVENT, \
- "RX_EVENT", __func__, __LINE__); \
- if (val4 != 0x00) \
- a_onchip_fifo_mem_core_write( \
- (sc)->atse_rxc_mem_res, \
- A_ONCHIP_FIFO_MEM_CORE_STATUS_REG_EVENT, \
- val4, "RX_EVENT", __func__, __LINE__); \
- } while(0)
-#define ATSE_TX_EVENT_CLEAR(sc) \
- do { \
- uint32_t val4; \
- \
- val4 = a_onchip_fifo_mem_core_read( \
- (sc)->atse_txc_mem_res, \
- A_ONCHIP_FIFO_MEM_CORE_STATUS_REG_EVENT, \
- "TX_EVENT", __func__, __LINE__); \
- if (val4 != 0x00) \
- a_onchip_fifo_mem_core_write( \
- (sc)->atse_txc_mem_res, \
- A_ONCHIP_FIFO_MEM_CORE_STATUS_REG_EVENT, \
- val4, "TX_EVENT", __func__, __LINE__); \
- } while(0)
-
-#define ATSE_RX_EVENTS (A_ONCHIP_FIFO_MEM_CORE_INTR_FULL | \
- A_ONCHIP_FIFO_MEM_CORE_INTR_OVERFLOW | \
- A_ONCHIP_FIFO_MEM_CORE_INTR_UNDERFLOW)
-#define ATSE_RX_INTR_ENABLE(sc) \
- a_onchip_fifo_mem_core_write((sc)->atse_rxc_mem_res, \
- A_ONCHIP_FIFO_MEM_CORE_STATUS_REG_INT_ENABLE, \
- ATSE_RX_EVENTS, \
- "RX_INTR", __func__, __LINE__) /* XXX-BZ review later. */
-#define ATSE_RX_INTR_DISABLE(sc) \
- a_onchip_fifo_mem_core_write((sc)->atse_rxc_mem_res, \
- A_ONCHIP_FIFO_MEM_CORE_STATUS_REG_INT_ENABLE, 0, \
- "RX_INTR", __func__, __LINE__)
-#define ATSE_RX_INTR_READ(sc) \
- a_onchip_fifo_mem_core_read((sc)->atse_rxc_mem_res, \
- A_ONCHIP_FIFO_MEM_CORE_STATUS_REG_INT_ENABLE, \
- "RX_INTR", __func__, __LINE__)
-
-#define ATSE_TX_EVENTS (A_ONCHIP_FIFO_MEM_CORE_INTR_EMPTY | \
- A_ONCHIP_FIFO_MEM_CORE_INTR_OVERFLOW | \
- A_ONCHIP_FIFO_MEM_CORE_INTR_UNDERFLOW)
-#define ATSE_TX_INTR_ENABLE(sc) \
- a_onchip_fifo_mem_core_write((sc)->atse_txc_mem_res, \
- A_ONCHIP_FIFO_MEM_CORE_STATUS_REG_INT_ENABLE, \
- ATSE_TX_EVENTS, \
- "TX_INTR", __func__, __LINE__) /* XXX-BZ review later. */
-#define ATSE_TX_INTR_DISABLE(sc) \
- a_onchip_fifo_mem_core_write((sc)->atse_txc_mem_res, \
- A_ONCHIP_FIFO_MEM_CORE_STATUS_REG_INT_ENABLE, 0, \
- "TX_INTR", __func__, __LINE__)
-#define ATSE_TX_INTR_READ(sc) \
- a_onchip_fifo_mem_core_read((sc)->atse_txc_mem_res, \
- A_ONCHIP_FIFO_MEM_CORE_STATUS_REG_INT_ENABLE, \
- "TX_INTR", __func__, __LINE__)
-
-static int atse_rx_locked(struct atse_softc *sc);
-
/*
* Register space access macros.
*/
static inline void
csr_write_4(struct atse_softc *sc, uint32_t reg, uint32_t val4,
const char *f, const int l)
{
val4 = htole32(val4);
DPRINTF("[%s:%d] CSR W %s 0x%08x (0x%08x) = 0x%08x\n", f, l,
"atse_mem_res", reg, reg * 4, val4);
bus_write_4(sc->atse_mem_res, reg * 4, val4);
}
static inline uint32_t
csr_read_4(struct atse_softc *sc, uint32_t reg, const char *f, const int l)
{
uint32_t val4;
val4 = le32toh(bus_read_4(sc->atse_mem_res, reg * 4));
DPRINTF("[%s:%d] CSR R %s 0x%08x (0x%08x) = 0x%08x\n", f, l,
"atse_mem_res", reg, reg * 4, val4);
return (val4);
}
/*
* See page 5-2 that it's all dword offsets and the MS 16 bits need to be zero
* on write and ignored on read.
*/
static inline void
pxx_write_2(struct atse_softc *sc, bus_addr_t bmcr, uint32_t reg, uint16_t val,
const char *f, const int l, const char *s)
{
uint32_t val4;
val4 = htole32(val & 0x0000ffff);
DPRINTF("[%s:%d] %s W %s 0x%08x (0x%08jx) = 0x%08x\n", f, l, s,
"atse_mem_res", reg, (bmcr + reg) * 4, val4);
bus_write_4(sc->atse_mem_res, (bmcr + reg) * 4, val4);
}
static inline uint16_t
pxx_read_2(struct atse_softc *sc, bus_addr_t bmcr, uint32_t reg, const char *f,
const int l, const char *s)
{
uint32_t val4;
uint16_t val;
val4 = bus_read_4(sc->atse_mem_res, (bmcr + reg) * 4);
val = le32toh(val4) & 0x0000ffff;
DPRINTF("[%s:%d] %s R %s 0x%08x (0x%08jx) = 0x%04x\n", f, l, s,
"atse_mem_res", reg, (bmcr + reg) * 4, val);
return (val);
}
#define CSR_WRITE_4(sc, reg, val) \
csr_write_4((sc), (reg), (val), __func__, __LINE__)
#define CSR_READ_4(sc, reg) \
csr_read_4((sc), (reg), __func__, __LINE__)
#define PCS_WRITE_2(sc, reg, val) \
pxx_write_2((sc), sc->atse_bmcr0, (reg), (val), __func__, __LINE__, \
"PCS")
#define PCS_READ_2(sc, reg) \
pxx_read_2((sc), sc->atse_bmcr0, (reg), __func__, __LINE__, "PCS")
#define PHY_WRITE_2(sc, reg, val) \
pxx_write_2((sc), sc->atse_bmcr1, (reg), (val), __func__, __LINE__, \
"PHY")
#define PHY_READ_2(sc, reg) \
pxx_read_2((sc), sc->atse_bmcr1, (reg), __func__, __LINE__, "PHY")
static void atse_tick(void *);
static int atse_detach(device_t);
devclass_t atse_devclass;
static int
-atse_tx_locked(struct atse_softc *sc, int *sent)
+atse_rx_enqueue(struct atse_softc *sc, uint32_t n)
{
struct mbuf *m;
- uint32_t val4, fill_level;
- int leftm;
- int c;
+ int i;
- ATSE_LOCK_ASSERT(sc);
+ for (i = 0; i < n; i++) {
+ m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
+ if (m == NULL) {
+ device_printf(sc->dev,
+ "%s: Can't alloc rx mbuf\n", __func__);
+ return (-1);
+ }
- m = sc->atse_tx_m;
- 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.
- */
- if (sc->atse_tx_m_offset == 0) {
- m_copydata(m, 0, m->m_pkthdr.len, sc->atse_tx_buf);
- sc->atse_tx_buf_len = m->m_pkthdr.len;
+ m->m_pkthdr.len = m->m_len = m->m_ext.ext_size;
+ xdma_enqueue_mbuf(sc->xchan_rx, &m, 0, 4, 4, XDMA_DEV_TO_MEM);
}
- fill_level = ATSE_TX_READ_FILL_LEVEL(sc);
-#if 0 /* Returns 0xdeadc0de. */
- val4 = ATSE_TX_META_READ(sc);
-#endif
- if (sc->atse_tx_m_offset == 0) {
- /* Write start of packet. */
- val4 = A_ONCHIP_FIFO_MEM_CORE_SOP;
- val4 &= ~A_ONCHIP_FIFO_MEM_CORE_EOP;
- ATSE_TX_META_WRITE(sc, val4);
+ return (0);
+}
+
+static int
+atse_xdma_tx_intr(void *arg, xdma_transfer_status_t *status)
+{
+ xdma_transfer_status_t st;
+ struct atse_softc *sc;
+ struct ifnet *ifp;
+ struct mbuf *m;
+ int err;
+
+ sc = arg;
+
+ ATSE_LOCK(sc);
+
+ ifp = sc->atse_ifp;
+
+ for (;;) {
+ err = xdma_dequeue_mbuf(sc->xchan_tx, &m, &st);
+ if (err != 0) {
+ break;
+ }
+
+ if (st.error != 0) {
+ if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
+ }
+
+ m_freem(m);
+ sc->txcount--;
}
- /* TX FIFO is single clock mode, so we have the full FIFO. */
- c = 0;
- while ((sc->atse_tx_buf_len - sc->atse_tx_m_offset) > 4 &&
- fill_level < AVALON_FIFO_TX_BASIC_OPTS_DEPTH) {
+ ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
- bcopy(&sc->atse_tx_buf[sc->atse_tx_m_offset], &val4,
- sizeof(val4));
- ATSE_TX_DATA_WRITE(sc, val4);
- sc->atse_tx_m_offset += sizeof(val4);
- c += sizeof(val4);
+ ATSE_UNLOCK(sc);
- fill_level++;
- if (fill_level == AVALON_FIFO_TX_BASIC_OPTS_DEPTH)
- fill_level = ATSE_TX_READ_FILL_LEVEL(sc);
+ return (0);
+}
+
+static int
+atse_xdma_rx_intr(void *arg, xdma_transfer_status_t *status)
+{
+ xdma_transfer_status_t st;
+ struct atse_softc *sc;
+ struct ifnet *ifp;
+ struct mbuf *m;
+ int err;
+ uint32_t cnt_processed;
+
+ sc = arg;
+
+ ATSE_LOCK(sc);
+
+ ifp = sc->atse_ifp;
+
+ cnt_processed = 0;
+ for (;;) {
+ err = xdma_dequeue_mbuf(sc->xchan_rx, &m, &st);
+ if (err != 0) {
+ break;
+ }
+ cnt_processed++;
+
+ if (st.error != 0) {
+ if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
+ m_freem(m);
+ continue;
+ }
+
+ m->m_pkthdr.len = m->m_len = st.transferred;
+ m->m_pkthdr.rcvif = ifp;
+ m_adj(m, ETHER_ALIGN);
+ ATSE_UNLOCK(sc);
+ (*ifp->if_input)(ifp, m);
+ ATSE_LOCK(sc);
}
- if (sent != NULL)
- *sent += c;
- /* Set EOP *before* writing the last symbol. */
- if (sc->atse_tx_m_offset >= (sc->atse_tx_buf_len - 4) &&
- fill_level < AVALON_FIFO_TX_BASIC_OPTS_DEPTH) {
+ atse_rx_enqueue(sc, cnt_processed);
- /* Set EndOfPacket. */
- val4 = A_ONCHIP_FIFO_MEM_CORE_EOP;
+ ATSE_UNLOCK(sc);
- /* Set EMPTY. */
- leftm = sc->atse_tx_buf_len - sc->atse_tx_m_offset;
- val4 |= ((4 - leftm) << A_ONCHIP_FIFO_MEM_CORE_EMPTY_SHIFT);
- ATSE_TX_META_WRITE(sc, val4);
+ return (0);
+}
- /* Write last symbol. */
- val4 = 0;
- bcopy(sc->atse_tx_buf + sc->atse_tx_m_offset, &val4, leftm);
- ATSE_TX_DATA_WRITE(sc, val4);
+static int
+atse_transmit_locked(struct ifnet *ifp)
+{
+ struct atse_softc *sc;
+ struct mbuf *m;
+ struct buf_ring *br;
+ int error;
+ int enq;
- if (sent != NULL)
- *sent += leftm;
+ sc = ifp->if_softc;
+ br = sc->br;
- /* OK, the packet is gone. */
- sc->atse_tx_m = NULL;
- sc->atse_tx_m_offset = 0;
+ enq = 0;
+ while ((m = drbr_peek(ifp, br)) != NULL) {
+ error = xdma_enqueue_mbuf(sc->xchan_tx, &m, 0, 4, 4, XDMA_MEM_TO_DEV);
+ if (error != 0) {
+ /* No space in request queue available yet. */
+ drbr_putback(ifp, br, m);
+ break;
+ }
+
+ drbr_advance(ifp, br);
+
+ sc->txcount++;
+ enq++;
+
/* If anyone is interested give them a copy. */
- BPF_MTAP(sc->atse_ifp, m);
+ ETHER_BPF_MTAP(ifp, m);
+ }
- m_freem(m);
- return (0);
- }
+ if (enq > 0)
+ xdma_queue_submit(sc->xchan_tx);
- return (EBUSY);
+ return (0);
}
-static void
-atse_start_locked(struct ifnet *ifp)
+static int
+atse_transmit(struct ifnet *ifp, struct mbuf *m)
{
struct atse_softc *sc;
- int error, sent;
+ struct buf_ring *br;
+ int error;
sc = ifp->if_softc;
- ATSE_LOCK_ASSERT(sc);
+ br = sc->br;
- if ((ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) !=
- IFF_DRV_RUNNING || (sc->atse_flags & ATSE_FLAGS_LINK) == 0)
- return;
+ ATSE_LOCK(sc);
-#if 1
- /*
- * 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->atse_watchdog_timer = 0;
-#endif
+ mtx_lock(&sc->br_mtx);
- if (sc->atse_tx_m != NULL) {
- error = atse_tx_locked(sc, &sent);
- if (error != 0)
- goto done;
+ if ((ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) != IFF_DRV_RUNNING) {
+ error = drbr_enqueue(ifp, sc->br, m);
+ mtx_unlock(&sc->br_mtx);
+ ATSE_UNLOCK(sc);
+ return (error);
}
- /* We have more space to send so continue ... */
- for (; !IFQ_DRV_IS_EMPTY(&ifp->if_snd); ) {
- IFQ_DRV_DEQUEUE(&ifp->if_snd, sc->atse_tx_m);
- sc->atse_tx_m_offset = 0;
- if (sc->atse_tx_m == NULL)
- break;
- error = atse_tx_locked(sc, &sent);
- if (error != 0)
- goto done;
+ if ((sc->atse_flags & ATSE_FLAGS_LINK) == 0) {
+ error = drbr_enqueue(ifp, sc->br, m);
+ mtx_unlock(&sc->br_mtx);
+ ATSE_UNLOCK(sc);
+ return (error);
}
-done:
- /* If the IP core walks into Nekromanteion try to bail out. */
- if (sent > 0)
- sc->atse_watchdog_timer = ATSE_WATCHDOG_TIME;
+ error = drbr_enqueue(ifp, br, m);
+ if (error) {
+ mtx_unlock(&sc->br_mtx);
+ ATSE_UNLOCK(sc);
+ return (error);
+ }
+ error = atse_transmit_locked(ifp);
+
+ mtx_unlock(&sc->br_mtx);
+ ATSE_UNLOCK(sc);
+
+ return (error);
}
static void
-atse_start(struct ifnet *ifp)
+atse_qflush(struct ifnet *ifp)
{
struct atse_softc *sc;
sc = ifp->if_softc;
- ATSE_LOCK(sc);
- atse_start_locked(ifp);
- ATSE_UNLOCK(sc);
+
+ printf("%s\n", __func__);
}
static int
atse_stop_locked(struct atse_softc *sc)
{
uint32_t mask, val4;
struct ifnet *ifp;
int i;
ATSE_LOCK_ASSERT(sc);
- sc->atse_watchdog_timer = 0;
callout_stop(&sc->atse_tick);
ifp = sc->atse_ifp;
ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
- ATSE_RX_INTR_DISABLE(sc);
- ATSE_TX_INTR_DISABLE(sc);
- ATSE_RX_EVENT_CLEAR(sc);
- ATSE_TX_EVENT_CLEAR(sc);
/* Disable MAC transmit and receive datapath. */
mask = BASE_CFG_COMMAND_CONFIG_TX_ENA|BASE_CFG_COMMAND_CONFIG_RX_ENA;
val4 = CSR_READ_4(sc, BASE_CFG_COMMAND_CONFIG);
val4 &= ~mask;
CSR_WRITE_4(sc, BASE_CFG_COMMAND_CONFIG, val4);
+
/* Wait for bits to be cleared; i=100 is excessive. */
for (i = 0; i < 100; i++) {
val4 = CSR_READ_4(sc, BASE_CFG_COMMAND_CONFIG);
- if ((val4 & mask) == 0)
+ if ((val4 & mask) == 0) {
break;
+ }
DELAY(10);
}
- if ((val4 & mask) != 0)
+
+ if ((val4 & mask) != 0) {
device_printf(sc->atse_dev, "Disabling MAC TX/RX timed out.\n");
/* Punt. */
+ }
sc->atse_flags &= ~ATSE_FLAGS_LINK;
- /* XXX-BZ free the RX/TX rings. */
-
return (0);
}
static uint8_t
atse_mchash(struct atse_softc *sc __unused, const uint8_t *addr)
{
uint8_t x, y;
int i, j;
x = 0;
for (i = 0; i < ETHER_ADDR_LEN; i++) {
y = addr[i] & 0x01;
for (j = 1; j < 8; j++)
y ^= (addr[i] >> j) & 0x01;
x |= (y << i);
}
return (x);
}
static int
atse_rxfilter_locked(struct atse_softc *sc)
{
struct ifmultiaddr *ifma;
struct ifnet *ifp;
uint32_t val4;
int i;
/* XXX-BZ can we find out if we have the MHASH synthesized? */
val4 = CSR_READ_4(sc, BASE_CFG_COMMAND_CONFIG);
/* For simplicity always hash full 48 bits of addresses. */
if ((val4 & BASE_CFG_COMMAND_CONFIG_MHASH_SEL) != 0)
val4 &= ~BASE_CFG_COMMAND_CONFIG_MHASH_SEL;
ifp = sc->atse_ifp;
- if (ifp->if_flags & IFF_PROMISC)
+ if (ifp->if_flags & IFF_PROMISC) {
val4 |= BASE_CFG_COMMAND_CONFIG_PROMIS_EN;
- else
+ } else {
val4 &= ~BASE_CFG_COMMAND_CONFIG_PROMIS_EN;
+ }
CSR_WRITE_4(sc, BASE_CFG_COMMAND_CONFIG, val4);
if (ifp->if_flags & IFF_ALLMULTI) {
/* Accept all multicast addresses. */
for (i = 0; i <= MHASH_LEN; i++)
CSR_WRITE_4(sc, MHASH_START + i, 0x1);
} else {
/*
* Can hold MHASH_LEN entries.
* XXX-BZ bitstring.h would be more general.
*/
uint64_t h;
h = 0;
/*
* Re-build and re-program hash table. First build the
* bit-field "yes" or "no" for each slot per address, then
* do all the programming afterwards.
*/
if_maddr_rlock(ifp);
TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
- if (ifma->ifma_addr->sa_family != AF_LINK)
+ if (ifma->ifma_addr->sa_family != AF_LINK) {
continue;
+ }
h |= (1 << atse_mchash(sc,
LLADDR((struct sockaddr_dl *)ifma->ifma_addr)));
}
if_maddr_runlock(ifp);
- for (i = 0; i <= MHASH_LEN; i++)
+ for (i = 0; i <= MHASH_LEN; i++) {
CSR_WRITE_4(sc, MHASH_START + i,
(h & (1 << i)) ? 0x01 : 0x00);
+ }
}
return (0);
}
static int
atse_ethernet_option_bits_read_fdt(device_t dev)
{
struct resource *res;
device_t fdev;
int i, rid;
- if (atse_ethernet_option_bits_flag & ATSE_ETHERNET_OPTION_BITS_READ)
+ if (atse_ethernet_option_bits_flag & ATSE_ETHERNET_OPTION_BITS_READ) {
return (0);
+ }
fdev = device_find_child(device_get_parent(dev), "cfi", 0);
- if (fdev == NULL)
+ if (fdev == NULL) {
return (ENOENT);
+ }
rid = 0;
res = bus_alloc_resource_any(fdev, SYS_RES_MEMORY, &rid,
RF_ACTIVE | RF_SHAREABLE);
- if (res == NULL)
+ if (res == NULL) {
return (ENXIO);
+ }
- for (i = 0; i < ALTERA_ETHERNET_OPTION_BITS_LEN; i++)
+ for (i = 0; i < ALTERA_ETHERNET_OPTION_BITS_LEN; i++) {
atse_ethernet_option_bits[i] = bus_read_1(res,
ALTERA_ETHERNET_OPTION_BITS_OFF + i);
+ }
bus_release_resource(fdev, SYS_RES_MEMORY, rid, res);
atse_ethernet_option_bits_flag |= ATSE_ETHERNET_OPTION_BITS_READ;
return (0);
}
static int
atse_ethernet_option_bits_read(device_t dev)
{
int error;
error = atse_ethernet_option_bits_read_fdt(dev);
if (error == 0)
return (0);
device_printf(dev, "Cannot read Ethernet addresses from flash.\n");
return (error);
}
static int
atse_get_eth_address(struct atse_softc *sc)
{
unsigned long hostid;
uint32_t val4;
int unit;
/*
* Make sure to only ever do this once. Otherwise a reset would
* possibly change our ethernet address, which is not good at all.
*/
if (sc->atse_eth_addr[0] != 0x00 || sc->atse_eth_addr[1] != 0x00 ||
- sc->atse_eth_addr[2] != 0x00)
+ sc->atse_eth_addr[2] != 0x00) {
return (0);
+ }
if ((atse_ethernet_option_bits_flag &
- ATSE_ETHERNET_OPTION_BITS_READ) == 0)
+ ATSE_ETHERNET_OPTION_BITS_READ) == 0) {
goto get_random;
+ }
val4 = atse_ethernet_option_bits[0] << 24;
val4 |= atse_ethernet_option_bits[1] << 16;
val4 |= atse_ethernet_option_bits[2] << 8;
val4 |= atse_ethernet_option_bits[3];
/* They chose "safe". */
if (val4 != le32toh(0x00005afe)) {
device_printf(sc->atse_dev, "Magic '5afe' is not safe: 0x%08x. "
"Falling back to random numbers for hardware address.\n",
val4);
goto get_random;
}
sc->atse_eth_addr[0] = atse_ethernet_option_bits[4];
sc->atse_eth_addr[1] = atse_ethernet_option_bits[5];
sc->atse_eth_addr[2] = atse_ethernet_option_bits[6];
sc->atse_eth_addr[3] = atse_ethernet_option_bits[7];
sc->atse_eth_addr[4] = atse_ethernet_option_bits[8];
sc->atse_eth_addr[5] = atse_ethernet_option_bits[9];
/* Handle factory default ethernet addresss: 00:07:ed:ff:ed:15 */
if (sc->atse_eth_addr[0] == 0x00 && sc->atse_eth_addr[1] == 0x07 &&
sc->atse_eth_addr[2] == 0xed && sc->atse_eth_addr[3] == 0xff &&
sc->atse_eth_addr[4] == 0xed && sc->atse_eth_addr[5] == 0x15) {
device_printf(sc->atse_dev, "Factory programmed Ethernet "
"hardware address blacklisted. Falling back to random "
"address to avoid collisions.\n");
device_printf(sc->atse_dev, "Please re-program your flash.\n");
goto get_random;
}
if (sc->atse_eth_addr[0] == 0x00 && sc->atse_eth_addr[1] == 0x00 &&
sc->atse_eth_addr[2] == 0x00 && sc->atse_eth_addr[3] == 0x00 &&
sc->atse_eth_addr[4] == 0x00 && sc->atse_eth_addr[5] == 0x00) {
device_printf(sc->atse_dev, "All zero's Ethernet hardware "
"address blacklisted. Falling back to random address.\n");
device_printf(sc->atse_dev, "Please re-program your flash.\n");
goto get_random;
}
if (ETHER_IS_MULTICAST(sc->atse_eth_addr)) {
device_printf(sc->atse_dev, "Multicast Ethernet hardware "
"address blacklisted. Falling back to random address.\n");
device_printf(sc->atse_dev, "Please re-program your flash.\n");
goto get_random;
}
/*
* If we find an Altera prefixed address with a 0x0 ending
* adjust by device unit. If not and this is not the first
* Ethernet, go to random.
*/
unit = device_get_unit(sc->atse_dev);
- if (unit == 0x00)
+ if (unit == 0x00) {
return (0);
+ }
if (unit > 0x0f) {
device_printf(sc->atse_dev, "We do not support Ethernet "
"addresses for more than 16 MACs. Falling back to "
"random hadware address.\n");
goto get_random;
}
if ((sc->atse_eth_addr[0] & ~0x2) != 0 ||
sc->atse_eth_addr[1] != 0x07 || sc->atse_eth_addr[2] != 0xed ||
(sc->atse_eth_addr[5] & 0x0f) != 0x0) {
device_printf(sc->atse_dev, "Ethernet address not meeting our "
"multi-MAC standards. Falling back to random hadware "
"address.\n");
goto get_random;
}
sc->atse_eth_addr[5] |= (unit & 0x0f);
return (0);
get_random:
/*
* Fall back to random code we also use on bridge(4).
*/
getcredhostid(curthread->td_ucred, &hostid);
if (hostid == 0) {
arc4rand(sc->atse_eth_addr, ETHER_ADDR_LEN, 1);
sc->atse_eth_addr[0] &= ~1;/* clear multicast bit */
sc->atse_eth_addr[0] |= 2; /* set the LAA bit */
} else {
sc->atse_eth_addr[0] = 0x2;
sc->atse_eth_addr[1] = (hostid >> 24) & 0xff;
sc->atse_eth_addr[2] = (hostid >> 16) & 0xff;
sc->atse_eth_addr[3] = (hostid >> 8 ) & 0xff;
sc->atse_eth_addr[4] = hostid & 0xff;
sc->atse_eth_addr[5] = sc->atse_unit & 0xff;
}
return (0);
}
static int
atse_set_eth_address(struct atse_softc *sc, int n)
{
uint32_t v0, v1;
v0 = (sc->atse_eth_addr[3] << 24) | (sc->atse_eth_addr[2] << 16) |
(sc->atse_eth_addr[1] << 8) | sc->atse_eth_addr[0];
v1 = (sc->atse_eth_addr[5] << 8) | sc->atse_eth_addr[4];
if (n & ATSE_ETH_ADDR_DEF) {
CSR_WRITE_4(sc, BASE_CFG_MAC_0, v0);
CSR_WRITE_4(sc, BASE_CFG_MAC_1, v1);
}
if (n & ATSE_ETH_ADDR_SUPP1) {
CSR_WRITE_4(sc, SUPPL_ADDR_SMAC_0_0, v0);
CSR_WRITE_4(sc, SUPPL_ADDR_SMAC_0_1, v1);
}
if (n & ATSE_ETH_ADDR_SUPP2) {
CSR_WRITE_4(sc, SUPPL_ADDR_SMAC_1_0, v0);
CSR_WRITE_4(sc, SUPPL_ADDR_SMAC_1_1, v1);
}
if (n & ATSE_ETH_ADDR_SUPP3) {
CSR_WRITE_4(sc, SUPPL_ADDR_SMAC_2_0, v0);
CSR_WRITE_4(sc, SUPPL_ADDR_SMAC_2_1, v1);
}
if (n & ATSE_ETH_ADDR_SUPP4) {
CSR_WRITE_4(sc, SUPPL_ADDR_SMAC_3_0, v0);
CSR_WRITE_4(sc, SUPPL_ADDR_SMAC_3_1, v1);
}
return (0);
}
static int
atse_reset(struct atse_softc *sc)
{
uint32_t val4, mask;
uint16_t val;
int i;
/* 1. External PHY Initialization using MDIO. */
/*
* We select the right MDIO space in atse_attach() and let MII do
* anything else.
*/
/* 2. PCS Configuration Register Initialization. */
/* a. Set auto negotiation link timer to 1.6ms for SGMII. */
PCS_WRITE_2(sc, PCS_EXT_LINK_TIMER_0, 0x0D40);
PCS_WRITE_2(sc, PCS_EXT_LINK_TIMER_1, 0x0003);
/* b. Configure SGMII. */
val = PCS_EXT_IF_MODE_SGMII_ENA|PCS_EXT_IF_MODE_USE_SGMII_AN;
PCS_WRITE_2(sc, PCS_EXT_IF_MODE, val);
/* c. Enable auto negotiation. */
/* Ignore Bits 6,8,13; should be set,set,unset. */
val = PCS_READ_2(sc, PCS_CONTROL);
val &= ~(PCS_CONTROL_ISOLATE|PCS_CONTROL_POWERDOWN);
val &= ~PCS_CONTROL_LOOPBACK; /* Make this a -link1 option? */
val |= PCS_CONTROL_AUTO_NEGOTIATION_ENABLE;
PCS_WRITE_2(sc, PCS_CONTROL, val);
/* d. PCS reset. */
val = PCS_READ_2(sc, PCS_CONTROL);
val |= PCS_CONTROL_RESET;
PCS_WRITE_2(sc, PCS_CONTROL, val);
/* Wait for reset bit to clear; i=100 is excessive. */
for (i = 0; i < 100; i++) {
val = PCS_READ_2(sc, PCS_CONTROL);
- if ((val & PCS_CONTROL_RESET) == 0)
+ if ((val & PCS_CONTROL_RESET) == 0) {
break;
+ }
DELAY(10);
}
if ((val & PCS_CONTROL_RESET) != 0) {
device_printf(sc->atse_dev, "PCS reset timed out.\n");
return (ENXIO);
}
/* 3. MAC Configuration Register Initialization. */
/* a. Disable MAC transmit and receive datapath. */
mask = BASE_CFG_COMMAND_CONFIG_TX_ENA|BASE_CFG_COMMAND_CONFIG_RX_ENA;
val4 = CSR_READ_4(sc, BASE_CFG_COMMAND_CONFIG);
val4 &= ~mask;
/* Samples in the manual do have the SW_RESET bit set here, why? */
CSR_WRITE_4(sc, BASE_CFG_COMMAND_CONFIG, val4);
/* Wait for bits to be cleared; i=100 is excessive. */
for (i = 0; i < 100; i++) {
val4 = CSR_READ_4(sc, BASE_CFG_COMMAND_CONFIG);
- if ((val4 & mask) == 0)
+ if ((val4 & mask) == 0) {
break;
+ }
DELAY(10);
}
if ((val4 & mask) != 0) {
device_printf(sc->atse_dev, "Disabling MAC TX/RX timed out.\n");
return (ENXIO);
}
/* b. MAC FIFO configuration. */
CSR_WRITE_4(sc, BASE_CFG_TX_SECTION_EMPTY, FIFO_DEPTH_TX - 16);
CSR_WRITE_4(sc, BASE_CFG_TX_ALMOST_FULL, 3);
CSR_WRITE_4(sc, BASE_CFG_TX_ALMOST_EMPTY, 8);
CSR_WRITE_4(sc, BASE_CFG_RX_SECTION_EMPTY, FIFO_DEPTH_RX - 16);
CSR_WRITE_4(sc, BASE_CFG_RX_ALMOST_FULL, 8);
CSR_WRITE_4(sc, BASE_CFG_RX_ALMOST_EMPTY, 8);
#if 0
CSR_WRITE_4(sc, BASE_CFG_TX_SECTION_FULL, 16);
CSR_WRITE_4(sc, BASE_CFG_RX_SECTION_FULL, 16);
#else
/* For store-and-forward mode, set this threshold to 0. */
CSR_WRITE_4(sc, BASE_CFG_TX_SECTION_FULL, 0);
CSR_WRITE_4(sc, BASE_CFG_RX_SECTION_FULL, 0);
#endif
/* c. MAC address configuration. */
/* Also intialize supplementary addresses to our primary one. */
/* XXX-BZ FreeBSD really needs to grow and API for using these. */
atse_get_eth_address(sc);
atse_set_eth_address(sc, ATSE_ETH_ADDR_ALL);
/* d. MAC function configuration. */
CSR_WRITE_4(sc, BASE_CFG_FRM_LENGTH, 1518); /* Default. */
CSR_WRITE_4(sc, BASE_CFG_TX_IPG_LENGTH, 12);
CSR_WRITE_4(sc, BASE_CFG_PAUSE_QUANT, 0xFFFF);
val4 = CSR_READ_4(sc, BASE_CFG_COMMAND_CONFIG);
/*
* If 1000BASE-X/SGMII PCS is initialized, set the ETH_SPEED (bit 3)
* and ENA_10 (bit 25) in command_config register to 0. If half duplex
* is reported in the PHY/PCS status register, set the HD_ENA (bit 10)
* to 1 in command_config register.
* BZ: We shoot for 1000 instead.
*/
#if 0
val4 |= BASE_CFG_COMMAND_CONFIG_ETH_SPEED;
#else
val4 &= ~BASE_CFG_COMMAND_CONFIG_ETH_SPEED;
#endif
val4 &= ~BASE_CFG_COMMAND_CONFIG_ENA_10;
#if 0
/*
* We do not want to set this, otherwise, we could not even send
* random raw ethernet frames for various other research. By default
* FreeBSD will use the right ether source address.
*/
val4 |= BASE_CFG_COMMAND_CONFIG_TX_ADDR_INS;
#endif
val4 |= BASE_CFG_COMMAND_CONFIG_PAD_EN;
val4 &= ~BASE_CFG_COMMAND_CONFIG_CRC_FWD;
#if 0
val4 |= BASE_CFG_COMMAND_CONFIG_CNTL_FRM_ENA;
#endif
#if 1
val4 |= BASE_CFG_COMMAND_CONFIG_RX_ERR_DISC;
#endif
val &= ~BASE_CFG_COMMAND_CONFIG_LOOP_ENA; /* link0? */
CSR_WRITE_4(sc, BASE_CFG_COMMAND_CONFIG, val4);
/*
* Make sure we do not enable 32bit alignment; FreeBSD cannot
* cope with the additional padding (though we should!?).
* Also make sure we get the CRC appended.
*/
val4 = CSR_READ_4(sc, TX_CMD_STAT);
val4 &= ~(TX_CMD_STAT_OMIT_CRC|TX_CMD_STAT_TX_SHIFT16);
CSR_WRITE_4(sc, TX_CMD_STAT, val4);
+
val4 = CSR_READ_4(sc, RX_CMD_STAT);
val4 &= ~RX_CMD_STAT_RX_SHIFT16;
+ val4 |= RX_CMD_STAT_RX_SHIFT16;
CSR_WRITE_4(sc, RX_CMD_STAT, val4);
/* e. Reset MAC. */
val4 = CSR_READ_4(sc, BASE_CFG_COMMAND_CONFIG);
val4 |= BASE_CFG_COMMAND_CONFIG_SW_RESET;
CSR_WRITE_4(sc, BASE_CFG_COMMAND_CONFIG, val4);
/* Wait for bits to be cleared; i=100 is excessive. */
for (i = 0; i < 100; i++) {
val4 = CSR_READ_4(sc, BASE_CFG_COMMAND_CONFIG);
- if ((val4 & BASE_CFG_COMMAND_CONFIG_SW_RESET) == 0)
+ if ((val4 & BASE_CFG_COMMAND_CONFIG_SW_RESET) == 0) {
break;
+ }
DELAY(10);
}
if ((val4 & BASE_CFG_COMMAND_CONFIG_SW_RESET) != 0) {
device_printf(sc->atse_dev, "MAC reset timed out.\n");
return (ENXIO);
}
/* f. Enable MAC transmit and receive datapath. */
mask = BASE_CFG_COMMAND_CONFIG_TX_ENA|BASE_CFG_COMMAND_CONFIG_RX_ENA;
val4 = CSR_READ_4(sc, BASE_CFG_COMMAND_CONFIG);
val4 |= mask;
CSR_WRITE_4(sc, BASE_CFG_COMMAND_CONFIG, val4);
/* Wait for bits to be cleared; i=100 is excessive. */
for (i = 0; i < 100; i++) {
val4 = CSR_READ_4(sc, BASE_CFG_COMMAND_CONFIG);
- if ((val4 & mask) == mask)
+ if ((val4 & mask) == mask) {
break;
+ }
DELAY(10);
}
if ((val4 & mask) != mask) {
device_printf(sc->atse_dev, "Enabling MAC TX/RX timed out.\n");
return (ENXIO);
}
return (0);
}
static void
atse_init_locked(struct atse_softc *sc)
{
struct ifnet *ifp;
struct mii_data *mii;
uint8_t *eaddr;
ATSE_LOCK_ASSERT(sc);
ifp = sc->atse_ifp;
- if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0)
+ if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) {
return;
+ }
/*
* Must update the ether address if changed. Given we do not handle
* in atse_ioctl() but it's in the general framework, just always
* do it here before atse_reset().
*/
eaddr = IF_LLADDR(sc->atse_ifp);
bcopy(eaddr, &sc->atse_eth_addr, ETHER_ADDR_LEN);
/* Make things frind to halt, cleanup, ... */
atse_stop_locked(sc);
- /* ... reset, ... */
+
atse_reset(sc);
/* ... and fire up the engine again. */
atse_rxfilter_locked(sc);
- /* Memory rings? DMA engine? */
-
- sc->atse_rx_buf_len = 0;
sc->atse_flags &= ATSE_FLAGS_LINK; /* Preserve. */
-#ifdef DEVICE_POLLING
- /* Only enable interrupts if we are not polling. */
- if (ifp->if_capenable & IFCAP_POLLING) {
- ATSE_RX_INTR_DISABLE(sc);
- ATSE_TX_INTR_DISABLE(sc);
- ATSE_RX_EVENT_CLEAR(sc);
- ATSE_TX_EVENT_CLEAR(sc);
- } else
-#endif
- {
- ATSE_RX_INTR_ENABLE(sc);
- ATSE_TX_INTR_ENABLE(sc);
- }
-
mii = device_get_softc(sc->atse_miibus);
sc->atse_flags &= ~ATSE_FLAGS_LINK;
mii_mediachg(mii);
ifp->if_drv_flags |= IFF_DRV_RUNNING;
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
callout_reset(&sc->atse_tick, hz, atse_tick, sc);
}
static void
atse_init(void *xsc)
{
struct atse_softc *sc;
/*
* XXXRW: There is some argument that we should immediately do RX
* processing after enabling interrupts, or one may not fire if there
* are buffered packets.
*/
sc = (struct atse_softc *)xsc;
ATSE_LOCK(sc);
atse_init_locked(sc);
ATSE_UNLOCK(sc);
}
static int
atse_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
{
struct atse_softc *sc;
struct ifreq *ifr;
int error, mask;
error = 0;
sc = ifp->if_softc;
ifr = (struct ifreq *)data;
switch (command) {
case SIOCSIFFLAGS:
ATSE_LOCK(sc);
if (ifp->if_flags & IFF_UP) {
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0 &&
((ifp->if_flags ^ sc->atse_if_flags) &
(IFF_PROMISC | IFF_ALLMULTI)) != 0)
atse_rxfilter_locked(sc);
else
atse_init_locked(sc);
} else if (ifp->if_drv_flags & IFF_DRV_RUNNING)
atse_stop_locked(sc);
sc->atse_if_flags = ifp->if_flags;
ATSE_UNLOCK(sc);
break;
case SIOCSIFCAP:
ATSE_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(atse_poll, ifp);
- if (error != 0) {
- ATSE_UNLOCK(sc);
- break;
- }
- /* Disable interrupts. */
- ATSE_RX_INTR_DISABLE(sc);
- ATSE_TX_INTR_DISABLE(sc);
- ATSE_RX_EVENT_CLEAR(sc);
- ATSE_TX_EVENT_CLEAR(sc);
-
- /*
- * Do not allow disabling of polling if we do
- * not have interrupts.
- */
- } else if (sc->atse_rx_irq_res != NULL ||
- sc->atse_tx_irq_res != NULL) {
- error = ether_poll_deregister(ifp);
- /* Enable interrupts. */
- ATSE_RX_INTR_ENABLE(sc);
- ATSE_TX_INTR_ENABLE(sc);
- } else {
- ifp->if_capenable ^= IFCAP_POLLING;
- error = EINVAL;
- }
- }
-#endif /* DEVICE_POLLING */
ATSE_UNLOCK(sc);
break;
case SIOCADDMULTI:
case SIOCDELMULTI:
ATSE_LOCK(sc);
atse_rxfilter_locked(sc);
ATSE_UNLOCK(sc);
break;
case SIOCGIFMEDIA:
case SIOCSIFMEDIA:
{
struct mii_data *mii;
struct ifreq *ifr;
mii = device_get_softc(sc->atse_miibus);
ifr = (struct ifreq *)data;
error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, command);
break;
}
default:
error = ether_ioctl(ifp, command, data);
break;
}
return (error);
}
static void
-atse_intr_debug(struct atse_softc *sc, const char *intrname)
-{
- uint32_t rxs, rxe, rxi, rxf, txs, txe, txi, txf;
-
- if (!atse_intr_debug_enable)
- return;
-
- rxs = ATSE_RX_STATUS_READ(sc);
- rxe = ATSE_RX_EVENT_READ(sc);
- rxi = ATSE_RX_INTR_READ(sc);
- rxf = ATSE_RX_READ_FILL_LEVEL(sc);
-
- txs = ATSE_TX_STATUS_READ(sc);
- txe = ATSE_TX_EVENT_READ(sc);
- txi = ATSE_TX_INTR_READ(sc);
- txf = ATSE_TX_READ_FILL_LEVEL(sc);
-
- printf(
- "%s - %s: "
- "rxs 0x%x rxe 0x%x rxi 0x%x rxf 0x%x "
- "txs 0x%x txe 0x%x txi 0x%x txf 0x%x\n",
- __func__, intrname,
- rxs, rxe, rxi, rxf,
- txs, txe, txi, txf);
-}
-
-static void
-atse_watchdog(struct atse_softc *sc)
-{
-
- ATSE_LOCK_ASSERT(sc);
-
- if (sc->atse_watchdog_timer == 0 || --sc->atse_watchdog_timer > 0)
- return;
-
- device_printf(sc->atse_dev, "watchdog timeout\n");
- if_inc_counter(sc->atse_ifp, IFCOUNTER_OERRORS, 1);
-
- atse_intr_debug(sc, "poll");
-
- sc->atse_ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
- atse_init_locked(sc);
-
- atse_rx_locked(sc);
- if (!IFQ_DRV_IS_EMPTY(&sc->atse_ifp->if_snd))
- atse_start_locked(sc->atse_ifp);
-}
-
-static void
atse_tick(void *xsc)
{
struct atse_softc *sc;
struct mii_data *mii;
struct ifnet *ifp;
sc = (struct atse_softc *)xsc;
ATSE_LOCK_ASSERT(sc);
ifp = sc->atse_ifp;
mii = device_get_softc(sc->atse_miibus);
mii_tick(mii);
- atse_watchdog(sc);
- if ((sc->atse_flags & ATSE_FLAGS_LINK) == 0)
+ if ((sc->atse_flags & ATSE_FLAGS_LINK) == 0) {
atse_miibus_statchg(sc->atse_dev);
+ }
+
callout_reset(&sc->atse_tick, hz, atse_tick, sc);
}
/*
* Set media options.
*/
static int
atse_ifmedia_upd(struct ifnet *ifp)
{
struct atse_softc *sc;
struct mii_data *mii;
struct mii_softc *miisc;
int error;
sc = ifp->if_softc;
ATSE_LOCK(sc);
mii = device_get_softc(sc->atse_miibus);
- LIST_FOREACH(miisc, &mii->mii_phys, mii_list)
+ LIST_FOREACH(miisc, &mii->mii_phys, mii_list) {
PHY_RESET(miisc);
+ }
error = mii_mediachg(mii);
ATSE_UNLOCK(sc);
return (error);
}
-static void
-atse_update_rx_err(struct atse_softc *sc, uint32_t mask)
-{
- int i;
-
- /* RX error are 6 bits, we only know 4 of them. */
- for (i = 0; i < ATSE_RX_ERR_MAX; i++)
- if ((mask & (1 << i)) != 0)
- sc->atse_rx_err[i]++;
-}
-
-static int
-atse_rx_locked(struct atse_softc *sc)
-{
- uint32_t fill, i, j;
- uint32_t data, meta;
- struct ifnet *ifp;
- struct mbuf *m;
- int rx_npkts;
-
- ATSE_LOCK_ASSERT(sc);
-
- ifp = sc->atse_ifp;
- rx_npkts = 0;
- j = 0;
- meta = 0;
- do {
-outer:
- if (sc->atse_rx_m == NULL) {
- m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
- if (m == NULL)
- return (rx_npkts);
- m->m_len = m->m_pkthdr.len = MCLBYTES;
- /* Make sure upper layers will be aligned. */
- m_adj(m, ETHER_ALIGN);
- sc->atse_rx_m = m;
- }
-
- fill = ATSE_RX_READ_FILL_LEVEL(sc);
- for (i = 0; i < fill; i++) {
- /*
- * XXX-BZ for whatever reason the FIFO requires the
- * the data read before we can access the meta data.
- */
- data = ATSE_RX_DATA_READ(sc);
- meta = ATSE_RX_META_READ(sc);
- if (meta & A_ONCHIP_FIFO_MEM_CORE_ERROR_MASK) {
- /* XXX-BZ evaluate error. */
- atse_update_rx_err(sc, ((meta &
- A_ONCHIP_FIFO_MEM_CORE_ERROR_MASK) >>
- A_ONCHIP_FIFO_MEM_CORE_ERROR_SHIFT) & 0xff);
- if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
- sc->atse_rx_buf_len = 0;
- /*
- * Should still read till EOP or next SOP.
- *
- * XXX-BZ might also depend on
- * BASE_CFG_COMMAND_CONFIG_RX_ERR_DISC
- */
- sc->atse_flags |= ATSE_FLAGS_ERROR;
- return (rx_npkts);
- }
- if ((meta & A_ONCHIP_FIFO_MEM_CORE_CHANNEL_MASK) != 0)
- device_printf(sc->atse_dev, "%s: unexpected "
- "channel %u\n", __func__, (meta &
- A_ONCHIP_FIFO_MEM_CORE_CHANNEL_MASK) >>
- A_ONCHIP_FIFO_MEM_CORE_CHANNEL_SHIFT);
-
- if (meta & A_ONCHIP_FIFO_MEM_CORE_SOP) {
- /*
- * There is no need to clear SOP between 1st
- * and subsequent packet data junks.
- */
- if (sc->atse_rx_buf_len != 0 &&
- (sc->atse_flags & ATSE_FLAGS_SOP_SEEN) == 0)
- {
- device_printf(sc->atse_dev, "%s: SOP "
- "without empty buffer: %u\n",
- __func__, sc->atse_rx_buf_len);
- /* XXX-BZ any better counter? */
- if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
- }
-
- if ((sc->atse_flags & ATSE_FLAGS_SOP_SEEN) == 0)
- {
- sc->atse_flags |= ATSE_FLAGS_SOP_SEEN;
- sc->atse_rx_buf_len = 0;
- }
- }
-#if 0 /* We had to read the data before we could access meta data. See above. */
- data = ATSE_RX_DATA_READ(sc);
-#endif
- /* Make sure to not overflow the mbuf data size. */
- if (sc->atse_rx_buf_len >= sc->atse_rx_m->m_len -
- sizeof(data)) {
- /*
- * XXX-BZ Error. We need more mbufs and are
- * not setup for this yet.
- */
- if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
- sc->atse_flags |= ATSE_FLAGS_ERROR;
- }
- if ((sc->atse_flags & ATSE_FLAGS_ERROR) == 0)
- /*
- * MUST keep this bcopy as m_data after m_adj
- * for IP header aligment is on half-word
- * and not word alignment.
- */
- bcopy(&data, (uint8_t *)(sc->atse_rx_m->m_data +
- sc->atse_rx_buf_len), sizeof(data));
- if (meta & A_ONCHIP_FIFO_MEM_CORE_EOP) {
- uint8_t empty;
-
- empty = (meta &
- A_ONCHIP_FIFO_MEM_CORE_EMPTY_MASK) >>
- A_ONCHIP_FIFO_MEM_CORE_EMPTY_SHIFT;
- sc->atse_rx_buf_len += (4 - empty);
-
- if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1);
- rx_npkts++;
-
- m = sc->atse_rx_m;
- m->m_pkthdr.len = m->m_len =
- sc->atse_rx_buf_len;
- sc->atse_rx_m = NULL;
-
- sc->atse_rx_buf_len = 0;
- sc->atse_flags &= ~ATSE_FLAGS_SOP_SEEN;
- if (sc->atse_flags & ATSE_FLAGS_ERROR) {
- sc->atse_flags &= ~ATSE_FLAGS_ERROR;
- m_freem(m);
- } else {
- m->m_pkthdr.rcvif = ifp;
- ATSE_UNLOCK(sc);
- (*ifp->if_input)(ifp, m);
- ATSE_LOCK(sc);
- }
-#ifdef DEVICE_POLLING
- if (ifp->if_capenable & IFCAP_POLLING) {
- if (sc->atse_rx_cycles <= 0)
- return (rx_npkts);
- sc->atse_rx_cycles--;
- }
-#endif
- goto outer; /* Need a new mbuf. */
- } else {
- sc->atse_rx_buf_len += sizeof(data);
- }
- } /* for */
-
- /* XXX-BZ could optimize in case of another packet waiting. */
- } while (fill > 0);
-
- return (rx_npkts);
-}
-
-
/*
* Report current media status.
*/
static void
atse_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
{
struct atse_softc *sc;
struct mii_data *mii;
sc = ifp->if_softc;
ATSE_LOCK(sc);
mii = device_get_softc(sc->atse_miibus);
mii_pollstat(mii);
ifmr->ifm_active = mii->mii_media_active;
ifmr->ifm_status = mii->mii_media_status;
ATSE_UNLOCK(sc);
}
-static void
-atse_rx_intr(void *arg)
-{
- struct atse_softc *sc;
- struct ifnet *ifp;
- uint32_t rxe;
-
- sc = (struct atse_softc *)arg;
- ifp = sc->atse_ifp;
-
- ATSE_LOCK(sc);
-#ifdef DEVICE_POLLING
- if (ifp->if_capenable & IFCAP_POLLING) {
- ATSE_UNLOCK(sc);
- return;
- }
-#endif
-
- atse_intr_debug(sc, "rx");
- rxe = ATSE_RX_EVENT_READ(sc);
- if (rxe & (A_ONCHIP_FIFO_MEM_CORE_EVENT_OVERFLOW|
- A_ONCHIP_FIFO_MEM_CORE_EVENT_UNDERFLOW)) {
- /* XXX-BZ ERROR HANDLING. */
- atse_update_rx_err(sc, ((rxe &
- A_ONCHIP_FIFO_MEM_CORE_ERROR_MASK) >>
- A_ONCHIP_FIFO_MEM_CORE_ERROR_SHIFT) & 0xff);
- if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
- }
-
- /*
- * There is considerable subtlety in the race-free handling of rx
- * interrupts: we must disable interrupts whenever we manipulate the
- * FIFO to prevent further interrupts from firing before we are done;
- * we must clear the event after processing to prevent the event from
- * being immediately reposted due to data remaining; we must clear the
- * event mask before reenabling interrupts or risk missing a positive
- * edge; and we must recheck everything after completing in case the
- * event posted between clearing events and reenabling interrupts. If
- * a race is experienced, we must restart the whole mechanism.
- */
- do {
- ATSE_RX_INTR_DISABLE(sc);
-#if 0
- sc->atse_rx_cycles = RX_CYCLES_IN_INTR;
-#endif
- atse_rx_locked(sc);
- ATSE_RX_EVENT_CLEAR(sc);
-
- /* Disable interrupts if interface is down. */
- if (ifp->if_drv_flags & IFF_DRV_RUNNING)
- ATSE_RX_INTR_ENABLE(sc);
- } while (!(ATSE_RX_STATUS_READ(sc) &
- A_ONCHIP_FIFO_MEM_CORE_STATUS_EMPTY));
- ATSE_UNLOCK(sc);
-
-}
-
-static void
-atse_tx_intr(void *arg)
-{
- struct atse_softc *sc;
- struct ifnet *ifp;
- uint32_t txe;
-
- sc = (struct atse_softc *)arg;
- ifp = sc->atse_ifp;
-
- ATSE_LOCK(sc);
-#ifdef DEVICE_POLLING
- if (ifp->if_capenable & IFCAP_POLLING) {
- ATSE_UNLOCK(sc);
- return;
- }
-#endif
-
- /* XXX-BZ build histogram. */
- atse_intr_debug(sc, "tx");
- txe = ATSE_TX_EVENT_READ(sc);
- if (txe & (A_ONCHIP_FIFO_MEM_CORE_EVENT_OVERFLOW|
- A_ONCHIP_FIFO_MEM_CORE_EVENT_UNDERFLOW)) {
- /* XXX-BZ ERROR HANDLING. */
- if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
- }
-
- /*
- * There is also considerable subtlety in the race-free handling of
- * tx interrupts: all processing occurs with interrupts disabled to
- * prevent spurious refiring while transmit is in progress (which
- * could occur if the FIFO drains while sending -- quite likely); we
- * must not clear the event mask until after we've sent, also to
- * prevent spurious refiring; once we've cleared the event mask we can
- * reenable interrupts, but there is a possible race between clear and
- * enable, so we must recheck and potentially repeat the whole process
- * if it is detected.
- */
- do {
- ATSE_TX_INTR_DISABLE(sc);
- sc->atse_watchdog_timer = 0;
- atse_start_locked(ifp);
- ATSE_TX_EVENT_CLEAR(sc);
-
- /* Disable interrupts if interface is down. */
- if (ifp->if_drv_flags & IFF_DRV_RUNNING)
- ATSE_TX_INTR_ENABLE(sc);
- } while (ATSE_TX_PENDING(sc) &&
- !(ATSE_TX_STATUS_READ(sc) & A_ONCHIP_FIFO_MEM_CORE_STATUS_FULL));
- ATSE_UNLOCK(sc);
-}
-
-#ifdef DEVICE_POLLING
-static int
-atse_poll(struct ifnet *ifp, enum poll_cmd cmd, int count)
-{
- struct atse_softc *sc;
- int rx_npkts = 0;
-
- sc = ifp->if_softc;
- ATSE_LOCK(sc);
- if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
- ATSE_UNLOCK(sc);
- return (rx_npkts);
- }
-
- sc->atse_rx_cycles = count;
- rx_npkts = atse_rx_locked(sc);
- atse_start_locked(ifp);
-
- if (sc->atse_rx_cycles > 0 || cmd == POLL_AND_CHECK_STATUS) {
- uint32_t rx, tx;
-
- rx = ATSE_RX_EVENT_READ(sc);
- tx = ATSE_TX_EVENT_READ(sc);
-
- if (rx & (A_ONCHIP_FIFO_MEM_CORE_EVENT_OVERFLOW|
- A_ONCHIP_FIFO_MEM_CORE_EVENT_UNDERFLOW)) {
- /* XXX-BZ ERROR HANDLING. */
- atse_update_rx_err(sc, ((rx &
- A_ONCHIP_FIFO_MEM_CORE_ERROR_MASK) >>
- A_ONCHIP_FIFO_MEM_CORE_ERROR_SHIFT) & 0xff);
- if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
- }
- if (tx & (A_ONCHIP_FIFO_MEM_CORE_EVENT_OVERFLOW|
- A_ONCHIP_FIFO_MEM_CORE_EVENT_UNDERFLOW)) {
- /* XXX-BZ ERROR HANDLING. */
- if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
- }
- if (ATSE_TX_READ_FILL_LEVEL(sc) == 0)
- sc->atse_watchdog_timer = 0;
-
-#if 0
- if (/* Severe error; if only we could find out. */) {
- ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
- atse_init_locked(sc);
- }
-#endif
- }
-
- ATSE_UNLOCK(sc);
- return (rx_npkts);
-}
-#endif /* DEVICE_POLLING */
-
static struct atse_mac_stats_regs {
const char *name;
const char *descr; /* Mostly copied from Altera datasheet. */
} atse_mac_stats_regs[] = {
[0x1a] =
{ "aFramesTransmittedOK",
"The number of frames that are successfully transmitted including "
"the pause frames." },
{ "aFramesReceivedOK",
"The number of frames that are successfully received including the "
"pause frames." },
{ "aFrameCheckSequenceErrors",
"The number of receive frames with CRC error." },
{ "aAlignmentErrors",
"The number of receive frames with alignment error." },
{ "aOctetsTransmittedOK",
"The lower 32 bits of the number of data and padding octets that "
"are successfully transmitted." },
{ "aOctetsReceivedOK",
"The lower 32 bits of the number of data and padding octets that "
" are successfully received." },
{ "aTxPAUSEMACCtrlFrames",
"The number of pause frames transmitted." },
{ "aRxPAUSEMACCtrlFrames",
"The number received pause frames received." },
{ "ifInErrors",
"The number of errored frames received." },
{ "ifOutErrors",
"The number of transmit frames with either a FIFO overflow error, "
"a FIFO underflow error, or a error defined by the user "
"application." },
{ "ifInUcastPkts",
"The number of valid unicast frames received." },
{ "ifInMulticastPkts",
"The number of valid multicast frames received. The count does "
"not include pause frames." },
{ "ifInBroadcastPkts",
"The number of valid broadcast frames received." },
{ "ifOutDiscards",
"This statistics counter is not in use. The MAC function does not "
"discard frames that are written to the FIFO buffer by the user "
"application." },
{ "ifOutUcastPkts",
"The number of valid unicast frames transmitted." },
{ "ifOutMulticastPkts",
"The number of valid multicast frames transmitted, excluding pause "
"frames." },
{ "ifOutBroadcastPkts",
"The number of valid broadcast frames transmitted." },
{ "etherStatsDropEvents",
"The number of frames that are dropped due to MAC internal errors "
"when FIFO buffer overflow persists." },
{ "etherStatsOctets",
"The lower 32 bits of the total number of octets received. This "
"count includes both good and errored frames." },
{ "etherStatsPkts",
"The total number of good and errored frames received." },
{ "etherStatsUndersizePkts",
"The number of frames received with length less than 64 bytes. "
"This count does not include errored frames." },
{ "etherStatsOversizePkts",
"The number of frames received that are longer than the value "
"configured in the frm_length register. This count does not "
"include errored frames." },
{ "etherStatsPkts64Octets",
"The number of 64-byte frames received. This count includes good "
"and errored frames." },
{ "etherStatsPkts65to127Octets",
"The number of received good and errored frames between the length "
"of 65 and 127 bytes." },
{ "etherStatsPkts128to255Octets",
"The number of received good and errored frames between the length "
"of 128 and 255 bytes." },
{ "etherStatsPkts256to511Octets",
"The number of received good and errored frames between the length "
"of 256 and 511 bytes." },
{ "etherStatsPkts512to1023Octets",
"The number of received good and errored frames between the length "
"of 512 and 1023 bytes." },
{ "etherStatsPkts1024to1518Octets",
"The number of received good and errored frames between the length "
"of 1024 and 1518 bytes." },
{ "etherStatsPkts1519toXOctets",
"The number of received good and errored frames between the length "
"of 1519 and the maximum frame length configured in the frm_length "
"register." },
{ "etherStatsJabbers",
"Too long frames with CRC error." },
{ "etherStatsFragments",
"Too short frames with CRC error." },
/* 0x39 unused, 0x3a/b non-stats. */
[0x3c] =
/* Extended Statistics Counters */
{ "msb_aOctetsTransmittedOK",
"Upper 32 bits of the number of data and padding octets that are "
"successfully transmitted." },
{ "msb_aOctetsReceivedOK",
"Upper 32 bits of the number of data and padding octets that are "
"successfully received." },
{ "msb_etherStatsOctets",
"Upper 32 bits of the total number of octets received. This count "
"includes both good and errored frames." }
};
static int
sysctl_atse_mac_stats_proc(SYSCTL_HANDLER_ARGS)
{
struct atse_softc *sc;
int error, offset, s;
sc = arg1;
offset = arg2;
s = CSR_READ_4(sc, offset);
error = sysctl_handle_int(oidp, &s, 0, req);
- if (error || !req->newptr)
+ if (error || !req->newptr) {
return (error);
+ }
return (0);
}
static struct atse_rx_err_stats_regs {
const char *name;
const char *descr;
} atse_rx_err_stats_regs[] = {
#define ATSE_RX_ERR_FIFO_THRES_EOP 0 /* FIFO threshold reached, on EOP. */
#define ATSE_RX_ERR_ELEN 1 /* Frame/payload length not valid. */
#define ATSE_RX_ERR_CRC32 2 /* CRC-32 error. */
#define ATSE_RX_ERR_FIFO_THRES_TRUNC 3 /* FIFO thresh., truncated frame. */
#define ATSE_RX_ERR_4 4 /* ? */
#define ATSE_RX_ERR_5 5 /* / */
{ "rx_err_fifo_thres_eop",
"FIFO threshold reached, reported on EOP." },
{ "rx_err_fifo_elen",
"Frame or payload length not valid." },
{ "rx_err_fifo_crc32",
"CRC-32 error." },
{ "rx_err_fifo_thres_trunc",
"FIFO threshold reached, truncated frame" },
{ "rx_err_4",
"?" },
{ "rx_err_5",
"?" },
};
static int
sysctl_atse_rx_err_stats_proc(SYSCTL_HANDLER_ARGS)
{
struct atse_softc *sc;
int error, offset, s;
sc = arg1;
offset = arg2;
s = sc->atse_rx_err[offset];
error = sysctl_handle_int(oidp, &s, 0, req);
- if (error || !req->newptr)
+ if (error || !req->newptr) {
return (error);
+ }
return (0);
}
static void
atse_sysctl_stats_attach(device_t dev)
{
struct sysctl_ctx_list *sctx;
struct sysctl_oid *soid;
struct atse_softc *sc;
int i;
sc = device_get_softc(dev);
sctx = device_get_sysctl_ctx(dev);
soid = device_get_sysctl_tree(dev);
/* MAC statistics. */
for (i = 0; i < nitems(atse_mac_stats_regs); i++) {
if (atse_mac_stats_regs[i].name == NULL ||
- atse_mac_stats_regs[i].descr == NULL)
+ atse_mac_stats_regs[i].descr == NULL) {
continue;
+ }
SYSCTL_ADD_PROC(sctx, SYSCTL_CHILDREN(soid), OID_AUTO,
atse_mac_stats_regs[i].name, CTLTYPE_UINT|CTLFLAG_RD,
sc, i, sysctl_atse_mac_stats_proc, "IU",
atse_mac_stats_regs[i].descr);
}
/* rx_err[]. */
for (i = 0; i < ATSE_RX_ERR_MAX; i++) {
if (atse_rx_err_stats_regs[i].name == NULL ||
- atse_rx_err_stats_regs[i].descr == NULL)
+ atse_rx_err_stats_regs[i].descr == NULL) {
continue;
+ }
SYSCTL_ADD_PROC(sctx, SYSCTL_CHILDREN(soid), OID_AUTO,
atse_rx_err_stats_regs[i].name, CTLTYPE_UINT|CTLFLAG_RD,
sc, i, sysctl_atse_rx_err_stats_proc, "IU",
atse_rx_err_stats_regs[i].descr);
}
}
/*
* Generic device handling routines.
*/
int
atse_attach(device_t dev)
{
struct atse_softc *sc;
struct ifnet *ifp;
+ uint32_t caps;
int error;
sc = device_get_softc(dev);
+ sc->dev = dev;
+ /* Get xDMA controller */
+ sc->xdma_tx = xdma_ofw_get(sc->dev, "tx");
+ if (sc->xdma_tx == NULL) {
+ device_printf(dev, "Can't find DMA controller.\n");
+ return (ENXIO);
+ }
+
+ /*
+ * Only final (EOP) write can be less than "symbols per beat" value
+ * so we have to defrag mbuf chain.
+ * Chapter 15. On-Chip FIFO Memory Core.
+ * Embedded Peripherals IP User Guide.
+ */
+ caps = XCHAN_CAP_BUSDMA_NOSEG;
+
+ /* Alloc xDMA virtual channel. */
+ sc->xchan_tx = xdma_channel_alloc(sc->xdma_tx, caps);
+ if (sc->xchan_tx == NULL) {
+ device_printf(dev, "Can't alloc virtual DMA channel.\n");
+ return (ENXIO);
+ }
+
+ /* Setup interrupt handler. */
+ error = xdma_setup_intr(sc->xchan_tx, atse_xdma_tx_intr, sc, &sc->ih_tx);
+ if (error) {
+ device_printf(sc->dev,
+ "Can't setup xDMA interrupt handler.\n");
+ return (ENXIO);
+ }
+
+ xdma_prep_sg(sc->xchan_tx,
+ TX_QUEUE_SIZE, /* xchan requests queue size */
+ MCLBYTES, /* maxsegsize */
+ 8, /* maxnsegs */
+ 16, /* alignment */
+ 0, /* boundary */
+ BUS_SPACE_MAXADDR_32BIT,
+ BUS_SPACE_MAXADDR);
+
+ /* Get RX xDMA controller */
+ sc->xdma_rx = xdma_ofw_get(sc->dev, "rx");
+ if (sc->xdma_rx == NULL) {
+ device_printf(dev, "Can't find DMA controller.\n");
+ return (ENXIO);
+ }
+
+ /* Alloc xDMA virtual channel. */
+ sc->xchan_rx = xdma_channel_alloc(sc->xdma_rx, caps);
+ if (sc->xchan_rx == NULL) {
+ device_printf(dev, "Can't alloc virtual DMA channel.\n");
+ return (ENXIO);
+ }
+
+ /* Setup interrupt handler. */
+ error = xdma_setup_intr(sc->xchan_rx, atse_xdma_rx_intr, sc, &sc->ih_rx);
+ if (error) {
+ device_printf(sc->dev,
+ "Can't setup xDMA interrupt handler.\n");
+ return (ENXIO);
+ }
+
+ xdma_prep_sg(sc->xchan_rx,
+ RX_QUEUE_SIZE, /* xchan requests queue size */
+ MCLBYTES, /* maxsegsize */
+ 1, /* maxnsegs */
+ 16, /* alignment */
+ 0, /* boundary */
+ BUS_SPACE_MAXADDR_32BIT,
+ BUS_SPACE_MAXADDR);
+
+ mtx_init(&sc->br_mtx, "buf ring mtx", NULL, MTX_DEF);
+ sc->br = buf_ring_alloc(BUFRING_SIZE, M_DEVBUF,
+ M_NOWAIT, &sc->br_mtx);
+ if (sc->br == NULL) {
+ return (ENOMEM);
+ }
+
atse_ethernet_option_bits_read(dev);
mtx_init(&sc->atse_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK,
MTX_DEF);
callout_init_mtx(&sc->atse_tick, &sc->atse_mtx, 0);
- sc->atse_tx_buf = malloc(ETHER_MAX_LEN_JUMBO, M_DEVBUF, M_WAITOK);
-
/*
* We are only doing single-PHY with this driver currently. The
* defaults would be right so that BASE_CFG_MDIO_ADDR0 points to the
* 1st PHY address (0) apart from the fact that BMCR0 is always
* the PCS mapping, so we always use BMCR1. See Table 5-1 0xA0-0xBF.
*/
#if 0 /* Always PCS. */
sc->atse_bmcr0 = MDIO_0_START;
CSR_WRITE_4(sc, BASE_CFG_MDIO_ADDR0, 0x00);
#endif
/* Always use matching PHY for atse[0..]. */
sc->atse_phy_addr = device_get_unit(dev);
sc->atse_bmcr1 = MDIO_1_START;
CSR_WRITE_4(sc, BASE_CFG_MDIO_ADDR1, sc->atse_phy_addr);
/* Reset the adapter. */
atse_reset(sc);
/* Setup interface. */
ifp = sc->atse_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 = atse_ioctl;
- ifp->if_start = atse_start;
+ ifp->if_transmit = atse_transmit;
+ ifp->if_qflush = atse_qflush;
ifp->if_init = atse_init;
IFQ_SET_MAXLEN(&ifp->if_snd, ATSE_TX_LIST_CNT - 1);
ifp->if_snd.ifq_drv_maxlen = ATSE_TX_LIST_CNT - 1;
IFQ_SET_READY(&ifp->if_snd);
/* MII setup. */
error = mii_attach(dev, &sc->atse_miibus, ifp, atse_ifmedia_upd,
atse_ifmedia_sts, BMSR_DEFCAPMASK, MII_PHY_ANY, MII_OFFSET_ANY, 0);
if (error != 0) {
device_printf(dev, "attaching PHY failed: %d\n", error);
goto err;
}
/* Call media-indepedent attach routine. */
ether_ifattach(ifp, sc->atse_eth_addr);
/* Tell the upper layer(s) about vlan mtu support. */
ifp->if_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
- /* Hook up interrupts. */
- if (sc->atse_rx_irq_res != NULL) {
- error = bus_setup_intr(dev, sc->atse_rx_irq_res, INTR_TYPE_NET |
- INTR_MPSAFE, NULL, atse_rx_intr, sc, &sc->atse_rx_intrhand);
- if (error != 0) {
- device_printf(dev, "enabling RX IRQ failed\n");
- ether_ifdetach(ifp);
- goto err;
- }
- }
-
- if (sc->atse_tx_irq_res != NULL) {
- error = bus_setup_intr(dev, sc->atse_tx_irq_res, INTR_TYPE_NET |
- INTR_MPSAFE, NULL, atse_tx_intr, sc, &sc->atse_tx_intrhand);
- if (error != 0) {
- bus_teardown_intr(dev, sc->atse_rx_irq_res,
- sc->atse_rx_intrhand);
- device_printf(dev, "enabling TX IRQ failed\n");
- ether_ifdetach(ifp);
- goto err;
- }
- }
-
- if ((ifp->if_capenable & IFCAP_POLLING) != 0 ||
- (sc->atse_rx_irq_res == NULL && sc->atse_tx_irq_res == NULL)) {
-#ifdef DEVICE_POLLING
- /* If not on and no IRQs force it on. */
- if (sc->atse_rx_irq_res == NULL && sc->atse_tx_irq_res == NULL){
- ifp->if_capenable |= IFCAP_POLLING;
- device_printf(dev, "forcing to polling due to no "
- "interrupts\n");
- }
- error = ether_poll_register(atse_poll, ifp);
- if (error != 0)
- goto err;
-#else
- device_printf(dev, "no DEVICE_POLLING in kernel and no IRQs\n");
- error = ENXIO;
-#endif
- } else {
- ATSE_RX_INTR_ENABLE(sc);
- ATSE_TX_INTR_ENABLE(sc);
- }
-
err:
- if (error != 0)
+ if (error != 0) {
atse_detach(dev);
+ }
- if (error == 0)
+ if (error == 0) {
atse_sysctl_stats_attach(dev);
+ }
+ atse_rx_enqueue(sc, NUM_RX_MBUF);
+ xdma_queue_submit(sc->xchan_rx);
+
return (error);
}
static int
atse_detach(device_t dev)
{
struct atse_softc *sc;
struct ifnet *ifp;
sc = device_get_softc(dev);
KASSERT(mtx_initialized(&sc->atse_mtx), ("%s: mutex not initialized",
device_get_nameunit(dev)));
ifp = sc->atse_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)) {
ATSE_LOCK(sc);
atse_stop_locked(sc);
ATSE_UNLOCK(sc);
callout_drain(&sc->atse_tick);
ether_ifdetach(ifp);
}
- if (sc->atse_miibus != NULL)
+ if (sc->atse_miibus != NULL) {
device_delete_child(dev, sc->atse_miibus);
+ }
- if (sc->atse_tx_intrhand)
- bus_teardown_intr(dev, sc->atse_tx_irq_res,
- sc->atse_tx_intrhand);
- if (sc->atse_rx_intrhand)
- bus_teardown_intr(dev, sc->atse_rx_irq_res,
- sc->atse_rx_intrhand);
-
- if (ifp != NULL)
+ if (ifp != NULL) {
if_free(ifp);
+ }
- if (sc->atse_tx_buf != NULL)
- free(sc->atse_tx_buf, M_DEVBUF);
-
mtx_destroy(&sc->atse_mtx);
return (0);
}
/* Shared between nexus and fdt implementation. */
void
atse_detach_resources(device_t dev)
{
struct atse_softc *sc;
sc = device_get_softc(dev);
- if (sc->atse_txc_mem_res != NULL) {
- bus_release_resource(dev, SYS_RES_MEMORY, sc->atse_txc_mem_rid,
- sc->atse_txc_mem_res);
- sc->atse_txc_mem_res = NULL;
- }
- if (sc->atse_tx_mem_res != NULL) {
- bus_release_resource(dev, SYS_RES_MEMORY, sc->atse_tx_mem_rid,
- sc->atse_tx_mem_res);
- sc->atse_tx_mem_res = NULL;
- }
- if (sc->atse_tx_irq_res != NULL) {
- bus_release_resource(dev, SYS_RES_IRQ, sc->atse_tx_irq_rid,
- sc->atse_tx_irq_res);
- sc->atse_tx_irq_res = NULL;
- }
- if (sc->atse_rxc_mem_res != NULL) {
- bus_release_resource(dev, SYS_RES_MEMORY, sc->atse_rxc_mem_rid,
- sc->atse_rxc_mem_res);
- sc->atse_rxc_mem_res = NULL;
- }
- if (sc->atse_rx_mem_res != NULL) {
- bus_release_resource(dev, SYS_RES_MEMORY, sc->atse_rx_mem_rid,
- sc->atse_rx_mem_res);
- sc->atse_rx_mem_res = NULL;
- }
- if (sc->atse_rx_irq_res != NULL) {
- bus_release_resource(dev, SYS_RES_IRQ, sc->atse_rx_irq_rid,
- sc->atse_rx_irq_res);
- sc->atse_rx_irq_res = NULL;
- }
if (sc->atse_mem_res != NULL) {
bus_release_resource(dev, SYS_RES_MEMORY, sc->atse_mem_rid,
sc->atse_mem_res);
sc->atse_mem_res = NULL;
}
}
int
atse_detach_dev(device_t dev)
{
int error;
error = atse_detach(dev);
if (error) {
/* We are basically in undefined state now. */
device_printf(dev, "atse_detach() failed: %d\n", error);
return (error);
}
atse_detach_resources(dev);
return (0);
}
int
atse_miibus_readreg(device_t dev, int phy, int reg)
{
struct atse_softc *sc;
+ int val;
sc = device_get_softc(dev);
/*
* We currently do not support re-mapping of MDIO space on-the-fly
* but de-facto hard-code the phy#.
*/
- if (phy != sc->atse_phy_addr)
+ if (phy != sc->atse_phy_addr) {
return (0);
+ }
- return (PHY_READ_2(sc, reg));
+ val = PHY_READ_2(sc, reg);
+
+ return (val);
}
int
atse_miibus_writereg(device_t dev, int phy, int reg, int data)
{
struct atse_softc *sc;
sc = device_get_softc(dev);
/*
* We currently do not support re-mapping of MDIO space on-the-fly
* but de-facto hard-code the phy#.
*/
- if (phy != sc->atse_phy_addr)
+ if (phy != sc->atse_phy_addr) {
return (0);
+ }
PHY_WRITE_2(sc, reg, data);
return (0);
}
void
atse_miibus_statchg(device_t dev)
{
struct atse_softc *sc;
struct mii_data *mii;
struct ifnet *ifp;
uint32_t val4;
sc = device_get_softc(dev);
ATSE_LOCK_ASSERT(sc);
mii = device_get_softc(sc->atse_miibus);
ifp = sc->atse_ifp;
if (mii == NULL || ifp == NULL ||
- (ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
+ (ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
return;
+ }
val4 = CSR_READ_4(sc, BASE_CFG_COMMAND_CONFIG);
/* Assume no link. */
sc->atse_flags &= ~ATSE_FLAGS_LINK;
if ((mii->mii_media_status & (IFM_ACTIVE | IFM_AVALID)) ==
(IFM_ACTIVE | IFM_AVALID)) {
switch (IFM_SUBTYPE(mii->mii_media_active)) {
case IFM_10_T:
val4 |= BASE_CFG_COMMAND_CONFIG_ENA_10;
val4 &= ~BASE_CFG_COMMAND_CONFIG_ETH_SPEED;
sc->atse_flags |= ATSE_FLAGS_LINK;
break;
case IFM_100_TX:
val4 &= ~BASE_CFG_COMMAND_CONFIG_ENA_10;
val4 &= ~BASE_CFG_COMMAND_CONFIG_ETH_SPEED;
sc->atse_flags |= ATSE_FLAGS_LINK;
break;
case IFM_1000_T:
val4 &= ~BASE_CFG_COMMAND_CONFIG_ENA_10;
val4 |= BASE_CFG_COMMAND_CONFIG_ETH_SPEED;
sc->atse_flags |= ATSE_FLAGS_LINK;
break;
default:
break;
}
}
if ((sc->atse_flags & ATSE_FLAGS_LINK) == 0) {
- /* XXX-BZ need to stop the MAC? */
+ /* Need to stop the MAC? */
return;
}
- if (IFM_OPTIONS(mii->mii_media_active & IFM_FDX) != 0)
+ if (IFM_OPTIONS(mii->mii_media_active & IFM_FDX) != 0) {
val4 &= ~BASE_CFG_COMMAND_CONFIG_HD_ENA;
- else
+ } else {
val4 |= BASE_CFG_COMMAND_CONFIG_HD_ENA;
- /* XXX-BZ flow control? */
+ }
+ /* flow control? */
+
/* Make sure the MAC is activated. */
val4 |= BASE_CFG_COMMAND_CONFIG_TX_ENA;
val4 |= BASE_CFG_COMMAND_CONFIG_RX_ENA;
CSR_WRITE_4(sc, BASE_CFG_COMMAND_CONFIG, val4);
}
-/* end */
+MODULE_DEPEND(atse, ether, 1, 1, 1);
+MODULE_DEPEND(atse, miibus, 1, 1, 1);
Index: head/sys/dev/altera/atse/if_atse_fdt.c
===================================================================
--- head/sys/dev/altera/atse/if_atse_fdt.c (revision 332473)
+++ head/sys/dev/altera/atse/if_atse_fdt.c (revision 332474)
@@ -1,222 +1,147 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2013 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.
*/
#include
__FBSDID("$FreeBSD$");
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
-
#include
#include
#include
#include
#include
/* "device miibus" required. See GENERIC if you get errors here. */
#include "miibus_if.h"
static int
atse_probe_fdt(device_t dev)
{
if (!ofw_bus_status_okay(dev))
return (ENXIO);
- if (ofw_bus_is_compatible(dev, "altera,atse")) {
- device_set_desc(dev, "Altera Triple-Speed Ethernet MegaCore");
- return (BUS_PROBE_DEFAULT);
+ if (!ofw_bus_is_compatible(dev, "altera,atse")) {
+ return (ENXIO);
}
- return (ENXIO);
+
+ device_set_desc(dev, "Altera Triple-Speed Ethernet MegaCore");
+
+ return (BUS_PROBE_DEFAULT);
}
static int
atse_attach_fdt(device_t dev)
{
struct atse_softc *sc;
int error;
sc = device_get_softc(dev);
sc->atse_dev = dev;
sc->atse_unit = device_get_unit(dev);
/*
* FDT has the list of our resources. Given we are using multiple
* memory regions and possibly multiple interrupts, we need to attach
* them in the order specified in .dts:
* MAC, RX and RXC FIFO, TX and TXC FIFO; RX INTR, TX INTR.
*/
/* MAC: Avalon-MM, atse management register region. */
sc->atse_mem_rid = 0;
sc->atse_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
&sc->atse_mem_rid, RF_ACTIVE);
if (sc->atse_mem_res == NULL) {
device_printf(dev, "failed to map memory for ctrl region\n");
- error = ENXIO;
- goto err;
+ /* Cleanup. */
+ atse_detach_resources(dev);
+
+ return (ENXIO);
}
if (bootverbose)
device_printf(sc->atse_dev, "MAC ctrl region at mem %p-%p\n",
(void *)rman_get_start(sc->atse_mem_res),
(void *)(rman_get_start(sc->atse_mem_res) +
rman_get_size(sc->atse_mem_res)));
- /*
- * RX and RXC FIFO memory regions.
- * 0x00: 2 * 32bit FIFO data,
- * 0x20: 8 * 32bit FIFO ctrl, Avalon-ST Sink to Avalon-MM R-Slave.
- */
- sc->atse_rx_mem_rid = 1;
- sc->atse_rx_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
- &sc->atse_rx_mem_rid, RF_ACTIVE);
- if (sc->atse_rx_mem_res == NULL) {
- device_printf(dev, "failed to map memory for RX FIFO\n");
- error = ENXIO;
- goto err;
- }
- if (bootverbose)
- device_printf(sc->atse_dev, "RX FIFO at mem %p-%p\n",
- (void *)rman_get_start(sc->atse_rx_mem_res),
- (void *)(rman_get_start(sc->atse_rx_mem_res) +
- rman_get_size(sc->atse_rx_mem_res)));
+ error = atse_attach(dev);
+ if (error) {
+ /* Cleanup. */
+ atse_detach_resources(dev);
- sc->atse_rxc_mem_rid = 2;
- sc->atse_rxc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
- &sc->atse_rxc_mem_rid, RF_ACTIVE);
- if (sc->atse_rxc_mem_res == NULL) {
- device_printf(dev, "failed to map memory for RXC FIFO\n");
- error = ENXIO;
- goto err;
+ return (error);
}
- if (bootverbose)
- device_printf(sc->atse_dev, "RXC FIFO at mem %p-%p\n",
- (void *)rman_get_start(sc->atse_rxc_mem_res),
- (void *)(rman_get_start(sc->atse_rxc_mem_res) +
- rman_get_size(sc->atse_rxc_mem_res)));
- /*
- * TX and TXC FIFO memory regions.
- * 0x00: 2 * 32bit FIFO data,
- * 0x20: 8 * 32bit FIFO ctrl, Avalon-MM W-Slave to Avalon-ST Source.
- */
- sc->atse_tx_mem_rid = 3;
- sc->atse_tx_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
- &sc->atse_tx_mem_rid, RF_ACTIVE);
- if (sc->atse_tx_mem_res == NULL) {
- device_printf(dev, "failed to map memory for TX FIFO\n");
- error = ENXIO;
- goto err;
- }
- if (bootverbose)
- device_printf(sc->atse_dev, "TX FIFO at mem %p-%p\n",
- (void *)rman_get_start(sc->atse_tx_mem_res),
- (void *)(rman_get_start(sc->atse_tx_mem_res) +
- rman_get_size(sc->atse_tx_mem_res)));
-
- sc->atse_txc_mem_rid = 4;
- sc->atse_txc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
- &sc->atse_txc_mem_rid, RF_ACTIVE);
- if (sc->atse_txc_mem_res == NULL) {
- device_printf(dev, "failed to map memory for TXC FIFO\n");
- error = ENXIO;
- goto err;
- }
- if (bootverbose)
- device_printf(sc->atse_dev, "TXC FIFO at mem %p-%p\n",
- (void *)rman_get_start(sc->atse_txc_mem_res),
- (void *)(rman_get_start(sc->atse_txc_mem_res) +
- rman_get_size(sc->atse_txc_mem_res)));
-
- /* (Optional) RX and TX IRQ. */
- sc->atse_rx_irq_rid = 0;
- sc->atse_rx_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ,
- &sc->atse_rx_irq_rid, RF_ACTIVE | RF_SHAREABLE);
- sc->atse_tx_irq_rid = 1;
- sc->atse_tx_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ,
- &sc->atse_tx_irq_rid, RF_ACTIVE | RF_SHAREABLE);
-
- error = atse_attach(dev);
- if (error)
- goto err;
-
return (0);
-
-err:
- /* Cleanup. */
- atse_detach_resources(dev);
-
- return (error);
}
static device_method_t atse_methods_fdt[] = {
/* Device interface */
DEVMETHOD(device_probe, atse_probe_fdt),
DEVMETHOD(device_attach, atse_attach_fdt),
DEVMETHOD(device_detach, atse_detach_dev),
/* MII interface */
DEVMETHOD(miibus_readreg, atse_miibus_readreg),
DEVMETHOD(miibus_writereg, atse_miibus_writereg),
DEVMETHOD(miibus_statchg, atse_miibus_statchg),
DEVMETHOD_END
};
static driver_t atse_driver_fdt = {
"atse",
atse_methods_fdt,
sizeof(struct atse_softc)
};
DRIVER_MODULE(atse, simplebus, atse_driver_fdt, atse_devclass, 0, 0);
DRIVER_MODULE(miibus, atse, miibus_driver, miibus_devclass, 0, 0);
-
-/* end */
Index: head/sys/dev/altera/atse/if_atse_nexus.c
===================================================================
--- head/sys/dev/altera/atse/if_atse_nexus.c (revision 332473)
+++ head/sys/dev/altera/atse/if_atse_nexus.c (revision 332474)
@@ -1,261 +1,160 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2012,2013 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.
*/
#include
__FBSDID("$FreeBSD$");
#include "opt_device_polling.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
/* "device miibus" required. See GENERIC if you get errors here. */
#include "miibus_if.h"
MODULE_DEPEND(atse, ether, 1, 1, 1);
MODULE_DEPEND(atse, miibus, 1, 1, 1);
/*
* Device routines for interacting with nexus (probe, attach, detach) & helpers.
* XXX We should add suspend/resume later.
*/
-static int
+static int __unused
atse_resource_int(device_t dev, const char *resname, int *v)
{
int error;
error = resource_int_value(device_get_name(dev), device_get_unit(dev),
resname, v);
if (error != 0) {
/* If it does not exist, we fail, so not ingoring ENOENT. */
device_printf(dev, "could not fetch '%s' hint\n", resname);
return (error);
}
return (0);
}
-static int
+static int __unused
atse_resource_long(device_t dev, const char *resname, long *v)
{
int error;
error = resource_long_value(device_get_name(dev), device_get_unit(dev),
resname, v);
if (error != 0) {
/* If it does not exist, we fail, so not ingoring ENOENT. */
device_printf(dev, "could not fetch '%s' hint\n", resname);
return (error);
}
return (0);
}
static int
atse_probe_nexus(device_t dev)
{
- struct resource *res;
- long l;
- int error, rid;
- /*
- * It is almost impossible to properly probe this device. We must
- * rely on hints being set correctly. So try to get hints and
- * one memory mapping. Must cleanup and do again in attach but
- * should not probe successfully if not able to attach later.
- */
- error = atse_resource_int(dev, "rx_irq", &rid);
- error += atse_resource_long(dev, "rx_maddr", &l);
- error += atse_resource_long(dev, "rx_msize", &l);
- error += atse_resource_long(dev, "rxc_maddr", &l);
- error += atse_resource_long(dev, "rxc_msize", &l);
- error += atse_resource_int(dev, "tx_irq", &rid);
- error += atse_resource_long(dev, "tx_maddr", &l);
- error += atse_resource_long(dev, "tx_msize", &l);
- error += atse_resource_long(dev, "txc_maddr", &l);
- error += atse_resource_long(dev, "txc_msize", &l);
- if (error != 0)
- return (ENXIO);
-
- rid = 0;
- res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE);
- if (res == NULL)
- return (ENXIO);
- bus_release_resource(dev, SYS_RES_MEMORY, rid, res);
-
- /* Success. */
device_set_desc(dev, "Altera Triple-Speed Ethernet MegaCore");
+
return (BUS_PROBE_NOWILDCARD);
}
static int
atse_attach_nexus(device_t dev)
{
struct atse_softc *sc;
int error;
sc = device_get_softc(dev);
sc->atse_dev = dev;
sc->atse_unit = device_get_unit(dev);
- /* Get RX and TX IRQ and FIFO information from hints. */
- error = atse_resource_int(dev, "rx_irq", &sc->atse_rx_irq);
- error += atse_resource_long(dev, "rx_maddr", &sc->atse_rx_maddr);
- error += atse_resource_long(dev, "rx_msize", &sc->atse_rx_msize);
- error += atse_resource_long(dev, "rxc_maddr", &sc->atse_rxc_maddr);
- error += atse_resource_long(dev, "rxc_msize", &sc->atse_rxc_msize);
- error += atse_resource_int(dev, "tx_irq", &sc->atse_tx_irq);
- error += atse_resource_long(dev, "tx_maddr", &sc->atse_tx_maddr);
- error += atse_resource_long(dev, "tx_msize", &sc->atse_tx_msize);
- error += atse_resource_long(dev, "txc_maddr", &sc->atse_txc_maddr);
- error += atse_resource_long(dev, "txc_msize", &sc->atse_txc_msize);
- if (error != 0)
- return (error);
-
/* Avalon-MM, atse management register region. */
sc->atse_mem_rid = 0;
sc->atse_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
&sc->atse_mem_rid, RF_ACTIVE);
if (sc->atse_mem_res == NULL) {
device_printf(dev, "failed to map memory for ctrl region\n");
return (ENXIO);
}
- /*
- * (Optional) RX IRQ and memory mapped regions.
- * 0x00: 2 * 32bit FIFO data,
- * 0x20: 8 * 32bit FIFO ctrl, Avalon-ST Sink to Avalon-MM R-Slave.
- */
- sc->atse_rx_irq_rid = 0;
- sc->atse_rx_irq_res = bus_alloc_resource(dev, SYS_RES_IRQ,
- &sc->atse_rx_irq_rid, sc->atse_rx_irq, sc->atse_rx_irq, 1,
- RF_ACTIVE | RF_SHAREABLE);
-
- sc->atse_rx_mem_rid = 0;
- sc->atse_rx_mem_res = bus_alloc_resource(dev, SYS_RES_MEMORY,
- &sc->atse_rx_mem_rid, sc->atse_rx_maddr, sc->atse_rx_maddr +
- sc->atse_rx_msize, sc->atse_rx_msize, RF_ACTIVE);
- if (sc->atse_rx_mem_res == NULL) {
- device_printf(dev, "failed to map memory for RX\n");
- goto err;
- }
- sc->atse_rxc_mem_rid = 0;
- sc->atse_rxc_mem_res = bus_alloc_resource(dev, SYS_RES_MEMORY,
- &sc->atse_rxc_mem_rid, sc->atse_rxc_maddr, sc->atse_rxc_maddr +
- sc->atse_rxc_msize, sc->atse_rxc_msize, RF_ACTIVE);
- if (sc->atse_rxc_mem_res == NULL) {
- device_printf(dev, "failed to map memory for RX control\n");
- goto err;
- }
-
- /*
- * (Optional) TX IRQ and memory mapped regions.
- * 0x00: 2 * 32bit FIFO data,
- * 0x20: 8 * 32bit FIFO ctrl, Avalon-MM W-Slave to Avalon-ST Source.
- */
- sc->atse_tx_irq_rid = 0;
- sc->atse_tx_irq_res = bus_alloc_resource(dev, SYS_RES_IRQ,
- &sc->atse_tx_irq_rid, sc->atse_tx_irq, sc->atse_tx_irq, 1,
- RF_ACTIVE | RF_SHAREABLE);
-
- sc->atse_tx_mem_rid = 0;
- sc->atse_tx_mem_res = bus_alloc_resource(dev, SYS_RES_MEMORY,
- &sc->atse_tx_mem_rid, sc->atse_tx_maddr, sc->atse_tx_maddr +
- sc->atse_tx_msize, sc->atse_tx_msize, RF_ACTIVE);
- if (sc->atse_tx_mem_res == NULL) {
- device_printf(dev, "failed to map memory for TX\n");
- goto err;
+ error = atse_attach(dev);
+ if (error) {
+ /* Cleanup. */
+ atse_detach_resources(dev);
+ return (error);
}
- sc->atse_txc_mem_rid = 0;
- sc->atse_txc_mem_res = bus_alloc_resource(dev, SYS_RES_MEMORY,
- &sc->atse_txc_mem_rid, sc->atse_txc_maddr, sc->atse_txc_maddr +
- sc->atse_txc_msize, sc->atse_txc_msize, RF_ACTIVE);
- if (sc->atse_txc_mem_res == NULL) {
- device_printf(dev, "failed to map memory for TX control\n");
- goto err;
- }
- error = atse_attach(dev);
- if (error)
- goto err;
-
return (0);
-
-err:
- /* Cleanup. */
- atse_detach_resources(dev);
-
- return (error);
}
static device_method_t atse_methods_nexus[] = {
/* Device interface */
DEVMETHOD(device_probe, atse_probe_nexus),
DEVMETHOD(device_attach, atse_attach_nexus),
DEVMETHOD(device_detach, atse_detach_dev),
/* MII interface */
DEVMETHOD(miibus_readreg, atse_miibus_readreg),
DEVMETHOD(miibus_writereg, atse_miibus_writereg),
DEVMETHOD(miibus_statchg, atse_miibus_statchg),
DEVMETHOD_END
};
static driver_t atse_driver_nexus = {
"atse",
atse_methods_nexus,
sizeof(struct atse_softc)
};
DRIVER_MODULE(atse, nexus, atse_driver_nexus, atse_devclass, 0, 0);
DRIVER_MODULE(miibus, atse, miibus_driver, miibus_devclass, 0, 0);
-
-/* end */
Index: head/sys/dev/altera/atse/if_atsereg.h
===================================================================
--- head/sys/dev/altera/atse/if_atsereg.h (revision 332473)
+++ head/sys/dev/altera/atse/if_atsereg.h (revision 332474)
@@ -1,488 +1,471 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2012 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_ATSEREG_H
#define _DEV_IF_ATSEREG_H
+#include
+
#define ATSE_VENDOR 0x6af7
#define ATSE_DEVICE 0x00bd
/* See hints file/fdt for ctrl port and Avalon FIFO addresses. */
/* Section 3. Parameter Settings. */
/*
* This is a lot of options that affect the way things are synthesized.
* We cannot really make them all hints and most of them might be stale.
*/
/* 3-1 Core Configuration */
#if 0
static const char *atse_core_core_variation[] = {
[0] = "10/100/1000 Mbps Ethernet MAC only",
[1] = "10/100/1000 Mbps Ethernet MAC with 1000BASE-X/SGMII PCS",
[2] = "1000BASE-X/SGMII PCS only",
[3] = "1000 Mbps Small MAC",
[4] = "10/100 Mbps Small MAC",
NULL
};
static const char *atse_core_interface[] = {
[0] = "MII", /* Core variation 4. */
[1] = "GMII", /* Core variation 3. */
[2] = "RGMII", /* Core variation 0,1,3. */
[3] = "MII/GMII", /* Core variation 0,1. */
NULL
};
#endif
#define CORE_CORE_VARIATION 1 /* atse_core_core_variation[] */
#define CORE_INTERFACE 3 /* atse_core_interface[] */
#define CORE_USE_INTERNAL_FIFO 1
#define CORE_NUMBER_OF_PORTS 1 /* Internal FIFO count. */
#define CORE_USE_TRANSCEIVER_BLOCK 1 /* SGMII PCS transceiver:
* LVDS I/O. */
/* 3-2 MAC Options. */
/* Ethernet MAC Options. */
#define MAC_ENABLE_10_100_HDX_SUPPORT 0
#define MAC_ENABLE_RG_G_MII_LOOPBACK 0
#define MAC_ENABLE_SUPL_MAC_UCAST_ADDR 0 /* Supplementary MAC unicast. */
#define MAC_INCLUDE_STATISTICS_COUNTERS 0
#define MAC_STATISTICS_COUNTERS_64BIT 0
#define MAC_INCLUDE_MC_HASHTABLE 0 /* Multicast. */
#define MAC_ALIGN_PKTHDR_32BIT 1
#define MAC_ENABLE_FDX_FLOW_CTRL 0
#define MAC_ENABLE_VLAN_DETECTION 0 /* VLAN and stacked VLANs. */
#define MAC_ENABLE_MAGIC_PKT_DETECTION 0
/* MDIO Module. */
#define MAC_MDIO_INCLUDE_MDIO_MODULE 1
#define MAC_MDIO_HOST_CLOCK_DIVISOR 40 /* Not just On/Off. */
/* 3-4 FIFO Options. */
/* Width and Memory Type. */
#if 0
static char *fifo_memory_block[] = {
[0] = "M4K",
[1] = "M9K",
[2] = "M144K",
[3] = "MRAM",
[4] = "AUTO",
NULL
};
#endif
#define FIFO_MEMORY_BLOCK 4
#define FIFO_WITDH 32 /* Other: 8 bits. */
/* Depth. */
#define FIFO_DEPTH_TX 2048 /* 64 .. 64k, 2048x32bits. */
#define FIFO_DEPTH_RX 2048 /* 64 .. 64k, 2048x32bits. */
#define ATSE_TX_LIST_CNT 5 /* Certainly not bufferbloat. */
/* 3-4 PCS/Transceiver Options */
/* PCS Options. */
#define PCS_TXRX_PHY_ID 0x00000000 /* 32 bits */
#define PCS_TXRX_ENABLE_SGMII_BRIDGE 0
/* Transceiver Options. */
#define PCS_TXRX_EXP_POWER_DOWN_SIGNAL 0 /* Export power down signal. */
#define PCS_TXRX_ENABLE_DYNAMIC_RECONF 0 /* Dynamic trans. reconfig. */
#define PCS_TXRX_STARTING_CHANNEL 0 /* 0..284. */
/* -------------------------------------------------------------------------- */
/* XXX more values based on the bitmaps provided. Cleanup. */
/* See regs above. */
#define AVALON_FIFO_TX_BLOCK_DIAGRAM 0
#define AVALON_FIFO_TX_BLOCK_DIAGRAM_SHOW_SIGANLS 0
#define AVALON_FIFO_TX_PARAM_SINGLE_RESET_MODE 0
#define AVALON_FIFO_TX_BASIC_OPTS_DEPTH 16
#define AVALON_FIFO_TX_BASIC_OPTS_ALLOW_BACKPRESSURE 1
#define AVALON_FIFO_TX_BASIC_OPTS_CLOCK_SETTING "Single Clock Mode"
#define AVALON_FIFO_TX_BASIC_OPTS_FIFO_IMPL "Construct FIFO from embedded memory blocks"
#define AVALON_FIFO_TX_STATUS_PORT_CREATE_STATUS_INT_FOR_INPUT 1
#define AVALON_FIFO_TX_STATUS_PORT_CREATE_STATUS_INT_FOR_OUTPUT 0
#define AVALON_FIFO_TX_STATUS_PORT_ENABLE_IRQ_FOR_STATUS_PORT 1
#define AVALON_FIFO_TX_INPUT_TYPE "AVALONMM_WRITE"
#define AVALON_FIFO_TX_OUTPUT_TYPE "AVALONST_SOURCE"
#define AVALON_FIFO_TX_AVALON_MM_PORT_SETTINGS_DATA_WIDTH ""
#define AVALON_FIFO_TX_AVALON_ST_PORT_SETTINGS_BITS_PER_SYMBOL 8
#define AVALON_FIFO_TX_AVALON_ST_PORT_SETTINGS_SYM_PER_BEAT 4
#define AVALON_FIFO_TX_AVALON_ST_PORT_SETTINGS_ERROR_WIDTH 1
#define AVALON_FIFO_TX_AVALON_ST_PORT_SETTINGS_CHANNEL_WIDTH 0
#define AVALON_FIFO_TX_AVALON_ST_PORT_SETTINGS_ENABLE_PACKET_DATA 1
#define AVALON_FIFO_RX_BLOCK_DIAGRAM 0
#define AVALON_FIFO_RX_BLOCK_DIAGRAM_SHOW_SIGNALS 0
#define AVALON_FIFO_RX_PARAM_SINGLE_RESET_MODE 0
#define AVALON_FIFO_RX_BASIC_OPTS_DEPTH 16
#define AVALON_FIFO_RX_BASIC_OPTS_ALLOW_BACKPRESSURE 1
#define AVALON_FIFO_RX_BASIC_OPTS_CLOCK_SETTING "Single Clock Mode"
#define AVALON_FIFO_RX_BASIC_OPTS_FIFO_IMPL "Construct FIFO from embedded memory blocks"
#define AVALON_FIFO_RX_STATUS_PORT_CREATE_STATUS_INT_FOR_INPUT 1
#define AVALON_FIFO_RX_STATUS_PORT_CREATE_STATUS_INT_FOR_OUTPUT 0
#define AVALON_FIFO_RX_STATUS_PORT_ENABLE_IRQ_FOR_STATUS_PORT 1
#define AVALON_FIFO_RX_INPUT_TYPE "AVALONST_SINK"
#define AVALON_FIFO_RX_OUTPUT_TYPE "AVALONMM_READ"
#define AVALON_FIFO_RX_AVALON_MM_PORT_SETTINGS_DATA_WIDTH ""
#define AVALON_FIFO_RX_AVALON_ST_PORT_SETTINGS_BITS_PER_SYMBOL 8
#define AVALON_FIFO_RX_AVALON_ST_PORT_SETTINGS_SYM_PER_BEAT 4
#define AVALON_FIFO_RX_AVALON_ST_PORT_SETTINGS_ERROR_WIDTH 6
#define AVALON_FIFO_RX_AVALON_ST_PORT_SETTINGS_CHANNEL_WIDTH 0
#define AVALON_FIFO_RX_AVALON_ST_PORT_SETTINGS_ENABLE_PACKET_DATA 1
/* -------------------------------------------------------------------------- */
/* 5. Configuration Register Space. */
/* 5-1, MAC Configuration Register Space; Dword offsets. */
/* 0x00 - 0x17, Base Configuration. */
#define BASE_CONFIG_REV 0x00 /* ro, IP Core ver. */
#define BASE_CFG_REV_VER_MASK 0x0000FFFF
#define BASE_CFG_REV_CUST_VERSION__MASK 0xFFFF0000
#define BASE_CFG_SCRATCH 0x01 /* rw, 0 */
#define BASE_CFG_COMMAND_CONFIG 0x02 /* rw, 0 */
#define BASE_CFG_COMMAND_CONFIG_TX_ENA (1<<0) /* rw */
#define BASE_CFG_COMMAND_CONFIG_RX_ENA (1<<1) /* rw */
#define BASE_CFG_COMMAND_CONFIG_XON_GEN (1<<2) /* rw */
#define BASE_CFG_COMMAND_CONFIG_ETH_SPEED (1<<3) /* rw */
#define BASE_CFG_COMMAND_CONFIG_PROMIS_EN (1<<4) /* rw */
#define BASE_CFG_COMMAND_CONFIG_PAD_EN (1<<5) /* rw */
#define BASE_CFG_COMMAND_CONFIG_CRC_FWD (1<<6) /* rw */
#define BASE_CFG_COMMAND_CONFIG_PAUSE_FWD (1<<7) /* rw */
#define BASE_CFG_COMMAND_CONFIG_PAUSE_IGNORE (1<<8) /* rw */
#define BASE_CFG_COMMAND_CONFIG_TX_ADDR_INS (1<<9) /* rw */
#define BASE_CFG_COMMAND_CONFIG_HD_ENA (1<<10) /* rw */
#define BASE_CFG_COMMAND_CONFIG_EXCESS_COL (1<<11) /* ro */
#define BASE_CFG_COMMAND_CONFIG_LATE_COL (1<<12) /* ro */
#define BASE_CFG_COMMAND_CONFIG_SW_RESET (1<<13) /* rw */
#define BASE_CFG_COMMAND_CONFIG_MHASH_SEL (1<<14) /* rw */
#define BASE_CFG_COMMAND_CONFIG_LOOP_ENA (1<<15) /* rw */
#define BASE_CFG_COMMAND_CONFIG_TX_ADDR_SEL (1<<16|1<<17|1<<18) /* rw */
#define BASE_CFG_COMMAND_CONFIG_MAGIC_ENA (1<<19) /* rw */
#define BASE_CFG_COMMAND_CONFIG_SLEEP (1<<20) /* rw */
#define BASE_CFG_COMMAND_CONFIG_WAKEUP (1<<21) /* ro */
#define BASE_CFG_COMMAND_CONFIG_XOFF_GEN (1<<22) /* rw */
#define BASE_CFG_COMMAND_CONFIG_CNTL_FRM_ENA (1<<23) /* rw */
#define BASE_CFG_COMMAND_CONFIG_NO_LGTH_CHECK (1<<24) /* rw */
#define BASE_CFG_COMMAND_CONFIG_ENA_10 (1<<25) /* rw */
#define BASE_CFG_COMMAND_CONFIG_RX_ERR_DISC (1<<26) /* rw */
#define BASE_CFG_COMMAND_CONFIG_DISABLE_READ_TIMEOUT (1<<27) /* rw */
/* 28-30 Reserved. */ /* - */
#define BASE_CFG_COMMAND_CONFIG_CNT_RESET (1<<31) /* rw */
#define BASE_CFG_MAC_0 0x03 /* rw, 0 */
#define BASE_CFG_MAC_1 0x04 /* rw, 0 */
#define BASE_CFG_FRM_LENGTH 0x05 /* rw/ro, 1518 */
#define BASE_CFG_PAUSE_QUANT 0x06 /* rw, 0 */
#define BASE_CFG_RX_SECTION_EMPTY 0x07 /* rw/ro, 0 */
#define BASE_CFG_RX_SECTION_FULL 0x08 /* rw/ro, 0 */
#define BASE_CFG_TX_SECTION_EMPTY 0x09 /* rw/ro, 0 */
#define BASE_CFG_TX_SECTION_FULL 0x0A /* rw/ro, 0 */
#define BASE_CFG_RX_ALMOST_EMPTY 0x0B /* rw/ro, 0 */
#define BASE_CFG_RX_ALMOST_FULL 0x0C /* rw/ro, 0 */
#define BASE_CFG_TX_ALMOST_EMPTY 0x0D /* rw/ro, 0 */
#define BASE_CFG_TX_ALMOST_FULL 0x0E /* rw/ro, 0 */
#define BASE_CFG_MDIO_ADDR0 0x0F /* rw, 0 */
#define BASE_CFG_MDIO_ADDR1 0x10 /* rw, 1 */
#define BASE_CFG_HOLDOFF_QUANT 0x11 /* rw, 0xFFFF */
/* 0x12-0x16 Reserved. */ /* -, 0 */
#define BASE_CFG_TX_IPG_LENGTH 0x17 /* rw, 0 */
/* 0x18 - 0x38, Statistics Counters. */
#define STATS_A_MAC_ID_0 0x18 /* ro */
#define STATS_A_MAC_ID_1 0x19 /* ro */
#define STATS_A_FRAMES_TX_OK 0x1A /* ro */
#define STATS_A_FRAMES_RX_OK 0x1B /* ro */
#define STATS_A_FCS_ERRORS 0x1C /* ro */
#define STATS_A_ALIGNMENT_ERRORS 0x1D /* ro */
#define STATS_A_OCTETS_TX_OK 0x1E /* ro */
#define STATS_A_OCTETS_RX_OK 0x1F /* ro */
#define STATS_A_TX_PAUSE_MAX_CTRL_FRAME 0x20 /* ro */
#define STATS_A_RX_PAUSE_MAX_CTRL_FRAME 0x21 /* ro */
#define STATS_IF_IN_ERRORS 0x22 /* ro */
#define STATS_IF_OUT_ERRORS 0x23 /* ro */
#define STATS_IF_IN_UCAST_PKTS 0x24 /* ro */
#define STATS_IF_IN_MULTICAST_PKTS 0x25 /* ro */
#define STATS_IF_IN_BROADCAST_PKTS 0x26 /* ro */
#define STATS_IF_OUT_DISCARDS 0x27 /* ro */
#define STATS_IF_OUT_UCAST_PKTS 0x28 /* ro */
#define STATS_IF_OUT_MULTICAST_PKTS 0x29 /* ro */
#define STATS_IF_OUT_BROADCAST_PKTS 0x2A /* ro */
#define STATS_ETHER_STATS_DROP_EVENT 0x2B /* ro */
#define STATS_ETHER_STATS_OCTETS 0x2C /* ro */
#define STATS_ETHER_STATS_PKTS 0x2D /* ro */
#define STATS_ETHER_STATS_USIZE_PKTS 0x2E /* ro */
#define STATS_ETHER_STATS_OSIZE_PKTS 0x2F /* ro */
#define STATS_ETHER_STATS_PKTS_64_OCTETS 0x30 /* ro */
#define STATS_ETHER_STATS_PKTS_65_TO_127_OCTETS 0x31 /* ro */
#define STATS_ETHER_STATS_PKTS_128_TO_255_OCTETS 0x32 /* ro */
#define STATS_ETHER_STATS_PKTS_256_TO_511_OCTETS 0x33 /* ro */
#define STATS_ETHER_STATS_PKTS_512_TO_1023_OCTETS 0x34 /* ro */
#define STATS_ETHER_STATS_PKTS_1024_TO_1518_OCTETS 0x35 /* ro */
#define STATS_ETHER_STATS_PKTS_1519_TO_X_OCTETS 0x36 /* ro */
#define STATS_ETHER_STATS_JABBERS 0x37 /* ro */
#define STATS_ETHER_STATS_FRAGMENTS 0x38 /* ro */
/* 0x39, Reserved. */ /* - */
/* 0x3A, Transmit Command. */
#define TX_CMD_STAT 0x3A /* rw */
#define TX_CMD_STAT_OMIT_CRC (1<<17)
#define TX_CMD_STAT_TX_SHIFT16 (1<<18)
/* 0x3B, Receive Command. */
#define RX_CMD_STAT 0x3B /* rw */
#define RX_CMD_STAT_RX_SHIFT16 (1<<25)
/* 0x3C - 0x3E, Extended Statistics Counters. */
#define ESTATS_MSB_A_OCTETS_TX_OK 0x3C /* ro */
#define ESTATS_MSB_A_OCTETS_RX_OK 0x3D /* ro */
#define ESTATS_MSB_ETHER_STATS_OCTETS 0x3E /* ro */
/* 0x3F, Reserved. */
/* 0x40 - 0x7F, Multicast Hash Table. */
#define MHASH_START 0x40
#define MHASH_LEN 0x3F
/* 0x80 - 0x9F, MDIO Space 0 or PCS Function Configuration. */
#define MDIO_0_START 0x80
/* The following are offsets to the first PCS register at 0x80. */
/* See sys/dev/mii/mii.h. */
#define PCS_CONTROL 0x00 /* rw */
/* Bits 0:4, Reserved. */ /* - */
#define PCS_CONTROL_UNIDIRECTIONAL_ENABLE (1<<5) /* rw */
#define PCS_CONTROL_SPEED_SELECTION (1<<6|1<<13) /* ro */
#define PCS_CONTROL_COLLISION_TEST (1<<7) /* ro */
#define PCS_CONTROL_DUPLEX_MODE (1<<8) /* ro */
#define PCS_CONTROL_RESTART_AUTO_NEGOTIATION (1<<9) /* rw */
#define PCS_CONTROL_ISOLATE (1<<10) /* rw */
#define PCS_CONTROL_POWERDOWN (1<<11) /* rw */
#define PCS_CONTROL_AUTO_NEGOTIATION_ENABLE (1<<12) /* rw */
/* See bit 6 above. */ /* ro */
#define PCS_CONTROL_LOOPBACK (1<<14) /* rw */
#define PCS_CONTROL_RESET (1<<15) /* rw */
#define PCS_STATUS 0x01 /* ro */
#define PCS_STATUS_EXTENDED_CAPABILITY (1<<0) /* ro */
#define PCS_STATUS_JABBER_DETECT (1<<1) /* -, 0 */
#define PCS_STATUS_LINK_STATUS (1<<2) /* ro */
#define PCS_STATUS_AUTO_NEGOTIATION_ABILITY (1<<3) /* ro */
#define PCS_STATUS_REMOTE_FAULT (1<<4) /* -, 0 */
#define PCS_STATUS_AUTO_NEGOTIATION_COMPLETE (1<<5) /* ro */
#define PCS_STATUS_MF_PREAMBLE_SUPPRESSION (1<<6) /* -, 0 */
#define PCS_STATUS_UNIDIRECTIONAL_ABILITY (1<<7) /* ro */
#define PCS_STATUS_EXTENDED_STATUS (1<<8) /* -, 0 */
#define PCS_STATUS_100BASET2_HALF_DUPLEX (1<<9) /* ro */
#define PCS_STATUS_100BASET2_FULL_DUPLEX (1<<10) /* ro */
#define PCS_STATUS_10MBPS_HALF_DUPLEX (1<<11) /* ro */
#define PCS_STATUS_10MBPS_FULL_DUPLEX (1<<12) /* ro */
#define PCS_STATUS_100BASE_X_HALF_DUPLEX (1<<13) /* ro */
#define PCS_STATUS_100BASE_X_FULL_DUPLEX (1<<14) /* ro */
#define PCS_STATUS_100BASE_T4 (1<<15) /* ro */
#define PCS_PHY_IDENTIFIER_0 0x02 /* ro */
#define PCS_PHY_IDENTIFIER_1 0x03 /* ro */
#define PCS_DEV_ABILITY 0x04 /* rw */
/* 1000BASE-X */
/* Bits 0:4, Reserved. */ /* - */
#define PCS_DEV_ABILITY_1000BASE_X_FD (1<<5) /* rw */
#define PCS_DEV_ABILITY_1000BASE_X_HD (1<<6) /* rw */
#define PCS_DEV_ABILITY_1000BASE_X_PS1 (1<<7) /* rw */
#define PCS_DEV_ABILITY_1000BASE_X_PS2 (1<<8) /* rw */
/* Bits 9:11, Reserved. */ /* - */
#define PCS_DEV_ABILITY_1000BASE_X_RF1 (1<<12) /* rw */
#define PCS_DEV_ABILITY_1000BASE_X_RF2 (1<<13) /* rw */
#define PCS_DEV_ABILITY_1000BASE_X_ACK (1<<14) /* rw */
#define PCS_DEV_ABILITY_1000BASE_X_NP (1<<15) /* rw */
#define PCS_PARTNER_ABILITY 0x05 /* ro */
/* 1000BASE-X */
/* Bits 0:4, Reserved. */ /* - */
#define PCS_PARTNER_ABILITY_1000BASE_X_FD (1<<5) /* ro */
#define PCS_PARTNER_ABILITY_1000BASE_X_HD (1<<6) /* ro */
#define PCS_PARTNER_ABILITY_1000BASE_X_PS1 (1<<7) /* ro */
#define PCS_PARTNER_ABILITY_1000BASE_X_PS2 (1<<8) /* ro */
/* Bits 9:11, Reserved. */ /* - */
#define PCS_PARTNER_ABILITY_1000BASE_X_RF1 (1<<12) /* ro */
#define PCS_PARTNER_ABILITY_1000BASE_X_RF2 (1<<13) /* ro */
#define PCS_PARTNER_ABILITY_1000BASE_X_ACK (1<<14) /* ro */
#define PCS_PARTNER_ABILITY_1000BASE_X_NP (1<<15) /* ro */
/* SGMII */
/* Bits 0:9, Reserved. */ /* - */
#define PCS_PARTNER_ABILITY_SGMII_COPPER_SPEED0 (1<<10) /* ro */
#define PCS_PARTNER_ABILITY_SGMII_COPPER_SPEED1 (1<<11) /* ro */
#define PCS_PARTNER_ABILITY_SGMII_COPPER_DUPLEX_STATUS (1<<12) /* ro */
/* Bit 13, Reserved. */ /* - */
#define PCS_PARTNER_ABILITY_SGMII_ACK (1<<14) /* ro */
#define PCS_PARTNER_ABILITY_SGMII_COPPER_LINK_STATUS (1<<15) /* ro */
#define PCS_AN_EXPANSION 0x06 /* ro */
#define PCS_AN_EXPANSION_LINK_PARTNER_AUTO_NEGOTIATION_ABLE (1<<0) /* ro */
#define PCS_AN_EXPANSION_PAGE_RECEIVE (1<<1) /* ro */
#define PCS_AN_EXPANSION_NEXT_PAGE_ABLE (1<<2) /* -, 0 */
/* Bits 3:15, Reserved. */ /* - */
#define PCS_DEVICE_NEXT_PAGE 0x07 /* ro */
#define PCS_PARTNER_NEXT_PAGE 0x08 /* ro */
#define PCS_MASTER_SLAVE_CNTL 0x09 /* ro */
#define PCS_MASTER_SLAVE_STAT 0x0A /* ro */
/* 0x0B - 0x0E, Reserved */ /* - */
#define PCS_EXTENDED_STATUS 0x0F /* ro */
/* Specific Extended Registers. */
#define PCS_EXT_SCRATCH 0x10 /* rw */
#define PCS_EXT_REV 0x11 /* ro */
#define PCS_EXT_LINK_TIMER_0 0x12 /* rw */
#define PCS_EXT_LINK_TIMER_1 0x13 /* rw */
#define PCS_EXT_IF_MODE 0x14 /* rw */
#define PCS_EXT_IF_MODE_SGMII_ENA (1<<0) /* rw */
#define PCS_EXT_IF_MODE_USE_SGMII_AN (1<<1) /* rw */
#define PCS_EXT_IF_MODE_SGMII_SPEED1 (1<<2) /* rw */
#define PCS_EXT_IF_MODE_SGMII_SPEED0 (1<<3) /* rw */
#define PCS_EXT_IF_MODE_SGMII_DUPLEX (1<<4) /* rw */
/* Bits 5:15, Reserved. */ /* - */
#define PCS_EXT_DISABLE_READ_TIMEOUT 0x15 /* rw */
#define PCS_EXT_READ_TIMEOUT 0x16 /* r0 */
/* 0x17-0x1F, Reserved. */
/* 0xA0 - 0xBF, MDIO Space 1. */
#define MDIO_1_START 0xA0
#define ATSE_BMCR MDIO_1_START
/* 0xC0 - 0xC7, Supplementary Address. */
#define SUPPL_ADDR_SMAC_0_0 0xC0 /* rw */
#define SUPPL_ADDR_SMAC_0_1 0xC1 /* rw */
#define SUPPL_ADDR_SMAC_1_0 0xC2 /* rw */
#define SUPPL_ADDR_SMAC_1_1 0xC3 /* rw */
#define SUPPL_ADDR_SMAC_2_0 0xC4 /* rw */
#define SUPPL_ADDR_SMAC_2_1 0xC5 /* rw */
#define SUPPL_ADDR_SMAC_3_0 0xC6 /* rw */
#define SUPPL_ADDR_SMAC_3_1 0xC7 /* rw */
/* 0xC8 - 0xCF, Reserved; set to zero, ignore on read. */
/* 0xD7 - 0xFF, Reserved; set to zero, ignore on read. */
/* -------------------------------------------------------------------------- */
/* DE4 Intel Strata Flash Ethernet Option Bits area. */
/* XXX-BZ this is something a loader will have to handle for us. */
#define ALTERA_ETHERNET_OPTION_BITS_OFF 0x00008000
#define ALTERA_ETHERNET_OPTION_BITS_LEN 0x00007fff
/* -------------------------------------------------------------------------- */
struct atse_softc {
struct ifnet *atse_ifp;
- struct mbuf *atse_rx_m;
- struct mbuf *atse_tx_m;
- uint8_t *atse_tx_buf;
struct resource *atse_mem_res;
- struct resource *atse_rx_irq_res;
- struct resource *atse_rx_mem_res;
- struct resource *atse_rxc_mem_res;
- struct resource *atse_tx_irq_res;
- struct resource *atse_tx_mem_res;
- struct resource *atse_txc_mem_res;
device_t atse_miibus;
device_t atse_dev;
int atse_unit;
int atse_mem_rid;
- int atse_rx_irq_rid;
- int atse_rx_mem_rid;
- int atse_rxc_mem_rid;
- int atse_tx_irq_rid;
- int atse_tx_mem_rid;
- int atse_txc_mem_rid;
int atse_phy_addr;
int atse_if_flags;
- int atse_rx_irq;
- int atse_tx_irq;
- u_long atse_rx_maddr;
- u_long atse_rx_msize;
- u_long atse_tx_maddr;
- u_long atse_tx_msize;
- u_long atse_rxc_maddr;
- u_long atse_rxc_msize;
- u_long atse_txc_maddr;
- u_long atse_txc_msize;
- void *atse_rx_intrhand;
- void *atse_tx_intrhand;
bus_addr_t atse_bmcr0;
bus_addr_t atse_bmcr1;
uint32_t atse_flags;
#define ATSE_FLAGS_LINK 0x00000001
#define ATSE_FLAGS_ERROR 0x00000002
#define ATSE_FLAGS_SOP_SEEN 0x00000004
uint8_t atse_eth_addr[ETHER_ADDR_LEN];
#define ATSE_ETH_ADDR_DEF 0x01
#define ATSE_ETH_ADDR_SUPP1 0x02
#define ATSE_ETH_ADDR_SUPP2 0x04
#define ATSE_ETH_ADDR_SUPP3 0x08
#define ATSE_ETH_ADDR_SUPP4 0x10
#define ATSE_ETH_ADDR_ALL 0x1f
- uint16_t atse_watchdog_timer;
- uint16_t atse_tx_m_offset;
- uint16_t atse_tx_buf_len;
- uint16_t atse_rx_buf_len;
int16_t atse_rx_cycles; /* POLLING */
#define RX_CYCLES_IN_INTR 5
uint32_t atse_rx_err[6];
#define ATSE_RX_ERR_FIFO_THRES_EOP 0 /* FIFO threshold reached, on EOP. */
#define ATSE_RX_ERR_ELEN 1 /* Frame/payload length not valid. */
#define ATSE_RX_ERR_CRC32 2 /* CRC-32 error. */
#define ATSE_RX_ERR_FIFO_THRES_TRUNC 3 /* FIFO thresh., truncated frame. */
#define ATSE_RX_ERR_4 4 /* ? */
#define ATSE_RX_ERR_5 5 /* / */
#define ATSE_RX_ERR_MAX 6
struct callout atse_tick;
struct mtx atse_mtx;
+ device_t dev;
+
+ /* xDMA */
+ xdma_controller_t *xdma_tx;
+ xdma_channel_t *xchan_tx;
+ void *ih_tx;
+ int txcount;
+
+ xdma_controller_t *xdma_rx;
+ xdma_channel_t *xchan_rx;
+ void *ih_rx;
+
+ struct buf_ring *br;
+ struct mtx br_mtx;
};
int atse_attach(device_t);
int atse_detach_dev(device_t);
void atse_detach_resources(device_t);
int atse_miibus_readreg(device_t, int, int);
int atse_miibus_writereg(device_t, int, int, int);
void atse_miibus_statchg(device_t);
extern devclass_t atse_devclass;
#endif /* _DEV_IF_ATSEREG_H */
-
-/* end */
Index: head/sys/dts/mips/beripad-de4.dts
===================================================================
--- head/sys/dts/mips/beripad-de4.dts (revision 332473)
+++ head/sys/dts/mips/beripad-de4.dts (revision 332474)
@@ -1,335 +1,336 @@
/*-
* Copyright (c) 2012-2013 Robert N. M. Watson
* Copyright (c) 2013 SRI International
* 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/;
/*
* Device names here have been largely made up on the spot, especially for the
* "compatible" strings, and might want to be revised.
*
* For now, use 32-bit addressing as our Avalon bus is 32-bit. However, in
* the future, we should likely change to 64-bit.
*/
/ {
model = "SRI/Cambridge BeriPad (DE4)";
compatible = "sri-cambridge,beripad-de4";
#address-cells = <1>;
#size-cells = <1>;
cpus {
#address-cells = <1>;
#size-cells = <1>;
/*
* Secondary CPUs all start disabled and use the
* spin-table enable method. cpu-release-addr must be
* specified for each cpu other than cpu@0. Values of
* cpu-release-addr grow down from 0x100000 (kernel).
*/
status = "disabled";
enable-method = "spin-table";
cpu@0 {
device-type = "cpu";
compatible = "sri-cambridge,beri";
reg = <0 1>;
status = "okay";
};
/*
cpu@1 {
device-type = "cpu";
compatible = "sri-cambridge,beri";
reg = <1 1>;
// XXX: should we need cached prefix?
cpu-release-addr = <0xffffffff 0x800fffe0>;
};
*/
};
memory {
device_type = "memory";
reg = <0x0 0x40000000>; // 1G at 0x0
};
cpuintc: cpuintc@0 {
#address-cells = <0>;
#interrupt-cells = <1>;
interrupt-controller;
compatible = "mti,cpu-interrupt-controller";
};
beripic0: beripic@7f804000 {
compatible = "sri-cambridge,beri-pic";
interrupt-controller;
#address-cells = <0>;
#interrupt-cells = <1>;
reg = <0x7f804000 0x400
0x7f806000 0x10
0x7f806080 0x10
0x7f806100 0x10>;
interrupts = < 2 3 4 5 6 >;
hard-interrupt-sources = <64>;
soft-interrupt-sources = <64>;
interrupt-parent = <&cpuintc>;
};
/*
beripic1: beripic@7f808000 {
compatible = "sri-cambridge,beri-pic";
interrupt-controller;
#address-cells = <0>;
#interrupt-cells = <1>;
reg = <0x7f808000 0x400
0x7f80a000 0x10
0x7f80a080 0x10
0x7f80a100 0x10>;
interrupts = < 2 3 4 5 6 >;
hard-interrupt-sources = <64>;
soft-interrupt-sources = <64>;
interrupt-parent = <&cpuintc>;
};
*/
soc {
#address-cells = <1>;
#size-cells = <1>;
#interrupt-cells = <1>;
compatible = "simple-bus", "mips,mips4k";
ranges;
serial@7f002100 {
compatible = "ns16550";
reg = <0x7f002100 0x20>;
reg-shift = <2>;
clock-frequency = <50000000>;
interrupts = <6>;
interrupt-parent = <&beripic0>;
};
serial@7f000000 {
compatible = "altera,jtag_uart-11_0";
reg = <0x7f000000 0x40>;
interrupts = <0>;
interrupt-parent = <&beripic0>;
};
serial@7f001000 {
compatible = "altera,jtag_uart-11_0";
reg = <0x7f001000 0x40>;
};
serial@7f002000 {
compatible = "altera,jtag_uart-11_0";
reg = <0x7f002000 0x40>;
};
sdcard@7f008000 {
compatible = "altera,sdcard_11_2011";
reg = <0x7f008000 0x400>;
};
led@7f006000 {
compatible = "sri-cambridge,de4led";
reg = <0x7f006000 0x1>;
};
/*
* XXX-BZ keep flash before ethernet so that atse can read the
* Ethernet addresses for now.
*/
flash@74000000 {
#address-cells = <1>;
#size-cells = <1>;
compatible = "cfi-flash";
reg = <0x74000000 0x4000000>;
/* Board configuration */
partition@0 {
reg = <0x0 0x20000>;
label = "config";
};
/* Power up FPGA image */
partition@20000 {
reg = <0x20000 0xc00000>;
label = "fpga0";
};
/* Secondary FPGA image (on RE_CONFIGn button) */
partition@C20000 {
reg = <0xc20000 0xc00000>;
label = "fpga1";
};
/* Space for operating system use */
partition@1820000 {
reg = <0x1820000 0x027c0000>;
label = "os";
};
/* Second stage bootloader */
parition@3fe0000 {
reg = <0x3fe0000 0x20000>;
label = "boot";
};
};
msgdma0: msgdma@80004080 {
compatible = "altr,msgdma-16.0", "altr,msgdma-1.0";
reg = <0x80004080 0x00000020>,
<0x800040a0 0x00000020>;
reg-names = "csr", "descriptor_slave";
interrupts = <14>;
interrupt-parent = <&beripic0>;
#dma-cells = <3>;
};
msgdma1: msgdma@80004000 {
compatible = "altr,msgdma-16.0", "altr,msgdma-1.0";
reg = <0x80004000 0x00000020>,
<0x80004020 0x00000020>;
reg-names = "csr", "descriptor_slave";
interrupts = <13>;
interrupt-parent = <&beripic0>;
#dma-cells = <3>;
};
softdma0: softdma@7f007400 {
compatible = "altr,softdma";
reg = < 0x7f007400 0x8 /* tx */
0x7f007420 0x20 >; /* txc */
interrupts = <2>;
interrupt-parent = <&beripic0>;
#dma-cells = <3>;
};
softdma1: softdma@7f007500 {
compatible = "altr,softdma";
reg = < 0x7f007500 0x8 /* rx */
0x7f007520 0x20 >; /* rxc */
interrupts = <1>;
interrupt-parent = <&beripic0>;
#dma-cells = <3>;
};
softdma2: softdma@7f005400 {
compatible = "altr,softdma";
reg = < 0x7f005400 0x8 /* tx */
0x7f005420 0x20 >; /* txc */
interrupts = <12>;
interrupt-parent = <&beripic0>;
#dma-cells = <3>;
};
softdma3: softdma@7f005500 {
compatible = "altr,softdma";
reg = < 0x7f005500 0x8 /* rx */
0x7f005520 0x20 >; /* rxc */
interrupts = <11>;
interrupt-parent = <&beripic0>;
#dma-cells = <3>;
};
+ ethernet@80007000 {
+ compatible = "altera,atse";
+ reg = <0x80007000 0x400>; /* mac */
+ dmas = <&msgdma0 0 0 0xffffffff>,
+ <&msgdma1 1 1 0xffffffff>;
+ dma-names = "tx", "rx";
+ status = "disabled";
+ };
+
ethernet@7f007000 {
compatible = "altera,atse";
- // MAC, RX+RXC, TX+TXC.
- reg = <0x7f007000 0x400
- 0x7f007500 0x8
- 0x7f007520 0x20
- 0x7f007400 0x8
- 0x7f007420 0x20>;
- // RX, TX
- interrupts = <1 2>;
- interrupt-parent = <&beripic0>;
+ reg = <0x7f007000 0x400>; /* mac */
+ dmas = <&softdma0 0 0 0xffffffff>,
+ <&softdma1 1 1 0xffffffff>;
+ dma-names = "tx", "rx";
+ status = "okay";
};
ethernet@7f005000 {
compatible = "altera,atse";
- // MAC, RX+RXC, TX+TXC.
- reg = <0x7f005000 0x400
- 0x7f005500 0x8
- 0x7f005520 0x20
- 0x7f005400 0x8
- 0x7f005420 0x20>;
- // RX, TX
- interrupts = <11 12>;
- interrupt-parent = <&beripic0>;
+ reg = <0x7f005000 0x400>;
+ dmas = <&softdma2 0 0 0xffffffff>,
+ <&softdma3 1 1 0xffffffff>;
+ dma-names = "tx", "rx";
+ status = "disabled";
};
touchscreen@70400000 {
compatible = "sri-cambridge,mtl";
panel-size = < 800 480 >;
reg = <0x70400000 0x1000
0x70000000 0x177000
0x70177000 0x2000>;
};
usb@0x7f100000 {
compatible = "nxp,usb-isp1761";
reg = <0x7f100000 0x40000
0x7f140000 0x4>;
// IRQ 4 is DC, IRQ 5 is HC.
interrupts = <4 5>;
interrupt-parent = <&beripic0>;
};
avgen@0x7f009000 {
compatible = "sri-cambridge,avgen";
reg = <0x7f009000 0x2>;
sri-cambridge,width = <1>;
sri-cambridge,fileio = "r";
sri-cambridge,devname = "de4bsw";
};
avgen@0x7f00a000 {
compatible = "sri-cambridge,avgen";
reg = <0x7f00a000 0x14>;
sri-cambridge,width = <4>;
sri-cambridge,fileio = "rw";
sri-cambridge,devname = "berirom";
};
avgen@0x7f00c000 {
compatible = "sri-cambridge,avgen";
reg = <0x7f00c000 0x8>;
sri-cambridge,width = <4>;
sri-cambridge,fileio = "rw";
sri-cambridge,devname = "de4tempfan";
};
};
};
Index: head/sys/mips/conf/BERI_DE4_BASE
===================================================================
--- head/sys/mips/conf/BERI_DE4_BASE (revision 332473)
+++ head/sys/mips/conf/BERI_DE4_BASE (revision 332474)
@@ -1,52 +1,59 @@
#
# BERI_DE4_BASE -- Kernel for the SRI/Cambridge "BERI" (Bluespec Extensible RISC
# Implementation) FPGA soft core, as configured in its Terasic DE-4 reference
# configuration. This kernel configration must be further specialized to
# to include a root filesystem specification.
#
# $FreeBSD$
#
#NO_UNIVERSE
include "std.BERI"
options NFSCL # Network Filesystem Client
options NFSLOCKD # Network Lock Manager
options NFS_ROOT # NFS usable as /, requires NFSCL
options FDT
options FDT_DTB_STATIC
makeoptions FDT_DTS_FILE=beripad-de4.dts
hints "BERI_DE4.hints" # Flash partitions still use hints.
device altera_atse
device altera_avgen
device altera_jtag_uart
device altera_sdcard
device terasic_de4led
device terasic_mtl
device bpf
device cfi
device cfid
options CFI_SUPPORT_STRATAFLASH
options ATSE_CFI_HACK
device vt
device kbdmux
device uart
device miibus
options DEVICE_POLLING
#
+# DMA support
+#
+device xdma
+device altera_softdma
+device altera_msgdma
+
+#
# USB support
#
#options USB_DEBUG
#options USB_REQ_DEBUG
#options USB_VERBOSE
device usb
device saf1761otg