主要介绍下ast2500内置网卡(MAC)的linux下的驱动程序。
文件所在目录:
Linux/drivers/net/ethernet/aspeed/ast_ether.c
先来看一下内核的配置文件.config
从.config文件的定义中,我们看到该驱动是编进内核中的,在内核初始化的时候,do_basic_setup()时会调用该驱动的module_init()申明的函数,如下:
我们来看一下这个ast_ether_init()函数。
2209行,调用ast_ether_scu_init()去初始化一些寄存器,主要是reset MAC:
2215行,调用ast_ether_init_one()初始化ether.
2075行,申请net_device内存。
2079行,检查ethernet MAC的寄存器地址是否被别人占用了,并占用该地址(这里的地址为物理地址)
2084行,将ethernet MAC的寄存器地址ioremap,即给寄存器地址分配相应的虚拟地址va,并将这个va和寄存器物理地址的转换写入MMU表(va->pa 内存页表)。
2090-2092行,取MAC的中断号,并设置为上升沿出发中断。
2096行,设置net_device的操作函数。
2098行,注册该网络设备(eth0),这样,我们就可以用ip link看到这个网络接口了.
2103行,设置net_device一些内容,比如ethernet构造函数,MTU, ether type等。
2104行,设置ethtool操作函数。
2112行,保存设备MAC地址信息到net_device结构。
2116行,设置napi钩子函数,这个函数用于从网卡上取网络数据包。
取包过程:
- 硬件将网络包搬运到RX buffer后,触发中断。
- 中断处理函数中,判断当前中断事件中有网络数据包ready的事件后,raise一个软中断NET_RX_SOFTIRQ,同时禁止硬件再触发网络数据包ready中断。
- 当前硬件中断完成后,判断是否有软中断需要处理,有则调用相应的钩子函数。即,这里就会调用注册的napi钩子函数 ast_ether_poll,ast_ether_poll来处理收包,并使能网络数据包ready中断,这样,硬件就又可以给包了。
2126行,ast_ether_alloc_descriptor()主要是申请rx/tx descriptor内存,软件和硬件通过这块内存交互状态信息,以及DMA内存地址(用于存放收到的网络包或者将要发送的网络包)。
注意,这里的rx/tx descriptor使用的是dma coherent(dma一致性)内存,以保证这块内存不被cpu cache(如果cache了,当硬件修改这块内存后,cpu读取的由于是cache中数据,这样就和内存中的最新数据不一致了,反过来也一样)
这样初始化MAC就完成了。
当我们要使用这个设备时,首先是调用dev->open()函数,即ast_ether_open(),我们来分析下这个函数在做什么。
1573行,注册中断处理函数ast_ether_irq_handler,中断号dev->irq.
1578行,读取PHY芯片的id, mode, revision。有关PHY芯片寄存器的描述,参考《PHY 寄存器.docx》
1579行,设置PHY的mode: 100M&全双工等。
1581行,初始化tx/rx descriptor, 设置descriptor状态,申请rx descriptor的接受网络包的内存等。
1582行,配置MAC地址到MAC engine,告知MAC engine rx/tx descriptor的内存地址,使能中断,使能MAC engine.
1076行使得MAC engine&PHY开始工作了,即硬件设备working了。
open了之后,就是收包和发包了。
我们先介绍收包。之前有介绍一部分,硬件收到包,并将包DMA到buffer后通过中断告知软件,软件中断程序再raise一个软中断,收包的处理则在软中断钩子函数中进行。我们来看看这个软中断钩子函数ast_ether_poll().
1471-1472行,取rx descriptor的状态,如果是RX_DESC_RXPKT_RDY, 表明当前这个descriptor已经由硬件完成收包了,则调用ast_ether_rx()去收包。
ast_ether_rx()循环检查rx buffer中是否由包,有包则取出(1308行),然后调用netif_receive_skb()将包递交给上层协议处理。ast_ether_rx()一次只处理一个包(1427行break).
1475行,在ast_ether_rx()收包后,调用ast_ether_realloc_rx_buf(), 将被取走包的rx descriptor重新给申请内存,以便硬件再次使用。
接下去,我们来看发包处理tx. Tx的函数为ast_ether_tx().
1106-1114行,取一个可用的tx descriptor(TX_DESC_TXDMA_OWN表明该descriptor硬件还在使用)。
1116-1121行,将待发送的包skb,放入tx descriptor中。
1127行,通知MAC engine将tx descriptor中的包发送到网络上。
当硬件将包发送完后(FIFO -> ethernet),会触发一个中断,报告中断事件ISR_TPKT2E。我们来看看这个中断事件的处理(ast_ether_irq_handler).
处理这个ISR_TPKT2E中断事件,就是做一个tx_packets统计,并释放此次发包所占用的tx descriptor.
至此,我们讲完这个网卡的最基本,最重要的操作函数。