17、网卡驱动程序-DM9000举例
(参考:cs89x0.c可以参考)
DM9000 芯片实现网络功能的基础,在接收数据时采用中断方式,即当有数据到来并在 DM9000 内部 CRC 校验通过后会产生一个接收中断;
网卡驱动程序框架:
app: socket
--------------------------------------------------
---------------
--------------- 若干层网络协议--纯软件
---------------
---------------
hard_start_xmit(解析sk_buff结构体,把真实数据发送出去) || /\
\/ || netif_rx sk_buff (构造sk_buff结构体,上传)
---------------
硬件相关的驱动程序(要提供hard_start_xmit, 有数据时要用netif_rx上报)
--------------------------------------------------
硬件
怎么写网卡驱动程序?
1. 分配一个net_device结构体
2. 设置:
2.1 发包函数: hard_start_xmit
2.2 收到数据时(在中断处理函数里)用netif_rx上报数据
2.3 其他设置
3. 注册: register_netdev()
测试1th/2th:
1. insmod virt_net.ko
2. ifconfig vnet0 3.3.3.3
ifconfig // 查看
3. ping 3.3.3.3 // 成功(能成功是因为,ping3.3.3.3的时候先看前面3.3.3.X去寻找同一网段的网卡,在发出去,所以当主机有多个网卡的时候,不要设置为同一个网段,否则程序不知道发给那个网卡)
ping 3.3.3.4 // 死机
(网卡的接口地址和内存一样,直接访问就可以)
(JZ2440中DM9000的片选信号是nGCS4,对应的地址是0x20000000~0x28000000,只要CPU发出的地址位于这区间的地址,nGCS4就会被置起来)
(2440与通过内存控制器与DM9000通讯的,那这个内存控制器读写DM9000的时序应该在init中设置,本驱动没设置的原因是uboot中已经设置好了)
测试DM9000C驱动程序:
1. 把dm9dev9000c.c放到内核的drivers/net目录下
2. 修改drivers/net/Makefile
把 obj-$(CONFIG_DM9000) += dm9000.o
改为 obj-$(CONFIG_DM9000) += dm9dev9000c.o
3. make uImage
使用新内核启动
4. 使用NFS启动 或 ifconfig eth0 192.168.1.17
ping 192.168.1.1
(DM9000能像内存一样读写的原因是其数据线和cpu数据线相连,当访问nGCS4的任何地址区域,发给网卡的不管是地址还是数据,在CPU的角度都是数据)
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上面
比如当在地址0X2000 0000上读写数据时,表示读写的数据是DM9000C的地址
访问的地址0X2000 0004上读写数据时,表示读写的数据是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可以同时结束(bank4地址(也就是CMD)稳定多久后,CS片选才启动)
- 设置Tcos=T1=0(CS片选后,多久才能使能读写)
- 设置Tacc=T2>=10ns=1,表示2个时钟 (access cycle ,读写使能后,多久才能访问数据)
- 设置Tcoh=T4>=3ns=1,表示1个时钟 ,因为当DM9000的写信号取消后,数据线上的数据还需要至少3ns才消失(nOE读写取消后,片选需要维持多长时间)
- 设置Tcah=0,因为 CS和CMD可以同时结束 (CS片选取消后,地址(也就是CMD)需要维持多长时间)
代码如下图,在init入口函数中设置

(PS:若DM9000C无法驱动,可能是Tacc时间太短,导致读取不到数据,可以将Tacc设大一点)
与硬件相关的部分已经改好了,接下来开始编译
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通,说明移植成功


