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

📄 csend.c

📁 Crystal Semiconductor CS8900 network interface driver.
💻 C
📖 第 1 页 / 共 5 页
字号:
    if( errorCount != 0 )
    {
#ifdef CS_DEBUG_ENABLE
        logMsg("csVerifyChip: ERROR SRAM test failed, errorCount %d\n", 
                errorCount,0,0,0,0,0 );
#endif
       return( ERROR );
    }

    return OK;
}


/*******************************************************************************
*
* csStart - start the device
*
* This function calls BSP functions to connect interrupts and start the
* device running in interrupt mode.
*
* RETURNS: OK or ERROR
*
*/

LOCAL STATUS csStart(END_OBJ *pV )
{
CS_END_DEVICE *pCS;

/* @Conexant ARM 940 specific code 
extern CS_END_DEVICE *EndObject;
*/
   pCS=(CS_END_DEVICE *)pV;


/* @Conexant ARM 940 specific code 
   EndObject = pCS;
*/
  
   
/* For @Conexant ARM 940 User: 
Comment out the following code.*/ 
   /* Setup the interrupt handler and the IDT table entry */
   if ( intConnect(INUM_TO_IVEC((ULONG)pCS->IntVector), csIntr, (int)pCS) == ERROR )
   {
#ifdef CS_DEBUG_ENABLE
      logMsg("csStart: CS_END_DEVICE %d, Can not connect intertupt\n", 
         pCS->unit,0,0,0,0,0 );
#endif
      return NULL;
   }



#ifdef CS_DEBUG_ENABLE
   logMsg("csStart: unit=%d, Initializing interface\n",
           pCS->unit, 0,0,0,0,0 );
#endif

   /* Initialize the chip */
   csInitChip( pCS );

   /* Enable CS8900 interrupts at the system level */
   if ( sysEnetIntEnable(pCS) == ERROR )
   {
#ifdef CS_DEBUG_ENABLE
      logMsg("csStart: CS_END_DEVICE %d, sysEnetIntEnable failed\n", 
              pCS->unit,0,0,0,0,0 );
#endif
      return( NULL );
   }


   /* Mark the interface as up and running */
   END_FLAGS_SET (&pCS->end, IFF_UP | IFF_RUNNING);

   return OK;
}

/*******************************************************************************
*
* csStop - stop the device
*
* This function calls BSP functions to disconnect interrupts and stop
* the device from operating in interrupt mode.
*
* RETURNS: OK or ERROR.
*/
LOCAL STATUS csStop(END_OBJ *pV)
{
CS_END_DEVICE *pCS;

   pCS=(CS_END_DEVICE *)pV;

   /* disable CS8900 interrupts at the system level */
   if ( sysEnetIntDisable(pCS) == ERROR )
   {
#ifdef CS_DEBUG_ENABLE
      logMsg("csStop: CS_END_DEVICE %d, sysEnetIntDisable failed\n", 
              pCS->unit,0,0,0,0,0 );
#endif
      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 )
   {
#ifdef CS_DEBUG_ENABLE
      logMsg("csStop: CS_END_DEVICE %d, Can not reset the chip\n",
              pCS->unit, 0,0,0,0,0 );
#endif
      return ERROR;
   }


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


   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);
#ifdef CS_DEBUG_ENABLE
   logMsg("csUnLoad(): unit=%d, CS8900 driver is unloaded!\n", 
           pCS->unit,0,0,0,0,0 );
#endif
   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) );

#ifdef CS_DEBUG_ENABLE
            logMsg("csRxMissEvent: CS_END_DEVICE %d,, %d added to RX miss counter\n",
            pCS->unit, ( (BYTE_SWAP(Event)) >> 6),0,0,0,0 );
#endif
            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);
        
#ifdef CS_DEBUG_ENABLE
            logMsg("csTxColEvent: CS_END_DEVICE %d, %d added to collision counter\n",
            pCS->unit, ( (BYTE_SWAP(Event)) >> 6),0,0,0,0 );
#endif
            break;
  
         default: 
#ifdef CS_DEBUG_ENABLE
            logMsg("csIntr: CS_END_DEVICE %d, Unknown interrupt event: %04X\n",
               pCS->unit, (BYTE_SWAP(Event)),0,0,0,0 );
#endif
            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 )

⌨️ 快捷键说明

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