-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Hi! This patch allows to use the fiber interface of the SMC9432FTX NIC or other epic-based cards using the LXT970 transceiver. Please apply the attached patch (md5sum: abcb5c02ea3e14a6ac50badaddc465ba). If you miss the patch (i.e. if you find this message on some list archive stripping of attachments), you can also retrieve it from my web page referenced below. I did many final code cleanups and tried to eliminate all weaknesses you pointed me to. So here are the changes against the last patches I published: * code cleanup * no additions to check_media() running in intterrupt context any more * replaced the long udelay in epic_open() by schedule_timeout() * driver now checks for the right transceiver and tries to enable fiber only on cards having the LXT970 * module option for forcing the use of fiber interface added (options=6) * all LXT970-specific symbols put into a new header file include/linux/lxt970.h - so other drivers for cards using the same transceiver can benefit, no changes to mii.h any more * added some debug output for debug >= 2 Short overview of the functionality: The driver reads the ID of the PHY chip. If it's a LXT970 it tries to do the following steps in epic_open(): * disable auto-negotiation (not supported for fiber by LXT970) * enable fiber interface * wait 1.5 seconds for fiber interface to get ready * read link status * if we have no link, disable fiber and switch back to old code (utp/bnc) I don't want to bore you by repeating what we've already written here, so I put up a web site containing all summed up details and some usage notes. Please see http://www.hillier.de/linux/epic100-fiber.php3 The patch has been tested successfully with the following configurations: SMC 9432 BTX (card with BNC and TP connector) using TP SMC 9432 TX-MP (card with TP connector only) SMC 9432 FTX-SC (card with fiber and TP connector): tested thoroughly since some weeks on 48 workstations and 2 servers running 24/7 TIA! - -- Ciao, Gernot -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.0.6 (GNU/Linux) Comment: For info see http://www.gnupg.org iD8DBQE9Xknck997/GGeSeIRAhEdAJ9nx0xZbLF43Ce1gQSU+ygx7YHqrACeIYKE ZNXq3h2FAPLm9qz874dr3T0= =SxY3 -----END PGP SIGNATURE-----
diff -uNr linux-2.4.19.SuSE/drivers/net/epic100.c linux-2.4.19.SuSE-new/drivers/net/epic100.c --- linux-2.4.19.SuSE/drivers/net/epic100.c Sat Aug 17 02:32:39 2002 +++ linux-2.4.19.SuSE-new/drivers/net/epic100.c Sat Aug 17 13:37:48 2002 @@ -63,11 +63,15 @@ LK1.1.13: * revert version 1.1.12, power-up sequence "fix" + epic100_fx.diff: + * fiber link enabled on the SMC9432FTX-SC, tested during open of the interface; if no link found, utp/bnc is enabled + real work done by Christoph Dolina, I made some improvements and code-cleanup (<gernot@hillier.de>) + for details see http://www.hillier.de/linux/epic100-fiber.php3 */ #define DRV_NAME "epic100" -#define DRV_VERSION "1.11+LK1.1.13" -#define DRV_RELDATE "Mar 20, 2002" +#define DRV_VERSION "1.11+LK1.1.13+fx.diff" +#define DRV_RELDATE "Aug 9, 2002" /* The user-configurable values. @@ -133,6 +137,7 @@ #include <linux/init.h> #include <linux/spinlock.h> #include <linux/ethtool.h> +#include <linux/lxt970.h> #include <linux/mii.h> #include <linux/crc32.h> #include <asm/bitops.h> @@ -158,9 +163,9 @@ MODULE_PARM(full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i"); MODULE_PARM_DESC(debug, "EPIC/100 debug level (0-5)"); MODULE_PARM_DESC(max_interrupt_work, "EPIC/100 maximum events handled per interrupt"); -MODULE_PARM_DESC(options, "EPIC/100: Bits 0-3: media type, bit 4: full duplex"); +MODULE_PARM_DESC(options, "EPIC/100: Bits 0-3: media type (0=auto, 1=10Base2, 6=100BaseFX), bit 4: full duplex"); MODULE_PARM_DESC(rx_copybreak, "EPIC/100 copy breakpoint for copy-only-tiny-frames"); -MODULE_PARM_DESC(full_duplex, "EPIC/100 full duplex setting(s) (1)"); +MODULE_PARM_DESC(full_duplex, "EPIC/100 full duplex setting(s) (1=enable) - must be set manually on fiber"); /* Theory of Operation @@ -345,6 +350,7 @@ struct mii_if_info mii; unsigned int tx_full:1; /* The Tx queue is full. */ unsigned int default_port:4; /* Last dev->if_port value. */ + unsigned int mii_phy_id:32; /* MII_PHY_ID1 << 16 + MII_PHY_ID2 -> type of MII we have */ }; static int epic_open(struct net_device *dev); @@ -481,6 +487,9 @@ ep->chip_id = chip_idx; ep->chip_flags = pci_id_tbl[chip_idx].drv_flags; + /* (Christoph Dolina): Needed for rising up the Hardware */ + udelay(200); + /* Find the connected MII xcvrs. Doing this in open() would allow detecting external xcvrs later, but takes much time and no cards have external MII. */ @@ -502,6 +511,8 @@ printk(KERN_INFO DRV_NAME "(%s): Autonegotiation advertising %4.4x link " "partner %4.4x.\n", pdev->slot_name, ep->mii.advertising, mdio_read(dev, phy, 5)); + ep->mii_phy_id = mdio_read(dev,phy,MII_PHYSID1); + ep->mii_phy_id = (ep->mii_phy_id << 16) + mdio_read(dev,phy,MII_PHYSID2); } else if ( ! (ep->chip_flags & NO_MII)) { printk(KERN_WARNING DRV_NAME "(%s): ***WARNING***: No MII transceiver found!\n", pdev->slot_name); @@ -661,8 +672,9 @@ { struct epic_private *ep = dev->priv; long ioaddr = dev->base_addr; - int i; + int i,linkok; int retval; + signed long remaining; /* Soft reset the chip. */ outl(0x4001, ioaddr + GENCTL); @@ -697,33 +709,84 @@ outl(0x0412 | (RX_FIFO_THRESH<<8), ioaddr + GENCTL); #endif + /* (Christoph Dolina): Needed for rising up the Hardware */ + udelay(200); + for (i = 0; i < 3; i++) outl(cpu_to_le16(((u16*)dev->dev_addr)[i]), ioaddr + LAN0 + i*4); ep->tx_threshold = TX_FIFO_THRESH; outl(ep->tx_threshold, ioaddr + TxThresh); - if (media2miictl[dev->if_port & 15]) { - if (ep->mii_phy_cnt) - mdio_write(dev, ep->phys[0], MII_BMCR, media2miictl[dev->if_port&15]); - if (dev->if_port == 1) { - if (debug > 1) - printk(KERN_INFO "%s: Using the 10base2 transceiver, MII " - "status %4.4x.\n", - dev->name, mdio_read(dev, ep->phys[0], MII_BMSR)); + udelay(200); + + /* fiber media support for the SMC9432FTX-SC (using LevelOne LXT970 MII) */ + /* if fiber was selected and we have the LXT970 MII, search for link on fiber, if not found switch to utp */ + if ((dev->if_port==0 || dev->if_port==6) && ((ep->mii_phy_id & 0xfffffc00) == 0x78100000 ) ) + { + if (debug>1) + printk(KERN_INFO "%s: LXT970 found, activating fiber, waiting 1.5 sec for link up\n",dev->name); + + /* disable auto-negotiation, enable full duplex and 100 Mbps (see Level One LXT970 data sheet, revision 1.1, page 11-185) */ + mdio_write(dev, ep->phys[0], MII_BMCR, BMCR_FULLDPLX | BMCR_SPEED100); + /* enable fiber, Led_On must be set otherwise the fiber transceiver on the SMC9432FTX won't work ?! */ + mdio_write(dev, ep->phys[0], MII_LXT970_CONFIG, LXT970_CONFIG_100BASEFX | LXT970_CONFIG_LEDC_ON); + + /* Wait until fiber ready => so we can check for link up */ + remaining=1.5*HZ; + while (remaining) + { + set_current_state(TASK_INTERRUPTIBLE); + remaining=schedule_timeout(remaining); } - } else { - int mii_lpa = mdio_read(dev, ep->phys[0], MII_LPA); - if (mii_lpa != 0xffff) { - if ((mii_lpa & LPA_100FULL) || (mii_lpa & 0x01C0) == LPA_10FULL) - ep->mii.full_duplex = 1; - else if (! (mii_lpa & LPA_LPACK)) - mdio_write(dev, ep->phys[0], MII_BMCR, BMCR_ANENABLE|BMCR_ANRESTART); - if (debug > 1) - printk(KERN_INFO "%s: Setting %s-duplex based on MII xcvr %d" - " register read of %4.4x.\n", dev->name, - ep->mii.full_duplex ? "full" : "half", - ep->phys[0], mii_lpa); + + /* Status-Reg (0x14): check for link up */ + linkok = mdio_read(dev, ep->phys[0], MII_LXT970_CHIPSTAT); + if (debug>1) + if (linkok & LXT970_CHIPSTAT_LINKOK) + printk(KERN_INFO "%s: link on fiber interface detected\n", dev->name); + else + printk(KERN_INFO "%s: no link on fiber interface\n", dev->name); + } + else + { + linkok=0; /* we have no link till now */ + } + + /* IF no Link, change type of media */ + if ( (dev->if_port != 6) && (( linkok & LXT970_CHIPSTAT_LINKOK) == 0) ) { + if (debug > 1) + printk(KERN_INFO "%s: change media to utp/bnc\n", dev->name); + + /* if we have LXT970 transceiver, then disable fiber interface */ + if ( (ep->mii_phy_id & 0xfffffc00) == 0x78100000 ) + mdio_write(dev, ep->phys[0], MII_LXT970_CONFIG, 0x0000); + /* re-enable auto-negotiation */ + mdio_write(dev, ep->phys[0], MII_BMCR, BMCR_ANENABLE); + + /* now let's activate utp or bnc */ + if (media2miictl[dev->if_port & 15]) { + if (ep->mii_phy_cnt) + mdio_write(dev, ep->phys[0], MII_BMCR, media2miictl[dev->if_port&15]); + if (dev->if_port == 1) { + if (debug > 1) + printk(KERN_INFO "%s: Using the 10base2 transceiver, MII " + "status %4.4x.\n", + dev->name, mdio_read(dev, ep->phys[0], MII_BMSR)); + } + } else { + int mii_lpa = mdio_read(dev, ep->phys[0], MII_LPA); + if (mii_lpa != 0xffff) { + if ((mii_lpa & LPA_100FULL) || (mii_lpa & 0x01C0) == LPA_10FULL) + ep->mii.full_duplex = 1; + else if (! (mii_lpa & LPA_LPACK)) + mdio_write(dev, ep->phys[0], MII_BMCR, BMCR_ANENABLE|BMCR_ANRESTART); + if (debug > 1) + printk(KERN_INFO "%s: Setting %s-duplex based on MII xcvr %d" + " register read of %4.4x.\n", dev->name, + ep->mii.full_duplex ? "full" : "half", + ep->phys[0], mii_lpa); + } } } diff -uNr linux-2.4.19.SuSE/include/linux/lxt970.h linux-2.4.19.SuSE-new/include/linux/lxt970.h --- linux-2.4.19.SuSE/include/linux/lxt970.h Thu Jan 1 01:00:00 1970 +++ linux-2.4.19.SuSE-new/include/linux/lxt970.h Sat Aug 17 02:10:49 2002 @@ -0,0 +1,80 @@ +/* + * linux/lxt970.h: definitions for Level One LXT970 MII-compatible transceivers + * + * Copyright (C) 2002 Gernot Hillier (<gernot@hillier.de>) + */ + +#ifndef __LINUX_LXT970_H +#define __LINUX_LXT970_H + +#include <linux/mii.h> + +/* + * These are the register definitios for the Level One LXT970 MII-transceiver. + * + * As Level One isn't existing any more, there doesn't seem to be an official place + * for downloading data sheets out there (at least I didn't find one). + * + * Therefore I mirrored a copy of the data sheet on http://www.hillier.de/linux/970REV11.PDF + * + * The LXT970 is capable of both 10 and 100Mbps ethernet, in both + * half and full duplex mode. It supports cat5 and fiber optics. + * + */ + +/* vendor specific register set for LXT970 */ +#define MII_LXT970_MIRROR 0x10 /* Mirror Register */ +#define MII_LXT970_INTENAB 0x11 /* Interrupt Enable Register */ +#define MII_LXT970_INTSTAT 0x12 /* Interrupt Status Register */ +#define MII_LXT970_CONFIG 0x13 /* Config Register */ +#define MII_LXT970_CHIPSTAT 0x14 /* Chip Status Register */ + +/* LXT970 Interrupt Enable Register. */ +#define LXT970_INTENAB_TINT 0x0001 /* force MDINT */ +#define LXT970_INTENAB_INTEN 0x0002 /* enable interrupts */ +#define LXT970_INTENAB_RESV 0xfffc /* Unused... */ + +/* LXT970 Interrupt Status Register. */ +#define LXT970_INTSTAT_RESV 0x3fff /* Unused... */ +#define LXT970_INTSTAT_XTALOK 0x4000 /* XTAL circuit available */ +#define LXT970_INTSTAT_MINT 0x8000 /* MII interrupt pending */ + +/* LXT970 Configuration Register. */ +#define LXT970_CONFIG_TRANSDISC 0x0001 /* disconnect TP transmitter */ +#define LXT970_CONFIG_RESV1 0x0002 /* Unused... */ +#define LXT970_CONFIG_100BASEFX 0x0004 /* enable fiber interface */ +#define LXT970_CONFIG_NOSCRAM 0x0008 /* bypass scramblers */ +#define LXT970_CONFIG_5BSYMBOL 0x0010 /* 5-bit Symbol Mode */ +#define LXT970_CONFIG_TXCLOCK 0x0020 /* special TX clock mode */ +#define LXT970_CONFIG_LEDC_COLL 0x0000 /* LEDC indicates collision */ +#define LXT970_CONFIG_LEDC_OFF 0x0040 /* LEDC off */ +#define LXT970_CONFIG_LEDC_ACT 0x0080 /* LEDC indicates activity */ +#define LXT970_CONFIG_LEDC_ON 0x00c0 /* LEDC continuously on */ +#define LXT970_CONFIG_NOLINKTST 0x0100 /* disable 10BaseT link test */ +#define LXT970_CONFIG_NOJABBER 0x0200 /* disable 10BaseT jabber */ +#define LXT970_CONFIG_SQE 0x0400 /* enable 10BaseT SQE */ +#define LXT970_CONFIG_NOTPLOOPB 0x0800 /* disable 10BaseT TP loopback */ +#define LXT970_CONFIG_MDIOINT 0x1000 /* enable MDIO interrupt */ +#define LXT970_CONFIG_REPEATER 0x2000 /* enable repeater mode */ +#define LXT970_CONFIG_TXTEST 0x4000 /* enable 100BaseT transmit tst*/ +#define LXT970_CONFIG_RESV2 0x8000 /* Unused... */ + +/* LXT970 Chip Status Register. */ +#define LXT970_CHIPSTAT_NOPLL 0x0001 /* 100BaseTX/FX recv not locked*/ +#define LXT970_CHIPSTAT_RESV1 0x0002 /* Unused... */ +#define LXT970_CHIPSTAT_LVFAULT 0x0004 /* low voltage fault on VCC */ +#define LXT970_CHIPSTAT_RESV2 0x0008 /* Unused... */ +#define LXT970_CHIPSTAT_MLT3ERR 0x0010 /* MLT3 encoding error */ +#define LXT970_CHIPSTAT_SYMBERR 0x0020 /* Symbol Error detected */ +#define LXT970_CHIPSTAT_STREAML 0x0040 /* scrambler/decoder locked */ +#define LXT970_CHIPSTAT_RESV3 0x0080 /* Unused... */ +#define LXT970_CHIPSTAT_PAGERCV 0x0100 /* duplicate of EXPANSION_LCWP */ +#define LXT970_CHIPSTAT_ANCOMPL 0x0200 /* dupl of BMSR_ANEGCOMPLETE */ +#define LXT970_CHIPSTAT_RESV4 0x0400 /* Unused... */ +#define LXT970_CHIPSTAT_100MBPS 0x0800 /* 100 Mbps operation */ +#define LXT970_CHIPSTAT_FULLDPL 0x1000 /* full duplex operation */ +#define LXT970_CHIPSTAT_LINKOK 0x2000 /* link is up (dynamic) */ +#define LXT970_CHIPSTAT_RESV5 0xc000 /* Unused... */ + +#endif /* __LINUX_LXT970_H */ +