/*分析DM9000发生数据函数**/
/*
* Hardware start transmission.
* Send a packet to media from the upper layer.
*/
static int
dm9000_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
unsigned long flags;
board_info_t *db = netdev_priv(dev);
dm9000_dbg(db, 3, "%s:\n", __func__);
if (db->tx_pkt_cnt > 1)
return NETDEV_TX_BUSY;
spin_lock_irqsave(&db->lock, flags);
/* Move data to DM9000 TX RAM */
//写数据到DM9000 Tx RAM中, 写地址自动增加
writeb(DM9000_MWCMD, db->io_addr);
/*将skb中的数据写入寄存器,然后发送字节改变*/
(db->outblk)(db->io_data, skb->data, skb->len);
dev->stats.tx_bytes += skb->len;
db->tx_pkt_cnt++;
/*第一个发送包立刻发送, 第二个排列到发送队列中去*/
/* TX control: First packet immediately send, second packet queue */
if (db->tx_pkt_cnt == 1) {
dm9000_send_packet(dev, skb->ip_summed, skb->len);
} else {
/* Second packet */
db->queue_pkt_len = skb->len;
db->queue_ip_summed = skb->ip_summed;
/*告诉网络协议栈,停止发送数据。*/
netif_stop_queue(dev);
}
spin_unlock_irqrestore(&db->lock, flags);
/* free this SKB */
/*释放skb*/
dev_kfree_skb(skb);
return NETDEV_TX_OK;
}
/*当发送完成后,会触发一次发送完成的中断。 当然要去中断处理函数中*/
static irqreturn_t dm9000_interrupt(int irq, void *dev_id)
{
struct net_device *dev = dev_id;
board_info_t *db = netdev_priv(dev);
int int_status;
unsigned long flags;
u8 reg_save;
dm9000_dbg(db, 3, "entering %s\n", __func__);
/* A real interrupt coming */
/* holders of db->lock must always block IRQs */
spin_lock_irqsave(&db->lock, flags);
/* Save previous register address */
reg_save = readb(db->io_addr); //存储以前的地址
/* Disable all interrupts */ //屏蔽所有中断
iow(db, DM9000_IMR, IMR_PAR);
/* Got DM9000 interrupt status */
int_status = ior(db, DM9000_ISR); /* Got ISR */
iow(db, DM9000_ISR, int_status); /* Clear ISR status */
if (netif_msg_intr(db))
dev_dbg(db->dev, "interrupt status %02x\n", int_status);
/* Received the coming packet */ //接受中断发生
if (int_status & ISR_PRS)
dm9000_rx(dev);
/* Trnasmit Interrupt check */
if (int_status & ISR_PTS) //检测是否发送完成
dm9000_tx_done(dev, db);
if (db->type != TYPE_DM9000E) {
if (int_status & ISR_LNKCHNG) {
/* fire a link-change request */
schedule_delayed_work(&db->phy_poll, 1);
}
}
/* Re-enable interrupt mask */
iow(db, DM9000_IMR, db->imr_all); //使能中断
/* Restore previous register address */
writeb(reg_save, db->io_addr); //恢复以前的地址
spin_unlock_irqrestore(&db->lock, flags);
return IRQ_HANDLED;
}
/*分析中断发送完成处理函数*/
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--;
dev->stats.tx_packets++;
if (netif_msg_tx_done(db))
dev_dbg(db->dev, "tx done, NSR %02x\n", tx_status);
/* Queue packet check & send */ //如果超过2个,进入队列。发送
if (db->tx_pkt_cnt > 0)
dm9000_send_packet(dev, db->queue_ip_summed,
db->queue_pkt_len);
netif_wake_queue(dev); //唤醒发送队列
}
}
/*
* 总结:
1. 通知网络协议栈,停止发送队列
2. 写skb数据到寄存器中去
3. 释放skb资源
4. 当发送完成后,唤醒发送队列
*/