一、源文件

源码路径:\drivers\net\ethernet\rockchip\gmac

源码阅读顺序:

二、重要探针函数stmmac_dvr_probe

1. alloc_etherdev

申请网卡设备和私有数据。

struct net_device *ndev = NULL;

struct stmmac_priv *priv;

ndev = alloc_etherdev(sizeof(struct stmmac_priv));

priv = netdev_priv(ndev);

网卡设备和私有数据紧紧的挨在一起:网卡设备+私用数据结构,通过netdev_priv获取私有数据。网卡设备是通用数据结构,私有数据则为各个MAC控制器的数据结构。

2. stmmac_hw_init

初始化MAC设备。检测要添加的设备(GMAC/MAC10-100),检查HW能力并设置驱动程序的特性。

3. netif_napi_add

初始化一个NAPI上下文,轮询接收数据包接口。

netif_napi_add(ndev, &priv->napi, stmmac_poll, 64);

stmmac_poll是轮询接口

该接口完成两个事情:

1)当数据发送完成时产生中断,进入该函数进行资源回收。

2)收到数据产生中断,进入该函数进行数据接收和处理。

static int stmmac_poll(struct napi_struct *napi, int budget)
{
  ......
  stmmac_tx_clean(priv); //传输完成后回收资源
  work_done = stmmac_rx(priv, budget); //数据包接收处理
  stmmac_enable_dma_irq(priv); //使能dma终端
  ......
}

stmmac_rx函数解析

作用:再次填充并使用skb预先分配的缓存,由NAPI轮询方法调用,可以获得环内所有帧。

函数:static int stmmac_rx(struct stmmac_priv *priv, int limit)

函数内定义:

1)priv->hw->desc->get_rx_owner(p)

判断当前描述子的归属:描述子数据结构中OWN位,

  0: 当前描述子应该由CPU操作,

  1: 前描述子应该由GMAC操作。

对于接收,初始化dma描述子队列时设置为1。

GMAC根据寄存器配置,获取可用接收描述子,然后从RxFIFO中读取从PHY接收的Ethernet报文,如果报文符合接收条件,将该报文写入接收描述子指向的数据缓冲区,并回写接收描述子。这个回写就会将OWN位设置为0。

2)next_entry = (++priv->cur_rx) % rxsize;

获取下一帧描述符,

p_next =priv->dma_rx + next_entry;

priv->cur_rx:已经传递给协议层的index。

3)status =(priv->hw->desc->rx_status(&priv->dev->stats, &priv->xstats,p));

获取收到帧状态,如果是丢弃帧,则什么都不处理;否则上传到上层网络。

4)frame_len = priv->hw->desc->get_rx_frame_len(p, coe); 获取帧长度

5)skb = priv->rx_skbuff[entry];

priv->rx_skbuff[entry] = NULL;

注意:skb将有上层网络处理完后进行释放。

6)skb_put(skb, frame_len);

dma_unmap_single(priv->device,priv->rx_skbuff_dma[entry],priv->dma_buf_sz, DMA_FROM_DEVICE);  设置skb数据长度和解除流式DMA映射

7)获取skb的协议类型

skb->protocol = eth_type_trans(skb,priv->dev);

skb->dev = priv->dev;

8)napi_gro_receive(&priv->napi,skb);

将skb通过NAPI接口上传上层网络协议处理。

9)stmmac_rx_refill(priv); 重新填充接收队列

三、打开网卡设备接口stmmac_open

网卡刚起来时是关闭的,要用命令去打开,ifconfig eth0 up 时调用net_device_ops的.ndo_open,这里为stmmac_open。

  1. netdev_priv 获得网络设备私有数据
  2. stmmac_check_ether_addr 检测MAC地址是否有效,若无效,随机产生一个
  3. stmmac_mdio_register注册MII总线

mdiobus_register()

a.注册总线设备device_register(&bus->dev);

b.复位总线bus->reset(bus);

c.扫描总线上的PHY设备,最大支持32个

4. stmmac_init_phy初始化PHY设备,并将PHY和MAC绑定

5. request_irq 申请中断

ret = request_irq(dev->irq, stmmac_interrupt,

IRQF_SHARED, dev->name, dev);

