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

📄 if_cs.c

📁 CS8900A网络芯片驱动
💻 C
📖 第 1 页 / 共 5 页
字号:



/*******************************************************************************
*
* csInitRxBuff -
*
* This routine initializes the network interface driver's collection of
* receive buffers.  The receive buffers are allocated from system memory
* and linked together in a linked list of free receive buffers.
*
*/

LOCAL STATUS csInitRxBuff( CS_SOFTC *pCS )
{
   PRXBUF pRxBuff;
   PRXBUF pRxLast;

   /* Allocate the receive frame buffers */
   pCS->pFreeRxBuff = (PRXBUF)malloc( sizeof(RXBUF)*CS_NUM_RX_BUFFERS );
   if ( pCS->pFreeRxBuff == NULL ) 
   {
     return ERROR;
   }

   /* Link all the receive frame buffers together on the free list */
   pRxLast = pCS->pFreeRxBuff + CS_NUM_RX_BUFFERS - 1;
   for ( pRxBuff=pCS->pFreeRxBuff; pRxBuff<pRxLast; pRxBuff++ )
   {
      pRxBuff->pNext  = pRxBuff+1;
      pRxBuff->Status = RXBUF_FREE;
   }
   pRxLast->pNext  = NULL;
   pRxLast->Status = RXBUF_FREE;

   return OK;
}



/*******************************************************************************
*
* csAllocRxBuff -
*
* This routine removes a receive buffer from the free receive buffer list.
*
*/

LOCAL PRXBUF csAllocRxBuff( CS_SOFTC *pCS )
{
   PRXBUF pRxBuff;

   if ( pCS->pFreeRxBuff == NULL ) 
   {
     return NULL;
   }

   /* Remove a buffer from the free list */
   pRxBuff = pCS->pFreeRxBuff;
   pCS->pFreeRxBuff = pRxBuff->pNext;
   pRxBuff->pNext = NULL;

   /* Init the reference count to zero */
   pRxBuff->RefCount = 0;

   /* The buffer is now allocated */
   pRxBuff->Status = RXBUF_ALLOCATED;

   /* Increment number of receive buffers currently in use */
   pCS->RxDepth++;
   if ( pCS->RxDepth > pCS->MaxRxDepth )
   {
      pCS->MaxRxDepth = pCS->RxDepth;
   }

   return pRxBuff;
}



/*******************************************************************************
*
* csFreeRxBuff -
*
* This routine returns an allocated receive buffer back to the free list.
*
*/

LOCAL void csFreeRxBuff( CS_SOFTC *pCS, PRXBUF pRxBuff )
{
   int IntState;

   /* Disable interrupts at the CPU so csAllocRxBuff() will not interrupt */
   IntState = intLock();

   /* Put the buffer at the head of the free list */
   pRxBuff->pNext = pCS->pFreeRxBuff;
   pCS->pFreeRxBuff = pRxBuff;

   /* The buffer is now free */
   pRxBuff->Status = RXBUF_FREE;

   /* Decrement the outstanding receive depth */
   pCS->RxDepth--;

   /* Re-enable interrupts at the CPU */
   intUnlock( IntState );

}




/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *
 * Misc. Routines                                                          *
 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */



/*******************************************************************************
* csInitQueue -
*
* Initializes an array-implemented circular queue.
*
* RETURNS: Nothing.
*
*/
LOCAL void csInitQueue( CIR_QUEUE *Q )
{
   Q->Head = Q->Tail = 0;
}



/*******************************************************************************
* csQueueEmpty -
*
* Checks the queue's status.
*
* RETURNS: TRUE if queue is empty, FALSE if queue is not empty.
*
*/

LOCAL BOOL csQueueEmpty( CIR_QUEUE *Q )
{
   if( Q->Head == Q->Tail )
      return TRUE;  /* Queue is empty */
   else
      return FALSE;
}




/*******************************************************************************
* csDequeue -
*
* This routine removes a pointer to a value from the end off an 
* array-implemented circular queue.  Assumes the queue is not empty.
*
* RETURNS: Pointer to the dequeued value.
*
*/
LOCAL void *csDequeue( CIR_QUEUE *Q )
{
   FAST void  *Element;

   Element = Q->Queue[Q->Head];
   Q->Head = (Q->Head == CS_MAX_QUEUE) ? 0 : (Q->Head + 1);
   return Element;

}



/*******************************************************************************
* csEnqueue -
*
* This routine adds a pointer to a value to the front of an array-implmented
* circular queue.
*
* RETURNS: OK, or ERROR if the enqueue would cause a queue overflow.
*
*/
LOCAL STATUS csEnqueue( CIR_QUEUE *Q, void *pBuff )
{
   /* If queue is full return ERROR */
   if ( Q->Tail == ((Q->Head == 0) ? CS_MAX_QUEUE : (Q->Head -1)) )
   {
      LOGMSG("csEnqueue: unit %d, Queue Overflow\n",
         0,0,0,0,0,0 );
      return ERROR;    /* Queue overflow */
   }

   /* Else, add data to the queue and return OK */
   Q->Queue[Q->Tail] = pBuff;
   Q->Tail = (Q->Tail == CS_MAX_QUEUE) ? 0 : (Q->Tail + 1);

   return OK;
}



