- 论坛徽章:
- 0
|
这个不懂, 但之前看过一段时间的e1000的驱动,写过点东西,有点乱,胡乱贴上,希望有帮助.
工作原理:
发送BD环head和tail指针维护的是将要发送的BD的队列;而接收BD环head和tail指针维护的是可用来接收报文的BD队列。Tail指针通过软件来维护,head指针通过硬件来维护。
发包:
1, 将skb描述的报文加载到发送buffer中;
2, 将buffer中存放报文的信息填充到发送描述结构(BD)中;
3, 更新BD环的rail指针开始硬件发送,具体实现为 writel(i, adapter->hw.hw_addr + tx_ring->tail);
4, 触发中断处理函数e1000_clean_tx_irq,根据对BD中Descriptor Done bit的判断回收已经发送完的buffer,然后清零Status(内含Descriptor Done bit)
收包:
1, 设备接收到报文后,触发报文接收中断处理函数e1000_clean_rx_irq;
2, 根据对BD中E1000_RXD_STAT_DD的判断接收硬件已经接收完的报文,然后清零Status(内含Descriptor Done bit);
3, 并回填buffer,更新BD环的rail指针,具体实现为 writel(i, adapter->hw.hw_addr + tx_ring->tail);
初始化流程:
在e1000_probe中完成的工作:
通过函数alloc_etherdev为每个设备分配net_device结构,并初始化该结构体成员,包括报文发送函数(netdev->hard_start_xmit ),设备的打开关闭函数等等。最后通过register_netdev向上层注册该设备。
在e1000_open中完成的工作:
1, 通过e1000e_setup_tx_resources分配发送描述环所需空间。
2, 通过e1000e_setup_rx_resources分配接收描述环所需空间。
3, 在e1000_configure中,通过e1000_configure_tx(adapter)配置发送单元;通过 e1000_setup_rctl(adapter)配置接收控制寄存器;通过 e1000_configure_rx(adapter)配置发送单元,同时初始化adapter->clean_rx为e1000_clean_rx_irq(接收报文并交给协议栈同时为网口回填buffer),初始化adapter->alloc_rx_buf为e1000_alloc_rx_buffers(为每个设备分配存放接收报文buffer的函数);通过adapter->alloc_rx_buf(这儿调用的是e1000_alloc_rx_buffers)为每个设备来分配存放接收报文的buffer。
4, 通过e1000_request_irq()来初始化发送中断处理函数e1000_intr();在e1000_intr()中注册接收报文中断函数钩子adapter->clean_rx(adapter)和回收发送buffer的中断函数
5, 中断使能e1000_irq_enable,同时打开设备netif_tx_start_all_queues。
到此初始化流程结束。
报文发送流程:
e1000_ring结构中重要指针的说明:
tx_ring->next_to_use:软件主动发送报文时,当前发送BD的尾指针,即下一个将要发送BD的首指针。
tx_ring->next_to_clean:软件未回收的已经发送BD首指针
tx_ring->buffer_info[i].next_to_watch:软件下一次将要回收的buffer的指针,即软件已经交给硬件发送但没有回收buffer的最后一个分片包尾指针。
报文发送函数e1000_xmit_frame()中完成的工作:
1, 调用e1000_tx_map把skb所描述的报文映射到设备发送buffer。
2, 调用e1000_tx_queue把报文缓冲区中存放报文的信息填充到发送描述结构(BD)中,启动发送(Software updates the transmit descriptor tail pointer (TDT) to indicate the hardware that Tx descriptors are ready)。
对已发送报文buffer的回收在e1000_clean_tx_irq中通过e1000_put_txbuf函数来完成。
报文接收流程:
rx_ring->next_to_clean:下一个要接收的BD指针
在e1000_clean_rx_irq中调用e1000_receive_skb来接收报文,通过alloc_rx_buf来补充已被使用的buffer。 |
|