1 /* 2 * Copyright 2014-2017 Cavium, Inc. 3 * The contents of this file are subject to the terms of the Common Development 4 * and Distribution License, v.1, (the "License"). 5 * 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the License at available 9 * at http://opensource.org/licenses/CDDL-1.0 10 * 11 * See the License for the specific language governing permissions and 12 * limitations under the License. 13 */ 14 15 /* 16 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. 17 * Copyright (c) 2019, Joyent, Inc. 18 */ 19 20 #include "bnxcfg.h" 21 22 const bnx_lnk_cfg_t bnx_copper_config = { 23 B_TRUE, /* link_autoneg */ 24 B_FALSE, /* param_2500fdx */ 25 B_TRUE, /* param_1000fdx */ 26 B_TRUE, /* param_1000hdx */ 27 B_TRUE, /* param_100fdx */ 28 B_TRUE, /* param_100hdx */ 29 B_TRUE, /* param_10fdx */ 30 B_TRUE, /* param_10hdx */ 31 B_TRUE, /* param_tx_pause */ 32 B_TRUE /* param_rx_pause */ 33 }; 34 35 const bnx_lnk_cfg_t bnx_serdes_config = { 36 B_TRUE, /* link_autoneg */ 37 B_TRUE, /* param_2500fdx */ 38 B_TRUE, /* param_1000fdx */ 39 B_TRUE, /* param_1000hdx */ 40 B_FALSE, /* param_100fdx */ 41 B_FALSE, /* param_100hdx */ 42 B_FALSE, /* param_10fdx */ 43 B_FALSE, /* param_10hdx */ 44 B_TRUE, /* param_tx_pause */ 45 B_TRUE /* param_rx_pause */ 46 }; 47 48 static void 49 bnx_cfg_readbool(dev_info_t *dip, char *paramname, boolean_t *paramval) 50 { 51 int rc; 52 int *option; 53 uint_t num_options; 54 55 if (ddi_prop_exists(DDI_DEV_T_ANY, dip, DDI_PROP_NOTPROM, paramname) == 56 1) { 57 rc = ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, 58 DDI_PROP_DONTPASS, paramname, &option, &num_options); 59 60 if (rc == DDI_PROP_SUCCESS) { 61 int inst = ddi_get_instance(dip); 62 63 if (num_options >= inst) { 64 if (option[inst] == 1) { 65 *paramval = B_TRUE; 66 } else { 67 *paramval = B_FALSE; 68 } 69 } 70 } 71 72 ddi_prop_free(option); 73 } 74 } /* bnx_cfg_readbool */ 75 76 static void 77 bnx_cfg_readint(dev_info_t *dip, char *paramname, int *paramval) 78 { 79 int rc; 80 int *option; 81 uint_t num_options; 82 83 rc = ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, 84 paramname, &option, &num_options); 85 if (rc == DDI_PROP_SUCCESS) { 86 int inst = ddi_get_instance(dip); 87 88 if (num_options >= inst) { 89 *paramval = option[inst]; 90 } 91 92 ddi_prop_free(option); 93 } 94 } /* bnx_cfg_readint */ 95 96 void 97 bnx_cfg_msix(um_device_t * const umdevice) 98 { 99 umdevice->dev_var.disableMsix = B_FALSE; 100 101 bnx_cfg_readbool(umdevice->os_param.dip, "disable_msix", 102 &(umdevice->dev_var.disableMsix)); 103 } 104 105 void 106 bnx_cfg_init(um_device_t *const umdevice) 107 { 108 int option; 109 lm_medium_t lmmedium; 110 lm_device_t *lmdevice; 111 112 lmdevice = &(umdevice->lm_dev); 113 114 lmmedium = lm_get_medium(lmdevice); 115 if (lmmedium == LM_MEDIUM_TYPE_FIBER) { 116 umdevice->dev_var.isfiber = B_TRUE; 117 118 bcopy(&bnx_serdes_config, 119 &(umdevice->hwinit.lnkcfg), 120 sizeof (bnx_serdes_config)); 121 } else { 122 umdevice->dev_var.isfiber = B_FALSE; 123 124 bcopy(&bnx_copper_config, &(umdevice->hwinit.lnkcfg), 125 sizeof (bnx_copper_config)); 126 } 127 128 umdevice->hwinit.flow_autoneg = B_TRUE; 129 umdevice->hwinit.wirespeed = B_TRUE; 130 131 bnx_cfg_readbool(umdevice->os_param.dip, "adv_autoneg_cap", 132 &(umdevice->hwinit.lnkcfg.link_autoneg)); 133 134 bnx_cfg_readbool(umdevice->os_param.dip, "adv_1000fdx_cap", 135 &(umdevice->hwinit.lnkcfg.param_1000fdx)); 136 137 bnx_cfg_readbool(umdevice->os_param.dip, "adv_1000hdx_cap", 138 &(umdevice->hwinit.lnkcfg.param_1000hdx)); 139 140 bnx_cfg_readbool(umdevice->os_param.dip, "tx_pause_cap", 141 &(umdevice->hwinit.lnkcfg.param_tx_pause)); 142 143 bnx_cfg_readbool(umdevice->os_param.dip, "rx_pause_cap", 144 &(umdevice->hwinit.lnkcfg.param_rx_pause)); 145 146 if (umdevice->dev_var.isfiber) { 147 bnx_cfg_readbool(umdevice->os_param.dip, "adv_2500fdx_cap", 148 &(umdevice->hwinit.lnkcfg.param_2500fdx)); 149 } else { 150 bnx_cfg_readbool(umdevice->os_param.dip, "adv_100fdx_cap", 151 &(umdevice->hwinit.lnkcfg.param_100fdx)); 152 153 bnx_cfg_readbool(umdevice->os_param.dip, "adv_100hdx_cap", 154 &(umdevice->hwinit.lnkcfg.param_100hdx)); 155 156 bnx_cfg_readbool(umdevice->os_param.dip, "adv_10fdx_cap", 157 &(umdevice->hwinit.lnkcfg.param_10fdx)); 158 159 bnx_cfg_readbool(umdevice->os_param.dip, "adv_10hdx_cap", 160 &(umdevice->hwinit.lnkcfg.param_10hdx)); 161 } 162 163 bnx_cfg_readbool(umdevice->os_param.dip, "autoneg_flow", 164 &(umdevice->hwinit.flow_autoneg)); 165 166 bnx_cfg_readbool(umdevice->os_param.dip, "wirespeed", 167 &(umdevice->hwinit.wirespeed)); 168 169 #if 1 170 /* FIXME -- Do we really need "transfer-speed"? */ 171 /* 172 * The link speed may be forced to 10, 100 or 1000 Mbps using 173 * the property "transfer-speed". This may be done in OBP by 174 * using the command "apply transfer-speed=<speed> <device>". 175 * The speed may be 10, 100 or 1000 - any other value will be 176 * ignored. Note that this *enables* autonegotiation, but 177 * restricts it to the speed specified by the property. 178 */ 179 option = 0; 180 bnx_cfg_readint(umdevice->os_param.dip, 181 "transfer-speed", &option); 182 switch (option) { 183 case 1000: 184 umdevice->hwinit.lnkcfg.link_autoneg = B_TRUE; 185 umdevice->hwinit.lnkcfg.param_1000fdx = B_TRUE; 186 umdevice->hwinit.lnkcfg.param_1000hdx = B_TRUE; 187 umdevice->hwinit.lnkcfg.param_100fdx = B_FALSE; 188 umdevice->hwinit.lnkcfg.param_100hdx = B_FALSE; 189 umdevice->hwinit.lnkcfg.param_10fdx = B_FALSE; 190 umdevice->hwinit.lnkcfg.param_10hdx = B_FALSE; 191 break; 192 193 case 100: 194 umdevice->hwinit.lnkcfg.link_autoneg = B_TRUE; 195 umdevice->hwinit.lnkcfg.param_1000fdx = B_FALSE; 196 umdevice->hwinit.lnkcfg.param_1000hdx = B_FALSE; 197 umdevice->hwinit.lnkcfg.param_100fdx = B_TRUE; 198 umdevice->hwinit.lnkcfg.param_100hdx = B_TRUE; 199 umdevice->hwinit.lnkcfg.param_10fdx = B_FALSE; 200 umdevice->hwinit.lnkcfg.param_10hdx = B_FALSE; 201 break; 202 203 case 10: 204 umdevice->hwinit.lnkcfg.link_autoneg = B_TRUE; 205 umdevice->hwinit.lnkcfg.param_1000fdx = B_FALSE; 206 umdevice->hwinit.lnkcfg.param_1000hdx = B_FALSE; 207 umdevice->hwinit.lnkcfg.param_100fdx = B_FALSE; 208 umdevice->hwinit.lnkcfg.param_100hdx = B_FALSE; 209 umdevice->hwinit.lnkcfg.param_10fdx = B_TRUE; 210 umdevice->hwinit.lnkcfg.param_10hdx = B_TRUE; 211 break; 212 } 213 #endif 214 215 216 /* FIXME -- Make the MAC address hwconf configurable. */ 217 218 /* Checksum configuration */ 219 option = USER_OPTION_CKSUM_DEFAULT; 220 bnx_cfg_readint(umdevice->os_param.dip, 221 "checksum", &option); 222 switch (option) { 223 case USER_OPTION_CKSUM_TX_ONLY: 224 umdevice->dev_var.enabled_oflds = LM_OFFLOAD_TX_IP_CKSUM 225 | LM_OFFLOAD_TX_TCP_CKSUM 226 | LM_OFFLOAD_TX_UDP_CKSUM; 227 break; 228 229 case USER_OPTION_CKSUM_RX_ONLY: 230 umdevice->dev_var.enabled_oflds = LM_OFFLOAD_RX_IP_CKSUM 231 | LM_OFFLOAD_RX_TCP_CKSUM 232 | LM_OFFLOAD_RX_UDP_CKSUM; 233 break; 234 235 case USER_OPTION_CKSUM_TX_RX: 236 umdevice->dev_var.enabled_oflds = LM_OFFLOAD_TX_IP_CKSUM 237 | LM_OFFLOAD_RX_IP_CKSUM 238 | LM_OFFLOAD_TX_TCP_CKSUM 239 | LM_OFFLOAD_RX_TCP_CKSUM 240 | LM_OFFLOAD_TX_UDP_CKSUM 241 | LM_OFFLOAD_RX_UDP_CKSUM; 242 break; 243 244 case USER_OPTION_CKSUM_NONE: 245 default: 246 umdevice->dev_var.enabled_oflds = LM_OFFLOAD_NONE; 247 break; 248 } 249 250 /* Ticks interval between statistics block updates. */ 251 option = USER_OPTION_STATSTICKS_DEFAULT; 252 bnx_cfg_readint(umdevice->os_param.dip, 253 USER_OPTION_KEYWORD_STATSTICKS, &option); 254 if (option >= USER_OPTION_STATSTICKS_MIN && 255 option <= USER_OPTION_STATSTICKS_MAX) { 256 lmdevice->params.stats_ticks = option; 257 } else { 258 lmdevice->params.stats_ticks = USER_OPTION_STATSTICKS_DEFAULT; 259 } 260 261 /* Tx ticks for interrupt coalescing */ 262 option = USER_OPTION_TXTICKS_DEFAULT; 263 bnx_cfg_readint(umdevice->os_param.dip, 264 "tx_coalesce_ticks", &option); 265 if (option >= USER_OPTION_TICKS_MIN && 266 option <= USER_OPTION_TICKS_MAX) { 267 lmdevice->params.tx_ticks = option; 268 } else { 269 lmdevice->params.tx_ticks = USER_OPTION_TXTICKS_DEFAULT; 270 } 271 272 /* Interrupt mode Tx ticks for interrupt coalescing */ 273 option = USER_OPTION_TXTICKS_INT_DEFAULT; 274 bnx_cfg_readint(umdevice->os_param.dip, 275 "tx_coalesce_ticks_int", &option); 276 if (option >= USER_OPTION_TICKS_MIN && 277 option <= USER_OPTION_TICKS_MAX) { 278 lmdevice->params.tx_ticks_int = option; 279 } else { 280 lmdevice->params.tx_ticks_int = USER_OPTION_TXTICKS_INT_DEFAULT; 281 } 282 283 /* Rx ticks for interrupt coalescing */ 284 option = USER_OPTION_RXTICKS_DEFAULT; 285 bnx_cfg_readint(umdevice->os_param.dip, 286 "rx_coalesce_ticks", &option); 287 if (option >= USER_OPTION_TICKS_MIN && 288 option <= USER_OPTION_TICKS_MAX) { 289 lmdevice->params.rx_ticks = option; 290 } else { 291 lmdevice->params.rx_ticks = USER_OPTION_RXTICKS_DEFAULT; 292 } 293 294 /* Interrupt mode Rx ticks for interrupt coalescing */ 295 option = USER_OPTION_RXTICKS_INT_DEFAULT; 296 bnx_cfg_readint(umdevice->os_param.dip, 297 "rx_coalesce_ticks_int", &option); 298 if (option >= USER_OPTION_TICKS_INT_MIN && 299 option <= USER_OPTION_TICKS_INT_MAX) { 300 lmdevice->params.rx_ticks_int = option; 301 } else { 302 lmdevice->params.rx_ticks_int = USER_OPTION_RXTICKS_INT_DEFAULT; 303 } 304 305 306 /* Tx frames for interrupt coalescing */ 307 option = USER_OPTION_TXFRAMES_DEFAULT; 308 bnx_cfg_readint(umdevice->os_param.dip, 309 "tx_coalesce_frames", &option); 310 if (option >= USER_OPTION_FRAMES_MIN && 311 option <= USER_OPTION_FRAMES_MAX) { 312 lmdevice->params.tx_quick_cons_trip = option; 313 } else { 314 lmdevice->params.tx_quick_cons_trip = 315 USER_OPTION_TXFRAMES_DEFAULT; 316 } 317 318 /* Interrupt mode Tx frames for interrupt coalescing */ 319 option = USER_OPTION_TXFRAMES_INT_DEFAULT; 320 bnx_cfg_readint(umdevice->os_param.dip, 321 "tx_coalesce_frames_int", &option); 322 if (option >= USER_OPTION_FRAMES_MIN && 323 option <= USER_OPTION_FRAMES_MAX) { 324 lmdevice->params.tx_quick_cons_trip_int = option; 325 } else { 326 lmdevice->params.tx_quick_cons_trip_int = 327 USER_OPTION_TXFRAMES_INT_DEFAULT; 328 } 329 330 /* Rx frames for interrupt coalescing */ 331 option = USER_OPTION_RXFRAMES_DEFAULT; 332 bnx_cfg_readint(umdevice->os_param.dip, 333 "rx_coalesce_frames", &option); 334 if (option >= USER_OPTION_FRAMES_MIN && 335 option <= USER_OPTION_FRAMES_MAX) { 336 lmdevice->params.rx_quick_cons_trip = option; 337 } else { 338 lmdevice->params.rx_quick_cons_trip = 339 USER_OPTION_RXFRAMES_DEFAULT; 340 } 341 342 /* Interrupt mode Rx frames for interrupt coalescing */ 343 option = USER_OPTION_RXFRAMES_INT_DEFAULT; 344 bnx_cfg_readint(umdevice->os_param.dip, 345 "rx_coalesce_frames_int", &option); 346 if (option >= USER_OPTION_FRAMES_MIN && 347 option <= USER_OPTION_FRAMES_MAX) { 348 lmdevice->params.rx_quick_cons_trip_int = option; 349 } else { 350 lmdevice->params.rx_quick_cons_trip_int = 351 USER_OPTION_RXFRAMES_INT_DEFAULT; 352 } 353 354 355 option = USER_OPTION_TX_DESC_CNT_DEFAULT; 356 bnx_cfg_readint(umdevice->os_param.dip, 357 "tx_descriptor_count", &option); 358 if (option < USER_OPTION_TX_DESC_CNT_MIN || 359 option > USER_OPTION_TX_DESC_CNT_MAX) { 360 option = USER_OPTION_TX_DESC_CNT_DEFAULT; 361 } 362 363 /* FIXME -- tx bd pages assumes 1 pd === 1 bd */ 364 _TX_QINFO(umdevice, 0).desc_cnt = option; 365 lmdevice->params.l2_tx_bd_page_cnt[0] = option / MAX_BD_PER_PAGE; 366 if (option % MAX_BD_PER_PAGE) { 367 lmdevice->params.l2_tx_bd_page_cnt[0]++; 368 } 369 if (lmdevice->params.l2_tx_bd_page_cnt[0] > 127) { 370 lmdevice->params.l2_tx_bd_page_cnt[0] = 127; 371 } 372 373 374 option = USER_OPTION_RX_DESC_CNT_DEFAULT; 375 bnx_cfg_readint(umdevice->os_param.dip, 376 "rx_descriptor_count", &option); 377 if (option < USER_OPTION_RX_DESC_CNT_MIN || 378 option > USER_OPTION_RX_DESC_CNT_MAX) { 379 option = USER_OPTION_RX_DESC_CNT_DEFAULT; 380 } 381 382 lmdevice->params.l2_rx_desc_cnt[0] = option; 383 option = (option * BNX_RECV_MAX_FRAGS) / MAX_BD_PER_PAGE; 384 lmdevice->params.l2_rx_bd_page_cnt[0] = option; 385 if (option % MAX_BD_PER_PAGE) { 386 lmdevice->params.l2_rx_bd_page_cnt[0]++; 387 } 388 389 option = USER_OPTION_MTU_DEFAULT; 390 bnx_cfg_readint(umdevice->os_param.dip, 391 "mtu", &option); 392 if (option < USER_OPTION_MTU_MIN) { 393 umdevice->dev_var.mtu = USER_OPTION_MTU_MIN; 394 } else if (option > USER_OPTION_MTU_MAX) { 395 umdevice->dev_var.mtu = USER_OPTION_MTU_MAX; 396 } else { 397 umdevice->dev_var.mtu = option; 398 } 399 lmdevice->params.mtu = umdevice->dev_var.mtu + 400 sizeof (struct ether_header) + VLAN_TAGSZ; 401 402 /* Flag to enable double copy of transmit payload. */ 403 option = USER_OPTION_TX_DCOPY_THRESH_DEFAULT; 404 bnx_cfg_readint(umdevice->os_param.dip, 405 "tx_copy_thresh", &option); 406 if (option < MIN_ETHERNET_PACKET_SIZE) { 407 option = MIN_ETHERNET_PACKET_SIZE; 408 } 409 umdevice->tx_copy_threshold = option; 410 411 /* Flag to enable double copy of receive packet. */ 412 option = USER_OPTION_RX_DCOPY_DEFAULT; 413 bnx_cfg_readint(umdevice->os_param.dip, USER_OPTION_KEYWORD_RX_DCOPY, 414 &option); 415 if (option) { 416 umdevice->rx_copy_threshold = 0xffffffff; 417 } else { 418 umdevice->rx_copy_threshold = 0; 419 } 420 } /* bnx_cfg_init */ 421 422 423 void 424 bnx_cfg_reset(um_device_t *const umdevice) 425 { 426 /* Reset the link status. */ 427 umdevice->nddcfg.link_speed = 0; 428 umdevice->nddcfg.link_duplex = B_FALSE; 429 umdevice->nddcfg.link_tx_pause = B_FALSE; 430 umdevice->nddcfg.link_rx_pause = B_FALSE; 431 432 /* Reset the link partner status. */ 433 umdevice->remote.link_autoneg = B_FALSE; 434 umdevice->remote.param_2500fdx = B_FALSE; 435 umdevice->remote.param_1000fdx = B_FALSE; 436 umdevice->remote.param_1000hdx = B_FALSE; 437 umdevice->remote.param_100fdx = B_FALSE; 438 umdevice->remote.param_100hdx = B_FALSE; 439 umdevice->remote.param_10fdx = B_FALSE; 440 umdevice->remote.param_10hdx = B_FALSE; 441 umdevice->remote.param_tx_pause = B_FALSE; 442 umdevice->remote.param_rx_pause = B_FALSE; 443 444 /* Reset the configuration to the hardware default. */ 445 bcopy(&(umdevice->hwinit), &(umdevice->curcfg), sizeof (bnx_phy_cfg_t)); 446 } /* bnx_cfg_reset */ 447 448 449 450 static lm_medium_t 451 bnx_cfg_map_serdes(um_device_t *const umdevice) 452 { 453 lm_medium_t lmmedium; 454 lm_device_t *lmdevice; 455 456 lmdevice = &(umdevice->lm_dev); 457 458 lmmedium = LM_MEDIUM_TYPE_FIBER; 459 460 if (umdevice->curcfg.lnkcfg.link_autoneg) { 461 if (umdevice->curcfg.lnkcfg.param_2500fdx && 462 umdevice->curcfg.lnkcfg.param_1000fdx && 463 umdevice->curcfg.lnkcfg.param_1000hdx) { 464 /* 465 * All autoneg speeds are advertised. 466 * Don't specify a speed so we get the full range. 467 */ 468 lmmedium |= LM_MEDIUM_SPEED_AUTONEG; 469 } else { 470 lmdevice->params.selective_autoneg = 471 SELECTIVE_AUTONEG_SINGLE_SPEED; 472 473 if (umdevice->curcfg.lnkcfg.param_2500fdx) { 474 lmmedium |= LM_MEDIUM_SPEED_2500MBPS 475 | LM_MEDIUM_FULL_DUPLEX; 476 } else if (umdevice->curcfg.lnkcfg.param_1000fdx) { 477 lmmedium |= LM_MEDIUM_SPEED_1000MBPS 478 | LM_MEDIUM_FULL_DUPLEX; 479 } else if (umdevice->curcfg.lnkcfg.param_1000hdx) { 480 lmmedium |= LM_MEDIUM_SPEED_1000MBPS 481 | LM_MEDIUM_HALF_DUPLEX; 482 } else { 483 /* Configuration error. */ 484 lmdevice->params.selective_autoneg = 485 SELECTIVE_AUTONEG_OFF; 486 goto error; 487 } 488 } 489 490 /* 491 * Enable serdes fallback for all but one particular HP 492 * platform. 493 */ 494 if (CHIP_NUM(lmdevice) == CHIP_NUM_5706 && 495 !(lmdevice->hw_info.svid == 0x103c && 496 lmdevice->hw_info.ssid == 0x310c)) { 497 if (umdevice->curcfg.lnkcfg.param_2500fdx) { 498 lmmedium |= 499 LM_MEDIUM_SPEED_AUTONEG_2_5G_FALLBACK; 500 } else { 501 lmmedium |= LM_MEDIUM_SPEED_AUTONEG_1G_FALLBACK; 502 } 503 } 504 } else { 505 if (umdevice->curcfg.lnkcfg.param_2500fdx) { 506 lmmedium |= LM_MEDIUM_SPEED_2500MBPS 507 | LM_MEDIUM_FULL_DUPLEX; 508 } else if (umdevice->curcfg.lnkcfg.param_1000fdx) { 509 lmmedium |= LM_MEDIUM_SPEED_1000MBPS 510 | LM_MEDIUM_FULL_DUPLEX; 511 } else { 512 /* Configuration error. */ 513 goto error; 514 } 515 } 516 517 return (lmmedium); 518 519 error: 520 /* Just give them full autoneg with no fallback capabilities. */ 521 lmmedium |= LM_MEDIUM_SPEED_AUTONEG; 522 523 return (lmmedium); 524 } /* bnx_cfg_map_serdes */ 525 526 527 528 static lm_medium_t 529 bnx_cfg_map_copper(um_device_t *const umdevice) 530 { 531 lm_medium_t lmmedium; 532 lm_device_t *lmdevice; 533 534 lmdevice = &(umdevice->lm_dev); 535 536 lmmedium = LM_MEDIUM_TYPE_UTP; 537 538 if (umdevice->curcfg.lnkcfg.link_autoneg) { 539 if (umdevice->curcfg.lnkcfg.param_1000fdx == B_TRUE && 540 umdevice->curcfg.lnkcfg.param_1000hdx == B_TRUE && 541 umdevice->curcfg.lnkcfg.param_100fdx == B_TRUE && 542 umdevice->curcfg.lnkcfg.param_100hdx == B_TRUE && 543 umdevice->curcfg.lnkcfg.param_10fdx == B_TRUE && 544 umdevice->curcfg.lnkcfg.param_10hdx == B_TRUE) { 545 /* 546 * All autoneg speeds are advertised. 547 * Don't specify a speed so we get the full range. 548 */ 549 lmmedium |= LM_MEDIUM_SPEED_AUTONEG; 550 } else { 551 lmdevice->params.selective_autoneg = 552 SELECTIVE_AUTONEG_SINGLE_SPEED; 553 554 if (umdevice->curcfg.lnkcfg.param_1000fdx) { 555 lmmedium |= LM_MEDIUM_SPEED_1000MBPS 556 | LM_MEDIUM_FULL_DUPLEX; 557 } else if (umdevice->curcfg.lnkcfg.param_1000hdx) { 558 lmmedium |= LM_MEDIUM_SPEED_1000MBPS 559 | LM_MEDIUM_HALF_DUPLEX; 560 561 if (umdevice->curcfg.lnkcfg.param_100fdx == 562 B_TRUE && 563 umdevice->curcfg.lnkcfg.param_100hdx == 564 B_TRUE && 565 umdevice->curcfg.lnkcfg.param_10fdx == 566 B_TRUE && 567 umdevice->curcfg.lnkcfg.param_10hdx == 568 B_TRUE) { 569 lmdevice->params.selective_autoneg = 570 SELECTIVE_AUTONEG_ENABLE_SLOWER_SPEEDS; 571 } 572 } else if (umdevice->curcfg.lnkcfg.param_100fdx) { 573 lmmedium |= LM_MEDIUM_SPEED_100MBPS 574 | LM_MEDIUM_FULL_DUPLEX; 575 576 if (umdevice->curcfg.lnkcfg.param_100hdx == 577 B_TRUE && 578 umdevice->curcfg.lnkcfg.param_10fdx == 579 B_TRUE && 580 umdevice->curcfg.lnkcfg.param_10hdx == 581 B_TRUE) { 582 lmdevice->params.selective_autoneg = 583 SELECTIVE_AUTONEG_ENABLE_SLOWER_SPEEDS; 584 } 585 } else if (umdevice->curcfg.lnkcfg.param_100hdx) { 586 lmmedium |= LM_MEDIUM_SPEED_100MBPS 587 | LM_MEDIUM_HALF_DUPLEX; 588 589 if (umdevice->curcfg.lnkcfg.param_10fdx == 590 B_TRUE && 591 umdevice->curcfg.lnkcfg.param_10hdx == 592 B_TRUE) { 593 lmdevice->params.selective_autoneg = 594 SELECTIVE_AUTONEG_ENABLE_SLOWER_SPEEDS; 595 } 596 } else if (umdevice->curcfg.lnkcfg.param_10fdx) { 597 lmmedium |= LM_MEDIUM_SPEED_10MBPS 598 | LM_MEDIUM_FULL_DUPLEX; 599 600 if (umdevice->curcfg.lnkcfg.param_10hdx == 601 B_TRUE) { 602 lmdevice->params.selective_autoneg = 603 SELECTIVE_AUTONEG_ENABLE_SLOWER_SPEEDS; 604 } 605 } else if (umdevice->curcfg.lnkcfg.param_10hdx) { 606 lmmedium |= LM_MEDIUM_SPEED_10MBPS 607 | LM_MEDIUM_HALF_DUPLEX; 608 } else { 609 /* Configuration error. */ 610 lmdevice->params.selective_autoneg = 611 SELECTIVE_AUTONEG_OFF; 612 goto error; 613 } 614 } 615 } else { 616 /* 617 * Forced speeds greater than 100Mbps intentionally omitted. 618 * Forcing speeds greater than 100Mbps on copper media is 619 * illegal. 620 */ 621 if (umdevice->curcfg.lnkcfg.param_100fdx) { 622 lmmedium |= LM_MEDIUM_SPEED_100MBPS 623 | LM_MEDIUM_FULL_DUPLEX; 624 } else if (umdevice->curcfg.lnkcfg.param_100hdx) { 625 lmmedium |= LM_MEDIUM_SPEED_100MBPS 626 | LM_MEDIUM_HALF_DUPLEX; 627 } else if (umdevice->curcfg.lnkcfg.param_10fdx) { 628 lmmedium |= LM_MEDIUM_SPEED_10MBPS 629 | LM_MEDIUM_FULL_DUPLEX; 630 } else if (umdevice->curcfg.lnkcfg.param_10hdx) { 631 lmmedium |= LM_MEDIUM_SPEED_10MBPS 632 | LM_MEDIUM_HALF_DUPLEX; 633 } else { 634 /* Configuration error. */ 635 goto error; 636 } 637 } 638 639 return (lmmedium); 640 641 error: 642 /* Just give them full autoneg. */ 643 lmmedium |= LM_MEDIUM_SPEED_AUTONEG; 644 645 return (lmmedium); 646 } /* bnx_cfg_map_copper */ 647 648 649 650 /* 651 * Name: bnx_cfg_map_phy 652 * 653 * Input: ptr to device structure 654 * 655 * Return: None 656 * 657 * Description: This function is translates user configuration parameter, 658 * ones accessible through 'ndd' commands to LM driver settings. 659 * Driver chooses best possible parameters if conflicting ones 660 * are set by the user. 661 */ 662 void 663 bnx_cfg_map_phy(um_device_t *const umdevice) 664 { 665 lm_medium_t lmmedium; 666 lm_device_t *lmdevice; 667 lm_flow_control_t flowctrl; 668 669 lmdevice = &(umdevice->lm_dev); 670 671 /* Disable the remote PHY. */ 672 lmdevice->params.enable_remote_phy = 0; 673 674 /* Assume selective autonegotiation is turned off. */ 675 lmdevice->params.selective_autoneg = SELECTIVE_AUTONEG_OFF; 676 677 /* FIXME -- Clean up configuration parameters. */ 678 if (umdevice->dev_var.isfiber) { 679 lmmedium = bnx_cfg_map_serdes(umdevice); 680 } else { 681 lmmedium = bnx_cfg_map_copper(umdevice); 682 } 683 684 lmdevice->params.req_medium = lmmedium; 685 686 687 flowctrl = LM_FLOW_CONTROL_NONE; 688 689 if (umdevice->curcfg.lnkcfg.param_tx_pause) { 690 flowctrl |= LM_FLOW_CONTROL_TRANSMIT_PAUSE; 691 } 692 693 if (umdevice->curcfg.lnkcfg.param_rx_pause) { 694 flowctrl |= LM_FLOW_CONTROL_RECEIVE_PAUSE; 695 } 696 697 if (umdevice->curcfg.flow_autoneg == B_TRUE && 698 flowctrl != LM_FLOW_CONTROL_NONE) { 699 /* 700 * FIXME -- LM Flow control constraint. 701 * LM_FLOW_CONTROL_AUTO_PAUSE == 702 * (LM_FLOW_CONTROL_AUTO_PAUSE | 703 * LM_FLOW_CONTROL_TRANSMIT_PAUSE | 704 * LM_FLOW_CONTROL_RECEIVE_PAUSE) 705 * The LM does not allow us finer selection of what 706 * pause features to autoneg. 707 */ 708 flowctrl |= LM_FLOW_CONTROL_AUTO_PAUSE; 709 } 710 711 lmdevice->params.flow_ctrl_cap = flowctrl; 712 713 lmdevice->params.wire_speed = umdevice->curcfg.wirespeed; 714 } /* bnx_cfg_map_phy */ 715