注册中断请求线IRQ,中断处理函数stmmac_interrupt用于接收DMA数据,配合NAPI处理。

static irqreturn_t stmmac_interrupt(int irq, void *dev_id)
{
  ......
  /* To handle DMA interrupts */
  stmmac_dma_interrupt(priv);  
} static void stmmac_dma_interrupt(struct stmmac_priv *priv)
{
  ......
  status = priv->hw->dma->dma_interrupt(priv->ioaddr, &priv->xstats);
  if (likely((status & handle_rx)) || (status & handle_tx)) {
    if (likely(napi_schedule_prep(&priv->napi))) {
      stmmac_disable_dma_irq(priv);
      __napi_schedule(&priv->napi); //加入poll流程
    }
  }
  ......
}

四、发送数据接口stmmac_xmit

该接口实现了Scatter/Gather I/O功能,通过skb_shinfo宏来判断数据包是由一个数据片段组成,还是由大量数据片段组成。

1、entry= priv->cur_tx % txsize;

desc= priv->dma_tx + entry; 获取可用发送描述子

first= desc; 保存第一个数据片段

2、priv->tx_skbuff[entry]= skb;

priv->tx_page[entry]= NULL; 将skb放到发送队列

3、unsignedint nopaged_len = skb_headlen(skb);

desc->des2=dma_map_single(priv->device,skb->data,nopaged_len, DMA_TO_DEVICE);

priv->hw->desc->prepare_tx_desc(desc,1, nopaged_len, csum_insertion);

发送单个或第一个数据包,当只有一个数据片段时,skb->data将发送所有数据;当有多个数据片段时,skb->data则指向第一个数据片段,数据长度skb->len –skb->data_len,其他数据存放在共享数据结构frags数组中。(skb->len:数据包中全部数据的长度,skb->data_len分隔存储数据片段长度)

4、

for (i = ; i < nfrags; i++) {
  const skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
  int len = skb_frag_size(frag);
  entry = (++priv->cur_tx) % txsize;
  if (priv->extend_desc)
    desc = (struct dma_desc *)(priv->dma_etx + entry);
  else
    desc = priv->dma_tx + entry;
  TX_DBG("\t[entry %d] segment len: %d\n", entry, len);
  desc->des2 = skb_frag_dma_map(priv->device, frag, , len, DMA_TO_DEVICE);
  priv->tx_skbuff_dma[entry] = desc->des2;
  priv->tx_skbuff[entry] = NULL;
  priv->hw->desc->prepare_tx_desc(desc, , len, csum_insertion,
  priv->mode);
  wmb();
  priv->hw->desc->set_tx_owner(desc);
  wmb();
}

发送剩余数据片段。

对于多个数据片段时,还要进行数据片段的发送,采用页处理。直接处理页结构,而不是内核虚拟地址。

5、priv->hw->desc->set_tx_owner(first);

priv->cur_tx ++;

将第一个数据片段描述子交给GMAC,记录当前发送index

6、priv->hw->dma->enable_dma_transmission(priv->dma_ioaddr,

priv->dma_channel);

写任何值唤醒处于挂起的RxDMA

