u-boot下網路驅動程式的修改
Eth.c工作之前的初始化
static struct eth_device *eth_devices, *eth_current;
Eth.c中有個eth_devices需要外部呼叫函式eth_register做初始化工作,其它函式(除eth_initialize外)都必須在這個初始化之後才能使用。
結構eth_devices是個迴圈連結串列,可包含多個eth_device。eth_register每次呼叫新增一個結構,呼叫多次可生成迴圈連結串列。eth_devices指向連結串列的第1個元素。
at91sam9260ek中先呼叫eth_initialize,在此函式中呼叫Eth.c:eth_register
board.c:呼叫Eth.c:eth_initialize()
呼叫at91sam9260ek.c: board_eth_init()
呼叫macb.c: macb_eth_initialize()
呼叫Eth.c: eth_register()。
int eth_register(struct eth_device* dev) { struct eth_device *d; if (!eth_devices) { eth_current = eth_devices = dev; #ifdef CONFIG_NET_MULTI /* update current ethernet name */ { char *act = getenv("ethact"); if (act == NULL || strcmp(act, eth_current->name) != 0) setenv("ethact", eth_current->name); } #endif } else { for (d=eth_devices; d->next!=eth_devices; d=d->next) ; d->next = dev; } dev->state = ETH_STATE_INIT; dev->next= eth_devices; return 0; } |
如果移植新的網絡卡驅動的話,應在board_eth_init中初始dev並呼叫eth_register。
eth_initialize
int eth_initialize(bd_t *bis) { unsigned char env_enetaddr[6]; int eth_number = 0; eth_devices = NULL; eth_current = NULL; show_boot_progress (64); #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) miiphy_init(); #endif /* Try board-specific initialization first.If it fails or isn't * present, try the cpu-specific initialization */ if (board_eth_init(bis) < 0)//呼叫board_eth_init,此函式內部實現初始化eth_devices和eth_current,並呼叫eth_register(struct eth_device* dev)。 cpu_eth_init(bis); #if defined(CONFIG_DB64360) || defined(CONFIG_CPCI750) mv6436x_eth_initialize(bis); #endif #if defined(CONFIG_DB64460) || defined(CONFIG_P3Mx) mv6446x_eth_initialize(bis); #endif if (!eth_devices) { puts ("No ethernet found./n"); show_boot_progress (-64); } else { struct eth_device *dev = eth_devices; char *ethprime = getenv ("ethprime"); show_boot_progress (65); do { if (eth_number) puts (", "); printf("%s", dev->name); //如果找到環境變數”ethprime”,則將eth_current指向當前eth_device。 if (ethprime && strcmp (dev->name, ethprime) == 0) { eth_current = dev; puts (" [PRIME]"); } //讀取環境變數“ethaddr”、“eth1addr”…設定的網路地址 eth_getenv_enetaddr_by_index(eth_number, env_enetaddr); //複製環境變數的網路地址到dev->enetadddr中。如果dev->write_hwaddr有效,寫入到網絡卡的實際裝置中。 if (memcmp(env_enetaddr, "/0/0/0/0/0/0", 6)) { if (memcmp(dev->enetaddr, "/0/0/0/0/0/0", 6) && memcmp(dev->enetaddr, env_enetaddr, 6)) { printf ("/nWarning: %s MAC addresses don't match:/n", dev->name); printf ("Address in SROM is%pM/n", dev->enetaddr); printf ("Address in environment is%pM/n", env_enetaddr); } memcpy(dev->enetaddr, env_enetaddr, 6); } if (dev->write_hwaddr && !eth_mac_skip(eth_number) && is_valid_ether_addr(dev->enetaddr)) { dev->write_hwaddr(dev); } eth_number++; dev = dev->next; } while(dev != eth_devices); #ifdef CONFIG_NET_MULTI /* update current ethernet name */ if (eth_current) { char *act = getenv("ethact"); if (act == NULL || strcmp(act, eth_current->name) != 0) setenv("ethact", eth_current->name); } else setenv("ethact", NULL); #endif putc ('/n'); } return eth_number; } |
eth_init函式
使用eth_init必須定義巨集CONFIG_RESET_PHY_R。在board.c:start_armboot函式中它呼叫reset_phy,再呼叫eth_init。
eth_init主要是要呼叫eth_current->init.
int eth_init(bd_t *bis) { int eth_number; struct eth_device *old_current, *dev; if (!eth_current) { puts ("No ethernet found./n"); return -1; } /* Sync environment with network devices */ eth_number = 0; dev = eth_devices; do { uchar env_enetaddr[6]; if (eth_getenv_enetaddr_by_index(eth_number, env_enetaddr)) memcpy(dev->enetaddr, env_enetaddr, 6); ++eth_number; dev = dev->next; } while (dev != eth_devices); old_current = eth_current; do { debug("Trying %s/n", eth_current->name); if (eth_current->init(eth_current,bis) >= 0) { eth_current->state = ETH_STATE_ACTIVE; return 0; } debug("FAIL/n"); eth_try_another(0); } while (old_current != eth_current); return -1; } |
NET有關的環境變數
(1)“ethaddr”表示網路地址,“eth1addr”、“eth2addr”表示第2個和第3個的網路地址;
(2)"ethact"表示eth_current網路地址的名稱,eth_current改變後重新寫入此環境變數;
(3)"ethprime"表示上電後初始eth_current的名稱;
Env_common.c中有一個default_environment陣列,可以在板子配置檔案中定義相應的巨集來定義相應的環境變數。