/*******************************************************************************
*
* csVerifyChip -
*
* This routine verifies that the Ethernet chip is present and correct.
*
*/

LOCAL STATUS csVerifyChip( CS_SOFTC *pCS )
{
   USHORT wrVal, rdVal;
   USHORT errorCount = 0;
   USHORT x;

   /* Verify that we can read from the chip */
   x = csReadPacketPage( pCS, PKTPG_EISA_NUM );
   if ( x == 0xFFFF )
   {
      LOGMSG("csInit: unit %d, can't read from chip (I/O address correct?)\n",
         pCS->ArpCom.ac_if.if_unit, 0,0,0,0,0 );
      return ERROR;
   }

   /* Verify that the chip is a Crystal Semiconductor chip */
   if ( x != EISA_NUM_CRYSTAL )
   {
      LOGMSG("csInit: unit %d, Chip is not a Crystal Semiconductor chip\n",
         pCS->ArpCom.ac_if.if_unit, 0,0,0,0,0 );
      return ERROR;
   }

   /* Verify that the chip is a CS8900 */
   x = csReadPacketPage(pCS,PKTPG_PRODUCT_ID);
   x &= PROD_ID_MASK;
   if ( x != PROD_ID_CS8900)
   {
      LOGMSG("csInit: unit %d, Chip is not a CS8900p\n",
         pCS->ArpCom.ac_if.if_unit, 0,0,0,0,0 );
      return ERROR;
   }

    /* walk a one in the memory of the enet controller */
    for( wrVal = 0x0001; wrVal != 0; wrVal <<= 1 )
    {
 
      for( x=0x150; x<= 0x15d; x+=2 )
      {
        /* write out value - don't swap bytes */
        csWritePacketPage( pCS, x, wrVal );
   
        /* read back value - don't swap bytes */
        rdVal = csReadPacketPage( pCS, x );
  
        if( wrVal != rdVal )
        {
          if( errorCount <=10 )
          {
            LOGMSG("csVerifyChip:  ERROR reg %04X, wrVal %04X, rdVal %04X\n",
              x, 
              (unsigned int) BYTE_SWAP(wrVal), 
              (unsigned int) BYTE_SWAP(rdVal),0,0,0 );
          }
          errorCount++;
        }
      }
    } /* end walking one test */

    /* write incrementing value test */
    for( x=0x150, wrVal=0x0101; x<= 0x15d; x+=2, wrVal+=0x0101 )
    {
      /* write out value - don't worry about swapping bytes */
      csWritePacketPage( pCS, x, wrVal );
    } 

    /* read incrementing value test */
    for( x=0x150, wrVal=0x0101; x<= 0x15d; x+=2, wrVal+=0x0101 )
    {
      /* read back value - don't worry about swapping bytes */
      rdVal = csReadPacketPage( pCS, x );
 
      if( wrVal != rdVal )
      {
        LOGMSG("\ncsVerifyChip:  ERROR reg %04X, wrVal %04X, rdVal %04X\n",
              x, 
              (unsigned int) BYTE_SWAP(wrVal), 
              (unsigned int) BYTE_SWAP(rdVal),0,0,0 );
        errorCount++;
      }
    } /* end walking one test */

    if( errorCount != 0 )
    {
      LOGMSG("csVerifyChip: ERROR SRAM test failed, errorCount %d\n", 
        errorCount,0,0,0,0,0 );
      return( ERROR );
    }

   return OK;
}



/*******************************************************************************
*
* csInitChip -
*
* This routine uses the instance global variables in the cs_softc structure to
* initialize the CS890.
*
*/

