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

📄 c5471_ethernet.c

📁 這是一個實時嵌入式作業系統 實作了MCS51 ARM等MCU
💻 C
📖 第 1 页 / 共 5 页
字号:
  c5471->c_bifup = FALSE;  irqrestore(flags);  return OK;}/**************************************************************************** * Function: c5471_txavail * * Description: *   Driver callback invoked when new TX data is available.  This is a  *   stimulus perform an out-of-cycle poll and, thereby, reduce the TX *   latency. * * Parameters: *   dev  - Reference to the NuttX driver state structure * * Returned Value: *   None * * Assumptions: *   Called in normal user mode * ****************************************************************************/static int c5471_txavail(struct uip_driver_s *dev){  struct c5471_driver_s *c5471 = (struct c5471_driver_s *)dev->d_private;  irqstate_t flags;  ndbg("Polling\n");  flags = irqsave();  /* Ignore the notification if the interface is not yet up */  if (c5471->c_bifup)    {      /* Check if the ESM has let go of the RX descriptor giving us access       * rights to submit another Ethernet frame.       */      if ((EIM_TXDESC_OWN_HOST & getreg32(c5471->c_rxcpudesc)) == 0)       {          /* If so, then poll uIP for new XMIT data */          (void)uip_poll(&c5471->c_dev, c5471_uiptxpoll);       }    }  irqrestore(flags);  return OK;}/**************************************************************************** * Name: c5471_eimreset * * Description *   The C547x docs states that a module should generally be reset according *   to the following algorithm: * *   1. Put the module in reset. *   2. Switch on the module clock. *   3. Wait for eight clock cycles. *   4. Release the reset. * ****************************************************************************/static void c5471_eimreset (struct c5471_driver_s *c5471){  /* Stop the EIM module clock */  putreg32((getreg32(CLKM) | CLKM_EIM_CLK_STOP), CLKM);  /* Put EIM module in reset */  putreg32((getreg32(CLKM_RESET) & ~CLKM_RESET_EIM), CLKM_RESET);  /* Start the EIM module clock */  putreg32((getreg32(CLKM) & ~CLKM_EIM_CLK_STOP), CLKM);  /* Assert nRESET to reset the board's PHY0/1 chips */  putreg32((CLKM_CTL_RST_EXT_RESET|CLKM_CTL_RST_LEAD_RESET), CLKM_CTL_RST);  up_mdelay(2);  /* Release the peripheral nRESET signal */  putreg32(CLKM_CTL_RST_LEAD_RESET, CLKM_CTL_RST);  /* Release EIM module reset */  putreg32((getreg32(CLKM_RESET) | CLKM_RESET_EIM), CLKM_RESET);  /* All EIM register should now be in there power-up default states */  c5471->c_lastdescstart = 0;  c5471->c_lastdescend   = 0;}/**************************************************************************** * Name: c5471_eimconfig * * Description *    Assumes that all registers are currently in the power-up reset state. *    This routine then modifies that state to provide our specific ethernet *    configuration. * ****************************************************************************/static void c5471_eimconfig(struct c5471_driver_s *c5471){  volatile uint32 pbuf;  volatile uint32 desc;  volatile uint32 val;  int i;  desc = EIM_RAM_START;  pbuf = EIM_RAM_START + 0x6C0;  /* TX ENET 0 */  ndbg("TX ENET0 desc: %08x pbuf: %08x\n", desc, pbuf);  putreg32((desc & 0x0000ffff), ENET0_TDBA); /* 16-bit offset address */  for (i = NUM_DESC_TX-1; i >= 0; i--)    {      if (i == 0)        val = EIM_TXDESC_WRAP_NEXT;      else        val = EIM_TXDESC_WRAP_FIRST;      val |= EIM_TXDESC_OWN_HOST|EIM_TXDESC_INTRE|EIM_TXDESC_PADCRC|EIM_PACKET_BYTES;      putreg32(val, desc);      desc += sizeof(uint32);      putreg32(pbuf, desc);      desc += sizeof(uint32);      putreg32(0, pbuf);      pbuf += EIM_PACKET_BYTES;      putreg32(0, pbuf);      pbuf += sizeof(uint32); /* Ether Module's "Buffer Usage Word" */    }  /* RX ENET 0 */  ndbg("RX ENET0 desc: %08x pbuf: %08x\n", desc, pbuf);  putreg32((desc & 0x0000ffff), ENET0_RDBA); /* 16-bit offset address */  for (i = NUM_DESC_RX-1; i >= 0; i--)    {      if (i == 0)        val = EIM_RXDESC_WRAP_NEXT;      else        val = EIM_RXDESC_WRAP_FIRST;      val |= EIM_RXDESC_OWN_ENET|EIM_RXDESC_INTRE|EIM_RXDESC_PADCRC|EIM_PACKET_BYTES;      putreg32(val, desc);      desc += sizeof(uint32);      putreg32(pbuf, desc);      desc += sizeof(uint32);      putreg32(0, pbuf);      pbuf += EIM_PACKET_BYTES;      putreg32(0, pbuf);      pbuf += sizeof(uint32); /* Ether Module's "Buffer Usage Word" */  }  /* TX CPU */  ndbg("TX CPU desc: %08x pbuf: %08x\n", desc, pbuf);  c5471->c_txcpudesc = desc;  putreg32((desc & 0x0000ffff), EIM_CPU_TXBA); /* 16-bit offset address */  for (i = NUM_DESC_TX-1; i >= 0; i--)    {      /* Set words 1+2 of the TXDESC */      if (i == 0)        val = EIM_TXDESC_WRAP_NEXT;      else        val = EIM_TXDESC_WRAP_FIRST;      val |= EIM_TXDESC_OWN_HOST|EIM_TXDESC_INTRE|EIM_TXDESC_PADCRC|EIM_PACKET_BYTES;      putreg32(val, desc);      desc += sizeof(uint32);      putreg32(pbuf, desc);      desc += sizeof(uint32);      putreg(0, pbuf);      pbuf += EIM_PACKET_BYTES;      putreg(0, pbuf);      pbuf += sizeof(uint32); /* Ether Module's "Buffer Usage Word" */  }  /* RX CPU */  ndbg("RX CPU desc: %08x pbuf: %08x\n", desc, pbuf);  c5471->c_rxcpudesc = desc;  putreg32((desc & 0x0000ffff), EIM_CPU_RXBA); /* 16-bit offset address */  for (i = NUM_DESC_RX-1; i >= 0; i--)    {      /* Set words 1+2 of the RXDESC */      if (i == 0)        val = EIM_RXDESC_WRAP_NEXT;      else        val = EIM_RXDESC_WRAP_FIRST;      val |= EIM_RXDESC_OWN_ENET|EIM_RXDESC_INTRE|EIM_RXDESC_PADCRC|EIM_PACKET_BYTES;      putreg32(val, desc);      desc += sizeof(uint32);      putreg32(pbuf, desc);      desc += sizeof(uint32);      putreg32(0, pbuf);      pbuf += EIM_PACKET_BYTES;      putreg32(0, pbuf);      pbuf += sizeof(uint32); /* Ether Module's "Buffer Usage Word" */  }  ndbg("END desc: %08x pbuf: %08x\n", desc, pbuf);  /* Save the descriptor packet size */  putreg32(EIM_PACKET_BYTES, EIM_BUFSIZE);  /* Set the filter mode */#if 0  putreg32(EIM_FILTER_UNICAST, EIM_CPU_FILTER);#else//  putreg32(EIM_FILTER_LOGICAL|EIM_FILTER_UNICAST|EIM_FILTER_MULTICAST|//           EIM_FILTER_BROADCAST, EIM_CPU_FILTER);  putreg32(EIM_FILTER_UNICAST|EIM_FILTER_MULTICAST|EIM_FILTER_BROADCAST, EIM_CPU_FILTER);#endif   /* Disable all Ethernet interrupts */  putreg32(0x00000000, EIM_INTEN);  /* Setup the EIM control register */#if 1  putreg32(EIM_CTRL_ENET0_EN|EIM_CTRL_RXENET0_EN|EIM_CTRL_TXENET0_EN|           EIM_CTRL_RXCPU_EN|EIM_CTRL_TXCPU_EN, EIM_CTRL);#else   putreg32(EIM_CTRL_ENET0_EN|EIM_CTRL_ENET0_FLW|EIM_CTRL_RXENET0_EN|           EIM_CTRL_TXENET0_EN|EIM_CTRL_RXCPU_EN|EIM_CTRL_TXCPU_EN, EIM_CTRL);#endif#if 1   putreg32(0x00000000, EIM_MFVHI);#else  putreg32(0x0000ff00, EIM_MFVHI);#endif   putreg32(0x00000000, EIM_MFVLO);  putreg32(0x00000000, EIM_MFMHI);  putreg32(0x00000000, EIM_MFMLO);  putreg32(0x00000018, EIM_RXTH);  putreg32(0x00000000, EIM_CPU_RXREADY);  /* Setup the ENET0 mode register */#if 1  putreg32(ENET_MODE_RJCT_SFE|ENET_MODE_MWIDTH|ENET_MODE_FULLDUPLEX, ENET0_MODE);#else  putreg32(ENET_MODE_RJCT_SFE|ENET_MODE_MWIDTH|ENET_MODE_HALFDUPLEX, ENET0_MODE);#endif   putreg32(0x00000000, ENET0_BOFFSEED);  putreg32(0x00000000, ENET0_FLWPAUSE);  putreg32(0x00000000, ENET0_FLWCONTROL);  putreg32(0x00000000, ENET0_VTYPE);#if 0   putreg32(ENET_ADR_BROADCAST|ENET_ADR_PROMISCUOUS, ENET0_ADRMODE_EN);#else   /* The CPU port is not PROMISCUOUS, it wants a no-promiscuous address   * match yet the the SWITCH receives packets from the PROMISCUOUS ENET0   * which routes all packets for filter matching at the CPU port which   * then allows the s/w to see the new incoming packetes that passed   * the filter. Here we are setting the main SWITCH closest the ether   * wire.   */  putreg32(ENET_ADR_PROMISCUOUS, ENET0_ADRMODE_EN);#endif   putreg32(0x00000000, ENET0_DRP);  up_mdelay(500);}/**************************************************************************** * Name: c5471_reset * * Description * ****************************************************************************/static void c5471_reset(struct c5471_driver_s *c5471){#if (CONFIG_C5471_ETHERNET_PHY == ETHERNET_PHY_LU3X31T_T64)  ndbg("EIM reset\n");  c5471_eimreset(c5471);#endif  ndbg("PHY init\n");  c5471_phyinit();  ndbg("EIM config\n");  c5471_eimconfig(c5471);}/**************************************************************************** * Name: c5471_macassign * * Description *    Set the mac address of our CPU ether port so that when the SWITCH *    receives packets from the PROMISCUOUS ENET0 it will switch them to the *    CPU port and cause a packet arrival event on the Switch's CPU TX queue *    when an address match occurs. The CPU port is not PROMISCUOUS and wants *    to see only packets specifically addressed to this device. * ****************************************************************************/static void c5471_macassign(struct c5471_driver_s *c5471){  struct uip_driver_s *dev = &c5471->c_dev;  uint8 *mptr = dev->d_mac.ether_addr_octet;  register uint32 tmp;  ndbg("MAC: %0x:%0x:%0x:%0x:%0x:%0x\n",        mptr[0], mptr[1], mptr[2], mptr[3], mptr[4], mptr[5]);  /* Set CPU port MAC address. S/W will only see incoming packets that match   * this destination address.   */  tmp = (((uint32)mptr[0]) << 8) | ((uint32)mptr[1]);  putreg32(tmp, EIM_CPU_DAHI);  tmp = (((uint32)mptr[2]) << 24) | (((uint32)mptr[3]) << 16) |        (((uint32)mptr[4]) <<  8) |  ((uint32)mptr[5]);  putreg32(tmp, EIM_CPU_DALO);#if 0  /* Set the ENET MAC address */  putreg32(getreg32(EIM_CPU_DAHI), ENET0_PARHI);  putreg32(getreg32(EIM_CPU_DALO), ENET0_PARLO);  putreg32(getreg32(EIM_CPU_DAHI), ENET0_LARHI);  putreg32(getreg32(EIM_CPU_DALO), ENET0_LARLO);#else  /* ENET MAC assignment not needed for its PROMISCUOUS mode */   putreg32(0x00000000, ENET0_PARHI);  putreg32(0x00000000, ENET0_PARLO);  putreg32(0x00000000, ENET0_LARHI);  putreg32(0x00000000, ENET0_LARLO);#endif}/**************************************************************************** * Public Functions ****************************************************************************//**************************************************************************** * Function: c5471_initialize * * Description: *   Initialize the Ethernet driver * * Parameters: *   None * * Returned Value: *   OK on success; Negated errno on failure. * * Assumptions: * ****************************************************************************//* Initialize the DM90x0 chip and driver */void up_netinitialize(void){  /* Attach the IRQ to the driver */  if (irq_attach(C5471_IRQ_ETHER, c5471_interrupt))    {      /* We could not attach the ISR to the ISR */      nlldbg("irq_attach() failed\n");      return;    }  /* Initialize the driver structure */  memset(g_c5471, 0, CONFIG_C5471_NET_NINTERFACES*sizeof(struct c5471_driver_s));  g_c5471[0].c_dev.d_ifup    = c5471_ifup;     /* I/F down callback */  g_c5471[0].c_dev.d_ifdown  = c5471_ifdown;   /* I/F up (new IP address) callback */  g_c5471[0].c_dev.d_txavail = c5471_txavail;  /* New TX data callback */  g_c5471[0].c_dev.d_private = (void*)g_c5471; /* Used to recover private state from dev */  /* Create a watchdog for timing polling for and timing of transmisstions */  g_c5471[0].c_txpoll       = wd_create();   /* Create periodic poll timer */  g_c5471[0].c_txtimeout    = wd_create();   /* Create TX timeout timer */  /* Register the device with the OS so that socket IOCTLs can be performed */  (void)netdev_register(&g_c5471[0].c_dev);}#endif /* CONFIG_NET */

⌨️ 快捷键说明

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