示例#1
0
static int
atphy_attach(device_t dev)
{
	struct mii_softc *sc;
	struct mii_attach_args *ma;
	struct mii_data *mii;

	sc = device_get_softc(dev);
	ma = device_get_ivars(dev);

	mii_softc_init(sc, ma);
	sc->mii_dev = device_get_parent(dev);
	mii = device_get_softc(sc->mii_dev);
	LIST_INSERT_HEAD(&mii->mii_phys, sc, mii_list);

	sc->mii_inst = mii->mii_instance;
	sc->mii_service = atphy_service;
	sc->mii_pdata = mii;
	sc->mii_anegticks = MII_ANEGTICKS_GIGE;

	mii->mii_instance++;

	sc->mii_capabilities = PHY_READ(sc, MII_BMSR) & ma->mii_capmask;
	if (sc->mii_capabilities & BMSR_EXTSTAT)
		sc->mii_extcapabilities = PHY_READ(sc, MII_EXTSR);

	device_printf(dev, " ");
	if ((sc->mii_capabilities & BMSR_MEDIAMASK) == 0 &&
	    (sc->mii_extcapabilities & EXTSR_MEDIAMASK) == 0)
		kprintf("no media present");
	else
		mii_phy_add_media(sc);
	kprintf("\n");

	atphy_reset(sc);

	MIIBUS_MEDIAINIT(sc->mii_dev);
	return 0;
}
示例#2
0
static void
miibus_mediainit(device_t dev)
{
	struct mii_data		*mii;
	struct ifmedia_entry	*m;
	int			media = 0;

	/* Poke the parent in case it has any media of its own to add. */
	MIIBUS_MEDIAINIT(device_get_parent(dev));

	mii = device_get_softc(dev);
	for (m = LIST_FIRST(&mii->mii_media.ifm_list); m != NULL;
	     m = LIST_NEXT(m, ifm_list)) {
		media = m->ifm_media;
		if (media == (IFM_ETHER|IFM_AUTO))
			break;
	}

	ifmedia_set(&mii->mii_media, media);

	return;
}
示例#3
0
static int
amphy_attach(device_t dev)
{
	struct mii_softc *sc;
	struct mii_attach_args *ma;
	struct mii_data *mii;

	sc = device_get_softc(dev);
	ma = device_get_ivars(dev);
	sc->mii_dev = device_get_parent(dev);
	mii = device_get_softc(sc->mii_dev);
	LIST_INSERT_HEAD(&mii->mii_phys, sc, mii_list);

	sc->mii_inst = mii->mii_instance;
	sc->mii_phy = ma->mii_phyno;
	sc->mii_service = amphy_service;
	sc->mii_pdata = mii;

	mii->mii_instance++;

#define	ADD(m, c)	ifmedia_add(&mii->mii_media, (m), (c), NULL)

#if 0
	ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, IFM_LOOP, sc->mii_inst),
	    MII_MEDIA_100_TX);
#endif

	mii_phy_reset(sc);

	sc->mii_capabilities =
	    PHY_READ(sc, MII_BMSR) & ma->mii_capmask;
	device_printf(dev, " ");
	mii_phy_add_media(sc);
	printf("\n");
