From c2257f6c8a69b4a7cae98128bd89f28f3893f3c5 Mon Sep 17 00:00:00 2001 From: imp Date: Sat, 3 Mar 2001 08:31:37 +0000 Subject: [PATCH] Add support for Dlink DL10022 to the ed driver. This is a mii part bolted to a ne-2000 chip. This is necessary for the NetGear FA-410TX and other cards. This also requires you add mii to your kernel if you have an ed driver configured. This code will result in a couple of timeout messages for ed on the impacted cards. Additional work will be needed, but this does work right now, and many people need these cards. Submitted by: Ian Dowse --- sys/amd64/conf/GENERIC | 1 + sys/dev/ed/if_ed.c | 144 ++++++++++++++++++++++++++++++++++++++ sys/dev/ed/if_ed_pccard.c | 94 +++++++++++++++++++++++++ sys/dev/ed/if_ed_pci.c | 1 + sys/dev/ed/if_edreg.h | 29 ++++++++ sys/dev/ed/if_edvar.h | 9 +++ sys/i386/conf/GENERIC | 1 + sys/i386/conf/NEWCARD | 27 ++++--- sys/modules/ed/Makefile | 2 +- 9 files changed, 298 insertions(+), 10 deletions(-) diff --git a/sys/amd64/conf/GENERIC b/sys/amd64/conf/GENERIC index f6eb26baa87..f02e405d462 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 604c287774a..11843d71da3 100644 --- a/sys/dev/ed/if_ed.c +++ b/sys/dev/ed/if_ed.c @@ -41,6 +41,7 @@ #include #include #include +#include #include #include @@ -55,6 +56,10 @@ #include #include #include +#include + +#include +#include #include #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 d579d16b89f..23ef71d902d 100644 --- a/sys/dev/ed/if_ed_pccard.c +++ b/sys/dev/ed/if_ed_pccard.c @@ -44,13 +44,20 @@ #include #include #include +#include #include #include #include #include +#include +#include #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 08d1e80b646..144ba8220cc 100644 --- a/sys/dev/ed/if_ed_pci.c +++ b/sys/dev/ed/if_ed_pci.c @@ -21,6 +21,7 @@ */ #include +#include #include #include diff --git a/sys/dev/ed/if_edreg.h b/sys/dev/ed/if_edreg.h index e42ef42d2d0..a2e18820642 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 d4e896f9065..8c58b64b8aa 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 f6eb26baa87..f02e405d462 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 9f4cc984faa..d1ee7457981 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 23dda90b483..d8a622bd4f9 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 -- 2.45.0