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

📄 ks5000_ether.c

📁 eCos/RedBoot for勤研ARM AnywhereII(4510) 含全部源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
    --freeCount;
  else
    {
      ++allocFail;
      if (freeCount)
        bufferListError();
    }
  return r;
}
#endif

static void initFreeList(void)
{
  int i;
  ethBufQueueClear(&freeList);
  freeCount = 0;
  for (i=0; i<NUM_ETH_BUFFERS; ++i)
    isrFreeBuffer(bufferPool+i);
}


//----------------------------------------------------------------------
// queue a buffer for transmit
//
// returns true if buffer was queued.

static int ks32c5000_eth_buffer_send(tEthBuffer *buf)
{
#if defined(CYGINT_IO_ETH_INT_SUPPORT_REQUIRED)
  while (!configDone)
    cyg_thread_delay(10);
#endif

  if (txWritePointer->FrameDataPtr & FRM_OWNERSHIP_BDMA)
    {
      // queue is full!  make sure transmit is running
      BDMATXCON |= BDMATXCON_EN;
      MACTXCON |= MACTXCON_TX_EN;
      return 0;
    }
  
  cyg_drv_mutex_lock(&txMutex);

  // free old buffer if we need to
  
  cyg_drv_isr_lock();
  if (txWritePointer->FrameDataPtr)
    {
      freeBuffer((tEthBuffer*)txWritePointer->FrameDataPtr);
      txWritePointer->FrameDataPtr = 0;
    }
  cyg_drv_isr_unlock();

  MAC_Tx_Pkts += 1;
  MAC_Tx_Octets += buf->length;

  // fill in the packet descriptor

#if (CYG_BYTEORDER == CYG_MSBFIRST) // Big endian
  txWritePointer->Reserved = (TXFDCON_PADDING_MODE | TXFDCON_CRC_MODE |
                    TXFDCON_SRC_ADDR_INC | TXFDCON_BIG_ENDIAN |
                    TXFDCON_WIDGET_ALIGN00 | TXFDCON_MAC_TX_INT_EN);
#else // Little endian
  txWritePointer->Reserved = (TXFDCON_PADDING_MODE | TXFDCON_CRC_MODE |
                    TXFDCON_SRC_ADDR_INC | TXFDCON_LITTLE_ENDIAN |
                    TXFDCON_WIDGET_ALIGN00 | TXFDCON_MAC_TX_INT_EN);
#endif
  
  txWritePointer->StatusAndFrameLength = buf->length;
  txWritePointer->FrameDataPtr = ((unsigned)buf | FRM_OWNERSHIP_BDMA);
  
  txWritePointer = txWritePointer->NextFD;
  
  cyg_drv_mutex_unlock(&txMutex);
    
  // start transmit

#if defined(CYGPKG_NET)  
  ++ifStats.tx_count;
#endif
  
  BDMATXCON |= BDMATXCON_EN;
  MACTXCON |= MACTXCON_TX_EN;
  return 1;
}


//======================================================================
// check to see if there's a frame waiting

static int rx_frame_avail(void)
{
  if (rxReadPointer->FrameDataPtr & FRM_OWNERSHIP_BDMA)
    {
      // queue is empty -- make sure Rx is running
      if (!(BDMARXCON & BDMARXCON_EN))
          {
            ++BDMARxErrCnt.queueOverflow;
            BDMARXCON |= BDMARXCON_EN;
          }
      return 0;
    }
  else
    return 1;
}


