if_tsec.h revision 176774
1176774Sraj/*-
2176774Sraj * Copyright (C) 2006-2007 Semihalf
3176774Sraj * All rights reserved.
4176774Sraj *
5176774Sraj * Written by: Piotr Kruszynski <ppk@semihalf.com>
6176774Sraj *
7176774Sraj * Redistribution and use in source and binary forms, with or without
8176774Sraj * modification, are permitted provided that the following conditions
9176774Sraj * are met:
10176774Sraj * 1. Redistributions of source code must retain the above copyright
11176774Sraj *    notice, this list of conditions and the following disclaimer.
12176774Sraj * 2. Redistributions in binary form must reproduce the above copyright
13176774Sraj *    notice, this list of conditions and the following disclaimer in the
14176774Sraj *    documentation and/or other materials provided with the distribution.
15176774Sraj * 3. The name of the author may not be used to endorse or promote products
16176774Sraj *    derived from this software without specific prior written permission.
17176774Sraj *
18176774Sraj * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19176774Sraj * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20176774Sraj * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
21176774Sraj * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22176774Sraj * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
23176774Sraj * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24176774Sraj * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25176774Sraj * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26176774Sraj * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27176774Sraj * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28176774Sraj *
29176774Sraj * $FreeBSD: head/sys/dev/tsec/if_tsec.h 176774 2008-03-03 19:03:44Z raj $
30176774Sraj */
31176774Sraj
32176774Sraj#define TSEC_RX_NUM_DESC	256
33176774Sraj#define TSEC_TX_NUM_DESC	256
34176774Sraj
35176774Sraj#define	OCP_TSEC_RID_TXIRQ	0
36176774Sraj#define	OCP_TSEC_RID_RXIRQ	1
37176774Sraj#define	OCP_TSEC_RID_ERRIRQ	2
38176774Sraj
39176774Srajstruct tsec_softc {
40176774Sraj	/* XXX MII bus requires that struct ifnet is first!!! */
41176774Sraj	struct ifnet	*tsec_ifp;
42176774Sraj
43176774Sraj	struct mtx	transmit_lock;	/* transmitter lock */
44176774Sraj	struct mtx	receive_lock;	/* receiver lock */
45176774Sraj
46176774Sraj	device_t	dev;
47176774Sraj	device_t	tsec_miibus;
48176774Sraj	struct mii_data	*tsec_mii;	/* MII media control */
49176774Sraj	struct callout	tsec_tick_ch;
50176774Sraj	int		tsec_link;
51176774Sraj
52176774Sraj	bus_dma_tag_t	tsec_tx_dtag;	/* TX descriptors tag */
53176774Sraj	bus_dmamap_t	tsec_tx_dmap;	/* TX descriptors map */
54176774Sraj	struct tsec_desc *tsec_tx_vaddr;/* vadress of TX descriptors */
55176774Sraj	uint32_t	tsec_tx_raddr;	/* real adress of TX descriptors */
56176774Sraj
57176774Sraj	bus_dma_tag_t	tsec_rx_dtag;	/* RX descriptors tag */
58176774Sraj	bus_dmamap_t	tsec_rx_dmap;	/* RX descriptors map */
59176774Sraj	struct tsec_desc *tsec_rx_vaddr; /* vadress of RX descriptors */
60176774Sraj	uint32_t	tsec_rx_raddr;	/* real adress of RX descriptors */
61176774Sraj
62176774Sraj	bus_dma_tag_t	tsec_tx_mtag;	/* TX mbufs tag */
63176774Sraj	bus_dma_tag_t	tsec_rx_mtag;	/* TX mbufs tag */
64176774Sraj
65176774Sraj	struct rx_data_type {
66176774Sraj		bus_dmamap_t	map;	/* mbuf map */
67176774Sraj		struct mbuf	*mbuf;
68176774Sraj		uint32_t	paddr;	/* DMA addres of buffer */
69176774Sraj	} rx_data[TSEC_RX_NUM_DESC];
70176774Sraj
71176774Sraj	uint32_t	tx_cur_desc_cnt;
72176774Sraj	uint32_t	tx_dirty_desc_cnt;
73176774Sraj	uint32_t	rx_cur_desc_cnt;
74176774Sraj
75176774Sraj	struct resource	*sc_rres;	/* register resource */
76176774Sraj	int		sc_rrid;	/* register rid */
77176774Sraj	struct {
78176774Sraj		bus_space_tag_t bst;
79176774Sraj		bus_space_handle_t bsh;
80176774Sraj	} sc_bas;
81176774Sraj
82176774Sraj	struct resource *sc_transmit_ires;
83176774Sraj	void		*sc_transmit_ihand;
84176774Sraj	int		sc_transmit_irid;
85176774Sraj	struct resource *sc_receive_ires;
86176774Sraj	void		*sc_receive_ihand;
87176774Sraj	int		sc_receive_irid;
88176774Sraj	struct resource *sc_error_ires;
89176774Sraj	void		*sc_error_ihand;
90176774Sraj	int		sc_error_irid;
91176774Sraj
92176774Sraj	int		tsec_if_flags;
93176774Sraj
94176774Sraj	/* TX maps */
95176774Sraj	bus_dmamap_t	tx_map_data[TSEC_TX_NUM_DESC];
96176774Sraj
97176774Sraj	/* unused TX maps data */
98176774Sraj	uint32_t	tx_map_unused_get_cnt;
99176774Sraj	uint32_t	tx_map_unused_put_cnt;
100176774Sraj	bus_dmamap_t	*tx_map_unused_data[TSEC_TX_NUM_DESC];
101176774Sraj
102176774Sraj	/* used TX maps data */
103176774Sraj	uint32_t	tx_map_used_get_cnt;
104176774Sraj	uint32_t	tx_map_used_put_cnt;
105176774Sraj	bus_dmamap_t	*tx_map_used_data[TSEC_TX_NUM_DESC];
106176774Sraj
107176774Sraj	/* mbufs in TX queue */
108176774Sraj	uint32_t	tx_mbuf_used_get_cnt;
109176774Sraj	uint32_t	tx_mbuf_used_put_cnt;
110176774Sraj	struct mbuf	*tx_mbuf_used_data[TSEC_TX_NUM_DESC];
111176774Sraj};
112176774Sraj
113176774Sraj/* interface to get/put generic objects */
114176774Sraj#define TSEC_CNT_INIT(cnt, wrap) ((cnt) = ((wrap) - 1))
115176774Sraj
116176774Sraj#define TSEC_INC(count, wrap) (count = ((count) + 1) & ((wrap) - 1))
117176774Sraj
118176774Sraj#define TSEC_GET_GENERIC(hand, tab, count, wrap) \
119176774Sraj		((hand)->tab[TSEC_INC((hand)->count, wrap)])
120176774Sraj
121176774Sraj#define TSEC_PUT_GENERIC(hand, tab, count, wrap, val)	\
122176774Sraj		((hand)->tab[TSEC_INC((hand)->count, wrap)] = val)
123176774Sraj
124176774Sraj#define TSEC_BACK_GENERIC(sc, count, wrap) do {				\
125176774Sraj		if ((sc)->count > 0)					\
126176774Sraj			(sc)->count--;					\
127176774Sraj		else							\
128176774Sraj			(sc)->count = (wrap) - 1;			\
129176774Sraj} while (0)
130176774Sraj
131176774Sraj/* TX maps interface */
132176774Sraj#define TSEC_TX_MAP_CNT_INIT(sc) do {						\
133176774Sraj		TSEC_CNT_INIT((sc)->tx_map_unused_get_cnt, TSEC_TX_NUM_DESC);	\
134176774Sraj		TSEC_CNT_INIT((sc)->tx_map_unused_put_cnt, TSEC_TX_NUM_DESC);	\
135176774Sraj		TSEC_CNT_INIT((sc)->tx_map_used_get_cnt, TSEC_TX_NUM_DESC);	\
136176774Sraj		TSEC_CNT_INIT((sc)->tx_map_used_put_cnt, TSEC_TX_NUM_DESC);	\
137176774Sraj} while (0)
138176774Sraj
139176774Sraj/* interface to get/put unused TX maps */
140176774Sraj#define TSEC_ALLOC_TX_MAP(sc)							\
141176774Sraj		TSEC_GET_GENERIC(sc, tx_map_unused_data, tx_map_unused_get_cnt,	\
142176774Sraj		TSEC_TX_NUM_DESC)
143176774Sraj
144176774Sraj#define TSEC_FREE_TX_MAP(sc, val)						\
145176774Sraj		TSEC_PUT_GENERIC(sc, tx_map_unused_data, tx_map_unused_put_cnt,	\
146176774Sraj		TSEC_TX_NUM_DESC, val)
147176774Sraj
148176774Sraj/* interface to get/put used TX maps */
149176774Sraj#define TSEC_GET_TX_MAP(sc)							\
150176774Sraj		TSEC_GET_GENERIC(sc, tx_map_used_data, tx_map_used_get_cnt,	\
151176774Sraj		TSEC_TX_NUM_DESC)
152176774Sraj
153176774Sraj#define TSEC_PUT_TX_MAP(sc, val)						\
154176774Sraj		TSEC_PUT_GENERIC(sc, tx_map_used_data, tx_map_used_put_cnt,	\
155176774Sraj		TSEC_TX_NUM_DESC, val)
156176774Sraj
157176774Sraj/* interface to get/put TX mbufs in send queue */
158176774Sraj#define TSEC_TX_MBUF_CNT_INIT(sc) do {						\
159176774Sraj		TSEC_CNT_INIT((sc)->tx_mbuf_used_get_cnt, TSEC_TX_NUM_DESC);	\
160176774Sraj		TSEC_CNT_INIT((sc)->tx_mbuf_used_put_cnt, TSEC_TX_NUM_DESC);	\
161176774Sraj} while (0)
162176774Sraj
163176774Sraj#define TSEC_GET_TX_MBUF(sc)							\
164176774Sraj		TSEC_GET_GENERIC(sc, tx_mbuf_used_data, tx_mbuf_used_get_cnt,	\
165176774Sraj		TSEC_TX_NUM_DESC)
166176774Sraj
167176774Sraj#define TSEC_PUT_TX_MBUF(sc, val)						\
168176774Sraj		TSEC_PUT_GENERIC(sc, tx_mbuf_used_data, tx_mbuf_used_put_cnt,	\
169176774Sraj		TSEC_TX_NUM_DESC, val)
170176774Sraj
171176774Sraj#define TSEC_EMPTYQ_TX_MBUF(sc) \
172176774Sraj		((sc)->tx_mbuf_used_get_cnt == (sc)->tx_mbuf_used_put_cnt)
173176774Sraj
174176774Sraj/* interface for manage tx tsec_desc */
175176774Sraj#define TSEC_TX_DESC_CNT_INIT(sc) do {						\
176176774Sraj		TSEC_CNT_INIT((sc)->tx_cur_desc_cnt, TSEC_TX_NUM_DESC);		\
177176774Sraj		TSEC_CNT_INIT((sc)->tx_dirty_desc_cnt, TSEC_TX_NUM_DESC);	\
178176774Sraj} while (0)
179176774Sraj
180176774Sraj#define TSEC_GET_CUR_TX_DESC(sc)					\
181176774Sraj		&TSEC_GET_GENERIC(sc, tsec_tx_vaddr, tx_cur_desc_cnt,	\
182176774Sraj		TSEC_TX_NUM_DESC)
183176774Sraj
184176774Sraj#define TSEC_GET_DIRTY_TX_DESC(sc)					\
185176774Sraj		&TSEC_GET_GENERIC(sc, tsec_tx_vaddr, tx_dirty_desc_cnt,	\
186176774Sraj		TSEC_TX_NUM_DESC)
187176774Sraj
188176774Sraj#define TSEC_BACK_DIRTY_TX_DESC(sc) \
189176774Sraj		TSEC_BACK_GENERIC(sc, tx_dirty_desc_cnt, TSEC_TX_NUM_DESC)
190176774Sraj
191176774Sraj#define TSEC_CUR_DIFF_DIRTY_TX_DESC(sc) \
192176774Sraj		((sc)->tx_cur_desc_cnt != (sc)->tx_dirty_desc_cnt)
193176774Sraj
194176774Sraj#define TSEC_FREE_TX_DESC(sc)						\
195176774Sraj		(((sc)->tx_cur_desc_cnt < (sc)->tx_dirty_desc_cnt) ?	\
196176774Sraj		((sc)->tx_dirty_desc_cnt - (sc)->tx_cur_desc_cnt - 1)	\
197176774Sraj		:							\
198176774Sraj		(TSEC_TX_NUM_DESC - (sc)->tx_cur_desc_cnt		\
199176774Sraj		+ (sc)->tx_dirty_desc_cnt - 1))
200176774Sraj
201176774Sraj/* interface for manage rx tsec_desc */
202176774Sraj#define TSEC_RX_DESC_CNT_INIT(sc) do {					\
203176774Sraj		TSEC_CNT_INIT((sc)->rx_cur_desc_cnt, TSEC_RX_NUM_DESC);	\
204176774Sraj} while (0)
205176774Sraj
206176774Sraj#define TSEC_GET_CUR_RX_DESC(sc)					\
207176774Sraj		&TSEC_GET_GENERIC(sc, tsec_rx_vaddr, rx_cur_desc_cnt,	\
208176774Sraj		TSEC_RX_NUM_DESC)
209176774Sraj
210176774Sraj#define TSEC_BACK_CUR_RX_DESC(sc) \
211176774Sraj		TSEC_BACK_GENERIC(sc, rx_cur_desc_cnt, TSEC_RX_NUM_DESC)
212176774Sraj
213176774Sraj#define TSEC_GET_CUR_RX_DESC_CNT(sc) \
214176774Sraj		((sc)->rx_cur_desc_cnt)
215176774Sraj
216176774Sraj/* init all counters (for init only!) */
217176774Sraj#define TSEC_TX_RX_COUNTERS_INIT(sc) do {	\
218176774Sraj		TSEC_TX_MAP_CNT_INIT(sc);	\
219176774Sraj		TSEC_TX_MBUF_CNT_INIT(sc);	\
220176774Sraj		TSEC_TX_DESC_CNT_INIT(sc);	\
221176774Sraj		TSEC_RX_DESC_CNT_INIT(sc);	\
222176774Sraj} while (0)
223176774Sraj
224176774Sraj/* read/write bus functions */
225176774Sraj#define TSEC_READ(sc, reg)		\
226176774Sraj		bus_space_read_4((sc)->sc_bas.bst, (sc)->sc_bas.bsh, (reg))
227176774Sraj#define TSEC_WRITE(sc, reg, val)	\
228176774Sraj		bus_space_write_4((sc)->sc_bas.bst, (sc)->sc_bas.bsh, (reg), (val))
229176774Sraj
230176774Sraj/* Lock for transmitter */
231176774Sraj#define TSEC_TRANSMIT_LOCK(sc) do {					\
232176774Sraj		mtx_assert(&(sc)->receive_lock, MA_NOTOWNED);		\
233176774Sraj		mtx_lock(&(sc)->transmit_lock);				\
234176774Sraj} while (0)
235176774Sraj
236176774Sraj#define TSEC_TRANSMIT_UNLOCK(sc)	mtx_unlock(&(sc)->transmit_lock)
237176774Sraj#define TSEC_TRANSMIT_LOCK_ASSERT(sc)	mtx_assert(&(sc)->transmit_lock, MA_OWNED)
238176774Sraj
239176774Sraj/* Lock for receiver */
240176774Sraj#define TSEC_RECEIVE_LOCK(sc) do {				\
241176774Sraj		mtx_assert(&(sc)->transmit_lock, MA_NOTOWNED);	\
242176774Sraj		mtx_lock(&(sc)->receive_lock);			\
243176774Sraj} while (0)
244176774Sraj
245176774Sraj#define TSEC_RECEIVE_UNLOCK(sc)		mtx_unlock(&(sc)->receive_lock)
246176774Sraj#define TSEC_RECEIVE_LOCK_ASSERT(sc)	mtx_assert(&(sc)->receive_lock, MA_OWNED)
247176774Sraj
248176774Sraj/* Global tsec lock (with all locks) */
249176774Sraj#define TSEC_GLOBAL_LOCK(sc) do {					\
250176774Sraj		if ((mtx_owned(&(sc)->transmit_lock) ? 1 : 0) !=	\
251176774Sraj			(mtx_owned(&(sc)->receive_lock) ? 1 : 0)) {	\
252176774Sraj			panic("tsec deadlock possibility detection!");	\
253176774Sraj		}							\
254176774Sraj		mtx_lock(&(sc)->transmit_lock);				\
255176774Sraj		mtx_lock(&(sc)->receive_lock);				\
256176774Sraj} while (0)
257176774Sraj
258176774Sraj#define TSEC_GLOBAL_UNLOCK(sc) do {		\
259176774Sraj		TSEC_RECEIVE_UNLOCK(sc);	\
260176774Sraj		TSEC_TRANSMIT_UNLOCK(sc);	\
261176774Sraj} while (0)
262176774Sraj
263176774Sraj#define TSEC_GLOBAL_LOCK_ASSERT(sc) do {	\
264176774Sraj		TSEC_TRANSMIT_LOCK_ASSERT(sc);	\
265176774Sraj		TSEC_RECEIVE_LOCK_ASSERT(sc);	\
266176774Sraj} while (0)
267176774Sraj
268176774Sraj/* From global to {transmit,receive} */
269176774Sraj#define TSEC_GLOBAL_TO_TRANSMIT_LOCK(sc) do {	\
270176774Sraj		mtx_unlock(&(sc)->receive_lock);\
271176774Sraj} while (0)
272176774Sraj
273176774Sraj#define TSEC_GLOBAL_TO_RECEIVE_LOCK(sc) do {	\
274176774Sraj		mtx_unlock(&(sc)->transmit_lock);\
275176774Sraj} while (0)
276176774Sraj
277176774Srajstruct tsec_desc {
278176774Sraj	volatile uint16_t	flags; /* descriptor flags */
279176774Sraj	volatile uint16_t	length; /* buffer length */
280176774Sraj	volatile uint32_t	bufptr; /* buffer pointer */
281176774Sraj};
282176774Sraj
283176774Sraj#define TSEC_READ_RETRY	10000
284176774Sraj#define TSEC_READ_DELAY	100
285