Linux2.6 下DM9000网卡驱动

 

Linux2.6.14 下已经有DM9000的驱动源代码,我们要做的工作是使内核支持它,移植的关键是接口与中断。其它工作就完全交给源代码了。

移植工作包括三件事情:

1、 要让系统能检测到DM9000

2、 初始化DM9000,

3、 让驱动找到收发的接口,也就是中断。

 

DM9000网卡驱动的移植探索过程较复杂。以下是我整理的全部过程:

 

Linux2.6内核加入了设备平台与设备驱动的概念:platform_device 和platform_driver

说明:根据华恒的资料,DM9000占用S3C2410的片选CS1,即0X08000000。占用外部中断:EINT0。DM9000 默认I/0 基地址为300H。CMD 引脚用于设置COMMAND 模式,CMD为高时,选择数据端口。CMD为低时,选地址端口。数据端口和地址端口的地址码由下式决定:

  DM9000地址端口=高位片选地址+300H

  DM9000数据端口=高位片选地址+300H+4H

一:打开linux-2.6.14/ach/arm/mach-s3c2410/devs.c文件。

 

增加:include <linux/dm9000.h>

把DM9000的平台设备加进去。最后用EXPORT_SYMBOL(s3c_device_dm9000) 声明。被mach-smdk2410.c调用。

 

static struct resource s3c_dm9000_resource[] = {

[0] = {

.start =  S3C2410_CS1+0x300,

.end   = S3C2410_CS1+0x300+0x3,

.flags = IORESOURCE_MEM,

},

[1]={

.start = S3C2410_CS1+0x300+0x4,

.end = S3C2410_CS1+0x300+0x4+0x7c,

.flags = IORESOURCE_MEM,

},

[2] = {

.start = IRQ_EINT0,

.end   = IRQ_EINT0,

.flags = IORESOURCE_IRQ,

}

};

 

static struct dm9000_plat_data s3c_device_dm9000_platdata = {

.flags= DM9000_PLATF_16BITONLY,

};

 

struct platform_device s3c_device_dm9000 = {

.name= "dm9000",

.id= -1,

.num_resources= ARRAY_SIZE(s3c_dm9000_resource),

.resource= s3c_dm9000_resource,

.dev= {

.platform_data = &s3c_device_dm9000_platdata,

}

};

EXPORT_SYMBOL(s3c_device_dm9000);      

 

二:在devs.h 中加入以下这句声明:

extern struct platform_device s3c_device_dm9000;  

 

三:打开arch/arm/mach-s3c2410/mach-smdk2410.c将dm9000加入到要初始化的设备链表里去,内核启动时将会检测设备并加载驱动。

static struct platform_device *smdk2410_devices[] __initdata = {

       &s3c_device_usb,

       &s3c_device_lcd,

       &s3c_device_wdt,

       &s3c_device_i2c,

       &s3c_device_iis,

       &s3c_device_dm9000,  //add here

};

 

四:在驱动源代码里,加入:使能EINT0中断,设备中断类型,总线带宽和等待时间控制,BANKCON1总线控制。

所有要用到的寄存器所在的物理地址以及各位参数的意义参考S3C2410用户手册。

打开linux-2.6.14/driver/net/dm9000.c

在开头部分加入CPU中断寄存器的地址定义:

#define BWSCON  (0x48000000)  //总线带宽和等待时间控制寄存器

#define BANKCON1 (0x48000008)  // BANKCON1总线控制

#define EXTINT0  (0x56000088)   //EINT0号中断控制

#define INTMSK  (0x4A000008)   //中断使能控制

#define INTMOD  (0x4A000004)   //中断类型控制

 

找到dm9000_probe() 函数,

该函数在模块加载时被调用。作用是探测设备,并记录设备型号和相关信息,在

该函数中要设置相关的中断。把控制字写入相关寄存器。

在函数开始部分加入以下内容:

 

 

 

 

static void *bwscon, *bankcon1, *extint0, *intmsk, *intmod;

bwscon=ioremap_nocache(BWSCON, 4);

bankcon1=ioremap_nocache(BANKCON1, 4);

ettint0=ioremap_nocache(EXTINT0, 4);

intmsk=ioremap_nocache(INTMSK, 4);

intmod=ioremap_nocache(INTMOD, 4);

 

