(2)分配发送和接收的缓存空间
根据官方文档,发送一个数据包的过程是这样的:先从应用程序中把数据包拷贝到一段连续的内存中(这段内存就是我们这里要分配的缓存),然后把这段内存的地址写进网卡的数据发送地址寄存器(TSAD)中,这个寄存器的偏移量是TxAddr0 = 0x20。在把这个数据包的长度写进另一个寄存器(TSD)中,它的偏移量是TxStatus0 = 0x10。然后就把这段内存的数据发送到网卡内部的发送缓冲中(FIFO),后由这个发送缓冲区把数据发送到网线上。tp->tx_bufs = pci_alloc_consistent(tp->pdev, 1536*4,&tp->tx_bufs_dma);
tp->rx_bufs = pci_alloc_consistent(tp->pdev, RX_BUF_TOT_LEN,&tp->rx_bufs_dma);
(3)发送和接收缓冲区初始化和网卡开始工作的操作
RTL8139有4个发送描述符(包括4个发送缓冲区的基地址寄存器(TSAD0-TSAD3)和4个发送状态寄存器(TSD0-TSD3)。也就是说我们分配的缓冲区要分成四个等分并把这四个空间的地址都写到相关寄存器里去,下面这段代码完成了这个操作。
for (i = 0; i < 4; i++)
tp->tx_buf[i] = &tp->tx_bufs[i * 1536];
这段代码负责把发送缓冲区物理空间进行了分割,并把它写到了相关寄存器中,这样在网卡开始工作后就能够迅速定位和找到这些内存并存取它们的数据。
for (i = 0; i < 4; i++) {
iowrite32(tp->tx_bufs_dma + (tp->tx_buf[i] - tp->tx_bufs), ioaddr+TxAddr0 + (i * 4));
ioread32(ioaddr+TxAddr0 + (i * 4));
}
下面这行代码是把接收缓冲区的物理地址写到了相关寄存器中,这样网卡接收到数据后就能准确地把数据从网卡中搬运到这些内存空间中,等待CPU来领走它们。
如果你想了解更多关于如何发送数据包的细节,可以参考发送数据包的文档说明;对发送TCP数据包感兴趣的朋友,不妨看看这篇发送TCP数据包文章。关于使用winpcap发送数据包的详细信息,请访问winpcap发送数据包。
暂无评论