1194246Smarius/*- 2194246Smarius * Copyright (C) 2001 Eduardo Horvath. 3194246Smarius * Copyright (c) 2008 Marius Strobl <marius@FreeBSD.org> 4194246Smarius * All rights reserved. 5194246Smarius * 6194246Smarius * Redistribution and use in source and binary forms, with or without 7194246Smarius * modification, are permitted provided that the following conditions 8194246Smarius * are met: 9194246Smarius * 1. Redistributions of source code must retain the above copyright 10194246Smarius * notice, this list of conditions and the following disclaimer. 11194246Smarius * 2. Redistributions in binary form must reproduce the above copyright 12194246Smarius * notice, this list of conditions and the following disclaimer in the 13194246Smarius * documentation and/or other materials provided with the distribution. 14194246Smarius * 15194246Smarius * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND 16194246Smarius * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17194246Smarius * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18194246Smarius * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE 19194246Smarius * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20194246Smarius * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21194246Smarius * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22194246Smarius * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23194246Smarius * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24194246Smarius * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25194246Smarius * SUCH DAMAGE. 26194246Smarius * 27194246Smarius * from: NetBSD: gemvar.h,v 1.8 2002/05/15 02:36:12 matt Exp 28194246Smarius * from: FreeBSD: if_gemvar.h 177560 2008-03-24 17:23:53Z marius 29194246Smarius * 30194246Smarius * $FreeBSD$ 31194246Smarius */ 32194246Smarius 33194246Smarius#ifndef _IF_CASVAR_H 34194246Smarius#define _IF_CASVAR_H 35194246Smarius 36194246Smarius/* 37194246Smarius * The page size is configurable, but needs to be at least 8k (the 38194246Smarius * default) in order to also support jumbo buffers. 39194246Smarius */ 40194246Smarius#define CAS_PAGE_SIZE 8192 41194246Smarius 42194246Smarius/* 43194246Smarius * Transmit descriptor ring size - this is arbitrary, but allocate 44194246Smarius * enough descriptors for 64 pending transmissions and 16 segments 45194246Smarius * per packet. This limit is not actually enforced (packets with 46194246Smarius * more segments can be sent, depending on the busdma backend); it 47194246Smarius * is however used as an estimate for the TX window size. 48194246Smarius */ 49194246Smarius#define CAS_NTXSEGS 16 50194246Smarius 51194246Smarius#define CAS_TXQUEUELEN 64 52194246Smarius#define CAS_NTXDESC (CAS_TXQUEUELEN * CAS_NTXSEGS) 53194246Smarius#define CAS_MAXTXFREE (CAS_NTXDESC - 1) 54194246Smarius#define CAS_NTXDESC_MASK (CAS_NTXDESC - 1) 55194246Smarius#define CAS_NEXTTX(x) ((x + 1) & CAS_NTXDESC_MASK) 56194246Smarius 57194246Smarius/* 58194246Smarius * Receive completion ring size - we have one completion per 59249583Sgabor * incoming packet (though the opposite isn't necessarily true), 60194246Smarius * so this logic is a little simpler. 61194246Smarius */ 62194246Smarius#define CAS_NRXCOMP 4096 63194246Smarius#define CAS_NRXCOMP_MASK (CAS_NRXCOMP - 1) 64194246Smarius#define CAS_NEXTRXCOMP(x) ((x + 1) & CAS_NRXCOMP_MASK) 65194246Smarius 66194246Smarius/* 67194246Smarius * Receive descriptor ring sizes - for Cassini+ and Saturn both 68194246Smarius * rings must be at least initialized. 69194246Smarius */ 70194246Smarius#define CAS_NRXDESC 1024 71194246Smarius#define CAS_NRXDESC_MASK (CAS_NRXDESC - 1) 72194246Smarius#define CAS_NEXTRXDESC(x) ((x + 1) & CAS_NRXDESC_MASK) 73194246Smarius#define CAS_NRXDESC2 32 74194246Smarius#define CAS_NRXDESC2_MASK (CAS_NRXDESC2 - 1) 75194246Smarius#define CAS_NEXTRXDESC2(x) ((x + 1) & CAS_NRXDESC2_MASK) 76194246Smarius 77194246Smarius/* 78194246Smarius * How many ticks to wait until to retry on a RX descriptor that is 79194246Smarius * still owned by the hardware. 80194246Smarius */ 81194246Smarius#define CAS_RXOWN_TICKS (hz / 50) 82194246Smarius 83194246Smarius/* 84194246Smarius * Control structures are DMA'd to the chip. We allocate them 85194246Smarius * in a single clump that maps to a single DMA segment to make 86194246Smarius * several things easier. 87194246Smarius */ 88194246Smariusstruct cas_control_data { 89194246Smarius struct cas_desc ccd_txdescs[CAS_NTXDESC]; /* TX descriptors */ 90194246Smarius struct cas_rx_comp ccd_rxcomps[CAS_NRXCOMP]; /* RX completions */ 91194246Smarius struct cas_desc ccd_rxdescs[CAS_NRXDESC]; /* RX descriptors */ 92194246Smarius struct cas_desc ccd_rxdescs2[CAS_NRXDESC2]; /* RX descriptors 2 */ 93194246Smarius}; 94194246Smarius 95194246Smarius#define CAS_CDOFF(x) offsetof(struct cas_control_data, x) 96194246Smarius#define CAS_CDTXDOFF(x) CAS_CDOFF(ccd_txdescs[(x)]) 97194246Smarius#define CAS_CDRXCOFF(x) CAS_CDOFF(ccd_rxcomps[(x)]) 98194246Smarius#define CAS_CDRXDOFF(x) CAS_CDOFF(ccd_rxdescs[(x)]) 99194246Smarius#define CAS_CDRXD2OFF(x) CAS_CDOFF(ccd_rxdescs2[(x)]) 100194246Smarius 101194246Smarius/* 102194246Smarius * software state for transmit job mbufs (may be elements of mbuf chains) 103194246Smarius */ 104194246Smariusstruct cas_txsoft { 105194246Smarius struct mbuf *txs_mbuf; /* head of our mbuf chain */ 106194246Smarius bus_dmamap_t txs_dmamap; /* our DMA map */ 107194246Smarius u_int txs_firstdesc; /* first descriptor in packet */ 108194246Smarius u_int txs_lastdesc; /* last descriptor in packet */ 109194246Smarius u_int txs_ndescs; /* number of descriptors */ 110194246Smarius STAILQ_ENTRY(cas_txsoft) txs_q; 111194246Smarius}; 112194246Smarius 113194246SmariusSTAILQ_HEAD(cas_txsq, cas_txsoft); 114194246Smarius 115194246Smarius/* 116194246Smarius * software state for receive descriptors 117194246Smarius */ 118194246Smariusstruct cas_rxdsoft { 119194246Smarius void *rxds_buf; /* receive buffer */ 120194246Smarius bus_dmamap_t rxds_dmamap; /* our DMA map */ 121194246Smarius bus_addr_t rxds_paddr; /* physical address of the segment */ 122194246Smarius#if __FreeBSD_version < 800016 123194246Smarius struct cas_softc *rxds_sc; /* softc pointer */ 124194246Smarius u_int rxds_idx; /* our index */ 125194246Smarius#endif 126194246Smarius u_int rxds_refcount; /* hardware + mbuf references */ 127194246Smarius}; 128194246Smarius 129194246Smarius/* 130194246Smarius * software state per device 131194246Smarius */ 132194246Smariusstruct cas_softc { 133194246Smarius struct ifnet *sc_ifp; 134194246Smarius struct mtx sc_mtx; 135194246Smarius device_t sc_miibus; 136194246Smarius struct mii_data *sc_mii; /* MII media control */ 137194246Smarius device_t sc_dev; /* generic device information */ 138194246Smarius u_char sc_enaddr[ETHER_ADDR_LEN]; 139194246Smarius struct callout sc_tick_ch; /* tick callout */ 140194246Smarius struct callout sc_rx_ch; /* delayed RX callout */ 141194904Smarius struct task sc_intr_task; 142194904Smarius struct task sc_tx_task; 143194904Smarius struct taskqueue *sc_tq; 144194246Smarius u_int sc_wdog_timer; /* watchdog timer */ 145194246Smarius 146194246Smarius void *sc_ih; 147194246Smarius struct resource *sc_res[2]; 148194246Smarius#define CAS_RES_INTR 0 149194246Smarius#define CAS_RES_MEM 1 150194246Smarius 151194246Smarius bus_dma_tag_t sc_pdmatag; /* parent bus DMA tag */ 152194246Smarius bus_dma_tag_t sc_rdmatag; /* RX bus DMA tag */ 153194246Smarius bus_dma_tag_t sc_tdmatag; /* TX bus DMA tag */ 154194246Smarius bus_dma_tag_t sc_cdmatag; /* control data bus DMA tag */ 155194246Smarius bus_dmamap_t sc_dmamap; /* bus DMA handle */ 156194246Smarius 157194246Smarius u_int sc_variant; 158194246Smarius#define CAS_UNKNOWN 0 /* don't know */ 159194246Smarius#define CAS_CAS 1 /* Sun Cassini */ 160194246Smarius#define CAS_CASPLUS 2 /* Sun Cassini+ */ 161194246Smarius#define CAS_SATURN 3 /* National Semiconductor Saturn */ 162194246Smarius 163194246Smarius u_int sc_flags; 164194246Smarius#define CAS_INITED (1 << 0) /* reset persistent regs init'ed */ 165194246Smarius#define CAS_NO_CSUM (1 << 1) /* don't use hardware checksumming */ 166194246Smarius#define CAS_LINK (1 << 2) /* link is up */ 167194246Smarius#define CAS_REG_PLUS (1 << 3) /* has Cassini+ registers */ 168194246Smarius#define CAS_SERDES (1 << 4) /* use the SERDES */ 169194246Smarius#define CAS_TABORT (1 << 5) /* has target abort issues */ 170194246Smarius 171194246Smarius bus_dmamap_t sc_cddmamap; /* control data DMA map */ 172194246Smarius bus_addr_t sc_cddma; 173194246Smarius 174194246Smarius /* 175194246Smarius * software state for transmit and receive descriptors 176194246Smarius */ 177194246Smarius struct cas_txsoft sc_txsoft[CAS_TXQUEUELEN]; 178194246Smarius struct cas_rxdsoft sc_rxdsoft[CAS_NRXDESC]; 179194246Smarius 180194246Smarius /* 181194246Smarius * control data structures 182194246Smarius */ 183194246Smarius struct cas_control_data *sc_control_data; 184194246Smarius#define sc_txdescs sc_control_data->ccd_txdescs 185194246Smarius#define sc_rxcomps sc_control_data->ccd_rxcomps 186194246Smarius#define sc_rxdescs sc_control_data->ccd_rxdescs 187194246Smarius#define sc_rxdescs2 sc_control_data->ccd_rxdescs2 188194246Smarius 189194246Smarius u_int sc_txfree; /* number of free TX descriptors */ 190194246Smarius u_int sc_txnext; /* next ready TX descriptor */ 191194246Smarius u_int sc_txwin; /* TX desc. since last TX intr. */ 192194246Smarius 193194246Smarius struct cas_txsq sc_txfreeq; /* free software TX descriptors */ 194194246Smarius struct cas_txsq sc_txdirtyq; /* dirty software TX descriptors */ 195194246Smarius 196194246Smarius u_int sc_rxcptr; /* next ready RX completion */ 197194246Smarius u_int sc_rxdptr; /* next ready RX descriptor */ 198194246Smarius 199223951Smarius uint32_t sc_mac_rxcfg; /* RX MAC conf. % CAS_MAC_RX_CONF_EN */ 200223951Smarius 201194246Smarius int sc_ifflags; 202194246Smarius}; 203194246Smarius 204194246Smarius#define CAS_BARRIER(sc, offs, len, flags) \ 205194246Smarius bus_barrier((sc)->sc_res[CAS_RES_MEM], (offs), (len), (flags)) 206194246Smarius 207194246Smarius#define CAS_READ_N(n, sc, offs) \ 208194246Smarius bus_read_ ## n((sc)->sc_res[CAS_RES_MEM], (offs)) 209194246Smarius#define CAS_READ_1(sc, offs) CAS_READ_N(1, (sc), (offs)) 210194246Smarius#define CAS_READ_2(sc, offs) CAS_READ_N(2, (sc), (offs)) 211194246Smarius#define CAS_READ_4(sc, offs) CAS_READ_N(4, (sc), (offs)) 212194246Smarius 213194246Smarius#define CAS_WRITE_N(n, sc, offs, v) \ 214194246Smarius bus_write_ ## n((sc)->sc_res[CAS_RES_MEM], (offs), (v)) 215194246Smarius#define CAS_WRITE_1(sc, offs, v) CAS_WRITE_N(1, (sc), (offs), (v)) 216194246Smarius#define CAS_WRITE_2(sc, offs, v) CAS_WRITE_N(2, (sc), (offs), (v)) 217194246Smarius#define CAS_WRITE_4(sc, offs, v) CAS_WRITE_N(4, (sc), (offs), (v)) 218194246Smarius 219194246Smarius#define CAS_CDTXDADDR(sc, x) ((sc)->sc_cddma + CAS_CDTXDOFF((x))) 220194246Smarius#define CAS_CDRXCADDR(sc, x) ((sc)->sc_cddma + CAS_CDRXCOFF((x))) 221194246Smarius#define CAS_CDRXDADDR(sc, x) ((sc)->sc_cddma + CAS_CDRXDOFF((x))) 222194246Smarius#define CAS_CDRXD2ADDR(sc, x) ((sc)->sc_cddma + CAS_CDRXD2OFF((x))) 223194246Smarius 224194246Smarius#define CAS_CDSYNC(sc, ops) \ 225194246Smarius bus_dmamap_sync((sc)->sc_cdmatag, (sc)->sc_cddmamap, (ops)); 226194246Smarius 227194246Smarius#define __CAS_UPDATE_RXDESC(rxd, rxds, s) \ 228194246Smariusdo { \ 229194246Smarius \ 230194246Smarius refcount_init(&(rxds)->rxds_refcount, 1); \ 231194246Smarius (rxd)->cd_buf_ptr = htole64((rxds)->rxds_paddr); \ 232194246Smarius KASSERT((s) < CAS_RD_BUF_INDEX_MASK >> CAS_RD_BUF_INDEX_SHFT, \ 233194246Smarius ("%s: RX buffer index too large!", __func__)); \ 234194246Smarius (rxd)->cd_flags = \ 235194246Smarius htole64((uint64_t)((s) << CAS_RD_BUF_INDEX_SHFT)); \ 236194246Smarius} while (0) 237194246Smarius 238194246Smarius#define CAS_UPDATE_RXDESC(sc, d, s) \ 239194246Smarius __CAS_UPDATE_RXDESC(&(sc)->sc_rxdescs[(d)], \ 240194246Smarius &(sc)->sc_rxdsoft[(s)], (s)) 241194246Smarius 242194246Smarius#if __FreeBSD_version < 800016 243194246Smarius#define CAS_INIT_RXDESC(sc, d, s) \ 244194246Smariusdo { \ 245194246Smarius struct cas_rxdsoft *__rxds = &(sc)->sc_rxdsoft[(s)]; \ 246194246Smarius \ 247194246Smarius __rxds->rxds_sc = (sc); \ 248194246Smarius __rxds->rxds_idx = (s); \ 249194246Smarius __CAS_UPDATE_RXDESC(&(sc)->sc_rxdescs[(d)], __rxds, (s)); \ 250194246Smarius} while (0) 251194246Smarius#else 252194246Smarius#define CAS_INIT_RXDESC(sc, d, s) CAS_UPDATE_RXDESC(sc, d, s) 253194246Smarius#endif 254194246Smarius 255194246Smarius#define CAS_LOCK_INIT(_sc, _name) \ 256194246Smarius mtx_init(&(_sc)->sc_mtx, _name, MTX_NETWORK_LOCK, MTX_DEF) 257194246Smarius#define CAS_LOCK(_sc) mtx_lock(&(_sc)->sc_mtx) 258194246Smarius#define CAS_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_mtx) 259194246Smarius#define CAS_LOCK_ASSERT(_sc, _what) mtx_assert(&(_sc)->sc_mtx, (_what)) 260194246Smarius#define CAS_LOCK_DESTROY(_sc) mtx_destroy(&(_sc)->sc_mtx) 261194246Smarius#define CAS_LOCK_OWNED(_sc) mtx_owned(&(_sc)->sc_mtx) 262194246Smarius 263194246Smarius#endif 264