DM9000網驅動移植

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
新建一個函數即可

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章