/* Serial EEPROM section. */ /* The main routine to parse the very complicated SROM structure. Searchwww.digital.comfor"21X4SROM"togetdetails. Thiscodeisverycomplex,andwillrequirechangestosupport additionalcards,soI'llbeverboseaboutwhatisgoingon.
*/
/* The last media info list parsed, for multiport boards. */ staticstruct mediatable *last_mediatable; staticunsignedchar *last_ee_data; staticint controller_index; struct tulip_private *tp = netdev_priv(dev); unsignedchar *ee_data = tp->eeprom; int i;
tp->mtable = NULL; /* Detect an old-style (SA only) EEPROM layout:
memcmp(eedata, eedata+16, 8). */ for (i = 0; i < 8; i ++) if (ee_data[i] != ee_data[16+i]) break; if (i >= 8) { if (ee_data[0] == 0xff) { if (last_mediatable) {
controller_index++;
pr_info("%s: Controller %d of multiport board\n",
dev->name, controller_index);
tp->mtable = last_mediatable;
ee_data = last_ee_data; goto subsequent_board;
} else
pr_info("%s: Missing EEPROM, this interface may not work correctly!\n",
dev->name); return;
} /* Do a fix-up based on the vendor half of the station address prefix. */ for (i = 0; eeprom_fixups[i].name; i++) { if (dev->dev_addr[0] == eeprom_fixups[i].addr0 &&
dev->dev_addr[1] == eeprom_fixups[i].addr1 &&
dev->dev_addr[2] == eeprom_fixups[i].addr2) { if (dev->dev_addr[2] == 0xE8 && ee_data[0x1a] == 0x55)
i++; /* An Accton EN1207, not an outlaw Maxtech. */
memcpy(ee_data + 26, eeprom_fixups[i].newtable, sizeof(eeprom_fixups[i].newtable));
pr_info("%s: Old format EEPROM on '%s' board. Using substitute media control info\n",
dev->name, eeprom_fixups[i].name); break;
}
} if (eeprom_fixups[i].name == NULL) { /* No fixup found. */
pr_info("%s: Old style EEPROM with no media selection information\n",
dev->name); return;
}
}
if (ee_data[27] == 0) { /* No valid media table. */
tulip_build_fake_mediatable(tp);
} else { unsignedchar *p = (void *)ee_data + ee_data[27]; unsignedchar csr12dir = 0; int count, new_advertise = 0; struct mediatable *mtable;
u16 media = get_u16(p);
p += 2; if (tp->flags & CSR12_IN_SROM)
csr12dir = *p++;
count = *p++;
/* there is no phy information, don't even try to build mtable */ if (count == 0) { if (tulip_debug > 0)
pr_warn("%s: no phy info, aborting mtable build\n",
dev->name); return;
}
pr_info("%s: EEPROM default media type %s\n",
dev->name,
media & 0x0800 ? "Autosense"
: medianame[media & MEDIA_MASK]); for (i = 0; i < count; i++) { struct medialeaf *leaf = &mtable->mleaf[i];
if ((p[0] & 0x80) == 0) { /* 21140 Compact block. */
leaf->type = 0;
leaf->media = p[0] & 0x3f;
leaf->leafdata = p; if ((p[2] & 0x61) == 0x01) /* Bogus, but Znyx boards do it. */
mtable->has_mii = 1;
p += 4;
} else {
leaf->type = p[1]; if (p[1] == 0x05) {
mtable->has_reset = i;
leaf->media = p[2] & 0x0f;
} elseif (tp->chip_id == DM910X && p[1] == 0x80) { /* Hack to ignore Davicom delay period block */
mtable->leafcount--;
count--;
i--;
leaf->leafdata = p + 2;
p += (p[0] & 0x3f) + 1; continue;
} elseif (p[1] & 1) { int gpr_len, reset_len;
mtable->has_mii = 1;
leaf->media = 11;
gpr_len=p[3]*2;
reset_len=p[4+gpr_len]*2;
new_advertise |= get_u16(&p[7+gpr_len+reset_len]);
} else {
mtable->has_nonmii = 1;
leaf->media = p[2] & MEDIA_MASK; /* Davicom's media number for 100BaseTX is strange */ if (tp->chip_id == DM910X && leaf->media == 1)
leaf->media = 3; switch (leaf->media) { case0: new_advertise |= 0x0020; break; case4: new_advertise |= 0x0040; break; case3: new_advertise |= 0x0080; break; case5: new_advertise |= 0x0100; break; case6: new_advertise |= 0x0200; break;
} if (p[1] == 2 && leaf->media == 0) { if (p[2] & 0x40) {
u32 base15 = get_unaligned((u16*)&p[7]);
mtable->csr15dir =
(get_unaligned((u16*)&p[9])<<16) + base15;
mtable->csr15val =
(get_unaligned((u16*)&p[11])<<16) + base15;
} else {
mtable->csr15dir = get_unaligned((u16*)&p[3])<<16;
mtable->csr15val = get_unaligned((u16*)&p[5])<<16;
}
}
}
leaf->leafdata = p + 2;
p += (p[0] & 0x3f) + 1;
} if (tulip_debug > 1 && leaf->media == 11) { unsignedchar *bp = leaf->leafdata;
pr_info("%s: MII interface PHY %d, setup/reset sequences %d/%d long, capabilities %02x %02x\n",
dev->name,
bp[0], bp[1], bp[2 + bp[1]*2],
bp[5 + bp[2 + bp[1]*2]*2],
bp[4 + bp[2 + bp[1]*2]*2]);
}
pr_info("%s: Index #%d - Media %s (#%d) described by a %s (%d) block\n",
dev->name,
i, medianame[leaf->media & 15], leaf->media,
leaf->type < ARRAY_SIZE(block_name) ? block_name[leaf->type] : "<unknown>",
leaf->type);
} if (new_advertise)
tp->sym_advertise = new_advertise;
}
} /* Reading a serial EEPROM is a "bit" grungy, but we work our way through:->.*/
/* EEPROM_Ctrl bits. */ #define EE_SHIFT_CLK 0x02 /* EEPROM shift clock. */ #define EE_CS 0x01 /* EEPROM chip select. */ #define EE_DATA_WRITE 0x04 /* Data from the Tulip to EEPROM. */ #define EE_WRITE_0 0x01 #define EE_WRITE_1 0x05 #define EE_DATA_READ 0x08 /* Data from the EEPROM chip. */ #define EE_ENB (0x4800 | EE_CS)
/* Delay between EEPROM clock transitions. Evenat33MhzcurrentPCIimplementationsdon'toverruntheEEPROMclock.
We add a bus turn-around to insure that this remains true. */ #define eeprom_delay() ioread32(ee_addr)
/* The EEPROM commands include the alway-set leading bit. */ #define EE_READ_CMD (6)
/* Note: this routine returns extra data bits for size detection. */ int tulip_read_eeprom(struct net_device *dev, int location, int addr_len)
{ int i; unsigned retval = 0; struct tulip_private *tp = netdev_priv(dev); void __iomem *ee_addr = tp->base_addr + CSR9; int read_cmd = location | (EE_READ_CMD << addr_len);
/* If location is past the end of what we can address, don't *readsomeotherlocation(ietruncate).Justreturnzero.
*/ if (location > (1 << addr_len) - 1) return0;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.