summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/amd64/conf/GENERIC1
-rw-r--r--sys/dev/ed/if_ed.c144
-rw-r--r--sys/dev/ed/if_ed_pccard.c94
-rw-r--r--sys/dev/ed/if_ed_pci.c1
-rw-r--r--sys/dev/ed/if_edreg.h29
-rw-r--r--sys/dev/ed/if_edvar.h9
-rw-r--r--sys/i386/conf/GENERIC1
-rw-r--r--sys/i386/conf/NEWCARD27
-rw-r--r--sys/modules/ed/Makefile2
9 files changed, 298 insertions, 10 deletions
diff --git a/sys/amd64/conf/GENERIC b/sys/amd64/conf/GENERIC
index f6eb26b..f02e405 100644
--- a/sys/amd64/conf/GENERIC
+++ b/sys/amd64/conf/GENERIC
@@ -182,6 +182,7 @@ device xl # 3Com 3c90x (``Boomerang'', ``Cyclone'')
# ISA Ethernet NICs. pccard nics included.
device cs # Crystal Semiconductor CS89x0 NIC
+# 'device ed' requires 'device miibus'
device ed # NE[12]000, SMC Ultra, 3c503, DS8390 cards
device ex # Intel EtherExpress Pro/10 and Pro/10+
device ep # Etherlink III based cards
diff --git a/sys/dev/ed/if_ed.c b/sys/dev/ed/if_ed.c
index 604c287..11843d7 100644
--- a/sys/dev/ed/if_ed.c
+++ b/sys/dev/ed/if_ed.c
@@ -41,6 +41,7 @@
#include <sys/systm.h>
#include <sys/sockio.h>
#include <sys/mbuf.h>
+#include <sys/kernel.h>
#include <sys/socket.h>
#include <sys/syslog.h>
@@ -55,6 +56,10 @@
#include <net/if_arp.h>
#include <net/if_dl.h>
#include <net/if_mib.h>
+#include <net/if_media.h>
+
+#include <dev/mii/mii.h>
+#include <dev/mii/miivar.h>
#include <net/bpf.h>
#include "opt_bdg.h"
@@ -74,6 +79,7 @@ static int ed_ioctl __P((struct ifnet *, u_long, caddr_t));
static void ed_start __P((struct ifnet *));
static void ed_reset __P((struct ifnet *));
static void ed_watchdog __P((struct ifnet *));
+static void ed_tick __P((void *));
static void ds_getmcaf __P((struct ed_softc *, u_int32_t *));
@@ -1586,6 +1592,7 @@ ed_attach(sc, unit, flags)
{
struct ifnet *ifp = &sc->arpcom.ac_if;
+ callout_handle_init(&sc->tick_ch);
/*
* Set interface to stopped condition (reset)
*/
@@ -1695,6 +1702,8 @@ ed_stop(sc)
{
int n = 5000;
+ untimeout(ed_tick, sc, sc->tick_ch);
+ callout_handle_init(&sc->tick_ch);
if (sc->gone)
return;
/*
@@ -1729,6 +1738,27 @@ ed_watchdog(ifp)
ed_reset(ifp);
}
+static void
+ed_tick(arg)
+ void *arg;
+{
+ struct ed_softc *sc = arg;
+ struct mii_data *mii;
+ int s;
+
+ if (sc->gone) {
+ callout_handle_init(&sc->tick_ch);
+ return;
+ }
+ s = splimp();
+ if (sc->miibus != NULL) {
+ mii = device_get_softc(sc->miibus);
+ mii_tick(mii);
+ }
+ sc->tick_ch = timeout(ed_tick, sc, hz);
+ splx(s);
+}
+
/*
* Initialize device.
*/
@@ -1870,6 +1900,11 @@ ed_init(xsc)
}
}
+ if (sc->miibus != NULL) {
+ struct mii_data *mii;
+ mii = device_get_softc(sc->miibus);
+ mii_mediachg(mii);
+ }
/*
* Set 'running' flag, and clear output active flag.
*/
@@ -1881,6 +1916,8 @@ ed_init(xsc)
*/
ed_start(ifp);
+ untimeout(ed_tick, sc, sc->tick_ch);
+ sc->tick_ch = timeout(ed_tick, sc, hz);
(void) splx(s);
}
@@ -2492,6 +2529,8 @@ ed_ioctl(ifp, command, data)
caddr_t data;
{
struct ed_softc *sc = ifp->if_softc;
+ struct ifreq *ifr = (struct ifreq *)data;
+ struct mii_data *mii;
int s, error = 0;
if (sc == NULL || sc->gone) {
@@ -2554,6 +2593,16 @@ ed_ioctl(ifp, command, data)
error = 0;
break;
+ case SIOCGIFMEDIA:
+ case SIOCSIFMEDIA:
+ if (sc->miibus == NULL) {
+ error = EINVAL;
+ break;
+ }
+ mii = device_get_softc(sc->miibus);
+ error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, command);
+ break;
+
default:
error = EINVAL;
}
@@ -3173,6 +3222,101 @@ ed_hpp_write_mbufs(struct ed_softc *sc, struct mbuf *m, int dst)
return (total_len);
}
+/*
+ * MII bus support routines.
+ */
+int
+ed_miibus_readreg(dev, phy, reg)
+ device_t dev;
+ int phy, reg;
+{
+ struct ed_softc *sc;
+ int val;
+ int failed;
+
+ sc = device_get_softc(dev);
+ if (sc->gone)
+ return 0;
+
+ (*sc->mii_writebits)(sc, 0xffffffff, 32);
+ (*sc->mii_writebits)(sc, ED_MII_STARTDELIM, ED_MII_STARTDELIM_BITS);
+ (*sc->mii_writebits)(sc, ED_MII_READOP, ED_MII_OP_BITS);
+ (*sc->mii_writebits)(sc, phy, ED_MII_PHY_BITS);
+ (*sc->mii_writebits)(sc, reg, ED_MII_REG_BITS);
+
+ failed = (*sc->mii_readbits)(sc, ED_MII_ACK_BITS);
+ val = (*sc->mii_readbits)(sc, ED_MII_DATA_BITS);
+ (*sc->mii_writebits)(sc, ED_MII_IDLE, ED_MII_IDLE_BITS);
+
+ return (failed ? 0 : val);
+}
+
+void
+ed_miibus_writereg(dev, phy, reg, data)
+ device_t dev;
+ int phy, reg, data;
+{
+ struct ed_softc *sc;
+
+ sc = device_get_softc(dev);
+ if (sc->gone)
+ return;
+
+ (*sc->mii_writebits)(sc, 0xffffffff, 32);
+ (*sc->mii_writebits)(sc, ED_MII_STARTDELIM, ED_MII_STARTDELIM_BITS);
+ (*sc->mii_writebits)(sc, ED_MII_WRITEOP, ED_MII_OP_BITS);
+ (*sc->mii_writebits)(sc, phy, ED_MII_PHY_BITS);
+ (*sc->mii_writebits)(sc, reg, ED_MII_REG_BITS);
+ (*sc->mii_writebits)(sc, ED_MII_TURNAROUND, ED_MII_TURNAROUND_BITS);
+ (*sc->mii_writebits)(sc, data, ED_MII_DATA_BITS);
+ (*sc->mii_writebits)(sc, ED_MII_IDLE, ED_MII_IDLE_BITS);
+}
+
+int
+ed_ifmedia_upd(ifp)
+ struct ifnet *ifp;
+{
+ struct ed_softc *sc;
+ struct mii_data *mii;
+
+ sc = ifp->if_softc;
+ if (sc->gone || sc->miibus == NULL)
+ return (ENXIO);
+
+ mii = device_get_softc(sc->miibus);
+ return mii_mediachg(mii);
+}
+
+void
+ed_ifmedia_sts(ifp, ifmr)
+ struct ifnet *ifp;
+ struct ifmediareq *ifmr;
+{
+ struct ed_softc *sc;
+ struct mii_data *mii;
+
+ sc = ifp->if_softc;
+ if (sc->gone || sc->miibus == NULL)
+ return;
+
+ mii = device_get_softc(sc->miibus);
+ mii_pollstat(mii);
+ ifmr->ifm_active = mii->mii_media_active;
+ ifmr->ifm_status = mii->mii_media_status;
+}
+
+void
+ed_child_detached(dev, child)
+ device_t dev;
+ device_t child;
+{
+ struct ed_softc *sc;
+
+ sc = device_get_softc(dev);
+ if (child == sc->miibus)
+ sc->miibus = NULL;
+}
+
static void
ed_setrcr(sc)
struct ed_softc *sc;
diff --git a/sys/dev/ed/if_ed_pccard.c b/sys/dev/ed/if_ed_pccard.c
index d579d16..23ef71d 100644
--- a/sys/dev/ed/if_ed_pccard.c
+++ b/sys/dev/ed/if_ed_pccard.c
@@ -44,13 +44,20 @@
#include <net/if.h>
#include <net/if_arp.h>
#include <net/if_mib.h>
+#include <net/if_media.h>
#include <dev/ed/if_edreg.h>
#include <dev/ed/if_edvar.h>
#include <dev/pccard/pccardvar.h>
#include <dev/pccard/pccarddevs.h>
+#include <dev/mii/mii.h>
+#include <dev/mii/miivar.h>
#include "card_if.h"
+/* "device miibus" required. See GENERIC if you get errors here. */
+#include "miibus_if.h"
+
+MODULE_DEPEND(ed, miibus, 1, 1, 1);
/*
* PC-Card (PCMCIA) specific code.
@@ -65,6 +72,10 @@ static int ed_pccard_ax88190(device_t dev);
static void ax88190_geteprom(struct ed_softc *);
static int ed_pccard_memwrite(device_t dev, off_t offset, u_char byte);
+static void ed_pccard_dlink_mii_reset(struct ed_softc *sc);
+static u_int ed_pccard_dlink_mii_readbits(struct ed_softc *sc, int nbits);
+static void ed_pccard_dlink_mii_writebits(struct ed_softc *sc, u_int val,
+ int nbits);
static int linksys;
/*
@@ -659,6 +670,13 @@ ed_pccard_Linksys(device_t dev)
sc->isa16bit = 1;
sc->type = ED_TYPE_NE2000;
sc->type_str = "Linksys";
+
+ /* Probe for an MII bus, but continue as normal if there isn't one. */
+ ed_pccard_dlink_mii_reset(sc);
+ sc->mii_readbits = ed_pccard_dlink_mii_readbits;
+ sc->mii_writebits = ed_pccard_dlink_mii_writebits;
+ mii_phy_probe(dev, &sc->miibus, ed_ifmedia_upd, ed_ifmedia_sts);
+
return (1);
}
@@ -694,12 +712,87 @@ ed_pccard_ax88190(device_t dev)
return (error);
}
+/* MII bit-twiddling routines for cards using Dlink chipset */
+#define DLINK_MIISET(sc, x) ed_asic_outb(sc, ED_DLINK_MIIBUS, \
+ ed_asic_inb(sc, ED_DLINK_MIIBUS) | (x))
+#define DLINK_MIICLR(sc, x) ed_asic_outb(sc, ED_DLINK_MIIBUS, \
+ ed_asic_inb(sc, ED_DLINK_MIIBUS) & ~(x))
+
+static void
+ed_pccard_dlink_mii_reset(sc)
+ struct ed_softc *sc;
+{
+ ed_asic_outb(sc, ED_DLINK_MIIBUS, 0);
+ DELAY(10);
+ DLINK_MIISET(sc, ED_DLINK_MII_RESET2);
+ DELAY(10);
+ DLINK_MIISET(sc, ED_DLINK_MII_RESET1);
+ DELAY(10);
+ DLINK_MIICLR(sc, ED_DLINK_MII_RESET1);
+ DELAY(10);
+ DLINK_MIICLR(sc, ED_DLINK_MII_RESET2);
+ DELAY(10);
+}
+
+static void
+ed_pccard_dlink_mii_writebits(sc, val, nbits)
+ struct ed_softc *sc;
+ u_int val;
+ int nbits;
+{
+ int i;
+
+ DLINK_MIISET(sc, ED_DLINK_MII_DIROUT);
+
+ for (i = nbits - 1; i >= 0; i--) {
+ if ((val >> i) & 1)
+ DLINK_MIISET(sc, ED_DLINK_MII_DATAOUT);
+ else
+ DLINK_MIICLR(sc, ED_DLINK_MII_DATAOUT);
+ DELAY(10);
+ DLINK_MIISET(sc, ED_DLINK_MII_CLK);
+ DELAY(10);
+ DLINK_MIICLR(sc, ED_DLINK_MII_CLK);
+ DELAY(10);
+ }
+}
+
+static u_int
+ed_pccard_dlink_mii_readbits(sc, nbits)
+ struct ed_softc *sc;
+ int nbits;
+{
+ int i;
+ u_int val = 0;
+
+ DLINK_MIICLR(sc, ED_DLINK_MII_DIROUT);
+
+ for (i = nbits - 1; i >= 0; i--) {
+ DLINK_MIISET(sc, ED_DLINK_MII_CLK);
+ DELAY(10);
+ val <<= 1;
+ if (ed_asic_inb(sc, ED_DLINK_MIIBUS) & ED_DLINK_MII_DATATIN)
+ val++;
+ DLINK_MIICLR(sc, ED_DLINK_MII_CLK);
+ DELAY(10);
+ }
+
+ return val;
+}
+
static device_method_t ed_pccard_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, pccard_compat_probe),
DEVMETHOD(device_attach, pccard_compat_attach),
DEVMETHOD(device_detach, ed_pccard_detach),
+ /* Bus interface */
+ DEVMETHOD(bus_child_detached, ed_child_detached),
+
+ /* MII interface */
+ DEVMETHOD(miibus_readreg, ed_miibus_readreg),
+ DEVMETHOD(miibus_writereg, ed_miibus_writereg),
+
/* Card interface */
DEVMETHOD(card_compat_match, ed_pccard_match),
DEVMETHOD(card_compat_probe, ed_pccard_probe),
@@ -714,3 +807,4 @@ static driver_t ed_pccard_driver = {
};
DRIVER_MODULE(if_ed, pccard, ed_pccard_driver, ed_devclass, 0, 0);
+DRIVER_MODULE(miibus, ed, miibus_driver, miibus_devclass, 0, 0);
diff --git a/sys/dev/ed/if_ed_pci.c b/sys/dev/ed/if_ed_pci.c
index 08d1e80..144ba82 100644
--- a/sys/dev/ed/if_ed_pci.c
+++ b/sys/dev/ed/if_ed_pci.c
@@ -21,6 +21,7 @@
*/
#include <sys/param.h>
+#include <sys/systm.h>
#include <sys/socket.h>
#include <sys/kernel.h>
diff --git a/sys/dev/ed/if_edreg.h b/sys/dev/ed/if_edreg.h
index e42ef42d2..a2e1882 100644
--- a/sys/dev/ed/if_edreg.h
+++ b/sys/dev/ed/if_edreg.h
@@ -1113,3 +1113,32 @@ struct ed_ring {
#define ED_AX88190_IOBASE0 0x3ca
#define ED_AX88190_IOBASE1 0x3cc
+
+/*
+ * MII bus definitions.
+ */
+#define ED_MII_STARTDELIM 0x01
+#define ED_MII_WRITEOP 0x01
+#define ED_MII_READOP 0x02
+#define ED_MII_TURNAROUND 0x02
+#define ED_MII_IDLE 0x01
+
+#define ED_MII_STARTDELIM_BITS 2
+#define ED_MII_OP_BITS 2
+#define ED_MII_PHY_BITS 5
+#define ED_MII_REG_BITS 5
+#define ED_MII_TURNAROUND_BITS 2
+#define ED_MII_DATA_BITS 16
+#define ED_MII_ACK_BITS 1
+#define ED_MII_IDLE_BITS 1
+
+/* Dlink chipset used on some Netgear and Dlink PCMCIA cards */
+#define ED_DLINK_MIIBUS 0x0c /* MII bus register on ASIC */
+
+#define ED_DLINK_MII_RESET1 0x04
+#define ED_DLINK_MII_RESET2 0x08
+
+#define ED_DLINK_MII_DATATIN 0x10
+#define ED_DLINK_MII_DIROUT 0x20
+#define ED_DLINK_MII_DATAOUT 0x40
+#define ED_DLINK_MII_CLK 0x80
diff --git a/sys/dev/ed/if_edvar.h b/sys/dev/ed/if_edvar.h
index d4e896f..8c58b64 100644
--- a/sys/dev/ed/if_edvar.h
+++ b/sys/dev/ed/if_edvar.h
@@ -49,6 +49,10 @@ struct ed_softc {
int irq_rid; /* resource id for irq */
struct resource* irq_res; /* resource for irq */
void* irq_handle; /* handle for irq handler */
+ device_t miibus; /* MII bus for cards with MII. */
+ void (*mii_writebits)__P((struct ed_softc *, u_int, int));
+ u_int (*mii_readbits)__P((struct ed_softc *, int));
+ struct callout_handle tick_ch; /* Callout handle for ed_tick */
int nic_offset; /* NIC (DS8390) I/O bus address offset */
int asic_offset; /* ASIC I/O bus address offset */
@@ -205,6 +209,11 @@ void ed_pio_readmem __P((struct ed_softc *, int, unsigned char *,
unsigned short));
void ed_pio_writemem __P((struct ed_softc *, char *,
unsigned short, unsigned short));
+int ed_miibus_readreg __P((device_t, int, int));
+void ed_miibus_writereg __P((device_t, int, int, int));
+int ed_ifmedia_upd __P((struct ifnet *));
+void ed_ifmedia_sts __P((struct ifnet *, struct ifmediareq *));
+void ed_child_detached __P((device_t, device_t));
driver_intr_t edintr;
diff --git a/sys/i386/conf/GENERIC b/sys/i386/conf/GENERIC
index f6eb26b..f02e405 100644
--- a/sys/i386/conf/GENERIC
+++ b/sys/i386/conf/GENERIC
@@ -182,6 +182,7 @@ device xl # 3Com 3c90x (``Boomerang'', ``Cyclone'')
# ISA Ethernet NICs. pccard nics included.
device cs # Crystal Semiconductor CS89x0 NIC
+# 'device ed' requires 'device miibus'
device ed # NE[12]000, SMC Ultra, 3c503, DS8390 cards
device ex # Intel EtherExpress Pro/10 and Pro/10+
device ep # Etherlink III based cards
diff --git a/sys/i386/conf/NEWCARD b/sys/i386/conf/NEWCARD
index 9f4cc98..d1ee745 100644
--- a/sys/i386/conf/NEWCARD
+++ b/sys/i386/conf/NEWCARD
@@ -40,7 +40,7 @@ maxusers 32
options MATH_EMULATE #Support for x87 emulation
options INET #InterNETworking
-options INET6 #IPv6 communications protocols
+#options INET6 #IPv6 communications protocols
options FFS #Berkeley Fast Filesystem
options SOFTUPDATES #Enable FFS soft updates support
options MFS #Memory Filesystem
@@ -68,13 +68,18 @@ options KBD_INSTALL_CDEV # install a CDEV entry in /dev
#options SMP # Symmetric MultiProcessor Kernel
#options APIC_IO # Symmetric (APIC) I/O
+options IPFIREWALL
+options DUMMYNET
+options IPFIREWALL_DEFAULT_TO_ACCEPT
+options IPDIVERT
+
device isa
device eisa
device pci
device pccard
device pmtimer
device cardbus
-options COMPAT_OLDISA # compatability shims for lnc, le
+#options COMPAT_OLDISA # compatability shims for lnc, le
# Floppy drives
device fdc
@@ -158,7 +163,7 @@ device pcm
# Pcmcia and cardbus bridge support
-device pcic # pcmcia bridge
+#device pcic # pcmcia bridge
device pccbb # cardbus (yenta) bridge
# Serial (COM) ports
@@ -196,6 +201,7 @@ device xl # 3Com 3c90x (``Boomerang'', ``Cyclone'')
# ISA Ethernet NICs. pccard nics included.
device cs # Crystal Semiconductor CS89x0 NIC
+# 'device ed' requires 'device miibus'
device ed # NE[12]000, SMC Ultra, 3c503, DS8390 cards
device ex # Intel EtherExpress Pro/10 and Pro/10+
device ep # Etherlink III based cards
@@ -204,8 +210,8 @@ device sn # SMC's 9000 series of ethernet chips
device xe # Xircom pccard ethernet
# The probe order of these is presently determined by i386/isa/isa_compat.c.
-device ie
-device le
+#device ie
+#device le
#device lnc
# Wireless NIC cards
@@ -223,8 +229,8 @@ device ppp 1 # Kernel PPP
device tun # Packet tunnel.
device pty # Pseudo-ttys (telnet etc)
device md # Memory "disks"
-device gif 4 # IPv6 and IPv4 tunneling
-device faith 1 # IPv6-to-IPv4 relaying (translation)
+#device gif 4 # IPv6 and IPv4 tunneling
+#device faith 1 # IPv6-to-IPv4 relaying (translation)
# The `bpf' device enables the Berkeley Packet Filter.
# Be aware of the administrative consequences of enabling this!
@@ -248,5 +254,8 @@ device aue # ADMtek USB ethernet
device cue # CATC USB ethernet
device kue # Kawasaki LSI USB ethernet
-# This is an experimental kernel, so include DDB
-options DDB
+# This is an experimental kernel, so include DDB, INVARIANTS and WITNESS
+options DDB
+options INVARIANTS
+options INVARIANT_SUPPORT
+options WITNESS
diff --git a/sys/modules/ed/Makefile b/sys/modules/ed/Makefile
index 23dda90b..d8a622b 100644
--- a/sys/modules/ed/Makefile
+++ b/sys/modules/ed/Makefile
@@ -12,6 +12,6 @@ CFLAGS+= -DPC98
SRCS+= if_ed_isa.c
.endif
-SRCS+= opt_bdg.h bus_if.h card_if.h device_if.h isa_if.h pci_if.h
+SRCS+= opt_bdg.h bus_if.h card_if.h device_if.h isa_if.h pci_if.h miibus_if.h
.include <bsd.kmod.mk>
OpenPOWER on IntegriCloud