2005-01-07 02:29:27 +00:00
|
|
|
/*-
|
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).
2003-09-08 02:11:25 +00:00
|
|
|
* Copyright (c) 1997, 1998
|
1998-10-18 16:24:34 +00:00
|
|
|
* Bill Paul <wpaul@ctr.columbia.edu>. 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, 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.
|
|
|
|
* 3. All advertising materials mentioning features or use of this software
|
|
|
|
* must display the following acknowledgement:
|
|
|
|
* This product includes software developed by Bill Paul.
|
|
|
|
* 4. Neither the name of the author nor the names of any co-contributors
|
|
|
|
* may be used to endorse or promote products derived from this software
|
|
|
|
* without specific prior written permission.
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY Bill Paul 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 Bill Paul OR THE VOICES IN HIS HEAD
|
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
|
2003-11-14 17:16:58 +00:00
|
|
|
#include <sys/cdefs.h>
|
|
|
|
__FBSDID("$FreeBSD$");
|
|
|
|
|
1998-10-18 16:24:34 +00:00
|
|
|
/*
|
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).
2003-09-08 02:11:25 +00:00
|
|
|
* RealTek 8129/8139 PCI NIC driver
|
1998-10-18 16:24:34 +00:00
|
|
|
*
|
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).
2003-09-08 02:11:25 +00:00
|
|
|
* Supports several extremely cheap PCI 10/100 adapters based on
|
|
|
|
* the RealTek chipset. Datasheets can be obtained from
|
1998-10-18 16:24:34 +00:00
|
|
|
* www.realtek.com.tw.
|
|
|
|
*
|
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).
2003-09-08 02:11:25 +00:00
|
|
|
* Written by Bill Paul <wpaul@ctr.columbia.edu>
|
|
|
|
* Electrical Engineering Department
|
|
|
|
* Columbia University, New York City
|
1998-10-18 16:24:34 +00:00
|
|
|
*/
|
|
|
|
/*
|
|
|
|
* The RealTek 8139 PCI NIC redefines the meaning of 'low end.' This is
|
|
|
|
* probably the worst PCI ethernet controller ever made, with the possible
|
|
|
|
* exception of the FEAST chip made by SMC. The 8139 supports bus-master
|
|
|
|
* DMA, but it has a terrible interface that nullifies any performance
|
|
|
|
* gains that bus-master DMA usually offers.
|
|
|
|
*
|
|
|
|
* For transmission, the chip offers a series of four TX descriptor
|
|
|
|
* registers. Each transmit frame must be in a contiguous buffer, aligned
|
1998-12-07 00:35:06 +00:00
|
|
|
* on a longword (32-bit) boundary. This means we almost always have to
|
1998-10-18 16:24:34 +00:00
|
|
|
* do mbuf copies in order to transmit a frame, except in the unlikely
|
|
|
|
* case where a) the packet fits into a single mbuf, and b) the packet
|
|
|
|
* is 32-bit aligned within the mbuf's data area. The presence of only
|
|
|
|
* four descriptor registers means that we can never have more than four
|
|
|
|
* packets queued for transmission at any one time.
|
|
|
|
*
|
|
|
|
* Reception is not much better. The driver has to allocate a single large
|
|
|
|
* buffer area (up to 64K in size) into which the chip will DMA received
|
|
|
|
* frames. Because we don't know where within this region received packets
|
|
|
|
* will begin or end, we have no choice but to copy data from the buffer
|
|
|
|
* area into mbufs in order to pass the packets up to the higher protocol
|
|
|
|
* levels.
|
|
|
|
*
|
|
|
|
* It's impossible given this rotten design to really achieve decent
|
|
|
|
* performance at 100Mbps, unless you happen to have a 400Mhz PII or
|
|
|
|
* some equally overmuscled CPU to drive it.
|
|
|
|
*
|
|
|
|
* On the bright side, the 8139 does have a built-in PHY, although
|
|
|
|
* rather than using an MDIO serial interface like most other NICs, the
|
|
|
|
* PHY registers are directly accessible through the 8139's register
|
|
|
|
* space. The 8139 supports autonegotiation, as well as a 64-bit multicast
|
|
|
|
* filter.
|
|
|
|
*
|
|
|
|
* The 8129 chip is an older version of the 8139 that uses an external PHY
|
|
|
|
* chip. The 8129 has a serial MDIO interface for accessing the MII where
|
|
|
|
* the 8139 lets you directly access the on-board PHY registers. We need
|
|
|
|
* to select which interface to use depending on the chip type.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <sys/param.h>
|
2003-01-05 21:36:59 +00:00
|
|
|
#include <sys/endian.h>
|
1998-10-18 16:24:34 +00:00
|
|
|
#include <sys/systm.h>
|
|
|
|
#include <sys/sockio.h>
|
|
|
|
#include <sys/mbuf.h>
|
|
|
|
#include <sys/malloc.h>
|
|
|
|
#include <sys/kernel.h>
|
2004-05-30 20:00:41 +00:00
|
|
|
#include <sys/module.h>
|
1998-10-18 16:24:34 +00:00
|
|
|
#include <sys/socket.h>
|
|
|
|
|
|
|
|
#include <net/if.h>
|
|
|
|
#include <net/if_arp.h>
|
|
|
|
#include <net/ethernet.h>
|
|
|
|
#include <net/if_dl.h>
|
|
|
|
#include <net/if_media.h>
|
2005-06-10 16:49:24 +00:00
|
|
|
#include <net/if_types.h>
|
1998-10-18 16:24:34 +00:00
|
|
|
|
|
|
|
#include <net/bpf.h>
|
|
|
|
|
1998-12-07 00:35:06 +00:00
|
|
|
#include <machine/bus.h>
|
1999-08-31 14:45:51 +00:00
|
|
|
#include <machine/resource.h>
|
|
|
|
#include <sys/bus.h>
|
|
|
|
#include <sys/rman.h>
|
|
|
|
|
|
|
|
#include <dev/mii/mii.h>
|
|
|
|
#include <dev/mii/miivar.h>
|
1998-10-18 16:24:34 +00:00
|
|
|
|
2003-09-08 04:28:20 +00:00
|
|
|
#include <dev/pci/pcireg.h>
|
|
|
|
#include <dev/pci/pcivar.h>
|
1998-10-18 16:24:34 +00:00
|
|
|
|
2003-04-15 06:37:30 +00:00
|
|
|
MODULE_DEPEND(rl, pci, 1, 1, 1);
|
|
|
|
MODULE_DEPEND(rl, ether, 1, 1, 1);
|
2000-04-29 13:41:57 +00:00
|
|
|
MODULE_DEPEND(rl, miibus, 1, 1, 1);
|
|
|
|
|
1999-09-08 15:01:58 +00:00
|
|
|
/* "controller miibus0" required. See GENERIC if you get errors here. */
|
1999-08-31 14:45:51 +00:00
|
|
|
#include "miibus_if.h"
|
|
|
|
|
1998-10-18 16:24:34 +00:00
|
|
|
/*
|
|
|
|
* Default to using PIO access for this driver. On SMP systems,
|
|
|
|
* there appear to be problems with memory mapped mode: it looks like
|
|
|
|
* doing too many memory mapped access back to back in rapid succession
|
|
|
|
* can hang the bus. I'm inclined to blame this on crummy design/construction
|
|
|
|
* on the part of RealTek. Memory mapped mode does appear to work on
|
|
|
|
* uniprocessor systems though.
|
|
|
|
*/
|
|
|
|
#define RL_USEIOSPACE
|
|
|
|
|
|
|
|
#include <pci/if_rlreg.h>
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Various supported device vendors/types and their names.
|
|
|
|
*/
|
|
|
|
static struct rl_type rl_devs[] = {
|
2003-07-10 20:38:48 +00:00
|
|
|
{ RT_VENDORID, RT_DEVICEID_8129, RL_8129,
|
1998-10-18 16:24:34 +00:00
|
|
|
"RealTek 8129 10/100BaseTX" },
|
2003-07-10 20:38:48 +00:00
|
|
|
{ RT_VENDORID, RT_DEVICEID_8139, RL_8139,
|
1998-10-18 16:24:34 +00:00
|
|
|
"RealTek 8139 10/100BaseTX" },
|
2003-07-10 20:38:48 +00:00
|
|
|
{ RT_VENDORID, RT_DEVICEID_8138, RL_8139,
|
2000-10-28 09:00:20 +00:00
|
|
|
"RealTek 8139 10/100BaseTX CardBus" },
|
2003-08-15 22:47:55 +00:00
|
|
|
{ RT_VENDORID, RT_DEVICEID_8100, RL_8139,
|
|
|
|
"RealTek 8100 10/100BaseTX" },
|
2003-07-10 20:38:48 +00:00
|
|
|
{ ACCTON_VENDORID, ACCTON_DEVICEID_5030, RL_8139,
|
1998-11-18 21:03:58 +00:00
|
|
|
"Accton MPX 5030/5038 10/100BaseTX" },
|
2003-07-10 20:38:48 +00:00
|
|
|
{ DELTA_VENDORID, DELTA_DEVICEID_8139, RL_8139,
|
1999-02-23 15:38:25 +00:00
|
|
|
"Delta Electronics 8139 10/100BaseTX" },
|
2003-07-10 20:38:48 +00:00
|
|
|
{ ADDTRON_VENDORID, ADDTRON_DEVICEID_8139, RL_8139,
|
1999-02-23 15:38:25 +00:00
|
|
|
"Addtron Technolgy 8139 10/100BaseTX" },
|
2003-07-10 20:38:48 +00:00
|
|
|
{ DLINK_VENDORID, DLINK_DEVICEID_530TXPLUS, RL_8139,
|
2001-02-21 20:54:22 +00:00
|
|
|
"D-Link DFE-530TX+ 10/100BaseTX" },
|
2003-07-10 20:38:48 +00:00
|
|
|
{ DLINK_VENDORID, DLINK_DEVICEID_690TXD, RL_8139,
|
2002-05-06 13:43:00 +00:00
|
|
|
"D-Link DFE-690TXD 10/100BaseTX" },
|
2003-07-10 20:38:48 +00:00
|
|
|
{ NORTEL_VENDORID, ACCTON_DEVICEID_5030, RL_8139,
|
2002-04-11 06:12:51 +00:00
|
|
|
"Nortel Networks 10/100BaseTX" },
|
2003-07-10 20:38:48 +00:00
|
|
|
{ COREGA_VENDORID, COREGA_DEVICEID_FETHERCBTXD, RL_8139,
|
2002-09-06 16:38:06 +00:00
|
|
|
"Corega FEther CB-TXD" },
|
2003-07-10 20:38:48 +00:00
|
|
|
{ COREGA_VENDORID, COREGA_DEVICEID_FETHERIICBTXD, RL_8139,
|
2003-01-11 07:10:35 +00:00
|
|
|
"Corega FEtherII CB-TXD" },
|
2003-07-10 20:38:48 +00:00
|
|
|
{ PEPPERCON_VENDORID, PEPPERCON_DEVICEID_ROLF, RL_8139,
|
2003-02-23 23:35:35 +00:00
|
|
|
"Peppercon AG ROL-F" },
|
2003-07-10 20:38:48 +00:00
|
|
|
{ PLANEX_VENDORID, PLANEX_DEVICEID_FNW3800TX, RL_8139,
|
2003-03-18 14:57:09 +00:00
|
|
|
"Planex FNW-3800-TX" },
|
2003-07-10 20:38:48 +00:00
|
|
|
{ CP_VENDORID, RT_DEVICEID_8139, RL_8139,
|
|
|
|
"Compaq HNE-300" },
|
|
|
|
{ LEVEL1_VENDORID, LEVEL1_DEVICEID_FPC0106TX, RL_8139,
|
|
|
|
"LevelOne FPC-0106TX" },
|
|
|
|
{ EDIMAX_VENDORID, EDIMAX_DEVICEID_EP4103DL, RL_8139,
|
|
|
|
"Edimax EP-4103DL CardBus" },
|
2003-12-23 02:36:43 +00:00
|
|
|
{ 0, 0, 0, NULL }
|
1998-10-18 16:24:34 +00:00
|
|
|
};
|
|
|
|
|
2005-02-24 22:33:05 +00:00
|
|
|
static int rl_attach(device_t);
|
|
|
|
static int rl_detach(device_t);
|
|
|
|
static void rl_dma_map_rxbuf(void *, bus_dma_segment_t *, int, int);
|
|
|
|
static void rl_dma_map_txbuf(void *, bus_dma_segment_t *, int, int);
|
|
|
|
static void rl_eeprom_putbyte(struct rl_softc *, int);
|
|
|
|
static void rl_eeprom_getword(struct rl_softc *, int, uint16_t *);
|
|
|
|
static int rl_encap(struct rl_softc *, struct mbuf * );
|
|
|
|
static int rl_list_tx_init(struct rl_softc *);
|
|
|
|
static int rl_ifmedia_upd(struct ifnet *);
|
|
|
|
static void rl_ifmedia_sts(struct ifnet *, struct ifmediareq *);
|
|
|
|
static int rl_ioctl(struct ifnet *, u_long, caddr_t);
|
|
|
|
static void rl_intr(void *);
|
|
|
|
static void rl_init(void *);
|
|
|
|
static void rl_init_locked(struct rl_softc *sc);
|
|
|
|
static void rl_mii_send(struct rl_softc *, uint32_t, int);
|
|
|
|
static void rl_mii_sync(struct rl_softc *);
|
|
|
|
static int rl_mii_readreg(struct rl_softc *, struct rl_mii_frame *);
|
|
|
|
static int rl_mii_writereg(struct rl_softc *, struct rl_mii_frame *);
|
|
|
|
static int rl_miibus_readreg(device_t, int, int);
|
|
|
|
static void rl_miibus_statchg(device_t);
|
|
|
|
static int rl_miibus_writereg(device_t, int, int, int);
|
2004-07-09 00:07:06 +00:00
|
|
|
#ifdef DEVICE_POLLING
|
2005-02-24 22:33:05 +00:00
|
|
|
static void rl_poll(struct ifnet *ifp, enum poll_cmd cmd,
|
2004-07-09 00:07:06 +00:00
|
|
|
int count);
|
2005-02-24 22:33:05 +00:00
|
|
|
static void rl_poll_locked(struct ifnet *ifp, enum poll_cmd cmd,
|
2004-07-09 00:07:06 +00:00
|
|
|
int count);
|
|
|
|
#endif
|
2005-02-24 22:33:05 +00:00
|
|
|
static int rl_probe(device_t);
|
|
|
|
static void rl_read_eeprom(struct rl_softc *, uint8_t *, int, int, int);
|
|
|
|
static void rl_reset(struct rl_softc *);
|
|
|
|
static int rl_resume(device_t);
|
|
|
|
static void rl_rxeof(struct rl_softc *);
|
|
|
|
static void rl_setmulti(struct rl_softc *);
|
|
|
|
static void rl_shutdown(device_t);
|
|
|
|
static void rl_start(struct ifnet *);
|
|
|
|
static void rl_start_locked(struct ifnet *);
|
|
|
|
static void rl_stop(struct rl_softc *);
|
|
|
|
static int rl_suspend(device_t);
|
|
|
|
static void rl_tick(void *);
|
|
|
|
static void rl_txeof(struct rl_softc *);
|
|
|
|
static void rl_watchdog(struct ifnet *);
|
2001-08-15 17:38:43 +00:00
|
|
|
|
1999-08-31 14:45:51 +00:00
|
|
|
#ifdef RL_USEIOSPACE
|
|
|
|
#define RL_RES SYS_RES_IOPORT
|
|
|
|
#define RL_RID RL_PCI_LOIO
|
|
|
|
#else
|
|
|
|
#define RL_RES SYS_RES_MEMORY
|
|
|
|
#define RL_RID RL_PCI_LOMEM
|
|
|
|
#endif
|
|
|
|
|
|
|
|
static device_method_t rl_methods[] = {
|
|
|
|
/* Device interface */
|
|
|
|
DEVMETHOD(device_probe, rl_probe),
|
|
|
|
DEVMETHOD(device_attach, rl_attach),
|
|
|
|
DEVMETHOD(device_detach, rl_detach),
|
2001-11-23 14:27:33 +00:00
|
|
|
DEVMETHOD(device_suspend, rl_suspend),
|
|
|
|
DEVMETHOD(device_resume, rl_resume),
|
1999-08-31 14:45:51 +00:00
|
|
|
DEVMETHOD(device_shutdown, rl_shutdown),
|
|
|
|
|
|
|
|
/* bus interface */
|
|
|
|
DEVMETHOD(bus_print_child, bus_generic_print_child),
|
|
|
|
DEVMETHOD(bus_driver_added, bus_generic_driver_added),
|
|
|
|
|
|
|
|
/* MII interface */
|
|
|
|
DEVMETHOD(miibus_readreg, rl_miibus_readreg),
|
|
|
|
DEVMETHOD(miibus_writereg, rl_miibus_writereg),
|
|
|
|
DEVMETHOD(miibus_statchg, rl_miibus_statchg),
|
|
|
|
|
|
|
|
{ 0, 0 }
|
|
|
|
};
|
|
|
|
|
|
|
|
static driver_t rl_driver = {
|
1999-09-20 08:47:11 +00:00
|
|
|
"rl",
|
1999-08-31 14:45:51 +00:00
|
|
|
rl_methods,
|
|
|
|
sizeof(struct rl_softc)
|
|
|
|
};
|
|
|
|
|
|
|
|
static devclass_t rl_devclass;
|
|
|
|
|
2003-04-15 06:37:30 +00:00
|
|
|
DRIVER_MODULE(rl, pci, rl_driver, rl_devclass, 0, 0);
|
2003-11-28 05:28:29 +00:00
|
|
|
DRIVER_MODULE(rl, cardbus, rl_driver, rl_devclass, 0, 0);
|
1999-09-20 19:06:45 +00:00
|
|
|
DRIVER_MODULE(miibus, rl, miibus_driver, miibus_devclass, 0, 0);
|
1999-08-31 14:45:51 +00:00
|
|
|
|
1998-10-18 16:24:34 +00:00
|
|
|
#define EE_SET(x) \
|
|
|
|
CSR_WRITE_1(sc, RL_EECMD, \
|
|
|
|
CSR_READ_1(sc, RL_EECMD) | x)
|
|
|
|
|
|
|
|
#define EE_CLR(x) \
|
|
|
|
CSR_WRITE_1(sc, RL_EECMD, \
|
|
|
|
CSR_READ_1(sc, RL_EECMD) & ~x)
|
|
|
|
|
2001-08-15 17:38:43 +00:00
|
|
|
static void
|
2004-07-05 02:46:42 +00:00
|
|
|
rl_dma_map_rxbuf(void *arg, bus_dma_segment_t *segs, int nseg, int error)
|
2001-08-15 17:38:43 +00:00
|
|
|
{
|
2004-07-05 02:46:42 +00:00
|
|
|
struct rl_softc *sc = arg;
|
2001-08-15 17:38:43 +00:00
|
|
|
|
|
|
|
CSR_WRITE_4(sc, RL_RXADDR, segs->ds_addr & 0xFFFFFFFF);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2004-07-05 02:46:42 +00:00
|
|
|
rl_dma_map_txbuf(void *arg, bus_dma_segment_t *segs, int nseg, int error)
|
2001-08-15 17:38:43 +00:00
|
|
|
{
|
2004-07-05 02:46:42 +00:00
|
|
|
struct rl_softc *sc = arg;
|
2001-08-15 17:38:43 +00:00
|
|
|
|
|
|
|
CSR_WRITE_4(sc, RL_CUR_TXADDR(sc), segs->ds_addr & 0xFFFFFFFF);
|
|
|
|
}
|
|
|
|
|
1998-10-18 16:24:34 +00:00
|
|
|
/*
|
|
|
|
* Send a read command and address to the EEPROM, check for ACK.
|
|
|
|
*/
|
2002-08-23 23:49:02 +00:00
|
|
|
static void
|
2004-07-05 02:46:42 +00:00
|
|
|
rl_eeprom_putbyte(struct rl_softc *sc, int addr)
|
1998-10-18 16:24:34 +00:00
|
|
|
{
|
|
|
|
register int d, i;
|
|
|
|
|
2000-10-30 07:54:38 +00:00
|
|
|
d = addr | sc->rl_eecmd_read;
|
1998-10-18 16:24:34 +00:00
|
|
|
|
|
|
|
/*
|
1999-12-28 06:04:29 +00:00
|
|
|
* Feed in each bit and strobe the clock.
|
1998-10-18 16:24:34 +00:00
|
|
|
*/
|
|
|
|
for (i = 0x400; i; i >>= 1) {
|
|
|
|
if (d & i) {
|
|
|
|
EE_SET(RL_EE_DATAIN);
|
|
|
|
} else {
|
|
|
|
EE_CLR(RL_EE_DATAIN);
|
|
|
|
}
|
|
|
|
DELAY(100);
|
|
|
|
EE_SET(RL_EE_CLK);
|
|
|
|
DELAY(150);
|
|
|
|
EE_CLR(RL_EE_CLK);
|
|
|
|
DELAY(100);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Read a word of data stored in the EEPROM at address 'addr.'
|
|
|
|
*/
|
2002-08-23 23:49:02 +00:00
|
|
|
static void
|
2004-07-05 02:46:42 +00:00
|
|
|
rl_eeprom_getword(struct rl_softc *sc, int addr, uint16_t *dest)
|
1998-10-18 16:24:34 +00:00
|
|
|
{
|
|
|
|
register int i;
|
2004-07-05 02:46:42 +00:00
|
|
|
uint16_t word = 0;
|
1998-10-18 16:24:34 +00:00
|
|
|
|
|
|
|
/* Enter EEPROM access mode. */
|
|
|
|
CSR_WRITE_1(sc, RL_EECMD, RL_EEMODE_PROGRAM|RL_EE_SEL);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Send address of word we want to read.
|
|
|
|
*/
|
|
|
|
rl_eeprom_putbyte(sc, addr);
|
|
|
|
|
|
|
|
CSR_WRITE_1(sc, RL_EECMD, RL_EEMODE_PROGRAM|RL_EE_SEL);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Start reading bits from EEPROM.
|
|
|
|
*/
|
|
|
|
for (i = 0x8000; i; i >>= 1) {
|
|
|
|
EE_SET(RL_EE_CLK);
|
|
|
|
DELAY(100);
|
|
|
|
if (CSR_READ_1(sc, RL_EECMD) & RL_EE_DATAOUT)
|
|
|
|
word |= i;
|
|
|
|
EE_CLR(RL_EE_CLK);
|
|
|
|
DELAY(100);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Turn off EEPROM access mode. */
|
|
|
|
CSR_WRITE_1(sc, RL_EECMD, RL_EEMODE_OFF);
|
|
|
|
|
|
|
|
*dest = word;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Read a sequence of words from the EEPROM.
|
|
|
|
*/
|
2002-08-23 23:49:02 +00:00
|
|
|
static void
|
2004-07-05 02:46:42 +00:00
|
|
|
rl_read_eeprom(struct rl_softc *sc, uint8_t *dest, int off, int cnt, int swap)
|
1998-10-18 16:24:34 +00:00
|
|
|
{
|
|
|
|
int i;
|
2004-07-05 02:46:42 +00:00
|
|
|
uint16_t word = 0, *ptr;
|
1998-10-18 16:24:34 +00:00
|
|
|
|
|
|
|
for (i = 0; i < cnt; i++) {
|
|
|
|
rl_eeprom_getword(sc, off + i, &word);
|
2004-07-05 02:46:42 +00:00
|
|
|
ptr = (uint16_t *)(dest + (i * 2));
|
1998-10-18 16:24:34 +00:00
|
|
|
if (swap)
|
|
|
|
*ptr = ntohs(word);
|
|
|
|
else
|
|
|
|
*ptr = word;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* MII access routines are provided for the 8129, which
|
|
|
|
* doesn't have a built-in PHY. For the 8139, we fake things
|
|
|
|
* up by diverting rl_phy_readreg()/rl_phy_writereg() to the
|
|
|
|
* direct access PHY registers.
|
|
|
|
*/
|
|
|
|
#define MII_SET(x) \
|
|
|
|
CSR_WRITE_1(sc, RL_MII, \
|
2002-10-16 09:14:59 +00:00
|
|
|
CSR_READ_1(sc, RL_MII) | (x))
|
1998-10-18 16:24:34 +00:00
|
|
|
|
|
|
|
#define MII_CLR(x) \
|
|
|
|
CSR_WRITE_1(sc, RL_MII, \
|
2002-10-16 09:14:59 +00:00
|
|
|
CSR_READ_1(sc, RL_MII) & ~(x))
|
1998-10-18 16:24:34 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Sync the PHYs by setting data bit and strobing the clock 32 times.
|
|
|
|
*/
|
2002-08-23 23:49:02 +00:00
|
|
|
static void
|
2004-07-05 02:46:42 +00:00
|
|
|
rl_mii_sync(struct rl_softc *sc)
|
1998-10-18 16:24:34 +00:00
|
|
|
{
|
|
|
|
register int i;
|
|
|
|
|
|
|
|
MII_SET(RL_MII_DIR|RL_MII_DATAOUT);
|
|
|
|
|
|
|
|
for (i = 0; i < 32; i++) {
|
|
|
|
MII_SET(RL_MII_CLK);
|
|
|
|
DELAY(1);
|
|
|
|
MII_CLR(RL_MII_CLK);
|
|
|
|
DELAY(1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Clock a series of bits through the MII.
|
|
|
|
*/
|
2002-08-23 23:49:02 +00:00
|
|
|
static void
|
2004-07-05 02:46:42 +00:00
|
|
|
rl_mii_send(struct rl_softc *sc, uint32_t bits, int cnt)
|
1998-10-18 16:24:34 +00:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
MII_CLR(RL_MII_CLK);
|
|
|
|
|
|
|
|
for (i = (0x1 << (cnt - 1)); i; i >>= 1) {
|
2003-01-11 16:11:21 +00:00
|
|
|
if (bits & i) {
|
1998-10-18 16:24:34 +00:00
|
|
|
MII_SET(RL_MII_DATAOUT);
|
2003-01-11 16:11:21 +00:00
|
|
|
} else {
|
1998-10-18 16:24:34 +00:00
|
|
|
MII_CLR(RL_MII_DATAOUT);
|
2003-01-11 16:11:21 +00:00
|
|
|
}
|
1998-10-18 16:24:34 +00:00
|
|
|
DELAY(1);
|
|
|
|
MII_CLR(RL_MII_CLK);
|
|
|
|
DELAY(1);
|
|
|
|
MII_SET(RL_MII_CLK);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Read an PHY register through the MII.
|
|
|
|
*/
|
2002-08-23 23:49:02 +00:00
|
|
|
static int
|
2004-07-05 02:46:42 +00:00
|
|
|
rl_mii_readreg(struct rl_softc *sc, struct rl_mii_frame *frame)
|
1998-10-18 16:24:34 +00:00
|
|
|
{
|
2000-10-13 17:54:19 +00:00
|
|
|
int i, ack;
|
1998-10-18 16:24:34 +00:00
|
|
|
|
2000-10-13 17:54:19 +00:00
|
|
|
RL_LOCK(sc);
|
1998-10-18 16:24:34 +00:00
|
|
|
|
2004-07-05 02:46:42 +00:00
|
|
|
/* Set up frame for RX. */
|
1998-10-18 16:24:34 +00:00
|
|
|
frame->mii_stdelim = RL_MII_STARTDELIM;
|
|
|
|
frame->mii_opcode = RL_MII_READOP;
|
|
|
|
frame->mii_turnaround = 0;
|
|
|
|
frame->mii_data = 0;
|
2003-01-11 16:11:21 +00:00
|
|
|
|
1998-10-18 16:24:34 +00:00
|
|
|
CSR_WRITE_2(sc, RL_MII, 0);
|
|
|
|
|
2004-07-05 02:46:42 +00:00
|
|
|
/* Turn on data xmit. */
|
1998-10-18 16:24:34 +00:00
|
|
|
MII_SET(RL_MII_DIR);
|
|
|
|
|
|
|
|
rl_mii_sync(sc);
|
|
|
|
|
2004-07-05 02:46:42 +00:00
|
|
|
/* Send command/address info. */
|
1998-10-18 16:24:34 +00:00
|
|
|
rl_mii_send(sc, frame->mii_stdelim, 2);
|
|
|
|
rl_mii_send(sc, frame->mii_opcode, 2);
|
|
|
|
rl_mii_send(sc, frame->mii_phyaddr, 5);
|
|
|
|
rl_mii_send(sc, frame->mii_regaddr, 5);
|
|
|
|
|
|
|
|
/* Idle bit */
|
|
|
|
MII_CLR((RL_MII_CLK|RL_MII_DATAOUT));
|
|
|
|
DELAY(1);
|
|
|
|
MII_SET(RL_MII_CLK);
|
|
|
|
DELAY(1);
|
|
|
|
|
|
|
|
/* Turn off xmit. */
|
|
|
|
MII_CLR(RL_MII_DIR);
|
|
|
|
|
|
|
|
/* Check for ack */
|
|
|
|
MII_CLR(RL_MII_CLK);
|
|
|
|
DELAY(1);
|
2003-01-10 08:09:58 +00:00
|
|
|
ack = CSR_READ_2(sc, RL_MII) & RL_MII_DATAIN;
|
1998-10-18 16:24:34 +00:00
|
|
|
MII_SET(RL_MII_CLK);
|
|
|
|
DELAY(1);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Now try reading data bits. If the ack failed, we still
|
|
|
|
* need to clock through 16 cycles to keep the PHY(s) in sync.
|
|
|
|
*/
|
|
|
|
if (ack) {
|
|
|
|
for(i = 0; i < 16; i++) {
|
|
|
|
MII_CLR(RL_MII_CLK);
|
|
|
|
DELAY(1);
|
|
|
|
MII_SET(RL_MII_CLK);
|
|
|
|
DELAY(1);
|
|
|
|
}
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0x8000; i; i >>= 1) {
|
|
|
|
MII_CLR(RL_MII_CLK);
|
|
|
|
DELAY(1);
|
|
|
|
if (!ack) {
|
|
|
|
if (CSR_READ_2(sc, RL_MII) & RL_MII_DATAIN)
|
|
|
|
frame->mii_data |= i;
|
|
|
|
DELAY(1);
|
|
|
|
}
|
|
|
|
MII_SET(RL_MII_CLK);
|
|
|
|
DELAY(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
fail:
|
|
|
|
MII_CLR(RL_MII_CLK);
|
|
|
|
DELAY(1);
|
|
|
|
MII_SET(RL_MII_CLK);
|
|
|
|
DELAY(1);
|
|
|
|
|
2000-10-13 17:54:19 +00:00
|
|
|
RL_UNLOCK(sc);
|
1998-10-18 16:24:34 +00:00
|
|
|
|
2004-07-05 02:46:42 +00:00
|
|
|
return (ack ? 1 : 0);
|
1998-10-18 16:24:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Write to a PHY register through the MII.
|
|
|
|
*/
|
2002-08-23 23:49:02 +00:00
|
|
|
static int
|
2004-07-05 02:46:42 +00:00
|
|
|
rl_mii_writereg(struct rl_softc *sc, struct rl_mii_frame *frame)
|
1998-10-18 16:24:34 +00:00
|
|
|
{
|
|
|
|
|
2004-07-05 02:46:42 +00:00
|
|
|
RL_LOCK(sc);
|
1998-10-18 16:24:34 +00:00
|
|
|
|
2004-07-05 02:46:42 +00:00
|
|
|
/* Set up frame for TX. */
|
1998-10-18 16:24:34 +00:00
|
|
|
frame->mii_stdelim = RL_MII_STARTDELIM;
|
|
|
|
frame->mii_opcode = RL_MII_WRITEOP;
|
|
|
|
frame->mii_turnaround = RL_MII_TURNAROUND;
|
2003-01-11 16:11:21 +00:00
|
|
|
|
2004-07-05 02:46:42 +00:00
|
|
|
/* Turn on data output. */
|
1998-10-18 16:24:34 +00:00
|
|
|
MII_SET(RL_MII_DIR);
|
|
|
|
|
|
|
|
rl_mii_sync(sc);
|
|
|
|
|
|
|
|
rl_mii_send(sc, frame->mii_stdelim, 2);
|
|
|
|
rl_mii_send(sc, frame->mii_opcode, 2);
|
|
|
|
rl_mii_send(sc, frame->mii_phyaddr, 5);
|
|
|
|
rl_mii_send(sc, frame->mii_regaddr, 5);
|
|
|
|
rl_mii_send(sc, frame->mii_turnaround, 2);
|
|
|
|
rl_mii_send(sc, frame->mii_data, 16);
|
|
|
|
|
|
|
|
/* Idle bit. */
|
|
|
|
MII_SET(RL_MII_CLK);
|
|
|
|
DELAY(1);
|
|
|
|
MII_CLR(RL_MII_CLK);
|
|
|
|
DELAY(1);
|
|
|
|
|
2004-07-05 02:46:42 +00:00
|
|
|
/* Turn off xmit. */
|
1998-10-18 16:24:34 +00:00
|
|
|
MII_CLR(RL_MII_DIR);
|
|
|
|
|
2000-10-13 17:54:19 +00:00
|
|
|
RL_UNLOCK(sc);
|
1998-10-18 16:24:34 +00:00
|
|
|
|
2004-07-05 02:46:42 +00:00
|
|
|
return (0);
|
1998-10-18 16:24:34 +00:00
|
|
|
}
|
|
|
|
|
2002-08-23 23:49:02 +00:00
|
|
|
static int
|
2004-07-05 02:46:42 +00:00
|
|
|
rl_miibus_readreg(device_t dev, int phy, int reg)
|
1998-10-18 16:24:34 +00:00
|
|
|
{
|
1999-08-31 14:45:51 +00:00
|
|
|
struct rl_softc *sc;
|
1998-10-18 16:24:34 +00:00
|
|
|
struct rl_mii_frame frame;
|
2004-07-05 02:46:42 +00:00
|
|
|
uint16_t rval = 0;
|
|
|
|
uint16_t rl8139_reg = 0;
|
1998-10-18 16:24:34 +00:00
|
|
|
|
1999-08-31 14:45:51 +00:00
|
|
|
sc = device_get_softc(dev);
|
|
|
|
|
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).
2003-09-08 02:11:25 +00:00
|
|
|
if (sc->rl_type == RL_8139) {
|
1999-08-31 14:45:51 +00:00
|
|
|
/* Pretend the internal PHY is only at address 0 */
|
2000-10-13 17:54:19 +00:00
|
|
|
if (phy) {
|
2004-07-05 02:46:42 +00:00
|
|
|
return (0);
|
2000-10-13 17:54:19 +00:00
|
|
|
}
|
2004-07-05 02:46:42 +00:00
|
|
|
switch (reg) {
|
1999-08-31 14:45:51 +00:00
|
|
|
case MII_BMCR:
|
1998-10-18 16:24:34 +00:00
|
|
|
rl8139_reg = RL_BMCR;
|
|
|
|
break;
|
1999-08-31 14:45:51 +00:00
|
|
|
case MII_BMSR:
|
1998-10-18 16:24:34 +00:00
|
|
|
rl8139_reg = RL_BMSR;
|
|
|
|
break;
|
1999-08-31 14:45:51 +00:00
|
|
|
case MII_ANAR:
|
1998-10-18 16:24:34 +00:00
|
|
|
rl8139_reg = RL_ANAR;
|
|
|
|
break;
|
1999-08-31 14:45:51 +00:00
|
|
|
case MII_ANER:
|
|
|
|
rl8139_reg = RL_ANER;
|
|
|
|
break;
|
|
|
|
case MII_ANLPAR:
|
1998-10-18 16:24:34 +00:00
|
|
|
rl8139_reg = RL_LPAR;
|
|
|
|
break;
|
1999-08-31 14:45:51 +00:00
|
|
|
case MII_PHYIDR1:
|
|
|
|
case MII_PHYIDR2:
|
2004-07-05 02:46:42 +00:00
|
|
|
return (0);
|
2002-04-07 20:55:50 +00:00
|
|
|
/*
|
|
|
|
* Allow the rlphy driver to read the media status
|
|
|
|
* register. If we have a link partner which does not
|
|
|
|
* support NWAY, this is the register which will tell
|
|
|
|
* us the results of parallel detection.
|
|
|
|
*/
|
|
|
|
case RL_MEDIASTAT:
|
|
|
|
rval = CSR_READ_1(sc, RL_MEDIASTAT);
|
2004-07-05 02:46:42 +00:00
|
|
|
return (rval);
|
1998-10-18 16:24:34 +00:00
|
|
|
default:
|
2005-06-10 16:49:24 +00:00
|
|
|
if_printf(sc->rl_ifp, "bad phy register\n");
|
2004-07-05 02:46:42 +00:00
|
|
|
return (0);
|
1998-10-18 16:24:34 +00:00
|
|
|
}
|
|
|
|
rval = CSR_READ_2(sc, rl8139_reg);
|
2004-07-05 02:46:42 +00:00
|
|
|
return (rval);
|
1998-10-18 16:24:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bzero((char *)&frame, sizeof(frame));
|
1999-08-31 14:45:51 +00:00
|
|
|
frame.mii_phyaddr = phy;
|
1998-10-18 16:24:34 +00:00
|
|
|
frame.mii_regaddr = reg;
|
|
|
|
rl_mii_readreg(sc, &frame);
|
2004-07-05 02:46:42 +00:00
|
|
|
|
|
|
|
return (frame.mii_data);
|
1998-10-18 16:24:34 +00:00
|
|
|
}
|
|
|
|
|
2002-08-23 23:49:02 +00:00
|
|
|
static int
|
2004-07-05 02:46:42 +00:00
|
|
|
rl_miibus_writereg(device_t dev, int phy, int reg, int data)
|
1998-10-18 16:24:34 +00:00
|
|
|
{
|
1999-08-31 14:45:51 +00:00
|
|
|
struct rl_softc *sc;
|
1998-10-18 16:24:34 +00:00
|
|
|
struct rl_mii_frame frame;
|
2004-07-05 02:46:42 +00:00
|
|
|
uint16_t rl8139_reg = 0;
|
1998-10-18 16:24:34 +00:00
|
|
|
|
1999-08-31 14:45:51 +00:00
|
|
|
sc = device_get_softc(dev);
|
|
|
|
|
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).
2003-09-08 02:11:25 +00:00
|
|
|
if (sc->rl_type == RL_8139) {
|
1999-08-31 14:45:51 +00:00
|
|
|
/* Pretend the internal PHY is only at address 0 */
|
2000-10-13 17:54:19 +00:00
|
|
|
if (phy) {
|
2004-07-05 02:46:42 +00:00
|
|
|
return (0);
|
2000-10-13 17:54:19 +00:00
|
|
|
}
|
2004-07-05 02:46:42 +00:00
|
|
|
switch (reg) {
|
1999-08-31 14:45:51 +00:00
|
|
|
case MII_BMCR:
|
1998-10-18 16:24:34 +00:00
|
|
|
rl8139_reg = RL_BMCR;
|
|
|
|
break;
|
1999-08-31 14:45:51 +00:00
|
|
|
case MII_BMSR:
|
1998-10-18 16:24:34 +00:00
|
|
|
rl8139_reg = RL_BMSR;
|
|
|
|
break;
|
1999-08-31 14:45:51 +00:00
|
|
|
case MII_ANAR:
|
1998-10-18 16:24:34 +00:00
|
|
|
rl8139_reg = RL_ANAR;
|
|
|
|
break;
|
1999-08-31 14:45:51 +00:00
|
|
|
case MII_ANER:
|
|
|
|
rl8139_reg = RL_ANER;
|
|
|
|
break;
|
|
|
|
case MII_ANLPAR:
|
1998-10-18 16:24:34 +00:00
|
|
|
rl8139_reg = RL_LPAR;
|
|
|
|
break;
|
1999-08-31 14:45:51 +00:00
|
|
|
case MII_PHYIDR1:
|
|
|
|
case MII_PHYIDR2:
|
2004-07-05 02:46:42 +00:00
|
|
|
return (0);
|
1999-08-31 14:45:51 +00:00
|
|
|
break;
|
1998-10-18 16:24:34 +00:00
|
|
|
default:
|
2005-06-10 16:49:24 +00:00
|
|
|
if_printf(sc->rl_ifp, "bad phy register\n");
|
2004-07-05 02:46:42 +00:00
|
|
|
return (0);
|
1998-10-18 16:24:34 +00:00
|
|
|
}
|
|
|
|
CSR_WRITE_2(sc, rl8139_reg, data);
|
2004-07-05 02:46:42 +00:00
|
|
|
return (0);
|
1998-10-18 16:24:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bzero((char *)&frame, sizeof(frame));
|
1999-08-31 14:45:51 +00:00
|
|
|
frame.mii_phyaddr = phy;
|
1998-10-18 16:24:34 +00:00
|
|
|
frame.mii_regaddr = reg;
|
|
|
|
frame.mii_data = data;
|
|
|
|
rl_mii_writereg(sc, &frame);
|
|
|
|
|
2004-07-05 02:46:42 +00:00
|
|
|
return (0);
|
1999-08-31 14:45:51 +00:00
|
|
|
}
|
|
|
|
|
2002-08-23 23:49:02 +00:00
|
|
|
static void
|
2004-07-05 02:46:42 +00:00
|
|
|
rl_miibus_statchg(device_t dev)
|
1999-08-31 14:45:51 +00:00
|
|
|
{
|
1998-10-18 16:24:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Program the 64-bit multicast hash filter.
|
|
|
|
*/
|
2002-08-23 23:49:02 +00:00
|
|
|
static void
|
2004-07-05 02:46:42 +00:00
|
|
|
rl_setmulti(struct rl_softc *sc)
|
1998-10-18 16:24:34 +00:00
|
|
|
{
|
2005-06-10 16:49:24 +00:00
|
|
|
struct ifnet *ifp = sc->rl_ifp;
|
1998-10-18 16:24:34 +00:00
|
|
|
int h = 0;
|
2004-07-05 02:46:42 +00:00
|
|
|
uint32_t hashes[2] = { 0, 0 };
|
1998-10-18 16:24:34 +00:00
|
|
|
struct ifmultiaddr *ifma;
|
2004-07-05 02:46:42 +00:00
|
|
|
uint32_t rxfilt;
|
1998-10-18 16:24:34 +00:00
|
|
|
int mcnt = 0;
|
|
|
|
|
2004-07-05 02:51:32 +00:00
|
|
|
RL_LOCK_ASSERT(sc);
|
|
|
|
|
1998-10-18 16:24:34 +00:00
|
|
|
rxfilt = CSR_READ_4(sc, RL_RXCFG);
|
|
|
|
|
1999-01-22 15:25:04 +00:00
|
|
|
if (ifp->if_flags & IFF_ALLMULTI || ifp->if_flags & IFF_PROMISC) {
|
1998-10-18 16:24:34 +00:00
|
|
|
rxfilt |= RL_RXCFG_RX_MULTI;
|
|
|
|
CSR_WRITE_4(sc, RL_RXCFG, rxfilt);
|
|
|
|
CSR_WRITE_4(sc, RL_MAR0, 0xFFFFFFFF);
|
|
|
|
CSR_WRITE_4(sc, RL_MAR4, 0xFFFFFFFF);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* first, zot all the existing hash bits */
|
|
|
|
CSR_WRITE_4(sc, RL_MAR0, 0);
|
|
|
|
CSR_WRITE_4(sc, RL_MAR4, 0);
|
|
|
|
|
|
|
|
/* now program new ones */
|
2001-02-06 10:12:15 +00:00
|
|
|
TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
|
1998-10-18 16:24:34 +00:00
|
|
|
if (ifma->ifma_addr->sa_family != AF_LINK)
|
|
|
|
continue;
|
2004-06-09 14:34:04 +00:00
|
|
|
h = ether_crc32_be(LLADDR((struct sockaddr_dl *)
|
|
|
|
ifma->ifma_addr), ETHER_ADDR_LEN) >> 26;
|
1998-10-18 16:24:34 +00:00
|
|
|
if (h < 32)
|
|
|
|
hashes[0] |= (1 << h);
|
|
|
|
else
|
|
|
|
hashes[1] |= (1 << (h - 32));
|
|
|
|
mcnt++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mcnt)
|
|
|
|
rxfilt |= RL_RXCFG_RX_MULTI;
|
|
|
|
else
|
|
|
|
rxfilt &= ~RL_RXCFG_RX_MULTI;
|
|
|
|
|
|
|
|
CSR_WRITE_4(sc, RL_RXCFG, rxfilt);
|
|
|
|
CSR_WRITE_4(sc, RL_MAR0, hashes[0]);
|
|
|
|
CSR_WRITE_4(sc, RL_MAR4, hashes[1]);
|
|
|
|
}
|
|
|
|
|
2002-08-23 23:49:02 +00:00
|
|
|
static void
|
2004-07-05 02:46:42 +00:00
|
|
|
rl_reset(struct rl_softc *sc)
|
1998-10-18 16:24:34 +00:00
|
|
|
{
|
|
|
|
register int i;
|
|
|
|
|
2004-07-05 02:51:32 +00:00
|
|
|
RL_LOCK_ASSERT(sc);
|
|
|
|
|
1998-10-18 16:24:34 +00:00
|
|
|
CSR_WRITE_1(sc, RL_COMMAND, RL_CMD_RESET);
|
|
|
|
|
|
|
|
for (i = 0; i < RL_TIMEOUT; i++) {
|
|
|
|
DELAY(10);
|
|
|
|
if (!(CSR_READ_1(sc, RL_COMMAND) & RL_CMD_RESET))
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (i == RL_TIMEOUT)
|
2005-06-10 16:49:24 +00:00
|
|
|
if_printf(sc->rl_ifp, "reset never completed!\n");
|
1998-10-18 16:24:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Probe for a RealTek 8129/8139 chip. Check the PCI vendor and device
|
|
|
|
* IDs against our list and return a device name if we find a match.
|
|
|
|
*/
|
2002-08-23 23:49:02 +00:00
|
|
|
static int
|
2004-07-05 02:46:42 +00:00
|
|
|
rl_probe(device_t dev)
|
1998-10-18 16:24:34 +00:00
|
|
|
{
|
2004-07-05 02:46:42 +00:00
|
|
|
struct rl_softc *sc;
|
|
|
|
struct rl_type *t = rl_devs;
|
2003-07-10 20:38:48 +00:00
|
|
|
int rid;
|
2004-07-05 02:46:42 +00:00
|
|
|
uint32_t hwrev;
|
1998-10-18 16:24:34 +00:00
|
|
|
|
2003-07-10 20:38:48 +00:00
|
|
|
sc = device_get_softc(dev);
|
1998-10-18 16:24:34 +00:00
|
|
|
|
2004-07-05 02:46:42 +00:00
|
|
|
while (t->rl_name != NULL) {
|
1999-08-31 14:45:51 +00:00
|
|
|
if ((pci_get_vendor(dev) == t->rl_vid) &&
|
|
|
|
(pci_get_device(dev) == t->rl_did)) {
|
2003-07-10 20:38:48 +00:00
|
|
|
/*
|
|
|
|
* Temporarily map the I/O space
|
|
|
|
* so we can read the chip ID register.
|
|
|
|
*/
|
|
|
|
rid = RL_RID;
|
2004-03-17 17:50:55 +00:00
|
|
|
sc->rl_res = bus_alloc_resource_any(dev, RL_RES, &rid,
|
|
|
|
RF_ACTIVE);
|
2003-07-10 20:38:48 +00:00
|
|
|
if (sc->rl_res == NULL) {
|
|
|
|
device_printf(dev,
|
|
|
|
"couldn't map ports/memory\n");
|
2004-07-05 02:46:42 +00:00
|
|
|
return (ENXIO);
|
2003-07-10 20:38:48 +00:00
|
|
|
}
|
|
|
|
sc->rl_btag = rman_get_bustag(sc->rl_res);
|
|
|
|
sc->rl_bhandle = rman_get_bushandle(sc->rl_res);
|
2004-07-05 02:46:42 +00:00
|
|
|
|
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).
2003-09-08 02:11:25 +00:00
|
|
|
hwrev = CSR_READ_4(sc, RL_TXCFG) & RL_TXCFG_HWREV;
|
|
|
|
bus_release_resource(dev, RL_RES, RL_RID, sc->rl_res);
|
2004-07-05 02:46:42 +00:00
|
|
|
|
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).
2003-09-08 02:11:25 +00:00
|
|
|
/* Don't attach to 8139C+ or 8169/8110 chips. */
|
|
|
|
if (hwrev == RL_HWREV_8139CPLUS ||
|
2004-01-02 17:22:12 +00:00
|
|
|
(hwrev == RL_HWREV_8169 &&
|
|
|
|
t->rl_did == RT_DEVICEID_8169) ||
|
2003-09-10 15:12:55 +00:00
|
|
|
hwrev == RL_HWREV_8169S ||
|
|
|
|
hwrev == RL_HWREV_8110S) {
|
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).
2003-09-08 02:11:25 +00:00
|
|
|
t++;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
device_set_desc(dev, t->rl_name);
|
2005-02-24 21:32:56 +00:00
|
|
|
return (BUS_PROBE_DEFAULT);
|
1998-10-18 16:24:34 +00:00
|
|
|
}
|
|
|
|
t++;
|
|
|
|
}
|
|
|
|
|
2004-07-05 02:46:42 +00:00
|
|
|
return (ENXIO);
|
1998-10-18 16:24:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Attach the interface. Allocate softc structures, do ifmedia
|
|
|
|
* setup and ethernet/BPF attach.
|
|
|
|
*/
|
2002-08-23 23:49:02 +00:00
|
|
|
static int
|
2004-07-05 02:46:42 +00:00
|
|
|
rl_attach(device_t dev)
|
1998-10-18 16:24:34 +00:00
|
|
|
{
|
2004-07-05 02:46:42 +00:00
|
|
|
uint8_t eaddr[ETHER_ADDR_LEN];
|
|
|
|
uint16_t as[3];
|
1998-10-18 16:24:34 +00:00
|
|
|
struct ifnet *ifp;
|
2004-07-05 02:46:42 +00:00
|
|
|
struct rl_softc *sc;
|
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).
2003-09-08 02:11:25 +00:00
|
|
|
struct rl_type *t;
|
2004-07-05 02:46:42 +00:00
|
|
|
int error = 0, i, rid;
|
|
|
|
int unit;
|
|
|
|
uint16_t rl_did = 0;
|
1998-10-18 16:24:34 +00:00
|
|
|
|
1999-08-31 14:45:51 +00:00
|
|
|
sc = device_get_softc(dev);
|
|
|
|
unit = device_get_unit(dev);
|
1998-10-18 16:24:34 +00:00
|
|
|
|
2002-04-04 21:03:38 +00:00
|
|
|
mtx_init(&sc->rl_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK,
|
2004-07-05 02:51:32 +00:00
|
|
|
MTX_DEF);
|
2004-07-05 02:46:42 +00:00
|
|
|
|
2001-02-21 20:54:22 +00:00
|
|
|
pci_enable_busmaster(dev);
|
1998-10-18 16:24:34 +00:00
|
|
|
|
2004-07-05 02:46:42 +00:00
|
|
|
/* Map control/status registers. */
|
2003-01-11 16:11:21 +00:00
|
|
|
rid = RL_RID;
|
2004-03-17 17:50:55 +00:00
|
|
|
sc->rl_res = bus_alloc_resource_any(dev, RL_RES, &rid, RF_ACTIVE);
|
1999-08-31 14:45:51 +00:00
|
|
|
|
|
|
|
if (sc->rl_res == NULL) {
|
2004-07-05 02:46:42 +00:00
|
|
|
device_printf(dev, "couldn't map ports/memory\n");
|
1999-08-31 14:45:51 +00:00
|
|
|
error = ENXIO;
|
1998-10-18 16:24:34 +00:00
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
|
2003-07-10 20:38:48 +00:00
|
|
|
#ifdef notdef
|
2004-07-05 02:46:42 +00:00
|
|
|
/*
|
|
|
|
* Detect the Realtek 8139B. For some reason, this chip is very
|
2000-11-24 17:36:07 +00:00
|
|
|
* unstable when left to autoselect the media
|
|
|
|
* The best workaround is to set the device to the required
|
|
|
|
* media type or to set it to the 10 Meg speed.
|
|
|
|
*/
|
2004-07-05 02:46:42 +00:00
|
|
|
if ((rman_get_end(sc->rl_res) - rman_get_start(sc->rl_res)) == 0xFF)
|
|
|
|
device_printf(dev,
|
|
|
|
"Realtek 8139B detected. Warning, this may be unstable in autoselect mode\n");
|
2003-07-10 20:38:48 +00:00
|
|
|
#endif
|
2000-11-24 17:36:07 +00:00
|
|
|
|
1999-08-31 14:45:51 +00:00
|
|
|
sc->rl_btag = rman_get_bustag(sc->rl_res);
|
|
|
|
sc->rl_bhandle = rman_get_bushandle(sc->rl_res);
|
|
|
|
|
2003-03-31 17:29:43 +00:00
|
|
|
/* Allocate interrupt */
|
1999-08-31 14:45:51 +00:00
|
|
|
rid = 0;
|
2004-03-17 17:50:55 +00:00
|
|
|
sc->rl_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
|
1999-08-31 14:45:51 +00:00
|
|
|
RF_SHAREABLE | RF_ACTIVE);
|
|
|
|
|
|
|
|
if (sc->rl_irq == NULL) {
|
2004-07-05 02:46:42 +00:00
|
|
|
device_printf(dev, "couldn't map interrupt\n");
|
1999-08-31 14:45:51 +00:00
|
|
|
error = ENXIO;
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
|
2004-07-05 02:51:32 +00:00
|
|
|
/*
|
|
|
|
* Reset the adapter. Only take the lock here as it's needed in
|
|
|
|
* order to call rl_reset().
|
|
|
|
*/
|
|
|
|
RL_LOCK(sc);
|
1998-10-18 16:24:34 +00:00
|
|
|
rl_reset(sc);
|
2004-07-05 02:51:32 +00:00
|
|
|
RL_UNLOCK(sc);
|
|
|
|
|
2000-10-30 07:54:38 +00:00
|
|
|
sc->rl_eecmd_read = RL_EECMD_READ_6BIT;
|
2004-07-05 02:46:42 +00:00
|
|
|
rl_read_eeprom(sc, (uint8_t *)&rl_did, 0, 1, 0);
|
2000-11-01 23:56:46 +00:00
|
|
|
if (rl_did != 0x8129)
|
2000-10-30 07:54:38 +00:00
|
|
|
sc->rl_eecmd_read = RL_EECMD_READ_8BIT;
|
1998-10-18 16:24:34 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Get station address from the EEPROM.
|
|
|
|
*/
|
2004-07-05 02:46:42 +00:00
|
|
|
rl_read_eeprom(sc, (uint8_t *)as, RL_EE_EADDR, 3, 0);
|
2003-01-05 21:36:59 +00:00
|
|
|
for (i = 0; i < 3; i++) {
|
|
|
|
eaddr[(i * 2) + 0] = as[i] & 0xff;
|
|
|
|
eaddr[(i * 2) + 1] = as[i] >> 8;
|
|
|
|
}
|
1998-10-18 16:24:34 +00:00
|
|
|
|
|
|
|
sc->rl_unit = unit;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Now read the exact device type from the EEPROM to find
|
|
|
|
* out if it's an 8129 or 8139.
|
|
|
|
*/
|
2004-07-05 02:46:42 +00:00
|
|
|
rl_read_eeprom(sc, (uint8_t *)&rl_did, RL_EE_PCI_DID, 1, 0);
|
1998-10-18 16:24:34 +00:00
|
|
|
|
2003-07-10 20:38:48 +00:00
|
|
|
t = rl_devs;
|
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).
2003-09-08 02:11:25 +00:00
|
|
|
sc->rl_type = 0;
|
2003-07-10 20:38:48 +00:00
|
|
|
while(t->rl_name != NULL) {
|
|
|
|
if (rl_did == t->rl_did) {
|
|
|
|
sc->rl_type = t->rl_basetype;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
t++;
|
|
|
|
}
|
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).
2003-09-08 02:11:25 +00:00
|
|
|
|
|
|
|
if (sc->rl_type == 0) {
|
2004-07-05 02:46:42 +00:00
|
|
|
device_printf(dev, "unknown device ID: %x\n", rl_did);
|
1999-08-31 14:45:51 +00:00
|
|
|
error = ENXIO;
|
1998-10-18 16:24:34 +00:00
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
|
2001-08-15 17:38:43 +00:00
|
|
|
/*
|
|
|
|
* Allocate the parent bus DMA tag appropriate for PCI.
|
|
|
|
*/
|
|
|
|
#define RL_NSEG_NEW 32
|
2003-01-11 16:11:21 +00:00
|
|
|
error = bus_dma_tag_create(NULL, /* parent */
|
2001-08-15 17:38:43 +00:00
|
|
|
1, 0, /* alignment, boundary */
|
|
|
|
BUS_SPACE_MAXADDR_32BIT,/* lowaddr */
|
|
|
|
BUS_SPACE_MAXADDR, /* highaddr */
|
|
|
|
NULL, NULL, /* filter, filterarg */
|
|
|
|
MAXBSIZE, RL_NSEG_NEW, /* maxsize, nsegments */
|
2003-01-11 16:11:21 +00:00
|
|
|
BUS_SPACE_MAXSIZE_32BIT,/* maxsegsize */
|
2001-08-15 17:38:43 +00:00
|
|
|
BUS_DMA_ALLOCNOW, /* flags */
|
2003-07-01 15:52:06 +00:00
|
|
|
NULL, NULL, /* lockfunc, lockarg */
|
2001-08-15 17:38:43 +00:00
|
|
|
&sc->rl_parent_tag);
|
2003-03-31 17:29:43 +00:00
|
|
|
if (error)
|
|
|
|
goto fail;
|
2001-08-15 17:38:43 +00:00
|
|
|
|
|
|
|
/*
|
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).
2003-09-08 02:11:25 +00:00
|
|
|
* Now allocate a tag for the DMA descriptor lists.
|
|
|
|
* All of our lists are allocated as a contiguous block
|
|
|
|
* of memory.
|
2001-08-15 17:38:43 +00:00
|
|
|
*/
|
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).
2003-09-08 02:11:25 +00:00
|
|
|
error = bus_dma_tag_create(sc->rl_parent_tag, /* parent */
|
|
|
|
1, 0, /* alignment, boundary */
|
|
|
|
BUS_SPACE_MAXADDR, /* lowaddr */
|
|
|
|
BUS_SPACE_MAXADDR, /* highaddr */
|
|
|
|
NULL, NULL, /* filter, filterarg */
|
|
|
|
RL_RXBUFLEN + 1518, 1, /* maxsize,nsegments */
|
|
|
|
BUS_SPACE_MAXSIZE_32BIT,/* maxsegsize */
|
|
|
|
BUS_DMA_ALLOCNOW, /* flags */
|
|
|
|
NULL, NULL, /* lockfunc, lockarg */
|
|
|
|
&sc->rl_tag);
|
2003-07-10 20:38:48 +00:00
|
|
|
if (error)
|
1998-10-18 16:24:34 +00:00
|
|
|
goto fail;
|
1999-06-19 20:17:38 +00:00
|
|
|
|
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).
2003-09-08 02:11:25 +00:00
|
|
|
/*
|
|
|
|
* Now allocate a chunk of DMA-able memory based on the
|
|
|
|
* tag we just created.
|
|
|
|
*/
|
|
|
|
error = bus_dmamem_alloc(sc->rl_tag,
|
|
|
|
(void **)&sc->rl_cdata.rl_rx_buf, BUS_DMA_NOWAIT | BUS_DMA_ZERO,
|
|
|
|
&sc->rl_cdata.rl_rx_dmamap);
|
|
|
|
if (error) {
|
2004-07-05 02:46:42 +00:00
|
|
|
device_printf(dev, "no memory for list buffers!\n");
|
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).
2003-09-08 02:11:25 +00:00
|
|
|
bus_dma_tag_destroy(sc->rl_tag);
|
|
|
|
sc->rl_tag = NULL;
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Leave a few bytes before the start of the RX ring buffer. */
|
|
|
|
sc->rl_cdata.rl_rx_buf_ptr = sc->rl_cdata.rl_rx_buf;
|
2004-07-05 02:46:42 +00:00
|
|
|
sc->rl_cdata.rl_rx_buf += sizeof(uint64_t);
|
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).
2003-09-08 02:11:25 +00:00
|
|
|
|
2005-06-11 01:37:46 +00:00
|
|
|
ifp = sc->rl_ifp = if_alloc(IFT_ETHER);
|
|
|
|
if (ifp == NULL) {
|
|
|
|
device_printf(dev, "can not if_alloc()\n");
|
|
|
|
error = ENOSPC;
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
|
1999-08-31 14:45:51 +00:00
|
|
|
/* Do MII setup */
|
|
|
|
if (mii_phy_probe(dev, &sc->rl_miibus,
|
|
|
|
rl_ifmedia_upd, rl_ifmedia_sts)) {
|
2004-07-05 02:46:42 +00:00
|
|
|
device_printf(dev, "MII without any phy!\n");
|
1999-08-31 14:45:51 +00:00
|
|
|
error = ENXIO;
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
|
1998-10-18 16:24:34 +00:00
|
|
|
ifp->if_softc = sc;
|
2003-10-31 18:32:15 +00:00
|
|
|
if_initname(ifp, device_get_name(dev), device_get_unit(dev));
|
1998-10-18 16:24:34 +00:00
|
|
|
ifp->if_mtu = ETHERMTU;
|
|
|
|
ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
|
|
|
|
ifp->if_ioctl = rl_ioctl;
|
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).
2003-09-08 02:11:25 +00:00
|
|
|
ifp->if_start = rl_start;
|
1998-10-18 16:24:34 +00:00
|
|
|
ifp->if_watchdog = rl_watchdog;
|
|
|
|
ifp->if_init = rl_init;
|
|
|
|
ifp->if_baudrate = 10000000;
|
2003-09-11 03:53:46 +00:00
|
|
|
ifp->if_capabilities = IFCAP_VLAN_MTU;
|
2004-04-11 16:23:16 +00:00
|
|
|
#ifdef DEVICE_POLLING
|
|
|
|
ifp->if_capabilities |= IFCAP_POLLING;
|
|
|
|
#endif
|
2003-09-11 04:05:01 +00:00
|
|
|
ifp->if_capenable = ifp->if_capabilities;
|
2004-07-02 12:16:02 +00:00
|
|
|
IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
|
|
|
|
ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN;
|
|
|
|
IFQ_SET_READY(&ifp->if_snd);
|
2004-07-05 02:46:42 +00:00
|
|
|
|
2003-03-31 17:29:43 +00:00
|
|
|
callout_handle_init(&sc->rl_stat_ch);
|
|
|
|
|
1998-10-18 16:24:34 +00:00
|
|
|
/*
|
2000-07-13 22:54:34 +00:00
|
|
|
* Call MI attach routine.
|
1998-10-18 16:24:34 +00:00
|
|
|
*/
|
2002-11-14 23:49:09 +00:00
|
|
|
ether_ifattach(ifp, eaddr);
|
1998-10-18 16:24:34 +00:00
|
|
|
|
2003-04-17 20:32:06 +00:00
|
|
|
/* Hook interrupt last to avoid having to lock softc */
|
2004-07-05 02:51:32 +00:00
|
|
|
error = bus_setup_intr(dev, sc->rl_irq, INTR_TYPE_NET | INTR_MPSAFE,
|
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).
2003-09-08 02:11:25 +00:00
|
|
|
rl_intr, sc, &sc->rl_intrhand);
|
2002-10-29 19:02:19 +00:00
|
|
|
if (error) {
|
2004-07-05 02:46:42 +00:00
|
|
|
if_printf(ifp, "couldn't set up irq\n");
|
2003-04-17 20:32:06 +00:00
|
|
|
ether_ifdetach(ifp);
|
2005-06-10 16:49:24 +00:00
|
|
|
if_free(ifp);
|
2002-10-29 19:02:19 +00:00
|
|
|
}
|
|
|
|
|
1998-10-18 16:24:34 +00:00
|
|
|
fail:
|
2003-03-31 17:29:43 +00:00
|
|
|
if (error)
|
|
|
|
rl_detach(dev);
|
|
|
|
|
2003-02-09 22:32:50 +00:00
|
|
|
return (error);
|
1999-08-31 14:45:51 +00:00
|
|
|
}
|
|
|
|
|
2003-04-17 20:32:06 +00:00
|
|
|
/*
|
|
|
|
* Shutdown hardware and free up resources. This can be called any
|
|
|
|
* time after the mutex has been initialized. It is called in both
|
|
|
|
* the error case in attach and the normal detach case so it needs
|
|
|
|
* to be careful about only freeing resources that have actually been
|
|
|
|
* allocated.
|
|
|
|
*/
|
2002-08-23 23:49:02 +00:00
|
|
|
static int
|
2004-07-05 02:46:42 +00:00
|
|
|
rl_detach(device_t dev)
|
1999-08-31 14:45:51 +00:00
|
|
|
{
|
|
|
|
struct rl_softc *sc;
|
|
|
|
struct ifnet *ifp;
|
2004-08-09 20:22:17 +00:00
|
|
|
int attached;
|
1999-08-31 14:45:51 +00:00
|
|
|
|
|
|
|
sc = device_get_softc(dev);
|
2005-06-10 16:49:24 +00:00
|
|
|
ifp = sc->rl_ifp;
|
2004-07-05 02:46:42 +00:00
|
|
|
|
2003-03-31 20:22:00 +00:00
|
|
|
KASSERT(mtx_initialized(&sc->rl_mtx), ("rl mutex not initialized"));
|
2004-08-09 20:22:17 +00:00
|
|
|
attached = device_is_attached(dev);
|
|
|
|
/* These should only be active if attach succeeded */
|
2005-06-10 16:49:24 +00:00
|
|
|
if (attached) {
|
2004-08-09 20:22:17 +00:00
|
|
|
ether_ifdetach(ifp);
|
2005-06-10 16:49:24 +00:00
|
|
|
if_free(ifp);
|
|
|
|
}
|
2000-10-13 17:54:19 +00:00
|
|
|
RL_LOCK(sc);
|
2004-07-05 02:51:32 +00:00
|
|
|
#if 0
|
|
|
|
sc->suspended = 1;
|
|
|
|
#endif
|
2004-08-09 20:22:17 +00:00
|
|
|
if (attached)
|
2003-04-17 20:32:06 +00:00
|
|
|
rl_stop(sc);
|
|
|
|
if (sc->rl_miibus)
|
|
|
|
device_delete_child(dev, sc->rl_miibus);
|
|
|
|
bus_generic_detach(dev);
|
1999-08-31 14:45:51 +00:00
|
|
|
|
2003-03-31 17:29:43 +00:00
|
|
|
if (sc->rl_intrhand)
|
|
|
|
bus_teardown_intr(dev, sc->rl_irq, sc->rl_intrhand);
|
|
|
|
if (sc->rl_irq)
|
|
|
|
bus_release_resource(dev, SYS_RES_IRQ, 0, sc->rl_irq);
|
|
|
|
if (sc->rl_res)
|
|
|
|
bus_release_resource(dev, RL_RES, RL_RID, sc->rl_res);
|
1999-08-31 14:45:51 +00:00
|
|
|
|
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).
2003-09-08 02:11:25 +00:00
|
|
|
if (sc->rl_tag) {
|
|
|
|
bus_dmamap_unload(sc->rl_tag, sc->rl_cdata.rl_rx_dmamap);
|
|
|
|
bus_dmamem_free(sc->rl_tag, sc->rl_cdata.rl_rx_buf,
|
|
|
|
sc->rl_cdata.rl_rx_dmamap);
|
|
|
|
bus_dma_tag_destroy(sc->rl_tag);
|
2003-03-31 17:29:43 +00:00
|
|
|
}
|
|
|
|
if (sc->rl_parent_tag)
|
|
|
|
bus_dma_tag_destroy(sc->rl_parent_tag);
|
1999-08-31 14:45:51 +00:00
|
|
|
|
2000-10-13 17:54:19 +00:00
|
|
|
RL_UNLOCK(sc);
|
|
|
|
mtx_destroy(&sc->rl_mtx);
|
1999-08-31 14:45:51 +00:00
|
|
|
|
2004-07-05 02:46:42 +00:00
|
|
|
return (0);
|
1998-10-18 16:24:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Initialize the transmit descriptors.
|
|
|
|
*/
|
2002-08-23 23:49:02 +00:00
|
|
|
static int
|
2004-07-05 02:46:42 +00:00
|
|
|
rl_list_tx_init(struct rl_softc *sc)
|
1998-10-18 16:24:34 +00:00
|
|
|
{
|
|
|
|
struct rl_chain_data *cd;
|
|
|
|
int i;
|
|
|
|
|
2004-07-05 02:51:32 +00:00
|
|
|
RL_LOCK_ASSERT(sc);
|
|
|
|
|
1998-10-18 16:24:34 +00:00
|
|
|
cd = &sc->rl_cdata;
|
|
|
|
for (i = 0; i < RL_TX_LIST_CNT; i++) {
|
1999-04-12 21:37:00 +00:00
|
|
|
cd->rl_tx_chain[i] = NULL;
|
1999-06-19 20:17:38 +00:00
|
|
|
CSR_WRITE_4(sc,
|
2004-07-05 02:46:42 +00:00
|
|
|
RL_TXADDR0 + (i * sizeof(uint32_t)), 0x0000000);
|
1998-10-18 16:24:34 +00:00
|
|
|
}
|
|
|
|
|
1999-04-12 21:37:00 +00:00
|
|
|
sc->rl_cdata.cur_tx = 0;
|
|
|
|
sc->rl_cdata.last_tx = 0;
|
1998-10-18 16:24:34 +00:00
|
|
|
|
2004-07-05 02:46:42 +00:00
|
|
|
return (0);
|
1998-10-18 16:24:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* A frame has been uploaded: pass the resulting mbuf chain up to
|
|
|
|
* the higher level protocols.
|
|
|
|
*
|
|
|
|
* You know there's something wrong with a PCI bus-master chip design
|
|
|
|
* when you have to use m_devget().
|
|
|
|
*
|
|
|
|
* The receive operation is badly documented in the datasheet, so I'll
|
|
|
|
* attempt to document it here. The driver provides a buffer area and
|
|
|
|
* places its base address in the RX buffer start address register.
|
|
|
|
* The chip then begins copying frames into the RX buffer. Each frame
|
2001-02-18 10:43:53 +00:00
|
|
|
* is preceded by a 32-bit RX status word which specifies the length
|
1998-10-18 16:24:34 +00:00
|
|
|
* of the frame and certain other status bits. Each frame (starting with
|
|
|
|
* the status word) is also 32-bit aligned. The frame length is in the
|
|
|
|
* first 16 bits of the status word; the lower 15 bits correspond with
|
|
|
|
* the 'rx status register' mentioned in the datasheet.
|
1999-06-19 20:17:38 +00:00
|
|
|
*
|
|
|
|
* Note: to make the Alpha happy, the frame payload needs to be aligned
|
2001-06-20 19:48:35 +00:00
|
|
|
* on a 32-bit boundary. To achieve this, we pass RL_ETHER_ALIGN (2 bytes)
|
2003-01-11 16:11:21 +00:00
|
|
|
* as the offset argument to m_devget().
|
1998-10-18 16:24:34 +00:00
|
|
|
*/
|
2002-08-23 23:49:02 +00:00
|
|
|
static void
|
2004-07-05 02:46:42 +00:00
|
|
|
rl_rxeof(struct rl_softc *sc)
|
1998-10-18 16:24:34 +00:00
|
|
|
{
|
2003-01-11 16:11:21 +00:00
|
|
|
struct mbuf *m;
|
2005-06-10 16:49:24 +00:00
|
|
|
struct ifnet *ifp = sc->rl_ifp;
|
2004-07-05 02:46:42 +00:00
|
|
|
uint8_t *rxbufpos;
|
1998-10-18 16:24:34 +00:00
|
|
|
int total_len = 0;
|
|
|
|
int wrap = 0;
|
2004-07-05 02:46:42 +00:00
|
|
|
uint32_t rxstat;
|
|
|
|
uint16_t cur_rx;
|
|
|
|
uint16_t limit;
|
|
|
|
uint16_t max_bytes, rx_bytes = 0;
|
1998-10-18 16:24:34 +00:00
|
|
|
|
2003-11-14 19:00:32 +00:00
|
|
|
RL_LOCK_ASSERT(sc);
|
|
|
|
|
2001-08-15 17:38:43 +00:00
|
|
|
bus_dmamap_sync(sc->rl_tag, sc->rl_cdata.rl_rx_dmamap,
|
2003-01-05 21:36:59 +00:00
|
|
|
BUS_DMASYNC_POSTREAD);
|
2001-08-15 17:38:43 +00:00
|
|
|
|
1998-10-18 16:24:34 +00:00
|
|
|
cur_rx = (CSR_READ_2(sc, RL_CURRXADDR) + 16) % RL_RXBUFLEN;
|
|
|
|
|
|
|
|
/* Do not try to read past this point. */
|
|
|
|
limit = CSR_READ_2(sc, RL_CURRXBUF) % RL_RXBUFLEN;
|
|
|
|
|
|
|
|
if (limit < cur_rx)
|
|
|
|
max_bytes = (RL_RXBUFLEN - cur_rx) + limit;
|
|
|
|
else
|
|
|
|
max_bytes = limit - cur_rx;
|
|
|
|
|
1999-01-16 21:03:57 +00:00
|
|
|
while((CSR_READ_1(sc, RL_COMMAND) & RL_CMD_EMPTY_RXBUF) == 0) {
|
2002-04-16 22:03:14 +00:00
|
|
|
#ifdef DEVICE_POLLING
|
2002-08-18 07:05:00 +00:00
|
|
|
if (ifp->if_flags & IFF_POLLING) {
|
2002-04-16 22:03:14 +00:00
|
|
|
if (sc->rxcycles <= 0)
|
|
|
|
break;
|
|
|
|
sc->rxcycles--;
|
|
|
|
}
|
|
|
|
#endif /* DEVICE_POLLING */
|
1998-10-18 16:24:34 +00:00
|
|
|
rxbufpos = sc->rl_cdata.rl_rx_buf + cur_rx;
|
2004-07-05 02:46:42 +00:00
|
|
|
rxstat = le32toh(*(uint32_t *)rxbufpos);
|
1998-10-18 16:24:34 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Here's a totally undocumented fact for you. When the
|
|
|
|
* RealTek chip is in the process of copying a packet into
|
|
|
|
* RAM for you, the length will be 0xfff0. If you spot a
|
|
|
|
* packet header with this value, you need to stop. The
|
|
|
|
* datasheet makes absolutely no mention of this and
|
|
|
|
* RealTek should be shot for this.
|
|
|
|
*/
|
2004-07-05 02:46:42 +00:00
|
|
|
if ((uint16_t)(rxstat >> 16) == RL_RXSTAT_UNFINISHED)
|
1998-10-18 16:24:34 +00:00
|
|
|
break;
|
2003-01-11 16:11:21 +00:00
|
|
|
|
1998-10-18 16:24:34 +00:00
|
|
|
if (!(rxstat & RL_RXSTAT_RXOK)) {
|
|
|
|
ifp->if_ierrors++;
|
2004-07-09 00:07:06 +00:00
|
|
|
rl_init_locked(sc);
|
1999-08-31 14:45:51 +00:00
|
|
|
return;
|
1998-10-18 16:24:34 +00:00
|
|
|
}
|
|
|
|
|
2003-01-11 16:11:21 +00:00
|
|
|
/* No errors; receive the packet. */
|
1998-10-18 16:24:34 +00:00
|
|
|
total_len = rxstat >> 16;
|
|
|
|
rx_bytes += total_len + 4;
|
|
|
|
|
1998-12-24 18:39:48 +00:00
|
|
|
/*
|
|
|
|
* XXX The RealTek chip includes the CRC with every
|
|
|
|
* received frame, and there's no way to turn this
|
|
|
|
* behavior off (at least, I can't find anything in
|
2003-01-11 16:11:21 +00:00
|
|
|
* the manual that explains how to do it) so we have
|
1998-12-24 18:39:48 +00:00
|
|
|
* to trim off the CRC manually.
|
|
|
|
*/
|
|
|
|
total_len -= ETHER_CRC_LEN;
|
|
|
|
|
1998-10-18 16:24:34 +00:00
|
|
|
/*
|
|
|
|
* Avoid trying to read more bytes than we know
|
|
|
|
* the chip has prepared for us.
|
|
|
|
*/
|
|
|
|
if (rx_bytes > max_bytes)
|
|
|
|
break;
|
|
|
|
|
|
|
|
rxbufpos = sc->rl_cdata.rl_rx_buf +
|
2004-07-05 02:46:42 +00:00
|
|
|
((cur_rx + sizeof(uint32_t)) % RL_RXBUFLEN);
|
1998-10-18 16:24:34 +00:00
|
|
|
if (rxbufpos == (sc->rl_cdata.rl_rx_buf + RL_RXBUFLEN))
|
|
|
|
rxbufpos = sc->rl_cdata.rl_rx_buf;
|
|
|
|
|
|
|
|
wrap = (sc->rl_cdata.rl_rx_buf + RL_RXBUFLEN) - rxbufpos;
|
|
|
|
if (total_len > wrap) {
|
2001-06-20 19:48:35 +00:00
|
|
|
m = m_devget(rxbufpos, total_len, RL_ETHER_ALIGN, ifp,
|
|
|
|
NULL);
|
1998-10-18 16:24:34 +00:00
|
|
|
if (m == NULL) {
|
|
|
|
ifp->if_ierrors++;
|
1999-10-21 19:42:03 +00:00
|
|
|
} else {
|
1998-10-18 16:24:34 +00:00
|
|
|
m_copyback(m, wrap, total_len - wrap,
|
|
|
|
sc->rl_cdata.rl_rx_buf);
|
1999-06-19 20:17:38 +00:00
|
|
|
}
|
1998-12-24 18:39:48 +00:00
|
|
|
cur_rx = (total_len - wrap + ETHER_CRC_LEN);
|
1998-10-18 16:24:34 +00:00
|
|
|
} else {
|
2001-06-20 19:48:35 +00:00
|
|
|
m = m_devget(rxbufpos, total_len, RL_ETHER_ALIGN, ifp,
|
|
|
|
NULL);
|
2004-07-05 02:46:42 +00:00
|
|
|
if (m == NULL)
|
1998-10-18 16:24:34 +00:00
|
|
|
ifp->if_ierrors++;
|
1998-12-24 18:39:48 +00:00
|
|
|
cur_rx += total_len + 4 + ETHER_CRC_LEN;
|
1998-10-18 16:24:34 +00:00
|
|
|
}
|
|
|
|
|
2004-07-05 02:46:42 +00:00
|
|
|
/* Round up to 32-bit boundary. */
|
1998-10-18 16:24:34 +00:00
|
|
|
cur_rx = (cur_rx + 3) & ~3;
|
|
|
|
CSR_WRITE_2(sc, RL_CURRXADDR, cur_rx - 16);
|
|
|
|
|
|
|
|
if (m == NULL)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
ifp->if_ipackets++;
|
2003-11-14 19:00:32 +00:00
|
|
|
RL_UNLOCK(sc);
|
2002-11-14 23:49:09 +00:00
|
|
|
(*ifp->if_input)(ifp, m);
|
2003-11-14 19:00:32 +00:00
|
|
|
RL_LOCK(sc);
|
1998-10-18 16:24:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* A frame was downloaded to the chip. It's safe for us to clean up
|
|
|
|
* the list buffers.
|
|
|
|
*/
|
2002-08-23 23:49:02 +00:00
|
|
|
static void
|
2004-07-05 02:46:42 +00:00
|
|
|
rl_txeof(struct rl_softc *sc)
|
1998-10-18 16:24:34 +00:00
|
|
|
{
|
2005-06-10 16:49:24 +00:00
|
|
|
struct ifnet *ifp = sc->rl_ifp;
|
2004-07-05 02:46:42 +00:00
|
|
|
uint32_t txstat;
|
1998-10-18 16:24:34 +00:00
|
|
|
|
2004-07-05 02:51:32 +00:00
|
|
|
RL_LOCK_ASSERT(sc);
|
|
|
|
|
1998-10-18 16:24:34 +00:00
|
|
|
/*
|
|
|
|
* Go through our tx list and free mbufs for those
|
|
|
|
* frames that have been uploaded.
|
|
|
|
*/
|
1999-04-12 21:37:00 +00:00
|
|
|
do {
|
Fixed a few bugs in the rl(4) driver:
Under polling(4), we counted non-existent output packets and wasted
CPU cycles, corrected. (PR kern/64975.)
The fix in revision 1.71 to correct resetting of the watchdog timer
was wrong.
In rl(4), the TX list does not have a gap between the consumer and
producer, so the "empty TX list" test was wrong, corrected.
Also, resetting the timer to five each time we know there is still
some TX work to do was a bad idea -- under polling(4), if the chip
goes out to lunch, this results in the watchdog routine to _never_
be called. Instead, let the timer downgrade to zero and fire the
watchdog, then reset it to five when it is zero AND there is some
TX work left. (Most other network drivers need this fix too.)
MFC after: 3 days
2004-04-03 00:42:33 +00:00
|
|
|
if (RL_LAST_TXMBUF(sc) == NULL)
|
|
|
|
break;
|
1999-04-12 21:37:00 +00:00
|
|
|
txstat = CSR_READ_4(sc, RL_LAST_TXSTAT(sc));
|
|
|
|
if (!(txstat & (RL_TXSTAT_TX_OK|
|
|
|
|
RL_TXSTAT_TX_UNDERRUN|RL_TXSTAT_TXABRT)))
|
1998-10-18 16:24:34 +00:00
|
|
|
break;
|
|
|
|
|
1999-04-12 21:37:00 +00:00
|
|
|
ifp->if_collisions += (txstat & RL_TXSTAT_COLLCNT) >> 24;
|
1998-10-18 16:24:34 +00:00
|
|
|
|
Fixed a few bugs in the rl(4) driver:
Under polling(4), we counted non-existent output packets and wasted
CPU cycles, corrected. (PR kern/64975.)
The fix in revision 1.71 to correct resetting of the watchdog timer
was wrong.
In rl(4), the TX list does not have a gap between the consumer and
producer, so the "empty TX list" test was wrong, corrected.
Also, resetting the timer to five each time we know there is still
some TX work to do was a bad idea -- under polling(4), if the chip
goes out to lunch, this results in the watchdog routine to _never_
be called. Instead, let the timer downgrade to zero and fire the
watchdog, then reset it to five when it is zero AND there is some
TX work left. (Most other network drivers need this fix too.)
MFC after: 3 days
2004-04-03 00:42:33 +00:00
|
|
|
bus_dmamap_unload(sc->rl_tag, RL_LAST_DMAMAP(sc));
|
|
|
|
bus_dmamap_destroy(sc->rl_tag, RL_LAST_DMAMAP(sc));
|
|
|
|
m_freem(RL_LAST_TXMBUF(sc));
|
|
|
|
RL_LAST_TXMBUF(sc) = NULL;
|
2005-02-11 01:05:52 +00:00
|
|
|
/*
|
|
|
|
* If there was a transmit underrun, bump the TX threshold.
|
|
|
|
* Make sure not to overflow the 63 * 32byte we can address
|
|
|
|
* with the 6 available bit.
|
|
|
|
*/
|
|
|
|
if ((txstat & RL_TXSTAT_TX_UNDERRUN) &&
|
|
|
|
(sc->rl_txthresh < 2016))
|
|
|
|
sc->rl_txthresh += 32;
|
1999-04-12 21:37:00 +00:00
|
|
|
if (txstat & RL_TXSTAT_TX_OK)
|
|
|
|
ifp->if_opackets++;
|
|
|
|
else {
|
1999-10-21 19:42:03 +00:00
|
|
|
int oldthresh;
|
1999-04-12 21:37:00 +00:00
|
|
|
ifp->if_oerrors++;
|
|
|
|
if ((txstat & RL_TXSTAT_TXABRT) ||
|
|
|
|
(txstat & RL_TXSTAT_OUTOFWIN))
|
|
|
|
CSR_WRITE_4(sc, RL_TXCFG, RL_TXCFG_CONFIG);
|
1999-10-21 19:42:03 +00:00
|
|
|
oldthresh = sc->rl_txthresh;
|
|
|
|
/* error recovery */
|
|
|
|
rl_reset(sc);
|
2004-07-09 00:07:06 +00:00
|
|
|
rl_init_locked(sc);
|
2005-02-11 01:05:52 +00:00
|
|
|
/* restore original threshold */
|
|
|
|
sc->rl_txthresh = oldthresh;
|
1999-10-21 19:42:03 +00:00
|
|
|
return;
|
1999-04-12 21:37:00 +00:00
|
|
|
}
|
|
|
|
RL_INC(sc->rl_cdata.last_tx);
|
1998-10-18 16:24:34 +00:00
|
|
|
ifp->if_flags &= ~IFF_OACTIVE;
|
1999-04-12 21:37:00 +00:00
|
|
|
} while (sc->rl_cdata.last_tx != sc->rl_cdata.cur_tx);
|
|
|
|
|
Fixed a few bugs in the rl(4) driver:
Under polling(4), we counted non-existent output packets and wasted
CPU cycles, corrected. (PR kern/64975.)
The fix in revision 1.71 to correct resetting of the watchdog timer
was wrong.
In rl(4), the TX list does not have a gap between the consumer and
producer, so the "empty TX list" test was wrong, corrected.
Also, resetting the timer to five each time we know there is still
some TX work to do was a bad idea -- under polling(4), if the chip
goes out to lunch, this results in the watchdog routine to _never_
be called. Instead, let the timer downgrade to zero and fire the
watchdog, then reset it to five when it is zero AND there is some
TX work left. (Most other network drivers need this fix too.)
MFC after: 3 days
2004-04-03 00:42:33 +00:00
|
|
|
if (RL_LAST_TXMBUF(sc) == NULL)
|
|
|
|
ifp->if_timer = 0;
|
|
|
|
else if (ifp->if_timer == 0)
|
|
|
|
ifp->if_timer = 5;
|
1999-08-31 14:45:51 +00:00
|
|
|
}
|
|
|
|
|
2002-08-23 23:49:02 +00:00
|
|
|
static void
|
2004-07-05 02:46:42 +00:00
|
|
|
rl_tick(void *xsc)
|
1999-08-31 14:45:51 +00:00
|
|
|
{
|
2004-07-05 02:46:42 +00:00
|
|
|
struct rl_softc *sc = xsc;
|
1999-08-31 14:45:51 +00:00
|
|
|
struct mii_data *mii;
|
|
|
|
|
2000-10-13 17:54:19 +00:00
|
|
|
RL_LOCK(sc);
|
1999-08-31 14:45:51 +00:00
|
|
|
mii = device_get_softc(sc->rl_miibus);
|
|
|
|
mii_tick(mii);
|
|
|
|
|
|
|
|
sc->rl_stat_ch = timeout(rl_tick, sc, hz);
|
2000-10-13 17:54:19 +00:00
|
|
|
RL_UNLOCK(sc);
|
1998-10-18 16:24:34 +00:00
|
|
|
}
|
|
|
|
|
2002-04-16 22:03:14 +00:00
|
|
|
#ifdef DEVICE_POLLING
|
|
|
|
static void
|
2004-07-09 00:07:06 +00:00
|
|
|
rl_poll(struct ifnet *ifp, enum poll_cmd cmd, int count)
|
2002-04-16 22:03:14 +00:00
|
|
|
{
|
|
|
|
struct rl_softc *sc = ifp->if_softc;
|
|
|
|
|
|
|
|
RL_LOCK(sc);
|
2004-07-09 00:07:06 +00:00
|
|
|
rl_poll_locked(ifp, cmd, count);
|
|
|
|
RL_UNLOCK(sc);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
rl_poll_locked(struct ifnet *ifp, enum poll_cmd cmd, int count)
|
|
|
|
{
|
|
|
|
struct rl_softc *sc = ifp->if_softc;
|
|
|
|
|
|
|
|
RL_LOCK_ASSERT(sc);
|
2004-07-05 02:46:42 +00:00
|
|
|
|
2004-04-11 16:23:16 +00:00
|
|
|
if (!(ifp->if_capenable & IFCAP_POLLING)) {
|
|
|
|
ether_poll_deregister(ifp);
|
|
|
|
cmd = POLL_DEREGISTER;
|
|
|
|
}
|
2004-07-05 02:46:42 +00:00
|
|
|
|
|
|
|
if (cmd == POLL_DEREGISTER) {
|
|
|
|
/* Final call; enable interrupts. */
|
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).
2003-09-08 02:11:25 +00:00
|
|
|
CSR_WRITE_2(sc, RL_IMR, RL_INTRS);
|
2004-07-09 00:07:06 +00:00
|
|
|
return;
|
2002-04-16 22:03:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
sc->rxcycles = count;
|
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).
2003-09-08 02:11:25 +00:00
|
|
|
rl_rxeof(sc);
|
|
|
|
rl_txeof(sc);
|
2004-07-05 02:46:42 +00:00
|
|
|
|
2004-07-09 00:07:06 +00:00
|
|
|
if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
|
|
|
|
rl_start_locked(ifp);
|
2002-04-16 22:03:14 +00:00
|
|
|
|
2004-07-05 02:46:42 +00:00
|
|
|
if (cmd == POLL_AND_CHECK_STATUS) {
|
|
|
|
uint16_t status;
|
2002-04-16 22:03:14 +00:00
|
|
|
|
2004-07-05 02:46:42 +00:00
|
|
|
/* We should also check the status register. */
|
2002-04-16 22:03:14 +00:00
|
|
|
status = CSR_READ_2(sc, RL_ISR);
|
2002-07-30 17:31:42 +00:00
|
|
|
if (status == 0xffff)
|
2004-07-09 00:07:06 +00:00
|
|
|
return;
|
2004-07-05 02:46:42 +00:00
|
|
|
if (status != 0)
|
2002-04-16 22:03:14 +00:00
|
|
|
CSR_WRITE_2(sc, RL_ISR, status);
|
|
|
|
|
2004-07-05 02:46:42 +00:00
|
|
|
/* XXX We should check behaviour on receiver stalls. */
|
2002-04-16 22:03:14 +00:00
|
|
|
|
|
|
|
if (status & RL_ISR_SYSTEM_ERR) {
|
|
|
|
rl_reset(sc);
|
2004-07-09 00:07:06 +00:00
|
|
|
rl_init_locked(sc);
|
2002-04-16 22:03:14 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif /* DEVICE_POLLING */
|
|
|
|
|
2002-08-23 23:49:02 +00:00
|
|
|
static void
|
2004-07-05 02:46:42 +00:00
|
|
|
rl_intr(void *arg)
|
1998-10-18 16:24:34 +00:00
|
|
|
{
|
2004-07-05 02:46:42 +00:00
|
|
|
struct rl_softc *sc = arg;
|
2005-06-10 16:49:24 +00:00
|
|
|
struct ifnet *ifp = sc->rl_ifp;
|
2004-07-05 02:46:42 +00:00
|
|
|
uint16_t status;
|
2001-11-23 14:27:33 +00:00
|
|
|
|
2000-10-13 17:54:19 +00:00
|
|
|
RL_LOCK(sc);
|
2004-07-05 02:51:32 +00:00
|
|
|
|
2004-07-09 00:07:06 +00:00
|
|
|
if (sc->suspended)
|
|
|
|
goto done_locked;
|
1998-10-18 16:24:34 +00:00
|
|
|
|
2002-04-16 22:03:14 +00:00
|
|
|
#ifdef DEVICE_POLLING
|
2004-07-09 00:07:06 +00:00
|
|
|
if (ifp->if_flags & IFF_POLLING)
|
|
|
|
goto done_locked;
|
|
|
|
|
2004-04-11 16:23:16 +00:00
|
|
|
if ((ifp->if_capenable & IFCAP_POLLING) &&
|
2004-07-05 02:46:42 +00:00
|
|
|
ether_poll_register(rl_poll, ifp)) {
|
|
|
|
/* Disable interrupts. */
|
2002-04-16 22:03:14 +00:00
|
|
|
CSR_WRITE_2(sc, RL_IMR, 0x0000);
|
2004-07-09 00:07:06 +00:00
|
|
|
rl_poll_locked(ifp, 0, 1);
|
|
|
|
goto done_locked;
|
2002-04-16 22:03:14 +00:00
|
|
|
}
|
|
|
|
#endif /* DEVICE_POLLING */
|
1998-10-18 16:24:34 +00:00
|
|
|
|
|
|
|
for (;;) {
|
|
|
|
status = CSR_READ_2(sc, RL_ISR);
|
2004-07-05 02:46:42 +00:00
|
|
|
/* If the card has gone away, the read returns 0xffff. */
|
2002-07-30 17:31:42 +00:00
|
|
|
if (status == 0xffff)
|
|
|
|
break;
|
2004-07-05 02:46:42 +00:00
|
|
|
if (status != 0)
|
1998-10-18 16:24:34 +00:00
|
|
|
CSR_WRITE_2(sc, RL_ISR, status);
|
|
|
|
if ((status & RL_INTRS) == 0)
|
|
|
|
break;
|
|
|
|
if (status & RL_ISR_RX_OK)
|
|
|
|
rl_rxeof(sc);
|
|
|
|
if (status & RL_ISR_RX_ERR)
|
|
|
|
rl_rxeof(sc);
|
1999-04-12 21:37:00 +00:00
|
|
|
if ((status & RL_ISR_TX_OK) || (status & RL_ISR_TX_ERR))
|
1998-10-18 16:24:34 +00:00
|
|
|
rl_txeof(sc);
|
|
|
|
if (status & RL_ISR_SYSTEM_ERR) {
|
|
|
|
rl_reset(sc);
|
2004-07-09 00:07:06 +00:00
|
|
|
rl_init_locked(sc);
|
1998-10-18 16:24:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-07-02 12:16:02 +00:00
|
|
|
if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
|
2004-07-09 00:07:06 +00:00
|
|
|
rl_start_locked(ifp);
|
|
|
|
|
|
|
|
done_locked:
|
|
|
|
RL_UNLOCK(sc);
|
1998-10-18 16:24:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Encapsulate an mbuf chain in a descriptor by coupling the mbuf data
|
|
|
|
* pointers to the fragment pointers.
|
|
|
|
*/
|
2002-08-23 23:49:02 +00:00
|
|
|
static int
|
2004-07-05 02:46:42 +00:00
|
|
|
rl_encap(struct rl_softc *sc, struct mbuf *m_head)
|
1998-10-18 16:24:34 +00:00
|
|
|
{
|
1998-11-18 21:03:58 +00:00
|
|
|
struct mbuf *m_new = NULL;
|
1998-10-18 16:24:34 +00:00
|
|
|
|
2004-07-05 02:51:32 +00:00
|
|
|
RL_LOCK_ASSERT(sc);
|
|
|
|
|
1998-10-18 16:24:34 +00:00
|
|
|
/*
|
1999-04-12 21:37:00 +00:00
|
|
|
* The RealTek is brain damaged and wants longword-aligned
|
|
|
|
* TX buffers, plus we can only have one fragment buffer
|
|
|
|
* per packet. We have to copy pretty much all the time.
|
1998-10-18 16:24:34 +00:00
|
|
|
*/
|
2003-03-30 03:45:28 +00:00
|
|
|
m_new = m_defrag(m_head, M_DONTWAIT);
|
1998-10-18 16:24:34 +00:00
|
|
|
|
2003-04-15 04:06:01 +00:00
|
|
|
if (m_new == NULL) {
|
|
|
|
m_freem(m_head);
|
2004-07-05 02:46:42 +00:00
|
|
|
return (1);
|
2003-04-15 04:06:01 +00:00
|
|
|
}
|
1998-11-18 21:03:58 +00:00
|
|
|
m_head = m_new;
|
1998-10-18 16:24:34 +00:00
|
|
|
|
|
|
|
/* Pad frames to at least 60 bytes. */
|
1998-11-18 21:03:58 +00:00
|
|
|
if (m_head->m_pkthdr.len < RL_MIN_FRAMELEN) {
|
1999-12-23 19:05:58 +00:00
|
|
|
/*
|
|
|
|
* Make security concious people happy: zero out the
|
|
|
|
* bytes in the pad area, since we don't know what
|
|
|
|
* this mbuf cluster buffer's previous user might
|
|
|
|
* have left in it.
|
2003-01-11 16:11:21 +00:00
|
|
|
*/
|
1999-12-23 19:05:58 +00:00
|
|
|
bzero(mtod(m_head, char *) + m_head->m_pkthdr.len,
|
|
|
|
RL_MIN_FRAMELEN - m_head->m_pkthdr.len);
|
1998-10-18 16:24:34 +00:00
|
|
|
m_head->m_pkthdr.len +=
|
1999-10-21 19:42:03 +00:00
|
|
|
(RL_MIN_FRAMELEN - m_head->m_pkthdr.len);
|
1998-11-18 21:03:58 +00:00
|
|
|
m_head->m_len = m_head->m_pkthdr.len;
|
|
|
|
}
|
1998-10-18 16:24:34 +00:00
|
|
|
|
1999-04-12 21:37:00 +00:00
|
|
|
RL_CUR_TXMBUF(sc) = m_head;
|
1998-10-18 16:24:34 +00:00
|
|
|
|
2004-07-05 02:46:42 +00:00
|
|
|
return (0);
|
1998-10-18 16:24:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Main transmit routine.
|
|
|
|
*/
|
2002-08-23 23:49:02 +00:00
|
|
|
static void
|
2004-07-05 02:46:42 +00:00
|
|
|
rl_start(struct ifnet *ifp)
|
1998-10-18 16:24:34 +00:00
|
|
|
{
|
2004-07-05 02:46:42 +00:00
|
|
|
struct rl_softc *sc = ifp->if_softc;
|
1998-10-18 16:24:34 +00:00
|
|
|
|
2000-10-13 17:54:19 +00:00
|
|
|
RL_LOCK(sc);
|
2004-07-09 00:07:06 +00:00
|
|
|
rl_start_locked(ifp);
|
|
|
|
RL_UNLOCK(sc);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
rl_start_locked(struct ifnet *ifp)
|
|
|
|
{
|
|
|
|
struct rl_softc *sc = ifp->if_softc;
|
|
|
|
struct mbuf *m_head = NULL;
|
|
|
|
|
|
|
|
RL_LOCK_ASSERT(sc);
|
1998-10-18 16:24:34 +00:00
|
|
|
|
2004-07-05 02:46:42 +00:00
|
|
|
while (RL_CUR_TXMBUF(sc) == NULL) {
|
2004-07-09 00:07:06 +00:00
|
|
|
|
2004-07-02 12:16:02 +00:00
|
|
|
IFQ_DRV_DEQUEUE(&ifp->if_snd, m_head);
|
2004-07-09 00:07:06 +00:00
|
|
|
|
1998-10-18 16:24:34 +00:00
|
|
|
if (m_head == NULL)
|
|
|
|
break;
|
|
|
|
|
2004-07-09 00:07:06 +00:00
|
|
|
if (rl_encap(sc, m_head))
|
2000-03-29 20:06:15 +00:00
|
|
|
break;
|
1998-10-18 16:24:34 +00:00
|
|
|
|
2004-07-05 02:46:42 +00:00
|
|
|
/* Pass a copy of this mbuf chain to the bpf subsystem. */
|
2002-11-14 23:49:09 +00:00
|
|
|
BPF_MTAP(ifp, RL_CUR_TXMBUF(sc));
|
1999-09-23 03:32:57 +00:00
|
|
|
|
2004-07-05 02:46:42 +00:00
|
|
|
/* Transmit the frame. */
|
2001-08-15 17:38:43 +00:00
|
|
|
bus_dmamap_create(sc->rl_tag, 0, &RL_CUR_DMAMAP(sc));
|
|
|
|
bus_dmamap_load(sc->rl_tag, RL_CUR_DMAMAP(sc),
|
|
|
|
mtod(RL_CUR_TXMBUF(sc), void *),
|
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).
2003-09-08 02:11:25 +00:00
|
|
|
RL_CUR_TXMBUF(sc)->m_pkthdr.len, rl_dma_map_txbuf, sc, 0);
|
2001-08-15 17:38:43 +00:00
|
|
|
bus_dmamap_sync(sc->rl_tag, RL_CUR_DMAMAP(sc),
|
|
|
|
BUS_DMASYNC_PREREAD);
|
1999-04-12 21:37:00 +00:00
|
|
|
CSR_WRITE_4(sc, RL_CUR_TXSTAT(sc),
|
1999-10-21 19:42:03 +00:00
|
|
|
RL_TXTHRESH(sc->rl_txthresh) |
|
|
|
|
RL_CUR_TXMBUF(sc)->m_pkthdr.len);
|
1999-04-12 21:37:00 +00:00
|
|
|
|
|
|
|
RL_INC(sc->rl_cdata.cur_tx);
|
2003-04-08 03:32:52 +00:00
|
|
|
|
2004-07-05 02:46:42 +00:00
|
|
|
/* Set a timeout in case the chip goes out to lunch. */
|
2003-04-08 03:32:52 +00:00
|
|
|
ifp->if_timer = 5;
|
1998-10-18 16:24:34 +00:00
|
|
|
}
|
|
|
|
|
1999-04-12 21:37:00 +00:00
|
|
|
/*
|
|
|
|
* We broke out of the loop because all our TX slots are
|
|
|
|
* full. Mark the NIC as busy until it drains some of the
|
|
|
|
* packets from the queue.
|
|
|
|
*/
|
|
|
|
if (RL_CUR_TXMBUF(sc) != NULL)
|
|
|
|
ifp->if_flags |= IFF_OACTIVE;
|
1998-10-18 16:24:34 +00:00
|
|
|
}
|
|
|
|
|
2002-08-23 23:49:02 +00:00
|
|
|
static void
|
2004-07-05 02:46:42 +00:00
|
|
|
rl_init(void *xsc)
|
1998-10-18 16:24:34 +00:00
|
|
|
{
|
|
|
|
struct rl_softc *sc = xsc;
|
2004-07-09 00:07:06 +00:00
|
|
|
|
|
|
|
RL_LOCK(sc);
|
|
|
|
rl_init_locked(sc);
|
|
|
|
RL_UNLOCK(sc);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
rl_init_locked(struct rl_softc *sc)
|
|
|
|
{
|
2005-06-10 16:49:24 +00:00
|
|
|
struct ifnet *ifp = sc->rl_ifp;
|
1999-08-31 14:45:51 +00:00
|
|
|
struct mii_data *mii;
|
2004-07-05 02:46:42 +00:00
|
|
|
uint32_t rxcfg = 0;
|
1998-10-18 16:24:34 +00:00
|
|
|
|
2004-07-09 00:07:06 +00:00
|
|
|
RL_LOCK_ASSERT(sc);
|
|
|
|
|
1999-08-31 14:45:51 +00:00
|
|
|
mii = device_get_softc(sc->rl_miibus);
|
1998-10-18 16:24:34 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Cancel pending I/O and free all RX/TX buffers.
|
|
|
|
*/
|
|
|
|
rl_stop(sc);
|
|
|
|
|
2003-06-29 17:33:33 +00:00
|
|
|
/*
|
|
|
|
* Init our MAC address. Even though the chipset
|
|
|
|
* documentation doesn't mention it, we need to enter "Config
|
|
|
|
* register write enable" mode to modify the ID registers.
|
|
|
|
*/
|
|
|
|
CSR_WRITE_1(sc, RL_EECMD, RL_EEMODE_WRITECFG);
|
2003-09-04 15:39:44 +00:00
|
|
|
CSR_WRITE_STREAM_4(sc, RL_IDR0,
|
2005-06-10 16:49:24 +00:00
|
|
|
*(uint32_t *)(&IFP2ENADDR(sc->rl_ifp)[0]));
|
2003-09-04 15:39:44 +00:00
|
|
|
CSR_WRITE_STREAM_4(sc, RL_IDR4,
|
2005-06-10 16:49:24 +00:00
|
|
|
*(uint32_t *)(&IFP2ENADDR(sc->rl_ifp)[4]));
|
2003-06-29 17:33:33 +00:00
|
|
|
CSR_WRITE_1(sc, RL_EECMD, RL_EEMODE_OFF);
|
1998-10-18 16:24:34 +00:00
|
|
|
|
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).
2003-09-08 02:11:25 +00:00
|
|
|
/* Init the RX buffer pointer register. */
|
|
|
|
bus_dmamap_load(sc->rl_tag, sc->rl_cdata.rl_rx_dmamap,
|
|
|
|
sc->rl_cdata.rl_rx_buf, RL_RXBUFLEN, rl_dma_map_rxbuf, sc, 0);
|
|
|
|
bus_dmamap_sync(sc->rl_tag, sc->rl_cdata.rl_rx_dmamap,
|
|
|
|
BUS_DMASYNC_PREWRITE);
|
2003-07-10 20:38:48 +00:00
|
|
|
|
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).
2003-09-08 02:11:25 +00:00
|
|
|
/* Init TX descriptors. */
|
|
|
|
rl_list_tx_init(sc);
|
1998-10-18 16:24:34 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Enable transmit and receive.
|
|
|
|
*/
|
|
|
|
CSR_WRITE_1(sc, RL_COMMAND, RL_CMD_TX_ENB|RL_CMD_RX_ENB);
|
|
|
|
|
|
|
|
/*
|
1999-04-12 21:37:00 +00:00
|
|
|
* Set the initial TX and RX configuration.
|
1998-10-18 16:24:34 +00:00
|
|
|
*/
|
1999-04-12 21:37:00 +00:00
|
|
|
CSR_WRITE_4(sc, RL_TXCFG, RL_TXCFG_CONFIG);
|
1998-10-18 16:24:34 +00:00
|
|
|
CSR_WRITE_4(sc, RL_RXCFG, RL_RXCFG_CONFIG);
|
|
|
|
|
|
|
|
/* Set the individual bit to receive frames for this host only. */
|
|
|
|
rxcfg = CSR_READ_4(sc, RL_RXCFG);
|
|
|
|
rxcfg |= RL_RXCFG_RX_INDIV;
|
|
|
|
|
|
|
|
/* If we want promiscuous mode, set the allframes bit. */
|
|
|
|
if (ifp->if_flags & IFF_PROMISC) {
|
|
|
|
rxcfg |= RL_RXCFG_RX_ALLPHYS;
|
|
|
|
CSR_WRITE_4(sc, RL_RXCFG, rxcfg);
|
|
|
|
} else {
|
|
|
|
rxcfg &= ~RL_RXCFG_RX_ALLPHYS;
|
|
|
|
CSR_WRITE_4(sc, RL_RXCFG, rxcfg);
|
|
|
|
}
|
|
|
|
|
2004-07-05 02:46:42 +00:00
|
|
|
/* Set capture broadcast bit to capture broadcast frames. */
|
1998-10-18 16:24:34 +00:00
|
|
|
if (ifp->if_flags & IFF_BROADCAST) {
|
|
|
|
rxcfg |= RL_RXCFG_RX_BROAD;
|
|
|
|
CSR_WRITE_4(sc, RL_RXCFG, rxcfg);
|
|
|
|
} else {
|
|
|
|
rxcfg &= ~RL_RXCFG_RX_BROAD;
|
|
|
|
CSR_WRITE_4(sc, RL_RXCFG, rxcfg);
|
|
|
|
}
|
|
|
|
|
2004-07-05 02:46:42 +00:00
|
|
|
/* Program the multicast filter, if necessary. */
|
1998-10-18 16:24:34 +00:00
|
|
|
rl_setmulti(sc);
|
|
|
|
|
2002-04-16 22:03:14 +00:00
|
|
|
#ifdef DEVICE_POLLING
|
2004-07-05 02:46:42 +00:00
|
|
|
/* Disable interrupts if we are polling. */
|
2002-08-18 07:05:00 +00:00
|
|
|
if (ifp->if_flags & IFF_POLLING)
|
2002-04-16 22:03:14 +00:00
|
|
|
CSR_WRITE_2(sc, RL_IMR, 0);
|
2004-07-05 02:46:42 +00:00
|
|
|
else
|
2002-04-16 22:03:14 +00:00
|
|
|
#endif /* DEVICE_POLLING */
|
2004-07-05 02:46:42 +00:00
|
|
|
/* Enable interrupts. */
|
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).
2003-09-08 02:11:25 +00:00
|
|
|
CSR_WRITE_2(sc, RL_IMR, RL_INTRS);
|
1998-10-18 16:24:34 +00:00
|
|
|
|
1999-10-21 19:42:03 +00:00
|
|
|
/* Set initial TX threshold */
|
|
|
|
sc->rl_txthresh = RL_TX_THRESH_INIT;
|
|
|
|
|
1998-10-18 16:24:34 +00:00
|
|
|
/* Start RX/TX process. */
|
|
|
|
CSR_WRITE_4(sc, RL_MISSEDPKT, 0);
|
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).
2003-09-08 02:11:25 +00:00
|
|
|
|
1998-10-18 16:24:34 +00:00
|
|
|
/* Enable receiver and transmitter. */
|
|
|
|
CSR_WRITE_1(sc, RL_COMMAND, RL_CMD_TX_ENB|RL_CMD_RX_ENB);
|
|
|
|
|
1999-08-31 14:45:51 +00:00
|
|
|
mii_mediachg(mii);
|
1998-10-18 16:24:34 +00:00
|
|
|
|
|
|
|
CSR_WRITE_1(sc, RL_CFG1, RL_CFG1_DRVLOAD|RL_CFG1_FULLDUPLEX);
|
|
|
|
|
|
|
|
ifp->if_flags |= IFF_RUNNING;
|
|
|
|
ifp->if_flags &= ~IFF_OACTIVE;
|
|
|
|
|
1999-08-31 14:45:51 +00:00
|
|
|
sc->rl_stat_ch = timeout(rl_tick, sc, hz);
|
1998-10-18 16:24:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Set media options.
|
|
|
|
*/
|
2002-08-23 23:49:02 +00:00
|
|
|
static int
|
2004-07-05 02:46:42 +00:00
|
|
|
rl_ifmedia_upd(struct ifnet *ifp)
|
1998-10-18 16:24:34 +00:00
|
|
|
{
|
2004-07-05 02:46:42 +00:00
|
|
|
struct rl_softc *sc = ifp->if_softc;
|
1999-08-31 14:45:51 +00:00
|
|
|
struct mii_data *mii;
|
1998-10-18 16:24:34 +00:00
|
|
|
|
1999-08-31 14:45:51 +00:00
|
|
|
mii = device_get_softc(sc->rl_miibus);
|
2004-07-05 02:46:42 +00:00
|
|
|
|
1999-08-31 14:45:51 +00:00
|
|
|
mii_mediachg(mii);
|
1998-10-18 16:24:34 +00:00
|
|
|
|
2004-07-05 02:46:42 +00:00
|
|
|
return (0);
|
1998-10-18 16:24:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Report current media status.
|
|
|
|
*/
|
2002-08-23 23:49:02 +00:00
|
|
|
static void
|
2004-07-05 02:46:42 +00:00
|
|
|
rl_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
|
1998-10-18 16:24:34 +00:00
|
|
|
{
|
2004-07-05 02:46:42 +00:00
|
|
|
struct rl_softc *sc = ifp->if_softc;
|
1999-08-31 14:45:51 +00:00
|
|
|
struct mii_data *mii;
|
1998-10-18 16:24:34 +00:00
|
|
|
|
1999-08-31 14:45:51 +00:00
|
|
|
mii = device_get_softc(sc->rl_miibus);
|
1998-10-18 16:24:34 +00:00
|
|
|
|
1999-08-31 14:45:51 +00:00
|
|
|
mii_pollstat(mii);
|
|
|
|
ifmr->ifm_active = mii->mii_media_active;
|
|
|
|
ifmr->ifm_status = mii->mii_media_status;
|
1998-10-18 16:24:34 +00:00
|
|
|
}
|
|
|
|
|
2002-08-23 23:49:02 +00:00
|
|
|
static int
|
2004-07-05 02:46:42 +00:00
|
|
|
rl_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
|
1998-10-18 16:24:34 +00:00
|
|
|
{
|
2004-07-05 02:46:42 +00:00
|
|
|
struct ifreq *ifr = (struct ifreq *)data;
|
1999-08-31 14:45:51 +00:00
|
|
|
struct mii_data *mii;
|
2004-07-05 02:46:42 +00:00
|
|
|
struct rl_softc *sc = ifp->if_softc;
|
2000-10-13 17:54:19 +00:00
|
|
|
int error = 0;
|
1998-10-18 16:24:34 +00:00
|
|
|
|
2004-07-05 02:46:42 +00:00
|
|
|
switch (command) {
|
1998-10-18 16:24:34 +00:00
|
|
|
case SIOCSIFFLAGS:
|
2004-07-09 00:07:06 +00:00
|
|
|
RL_LOCK(sc);
|
1998-10-18 16:24:34 +00:00
|
|
|
if (ifp->if_flags & IFF_UP) {
|
2004-07-09 00:07:06 +00:00
|
|
|
rl_init_locked(sc);
|
1998-10-18 16:24:34 +00:00
|
|
|
} else {
|
|
|
|
if (ifp->if_flags & IFF_RUNNING)
|
|
|
|
rl_stop(sc);
|
|
|
|
}
|
2004-07-09 00:07:06 +00:00
|
|
|
RL_UNLOCK(sc);
|
1998-10-18 16:24:34 +00:00
|
|
|
error = 0;
|
|
|
|
break;
|
|
|
|
case SIOCADDMULTI:
|
|
|
|
case SIOCDELMULTI:
|
2004-07-05 02:51:32 +00:00
|
|
|
RL_LOCK(sc);
|
1998-10-18 16:24:34 +00:00
|
|
|
rl_setmulti(sc);
|
2004-07-05 02:51:32 +00:00
|
|
|
RL_UNLOCK(sc);
|
1998-10-18 16:24:34 +00:00
|
|
|
error = 0;
|
|
|
|
break;
|
|
|
|
case SIOCGIFMEDIA:
|
|
|
|
case SIOCSIFMEDIA:
|
1999-08-31 14:45:51 +00:00
|
|
|
mii = device_get_softc(sc->rl_miibus);
|
|
|
|
error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, command);
|
1998-10-18 16:24:34 +00:00
|
|
|
break;
|
2004-04-11 16:23:16 +00:00
|
|
|
case SIOCSIFCAP:
|
2004-05-23 21:05:08 +00:00
|
|
|
ifp->if_capenable &= ~IFCAP_POLLING;
|
|
|
|
ifp->if_capenable |= ifr->ifr_reqcap & IFCAP_POLLING;
|
2004-04-11 16:23:16 +00:00
|
|
|
break;
|
1998-10-18 16:24:34 +00:00
|
|
|
default:
|
2002-11-14 23:49:09 +00:00
|
|
|
error = ether_ioctl(ifp, command, data);
|
1998-10-18 16:24:34 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2004-07-05 02:46:42 +00:00
|
|
|
return (error);
|
1998-10-18 16:24:34 +00:00
|
|
|
}
|
|
|
|
|
2002-08-23 23:49:02 +00:00
|
|
|
static void
|
2004-07-05 02:46:42 +00:00
|
|
|
rl_watchdog(struct ifnet *ifp)
|
1998-10-18 16:24:34 +00:00
|
|
|
{
|
2004-07-05 02:46:42 +00:00
|
|
|
struct rl_softc *sc = ifp->if_softc;
|
1998-10-18 16:24:34 +00:00
|
|
|
|
2000-10-13 17:54:19 +00:00
|
|
|
RL_LOCK(sc);
|
2004-07-05 02:46:42 +00:00
|
|
|
|
|
|
|
if_printf(ifp, "watchdog timeout\n");
|
1998-10-18 16:24:34 +00:00
|
|
|
ifp->if_oerrors++;
|
1999-08-31 14:45:51 +00:00
|
|
|
|
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).
2003-09-08 02:11:25 +00:00
|
|
|
rl_txeof(sc);
|
|
|
|
rl_rxeof(sc);
|
2004-07-09 00:07:06 +00:00
|
|
|
rl_init_locked(sc);
|
1998-10-18 16:24:34 +00:00
|
|
|
|
2004-07-05 02:46:42 +00:00
|
|
|
RL_UNLOCK(sc);
|
1998-10-18 16:24:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Stop the adapter and free any mbufs allocated to the
|
|
|
|
* RX and TX lists.
|
|
|
|
*/
|
2002-08-23 23:49:02 +00:00
|
|
|
static void
|
2004-07-05 02:46:42 +00:00
|
|
|
rl_stop(struct rl_softc *sc)
|
1998-10-18 16:24:34 +00:00
|
|
|
{
|
|
|
|
register int i;
|
2005-06-10 16:49:24 +00:00
|
|
|
struct ifnet *ifp = sc->rl_ifp;
|
1998-10-18 16:24:34 +00:00
|
|
|
|
2004-07-05 02:51:32 +00:00
|
|
|
RL_LOCK_ASSERT(sc);
|
2004-07-05 02:46:42 +00:00
|
|
|
|
2004-07-05 02:51:32 +00:00
|
|
|
ifp->if_timer = 0;
|
1999-08-31 14:45:51 +00:00
|
|
|
untimeout(rl_tick, sc, sc->rl_stat_ch);
|
2002-04-16 22:03:14 +00:00
|
|
|
ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
|
|
|
|
#ifdef DEVICE_POLLING
|
|
|
|
ether_poll_deregister(ifp);
|
|
|
|
#endif /* DEVICE_POLLING */
|
1999-08-31 14:45:51 +00:00
|
|
|
|
1998-10-18 16:24:34 +00:00
|
|
|
CSR_WRITE_1(sc, RL_COMMAND, 0x00);
|
|
|
|
CSR_WRITE_2(sc, RL_IMR, 0x0000);
|
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).
2003-09-08 02:11:25 +00:00
|
|
|
bus_dmamap_unload(sc->rl_tag, sc->rl_cdata.rl_rx_dmamap);
|
1998-10-18 16:24:34 +00:00
|
|
|
|
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).
2003-09-08 02:11:25 +00:00
|
|
|
/*
|
|
|
|
* Free the TX list buffers.
|
|
|
|
*/
|
|
|
|
for (i = 0; i < RL_TX_LIST_CNT; i++) {
|
|
|
|
if (sc->rl_cdata.rl_tx_chain[i] != NULL) {
|
|
|
|
bus_dmamap_unload(sc->rl_tag,
|
|
|
|
sc->rl_cdata.rl_tx_dmamap[i]);
|
|
|
|
bus_dmamap_destroy(sc->rl_tag,
|
|
|
|
sc->rl_cdata.rl_tx_dmamap[i]);
|
|
|
|
m_freem(sc->rl_cdata.rl_tx_chain[i]);
|
|
|
|
sc->rl_cdata.rl_tx_chain[i] = NULL;
|
2004-07-05 02:46:42 +00:00
|
|
|
CSR_WRITE_4(sc, RL_TXADDR0 + (i * sizeof(uint32_t)),
|
2004-01-21 22:29:51 +00:00
|
|
|
0x0000000);
|
1998-10-18 16:24:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2001-11-23 14:27:33 +00:00
|
|
|
/*
|
|
|
|
* Device suspend routine. Stop the interface and save some PCI
|
|
|
|
* settings in case the BIOS doesn't restore them properly on
|
|
|
|
* resume.
|
|
|
|
*/
|
2002-08-23 23:49:02 +00:00
|
|
|
static int
|
2004-07-05 02:46:42 +00:00
|
|
|
rl_suspend(device_t dev)
|
2001-11-23 14:27:33 +00:00
|
|
|
{
|
|
|
|
struct rl_softc *sc;
|
|
|
|
|
|
|
|
sc = device_get_softc(dev);
|
2004-07-05 02:51:32 +00:00
|
|
|
|
|
|
|
RL_LOCK(sc);
|
2001-11-23 14:27:33 +00:00
|
|
|
rl_stop(sc);
|
|
|
|
sc->suspended = 1;
|
2004-07-05 02:51:32 +00:00
|
|
|
RL_UNLOCK(sc);
|
2001-11-23 14:27:33 +00:00
|
|
|
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Device resume routine. Restore some PCI settings in case the BIOS
|
|
|
|
* doesn't, re-enable busmastering, and restart the interface if
|
|
|
|
* appropriate.
|
|
|
|
*/
|
2002-08-23 23:49:02 +00:00
|
|
|
static int
|
2004-07-05 02:46:42 +00:00
|
|
|
rl_resume(device_t dev)
|
2001-11-23 14:27:33 +00:00
|
|
|
{
|
|
|
|
struct rl_softc *sc;
|
|
|
|
struct ifnet *ifp;
|
|
|
|
|
|
|
|
sc = device_get_softc(dev);
|
2005-06-10 16:49:24 +00:00
|
|
|
ifp = sc->rl_ifp;
|
2001-11-23 14:27:33 +00:00
|
|
|
|
2004-07-09 00:07:06 +00:00
|
|
|
RL_LOCK(sc);
|
|
|
|
|
2003-01-11 16:11:21 +00:00
|
|
|
/* reinitialize interface if necessary */
|
|
|
|
if (ifp->if_flags & IFF_UP)
|
2004-07-09 00:07:06 +00:00
|
|
|
rl_init_locked(sc);
|
2001-11-23 14:27:33 +00:00
|
|
|
|
|
|
|
sc->suspended = 0;
|
2004-07-09 00:07:06 +00:00
|
|
|
|
2004-07-05 02:51:32 +00:00
|
|
|
RL_UNLOCK(sc);
|
2001-11-23 14:27:33 +00:00
|
|
|
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
1998-10-18 16:24:34 +00:00
|
|
|
/*
|
|
|
|
* Stop all chip I/O so that the kernel's probe routines don't
|
|
|
|
* get confused by errant DMAs when rebooting.
|
|
|
|
*/
|
2002-08-23 23:49:02 +00:00
|
|
|
static void
|
2004-07-05 02:46:42 +00:00
|
|
|
rl_shutdown(device_t dev)
|
1998-10-18 16:24:34 +00:00
|
|
|
{
|
1999-08-31 14:45:51 +00:00
|
|
|
struct rl_softc *sc;
|
|
|
|
|
|
|
|
sc = device_get_softc(dev);
|
2004-07-05 02:51:32 +00:00
|
|
|
|
|
|
|
RL_LOCK(sc);
|
1998-10-18 16:24:34 +00:00
|
|
|
rl_stop(sc);
|
2004-07-05 02:51:32 +00:00
|
|
|
RL_UNLOCK(sc);
|
1998-10-18 16:24:34 +00:00
|
|
|
}
|