Home | History | Annotate | Line # | Download | only in mii
igphy.c revision 1.29
      1 /*	$NetBSD: igphy.c,v 1.29 2019/01/22 03:42:27 msaitoh Exp $	*/
      2 
      3 /*
      4  * The Intel copyright applies to the analog register setup, and the
      5  * SmartSpeed workaround code.
      6  */
      7 
      8 /*******************************************************************************
      9 
     10   Copyright (c) 2001-2003, Intel Corporation
     11   All rights reserved.
     12 
     13   Redistribution and use in source and binary forms, with or without
     14   modification, are permitted provided that the following conditions are met:
     15 
     16    1. Redistributions of source code must retain the above copyright notice,
     17       this list of conditions and the following disclaimer.
     18 
     19    2. Redistributions in binary form must reproduce the above copyright
     20       notice, this list of conditions and the following disclaimer in the
     21       documentation and/or other materials provided with the distribution.
     22 
     23    3. Neither the name of the Intel Corporation nor the names of its
     24       contributors may be used to endorse or promote products derived from
     25       this software without specific prior written permission.
     26 
     27   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
     28   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     29   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     30   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
     31   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     32   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     33   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     34   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     35   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     36   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     37   POSSIBILITY OF SUCH DAMAGE.
     38 
     39 *******************************************************************************/
     40 
     41 
     42 /*-
     43  * Copyright (c) 1998, 1999, 2000, 2003 The NetBSD Foundation, Inc.
     44  * All rights reserved.
     45  *
     46  * This code is derived from software contributed to The NetBSD Foundation
     47  * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
     48  * NASA Ames Research Center, and by Frank van der Linden.
     49  *
     50  * Redistribution and use in source and binary forms, with or without
     51  * modification, are permitted provided that the following conditions
     52  * are met:
     53  * 1. Redistributions of source code must retain the above copyright
     54  *    notice, this list of conditions and the following disclaimer.
     55  * 2. Redistributions in binary form must reproduce the above copyright
     56  *    notice, this list of conditions and the following disclaimer in the
     57  *    documentation and/or other materials provided with the distribution.
     58  *
     59  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     60  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     61  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     62  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     63  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     64  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     65  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     66  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     67  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     68  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     69  * POSSIBILITY OF SUCH DAMAGE.
     70  */
     71 
     72 #include <sys/cdefs.h>
     73 __KERNEL_RCSID(0, "$NetBSD: igphy.c,v 1.29 2019/01/22 03:42:27 msaitoh Exp $");
     74 
     75 #ifdef _KERNEL_OPT
     76 #include "opt_mii.h"
     77 #endif
     78 
     79 #include <sys/param.h>
     80 #include <sys/systm.h>
     81 #include <sys/kernel.h>
     82 #include <sys/device.h>
     83 #include <sys/socket.h>
     84 #include <sys/errno.h>
     85 
     86 #include <net/if.h>
     87 #include <net/if_media.h>
     88 
     89 #include <dev/mii/mii.h>
     90 #include <dev/mii/miivar.h>
     91 #include <dev/mii/miidevs.h>
     92 #include <dev/mii/igphyreg.h>
     93 #include <dev/mii/igphyvar.h>
     94 #include <dev/pci/if_wmvar.h>
     95 
     96 static void igphy_reset(struct mii_softc *);
     97 static void igphy_load_dspcode(struct mii_softc *);
     98 static void igphy_load_dspcode_igp3(struct mii_softc *);
     99 static void igphy_smartspeed_workaround(struct mii_softc *sc);
    100 
    101 static int	igphymatch(device_t, cfdata_t, void *);
    102 static void	igphyattach(device_t, device_t, void *);
    103 
    104 CFATTACH_DECL_NEW(igphy, sizeof(struct igphy_softc),
    105     igphymatch, igphyattach, mii_phy_detach, mii_phy_activate);
    106 
    107 static int	igphy_service(struct mii_softc *, struct mii_data *, int);
    108 static void	igphy_status(struct mii_softc *);
    109 
    110 static const struct mii_phy_funcs igphy_funcs = {
    111 	igphy_service, igphy_status, igphy_reset,
    112 };
    113 
    114 static const struct mii_phydesc igphys[] = {
    115 	{ MII_OUI_yyINTEL,		MII_MODEL_yyINTEL_IGP01E1000,
    116 	  MII_STR_yyINTEL_IGP01E1000 },
    117 
    118 	{ MII_OUI_yyINTEL,		MII_MODEL_yyINTEL_I82566,
    119 	  MII_STR_yyINTEL_I82566 },
    120 
    121 	{0,				0,
    122 	 NULL },
    123 };
    124 
    125 static int
    126 igphymatch(device_t parent, cfdata_t match, void *aux)
    127 {
    128 	struct mii_attach_args *ma = aux;
    129 
    130 	if (mii_phy_match(ma, igphys) != NULL)
    131 		return 10;
    132 
    133 	return 0;
    134 }
    135 
    136 static void
    137 igphyattach(device_t parent, device_t self, void *aux)
    138 {
    139 	struct mii_softc *sc = device_private(self);
    140 	struct mii_attach_args *ma = aux;
    141 	struct mii_data *mii = ma->mii_data;
    142 	const struct mii_phydesc *mpd;
    143 	struct igphy_softc *igsc = (struct igphy_softc *) sc;
    144 	prop_dictionary_t dict;
    145 
    146 	mpd = mii_phy_match(ma, igphys);
    147 	aprint_naive(": Media interface\n");
    148 	aprint_normal(": %s, rev. %d\n", mpd->mpd_name, MII_REV(ma->mii_id2));
    149 
    150 	dict = device_properties(parent);
    151 	if (!prop_dictionary_get_uint32(dict, "mactype", &igsc->sc_mactype))
    152 		aprint_error("WARNING! Failed to get mactype\n");
    153 	if (!prop_dictionary_get_uint32(dict, "macflags", &igsc->sc_macflags))
    154 		aprint_error("WARNING! Failed to get macflags\n");
    155 
    156 	sc->mii_dev = self;
    157 	sc->mii_inst = mii->mii_instance;
    158 	sc->mii_phy = ma->mii_phyno;
    159 	sc->mii_mpd_oui = MII_OUI(ma->mii_id1, ma->mii_id2);
    160 	sc->mii_mpd_model = MII_MODEL(ma->mii_id2);
    161 	sc->mii_mpd_rev = MII_REV(ma->mii_id2);
    162 	sc->mii_funcs = &igphy_funcs;
    163 	sc->mii_pdata = mii;
    164 	sc->mii_flags = ma->mii_flags;
    165 	sc->mii_anegticks = MII_ANEGTICKS_GIGE;
    166 
    167 	PHY_RESET(sc);
    168 
    169 	PHY_READ(sc, MII_BMSR, &sc->mii_capabilities);
    170 	sc->mii_capabilities &= ma->mii_capmask;
    171 	if (sc->mii_capabilities & BMSR_EXTSTAT)
    172 		PHY_READ(sc, MII_EXTSR, &sc->mii_extcapabilities);
    173 	aprint_normal_dev(self, "");
    174 	if ((sc->mii_capabilities & BMSR_MEDIAMASK) == 0 &&
    175 	    (sc->mii_extcapabilities & EXTSR_MEDIAMASK) == 0)
    176 		aprint_error("no media present");
    177 	else
    178 		mii_phy_add_media(sc);
    179 	aprint_normal("\n");
    180 }
    181 
    182 typedef struct {
    183 	int reg;
    184 	uint16_t val;
    185 } dspcode;
    186 
    187 static const dspcode igp1code[] = {
    188 	{ 0x1f95, 0x0001 },
    189 	{ 0x1f71, 0xbd21 },
    190 	{ 0x1f79, 0x0018 },
    191 	{ 0x1f30, 0x1600 },
    192 	{ 0x1f31, 0x0014 },
    193 	{ 0x1f32, 0x161c },
    194 	{ 0x1f94, 0x0003 },
    195 	{ 0x1f96, 0x003f },
    196 	{ 0x2010, 0x0008 },
    197 	{ 0, 0 },
    198 };
    199 
    200 static const dspcode igp1code_r2[] = {
    201 	{ 0x1f73, 0x0099 },
    202 	{ 0, 0 },
    203 };
    204 
    205 static const dspcode igp3code[] = {
    206 	{ 0x2f5b, 0x9018},
    207 	{ 0x2f52, 0x0000},
    208 	{ 0x2fb1, 0x8b24},
    209 	{ 0x2fb2, 0xf8f0},
    210 	{ 0x2010, 0x10b0},
    211 	{ 0x2011, 0x0000},
    212 	{ 0x20dd, 0x249a},
    213 	{ 0x20de, 0x00d3},
    214 	{ 0x28b4, 0x04ce},
    215 	{ 0x2f70, 0x29e4},
    216 	{ 0x0000, 0x0140},
    217 	{ 0x1f30, 0x1606},
    218 	{ 0x1f31, 0xb814},
    219 	{ 0x1f35, 0x002a},
    220 	{ 0x1f3e, 0x0067},
    221 	{ 0x1f54, 0x0065},
    222 	{ 0x1f55, 0x002a},
    223 	{ 0x1f56, 0x002a},
    224 	{ 0x1f72, 0x3fb0},
    225 	{ 0x1f76, 0xc0ff},
    226 	{ 0x1f77, 0x1dec},
    227 	{ 0x1f78, 0xf9ef},
    228 	{ 0x1f79, 0x0210},
    229 	{ 0x1895, 0x0003},
    230 	{ 0x1796, 0x0008},
    231 	{ 0x1798, 0xd008},
    232 	{ 0x1898, 0xd918},
    233 	{ 0x187a, 0x0800},
    234 	{ 0x0019, 0x008d},
    235 	{ 0x001b, 0x2080},
    236 	{ 0x0014, 0x0045},
    237 	{ 0x0000, 0x1340},
    238 	{ 0, 0 },
    239 };
    240 
    241 /* DSP patch for igp1 and igp2 */
    242 static void
    243 igphy_load_dspcode(struct mii_softc *sc)
    244 {
    245 	struct igphy_softc *igsc = (struct igphy_softc *) sc;
    246 	const dspcode *code;
    247 	uint16_t reg;
    248 	int i;
    249 
    250 	/* This workaround is only for 82541 and 82547 */
    251 	switch (igsc->sc_mactype) {
    252 	case WM_T_82541:
    253 	case WM_T_82547:
    254 		code = igp1code;
    255 		break;
    256 	case WM_T_82541_2:
    257 	case WM_T_82547_2:
    258 		code = igp1code_r2;
    259 		break;
    260 	default:
    261 		return;	/* byebye */
    262 	}
    263 
    264 	/* Delay after phy reset to enable NVM configuration to load */
    265 	delay(20000);
    266 
    267 	/*
    268 	 * Save off the current value of register 0x2F5B to be restored at
    269 	 * the end of this routine.
    270 	 */
    271 	IGPHY_READ(sc, 0x2f5b, &reg);
    272 
    273 	/* Disabled the PHY transmitter */
    274 	IGPHY_WRITE(sc, 0x2f5b, 0x0003);
    275 
    276 	delay(20000);
    277 
    278 	PHY_WRITE(sc, MII_IGPHY_PAGE_SELECT, 0x0000);
    279 	PHY_WRITE(sc, 0x0000, 0x0140);
    280 
    281 	delay(5000);
    282 
    283 	for (i = 0; !((code[i].reg == 0) && (code[i].val == 0)); i++)
    284 		IGPHY_WRITE(sc, code[i].reg, code[i].val);
    285 
    286 	PHY_WRITE(sc, MII_IGPHY_PAGE_SELECT, 0x0000);
    287 	PHY_WRITE(sc, 0x0000, 0x3300);
    288 
    289 	delay(20000);
    290 
    291 	/* Now enable the transmitter */
    292 	IGPHY_WRITE(sc, 0x2f5b, reg);
    293 }
    294 
    295 static void
    296 igphy_load_dspcode_igp3(struct mii_softc *sc)
    297 {
    298 	const dspcode *code = igp3code;
    299 	int i;
    300 
    301 	for (i = 0; !((code[i].reg == 0) && (code[i].val == 0)); i++)
    302 		IGPHY_WRITE(sc, code[i].reg, code[i].val);
    303 }
    304 
    305 static void
    306 igphy_reset(struct mii_softc *sc)
    307 {
    308 	struct igphy_softc *igsc = (struct igphy_softc *) sc;
    309 	uint16_t fused, fine, coarse;
    310 
    311 	mii_phy_reset(sc);
    312 	delay(150);
    313 
    314 	switch (igsc->sc_mactype) {
    315 	case WM_T_82541:
    316 	case WM_T_82547:
    317 	case WM_T_82541_2:
    318 	case WM_T_82547_2:
    319 		igphy_load_dspcode(sc);
    320 		break;
    321 	case WM_T_ICH8:
    322 	case WM_T_ICH9:
    323 		if ((igsc->sc_macflags & WM_F_EEPROM_INVALID) != 0)
    324 			igphy_load_dspcode_igp3(sc);
    325 		break;
    326 	default:	/* Not for ICH10, PCH and 8257[12] */
    327 		break;
    328 	}
    329 
    330 	if (igsc->sc_mactype == WM_T_82547) {
    331 		IGPHY_READ(sc, MII_IGPHY_ANALOG_SPARE_FUSE_STATUS, &fused);
    332 		if ((fused & ANALOG_SPARE_FUSE_ENABLED) == 0) {
    333 			IGPHY_READ(sc, MII_IGPHY_ANALOG_FUSE_STATUS, &fused);
    334 
    335 			fine = fused & ANALOG_FUSE_FINE_MASK;
    336 			coarse = fused & ANALOG_FUSE_COARSE_MASK;
    337 
    338 			if (coarse > ANALOG_FUSE_COARSE_THRESH) {
    339 				coarse -= ANALOG_FUSE_COARSE_10;
    340 				fine -= ANALOG_FUSE_FINE_1;
    341 			} else if (coarse == ANALOG_FUSE_COARSE_THRESH)
    342 				fine -= ANALOG_FUSE_FINE_10;
    343 
    344 			fused = (fused & ANALOG_FUSE_POLY_MASK) |
    345 			    (fine & ANALOG_FUSE_FINE_MASK) |
    346 			    (coarse & ANALOG_FUSE_COARSE_MASK);
    347 
    348 			IGPHY_WRITE(sc, MII_IGPHY_ANALOG_FUSE_CONTROL, fused);
    349 			IGPHY_WRITE(sc, MII_IGPHY_ANALOG_FUSE_BYPASS,
    350 			    ANALOG_FUSE_ENABLE_SW_CONTROL);
    351 		}
    352 	}
    353 	PHY_WRITE(sc, MII_IGPHY_PAGE_SELECT, 0x0000);
    354 }
    355 
    356 
    357 static int
    358 igphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
    359 {
    360 	struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
    361 	uint16_t reg;
    362 
    363 	switch (cmd) {
    364 	case MII_POLLSTAT:
    365 		/*
    366 		 * If we're not polling our PHY instance, just return.
    367 		 */
    368 		if (IFM_INST(ife->ifm_media) != sc->mii_inst)
    369 			return (0);
    370 		break;
    371 
    372 	case MII_MEDIACHG:
    373 		/*
    374 		 * If the media indicates a different PHY instance,
    375 		 * isolate ourselves.
    376 		 */
    377 		if (IFM_INST(ife->ifm_media) != sc->mii_inst) {
    378 			PHY_READ(sc, MII_BMCR, &reg);
    379 			PHY_WRITE(sc, MII_BMCR, reg | BMCR_ISO);
    380 			return (0);
    381 		}
    382 
    383 		/*
    384 		 * If the interface is not up, don't do anything.
    385 		 */
    386 		if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
    387 			break;
    388 
    389 		PHY_READ(sc, MII_IGPHY_PORT_CTRL, &reg);
    390 		if (IFM_SUBTYPE(ife->ifm_media) == IFM_AUTO) {
    391 			reg |= PSCR_AUTO_MDIX;
    392 			reg &= ~PSCR_FORCE_MDI_MDIX;
    393 			PHY_WRITE(sc, MII_IGPHY_PORT_CTRL, reg);
    394 		} else {
    395 			reg &= ~(PSCR_AUTO_MDIX | PSCR_FORCE_MDI_MDIX);
    396 			PHY_WRITE(sc, MII_IGPHY_PORT_CTRL, reg);
    397 		}
    398 
    399 		mii_phy_setmedia(sc);
    400 		break;
    401 
    402 	case MII_TICK:
    403 		/*
    404 		 * If we're not currently selected, just return.
    405 		 */
    406 		if (IFM_INST(ife->ifm_media) != sc->mii_inst)
    407 			return (0);
    408 
    409 		igphy_smartspeed_workaround(sc);
    410 
    411 		if (mii_phy_tick(sc) == EJUSTRETURN)
    412 			return (0);
    413 		break;
    414 
    415 	case MII_DOWN:
    416 		mii_phy_down(sc);
    417 		return (0);
    418 	}
    419 
    420 	/* Update the media status. */
    421 	mii_phy_status(sc);
    422 
    423 	/* Callback if something changed. */
    424 	mii_phy_update(sc, cmd);
    425 	return (0);
    426 }
    427 
    428 
    429 static void
    430 igphy_status(struct mii_softc *sc)
    431 {
    432 	struct mii_data *mii = sc->mii_pdata;
    433 	struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
    434 	uint16_t bmcr, pssr, gtsr, bmsr;
    435 
    436 	mii->mii_media_status = IFM_AVALID;
    437 	mii->mii_media_active = IFM_ETHER;
    438 
    439 	PHY_READ(sc, MII_IGPHY_PORT_STATUS, &pssr);
    440 
    441 	if (pssr & PSSR_LINK_UP)
    442 		mii->mii_media_status |= IFM_ACTIVE;
    443 
    444 	PHY_READ(sc, MII_BMCR, &bmcr);
    445 	if (bmcr & BMCR_ISO) {
    446 		mii->mii_media_active |= IFM_NONE;
    447 		mii->mii_media_status = 0;
    448 		return;
    449 	}
    450 
    451 	if (bmcr & BMCR_LOOP)
    452 		mii->mii_media_active |= IFM_LOOP;
    453 
    454 	PHY_READ(sc, MII_BMSR, &bmsr);
    455 	PHY_READ(sc, MII_BMSR, &bmsr);
    456 
    457 	/*
    458 	 * XXX can't check if the info is valid, no
    459 	 * 'negotiation done' bit?
    460 	 */
    461 	if (bmcr & BMCR_AUTOEN) {
    462 		if ((bmsr & BMSR_ACOMP) == 0) {
    463 			mii->mii_media_active |= IFM_NONE;
    464 			return;
    465 		}
    466 		switch (pssr & PSSR_SPEED_MASK) {
    467 		case PSSR_SPEED_1000MBPS:
    468 			mii->mii_media_active |= IFM_1000_T;
    469 			PHY_READ(sc, MII_100T2SR, &gtsr);
    470 			if (gtsr & GTSR_MS_RES)
    471 				mii->mii_media_active |= IFM_ETH_MASTER;
    472 			break;
    473 
    474 		case PSSR_SPEED_100MBPS:
    475 			mii->mii_media_active |= IFM_100_TX;
    476 			break;
    477 
    478 		case PSSR_SPEED_10MBPS:
    479 			mii->mii_media_active |= IFM_10_T;
    480 			break;
    481 
    482 		default:
    483 			mii->mii_media_active |= IFM_NONE;
    484 			mii->mii_media_status = 0;
    485 			return;
    486 		}
    487 
    488 		if (pssr & PSSR_FULL_DUPLEX)
    489 			mii->mii_media_active |=
    490 			    IFM_FDX | mii_phy_flowstatus(sc);
    491 		else
    492 			mii->mii_media_active |= IFM_HDX;
    493 	} else
    494 		mii->mii_media_active = ife->ifm_media;
    495 }
    496 
    497 static void
    498 igphy_smartspeed_workaround(struct mii_softc *sc)
    499 {
    500 	struct igphy_softc *igsc = (struct igphy_softc *) sc;
    501 	uint16_t reg, gtsr, gtcr;
    502 
    503 	/* This workaround is only for 82541 and 82547 */
    504 	switch (igsc->sc_mactype) {
    505 	case WM_T_82541:
    506 	case WM_T_82541_2:
    507 	case WM_T_82547:
    508 	case WM_T_82547_2:
    509 		break;
    510 	default:
    511 		/* byebye */
    512 		return;
    513 	}
    514 
    515 	PHY_READ(sc, MII_BMCR, &reg);
    516 	if ((reg & BMCR_AUTOEN) == 0)
    517 		return;
    518 
    519 	/* XXX Assume 1000TX-FDX is advertized if doing autonegotiation. */
    520 
    521 	PHY_READ(sc, MII_BMSR, &reg);
    522 	PHY_READ(sc, MII_BMSR, &reg);
    523 	if ((reg & BMSR_LINK) == 0) {
    524 		switch (igsc->sc_smartspeed) {
    525 		case 0:
    526 			PHY_READ(sc, MII_100T2SR, &gtsr);
    527 			if (!(gtsr & GTSR_MAN_MS_FLT))
    528 				break;
    529 			PHY_READ(sc, MII_100T2SR, &gtsr);
    530 			if (gtsr & GTSR_MAN_MS_FLT) {
    531 				PHY_READ(sc, MII_100T2CR, &gtcr);
    532 				if (gtcr & GTCR_MAN_MS) {
    533 					gtcr &= ~GTCR_MAN_MS;
    534 					PHY_WRITE(sc, MII_100T2CR, gtcr);
    535 				}
    536 				mii_phy_auto(sc, 0);
    537 			}
    538 			break;
    539 		case IGPHY_TICK_DOWNSHIFT:
    540 			PHY_READ(sc, MII_100T2CR, &gtcr);
    541 			gtcr |= GTCR_MAN_MS;
    542 			PHY_WRITE(sc, MII_100T2CR, gtcr);
    543 			mii_phy_auto(sc, 0);
    544 			break;
    545 		default:
    546 			break;
    547 		}
    548 		if (igsc->sc_smartspeed++ == IGPHY_TICK_MAX)
    549 			igsc->sc_smartspeed = 0;
    550 	} else
    551 		igsc->sc_smartspeed = 0;
    552 }
    553