diff --git a/board/qemu-mips/qemu-mips.c b/board/qemu-mips/qemu-mips.c index 7a69a00..2b3a1d6 100644 --- a/board/qemu-mips/qemu-mips.c +++ b/board/qemu-mips/qemu-mips.c @@ -25,6 +25,7 @@ #include #include #include +#include phys_size_t initdram(int board_type) { @@ -87,3 +88,8 @@ int misc_init_r(void) set_io_port_base(0); return 0; } + +int board_eth_init(bd_t *bis) +{ + return ne2k_register(); +} diff --git a/board/renesas/r7780mp/r7780mp.c b/board/renesas/r7780mp/r7780mp.c index 0b80099..82cef02 100644 --- a/board/renesas/r7780mp/r7780mp.c +++ b/board/renesas/r7780mp/r7780mp.c @@ -81,5 +81,6 @@ void pci_init_board(void) int board_eth_init(bd_t *bis) { - return pci_eth_init(bis); + /* return >= 0 if a chip is found, the board's AX88796L is n2k-based */ + return ne2k_register() + pci_eth_init(bis); } diff --git a/board/shmin/shmin.c b/board/shmin/shmin.c index 8742f10..7348f52 100644 --- a/board/shmin/shmin.c +++ b/board/shmin/shmin.c @@ -28,6 +28,7 @@ #include #include #include +#include int checkboard(void) { @@ -55,6 +56,11 @@ int dram_init(void) return 0; } +int board_eth_init(bd_t *bis) +{ + return ne2k_register(); +} + void led_set_state(unsigned short value) { diff --git a/drivers/net/ne2000_base.c b/drivers/net/ne2000_base.c index f0cd2b6..88f2b37 100644 --- a/drivers/net/ne2000_base.c +++ b/drivers/net/ne2000_base.c @@ -94,8 +94,12 @@ void uboot_push_tx_done(int key, int val); static dp83902a_priv_data_t nic; /* just one instance of the card supported */ +/** + * This function reads the MAC address from the serial EEPROM, + * used if PROM read fails. Does nothing for ax88796 chips (sh boards) + */ static bool -dp83902a_init(void) +dp83902a_init(unsigned char *enetaddr) { dp83902a_priv_data_t *dp = &nic; u8* base; @@ -129,6 +133,7 @@ dp83902a_init(void) dp->esa[4], dp->esa[5] ); + memcpy(enetaddr, dp->esa, 6); /* Use MAC from serial EEPROM */ #endif /* NE2000_BASIC_INIT */ return true; } @@ -161,6 +166,8 @@ dp83902a_start(u8 * enaddr) u8 *base = dp->base; int i; + debug("The MAC is %pM\n", enaddr); + DEBUG_FUNCTION(); DP_OUT(base, DP_CR, DP_CR_PAGE0 | DP_CR_NODMA | DP_CR_STOP); /* Brutal */ @@ -665,12 +672,16 @@ void uboot_push_tx_done(int key, int val) { pkey = key; } -int eth_init(bd_t *bd) { - int r; - u8 dev_addr[6]; - char ethaddr[20]; - - PRINTK("### eth_init\n"); +/** + * Setup the driver and init MAC address according to doc/README.enetaddr + * Called by ne2k_register() before registering the driver @eth layer + * + * @param struct ethdevice of this instance of the driver for dev->enetaddr + * @return 0 on success, -1 on error (causing caller to print error msg) + */ +static int ne2k_setup_driver(struct eth_device *dev) +{ + PRINTK("### ne2k_setup_driver\n"); if (!pbuf) { pbuf = malloc(2000); @@ -692,49 +703,56 @@ int eth_init(bd_t *bd) { nic.base = (u8 *) CONFIG_DRIVER_NE2000_BASE; - r = get_prom(dev_addr, nic.base); - if (!r) - return -1; - - sprintf (ethaddr, "%02X:%02X:%02X:%02X:%02X:%02X", - dev_addr[0], dev_addr[1], - dev_addr[2], dev_addr[3], - dev_addr[4], dev_addr[5]) ; - PRINTK("Set environment from HW MAC addr = \"%s\"\n", ethaddr); - setenv ("ethaddr", ethaddr); - nic.data = nic.base + DP_DATA; nic.tx_buf1 = START_PG; nic.tx_buf2 = START_PG2; nic.rx_buf_start = RX_START; nic.rx_buf_end = RX_END; - if (dp83902a_init() == false) - return -1; + /* + * According to doc/README.enetaddr, drivers shall give priority + * to the MAC address value in the environment, so we do not read + * it from the prom or eeprom if it is specified in the environment. + */ + if (!eth_getenv_enetaddr("ethaddr", dev->enetaddr)) { + /* If the MAC address is not in the environment, get it: */ + if (!get_prom(dev->enetaddr, nic.base)) /* get MAC from prom */ + dp83902a_init(dev->enetaddr); /* fallback: seeprom */ + /* And write it into the environment otherwise eth_write_hwaddr + * returns -1 due to eth_getenv_enetaddr_by_index() failing, + * and this causes "Warning: failed to set MAC address", and + * cmd_bdinfo has no ethaddr value which it can show: */ + eth_setenv_enetaddr("ethaddr", dev->enetaddr); + } + return 0; +} - dp83902a_start(dev_addr); +static int ne2k_init(struct eth_device *dev, bd_t *bd) +{ + dp83902a_start(dev->enetaddr); initialized = 1; - return 0; } -void eth_halt() { - - PRINTK("### eth_halt\n"); +static void ne2k_halt(struct eth_device *dev) +{ + debug("### ne2k_halt\n"); if(initialized) dp83902a_stop(); initialized = 0; } -int eth_rx() { +static int ne2k_recv(struct eth_device *dev) +{ dp83902a_poll(); return 1; } -int eth_send(volatile void *packet, int length) { +static int ne2k_send(struct eth_device *dev, volatile void *packet, int length) +{ int tmo; - PRINTK("### eth_send\n"); + debug("### ne2k_send\n"); pkey = -1; @@ -754,3 +772,28 @@ int eth_send(volatile void *packet, int length) { } return 0; } + +/** + * Setup the driver for use and register it with the eth layer + * @return 0 on success, -1 on error (causing caller to print error msg) + */ +int ne2k_register(void) +{ + struct eth_device *dev; + + dev = calloc(sizeof(*dev), 1); + if (dev == NULL) + return -1; + + if (ne2k_setup_driver(dev)) + return -1; + + dev->init = ne2k_init; + dev->halt = ne2k_halt; + dev->send = ne2k_send; + dev->recv = ne2k_recv; + + sprintf(dev->name, "NE2000"); + + return eth_register(dev); +} diff --git a/include/netdev.h b/include/netdev.h index 04d9f75..150fa8e 100644 --- a/include/netdev.h +++ b/include/netdev.h @@ -80,6 +80,7 @@ int mpc8220_fec_initialize(bd_t *bis); int mpc82xx_scc_enet_initialize(bd_t *bis); int mvgbe_initialize(bd_t *bis); int natsemi_initialize(bd_t *bis); +int ne2k_register(void); int npe_initialize(bd_t *bis); int ns8382x_initialize(bd_t *bis); int pcnet_initialize(bd_t *bis);