[epic] [PATCH] epic100-fiber support, improved
Gernot Hillier
gernot@hillier.de
Mon Aug 19 10:09:23 2002
--------------Boundary-00=_3DOZ11EFAKBW9ZHPZDJ8
Content-Type: text/plain;
charset="iso-8859-1"
Content-Transfer-Encoding: quoted-printable
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Hi!
This patch allows to use the fiber interface of the SMC9432FTX NIC or oth=
er
epic-based cards using the LXT970 transceiver.
The attached patch (md5sum: abcb5c02ea3e14a6ac50badaddc465ba) applies cle=
anly=20
to 2.4.19-marcelo. If you miss the patch (i.e. if you find this message o=
n=20
some list archive stripping of attachments), you can also retrieve it fro=
m my=20
web page referenced below.
If someone needs a patch against the sources of Donald Becker, please tel=
l me=20
and I'll try to make one ASAP!
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 o=
nly
on cards having the LXT970
* module option for forcing the use of fiber interface added (options=3D6=
)
* 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 >=3D 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 sin=
ce
some weeks on 48 workstations and 2 servers running 24/7
TIA for your feedback!
This patch has also been submitted for inclusion in the 2.4.X-kernel-seri=
es to=20
linux-net.
- --
Ciao,
Gernot
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.0.6 (GNU/Linux)
Comment: For info see http://www.gnupg.org
iD8DBQE9XkoZk997/GGeSeIRAhzAAJ9D7sHPS3ERmya1Tnc5LTKcXmvHBgCgp8N7
/H4NZ30Gdv8v+RiDbFSpZno=3D
=3D55JX
-----END PGP SIGNATURE-----
--------------Boundary-00=_3DOZ11EFAKBW9ZHPZDJ8
Content-Type: text/x-diff;
charset="iso-8859-1";
name="epic100_fx_2.4.19.diff"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename="epic100_fx_2.4.19.diff"
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 */
+
--------------Boundary-00=_3DOZ11EFAKBW9ZHPZDJ8--