Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 5 Jan 2003 10:00:18 -0800 (PST)
From:      "David S. Madole" <david@madole.net>
To:        freebsd-bugs@FreeBSD.org
Subject:   Re: i386/15845: Driver for RealTek 8029
Message-ID:  <200301051800.h05I0Ic3096955@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help
The following reply was made to PR i386/15845; it has been noted by GNATS.

From: "David S. Madole" <david@madole.net>
To: <freebsd-gnats-submit@FreeBSD.org>, <slavoff@bnc.bg>
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 <net/if.h>
  #include <net/if_arp.h>
  #include <net/if_mib.h>
 +#include <net/if_media.h>
 =20
  #include <isa/isavar.h>
  #include <isa/pnpvar.h>
 @@ -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 <net/if.h>
  #include <net/if_arp.h>
  #include <net/if_mib.h>
 +#include <net/if_media.h>
 =20
  #include <pci/pcireg.h>
  #include <pci/pcivar.h>
 @@ -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




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200301051800.h05I0Ic3096955>