linux网卡驱动注册与接受数据处理

Linux网络接受

本文基于2.6.15的内核版本来简单学习一下有关Linux内核如何进行网络数据的处理流程。

网卡驱动注册

以ixgb驱动为例,在网卡注册的时候会进入如下流程。

static struct pci_driver ixgb_driver = {
   
	.name     = ixgb_driver_name,
	.id_table = ixgb_pci_tbl,
	.probe    = ixgb_probe,
	.remove   = __devexit_p(ixgb_remove),
};

...
/**
 * ixgb_init_module - Driver Registration Routine
 *
 * ixgb_init_module is the first routine called when the driver is
 * loaded. All it does is register with the PCI subsystem.
 **/

static int __init
ixgb_init_module(void)
{
   
	printk(KERN_INFO "%s - version %s\n",
	       ixgb_driver_string, ixgb_driver_version);

	printk(KERN_INFO "%s\n", ixgb_copyright);

	return pci_module_init(&ixgb_driver);
}

module_init(ixgb_init_module);

PCI注册的流程会将调用probe方法,即ixgb_probe。

/**
 * ixgb_probe - Device Initialization Routine
 * @pdev: PCI device information struct
 * @ent: entry in ixgb_pci_tbl
 *
 * Returns 0 on success, negative on failure
 *
 * ixgb_probe initializes an adapter identified by a pci_dev structure.
 * The OS initialization, configuring of the adapter private structure,
 * and a hardware reset occur.
 **/

static int __devinit
ixgb_probe(struct pci_dev *pdev,
		const struct pci_device_id *ent)
{
   
	struct net_device *netdev = NULL;
	struct ixgb_adapter *adapter;
	static int cards_found = 0;
	unsigned long mmio_start;
	int mmio_len;
	int pci_using_dac;
	int i;
	int err;

	if((err = pci_enable_device(pdev)))  // 是否可以注册该设备
		return err;

	if(!(err = pci_set_dma_mask(pdev, DMA_64BIT_MASK))) {
    //设置DMA的掩码
		pci_using_dac = 1;
	} else {
   
		if((err = pci_set_dma_mask(pdev, DMA_32BIT_MASK))) {
   
			IXGB_ERR("No usable DMA configuration, aborting\n");
			return err;
		}
		pci_using_dac = 0;
	}

	if((err = pci_request_regions(pdev, ixgb_driver_name)))
		return err;

	pci_set_master(pdev);

	netdev = alloc_etherdev(sizeof(struct ixgb_adapter)); // 申请设备结构体
	if(!netdev) {
   
		err = -ENOMEM;
		goto err_alloc_etherdev;
	}

	SET_MODULE_OWNER(netdev);
	SET_NETDEV_DEV(netdev, &pdev->dev);

	pci_set_drvdata(pdev, netdev);    // 设置DMA对应的管理的内存空间
	adapter = netdev_priv(netdev);
	adapter->netdev = netdev;
	adapter->pdev = pdev;
	adapter->hw.back = adapter;

	mmio_start = pci_resource_start(pdev, BAR_0);
	mmio_len = pci_resource_len(pdev, BAR_0);

	adapter->hw.hw_addr = ioremap(mmio_start, mmio_len);
	if(!adapter->hw.hw_addr) {
   
		err = -EIO;
		goto err_ioremap;
	}

	for(i = BAR_1; i <= BAR_5; i++) {
   
		if(pci_resource_len(pdev, i) == 0)
			continue;
		if(pci_resource_flags(pdev, i) & IORESOURCE_IO) {
   
			adapter->hw.io_base = pci_resource_start(pdev, i);
			break;
		}
	}

	netdev->open = &ixgb_open;  // 设置ethtool对应的操作的方法,即设备的打开的方法
	netdev->stop = &ixgb_close;   // 设备的关闭的方法
	netdev->hard_start_xmit = &ixgb_xmit_frame;
	netdev->get_stats = &ixgb_get_stats;
	netdev->set_multicast_list = &ixgb_set_multi;
	netdev->set_mac_address = &ixgb_set_mac;
	netdev->change_mtu = &ixgb_change_mtu;  // 设置mtu长度
	ixgb_set_ethtool_ops(netdev);
	netdev->tx_timeout = &ixgb_tx_timeout;  // 设置超时时间
	netdev->watchdog_timeo = HZ;
#ifdef CONFIG_IXGB_NAPI
	netdev->poll = &ixgb_clean;    // 设置设备的poll方法 一般用在NAPI模式中
	netdev->weight = 64;
#endif
	netdev->vlan_rx_register = ixgb_vlan_rx_register;  // 设置vlan的方法
	netdev->vlan_rx_add_vid = ixgb_vlan_rx_add_vid;
	netdev->vlan_rx_kill_vid = ixgb_vlan_rx_kill_vid;
#ifdef CONFIG_NET_POLL_CONTROLLER
	netdev->poll_controller = ixgb_netpoll
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值