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

📄 csend.c

📁 VxWorks系统CS网卡END驱动(源码)
💻 C
📖 第 1 页 / 共 5 页
字号:
         if ( TxEvent & TX_EVENT_LOSS_CRS )
         {
            LOGMSG("csTransmitEvent: CS_END_DEVICE %d, Loss of carrier\n",
               pCS->unit, 0,0,0,0,0 );
         }
         if ( TxEvent & TX_EVENT_SQE_ERR )
         {
            LOGMSG("csTransmitEvent: CS_END_DEVICE %d, SQE error\n",
               pCS->unit, 0,0,0,0,0 );
         }
         if ( TxEvent & TX_EVENT_OUT_WIN )
         {
            LOGMSG("csTransmitEvent: CS_END_DEVICE %d, Out-of-window collision\n",
               pCS->unit, 0,0,0,0,0 );
         }
         if ( TxEvent & TX_EVENT_JABBER )
         {
            LOGMSG("csTransmitEvent: CS_END_DEVICE %d, Jabber\n",
               pCS->unit, 0,0,0,0,0 );
         }
         if ( TxEvent & TX_EVENT_16_COLL )
         {
            LOGMSG("csTransmitEvent: CS_END_DEVICE %d, 16 collisions\n",
               pCS->unit, 0,0,0,0,0 );
         }
#endif

    }

   /* Previous TX complete so start the next TX now if more to transmit */
   csTxNextFrame( pCS );

}




/*******************************************************************************
*
* csReceiveEvent -
*
* This routine is called whenever a packet is received at the chip.  If the
* packet is received with errors, then the input error count is incremented.
* If the packet is received OK, then the data is copied to an internal receive
* buffer and processed at task level (in csEventHandler). 
*
* RETURNS: Nothing
*/

LOCAL void csReceiveEvent( CS_END_DEVICE *pCS, USHORT RxEvent )
{
   M_BLK_ID         pMblk;
   CL_BLK_ID        pClBlk;
   char *pData;
   int DataLen;

 
  /* If the frame was not received OK */
   if ( !(RxEvent & RX_EVENT_RX_OK) )
   {

      /* Increment the input error count */
      /*pIf->if_ierrors++;*/
      END_ERR_ADD (&pCS->end, MIB2_IN_ERRS, +1);

      /* If debugging is enabled then log error messages */
#ifdef  CS_DEBUG_ENABLE

         /* If an error bit is set */
         if ( RxEvent != REG_NUM_RX_EVENT )
         {
            if ( RxEvent & RX_EVENT_RUNT )
            {
              LOGMSG("csReceiveEvent: CS_END_DEVICE %d, Runt\n",
                 pCS->unit, 0,0,0,0,0 );
            }
            if ( RxEvent & RX_EVENT_X_DATA )
            {
              LOGMSG("csReceiveEvent: CS_END_DEVICE %d, Extra data\n",
                 pCS->unit, 0,0,0,0,0 );
            }
            if ( RxEvent & RX_EVENT_CRC_ERR )
            {
               if ( RxEvent & RX_EVENT_DRIBBLE )
               {
                  LOGMSG("csReceiveEvent: CS_END_DEVICE %d, Alignment error\n",
                     pCS->unit, 0,0,0,0,0 );
               }
               else
               {
                  LOGMSG("csReceiveEvent: CS_END_DEVICE %d, CRC Error\n",
                     pCS->unit, 0,0,0,0,0 );
               }
            }
            else if ( RxEvent & RX_EVENT_DRIBBLE )
            {
               LOGMSG("csReceiveEvent: CS_END_DEVICE %d, Dribble bits\n",
                  pCS->unit, 0,0,0,0,0 );
            }
         }
#endif
      

      /* Skip this error frame */
      csReadPacketPage( pCS, PKTPG_RX_LENGTH );
      csWritePacketPage( pCS, PKTPG_RX_CFG,
                         csReadPacketPage(pCS,PKTPG_RX_CFG) | RX_CFG_SKIP );

      return;
   }

   /* Get a receive frame buffer */
     pData = netClusterGet(pCS->end.pNetPool, pCS->pClPoolId);

    /* Grab a cluster block to marry to the cluster we received. */

    pClBlk = netClBlkGet (pCS->end.pNetPool, M_DONTWAIT);

           
    /*
     * OK we've got a spare, let's get an M_BLK_ID and marry it to the
     * one in the ring.
     */

    pMblk = mBlkGet (pCS->end.pNetPool, M_DONTWAIT, MT_DATA);
 
   if ( pData == NULL || pClBlk == NULL || pMblk == NULL)  /* If no buffer available */
   {
           if (pData) {
        netClFree (pCS->end.pNetPool, pData);
       }

                if (pClBlk) {
        netClBlkFree (pCS->end.pNetPool, pClBlk); 
        }

        if ( pMblk ) {
        netMblkFree (pCS->end.pNetPool, pMblk);
                }

      /* Increment the input error count */
      /*pIf->if_ierrors++;*/
      END_ERR_ADD (&pCS->end, MIB2_IN_ERRS, +1);
 
      LOGMSG("csReceiveEvent(): unit=%d, No receive buffer available!\n",
         pCS->unit, 0,0,0,0,0 );


      /* Must read the length of all received frames */
      csReadPacketPage( pCS, PKTPG_RX_LENGTH );

      /* Skip the received frame */
      csWritePacketPage( pCS, PKTPG_RX_CFG,
            csReadPacketPage(pCS,PKTPG_RX_CFG) | RX_CFG_SKIP );
      return;
   }


   /* Copy the received frame from the chip to the buffer */
   /* Set offset 2 to the receiving buffer pointer so that the IP heater starts the
      17th bytes for 32-bits alignment*/
   DataLen=csCopyRxFrame( pCS, pData+2);

    /* Join the cluster to the MBlock */

    netClBlkJoin (pClBlk, pData, DataLen, NULL, 0, 0, 0);
    netMblkClJoin (pMblk, pClBlk);

   /* Set offset 2 to the receiving buffer pointer so that the IP heater starts the
      17th bytes for 32-bits alignment*/
    /*pMblk->mBlkHdr.mData += pDrvCtrl->offset;*/
    pMblk->mBlkHdr.mData += 2;
    pMblk->mBlkHdr.mLen = DataLen;
    pMblk->mBlkHdr.mFlags |= M_PKTHDR;
    pMblk->mBlkPktHdr.len = DataLen;

   /* Queue a pointer to the buffer to be processed at task level */
   csEnqueue( pCS->pRxBuffProcessList, pMblk );
}