//======================================================================
// de-queue a receive buffer
static tEthBuffer *ks32c5000_eth_get_recv_buffer(void)
{
  unsigned RxStatusAndLength;
  tEthBuffer *RxBufPtr;
  tEthBuffer *emptyBuf;
#if SoftwareCRC  
  unsigned crc, crclen;
  int crcOK;
#else
# define crcOK 1
#endif

  while (1)
    {
      if (rxReadPointer->FrameDataPtr & FRM_OWNERSHIP_BDMA)
        {
          // queue is empty -- make sure Rx is running
          if (!(BDMARXCON & BDMARXCON_EN))
            {
              ++BDMARxErrCnt.queueOverflow;
              BDMARXCON |= BDMARXCON_EN;
            }
          return NULL;
        }
  
      RxBufPtr = (tEthBuffer*)rxReadPointer->FrameDataPtr;
      RxStatusAndLength = rxReadPointer->StatusAndFrameLength;
      
      // counting on short-circuit && evaluation below to only
      // allocate a fresh buffer if rx packet is good!!

#if defined (CYGPKG_NET)      
      ++ifStats.rx_count;
#endif      
      
#if SoftwareCRC
      crclen = (RxStatusAndLength & 0xffff) - 4;
      crc = cyg_ether_crc32(RxBufPtr->data+2,crclen);
      crcOK = ((U08)(crc>>0) == RxBufPtr->data[2+crclen+0] &&
               (U08)(crc>>8) == RxBufPtr->data[2+crclen+1] &&
               (U08)(crc>>16) == RxBufPtr->data[2+crclen+2] &&
               (U08)(crc>>24) == RxBufPtr->data[2+crclen+3]);
#endif
      if ((RxStatusAndLength & (RXFDSTAT_GOOD<<16)) 
          && crcOK
          && (emptyBuf = allocBuffer()))
        {
          // good packet and we've got a fresh buffer to take
          // it's place in the receive queue
          rxReadPointer->FrameDataPtr = (unsigned)emptyBuf | FRM_OWNERSHIP_BDMA;
          rxReadPointer = rxReadPointer->NextFD;
          RxBufPtr->length = RxStatusAndLength & 0xffff;
#if defined(CYGPKG_NET)
          ++ifStats.rx_deliver;
#endif          
          return RxBufPtr;
        }
      else
        {
          // bad packet or out of buffers.  either way we
          // ignore this packet, and reuse the buffer
#if defined(CYGPKG_NET)
          if (RxStatusAndLength & (RXFDSTAT_GOOD<<16) && crcOK)
            ++ifStats.rx_resource;
          else
            ++ifStats.rx_crc_errors;
#endif          
          rxReadPointer->FrameDataPtr |= FRM_OWNERSHIP_BDMA;
          rxReadPointer = rxReadPointer->NextFD;
        }
    }
}

//======================================================================
static int EthInit(U08* mac_address)
{
#if CYGINT_DEVS_ETH_ARM_KS32C5000_PHY && defined(CYGPKG_NET)
  unsigned linkStatus;
#endif

  if (mac_address)
    debug2_printf("EthInit(%02x:%02x:%02x:%02x:%02x:%02x)\n",
                mac_address[0],mac_address[1],mac_address[2],
                mac_address[3],mac_address[4],mac_address[5]);
  else
    debug2_printf("EthInit(NULL)\n");

#if CYGINT_DEVS_ETH_ARM_KS32C5000_PHY
  PhyReset();
#endif
  
  /* Set the initial condition of the BDMA. */
  BDMARXCON = BDMARXCON_RESET;
  BDMATXCON = BDMATXCON_RESET;
  BDMARXLSZ = MAX_ETH_FRAME_SIZE;

  BDMARXPTR = (U32)rxReadPointer;
  BDMATXPTR = (U32)txWritePointer;
  
  MACCON = MACON_SW_RESET;
  MACCON = MACConfigVar;
	 
  CAMCON = CAMConfigVar;
  
  // set up our MAC address
  if (mac_address)
    {
      *((volatile U32*)CAM_BaseAddr) = 
        (mac_address[0]<<24) |
        (mac_address[1]<<16) |
        (mac_address[2]<< 8) |
        (mac_address[3]<< 0);
      *((volatile U16*)(CAM_BaseAddr+4)) =
        (mac_address[4]<< 8) |
        (mac_address[5]<< 0);
    }
  
  // CAM Enable
  CAMEN = 0x0001;
  
  // update the Configuration of BDMA and MAC to begin Rx/Tx

  BDMARXCON = BDMARxConfigVar;
  MACRXCON = MACRxConfigVar;

  BDMATXCON = BDMATxConfigVar;
  MACTXCON =  MACTxConfigVar;

    debug2_printf("ks32C5000 eth: %02x:%02x:%02x:%02x:%02x:%02x  ",
              *((volatile unsigned char*)CAM_BaseAddr+0),
              *((volatile unsigned char*)CAM_BaseAddr+1),
              *((volatile unsigned char*)CAM_BaseAddr+2),
              *((volatile unsigned char*)CAM_BaseAddr+3),
              *((volatile unsigned char*)CAM_BaseAddr+4),
              *((volatile unsigned char*)CAM_BaseAddr+5));

#if CYGINT_DEVS_ETH_ARM_KS32C5000_PHY && defined(CYGPKG_NET)
  // Read link status to be up to date
  linkStatus = PhyStatus();
  if (linkStatus & PhyStatus_FullDuplex)
    ifStats.duplex = 3;
  else
    ifStats.duplex = 2;

  if (linkStatus & PhyStatus_LinkUp)
    ifStats.operational = 3;
  else
    ifStats.operational = 2;

  if (linkStatus & PhyStatus_100Mb)
    ifStats.speed = 100000000;
  else
    ifStats.speed = 10000000;
#endif

#if SoftwareCRC
  debug2_printf("Software CRC\n");
#else
  debug2_printf("Hardware CRC\n");
#endif
  
  return 0;
}

