Commit abe0c94c authored by Jeff Garzik's avatar Jeff Garzik

merge most of hppa support for tulip net driver

parent 13f4b95d
2002-09-18 Ryan Bradetich <rbradetich@uswest.net>
tulip hppa support:
* eeprom.c (tulip_build_fake_mediatable): new function
(tulip_parse_eeprom): call it, when no media table
* interrupt.c (phy_interrupt): new function
(tulip_interrupt): call it, before checking for no-irq-work
* tulip.c: add HAS_PHY_IRQ chip feature flag.
add csr12_shadow to tulip_private struct, only for hppa currently.
* tulip_core (tulip_init_one): support hppa wonky eeproms
2002-05-11 Juan Quintela <quintela@mandrakesoft.com> 2002-05-11 Juan Quintela <quintela@mandrakesoft.com>
* 21142.c (t21142_lnk_change): Revert earlier patch * 21142.c (t21142_lnk_change): Revert earlier patch
......
...@@ -75,6 +75,61 @@ static const char *block_name[] __devinitdata = { ...@@ -75,6 +75,61 @@ static const char *block_name[] __devinitdata = {
}; };
/**
* tulip_build_fake_mediatable - Build a fake mediatable entry.
* @tp: Ptr to the tulip private data.
*
* Some cards like the 3x5 HSC cards (J3514A) do not have a standard
* srom and can not be handled under the fixup routine. These cards
* still need a valid mediatable entry for correct csr12 setup and
* mii handling.
*
* Since this is currently a parisc-linux specific function, the
* #ifdef __hppa__ should completely optimize this function away for
* non-parisc hardware.
*/
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) {
static unsigned char leafdata[] =
{ 0x01, /* phy number */
0x02, /* gpr setup sequence length */
0x02, 0x00, /* gpr setup sequence */
0x02, /* phy reset sequence length */
0x01, 0x00, /* phy reset sequence */
0x00, 0x78, /* media capabilities */
0x00, 0xe0, /* nway advertisment */
0x00, 0x05, /* fdx bit map */
0x00, 0x06 /* ttm bit map */
};
tp->mtable = (struct mediatable *)
kmalloc(sizeof(struct mediatable) + sizeof(struct medialeaf), GFP_KERNEL);
if (tp->mtable == NULL)
return; /* Horrible, impossible failure. */
tp->mtable->defaultmedia = 0x800;
tp->mtable->leafcount = 1;
tp->mtable->csr12dir = 0x3f; /* inputs on bit7 for hsc-pci, bit6 for pci-fx */
tp->mtable->has_nonmii = 0;
tp->mtable->has_reset = 0;
tp->mtable->has_mii = 1;
tp->mtable->csr15dir = tp->mtable->csr15val = 0;
tp->mtable->mleaf[0].type = 1;
tp->mtable->mleaf[0].media = 11;
tp->mtable->mleaf[0].leafdata = &leafdata[0];
tp->flags |= HAS_PHY_IRQ;
tp->csr12_shadow = -1;
}
#endif
}
void __devinit tulip_parse_eeprom(struct net_device *dev) void __devinit tulip_parse_eeprom(struct net_device *dev)
{ {
/* The last media info list parsed, for multiport boards. */ /* The last media info list parsed, for multiport boards. */
...@@ -136,6 +191,7 @@ void __devinit tulip_parse_eeprom(struct net_device *dev) ...@@ -136,6 +191,7 @@ void __devinit tulip_parse_eeprom(struct net_device *dev)
subsequent_board: subsequent_board:
if (ee_data[27] == 0) { /* No valid media table. */ if (ee_data[27] == 0) { /* No valid media table. */
tulip_build_fake_mediatable(tp);
} else { } else {
unsigned char *p = (void *)ee_data + ee_data[27]; unsigned char *p = (void *)ee_data + ee_data[27];
unsigned char csr12dir = 0; unsigned char csr12dir = 0;
......
...@@ -291,6 +291,25 @@ static int tulip_rx(struct net_device *dev) ...@@ -291,6 +291,25 @@ static int tulip_rx(struct net_device *dev)
#endif #endif
} }
static inline void phy_interrupt (struct net_device *dev)
{
#ifdef __hppa__
int csr12 = inl(dev->base_addr + CSR12) & 0xff;
struct tulip_private *tp = (struct tulip_private *)dev->priv;
if (csr12 != tp->csr12_shadow) {
/* ack interrupt */
outl(csr12 | 0x02, dev->base_addr + CSR12);
tp->csr12_shadow = csr12;
/* do link change stuff */
spin_lock(&tp->lock);
tulip_check_duplex(dev);
spin_unlock(&tp->lock);
/* clear irq ack bit */
outl(csr12 & ~0x02, dev->base_addr + CSR12);
}
#endif
}
/* The interrupt handler does all of the Rx thread work and cleans up /* The interrupt handler does all of the Rx thread work and cleans up
after the Tx thread. */ after the Tx thread. */
...@@ -313,6 +332,9 @@ void tulip_interrupt(int irq, void *dev_instance, struct pt_regs *regs) ...@@ -313,6 +332,9 @@ void tulip_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
/* Let's see whether the interrupt really is for us */ /* Let's see whether the interrupt really is for us */
csr5 = inl(ioaddr + CSR5); csr5 = inl(ioaddr + CSR5);
if (tp->flags & HAS_PHY_IRQ)
phy_interrupt (dev);
if ((csr5 & (NormalIntr|AbnormalIntr)) == 0) if ((csr5 & (NormalIntr|AbnormalIntr)) == 0)
return; return;
......
...@@ -63,6 +63,7 @@ enum tbl_flag { ...@@ -63,6 +63,7 @@ enum tbl_flag {
HAS_8023X = 0x0400, HAS_8023X = 0x0400,
COMET_MAC_ADDR = 0x0800, COMET_MAC_ADDR = 0x0800,
HAS_PCI_MWI = 0x1000, HAS_PCI_MWI = 0x1000,
HAS_PHY_IRQ = 0x2000,
}; };
...@@ -388,7 +389,8 @@ struct tulip_private { ...@@ -388,7 +389,8 @@ struct tulip_private {
int susp_rx; int susp_rx;
unsigned long nir; unsigned long nir;
unsigned long base_addr; unsigned long base_addr;
int pad0, pad1; /* Used for 8-byte alignment */ int csr12_shadow;
int pad0; /* Used for 8-byte alignment */
}; };
......
...@@ -1489,6 +1489,25 @@ static int __devinit tulip_init_one (struct pci_dev *pdev, ...@@ -1489,6 +1489,25 @@ static int __devinit tulip_init_one (struct pci_dev *pdev,
/* No media table either */ /* No media table either */
tp->flags &= ~HAS_MEDIA_TABLE; tp->flags &= ~HAS_MEDIA_TABLE;
} }
#endif
#ifdef __hppa__
/* 3x5 HSC (J3514A) has 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.
*/
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 #endif
for (i = 0; i < 6; i ++) { for (i = 0; i < 6; i ++) {
dev->dev_addr[i] = ee_data[i + sa_offset]; dev->dev_addr[i] = ee_data[i + sa_offset];
......
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