DM9000网卡驱动移植

本文详细介绍了DM9000网卡驱动的移植步骤,包括修改基地址、设置中断号、注册中断处理函数等内容,并给出了具体的代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

首先需要明白下面一点:
我们移植dm9000网卡驱动程序,要做的就是找出最小相异性,然后修改。这里的最小相异性是:基地址、位宽、中断引脚等信息

移植过程:
1、入口函数和出口函数改为:dm9000c_initdm9000c_exit,添加修饰函数:module_init(dm9000c_init);module_exit(dm9000c_exit);

2、修改基地址:dm9000c_init函数中添加iobase = (int)ioremap(0x20000000, 1024);当然也要在dm9000c_exit函数中加上这么一句:iounmap((void *)iobase);
分析:我们的dm9000网卡接在2440的BANK4,所以其基地址是0x20000000

3、注释掉dmfe_probe1函数中的这一句://if((db->chip_revision!=0x1A) || ((chip_info&(1<<5))!=0) || ((chip_info&(1<<2))!=1)) return -ENODEV;

4、设置中断号:dm9000c_init函数中添加下面一句:irq    = IRQ_EINT7; 
分析:当网卡收到数据时,会产生中断,在这个中断处理函数中,将会处理接收到的数据包。那么这个中断的中断号是什么呢?我们查看原理图发现使用的是外部中断7,所以加上这么一句。

5、注册中断处理函数:在dmfe_open函数中将:
if (request_irq(dev->irq,&dmfe_interrupt,0,dev->name,dev)) 
改为
if (request_irq(dev->irq,&dmfe_interrupt, IRQF_TRIGGER_RISING,dev->name,dev))

6、包含一下头文件:
#include <asm/delay.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <asm/arch-s3c2410/regs-mem.h>

7、我们在dm9000c_init函数中加入如下代码:

volatile unsigned long *bwscon; 
volatile unsigned long *bankcon4;
unsigned long val;

bwscon   = ioremap(0x48000000, 4);//总线位宽和等待控制寄存器
bankcon4 = ioremap(0x48000014, 4);//存储器4控制寄存器

val = *bwscon;
val &= ~(0xf<<16);
val |= (1<<16);
*bwscon = val;//设置位宽、是否等待等信息,详见注释1

*bankcon4 = (1<<8)|(1<<6);//设置各种时间参数,详见注释2

  iounmap(bwscon);
iounmap(bankcon4);

注释1:
bswcon寄存器可以对bankcon0--bankcon7进行设置,我们要设置的是bankcon4
bit[16:17]:设置位宽,00:8位  01:16位  10:32位  11:保留。我们是16位的。
bit[18]     :使用/禁用存储器组的WAIT位,1表示使用,0表示禁用。我们禁止使用
bit[19]     :控制存储器组的UB/LB引脚输出信号,1:使UB/LB与nBE[3:0]相连,0:使UB/LB与与nWBE[3:0]相连。我们设为0

注释2:
关于时间参数的设置比较复杂,贴出几张截图先:
2440截图:
DM9000网卡驱动移植 - 小白 - 小白的博客
 
DM9000网卡驱动移植 - 小白 - 小白的博客
 
DM9000网卡驱动移植 - 小白 - 小白的博客

下面是dm9000芯片资料截图:
DM9000网卡驱动移植 - 小白 - 小白的博客
DM9000网卡驱动移植 - 小白 - 小白的博客
 
我们先来了解一下对dm9000寄存器的操作:
outb(DM9KS_VID_L, iobase);//将要操作的寄存器地址写入DM9000C的索引寄存器
id_val = inb(iobase + 4);//从DM9000C的数据寄存器里读出数据
 那么怎么分辨是操作的索引寄存器还是数据寄存器呢?就是通过CMD引脚!我们看到CMD引脚接的是LADDR2,当LADDR2为0时表示操作的是索引寄存器,当LADDR2为1时,表示操作的是数据寄存器。
DM9000的地址线只有LADDR2。

下面我们开始正式分析:

从上面的图中我们找到如下对应关系:
Tacs:表示发出片选信号之前,多长时间内要先发出地址信号,有dm9000时序图知她们可以同时发出,所以Tacs=0
Tcos:表示片选信号发出后需要多长时间才能发出读信号,它对应T1>=0ns,Tcos=0
Tacc:表示读信号的长度,对应T2>=10ns,Tacc=001
Tcoh:表示读信号接收后片选信号要保持的时间,对应T5>=0,我们取为10ns,Tcoh=01
Tcah:表示片选信号之后,地址信号保持的时间,她们可以同时,Tcah=0
Tacp:表示页模式下的访问周期,不用设置
PMC:表示页模式配置,PMC=00表示正常模式

所以:*bankcon4 = (1<<8)|(1<<6);

测试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   

我们看到网卡可用了!很开心哦!
我们再来补充一点内存控制器的知识:
我们知道2440的cpu里面集成了内存控制器,内存控制器外接一些存储设备。我们来分析一下下面代码的执行情况
mov r1,#0
ldr R0,[R1]
这表示cpu要从0地址读4个字节的内容,如果外接存储设备的位宽为16,这怎么实现呢?这里内存控制器就发挥了很大的作用!
首先内存控制器已经知道了外接设备的位宽,它首先发出0地址,得到两个字节的数据。然后发出2地址,又得到两个字节的数据。将4个字节的数据交给cpu就可以了。为了实现这一点,外接存储设备的0地址要与cpu的1地址相连,以此类推。这样的话,发出2地址时,对外接设备来说是1地址,它会将1地址开始的2个字节数据交给cpu。

我们在来分析一下下面的代码:
mov R1,#3
ldb R0,[R1]
首先发出地址3,从外接设备的地址1读出2字节的数据。内存控制器取出高字节的8位,送给cpu
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值