if_tsec.h revision 194101
1193323Sed/*-
2193323Sed * Copyright (C) 2006-2007 Semihalf, Piotr Kruszynski <ppk@semihalf.com>
3193323Sed * All rights reserved.
4193323Sed *
5193323Sed * Redistribution and use in source and binary forms, with or without
6193323Sed * modification, are permitted provided that the following conditions
7193323Sed * are met:
8193323Sed * 1. Redistributions of source code must retain the above copyright
9193323Sed *    notice, this list of conditions and the following disclaimer.
10193323Sed * 2. Redistributions in binary form must reproduce the above copyright
11193323Sed *    notice, this list of conditions and the following disclaimer in the
12193323Sed *    documentation and/or other materials provided with the distribution.
13193323Sed *
14193323Sed * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15193323Sed * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16193323Sed * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
17193323Sed * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
18218893Sdim * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
19249423Sdim * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20263508Sdim * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
21249423Sdim * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
22193323Sed * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
23193323Sed * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24193323Sed *
25263508Sdim * $FreeBSD: head/sys/dev/tsec/if_tsec.h 194101 2009-06-13 08:57:04Z raj $
26234353Sdim */
27193323Sed
28193323Sed#ifndef _IF_TSEC_H
29193323Sed#define _IF_TSEC_H
30193323Sed
31263508Sdim#define TSEC_RX_NUM_DESC	256
32263508Sdim#define TSEC_TX_NUM_DESC	256
33263508Sdim
34263508Sdim/* Interrupt Coalescing types */
35263508Sdim#define	TSEC_IC_RX		0
36226633Sdim#define	TSEC_IC_TX		1
37263508Sdim
38263508Sdim/* eTSEC ID */
39263508Sdim#define	TSEC_ETSEC_ID		0x0124
40263508Sdim
41263508Sdim/* Frame sizes */
42263508Sdim#define	TSEC_MIN_FRAME_SIZE	64
43263508Sdim#define	TSEC_MAX_FRAME_SIZE	9600
44226633Sdim
45226633Sdimstruct tsec_softc {
46226633Sdim	/* XXX MII bus requires that struct ifnet is first!!! */
47226633Sdim	struct ifnet	*tsec_ifp;
48234353Sdim
49234353Sdim	struct mtx	transmit_lock;	/* transmitter lock */
50234353Sdim	struct mtx	receive_lock;	/* receiver lock */
51234353Sdim
52234353Sdim	device_t	dev;
53218893Sdim	device_t	tsec_miibus;
54193323Sed	struct mii_data	*tsec_mii;	/* MII media control */
55193323Sed	int		tsec_link;
56193323Sed
57218893Sdim	bus_dma_tag_t	tsec_tx_dtag;	/* TX descriptors tag */
58218893Sdim	bus_dmamap_t	tsec_tx_dmap;	/* TX descriptors map */
59193323Sed	struct tsec_desc *tsec_tx_vaddr;/* vadress of TX descriptors */
60194612Sed	uint32_t	tsec_tx_raddr;	/* real adress of TX descriptors */
61194612Sed
62194612Sed	bus_dma_tag_t	tsec_rx_dtag;	/* RX descriptors tag */
63194612Sed	bus_dmamap_t	tsec_rx_dmap;	/* RX descriptors map */
64194612Sed	struct tsec_desc *tsec_rx_vaddr; /* vadress of RX descriptors */
65194612Sed	uint32_t	tsec_rx_raddr;	/* real adress of RX descriptors */
66194612Sed
67218893Sdim	bus_dma_tag_t	tsec_tx_mtag;	/* TX mbufs tag */
68234353Sdim	bus_dma_tag_t	tsec_rx_mtag;	/* TX mbufs tag */
69193323Sed
70193323Sed	struct rx_data_type {
71234353Sdim		bus_dmamap_t	map;	/* mbuf map */
72234353Sdim		struct mbuf	*mbuf;
73239462Sdim		uint32_t	paddr;	/* DMA addres of buffer */
74239462Sdim	} rx_data[TSEC_RX_NUM_DESC];
75239462Sdim
76239462Sdim	uint32_t	tx_cur_desc_cnt;
77239462Sdim	uint32_t	tx_dirty_desc_cnt;
78239462Sdim	uint32_t	rx_cur_desc_cnt;
79239462Sdim
80239462Sdim	struct resource	*sc_rres;	/* register resource */
81239462Sdim	int		sc_rrid;	/* register rid */
82239462Sdim	struct {
83239462Sdim		bus_space_tag_t bst;
84239462Sdim		bus_space_handle_t bsh;
85239462Sdim	} sc_bas;
86239462Sdim
87239462Sdim	struct resource *sc_transmit_ires;
88239462Sdim	void		*sc_transmit_ihand;
89239462Sdim	int		sc_transmit_irid;
90239462Sdim	struct resource *sc_receive_ires;
91239462Sdim	void		*sc_receive_ihand;
92239462Sdim	int		sc_receive_irid;
93243830Sdim	struct resource *sc_error_ires;
94193323Sed	void		*sc_error_ihand;
95193323Sed	int		sc_error_irid;
96193323Sed
97193323Sed	int		tsec_if_flags;
98243830Sdim	int		is_etsec;
99243830Sdim
100243830Sdim	/* Watchdog and MII tick related */
101243830Sdim	struct callout	tsec_callout;
102234353Sdim	int		tsec_watchdog;
103243830Sdim
104243830Sdim	/* TX maps */
105243830Sdim	bus_dmamap_t	tx_map_data[TSEC_TX_NUM_DESC];
106243830Sdim
107234353Sdim	/* unused TX maps data */
108234353Sdim	uint32_t	tx_map_unused_get_cnt;
109234353Sdim	uint32_t	tx_map_unused_put_cnt;
110234353Sdim	bus_dmamap_t	*tx_map_unused_data[TSEC_TX_NUM_DESC];
111234353Sdim
112234353Sdim	/* used TX maps data */
113234353Sdim	uint32_t	tx_map_used_get_cnt;
114234353Sdim	uint32_t	tx_map_used_put_cnt;
115249423Sdim	bus_dmamap_t	*tx_map_used_data[TSEC_TX_NUM_DESC];
116249423Sdim
117249423Sdim	/* mbufs in TX queue */
118249423Sdim	uint32_t	tx_mbuf_used_get_cnt;
119193323Sed	uint32_t	tx_mbuf_used_put_cnt;
120234353Sdim	struct mbuf	*tx_mbuf_used_data[TSEC_TX_NUM_DESC];
121243830Sdim
122243830Sdim	/* interrupt coalescing */
123193323Sed	struct mtx	ic_lock;
124263508Sdim	uint32_t	rx_ic_time;	/* RW, valid values 0..65535 */
125193323Sed	uint32_t	rx_ic_count;	/* RW, valid values 0..255 */
126226633Sdim	uint32_t	tx_ic_time;
127263508Sdim	uint32_t	tx_ic_count;
128263508Sdim
129263508Sdim	/* currently received frame */
130263508Sdim	struct mbuf	*frame;
131263508Sdim};
132263508Sdim
133263508Sdim/* interface to get/put generic objects */
134263508Sdim#define TSEC_CNT_INIT(cnt, wrap) ((cnt) = ((wrap) - 1))
135263508Sdim
136263508Sdim#define TSEC_INC(count, wrap) (count = ((count) + 1) & ((wrap) - 1))
137263508Sdim
138263508Sdim#define TSEC_GET_GENERIC(hand, tab, count, wrap) \
139263508Sdim		((hand)->tab[TSEC_INC((hand)->count, wrap)])
140263508Sdim
141263508Sdim#define TSEC_PUT_GENERIC(hand, tab, count, wrap, val)	\
142263508Sdim		((hand)->tab[TSEC_INC((hand)->count, wrap)] = val)
143263508Sdim
144263508Sdim#define TSEC_BACK_GENERIC(sc, count, wrap) do {			\
145263508Sdim		if ((sc)->count > 0)				\
146263508Sdim			(sc)->count--;				\
147263508Sdim		else						\
148193323Sed			(sc)->count = (wrap) - 1;		\
149226633Sdim} while (0)
150226633Sdim
151226633Sdim/* TX maps interface */
152226633Sdim#define TSEC_TX_MAP_CNT_INIT(sc) do {						\
153226633Sdim		TSEC_CNT_INIT((sc)->tx_map_unused_get_cnt, TSEC_TX_NUM_DESC);	\
154226633Sdim		TSEC_CNT_INIT((sc)->tx_map_unused_put_cnt, TSEC_TX_NUM_DESC);	\
155226633Sdim		TSEC_CNT_INIT((sc)->tx_map_used_get_cnt, TSEC_TX_NUM_DESC);	\
156226633Sdim		TSEC_CNT_INIT((sc)->tx_map_used_put_cnt, TSEC_TX_NUM_DESC);	\
157226633Sdim} while (0)
158226633Sdim
159226633Sdim/* interface to get/put unused TX maps */
160226633Sdim#define TSEC_ALLOC_TX_MAP(sc)							\
161226633Sdim		TSEC_GET_GENERIC(sc, tx_map_unused_data, tx_map_unused_get_cnt,	\
162226633Sdim		TSEC_TX_NUM_DESC)
163226633Sdim
164234353Sdim#define TSEC_FREE_TX_MAP(sc, val)						\
165234353Sdim		TSEC_PUT_GENERIC(sc, tx_map_unused_data, tx_map_unused_put_cnt,	\
166234353Sdim		TSEC_TX_NUM_DESC, val)
167234353Sdim
168234353Sdim/* interface to get/put used TX maps */
169234353Sdim#define TSEC_GET_TX_MAP(sc)							\
170234353Sdim		TSEC_GET_GENERIC(sc, tx_map_used_data, tx_map_used_get_cnt,	\
171234353Sdim		TSEC_TX_NUM_DESC)
172234353Sdim
173234353Sdim#define TSEC_PUT_TX_MAP(sc, val)						\
174234353Sdim		TSEC_PUT_GENERIC(sc, tx_map_used_data, tx_map_used_put_cnt,	\
175234353Sdim		TSEC_TX_NUM_DESC, val)
176234353Sdim
177234353Sdim/* interface to get/put TX mbufs in send queue */
178234353Sdim#define TSEC_TX_MBUF_CNT_INIT(sc) do {						\
179234353Sdim		TSEC_CNT_INIT((sc)->tx_mbuf_used_get_cnt, TSEC_TX_NUM_DESC);	\
180234353Sdim		TSEC_CNT_INIT((sc)->tx_mbuf_used_put_cnt, TSEC_TX_NUM_DESC);	\
181226633Sdim} while (0)
182193323Sed
183193323Sed#define TSEC_GET_TX_MBUF(sc)							\
184193323Sed		TSEC_GET_GENERIC(sc, tx_mbuf_used_data, tx_mbuf_used_get_cnt,	\
185239462Sdim		TSEC_TX_NUM_DESC)
186239462Sdim
187239462Sdim#define TSEC_PUT_TX_MBUF(sc, val)						\
188239462Sdim		TSEC_PUT_GENERIC(sc, tx_mbuf_used_data, tx_mbuf_used_put_cnt,	\
189239462Sdim		TSEC_TX_NUM_DESC, val)
190239462Sdim
191249423Sdim#define TSEC_EMPTYQ_TX_MBUF(sc) \
192249423Sdim		((sc)->tx_mbuf_used_get_cnt == (sc)->tx_mbuf_used_put_cnt)
193249423Sdim
194251662Sdim/* interface for manage tx tsec_desc */
195251662Sdim#define TSEC_TX_DESC_CNT_INIT(sc) do {						\
196251662Sdim		TSEC_CNT_INIT((sc)->tx_cur_desc_cnt, TSEC_TX_NUM_DESC);		\
197251662Sdim		TSEC_CNT_INIT((sc)->tx_dirty_desc_cnt, TSEC_TX_NUM_DESC);	\
198251662Sdim} while (0)
199251662Sdim
200193323Sed#define TSEC_GET_CUR_TX_DESC(sc)						\
201193323Sed		&TSEC_GET_GENERIC(sc, tsec_tx_vaddr, tx_cur_desc_cnt,		\
202193323Sed		TSEC_TX_NUM_DESC)
203203954Srdivacky
204193323Sed#define TSEC_GET_DIRTY_TX_DESC(sc)						\
205193323Sed		&TSEC_GET_GENERIC(sc, tsec_tx_vaddr, tx_dirty_desc_cnt,		\
206239462Sdim		TSEC_TX_NUM_DESC)
207239462Sdim
208239462Sdim#define TSEC_BACK_DIRTY_TX_DESC(sc) \
209193323Sed		TSEC_BACK_GENERIC(sc, tx_dirty_desc_cnt, TSEC_TX_NUM_DESC)
210193323Sed
211203954Srdivacky#define TSEC_CUR_DIFF_DIRTY_TX_DESC(sc) \
212193323Sed		((sc)->tx_cur_desc_cnt != (sc)->tx_dirty_desc_cnt)
213193323Sed
214193323Sed#define TSEC_FREE_TX_DESC(sc)						\
215193323Sed		(((sc)->tx_cur_desc_cnt < (sc)->tx_dirty_desc_cnt) ?	\
216193323Sed		((sc)->tx_dirty_desc_cnt - (sc)->tx_cur_desc_cnt - 1)	\
217193323Sed		:							\
218193323Sed		(TSEC_TX_NUM_DESC - (sc)->tx_cur_desc_cnt		\
219193323Sed		+ (sc)->tx_dirty_desc_cnt - 1))
220193323Sed
221208599Srdivacky/* interface for manage rx tsec_desc */
222208599Srdivacky#define TSEC_RX_DESC_CNT_INIT(sc) do {					\
223208599Srdivacky		TSEC_CNT_INIT((sc)->rx_cur_desc_cnt, TSEC_RX_NUM_DESC);	\
224208599Srdivacky} while (0)
225208599Srdivacky
226208599Srdivacky#define TSEC_GET_CUR_RX_DESC(sc)					\
227208599Srdivacky		&TSEC_GET_GENERIC(sc, tsec_rx_vaddr, rx_cur_desc_cnt,	\
228208599Srdivacky		TSEC_RX_NUM_DESC)
229208599Srdivacky
230208599Srdivacky#define TSEC_BACK_CUR_RX_DESC(sc) \
231208599Srdivacky		TSEC_BACK_GENERIC(sc, rx_cur_desc_cnt, TSEC_RX_NUM_DESC)
232208599Srdivacky
233208599Srdivacky#define TSEC_GET_CUR_RX_DESC_CNT(sc) \
234208599Srdivacky		((sc)->rx_cur_desc_cnt)
235193323Sed
236203954Srdivacky/* init all counters (for init only!) */
237193323Sed#define TSEC_TX_RX_COUNTERS_INIT(sc) do {	\
238193323Sed		TSEC_TX_MAP_CNT_INIT(sc);	\
239193323Sed		TSEC_TX_MBUF_CNT_INIT(sc);	\
240193323Sed		TSEC_TX_DESC_CNT_INIT(sc);	\
241193323Sed		TSEC_RX_DESC_CNT_INIT(sc);	\
242193323Sed} while (0)
243193323Sed
244193323Sed/* read/write bus functions */
245193323Sed#define TSEC_READ(sc, reg)		\
246239462Sdim		bus_space_read_4((sc)->sc_bas.bst, (sc)->sc_bas.bsh, (reg))
247239462Sdim#define TSEC_WRITE(sc, reg, val)	\
248239462Sdim		bus_space_write_4((sc)->sc_bas.bst, (sc)->sc_bas.bsh, (reg), (val))
249239462Sdim
250239462Sdim/* Lock for transmitter */
251239462Sdim#define TSEC_TRANSMIT_LOCK(sc) do {					\
252239462Sdim		mtx_assert(&(sc)->receive_lock, MA_NOTOWNED);		\
253239462Sdim		mtx_lock(&(sc)->transmit_lock);				\
254239462Sdim} while (0)
255193323Sed
256203954Srdivacky#define TSEC_TRANSMIT_UNLOCK(sc)	mtx_unlock(&(sc)->transmit_lock)
257193323Sed#define TSEC_TRANSMIT_LOCK_ASSERT(sc)	mtx_assert(&(sc)->transmit_lock, MA_OWNED)
258193323Sed
259193323Sed/* Lock for receiver */
260193323Sed#define TSEC_RECEIVE_LOCK(sc) do {					\
261234353Sdim		mtx_assert(&(sc)->transmit_lock, MA_NOTOWNED);		\
262193323Sed		mtx_lock(&(sc)->receive_lock);				\
263193323Sed} while (0)
264193323Sed
265193323Sed#define TSEC_RECEIVE_UNLOCK(sc)		mtx_unlock(&(sc)->receive_lock)
266204792Srdivacky#define TSEC_RECEIVE_LOCK_ASSERT(sc)	mtx_assert(&(sc)->receive_lock, MA_OWNED)
267204792Srdivacky
268239462Sdim/* Lock for interrupts coalescing */
269239462Sdim#define	TSEC_IC_LOCK(sc) do {						\
270239462Sdim		mtx_assert(&(sc)->ic_lock, MA_NOTOWNED);		\
271239462Sdim		mtx_lock(&(sc)->ic_lock);				\
272239462Sdim} while (0)
273239462Sdim
274204792Srdivacky#define	TSEC_IC_UNLOCK(sc)		mtx_unlock(&(sc)->ic_lock)
275203954Srdivacky#define	TSEC_IC_LOCK_ASSERT(sc)		mtx_assert(&(sc)->ic_lock, MA_OWNED)
276203954Srdivacky
277203954Srdivacky/* Global tsec lock (with all locks) */
278203954Srdivacky#define TSEC_GLOBAL_LOCK(sc) do {					\
279203954Srdivacky		if ((mtx_owned(&(sc)->transmit_lock) ? 1 : 0) !=	\
280203954Srdivacky			(mtx_owned(&(sc)->receive_lock) ? 1 : 0)) {	\
281203954Srdivacky			panic("tsec deadlock possibility detection!");	\
282234353Sdim		}							\
283203954Srdivacky		mtx_lock(&(sc)->transmit_lock);				\
284203954Srdivacky		mtx_lock(&(sc)->receive_lock);				\
285203954Srdivacky} while (0)
286203954Srdivacky
287203954Srdivacky#define TSEC_GLOBAL_UNLOCK(sc) do {		\
288203954Srdivacky		TSEC_RECEIVE_UNLOCK(sc);	\
289204792Srdivacky		TSEC_TRANSMIT_UNLOCK(sc);	\
290204792Srdivacky} while (0)
291204792Srdivacky
292204792Srdivacky#define TSEC_GLOBAL_LOCK_ASSERT(sc) do {	\
293193323Sed		TSEC_TRANSMIT_LOCK_ASSERT(sc);	\
294193323Sed		TSEC_RECEIVE_LOCK_ASSERT(sc);	\
295193323Sed} while (0)
296234353Sdim
297234353Sdim/* From global to {transmit,receive} */
298234353Sdim#define TSEC_GLOBAL_TO_TRANSMIT_LOCK(sc) do {	\
299234353Sdim		mtx_unlock(&(sc)->receive_lock);\
300234353Sdim} while (0)
301234353Sdim
302234353Sdim#define TSEC_GLOBAL_TO_RECEIVE_LOCK(sc) do {	\
303234353Sdim		mtx_unlock(&(sc)->transmit_lock);\
304193323Sed} while (0)
305234353Sdim
306193323Sedstruct tsec_desc {
307193323Sed	volatile uint16_t	flags;	/* descriptor flags */
308193323Sed	volatile uint16_t	length;	/* buffer length */
309193323Sed	volatile uint32_t	bufptr;	/* buffer pointer */
310208599Srdivacky};
311239462Sdim
312239462Sdim#define TSEC_READ_RETRY	10000
313239462Sdim#define TSEC_READ_DELAY	100
314239462Sdim
315239462Sdim/* Structures and defines for TCP/IP Off-load */
316208599Srdivackystruct tsec_tx_fcb {
317208599Srdivacky	volatile uint16_t	flags;
318208599Srdivacky	volatile uint8_t	l4_offset;
319208599Srdivacky	volatile uint8_t	l3_offset;
320208599Srdivacky	volatile uint16_t	ph_chsum;
321234353Sdim	volatile uint16_t	vlan;
322193323Sed};
323193323Sed
324193323Sedstruct tsec_rx_fcb {
325234353Sdim	volatile uint16_t	flags;
326234353Sdim	volatile uint8_t	rq_index;
327234353Sdim	volatile uint8_t	protocol;
328234353Sdim	volatile uint16_t	unused;
329234353Sdim	volatile uint16_t	vlan;
330234353Sdim};
331263508Sdim
332263508Sdim#define	TSEC_CHECKSUM_FEATURES	(CSUM_IP | CSUM_TCP | CSUM_UDP)
333263508Sdim
334263508Sdim#define	TSEC_TX_FCB_IP4		TSEC_TX_FCB_L3_IS_IP
335263508Sdim#define	TSEC_TX_FCB_IP6		(TSEC_TX_FCB_L3_IS_IP | TSEC_TX_FCB_L3_IS_IP6)
336193323Sed
337193323Sed#define	TSEC_TX_FCB_TCP		TSEC_TX_FCB_L4_IS_TCP_UDP
338193323Sed#define	TSEC_TX_FCB_UDP		(TSEC_TX_FCB_L4_IS_TCP_UDP | TSEC_TX_FCB_L4_IS_UDP)
339234353Sdim
340193323Sed#define	TSEC_RX_FCB_IP_CSUM_CHECKED(flags)					\
341193323Sed		((flags & (TSEC_RX_FCB_IP_FOUND | TSEC_RX_FCB_IP6_FOUND |	\
342193323Sed		TSEC_RX_FCB_IP_CSUM | TSEC_RX_FCB_PARSE_ERROR))			\
343193323Sed		 == (TSEC_RX_FCB_IP_FOUND | TSEC_RX_FCB_IP_CSUM))
344193323Sed
345193323Sed#define TSEC_RX_FCB_TCP_UDP_CSUM_CHECKED(flags)					\
346193323Sed		((flags & (TSEC_RX_FCB_TCP_UDP_FOUND | TSEC_RX_FCB_TCP_UDP_CSUM	\
347193323Sed		| TSEC_RX_FCB_PARSE_ERROR))					\
348193323Sed		== (TSEC_RX_FCB_TCP_UDP_FOUND | TSEC_RX_FCB_TCP_UDP_CSUM))
349193323Sed
350218893Sdim/* Prototypes */
351226633Sdimextern devclass_t tsec_devclass;
352226633Sdim
353226633Sdimint	tsec_attach(struct tsec_softc *sc);
354218893Sdimint	tsec_detach(struct tsec_softc *sc);
355218893Sdim
356226633Sdimvoid	tsec_error_intr(void *arg);
357218893Sdimvoid	tsec_receive_intr(void *arg);
358226633Sdimvoid	tsec_transmit_intr(void *arg);
359226633Sdim
360218893Sdimint	tsec_miibus_readreg(device_t dev, int phy, int reg);
361226633Sdimint	tsec_miibus_writereg(device_t dev, int phy, int reg, int value);
362226633Sdimvoid	tsec_miibus_statchg(device_t dev);
363226633Sdimint	tsec_resume(device_t dev); /* XXX */
364226633Sdimint	tsec_shutdown(device_t dev);
365226633Sdimint	tsec_suspend(device_t dev); /* XXX */
366226633Sdim
367226633Sdimvoid	tsec_get_hwaddr(struct tsec_softc *sc, uint8_t *addr);
368226633Sdim
369226633Sdim#endif /* _IF_TSEC_H */
370226633Sdim