【引用】Linux-2.6.32.2内核在mini2440上的移植(三)---DM9000网卡驱动移植

时间:2020-11-30 17:12:44

移植环境(红色粗字体字修改后内容,蓝色粗体字为特别注意内容)

1,主机环境:VMare下CentOS 5.5 ,1G内存。

2,集成开发环境:Elipse IDE

3,编译编译环境:arm-linux-gcc v4.4.3,arm-none-linux-gnueabi-gcc v4.5.1。

4,开发板:mini2440,2M nor flash,128M nand flash。

5,u-boot版本:u-boot-2009.08

6,linux 版本:linux-2.6.32.2

7,参考文章:

【1】嵌入式linux应用开发完全手册,韦东山,编著。

【2】Mini2440 之Linux 移植开发实战指南

【3】http://linux.chinaunix.net/techdoc/system/2009/08/24/1131864.shtml

3.1,移植DM9000 网卡驱动

【1】设备资源初始化

Linux-2..6.32.2 已经自带了完善的DM9000 网卡驱动驱动(源代码位置:linux-2.6.32.2/drivers/net/dm9000.c),它也是一个平台设备,因此在目标平台初始化代码中,只要填写好相应的结构表即可,具体步骤如下:
(1)确认已经添加了驱动所需的头文件 dm9000.h:

用gedit打开linux-2.6.32.2/arch/arm/mach-mini2440.c,定位到55行附近,加入dm9000.h,如下所示:

#include <plat/common-smdk.h>

#include <linux/mtd/mtd.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/nand_ecc.h>
#include <linux/mtd/partitions.h>
#include <plat/nand.h>
#include <linux/dm9000.h>

(2)填充该平台设备的资源设置

定位到210行附近,如入下面代码:

tatic struct s3c2410_platform_nand mini2440_nand_info = {
 .tacls  = 20,
 .twrph0  = 60,
 .twrph1  = 20,
 .nr_sets = ARRAY_SIZE(mini2440_nand_sets),
 .sets  = mini2440_nand_sets,
 .ignore_unset_ecc = 1,
};
/* DM9000AEP 10/100 ethernet controller */  //定义DM9000 网卡设备的物理基地址,以便后面用到
#define MACH_MINI2440_DM9K_BASE (S3C2410_CS4 + 0x300)

//再填充该平台设备的资源设置,以便和 DM9000 网卡驱动接口配合起来

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,
        }
};
/*
 *  * The DM9000 has no eeprom, and it\'s MAC address is set by
 *   * the bootloader before starting the kernel.
 *    */
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,
        },
};
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,  //;把nand flash 设备添加到开发板的设备列表结构
 &mini2440_device_eth,  //;把网卡平台设备添加到开发板的设备列表结构
};

static void __init mini2440_map_io(void)

【2】调整DM9000 所用的位宽寄存器

因为 Linux-2.6.32.2 的DM9000 网卡驱动并不是专门为mini2440 准备的,所以还要在其源代码中做一些移植工作,如下步骤。

(1)打开linux-2.6.32.2/drivers/net/dm9000.c,定位到41行附近,添加2410 相关的配置定义,如下红色部分:

#include <asm/delay.h>
#include <asm/irq.h>
#include <asm/io.h>

#include \"dm9000.h\"
#if defined(CONFIG_ARCH_S3C2410)
#include <mach/regs-mem.h>
#endif

(2) 在dm9000 设备的初始化函数中添加如下红色部分,这里是配置DM9000 所用片选总线的时序,因为mini2440 目前只有一个通过总线外扩的设备,在此设备驱动中直接修改相关的寄存器配置会更加容易理解一些,当然这部分也可以放到mach-mini2440.c 中。

打开linux-2.6.32.2/drivers/net/dm9000.c,定位到1555行附近,加入下面代码:

static int __init
dm9000_init(void)
{
#if defined(CONFIG_ARCH_S3C2410)
 unsigned int oldval_bwscon = *(volatile unsigned int *)S3C2410_BWSCON;
 unsigned int oldval_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);
}

【3】需要注意的是,本开发板所用的DM9000 网卡并没有外接EEPROM 用以存储MAC 地址,因此系统中的MAC 地址是一个“软”地址,也就是可以通过软件进行修改,可以随意改为其他值。

打开linux-2.6.32.2/drivers/net/dm9000.c,定位到1461行附近,加入下面一行代码:

static int __devinit
dm9000_probe(struct platform_device *pdev)
{

... ...

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

//;尝试从EEPROM 读取MAC 地址
 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\