//======================================================================
static void Init_TxFrameDescriptorArray(void)
{
  FRAME_DESCRIPTOR *pFrameDescriptor;
  int i;
  
  // Each Frame Descriptor's frame data pointer points is NULL
  // if not in use, otherwise points to an ethBuffer

  pFrameDescriptor = txFrameDescrArray;
  
  for(i=0; i < MAX_TX_FRAME_DESCRIPTORS; i++) 
    {
      pFrameDescriptor->FrameDataPtr = 0;
      pFrameDescriptor->Reserved = 0;
      pFrameDescriptor->StatusAndFrameLength = 0;
      pFrameDescriptor->NextFD = pFrameDescriptor+1;
      pFrameDescriptor++;
    }

  // fix up the last pointer to loop back to the first

  txFrameDescrArray[MAX_TX_FRAME_DESCRIPTORS-1].NextFD = txFrameDescrArray;
  
  txDonePointer = txWritePointer = txFrameDescrArray;
  
  return;
}


//======================================================================
static void Init_RxFrameDescriptorArray(void)
{
  FRAME_DESCRIPTOR *pFrameDescriptor;
  int i;
  
  // Each Frame Descriptor's frame data pointer points to
  // an ethBuffer struct

  pFrameDescriptor = rxFrameDescrArray;
  
  for(i=0; i < MAX_RX_FRAME_DESCRIPTORS; i++) 
    {
      pFrameDescriptor->FrameDataPtr = ((unsigned)allocBuffer() | FRM_OWNERSHIP_BDMA);
      pFrameDescriptor->Reserved = 0;
      pFrameDescriptor->StatusAndFrameLength = 0;
      pFrameDescriptor->NextFD = pFrameDescriptor+1;
      pFrameDescriptor++;
    }
  
  // fix up the last pointer to loop back to the first

  rxFrameDescrArray[MAX_RX_FRAME_DESCRIPTORS-1].NextFD = rxFrameDescrArray;
  
  rxReadPointer = rxFrameDescrArray;
  
  return;
}

#if CYGINT_DEVS_ETH_ARM_KS32C5000_PHY

#if HavePHYinterrupt
static unsigned linkStatus;

static cyg_uint32 MAC_Phy_isr(cyg_vector_t vector, cyg_addrword_t data)
{
  cyg_drv_interrupt_acknowledge(vector);
  PhyInterruptAck();
  ++ks5000_MAC_Phy_Cnt;
  linkStatus = PhyStatus();
  if (linkStatus & PhyStatus_FullDuplex)  
    MACConfigVar |= (MACON_FULL_DUP);
  else
    MACConfigVar &= ~(MACON_FULL_DUP);
  
#if defined(CYGPKG_NET)      
  if (linkStatus & PhyStatus_FullDuplex)
    ifStats.duplex = 3;
  else
    ifStats.duplex = 2;
  
  if (linkStatus & PhyStatus_LinkUp)
    ifStats.operational = 3;
  else
    ifStats.operational = 2;

  if (linkStatus & PhyStatus_100Mb)
    ifStats.speed = 100000000;
  else
    ifStats.speed = 10000000;
#endif  
  
  MACCON = MACConfigVar;
  return CYG_ISR_HANDLED;
}
#endif
#endif

