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"); }
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); }
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); }
/* * 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); }
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 }
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); }
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); }
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); }
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); }
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); }
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); }