Exemple #1
0
void
conf_print_media_word(FILE *output, int ifmw)
{
	const struct ifmedia_description *desc;
	int seen_option = 0;

	fprintf(output, " media %s", get_media_subtype_string(ifmw));
	if (IFM_INST(ifmw) != 0)
		printf(" %llu", IFM_INST(ifmw));
	fprintf(output, "\n");

	/* Find options. */
	for (desc = ifm_option_descriptions; desc->ifmt_string != NULL;
	    desc++) {
		if (IFM_TYPE_MATCH(desc->ifmt_word, ifmw) &&
		    (IFM_OPTIONS(ifmw) & IFM_OPTIONS(desc->ifmt_word)) != 0 &&
		    (seen_option & IFM_OPTIONS(desc->ifmt_word)) == 0) {
			if (seen_option == 0)
				fprintf(output, " mediaopt ");
			fprintf(output, "%s%s", seen_option ? "," : "",
			    desc->ifmt_string);
			seen_option |= IFM_OPTIONS(desc->ifmt_word);
		}
	}
	if (seen_option)
		fprintf(output, "\n");
}
Exemple #2
0
void
print_media_word(uint64_t ifmw, int print_type, int as_syntax)
{
	const struct ifmedia_description *desc;
	uint64_t	seen_option = 0;

	if (print_type)
		printf("%s ", get_media_type_string(ifmw));
	printf("%s%s", as_syntax ? "media " : "",
	       get_media_subtype_string(ifmw));
	if (IFM_INST(ifmw) != 0)
		printf(" %lld", IFM_INST(ifmw));

	/* Find options. */
	for (desc = ifm_option_descriptions; desc->ifmt_string != NULL;
	     desc++) {
		if (IFM_TYPE_MATCH(desc->ifmt_word, ifmw) &&
		  (IFM_OPTIONS(ifmw) & IFM_OPTIONS(desc->ifmt_word)) != 0 &&
		    (seen_option & IFM_OPTIONS(desc->ifmt_word)) == 0) {
			if (seen_option == 0)
				printf("%s", as_syntax ? ", mediaopt " : " ");
			printf("%s%s", seen_option ? "," : "",
			       desc->ifmt_string);
			seen_option |= IFM_OPTIONS(desc->ifmt_word);
		}
	}
}
void
cas_mii_statchg(struct device *dev)
{
	struct cas_softc *sc = (void *)dev;
#ifdef CAS_DEBUG
	int instance = IFM_INST(sc->sc_mii.mii_media.ifm_cur->ifm_media);
#endif
	bus_space_tag_t t = sc->sc_memt;
	bus_space_handle_t mac = sc->sc_memh;
	u_int32_t v;

#ifdef CAS_DEBUG
	if (sc->sc_debug)
		printf("cas_mii_statchg: status change: phy = %d\n",
		    sc->sc_phys[instance]);
#endif

	/* Set tx full duplex options */
	bus_space_write_4(t, mac, CAS_MAC_TX_CONFIG, 0);
	delay(10000); /* reg must be cleared and delay before changing. */
	v = CAS_MAC_TX_ENA_IPG0|CAS_MAC_TX_NGU|CAS_MAC_TX_NGU_LIMIT|
		CAS_MAC_TX_ENABLE;
	if ((IFM_OPTIONS(sc->sc_mii.mii_media_active) & IFM_FDX) != 0) {
		v |= CAS_MAC_TX_IGN_CARRIER|CAS_MAC_TX_IGN_COLLIS;
	}
	bus_space_write_4(t, mac, CAS_MAC_TX_CONFIG, v);

	/* XIF Configuration */
	v = CAS_MAC_XIF_TX_MII_ENA;
	v |= CAS_MAC_XIF_LINK_LED;

	/* MII needs echo disable if half duplex. */
	if ((IFM_OPTIONS(sc->sc_mii.mii_media_active) & IFM_FDX) != 0)
		/* turn on full duplex LED */
		v |= CAS_MAC_XIF_FDPLX_LED;
	else
		/* half duplex -- disable echo */
		v |= CAS_MAC_XIF_ECHO_DISABL;

	switch (IFM_SUBTYPE(sc->sc_mii.mii_media_active)) {
	case IFM_1000_T:  /* Gigabit using GMII interface */
	case IFM_1000_SX:
		v |= CAS_MAC_XIF_GMII_MODE;
		break;
	default:
		v &= ~CAS_MAC_XIF_GMII_MODE;
	}
	bus_space_write_4(t, mac, CAS_MAC_XIF_CONFIG, v);
}
Exemple #4
0
uint64_t
get_media_options(uint64_t type, const char *val)
{
	char           *optlist, *str;
	uint64_t	option, rval = 0;

	/* We muck with the string, so copy it. */
	optlist = (char *)strdup(val);
	if (optlist == NULL) {
		printf("%% get_media_options: strdup: %s\n", strerror(errno));
		return(-1);
	}
	str = optlist;

	/*
         * Look up the options in the user-provided comma-separated list.
         */
	for (; (str = (char *)strtok(str, ",")) != NULL; str = NULL) {
		option = lookup_media_word(ifm_option_descriptions, type, str);
		if (option == -1) {
			printf("%% get_media_options: unknown %s media option: %s\n",
			     get_media_type_string(type), str);
			free(optlist);
			return(-1);
		}
		rval |= IFM_OPTIONS(option);
	}

	free(optlist);
	return (rval);
}
Exemple #5
0
/*
 * Callback from PHY when media changes.
 */