LOCAL void csInitChip( CS_SOFTC *pCS )
{
   PIA    pIA;
   USHORT RxCtl;/*Promiscuous@kml*/

   /* Configure the adapter for board-specific IO and media type support */
   sysEnetHWInit( pCS );

   /* Initialize the config and control registers */
   csWritePacketPage( pCS, PKTPG_RX_CFG, RX_CFG_ALL_IE );
   csWritePacketPage( pCS, PKTPG_RX_CTL,
         RX_CTL_RX_OK_A | RX_CTL_IND_A | RX_CTL_BCAST_A | RX_CTL_MCAST_A);
   csWritePacketPage( pCS, PKTPG_TX_CFG, TX_CFG_ALL_IE );
   csWritePacketPage( pCS, PKTPG_BUF_CFG, BUF_CFG_ALL_IE ); 

   /* Put Ethernet address into the Individual Address register */
   pIA = (PIA)pCS->ArpCom.ac_enaddr;
   csWritePacketPage( pCS, PKTPG_IND_ADDR,   pIA->word[0] );
   csWritePacketPage( pCS, PKTPG_IND_ADDR+2, pIA->word[1] );
   csWritePacketPage( pCS, PKTPG_IND_ADDR+4, pIA->word[2] );

   /* Set the interrupt level in the chip */
   if ( pCS->IntLevel == 5 )
      csWritePacketPage( pCS, PKTPG_INT_NUM, BYTE_SWAP(3) );
   else
      csWritePacketPage( pCS, PKTPG_INT_NUM, BYTE_SWAP( (pCS->IntLevel)-10 ) );

   /* Promiscuous@kml If need to enable the promiscuous mode */
   if ( pCS->ConfigFlags & CFGFLG_PROMISC_MODE ) {
	  RxCtl=csReadPacketPage(pCS,PKTPG_RX_CTL);
      RxCtl |= (RX_CTL_PROM_A|RX_CTL_MCAST_A|RX_CTL_RX_OK_A | RX_CTL_IND_A | RX_CTL_BCAST_A);
      csWritePacketPage( pCS, PKTPG_RX_CTL, RxCtl );

	  LOGMSG ("csInitChip() Setting promiscuous mode on!\n", 0, 0, 0, 0, 0, 0);
   } else {
	  LOGMSG ("csInitChip() Setting promiscuous mode off!\n", 0, 0, 0, 0, 0, 0);
   }

     
   /* Enable reception and transmission of frames */
   csWritePacketPage( pCS, PKTPG_LINE_CTL,
   csReadPacketPage(pCS,PKTPG_LINE_CTL) | LINE_CTL_RX_ON | LINE_CTL_TX_ON );

   /* Enable interrupt at the chip */
   csWritePacketPage( pCS, PKTPG_BUS_CTL,
   csReadPacketPage(pCS,PKTPG_BUS_CTL) | BUS_CTL_INT_ENBL );
}



/*******************************************************************************
*
* csResetChip -
*
* This routine resets the CS8900 chip.
*
*/

LOCAL STATUS csResetChip( CS_SOFTC *pCS )
{
   int y;
   int x;
   UCHAR dummyVal;

   LOGMSG("csResetChip: unit %d, Reseting the chip......\n",
         pCS->ArpCom.ac_if.if_unit,0,0,0,0,0);

/*@kml assign an initial values to avoid "unused variable" warning when compiling*/
   x=0;
   dummyVal=0;
   
#ifdef HARD_RESET
   /* Disable interrupts at the CPU so reset command is atomic */
   y = intLock();

   /* We are now resetting the chip */
   /* A spurious interrupt is generated by the chip when it is reset. */
   /* This variable informs the interrupt handler to ignore this interrupt. */
   pCS->Resetting = TRUE;

   /* Issue a reset command to the chip */
   csWritePacketPage( pCS, PKTPG_SELF_CTL, SELF_CTL_RESET );

   /* Re-enable interrupts at the CPU */
   intUnlock( y );

   /* If transmission was in progress, it is not now */
   pCS->TxInProgress = FALSE;
   pCS->pTxFrameChain = NULL;

   /* The chip is always in IO mode after a reset */
   pCS->InMemoryMode = FALSE;

   /* Initialize locale flag */
   pCS->InISR = FALSE;

   /* Delay for 125 micro-seconds (one eighth of a second) */
   taskDelay( sysClkRateGet()/8 );

   /* Transition SBHE to switch chip from 8-bit to 16-bit */
   dummyVal = SYS_ENET_IN_BYTE( (pCS->IOAddr)+PORT_PKTPG_PTR );
   dummyVal = SYS_ENET_IN_BYTE( (pCS->IOAddr)+PORT_PKTPG_PTR+1 );
   dummyVal = SYS_ENET_IN_BYTE( (pCS->IOAddr)+PORT_PKTPG_PTR );
   dummyVal = SYS_ENET_IN_BYTE( (pCS->IOAddr)+PORT_PKTPG_PTR+1 );

   /* If EEPROM present, wait up to 125 mSec for EEPROM not busy*/
   y = sysClkRateGet()/8;
   for ( x=0; x<y; x++ )
   {
      if( !(csReadPacketPage(pCS,PKTPG_SELF_ST)&SELF_ST_SI_BUSY) )
         break;
   }
   if ( x == y )
      return ERROR;

   /* Wait up to 125 mSec for initialization is become done */
   for ( x=0; x<y; x++ )
   {
      if ( csReadPacketPage(pCS,PKTPG_SELF_ST)&SELF_ST_INIT_DONE )
         break;
   }
   if ( x == y )
      return ERROR;

   /* Reset is

⌨️ 快捷键说明

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