if_tsec.h revision 188712
1176774Sraj/*-
2182189Sraj * Copyright (C) 2006-2007 Semihalf, Piotr Kruszynski <ppk@semihalf.com>
3176774Sraj * All rights reserved.
4176774Sraj *
5176774Sraj * Redistribution and use in source and binary forms, with or without
6176774Sraj * modification, are permitted provided that the following conditions
7176774Sraj * are met:
8176774Sraj * 1. Redistributions of source code must retain the above copyright
9176774Sraj *    notice, this list of conditions and the following disclaimer.
10176774Sraj * 2. Redistributions in binary form must reproduce the above copyright
11176774Sraj *    notice, this list of conditions and the following disclaimer in the
12176774Sraj *    documentation and/or other materials provided with the distribution.
13176774Sraj *
14176774Sraj * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15176774Sraj * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16176774Sraj * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
17176774Sraj * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
18176774Sraj * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
19176774Sraj * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20176774Sraj * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
21176774Sraj * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
22176774Sraj * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
23176774Sraj * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24176774Sraj *
25176774Sraj * $FreeBSD: head/sys/dev/tsec/if_tsec.h 188712 2009-02-17 14:59:47Z raj $
26176774Sraj */
27176774Sraj
28182189Sraj#ifndef _IF_TSEC_H
29182189Sraj#define _IF_TSEC_H
30182189Sraj
31176774Sraj#define TSEC_RX_NUM_DESC	256
32176774Sraj#define TSEC_TX_NUM_DESC	256
33176774Sraj
34188711Sraj/* Interrupt Coalescing types */
35188711Sraj#define	TSEC_IC_RX		0
36188711Sraj#define	TSEC_IC_TX		1
37188711Sraj
38188711Sraj/* eTSEC ID */
39188711Sraj#define	TSEC_ETSEC_ID		0x0124
40188711Sraj
41188711Sraj/* Frame sizes */
42188711Sraj#define	TSEC_MIN_FRAME_SIZE	64
43188711Sraj#define	TSEC_MAX_FRAME_SIZE	9600
44188711Sraj
45176774Srajstruct tsec_softc {
46176774Sraj	/* XXX MII bus requires that struct ifnet is first!!! */
47176774Sraj	struct ifnet	*tsec_ifp;
48182189Sraj
49176774Sraj	struct mtx	transmit_lock;	/* transmitter lock */
50176774Sraj	struct mtx	receive_lock;	/* receiver lock */
51176774Sraj
52176774Sraj	device_t	dev;
53176774Sraj	device_t	tsec_miibus;
54176774Sraj	struct mii_data	*tsec_mii;	/* MII media control */
55176774Sraj	int		tsec_link;
56176774Sraj
57176774Sraj	bus_dma_tag_t	tsec_tx_dtag;	/* TX descriptors tag */
58176774Sraj	bus_dmamap_t	tsec_tx_dmap;	/* TX descriptors map */
59176774Sraj	struct tsec_desc *tsec_tx_vaddr;/* vadress of TX descriptors */
60176774Sraj	uint32_t	tsec_tx_raddr;	/* real adress of TX descriptors */
61176774Sraj
62176774Sraj	bus_dma_tag_t	tsec_rx_dtag;	/* RX descriptors tag */
63176774Sraj	bus_dmamap_t	tsec_rx_dmap;	/* RX descriptors map */
64176774Sraj	struct tsec_desc *tsec_rx_vaddr; /* vadress of RX descriptors */
65176774Sraj	uint32_t	tsec_rx_raddr;	/* real adress of RX descriptors */
66176774Sraj
67176774Sraj	bus_dma_tag_t	tsec_tx_mtag;	/* TX mbufs tag */
68176774Sraj	bus_dma_tag_t	tsec_rx_mtag;	/* TX mbufs tag */
69176774Sraj
70176774Sraj	struct rx_data_type {
71176774Sraj		bus_dmamap_t	map;	/* mbuf map */
72176774Sraj		struct mbuf	*mbuf;
73176774Sraj		uint32_t	paddr;	/* DMA addres of buffer */
74176774Sraj	} rx_data[TSEC_RX_NUM_DESC];
75176774Sraj
76176774Sraj	uint32_t	tx_cur_desc_cnt;
77176774Sraj	uint32_t	tx_dirty_desc_cnt;
78176774Sraj	uint32_t	rx_cur_desc_cnt;
79176774Sraj
80176774Sraj	struct resource	*sc_rres;	/* register resource */
81176774Sraj	int		sc_rrid;	/* register rid */
82176774Sraj	struct {
83176774Sraj		bus_space_tag_t bst;
84176774Sraj		bus_space_handle_t bsh;
85176774Sraj	} sc_bas;
86176774Sraj
87176774Sraj	struct resource *sc_transmit_ires;
88176774Sraj	void		*sc_transmit_ihand;
89176774Sraj	int		sc_transmit_irid;
90176774Sraj	struct resource *sc_receive_ires;
91176774Sraj	void		*sc_receive_ihand;
92176774Sraj	int		sc_receive_irid;
93176774Sraj	struct resource *sc_error_ires;
94176774Sraj	void		*sc_error_ihand;
95176774Sraj	int		sc_error_irid;
96176774Sraj
97176774Sraj	int		tsec_if_flags;
98188711Sraj	int		is_etsec;
99176774Sraj
100182187Sraj	/* Watchdog and MII tick related */
101182187Sraj	struct callout	tsec_callout;
102182187Sraj	int		tsec_watchdog;
103177111Sraj
104176774Sraj	/* TX maps */
105176774Sraj	bus_dmamap_t	tx_map_data[TSEC_TX_NUM_DESC];
106176774Sraj
107176774Sraj	/* unused TX maps data */
108176774Sraj	uint32_t	tx_map_unused_get_cnt;
109176774Sraj	uint32_t	tx_map_unused_put_cnt;
110176774Sraj	bus_dmamap_t	*tx_map_unused_data[TSEC_TX_NUM_DESC];
111176774Sraj
112176774Sraj	/* used TX maps data */
113176774Sraj	uint32_t	tx_map_used_get_cnt;
114176774Sraj	uint32_t	tx_map_used_put_cnt;
115176774Sraj	bus_dmamap_t	*tx_map_used_data[TSEC_TX_NUM_DESC];
116182189Sraj
117176774Sraj	/* mbufs in TX queue */
118176774Sraj	uint32_t	tx_mbuf_used_get_cnt;
119176774Sraj	uint32_t	tx_mbuf_used_put_cnt;
120176774Sraj	struct mbuf	*tx_mbuf_used_data[TSEC_TX_NUM_DESC];
121188711Sraj
122188711Sraj	/* interrupt coalescing */
123188711Sraj	struct mtx	ic_lock;
124188711Sraj	uint32_t	rx_ic_time;	/* RW, valid values 0..65535 */
125188711Sraj	uint32_t	rx_ic_count;	/* RW, valid values 0..255 */
126188711Sraj	uint32_t	tx_ic_time;
127188711Sraj	uint32_t	tx_ic_count;
128188711Sraj
129188711Sraj	/* currently received frame */
130188711Sraj	struct mbuf	*frame;
131176774Sraj};
132176774Sraj
133176774Sraj/* interface to get/put generic objects */
134176774Sraj#define TSEC_CNT_INIT(cnt, wrap) ((cnt) = ((wrap) - 1))
135176774Sraj
136176774Sraj#define TSEC_INC(count, wrap) (count = ((count) + 1) & ((wrap) - 1))
137176774Sraj
138176774Sraj#define TSEC_GET_GENERIC(hand, tab, count, wrap) \
139176774Sraj		((hand)->tab[TSEC_INC((hand)->count, wrap)])
140176774Sraj
141176774Sraj#define TSEC_PUT_GENERIC(hand, tab, count, wrap, val)	\
142176774Sraj		((hand)->tab[TSEC_INC((hand)->count, wrap)] = val)
143176774Sraj
144188712Sraj#define TSEC_BACK_GENERIC(sc, count, wrap) do {			\
145188712Sraj		if ((sc)->count > 0)				\
146188712Sraj			(sc)->count--;				\
147188712Sraj		else						\
148188712Sraj			(sc)->count = (wrap) - 1;		\
149176774Sraj} while (0)
150176774Sraj
151176774Sraj/* TX maps interface */
152176774Sraj#define TSEC_TX_MAP_CNT_INIT(sc) do {						\
153176774Sraj		TSEC_CNT_INIT((sc)->tx_map_unused_get_cnt, TSEC_TX_NUM_DESC);	\
154176774Sraj		TSEC_CNT_INIT((sc)->tx_map_unused_put_cnt, TSEC_TX_NUM_DESC);	\
155176774Sraj		TSEC_CNT_INIT((sc)->tx_map_used_get_cnt, TSEC_TX_NUM_DESC);	\
156176774Sraj		TSEC_CNT_INIT((sc)->tx_map_used_put_cnt, TSEC_TX_NUM_DESC);	\
157176774Sraj} while (0)
158176774Sraj
159176774Sraj/* interface to get/put unused TX maps */
160176774Sraj#define TSEC_ALLOC_TX_MAP(sc)							\
161176774Sraj		TSEC_GET_GENERIC(sc, tx_map_unused_data, tx_map_unused_get_cnt,	\
162176774Sraj		TSEC_TX_NUM_DESC)
163176774Sraj
164176774Sraj#define TSEC_FREE_TX_MAP(sc, val)						\
165176774Sraj		TSEC_PUT_GENERIC(sc, tx_map_unused_data, tx_map_unused_put_cnt,	\
166176774Sraj		TSEC_TX_NUM_DESC, val)
167176774Sraj
168176774Sraj/* interface to get/put used TX maps */
169176774Sraj#define TSEC_GET_TX_MAP(sc)							\
170176774Sraj		TSEC_GET_GENERIC(sc, tx_map_used_data, tx_map_used_get_cnt,	\
171176774Sraj		TSEC_TX_NUM_DESC)
172176774Sraj
173176774Sraj#define TSEC_PUT_TX_MAP(sc, val)						\
174176774Sraj		TSEC_PUT_GENERIC(sc, tx_map_used_data, tx_map_used_put_cnt,	\
175176774Sraj		TSEC_TX_NUM_DESC, val)
176176774Sraj
177176774Sraj/* interface to get/put TX mbufs in send queue */
178176774Sraj#define TSEC_TX_MBUF_CNT_INIT(sc) do {						\
179176774Sraj		TSEC_CNT_INIT((sc)->tx_mbuf_used_get_cnt, TSEC_TX_NUM_DESC);	\
180176774Sraj		TSEC_CNT_INIT((sc)->tx_mbuf_used_put_cnt, TSEC_TX_NUM_DESC);	\
181176774Sraj} while (0)
182176774Sraj
183176774Sraj#define TSEC_GET_TX_MBUF(sc)							\
184176774Sraj		TSEC_GET_GENERIC(sc, tx_mbuf_used_data, tx_mbuf_used_get_cnt,	\
185176774Sraj		TSEC_TX_NUM_DESC)
186176774Sraj
187176774Sraj#define TSEC_PUT_TX_MBUF(sc, val)						\
188176774Sraj		TSEC_PUT_GENERIC(sc, tx_mbuf_used_data, tx_mbuf_used_put_cnt,	\
189176774Sraj		TSEC_TX_NUM_DESC, val)
190176774Sraj
191176774Sraj#define TSEC_EMPTYQ_TX_MBUF(sc) \
192176774Sraj		((sc)->tx_mbuf_used_get_cnt == (sc)->tx_mbuf_used_put_cnt)
193176774Sraj
194176774Sraj/* interface for manage tx tsec_desc */
195176774Sraj#define TSEC_TX_DESC_CNT_INIT(sc) do {						\
196176774Sraj		TSEC_CNT_INIT((sc)->tx_cur_desc_cnt, TSEC_TX_NUM_DESC);		\
197176774Sraj		TSEC_CNT_INIT((sc)->tx_dirty_desc_cnt, TSEC_TX_NUM_DESC);	\
198176774Sraj} while (0)
199176774Sraj
200188712Sraj#define TSEC_GET_CUR_TX_DESC(sc)						\
201188712Sraj		&TSEC_GET_GENERIC(sc, tsec_tx_vaddr, tx_cur_desc_cnt,		\
202176774Sraj		TSEC_TX_NUM_DESC)
203176774Sraj
204188712Sraj#define TSEC_GET_DIRTY_TX_DESC(sc)						\
205188712Sraj		&TSEC_GET_GENERIC(sc, tsec_tx_vaddr, tx_dirty_desc_cnt,		\
206176774Sraj		TSEC_TX_NUM_DESC)
207176774Sraj
208176774Sraj#define TSEC_BACK_DIRTY_TX_DESC(sc) \
209176774Sraj		TSEC_BACK_GENERIC(sc, tx_dirty_desc_cnt, TSEC_TX_NUM_DESC)
210176774Sraj
211176774Sraj#define TSEC_CUR_DIFF_DIRTY_TX_DESC(sc) \
212176774Sraj		((sc)->tx_cur_desc_cnt != (sc)->tx_dirty_desc_cnt)
213176774Sraj
214176774Sraj#define TSEC_FREE_TX_DESC(sc)						\
215176774Sraj		(((sc)->tx_cur_desc_cnt < (sc)->tx_dirty_desc_cnt) ?	\
216176774Sraj		((sc)->tx_dirty_desc_cnt - (sc)->tx_cur_desc_cnt - 1)	\
217176774Sraj		:							\
218176774Sraj		(TSEC_TX_NUM_DESC - (sc)->tx_cur_desc_cnt		\
219176774Sraj		+ (sc)->tx_dirty_desc_cnt - 1))
220176774Sraj
221176774Sraj/* interface for manage rx tsec_desc */
222176774Sraj#define TSEC_RX_DESC_CNT_INIT(sc) do {					\
223176774Sraj		TSEC_CNT_INIT((sc)->rx_cur_desc_cnt, TSEC_RX_NUM_DESC);	\
224176774Sraj} while (0)
225176774Sraj
226176774Sraj#define TSEC_GET_CUR_RX_DESC(sc)					\
227176774Sraj		&TSEC_GET_GENERIC(sc, tsec_rx_vaddr, rx_cur_desc_cnt,	\
228176774Sraj		TSEC_RX_NUM_DESC)
229176774Sraj
230176774Sraj#define TSEC_BACK_CUR_RX_DESC(sc) \
231176774Sraj		TSEC_BACK_GENERIC(sc, rx_cur_desc_cnt, TSEC_RX_NUM_DESC)
232176774Sraj
233176774Sraj#define TSEC_GET_CUR_RX_DESC_CNT(sc) \
234176774Sraj		((sc)->rx_cur_desc_cnt)
235176774Sraj
236176774Sraj/* init all counters (for init only!) */
237176774Sraj#define TSEC_TX_RX_COUNTERS_INIT(sc) do {	\
238176774Sraj		TSEC_TX_MAP_CNT_INIT(sc);	\
239176774Sraj		TSEC_TX_MBUF_CNT_INIT(sc);	\
240176774Sraj		TSEC_TX_DESC_CNT_INIT(sc);	\
241176774Sraj		TSEC_RX_DESC_CNT_INIT(sc);	\
242176774Sraj} while (0)
243176774Sraj
244176774Sraj/* read/write bus functions */
245176774Sraj#define TSEC_READ(sc, reg)		\
246176774Sraj		bus_space_read_4((sc)->sc_bas.bst, (sc)->sc_bas.bsh, (reg))
247176774Sraj#define TSEC_WRITE(sc, reg, val)	\
248176774Sraj		bus_space_write_4((sc)->sc_bas.bst, (sc)->sc_bas.bsh, (reg), (val))
249176774Sraj
250176774Sraj/* Lock for transmitter */
251176774Sraj#define TSEC_TRANSMIT_LOCK(sc) do {					\
252176774Sraj		mtx_assert(&(sc)->receive_lock, MA_NOTOWNED);		\
253176774Sraj		mtx_lock(&(sc)->transmit_lock);				\
254176774Sraj} while (0)
255176774Sraj
256176774Sraj#define TSEC_TRANSMIT_UNLOCK(sc)	mtx_unlock(&(sc)->transmit_lock)
257176774Sraj#define TSEC_TRANSMIT_LOCK_ASSERT(sc)	mtx_assert(&(sc)->transmit_lock, MA_OWNED)
258176774Sraj
259176774Sraj/* Lock for receiver */
260188711Sraj#define TSEC_RECEIVE_LOCK(sc) do {					\
261188711Sraj		mtx_assert(&(sc)->transmit_lock, MA_NOTOWNED);		\
262188711Sraj		mtx_lock(&(sc)->receive_lock);				\
263176774Sraj} while (0)
264176774Sraj
265176774Sraj#define TSEC_RECEIVE_UNLOCK(sc)		mtx_unlock(&(sc)->receive_lock)
266176774Sraj#define TSEC_RECEIVE_LOCK_ASSERT(sc)	mtx_assert(&(sc)->receive_lock, MA_OWNED)
267176774Sraj
268188711Sraj/* Lock for interrupts coalescing */
269188711Sraj#define	TSEC_IC_LOCK(sc) do {						\
270188711Sraj		mtx_assert(&(sc)->ic_lock, MA_NOTOWNED);		\
271188711Sraj		mtx_lock(&(sc)->ic_lock);				\
272188711Sraj} while (0)
273188711Sraj
274188711Sraj#define	TSEC_IC_UNLOCK(sc)		mtx_unlock(&(sc)->ic_lock)
275188711Sraj#define	TSEC_IC_LOCK_ASSERT(sc)		mtx_assert(&(sc)->ic_lock, MA_OWNED)
276188711Sraj
277176774Sraj/* Global tsec lock (with all locks) */
278176774Sraj#define TSEC_GLOBAL_LOCK(sc) do {					\
279176774Sraj		if ((mtx_owned(&(sc)->transmit_lock) ? 1 : 0) !=	\
280176774Sraj			(mtx_owned(&(sc)->receive_lock) ? 1 : 0)) {	\
281176774Sraj			panic("tsec deadlock possibility detection!");	\
282176774Sraj		}							\
283176774Sraj		mtx_lock(&(sc)->transmit_lock);				\
284176774Sraj		mtx_lock(&(sc)->receive_lock);				\
285176774Sraj} while (0)
286176774Sraj
287176774Sraj#define TSEC_GLOBAL_UNLOCK(sc) do {		\
288176774Sraj		TSEC_RECEIVE_UNLOCK(sc);	\
289176774Sraj		TSEC_TRANSMIT_UNLOCK(sc);	\
290176774Sraj} while (0)
291176774Sraj
292176774Sraj#define TSEC_GLOBAL_LOCK_ASSERT(sc) do {	\
293176774Sraj		TSEC_TRANSMIT_LOCK_ASSERT(sc);	\
294176774Sraj		TSEC_RECEIVE_LOCK_ASSERT(sc);	\
295176774Sraj} while (0)
296176774Sraj
297176774Sraj/* From global to {transmit,receive} */
298176774Sraj#define TSEC_GLOBAL_TO_TRANSMIT_LOCK(sc) do {	\
299176774Sraj		mtx_unlock(&(sc)->receive_lock);\
300176774Sraj} while (0)
301176774Sraj
302176774Sraj#define TSEC_GLOBAL_TO_RECEIVE_LOCK(sc) do {	\
303176774Sraj		mtx_unlock(&(sc)->transmit_lock);\
304176774Sraj} while (0)
305176774Sraj
306176774Srajstruct tsec_desc {
307188711Sraj	volatile uint16_t	flags;	/* descriptor flags */
308188711Sraj	volatile uint16_t	length;	/* buffer length */
309188711Sraj	volatile uint32_t	bufptr;	/* buffer pointer */
310176774Sraj};
311176774Sraj
312176774Sraj#define TSEC_READ_RETRY	10000
313176774Sraj#define TSEC_READ_DELAY	100
314182189Sraj
315188711Sraj/* Structures and defines for TCP/IP Off-load */
316188711Srajstruct tsec_tx_fcb {
317188711Sraj	volatile uint16_t	flags;
318188711Sraj	volatile uint8_t	l4_offset;
319188711Sraj	volatile uint8_t	l3_offset;
320188711Sraj	volatile uint16_t	ph_chsum;
321188711Sraj	volatile uint16_t	vlan;
322188711Sraj};
323188711Sraj
324188711Srajstruct tsec_rx_fcb {
325188711Sraj	volatile uint16_t	flags;
326188711Sraj	volatile uint8_t	rq_index;
327188711Sraj	volatile uint8_t	protocol;
328188711Sraj	volatile uint16_t	unused;
329188711Sraj	volatile uint16_t	vlan;
330188711Sraj};
331188711Sraj
332188711Sraj#define	TSEC_CHECKSUM_FEATURES	(CSUM_IP | CSUM_TCP | CSUM_UDP)
333188711Sraj
334188711Sraj#define	TSEC_TX_FCB_IP4		TSEC_TX_FCB_L3_IS_IP
335188711Sraj#define	TSEC_TX_FCB_IP6		(TSEC_TX_FCB_L3_IS_IP | TSEC_TX_FCB_L3_IS_IP6)
336188711Sraj
337188711Sraj#define	TSEC_TX_FCB_TCP		TSEC_TX_FCB_L4_IS_TCP_UDP
338188711Sraj#define	TSEC_TX_FCB_UDP		(TSEC_TX_FCB_L4_IS_TCP_UDP | TSEC_TX_FCB_L4_IS_UDP)
339188711Sraj
340188711Sraj#define	TSEC_RX_FCB_IP_CSUM_CHECKED(flags)					\
341188711Sraj		((flags & (TSEC_RX_FCB_IP_FOUND | TSEC_RX_FCB_IP6_FOUND |	\
342188711Sraj		TSEC_RX_FCB_IP_CSUM | TSEC_RX_FCB_PARSE_ERROR))			\
343188711Sraj		 == (TSEC_RX_FCB_IP_FOUND | TSEC_RX_FCB_IP_CSUM))
344188711Sraj
345188711Sraj#define TSEC_RX_FCB_TCP_UDP_CSUM_CHECKED(flags)					\
346188711Sraj		((flags & (TSEC_RX_FCB_TCP_UDP_FOUND | TSEC_RX_FCB_TCP_UDP_CSUM	\
347188711Sraj		| TSEC_RX_FCB_PARSE_ERROR))					\
348188711Sraj		== (TSEC_RX_FCB_TCP_UDP_FOUND | TSEC_RX_FCB_TCP_UDP_CSUM))
349188711Sraj
350182189Sraj/* Prototypes */
351182189Srajextern devclass_t tsec_devclass;
352182189Sraj
353182189Srajint	tsec_attach(struct tsec_softc *sc);
354182189Srajint	tsec_detach(struct tsec_softc *sc);
355182189Sraj
356182189Srajvoid	tsec_error_intr(void *arg);
357182189Srajvoid	tsec_receive_intr(void *arg);
358182189Srajvoid	tsec_transmit_intr(void *arg);
359182189Sraj
360182189Srajint	tsec_miibus_readreg(device_t dev, int phy, int reg);
361182189Srajvoid	tsec_miibus_writereg(device_t dev, int phy, int reg, int value);
362182189Srajvoid	tsec_miibus_statchg(device_t dev);
363182189Srajint	tsec_resume(device_t dev); /* XXX */
364182189Srajvoid	tsec_shutdown(device_t dev);
365182189Srajint	tsec_suspend(device_t dev); /* XXX */
366182189Sraj
367182189Srajvoid	tsec_get_hwaddr(struct tsec_softc *sc, uint8_t *addr);
368182189Sraj
369188712Sraj#endif /* _IF_TSEC_H */
370