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

📄 csend.c

📁 VxWorks系统CS网卡END驱动(源码)
💻 C
📖 第 1 页 / 共 5 页
字号:
{
CS_END_DEVICE *pCS;

   pCS=(CS_END_DEVICE *)pV;

   /* disable CS8900 interrupts at the system level */
   if ( sysEnetIntDisable(pCS) == ERROR )
   {
      LOGMSG("csStop: CS_END_DEVICE %d, sysEnetIntDisable failed\n", 
              pCS->unit,0,0,0,0,0 );
      return( NULL );
   }

   /* set the flags to indicate NIC status */ 
   /* Mark the interface as down */
   END_FLAGS_CLR (&pCS->end, IFF_UP | IFF_RUNNING);

   /* Stop the chip */
   if ( csResetChip(pCS) == ERROR )
   {
      LOGMSG("csStop: CS_END_DEVICE %d, Can not reset the chip\n",
              pCS->unit, 0,0,0,0,0 );
      return ERROR;
   }


   LOGMSG("csStop(): unit=%d, The CS8900 device has been stopped.\n", 
            pCS->unit,0,0,0,0,0 );


   return OK;
}


/******************************************************************************
*
* csUnload - unload a driver from the system
*
* This function first brings down the device, and then frees any
* stuff that was allocated by the driver in the load function.
*
* RETURNS: OK or ERROR.
*/

LOCAL STATUS csUnload ( END_OBJ *pV        /* device to be unloaded */
    )
{
CS_END_DEVICE *pCS;

   pCS=(CS_END_DEVICE *)pV;

   END_OBJECT_UNLOAD (&pCS->end);
   LOGMSG("csUnLoad(): unit=%d, CS8900 driver is unloaded!\n", 
           pCS->unit,0,0,0,0,0 );
   return (OK);
}

/*******************************************************************************
*
* csIoctl -
*
* This routine is a major entry point and is called by the protocol stack to
* modify characteristics of this network interface driver.  
*/
LOCAL int csIoctl(     
    END_OBJ *pV,        /* device receiving command */
    int cmd,                        /* ioctl command code */
    caddr_t data                /* command argument */
    )
{
int status = 0;
long value;
CS_END_DEVICE *pCS;

   pCS=(CS_END_DEVICE *)pV;

   switch( cmd )
   {
      case EIOCSADDR:
         if (data == NULL)
            return (EINVAL);
         bcopy ((char *)data, (char *)END_HADDR(&pCS->end), 
                END_HADDR_LEN(&pCS->end));
         bcopy( (char *)data, (char *)pCS->enetAddr, 6);
         csConfig(pCS);
         break;
      case EIOCGADDR:
         if (data == NULL) return (EINVAL);
         bcopy ((char *)END_HADDR(&pCS->end), (char *)data,
                END_HADDR_LEN(&pCS->end));
         break;
      case EIOCSFLAGS: /* set Promiscuous Mode */
         value = (long)data;
         if (value < 0)
         {
            value = -(--value);
            END_FLAGS_CLR (&pCS->end, value);
         }
         else
         {
            END_FLAGS_SET (&pCS->end, value);
         }
         csConfig (pCS);
         break;
      case EIOCGFLAGS:
         *(int *)data = END_FLAGS_GET(&pCS->end);
         break;
      case EIOCMULTIADD:
         status = csMCastAdd ((void*)pCS, (char *) data);
         break;
      case EIOCMULTIDEL:
         status = csMCastDel ((void*)pCS, (char *) data);
         break;
      case EIOCMULTIGET:
         status = csMCastGet ((void*)pCS, (MULTI_TABLE *) data);
         break;
      case EIOCPOLLSTART:
         csPollStart ((void*)pCS);
         break;
      case EIOCPOLLSTOP:
         csPollStop ((void*)pCS);
         break;
      case EIOCGMIB2:
         if (data == NULL) return (EINVAL);
         bcopy((char *)&pCS->end.mib2Tbl, (char *)data,
               sizeof(pCS->end.mib2Tbl));
         break;
      case EIOCGFBUF:
         if (data == NULL)
         return (EINVAL);
         *(int *)data = CS_MIN_FBUF;
         break;
      default:
         status = EINVAL;
   }


   return (status);
}


