Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit dcaa6a94 authored by Finn Thain's avatar Finn Thain Committed by David S. Miller
Browse files

macsonic: fix crash on PowerBook 520



No-one seems to know where the PowerBook 500 series store their ethernet
MAC addresses. So, rather than crash, use a MAC address from the SONIC
CAM. Failing that, generate a random one.

Signed-off-by: default avatarFinn Thain <fthain@telegraphics.com.au>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 87d75b52
Loading
Loading
Loading
Loading
+60 −57
Original line number Diff line number Diff line
@@ -223,40 +223,51 @@ static int __devinit macsonic_init(struct net_device *dev)
	return 0;
}

static int __devinit mac_onboard_sonic_ethernet_addr(struct net_device *dev)
#define INVALID_MAC(mac) (memcmp(mac, "\x08\x00\x07", 3) && \
                          memcmp(mac, "\x00\xA0\x40", 3) && \
                          memcmp(mac, "\x00\x80\x19", 3) && \
                          memcmp(mac, "\x00\x05\x02", 3))

static void __devinit mac_onboard_sonic_ethernet_addr(struct net_device *dev)
{
	struct sonic_local *lp = netdev_priv(dev);
	const int prom_addr = ONBOARD_SONIC_PROM_BASE;
	unsigned short val;

	/*
	 * On NuBus boards we can sometimes look in the ROM resources.
	 * No such luck for comm-slot/onboard.
	 * On the PowerBook 520, the PROM base address is a mystery.
	 */
	if (hwreg_present((void *)prom_addr)) {
		int i;

	/* On NuBus boards we can sometimes look in the ROM resources.
	   No such luck for comm-slot/onboard. */
		for (i = 0; i < 6; i++)
			dev->dev_addr[i] = SONIC_READ_PROM(i);
		if (!INVALID_MAC(dev->dev_addr))
			return;

	/* Most of the time, the address is bit-reversed.  The NetBSD
	   source has a rather long and detailed historical account of
	   why this is so. */
	if (memcmp(dev->dev_addr, "\x08\x00\x07", 3) &&
	    memcmp(dev->dev_addr, "\x00\xA0\x40", 3) &&
	    memcmp(dev->dev_addr, "\x00\x80\x19", 3) &&
	    memcmp(dev->dev_addr, "\x00\x05\x02", 3))
		/*
		 * Most of the time, the address is bit-reversed. The NetBSD
		 * source has a rather long and detailed historical account of
		 * why this is so.
		 */
		bit_reverse_addr(dev->dev_addr);
	else
		return 0;
		if (!INVALID_MAC(dev->dev_addr))
			return;

	/* If we still have what seems to be a bogus address, we'll
           look in the CAM.  The top entry should be ours. */
	/* Danger! This only works if MacOS has already initialized
           the card... */
	if (memcmp(dev->dev_addr, "\x08\x00\x07", 3) &&
	    memcmp(dev->dev_addr, "\x00\xA0\x40", 3) &&
	    memcmp(dev->dev_addr, "\x00\x80\x19", 3) &&
	    memcmp(dev->dev_addr, "\x00\x05\x02", 3))
	{
		unsigned short val;
		/*
		 * If we still have what seems to be a bogus address, we'll
		 * look in the CAM. The top entry should be ours.
		 */
		printk(KERN_WARNING "macsonic: MAC address in PROM seems "
		                    "to be invalid, trying CAM\n");
	} else {
		printk(KERN_WARNING "macsonic: cannot read MAC address from "
		                    "PROM, trying CAM\n");
	}

		printk(KERN_INFO "macsonic: PROM seems to be wrong, trying CAM entry 15\n");
	/* This only works if MacOS has already initialized the card. */

	SONIC_WRITE(SONIC_CMD, SONIC_CR_RST);
	SONIC_WRITE(SONIC_CEP, 15);
@@ -271,21 +282,14 @@ static int __devinit mac_onboard_sonic_ethernet_addr(struct net_device *dev)
	dev->dev_addr[1] = val >> 8;
	dev->dev_addr[0] = val & 0xff;

		printk(KERN_INFO "HW Address from CAM 15: %pM\n",
		       dev->dev_addr);
	} else return 0;
	if (!INVALID_MAC(dev->dev_addr))
		return;

	if (memcmp(dev->dev_addr, "\x08\x00\x07", 3) &&
	    memcmp(dev->dev_addr, "\x00\xA0\x40", 3) &&
	    memcmp(dev->dev_addr, "\x00\x80\x19", 3) &&
	    memcmp(dev->dev_addr, "\x00\x05\x02", 3))
	{
		/*
		 * Still nonsense ... messed up someplace!
		 */
		printk(KERN_ERR "macsonic: ERROR (INVALID MAC)\n");
		return -EIO;
	} else return 0;
	/* Still nonsense ... messed up someplace! */

	printk(KERN_WARNING "macsonic: MAC address in CAM entry 15 "
	                    "seems invalid, will use a random MAC\n");
	random_ether_addr(dev->dev_addr);
}

static int __devinit mac_onboard_sonic_probe(struct net_device *dev)
@@ -402,8 +406,7 @@ static int __devinit mac_onboard_sonic_probe(struct net_device *dev)
	SONIC_WRITE(SONIC_ISR, 0x7fff);

	/* Now look for the MAC address. */
	if (mac_onboard_sonic_ethernet_addr(dev) != 0)
		return -ENODEV;
	mac_onboard_sonic_ethernet_addr(dev);

	/* Shared init code */
	return macsonic_init(dev);