Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/dev/ic Many fixes. Multicast hash filter works now. Au...
details: https://anonhg.NetBSD.org/src/rev/32852abf25d1
branches: trunk
changeset: 526799:32852abf25d1
user: matt <matt%NetBSD.org@localhost>
date: Sat May 11 00:36:02 2002 +0000
description:
Many fixes. Multicast hash filter works now. Autonegotiation with GigE
on Mac G4's now works. XXX Checksum offload still needs to be done.
diffstat:
sys/dev/ic/gem.c | 186 +++++++++++++++++++++++++++++++--------------------
sys/dev/ic/gemreg.h | 11 +-
sys/dev/ic/gemvar.h | 10 ++-
3 files changed, 129 insertions(+), 78 deletions(-)
diffs (truncated from 431 to 300 lines):
diff -r 126ec56e155b -r 32852abf25d1 sys/dev/ic/gem.c
--- a/sys/dev/ic/gem.c Fri May 10 23:21:17 2002 +0000
+++ b/sys/dev/ic/gem.c Sat May 11 00:36:02 2002 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: gem.c,v 1.14 2002/05/08 02:12:55 matt Exp $ */
+/* $NetBSD: gem.c,v 1.15 2002/05/11 00:36:02 matt Exp $ */
/*
*
@@ -34,7 +34,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: gem.c,v 1.14 2002/05/08 02:12:55 matt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: gem.c,v 1.15 2002/05/11 00:36:02 matt Exp $");
#include "bpfilter.h"
@@ -132,7 +132,9 @@
struct ifnet *ifp = &sc->sc_ethercom.ec_if;
struct mii_data *mii = &sc->sc_mii;
struct mii_softc *child;
+ struct ifmedia_entry *ifm;
int i, error;
+ u_int32_t v;
/* Make sure the chip is stopped. */
ifp->if_softc = sc;
@@ -189,8 +191,9 @@
txs = &sc->sc_txsoft[i];
txs->txs_mbuf = NULL;
- if ((error = bus_dmamap_create(sc->sc_dmatag, MCLBYTES,
- GEM_NTXSEGS, MCLBYTES, 0, 0,
+ if ((error = bus_dmamap_create(sc->sc_dmatag,
+ ETHER_MAX_LEN_JUMBO, GEM_NTXSEGS,
+ ETHER_MAX_LEN_JUMBO, 0, 0,
&txs->txs_dmamap)) != 0) {
printf("%s: unable to create tx DMA map %d, "
"error = %d\n", sc->sc_dev.dv_xname, i, error);
@@ -219,9 +222,18 @@
*/
/* Announce ourselves. */
- printf("%s: Ethernet address %s\n", sc->sc_dev.dv_xname,
+ printf("%s: Ethernet address %s", sc->sc_dev.dv_xname,
ether_sprintf(enaddr));
+ /* Get RX FIFO size */
+ sc->sc_rxfifosize = 64 *
+ bus_space_read_4(sc->sc_bustag, sc->sc_h, GEM_RX_FIFO_SIZE);
+ printf(", %uKB RX fifo", sc->sc_rxfifosize / 1024);
+
+ /* Get TX FIFO size */
+ v = bus_space_read_4(sc->sc_bustag, sc->sc_h, GEM_TX_FIFO_SIZE);
+ printf(", %uKB TX fifo\n", v / 16);
+
/* Initialize ifnet structure. */
strcpy(ifp->if_xname, sc->sc_dev.dv_xname);
ifp->if_softc = sc;
@@ -276,6 +288,7 @@
}
sc->sc_phys[child->mii_inst] = child->mii_phy;
+
}
/*
@@ -305,6 +318,24 @@
ifmedia_set(&sc->sc_media, IFM_ETHER|IFM_AUTO);
}
+ /*
+ * If we support GigE media, we support jumbo frames too.
+ * Unless we are Apple.
+ */
+ TAILQ_FOREACH(ifm, &sc->sc_media.ifm_list, ifm_list) {
+ if (IFM_SUBTYPE(ifm->ifm_media) == IFM_1000_T ||
+ IFM_SUBTYPE(ifm->ifm_media) == IFM_1000_SX ||
+ IFM_SUBTYPE(ifm->ifm_media) == IFM_1000_LX ||
+ IFM_SUBTYPE(ifm->ifm_media) == IFM_1000_CX) {
+ if (sc->sc_variant != GEM_APPLE_GMAC)
+ sc->sc_ethercom.ec_capabilities
+ |= ETHERCAP_JUMBO_MTU;
+
+ sc->sc_flags |= GEM_GIGABIT;
+ break;
+ }
+ }
+
/* claim 802.1q capability */
sc->sc_ethercom.ec_capabilities |= ETHERCAP_VLAN_MTU;
@@ -705,6 +736,7 @@
bus_space_tag_t t = sc->sc_bustag;
bus_space_handle_t h = sc->sc_h;
int s;
+ u_int max_frame_size;
u_int32_t v;
s = splnet();
@@ -734,10 +766,12 @@
/* step 4. TX MAC registers & counters */
gem_init_regs(sc);
+ max_frame_size = max(sc->sc_ethercom.ec_if.if_mtu, ETHERMTU);
+ max_frame_size += ETHER_HDR_LEN + ETHER_CRC_LEN;
+ if (sc->sc_ethercom.ec_capenable & ETHERCAP_VLAN_MTU)
+ max_frame_size += ETHER_VLAN_ENCAP_LEN;
bus_space_write_4(t, h, GEM_MAC_MAC_MAX_FRAME,
- ((sc->sc_ethercom.ec_capenable & ETHERCAP_VLAN_MTU) ?
- ETHER_VLAN_ENCAP_LEN + ETHER_MAX_LEN + sizeof(struct ether_header):
- ETHER_MAX_LEN + sizeof(struct ether_header)) | (0x2000<<16));
+ max_frame_size|/* burst size */(0x2000<<16));
/* step 5. RX MAC registers & counters */
gem_setladrf(sc);
@@ -782,14 +816,16 @@
(2<<GEM_RX_CONFIG_FBOFF_SHFT)|GEM_RX_CONFIG_RXDMA_EN|
(0<<GEM_RX_CONFIG_CXM_START_SHFT));
/*
- * The following value is for an OFF Threshold of about 15.5 Kbytes
- * and an ON Threshold of 4K bytes.
+ * The following value is for an OFF Threshold of about 3/4 full
+ * and an ON Threshold of 1/4 full.
*/
- bus_space_write_4(t, h, GEM_RX_PAUSE_THRESH, 0xf8 | (0x40 << 12));
- bus_space_write_4(t, h, GEM_RX_BLANKING, (2<<12)|6);
+ bus_space_write_4(t, h, GEM_RX_PAUSE_THRESH,
+ (3 * sc->sc_rxfifosize / 256) |
+ ( (sc->sc_rxfifosize / 256) << 12));
+ bus_space_write_4(t, h, GEM_RX_BLANKING, (6<<12)|6);
/* step 11. Configure Media */
- gem_mii_statchg(&sc->sc_dev);
+ mii_mediachg(&sc->sc_mii);
/* XXXX Serial link needs a whole different setup. */
@@ -827,6 +863,7 @@
bus_space_tag_t t = sc->sc_bustag;
bus_space_handle_t h = sc->sc_h;
const u_char *laddr = LLADDR(ifp->if_sadl);
+ u_int32_t v;
/* These regs are not cleared on reset */
if (!sc->sc_inited) {
@@ -839,14 +876,15 @@
bus_space_write_4(t, h, GEM_MAC_MAC_MIN_FRAME, ETHER_MIN_LEN);
/* Max frame and max burst size */
bus_space_write_4(t, h, GEM_MAC_MAC_MAX_FRAME,
- (ifp->if_mtu+18) | (0x2000<<16)/* Burst size */);
+ ETHER_MAX_LEN | (0x2000<<16));
+
bus_space_write_4(t, h, GEM_MAC_PREAMBLE_LEN, 0x7);
bus_space_write_4(t, h, GEM_MAC_JAM_SIZE, 0x4);
bus_space_write_4(t, h, GEM_MAC_ATTEMPT_LIMIT, 0x10);
/* Dunno.... */
bus_space_write_4(t, h, GEM_MAC_CONTROL_TYPE, 0x8088);
bus_space_write_4(t, h, GEM_MAC_RANDOM_SEED,
- ((laddr[5]<<8)|laddr[4])&0x3ff);
+ ((laddr[5]<<8)|laddr[4])&0x3ff);
/* Secondary MAC addr set to 0:0:0:0:0:0 */
bus_space_write_4(t, h, GEM_MAC_ADDR3, 0);
@@ -896,9 +934,23 @@
bus_space_write_4(t, h, GEM_MAC_ADDR1, (laddr[2]<<8)|laddr[3]);
bus_space_write_4(t, h, GEM_MAC_ADDR2, (laddr[0]<<8)|laddr[1]);
-}
+#if 0
+ if (sc->sc_variant != APPLE_GMAC)
+ return;
+#endif
-
+ /*
+ * Enable MII outputs. Enable GMII if there is a gigabit PHY.
+ */
+ sc->sc_mif_config = bus_space_read_4(t, h, GEM_MIF_CONFIG);
+ v = GEM_MAC_XIF_TX_MII_ENA;
+ if (sc->sc_mif_config & GEM_MIF_CONFIG_MDI1) {
+ v |= GEM_MAC_XIF_FDPLX_LED;
+ if (sc->sc_flags & GEM_GIGABIT)
+ v |= GEM_MAC_XIF_GMII_MODE;
+ }
+ bus_space_write_4(t, h, GEM_MAC_XIF_CONFIG, v);
+}
void
gem_start(ifp)
@@ -948,6 +1000,13 @@
*/
if (bus_dmamap_load_mbuf(sc->sc_dmatag, dmamap, m0,
BUS_DMA_WRITE|BUS_DMA_NOWAIT) != 0) {
+ if (m0->m_pkthdr.len > MCLBYTES) {
+ printf("%s: unable to allocate jumbo Tx "
+ "cluster\n", sc->sc_dev.dv_xname);
+ IFQ_DEQUEUE(&ifp->if_snd, m0);
+ m_freem(m0);
+ continue;
+ }
MGETHDR(m, M_DONTWAIT, MT_DATA);
if (m == NULL) {
printf("%s: unable to allocate Tx mbuf\n",
@@ -1636,6 +1695,7 @@
v = bus_space_read_4(t, mac, GEM_MAC_XIF_CONFIG);
v = GEM_MAC_XIF_LINK_LED;
v |= GEM_MAC_XIF_TX_MII_ENA;
+
/* If an external transceiver is connected, enable its MII drivers */
sc->sc_mif_config = bus_space_read_4(t, mac, GEM_MIF_CONFIG);
if ((sc->sc_mif_config & GEM_MIF_CONFIG_MDI1) != 0) {
@@ -1643,9 +1703,10 @@
if ((IFM_OPTIONS(sc->sc_mii.mii_media_active) & IFM_FDX) != 0)
/* turn on full duplex LED */
v |= GEM_MAC_XIF_FDPLX_LED;
- else
- /* half duplex -- disable echo */
- v |= GEM_MAC_XIF_ECHO_DISABL;
+ else
+ /* half duplex -- disable echo */
+ v |= GEM_MAC_XIF_ECHO_DISABL;
+
if (sc->sc_ethercom.ec_if.if_baudrate == IF_Mbps(1000))
v |= GEM_MAC_XIF_GMII_MODE;
else
@@ -1746,44 +1807,46 @@
gem_setladrf(sc)
struct gem_softc *sc;
{
- struct ifnet *ifp = &sc->sc_ethercom.ec_if;
+ struct ethercom *ec = &sc->sc_ethercom;
+ struct ifnet *ifp = &ec->ec_if;
struct ether_multi *enm;
struct ether_multistep step;
- struct ethercom *ec = &sc->sc_ethercom;
bus_space_tag_t t = sc->sc_bustag;
bus_space_handle_t h = sc->sc_h;
- u_char *cp;
u_int32_t crc;
u_int32_t hash[16];
u_int32_t v;
- int len;
-
- /* Clear hash table */
- memset(hash, 0, sizeof(hash));
+ int i;
/* Get current RX configuration */
v = bus_space_read_4(t, h, GEM_MAC_RX_CONFIG);
+ /*
+ * Turn off promiscuous mode, promiscuous group mode (all multicast),
+ * and hash filter. Depending on the case, the right bit will be
+ * enabled.
+ */
+ v &= ~(GEM_MAC_RX_PROMISCUOUS|GEM_MAC_RX_HASH_FILTER|
+ GEM_MAC_RX_PROMISC_GRP);
+
if ((ifp->if_flags & IFF_PROMISC) != 0) {
- /* Turn on promiscuous mode; turn off the hash filter */
+ /* Turn on promiscuous mode */
v |= GEM_MAC_RX_PROMISCUOUS;
- v &= ~GEM_MAC_RX_HASH_FILTER;
ifp->if_flags |= IFF_ALLMULTI;
goto chipit;
}
- /* Turn off promiscuous mode; turn on the hash filter */
- v &= ~GEM_MAC_RX_PROMISCUOUS;
- v |= GEM_MAC_RX_HASH_FILTER;
-
/*
* Set up multicast address filter by passing all multicast addresses
- * through a crc generator, and then using the high order 6 bits as an
- * index into the 256 bit logical address filter. The high order bit
- * selects the word, while the rest of the bits select the bit within
- * the word.
+ * through a crc generator, and then using the high order 8 bits as an
+ * index into the 256 bit logical address filter. The high order 4
+ * bits select the word, while the other 4 bits select the bit within
+ * the word (where bit 0 is the MSB).
*/
+ /* Clear hash table */
+ memset(hash, 0, sizeof(hash));
+
ETHER_FIRST_MULTI(step, ec, enm);
while (enm != NULL) {
if (memcmp(enm->enm_addrlo, enm->enm_addrhi, ETHER_ADDR_LEN)) {
@@ -1794,59 +1857,36 @@
* the range. (At this time, the only use of address
* ranges is for IP multicast routing, for which the
* range is big enough to require all bits set.)
+ * XXX use the addr filter for this
*/
- hash[3] = hash[2] = hash[1] = hash[0] = 0xffff;
ifp->if_flags |= IFF_ALLMULTI;
+ v |= GEM_MAC_RX_PROMISC_GRP;
Home |
Main Index |
Thread Index |
Old Index