Linux-2.6.32.67内核裁剪与移植之DM9000网卡驱动移植
作者:赵凯
QQ: 1205958201
修改arch/arm/mach-s3c2440/mach-smdk2440.c的182行,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
说明设置成功。