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

📄 smc8xx.c

📁 这是单板上DPRAM的驱动程序
💻 C
📖 第 1 页 / 共 5 页
字号:

/*---------------------------------------------------------------------*/
/* Update the status of the frame: may set a new (error) bit.          */
/* NOTE: This is a accumulate error from each buffer processed.        */
/*---------------------------------------------------------------------*/
   rxstatus |= status & ~( SMC_RX_WRAP | SMC_RX_EMPTY | SMC_RX_INTR );

/*---------------------------------------------------------------------*/
/* Check rxstatus of frame                                             */
/*---------------------------------------------------------------------*/
   if (rxstatus != 0)
      {
      if (rxstatus & SMC_RX_IDLE)
         *frameFlag |= SIOCMARK;

      if (rxstatus & SMC_RX_BRKRCV)
         *frameFlag |= SIOCBREAKR;

      if (rxstatus & SMC_RX_FRMERR)
         *frameFlag |= SIOCFRAMING;

      if (rxstatus & SMC_RX_PARITY)
         *frameFlag |= SIOCPARITY;

      if (rxstatus & SMC_RX_OVERRUN)
         *frameFlag |= SIOCOVERRUN;

      if ((rxstatus & SMC_RX_CDLOST) &&
         (chan->cfg.Cfg.Uart.Flags & SWDCD) == 0)
         *frameFlag |= SIOCCDLOST;
      }
    _sync_io();
    BufAdjust(frame, BufSize(frame) - length);
/*
 * Increment receive frame statistics (both frame counts and bytes).
 */
   ++chan->stats.receive_Aframes;
   chan->stats.receive_bytes += length;

   return(frame);
}

/***********************************************************************/
/* frame_transmit:                                                     */
/*              Transmit Frame.  Check priority parameter and          */
/*              place on either hardware queue or backup queue.        */
/*                                                                     */
/*      INPUTS:                                                        */
/*              chan pointer to the structure that contains channel    */
/*                   information                                       */
/*                                                                     */
/*     RETURNS: error code                                             */
/*                                                                     */
/***********************************************************************/
static int
frame_transmit(chan_control  *chan, mblk_t *frame, UINT priority)
{
   ULONG        imask;      /* slpx saved level */

/*---------------------------------------------------------------------*/
/* Transmit the frame immediately if it has priority or if             */
/* nothing is in the soft queue.                                       */
/*---------------------------------------------------------------------*/
   if (priority || (chan->soft_queued == 0))
      {
      if (hardware_transmit(chan, frame) == SIOCOK)
         return(SIOCOK);

   /*-----------------------------------------------------------------*/
   /* If hardware transmit fails (lack of ring descriptors),          */
   /* queue in backup queue.                                          */
   /*-----------------------------------------------------------------*/
      }

/*---------------------------------------------------------------------*/
/* Check space on backup queue and return error if there is            */
/* no room (logically).                                                */
/*---------------------------------------------------------------------*/
   if ((chan->tx_count + chan->backup_count) > chan->credit)
      {
      chan->stats.xmit_queue_full++;
      return(SIOCOQFULL);
      }

/*---------------------------------------------------------------------*/
/* queue on soft que                                                   */
/*---------------------------------------------------------------------*/
   imask = splx(MAX_ILEV);
   BufListAppend(frame, &chan->backup_queue);
   (void)splx(imask);

   chan->backup_count++;
   chan->soft_queued += BufSize(frame);

   return (SIOCOK);
}