/*******************************************************************************
* csEventHandler -
*
* This routine runs at the task level to processes RX frames and frees TX'd 
* mbuf chains queued at the ISR level.  Up to two instances of this
* routine may be queued to tNetTask to prevent a race condition between final
* checking of a queue here and an enqueue at the ISR level.  A netJob
* "counter" is decremented each time this routine starts.
*
* RETURNS: Nothing.
*
*/

LOCAL void csEventHandler( CS_END_DEVICE *pCS )
{
   void  *pBuff;

   if( pCS->NetJobDepth > 0 ) 
       pCS->NetJobDepth--;
      
   while( !csQueueEmpty( pCS->pRxBuffProcessList ) )
   {
      /* Process an RX frame */  
      pBuff = csDequeue( pCS->pRxBuffProcessList );
      csProcessReceive( pCS, pBuff ); 
   }

   while( !csQueueEmpty( pCS->pTxBuffFreeList ) )
   {
      /* Free up the TX'd mbuf chains */
      pBuff = csDequeue( pCS->pTxBuffFreeList );    
      netMblkClChainFree (pBuff);
   }
}






/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *
 * Transmit-releated Routines                                              *
 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */



/*******************************************************************************
*
* csStartOutput -
*
* This routine is called to start the transmission of the packet at the head
* of the transmit queue.  This routine is called by the ether_output() routine
* when a new packet is added to the transmit queue. 
*
* RETURNS: Nothing
*
*/

LOCAL void csStartOutput( CS_END_DEVICE *pCS,  M_BLK_ID pMBuf)
{
   BOOL  QError;

   END_TX_SEM_TAKE(&pCS->end, WAIT_FOREVER);
   QError = csEnqueue( pCS->pTxQueue, pMBuf );
   END_TX_SEM_GIVE(&pCS->end);
     
   if ( QError )
   {
      /* TxQueue is full -- dump the frame and exit loop */             
      netMblkClChainFree (pMBuf);
      /* Update output stats */
      END_ERR_ADD (&pCS->end, MIB2_OUT_ERRS, +1);
      LOGMSG("csStartOutput: CS_END_DEVICE %d, Transmit queue overflow\n",
              pCS->unit, 0,0,0,0,0 );
   }

#ifdef CS_DEBUG_ENABLE
   pCS->TxQueueDepth++;
   if ( pCS->TxQueueDepth > pCS->MaxTxQueueDepth )
             pCS->MaxTxQueueDepth = pCS->TxQueueDepth;
#endif

   /* Update output stats */
   END_ERR_ADD (&pCS->end, MIB2_OUT_UCAST, +1);

   /* Transmit another frame if a TX is not currently in progress */
   if ( !pCS->TxInProgress ) 
   {
      csTxNextFrame( pCS );
   }
}



/*******************************************************************************
* csTxNextFrame -
*
* This routine start the TX of the next frame in the local TX send queue.
* If an error occurs, the output error count is incremented and the mbuf chain
* is freed, either by immediately calling mfree_m() if we are at task level, 
* or queueing the mbuf chain for release at the task level if we are currently
* at the ISR level.
*
* RETURNS: Nothing
*
*/

