if_tsec.h revision 209908
1176774Sraj/*-
2209908Sraj * Copyright (C) 2006-2007 Semihalf, Piotr Kruszynski
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 209908 2010-07-11 21:08:29Z raj $
26176774Sraj */
27176774Sraj
28182189Sraj#ifndef _IF_TSEC_H
29182189Sraj#define _IF_TSEC_H
30182189Sraj
31209908Sraj#include <dev/ofw/openfirm.h>
32209908Sraj
33176774Sraj#define TSEC_RX_NUM_DESC	256
34176774Sraj#define TSEC_TX_NUM_DESC	256
35176774Sraj
36188711Sraj/* Interrupt Coalescing types */
37188711Sraj#define	TSEC_IC_RX		0
38188711Sraj#define	TSEC_IC_TX		1
39188711Sraj
40188711Sraj/* eTSEC ID */
41188711Sraj#define	TSEC_ETSEC_ID		0x0124
42188711Sraj
43188711Sraj/* Frame sizes */
44188711Sraj#define	TSEC_MIN_FRAME_SIZE	64
45188711Sraj#define	TSEC_MAX_FRAME_SIZE	9600
46188711Sraj
47176774Srajstruct tsec_softc {
48176774Sraj	/* XXX MII bus requires that struct ifnet is first!!! */
49176774Sraj	struct ifnet	*tsec_ifp;
50182189Sraj
51176774Sraj	struct mtx	transmit_lock;	/* transmitter lock */
52176774Sraj	struct mtx	receive_lock;	/* receiver lock */
53176774Sraj
54209908Sraj	phandle_t	node;
55176774Sraj	device_t	dev;
56176774Sraj	device_t	tsec_miibus;
57176774Sraj	struct mii_data	*tsec_mii;	/* MII media control */
58176774Sraj	int		tsec_link;
59176774Sraj
60176774Sraj	bus_dma_tag_t	tsec_tx_dtag;	/* TX descriptors tag */
61176774Sraj	bus_dmamap_t	tsec_tx_dmap;	/* TX descriptors map */
62176774Sraj	struct tsec_desc *tsec_tx_vaddr;/* vadress of TX descriptors */
63176774Sraj	uint32_t	tsec_tx_raddr;	/* real adress of TX descriptors */
64176774Sraj
65176774Sraj	bus_dma_tag_t	tsec_rx_dtag;	/* RX descriptors tag */
66176774Sraj	bus_dmamap_t	tsec_rx_dmap;	/* RX descriptors map */
67176774Sraj	struct tsec_desc *tsec_rx_vaddr; /* vadress of RX descriptors */
68176774Sraj	uint32_t	tsec_rx_raddr;	/* real adress of RX descriptors */
69176774Sraj
70176774Sraj	bus_dma_tag_t	tsec_tx_mtag;	/* TX mbufs tag */
71176774Sraj	bus_dma_tag_t	tsec_rx_mtag;	/* TX mbufs tag */
72176774Sraj
73176774Sraj	struct rx_data_type {
74176774Sraj		bus_dmamap_t	map;	/* mbuf map */
75176774Sraj		struct mbuf	*mbuf;
76176774Sraj		uint32_t	paddr;	/* DMA addres of buffer */
77176774Sraj	} rx_data[TSEC_RX_NUM_DESC];
78176774Sraj
79176774Sraj	uint32_t	tx_cur_desc_cnt;
80176774Sraj	uint32_t	tx_dirty_desc_cnt;
81176774Sraj	uint32_t	rx_cur_desc_cnt;
82176774Sraj
83176774Sraj	struct resource	*sc_rres;	/* register resource */
84176774Sraj	int		sc_rrid;	/* register rid */
85176774Sraj	struct {
86176774Sraj		bus_space_tag_t bst;
87176774Sraj		bus_space_handle_t bsh;
88176774Sraj	} sc_bas;
89176774Sraj
90176774Sraj	struct resource *sc_transmit_ires;
91176774Sraj	void		*sc_transmit_ihand;
92176774Sraj	int		sc_transmit_irid;
93176774Sraj	struct resource *sc_receive_ires;
94176774Sraj	void		*sc_receive_ihand;
95176774Sraj	int		sc_receive_irid;
96176774Sraj	struct resource *sc_error_ires;
97176774Sraj	void		*sc_error_ihand;
98176774Sraj	int		sc_error_irid;
99176774Sraj
100176774Sraj	int		tsec_if_flags;
101188711Sraj	int		is_etsec;
102176774Sraj
103182187Sraj	/* Watchdog and MII tick related */
104182187Sraj	struct callout	tsec_callout;
105182187Sraj	int		tsec_watchdog;
106177111Sraj
107176774Sraj	/* TX maps */
108176774Sraj	bus_dmamap_t	tx_map_data[TSEC_TX_NUM_DESC];
109176774Sraj
110176774Sraj	/* unused TX maps data */
111176774Sraj	uint32_t	tx_map_unused_get_cnt;
112176774Sraj	uint32_t	tx_map_unused_put_cnt;
113176774Sraj	bus_dmamap_t	*tx_map_unused_data[TSEC_TX_NUM_DESC];
114176774Sraj
115176774Sraj	/* used TX maps data */
116176774Sraj	uint32_t	tx_map_used_get_cnt;
117176774Sraj	uint32_t	tx_map_used_put_cnt;
118176774Sraj	bus_dmamap_t	*tx_map_used_data[TSEC_TX_NUM_DESC];
119182189Sraj
120176774Sraj	/* mbufs in TX queue */
121176774Sraj	uint32_t	tx_mbuf_used_get_cnt;
122176774Sraj	uint32_t	tx_mbuf_used_put_cnt;
123176774Sraj	struct mbuf	*tx_mbuf_used_data[TSEC_TX_NUM_DESC];
124188711Sraj
125188711Sraj	/* interrupt coalescing */
126188711Sraj	struct mtx	ic_lock;
127188711Sraj	uint32_t	rx_ic_time;	/* RW, valid values 0..65535 */
128188711Sraj	uint32_t	rx_ic_count;	/* RW, valid values 0..255 */
129188711Sraj	uint32_t	tx_ic_time;
130188711Sraj	uint32_t	tx_ic_count;
131188711Sraj
132188711Sraj	/* currently received frame */
133188711Sraj	struct mbuf	*frame;
134209908Sraj
135209908Sraj	int		phyaddr;
136176774Sraj};
137176774Sraj
138176774Sraj/* interface to get/put generic objects */
139176774Sraj#define TSEC_CNT_INIT(cnt, wrap) ((cnt) = ((wrap) - 1))
140176774Sraj
141176774Sraj#define TSEC_INC(count, wrap) (count = ((count) + 1) & ((wrap) - 1))
142176774Sraj
143176774Sraj#define TSEC_GET_GENERIC(hand, tab, count, wrap) \
144176774Sraj		((hand)->tab[TSEC_INC((hand)->count, wrap)])
145176774Sraj
146176774Sraj#define TSEC_PUT_GENERIC(hand, tab, count, wrap, val)	\
147176774Sraj		((hand)->tab[TSEC_INC((hand)->count, wrap)] = val)
148176774Sraj
149188712Sraj#define TSEC_BACK_GENERIC(sc, count, wrap) do {			\
150188712Sraj		if ((sc)->count > 0)				\
151188712Sraj			(sc)->count--;				\
152188712Sraj		else						\
153188712Sraj			(sc)->count = (wrap) - 1;		\
154176774Sraj} while (0)
155176774Sraj
156176774Sraj/* TX maps interface */
157176774Sraj#define TSEC_TX_MAP_CNT_INIT(sc) do {						\
158176774Sraj		TSEC_CNT_INIT((sc)->tx_map_unused_get_cnt, TSEC_TX_NUM_DESC);	\
159176774Sraj		TSEC_CNT_INIT((sc)->tx_map_unused_put_cnt, TSEC_TX_NUM_DESC);	\
160176774Sraj		TSEC_CNT_INIT((sc)->tx_map_used_get_cnt, TSEC_TX_NUM_DESC);	\
161176774Sraj		TSEC_CNT_INIT((sc)->tx_map_used_put_cnt, TSEC_TX_NUM_DESC);	\
162176774Sraj} while (0)
163176774Sraj
164176774Sraj/* interface to get/put unused TX maps */
165176774Sraj#define TSEC_ALLOC_TX_MAP(sc)							\
166176774Sraj		TSEC_GET_GENERIC(sc, tx_map_unused_data, tx_map_unused_get_cnt,	\
167176774Sraj		TSEC_TX_NUM_DESC)
168176774Sraj
169176774Sraj#define TSEC_FREE_TX_MAP(sc, val)						\
170176774Sraj		TSEC_PUT_GENERIC(sc, tx_map_unused_data, tx_map_unused_put_cnt,	\
171176774Sraj		TSEC_TX_NUM_DESC, val)
172176774Sraj
173176774Sraj/* interface to get/put used TX maps */
174176774Sraj#define TSEC_GET_TX_MAP(sc)							\
175176774Sraj		TSEC_GET_GENERIC(sc, tx_map_used_data, tx_map_used_get_cnt,	\
176176774Sraj		TSEC_TX_NUM_DESC)
177176774Sraj
178176774Sraj#define TSEC_PUT_TX_MAP(sc, val)						\
179176774Sraj		TSEC_PUT_GENERIC(sc, tx_map_used_data, tx_map_used_put_cnt,	\
180176774Sraj		TSEC_TX_NUM_DESC, val)
181176774Sraj
182176774Sraj/* interface to get/put TX mbufs in send queue */
183176774Sraj#define TSEC_TX_MBUF_CNT_INIT(sc) do {						\
184176774Sraj		TSEC_CNT_INIT((sc)->tx_mbuf_used_get_cnt, TSEC_TX_NUM_DESC);	\
185176774Sraj		TSEC_CNT_INIT((sc)->tx_mbuf_used_put_cnt, TSEC_TX_NUM_DESC);	\
186176774Sraj} while (0)
187176774Sraj
188176774Sraj#define TSEC_GET_TX_MBUF(sc)							\
189176774Sraj		TSEC_GET_GENERIC(sc, tx_mbuf_used_data, tx_mbuf_used_get_cnt,	\
190176774Sraj		TSEC_TX_NUM_DESC)
191176774Sraj
192176774Sraj#define TSEC_PUT_TX_MBUF(sc, val)						\
193176774Sraj		TSEC_PUT_GENERIC(sc, tx_mbuf_used_data, tx_mbuf_used_put_cnt,	\
194176774Sraj		TSEC_TX_NUM_DESC, val)
195176774Sraj
196176774Sraj#define TSEC_EMPTYQ_TX_MBUF(sc) \
197176774Sraj		((sc)->tx_mbuf_used_get_cnt == (sc)->tx_mbuf_used_put_cnt)
198176774Sraj
199176774Sraj/* interface for manage tx tsec_desc */
200176774Sraj#define TSEC_TX_DESC_CNT_INIT(sc) do {						\
201176774Sraj		TSEC_CNT_INIT((sc)->tx_cur_desc_cnt, TSEC_TX_NUM_DESC);		\
202176774Sraj		TSEC_CNT_INIT((sc)->tx_dirty_desc_cnt, TSEC_TX_NUM_DESC);	\
203176774Sraj} while (0)
204176774Sraj
205188712Sraj#define TSEC_GET_CUR_TX_DESC(sc)						\
206188712Sraj		&TSEC_GET_GENERIC(sc, tsec_tx_vaddr, tx_cur_desc_cnt,		\
207176774Sraj		TSEC_TX_NUM_DESC)
208176774Sraj
209188712Sraj#define TSEC_GET_DIRTY_TX_DESC(sc)						\
210188712Sraj		&TSEC_GET_GENERIC(sc, tsec_tx_vaddr, tx_dirty_desc_cnt,		\
211176774Sraj		TSEC_TX_NUM_DESC)
212176774Sraj
213176774Sraj#define TSEC_BACK_DIRTY_TX_DESC(sc) \
214176774Sraj		TSEC_BACK_GENERIC(sc, tx_dirty_desc_cnt, TSEC_TX_NUM_DESC)
215176774Sraj
216176774Sraj#define TSEC_CUR_DIFF_DIRTY_TX_DESC(sc) \
217176774Sraj		((sc)->tx_cur_desc_cnt != (sc)->tx_dirty_desc_cnt)
218176774Sraj
219176774Sraj#define TSEC_FREE_TX_DESC(sc)						\
220176774Sraj		(((sc)->tx_cur_desc_cnt < (sc)->tx_dirty_desc_cnt) ?	\
221176774Sraj		((sc)->tx_dirty_desc_cnt - (sc)->tx_cur_desc_cnt - 1)	\
222176774Sraj		:							\
223176774Sraj		(TSEC_TX_NUM_DESC - (sc)->tx_cur_desc_cnt		\
224176774Sraj		+ (sc)->tx_dirty_desc_cnt - 1))
225176774Sraj
226176774Sraj/* interface for manage rx tsec_desc */
227176774Sraj#define TSEC_RX_DESC_CNT_INIT(sc) do {					\
228176774Sraj		TSEC_CNT_INIT((sc)->rx_cur_desc_cnt, TSEC_RX_NUM_DESC);	\
229176774Sraj} while (0)
230176774Sraj
231176774Sraj#define TSEC_GET_CUR_RX_DESC(sc)					\
232176774Sraj		&TSEC_GET_GENERIC(sc, tsec_rx_vaddr, rx_cur_desc_cnt,	\
233176774Sraj		TSEC_RX_NUM_DESC)
234176774Sraj
235176774Sraj#define TSEC_BACK_CUR_RX_DESC(sc) \
236176774Sraj		TSEC_BACK_GENERIC(sc, rx_cur_desc_cnt, TSEC_RX_NUM_DESC)
237176774Sraj
238176774Sraj#define TSEC_GET_CUR_RX_DESC_CNT(sc) \
239176774Sraj		((sc)->rx_cur_desc_cnt)
240176774Sraj
241176774Sraj/* init all counters (for init only!) */
242176774Sraj#define TSEC_TX_RX_COUNTERS_INIT(sc) do {	\
243176774Sraj		TSEC_TX_MAP_CNT_INIT(sc);	\
244176774Sraj		TSEC_TX_MBUF_CNT_INIT(sc);	\
245176774Sraj		TSEC_TX_DESC_CNT_INIT(sc);	\
246176774Sraj		TSEC_RX_DESC_CNT_INIT(sc);	\
247176774Sraj} while (0)
248176774Sraj
249176774Sraj/* read/write bus functions */
250176774Sraj#define TSEC_READ(sc, reg)		\
251176774Sraj		bus_space_read_4((sc)->sc_bas.bst, (sc)->sc_bas.bsh, (reg))
252176774Sraj#define TSEC_WRITE(sc, reg, val)	\
253176774Sraj		bus_space_write_4((sc)->sc_bas.bst, (sc)->sc_bas.bsh, (reg), (val))
254176774Sraj
255176774Sraj/* Lock for transmitter */
256176774Sraj#define TSEC_TRANSMIT_LOCK(sc) do {					\
257176774Sraj		mtx_assert(&(sc)->receive_lock, MA_NOTOWNED);		\
258176774Sraj		mtx_lock(&(sc)->transmit_lock);				\
259176774Sraj} while (0)
260176774Sraj
261176774Sraj#define TSEC_TRANSMIT_UNLOCK(sc)	mtx_unlock(&(sc)->transmit_lock)
262176774Sraj#define TSEC_TRANSMIT_LOCK_ASSERT(sc)	mtx_assert(&(sc)->transmit_lock, MA_OWNED)
263176774Sraj
264176774Sraj/* Lock for receiver */
265188711Sraj#define TSEC_RECEIVE_LOCK(sc) do {					\
266188711Sraj		mtx_assert(&(sc)->transmit_lock, MA_NOTOWNED);		\
267188711Sraj		mtx_lock(&(sc)->receive_lock);				\
268176774Sraj} while (0)
269176774Sraj
270176774Sraj#define TSEC_RECEIVE_UNLOCK(sc)		mtx_unlock(&(sc)->receive_lock)
271176774Sraj#define TSEC_RECEIVE_LOCK_ASSERT(sc)	mtx_assert(&(sc)->receive_lock, MA_OWNED)
272176774Sraj
273188711Sraj/* Lock for interrupts coalescing */
274188711Sraj#define	TSEC_IC_LOCK(sc) do {						\
275188711Sraj		mtx_assert(&(sc)->ic_lock, MA_NOTOWNED);		\
276188711Sraj		mtx_lock(&(sc)->ic_lock);				\
277188711Sraj} while (0)
278188711Sraj
279188711Sraj#define	TSEC_IC_UNLOCK(sc)		mtx_unlock(&(sc)->ic_lock)
280188711Sraj#define	TSEC_IC_LOCK_ASSERT(sc)		mtx_assert(&(sc)->ic_lock, MA_OWNED)
281188711Sraj
282176774Sraj/* Global tsec lock (with all locks) */
283176774Sraj#define TSEC_GLOBAL_LOCK(sc) do {					\
284176774Sraj		if ((mtx_owned(&(sc)->transmit_lock) ? 1 : 0) !=	\
285176774Sraj			(mtx_owned(&(sc)->receive_lock) ? 1 : 0)) {	\
286176774Sraj			panic("tsec deadlock possibility detection!");	\
287176774Sraj		}							\
288176774Sraj		mtx_lock(&(sc)->transmit_lock);				\
289176774Sraj		mtx_lock(&(sc)->receive_lock);				\
290176774Sraj} while (0)
291176774Sraj
292176774Sraj#define TSEC_GLOBAL_UNLOCK(sc) do {		\
293176774Sraj		TSEC_RECEIVE_UNLOCK(sc);	\
294176774Sraj		TSEC_TRANSMIT_UNLOCK(sc);	\
295176774Sraj} while (0)
296176774Sraj
297176774Sraj#define TSEC_GLOBAL_LOCK_ASSERT(sc) do {	\
298176774Sraj		TSEC_TRANSMIT_LOCK_ASSERT(sc);	\
299176774Sraj		TSEC_RECEIVE_LOCK_ASSERT(sc);	\
300176774Sraj} while (0)
301176774Sraj
302176774Sraj/* From global to {transmit,receive} */
303176774Sraj#define TSEC_GLOBAL_TO_TRANSMIT_LOCK(sc) do {	\
304176774Sraj		mtx_unlock(&(sc)->receive_lock);\
305176774Sraj} while (0)
306176774Sraj
307176774Sraj#define TSEC_GLOBAL_TO_RECEIVE_LOCK(sc) do {	\
308176774Sraj		mtx_unlock(&(sc)->transmit_lock);\
309176774Sraj} while (0)
310176774Sraj
311176774Srajstruct tsec_desc {
312188711Sraj	volatile uint16_t	flags;	/* descriptor flags */
313188711Sraj	volatile uint16_t	length;	/* buffer length */
314188711Sraj	volatile uint32_t	bufptr;	/* buffer pointer */
315176774Sraj};
316176774Sraj
317176774Sraj#define TSEC_READ_RETRY	10000
318176774Sraj#define TSEC_READ_DELAY	100
319182189Sraj
320188711Sraj/* Structures and defines for TCP/IP Off-load */
321188711Srajstruct tsec_tx_fcb {
322188711Sraj	volatile uint16_t	flags;
323188711Sraj	volatile uint8_t	l4_offset;
324188711Sraj	volatile uint8_t	l3_offset;
325188711Sraj	volatile uint16_t	ph_chsum;
326188711Sraj	volatile uint16_t	vlan;
327188711Sraj};
328188711Sraj
329188711Srajstruct tsec_rx_fcb {
330188711Sraj	volatile uint16_t	flags;
331188711Sraj	volatile uint8_t	rq_index;
332188711Sraj	volatile uint8_t	protocol;
333188711Sraj	volatile uint16_t	unused;
334188711Sraj	volatile uint16_t	vlan;
335188711Sraj};
336188711Sraj
337188711Sraj#define	TSEC_CHECKSUM_FEATURES	(CSUM_IP | CSUM_TCP | CSUM_UDP)
338188711Sraj
339188711Sraj#define	TSEC_TX_FCB_IP4		TSEC_TX_FCB_L3_IS_IP
340188711Sraj#define	TSEC_TX_FCB_IP6		(TSEC_TX_FCB_L3_IS_IP | TSEC_TX_FCB_L3_IS_IP6)
341188711Sraj
342188711Sraj#define	TSEC_TX_FCB_TCP		TSEC_TX_FCB_L4_IS_TCP_UDP
343188711Sraj#define	TSEC_TX_FCB_UDP		(TSEC_TX_FCB_L4_IS_TCP_UDP | TSEC_TX_FCB_L4_IS_UDP)
344188711Sraj
345188711Sraj#define	TSEC_RX_FCB_IP_CSUM_CHECKED(flags)					\
346188711Sraj		((flags & (TSEC_RX_FCB_IP_FOUND | TSEC_RX_FCB_IP6_FOUND |	\
347188711Sraj		TSEC_RX_FCB_IP_CSUM | TSEC_RX_FCB_PARSE_ERROR))			\
348188711Sraj		 == (TSEC_RX_FCB_IP_FOUND | TSEC_RX_FCB_IP_CSUM))
349188711Sraj
350188711Sraj#define TSEC_RX_FCB_TCP_UDP_CSUM_CHECKED(flags)					\
351188711Sraj		((flags & (TSEC_RX_FCB_TCP_UDP_FOUND | TSEC_RX_FCB_TCP_UDP_CSUM	\
352188711Sraj		| TSEC_RX_FCB_PARSE_ERROR))					\
353188711Sraj		== (TSEC_RX_FCB_TCP_UDP_FOUND | TSEC_RX_FCB_TCP_UDP_CSUM))
354188711Sraj
355182189Sraj/* Prototypes */
356182189Srajextern devclass_t tsec_devclass;
357182189Sraj
358182189Srajint	tsec_attach(struct tsec_softc *sc);
359182189Srajint	tsec_detach(struct tsec_softc *sc);
360182189Sraj
361182189Srajvoid	tsec_error_intr(void *arg);
362182189Srajvoid	tsec_receive_intr(void *arg);
363182189Srajvoid	tsec_transmit_intr(void *arg);
364182189Sraj
365182189Srajint	tsec_miibus_readreg(device_t dev, int phy, int reg);
366194101Srajint	tsec_miibus_writereg(device_t dev, int phy, int reg, int value);
367182189Srajvoid	tsec_miibus_statchg(device_t dev);
368182189Srajint	tsec_resume(device_t dev); /* XXX */
369194101Srajint	tsec_shutdown(device_t dev);
370182189Srajint	tsec_suspend(device_t dev); /* XXX */
371182189Sraj
372182189Srajvoid	tsec_get_hwaddr(struct tsec_softc *sc, uint8_t *addr);
373182189Sraj
374188712Sraj#endif /* _IF_TSEC_H */
375