summaryrefslogtreecommitdiffstats
path: root/sys/dev
diff options
context:
space:
mode:
authorimp <imp@FreeBSD.org>2005-09-18 20:51:34 +0000
committerimp <imp@FreeBSD.org>2005-09-18 20:51:34 +0000
commit0fa86d9cb5a02270dc33ae4359c756ad82b6d43e (patch)
tree1473f976a8ea5fd0c3df4189e61390ca888762c4 /sys/dev
parentcbeddbcc36a506db16de76f805b78fab65f5311a (diff)
downloadFreeBSD-src-0fa86d9cb5a02270dc33ae4359c756ad82b6d43e.zip
FreeBSD-src-0fa86d9cb5a02270dc33ae4359c756ad82b6d43e.tar.gz
MFp4:
o eliminate the ED_NO_MIIBUS option. Now, you need miibus to use ed with pccard. If you have an old ISA or PCI card w/o a miibus, then you'll still be able to use the ed driver w/o miibus in the kernel. If you have pccard you'll need mii now. Most pccards these days have miibus, and many cards have ISSUES if you don't attach miibus. issues I don't want to constantly rediagnose. - Add new media_ioctl, mediachg and tick function pointers. The core driver will call these if they aren't NULL, or return an error if they are. - migrate remaining mii code into if_ed_pccard. o include some notes from my datasheet fishing. this may allow us to get media status from some pccards. o Fix one bug that's common to many drivers. call if_free(ifp) after we tear down the interrupt. ed_intr() depends on ifp being there and freeing it while interrupts can still happen is, ummm, bad.
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/ed/if_ed.c103
-rw-r--r--sys/dev/ed/if_ed_pccard.c162
-rw-r--r--sys/dev/ed/if_edvar.h9
3 files changed, 149 insertions, 125 deletions
diff --git a/sys/dev/ed/if_ed.c b/sys/dev/ed/if_ed.c
index 1f60e132..e76c0c8 100644
--- a/sys/dev/ed/if_ed.c
+++ b/sys/dev/ed/if_ed.c
@@ -62,11 +62,6 @@ __FBSDID("$FreeBSD$");
#include <net/if_media.h>
#include <net/if_types.h>
-#ifndef ED_NO_MIIBUS
-#include <dev/mii/mii.h>
-#include <dev/mii/miivar.h>
-#endif
-
#include <net/bpf.h>
#include <dev/ed/if_edreg.h>
@@ -82,9 +77,6 @@ static void ed_start(struct ifnet *);
static void ed_start_locked(struct ifnet *);
static void ed_reset(struct ifnet *);
static void ed_watchdog(struct ifnet *);
-#ifndef ED_NO_MIIBUS
-static void ed_tick(void *);
-#endif
static void ed_ds_getmcaf(struct ed_softc *, uint32_t *);
@@ -377,6 +369,7 @@ ed_detach(device_t dev)
callout_drain(&sc->tick_ch);
ether_ifdetach(ifp);
bus_teardown_intr(dev, sc->irq_res, sc->irq_handle);
+ if_free(ifp);
ed_release_resources(dev);
ED_LOCK_DESTROY(sc);
return (0);
@@ -425,9 +418,8 @@ void
ed_stop(struct ed_softc *sc)
{
ED_ASSERT_LOCKED(sc);
-#ifndef ED_NO_MIIBUS
- callout_stop(&sc->tick_ch);
-#endif
+ if (sc->sc_tick)
+ callout_stop(&sc->tick_ch);
ed_stop_hw(sc);
}
@@ -448,22 +440,6 @@ ed_watchdog(struct ifnet *ifp)
ED_UNLOCK(sc);
}
-#ifndef ED_NO_MIIBUS
-static void
-ed_tick(void *arg)
-{
- struct ed_softc *sc = arg;
- struct mii_data *mii;
-
- ED_ASSERT_LOCKED(sc);
- if (sc->miibus != NULL) {
- mii = device_get_softc(sc->miibus);
- mii_tick(mii);
- }
- callout_reset(&sc->tick_ch, hz, ed_tick, sc);
-}
-#endif
-
/*
* Initialize device.
*/
@@ -605,13 +581,9 @@ ed_init_locked(struct ed_softc *sc)
ed_asic_outb(sc, ED_3COM_CR, ED_3COM_CR_XSEL);
}
#endif
-#ifndef ED_NO_MIIBUS
- if (sc->miibus != NULL) {
- struct mii_data *mii;
- mii = device_get_softc(sc->miibus);
- mii_mediachg(mii);
- }
-#endif
+ if (sc->sc_mediachg)
+ sc->sc_mediachg(sc);
+
/*
* Set 'running' flag, and clear output active flag.
*/
@@ -623,9 +595,8 @@ ed_init_locked(struct ed_softc *sc)
*/
ed_start_locked(ifp);
-#ifndef ED_NO_MIIBUS
- callout_reset(&sc->tick_ch, hz, ed_tick, sc);
-#endif
+ if (sc->sc_tick)
+ callout_reset(&sc->tick_ch, hz, sc->sc_tick, sc);
}
/*
@@ -991,12 +962,10 @@ edintr(void *arg)
int count;
ED_LOCK(sc);
-#if 0
- if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
+ if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
ED_UNLOCK(sc);
return;
}
-#endif
/*
* Set NIC to page 0 registers
*/
@@ -1239,10 +1208,7 @@ static int
ed_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
{
struct ed_softc *sc = ifp->if_softc;
-#ifndef ED_NO_MIIBUS
struct ifreq *ifr = (struct ifreq *)data;
- struct mii_data *mii;
-#endif
int error = 0;
/*
@@ -1279,8 +1245,6 @@ ed_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
* An unfortunate hack to provide the (required) software
* control of the tranceiver for 3Com/HP boards.
* The ALTPHYS flag disables the tranceiver if set.
- *
- * XXX - should use ifmedia.
*/
#ifdef ED_3C503
if (sc->vendor == ED_VENDOR_3COM) {
@@ -1311,15 +1275,12 @@ ed_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
case SIOCGIFMEDIA:
case SIOCSIFMEDIA:
- if (sc->miibus == NULL) {
+ if (sc->sc_media_ioctl == NULL) {
error = EINVAL;
break;
}
-#ifndef ED_NO_MIIBUS
- mii = device_get_softc(sc->miibus);
- error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, command);
+ sc->sc_media_ioctl(sc, ifr, command);
break;
-#endif
default:
error = ether_ioctl(ifp, command, data);
@@ -1635,48 +1596,6 @@ ed_pio_write_mbufs(struct ed_softc *sc, struct mbuf *m, bus_size_t dst)
return (total_len);
}
-#ifndef ED_NO_MIIBUS
-int
-ed_ifmedia_upd(struct ifnet *ifp)
-{
- struct ed_softc *sc;
- struct mii_data *mii;
-
- sc = ifp->if_softc;
- if (sc->miibus == NULL)
- return (ENXIO);
-
- mii = device_get_softc(sc->miibus);
- return mii_mediachg(mii);
-}
-
-void
-ed_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
-{
- struct ed_softc *sc;
- struct mii_data *mii;
-
- sc = ifp->if_softc;
- if (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(device_t dev, device_t child)
-{
- struct ed_softc *sc;
-
- sc = device_get_softc(dev);
- if (child == sc->miibus)
- sc->miibus = NULL;
-}
-#endif
-
static void
ed_setrcr(struct ed_softc *sc)
{
diff --git a/sys/dev/ed/if_ed_pccard.c b/sys/dev/ed/if_ed_pccard.c
index 0ff8b0a..cfe603f 100644
--- a/sys/dev/ed/if_ed_pccard.c
+++ b/sys/dev/ed/if_ed_pccard.c
@@ -30,6 +30,49 @@
#include "opt_ed.h"
+/*
+ * Notes for adding media support. Each chipset is somewhat different
+ * from the others. Linux has a table of OIDs that it uses to see what
+ * supports the misc register of the NS83903. But a sampling of datasheets
+ * I could dig up on cards I own paints a different picture.
+ *
+ * Chipset specific details:
+ * NS 83903/902A paired
+ * ccr base 0x1020
+ * id register at 0x1000: 7-3 = 0, 2-0 = 1.
+ * (maybe this test is too week)
+ * misc register at 0x018:
+ * 6 WAIT_TOUTENABLE enable watchdog timeout
+ * 3 AUI/TPI 1 AUX, 0 TPI
+ * 2 loopback
+ * 1 gdlink (tpi mode only) 1 tp good, 0 tp bad
+ * 0 0-no mam, 1 mam connected
+ * NS83926 appears to be a NS pcmcia glue chip used on the IBM Ethernet II
+ * and the NEC PC9801N-J12 ccr base 0x2000!
+ *
+ * winbond 289c926
+ * ccr base 0xfd0
+ * cfb (am 0xff2):
+ * 0-1 PHY01 00 TPI, 01 10B2, 10 10B5, 11 TPI (reduced squ)
+ * 2 LNKEN 0 - enable link and auto switch, 1 disable
+ * 3 LNKSTS TPI + LNKEN=0 + link good == 1, else 0
+ * sr (am 0xff4)
+ * 88 00 88 00 88 00, etc
+ *
+ * TMI tc3299a (cr PHY01 == 0)
+ * ccr base 0x3f8
+ * cra (io 0xa)
+ * crb (io 0xb)
+ * 0-1 PHY01 00 auto, 01 res, 10 10B5, 11 TPI
+ * 2 GDLINK 1 disable checking of link
+ * 6 LINK 0 bad link, 1 good link
+ * TMI tc5299 (not seen in the wild, afaik) 10/100 chip
+ *
+ * EN5017A, EN5020 no data, but very popular
+ * Other chips?
+ * NetBSD supports RTL8019, but none have surfaced that I can see
+ */
+
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/socket.h>
@@ -54,23 +97,14 @@
#include <dev/pccard/pccardvar.h>
#include <dev/pccard/pccardreg.h>
#include <dev/pccard/pccard_cis.h>
-#ifndef ED_NO_MIIBUS
#include <dev/mii/mii.h>
#include <dev/mii/miivar.h>
-#endif
#include "card_if.h"
-#ifndef ED_NO_MIIBUS
/* "device miibus" required. See GENERIC if you get errors here. */
#include "miibus_if.h"
-#endif
#include "pccarddevs.h"
-#ifndef ED_NO_MIIBUS
-MODULE_DEPEND(ed, miibus, 1, 1, 1);
-#endif
-MODULE_DEPEND(ed, ether, 1, 1, 1);
-
/*
* PC Cards should be using a network specific FUNCE in the CIS to
* communicate their MAC address to the driver. However, there are a
@@ -128,6 +162,7 @@ static const struct ed_product {
{ PCMCIA_CARD(DLINK, DE660PLUS), 0},
{ PCMCIA_CARD(DYNALINK, L10C), 0},
{ PCMCIA_CARD(EDIMAX, EP4000A), 0},
+ /* { PCMCIA_CARD(EPSON, EEN10B), NE2000DVF_ENADDR, 0xff0}, */
{ PCMCIA_CARD(EPSON, EEN10B), 0},
{ PCMCIA_CARD(EXP, THINLANCOMBO), 0},
{ PCMCIA_CARD(GREY_CELL, TDK3000), 0},
@@ -159,7 +194,8 @@ static const struct ed_product {
{ PCMCIA_CARD(OEM2, NE2000), 0},
{ PCMCIA_CARD(PLANET, SMARTCOM2000), 0 },
{ PCMCIA_CARD(PREMAX, PE200), 0},
- { PCMCIA_CARD(PSION, LANGLOBAL), 0},
+ { PCMCIA_CARD(PSION, LANGLOBAL),
+ NE2000DVF_ANYFUNC | NE2000DVF_AX88X90 | NE2000DVF_MODEM},
{ PCMCIA_CARD(RACORE, ETHERNET), 0},
{ PCMCIA_CARD(RACORE, FASTENET), NE2000DVF_AX88X90},
{ PCMCIA_CARD(RACORE, 8041TX), NE2000DVF_AX88X90},
@@ -191,7 +227,6 @@ static int ed_pccard_probe(device_t);
static int ed_pccard_attach(device_t);
static int ed_pccard_dl100xx(device_t dev, const struct ed_product *);
-#ifndef ED_NO_MIIBUS
static void ed_pccard_dl100xx_mii_reset(struct ed_softc *sc);
static u_int ed_pccard_dl100xx_mii_readbits(struct ed_softc *sc, int nbits);
static void ed_pccard_dl100xx_mii_writebits(struct ed_softc *sc, u_int val,
@@ -202,7 +237,8 @@ static u_int ed_pccard_ax88x90_mii_readbits(struct ed_softc *sc, int nbits);
static void ed_pccard_ax88x90_mii_writebits(struct ed_softc *sc, u_int val,
int nbits);
static int ed_miibus_readreg(device_t dev, int phy, int reg);
-#endif
+static int ed_ifmedia_upd(struct ifnet *);
+static void ed_ifmedia_sts(struct ifnet *, struct ifmediareq *);
static int ed_pccard_ax88x90(device_t dev, const struct ed_product *);
@@ -296,6 +332,43 @@ ed_pccard_add_modem(device_t dev)
}
static int
+ed_pccard_media_ioctl(struct ed_softc *sc, struct ifreq *ifr, u_long command)
+{
+ struct mii_data *mii;
+
+ if (sc->miibus == NULL)
+ return (EINVAL);
+ mii = device_get_softc(sc->miibus);
+ return (ifmedia_ioctl(sc->ifp, ifr, &mii->mii_media, command));
+}
+
+
+static void
+ed_pccard_mediachg(struct ed_softc *sc)
+{
+ struct mii_data *mii;
+
+ if (sc->miibus == NULL)
+ return;
+ mii = device_get_softc(sc->miibus);
+ mii_mediachg(mii);
+}
+
+static void
+ed_pccard_tick(void *arg)
+{
+ struct ed_softc *sc = arg;
+ struct mii_data *mii;
+
+ ED_ASSERT_LOCKED(sc);
+ if (sc->miibus != NULL) {
+ mii = device_get_softc(sc->miibus);
+ mii_tick(mii);
+ }
+ callout_reset(&sc->tick_ch, hz, ed_pccard_tick, sc);
+}
+
+static int
ed_pccard_attach(device_t dev)
{
u_char sum;
@@ -368,6 +441,8 @@ ed_pccard_attach(device_t dev)
* but don't right now.
*/
if (sc->chip_type == ED_CHIP_TYPE_DP8390) {
+ ed_nic_outb(sc, ED_P0_CR, ED_CR_RD2 | ED_CR_STP | ED_CR_PAGE_0);
+ printf("%#x and %#x", ed_nic_inb(sc, 0xa), ed_nic_inb(sc, 0xb));
pccard_get_ether(dev, enaddr);
if (bootverbose)
device_printf(dev, "CIS MAC %6D\n", enaddr, ":");
@@ -410,7 +485,6 @@ ed_pccard_attach(device_t dev)
error = ed_attach(dev);
if (error)
goto bad;
-#ifndef ED_NO_MIIBUS
if (sc->chip_type == ED_CHIP_TYPE_DL10019 ||
sc->chip_type == ED_CHIP_TYPE_DL10022) {
/* Probe for an MII bus, but ignore errors. */
@@ -426,7 +500,11 @@ ed_pccard_attach(device_t dev)
}
}
-#endif
+ if (sc->miibus != NULL) {
+ sc->sc_tick = ed_pccard_tick;
+ sc->sc_mediachg = ed_pccard_mediachg;
+ sc->sc_media_ioctl = ed_pccard_media_ioctl;
+ }
if (sc->modem_rid != -1)
ed_pccard_add_modem(dev);
return (0);
@@ -492,7 +570,6 @@ ed_pccard_dl100xx(device_t dev, const struct ed_product *pp)
return (0);
}
-#ifndef ED_NO_MIIBUS
/* MII bit-twiddling routines for cards using Dlink chipset */
#define DL100XX_MIISET(sc, x) ed_asic_outb(sc, ED_DL100XX_MIIBUS, \
ed_asic_inb(sc, ED_DL100XX_MIIBUS) | (x))
@@ -563,7 +640,6 @@ ed_pccard_dl100xx_mii_readbits(struct ed_softc *sc, int nbits)
}
return val;
}
-#endif
static int
ed_pccard_ax88x90_geteprom(struct ed_softc *sc)
@@ -635,9 +711,6 @@ ed_pccard_ax88x90(device_t dev, const struct ed_product *pp)
pccard_ccr_write_1(dev, PCCARD_CCR_IOBASE0, iobase & 0xff);
pccard_ccr_write_1(dev, PCCARD_CCR_IOBASE1, (iobase >> 8) & 0xff);
-#ifdef ED_NO_MIIBUS
- return (ENXIO);
-#else
/*
* Check to see if we have a MII PHY ID at any of the first 17
* locations. All AX88x90 devices have MII and a PHY, so we use
@@ -685,10 +758,8 @@ ed_pccard_ax88x90(device_t dev, const struct ed_product *pp)
sc->type_str = ts;
}
return (error);
-#endif
}
-#ifndef ED_NO_MIIBUS
/* MII bit-twiddling routines for cards using Dlink chipset */
#define AX88X90_MIISET(sc, x) ed_asic_outb(sc, ED_AX88X90_MIIBUS, \
ed_asic_inb(sc, ED_AX88X90_MIIBUS) | (x))
@@ -738,9 +809,7 @@ ed_pccard_ax88x90_mii_readbits(struct ed_softc *sc, int nbits)
}
return val;
}
-#endif
-#ifndef ED_NO_MIIBUS
/*
* MII bus support routines.
*/
@@ -793,7 +862,46 @@ ed_miibus_writereg(device_t dev, int phy, int reg, int data)
(*sc->mii_writebits)(sc, data, ED_MII_DATA_BITS);
(*sc->mii_writebits)(sc, ED_MII_IDLE, ED_MII_IDLE_BITS);
}
-#endif
+
+static int
+ed_ifmedia_upd(struct ifnet *ifp)
+{
+ struct ed_softc *sc;
+ struct mii_data *mii;
+
+ sc = ifp->if_softc;
+ if (sc->miibus == NULL)
+ return (ENXIO);
+
+ mii = device_get_softc(sc->miibus);
+ return mii_mediachg(mii);
+}
+
+static void
+ed_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
+{
+ struct ed_softc *sc;
+ struct mii_data *mii;
+
+ sc = ifp->if_softc;
+ if (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;
+}
+
+static void
+ed_child_detached(device_t dev, device_t child)
+{
+ struct ed_softc *sc;
+
+ sc = device_get_softc(dev);
+ if (child == sc->miibus)
+ sc->miibus = NULL;
+}
static device_method_t ed_pccard_methods[] = {
/* Device interface */
@@ -801,14 +909,12 @@ static device_method_t ed_pccard_methods[] = {
DEVMETHOD(device_attach, ed_pccard_attach),
DEVMETHOD(device_detach, ed_detach),
-#ifndef ED_NO_MIIBUS
/* Bus interface */
DEVMETHOD(bus_child_detached, ed_child_detached),
/* MII interface */
DEVMETHOD(miibus_readreg, ed_miibus_readreg),
DEVMETHOD(miibus_writereg, ed_miibus_writereg),
-#endif
{ 0, 0 }
};
@@ -820,6 +926,6 @@ static driver_t ed_pccard_driver = {
};
DRIVER_MODULE(ed, pccard, ed_pccard_driver, ed_devclass, 0, 0);
-#ifndef ED_NO_MIIBUS
DRIVER_MODULE(miibus, ed, miibus_driver, miibus_devclass, 0, 0);
-#endif
+MODULE_DEPEND(ed, miibus, 1, 1, 1);
+MODULE_DEPEND(ed, ether, 1, 1, 1);
diff --git a/sys/dev/ed/if_edvar.h b/sys/dev/ed/if_edvar.h
index f03b385..4e8afe8 100644
--- a/sys/dev/ed/if_edvar.h
+++ b/sys/dev/ed/if_edvar.h
@@ -61,10 +61,14 @@ struct ed_softc {
struct resource* irq_res; /* resource for irq */
void* irq_handle; /* handle for irq handler */
int modem_rid; /* resource ID for modem part of device */
+ int (*sc_media_ioctl)(struct ed_softc *sc, struct ifreq *ifr,
+ u_long command);
+ void (*sc_mediachg)(struct ed_softc *);
device_t miibus; /* MII bus for cards with MII. */
void (*mii_writebits)(struct ed_softc *, u_int, int);
u_int (*mii_readbits)(struct ed_softc *, int);
struct callout tick_ch;
+ void (*sc_tick)(void *);
void (*readmem)(struct ed_softc *sc, bus_size_t src, uint8_t *dst,
uint16_t amount);
@@ -212,11 +216,6 @@ void ed_shmem_readmem16(struct ed_softc *, bus_size_t, uint8_t *, uint16_t);
void ed_shmem_readmem8(struct ed_softc *, bus_size_t, uint8_t *, uint16_t);
void ed_pio_readmem(struct ed_softc *, bus_size_t, uint8_t *, uint16_t);
void ed_pio_writemem(struct ed_softc *, uint8_t *, uint16_t, uint16_t);
-#ifndef ED_NO_MIIBUS
-int ed_ifmedia_upd(struct ifnet *);
-void ed_ifmedia_sts(struct ifnet *, struct ifmediareq *);
-void ed_child_detached(device_t, device_t);
-#endif
/* The following is unsatisfying XXX */
#ifdef ED_HPP
OpenPOWER on IntegriCloud