Support for large frames for VLANs was added by tweaking the packet size

register, present only on 3c90xB and later NICs. This meant that you could
not use a 1500 byte MTU with VLANs on original 3c905/3c900 cards (boomerang
chipset). The boomerang chip does support large frames though, just not
in the same way: you can set the 'allow large frames' bit in the MAC
control register to receive frames up to 4K in size.

Changes:

- Set the 'allow large frames' bit for boomerang chips and increase
  the packet size register for cyclone and later chips. This allows
  us to use IFCAP_VLAN_MTU on all supported xl(4) NICs.
- Actually set the IFCAP_VLAN_MTU flag in the capabilities word
  in xl_attach().
- Change the method used to detect older boomerang chips. My 3c575C
  cardbus NIC was being incorrectly identified as 3c90x chip instead
  of 3c90xB because the capabilities word in its EEPROM reports
  a bizzare value. In addition to checking for the supportsNoTxLength
  bit, also check for the absence of the supportsLargePackets bit.
  Both of these cases denote a 3c90xB chip.
- Make RX and TX checksums configurable via the SIOCSIFCAP ioctl.
- Avoid an unecessary le32toh() in xl_rxeof(): we already have the
  received frame size in the lower 16 bits of rxstat, no need to
  read it again.

Tested with 3c905-TX, 3c900-TPO, 3c980C and 3c575C NICs.
This commit is contained in:
Bill Paul 2003-07-10 05:24:33 +00:00
parent 85a94674d0
commit e4cffe95c7
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=117375
2 changed files with 47 additions and 8 deletions

View File

@ -1567,9 +1567,15 @@ xl_attach(dev)
* Figure out the card type. 3c905B adapters have the
* 'supportsNoTxLength' bit set in the capabilities
* word in the EEPROM.
* Note: my 3c575C cardbus card lies. It returns a value
* of 0x1578 for its capabilities word, which is somewhat
* nonsensical. Another way to distinguish a 3c90x chip
* from a 3c90xB/C chip is to check for the 'supportsLargePackets'
* bit. This will only be set for 3c90x boomerage chips.
*/
xl_read_eeprom(sc, (caddr_t)&sc->xl_caps, XL_EE_CAPS, 1, 0);
if (sc->xl_caps & XL_CAPS_NO_TXLENGTH)
if (sc->xl_caps & XL_CAPS_NO_TXLENGTH ||
!(sc->xl_caps & XL_CAPS_LARGE_PKTS))
sc->xl_type = XL_TYPE_905B;
else
sc->xl_type = XL_TYPE_90X;
@ -1582,10 +1588,11 @@ xl_attach(dev)
ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
ifp->if_ioctl = xl_ioctl;
ifp->if_output = ether_output;
ifp->if_capabilities = IFCAP_VLAN_MTU;
if (sc->xl_type == XL_TYPE_905B) {
ifp->if_start = xl_start_90xB;
ifp->if_hwassist = XL905B_CSUM_FEATURES;
ifp->if_capabilities = IFCAP_HWCSUM;
ifp->if_capabilities |= IFCAP_HWCSUM;
} else
ifp->if_start = xl_start;
ifp->if_watchdog = xl_watchdog;
@ -2036,6 +2043,16 @@ xl_rxeof(sc)
while((rxstat = le32toh(sc->xl_cdata.xl_rx_head->xl_ptr->xl_status))) {
cur_rx = sc->xl_cdata.xl_rx_head;
sc->xl_cdata.xl_rx_head = cur_rx->xl_next;
total_len = rxstat & XL_RXSTAT_LENMASK;
/*
* Since we have told the chip to allow large frames,
* we need to trap giant frame errors in software. We allow
* a little more than the normal frame size to account for
* frames with VLAN tags.
*/
if (total_len > XL_MAX_FRAMELEN)
rxstat |= (XL_RXSTAT_UP_ERROR|XL_RXSTAT_OVERSIZE);
/*
* If an error occurs, update stats, clear the
@ -2052,7 +2069,7 @@ xl_rxeof(sc)
}
/*
* If there error bit was not set, the upload complete
* If the error bit was not set, the upload complete
* bit should be set which means we have a valid packet.
* If not, something truly strange has happened.
*/
@ -2070,8 +2087,6 @@ xl_rxeof(sc)
bus_dmamap_sync(sc->xl_mtag, cur_rx->xl_map,
BUS_DMASYNC_POSTREAD);
m = cur_rx->xl_mbuf;
total_len = le32toh(cur_rx->xl_ptr->xl_status) &
XL_RXSTAT_LENMASK;
/*
* Try to conjure up a new mbuf cluster. If that
@ -2094,7 +2109,7 @@ xl_rxeof(sc)
m->m_pkthdr.rcvif = ifp;
m->m_pkthdr.len = m->m_len = total_len;
if (sc->xl_type == XL_TYPE_905B) {
if (ifp->if_capenable & IFCAP_RXCSUM) {
/* Do IP checksum checking. */
if (rxstat & XL_RXSTAT_IPCKOK)
m->m_pkthdr.csum_flags |= CSUM_IP_CHECKED;
@ -2432,6 +2447,9 @@ xl_encap(sc, c, m_head)
{
int error;
u_int32_t status;
struct ifnet *ifp;
ifp = &sc->arpcom.ac_if;
/*
* Start packing the mbufs in this chain into
@ -2894,9 +2912,22 @@ xl_init(xsc)
else
CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_COAX_STOP);
/* increase packet size to allow reception of 802.1q or ISL packets */
/*
* increase packet size to allow reception of 802.1q or ISL packets.
* For the 3c90x chip, set the 'allow large packets' bit in the MAC
* control register. For 3c90xB/C chips, use the RX packet size
* register.
*/
if (sc->xl_type == XL_TYPE_905B)
CSR_WRITE_2(sc, XL_W3_MAXPKTSIZE, XL_PACKET_SIZE);
else {
u_int8_t macctl;
macctl = CSR_READ_1(sc, XL_W3_MAC_CTRL);
macctl |= XL_MACCTRL_ALLOW_LARGE_PACK;
CSR_WRITE_1(sc, XL_W3_MAC_CTRL, macctl);
}
/* Clear out the stats counters. */
CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_STATS_DISABLE);
sc->xl_stats_no_timeout = 1;
@ -3111,6 +3142,13 @@ xl_ioctl(ifp, command, data)
error = ifmedia_ioctl(ifp, ifr,
&mii->mii_media, command);
break;
case SIOCSIFCAP:
ifp->if_capenable = ifr->ifr_reqcap;
if (ifp->if_capenable & IFCAP_TXCSUM)
ifp->if_hwassist = XL905B_CSUM_FEATURES;
else
ifp->if_hwassist = 0;
break;
default:
error = ether_ioctl(ifp, command, data);
break;

View File

@ -82,6 +82,7 @@
#define XL_CAPS_PWRMGMT 0x2000
#define XL_PACKET_SIZE 1540
#define XL_MAX_FRAMELEN (ETHER_MAX_LEN + ETHER_VLAN_ENCAP_LEN)
/*
* Register layouts.