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
dtsec_im_fm_port_rx_callback(t_Handle app,uint8_t * data,uint16_t length,uint16_t status,uint8_t position,t_Handle buf_context)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
dtsec_im_fm_port_tx_conf_callback(t_Handle app,uint8_t * data,uint16_t status,t_Handle buf_context)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 *
dtsec_im_fm_port_rx_get_buf(t_Handle buffer_pool,t_Handle * buf_context_handle)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
dtsec_im_fm_port_rx_put_buf(t_Handle buffer_pool,uint8_t * buffer,t_Handle buf_context)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
dtsec_im_fm_port_rx_init(struct dtsec_softc * sc,int unit)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(¶ms, 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 = ¶ms.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 = ¶ms.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(¶ms);
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
dtsec_im_fm_port_tx_init(struct dtsec_softc * sc,int unit)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(¶ms, 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 = ¶ms.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(¶ms);
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
dtsec_im_if_start_locked(struct dtsec_softc * sc)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