/*-1* SPDX-License-Identifier: BSD-2-Clause2*3* Copyright (C) 2001 Eduardo Horvath.4* Copyright (c) 2008 Marius Strobl <[email protected]>5* All rights reserved.6*7* Redistribution and use in source and binary forms, with or without8* modification, are permitted provided that the following conditions9* are met:10* 1. Redistributions of source code must retain the above copyright11* notice, this list of conditions and the following disclaimer.12* 2. Redistributions in binary form must reproduce the above copyright13* notice, this list of conditions and the following disclaimer in the14* documentation and/or other materials provided with the distribution.15*16* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND17* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE18* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE19* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE20* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL21* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS22* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)23* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT24* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY25* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF26* SUCH DAMAGE.27*28* from: NetBSD: gemvar.h,v 1.8 2002/05/15 02:36:12 matt Exp29* from: FreeBSD: if_gemvar.h 177560 2008-03-24 17:23:53Z marius30*/3132#ifndef _IF_CASVAR_H33#define _IF_CASVAR_H3435/*36* The page size is configurable, but needs to be at least 8k (the37* default) in order to also support jumbo buffers.38*/39#define CAS_PAGE_SIZE 81924041/*42* Transmit descriptor ring size - this is arbitrary, but allocate43* enough descriptors for 64 pending transmissions and 16 segments44* per packet. This limit is not actually enforced (packets with45* more segments can be sent, depending on the busdma backend); it46* is however used as an estimate for the TX window size.47*/48#define CAS_NTXSEGS 164950#define CAS_TXQUEUELEN 6451#define CAS_NTXDESC (CAS_TXQUEUELEN * CAS_NTXSEGS)52#define CAS_MAXTXFREE (CAS_NTXDESC - 1)53#define CAS_NTXDESC_MASK (CAS_NTXDESC - 1)54#define CAS_NEXTTX(x) ((x + 1) & CAS_NTXDESC_MASK)5556/*57* Receive completion ring size - we have one completion per58* incoming packet (though the opposite isn't necessarily true),59* so this logic is a little simpler.60*/61#define CAS_NRXCOMP 409662#define CAS_NRXCOMP_MASK (CAS_NRXCOMP - 1)63#define CAS_NEXTRXCOMP(x) ((x + 1) & CAS_NRXCOMP_MASK)6465/*66* Receive descriptor ring sizes - for Cassini+ and Saturn both67* rings must be at least initialized.68*/69#define CAS_NRXDESC 102470#define CAS_NRXDESC_MASK (CAS_NRXDESC - 1)71#define CAS_NEXTRXDESC(x) ((x + 1) & CAS_NRXDESC_MASK)72#define CAS_NRXDESC2 3273#define CAS_NRXDESC2_MASK (CAS_NRXDESC2 - 1)74#define CAS_NEXTRXDESC2(x) ((x + 1) & CAS_NRXDESC2_MASK)7576/*77* How many ticks to wait until to retry on a RX descriptor that is78* still owned by the hardware.79*/80#define CAS_RXOWN_TICKS (hz / 50)8182/*83* Control structures are DMA'd to the chip. We allocate them84* in a single clump that maps to a single DMA segment to make85* several things easier.86*/87struct cas_control_data {88struct cas_desc ccd_txdescs[CAS_NTXDESC]; /* TX descriptors */89struct cas_rx_comp ccd_rxcomps[CAS_NRXCOMP]; /* RX completions */90struct cas_desc ccd_rxdescs[CAS_NRXDESC]; /* RX descriptors */91struct cas_desc ccd_rxdescs2[CAS_NRXDESC2]; /* RX descriptors 2 */92};9394#define CAS_CDOFF(x) offsetof(struct cas_control_data, x)95#define CAS_CDTXDOFF(x) CAS_CDOFF(ccd_txdescs[(x)])96#define CAS_CDRXCOFF(x) CAS_CDOFF(ccd_rxcomps[(x)])97#define CAS_CDRXDOFF(x) CAS_CDOFF(ccd_rxdescs[(x)])98#define CAS_CDRXD2OFF(x) CAS_CDOFF(ccd_rxdescs2[(x)])99100/*101* software state for transmit job mbufs (may be elements of mbuf chains)102*/103struct cas_txsoft {104struct mbuf *txs_mbuf; /* head of our mbuf chain */105bus_dmamap_t txs_dmamap; /* our DMA map */106u_int txs_firstdesc; /* first descriptor in packet */107u_int txs_lastdesc; /* last descriptor in packet */108u_int txs_ndescs; /* number of descriptors */109STAILQ_ENTRY(cas_txsoft) txs_q;110};111112STAILQ_HEAD(cas_txsq, cas_txsoft);113114/*115* software state for receive descriptors116*/117struct cas_rxdsoft {118void *rxds_buf; /* receive buffer */119bus_dmamap_t rxds_dmamap; /* our DMA map */120bus_addr_t rxds_paddr; /* physical address of the segment */121u_int rxds_refcount; /* hardware + mbuf references */122};123124/*125* software state per device126*/127struct cas_softc {128if_t sc_ifp;129struct mtx sc_mtx;130device_t sc_miibus;131struct mii_data *sc_mii; /* MII media control */132device_t sc_dev; /* generic device information */133u_char sc_enaddr[ETHER_ADDR_LEN];134struct callout sc_tick_ch; /* tick callout */135struct callout sc_rx_ch; /* delayed RX callout */136struct task sc_intr_task;137struct task sc_tx_task;138struct taskqueue *sc_tq;139u_int sc_wdog_timer; /* watchdog timer */140141void *sc_ih;142struct resource *sc_res[2];143#define CAS_RES_INTR 0144#define CAS_RES_MEM 1145146bus_dma_tag_t sc_pdmatag; /* parent bus DMA tag */147bus_dma_tag_t sc_rdmatag; /* RX bus DMA tag */148bus_dma_tag_t sc_tdmatag; /* TX bus DMA tag */149bus_dma_tag_t sc_cdmatag; /* control data bus DMA tag */150bus_dmamap_t sc_dmamap; /* bus DMA handle */151152u_int sc_variant;153#define CAS_UNKNOWN 0 /* don't know */154#define CAS_CAS 1 /* Sun Cassini */155#define CAS_CASPLUS 2 /* Sun Cassini+ */156#define CAS_SATURN 3 /* National Semiconductor Saturn */157158u_int sc_flags;159#define CAS_INITED (1 << 0) /* reset persistent regs init'ed */160#define CAS_NO_CSUM (1 << 1) /* don't use hardware checksumming */161#define CAS_LINK (1 << 2) /* link is up */162#define CAS_REG_PLUS (1 << 3) /* has Cassini+ registers */163#define CAS_SERDES (1 << 4) /* use the SERDES */164#define CAS_TABORT (1 << 5) /* has target abort issues */165166bus_dmamap_t sc_cddmamap; /* control data DMA map */167bus_addr_t sc_cddma;168169/*170* software state for transmit and receive descriptors171*/172struct cas_txsoft sc_txsoft[CAS_TXQUEUELEN];173struct cas_rxdsoft sc_rxdsoft[CAS_NRXDESC];174175/*176* control data structures177*/178struct cas_control_data *sc_control_data;179#define sc_txdescs sc_control_data->ccd_txdescs180#define sc_rxcomps sc_control_data->ccd_rxcomps181#define sc_rxdescs sc_control_data->ccd_rxdescs182#define sc_rxdescs2 sc_control_data->ccd_rxdescs2183184u_int sc_txfree; /* number of free TX descriptors */185u_int sc_txnext; /* next ready TX descriptor */186u_int sc_txwin; /* TX desc. since last TX intr. */187188struct cas_txsq sc_txfreeq; /* free software TX descriptors */189struct cas_txsq sc_txdirtyq; /* dirty software TX descriptors */190191u_int sc_rxcptr; /* next ready RX completion */192u_int sc_rxdptr; /* next ready RX descriptor */193194uint32_t sc_mac_rxcfg; /* RX MAC conf. % CAS_MAC_RX_CONF_EN */195196int sc_ifflags;197};198199#define CAS_BARRIER(sc, offs, len, flags) \200bus_barrier((sc)->sc_res[CAS_RES_MEM], (offs), (len), (flags))201202#define CAS_READ_N(n, sc, offs) \203bus_read_ ## n((sc)->sc_res[CAS_RES_MEM], (offs))204#define CAS_READ_1(sc, offs) CAS_READ_N(1, (sc), (offs))205#define CAS_READ_2(sc, offs) CAS_READ_N(2, (sc), (offs))206#define CAS_READ_4(sc, offs) CAS_READ_N(4, (sc), (offs))207208#define CAS_WRITE_N(n, sc, offs, v) \209bus_write_ ## n((sc)->sc_res[CAS_RES_MEM], (offs), (v))210#define CAS_WRITE_1(sc, offs, v) CAS_WRITE_N(1, (sc), (offs), (v))211#define CAS_WRITE_2(sc, offs, v) CAS_WRITE_N(2, (sc), (offs), (v))212#define CAS_WRITE_4(sc, offs, v) CAS_WRITE_N(4, (sc), (offs), (v))213214#define CAS_CDTXDADDR(sc, x) ((sc)->sc_cddma + CAS_CDTXDOFF((x)))215#define CAS_CDRXCADDR(sc, x) ((sc)->sc_cddma + CAS_CDRXCOFF((x)))216#define CAS_CDRXDADDR(sc, x) ((sc)->sc_cddma + CAS_CDRXDOFF((x)))217#define CAS_CDRXD2ADDR(sc, x) ((sc)->sc_cddma + CAS_CDRXD2OFF((x)))218219#define CAS_CDSYNC(sc, ops) \220bus_dmamap_sync((sc)->sc_cdmatag, (sc)->sc_cddmamap, (ops));221222#define __CAS_UPDATE_RXDESC(rxd, rxds, s) \223do { \224\225refcount_init(&(rxds)->rxds_refcount, 1); \226(rxd)->cd_buf_ptr = htole64((rxds)->rxds_paddr); \227KASSERT((s) < CAS_RD_BUF_INDEX_MASK >> CAS_RD_BUF_INDEX_SHFT, \228("%s: RX buffer index too large!", __func__)); \229(rxd)->cd_flags = \230htole64((uint64_t)((s) << CAS_RD_BUF_INDEX_SHFT)); \231} while (0)232233#define CAS_UPDATE_RXDESC(sc, d, s) \234__CAS_UPDATE_RXDESC(&(sc)->sc_rxdescs[(d)], \235&(sc)->sc_rxdsoft[(s)], (s))236237#define CAS_INIT_RXDESC(sc, d, s) CAS_UPDATE_RXDESC(sc, d, s)238239#define CAS_LOCK_INIT(_sc, _name) \240mtx_init(&(_sc)->sc_mtx, _name, MTX_NETWORK_LOCK, MTX_DEF)241#define CAS_LOCK(_sc) mtx_lock(&(_sc)->sc_mtx)242#define CAS_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_mtx)243#define CAS_LOCK_ASSERT(_sc, _what) mtx_assert(&(_sc)->sc_mtx, (_what))244#define CAS_LOCK_DESTROY(_sc) mtx_destroy(&(_sc)->sc_mtx)245#define CAS_LOCK_OWNED(_sc) mtx_owned(&(_sc)->sc_mtx)246247#endif248249250