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

📄 freedev_lan91c111.c

📁 lan91c111网络接口的设计 包括功能设计文件和驱动程序文件
💻 C
📖 第 1 页 / 共 3 页
字号:
  for(i=15;i>=0;i--) 
  {
    clock_phy_bit(dev, mgmt_value | 
                                  FREEDEV_LAN91C111_MGMT_MDOE_MSK |
                                  ((value >> i) & 0x1));
  }

  IOWR_FREEDEV_LAN91C111_BSR( dev->base_addr,old_bank);

  return;  
}

/*-----------------------------------------------------------------------------------*
 *
 * reset_device(freedev_lan91c111_if *dev):
 *
 * Reset the device and get it into a known state
 *
 * 
 *-----------------------------------------------------------------------------------*/
static err_t reset_device(freedev_lan91c111_if *dev)
{
  alt_u16 register_value;
  alt_u16 chip_id;
  err_t   ret_code = ERR_OK;

  LWIP_DEBUGF(NETIF_DEBUG | DBG_TRACE, ("reset_device()\n"));

  IOWR_FREEDEV_LAN91C111_BSR( dev->base_addr, 3);
  chip_id = IORD_FREEDEV_LAN91C111_REV(dev->base_addr);

  if (( chip_id & FREEDEV_LAN91C111_CHIP_ID) != 
                  FREEDEV_LAN91C111_CHIP_ID ) 
  {
    LWIP_DEBUGF(NETIF_DEBUG | DBG_TRACE, ("Not an SMC91C111 chip\n"));
    ret_code = ERR_IF;
    goto exit;
  }

  /* Bank 0 */
  IOWR_FREEDEV_LAN91C111_BSR( dev->base_addr, 0);
  /*There are a bug in altera_avalon_lan91c111.c,modify by free_electron
   * IOWR_FREEDEV_LAN91C111_RCR( dev->base_addr, 
                                FREEDEV_LAN91C111_RCR_SOFTRST_OFST);
   */
  IOWR_FREEDEV_LAN91C111_RCR( dev->base_addr, 
                                FREEDEV_LAN91C111_RCR_SOFTRST_MSK);
  /* a very generous reset pulse */
  usleep(1000);
  
  IOWR_FREEDEV_LAN91C111_RCR(dev->base_addr, 0);

  /* This should be plenty of time for the device to settle */
  usleep(5000);
  
  /* Reset the MMU */
  IOWR_FREEDEV_LAN91C111_BSR( dev->base_addr, 2);
  IOWR_FREEDEV_LAN91C111_MMUCR( dev->base_addr,
                                  FREEDEV_LAN91C111_MMUCR_RESET_MSK);

  do {
    register_value = IORD_FREEDEV_LAN91C111_MMUCR(dev->base_addr);
  }while(register_value & FREEDEV_LAN91C111_MMUCR_BUSY_MSK);

exit:
  LWIP_DEBUGF(NETIF_DEBUG | DBG_TRACE, ("reset_device() exit = %d\n", ret_code));

  return ret_code;

}

/*
* set_mac_address
*
* Configure the MAC address of the SMSC chip
*/
static err_t set_mac_address(freedev_lan91c111_if* dev)
{
  struct netif* netif = dev->lwip_dev_list.dev.netif;
  IOWR_FREEDEV_LAN91C111_BSR(dev->base_addr, 1);
  IOWR_FREEDEV_LAN91C111_IAR0(dev->base_addr, 
                                    netif->hwaddr[0]);
  IOWR_FREEDEV_LAN91C111_IAR1(dev->base_addr, 
                                    netif->hwaddr[1]);
  IOWR_FREEDEV_LAN91C111_IAR2(dev->base_addr, 
                                    netif->hwaddr[2]);
  IOWR_FREEDEV_LAN91C111_IAR3(dev->base_addr, 
                                    netif->hwaddr[3]);
  IOWR_FREEDEV_LAN91C111_IAR4(dev->base_addr, 
                                    netif->hwaddr[4]);
  IOWR_FREEDEV_LAN91C111_IAR5(dev->base_addr, 
                                    netif->hwaddr[5]);

  return ERR_OK;
}


