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

📄 smc8xx.c

📁 这是单板上DPRAM的驱动程序
💻 C
📖 第 1 页 / 共 5 页
字号:
    /* mblk.                                                           */
    /* The mblk pointer is then used to free the mblk (return it to    */
    /* the mblk pool of free mblks.                                    */
    /*-----------------------------------------------------------------*/

    /* MUST CHANGE what happens if the ring is out of sync with */
    /* the rx_queue ? Need some check! */

    imask = splx(MAX_ILEV);
    buffer = BufListRxRemove(&chan->rx_queue);
    (void)splx(imask);

    if(SCLOSENOFREE == 0)
        (chan->freeb)(buffer);

    /*-----------------------------------------------------------------*/
    /* Update rx ring pointer, wrap if needed.                         */
    /* rxrg_bottom contains a pointer to the ring bottom. If there     */
    /* set ring to top and continue.                                   */
    /*-----------------------------------------------------------------*/
    _sync_io();
    if (ring == chan->rxrg_bottom)
        {
        ring->status = SMC_TX_WRAP;
        ring = chan->rxrg_top;
        }
    else
        {
        ring->status  = 0;
        ring++;
        }
    }
    _sync_io();

    /*
     *  update read pointer and clear unused receive descriptor counter
     */
    chan->rxrg_rd   = ring;
    chan->unused_rx = 0;
}

/***********************************************************************/
/* flush_txring:                                                       */
/*               This routine flushes the transmit descriptor ring     */
/*               by returning all buffers to the upper layer.          */
/*               The transmitter should be stopped before this         */
/*               routine is executed.                                  */
/*                                                                     */
/*      INPUTS:                                                        */
/*              chan pointer to the structure that contains channel    */
/*                   information                                       */
/*                                                                     */
/***********************************************************************/
static void
flush_txring(chan_control *chan)
{
    BuffDescType *ring;          /* pointer to tx descriptor ring */
    mblk_t       *buffer;        /* upper layer buffer to be returned */
    USHORT       status;         /* ring entry status */
    ULONG        imask;          /* slpx saved level */

/*---------------------------------------------------------------------*/
/* Get current read pointer to descriptor ring.                        */
/*---------------------------------------------------------------------*/
    ring = chan->txrg_rd;

/*---------------------------------------------------------------------*/
/* Delete everything from the transmit descriptor ring and             */
/* Call the UDataCnf for each buffer in ring.                          */
/* Go through the ring until a null buffer pointer is found.           */
/*---------------------------------------------------------------------*/
    while (ring->address != (void *)0)
        {
        status = ring->status;
        _sync_io();

    /*-----------------------------------------------------------------*/
    /* Instead of adjusting these counters once (at the end of          */
    /* the loop), we have to keep exact track of what is freed         */
    /* as the Data Link layer may provide more data to be queued       */
    /* within the Data Confirmation handler: BEWARE...                 */
    /*-----------------------------------------------------------------*/
        chan->unused_tx++;
        chan->hard_queued -= ring->length;

    /*-----------------------------------------------------------------*/
    /* Clear the Buffer Descriptor data pointer and data length.       */
    /*-----------------------------------------------------------------*/
        ring->length = 0;
        ring->address = (void *)0;

    /*-----------------------------------------------------------------*/
    /* Update tx ring pointer, wrap if needed.                         */
    /*-----------------------------------------------------------------*/
        _sync_io();
        if (ring == chan->txrg_bottom)
            {
            ring->status = SMC_TX_WRAP;
            ring = chan->txrg_top;
            }
        else
            {
            ring->status  = 0;
            ring++;
            }

    /*-----------------------------------------------------------------*/
    /* Check the Interrupt flag (TBD_INT  always set if descriptor     */
    /* is valid).                                                      */
    /*-----------------------------------------------------------------*/
      if ((status & SMC_TX_INTR) != 0)
          {
        /*-------------------------------------------------------------*/
        /* The tx_queue contains a list of actual mblk_t structures,   */
        /* it operates in parallel to the transmit ring.               */
        /* The macro BufListTxRemove will remove the first mblk_t      */
        /* structure from the transmit and return the pointer that     */
        /* mblk.                                                       */
        /* The mblk pointer is then used to in the UDataCnf call.      */
        /* The UDataCnf function status is set to SIOCABORT so the     */
        /* upper layer code will know this buffer was not transmitted. */
        /* NOTE: The upper layer is responsible for freeing the buffer.*/
        /*-------------------------------------------------------------*/
          imask = splx(MAX_ILEV);
          buffer = BufListTxRemove(&chan->tx_queue);
          (void)splx(imask);

          chan->tx_count--;
          DO_DATACNF(buffer, SIOCABORT);
          _sync_io();
          }
      }

/*---------------------------------------------------------------------*/
/* Update read pointer.                                                */
/*---------------------------------------------------------------------*/
      chan->txrg_rd = ring;
}