#undef ADD
	MIIBUS_MEDIAINIT(sc->mii_dev);
	return (0);
}
示例#4
0
文件: nsgphy.c 项目: MarginC/kame
static int
nsgphy_attach(device_t dev)
{
	struct mii_softc *sc;
	struct mii_attach_args *ma;
	struct mii_data *mii;
	const struct mii_phydesc *mpd;

	sc = device_get_softc(dev);
	ma = device_get_ivars(dev);
	mpd = mii_phy_match(ma, gphyters);
	if (bootverbose)
		device_printf(dev, "<rev. %d>\n", MII_REV(ma->mii_id2));
	device_printf(dev, " ");
	sc->mii_dev = device_get_parent(dev);
	mii = device_get_softc(sc->mii_dev);
	LIST_INSERT_HEAD(&mii->mii_phys, sc, mii_list);

	sc->mii_inst = mii->mii_instance;
	sc->mii_phy = ma->mii_phyno;
	sc->mii_service = nsgphy_service;
	sc->mii_pdata = mii;
	sc->mii_anegticks = 5;

	mii->mii_instance++;

	sc->mii_capabilities = (PHY_READ(sc, MII_BMSR) |
	    (BMSR_10TFDX|BMSR_10THDX)) & ma->mii_capmask;
	if (sc->mii_capabilities & BMSR_EXTSTAT)
		sc->mii_extcapabilities = PHY_READ(sc, MII_EXTSR);

	mii_phy_add_media(sc);
	printf("\n");

	MIIBUS_MEDIAINIT(sc->mii_dev);
	return(0);
}
示例#5
0
文件: bmtphy.c 项目: luciang/haiku
static int
bmtphy_attach(device_t dev)
{
	struct	mii_softc *sc;
	struct	mii_attach_args *ma;
	struct	mii_data *mii;

	sc = device_get_softc(dev);
	ma = device_get_ivars(dev);
	sc->mii_dev = device_get_parent(dev);
	mii = device_get_softc(sc->mii_dev);
	LIST_INSERT_HEAD(&mii->mii_phys, sc, mii_list);

	sc->mii_inst = mii->mii_instance;
	sc->mii_phy = ma->mii_phyno;
	sc->mii_service = bmtphy_service;
	sc->mii_pdata = mii;

	mii_phy_reset(sc);

	mii->mii_instance++;

	sc->mii_capabilities =
	    PHY_READ(sc, MII_BMSR) & ma->mii_capmask;
	device_printf(dev, " ");
	if ((sc->mii_capabilities & BMSR_MEDIAMASK) == 0)
		printf("no media present");
	else
		mii_phy_add_media(sc);

	printf("\n");

	MIIBUS_MEDIAINIT(sc->mii_dev);

	return (0);
}
示例#6
0
static int
tlphy_attach(device_t dev)
{
	struct tlphy_softc *sc;
	struct mii_attach_args *ma;
	struct mii_data *mii;
	const char *sep = "";
	int capmask = 0xFFFFFFFF;

	sc = device_get_softc(dev);
	ma = device_get_ivars(dev);
	mii_softc_init(&sc->sc_mii, ma);
	sc->sc_mii.mii_dev = device_get_parent(dev);
	mii = device_get_softc(sc->sc_mii.mii_dev);
	LIST_INSERT_HEAD(&mii->mii_phys, &sc->sc_mii, mii_list);

	sc->sc_mii.mii_inst = mii->mii_instance;
	sc->sc_mii.mii_service = tlphy_service;
	sc->sc_mii.mii_reset = mii_phy_reset;
	sc->sc_mii.mii_pdata = mii;

	if (mii->mii_instance) {
		struct mii_softc	*other;
		device_t		*devlist;
		int			devs, i;

		device_get_children(sc->sc_mii.mii_dev, &devlist, &devs);
		for (i = 0; i < devs; i++) {
			if (strcmp(device_get_name(devlist[i]), "tlphy")) {
				other = device_get_softc(devlist[i]);
				capmask &= ~other->mii_capabilities;
				break;
			}
		}
		kfree(devlist, M_TEMP);
	}

	mii->mii_instance++;

	sc->sc_mii.mii_flags &= ~MIIF_NOISOLATE;
	mii_phy_reset(&sc->sc_mii);
	sc->sc_mii.mii_flags |= MIIF_NOISOLATE;

	/*
	 * Note that if we're on a device that also supports 100baseTX,
	 * we are not going to want to use the built-in 10baseT port,
	 * since there will be another PHY on the MII wired up to the
	 * UTP connector.  The parent indicates this to us by specifying
	 * the TLPHY_MEDIA_NO_10_T bit.
	 */
	sc->sc_mii.mii_capabilities =
	    PHY_READ(&sc->sc_mii, MII_BMSR) & capmask /*ma->mii_capmask*/;

#define	ADD(m, c)	ifmedia_add(&mii->mii_media, (m), (c), NULL)

	ADD(IFM_MAKEWORD(IFM_ETHER, IFM_10_T, IFM_LOOP,
	    sc->sc_mii.mii_inst), MII_MEDIA_10_T);

#define	PRINT(s)	kprintf("%s%s", sep, s); sep = ", "

	device_printf(dev, " ");
	ADD(IFM_MAKEWORD(IFM_ETHER, IFM_10_2, 0, sc->sc_mii.mii_inst), 0);
	PRINT("10base2/BNC");
	ADD(IFM_MAKEWORD(IFM_ETHER, IFM_10_5, 0, sc->sc_mii.mii_inst), 0);
	PRINT("10base5/AUI");

	if (sc->sc_mii.mii_capabilities & BMSR_MEDIAMASK) {
		kprintf("%s", sep);
		mii_phy_add_media(&sc->sc_mii);
	} else {
		ADD(IFM_MAKEWORD(IFM_ETHER, IFM_NONE, 0, sc->sc_mii.mii_inst),
		    MII_MEDIA_NONE);
	}

	kprintf("\n");
#undef ADD
#undef PRINT
	MIIBUS_MEDIAINIT(sc->sc_mii.mii_dev);
	return(0);
}
示例#7
0
文件: brgphy.c 项目: AmirAbrams/haiku
/* Attach the PHY to the MII bus */
static int
brgphy_attach(device_t dev)
{
	struct brgphy_softc *bsc;
	struct bge_softc *bge_sc = NULL;
	struct bce_softc *bce_sc = NULL;
	struct mii_softc *sc;
	struct ifnet *ifp;

	bsc = device_get_softc(dev);
	sc = &bsc->mii_sc;

	mii_phy_dev_attach(dev, MIIF_NOISOLATE | MIIF_NOMANPAUSE,
	    &brgphy_funcs, 0);

	bsc->serdes_flags = 0;
	ifp = sc->mii_pdata->mii_ifp;

	/* Find the MAC driver associated with this PHY. */
	if (strcmp(ifp->if_dname, "bge") == 0)
		bge_sc = ifp->if_softc;
	else if (strcmp(ifp->if_dname, "bce") == 0)
		bce_sc = ifp->if_softc;

	/* Handle any special cases based on the PHY ID */
	switch (sc->mii_mpd_oui) {
	case MII_OUI_BROADCOM:
		switch (sc->mii_mpd_model) {
		case MII_MODEL_BROADCOM_BCM5706:
		case MII_MODEL_BROADCOM_BCM5714:
			/*
			 * The 5464 PHY used in the 5706 supports both copper
			 * and fiber interfaces over GMII.  Need to check the
			 * shadow registers to see which mode is actually
			 * in effect, and therefore whether we have 5706C or
			 * 5706S.
			 */
			PHY_WRITE(sc, BRGPHY_MII_SHADOW_1C,
				BRGPHY_SHADOW_1C_MODE_CTRL);
			if (PHY_READ(sc, BRGPHY_MII_SHADOW_1C) &
				BRGPHY_SHADOW_1C_ENA_1000X) {
				bsc->serdes_flags |= BRGPHY_5706S;
				sc->mii_flags |= MIIF_HAVEFIBER;
			}
			break;
		}
		break;
	case MII_OUI_BROADCOM2:
		switch (sc->mii_mpd_model) {
		case MII_MODEL_BROADCOM2_BCM5708S:
			bsc->serdes_flags |= BRGPHY_5708S;
			sc->mii_flags |= MIIF_HAVEFIBER;
			break;
		case MII_MODEL_BROADCOM2_BCM5709S:
			/*
			 * XXX
			 * 5720S and 5709S shares the same PHY id.
			 * Assume 5720S PHY if parent device is bge(4).
			 */
			if (bge_sc != NULL)
				bsc->serdes_flags |= BRGPHY_5708S;
			else
				bsc->serdes_flags |= BRGPHY_5709S;
			sc->mii_flags |= MIIF_HAVEFIBER;
			break;
		}
		break;
	}

	PHY_RESET(sc);

	/* Read the PHY's capabilities. */
	sc->mii_capabilities = PHY_READ(sc, MII_BMSR) & sc->mii_capmask;
	if (sc->mii_capabilities & BMSR_EXTSTAT)
		sc->mii_extcapabilities = PHY_READ(sc, MII_EXTSR);
	device_printf(dev, " ");

#define	ADD(m, c)	ifmedia_add(&sc->mii_pdata->mii_media, (m), (c), NULL)

	/* Add the supported media types */
	if ((sc->mii_flags & MIIF_HAVEFIBER) == 0) {
		mii_phy_add_media(sc);
		printf("\n");
	} else {
		sc->mii_anegticks = MII_ANEGTICKS_GIGE;
		ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_SX, IFM_FDX, sc->mii_inst),
			BRGPHY_S1000 | BRGPHY_BMCR_FDX);
		printf("1000baseSX-FDX, ");
		/* 2.5G support is a software enabled feature on the 5708S and 5709S. */
		if (bce_sc && (bce_sc->bce_phy_flags & BCE_PHY_2_5G_CAPABLE_FLAG)) {
			ADD(IFM_MAKEWORD(IFM_ETHER, IFM_2500_SX, IFM_FDX, sc->mii_inst), 0);
			printf("2500baseSX-FDX, ");
		} else if ((bsc->serdes_flags & BRGPHY_5708S) && bce_sc &&
		    (detect_hs21(bce_sc) != 0)) {
			/*
			 * There appears to be certain silicon revision
			 * in IBM HS21 blades that is having issues with
			 * this driver wating for the auto-negotiation to
			 * complete. This happens with a specific chip id
			 * only and when the 1000baseSX-FDX is the only
			 * mode. Workaround this issue since it's unlikely
			 * to be ever addressed.
			 */
			printf("auto-neg workaround, ");
			bsc->serdes_flags |= BRGPHY_NOANWAIT;
		}
		ADD(IFM_MAKEWORD(IFM_ETHER, IFM_AUTO, 0, sc->mii_inst), 0);
		printf("auto\n");
	}

