Chinaunix首页 | 论坛 | 博客
  • 博客访问: 13547
  • 博文数量: 4
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 10
  • 用 户 组: 普通用户
  • 注册时间: 2015-09-23 09:43
文章分类
文章存档

2016年(4)

我的朋友
最近访客

分类: LINUX

2016-08-10 11:33:34

原文地址:dm9000网卡驱动分析3 作者:zhongli_i

8.发送数据
dm9000_start_xmit函数中获得要发送的数据字节数,并调用dm9000_send_packet来发送数据。

点击(此处)折叠或打开

  1. static void dm9000_send_packet(struct net_device *dev,
  2.              int ip_summed,
  3.              u16 pkt_len)
  4. {
  5.     board_info_t *dm = to_dm9000_board(dev);

  6.     /* The DM9000 is not smart enough to leave fragmented packets alone. */
  7.     if (dm->ip_summed != ip_summed) {
  8.         if (ip_summed == CHECKSUM_NONE)
  9.             iow(dm, DM9000_TCCR, 0);
  10.         else
  11.             iow(dm, DM9000_TCCR, TCCR_IP | TCCR_UDP | TCCR_TCP);
  12.         dm->ip_summed = ip_summed;
  13.     }

  14.     /* Set TX length to DM9000 *///设置发送数据的长度到TXPLL\TXPLH中
  15.     iow(dm, DM9000_TXPLL, pkt_len);
  16.     iow(dm, DM9000_TXPLH, pkt_len >> 8);

  17.     /* Issue TX polling command *///设置发送寄存器的发送控制位,启动发送数据
  18.     iow(dm, DM9000_TCR, TCR_TXREQ);    /* Cleared after TX complete */
  19. }

9.发送超时函数
发送数据时并不一定会成功,系统会调用dm9000_timeout函数。当传输数据超时时,意味发送操作失败或硬件进入未知状态。在超时函数中会调用netif_wake_queue()函数来重新启动设备发送队列。

点击(此处)折叠或打开

  1. static void dm9000_timeout(struct net_device *dev)
  2. {
  3.     board_info_t *db = netdev_priv(dev);
  4.     u8 reg_save;
  5.     unsigned long flags;

  6.     /* Save previous register address */
  7.     reg_save = readb(db->io_addr);
  8.     spin_lock_irqsave(&db->lock, flags);

  9.     netif_stop_queue(dev);
  10.     dm9000_reset(db);
  11.     dm9000_init_dm9000(dev);
  12.     /* We can accept TX packets again */
  13.     dev->trans_start = jiffies; /* prevent tx timeout */
  14.     netif_wake_queue(dev); //重启发送队列

  15.     /* Restore previous register address */
  16.     writeb(reg_save, db->io_addr);
  17.     spin_unlock_irqrestore(&db->lock, flags);
  18. }
由此,netif_wake_queue()函数与netif_stop_queue()是数据发送流程中要调用的两个重要的函数,分别用于唤醒和阻止上层向下层传送数据包。原型定义于include/linux/netdevice.h中。

10.发送中断处理函数
当一个数据包发送完成后会产生一个中断,进入中断处理函数。

点击(此处)折叠或打开

  1. static void dm9000_tx_done(struct net_device *dev, board_info_t *db)
  2. {
  3.     int tx_status = ior(db, DM9000_NSR);    /* Got TX status */

  4.     if (tx_status & (NSR_TX2END | NSR_TX1END)) { //检测一个数据包发送完毕
  5.         /* One packet sent complete */
  6.         db->tx_pkt_cnt--;  //待发送的数据包数减1
  7.         dev->stats.tx_packets++;//已发送数据包加1

  8.         if (netif_msg_tx_done(db))
  9.             dev_dbg(db->dev, "tx done, NSR %02x\n", tx_status);

  10.         /* Queue packet check & send */
  11.         if (db->tx_pkt_cnt > 0) //如果还有数据包,则继续发送
  12.             dm9000_send_packet(dev, db->queue_ip_summed,
  13.                      db->queue_pkt_len);
  14.         netif_wake_queue(dev); //启动发送队列
  15.     }
  16. }

阅读(1026) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~