コード例 #1
0
ファイル: if_smsc.c プロジェクト: ryoon/netbsd-xhci
void
smsc_setmulti(struct smsc_softc *sc)
{
    struct ifnet		*ifp = &sc->sc_ec.ec_if;
    struct ether_multi	*enm;
    struct ether_multistep	 step;
    uint32_t		 hashtbl[2] = { 0, 0 };
    uint32_t		 hash;

    if (sc->sc_dying)
        return;

    if (ifp->if_flags & (IFF_ALLMULTI | IFF_PROMISC)) {
allmulti:
        smsc_dbg_printf(sc, "receive all multicast enabled\n");
        sc->sc_mac_csr |= SMSC_MAC_CSR_MCPAS;
        sc->sc_mac_csr &= ~SMSC_MAC_CSR_HPFILT;
        smsc_write_reg(sc, SMSC_MAC_CSR, sc->sc_mac_csr);
        return;
    } else {
        sc->sc_mac_csr |= SMSC_MAC_CSR_HPFILT;
        sc->sc_mac_csr &= ~(SMSC_MAC_CSR_PRMS | SMSC_MAC_CSR_MCPAS);
    }

    ETHER_FIRST_MULTI(step, &sc->sc_ec, enm);
    while (enm != NULL) {
        if (memcmp(enm->enm_addrlo, enm->enm_addrhi,
                   ETHER_ADDR_LEN) != 0)
            goto allmulti;

        hash = smsc_hash(enm->enm_addrlo);
        hashtbl[hash >> 5] |= 1 << (hash & 0x1F);
        ETHER_NEXT_MULTI(step, enm);
    }

    /* Debug */
    if (sc->sc_mac_csr & SMSC_MAC_CSR_HPFILT) {
        smsc_dbg_printf(sc, "receive select group of macs\n");
    } else {
        smsc_dbg_printf(sc, "receive own packets only\n");
    }

    /* Write the hash table and mac control registers */
    ifp->if_flags &= ~IFF_ALLMULTI;
    smsc_write_reg(sc, SMSC_HASHH, hashtbl[1]);
    smsc_write_reg(sc, SMSC_HASHL, hashtbl[0]);
    smsc_write_reg(sc, SMSC_MAC_CSR, sc->sc_mac_csr);
}
コード例 #2
0
void
smsc_iff(struct smsc_softc *sc)
{
	struct ifnet		*ifp = &sc->sc_ac.ac_if;
	struct arpcom		*ac = &sc->sc_ac;
	struct ether_multi	*enm;
	struct ether_multistep	 step;
	uint32_t		 hashtbl[2] = { 0, 0 };
	uint32_t		 hash;

	if (usbd_is_dying(sc->sc_udev))
		return;

	sc->sc_mac_csr &= ~(SMSC_MAC_CSR_HPFILT | SMSC_MAC_CSR_MCPAS |
	    SMSC_MAC_CSR_PRMS);
	ifp->if_flags &= ~IFF_ALLMULTI;

	if (ifp->if_flags & IFF_PROMISC || ac->ac_multirangecnt > 0) {
		ifp->if_flags |= IFF_ALLMULTI;
		sc->sc_mac_csr |= SMSC_MAC_CSR_MCPAS;
		if (ifp->if_flags & IFF_PROMISC)
			sc->sc_mac_csr |= SMSC_MAC_CSR_PRMS;
	} else {
		sc->sc_mac_csr |= SMSC_MAC_CSR_HPFILT;

		ETHER_FIRST_MULTI(step, ac, enm);
		while (enm != NULL) {
			hash = smsc_hash(enm->enm_addrlo);

			hashtbl[hash >> 5] |= 1 << (hash & 0x1F);

			ETHER_NEXT_MULTI(step, enm);
		}
	}

	/* Debug */
	if (sc->sc_mac_csr & SMSC_MAC_CSR_MCPAS)
		smsc_dbg_printf(sc, "receive all multicast enabled\n");
	else if (sc->sc_mac_csr & SMSC_MAC_CSR_HPFILT)
		smsc_dbg_printf(sc, "receive select group of macs\n");

	/* Write the hash table and mac control registers */
	smsc_write_reg(sc, SMSC_HASHH, hashtbl[1]);
	smsc_write_reg(sc, SMSC_HASHL, hashtbl[0]);
	smsc_write_reg(sc, SMSC_MAC_CSR, sc->sc_mac_csr);
}
コード例 #3
0
int
smsc_setmacaddress(struct smsc_softc *sc, const uint8_t *addr)
{
	int err;
	uint32_t val;

	smsc_dbg_printf(sc, "setting mac address to "
	    "%02x:%02x:%02x:%02x:%02x:%02x\n",
	    addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);

	val = (addr[3] << 24) | (addr[2] << 16) | (addr[1] << 8) | addr[0];
	if ((err = smsc_write_reg(sc, SMSC_MAC_ADDRL, val)) != 0)
		goto done;
		
	val = (addr[5] << 8) | addr[4];
	err = smsc_write_reg(sc, SMSC_MAC_ADDRH, val);
	
done:
	return (err);
}
コード例 #4
0
void
smsc_miibus_statchg(struct device *dev)
{
	struct smsc_softc *sc = (struct smsc_softc *)dev;
	struct mii_data *mii = &sc->sc_mii;
	struct ifnet *ifp = &sc->sc_ac.ac_if;
	int err;
	uint32_t flow;
	uint32_t afc_cfg;

	if (mii == NULL || ifp == NULL ||
	    (ifp->if_flags & IFF_RUNNING) == 0)
		return;

	/* Use the MII status to determine link status */
	sc->sc_flags &= ~SMSC_FLAG_LINK;
	if ((mii->mii_media_status & (IFM_ACTIVE | IFM_AVALID)) ==
	    (IFM_ACTIVE | IFM_AVALID)) {
		switch (IFM_SUBTYPE(mii->mii_media_active)) {
			case IFM_10_T:
			case IFM_100_TX:
				sc->sc_flags |= SMSC_FLAG_LINK;
				break;
			case IFM_1000_T:
				/* Gigabit ethernet not supported by chipset */
				break;
			default:
				break;
		}
	}

	/* Lost link, do nothing. */
	if ((sc->sc_flags & SMSC_FLAG_LINK) == 0) {
		smsc_dbg_printf(sc, "link flag not set\n");
		return;
	}
	
	err = smsc_read_reg(sc, SMSC_AFC_CFG, &afc_cfg);
	if (err) {
		smsc_warn_printf(sc, "failed to read initial AFC_CFG, "
		    "error %d\n", err);
		return;
	}
	
	/* Enable/disable full duplex operation and TX/RX pause */
	if ((IFM_OPTIONS(mii->mii_media_active) & IFM_FDX) != 0) {
		smsc_dbg_printf(sc, "full duplex operation\n");
		sc->sc_mac_csr &= ~SMSC_MAC_CSR_RCVOWN;
		sc->sc_mac_csr |= SMSC_MAC_CSR_FDPX;

		if ((IFM_OPTIONS(mii->mii_media_active) & IFM_ETH_RXPAUSE) != 0)
			flow = 0xffff0002;
		else
			flow = 0;
			
		if ((IFM_OPTIONS(mii->mii_media_active) & IFM_ETH_TXPAUSE) != 0)
			afc_cfg |= 0xf;
		else
			afc_cfg &= ~0xf;
		
	} else {
		smsc_dbg_printf(sc, "half duplex operation\n");
		sc->sc_mac_csr &= ~SMSC_MAC_CSR_FDPX;
		sc->sc_mac_csr |= SMSC_MAC_CSR_RCVOWN;
		
		flow = 0;
		afc_cfg |= 0xf;
	}

	err = smsc_write_reg(sc, SMSC_MAC_CSR, sc->sc_mac_csr);
	err += smsc_write_reg(sc, SMSC_FLOW, flow);
	err += smsc_write_reg(sc, SMSC_AFC_CFG, afc_cfg);
	if (err)
		smsc_warn_printf(sc, "media change failed, error %d\n", err);
}