专栏首页Linux驱动27.Linux-DM9000C网卡移植(详解)

27.Linux-DM9000C网卡移植(详解)

上一节 我们学习了:  

网卡驱动介绍以及制作虚拟网卡驱动

接下来本节,学习网卡芯片DM9000C,如何编写移植DM9000C网卡驱动程序。

1.首先来看DM9000C原理图

如下图所示:

  (#:表示低电平有效)

  • SD0~15: 16位数据线,有CMD引脚决定访问类型
  • CMD:      命令线,当CMD为高,表示SD 传输的是数据,CMD为低表示传输的是地址
  • INT:         中断引脚,接在2440的GPF7脚上
  • IOR#:      读引脚,接在2440的nOE脚上
  • IOW#:     写引脚,接在2440的nWE脚上
  • CS#:       片选,放在2440的bank4的片选上面

1.1其中2440手册的bank4地址区间如下图:

bank4的区间位于: 0X20000000~0X28000000,当我们访问这个区间的地址,内存控制器便会使能网卡DM9000C的使能脚,所以我们的DM9000C的io基地址=0X20000000

其中DM9000C的CMD引脚接在bank4的LADDR2上面

所以当访问的io基地址=0X2000 0000,表示读写的地址里的内容是DM9000C的地址

访问的io基地址=0X2000 0100,表示读写的地址里的内容是DM9000C的数据

1.2 DM9000C收发过程

当DM9000C收到外部的数据后,会暂存到内部地址中,然后产生一个上升沿中断,等待2440读取数据

当DM9000C将2440的数据转发出去后,也会产生一个上升沿中断给2440

如下图所示,DM9000C的中断引脚位于pin34脚

接在2440的GPF7引脚上,使用的中断为EINT7

接下来便来修改厂家提供的DM9000C源代码

2.发现它的init_module()入口函数前有个条件编译

所以要注释掉 “#ifdef MODULE” 和 “#endif”

3.修改入口出口函数名,并修饰它们(修改函数名避免与内核的其它函数重名)

4.修改驱动的硬件相异性(设置基地址,寄存器,中断等)

4.1先来找找代码在哪里初始化DM9000C硬件的

进入dm9000c_init()

       -> dmfe_probe()

其中dmfe_probe()函数如下:

struct net_device * __init dmfe_probe(void)
{
struct net_device *dev;

dev= alloc_etherdev(sizeof(struct board_info));          //分配一个net_device结构体
... ...

err = dmfe_probe1(dev);                                 //调用dmfe_probe1()函数
... ...

err = register_netdev(dev);                            //向内核注册net_device结构体
... ...
}

显然dmfe_probe1()函数就是用来初始化DM9000C硬件和设置net_device结构体的成员用的

4.2 进入dmfe_probe1()函数

如下图,这个iobase 变量就是我们DM9000C的io基地址0x20000000

iobase的作用:

如上图, 读一次DM9000C的VID低字节之前,需要先将地址赋为0x20000000,也就是将DM9000C的CMD置0,然后向0x20000000写入要读的DM9KS_VID_L地址值

最后再将地址+4,也就是赋为0x20000100,将CMD置1,然后读出0x20000100的值,也就是DM9000C的VID低字节

DM9000C的读写方式都是这样的,先将CMD置0,写入DM9000C的地址,然后再将CMD置1,来读写数据

4.3所以在init函数中便重新设置iobase 变量,其中iobase是int型

并在exit出口函数中,添加iounmp()

4.4 继续进入dmfe_probe1()函数,往下看

如下图所示,屏蔽红框里的代码,该代码用来核对版本,我们的DM9000C版本号不一样,所以要屏蔽

4.5 在init函数中,修改中断名,将irq改为IRQ_EINT7

4.6 修改中断

当使用了register_netdev()注册了网卡驱动net_device后,在内核中使用ifconfig就会进入net_device->open成员函数申请中断,激活队列等

所以我们要修改open成员函数的申请中断函数,将触发中断改为“IRQT_RISING”,上升沿触发

5.接下来便开始设置2440的存储控制寄存器

设置2440的bank4的硬件位宽,时序,因为不同的硬件,涉及的数据收发都不同,

5.1设置BWSCON总线宽度控制寄存器

我们只设置BANK4的内容,所以只有下面3个(BANK0的位宽由OM[1:0] 硬件设置)

设置ST4=0,不使用UB/LB(UB/LB:表示高字节与低字节数据是否分开传输)

设置WS4=0,其中WAIT引脚为PE4,而我们DM9000C没有引脚接入PE4,所以禁止

设置DW4=0x01,我们的DM9000C的数据线为16位

5.2设置BANKCON4控制寄存器

 设置这些时序之前,首先来看DM9000C芯片手册时序图和2440的时序图

参考上图,得出BANKCON4 寄存器设置如下(HCLK=100MHZ,1个时钟等于10ns)

设置Tacs=0,CS和CMD信号可以同时进行(CMD脚就是2440的地址引脚)

设置Tcos=T1=0(CS片选使能后维持时间)

设置Tacc=T2=0,要>=10ns(读写信号的访问维持时间)

设置Tcoh=T4=1,要>=3ns(片选结束维持时间)

设置Tcah=T8=0, CS和CMD信号可以同时结束(地址总线结束维持时间)

代码如下图,在init入口函数中设置

与硬件相关的部分已经改好了,接下来开始编译

6.编译测试

编译之前,首先添加该驱动需要的内核头文件:

#include <asm/delay.h>
#include <asm/irq.h>
#include <linux/irq.h>
#include <asm/io.h>
#include <asm/arch-s3c2410/regs-mem.h>

编译无误后,便开始测试DM9000C驱动程序:

1) 把dm9dev9000c.c放到内核的drivers/net目录下,来替换原来内核的DM9000C