static void ks32c5000_handle_tx_complete(void)
{

  // record status and then free any buffers we're done with
  
  while (txDonePointer->FrameDataPtr && !(txDonePointer->FrameDataPtr & FRM_OWNERSHIP_BDMA))
    {
#if defined(CYGPKG_NET)
      U32 txStatus;
        
      txStatus = txDonePointer->StatusAndFrameLength>>16;
    
      ++ks5000_MAC_Tx_Cnt;
      ++ifStats.interrupts;
  
      if (txStatus & MACTXSTAT_COMP)
        ++ifStats.tx_complete;
      
      if (txStatus & (MACTXSTAT_EX_COLL | MACTXSTAT_DEFFERED |
                            MACTXSTAT_UNDER | MACTXSTAT_DEFER |
                            MACTXSTAT_NCARR | MACTXSTAT_SIG_QUAL |
                            MACTXSTAT_LATE_COLL | MACTXSTAT_PAR |
                            MACTXSTAT_PAUSED | MACTXSTAT_HALTED)) 
        {
          // transmit failed, log errors
          if (txStatus & MACTXSTAT_EX_COLL)
            ++ifStats.tx_max_collisions;
          if (txStatus & MACTXSTAT_DEFFERED)
            ++ifStats.tx_deferred;
          if (txStatus & MACTXSTAT_UNDER)
            ++ifStats.tx_underrun;
          if (txStatus & MACTXSTAT_DEFER)
            ;
          if (txStatus & MACTXSTAT_NCARR)
            ++ifStats.tx_carrier_loss;
          if (txStatus & MACTXSTAT_SIG_QUAL)
            ++ifStats.tx_sqetesterrors;
          if (txStatus & MACTXSTAT_LATE_COLL)
            ++ifStats.tx_late_collisions;
          if (txStatus & MACTXSTAT_PAR)
            ;
          if (txStatus & MACTXSTAT_PAUSED)
            ;
          if (txStatus & MACTXSTAT_HALTED)
            ;
        }
      else
        {
          // transmit OK
          int collisionCnt = txStatus & 0x0f;
          ++ifStats.tx_good;
          if (collisionCnt)
            {
              if (collisionCnt == 1)
                ++ifStats.tx_single_collisions;
              else
                ++ifStats.tx_mult_collisions;
              ifStats.tx_total_collisions += collisionCnt;
            }
        }
#endif      
      isrFreeBuffer((tEthBuffer*)txDonePointer->FrameDataPtr);
      txDonePointer->FrameDataPtr = 0;
      txDonePointer = txDonePointer->NextFD;
    }
}


//======================================================================
static cyg_uint32 MAC_Tx_isr(cyg_vector_t vector, cyg_addrword_t data)
{
  cyg_drv_interrupt_acknowledge(vector);
  ks32c5000_handle_tx_complete();
  return CYG_ISR_HANDLED;
}

static unsigned accumulatedMaxRxStatus=0;

//======================================================================
static cyg_uint32 MAC_Rx_isr(cyg_vector_t vector, cyg_addrword_t data)
{
  U32 IntMACRxStatus;
  
  cyg_drv_interrupt_acknowledge(vector);
  
  IntMACRxStatus = MACRXSTAT;
  MACRXSTAT = IntMACRxStatus;

  accumulatedMaxRxStatus |= IntMACRxStatus;
  
  ++ks5000_MAC_Rx_Cnt;

#if defined(CYGPKG_NET)
  
  ++ifStats.interrupts;

  if (IntMACRxStatus & MACRXSTAT_GOOD) 
    {
      ++ifStats.rx_good;
      
      if (IntMACRxStatus & MACRXSTAT_CTL_RECD)
        ;  // we don't do anything with control packets
      
      return CYG_ISR_HANDLED;
    }

  if (IntMACRxStatus & (MACRXSTAT_ALLIGN_ERR | MACRXSTAT_CRC_ERR |
                        MACRXSTAT_OVERFLOW | MACRXSTAT_LONG_ERR |
                        MACRXSTAT_PAR | MACRXSTAT_HALTED) ) 
    {
      if (IntMACRxStatus & MACRXSTAT_ALLIGN_ERR)
        ++ifStats.rx_align_errors;
      if (IntMACRxStatus & MACRXSTAT_CRC_ERR)
        ++ifStats.rx_crc_errors;
      if (IntMACRxStatus & MACRXSTAT_OVERFLOW)
        ++ifStats.rx_overrun_errors;
      if (IntMACRxStatus & MACRXSTAT_LONG_ERR)
        ++ifStats.rx_too_long_frames;
      if (IntMACRxStatus & MACRXSTAT_PAR)
        ++ifStats.rx_symbol_errors;
      if (IntMACRxStatus & MACRXSTAT_HALTED)
        ;
    }

⌨️ 快捷键说明

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