/*******************************************************************************
*
* csSend - the driver send routine
*
* This routine takes a M_BLK_ID sends off the data in the M_BLK_ID.
* The buffer must already have the addressing information properly installed
* in it.  This is done by a higher layer.    
*
* RETURNS: OK or ERROR.
*/

LOCAL STATUS csSend ( END_OBJ  *pV,        /* device ptr */
                      M_BLK_ID pMBuff   /* data to send */
)
{    
   int         oldLevel=0;
CS_END_DEVICE *pCS;

   pCS=(CS_END_DEVICE *)pV;
   /*
    * Obtain exclusive access to transmitter.  This is necessary because
    * we might have more than one stack transmitting at once.
    */

    if (!(pCS->ConfigFlags & CFGFLG_POLL_MODE))
        END_TX_SEM_TAKE (&pCS->end, WAIT_FOREVER);

    /* This is the normal case where all the data is in one M_BLK_ID */
    /* Set pointers in local structures to point to data. */
    /* place a transmit request */

    if (!(pCS->ConfigFlags & CFGFLG_POLL_MODE))
    {
	  /*  disable interrupts*/
      oldLevel=INT_LOCK();
    }
    
    /* initiate device transmit */
    csStartOutput(pCS, pMBuff);

    if (!(pCS->ConfigFlags & CFGFLG_POLL_MODE))
    {
 	  /*  enable interrupts*/
      INT_UNLOCK(oldLevel);
    }
    
    /* Advance our management index */

    if (!(pCS->ConfigFlags & CFGFLG_POLL_MODE))
        END_TX_SEM_GIVE (&pCS->end);

    return (OK);
}


/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *
 * Interrupt-handler Routines                                              *
 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */


/*******************************************************************************
*
* csIntr -
*
* This routine in the interrupt service routine.  This routine is called by
* VxWorks wrapper code whenever the CS8900 chip generates and interrupt.  The 
* wrapper code issues an EOI command.
*
* This routine processes the events on the Interrupt Status Queue.  The events
* are read one at a time from the ISQ and the appropriate event handlers are
* called.  The ISQ is read until it is empty.  Reading a zero from the ISQ will
* deassert the interrupt request line.
*
* RETURNS: Nothing
*
*/

LOCAL void csIntr(CS_END_DEVICE *pCS)
{
   USHORT Event;

   /* Ignore any interrupts that happen while the chip is being reset */
   if( pCS->Resetting )
      return;

   /* Set locale flag */
   pCS->InISR = TRUE;
   /* Read an event from the Interrupt Status Queue */
   if( pCS->InMemoryMode )
      Event = csReadPacketPage( pCS, PKTPG_ISQ );
   else
      Event = SYS_ENET_IN_WORD( (pCS->IOAddr)+PORT_ISQ );

   /* Process all the events in the Interrupt Status Queue */
   while( Event != 0 )
   {
      /* Dispatch to an event handler based on the register number */
      switch ( Event & REG_NUM_MASK )
      {
         case REG_NUM_RX_EVENT:
            csReceiveEvent( pCS, Event );
            break;

         case REG_NUM_TX_EVENT:
            csTransmitEvent( pCS, Event );
            break;

         case REG_NUM_BUF_EVENT:
            csBufferEvent( pCS, Event );
            break;

         case REG_NUM_RX_MISS: 
            /* Read the Rx Miss count (clears the counter). */
            /* Miss count is in the 10 MSBs */
            /*pCS->ArpCom.ac_if.if_ierrors += ( (BYTE_SWAP(Event)) >> 6); */
            END_ERR_ADD (&pCS->end, MIB2_IN_ERRS,( (BYTE_SWAP(Event)) >> 6) );

            LOGMSG("csRxMissEvent: CS_END_DEVICE %d,, %d added to RX miss counter\n",
            pCS->unit, ( (BYTE_SWAP(Event)) >> 6),0,0,0,0 );
            break;

         case REG_NUM_TX_COL:  
            /* Read the collision counter (clears the counter). */           
            /* Collision count is in the 10 MSBs */
            pCS->Collisions += ( (BYTE_SWAP(Event)) >> 6);
        
            LOGMSG("csTxColEvent: CS_END_DEVICE %d, %d added to collision counter\n",
            pCS->unit, ( (BYTE_SWAP(Event)) >> 6),0,0,0,0 );
            break;
  
         default: 
            LOGMSG("csIntr: CS_END_DEVICE %d, Unknown interrupt event: %04X\n",
               pCS->unit, (BYTE_SWAP(Event)),0,0,0,0 );
            break;
      }

      /* Read another event from the Interrupt Status Queue */
      if ( pCS->InMemoryMode )
         Event = csReadPacketPage( pCS, PKTPG_ISQ );
      else
         Event = SYS_ENET_IN_WORD( (pCS->IOAddr)+PORT_ISQ );
   }
   
   /* Ensure task-level event handler is running */
   if( pCS->NetJobDepth < 2 )
   {
      pCS->NetJobDepth++;
      netJobAdd( (FUNCPTR)csEventHandler, (int)pCS, 0, 0, 0, 0 ); 
   }

   /* Clear locale flag */
   pCS->InISR = FALSE;
}


