From owner-freebsd-bugs Sun Jan 5 10: 0:27 2003 Delivered-To: freebsd-bugs@hub.freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 1C39537B401 for ; Sun, 5 Jan 2003 10:00:19 -0800 (PST) Received: from freefall.freebsd.org (freefall.freebsd.org [216.136.204.21]) by mx1.FreeBSD.org (Postfix) with ESMTP id 9218F43ED8 for ; Sun, 5 Jan 2003 10:00:18 -0800 (PST) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (gnats@localhost [127.0.0.1]) by freefall.freebsd.org (8.12.6/8.12.6) with ESMTP id h05I0INS096956 for ; Sun, 5 Jan 2003 10:00:18 -0800 (PST) (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.12.6/8.12.6/Submit) id h05I0Ic3096955; Sun, 5 Jan 2003 10:00:18 -0800 (PST) Date: Sun, 5 Jan 2003 10:00:18 -0800 (PST) Message-Id: <200301051800.h05I0Ic3096955@freefall.freebsd.org> To: freebsd-bugs@FreeBSD.org Cc: From: "David S. Madole" Subject: Re: i386/15845: Driver for RealTek 8029 Reply-To: "David S. Madole" Sender: owner-freebsd-bugs@FreeBSD.ORG Precedence: bulk List-ID: List-Archive: (Web Archive) List-Help: (List Instructions) List-Subscribe: List-Unsubscribe: X-Loop: FreeBSD.org The following reply was made to PR i386/15845; it has been noted by GNATS. From: "David S. Madole" To: , Cc: Subject: Re: i386/15845: Driver for RealTek 8029 Date: Sun, 5 Jan 2003 13:00:19 -0500 This is a multi-part message in MIME format. ------=_NextPart_000_0003_01C2B4BA.666F92A0 Content-Type: text/plain; charset="Windows-1252" Content-Transfer-Encoding: 7bit I have implemented media selection for the Realtek chips under the ed driver. I was not fully aware of this PR at the time I did it, but here it is, against 4.7-RELEASE. Note that there are some hardware limitations of these simple chips, most notably that there is no way to tell what media options are valid on a given card. This code assumes that 10baseT, 10base5, and 10base2 are all always present. There is also no way to detect 10baseT link except to set autoselect and see if the card chooses 10base2 instead. On a card that does not have 10base2, this would be viable, but because you can't know if 10base2 is present, I chose not to attempt to report status at all. Finally, these chips do not support autonegotiation, so media autoselect only supports half-duplex. Full duplex can however be set manually for 10baseT. This also means that switches that are not able to have the port duplex set manually will only work half-duplex with these cards. Still, it adds a tiny bit more versatility to these crufty old workhorses. I have tested this on both the RTL8019AS (ISA) and the RTL8029AS (PCI) and it seems to work fine, although my PCI card has only 10baseT media and my ISA card has only 10baseT and 10base2, so all media types have not been verified. Still, it's simple enough that I am confident it works for all options. Thanks, David Madole ------=_NextPart_000_0003_01C2B4BA.666F92A0 Content-Type: application/octet-stream; name="diff" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="diff" diff -u ed.orig/if_ed.c ed/if_ed.c --- ed.orig/if_ed.c Fri Nov 2 19:36:07 2001 +++ ed/if_ed.c Sun Jan 5 12:13:32 2003 @@ -87,6 +87,9 @@ static __inline void ed_xmit __P((struct ed_softc *)); static __inline char * ed_ring_copy __P((struct ed_softc *, char *, = char *, /* u_short */ int)); +static int ed_rtl_set_media __P((struct ifnet *ifp)); +static void ed_rtl_get_media __P(( struct ifnet *ifp, + struct ifmediareq *)); static void ed_hpp_set_physical_link __P((struct ed_softc *)); static void ed_hpp_readmem __P((struct ed_softc *, int, unsigned char = *, /* u_short */ int)); @@ -1139,6 +1142,152 @@ return ed_probe_Novell_generic(dev, flags); } =20 +int +ed_probe_Realtek(dev, port_rid, flags) + device_t dev; + int port_rid; + int flags; +{ + struct ed_softc *sc =3D device_get_softc(dev); + int error; + + if ((error =3D 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) !=3D 0x50) + return (ENXIO); + + switch (ed_nic_inb(sc, ED_RTL80X9_80X9ID1)) { + case 0x70: + sc->chip_type =3D ED_CHIP_TYPE_RTL8019; + break; + case 0x43: + sc->chip_type =3D ED_CHIP_TYPE_RTL8029; + break; + default: + return (ENXIO); + } + + sc->asic_offset =3D ED_NOVELL_ASIC_OFFSET; + sc->nic_offset =3D ED_NOVELL_NIC_OFFSET; + + if ((error =3D ed_probe_Novell_generic(dev, flags))) + return (error); + + 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(ifp) + struct ifnet *ifp; +{ + struct ed_softc *sc; + int spl; + + sc =3D ifp->if_softc; + spl =3D splimp(); + 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)); + + (void) splx(spl); + return (0); +} + +static void +ed_rtl_get_media(ifp, imr) + struct ifnet *ifp; + struct ifmediareq *imr; +{ + struct ed_softc *sc; + int spl; + + sc =3D ifp->if_softc; + imr->ifm_active =3D sc->ifmedia.ifm_cur->ifm_media; + + + if (IFM_SUBTYPE(imr->ifm_active) =3D=3D IFM_AUTO) { + spl =3D splimp(); + 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 |=3D IFM_10_2; + break; + case ED_RTL80X9_CF0_AUI: + imr->ifm_active |=3D IFM_10_5; + break; + default: + imr->ifm_active |=3D IFM_10_T; + break; + } + (void) splx(spl); + } + imr->ifm_status =3D 0; +} + #define ED_HPP_TEST_SIZE 16 =20 /* @@ -2587,6 +2736,12 @@ =20 case SIOCGIFMEDIA: case SIOCSIFMEDIA: + if (sc->chip_type =3D=3D ED_CHIP_TYPE_RTL8019 || + sc->chip_type =3D=3D ED_CHIP_TYPE_RTL8029) { + + error =3D ifmedia_ioctl(ifp, ifr, &sc->ifmedia, command); + break; + } if (sc->miibus =3D=3D NULL) { error =3D EINVAL; break; diff -u ed.orig/if_ed_isa.c ed/if_ed_isa.c --- ed.orig/if_ed_isa.c Mon Jul 29 03:52:57 2002 +++ ed/if_ed_isa.c Sun Jan 5 01:06:51 2003 @@ -40,6 +40,7 @@ #include #include #include +#include =20 #include #include @@ -93,6 +94,11 @@ ed_release_resources(dev); =20 error =3D ed_probe_3Com(dev, 0, flags); + if (error =3D=3D 0) + goto end; + ed_release_resources(dev); + + error =3D ed_probe_Realtek(dev, 0, flags); if (error =3D=3D 0) goto end; ed_release_resources(dev); diff -u ed.orig/if_ed_pci.c ed/if_ed_pci.c --- ed.orig/if_ed_pci.c Sun Sep 10 04:45:11 2000 +++ ed/if_ed_pci.c Sun Jan 5 12:16:44 2003 @@ -35,6 +35,7 @@ #include #include #include +#include =20 #include #include @@ -84,7 +85,11 @@ int flags =3D 0; int error; =20 - error =3D ed_probe_Novell(dev, PCIR_MAPS, flags); + if (pci_get_devid(dev) =3D=3D 0x802910ec) + error =3D ed_probe_Realtek(dev, PCIR_MAPS, flags); + else + error =3D ed_probe_Novell(dev, PCIR_MAPS, flags); + if (error) return (error); =20 diff -u ed.orig/if_edreg.h ed/if_edreg.h --- ed.orig/if_edreg.h Wed Jul 25 14:06:01 2001 +++ ed/if_edreg.h Sat Jan 4 22:16:59 2003 @@ -1107,6 +1107,31 @@ #define ED_CHIP_TYPE_DP8390 0x00 #define ED_CHIP_TYPE_WD790 0x01 #define ED_CHIP_TYPE_AX88190 0x02 +#define ED_CHIP_TYPE_RTL8019 0x03 +#define ED_CHIP_TYPE_RTL8029 0x04 + +/* + * 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_80X9ID1 0x0b + +#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_CR_PAGE_3 0xc0 =20 /* * AX88190 IOBASE registers. diff -u ed.orig/if_edvar.h ed/if_edvar.h --- ed.orig/if_edvar.h Wed Jul 25 14:06:01 2001 +++ ed/if_edvar.h Sun Jan 5 01:07:29 2003 @@ -90,6 +90,8 @@ u_char rec_page_stop; /* last page of RX ring-buffer */ u_char next_packet; /* pointer to next unread RX packet */ struct ifmib_iso_8802_3 mibdata; /* stuff for network mgmt */ + + struct ifmedia ifmedia; /* resource for media selection */ }; =20 #define ed_nic_inb(sc, port) \ @@ -197,6 +199,7 @@ int ed_probe_WD80x3 __P((device_t, int, int)); int ed_probe_WD80x3_generic __P((device_t, int, unsigned short *[])); int ed_probe_3Com __P((device_t, int, int)); +int ed_probe_Realtek __P((device_t, int, int)); int ed_probe_Novell __P((device_t, int, int)); int ed_probe_Novell_generic __P((device_t, int)); int ed_probe_HP_pclanp __P((device_t, int, int)); ------=_NextPart_000_0003_01C2B4BA.666F92A0-- To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-bugs" in the body of the message