15779Sxy150489 /* 25779Sxy150489 * CDDL HEADER START 35779Sxy150489 * 45779Sxy150489 * The contents of this file are subject to the terms of the 55779Sxy150489 * Common Development and Distribution License (the "License"). 65779Sxy150489 * You may not use this file except in compliance with the License. 75779Sxy150489 * 88275SEric Cheng * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 98275SEric Cheng * or http://www.opensolaris.org/os/licensing. 105779Sxy150489 * See the License for the specific language governing permissions 115779Sxy150489 * and limitations under the License. 125779Sxy150489 * 138275SEric Cheng * When distributing Covered Code, include this CDDL HEADER in each 148275SEric Cheng * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 155779Sxy150489 * If applicable, add the following below this CDDL HEADER, with the 165779Sxy150489 * fields enclosed by brackets "[]" replaced with your own identifying 175779Sxy150489 * information: Portions Copyright [yyyy] [name of copyright owner] 185779Sxy150489 * 195779Sxy150489 * CDDL HEADER END 205779Sxy150489 */ 215779Sxy150489 225779Sxy150489 /* 238275SEric Cheng * Copyright(c) 2007-2008 Intel Corporation. All rights reserved. 245779Sxy150489 */ 255779Sxy150489 268275SEric Cheng /* 27*9188SPaul.Guo@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 288275SEric Cheng * Use is subject to license terms. 298275SEric Cheng */ 305779Sxy150489 315779Sxy150489 #include "igb_sw.h" 325779Sxy150489 335779Sxy150489 int 345779Sxy150489 igb_m_stat(void *arg, uint_t stat, uint64_t *val) 355779Sxy150489 { 365779Sxy150489 igb_t *igb = (igb_t *)arg; 375779Sxy150489 struct e1000_hw *hw = &igb->hw; 385779Sxy150489 igb_stat_t *igb_ks; 395779Sxy150489 uint32_t low_val, high_val; 405779Sxy150489 415779Sxy150489 igb_ks = (igb_stat_t *)igb->igb_ks->ks_data; 425779Sxy150489 435779Sxy150489 mutex_enter(&igb->gen_lock); 445779Sxy150489 455779Sxy150489 if (igb->igb_state & IGB_SUSPENDED) { 465779Sxy150489 mutex_exit(&igb->gen_lock); 475779Sxy150489 return (ECANCELED); 485779Sxy150489 } 495779Sxy150489 505779Sxy150489 switch (stat) { 515779Sxy150489 case MAC_STAT_IFSPEED: 525779Sxy150489 *val = igb->link_speed * 1000000ull; 535779Sxy150489 break; 545779Sxy150489 555779Sxy150489 case MAC_STAT_MULTIRCV: 565779Sxy150489 igb_ks->mprc.value.ui64 += 575779Sxy150489 E1000_READ_REG(hw, E1000_MPRC); 585779Sxy150489 *val = igb_ks->mprc.value.ui64; 595779Sxy150489 break; 605779Sxy150489 615779Sxy150489 case MAC_STAT_BRDCSTRCV: 625779Sxy150489 igb_ks->bprc.value.ui64 += 635779Sxy150489 E1000_READ_REG(hw, E1000_BPRC); 645779Sxy150489 *val = igb_ks->bprc.value.ui64; 655779Sxy150489 break; 665779Sxy150489 675779Sxy150489 case MAC_STAT_MULTIXMT: 685779Sxy150489 igb_ks->mptc.value.ui64 += 695779Sxy150489 E1000_READ_REG(hw, E1000_MPTC); 705779Sxy150489 *val = igb_ks->mptc.value.ui64; 715779Sxy150489 break; 725779Sxy150489 735779Sxy150489 case MAC_STAT_BRDCSTXMT: 745779Sxy150489 igb_ks->bptc.value.ui64 += 755779Sxy150489 E1000_READ_REG(hw, E1000_BPTC); 765779Sxy150489 *val = igb_ks->bptc.value.ui64; 775779Sxy150489 break; 785779Sxy150489 795779Sxy150489 case MAC_STAT_NORCVBUF: 805779Sxy150489 igb_ks->rnbc.value.ui64 += 815779Sxy150489 E1000_READ_REG(hw, E1000_RNBC); 825779Sxy150489 *val = igb_ks->rnbc.value.ui64; 835779Sxy150489 break; 845779Sxy150489 855779Sxy150489 case MAC_STAT_IERRORS: 865779Sxy150489 igb_ks->rxerrc.value.ui64 += 875779Sxy150489 E1000_READ_REG(hw, E1000_RXERRC); 885779Sxy150489 igb_ks->algnerrc.value.ui64 += 895779Sxy150489 E1000_READ_REG(hw, E1000_ALGNERRC); 905779Sxy150489 igb_ks->rlec.value.ui64 += 915779Sxy150489 E1000_READ_REG(hw, E1000_RLEC); 925779Sxy150489 igb_ks->crcerrs.value.ui64 += 935779Sxy150489 E1000_READ_REG(hw, E1000_CRCERRS); 945779Sxy150489 igb_ks->cexterr.value.ui64 += 955779Sxy150489 E1000_READ_REG(hw, E1000_CEXTERR); 965779Sxy150489 *val = igb_ks->rxerrc.value.ui64 + 975779Sxy150489 igb_ks->algnerrc.value.ui64 + 985779Sxy150489 igb_ks->rlec.value.ui64 + 995779Sxy150489 igb_ks->crcerrs.value.ui64 + 1005779Sxy150489 igb_ks->cexterr.value.ui64; 1015779Sxy150489 break; 1025779Sxy150489 1035779Sxy150489 case MAC_STAT_NOXMTBUF: 1045779Sxy150489 *val = 0; 1055779Sxy150489 break; 1065779Sxy150489 1075779Sxy150489 case MAC_STAT_OERRORS: 1085779Sxy150489 igb_ks->ecol.value.ui64 += 1095779Sxy150489 E1000_READ_REG(hw, E1000_ECOL); 1105779Sxy150489 *val = igb_ks->ecol.value.ui64; 1115779Sxy150489 break; 1125779Sxy150489 1135779Sxy150489 case MAC_STAT_COLLISIONS: 1145779Sxy150489 igb_ks->colc.value.ui64 += 1155779Sxy150489 E1000_READ_REG(hw, E1000_COLC); 1165779Sxy150489 *val = igb_ks->colc.value.ui64; 1175779Sxy150489 break; 1185779Sxy150489 1195779Sxy150489 case MAC_STAT_RBYTES: 1205779Sxy150489 /* 1215779Sxy150489 * The 64-bit register will reset whenever the upper 1225779Sxy150489 * 32 bits are read. So we need to read the lower 1235779Sxy150489 * 32 bits first, then read the upper 32 bits. 1245779Sxy150489 */ 1255779Sxy150489 low_val = E1000_READ_REG(hw, E1000_TORL); 1265779Sxy150489 high_val = E1000_READ_REG(hw, E1000_TORH); 1275779Sxy150489 igb_ks->tor.value.ui64 += 1285779Sxy150489 (uint64_t)high_val << 32 | (uint64_t)low_val; 1295779Sxy150489 *val = igb_ks->tor.value.ui64; 1305779Sxy150489 break; 1315779Sxy150489 1325779Sxy150489 case MAC_STAT_IPACKETS: 1335779Sxy150489 igb_ks->tpr.value.ui64 += 1345779Sxy150489 E1000_READ_REG(hw, E1000_TPR); 1355779Sxy150489 *val = igb_ks->tpr.value.ui64; 1365779Sxy150489 break; 1375779Sxy150489 1385779Sxy150489 case MAC_STAT_OBYTES: 1395779Sxy150489 /* 1405779Sxy150489 * The 64-bit register will reset whenever the upper 1415779Sxy150489 * 32 bits are read. So we need to read the lower 1425779Sxy150489 * 32 bits first, then read the upper 32 bits. 1435779Sxy150489 */ 1445779Sxy150489 low_val = E1000_READ_REG(hw, E1000_TOTL); 1455779Sxy150489 high_val = E1000_READ_REG(hw, E1000_TOTH); 1465779Sxy150489 igb_ks->tot.value.ui64 += 1475779Sxy150489 (uint64_t)high_val << 32 | (uint64_t)low_val; 1485779Sxy150489 *val = igb_ks->tot.value.ui64; 1495779Sxy150489 break; 1505779Sxy150489 1515779Sxy150489 case MAC_STAT_OPACKETS: 1525779Sxy150489 igb_ks->tpt.value.ui64 += 1535779Sxy150489 E1000_READ_REG(hw, E1000_TPT); 1545779Sxy150489 *val = igb_ks->tpt.value.ui64; 1555779Sxy150489 break; 1565779Sxy150489 1575779Sxy150489 /* RFC 1643 stats */ 1585779Sxy150489 case ETHER_STAT_ALIGN_ERRORS: 1595779Sxy150489 igb_ks->algnerrc.value.ui64 += 1605779Sxy150489 E1000_READ_REG(hw, E1000_ALGNERRC); 1615779Sxy150489 *val = igb_ks->algnerrc.value.ui64; 1625779Sxy150489 break; 1635779Sxy150489 1645779Sxy150489 case ETHER_STAT_FCS_ERRORS: 1655779Sxy150489 igb_ks->crcerrs.value.ui64 += 1665779Sxy150489 E1000_READ_REG(hw, E1000_CRCERRS); 1675779Sxy150489 *val = igb_ks->crcerrs.value.ui64; 1685779Sxy150489 break; 1695779Sxy150489 1705779Sxy150489 case ETHER_STAT_FIRST_COLLISIONS: 1715779Sxy150489 igb_ks->scc.value.ui64 += 1725779Sxy150489 E1000_READ_REG(hw, E1000_SCC); 1735779Sxy150489 *val = igb_ks->scc.value.ui64; 1745779Sxy150489 break; 1755779Sxy150489 1765779Sxy150489 case ETHER_STAT_MULTI_COLLISIONS: 1775779Sxy150489 igb_ks->mcc.value.ui64 += 1785779Sxy150489 E1000_READ_REG(hw, E1000_MCC); 1795779Sxy150489 *val = igb_ks->mcc.value.ui64; 1805779Sxy150489 break; 1815779Sxy150489 1825779Sxy150489 case ETHER_STAT_SQE_ERRORS: 1835779Sxy150489 igb_ks->sec.value.ui64 += 1845779Sxy150489 E1000_READ_REG(hw, E1000_SEC); 1855779Sxy150489 *val = igb_ks->sec.value.ui64; 1865779Sxy150489 break; 1875779Sxy150489 1885779Sxy150489 case ETHER_STAT_DEFER_XMTS: 1895779Sxy150489 igb_ks->dc.value.ui64 += 1905779Sxy150489 E1000_READ_REG(hw, E1000_DC); 1915779Sxy150489 *val = igb_ks->dc.value.ui64; 1925779Sxy150489 break; 1935779Sxy150489 1945779Sxy150489 case ETHER_STAT_TX_LATE_COLLISIONS: 1955779Sxy150489 igb_ks->latecol.value.ui64 += 1965779Sxy150489 E1000_READ_REG(hw, E1000_LATECOL); 1975779Sxy150489 *val = igb_ks->latecol.value.ui64; 1985779Sxy150489 break; 1995779Sxy150489 2005779Sxy150489 case ETHER_STAT_EX_COLLISIONS: 2015779Sxy150489 igb_ks->ecol.value.ui64 += 2025779Sxy150489 E1000_READ_REG(hw, E1000_ECOL); 2035779Sxy150489 *val = igb_ks->ecol.value.ui64; 2045779Sxy150489 break; 2055779Sxy150489 2065779Sxy150489 case ETHER_STAT_MACXMT_ERRORS: 2075779Sxy150489 igb_ks->ecol.value.ui64 += 2085779Sxy150489 E1000_READ_REG(hw, E1000_ECOL); 2095779Sxy150489 *val = igb_ks->ecol.value.ui64; 2105779Sxy150489 break; 2115779Sxy150489 2125779Sxy150489 case ETHER_STAT_CARRIER_ERRORS: 2135779Sxy150489 igb_ks->cexterr.value.ui64 += 2145779Sxy150489 E1000_READ_REG(hw, E1000_CEXTERR); 2155779Sxy150489 *val = igb_ks->cexterr.value.ui64; 2165779Sxy150489 break; 2175779Sxy150489 2185779Sxy150489 case ETHER_STAT_TOOLONG_ERRORS: 2195779Sxy150489 igb_ks->roc.value.ui64 += 2205779Sxy150489 E1000_READ_REG(hw, E1000_ROC); 2215779Sxy150489 *val = igb_ks->roc.value.ui64; 2225779Sxy150489 break; 2235779Sxy150489 2245779Sxy150489 case ETHER_STAT_MACRCV_ERRORS: 2255779Sxy150489 igb_ks->rxerrc.value.ui64 += 2265779Sxy150489 E1000_READ_REG(hw, E1000_RXERRC); 2275779Sxy150489 *val = igb_ks->rxerrc.value.ui64; 2285779Sxy150489 break; 2295779Sxy150489 2305779Sxy150489 /* MII/GMII stats */ 2315779Sxy150489 case ETHER_STAT_XCVR_ADDR: 2325779Sxy150489 /* The Internal PHY's MDI address for each MAC is 1 */ 2335779Sxy150489 *val = 1; 2345779Sxy150489 break; 2355779Sxy150489 2365779Sxy150489 case ETHER_STAT_XCVR_ID: 2375779Sxy150489 *val = hw->phy.id | hw->phy.revision; 2385779Sxy150489 break; 2395779Sxy150489 2405779Sxy150489 case ETHER_STAT_XCVR_INUSE: 2415779Sxy150489 switch (igb->link_speed) { 2425779Sxy150489 case SPEED_1000: 2435779Sxy150489 *val = 2445779Sxy150489 (hw->phy.media_type == e1000_media_type_copper) ? 2455779Sxy150489 XCVR_1000T : XCVR_1000X; 2465779Sxy150489 break; 2475779Sxy150489 case SPEED_100: 2485779Sxy150489 *val = 2495779Sxy150489 (hw->phy.media_type == e1000_media_type_copper) ? 2505779Sxy150489 (igb->param_100t4_cap == 1) ? 2515779Sxy150489 XCVR_100T4 : XCVR_100T2 : XCVR_100X; 2525779Sxy150489 break; 2535779Sxy150489 case SPEED_10: 2545779Sxy150489 *val = XCVR_10; 2555779Sxy150489 break; 2565779Sxy150489 default: 2575779Sxy150489 *val = XCVR_NONE; 2585779Sxy150489 break; 2595779Sxy150489 } 2605779Sxy150489 break; 2615779Sxy150489 2625779Sxy150489 case ETHER_STAT_CAP_1000FDX: 2635779Sxy150489 *val = igb->param_1000fdx_cap; 2645779Sxy150489 break; 2655779Sxy150489 2665779Sxy150489 case ETHER_STAT_CAP_1000HDX: 2675779Sxy150489 *val = igb->param_1000hdx_cap; 2685779Sxy150489 break; 2695779Sxy150489 2705779Sxy150489 case ETHER_STAT_CAP_100FDX: 2715779Sxy150489 *val = igb->param_100fdx_cap; 2725779Sxy150489 break; 2735779Sxy150489 2745779Sxy150489 case ETHER_STAT_CAP_100HDX: 2755779Sxy150489 *val = igb->param_100hdx_cap; 2765779Sxy150489 break; 2775779Sxy150489 2785779Sxy150489 case ETHER_STAT_CAP_10FDX: 2795779Sxy150489 *val = igb->param_10fdx_cap; 2805779Sxy150489 break; 2815779Sxy150489 2825779Sxy150489 case ETHER_STAT_CAP_10HDX: 2835779Sxy150489 *val = igb->param_10hdx_cap; 2845779Sxy150489 break; 2855779Sxy150489 2865779Sxy150489 case ETHER_STAT_CAP_ASMPAUSE: 2875779Sxy150489 *val = igb->param_asym_pause_cap; 2885779Sxy150489 break; 2895779Sxy150489 2905779Sxy150489 case ETHER_STAT_CAP_PAUSE: 2915779Sxy150489 *val = igb->param_pause_cap; 2925779Sxy150489 break; 2935779Sxy150489 2945779Sxy150489 case ETHER_STAT_CAP_AUTONEG: 2955779Sxy150489 *val = igb->param_autoneg_cap; 2965779Sxy150489 break; 2975779Sxy150489 2985779Sxy150489 case ETHER_STAT_ADV_CAP_1000FDX: 2995779Sxy150489 *val = igb->param_adv_1000fdx_cap; 3005779Sxy150489 break; 3015779Sxy150489 3025779Sxy150489 case ETHER_STAT_ADV_CAP_1000HDX: 3035779Sxy150489 *val = igb->param_adv_1000hdx_cap; 3045779Sxy150489 break; 3055779Sxy150489 3065779Sxy150489 case ETHER_STAT_ADV_CAP_100FDX: 3075779Sxy150489 *val = igb->param_adv_100fdx_cap; 3085779Sxy150489 break; 3095779Sxy150489 3105779Sxy150489 case ETHER_STAT_ADV_CAP_100HDX: 3115779Sxy150489 *val = igb->param_adv_100hdx_cap; 3125779Sxy150489 break; 3135779Sxy150489 3145779Sxy150489 case ETHER_STAT_ADV_CAP_10FDX: 3155779Sxy150489 *val = igb->param_adv_10fdx_cap; 3165779Sxy150489 break; 3175779Sxy150489 3185779Sxy150489 case ETHER_STAT_ADV_CAP_10HDX: 3195779Sxy150489 *val = igb->param_adv_10hdx_cap; 3205779Sxy150489 break; 3215779Sxy150489 3225779Sxy150489 case ETHER_STAT_ADV_CAP_ASMPAUSE: 3235779Sxy150489 *val = igb->param_adv_asym_pause_cap; 3245779Sxy150489 break; 3255779Sxy150489 3265779Sxy150489 case ETHER_STAT_ADV_CAP_PAUSE: 3275779Sxy150489 *val = igb->param_adv_pause_cap; 3285779Sxy150489 break; 3295779Sxy150489 3305779Sxy150489 case ETHER_STAT_ADV_CAP_AUTONEG: 3315779Sxy150489 *val = hw->mac.autoneg; 3325779Sxy150489 break; 3335779Sxy150489 3345779Sxy150489 case ETHER_STAT_LP_CAP_1000FDX: 3355779Sxy150489 *val = igb->param_lp_1000fdx_cap; 3365779Sxy150489 break; 3375779Sxy150489 3385779Sxy150489 case ETHER_STAT_LP_CAP_1000HDX: 3395779Sxy150489 *val = igb->param_lp_1000hdx_cap; 3405779Sxy150489 break; 3415779Sxy150489 3425779Sxy150489 case ETHER_STAT_LP_CAP_100FDX: 3435779Sxy150489 *val = igb->param_lp_100fdx_cap; 3445779Sxy150489 break; 3455779Sxy150489 3465779Sxy150489 case ETHER_STAT_LP_CAP_100HDX: 3475779Sxy150489 *val = igb->param_lp_100hdx_cap; 3485779Sxy150489 break; 3495779Sxy150489 3505779Sxy150489 case ETHER_STAT_LP_CAP_10FDX: 3515779Sxy150489 *val = igb->param_lp_10fdx_cap; 3525779Sxy150489 break; 3535779Sxy150489 3545779Sxy150489 case ETHER_STAT_LP_CAP_10HDX: 3555779Sxy150489 *val = igb->param_lp_10hdx_cap; 3565779Sxy150489 break; 3575779Sxy150489 3585779Sxy150489 case ETHER_STAT_LP_CAP_ASMPAUSE: 3595779Sxy150489 *val = igb->param_lp_asym_pause_cap; 3605779Sxy150489 break; 3615779Sxy150489 3625779Sxy150489 case ETHER_STAT_LP_CAP_PAUSE: 3635779Sxy150489 *val = igb->param_lp_pause_cap; 3645779Sxy150489 break; 3655779Sxy150489 3665779Sxy150489 case ETHER_STAT_LP_CAP_AUTONEG: 3675779Sxy150489 *val = igb->param_lp_autoneg_cap; 3685779Sxy150489 break; 3695779Sxy150489 3705779Sxy150489 case ETHER_STAT_LINK_ASMPAUSE: 3715779Sxy150489 *val = igb->param_asym_pause_cap; 3725779Sxy150489 break; 3735779Sxy150489 3745779Sxy150489 case ETHER_STAT_LINK_PAUSE: 3755779Sxy150489 *val = igb->param_pause_cap; 3765779Sxy150489 break; 3775779Sxy150489 3785779Sxy150489 case ETHER_STAT_LINK_AUTONEG: 3795779Sxy150489 *val = hw->mac.autoneg; 3805779Sxy150489 break; 3815779Sxy150489 3825779Sxy150489 case ETHER_STAT_LINK_DUPLEX: 3835779Sxy150489 *val = (igb->link_duplex == FULL_DUPLEX) ? 3845779Sxy150489 LINK_DUPLEX_FULL : LINK_DUPLEX_HALF; 3855779Sxy150489 break; 3865779Sxy150489 3875779Sxy150489 case ETHER_STAT_TOOSHORT_ERRORS: 3885779Sxy150489 igb_ks->ruc.value.ui64 += 3895779Sxy150489 E1000_READ_REG(hw, E1000_RUC); 3905779Sxy150489 *val = igb_ks->ruc.value.ui64; 3915779Sxy150489 break; 3925779Sxy150489 3935779Sxy150489 case ETHER_STAT_CAP_REMFAULT: 3945779Sxy150489 *val = igb->param_rem_fault; 3955779Sxy150489 break; 3965779Sxy150489 3975779Sxy150489 case ETHER_STAT_ADV_REMFAULT: 3985779Sxy150489 *val = igb->param_adv_rem_fault; 3995779Sxy150489 break; 4005779Sxy150489 4015779Sxy150489 case ETHER_STAT_LP_REMFAULT: 4025779Sxy150489 *val = igb->param_lp_rem_fault; 4035779Sxy150489 break; 4045779Sxy150489 4055779Sxy150489 case ETHER_STAT_JABBER_ERRORS: 4065779Sxy150489 igb_ks->rjc.value.ui64 += 4075779Sxy150489 E1000_READ_REG(hw, E1000_RJC); 4085779Sxy150489 *val = igb_ks->rjc.value.ui64; 4095779Sxy150489 break; 4105779Sxy150489 4115779Sxy150489 case ETHER_STAT_CAP_100T4: 4125779Sxy150489 *val = igb->param_100t4_cap; 4135779Sxy150489 break; 4145779Sxy150489 4155779Sxy150489 case ETHER_STAT_ADV_CAP_100T4: 4165779Sxy150489 *val = igb->param_adv_100t4_cap; 4175779Sxy150489 break; 4185779Sxy150489 4195779Sxy150489 case ETHER_STAT_LP_CAP_100T4: 4205779Sxy150489 *val = igb->param_lp_100t4_cap; 4215779Sxy150489 break; 4225779Sxy150489 4235779Sxy150489 default: 4245779Sxy150489 mutex_exit(&igb->gen_lock); 4255779Sxy150489 return (ENOTSUP); 4265779Sxy150489 } 4275779Sxy150489 4285779Sxy150489 mutex_exit(&igb->gen_lock); 4295779Sxy150489 4306624Sgl147354 if (igb_check_acc_handle(igb->osdep.reg_handle) != DDI_FM_OK) 4316624Sgl147354 ddi_fm_service_impact(igb->dip, DDI_SERVICE_UNAFFECTED); 4326624Sgl147354 4335779Sxy150489 return (0); 4345779Sxy150489 } 4355779Sxy150489 4365779Sxy150489 /* 4375779Sxy150489 * Bring the device out of the reset/quiesced state that it 4385779Sxy150489 * was in when the interface was registered. 4395779Sxy150489 */ 4405779Sxy150489 int 4415779Sxy150489 igb_m_start(void *arg) 4425779Sxy150489 { 4435779Sxy150489 igb_t *igb = (igb_t *)arg; 4445779Sxy150489 4455779Sxy150489 mutex_enter(&igb->gen_lock); 4465779Sxy150489 4475779Sxy150489 if (igb->igb_state & IGB_SUSPENDED) { 4485779Sxy150489 mutex_exit(&igb->gen_lock); 4495779Sxy150489 return (ECANCELED); 4505779Sxy150489 } 4515779Sxy150489 4525779Sxy150489 if (igb_start(igb) != IGB_SUCCESS) { 4535779Sxy150489 mutex_exit(&igb->gen_lock); 4545779Sxy150489 return (EIO); 4555779Sxy150489 } 4565779Sxy150489 4575779Sxy150489 igb->igb_state |= IGB_STARTED; 4585779Sxy150489 4595779Sxy150489 mutex_exit(&igb->gen_lock); 4605779Sxy150489 4615779Sxy150489 /* 4625779Sxy150489 * Enable and start the watchdog timer 4635779Sxy150489 */ 4645779Sxy150489 igb_enable_watchdog_timer(igb); 4655779Sxy150489 4665779Sxy150489 return (0); 4675779Sxy150489 } 4685779Sxy150489 4695779Sxy150489 /* 4705779Sxy150489 * Stop the device and put it in a reset/quiesced state such 4715779Sxy150489 * that the interface can be unregistered. 4725779Sxy150489 */ 4735779Sxy150489 void 4745779Sxy150489 igb_m_stop(void *arg) 4755779Sxy150489 { 4765779Sxy150489 igb_t *igb = (igb_t *)arg; 4775779Sxy150489 4785779Sxy150489 mutex_enter(&igb->gen_lock); 4795779Sxy150489 4805779Sxy150489 if (igb->igb_state & IGB_SUSPENDED) { 4815779Sxy150489 mutex_exit(&igb->gen_lock); 4825779Sxy150489 return; 4835779Sxy150489 } 4845779Sxy150489 4855779Sxy150489 igb->igb_state &= ~IGB_STARTED; 4865779Sxy150489 4875779Sxy150489 igb_stop(igb); 4885779Sxy150489 4895779Sxy150489 mutex_exit(&igb->gen_lock); 4905779Sxy150489 4915779Sxy150489 /* 4925779Sxy150489 * Disable and stop the watchdog timer 4935779Sxy150489 */ 4945779Sxy150489 igb_disable_watchdog_timer(igb); 4955779Sxy150489 } 4965779Sxy150489 4975779Sxy150489 /* 4985779Sxy150489 * Set the promiscuity of the device. 4995779Sxy150489 */ 5005779Sxy150489 int 5015779Sxy150489 igb_m_promisc(void *arg, boolean_t on) 5025779Sxy150489 { 5035779Sxy150489 igb_t *igb = (igb_t *)arg; 5045779Sxy150489 uint32_t reg_val; 5055779Sxy150489 5065779Sxy150489 mutex_enter(&igb->gen_lock); 5075779Sxy150489 5085779Sxy150489 if (igb->igb_state & IGB_SUSPENDED) { 5095779Sxy150489 mutex_exit(&igb->gen_lock); 5105779Sxy150489 return (ECANCELED); 5115779Sxy150489 } 5125779Sxy150489 5135779Sxy150489 reg_val = E1000_READ_REG(&igb->hw, E1000_RCTL); 5145779Sxy150489 5155779Sxy150489 if (on) 5165779Sxy150489 reg_val |= (E1000_RCTL_UPE | E1000_RCTL_MPE); 5175779Sxy150489 else 5185779Sxy150489 reg_val &= (~(E1000_RCTL_UPE | E1000_RCTL_MPE)); 5195779Sxy150489 5205779Sxy150489 E1000_WRITE_REG(&igb->hw, E1000_RCTL, reg_val); 5215779Sxy150489 5225779Sxy150489 mutex_exit(&igb->gen_lock); 5235779Sxy150489 5246624Sgl147354 if (igb_check_acc_handle(igb->osdep.reg_handle) != DDI_FM_OK) { 5256624Sgl147354 ddi_fm_service_impact(igb->dip, DDI_SERVICE_DEGRADED); 5266624Sgl147354 return (EIO); 5276624Sgl147354 } 5286624Sgl147354 5295779Sxy150489 return (0); 5305779Sxy150489 } 5315779Sxy150489 5325779Sxy150489 /* 5335779Sxy150489 * Add/remove the addresses to/from the set of multicast 5345779Sxy150489 * addresses for which the device will receive packets. 5355779Sxy150489 */ 5365779Sxy150489 int 5375779Sxy150489 igb_m_multicst(void *arg, boolean_t add, const uint8_t *mcst_addr) 5385779Sxy150489 { 5395779Sxy150489 igb_t *igb = (igb_t *)arg; 5405779Sxy150489 int result; 5415779Sxy150489 5425779Sxy150489 mutex_enter(&igb->gen_lock); 5435779Sxy150489 5445779Sxy150489 if (igb->igb_state & IGB_SUSPENDED) { 5455779Sxy150489 mutex_exit(&igb->gen_lock); 5465779Sxy150489 return (ECANCELED); 5475779Sxy150489 } 5485779Sxy150489 5495779Sxy150489 result = (add) ? igb_multicst_add(igb, mcst_addr) 5505779Sxy150489 : igb_multicst_remove(igb, mcst_addr); 5515779Sxy150489 5525779Sxy150489 mutex_exit(&igb->gen_lock); 5535779Sxy150489 5545779Sxy150489 return (result); 5555779Sxy150489 } 5565779Sxy150489 5575779Sxy150489 /* 5585779Sxy150489 * Pass on M_IOCTL messages passed to the DLD, and support 5595779Sxy150489 * private IOCTLs for debugging and ndd. 5605779Sxy150489 */ 5615779Sxy150489 void 5625779Sxy150489 igb_m_ioctl(void *arg, queue_t *q, mblk_t *mp) 5635779Sxy150489 { 5645779Sxy150489 igb_t *igb = (igb_t *)arg; 5655779Sxy150489 struct iocblk *iocp; 5665779Sxy150489 enum ioc_reply status; 5675779Sxy150489 5685779Sxy150489 iocp = (struct iocblk *)(uintptr_t)mp->b_rptr; 5695779Sxy150489 iocp->ioc_error = 0; 5705779Sxy150489 5715779Sxy150489 switch (iocp->ioc_cmd) { 5725779Sxy150489 case LB_GET_INFO_SIZE: 5735779Sxy150489 case LB_GET_INFO: 5745779Sxy150489 case LB_GET_MODE: 5755779Sxy150489 case LB_SET_MODE: 5765779Sxy150489 status = igb_loopback_ioctl(igb, iocp, mp); 5775779Sxy150489 break; 5785779Sxy150489 5795779Sxy150489 case ND_GET: 5805779Sxy150489 case ND_SET: 5815779Sxy150489 status = igb_nd_ioctl(igb, q, mp, iocp); 5825779Sxy150489 break; 5835779Sxy150489 5845779Sxy150489 default: 5855779Sxy150489 status = IOC_INVAL; 5865779Sxy150489 break; 5875779Sxy150489 } 5885779Sxy150489 5895779Sxy150489 /* 5905779Sxy150489 * Decide how to reply 5915779Sxy150489 */ 5925779Sxy150489 switch (status) { 5935779Sxy150489 default: 5945779Sxy150489 case IOC_INVAL: 5955779Sxy150489 /* 5965779Sxy150489 * Error, reply with a NAK and EINVAL or the specified error 5975779Sxy150489 */ 5985779Sxy150489 miocnak(q, mp, 0, iocp->ioc_error == 0 ? 5995779Sxy150489 EINVAL : iocp->ioc_error); 6005779Sxy150489 break; 6015779Sxy150489 6025779Sxy150489 case IOC_DONE: 6035779Sxy150489 /* 6045779Sxy150489 * OK, reply already sent 6055779Sxy150489 */ 6065779Sxy150489 break; 6075779Sxy150489 6085779Sxy150489 case IOC_ACK: 6095779Sxy150489 /* 6105779Sxy150489 * OK, reply with an ACK 6115779Sxy150489 */ 6125779Sxy150489 miocack(q, mp, 0, 0); 6135779Sxy150489 break; 6145779Sxy150489 6155779Sxy150489 case IOC_REPLY: 6165779Sxy150489 /* 6175779Sxy150489 * OK, send prepared reply as ACK or NAK 6185779Sxy150489 */ 6195779Sxy150489 mp->b_datap->db_type = iocp->ioc_error == 0 ? 6205779Sxy150489 M_IOCACK : M_IOCNAK; 6215779Sxy150489 qreply(q, mp); 6225779Sxy150489 break; 6235779Sxy150489 } 6245779Sxy150489 } 6255779Sxy150489 6265779Sxy150489 /* 6278275SEric Cheng * Add a MAC address to the target RX group. 6285779Sxy150489 */ 6298275SEric Cheng static int 6308275SEric Cheng igb_addmac(void *arg, const uint8_t *mac_addr) 6315779Sxy150489 { 6328275SEric Cheng igb_rx_group_t *rx_group = (igb_rx_group_t *)arg; 6338275SEric Cheng igb_t *igb = rx_group->igb; 6348275SEric Cheng struct e1000_hw *hw = &igb->hw; 6358275SEric Cheng int i, slot; 6365779Sxy150489 6375779Sxy150489 mutex_enter(&igb->gen_lock); 6385779Sxy150489 6395779Sxy150489 if (igb->igb_state & IGB_SUSPENDED) { 6405779Sxy150489 mutex_exit(&igb->gen_lock); 6415779Sxy150489 return (ECANCELED); 6425779Sxy150489 } 6435779Sxy150489 6445779Sxy150489 if (igb->unicst_avail == 0) { 6455779Sxy150489 /* no slots available */ 6465779Sxy150489 mutex_exit(&igb->gen_lock); 6475779Sxy150489 return (ENOSPC); 6485779Sxy150489 } 6495779Sxy150489 6505779Sxy150489 /* 6518275SEric Cheng * The slots from 0 to igb->num_rx_groups are reserved slots which 6528275SEric Cheng * are 1 to 1 mapped with group index directly. The other slots are 6538275SEric Cheng * shared between the all of groups. While adding a MAC address, 6548275SEric Cheng * it will try to set the reserved slots first, then the shared slots. 6555779Sxy150489 */ 6568275SEric Cheng slot = -1; 6578275SEric Cheng if (igb->unicst_addr[rx_group->index].mac.set == 1) { 6588275SEric Cheng /* 6598275SEric Cheng * The reserved slot for current group is used, find the free 6608275SEric Cheng * slots in the shared slots. 6618275SEric Cheng */ 6628275SEric Cheng for (i = igb->num_rx_groups; i < igb->unicst_total; i++) { 6638275SEric Cheng if (igb->unicst_addr[i].mac.set == 0) { 6648275SEric Cheng slot = i; 6658275SEric Cheng break; 6668275SEric Cheng } 6678275SEric Cheng } 6688275SEric Cheng } else 6698275SEric Cheng slot = rx_group->index; 6708275SEric Cheng 6718275SEric Cheng if (slot == -1) { 6728275SEric Cheng /* no slots available in the shared slots */ 6738275SEric Cheng mutex_exit(&igb->gen_lock); 6748275SEric Cheng return (ENOSPC); 6755779Sxy150489 } 6765779Sxy150489 6778275SEric Cheng /* Set VMDq according to the mode supported by hardware. */ 6788275SEric Cheng e1000_rar_set_vmdq(hw, mac_addr, slot, igb->vmdq_mode, rx_group->index); 6795779Sxy150489 6808275SEric Cheng bcopy(mac_addr, igb->unicst_addr[slot].mac.addr, ETHERADDRL); 6818275SEric Cheng igb->unicst_addr[slot].mac.group_index = rx_group->index; 6828275SEric Cheng igb->unicst_addr[slot].mac.set = 1; 6838275SEric Cheng igb->unicst_avail--; 6845779Sxy150489 6857072Sxy150489 mutex_exit(&igb->gen_lock); 6867072Sxy150489 6878275SEric Cheng return (0); 6885779Sxy150489 } 6895779Sxy150489 6905779Sxy150489 /* 6918275SEric Cheng * Remove a MAC address from the specified RX group. 6925779Sxy150489 */ 6938275SEric Cheng static int 6948275SEric Cheng igb_remmac(void *arg, const uint8_t *mac_addr) 6955779Sxy150489 { 6968275SEric Cheng igb_rx_group_t *rx_group = (igb_rx_group_t *)arg; 6978275SEric Cheng igb_t *igb = rx_group->igb; 6988275SEric Cheng struct e1000_hw *hw = &igb->hw; 6998275SEric Cheng int slot; 7005779Sxy150489 7015779Sxy150489 mutex_enter(&igb->gen_lock); 7025779Sxy150489 7035779Sxy150489 if (igb->igb_state & IGB_SUSPENDED) { 7045779Sxy150489 mutex_exit(&igb->gen_lock); 7055779Sxy150489 return (ECANCELED); 7065779Sxy150489 } 7075779Sxy150489 7088275SEric Cheng slot = igb_unicst_find(igb, mac_addr); 7098275SEric Cheng if (slot == -1) { 7105779Sxy150489 mutex_exit(&igb->gen_lock); 7115779Sxy150489 return (EINVAL); 7125779Sxy150489 } 7135779Sxy150489 7147072Sxy150489 if (igb->unicst_addr[slot].mac.set == 0) { 7157072Sxy150489 mutex_exit(&igb->gen_lock); 7167072Sxy150489 return (EINVAL); 7177072Sxy150489 } 7187072Sxy150489 7198275SEric Cheng /* Clear the MAC ddress in the slot */ 7208275SEric Cheng e1000_rar_clear(hw, slot); 7218275SEric Cheng igb->unicst_addr[slot].mac.set = 0; 7228275SEric Cheng igb->unicst_avail++; 7235779Sxy150489 7245779Sxy150489 mutex_exit(&igb->gen_lock); 7255779Sxy150489 7268275SEric Cheng return (0); 7278275SEric Cheng } 7288275SEric Cheng 7298275SEric Cheng /* 7308275SEric Cheng * Enable interrupt on the specificed rx ring. 7318275SEric Cheng */ 7328275SEric Cheng int 7338275SEric Cheng igb_rx_ring_intr_enable(mac_intr_handle_t intrh) 7348275SEric Cheng { 7358275SEric Cheng igb_rx_ring_t *rx_ring = (igb_rx_ring_t *)intrh; 7368275SEric Cheng igb_t *igb = rx_ring->igb; 7378275SEric Cheng struct e1000_hw *hw = &igb->hw; 7388275SEric Cheng uint32_t index = rx_ring->index; 7398275SEric Cheng 7408275SEric Cheng if (igb->intr_type == DDI_INTR_TYPE_MSIX) { 7418275SEric Cheng /* Interrupt enabling for MSI-X */ 7428275SEric Cheng igb->eims_mask |= (E1000_EICR_RX_QUEUE0 << index); 7438275SEric Cheng E1000_WRITE_REG(hw, E1000_EIMS, igb->eims_mask); 7448275SEric Cheng E1000_WRITE_REG(hw, E1000_EIAC, igb->eims_mask); 7458275SEric Cheng } else { 7468275SEric Cheng ASSERT(index == 0); 7478275SEric Cheng /* Interrupt enabling for MSI and legacy */ 7488275SEric Cheng igb->ims_mask |= E1000_IMS_RXT0; 7498275SEric Cheng E1000_WRITE_REG(hw, E1000_IMS, igb->ims_mask); 7508275SEric Cheng } 7518275SEric Cheng 7528275SEric Cheng E1000_WRITE_FLUSH(hw); 7538275SEric Cheng 7548275SEric Cheng return (0); 7558275SEric Cheng } 7568275SEric Cheng 7578275SEric Cheng /* 7588275SEric Cheng * Disable interrupt on the specificed rx ring. 7598275SEric Cheng */ 7608275SEric Cheng int 7618275SEric Cheng igb_rx_ring_intr_disable(mac_intr_handle_t intrh) 7628275SEric Cheng { 7638275SEric Cheng igb_rx_ring_t *rx_ring = (igb_rx_ring_t *)intrh; 7648275SEric Cheng igb_t *igb = rx_ring->igb; 7658275SEric Cheng struct e1000_hw *hw = &igb->hw; 7668275SEric Cheng uint32_t index = rx_ring->index; 7678275SEric Cheng 7688275SEric Cheng if (igb->intr_type == DDI_INTR_TYPE_MSIX) { 7698275SEric Cheng /* Interrupt disabling for MSI-X */ 7708275SEric Cheng igb->eims_mask &= ~(E1000_EICR_RX_QUEUE0 << index); 7718275SEric Cheng E1000_WRITE_REG(hw, E1000_EIMC, 7728275SEric Cheng (E1000_EICR_RX_QUEUE0 << index)); 7738275SEric Cheng E1000_WRITE_REG(hw, E1000_EIAC, igb->eims_mask); 7748275SEric Cheng } else { 7758275SEric Cheng ASSERT(index == 0); 7768275SEric Cheng /* Interrupt disabling for MSI and legacy */ 7778275SEric Cheng igb->ims_mask &= ~E1000_IMS_RXT0; 7788275SEric Cheng E1000_WRITE_REG(hw, E1000_IMC, E1000_IMS_RXT0); 7798275SEric Cheng } 7808275SEric Cheng 7818275SEric Cheng E1000_WRITE_FLUSH(hw); 7828275SEric Cheng 7838275SEric Cheng return (0); 7845779Sxy150489 } 7855779Sxy150489 7865779Sxy150489 /* 7878275SEric Cheng * Get the global ring index by a ring index within a group. 7885779Sxy150489 */ 7895779Sxy150489 int 7908275SEric Cheng igb_get_rx_ring_index(igb_t *igb, int gindex, int rindex) 7915779Sxy150489 { 7928275SEric Cheng igb_rx_ring_t *rx_ring; 7938275SEric Cheng int i; 7945779Sxy150489 7958275SEric Cheng for (i = 0; i < igb->num_rx_rings; i++) { 7968275SEric Cheng rx_ring = &igb->rx_rings[i]; 7978275SEric Cheng if (rx_ring->group_index == gindex) 7988275SEric Cheng rindex--; 7998275SEric Cheng if (rindex < 0) 8008275SEric Cheng return (i); 8015779Sxy150489 } 8025779Sxy150489 8038275SEric Cheng return (-1); 8048275SEric Cheng } 8055779Sxy150489 8068275SEric Cheng static int 8078275SEric Cheng igb_ring_start(mac_ring_driver_t rh, uint64_t mr_gen_num) 8088275SEric Cheng { 8098275SEric Cheng igb_rx_ring_t *rx_ring = (igb_rx_ring_t *)rh; 8105779Sxy150489 8118275SEric Cheng mutex_enter(&rx_ring->rx_lock); 8128275SEric Cheng rx_ring->ring_gen_num = mr_gen_num; 8138275SEric Cheng mutex_exit(&rx_ring->rx_lock); 8148275SEric Cheng return (0); 8155779Sxy150489 } 8165779Sxy150489 8175779Sxy150489 /* 8188275SEric Cheng * Callback funtion for MAC layer to register all rings. 8195779Sxy150489 */ 8208275SEric Cheng /* ARGSUSED */ 8218275SEric Cheng void 8228275SEric Cheng igb_fill_ring(void *arg, mac_ring_type_t rtype, const int rg_index, 8238275SEric Cheng const int index, mac_ring_info_t *infop, mac_ring_handle_t rh) 8245779Sxy150489 { 8255779Sxy150489 igb_t *igb = (igb_t *)arg; 8268275SEric Cheng mac_intr_t *mintr = &infop->mri_intr; 8278275SEric Cheng 8288275SEric Cheng switch (rtype) { 8298275SEric Cheng case MAC_RING_TYPE_RX: { 8308275SEric Cheng igb_rx_ring_t *rx_ring; 8318275SEric Cheng int global_index; 8325779Sxy150489 8338275SEric Cheng /* 8348275SEric Cheng * 'index' is the ring index within the group. 8358275SEric Cheng * We need the global ring index by searching in group. 8368275SEric Cheng */ 8378275SEric Cheng global_index = igb_get_rx_ring_index(igb, rg_index, index); 8388275SEric Cheng 8398275SEric Cheng ASSERT(global_index >= 0); 8405779Sxy150489 8418275SEric Cheng rx_ring = &igb->rx_rings[global_index]; 8428275SEric Cheng rx_ring->ring_handle = rh; 8438275SEric Cheng 8448275SEric Cheng infop->mri_driver = (mac_ring_driver_t)rx_ring; 8458275SEric Cheng infop->mri_start = igb_ring_start; 8468275SEric Cheng infop->mri_stop = NULL; 8478275SEric Cheng infop->mri_poll = (mac_ring_poll_t)igb_rx_ring_poll; 8488275SEric Cheng 8498275SEric Cheng mintr->mi_handle = (mac_intr_handle_t)rx_ring; 8508275SEric Cheng mintr->mi_enable = igb_rx_ring_intr_enable; 8518275SEric Cheng mintr->mi_disable = igb_rx_ring_intr_disable; 8528275SEric Cheng 8538275SEric Cheng break; 8545779Sxy150489 } 8558275SEric Cheng case MAC_RING_TYPE_TX: { 8568275SEric Cheng ASSERT(index < igb->num_tx_rings); 8575779Sxy150489 8588275SEric Cheng igb_tx_ring_t *tx_ring = &igb->tx_rings[index]; 8598275SEric Cheng tx_ring->ring_handle = rh; 8605779Sxy150489 8618275SEric Cheng infop->mri_driver = (mac_ring_driver_t)tx_ring; 8628275SEric Cheng infop->mri_start = NULL; 8638275SEric Cheng infop->mri_stop = NULL; 8648275SEric Cheng infop->mri_tx = igb_tx_ring_send; 8658275SEric Cheng 8668275SEric Cheng break; 8675779Sxy150489 } 8688275SEric Cheng default: 8698275SEric Cheng break; 8708275SEric Cheng } 8718275SEric Cheng } 8728275SEric Cheng 8738275SEric Cheng void 8748275SEric Cheng igb_fill_group(void *arg, mac_ring_type_t rtype, const int index, 8758275SEric Cheng mac_group_info_t *infop, mac_group_handle_t gh) 8768275SEric Cheng { 8778275SEric Cheng igb_t *igb = (igb_t *)arg; 8785779Sxy150489 8798275SEric Cheng switch (rtype) { 8808275SEric Cheng case MAC_RING_TYPE_RX: { 8818275SEric Cheng igb_rx_group_t *rx_group; 8828275SEric Cheng 8838275SEric Cheng ASSERT((index >= 0) && (index < igb->num_rx_groups)); 8848275SEric Cheng 8858275SEric Cheng rx_group = &igb->rx_groups[index]; 8868275SEric Cheng rx_group->group_handle = gh; 8878275SEric Cheng 8888275SEric Cheng infop->mgi_driver = (mac_group_driver_t)rx_group; 8898275SEric Cheng infop->mgi_start = NULL; 8908275SEric Cheng infop->mgi_stop = NULL; 8918275SEric Cheng infop->mgi_addmac = igb_addmac; 8928275SEric Cheng infop->mgi_remmac = igb_remmac; 8938275SEric Cheng infop->mgi_count = (igb->num_rx_rings / igb->num_rx_groups); 8948275SEric Cheng 8958275SEric Cheng break; 8965779Sxy150489 } 8978275SEric Cheng case MAC_RING_TYPE_TX: 8988275SEric Cheng break; 8998275SEric Cheng default: 9008275SEric Cheng break; 9018275SEric Cheng } 9025779Sxy150489 } 9035779Sxy150489 9045779Sxy150489 /* 9055779Sxy150489 * Obtain the MAC's capabilities and associated data from 9065779Sxy150489 * the driver. 9075779Sxy150489 */ 9085779Sxy150489 boolean_t 9095779Sxy150489 igb_m_getcapab(void *arg, mac_capab_t cap, void *cap_data) 9105779Sxy150489 { 9115779Sxy150489 igb_t *igb = (igb_t *)arg; 9125779Sxy150489 9135779Sxy150489 switch (cap) { 9145779Sxy150489 case MAC_CAPAB_HCKSUM: { 9155779Sxy150489 uint32_t *tx_hcksum_flags = cap_data; 9165779Sxy150489 9175779Sxy150489 /* 9185779Sxy150489 * We advertise our capabilities only if tx hcksum offload is 9195779Sxy150489 * enabled. On receive, the stack will accept checksummed 9205779Sxy150489 * packets anyway, even if we haven't said we can deliver 9215779Sxy150489 * them. 9225779Sxy150489 */ 9235779Sxy150489 if (!igb->tx_hcksum_enable) 9245779Sxy150489 return (B_FALSE); 9255779Sxy150489 9265779Sxy150489 *tx_hcksum_flags = HCKSUM_INET_PARTIAL | HCKSUM_IPHDRCKSUM; 9275779Sxy150489 break; 9285779Sxy150489 } 929*9188SPaul.Guo@Sun.COM case MAC_CAPAB_LSO: { 930*9188SPaul.Guo@Sun.COM mac_capab_lso_t *cap_lso = cap_data; 931*9188SPaul.Guo@Sun.COM 932*9188SPaul.Guo@Sun.COM if (igb->lso_enable) { 933*9188SPaul.Guo@Sun.COM cap_lso->lso_flags = LSO_TX_BASIC_TCP_IPV4; 934*9188SPaul.Guo@Sun.COM cap_lso->lso_basic_tcp_ipv4.lso_max = IGB_LSO_MAXLEN; 935*9188SPaul.Guo@Sun.COM break; 936*9188SPaul.Guo@Sun.COM } else { 937*9188SPaul.Guo@Sun.COM return (B_FALSE); 938*9188SPaul.Guo@Sun.COM } 939*9188SPaul.Guo@Sun.COM } 9408275SEric Cheng case MAC_CAPAB_RINGS: { 9418275SEric Cheng mac_capab_rings_t *cap_rings = cap_data; 9428275SEric Cheng 9438275SEric Cheng switch (cap_rings->mr_type) { 9448275SEric Cheng case MAC_RING_TYPE_RX: 9458275SEric Cheng cap_rings->mr_group_type = MAC_GROUP_TYPE_STATIC; 9468275SEric Cheng cap_rings->mr_rnum = igb->num_rx_rings; 9478275SEric Cheng cap_rings->mr_gnum = igb->num_rx_groups; 9488275SEric Cheng cap_rings->mr_rget = igb_fill_ring; 9498275SEric Cheng cap_rings->mr_gget = igb_fill_group; 9508275SEric Cheng cap_rings->mr_gaddring = NULL; 9518275SEric Cheng cap_rings->mr_gremring = NULL; 9525779Sxy150489 9538275SEric Cheng break; 9548275SEric Cheng case MAC_RING_TYPE_TX: 9558275SEric Cheng cap_rings->mr_group_type = MAC_GROUP_TYPE_STATIC; 9568275SEric Cheng cap_rings->mr_rnum = igb->num_tx_rings; 9578275SEric Cheng cap_rings->mr_gnum = 0; 9588275SEric Cheng cap_rings->mr_rget = igb_fill_ring; 9598275SEric Cheng cap_rings->mr_gget = NULL; 9608275SEric Cheng 9618275SEric Cheng break; 9628275SEric Cheng default: 9638275SEric Cheng break; 9648275SEric Cheng } 9655779Sxy150489 break; 9665779Sxy150489 } 9678275SEric Cheng 9685779Sxy150489 default: 9695779Sxy150489 return (B_FALSE); 9705779Sxy150489 } 9715779Sxy150489 return (B_TRUE); 9725779Sxy150489 } 973