S3C2440嵌入式Linux下网卡DM9000E移植

在mini2440上移植DM9000E网卡的参考步骤如下:

一、看电路图

在mini2440开发板上移植好Linux-2.6.29.1内核和根文件系统的基础上,进行网卡DM9000E的移植,因为手里面有韦东山写的《嵌入式Linux应用开发完全手册》一书,在书中找到了DM9000网卡移植部分,对照该书与友善光盘里面的原理图,移植之前先从看原理图开始。看了DM9000E与S3C2440的电路图发现:

1、DM9000E挂接到S3C2440总线

S3C2440通过总线来访问DM9000E。mini2440访问DM9000E的物理地址的基址是BANK4,用到一条地址线ADDR2,对应DM9000E的CMD引脚,,因为DM9000E的地址信号和数据信号复用,CMD引脚决定传输的是地址信号还是数据信号,于是地址线ADDR2的引脚状态决定了DM9000E与S3C2440传输的是地址信号还是数据信号。

2、总线位宽16,用到nWAIT信号

3、DM9000E收到完整的数据包,通过中断引脚通知S3C2440来接收数据包,与S3C2440相连的中断引脚为EINT7。

二、网卡驱动程序修改

修改内核中网卡驱动程序时需要先结合所使用的内核,先查看当前内核是否支持该网卡,如果不支持需要查找支持该网卡的驱动程序进行修改。我用的是Linux-2.6.29.1内核,该内核已经对DM9000E具有很好的支持了,这在内核的Documentation/networking/dm9000.txt中有对内核中dm9000驱动程序详细地说明,其中如下部分说明Linux-2.6.29.1内核对DM9000E网卡的友好支持。

一些低版本的内核(比如linux-2.6.13等)对DM9000E不支持,可以用其它内核版本的dm9000.c驱动程序添加到内核中,进行修改和配置。由于这里使用的内核已经对DM9000E网卡具有很好的支持,只需简单的配置和修改即可。
1、修改DM9000平台设备
修改/arch/arm/plat-s3c24xx/common-smdk.c文件

(1)、添加要包含的头文件

#if defined(CONFIG_DM9000) || defined(CONFIG_DM9000_MODULE)
#include
#endif
(2)、添加DM9000的平台设备结构

#if defined(CONFIG_DM9000) || defined(CONFIG_DM9000_MODULE)
/*DM9000*/
static struct resource s3c_dm9k_resource[]={
[0] = {
.start = S3C2410_CS4, //ADDR2 = 0
.end = S3C2410_CS4 + 3,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = S3C2410_CS4 + 4, //ADDR2 = 1
.end = S3C2410_CS4 + 4 + 3,
.flags = IORESOURCE_MEM,
},
[2] = {
.start = IRQ_EINT7,
.end = IRQ_EINT7,
.flags = IORESOURCE_IRQ,
}
};
static struct dm9000_plat_data s3c_dm9k_platdata = {
.flags = DM9000_PLATF_16BITONLY,
};
static struct platform_device s3c_device_dm9k = {
.name = "dm9000",
.id = 0,
.num_resources = ARRAY_SIZE(s3c_dm9k_resource),
.resource = s3c_dm9k_resource,
.dev = {
.platform_data = &s3c_dm9k_platdata,
}
};
#endif


(3)、将DM9000平台设备加入内核设备列表中

/* devices we initialise */
static struct platform_device __initdata *smdk_devs[] = {
&s3c_device_nand,
&smdk_led4,
&smdk_led5,
&smdk_led6,
&smdk_led7,
#if defined(CONFIG_DM9000) || defined(CONFIG_DM9000_MODULE)
&s3c_device_dm9k,
#endif
};
2、修改drivers/net/dm9000.c
dm9000.c中包含dm9000_probe函数,该函数完成DM9000设备的枚举,dm9000_probe函数的介绍在《嵌入式Linux应用开发完全手册》一书中详细介绍。
(1)、添加必要的头文件
#if defined(CONFIG_ARCH_S3C2410)
#include
#endif
在《嵌入式Linux应用开发完全手册》一书中上面的#include是#include ,这使得我编译通不过,被我改成#include后编译成功,这是不同版本内核文件的程序所在文件的差别造成。
(2)、在dm9000_probe中设置存储器使BANK4可用,设置默认MAC地址(也可以在根文件系统启动脚本设置),添加的代码如下:
/*
* Search DM9000 board, allocate space and register it
*/
static int __devinit
dm9000_probe(struct platform_device *pdev)
{

#if defined(CONFIG_ARCH_S3C2410)
unsigned int oldval_bwscon; //用来保存BWSCON寄存器的值
unsigned int oldval_bankcon4; //用来保存S3C2410_BANKCON4寄存器的值
#endif

#if defined (CONFIG_ARCH_S3C2410)
//设置BANK4:总线宽度为16,使能nWAIT
oldval_bwscon = *((volatile unsigned int *)S3C2410_BWSCON);
*((volatile unsigned int *)S3C2410_BWSCON) = (oldval_bwscon & ~(3<<16)) \
| S3C2410_BWSCON_DW4_16 | S3C2410_BWSCON_WS4 | S3C2410_BWSCON_ST4;
//设置BANK4的时间参数
oldval_bankcon4 = *((volatile unsigned int *)S3C2410_BANKCON4);
*((volatile unsigned int *)S3C2410_BANKCON4) = 0x1f7c;
#endif

if (!is_valid_ether_addr(ndev->dev_addr))
dev_warn(db->dev, "%s: Invalid ethernet MAC address. Please "
"set using ifconfig\n", ndev->name);
#if defined(CONFIG_ARCH_S3C2410)
printk("Now use the default MAC address:08:90:90:90:90:90\n");
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;
#endif

out:
printk("%s:not found (%d).\n",CARDNAME,ret);
#if defined(CONFIG_ARCH_S3C2410)
*((volatile unsigned int *)S3C2410_BWSCON) = oldval_bwscon;
*((volatile unsigned int *)S3C2410_BANKCON4) = oldval_bankcon4;
#endif
(3)、指定注册中断时的触发方式
dm9000_open(struct net_device *dev)
{

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;

}

相关推荐