当前位置: 代码迷 >> 综合 >> linux 内核网卡驱动 ast2500 board
  详细解决方案

linux 内核网卡驱动 ast2500 board

热度:42   发布时间:2024-02-12 22:41:20.0

主要介绍下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钩子函数,这个函数用于从网卡上取网络数据包。

取包过程:

  1. 硬件将网络包搬运到RX buffer后,触发中断。
  2. 中断处理函数中,判断当前中断事件中有网络数据包ready的事件后,raise一个软中断NET_RX_SOFTIRQ,同时禁止硬件再触发网络数据包ready中断。
  3. 当前硬件中断完成后,判断是否有软中断需要处理,有则调用相应的钩子函数。即,这里就会调用注册的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.

 

至此,我们讲完这个网卡的最基本,最重要的操作函数。