RK3288 GMAC整理的更多相关文章

  1. dotNET跨平台相关文档整理

    一直在从事C#开发的相关技术工作,从C# 1.0一路用到现在的C# 6.0, 通常情况下被局限于Windows平台,Mono项目把我们C#程序带到了Windows之外的平台,在工作之余花了很多时间在M ...

  2. UWP学习目录整理

    UWP学习目录整理 0x00 可以忽略的废话 10月6号靠着半听半猜和文字直播的补充看完了微软的秋季新品发布会,信仰充值成功,对UWP的开发十分感兴趣,打算后面找时间学习一下.谁想到学习的欲望越来越强 ...

  3. SQL Server 常用内置函数(built-in)持续整理

    本文用于收集在运维中经常使用的系统内置函数,持续整理中 一,常用Metadata函数 1,查看数据库的ID和Name db_id(‘DB Name’),db_name('DB ID') 2,查看对象的 ...

  4. kafka学习笔记:知识点整理

    一.为什么需要消息系统 1.解耦: 允许你独立的扩展或修改两边的处理过程,只要确保它们遵守同样的接口约束. 2.冗余: 消息队列把数据进行持久化直到它们已经被完全处理,通过这一方式规避了数据丢失风险. ...

  5. JAVA程序员常用软件整理下载

    ********为了大家学习方便,特意整理软件下载如下:*************Java类软件:-------------------------------JDK7.0:http://pan.ba ...

  6. js数组学习整理

    原文地址:js数组学习整理 常用的js数组操作方法及原理 1.声明数组的方式 var colors = new Array();//空的数组 var colors = new Array(3); // ...

  7. GJM : C#设计模式汇总整理——导航 【原创】

    感谢您的阅读.喜欢的.有用的就请大哥大嫂们高抬贵手"推荐一下"吧!你的精神支持是博主强大的写作动力以及转载收藏动力.欢迎转载! 版权声明:本文原创发表于 [请点击连接前往] ,未经 ...

  8. 整理下.net分布式系统架构的思路

    最近看到有部分招聘信息,要求应聘者说一下分布式系统架构的思路.今天早晨正好有些时间,我也把我们实际在.net方面网站架构的演化路线整理一下,只是我自己的一些想法,欢迎大家批评指正. 首先说明的是.ne ...

  9. 安卓GreenDao框架一些进阶用法整理

    大致分为以下几个方面: 一些查询指令整理 使用SQL语句进行特殊查询 检测表字段是否存在 数据库升级 数据库表字段赋初始值 一.查询指令整理 1.链式执行的指令 return mDaoSession. ...

随机推荐

  1. C++ 项目中直接使用JsonCpp源码文件

    之前在网上看到使用JsonCpp都是以库的形式使用(编译源码为静态库或者动态库),这样引用很方便,但有时候报错调试看不到错误的地方,所以就想直接把源文件添加到项目中,方便调试 这是用到源码文件: 创建 ...

  2. 在Windows下搭建Android开发环境及遇到的问题

    转载1:http://www.cnblogs.com/xdp-gacl/p/4322165.html 转载2:http://www.cnblogs.com/zoupeiyang/p/4034517.h ...

  3. 获取转UTF8的字符串

    /// <summary> /// 获取转UTF8的字符串 /// </summary> /// <param name="strWord">& ...

  4. POJ 2425 A Chess Game(有向图SG函数)题解

    题意:给一个有向图,然后个m颗石头放在图上的几个点上,每次只能移动一步,如果不能移动者败 思路:dfs打表sg函数,然后求异或和 代码: #include<queue> #include& ...

  5. POJ2528 Mayor's posters(线段树&区间更新+离散化)题解

    题意:给一个区间,表示这个区间贴了一张海报,后贴的会覆盖前面的,问最后能看到几张海报. 思路: 之前就不会离散化,先讲一下离散化:这里离散化的原理是:先把每个端点值都放到一个数组中并除重+排序,我们就 ...

  6. Adobe Reader 2019 Offline Installer, Free Download - Best PDF Reader

    https://ridnt-b.blogspot.com/2018/01/adobe-reader-2018-free-download.html http://ardownload.adobe.co ...

  7. 将DevExpress.Utils.ImageCollection变量的image导出

    private void tspBtnExportExcel_Click(object sender, EventArgs e) { //暂时用来导出图片 string filePath = Syst ...

  8. 【打分策略】Elasticsearch打分策略详解与explain手把手计算

    一.目的 一个搜索引擎使用的时候必定需要排序这个模块,一般情况下在不选择按照某一字段排序的情况下,都是按照打分的高低进行一个默认排序的,所以如果正式使用的话,必须对默认排序的打分策略有一个详细的了解才 ...

  9. 第十一章 非对称加密算法--DH

    注意:本节内容主要参考自<Java加密与解密的艺术(第2版)>第8章“高等加密算法--非对称加密算法” 11.1.非对称加密算法 特点: 发送方和接收方均有一个密钥对(公钥+私钥),其中公 ...

  10. BZOJ2724 [Violet]蒲公英 分块

    题目描述 经典区间众数题目 然而是权限题,所以题目链接放Luogu的 题解 因为太菜所以只会$O(n*\sqrt{n}+n*\sqrt{n}*log(n))$的做法 就是那种要用二分的,并不会clj那 ...