The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/contrib/ncsw/Peripherals/FM/Port/fm_port_im.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    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 
   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 
   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 
  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 
  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 
  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 
  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 
  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 
  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 
  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 
  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 
  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 
  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 
  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 
  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 
  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 
  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 
  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 
  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 }

Cache object: 561e5dc04ff4fb38f9d0b1dc83887e3c


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.