#ifndef _IF_MVNETAVAR_H_
#define _IF_MVNETAVAR_H_
#include <net/if.h>
#define MVNETA_HWHEADER_SIZE 2
#define MVNETA_ETHER_SIZE 22
#define MVNETA_A370_MAX_CSUM_MTU 1600
#define MVNETA_A3700_MAX_CSUM_MTU 9600
#define MVNETA_MAX_FRAME (MJUM9BYTES)
#define MVNETA_TX_RING_CNT 512
#define MVNETA_RX_RING_CNT 256
#define MVNETA_BUFRING_SIZE 1024
#define MVNETA_PACKET_OFFSET 64
#define MVNETA_RXTH_COUNT 128
#define MVNETA_RX_REFILL_COUNT 8
#define MVNETA_TX_RECLAIM_COUNT 32
#define MVNETA_READ(sc, reg) \
bus_read_4((sc)->res[0], (reg))
#define MVNETA_WRITE(sc, reg, val) \
bus_write_4((sc)->res[0], (reg), (val))
#define MVNETA_READ_REGION(sc, reg, val, c) \
bus_read_region_4((sc)->res[0], (reg), (val), (c))
#define MVNETA_WRITE_REGION(sc, reg, val, c) \
bus_write_region_4((sc)->res[0], (reg), (val), (c))
#define MVNETA_READ_MIB(sc, reg) \
bus_read_4((sc)->res[0], MVNETA_PORTMIB_BASE + (reg))
#define MVNETA_IS_LINKUP(sc) \
(MVNETA_READ((sc), MVNETA_PSR) & MVNETA_PSR_LINKUP)
#define MVNETA_IS_QUEUE_SET(queues, q) \
((((queues) >> (q)) & 0x1))
#define MVNETA_LPI_TS (ETHERMTU * 8 / 1000)
#define MVNETA_LPI_TW (ETHERMTU * 8 / 1000)
#define MVNETA_LPI_LI (ETHERMTU * 8 / 1000)
#define MVNETA_TX_SEGLIMIT 32
#define MVNETA_QUEUE_IDLE 1
#define MVNETA_QUEUE_WORKING 2
#define MVNETA_QUEUE_DISABLED 3
struct mvneta_buf {
struct mbuf * m;
bus_dmamap_t dmap;
};
struct mvneta_rx_ring {
int queue_status;
struct mvneta_rx_desc *desc;
bus_dmamap_t desc_map;
bus_addr_t desc_pa;
void *rxbuf_virt_addr[MVNETA_RX_RING_CNT];
struct mvneta_buf rxbuf[MVNETA_RX_RING_CNT];
struct mtx ring_mtx;
int dma;
int cpu;
int queue_th_received;
int queue_th_time;
struct lro_ctrl lro;
boolean_t lro_enabled;
boolean_t needs_refill;
} __aligned(CACHE_LINE_SIZE);
struct mvneta_tx_ring {
int qidx;
if_t ifp;
struct buf_ring *br;
struct mvneta_tx_desc *desc;
bus_dmamap_t desc_map;
bus_addr_t desc_pa;
struct mvneta_buf txbuf[MVNETA_TX_RING_CNT];
struct mtx ring_mtx;
int used;
int dma;
int cpu;
#define MVNETA_WATCHDOG_TXCOMP (hz / 10)
#define MVNETA_WATCHDOG (10 * hz)
int watchdog_time;
int queue_status;
boolean_t queue_hung;
struct task task;
struct taskqueue *taskq;
uint32_t drv_error;
} __aligned(CACHE_LINE_SIZE);
static __inline int
tx_counter_adv(int ctr, int n)
{
ctr += n;
while (__predict_false(ctr >= MVNETA_TX_RING_CNT))
ctr -= MVNETA_TX_RING_CNT;
return (ctr);
}
static __inline int
rx_counter_adv(int ctr, int n)
{
ctr += n;
while (__predict_false(ctr >= MVNETA_RX_RING_CNT))
ctr -= MVNETA_RX_RING_CNT;
return (ctr);
}
#define MVNETA_PHY_TIMEOUT 10000
#define RX_DISABLE_TIMEOUT 0x1000000
#define TX_DISABLE_TIMEOUT 0x1000000
#define TX_FIFO_EMPTY_TIMEOUT 0x1000000
#define KASSERT_SC_MTX(sc) \
KASSERT(mtx_owned(&(sc)->mtx), ("SC mutex not owned"))
#define KASSERT_BM_MTX(sc) \
KASSERT(mtx_owned(&(sc)->bm.bm_mtx), ("BM mutex not owned"))
#define KASSERT_RX_MTX(sc, q) \
KASSERT(mtx_owned(&(sc)->rx_ring[(q)].ring_mtx),\
("RX mutex not owned"))
#define KASSERT_TX_MTX(sc, q) \
KASSERT(mtx_owned(&(sc)->tx_ring[(q)].ring_mtx),\
("TX mutex not owned"))
struct mvneta_sysctl_queue {
struct mvneta_softc *sc;
int rxtx;
int queue;
};
#define MVNETA_SYSCTL_RX 0
#define MVNETA_SYSCTL_TX 1
struct mvneta_sysctl_mib {
struct mvneta_softc *sc;
int index;
uint64_t counter;
};
enum mvneta_phy_mode {
MVNETA_PHY_QSGMII,
MVNETA_PHY_SGMII,
MVNETA_PHY_RGMII,
MVNETA_PHY_RGMII_ID
};
DECLARE_CLASS(mvneta_driver);
struct mvneta_softc {
device_t dev;
uint32_t version;
struct mtx mtx;
struct resource *res[2];
void *ih_cookie[1];
uint64_t clk_freq;
if_t ifp;
uint32_t mvneta_if_flags;
uint32_t mvneta_media;
uint32_t tx_csum_limit;
uint32_t rx_frame_size;
int phy_attached;
enum mvneta_phy_mode phy_mode;
int phy_addr;
int phy_speed;
boolean_t phy_fdx;
boolean_t autoneg;
boolean_t use_inband_status;
boolean_t linkup;
device_t miibus;
struct mii_data *mii;
uint8_t enaddr[ETHER_ADDR_LEN];
struct ifmedia mvneta_ifmedia;
bus_dma_tag_t rx_dtag;
bus_dma_tag_t rxbuf_dtag;
bus_dma_tag_t tx_dtag;
bus_dma_tag_t txmbuf_dtag;
struct mvneta_rx_ring rx_ring[MVNETA_RX_QNUM_MAX];
struct mvneta_tx_ring tx_ring[MVNETA_TX_QNUM_MAX];
struct callout tick_ch;
int cf_lpi;
int cf_fc;
int debug;
struct mvneta_sysctl_queue sysctl_rx_queue[MVNETA_RX_QNUM_MAX];
struct mvneta_sysctl_queue sysctl_tx_queue[MVNETA_TX_QNUM_MAX];
struct mvneta_sysctl_mib sysctl_mib[MVNETA_PORTMIB_NOCOUNTER];
uint64_t counter_pdfc;
uint64_t counter_pofc;
uint32_t counter_watchdog;
uint32_t counter_watchdog_mib;
};
#define MVNETA_RX_RING(sc, q) \
(&(sc)->rx_ring[(q)])
#define MVNETA_TX_RING(sc, q) \
(&(sc)->tx_ring[(q)])
int mvneta_attach(device_t);
#ifdef FDT
boolean_t mvneta_has_switch_fdt(device_t);
int mvneta_fdt_mac_address(struct mvneta_softc *, uint8_t *);
#endif
#endif