/*
* configure_phy 
*
* reset the PHY and auto negotiate for the link capabilities
*
*/
static err_t configure_phy(freedev_lan91c111_if *dev)
{
  int timeout, i;
  alt_u16 value, old_value;
  err_t ret_code = ERR_OK;

  LWIP_DEBUGF(NETIF_DEBUG | DBG_TRACE, ("configure_phy()\n"));

  /* Read the ID register let's just check we've detected the correct PHY */
  value = read_phy_register(dev, 
                            FREEDEV_LAN91C111_PHY_ID1_REG);
  if (value != FREEDEV_LAN91C111_PHY_COMPANY_ID) 
  {
    ret_code = ERR_IF;
    goto exit;
  }

  value = read_phy_register(dev, 
                            FREEDEV_LAN91C111_PHY_ID2_REG);
  if ((value & 0xfff0) != FREEDEV_LAN91C111_PHY_MFCT_ID ) 
  {
    ret_code = ERR_IF;
    goto exit;
  }

  /* Reset the PHY */
  write_phy_register( dev, 
                      FREEDEV_LAN91C111_PHY_CONTROL_REG, 
                      FREEDEV_LAN91C111_PHY_CONTROL_RST_MSK);

  /* Spec says wait 50 mS */
  usleep(50000);

  /* Let's just check  it's out of reset */
  value = read_phy_register(dev, 
                            FREEDEV_LAN91C111_PHY_CONTROL_REG);

  if (value & FREEDEV_LAN91C111_PHY_CONTROL_RST_MSK) 
  {
    ret_code = ERR_IF;
    goto exit;
  }

  /* Turn off Auto negotiation til we're ready for it */
  write_phy_register( dev, 
                      FREEDEV_LAN91C111_PHY_CONTROL_REG , 0);

  /* We'll auto negotiate the capabilities
   * 20051227 Free-electron modify orange LED is 10M/100M link,
   * green LED is Rx/Tx
   * */
  IOWR_FREEDEV_LAN91C111_BSR(dev->base_addr, 0); 
  /*IOWR_FREEDEV_LAN91C111_RPCR(dev->base_addr,
                                    FREEDEV_LAN91C111_RPCR_ANEG_MSK |
                                    FREEDEV_LAN91C111_RPCR_LS2A_MSK | 
                                    FREEDEV_LAN91C111_RPCR_LS1A_MSK |                                     
                                    FREEDEV_LAN91C111_RPCR_LS2B_MSK | 
                                    FREEDEV_LAN91C111_RPCR_LS1B_MSK | 
                                    FREEDEV_LAN91C111_RPCR_LS0B_MSK ); */
  IOWR_FREEDEV_LAN91C111_RPCR(dev->base_addr,
                                    FREEDEV_LAN91C111_RPCR_ANEG_MSK |                                   
                                    FREEDEV_LAN91C111_RPCR_LS2B_MSK ); 
  /* Start the Auto Negotiation process */
  /* Try to negotiate, we have a go at this five times if it fails */
  i = 5;
  do 
  {
    write_phy_register( dev, 
                        FREEDEV_LAN91C111_PHY_CONTROL_REG, 
                        FREEDEV_LAN91C111_PHY_CONTROL_ANEG_EN_MSK | 
                        FREEDEV_LAN91C111_PHY_CONTROL_ANEG_RST_MSK);

    /* 
    * Spec says wait 1500 mS after turning on auto negotiation before 
    * reading the ANEG_ACK bit see section 7.7.12
    */
    usleep(1500000);

    /* This may take a few seconds */
    timeout = 20;

    do 
    {
      value = read_phy_register(dev, FREEDEV_LAN91C111_PHY_STATUS_REG);
      timeout --;
      usleep(500000);
    }while (!(value & FREEDEV_LAN91C111_PHY_STATUS_ANEG_ACK_MSK)  
              && (timeout > 0));

    i --;
  }
  while( (i != 0) && (timeout == 0));

  if (timeout == 0)
  {
    ret_code = ERR_IF;
    goto exit;
  }

  if (value & FREEDEV_LAN91C111_PHY_STATUS_REM_FLT_MSK) 
  {
    /* 
     * We may wish to come up with a sensible default here, 
     *set to 10MBits, CSMA?
     */
    ret_code = ERR_IF;
    goto exit;
  }

  /* 
   * Find out what we've negotiated so that we can configure the MAC 
   * takes a few reads to stabilise
   */

  old_value = read_phy_register(dev, 
                            FREEDEV_LAN91C111_PHY_INT_STATUS_REG);
  value = read_phy_register(dev, 
                            FREEDEV_LAN91C111_PHY_INT_STATUS_REG);

  while(value != old_value)
  {
    old_value = value;
    value = read_phy_register(dev, 
                            FREEDEV_LAN91C111_PHY_INT_STATUS_REG);
  }

  if (value & FREEDEV_LAN91C111_PHY_INT_SPDDET_MSK) 
  {
    LWIP_DEBUGF(NETIF_DEBUG | DBG_TRACE, ("100MBits/s\n"));
  }
  else 
  {
    LWIP_DEBUGF(NETIF_DEBUG | DBG_TRACE, ("10MBits/s\n"));
  }

  if (value & FREEDEV_LAN91C111_PHY_INT_DPLXDET_MSK) 
  {
    LWIP_DEBUGF(NETIF_DEBUG | DBG_TRACE, ("Full Duplex\n"));

    /* Set the MAC for Full Duplex */
    value = IORD_FREEDEV_LAN91C111_TCR(dev->base_addr);
    value |= FREEDEV_LAN91C111_TCR_SWFDUP_MSK;
    IOWR_FREEDEV_LAN91C111_TCR(dev->base_addr,value);
  }
  else 
  {
    LWIP_DEBUGF(NETIF_DEBUG | DBG_TRACE, ("Half Duplex\n"));
  }

exit:
  LWIP_DEBUGF(NETIF_DEBUG | DBG_TRACE, ("configure_phy() exit = %d\n", ret_code));

  return ret_code;
}

