|
@@ -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 */
|
|
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
|
|
static bool
|
|
-dp83902a_init(void)
|
|
|
|
|
|
+dp83902a_init(unsigned char *enetaddr)
|
|
{
|
|
{
|
|
dp83902a_priv_data_t *dp = &nic;
|
|
dp83902a_priv_data_t *dp = &nic;
|
|
u8* base;
|
|
u8* base;
|
|
@@ -129,6 +133,7 @@ dp83902a_init(void)
|
|
dp->esa[4],
|
|
dp->esa[4],
|
|
dp->esa[5] );
|
|
dp->esa[5] );
|
|
|
|
|
|
|
|
+ memcpy(enetaddr, dp->esa, 6); /* Use MAC from serial EEPROM */
|
|
#endif /* NE2000_BASIC_INIT */
|
|
#endif /* NE2000_BASIC_INIT */
|
|
return true;
|
|
return true;
|
|
}
|
|
}
|
|
@@ -161,6 +166,8 @@ dp83902a_start(u8 * enaddr)
|
|
u8 *base = dp->base;
|
|
u8 *base = dp->base;
|
|
int i;
|
|
int i;
|
|
|
|
|
|
|
|
+ debug("The MAC is %pM\n", enaddr);
|
|
|
|
+
|
|
DEBUG_FUNCTION();
|
|
DEBUG_FUNCTION();
|
|
|
|
|
|
DP_OUT(base, DP_CR, DP_CR_PAGE0 | DP_CR_NODMA | DP_CR_STOP); /* Brutal */
|
|
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;
|
|
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) {
|
|
if (!pbuf) {
|
|
pbuf = malloc(2000);
|
|
pbuf = malloc(2000);
|
|
@@ -692,49 +703,56 @@ int eth_init(bd_t *bd) {
|
|
|
|
|
|
nic.base = (u8 *) CONFIG_DRIVER_NE2000_BASE;
|
|
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.data = nic.base + DP_DATA;
|
|
nic.tx_buf1 = START_PG;
|
|
nic.tx_buf1 = START_PG;
|
|
nic.tx_buf2 = START_PG2;
|
|
nic.tx_buf2 = START_PG2;
|
|
nic.rx_buf_start = RX_START;
|
|
nic.rx_buf_start = RX_START;
|
|
nic.rx_buf_end = RX_END;
|
|
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;
|
|
initialized = 1;
|
|
-
|
|
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
-void eth_halt() {
|
|
|
|
-
|
|
|
|
- PRINTK("### eth_halt\n");
|
|
|
|
|
|
+static void ne2k_halt(struct eth_device *dev)
|
|
|
|
+{
|
|
|
|
+ debug("### ne2k_halt\n");
|
|
if(initialized)
|
|
if(initialized)
|
|
dp83902a_stop();
|
|
dp83902a_stop();
|
|
initialized = 0;
|
|
initialized = 0;
|
|
}
|
|
}
|
|
|
|
|
|
-int eth_rx() {
|
|
|
|
|
|
+static int ne2k_recv(struct eth_device *dev)
|
|
|
|
+{
|
|
dp83902a_poll();
|
|
dp83902a_poll();
|
|
return 1;
|
|
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;
|
|
int tmo;
|
|
|
|
|
|
- PRINTK("### eth_send\n");
|
|
|
|
|
|
+ debug("### ne2k_send\n");
|
|
|
|
|
|
pkey = -1;
|
|
pkey = -1;
|
|
|
|
|
|
@@ -754,3 +772,28 @@ int eth_send(volatile void *packet, int length) {
|
|
}
|
|
}
|
|
return 0;
|
|
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);
|
|
|
|
+}
|