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 $
* 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
* Benjamin Herrenscmidt (benh@kernel.crashing.org)
......@@ -67,8 +67,8 @@
NETIF_MSG_LINK)
#define DRV_NAME "sungem"
#define DRV_VERSION "0.96"
#define DRV_RELDATE "11/17/01"
#define DRV_VERSION "0.97"
#define DRV_RELDATE "3/20/02"
#define DRV_AUTHOR "David S. Miller (davem@redhat.com)"
static char version[] __devinitdata =
......@@ -2570,13 +2570,63 @@ static int gem_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
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)
{
#if defined(__sparc__) || defined(CONFIG_ALL_PPC)
struct net_device *dev = gp->dev;
#endif
#ifdef __sparc__
#if defined(__sparc__)
struct pci_dev *pdev = gp->pdev;
struct pcidev_cookie *pcp = pdev->sysdata;
int node = -1;
......@@ -2591,8 +2641,7 @@ static int __devinit gem_get_device_address(struct gem *gp)
}
if (node == -1)
memcpy(dev->dev_addr, idprom->id_ethaddr, 6);
#endif
#ifdef CONFIG_ALL_PPC
#elif defined(CONFIG_ALL_PPC)
unsigned char *addr;
addr = get_property(gp->of_node, "local-mac-address", NULL);
......@@ -2602,6 +2651,8 @@ static int __devinit gem_get_device_address(struct gem *gp)
return -1;
}
memcpy(dev->dev_addr, addr, MAX_ADDR_LEN);
#else
get_gem_mac_nonobp(gp->pdev, gp->dev->dev_addr);
#endif
return 0;
}
......
......@@ -3,7 +3,7 @@
* auto carrier detecting ethernet driver. Also known as the
* "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 :
* 2000/11/11 Willy Tarreau <willy AT meta-x.org>
......@@ -14,7 +14,7 @@
*/
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>
......@@ -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 */
for (i = 0; i < 6; i++)
dev->dev_addr[i] = macaddr[i];
macaddr[5]++;
} else if (qfe_slot != -1 &&
prom_getproplen(sdev->prom_node,
"local-mac-address") == 6) {
......@@ -2853,6 +2854,99 @@ static int __init happy_meal_sbus_init(struct sbus_dev *sdev, int is_qfe)
#endif
#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)
{
struct quattro *qp = NULL;
......@@ -2878,8 +2972,10 @@ static int __init happy_meal_pci_init(struct pci_dev *pdev)
prom_getstring(node, "name", prom_name, sizeof(prom_name));
#else
/* This needs to be corrected... -DaveM */
strcpy(prom_name, "qfe");
if (is_quattro_p(pdev))
strcpy(prom_name, "SUNW,qfe");
else
strcpy(prom_name, "SUNW,hme");
#endif
err = -ENODEV;
......@@ -2959,6 +3055,7 @@ static int __init happy_meal_pci_init(struct pci_dev *pdev)
if (i < 6) { /* a mac address was given */
for (i = 0; i < 6; i++)
dev->dev_addr[i] = macaddr[i];
macaddr[5]++;
} else {
#ifdef __sparc__
if (qfe_slot != -1 &&
......@@ -2969,7 +3066,7 @@ static int __init happy_meal_pci_init(struct pci_dev *pdev)
memcpy(dev->dev_addr, idprom->id_ethaddr, 6);
}
#else
memset(dev->dev_addr, 0, 6);
get_hme_mac_nonsparc(pdev, &dev->dev_addr[0]);
#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