/*
* allocate_tx_packet
*
* Allocate (within the device) the one packet we will use for all transmissions
*/
static err_t allocate_tx_packet( freedev_lan91c111_if *dev )
{
  alt_u16 value;
  alt_u8 byte_value;
  int timeout;
  err_t ret_code = ERR_OK;

  LWIP_DEBUGF(NETIF_DEBUG | DBG_TRACE, ("allocate_tx_packet()\n"));

  IOWR_FREEDEV_LAN91C111_BSR(dev->base_addr, 2);
  value = IORD_FREEDEV_LAN91C111_MMUCR(dev->base_addr);
  value |= FREEDEV_LAN91C111_MMUCR_ALLOC_MSK;
  IOWR_FREEDEV_LAN91C111_MMUCR(dev->base_addr, value);

  /* Wait for the command to complete */
  timeout = 10;
  do 
  {
    byte_value = IORD_FREEDEV_LAN91C111_IST(dev->base_addr);
    usleep(100000);
    timeout --;
  }
  while((!(byte_value & FREEDEV_LAN91C111_INT_ALLOC_INT_MSK)) && 
        (timeout > 0));

  if (timeout == 0) 
  {
    ret_code = ERR_IF;
    goto exit;
  }

  /* Save the allocated packet number for future use */
  byte_value = IORD_FREEDEV_LAN91C111_ARR(dev->base_addr);

  if (byte_value & FREEDEV_LAN91C111_ARR_FAILED_MSK) 
  {
    ret_code = ERR_IF;
    goto exit;
  }

  dev->tx_packet_no = byte_value & ~FREEDEV_LAN91C111_ARR_FAILED_MSK;


exit:
  LWIP_DEBUGF(NETIF_DEBUG | DBG_TRACE, ("allocate_tx_packet() exit = %d\n", ret_code));
  return ERR_OK;

}

/*-----------------------------------------------------------------------------------*/
static err_t low_level_init(freedev_lan91c111_if *dev)
{
  /* 
  * Need to have a pointer to a generice lwip_dev
  * This is so that the get_mac_addr function interface
  * is device agnostic
  */
  alt_lwip_dev* lwip_dev = &dev->lwip_dev_list.dev;
  err_t ret_code = ERR_OK;

  LWIP_DEBUGF(NETIF_DEBUG | DBG_TRACE, ("low_level_init()\n"));

  /*
  * Read the MAC address out of flash
  */
  ret_code = get_mac_addr(lwip_dev);
  if (ret_code != ERR_OK) 
  {
    goto exit;
  }

  /* Set MAC hardware address length */
  lwip_dev->netif->hwaddr_len = 6;

  ret_code = reset_device(dev);
  if (ret_code != ERR_OK) 
  {
    goto exit;
  }

  ret_code = set_mac_address(dev);
  if (ret_code != ERR_OK) 
  {
    goto exit;
  }

  ret_code = configure_phy(dev);
  if (ret_code != ERR_OK) 
  {
    goto exit;
  }

  ret_code = allocate_tx_packet(dev);
  if (ret_code != ERR_OK) 
  {
    goto exit;
  }

  /* maximum transfer unit */
  dev->lwip_dev_list.dev.netif->mtu = 1500;
  
  /* broadcast capability */
  dev->lwip_dev_list.dev.netif->flags = NETIF_FLAG_BROADCAST;
  
  dev->semaphore = sys_sem_new(1);
  if (dev->semaphore == NULL)
  {
    ret_code = ERR_MEM;
    goto exit;
  }

  dev->arp_semaphore = sys_sem_new(1);
  if (dev->arp_semaphore == NULL)
  {
    ret_code = ERR_MEM;
    goto exit;
  }

  /* Turn on Rx & Tx */
  IOWR_FREEDEV_LAN91C111_BSR( dev->base_addr, 0);
  IOWR_FREEDEV_LAN91C111_RCR( dev->base_addr,
                                    FREEDEV_LAN91C111_RCR_STRIP_CRC_MSK | 
                                    FREEDEV_LAN91C111_RCR_RXEN_MSK);
  IOWR_FREEDEV_LAN91C111_TCR( dev->base_addr,
                                    FREEDEV_LAN91C111_TCR_TXENA_MSK |
                                    FREEDEV_LAN91C111_TCR_PAD_EN_MSK);

  /* 
  * From this point on we don't change banks again, bank 2 is all that's needed 
  * for Rx, TX and interrupt handling
  */
  IOWR_FREEDEV_LAN91C111_BSR( dev->base_addr, 2);

  /*
  * Let's make sure no interupts are enabled
  */
  IOWR_FREEDEV_LAN91C111_MSK(dev->base_addr, 0);

  /*
   *  Install ISR and turn on interrupts
   *  
   *  If you're counting stats then we also turn on the RCV_OVRN 
   *  interrupt and increment the error counter for each interrupt

⌨️ 快捷键说明

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