#undef ADD
	MIIBUS_MEDIAINIT(sc->mii_dev);
	return (0);
}
示例#8
0
static int
tlphy_attach(device_t dev)
{
	device_t *devlist;
	struct mii_softc *other, *sc_mii;
	const char *sep = "";
	int capmask, devs, i;

	sc_mii = device_get_softc(dev);

	mii_phy_dev_attach(dev, MIIF_NOMANPAUSE, &tlphy_funcs, 0);

	/*
	 * Note that if we're on a device that also supports 100baseTX,
	 * we are not going to want to use the built-in 10baseT port,
	 * since there will be another PHY on the MII wired up to the
	 * UTP connector.
	 */
	capmask = BMSR_DEFCAPMASK;
	if (sc_mii->mii_inst &&
	    device_get_children(sc_mii->mii_dev, &devlist, &devs) == 0) {
		for (i = 0; i < devs; i++) {
			if (devlist[i] != dev) {
				other = device_get_softc(devlist[i]);
				capmask &= ~other->mii_capabilities;
				break;
			}
		}
		free(devlist, M_TEMP);
	}

	PHY_RESET(sc_mii);

	sc_mii->mii_capabilities = PHY_READ(sc_mii, MII_BMSR) & capmask;

#define	ADD(m, c)							\
    ifmedia_add(&sc_mii->mii_pdata->mii_media, (m), (c), NULL)
#define	PRINT(s)	printf("%s%s", sep, s); sep = ", "

	if ((sc_mii->mii_flags & (MIIF_MACPRIV0 | MIIF_MACPRIV1)) != 0 &&
	    (sc_mii->mii_capabilities & BMSR_MEDIAMASK) != 0)
		device_printf(dev, " ");
	if ((sc_mii->mii_flags & MIIF_MACPRIV0) != 0) {
		ADD(IFM_MAKEWORD(IFM_ETHER, IFM_10_2, 0, sc_mii->mii_inst),
		    0);
		PRINT("10base2/BNC");
	}
	if ((sc_mii->mii_flags & MIIF_MACPRIV1) != 0) {
		ADD(IFM_MAKEWORD(IFM_ETHER, IFM_10_5, 0, sc_mii->mii_inst),
		    0);
		PRINT("10base5/AUI");
	}
	if ((sc_mii->mii_capabilities & BMSR_MEDIAMASK) != 0) {
		printf("%s", sep);
		mii_phy_add_media(sc_mii);
	}
	if ((sc_mii->mii_flags & (MIIF_MACPRIV0 | MIIF_MACPRIV1)) != 0 &&
	    (sc_mii->mii_capabilities & BMSR_MEDIAMASK) != 0)
		printf("\n");
#undef ADD
#undef PRINT

	MIIBUS_MEDIAINIT(sc_mii->mii_dev);
	return (0);
}
示例#9
0
static int
e1000phy_attach(device_t dev)
{
	struct mii_softc *sc;
	struct mii_attach_args *ma;
	struct mii_data *mii;
	const char *sep = "";
	int fast_ether = 0;

	sc = device_get_softc(dev);
	ma = device_get_ivars(dev);
	mii_softc_init(sc, ma);
	sc->mii_dev = device_get_parent(dev);
	mii = device_get_softc(sc->mii_dev);
	LIST_INSERT_HEAD(&mii->mii_phys, sc, mii_list);

	sc->mii_inst = mii->mii_instance;
	sc->mii_service = e1000phy_service;
	sc->mii_reset = e1000phy_reset;
	sc->mii_anegticks = MII_ANEGTICKS_GIGE;
	sc->mii_pdata = mii;

	sc->mii_flags |= MIIF_NOISOLATE;

	switch (sc->mii_model) {
	case MII_MODEL_MARVELL_E1011:
	case MII_MODEL_MARVELL_E1112:
		if (PHY_READ(sc, E1000_ESSR) & E1000_ESSR_FIBER_LINK)
			sc->mii_flags |= MIIF_HAVEFIBER;
		break;
	case MII_MODEL_MARVELL_E3082:
		/* 88E3082 10/100 Fast Ethernet PHY. */
		sc->mii_anegticks = MII_ANEGTICKS;
		fast_ether = 1;
		break;
	}

	mii->mii_instance++;

	e1000phy_reset(sc);

#define	ADD(m, c)	ifmedia_add(&mii->mii_media, (m), (c), NULL)
#define PRINT(s)	kprintf("%s%s", sep, s); sep = ", "

	device_printf(dev, "%s", "");

	ADD(IFM_MAKEWORD(IFM_ETHER, IFM_NONE, 0, sc->mii_inst),
	    E1000_CR_ISOLATE);
	if ((sc->mii_flags & MIIF_HAVEFIBER) == 0) {
		if (!fast_ether) {
			/*
			 * 1000T-simplex not supported; driver must ignore
			 * this entry, but it must be present in order to
			 * manually set full-duplex.
			 */
			ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_T, 0,
			    sc->mii_inst), E1000_CR_SPEED_1000);
			ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_T, IFM_FDX,
			    sc->mii_inst),
			    E1000_CR_SPEED_1000 | E1000_CR_FULL_DUPLEX);
			PRINT("1000baseT-FDX");
		}
		ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, IFM_FDX, sc->mii_inst),
		    E1000_CR_SPEED_100 | E1000_CR_FULL_DUPLEX);
		PRINT("100baseTX-FDX");
		ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, 0, sc->mii_inst),
		    E1000_CR_SPEED_100);
		PRINT("100baseTX");
		ADD(IFM_MAKEWORD(IFM_ETHER, IFM_10_T, IFM_FDX, sc->mii_inst),
		    E1000_CR_SPEED_10 | E1000_CR_FULL_DUPLEX);
		PRINT("10baseTX-FDX");
		ADD(IFM_MAKEWORD(IFM_ETHER, IFM_10_T, 0, sc->mii_inst),
		    E1000_CR_SPEED_10);
		PRINT("10baseTX");
	} else {
		ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_SX, IFM_FDX, sc->mii_inst),
		    E1000_CR_SPEED_1000 | E1000_CR_FULL_DUPLEX);
		PRINT("1000baseSX-FDX");
	}

	ADD(IFM_MAKEWORD(IFM_ETHER, IFM_AUTO, 0, sc->mii_inst), 0);
	PRINT("auto\n");