/***********************************************************************/
/* hardware_transmit                                                   */
/*              Transmit a frame.  Check for sufficient open           */
/*              descriptors. Transfer the pointers and lengths         */
/*              to the ring descriptors. Initiate a transmit immediate */
/*              command to SMC if it was idle.                         */
/*                                                                     */
/*      INPUTS:                                                        */
/*              chan pointer to the structure that contains channel    */
/*                   information                                       */
/*              frame mblock to transmit                               */
/*                                                                     */
/*     RETURNS:                                                        */
/*              SIOCOQFULL if transmit descriptors are all used        */
/*              SIOCOK on success                                      */
/*                                                                     */
/***********************************************************************/
static int
hardware_transmit(chan_control *chan, mblk_t *frame)
{
   BuffDescType *ring;          /* transmit descriptor ring pointer */
   BuffDescType *last;          /* last descriptor ring pointer */
   UINT         entries;        /* number of segments in a frame */
   UINT         length;         /* total length of frame */
   mblk_t       *segment;       /* intermediate segment making up a frame */
   ULONG        imask;          /* splx saved level */

/*---------------------------------------------------------------------*/
/* Count how many segments make up one frame.                          */
/*---------------------------------------------------------------------*/
   for (segment = frame, entries = 0;
      segment != (mblk_t *)NULL;
      segment = BufSegNext(segment))
      {
      entries++;
      }

/*---------------------------------------------------------------------*/
/* Check unused transmit descriptor space and transmit queue           */
/* full condition, also report an exception.                           */
/*---------------------------------------------------------------------*/
   if (entries > chan->unused_tx)
      {
      chan->stats.xmit_hwqueue_full++;
      return(SIOCOQFULL);
      }

   length = BufSize(frame);

/*---------------------------------------------------------------------*/
/* Queue the buffer descriptor in the logical tx queue.                */
/*---------------------------------------------------------------------*/
   imask = splx(MAX_ILEV);
   _sync_io();
   BufListAppend(frame, &chan->tx_queue);
   (void)splx(imask);

   chan->tx_count++;

/*---------------------------------------------------------------------*/
/* Transfer buffer addresses to SMC descriptor ring                    */
/*---------------------------------------------------------------------*/
   ring = chan->txrg_wr;            /* get first descriptor address */
   segment = frame;                /* start from beginning of frame */

/*---------------------------------------------------------------------*/
/* Queue all mblocks that make up the frame                            */
/*---------------------------------------------------------------------*/
   while (segment != (mblk_t *)NULL)
      {
      _sync_io();
      ring->address = (void *)BufSegAddr(segment);
      ring->length = BufSegSize(segment);

#if (BRD_DCACHE == YES) && (BRD_DCACHE_WRITE_THRU == NO)
     SysDcacheFlush(ring->address, ring->length);
#endif

    /*-----------------------------------------------------------------*/
    /* Wrap descriptor pointer if bottom of ring.                      */
    /* NOTE: don't set status here they need to be set when the hole    */
    /* frame is ready to go.                                           */
    /*-----------------------------------------------------------------*/
      if (ring++ == chan->txrg_bottom)
           ring = chan->txrg_top;

      segment = BufSegNext(segment);
      }

   last = ring;    /* actually: one past the last entry */

/*---------------------------------------------------------------------*/
/* Update transmit descriptor head pointer, unused descriptor          */
/* counter, and transmit descriptor used statistics                    */
/*---------------------------------------------------------------------*/
   chan->txrg_wr = ring;
   chan->unused_tx -= entries;

/*---------------------------------------------------------------------*/
/* Fill descriptor status (starting from the last one, so that all      */
/* the READY bits are set orderly). Note that the WRAP bit is          */
/* already set in the bottom ring entry.                               */
/*---------------------------------------------------------------------*/
   if (last-- == chan->txrg_top)
      last = chan->txrg_bottom;

   last->status |= (SMC_TX_READY | SMC_TX_INTR );

/*---------------------------------------------------------------------*/
/* Set READY bit for intermediate (and first) descriptors in chain     */
/* One entry (the last) has already been taken into account.           */
/*---------------------------------------------------------------------*/
   while (--entries != 0)
      {
      _sync_io();
      if (last-- == chan->txrg_top)
         last = chan->txrg_bottom;

      last->status |= SMC_TX_READY;
      }

/*---------------------------------------------------------------------*/
/* Update frame transmit statistics and return:                        */
/*---------------------------------------------------------------------*/
   ++chan->stats.transmit_frames;
   chan->stats.transmit_bytes += length;
   chan->hard_queued += length;

   return(SIOCOK);
}

/***********************************************************************/
/* buffer_done:                                                        */
/*              Checks transmit descriptor ring for buffers finished   */
/*              transmitting and return them to the data link layer    */
/*              with their completion status.                          */
/*                                                                     */
/*      INPUTS:                                                        */
/*              chan pointer to the structure that contains channel    */
/*                   information                                       */
/*                                                                     */
/***********************************************************************/
static void
buffer_done(chan_control *chan)
{
   BuffDescType *ring;          /* transmit descriptor ring pointer */
   mblk_t       *mblk;          /* data link layer buffer */
   USHORT       txstatus;       /* txstatus of a transmitted frame */
   USHORT       status;         /* status of current Rx BD */
   ULONG        frameFlag;      /* frame transmission status */
   ULONG        imask;          /* splx saved level */

/*---------------------------------------------------------------------*/
/* Initialize transmit ring pointer: restart from where we left off    */
/*---------------------------------------------------------------------*/
   ring = chan->txrg_rd;

/*---------------------------------------------------------------------*/
/* Let's assume the frame was sent OK                                  */
/*---------------------------------------------------------------------*/
/*    txstatus    = 0;  , ---deleted by szg , not used */
   frameFlag = 0;

/*---------------------------------------------------------------------*/
/* Look for descriptors that contain meaningful data (i.e not NULL)    */
/* and poll their READY bit. Return the buffer (found in the parallel  */
/* transmit queue) when transmit is done and the ring descriptor entry */
/* is located at the end of frame. Otherwise just return...            */
/*---------------------------------------------------------------------*/
   while (ring->address != (void *)0)
      {
      status  = ring->status;

      _sync_io();
      if ( !(status & SMC_TX_READY) )
         {
      /*-------------------------------------------------------------*/
      /* Clear descriptor entry, increment unused count.             */
      /*-------------------------------------------------------------*/
         if (++chan->unused_tx == chan->MaxBuffers)
            chan->hard_queued = 0;
         else
            chan->hard_queued -= ring->length;

⌨️ 快捷键说明

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