Linux内核--从上向下分析驱动程序层
作者:网络转载 发布时间:[ 2013/1/7 10:35:40 ] 推荐标签:
在<Linux内核--Linux内核:从底层向上分析驱动程序层+链路层>中对网络设备结构,网络设备初始化等函数有了初步认识,并列出了设备的发送和接收函数。
设备接口层会调用函数设备驱动层ei_start_xmit()函数发送数据,这里没有详细分析。
static int ei_start_xmit(struct sk_buff *skb, struct device *dev)
{
int e8390_base = dev->base_addr;
struct ei_device *ei_local = (struct ei_device *) dev->priv;//取出网卡设备的私有数据,和具体的网卡型号有关,在ethdev_init()函数中已经分配空间
int length, send_length;
unsigned long flags;
/*
* We normally shouldn't be called if dev->tbusy is set, but the
* existing code does anyway. If it has been too long since the
* last Tx, we assume the board has died and kick it.
*/
if (dev->tbusy) { /* Do timeouts, just like the 8003 driver. */
........................................
........................................
}
/* Sending a NULL skb means some higher layer thinks we've missed an
tx-done interrupt. Caution: dev_tint() handles the cli()/sti()
itself. */
if (skb == NULL) {//该条件似乎不会发生,这用于处理内核中的BUG
dev_tint(dev);//发送设备中的所有缓存的数据包
return 0;
}
length = skb->len;
if (skb->len <= 0)
return 0;
save_flags(flags);
cli();
/* Block a timer-based transmit from overlapping. */
if ((set_bit(0, (void*)&dev->tbusy) != 0) || ei_local->irqlock) {
printk("%s: Tx access conflict. irq=%d lock=%d tx1=%d tx2=%d last=%d
",
dev->name, dev->interrupt, ei_local->irqlock, ei_local->tx1,
ei_local->tx2, ei_local->lasttx);
restore_flags(flags);
return 1;
}
/* Mask interrupts from the ethercard. */
outb(0x00, e8390_base + EN0_IMR);
ei_local->irqlock = 1;
restore_flags(flags);
send_length = ETH_ZLEN < length ? length : ETH_ZLEN;
if (ei_local->pingpong) {
int output_page;
if (ei_local->tx1 == 0) {
output_page = ei_local->tx_start_page;
ei_local->tx1 = send_length;
if (ei_debug && ei_local->tx2 > 0)
printk("%s: idle transmitter tx2=%d, lasttx=%d, txing=%d.
",
dev->name, ei_local->tx2, ei_local->lasttx,
ei_local->txing);
} else if (ei_local->tx2 == 0) {
output_page = ei_local->tx_start_page + 6;
ei_local->tx2 = send_length;
if (ei_debug && ei_local->tx1 > 0)
printk("%s: idle transmitter, tx1=%d, lasttx=%d, txing=%d.
",
dev->name, ei_local->tx1, ei_local->lasttx,
ei_local->txing);
} else { /* We should never get here. */
if (ei_debug)
printk("%s: No Tx buffers free. irq=%d tx1=%d tx2=%d last=%d
",
dev->name, dev->interrupt, ei_local->tx1,
ei_local->tx2, ei_local->lasttx);
ei_local->irqlock = 0;
dev->tbusy = 1;
outb_p(ENISR_ALL, e8390_base + EN0_IMR);
return 1;
}
ei_block_output(dev, length, skb->data, output_page);
if (! ei_local->txing) {
ei_local->txing = 1;
NS8390_trigger_send(dev, send_length, output_page);
dev->trans_start = jiffies;
if (output_page == ei_local->tx_start_page)
ei_local->tx1 = -1, ei_local->lasttx = -1;
else
ei_local->tx2 = -1, ei_local->lasttx = -2;
} else
ei_local->txqueue++;
dev->tbusy = (ei_local->tx1 && ei_local->tx2);
} else { /* No pingpong, just a single Tx buffer. */
ei_block_output(dev, length, skb->data, ei_local->tx_start_page);
ei_local->txing = 1;
NS8390_trigger_send(dev, send_length, ei_local->tx_start_page);
dev->trans_start = jiffies;
dev->tbusy = 1;
}
/* Turn 8390 interrupts back on. */
ei_local->irqlock = 0;
outb_p(ENISR_ALL, e8390_base + EN0_IMR);
dev_kfree_skb (skb, FREE_WRITE);
return 0;
相关推荐
更新发布
功能测试和接口测试的区别
2023/3/23 14:23:39如何写好测试用例文档
2023/3/22 16:17:39常用的选择回归测试的方式有哪些?
2022/6/14 16:14:27测试流程中需要重点把关几个过程?
2021/10/18 15:37:44性能测试的七种方法
2021/9/17 15:19:29全链路压测优化思路
2021/9/14 15:42:25性能测试流程浅谈
2021/5/28 17:25:47常见的APP性能测试指标
2021/5/8 17:01:11