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
...@@ -223,40 +223,51 @@ static int __devinit macsonic_init(struct net_device *dev) ...@@ -223,40 +223,51 @@ static int __devinit macsonic_init(struct net_device *dev)
return 0; 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); struct sonic_local *lp = netdev_priv(dev);
const int prom_addr = ONBOARD_SONIC_PROM_BASE; 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; int i;
/* On NuBus boards we can sometimes look in the ROM resources. for (i = 0; i < 6; i++)
No such luck for comm-slot/onboard. */
for(i = 0; i < 6; i++)
dev->dev_addr[i] = SONIC_READ_PROM(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 * Most of the time, the address is bit-reversed. The NetBSD
why this is so. */ * source has a rather long and detailed historical account of
if (memcmp(dev->dev_addr, "\x08\x00\x07", 3) && * why this is so.
memcmp(dev->dev_addr, "\x00\xA0\x40", 3) && */
memcmp(dev->dev_addr, "\x00\x80\x19", 3) &&
memcmp(dev->dev_addr, "\x00\x05\x02", 3))
bit_reverse_addr(dev->dev_addr); bit_reverse_addr(dev->dev_addr);
else if (!INVALID_MAC(dev->dev_addr))
return 0; return;
/* If we still have what seems to be a bogus address, we'll /*
look in the CAM. The top entry should be ours. */ * If we still have what seems to be a bogus address, we'll
/* Danger! This only works if MacOS has already initialized * look in the CAM. The top entry should be ours.
the card... */ */
if (memcmp(dev->dev_addr, "\x08\x00\x07", 3) && printk(KERN_WARNING "macsonic: MAC address in PROM seems "
memcmp(dev->dev_addr, "\x00\xA0\x40", 3) && "to be invalid, trying CAM\n");
memcmp(dev->dev_addr, "\x00\x80\x19", 3) && } else {
memcmp(dev->dev_addr, "\x00\x05\x02", 3)) printk(KERN_WARNING "macsonic: cannot read MAC address from "
{ "PROM, trying CAM\n");
unsigned short val; }
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_CMD, SONIC_CR_RST);
SONIC_WRITE(SONIC_CEP, 15); SONIC_WRITE(SONIC_CEP, 15);
...@@ -271,21 +282,14 @@ static int __devinit mac_onboard_sonic_ethernet_addr(struct net_device *dev) ...@@ -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[1] = val >> 8;
dev->dev_addr[0] = val & 0xff; dev->dev_addr[0] = val & 0xff;
printk(KERN_INFO "HW Address from CAM 15: %pM\n", if (!INVALID_MAC(dev->dev_addr))
dev->dev_addr); return;
} else return 0;
if (memcmp(dev->dev_addr, "\x08\x00\x07", 3) && /* Still nonsense ... messed up someplace! */
memcmp(dev->dev_addr, "\x00\xA0\x40", 3) &&
memcmp(dev->dev_addr, "\x00\x80\x19", 3) && printk(KERN_WARNING "macsonic: MAC address in CAM entry 15 "
memcmp(dev->dev_addr, "\x00\x05\x02", 3)) "seems invalid, will use a random MAC\n");
{ random_ether_addr(dev->dev_addr);
/*
* Still nonsense ... messed up someplace!
*/
printk(KERN_ERR "macsonic: ERROR (INVALID MAC)\n");
return -EIO;
} else return 0;
} }
static int __devinit mac_onboard_sonic_probe(struct net_device *dev) 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) ...@@ -402,8 +406,7 @@ static int __devinit mac_onboard_sonic_probe(struct net_device *dev)
SONIC_WRITE(SONIC_ISR, 0x7fff); SONIC_WRITE(SONIC_ISR, 0x7fff);
/* Now look for the MAC address. */ /* Now look for the MAC address. */
if (mac_onboard_sonic_ethernet_addr(dev) != 0) mac_onboard_sonic_ethernet_addr(dev);
return -ENODEV;
/* Shared init code */ /* Shared init code */
return macsonic_init(dev); return macsonic_init(dev);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment