Commit c92b7ab8 authored by David S. Miller's avatar David S. Miller

In Sun GEM/HME drivers, if OpenBoot firmware is not

available (e.g. i386) fetch the ethernet MAC address
from the vital-product data contained in the PCI
ROM of the card.
parent b38781e5
/* $Id: sungem.c,v 1.49 2002/01/23 15:40:45 davem Exp $ /* $Id: sungem.c,v 1.49 2002/01/23 15:40:45 davem Exp $
* sungem.c: Sun GEM ethernet driver. * sungem.c: Sun GEM ethernet driver.
* *
* Copyright (C) 2000, 2001 David S. Miller (davem@redhat.com) * Copyright (C) 2000, 2001, 2002 David S. Miller (davem@redhat.com)
* *
* Support for Apple GMAC and assorted PHYs by * Support for Apple GMAC and assorted PHYs by
* Benjamin Herrenscmidt (benh@kernel.crashing.org) * Benjamin Herrenscmidt (benh@kernel.crashing.org)
...@@ -67,8 +67,8 @@ ...@@ -67,8 +67,8 @@
NETIF_MSG_LINK) NETIF_MSG_LINK)
#define DRV_NAME "sungem" #define DRV_NAME "sungem"
#define DRV_VERSION "0.96" #define DRV_VERSION "0.97"
#define DRV_RELDATE "11/17/01" #define DRV_RELDATE "3/20/02"
#define DRV_AUTHOR "David S. Miller (davem@redhat.com)" #define DRV_AUTHOR "David S. Miller (davem@redhat.com)"
static char version[] __devinitdata = static char version[] __devinitdata =
...@@ -2570,13 +2570,63 @@ static int gem_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) ...@@ -2570,13 +2570,63 @@ static int gem_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
return rc; return rc;
} }
#if (!defined(__sparc__) && !defined(CONFIG_ALL_PPC))
/* Fetch MAC address from vital product data of PCI ROM. */
static void find_eth_addr_in_vpd(void *rom_base, int len, unsigned char *dev_addr)
{
int this_offset;
for (this_offset = 0x20; this_offset < len; this_offset++) {
void *p = rom_base + this_offset;
int i;
if (readb(p + 0) != 0x90 ||
readb(p + 1) != 0x00 ||
readb(p + 2) != 0x09 ||
readb(p + 3) != 0x4e ||
readb(p + 4) != 0x41 ||
readb(p + 5) != 0x06)
continue;
this_offset += 6;
p += 6;
for (i = 0; i < 6; i++)
dev_addr[i] = readb(p + i);
break;
}
}
static void get_gem_mac_nonobp(struct pci_dev *pdev, unsigned char *dev_addr)
{
u32 rom_reg_orig;
void *p;
if (pdev->resource[PCI_ROM_RESOURCE].parent == NULL)
pci_assign_resource(pdev, PCI_ROM_RESOURCE);
pci_read_config_dword(pdev, pdev->rom_base_reg, &rom_reg_orig);
pci_write_config_dword(pdev, pdev->rom_base_reg,
rom_reg_orig | PCI_ROM_ADDRESS_ENABLE);
p = ioremap(pci_resource_start(pdev, PCI_ROM_RESOURCE), (64 * 1024));
if (p != NULL && readb(p) == 0x55 && readb(p + 1) == 0xaa)
find_eth_addr_in_vpd(p, (64 * 1024), dev_addr);
if (p != NULL)
iounmap(p);
pci_write_config_dword(pdev, pdev->rom_base_reg, rom_reg_orig);
}
#endif /* not Sparc and not PPC */
static int __devinit gem_get_device_address(struct gem *gp) static int __devinit gem_get_device_address(struct gem *gp)
{ {
#if defined(__sparc__) || defined(CONFIG_ALL_PPC) #if defined(__sparc__) || defined(CONFIG_ALL_PPC)
struct net_device *dev = gp->dev; struct net_device *dev = gp->dev;
#endif #endif
#ifdef __sparc__ #if defined(__sparc__)
struct pci_dev *pdev = gp->pdev; struct pci_dev *pdev = gp->pdev;
struct pcidev_cookie *pcp = pdev->sysdata; struct pcidev_cookie *pcp = pdev->sysdata;
int node = -1; int node = -1;
...@@ -2591,8 +2641,7 @@ static int __devinit gem_get_device_address(struct gem *gp) ...@@ -2591,8 +2641,7 @@ static int __devinit gem_get_device_address(struct gem *gp)
} }
if (node == -1) if (node == -1)
memcpy(dev->dev_addr, idprom->id_ethaddr, 6); memcpy(dev->dev_addr, idprom->id_ethaddr, 6);
#endif #elif defined(CONFIG_ALL_PPC)
#ifdef CONFIG_ALL_PPC
unsigned char *addr; unsigned char *addr;
addr = get_property(gp->of_node, "local-mac-address", NULL); addr = get_property(gp->of_node, "local-mac-address", NULL);
...@@ -2602,6 +2651,8 @@ static int __devinit gem_get_device_address(struct gem *gp) ...@@ -2602,6 +2651,8 @@ static int __devinit gem_get_device_address(struct gem *gp)
return -1; return -1;
} }
memcpy(dev->dev_addr, addr, MAX_ADDR_LEN); memcpy(dev->dev_addr, addr, MAX_ADDR_LEN);
#else
get_gem_mac_nonobp(gp->pdev, gp->dev->dev_addr);
#endif #endif
return 0; return 0;
} }
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
* auto carrier detecting ethernet driver. Also known as the * auto carrier detecting ethernet driver. Also known as the
* "Happy Meal Ethernet" found on SunSwift SBUS cards. * "Happy Meal Ethernet" found on SunSwift SBUS cards.
* *
* Copyright (C) 1996, 1998, 1999 David S. Miller (davem@redhat.com) * Copyright (C) 1996, 1998, 1999, 2002 David S. Miller (davem@redhat.com)
* *
* Changes : * Changes :
* 2000/11/11 Willy Tarreau <willy AT meta-x.org> * 2000/11/11 Willy Tarreau <willy AT meta-x.org>
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
*/ */
static char version[] = static char version[] =
"sunhme.c:v1.99 12/Sep/99 David S. Miller (davem@redhat.com)\n"; "sunhme.c:v2.00 20/Mar/2002 David S. Miller (davem@redhat.com)\n";
#include <linux/module.h> #include <linux/module.h>
...@@ -2682,6 +2682,7 @@ static int __init happy_meal_sbus_init(struct sbus_dev *sdev, int is_qfe) ...@@ -2682,6 +2682,7 @@ static int __init happy_meal_sbus_init(struct sbus_dev *sdev, int is_qfe)
if (i < 6) { /* a mac address was given */ if (i < 6) { /* a mac address was given */
for (i = 0; i < 6; i++) for (i = 0; i < 6; i++)
dev->dev_addr[i] = macaddr[i]; dev->dev_addr[i] = macaddr[i];
macaddr[5]++;
} else if (qfe_slot != -1 && } else if (qfe_slot != -1 &&
prom_getproplen(sdev->prom_node, prom_getproplen(sdev->prom_node,
"local-mac-address") == 6) { "local-mac-address") == 6) {
...@@ -2853,6 +2854,99 @@ static int __init happy_meal_sbus_init(struct sbus_dev *sdev, int is_qfe) ...@@ -2853,6 +2854,99 @@ static int __init happy_meal_sbus_init(struct sbus_dev *sdev, int is_qfe)
#endif #endif
#ifdef CONFIG_PCI #ifdef CONFIG_PCI
#ifndef __sparc__
static int is_quattro_p(struct pci_dev *pdev)
{
struct pci_dev *busdev = pdev->bus->self;
struct list_head *tmp;
int n_hmes;
if (busdev->vendor != PCI_VENDOR_ID_DEC ||
busdev->device != PCI_DEVICE_ID_DEC_21153)
return 0;
n_hmes = 0;
tmp = pdev->bus->devices.next;
while (tmp != &pdev->bus->devices) {
struct pci_dev *this_pdev = pci_dev_b(tmp);
if (this_pdev->vendor == PCI_VENDOR_ID_SUN &&
this_pdev->device == PCI_DEVICE_ID_SUN_HAPPYMEAL)
n_hmes++;
tmp = tmp->next;
}
if (n_hmes != 4)
return 0;
return 1;
}
/* Fetch MAC address from vital product data of PCI ROM. */
static void find_eth_addr_in_vpd(void *rom_base, int len, int index, unsigned char *dev_addr)
{
int this_offset;
int orig_index = index;
for (this_offset = 0x20; this_offset < len; this_offset++) {
void *p = rom_base + this_offset;
if (readb(p + 0) != 0x90 ||
readb(p + 1) != 0x00 ||
readb(p + 2) != 0x09 ||
readb(p + 3) != 0x4e ||
readb(p + 4) != 0x41 ||
readb(p + 5) != 0x06)
continue;
this_offset += 6;
p += 6;
if (index == 0) {
int i;
printk("MAC(%d): [%02x %02x %02x %02x %02x %02x]\n",
orig_index,
readb(p + 0), readb(p + 1), readb(p + 2),
readb(p + 3), readb(p + 4), readb(p + 5));
for (i = 0; i < 6; i++)
dev_addr[i] = readb(p + i);
break;
}
index--;
}
}
static void get_hme_mac_nonsparc(struct pci_dev *pdev, unsigned char *dev_addr)
{
u32 rom_reg_orig;
void *p;
int index;
index = 0;
if (is_quattro_p(pdev))
index = PCI_SLOT(pdev->devfn);
if (pdev->resource[PCI_ROM_RESOURCE].parent == NULL)
pci_assign_resource(pdev, PCI_ROM_RESOURCE);
pci_read_config_dword(pdev, pdev->rom_base_reg, &rom_reg_orig);
pci_write_config_dword(pdev, pdev->rom_base_reg,
rom_reg_orig | PCI_ROM_ADDRESS_ENABLE);
p = ioremap(pci_resource_start(pdev, PCI_ROM_RESOURCE), (64 * 1024));
if (p != NULL && readb(p) == 0x55 && readb(p + 1) == 0xaa)
find_eth_addr_in_vpd(p, (64 * 1024), index, dev_addr);
if (p != NULL)
iounmap(p);
pci_write_config_dword(pdev, pdev->rom_base_reg, rom_reg_orig);
}
#endif /* !(__sparc__) */
static int __init happy_meal_pci_init(struct pci_dev *pdev) static int __init happy_meal_pci_init(struct pci_dev *pdev)
{ {
struct quattro *qp = NULL; struct quattro *qp = NULL;
...@@ -2878,8 +2972,10 @@ static int __init happy_meal_pci_init(struct pci_dev *pdev) ...@@ -2878,8 +2972,10 @@ static int __init happy_meal_pci_init(struct pci_dev *pdev)
prom_getstring(node, "name", prom_name, sizeof(prom_name)); prom_getstring(node, "name", prom_name, sizeof(prom_name));
#else #else
/* This needs to be corrected... -DaveM */ if (is_quattro_p(pdev))
strcpy(prom_name, "qfe"); strcpy(prom_name, "SUNW,qfe");
else
strcpy(prom_name, "SUNW,hme");
#endif #endif
err = -ENODEV; err = -ENODEV;
...@@ -2959,6 +3055,7 @@ static int __init happy_meal_pci_init(struct pci_dev *pdev) ...@@ -2959,6 +3055,7 @@ static int __init happy_meal_pci_init(struct pci_dev *pdev)
if (i < 6) { /* a mac address was given */ if (i < 6) { /* a mac address was given */
for (i = 0; i < 6; i++) for (i = 0; i < 6; i++)
dev->dev_addr[i] = macaddr[i]; dev->dev_addr[i] = macaddr[i];
macaddr[5]++;
} else { } else {
#ifdef __sparc__ #ifdef __sparc__
if (qfe_slot != -1 && if (qfe_slot != -1 &&
...@@ -2969,7 +3066,7 @@ static int __init happy_meal_pci_init(struct pci_dev *pdev) ...@@ -2969,7 +3066,7 @@ static int __init happy_meal_pci_init(struct pci_dev *pdev)
memcpy(dev->dev_addr, idprom->id_ethaddr, 6); memcpy(dev->dev_addr, idprom->id_ethaddr, 6);
} }
#else #else
memset(dev->dev_addr, 0, 6); get_hme_mac_nonsparc(pdev, &dev->dev_addr[0]);
#endif #endif
} }
......
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