xref: /freebsd/sys/dev/dpaa/if_dtsec_im.c (revision 3416500aef140042c64bc149cb1ec6620483bc44)
1 /*-
2  * Copyright (c) 2012 Semihalf.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  */
26 
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
29 
30 #include <sys/param.h>
31 #include <sys/systm.h>
32 #include <sys/kernel.h>
33 #include <sys/module.h>
34 #include <sys/bus.h>
35 #include <sys/rman.h>
36 #include <sys/malloc.h>
37 #include <sys/mbuf.h>
38 #include <sys/socket.h>
39 #include <sys/sysctl.h>
40 #include <sys/sockio.h>
41 
42 #include <net/ethernet.h>
43 #include <net/if.h>
44 #include <net/if_dl.h>
45 #include <net/if_media.h>
46 #include <net/if_types.h>
47 #include <net/if_arp.h>
48 
49 #include <dev/mii/mii.h>
50 #include <dev/mii/miivar.h>
51 
52 #include "miibus_if.h"
53 
54 #include <contrib/ncsw/inc/Peripherals/fm_mac_ext.h>
55 #include <contrib/ncsw/inc/Peripherals/fm_port_ext.h>
56 #include <contrib/ncsw/inc/xx_ext.h>
57 
58 #include "fman.h"
59 #include "if_dtsec.h"
60 #include "if_dtsec_im.h"
61 
62 
63 /**
64  * @group dTSEC FMan PORT routines.
65  * @{
66  */
67 static e_RxStoreResponse
68 dtsec_im_fm_port_rx_callback(t_Handle app, uint8_t *data, uint16_t length,
69     uint16_t status, uint8_t position, t_Handle buf_context)
70 {
71 	struct dtsec_softc *sc;
72 	struct mbuf *m;
73 
74 	/* TODO STATUS / Position checking */
75 	sc = app;
76 
77 	m = m_devget(data, length, 0, sc->sc_ifnet, NULL);
78 	if (m)
79 		(*sc->sc_ifnet->if_input)(sc->sc_ifnet, m);
80 
81 	XX_FreeSmart(data);
82 
83 	return (e_RX_STORE_RESPONSE_CONTINUE);
84 }
85 
86 static void
87 dtsec_im_fm_port_tx_conf_callback(t_Handle app, uint8_t *data, uint16_t status,
88     t_Handle buf_context)
89 {
90 
91 	/* TODO: Check status */
92 	XX_FreeSmart(data);
93 }
94 
95 static uint8_t *
96 dtsec_im_fm_port_rx_get_buf(t_Handle buffer_pool, t_Handle *buf_context_handle)
97 {
98 	struct dtsec_softc *sc;
99 	uint8_t *buffer;
100 
101 	sc = buffer_pool;
102 
103 	buffer = XX_MallocSmart(FM_PORT_BUFFER_SIZE, 0, sizeof(void *));
104 	if (!buffer)
105 		device_printf(sc->sc_dev, "couldn't allocate RX buffer.\n");
106 
107 	return (buffer);
108 }
109 
110 static t_Error
111 dtsec_im_fm_port_rx_put_buf(t_Handle buffer_pool, uint8_t *buffer,
112     t_Handle buf_context)
113 {
114 
115 	XX_FreeSmart(buffer);
116 	return (E_OK);
117 }
118 
119 int
120 dtsec_im_fm_port_rx_init(struct dtsec_softc *sc, int unit)
121 {
122 	t_FmPortParams params;
123 	t_BufferPoolInfo *pool_params;
124 	t_FmPortImRxTxParams *im_params;
125 	t_Error error;
126 
127 	memset(&params, 0, sizeof(params));
128 
129 	params.baseAddr = sc->sc_fm_base + sc->sc_port_rx_hw_id;
130 	params.h_Fm = sc->sc_fmh;
131 	params.portType = dtsec_fm_port_rx_type(sc->sc_eth_dev_type);
132 	params.portId = sc->sc_eth_id;
133 	params.independentModeEnable = TRUE;
134 	params.liodnBase = FM_PORT_LIODN_BASE;
135 	params.f_Exception = dtsec_fm_port_rx_exception_callback;
136 	params.h_App = sc;
137 
138 	im_params = &params.specificParams.imRxTxParams;
139 	im_params->h_FmMuram = sc->sc_muramh;
140 	im_params->liodnOffset = FM_PORT_LIODN_OFFSET;
141 	im_params->dataMemId = FM_PORT_MEM_ID;
142 	im_params->dataMemAttributes = FM_PORT_MEM_ATTR;
143 	im_params->f_RxStore = dtsec_im_fm_port_rx_callback;
144 
145 	pool_params = &params.specificParams.imRxTxParams.rxPoolParams;
146 	pool_params->h_BufferPool = sc;
147 	pool_params->f_GetBuf = dtsec_im_fm_port_rx_get_buf;
148 	pool_params->f_PutBuf = dtsec_im_fm_port_rx_put_buf;
149 	pool_params->bufferSize = FM_PORT_BUFFER_SIZE;
150 
151 	sc->sc_rxph = FM_PORT_Config(&params);
152 	if (sc->sc_rxph == NULL) {
153 		device_printf(sc->sc_dev, "couldn't configure FM Port RX.\n");
154 		return (ENXIO);
155 	}
156 
157 	error = FM_PORT_Init(sc->sc_rxph);
158 	if (error != E_OK) {
159 		device_printf(sc->sc_dev, "couldn't initialize FM Port RX.\n");
160 		FM_PORT_Free(sc->sc_rxph);
161 		return (ENXIO);
162 	}
163 
164 	if (bootverbose)
165 		device_printf(sc->sc_dev, "RX hw port 0x%02x initialized.\n",
166 		    sc->sc_port_rx_hw_id);
167 
168 	return (0);
169 }
170 
171 int
172 dtsec_im_fm_port_tx_init(struct dtsec_softc *sc, int unit)
173 {
174 	t_FmPortParams params;
175 	t_FmPortImRxTxParams *im_params;
176 	t_Error error;
177 
178 	memset(&params, 0, sizeof(params));
179 
180 	params.baseAddr = sc->sc_fm_base + sc->sc_port_tx_hw_id;
181 	params.h_Fm = sc->sc_fmh;
182 	params.portType = dtsec_fm_port_tx_type(sc->sc_eth_dev_type);
183 	params.portId = unit;
184 	params.independentModeEnable = TRUE;
185 	params.liodnBase = FM_PORT_LIODN_BASE;
186 	params.f_Exception = dtsec_fm_port_tx_exception_callback;
187 	params.h_App = sc;
188 
189 	im_params = &params.specificParams.imRxTxParams;
190 	im_params->h_FmMuram = sc->sc_muramh;
191 	im_params->liodnOffset = FM_PORT_LIODN_OFFSET;
192 	im_params->dataMemId = FM_PORT_MEM_ID;
193 	im_params->dataMemAttributes = FM_PORT_MEM_ATTR;
194 	im_params->f_TxConf = dtsec_im_fm_port_tx_conf_callback;
195 
196 	sc->sc_txph = FM_PORT_Config(&params);
197 	if (sc->sc_txph == NULL) {
198 		device_printf(sc->sc_dev, "couldn't configure FM Port TX.\n");
199 		return (ENXIO);
200 	}
201 
202 	error = FM_PORT_Init(sc->sc_txph);
203 	if (error != E_OK) {
204 		device_printf(sc->sc_dev, "couldn't initialize FM Port TX.\n");
205 		FM_PORT_Free(sc->sc_txph);
206 		return (ENXIO);
207 	}
208 
209 	if (bootverbose)
210 		device_printf(sc->sc_dev, "TX hw port 0x%02x initialized.\n",
211 		    sc->sc_port_tx_hw_id);
212 
213 	return (0);
214 }
215 /** @} */
216 
217 
218 /**
219  * @group dTSEC IFnet routines.
220  * @{
221  */
222 void
223 dtsec_im_if_start_locked(struct dtsec_softc *sc)
224 {
225 	uint8_t *buffer;
226 	uint16_t length;
227 	struct mbuf *m;
228 	int error;
229 
230 	DTSEC_LOCK_ASSERT(sc);
231 	/* TODO: IFF_DRV_OACTIVE */
232 
233 	if ((sc->sc_mii->mii_media_status & IFM_ACTIVE) == 0)
234 		return;
235 
236 	if ((sc->sc_ifnet->if_drv_flags & IFF_DRV_RUNNING) != IFF_DRV_RUNNING)
237 		return;
238 
239 	while (!IFQ_DRV_IS_EMPTY(&sc->sc_ifnet->if_snd)) {
240 		IFQ_DRV_DEQUEUE(&sc->sc_ifnet->if_snd, m);
241 		if (m == NULL)
242 			break;
243 
244 		length = m_length(m, NULL);
245 		buffer = XX_MallocSmart(length, 0, sizeof(void *));
246 		if (!buffer) {
247 			m_freem(m);
248 			break;
249 		}
250 
251 		m_copydata(m, 0, length, buffer);
252 		m_freem(m);
253 
254 		error = FM_PORT_ImTx(sc->sc_txph, buffer, length, TRUE, buffer);
255 		if (error != E_OK) {
256 			/* TODO: Ring full */
257 			XX_FreeSmart(buffer);
258 			break;
259 		}
260 	}
261 }
262 /** @} */
263