/*******************************************************************************
*
* csBufferEvent -
*
* The routine is called whenever an event occurs regarding the transmit and
* receive buffers within the CS8900 chip.  The only buffer events we 
* currently handle are Rdy4TX interrupts, Tx Underruns, and SW ints.
*
*/

LOCAL void csBufferEvent( CS_END_DEVICE *pCS, USHORT BufEvent )
{
USHORT BusStatus;

   if ( BufEvent & BUF_EVENT_TX_UNDR )
   {

      /* TX underrun occured */
      pCS->TxUnderruns++;

      /* Modify start command if total underruns > threshold value */
      /* by setting TX start command to next increment */
      if( pCS->TxUnderruns == CS_TX_UNDRUN_TRHSHOLD )
      {
          /* Reset the threshold counter */
          pCS->TxUnderruns = 0;
          
          /* Select the next TxStartCommand */ 
          if( pCS->TxStartCMD == TX_CMD_START_5 )
             pCS->TxStartCMD = TX_CMD_START_381;

          else if( pCS->TxStartCMD == TX_CMD_START_381 )
             pCS->TxStartCMD = TX_CMD_START_1021;

          else pCS->TxStartCMD = TX_CMD_START_ALL;
      }
       
      /* Try to TX the frame again */
      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 )
      {
            /* On-chip buffer space available -- start transmission */
             csCopyTxFrame( pCS, pCS->pTxFrameChain );
      }

      LOGMSG("csBufferEvent: CS_END_DEVICE %d, Transmit underrun\n",
         pCS->unit, 0,0,0,0,0 );

      pCS->TotalTxUnderruns++;
   }


   else if ( BufEvent & BUF_EVENT_RDY4TX )
   {
      (pCS->Rdy4TxInts) += 1;

      /* The chip is ready for transmission now */

      /* If a TX is pending, copy the frame to the chip to start transmission */
      if( pCS->pTxFrameChain != NULL )
      {
         csCopyTxFrame( pCS, pCS->pTxFrameChain );
      }
   }


   else if ( BufEvent & BUF_EVENT_SW_INT )
   {
      LOGMSG("csBufferEvent: CS_END_DEVICE %d, Software initiated interrupt\n",
         pCS->unit, 0,0,0,0,0 );
   }
}




/*******************************************************************************
*
* csTransmitEvent -
*
* This routine is called whenever the transmission of a packet has completed
* successfully or unsuccessfully.  If the transmission was not successful,
* then the output error count is incremented.  If there are more packets in the
* transmit queue, then the next packet is started immediately.
*
*/

LOCAL void csTransmitEvent( CS_END_DEVICE *pCS, USHORT TxEvent )
{
   /* WE only get here if the transmit in progress has completed, either 
    * successfully or due to an error condition.  In any event, queue the 
    * mbuf chain for freeing at task level and NULL the frame pointer to mark
    * the TX no longer in progress.
    */

   csEnqueue( pCS->pTxBuffFreeList, pCS->pTxFrameChain );
   pCS->pTxFrameChain = NULL;
   pCS->TxInProgress = FALSE;   

   /* If there were any errors transmitting this frame */
   if ( TxEvent & (TX_EVENT_LOSS_CRS | TX_EVENT_SQE_ERR | TX_EVENT_OUT_WIN |
            TX_EVENT_JABBER | TX_EVENT_16_COLL) )
   {
      /* Increment the output error count */
    /* @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."*/
      END_ERR_ADD (&pCS->end, MIB2_OUT_ERRS, +1);

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

⌨️ 快捷键说明

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