DM9000网卡驱动是基于平台驱动架构的。下面可以对dm9000.c文件进行相关简单分析:
1) 找到module_init()函数:
2) 进入初始化函数(dm9000_init)
由上可知,将dm9000驱动视为平台驱动处理。这里首先明确一点,平台设备和平台驱动是通过名字来进行匹配的。接下来再来看看dm9000_driver结构体变量成员是怎样填值的。
2) dm9000_driver结构体变量
当平台设备和平台驱动匹配时,就会调用到probe函数,这里我们着重来看一看dm9000_probe函数实现
3) dm9000_probe函数
分配一个net_device结构
获取相关资源
初始化基地址和中断号
初始化了netdev_ops成员,至此,设备操作函数集dm9000_netdev_ops和net_device建立联系
向内核注册net_device
至此,我们可以总结probe函数中所做的主要工作:
a. 分配net_device结构-- alloc_etherdev
b. 初始化net_device结构(包括中断号、基地址、netdev_ops等)
c. 向内核注册net_device-----register_netdev()
d. 释放net_device结构--free_netdev
4) 分析dm9000_netdev_ops中操作函数集
a. dm9000_open
这里进行了中断注册,接下来的代码都是进行硬件初始化的工作
注意这里调用了netif_start_queue()函数,激活设备发送队列。接下来的重点,就是去看看前面提到的注册中断处理函数dm9000_interrupt的实现:
我觉得最有作用的是这几行代码,根据不同的中断类型,调用不同的函数去处理,dm9000_rx()是去处理接收中断,dm9000_tx_done()是去处理发送完成中断。好,我们的分析流程就跳转到这两个函数的实现:
dm9000_rx()
这里就是在读取接收到的数据,分配sk_buffer数据结构和数据缓冲区,将接收到的数据复制到数据缓冲区。(至于这里具体的dev_alloc_skb、skb_reserve(skb, 2)、rdptr = (u8 *) skb_put(skb, RxLen - 4)等操作的作用可参考宋宝华老师的《Linux设备驱动开发详解》、《精通Linux设备驱动程序开发》以及国嵌谢老师的视频)
并调用netif_rx()函数将sk_buffer传递给上层协议。
dm9000_tx_done()
这里调用了netif_wake_queue()函数以重新启动设备发送队列。
b. dm9000_start_xmit()—发送函数
这里调用了netif_stop_queue()函数,通知上层暂停向驱动发送数据。为什么只有停止设备传输包呢?那什么时候会去通知上层可以发送数据呢?别忘了我们前面提到的中断处理函数dm9000_interrupt中调用的dm9000_tx_done(),这里面调用了netif_wake_queue()函数以重新启动设备发送队列。
5) 简单总结数据发送和数据接收:
a. 数据发送:主要涉及两个函数dm9000_start_xmit()(通知上层停止发送)和dm9000_tx_done()(通知上层可以发送)
b. 数据接收:由中断引发设备的中断处理函数,即dm9000_rx()