Linux-2.6.32.67内核裁剪与移植之DM9000网卡驱动移植(3)

时间:2021-06-27 12:23:13

                                  Linux-2.6.32.67内核裁剪与移植之DM9000网卡驱动移植

                                                                                           作者:赵凯

                                                                                           QQ: 1205958201

  

修改arch/arm/mach-s3c2440/mach-smdk2440.c182行,Platform_device结构体中加入:

static struct platform_device *smdk2440_devices[] __initdata = {

    &s3c_device_usb,

    &s3c_device_lcd,

    &s3c_device_wdt,

    &s3c_device_i2c0,

    &s3c_device_iis,

   &s3c_device_dm9000,

};

修改arch/arm/plat-s3c24xx/devs.c在第38行之后加入:

#include <linux/dm9000.h>

     /*DM9000*/

static struct resource s3c_dm9000_resource[] = {

[0] = {

    .start = S3C2410_CS4,

    .end = S3C2410_CS4 + 3,

    .flags = IORESOURCE_MEM,

},

[1] = {

    .start = S3C2410_CS4 + 4,

    .end = S3C2410_CS4 + 4 + 3,

    .flags = IORESOURCE_MEM,

},

[2] = {

    .start = IRQ_EINT18, /*use eint18 GPG10*/

    .end = IRQ_EINT18,

    .flags = IORESOURCE_IRQ,

}

};

static struct dm9000_plat_data s3c_dm9000_platdata = {

    .flags = DM9000_PLATF_16BITONLY,

};

extern struct platform_device s3c_device_dm9000 = {

    .name = "dm9000",

    .id = 0,

    .num_resources = ARRAY_SIZE(s3c_dm9000_resource),

    .resource = s3c_dm9000_resource,

    .dev = {

    .platform_data = &s3c_dm9000_platdata,

}

};

EXPORT_SYMBOL(s3c_device_dm9000);

arch/arm/plat-s3c/include/plat/devs.h中加入一行:

extern struct platform_device s3c_device_dm9000;

 

修改dm9000.c源码,在drivers/net/dm9000.c中

1. 添加头文件,在第43行加入:

#if defined(CONFIG_ARCH_S3C2410)

#include <mach/regs-mem.h>

#endif

2. 指定注册时的中断触发方式,在第1085行加入:

static int

dm9000_open(struct net_device *dev)

{

    board_info_t *db = netdev_priv(dev);

    unsigned long irqflags = db->irq_res->flags & IRQF_TRIGGER_MASK;

 

    if (netif_msg_ifup(db))

       dev_dbg(db->dev, "enabling %s\n", dev->name);

 

    /* If there is no IRQ type specified, default to something that

     * may work, and tell the user that this is a problem */

 

    if (irqflags == IRQF_TRIGGER_NONE)

       dev_warn(db->dev, "WARNING: no IRQ resource flags set.\n");

 

    irqflags |= IRQF_SHARED;

    #if defined (CONFIG_ARCH_S3C2410)

if(request_irq(dev->irq,&dm9000_interrupt,IRQF_SHARED|IRQF_TRIGGER_RISING,dev->name,dev))

    #else

    if(request_irq(dev->irq,&dm9000_interrupt,IRQF_SHARED,dev->name,dev))

    #endif

    //if (request_irq(dev->irq, &dm9000_interrupt, irqflags, dev->name, dev))

       return -EAGAIN;

 

    /* Initialize DM9000 board */

    dm9000_reset(db);

    dm9000_init_dm9000(dev);

 

    /* Init driver variable */

    db->dbug_cnt = 0;

 

    mii_check_media(&db->mii, netif_msg_link(db), 1);

    netif_start_queue(dev);

   

    dm9000_schedule_poll(db);

    return 0;

}

3. 设置BANK4,设置MAC地址,在1292行,dm9000_probe函数中加入:

dm9000_probe(struct platform_device *pdev)

