Take the support for the 8139C+/8169/8169S/8110S chips out of the

rl(4) driver and put it in a new re(4) driver. The re(4) driver shares
the if_rlreg.h file with rl(4) but is a separate module. (Ultimately
I may change this. For now, it's convenient.)

rl(4) has been modified so that it will never attach to an 8139C+
chip, leaving it to re(4) instead. Only re(4) has the PCI IDs to
match the 8169/8169S/8110S gigE chips. if_re.c contains the same
basic code that was originally bolted onto if_rl.c, with the
following updates:

- Added support for jumbo frames. Currently, there seems to be
  a limit of approximately 6200 bytes for jumbo frames on transmit.
  (This was determined via experimentation.) The 8169S/8110S chips
  apparently are limited to 7.5K frames on transmit. This may require
  some more work, though the framework to handle jumbo frames on RX
  is in place: the re_rxeof() routine will gather up frames than span
  multiple 2K clusters into a single mbuf list.

- Fixed bug in re_txeof(): if we reap some of the TX buffers,
  but there are still some pending, re-arm the timer before exiting
  re_txeof() so that another timeout interrupt will be generated, just
  in case re_start() doesn't do it for us.

- Handle the 'link state changed' interrupt

- Fix a detach bug. If re(4) is loaded as a module, and you do
  tcpdump -i re0, then you do 'kldunload if_re,' the system will
  panic after a few seconds. This happens because ether_ifdetach()
  ends up calling the BPF detach code, which notices the interface
  is in promiscuous mode and tries to switch promisc mode off while
  detaching the BPF listner. This ultimately results in a call
  to re_ioctl() (due to SIOCSIFFLAGS), which in turn calls re_init()
  to handle the IFF_PROMISC flag change. Unfortunately, calling re_init()
  here turns the chip back on and restarts the 1-second timeout loop
  that drives re_tick(). By the time the timeout fires, if_re.ko
  has been unloaded, which results in a call to invalid code and
  blows up the system.

  To fix this, I cleared the IFF_UP flag before calling ether_ifdetach(),
  which stops the ioctl routine from trying to reset the chip.

- Modified comments in re_rxeof() relating to the difference in
  RX descriptor status bit layout between the 8139C+ and the gigE
  chips. The layout is different because the frame length field
  was expanded from 12 bits to 13, and they got rid of one of the
  status bits to make room.

- Add diagnostic code (re_diag()) to test for the case where a user
  has installed a broken 32-bit 8169 PCI NIC in a 64-bit slot. Some
  NICs have the REQ64# and ACK64# lines connected even though the
  board is 32-bit only (in this case, they should be pulled high).
  This fools the chip into doing 64-bit DMA transfers even though
  there is no 64-bit data path. To detect this, re_diag() puts the
  chip into digital loopback mode and sets the receiver to promiscuous
  mode, then initiates a single 64-byte packet transmission. The
  frame is echoed back to the host, and if the frame contents are
  intact, we know DMA is working correctly, otherwise we complain
  loudly on the console and abort the device attach. (At the moment,
  I don't know of any way to work around the problem other than
  physically modifying the board, so until/unless I can think of a
  software workaround, this will have do to.)

- Created re(4) man page

- Modified rlphy.c to allow re(4) to attach as well as rl(4).

Note that this code works for the sample 8169/Marvell 88E1000 NIC
that I have, but probably won't work for the 8169S/8110S chips.
RealTek has sent me some sample NICs, but they haven't arrived yet.
I will probably need to add an rlgphy driver to handle the on-board
PHY in the 8169S/8110S (it needs special DSP initialization).
This commit is contained in:
Bill Paul 2003-09-08 02:11:25 +00:00
parent 5e3cb29a6b
commit a94100fa9b
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=119868
16 changed files with 2589 additions and 1242 deletions

View File

@ -197,6 +197,7 @@ MAN= aac.4 \
puc.4 \
raid.4 \
random.4 \
re.4 \
rl.4 \
rndtest.4 \
route.4 \

View File

@ -35,7 +35,7 @@
.Os
.Sh NAME
.Nm rl
.Nd RealTek 8129/8139/8139C+ fast ethernet device driver
.Nd RealTek 8129/8139 fast ethernet device driver
.Sh SYNOPSIS
.Cd "device miibus"
.Cd "device rl"
@ -120,20 +120,9 @@ supports both 10 and 100Mbps speeds in either full or half duplex.
The 8129 can support the same speeds and modes given an appropriate
PHY chip.
.Pp
Support is also provided for the special C+ mode of the 8139C+ chip.
By default, the 8139C+ is back backwards compatible with the 8139, but
in C+ mode it supports advanced features such as descriptor-based DMA,
64-bit addressing, TCP/IP checksum offload on both receive and transmit,
hardware VLAN tag insertion and extraction, and TCP large send.
When used with an 8139C+ chip, the
.Nm
driver makes use of all of these features, except for TCP large send,
since there is currently no OS support for it. Transmit interrupt
moderation is also used to improve performance at high frame rates.
The receive and transmit checksum offload capabilities are on by default
but can be toggled off using the
.Xr ifconfig 8
command.
Note: support for the 8139C+ chip is provided by the
.Xr re 4
driver.
.Pp
The
.Nm

View File

@ -171,6 +171,7 @@ device miibus # MII bus support
device dc # DEC/Intel 21143 and various workalikes
device fxp # Intel EtherExpress PRO/100B (82557, 82558)
device pcn # AMD Am79C97x PCI 10/100 (precedence over 'lnc')
device re # RealTek 8139C+/8169/8169S/8110S
device rl # RealTek 8129/8139
device sf # Adaptec AIC-6915 (``Starfire'')
device sis # Silicon Integrated Systems SiS 900/SiS 7016

View File

@ -662,6 +662,7 @@ crypto/sha2/sha2.c optional random
dev/ray/if_ray.c optional ray card
dev/ray/if_ray.c optional ray pccard
dev/rc/rc.c optional rc
dev/re/if_re.c optional re
dev/rndtest/rndtest.c optional rndtest
dev/rp/rp.c optional rp
dev/rp/rp_isa.c optional rp isa

View File

@ -110,9 +110,10 @@ rlphy_probe(dev)
return (ENXIO);
/*
* Make sure the parent is an `rl'.
* Make sure the parent is an `rl' or an `re'.
*/
if (strcmp(device_get_name(parent), "rl") != 0)
if (strcmp(device_get_name(parent), "rl") != 0 &&
strcmp(device_get_name(parent), "re") != 0)
return (ENXIO);
device_set_desc(dev, "RealTek internal media interface");

2430
sys/dev/re/if_re.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -190,6 +190,7 @@ device miibus # MII bus support
device dc # DEC/Intel 21143 and various workalikes
device fxp # Intel EtherExpress PRO/100B (82557, 82558)
device pcn # AMD Am79C97x PCI 10/100 (precedence over 'lnc')
device re # RealTek 8139C+/8169/8169S/8110S
device rl # RealTek 8129/8139
device sf # Adaptec AIC-6915 (``Starfire'')
device sis # Silicon Integrated Systems SiS 900/SiS 7016

View File

@ -120,6 +120,7 @@ device bge # Broadcom BCM570xx Gigabit Ethernet
device dc # DEC/Intel 21143 and various workalikes
device fxp # Intel EtherExpress PRO/100B (82557, 82558)
device pcn # AMD Am79C97x PCI 10/100 NICs
device re # RealTek 8139C+/8169/8169S/8110S
device rl # RealTek 8129/8139
device sf # Adaptec AIC-6915 (``Starfire'')
device sis # Silicon Integrated Systems SiS 900/SiS 7016

View File

@ -105,6 +105,7 @@ SUBDIR= accf_data \
${_random} \
rc \
rc4 \
re \
rl \
rp \
rue \

9
sys/modules/re/Makefile Normal file
View File

@ -0,0 +1,9 @@
# $FreeBSD$
.PATH: ${.CURDIR}/../../pci
KMOD= if_re
SRCS= if_re.c opt_bdg.h device_if.h bus_if.h pci_if.h
SRCS+= miibus_if.h
.include <bsd.kmod.mk>

View File

@ -177,6 +177,7 @@ device miibus # MII bus support
device dc # DEC/Intel 21143 and various workalikes
device fxp # Intel EtherExpress PRO/100B (82557, 82558)
device pcn # AMD Am79C97x PCI 10/100 NICs
device re # RealTek 8139C+/8169/8169S/8110S
device rl # RealTek 8129/8139
device sf # Adaptec AIC-6915 (``Starfire'')
device sis # Silicon Integrated Systems SiS 900/SiS 7016

File diff suppressed because it is too large Load Diff

View File

@ -136,9 +136,13 @@
#define RL_TXCFG_MAXDMA 0x00000700 /* max DMA burst size */
#define RL_TXCFG_CRCAPPEND 0x00010000 /* CRC append (0 = yes) */
#define RL_TXCFG_LOOPBKTST 0x00060000 /* loopback test */
#define RL_TXCFG_IFG2 0x00080000 /* 8169 only */
#define RL_TXCFG_IFG 0x03000000 /* interframe gap */
#define RL_TXCFG_HWREV 0x7CC00000
#define RL_LOOPTEST_OFF 0x00000000
#define RL_LOOPTEST_ON 0x00020000
#define RL_HWREV_8169 0x00000000
#define RL_HWREV_8110 0x00800000
#define RL_HWREV_8139 0x60000000
@ -184,6 +188,7 @@
#define RL_ISR_TX_ERR 0x0008
#define RL_ISR_RX_OVERRUN 0x0010
#define RL_ISR_PKT_UNDERRUN 0x0020
#define RL_ISR_LINKCHG 0x0020 /* 8169 only */
#define RL_ISR_FIFO_OFLOW 0x0040 /* 8139 only */
#define RL_ISR_TX_DESC_UNAVAIL 0x0080 /* C+ only */
#define RL_ISR_SWI 0x0100 /* C+ only */
@ -198,7 +203,7 @@
RL_ISR_PCS_TIMEOUT|RL_ISR_SYSTEM_ERR)
#define RL_INTRS_CPLUS \
(RL_ISR_RX_OK|RL_ISR_RX_ERR|RL_ISR_TX_ERR| \
(RL_ISR_RX_OK|RL_ISR_RX_ERR|RL_ISR_TX_ERR| \
RL_ISR_RX_OVERRUN|RL_ISR_PKT_UNDERRUN|RL_ISR_FIFO_OFLOW| \
RL_ISR_PCS_TIMEOUT|RL_ISR_SYSTEM_ERR|RL_ISR_TIMEOUT_EXPIRED)
@ -401,8 +406,8 @@
#define RL_MIN_FRAMELEN 60
#define RL_TXTHRESH(x) ((x) << 11)
#define RL_TX_THRESH_INIT 96
#define RL_RX_FIFOTHRESH RL_RXFIFO_256BYTES
#define RL_RX_MAXDMA RL_RXDMA_1024BYTES /*RL_RXDMA_UNLIMITED*/
#define RL_RX_FIFOTHRESH RL_RXFIFO_NOTHRESH
#define RL_RX_MAXDMA RL_RXDMA_UNLIMITED
#define RL_TX_MAXDMA RL_TXDMA_2048BYTES
#define RL_RXCFG_CONFIG (RL_RX_FIFOTHRESH|RL_RX_MAXDMA|RL_RX_BUF_SZ)
@ -524,7 +529,7 @@ struct rl_desc {
#define RL_RDESC_CMD_EOR 0x40000000
#define RL_RDESC_CMD_OWN 0x80000000
#define RL_RDESC_CMD_BUFLEN 0x00001FFF
#define RL_RDESC_CMD_BUFLEN 0x00003FFF
#define RL_RDESC_STAT_OWN 0x80000000
#define RL_RDESC_STAT_EOR 0x40000000
@ -544,7 +549,7 @@ struct rl_desc {
#define RL_RDESC_STAT_IPSUMBAD 0x00008000 /* IP header checksum bad */
#define RL_RDESC_STAT_UDPSUMBAD 0x00004000 /* UDP checksum bad */
#define RL_RDESC_STAT_TCPSUMBAD 0x00002000 /* TCP checksum bad */
#define RL_RDESC_STAT_FRAGLEN 0x00001FFF /* RX'ed frame/frag len */
#define RL_RDESC_STAT_FRAGLEN 0x00003FFF /* RX'ed frame/frag len */
#define RL_RDESC_VLANCTL_TAG 0x00010000 /* VLAN tag available
(rl_vlandata valid)*/
@ -591,11 +596,22 @@ struct rl_stats {
#define RL_OWN(x) (le32toh((x)->rl_cmdstat) & RL_RDESC_STAT_OWN)
#define RL_RXBYTES(x) (le32toh((x)->rl_cmdstat) & \
RL_RDESC_STAT_FRAGLEN)
#define RL_PKTSZ(x) ((x) >> 3)
#define RL_PKTSZ(x) ((x)/* >> 3*/)
#define RL_ADDR_LO(y) ((u_int64_t) (y) & 0xFFFFFFFF)
#define RL_ADDR_HI(y) ((u_int64_t) (y) >> 32)
#define RL_JUMBO_FRAMELEN 9018
#define RL_JUMBO_MTU (RL_JUMBO_FRAMELEN-ETHER_HDR_LEN-ETHER_CRC_LEN)
#define RL_JSLOTS 128
#define RL_JRAWLEN (RL_JUMBO_FRAMELEN + ETHER_ALIGN + sizeof(u_int64_t))
#define RL_JLEN (RL_JRAWLEN + (sizeof(u_int64_t) - \
(RL_JRAWLEN % sizeof(u_int64_t))))
#define RL_JPAGESZ PAGE_SIZE
#define RL_RESID (RL_JPAGESZ - (RL_JLEN * RL_JSLOTS) % RL_JPAGESZ)
#define RL_JMEM ((RL_JLEN * RL_JSLOTS) + RL_RESID)
struct rl_softc;
struct rl_dmaload_arg {
@ -649,6 +665,10 @@ struct rl_softc {
struct rl_list_data rl_ldata;
struct callout_handle rl_stat_ch;
struct mtx rl_mtx;
struct mbuf *rl_head;
struct mbuf *rl_tail;
u_int32_t rl_hwrev;
int rl_testmode;
int suspended; /* 0 = normal 1 = suspended */
#ifdef DEVICE_POLLING
int rxcycles;
@ -667,7 +687,7 @@ struct rl_softc {
/*
* register space access macros
*/
#define CSR_WRITE_STREAM_4(sc, reg, val) \
#define CSR_WRITE_STREAM_4(sc, reg, val) \
bus_space_write_stream_4(sc->rl_btag, sc->rl_bhandle, reg, val)
#define CSR_WRITE_4(sc, reg, val) \
bus_space_write_4(sc->rl_btag, sc->rl_bhandle, reg, val)

View File

@ -162,6 +162,7 @@ device fxp # Intel EtherExpress PRO/100B (82557, 82558)
device gem # Sun GEM/Sun ERI/Apple GMAC
device hme # Sun HME (Happy Meal Ethernet)
#device pcn # AMD Am79C97x PCI 10/100 NICs
device re # RealTek 8139C+/8169/8169S/8110S
device rl # RealTek 8129/8139
#device sf # Adaptec AIC-6915 (``Starfire'')
#device sis # Silicon Integrated Systems SiS 900/SiS 7016

View File

@ -109,7 +109,9 @@ static struct _devname {
{ DEVICE_TYPE_NETWORK, "nge", "NatSemi PCI gigabit ethernet card" },
{ DEVICE_TYPE_NETWORK, "pcn", "AMD Am79c79x PCI ethernet card" },
{ DEVICE_TYPE_NETWORK, "ray", "Raytheon Raylink 802.11 wireless adaptor" },
{ DEVICE_TYPE_NETWORK, "re", "RealTek 8139C+/8169/8169S/8110S PCI ethernet card" },
{ DEVICE_TYPE_NETWORK, "rl", "RealTek 8129/8139 PCI ethernet card" },
{ DEVICE_TYPE_NETWORK, "rue", "RealTek USB ethernet card" },
{ DEVICE_TYPE_NETWORK, "sf", "Adaptec AIC-6915 PCI ethernet card" },
{ DEVICE_TYPE_NETWORK, "sis", "SiS 900/SiS 7016 PCI ethernet card" },
#ifdef PC98

View File

@ -109,7 +109,9 @@ static struct _devname {
{ DEVICE_TYPE_NETWORK, "nge", "NatSemi PCI gigabit ethernet card" },
{ DEVICE_TYPE_NETWORK, "pcn", "AMD Am79c79x PCI ethernet card" },
{ DEVICE_TYPE_NETWORK, "ray", "Raytheon Raylink 802.11 wireless adaptor" },
{ DEVICE_TYPE_NETWORK, "re", "RealTek 8139C+/8169/8169S/8110S PCI ethernet card" },
{ DEVICE_TYPE_NETWORK, "rl", "RealTek 8129/8139 PCI ethernet card" },
{ DEVICE_TYPE_NETWORK, "rue", "RealTek USB ethernet card" },
{ DEVICE_TYPE_NETWORK, "sf", "Adaptec AIC-6915 PCI ethernet card" },
{ DEVICE_TYPE_NETWORK, "sis", "SiS 900/SiS 7016 PCI ethernet card" },
#ifdef PC98