LOCAL void csTxNextFrame ( CS_END_DEVICE *pCS )
{
USHORT BusStatus;
M_BLK_ID  pMbuf;

   /* Transmit the next frame in the local TxQueue */
   while( !csQueueEmpty( pCS->pTxQueue ) )
   {
#ifdef CS_DEBUG_ENABLE
      pCS->TxQueueDepth--;
#endif

      pCS->pTxFrameChain = csDequeue( pCS->pTxQueue );
         
      /* Find the total length of the data to transmit */
      pCS->TxLength = 0;
      for ( pMbuf = pCS->pTxFrameChain; pMbuf!=NULL; pMbuf=pMbuf->mBlkHdr.mNext )
      {
         pCS->TxLength += pMbuf->mBlkHdr.mLen;
      }

      /* Bid for space on the chip and start the TX if bid successful */
      if ( pCS->InMemoryMode )
      {
             csWritePacketPage( pCS, PKTPG_TX_CMD, pCS->TxStartCMD );
             csWritePacketPage( pCS, PKTPG_TX_LENGTH, BYTE_SWAP(pCS->TxLength) );
      }
      else  /* In IO mode */
      {
             SYS_ENET_OUT_WORD( (pCS->IOAddr)+PORT_TX_CMD, pCS->TxStartCMD );
             SYS_ENET_OUT_WORD( (pCS->IOAddr)+PORT_TX_LENGTH, 
                                 BYTE_SWAP(pCS->TxLength));
      }

      /* Read BusStatus register which indicates success of the request */
      BusStatus = csReadPacketPage( pCS, PKTPG_BUS_ST );

      if ( BusStatus & BUS_ST_RDY4TXNOW )
      {
         /* The chip is ready for transmission now */
         /* Copy the frame to the chip to start transmission */
         csCopyTxFrame( pCS, pCS->pTxFrameChain );

         /* Mark TX as in progress */
         pCS->TxInProgress = TRUE;
         /* Transmission now in progress */
         break;
      }
      else /* Not ready for TX */
      {

         /* If there was an error in the transmit bid */
         if ( BusStatus & BUS_ST_TX_BID_ERR )
         {
            /* Set TX not in progress */
            pMbuf = pCS->pTxFrameChain;
            pCS->pTxFrameChain = NULL;
            pCS->TxInProgress = FALSE;

            if ( !pCS->InISR )
            {
               /* Free the bad mbuf chain */      
               netMblkClChainFree (pMbuf);
            }
            else
            {
               /* queue the mbuf chain to be freed at task level */
               csEnqueue( pCS->pTxBuffFreeList, pMbuf );
            }

            /* Update output stats */
            END_ERR_ADD (&pCS->end, MIB2_OUT_ERRS, +1);
            /*   END_ERR_ADD (&pCS->end, MIB2_OUT_UCAST, -1);*/
            /* @kml         The definition of the MIB-II variable ifOutUcastPkts in Interface
               group from RFC 1158 is "The total  number of  packets that higher-level 
               protocols requested be transmitted to a subnetwork-unicast address, 
               INCLUDE those that were discarded or not sent."*/
            LOGMSG("csStartOutput: CS_END_DEVICE %d, Transmit bid error (too big)\n",
                       pCS->unit, 0,0,0,0,0 );

            /* Loop up to transmit the next chain */

         }
         else /* Not Rdy4Tx and Not Bid Error */
         {


            /* Start the TX on Rdy4Tx interrupt */
            /* TX buff space not available now. */

            /* Mark TX as in progress */
            pCS->TxInProgress = TRUE;

            /* Exit loop */
            break;
         }
      }
   }
}



/*******************************************************************************
*
* csCopyTxFrame -
*
* This routine copies the packet from a chain of mbufs to the chip.  When all
* the data has been copied, then the chip automatically begins transmitting
* the data.
*
* The reason why this "simple" copy routine is so long and complicated is
* because all reads and writes to the chip must be done as 16-bit words.
* If an mbuf has an odd number of bytes, then the last byte must be saved
* and combined with the first byte of the next mbuf.  Also, some processors,
* such as the MIPS do not allow word writes to non-word aligned addresses.
*
*/

LOCAL void csCopyTxFrame( CS_END_DEVICE *pCS, M_BLK_ID pMbufChain )
{
   M_BLK_ID pMbuf;
   FAST USHORT *pFrame;
   FAST USHORT *pBuff;
   FAST USHORT *pBuffLimit;
   IOADDR TxDataPort;
   UCHAR  *pStart;
   USHORT  Length;
   BOOL HaveExtraByte;
   union
   {
      UCHAR  byte[2];
      USHORT word;
   } Straddle;

⌨️ 快捷键说明

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