{

   struct dm9000_plat_data *pdata = pdev->dev.platform_data;

   struct board_info *db;   /* Point a board information structure */

   struct net_device *ndev;

   const unsigned char *mac_src;

   int ret = 0;

   int iosize;

   int i;

   u32 id_val;

   #if defined(CONFIG_ARCH_S3C2410)

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

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

   #endif

/* Init network device */

    ndev = alloc_etherdev(sizeof(struct board_info));

    if (!ndev) {

       dev_err(&pdev->dev, "could not allocate device.\n");

       return -ENOMEM;

    }

。。。。。。

在1305行加入:

SET_NETDEV_DEV(ndev, &pdev->dev);

    dev_dbg(&pdev->dev, "dm9000_probe()\n");

    #if defined(CONFIG_ARCH_S3C2410)

    *((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

 

    /* setup board info structure */

    db = netdev_priv(ndev);

在1469行之后加入:

 

db->mii.mdio_read    = dm9000_phy_read;

    db->mii.mdio_write   = dm9000_phy_write;

#if defined(CONFIG_ARCH_S3C2410)

printk("Now use the default MAC address: 08:90:90:90:90:90 ");

mac_src = "www.txmcu.com";

ndev->dev_addr[0] = 0x08;

ndev->dev_addr[1] = 0x90;

ndev->dev_addr[2] = 0x90;

ndev->dev_addr[3] = 0x90;

ndev->dev_addr[4] = 0x90;

ndev->dev_addr[5] = 0x90;

#else

    mac_src = "eeprom";

 

    /* try reading the node address from the attached EEPROM */

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

       dm9000_read_eeprom(db, i / 2, ndev->dev_addr+i);

 

    if (!is_valid_ether_addr(ndev->dev_addr) && pdata != NULL) {

       mac_src = "platform data";

       memcpy(ndev->dev_addr, pdata->dev_addr, 6);

    }

 

    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);

    }

 

    if (!is_valid_ether_addr(ndev->dev_addr))

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

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

#endif

    platform_set_drvdata(pdev, ndev);

    ret = register_netdev(ndev);

 

    if (ret == 0)

       printk(KERN_INFO "%s: dm9000%c at %p,%p IRQ %d MAC: %pM (%s)\n",

              ndev->name, dm9000_type_to_char(db->type),

              db->io_addr, db->io_data, ndev->irq,

              ndev->dev_addr, mac_src);

    return 0;

 

out:

#if defined(CONFIG_ARCH_S3C2410)

*(volatile unsigned int *)S3C2410_BWSCON = oldval_bwscon;

*(volatile unsigned int *)S3C2410_BANKCON4 = oldval_bankcon4;

#endif

    dev_err(db->dev, "not found (%d).\n", ret);

 

    dm9000_release_board(pdev, db);

    free_netdev(ndev);

 

    return ret;

}

最后是配置内核,支持网卡:

Device Drivers --->

[*] Network device support --->

[*] Ethernet(10 or 100 Mbit) --->

<*> DM9000 support

(4)DM9000 maximum debug level

生成uImage,下载到开发板中:

tftp 0x32000000 uImage;nand erase 0 400000

nand write.jffs2 0x32000000 0 $filesize

这个时候开发板启动内核时候,开发板无法ping通虚拟机。

[root@ZK2440 /]# ping 192.168.1.8

PING 192.168.1.8 (192.168.1.8): 56 data bytes

ping: sendto: Network is unreachable

利用ifconfig查看环境变量发现没有配置网络。

先使用ifconfig命令配置一下网络(重启会失效)

ifconfig eth0 192.168.1.6 netmask 255.255.255.0 up

然后ping主机出现错误:

[root@ZK2440 /]# ping 192.168.1.9

PING 192.168.1.9 (192.168.1.9): 56 data bytes

------------[ cut here ]------------

WARNING: at net/sched/sch_generic.c:261 dev_watchdog+0x148/0x234()

NETDEV WATCHDOG: eth0 (dm9000): transmit queue 0 timed out

Modules linked in:

[<c00509a8>] (unwind_backtrace+0x0/0xdc) from [<c006c5b0>] (warn_slowpath_common+0x48/0x7c)

[<c006c5b0>] (warn_slowpath_common+0x48/0x7c) from [<c006c620>] (warn_slowpath_fmt+0x28/0x38)

[<c006c620>] (warn_slowpath_fmt+0x28/0x38) from [<c02b6a84>] (dev_watchdog+0x148/0x234)

[<c02b6a84>] (dev_watchdog+0x148/0x234) from [<c0075c6c>] (run_timer_softirq+0x160/0x1f4)

[<c0075c6c>] (run_timer_softirq+0x160/0x1f4) from [<c0071444>] (__do_softirq+0x98/0x150)

