DM9000网卡驱动移植

首先需要明白下面一点:
我们移植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网卡驱动移植_第1张图片
 
DM9000网卡驱动移植_第2张图片
 
DM9000网卡驱动移植_第3张图片

下面是dm9000芯片资料截图:
DM9000网卡驱动移植_第4张图片
DM9000网卡驱动移植_第5张图片
 
我们先来了解一下对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

你可能感兴趣的:(DM9000网卡驱动移植)