⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 zl5011xcetqueue.c

📁 Zalink50114----TDMoIP芯片驱动源码
💻 C
📖 第 1 页 / 共 3 页
字号:
 Remarks
   If the context is not currently active, then management can be enabled, but
   will not take place until it is active.
   Re-enabling queue management allows the resetPktDepth to be modified to
   adjust the target latency.

*******************************************************************************/

zlStatusE zl5011xCetQueueSetMode(zl5011xParamsS *zl5011xParams,
      zl5011xCetQueueSetModeS *par)
{
   zlStatusE status = ZL5011X_OK;
   Uint32T i;
   zl5011xBooleanE gotCet = ZL5011X_FALSE;

   status = ZL5011X_CHECK_POINTERS(zl5011xParams, par);

   if (status == ZL5011X_OK)
   {
      ZL5011X_TRACE(ZL5011X_CET_FN_ID,
            "zl5011xCetQueueSetMode: ctxt %d, mode %d, resetPktDepth %d",
            par->context, par->mode, par->resetPktDepth, 0, 0, 0);

      if (zl5011xCetRunning != ZL5011X_TRUE)
      {
         status = ZL5011X_NOT_RUNNING;
      }
   }

   if (status == ZL5011X_OK)
   {
      status = zl5011xContextCheckTx(zl5011xParams, par->context, ZL5011X_CHECK_CONTEXT_NUMBER);
   }

   if (status == ZL5011X_OK)
   {
      status = zl5011xGetCet(ZL5011X_FALSE);

      if (status == ZL5011X_OK)
      {
         gotCet = ZL5011X_TRUE;
      }
   }

   /* find the device in the CET table */
   if (status == ZL5011X_OK)
   {
      for (i = 0; i < ZL5011X_CET_MAX_NUMBER_DEVICES; i++)
      {
         /* Find element in the Table */
         if (zl5011xCetExtensionTable->device[i].zl5011xParams == zl5011xParams)
         {
            break;
         }
      }

      if (i == ZL5011X_CET_MAX_NUMBER_DEVICES)
      {
         ZL5011X_TRACE(ZL5011X_CET_FN_ID, "zl5011xCetQueueSetMode: Device does not exist",0,0,0,0,0,0);
         status = ZL5011X_ERROR;
      }
   }

   if (status == ZL5011X_OK)
   {
      /* record the queue mode in the CET table */
      zl5011xCetExtensionTable->device[i].queue[par->context].mode = par->mode;
      zl5011xCetExtensionTable->device[i].queue[par->context].resetPktDepth = par->resetPktDepth;

      /* Parameters may have changed so reset the queue management state machine */
      zl5011xCetExtensionTable->device[i].queue[par->context].state = ZL5011X_CET_QUEUE_STATE_INIT;
   }

   if (gotCet == ZL5011X_TRUE)
   {
      if (status == ZL5011X_OK)
      {
         status = zl5011xReleaseCet();
      }
      else
      {
         /* already have an error code, so don't overwrite it */
         (void)zl5011xReleaseCet();
      }
   }

   return(status);
}

/*****************   STATIC FUNCTION DEFINTIONS   *****************************/

/*******************************************************************************

 Function:
    zl5011xCetQueueTask

 Description:
   This task services the queues for each context on a device, and then delays
   for the required period of time, to give the service rate for the queue as
   specified during CET initialisation.

 Inputs:
   None

 Outputs:
   None

 Returns:
   This function does not return.

 Remarks:

*******************************************************************************/

void zl5011xCetQueueTask(void)
{
   Uint32T delay;
   Uint32T loop, temp;

   ZL5011X_TRACE(ZL5011X_CET_FN_ID, "zl5011xCetQueueTask:", 0,0,0,0,0,0);

   zl5011xCetExtensionTable->queueCurrDevice = 0;

   while (ZL5011X_TRUE) /* loop forever */
   {
      /* find out which is the next device to be serviced */
      if ((zl5011xCetExtensionTable->deviceCount > 1) ||
         ((zl5011xCetExtensionTable->deviceCount == 1) &&
         (zl5011xCetExtensionTable->device[zl5011xCetExtensionTable->queueCurrDevice].zl5011xParams == NULL)))
      {
         for (loop = 1; loop < ZL5011X_CET_MAX_NUMBER_DEVICES; loop++)
         {
            temp = (loop + zl5011xCetExtensionTable->queueCurrDevice) % ZL5011X_CET_MAX_NUMBER_DEVICES;

            if (zl5011xCetExtensionTable->device[temp].zl5011xParams != NULL)
            {
               /* found the next device so stop looking */
               zl5011xCetExtensionTable->queueCurrDevice = temp;
               break;
            }
         }
      }

      if (zl5011xCetExtensionTable->device[zl5011xCetExtensionTable->queueCurrDevice].zl5011xParams != NULL)
      {
         /* service the queues for the current device */
         zl5011xCetQueueHandler(zl5011xCetExtensionTable->queueCurrDevice);
      }

      /* completed processing the device, so delay for as long as required.
         The delay specified is to come back around to the beginning again, so
         need to divide the required delay by the number of devices */
      delay = zl5011xCetExtensionTable->queueManagePeriodMs;

      if (zl5011xCetExtensionTable->deviceCount > 0)
      {
         delay /= zl5011xCetExtensionTable->deviceCount;

         if (delay < ZL5011X_CET_QUEUE_MIN_PERIOD_LIMIT_MS)
         {
            /* ensure that the queues are not being serviced quicker than the
               minimum period */
            delay = ZL5011X_CET_QUEUE_MIN_PERIOD_LIMIT_MS;
         }
      }

      OS_TASK_DELAY(delay);
   }
}

