1296177Sjhibbits/* Copyright (c) 2008-2011 Freescale Semiconductor, Inc.
2296177Sjhibbits * All rights reserved.
3296177Sjhibbits *
4296177Sjhibbits * Redistribution and use in source and binary forms, with or without
5296177Sjhibbits * modification, are permitted provided that the following conditions are met:
6296177Sjhibbits *     * Redistributions of source code must retain the above copyright
7296177Sjhibbits *       notice, this list of conditions and the following disclaimer.
8296177Sjhibbits *     * Redistributions in binary form must reproduce the above copyright
9296177Sjhibbits *       notice, this list of conditions and the following disclaimer in the
10296177Sjhibbits *       documentation and/or other materials provided with the distribution.
11296177Sjhibbits *     * Neither the name of Freescale Semiconductor nor the
12296177Sjhibbits *       names of its contributors may be used to endorse or promote products
13296177Sjhibbits *       derived from this software without specific prior written permission.
14296177Sjhibbits *
15296177Sjhibbits *
16296177Sjhibbits * ALTERNATIVELY, this software may be distributed under the terms of the
17296177Sjhibbits * GNU General Public License ("GPL") as published by the Free Software
18296177Sjhibbits * Foundation, either version 2 of that License or (at your option) any
19296177Sjhibbits * later version.
20296177Sjhibbits *
21296177Sjhibbits * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
22296177Sjhibbits * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23296177Sjhibbits * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24296177Sjhibbits * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
25296177Sjhibbits * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26296177Sjhibbits * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27296177Sjhibbits * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
28296177Sjhibbits * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29296177Sjhibbits * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30296177Sjhibbits * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31296177Sjhibbits */
32296177Sjhibbits
33296177Sjhibbits/******************************************************************************
34296177Sjhibbits @File          fm_port_im.c
35296177Sjhibbits
36296177Sjhibbits @Description   FM Port Independent-Mode ...
37296177Sjhibbits*//***************************************************************************/
38296177Sjhibbits#include "std_ext.h"
39296177Sjhibbits#include "string_ext.h"
40296177Sjhibbits#include "error_ext.h"
41296177Sjhibbits#include "fm_muram_ext.h"
42296177Sjhibbits
43296177Sjhibbits#include "fm_port.h"
44296177Sjhibbits
45296177Sjhibbits
46296177Sjhibbits#define TX_CONF_STATUS_UNSENT 0x1
47296177Sjhibbits
48296177Sjhibbits#ifdef CORE_8BIT_ACCESS_ERRATA
49296177Sjhibbits#undef WRITE_UINT16
50296177Sjhibbits#undef GET_UINT16
51296177Sjhibbits
52296177Sjhibbits#define WRITE_UINT16(addr, val)  \
53296177Sjhibbits    do{                             \
54296177Sjhibbits            if((int)&(addr) % 4)    \
55296177Sjhibbits                WRITE_UINT32(*(uint32_t*)(uint32_t)((uint32_t)&addr & ~0x3L),                                           \
56296177Sjhibbits                        ((GET_UINT32(*(uint32_t*)(uint32_t)((uint32_t)&addr & ~0x3L)) & 0xffff0000) | (uint32_t)val));  \
57296177Sjhibbits            else                    \
58296177Sjhibbits                WRITE_UINT32(*(uint32_t*)&addr,                                                                         \
59296177Sjhibbits                        ((GET_UINT32(*(uint32_t*)&addr) & 0x0000ffff) | (uint32_t)val<<16));                            \
60296177Sjhibbits      }while(0);
61296177Sjhibbits
62296177Sjhibbits#define GET_UINT16(addr) (((uint32_t)&addr%4) ?           \
63296177Sjhibbits       ((uint16_t)GET_UINT32(*(uint32_t*)(uint32_t)((uint32_t)&addr & ~0x3L))):  \
64296177Sjhibbits       ((uint16_t)(GET_UINT32(*(uint32_t*)(uint32_t)&addr) >> 16)))
65296177Sjhibbits#endif /* CORE_8BIT_ACCESS_ERRATA */
66296177Sjhibbits
67296177Sjhibbits
68296177Sjhibbitstypedef enum e_TxConfType
69296177Sjhibbits{
70296177Sjhibbits     e_TX_CONF_TYPE_CHECK      = 0  /**< check if all the buffers were touched by the muxator, no confirmation callback */
71296177Sjhibbits    ,e_TX_CONF_TYPE_CALLBACK   = 1  /**< confirm to user all the available sent buffers */
72296177Sjhibbits    ,e_TX_CONF_TYPE_FLUSH      = 3  /**< confirm all buffers plus the unsent one with an appropriate status */
73296177Sjhibbits} e_TxConfType;
74296177Sjhibbits
75296177Sjhibbits
76296177Sjhibbitsstatic void ImException(t_Handle h_FmPort, uint32_t event)
77296177Sjhibbits{
78296177Sjhibbits    t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
79296177Sjhibbits
80296177Sjhibbits    ASSERT_COND(((event & IM_EV_RX) && FmIsMaster(p_FmPort->h_Fm)) ||
81296177Sjhibbits                !FmIsMaster(p_FmPort->h_Fm));
82296177Sjhibbits
83296177Sjhibbits    if (event & IM_EV_RX)
84296177Sjhibbits        FmPortImRx(p_FmPort);
85296177Sjhibbits    if ((event & IM_EV_BSY) && p_FmPort->f_Exception)
86296177Sjhibbits        p_FmPort->f_Exception(p_FmPort->h_App, e_FM_PORT_EXCEPTION_IM_BUSY);
87296177Sjhibbits}
88296177Sjhibbits
89296177Sjhibbits
90296177Sjhibbitsstatic t_Error TxConf(t_FmPort *p_FmPort, e_TxConfType confType)
91296177Sjhibbits{
92296177Sjhibbits    t_Error             retVal = E_BUSY;
93296177Sjhibbits    uint32_t            bdStatus;
94296177Sjhibbits    uint16_t            savedStartBdId, confBdId;
95296177Sjhibbits
96296177Sjhibbits    ASSERT_COND(p_FmPort);
97296177Sjhibbits
98296177Sjhibbits    /*
99296177Sjhibbits    if (confType==e_TX_CONF_TYPE_CHECK)
100296177Sjhibbits        return (WfqEntryIsQueueEmpty(p_FmPort->im.h_WfqEntry) ? E_OK : E_BUSY);
101296177Sjhibbits    */
102296177Sjhibbits
103296177Sjhibbits    confBdId = savedStartBdId = p_FmPort->im.currBdId;
104296177Sjhibbits    bdStatus = BD_STATUS_AND_LENGTH(BD_GET(confBdId));
105296177Sjhibbits
106296177Sjhibbits    /* If R bit is set, we don't enter, or we break.
107296177Sjhibbits       we run till we get to R, or complete the loop */
108296177Sjhibbits    while ((!(bdStatus & BD_R_E) || (confType == e_TX_CONF_TYPE_FLUSH)) && (retVal != E_OK))
109296177Sjhibbits    {
110296177Sjhibbits        if (confType & e_TX_CONF_TYPE_CALLBACK) /* if it is confirmation with user callbacks */
111296177Sjhibbits            BD_STATUS_AND_LENGTH_SET(BD_GET(confBdId), 0);
112296177Sjhibbits
113296177Sjhibbits        /* case 1: R bit is 0 and Length is set -> confirm! */
114296177Sjhibbits        if ((confType & e_TX_CONF_TYPE_CALLBACK) && (bdStatus & BD_LENGTH_MASK))
115296177Sjhibbits        {
116296177Sjhibbits            if (p_FmPort->im.f_TxConf)
117296177Sjhibbits            {
118296177Sjhibbits                if ((confType == e_TX_CONF_TYPE_FLUSH) && (bdStatus & BD_R_E))
119296177Sjhibbits                    p_FmPort->im.f_TxConf(p_FmPort->h_App,
120296177Sjhibbits                                          BdBufferGet(XX_PhysToVirt, BD_GET(confBdId)),
121296177Sjhibbits                                          TX_CONF_STATUS_UNSENT,
122296177Sjhibbits                                          p_FmPort->im.p_BdShadow[confBdId]);
123296177Sjhibbits                else
124296177Sjhibbits                    p_FmPort->im.f_TxConf(p_FmPort->h_App,
125296177Sjhibbits                                          BdBufferGet(XX_PhysToVirt, BD_GET(confBdId)),
126296177Sjhibbits                                          0,
127296177Sjhibbits                                          p_FmPort->im.p_BdShadow[confBdId]);
128296177Sjhibbits            }
129296177Sjhibbits        }
130296177Sjhibbits        /* case 2: R bit is 0 and Length is 0 -> not used yet, nop! */
131296177Sjhibbits
132296177Sjhibbits        confBdId = GetNextBdId(p_FmPort, confBdId);
133296177Sjhibbits        if (confBdId == savedStartBdId)
134296177Sjhibbits            retVal = E_OK;
135296177Sjhibbits        bdStatus = BD_STATUS_AND_LENGTH(BD_GET(confBdId));
136296177Sjhibbits    }
137296177Sjhibbits
138296177Sjhibbits    return retVal;
139296177Sjhibbits}
140296177Sjhibbits
141296177Sjhibbitst_Error FmPortImEnable(t_FmPort *p_FmPort)
142296177Sjhibbits{
143296177Sjhibbits    uint32_t    tmpReg = GET_UINT32(p_FmPort->im.p_FmPortImPram->mode);
144296177Sjhibbits    WRITE_UINT32(p_FmPort->im.p_FmPortImPram->mode, (uint32_t)(tmpReg & ~IM_MODE_GRC_STP));
145296177Sjhibbits    return E_OK;
146296177Sjhibbits}
147296177Sjhibbits
148296177Sjhibbitst_Error FmPortImDisable(t_FmPort *p_FmPort)
149296177Sjhibbits{
150296177Sjhibbits    uint32_t    tmpReg = GET_UINT32(p_FmPort->im.p_FmPortImPram->mode);
151296177Sjhibbits    WRITE_UINT32(p_FmPort->im.p_FmPortImPram->mode, (uint32_t)(tmpReg | IM_MODE_GRC_STP));
152296177Sjhibbits    return E_OK;
153296177Sjhibbits}
154296177Sjhibbits
155296177Sjhibbitst_Error FmPortImRx(t_FmPort *p_FmPort)
156296177Sjhibbits{
157296177Sjhibbits    t_Handle                h_CurrUserPriv, h_NewUserPriv;
158296177Sjhibbits    uint32_t                bdStatus;
159296177Sjhibbits    volatile uint8_t        buffPos;
160296177Sjhibbits    uint16_t                length;
161296177Sjhibbits    uint16_t                errors/*, reportErrors*/;
162296177Sjhibbits    uint8_t                 *p_CurData, *p_Data;
163296177Sjhibbits    uint32_t                flags;
164296177Sjhibbits
165296177Sjhibbits    ASSERT_COND(p_FmPort);
166296177Sjhibbits
167296177Sjhibbits    flags = XX_LockIntrSpinlock(p_FmPort->h_Spinlock);
168296177Sjhibbits    if (p_FmPort->lock)
169296177Sjhibbits    {
170296177Sjhibbits        XX_UnlockIntrSpinlock(p_FmPort->h_Spinlock, flags);
171296177Sjhibbits        return E_OK;
172296177Sjhibbits    }
173296177Sjhibbits    p_FmPort->lock = TRUE;
174296177Sjhibbits    XX_UnlockIntrSpinlock(p_FmPort->h_Spinlock, flags);
175296177Sjhibbits
176296177Sjhibbits    bdStatus = BD_STATUS_AND_LENGTH(BD_GET(p_FmPort->im.currBdId));
177296177Sjhibbits
178296177Sjhibbits    while (!(bdStatus & BD_R_E)) /* while there is data in the Rx BD */
179296177Sjhibbits    {
180296177Sjhibbits        if ((p_Data = p_FmPort->im.rxPool.f_GetBuf(p_FmPort->im.rxPool.h_BufferPool, &h_NewUserPriv)) == NULL)
181296177Sjhibbits        {
182296177Sjhibbits            p_FmPort->lock = FALSE;
183296177Sjhibbits            RETURN_ERROR(MAJOR, E_NOT_AVAILABLE, ("Data buffer"));
184296177Sjhibbits        }
185296177Sjhibbits
186296177Sjhibbits        if (p_FmPort->im.firstBdOfFrameId == IM_ILEGAL_BD_ID)
187296177Sjhibbits            p_FmPort->im.firstBdOfFrameId = p_FmPort->im.currBdId;
188296177Sjhibbits
189296177Sjhibbits        errors = 0;
190296177Sjhibbits        p_CurData = BdBufferGet(p_FmPort->im.rxPool.f_PhysToVirt, BD_GET(p_FmPort->im.currBdId));
191296177Sjhibbits        h_CurrUserPriv = p_FmPort->im.p_BdShadow[p_FmPort->im.currBdId];
192296177Sjhibbits        length = (uint16_t)((bdStatus & BD_L) ?
193296177Sjhibbits                            ((bdStatus & BD_LENGTH_MASK) - p_FmPort->im.rxFrameAccumLength):
194296177Sjhibbits                            (bdStatus & BD_LENGTH_MASK));
195296177Sjhibbits        p_FmPort->im.rxFrameAccumLength += length;
196296177Sjhibbits
197296177Sjhibbits        /* determine whether buffer is first, last, first and last (single  */
198296177Sjhibbits        /* buffer frame) or middle (not first and not last)                 */
199296177Sjhibbits        buffPos = (uint8_t)((p_FmPort->im.currBdId == p_FmPort->im.firstBdOfFrameId) ?
200296177Sjhibbits                            ((bdStatus & BD_L) ? SINGLE_BUF : FIRST_BUF) :
201296177Sjhibbits                            ((bdStatus & BD_L) ? LAST_BUF : MIDDLE_BUF));
202296177Sjhibbits
203296177Sjhibbits        if (bdStatus & BD_L)
204296177Sjhibbits        {
205296177Sjhibbits            p_FmPort->im.rxFrameAccumLength = 0;
206296177Sjhibbits            p_FmPort->im.firstBdOfFrameId = IM_ILEGAL_BD_ID;
207296177Sjhibbits        }
208296177Sjhibbits
209296177Sjhibbits        BdBufferSet(p_FmPort->im.rxPool.f_VirtToPhys, BD_GET(p_FmPort->im.currBdId), p_Data);
210296177Sjhibbits
211296177Sjhibbits        BD_STATUS_AND_LENGTH_SET(BD_GET(p_FmPort->im.currBdId), BD_R_E);
212296177Sjhibbits
213296177Sjhibbits        errors = (uint16_t)((bdStatus & BD_RX_ERRORS) >> 16);
214296177Sjhibbits        p_FmPort->im.p_BdShadow[p_FmPort->im.currBdId] = h_NewUserPriv;
215296177Sjhibbits
216296177Sjhibbits        p_FmPort->im.currBdId = GetNextBdId(p_FmPort, p_FmPort->im.currBdId);
217296177Sjhibbits        WRITE_UINT16(p_FmPort->im.p_FmPortImPram->rxQd.offsetOut, (uint16_t)(p_FmPort->im.currBdId<<4));
218296177Sjhibbits        /* Pass the buffer if one of the conditions is true:
219296177Sjhibbits        - There are no errors
220296177Sjhibbits        - This is a part of a larger frame ( the application has already received some buffers )
221296177Sjhibbits        - There is an error, but it was defined to be passed anyway. */
222296177Sjhibbits        if ((buffPos != SINGLE_BUF) || !errors || (errors & (uint16_t)(BD_ERROR_PASS_FRAME>>16)))
223296177Sjhibbits        {
224296177Sjhibbits            if (p_FmPort->im.f_RxStore(p_FmPort->h_App,
225296177Sjhibbits                                       p_CurData,
226296177Sjhibbits                                       length,
227296177Sjhibbits                                       errors,
228296177Sjhibbits                                       buffPos,
229296177Sjhibbits                                       h_CurrUserPriv) == e_RX_STORE_RESPONSE_PAUSE)
230296177Sjhibbits                break;
231296177Sjhibbits        }
232296177Sjhibbits        else if (p_FmPort->im.rxPool.f_PutBuf(p_FmPort->im.rxPool.h_BufferPool,
233296177Sjhibbits                                              p_CurData,
234296177Sjhibbits                                              h_CurrUserPriv))
235296177Sjhibbits        {
236296177Sjhibbits            p_FmPort->lock = FALSE;
237296177Sjhibbits            RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Failed freeing data buffer"));
238296177Sjhibbits        }
239296177Sjhibbits
240296177Sjhibbits        bdStatus = BD_STATUS_AND_LENGTH(BD_GET(p_FmPort->im.currBdId));
241296177Sjhibbits    }
242296177Sjhibbits    p_FmPort->lock = FALSE;
243296177Sjhibbits    return E_OK;
244296177Sjhibbits}
245296177Sjhibbits
246296177Sjhibbitsvoid FmPortConfigIM (t_FmPort *p_FmPort, t_FmPortParams *p_FmPortParams)
247296177Sjhibbits{
248296177Sjhibbits    ASSERT_COND(p_FmPort);
249296177Sjhibbits
250296177Sjhibbits    SANITY_CHECK_RETURN(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
251296177Sjhibbits
252296177Sjhibbits    p_FmPort->im.h_FmMuram                      = p_FmPortParams->specificParams.imRxTxParams.h_FmMuram;
253296177Sjhibbits    p_FmPort->p_FmPortDriverParam->liodnOffset  = p_FmPortParams->specificParams.imRxTxParams.liodnOffset;
254296177Sjhibbits    p_FmPort->im.dataMemId                      = p_FmPortParams->specificParams.imRxTxParams.dataMemId;
255296177Sjhibbits    p_FmPort->im.dataMemAttributes              = p_FmPortParams->specificParams.imRxTxParams.dataMemAttributes;
256296177Sjhibbits
257296177Sjhibbits    p_FmPort->im.fwExtStructsMemId              = DEFAULT_PORT_ImfwExtStructsMemId;
258296177Sjhibbits    p_FmPort->im.fwExtStructsMemAttr            = DEFAULT_PORT_ImfwExtStructsMemAttr;
259296177Sjhibbits
260296177Sjhibbits    if ((p_FmPort->portType == e_FM_PORT_TYPE_RX) ||
261296177Sjhibbits        (p_FmPort->portType == e_FM_PORT_TYPE_RX_10G))
262296177Sjhibbits    {
263296177Sjhibbits        p_FmPort->im.rxPool.h_BufferPool    = p_FmPortParams->specificParams.imRxTxParams.rxPoolParams.h_BufferPool;
264296177Sjhibbits        p_FmPort->im.rxPool.f_GetBuf        = p_FmPortParams->specificParams.imRxTxParams.rxPoolParams.f_GetBuf;
265296177Sjhibbits        p_FmPort->im.rxPool.f_PutBuf        = p_FmPortParams->specificParams.imRxTxParams.rxPoolParams.f_PutBuf;
266296177Sjhibbits        p_FmPort->im.rxPool.bufferSize      = p_FmPortParams->specificParams.imRxTxParams.rxPoolParams.bufferSize;
267296177Sjhibbits        p_FmPort->im.rxPool.f_PhysToVirt    = p_FmPortParams->specificParams.imRxTxParams.rxPoolParams.f_PhysToVirt;
268296177Sjhibbits        if (!p_FmPort->im.rxPool.f_PhysToVirt)
269296177Sjhibbits            p_FmPort->im.rxPool.f_PhysToVirt = XX_PhysToVirt;
270296177Sjhibbits        p_FmPort->im.rxPool.f_VirtToPhys    = p_FmPortParams->specificParams.imRxTxParams.rxPoolParams.f_VirtToPhys;
271296177Sjhibbits        if (!p_FmPort->im.rxPool.f_VirtToPhys)
272296177Sjhibbits            p_FmPort->im.rxPool.f_VirtToPhys = XX_VirtToPhys;
273296177Sjhibbits        p_FmPort->im.f_RxStore              = p_FmPortParams->specificParams.imRxTxParams.f_RxStore;
274296177Sjhibbits
275296177Sjhibbits        p_FmPort->im.mrblr                  = 0x8000;
276296177Sjhibbits        while (p_FmPort->im.mrblr)
277296177Sjhibbits        {
278296177Sjhibbits            if (p_FmPort->im.rxPool.bufferSize & p_FmPort->im.mrblr)
279296177Sjhibbits                break;
280296177Sjhibbits            p_FmPort->im.mrblr >>= 1;
281296177Sjhibbits        }
282296177Sjhibbits        if (p_FmPort->im.mrblr != p_FmPort->im.rxPool.bufferSize)
283296177Sjhibbits            DBG(WARNING, ("Max-Rx-Buffer-Length set to %d", p_FmPort->im.mrblr));
284296177Sjhibbits        p_FmPort->im.bdRingSize             = DEFAULT_PORT_rxBdRingLength;
285296177Sjhibbits        p_FmPort->exceptions                = DEFAULT_exception;
286296177Sjhibbits        if (FmIsMaster(p_FmPort->h_Fm))
287296177Sjhibbits            p_FmPort->polling               = FALSE;
288296177Sjhibbits        else
289296177Sjhibbits            p_FmPort->polling               = TRUE;
290296177Sjhibbits        p_FmPort->fmanCtrlEventId           = (uint8_t)NO_IRQ;
291296177Sjhibbits    }
292296177Sjhibbits    else
293296177Sjhibbits    {
294296177Sjhibbits        p_FmPort->im.f_TxConf               = p_FmPortParams->specificParams.imRxTxParams.f_TxConf;
295296177Sjhibbits
296296177Sjhibbits        p_FmPort->im.bdRingSize             = DEFAULT_PORT_txBdRingLength;
297296177Sjhibbits    }
298296177Sjhibbits}
299296177Sjhibbits
300296177Sjhibbitst_Error FmPortImCheckInitParameters(t_FmPort *p_FmPort)
301296177Sjhibbits{
302296177Sjhibbits    if ((p_FmPort->portType != e_FM_PORT_TYPE_RX) &&
303296177Sjhibbits        (p_FmPort->portType != e_FM_PORT_TYPE_RX_10G) &&
304296177Sjhibbits        (p_FmPort->portType != e_FM_PORT_TYPE_TX) &&
305296177Sjhibbits        (p_FmPort->portType != e_FM_PORT_TYPE_TX_10G))
306296177Sjhibbits        RETURN_ERROR(MAJOR, E_INVALID_VALUE, NO_MSG);
307296177Sjhibbits
308296177Sjhibbits    if ((p_FmPort->portType == e_FM_PORT_TYPE_RX) ||
309296177Sjhibbits        (p_FmPort->portType == e_FM_PORT_TYPE_RX_10G))
310296177Sjhibbits    {
311296177Sjhibbits        if (!POWER_OF_2(p_FmPort->im.mrblr))
312296177Sjhibbits            RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("max Rx buffer length must be power of 2!!!"));
313296177Sjhibbits        if (p_FmPort->im.mrblr < 256)
314296177Sjhibbits            RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("max Rx buffer length must at least 256!!!"));
315296177Sjhibbits        if(p_FmPort->p_FmPortDriverParam->liodnOffset & ~FM_LIODN_OFFSET_MASK)
316296177Sjhibbits            RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("liodnOffset is larger than %d", FM_LIODN_OFFSET_MASK+1));
317296177Sjhibbits#ifdef FM_PARTITION_ARRAY
318296177Sjhibbits        {
319296177Sjhibbits            t_FmRevisionInfo revInfo;
320296177Sjhibbits            FM_GetRevision(p_FmPort->h_Fm, &revInfo);
321296177Sjhibbits            if ((revInfo.majorRev == 1) && (revInfo.minorRev == 0))
322296177Sjhibbits            {
323296177Sjhibbits                if(p_FmPort->p_FmPortDriverParam->liodnOffset >= MAX_LIODN_OFFSET)
324296177Sjhibbits                {
325296177Sjhibbits                    p_FmPort->p_FmPortDriverParam->liodnOffset =
326296177Sjhibbits                        (uint16_t)(p_FmPort->p_FmPortDriverParam->liodnOffset & (MAX_LIODN_OFFSET-1));
327296177Sjhibbits                    DBG(WARNING, ("liodnOffset number is out of rev1 range - MSB bits cleard."));
328296177Sjhibbits                }
329296177Sjhibbits            }
330296177Sjhibbits        }
331296177Sjhibbits#endif /* FM_PARTITION_ARRAY */
332296177Sjhibbits/* TODO - add checks */
333296177Sjhibbits    }
334296177Sjhibbits    else
335296177Sjhibbits    {
336296177Sjhibbits/* TODO - add checks */
337296177Sjhibbits    }
338296177Sjhibbits
339296177Sjhibbits    return E_OK;
340296177Sjhibbits}
341296177Sjhibbits
342296177Sjhibbitst_Error FmPortImInit(t_FmPort *p_FmPort)
343296177Sjhibbits{
344296177Sjhibbits    t_FmImBd    *p_Bd=NULL;
345296177Sjhibbits    t_Handle    h_BufContext;
346296177Sjhibbits    uint64_t    tmpPhysBase;
347296177Sjhibbits    uint16_t    log2Num;
348296177Sjhibbits    uint8_t     *p_Data/*, *p_Tmp*/;
349296177Sjhibbits    int         i;
350296177Sjhibbits    t_Error     err;
351296177Sjhibbits    uint16_t    tmpReg16;
352296177Sjhibbits    uint32_t    tmpReg32;
353296177Sjhibbits
354296177Sjhibbits    ASSERT_COND(p_FmPort);
355296177Sjhibbits
356296177Sjhibbits    p_FmPort->im.p_FmPortImPram =
357296177Sjhibbits        (t_FmPortImPram *)FM_MURAM_AllocMem(p_FmPort->im.h_FmMuram, sizeof(t_FmPortImPram), IM_PRAM_ALIGN);
358296177Sjhibbits    if (!p_FmPort->im.p_FmPortImPram)
359296177Sjhibbits        RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Independent-Mode Parameter-RAM!!!"));
360296177Sjhibbits    WRITE_BLOCK(p_FmPort->im.p_FmPortImPram, 0, sizeof(t_FmPortImPram));
361296177Sjhibbits
362296177Sjhibbits    if ((p_FmPort->portType == e_FM_PORT_TYPE_RX) ||
363296177Sjhibbits        (p_FmPort->portType == e_FM_PORT_TYPE_RX_10G))
364296177Sjhibbits    {
365296177Sjhibbits        p_FmPort->im.p_BdRing = (t_FmImBd *)XX_MallocSmart((uint32_t)(sizeof(t_FmImBd)*p_FmPort->im.bdRingSize), p_FmPort->im.fwExtStructsMemId, 4);
366296177Sjhibbits        if (!p_FmPort->im.p_BdRing)
367296177Sjhibbits            RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Independent-Mode Rx BD ring!!!"));
368296177Sjhibbits        IOMemSet32(p_FmPort->im.p_BdRing, 0, (uint32_t)(sizeof(t_FmImBd)*p_FmPort->im.bdRingSize));
369296177Sjhibbits
370296177Sjhibbits        p_FmPort->im.p_BdShadow = (t_Handle *)XX_Malloc((uint32_t)(sizeof(t_Handle)*p_FmPort->im.bdRingSize));
371296177Sjhibbits        if (!p_FmPort->im.p_BdShadow)
372296177Sjhibbits            RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Independent-Mode Rx BD shadow!!!"));
373296177Sjhibbits        memset(p_FmPort->im.p_BdShadow, 0, (uint32_t)(sizeof(t_Handle)*p_FmPort->im.bdRingSize));
374296177Sjhibbits
375296177Sjhibbits        /* Initialize the Rx-BD ring */
376296177Sjhibbits        for (i=0; i<p_FmPort->im.bdRingSize; i++)
377296177Sjhibbits        {
378296177Sjhibbits            p_Bd = BD_GET(i);
379296177Sjhibbits            BD_STATUS_AND_LENGTH_SET (p_Bd, BD_R_E);
380296177Sjhibbits
381296177Sjhibbits            if ((p_Data = p_FmPort->im.rxPool.f_GetBuf(p_FmPort->im.rxPool.h_BufferPool, &h_BufContext)) == NULL)
382296177Sjhibbits                RETURN_ERROR(MAJOR, E_NOT_AVAILABLE, ("Data buffer"));
383296177Sjhibbits            BdBufferSet(p_FmPort->im.rxPool.f_VirtToPhys, p_Bd, p_Data);
384296177Sjhibbits            p_FmPort->im.p_BdShadow[i] = h_BufContext;
385296177Sjhibbits        }
386296177Sjhibbits
387296177Sjhibbits        if ((p_FmPort->im.dataMemAttributes & MEMORY_ATTR_CACHEABLE) ||
388296177Sjhibbits            (p_FmPort->im.fwExtStructsMemAttr & MEMORY_ATTR_CACHEABLE))
389296177Sjhibbits            WRITE_UINT32(p_FmPort->im.p_FmPortImPram->mode, IM_MODE_GBL | IM_MODE_SET_BO(2));
390296177Sjhibbits        else
391296177Sjhibbits            WRITE_UINT32(p_FmPort->im.p_FmPortImPram->mode, IM_MODE_SET_BO(2));
392296177Sjhibbits
393296177Sjhibbits        WRITE_UINT32(p_FmPort->im.p_FmPortImPram->rxQdPtr,
394296177Sjhibbits                     (uint32_t)((uint64_t)(XX_VirtToPhys(p_FmPort->im.p_FmPortImPram)) -
395296177Sjhibbits                                p_FmPort->p_FmPortDriverParam->fmMuramPhysBaseAddr + 0x20));
396296177Sjhibbits
397296177Sjhibbits        LOG2((uint64_t)p_FmPort->im.mrblr, log2Num);
398296177Sjhibbits        WRITE_UINT16(p_FmPort->im.p_FmPortImPram->mrblr, log2Num);
399296177Sjhibbits
400296177Sjhibbits        /* Initialize Rx QD */
401296177Sjhibbits        tmpPhysBase = (uint64_t)(XX_VirtToPhys(p_FmPort->im.p_BdRing));
402296177Sjhibbits        SET_ADDR(&p_FmPort->im.p_FmPortImPram->rxQd.bdRingBase, tmpPhysBase);
403296177Sjhibbits        WRITE_UINT16(p_FmPort->im.p_FmPortImPram->rxQd.bdRingSize, (uint16_t)(sizeof(t_FmImBd)*p_FmPort->im.bdRingSize));
404296177Sjhibbits
405296177Sjhibbits        /* Update the IM PRAM address in the BMI */
406296177Sjhibbits        WRITE_UINT32(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rfqid,
407296177Sjhibbits                     (uint32_t)((uint64_t)(XX_VirtToPhys(p_FmPort->im.p_FmPortImPram)) -
408296177Sjhibbits                                p_FmPort->p_FmPortDriverParam->fmMuramPhysBaseAddr));
409296177Sjhibbits        if (!p_FmPort->polling || p_FmPort->exceptions)
410296177Sjhibbits        {
411296177Sjhibbits            /* Allocate, configure and register interrupts */
412296177Sjhibbits            err = FmAllocFmanCtrlEventReg(p_FmPort->h_Fm, &p_FmPort->fmanCtrlEventId);
413296177Sjhibbits            if(err)
414296177Sjhibbits                RETURN_ERROR(MAJOR, err, NO_MSG);
415296177Sjhibbits
416296177Sjhibbits            ASSERT_COND(!(p_FmPort->fmanCtrlEventId & ~IM_RXQD_FPMEVT_SEL_MASK));
417296177Sjhibbits            tmpReg16 = (uint16_t)(p_FmPort->fmanCtrlEventId & IM_RXQD_FPMEVT_SEL_MASK);
418296177Sjhibbits            tmpReg32 = 0;
419296177Sjhibbits
420296177Sjhibbits            if(p_FmPort->exceptions & IM_EV_BSY)
421296177Sjhibbits            {
422296177Sjhibbits                tmpReg16 |= IM_RXQD_BSYINTM;
423296177Sjhibbits                tmpReg32 |= IM_EV_BSY;
424296177Sjhibbits            }
425296177Sjhibbits            if(!p_FmPort->polling)
426296177Sjhibbits            {
427296177Sjhibbits                tmpReg16 |= IM_RXQD_RXFINTM;
428296177Sjhibbits                tmpReg32 |= IM_EV_RX;
429296177Sjhibbits            }
430296177Sjhibbits            WRITE_UINT16(p_FmPort->im.p_FmPortImPram->rxQd.gen, tmpReg16);
431296177Sjhibbits
432296177Sjhibbits            FmRegisterFmanCtrlIntr(p_FmPort->h_Fm, p_FmPort->fmanCtrlEventId, ImException , (t_Handle)p_FmPort);
433296177Sjhibbits
434296177Sjhibbits            FmSetFmanCtrlIntr(p_FmPort->h_Fm, p_FmPort->fmanCtrlEventId, tmpReg32);
435296177Sjhibbits        }
436296177Sjhibbits        else
437296177Sjhibbits            p_FmPort->fmanCtrlEventId = (uint8_t)NO_IRQ;
438296177Sjhibbits    }
439296177Sjhibbits    else
440296177Sjhibbits    {
441296177Sjhibbits        p_FmPort->im.p_BdRing = (t_FmImBd *)XX_MallocSmart((uint32_t)(sizeof(t_FmImBd)*p_FmPort->im.bdRingSize), p_FmPort->im.fwExtStructsMemId, 4);
442296177Sjhibbits        if (!p_FmPort->im.p_BdRing)
443296177Sjhibbits            RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Independent-Mode Tx BD ring!!!"));
444296177Sjhibbits        IOMemSet32(p_FmPort->im.p_BdRing, 0, (uint32_t)(sizeof(t_FmImBd)*p_FmPort->im.bdRingSize));
445296177Sjhibbits
446296177Sjhibbits        p_FmPort->im.p_BdShadow = (t_Handle *)XX_Malloc((uint32_t)(sizeof(t_Handle)*p_FmPort->im.bdRingSize));
447296177Sjhibbits        if (!p_FmPort->im.p_BdShadow)
448296177Sjhibbits            RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Independent-Mode Rx BD shadow!!!"));
449296177Sjhibbits        memset(p_FmPort->im.p_BdShadow, 0, (uint32_t)(sizeof(t_Handle)*p_FmPort->im.bdRingSize));
450296177Sjhibbits        p_FmPort->im.firstBdOfFrameId = IM_ILEGAL_BD_ID;
451296177Sjhibbits
452296177Sjhibbits        if ((p_FmPort->im.dataMemAttributes & MEMORY_ATTR_CACHEABLE) ||
453296177Sjhibbits            (p_FmPort->im.fwExtStructsMemAttr & MEMORY_ATTR_CACHEABLE))
454296177Sjhibbits            WRITE_UINT32(p_FmPort->im.p_FmPortImPram->mode, IM_MODE_GBL | IM_MODE_SET_BO(2));
455296177Sjhibbits        else
456296177Sjhibbits            WRITE_UINT32(p_FmPort->im.p_FmPortImPram->mode, IM_MODE_SET_BO(2));
457296177Sjhibbits
458296177Sjhibbits        WRITE_UINT32(p_FmPort->im.p_FmPortImPram->txQdPtr,
459296177Sjhibbits                     (uint32_t)((uint64_t)(XX_VirtToPhys(p_FmPort->im.p_FmPortImPram)) -
460296177Sjhibbits                                p_FmPort->p_FmPortDriverParam->fmMuramPhysBaseAddr + 0x40));
461296177Sjhibbits
462296177Sjhibbits        /* Initialize Tx QD */
463296177Sjhibbits        tmpPhysBase = (uint64_t)(XX_VirtToPhys(p_FmPort->im.p_BdRing));
464296177Sjhibbits        SET_ADDR(&p_FmPort->im.p_FmPortImPram->txQd.bdRingBase, tmpPhysBase);
465296177Sjhibbits        WRITE_UINT16(p_FmPort->im.p_FmPortImPram->txQd.bdRingSize, (uint16_t)(sizeof(t_FmImBd)*p_FmPort->im.bdRingSize));
466296177Sjhibbits
467296177Sjhibbits        /* Update the IM PRAM address in the BMI */
468296177Sjhibbits        WRITE_UINT32(p_FmPort->p_FmPortBmiRegs->txPortBmiRegs.fmbm_tcfqid,
469296177Sjhibbits                     (uint32_t)((uint64_t)(XX_VirtToPhys(p_FmPort->im.p_FmPortImPram)) -
470296177Sjhibbits                                p_FmPort->p_FmPortDriverParam->fmMuramPhysBaseAddr));
471296177Sjhibbits    }
472296177Sjhibbits
473296177Sjhibbits
474296177Sjhibbits    return E_OK;
475296177Sjhibbits}
476296177Sjhibbits
477296177Sjhibbitsvoid FmPortImFree(t_FmPort *p_FmPort)
478296177Sjhibbits{
479296177Sjhibbits    uint32_t    bdStatus;
480296177Sjhibbits    uint8_t     *p_CurData;
481296177Sjhibbits
482296177Sjhibbits    ASSERT_COND(p_FmPort);
483296177Sjhibbits    ASSERT_COND(p_FmPort->im.p_FmPortImPram);
484296177Sjhibbits
485296177Sjhibbits    if ((p_FmPort->portType == e_FM_PORT_TYPE_RX) ||
486296177Sjhibbits        (p_FmPort->portType == e_FM_PORT_TYPE_RX_10G))
487296177Sjhibbits    {
488296177Sjhibbits        if (!p_FmPort->polling || p_FmPort->exceptions)
489296177Sjhibbits        {
490296177Sjhibbits            /* Deallocate and unregister interrupts */
491296177Sjhibbits            FmSetFmanCtrlIntr(p_FmPort->h_Fm, p_FmPort->fmanCtrlEventId, 0);
492296177Sjhibbits
493296177Sjhibbits            FmFreeFmanCtrlEventReg(p_FmPort->h_Fm, p_FmPort->fmanCtrlEventId);
494296177Sjhibbits
495296177Sjhibbits            WRITE_UINT16(p_FmPort->im.p_FmPortImPram->rxQd.gen, 0);
496296177Sjhibbits
497296177Sjhibbits            FmUnregisterFmanCtrlIntr(p_FmPort->h_Fm, p_FmPort->fmanCtrlEventId);
498296177Sjhibbits        }
499296177Sjhibbits        /* Try first clean what has received */
500296177Sjhibbits        FmPortImRx(p_FmPort);
501296177Sjhibbits
502296177Sjhibbits        /* Now, get rid of the the empty buffer! */
503296177Sjhibbits        bdStatus = BD_STATUS_AND_LENGTH(BD_GET(p_FmPort->im.currBdId));
504296177Sjhibbits
505296177Sjhibbits        while (bdStatus & BD_R_E) /* while there is data in the Rx BD */
506296177Sjhibbits        {
507296177Sjhibbits            p_CurData = BdBufferGet(p_FmPort->im.rxPool.f_PhysToVirt, BD_GET(p_FmPort->im.currBdId));
508296177Sjhibbits
509296177Sjhibbits            BdBufferSet(p_FmPort->im.rxPool.f_VirtToPhys, BD_GET(p_FmPort->im.currBdId), NULL);
510296177Sjhibbits            BD_STATUS_AND_LENGTH_SET(BD_GET(p_FmPort->im.currBdId), 0);
511296177Sjhibbits
512296177Sjhibbits            p_FmPort->im.rxPool.f_PutBuf(p_FmPort->im.rxPool.h_BufferPool,
513296177Sjhibbits                                         p_CurData,
514296177Sjhibbits                                         p_FmPort->im.p_BdShadow[p_FmPort->im.currBdId]);
515296177Sjhibbits
516296177Sjhibbits            p_FmPort->im.currBdId = GetNextBdId(p_FmPort, p_FmPort->im.currBdId);
517296177Sjhibbits            bdStatus = BD_STATUS_AND_LENGTH(BD_GET(p_FmPort->im.currBdId));
518296177Sjhibbits        }
519296177Sjhibbits    }
520296177Sjhibbits    else
521296177Sjhibbits        TxConf(p_FmPort, e_TX_CONF_TYPE_FLUSH);
522296177Sjhibbits
523296177Sjhibbits    FM_MURAM_FreeMem(p_FmPort->im.h_FmMuram, p_FmPort->im.p_FmPortImPram);
524296177Sjhibbits
525296177Sjhibbits    if (p_FmPort->im.p_BdShadow)
526296177Sjhibbits        XX_Free(p_FmPort->im.p_BdShadow);
527296177Sjhibbits
528296177Sjhibbits    if (p_FmPort->im.p_BdRing)
529296177Sjhibbits        XX_FreeSmart(p_FmPort->im.p_BdRing);
530296177Sjhibbits}
531296177Sjhibbits
532296177Sjhibbits
533296177Sjhibbitst_Error FM_PORT_ConfigIMMaxRxBufLength(t_Handle h_FmPort, uint16_t newVal)
534296177Sjhibbits{
535296177Sjhibbits    t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
536296177Sjhibbits
537296177Sjhibbits    SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
538296177Sjhibbits    SANITY_CHECK_RETURN_ERROR(p_FmPort->imEn, E_INVALID_STATE);
539296177Sjhibbits    SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
540296177Sjhibbits
541296177Sjhibbits    p_FmPort->im.mrblr = newVal;
542296177Sjhibbits
543296177Sjhibbits    return E_OK;
544296177Sjhibbits}
545296177Sjhibbits
546296177Sjhibbitst_Error FM_PORT_ConfigIMRxBdRingLength(t_Handle h_FmPort, uint16_t newVal)
547296177Sjhibbits{
548296177Sjhibbits    t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
549296177Sjhibbits
550296177Sjhibbits    SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
551296177Sjhibbits    SANITY_CHECK_RETURN_ERROR(p_FmPort->imEn, E_INVALID_STATE);
552296177Sjhibbits    SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
553296177Sjhibbits
554296177Sjhibbits    p_FmPort->im.bdRingSize = newVal;
555296177Sjhibbits
556296177Sjhibbits    return E_OK;
557296177Sjhibbits}
558296177Sjhibbits
559296177Sjhibbitst_Error FM_PORT_ConfigIMTxBdRingLength(t_Handle h_FmPort, uint16_t newVal)
560296177Sjhibbits{
561296177Sjhibbits    t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
562296177Sjhibbits
563296177Sjhibbits    SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
564296177Sjhibbits    SANITY_CHECK_RETURN_ERROR(p_FmPort->imEn, E_INVALID_STATE);
565296177Sjhibbits    SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
566296177Sjhibbits
567296177Sjhibbits    p_FmPort->im.bdRingSize = newVal;
568296177Sjhibbits
569296177Sjhibbits    return E_OK;
570296177Sjhibbits}
571296177Sjhibbits
572296177Sjhibbitst_Error  FM_PORT_ConfigIMFmanCtrlExternalStructsMemory(t_Handle h_FmPort,
573296177Sjhibbits                                                       uint8_t  memId,
574296177Sjhibbits                                                       uint32_t memAttributes)
575296177Sjhibbits{
576296177Sjhibbits    t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
577296177Sjhibbits
578296177Sjhibbits    SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
579296177Sjhibbits    SANITY_CHECK_RETURN_ERROR(p_FmPort->imEn, E_INVALID_STATE);
580296177Sjhibbits    SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
581296177Sjhibbits
582296177Sjhibbits    p_FmPort->im.fwExtStructsMemId              = memId;
583296177Sjhibbits    p_FmPort->im.fwExtStructsMemAttr            = memAttributes;
584296177Sjhibbits
585296177Sjhibbits    return E_OK;
586296177Sjhibbits}
587296177Sjhibbits
588296177Sjhibbitst_Error FM_PORT_ConfigIMPolling(t_Handle h_FmPort)
589296177Sjhibbits{
590296177Sjhibbits    t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
591296177Sjhibbits
592296177Sjhibbits    SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
593296177Sjhibbits    SANITY_CHECK_RETURN_ERROR(p_FmPort->imEn, E_INVALID_STATE);
594296177Sjhibbits    SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
595296177Sjhibbits
596296177Sjhibbits    if((p_FmPort->portType != e_FM_PORT_TYPE_RX_10G) && (p_FmPort->portType != e_FM_PORT_TYPE_RX))
597296177Sjhibbits        RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("Available for Rx ports only"));
598296177Sjhibbits
599296177Sjhibbits    if (!FmIsMaster(p_FmPort->h_Fm))
600296177Sjhibbits        RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("Available on master-partition only;"
601296177Sjhibbits                                                  "in guest-partitions, IM is always in polling!"));
602296177Sjhibbits
603296177Sjhibbits    p_FmPort->polling = TRUE;
604296177Sjhibbits
605296177Sjhibbits    return E_OK;
606296177Sjhibbits}
607296177Sjhibbits
608296177Sjhibbitst_Error FM_PORT_SetIMExceptions(t_Handle h_FmPort, e_FmPortExceptions exception, bool enable)
609296177Sjhibbits{
610296177Sjhibbits    t_FmPort    *p_FmPort = (t_FmPort*)h_FmPort;
611296177Sjhibbits    t_Error     err;
612296177Sjhibbits    uint16_t    tmpReg16;
613296177Sjhibbits    uint32_t    tmpReg32;
614296177Sjhibbits
615296177Sjhibbits    SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
616296177Sjhibbits    SANITY_CHECK_RETURN_ERROR(p_FmPort->imEn, E_INVALID_STATE);
617296177Sjhibbits    SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
618296177Sjhibbits
619296177Sjhibbits    if(exception == e_FM_PORT_EXCEPTION_IM_BUSY)
620296177Sjhibbits    {
621296177Sjhibbits        if(enable)
622296177Sjhibbits        {
623296177Sjhibbits            p_FmPort->exceptions |= IM_EV_BSY;
624296177Sjhibbits            if(p_FmPort->fmanCtrlEventId == (uint8_t)NO_IRQ)
625296177Sjhibbits            {
626296177Sjhibbits                /* Allocate, configure and register interrupts */
627296177Sjhibbits                err = FmAllocFmanCtrlEventReg(p_FmPort->h_Fm, &p_FmPort->fmanCtrlEventId);
628296177Sjhibbits                if(err)
629296177Sjhibbits                    RETURN_ERROR(MAJOR, err, NO_MSG);
630296177Sjhibbits                ASSERT_COND(!(p_FmPort->fmanCtrlEventId & ~IM_RXQD_FPMEVT_SEL_MASK));
631296177Sjhibbits
632296177Sjhibbits                FmRegisterFmanCtrlIntr(p_FmPort->h_Fm, p_FmPort->fmanCtrlEventId, ImException, (t_Handle)p_FmPort);
633296177Sjhibbits                tmpReg16 = (uint16_t)((p_FmPort->fmanCtrlEventId & IM_RXQD_FPMEVT_SEL_MASK) | IM_RXQD_BSYINTM);
634296177Sjhibbits                tmpReg32 = IM_EV_BSY;
635296177Sjhibbits            }
636296177Sjhibbits            else
637296177Sjhibbits            {
638296177Sjhibbits                tmpReg16 = (uint16_t)(GET_UINT16(p_FmPort->im.p_FmPortImPram->rxQd.gen) | IM_RXQD_BSYINTM);
639296177Sjhibbits                tmpReg32 = FmGetFmanCtrlIntr(p_FmPort->h_Fm, p_FmPort->fmanCtrlEventId) | IM_EV_BSY;
640296177Sjhibbits            }
641296177Sjhibbits
642296177Sjhibbits            WRITE_UINT16(p_FmPort->im.p_FmPortImPram->rxQd.gen, tmpReg16);
643296177Sjhibbits            FmSetFmanCtrlIntr(p_FmPort->h_Fm, p_FmPort->fmanCtrlEventId, tmpReg32);
644296177Sjhibbits        }
645296177Sjhibbits        else
646296177Sjhibbits        {
647296177Sjhibbits            p_FmPort->exceptions &= ~IM_EV_BSY;
648296177Sjhibbits            if (!p_FmPort->exceptions && p_FmPort->polling)
649296177Sjhibbits            {
650296177Sjhibbits                FmFreeFmanCtrlEventReg(p_FmPort->h_Fm, p_FmPort->fmanCtrlEventId);
651296177Sjhibbits                FmUnregisterFmanCtrlIntr(p_FmPort->h_Fm, p_FmPort->fmanCtrlEventId);
652296177Sjhibbits                FmSetFmanCtrlIntr(p_FmPort->h_Fm, p_FmPort->fmanCtrlEventId, 0);
653296177Sjhibbits                WRITE_UINT16(p_FmPort->im.p_FmPortImPram->rxQd.gen, 0);
654296177Sjhibbits                p_FmPort->fmanCtrlEventId = (uint8_t)NO_IRQ;
655296177Sjhibbits            }
656296177Sjhibbits            else
657296177Sjhibbits            {
658296177Sjhibbits                tmpReg16 = (uint16_t)(GET_UINT16(p_FmPort->im.p_FmPortImPram->rxQd.gen) & ~IM_RXQD_BSYINTM);
659296177Sjhibbits                WRITE_UINT16(p_FmPort->im.p_FmPortImPram->rxQd.gen, tmpReg16);
660296177Sjhibbits                tmpReg32 = FmGetFmanCtrlIntr(p_FmPort->h_Fm, p_FmPort->fmanCtrlEventId) & ~IM_EV_BSY;
661296177Sjhibbits                FmSetFmanCtrlIntr(p_FmPort->h_Fm, p_FmPort->fmanCtrlEventId, tmpReg32);
662296177Sjhibbits            }
663296177Sjhibbits        }
664296177Sjhibbits    }
665296177Sjhibbits    else
666296177Sjhibbits        RETURN_ERROR(MINOR, E_INVALID_SELECTION, ("Invalid exception."));
667296177Sjhibbits
668296177Sjhibbits    return E_OK;
669296177Sjhibbits}
670296177Sjhibbits
671296177Sjhibbitst_Error  FM_PORT_ImTx( t_Handle               h_FmPort,
672296177Sjhibbits                       uint8_t                *p_Data,
673296177Sjhibbits                       uint16_t               length,
674296177Sjhibbits                       bool                   lastBuffer,
675296177Sjhibbits                       t_Handle               h_BufContext)
676296177Sjhibbits{
677296177Sjhibbits    t_FmPort            *p_FmPort = (t_FmPort*)h_FmPort;
678296177Sjhibbits    uint16_t            nextBdId;
679296177Sjhibbits    uint32_t            bdStatus, nextBdStatus;
680296177Sjhibbits    bool                firstBuffer;
681296177Sjhibbits
682296177Sjhibbits    SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
683296177Sjhibbits    SANITY_CHECK_RETURN_ERROR(p_FmPort->imEn, E_INVALID_STATE);
684296177Sjhibbits    SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
685296177Sjhibbits
686296177Sjhibbits    bdStatus = BD_STATUS_AND_LENGTH(BD_GET(p_FmPort->im.currBdId));
687296177Sjhibbits    nextBdId = GetNextBdId(p_FmPort, p_FmPort->im.currBdId);
688296177Sjhibbits    nextBdStatus = BD_STATUS_AND_LENGTH(BD_GET(nextBdId));
689296177Sjhibbits
690296177Sjhibbits    if (!(bdStatus & BD_R_E) && !(nextBdStatus & BD_R_E))
691296177Sjhibbits    {
692296177Sjhibbits        /* Confirm the current BD - BD is available */
693296177Sjhibbits        if ((bdStatus & BD_LENGTH_MASK) && (p_FmPort->im.f_TxConf))
694296177Sjhibbits            p_FmPort->im.f_TxConf (p_FmPort->h_App,
695296177Sjhibbits                                   BdBufferGet(XX_PhysToVirt, BD_GET(p_FmPort->im.currBdId)),
696296177Sjhibbits                                   0,
697296177Sjhibbits                                   p_FmPort->im.p_BdShadow[p_FmPort->im.currBdId]);
698296177Sjhibbits
699296177Sjhibbits        bdStatus = length;
700296177Sjhibbits
701296177Sjhibbits        /* if this is the first BD of a frame */
702296177Sjhibbits        if (p_FmPort->im.firstBdOfFrameId == IM_ILEGAL_BD_ID)
703296177Sjhibbits        {
704296177Sjhibbits            firstBuffer = TRUE;
705296177Sjhibbits            p_FmPort->im.txFirstBdStatus = (bdStatus | BD_R_E);
706296177Sjhibbits
707296177Sjhibbits            if (!lastBuffer)
708296177Sjhibbits                p_FmPort->im.firstBdOfFrameId = p_FmPort->im.currBdId;
709296177Sjhibbits        }
710296177Sjhibbits        else
711296177Sjhibbits            firstBuffer = FALSE;
712296177Sjhibbits
713296177Sjhibbits        BdBufferSet(XX_VirtToPhys, BD_GET(p_FmPort->im.currBdId), p_Data);
714296177Sjhibbits        p_FmPort->im.p_BdShadow[p_FmPort->im.currBdId] = h_BufContext;
715296177Sjhibbits
716296177Sjhibbits        /* deal with last */
717296177Sjhibbits        if (lastBuffer)
718296177Sjhibbits        {
719296177Sjhibbits            /* if single buffer frame */
720296177Sjhibbits            if (firstBuffer)
721296177Sjhibbits                BD_STATUS_AND_LENGTH_SET(BD_GET(p_FmPort->im.currBdId), p_FmPort->im.txFirstBdStatus | BD_L);
722296177Sjhibbits            else
723296177Sjhibbits            {
724296177Sjhibbits                /* Set the last BD of the frame */
725296177Sjhibbits                BD_STATUS_AND_LENGTH_SET (BD_GET(p_FmPort->im.currBdId), (bdStatus | BD_R_E | BD_L));
726296177Sjhibbits                /* Set the first BD of the frame */
727296177Sjhibbits                BD_STATUS_AND_LENGTH_SET(BD_GET(p_FmPort->im.firstBdOfFrameId), p_FmPort->im.txFirstBdStatus);
728296177Sjhibbits                p_FmPort->im.firstBdOfFrameId = IM_ILEGAL_BD_ID;
729296177Sjhibbits            }
730296177Sjhibbits            WRITE_UINT16(p_FmPort->im.p_FmPortImPram->txQd.offsetIn, (uint16_t)(GetNextBdId(p_FmPort, p_FmPort->im.currBdId)<<4));
731296177Sjhibbits        }
732296177Sjhibbits        else if (!firstBuffer) /* mid frame buffer */
733296177Sjhibbits            BD_STATUS_AND_LENGTH_SET (BD_GET(p_FmPort->im.currBdId), bdStatus | BD_R_E);
734296177Sjhibbits
735296177Sjhibbits        p_FmPort->im.currBdId = GetNextBdId(p_FmPort, p_FmPort->im.currBdId);
736296177Sjhibbits    }
737296177Sjhibbits    else
738296177Sjhibbits    {
739296177Sjhibbits        /* Discard current frame. Return error.   */
740296177Sjhibbits        if (p_FmPort->im.firstBdOfFrameId != IM_ILEGAL_BD_ID)
741296177Sjhibbits        {
742296177Sjhibbits            /* Error:    No free BD */
743296177Sjhibbits            /* Response: Discard current frame. Return error.   */
744296177Sjhibbits            uint16_t   cleanBdId = p_FmPort->im.firstBdOfFrameId;
745296177Sjhibbits
746296177Sjhibbits            ASSERT_COND(p_FmPort->im.firstBdOfFrameId != p_FmPort->im.currBdId);
747296177Sjhibbits
748296177Sjhibbits            /* Since firstInFrame is not NULL, one buffer at least has already been
749296177Sjhibbits               inserted into the BD ring. Using do-while covers the situation of a
750296177Sjhibbits               frame spanned throughout the whole Tx BD ring (p_CleanBd is incremented
751296177Sjhibbits               prior to testing whether or not it's equal to TxBd). */
752296177Sjhibbits            do
753296177Sjhibbits            {
754296177Sjhibbits                BD_STATUS_AND_LENGTH_SET(BD_GET(cleanBdId), 0);
755296177Sjhibbits                /* Advance BD pointer */
756296177Sjhibbits                cleanBdId = GetNextBdId(p_FmPort, cleanBdId);
757296177Sjhibbits            } while (cleanBdId != p_FmPort->im.currBdId);
758296177Sjhibbits
759296177Sjhibbits            p_FmPort->im.currBdId = cleanBdId;
760296177Sjhibbits            p_FmPort->im.firstBdOfFrameId = IM_ILEGAL_BD_ID;
761296177Sjhibbits        }
762296177Sjhibbits
763296177Sjhibbits        return ERROR_CODE(E_FULL);
764296177Sjhibbits    }
765296177Sjhibbits
766296177Sjhibbits    return E_OK;
767296177Sjhibbits}
768296177Sjhibbits
769296177Sjhibbitsvoid FM_PORT_ImTxConf(t_Handle h_FmPort)
770296177Sjhibbits{
771296177Sjhibbits    t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
772296177Sjhibbits
773296177Sjhibbits    SANITY_CHECK_RETURN(p_FmPort, E_INVALID_HANDLE);
774296177Sjhibbits    SANITY_CHECK_RETURN(p_FmPort->imEn, E_INVALID_STATE);
775296177Sjhibbits    SANITY_CHECK_RETURN(!p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
776296177Sjhibbits
777296177Sjhibbits    TxConf(p_FmPort, e_TX_CONF_TYPE_CALLBACK);
778296177Sjhibbits}
779296177Sjhibbits
780296177Sjhibbitst_Error  FM_PORT_ImRx(t_Handle h_FmPort)
781296177Sjhibbits{
782296177Sjhibbits    t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
783296177Sjhibbits
784296177Sjhibbits    SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
785296177Sjhibbits    SANITY_CHECK_RETURN_ERROR(p_FmPort->imEn, E_INVALID_STATE);
786296177Sjhibbits    SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
787296177Sjhibbits
788296177Sjhibbits    return FmPortImRx(p_FmPort);
789296177Sjhibbits}
790