/***********************************************************************/
/* service_queue:                                                      */
/*                Services SMC software backup queue and keeps         */
/*                hardware queue full of data.                         */
/*                                                                     */
/*      INPUTS:                                                        */
/*              chan pointer to the structure that contains channel    */
/*                   information                                       */
/*                                                                     */
/***********************************************************************/
static void
service_queue(chan_control *chan)
{
    mblk_t       *mblk=NULL;          /* frame to be transmitted */
    ULONG        imask;          /* splx saved level */

/*---------------------------------------------------------------------*/
/* Transmit entries out of software queue until empty                  */
/*---------------------------------------------------------------------*/
    while (chan->backup_count > 0)
        {
        imask = splx(MAX_ILEV);
        mblk = BufListTxRemove(&chan->backup_queue);
        (void)splx(imask);

        if (hardware_transmit(chan, mblk) != SIOCOK)
            break;

        chan->soft_queued -= BufSize(mblk);
        chan->backup_count--;
        }

/*---------------------------------------------------------------------*/
/* Requeue the buffer we could not send (at the front of the queue)    */
/*---------------------------------------------------------------------*/
   if (chan->backup_count != 0 
        && mblk!=NULL /* added by just for restraining warning */
        )
       {
       imask = splx(MAX_ILEV);
       BufListPrepend(mblk, &chan->backup_queue);
       (void)splx(imask);
       }
}

/***********************************************************************/
/* flush_backup:                                                       */
/*               Flush software queue and return all buffers           */
/*               to their data link layer (should only be called       */
/*               when the hardware queue is empty!)                    */
/*                                                                     */
/*      INPUTS:                                                        */
/*              chan pointer to the structure that contains channel    */
/*                   information                                       */
/*                                                                     */
/***********************************************************************/
static void
flush_backup(chan_control *chan)
{
    mblk_t       *buffer;        /* pointer to buffer to cancel */
    ULONG        imask;          /* splx saved level */

    while (chan->backup_count != 0)
        {
        imask = splx(MAX_ILEV);
        buffer = BufListTxRemove(&chan->backup_queue);
        (void)splx(imask);

        chan->backup_count--;

    /*----------------------------------------------------------------*/
    /* Call the data confirmation function and tell it that this      */
    /* buffer has been aborted.                                       */
    /*----------------------------------------------------------------*/
        DO_DATACNF(buffer, SIOCABORT);
        }
/*---------------------------------------------------------------------*/
/* Nothing left on the software queue. Set the pointer to NULL.        */
/*---------------------------------------------------------------------*/
    chan->soft_queued = 0;
}

/***********************************************************************/
/* replenish_desc:                                                     */
/*                 This routine replenishes the receive descriptor     */
/*                 ring with fresh buffers.  Only the descriptors      */
/*                 that were used are replenished. Replenish stops     */
/*                 when either the ring is full or we run out of       */
/*                 buffers (up to the maximum configured).             */
/*                                                                     */
/*      INPUTS:                                                        */
/*              chan pointer to the structure that contains channel    */
/*                   information                                       */
/*                                                                     */
/***********************************************************************/
static void
replenish_desc(chan_control *chan)
{
    BuffDescType    *ring;          /* pointer to receive descriptors */
    BuffDescType    *bottom;        /* bottom of circular ring */
    mblk_t          *mblk;          /* mblk from RxPool */
    UINT            count;          /* count of descriptors ready for SMC */
    UINT            maxcount;       /* max count of desc. for SMC at any time*/
    int             bufsize;        /* individual segment size */
    ULONG           imask;          /* slpx saved level */

    maxcount = chan->MaxBuffers;

/*---------------------------------------------------------------------*/
/* Get current write pointer to receive descriptor ring                */
/*---------------------------------------------------------------------*/
    count    = chan->unused_rx;
    ring     = chan->rxrg_wr;
    bottom   = chan->rxrg_bottom;

/*---------------------------------------------------------------------*/
/* Set size of individual mblk.                                        */
/*---------------------------------------------------------------------*/
    bufsize = chan->cfg.RBuffSize;

/*---------------------------------------------------------------------*/
/* Replenish all receive descriptors with new mblocks                  */
/* and set EMPTY bit                                                   */
/*---------------------------------------------------------------------*/
    while (ring->address == (void *)0)
        {

    /*-----------------------------------------------------------------*/
    /* Get a mblock with buffer attached by using the allocation       */
    /* function pointer for the channel supplied to the smc8xx_Open    */
    /* call.                                                           */
    /*-----------------------------------------------------------------*/
        mblk = (chan->allocb)(bufsize, BPRI_HI);
        if (mblk == (mblk_t *)NULL)
            {
            chan->stats.no_mblks++;
            break;
            }

    /*-----------------------------------------------------------------*/
    /* Compensate for the allocation code not really allocating        */

⌨️ 快捷键说明

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