/*******************************************************************************

 Function:
    zl5011xCetQueueHandler

 Description:
   Services all of the contexts for the given device, to ensure that none are
   under / over running (if queue management is enabled for the context)

 Inputs:
   index       index into the CET table for the device to service

 Outputs:
   None

 Returns:
   zlStatusE

*******************************************************************************/

void zl5011xCetQueueHandler(Uint32T index)
{
   zl5011xParamsS *zl5011xParams;
   Uint32T context, underrun, early, late, avgLength, discardedPkts, seqDiff;
   Uint32T seq;
   zl5011xCetQueueS *settings;
   zlStatusE status;

   zl5011xParams = zl5011xCetExtensionTable->device[index].zl5011xParams;

   for (context = 0; (context < zl5011xCetExtensionTable->device[index].numContexts) && (zl5011xParams != NULL); context++)
   {
      status = ZL5011X_OK;

      /* if CET queue management is enabled, then check the context */
      if (zl5011xCetExtensionTable->device[index].queue[context].mode == ZL5011X_CET_QUEUE_ENABLE)
      {
         settings = zl5011xCetExtensionTable->device[index].queue + context;

         /* if the context is in an active state then check the queue */
         if (((zl5011xParams->wanIf.tfmCurrent.context[context].state == ZL5011X_STATE_TAKEN) ||
            (zl5011xParams->wanIf.tfmCurrent.context[context].state == ZL5011X_STATE_ACTIVE) ||
            (zl5011xParams->wanIf.tfmCurrent.context[context].state == ZL5011X_STATE_UPDATING)) &&
            (zl5011xParams->wanIf.txQueue[context].queueMode != ZL5011X_WAN_TX_QUEUE_FIFO))
         {
            /* check for over / underruns on this context */
            status = zl5011xTfqGetUnderrunCount(zl5011xParams, context, &underrun);

            if (status == ZL5011X_OK)
            {
               /* read the sequence number of the packet at the head of the Wan queue */
               status = zl5011xTfqGetReadPointer(zl5011xParams, context, &seq);

               /* The sequence number is either a 24 or 32 bit value. To cope with this difference, the
                  number is shifted left by 8 bits, to make all measurements 24 bit. Any calculations
                  will be made and then the 8 bit shift reversed. */
               seq <<= 8;
            }

            if (status == ZL5011X_OK)
            {
               if ((underrun != settings->prevUnderrun) ||
                  (settings->state == ZL5011X_CET_QUEUE_STATE_INIT) ||
                  (settings->currPktAdjust != 0))
               {
                  /* read all of the relevant queue statistics for checking */
                  if (status == ZL5011X_OK)
                  {
                     status = zl5011xTfqGetLatePackets(zl5011xParams, context, &late);
                  }

                  if (status == ZL5011X_OK)
                  {
                     status = zl5011xTfqGetEarlyPackets(zl5011xParams, context, &early);
                  }

                  if (status == ZL5011X_OK)
                  {
                     status = zl5011xTfqGetAvgLength(zl5011xParams, context, &avgLength);
                  }

                  switch (settings->state)
                  {
                     case ZL5011X_CET_QUEUE_STATE_INIT:
                        if (status == ZL5011X_OK)
                        {
                           Uint32T temp;

                           settings->prevLate = late;
                           settings->prevEarly = early;
                           settings->prevUnderrun = underrun;
                           settings->prevEmpty = ZL5011X_FALSE;
                           settings->prevAdjusts = 0;

                           /* work out the maximum queue depth in packets */
                           temp = 1 << zl5011xParams->wanIf.txQueue[context].queueSize;

                           /* check if the requested packet depth following reset is valid */
                           if ((settings->resetPktDepth < temp) && (settings->resetPktDepth > 0))
                           {
                              settings->resetPktAdjust = (Sint32T)settings->resetPktDepth - ((Sint32T)temp / 2);
                           }
                           else
                           {
                              /* leave the queue at 1/2 depth following a reset */
                              settings->resetPktAdjust = 0;
                           }

                           settings->currPktAdjust = 0;
                           settings->state = ZL5011X_CET_QUEUE_STATE_RUN;
                        }
                        break;

                     case ZL5011X_CET_QUEUE_STATE_RUN:
                        if (status == ZL5011X_OK)
                        {
                           /* calculate how many packets have been received in the interval.
                              The seq number has been shifted left by 8 bits, so shift it back */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -