DM9000网卡驱动深度分析

时间:2023-03-10 05:57:22
DM9000网卡驱动深度分析

一、dm9000_porbe函数分析

不同于u-boot代码,tq2440中的DM9000更加复杂,需要分析的点也很多:

  1. /*
  2. * Search DM9000 board, allocate space and register it
  3. */
  4. static int __devinit
  5. dm9000_probe(struct platform_device *pdev)
  6. {
  7. struct dm9000_plat_data *pdata = pdev->dev.platform_data;
  8. struct board_info *db;    /* Point a board information structure */
  9. struct net_device *ndev;
  10. const unsigned char *mac_src;
  11. int ret = 0;
  12. int iosize;
  13. int i;
  14. u32 id_val;
  15. #if defined(CONFIG_ARCH_S3C2410)
  16. unsigned int oldval_bwscon = *(volatile unsigned int *)S3C2410_BWSCON;
  17. unsigned int oldval_bankcon4 = *(volatile unsigned int *)S3C2410_BANKCON4;
  18. #endif
  19. /* Init network device */
  20. ndev = alloc_etherdev(sizeof(struct board_info));                                     //分配netdev结构
  21. if (!ndev) {
  22. dev_err(&pdev->dev, "could not allocate device.\n");
  23. return -ENOMEM;
  24. }
  25. SET_NETDEV_DEV(ndev, &pdev->dev);
  26. dev_dbg(&pdev->dev, "dm9000_probe()\n");                     //不管
  27. #if defined(CONFIG_ARCH_S3C2410)                                 //2410可以不管
  28. //    *((volatile unsigned int *)S3C2410_BWSCON) = (oldval_bwscon & ~(3<<16)) | S3C2410_BWSCON_DW4_16 | S3C2410_BWSCON_WS4 | S3C2410_BWSCON_ST4;
  29. *((volatile unsigned int *)S3C2410_BWSCON) = (oldval_bwscon & ~(3<<16)) | S3C2410_BWSCON_DW4_16 ;
  30. *((volatile unsigned int *)S3C2410_BANKCON4) = 0x1f7c;
  31. #endif
  32. /* setup board info structure */
  33. db = netdev_priv(ndev);
  34. memset(db, 0, sizeof(*db));
  35. db->dev = &pdev->dev;
  36. db->ndev = ndev;
  37. spin_lock_init(&db->lock);
  38. mutex_init(&db->addr_lock);
  39. INIT_DELAYED_WORK(&db->phy_poll, dm9000_poll_work);
  40. db->addr_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);                  //获取平台资源,对应的platform_driver
  41. db->data_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
  42. db->irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
  43. ..................
  44. }

从这里可以引出之前的知识点:平台设备和平台驱动的相关知识。在dm9000.c中有:

  1. static struct platform_driver dm9000_driver = {
  2. .driver    = {
  3. .name = "dm9000",                                                //这个平台驱动通过name和tq2440中的dm9000的驱动设备结构对接
  4. .owner     = THIS_MODULE,
  5. },
  6. .probe = dm9000_probe,
  7. .remove = __devexit_p(dm9000_drv_remove),
  8. .suspend = dm9000_drv_suspend,
  9. .resume = dm9000_drv_resume,
  10. };

在arch/arm/mach-tq2440.c:

  1. struct platform_device s3c_device_dm9000 = {
  2. .name        = "dm9000",                                          //这里有同样的name来实现
  3. .id            = 0,
  4. .num_resources    = ARRAY_SIZE(s3c_dm9k_resource),
  5. .resource        = s3c_dm9k_resource,                             //这里保存着dm9000硬件的资源
  6. .dev            = {
  7. .platform_data = &s3c_dm9k_platdata,
  8. }
  9. };

同样在此文件中:

  1. static struct resource s3c_dm9k_resource[] = {
  2. [0] = {                                               //用的片选4
  3. .start    = S3C2410_CS4,                          //这里的起始地址是0x20000000和网上一些0x20000300不一样。wu'suo
  4. .end    = S3C2410_CS4 + 3,                        //.end为什么尾地址是+3?因为一个地址需要四个字节。这是根据网卡来定义的
  5. .flags    = IORESOURCE_MEM,
  6. },
  7. [1] = {                                               //0x20000004~0x20000007?
  8. .start    = S3C2410_CS4 + 4,                      //这里的4意味着地址线2等于1,设置了cmd为高位,是数据内容
  9. .end    = S3C2410_CS4 + 4 + 3,
  10. .flags    = IORESOURCE_MEM,
  11. },
  12. [2] = {
  13. .start    = IRQ_EINT7,                            //对应的中断信息
  14. .end    = IRQ_EINT7,
  15. .flags    = IORESOURCE_IRQ | IRQF_TRIGGER_RISING,
  16. }
  17. };

回来继续看dm9000.c中的probe函数:

  1. db->addr_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  2. db->data_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
  3. db->irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
  4. if (db->addr_res == NULL || db->data_res == NULL ||
  5. db->irq_res == NULL) {
  6. dev_err(db->dev, "insufficient resources\n");
  7. ret = -ENOENT;
  8. goto out;
  9. }
  10. iosize = res_size(db->addr_res);
  11. db->addr_req = request_mem_region(db->addr_res->start, iosize,
  12. pdev->name);
  13. if (db->addr_req == NULL) {
  14. dev_err(db->dev, "cannot claim address reg area\n");
  15. ret = -EIO;
  16. goto out;
  17. }
  18. db->io_addr = ioremap(db->addr_res->start, iosize);                    //将地址信息重映射
  19. if (db->io_addr == NULL) {
  20. dev_err(db->dev, "failed to ioremap address reg\n");
  21. ret = -EINVAL;
  22. goto out;
  23. }
  24. iosize = res_size(db->data_res);
  25. db->data_req = request_mem_region(db->data_res->start, iosize,
  26. pdev->name);
  27. if (db->data_req == NULL) {
  28. dev_err(db->dev, "cannot claim data reg area\n");
  29. ret = -EIO;
  30. goto out;
  31. }
  32. db->io_data = ioremap(db->data_res->start, iosize);               //将数据信息重映射
  33. if (db->io_data == NULL) {
  34. dev_err(db->dev, "failed to ioremap data reg\n");
  35. ret = -EINVAL;
  36. goto out;
  37. }
  38. .........................
  39. id_val = ior(db, DM9000_CHIPR);                                    //读取芯片信息
  40. //    dev_dbg(db->dev, "dm9000 revision 0x%02x io_mode %02x \n", id_val, db->io_mode);
  41. printk(KERN_INFO "dm9000 revision 0x%02x io_mode %02x \n", id_val, db->io_mode);
  42. switch (id_val) {
  43. case CHIPR_DM9000A:
  44. db->type = TYPE_DM9000A;
  45. break;
  46. case CHIPR_DM9000B:
  47. db->type = TYPE_DM9000B;
  48. break;
  49. case CHIPR_DM9000C:
  50. db->type = TYPE_DM9000C;
  51. break;
  52. default:
  53. dev_dbg(db->dev, "ID %02x => defaulting to DM9000E\n", id_val);
  54. db->type = TYPE_DM9000E;
  55. }
  56. /* from this point we assume that we have found a DM9000 */
  57. /* driver system function */                                                //下面在设置dm9000的操作函数集了
  58. ether_setup(ndev);
  59. ndev->open         = &dm9000_open;
  60. ndev->hard_start_xmit = &dm9000_start_xmit;
  61. ndev->tx_timeout = &dm9000_timeout;
  62. ndev->watchdog_timeo = msecs_to_jiffies(watchdog);
  63. ndev->stop         = &dm9000_stop;
  64. ndev->set_multicast_list = &dm9000_hash_table;
  65. ndev->ethtool_ops     = &dm9000_ethtool_ops;
  66. ndev->do_ioctl         = &dm9000_ioctl;
  67. #ifdef CONFIG_NET_POLL_CONTROLLER
  68. ndev->poll_controller     = &dm9000_poll_controller;
  69. #endif
  70. db->msg_enable = NETIF_MSG_LINK;
  71. db->mii.phy_id_mask = 0x1f;
  72. db->mii.reg_num_mask = 0x1f;
  73. db->mii.force_media = 0;
  74. db->mii.full_duplex = 0;
  75. db->mii.dev     = ndev;
  76. db->mii.mdio_read = dm9000_phy_read;
  77. db->mii.mdio_write = dm9000_phy_write;
  78. #if defined(CONFIG_ARCH_S3C2410)
  79. printk("Now use the default MAC address: 10:23:45:67:89:ab\n");
  80. mac_src = "EmbedSky";
  81. ndev->dev_addr[0] = 0x10;
  82. ndev->dev_addr[1] = 0x23;
  83. ndev->dev_addr[2] = 0x45;
  84. ndev->dev_addr[3] = 0x67;
  85. ndev->dev_addr[4] = 0x89;
  86. ndev->dev_addr[5] = 0xab;
  87. #else
  88. mac_src = "eeprom";
  89. /* try reading the node address from the attached EEPROM */         //读取MAC地址,从EEPROM中
  90. for (i = 0; i < 6; i += 2)
  91. dm9000_read_eeprom(db, i / 2, ndev->dev_addr+i);
  92. if (!is_valid_ether_addr(ndev->dev_addr) && pdata != NULL) {
  93. mac_src = "platform data";
  94. memcpy(ndev->dev_addr, pdata->dev_addr, 6);
  95. }
  96. if (!is_valid_ether_addr(ndev->dev_addr)) {
  97. /* try reading from mac */
  98. mac_src = "chip";
  99. for (i = 0; i < 6; i++)
  100. ndev->dev_addr[i] = ior(db, i+DM9000_PAR);
  101. }
  102. if (!is_valid_ether_addr(ndev->dev_addr))
  103. dev_warn(db->dev, "%s: Invalid ethernet MAC address. Please "
  104. "set using ifconfig\n", ndev->name);
  105. #endif
  106. platform_set_drvdata(pdev, ndev);
  107. ret = register_netdev(ndev);                                           //注册网卡驱动
  108. if (ret == 0)
  109. printk(KERN_INFO "%s: dm9000%c at %p,%p IRQ %d MAC: %pM (%s)\n",
  110. ndev->name, dm9000_type_to_char(db->type),
  111. db->io_addr, db->io_data, ndev->irq,
  112. ndev->dev_addr, mac_src);
  113. return 0;
  114. out:
  115. #if defined(CONFIG_ARCH_S3C2410)
  116. *(volatile unsigned int *)S3C2410_BWSCON = oldval_bwscon;
  117. *(volatile unsigned int *)S3C2410_BANKCON4 = oldval_bankcon4;
  118. #endif
  119. dev_err(db->dev, "not found (%d).\n", ret);
  120. dm9000_release_board(pdev, db);
  121. free_netdev(ndev);
  122. return ret;
  123. }

二、DM9000_OPEN函数分析

在probe中没有太多的dm9000的初始化代码,都写在了open中(这个open函数在ifconfig eth0 192.168.1.1时调用):

  1. /*
  2. * Open the interface.
  3. * The interface is opened whenever "ifconfig" actives it.
  4. */
  5. static int
  6. dm9000_open(struct net_device *dev)
  7. {
  8. board_info_t *db = netdev_priv(dev);
  9. unsigned long irqflags = db->irq_res->flags & IRQF_TRIGGER_MASK;
  10. if (netif_msg_ifup(db))
  11. dev_dbg(db->dev, "enabling %s\n", dev->name);
  12. /* If there is no IRQ type specified, default to something that
  13. * may work, and tell the user that this is a problem */
  14. if (irqflags == IRQF_TRIGGER_NONE)
  15. dev_warn(db->dev, "WARNING: no IRQ resource flags set.\n");
  16. irqflags |= IRQF_SHARED;
  17. if (request_irq(dev->irq, &dm9000_interrupt, irqflags, dev->name, dev))                      //注册网卡驱动的中断处理函数
  18. return -EAGAIN;
  19. /* Initialize DM9000 board */
  20. //    dm9000_reset(db);
  21. dm9000_init_dm9000(dev);                                                                     //网卡初始化在这里
  22. /* Init driver variable */
  23. db->dbug_cnt = 0;
  24. mii_check_media(&db->mii, netif_msg_link(db), 1);
  25. netif_start_queue(dev);                                                                      //启动发送队列
  26. dm9000_schedule_poll(db);
  27. return 0;
  28. }

DM9000初始化:

①分配net_device结构

②从platform_device中获取地址,中断号

③把获取到的地址映射为虚拟地址

④读取芯片类型

⑤设置操作函数集

⑥注册网卡驱动



三、dm9000_start_xmit发送函数分析


dm9000_start_xmit:

  1. /*
  2. * Hardware start transmission.
  3. * Send a packet to media from the upper layer.
  4. */
  5. static int
  6. dm9000_start_xmit(struct sk_buff *skb, struct net_device *dev)
  7. {
  8. unsigned long flags;
  9. board_info_t *db = netdev_priv(dev);
  10. int save_mwr, check_mwr, calc_mwr;
  11. dm9000_dbg(db, 3, "%s:\n", __func__);
  12. if ((db->tx_pkt_cnt > 0) || !netif_carrier_ok(dev))
  13. return 1;
  14. spin_lock_irqsave(&db->lock, flags);
  15. netif_stop_queue(dev);                                                                                     //通知协议栈,暂停向驱动传送数据
  16. db->tx_pkt_cnt++;
  17. dev->stats.tx_bytes += skb->len;
  18. dev->stats.tx_packets++;
  19. save_mwr = (ior(db, 0xfb) << 8) | ior(db, 0xfa);
  20. calc_mwr = save_mwr + skb->len;
  21. if(skb->len & 0x01) calc_mwr++;
  22. if(calc_mwr > 0x0bff ) calc_mwr -= 0x0c00;
  23. /* Set TX length to DM9000 */                                                                              //获取发送长度
  24. iow(db, DM9000_TXPLL, skb->len);
  25. iow(db, DM9000_TXPLH, skb->len >> 8);
  26. /* Move data to DM9000 TX RAM */                                                                           //将要发送的数据发送入缓存
  27. writeb(DM9000_MWCMD, db->io_addr);
  28. (db->outblk)(db->io_data, skb->data, skb->len);                                                            //skb->data,skb->len分别指向结构体数据的头和尾
  29. /* Issue TX polling command */
  30. iow(db, DM9000_TCR, TCR_TXREQ);    /* Cleared after TX complete */                                         //清除发送位
  31. dev->trans_start = jiffies;    /* save the time stamp */
  32. check_mwr = (ior(db, 0xfb) << 8) | ior(db, 0xfa);
  33. if(calc_mwr != check_mwr)
  34. {
  35. printk(KERN_INFO "TX: fifo error %04x %04x %04x %04x\n", save_mwr, skb->len, calc_mwr, check_mwr);
  36. iow(db, 0xfb, (calc_mwr >> 8) & 0xff);
  37. iow(db, 0xfa, calc_mwr & 0xff);
  38. }
  39. spin_unlock_irqrestore(&db->lock, flags);
  40. /* free this SKB */
  41. dev_kfree_skb(skb);                                                                                          //释放SKB结构
  42. return 0;
  43. }

发送完成产生中断(dm9000_interrupt):

  1. static irqreturn_t dm9000_interrupt(int irq, void *dev_id)
  2. {
  3. struct net_device *dev = dev_id;
  4. board_info_t *db = netdev_priv(dev);
  5. int int_status;
  6. unsigned long flags;
  7. u8 reg_save;
  8. dm9000_dbg(db, 3, "entering %s\n", __func__);
  9. /* A real interrupt coming */
  10. /* holders of db->lock must always block IRQs */
  11. spin_lock_irqsave(&db->lock, flags);
  12. /* Save previous register address */
  13. reg_save = readb(db->io_addr);
  14. /* Disable all interrupts */
  15. iow(db, DM9000_IMR, IMR_PAR);
  16. /* Got DM9000 interrupt status */
  17. int_status = ior(db, DM9000_ISR);    /* Got ISR */
  18. iow(db, DM9000_ISR, int_status);    /* Clear ISR status */
  19. if (netif_msg_intr(db))
  20. dev_dbg(db->dev, "interrupt status %02x\n", int_status);
  21. /* Received the coming packet */
  22. if (int_status & ISR_PRS)
  23. dm9000_rx(dev);                                                               //接收中断
  24. int_status |= ior(db, DM9000_ISR);    /* Got ISR */
  25. /* Trnasmit Interrupt check */
  26. if (int_status & ISR_PTS)
  27. {
  28. iow(db, DM9000_ISR, ISR_PTS);
  29. dm9000_tx_done(dev, db);                                                      //发送中断
  30. }
  31. if (db->type != TYPE_DM9000E) {
  32. if (int_status & ISR_LNKCHNG) {
  33. /* fire a link-change request */
  34. schedule_delayed_work(&db->phy_poll, 1);
  35. }
  36. }
  37. /* Re-enable interrupt mask */
  38. iow(db, DM9000_IMR, db->imr_all);
  39. /* Restore previous register address */
  40. writeb(reg_save, db->io_addr);
  41. spin_unlock_irqrestore(&db->lock, flags);
  42. return IRQ_HANDLED;
  43. }

发送函数完成后进入中断dm9000_tx_done:

  1. /*
  2. * DM9000 interrupt handler
  3. * receive the packet to upper layer, free the transmitted packet
  4. */
  5. static void dm9000_tx_done(struct net_device *dev, board_info_t *db)
  6. {
  7. int tx_status = ior(db, DM9000_TCR);    /* Got TX status */                           //获取中断状态
  8. if(tx_status & TCR_TXREQ)                                                             //查看发送是否出错
  9. {
  10. dev->stats.rx_fifo_errors++;                                                      //错误计数加1
  11. }
  12. else
  13. {
  14. db->tx_pkt_cnt = 0;
  15. dev->trans_start = 0;
  16. netif_wake_queue(dev);                                                            //调用netif_wake_queue(),通知协议栈发送数据
  17. }
  18. }

dm9000_rx():

  1. /*
  2. * Received a packet and pass to upper layer
  3. */
  4. static void
  5. dm9000_rx(struct net_device *dev)
  6. {
  7. board_info_t *db = netdev_priv(dev);
  8. struct dm9000_rxhdr rxhdr;
  9. struct sk_buff *skb;
  10. u8 rxbyte, *rdptr;
  11. bool GoodPacket;
  12. int RxLen;
  13. int save_mrr, check_mrr, calc_mrr;
  14. /* Check packet ready or not */
  15. do {
  16. ior(db, DM9000_MRCMDX);    /* Dummy read */                                                     //空读
  17. save_mrr = (ior(db, 0xf5) << 8) | ior(db, 0xf4);
  18. /* Get most updated data */
  19. rxbyte = ior(db, DM9000_MRCMDX);                                                                //查看接收状态
  20. if(DM9000_PKT_RDY != rxbyte)                                                                    //是否已经ready
  21. {
  22. /* Status check: this byte must be 0 or 1 */
  23. if (rxbyte) {
  24. //                dev_warn(db->dev, "status check fail: %d\n", rxbyte);
  25. printk(KERN_INFO "status check fail: %d\n", rxbyte);
  26. iow(db, DM9000_RCR, 0x00);    /* Stop Device */
  27. iow(db, DM9000_IMR, IMR_PAR);    /* Stop INT request */
  28. dm9000_init_dm9000(dev);
  29. }
  30. return;
  31. }
  32. /* A packet ready now & Get status/length */
  33. GoodPacket = true;
  34. writeb(DM9000_MRCMD, db->io_addr);                                                                //
  35. (db->inblk)(db->io_data, &rxhdr, sizeof(rxhdr));                                                  //dm9000_rxhdr结构中有rx_len,接收长度
  36. calc_mrr = save_mrr + 4;
  37. if(calc_mrr > 0x3fff) calc_mrr -= 0x3400;
  38. check_mrr = (ior(db, 0xf5) << 8) | ior(db, 0xf4);
  39. if(calc_mrr != check_mrr)
  40. {
  41. printk(KERN_INFO "RX: 4 byte error %04x %04x %04x \n", save_mrr, calc_mrr, check_mrr);
  42. iow(db, 0xf5, (save_mrr >> 8) & 0xff);
  43. iow(db, 0xf4, save_mrr & 0xff);
  44. continue;
  45. }
  46. writeb(DM9000_MRCMD, db->io_addr);
  47. RxLen = le16_to_cpu(rxhdr.RxLen);
  48. calc_mrr = save_mrr + 4 + RxLen;
  49. if(RxLen & 0x01) calc_mrr++;
  50. if(calc_mrr > 0x3fff) calc_mrr -= 0x3400;
  51. if (netif_msg_rx_status(db))
  52. dev_dbg(db->dev, "RX: status %02x, length %04x\n",
  53. rxhdr.RxStatus, RxLen);
  54. /* Packet Status check */                                                                     //判断长度
  55. if (RxLen < 0x40) {
  56. GoodPacket = false;
  57. if (netif_msg_rx_err(db))
  58. dev_dbg(db->dev, "RX: Bad Packet (runt)\n");
  59. }
  60. if (RxLen > DM9000_PKT_MAX) {
  61. dev_dbg(db->dev, "RST: RX Len:%x\n", RxLen);
  62. }
  63. /* rxhdr.RxStatus is identical to RSR register. */                                             //读取状态看有没有出错
  64. if (rxhdr.RxStatus & (RSR_FOE | RSR_CE | RSR_AE |
  65. RSR_PLE | RSR_RWTO |
  66. RSR_LCS | RSR_RF)) {
  67. GoodPacket = false;
  68. if (rxhdr.RxStatus & RSR_FOE) {
  69. if (netif_msg_rx_err(db))
  70. dev_dbg(db->dev, "fifo error\n");
  71. dev->stats.rx_fifo_errors++;
  72. }
  73. if (rxhdr.RxStatus & RSR_CE) {
  74. if (netif_msg_rx_err(db))
  75. dev_dbg(db->dev, "crc error\n");
  76. dev->stats.rx_crc_errors++;
  77. }
  78. if (rxhdr.RxStatus & RSR_RF) {
  79. if (netif_msg_rx_err(db))
  80. dev_dbg(db->dev, "length error\n");
  81. dev->stats.rx_length_errors++;
  82. }
  83. }
  84. /* Move data from DM9000 */
  85. if (GoodPacket
  86. && ((skb = dev_alloc_skb(RxLen + 4)) != NULL)) {                                                    //分配skb=接收到的数据长度+4
  87. skb_reserve(skb, 2);                                                                             //skb中的ip包需要4字节对齐,所以skb要保留多2个字节。(以太网包格式)
  88. rdptr = (u8 *) skb_put(skb, RxLen - 4);                                                          //skb的tail指针,数据包长度减4
  89. /* Read received packet from RX SRAM */
  90. (db->inblk)(db->io_data, rdptr, RxLen);                                                          //读取io_data地址到rdptr中
  91. dev->stats.rx_bytes += RxLen;
  92. /* Pass to upper layer */
  93. skb->protocol = eth_type_trans(skb, dev);
  94. netif_rx(skb);                                                                                   //把准备好的skb提交给上层协议
  95. dev->stats.rx_packets++;
  96. check_mrr = (ior(db, 0xf5) << 8) | ior(db, 0xf4);
  97. if(calc_mrr != check_mrr)
  98. {
  99. //                dev_dbg(db->dev, "RX: fifo error %04x %04x %04x %04x\n", save_mrr, RxLen, calc_mrr, check_mrr);
  100. printk(KERN_INFO "RX: fifo error %04x %04x %04x %04x\n", save_mrr, RxLen, calc_mrr, check_mrr);
  101. iow(db, 0xf5, (calc_mrr >> 8) & 0xff);
  102. iow(db, 0xf4, calc_mrr & 0xff);
  103. }
  104. } else {
  105. /* need to dump the packet's data */
  106. iow(db, 0xf5, (calc_mrr >> 8) & 0xff);
  107. iow(db, 0xf4, calc_mrr & 0xff);
  108. }
  109. } while (rxbyte == DM9000_PKT_RDY);
  110. }