2) 修改drivers/net/Makefile 

把 obj-$(CONFIG_DM9000) += dm9000.o 改为(如下图所示) obj-$(CONFIG_DM9000) += dm9dev9000c.o

3) make uImage

如下图,说明新的驱动已编译进内核

4) 使用新内核启动

ifconfig eth0 192.168.2.107

ping 192.168.2.1

如下图,可以ping通,说明移植成功

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 7.Android-压力测试、单元测试、日志猫使用

    表示测试com.example.phonecall应用程序,随机发送点击/滑动/切换事件10000次,( -v -v -v)表示信息日志为最高级,然后打印的信息...

    张诺谦
  • 第1阶段——uboot分析之硬件初始化start.S(4)

    分析uboot第一个执行函数_start(cpu/arm920t/start.S)  打开cpu/arm920t/start.S 1 .globl _start...

    张诺谦
  • 12.Android-SQLiteOpenHelper使用

    为了在本地创建SQLite数据库,我们需要创建一个SQLiteOpenHelper的子类,这里取名的为MyOpenHelper类,然后还要写构造方法来初始化父类...

    张诺谦
  • 为什么会有那么多的云计算浪费?

    随着2019年即将结束,调研机构Gartner公司预测,2019年全球云计算浪费约为141亿美元。尽管由于某些原因,这个数字实际可能会高得多,但这个数字是巨大的...

    静一
  • 假如用多个CPU核同时控制一个GPU,并且进行运算与数据的传递,请问这能够实现么?...

    问:假如用多个CPU核同时控制一个GPU,并且进行运算与数据的传递,请问这能够实现么?我的工作站是48个CPU核,两块GPU卡,打算把CPU和GPU都用起来,我...

    GPUS Lady
  • 美团点评容器平台HULK的调度系统

    背景 美团点评作为国内最大的O2O平台,业务热度的高峰低谷非常显著且规律,如果遇到节假日或促销活动,流量还会在短时间内出现成倍的增长。过去传统虚拟机的服务运行及...

    美团技术团队
  • POJ 1066--Treasure Hunt(判断线段相交)

    Treasure Hunt Time Limit: 1000MS Memory Limit: 10000K Total Submissions...

    Enterprise_
  • SLIC超像素分割详解(二):关键代码分析

    SLIC超像素分割详解(二) 网站http://ivrl.epfl.ch/research/superpixels给出了SLIC的代码。对于其中C++代码的几个...

    用户1150922
  • 一次切割日志引发的血案

    一次切割日志引发的血案 很多应用程序会产生日志,有些程序已经实现了日志切割,一般是每天一个文件。但有时这个切割并不能满足我们的需求,例如我们需要颗粒度更细的切割...

    netkiller old
  • node乞丐版require方法

    在node环境中,每一个文件都是一个模块,解决了命名冲突的问题,node会默认给js加上一个函数,比如一个js文件打印this:

    wade

扫码关注云+社区

领取腾讯云代金券