writel(readl(bwscon)|0xc0, bwscon); //设置总线带宽和等待时间控制寄存器
writel(readl(bankcon1)|0x1f7c, bankcon1);  //设置片选1
writel(readl(intmsk)&0xfff7,intmsk); //使能EINT0中断

writel(readl(intmod)&0xfffffffe,intmod);//设置EINT0为IRQ,重要!

writel(readl(extint0)|0x4, extint0); //设置中断为上升缘触发

iounmap(bwscon);

iounmap(bankcon1);

iounmap(extint0);

iounmap(intmsk);

iounmap(intmod);

 

说明:ioremap_nocache()函数的功能是把相关寄存器的物理地址映射为虚拟地址,因为内核不能处理物理地址的。第一个参数是物理地址,第二个参数是大小。该函数返回一个虚拟地址。供内核调用处理。函数writel()将向IO写入32位的控制字。writel()函数的第一个参数是要写入的值,第二个参数是地址。

在函数ioremap_nocache()中获得的虚拟地址要被iounmap()释放。

 

五:设置MAC 地址:

还是在probe()函数中,

在该函数开头部分加入MAC地址数组:

unsigned char ne_eth_mac_addr[]={

       0x00,0x12,0x34,0x56,0x78,0x49};

这时要把原来的设置MAC地址的两行代码注释掉:

/*for(i=0;i<6;i++)

{dev->dev_addr[i]=db->srom[i]; 

}   */

然后在驱动函数初始化之后(在上面被注释掉的地方)设置MAC地址值加入以代码:

/*set mac address*/

for(i=0;i<6;i++)

{

       ndev->dev_addr[i]=ne_eth_mac_addr[i];

}

 

说明:之所以把它注释掉,是因为在ROM里读出来的MAC是全零。MAC数组里可以随便设置,只要不是全0或者全1的6组数据。dev_addr[]是net_device里的成员,记录着MAC地址。

 

调试的过程中,可以用printk()函数跟踪调试,看是否有输出。然后确定错误的出处,驱动要打交道的是硬件,所以一定要看S3C2410 user manul,以及华恒提供的技术手册,因为整个硬件平台上的连线是华恒公司决定的。

DM9000移植过程中,关键是中断的设置,中断是否申请成功。主要是设置INTMOD寄存器的值,使申请的EINT0不会变成FIQ,我们只需要IRQ,否则驱动无法加载,中断的申请在open()函数中,如果中断设置不正确,虽然驱动可以探测出网卡的信息,但用ifconfig eth0 up的时候会出错。用户空间调用eth0 up的时候,会调用到内核空间的open()函数。

 

 以下是加载网卡后出现的主要问题以及解决方法:

1:可以ping 通主机,但不能ping通自己。调用ifconfig 后发现只有网卡eth0

方法:启动虚拟网卡lo ,这是一个不真实存在的网卡。

ifconfig lo 127.0.0.1

也可以在文件系统的etc/init.d/rc.S启动文件中加入以下两句:

ifconfig eth0 192.168.2.222

ifconfig lo 127.0.0.1

这样系统启动后会自动启动这两块网卡。

 

2:网络可以ping通自己,也可以ping通主机。但不能mount主机。

方法:内核配置里要选上

File systemsà

       Network file systems-à

                            [*]NFS file system support

                            [*]Provide NFSv3 client support

 

在BUSYBOX-1.2.0里选上

Linux System Utilitiesà

              [*]mount

                 [*]Support mounting NFS file systems

这里建议最好使用BUSYBOX-1.2.0,多次试验发觉其它的版本的BUSYBOX使用情况都不够理想,然后把生成的_install目录下的bin sbin目录覆盖原来文件系统的两个目录。如果还是无法MOUNT宿主机,就换BUSYBOX,直到可行为止。

       一点疑问:DM9000占用外部0号中断,CPU的中断号应该是0,但查看内核源代码,EINT0为16,上网查看资料,原来LINUX2.6保留了16号之前的中断,所以我们只能申请16号之后的中断源,EINT0=16。只能这样理解了,但DM9000中断接的是外部中断0,这是硬件的连接,我们不能更改的,怎么能用16号中断取代0号中断??无法理解。

                                                      

 05电子 陈培泽

                                                                                                                2009.1.10

你可能感兴趣的:(c,linux,struct,cmd,File,resources)