#undef ADD
#undef PRINT

	MIIBUS_MEDIAINIT(sc->mii_dev);
	return(0);
}
示例#10
0
static int
e1000phy_attach(device_t dev)
{
	struct mii_softc *sc;
	struct mii_attach_args *ma;
	struct mii_data *mii;
	const char *sep = "";

	getenv_int("e1000phy_debug", &e1000phy_debug);

	sc = device_get_softc(dev);
	ma = device_get_ivars(dev);
	sc->mii_dev = device_get_parent(dev);
	mii = device_get_softc(sc->mii_dev);
	LIST_INSERT_HEAD(&mii->mii_phys, sc, mii_list);

	sc->mii_inst = mii->mii_instance;
	sc->mii_phy = ma->mii_phyno;
	sc->mii_service = e1000phy_service;
	sc->mii_pdata = mii;

	sc->mii_flags |= MIIF_NOISOLATE;
	mii->mii_instance++;
	e1000phy_reset(sc);

#define	ADD(m, c)	ifmedia_add(&mii->mii_media, (m), (c), NULL)
#define PRINT(s)	printf("%s%s", sep, s); sep = ", "

#if	0
	ADD(IFM_MAKEWORD(IFM_ETHER, IFM_NONE, 0, sc->mii_inst),
	    E1000_CR_ISOLATE);
#endif

	device_printf(dev, " ");
	ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_TX, IFM_FDX, sc->mii_inst),
			E1000_CR_SPEED_1000 | E1000_CR_FULL_DUPLEX);
	PRINT("1000baseTX-FDX");
	/*
	TODO - apparently 1000BT-simplex not supported?
	ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_TX, 0, sc->mii_inst),
			E1000_CR_SPEED_1000);
	PRINT("1000baseTX");
	*/
	ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, IFM_FDX, sc->mii_inst),
			E1000_CR_SPEED_100 | E1000_CR_FULL_DUPLEX);
	PRINT("100baseTX-FDX");
	ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, 0, sc->mii_inst),
			E1000_CR_SPEED_100);
	PRINT("100baseTX");
	ADD(IFM_MAKEWORD(IFM_ETHER, IFM_10_T, IFM_FDX, sc->mii_inst),
			E1000_CR_SPEED_10 | E1000_CR_FULL_DUPLEX);
	PRINT("10baseTX-FDX");
	ADD(IFM_MAKEWORD(IFM_ETHER, IFM_10_T, 0, sc->mii_inst),
			E1000_CR_SPEED_10);
	PRINT("10baseTX");
	ADD(IFM_MAKEWORD(IFM_ETHER, IFM_AUTO, 0, sc->mii_inst), 0);
	PRINT("auto");

	printf("\n");
