网络设备的初始化主要完成如下几个方面的工作。
- 进行硬件上的准备工作,检查网络设备是否存在,如果存在,则检测设备所使用的硬件资源。
- 进行软件接口上的准备工作,分配 net_device 结构体并对其数据结构和函数指针成员赋值。
- 获得设备的私有信息指针并初始化各成员的值。如果私有信息中包括自旋锁或信号量等并发或同步机制,则需对其进行初始化。
对 net_device 结构体成员及私有数据的赋值都可能需要与硬件初始化工作协同进行,即硬件检测出了相应的资源,需要根据检测结果填充 net_device 结构体成员和私有数据。
网络设备驱动的初始化函数模板如下所示,具体的设备驱动初始化函数并不一定和以下模板完全一致,但其本质过程是一致的。
/* * 网络设备驱动的初始化函数模板 */ void xxx_init(struct net_device *dev) { /* 设备的私有信息结构体 */ struct xxx_priv *priv; /* 检查设备是否存在和设备所使用的硬件资源 */ xxx_hw_init(); /* 初始化以太网设备的公用成员 */ ether_setup(); /* 设置设备的成员函数指针 */ ndev->netdev_ops = &xxx_netdev_ops; ndev->ethtool_ops = &xxx_ethtool_ops; dev->watchdog_timeo = timeout; /* 取得私有信息,并初始化它 */ priv = netdev_priv(dev); ``` /* 初始化设备私有数据区 */ }
上述代码的 xxx_hw_init( ) 函数完成的与硬件相关的初始化操作如下:
- 探测 xxx 网络设备是否存在。探测的方法类似于数学上的 “反证法”, 即先假设存在设备 xxx,访问该设备,如果设备的表现与预期一致,就确定设备存在;否则,假设错误,设备 xxx 不存在。
- 探测设备的具体硬件配置。一些设备驱动编写的非常通用,对于同类的设备使用统一的驱动,我们需要在初始化时探测设备的具体型号。另外,即便是同一设备,在硬件上的配置也可能会不一样,我们也可以探测设备所使用的硬件资源。
- 申请设备所需要的硬件资源,如用 request_region( ) 函数进行I/O端口的申请等,但是这个过程可以放在设备的打开函数 xxx_open( ) 中完成。