/*
* 改变设备MTU值.
*/
int snull_change_mtu(struct net_device *dev, int new_mtu)
{
unsigned long flags;
struct snull_priv *priv = netdev_priv(dev);
spinlock_t *lock = &priv->lock;
/* check ranges */
if ((new_mtu < 68) || (new_mtu > 1500))
return -EINVAL;
/*
* Do anything you need, and the accept the value
*/
spin_lock_irqsave(lock, flags);
dev->mtu = new_mtu;
spin_unlock_irqrestore(lock, flags);
return 0; /* success */
}
/*
* 设备初始化函数,它必须在 register_netdev 函数被调用之前调用
*/
void snull_init(struct net_device *dev)
{
/*设备的“私有”结构,保存一些设备一些“私有数据”*/
struct snull_priv *priv;
#if 0
/*
* Make the usual checks: check_region(), probe irq, ... -ENODEV
* should be returned if no device found. No resource should be
* grabbed: this is done on open().
*/
#endif
/*
* 初始化以太网设备的一些共用的成员
*/
ether_setup(dev); /* assign some of the fields */
/*设置设备的许多成员函数指针*/
dev->open = snull_open;
dev->stop = snull_release;
dev->set_config = snull_config;
dev->hard_start_xmit = snull_tx;
dev->do_ioctl = snull_ioctl;
dev->get_stats = snull_stats;
dev->change_mtu = snull_change_mtu;
dev->rebuild_header = snull_rebuild_header;
dev->hard_header = snull_header;
dev->tx_timeout = snull_tx_timeout;
dev->watchdog_timeo = timeout;
/*如果使用NAPI,设置pool函数*/
if (use_napi) {
dev->poll = snull_poll;
dev->weight = 2; /*weight是接口在资源紧张时,在接口上能承受多大流量的权重*/
}
/* keep the default flags, just add NOARP */
dev->flags |= IFF_NOARP;
dev->features |= NETIF_F_NO_CSUM;
dev->hard_header_cache = NULL; /* Disable caching */
/*
* 取得私有数据区,并初始化它.
*/
priv = netdev_priv(dev);
memset(priv, 0, sizeof(struct snull_priv));
spin_lock_init(&priv->lock);
snull_rx_ints(dev, 1); /* 打开接收中断标志 */
snull_setup_pool(dev); /*设置使用NAPI时的接收缓冲池*/
}
/*
* The devices
*/
struct net_device *snull_devs[2];
/*
* Finally, the module stuff
*/
void snull_cleanup(void)
{
int i;
for (i = 0; i < 2; i++) {
if (snull_devs) {
unregister_netdev(snull_devs);
snull_teardown_pool(snull_devs);
free_netdev(snull_devs);
}
}
return;
}
/*模块初始化,初始化的只有一个工作:分配一个设备结构并注册它*/
int snull_init_module(void)
{
int result, i, ret = -ENOMEM;
/*中断函数指针,因是否使用NAPI而指向不同的中断函数*/
snull_interrupt = use_napi ? snull_napi_interrupt : snull_regular_interrupt;
/*
* 分配两个设备,网络设备都是用struct net_device来描述,alloc_netdev分配设备,第三个参数是
* 对struct net_device结构成员进行初始化的函数,对于以太网来说,可以把alloc_netdev/snull_init
* 两个函数变为一个,alloc_etherdev,它会自动调用以太网的初始化函数ether_setup,因为以太网的初
* 始化函数工作都是近乎一样的 */
snull_devs[0] = alloc_netdev(sizeof(struct snull_priv), "sn%d",
snull_init);
snull_devs[1] = alloc_netdev(sizeof(struct snull_priv), "sn%d",
snull_init);
/*分配失败*/
if (snull_devs[0] == NULL || snull_devs[1] == NULL)
goto out;
ret = -ENODEV;
/*向内核注册网络设备,这样,设备就可以被使用了*/
for (i = 0; i < 2; i++)
if ((result = register_netdev(snull_devs)))
printk("snull: error %i registering device \"%s\"\n",
result, snull_devs->name);
else
ret = 0;
out:
if (ret)
snull_cleanup();
return ret;
}
module_init(snull_init_module);
module_exit(snull_cleanup);
阅读(1272) | 评论(0) | 转发(0) |