#undef ADD
#undef PRINT

	MIIBUS_MEDIAINIT(sc->mii_dev);
	return(0);
}
示例#11
0
/* Attach the PHY to the MII bus */
static int
brgphy_attach(device_t dev)
{
	struct brgphy_softc *bsc;
	struct bge_softc *bge_sc = NULL;
	struct bce_softc *bce_sc = NULL;
	struct mii_softc *sc;
	struct mii_attach_args *ma;
	struct mii_data *mii;
	struct ifnet *ifp;
	int fast_ether;

	bsc = device_get_softc(dev);
	sc = &bsc->mii_sc;
	ma = device_get_ivars(dev);
	sc->mii_dev = device_get_parent(dev);
	mii = device_get_softc(sc->mii_dev);
	LIST_INSERT_HEAD(&mii->mii_phys, sc, mii_list);

	/* Initialize mii_softc structure */
	sc->mii_inst = mii->mii_instance;
	sc->mii_phy = ma->mii_phyno;
	sc->mii_service = brgphy_service;
	sc->mii_pdata = mii;
	sc->mii_anegticks = MII_ANEGTICKS_GIGE;
	sc->mii_flags |= MIIF_NOISOLATE | MIIF_NOLOOP;
	mii->mii_instance++;

	/* Initialize brgphy_softc structure */
	bsc->mii_oui = MII_OUI(ma->mii_id1, ma->mii_id2);
	bsc->mii_model = MII_MODEL(ma->mii_id2);
	bsc->mii_rev = MII_REV(ma->mii_id2);
	bsc->serdes_flags = 0;

	fast_ether = 0;

	if (bootverbose)
		device_printf(dev, "OUI 0x%06x, model 0x%04x, rev. %d\n",
		    bsc->mii_oui, bsc->mii_model, bsc->mii_rev);

	/* Handle any special cases based on the PHY ID */
	switch (bsc->mii_oui) {
	case MII_OUI_BROADCOM:
	case MII_OUI_BROADCOM2:
		break;
	case MII_OUI_xxBROADCOM:
		switch (bsc->mii_model) {
			case MII_MODEL_xxBROADCOM_BCM5706:
				/*
				 * The 5464 PHY used in the 5706 supports both copper
				 * and fiber interfaces over GMII.  Need to check the
				 * shadow registers to see which mode is actually
				 * in effect, and therefore whether we have 5706C or
				 * 5706S.
				 */
				PHY_WRITE(sc, BRGPHY_MII_SHADOW_1C,
					BRGPHY_SHADOW_1C_MODE_CTRL);
				if (PHY_READ(sc, BRGPHY_MII_SHADOW_1C) &
					BRGPHY_SHADOW_1C_ENA_1000X) {
					bsc->serdes_flags |= BRGPHY_5706S;
					sc->mii_flags |= MIIF_HAVEFIBER;
				}
				break;
		} break;
	case MII_OUI_xxBROADCOM_ALT1:
		switch (bsc->mii_model) {
			case MII_MODEL_xxBROADCOM_ALT1_BCM5708S:
				bsc->serdes_flags |= BRGPHY_5708S;
				sc->mii_flags |= MIIF_HAVEFIBER;
				break;
		} break;
	default:
		device_printf(dev, "Unrecognized OUI for PHY!\n");
	}

	ifp = sc->mii_pdata->mii_ifp;

	/* Find the MAC driver associated with this PHY. */
	if (strcmp(ifp->if_dname, "bge") == 0)	{
		bge_sc = ifp->if_softc;
	} else if (strcmp(ifp->if_dname, "bce") == 0) {
		bce_sc = ifp->if_softc;
	}

	/* Todo: Need to add additional controllers such as 5906 & 5787F */
	/* The 590x chips are 10/100 only. */
	if (bge_sc &&
	    pci_get_vendor(bge_sc->bge_dev) == BCOM_VENDORID &&
	    (pci_get_device(bge_sc->bge_dev) == BCOM_DEVICEID_BCM5901 ||
	    pci_get_device(bge_sc->bge_dev) == BCOM_DEVICEID_BCM5901A2 ||
	    pci_get_device(bge_sc->bge_dev) == BCOM_DEVICEID_BCM5906 ||
	    pci_get_device(bge_sc->bge_dev) == BCOM_DEVICEID_BCM5906M)) {
		fast_ether = 1;
		sc->mii_anegticks = MII_ANEGTICKS;
	}

	brgphy_reset(sc);

	/* Read the PHY's capabilities. */
	sc->mii_capabilities = PHY_READ(sc, MII_BMSR) & ma->mii_capmask;
	if (sc->mii_capabilities & BMSR_EXTSTAT)
		sc->mii_extcapabilities = PHY_READ(sc, MII_EXTSR);
	device_printf(dev, " ");

#define	ADD(m, c)	ifmedia_add(&mii->mii_media, (m), (c), NULL)

	/* Create an instance of Ethernet media. */
	ADD(IFM_MAKEWORD(IFM_ETHER, IFM_NONE, 0, sc->mii_inst), BMCR_ISO);

	/* Add the supported media types */
	if ((sc->mii_flags & MIIF_HAVEFIBER) == 0) {
		ADD(IFM_MAKEWORD(IFM_ETHER, IFM_10_T, 0, sc->mii_inst),
			BRGPHY_S10);
		printf("10baseT, ");
		ADD(IFM_MAKEWORD(IFM_ETHER, IFM_10_T, IFM_FDX, sc->mii_inst),
			BRGPHY_S10 | BRGPHY_BMCR_FDX);
		printf("10baseT-FDX, ");
		ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, 0, sc->mii_inst),
			BRGPHY_S100);
		printf("100baseTX, ");
		ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, IFM_FDX, sc->mii_inst),
			BRGPHY_S100 | BRGPHY_BMCR_FDX);
		printf("100baseTX-FDX, ");
		if (fast_ether == 0) {
			ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_T, 0, sc->mii_inst),
				BRGPHY_S1000);
			printf("1000baseT, ");
			ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_T, IFM_FDX, sc->mii_inst),
				BRGPHY_S1000 | BRGPHY_BMCR_FDX);
			printf("1000baseT-FDX, ");
		}
	} else {
		ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_SX, IFM_FDX, sc->mii_inst),
			BRGPHY_S1000 | BRGPHY_BMCR_FDX);
		printf("1000baseSX-FDX, ");
		/* 2.5G support is a software enabled feature on the 5708S and 5709S. */
		if (bce_sc && (bce_sc->bce_phy_flags & BCE_PHY_2_5G_CAPABLE_FLAG)) {
			ADD(IFM_MAKEWORD(IFM_ETHER, IFM_2500_SX, IFM_FDX, sc->mii_inst), 0);
			printf("2500baseSX-FDX, ");
		}
	}

	ADD(IFM_MAKEWORD(IFM_ETHER, IFM_AUTO, 0, sc->mii_inst), 0);
	printf("auto\n");