[<c0071444>] (__do_softirq+0x98/0x150) from [<c004a06c>] (asm_do_IRQ+0x6c/0x88)

[<c004a06c>] (asm_do_IRQ+0x6c/0x88) from [<c004aaa4>] (__irq_svc+0x24/0xa0)

Exception stack(0xc041df78 to 0xc041dfc0)

仔细检查开发板原理图与网卡相关的部分,发现DM9000的第100管脚接的是EINT7,这时候需要修改arch/arm/plat-s3c24xx/devs.c中的一个地方,将

[2] = {

    .start = IRQ_EINT18, /*use eint18 GPG10*/

    .end = IRQ_EINT18,

    .flags = IORESOURCE_IRQ,

}

改为:

[2] = {

    .start = IRQ_EINT7, /*use eint18 GPG10*/

    .end = IRQ_EINT7,

    .flags = IORESOURCE_IRQ,

}

重新生成uImage,下载到开发板中,设置开发板中的ip,网关等,然后ping主机,结果如下:

[root@ZK2440 /]# ping 192.168.1.8

PING 192.168.1.8 (192.168.1.8): 56 data bytes

64 bytes from 192.168.1.8: seq=0 ttl=64 time=6.210 ms

64 bytes from 192.168.1.8: seq=1 ttl=64 time=1.277 ms

64 bytes from 192.168.1.8: seq=2 ttl=64 time=1.340 ms

64 bytes from 192.168.1.8: seq=3 ttl=64 time=1.320 ms

64 bytes from 192.168.1.8: seq=4 ttl=64 time=1.375 ms

64 bytes from 192.168.1.8: seq=5 ttl=64 time=1.361 ms

64 bytes from 192.168.1.8: seq=6 ttl=64 time=1.270 ms

64 bytes from 192.168.1.8: seq=7 ttl=64 time=1.326 ms

64 bytes from 192.168.1.8: seq=8 ttl=64 time=1.354 ms

64 bytes from 192.168.1.8: seq=9 ttl=64 time=1.326 ms

64 bytes from 192.168.1.8: seq=10 ttl=64 time=1.363 ms

64 bytes from 192.168.1.8: seq=11 ttl=64 time=1.070 ms

64 bytes from 192.168.1.8: seq=12 ttl=64 time=1.255 ms

^C

--- 192.168.1.8 ping statistics ---

13 packets transmitted, 13 packets received, 0% packet loss

round-trip min/avg/max = 1.070/1.680/6.210 ms

同时,虚拟机ping开发板的情况如下:

 

[root@localhost linux-2.6.32.67]# ping 192.168.1.6

PING 192.168.1.6 (192.168.1.6) 56(84) bytes of data.

64 bytes from 192.168.1.6: icmp_seq=1 ttl=64 time=1.06 ms

64 bytes from 192.168.1.6: icmp_seq=2 ttl=64 time=1.13 ms

64 bytes from 192.168.1.6: icmp_seq=3 ttl=64 time=1.42 ms

64 bytes from 192.168.1.6: icmp_seq=4 ttl=64 time=1.08 ms

64 bytes from 192.168.1.6: icmp_seq=5 ttl=64 time=1.09 ms

64 bytes from 192.168.1.6: icmp_seq=6 ttl=64 time=1.04 ms

^C

--- 192.168.1.6 ping statistics ---

6 packets transmitted, 6 received, 0% packet loss, time 5647ms

rtt min/avg/max/mdev = 1.046/1.141/1.426/0.136 ms

表明DM9000移植成功。同时为了开发板上电内核保存设置的ip信息。修改etc/init.d/rcS文件,加入如下内容:

ifconfig eth0 192.168.1.6 netmask 255.255.255.0 up

然后开发板重启,利用ifconfig命令查看设置如下:

eth0      Link encap:Ethernet  HWaddr 08:90:90:90:90:90 

          inet addr:192.168.1.6  Bcast:192.168.1.255  Mask:255.255.255.0

          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1

          RX packets:3 errors:0 dropped:0 overruns:0 frame:0

          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0

          collisions:0 txqueuelen:1000

          RX bytes:192 (192.0 B)  TX bytes:0 (0.0 B)

          Interrupt:51 Base address:0xe000

说明设置成功。