diff options
Diffstat (limited to 'sys/dev/ed')
-rw-r--r-- | sys/dev/ed/ax88x90reg.h | 38 | ||||
-rw-r--r-- | sys/dev/ed/dl100xxreg.h | 42 | ||||
-rw-r--r-- | sys/dev/ed/if_ed_isa.c | 8 | ||||
-rw-r--r-- | sys/dev/ed/if_ed_pccard.c | 213 | ||||
-rw-r--r-- | sys/dev/ed/if_ed_pci.c | 8 | ||||
-rw-r--r-- | sys/dev/ed/if_ed_rtl80x9.c | 211 | ||||
-rw-r--r-- | sys/dev/ed/if_edreg.h | 41 | ||||
-rw-r--r-- | sys/dev/ed/if_edvar.h | 1 | ||||
-rw-r--r-- | sys/dev/ed/rtl80x9reg.h | 58 | ||||
-rw-r--r-- | sys/dev/ed/tc5299jreg.h | 38 |
10 files changed, 591 insertions, 67 deletions
diff --git a/sys/dev/ed/ax88x90reg.h b/sys/dev/ed/ax88x90reg.h new file mode 100644 index 0000000..9d2eeed --- /dev/null +++ b/sys/dev/ed/ax88x90reg.h @@ -0,0 +1,38 @@ +/*- + * Copyright (c) 2005, M. Warner Losh. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice unmodified, this list of conditions, and the following + * disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +/* AX88x90 based miibus defines */ +#define ED_AX88X90_MIIBUS 0x04 /* MII bus register on ASIC */ +#define ED_AX88X90_MII_CLK 0x01 +#define ED_AX88X90_MII_DIROUT 0x02 +#define ED_AX88X90_MII_DATAIN 0x04 +#define ED_AX88X90_MII_DATAOUT 0x08 +#define ED_AX88X90_TEST 0x05 /* "test" register on asic */ +#define ED_AX88X90_GPIO 0x07 /* GPIO pins */ +#define ED_AX88X90_GPIO_INT_PHY 0x10 diff --git a/sys/dev/ed/dl100xxreg.h b/sys/dev/ed/dl100xxreg.h new file mode 100644 index 0000000..a4659b0 --- /dev/null +++ b/sys/dev/ed/dl100xxreg.h @@ -0,0 +1,42 @@ +/*- + * Copyright (c) 2005, M. Warner Losh. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice unmodified, this list of conditions, and the following + * disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +/* Dlink chipset used on some Netgear and Dlink PCMCIA cards */ +#define ED_DL100XX_MIIBUS 0x0c /* MII bus register on ASIC */ +#define ED_DL100XX_DIAG 0x0d +#define ED_DL100XX_COLLISON_DIS 4 /* Disable collision detection */ + +#define ED_DL100XX_MII_RESET1 0x04 +#define ED_DL100XX_MII_RESET2 0x08 + +#define ED_DL100XX_MII_DATAIN 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 diff --git a/sys/dev/ed/if_ed_isa.c b/sys/dev/ed/if_ed_isa.c index fcf9b20..ec970e1 100644 --- a/sys/dev/ed/if_ed_isa.c +++ b/sys/dev/ed/if_ed_isa.c @@ -114,6 +114,11 @@ ed_isa_probe(device_t dev) goto end; ed_release_resources(dev); + error = ed_probe_RTL80x9(dev, 0, flags); + if (error == 0) + goto end; + ed_release_resources(dev); + #ifdef ED_3C503 error = ed_probe_3Com(dev, 0, flags); if (error == 0) @@ -166,6 +171,9 @@ ed_isa_attach(device_t dev) return (error); } + if (sc->chip_type == ED_CHIP_TYPE_RTL8029) + ed_Novell_read_mac(sc); + #ifdef ED_HPP if (sc->vendor == ED_VENDOR_HP && sc->type == ED_TYPE_HP_PCLANPLUS) sc->readmem = ed_hpp_readmem; diff --git a/sys/dev/ed/if_ed_pccard.c b/sys/dev/ed/if_ed_pccard.c index 9c3cd9a..0c36b61 100644 --- a/sys/dev/ed/if_ed_pccard.c +++ b/sys/dev/ed/if_ed_pccard.c @@ -64,7 +64,8 @@ * 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 + * TMI tc5299 10/100 chip, has a different MII interaction than + * dl100xx and ax88x90. * * EN5017A, EN5020 no data, but very popular * Other chips? @@ -92,6 +93,9 @@ #include <dev/ed/if_edreg.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/pccardreg.h> #include <dev/pccard/pccard_cis.h> @@ -104,18 +108,15 @@ #include "pccarddevs.h" /* - * PC Cards should be using a network specific FUNCE in the CIS to - * communicate their MAC address to the driver. However, there are a - * large number of NE-2000ish PC Cards that don't do this. Nearly all - * of them store the MAC address at a fixed offset into attribute - * memory, without any reference at all appearing in the CIS. And - * nearly all of those store it at the same location. + * NE-2000 based PC Cards have a number of ways to get the MAC address. + * Some cards encode this as a FUNCE. Others have this in the ROMs the + * same way that ISA cards do. Some have it encoded in the attribute + * memory somewhere that isn't in the CIS. Some new chipsets have it + * in special registers in the ASIC part of the chip. * - * This applies only to the older, NE-2000 compatbile cards. The newer - * cards based on the AX88x90 or DL100XX chipsets have a specific place - * to look for MAC information. And only to those NE-2000 compatible cards - * that don't the NE-2000 compatible thing of placing the PROM contents - * starting at location 0 of memory. + * For those cards that have the MAC adress stored in attribute memory, + * nearly all of them have it at a fixed offset (0xff0). We use that + * offset as a source of last resource if other offsets have failed. */ #define ED_DEFAULT_MAC_OFFSET 0xff0 @@ -124,9 +125,10 @@ static const struct ed_product { int flags; #define NE2000DVF_DL100XX 0x0001 /* chip is D-Link DL10019/22 */ #define NE2000DVF_AX88X90 0x0002 /* chip is ASIX AX88[17]90 */ -#define NE2000DVF_ENADDR 0x0004 /* Get MAC from attr mem */ -#define NE2000DVF_ANYFUNC 0x0008 /* Allow any function type */ -#define NE2000DVF_MODEM 0x0010 /* Has a modem/serial */ +#define NE2000DVF_TC5299J 0x0004 /* chip is Tamarack TC5299J */ +#define NE2000DVF_ENADDR 0x0100 /* Get MAC from attr mem */ +#define NE2000DVF_ANYFUNC 0x0200 /* Allow any function type */ +#define NE2000DVF_MODEM 0x0400 /* Has a modem/serial */ int enoff; } ed_pccard_products[] = { { PCMCIA_CARD(ACCTON, EN2212), 0}, @@ -194,7 +196,7 @@ static const struct ed_product { NE2000DVF_ANYFUNC | NE2000DVF_AX88X90 | NE2000DVF_MODEM}, { PCMCIA_CARD(RACORE, ETHERNET), 0}, { 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(RPTI, EP400), 0}, { PCMCIA_CARD(RPTI, EP401), 0}, @@ -228,15 +230,21 @@ 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, 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 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); 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 *); +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) @@ -388,11 +396,23 @@ 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) { + printf("'22: state change up: %x %x\n", + mii->mii_media_status, mii->mii_media_active); + 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); } @@ -448,6 +468,8 @@ ed_pccard_attach(device_t dev) if (error != 0) error = ed_pccard_ax88x90(dev, pp); if (error != 0) + error = ed_pccard_tc5299j(dev, pp); + if (error != 0) error = ed_probe_Novell_generic(dev, device_get_flags(dev)); if (error) goto bad; @@ -528,6 +550,14 @@ ed_pccard_attach(device_t dev) 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; @@ -662,7 +692,7 @@ ed_pccard_dl100xx_mii_readbits(struct ed_softc *sc, int nbits) DL100XX_MIISET(sc, ED_DL100XX_MII_CLK); DELAY(10); 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++; DL100XX_MIICLR(sc, ED_DL100XX_MII_CLK); DELAY(10); @@ -740,6 +770,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_IOBASE1, (iobase >> 8) & 0xff); + ts = "AX88190"; + if (ed_asic_inb(sc, ED_AX88X90_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); + /* + * 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 * locations. All AX88x90 devices have MII and a PHY, so we use @@ -759,20 +807,6 @@ ed_pccard_ax88x90(device_t dev, const struct ed_product *pp) 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; error = ed_pccard_ax88x90_geteprom(sc); if (error) @@ -789,7 +823,7 @@ ed_pccard_ax88x90(device_t dev, const struct ed_product *pp) return (error); } -/* MII bit-twiddling routines for cards using Dlink chipset */ +/* MII bit-twiddling routines for cards using AX88x90 chipset */ #define AX88X90_MIISET(sc, x) ed_asic_outb(sc, ED_AX88X90_MIIBUS, \ ed_asic_inb(sc, ED_AX88X90_MIIBUS) | (x)) #define AX88X90_MIICLR(sc, x) ed_asic_outb(sc, ED_AX88X90_MIIBUS, \ @@ -831,7 +865,7 @@ ed_pccard_ax88x90_mii_readbits(struct ed_softc *sc, int nbits) AX88X90_MIISET(sc, ED_AX88X90_MII_CLK); DELAY(10); 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++; AX88X90_MIICLR(sc, ED_AX88X90_MII_CLK); DELAY(10); @@ -840,6 +874,117 @@ ed_pccard_ax88x90_mii_readbits(struct ed_softc *sc, int nbits) } /* + * 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. */ static int diff --git a/sys/dev/ed/if_ed_pci.c b/sys/dev/ed/if_ed_pci.c index 2a88576..bdb3e73 100644 --- a/sys/dev/ed/if_ed_pci.c +++ b/sys/dev/ed/if_ed_pci.c @@ -41,6 +41,7 @@ __FBSDID("$FreeBSD$"); #include <dev/pci/pcivar.h> #include <dev/ed/if_edvar.h> +#include <dev/ed/rtl80x9reg.h> static struct _pcsid { @@ -48,7 +49,7 @@ static struct _pcsid const char *desc; } pci_ids[] = { - { 0x802910ec, "RealTek 8029" }, + { ED_RTL8029_PCI_ID, "RealTek 8029" }, { 0x50004a14, "NetVin 5000" }, { 0x09401050, "ProLAN" }, { 0x140111f6, "Compex" }, @@ -83,7 +84,10 @@ ed_pci_attach(device_t dev) int flags = 0; 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) { ed_release_resources(dev); return (error); diff --git a/sys/dev/ed/if_ed_rtl80x9.c b/sys/dev/ed/if_ed_rtl80x9.c new file mode 100644 index 0000000..f2c1a43 --- /dev/null +++ b/sys/dev/ed/if_ed_rtl80x9.c @@ -0,0 +1,211 @@ +/*- + * Copyright (c) 2003, David Madole + * All rights reserved. + * Copyright (c) 2005, M. Warner Losh. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice unmodified, this list of conditions, and the following + * disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * Based on patches subitted by: David Madole, edited by M. Warner Losh. + */ + + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include "opt_ed.h" + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/sockio.h> +#include <sys/mbuf.h> +#include <sys/kernel.h> +#include <sys/socket.h> +#include <sys/syslog.h> + +#include <sys/bus.h> + +#include <machine/bus.h> +#include <sys/rman.h> +#include <machine/resource.h> + +#include <net/ethernet.h> +#include <net/if.h> +#include <net/if_arp.h> +#include <net/if_dl.h> +#include <net/if_mib.h> +#include <net/if_media.h> + +#include <net/bpf.h> + +#include <dev/ed/if_edreg.h> +#include <dev/ed/if_edvar.h> +#include <dev/ed/rtl80x9reg.h> + +static int ed_rtl_set_media(struct ifnet *ifp); +static void ed_rtl_get_media(struct ifnet *ifp, struct ifmediareq *); + +static int +ed_rtl80x9_media_ioctl(struct ed_softc *sc, struct ifreq *ifr, u_long command) +{ + return (ifmedia_ioctl(sc->ifp, ifr, &sc->ifmedia, command)); +} + +int +ed_probe_RTL80x9(device_t dev, int port_rid, int flags) +{ + struct ed_softc *sc = device_get_softc(dev); + int error; + + if ((error = ed_alloc_port(dev, port_rid, ED_NOVELL_IO_PORTS))) + return (error); + + if (!ed_probe_generic8390(sc)) + return (ENXIO); + + if (ed_nic_inb(sc, ED_P0_CR) & (ED_CR_PS0 | ED_CR_PS1)) + ed_nic_outb(sc, ED_P0_CR, ED_CR_RD2 | ED_CR_STP); + + if (ed_nic_inb(sc, ED_RTL80X9_80X9ID0) != ED_RTL80X9_ID0) + return (ENXIO); + + switch (ed_nic_inb(sc, ED_RTL80X9_80X9ID1)) { + case ED_RTL8019_ID1: + sc->chip_type = ED_CHIP_TYPE_RTL8019; + break; + case ED_RTL8029_ID1: + sc->chip_type = ED_CHIP_TYPE_RTL8029; + break; + default: + return (ENXIO); + } + + sc->asic_offset = ED_NOVELL_ASIC_OFFSET; + sc->nic_offset = ED_NOVELL_NIC_OFFSET; + + if ((error = ed_probe_Novell_generic(dev, flags))) + return (error); + + sc->sc_media_ioctl = &ed_rtl80x9_media_ioctl; + ifmedia_init(&sc->ifmedia, 0, ed_rtl_set_media, ed_rtl_get_media); + + ifmedia_add(&sc->ifmedia, IFM_ETHER | IFM_10_T | IFM_FDX, 0, 0); + ifmedia_add(&sc->ifmedia, IFM_ETHER | IFM_10_T, 0, 0); + ifmedia_add(&sc->ifmedia, IFM_ETHER | IFM_10_2, 0, 0); + ifmedia_add(&sc->ifmedia, IFM_ETHER | IFM_10_5, 0, 0); + ifmedia_add(&sc->ifmedia, IFM_ETHER | IFM_AUTO, 0, 0); + + ed_nic_outb(sc, ED_P0_CR, ED_CR_RD2 | ED_CR_PAGE_3 | ED_CR_STP); + + switch (ed_nic_inb(sc, ED_RTL80X9_CONFIG2) & ED_RTL80X9_CF2_MEDIA) { + case ED_RTL80X9_CF2_AUTO: + ifmedia_set(&sc->ifmedia, IFM_ETHER | IFM_AUTO); + break; + case ED_RTL80X9_CF2_10_5: + ifmedia_set(&sc->ifmedia, IFM_ETHER | IFM_10_5); + break; + case ED_RTL80X9_CF2_10_2: + ifmedia_set(&sc->ifmedia, IFM_ETHER | IFM_10_2); + break; + case ED_RTL80X9_CF2_10_T: + ifmedia_set(&sc->ifmedia, IFM_ETHER | IFM_10_T | + (ed_nic_inb(sc, ED_RTL80X9_CONFIG3) + & ED_RTL80X9_CF3_FUDUP) ? IFM_FDX : 0); + break; + } + return (0); +} + +static int +ed_rtl_set_media(struct ifnet *ifp) +{ + struct ed_softc *sc; + + sc = ifp->if_softc; + ED_LOCK(sc); + ed_nic_outb(sc, ED_P0_CR, sc->cr_proto | ED_CR_PAGE_3 + | (ed_nic_inb(sc, ED_P0_CR) & (ED_CR_STA | ED_CR_STP))); + + switch(IFM_SUBTYPE(sc->ifmedia.ifm_cur->ifm_media)) { + case IFM_10_T: + ed_nic_outb(sc, ED_RTL80X9_CONFIG2, ED_RTL80X9_CF2_10_T + | (ed_nic_inb(sc, ED_RTL80X9_CONFIG2) + & ~ED_RTL80X9_CF2_MEDIA)); + break; + case IFM_10_2: + ed_nic_outb(sc, ED_RTL80X9_CONFIG2, ED_RTL80X9_CF2_10_2 + | (ed_nic_inb(sc, ED_RTL80X9_CONFIG2) + & ~ED_RTL80X9_CF2_MEDIA)); + break; + case IFM_10_5: + ed_nic_outb(sc, ED_RTL80X9_CONFIG2, ED_RTL80X9_CF2_10_5 + | (ed_nic_inb(sc, ED_RTL80X9_CONFIG2) + & ~ED_RTL80X9_CF2_MEDIA)); + break; + case IFM_AUTO: + ed_nic_outb(sc, ED_RTL80X9_CONFIG2, ED_RTL80X9_CF2_AUTO + | (ed_nic_inb(sc, ED_RTL80X9_CONFIG2) + & ~ED_RTL80X9_CF2_MEDIA)); + break; + } + ed_nic_outb(sc, ED_RTL80X9_CONFIG3, + (sc->ifmedia.ifm_cur->ifm_media & IFM_FDX) ? + (ed_nic_inb(sc, ED_RTL80X9_CONFIG3) | ED_RTL80X9_CF3_FUDUP) : + (ed_nic_inb(sc, ED_RTL80X9_CONFIG3) & ~ED_RTL80X9_CF3_FUDUP)); + + ED_UNLOCK(sc); + return (0); +} + +static void +ed_rtl_get_media(struct ifnet *ifp, struct ifmediareq *imr) +{ + struct ed_softc *sc; + + sc = ifp->if_softc; + imr->ifm_active = sc->ifmedia.ifm_cur->ifm_media; + + + if (IFM_SUBTYPE(imr->ifm_active) == IFM_AUTO) { + ED_LOCK(sc); + ed_nic_outb(sc, ED_P0_CR, sc->cr_proto | ED_CR_PAGE_3 | + (ed_nic_inb(sc, ED_P0_CR) & (ED_CR_STA | ED_CR_STP))); + + switch (ed_nic_inb(sc, ED_RTL80X9_CONFIG0) + & (ED_CHIP_TYPE_RTL8029 ? ED_RTL80X9_CF0_BNC + : (ED_RTL80X9_CF0_AUI | ED_RTL80X9_CF0_BNC))) { + case ED_RTL80X9_CF0_BNC: + imr->ifm_active |= IFM_10_2; + break; + case ED_RTL80X9_CF0_AUI: + imr->ifm_active |= IFM_10_5; + break; + default: + imr->ifm_active |= IFM_10_T; + break; + } + ED_UNLOCK(sc); + } + imr->ifm_status = 0; +} + diff --git a/sys/dev/ed/if_edreg.h b/sys/dev/ed/if_edreg.h index f73b1e1..3f2b719 100644 --- a/sys/dev/ed/if_edreg.h +++ b/sys/dev/ed/if_edreg.h @@ -174,7 +174,7 @@ * 0 0 0 * 0 1 1 * 1 0 2 - * 1 1 reserved + * 1 1 3 (some chips it is reserved) */ #define ED_CR_PS0 0x40 #define ED_CR_PS1 0x80 @@ -182,6 +182,7 @@ #define ED_CR_PAGE_0 0x00 /* (for consistency) */ #define ED_CR_PAGE_1 0x40 #define ED_CR_PAGE_2 0x80 +#define ED_CR_PAGE_3 0xc0 /* * Interrupt Status Register (ISR) definitions @@ -1066,16 +1067,14 @@ struct ed_ring { * Chip types. */ -#define ED_CHIP_TYPE_DP8390 0x00 -#define ED_CHIP_TYPE_WD790 0x01 -#define ED_CHIP_TYPE_AX88190 0x02 -#define ED_CHIP_TYPE_DL10019 0x03 -#define ED_CHIP_TYPE_DL10022 0x04 - -/* - * Test for AX88790 vs 88190 cards. - */ -#define ED_ASIX_TEST 0x05 +#define ED_CHIP_TYPE_DP8390 0 +#define ED_CHIP_TYPE_WD790 1 +#define ED_CHIP_TYPE_AX88190 2 +#define ED_CHIP_TYPE_DL10019 3 +#define ED_CHIP_TYPE_DL10022 4 +#define ED_CHIP_TYPE_TC5299J 5 +#define ED_CHIP_TYPE_RTL8019 6 +#define ED_CHIP_TYPE_RTL8029 7 /* * 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_ACK_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 diff --git a/sys/dev/ed/if_edvar.h b/sys/dev/ed/if_edvar.h index 4e8afe8..4c9b95b 100644 --- a/sys/dev/ed/if_edvar.h +++ b/sys/dev/ed/if_edvar.h @@ -194,6 +194,7 @@ int ed_alloc_irq(device_t, int, int); int ed_probe_generic8390(struct ed_softc *); int ed_probe_WD80x3(device_t, int, int); int ed_probe_WD80x3_generic(device_t, int, uint16_t *[]); +int ed_probe_RTL80x9(device_t, int, int); #ifdef ED_3C503 int ed_probe_3Com(device_t, int, int); #endif diff --git a/sys/dev/ed/rtl80x9reg.h b/sys/dev/ed/rtl80x9reg.h new file mode 100644 index 0000000..2120fcf --- /dev/null +++ b/sys/dev/ed/rtl80x9reg.h @@ -0,0 +1,58 @@ +/*- + * Copyright (c) 2003, David Madole + * All rights reserved. + * Copyright (c) 2005, M. Warner Losh. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice unmodified, this list of conditions, and the following + * disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * Based on patches subitted by: David Madole, edited by M. Warner Losh. + * + * $FreeBSD$ + */ + +/* + * RTL8019/8029 Specific Registers + */ + +#define ED_RTL80X9_CONFIG0 0x03 +#define ED_RTL80X9_CONFIG2 0x05 +#define ED_RTL80X9_CONFIG3 0x06 +#define ED_RTL80X9_80X9ID0 0x0a +#define ED_RTL80X9_ID0 0x50 +#define ED_RTL80X9_80X9ID1 0x0b +#define ED_RTL8019_ID1 0x70 +#define ED_RTL8029_ID1 0x43 + +#define ED_RTL80X9_CF0_BNC 0x04 +#define ED_RTL80X9_CF0_AUI 0x20 + +#define ED_RTL80X9_CF2_MEDIA 0xc0 +#define ED_RTL80X9_CF2_AUTO 0x00 +#define ED_RTL80X9_CF2_10_T 0x40 +#define ED_RTL80X9_CF2_10_5 0x80 +#define ED_RTL80X9_CF2_10_2 0xc0 + +#define ED_RTL80X9_CF3_FUDUP 0x40 + +#define ED_RTL8029_PCI_ID 0x802910ec diff --git a/sys/dev/ed/tc5299jreg.h b/sys/dev/ed/tc5299jreg.h new file mode 100644 index 0000000..6fb7939 --- /dev/null +++ b/sys/dev/ed/tc5299jreg.h @@ -0,0 +1,38 @@ +/*- + * Copyright (c) 2005, M. Warner Losh. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice unmodified, this list of conditions, and the following + * disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +/* Tamarack TC5299J */ +#define ED_TC5299J_CRA 0x0a /* Config Register A */ +#define ED_TC5299J_CRB 0x0b /* Config Register B */ +#define ED_TC5299J_MIIBUS 0x03 /* MII bus register on in bank 3 */ + +#define ED_TC5299J_MII_CLK 0x01 +#define ED_TC5299J_MII_DATAOUT 0x02 +#define ED_TC5299J_MII_DIROUT 0x04 +#define ED_TC5299J_MII_DATAIN 0x08 |