xref: /freebsd/sys/dev/tsec/if_tsec.h (revision 95ee2897)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause
3  *
4  * Copyright (C) 2006-2007 Semihalf, Piotr Kruszynski
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
19  * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
21  * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
23  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
24  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 #ifndef _IF_TSEC_H
29 #define _IF_TSEC_H
30 
31 #include <dev/ofw/openfirm.h>
32 
33 #define TSEC_RX_NUM_DESC	256
34 #define TSEC_TX_NUM_DESC	256
35 #define	TSEC_TX_MAX_DMA_SEGS	8
36 
37 /* Interrupt Coalescing types */
38 #define	TSEC_IC_RX		0
39 #define	TSEC_IC_TX		1
40 
41 /* eTSEC ID */
42 #define	TSEC_ETSEC_ID		0x0124
43 
44 /* Frame sizes */
45 #define	TSEC_MIN_FRAME_SIZE	64
46 #define	TSEC_MAX_FRAME_SIZE	9600
47 
48 struct tsec_bufmap {
49 	bus_dmamap_t	map;
50 	int		map_initialized;
51 	struct mbuf	*mbuf;
52 };
53 
54 struct tsec_softc {
55 	/* XXX MII bus requires that struct ifnet is first!!! */
56 	if_t		tsec_ifp;
57 
58 	struct mtx	transmit_lock;	/* transmitter lock */
59 	struct mtx	receive_lock;	/* receiver lock */
60 
61 	phandle_t	node;
62 	device_t	dev;
63 	device_t	tsec_miibus;
64 	struct mii_data	*tsec_mii;	/* MII media control */
65 	int		tsec_link;
66 
67 	bus_dma_tag_t	tsec_tx_dtag;	/* TX descriptors tag */
68 	bus_dmamap_t	tsec_tx_dmap;	/* TX descriptors map */
69 	bus_dma_tag_t	tsec_tx_mtag;	/* TX mbufs tag */
70 	uint32_t	tx_idx_head;	/* TX head descriptor/bufmap index */
71 	uint32_t	tx_idx_tail;	/* TX tail descriptor/bufmap index */
72 	struct tsec_desc *tsec_tx_vaddr;/* virtual address of TX descriptors */
73 	struct tsec_bufmap tx_bufmap[TSEC_TX_NUM_DESC];
74 
75 	bus_dma_tag_t	tsec_rx_mtag;	/* TX mbufs tag */
76 	bus_dma_tag_t	tsec_rx_dtag;	/* RX descriptors tag */
77 	bus_dmamap_t	tsec_rx_dmap;	/* RX descriptors map */
78 	struct tsec_desc *tsec_rx_vaddr; /* vadress of RX descriptors */
79 
80 	struct rx_data_type {
81 		bus_dmamap_t	map;	/* mbuf map */
82 		struct mbuf	*mbuf;
83 		uint32_t	paddr;	/* DMA address of buffer */
84 	} rx_data[TSEC_RX_NUM_DESC];
85 
86 	uint32_t	rx_cur_desc_cnt;
87 
88 	struct resource	*sc_rres;	/* register resource */
89 	int		sc_rrid;	/* register rid */
90 	struct {
91 		bus_space_tag_t bst;
92 		bus_space_handle_t bsh;
93 	} sc_bas;
94 
95 	struct resource *sc_transmit_ires;
96 	void		*sc_transmit_ihand;
97 	int		sc_transmit_irid;
98 	struct resource *sc_receive_ires;
99 	void		*sc_receive_ihand;
100 	int		sc_receive_irid;
101 	struct resource *sc_error_ires;
102 	void		*sc_error_ihand;
103 	int		sc_error_irid;
104 
105 	int		tsec_if_flags;
106 	int		is_etsec;
107 
108 	/* Watchdog and MII tick related */
109 	struct callout	tsec_callout;
110 	int		tsec_watchdog;
111 
112 	/* interrupt coalescing */
113 	struct mtx	ic_lock;
114 	uint32_t	rx_ic_time;	/* RW, valid values 0..65535 */
115 	uint32_t	rx_ic_count;	/* RW, valid values 0..255 */
116 	uint32_t	tx_ic_time;
117 	uint32_t	tx_ic_count;
118 
119 	/* currently received frame */
120 	struct mbuf	*frame;
121 
122 	int		phyaddr;
123 	bus_space_tag_t phy_bst;
124 	bus_space_handle_t phy_bsh;
125 	int		phy_regoff;
126 
127 	uint32_t	tsec_rx_raddr;	/* real address of RX descriptors */
128 	uint32_t	tsec_tx_raddr;	/* real address of TX descriptors */
129 };
130 
131 /* interface to get/put generic objects */
132 #define TSEC_CNT_INIT(cnt, wrap) ((cnt) = ((wrap) - 1))
133 
134 #define TSEC_INC(count, wrap) (count = ((count) + 1) & ((wrap) - 1))
135 
136 #define TSEC_GET_GENERIC(hand, tab, count, wrap) \
137 		((hand)->tab[TSEC_INC((hand)->count, wrap)])
138 
139 #define TSEC_PUT_GENERIC(hand, tab, count, wrap, val)	\
140 		((hand)->tab[TSEC_INC((hand)->count, wrap)] = val)
141 
142 #define TSEC_BACK_GENERIC(sc, count, wrap) do {			\
143 		if ((sc)->count > 0)				\
144 			(sc)->count--;				\
145 		else						\
146 			(sc)->count = (wrap) - 1;		\
147 } while (0)
148 
149 #define TSEC_FREE_TX_DESC(sc) \
150     (((sc)->tx_idx_tail - (sc)->tx_idx_head - 1) & (TSEC_TX_NUM_DESC - 1))
151 
152 /* interface for manage rx tsec_desc */
153 #define TSEC_RX_DESC_CNT_INIT(sc) do {					\
154 		TSEC_CNT_INIT((sc)->rx_cur_desc_cnt, TSEC_RX_NUM_DESC);	\
155 } while (0)
156 
157 #define TSEC_GET_CUR_RX_DESC(sc)					\
158 		&TSEC_GET_GENERIC(sc, tsec_rx_vaddr, rx_cur_desc_cnt,	\
159 		TSEC_RX_NUM_DESC)
160 
161 #define TSEC_BACK_CUR_RX_DESC(sc) \
162 		TSEC_BACK_GENERIC(sc, rx_cur_desc_cnt, TSEC_RX_NUM_DESC)
163 
164 #define TSEC_GET_CUR_RX_DESC_CNT(sc) \
165 		((sc)->rx_cur_desc_cnt)
166 
167 /* init all counters (for init only!) */
168 #define TSEC_TX_RX_COUNTERS_INIT(sc) do {	\
169 		sc->tx_idx_head = 0;		\
170 		sc->tx_idx_tail = 0;		\
171 		TSEC_RX_DESC_CNT_INIT(sc);	\
172 } while (0)
173 
174 /* read/write bus functions */
175 #define TSEC_READ(sc, reg)		\
176 		bus_space_read_4((sc)->sc_bas.bst, (sc)->sc_bas.bsh, (reg))
177 #define TSEC_WRITE(sc, reg, val)	\
178 		bus_space_write_4((sc)->sc_bas.bst, (sc)->sc_bas.bsh, (reg), (val))
179 
180 extern struct mtx tsec_phy_mtx;
181 #define TSEC_PHY_LOCK(sc)	mtx_lock(&tsec_phy_mtx)
182 #define TSEC_PHY_UNLOCK(sc)	mtx_unlock(&tsec_phy_mtx)
183 #define TSEC_PHY_READ(sc, reg)		\
184 		bus_space_read_4((sc)->phy_bst, (sc)->phy_bsh, \
185 			(reg) + (sc)->phy_regoff)
186 #define TSEC_PHY_WRITE(sc, reg, val)	\
187 		bus_space_write_4((sc)->phy_bst, (sc)->phy_bsh, \
188 			(reg) + (sc)->phy_regoff, (val))
189 
190 /* Lock for transmitter */
191 #define TSEC_TRANSMIT_LOCK(sc) do {					\
192 		mtx_assert(&(sc)->receive_lock, MA_NOTOWNED);		\
193 		mtx_lock(&(sc)->transmit_lock);				\
194 } while (0)
195 
196 #define TSEC_TRANSMIT_UNLOCK(sc)	mtx_unlock(&(sc)->transmit_lock)
197 #define TSEC_TRANSMIT_LOCK_ASSERT(sc)	mtx_assert(&(sc)->transmit_lock, MA_OWNED)
198 
199 /* Lock for receiver */
200 #define TSEC_RECEIVE_LOCK(sc) do {					\
201 		mtx_assert(&(sc)->transmit_lock, MA_NOTOWNED);		\
202 		mtx_lock(&(sc)->receive_lock);				\
203 } while (0)
204 
205 #define TSEC_RECEIVE_UNLOCK(sc)		mtx_unlock(&(sc)->receive_lock)
206 #define TSEC_RECEIVE_LOCK_ASSERT(sc)	mtx_assert(&(sc)->receive_lock, MA_OWNED)
207 
208 /* Lock for interrupts coalescing */
209 #define	TSEC_IC_LOCK(sc) do {						\
210 		mtx_assert(&(sc)->ic_lock, MA_NOTOWNED);		\
211 		mtx_lock(&(sc)->ic_lock);				\
212 } while (0)
213 
214 #define	TSEC_IC_UNLOCK(sc)		mtx_unlock(&(sc)->ic_lock)
215 #define	TSEC_IC_LOCK_ASSERT(sc)		mtx_assert(&(sc)->ic_lock, MA_OWNED)
216 
217 /* Global tsec lock (with all locks) */
218 #define TSEC_GLOBAL_LOCK(sc) do {					\
219 		if ((mtx_owned(&(sc)->transmit_lock) ? 1 : 0) !=	\
220 			(mtx_owned(&(sc)->receive_lock) ? 1 : 0)) {	\
221 			panic("tsec deadlock possibility detection!");	\
222 		}							\
223 		mtx_lock(&(sc)->transmit_lock);				\
224 		mtx_lock(&(sc)->receive_lock);				\
225 } while (0)
226 
227 #define TSEC_GLOBAL_UNLOCK(sc) do {		\
228 		TSEC_RECEIVE_UNLOCK(sc);	\
229 		TSEC_TRANSMIT_UNLOCK(sc);	\
230 } while (0)
231 
232 #define TSEC_GLOBAL_LOCK_ASSERT(sc) do {	\
233 		TSEC_TRANSMIT_LOCK_ASSERT(sc);	\
234 		TSEC_RECEIVE_LOCK_ASSERT(sc);	\
235 } while (0)
236 
237 /* From global to {transmit,receive} */
238 #define TSEC_GLOBAL_TO_TRANSMIT_LOCK(sc) do {	\
239 		mtx_unlock(&(sc)->receive_lock);\
240 } while (0)
241 
242 #define TSEC_GLOBAL_TO_RECEIVE_LOCK(sc) do {	\
243 		mtx_unlock(&(sc)->transmit_lock);\
244 } while (0)
245 
246 struct tsec_desc {
247 	volatile uint16_t	flags;	/* descriptor flags */
248 	volatile uint16_t	length;	/* buffer length */
249 	volatile uint32_t	bufptr;	/* buffer pointer */
250 };
251 
252 #define TSEC_READ_RETRY	10000
253 #define TSEC_READ_DELAY	100
254 
255 /* Structures and defines for TCP/IP Off-load */
256 struct tsec_tx_fcb {
257 	volatile uint16_t	flags;
258 	volatile uint8_t	l4_offset;
259 	volatile uint8_t	l3_offset;
260 	volatile uint16_t	ph_chsum;
261 	volatile uint16_t	vlan;
262 };
263 
264 struct tsec_rx_fcb {
265 	volatile uint16_t	flags;
266 	volatile uint8_t	rq_index;
267 	volatile uint8_t	protocol;
268 	volatile uint16_t	unused;
269 	volatile uint16_t	vlan;
270 };
271 
272 #define	TSEC_CHECKSUM_FEATURES	(CSUM_IP | CSUM_TCP | CSUM_UDP)
273 
274 #define	TSEC_TX_FCB_IP4		TSEC_TX_FCB_L3_IS_IP
275 #define	TSEC_TX_FCB_IP6		(TSEC_TX_FCB_L3_IS_IP | TSEC_TX_FCB_L3_IS_IP6)
276 
277 #define	TSEC_TX_FCB_TCP		TSEC_TX_FCB_L4_IS_TCP_UDP
278 #define	TSEC_TX_FCB_UDP		(TSEC_TX_FCB_L4_IS_TCP_UDP | TSEC_TX_FCB_L4_IS_UDP)
279 
280 #define	TSEC_RX_FCB_IP_CSUM_CHECKED(flags)					\
281 		((flags & (TSEC_RX_FCB_IP_FOUND | TSEC_RX_FCB_IP6_FOUND |	\
282 		TSEC_RX_FCB_IP_CSUM | TSEC_RX_FCB_PARSE_ERROR))			\
283 		 == (TSEC_RX_FCB_IP_FOUND | TSEC_RX_FCB_IP_CSUM))
284 
285 #define TSEC_RX_FCB_TCP_UDP_CSUM_CHECKED(flags)					\
286 		((flags & (TSEC_RX_FCB_TCP_UDP_FOUND | TSEC_RX_FCB_TCP_UDP_CSUM	\
287 		| TSEC_RX_FCB_PARSE_ERROR))					\
288 		== (TSEC_RX_FCB_TCP_UDP_FOUND | TSEC_RX_FCB_TCP_UDP_CSUM))
289 
290 /* Prototypes */
291 int	tsec_attach(struct tsec_softc *sc);
292 int	tsec_detach(struct tsec_softc *sc);
293 
294 void	tsec_error_intr(void *arg);
295 void	tsec_receive_intr(void *arg);
296 void	tsec_transmit_intr(void *arg);
297 
298 int	tsec_miibus_readreg(device_t dev, int phy, int reg);
299 int	tsec_miibus_writereg(device_t dev, int phy, int reg, int value);
300 void	tsec_miibus_statchg(device_t dev);
301 int	tsec_resume(device_t dev); /* XXX */
302 int	tsec_shutdown(device_t dev);
303 int	tsec_suspend(device_t dev); /* XXX */
304 
305 void	tsec_get_hwaddr(struct tsec_softc *sc, uint8_t *addr);
306 
307 #endif /* _IF_TSEC_H */
308