Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/netbsd-1-5]: src/sys/dev/pci Sync with trunk: Add support for the DP8381...
details: https://anonhg.NetBSD.org/src/rev/6ce397ac0300
branches: netbsd-1-5
changeset: 489559:6ce397ac0300
user: thorpej <thorpej%NetBSD.org@localhost>
date: Thu Sep 28 16:42:55 2000 +0000
description:
Sync with trunk: Add support for the DP83815 10/100 Ethernet,
found on new NetGear cards.
diffstat:
sys/dev/pci/if_sip.c | 321 +++++++++++++++++++++++++++++++++++++++++------
sys/dev/pci/if_sipreg.h | 73 ++++++++++-
2 files changed, 350 insertions(+), 44 deletions(-)
diffs (truncated from 585 to 300 lines):
diff -r ed8a0f6416da -r 6ce397ac0300 sys/dev/pci/if_sip.c
--- a/sys/dev/pci/if_sip.c Thu Sep 28 16:36:36 2000 +0000
+++ b/sys/dev/pci/if_sip.c Thu Sep 28 16:42:55 2000 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: if_sip.c,v 1.11.4.1 2000/08/12 18:50:25 tsutsui Exp $ */
+/* $NetBSD: if_sip.c,v 1.11.4.2 2000/09/28 16:42:55 thorpej Exp $ */
/*-
* Copyright (c) 1999 Network Computer, Inc.
@@ -77,6 +77,7 @@
#include <machine/intr.h>
#include <machine/endian.h>
+#include <dev/mii/mii.h>
#include <dev/mii/miivar.h>
#include <dev/pci/pcireg.h>
@@ -86,23 +87,6 @@
#include <dev/pci/if_sipreg.h>
/*
- * Devices supported by this driver.
- */
-const struct sip_product {
- pci_vendor_id_t sip_vendor;
- pci_product_id_t sip_product;
- const char *sip_name;
-} sip_products[] = {
- { PCI_VENDOR_SIS, PCI_PRODUCT_SIS_900,
- "SiS 900 10/100 Ethernet" },
- { PCI_VENDOR_SIS, PCI_PRODUCT_SIS_7016,
- "SiS 7016 10/100 Ethernet" },
-
- { 0, 0,
- NULL },
-};
-
-/*
* Transmit descriptor list size. This is arbitrary, but allocate
* enough descriptors for 64 pending transmissions, and 16 segments
* per packet. This MUST work out to a power of 2.
@@ -174,7 +158,8 @@
bus_dma_tag_t sc_dmat; /* bus DMA tag */
struct ethercom sc_ethercom; /* ethernet common data */
void *sc_sdhook; /* shutdown hook */
- pci_product_id_t sc_model; /* which model are we? */
+
+ const struct sip_product *sc_model; /* which model are we? */
void *sc_ih; /* interrupt cookie */
@@ -258,8 +243,8 @@
struct sip_rxsoft *__rxs = &(sc)->sc_rxsoft[(x)]; \
struct sip_desc *__sipd = &(sc)->sc_rxdescs[(x)]; \
\
- __sipd->sipd_link = htole32(SIP_CDRXADDR((sc), SIP_NEXTRX((x)))); \
- __sipd->sipd_bufptr = htole32(__rxs->rxs_dmamap->dm_segs[0].ds_addr); \
+ __sipd->sipd_link = htole32(SIP_CDRXADDR((sc), SIP_NEXTRX((x)))); \
+ __sipd->sipd_bufptr = htole32(__rxs->rxs_dmamap->dm_segs[0].ds_addr); \
__sipd->sipd_cmdsts = htole32(CMDSTS_INTR | \
((MCLBYTES - 1) & CMDSTS_SIZE_MASK)); \
SIP_CDRXSYNC((sc), (x), BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); \
@@ -279,16 +264,22 @@
void sip_rxdrain __P((struct sip_softc *));
int sip_add_rxbuf __P((struct sip_softc *, int));
void sip_read_eeprom __P((struct sip_softc *, int, int, u_int16_t *));
-void sip_set_filter __P((struct sip_softc *));
void sip_tick __P((void *));
+void sip_sis900_set_filter __P((struct sip_softc *));
+void sip_dp83815_set_filter __P((struct sip_softc *));
+
int sip_intr __P((void *));
void sip_txintr __P((struct sip_softc *));
void sip_rxintr __P((struct sip_softc *));
-int sip_mii_readreg __P((struct device *, int, int));
-void sip_mii_writereg __P((struct device *, int, int, int));
-void sip_mii_statchg __P((struct device *));
+int sip_sis900_mii_readreg __P((struct device *, int, int));
+void sip_sis900_mii_writereg __P((struct device *, int, int, int));
+void sip_sis900_mii_statchg __P((struct device *));
+
+int sip_dp83815_mii_readreg __P((struct device *, int, int));
+void sip_dp83815_mii_writereg __P((struct device *, int, int, int));
+void sip_dp83815_mii_statchg __P((struct device *));
int sip_mediachange __P((struct ifnet *));
void sip_mediastatus __P((struct ifnet *, struct ifmediareq *));
@@ -302,6 +293,51 @@
sizeof(struct sip_softc), sip_match, sip_attach,
};
+/*
+ * Descriptions of the variants of the SiS900.
+ */
+struct sip_variant {
+ int (*sipv_mii_readreg) __P((struct device *, int, int));
+ void (*sipv_mii_writereg) __P((struct device *, int, int, int));
+ void (*sipv_mii_statchg) __P((struct device *));
+ void (*sipv_set_filter) __P((struct sip_softc *));
+};
+
+const struct sip_variant sip_variant_sis900 = {
+ sip_sis900_mii_readreg, sip_sis900_mii_writereg,
+ sip_sis900_mii_statchg, sip_sis900_set_filter
+};
+
+const struct sip_variant sip_variant_dp83815 = {
+ sip_dp83815_mii_readreg, sip_dp83815_mii_writereg,
+ sip_dp83815_mii_statchg, sip_dp83815_set_filter
+};
+
+/*
+ * Devices supported by this driver.
+ */
+const struct sip_product {
+ pci_vendor_id_t sip_vendor;
+ pci_product_id_t sip_product;
+ const char *sip_name;
+ const struct sip_variant *sip_variant;
+} sip_products[] = {
+ { PCI_VENDOR_SIS, PCI_PRODUCT_SIS_900,
+ "SiS 900 10/100 Ethernet",
+ &sip_variant_sis900 },
+ { PCI_VENDOR_SIS, PCI_PRODUCT_SIS_7016,
+ "SiS 7016 10/100 Ethernet",
+ &sip_variant_sis900 },
+
+ { PCI_VENDOR_NS, PCI_PRODUCT_NS_DP83815,
+ "NatSemi DP83815 10/100 Ethernet",
+ &sip_variant_dp83815 },
+
+ { 0, 0,
+ NULL,
+ NULL },
+};
+
const struct sip_product *sip_lookup __P((const struct pci_attach_args *));
const struct sip_product *
@@ -364,7 +400,7 @@
printf(": %s\n", sip->sip_name);
- sc->sc_model = PCI_PRODUCT(pa->pa_id);
+ sc->sc_model = sip;
/*
* Map the device.
@@ -524,9 +560,9 @@
* Initialize our media structures and probe the MII.
*/
sc->sc_mii.mii_ifp = ifp;
- sc->sc_mii.mii_readreg = sip_mii_readreg;
- sc->sc_mii.mii_writereg = sip_mii_writereg;
- sc->sc_mii.mii_statchg = sip_mii_statchg;
+ sc->sc_mii.mii_readreg = sip->sip_variant->sipv_mii_readreg;
+ sc->sc_mii.mii_writereg = sip->sip_variant->sipv_mii_writereg;
+ sc->sc_mii.mii_statchg = sip->sip_variant->sipv_mii_statchg;
ifmedia_init(&sc->sc_mii.mii_media, 0, sip_mediachange,
sip_mediastatus);
mii_attach(&sc->sc_dev, &sc->sc_mii, 0xffffffff, MII_PHY_ANY,
@@ -934,7 +970,7 @@
* Multicast list has changed; set the hardware filter
* accordingly.
*/
- sip_set_filter(sc);
+ (*sc->sc_model->sip_variant->sipv_set_filter)(sc);
error = 0;
}
break;
@@ -1499,7 +1535,7 @@
bus_space_write_4(st, sh, SIP_RXCFG, sc->sc_rxcfg);
/* Set up the receive filter. */
- sip_set_filter(sc);
+ (*sc->sc_model->sip_variant->sipv_set_filter)(sc);
/*
* Give the transmit and receive rings to the chip.
@@ -1762,12 +1798,12 @@
}
/*
- * sip_set_filter:
+ * sip_sis900_set_filter:
*
* Set up the receive filter.
*/
void
-sip_set_filter(sc)
+sip_sis900_set_filter(sc)
struct sip_softc *sc;
{
bus_space_tag_t st = sc->sc_st;
@@ -1870,12 +1906,120 @@
}
/*
- * sip_mii_readreg: [mii interface function]
+ * sip_dp83815_set_filter:
+ *
+ * Set up the receive filter.
+ */
+void
+sip_dp83815_set_filter(sc)
+ struct sip_softc *sc;
+{
+ bus_space_tag_t st = sc->sc_st;
+ bus_space_handle_t sh = sc->sc_sh;
+ struct ethercom *ec = &sc->sc_ethercom;
+ struct ifnet *ifp = &sc->sc_ethercom.ec_if;
+ struct ether_multi *enm;
+ u_int8_t *cp;
+ struct ether_multistep step;
+ u_int32_t crc, mchash[16];
+ int i;
+
+ /*
+ * Initialize the prototype RFCR.
+ */
+ sc->sc_rfcr = RFCR_RFEN | RFCR_AARP | RFCR_APM;
+ if (ifp->if_flags & IFF_BROADCAST)
+ sc->sc_rfcr |= RFCR_AAB;
+ if (ifp->if_flags & IFF_PROMISC) {
+ sc->sc_rfcr |= RFCR_AAP;
+ goto allmulti;
+ }
+
+ /*
+ * Set up the multicast address filter by passing all multicast
+ * addresses through a CRC generator, and then using the high-order
+ * 9 bits as an index into the 512 bit multicast hash table. The
+ * high-order bits select the slot, while the rest of the bits
+ * select the bit within the slot. Note that only the low 16-bits
+ * of each filter word are used, and there are 64 filter words.
+ */
+
+ memset(mchash, 0, sizeof(mchash));
+
+ ETHER_FIRST_MULTI(step, ec, enm);
+ while (enm != NULL) {
+ if (memcmp(enm->enm_addrlo, enm->enm_addrhi, ETHER_ADDR_LEN)) {
+ /*
+ * We must listen to a range of multicast addresses.
+ * For now, just accept all multicasts, rather than
+ * trying to set only those filter bits needed to match
+ * 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.)
+ */
+ goto allmulti;
+ }
+
+ crc = ether_crc32_le(enm->enm_addrlo, ETHER_ADDR_LEN);
+
+ /* Just want the 9 most significant bits. */
+ crc >>= 23;
+
+ /* Set the corresponding bit in the hash table. */
+ mchash[crc >> 5] |= 1 << (crc & 0x1f);
+
+ ETHER_NEXT_MULTI(step, enm);
+ }
+
+ ifp->if_flags |= ~IFF_ALLMULTI;
+ sc->sc_rfcr |= RFCR_MHEN;
+ goto setit;
+
+ allmulti:
+ ifp->if_flags |= IFF_ALLMULTI;
+ sc->sc_rfcr |= RFCR_AAM;
+
+ setit:
+#define FILTER_EMIT(addr, data) \
+ bus_space_write_4(st, sh, SIP_RFCR, (addr)); \
+ delay(1); \
+ bus_space_write_4(st, sh, SIP_RFDR, (data)); \
+ delay(1);
+
+ /*
+ * Disable receive filter, and program the node address.
+ */
+ cp = LLADDR(ifp->if_sadl);
+ FILTER_EMIT(RFCR_NS_RFADDR_PMATCH, (cp[1] << 8) | cp[0]);
+ FILTER_EMIT(RFCR_NS_RFADDR_PMATCH, (cp[3] << 8) | cp[2]);
+ FILTER_EMIT(RFCR_NS_RFADDR_PMATCH, (cp[5] << 8) | cp[4]);
+
+ if ((ifp->if_flags & IFF_ALLMULTI) == 0) {
+ /*
+ * Program the multicast hash table.
+ */
+ for (i = 0; i < 16; i++) {
+ FILTER_EMIT(RFCR_NS_RFADDR_FILTMEM + (i * 2),
+ mchash[i] & 0xffff);
+ FILTER_EMIT(RFCR_NS_RFADDR_FILTMEM + (i * 2) + 2,
+ (mchash[i] >> 16) & 0xffff);
+ }
+ }
Home |
Main Index |
Thread Index |
Old Index