#undef ADD
	MIIBUS_MEDIAINIT(sc->mii_dev);
	return (0);
}
示例#12
0
static int
rlswitch_attach(device_t dev)
{
	struct mii_softc	*sc;

	sc = device_get_softc(dev);

	/*
	 * We handle all pseudo PHYs in a single instance.
	 */
	mii_phy_dev_attach(dev, MIIF_NOISOLATE | MIIF_NOMANPAUSE,
	    &rlswitch_funcs, 0);

	sc->mii_capabilities = BMSR_100TXFDX & sc->mii_capmask;
	device_printf(dev, " ");
	mii_phy_add_media(sc);
	printf("\n");
#ifdef RL_DEBUG
	rlswitch_phydump(dev);
#endif
	
#ifdef RL_VLAN
	int val;

	/* Global Control 0 */
	val = 0;
	val |= 0 << 10;		/* enable 802.1q VLAN Tag support */
	val |= 0 << 9;		/* enable VLAN ingress filtering */
	val |= 1 << 8;		/* disable VLAN tag admit control */
	val |= 1 << 6;		/* internal use */
	val |= 1 << 5;		/* internal use */
	val |= 1 << 4;		/* internal use */
	val |= 1 << 3;		/* internal use */
	val |= 1 << 1;		/* reserved */
	MIIBUS_WRITEREG(sc->mii_dev, 0, 16, val);

	/* Global Control 2 */
	val = 0;
	val |= 1 << 15;		/* reserved */
	val |= 0 << 14;		/* enable 1552 Bytes support */
	val |= 1 << 13;		/* enable broadcast input drop */
	val |= 1 << 12;		/* forward reserved control frames */
	val |= 1 << 11;		/* disable forwarding unicast frames to other VLAN's */
	val |= 1 << 10;		/* disable forwarding ARP broadcasts to other VLAN's */
	val |= 1 << 9;		/* enable 48 pass 1 */
	val |= 0 << 8;		/* enable VLAN */
	val |= 1 << 7;		/* reserved */
	val |= 1 << 6;		/* enable defer */
	val |= 1 << 5;		/* 43ms LED blink time */
	val |= 3 << 3;		/* 16:1 queue weight */
	val |= 1 << 2;		/* disable broadcast storm control */
	val |= 1 << 1;		/* enable power-on LED blinking */
	val |= 1 << 0;		/* reserved */
	MIIBUS_WRITEREG(sc->mii_dev, 0, 18, val);

	/* Port 0 Control Register 0 */
	val = 0;
	val |= 1 << 15;		/* reserved */
	val |= 1 << 11;		/* drop received packets with wrong VLAN tag */
	val |= 1 << 10;		/* disable 802.1p priority classification */
	val |= 1 << 9;		/* disable diffserv priority classification */
	val |= 1 << 6;		/* internal use */
	val |= 3 << 4;		/* internal use */
	val |= 1 << 3;		/* internal use */
	val |= 1 << 2;		/* internal use */
	val |= 1 << 0;		/* remove VLAN tags on output */
	MIIBUS_WRITEREG(sc->mii_dev, 0, 22, val);

	/* Port 1 Control Register 0 */
	val = 0;
	val |= 1 << 15;		/* reserved */
	val |= 1 << 11;		/* drop received packets with wrong VLAN tag */
	val |= 1 << 10;		/* disable 802.1p priority classification */
	val |= 1 << 9;		/* disable diffserv priority classification */
	val |= 1 << 6;		/* internal use */
	val |= 3 << 4;		/* internal use */
	val |= 1 << 3;		/* internal use */
	val |= 1 << 2;		/* internal use */
	val |= 1 << 0;		/* remove VLAN tags on output */
	MIIBUS_WRITEREG(sc->mii_dev, 1, 22, val);

	/* Port 2 Control Register 0 */
	val = 0;
	val |= 1 << 15;		/* reserved */
	val |= 1 << 11;		/* drop received packets with wrong VLAN tag */
	val |= 1 << 10;		/* disable 802.1p priority classification */
	val |= 1 << 9;		/* disable diffserv priority classification */
	val |= 1 << 6;		/* internal use */
	val |= 3 << 4;		/* internal use */
	val |= 1 << 3;		/* internal use */
	val |= 1 << 2;		/* internal use */
	val |= 1 << 0;		/* remove VLAN tags on output */
	MIIBUS_WRITEREG(sc->mii_dev, 2, 22, val);

	/* Port 3 Control Register 0 */
	val = 0;
	val |= 1 << 15;		/* reserved */
	val |= 1 << 11;		/* drop received packets with wrong VLAN tag */
	val |= 1 << 10;		/* disable 802.1p priority classification */
	val |= 1 << 9;		/* disable diffserv priority classification */
	val |= 1 << 6;		/* internal use */
	val |= 3 << 4;		/* internal use */
	val |= 1 << 3;		/* internal use */
	val |= 1 << 2;		/* internal use */
	val |= 1 << 0;		/* remove VLAN tags on output */
	MIIBUS_WRITEREG(sc->mii_dev, 3, 22, val);

	/* Port 4 (system port) Control Register 0 */
	val = 0;
	val |= 1 << 15;		/* reserved */
	val |= 0 << 11;		/* don't drop received packets with wrong VLAN tag */
	val |= 1 << 10;		/* disable 802.1p priority classification */
	val |= 1 << 9;		/* disable diffserv priority classification */
	val |= 1 << 6;		/* internal use */
	val |= 3 << 4;		/* internal use */
	val |= 1 << 3;		/* internal use */
	val |= 1 << 2;		/* internal use */
	val |= 2 << 0;		/* add VLAN tags for untagged packets on output */
	MIIBUS_WRITEREG(sc->mii_dev, 4, 22, val);

	/* Port 0 Control Register 1 and VLAN A */
	val = 0;
	val |= 0x0 << 12;	/* Port 0 VLAN Index */
	val |= 1 << 11;		/* internal use */
	val |= 1 << 10;		/* internal use */
	val |= 1 << 9;		/* internal use */
	val |= 1 << 7;		/* internal use */
	val |= 1 << 6;		/* internal use */
	val |= 0x11 << 0;	/* VLAN A membership */
	MIIBUS_WRITEREG(sc->mii_dev, 0, 24, val);

	/* Port 0 Control Register 2 and VLAN A */
	val = 0;
	val |= 1 << 15;		/* internal use */
	val |= 1 << 14;		/* internal use */
	val |= 1 << 13;		/* internal use */
	val |= 1 << 12;		/* internal use */
	val |= 0x100 << 0;	/* VLAN A ID */
	MIIBUS_WRITEREG(sc->mii_dev, 0, 25, val);

	/* Port 1 Control Register 1 and VLAN B */
	val = 0;
	val |= 0x1 << 12;	/* Port 1 VLAN Index */
	val |= 1 << 11;		/* internal use */
	val |= 1 << 10;		/* internal use */
	val |= 1 << 9;		/* internal use */
	val |= 1 << 7;		/* internal use */
	val |= 1 << 6;		/* internal use */
	val |= 0x12 << 0;	/* VLAN B membership */
	MIIBUS_WRITEREG(sc->mii_dev, 1, 24, val);

	/* Port 1 Control Register 2 and VLAN B */
	val = 0;
	val |= 1 << 15;		/* internal use */
	val |= 1 << 14;		/* internal use */
	val |= 1 << 13;		/* internal use */
	val |= 1 << 12;		/* internal use */
	val |= 0x101 << 0;	/* VLAN B ID */
	MIIBUS_WRITEREG(sc->mii_dev, 1, 25, val);

	/* Port 2 Control Register 1 and VLAN C */
	val = 0;
	val |= 0x2 << 12;	/* Port 2 VLAN Index */
	val |= 1 << 11;		/* internal use */
	val |= 1 << 10;		/* internal use */
	val |= 1 << 9;		/* internal use */
	val |= 1 << 7;		/* internal use */
	val |= 1 << 6;		/* internal use */
	val |= 0x14 << 0;	/* VLAN C membership */
	MIIBUS_WRITEREG(sc->mii_dev, 2, 24, val);

	/* Port 2 Control Register 2 and VLAN C */
	val = 0;
	val |= 1 << 15;		/* internal use */
	val |= 1 << 14;		/* internal use */
	val |= 1 << 13;		/* internal use */
	val |= 1 << 12;		/* internal use */
	val |= 0x102 << 0;	/* VLAN C ID */
	MIIBUS_WRITEREG(sc->mii_dev, 2, 25, val);

	/* Port 3 Control Register 1 and VLAN D */
	val = 0;
	val |= 0x3 << 12;	/* Port 3 VLAN Index */
	val |= 1 << 11;		/* internal use */
	val |= 1 << 10;		/* internal use */
	val |= 1 << 9;		/* internal use */
	val |= 1 << 7;		/* internal use */
	val |= 1 << 6;		/* internal use */
	val |= 0x18 << 0;	/* VLAN D membership */
	MIIBUS_WRITEREG(sc->mii_dev, 3, 24, val);

	/* Port 3 Control Register 2 and VLAN D */
	val = 0;
	val |= 1 << 15;		/* internal use */
	val |= 1 << 14;		/* internal use */
	val |= 1 << 13;		/* internal use */
	val |= 1 << 12;		/* internal use */
	val |= 0x103 << 0;	/* VLAN D ID */
	MIIBUS_WRITEREG(sc->mii_dev, 3, 25, val);

	/* Port 4 Control Register 1 and VLAN E */
	val = 0;
	val |= 0x0 << 12;	/* Port 4 VLAN Index */
	val |= 1 << 11;		/* internal use */
	val |= 1 << 10;		/* internal use */
	val |= 1 << 9;		/* internal use */
	val |= 1 << 7;		/* internal use */
	val |= 1 << 6;		/* internal use */
	val |= 0 << 0;		/* VLAN E membership */
	MIIBUS_WRITEREG(sc->mii_dev, 4, 24, val);

	/* Port 4 Control Register 2 and VLAN E */
	val = 0;
	val |= 1 << 15;		/* internal use */
	val |= 1 << 14;		/* internal use */
	val |= 1 << 13;		/* internal use */
	val |= 1 << 12;		/* internal use */
	val |= 0x104 << 0;	/* VLAN E ID */
	MIIBUS_WRITEREG(sc->mii_dev, 4, 25, val);
#endif

#ifdef RL_DEBUG
	rlswitch_phydump(dev);
#endif
	MIIBUS_MEDIAINIT(sc->mii_dev);
	return (0);
}