最近一个月挣扎于千兆网的设备驱动移植,现在终于弄出来了,虽然有点累但是收获还是挺多的。
进入主题前,首先要感谢网友
gorilla0123,他的博客给了我很多启发,在此非常感谢。我建议做网卡驱动这方面的可以参考他的博客,写得很详细,我写的主要是自己遇到的问题以及解决方法。还有很多我不大明白的地方,希望大家多多交流
下面进入主题:
首先是我们自己的开发平台的介绍:
CPU:MPC8313erdb Net:Marvell88E1111
UBOOT:1.3.0版本 LINUX:2.6.23版本
UBOOT下遇到的问题:
因为硬件上的改动并不大,所以直接移植开发板对应的UBOOT之后,TSEC2是可以直接使用的
打印如下信息:
U-Boot 1.3.0 (Apr 2 2013 - 18:30:24) MPC83XX
Reset Status:
CPU: e300c3, MPC8313E, Rev: 21 at 333.333 MHz, CSB: 166 MHz
Board: Freescale MPC8313ERDB
I2C: ready
DRAM: 128 MB
FLASH: 8 MB
NAND:
In: serial
Out: serial
Err: serial
Net: TSEC0 , TSEC1[PRIME]
=>
虚拟机:192.168.1.15
UBOOT下的开发版地址需要自己设置,我设置为:192.168.1.8
通过TSEC1口ping虚拟机(同一个网段)可以返回虚拟机alive。
注意:这里虚拟机是ping不通开发板的
而TSEC0口却ping不通虚拟机,我追踪了两天关于千兆网卡在uboot中的设置,才发现问题出现在我们自己的开发板改了其中一个网卡的硬件地址,所以无法配上
具体如以下代码:
MPC8313ERDB.h 的其中两句定义了千兆网卡的硬件地址
#define TSEC1_PHY_ADDR 3
#define TSEC2_PHY_ADDR 4
改为
#define TSEC1_PHY_ADDR 5
#define TSEC2_PHY_ADDR 4
修改完毕以后重新移植,然后利用两个网卡ping虚拟机,都是alive
UBOOT下两个网卡OK,确定硬件基本没问题
KERNEL下遇到的问题:
通过tftp移植uImage、rootfs.ext2.gz.uboot 、mpc8313erdb.dtb到RAM里去,然后再拷贝到Flash中,这样我们在重启开发板的时候数据不会丢失。
首先简单介绍这三个文件
1、uImage:kernel image。即内核的镜像文件,也就是你要一直到你的开发板上的linux系统(可裁剪,比如:我们的开发板没有USB口,所以我就把USB给注释了)
2、rootfs.ext2.gz.uboot:ramdisk image。文件系统。(我也不知道做什么用的啊!)
3、mpc8313erdb.dtb:设备树是一种描述硬件配置的树形数据结构,有且仅有一个根节点。它包含了有关CPU、物理内存、总线、串口、PHY以及其他外围设备信息等(参考:powerpc_linux设备树dts移植)
移植完这三个文件以后,我遇到一个让我弄了一周的问题:eth1不能使用!
1、platform总线注册
此时/sys/bus/目录下将会有of_platform
2、mdio总线注册
3、platform总线上设备注册
4、mdio总线上的驱动添加
5、platform上的mdio设备驱动添加并绑定设备
6、mdio总线设备添加并绑定驱动
7、platform上的gianfar设备驱动添加并绑定设备
8、gianfar和phy连接
部分解读:
1、我跟踪内核源代码的时候,在完成第三步时候,共注册了三个相关网卡的设备:e0024000.ethernet, e0024520.mdio,e0025000.ethernet ,这个时候并不注册设备e0025520.mdio设备,因为我的两个网卡是连 接到CPU的同一个mdio口
2、platform总线上设备注册完毕以后,到了第五步完成mdio设备驱动添加并绑定设备,即
driver_probe_device() - mdio_bus: Matched Device e0024520:04 with Driver Marvell 88E1111
driver_probe_device() - mdio_bus: Matched Device e0024520:05 with Driver Marvell 88E1111
3、第八步的时候,应该就有gianfar设备驱动添加,并绑定设备e0024000.ethernet和e0025000.ethernet
这个gianfar设备我也不太清楚,但是我的问题就是出现在这里
我打印了一些信息如下:
Setting up networking on loopback device:
Setting up networking on eth0:
init_phy:
priv->einfo->bus_id = 0
priv->einfo->phy_id = 1
gianfar.c : ecntrl = 1050
init_phy:phy_id = 0:01
phy_connect :1phy_id = 0:01
phy_attach:d = c7e4d608
phy_id = 0:01
shit!!!!
phy_connect :2phy_id = 0:01
Adding static route for default gateway to 192.168.1.1:
Setting nameserver to 192.168.1.1 in /etc/resolv.conf:
Setting up networking on eth1:
init_phy:priv->einfo->bus_id = e0024520
priv->einfo->phy_id = 4
gianfar.c : ecntrl = 1050
init_phy:phy_id = e0024520:04
phy_connect :1phy_id = e0024520:04
phy_attach:d = c7e4de08
phy_id = e0024520:04
phy_connect :2phy_id = e0024520:04
Adding static route for default gateway to 192.168.1.1:
Setting nameserver to 192.168.1.1 in /etc/resolv.conf:
通过红色的打印部分我们可以看出其中一个网卡5没有被添加上去,并且被默认的一个网卡驱动给替代了,为什么呢?通过之前的代码分析以及其中一个网卡在linux下也可以使用,我们可以判断:platform总线OK,mdio总线OK,网卡对应的驱动加载上了并且匹配了,问题出在phy_init初始化的地方并与gianfar设备相连上,即设备可能没有初始化成功,而设备的初始化所需要的数据以及配置都是从一个内核配置树上面得到的,即dtb文件,而dtb文件是由dts文件编译过来的二进制文件,dts文件可以用来编辑,所以我们查看以下文件:
ltib-mpc8313erdb-20081222/config/platform/mpc8313erdb/dts/mpc8313erdb.dts
打开查看
mdio@24520 {
device_type = "mdio";
compatible = "gianfar";
reg = <24520 20>;
#address-cells = <1>;
#size-cells = <0>;
phy4: ethernet-phy@4 {
interrupt-parent = < &ipic >;
interrupts = <14 8>;
reg = <4>;
device_type = "ethernet-phy";
};
};
ethernet@24000 {
device_type = "network";
model = "eTSEC";
compatible = "gianfar";
reg = <24000 1000>;
ptimer-handle = < &ptimer >;
local-mac-address = [ 00 00 00 00 00 00 ];
interrupts = <20 8 21 8 22 8>;
interrupt-parent = < &ipic >;
phy-handle = < &phy4 >;
sleep = ;
fsl,magic-packet;
};
ethernet@25000 {
device_type = "network";
model = "eTSEC";
compatible = "gianfar";
reg = <25000 1000>;
ptimer-handle = < &ptimer >;
local-mac-address = [ 00 00 00 00 00 00 ];
interrupts = <23 8 24 8 25 8>;
interrupt-parent = < &ipic >;
phy-handle = < &phy5 >;
sleep = ;
fsl,magic-packet;
};
按照linux内核给的参考 booting-without-of.txt 文件修改为如下:
mdio@24520 {
device_type = "mdio";
compatible = "gianfar";
reg = <24520 20>;
#address-cells = <1>;
#size-cells = <0>;
phy4: ethernet-phy@4 {
interrupt-parent = < &ipic >;
interrupts = <14 8>;
reg = <4>;
device_type = "ethernet-phy";
};
phy5: ethernet-phy@5 {
interrupt-parent = < &ipic >;
interrupts = <14 8>;
reg = <5>;
device_type = "ethernet-phy";
};
};
ethernet@24000 {
device_type = "network";
model = "eTSEC";
compatible = "gianfar";
reg = <24000 1000>;
ptimer-handle = < &ptimer >;
local-mac-address = [ 00 00 00 00 00 00 ];
interrupts = <20 8 21 8 22 8>;
interrupt-parent = < &ipic >;
phy-handle = < &phy4 >;
sleep = ;
fsl,magic-packet;
};
ethernet@25000 {
device_type = "network";
model = "eTSEC";
compatible = "gianfar";
reg = <25000 1000>;
ptimer-handle = < &ptimer >;
local-mac-address = [ 00 00 00 00 00 00 ];
interrupts = <23 8 24 8 25 8>;
interrupt-parent = < &ipic >;
phy-handle = < &phy5 >;
sleep = ;
fsl,magic-packet;
};
然后通过命令:
(dtc -I dts -O dtb -R 8 -S 0x30000 mpc8313erdb.dtb mpc8313erdb.dts 不可行,泪。。。)
dtc -f -b 0 -I dts -O dtb -R 8 -S 0x3000 -o mpc8313erdb.dtb mpc8313erdb.dts
生成dtb文件然后移植,相关网卡信息打印如下:
Setting up networking on loopback device:
Setting up networking on eth0:
init_phy:priv->einfo->bus_id = e0024520
priv->einfo->phy_id = 5
gianfar.c : ecntrl = 1050
init_phy:phy_id = e0024520:05
phy_connect :1phy_id = e0024520:05
phy_attach:d = c7e25c08
phy_id = e0024520:05
phy_connect :2phy_id = e0024520:05
Adding static route for default gateway to 192.168.1.1:
Setting nameserver to 192.168.1.1 in /etc/resolv.conf:
Setting up networking on eth1:
init_phy:priv->einfo->bus_id = e0024520
priv->einfo->phy_id = 4
gianfar.c : ecntrl = 1050
init_phy:phy_id = e0024520:04
phy_connect :1phy_id = e0024520:04
phy_attach:d = c7e25e08
phy_id = e0024520:04
phy_connect :2phy_id = e0024520:04
Adding static route for default gateway to 192.168.1.1:
Setting nameserver to 192.168.1.1 in /etc/resolv.conf:
好了,我们再从新启动系统,一切OK,试一下两个网卡都可以与虚拟机相互ping通
小提示:
有时候直接ping可能ping不通,但是可以试着用下面这个命令改一下开发板网卡的ip地址
ifconfig eth0
ifconfig eth0 up
同理eth1
由于笔者水平有限,传达的信息量很低,希望对大家有帮助,同时欢迎大家和我交流