xref: /freebsd/sys/dev/dpaa/if_dtsec_im.c (revision 069ac184)
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/param.h>
28 #include <sys/systm.h>
29 #include <sys/kernel.h>
30 #include <sys/module.h>
31 #include <sys/bus.h>
32 #include <sys/rman.h>
33 #include <sys/malloc.h>
34 #include <sys/mbuf.h>
35 #include <sys/socket.h>
36 #include <sys/sysctl.h>
37 #include <sys/sockio.h>
38 
39 #include <net/ethernet.h>
40 #include <net/if.h>
41 #include <net/if_dl.h>
42 #include <net/if_media.h>
43 #include <net/if_types.h>
44 #include <net/if_arp.h>
45 
46 #include <dev/mii/mii.h>
47 #include <dev/mii/miivar.h>
48 
49 #include "miibus_if.h"
50 
51 #include <contrib/ncsw/inc/integrations/dpaa_integration_ext.h>
52 #include <contrib/ncsw/inc/Peripherals/fm_mac_ext.h>
53 #include <contrib/ncsw/inc/Peripherals/fm_port_ext.h>
54 #include <contrib/ncsw/inc/xx_ext.h>
55 
56 #include "fman.h"
57 #include "if_dtsec.h"
58 #include "if_dtsec_im.h"
59 
60 
61 /**
62  * @group dTSEC FMan PORT routines.
63  * @{
64  */
65 static e_RxStoreResponse
66 dtsec_im_fm_port_rx_callback(t_Handle app, uint8_t *data, uint16_t length,
67     uint16_t status, uint8_t position, t_Handle buf_context)
68 {
69 	struct dtsec_softc *sc;
70 	struct mbuf *m;
71 
72 	/* TODO STATUS / Position checking */
73 	sc = app;
74 
75 	m = m_devget(data, length, 0, sc->sc_ifnet, NULL);
76 	if (m)
77 		if_input(sc->sc_ifnet, m);
78 
79 	XX_FreeSmart(data);
80 
81 	return (e_RX_STORE_RESPONSE_CONTINUE);
82 }
83 
84 static void
85 dtsec_im_fm_port_tx_conf_callback(t_Handle app, uint8_t *data, uint16_t status,
86     t_Handle buf_context)
87 {
88 
89 	/* TODO: Check status */
90 	XX_FreeSmart(data);
91 }
92 
93 static uint8_t *
94 dtsec_im_fm_port_rx_get_buf(t_Handle buffer_pool, t_Handle *buf_context_handle)
95 {
96 	struct dtsec_softc *sc;
97 	uint8_t *buffer;
98 
99 	sc = buffer_pool;
100 
101 	buffer = XX_MallocSmart(FM_PORT_BUFFER_SIZE, 0, sizeof(void *));
102 	if (!buffer)
103 		device_printf(sc->sc_dev, "couldn't allocate RX buffer.\n");
104 
105 	return (buffer);
106 }
107 
108 static t_Error
109 dtsec_im_fm_port_rx_put_buf(t_Handle buffer_pool, uint8_t *buffer,
110     t_Handle buf_context)
111 {
112 
113 	XX_FreeSmart(buffer);
114 	return (E_OK);
115 }
116 
117 int
118 dtsec_im_fm_port_rx_init(struct dtsec_softc *sc, int unit)
119 {
120 	t_FmPortParams params;
121 	t_BufferPoolInfo *pool_params;
122 	t_FmPortImRxTxParams *im_params;
123 	t_Error error;
124 
125 	memset(&params, 0, sizeof(params));
126 
127 	params.baseAddr = sc->sc_fm_base + sc->sc_port_rx_hw_id;
128 	params.h_Fm = sc->sc_fmh;
129 	params.portType = dtsec_fm_port_rx_type(sc->sc_eth_dev_type);
130 	params.portId = sc->sc_eth_id;
131 	params.independentModeEnable = TRUE;
132 	params.liodnBase = FM_PORT_LIODN_BASE;
133 	params.f_Exception = dtsec_fm_port_rx_exception_callback;
134 	params.h_App = sc;
135 
136 	im_params = &params.specificParams.imRxTxParams;
137 	im_params->h_FmMuram = sc->sc_muramh;
138 	im_params->liodnOffset = FM_PORT_LIODN_OFFSET;
139 	im_params->dataMemId = FM_PORT_MEM_ID;
140 	im_params->dataMemAttributes = FM_PORT_MEM_ATTR;
141 	im_params->f_RxStore = dtsec_im_fm_port_rx_callback;
142 
143 	pool_params = &params.specificParams.imRxTxParams.rxPoolParams;
144 	pool_params->h_BufferPool = sc;
145 	pool_params->f_GetBuf = dtsec_im_fm_port_rx_get_buf;
146 	pool_params->f_PutBuf = dtsec_im_fm_port_rx_put_buf;
147 	pool_params->bufferSize = FM_PORT_BUFFER_SIZE;
148 
149 	sc->sc_rxph = FM_PORT_Config(&params);
150 	if (sc->sc_rxph == NULL) {
151 		device_printf(sc->sc_dev, "couldn't configure FM Port RX.\n");
152 		return (ENXIO);
153 	}
154 
155 	error = FM_PORT_Init(sc->sc_rxph);
156 	if (error != E_OK) {
157 		device_printf(sc->sc_dev, "couldn't initialize FM Port RX.\n");
158 		FM_PORT_Free(sc->sc_rxph);
159 		return (ENXIO);
160 	}
161 
162 	if (bootverbose)
163 		device_printf(sc->sc_dev, "RX hw port 0x%02x initialized.\n",
164 		    sc->sc_port_rx_hw_id);
165 
166 	return (0);
167 }
168 
169 int
170 dtsec_im_fm_port_tx_init(struct dtsec_softc *sc, int unit)
171 {
172 	t_FmPortParams params;
173 	t_FmPortImRxTxParams *im_params;
174 	t_Error error;
175 
176 	memset(&params, 0, sizeof(params));
177 
178 	params.baseAddr = sc->sc_fm_base + sc->sc_port_tx_hw_id;
179 	params.h_Fm = sc->sc_fmh;
180 	params.portType = dtsec_fm_port_tx_type(sc->sc_eth_dev_type);
181 	params.portId = unit;
182 	params.independentModeEnable = TRUE;
183 	params.liodnBase = FM_PORT_LIODN_BASE;
184 	params.f_Exception = dtsec_fm_port_tx_exception_callback;
185 	params.h_App = sc;
186 
187 	im_params = &params.specificParams.imRxTxParams;
188 	im_params->h_FmMuram = sc->sc_muramh;
189 	im_params->liodnOffset = FM_PORT_LIODN_OFFSET;
190 	im_params->dataMemId = FM_PORT_MEM_ID;
191 	im_params->dataMemAttributes = FM_PORT_MEM_ATTR;
192 	im_params->f_TxConf = dtsec_im_fm_port_tx_conf_callback;
193 
194 	sc->sc_txph = FM_PORT_Config(&params);
195 	if (sc->sc_txph == NULL) {
196 		device_printf(sc->sc_dev, "couldn't configure FM Port TX.\n");
197 		return (ENXIO);
198 	}
199 
200 	error = FM_PORT_Init(sc->sc_txph);
201 	if (error != E_OK) {
202 		device_printf(sc->sc_dev, "couldn't initialize FM Port TX.\n");
203 		FM_PORT_Free(sc->sc_txph);
204 		return (ENXIO);
205 	}
206 
207 	if (bootverbose)
208 		device_printf(sc->sc_dev, "TX hw port 0x%02x initialized.\n",
209 		    sc->sc_port_tx_hw_id);
210 
211 	return (0);
212 }
213 /** @} */
214 
215 
216 /**
217  * @group dTSEC IFnet routines.
218  * @{
219  */
220 void
221 dtsec_im_if_start_locked(struct dtsec_softc *sc)
222 {
223 	uint8_t *buffer;
224 	uint16_t length;
225 	struct mbuf *m;
226 	int error;
227 
228 	DTSEC_LOCK_ASSERT(sc);
229 	/* TODO: IFF_DRV_OACTIVE */
230 
231 	if ((sc->sc_mii->mii_media_status & IFM_ACTIVE) == 0)
232 		return;
233 
234 	if ((if_getdrvflags(sc->sc_ifnet) & IFF_DRV_RUNNING) != IFF_DRV_RUNNING)
235 		return;
236 
237 	while (!if_sendq_empty(sc->sc_ifnet)) {
238 		m = if_dequeue(sc->sc_ifnet);
239 		if (m == NULL)
240 			break;
241 
242 		length = m_length(m, NULL);
243 		buffer = XX_MallocSmart(length, 0, sizeof(void *));
244 		if (!buffer) {
245 			m_freem(m);
246 			break;
247 		}
248 
249 		m_copydata(m, 0, length, buffer);
250 		m_freem(m);
251 
252 		error = FM_PORT_ImTx(sc->sc_txph, buffer, length, TRUE, buffer);
253 		if (error != E_OK) {
254 			/* TODO: Ring full */
255 			XX_FreeSmart(buffer);
256 			break;
257 		}
258 	}
259 }
260 /** @} */
261