summaryrefslogtreecommitdiffstats
path: root/sys/dev/fxp
diff options
context:
space:
mode:
authorjlemon <jlemon@FreeBSD.org>2001-03-12 21:30:52 +0000
committerjlemon <jlemon@FreeBSD.org>2001-03-12 21:30:52 +0000
commitf2248a59960d4aa49a221cef285ef5ec4e6694ab (patch)
treefb73368db8fab000c9b12c27371ca6e4ca5bba19 /sys/dev/fxp
parentbfe50892f16ba10eae7e56bc0e969046f2a3cf4b (diff)
downloadFreeBSD-src-f2248a59960d4aa49a221cef285ef5ec4e6694ab.zip
FreeBSD-src-f2248a59960d4aa49a221cef285ef5ec4e6694ab.tar.gz
Convert the fxp driver to miibus, which involves ripping out the PHY
logic and media bits. Support for Intel PHYs can now be found in dev/mii/inphy.c. Clean up the driver, and add various 82558 and 82559 specific bits.
Diffstat (limited to 'sys/dev/fxp')
-rw-r--r--sys/dev/fxp/if_fxp.c1103
-rw-r--r--sys/dev/fxp/if_fxpreg.h173
-rw-r--r--sys/dev/fxp/if_fxpvar.h70
3 files changed, 589 insertions, 757 deletions
diff --git a/sys/dev/fxp/if_fxp.c b/sys/dev/fxp/if_fxp.c
index 068bd8c..dff27c5 100644
--- a/sys/dev/fxp/if_fxp.c
+++ b/sys/dev/fxp/if_fxp.c
@@ -1,10 +1,8 @@
-/*
+/*-
+ * Copyright (c) 2001 Jonathan Lemon <jlemon@freebsd.org>
* Copyright (c) 1995, David Greenman
* All rights reserved.
*
- * Modifications to support media selection:
- * Copyright (c) 1997 Jason R. Thorpe. All rights reserved.
- *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
@@ -38,7 +36,7 @@
#include <sys/systm.h>
#include <sys/mbuf.h>
#include <sys/malloc.h>
-#include <sys/mutex.h>
+ /* #include <sys/mutex.h> */
#include <sys/kernel.h>
#include <sys/socket.h>
@@ -63,17 +61,19 @@
#include <vm/vm.h> /* for vtophys */
#include <vm/pmap.h> /* for vtophys */
+#include <machine/clock.h> /* for DELAY */
#include <pci/pcivar.h>
#include <pci/pcireg.h> /* for PCIM_CMD_xxx */
-#include <pci/if_fxpreg.h>
-#include <pci/if_fxpvar.h>
-#ifdef __alpha__ /* XXX */
-/* XXX XXX NEED REAL DMA MAPPING SUPPORT XXX XXX */
-#undef vtophys
-#define vtophys(va) alpha_XXX_dmamap((vm_offset_t)(va))
-#endif /* __alpha__ */
+#include <dev/mii/mii.h>
+#include <dev/mii/miivar.h>
+
+#include <dev/fxp/if_fxpreg.h>
+#include <dev/fxp/if_fxpvar.h>
+
+MODULE_DEPEND(fxp, miibus, 1, 1, 1);
+#include "miibus_if.h"
/*
* NOTE! On the Alpha, we have an alignment constraint. The
@@ -87,195 +87,183 @@
#define RFA_ALIGNMENT_FUDGE 2
/*
- * Inline function to copy a 16-bit aligned 32-bit quantity.
+ * Set initial transmit threshold at 64 (512 bytes). This is
+ * increased by 64 (512 bytes) at a time, to maximum of 192
+ * (1536 bytes), if an underrun occurs.
*/
-static __inline void fxp_lwcopy __P((volatile u_int32_t *,
- volatile u_int32_t *));
-static __inline void
-fxp_lwcopy(src, dst)
- volatile u_int32_t *src, *dst;
-{
-#ifdef __i386__
- *dst = *src;
-#else
- volatile u_int16_t *a = (volatile u_int16_t *)src;
- volatile u_int16_t *b = (volatile u_int16_t *)dst;
-
- b[0] = a[0];
- b[1] = a[1];
-#endif
-}
+static int tx_threshold = 64;
/*
- * Template for default configuration parameters.
+ * The configuration byte map has several undefined fields which
+ * must be one or must be zero. Set up a template for these bits
+ * only, (assuming a 82557 chip) leaving the actual configuration
+ * to fxp_init.
+ *
* See struct fxp_cb_config for the bit definitions.
*/
static u_char fxp_cb_config_template[] = {
0x0, 0x0, /* cb_status */
- 0x80, 0x2, /* cb_command */
- 0xff, 0xff, 0xff, 0xff, /* link_addr */
- 0x16, /* 0 */
- 0x8, /* 1 */
+ 0x0, 0x0, /* cb_command */
+ 0x0, 0x0, 0x0, 0x0, /* link_addr */
+ 0x0, /* 0 */
+ 0x0, /* 1 */
0x0, /* 2 */
0x0, /* 3 */
0x0, /* 4 */
- 0x80, /* 5 */
- 0xb2, /* 6 */
- 0x3, /* 7 */
- 0x1, /* 8 */
+ 0x0, /* 5 */
+ 0x32, /* 6 */
+ 0x0, /* 7 */
+ 0x0, /* 8 */
0x0, /* 9 */
- 0x26, /* 10 */
+ 0x6, /* 10 */
0x0, /* 11 */
- 0x60, /* 12 */
+ 0x0, /* 12 */
0x0, /* 13 */
0xf2, /* 14 */
0x48, /* 15 */
0x0, /* 16 */
0x40, /* 17 */
- 0xf3, /* 18 */
+ 0xf0, /* 18 */
0x0, /* 19 */
0x3f, /* 20 */
0x5 /* 21 */
};
-/* Supported media types. */
-struct fxp_supported_media {
- const int fsm_phy; /* PHY type */
- const int *fsm_media; /* the media array */
- const int fsm_nmedia; /* the number of supported media */
- const int fsm_defmedia; /* default media for this PHY */
+struct fxp_ident {
+ u_int16_t devid;
+ char *name;
};
-static const int fxp_media_standard[] = {
- IFM_ETHER|IFM_10_T,
- IFM_ETHER|IFM_10_T|IFM_FDX,
- IFM_ETHER|IFM_100_TX,
- IFM_ETHER|IFM_100_TX|IFM_FDX,
- IFM_ETHER|IFM_AUTO,
+/*
+ * Claim various Intel PCI device identifiers for this driver. The
+ * sub-vendor and sub-device field are extensively used to identify
+ * particular variants, but we don't currently differentiate between
+ * them.
+ */
+static struct fxp_ident fxp_ident_table[] = {
+ { 0x1229, "Intel Pro 10/100B/100+ Ethernet" },
+ { 0x2449, "Intel Pro/100 Ethernet" },
+ { 0x1209, "Intel Embedded 10/100 Ethernet" },
+ { 0x1029, "Intel Pro/100 Ethernet" },
+ { 0x1030, "Intel Pro/100 Ethernet" },
+ { 0x1031, "Intel Pro/100 Ethernet" },
+ { 0x1032, "Intel Pro/100 Ethernet" },
+ { 0x1033, "Intel Pro/100 Ethernet" },
+ { 0x1034, "Intel Pro/100 Ethernet" },
+ { 0x1035, "Intel Pro/100 Ethernet" },
+ { 0x1036, "Intel Pro/100 Ethernet" },
+ { 0x1037, "Intel Pro/100 Ethernet" },
+ { 0x1038, "Intel Pro/100 Ethernet" },
+ { 0, NULL },
};
-#define FXP_MEDIA_STANDARD_DEFMEDIA (IFM_ETHER|IFM_AUTO)
-static const int fxp_media_default[] = {
- IFM_ETHER|IFM_MANUAL, /* XXX IFM_AUTO ? */
-};
-#define FXP_MEDIA_DEFAULT_DEFMEDIA (IFM_ETHER|IFM_MANUAL)
-
-static const struct fxp_supported_media fxp_media[] = {
- { FXP_PHY_DP83840, fxp_media_standard,
- sizeof(fxp_media_standard) / sizeof(fxp_media_standard[0]),
- FXP_MEDIA_STANDARD_DEFMEDIA },
- { FXP_PHY_DP83840A, fxp_media_standard,
- sizeof(fxp_media_standard) / sizeof(fxp_media_standard[0]),
- FXP_MEDIA_STANDARD_DEFMEDIA },
- { FXP_PHY_82553A, fxp_media_standard,
- sizeof(fxp_media_standard) / sizeof(fxp_media_standard[0]),
- FXP_MEDIA_STANDARD_DEFMEDIA },
- { FXP_PHY_82553C, fxp_media_standard,
- sizeof(fxp_media_standard) / sizeof(fxp_media_standard[0]),
- FXP_MEDIA_STANDARD_DEFMEDIA },
- { FXP_PHY_82555, fxp_media_standard,
- sizeof(fxp_media_standard) / sizeof(fxp_media_standard[0]),
- FXP_MEDIA_STANDARD_DEFMEDIA },
- { FXP_PHY_82555B, fxp_media_standard,
- sizeof(fxp_media_standard) / sizeof(fxp_media_standard[0]),
- FXP_MEDIA_STANDARD_DEFMEDIA },
- { FXP_PHY_80C24, fxp_media_default,
- sizeof(fxp_media_default) / sizeof(fxp_media_default[0]),
- FXP_MEDIA_DEFAULT_DEFMEDIA },
-};
-#define NFXPMEDIA (sizeof(fxp_media) / sizeof(fxp_media[0]))
-
-static int fxp_mediachange __P((struct ifnet *));
-static void fxp_mediastatus __P((struct ifnet *, struct ifmediareq *));
-static void fxp_set_media __P((struct fxp_softc *, int));
-static __inline void fxp_scb_wait __P((struct fxp_softc *));
-static __inline void fxp_dma_wait __P((volatile u_int16_t *, struct fxp_softc *sc));
-static void fxp_intr __P((void *));
-static void fxp_start __P((struct ifnet *));
-static int fxp_ioctl __P((struct ifnet *,
- u_long, caddr_t));
-static void fxp_init __P((void *));
-static void fxp_stop __P((struct fxp_softc *));
-static void fxp_watchdog __P((struct ifnet *));
-static int fxp_add_rfabuf __P((struct fxp_softc *, struct mbuf *));
-static int fxp_mdi_read __P((struct fxp_softc *, int, int));
-static void fxp_mdi_write __P((struct fxp_softc *, int, int, int));
-static void fxp_autosize_eeprom __P((struct fxp_softc *));
-static void fxp_read_eeprom __P((struct fxp_softc *, u_int16_t *,
- int, int));
-static int fxp_attach_common __P((struct fxp_softc *, u_int8_t *));
-static void fxp_stats_update __P((void *));
-static void fxp_mc_setup __P((struct fxp_softc *));
+static int fxp_probe(device_t dev);
+static int fxp_attach(device_t dev);
+static int fxp_detach(device_t dev);
+static int fxp_shutdown(device_t dev);
+static int fxp_suspend(device_t dev);
+static int fxp_resume(device_t dev);
+
+static void fxp_intr(void *xsc);
+static void fxp_init(void *xsc);
+static void fxp_tick(void *xsc);
+static void fxp_start(struct ifnet *ifp);
+static void fxp_stop(struct fxp_softc *sc);
+static void fxp_release(struct fxp_softc *sc);
+static int fxp_ioctl(struct ifnet *ifp, u_long command,
+ caddr_t data);
+static void fxp_watchdog(struct ifnet *ifp);
+static int fxp_add_rfabuf(struct fxp_softc *sc, struct mbuf *oldm);
+static void fxp_mc_setup(struct fxp_softc *sc);
+static u_int16_t fxp_eeprom_getword(struct fxp_softc *sc, int offset,
+ int autosize);
+static void fxp_autosize_eeprom(struct fxp_softc *sc);
+static void fxp_read_eeprom(struct fxp_softc *sc, u_short *data,
+ int offset, int words);
+static int fxp_ifmedia_upd(struct ifnet *ifp);
+static void fxp_ifmedia_sts(struct ifnet *ifp,
+ struct ifmediareq *ifmr);
+static int fxp_serial_ifmedia_upd(struct ifnet *ifp);
+static void fxp_serial_ifmedia_sts(struct ifnet *ifp,
+ struct ifmediareq *ifmr);
+static volatile int fxp_miibus_readreg(device_t dev, int phy, int reg);
+static void fxp_miibus_writereg(device_t dev, int phy, int reg,
+ int value);
+static __inline void fxp_lwcopy(volatile u_int32_t *src,
+ volatile u_int32_t *dst);
+static __inline void fxp_scb_wait(struct fxp_softc *sc);
+static __inline void fxp_dma_wait(volatile u_int16_t *status,
+ struct fxp_softc *sc);
-/*
- * Set initial transmit threshold at 64 (512 bytes). This is
- * increased by 64 (512 bytes) at a time, to maximum of 192
- * (1536 bytes), if an underrun occurs.
- */
-static int tx_threshold = 64;
+static device_method_t fxp_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, fxp_probe),
+ DEVMETHOD(device_attach, fxp_attach),
+ DEVMETHOD(device_detach, fxp_detach),
+ DEVMETHOD(device_shutdown, fxp_shutdown),
+ DEVMETHOD(device_suspend, fxp_suspend),
+ DEVMETHOD(device_resume, fxp_resume),
-/*
- * Number of transmit control blocks. This determines the number
- * of transmit buffers that can be chained in the CB list.
- * This must be a power of two.
- */
-#define FXP_NTXCB 128
+ /* MII interface */
+ DEVMETHOD(miibus_readreg, fxp_miibus_readreg),
+ DEVMETHOD(miibus_writereg, fxp_miibus_writereg),
-/*
- * Number of completed TX commands at which point an interrupt
- * will be generated to garbage collect the attached buffers.
- * Must be at least one less than FXP_NTXCB, and should be
- * enough less so that the transmitter doesn't becomes idle
- * during the buffer rundown (which would reduce performance).
- */
-#define FXP_CXINT_THRESH 120
+ { 0, 0 }
+};
-/*
- * TxCB list index mask. This is used to do list wrap-around.
- */
-#define FXP_TXCB_MASK (FXP_NTXCB - 1)
+static driver_t fxp_driver = {
+ "fxp",
+ fxp_methods,
+ sizeof(struct fxp_softc),
+};
-/*
- * Number of receive frame area buffers. These are large so chose
- * wisely.
- */
-#define FXP_NRFABUFS 64
+static devclass_t fxp_devclass;
+
+DRIVER_MODULE(if_fxp, pci, fxp_driver, fxp_devclass, 0, 0);
+DRIVER_MODULE(if_fxp, cardbus, fxp_driver, fxp_devclass, 0, 0);
+DRIVER_MODULE(miibus, fxp, miibus_driver, miibus_devclass, 0, 0);
/*
- * Maximum number of seconds that the receiver can be idle before we
- * assume it's dead and attempt to reset it by reprogramming the
- * multicast filter. This is part of a work-around for a bug in the
- * NIC. See fxp_stats_update().
+ * Inline function to copy a 16-bit aligned 32-bit quantity.
*/
-#define FXP_MAX_RX_IDLE 15
+static __inline void
+fxp_lwcopy(volatile u_int32_t *src, volatile u_int32_t *dst)
+{
+#ifdef __i386__
+ *dst = *src;
+#else
+ volatile u_int16_t *a = (volatile u_int16_t *)src;
+ volatile u_int16_t *b = (volatile u_int16_t *)dst;
+
+ b[0] = a[0];
+ b[1] = a[1];
+#endif
+}
/*
* Wait for the previous command to be accepted (but not necessarily
* completed).
*/
static __inline void
-fxp_scb_wait(sc)
- struct fxp_softc *sc;
+fxp_scb_wait(struct fxp_softc *sc)
{
int i = 10000;
while (CSR_READ_1(sc, FXP_CSR_SCB_COMMAND) && --i)
DELAY(2);
if (i == 0)
- printf("fxp%d: SCB timeout\n", FXP_UNIT(sc));
+ device_printf(sc->dev, "SCB timeout\n");
}
static __inline void
-fxp_dma_wait(status, sc)
- volatile u_int16_t *status;
- struct fxp_softc *sc;
+fxp_dma_wait(volatile u_int16_t *status, struct fxp_softc *sc)
{
int i = 10000;
while (!(*status & FXP_CB_STATUS_C) && --i)
DELAY(2);
if (i == 0)
- printf("fxp%d: DMA timeout\n", FXP_UNIT(sc));
+ device_printf(sc->dev, "DMA timeout\n");
}
/*
@@ -284,27 +272,19 @@ fxp_dma_wait(status, sc)
static int
fxp_probe(device_t dev)
{
+ u_int16_t devid;
+ struct fxp_ident *ident;
+
if (pci_get_vendor(dev) == FXP_VENDORID_INTEL) {
- switch (pci_get_device(dev)) {
-
- case FXP_DEVICEID_i82557:
- device_set_desc(dev, "Intel Pro 10/100B/100+ Ethernet");
- return 0;
- case FXP_DEVICEID_i82559:
- device_set_desc(dev, "Intel InBusiness 10/100 Ethernet");
- return 0;
- case FXP_DEVICEID_i82559ER:
- device_set_desc(dev, "Intel Embedded 10/100 Ethernet");
- return 0;
- case FXP_DEVICEID_i82562:
- device_set_desc(dev, "Intel PLC 10/100 Ethernet");
- return 0;
- default:
- break;
+ devid = pci_get_device(dev);
+ for (ident = fxp_ident_table; ident->name != NULL; ident++) {
+ if (ident->devid == devid) {
+ device_set_desc(dev, ident->name);
+ return (0);
+ }
}
}
-
- return ENXIO;
+ return (ENXIO);
}
static int
@@ -314,12 +294,16 @@ fxp_attach(device_t dev)
struct fxp_softc *sc = device_get_softc(dev);
struct ifnet *ifp;
u_int32_t val;
- int rid, m1, m2, prefer_iomap;
+ u_int16_t data;
+ int i, rid, m1, m2, prefer_iomap;
+ int s;
- mtx_init(&sc->sc_mtx, device_get_nameunit(dev), MTX_DEF | MTX_RECURSE);
+ bzero(sc, sizeof(*sc));
+ sc->dev = dev;
callout_handle_init(&sc->stat_ch);
+ mtx_init(&sc->sc_mtx, device_get_nameunit(dev), MTX_DEF | MTX_RECURSE);
- FXP_LOCK(sc);
+ s = splimp();
/*
* Enable bus mastering. Enable memory space too, in case
@@ -330,6 +314,7 @@ fxp_attach(device_t dev)
pci_write_config(dev, PCIR_COMMAND, val, 2);
val = pci_read_config(dev, PCIR_COMMAND, 2);
+#if __FreeBSD_version >= 500000
if (pci_get_powerstate(dev) != PCI_POWERSTATE_D0) {
u_int32_t iobase, membase, irq;
@@ -349,6 +334,7 @@ fxp_attach(device_t dev)
pci_write_config(dev, FXP_PCI_MMBA, membase, 4);
pci_write_config(dev, PCIR_INTLINE, irq, 4);
}
+#endif
/*
* Figure out which we should try first - memory mapping or i/o mapping?
@@ -411,18 +397,83 @@ fxp_attach(device_t dev)
goto fail;
}
- /* Do generic parts of attach. */
- if (fxp_attach_common(sc, sc->arpcom.ac_enaddr)) {
- /* Failed! */
- bus_teardown_intr(dev, sc->irq, sc->ih);
- bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq);
- bus_release_resource(dev, sc->rtp, sc->rgd, sc->mem);
- error = ENXIO;
- goto fail;
+ /*
+ * Reset to a stable state.
+ */
+ CSR_WRITE_4(sc, FXP_CSR_PORT, FXP_PORT_SELECTIVE_RESET);
+ DELAY(10);
+
+ sc->cbl_base = malloc(sizeof(struct fxp_cb_tx) * FXP_NTXCB,
+ M_DEVBUF, M_NOWAIT | M_ZERO);
+ if (sc->cbl_base == NULL)
+ goto failmem;
+
+ sc->fxp_stats = malloc(sizeof(struct fxp_stats), M_DEVBUF,
+ M_NOWAIT | M_ZERO);
+ if (sc->fxp_stats == NULL)
+ goto failmem;
+
+ sc->mcsp = malloc(sizeof(struct fxp_cb_mcs), M_DEVBUF, M_NOWAIT);
+ if (sc->mcsp == NULL)
+ goto failmem;
+
+ /*
+ * Pre-allocate our receive buffers.
+ */
+ for (i = 0; i < FXP_NRFABUFS; i++) {
+ if (fxp_add_rfabuf(sc, NULL) != 0) {
+ goto failmem;
+ }
}
+ /*
+ * Find out how large of an SEEPROM we have.
+ */
+ fxp_autosize_eeprom(sc);
+
+ /*
+ * Determine in whether we must use the 503 serial interface.
+ */
+ fxp_read_eeprom(sc, &data, 6, 1);
+ if ((data & FXP_PHY_DEVICE_MASK) != 0 &&
+ (data & FXP_PHY_SERIAL_ONLY))
+ sc->flags &= FXP_FLAG_SERIAL_MEDIA;
+
+ /*
+ * Read MAC address.
+ */
+ fxp_read_eeprom(sc, (u_int16_t *)sc->arpcom.ac_enaddr, 0, 3);
device_printf(dev, "Ethernet address %6D%s\n",
- sc->arpcom.ac_enaddr, ":", sc->phy_10Mbps_only ? ", 10Mbps" : "");
+ sc->arpcom.ac_enaddr, ":",
+ sc->flags & FXP_FLAG_SERIAL_MEDIA ? ", 10Mbps" : "");
+ if (bootverbose) {
+ device_printf(dev, "PCI IDs: %04x %04x %04x %04x\n",
+ pci_get_vendor(dev), pci_get_device(dev),
+ pci_get_subvendor(dev), pci_get_subdevice(dev));
+ }
+
+ /*
+ * If this is only a 10Mbps device, then there is no MII, and
+ * the PHY will use a serial interface instead.
+ *
+ * The Seeq 80c24 AutoDUPLEX(tm) Ethernet Interface Adapter
+ * doesn't have a programming interface of any sort. The
+ * media is sensed automatically based on how the link partner
+ * is configured. This is, in essence, manual configuration.
+ */
+ if (sc->flags & FXP_FLAG_SERIAL_MEDIA) {
+ ifmedia_init(&sc->sc_media, 0, fxp_serial_ifmedia_upd,
+ fxp_serial_ifmedia_sts);
+ ifmedia_add(&sc->sc_media, IFM_ETHER|IFM_MANUAL, 0, NULL);
+ ifmedia_set(&sc->sc_media, IFM_ETHER|IFM_MANUAL);
+ } else {
+ if (mii_phy_probe(dev, &sc->miibus, fxp_ifmedia_upd,
+ fxp_ifmedia_sts)) {
+ device_printf(dev, "MII without any PHY!\n");
+ error = ENXIO;
+ goto fail;
+ }
+ }
ifp = &sc->arpcom.ac_if;
ifp->if_unit = device_get_unit(dev);
@@ -440,19 +491,53 @@ fxp_attach(device_t dev)
* Attach the interface.
*/
ether_ifattach(ifp, ETHER_BPF_SUPPORTED);
+
/*
* Let the system queue as many packets as we have available
* TX descriptors.
*/
ifp->if_snd.ifq_maxlen = FXP_NTXCB - 1;
- FXP_UNLOCK(sc);
- return 0;
+ splx(s);
+ return (0);
+
+failmem:
+ device_printf(dev, "Failed to malloc memory\n");
+ error = ENOMEM;
+fail:
+ splx(s);
+ fxp_release(sc);
+ return (error);
+}
+
+/*
+ * release all resources
+ */
+static void
+fxp_release(struct fxp_softc *sc)
+{
+
+ if (sc->miibus) {
+ bus_generic_detach(sc->dev);
+ device_delete_child(sc->dev, sc->miibus);
+ }
+
+ if (sc->cbl_base)
+ free(sc->cbl_base, M_DEVBUF);
+ if (sc->fxp_stats)
+ free(sc->fxp_stats, M_DEVBUF);
+ if (sc->mcsp)
+ free(sc->mcsp, M_DEVBUF);
+ if (sc->rfa_headm)
+ m_freem(sc->rfa_headm);
- fail:
- FXP_UNLOCK(sc);
+ if (sc->ih)
+ bus_teardown_intr(sc->dev, sc->irq, sc->ih);
+ if (sc->irq)
+ bus_release_resource(sc->dev, SYS_RES_IRQ, 0, sc->irq);
+ if (sc->mem)
+ bus_release_resource(sc->dev, sc->rtp, sc->rgd, sc->mem);
mtx_destroy(&sc->sc_mtx);
- return error;
}
/*
@@ -462,13 +547,9 @@ static int
fxp_detach(device_t dev)
{
struct fxp_softc *sc = device_get_softc(dev);
+ int s;
- FXP_LOCK(sc);
-
- /*
- * Close down routes etc.
- */
- ether_ifdetach(&sc->arpcom.ac_if, ETHER_BPF_SUPPORTED);
+ s = splimp();
/*
* Stop DMA and drop transmit queue.
@@ -476,34 +557,21 @@ fxp_detach(device_t dev)
fxp_stop(sc);
/*
- * Deallocate resources.
- */
- bus_teardown_intr(dev, sc->irq, sc->ih);
- bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq);
- bus_release_resource(dev, sc->rtp, sc->rgd, sc->mem);
-
- /*
- * Free all the receive buffers.
+ * Close down routes etc.
*/
- if (sc->rfa_headm != NULL)
- m_freem(sc->rfa_headm);
+ ether_ifdetach(&sc->arpcom.ac_if, ETHER_BPF_SUPPORTED);
/*
* Free all media structures.
*/
ifmedia_removeall(&sc->sc_media);
- /*
- * Free anciliary structures.
- */
- free(sc->cbl_base, M_DEVBUF);
- free(sc->fxp_stats, M_DEVBUF);
- free(sc->mcsp, M_DEVBUF);
+ splx(s);
- FXP_UNLOCK(sc);
- mtx_destroy(&sc->sc_mtx);
+ /* Release our allocated resources. */
+ fxp_release(sc);
- return 0;
+ return (0);
}
/*
@@ -520,7 +588,7 @@ fxp_shutdown(device_t dev)
* reboot before the driver initializes.
*/
fxp_stop((struct fxp_softc *) device_get_softc(dev));
- return 0;
+ return (0);
}
/*
@@ -532,9 +600,9 @@ static int
fxp_suspend(device_t dev)
{
struct fxp_softc *sc = device_get_softc(dev);
- int i;
+ int i, s;
- FXP_LOCK(sc);
+ s = splimp();
fxp_stop(sc);
@@ -547,9 +615,8 @@ fxp_suspend(device_t dev)
sc->suspended = 1;
- FXP_UNLOCK(sc);
-
- return 0;
+ splx(s);
+ return (0);
}
/*
@@ -563,9 +630,9 @@ fxp_resume(device_t dev)
struct fxp_softc *sc = device_get_softc(dev);
struct ifnet *ifp = &sc->sc_if;
u_int16_t pci_command;
- int i;
+ int i, s;
- FXP_LOCK(sc);
+ s = splimp();
/* better way to do this? */
for (i=0; i<5; i++)
@@ -589,132 +656,78 @@ fxp_resume(device_t dev)
sc->suspended = 0;
- FXP_UNLOCK(sc);
-
- return 0;
+ splx(s);
+ return (0);
}
-static device_method_t fxp_methods[] = {
- /* Device interface */
- DEVMETHOD(device_probe, fxp_probe),
- DEVMETHOD(device_attach, fxp_attach),
- DEVMETHOD(device_detach, fxp_detach),
- DEVMETHOD(device_shutdown, fxp_shutdown),
- DEVMETHOD(device_suspend, fxp_suspend),
- DEVMETHOD(device_resume, fxp_resume),
-
- { 0, 0 }
-};
-
-static driver_t fxp_driver = {
- "fxp",
- fxp_methods,
- sizeof(struct fxp_softc),
-};
-
-static devclass_t fxp_devclass;
-
-DRIVER_MODULE(if_fxp, pci, fxp_driver, fxp_devclass, 0, 0);
-DRIVER_MODULE(if_fxp, cardbus, fxp_driver, fxp_devclass, 0, 0);
-
/*
- * Do generic parts of attach.
+ * 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 int
-fxp_attach_common(sc, enaddr)
- struct fxp_softc *sc;
- u_int8_t *enaddr;
+static u_int16_t
+fxp_eeprom_getword(struct fxp_softc *sc, int offset, int autosize)
{
- u_int16_t data;
- int i, nmedia, defmedia;
- const int *media;
+ u_int16_t reg, data;
+ int x;
+ CSR_WRITE_2(sc, FXP_CSR_EEPROMCONTROL, FXP_EEPROM_EECS);
/*
- * Reset to a stable state.
+ * Shift in read opcode.
*/
- CSR_WRITE_4(sc, FXP_CSR_PORT, FXP_PORT_SELECTIVE_RESET);
- DELAY(10);
-
- sc->cbl_base = malloc(sizeof(struct fxp_cb_tx) * FXP_NTXCB,
- M_DEVBUF, M_NOWAIT | M_ZERO);
- if (sc->cbl_base == NULL)
- goto fail;
-
- sc->fxp_stats = malloc(sizeof(struct fxp_stats), M_DEVBUF,
- M_NOWAIT | M_ZERO);
- if (sc->fxp_stats == NULL)
- goto fail;
-
- sc->mcsp = malloc(sizeof(struct fxp_cb_mcs), M_DEVBUF, M_NOWAIT);
- if (sc->mcsp == NULL)
- goto fail;
-
+ for (x = 1 << 2; x; x >>= 1) {
+ if (FXP_EEPROM_OPC_READ & x)
+ reg = FXP_EEPROM_EECS | FXP_EEPROM_EEDI;
+ else
+ reg = FXP_EEPROM_EECS;
+ CSR_WRITE_2(sc, FXP_CSR_EEPROMCONTROL, reg);
+ DELAY(1);
+ CSR_WRITE_2(sc, FXP_CSR_EEPROMCONTROL, reg | FXP_EEPROM_EESK);
+ DELAY(1);
+ CSR_WRITE_2(sc, FXP_CSR_EEPROMCONTROL, reg);
+ DELAY(1);
+ }
/*
- * Pre-allocate our receive buffers.
+ * Shift in address.
*/
- for (i = 0; i < FXP_NRFABUFS; i++) {
- if (fxp_add_rfabuf(sc, NULL) != 0) {
- goto fail;
+ data = 0;
+ for (x = 1 << (sc->eeprom_size - 1); x; x >>= 1) {
+ if (offset & x)
+ reg = FXP_EEPROM_EECS | FXP_EEPROM_EEDI;
+ else
+ reg = FXP_EEPROM_EECS;
+ CSR_WRITE_2(sc, FXP_CSR_EEPROMCONTROL, reg);
+ DELAY(1);
+ CSR_WRITE_2(sc, FXP_CSR_EEPROMCONTROL, reg | FXP_EEPROM_EESK);
+ DELAY(1);
+ CSR_WRITE_2(sc, FXP_CSR_EEPROMCONTROL, reg);
+ DELAY(1);
+ reg = CSR_READ_2(sc, FXP_CSR_EEPROMCONTROL) & FXP_EEPROM_EEDO;
+ data++;
+ if (autosize && reg == 0) {
+ sc->eeprom_size = data;
+ break;
}
}
-
- /*
- * Find out how large of an SEEPROM we have.
- */
- fxp_autosize_eeprom(sc);
-
/*
- * Get info about the primary PHY
+ * Shift out data.
*/
- fxp_read_eeprom(sc, (u_int16_t *)&data, 6, 1);
- sc->phy_primary_addr = data & 0xff;
- sc->phy_primary_device = (data >> 8) & 0x3f;
- sc->phy_10Mbps_only = data >> 15;
-
- /*
- * Read MAC address.
- */
- fxp_read_eeprom(sc, (u_int16_t *)enaddr, 0, 3);
-
- /*
- * Initialize the media structures.
- */
-
- media = fxp_media_default;
- nmedia = sizeof(fxp_media_default) / sizeof(fxp_media_default[0]);
- defmedia = FXP_MEDIA_DEFAULT_DEFMEDIA;
-
- for (i = 0; i < NFXPMEDIA; i++) {
- if (sc->phy_primary_device == fxp_media[i].fsm_phy) {
- media = fxp_media[i].fsm_media;
- nmedia = fxp_media[i].fsm_nmedia;
- defmedia = fxp_media[i].fsm_defmedia;
- }
- }
-
- ifmedia_init(&sc->sc_media, 0, fxp_mediachange, fxp_mediastatus);
- for (i = 0; i < nmedia; i++) {
- if (IFM_SUBTYPE(media[i]) == IFM_100_TX && sc->phy_10Mbps_only)
- continue;
- ifmedia_add(&sc->sc_media, media[i], 0, NULL);
+ data = 0;
+ reg = FXP_EEPROM_EECS;
+ for (x = 1 << 15; x; x >>= 1) {
+ CSR_WRITE_2(sc, FXP_CSR_EEPROMCONTROL, reg | FXP_EEPROM_EESK);
+ DELAY(1);
+ if (CSR_READ_2(sc, FXP_CSR_EEPROMCONTROL) & FXP_EEPROM_EEDO)
+ data |= x;
+ CSR_WRITE_2(sc, FXP_CSR_EEPROMCONTROL, reg);
+ DELAY(1);
}
- ifmedia_set(&sc->sc_media, defmedia);
-
- return (0);
-
- fail:
- printf("fxp%d: Failed to malloc memory\n", FXP_UNIT(sc));
- if (sc->cbl_base)
- free(sc->cbl_base, M_DEVBUF);
- if (sc->fxp_stats)
- free(sc->fxp_stats, M_DEVBUF);
- if (sc->mcsp)
- free(sc->mcsp, M_DEVBUF);
- /* frees entire chain */
- if (sc->rfa_headm)
- m_freem(sc->rfa_headm);
+ CSR_WRITE_2(sc, FXP_CSR_EEPROMCONTROL, 0);
+ DELAY(1);
- return (ENOMEM);
+ return (data);
}
/*
@@ -746,136 +759,40 @@ fxp_attach_common(sc, enaddr)
* value of this checksum is not very well documented.
*/
static void
-fxp_autosize_eeprom(sc)
- struct fxp_softc *sc;
+fxp_autosize_eeprom(struct fxp_softc *sc)
{
- u_int16_t reg;
- int x;
- CSR_WRITE_2(sc, FXP_CSR_EEPROMCONTROL, FXP_EEPROM_EECS);
- /*
- * Shift in read opcode.
- */
- for (x = 3; x > 0; x--) {
- if (FXP_EEPROM_OPC_READ & (1 << (x - 1))) {
- reg = FXP_EEPROM_EECS | FXP_EEPROM_EEDI;
- } else {
- reg = FXP_EEPROM_EECS;
- }
- CSR_WRITE_2(sc, FXP_CSR_EEPROMCONTROL, reg);
- CSR_WRITE_2(sc, FXP_CSR_EEPROMCONTROL,
- reg | FXP_EEPROM_EESK);
- DELAY(1);
- CSR_WRITE_2(sc, FXP_CSR_EEPROMCONTROL, reg);
- DELAY(1);
- }
- /*
- * Shift in address.
- * Wait for the dummy zero following a correct address shift.
- */
- for (x = 1; x <= 8; x++) {
- CSR_WRITE_2(sc, FXP_CSR_EEPROMCONTROL, FXP_EEPROM_EECS);
- CSR_WRITE_2(sc, FXP_CSR_EEPROMCONTROL,
- FXP_EEPROM_EECS | FXP_EEPROM_EESK);
- DELAY(1);
- if ((CSR_READ_2(sc, FXP_CSR_EEPROMCONTROL) & FXP_EEPROM_EEDO) == 0)
- break;
- CSR_WRITE_2(sc, FXP_CSR_EEPROMCONTROL, FXP_EEPROM_EECS);
- DELAY(1);
- }
- CSR_WRITE_2(sc, FXP_CSR_EEPROMCONTROL, 0);
- DELAY(1);
- sc->eeprom_size = x;
+ /* guess maximum size of 256 words */
+ sc->eeprom_size = 8;
+
+ /* autosize */
+ (void) fxp_eeprom_getword(sc, 0, 1);
}
-/*
- * 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_read_eeprom(sc, data, offset, words)
- struct fxp_softc *sc;
- u_short *data;
- int offset;
- int words;
+fxp_read_eeprom(struct fxp_softc *sc, u_short *data, int offset, int words)
{
- u_int16_t reg;
- int i, x;
+ int i;
- for (i = 0; i < words; i++) {
- CSR_WRITE_2(sc, FXP_CSR_EEPROMCONTROL, FXP_EEPROM_EECS);
- /*
- * Shift in read opcode.
- */
- for (x = 3; x > 0; x--) {
- if (FXP_EEPROM_OPC_READ & (1 << (x - 1))) {
- reg = FXP_EEPROM_EECS | FXP_EEPROM_EEDI;
- } else {
- reg = FXP_EEPROM_EECS;
- }
- CSR_WRITE_2(sc, FXP_CSR_EEPROMCONTROL, reg);
- CSR_WRITE_2(sc, FXP_CSR_EEPROMCONTROL,
- reg | FXP_EEPROM_EESK);
- DELAY(1);
- CSR_WRITE_2(sc, FXP_CSR_EEPROMCONTROL, reg);
- DELAY(1);
- }
- /*
- * Shift in address.
- */
- for (x = sc->eeprom_size; x > 0; x--) {
- if ((i + offset) & (1 << (x - 1))) {
- reg = FXP_EEPROM_EECS | FXP_EEPROM_EEDI;
- } else {
- reg = FXP_EEPROM_EECS;
- }
- CSR_WRITE_2(sc, FXP_CSR_EEPROMCONTROL, reg);
- CSR_WRITE_2(sc, FXP_CSR_EEPROMCONTROL,
- reg | FXP_EEPROM_EESK);
- DELAY(1);
- CSR_WRITE_2(sc, FXP_CSR_EEPROMCONTROL, reg);
- DELAY(1);
- }
- reg = FXP_EEPROM_EECS;
- data[i] = 0;
- /*
- * Shift out data.
- */
- for (x = 16; x > 0; x--) {
- CSR_WRITE_2(sc, FXP_CSR_EEPROMCONTROL,
- reg | FXP_EEPROM_EESK);
- DELAY(1);
- if (CSR_READ_2(sc, FXP_CSR_EEPROMCONTROL) &
- FXP_EEPROM_EEDO)
- data[i] |= (1 << (x - 1));
- CSR_WRITE_2(sc, FXP_CSR_EEPROMCONTROL, reg);
- DELAY(1);
- }
- CSR_WRITE_2(sc, FXP_CSR_EEPROMCONTROL, 0);
- DELAY(1);
- }
+ for (i = 0; i < words; i++)
+ data[i] = fxp_eeprom_getword(sc, offset + i, 0);
}
/*
* Start packet transmission on the interface.
*/
static void
-fxp_start(ifp)
- struct ifnet *ifp;
+fxp_start(struct ifnet *ifp)
{
struct fxp_softc *sc = ifp->if_softc;
struct fxp_cb_tx *txp;
- FXP_LOCK(sc);
/*
* See if we need to suspend xmit until the multicast filter
* has been reprogrammed (which can only be done at the head
* of the command chain).
*/
if (sc->need_mcsetup) {
- FXP_UNLOCK(sc);
return;
}
@@ -1005,24 +922,20 @@ tbdinit:
fxp_scb_wait(sc);
CSR_WRITE_1(sc, FXP_CSR_SCB_COMMAND, FXP_SCB_COMMAND_CU_RESUME);
}
- FXP_UNLOCK(sc);
}
/*
* Process interface interrupts.
*/
static void
-fxp_intr(arg)
- void *arg;
+fxp_intr(void *xsc)
{
- struct fxp_softc *sc = arg;
+ struct fxp_softc *sc = xsc;
struct ifnet *ifp = &sc->sc_if;
u_int8_t statack;
- FXP_LOCK(sc);
if (sc->suspended) {
- FXP_UNLOCK(sc);
return;
}
@@ -1127,7 +1040,6 @@ rcvloop:
}
}
}
- FXP_UNLOCK(sc);
}
/*
@@ -1142,13 +1054,13 @@ rcvloop:
* them again next time.
*/
static void
-fxp_stats_update(arg)
- void *arg;
+fxp_tick(void *xsc)
{
- struct fxp_softc *sc = arg;
+ struct fxp_softc *sc = xsc;
struct ifnet *ifp = &sc->sc_if;
struct fxp_stats *sp = sc->fxp_stats;
struct fxp_cb_tx *txp;
+ int s;
ifp->if_opackets += sp->tx_good;
ifp->if_collisions += sp->tx_total_collisions;
@@ -1175,7 +1087,7 @@ fxp_stats_update(arg)
if (tx_threshold < 192)
tx_threshold += 64;
}
- FXP_LOCK(sc);
+ s = splimp();
/*
* Release any xmit buffers that have completed DMA. This isn't
* strictly necessary to do here, but it's advantagous for mbufs
@@ -1233,11 +1145,14 @@ fxp_stats_update(arg)
sp->rx_rnr_errors = 0;
sp->rx_overrun_errors = 0;
}
- FXP_UNLOCK(sc);
+
+ if (sc->miibus != NULL)
+ mii_tick(device_get_softc(sc->miibus));
+
/*
* Schedule another timeout one second from now.
*/
- sc->stat_ch = timeout(fxp_stats_update, sc, hz);
+ sc->stat_ch = timeout(fxp_tick, sc, hz);
}
/*
@@ -1245,14 +1160,12 @@ fxp_stats_update(arg)
* the interface.
*/
static void
-fxp_stop(sc)
- struct fxp_softc *sc;
+fxp_stop(struct fxp_softc *sc)
{
struct ifnet *ifp = &sc->sc_if;
struct fxp_cb_tx *txp;
int i;
- FXP_LOCK(sc);
ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
ifp->if_timer = 0;
@@ -1260,7 +1173,7 @@ fxp_stop(sc)
/*
* Cancel stats updater.
*/
- untimeout(fxp_stats_update, sc, sc->stat_ch);
+ untimeout(fxp_tick, sc, sc->stat_ch);
/*
* Issue software reset
@@ -1299,8 +1212,6 @@ fxp_stop(sc)
panic("fxp_stop: no buffers!");
}
}
-
- FXP_UNLOCK(sc);
}
/*
@@ -1310,29 +1221,27 @@ fxp_stop(sc)
* card has wedged for some reason.
*/
static void
-fxp_watchdog(ifp)
- struct ifnet *ifp;
+fxp_watchdog(struct ifnet *ifp)
{
struct fxp_softc *sc = ifp->if_softc;
- printf("fxp%d: device timeout\n", FXP_UNIT(sc));
+ device_printf(sc->dev, "device timeout\n");
ifp->if_oerrors++;
fxp_init(sc);
}
static void
-fxp_init(xsc)
- void *xsc;
+fxp_init(void *xsc)
{
struct fxp_softc *sc = xsc;
struct ifnet *ifp = &sc->sc_if;
struct fxp_cb_config *cbp;
struct fxp_cb_ias *cb_ias;
struct fxp_cb_tx *txp;
- int i, prm;
+ int i, prm, s;
- FXP_LOCK(sc);
+ s = splimp();
/*
* Cancel any pending I/O
*/
@@ -1380,16 +1289,32 @@ fxp_init(xsc)
cbp->rx_fifo_limit = 8; /* rx fifo threshold (32 bytes) */
cbp->tx_fifo_limit = 0; /* tx fifo threshold (0 bytes) */
cbp->adaptive_ifs = 0; /* (no) adaptive interframe spacing */
+ cbp->mwi_enable = sc->flags & FXP_FLAG_MWI_ENABLE ? 1 : 0;
+ cbp->type_enable = 0; /* actually reserved */
+ cbp->read_align_en = sc->flags & FXP_FLAG_READ_ALIGN ? 1 : 0;
+ cbp->end_wr_on_cl = sc->flags & FXP_FLAG_WRITE_ALIGN ? 1 : 0;
cbp->rx_dma_bytecount = 0; /* (no) rx DMA max */
cbp->tx_dma_bytecount = 0; /* (no) tx DMA max */
- cbp->dma_bce = 0; /* (disable) dma max counters */
+ cbp->dma_mbce = 0; /* (disable) dma max counters */
cbp->late_scb = 0; /* (don't) defer SCB update */
- cbp->tno_int = 0; /* (disable) tx not okay interrupt */
+ cbp->direct_dma_dis = 1; /* disable direct rcv dma mode */
+ cbp->tno_int_or_tco_en =0; /* (disable) tx not okay interrupt */
cbp->ci_int = 1; /* interrupt on CU idle */
+ cbp->ext_txcb_dis = sc->flags & FXP_FLAG_EXT_TXCB ? 0 : 1;
+ cbp->ext_stats_dis = 1; /* disable extended counters */
+ cbp->keep_overrun_rx = 0; /* don't pass overrun frames to host */
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 = !sc->phy_10Mbps_only; /* interface mode */
+ cbp->underrun_retry = 1; /* retry mode (once) on DMA underrun */
+ cbp->two_frames = 0; /* do not limit FIFO to 2 frames */
+ cbp->dyn_tbd = 0; /* (no) dynamic TBD mode */
+ cbp->mediatype = sc->flags & FXP_FLAG_SERIAL_MEDIA ? 0 : 1;
+ cbp->csma_dis = 0; /* (don't) disable link */
+ cbp->tcp_udp_cksum = 0; /* (don't) enable checksum */
+ cbp->vlan_tco = 0; /* (don't) enable vlan wakeup */
+ cbp->link_wake_en = 0; /* (don't) assert PME# on link change */
+ cbp->arp_wake_en = 0; /* (don't) assert PME# on arp */
+ cbp->mc_wake_en = 0; /* (don't) enable PME# on mcmatch */
cbp->nsai = 1; /* (don't) disable source addr insert */
cbp->preamble_length = 2; /* (7 byte) preamble */
cbp->loopback = 0; /* (don't) loopback */
@@ -1398,14 +1323,35 @@ fxp_init(xsc)
cbp->interfrm_spacing = 6; /* (96 bits of) interframe spacing */
cbp->promiscuous = prm; /* promiscuous mode */
cbp->bcast_disable = 0; /* (don't) disable broadcasts */
- cbp->crscdt = 0; /* (CRS only) */
+ cbp->wait_after_win = 0; /* (don't) enable modified backoff alg*/
+ cbp->ignore_ul = 0; /* consider U/L bit in IA matching */
+ cbp->crc16_en = 0; /* (don't) enable crc-16 algorithm */
+ cbp->crscdt = sc->flags & FXP_FLAG_SERIAL_MEDIA ? 1 : 0;
+
+ /*
+ * we may want to move all FC stuff to a separate section.
+ * the values here are 82557 compatible.
+ */
+ cbp->fc_delay_lsb = 0;
+ cbp->fc_delay_msb = 0x40;
+ cbp->pri_fc_thresh = 0x03;
+ cbp->tx_fc_dis = 0; /* (don't) disable transmit FC */
+ cbp->rx_fc_restop = 0; /* (don't) enable FC stop frame */
+ cbp->rx_fc_restart = 0; /* (don't) enable FC start frame */
+ cbp->fc_filter = 0; /* (do) pass FC frames to host */
+ cbp->pri_fc_loc = 1; /* location of priority in FC frame */
+
cbp->stripping = !prm; /* truncate rx packet to byte count */
cbp->padding = 1; /* (do) pad short tx packets */
cbp->rcv_crc_xfer = 0; /* (don't) xfer CRC to host */
+ cbp->long_rx_en = sc->flags & FXP_FLAG_LONG_PKT_EN ? 1 : 0;
+ cbp->ia_wake_en = 0; /* (don't) wake up on address match */
+ cbp->magic_pkt_dis = 0; /* (don't) disable magic packet */
+ /* must set wake_en in PMCSR also */
cbp->force_fdx = 0; /* (don't) force full duplex */
cbp->fdx_pin_en = 1; /* (enable) FDX# pin */
cbp->multi_ia = 0; /* (don't) accept multiple IAs */
- cbp->mc_all = sc->all_mcasts;/* accept all multicasts */
+ cbp->mc_all = sc->flags & FXP_FLAG_ALL_MCAST ? 1 : 0;
/*
* Start the config command/DMA.
@@ -1471,166 +1417,60 @@ fxp_init(xsc)
/*
* Set current media.
*/
- fxp_set_media(sc, sc->sc_media.ifm_cur->ifm_media);
+ if (sc->miibus != NULL)
+ mii_mediachg(device_get_softc(sc->miibus));
ifp->if_flags |= IFF_RUNNING;
ifp->if_flags &= ~IFF_OACTIVE;
- FXP_UNLOCK(sc);
+ splx(s);
/*
* Start stats updater.
*/
- sc->stat_ch = timeout(fxp_stats_update, sc, hz);
+ sc->stat_ch = timeout(fxp_tick, sc, hz);
+}
+
+static int
+fxp_serial_ifmedia_upd(struct ifnet *ifp)
+{
+
+ return (0);
}
static void
-fxp_set_media(sc, media)
- struct fxp_softc *sc;
- int media;
+fxp_serial_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
{
- switch (sc->phy_primary_device) {
- case FXP_PHY_DP83840:
- case FXP_PHY_DP83840A:
- fxp_mdi_write(sc, sc->phy_primary_addr, FXP_DP83840_PCR,
- fxp_mdi_read(sc, 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 */
- /* fall through */
- case FXP_PHY_82553A:
- case FXP_PHY_82553C: /* untested */
- case FXP_PHY_82555:
- case FXP_PHY_82555B:
- if (IFM_SUBTYPE(media) != IFM_AUTO) {
- int flags;
-
- flags = (IFM_SUBTYPE(media) == IFM_100_TX) ?
- FXP_PHY_BMCR_SPEED_100M : 0;
- flags |= (media & IFM_FDX) ?
- FXP_PHY_BMCR_FULLDUPLEX : 0;
- fxp_mdi_write(sc, sc->phy_primary_addr,
- FXP_PHY_BMCR,
- (fxp_mdi_read(sc, sc->phy_primary_addr,
- FXP_PHY_BMCR) &
- ~(FXP_PHY_BMCR_AUTOEN | FXP_PHY_BMCR_SPEED_100M |
- FXP_PHY_BMCR_FULLDUPLEX)) | flags);
- } else {
- fxp_mdi_write(sc, sc->phy_primary_addr,
- FXP_PHY_BMCR,
- (fxp_mdi_read(sc, sc->phy_primary_addr,
- FXP_PHY_BMCR) | FXP_PHY_BMCR_AUTOEN));
- }
- break;
- /*
- * The Seeq 80c24 doesn't have a PHY programming interface, so do
- * nothing.
- */
- case FXP_PHY_80C24:
- break;
- default:
- printf("fxp%d: warning: unsupported PHY, type = %d, addr = %d\n",
- FXP_UNIT(sc), sc->phy_primary_device,
- sc->phy_primary_addr);
- }
+ ifmr->ifm_active = IFM_ETHER|IFM_MANUAL;
}
/*
* Change media according to request.
*/
-int
-fxp_mediachange(ifp)
- struct ifnet *ifp;
+static int
+fxp_ifmedia_upd(struct ifnet *ifp)
{
struct fxp_softc *sc = ifp->if_softc;
- struct ifmedia *ifm = &sc->sc_media;
-
- if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER)
- return (EINVAL);
+ struct mii_data *mii;
- fxp_set_media(sc, ifm->ifm_media);
+ mii = device_get_softc(sc->miibus);
+ mii_mediachg(mii);
return (0);
}
/*
* Notify the world which media we're using.
*/
-void
-fxp_mediastatus(ifp, ifmr)
- struct ifnet *ifp;
- struct ifmediareq *ifmr;
+static void
+fxp_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
{
struct fxp_softc *sc = ifp->if_softc;
- int flags, stsflags;
-
- switch (sc->phy_primary_device) {
- case FXP_PHY_82555:
- case FXP_PHY_82555B:
- case FXP_PHY_DP83840:
- case FXP_PHY_DP83840A:
- ifmr->ifm_status = IFM_AVALID; /* IFM_ACTIVE will be valid */
- ifmr->ifm_active = IFM_ETHER;
- /*
- * the following is not an error.
- * You need to read this register twice to get current
- * status. This is correct documented behaviour, the
- * first read gets latched values.
- */
- stsflags = fxp_mdi_read(sc, sc->phy_primary_addr, FXP_PHY_STS);
- stsflags = fxp_mdi_read(sc, sc->phy_primary_addr, FXP_PHY_STS);
- if (stsflags & FXP_PHY_STS_LINK_STS)
- ifmr->ifm_status |= IFM_ACTIVE;
-
- /*
- * If we are in auto mode, then try report the result.
- */
- flags = fxp_mdi_read(sc, sc->phy_primary_addr, FXP_PHY_BMCR);
- if (flags & FXP_PHY_BMCR_AUTOEN) {
- ifmr->ifm_active |= IFM_AUTO; /* XXX presently 0 */
- if (stsflags & FXP_PHY_STS_AUTO_DONE) {
- /*
- * Intel and National parts report
- * differently on what they found.
- */
- if ((sc->phy_primary_device == FXP_PHY_82555)
- || (sc->phy_primary_device == FXP_PHY_82555B)) {
- flags = fxp_mdi_read(sc,
- sc->phy_primary_addr,
- FXP_PHY_USC);
-
- if (flags & FXP_PHY_USC_SPEED)
- ifmr->ifm_active |= IFM_100_TX;
- else
- ifmr->ifm_active |= IFM_10_T;
-
- if (flags & FXP_PHY_USC_DUPLEX)
- ifmr->ifm_active |= IFM_FDX;
- } else { /* it's National. only know speed */
- flags = fxp_mdi_read(sc,
- sc->phy_primary_addr,
- FXP_DP83840_PAR);
-
- if (flags & FXP_DP83840_PAR_SPEED_10)
- ifmr->ifm_active |= IFM_10_T;
- else
- ifmr->ifm_active |= IFM_100_TX;
- }
- }
- } else { /* in manual mode.. just report what we were set to */
- if (flags & FXP_PHY_BMCR_SPEED_100M)
- ifmr->ifm_active |= IFM_100_TX;
- else
- ifmr->ifm_active |= IFM_10_T;
-
- if (flags & FXP_PHY_BMCR_FULLDUPLEX)
- ifmr->ifm_active |= IFM_FDX;
- }
- break;
+ struct mii_data *mii;
- case FXP_PHY_80C24:
- default:
- ifmr->ifm_active = IFM_ETHER|IFM_MANUAL; /* XXX IFM_AUTO ? */
- }
+ mii = device_get_softc(sc->miibus);
+ mii_pollstat(mii);
+ ifmr->ifm_active = mii->mii_media_active;
+ ifmr->ifm_status = mii->mii_media_status;
}
/*
@@ -1642,9 +1482,7 @@ fxp_mediastatus(ifp, ifmr)
* data pointer is fixed up to point just past it.
*/
static int
-fxp_add_rfabuf(sc, oldm)
- struct fxp_softc *sc;
- struct mbuf *oldm;
+fxp_add_rfabuf(struct fxp_softc *sc, struct mbuf *oldm)
{
u_int32_t v;
struct mbuf *m;
@@ -1715,11 +1553,9 @@ fxp_add_rfabuf(sc, oldm)
}
static volatile int
-fxp_mdi_read(sc, phy, reg)
- struct fxp_softc *sc;
- int phy;
- int reg;
+fxp_miibus_readreg(device_t dev, int phy, int reg)
{
+ struct fxp_softc *sc = device_get_softc(dev);
int count = 10000;
int value;
@@ -1731,46 +1567,40 @@ fxp_mdi_read(sc, phy, reg)
DELAY(10);
if (count <= 0)
- printf("fxp%d: fxp_mdi_read: timed out\n", FXP_UNIT(sc));
+ device_printf(dev, "fxp_miibus_readreg: timed out\n");
return (value & 0xffff);
}
static void
-fxp_mdi_write(sc, phy, reg, value)
- struct fxp_softc *sc;
- int phy;
- int reg;
- int value;
+fxp_miibus_writereg(device_t dev, int phy, int reg, int value)
{
+ struct fxp_softc *sc = device_get_softc(dev);
int count = 10000;
CSR_WRITE_4(sc, FXP_CSR_MDICONTROL,
(FXP_MDI_WRITE << 26) | (reg << 16) | (phy << 21) |
(value & 0xffff));
- while((CSR_READ_4(sc, FXP_CSR_MDICONTROL) & 0x10000000) == 0 &&
+ while ((CSR_READ_4(sc, FXP_CSR_MDICONTROL) & 0x10000000) == 0 &&
count--)
DELAY(10);
if (count <= 0)
- printf("fxp%d: fxp_mdi_write: timed out\n", FXP_UNIT(sc));
+ device_printf(dev, "fxp_miibus_writereg: timed out\n");
}
static int
-fxp_ioctl(ifp, command, data)
- struct ifnet *ifp;
- u_long command;
- caddr_t data;
+fxp_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
{
struct fxp_softc *sc = ifp->if_softc;
struct ifreq *ifr = (struct ifreq *)data;
- int error = 0;
+ struct mii_data *mii;
+ int s, error = 0;
- FXP_LOCK(sc);
+ s = splimp();
switch (command) {
-
case SIOCSIFADDR:
case SIOCGIFADDR:
case SIOCSIFMTU:
@@ -1778,7 +1608,10 @@ fxp_ioctl(ifp, command, data)
break;
case SIOCSIFFLAGS:
- sc->all_mcasts = (ifp->if_flags & IFF_ALLMULTI) ? 1 : 0;
+ if (ifp->if_flags & IFF_ALLMULTI)
+ sc->flags |= FXP_FLAG_ALL_MCAST;
+ else
+ sc->flags &= ~FXP_FLAG_ALL_MCAST;
/*
* If interface is marked up and not running, then start it.
@@ -1796,31 +1629,40 @@ fxp_ioctl(ifp, command, data)
case SIOCADDMULTI:
case SIOCDELMULTI:
- sc->all_mcasts = (ifp->if_flags & IFF_ALLMULTI) ? 1 : 0;
+ if (ifp->if_flags & IFF_ALLMULTI)
+ sc->flags |= FXP_FLAG_ALL_MCAST;
+ else
+ sc->flags &= ~FXP_FLAG_ALL_MCAST;
/*
* Multicast list has changed; set the hardware filter
* accordingly.
*/
- if (!sc->all_mcasts)
+ if ((sc->flags & FXP_FLAG_ALL_MCAST) == 0)
fxp_mc_setup(sc);
/*
- * fxp_mc_setup() can turn on sc->all_mcasts, so check it
+ * fxp_mc_setup() can set FXP_FLAG_ALL_MCAST, so check it
* again rather than else {}.
*/
- if (sc->all_mcasts)
+ if (sc->flags & FXP_FLAG_ALL_MCAST)
fxp_init(sc);
error = 0;
break;
case SIOCSIFMEDIA:
case SIOCGIFMEDIA:
- error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, command);
+ if (sc->miibus != NULL) {
+ mii = device_get_softc(sc->miibus);
+ error = ifmedia_ioctl(ifp, ifr,
+ &mii->mii_media, command);
+ } else {
+ error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, command);
+ }
break;
default:
error = EINVAL;
}
- FXP_UNLOCK(sc);
+ splx(s);
return (error);
}
@@ -1839,8 +1681,7 @@ fxp_ioctl(ifp, command, data)
* This function must be called at splimp.
*/
static void
-fxp_mc_setup(sc)
- struct fxp_softc *sc;
+fxp_mc_setup(struct fxp_softc *sc)
{
struct fxp_cb_mcs *mcsp = sc->mcsp;
struct ifnet *ifp = &sc->sc_if;
@@ -1905,12 +1746,16 @@ fxp_mc_setup(sc)
mcsp->link_addr = vtophys(&sc->cbl_base->cb_status);
nmcasts = 0;
- if (!sc->all_mcasts) {
+ if ((sc->flags & FXP_FLAG_ALL_MCAST) == 0) {
+#if __FreeBSD_version < 500000
+ LIST_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
+#else
TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
+#endif
if (ifma->ifma_addr->sa_family != AF_LINK)
continue;
if (nmcasts >= MAXMCADDR) {
- sc->all_mcasts = 1;
+ sc->flags |= FXP_FLAG_ALL_MCAST;
nmcasts = 0;
break;
}
@@ -1933,7 +1778,7 @@ fxp_mc_setup(sc)
FXP_SCB_CUS_ACTIVE && --count)
DELAY(10);
if (count == 0) {
- printf("fxp%d: command queue timeout\n", FXP_UNIT(sc));
+ device_printf(sc->dev, "command queue timeout\n");
return;
}
diff --git a/sys/dev/fxp/if_fxpreg.h b/sys/dev/fxp/if_fxpreg.h
index 6cbcd40..3d32fb6 100644
--- a/sys/dev/fxp/if_fxpreg.h
+++ b/sys/dev/fxp/if_fxpreg.h
@@ -1,4 +1,5 @@
/*
+ * Copyright (c) 2001 Jonathan Lemon <jlemon@freebsd.org>
* Copyright (c) 1995, David Greenman
* All rights reserved.
*
@@ -28,10 +29,6 @@
*/
#define FXP_VENDORID_INTEL 0x8086
-#define FXP_DEVICEID_i82557 0x1229 /* 82557 - 82559 "classic" */
-#define FXP_DEVICEID_i82559 0x1030 /* New 82559 device id.. */
-#define FXP_DEVICEID_i82559ER 0x1209 /* 82559 for embedded applications */
-#define FXP_DEVICEID_i82562 0x2449 /* 82562 PLC devices */
#define FXP_PCI_MMBA 0x10
#define FXP_PCI_IOBA 0x14
@@ -125,48 +122,74 @@ struct fxp_cb_config {
tx_fifo_limit:3,
:1;
volatile u_int8_t adaptive_ifs;
- volatile u_int :8;
+ volatile u_int mwi_enable:1, /* 8,9 */
+ type_enable:1, /* 8,9 */
+ read_align_en:1, /* 8,9 */
+ end_wr_on_cl:1, /* 8,9 */
+ :4;
volatile u_int rx_dma_bytecount:7,
:1;
volatile u_int tx_dma_bytecount:7,
- dma_bce:1;
- volatile u_int late_scb:1,
- :1,
- tno_int:1,
+ dma_mbce:1;
+ volatile u_int late_scb:1, /* 7 */
+ direct_dma_dis:1, /* 8,9 */
+ tno_int_or_tco_en:1, /* 7,9 */
ci_int:1,
- :3,
+ ext_txcb_dis:1, /* 8,9 */
+ ext_stats_dis:1, /* 8,9 */
+ keep_overrun_rx:1,
save_bf:1;
volatile u_int disc_short_rx:1,
underrun_retry:2,
- :5;
- volatile u_int mediatype:1,
- :7;
- volatile u_int :8;
+ :3,
+ two_frames:1, /* 8,9 */
+ dyn_tbd:1; /* 8,9 */
+ volatile u_int mediatype:1, /* 7 */
+ :6,
+ csma_dis:1; /* 8,9 */
+ volatile u_int tcp_udp_cksum:1, /* 9 */
+ :3,
+ vlan_tco:1, /* 8,9 */
+ link_wake_en:1, /* 8,9 */
+ arp_wake_en:1, /* 8 */
+ mc_wake_en:1; /* 8 */
volatile u_int :3,
nsai:1,
preamble_length:2,
loopback:2;
- volatile u_int linear_priority:3,
+ volatile u_int linear_priority:3, /* 7 */
:5;
- volatile u_int linear_pri_mode:1,
+ volatile u_int linear_pri_mode:1, /* 7 */
:3,
interfrm_spacing:4;
volatile u_int :8;
volatile u_int :8;
volatile u_int promiscuous:1,
bcast_disable:1,
- :5,
+ wait_after_win:1, /* 8,9 */
+ :1,
+ ignore_ul:1, /* 8,9 */
+ crc16_en:1, /* 9 */
+ :1,
crscdt:1;
- volatile u_int :8;
- volatile u_int :8;
+ volatile u_int fc_delay_lsb:8; /* 8,9 */
+ volatile u_int fc_delay_msb:8; /* 8,9 */
volatile u_int stripping:1,
padding:1,
rcv_crc_xfer:1,
- :5;
- volatile u_int :6,
+ long_rx_en:1, /* 8,9 */
+ pri_fc_thresh:3, /* 8,9 */
+ :1;
+ volatile u_int ia_wake_en:1, /* 8 */
+ magic_pkt_dis:1, /* 8,9,!9ER */
+ tx_fc_dis:1, /* 8,9 */
+ rx_fc_restop:1, /* 8,9 */
+ rx_fc_restart:1, /* 8,9 */
+ fc_filter:1, /* 8,9 */
force_fdx:1,
fdx_pin_en:1;
- volatile u_int :6,
+ volatile u_int :5,
+ pri_fc_loc:1, /* 8,9 */
multi_ia:1,
:1;
volatile u_int :3,
@@ -296,14 +319,10 @@ struct fxp_stats {
/*
* Serial EEPROM control register bits
*/
-/* shift clock */
-#define FXP_EEPROM_EESK 0x01
-/* chip select */
-#define FXP_EEPROM_EECS 0x02
-/* data in */
-#define FXP_EEPROM_EEDI 0x04
-/* data out */
-#define FXP_EEPROM_EEDO 0x08
+#define FXP_EEPROM_EESK 0x01 /* shift clock */
+#define FXP_EEPROM_EECS 0x02 /* chip select */
+#define FXP_EEPROM_EEDI 0x04 /* data in */
+#define FXP_EEPROM_EEDO 0x08 /* data out */
/*
* Serial EEPROM opcodes, including start bit
@@ -321,6 +340,8 @@ struct fxp_stats {
/*
* PHY device types
*/
+#define FXP_PHY_DEVICE_MASK 0x03f0
+#define FXP_PHY_SERIAL_ONLY 0x8000
#define FXP_PHY_NONE 0
#define FXP_PHY_82553A 1
#define FXP_PHY_82553C 2
@@ -331,95 +352,3 @@ struct fxp_stats {
#define FXP_PHY_82555 7
#define FXP_PHY_DP83840A 10
#define FXP_PHY_82555B 11
-
-/*
- * PHY BMCR Basic Mode Control Register
- * Should probably be in i82555.h or dp83840.h (Intel/National names).
- * (Called "Management Data Interface Control Reg" in some Intel data books).
- * (*) indicates bit ignored in auto negotiation mode.
- */
-#define FXP_PHY_BMCR 0x0
-#define FXP_PHY_BMCR_COLTEST 0x0080 /* not on Intel parts */
-#define FXP_PHY_BMCR_FULLDUPLEX 0x0100 /* 1 = Fullduplex (*) */
-#define FXP_PHY_BMCR_RESTART_NEG 0x0200 /* ==> 1 to restart autoneg */
-#define FXP_PHY_BMCR_ISOLATE 0x0400 /* not on Intel parts */
-#define FXP_PHY_BMCR_POWERDOWN 0x0800 /* 1 = low power mode */
-#define FXP_PHY_BMCR_AUTOEN 0x1000 /* 1 = for auto mode */
-#define FXP_PHY_BMCR_SPEED_100M 0x2000 /* 1 = for 100Mb/sec (*) */
-#define FXP_PHY_BMCR_LOOPBACK 0x4000 /* 1 = loopback at the PHY */
-#define FXP_PHY_BMCR_RESET 0x8000 /* ==> 1 sets to defaults */
-
-/*
- * Basic Mode Status Register (National name)
- * Management Data Interface Status reg. (Intel name)
- * in both Intel and National parts.
- */
-#define FXP_PHY_STS 0x1
-#define FXP_PHY_STS_EXND 0x0001 /* Extended regs enabled */
-#define FXP_PHY_STS_JABR 0x0002 /* Jabber detected */
-#define FXP_PHY_STS_LINK_STS 0x0004 /* Link valid */
-#define FXP_PHY_STS_CAN_AUTO 0x0008 /* Auto detection available */
-#define FXP_PHY_STS_REMT_FAULT 0x0010 /* remote fault detected */
-#define FXP_PHY_STS_AUTO_DONE 0x0020 /* auto negotiation completed */
-#define FXP_PHY_STS_MGMT_PREAMBLE 0x0040 /* real complicated */
-#define FXP_PHY_STS_10HDX_OK 0x0800 /* can do 10Mb HDX */
-#define FXP_PHY_STS_10FDX_OK 0x1000 /* can do 10Mb FDX */
-#define FXP_PHY_STS_100HDX_OK 0x2000 /* can do 100Mb HDX */
-#define FXP_PHY_STS_100FDX_OK 0x4000 /* can do 100Mb FDX */
-#define FXP_PHY_STS_100T4_OK 0x8000 /* can do 100bT4 -not Intel */
-
-/*
- * More Phy regs
- */
-#define FXP_PHY_ID1 0x2
-#define FXP_PHY_ID2 0x3
-
-/*
- * MDI Auto negotiation advertisement register.
- * What we advertise we can do..
- * The same bits are used to indicate the response too.
- */
-#define FXP_PHY_ADVRT 0x4
-#define FXP_PHY_RMT_ADVRT 0x5 /* what the other end said */
-#define FXP_PHY_ADVRT_SELECT 0x001F /* real complicated */
-#define FXP_PHY_ADVRT_TECH_AVAIL 0x1FE0 /* can do 10Mb HDX */
-#define FXP_PHY_ADVRT_RMT_FAULT 0x2000 /* can do 10Mb FDX */
-#define FXP_PHY_ADVRT_ACK 0x4000 /* Acked */
-#define FXP_PHY_ADVRT_NXT_PAGE 0x8000 /* can do 100Mb FDX */
-
-/*
- * Phy Unit Status and Control Register (another one)
- * This is not in the National part!
- */
-#define FXP_PHY_USC 0x10
-#define FXP_PHY_USC_DUPLEX 0x0001 /* in FDX mode */
-#define FXP_PHY_USC_SPEED 0x0002 /* 1 = in 100Mb mode */
-#define FXP_PHY_USC_POLARITY 0x0100 /* 1 = reverse polarity */
-#define FXP_PHY_USC_10_PWRDOWN 0x0200 /* 10Mb PHY powered down */
-#define FXP_PHY_USC_100_PWRDOWN 0x0400 /* 100Mb PHY powered down */
-#define FXP_PHY_USC_INSYNC 0x0800 /* 100Mb PHY is in sync */
-#define FXP_PHY_USC_TX_FLOWCNTRL 0x1000 /* TX FC mode in use */
-#define FXP_PHY_USC_PHY_FLOWCNTRL 0x8000 /* PHY FC mode in use */
-
-
-/*
- * DP83830 PHY, PCS Configuration Register
- * NOT compatible with Intel parts,
- * (where it is the 100BTX premature eof counter).
- */
-#define FXP_DP83840_PCR 0x17
-#define FXP_DP83840_PCR_LED4_MODE 0x0002 /* 1 = LED4 always = FDX */
-#define FXP_DP83840_PCR_F_CONNECT 0x0020 /* 1 = link disconnect bypass */
-#define FXP_DP83840_PCR_BIT8 0x0100
-#define FXP_DP83840_PCR_BIT10 0x0400
-
-/*
- * DP83830 PHY, Address/status Register
- * NOT compatible with Intel parts,
- * (where it is the 10BT jabber detect counter).
- */
-#define FXP_DP83840_PAR 0x19
-#define FXP_DP83840_PAR_PHYADDR 0x1F
-#define FXP_DP83840_PAR_CON_STATUS 0x20
-#define FXP_DP83840_PAR_SPEED_10 0x40 /* 1 == running at 10 Mb/Sec */
-
diff --git a/sys/dev/fxp/if_fxpvar.h b/sys/dev/fxp/if_fxpvar.h
index 7a9eb8d..244c447 100644
--- a/sys/dev/fxp/if_fxpvar.h
+++ b/sys/dev/fxp/if_fxpvar.h
@@ -31,6 +31,58 @@
* Misc. defintions for the Intel EtherExpress Pro/100B PCI Fast
* Ethernet driver
*/
+
+/*
+ * Number of transmit control blocks. This determines the number
+ * of transmit buffers that can be chained in the CB list.
+ * This must be a power of two.
+ */
+#define FXP_NTXCB 128
+
+/*
+ * Number of completed TX commands at which point an interrupt
+ * will be generated to garbage collect the attached buffers.
+ * Must be at least one less than FXP_NTXCB, and should be
+ * enough less so that the transmitter doesn't becomes idle
+ * during the buffer rundown (which would reduce performance).
+ */
+#define FXP_CXINT_THRESH 120
+
+/*
+ * TxCB list index mask. This is used to do list wrap-around.
+ */
+#define FXP_TXCB_MASK (FXP_NTXCB - 1)
+
+/*
+ * Number of receive frame area buffers. These are large so chose
+ * wisely.
+ */
+#define FXP_NRFABUFS 64
+
+/*
+ * Maximum number of seconds that the receiver can be idle before we
+ * assume it's dead and attempt to reset it by reprogramming the
+ * multicast filter. This is part of a work-around for a bug in the
+ * NIC. See fxp_stats_update().
+ */
+#define FXP_MAX_RX_IDLE 15
+
+#if __FreeBSD_version < 500000
+#define FXP_LOCK(_sc)
+#define FXP_UNLOCK(_sc)
+#define mtx_init(a, b, c)
+#define mtx_destroy(a)
+struct mtx { int dummy; };
+#else
+#define FXP_LOCK(_sc) mtx_lock(&(_sc)->sc_mtx)
+#define FXP_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_mtx)
+#endif
+
+#ifdef __alpha__
+#undef vtophys
+#define vtophys(va) alpha_XXX_dmamap((vm_offset_t)(va))
+#endif /* __alpha__ */
+
/*
* NOTE: Elements are ordered for optimal cacheline behavior, and NOT
* for functional grouping.
@@ -56,13 +108,12 @@ struct fxp_softc {
struct callout_handle stat_ch; /* Handle for canceling our stat timeout */
struct fxp_cb_tx *cbl_base; /* base of TxCB list */
struct fxp_cb_mcs *mcsp; /* Pointer to mcast setup descriptor */
- int all_mcasts; /* receive all multicasts */
struct ifmedia sc_media; /* media information */
- 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 */
+ device_t miibus;
+ device_t dev;
int eeprom_size; /* size of serial EEPROM */
int suspended; /* 0 = normal 1 = suspended (APM) */
+ int flags;
u_int32_t saved_maps[5]; /* pci data */
u_int32_t saved_biosaddr;
u_int8_t saved_intline;
@@ -70,6 +121,14 @@ struct fxp_softc {
u_int8_t saved_lattimer;
};
+#define FXP_FLAG_MWI_ENABLE 0x0001 /* MWI enable */
+#define FXP_FLAG_READ_ALIGN 0x0002 /* align read access with cacheline */
+#define FXP_FLAG_WRITE_ALIGN 0x0004 /* end write on cacheline */
+#define FXP_FLAG_EXT_TXCB 0x0008 /* enable use of extended TXCB */
+#define FXP_FLAG_SERIAL_MEDIA 0x0010 /* 10Mbps serial interface */
+#define FXP_FLAG_LONG_PKT_EN 0x0020 /* enable long packet reception */
+#define FXP_FLAG_ALL_MCAST 0x0040 /* accept all multicast frames */
+
/* Macros to ease CSR access. */
#define CSR_READ_1(sc, reg) \
bus_space_read_1((sc)->sc_st, (sc)->sc_sh, (reg))
@@ -85,6 +144,5 @@ struct fxp_softc {
bus_space_write_4((sc)->sc_st, (sc)->sc_sh, (reg), (val))
#define sc_if arpcom.ac_if
+
#define FXP_UNIT(_sc) (_sc)->arpcom.ac_if.if_unit
-#define FXP_LOCK(_sc) mtx_lock(&(_sc)->sc_mtx)
-#define FXP_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_mtx)
OpenPOWER on IntegriCloud