17、网卡驱动程序-DM9000举例的更多相关文章
- Linux DM9000网卡驱动程序完全分析
Linux DM9000网卡驱动程序完全分析http://blog.csdn.net/ypoflyer/article/details/6209922
- DM9000C网卡驱动程序编写与测试
一般网卡驱动程序厂商会给我们提供一份模板驱动,我们的工作就是需要根据自己的需要更改这个模板驱动 1.DM9000C的硬件连接 硬件连接图如下所示:它接在S3C2440的BANK4内存控制器上,它只占用 ...
- 转:Linux网卡驱动程序编写
Linux网卡驱动程序编写 [摘自 LinuxAID] 工作需要写了我们公司一块网卡的Linux驱动程序.经历一个从无到有的过程,深感技术交流的重要.Linux作为挑战微软垄断的强有力武器,日益受到大 ...
- freebsd网卡驱动程序详解
freebsd网卡驱动程序详解 来源 https://blog.csdn.net/h_cszc/article/details/7776116 /* 注释:xie_minix */ /*此处为BSD申 ...
- Linux网卡驱动(4)—DM9000网卡驱动程序完全分析
1.硬件连接 mini2440开发板上DM9000的电气连接和mach-mini2440.c文件的关系 其中片选信号AEN使用了nGCS4,所以网卡的内存区域在BANK4,也就是从地址0x200000 ...
- 嵌入式Linux驱动学习之路(二十六)DM9000C网卡驱动程序
基于DM9000C的原厂代码修改dm9000c的驱动程序. 首先确认内存的基地址 iobase. 确定中断号码. 打开模块的初始化函数定义. 配置内存控制器的相应时序(结合DM9000C.C的手册). ...
- 嵌入式Linux驱动学习之路(二十五)虚拟网卡驱动程序
一.协议栈层次对比 设备无关层到驱动层的体系结构 1).网络协议接口层向网络层协议提供提供统一的数据包收发接口,不论上层协议为ARP还是IP,都通过dev_queue_xmit()函数发送数据,并通过 ...
- Linux下的网卡驱动程序的编写过程(转)
工作需要写了我们公司一块网卡的linux驱动程序.经历一个从无到有的过程,深感技术交流的重要.Linux作为挑战微软垄断的强有力武器,日益受到大家的喜爱.真希望她能在中国迅速成长.把程序文档贴出来,希 ...
- DM9000C网卡驱动程序移植
1.取消版本号不符终止程序运行 2.iobase基地址修改为s3c3440的0x20000000 3.网卡使用的中断号改为IRQ_EINT7 4.中断触发方式改为上升沿触发 5.设置S3C2440的m ...
随机推荐
- 原生JS实现页面内定位
需求:点击跳转到页面指定位置 <div id="test">点击跳转到此处</div> [法一]: 利用a标签的锚点跳转 <a href=" ...
- 【Codeforces Round #428 (Div. 2) B】Game of the Rows
[Link]:http://codeforces.com/contest/839/problem/B [Description] 给你n排的如题目所示的位置; 同一排中(1,2) 算相邻; (3,4) ...
- artDialog提示框、对话框
/** * 警告 * @param {String}消息内容 */ artDialog.alert = function (content, callback) { return artDialog( ...
- 【UML】UML在软件开发各个阶段的应用
一.UML5个互联视图 UML中经常使用5个互联的视图来描写叙述系统的体系结构. 如图 (1)用例视图(Use-case View) 由专门描写叙述可被终于用户.分析人员.測试人员看到的系统行为的用例 ...
- 【翻译自mos文章】OGG的集成捕捉模式支持Oracle database标准版么?
OGG的集成捕捉模式支持Oracle database标准版么? 来源于: Does OGG 11.2.1 Integrated Capture Work with Oracle Database S ...
- IPv6地址表示方法详解
IPv6是互联网协议的第六版:最初它在IETF的 IPng选取过程中胜出时称为互联网新一代网际协议(IPng),IPv6是被正式广泛使用的第二版互联网协议. 现有标准IPv4只支持大概40亿(4×10 ...
- R语言-上海二手房数据分析
案例:通过分析上海的二手房的数据,分析出性价比(地段,价格,未来的升值空间)来判断哪个区位的二手房性价比最高 1.载入包 library(ggplot2) library(Hmisc) library ...
- 使用Notepad++的XML Tools插件格式化XML文件
转自“”:https://blog.csdn.net/qq_36279445/article/details/79803310 1. 安装XML Tools插件 (1) 通过网址http://sour ...
- JS match方法的返回数据的探究
match方法是JS的字符串方法,详细说明可以看MDN的说明. 如果正则表达式匹配成功的话,match方法会返回一个数组,而数组里的数据有两种形式,对应着匹配方式:全局匹配与非全局匹配. 1. 全局匹 ...
- Flask项目之手机端租房网站的实战开发(十三)
说明:该篇博客是博主一字一码编写的,实属不易,请尊重原创,谢谢大家! 接着上一篇博客继续往下写 :https://blog.csdn.net/qq_41782425/article/details/8 ...