8.发送数据
dm9000_start_xmit函数中获得要发送的数据字节数,并调用dm9000_send_packet来发送数据。
- static void dm9000_send_packet(struct net_device *dev,
- int ip_summed,
- u16 pkt_len)
- {
- board_info_t *dm = to_dm9000_board(dev);
- /* The DM9000 is not smart enough to leave fragmented packets alone. */
- if (dm->ip_summed != ip_summed) {
- if (ip_summed == CHECKSUM_NONE)
- iow(dm, DM9000_TCCR, 0);
- else
- iow(dm, DM9000_TCCR, TCCR_IP | TCCR_UDP | TCCR_TCP);
- dm->ip_summed = ip_summed;
- }
- /* Set TX length to DM9000 *///设置发送数据的长度到TXPLL\TXPLH中
- iow(dm, DM9000_TXPLL, pkt_len);
- iow(dm, DM9000_TXPLH, pkt_len >> 8);
- /* Issue TX polling command *///设置发送寄存器的发送控制位,启动发送数据
- iow(dm, DM9000_TCR, TCR_TXREQ); /* Cleared after TX complete */
- }
9.发送超时函数
发送数据时并不一定会成功,系统会调用dm9000_timeout函数。当传输数据超时时,意味发送操作失败或硬件进入未知状态。在超时函数中会调用netif_wake_queue()函数来重新启动设备发送队列。
- static void dm9000_timeout(struct net_device *dev)
- {
- board_info_t *db = netdev_priv(dev);
- u8 reg_save;
- unsigned long flags;
- /* Save previous register address */
- reg_save = readb(db->io_addr);
- spin_lock_irqsave(&db->lock, flags);
- netif_stop_queue(dev);
- dm9000_reset(db);
- dm9000_init_dm9000(dev);
- /* We can accept TX packets again */
- dev->trans_start = jiffies; /* prevent tx timeout */
- netif_wake_queue(dev); //重启发送队列
- /* Restore previous register address */
- writeb(reg_save, db->io_addr);
- spin_unlock_irqrestore(&db->lock, flags);
- }
由此,
netif_wake_queue()函数与netif_stop_queue()是数据发送流程中要调用的两个重要的函数,分别用于唤醒和阻止上层向下层传送数据包。原型定义于include/linux/netdevice.h中。
10.发送中断处理函数
当一个数据包发送完成后会产生一个中断,进入中断处理函数。
- static void dm9000_tx_done(struct net_device *dev, board_info_t *db)
- {
- int tx_status = ior(db, DM9000_NSR); /* Got TX status */
- if (tx_status & (NSR_TX2END | NSR_TX1END)) { //检测一个数据包发送完毕
- /* One packet sent complete */
- db->tx_pkt_cnt--; //待发送的数据包数减1
- dev->stats.tx_packets++;//已发送数据包加1
- if (netif_msg_tx_done(db))
- dev_dbg(db->dev, "tx done, NSR %02x\n", tx_status);
- /* Queue packet check & send */
- if (db->tx_pkt_cnt > 0) //如果还有数据包,则继续发送
- dm9000_send_packet(dev, db->queue_ip_summed,
- db->queue_pkt_len);
- netif_wake_queue(dev); //启动发送队列
- }
- }
阅读(1026) | 评论(0) | 转发(0) |