FreeBSD/sys/dev/mxge/if_mxge.c
/*
 * Determine the media type for a NIC.  Some XFPs will identify
 * themselves only when their link is up, so this is initiated via a
 * link up interrupt.  However, this can potentially take up to
 * several milliseconds, so it is run via the watchdog routine, rather
 * than in the interrupt handler itself.
 */
Determine the media type for a NIC.  Some XFPs will identify
themselves only when their link is up, so this is initiated via a
link up interrupt.  However, this can potentially take up to
several milliseconds, so it is run via the watchdog routine, rather
than in the interrupt handler itself.
Determine the media type for a NIC . Some XFPs will identify themselves only when their link is up so this is initiated via a link up interrupt . However this can potentially take up to several milliseconds so it is run via the watchdog routine rather than in the interrupt handler itself .
static void
mxge_media_probe(mxge_softc_t *sc)
{
	mxge_cmd_t cmd;
	char *cage_type;
	struct mxge_media_type *mxge_media_types = NULL;
	int i, err, ms, mxge_media_type_entries;
	uint32_t byte;
	sc->need_media_probe = 0;
	if (sc->connector == MXGE_XFP) {
		mxge_media_types = mxge_xfp_media_types;
		mxge_media_type_entries =
			nitems(mxge_xfp_media_types);
		byte = MXGE_XFP_COMPLIANCE_BYTE;
		cage_type = "XFP";
	} else 	if (sc->connector == MXGE_SFP) {
		mxge_media_types = mxge_sfp_media_types;
		mxge_media_type_entries =
			nitems(mxge_sfp_media_types);
		cage_type = "SFP+";
		byte = 3;
	} else {
		return;
	}
	cmd.data0 = 0;	 
	cmd.data1 = byte;
	err = mxge_send_cmd(sc, MXGEFW_CMD_I2C_READ, &cmd);
	if (err == MXGEFW_CMD_ERROR_I2C_FAILURE) {
		device_printf(sc->dev, "failed to read XFP\n");
	}
	if (err == MXGEFW_CMD_ERROR_I2C_ABSENT) {
		device_printf(sc->dev, "Type R/S with no XFP!?!?\n");
	}
	if (err != MXGEFW_CMD_OK) {
		return;
	}
	cmd.data0 = byte;
	err = mxge_send_cmd(sc, MXGEFW_CMD_I2C_BYTE, &cmd);
	for (ms = 0; (err == EBUSY) && (ms < 50); ms++) {
		DELAY(1000);
		cmd.data0 = byte;
		err = mxge_send_cmd(sc, MXGEFW_CMD_I2C_BYTE, &cmd);
	}
	if (err != MXGEFW_CMD_OK) {
		device_printf(sc->dev, "failed to read %s (%d, %dms)\n",
			      cage_type, err, ms);
		return;
	}
	if (cmd.data0 == mxge_media_types[0].bitmask) {
		if (mxge_verbose)
			device_printf(sc->dev, "%s:%s\n", cage_type,
				      mxge_media_types[0].name);
		if (sc->current_media != mxge_media_types[0].flag) {
			mxge_media_init(sc);
			mxge_media_set(sc, mxge_media_types[0].flag);
		}
		return;
	}
	for (i = 1; i < mxge_media_type_entries; i++) {
		if (cmd.data0 & mxge_media_types[i].bitmask) {
			if (mxge_verbose)
				device_printf(sc->dev, "%s:%s\n",
					      cage_type,
					      mxge_media_types[i].name);
			if (sc->current_media != mxge_media_types[i].flag) {
				mxge_media_init(sc);
				mxge_media_set(sc, mxge_media_types[i].flag);
			}
			return;
		}
	}
	if (mxge_verbose)
		device_printf(sc->dev, "%s media 0x%x unknown\n",
			      cage_type, cmd.data0);
	return;
}
static void mxge_media_probe ( mxge_softc_t * sc ) { mxge_cmd_t cmd ; char * cage_type ; struct mxge_media_type * mxge_media_types = NULL ; int i , err , ms , mxge_media_type_entries ; uint32_t byte ; sc -> need_media_probe = 0 ; if ( sc -> connector == MXGE_XFP ) { mxge_media_types = mxge_xfp_media_types ; mxge_media_type_entries = nitems ( mxge_xfp_media_types ) ; byte = MXGE_XFP_COMPLIANCE_BYTE ; cage_type = " " ; } else if ( sc -> connector == MXGE_SFP ) { mxge_media_types = mxge_sfp_media_types ; mxge_media_type_entries = nitems ( mxge_sfp_media_types ) ; cage_type = " " ; byte = 3 ; } else { return ; } cmd . data0 = 0 ; cmd . data1 = byte ; err = mxge_send_cmd ( sc , MXGEFW_CMD_I2C_READ , & cmd ) ; if ( err == MXGEFW_CMD_ERROR_I2C_FAILURE ) { device_printf ( sc -> dev , " \n " ) ; } if ( err == MXGEFW_CMD_ERROR_I2C_ABSENT ) { device_printf ( sc -> dev , " \n " ) ; } if ( err != MXGEFW_CMD_OK ) { return ; } cmd . data0 = byte ; err = mxge_send_cmd ( sc , MXGEFW_CMD_I2C_BYTE , & cmd ) ; for ( ms = 0 ; ( err == EBUSY ) && ( ms < 50 ) ; ms ++ ) { DELAY ( 1000 ) ; cmd . data0 = byte ; err = mxge_send_cmd ( sc , MXGEFW_CMD_I2C_BYTE , & cmd ) ; } if ( err != MXGEFW_CMD_OK ) { device_printf ( sc -> dev , " \n " , cage_type , err , ms ) ; return ; } if ( cmd . data0 == mxge_media_types [ 0 ] . bitmask ) { if ( mxge_verbose ) device_printf ( sc -> dev , " \n " , cage_type , mxge_media_types [ 0 ] . name ) ; if ( sc -> current_media != mxge_media_types [ 0 ] . flag ) { mxge_media_init ( sc ) ; mxge_media_set ( sc , mxge_media_types [ 0 ] . flag ) ; } return ; } for ( i = 1 ; i < mxge_media_type_entries ; i ++ ) { if ( cmd . data0 & mxge_media_types [ i ] . bitmask ) { if ( mxge_verbose ) device_printf ( sc -> dev , " \n " , cage_type , mxge_media_types [ i ] . name ) ; if ( sc -> current_media != mxge_media_types [ i ] . flag ) { mxge_media_init ( sc ) ; mxge_media_set ( sc , mxge_media_types [ i ] . flag ) ; } return ; } } if ( mxge_verbose ) device_printf ( sc -> dev , " \n " , cage_type , cmd . data0 ) ; return ; }
Determine the media type for a NIC.
Determine the media type for a NIC .
/* -R is XFP */ /* -S or -2S is SFP+ */ /* nothing to do; media type cannot change */ /*
	 * At this point we know the NIC has an XFP cage, so now we
	 * try to determine what is in the cage by using the
	 * firmware's XFP I2C commands to read the XFP 10GbE compilance
	 * register.  We read just one byte, which may take over
	 * a millisecond
	 */ /* just fetch 1 byte, not all 256 */ /* now we wait for the data to be cached */