summaryrefslogtreecommitdiffstats
path: root/sys/dev/fxp
diff options
context:
space:
mode:
authordg <dg@FreeBSD.org>1997-03-17 11:08:16 +0000
committerdg <dg@FreeBSD.org>1997-03-17 11:08:16 +0000
commit8032f5328d8046c507154b8fdad9c17459bfb0c9 (patch)
tree1927984bcafa4dee1f2bec9126ab19549f49c537 /sys/dev/fxp
parent1062c914df46ad60942bb36e0bf0e6d8dc429171 (diff)
downloadFreeBSD-src-8032f5328d8046c507154b8fdad9c17459bfb0c9.zip
FreeBSD-src-8032f5328d8046c507154b8fdad9c17459bfb0c9.tar.gz
Fixed two deficiencies in the driver that have existed since it was
written: 1) Full duplex mode is now supported (and works!) 2) The 10Mbps-only PCI Pro/10 should now work (untested, however) Thanks to Justin Gibbs for providing a PCI bus analyzer trace while the Intel Windows driver was configuring the board...this made it possible to figure out the mystery bit that I wasn't setting in the PHY for full duplex to work.
Diffstat (limited to 'sys/dev/fxp')
-rw-r--r--sys/dev/fxp/if_fxp.c111
-rw-r--r--sys/dev/fxp/if_fxpreg.h28
2 files changed, 116 insertions, 23 deletions
diff --git a/sys/dev/fxp/if_fxp.c b/sys/dev/fxp/if_fxp.c
index ff4fef7..0b154cc 100644
--- a/sys/dev/fxp/if_fxp.c
+++ b/sys/dev/fxp/if_fxp.c
@@ -24,7 +24,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id$
+ * $Id: if_fxp.c,v 1.29 1997/02/22 09:44:05 peter Exp $
*/
/*
@@ -88,6 +88,9 @@ struct fxp_softc {
struct fxp_stats *fxp_stats; /* Pointer to interface stats */
int tx_queued; /* # of active TxCB's */
int promisc_mode; /* promiscuous mode enabled */
+ int phy_primary_addr; /* address of primary PHY */
+ int phy_primary_device; /* device type of primary PHY */
+ int phy_10Mbps_only; /* PHY is 10Mbps-only device */
};
static u_long fxp_count;
@@ -134,9 +137,12 @@ static int fxp_ioctl __P((struct ifnet *, int, caddr_t));
static void fxp_init __P((void *));
static void fxp_stop __P((struct fxp_softc *));
static void fxp_watchdog __P((struct ifnet *));
-static void fxp_get_macaddr __P((struct fxp_softc *));
static int fxp_add_rfabuf __P((struct fxp_softc *, struct mbuf *));
static void fxp_shutdown __P((int, void *));
+static int fxp_mdi_read __P((struct fxp_csr *, int, int));
+static void fxp_mdi_write __P((struct fxp_csr *, int, int, int));
+static void fxp_read_eeprom __P((struct fxp_csr *, u_short *, int, int));
+
timeout_t fxp_stats_update;
@@ -208,7 +214,7 @@ fxp_probe(config_id, device_id)
{
if (((device_id & 0xffff) == FXP_VENDORID_INTEL) &&
((device_id >> 16) & 0xffff) == FXP_DEVICEID_i82557)
- return ("Intel EtherExpress Pro/100B Fast Ethernet");
+ return ("Intel EtherExpress Pro 10/100B Ethernet");
return NULL;
}
@@ -225,6 +231,7 @@ fxp_attach(config_id, unit)
struct ifnet *ifp;
vm_offset_t pbase;
int s, i;
+ u_short data;
sc = malloc(sizeof(struct fxp_softc), M_DEVBUF, M_NOWAIT);
if (sc == NULL)
@@ -275,6 +282,14 @@ fxp_attach(config_id, unit)
}
}
+ /*
+ * Get info about the primary PHY
+ */
+ fxp_read_eeprom(sc->csr, (u_short *)&data, 6, 1);
+ sc->phy_primary_addr = data & 0xff;
+ sc->phy_primary_device = (data >> 8) & 0x3f;
+ sc->phy_10Mbps_only = data >> 15;
+
ifp = &sc->arpcom.ac_if;
ifp->if_softc = sc;
ifp->if_unit = unit;
@@ -287,9 +302,14 @@ fxp_attach(config_id, unit)
ifp->if_baudrate = 100000000;
ifp->if_init = fxp_init;
- fxp_get_macaddr(sc);
- printf("fxp%d: Ethernet address %6D\n", unit,
- sc->arpcom.ac_enaddr, ":");
+ /*
+ * Read MAC address
+ */
+ fxp_read_eeprom(sc->csr, (u_short *)sc->arpcom.ac_enaddr, 0, 3);
+ printf("fxp%d: Ethernet address %6D", unit, sc->arpcom.ac_enaddr, ":");
+ if (sc->phy_10Mbps_only)
+ printf(", 10Mbps");
+ printf("\n");
/*
* Attach the interface.
@@ -328,25 +348,23 @@ fail:
}
/*
- * Read station (MAC) address from serial EEPROM. Basically, you
- * manually shift in the read opcode (one bit at a time) and then
- * shift in the address, and then you shift out the data (all of
- * this one bit at a time). The word size is 16 bits, so you have
- * to provide the address for every 16 bits of data. The MAC address
- * is in the first 3 words (6 bytes total).
+ * Read from the serial EEPROM. Basically, you manually shift in
+ * the read opcode (one bit at a time) and then shift in the address,
+ * and then you shift out the data (all of this one bit at a time).
+ * The word size is 16 bits, so you have to provide the address for
+ * every 16 bits of data.
*/
static void
-fxp_get_macaddr(sc)
- struct fxp_softc *sc;
-{
+fxp_read_eeprom(csr, data, offset, words)
struct fxp_csr *csr;
- u_short reg, *data;
+ u_short *data;
+ int offset;
+ int words;
+{
+ u_short reg;
int i, x;
- csr = sc->csr;
- data = (u_short *)sc->arpcom.ac_enaddr;
-
- for (i = 0; i < 3; i++) {
+ for (i = 0; i < words; i++) {
csr->eeprom_control = FXP_EEPROM_EECS;
/*
* Shift in read opcode.
@@ -367,7 +385,7 @@ fxp_get_macaddr(sc)
* Shift in address.
*/
for (x = 6; x > 0; x--) {
- if (i & (1 << (x - 1))) {
+ if ((i + offset) & (1 << (x - 1))) {
reg = FXP_EEPROM_EECS | FXP_EEPROM_EEDI;
} else {
reg = FXP_EEPROM_EECS;
@@ -864,7 +882,7 @@ fxp_init(xsc)
cbp->save_bf = prm; /* save bad frames */
cbp->disc_short_rx = !prm; /* discard short packets */
cbp->underrun_retry = 1; /* retry mode (1) on DMA underrun */
- cbp->mediatype = 1; /* (MII) interface mode */
+ cbp->mediatype = !sc->phy_10Mbps_only; /* interface mode */
cbp->nsai = 1; /* (don't) disable source addr insert */
cbp->preamble_length = 2; /* (7 byte) preamble */
cbp->loopback = 0; /* (don't) loopback */
@@ -941,6 +959,17 @@ fxp_init(xsc)
csr->scb_general = vtophys(sc->rfa_headm->m_ext.ext_buf);
csr->scb_command = FXP_SCB_COMMAND_RU_START;
+ /*
+ * Toggle a few bits in the DP83840 PHY.
+ */
+ if (sc->phy_primary_device == FXP_PHY_DP83840) {
+ fxp_mdi_write(sc->csr, sc->phy_primary_addr, FXP_DP83840_PCR,
+ fxp_mdi_read(sc->csr, sc->phy_primary_addr, FXP_DP83840_PCR) |
+ FXP_DP83840_PCR_LED4_MODE | /* LED4 always indicates duplex */
+ FXP_DP83840_PCR_F_CONNECT | /* force link disconnect bypass */
+ FXP_DP83840_PCR_BIT10); /* XXX I have no idea */
+ }
+
ifp->if_flags |= IFF_RUNNING;
ifp->if_flags &= ~IFF_OACTIVE;
splx(s);
@@ -1014,6 +1043,44 @@ fxp_add_rfabuf(sc, oldm)
}
static int
+fxp_mdi_read(csr, phy, reg)
+ struct fxp_csr *csr;
+ int phy;
+ int reg;
+{
+ int count = 10000;
+
+ csr->mdi_control = (FXP_MDI_READ << 26) | (reg << 16) | (phy << 21);
+
+ while ((csr->mdi_control & 0x10000000) == 0 && count--)
+ DELAY(1);
+
+ if (count <= 0)
+ printf("fxp_mdi_read: timed out\n");
+
+ return (csr->mdi_control & 0xffff);
+}
+
+static void
+fxp_mdi_write(csr, phy, reg, value)
+ struct fxp_csr *csr;
+ int phy;
+ int reg;
+ int value;
+{
+ int count = 10000;
+
+ csr->mdi_control = (FXP_MDI_WRITE << 26) | (reg << 16) | (phy << 21)
+ | (value & 0xffff);
+
+ while ((csr->mdi_control & 10000000) == 0 && count--)
+ DELAY(1);
+
+ if (count <= 0)
+ printf("fxp_mdi_write: timed out\n");
+}
+
+static int
fxp_ioctl(ifp, command, data)
struct ifnet *ifp;
int command;
diff --git a/sys/dev/fxp/if_fxpreg.h b/sys/dev/fxp/if_fxpreg.h
index e62e727..b6005d7 100644
--- a/sys/dev/fxp/if_fxpreg.h
+++ b/sys/dev/fxp/if_fxpreg.h
@@ -24,7 +24,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id$
+ * $Id: if_fxpreg.h,v 1.6 1997/02/22 09:44:06 peter Exp $
*/
#define FXP_VENDORID_INTEL 0x8086
@@ -275,3 +275,29 @@ struct fxp_stats {
#define FXP_EEPROM_OPC_ERASE 0x4
#define FXP_EEPROM_OPC_WRITE 0x5
#define FXP_EEPROM_OPC_READ 0x6
+
+/*
+ * Management Data Interface opcodes
+ */
+#define FXP_MDI_WRITE 0x1
+#define FXP_MDI_READ 0x2
+
+/*
+ * PHY device types
+ */
+#define FXP_PHY_NONE 0
+#define FXP_PHY_82553A 1
+#define FXP_PHY_82553C 2
+#define FXP_PHY_82503 3
+#define FXP_PHY_DP83840 4
+#define FXP_PHY_80C240 5
+#define FXP_PHY_80C24 6
+
+/*
+ * DP84830 PHY, PCS Configuration Register
+ */
+#define FXP_DP83840_PCR 0x17
+#define FXP_DP83840_PCR_LED4_MODE 0x0002 /* 1 = LED4 always indicates full duplex */
+#define FXP_DP83840_PCR_F_CONNECT 0x0020 /* 1 = force link disconnect function bypass */
+#define FXP_DP83840_PCR_BIT8 0x0100
+#define FXP_DP83840_PCR_BIT10 0x0400
OpenPOWER on IntegriCloud