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

📄 dm90x0.c

📁 這是一個實時嵌入式作業系統 實作了MCS51 ARM等MCU
💻 C
📖 第 1 页 / 共 4 页
字号:
 * Assumptions: * ****************************************************************************/static inline void dm9x_phymode(struct dm9x_driver_s *dm9x){  uint16 phyreg0;  uint16 phyreg4;#if CONFIG_DM9X_MODE == DM9X_MODE_AUTO  phyreg0 = 0x1200;  /* Auto-negotiation & Restart Auto-negotiation */  phyreg4 = 0x01e1;  /* Default flow control disable*/#elif CONFIG_DM9X_MODE == DM9X_MODE_10MHD  phyreg4 = 0x21;   phyreg0 = 0x1000;#elif CONFIG_DM9X_MODE == DM9X_MODE_10MFD  phyreg4 = 0x41;   phyreg0 = 0x1100;#elif CONFIG_DM9X_MODE == DM9X_MODE_100MHD  phyreg4 = 0x81;   phyreg0 = 0x3000;#elif CONFIG_DM9X_MODE == DM9X_MODE_100MFD  phyreg4 = 0x101;   phyreg0 = 0x3100;#else# error "Recognized PHY mode"#endif  dm9x_phywrite(dm9x, 0, phyreg0);  dm9x_phywrite(dm9x, 4, phyreg4);}/**************************************************************************** * Function: dm9x_ifup * * Description: *   NuttX Callback: Bring up the DM90x0 interface when an IP address is *   provided  * * Parameters: *   dev  - Reference to the NuttX driver state structure * * Returned Value: *   None * * Assumptions: * ****************************************************************************/static int dm9x_ifup(struct uip_driver_s *dev){  struct dm9x_driver_s *dm9x = (struct dm9x_driver_s *)dev->d_private;  uint8 netstatus;  int i;  ndbg("Bringing up: %d.%d.%d.%d\n",       dev->d_ipaddr & 0xff, (dev->d_ipaddr >> 8) & 0xff,       (dev->d_ipaddr >> 16) & 0xff, dev->d_ipaddr >> 24 );  /* Initilize DM90x0 chip */  dm9x_bringup(dm9x);  /* Check link state and media speed (waiting up to 3s for link OK) */  dm9x->dm_b100M = FALSE;  for (i = 0; i < 3000; i++)    {      netstatus = getreg(DM9X_NETS);      if (netstatus & DM9X_NETS_LINKST)        {          /* Link OK... Wait a bit before getting the detected speed */          up_mdelay(200);          netstatus = getreg(DM9X_NETS);          if ((netstatus & DM9X_NETS_SPEED) == 0)            {              dm9x->dm_b100M = TRUE;            }          break;        }      i++;      up_mdelay(1);    }  ndbg("delay: %dmS speed: %s\n", i, dm9x->dm_b100M ? "100M" : "10M");   /* Set and activate a timer process */  (void)wd_start(dm9x->dm_txpoll, DM6X_WDDELAY, dm9x_polltimer, 1, (uint32)dm9x);  /* Enable the DM9X interrupt */  dm9x->dm_bifup = TRUE;  up_enable_irq(CONFIG_DM9X_IRQ);  return OK;}/**************************************************************************** * Function: dm9x_ifdown * * Description: *   NuttX Callback: Stop the interface. * * Parameters: *   dev  - Reference to the NuttX driver state structure * * Returned Value: *   None * * Assumptions: * ****************************************************************************/static int dm9x_ifdown(struct uip_driver_s *dev){  struct dm9x_driver_s *dm9x = (struct dm9x_driver_s *)dev->d_private;  irqstate_t flags;  ndbg("Stopping\n");  /* Disable the DM9X interrupt */  flags = irqsave();  up_disable_irq(CONFIG_DM9X_IRQ);  /* Cancel the TX poll timer and TX timeout timers */  wd_cancel(dm9x->dm_txpoll);  wd_cancel(dm9x->dm_txtimeout);  /* Reset the device */  dm9x_phywrite(dm9x, 0x00, 0x8000);  /* PHY reset */  putreg(DM9X_GPD, 0x01);             /* Power-down PHY (GEPIO0=1) */  putreg(DM9X_IMR, DM9X_IMRDISABLE);  /* Disable all interrupts */  putreg(DM9X_RXC, 0x00);             /* Disable RX */  putreg(DM9X_ISR, DM9X_INT_ALL);     /* Clear interrupt status */  dm9x->dm_bifup = FALSE;  irqrestore(flags);  /* Dump statistics */  dm9x_dumpstatistics(dm9x);  return OK;}/**************************************************************************** * Function: dm9x_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 dm9x_txavail(struct uip_driver_s *dev){  struct dm9x_driver_s *dm9x = (struct dm9x_driver_s *)dev->d_private;  irqstate_t flags;  ndbg("Polling\n");  flags = irqsave();  /* Ignore the notification if the interface is not yet up */  if (dm9x->dm_bifup)    {      /* Check if there is room in the DM90x0 to hold another packet.  In 100M       * mode, that can be 2 packets, otherwise it is a single packet.       */      if (dm9x->dm_ntxpending < 1 || (dm9x->dm_b100M && dm9x->dm_ntxpending < 2))        {          /* If so, then poll uIP for new XMIT data */          (void)uip_poll(&dm9x->dm_dev, dm9x_uiptxpoll);        }    }  irqrestore(flags);  return OK;}/**************************************************************************** * Function: dm9x_bringup * * Description: *   Initialize the dm90x0 chip * * Parameters: *   dm9x  - Reference to the driver state structure * * Returned Value: *   None * * Assumptions: * ****************************************************************************/static void dm9x_bringup(struct dm9x_driver_s *dm9x){  ndbg("Initializing\n");  /* Set the internal PHY power-on, GPIOs normal, and wait 2ms */  putreg(DM9X_GPD, 0x01);  /* Power-down the PHY (GEPIO0=1) */  up_udelay(500);  putreg(DM9X_GPD, 0x00);  /* Preactivate PHY (GPIO0=0 */  up_udelay(20);           /* Wait 20us for PHY power-on ready */  /* Do a software reset and wait 20us (twice).  The reset autoclears   * in 10us; 20us guarantees completion of the reset   */  putreg(DM9X_NETC, (DM9X_NETC_RST|DM9X_NETC_LBK1));  up_udelay(20);  putreg(DM9X_NETC, (DM9X_NETC_RST|DM9X_NETC_LBK1));  up_udelay(20);  /* Configure I/O mode */  switch (getreg(DM9X_ISR) & DM9X_ISR_IOMODEM)    {      case DM9X_ISR_IOMODE8:        dm9x->dm_read    = read8;        dm9x->dm_write   = write8;        dm9x->dm_discard = discard8;        break;      case DM9X_ISR_IOMODE16:        dm9x->dm_read    = read16;        dm9x->dm_write   = write16;        dm9x->dm_discard = discard16;        break;      case DM9X_ISR_IOMODE32:        dm9x->dm_read    = read32;        dm9x->dm_write   = write32;        dm9x->dm_discard = discard32;        break;      default:        break;    }  /* Program PHY operating mode */  dm9x_phymode(dm9x);  /* Program operating mode */  putreg(DM9X_NETC, 0x00);        /* Network control */  putreg(DM9X_TXC, 0x00);         /* Clear TX Polling */  putreg(DM9X_BPTHRES, 0x3f);     /* Less 3kb, 600us */  putreg(DM9X_SMODEC, 0x00);      /* Special mode */  putreg(DM9X_NETS, (DM9X_NETS_WAKEST|DM9X_NETS_TX1END|DM9X_NETS_TX2END)); /* Clear TX status */  putreg(DM9X_ISR, DM9X_INT_ALL); /* Clear interrupt status */#if defined(CONFIG_DM9X_CHECKSUM)  putreg(DM9X_TCCR, 0x07);        /* TX UDP/TCP/IP checksum enable */  putreg(DM9X_RCSR, 0x02);        /* Receive checksum enable */#endif#if defined(CONFIG_DM9X_ETRANS)  putreg(DM9X_ETXCSR, 0x83);#endif  /* Initialize statistics */  dm9x->ncrxpackets   = 0; /* Number of continuous RX packets  */  dm9x->dm_ntxpending = 0; /* Number of pending TX packets */  dm9x_resetstatistics(dm9x);  /* Activate DM9000A/DM9010 */  putreg(DM9X_RXC, DM9X_RXCSETUP | 1); /* RX enable */  putreg(DM9X_IMR, DM9X_IMRENABLE);    /* Enable TX/RX interrupts */}/**************************************************************************** * Function: dm9x_reset * * Description: *   Stop, reset, re-initialize, and restart the DM90x0 chip and driver.  At *   present, the chip is only reset after a TX timeout. * * Parameters: *   dm9x  - Reference to the driver state structure * * Returned Value: *   None * * Assumptions: * ****************************************************************************/static void dm9x_reset(struct dm9x_driver_s *dm9x){  uint8 save;  int i;  /* Cancel the TX poll timer and TX timeout timers */  wd_cancel(dm9x->dm_txpoll);  wd_cancel(dm9x->dm_txtimeout);  /* Save previous register address */  save = (uint8)DM9X_INDEX;#if defined(CONFIG_DM9X_STATS)  dm9x->dm_nresets++;#endif  dm9x_bringup(dm9x);  /* Wait up to 1 second for the link to be OK */  dm9x->dm_b100M = FALSE;  for (i = 0; i < 1000; i++)    {      if (dm9x_phyread(dm9x,0x1) & 0x4)        {          if (dm9x_phyread(dm9x, 0) &0x2000)            {              dm9x->dm_b100M = TRUE;            }          break;        }      up_mdelay(1);    }  /* Restore previous register address */  DM9X_INDEX = save;}/**************************************************************************** * Public Functions ****************************************************************************//**************************************************************************** * Function: dm9x_initialize * * Description: *   Initialize the DM90x0 driver * * Parameters: *   None * * Returned Value: *   OK on success; Negated errno on failure. * * Assumptions: * ****************************************************************************//* Initialize the DM90x0 chip and driver */int dm9x_initialize(void){  uint8 *mptr;  uint16 vid;  uint16 pid;  int i;  int j;  /* Get the chip vendor ID and product ID */  vid = (((uint16)getreg(DM9X_VIDH)) << 8) | (uint16)getreg(DM9X_VIDL);  pid = (((uint16)getreg(DM9X_PIDH)) << 8) | (uint16)getreg(DM9X_PIDL);  nlldbg("I/O base: %08x VID: %04x PID: %04x\n", CONFIG_DM9X_BASE, vid, pid);  /* Check if a DM90x0 chip is recognized at this I/O base */  if (vid != DM9X_DAVICOMVID || (pid != DM9X_DM9000PID && pid != DM9X_DM9010PID))    {      nlldbg("DM90x0 vender/product ID not found at this base address\n");      return -ENODEV;    }  /* Attach the IRQ to the driver */  if (irq_attach(CONFIG_DM9X_IRQ, dm9x_interrupt))    {      /* We could not attach the ISR to the ISR */      nlldbg("irq_attach() failed\n");      return -EAGAIN;    }  /* Initialize the driver structure */  memset(g_dm9x, 0, CONFIG_DM9X_NINTERFACES*sizeof(struct dm9x_driver_s));  g_dm9x[0].dm_dev.d_ifup    = dm9x_ifup;     /* I/F down callback */  g_dm9x[0].dm_dev.d_ifdown  = dm9x_ifdown;   /* I/F up (new IP address) callback */  g_dm9x[0].dm_dev.d_txavail = dm9x_txavail;  /* New TX data callback */  g_dm9x[0].dm_dev.d_private = (void*)g_dm9x; /* Used to recover private state from dev */  /* Create a watchdog for timing polling for and timing of transmisstions */  g_dm9x[0].dm_txpoll       = wd_create();   /* Create periodic poll timer */  g_dm9x[0].dm_txtimeout    = wd_create();   /* Create TX timeout timer */  /* Read the MAC address */  mptr = g_dm9x[0].dm_dev.d_mac.ether_addr_octet;  for (i = 0, j = DM9X_PAB0; i < ETHER_ADDR_LEN; i++, j++)    {      mptr[i] = getreg(j);    }  nlldbg("MAC: %0x:%0x:%0x:%0x:%0x:%0x\n",         mptr[0], mptr[1], mptr[2], mptr[3], mptr[4], mptr[5]);  /* Register the device with the OS so that socket IOCTLs can be performed */  (void)netdev_register(&g_dm9x[0].dm_dev);  return OK;}#endif /* CONFIG_NET && CONFIG_NET_DM90x0 */

⌨️ 快捷键说明

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