1 /*
2 * Copyright 2008-2012 Freescale Semiconductor Inc.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 * * Redistributions of source code must retain the above copyright
7 * notice, this list of conditions and the following disclaimer.
8 * * Redistributions in binary form must reproduce the above copyright
9 * notice, this list of conditions and the following disclaimer in the
10 * documentation and/or other materials provided with the distribution.
11 * * Neither the name of Freescale Semiconductor nor the
12 * names of its contributors may be used to endorse or promote products
13 * derived from this software without specific prior written permission.
14 *
15 *
16 * ALTERNATIVELY, this software may be distributed under the terms of the
17 * GNU General Public License ("GPL") as published by the Free Software
18 * Foundation, either version 2 of that License or (at your option) any
19 * later version.
20 *
21 * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
22 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24 * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
25 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
28 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33
34 /******************************************************************************
35 @File fm_port_im.c
36
37 @Description FM Port Independent-Mode ...
38 *//***************************************************************************/
39 #include "std_ext.h"
40 #include "string_ext.h"
41 #include "error_ext.h"
42 #include "memcpy_ext.h"
43 #include "fm_muram_ext.h"
44
45 #include "fm_port.h"
46
47
48 #define TX_CONF_STATUS_UNSENT 0x1
49
50
51 typedef enum e_TxConfType
52 {
53 e_TX_CONF_TYPE_CHECK = 0 /**< check if all the buffers were touched by the muxator, no confirmation callback */
54 ,e_TX_CONF_TYPE_CALLBACK = 1 /**< confirm to user all the available sent buffers */
55 ,e_TX_CONF_TYPE_FLUSH = 3 /**< confirm all buffers plus the unsent one with an appropriate status */
56 } e_TxConfType;
57
58
ImException(t_Handle h_FmPort,uint32_t event)59 static void ImException(t_Handle h_FmPort, uint32_t event)
60 {
61 t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
62
63 ASSERT_COND(((event & (IM_EV_RX | IM_EV_BSY)) && FmIsMaster(p_FmPort->h_Fm)) ||
64 !FmIsMaster(p_FmPort->h_Fm));
65
66 if (event & IM_EV_RX)
67 FmPortImRx(p_FmPort);
68 if ((event & IM_EV_BSY) && p_FmPort->f_Exception)
69 p_FmPort->f_Exception(p_FmPort->h_App, e_FM_PORT_EXCEPTION_IM_BUSY);
70 }
71
72
TxConf(t_FmPort * p_FmPort,e_TxConfType confType)73 static t_Error TxConf(t_FmPort *p_FmPort, e_TxConfType confType)
74 {
75 t_Error retVal = E_BUSY;
76 uint32_t bdStatus;
77 uint16_t savedStartBdId, confBdId;
78
79 ASSERT_COND(p_FmPort);
80
81 /*
82 if (confType==e_TX_CONF_TYPE_CHECK)
83 return (WfqEntryIsQueueEmpty(p_FmPort->im.h_WfqEntry) ? E_OK : E_BUSY);
84 */
85
86 confBdId = savedStartBdId = p_FmPort->im.currBdId;
87 bdStatus = BD_STATUS_AND_LENGTH(BD_GET(confBdId));
88
89 /* If R bit is set, we don't enter, or we break.
90 we run till we get to R, or complete the loop */
91 while ((!(bdStatus & BD_R_E) || (confType == e_TX_CONF_TYPE_FLUSH)) && (retVal != E_OK))
92 {
93 if (confType & e_TX_CONF_TYPE_CALLBACK) /* if it is confirmation with user callbacks */
94 BD_STATUS_AND_LENGTH_SET(BD_GET(confBdId), 0);
95
96 /* case 1: R bit is 0 and Length is set -> confirm! */
97 if ((confType & e_TX_CONF_TYPE_CALLBACK) && (bdStatus & BD_LENGTH_MASK))
98 {
99 if (p_FmPort->im.f_TxConf)
100 {
101 if ((confType == e_TX_CONF_TYPE_FLUSH) && (bdStatus & BD_R_E))
102 p_FmPort->im.f_TxConf(p_FmPort->h_App,
103 BdBufferGet(XX_PhysToVirt, BD_GET(confBdId)),
104 TX_CONF_STATUS_UNSENT,
105 p_FmPort->im.p_BdShadow[confBdId]);
106 else
107 p_FmPort->im.f_TxConf(p_FmPort->h_App,
108 BdBufferGet(XX_PhysToVirt, BD_GET(confBdId)),
109 0,
110 p_FmPort->im.p_BdShadow[confBdId]);
111 }
112 }
113 /* case 2: R bit is 0 and Length is 0 -> not used yet, nop! */
114
115 confBdId = GetNextBdId(p_FmPort, confBdId);
116 if (confBdId == savedStartBdId)
117 retVal = E_OK;
118 bdStatus = BD_STATUS_AND_LENGTH(BD_GET(confBdId));
119 }
120
121 return retVal;
122 }
123
FmPortImEnable(t_FmPort * p_FmPort)124 t_Error FmPortImEnable(t_FmPort *p_FmPort)
125 {
126 uint32_t tmpReg = GET_UINT32(p_FmPort->im.p_FmPortImPram->mode);
127 WRITE_UINT32(p_FmPort->im.p_FmPortImPram->mode, (uint32_t)(tmpReg & ~IM_MODE_GRC_STP));
128 return E_OK;
129 }
130
FmPortImDisable(t_FmPort * p_FmPort)131 t_Error FmPortImDisable(t_FmPort *p_FmPort)
132 {
133 uint32_t tmpReg = GET_UINT32(p_FmPort->im.p_FmPortImPram->mode);
134 WRITE_UINT32(p_FmPort->im.p_FmPortImPram->mode, (uint32_t)(tmpReg | IM_MODE_GRC_STP));
135 return E_OK;
136 }
137
FmPortImRx(t_FmPort * p_FmPort)138 t_Error FmPortImRx(t_FmPort *p_FmPort)
139 {
140 t_Handle h_CurrUserPriv, h_NewUserPriv;
141 uint32_t bdStatus;
142 volatile uint8_t buffPos;
143 uint16_t length;
144 uint16_t errors;
145 uint8_t *p_CurData, *p_Data;
146 uint32_t flags;
147
148 ASSERT_COND(p_FmPort);
149
150 flags = XX_LockIntrSpinlock(p_FmPort->h_Spinlock);
151 if (p_FmPort->lock)
152 {
153 XX_UnlockIntrSpinlock(p_FmPort->h_Spinlock, flags);
154 return E_OK;
155 }
156 p_FmPort->lock = TRUE;
157 XX_UnlockIntrSpinlock(p_FmPort->h_Spinlock, flags);
158
159 bdStatus = BD_STATUS_AND_LENGTH(BD_GET(p_FmPort->im.currBdId));
160
161 while (!(bdStatus & BD_R_E)) /* while there is data in the Rx BD */
162 {
163 if ((p_Data = p_FmPort->im.rxPool.f_GetBuf(p_FmPort->im.rxPool.h_BufferPool, &h_NewUserPriv)) == NULL)
164 {
165 p_FmPort->lock = FALSE;
166 RETURN_ERROR(MAJOR, E_NOT_AVAILABLE, ("Data buffer"));
167 }
168
169 if (p_FmPort->im.firstBdOfFrameId == IM_ILEGAL_BD_ID)
170 p_FmPort->im.firstBdOfFrameId = p_FmPort->im.currBdId;
171
172 p_CurData = BdBufferGet(p_FmPort->im.rxPool.f_PhysToVirt, BD_GET(p_FmPort->im.currBdId));
173 h_CurrUserPriv = p_FmPort->im.p_BdShadow[p_FmPort->im.currBdId];
174 length = (uint16_t)((bdStatus & BD_L) ?
175 ((bdStatus & BD_LENGTH_MASK) - p_FmPort->im.rxFrameAccumLength):
176 (bdStatus & BD_LENGTH_MASK));
177 p_FmPort->im.rxFrameAccumLength += length;
178
179 /* determine whether buffer is first, last, first and last (single */
180 /* buffer frame) or middle (not first and not last) */
181 buffPos = (uint8_t)((p_FmPort->im.currBdId == p_FmPort->im.firstBdOfFrameId) ?
182 ((bdStatus & BD_L) ? SINGLE_BUF : FIRST_BUF) :
183 ((bdStatus & BD_L) ? LAST_BUF : MIDDLE_BUF));
184
185 if (bdStatus & BD_L)
186 {
187 p_FmPort->im.rxFrameAccumLength = 0;
188 p_FmPort->im.firstBdOfFrameId = IM_ILEGAL_BD_ID;
189 }
190
191 BdBufferSet(p_FmPort->im.rxPool.f_VirtToPhys, BD_GET(p_FmPort->im.currBdId), p_Data);
192
193 BD_STATUS_AND_LENGTH_SET(BD_GET(p_FmPort->im.currBdId), BD_R_E);
194
195 errors = (uint16_t)((bdStatus & BD_RX_ERRORS) >> 16);
196 p_FmPort->im.p_BdShadow[p_FmPort->im.currBdId] = h_NewUserPriv;
197
198 p_FmPort->im.currBdId = GetNextBdId(p_FmPort, p_FmPort->im.currBdId);
199 WRITE_UINT16(p_FmPort->im.p_FmPortImPram->rxQd.offsetOut, (uint16_t)(p_FmPort->im.currBdId<<4));
200 /* Pass the buffer if one of the conditions is true:
201 - There are no errors
202 - This is a part of a larger frame ( the application has already received some buffers ) */
203 if ((buffPos != SINGLE_BUF) || !errors)
204 {
205 if (p_FmPort->im.f_RxStore(p_FmPort->h_App,
206 p_CurData,
207 length,
208 errors,
209 buffPos,
210 h_CurrUserPriv) == e_RX_STORE_RESPONSE_PAUSE)
211 break;
212 }
213 else if (p_FmPort->im.rxPool.f_PutBuf(p_FmPort->im.rxPool.h_BufferPool,
214 p_CurData,
215 h_CurrUserPriv))
216 {
217 p_FmPort->lock = FALSE;
218 RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Failed freeing data buffer"));
219 }
220
221 bdStatus = BD_STATUS_AND_LENGTH(BD_GET(p_FmPort->im.currBdId));
222 }
223 p_FmPort->lock = FALSE;
224 return E_OK;
225 }
226
FmPortConfigIM(t_FmPort * p_FmPort,t_FmPortParams * p_FmPortParams)227 void FmPortConfigIM (t_FmPort *p_FmPort, t_FmPortParams *p_FmPortParams)
228 {
229 ASSERT_COND(p_FmPort);
230
231 SANITY_CHECK_RETURN(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
232
233 p_FmPort->im.h_FmMuram = p_FmPortParams->specificParams.imRxTxParams.h_FmMuram;
234 p_FmPort->p_FmPortDriverParam->liodnOffset = p_FmPortParams->specificParams.imRxTxParams.liodnOffset;
235 p_FmPort->im.dataMemId = p_FmPortParams->specificParams.imRxTxParams.dataMemId;
236 p_FmPort->im.dataMemAttributes = p_FmPortParams->specificParams.imRxTxParams.dataMemAttributes;
237
238 p_FmPort->im.fwExtStructsMemId = DEFAULT_PORT_ImfwExtStructsMemId;
239 p_FmPort->im.fwExtStructsMemAttr = DEFAULT_PORT_ImfwExtStructsMemAttr;
240
241 if ((p_FmPort->portType == e_FM_PORT_TYPE_RX) ||
242 (p_FmPort->portType == e_FM_PORT_TYPE_RX_10G))
243 {
244 p_FmPort->im.rxPool.h_BufferPool = p_FmPortParams->specificParams.imRxTxParams.rxPoolParams.h_BufferPool;
245 p_FmPort->im.rxPool.f_GetBuf = p_FmPortParams->specificParams.imRxTxParams.rxPoolParams.f_GetBuf;
246 p_FmPort->im.rxPool.f_PutBuf = p_FmPortParams->specificParams.imRxTxParams.rxPoolParams.f_PutBuf;
247 p_FmPort->im.rxPool.bufferSize = p_FmPortParams->specificParams.imRxTxParams.rxPoolParams.bufferSize;
248 p_FmPort->im.rxPool.f_PhysToVirt = p_FmPortParams->specificParams.imRxTxParams.rxPoolParams.f_PhysToVirt;
249 if (!p_FmPort->im.rxPool.f_PhysToVirt)
250 p_FmPort->im.rxPool.f_PhysToVirt = XX_PhysToVirt;
251 p_FmPort->im.rxPool.f_VirtToPhys = p_FmPortParams->specificParams.imRxTxParams.rxPoolParams.f_VirtToPhys;
252 if (!p_FmPort->im.rxPool.f_VirtToPhys)
253 p_FmPort->im.rxPool.f_VirtToPhys = XX_VirtToPhys;
254 p_FmPort->im.f_RxStore = p_FmPortParams->specificParams.imRxTxParams.f_RxStore;
255
256 p_FmPort->im.mrblr = 0x8000;
257 while (p_FmPort->im.mrblr)
258 {
259 if (p_FmPort->im.rxPool.bufferSize & p_FmPort->im.mrblr)
260 break;
261 p_FmPort->im.mrblr >>= 1;
262 }
263 if (p_FmPort->im.mrblr != p_FmPort->im.rxPool.bufferSize)
264 DBG(WARNING, ("Max-Rx-Buffer-Length set to %d", p_FmPort->im.mrblr));
265 p_FmPort->im.bdRingSize = DEFAULT_PORT_rxBdRingLength;
266 p_FmPort->exceptions = DEFAULT_PORT_exception;
267 if (FmIsMaster(p_FmPort->h_Fm))
268 p_FmPort->polling = FALSE;
269 else
270 p_FmPort->polling = TRUE;
271 p_FmPort->fmanCtrlEventId = (uint8_t)NO_IRQ;
272 }
273 else
274 {
275 p_FmPort->im.f_TxConf = p_FmPortParams->specificParams.imRxTxParams.f_TxConf;
276
277 p_FmPort->im.bdRingSize = DEFAULT_PORT_txBdRingLength;
278 }
279 }
280
FmPortImCheckInitParameters(t_FmPort * p_FmPort)281 t_Error FmPortImCheckInitParameters(t_FmPort *p_FmPort)
282 {
283 if ((p_FmPort->portType != e_FM_PORT_TYPE_RX) &&
284 (p_FmPort->portType != e_FM_PORT_TYPE_RX_10G) &&
285 (p_FmPort->portType != e_FM_PORT_TYPE_TX) &&
286 (p_FmPort->portType != e_FM_PORT_TYPE_TX_10G))
287 RETURN_ERROR(MAJOR, E_INVALID_VALUE, NO_MSG);
288
289 if ((p_FmPort->portType == e_FM_PORT_TYPE_RX) ||
290 (p_FmPort->portType == e_FM_PORT_TYPE_RX_10G))
291 {
292 if (!POWER_OF_2(p_FmPort->im.mrblr))
293 RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("max Rx buffer length must be power of 2!!!"));
294 if (p_FmPort->im.mrblr < 256)
295 RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("max Rx buffer length must at least 256!!!"));
296 if (p_FmPort->p_FmPortDriverParam->liodnOffset & ~FM_LIODN_OFFSET_MASK)
297 RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("liodnOffset is larger than %d", FM_LIODN_OFFSET_MASK+1));
298 }
299
300 return E_OK;
301 }
302
FmPortImInit(t_FmPort * p_FmPort)303 t_Error FmPortImInit(t_FmPort *p_FmPort)
304 {
305 t_FmImBd *p_Bd=NULL;
306 t_Handle h_BufContext;
307 uint64_t tmpPhysBase;
308 uint16_t log2Num;
309 uint8_t *p_Data/*, *p_Tmp*/;
310 int i;
311 t_Error err;
312 uint16_t tmpReg16;
313 uint32_t tmpReg32;
314
315 ASSERT_COND(p_FmPort);
316
317 p_FmPort->im.p_FmPortImPram =
318 (t_FmPortImPram *)FM_MURAM_AllocMem(p_FmPort->im.h_FmMuram, sizeof(t_FmPortImPram), IM_PRAM_ALIGN);
319 if (!p_FmPort->im.p_FmPortImPram)
320 RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Independent-Mode Parameter-RAM!!!"));
321 WRITE_BLOCK(p_FmPort->im.p_FmPortImPram, 0, sizeof(t_FmPortImPram));
322
323 if ((p_FmPort->portType == e_FM_PORT_TYPE_RX) ||
324 (p_FmPort->portType == e_FM_PORT_TYPE_RX_10G))
325 {
326 p_FmPort->im.p_BdRing =
327 (t_FmImBd *)XX_MallocSmart((uint32_t)(sizeof(t_FmImBd)*p_FmPort->im.bdRingSize),
328 p_FmPort->im.fwExtStructsMemId,
329 4);
330 if (!p_FmPort->im.p_BdRing)
331 RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Independent-Mode Rx BD ring!!!"));
332 IOMemSet32(p_FmPort->im.p_BdRing, 0, (uint32_t)(sizeof(t_FmImBd)*p_FmPort->im.bdRingSize));
333
334 p_FmPort->im.p_BdShadow = (t_Handle *)XX_Malloc((uint32_t)(sizeof(t_Handle)*p_FmPort->im.bdRingSize));
335 if (!p_FmPort->im.p_BdShadow)
336 RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Independent-Mode Rx BD shadow!!!"));
337 memset(p_FmPort->im.p_BdShadow, 0, (uint32_t)(sizeof(t_Handle)*p_FmPort->im.bdRingSize));
338
339 /* Initialize the Rx-BD ring */
340 for (i=0; i<p_FmPort->im.bdRingSize; i++)
341 {
342 p_Bd = BD_GET(i);
343 BD_STATUS_AND_LENGTH_SET (p_Bd, BD_R_E);
344
345 if ((p_Data = p_FmPort->im.rxPool.f_GetBuf(p_FmPort->im.rxPool.h_BufferPool, &h_BufContext)) == NULL)
346 RETURN_ERROR(MAJOR, E_NOT_AVAILABLE, ("Data buffer"));
347 BdBufferSet(p_FmPort->im.rxPool.f_VirtToPhys, p_Bd, p_Data);
348 p_FmPort->im.p_BdShadow[i] = h_BufContext;
349 }
350
351 if ((p_FmPort->im.dataMemAttributes & MEMORY_ATTR_CACHEABLE) ||
352 (p_FmPort->im.fwExtStructsMemAttr & MEMORY_ATTR_CACHEABLE))
353 WRITE_UINT32(p_FmPort->im.p_FmPortImPram->mode, IM_MODE_GBL | IM_MODE_SET_BO(2));
354 else
355 WRITE_UINT32(p_FmPort->im.p_FmPortImPram->mode, IM_MODE_SET_BO(2));
356
357 WRITE_UINT32(p_FmPort->im.p_FmPortImPram->rxQdPtr,
358 (uint32_t)((uint64_t)(XX_VirtToPhys(p_FmPort->im.p_FmPortImPram)) -
359 p_FmPort->fmMuramPhysBaseAddr + 0x20));
360
361 LOG2((uint64_t)p_FmPort->im.mrblr, log2Num);
362 WRITE_UINT16(p_FmPort->im.p_FmPortImPram->mrblr, log2Num);
363
364 /* Initialize Rx QD */
365 tmpPhysBase = (uint64_t)(XX_VirtToPhys(p_FmPort->im.p_BdRing));
366 SET_ADDR(&p_FmPort->im.p_FmPortImPram->rxQd.bdRingBase, tmpPhysBase);
367 WRITE_UINT16(p_FmPort->im.p_FmPortImPram->rxQd.bdRingSize, (uint16_t)(sizeof(t_FmImBd)*p_FmPort->im.bdRingSize));
368
369 /* Update the IM PRAM address in the BMI */
370 WRITE_UINT32(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rfqid,
371 (uint32_t)((uint64_t)(XX_VirtToPhys(p_FmPort->im.p_FmPortImPram)) -
372 p_FmPort->fmMuramPhysBaseAddr));
373 if (!p_FmPort->polling || p_FmPort->exceptions)
374 {
375 /* Allocate, configure and register interrupts */
376 err = FmAllocFmanCtrlEventReg(p_FmPort->h_Fm, &p_FmPort->fmanCtrlEventId);
377 if (err)
378 RETURN_ERROR(MAJOR, err, NO_MSG);
379
380 ASSERT_COND(!(p_FmPort->fmanCtrlEventId & ~IM_RXQD_FPMEVT_SEL_MASK));
381 tmpReg16 = (uint16_t)(p_FmPort->fmanCtrlEventId & IM_RXQD_FPMEVT_SEL_MASK);
382 tmpReg32 = 0;
383
384 if (p_FmPort->exceptions & IM_EV_BSY)
385 {
386 tmpReg16 |= IM_RXQD_BSYINTM;
387 tmpReg32 |= IM_EV_BSY;
388 }
389 if (!p_FmPort->polling)
390 {
391 tmpReg16 |= IM_RXQD_RXFINTM;
392 tmpReg32 |= IM_EV_RX;
393 }
394 WRITE_UINT16(p_FmPort->im.p_FmPortImPram->rxQd.gen, tmpReg16);
395
396 FmRegisterFmanCtrlIntr(p_FmPort->h_Fm, p_FmPort->fmanCtrlEventId, ImException , (t_Handle)p_FmPort);
397
398 FmSetFmanCtrlIntr(p_FmPort->h_Fm, p_FmPort->fmanCtrlEventId, tmpReg32);
399 }
400 else
401 p_FmPort->fmanCtrlEventId = (uint8_t)NO_IRQ;
402 }
403 else
404 {
405 p_FmPort->im.p_BdRing = (t_FmImBd *)XX_MallocSmart((uint32_t)(sizeof(t_FmImBd)*p_FmPort->im.bdRingSize), p_FmPort->im.fwExtStructsMemId, 4);
406 if (!p_FmPort->im.p_BdRing)
407 RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Independent-Mode Tx BD ring!!!"));
408 IOMemSet32(p_FmPort->im.p_BdRing, 0, (uint32_t)(sizeof(t_FmImBd)*p_FmPort->im.bdRingSize));
409
410 p_FmPort->im.p_BdShadow = (t_Handle *)XX_Malloc((uint32_t)(sizeof(t_Handle)*p_FmPort->im.bdRingSize));
411 if (!p_FmPort->im.p_BdShadow)
412 RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Independent-Mode Rx BD shadow!!!"));
413 memset(p_FmPort->im.p_BdShadow, 0, (uint32_t)(sizeof(t_Handle)*p_FmPort->im.bdRingSize));
414 p_FmPort->im.firstBdOfFrameId = IM_ILEGAL_BD_ID;
415
416 if ((p_FmPort->im.dataMemAttributes & MEMORY_ATTR_CACHEABLE) ||
417 (p_FmPort->im.fwExtStructsMemAttr & MEMORY_ATTR_CACHEABLE))
418 WRITE_UINT32(p_FmPort->im.p_FmPortImPram->mode, IM_MODE_GBL | IM_MODE_SET_BO(2));
419 else
420 WRITE_UINT32(p_FmPort->im.p_FmPortImPram->mode, IM_MODE_SET_BO(2));
421
422 WRITE_UINT32(p_FmPort->im.p_FmPortImPram->txQdPtr,
423 (uint32_t)((uint64_t)(XX_VirtToPhys(p_FmPort->im.p_FmPortImPram)) -
424 p_FmPort->fmMuramPhysBaseAddr + 0x40));
425
426 /* Initialize Tx QD */
427 tmpPhysBase = (uint64_t)(XX_VirtToPhys(p_FmPort->im.p_BdRing));
428 SET_ADDR(&p_FmPort->im.p_FmPortImPram->txQd.bdRingBase, tmpPhysBase);
429 WRITE_UINT16(p_FmPort->im.p_FmPortImPram->txQd.bdRingSize, (uint16_t)(sizeof(t_FmImBd)*p_FmPort->im.bdRingSize));
430
431 /* Update the IM PRAM address in the BMI */
432 WRITE_UINT32(p_FmPort->p_FmPortBmiRegs->txPortBmiRegs.fmbm_tcfqid,
433 (uint32_t)((uint64_t)(XX_VirtToPhys(p_FmPort->im.p_FmPortImPram)) -
434 p_FmPort->fmMuramPhysBaseAddr));
435 }
436
437
438 return E_OK;
439 }
440
FmPortImFree(t_FmPort * p_FmPort)441 void FmPortImFree(t_FmPort *p_FmPort)
442 {
443 uint32_t bdStatus;
444 uint8_t *p_CurData;
445
446 ASSERT_COND(p_FmPort);
447 ASSERT_COND(p_FmPort->im.p_FmPortImPram);
448
449 if ((p_FmPort->portType == e_FM_PORT_TYPE_RX) ||
450 (p_FmPort->portType == e_FM_PORT_TYPE_RX_10G))
451 {
452 if (!p_FmPort->polling || p_FmPort->exceptions)
453 {
454 /* Deallocate and unregister interrupts */
455 FmSetFmanCtrlIntr(p_FmPort->h_Fm, p_FmPort->fmanCtrlEventId, 0);
456
457 FmFreeFmanCtrlEventReg(p_FmPort->h_Fm, p_FmPort->fmanCtrlEventId);
458
459 WRITE_UINT16(p_FmPort->im.p_FmPortImPram->rxQd.gen, 0);
460
461 FmUnregisterFmanCtrlIntr(p_FmPort->h_Fm, p_FmPort->fmanCtrlEventId);
462 }
463 /* Try first clean what has received */
464 FmPortImRx(p_FmPort);
465
466 /* Now, get rid of the the empty buffer! */
467 bdStatus = BD_STATUS_AND_LENGTH(BD_GET(p_FmPort->im.currBdId));
468
469 while (bdStatus & BD_R_E) /* while there is data in the Rx BD */
470 {
471 p_CurData = BdBufferGet(p_FmPort->im.rxPool.f_PhysToVirt, BD_GET(p_FmPort->im.currBdId));
472
473 BdBufferSet(p_FmPort->im.rxPool.f_VirtToPhys, BD_GET(p_FmPort->im.currBdId), NULL);
474 BD_STATUS_AND_LENGTH_SET(BD_GET(p_FmPort->im.currBdId), 0);
475
476 p_FmPort->im.rxPool.f_PutBuf(p_FmPort->im.rxPool.h_BufferPool,
477 p_CurData,
478 p_FmPort->im.p_BdShadow[p_FmPort->im.currBdId]);
479
480 p_FmPort->im.currBdId = GetNextBdId(p_FmPort, p_FmPort->im.currBdId);
481 bdStatus = BD_STATUS_AND_LENGTH(BD_GET(p_FmPort->im.currBdId));
482 }
483 }
484 else
485 TxConf(p_FmPort, e_TX_CONF_TYPE_FLUSH);
486
487 FM_MURAM_FreeMem(p_FmPort->im.h_FmMuram, p_FmPort->im.p_FmPortImPram);
488
489 if (p_FmPort->im.p_BdShadow)
490 XX_Free(p_FmPort->im.p_BdShadow);
491
492 if (p_FmPort->im.p_BdRing)
493 XX_FreeSmart(p_FmPort->im.p_BdRing);
494 }
495
496
FM_PORT_ConfigIMMaxRxBufLength(t_Handle h_FmPort,uint16_t newVal)497 t_Error FM_PORT_ConfigIMMaxRxBufLength(t_Handle h_FmPort, uint16_t newVal)
498 {
499 t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
500
501 SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
502 SANITY_CHECK_RETURN_ERROR(p_FmPort->imEn, E_INVALID_STATE);
503 SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
504
505 p_FmPort->im.mrblr = newVal;
506
507 return E_OK;
508 }
509
FM_PORT_ConfigIMRxBdRingLength(t_Handle h_FmPort,uint16_t newVal)510 t_Error FM_PORT_ConfigIMRxBdRingLength(t_Handle h_FmPort, uint16_t newVal)
511 {
512 t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
513
514 SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
515 SANITY_CHECK_RETURN_ERROR(p_FmPort->imEn, E_INVALID_STATE);
516 SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
517
518 p_FmPort->im.bdRingSize = newVal;
519
520 return E_OK;
521 }
522
FM_PORT_ConfigIMTxBdRingLength(t_Handle h_FmPort,uint16_t newVal)523 t_Error FM_PORT_ConfigIMTxBdRingLength(t_Handle h_FmPort, uint16_t newVal)
524 {
525 t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
526
527 SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
528 SANITY_CHECK_RETURN_ERROR(p_FmPort->imEn, E_INVALID_STATE);
529 SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
530
531 p_FmPort->im.bdRingSize = newVal;
532
533 return E_OK;
534 }
535
FM_PORT_ConfigIMFmanCtrlExternalStructsMemory(t_Handle h_FmPort,uint8_t memId,uint32_t memAttributes)536 t_Error FM_PORT_ConfigIMFmanCtrlExternalStructsMemory(t_Handle h_FmPort,
537 uint8_t memId,
538 uint32_t memAttributes)
539 {
540 t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
541
542 SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
543 SANITY_CHECK_RETURN_ERROR(p_FmPort->imEn, E_INVALID_STATE);
544 SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
545
546 p_FmPort->im.fwExtStructsMemId = memId;
547 p_FmPort->im.fwExtStructsMemAttr = memAttributes;
548
549 return E_OK;
550 }
551
FM_PORT_ConfigIMPolling(t_Handle h_FmPort)552 t_Error FM_PORT_ConfigIMPolling(t_Handle h_FmPort)
553 {
554 t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
555
556 SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
557 SANITY_CHECK_RETURN_ERROR(p_FmPort->imEn, E_INVALID_STATE);
558 SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
559
560 if ((p_FmPort->portType != e_FM_PORT_TYPE_RX_10G) && (p_FmPort->portType != e_FM_PORT_TYPE_RX))
561 RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("Available for Rx ports only"));
562
563 if (!FmIsMaster(p_FmPort->h_Fm))
564 RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("Available on master-partition only;"
565 "in guest-partitions, IM is always in polling!"));
566
567 p_FmPort->polling = TRUE;
568
569 return E_OK;
570 }
571
FM_PORT_SetIMExceptions(t_Handle h_FmPort,e_FmPortExceptions exception,bool enable)572 t_Error FM_PORT_SetIMExceptions(t_Handle h_FmPort, e_FmPortExceptions exception, bool enable)
573 {
574 t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
575 t_Error err;
576 uint16_t tmpReg16;
577 uint32_t tmpReg32;
578
579 SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
580 SANITY_CHECK_RETURN_ERROR(p_FmPort->imEn, E_INVALID_STATE);
581 SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
582
583 if (exception == e_FM_PORT_EXCEPTION_IM_BUSY)
584 {
585 if (enable)
586 {
587 p_FmPort->exceptions |= IM_EV_BSY;
588 if (p_FmPort->fmanCtrlEventId == (uint8_t)NO_IRQ)
589 {
590 /* Allocate, configure and register interrupts */
591 err = FmAllocFmanCtrlEventReg(p_FmPort->h_Fm, &p_FmPort->fmanCtrlEventId);
592 if (err)
593 RETURN_ERROR(MAJOR, err, NO_MSG);
594 ASSERT_COND(!(p_FmPort->fmanCtrlEventId & ~IM_RXQD_FPMEVT_SEL_MASK));
595
596 FmRegisterFmanCtrlIntr(p_FmPort->h_Fm, p_FmPort->fmanCtrlEventId, ImException, (t_Handle)p_FmPort);
597 tmpReg16 = (uint16_t)((p_FmPort->fmanCtrlEventId & IM_RXQD_FPMEVT_SEL_MASK) | IM_RXQD_BSYINTM);
598 tmpReg32 = IM_EV_BSY;
599 }
600 else
601 {
602 tmpReg16 = (uint16_t)(GET_UINT16(p_FmPort->im.p_FmPortImPram->rxQd.gen) | IM_RXQD_BSYINTM);
603 tmpReg32 = FmGetFmanCtrlIntr(p_FmPort->h_Fm, p_FmPort->fmanCtrlEventId) | IM_EV_BSY;
604 }
605
606 WRITE_UINT16(p_FmPort->im.p_FmPortImPram->rxQd.gen, tmpReg16);
607 FmSetFmanCtrlIntr(p_FmPort->h_Fm, p_FmPort->fmanCtrlEventId, tmpReg32);
608 }
609 else
610 {
611 p_FmPort->exceptions &= ~IM_EV_BSY;
612 if (!p_FmPort->exceptions && p_FmPort->polling)
613 {
614 FmFreeFmanCtrlEventReg(p_FmPort->h_Fm, p_FmPort->fmanCtrlEventId);
615 FmUnregisterFmanCtrlIntr(p_FmPort->h_Fm, p_FmPort->fmanCtrlEventId);
616 FmSetFmanCtrlIntr(p_FmPort->h_Fm, p_FmPort->fmanCtrlEventId, 0);
617 WRITE_UINT16(p_FmPort->im.p_FmPortImPram->rxQd.gen, 0);
618 p_FmPort->fmanCtrlEventId = (uint8_t)NO_IRQ;
619 }
620 else
621 {
622 tmpReg16 = (uint16_t)(GET_UINT16(p_FmPort->im.p_FmPortImPram->rxQd.gen) & ~IM_RXQD_BSYINTM);
623 WRITE_UINT16(p_FmPort->im.p_FmPortImPram->rxQd.gen, tmpReg16);
624 tmpReg32 = FmGetFmanCtrlIntr(p_FmPort->h_Fm, p_FmPort->fmanCtrlEventId) & ~IM_EV_BSY;
625 FmSetFmanCtrlIntr(p_FmPort->h_Fm, p_FmPort->fmanCtrlEventId, tmpReg32);
626 }
627 }
628 }
629 else
630 RETURN_ERROR(MINOR, E_INVALID_SELECTION, ("Invalid exception."));
631
632 return E_OK;
633 }
634
FM_PORT_ImTx(t_Handle h_FmPort,uint8_t * p_Data,uint16_t length,bool lastBuffer,t_Handle h_BufContext)635 t_Error FM_PORT_ImTx( t_Handle h_FmPort,
636 uint8_t *p_Data,
637 uint16_t length,
638 bool lastBuffer,
639 t_Handle h_BufContext)
640 {
641 t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
642 uint16_t nextBdId;
643 uint32_t bdStatus, nextBdStatus;
644 bool firstBuffer;
645
646 SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
647 SANITY_CHECK_RETURN_ERROR(p_FmPort->imEn, E_INVALID_STATE);
648 SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
649
650 bdStatus = BD_STATUS_AND_LENGTH(BD_GET(p_FmPort->im.currBdId));
651 nextBdId = GetNextBdId(p_FmPort, p_FmPort->im.currBdId);
652 nextBdStatus = BD_STATUS_AND_LENGTH(BD_GET(nextBdId));
653
654 if (!(bdStatus & BD_R_E) && !(nextBdStatus & BD_R_E))
655 {
656 /* Confirm the current BD - BD is available */
657 if ((bdStatus & BD_LENGTH_MASK) && (p_FmPort->im.f_TxConf))
658 p_FmPort->im.f_TxConf (p_FmPort->h_App,
659 BdBufferGet(XX_PhysToVirt, BD_GET(p_FmPort->im.currBdId)),
660 0,
661 p_FmPort->im.p_BdShadow[p_FmPort->im.currBdId]);
662
663 bdStatus = length;
664
665 /* if this is the first BD of a frame */
666 if (p_FmPort->im.firstBdOfFrameId == IM_ILEGAL_BD_ID)
667 {
668 firstBuffer = TRUE;
669 p_FmPort->im.txFirstBdStatus = (bdStatus | BD_R_E);
670
671 if (!lastBuffer)
672 p_FmPort->im.firstBdOfFrameId = p_FmPort->im.currBdId;
673 }
674 else
675 firstBuffer = FALSE;
676
677 BdBufferSet(XX_VirtToPhys, BD_GET(p_FmPort->im.currBdId), p_Data);
678 p_FmPort->im.p_BdShadow[p_FmPort->im.currBdId] = h_BufContext;
679
680 /* deal with last */
681 if (lastBuffer)
682 {
683 /* if single buffer frame */
684 if (firstBuffer)
685 BD_STATUS_AND_LENGTH_SET(BD_GET(p_FmPort->im.currBdId), p_FmPort->im.txFirstBdStatus | BD_L);
686 else
687 {
688 /* Set the last BD of the frame */
689 BD_STATUS_AND_LENGTH_SET (BD_GET(p_FmPort->im.currBdId), (bdStatus | BD_R_E | BD_L));
690 /* Set the first BD of the frame */
691 BD_STATUS_AND_LENGTH_SET(BD_GET(p_FmPort->im.firstBdOfFrameId), p_FmPort->im.txFirstBdStatus);
692 p_FmPort->im.firstBdOfFrameId = IM_ILEGAL_BD_ID;
693 }
694 WRITE_UINT16(p_FmPort->im.p_FmPortImPram->txQd.offsetIn, (uint16_t)(GetNextBdId(p_FmPort, p_FmPort->im.currBdId)<<4));
695 }
696 else if (!firstBuffer) /* mid frame buffer */
697 BD_STATUS_AND_LENGTH_SET (BD_GET(p_FmPort->im.currBdId), bdStatus | BD_R_E);
698
699 p_FmPort->im.currBdId = GetNextBdId(p_FmPort, p_FmPort->im.currBdId);
700 }
701 else
702 {
703 /* Discard current frame. Return error. */
704 if (p_FmPort->im.firstBdOfFrameId != IM_ILEGAL_BD_ID)
705 {
706 /* Error: No free BD */
707 /* Response: Discard current frame. Return error. */
708 uint16_t cleanBdId = p_FmPort->im.firstBdOfFrameId;
709
710 ASSERT_COND(p_FmPort->im.firstBdOfFrameId != p_FmPort->im.currBdId);
711
712 /* Since firstInFrame is not NULL, one buffer at least has already been
713 inserted into the BD ring. Using do-while covers the situation of a
714 frame spanned throughout the whole Tx BD ring (p_CleanBd is incremented
715 prior to testing whether or not it's equal to TxBd). */
716 do
717 {
718 BD_STATUS_AND_LENGTH_SET(BD_GET(cleanBdId), 0);
719 /* Advance BD pointer */
720 cleanBdId = GetNextBdId(p_FmPort, cleanBdId);
721 } while (cleanBdId != p_FmPort->im.currBdId);
722
723 p_FmPort->im.currBdId = cleanBdId;
724 p_FmPort->im.firstBdOfFrameId = IM_ILEGAL_BD_ID;
725 }
726
727 return ERROR_CODE(E_FULL);
728 }
729
730 return E_OK;
731 }
732
FM_PORT_ImTxConf(t_Handle h_FmPort)733 void FM_PORT_ImTxConf(t_Handle h_FmPort)
734 {
735 t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
736
737 SANITY_CHECK_RETURN(p_FmPort, E_INVALID_HANDLE);
738 SANITY_CHECK_RETURN(p_FmPort->imEn, E_INVALID_STATE);
739 SANITY_CHECK_RETURN(!p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
740
741 TxConf(p_FmPort, e_TX_CONF_TYPE_CALLBACK);
742 }
743
FM_PORT_ImRx(t_Handle h_FmPort)744 t_Error FM_PORT_ImRx(t_Handle h_FmPort)
745 {
746 t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
747
748 SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
749 SANITY_CHECK_RETURN_ERROR(p_FmPort->imEn, E_INVALID_STATE);
750 SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
751
752 return FmPortImRx(p_FmPort);
753 }
754