void
epic_statchg(struct device *self)
{
	struct epic_softc *sc = (struct epic_softc *)self;
	u_int32_t txcon, miicfg;

	/*
	 * Update loopback bits in TXCON to reflect duplex mode.
	 */
	txcon = bus_space_read_4(sc->sc_st, sc->sc_sh, EPIC_TXCON);
	if (sc->sc_mii.mii_media_active & IFM_FDX)
		txcon |= (TXCON_LOOPBACK_D1|TXCON_LOOPBACK_D2);
	else
		txcon &= ~(TXCON_LOOPBACK_D1|TXCON_LOOPBACK_D2);
	bus_space_write_4(sc->sc_st, sc->sc_sh, EPIC_TXCON, txcon);

	/* On some cards we need manualy set fullduplex led */
	if (sc->sc_hwflags & EPIC_DUPLEXLED_ON_694) {
		miicfg = bus_space_read_4(sc->sc_st, sc->sc_sh, EPIC_MIICFG);
		if (IFM_OPTIONS(sc->sc_mii.mii_media_active) & IFM_FDX)
			miicfg |= MIICFG_ENABLE;
		else
			miicfg &= ~MIICFG_ENABLE;
		bus_space_write_4(sc->sc_st, sc->sc_sh, EPIC_MIICFG, miicfg);
	}

	/*
	 * There is a multicast filter bug in 10Mbps mode.  Kick the
	 * multicast filter in case the speed changed.
	 */
	epic_set_mchash(sc);
}
Exemple #6
0
void
bmac_mii_statchg(struct device *dev)
{
	struct bmac_softc *sc = (void *)dev;
	int x;

	/* Update duplex mode in TX configuration */
	x = bmac_read_reg(sc, TXCFG);
	if ((IFM_OPTIONS(sc->sc_mii.mii_media_active) & IFM_FDX) != 0)
		x |= TxFullDuplex;
	else
		x &= ~TxFullDuplex;
	bmac_write_reg(sc, TXCFG, x);

#ifdef BMAC_DEBUG
	printf("bmac_mii_statchg 0x%x\n",
		IFM_OPTIONS(sc->sc_mii.mii_media_active));
#endif
}
Exemple #7
0
int
intmediaopt(char *ifname, int ifs, int argc, char **argv)
{
	int set, media_current, mediaopt;

	if (NO_ARG(argv[0])) {
		set = 0;
		argc--;
		argv++;
	} else
		set = 1;

	argv++;
	argc--;

	if ((set && (argc != 1)) || (!set && (argc > 1))) {
		printf("%% mediaopt <option>\n");
		printf("%% no mediaopt [option]\n");
		return(0);
	}

        media_current = init_current_media(ifs, ifname);

	if (media_current == -1) {
		if (errno == EINVAL)
			printf("%% This device does not support "
			    "media commands.\n");
		else
			printf("%% Failed to initialize media: %s\n",
			    strerror(errno));
		return(0);
	}

	if (argc == 1)
		mediaopt = get_media_options(IFM_TYPE(media_current), argv[0]);
	else
		mediaopt = IFM_OPTIONS(media_current);

	if (mediaopt == -1)
		return(0);

	if (set)
		media_current |= mediaopt;
	else
		media_current &= ~mediaopt;

	process_media_commands(ifs, ifname, media_current);

	return(0);
}
Exemple #8
0
static int
le_pci_mediachange(struct lance_softc *sc)
{
	struct ifmedia *ifm = &sc->sc_media;
	uint16_t reg;

	if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER)
		return (EINVAL);

	if (IFM_SUBTYPE(ifm->ifm_media) == IFM_HPNA_1)
		le_pci_wrbcr(sc, LE_BCR49,
		    (le_pci_rdbcr(sc, LE_BCR49) & ~LE_B49_PHYSEL) | 0x1);
	else if (IFM_SUBTYPE(ifm->ifm_media) == IFM_AUTO)
		le_pci_wrbcr(sc, LE_BCR2,
		    le_pci_rdbcr(sc, LE_BCR2) | LE_B2_ASEL);
	else {
		le_pci_wrbcr(sc, LE_BCR2,
		    le_pci_rdbcr(sc, LE_BCR2) & ~LE_B2_ASEL);

		reg = le_pci_rdcsr(sc, LE_CSR15);
		reg &= ~LE_C15_PORTSEL(LE_PORTSEL_MASK);
		if (IFM_SUBTYPE(ifm->ifm_media) == IFM_10_T)
			reg |= LE_C15_PORTSEL(LE_PORTSEL_10T);
		else
			reg |= LE_C15_PORTSEL(LE_PORTSEL_AUI);
		le_pci_wrcsr(sc, LE_CSR15, reg);
	}

	reg = le_pci_rdbcr(sc, LE_BCR9);
	if (IFM_OPTIONS(ifm->ifm_media) & IFM_FDX) {
		reg |= LE_B9_FDEN;
		/*
		 * Allow FDX on AUI only if explicitly chosen,
		 * not in autoselect mode.
		 */
		if (IFM_SUBTYPE(ifm->ifm_media) == IFM_10_5)
			reg |= LE_B9_AUIFD;
		else
			reg &= ~LE_B9_AUIFD;
	} else
		reg &= ~LE_B9_FDEN;
	le_pci_wrbcr(sc, LE_BCR9, reg);

	return (0);
}
Exemple #9
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);
}
Exemple #10
0
static void
ffec_miibus_statchg(device_t dev)
{
	struct ffec_softc *sc;
	struct mii_data *mii;
	uint32_t ecr, rcr, tcr;

	/*
	 * Called by the MII bus driver when the PHY establishes link to set the
	 * MAC interface registers.
	 */

	sc = device_get_softc(dev);

	FFEC_ASSERT_LOCKED(sc);

	mii = sc->mii_softc;

	if (mii->mii_media_status & IFM_ACTIVE)
		sc->link_is_up = true;
	else
		sc->link_is_up = false;

	ecr = RD4(sc, FEC_ECR_REG) & ~FEC_ECR_SPEED;
	rcr = RD4(sc, FEC_RCR_REG) & ~(FEC_RCR_RMII_10T | FEC_RCR_RMII_MODE |
	    FEC_RCR_RGMII_EN | FEC_RCR_DRT | FEC_RCR_FCE);
	tcr = RD4(sc, FEC_TCR_REG) & ~FEC_TCR_FDEN;

	rcr |= FEC_RCR_MII_MODE; /* Must always be on even for R[G]MII. */
	switch (sc->phy_conn_type) {
	case PHY_CONN_MII:
		break;
	case PHY_CONN_RMII:
		rcr |= FEC_RCR_RMII_MODE;
		break;
	case PHY_CONN_RGMII:
		rcr |= FEC_RCR_RGMII_EN;
		break;
	}

	switch (IFM_SUBTYPE(mii->mii_media_active)) {
	case IFM_1000_T:
	case IFM_1000_SX:
		ecr |= FEC_ECR_SPEED;
		break;
	case IFM_100_TX:
		/* Not-FEC_ECR_SPEED + not-FEC_RCR_RMII_10T means 100TX */
		break;
	case IFM_10_T:
		rcr |= FEC_RCR_RMII_10T;
		break;
	case IFM_NONE:
		sc->link_is_up = false;
		return;
	default:
		sc->link_is_up = false;
		device_printf(dev, "Unsupported media %u\n",
		    IFM_SUBTYPE(mii->mii_media_active));
		return;
	}

	if ((IFM_OPTIONS(mii->mii_media_active) & IFM_FDX) != 0)
		tcr |= FEC_TCR_FDEN;
	else
		rcr |= FEC_RCR_DRT;

	if ((IFM_OPTIONS(mii->mii_media_active) & IFM_FLOW) != 0)
		rcr |= FEC_RCR_FCE;

	WR4(sc, FEC_RCR_REG, rcr);
	WR4(sc, FEC_TCR_REG, tcr);
	WR4(sc, FEC_ECR_REG, ecr);
}
Exemple #11
0
void
mii_phy_setmedia(struct mii_softc *sc)
{
	struct mii_data *mii = sc->mii_pdata;
	struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
	int bmcr, anar, gtcr;
	int index = -1;

	switch (IFM_SUBTYPE(ife->ifm_media)) {
	case IFM_AUTO:
		/*
		 * Force renegotiation if MIIF_DOPAUSE or MIIF_FORCEANEG.
		 * The former is necessary as we might switch from flow-
		 * control advertisement being off to on or vice versa.
		 */
		if ((PHY_READ(sc, MII_BMCR) & BMCR_AUTOEN) == 0 ||
		    (sc->mii_flags & (MIIF_DOPAUSE | MIIF_FORCEANEG)) != 0)
			(void)mii_phy_auto(sc);
		return;

	case IFM_NONE:
		index = MII_MEDIA_NONE;
		break;

	case IFM_HPNA_1:
		index = MII_MEDIA_10_T;
		break;

	case IFM_10_T:
		switch (IFM_OPTIONS(ife->ifm_media)) {
		case 0:
			index = MII_MEDIA_10_T;
			break;
		case IFM_FDX:
		case (IFM_FDX | IFM_FLOW):
			index = MII_MEDIA_10_T_FDX;
			break;
		}
		break;

	case IFM_100_TX:
	case IFM_100_FX:
		switch (IFM_OPTIONS(ife->ifm_media)) {
		case 0:
			index = MII_MEDIA_100_TX;
			break;
		case IFM_FDX:
		case (IFM_FDX | IFM_FLOW):
			index = MII_MEDIA_100_TX_FDX;
			break;
		}
		break;

	case IFM_100_T4:
		index = MII_MEDIA_100_T4;
		break;

	case IFM_1000_SX:
		switch (IFM_OPTIONS(ife->ifm_media)) {
		case 0:
			index = MII_MEDIA_1000_X;
			break;
		case IFM_FDX:
		case (IFM_FDX | IFM_FLOW):
			index = MII_MEDIA_1000_X_FDX;
			break;
		}
		break;

	case IFM_1000_T:
		switch (IFM_OPTIONS(ife->ifm_media)) {
		case 0:
		case IFM_ETH_MASTER:
			index = MII_MEDIA_1000_T;
			break;
		case IFM_FDX:
		case (IFM_FDX | IFM_ETH_MASTER):
		case (IFM_FDX | IFM_FLOW):
		case (IFM_FDX | IFM_FLOW | IFM_ETH_MASTER):
			index = MII_MEDIA_1000_T_FDX;
			break;
		}
		break;
	}

	KASSERT(index != -1, ("%s: failed to map media word %d",
	    __func__, ife->ifm_media));

	anar = mii_media_table[index].mm_anar;
	bmcr = mii_media_table[index].mm_bmcr;
	gtcr = mii_media_table[index].mm_gtcr;

	if (IFM_SUBTYPE(ife->ifm_media) == IFM_1000_T) {
		gtcr |= GTCR_MAN_MS;
		if ((ife->ifm_media & IFM_ETH_MASTER) != 0)
			gtcr |= GTCR_ADV_MS;
	}

	if ((ife->ifm_media & IFM_FDX) != 0 &&
	    ((ife->ifm_media & IFM_FLOW) != 0 ||
	    (sc->mii_flags & MIIF_FORCEPAUSE) != 0)) {
		if ((sc->mii_flags & MIIF_IS_1000X) != 0)
			anar |= ANAR_X_PAUSE_TOWARDS;
		else {
			anar |= ANAR_FC;
			/* XXX Only 1000BASE-T has PAUSE_ASYM? */
			if ((sc->mii_flags & MIIF_HAVE_GTCR) != 0 &&
			    (sc->mii_extcapabilities &
			    (EXTSR_1000THDX | EXTSR_1000TFDX)) != 0)
				anar |= ANAR_X_PAUSE_ASYM;
		}
	}

	PHY_WRITE(sc, MII_ANAR, anar);
	PHY_WRITE(sc, MII_BMCR, bmcr);
	if ((sc->mii_flags & MIIF_HAVE_GTCR) != 0)
		PHY_WRITE(sc, MII_100T2CR, gtcr);
}
Exemple #12
0
static void
awg_update_link_locked(struct awg_softc *sc)
{
	struct mii_data *mii;
	uint32_t val;

	AWG_ASSERT_LOCKED(sc);

	if ((if_getdrvflags(sc->ifp) & IFF_DRV_RUNNING) == 0)
		return;
	mii = device_get_softc(sc->miibus);

	if ((mii->mii_media_status & (IFM_ACTIVE | IFM_AVALID)) ==
	    (IFM_ACTIVE | IFM_AVALID)) {
		switch (IFM_SUBTYPE(mii->mii_media_active)) {
		case IFM_1000_T:
		case IFM_1000_SX:
		case IFM_100_TX:
		case IFM_10_T:
			sc->link = 1;
			break;
		default:
			sc->link = 0;
			break;
		}
	} else
		sc->link = 0;

	if (sc->link == 0)
		return;

	val = RD4(sc, EMAC_BASIC_CTL_0);
	val &= ~(BASIC_CTL_SPEED | BASIC_CTL_DUPLEX);

	if (IFM_SUBTYPE(mii->mii_media_active) == IFM_1000_T ||
	    IFM_SUBTYPE(mii->mii_media_active) == IFM_1000_SX)
		val |= BASIC_CTL_SPEED_1000 << BASIC_CTL_SPEED_SHIFT;
	else if (IFM_SUBTYPE(mii->mii_media_active) == IFM_100_TX)
		val |= BASIC_CTL_SPEED_100 << BASIC_CTL_SPEED_SHIFT;
	else
		val |= BASIC_CTL_SPEED_10 << BASIC_CTL_SPEED_SHIFT;

	if ((IFM_OPTIONS(mii->mii_media_active) & IFM_FDX) != 0)
		val |= BASIC_CTL_DUPLEX;

	WR4(sc, EMAC_BASIC_CTL_0, val);

	val = RD4(sc, EMAC_RX_CTL_0);
	val &= ~RX_FLOW_CTL_EN;
	if ((IFM_OPTIONS(mii->mii_media_active) & IFM_ETH_RXPAUSE) != 0)
		val |= RX_FLOW_CTL_EN;
	WR4(sc, EMAC_RX_CTL_0, val);

	val = RD4(sc, EMAC_TX_FLOW_CTL);
	val &= ~(PAUSE_TIME|TX_FLOW_CTL_EN);
	if ((IFM_OPTIONS(mii->mii_media_active) & IFM_ETH_TXPAUSE) != 0)
		val |= TX_FLOW_CTL_EN;
	if ((IFM_OPTIONS(mii->mii_media_active) & IFM_FDX) != 0)
		val |= awg_pause_time << PAUSE_TIME_SHIFT;
	WR4(sc, EMAC_TX_FLOW_CTL, val);
}