Linux2.6.32移植到MINI2440(4)移植+分析DM9000网卡驱动

开发环境:

    主机:fedora 14

    虚拟机:vmware workstation 10

    交叉编译工具:arm-linux-gcc 4.3.2

    开发板:mini2440(2m nor ,64m sdram,256m nand)

    内核版本:linux2.6.32.2

 

    上一篇帖子的uImage可以起yaffs2文件系统,但是起不了nfs,我的yaffs2使用nfs打包来的,换一个内核可以起,bootargs也没有问题,可能是这里网卡没有移植造成的,移植结束之后再看能不能起,因为nfs对后面做驱动开发优势比较大,方便调试看现象,不需要每次都烧写进去,所以还是需要能够起nfs的。DM9000内核其实已经是支持了,我们需要根据mini2440的具体的硬件资源做添加和修改。

    首先,明确一下mini2440上dm9000的硬件资源,dm9000是直接挂在s3c2440的bank4上面,连接了16条数据线,1条地址线,这条地址线判断是地址还是数据传输,然后通过16条数据线来传输,也就是复用。

一、添加头文件

   在mach-mini2440.c中:

    添加头文件如下:

    #include

 

二、添加物理基地址宏定义

    #define MACH_MINI2440_DM9K_BASE (S3C2410_CS4+0X300)

    这个地址是怎么来的呢,这里S3C2410_CS4指的是BANK4的起始地址:0x20000000,后面加上0x300一开始我理解的是,就像我们烧写到sdram的时候虽然sdram挂在0x30000000上,我们烧写的时候还是会留点余地,烧写到0x30008000,这里的0x300和这个是一个意思,但是不超过128M,这样就到下一个BANK去了。

   

三、添加mini2440_dm9k_resource

static struct resource mini2440_dm9k_resource[]={

    [0] =   {

       .start =   MACH_MINI2440_DM9K_BASE,

       .end   =   MACH_MINI2440_DM9K_BASE+3,

       .flags =   IORESOURCE_MEM

       },

    [1] =   {

       .start =   MACH_MINI2440_DM9K_BASE_4,

       .end   =   MACH_MINI2440_DM9K_BASE+7,

       .flags =   IORESOURCE_MEM

       },

    [2] =   {

       .start =   IRQ_EINT7,

       .end   =   IRQ_EINT7,

       .flags =   IORESOURCE_IRQ|IORESOURCE_IRQ_HIGHEDGE,

       }

};

    这个函数是为了填充平台资源,以便和DM9000接口配合起来。

MACH_MINI2440_DM9K_BASE存放的是要发送的地址,MACH_MINI2440_DM9K_BASE+4存放的是要发送的数据,因为是地址和数据复用,所以要分开传送,两次,0代表地址,1代表数据。一个地址需要四个字节传送,所以每次end都要在start基础上+3,这样就是四个字节的大小。数组2则是跟中断有关的资源。

 

三、设置传送总线位宽

static struct dm9000_plat_data mini2440_dm9k_pdata   =   {

    .flags =   (DM9000_PLATF_16BITONLY|DM9000_PLATF_NO_EEPROM),

    };

四、添加设备注册函数

    static struct platform_device mini2440_device_eth = {

    .name  =   "dm9000",

    .id =   -1,

    .num_resources    =   ARRAY_SIZE(mini2440_dm9k_resource),

    .resource  =   mini2440_dm9k_resource,

    .dev   =   {

       .platform_data    =   &mini2440_dm9k_pdata,

       },

    };

   

五、添加平台设备函数

    在mini2440_devices[]中:

    static struct platform_device*mini2440_devices[] __initdata = {

    &s3c_device_usb,

    &s3c_device_lcd,

    &s3c_device_wdt,

    &s3c_device_i2c0,

    &s3c_device_iis,

    &s3c_device_nand,

    &s3c_device_eth,

};

 

六、修改drivers/net/dm9000.c文件

    添加头文件:

#ifdefined(CONFIG_ARCH_S3C2410)

#include

#endif

    修改dm9000_init函数:

staticint __init

dm9000_init(void)

