DM9000网驱动移植

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/huhuolianmeng/article/details/71126685

DM9000网驱动移植

函数分析,
/*
* CPU and board-specific Ethernet initializations. Aliased function
* signals caller to move on
*/
static int __def_eth_init(bd_t *bis)
{
return -1;
}
int cpu_eth_init(bd_t *bis) attribute((weak, alias(“__def_eth_init”)));
int board_eth_init(bd_t *bis) attribute((weak, alias(“__def_eth_init”)));
意思是:给cpu_eth_init和board_eth_init都起了同一个弱函数
名字,如果你没有定义其他函数(与刚才起别名的函数相同)的话就是用这个函数__def_eth_init

最后会返回 -1
weak, 弱名称
if (board_eth_init != __def_eth_init) {
if (board_eth_init(bis) < 0)
printf(“Board Net Initialization Failed\n”);
} else if (cpu_eth_init != __def_eth_init) {
if (cpu_eth_init(bis) < 0)
printf(“CPU Net Initialization Failed\n”);
} else
printf(“Net Initialization Skipped\n”);

上啊面的函数就是:如果你定义了board_eth_init 这个if (board_eth_init != __def_eth_init)成立,执行函数‘
如果你没定义则是不成立,就不会i执行。。。我们函数中没有定义,所以不执行。。。
if (!eth_devices) {
puts(“No ethernet found.\n”);/打印信息有这个解决*/
bootstage_error(BOOTSTAGE_ID_NET_ETH_START);
} else {
struct eth_device *dev = eth_devices;
char *ethprime = getenv(“ethprime”);
eth_devices 搜索找到下面的全局变量:
static struct eth_device *eth_devices;指针eth_devices(用来指向一个链表,这个链表中保存了当前系统中所有的网卡信息)
struct eth_device *eth_current;指针 eth_current(eth_current指针指向当前我们正在操作的那个网卡)。
指向这里:
struct eth_device {(网卡信息)
char name[16];
unsigned char enetaddr[6];
int iobase;
int state;

int  (*init) (struct eth_device *, bd_t *);
int  (*send) (struct eth_device *, void *packet, int length);
int  (*recv) (struct eth_device *);
void (*halt) (struct eth_device *);

ifdef CONFIG_MCAST_TFTP

int (*mcast) (struct eth_device *, u32 ip, u8 set);

endif

int  (*write_hwaddr) (struct eth_device *);
struct eth_device *next;
int index;
void *priv;

};
(1)因为我们没有自定义的网卡初始化函数(board_eth_init或者cpu_eth_init),所以uboot启动时初始化网卡时打印:Net: Net Initialization Skipped
(2)eth.c中有2个很重要的全局变量:eth_devices(用来指向一个链表,这个链表中保存了当前系统中所有的网卡信息)和eth_current(eth_current指针指向当前我们正在操作的那个网卡)。
(3)在linux的网卡驱动体系中,有一个数据结构(struct eth_device)用来表示(封装)一个网卡的所有信息,系统中注册一个网卡时就是要建立一个这个结构体的实例,然后填充这个实例中的各个元素,最后将这个结构体实例加入到eth_devices这个链表上,就完成了注册。了解了这些之后,你就明白了网卡驱动在初始化时必须负责将自己注册到系统的网卡驱动体系中(其实就是把自己的eth_device结构体实例添加到eth_devices链表中)。如果你不做这个过程就会出现:网卡找不到的错误。
if (!eth_devices) {
puts(“No ethernet found.\n”);/打印信息需要解决*/
bootstage_error(BOOTSTAGE_ID_NET_ETH_START);
} else {
struct eth_device *dev = eth_devices;
char *ethprime = getenv(“ethprime”);

(4)分析当前的问题是:在305行判断eth_devices是否为NULL之前没有去做网卡驱动的注册,所以这里为NULL,所以打印出了“No ethernet found.”

5.想解决问题,就是要在305行之前去注册网卡驱动。注册网卡驱动的代码不能随便乱写,一定要遵守linux网卡驱动架构的要求。这一块的代码一般属于网卡驱动的一部分,像这里就在dm9000x.c中。
(2)dm9000x.c中的最后一个函数int dm9000_initialize(bd_t *bis),这个函数就是用来注册dm9000网卡驱动的。
实例化:::struct eth_device *dev 及填充
int dm9000_initialize(bd_t *bis)
{
struct eth_device *dev = &(dm9000_info.netdev);

/* Load MAC address from EEPROM */
dm9000_get_enetaddr(dev);

dev->init = dm9000_init;
dev->halt = dm9000_halt;
dev->send = dm9000_send;
dev->recv = dm9000_rx;
sprintf(dev->name, "dm9000");

eth_register(dev);(注册网卡在这里 链表 )

return 0;

}
int eth_register(struct eth_device *dev)
{
struct eth_device *d;
static int index;

assert(strlen(dev->name) < sizeof(dev->name));

if (!eth_devices) {
    eth_current = eth_devices = dev;(如果是一个的话)
    eth_current_changed();
} else {
    for (d = eth_devices; d->next != eth_devices; d = d->next)(如果还是多个的话,遍历链表插入,尾插)
        ;
    d->next = dev;
}

dev->state = ETH_STATE_INIT;
dev->next  = eth_devices;
dev->index = index++;

return 0;

}
问题修复
(1)根据之前分析uboot函数,发现前面有2个函数预留的可以用来放网卡初始化函数的,经过对比感觉board_eth_init函数稍微合适点,于是乎去添加。board_eth_init
新建一个函数即可

猜你喜欢

转载自blog.csdn.net/huhuolianmeng/article/details/71126685
今日推荐