MFC: Bring in support for new PC Card chipset (TC5299J) and old
ISA/PCI chipset (RTL8019 and RTL8029). Eliminate ED_NO_MIIBUS option. You are now required to have miibus if you have pccard in your kernel (but not required if you don't!). Split out register definitions for possible future subsetting. Approved by: re@ (scottl)
This commit is contained in:
parent
7eae1cb08f
commit
5eaca6ae49
@ -525,6 +525,7 @@ dev/ed/if_ed.c optional ed
|
|||||||
dev/ed/if_ed_novell.c optional ed
|
dev/ed/if_ed_novell.c optional ed
|
||||||
dev/ed/if_ed_pccard.c optional ed pccard
|
dev/ed/if_ed_pccard.c optional ed pccard
|
||||||
dev/ed/if_ed_pci.c optional ed pci
|
dev/ed/if_ed_pci.c optional ed pci
|
||||||
|
dev/ed/if_ed_rtl80x9.c optional ed
|
||||||
dev/eisa/eisa_if.m standard
|
dev/eisa/eisa_if.m standard
|
||||||
dev/eisa/eisaconf.c optional eisa
|
dev/eisa/eisaconf.c optional eisa
|
||||||
dev/em/if_em.c optional em
|
dev/em/if_em.c optional em
|
||||||
|
@ -62,11 +62,6 @@ __FBSDID("$FreeBSD$");
|
|||||||
#include <net/if_media.h>
|
#include <net/if_media.h>
|
||||||
#include <net/if_types.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 <net/bpf.h>
|
||||||
|
|
||||||
#include <dev/ed/if_edreg.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_start_locked(struct ifnet *);
|
||||||
static void ed_reset(struct ifnet *);
|
static void ed_reset(struct ifnet *);
|
||||||
static void ed_watchdog(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 *);
|
static void ed_ds_getmcaf(struct ed_softc *, uint32_t *);
|
||||||
|
|
||||||
@ -379,6 +371,7 @@ ed_detach(device_t dev)
|
|||||||
bus_teardown_intr(dev, sc->irq_res, sc->irq_handle);
|
bus_teardown_intr(dev, sc->irq_res, sc->irq_handle);
|
||||||
ed_release_resources(dev);
|
ed_release_resources(dev);
|
||||||
ED_LOCK_DESTROY(sc);
|
ED_LOCK_DESTROY(sc);
|
||||||
|
bus_generic_detach(dev);
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -425,9 +418,8 @@ void
|
|||||||
ed_stop(struct ed_softc *sc)
|
ed_stop(struct ed_softc *sc)
|
||||||
{
|
{
|
||||||
ED_ASSERT_LOCKED(sc);
|
ED_ASSERT_LOCKED(sc);
|
||||||
#ifndef ED_NO_MIIBUS
|
if (sc->sc_tick)
|
||||||
callout_stop(&sc->tick_ch);
|
callout_stop(&sc->tick_ch);
|
||||||
#endif
|
|
||||||
ed_stop_hw(sc);
|
ed_stop_hw(sc);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -448,22 +440,6 @@ ed_watchdog(struct ifnet *ifp)
|
|||||||
ED_UNLOCK(sc);
|
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.
|
* Initialize device.
|
||||||
*/
|
*/
|
||||||
@ -605,13 +581,9 @@ ed_init_locked(struct ed_softc *sc)
|
|||||||
ed_asic_outb(sc, ED_3COM_CR, ED_3COM_CR_XSEL);
|
ed_asic_outb(sc, ED_3COM_CR, ED_3COM_CR_XSEL);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifndef ED_NO_MIIBUS
|
if (sc->sc_mediachg)
|
||||||
if (sc->miibus != NULL) {
|
sc->sc_mediachg(sc);
|
||||||
struct mii_data *mii;
|
|
||||||
mii = device_get_softc(sc->miibus);
|
|
||||||
mii_mediachg(mii);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
/*
|
/*
|
||||||
* Set 'running' flag, and clear output active flag.
|
* Set 'running' flag, and clear output active flag.
|
||||||
*/
|
*/
|
||||||
@ -623,9 +595,8 @@ ed_init_locked(struct ed_softc *sc)
|
|||||||
*/
|
*/
|
||||||
ed_start_locked(ifp);
|
ed_start_locked(ifp);
|
||||||
|
|
||||||
#ifndef ED_NO_MIIBUS
|
if (sc->sc_tick)
|
||||||
callout_reset(&sc->tick_ch, hz, ed_tick, sc);
|
callout_reset(&sc->tick_ch, hz, sc->sc_tick, sc);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -991,12 +962,10 @@ edintr(void *arg)
|
|||||||
int count;
|
int count;
|
||||||
|
|
||||||
ED_LOCK(sc);
|
ED_LOCK(sc);
|
||||||
#if 0
|
if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
|
||||||
if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
|
|
||||||
ED_UNLOCK(sc);
|
ED_UNLOCK(sc);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
/*
|
/*
|
||||||
* Set NIC to page 0 registers
|
* Set NIC to page 0 registers
|
||||||
*/
|
*/
|
||||||
@ -1239,10 +1208,7 @@ static int
|
|||||||
ed_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
|
ed_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
|
||||||
{
|
{
|
||||||
struct ed_softc *sc = ifp->if_softc;
|
struct ed_softc *sc = ifp->if_softc;
|
||||||
#ifndef ED_NO_MIIBUS
|
|
||||||
struct ifreq *ifr = (struct ifreq *)data;
|
struct ifreq *ifr = (struct ifreq *)data;
|
||||||
struct mii_data *mii;
|
|
||||||
#endif
|
|
||||||
int error = 0;
|
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
|
* An unfortunate hack to provide the (required) software
|
||||||
* control of the tranceiver for 3Com/HP boards.
|
* control of the tranceiver for 3Com/HP boards.
|
||||||
* The ALTPHYS flag disables the tranceiver if set.
|
* The ALTPHYS flag disables the tranceiver if set.
|
||||||
*
|
|
||||||
* XXX - should use ifmedia.
|
|
||||||
*/
|
*/
|
||||||
#ifdef ED_3C503
|
#ifdef ED_3C503
|
||||||
if (sc->vendor == ED_VENDOR_3COM) {
|
if (sc->vendor == ED_VENDOR_3COM) {
|
||||||
@ -1311,15 +1275,12 @@ ed_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
|
|||||||
|
|
||||||
case SIOCGIFMEDIA:
|
case SIOCGIFMEDIA:
|
||||||
case SIOCSIFMEDIA:
|
case SIOCSIFMEDIA:
|
||||||
if (sc->miibus == NULL) {
|
if (sc->sc_media_ioctl == NULL) {
|
||||||
error = EINVAL;
|
error = EINVAL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#ifndef ED_NO_MIIBUS
|
sc->sc_media_ioctl(sc, ifr, command);
|
||||||
mii = device_get_softc(sc->miibus);
|
|
||||||
error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, command);
|
|
||||||
break;
|
break;
|
||||||
#endif
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
error = ether_ioctl(ifp, command, data);
|
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);
|
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
|
static void
|
||||||
ed_setrcr(struct ed_softc *sc)
|
ed_setrcr(struct ed_softc *sc)
|
||||||
{
|
{
|
||||||
|
@ -28,7 +28,49 @@
|
|||||||
* $FreeBSD$
|
* $FreeBSD$
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#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 10/100 chip, has a different MII interaction than
|
||||||
|
* dl100xx and ax88x90.
|
||||||
|
*
|
||||||
|
* 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/param.h>
|
||||||
#include <sys/systm.h>
|
#include <sys/systm.h>
|
||||||
@ -51,39 +93,30 @@
|
|||||||
|
|
||||||
#include <dev/ed/if_edreg.h>
|
#include <dev/ed/if_edreg.h>
|
||||||
#include <dev/ed/if_edvar.h>
|
#include <dev/ed/if_edvar.h>
|
||||||
|
#include <dev/ed/ax88x90reg.h>
|
||||||
|
#include <dev/ed/dl100xxreg.h>
|
||||||
|
#include <dev/ed/tc5299jreg.h>
|
||||||
#include <dev/pccard/pccardvar.h>
|
#include <dev/pccard/pccardvar.h>
|
||||||
#include <dev/pccard/pccardreg.h>
|
#include <dev/pccard/pccardreg.h>
|
||||||
#include <dev/pccard/pccard_cis.h>
|
#include <dev/pccard/pccard_cis.h>
|
||||||
#ifndef ED_NO_MIIBUS
|
|
||||||
#include <dev/mii/mii.h>
|
#include <dev/mii/mii.h>
|
||||||
#include <dev/mii/miivar.h>
|
#include <dev/mii/miivar.h>
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "card_if.h"
|
#include "card_if.h"
|
||||||
#ifndef ED_NO_MIIBUS
|
|
||||||
/* "device miibus" required. See GENERIC if you get errors here. */
|
/* "device miibus" required. See GENERIC if you get errors here. */
|
||||||
#include "miibus_if.h"
|
#include "miibus_if.h"
|
||||||
#endif
|
|
||||||
#include "pccarddevs.h"
|
#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
|
* NE-2000 based PC Cards have a number of ways to get the MAC address.
|
||||||
* communicate their MAC address to the driver. However, there are a
|
* Some cards encode this as a FUNCE. Others have this in the ROMs the
|
||||||
* large number of NE-2000ish PC Cards that don't do this. Nearly all
|
* same way that ISA cards do. Some have it encoded in the attribute
|
||||||
* of them store the MAC address at a fixed offset into attribute
|
* memory somewhere that isn't in the CIS. Some new chipsets have it
|
||||||
* memory, without any reference at all appearing in the CIS. And
|
* in special registers in the ASIC part of the chip.
|
||||||
* nearly all of those store it at the same location.
|
|
||||||
*
|
*
|
||||||
* This applies only to the older, NE-2000 compatbile cards. The newer
|
* For those cards that have the MAC adress stored in attribute memory,
|
||||||
* cards based on the AX88x90 or DL100XX chipsets have a specific place
|
* nearly all of them have it at a fixed offset (0xff0). We use that
|
||||||
* to look for MAC information. And only to those NE-2000 compatible cards
|
* offset as a source of last resource if other offsets have failed.
|
||||||
* that don't the NE-2000 compatible thing of placing the PROM contents
|
|
||||||
* starting at location 0 of memory.
|
|
||||||
*/
|
*/
|
||||||
#define ED_DEFAULT_MAC_OFFSET 0xff0
|
#define ED_DEFAULT_MAC_OFFSET 0xff0
|
||||||
|
|
||||||
@ -92,9 +125,10 @@ static const struct ed_product {
|
|||||||
int flags;
|
int flags;
|
||||||
#define NE2000DVF_DL100XX 0x0001 /* chip is D-Link DL10019/22 */
|
#define NE2000DVF_DL100XX 0x0001 /* chip is D-Link DL10019/22 */
|
||||||
#define NE2000DVF_AX88X90 0x0002 /* chip is ASIX AX88[17]90 */
|
#define NE2000DVF_AX88X90 0x0002 /* chip is ASIX AX88[17]90 */
|
||||||
#define NE2000DVF_ENADDR 0x0004 /* Get MAC from attr mem */
|
#define NE2000DVF_TC5299J 0x0004 /* chip is Tamarack TC5299J */
|
||||||
#define NE2000DVF_ANYFUNC 0x0008 /* Allow any function type */
|
#define NE2000DVF_ENADDR 0x0100 /* Get MAC from attr mem */
|
||||||
#define NE2000DVF_MODEM 0x0010 /* Has a modem/serial */
|
#define NE2000DVF_ANYFUNC 0x0200 /* Allow any function type */
|
||||||
|
#define NE2000DVF_MODEM 0x0400 /* Has a modem/serial */
|
||||||
int enoff;
|
int enoff;
|
||||||
} ed_pccard_products[] = {
|
} ed_pccard_products[] = {
|
||||||
{ PCMCIA_CARD(ACCTON, EN2212), 0},
|
{ PCMCIA_CARD(ACCTON, EN2212), 0},
|
||||||
@ -123,12 +157,11 @@ static const struct ed_product {
|
|||||||
{ PCMCIA_CARD(COREGA, FETHER_PCC_TXF), NE2000DVF_DL100XX},
|
{ PCMCIA_CARD(COREGA, FETHER_PCC_TXF), NE2000DVF_DL100XX},
|
||||||
{ PCMCIA_CARD(DAYNA, COMMUNICARD_E_1), 0},
|
{ PCMCIA_CARD(DAYNA, COMMUNICARD_E_1), 0},
|
||||||
{ PCMCIA_CARD(DAYNA, COMMUNICARD_E_2), 0},
|
{ PCMCIA_CARD(DAYNA, COMMUNICARD_E_2), 0},
|
||||||
{ PCMCIA_CARD(DLINK, DE650), 0},
|
|
||||||
{ PCMCIA_CARD(DLINK, DE660), 0 },
|
{ PCMCIA_CARD(DLINK, DE660), 0 },
|
||||||
{ PCMCIA_CARD(DLINK, DE660PLUS), 0},
|
{ PCMCIA_CARD(DLINK, DE660PLUS), 0},
|
||||||
{ PCMCIA_CARD(DYNALINK, L10C), 0},
|
{ PCMCIA_CARD(DYNALINK, L10C), 0},
|
||||||
{ PCMCIA_CARD(EDIMAX, EP4000A), 0},
|
{ PCMCIA_CARD(EDIMAX, EP4000A), 0},
|
||||||
{ PCMCIA_CARD(EPSON, EEN10B), 0},
|
{ PCMCIA_CARD(EPSON, EEN10B), NE2000DVF_ENADDR, 0xff0},
|
||||||
{ PCMCIA_CARD(EXP, THINLANCOMBO), 0},
|
{ PCMCIA_CARD(EXP, THINLANCOMBO), 0},
|
||||||
{ PCMCIA_CARD(GREY_CELL, TDK3000), 0},
|
{ PCMCIA_CARD(GREY_CELL, TDK3000), 0},
|
||||||
{ PCMCIA_CARD(GREY_CELL, DMF650TX),
|
{ PCMCIA_CARD(GREY_CELL, DMF650TX),
|
||||||
@ -159,10 +192,11 @@ static const struct ed_product {
|
|||||||
{ PCMCIA_CARD(OEM2, NE2000), 0},
|
{ PCMCIA_CARD(OEM2, NE2000), 0},
|
||||||
{ PCMCIA_CARD(PLANET, SMARTCOM2000), 0 },
|
{ PCMCIA_CARD(PLANET, SMARTCOM2000), 0 },
|
||||||
{ PCMCIA_CARD(PREMAX, PE200), 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, ETHERNET), 0},
|
||||||
{ PCMCIA_CARD(RACORE, FASTENET), NE2000DVF_AX88X90},
|
{ PCMCIA_CARD(RACORE, FASTENET), NE2000DVF_AX88X90},
|
||||||
{ PCMCIA_CARD(RACORE, 8041TX), NE2000DVF_AX88X90},
|
{ PCMCIA_CARD(RACORE, 8041TX), NE2000DVF_AX88X90 | NE2000DVF_TC5299J},
|
||||||
{ PCMCIA_CARD(RELIA, COMBO), 0},
|
{ PCMCIA_CARD(RELIA, COMBO), 0},
|
||||||
{ PCMCIA_CARD(RPTI, EP400), 0},
|
{ PCMCIA_CARD(RPTI, EP400), 0},
|
||||||
{ PCMCIA_CARD(RPTI, EP401), 0},
|
{ PCMCIA_CARD(RPTI, EP401), 0},
|
||||||
@ -191,26 +225,48 @@ static int ed_pccard_probe(device_t);
|
|||||||
static int ed_pccard_attach(device_t);
|
static int ed_pccard_attach(device_t);
|
||||||
|
|
||||||
static int ed_pccard_dl100xx(device_t dev, const struct ed_product *);
|
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 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 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,
|
static void ed_pccard_dl100xx_mii_writebits(struct ed_softc *sc, u_int val,
|
||||||
int nbits);
|
int nbits);
|
||||||
|
|
||||||
|
static int ed_pccard_ax88x90(device_t dev, const struct ed_product *);
|
||||||
static void ed_pccard_ax88x90_mii_reset(struct ed_softc *sc);
|
static void ed_pccard_ax88x90_mii_reset(struct ed_softc *sc);
|
||||||
static u_int ed_pccard_ax88x90_mii_readbits(struct ed_softc *sc, int nbits);
|
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,
|
static void ed_pccard_ax88x90_mii_writebits(struct ed_softc *sc, u_int val,
|
||||||
int nbits);
|
int nbits);
|
||||||
static int ed_miibus_readreg(device_t dev, int phy, int reg);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static int ed_pccard_ax88x90(device_t dev, const struct ed_product *);
|
static int ed_miibus_readreg(device_t dev, int phy, int reg);
|
||||||
|
static int ed_ifmedia_upd(struct ifnet *);
|
||||||
|
static void ed_ifmedia_sts(struct ifnet *, struct ifmediareq *);
|
||||||
|
|
||||||
|
static int ed_pccard_tc5299j(device_t dev, const struct ed_product *);
|
||||||
|
static void ed_pccard_tc5299j_mii_reset(struct ed_softc *sc);
|
||||||
|
static u_int ed_pccard_tc5299j_mii_readbits(struct ed_softc *sc, int nbits);
|
||||||
|
static void ed_pccard_tc5299j_mii_writebits(struct ed_softc *sc, u_int val,
|
||||||
|
int nbits);
|
||||||
|
|
||||||
|
static void
|
||||||
|
ed_pccard_print_entry(const struct ed_product *pp)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
printf("Product entry: ");
|
||||||
|
if (pp->prod.pp_name)
|
||||||
|
printf("name='%s',", pp->prod.pp_name);
|
||||||
|
printf("vendor=%#x,product=%#x", pp->prod.pp_vendor,
|
||||||
|
pp->prod.pp_product);
|
||||||
|
for (i = 0; i < 4; i++)
|
||||||
|
if (pp->prod.pp_cis[i])
|
||||||
|
printf(",CIS%d='%s'", i, pp->prod.pp_cis[i]);
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
ed_pccard_probe(device_t dev)
|
ed_pccard_probe(device_t dev)
|
||||||
{
|
{
|
||||||
const struct ed_product *pp;
|
const struct ed_product *pp, *pp2;
|
||||||
int error;
|
int error, first = 1;
|
||||||
uint32_t fcn = PCCARD_FUNCTION_UNSPEC;
|
uint32_t fcn = PCCARD_FUNCTION_UNSPEC;
|
||||||
|
|
||||||
/* Make sure we're a network function */
|
/* Make sure we're a network function */
|
||||||
@ -230,6 +286,23 @@ ed_pccard_probe(device_t dev)
|
|||||||
if (!(pp->flags & NE2000DVF_ANYFUNC) &&
|
if (!(pp->flags & NE2000DVF_ANYFUNC) &&
|
||||||
fcn != PCCARD_FUNCTION_NETWORK)
|
fcn != PCCARD_FUNCTION_NETWORK)
|
||||||
return (ENXIO);
|
return (ENXIO);
|
||||||
|
/*
|
||||||
|
* Some devices match multiple entries. Report that
|
||||||
|
* as a warning to help cull the table
|
||||||
|
*/
|
||||||
|
pp2 = pp;
|
||||||
|
while ((pp2 = (const struct ed_product *)pccard_product_lookup(
|
||||||
|
dev, (const struct pccard_product *)(pp2 + 1),
|
||||||
|
sizeof(ed_pccard_products[0]), NULL)) != NULL) {
|
||||||
|
if (first) {
|
||||||
|
device_printf(dev,
|
||||||
|
"Warning: card matches multiple entries. Report to imp@freebsd.org\n");
|
||||||
|
ed_pccard_print_entry(pp);
|
||||||
|
first = 0;
|
||||||
|
}
|
||||||
|
ed_pccard_print_entry(pp2);
|
||||||
|
}
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
return (ENXIO);
|
return (ENXIO);
|
||||||
@ -295,6 +368,53 @@ ed_pccard_add_modem(device_t dev)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
int media = 0;
|
||||||
|
|
||||||
|
ED_ASSERT_LOCKED(sc);
|
||||||
|
if (sc->miibus != NULL) {
|
||||||
|
mii = device_get_softc(sc->miibus);
|
||||||
|
media = mii->mii_media_status;
|
||||||
|
mii_tick(mii);
|
||||||
|
if (mii->mii_media_status & IFM_ACTIVE &&
|
||||||
|
media != mii->mii_media_status && 0 &&
|
||||||
|
sc->chip_type == ED_CHIP_TYPE_DL10022) {
|
||||||
|
ed_asic_outb(sc, ED_DL100XX_DIAG,
|
||||||
|
(mii->mii_media_active & IFM_FDX) ?
|
||||||
|
ED_DL100XX_COLLISON_DIS : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
callout_reset(&sc->tick_ch, hz, ed_pccard_tick, sc);
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
ed_pccard_attach(device_t dev)
|
ed_pccard_attach(device_t dev)
|
||||||
{
|
{
|
||||||
@ -345,6 +465,8 @@ ed_pccard_attach(device_t dev)
|
|||||||
error = ed_pccard_dl100xx(dev, pp);
|
error = ed_pccard_dl100xx(dev, pp);
|
||||||
if (error != 0)
|
if (error != 0)
|
||||||
error = ed_pccard_ax88x90(dev, pp);
|
error = ed_pccard_ax88x90(dev, pp);
|
||||||
|
if (error != 0)
|
||||||
|
error = ed_pccard_tc5299j(dev, pp);
|
||||||
if (error != 0)
|
if (error != 0)
|
||||||
error = ed_probe_Novell_generic(dev, device_get_flags(dev));
|
error = ed_probe_Novell_generic(dev, device_get_flags(dev));
|
||||||
if (error)
|
if (error)
|
||||||
@ -410,7 +532,6 @@ ed_pccard_attach(device_t dev)
|
|||||||
error = ed_attach(dev);
|
error = ed_attach(dev);
|
||||||
if (error)
|
if (error)
|
||||||
goto bad;
|
goto bad;
|
||||||
#ifndef ED_NO_MIIBUS
|
|
||||||
if (sc->chip_type == ED_CHIP_TYPE_DL10019 ||
|
if (sc->chip_type == ED_CHIP_TYPE_DL10019 ||
|
||||||
sc->chip_type == ED_CHIP_TYPE_DL10022) {
|
sc->chip_type == ED_CHIP_TYPE_DL10022) {
|
||||||
/* Probe for an MII bus, but ignore errors. */
|
/* Probe for an MII bus, but ignore errors. */
|
||||||
@ -425,8 +546,20 @@ ed_pccard_attach(device_t dev)
|
|||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} else if (sc->chip_type == ED_CHIP_TYPE_TC5299J) {
|
||||||
|
ed_pccard_tc5299j_mii_reset(sc);
|
||||||
|
if ((error = mii_phy_probe(dev, &sc->miibus, ed_ifmedia_upd,
|
||||||
|
ed_ifmedia_sts)) != 0) {
|
||||||
|
device_printf(dev, "Missing mii!\n");
|
||||||
|
goto bad;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
if (sc->miibus != NULL) {
|
||||||
|
sc->sc_tick = ed_pccard_tick;
|
||||||
|
sc->sc_mediachg = ed_pccard_mediachg;
|
||||||
|
sc->sc_media_ioctl = ed_pccard_media_ioctl;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
if (sc->modem_rid != -1)
|
if (sc->modem_rid != -1)
|
||||||
ed_pccard_add_modem(dev);
|
ed_pccard_add_modem(dev);
|
||||||
return (0);
|
return (0);
|
||||||
@ -492,7 +625,6 @@ ed_pccard_dl100xx(device_t dev, const struct ed_product *pp)
|
|||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef ED_NO_MIIBUS
|
|
||||||
/* MII bit-twiddling routines for cards using Dlink chipset */
|
/* MII bit-twiddling routines for cards using Dlink chipset */
|
||||||
#define DL100XX_MIISET(sc, x) ed_asic_outb(sc, ED_DL100XX_MIIBUS, \
|
#define DL100XX_MIISET(sc, x) ed_asic_outb(sc, ED_DL100XX_MIIBUS, \
|
||||||
ed_asic_inb(sc, ED_DL100XX_MIIBUS) | (x))
|
ed_asic_inb(sc, ED_DL100XX_MIIBUS) | (x))
|
||||||
@ -556,14 +688,13 @@ ed_pccard_dl100xx_mii_readbits(struct ed_softc *sc, int nbits)
|
|||||||
DL100XX_MIISET(sc, ED_DL100XX_MII_CLK);
|
DL100XX_MIISET(sc, ED_DL100XX_MII_CLK);
|
||||||
DELAY(10);
|
DELAY(10);
|
||||||
val <<= 1;
|
val <<= 1;
|
||||||
if (ed_asic_inb(sc, ED_DL100XX_MIIBUS) & ED_DL100XX_MII_DATATIN)
|
if (ed_asic_inb(sc, ED_DL100XX_MIIBUS) & ED_DL100XX_MII_DATAIN)
|
||||||
val++;
|
val++;
|
||||||
DL100XX_MIICLR(sc, ED_DL100XX_MII_CLK);
|
DL100XX_MIICLR(sc, ED_DL100XX_MII_CLK);
|
||||||
DELAY(10);
|
DELAY(10);
|
||||||
}
|
}
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
ed_pccard_ax88x90_geteprom(struct ed_softc *sc)
|
ed_pccard_ax88x90_geteprom(struct ed_softc *sc)
|
||||||
@ -635,9 +766,24 @@ 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_IOBASE0, iobase & 0xff);
|
||||||
pccard_ccr_write_1(dev, PCCARD_CCR_IOBASE1, (iobase >> 8) & 0xff);
|
pccard_ccr_write_1(dev, PCCARD_CCR_IOBASE1, (iobase >> 8) & 0xff);
|
||||||
|
|
||||||
#ifdef ED_NO_MIIBUS
|
ts = "AX88190";
|
||||||
return (ENXIO);
|
if (ed_asic_inb(sc, ED_AX88X90_TEST) != 0) {
|
||||||
#else
|
/*
|
||||||
|
* AX88790 (and I think AX88190A) chips need to be
|
||||||
|
* powered down. There's an erratum that says we should
|
||||||
|
* power down the PHY for 2.5s, but this seems to power
|
||||||
|
* down the whole card. I'm unsure why this was done, but
|
||||||
|
* appears to be required for proper operation.
|
||||||
|
*/
|
||||||
|
pccard_ccr_write_1(dev, PCCARD_CCR_STATUS,
|
||||||
|
PCCARD_CCR_STATUS_PWRDWN);
|
||||||
|
/*
|
||||||
|
* Linux axnet driver selects the internal phy for the ax88790
|
||||||
|
*/
|
||||||
|
ed_asic_outb(sc, ED_AX88X90_GPIO, ED_AX88X90_GPIO_INT_PHY);
|
||||||
|
ts = "AX88790";
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check to see if we have a MII PHY ID at any of the first 17
|
* 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
|
* locations. All AX88x90 devices have MII and a PHY, so we use
|
||||||
@ -657,20 +803,6 @@ ed_pccard_ax88x90(device_t dev, const struct ed_product *pp)
|
|||||||
return (ENXIO);
|
return (ENXIO);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ts = "AX88190";
|
|
||||||
if (ed_asic_inb(sc, ED_ASIX_TEST) != 0) {
|
|
||||||
/*
|
|
||||||
* AX88790 (and I think AX88190A) chips need to be
|
|
||||||
* powered down. There's an erratum that says we should
|
|
||||||
* power down the PHY for 2.5s, but this seems to power
|
|
||||||
* down the whole card. I'm unsure why this was done, but
|
|
||||||
* appears to be required for proper operation.
|
|
||||||
*/
|
|
||||||
pccard_ccr_write_1(dev, PCCARD_CCR_STATUS,
|
|
||||||
PCCARD_CCR_STATUS_PWRDWN);
|
|
||||||
ts = "AX88790";
|
|
||||||
}
|
|
||||||
sc->chip_type = ED_CHIP_TYPE_AX88190;
|
sc->chip_type = ED_CHIP_TYPE_AX88190;
|
||||||
error = ed_pccard_ax88x90_geteprom(sc);
|
error = ed_pccard_ax88x90_geteprom(sc);
|
||||||
if (error)
|
if (error)
|
||||||
@ -685,11 +817,9 @@ ed_pccard_ax88x90(device_t dev, const struct ed_product *pp)
|
|||||||
sc->type_str = ts;
|
sc->type_str = ts;
|
||||||
}
|
}
|
||||||
return (error);
|
return (error);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef ED_NO_MIIBUS
|
/* MII bit-twiddling routines for cards using AX88x90 chipset */
|
||||||
/* MII bit-twiddling routines for cards using Dlink chipset */
|
|
||||||
#define AX88X90_MIISET(sc, x) ed_asic_outb(sc, ED_AX88X90_MIIBUS, \
|
#define AX88X90_MIISET(sc, x) ed_asic_outb(sc, ED_AX88X90_MIIBUS, \
|
||||||
ed_asic_inb(sc, ED_AX88X90_MIIBUS) | (x))
|
ed_asic_inb(sc, ED_AX88X90_MIIBUS) | (x))
|
||||||
#define AX88X90_MIICLR(sc, x) ed_asic_outb(sc, ED_AX88X90_MIIBUS, \
|
#define AX88X90_MIICLR(sc, x) ed_asic_outb(sc, ED_AX88X90_MIIBUS, \
|
||||||
@ -731,16 +861,125 @@ ed_pccard_ax88x90_mii_readbits(struct ed_softc *sc, int nbits)
|
|||||||
AX88X90_MIISET(sc, ED_AX88X90_MII_CLK);
|
AX88X90_MIISET(sc, ED_AX88X90_MII_CLK);
|
||||||
DELAY(10);
|
DELAY(10);
|
||||||
val <<= 1;
|
val <<= 1;
|
||||||
if (ed_asic_inb(sc, ED_AX88X90_MIIBUS) & ED_AX88X90_MII_DATATIN)
|
if (ed_asic_inb(sc, ED_AX88X90_MIIBUS) & ED_AX88X90_MII_DATAIN)
|
||||||
val++;
|
val++;
|
||||||
AX88X90_MIICLR(sc, ED_AX88X90_MII_CLK);
|
AX88X90_MIICLR(sc, ED_AX88X90_MII_CLK);
|
||||||
DELAY(10);
|
DELAY(10);
|
||||||
}
|
}
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef ED_NO_MIIBUS
|
/*
|
||||||
|
* Special setup for TC5299J
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
ed_pccard_tc5299j(device_t dev, const struct ed_product *pp)
|
||||||
|
{
|
||||||
|
int error, i, id;
|
||||||
|
char *ts;
|
||||||
|
struct ed_softc *sc = device_get_softc(dev);
|
||||||
|
|
||||||
|
if (!(pp->flags & NE2000DVF_TC5299J))
|
||||||
|
return (ENXIO);
|
||||||
|
|
||||||
|
if (bootverbose)
|
||||||
|
device_printf(dev, "Checking Tc5299j\n");
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check to see if we have a MII PHY ID at any of the first 32
|
||||||
|
* locations. All TC5299J devices have MII and a PHY, so we use
|
||||||
|
* this to weed out chips that would otherwise make it through
|
||||||
|
* the tests we have after this point.
|
||||||
|
*/
|
||||||
|
sc->mii_readbits = ed_pccard_tc5299j_mii_readbits;
|
||||||
|
sc->mii_writebits = ed_pccard_tc5299j_mii_writebits;
|
||||||
|
for (i = 0; i < 32; i++) {
|
||||||
|
id = ed_miibus_readreg(dev, i, MII_PHYIDR1);
|
||||||
|
if (id != 0 && id != 0xffff)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (i == 32) {
|
||||||
|
sc->mii_readbits = 0;
|
||||||
|
sc->mii_writebits = 0;
|
||||||
|
return (ENXIO);
|
||||||
|
}
|
||||||
|
|
||||||
|
ts = "TC5299J";
|
||||||
|
error = ed_probe_Novell_generic(dev, device_get_flags(dev));
|
||||||
|
if (bootverbose)
|
||||||
|
device_printf(dev, "probe novel returns %d\n", error);
|
||||||
|
if (error != 0) {
|
||||||
|
sc->mii_readbits = 0;
|
||||||
|
sc->mii_writebits = 0;
|
||||||
|
return (error);
|
||||||
|
}
|
||||||
|
if (ed_pccard_rom_mac(dev, sc->enaddr) == 0) {
|
||||||
|
sc->mii_readbits = 0;
|
||||||
|
sc->mii_writebits = 0;
|
||||||
|
return (ENXIO);
|
||||||
|
}
|
||||||
|
sc->vendor = ED_VENDOR_NOVELL;
|
||||||
|
sc->type = ED_TYPE_NE2000;
|
||||||
|
sc->chip_type = ED_CHIP_TYPE_TC5299J;
|
||||||
|
sc->type_str = ts;
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* MII bit-twiddling routines for cards using TC5299J chipset */
|
||||||
|
#define TC5299J_MIISET(sc, x) ed_nic_outb(sc, ED_TC5299J_MIIBUS, \
|
||||||
|
ed_nic_inb(sc, ED_TC5299J_MIIBUS) | (x))
|
||||||
|
#define TC5299J_MIICLR(sc, x) ed_nic_outb(sc, ED_TC5299J_MIIBUS, \
|
||||||
|
ed_nic_inb(sc, ED_TC5299J_MIIBUS) & ~(x))
|
||||||
|
|
||||||
|
static void
|
||||||
|
ed_pccard_tc5299j_mii_reset(struct ed_softc *sc)
|
||||||
|
{
|
||||||
|
/* Do nothing! */
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
ed_pccard_tc5299j_mii_writebits(struct ed_softc *sc, u_int val, int nbits)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
uint8_t cr;
|
||||||
|
|
||||||
|
cr = ed_nic_inb(sc, ED_P0_CR);
|
||||||
|
ed_nic_outb(sc, ED_P0_CR, cr | ED_CR_PAGE_3);
|
||||||
|
|
||||||
|
TC5299J_MIICLR(sc, ED_TC5299J_MII_DIROUT);
|
||||||
|
for (i = nbits - 1; i >= 0; i--) {
|
||||||
|
if ((val >> i) & 1)
|
||||||
|
TC5299J_MIISET(sc, ED_TC5299J_MII_DATAOUT);
|
||||||
|
else
|
||||||
|
TC5299J_MIICLR(sc, ED_TC5299J_MII_DATAOUT);
|
||||||
|
TC5299J_MIISET(sc, ED_TC5299J_MII_CLK);
|
||||||
|
TC5299J_MIICLR(sc, ED_TC5299J_MII_CLK);
|
||||||
|
}
|
||||||
|
ed_nic_outb(sc, ED_P0_CR, cr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static u_int
|
||||||
|
ed_pccard_tc5299j_mii_readbits(struct ed_softc *sc, int nbits)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
u_int val = 0;
|
||||||
|
uint8_t cr;
|
||||||
|
|
||||||
|
cr = ed_nic_inb(sc, ED_P0_CR);
|
||||||
|
ed_nic_outb(sc, ED_P0_CR, cr | ED_CR_PAGE_3);
|
||||||
|
|
||||||
|
TC5299J_MIISET(sc, ED_TC5299J_MII_DIROUT);
|
||||||
|
for (i = nbits - 1; i >= 0; i--) {
|
||||||
|
TC5299J_MIISET(sc, ED_TC5299J_MII_CLK);
|
||||||
|
val <<= 1;
|
||||||
|
if (ed_nic_inb(sc, ED_TC5299J_MIIBUS) & ED_TC5299J_MII_DATAIN)
|
||||||
|
val++;
|
||||||
|
TC5299J_MIICLR(sc, ED_TC5299J_MII_CLK);
|
||||||
|
}
|
||||||
|
ed_nic_outb(sc, ED_P0_CR, cr);
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* MII bus support routines.
|
* MII bus support routines.
|
||||||
*/
|
*/
|
||||||
@ -793,7 +1032,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, data, ED_MII_DATA_BITS);
|
||||||
(*sc->mii_writebits)(sc, ED_MII_IDLE, ED_MII_IDLE_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[] = {
|
static device_method_t ed_pccard_methods[] = {
|
||||||
/* Device interface */
|
/* Device interface */
|
||||||
@ -801,14 +1079,12 @@ static device_method_t ed_pccard_methods[] = {
|
|||||||
DEVMETHOD(device_attach, ed_pccard_attach),
|
DEVMETHOD(device_attach, ed_pccard_attach),
|
||||||
DEVMETHOD(device_detach, ed_detach),
|
DEVMETHOD(device_detach, ed_detach),
|
||||||
|
|
||||||
#ifndef ED_NO_MIIBUS
|
|
||||||
/* Bus interface */
|
/* Bus interface */
|
||||||
DEVMETHOD(bus_child_detached, ed_child_detached),
|
DEVMETHOD(bus_child_detached, ed_child_detached),
|
||||||
|
|
||||||
/* MII interface */
|
/* MII interface */
|
||||||
DEVMETHOD(miibus_readreg, ed_miibus_readreg),
|
DEVMETHOD(miibus_readreg, ed_miibus_readreg),
|
||||||
DEVMETHOD(miibus_writereg, ed_miibus_writereg),
|
DEVMETHOD(miibus_writereg, ed_miibus_writereg),
|
||||||
#endif
|
|
||||||
|
|
||||||
{ 0, 0 }
|
{ 0, 0 }
|
||||||
};
|
};
|
||||||
@ -820,6 +1096,6 @@ static driver_t ed_pccard_driver = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
DRIVER_MODULE(ed, pccard, ed_pccard_driver, ed_devclass, 0, 0);
|
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);
|
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);
|
||||||
|
@ -41,6 +41,7 @@ __FBSDID("$FreeBSD$");
|
|||||||
#include <dev/pci/pcivar.h>
|
#include <dev/pci/pcivar.h>
|
||||||
|
|
||||||
#include <dev/ed/if_edvar.h>
|
#include <dev/ed/if_edvar.h>
|
||||||
|
#include <dev/ed/rtl80x9reg.h>
|
||||||
|
|
||||||
static struct _pcsid
|
static struct _pcsid
|
||||||
{
|
{
|
||||||
@ -48,7 +49,7 @@ static struct _pcsid
|
|||||||
const char *desc;
|
const char *desc;
|
||||||
} pci_ids[] =
|
} pci_ids[] =
|
||||||
{
|
{
|
||||||
{ 0x802910ec, "RealTek 8029" },
|
{ ED_RTL8029_PCI_ID, "RealTek 8029" },
|
||||||
{ 0x50004a14, "NetVin 5000" },
|
{ 0x50004a14, "NetVin 5000" },
|
||||||
{ 0x09401050, "ProLAN" },
|
{ 0x09401050, "ProLAN" },
|
||||||
{ 0x140111f6, "Compex" },
|
{ 0x140111f6, "Compex" },
|
||||||
@ -83,7 +84,10 @@ ed_pci_attach(device_t dev)
|
|||||||
int flags = 0;
|
int flags = 0;
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
error = ed_probe_Novell(dev, PCIR_BAR(0), flags);
|
if (pci_get_devid(dev) == ED_RTL8029_PCI_ID)
|
||||||
|
error = ed_probe_RTL80x9(dev, PCIR_BAR(0), flags);
|
||||||
|
else
|
||||||
|
error = ed_probe_Novell(dev, PCIR_BAR(0), flags);
|
||||||
if (error) {
|
if (error) {
|
||||||
ed_release_resources(dev);
|
ed_release_resources(dev);
|
||||||
return (error);
|
return (error);
|
||||||
|
@ -174,7 +174,7 @@
|
|||||||
* 0 0 0
|
* 0 0 0
|
||||||
* 0 1 1
|
* 0 1 1
|
||||||
* 1 0 2
|
* 1 0 2
|
||||||
* 1 1 reserved
|
* 1 1 3 (some chips it is reserved)
|
||||||
*/
|
*/
|
||||||
#define ED_CR_PS0 0x40
|
#define ED_CR_PS0 0x40
|
||||||
#define ED_CR_PS1 0x80
|
#define ED_CR_PS1 0x80
|
||||||
@ -182,6 +182,7 @@
|
|||||||
#define ED_CR_PAGE_0 0x00 /* (for consistency) */
|
#define ED_CR_PAGE_0 0x00 /* (for consistency) */
|
||||||
#define ED_CR_PAGE_1 0x40
|
#define ED_CR_PAGE_1 0x40
|
||||||
#define ED_CR_PAGE_2 0x80
|
#define ED_CR_PAGE_2 0x80
|
||||||
|
#define ED_CR_PAGE_3 0xc0
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Interrupt Status Register (ISR) definitions
|
* Interrupt Status Register (ISR) definitions
|
||||||
@ -1066,16 +1067,14 @@ struct ed_ring {
|
|||||||
* Chip types.
|
* Chip types.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define ED_CHIP_TYPE_DP8390 0x00
|
#define ED_CHIP_TYPE_DP8390 0
|
||||||
#define ED_CHIP_TYPE_WD790 0x01
|
#define ED_CHIP_TYPE_WD790 1
|
||||||
#define ED_CHIP_TYPE_AX88190 0x02
|
#define ED_CHIP_TYPE_AX88190 2
|
||||||
#define ED_CHIP_TYPE_DL10019 0x03
|
#define ED_CHIP_TYPE_DL10019 3
|
||||||
#define ED_CHIP_TYPE_DL10022 0x04
|
#define ED_CHIP_TYPE_DL10022 4
|
||||||
|
#define ED_CHIP_TYPE_TC5299J 5
|
||||||
/*
|
#define ED_CHIP_TYPE_RTL8019 6
|
||||||
* Test for AX88790 vs 88190 cards.
|
#define ED_CHIP_TYPE_RTL8029 7
|
||||||
*/
|
|
||||||
#define ED_ASIX_TEST 0x05
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* MII bus definitions. These are common to both DL100xx and AX88x90
|
* MII bus definitions. These are common to both DL100xx and AX88x90
|
||||||
@ -1095,23 +1094,3 @@ struct ed_ring {
|
|||||||
#define ED_MII_DATA_BITS 16
|
#define ED_MII_DATA_BITS 16
|
||||||
#define ED_MII_ACK_BITS 1
|
#define ED_MII_ACK_BITS 1
|
||||||
#define ED_MII_IDLE_BITS 1
|
#define ED_MII_IDLE_BITS 1
|
||||||
|
|
||||||
/* Dlink chipset used on some Netgear and Dlink PCMCIA cards */
|
|
||||||
#define ED_DL100XX_MIIBUS 0x0c /* MII bus register on ASIC */
|
|
||||||
|
|
||||||
#define ED_DL100XX_MII_RESET1 0x04
|
|
||||||
#define ED_DL100XX_MII_RESET2 0x08
|
|
||||||
|
|
||||||
#define ED_DL100XX_MII_DATATIN 0x10
|
|
||||||
#define ED_DL100XX_MII_DIROUT_22 0x20
|
|
||||||
#define ED_DL100XX_MII_DIROUT_19 0x10
|
|
||||||
#define ED_DL100XX_MII_DATAOUT 0x40
|
|
||||||
#define ED_DL100XX_MII_CLK 0x80
|
|
||||||
|
|
||||||
/* AX88x90 based miibus defines */
|
|
||||||
#define ED_AX88X90_MIIBUS 0x04 /* MII bus register on ASIC */
|
|
||||||
|
|
||||||
#define ED_AX88X90_MII_DATAOUT 0x08
|
|
||||||
#define ED_AX88X90_MII_DATATIN 0x04
|
|
||||||
#define ED_AX88X90_MII_DIROUT 0x02
|
|
||||||
#define ED_AX88X90_MII_CLK 0x01
|
|
||||||
|
@ -61,10 +61,14 @@ struct ed_softc {
|
|||||||
struct resource* irq_res; /* resource for irq */
|
struct resource* irq_res; /* resource for irq */
|
||||||
void* irq_handle; /* handle for irq handler */
|
void* irq_handle; /* handle for irq handler */
|
||||||
int modem_rid; /* resource ID for modem part of device */
|
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. */
|
device_t miibus; /* MII bus for cards with MII. */
|
||||||
void (*mii_writebits)(struct ed_softc *, u_int, int);
|
void (*mii_writebits)(struct ed_softc *, u_int, int);
|
||||||
u_int (*mii_readbits)(struct ed_softc *, int);
|
u_int (*mii_readbits)(struct ed_softc *, int);
|
||||||
struct callout tick_ch;
|
struct callout tick_ch;
|
||||||
|
void (*sc_tick)(void *);
|
||||||
void (*readmem)(struct ed_softc *sc, bus_size_t src, uint8_t *dst,
|
void (*readmem)(struct ed_softc *sc, bus_size_t src, uint8_t *dst,
|
||||||
uint16_t amount);
|
uint16_t amount);
|
||||||
|
|
||||||
@ -190,6 +194,7 @@ int ed_alloc_irq(device_t, int, int);
|
|||||||
int ed_probe_generic8390(struct ed_softc *);
|
int ed_probe_generic8390(struct ed_softc *);
|
||||||
int ed_probe_WD80x3(device_t, int, int);
|
int ed_probe_WD80x3(device_t, int, int);
|
||||||
int ed_probe_WD80x3_generic(device_t, int, uint16_t *[]);
|
int ed_probe_WD80x3_generic(device_t, int, uint16_t *[]);
|
||||||
|
int ed_probe_RTL80x9(device_t, int, int);
|
||||||
#ifdef ED_3C503
|
#ifdef ED_3C503
|
||||||
int ed_probe_3Com(device_t, int, int);
|
int ed_probe_3Com(device_t, int, int);
|
||||||
#endif
|
#endif
|
||||||
@ -212,11 +217,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_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_readmem(struct ed_softc *, bus_size_t, uint8_t *, uint16_t);
|
||||||
void ed_pio_writemem(struct ed_softc *, uint8_t *, uint16_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 */
|
/* The following is unsatisfying XXX */
|
||||||
#ifdef ED_HPP
|
#ifdef ED_HPP
|
||||||
|
@ -3,15 +3,16 @@
|
|||||||
.PATH: ${.CURDIR}/../../dev/ed
|
.PATH: ${.CURDIR}/../../dev/ed
|
||||||
|
|
||||||
KMOD= if_ed
|
KMOD= if_ed
|
||||||
SRCS= if_ed.c if_ed_pccard.c if_ed_pci.c if_ed_novell.c if_ed_wd80x3.c
|
SRCS= if_ed.c
|
||||||
|
SRCS+= if_ed_novell.c if_ed_wd80x3.c if_ed_rtl80x9.c isa_if.h
|
||||||
.if ${MACHINE} == "pc98"
|
.if ${MACHINE} == "pc98"
|
||||||
SRCS+= if_ed_cbus.c
|
SRCS+= if_ed_cbus.c
|
||||||
.else
|
.else
|
||||||
SRCS+= if_ed_isa.c if_ed_3c503.c if_ed_hpp.c if_ed_sic.c
|
SRCS+= if_ed_isa.c if_ed_3c503.c if_ed_hpp.c if_ed_sic.c
|
||||||
.endif
|
.endif
|
||||||
|
SRCS+= if_ed_pccard.c pccarddevs.h card_if.h
|
||||||
|
SRCS+= if_ed_pci.c pci_if.h
|
||||||
|
|
||||||
SRCS+= opt_ed.h opt_bdg.h bus_if.h card_if.h device_if.h isa_if.h pci_if.h \
|
SRCS+= opt_ed.h bus_if.h device_if.h miibus_if.h
|
||||||
miibus_if.h pccarddevs.h
|
|
||||||
|
|
||||||
.include <bsd.kmod.mk>
|
.include <bsd.kmod.mk>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user