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
bnx_cfg_readbool(dev_info_t * dip,char * paramname,boolean_t * paramval)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
bnx_cfg_readint(dev_info_t * dip,char * paramname,int * paramval)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
bnx_cfg_msix(um_device_t * const umdevice)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
bnx_cfg_init(um_device_t * const umdevice)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
bnx_cfg_reset(um_device_t * const umdevice)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
bnx_cfg_map_serdes(um_device_t * const umdevice)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
bnx_cfg_map_copper(um_device_t * const umdevice)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
bnx_cfg_map_phy(um_device_t * const umdevice)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