{

#if defined(CONFIG_ARCH_S3C2410)

       unsigned intoldval_bwscon  =   *(volatile unsigned int *)S3C2410_BWSCON;

       unsigned intoldval_bankcon4    =   *(volatile unsigned int *)S3C2410_BANKCON4;

       *((volatile unsigned int*)S3C2410_BWSCON)    =    (oldval_bwscon&~(3<<16))|S3C2410_BWSCON_DW4_16|S3C2410_BWSCON_WS4|S3C2410_BWSCON_ST4;

       *((volatile unsigned int*)S3C2410_BANKCON4)  =   0x1f7c;

#endif

    printk(KERN_INFO "%s Ethernet Driver,V%s\n", CARDNAME, DRV_VERSION);

 

    return platform_driver_register(&dm9000_driver);

}

这里:

       unsigned int oldval_bwscon  =   *(volatile unsigned int *)S3C2410_BWSCON;

       unsigned intoldval_bankcon4    =   *(volatile unsigned int *)S3C2410_BANKCON4;

    是将两个寄存器的值保存,volatile是防止编译器因为优化省略掉它,要保证每次都去读他的值。

    下面首先设置BWSCON,可以查看datasheet:

Linux2.6.32移植到MINI2440(4)移植+分析DM9000网卡驱动_第1张图片

    这里,oldval_bwscon&~(3<<16)是保留原来寄存器的值,但是对16,17位清零,然后|S3C2410_BWSCON_DW4_16|S3C2410_BWSCON_WS4|S3C2410_BWSCON_ST4这里的三个宏定义如下,在arch/arm/mach-s3c2410/include/mach/regs-mem.h:

    /*bank 4 configurations */

#defineS3C2410_BWSCON_DW4_16      (1<<16)

#defineS3C2410_BWSCON_WS4      (1<<18)

#defineS3C2410_BWSCON_ST4      (1<<19)

    所以再对照datasheet就可知,设置总线位宽为16位,使能WAIT,使用UB/LB。

    在下面对S3C2410_BANKCON4赋值0x1f7c,这个查看datasheet,可以找到寄存器:

Linux2.6.32移植到MINI2440(4)移植+分析DM9000网卡驱动_第2张图片

    这里0x1f7c分解开来就是:0001 1111 0111 1100,可以自行对照datasheet查看其含义。这里应该是跟时序有关的设置,具体不清楚的可以去网上搜dm9000时序相关的帖子,这里知道其含义,不做深究了。

 

七、修改dm9000_probe函数

        if (!is_valid_ether_addr(ndev->dev_addr)){

       /*try reading from mac */

      

       mac_src= "chip";

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

           ndev->dev_addr[i]= ior(db, i+DM9000_PAR);

    }

   

    memcpy(ndev->dev_addr,"\0x08\0x90\0x90\0x90\0x90\0x90",6);

 

    if(!is_valid_ether_addr(ndev->dev_addr))

       dev_warn(db->dev,"%s: Invalid ethernet MAC address. Please "

            "set using ifconfig\n",ndev->name);

    红色字体为添加部分,大概在1463行。这其实添加“软”mac地址,不添加的话,可能无法挂在我们的nfs,很重要的哦。

 

八、编译测试

    #make menuconfig

    DeviceDrivers à

       Networkdevice support à

           Ethernet(10or 100Mbit) à

              <*>DM9000 support

    #make zImage

    转换成uImage烧写到开发板,这里我从nand启动,然后起了yaffs2之后使用ifconfig没有出来东西,然后我修改bootargs,这里我的是:

setenv bootargs console=ttySAC0root=/dev/nfs nfsroot=192.168.1.122:/opt/rootfsip=192.168.1.226:192.168.1.122:192.168.1.122:255.255.255.0:SMDK2440A.arm9.net:eth0:off

然后重新启动,这时候我的nfs就起来了,输出如下信息:

    eth0:link down

    IP-Config: Complete:

    device=eth0, addr=192.168.1.226, mask=255.255.255.0, gw=192.168.1.122,

    host=SMDK2440A, domain=, nis-domain=arm9.net,

    bootserver=192.168.1.122, rootserver=192.168.1.122, rootpath=

    Lookingup port of RPC 100003/2 on 192.168.1.122

    eth0:link up, 100Mbps, full-duplex, lpa 0xDDE1

    Lookingup port of RPC 100005/1 on 192.168.1.122

    VFS:Mounted root (nfs filesystem) on device 0:14.

    Freeinginit memory: 132K

    Pleasepress Enter to activate this console.

    Processing/etc/profile... Done

    / #

    / # ls

    bin      etc     linuxrc  proc     sys     usr

    dev      lib     mnt      sbin     tmp     var

    移植分析结束,如有不正确的地方,还请指出来,大家共同进步!

 

你可能感兴趣的:(OS_Kernel,ARM驱动开发)