Commit 77675260 authored by Matthew Wilcox's avatar Matthew Wilcox Committed by Jeff Garzik

[PATCH] Better tulip handling on PA-RISC

This patch improves some of the handling of PA-RISC tulip cards.

 - Introduce HAS_SWAPPED_SEEPROM and NEEDS_FAKE_MEDIA_TABLE
 - Only trigger this code on GSC machines.  The pure PCI machines don't
   have these cards.
 - Allow the chip_name to be overridden in tulip_init_one().
 - Fix some indentation.
 - Handle the output from tulip_read_eeprom() better.
parent c2b08fea
......@@ -90,12 +90,8 @@ static const char *block_name[] __devinitdata = {
*/
static void __devinit tulip_build_fake_mediatable(struct tulip_private *tp)
{
#ifdef __hppa__
unsigned char *ee_data = tp->eeprom;
if (ee_data[0] == 0x3c && ee_data[1] == 0x10 &&
(ee_data[2] == 0x63 || ee_data[2] == 0x61) && ee_data[3] == 0x10) {
#ifdef CONFIG_GSC
if (tp->flags & NEEDS_FAKE_MEDIA_TABLE) {
static unsigned char leafdata[] =
{ 0x01, /* phy number */
0x02, /* gpr setup sequence length */
......@@ -322,11 +318,12 @@ void __devinit tulip_parse_eeprom(struct net_device *dev)
#define EE_READ_CMD (6)
/* Note: this routine returns extra data bits for size detection. */
int __devinit tulip_read_eeprom(long ioaddr, int location, int addr_len)
int __devinit tulip_read_eeprom(struct net_device *dev, int location, int addr_len)
{
int i;
unsigned retval = 0;
long ee_addr = ioaddr + CSR9;
struct tulip_private *tp = dev->priv;
long ee_addr = tp->base_addr + CSR9;
int read_cmd = location | (EE_READ_CMD << addr_len);
outl(EE_ENB & ~EE_CS, ee_addr);
......@@ -354,6 +351,6 @@ int __devinit tulip_read_eeprom(long ioaddr, int location, int addr_len)
/* Terminate the EEPROM access. */
outl(EE_ENB & ~EE_CS, ee_addr);
return retval;
return (tp->flags & HAS_SWAPPED_SEEPROM) ? swab16(retval) : retval;
}
......@@ -64,6 +64,8 @@ enum tbl_flag {
COMET_MAC_ADDR = 0x0800,
HAS_PCI_MWI = 0x1000,
HAS_PHY_IRQ = 0x2000,
HAS_SWAPPED_SEEPROM = 0x4000,
NEEDS_FAKE_MEDIA_TABLE = 0x8000,
};
......@@ -407,7 +409,7 @@ void pnic2_lnk_change(struct net_device *dev, int csr5);
/* eeprom.c */
void tulip_parse_eeprom(struct net_device *dev);
int tulip_read_eeprom(long ioaddr, int location, int addr_len);
int tulip_read_eeprom(struct net_device *dev, int location, int addr_len);
/* interrupt.c */
extern unsigned int tulip_max_interrupt_work;
......
......@@ -1246,6 +1246,7 @@ static int __devinit tulip_init_one (struct pci_dev *pdev,
long ioaddr;
static int board_idx = -1;
int chip_idx = ent->driver_data;
const char *chip_name = tulip_tbl[chip_idx].chip_name;
unsigned int eeprom_missing = 0;
unsigned int force_csr0 = 0;
......@@ -1414,6 +1415,23 @@ static int __devinit tulip_init_one (struct pci_dev *pdev,
pci_set_master(pdev);
#ifdef CONFIG_GSC
if (pdev->subsystem_vendor == PCI_VENDOR_ID_HP) {
switch (pdev->subsystem_device) {
default:
break;
case 0x1061:
case 0x1062:
case 0x1063:
case 0x1098:
case 0x1099:
case 0x10EE:
tp->flags |= HAS_SWAPPED_SEEPROM | NEEDS_FAKE_MEDIA_TABLE;
chip_name = "GSC DS21140 Tulip";
}
}
#endif
/* Clear the missed-packet counter. */
inl(ioaddr + CSR8);
......@@ -1442,11 +1460,13 @@ static int __devinit tulip_init_one (struct pci_dev *pdev,
} else {
/* A serial EEPROM interface, we read now and sort it out later. */
int sa_offset = 0;
int ee_addr_size = tulip_read_eeprom(ioaddr, 0xff, 8) & 0x40000 ? 8 : 6;
int ee_addr_size = tulip_read_eeprom(dev, 0xff, 8) & 0x40000 ? 8 : 6;
for (i = 0; i < sizeof(tp->eeprom)/2; i++)
((u16 *)ee_data)[i] =
le16_to_cpu(tulip_read_eeprom(ioaddr, i, ee_addr_size));
for (i = 0; i < sizeof(tp->eeprom); i+=2) {
u16 data = tulip_read_eeprom(dev, i/2, ee_addr_size);
ee_data[i] = data & 0xff;
ee_data[i + 1] = data >> 8;
}
/* DEC now has a specification (see Notes) but early board makers
just put the address in the first EEPROM locations. */
......@@ -1489,25 +1509,26 @@ static int __devinit tulip_init_one (struct pci_dev *pdev,
tp->flags &= ~HAS_MEDIA_TABLE;
}
#endif
#ifdef __hppa__
/* 3x5 HSC (J3514A) has a broken srom */
if(ee_data[0] == 0x61 && ee_data[1] == 0x10) {
#ifdef CONFIG_GSC
/* Check to see if we have a broken srom */
if (ee_data[0] == 0x61 && ee_data[1] == 0x10) {
/* pci_vendor_id and subsystem_id are swapped */
ee_data[0] = ee_data[2];
ee_data[1] = ee_data[3];
ee_data[2] = 0x61;
ee_data[3] = 0x10;
/* srom need to be byte-swaped and shifted up 1 word.
* This shift needs to happen at the end of the MAC
* first because of the 2 byte overlap.
/* HSC-PCI boards need to be byte-swaped and shifted
* up 1 word. This shift needs to happen at the end
* of the MAC first because of the 2 byte overlap.
*/
for(i = 4; i >= 0; i -= 2) {
for (i = 4; i >= 0; i -= 2) {
ee_data[17 + i + 3] = ee_data[17 + i];
ee_data[16 + i + 5] = ee_data[16 + i];
}
}
#endif
for (i = 0; i < 6; i ++) {
dev->dev_addr[i] = ee_data[i + sa_offset];
sum += ee_data[i + sa_offset];
......@@ -1628,7 +1649,7 @@ static int __devinit tulip_init_one (struct pci_dev *pdev,
goto err_out_free_ring;
printk(KERN_INFO "%s: %s rev %d at %#3lx,",
dev->name, tulip_tbl[chip_idx].chip_name, chip_rev, ioaddr);
dev->name, chip_name, chip_rev, ioaddr);
pci_set_drvdata(pdev, dev);
if (eeprom_missing)
......
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