1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
23 */
24
25 #include <sys/nxge/nxge_impl.h>
26 #include <sys/nxge/nxge_mac.h>
27 #include <sys/nxge/nxge_hio.h>
28
29 #define LINK_MONITOR_PERIOD (1000 * 1000)
30 #define LM_WAIT_MULTIPLIER 8
31
32 #define SERDES_RDY_WT_INTERVAL 50
33 #define MAX_SERDES_RDY_RETRIES 10
34
35 #define TN1010_SPEED_1G 1
36 #define TN1010_SPEED_10G 0
37 #define TN1010_AN_IN_PROG 0 /* Auto negotiation in progress */
38 #define TN1010_AN_COMPLETE 1
39 #define TN1010_AN_RSVD 2
40 #define TN1010_AN_FAILED 3
41
42 extern uint32_t nxge_no_link_notify;
43 extern boolean_t nxge_no_msg;
44 extern uint32_t nxge_lb_dbg;
45 extern uint32_t nxge_jumbo_mtu;
46
47 typedef enum {
48 CHECK_LINK_RESCHEDULE,
49 CHECK_LINK_STOP
50 } check_link_state_t;
51
52 static check_link_state_t nxge_check_link_stop(nxge_t *);
53
54 /*
55 * Ethernet broadcast address definition.
56 */
57 static ether_addr_st etherbroadcastaddr =
58 {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}};
59 /*
60 * Ethernet zero address definition.
61 */
62 static ether_addr_st etherzeroaddr =
63 {{0x0, 0x0, 0x0, 0x0, 0x0, 0x0}};
64 /*
65 * Supported chip types
66 */
67 static uint32_t nxge_supported_cl45_ids[] = {
68 BCM8704_DEV_ID,
69 MARVELL_88X_201X_DEV_ID,
70 BCM8706_DEV_ID,
71 TN1010_DEV_ID
72 };
73
74 static uint32_t nxge_supported_cl22_ids[] = {
75 BCM5464R_PHY_ID,
76 BCM5482_PHY_ID
77 };
78
79 #define NUM_CLAUSE_45_IDS (sizeof (nxge_supported_cl45_ids) / \
80 sizeof (uint32_t))
81 #define NUM_CLAUSE_22_IDS (sizeof (nxge_supported_cl22_ids) / \
82 sizeof (uint32_t))
83 /*
84 * static functions
85 */
86 static uint32_t nxge_get_cl45_pma_pmd_id(p_nxge_t, int);
87 static uint32_t nxge_get_cl45_pcs_id(p_nxge_t, int);
88 static uint32_t nxge_get_cl22_phy_id(p_nxge_t, int);
89 static boolean_t nxge_is_supported_phy(uint32_t, uint8_t);
90 static boolean_t nxge_hswap_phy_present(p_nxge_t, uint8_t);
91 static boolean_t nxge_is_phy_present(p_nxge_t, int, uint32_t, uint32_t);
92 static nxge_status_t nxge_n2_serdes_init(p_nxge_t);
93 static nxge_status_t nxge_n2_kt_serdes_init(p_nxge_t);
94 static nxge_status_t nxge_neptune_10G_serdes_init(p_nxge_t);
95 static nxge_status_t nxge_1G_serdes_init(p_nxge_t);
96 static nxge_status_t nxge_10G_link_intr_stop(p_nxge_t);
97 static nxge_status_t nxge_10G_link_intr_start(p_nxge_t);
98 static nxge_status_t nxge_1G_copper_link_intr_stop(p_nxge_t);
99 static nxge_status_t nxge_1G_copper_link_intr_start(p_nxge_t);
100 static nxge_status_t nxge_1G_fiber_link_intr_stop(p_nxge_t);
101 static nxge_status_t nxge_1G_fiber_link_intr_start(p_nxge_t);
102 static nxge_status_t nxge_check_mii_link(p_nxge_t);
103 static nxge_status_t nxge_check_10g_link(p_nxge_t);
104 static nxge_status_t nxge_10G_xcvr_init(p_nxge_t);
105 static nxge_status_t nxge_BCM8704_xcvr_init(p_nxge_t);
106 static nxge_status_t nxge_BCM8706_xcvr_init(p_nxge_t);
107 static nxge_status_t nxge_1G_xcvr_init(p_nxge_t);
108 static void nxge_bcm5464_link_led_off(p_nxge_t);
109 static nxge_status_t nxge_check_mrvl88x2011_link(p_nxge_t, boolean_t *);
110 static nxge_status_t nxge_mrvl88x2011_xcvr_init(p_nxge_t);
111 static nxge_status_t nxge_check_nlp2020_link(p_nxge_t, boolean_t *);
112 static nxge_status_t nxge_nlp2020_xcvr_init(p_nxge_t);
113 static int nxge_nlp2020_i2c_read(p_nxge_t, uint8_t, uint16_t, uint16_t,
114 uint8_t *);
115 static boolean_t nxge_is_nlp2020_phy(p_nxge_t);
116 static uint8_t nxge_get_nlp2020_connector_type(p_nxge_t);
117 static nxge_status_t nxge_set_nlp2020_param(p_nxge_t);
118 static nxge_status_t nxge_get_num_of_xaui(uint32_t *port_pma_pmd_dev_id,
119 uint32_t *port_pcs_dev_id, uint32_t *port_phy_id, uint8_t *num_xaui);
120 static nxge_status_t nxge_get_tn1010_speed(p_nxge_t nxgep, uint16_t *speed);
121 static nxge_status_t nxge_set_tn1010_param(p_nxge_t nxgep);
122 static nxge_status_t nxge_tn1010_check(p_nxge_t nxgep,
123 nxge_link_state_t *link_up);
124 static boolean_t nxge_is_tn1010_phy(p_nxge_t nxgep);
125 static nxge_status_t nxge_tn1010_xcvr_init(p_nxge_t nxgep);
126
127 nxge_status_t nxge_mac_init(p_nxge_t);
128 static nxge_status_t nxge_mii_get_link_mode(p_nxge_t);
129
130 #ifdef NXGE_DEBUG
131 static void nxge_mii_dump(p_nxge_t);
132 static nxge_status_t nxge_tn1010_reset(p_nxge_t nxgep);
133 static void nxge_dump_tn1010_status_regs(p_nxge_t nxgep);
134 #endif
135
136 /*
137 * xcvr tables for supported transceivers
138 */
139
140 /*
141 * nxge_n2_10G_table is for 10G fiber or serdes on N2-NIU systems.
142 * The Teranetics TN1010 based copper XAUI card can also be used
143 * on N2-NIU systems in 10G mode, but it uses its own table
144 * nxge_n2_10G_tn1010_table below.
145 */
146 static nxge_xcvr_table_t nxge_n2_10G_table = {
147 nxge_n2_serdes_init,
148 nxge_10G_xcvr_init,
149 nxge_10G_link_intr_stop,
150 nxge_10G_link_intr_start,
151 nxge_check_10g_link,
152 PCS_XCVR
153 };
154
155 /*
156 * For the Teranetics TN1010 based copper XAUI card
157 */
158 static nxge_xcvr_table_t nxge_n2_10G_tn1010_table = {
159 nxge_n2_serdes_init, /* Handle both 1G and 10G */
160 nxge_tn1010_xcvr_init, /* Handle both 1G and 10G */
161 nxge_10G_link_intr_stop,
162 nxge_10G_link_intr_start,
163 nxge_check_tn1010_link, /* Will figure out speed */
164 XPCS_XCVR
165 };
166
167 static nxge_xcvr_table_t nxge_n2_1G_table = {
168 nxge_n2_serdes_init,
169 nxge_1G_xcvr_init,
170 nxge_1G_fiber_link_intr_stop,
171 nxge_1G_fiber_link_intr_start,
172 nxge_check_mii_link,
173 PCS_XCVR
174 };
175
176 static nxge_xcvr_table_t nxge_n2_1G_tn1010_table = {
177 nxge_n2_serdes_init,
178 nxge_tn1010_xcvr_init,
179 nxge_1G_fiber_link_intr_stop, /* TN1010 is a Cu PHY, but it uses */
180 nxge_1G_fiber_link_intr_start, /* PCS for 1G, so call fiber func */
181 nxge_check_tn1010_link,
182 PCS_XCVR
183 };
184
185 static nxge_xcvr_table_t nxge_10G_tn1010_table = {
186 nxge_neptune_10G_serdes_init,
187 nxge_tn1010_xcvr_init,
188 nxge_10G_link_intr_stop,
189 nxge_10G_link_intr_start,
190 nxge_check_tn1010_link,
191 XPCS_XCVR
192 };
193
194 static nxge_xcvr_table_t nxge_1G_tn1010_table = {
195 nxge_1G_serdes_init,
196 nxge_tn1010_xcvr_init,
197 nxge_1G_fiber_link_intr_stop,
198 nxge_1G_fiber_link_intr_start,
199 nxge_check_tn1010_link,
200 PCS_XCVR
201 };
202
203 static nxge_xcvr_table_t nxge_10G_fiber_table = {
204 nxge_neptune_10G_serdes_init,
205 nxge_10G_xcvr_init,
206 nxge_10G_link_intr_stop,
207 nxge_10G_link_intr_start,
208 nxge_check_10g_link,
209 PCS_XCVR
210 };
211
212 static nxge_xcvr_table_t nxge_1G_copper_table = {
213 NULL,
214 nxge_1G_xcvr_init,
215 nxge_1G_copper_link_intr_stop,
216 nxge_1G_copper_link_intr_start,
217 nxge_check_mii_link,
218 INT_MII_XCVR
219 };
220
221 /* This table is for Neptune portmode == PORT_1G_SERDES cases */
222 static nxge_xcvr_table_t nxge_1G_fiber_table = {
223 nxge_1G_serdes_init,
224 nxge_1G_xcvr_init,
225 nxge_1G_fiber_link_intr_stop,
226 nxge_1G_fiber_link_intr_start,
227 nxge_check_mii_link,
228 PCS_XCVR
229 };
230
231 static nxge_xcvr_table_t nxge_10G_copper_table = {
232 nxge_neptune_10G_serdes_init,
233 NULL,
234 NULL,
235 NULL,
236 NULL,
237 PCS_XCVR
238 };
239
240 /*
241 * NXGE_PORT_TN1010 is defined as,
242 * NXGE_PORT_SPD_NONE | (NXGE_PHY_TN1010 << NXGE_PHY_SHIFT)
243 * = 0 | 5 << 16 = 0x50000
244 *
245 * So NEPTUNE_2_TN1010 =
246 * (NXGE_PORT_TN1010 |
247 * (NXGE_PORT_TN1010 << 4) |
248 * (NXGE_PORT_NONE << 8) |
249 * (NXGE_PORT_NONE << 12)),
250 * = 0x50000 | (0x50000 << 4)
251 * = 0x550000
252 *
253 * This function partitions nxgep->nxge_hw_p->niu_type (which may have
254 * value NEPTUNE_2_TN1010) and checks if a port has type = NXGE_PORT_TN1010
255 * = 0x50000
256 */
nxge_is_tn1010_phy(p_nxge_t nxgep)257 static boolean_t nxge_is_tn1010_phy(p_nxge_t nxgep)
258 {
259 uint8_t portn = NXGE_GET_PORT_NUM(nxgep->function_num);
260
261 if (((nxgep->nxge_hw_p->niu_type >> (NXGE_PORT_TYPE_SHIFT * portn))
262 & NXGE_PHY_MASK) == NXGE_PORT_TN1010) {
263 return (B_TRUE);
264 } else {
265 return (B_FALSE);
266 }
267 }
268
269
270 /*
271 * Figure out nxgep->mac.portmode from nxge.conf, OBP's device properties,
272 * serial EEPROM or VPD if possible. Note that not all systems could get
273 * the portmode information by calling this function. For example, the
274 * Maramba system figures out the portmode information by calling function
275 * nxge_setup_xcvr_table.
276 */
277 nxge_status_t
nxge_get_xcvr_type(p_nxge_t nxgep)278 nxge_get_xcvr_type(p_nxge_t nxgep)
279 {
280 nxge_status_t status = NXGE_OK;
281 char *phy_type;
282 char *prop_val;
283 uint8_t portn = NXGE_GET_PORT_NUM(nxgep->function_num);
284 uint32_t val;
285 npi_status_t rs;
286
287 /* For Opus NEM, skip xcvr checking if 10G Serdes link is up */
288 if (nxgep->mac.portmode == PORT_10G_SERDES &&
289 nxgep->statsp->mac_stats.link_up) {
290 nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
291 return (status);
292 }
293
294 nxgep->mac.portmode = 0;
295 nxgep->xcvr_addr = 0;
296
297 /*
298 * First check for hot swappable phy property.
299 */
300 if (nxgep->hot_swappable_phy == B_TRUE) {
301 nxgep->statsp->mac_stats.xcvr_inuse = HSP_XCVR;
302 nxgep->mac.portmode = PORT_HSP_MODE;
303 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Other: Hot Swappable"));
304 } else if (ddi_prop_exists(DDI_DEV_T_ANY, nxgep->dip,
305 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM,
306 "hot-swappable-phy") == 1) {
307 nxgep->statsp->mac_stats.xcvr_inuse = HSP_XCVR;
308 nxgep->mac.portmode = PORT_HSP_MODE;
309 NXGE_DEBUG_MSG((nxgep, MAC_CTL, ".conf: Hot Swappable"));
310 } else if (nxgep->niu_type == N2_NIU &&
311 ddi_prop_exists(DDI_DEV_T_ANY, nxgep->dip, 0,
312 "hot-swappable-phy") == 1) {
313 nxgep->statsp->mac_stats.xcvr_inuse = HSP_XCVR;
314 nxgep->mac.portmode = PORT_HSP_MODE;
315 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "OBP: Hot Swappable"));
316 }
317
318 /*
319 * MDIO polling support for Monza RTM card, Goa NEM card
320 */
321 if (nxgep->mac.portmode == PORT_HSP_MODE) {
322 nxgep->hot_swappable_phy = B_TRUE;
323 if (portn > 1) {
324 return (NXGE_ERROR);
325 }
326
327 if (nxge_hswap_phy_present(nxgep, portn))
328 goto found_phy;
329
330 nxgep->phy_absent = B_TRUE;
331
332 /* Check Serdes link to detect Opus NEM */
333 rs = npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
334 XPCS_REG_STATUS, &val);
335
336 if (rs == 0 && val & XPCS_STATUS_LANE_ALIGN) {
337 nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
338 nxgep->mac.portmode = PORT_10G_SERDES;
339 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
340 "HSP 10G Serdes FOUND!!"));
341 }
342 goto check_phy_done;
343 found_phy:
344 nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
345 nxgep->mac.portmode = PORT_10G_FIBER;
346 nxgep->phy_absent = B_FALSE;
347 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "10G Fiber Xcvr "
348 "found for hot swappable phy"));
349 check_phy_done:
350 return (status);
351 }
352
353 /* Get phy-type property (May have been set by nxge.conf) */
354 if ((ddi_prop_lookup_string(DDI_DEV_T_ANY, nxgep->dip,
355 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM,
356 "phy-type", &prop_val)) == DDI_PROP_SUCCESS) {
357 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
358 "found conf file: phy-type %s", prop_val));
359 if (strcmp("xgsd", prop_val) == 0) {
360 nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
361 nxgep->mac.portmode = PORT_10G_SERDES;
362 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
363 "found: 10G Serdes"));
364 } else if (strcmp("gsd", prop_val) == 0) {
365 nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR;
366 nxgep->mac.portmode = PORT_1G_SERDES;
367 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G Serdes"));
368 } else if (strcmp("mif", prop_val) == 0) {
369 nxgep->statsp->mac_stats.xcvr_inuse = INT_MII_XCVR;
370 nxgep->mac.portmode = PORT_1G_COPPER;
371 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G Copper Xcvr"));
372 } else if (strcmp("pcs", prop_val) == 0) {
373 nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR;
374 nxgep->mac.portmode = PORT_1G_FIBER;
375 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G FIBER Xcvr"));
376 } else if (strcmp("xgf", prop_val) == 0) {
377 /*
378 * Before OBP supports new phy-type property
379 * value "xgc", the 10G copper XAUI may carry
380 * "xgf" instead of "xgc". If the OBP is
381 * upgraded to a newer version which supports
382 * "xgc", then the TN1010 related code in this
383 * "xgf" case will not be used anymore.
384 */
385 if (nxge_is_tn1010_phy(nxgep)) {
386 if ((status = nxge_set_tn1010_param(nxgep))
387 != NXGE_OK) {
388 return (status);
389 }
390 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "TN1010 Xcvr"));
391 } else { /* For Fiber XAUI */
392 nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
393 nxgep->mac.portmode = PORT_10G_FIBER;
394 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
395 "10G Fiber Xcvr"));
396 }
397 } else if (strcmp("xgc", prop_val) == 0) {
398 if ((status = nxge_set_tn1010_param(nxgep)) != NXGE_OK)
399 return (status);
400 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "TN1010 Xcvr"));
401 }
402
403 (void) ddi_prop_update_string(DDI_DEV_T_NONE, nxgep->dip,
404 "phy-type", prop_val);
405 ddi_prop_free(prop_val);
406
407 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_get_xcvr_type: "
408 "Got phy type [0x%x] from conf file",
409 nxgep->mac.portmode));
410
411 return (NXGE_OK);
412 }
413
414 /* Get phy-type property from OBP */
415 if (nxgep->niu_type == N2_NIU) {
416 if (ddi_prop_lookup_string(DDI_DEV_T_ANY, nxgep->dip, 0,
417 "phy-type", &prop_val) == DDI_PROP_SUCCESS) {
418 if (strcmp("xgf", prop_val) == 0) {
419 /*
420 * Before OBP supports new phy-type property
421 * value "xgc", the 10G copper XAUI may carry
422 * "xgf" instead of "xgc". If the OBP is
423 * upgraded to a newer version which supports
424 * "xgc", then the TN1010 related code in this
425 * "xgf" case will not be used anymore.
426 */
427 if (nxge_is_tn1010_phy(nxgep)) {
428 if ((status =
429 nxge_set_tn1010_param(nxgep))
430 != NXGE_OK) {
431 return (status);
432 }
433 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
434 "TN1010 Xcvr"));
435 } else if (nxge_is_nlp2020_phy(nxgep)) {
436 if ((status =
437 nxge_set_nlp2020_param(nxgep))
438 != NXGE_OK) {
439 return (status);
440 }
441 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
442 "NLP2020 Xcvr"));
443 } else { /* For Fiber XAUI */
444 nxgep->statsp->mac_stats.xcvr_inuse
445 = XPCS_XCVR;
446 nxgep->mac.portmode = PORT_10G_FIBER;
447 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
448 "10G Fiber Xcvr"));
449 }
450 } else if (strcmp("mif", prop_val) == 0) {
451 nxgep->statsp->mac_stats.xcvr_inuse =
452 INT_MII_XCVR;
453 nxgep->mac.portmode = PORT_1G_COPPER;
454 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
455 "1G Copper Xcvr"));
456 } else if (strcmp("pcs", prop_val) == 0) {
457 nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR;
458 nxgep->mac.portmode = PORT_1G_FIBER;
459 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
460 "1G Fiber Xcvr"));
461 } else if (strcmp("xgc", prop_val) == 0) {
462 status = nxge_set_tn1010_param(nxgep);
463 if (status != NXGE_OK)
464 return (status);
465 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "TN1010 Xcvr"));
466 } else if (strcmp("xgsd", prop_val) == 0) {
467 nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
468 nxgep->mac.portmode = PORT_10G_SERDES;
469 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
470 "OBP: 10G Serdes"));
471 } else if (strcmp("gsd", prop_val) == 0) {
472 nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR;
473 nxgep->mac.portmode = PORT_1G_SERDES;
474 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
475 "OBP: 1G Serdes"));
476 } else {
477 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
478 "Unknown phy-type: %s", prop_val));
479 ddi_prop_free(prop_val);
480 return (NXGE_ERROR);
481 }
482 status = NXGE_OK;
483 (void) ddi_prop_update_string(DDI_DEV_T_NONE,
484 nxgep->dip, "phy-type", prop_val);
485 ddi_prop_free(prop_val);
486
487 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_get_xcvr_type: "
488 "Got phy type [0x%x] from OBP",
489 nxgep->mac.portmode));
490
491 return (status);
492 } else {
493 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
494 "Exiting...phy-type property not found"));
495 return (NXGE_ERROR);
496 }
497 }
498
499
500 if (!nxgep->vpd_info.present) {
501 return (NXGE_OK);
502 }
503
504 if (!nxgep->vpd_info.ver_valid) {
505 goto read_seeprom;
506 }
507
508 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
509 "Reading phy type from expansion ROM"));
510 /*
511 * Try to read the phy type from the vpd data read off the
512 * expansion ROM.
513 */
514 phy_type = nxgep->vpd_info.phy_type;
515
516 if (strncmp(phy_type, "mif", 3) == 0) {
517 nxgep->mac.portmode = PORT_1G_COPPER;
518 nxgep->statsp->mac_stats.xcvr_inuse = INT_MII_XCVR;
519 } else if (strncmp(phy_type, "xgf", 3) == 0) {
520 nxgep->mac.portmode = PORT_10G_FIBER;
521 nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
522 } else if (strncmp(phy_type, "pcs", 3) == 0) {
523 nxgep->mac.portmode = PORT_1G_FIBER;
524 nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR;
525 } else if (strncmp(phy_type, "xgc", 3) == 0) {
526 status = nxge_set_tn1010_param(nxgep);
527 if (status != NXGE_OK) {
528 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
529 "nxge_get_xcvr_type: Failed to set TN1010 param"));
530 goto read_seeprom;
531 }
532 } else if (strncmp(phy_type, "xgsd", 4) == 0) {
533 nxgep->mac.portmode = PORT_10G_SERDES;
534 nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
535 } else if (strncmp(phy_type, "gsd", 3) == 0) {
536 nxgep->mac.portmode = PORT_1G_SERDES;
537 nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR;
538 } else {
539 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
540 "nxge_get_xcvr_type: Unknown phy type [%c%c%c] in EEPROM",
541 phy_type[0], phy_type[1], phy_type[2]));
542 goto read_seeprom;
543 }
544
545 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_get_xcvr_type: "
546 "Got phy type [0x%x] from VPD", nxgep->mac.portmode));
547
548 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_get_xcvr_type"));
549 return (status);
550
551 read_seeprom:
552 /*
553 * read the phy type from the SEEPROM - NCR registers
554 */
555 status = nxge_espc_phy_type_get(nxgep);
556 if (status != NXGE_OK) {
557 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
558 "Failed to get phy type"));
559 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "EEPROM version "
560 "[%s] invalid...please update", nxgep->vpd_info.ver));
561 }
562
563 return (status);
564
565 }
566
567 /* Set up the PHY specific values. */
568
569 nxge_status_t
nxge_setup_xcvr_table(p_nxge_t nxgep)570 nxge_setup_xcvr_table(p_nxge_t nxgep)
571 {
572 nxge_status_t status = NXGE_OK;
573 uint32_t port_type;
574 uint8_t portn = NXGE_GET_PORT_NUM(nxgep->function_num);
575 uint32_t pcs_id = 0;
576 uint32_t pma_pmd_id = 0;
577 uint32_t phy_id = 0;
578 uint16_t chip_id = 0;
579
580 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_setup_xcvr_table: port<%d>",
581 portn));
582
583 switch (nxgep->niu_type) {
584 case N2_NIU:
585 switch (nxgep->mac.portmode) {
586 case PORT_1G_FIBER:
587 case PORT_1G_SERDES:
588 nxgep->xcvr = nxge_n2_1G_table;
589 nxgep->xcvr_addr = portn;
590 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "NIU 1G %s Xcvr",
591 (nxgep->mac.portmode == PORT_1G_FIBER) ? "Fiber" :
592 "Serdes"));
593 break;
594 case PORT_10G_FIBER:
595 case PORT_10G_COPPER:
596 case PORT_10G_SERDES:
597 nxgep->xcvr = nxge_n2_10G_table;
598 if (nxgep->nxge_hw_p->xcvr_addr[portn]) {
599 nxgep->xcvr_addr =
600 nxgep->nxge_hw_p->xcvr_addr[portn];
601 }
602 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "NIU 10G %s Xcvr",
603 (nxgep->mac.portmode == PORT_10G_FIBER) ? "Fiber" :
604 ((nxgep->mac.portmode == PORT_10G_COPPER) ?
605 "Copper" : "Serdes")));
606 break;
607 case PORT_1G_TN1010:
608 nxgep->xcvr = nxge_n2_1G_tn1010_table;
609 nxgep->xcvr_addr = nxgep->nxge_hw_p->xcvr_addr[portn];
610 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
611 "TN1010 Copper Xcvr in 1G"));
612 break;
613 case PORT_10G_TN1010:
614 nxgep->xcvr = nxge_n2_10G_tn1010_table;
615 nxgep->xcvr_addr = nxgep->nxge_hw_p->xcvr_addr[portn];
616 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
617 "TN1010 Copper Xcvr in 10G"));
618 break;
619 case PORT_HSP_MODE:
620 nxgep->xcvr = nxge_n2_10G_table;
621 nxgep->xcvr.xcvr_inuse = HSP_XCVR;
622 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "NIU 10G Hot "
623 "Swappable Xcvr (not present)"));
624 break;
625 default:
626 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
627 "<== nxge_setup_xcvr_table: "
628 "Unable to determine NIU portmode"));
629 return (NXGE_ERROR);
630 }
631 break;
632 default:
633 if (nxgep->mac.portmode == 0) {
634 /*
635 * Would be the case for platforms like Maramba
636 * in which the phy type could not be got from conf
637 * file, OBP, VPD or Serial PROM.
638 */
639 if (!NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) {
640 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
641 "<== nxge_setup_xcvr_table:"
642 " Invalid Neptune type [0x%x]",
643 nxgep->niu_type));
644 return (NXGE_ERROR);
645 }
646
647 port_type = nxgep->niu_type >>
648 (NXGE_PORT_TYPE_SHIFT * portn);
649 port_type = port_type & (NXGE_PORT_TYPE_MASK);
650
651 switch (port_type) {
652
653 case NXGE_PORT_1G_COPPER:
654 nxgep->mac.portmode = PORT_1G_COPPER;
655 break;
656 case NXGE_PORT_10G_COPPER:
657 nxgep->mac.portmode = PORT_10G_COPPER;
658 break;
659 case NXGE_PORT_1G_FIBRE:
660 nxgep->mac.portmode = PORT_1G_FIBER;
661 break;
662 case NXGE_PORT_10G_FIBRE:
663 nxgep->mac.portmode = PORT_10G_FIBER;
664 break;
665 case NXGE_PORT_1G_SERDES:
666 nxgep->mac.portmode = PORT_1G_SERDES;
667 break;
668 case NXGE_PORT_10G_SERDES:
669 nxgep->mac.portmode = PORT_10G_SERDES;
670 break;
671 /* Ports 2 and 3 of Alonso or ARTM */
672 case NXGE_PORT_1G_RGMII_FIBER:
673 nxgep->mac.portmode = PORT_1G_RGMII_FIBER;
674 break;
675 case NXGE_PORT_TN1010:
676 /*
677 * If this port uses the TN1010 copper
678 * PHY, then its speed is not known yet
679 * because nxge_scan_ports_phy could only
680 * figure out the vendor of the PHY but
681 * not its speed. nxge_set_tn1010_param
682 * will read the PHY speed and set
683 * portmode accordingly.
684 */
685 if ((status = nxge_set_tn1010_param(nxgep))
686 != NXGE_OK) {
687 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
688 "nxge_set_tn1010_param failed"));
689 return (status);
690 }
691 break;
692 default:
693 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
694 "<== nxge_setup_xcvr_table: "
695 "Unknown port-type: 0x%x", port_type));
696 return (NXGE_ERROR);
697 }
698 }
699
700 /*
701 * Above switch has figured out nxge->mac.portmode, now set
702 * nxgep->xcvr (the table) and nxgep->xcvr_addr according
703 * to portmode.
704 */
705 switch (nxgep->mac.portmode) {
706 case PORT_1G_COPPER:
707 case PORT_1G_RGMII_FIBER:
708 nxgep->xcvr = nxge_1G_copper_table;
709 nxgep->xcvr_addr = nxgep->nxge_hw_p->xcvr_addr[portn];
710 /*
711 * For Altas 4-1G copper, Xcvr port numbers are
712 * swapped with ethernet port number. This is
713 * designed for better signal integrity in
714 * routing. This is also the case for the
715 * on-board Neptune copper ports on the Maramba
716 * platform.
717 */
718 switch (nxgep->platform_type) {
719 case P_NEPTUNE_ATLAS_4PORT:
720 case P_NEPTUNE_MARAMBA_P0:
721 case P_NEPTUNE_MARAMBA_P1:
722 switch (portn) {
723 case 0:
724 nxgep->xcvr_addr += 3;
725 break;
726 case 1:
727 nxgep->xcvr_addr += 1;
728 break;
729 case 2:
730 nxgep->xcvr_addr -= 1;
731 break;
732 case 3:
733 nxgep->xcvr_addr -= 3;
734 break;
735 default:
736 return (NXGE_ERROR);
737 }
738 break;
739 default:
740 break;
741 }
742
743 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G %s Xcvr",
744 (nxgep->mac.portmode == PORT_1G_COPPER) ?
745 "Copper" : "RGMII Fiber"));
746 break;
747
748 case PORT_10G_COPPER:
749 nxgep->xcvr = nxge_10G_copper_table;
750 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "10G Copper Xcvr"));
751 break;
752
753 case PORT_1G_TN1010:
754 nxgep->xcvr = nxge_1G_tn1010_table;
755 nxgep->xcvr_addr = nxgep->nxge_hw_p->xcvr_addr[portn];
756 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
757 "1G TN1010 copper Xcvr"));
758 break;
759
760 case PORT_10G_TN1010:
761 nxgep->xcvr = nxge_10G_tn1010_table;
762 nxgep->xcvr_addr = nxgep->nxge_hw_p->xcvr_addr[portn];
763 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
764 "10G TN1010 copper Xcvr"));
765 break;
766
767 case PORT_1G_FIBER:
768 case PORT_1G_SERDES:
769 nxgep->xcvr = nxge_1G_fiber_table;
770 nxgep->xcvr_addr = portn;
771 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G %s Xcvr",
772 (nxgep->mac.portmode == PORT_1G_FIBER) ?
773 "Fiber" : "Serdes"));
774 break;
775 case PORT_10G_FIBER:
776 case PORT_10G_SERDES:
777 nxgep->xcvr = nxge_10G_fiber_table;
778 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "10G xcvr "
779 "nxgep->nxge_hw_p->xcvr_addr[portn] = [%d] "
780 "nxgep->xcvr_addr = [%d]",
781 nxgep->nxge_hw_p->xcvr_addr[portn],
782 nxgep->xcvr_addr));
783 if (nxgep->nxge_hw_p->xcvr_addr[portn]) {
784 nxgep->xcvr_addr =
785 nxgep->nxge_hw_p->xcvr_addr[portn];
786 }
787 switch (nxgep->platform_type) {
788 case P_NEPTUNE_MARAMBA_P0:
789 case P_NEPTUNE_MARAMBA_P1:
790 /*
791 * Switch off LED for corresponding copper
792 * port
793 */
794 nxge_bcm5464_link_led_off(nxgep);
795 break;
796 default:
797 break;
798 }
799 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "10G %s Xcvr",
800 (nxgep->mac.portmode == PORT_10G_FIBER) ?
801 "Fiber" : "Serdes"));
802 break;
803
804 case PORT_HSP_MODE:
805 nxgep->xcvr = nxge_10G_fiber_table;
806 nxgep->xcvr.xcvr_inuse = HSP_XCVR;
807 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Neptune 10G Hot "
808 "Swappable Xcvr (not present)"));
809 break;
810 default:
811 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
812 "Unknown port-type: 0x%x", port_type));
813 return (NXGE_ERROR);
814 }
815 }
816
817 if (nxgep->mac.portmode == PORT_10G_FIBER ||
818 nxgep->mac.portmode == PORT_10G_COPPER) {
819 uint32_t pma_pmd_id;
820 pma_pmd_id = nxge_get_cl45_pma_pmd_id(nxgep,
821 nxgep->xcvr_addr);
822 if ((pma_pmd_id & BCM_PHY_ID_MASK) == MARVELL_88X201X_PHY_ID) {
823 chip_id = MRVL88X201X_CHIP_ID;
824 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
825 "nxge_setup_xcvr_table: "
826 "Chip ID MARVELL [0x%x] for 10G xcvr", chip_id));
827 } else if ((pma_pmd_id & NLP2020_DEV_ID_MASK) ==
828 NLP2020_DEV_ID) {
829 chip_id = NLP2020_CHIP_ID;
830 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
831 "nxge_setup_xcvr_table: "
832 "Chip ID AEL2020 [0x%x] for 10G xcvr", chip_id));
833 } else if ((status = nxge_mdio_read(nxgep, nxgep->xcvr_addr,
834 BCM8704_PCS_DEV_ADDR, BCM8704_CHIP_ID_REG,
835 &chip_id)) == NXGE_OK) {
836
837 switch (chip_id) {
838 case BCM8704_CHIP_ID:
839 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
840 "nxge_setup_xcvr_table: "
841 "Chip ID 8704 [0x%x] for 10G xcvr",
842 chip_id));
843 break;
844 case BCM8706_CHIP_ID:
845 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
846 "nxge_setup_xcvr_table: "
847 "Chip ID 8706 [0x%x] for 10G xcvr",
848 chip_id));
849 break;
850 default:
851 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
852 "nxge_setup_xcvr_table: "
853 "Unknown Chip ID [0x%x] for 10G xcvr",
854 chip_id));
855 break;
856 }
857 }
858 }
859
860 nxgep->statsp->mac_stats.xcvr_inuse = nxgep->xcvr.xcvr_inuse;
861 nxgep->statsp->mac_stats.xcvr_portn = nxgep->xcvr_addr;
862 nxgep->chip_id = chip_id;
863
864 /*
865 * Get the actual device ID value returned by MDIO read.
866 */
867 nxgep->statsp->mac_stats.xcvr_id = 0;
868
869 pma_pmd_id = nxge_get_cl45_pma_pmd_id(nxgep, nxgep->xcvr_addr);
870 if (nxge_is_supported_phy(pma_pmd_id, CLAUSE_45_TYPE)) {
871 nxgep->statsp->mac_stats.xcvr_id = pma_pmd_id;
872 } else {
873 pcs_id = nxge_get_cl45_pcs_id(nxgep, nxgep->xcvr_addr);
874 if (nxge_is_supported_phy(pcs_id, CLAUSE_45_TYPE)) {
875 nxgep->statsp->mac_stats.xcvr_id = pcs_id;
876 } else {
877 phy_id = nxge_get_cl22_phy_id(nxgep,
878 nxgep->xcvr_addr);
879 if (nxge_is_supported_phy(phy_id, CLAUSE_22_TYPE)) {
880 nxgep->statsp->mac_stats.xcvr_id = phy_id;
881 }
882 }
883 }
884
885 nxgep->mac.linkchkmode = LINKCHK_TIMER;
886
887 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_setup_xcvr_table: niu_type"
888 "[0x%x] platform type[0x%x] xcvr_addr[%d]", nxgep->niu_type,
889 nxgep->platform_type, nxgep->xcvr_addr));
890
891 return (status);
892 }
893
894 /* Initialize the entire MAC and physical layer */
895
896 nxge_status_t
nxge_mac_init(p_nxge_t nxgep)897 nxge_mac_init(p_nxge_t nxgep)
898 {
899 uint8_t portn;
900 nxge_status_t status = NXGE_OK;
901 portn = NXGE_GET_PORT_NUM(nxgep->function_num);
902
903 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mac_init: port<%d>", portn));
904
905 nxgep->mac.portnum = portn;
906 nxgep->mac.porttype = PORT_TYPE_XMAC;
907
908 if ((portn == BMAC_PORT_0) || (portn == BMAC_PORT_1))
909 nxgep->mac.porttype = PORT_TYPE_BMAC;
910
911
912 /* Initialize XIF to configure a network mode */
913 if ((status = nxge_xif_init(nxgep)) != NXGE_OK) {
914 goto fail;
915 }
916
917 if ((status = nxge_pcs_init(nxgep)) != NXGE_OK) {
918 goto fail;
919 }
920
921 /* Initialize TX and RX MACs */
922 /*
923 * Always perform XIF init first, before TX and RX MAC init
924 */
925 if ((status = nxge_tx_mac_reset(nxgep)) != NXGE_OK)
926 goto fail;
927
928 if ((status = nxge_tx_mac_init(nxgep)) != NXGE_OK)
929 goto fail;
930
931 if ((status = nxge_rx_mac_reset(nxgep)) != NXGE_OK)
932 goto fail;
933
934 if ((status = nxge_rx_mac_init(nxgep)) != NXGE_OK)
935 goto fail;
936
937 if ((status = nxge_tx_mac_enable(nxgep)) != NXGE_OK)
938 goto fail;
939
940 if (nxgep->nxge_mac_state == NXGE_MAC_STARTED) {
941 if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK)
942 goto fail;
943 }
944
945 /* Initialize MAC control configuration */
946 if ((status = nxge_mac_ctrl_init(nxgep)) != NXGE_OK) {
947 goto fail;
948 }
949
950 nxgep->statsp->mac_stats.mac_mtu = nxgep->mac.maxframesize;
951
952 /* The Neptune Serdes needs to be reinitialized again */
953 if ((NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) &&
954 ((nxgep->mac.portmode == PORT_1G_SERDES) ||
955 (nxgep->mac.portmode == PORT_1G_TN1010) ||
956 (nxgep->mac.portmode == PORT_1G_FIBER)) &&
957 ((portn == 0) || (portn == 1))) {
958 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
959 "nxge_mac_init: reinit Neptune 1G Serdes "));
960 if ((status = nxge_1G_serdes_init(nxgep)) != NXGE_OK) {
961 goto fail;
962 }
963 }
964
965
966 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_mac_init: port<%d>", portn));
967
968 return (NXGE_OK);
969 fail:
970 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
971 "nxge_mac_init: failed to initialize MAC port<%d>", portn));
972 return (status);
973 }
974
975 /* Initialize the Ethernet Link */
976
977 nxge_status_t
nxge_link_init(p_nxge_t nxgep)978 nxge_link_init(p_nxge_t nxgep)
979 {
980 nxge_status_t status = NXGE_OK;
981 nxge_port_mode_t portmode;
982 #ifdef NXGE_DEBUG
983 uint8_t portn;
984
985 portn = nxgep->mac.portnum;
986
987 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_init: port<%d>", portn));
988 #endif
989 /* For Opus NEM, Serdes always needs to be initialized */
990
991 portmode = nxgep->mac.portmode;
992
993 /*
994 * Workaround to get link up in both NIU ports. Some portmodes require
995 * that the xcvr be initialized twice, the first time before calling
996 * nxge_serdes_init.
997 */
998 if (nxgep->niu_type == N2_NIU && (portmode != PORT_10G_SERDES) &&
999 (portmode != PORT_10G_TN1010) &&
1000 (portmode != PORT_1G_TN1010) &&
1001 (portmode != PORT_1G_SERDES)) {
1002 if ((status = nxge_xcvr_init(nxgep)) != NXGE_OK) {
1003 goto fail;
1004 }
1005 }
1006
1007 NXGE_DELAY(200000);
1008 /* Initialize internal serdes */
1009 if ((status = nxge_serdes_init(nxgep)) != NXGE_OK)
1010 goto fail;
1011 NXGE_DELAY(200000);
1012 if ((status = nxge_xcvr_init(nxgep)) != NXGE_OK)
1013 goto fail;
1014
1015 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_init: port<%d>", portn));
1016
1017 return (NXGE_OK);
1018
1019 fail:
1020 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_link_init: ",
1021 "failed to initialize Ethernet link on port<%d>", portn));
1022
1023 return (status);
1024 }
1025
1026
1027 /* Initialize the XIF sub-block within the MAC */
1028
1029 nxge_status_t
nxge_xif_init(p_nxge_t nxgep)1030 nxge_xif_init(p_nxge_t nxgep)
1031 {
1032 uint32_t xif_cfg = 0;
1033 npi_attr_t ap;
1034 uint8_t portn;
1035 nxge_port_t portt;
1036 nxge_port_mode_t portmode;
1037 p_nxge_stats_t statsp;
1038 npi_status_t rs = NPI_SUCCESS;
1039 npi_handle_t handle;
1040
1041 portn = NXGE_GET_PORT_NUM(nxgep->function_num);
1042
1043 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xif_init: port<%d>", portn));
1044
1045 handle = nxgep->npi_handle;
1046 portmode = nxgep->mac.portmode;
1047 portt = nxgep->mac.porttype;
1048 statsp = nxgep->statsp;
1049
1050 if ((NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) &&
1051 ((nxgep->mac.portmode == PORT_1G_SERDES) ||
1052 (nxgep->mac.portmode == PORT_1G_TN1010) ||
1053 (nxgep->mac.portmode == PORT_1G_FIBER)) &&
1054 ((portn == 0) || (portn == 1))) {
1055 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1056 "nxge_xcvr_init: set ATCA mode"));
1057 npi_mac_mif_set_atca_mode(nxgep->npi_handle, B_TRUE);
1058 }
1059
1060 if (portt == PORT_TYPE_XMAC) {
1061
1062 /* Setup XIF Configuration for XMAC */
1063
1064 if ((portmode == PORT_10G_FIBER) ||
1065 (portmode == PORT_10G_COPPER) ||
1066 (portmode == PORT_10G_TN1010) ||
1067 (portmode == PORT_HSP_MODE) ||
1068 (portmode == PORT_10G_SERDES))
1069 xif_cfg |= CFG_XMAC_XIF_LFS;
1070
1071 /* Bypass PCS so that RGMII will be used */
1072 if (portmode == PORT_1G_COPPER) {
1073 xif_cfg |= CFG_XMAC_XIF_1G_PCS_BYPASS;
1074 }
1075
1076 /* Set MAC Internal Loopback if necessary */
1077 if (statsp->port_stats.lb_mode == nxge_lb_mac1000)
1078 xif_cfg |= CFG_XMAC_XIF_LOOPBACK;
1079
1080 if (statsp->mac_stats.link_speed == 100)
1081 xif_cfg |= CFG_XMAC_XIF_SEL_CLK_25MHZ;
1082
1083 xif_cfg |= CFG_XMAC_XIF_TX_OUTPUT;
1084
1085 if ((portmode == PORT_10G_FIBER) ||
1086 (portmode == PORT_10G_COPPER) ||
1087 (portmode == PORT_10G_TN1010) ||
1088 (portmode == PORT_1G_TN1010) ||
1089 (portmode == PORT_HSP_MODE) ||
1090 (portmode == PORT_10G_SERDES)) {
1091 /* Assume LED same for 1G and 10G */
1092 if (statsp->mac_stats.link_up) {
1093 xif_cfg |= CFG_XMAC_XIF_LED_POLARITY;
1094 } else {
1095 xif_cfg |= CFG_XMAC_XIF_LED_FORCE;
1096 }
1097 }
1098
1099 rs = npi_xmac_xif_config(handle, INIT, portn, xif_cfg);
1100 if (rs != NPI_SUCCESS)
1101 goto fail;
1102
1103 nxgep->mac.xif_config = xif_cfg;
1104
1105 /* Set Port Mode */
1106 if ((portmode == PORT_10G_FIBER) ||
1107 (portmode == PORT_10G_COPPER) ||
1108 (portmode == PORT_10G_TN1010) ||
1109 (portmode == PORT_HSP_MODE) ||
1110 (portmode == PORT_10G_SERDES)) {
1111 SET_MAC_ATTR1(handle, ap, portn, MAC_PORT_MODE,
1112 MAC_XGMII_MODE, rs);
1113 if (rs != NPI_SUCCESS)
1114 goto fail;
1115 if (statsp->mac_stats.link_up) {
1116 if (nxge_10g_link_led_on(nxgep) != NXGE_OK)
1117 goto fail;
1118 } else {
1119 if (nxge_10g_link_led_off(nxgep) != NXGE_OK)
1120 goto fail;
1121 }
1122 } else if ((portmode == PORT_1G_FIBER) ||
1123 (portmode == PORT_1G_COPPER) ||
1124 (portmode == PORT_1G_SERDES) ||
1125 (portmode == PORT_1G_TN1010) ||
1126 (portmode == PORT_1G_RGMII_FIBER)) {
1127 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1128 "nxge_xif_init: Port[%d] Mode[%d] Speed[%d]",
1129 portn, portmode, statsp->mac_stats.link_speed));
1130 if (statsp->mac_stats.link_speed == 1000) {
1131 SET_MAC_ATTR1(handle, ap, portn, MAC_PORT_MODE,
1132 MAC_GMII_MODE, rs);
1133 } else {
1134 SET_MAC_ATTR1(handle, ap, portn, MAC_PORT_MODE,
1135 MAC_MII_MODE, rs);
1136 }
1137 if (rs != NPI_SUCCESS)
1138 goto fail;
1139 } else {
1140 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1141 "nxge_xif_init: Unknown port mode (%d)"
1142 " for port<%d>", portmode, portn));
1143 goto fail;
1144 }
1145
1146 /* Enable ATCA mode */
1147
1148 } else if (portt == PORT_TYPE_BMAC) {
1149
1150 /* Setup XIF Configuration for BMAC */
1151
1152 if ((portmode == PORT_1G_COPPER) ||
1153 (portmode == PORT_1G_RGMII_FIBER)) {
1154 if (statsp->mac_stats.link_speed == 100)
1155 xif_cfg |= CFG_BMAC_XIF_SEL_CLK_25MHZ;
1156 }
1157
1158 if (statsp->port_stats.lb_mode == nxge_lb_mac1000)
1159 xif_cfg |= CFG_BMAC_XIF_LOOPBACK;
1160
1161 if (statsp->mac_stats.link_speed == 1000)
1162 xif_cfg |= CFG_BMAC_XIF_GMII_MODE;
1163
1164 xif_cfg |= CFG_BMAC_XIF_TX_OUTPUT;
1165
1166 rs = npi_bmac_xif_config(handle, INIT, portn, xif_cfg);
1167 if (rs != NPI_SUCCESS)
1168 goto fail;
1169 nxgep->mac.xif_config = xif_cfg;
1170 }
1171 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_xif_init: port<%d>", portn));
1172 return (NXGE_OK);
1173 fail:
1174 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1175 "nxge_xif_init: Failed to initialize XIF port<%d>", portn));
1176 return (NXGE_ERROR | rs);
1177 }
1178
1179
1180 /*
1181 * Initialize the PCS sub-block in the MAC. Note that PCS does not
1182 * support loopback like XPCS.
1183 */
1184 nxge_status_t
nxge_pcs_init(p_nxge_t nxgep)1185 nxge_pcs_init(p_nxge_t nxgep)
1186 {
1187 pcs_cfg_t pcs_cfg;
1188 uint32_t val;
1189 uint8_t portn;
1190 nxge_port_mode_t portmode;
1191 npi_handle_t handle;
1192 p_nxge_stats_t statsp;
1193 pcs_ctrl_t pcs_ctrl;
1194 npi_status_t rs = NPI_SUCCESS;
1195 uint8_t i;
1196
1197 handle = nxgep->npi_handle;
1198 portmode = nxgep->mac.portmode;
1199 portn = nxgep->mac.portnum;
1200 statsp = nxgep->statsp;
1201
1202 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_pcs_init: port<%d>", portn));
1203
1204 if (portmode == PORT_1G_FIBER ||
1205 portmode == PORT_1G_TN1010 ||
1206 portmode == PORT_1G_SERDES) {
1207 if (portmode == PORT_1G_TN1010) {
1208 /* Reset PCS multiple time in PORT_1G_TN1010 mode */
1209 for (i = 0; i < 6; i ++) {
1210 if ((rs = npi_mac_pcs_reset(handle, portn))
1211 != NPI_SUCCESS) {
1212 goto fail;
1213 }
1214 }
1215 } else {
1216 if ((rs = npi_mac_pcs_reset(handle, portn))
1217 != NPI_SUCCESS)
1218 goto fail;
1219 }
1220
1221 /* Initialize port's PCS */
1222 pcs_cfg.value = 0;
1223 pcs_cfg.bits.w0.enable = 1;
1224 pcs_cfg.bits.w0.mask = 1;
1225 PCS_REG_WR(handle, portn, PCS_CONFIG_REG, pcs_cfg.value);
1226 PCS_REG_WR(handle, portn, PCS_DATAPATH_MODE_REG, 0);
1227
1228 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1229 "==> nxge_pcs_init: (1G) port<%d> write config 0x%llx",
1230 portn, pcs_cfg.value));
1231
1232 if (portmode == PORT_1G_TN1010) {
1233 /*
1234 * Must disable PCS auto-negotiation when the the driver
1235 * is driving the TN1010 based XAUI card Otherwise the
1236 * autonegotiation between the PCS and the TN1010 PCS
1237 * will never complete and the Neptune/NIU will not work
1238 */
1239 pcs_ctrl.value = 0;
1240 PCS_REG_WR(handle, portn, PCS_MII_CTRL_REG,
1241 pcs_ctrl.value);
1242 }
1243 } else if (portmode == PORT_10G_FIBER ||
1244 portmode == PORT_10G_COPPER ||
1245 portmode == PORT_10G_TN1010 ||
1246 portmode == PORT_HSP_MODE ||
1247 portmode == PORT_10G_SERDES) {
1248 /* Use internal XPCS, bypass 1G PCS */
1249 XMAC_REG_RD(handle, portn, XMAC_CONFIG_REG, &val);
1250 val &= ~XMAC_XIF_XPCS_BYPASS;
1251 XMAC_REG_WR(handle, portn, XMAC_CONFIG_REG, val);
1252
1253 if ((rs = npi_xmac_xpcs_reset(handle, portn)) != NPI_SUCCESS)
1254 goto fail;
1255
1256 /* Set XPCS Internal Loopback if necessary */
1257 if ((rs = npi_xmac_xpcs_read(handle, portn,
1258 XPCS_REG_CONTROL1, &val)) != NPI_SUCCESS)
1259 goto fail;
1260
1261 if ((statsp->port_stats.lb_mode == nxge_lb_mac10g) ||
1262 (statsp->port_stats.lb_mode == nxge_lb_mac1000))
1263 val |= XPCS_CTRL1_LOOPBK;
1264 else
1265 val &= ~XPCS_CTRL1_LOOPBK;
1266 if ((rs = npi_xmac_xpcs_write(handle, portn,
1267 XPCS_REG_CONTROL1, val)) != NPI_SUCCESS)
1268 goto fail;
1269
1270 /* Clear descw errors */
1271 if ((rs = npi_xmac_xpcs_write(handle, portn,
1272 XPCS_REG_DESCWERR_COUNTER, 0)) != NPI_SUCCESS)
1273 goto fail;
1274 /* Clear symbol errors */
1275 if ((rs = npi_xmac_xpcs_read(handle, portn,
1276 XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val)) != NPI_SUCCESS)
1277 goto fail;
1278 if ((rs = npi_xmac_xpcs_read(handle, portn,
1279 XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val)) != NPI_SUCCESS)
1280 goto fail;
1281
1282 } else if ((portmode == PORT_1G_COPPER) ||
1283 (portmode == PORT_1G_RGMII_FIBER)) {
1284 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1285 "==> nxge_pcs_init: (1G) copper port<%d>", portn));
1286 if (portn < 4) {
1287 PCS_REG_WR(handle, portn, PCS_DATAPATH_MODE_REG,
1288 PCS_DATAPATH_MODE_MII);
1289 }
1290 if ((rs = npi_mac_pcs_reset(handle, portn)) != NPI_SUCCESS)
1291 goto fail;
1292
1293 } else {
1294 goto fail;
1295 }
1296 pass:
1297 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_pcs_init: port<%d>", portn));
1298 return (NXGE_OK);
1299 fail:
1300 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1301 "nxge_pcs_init: Failed to initialize PCS port<%d>", portn));
1302 return (NXGE_ERROR | rs);
1303 }
1304
1305 /*
1306 * Initialize the MAC CTRL sub-block within the MAC
1307 * Only the receive-pause-cap is supported.
1308 */
1309 nxge_status_t
nxge_mac_ctrl_init(p_nxge_t nxgep)1310 nxge_mac_ctrl_init(p_nxge_t nxgep)
1311 {
1312 uint8_t portn;
1313 nxge_port_t portt;
1314 p_nxge_stats_t statsp;
1315 npi_handle_t handle;
1316 uint32_t val;
1317
1318 portn = NXGE_GET_PORT_NUM(nxgep->function_num);
1319
1320 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mac_ctrl_init: port<%d>",
1321 portn));
1322
1323 handle = nxgep->npi_handle;
1324 portt = nxgep->mac.porttype;
1325 statsp = nxgep->statsp;
1326
1327 if (portt == PORT_TYPE_XMAC) {
1328 /* Reading the current XMAC Config Register for XMAC */
1329 XMAC_REG_RD(handle, portn, XMAC_CONFIG_REG, &val);
1330
1331 /*
1332 * Setup XMAC Configuration for XMAC
1333 * XMAC only supports receive-pause
1334 */
1335 if (statsp->mac_stats.adv_cap_asmpause) {
1336 if (!statsp->mac_stats.adv_cap_pause) {
1337 /*
1338 * If adv_cap_asmpause is 1 and adv_cap_pause
1339 * is 0, enable receive pause.
1340 */
1341 val |= XMAC_RX_CFG_RX_PAUSE_EN;
1342 } else {
1343 /*
1344 * If adv_cap_asmpause is 1 and adv_cap_pause
1345 * is 1, disable receive pause. Send pause is
1346 * not supported.
1347 */
1348 val &= ~XMAC_RX_CFG_RX_PAUSE_EN;
1349 }
1350 } else {
1351 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1352 "==> nxge_mac_ctrl_init: port<%d>: pause",
1353 portn));
1354 if (statsp->mac_stats.adv_cap_pause) {
1355 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1356 "==> nxge_mac_ctrl_init: port<%d>: "
1357 "enable pause", portn));
1358 /*
1359 * If adv_cap_asmpause is 0 and adv_cap_pause
1360 * is 1, enable receive pause.
1361 */
1362 val |= XMAC_RX_CFG_RX_PAUSE_EN;
1363 } else {
1364 /*
1365 * If adv_cap_asmpause is 0 and adv_cap_pause
1366 * is 0, disable receive pause. Send pause is
1367 * not supported
1368 */
1369 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1370 "==> nxge_mac_ctrl_init: port<%d>: "
1371 "disable pause", portn));
1372 val &= ~XMAC_RX_CFG_RX_PAUSE_EN;
1373 }
1374 }
1375 XMAC_REG_WR(handle, portn, XMAC_CONFIG_REG, val);
1376 } else if (portt == PORT_TYPE_BMAC) {
1377 /* Reading the current MAC CTRL Config Register for BMAC */
1378 BMAC_REG_RD(handle, portn, MAC_CTRL_CONFIG_REG, &val);
1379
1380 /* Setup MAC CTRL Configuration for BMAC */
1381 if (statsp->mac_stats.adv_cap_asmpause) {
1382 if (statsp->mac_stats.adv_cap_pause) {
1383 /*
1384 * If adv_cap_asmpause is 1 and adv_cap_pause
1385 * is 1, disable receive pause. Send pause
1386 * is not supported
1387 */
1388 val &= ~MAC_CTRL_CFG_RECV_PAUSE_EN;
1389 } else {
1390 /*
1391 * If adv_cap_asmpause is 1 and adv_cap_pause
1392 * is 0, enable receive pause and disable
1393 * send pause.
1394 */
1395 val |= MAC_CTRL_CFG_RECV_PAUSE_EN;
1396 val &= ~MAC_CTRL_CFG_SEND_PAUSE_EN;
1397 }
1398 } else {
1399 if (statsp->mac_stats.adv_cap_pause) {
1400 /*
1401 * If adv_cap_asmpause is 0 and adv_cap_pause
1402 * is 1, enable receive pause. Send pause is
1403 * not supported.
1404 */
1405 val |= MAC_CTRL_CFG_RECV_PAUSE_EN;
1406 } else {
1407 /*
1408 * If adv_cap_asmpause is 0 and adv_cap_pause
1409 * is 0, pause capability is not available in
1410 * either direction.
1411 */
1412 val &= (~MAC_CTRL_CFG_SEND_PAUSE_EN &
1413 ~MAC_CTRL_CFG_RECV_PAUSE_EN);
1414 }
1415 }
1416 BMAC_REG_WR(handle, portn, MAC_CTRL_CONFIG_REG, val);
1417 }
1418
1419 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_mac_ctrl_init: port<%d>",
1420 portn));
1421
1422 return (NXGE_OK);
1423 }
1424
1425 /* Initialize the Internal Serdes */
1426
1427 nxge_status_t
nxge_serdes_init(p_nxge_t nxgep)1428 nxge_serdes_init(p_nxge_t nxgep)
1429 {
1430 p_nxge_stats_t statsp;
1431 #ifdef NXGE_DEBUG
1432 uint8_t portn;
1433 #endif
1434 nxge_status_t status = NXGE_OK;
1435
1436 #ifdef NXGE_DEBUG
1437 portn = nxgep->mac.portnum;
1438 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1439 "==> nxge_serdes_init port<%d>", portn));
1440 #endif
1441
1442 if (nxgep->xcvr.serdes_init) {
1443 statsp = nxgep->statsp;
1444 status = nxgep->xcvr.serdes_init(nxgep);
1445 if (status != NXGE_OK)
1446 goto fail;
1447 statsp->mac_stats.serdes_inits++;
1448 }
1449
1450 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_serdes_init port<%d>",
1451 portn));
1452
1453 return (NXGE_OK);
1454
1455 fail:
1456 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1457 "nxge_serdes_init: Failed to initialize serdes for port<%d>",
1458 portn));
1459
1460 return (status);
1461 }
1462
1463 /* Initialize the TI Hedwig Internal Serdes (N2-NIU only) */
1464
1465 static nxge_status_t
nxge_n2_serdes_init(p_nxge_t nxgep)1466 nxge_n2_serdes_init(p_nxge_t nxgep)
1467 {
1468 uint8_t portn;
1469 int chan;
1470 esr_ti_cfgpll_l_t pll_cfg_l;
1471 esr_ti_cfgpll_l_t pll_sts_l;
1472 esr_ti_cfgrx_l_t rx_cfg_l;
1473 esr_ti_cfgrx_h_t rx_cfg_h;
1474 esr_ti_cfgtx_l_t tx_cfg_l;
1475 esr_ti_cfgtx_h_t tx_cfg_h;
1476 #ifdef NXGE_DEBUG
1477 esr_ti_testcfg_t cfg;
1478 #endif
1479 esr_ti_testcfg_t test_cfg;
1480 nxge_status_t status = NXGE_OK;
1481
1482 portn = nxgep->mac.portnum;
1483
1484 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_n2_serdes_init port<%d>",
1485 portn));
1486 if (nxgep->niu_hw_type == NIU_HW_TYPE_RF) {
1487 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1488 "==> nxge_n2_serdes_init port<%d>: KT-NIU", portn));
1489 return (nxge_n2_kt_serdes_init(nxgep));
1490 }
1491
1492 tx_cfg_l.value = 0;
1493 tx_cfg_h.value = 0;
1494 rx_cfg_l.value = 0;
1495 rx_cfg_h.value = 0;
1496 pll_cfg_l.value = 0;
1497 pll_sts_l.value = 0;
1498 test_cfg.value = 0;
1499
1500 /*
1501 * If the nxge driver has been plumbed without a link, then it will
1502 * detect a link up when a cable connecting to an anto-negotiation
1503 * partner is plugged into the port. Because the TN1010 PHY supports
1504 * both 1G and 10G speeds, the driver must re-configure the
1505 * Neptune/NIU according to the negotiated speed. nxge_n2_serdes_init
1506 * is called at the post-link-up reconfiguration time. Here it calls
1507 * nxge_set_tn1010_param to set portmode before re-initializing
1508 * the serdes.
1509 */
1510 if (nxgep->mac.portmode == PORT_1G_TN1010 ||
1511 nxgep->mac.portmode == PORT_10G_TN1010) {
1512 if (nxge_set_tn1010_param(nxgep) != NXGE_OK) {
1513 goto fail;
1514 }
1515 }
1516
1517 if (nxgep->mac.portmode == PORT_10G_FIBER ||
1518 nxgep->mac.portmode == PORT_10G_COPPER ||
1519 nxgep->mac.portmode == PORT_10G_TN1010 ||
1520 nxgep->mac.portmode == PORT_HSP_MODE ||
1521 nxgep->mac.portmode == PORT_10G_SERDES) {
1522 /* 0x0E01 */
1523 tx_cfg_l.bits.entx = 1;
1524 tx_cfg_l.bits.swing = CFGTX_SWING_1375MV;
1525
1526 /* 0x9101 */
1527 rx_cfg_l.bits.enrx = 1;
1528 rx_cfg_l.bits.term = CFGRX_TERM_0P8VDDT;
1529 rx_cfg_l.bits.align = CFGRX_ALIGN_EN;
1530 rx_cfg_l.bits.los = CFGRX_LOS_LOTHRES;
1531
1532 /* 0x0008 */
1533 rx_cfg_h.bits.eq = CFGRX_EQ_ADAPTIVE_LP_ADAPTIVE_ZF;
1534
1535 /* Set loopback mode if necessary */
1536 if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes10g) {
1537 tx_cfg_l.bits.entest = 1;
1538 rx_cfg_l.bits.entest = 1;
1539 test_cfg.bits.loopback = TESTCFG_INNER_CML_DIS_LOOPBACK;
1540 if ((status = nxge_mdio_write(nxgep, portn,
1541 ESR_N2_DEV_ADDR,
1542 ESR_N2_TEST_CFG_REG, test_cfg.value)) != NXGE_OK)
1543 goto fail;
1544 }
1545
1546 /* Initialize PLL for 10G */
1547 pll_cfg_l.bits.mpy = CFGPLL_MPY_10X;
1548 pll_cfg_l.bits.enpll = 1;
1549 pll_sts_l.bits.enpll = 1;
1550 if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
1551 ESR_N2_PLL_CFG_L_REG, pll_cfg_l.value)) != NXGE_OK)
1552 goto fail;
1553
1554 if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
1555 ESR_N2_PLL_STS_L_REG, pll_sts_l.value)) != NXGE_OK)
1556 goto fail;
1557
1558 #ifdef NXGE_DEBUG
1559 nxge_mdio_read(nxgep, portn, ESR_N2_DEV_ADDR,
1560 ESR_N2_PLL_CFG_L_REG, &cfg.value);
1561 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1562 "==> nxge_n2_serdes_init port<%d>: PLL cfg.l 0x%x (0x%x)",
1563 portn, pll_cfg_l.value, cfg.value));
1564
1565 nxge_mdio_read(nxgep, portn, ESR_N2_DEV_ADDR,
1566 ESR_N2_PLL_STS_L_REG, &cfg.value);
1567 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1568 "==> nxge_n2_serdes_init port<%d>: PLL sts.l 0x%x (0x%x)",
1569 portn, pll_sts_l.value, cfg.value));
1570 #endif
1571 } else if (nxgep->mac.portmode == PORT_1G_FIBER ||
1572 nxgep->mac.portmode == PORT_1G_TN1010 ||
1573 nxgep->mac.portmode == PORT_1G_SERDES) {
1574 /* 0x0E21 */
1575 tx_cfg_l.bits.entx = 1;
1576 tx_cfg_l.bits.rate = CFGTX_RATE_HALF;
1577 tx_cfg_l.bits.swing = CFGTX_SWING_1375MV;
1578
1579 /* 0x9121 */
1580 rx_cfg_l.bits.enrx = 1;
1581 rx_cfg_l.bits.rate = CFGRX_RATE_HALF;
1582 rx_cfg_l.bits.term = CFGRX_TERM_0P8VDDT;
1583 rx_cfg_l.bits.align = CFGRX_ALIGN_EN;
1584 rx_cfg_l.bits.los = CFGRX_LOS_LOTHRES;
1585
1586 if (portn == 0) {
1587 /* 0x8 */
1588 rx_cfg_h.bits.eq = CFGRX_EQ_ADAPTIVE_LP_ADAPTIVE_ZF;
1589 }
1590
1591 /* Initialize PLL for 1G */
1592 pll_cfg_l.bits.mpy = CFGPLL_MPY_8X;
1593 pll_cfg_l.bits.enpll = 1;
1594 pll_sts_l.bits.enpll = 1;
1595 if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
1596 ESR_N2_PLL_CFG_L_REG, pll_cfg_l.value)) != NXGE_OK)
1597 goto fail;
1598
1599 if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
1600 ESR_N2_PLL_STS_L_REG, pll_sts_l.value)) != NXGE_OK)
1601 goto fail;
1602
1603 #ifdef NXGE_DEBUG
1604 nxge_mdio_read(nxgep, portn, ESR_N2_DEV_ADDR,
1605 ESR_N2_PLL_CFG_L_REG, &cfg.value);
1606 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1607 "==> nxge_n2_serdes_init port<%d>: PLL cfg.l 0x%x (0x%x)",
1608 portn, pll_cfg_l.value, cfg.value));
1609
1610 nxge_mdio_read(nxgep, portn, ESR_N2_DEV_ADDR,
1611 ESR_N2_PLL_STS_L_REG, &cfg.value);
1612 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1613 "==> nxge_n2_serdes_init port<%d>: PLL sts.l 0x%x (0x%x)",
1614 portn, pll_sts_l.value, cfg.value));
1615 #endif
1616
1617 /* Set loopback mode if necessary */
1618 if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes1000) {
1619 tx_cfg_l.bits.entest = 1;
1620 rx_cfg_l.bits.entest = 1;
1621 test_cfg.bits.loopback = TESTCFG_INNER_CML_DIS_LOOPBACK;
1622 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1623 "==> nxge_n2_serdes_init port<%d>: loopback 0x%x",
1624 portn, test_cfg.value));
1625 if ((status = nxge_mdio_write(nxgep, portn,
1626 ESR_N2_DEV_ADDR,
1627 ESR_N2_TEST_CFG_REG, test_cfg.value)) != NXGE_OK) {
1628 goto fail;
1629 }
1630 }
1631 } else {
1632 goto fail;
1633 }
1634
1635 /* MIF_REG_WR(handle, MIF_MASK_REG, ~mask); */
1636
1637 NXGE_DELAY(20);
1638
1639 /* init TX channels */
1640 for (chan = 0; chan < 4; chan++) {
1641 if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
1642 ESR_N2_TX_CFG_L_REG_ADDR(chan), tx_cfg_l.value)) != NXGE_OK)
1643 goto fail;
1644
1645 if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
1646 ESR_N2_TX_CFG_H_REG_ADDR(chan), tx_cfg_h.value)) != NXGE_OK)
1647 goto fail;
1648
1649 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1650 "==> nxge_n2_serdes_init port<%d>: chan %d tx_cfg_l 0x%x",
1651 portn, chan, tx_cfg_l.value));
1652 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1653 "==> nxge_n2_serdes_init port<%d>: chan %d tx_cfg_h 0x%x",
1654 portn, chan, tx_cfg_h.value));
1655 }
1656
1657 /* init RX channels */
1658 for (chan = 0; chan < 4; chan++) {
1659 if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
1660 ESR_N2_RX_CFG_L_REG_ADDR(chan), rx_cfg_l.value)) != NXGE_OK)
1661 goto fail;
1662
1663 if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
1664 ESR_N2_RX_CFG_H_REG_ADDR(chan), rx_cfg_h.value)) != NXGE_OK)
1665 goto fail;
1666
1667 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1668 "==> nxge_n2_serdes_init port<%d>: chan %d rx_cfg_l 0x%x",
1669 portn, chan, rx_cfg_l.value));
1670
1671 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1672 "==> nxge_n2_serdes_init port<%d>: chan %d rx_cfg_h 0x%x",
1673 portn, chan, rx_cfg_h.value));
1674 }
1675
1676 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_n2_serdes_init port<%d>",
1677 portn));
1678
1679 return (NXGE_OK);
1680 fail:
1681 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1682 "nxge_n2_serdes_init: Failed to initialize N2 serdes for port<%d>",
1683 portn));
1684
1685 return (status);
1686
1687 }
1688
1689 /* Initialize the TI Hedwig Internal Serdes (N2-KT-NIU only) */
1690
1691 static nxge_status_t
nxge_n2_kt_serdes_init(p_nxge_t nxgep)1692 nxge_n2_kt_serdes_init(p_nxge_t nxgep)
1693 {
1694 uint8_t portn;
1695 int chan, i;
1696 k_esr_ti_cfgpll_l_t pll_cfg_l;
1697 k_esr_ti_cfgrx_l_t rx_cfg_l;
1698 k_esr_ti_cfgrx_h_t rx_cfg_h;
1699 k_esr_ti_cfgtx_l_t tx_cfg_l;
1700 k_esr_ti_cfgtx_h_t tx_cfg_h;
1701 #ifdef NXGE_DEBUG
1702 k_esr_ti_testcfg_t cfg;
1703 #endif
1704 k_esr_ti_testcfg_t test_cfg;
1705 nxge_status_t status = NXGE_OK;
1706 boolean_t mode_1g = B_FALSE;
1707 uint64_t val;
1708 npi_handle_t handle;
1709
1710 portn = nxgep->mac.portnum;
1711
1712 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1713 "==> nxge_n2_kt_serdes_init port<%d>", portn));
1714 handle = nxgep->npi_handle;
1715
1716 tx_cfg_l.value = 0;
1717 tx_cfg_h.value = 0;
1718 rx_cfg_l.value = 0;
1719 rx_cfg_h.value = 0;
1720 pll_cfg_l.value = 0;
1721 test_cfg.value = 0;
1722
1723 /*
1724 * The following setting assumes the reference clock frquency
1725 * is 156.25 MHz.
1726 */
1727 /*
1728 * If the nxge driver has been plumbed without a link, then it will
1729 * detect a link up when a cable connecting to an anto-negotiation
1730 * partner is plugged into the port. Because the TN1010 PHY supports
1731 * both 1G and 10G speeds, the driver must re-configure the
1732 * Neptune/NIU according to the negotiated speed. nxge_n2_serdes_init
1733 * is called at the post-link-up reconfiguration time. Here it calls
1734 * nxge_set_tn1010_param to set portmode before re-initializing
1735 * the serdes.
1736 */
1737 if (nxgep->mac.portmode == PORT_1G_TN1010 ||
1738 nxgep->mac.portmode == PORT_10G_TN1010) {
1739 if (nxge_set_tn1010_param(nxgep) != NXGE_OK) {
1740 goto fail;
1741 }
1742 }
1743 if (nxgep->mac.portmode == PORT_10G_FIBER ||
1744 nxgep->mac.portmode == PORT_10G_COPPER ||
1745 nxgep->mac.portmode == PORT_10G_TN1010 ||
1746 nxgep->mac.portmode == PORT_10G_SERDES) {
1747
1748 /* Take tunables from OBP if present, otherwise use defaults */
1749 if (nxgep->srds_prop.prop_set & NXGE_SRDS_TXCFGL) {
1750 tx_cfg_l.value = nxgep->srds_prop.tx_cfg_l;
1751 } else {
1752 tx_cfg_l.bits.entx = K_CFGTX_ENABLE_TX;
1753 /* 0x1e21 */
1754 tx_cfg_l.bits.swing = K_CFGTX_SWING_2000MV;
1755 tx_cfg_l.bits.rate = K_CFGTX_RATE_HALF;
1756 }
1757 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1758 "==> nxge_n2_kt_serdes_init port<%d> tx_cfg_l 0x%x",
1759 portn, tx_cfg_l.value));
1760
1761 if (nxgep->srds_prop.prop_set & NXGE_SRDS_TXCFGH) {
1762 tx_cfg_h.value = nxgep->srds_prop.tx_cfg_h;
1763 } else {
1764 /* channel 0: enable syn. master */
1765 /* 0x40 */
1766 tx_cfg_h.bits.msync = K_CFGTX_ENABLE_MSYNC;
1767 }
1768 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1769 "==> nxge_n2_kt_serdes_init port<%d> tx_cfg_h 0x%x",
1770 portn, tx_cfg_h.value));
1771
1772 if (nxgep->srds_prop.prop_set & NXGE_SRDS_RXCFGL) {
1773 rx_cfg_l.value = nxgep->srds_prop.rx_cfg_l;
1774 } else {
1775 /* 0x4821 */
1776 rx_cfg_l.bits.enrx = K_CFGRX_ENABLE_RX;
1777 rx_cfg_l.bits.rate = K_CFGRX_RATE_HALF;
1778 rx_cfg_l.bits.align = K_CFGRX_ALIGN_EN;
1779 rx_cfg_l.bits.los = K_CFGRX_LOS_ENABLE;
1780 }
1781 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1782 "==> nxge_n2_kt_serdes_init port<%d> rx_cfg_l 0x%x",
1783 portn, rx_cfg_l.value));
1784
1785 if (nxgep->srds_prop.prop_set & NXGE_SRDS_RXCFGH) {
1786 rx_cfg_h.value = nxgep->srds_prop.rx_cfg_h;
1787 } else {
1788 /* 0x0008 */
1789 rx_cfg_h.bits.eq = K_CFGRX_EQ_ADAPTIVE;
1790 }
1791
1792 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1793 "==> nxge_n2_kt_serdes_init port<%d> rx_cfg_h 0x%x",
1794 portn, rx_cfg_h.value));
1795
1796 if (nxgep->srds_prop.prop_set & NXGE_SRDS_PLLCFGL) {
1797 pll_cfg_l.value = nxgep->srds_prop.pll_cfg_l;
1798 } else {
1799 /* 0xa1: Initialize PLL for 10G */
1800 pll_cfg_l.bits.mpy = K_CFGPLL_MPY_20X;
1801 pll_cfg_l.bits.enpll = K_CFGPLL_ENABLE_PLL;
1802 }
1803
1804 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1805 "==> nxge_n2_kt_serdes_init port<%d> pll_cfg_l 0x%x",
1806 portn, pll_cfg_l.value));
1807
1808 if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
1809 ESR_N2_PLL_CFG_L_REG, pll_cfg_l.value)) != NXGE_OK)
1810 goto fail;
1811 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1812 "==> nxge_n2_kt_serdes_init port<%d> pll_cfg_l 0x%x",
1813 portn, pll_cfg_l.value));
1814
1815 /* Set loopback mode if necessary */
1816 if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes10g) {
1817 tx_cfg_h.bits.loopback = K_CFGTX_INNER_CML_ENA_LOOPBACK;
1818 rx_cfg_h.bits.loopback = K_CFGTX_INNER_CML_ENA_LOOPBACK;
1819 rx_cfg_l.bits.los = 0;
1820
1821 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1822 "==> nxge_n2_kt_serdes_init port<%d>: "
1823 "loopback 0x%x", portn, tx_cfg_h.value));
1824 }
1825 #ifdef NXGE_DEBUG
1826 nxge_mdio_read(nxgep, portn, ESR_N2_DEV_ADDR,
1827 ESR_N2_PLL_CFG_L_REG, &cfg.value);
1828 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1829 "==> nxge_n2_kt_serdes_init port<%d>: "
1830 "PLL cfg.l 0x%x (0x%x)",
1831 portn, pll_cfg_l.value, cfg.value));
1832
1833 nxge_mdio_read(nxgep, portn, ESR_N2_DEV_ADDR,
1834 ESR_N2_PLL_STS_L_REG, &cfg.value);
1835 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1836 "==> nxge_n2_kt_serdes_init port<%d>: (0x%x)",
1837 portn, cfg.value));
1838 #endif
1839 } else if (nxgep->mac.portmode == PORT_1G_FIBER ||
1840 nxgep->mac.portmode == PORT_1G_TN1010 ||
1841 nxgep->mac.portmode == PORT_1G_SERDES) {
1842 mode_1g = B_TRUE;
1843 /* 0x1e41 */
1844 tx_cfg_l.bits.entx = 1;
1845 tx_cfg_l.bits.rate = K_CFGTX_RATE_HALF;
1846 tx_cfg_l.bits.swing = K_CFGTX_SWING_2000MV;
1847
1848 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1849 "==> nxge_n2_kt_serdes_init port<%d> tx_cfg_l 0x%x",
1850 portn, tx_cfg_l.value));
1851
1852
1853 /* channel 0: enable syn. master */
1854 tx_cfg_h.bits.msync = K_CFGTX_ENABLE_MSYNC;
1855 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1856 "==> nxge_n2_kt_serdes_init port<%d> tx_cfg_h 0x%x",
1857 portn, tx_cfg_h.value));
1858
1859
1860 /* 0x4841 */
1861 rx_cfg_l.bits.enrx = 1;
1862 rx_cfg_l.bits.rate = K_CFGRX_RATE_HALF;
1863 rx_cfg_l.bits.align = K_CFGRX_ALIGN_EN;
1864 rx_cfg_l.bits.los = K_CFGRX_LOS_ENABLE;
1865
1866 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1867 "==> nxge_n2_kt_serdes_init port<%d> rx_cfg_l 0x%x",
1868 portn, rx_cfg_l.value));
1869
1870 /* 0x0008 */
1871 rx_cfg_h.bits.eq = K_CFGRX_EQ_ADAPTIVE_LF_365MHZ_ZF;
1872
1873 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1874 "==> nxge_n2_kt_serdes_init port<%d> tx_cfg_h 0x%x",
1875 portn, rx_cfg_h.value));
1876
1877 /* 0xa1: Initialize PLL for 1G */
1878 pll_cfg_l.bits.mpy = K_CFGPLL_MPY_20X;
1879 pll_cfg_l.bits.enpll = K_CFGPLL_ENABLE_PLL;
1880
1881 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1882 "==> nxge_n2_kt_serdes_init port<%d> pll_cfg_l 0x%x",
1883 portn, pll_cfg_l.value));
1884
1885 if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
1886 ESR_N2_PLL_CFG_L_REG, pll_cfg_l.value))
1887 != NXGE_OK)
1888 goto fail;
1889
1890
1891 #ifdef NXGE_DEBUG
1892 nxge_mdio_read(nxgep, portn, ESR_N2_DEV_ADDR,
1893 ESR_N2_PLL_CFG_L_REG, &cfg.value);
1894 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1895 "==> nxge_n2_serdes_init port<%d>: PLL cfg.l 0x%x (0x%x)",
1896 portn, pll_cfg_l.value, cfg.value));
1897
1898 nxge_mdio_read(nxgep, portn, ESR_N2_DEV_ADDR,
1899 ESR_N2_PLL_STS_L_REG, &cfg.value);
1900 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1901 "==> nxge_n2_kt_serdes_init port<%d>: (0x%x)",
1902 portn, cfg.value));
1903 #endif
1904
1905 /* Set loopback mode if necessary */
1906 if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes1000) {
1907 tx_cfg_h.bits.loopback = TESTCFG_INNER_CML_DIS_LOOPBACK;
1908
1909 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1910 "==> nxge_n2_kt_serdes_init port<%d>: "
1911 "loopback 0x%x", portn, test_cfg.value));
1912 if ((status = nxge_mdio_write(nxgep, portn,
1913 ESR_N2_DEV_ADDR,
1914 ESR_N2_TX_CFG_L_REG_ADDR(0),
1915 tx_cfg_h.value)) != NXGE_OK) {
1916 goto fail;
1917 }
1918 }
1919 } else {
1920 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1921 "nxge_n2_kt_serdes_init:port<%d> - "
1922 "unsupported port mode %d",
1923 portn, nxgep->mac.portmode));
1924 goto fail;
1925 }
1926
1927 NXGE_DELAY(20);
1928 /* Clear the test register (offset 0x8004) */
1929 if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
1930 ESR_N2_TEST_CFG_REG, test_cfg.value)) != NXGE_OK) {
1931 goto fail;
1932 }
1933 NXGE_DELAY(20);
1934
1935 /* init TX channels */
1936 for (chan = 0; chan < 4; chan++) {
1937 if (mode_1g)
1938 tx_cfg_l.value = 0;
1939 if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
1940 ESR_N2_TX_CFG_L_REG_ADDR(chan), tx_cfg_l.value)) != NXGE_OK)
1941 goto fail;
1942
1943 if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
1944 ESR_N2_TX_CFG_H_REG_ADDR(chan), tx_cfg_h.value)) != NXGE_OK)
1945 goto fail;
1946
1947 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1948 "==> nxge_n2_kt_serdes_init port<%d>: "
1949 "chan %d tx_cfg_l 0x%x", portn, chan, tx_cfg_l.value));
1950
1951 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1952 "==> nxge_n2_kt_serdes_init port<%d>: "
1953 "chan %d tx_cfg_h 0x%x", portn, chan, tx_cfg_h.value));
1954 }
1955
1956 /* init RX channels */
1957 /* 1G mode only write to the first channel */
1958 for (chan = 0; chan < 4; chan++) {
1959 if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
1960 ESR_N2_RX_CFG_L_REG_ADDR(chan), rx_cfg_l.value))
1961 != NXGE_OK)
1962 goto fail;
1963
1964 if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
1965 ESR_N2_RX_CFG_H_REG_ADDR(chan), rx_cfg_h.value))
1966 != NXGE_OK)
1967 goto fail;
1968
1969 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1970 "==> nxge_n2_kt_serdes_init port<%d>: "
1971 "chan %d rx_cfg_l 0x%x", portn, chan, rx_cfg_l.value));
1972
1973 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1974 "==> nxge_n2_kt_serdes_init port<%d>: "
1975 "chan %d rx_cfg_h 0x%x", portn, chan, rx_cfg_h.value));
1976 }
1977
1978 if (portn == 0) {
1979 /* Wait for serdes to be ready */
1980 for (i = 0; i < MAX_SERDES_RDY_RETRIES; i++) {
1981 ESR_REG_RD(handle, ESR_INTERNAL_SIGNALS_REG, &val);
1982 if ((val & ESR_SIG_P0_BITS_MASK) !=
1983 (ESR_SIG_SERDES_RDY0_P0 | ESR_SIG_DETECT0_P0 |
1984 ESR_SIG_XSERDES_RDY_P0 |
1985 ESR_SIG_XDETECT_P0_CH3 |
1986 ESR_SIG_XDETECT_P0_CH2 |
1987 ESR_SIG_XDETECT_P0_CH1 |
1988 ESR_SIG_XDETECT_P0_CH0))
1989
1990 NXGE_DELAY(SERDES_RDY_WT_INTERVAL);
1991 else
1992 break;
1993 }
1994
1995 if (i == MAX_SERDES_RDY_RETRIES) {
1996 /*
1997 * RDY signal stays low may due to the absent of the
1998 * external PHY, it is not an error condition.
1999 * But still print the message for the debugging
2000 * purpose when link stays down
2001 */
2002 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2003 "nxge_n2_kt_serdes_init: "
2004 "Serdes/signal for port<%d> not ready", portn));
2005 goto done;
2006 }
2007 } else if (portn == 1) {
2008 /* Wait for serdes to be ready */
2009 for (i = 0; i < MAX_SERDES_RDY_RETRIES; i++) {
2010 ESR_REG_RD(handle, ESR_INTERNAL_SIGNALS_REG, &val);
2011 if ((val & ESR_SIG_P1_BITS_MASK) !=
2012 (ESR_SIG_SERDES_RDY0_P1 | ESR_SIG_DETECT0_P1 |
2013 ESR_SIG_XSERDES_RDY_P1 |
2014 ESR_SIG_XDETECT_P1_CH3 |
2015 ESR_SIG_XDETECT_P1_CH2 |
2016 ESR_SIG_XDETECT_P1_CH1 |
2017 ESR_SIG_XDETECT_P1_CH0))
2018
2019 NXGE_DELAY(SERDES_RDY_WT_INTERVAL);
2020 else
2021 break;
2022 }
2023
2024 if (i == MAX_SERDES_RDY_RETRIES) {
2025 /*
2026 * RDY signal stays low may due to the absent of the
2027 * external PHY, it is not an error condition.
2028 * But still print the message for the debugging
2029 * purpose when link stays down
2030 */
2031 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2032 "nxge_n2_kt_serdes_init: "
2033 "Serdes/signal for port<%d> not ready", portn));
2034 goto done;
2035 }
2036 }
2037 done:
2038
2039 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
2040 "<== nxge_n2_kt_serdes_init port<%d>", portn));
2041
2042 return (NXGE_OK);
2043 fail:
2044 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2045 "nxge_n2_serdes_init: Failed to initialize N2 serdes for port<%d>",
2046 portn));
2047
2048 return (status);
2049 }
2050
2051 /* Initialize the Neptune Internal Serdes for 10G (Neptune only) */
2052
2053 static nxge_status_t
nxge_neptune_10G_serdes_init(p_nxge_t nxgep)2054 nxge_neptune_10G_serdes_init(p_nxge_t nxgep)
2055 {
2056 npi_handle_t handle;
2057 uint8_t portn;
2058 int chan, i;
2059 sr_rx_tx_ctrl_l_t rx_tx_ctrl_l;
2060 sr_rx_tx_ctrl_h_t rx_tx_ctrl_h;
2061 sr_glue_ctrl0_l_t glue_ctrl0_l;
2062 sr_glue_ctrl0_h_t glue_ctrl0_h;
2063 uint64_t val;
2064 uint16_t val16l;
2065 uint16_t val16h;
2066 nxge_status_t status = NXGE_OK;
2067
2068 portn = nxgep->mac.portnum;
2069
2070 if ((portn != 0) && (portn != 1))
2071 return (NXGE_OK);
2072
2073 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
2074 "==> nxge_neptune_10G_serdes_init port<%d>", portn));
2075 handle = nxgep->npi_handle;
2076 switch (portn) {
2077 case 0:
2078 /* Reset Serdes */
2079 ESR_REG_WR(handle, ESR_RESET_REG, ESR_RESET_0);
2080 NXGE_DELAY(20);
2081 ESR_REG_WR(handle, ESR_RESET_REG, 0x0);
2082 NXGE_DELAY(2000);
2083
2084 /* Configure Serdes to 10G mode */
2085 ESR_REG_WR(handle, ESR_0_PLL_CONFIG_REG,
2086 ESR_PLL_CFG_10G_SERDES);
2087
2088 ESR_REG_WR(handle, ESR_0_CONTROL_REG,
2089 ESR_CTL_EN_SYNCDET_0 | ESR_CTL_EN_SYNCDET_1 |
2090 ESR_CTL_EN_SYNCDET_2 | ESR_CTL_EN_SYNCDET_3 |
2091 (0x5 << ESR_CTL_OUT_EMPH_0_SHIFT) |
2092 (0x5 << ESR_CTL_OUT_EMPH_1_SHIFT) |
2093 (0x5 << ESR_CTL_OUT_EMPH_2_SHIFT) |
2094 (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) |
2095 (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) |
2096 (0x1 << ESR_CTL_LOSADJ_0_SHIFT) |
2097 (0x1 << ESR_CTL_LOSADJ_1_SHIFT) |
2098 (0x1 << ESR_CTL_LOSADJ_2_SHIFT) |
2099 (0x1 << ESR_CTL_LOSADJ_3_SHIFT));
2100
2101 /* Set Serdes0 Internal Loopback if necessary */
2102 if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes10g) {
2103 ESR_REG_WR(handle,
2104 ESR_0_TEST_CONFIG_REG,
2105 ESR_PAD_LOOPBACK_CH3 |
2106 ESR_PAD_LOOPBACK_CH2 |
2107 ESR_PAD_LOOPBACK_CH1 |
2108 ESR_PAD_LOOPBACK_CH0);
2109 } else {
2110 ESR_REG_WR(handle, ESR_0_TEST_CONFIG_REG, 0);
2111 }
2112 break;
2113 case 1:
2114 /* Reset Serdes */
2115 ESR_REG_WR(handle, ESR_RESET_REG, ESR_RESET_1);
2116 NXGE_DELAY(20);
2117 ESR_REG_WR(handle, ESR_RESET_REG, 0x0);
2118 NXGE_DELAY(2000);
2119
2120 /* Configure Serdes to 10G mode */
2121 ESR_REG_WR(handle, ESR_1_PLL_CONFIG_REG,
2122 ESR_PLL_CFG_10G_SERDES);
2123
2124 ESR_REG_WR(handle, ESR_1_CONTROL_REG,
2125 ESR_CTL_EN_SYNCDET_0 | ESR_CTL_EN_SYNCDET_1 |
2126 ESR_CTL_EN_SYNCDET_2 | ESR_CTL_EN_SYNCDET_3 |
2127 (0x5 << ESR_CTL_OUT_EMPH_0_SHIFT) |
2128 (0x5 << ESR_CTL_OUT_EMPH_1_SHIFT) |
2129 (0x5 << ESR_CTL_OUT_EMPH_2_SHIFT) |
2130 (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) |
2131 (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) |
2132 (0x1 << ESR_CTL_LOSADJ_0_SHIFT) |
2133 (0x1 << ESR_CTL_LOSADJ_1_SHIFT) |
2134 (0x1 << ESR_CTL_LOSADJ_2_SHIFT) |
2135 (0x1 << ESR_CTL_LOSADJ_3_SHIFT));
2136
2137 /* Set Serdes1 Internal Loopback if necessary */
2138 if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes10g) {
2139 ESR_REG_WR(handle, ESR_1_TEST_CONFIG_REG,
2140 ESR_PAD_LOOPBACK_CH3 | ESR_PAD_LOOPBACK_CH2 |
2141 ESR_PAD_LOOPBACK_CH1 | ESR_PAD_LOOPBACK_CH0);
2142 } else {
2143 ESR_REG_WR(handle, ESR_1_TEST_CONFIG_REG, 0);
2144 }
2145 break;
2146 default:
2147 /* Nothing to do here */
2148 goto done;
2149 }
2150
2151 /* init TX RX channels */
2152 for (chan = 0; chan < 4; chan++) {
2153 if ((status = nxge_mdio_read(nxgep, portn,
2154 ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_L_ADDR(chan),
2155 &rx_tx_ctrl_l.value)) != NXGE_OK)
2156 goto fail;
2157 if ((status = nxge_mdio_read(nxgep, portn,
2158 ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_H_ADDR(chan),
2159 &rx_tx_ctrl_h.value)) != NXGE_OK)
2160 goto fail;
2161 if ((status = nxge_mdio_read(nxgep, portn,
2162 ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_L_ADDR(chan),
2163 &glue_ctrl0_l.value)) != NXGE_OK)
2164 goto fail;
2165 if ((status = nxge_mdio_read(nxgep, portn,
2166 ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_H_ADDR(chan),
2167 &glue_ctrl0_h.value)) != NXGE_OK)
2168 goto fail;
2169 rx_tx_ctrl_l.bits.enstretch = 1;
2170 rx_tx_ctrl_h.bits.vmuxlo = 2;
2171 rx_tx_ctrl_h.bits.vpulselo = 2;
2172 glue_ctrl0_l.bits.rxlosenable = 1;
2173 glue_ctrl0_l.bits.samplerate = 0xF;
2174 glue_ctrl0_l.bits.thresholdcount = 0xFF;
2175 glue_ctrl0_h.bits.bitlocktime = BITLOCKTIME_300_CYCLES;
2176 if ((status = nxge_mdio_write(nxgep, portn,
2177 ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_L_ADDR(chan),
2178 rx_tx_ctrl_l.value)) != NXGE_OK)
2179 goto fail;
2180 if ((status = nxge_mdio_write(nxgep, portn,
2181 ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_H_ADDR(chan),
2182 rx_tx_ctrl_h.value)) != NXGE_OK)
2183 goto fail;
2184 if ((status = nxge_mdio_write(nxgep, portn,
2185 ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_L_ADDR(chan),
2186 glue_ctrl0_l.value)) != NXGE_OK)
2187 goto fail;
2188 if ((status = nxge_mdio_write(nxgep, portn,
2189 ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_H_ADDR(chan),
2190 glue_ctrl0_h.value)) != NXGE_OK)
2191 goto fail;
2192 }
2193
2194 /* Apply Tx core reset */
2195 if ((status = nxge_mdio_write(nxgep, portn,
2196 ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(),
2197 (uint16_t)0)) != NXGE_OK)
2198 goto fail;
2199
2200 if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
2201 ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), (uint16_t)0xffff)) !=
2202 NXGE_OK)
2203 goto fail;
2204
2205 NXGE_DELAY(200);
2206
2207 /* Apply Rx core reset */
2208 if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
2209 ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), (uint16_t)0xffff)) !=
2210 NXGE_OK)
2211 goto fail;
2212
2213 NXGE_DELAY(200);
2214 if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
2215 ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), (uint16_t)0)) != NXGE_OK)
2216 goto fail;
2217
2218 NXGE_DELAY(200);
2219 if ((status = nxge_mdio_read(nxgep, portn,
2220 ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(),
2221 &val16l)) != NXGE_OK)
2222 goto fail;
2223 if ((status = nxge_mdio_read(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
2224 ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), &val16h)) != NXGE_OK)
2225 goto fail;
2226 if ((val16l != 0) || (val16h != 0)) {
2227 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2228 "Failed to reset port<%d> XAUI Serdes "
2229 "(val16l 0x%x val16h 0x%x)",
2230 portn, val16l, val16h));
2231 }
2232
2233 if (portn == 0) {
2234 /* Wait for serdes to be ready */
2235 for (i = 0; i < MAX_SERDES_RDY_RETRIES; i++) {
2236 ESR_REG_RD(handle, ESR_INTERNAL_SIGNALS_REG, &val);
2237 if ((val & ESR_SIG_P0_BITS_MASK) !=
2238 (ESR_SIG_SERDES_RDY0_P0 | ESR_SIG_DETECT0_P0 |
2239 ESR_SIG_XSERDES_RDY_P0 |
2240 ESR_SIG_XDETECT_P0_CH3 |
2241 ESR_SIG_XDETECT_P0_CH2 |
2242 ESR_SIG_XDETECT_P0_CH1 |
2243 ESR_SIG_XDETECT_P0_CH0))
2244
2245 NXGE_DELAY(SERDES_RDY_WT_INTERVAL);
2246 else
2247 break;
2248 }
2249
2250 if (i == MAX_SERDES_RDY_RETRIES) {
2251 /*
2252 * RDY signal stays low may due to the absent of the
2253 * external PHY, it is not an error condition. But still
2254 * print the message for the debugging purpose when link
2255 * stays down
2256 */
2257 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
2258 "nxge_neptune_10G_serdes_init: "
2259 "Serdes/signal for port<%d> not ready", portn));
2260 goto done;
2261 }
2262 } else if (portn == 1) {
2263 /* Wait for serdes to be ready */
2264 for (i = 0; i < MAX_SERDES_RDY_RETRIES; i++) {
2265 ESR_REG_RD(handle, ESR_INTERNAL_SIGNALS_REG, &val);
2266 if ((val & ESR_SIG_P1_BITS_MASK) !=
2267 (ESR_SIG_SERDES_RDY0_P1 | ESR_SIG_DETECT0_P1 |
2268 ESR_SIG_XSERDES_RDY_P1 |
2269 ESR_SIG_XDETECT_P1_CH3 |
2270 ESR_SIG_XDETECT_P1_CH2 |
2271 ESR_SIG_XDETECT_P1_CH1 |
2272 ESR_SIG_XDETECT_P1_CH0))
2273
2274 NXGE_DELAY(SERDES_RDY_WT_INTERVAL);
2275 else
2276 break;
2277 }
2278
2279 if (i == MAX_SERDES_RDY_RETRIES) {
2280 /*
2281 * RDY signal stays low may due to the absent of the
2282 * external PHY, it is not an error condition. But still
2283 * print the message for the debugging purpose when link
2284 * stays down
2285 */
2286 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
2287 "nxge_neptune_10G_serdes_init: "
2288 "Serdes/signal for port<%d> not ready", portn));
2289 goto done;
2290 }
2291 }
2292
2293 done:
2294 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
2295 "<== nxge_neptune_10G_serdes_init port<%d>", portn));
2296
2297 return (NXGE_OK);
2298 fail:
2299 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2300 "nxge_neptune_10G_serdes_init: "
2301 "Failed to initialize Neptune serdes for port<%d>", portn));
2302
2303 return (status);
2304 }
2305
2306 /* Initialize Neptune Internal Serdes for 1G (Neptune only) */
2307
2308 static nxge_status_t
nxge_1G_serdes_init(p_nxge_t nxgep)2309 nxge_1G_serdes_init(p_nxge_t nxgep)
2310 {
2311 npi_handle_t handle;
2312 uint8_t portn;
2313 int chan;
2314 sr_rx_tx_ctrl_l_t rx_tx_ctrl_l;
2315 sr_rx_tx_ctrl_h_t rx_tx_ctrl_h;
2316 sr_glue_ctrl0_l_t glue_ctrl0_l;
2317 sr_glue_ctrl0_h_t glue_ctrl0_h;
2318 uint64_t val;
2319 uint16_t val16l;
2320 uint16_t val16h;
2321 nxge_status_t status = NXGE_OK;
2322
2323 portn = nxgep->mac.portnum;
2324
2325 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
2326 "==> nxge_1G_serdes_init port<%d>", portn));
2327
2328 handle = nxgep->npi_handle;
2329
2330 switch (portn) {
2331 case 0:
2332 /* Assert the reset register */
2333 ESR_REG_RD(handle, ESR_RESET_REG, &val);
2334 val |= ESR_RESET_0;
2335 ESR_REG_WR(handle, ESR_RESET_REG, val);
2336
2337 /* Set the PLL register to 0x79 */
2338 ESR_REG_WR(handle, ESR_0_PLL_CONFIG_REG,
2339 ESR_PLL_CFG_1G_SERDES);
2340
2341 /* Set the control register to 0x249249f */
2342 ESR_REG_WR(handle, ESR_0_CONTROL_REG, ESR_CTL_1G_SERDES);
2343
2344 /* Set Serdes0 Internal Loopback if necessary */
2345 if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes1000) {
2346 /* Set pad loopback modes 0xaa */
2347 ESR_REG_WR(handle, ESR_0_TEST_CONFIG_REG,
2348 ESR_TSTCFG_LBTEST_PAD);
2349 } else {
2350 ESR_REG_WR(handle, ESR_0_TEST_CONFIG_REG, 0);
2351 }
2352
2353 /* Deassert the reset register */
2354 ESR_REG_RD(handle, ESR_RESET_REG, &val);
2355 val &= ~ESR_RESET_0;
2356 ESR_REG_WR(handle, ESR_RESET_REG, val);
2357 break;
2358
2359 case 1:
2360 /* Assert the reset register */
2361 ESR_REG_RD(handle, ESR_RESET_REG, &val);
2362 val |= ESR_RESET_1;
2363 ESR_REG_WR(handle, ESR_RESET_REG, val);
2364
2365 /* Set PLL register to 0x79 */
2366 ESR_REG_WR(handle, ESR_1_PLL_CONFIG_REG,
2367 ESR_PLL_CFG_1G_SERDES);
2368
2369 /* Set the control register to 0x249249f */
2370 ESR_REG_WR(handle, ESR_1_CONTROL_REG, ESR_CTL_1G_SERDES);
2371
2372 /* Set Serdes1 Internal Loopback if necessary */
2373 if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes1000) {
2374 /* Set pad loopback mode 0xaa */
2375 ESR_REG_WR(handle, ESR_1_TEST_CONFIG_REG,
2376 ESR_TSTCFG_LBTEST_PAD);
2377 } else {
2378 ESR_REG_WR(handle, ESR_1_TEST_CONFIG_REG, 0);
2379 }
2380
2381 /* Deassert the reset register */
2382 ESR_REG_RD(handle, ESR_RESET_REG, &val);
2383 val &= ~ESR_RESET_1;
2384 ESR_REG_WR(handle, ESR_RESET_REG, val);
2385 break;
2386
2387 default:
2388 /* Nothing to do here */
2389 goto done;
2390 }
2391
2392 /* init TX RX channels */
2393 for (chan = 0; chan < 4; chan++) {
2394 if ((status = nxge_mdio_read(nxgep, portn,
2395 ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_L_ADDR(chan),
2396 &rx_tx_ctrl_l.value)) != NXGE_OK) {
2397 goto fail;
2398 }
2399 if ((status = nxge_mdio_read(nxgep, portn,
2400 ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_H_ADDR(chan),
2401 &rx_tx_ctrl_h.value)) != NXGE_OK) {
2402 goto fail;
2403 }
2404 if ((status = nxge_mdio_read(nxgep, portn,
2405 ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_L_ADDR(chan),
2406 &glue_ctrl0_l.value)) != NXGE_OK) {
2407 goto fail;
2408 }
2409 if ((status = nxge_mdio_read(nxgep, portn,
2410 ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_H_ADDR(chan),
2411 &glue_ctrl0_h.value)) != NXGE_OK) {
2412 goto fail;
2413 }
2414
2415 rx_tx_ctrl_l.bits.enstretch = 1;
2416 rx_tx_ctrl_h.bits.vmuxlo = 2;
2417 rx_tx_ctrl_h.bits.vpulselo = 2;
2418 glue_ctrl0_l.bits.rxlosenable = 1;
2419 glue_ctrl0_l.bits.samplerate = 0xF;
2420 glue_ctrl0_l.bits.thresholdcount = 0xFF;
2421 glue_ctrl0_h.bits.bitlocktime = BITLOCKTIME_300_CYCLES;
2422 if ((status = nxge_mdio_write(nxgep, portn,
2423 ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_L_ADDR(chan),
2424 rx_tx_ctrl_l.value)) != NXGE_OK) {
2425 goto fail;
2426 }
2427 if ((status = nxge_mdio_write(nxgep, portn,
2428 ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_H_ADDR(chan),
2429 rx_tx_ctrl_h.value)) != NXGE_OK) {
2430 goto fail;
2431 }
2432 if ((status = nxge_mdio_write(nxgep, portn,
2433 ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_L_ADDR(chan),
2434 glue_ctrl0_l.value)) != NXGE_OK) {
2435 goto fail;
2436 }
2437 if ((status = nxge_mdio_write(nxgep, portn,
2438 ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_H_ADDR(chan),
2439 glue_ctrl0_h.value)) != NXGE_OK) {
2440 goto fail;
2441 }
2442 }
2443
2444 if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
2445 ESR_NEP_RX_POWER_CONTROL_L_ADDR(), 0xfff)) != NXGE_OK) {
2446 goto fail;
2447 }
2448 if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
2449 ESR_NEP_RX_POWER_CONTROL_H_ADDR(), 0xfff)) != NXGE_OK) {
2450 goto fail;
2451 }
2452 if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
2453 ESR_NEP_TX_POWER_CONTROL_L_ADDR(), 0x70)) != NXGE_OK) {
2454 goto fail;
2455 }
2456 if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
2457 ESR_NEP_TX_POWER_CONTROL_H_ADDR(), 0xfff)) != NXGE_OK) {
2458 goto fail;
2459 }
2460
2461 /* Apply Tx core reset */
2462 if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
2463 ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), (uint16_t)0)) != NXGE_OK) {
2464 goto fail;
2465 }
2466
2467 if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
2468 ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), (uint16_t)0xffff)) !=
2469 NXGE_OK) {
2470 goto fail;
2471 }
2472
2473 NXGE_DELAY(200);
2474
2475 /* Apply Rx core reset */
2476 if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
2477 ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), (uint16_t)0xffff)) !=
2478 NXGE_OK) {
2479 goto fail;
2480 }
2481
2482 NXGE_DELAY(200);
2483 if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
2484 ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), (uint16_t)0)) != NXGE_OK) {
2485 goto fail;
2486 }
2487
2488 NXGE_DELAY(200);
2489 if ((status = nxge_mdio_read(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
2490 ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), &val16l)) != NXGE_OK) {
2491 goto fail;
2492 }
2493 if ((status = nxge_mdio_read(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
2494 ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), &val16h)) != NXGE_OK) {
2495 goto fail;
2496 }
2497 if ((val16l != 0) || (val16h != 0)) {
2498 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2499 "Failed to reset port<%d> XAUI Serdes "
2500 "(val16l 0x%x val16h 0x%x)", portn, val16l, val16h));
2501 status = NXGE_ERROR;
2502 goto fail;
2503 }
2504
2505 NXGE_DELAY(200);
2506 ESR_REG_RD(handle, ESR_INTERNAL_SIGNALS_REG, &val);
2507 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
2508 "nxge_neptune_serdes_init: read internal signal reg port<%d> "
2509 "val 0x%x", portn, val));
2510 if (portn == 0) {
2511 if ((val & ESR_SIG_P0_BITS_MASK_1G) !=
2512 (ESR_SIG_SERDES_RDY0_P0 | ESR_SIG_DETECT0_P0)) {
2513 /*
2514 * RDY signal stays low may due to the absent of the
2515 * external PHY, it is not an error condition. But still
2516 * print the message for the debugging purpose when link
2517 * stays down
2518 */
2519 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2520 "nxge_neptune_1G_serdes_init: "
2521 "Serdes/signal for port<%d> not ready", portn));
2522 goto done;
2523 }
2524 } else if (portn == 1) {
2525 if ((val & ESR_SIG_P1_BITS_MASK_1G) !=
2526 (ESR_SIG_SERDES_RDY0_P1 | ESR_SIG_DETECT0_P1)) {
2527 /*
2528 * RDY signal stays low may due to the absent of the
2529 * external PHY, it is not an error condition. But still
2530 * print the message for the debugging purpose when link
2531 * stays down
2532 */
2533 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2534 "nxge_neptune_1G_serdes_init: "
2535 "Serdes/signal for port<%d> not ready", portn));
2536 goto done;
2537
2538 }
2539 }
2540 done:
2541
2542 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
2543 "<== nxge_1G_serdes_init port<%d>", portn));
2544 return (NXGE_OK);
2545 fail:
2546 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2547 "nxge_1G_serdes_init: "
2548 "Failed to initialize Neptune serdes for port<%d>",
2549 portn));
2550
2551 return (status);
2552 }
2553
2554 #define NXGE_SET_PHY_TUNABLES(nxgep, phy_port, stat) \
2555 { \
2556 int i; \
2557 \
2558 if (nxgep->phy_prop.cnt > 0) { \
2559 for (i = 0; i < nxgep->phy_prop.cnt; i++) { \
2560 if ((stat = nxge_mdio_write(nxgep, phy_port, \
2561 nxgep->phy_prop.arr[i].dev, \
2562 nxgep->phy_prop.arr[i].reg, \
2563 nxgep->phy_prop.arr[i].val)) != NXGE_OK) { \
2564 break; \
2565 } \
2566 NXGE_DEBUG_MSG((nxgep, MAC_CTL, \
2567 "From OBP, write<dev.reg.val> = " \
2568 "<0x%x.0x%x.0x%x>", \
2569 nxgep->phy_prop.arr[i].dev, \
2570 nxgep->phy_prop.arr[i].reg, \
2571 nxgep->phy_prop.arr[i].val)); \
2572 } \
2573 } \
2574 }
2575
2576 /* Initialize the BCM 8704 xcvr */
2577
2578 static nxge_status_t
nxge_BCM8704_xcvr_init(p_nxge_t nxgep)2579 nxge_BCM8704_xcvr_init(p_nxge_t nxgep)
2580 {
2581 uint16_t val;
2582 #ifdef NXGE_DEBUG
2583 uint8_t portn;
2584 uint16_t val1;
2585 #endif
2586 uint8_t phy_port_addr;
2587 pmd_tx_control_t tx_ctl;
2588 control_t ctl;
2589 phyxs_control_t phyxs_ctl;
2590 pcs_control_t pcs_ctl;
2591 uint32_t delay = 0;
2592 optics_dcntr_t op_ctr;
2593 nxge_status_t status = NXGE_OK;
2594 #ifdef NXGE_DEBUG
2595 portn = nxgep->mac.portnum;
2596 #endif
2597
2598 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_BCM8704_xcvr_init: port<%d>",
2599 portn));
2600
2601 phy_port_addr = nxgep->statsp->mac_stats.xcvr_portn;
2602
2603 /* Reset the transceiver */
2604 if ((status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR,
2605 BCM8704_PHYXS_CONTROL_REG, &phyxs_ctl.value)) != NXGE_OK)
2606 goto fail;
2607
2608 phyxs_ctl.bits.reset = 1;
2609 if ((status = nxge_mdio_write(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR,
2610 BCM8704_PHYXS_CONTROL_REG, phyxs_ctl.value)) != NXGE_OK)
2611 goto fail;
2612
2613 do {
2614 drv_usecwait(500);
2615 if ((status = nxge_mdio_read(nxgep, phy_port_addr,
2616 BCM8704_PHYXS_ADDR, BCM8704_PHYXS_CONTROL_REG,
2617 &phyxs_ctl.value)) != NXGE_OK)
2618 goto fail;
2619 delay++;
2620 } while ((phyxs_ctl.bits.reset) && (delay < 100));
2621 if (delay == 100) {
2622 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_xcvr_init: "
2623 "failed to reset Transceiver on port<%d>", portn));
2624 status = NXGE_ERROR;
2625 goto fail;
2626 }
2627
2628 /* Set to 0x7FBF */
2629 ctl.value = 0;
2630 ctl.bits.res1 = 0x3F;
2631 ctl.bits.optxon_lvl = 1;
2632 ctl.bits.oprxflt_lvl = 1;
2633 ctl.bits.optrxlos_lvl = 1;
2634 ctl.bits.optxflt_lvl = 1;
2635 ctl.bits.opprflt_lvl = 1;
2636 ctl.bits.obtmpflt_lvl = 1;
2637 ctl.bits.opbiasflt_lvl = 1;
2638 ctl.bits.optxrst_lvl = 1;
2639 if ((status = nxge_mdio_write(nxgep, phy_port_addr,
2640 BCM8704_USER_DEV3_ADDR, BCM8704_USER_CONTROL_REG, ctl.value))
2641 != NXGE_OK)
2642 goto fail;
2643
2644 /* Set to 0x164 */
2645 tx_ctl.value = 0;
2646 tx_ctl.bits.tsck_lpwren = 1;
2647 tx_ctl.bits.tx_dac_txck = 0x2;
2648 tx_ctl.bits.tx_dac_txd = 0x1;
2649 tx_ctl.bits.xfp_clken = 1;
2650 if ((status = nxge_mdio_write(nxgep, phy_port_addr,
2651 BCM8704_USER_DEV3_ADDR, BCM8704_USER_PMD_TX_CONTROL_REG,
2652 tx_ctl.value)) != NXGE_OK)
2653 goto fail;
2654 /*
2655 * According to Broadcom's instruction, SW needs to read
2656 * back these registers twice after written.
2657 */
2658 if ((status = nxge_mdio_read(nxgep, phy_port_addr,
2659 BCM8704_USER_DEV3_ADDR, BCM8704_USER_CONTROL_REG, &val))
2660 != NXGE_OK)
2661 goto fail;
2662
2663 if ((status = nxge_mdio_read(nxgep, phy_port_addr,
2664 BCM8704_USER_DEV3_ADDR, BCM8704_USER_CONTROL_REG, &val))
2665 != NXGE_OK)
2666 goto fail;
2667
2668 if ((status = nxge_mdio_read(nxgep, phy_port_addr,
2669 BCM8704_USER_DEV3_ADDR, BCM8704_USER_PMD_TX_CONTROL_REG, &val))
2670 != NXGE_OK)
2671 goto fail;
2672
2673 if ((status = nxge_mdio_read(nxgep, phy_port_addr,
2674 BCM8704_USER_DEV3_ADDR, BCM8704_USER_PMD_TX_CONTROL_REG, &val))
2675 != NXGE_OK)
2676 goto fail;
2677
2678 /* Enable Tx and Rx LEDs to be driven by traffic */
2679 if ((status = nxge_mdio_read(nxgep, phy_port_addr,
2680 BCM8704_USER_DEV3_ADDR, BCM8704_USER_OPTICS_DIGITAL_CTRL_REG,
2681 &op_ctr.value)) != NXGE_OK)
2682 goto fail;
2683 if (NXGE_IS_XAUI_PLATFORM(nxgep)) {
2684 op_ctr.bits.gpio_sel = 0x1;
2685 } else {
2686 op_ctr.bits.gpio_sel = 0x3;
2687 }
2688 if ((status = nxge_mdio_write(nxgep, phy_port_addr,
2689 BCM8704_USER_DEV3_ADDR, BCM8704_USER_OPTICS_DIGITAL_CTRL_REG,
2690 op_ctr.value)) != NXGE_OK)
2691 goto fail;
2692
2693 NXGE_DELAY(1000000);
2694
2695 /*
2696 * Set XAUI link tunables from OBP if present.
2697 */
2698 NXGE_SET_PHY_TUNABLES(nxgep, phy_port_addr, status);
2699 if (status != NXGE_OK) {
2700 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2701 "nxge_BCM8704_xcvr_init: Failed setting PHY tunables"));
2702 goto fail;
2703 }
2704
2705 /* Set BCM8704 Internal Loopback mode if necessary */
2706 if ((status = nxge_mdio_read(nxgep, phy_port_addr,
2707 BCM8704_PCS_DEV_ADDR, BCM8704_PCS_CONTROL_REG, &pcs_ctl.value))
2708 != NXGE_OK)
2709 goto fail;
2710 if (nxgep->statsp->port_stats.lb_mode == nxge_lb_phy10g)
2711 pcs_ctl.bits.loopback = 1;
2712 else
2713 pcs_ctl.bits.loopback = 0;
2714 if ((status = nxge_mdio_write(nxgep, phy_port_addr,
2715 BCM8704_PCS_DEV_ADDR, BCM8704_PCS_CONTROL_REG, pcs_ctl.value))
2716 != NXGE_OK)
2717 goto fail;
2718
2719 status = nxge_mdio_read(nxgep, phy_port_addr, 0x1, 0xA, &val);
2720 if (status != NXGE_OK)
2721 goto fail;
2722 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
2723 "BCM8704 port<%d> Dev 1 Reg 0xA = 0x%x\n", portn, val));
2724 status = nxge_mdio_read(nxgep, phy_port_addr, 0x3, 0x20, &val);
2725 if (status != NXGE_OK)
2726 goto fail;
2727 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
2728 "BCM8704 port<%d> Dev 3 Reg 0x20 = 0x%x\n", portn, val));
2729 status = nxge_mdio_read(nxgep, phy_port_addr, 0x4, 0x18, &val);
2730 if (status != NXGE_OK)
2731 goto fail;
2732 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
2733 "BCM8704 port<%d> Dev 4 Reg 0x18 = 0x%x\n", portn, val));
2734
2735 #ifdef NXGE_DEBUG
2736 /* Diagnose link issue if link is not up */
2737 status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_USER_DEV3_ADDR,
2738 BCM8704_USER_ANALOG_STATUS0_REG,
2739 &val);
2740 if (status != NXGE_OK)
2741 goto fail;
2742
2743 status = nxge_mdio_read(nxgep, phy_port_addr,
2744 BCM8704_USER_DEV3_ADDR, BCM8704_USER_ANALOG_STATUS0_REG, &val);
2745 if (status != NXGE_OK)
2746 goto fail;
2747
2748 status = nxge_mdio_read(nxgep, phy_port_addr,
2749 BCM8704_USER_DEV3_ADDR, BCM8704_USER_TX_ALARM_STATUS_REG, &val1);
2750 if (status != NXGE_OK)
2751 goto fail;
2752
2753 status = nxge_mdio_read(nxgep, phy_port_addr,
2754 BCM8704_USER_DEV3_ADDR, BCM8704_USER_TX_ALARM_STATUS_REG, &val1);
2755 if (status != NXGE_OK)
2756 goto fail;
2757
2758 if (val != 0x3FC) {
2759 if ((val == 0x43BC) && (val1 != 0)) {
2760 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
2761 "Cable not connected to peer or bad"
2762 " cable on port<%d>\n", portn));
2763 } else if (val == 0x639C) {
2764 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2765 "Optical module (XFP) is bad or absent"
2766 " on port<%d>\n", portn));
2767 }
2768 }
2769 #endif
2770
2771 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_BCM8704_xcvr_init: port<%d>",
2772 portn));
2773 return (NXGE_OK);
2774
2775 fail:
2776 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2777 "nxge_BCM8704_xcvr_init: failed to initialize transceiver for "
2778 "port<%d>", nxgep->mac.portnum));
2779 return (NXGE_ERROR);
2780 }
2781
2782 /* Initialize the BCM 8706 Transceiver */
2783
2784 static nxge_status_t
nxge_BCM8706_xcvr_init(p_nxge_t nxgep)2785 nxge_BCM8706_xcvr_init(p_nxge_t nxgep)
2786 {
2787 uint8_t phy_port_addr;
2788 phyxs_control_t phyxs_ctl;
2789 pcs_control_t pcs_ctl;
2790 uint32_t delay = 0;
2791 optics_dcntr_t op_ctr;
2792 nxge_status_t status = NXGE_OK;
2793 #ifdef NXGE_DEBUG
2794 uint8_t portn = nxgep->mac.portnum;
2795 #endif
2796
2797 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_BCM8706_xcvr_init: port<%d>",
2798 portn));
2799
2800 phy_port_addr = nxgep->statsp->mac_stats.xcvr_portn;
2801
2802 /* Reset the transceiver */
2803 if ((status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR,
2804 BCM8704_PHYXS_CONTROL_REG, &phyxs_ctl.value)) != NXGE_OK)
2805 goto fail;
2806
2807 phyxs_ctl.bits.reset = 1;
2808 if ((status = nxge_mdio_write(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR,
2809 BCM8704_PHYXS_CONTROL_REG, phyxs_ctl.value)) != NXGE_OK)
2810 goto fail;
2811 do {
2812 drv_usecwait(500);
2813 if ((status = nxge_mdio_read(nxgep, phy_port_addr,
2814 BCM8704_PHYXS_ADDR, BCM8704_PHYXS_CONTROL_REG,
2815 &phyxs_ctl.value)) != NXGE_OK)
2816 goto fail;
2817 delay++;
2818 } while ((phyxs_ctl.bits.reset) && (delay < 100));
2819
2820 if (delay == 100) {
2821 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_xcvr_init: "
2822 "failed to reset Transceiver on port<%d>", portn));
2823 status = NXGE_ERROR;
2824 goto fail;
2825 }
2826
2827 NXGE_DELAY(1000000);
2828
2829 /*
2830 * Set XAUI link tunables from OBP if present.
2831 */
2832 NXGE_SET_PHY_TUNABLES(nxgep, phy_port_addr, status);
2833 if (status != NXGE_OK) {
2834 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2835 "nxge_BCM8706_xcvr_init: Failed setting PHY tunables"));
2836 goto fail;
2837 }
2838
2839 /* Set BCM8706 Internal Loopback mode if necessary */
2840 if ((status = nxge_mdio_read(nxgep, phy_port_addr,
2841 BCM8704_PCS_DEV_ADDR, BCM8704_PCS_CONTROL_REG, &pcs_ctl.value))
2842 != NXGE_OK)
2843 goto fail;
2844 if (nxgep->statsp->port_stats.lb_mode == nxge_lb_phy10g)
2845 pcs_ctl.bits.loopback = 1;
2846 else
2847 pcs_ctl.bits.loopback = 0;
2848 if ((status = nxge_mdio_write(nxgep, phy_port_addr,
2849 BCM8704_PCS_DEV_ADDR, BCM8704_PCS_CONTROL_REG, pcs_ctl.value))
2850 != NXGE_OK)
2851 goto fail;
2852
2853 /* Enable Tx and Rx LEDs to be driven by traffic */
2854 if ((status = nxge_mdio_read(nxgep, phy_port_addr,
2855 BCM8704_USER_DEV3_ADDR, BCM8704_USER_OPTICS_DIGITAL_CTRL_REG,
2856 &op_ctr.value)) != NXGE_OK)
2857 goto fail;
2858 op_ctr.bits.gpio_sel = 0x3;
2859 op_ctr.bits.res2 = 0x1;
2860
2861 if ((status = nxge_mdio_write(nxgep, phy_port_addr,
2862 BCM8704_USER_DEV3_ADDR, BCM8704_USER_OPTICS_DIGITAL_CTRL_REG,
2863 op_ctr.value)) != NXGE_OK)
2864 goto fail;
2865
2866 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_BCM8706_xcvr_init: port<%d>",
2867 portn));
2868 return (NXGE_OK);
2869
2870 fail:
2871 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2872 "nxge_BCM8706_xcvr_init: failed to initialize transceiver for "
2873 "port<%d>", nxgep->mac.portnum));
2874 return (status);
2875 }
2876
2877 static int
nxge_nlp2020_i2c_read(p_nxge_t nxgep,uint8_t ctrl_port,uint16_t address,uint16_t reg,uint8_t * data)2878 nxge_nlp2020_i2c_read(p_nxge_t nxgep, uint8_t ctrl_port, uint16_t address,
2879 uint16_t reg, uint8_t *data)
2880 {
2881 int phy_dev, phy_reg;
2882 uint16_t phy_data = 0;
2883 uint16_t stat;
2884 uint8_t count = 100;
2885
2886 /*
2887 * NLP2020_I2C_SNOOP_ADDR_REG [15:9][1] - Address
2888 * NLP2020_I2C_SNOOP_ADDR_REG[7:0] - register in the xcvr's i2c
2889 */
2890 phy_dev = NLP2020_I2C_SNOOP_DEV_ADDR;
2891 phy_reg = NLP2020_I2C_SNOOP_ADDR_REG;
2892 phy_data = ((address + 1) << NLP2020_XCVR_I2C_ADDR_SH) | reg;
2893 if (nxge_mdio_write(nxgep, ctrl_port,
2894 phy_dev, phy_reg, phy_data) != NXGE_OK)
2895 goto fail;
2896
2897 phy_reg = NLP2020_I2C_SNOOP_STAT_REG;
2898 (void) nxge_mdio_read(nxgep, ctrl_port, phy_dev, phy_reg, &stat);
2899 while ((stat != 0x01) && (count-- > 0)) {
2900 (void) nxge_mdio_read(nxgep, ctrl_port, phy_dev, phy_reg,
2901 &stat);
2902 }
2903 if (count) {
2904 phy_reg = NLP2020_I2C_SNOOP_DATA_REG;
2905 (void) nxge_mdio_read(nxgep, ctrl_port, phy_dev, phy_reg,
2906 &phy_data);
2907 *data = (phy_data >> 8);
2908 return (0);
2909 }
2910 fail:
2911 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2912 "nxge_nlp2020_i2c_read: FAILED"));
2913 return (1);
2914
2915 }
2916
2917 /* Initialize the Netlogic AEL2020 Transceiver */
2918
2919 #define NLP_INI_WAIT 1
2920 #define NLP_INI_STOP 0
2921
2922 static nxge_nlp_initseq_t nlp2020_revC_fiber_init[] = {
2923 {0x1C003, 0x3101},
2924 {0x1CC01, 0x488a},
2925 {0x1CB1B, 0x0200},
2926 {0x1CB1C, 0x00f0},
2927 {0x1CC06, 0x00e0},
2928 {NLP_INI_STOP, 0},
2929 };
2930
2931 static nxge_nlp_initseq_t nlp2020_revC_copper_init[] = {
2932
2933 {0x1C003, 0x3101},
2934 {0x1CD40, 0x0001},
2935
2936 {0x1CA12, 0x0100},
2937 {0x1CA22, 0x0100},
2938 {0x1CA42, 0x0100},
2939 {0x1C20D, 0x0002},
2940 {NLP_INI_WAIT, 100},
2941
2942 {0x1ff28, 0x4001},
2943 {0x1ff2A, 0x004A},
2944 {NLP_INI_WAIT, 500},
2945
2946 {0x1d000, 0x5200},
2947 {NLP_INI_WAIT, 500},
2948
2949 {0x1d800, 0x4009},
2950 {0x1d801, 0x2fff},
2951 {0x1d802, 0x300f},
2952 {0x1d803, 0x40aa},
2953 {0x1d804, 0x401c},
2954 {0x1d805, 0x401e},
2955 {0x1d806, 0x20c5},
2956 {0x1d807, 0x3c05},
2957 {0x1d808, 0x6536},
2958 {0x1d809, 0x2fe4},
2959 {0x1d80a, 0x3dc4},
2960 {0x1d80b, 0x6624},
2961 {0x1d80c, 0x2ff4},
2962 {0x1d80d, 0x3dc4},
2963 {0x1d80e, 0x2035},
2964 {0x1d80f, 0x30a5},
2965 {0x1d810, 0x6524},
2966 {0x1d811, 0x2ca2},
2967 {0x1d812, 0x3012},
2968 {0x1d813, 0x1002},
2969 {0x1d814, 0x2882},
2970 {0x1d815, 0x3022},
2971 {0x1d816, 0x1002},
2972 {0x1d817, 0x2972},
2973 {0x1d818, 0x3022},
2974 {0x1d819, 0x1002},
2975 {0x1d81a, 0x2892},
2976 {0x1d81b, 0x3012},
2977 {0x1d81c, 0x1002},
2978 {0x1d81d, 0x24e2},
2979 {0x1d81e, 0x3022},
2980 {0x1d81f, 0x1002},
2981 {0x1d820, 0x27e2},
2982 {0x1d821, 0x3012},
2983 {0x1d822, 0x1002},
2984 {0x1d823, 0x2422},
2985 {0x1d824, 0x3022},
2986 {0x1d825, 0x1002},
2987 {0x1d826, 0x22cd},
2988 {0x1d827, 0x301d},
2989 {0x1d828, 0x2992},
2990 {0x1d829, 0x3022},
2991 {0x1d82a, 0x1002},
2992 {0x1d82b, 0x5553},
2993 {0x1d82c, 0x0307},
2994 {0x1d82d, 0x2572},
2995 {0x1d82e, 0x3022},
2996 {0x1d82f, 0x1002},
2997 {0x1d830, 0x21a2},
2998 {0x1d831, 0x3012},
2999 {0x1d832, 0x1002},
3000 {0x1d833, 0x4016},
3001 {0x1d834, 0x5e63},
3002 {0x1d835, 0x0344},
3003 {0x1d836, 0x21a2},
3004 {0x1d837, 0x3012},
3005 {0x1d838, 0x1002},
3006 {0x1d839, 0x400e},
3007 {0x1d83a, 0x2572},
3008 {0x1d83b, 0x3022},
3009 {0x1d83c, 0x1002},
3010 {0x1d83d, 0x2b22},
3011 {0x1d83e, 0x3012},
3012 {0x1d83f, 0x1002},
3013 {0x1d840, 0x28e2},
3014 {0x1d841, 0x3022},
3015 {0x1d842, 0x1002},
3016 {0x1d843, 0x2782},
3017 {0x1d844, 0x3022},
3018 {0x1d845, 0x1002},
3019 {0x1d846, 0x2fa4},
3020 {0x1d847, 0x3dc4},
3021 {0x1d848, 0x6624},
3022 {0x1d849, 0x2e8b},
3023 {0x1d84a, 0x303b},
3024 {0x1d84b, 0x56b3},
3025 {0x1d84c, 0x03c6},
3026 {0x1d84d, 0x866b},
3027 {0x1d84e, 0x400c},
3028 {0x1d84f, 0x2782},
3029 {0x1d850, 0x3012},
3030 {0x1d851, 0x1002},
3031 {0x1d852, 0x2c4b},
3032 {0x1d853, 0x309b},
3033 {0x1d854, 0x56b3},
3034 {0x1d855, 0x03c3},
3035 {0x1d856, 0x866b},
3036 {0x1d857, 0x400c},
3037 {0x1d858, 0x22a2},
3038 {0x1d859, 0x3022},
3039 {0x1d85a, 0x1002},
3040 {0x1d85b, 0x28e2},
3041 {0x1d85c, 0x3022},
3042 {0x1d85d, 0x1002},
3043 {0x1d85e, 0x2782},
3044 {0x1d85f, 0x3022},
3045 {0x1d860, 0x1002},
3046 {0x1d861, 0x2fb4},
3047 {0x1d862, 0x3dc4},
3048 {0x1d863, 0x6624},
3049 {0x1d864, 0x56b3},
3050 {0x1d865, 0x03c3},
3051 {0x1d866, 0x866b},
3052 {0x1d867, 0x401c},
3053 {0x1d868, 0x2c45},
3054 {0x1d869, 0x3095},
3055 {0x1d86a, 0x5b53},
3056 {0x1d86b, 0x23d2},
3057 {0x1d86c, 0x3012},
3058 {0x1d86d, 0x13c2},
3059 {0x1d86e, 0x5cc3},
3060 {0x1d86f, 0x2782},
3061 {0x1d870, 0x3012},
3062 {0x1d871, 0x1312},
3063 {0x1d872, 0x2b22},
3064 {0x1d873, 0x3012},
3065 {0x1d874, 0x1002},
3066 {0x1d875, 0x28e2},
3067 {0x1d876, 0x3022},
3068 {0x1d877, 0x1002},
3069 {0x1d878, 0x2672},
3070 {0x1d879, 0x3022},
3071 {0x1d87a, 0x1002},
3072 {0x1d87b, 0x21a2},
3073 {0x1d87c, 0x3012},
3074 {0x1d87d, 0x1002},
3075 {0x1d87e, 0x628f},
3076 {0x1d87f, 0x2985},
3077 {0x1d880, 0x33a5},
3078 {0x1d881, 0x2782},
3079 {0x1d882, 0x3022},
3080 {0x1d883, 0x1002},
3081 {0x1d884, 0x5653},
3082 {0x1d885, 0x03d2},
3083 {0x1d886, 0x401e},
3084 {0x1d887, 0x6f72},
3085 {0x1d888, 0x1002},
3086 {0x1d889, 0x628f},
3087 {0x1d88a, 0x2304},
3088 {0x1d88b, 0x3c84},
3089 {0x1d88c, 0x6436},
3090 {0x1d88d, 0xdff4},
3091 {0x1d88e, 0x6436},
3092 {0x1d88f, 0x2ff5},
3093 {0x1d890, 0x3005},
3094 {0x1d891, 0x8656},
3095 {0x1d892, 0xdfba},
3096 {0x1d893, 0x56a3},
3097 {0x1d894, 0xd05a},
3098 {0x1d895, 0x29e2},
3099 {0x1d896, 0x3012},
3100 {0x1d897, 0x1392},
3101 {0x1d898, 0xd05a},
3102 {0x1d899, 0x56a3},
3103 {0x1d89a, 0xdfba},
3104 {0x1d89b, 0x0383},
3105 {0x1d89c, 0x6f72},
3106 {0x1d89d, 0x1002},
3107 {0x1d89e, 0x2a64},
3108 {0x1d89f, 0x3014},
3109 {0x1d8a0, 0x2005},
3110 {0x1d8a1, 0x3d75},
3111 {0x1d8a2, 0xc451},
3112 {0x1d8a3, 0x2a42},
3113 {0x1d8a4, 0x3022},
3114 {0x1d8a5, 0x1002},
3115 {0x1d8a6, 0x178c},
3116 {0x1d8a7, 0x1898},
3117 {0x1d8a8, 0x19a4},
3118 {0x1d8a9, 0x1ab0},
3119 {0x1d8aa, 0x1bbc},
3120 {0x1d8ab, 0x1cc8},
3121 {0x1d8ac, 0x1dd3},
3122 {0x1d8ad, 0x1ede},
3123 {0x1d8ae, 0x1fe9},
3124 {0x1d8af, 0x20f4},
3125 {0x1d8b0, 0x21ff},
3126 {0x1d8b1, 0x0000},
3127 {0x1d8b2, 0x27e1},
3128 {0x1d8b3, 0x3021},
3129 {0x1d8b4, 0x1001},
3130 {0x1d8b5, 0xc620},
3131 {0x1d8b6, 0x0000},
3132 {0x1d8b7, 0xc621},
3133 {0x1d8b8, 0x0000},
3134 {0x1d8b9, 0xc622},
3135 {0x1d8ba, 0x00e2},
3136 {0x1d8bb, 0xc623},
3137 {0x1d8bc, 0x007f},
3138 {0x1d8bd, 0xc624},
3139 {0x1d8be, 0x00ce},
3140 {0x1d8bf, 0xc625},
3141 {0x1d8c0, 0x0000},
3142 {0x1d8c1, 0xc627},
3143 {0x1d8c2, 0x0000},
3144 {0x1d8c3, 0xc628},
3145 {0x1d8c4, 0x0000},
3146 {0x1d8c5, 0xc90a},
3147 {0x1d8c6, 0x3a7c},
3148 {0x1d8c7, 0xc62c},
3149 {0x1d8c8, 0x0000},
3150 {0x1d8c9, 0x0000},
3151 {0x1d8ca, 0x27e1},
3152 {0x1d8cb, 0x3021},
3153 {0x1d8cc, 0x1001},
3154 {0x1d8cd, 0xc502},
3155 {0x1d8ce, 0x53ac},
3156 {0x1d8cf, 0xc503},
3157 {0x1d8d0, 0x2cd3},
3158 {0x1d8d1, 0xc600},
3159 {0x1d8d2, 0x2a6e},
3160 {0x1d8d3, 0xc601},
3161 {0x1d8d4, 0x2a2c},
3162 {0x1d8d5, 0xc605},
3163 {0x1d8d6, 0x5557},
3164 {0x1d8d7, 0xc60c},
3165 {0x1d8d8, 0x5400},
3166 {0x1d8d9, 0xc710},
3167 {0x1d8da, 0x0700},
3168 {0x1d8db, 0xc711},
3169 {0x1d8dc, 0x0f06},
3170 {0x1d8dd, 0xc718},
3171 {0x1d8de, 0x0700},
3172 {0x1d8df, 0xc719},
3173 {0x1d8e0, 0x0f06},
3174 {0x1d8e1, 0xc720},
3175 {0x1d8e2, 0x4700},
3176 {0x1d8e3, 0xc721},
3177 {0x1d8e4, 0x0f06},
3178 {0x1d8e5, 0xc728},
3179 {0x1d8e6, 0x0700},
3180 {0x1d8e7, 0xc729},
3181 {0x1d8e8, 0x1207},
3182 {0x1d8e9, 0xc801},
3183 {0x1d8ea, 0x7f50},
3184 {0x1d8eb, 0xc802},
3185 {0x1d8ec, 0x7760},
3186 {0x1d8ed, 0xc803},
3187 {0x1d8ee, 0x7fce},
3188 {0x1d8ef, 0xc804},
3189 {0x1d8f0, 0x520e},
3190 {0x1d8f1, 0xc805},
3191 {0x1d8f2, 0x5c11},
3192 {0x1d8f3, 0xc806},
3193 {0x1d8f4, 0x3c51},
3194 {0x1d8f5, 0xc807},
3195 {0x1d8f6, 0x4061},
3196 {0x1d8f7, 0xc808},
3197 {0x1d8f8, 0x49c1},
3198 {0x1d8f9, 0xc809},
3199 {0x1d8fa, 0x3840},
3200 {0x1d8fb, 0xc80a},
3201 {0x1d8fc, 0x0000},
3202 {0x1d8fd, 0xc821},
3203 {0x1d8fe, 0x0002},
3204 {0x1d8ff, 0xc822},
3205 {0x1d900, 0x0046},
3206 {0x1d901, 0xc844},
3207 {0x1d902, 0x182f},
3208 {0x1d903, 0xc849},
3209 {0x1d904, 0x0400},
3210 {0x1d905, 0xc84a},
3211 {0x1d906, 0x0002},
3212 {0x1d907, 0xc013},
3213 {0x1d908, 0xf341},
3214 {0x1d909, 0xc084},
3215 {0x1d90a, 0x0030},
3216 {0x1d90b, 0xc904},
3217 {0x1d90c, 0x1401},
3218 {0x1d90d, 0xcb0c},
3219 {0x1d90e, 0x0004},
3220 {0x1d90f, 0xcb0e},
3221 {0x1d910, 0xa00a},
3222 {0x1d911, 0xcb0f},
3223 {0x1d912, 0xc0c0},
3224 {0x1d913, 0xcb10},
3225 {0x1d914, 0xc0c0},
3226 {0x1d915, 0xcb11},
3227 {0x1d916, 0x00a0},
3228 {0x1d917, 0xcb12},
3229 {0x1d918, 0x0007},
3230 {0x1d919, 0xc241},
3231 {0x1d91a, 0xa000},
3232 {0x1d91b, 0xc243},
3233 {0x1d91c, 0x7fe0},
3234 {0x1d91d, 0xc604},
3235 {0x1d91e, 0x000e},
3236 {0x1d91f, 0xc609},
3237 {0x1d920, 0x00f5},
3238 {0x1d921, 0x0c61},
3239 {0x1d922, 0x000e},
3240 {0x1d923, 0xc660},
3241 {0x1d924, 0x9600},
3242 {0x1d925, 0xc687},
3243 {0x1d926, 0x0004},
3244 {0x1d927, 0xc60a},
3245 {0x1d928, 0x04f5},
3246 {0x1d929, 0x0000},
3247 {0x1d92a, 0x27e1},
3248 {0x1d92b, 0x3021},
3249 {0x1d92c, 0x1001},
3250 {0x1d92d, 0xc620},
3251 {0x1d92e, 0x14e5},
3252 {0x1d92f, 0xc621},
3253 {0x1d930, 0xc53d},
3254 {0x1d931, 0xc622},
3255 {0x1d932, 0x3cbe},
3256 {0x1d933, 0xc623},
3257 {0x1d934, 0x4452},
3258 {0x1d935, 0xc624},
3259 {0x1d936, 0xc5c5},
3260 {0x1d937, 0xc625},
3261 {0x1d938, 0xe01e},
3262 {0x1d939, 0xc627},
3263 {0x1d93a, 0x0000},
3264 {0x1d93b, 0xc628},
3265 {0x1d93c, 0x0000},
3266 {0x1d93d, 0xc62c},
3267 {0x1d93e, 0x0000},
3268 {0x1d93f, 0xc90a},
3269 {0x1d940, 0x3a7c},
3270 {0x1d941, 0x0000},
3271 {0x1d942, 0x2b84},
3272 {0x1d943, 0x3c74},
3273 {0x1d944, 0x6435},
3274 {0x1d945, 0xdff4},
3275 {0x1d946, 0x6435},
3276 {0x1d947, 0x2806},
3277 {0x1d948, 0x3006},
3278 {0x1d949, 0x8565},
3279 {0x1d94a, 0x2b24},
3280 {0x1d94b, 0x3c24},
3281 {0x1d94c, 0x6436},
3282 {0x1d94d, 0x1002},
3283 {0x1d94e, 0x2b24},
3284 {0x1d94f, 0x3c24},
3285 {0x1d950, 0x6436},
3286 {0x1d951, 0x4045},
3287 {0x1d952, 0x8656},
3288 {0x1d953, 0x5663},
3289 {0x1d954, 0x0302},
3290 {0x1d955, 0x401e},
3291 {0x1d956, 0x1002},
3292 {0x1d957, 0x2017},
3293 {0x1d958, 0x3b17},
3294 {0x1d959, 0x2084},
3295 {0x1d95a, 0x3c14},
3296 {0x1d95b, 0x6724},
3297 {0x1d95c, 0x2807},
3298 {0x1d95d, 0x31a7},
3299 {0x1d95e, 0x20c4},
3300 {0x1d95f, 0x3c24},
3301 {0x1d960, 0x6724},
3302 {0x1d961, 0x2ff7},
3303 {0x1d962, 0x30f7},
3304 {0x1d963, 0x20c4},
3305 {0x1d964, 0x3c04},
3306 {0x1d965, 0x6724},
3307 {0x1d966, 0x1002},
3308 {0x1d967, 0x2807},
3309 {0x1d968, 0x3187},
3310 {0x1d969, 0x20c4},
3311 {0x1d96a, 0x3c24},
3312 {0x1d96b, 0x6724},
3313 {0x1d96c, 0x2fe4},
3314 {0x1d96d, 0x3dc4},
3315 {0x1d96e, 0x6437},
3316 {0x1d96f, 0x20c4},
3317 {0x1d970, 0x3c04},
3318 {0x1d971, 0x6724},
3319 {0x1d972, 0x2017},
3320 {0x1d973, 0x3d17},
3321 {0x1d974, 0x2084},
3322 {0x1d975, 0x3c14},
3323 {0x1d976, 0x6724},
3324 {0x1d977, 0x1002},
3325 {0x1d978, 0x24f4},
3326 {0x1d979, 0x3c64},
3327 {0x1d97a, 0x6436},
3328 {0x1d97b, 0xdff4},
3329 {0x1d97c, 0x6436},
3330 {0x1d97d, 0x1002},
3331 {0x1d97e, 0x2006},
3332 {0x1d97f, 0x3d76},
3333 {0x1d980, 0xc161},
3334 {0x1d981, 0x6134},
3335 {0x1d982, 0x6135},
3336 {0x1d983, 0x5443},
3337 {0x1d984, 0x0303},
3338 {0x1d985, 0x6524},
3339 {0x1d986, 0x00fb},
3340 {0x1d987, 0x1002},
3341 {0x1d988, 0x20d4},
3342 {0x1d989, 0x3c24},
3343 {0x1d98a, 0x2025},
3344 {0x1d98b, 0x3005},
3345 {0x1d98c, 0x6524},
3346 {0x1d98d, 0x1002},
3347 {0x1d98e, 0xd019},
3348 {0x1d98f, 0x2104},
3349 {0x1d990, 0x3c24},
3350 {0x1d991, 0x2105},
3351 {0x1d992, 0x3805},
3352 {0x1d993, 0x6524},
3353 {0x1d994, 0xdff4},
3354 {0x1d995, 0x4005},
3355 {0x1d996, 0x6524},
3356 {0x1d997, 0x2e8d},
3357 {0x1d998, 0x303d},
3358 {0x1d999, 0x2408},
3359 {0x1d99a, 0x35d8},
3360 {0x1d99b, 0x5dd3},
3361 {0x1d99c, 0x0307},
3362 {0x1d99d, 0x8887},
3363 {0x1d99e, 0x63a7},
3364 {0x1d99f, 0x8887},
3365 {0x1d9a0, 0x63a7},
3366 {0x1d9a1, 0xdffd},
3367 {0x1d9a2, 0x00f9},
3368 {0x1d9a3, 0x1002},
3369 {0x1d9a4, 0x866a},
3370 {0x1d9a5, 0x6138},
3371 {0x1d9a6, 0x5883},
3372 {0x1d9a7, 0x2b42},
3373 {0x1d9a8, 0x3022},
3374 {0x1d9a9, 0x1302},
3375 {0x1d9aa, 0x2ff7},
3376 {0x1d9ab, 0x3007},
3377 {0x1d9ac, 0x8785},
3378 {0x1d9ad, 0xb887},
3379 {0x1d9ae, 0x8786},
3380 {0x1d9af, 0xb8c6},
3381 {0x1d9b0, 0x5a53},
3382 {0x1d9b1, 0x2a52},
3383 {0x1d9b2, 0x3022},
3384 {0x1d9b3, 0x13c2},
3385 {0x1d9b4, 0x2474},
3386 {0x1d9b5, 0x3c84},
3387 {0x1d9b6, 0x64d7},
3388 {0x1d9b7, 0x64d7},
3389 {0x1d9b8, 0x2ff5},
3390 {0x1d9b9, 0x3c05},
3391 {0x1d9ba, 0x8757},
3392 {0x1d9bb, 0xb886},
3393 {0x1d9bc, 0x9767},
3394 {0x1d9bd, 0x67c4},
3395 {0x1d9be, 0x6f72},
3396 {0x1d9bf, 0x1002},
3397 {0x1d9c0, 0x0000},
3398 {0x1d080, 0x0100},
3399 {0x1d092, 0x0000},
3400 {NLP_INI_STOP, 0},
3401 };
3402
3403 static nxge_status_t
nxge_nlp2020_xcvr_init(p_nxge_t nxgep)3404 nxge_nlp2020_xcvr_init(p_nxge_t nxgep)
3405 {
3406 uint8_t phy_port_addr;
3407 nxge_status_t status = NXGE_OK;
3408 uint16_t ctrl_reg, rst_val, pmd_ctl, rx_los;
3409 int i = 0, count = 1000;
3410
3411 uint8_t connector = 0, len, lpm;
3412 p_nxge_nlp_initseq_t initseq;
3413 uint16_t dev, reg, val;
3414
3415 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_nlp2020_xcvr_init: "
3416 "port<%d>, phyaddr[0x%x]", nxgep->mac.portnum,
3417 nxgep->statsp->mac_stats.xcvr_portn));
3418
3419 phy_port_addr = nxgep->statsp->mac_stats.xcvr_portn;
3420
3421 /* Reset the transceiver */
3422 rst_val = ctrl_reg = NLP2020_PMA_PMD_PHY_RST;
3423 if ((status = nxge_mdio_write(nxgep, phy_port_addr,
3424 NLP2020_PMA_PMD_ADDR, NLP2020_PMA_PMD_CTL_REG, rst_val))
3425 != NXGE_OK)
3426 goto fail;
3427 while ((count--) && (ctrl_reg & rst_val)) {
3428 drv_usecwait(1000);
3429 (void) nxge_mdio_read(nxgep, phy_port_addr,
3430 NLP2020_PMA_PMD_ADDR, NLP2020_PMA_PMD_CTL_REG, &ctrl_reg);
3431 }
3432 if (count == 0) {
3433 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_nlp2020_xcvr_init: "
3434 "PMA_PMD reset failed"));
3435 goto fail;
3436 }
3437
3438 /* Set loopback mode if required */
3439 /* Set PMA PMD system loopback */
3440 if ((status = nxge_mdio_read(nxgep, phy_port_addr,
3441 NLP2020_PMA_PMD_ADDR, NLP2020_PMA_PMD_CTL_REG, &pmd_ctl))
3442 != NXGE_OK)
3443 goto fail;
3444
3445 if (nxgep->statsp->port_stats.lb_mode == nxge_lb_phy10g)
3446 pmd_ctl |= 0x0001;
3447 else
3448 pmd_ctl &= 0xfffe;
3449 if ((status = nxge_mdio_write(nxgep, phy_port_addr,
3450 NLP2020_PMA_PMD_ADDR, NLP2020_PMA_PMD_CTL_REG, pmd_ctl))
3451 != NXGE_OK)
3452 goto fail;
3453
3454 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_nlp2020_xcvr_init: "
3455 "setting LB, wrote NLP2020_PMA_PMD_CTL_REG[0x%x]", pmd_ctl));
3456
3457 /* Check connector details using I2c */
3458 if (nxge_nlp2020_i2c_read(nxgep, phy_port_addr, NLP2020_XCVR_I2C_ADDR,
3459 QSFP_MSA_CONN_REG, &connector) == 1) {
3460 goto fail;
3461 }
3462
3463 switch (connector) {
3464 case SFPP_FIBER:
3465 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3466 "nxge_nlp2020_xcvr_init: SFPP_FIBER detected"));
3467 initseq = nlp2020_revC_fiber_init;
3468 nxgep->nlp_conn = NXGE_NLP_CONN_FIBER;
3469 break;
3470 case QSFP_FIBER:
3471 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3472 "nxge_nlp2020_xcvr_init: QSFP_FIBER detected"));
3473 initseq = nlp2020_revC_fiber_init;
3474 nxgep->nlp_conn = NXGE_NLP_CONN_FIBER;
3475 break;
3476 case QSFP_COPPER_TWINAX:
3477 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3478 "nxge_nlp2020_xcvr_init: QSFP_COPPER_TWINAX/"
3479 "SFPP_COPPER_TWINAX detected"));
3480
3481 initseq = nlp2020_revC_copper_init;
3482 nxgep->nlp_conn = NXGE_NLP_CONN_COPPER_LT_7M;
3483 break;
3484 default:
3485 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
3486 "nxge_nlp2020_xcvr_init: Unknown type [0x%x] detected",
3487 "...setting to QSFP_FIBER",
3488 connector));
3489 initseq = nlp2020_revC_fiber_init;
3490 nxgep->nlp_conn = NXGE_NLP_CONN_FIBER;
3491 break;
3492 }
3493
3494 /* Run appropriate init sequence */
3495 for (i = 0; initseq[i].dev_reg != NLP_INI_STOP; i++) {
3496 dev = initseq[i].dev_reg >> 16;
3497 reg = initseq[i].dev_reg & 0xffff;
3498 val = initseq[i].val;
3499
3500 if (reg == NLP_INI_WAIT) {
3501 drv_usecwait(1000 * val);
3502 } else {
3503 if ((status = nxge_mdio_write(nxgep, phy_port_addr,
3504 dev, reg, val)) != NXGE_OK)
3505 goto fail;
3506 }
3507 }
3508
3509 /* rx_los inversion */
3510 if ((status = nxge_mdio_read(nxgep, phy_port_addr,
3511 NLP2020_PMA_PMD_ADDR, NLP2020_OPT_SET_REG, &rx_los)) != NXGE_OK)
3512 goto fail;
3513
3514 rx_los &= ~(NLP2020_RXLOS_ACT_H);
3515
3516 if ((status = nxge_mdio_write(nxgep, phy_port_addr,
3517 NLP2020_PMA_PMD_ADDR, NLP2020_OPT_SET_REG, rx_los)) != NXGE_OK)
3518 goto fail;
3519
3520 if (nxge_nlp2020_i2c_read(nxgep, phy_port_addr, NLP2020_XCVR_I2C_ADDR,
3521 QSFP_MSA_LEN_REG, &len) == 1) {
3522 goto fail;
3523 }
3524
3525 if (nxge_nlp2020_i2c_read(nxgep, phy_port_addr, NLP2020_XCVR_I2C_ADDR,
3526 QSFP_MSA_LPM_REG, &lpm) == 1) {
3527 goto fail;
3528 }
3529 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3530 "nxge_nlp2020_xcvr_init: len[0x%x] lpm[0x%x]", len, lpm));
3531
3532 if (connector == QSFP_COPPER_TWINAX) {
3533 if (len >= 7) {
3534 nxgep->nlp_conn = NXGE_NLP_CONN_COPPER_7M_ABOVE;
3535 /* enable pre-emphasis */
3536 (void) nxge_mdio_write(nxgep, phy_port_addr,
3537 NLP2020_PMA_PMD_ADDR, NLP2020_TX_DRV_CTL1_REG,
3538 NLP2020_TX_DRV_CTL1_PREEMP_EN);
3539 /* write emphasis value */
3540 (void) nxge_mdio_write(nxgep, phy_port_addr,
3541 NLP2020_PMA_PMD_ADDR, NLP2020_TX_DRV_CTL2_REG,
3542 NLP2020_TX_DRV_CTL2_EMP_VAL);
3543 /* stop microcontroller */
3544 (void) nxge_mdio_write(nxgep, phy_port_addr,
3545 NLP2020_PMA_PMD_ADDR, NLP2020_UC_CTL_REG,
3546 NLP2020_UC_CTL_STOP);
3547 /* reset program counter */
3548 (void) nxge_mdio_write(nxgep, phy_port_addr,
3549 NLP2020_PMA_PMD_ADDR, NLP2020_UC_PC_START_REG,
3550 NLP2020_UC_PC_START_VAL);
3551 /* start microcontroller */
3552 (void) nxge_mdio_write(nxgep, phy_port_addr,
3553 NLP2020_PMA_PMD_ADDR, NLP2020_UC_CTL_REG,
3554 NLP2020_UC_CTL_START);
3555 }
3556 }
3557 if (lpm & QSFP_MSA_LPM_HIGH) {
3558 /* enable high power mode */
3559 (void) nxge_mdio_write(nxgep, phy_port_addr,
3560 NLP2020_GPIO_ADDR, NLP2020_GPIO_CTL_REG,
3561 NLP2020_GPIO_ACT);
3562 } else {
3563 /* revert to low power mode */
3564 (void) nxge_mdio_write(nxgep, phy_port_addr,
3565 NLP2020_GPIO_ADDR, NLP2020_GPIO_CTL_REG,
3566 NLP2020_GPIO_INACT);
3567 }
3568
3569 /*
3570 * Set XAUI link tunables from OBP if present.
3571 */
3572 NXGE_SET_PHY_TUNABLES(nxgep, phy_port_addr, status);
3573 if (status != NXGE_OK) {
3574 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
3575 "nxge_nlp2020_xcvr_init: Failed setting PHY tunables"));
3576 goto fail;
3577 }
3578
3579 /* It takes ~2s for EDC to settle */
3580 drv_usecwait(2000000);
3581
3582 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_nlp2020_xcvr_init: "
3583 "port<%d> phyaddr[0x%x]", nxgep->mac.portnum, phy_port_addr));
3584
3585 return (NXGE_OK);
3586
3587 fail:
3588 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
3589 "nxge_nlp2020_xcvr_init: failed to initialize transceiver for "
3590 "port<%d>", nxgep->mac.portnum));
3591 return (status);
3592 }
3593
nxge_is_nlp2020_phy(p_nxge_t nxgep)3594 static boolean_t nxge_is_nlp2020_phy(p_nxge_t nxgep)
3595 {
3596 uint8_t portn = NXGE_GET_PORT_NUM(nxgep->function_num);
3597 uint32_t pcs_id = 0;
3598 uint32_t pma_pmd_id = 0;
3599 uint8_t xcvr_addr = nxgep->nxge_hw_p->xcvr_addr[portn];
3600
3601 pma_pmd_id = nxge_get_cl45_pma_pmd_id(nxgep, xcvr_addr);
3602 pcs_id = nxge_get_cl45_pcs_id(nxgep, xcvr_addr);
3603
3604 if (((pma_pmd_id & NLP2020_DEV_ID_MASK) == NLP2020_DEV_ID) ||
3605 ((pcs_id & NLP2020_DEV_ID_MASK) == NLP2020_DEV_ID)) {
3606 return (B_TRUE);
3607 } else {
3608 return (B_FALSE);
3609 }
3610 }
3611
nxge_get_nlp2020_connector_type(p_nxge_t nxgep)3612 static uint8_t nxge_get_nlp2020_connector_type(p_nxge_t nxgep)
3613 {
3614 uint8_t portn = NXGE_GET_PORT_NUM(nxgep->function_num);
3615 uint8_t xcvr_addr = nxgep->nxge_hw_p->xcvr_addr[portn];
3616 uint8_t connector = 0;
3617
3618 (void) nxge_nlp2020_i2c_read(nxgep, xcvr_addr, NLP2020_XCVR_I2C_ADDR,
3619 QSFP_MSA_CONN_REG, &connector);
3620
3621 return (connector);
3622 }
3623
nxge_set_nlp2020_param(p_nxge_t nxgep)3624 static nxge_status_t nxge_set_nlp2020_param(p_nxge_t nxgep)
3625 {
3626 uint8_t connector = 0;
3627
3628 connector = nxge_get_nlp2020_connector_type(nxgep);
3629
3630 switch (connector) {
3631 case SFPP_FIBER:
3632 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3633 "nxge_set_nlp2020_param: SFPP_FIBER detected"));
3634 nxgep->mac.portmode = PORT_10G_FIBER;
3635 nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
3636 break;
3637 case QSFP_FIBER:
3638 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3639 "nxge_set_nlp2020_param: QSFP_FIBER detected"));
3640 nxgep->mac.portmode = PORT_10G_FIBER;
3641 nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
3642 break;
3643 case QSFP_COPPER_TWINAX:
3644 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3645 "nxge_set_nlp2020_param: QSFP_COPPER_TWINAX/"
3646 "SFPP_COPPER_TWINAX detected"));
3647 nxgep->mac.portmode = PORT_10G_COPPER;
3648 nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
3649 break;
3650 default:
3651 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
3652 "nxge_set_nlp2020_param: Unknown type [0x%x] detected"
3653 "...setting to QSFP_FIBER",
3654 connector));
3655 nxgep->mac.portmode = PORT_10G_FIBER;
3656 nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
3657 break;
3658 }
3659
3660 return (NXGE_OK);
3661 }
3662
3663 #define CHK_STAT(x) status = (x); if (status != NXGE_OK) goto fail
3664
3665 #define MRVL88X2011_RD(nxgep, port, d, r, p) \
3666 CHK_STAT(nxge_mdio_read(nxgep, port, d, r, p))
3667
3668 #define MRVL88X2011_WR(nxgep, port, d, r, p) \
3669 CHK_STAT(nxge_mdio_write(nxgep, port, d, r, p))
3670
3671
3672 static void
nxge_mrvl88x2011_led_blink_rate(p_nxge_t nxgep,uint16_t rate)3673 nxge_mrvl88x2011_led_blink_rate(p_nxge_t nxgep, uint16_t rate)
3674 {
3675 uint16_t value;
3676 uint8_t phy = nxgep->statsp->mac_stats.xcvr_portn;
3677
3678 if (nxge_mdio_read(nxgep, phy, MRVL_88X2011_USER_DEV2_ADDR,
3679 MRVL_88X2011_LED_BLINK_CTL, &value) == NXGE_OK) {
3680 value &= ~MRVL_88X2011_LED_BLK_MASK;
3681 value |= (rate << MRVL_88X2011_LED_BLK_SHIFT);
3682 (void) nxge_mdio_write(nxgep, phy,
3683 MRVL_88X2011_USER_DEV2_ADDR, MRVL_88X2011_LED_BLINK_CTL,
3684 value);
3685 }
3686 }
3687
3688 static nxge_status_t
nxge_mrvl88x2011_setup_lb(p_nxge_t nxgep)3689 nxge_mrvl88x2011_setup_lb(p_nxge_t nxgep)
3690 {
3691 nxge_status_t status;
3692 pcs_control_t pcs_ctl;
3693 uint8_t phy = nxgep->statsp->mac_stats.xcvr_portn;
3694
3695 MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV3_ADDR,
3696 MRVL_88X2011_PMA_PMD_CTL_1, &pcs_ctl.value);
3697
3698 if (nxgep->statsp->port_stats.lb_mode == nxge_lb_phy10g)
3699 pcs_ctl.bits.loopback = 1;
3700 else
3701 pcs_ctl.bits.loopback = 0;
3702
3703 MRVL88X2011_WR(nxgep, phy, MRVL_88X2011_USER_DEV3_ADDR,
3704 MRVL_88X2011_PMA_PMD_CTL_1, pcs_ctl.value);
3705
3706 fail:
3707 return (status);
3708 }
3709
3710
3711 static void
nxge_mrvl88x2011_led(p_nxge_t nxgep,uint16_t val)3712 nxge_mrvl88x2011_led(p_nxge_t nxgep, uint16_t val)
3713 {
3714 uint16_t val2;
3715 uint8_t phy = nxgep->statsp->mac_stats.xcvr_portn;
3716
3717 val2 = MRVL_88X2011_LED(MRVL_88X2011_LED_ACT, val);
3718 val2 &= ~MRVL_88X2011_LED(MRVL_88X2011_LED_ACT,
3719 MRVL_88X2011_LED_CTL_MASK);
3720 val2 |= MRVL_88X2011_LED(MRVL_88X2011_LED_ACT, val);
3721
3722 if (nxge_mdio_write(nxgep, phy, MRVL_88X2011_USER_DEV2_ADDR,
3723 MRVL_88X2011_LED_8_TO_11_CTL, val2) != NXGE_OK) {
3724 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
3725 "nxge_mrvl88x2011_led: nxge_mdio_write failed!!"));
3726 }
3727 }
3728
3729
3730 static nxge_status_t
nxge_mrvl88x2011_xcvr_init(p_nxge_t nxgep)3731 nxge_mrvl88x2011_xcvr_init(p_nxge_t nxgep)
3732 {
3733 uint8_t phy;
3734 nxge_status_t status;
3735 uint16_t clk;
3736
3737 phy = nxgep->statsp->mac_stats.xcvr_portn;
3738
3739 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3740 "==> nxge_mrvl88x2011_xcvr_init: port<%d> addr<0x%x>",
3741 nxgep->mac.portnum, phy));
3742
3743 /* Set LED functions */
3744 nxge_mrvl88x2011_led_blink_rate(nxgep, MRVL_88X2011_LED_BLK134MS);
3745 /* PCS activity */
3746 nxge_mrvl88x2011_led(nxgep, MRVL_88X2011_LED_ACT);
3747
3748 MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV3_ADDR,
3749 MRVL_88X2011_GEN_CTL, &clk);
3750 clk |= MRVL_88X2011_ENA_XFPREFCLK;
3751 MRVL88X2011_WR(nxgep, phy, MRVL_88X2011_USER_DEV3_ADDR,
3752 MRVL_88X2011_GEN_CTL, clk);
3753
3754 /* Set internal loopback mode if necessary */
3755
3756 CHK_STAT(nxge_mrvl88x2011_setup_lb(nxgep));
3757
3758 /* Enable PMD */
3759 MRVL88X2011_WR(nxgep, phy, MRVL_88X2011_USER_DEV1_ADDR,
3760 MRVL_88X2011_10G_PMD_TX_DIS, MRVL_88X2011_ENA_PMDTX);
3761
3762 NXGE_DEBUG_MSG((nxgep, MAC_CTL, " nxge_mrvl88x2011_reset: OK"));
3763
3764 fail:
3765 return (status);
3766 }
3767
3768
3769
3770 /* Initialize the 10G Transceiver */
3771
3772 static nxge_status_t
nxge_10G_xcvr_init(p_nxge_t nxgep)3773 nxge_10G_xcvr_init(p_nxge_t nxgep)
3774 {
3775 p_nxge_stats_t statsp;
3776 p_nxge_param_t param_arr = nxgep->param_arr;
3777 nxge_status_t status = NXGE_OK;
3778 #ifdef NXGE_DEBUG
3779 uint8_t portn = nxgep->mac.portnum;
3780 #endif
3781 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_10G_xcvr_init: port<%d>",
3782 portn));
3783
3784 statsp = nxgep->statsp;
3785
3786 /* Disable Link LEDs, with or without PHY */
3787 if (nxge_10g_link_led_off(nxgep) != NXGE_OK)
3788 goto done;
3789
3790 /* Skip MDIO, if PHY absent */
3791 if (nxgep->mac.portmode == PORT_10G_SERDES || nxgep->phy_absent) {
3792 goto done;
3793 }
3794
3795 /* Set Clause 45 */
3796 npi_mac_mif_set_indirect_mode(nxgep->npi_handle, B_TRUE);
3797
3798 switch (nxgep->chip_id) {
3799 case BCM8704_CHIP_ID:
3800 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_10G_xcvr_init: "
3801 "Chip ID 8704 [0x%x] for 10G xcvr", nxgep->chip_id));
3802 status = nxge_BCM8704_xcvr_init(nxgep);
3803 break;
3804 case BCM8706_CHIP_ID:
3805 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_10G_xcvr_init: "
3806 "Chip ID 8706 [0x%x] for 10G xcvr", nxgep->chip_id));
3807 status = nxge_BCM8706_xcvr_init(nxgep);
3808 break;
3809 case MRVL88X201X_CHIP_ID:
3810 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_10G_xcvr_init: "
3811 "Chip ID MRVL [0x%x] for 10G xcvr", nxgep->chip_id));
3812 status = nxge_mrvl88x2011_xcvr_init(nxgep);
3813 break;
3814 case NLP2020_CHIP_ID:
3815 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_10G_xcvr_init: "
3816 "Chip ID NL2020 [0x%x] for 10G xcvr", nxgep->chip_id));
3817 status = nxge_nlp2020_xcvr_init(nxgep);
3818 break;
3819 default:
3820 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_xcvr_init: "
3821 "Unknown chip ID 0x%x for 10G xcvr addr[%d]",
3822 nxgep->chip_id, nxgep->statsp->mac_stats.xcvr_portn));
3823 goto fail;
3824 }
3825
3826 if (status != NXGE_OK) {
3827 goto fail;
3828 }
3829 done:
3830 statsp->mac_stats.cap_10gfdx = 1;
3831 statsp->mac_stats.lp_cap_10gfdx = 1;
3832 statsp->mac_stats.adv_cap_asmpause =
3833 param_arr[param_anar_asmpause].value;
3834 statsp->mac_stats.adv_cap_pause = param_arr[param_anar_pause].value;
3835
3836 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_10G_xcvr_init: port<%d>",
3837 portn));
3838 return (NXGE_OK);
3839
3840 fail:
3841 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
3842 "nxge_10G_xcvr_init: failed to initialize transceiver for "
3843 "port<%d>", nxgep->mac.portnum));
3844 return (NXGE_ERROR);
3845 }
3846
3847 /* Initialize the 1G copper (BCM 5464) Transceiver */
3848
3849 static nxge_status_t
nxge_1G_xcvr_init(p_nxge_t nxgep)3850 nxge_1G_xcvr_init(p_nxge_t nxgep)
3851 {
3852 p_nxge_param_t param_arr = nxgep->param_arr;
3853 p_nxge_stats_t statsp = nxgep->statsp;
3854 nxge_status_t status = NXGE_OK;
3855
3856 if (nxgep->mac.portmode == PORT_1G_SERDES) {
3857 statsp->mac_stats.cap_1000fdx =
3858 param_arr[param_anar_1000fdx].value;
3859 goto done;
3860 }
3861
3862 /* Set Clause 22 */
3863 npi_mac_mif_set_indirect_mode(nxgep->npi_handle, B_FALSE);
3864
3865 /* Set capability flags */
3866 statsp->mac_stats.cap_1000fdx = param_arr[param_anar_1000fdx].value;
3867 if ((nxgep->mac.portmode == PORT_1G_COPPER) ||
3868 (nxgep->mac.portmode == PORT_1G_FIBER)) {
3869 statsp->mac_stats.cap_100fdx =
3870 param_arr[param_anar_100fdx].value;
3871 statsp->mac_stats.cap_10fdx =
3872 param_arr[param_anar_10fdx].value;
3873 }
3874
3875 status = nxge_mii_xcvr_init(nxgep);
3876 done:
3877 return (status);
3878 }
3879
3880 /*
3881 * Although the Teranetics copper transceiver (TN1010) does not need
3882 * to be initialized by the driver for passing packets, this funtion
3883 * initializes the members of nxgep->statsp->mac_stats struct for
3884 * kstat based on the value of nxgep->statsp->ports_stats.lb_mode.
3885 * It also configures the TN1010 for PHY loopback to support SunVTS.
3886 *
3887 * TN1010 only has the option to disable advertisement for the 10G
3888 * mode. So we can set it to either Dual Mode or 1G Only mode but
3889 * can't set it to 10G Only mode.
3890 *
3891 * ndd -set command can set the following 6 speed/duplex related parameters.
3892 *
3893 * ----------------------------------------------------------------
3894 * ndd -set /dev/nxgeX param n kstat nxge:X | grep param
3895 * ----------------------------------------------------------------
3896 * adv_autoneg_cap kstat nxge:1 | grep adv_cap_autoneg
3897 * adv_10gfdx_cap
3898 * adv_1000fdx_cap kstat nxge:1 | grep adv_cap_1000fdx
3899 * adv_100fdx_cap kstat nxge:1 | grep adv_cap_100fdx
3900 * adv_10fdx_cap kstat nxge:1 | grep adv_cap_10fdx
3901 * adv_pause_cap kstat nxge:1 | grep adv_cap_pause
3902 * ----------------------------------------------------------------
3903 */
3904 static nxge_status_t
nxge_tn1010_xcvr_init(p_nxge_t nxgep)3905 nxge_tn1010_xcvr_init(p_nxge_t nxgep)
3906 {
3907 p_nxge_param_t param_arr;
3908 p_nxge_stats_t statsp;
3909 tn1010_pcs_ctrl_t tn1010_pcs_ctrl;
3910 uint16_t speed;
3911 uint8_t phy_port_addr;
3912 uint8_t portn = NXGE_GET_PORT_NUM(nxgep->function_num);
3913 int status = NXGE_OK;
3914
3915 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_1G_tn1010_xcvr_init"));
3916
3917 param_arr = nxgep->param_arr;
3918 statsp = nxgep->statsp;
3919
3920 /*
3921 * Initialize the xcvr statistics which are NOT controlled by ndd
3922 */
3923 statsp->mac_stats.cap_autoneg = 1; /* TN1010 autoneg is always on */
3924 statsp->mac_stats.cap_100T4 = 0;
3925
3926 /*
3927 * Read the TN1010 link speed and initialize capabilities kstat. Note
3928 * that function nxge_check_tn1010_link repeatedly invoked by the
3929 * timer will update link_speed real time.
3930 */
3931 if (nxge_get_tn1010_speed(nxgep, &speed) != NXGE_OK) {
3932 goto fail;
3933 }
3934 if (speed == TN1010_SPEED_1G) {
3935 statsp->mac_stats.cap_10gfdx = 0;
3936 } else {
3937 statsp->mac_stats.cap_10gfdx = 1;
3938 }
3939
3940 /* Whether we are in 1G or 10G mode, we always have the 1G capability */
3941 statsp->mac_stats.cap_1000fdx = 1;
3942
3943 /* TN1010 is not able to operate in the following states */
3944 statsp->mac_stats.cap_1000hdx = 0;
3945 statsp->mac_stats.cap_100fdx = 0;
3946 statsp->mac_stats.cap_100hdx = 0;
3947 statsp->mac_stats.cap_10fdx = 0;
3948 statsp->mac_stats.cap_10hdx = 0;
3949
3950 /* param_anar_pause can be modified by ndd -set */
3951 statsp->mac_stats.cap_pause = param_arr[param_anar_pause].value;
3952
3953 /*
3954 * The following 4 lines actually overwrites what ever the ndd command
3955 * has set. For example, by command
3956 * ndd -set /dev/nxge1 adv_autoneg_cap n (n = 0 or 1)
3957 * we could set param_arr[param_autoneg].value to n. However, because
3958 * here we assign constants to these parameters, whatever we set with
3959 * the "ndd -set" command will be replaced. So command
3960 * kstat nxge:X | grep param
3961 * will always show those constant values. In other words, the
3962 * "ndd -set" command can NOT change the values of these 4 parameters
3963 * even though the command appears to be successful.
3964 *
3965 * Note: TN1010 auto negotiation is always enabled.
3966 */
3967 statsp->mac_stats.adv_cap_autoneg
3968 = param_arr[param_autoneg].value = 1;
3969 statsp->mac_stats.adv_cap_1000fdx
3970 = param_arr[param_anar_1000fdx].value = 1;
3971 statsp->mac_stats.adv_cap_100fdx
3972 = param_arr[param_anar_100fdx].value = 0;
3973 statsp->mac_stats.adv_cap_10fdx
3974 = param_arr[param_anar_10fdx].value = 0;
3975
3976 /*
3977 * The following 4 ndd params have type NXGE_PARAM_MAC_DONT_SHOW as
3978 * defined in nxge_param_arr[], therefore they are not seen by the
3979 * "ndd -get" command and can not be changed by ndd. We just set
3980 * them (both ndd param and kstat values) to constant 0 because TN1010
3981 * does not support those speeds.
3982 */
3983 statsp->mac_stats.adv_cap_100T4
3984 = param_arr[param_anar_100T4].value = 0;
3985 statsp->mac_stats.adv_cap_1000hdx
3986 = param_arr[param_anar_1000hdx].value = 0;
3987 statsp->mac_stats.adv_cap_100hdx
3988 = param_arr[param_anar_100hdx].value = 0;
3989 statsp->mac_stats.adv_cap_10hdx
3990 = param_arr[param_anar_10hdx].value = 0;
3991
3992 /*
3993 * adv_cap_pause has type NXGE_PARAM_MAC_RW, so it can be modified
3994 * by ndd
3995 */
3996 statsp->mac_stats.adv_cap_pause = param_arr[param_anar_pause].value;
3997
3998 /*
3999 * nxge_param_arr[] defines the adv_cap_asmpause with type
4000 * NXGE_PARAM_DONT_SHOW, therefore they are NOT seen by the
4001 * "ndd -get" command and can not be changed by ndd. Here we do not
4002 * assign a constant to it so the default value defined in
4003 * nxge_param_arr[] will be used to set the parameter and
4004 * will be shown by the kstat.
4005 */
4006 statsp->mac_stats.adv_cap_asmpause
4007 = param_arr[param_anar_asmpause].value;
4008
4009 /*
4010 * Initialize the link statistics.
4011 */
4012 statsp->mac_stats.link_T4 = 0;
4013 statsp->mac_stats.link_asmpause = 0;
4014 statsp->mac_stats.link_pause = 0;
4015 if (speed == TN1010_SPEED_1G) {
4016 statsp->mac_stats.link_speed = 1000;
4017 statsp->mac_stats.link_duplex = 2; /* Full duplex */
4018 statsp->mac_stats.link_up = 1;
4019 } else {
4020 statsp->mac_stats.link_speed = 10000;
4021 statsp->mac_stats.link_duplex = 2;
4022 statsp->mac_stats.link_up = 1;
4023 }
4024
4025 /*
4026 * Because TN1010 does not have a link partner register, to
4027 * figure out the link partner's capabilities is tricky. Here we
4028 * just set the kstat based on our knowledge about the partner
4029 * (The partner must support auto-neg because auto-negotiation
4030 * has completed, it must support 1G or 10G because that is the
4031 * negotiated speed we are using.)
4032 *
4033 * Note: Current kstat does not show lp_cap_10gfdx and
4034 * lp_cap_10ghdx.
4035 */
4036 if (speed == TN1010_SPEED_1G) {
4037 statsp->mac_stats.lp_cap_1000fdx = 1;
4038 statsp->mac_stats.lp_cap_10gfdx = 0;
4039 } else {
4040 statsp->mac_stats.lp_cap_1000fdx = 0;
4041 statsp->mac_stats.lp_cap_10gfdx = 1;
4042 }
4043 statsp->mac_stats.lp_cap_10ghdx = 0;
4044 statsp->mac_stats.lp_cap_1000hdx = 0;
4045 statsp->mac_stats.lp_cap_100fdx = 0;
4046 statsp->mac_stats.lp_cap_100hdx = 0;
4047 statsp->mac_stats.lp_cap_10fdx = 0;
4048 statsp->mac_stats.lp_cap_10hdx = 0;
4049 statsp->mac_stats.lp_cap_10gfdx = 0;
4050 statsp->mac_stats.lp_cap_10ghdx = 0;
4051 statsp->mac_stats.lp_cap_100T4 = 0;
4052 statsp->mac_stats.lp_cap_autoneg = 1;
4053 statsp->mac_stats.lp_cap_asmpause = 0;
4054 statsp->mac_stats.lp_cap_pause = 0;
4055
4056 /* Handle PHY loopback for SunVTS loopback test */
4057 npi_mac_mif_set_indirect_mode(nxgep->npi_handle, B_TRUE);
4058 phy_port_addr = nxgep->nxge_hw_p->xcvr_addr[portn];
4059
4060 if ((status = nxge_mdio_read(nxgep, phy_port_addr,
4061 TN1010_PCS_DEV_ADDR, TN1010_PCS_CONTROL_REG,
4062 &tn1010_pcs_ctrl.value)) != NXGE_OK) {
4063 goto fail;
4064 }
4065 if ((statsp->port_stats.lb_mode == nxge_lb_phy1000) ||
4066 (statsp->port_stats.lb_mode == nxge_lb_phy10g)) {
4067 tn1010_pcs_ctrl.bits.loopback = 1;
4068 } else {
4069 tn1010_pcs_ctrl.bits.loopback = 0;
4070 }
4071 if ((status = nxge_mdio_write(nxgep, phy_port_addr,
4072 TN1010_PCS_DEV_ADDR, TN1010_PCS_CONTROL_REG,
4073 tn1010_pcs_ctrl.value)) != NXGE_OK) {
4074 goto fail;
4075 }
4076
4077 statsp->mac_stats.xcvr_inits++;
4078
4079 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4080 "<== nxge_1G_tn1010_xcvr_init status 0x%x", status));
4081 return (status);
4082 fail:
4083 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
4084 "<== nxge_1G_tn1010_xcvr_init status 0x%x", status));
4085 return (status);
4086 }
4087
4088 /* Initialize transceiver */
4089
4090 nxge_status_t
nxge_xcvr_init(p_nxge_t nxgep)4091 nxge_xcvr_init(p_nxge_t nxgep)
4092 {
4093 p_nxge_stats_t statsp;
4094 #ifdef NXGE_DEBUG
4095 uint8_t portn;
4096 #endif
4097
4098 nxge_status_t status = NXGE_OK;
4099 #ifdef NXGE_DEBUG
4100 portn = nxgep->mac.portnum;
4101 #endif
4102 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xcvr_init: port<%d>", portn));
4103 statsp = nxgep->statsp;
4104
4105 /*
4106 * Initialize the xcvr statistics. nxgep->xcvr.xcvr_init will
4107 * modify mac_stats.
4108 */
4109 statsp->mac_stats.cap_autoneg = 0;
4110 statsp->mac_stats.cap_100T4 = 0;
4111 statsp->mac_stats.cap_100fdx = 0;
4112 statsp->mac_stats.cap_100hdx = 0;
4113 statsp->mac_stats.cap_10fdx = 0;
4114 statsp->mac_stats.cap_10hdx = 0;
4115 statsp->mac_stats.cap_asmpause = 0;
4116 statsp->mac_stats.cap_pause = 0;
4117 statsp->mac_stats.cap_1000fdx = 0;
4118 statsp->mac_stats.cap_1000hdx = 0;
4119 statsp->mac_stats.cap_10gfdx = 0;
4120 statsp->mac_stats.cap_10ghdx = 0;
4121
4122 /*
4123 * Initialize the link statistics.
4124 */
4125 statsp->mac_stats.link_T4 = 0;
4126 statsp->mac_stats.link_asmpause = 0;
4127 statsp->mac_stats.link_pause = 0;
4128
4129 if (nxgep->xcvr.xcvr_init) {
4130 status = nxgep->xcvr.xcvr_init(nxgep);
4131 if (status != NXGE_OK)
4132 goto fail;
4133 statsp->mac_stats.xcvr_inits++;
4134 }
4135
4136 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xcvr_init: port<%d>",
4137 portn));
4138 return (NXGE_OK);
4139
4140 fail:
4141 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4142 "nxge_xcvr_init: failed to initialize transceiver for port<%d>",
4143 portn));
4144 return (status);
4145 }
4146
4147 /* Look for transceiver type */
4148
4149 nxge_status_t
nxge_xcvr_find(p_nxge_t nxgep)4150 nxge_xcvr_find(p_nxge_t nxgep)
4151 {
4152 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xcvr_find: port<%d>",
4153 nxgep->mac.portnum));
4154
4155 if (nxge_get_xcvr_type(nxgep) != NXGE_OK)
4156 return (NXGE_ERROR);
4157
4158 if (nxge_setup_xcvr_table(nxgep) != NXGE_OK)
4159 return (NXGE_ERROR);
4160
4161 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_xcvr_find: xcvr_inuse = %d",
4162 nxgep->statsp->mac_stats.xcvr_inuse));
4163 return (NXGE_OK);
4164 }
4165
4166 /* Initialize the TxMAC sub-block */
4167
4168 nxge_status_t
nxge_tx_mac_init(p_nxge_t nxgep)4169 nxge_tx_mac_init(p_nxge_t nxgep)
4170 {
4171 npi_attr_t ap;
4172 uint8_t portn;
4173 nxge_port_mode_t portmode;
4174 nxge_port_t portt;
4175 npi_handle_t handle;
4176 npi_status_t rs = NPI_SUCCESS;
4177
4178 portn = NXGE_GET_PORT_NUM(nxgep->function_num);
4179 portt = nxgep->mac.porttype;
4180 handle = nxgep->npi_handle;
4181 portmode = nxgep->mac.portmode;
4182
4183 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_init: port<%d>",
4184 portn));
4185 /* Set Max and Min Frame Size */
4186 /*
4187 * Use maxframesize to configure the hardware maxframe size
4188 * and minframesize to configure the hardware minframe size.
4189 */
4190 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4191 "==> nxge_tx_mac_init: port<%d> "
4192 "min framesize %d max framesize %d ",
4193 nxgep->mac.minframesize,
4194 nxgep->mac.maxframesize,
4195 portn));
4196
4197 SET_MAC_ATTR2(handle, ap, portn,
4198 MAC_PORT_FRAME_SIZE,
4199 nxgep->mac.minframesize,
4200 nxgep->mac.maxframesize,
4201 rs);
4202 if (rs != NPI_SUCCESS)
4203 goto fail;
4204
4205 if (portt == PORT_TYPE_XMAC) {
4206 if ((rs = npi_xmac_tx_iconfig(handle, INIT, portn,
4207 0)) != NPI_SUCCESS)
4208 goto fail;
4209 nxgep->mac.tx_iconfig = NXGE_XMAC_TX_INTRS;
4210 if ((portmode == PORT_10G_FIBER) ||
4211 (portmode == PORT_10G_COPPER) ||
4212 (portmode == PORT_10G_TN1010) ||
4213 (portmode == PORT_HSP_MODE) ||
4214 (portmode == PORT_10G_SERDES)) {
4215 SET_MAC_ATTR1(handle, ap, portn, XMAC_10G_PORT_IPG,
4216 XGMII_IPG_12_15, rs);
4217 if (rs != NPI_SUCCESS)
4218 goto fail;
4219 nxgep->mac.ipg[0] = XGMII_IPG_12_15;
4220 } else {
4221 SET_MAC_ATTR1(handle, ap, portn, XMAC_PORT_IPG,
4222 MII_GMII_IPG_12, rs);
4223 if (rs != NPI_SUCCESS)
4224 goto fail;
4225 nxgep->mac.ipg[0] = MII_GMII_IPG_12;
4226 }
4227 if ((rs = npi_xmac_tx_config(handle, INIT, portn,
4228 CFG_XMAC_TX_CRC | CFG_XMAC_TX)) != NPI_SUCCESS)
4229 goto fail;
4230 nxgep->mac.tx_config = CFG_XMAC_TX_CRC | CFG_XMAC_TX;
4231 nxgep->mac.maxburstsize = 0; /* not programmable */
4232 nxgep->mac.ctrltype = 0; /* not programmable */
4233 nxgep->mac.pa_size = 0; /* not programmable */
4234
4235 if ((rs = npi_xmac_zap_tx_counters(handle, portn))
4236 != NPI_SUCCESS)
4237 goto fail;
4238
4239 } else {
4240 if ((rs = npi_bmac_tx_iconfig(handle, INIT, portn,
4241 0)) != NPI_SUCCESS)
4242 goto fail;
4243 nxgep->mac.tx_iconfig = NXGE_BMAC_TX_INTRS;
4244
4245 SET_MAC_ATTR1(handle, ap, portn, BMAC_PORT_CTRL_TYPE, 0x8808,
4246 rs);
4247 if (rs != NPI_SUCCESS)
4248 goto fail;
4249 nxgep->mac.ctrltype = 0x8808;
4250
4251 SET_MAC_ATTR1(handle, ap, portn, BMAC_PORT_PA_SIZE, 0x7, rs);
4252 if (rs != NPI_SUCCESS)
4253 goto fail;
4254 nxgep->mac.pa_size = 0x7;
4255
4256 if ((rs = npi_bmac_tx_config(handle, INIT, portn,
4257 CFG_BMAC_TX_CRC | CFG_BMAC_TX)) != NPI_SUCCESS)
4258 goto fail;
4259 nxgep->mac.tx_config = CFG_BMAC_TX_CRC | CFG_BMAC_TX;
4260 }
4261
4262 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_init: port<%d>",
4263 portn));
4264
4265 return (NXGE_OK);
4266 fail:
4267 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4268 "nxge_tx_mac_init: failed to initialize port<%d> TXMAC", portn));
4269
4270 return (NXGE_ERROR | rs);
4271 }
4272
4273 static npi_status_t
nxge_rx_mac_mcast_hash_table(p_nxge_t nxgep)4274 nxge_rx_mac_mcast_hash_table(p_nxge_t nxgep)
4275 {
4276 uint32_t i;
4277 uint16_t hashtab_e;
4278 p_hash_filter_t hash_filter;
4279 uint8_t portn;
4280 npi_handle_t handle;
4281 npi_status_t rs = NPI_SUCCESS;
4282
4283 portn = NXGE_GET_PORT_NUM(nxgep->function_num);
4284 handle = nxgep->npi_handle;
4285
4286 /*
4287 * Load the multicast hash filter bits.
4288 */
4289 hash_filter = nxgep->hash_filter;
4290 for (i = 0; i < MAC_MAX_HASH_ENTRY; i++) {
4291 if (hash_filter != NULL) {
4292 hashtab_e = (uint16_t)hash_filter->hash_filter_regs[
4293 (NMCFILTER_REGS - 1) - i];
4294 } else {
4295 hashtab_e = 0;
4296 }
4297
4298 if ((rs = npi_mac_hashtab_entry(handle, OP_SET, portn, i,
4299 (uint16_t *)&hashtab_e)) != NPI_SUCCESS)
4300 return (rs);
4301 }
4302
4303 return (NPI_SUCCESS);
4304 }
4305
4306 /*
4307 * Initialize the RxMAC sub-block
4308 */
4309 nxge_status_t
nxge_rx_mac_init(p_nxge_t nxgep)4310 nxge_rx_mac_init(p_nxge_t nxgep)
4311 {
4312 npi_attr_t ap;
4313 nxge_port_t portt;
4314 uint8_t portn;
4315 npi_handle_t handle;
4316 npi_status_t rs = NPI_SUCCESS;
4317 uint16_t *addr16p;
4318 uint16_t addr0, addr1, addr2;
4319 xmac_rx_config_t xconfig;
4320 bmac_rx_config_t bconfig;
4321
4322 portn = NXGE_GET_PORT_NUM(nxgep->function_num);
4323
4324 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_init: port<%d>\n",
4325 portn));
4326 handle = nxgep->npi_handle;
4327 portt = nxgep->mac.porttype;
4328
4329 addr16p = (uint16_t *)nxgep->ouraddr.ether_addr_octet;
4330 addr0 = ntohs(addr16p[2]);
4331 addr1 = ntohs(addr16p[1]);
4332 addr2 = ntohs(addr16p[0]);
4333 SET_MAC_ATTR3(handle, ap, portn, MAC_PORT_ADDR,
4334 addr0, addr1, addr2, rs);
4335 if (rs != NPI_SUCCESS)
4336 goto fail;
4337 SET_MAC_ATTR3(handle, ap, portn, MAC_PORT_ADDR_FILTER, 0, 0, 0, rs);
4338 if (rs != NPI_SUCCESS)
4339 goto fail;
4340 SET_MAC_ATTR2(handle, ap, portn, MAC_PORT_ADDR_FILTER_MASK, 0, 0, rs);
4341 if (rs != NPI_SUCCESS)
4342 goto fail;
4343
4344 rs = nxge_rx_mac_mcast_hash_table(nxgep);
4345 if (rs != NPI_SUCCESS)
4346 goto fail;
4347
4348 if (portt == PORT_TYPE_XMAC) {
4349 if ((rs = npi_xmac_rx_iconfig(handle, INIT, portn,
4350 0)) != NPI_SUCCESS)
4351 goto fail;
4352 nxgep->mac.rx_iconfig = NXGE_XMAC_RX_INTRS;
4353
4354 (void) nxge_fflp_init_hostinfo(nxgep);
4355
4356 xconfig = CFG_XMAC_RX_ERRCHK | CFG_XMAC_RX_CRC_CHK |
4357 CFG_XMAC_RX | CFG_XMAC_RX_CODE_VIO_CHK &
4358 ~CFG_XMAC_RX_STRIP_CRC;
4359
4360 if (nxgep->filter.all_phys_cnt != 0)
4361 xconfig |= CFG_XMAC_RX_PROMISCUOUS;
4362 if (nxgep->filter.all_multicast_cnt != 0)
4363 xconfig |= CFG_XMAC_RX_PROMISCUOUSGROUP;
4364
4365 xconfig |= CFG_XMAC_RX_HASH_FILTER;
4366
4367 if ((rs = npi_xmac_rx_config(handle, INIT,
4368 portn, xconfig)) != NPI_SUCCESS)
4369 goto fail;
4370 nxgep->mac.rx_config = xconfig;
4371
4372 /*
4373 * Comparison of mac unique address is always
4374 * enabled on XMAC
4375 */
4376 if ((rs = npi_xmac_zap_rx_counters(handle, portn))
4377 != NPI_SUCCESS)
4378 goto fail;
4379 } else {
4380 if (npi_bmac_rx_iconfig(nxgep->npi_handle, INIT, portn,
4381 0) != NPI_SUCCESS)
4382 goto fail;
4383
4384 nxgep->mac.rx_iconfig = NXGE_BMAC_RX_INTRS;
4385
4386 (void) nxge_fflp_init_hostinfo(nxgep);
4387
4388 bconfig = CFG_BMAC_RX_DISCARD_ON_ERR | CFG_BMAC_RX &
4389 ~CFG_BMAC_RX_STRIP_CRC;
4390
4391 if (nxgep->filter.all_phys_cnt != 0)
4392 bconfig |= CFG_BMAC_RX_PROMISCUOUS;
4393 if (nxgep->filter.all_multicast_cnt != 0)
4394 bconfig |= CFG_BMAC_RX_PROMISCUOUSGROUP;
4395
4396 bconfig |= CFG_BMAC_RX_HASH_FILTER;
4397 if ((rs = npi_bmac_rx_config(handle, INIT,
4398 portn, bconfig)) != NPI_SUCCESS)
4399 goto fail;
4400 nxgep->mac.rx_config = bconfig;
4401
4402 /*
4403 * Always enable comparison of mac unique address
4404 */
4405 if ((rs = npi_mac_altaddr_enable(handle,
4406 portn, 0)) != NPI_SUCCESS)
4407 goto fail;
4408 }
4409
4410 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_init: port<%d>\n",
4411 portn));
4412
4413 return (NXGE_OK);
4414
4415 fail:
4416 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
4417 "nxge_rx_mac_init: Failed to Initialize port<%d> RxMAC", portn));
4418
4419 return (NXGE_ERROR | rs);
4420 }
4421
4422 /* Enable TXMAC */
4423
4424 nxge_status_t
nxge_tx_mac_enable(p_nxge_t nxgep)4425 nxge_tx_mac_enable(p_nxge_t nxgep)
4426 {
4427 npi_handle_t handle;
4428 npi_status_t rs = NPI_SUCCESS;
4429 nxge_status_t status = NXGE_OK;
4430
4431 handle = nxgep->npi_handle;
4432
4433 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_enable: port<%d>",
4434 nxgep->mac.portnum));
4435
4436 if ((status = nxge_tx_mac_init(nxgep)) != NXGE_OK)
4437 goto fail;
4438
4439 /* based on speed */
4440 nxgep->msg_min = ETHERMIN;
4441
4442 if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
4443 if ((rs = npi_xmac_tx_config(handle, ENABLE, nxgep->mac.portnum,
4444 CFG_XMAC_TX)) != NPI_SUCCESS)
4445 goto fail;
4446 } else {
4447 if ((rs = npi_bmac_tx_config(handle, ENABLE, nxgep->mac.portnum,
4448 CFG_BMAC_TX)) != NPI_SUCCESS)
4449 goto fail;
4450 }
4451
4452 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_enable: port<%d>",
4453 nxgep->mac.portnum));
4454
4455 return (NXGE_OK);
4456 fail:
4457 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
4458 "nxgep_tx_mac_enable: Failed to enable port<%d> TxMAC",
4459 nxgep->mac.portnum));
4460 if (rs != NPI_SUCCESS)
4461 return (NXGE_ERROR | rs);
4462 else
4463 return (status);
4464 }
4465
4466 /* Disable TXMAC */
4467
4468 nxge_status_t
nxge_tx_mac_disable(p_nxge_t nxgep)4469 nxge_tx_mac_disable(p_nxge_t nxgep)
4470 {
4471 npi_handle_t handle;
4472 npi_status_t rs = NPI_SUCCESS;
4473
4474 if (isLDOMguest(nxgep))
4475 return (NXGE_OK);
4476
4477 handle = nxgep->npi_handle;
4478
4479 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_disable: port<%d>",
4480 nxgep->mac.portnum));
4481
4482 if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
4483 if ((rs = npi_xmac_tx_config(handle, DISABLE,
4484 nxgep->mac.portnum, CFG_XMAC_TX)) != NPI_SUCCESS)
4485 goto fail;
4486 } else {
4487 if ((rs = npi_bmac_tx_config(handle, DISABLE,
4488 nxgep->mac.portnum, CFG_BMAC_TX)) != NPI_SUCCESS)
4489 goto fail;
4490 }
4491
4492 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_disable: port<%d>",
4493 nxgep->mac.portnum));
4494 return (NXGE_OK);
4495 fail:
4496 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
4497 "nxge_tx_mac_disable: Failed to disable port<%d> TxMAC",
4498 nxgep->mac.portnum));
4499 return (NXGE_ERROR | rs);
4500 }
4501
4502 /* Enable RXMAC */
4503
4504 nxge_status_t
nxge_rx_mac_enable(p_nxge_t nxgep)4505 nxge_rx_mac_enable(p_nxge_t nxgep)
4506 {
4507 npi_handle_t handle;
4508 uint8_t portn;
4509 npi_status_t rs = NPI_SUCCESS;
4510 nxge_status_t status = NXGE_OK;
4511
4512 /* This is a service-domain-only activity. */
4513 if (isLDOMguest(nxgep))
4514 return (status);
4515
4516 handle = nxgep->npi_handle;
4517 portn = nxgep->mac.portnum;
4518
4519 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_enable: port<%d>",
4520 portn));
4521
4522 if ((status = nxge_rx_mac_init(nxgep)) != NXGE_OK)
4523 goto fail;
4524
4525 if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
4526 if ((rs = npi_xmac_rx_config(handle, ENABLE, portn,
4527 CFG_XMAC_RX)) != NPI_SUCCESS)
4528 goto fail;
4529 } else {
4530 if ((rs = npi_bmac_rx_config(handle, ENABLE, portn,
4531 CFG_BMAC_RX)) != NPI_SUCCESS)
4532 goto fail;
4533 }
4534
4535 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4536 "<== nxge_rx_mac_enable: port<%d>", portn));
4537
4538 return (NXGE_OK);
4539 fail:
4540 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
4541 "nxgep_rx_mac_enable: Failed to enable port<%d> RxMAC", portn));
4542
4543 if (rs != NPI_SUCCESS)
4544 return (NXGE_ERROR | rs);
4545 else
4546 return (status);
4547 }
4548
4549 /* Disable RXMAC */
4550
4551 nxge_status_t
nxge_rx_mac_disable(p_nxge_t nxgep)4552 nxge_rx_mac_disable(p_nxge_t nxgep)
4553 {
4554 npi_handle_t handle;
4555 uint8_t portn;
4556 npi_status_t rs = NPI_SUCCESS;
4557
4558 /* If we are a guest domain driver, don't bother. */
4559 if (isLDOMguest(nxgep))
4560 return (NXGE_OK);
4561
4562 handle = nxgep->npi_handle;
4563 portn = nxgep->mac.portnum;
4564
4565 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_disable: port<%d>",
4566 portn));
4567
4568 if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
4569 if ((rs = npi_xmac_rx_config(handle, DISABLE, portn,
4570 CFG_XMAC_RX)) != NPI_SUCCESS)
4571 goto fail;
4572 } else {
4573 if ((rs = npi_bmac_rx_config(handle, DISABLE, portn,
4574 CFG_BMAC_RX)) != NPI_SUCCESS)
4575 goto fail;
4576 }
4577
4578 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_disable: port<%d>",
4579 portn));
4580 return (NXGE_OK);
4581 fail:
4582 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
4583 "nxgep_rx_mac_disable: Failed to disable port<%d> RxMAC", portn));
4584
4585 return (NXGE_ERROR | rs);
4586 }
4587
4588 /* Reset TXMAC */
4589
4590 nxge_status_t
nxge_tx_mac_reset(p_nxge_t nxgep)4591 nxge_tx_mac_reset(p_nxge_t nxgep)
4592 {
4593 npi_handle_t handle;
4594 uint8_t portn;
4595 npi_status_t rs = NPI_SUCCESS;
4596
4597 handle = nxgep->npi_handle;
4598 portn = nxgep->mac.portnum;
4599
4600 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_reset: port<%d>",
4601 portn));
4602
4603 if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
4604 if ((rs = npi_xmac_reset(handle, portn, XTX_MAC_RESET_ALL))
4605 != NPI_SUCCESS)
4606 goto fail;
4607 } else {
4608 if ((rs = npi_bmac_reset(handle, portn, TX_MAC_RESET))
4609 != NPI_SUCCESS)
4610 goto fail;
4611 }
4612
4613 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_reset: port<%d>",
4614 portn));
4615
4616 return (NXGE_OK);
4617 fail:
4618 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
4619 "nxge_tx_mac_reset: Failed to Reset TxMAC port<%d>", portn));
4620
4621 return (NXGE_ERROR | rs);
4622 }
4623
4624 /* Reset RXMAC */
4625
4626 nxge_status_t
nxge_rx_mac_reset(p_nxge_t nxgep)4627 nxge_rx_mac_reset(p_nxge_t nxgep)
4628 {
4629 npi_handle_t handle;
4630 uint8_t portn;
4631 npi_status_t rs = NPI_SUCCESS;
4632
4633 handle = nxgep->npi_handle;
4634 portn = nxgep->mac.portnum;
4635
4636 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_reset: port<%d>",
4637 portn));
4638
4639 if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
4640 if ((rs = npi_xmac_reset(handle, portn, XRX_MAC_RESET_ALL))
4641 != NPI_SUCCESS)
4642 goto fail;
4643 } else {
4644 if ((rs = npi_bmac_reset(handle, portn, RX_MAC_RESET))
4645 != NPI_SUCCESS)
4646 goto fail;
4647 }
4648
4649 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_reset: port<%d>",
4650 portn));
4651
4652 return (NXGE_OK);
4653 fail:
4654 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
4655 "nxge_rx_mac_reset: Failed to Reset RxMAC port<%d>", portn));
4656 return (NXGE_ERROR | rs);
4657 }
4658
4659 /* 10G fiber link interrupt start routine */
4660
4661 static nxge_status_t
nxge_10G_link_intr_start(p_nxge_t nxgep)4662 nxge_10G_link_intr_start(p_nxge_t nxgep)
4663 {
4664 npi_status_t rs = NPI_SUCCESS;
4665 uint8_t portn = nxgep->mac.portnum;
4666
4667 rs = npi_xmac_xpcs_link_intr_enable(nxgep->npi_handle, portn);
4668
4669 if (rs != NPI_SUCCESS)
4670 return (NXGE_ERROR | rs);
4671 else
4672 return (NXGE_OK);
4673 }
4674
4675 /* 10G fiber link interrupt stop routine */
4676
4677 static nxge_status_t
nxge_10G_link_intr_stop(p_nxge_t nxgep)4678 nxge_10G_link_intr_stop(p_nxge_t nxgep)
4679 {
4680 npi_status_t rs = NPI_SUCCESS;
4681 uint8_t portn = nxgep->mac.portnum;
4682
4683 rs = npi_xmac_xpcs_link_intr_disable(nxgep->npi_handle, portn);
4684
4685 if (rs != NPI_SUCCESS)
4686 return (NXGE_ERROR | rs);
4687 else
4688 return (NXGE_OK);
4689 }
4690
4691 /* 1G fiber link interrupt start routine */
4692
4693 static nxge_status_t
nxge_1G_fiber_link_intr_start(p_nxge_t nxgep)4694 nxge_1G_fiber_link_intr_start(p_nxge_t nxgep)
4695 {
4696 npi_status_t rs = NPI_SUCCESS;
4697 uint8_t portn = nxgep->mac.portnum;
4698
4699 rs = npi_mac_pcs_link_intr_enable(nxgep->npi_handle, portn);
4700 if (rs != NPI_SUCCESS)
4701 return (NXGE_ERROR | rs);
4702 else
4703 return (NXGE_OK);
4704 }
4705
4706 /* 1G fiber link interrupt stop routine */
4707
4708 static nxge_status_t
nxge_1G_fiber_link_intr_stop(p_nxge_t nxgep)4709 nxge_1G_fiber_link_intr_stop(p_nxge_t nxgep)
4710 {
4711 npi_status_t rs = NPI_SUCCESS;
4712 uint8_t portn = nxgep->mac.portnum;
4713
4714 rs = npi_mac_pcs_link_intr_disable(nxgep->npi_handle, portn);
4715
4716 if (rs != NPI_SUCCESS)
4717 return (NXGE_ERROR | rs);
4718 else
4719 return (NXGE_OK);
4720 }
4721
4722 /* 1G copper link interrupt start routine */
4723
4724 static nxge_status_t
nxge_1G_copper_link_intr_start(p_nxge_t nxgep)4725 nxge_1G_copper_link_intr_start(p_nxge_t nxgep)
4726 {
4727 npi_status_t rs = NPI_SUCCESS;
4728 uint8_t portn = nxgep->mac.portnum;
4729
4730 rs = npi_mac_mif_link_intr_enable(nxgep->npi_handle, portn,
4731 MII_STATUS, MII_STATUS_LINKUP);
4732
4733 if (rs != NPI_SUCCESS)
4734 return (NXGE_ERROR | rs);
4735 else
4736 return (NXGE_OK);
4737 }
4738
4739 /* 1G copper link interrupt stop routine */
4740
4741 static nxge_status_t
nxge_1G_copper_link_intr_stop(p_nxge_t nxgep)4742 nxge_1G_copper_link_intr_stop(p_nxge_t nxgep)
4743 {
4744 npi_status_t rs = NPI_SUCCESS;
4745 uint8_t portn = nxgep->mac.portnum;
4746
4747 rs = npi_mac_mif_link_intr_disable(nxgep->npi_handle, portn);
4748
4749 if (rs != NPI_SUCCESS)
4750 return (NXGE_ERROR | rs);
4751 else
4752 return (NXGE_OK);
4753 }
4754
4755 /* Enable/Disable Link Status change interrupt */
4756
4757 nxge_status_t
nxge_link_intr(p_nxge_t nxgep,link_intr_enable_t enable)4758 nxge_link_intr(p_nxge_t nxgep, link_intr_enable_t enable)
4759 {
4760 uint8_t portn;
4761 nxge_status_t status = NXGE_OK;
4762
4763 portn = nxgep->mac.portnum;
4764
4765 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_intr: port<%d>", portn));
4766 if (!nxgep->xcvr.link_intr_stop || !nxgep->xcvr.link_intr_start)
4767 return (NXGE_OK);
4768
4769 if (enable == LINK_INTR_START)
4770 status = nxgep->xcvr.link_intr_start(nxgep);
4771 else if (enable == LINK_INTR_STOP)
4772 status = nxgep->xcvr.link_intr_stop(nxgep);
4773 if (status != NXGE_OK)
4774 goto fail;
4775
4776 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_intr: port<%d>", portn));
4777
4778 return (NXGE_OK);
4779 fail:
4780 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
4781 "nxge_link_intr: Failed to set port<%d> mif intr mode", portn));
4782
4783 return (status);
4784 }
4785
4786 /* Initialize 1G Fiber / Copper transceiver using Clause 22 */
4787
4788 nxge_status_t
nxge_mii_xcvr_init(p_nxge_t nxgep)4789 nxge_mii_xcvr_init(p_nxge_t nxgep)
4790 {
4791 p_nxge_param_t param_arr;
4792 p_nxge_stats_t statsp;
4793 uint8_t xcvr_portn;
4794 p_mii_regs_t mii_regs;
4795 mii_bmcr_t bmcr;
4796 mii_bmsr_t bmsr;
4797 mii_anar_t anar;
4798 mii_gcr_t gcr;
4799 mii_esr_t esr;
4800 mii_aux_ctl_t bcm5464r_aux;
4801 int status = NXGE_OK;
4802
4803 uint_t delay;
4804
4805 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_xcvr_init"));
4806
4807 param_arr = nxgep->param_arr;
4808 statsp = nxgep->statsp;
4809 xcvr_portn = statsp->mac_stats.xcvr_portn;
4810
4811 mii_regs = NULL;
4812
4813 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4814 "nxge_param_autoneg = 0x%02x", param_arr[param_autoneg].value));
4815
4816 /*
4817 * The mif phy mode may be connected to either a copper link
4818 * or fiber link. Read the mode control register to get the fiber
4819 * configuration if it is hard-wired to fiber link.
4820 */
4821 (void) nxge_mii_get_link_mode(nxgep);
4822 if (nxgep->mac.portmode == PORT_1G_RGMII_FIBER) {
4823 return (nxge_mii_xcvr_fiber_init(nxgep));
4824 }
4825
4826 /*
4827 * Reset the transceiver.
4828 */
4829 delay = 0;
4830 bmcr.value = 0;
4831 bmcr.bits.reset = 1;
4832 if ((status = nxge_mii_write(nxgep, xcvr_portn,
4833 #if defined(__i386)
4834 (uint8_t)(uint32_t)&mii_regs->bmcr,
4835 #else
4836 (uint8_t)(uint64_t)&mii_regs->bmcr,
4837 #endif
4838 bmcr.value)) != NXGE_OK)
4839 goto fail;
4840 do {
4841 drv_usecwait(500);
4842 if ((status = nxge_mii_read(nxgep, xcvr_portn,
4843 #if defined(__i386)
4844 (uint8_t)(uint32_t)&mii_regs->bmcr,
4845 #else
4846 (uint8_t)(uint64_t)&mii_regs->bmcr,
4847 #endif
4848 &bmcr.value)) != NXGE_OK)
4849 goto fail;
4850 delay++;
4851 } while ((bmcr.bits.reset) && (delay < 1000));
4852 if (delay == 1000) {
4853 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Xcvr reset failed."));
4854 goto fail;
4855 }
4856
4857 if ((status = nxge_mii_read(nxgep, xcvr_portn,
4858 #if defined(__i386)
4859 (uint8_t)(uint32_t)(&mii_regs->bmsr),
4860 #else
4861 (uint8_t)(uint64_t)(&mii_regs->bmsr),
4862 #endif
4863 &bmsr.value)) != NXGE_OK)
4864 goto fail;
4865
4866 param_arr[param_autoneg].value &= bmsr.bits.auto_neg_able;
4867 param_arr[param_anar_100T4].value &= bmsr.bits.link_100T4;
4868 param_arr[param_anar_100fdx].value &= bmsr.bits.link_100fdx;
4869 param_arr[param_anar_100hdx].value = 0;
4870 param_arr[param_anar_10fdx].value &= bmsr.bits.link_10fdx;
4871 param_arr[param_anar_10hdx].value = 0;
4872
4873 /*
4874 * Initialize the xcvr statistics.
4875 */
4876 statsp->mac_stats.cap_autoneg = bmsr.bits.auto_neg_able;
4877 statsp->mac_stats.cap_100T4 = bmsr.bits.link_100T4;
4878 statsp->mac_stats.cap_100fdx = bmsr.bits.link_100fdx;
4879 statsp->mac_stats.cap_100hdx = 0;
4880 statsp->mac_stats.cap_10fdx = bmsr.bits.link_10fdx;
4881 statsp->mac_stats.cap_10hdx = 0;
4882 statsp->mac_stats.cap_asmpause = param_arr[param_anar_asmpause].value;
4883 statsp->mac_stats.cap_pause = param_arr[param_anar_pause].value;
4884
4885 /*
4886 * Initialize the xcvr advertised capability statistics.
4887 */
4888 statsp->mac_stats.adv_cap_autoneg = param_arr[param_autoneg].value;
4889 statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value;
4890 statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value;
4891 statsp->mac_stats.adv_cap_100T4 = param_arr[param_anar_100T4].value;
4892 statsp->mac_stats.adv_cap_100fdx = param_arr[param_anar_100fdx].value;
4893 statsp->mac_stats.adv_cap_100hdx = param_arr[param_anar_100hdx].value;
4894 statsp->mac_stats.adv_cap_10fdx = param_arr[param_anar_10fdx].value;
4895 statsp->mac_stats.adv_cap_10hdx = param_arr[param_anar_10hdx].value;
4896 statsp->mac_stats.adv_cap_asmpause =
4897 param_arr[param_anar_asmpause].value;
4898 statsp->mac_stats.adv_cap_pause = param_arr[param_anar_pause].value;
4899
4900
4901 /*
4902 * Check for extended status just in case we're
4903 * running a Gigibit phy.
4904 */
4905 if (bmsr.bits.extend_status) {
4906 if ((status = nxge_mii_read(nxgep, xcvr_portn,
4907 #if defined(__i386)
4908 (uint8_t)(uint32_t)(&mii_regs->esr),
4909 #else
4910 (uint8_t)(uint64_t)(&mii_regs->esr),
4911 #endif
4912 &esr.value)) != NXGE_OK)
4913 goto fail;
4914 param_arr[param_anar_1000fdx].value &= esr.bits.link_1000fdx;
4915 param_arr[param_anar_1000hdx].value = 0;
4916
4917 statsp->mac_stats.cap_1000fdx =
4918 (esr.bits.link_1000Xfdx || esr.bits.link_1000fdx);
4919 statsp->mac_stats.cap_1000hdx = 0;
4920 } else {
4921 param_arr[param_anar_1000fdx].value = 0;
4922 param_arr[param_anar_1000hdx].value = 0;
4923 }
4924
4925 /*
4926 * Initialize 1G Statistics once the capability is established.
4927 */
4928 statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value;
4929 statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value;
4930
4931 /*
4932 * Initialize the link statistics.
4933 */
4934 statsp->mac_stats.link_T4 = 0;
4935 statsp->mac_stats.link_asmpause = 0;
4936 statsp->mac_stats.link_pause = 0;
4937 statsp->mac_stats.link_speed = 0;
4938 statsp->mac_stats.link_duplex = 0;
4939 statsp->mac_stats.link_up = 0;
4940
4941 /*
4942 * Switch off Auto-negotiation, 100M and full duplex.
4943 */
4944 bmcr.value = 0;
4945 if ((status = nxge_mii_write(nxgep, xcvr_portn,
4946 #if defined(__i386)
4947 (uint8_t)(uint32_t)(&mii_regs->bmcr),
4948 #else
4949 (uint8_t)(uint64_t)(&mii_regs->bmcr),
4950 #endif
4951 bmcr.value)) != NXGE_OK)
4952 goto fail;
4953
4954 if ((statsp->port_stats.lb_mode == nxge_lb_phy) ||
4955 (statsp->port_stats.lb_mode == nxge_lb_phy1000)) {
4956 bmcr.bits.loopback = 1;
4957 bmcr.bits.enable_autoneg = 0;
4958 if (statsp->port_stats.lb_mode == nxge_lb_phy1000)
4959 bmcr.bits.speed_1000_sel = 1;
4960 bmcr.bits.duplex_mode = 1;
4961 param_arr[param_autoneg].value = 0;
4962 } else {
4963 bmcr.bits.loopback = 0;
4964 }
4965
4966 if ((statsp->port_stats.lb_mode == nxge_lb_ext1000) ||
4967 (statsp->port_stats.lb_mode == nxge_lb_ext100) ||
4968 (statsp->port_stats.lb_mode == nxge_lb_ext10)) {
4969 param_arr[param_autoneg].value = 0;
4970 bcm5464r_aux.value = 0;
4971 bcm5464r_aux.bits.ext_lb = 1;
4972 bcm5464r_aux.bits.write_1 = 1;
4973 if ((status = nxge_mii_write(nxgep, xcvr_portn,
4974 BCM5464R_AUX_CTL, bcm5464r_aux.value)) != NXGE_OK)
4975 goto fail;
4976 }
4977
4978 /* If auto-negotiation is desired */
4979 if (param_arr[param_autoneg].value) {
4980 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4981 "Restarting Auto-negotiation."));
4982 /*
4983 * Setup our Auto-negotiation advertisement register.
4984 */
4985 anar.value = 0;
4986 anar.bits.selector = 1;
4987 anar.bits.cap_100T4 = param_arr[param_anar_100T4].value;
4988 anar.bits.cap_100fdx = param_arr[param_anar_100fdx].value;
4989 anar.bits.cap_100hdx = param_arr[param_anar_100hdx].value;
4990 anar.bits.cap_10fdx = param_arr[param_anar_10fdx].value;
4991 anar.bits.cap_10hdx = param_arr[param_anar_10hdx].value;
4992 anar.bits.cap_asmpause = 0;
4993 anar.bits.cap_pause = 0;
4994 if (param_arr[param_anar_1000fdx].value ||
4995 param_arr[param_anar_100fdx].value ||
4996 param_arr[param_anar_10fdx].value) {
4997 anar.bits.cap_asmpause = statsp->mac_stats.cap_asmpause;
4998 anar.bits.cap_pause = statsp->mac_stats.cap_pause;
4999 }
5000
5001 /* Write to the auto-negotiation advertisement register */
5002 if ((status = nxge_mii_write(nxgep, xcvr_portn,
5003 #if defined(__i386)
5004 (uint8_t)(uint32_t)(&mii_regs->anar),
5005 #else
5006 (uint8_t)(uint64_t)(&mii_regs->anar),
5007 #endif
5008 anar.value)) != NXGE_OK)
5009 goto fail;
5010 if (bmsr.bits.extend_status) {
5011 gcr.value = 0;
5012 gcr.bits.ms_mode_en =
5013 param_arr[param_master_cfg_enable].value;
5014 gcr.bits.master =
5015 param_arr[param_master_cfg_value].value;
5016 gcr.bits.link_1000fdx =
5017 param_arr[param_anar_1000fdx].value;
5018 gcr.bits.link_1000hdx =
5019 param_arr[param_anar_1000hdx].value;
5020 if ((status = nxge_mii_write(nxgep, xcvr_portn,
5021 #if defined(__i386)
5022 (uint8_t)(uint32_t)(&mii_regs->gcr),
5023 #else
5024 (uint8_t)(uint64_t)(&mii_regs->gcr),
5025 #endif
5026 gcr.value)) != NXGE_OK)
5027 goto fail;
5028 }
5029
5030 bmcr.bits.enable_autoneg = 1;
5031 bmcr.bits.restart_autoneg = 1;
5032
5033 } else {
5034 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Going into forced mode."));
5035 bmcr.bits.speed_1000_sel =
5036 param_arr[param_anar_1000fdx].value |
5037 param_arr[param_anar_1000hdx].value;
5038 bmcr.bits.speed_sel = (~bmcr.bits.speed_1000_sel) &
5039 (param_arr[param_anar_100fdx].value |
5040 param_arr[param_anar_100hdx].value);
5041
5042 /* Force to 1G */
5043 if (bmcr.bits.speed_1000_sel) {
5044 statsp->mac_stats.link_speed = 1000;
5045 gcr.value = 0;
5046 gcr.bits.ms_mode_en =
5047 param_arr[param_master_cfg_enable].value;
5048 gcr.bits.master =
5049 param_arr[param_master_cfg_value].value;
5050 if ((status = nxge_mii_write(nxgep, xcvr_portn,
5051 #if defined(__i386)
5052 (uint8_t)(uint32_t)(&mii_regs->gcr),
5053 #else
5054 (uint8_t)(uint64_t)(&mii_regs->gcr),
5055 #endif
5056 gcr.value)) != NXGE_OK)
5057 goto fail;
5058 if (param_arr[param_anar_1000fdx].value) {
5059 bmcr.bits.duplex_mode = 1;
5060 statsp->mac_stats.link_duplex = 2;
5061 } else
5062 statsp->mac_stats.link_duplex = 1;
5063
5064 /* Force to 100M */
5065 } else if (bmcr.bits.speed_sel) {
5066 statsp->mac_stats.link_speed = 100;
5067 if (param_arr[param_anar_100fdx].value) {
5068 bmcr.bits.duplex_mode = 1;
5069 statsp->mac_stats.link_duplex = 2;
5070 } else
5071 statsp->mac_stats.link_duplex = 1;
5072
5073 /* Force to 10M */
5074 } else {
5075 statsp->mac_stats.link_speed = 10;
5076 if (param_arr[param_anar_10fdx].value) {
5077 bmcr.bits.duplex_mode = 1;
5078 statsp->mac_stats.link_duplex = 2;
5079 } else
5080 statsp->mac_stats.link_duplex = 1;
5081 }
5082 if (statsp->mac_stats.link_duplex != 1) {
5083 statsp->mac_stats.link_asmpause =
5084 statsp->mac_stats.cap_asmpause;
5085 statsp->mac_stats.link_pause =
5086 statsp->mac_stats.cap_pause;
5087 }
5088
5089 if ((statsp->port_stats.lb_mode == nxge_lb_ext1000) ||
5090 (statsp->port_stats.lb_mode == nxge_lb_ext100) ||
5091 (statsp->port_stats.lb_mode == nxge_lb_ext10)) {
5092 if (statsp->port_stats.lb_mode == nxge_lb_ext1000) {
5093 /* BCM5464R 1000mbps external loopback mode */
5094 gcr.value = 0;
5095 gcr.bits.ms_mode_en = 1;
5096 gcr.bits.master = 1;
5097 if ((status = nxge_mii_write(nxgep, xcvr_portn,
5098 #if defined(__i386)
5099 (uint8_t)(uint32_t)(&mii_regs->gcr),
5100 #else
5101 (uint8_t)(uint64_t)(&mii_regs->gcr),
5102 #endif
5103 gcr.value)) != NXGE_OK)
5104 goto fail;
5105 bmcr.value = 0;
5106 bmcr.bits.speed_1000_sel = 1;
5107 statsp->mac_stats.link_speed = 1000;
5108 } else if (statsp->port_stats.lb_mode
5109 == nxge_lb_ext100) {
5110 /* BCM5464R 100mbps external loopback mode */
5111 bmcr.value = 0;
5112 bmcr.bits.speed_sel = 1;
5113 bmcr.bits.duplex_mode = 1;
5114 statsp->mac_stats.link_speed = 100;
5115 } else if (statsp->port_stats.lb_mode
5116 == nxge_lb_ext10) {
5117 /* BCM5464R 10mbps external loopback mode */
5118 bmcr.value = 0;
5119 bmcr.bits.duplex_mode = 1;
5120 statsp->mac_stats.link_speed = 10;
5121 }
5122 }
5123 }
5124
5125 if ((status = nxge_mii_write(nxgep, xcvr_portn,
5126 #if defined(__i386)
5127 (uint8_t)(uint32_t)(&mii_regs->bmcr),
5128 #else
5129 (uint8_t)(uint64_t)(&mii_regs->bmcr),
5130 #endif
5131 bmcr.value)) != NXGE_OK)
5132 goto fail;
5133
5134 if ((status = nxge_mii_read(nxgep, xcvr_portn,
5135 #if defined(__i386)
5136 (uint8_t)(uint32_t)(&mii_regs->bmcr),
5137 #else
5138 (uint8_t)(uint64_t)(&mii_regs->bmcr),
5139 #endif
5140 &bmcr.value)) != NXGE_OK)
5141 goto fail;
5142 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "bmcr = 0x%04X", bmcr.value));
5143
5144 /*
5145 * Initialize the xcvr status kept in the context structure.
5146 */
5147 nxgep->soft_bmsr.value = 0;
5148
5149 if ((status = nxge_mii_read(nxgep, xcvr_portn,
5150 #if defined(__i386)
5151 (uint8_t)(uint32_t)(&mii_regs->bmsr),
5152 #else
5153 (uint8_t)(uint64_t)(&mii_regs->bmsr),
5154 #endif
5155 &nxgep->bmsr.value)) != NXGE_OK)
5156 goto fail;
5157
5158 statsp->mac_stats.xcvr_inits++;
5159 nxgep->bmsr.value = 0;
5160
5161 fail:
5162 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
5163 "<== nxge_mii_xcvr_init status 0x%x", status));
5164 return (status);
5165 }
5166
5167 nxge_status_t
nxge_mii_xcvr_fiber_init(p_nxge_t nxgep)5168 nxge_mii_xcvr_fiber_init(p_nxge_t nxgep)
5169 {
5170 p_nxge_param_t param_arr;
5171 p_nxge_stats_t statsp;
5172 uint8_t xcvr_portn;
5173 p_mii_regs_t mii_regs;
5174 mii_bmcr_t bmcr;
5175 mii_bmsr_t bmsr;
5176 mii_gcr_t gcr;
5177 mii_esr_t esr;
5178 mii_aux_ctl_t bcm5464r_aux;
5179 int status = NXGE_OK;
5180
5181 uint_t delay;
5182
5183 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_xcvr_fiber_init"));
5184
5185 param_arr = nxgep->param_arr;
5186 statsp = nxgep->statsp;
5187 xcvr_portn = statsp->mac_stats.xcvr_portn;
5188
5189 mii_regs = NULL;
5190
5191 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
5192 "nxge_mii_xcvr_fiber_init: "
5193 "nxge_param_autoneg = 0x%02x", param_arr[param_autoneg].value));
5194
5195 /*
5196 * Reset the transceiver.
5197 */
5198 delay = 0;
5199 bmcr.value = 0;
5200 bmcr.bits.reset = 1;
5201
5202 #if defined(__i386)
5203
5204 if ((status = nxge_mii_write(nxgep, xcvr_portn,
5205 (uint8_t)(uint32_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK)
5206 goto fail;
5207 #else
5208 if ((status = nxge_mii_write(nxgep, xcvr_portn,
5209 (uint8_t)(uint64_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK)
5210 goto fail;
5211 #endif
5212 do {
5213 drv_usecwait(500);
5214 #if defined(__i386)
5215 if ((status = nxge_mii_read(nxgep, xcvr_portn,
5216 (uint8_t)(uint32_t)(&mii_regs->bmcr), &bmcr.value))
5217 != NXGE_OK)
5218 goto fail;
5219 #else
5220 if ((status = nxge_mii_read(nxgep, xcvr_portn,
5221 (uint8_t)(uint64_t)(&mii_regs->bmcr), &bmcr.value))
5222 != NXGE_OK)
5223 goto fail;
5224 #endif
5225 delay++;
5226 } while ((bmcr.bits.reset) && (delay < 1000));
5227 if (delay == 1000) {
5228 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Xcvr reset failed."));
5229 goto fail;
5230 }
5231
5232 #if defined(__i386)
5233 if ((status = nxge_mii_read(nxgep, xcvr_portn,
5234 (uint8_t)(uint32_t)(&mii_regs->bmsr), &bmsr.value)) != NXGE_OK)
5235 goto fail;
5236 #else
5237 if ((status = nxge_mii_read(nxgep, xcvr_portn,
5238 (uint8_t)(uint64_t)(&mii_regs->bmsr), &bmsr.value)) != NXGE_OK)
5239 goto fail;
5240 #endif
5241
5242 param_arr[param_autoneg].value &= bmsr.bits.auto_neg_able;
5243 param_arr[param_anar_100T4].value = 0;
5244 param_arr[param_anar_100fdx].value = 0;
5245 param_arr[param_anar_100hdx].value = 0;
5246 param_arr[param_anar_10fdx].value = 0;
5247 param_arr[param_anar_10hdx].value = 0;
5248
5249 /*
5250 * Initialize the xcvr statistics.
5251 */
5252 statsp->mac_stats.cap_autoneg = bmsr.bits.auto_neg_able;
5253 statsp->mac_stats.cap_100T4 = 0;
5254 statsp->mac_stats.cap_100fdx = 0;
5255 statsp->mac_stats.cap_100hdx = 0;
5256 statsp->mac_stats.cap_10fdx = 0;
5257 statsp->mac_stats.cap_10hdx = 0;
5258 statsp->mac_stats.cap_asmpause = param_arr[param_anar_asmpause].value;
5259 statsp->mac_stats.cap_pause = param_arr[param_anar_pause].value;
5260
5261 /*
5262 * Initialize the xcvr advertised capability statistics.
5263 */
5264 statsp->mac_stats.adv_cap_autoneg = param_arr[param_autoneg].value;
5265 statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value;
5266 statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value;
5267 statsp->mac_stats.adv_cap_100T4 = param_arr[param_anar_100T4].value;
5268 statsp->mac_stats.adv_cap_100fdx = param_arr[param_anar_100fdx].value;
5269 statsp->mac_stats.adv_cap_100hdx = param_arr[param_anar_100hdx].value;
5270 statsp->mac_stats.adv_cap_10fdx = param_arr[param_anar_10fdx].value;
5271 statsp->mac_stats.adv_cap_10hdx = param_arr[param_anar_10hdx].value;
5272 statsp->mac_stats.adv_cap_asmpause =
5273 param_arr[param_anar_asmpause].value;
5274 statsp->mac_stats.adv_cap_pause = param_arr[param_anar_pause].value;
5275
5276 /*
5277 * Check for extended status just in case we're
5278 * running a Gigibit phy.
5279 */
5280 if (bmsr.bits.extend_status) {
5281 #if defined(__i386)
5282 if ((status = nxge_mii_read(nxgep, xcvr_portn,
5283 (uint8_t)(uint32_t)(&mii_regs->esr), &esr.value)) !=
5284 NXGE_OK)
5285 goto fail;
5286 #else
5287 if ((status = nxge_mii_read(nxgep, xcvr_portn,
5288 (uint8_t)(uint64_t)(&mii_regs->esr), &esr.value)) !=
5289 NXGE_OK)
5290 goto fail;
5291 #endif
5292 param_arr[param_anar_1000fdx].value &=
5293 esr.bits.link_1000fdx;
5294 param_arr[param_anar_1000hdx].value = 0;
5295
5296 statsp->mac_stats.cap_1000fdx =
5297 (esr.bits.link_1000Xfdx || esr.bits.link_1000fdx);
5298 statsp->mac_stats.cap_1000hdx = 0;
5299 } else {
5300 param_arr[param_anar_1000fdx].value = 0;
5301 param_arr[param_anar_1000hdx].value = 0;
5302 }
5303
5304 /*
5305 * Initialize 1G Statistics once the capability is established.
5306 */
5307 statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value;
5308 statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value;
5309
5310 /*
5311 * Initialize the link statistics.
5312 */
5313 statsp->mac_stats.link_T4 = 0;
5314 statsp->mac_stats.link_asmpause = 0;
5315 statsp->mac_stats.link_pause = 0;
5316 statsp->mac_stats.link_speed = 0;
5317 statsp->mac_stats.link_duplex = 0;
5318 statsp->mac_stats.link_up = 0;
5319
5320 /*
5321 * Switch off Auto-negotiation, 100M and full duplex.
5322 */
5323 bmcr.value = 0;
5324 #if defined(__i386)
5325 if ((status = nxge_mii_write(nxgep, xcvr_portn,
5326 (uint8_t)(uint32_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK)
5327 goto fail;
5328 #else
5329 if ((status = nxge_mii_write(nxgep, xcvr_portn,
5330 (uint8_t)(uint64_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK)
5331 goto fail;
5332 #endif
5333
5334 if ((statsp->port_stats.lb_mode == nxge_lb_phy) ||
5335 (statsp->port_stats.lb_mode == nxge_lb_phy1000)) {
5336 bmcr.bits.loopback = 1;
5337 bmcr.bits.enable_autoneg = 0;
5338 if (statsp->port_stats.lb_mode == nxge_lb_phy1000)
5339 bmcr.bits.speed_1000_sel = 1;
5340 bmcr.bits.duplex_mode = 1;
5341 param_arr[param_autoneg].value = 0;
5342 } else {
5343 bmcr.bits.loopback = 0;
5344 }
5345
5346 if (statsp->port_stats.lb_mode == nxge_lb_ext1000) {
5347 param_arr[param_autoneg].value = 0;
5348 bcm5464r_aux.value = 0;
5349 bcm5464r_aux.bits.ext_lb = 1;
5350 bcm5464r_aux.bits.write_1 = 1;
5351 if ((status = nxge_mii_write(nxgep, xcvr_portn,
5352 BCM5464R_AUX_CTL, bcm5464r_aux.value)) != NXGE_OK)
5353 goto fail;
5354 }
5355
5356 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Going into forced mode."));
5357 bmcr.bits.speed_1000_sel = 1;
5358 bmcr.bits.speed_sel = 0;
5359 bmcr.bits.duplex_mode = 1;
5360 statsp->mac_stats.link_speed = 1000;
5361 statsp->mac_stats.link_duplex = 2;
5362
5363 if ((statsp->port_stats.lb_mode == nxge_lb_ext1000)) {
5364 /* BCM5464R 1000mbps external loopback mode */
5365 gcr.value = 0;
5366 gcr.bits.ms_mode_en = 1;
5367 gcr.bits.master = 1;
5368 #if defined(__i386)
5369 if ((status = nxge_mii_write(nxgep, xcvr_portn,
5370 (uint8_t)(uint32_t)(&mii_regs->gcr),
5371 gcr.value)) != NXGE_OK)
5372 goto fail;
5373 #else
5374 if ((status = nxge_mii_write(nxgep, xcvr_portn,
5375 (uint8_t)(uint64_t)(&mii_regs->gcr),
5376 gcr.value)) != NXGE_OK)
5377 goto fail;
5378 #endif
5379 bmcr.value = 0;
5380 bmcr.bits.speed_1000_sel = 1;
5381 statsp->mac_stats.link_speed = 1000;
5382 }
5383
5384 #if defined(__i386)
5385 if ((status = nxge_mii_write(nxgep, xcvr_portn,
5386 (uint8_t)(uint32_t)(&mii_regs->bmcr),
5387 bmcr.value)) != NXGE_OK)
5388 goto fail;
5389 #else
5390 if ((status = nxge_mii_write(nxgep, xcvr_portn,
5391 (uint8_t)(uint64_t)(&mii_regs->bmcr),
5392 bmcr.value)) != NXGE_OK)
5393 goto fail;
5394 #endif
5395
5396 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
5397 "nxge_mii_xcvr_fiber_init: value wrote bmcr = 0x%x",
5398 bmcr.value));
5399
5400 #if defined(__i386)
5401 if ((status = nxge_mii_read(nxgep, xcvr_portn,
5402 (uint8_t)(uint32_t)(&mii_regs->bmcr), &bmcr.value)) != NXGE_OK)
5403 goto fail;
5404 #else
5405 if ((status = nxge_mii_read(nxgep, xcvr_portn,
5406 (uint8_t)(uint64_t)(&mii_regs->bmcr), &bmcr.value)) != NXGE_OK)
5407 goto fail;
5408 #endif
5409
5410 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
5411 "nxge_mii_xcvr_fiber_init: read bmcr = 0x%04X", bmcr.value));
5412
5413 /*
5414 * Initialize the xcvr status kept in the context structure.
5415 */
5416 nxgep->soft_bmsr.value = 0;
5417 #if defined(__i386)
5418 if ((status = nxge_mii_read(nxgep, xcvr_portn,
5419 (uint8_t)(uint32_t)(&mii_regs->bmsr),
5420 &nxgep->bmsr.value)) != NXGE_OK)
5421 goto fail;
5422 #else
5423 if ((status = nxge_mii_read(nxgep, xcvr_portn,
5424 (uint8_t)(uint64_t)(&mii_regs->bmsr),
5425 &nxgep->bmsr.value)) != NXGE_OK)
5426 goto fail;
5427 #endif
5428
5429 statsp->mac_stats.xcvr_inits++;
5430 nxgep->bmsr.value = 0;
5431
5432 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
5433 "<== nxge_mii_xcvr_fiber_init status 0x%x", status));
5434 return (status);
5435
5436 fail:
5437 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
5438 "<== nxge_mii_xcvr_fiber_init status 0x%x", status));
5439 return (status);
5440 }
5441
5442 /* Read from a MII compliant register */
5443
5444 nxge_status_t
nxge_mii_read(p_nxge_t nxgep,uint8_t xcvr_portn,uint8_t xcvr_reg,uint16_t * value)5445 nxge_mii_read(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t xcvr_reg,
5446 uint16_t *value)
5447 {
5448 npi_status_t rs = NPI_SUCCESS;
5449
5450 NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mii_read: xcvr_port<%d>"
5451 "xcvr_reg<%d>", xcvr_portn, xcvr_reg));
5452
5453 MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock);
5454
5455 if ((nxgep->mac.portmode == PORT_1G_COPPER) ||
5456 (nxgep->mac.portmode == PORT_1G_RGMII_FIBER)) {
5457 if ((rs = npi_mac_mif_mii_read(nxgep->npi_handle,
5458 xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS)
5459 goto fail;
5460 } else if ((nxgep->mac.portmode == PORT_1G_FIBER) ||
5461 (nxgep->mac.portmode == PORT_1G_SERDES)) {
5462 if ((rs = npi_mac_pcs_mii_read(nxgep->npi_handle,
5463 xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS)
5464 goto fail;
5465 } else
5466 goto fail;
5467
5468 MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
5469
5470 NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mii_read: xcvr_port<%d>"
5471 "xcvr_reg<%d> value=0x%x", xcvr_portn, xcvr_reg, *value));
5472 return (NXGE_OK);
5473 fail:
5474 MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
5475 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
5476 "nxge_mii_read: Failed to read mii on xcvr %d", xcvr_portn));
5477
5478 return (NXGE_ERROR | rs);
5479 }
5480
5481 /* Write to a MII compliant Register */
5482
5483 nxge_status_t
nxge_mii_write(p_nxge_t nxgep,uint8_t xcvr_portn,uint8_t xcvr_reg,uint16_t value)5484 nxge_mii_write(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t xcvr_reg,
5485 uint16_t value)
5486 {
5487 npi_status_t rs = NPI_SUCCESS;
5488
5489 NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mii_write: xcvr_port<%d>"
5490 "xcvr_reg<%d> value=0x%x", xcvr_portn, xcvr_reg, value));
5491
5492 MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock);
5493
5494 if ((nxgep->mac.portmode == PORT_1G_COPPER) ||
5495 (nxgep->mac.portmode == PORT_1G_RGMII_FIBER)) {
5496 if ((rs = npi_mac_mif_mii_write(nxgep->npi_handle,
5497 xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS)
5498 goto fail;
5499 } else if ((nxgep->mac.portmode == PORT_1G_FIBER) ||
5500 (nxgep->mac.portmode == PORT_1G_SERDES)) {
5501 if ((rs = npi_mac_pcs_mii_write(nxgep->npi_handle,
5502 xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS)
5503 goto fail;
5504 } else
5505 goto fail;
5506
5507 MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
5508
5509 NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mii_write: xcvr_port<%d>"
5510 "xcvr_reg<%d>", xcvr_portn, xcvr_reg));
5511 return (NXGE_OK);
5512 fail:
5513 MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
5514
5515 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
5516 "nxge_mii_write: Failed to write mii on xcvr %d", xcvr_portn));
5517
5518 return (NXGE_ERROR | rs);
5519 }
5520
5521 /*
5522 * Perform write to Clause45 serdes / transceiver device
5523 * Arguments:
5524 * xcvr_portn: The IEEE 802.3 Clause45 PHYAD, it is the same as port
5525 * number if nxge_mdio_write is used for accessing the
5526 * internal LSIL serdes. Otherwise PHYAD is different
5527 * for different platforms.
5528 * device: With each PHYAD, the driver can use MDIO to control
5529 * multiple devices inside the PHY, here "device" is an
5530 * MMD (MDIO managable device).
5531 * xcvr_reg: Each device has multiple registers. xcvr_reg specifies
5532 * the register which the driver will write value to.
5533 * value: The register value will be filled in.
5534 */
5535 nxge_status_t
nxge_mdio_read(p_nxge_t nxgep,uint8_t xcvr_portn,uint8_t device,uint16_t xcvr_reg,uint16_t * value)5536 nxge_mdio_read(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t device,
5537 uint16_t xcvr_reg, uint16_t *value)
5538 {
5539 npi_status_t rs = NPI_SUCCESS;
5540
5541 NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mdio_read: xcvr_port<%d>",
5542 xcvr_portn));
5543
5544 MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock);
5545
5546 if ((rs = npi_mac_mif_mdio_read(nxgep->npi_handle,
5547 xcvr_portn, device, xcvr_reg, value)) != NPI_SUCCESS)
5548 goto fail;
5549
5550 MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
5551
5552 NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mdio_read: xcvr_port<%d>",
5553 xcvr_portn));
5554 return (NXGE_OK);
5555 fail:
5556 MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
5557
5558 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
5559 "nxge_mdio_read: Failed to read mdio on xcvr %d", xcvr_portn));
5560
5561 return (NXGE_ERROR | rs);
5562 }
5563
5564 /* Perform write to Clause45 serdes / transceiver device */
5565
5566 nxge_status_t
nxge_mdio_write(p_nxge_t nxgep,uint8_t xcvr_portn,uint8_t device,uint16_t xcvr_reg,uint16_t value)5567 nxge_mdio_write(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t device,
5568 uint16_t xcvr_reg, uint16_t value)
5569 {
5570 npi_status_t rs = NPI_SUCCESS;
5571
5572 NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mdio_write: xcvr_port<%d>",
5573 xcvr_portn));
5574
5575 MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock);
5576
5577 if ((rs = npi_mac_mif_mdio_write(nxgep->npi_handle,
5578 xcvr_portn, device, xcvr_reg, value)) != NPI_SUCCESS)
5579 goto fail;
5580
5581 MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
5582
5583 NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mdio_write: xcvr_port<%d>",
5584 xcvr_portn));
5585 return (NXGE_OK);
5586 fail:
5587 MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
5588
5589 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
5590 "nxge_mdio_write: Failed to write mdio on xcvr %d", xcvr_portn));
5591
5592 return (NXGE_ERROR | rs);
5593 }
5594
5595
5596 /* Check MII to see if there is any link status change */
5597
5598 nxge_status_t
nxge_mii_check(p_nxge_t nxgep,mii_bmsr_t bmsr,mii_bmsr_t bmsr_ints,nxge_link_state_t * link_up)5599 nxge_mii_check(p_nxge_t nxgep, mii_bmsr_t bmsr, mii_bmsr_t bmsr_ints,
5600 nxge_link_state_t *link_up)
5601 {
5602 p_nxge_param_t param_arr;
5603 p_nxge_stats_t statsp;
5604 p_mii_regs_t mii_regs;
5605 p_mii_bmsr_t soft_bmsr;
5606 mii_anar_t anar;
5607 mii_anlpar_t anlpar;
5608 mii_anar_t an_common;
5609 mii_aner_t aner;
5610 mii_gsr_t gsr;
5611 nxge_status_t status = NXGE_OK;
5612
5613 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_check"));
5614
5615 mii_regs = NULL;
5616 param_arr = nxgep->param_arr;
5617 statsp = nxgep->statsp;
5618 soft_bmsr = &nxgep->soft_bmsr;
5619 *link_up = LINK_NO_CHANGE;
5620
5621 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
5622 "==> nxge_mii_check bmsr 0x%x bmsr_int 0x%x",
5623 bmsr.value, bmsr_ints.value));
5624
5625 if (bmsr_ints.bits.link_status) {
5626 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
5627 "==> nxge_mii_check (link up) bmsr 0x%x bmsr_int 0x%x",
5628 bmsr.value, bmsr_ints.value));
5629 if (bmsr.bits.link_status) {
5630 soft_bmsr->bits.link_status = 1;
5631 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
5632 "==> nxge_mii_check (link up) soft bmsr 0x%x bmsr_int "
5633 "0x%x", bmsr.value, bmsr_ints.value));
5634 } else {
5635 /* Only status change will update *link_up */
5636 if (statsp->mac_stats.link_up == 1) {
5637 *link_up = LINK_IS_DOWN;
5638 /* Will notify, turn off further msg */
5639 nxgep->link_notify = B_FALSE;
5640 }
5641 statsp->mac_stats.link_up = 0;
5642 soft_bmsr->bits.link_status = 0;
5643 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
5644 "Link down cable problem"));
5645 }
5646 }
5647
5648 if (nxgep->mac.portmode == PORT_1G_COPPER &&
5649 param_arr[param_autoneg].value) {
5650 if (bmsr_ints.bits.auto_neg_complete) {
5651 if (bmsr.bits.auto_neg_complete)
5652 soft_bmsr->bits.auto_neg_complete = 1;
5653 else
5654 soft_bmsr->bits.auto_neg_complete = 0;
5655 }
5656 if (soft_bmsr->bits.link_status == 0) {
5657 statsp->mac_stats.link_T4 = 0;
5658 statsp->mac_stats.link_speed = 0;
5659 statsp->mac_stats.link_duplex = 0;
5660 statsp->mac_stats.link_asmpause = 0;
5661 statsp->mac_stats.link_pause = 0;
5662 statsp->mac_stats.lp_cap_autoneg = 0;
5663 statsp->mac_stats.lp_cap_100T4 = 0;
5664 statsp->mac_stats.lp_cap_1000fdx = 0;
5665 statsp->mac_stats.lp_cap_1000hdx = 0;
5666 statsp->mac_stats.lp_cap_100fdx = 0;
5667 statsp->mac_stats.lp_cap_100hdx = 0;
5668 statsp->mac_stats.lp_cap_10fdx = 0;
5669 statsp->mac_stats.lp_cap_10hdx = 0;
5670 statsp->mac_stats.lp_cap_10gfdx = 0;
5671 statsp->mac_stats.lp_cap_10ghdx = 0;
5672 statsp->mac_stats.lp_cap_asmpause = 0;
5673 statsp->mac_stats.lp_cap_pause = 0;
5674 }
5675 } else
5676 soft_bmsr->bits.auto_neg_complete = 1;
5677
5678 if ((bmsr_ints.bits.link_status ||
5679 bmsr_ints.bits.auto_neg_complete) &&
5680 soft_bmsr->bits.link_status &&
5681 soft_bmsr->bits.auto_neg_complete) {
5682 if (statsp->mac_stats.link_up == 0) {
5683 *link_up = LINK_IS_UP;
5684 nxgep->link_notify = B_FALSE;
5685 }
5686 statsp->mac_stats.link_up = 1;
5687
5688 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
5689 "==> nxge_mii_check "
5690 "(auto negotiation complete or link up) "
5691 "soft bmsr 0x%x bmsr_int 0x%x",
5692 bmsr.value, bmsr_ints.value));
5693
5694 if (nxgep->mac.portmode == PORT_1G_COPPER &&
5695 param_arr[param_autoneg].value) {
5696 if ((status = nxge_mii_read(nxgep,
5697 statsp->mac_stats.xcvr_portn,
5698 #if defined(__i386)
5699 (uint8_t)(uint32_t)(&mii_regs->anar),
5700 #else
5701 (uint8_t)(uint64_t)(&mii_regs->anar),
5702 #endif
5703 &anar.value)) != NXGE_OK)
5704 goto fail;
5705 if ((status = nxge_mii_read(nxgep,
5706 statsp->mac_stats.xcvr_portn,
5707 #if defined(__i386)
5708 (uint8_t)(uint32_t)(&mii_regs->anlpar),
5709 #else
5710 (uint8_t)(uint64_t)(&mii_regs->anlpar),
5711 #endif
5712 &anlpar.value)) != NXGE_OK)
5713 goto fail;
5714 if ((status = nxge_mii_read(nxgep,
5715 statsp->mac_stats.xcvr_portn,
5716 #if defined(__i386)
5717 (uint8_t)(uint32_t)(&mii_regs->aner),
5718 #else
5719 (uint8_t)(uint64_t)(&mii_regs->aner),
5720 #endif
5721 &aner.value)) != NXGE_OK)
5722 goto fail;
5723 statsp->mac_stats.lp_cap_autoneg = aner.bits.lp_an_able;
5724 statsp->mac_stats.lp_cap_100T4 = anlpar.bits.cap_100T4;
5725 statsp->mac_stats.lp_cap_100fdx =
5726 anlpar.bits.cap_100fdx;
5727 statsp->mac_stats.lp_cap_100hdx =
5728 anlpar.bits.cap_100hdx;
5729 statsp->mac_stats.lp_cap_10fdx = anlpar.bits.cap_10fdx;
5730 statsp->mac_stats.lp_cap_10hdx = anlpar.bits.cap_10hdx;
5731 statsp->mac_stats.lp_cap_asmpause =
5732 anlpar.bits.cap_asmpause;
5733 statsp->mac_stats.lp_cap_pause = anlpar.bits.cap_pause;
5734 an_common.value = anar.value & anlpar.value;
5735 if (param_arr[param_anar_1000fdx].value ||
5736 param_arr[param_anar_1000hdx].value) {
5737 if ((status = nxge_mii_read(nxgep,
5738 statsp->mac_stats.xcvr_portn,
5739 #if defined(__i386)
5740 (uint8_t)(uint32_t)(&mii_regs->gsr),
5741 #else
5742 (uint8_t)(uint64_t)(&mii_regs->gsr),
5743 #endif
5744 &gsr.value)) != NXGE_OK)
5745 goto fail;
5746 statsp->mac_stats.lp_cap_1000fdx =
5747 gsr.bits.link_1000fdx;
5748 statsp->mac_stats.lp_cap_1000hdx =
5749 gsr.bits.link_1000hdx;
5750 if (param_arr[param_anar_1000fdx].value &&
5751 gsr.bits.link_1000fdx) {
5752 statsp->mac_stats.link_speed = 1000;
5753 statsp->mac_stats.link_duplex = 2;
5754 } else if (
5755 param_arr[param_anar_1000hdx].value &&
5756 gsr.bits.link_1000hdx) {
5757 statsp->mac_stats.link_speed = 1000;
5758 statsp->mac_stats.link_duplex = 1;
5759 }
5760 }
5761 if ((an_common.value != 0) &&
5762 !(statsp->mac_stats.link_speed)) {
5763 if (an_common.bits.cap_100T4) {
5764 statsp->mac_stats.link_T4 = 1;
5765 statsp->mac_stats.link_speed = 100;
5766 statsp->mac_stats.link_duplex = 1;
5767 } else if (an_common.bits.cap_100fdx) {
5768 statsp->mac_stats.link_speed = 100;
5769 statsp->mac_stats.link_duplex = 2;
5770 } else if (an_common.bits.cap_100hdx) {
5771 statsp->mac_stats.link_speed = 100;
5772 statsp->mac_stats.link_duplex = 1;
5773 } else if (an_common.bits.cap_10fdx) {
5774 statsp->mac_stats.link_speed = 10;
5775 statsp->mac_stats.link_duplex = 2;
5776 } else if (an_common.bits.cap_10hdx) {
5777 statsp->mac_stats.link_speed = 10;
5778 statsp->mac_stats.link_duplex = 1;
5779 } else {
5780 goto fail;
5781 }
5782 }
5783 if (statsp->mac_stats.link_duplex != 1) {
5784 int link_pause;
5785 int cp, lcp;
5786
5787 statsp->mac_stats.link_asmpause =
5788 an_common.bits.cap_asmpause;
5789 cp = statsp->mac_stats.cap_pause;
5790 lcp = statsp->mac_stats.lp_cap_pause;
5791 if (statsp->mac_stats.link_asmpause) {
5792 if ((cp == 0) && (lcp == 1)) {
5793 link_pause = 0;
5794 } else {
5795 link_pause = 1;
5796 }
5797 } else {
5798 link_pause = an_common.bits.cap_pause;
5799 }
5800 statsp->mac_stats.link_pause = link_pause;
5801 }
5802 } else if (nxgep->mac.portmode == PORT_1G_RGMII_FIBER) {
5803 statsp->mac_stats.link_speed = 1000;
5804 statsp->mac_stats.link_duplex = 2;
5805 }
5806 }
5807 /* Initial link_notify, delay link down msg */
5808 if (nxgep->link_notify && nxgep->nxge_mac_state == NXGE_MAC_STARTED &&
5809 (statsp->mac_stats.link_up == 1 || nxgep->link_check_count > 3)) {
5810 *link_up = ((statsp->mac_stats.link_up) ? LINK_IS_UP :
5811 LINK_IS_DOWN);
5812 nxgep->link_notify = B_FALSE;
5813 }
5814 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_mii_check"));
5815 return (NXGE_OK);
5816 fail:
5817 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
5818 "nxge_mii_check: Unable to check MII"));
5819 return (status);
5820 }
5821
5822 /*
5823 * Check PCS to see if there is any link status change.
5824 * This function is called by PORT_1G_SERDES only.
5825 */
5826 void
nxge_pcs_check(p_nxge_t nxgep,uint8_t portn,nxge_link_state_t * link_up)5827 nxge_pcs_check(p_nxge_t nxgep, uint8_t portn, nxge_link_state_t *link_up)
5828 {
5829 p_nxge_stats_t statsp;
5830 boolean_t linkup;
5831
5832 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_pcs_check"));
5833
5834 statsp = nxgep->statsp;
5835 *link_up = LINK_NO_CHANGE;
5836
5837 (void) npi_mac_get_link_status(nxgep->npi_handle, portn, &linkup);
5838 if (linkup) {
5839 if ((nxgep->link_notify &&
5840 nxgep->nxge_mac_state == NXGE_MAC_STARTED) ||
5841 nxgep->statsp->mac_stats.link_up == 0) {
5842 statsp->mac_stats.link_up = 1;
5843 statsp->mac_stats.link_speed = 1000;
5844 statsp->mac_stats.link_duplex = 2;
5845 *link_up = LINK_IS_UP;
5846 nxgep->link_notify = B_FALSE;
5847 }
5848 } else {
5849 if ((nxgep->link_notify && nxgep->link_check_count > 3 &&
5850 nxgep->nxge_mac_state == NXGE_MAC_STARTED) ||
5851 nxgep->statsp->mac_stats.link_up == 1) {
5852 statsp->mac_stats.link_up = 0;
5853 statsp->mac_stats.link_speed = 0;
5854 statsp->mac_stats.link_duplex = 0;
5855 *link_up = LINK_IS_DOWN;
5856 nxgep->link_notify = B_FALSE;
5857 }
5858 }
5859
5860 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_pcs_check"));
5861 }
5862
5863 /* Add a multicast address entry into the HW hash table */
5864
5865 nxge_status_t
nxge_add_mcast_addr(p_nxge_t nxgep,struct ether_addr * addrp)5866 nxge_add_mcast_addr(p_nxge_t nxgep, struct ether_addr *addrp)
5867 {
5868 uint32_t mchash;
5869 p_hash_filter_t hash_filter;
5870 uint16_t hash_bit;
5871 uint_t j;
5872 nxge_status_t status = NXGE_OK;
5873 npi_status_t rs;
5874
5875 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_add_mcast_addr"));
5876
5877 RW_ENTER_WRITER(&nxgep->filter_lock);
5878 mchash = crc32_mchash(addrp);
5879 if (nxgep->hash_filter == NULL) {
5880 NXGE_DEBUG_MSG((NULL, STR_CTL,
5881 "Allocating hash filter storage."));
5882 nxgep->hash_filter = KMEM_ZALLOC(sizeof (hash_filter_t),
5883 KM_SLEEP);
5884 }
5885
5886 hash_filter = nxgep->hash_filter;
5887 j = mchash / HASH_REG_WIDTH;
5888 hash_bit = (1 << (mchash % HASH_REG_WIDTH));
5889 hash_filter->hash_filter_regs[j] |= hash_bit;
5890 hash_filter->hash_bit_ref_cnt[mchash]++;
5891 if (hash_filter->hash_bit_ref_cnt[mchash] == 1) {
5892 hash_filter->hash_ref_cnt++;
5893 }
5894
5895 rs = nxge_rx_mac_mcast_hash_table(nxgep);
5896 if (rs != NPI_SUCCESS)
5897 goto fail;
5898
5899 RW_EXIT(&nxgep->filter_lock);
5900 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_add_mcast_addr"));
5901 return (NXGE_OK);
5902 fail:
5903 RW_EXIT(&nxgep->filter_lock);
5904 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_add_mcast_addr: "
5905 "Unable to add multicast address"));
5906 return (status);
5907 }
5908
5909 /* Remove a multicast address entry from the HW hash table */
5910
5911 nxge_status_t
nxge_del_mcast_addr(p_nxge_t nxgep,struct ether_addr * addrp)5912 nxge_del_mcast_addr(p_nxge_t nxgep, struct ether_addr *addrp)
5913 {
5914 uint32_t mchash;
5915 p_hash_filter_t hash_filter;
5916 uint16_t hash_bit;
5917 uint_t j;
5918 nxge_status_t status = NXGE_OK;
5919 npi_status_t rs;
5920
5921 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_del_mcast_addr"));
5922 RW_ENTER_WRITER(&nxgep->filter_lock);
5923 mchash = crc32_mchash(addrp);
5924 if (nxgep->hash_filter == NULL) {
5925 NXGE_DEBUG_MSG((NULL, STR_CTL,
5926 "Hash filter already de_allocated."));
5927 RW_EXIT(&nxgep->filter_lock);
5928 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_del_mcast_addr"));
5929 return (NXGE_OK);
5930 }
5931 hash_filter = nxgep->hash_filter;
5932 hash_filter->hash_bit_ref_cnt[mchash]--;
5933 if (hash_filter->hash_bit_ref_cnt[mchash] == 0) {
5934 j = mchash / HASH_REG_WIDTH;
5935 hash_bit = (1 << (mchash % HASH_REG_WIDTH));
5936 hash_filter->hash_filter_regs[j] &= ~hash_bit;
5937 hash_filter->hash_ref_cnt--;
5938 }
5939
5940 if (hash_filter->hash_ref_cnt == 0) {
5941 NXGE_DEBUG_MSG((NULL, STR_CTL,
5942 "De-allocating hash filter storage."));
5943 KMEM_FREE(hash_filter, sizeof (hash_filter_t));
5944 nxgep->hash_filter = NULL;
5945 }
5946
5947 rs = nxge_rx_mac_mcast_hash_table(nxgep);
5948 if (rs != NPI_SUCCESS)
5949 goto fail;
5950
5951 RW_EXIT(&nxgep->filter_lock);
5952 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_del_mcast_addr"));
5953
5954 return (NXGE_OK);
5955 fail:
5956 RW_EXIT(&nxgep->filter_lock);
5957 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_del_mcast_addr: "
5958 "Unable to remove multicast address"));
5959
5960 return (status);
5961 }
5962
5963 /* Set MAC address into MAC address HW registers */
5964
5965 nxge_status_t
nxge_set_mac_addr(p_nxge_t nxgep,struct ether_addr * addrp)5966 nxge_set_mac_addr(p_nxge_t nxgep, struct ether_addr *addrp)
5967 {
5968 nxge_status_t status = NXGE_OK;
5969
5970 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_set_mac_addr"));
5971
5972 MUTEX_ENTER(&nxgep->ouraddr_lock);
5973 /*
5974 * Exit if the address is same as ouraddr or multicast or broadcast
5975 */
5976 if (((addrp->ether_addr_octet[0] & 01) == 1) ||
5977 (ether_cmp(addrp, ðerbroadcastaddr) == 0) ||
5978 (ether_cmp(addrp, &nxgep->ouraddr) == 0)) {
5979 goto nxge_set_mac_addr_exit;
5980 }
5981 nxgep->ouraddr = *addrp;
5982 /*
5983 * Set new interface local address and re-init device.
5984 * This is destructive to any other streams attached
5985 * to this device.
5986 */
5987 RW_ENTER_WRITER(&nxgep->filter_lock);
5988 if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK)
5989 goto fail;
5990 if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK)
5991 goto fail;
5992
5993 RW_EXIT(&nxgep->filter_lock);
5994 MUTEX_EXIT(&nxgep->ouraddr_lock);
5995 goto nxge_set_mac_addr_end;
5996 nxge_set_mac_addr_exit:
5997 MUTEX_EXIT(&nxgep->ouraddr_lock);
5998 nxge_set_mac_addr_end:
5999 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_set_mac_addr"));
6000
6001 return (NXGE_OK);
6002 fail:
6003 MUTEX_EXIT(&nxgep->ouraddr_lock);
6004 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_set_mac_addr: "
6005 "Unable to set mac address"));
6006 return (status);
6007 }
6008
6009 static
6010 check_link_state_t
nxge_check_link_stop(nxge_t * nxge)6011 nxge_check_link_stop(nxge_t *nxge)
6012 {
6013 /* If the poll has been cancelled, return STOP. */
6014 MUTEX_ENTER(&nxge->poll_lock);
6015 if (nxge->suspended || nxge->poll_state == LINK_MONITOR_STOPPING) {
6016 nxge->poll_state = LINK_MONITOR_STOP;
6017 nxge->nxge_link_poll_timerid = 0;
6018 cv_broadcast(&nxge->poll_cv);
6019 MUTEX_EXIT(&nxge->poll_lock);
6020
6021 NXGE_DEBUG_MSG((nxge, MAC_CTL,
6022 "nxge_check_%s_link(port<%d>) stopped.",
6023 nxge->mac.portmode == PORT_10G_FIBER ? "10g" : "mii",
6024 nxge->mac.portnum));
6025 return (CHECK_LINK_STOP);
6026 }
6027 MUTEX_EXIT(&nxge->poll_lock);
6028
6029 return (CHECK_LINK_RESCHEDULE);
6030 }
6031
6032 /*
6033 * Check status of MII (MIF or PCS) link.
6034 * This function is called once per second, that is because this function
6035 * calls nxge_link_monitor with LINK_MONITOR_START, which starts a timer to
6036 * call this function recursively.
6037 */
6038 static nxge_status_t
nxge_check_mii_link(p_nxge_t nxgep)6039 nxge_check_mii_link(p_nxge_t nxgep)
6040 {
6041 mii_bmsr_t bmsr_ints, bmsr_data;
6042 mii_anlpar_t anlpar;
6043 mii_gsr_t gsr;
6044 p_mii_regs_t mii_regs;
6045 nxge_status_t status = NXGE_OK;
6046 uint8_t portn;
6047 nxge_link_state_t link_up;
6048
6049 if (nxgep->nxge_magic != NXGE_MAGIC)
6050 return (NXGE_ERROR);
6051
6052 if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP)
6053 return (NXGE_OK);
6054
6055 portn = nxgep->mac.portnum;
6056
6057 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_check_mii_link port<%d>",
6058 portn));
6059
6060 mii_regs = NULL;
6061
6062 RW_ENTER_WRITER(&nxgep->filter_lock);
6063
6064 if (nxgep->statsp->port_stats.lb_mode > nxge_lb_ext10)
6065 goto nxge_check_mii_link_exit;
6066
6067 switch (nxgep->mac.portmode) {
6068 default:
6069 bmsr_data.value = 0;
6070 if ((status = nxge_mii_read(nxgep,
6071 nxgep->statsp->mac_stats.xcvr_portn,
6072 #if defined(__i386)
6073 (uint8_t)(uint32_t)(&mii_regs->bmsr),
6074 #else
6075 (uint8_t)(uint64_t)(&mii_regs->bmsr),
6076 #endif
6077 &bmsr_data.value)) != NXGE_OK) {
6078 goto fail;
6079 }
6080
6081 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
6082 "==> nxge_check_mii_link port<0x%x> "
6083 "RIGHT AFTER READ bmsr_data 0x%x (nxgep->bmsr 0x%x ",
6084 portn, bmsr_data.value, nxgep->bmsr.value));
6085
6086 if (nxgep->param_arr[param_autoneg].value) {
6087 if ((status = nxge_mii_read(nxgep,
6088 nxgep->statsp->mac_stats.xcvr_portn,
6089 #if defined(__i386)
6090 (uint8_t)(uint32_t)(&mii_regs->gsr),
6091 #else
6092 (uint8_t)(uint64_t)(&mii_regs->gsr),
6093 #endif
6094 &gsr.value)) != NXGE_OK)
6095 goto fail;
6096 if ((status = nxge_mii_read(nxgep,
6097 nxgep->statsp->mac_stats.xcvr_portn,
6098 #if defined(__i386)
6099 (uint8_t)(uint32_t)(&mii_regs->anlpar),
6100 #else
6101 (uint8_t)(uint64_t)(&mii_regs->anlpar),
6102 #endif
6103 &anlpar.value)) != NXGE_OK)
6104 goto fail;
6105 if (nxgep->mac.portmode != PORT_1G_RGMII_FIBER) {
6106
6107 if (nxgep->statsp->mac_stats.link_up &&
6108 ((nxgep->statsp->mac_stats.lp_cap_1000fdx ^
6109 gsr.bits.link_1000fdx) ||
6110 (nxgep->statsp->mac_stats.lp_cap_1000hdx ^
6111 gsr.bits.link_1000hdx) ||
6112 (nxgep->statsp->mac_stats.lp_cap_100T4 ^
6113 anlpar.bits.cap_100T4) ||
6114 (nxgep->statsp->mac_stats.lp_cap_100fdx ^
6115 anlpar.bits.cap_100fdx) ||
6116 (nxgep->statsp->mac_stats.lp_cap_100hdx ^
6117 anlpar.bits.cap_100hdx) ||
6118 (nxgep->statsp->mac_stats.lp_cap_10fdx ^
6119 anlpar.bits.cap_10fdx) ||
6120 (nxgep->statsp->mac_stats.lp_cap_10hdx ^
6121 anlpar.bits.cap_10hdx))) {
6122 bmsr_data.bits.link_status = 0;
6123 }
6124 }
6125 }
6126
6127 /* Workaround for link down issue */
6128 if (bmsr_data.value == 0) {
6129 cmn_err(CE_NOTE, "!LINK DEBUG: Read zero bmsr\n");
6130 goto nxge_check_mii_link_exit;
6131 }
6132
6133 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
6134 "==> nxge_check_mii_link port<0x%x> :"
6135 "BEFORE BMSR ^ nxgep->bmsr 0x%x bmsr_data 0x%x",
6136 portn, nxgep->bmsr.value, bmsr_data.value));
6137
6138 bmsr_ints.value = nxgep->bmsr.value ^ bmsr_data.value;
6139 nxgep->bmsr.value = bmsr_data.value;
6140
6141 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
6142 "==> nxge_check_mii_link port<0x%x> CALLING "
6143 "bmsr_data 0x%x bmsr_ints.value 0x%x",
6144 portn, bmsr_data.value, bmsr_ints.value));
6145
6146 if ((status = nxge_mii_check(nxgep, bmsr_data, bmsr_ints,
6147 &link_up)) != NXGE_OK) {
6148 goto fail;
6149 }
6150 break;
6151
6152 case PORT_1G_SERDES:
6153 /*
6154 * Above default is for all cases except PORT_1G_SERDES.
6155 * The default case gets information from the PHY, but a
6156 * nxge whose portmode equals PORT_1G_SERDES does not
6157 * have a PHY.
6158 */
6159 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
6160 "==> nxge_check_mii_link port<%d> (SERDES)", portn));
6161 nxge_pcs_check(nxgep, portn, &link_up);
6162 break;
6163 }
6164
6165 nxge_check_mii_link_exit:
6166 RW_EXIT(&nxgep->filter_lock);
6167 if (link_up == LINK_IS_UP) {
6168 nxge_link_is_up(nxgep);
6169 } else if (link_up == LINK_IS_DOWN) {
6170 nxge_link_is_down(nxgep);
6171 }
6172 (void) nxge_link_monitor(nxgep, LINK_MONITOR_START);
6173
6174 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_check_mii_link port<%d>",
6175 portn));
6176 return (NXGE_OK);
6177
6178 fail:
6179 RW_EXIT(&nxgep->filter_lock);
6180
6181 (void) nxge_link_monitor(nxgep, LINK_MONITOR_START);
6182 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
6183 "nxge_check_mii_link: Failed to check link port<%d>", portn));
6184 return (status);
6185 }
6186
6187 /*ARGSUSED*/
6188 static nxge_status_t
nxge_check_10g_link(p_nxge_t nxgep)6189 nxge_check_10g_link(p_nxge_t nxgep)
6190 {
6191 uint8_t portn;
6192 nxge_status_t status = NXGE_OK;
6193 boolean_t link_up;
6194 uint32_t val;
6195 npi_status_t rs;
6196
6197 if (nxgep->nxge_magic != NXGE_MAGIC)
6198 return (NXGE_ERROR);
6199
6200 if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP)
6201 return (NXGE_OK);
6202
6203 portn = nxgep->mac.portnum;
6204 val = 0;
6205 rs = NPI_SUCCESS;
6206
6207 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_check_10g_link port<%d>",
6208 portn));
6209
6210 switch (nxgep->mac.portmode) {
6211 default:
6212 /*
6213 * Check if the phy is present in case of hot swappable phy
6214 */
6215 if (nxgep->hot_swappable_phy) {
6216 boolean_t phy_present_now = B_FALSE;
6217
6218 if (nxge_hswap_phy_present(nxgep, portn))
6219 phy_present_now = B_TRUE;
6220
6221 /* Check back-to-back XAUI connect to detect Opus NEM */
6222 rs = npi_xmac_xpcs_read(nxgep->npi_handle,
6223 nxgep->mac.portnum, XPCS_REG_STATUS, &val);
6224 if (rs != 0)
6225 goto fail;
6226
6227 link_up = B_FALSE;
6228 if (val & XPCS_STATUS_LANE_ALIGN) {
6229 link_up = B_TRUE;
6230 }
6231
6232 if (nxgep->phy_absent) {
6233 if (phy_present_now) {
6234 /*
6235 * Detect, Initialize phy and do link up
6236 * set xcvr vals, link_init, nxge_init
6237 */
6238 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
6239 "Hot swappable phy DETECTED!!"));
6240 nxgep->phy_absent = B_FALSE;
6241 (void) nxge_xcvr_find(nxgep);
6242 (void) nxge_link_init(nxgep);
6243 if (!(nxgep->drv_state &
6244 STATE_HW_INITIALIZED)) {
6245 status = nxge_init(nxgep);
6246 if (status != NXGE_OK) {
6247 NXGE_ERROR_MSG((nxgep,
6248 NXGE_ERR_CTL,
6249 "Hot swappable "
6250 "phy present, but"
6251 " driver init"
6252 " failed..."));
6253 goto fail;
6254 }
6255 }
6256 } else if (link_up) { /* XAUI linkup, no PHY */
6257 /*
6258 * This is the back-to-back XAUI
6259 * connect case for Opus NEM.
6260 */
6261 nxgep->statsp->mac_stats.xcvr_inuse =
6262 XPCS_XCVR;
6263 nxgep->mac.portmode = PORT_10G_SERDES;
6264 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
6265 "HSP 10G Serdes DETECTED!!"));
6266 break;
6267 }
6268
6269 if (nxgep->link_notify &&
6270 nxgep->link_check_count > 3 &&
6271 nxgep->nxge_mac_state == NXGE_MAC_STARTED ||
6272 nxgep->statsp->mac_stats.link_up == 1) {
6273 nxgep->statsp->mac_stats.link_up = 0;
6274 nxgep->statsp->mac_stats.link_speed = 0;
6275 nxgep->statsp->mac_stats.link_duplex =
6276 0;
6277
6278 nxge_link_is_down(nxgep);
6279 nxgep->link_notify = B_FALSE;
6280 }
6281
6282 goto start_link_check;
6283
6284 } else if (!phy_present_now) {
6285 /*
6286 * Phy gone, bring link down reset xcvr vals
6287 */
6288 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
6289 "Hot swappable phy REMOVED!!"));
6290 nxgep->phy_absent = B_TRUE;
6291 nxgep->statsp->mac_stats.link_up = 0;
6292 nxgep->statsp->mac_stats.link_speed = 0;
6293 nxgep->statsp->mac_stats.link_duplex = 0;
6294 nxge_link_is_down(nxgep);
6295 nxgep->link_notify = B_FALSE;
6296
6297 (void) nxge_xcvr_find(nxgep);
6298
6299 goto start_link_check;
6300
6301 }
6302 }
6303
6304 switch (nxgep->chip_id) {
6305 case MRVL88X201X_CHIP_ID:
6306 status = nxge_check_mrvl88x2011_link(nxgep, &link_up);
6307 break;
6308 case NLP2020_CHIP_ID:
6309 status = nxge_check_nlp2020_link(nxgep, &link_up);
6310 break;
6311 default:
6312 status = nxge_check_bcm8704_link(nxgep, &link_up);
6313 break;
6314 }
6315
6316 if (status != NXGE_OK)
6317 goto fail;
6318 break;
6319 case PORT_10G_SERDES:
6320 rs = npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
6321 XPCS_REG_STATUS, &val);
6322 if (rs != 0)
6323 goto fail;
6324
6325 link_up = B_FALSE;
6326 if (val & XPCS_STATUS_LANE_ALIGN) {
6327 link_up = B_TRUE;
6328 }
6329
6330 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
6331 "==> nxge_check_10g_link port<%d> "
6332 "XPCS_REG_STATUS2 0x%x link_up %d",
6333 portn, val, link_up));
6334
6335 break;
6336 }
6337
6338 if (link_up) {
6339 if ((nxgep->link_notify &&
6340 nxgep->nxge_mac_state == NXGE_MAC_STARTED) ||
6341 nxgep->statsp->mac_stats.link_up == 0) {
6342 if (nxge_10g_link_led_on(nxgep) != NXGE_OK)
6343 goto fail;
6344 nxgep->statsp->mac_stats.link_up = 1;
6345 nxgep->statsp->mac_stats.link_speed = 10000;
6346 nxgep->statsp->mac_stats.link_duplex = 2;
6347
6348 nxge_link_is_up(nxgep);
6349 nxgep->link_notify = B_FALSE;
6350 }
6351 } else {
6352 if ((nxgep->link_notify && nxgep->link_check_count > 3 &&
6353 nxgep->nxge_mac_state == NXGE_MAC_STARTED) ||
6354 nxgep->statsp->mac_stats.link_up == 1) {
6355 if (nxge_10g_link_led_off(nxgep) != NXGE_OK)
6356 goto fail;
6357 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
6358 "Link down cable problem"));
6359 nxgep->statsp->mac_stats.link_up = 0;
6360 nxgep->statsp->mac_stats.link_speed = 0;
6361 nxgep->statsp->mac_stats.link_duplex = 0;
6362
6363 nxge_link_is_down(nxgep);
6364 nxgep->link_notify = B_FALSE;
6365
6366 if (nxgep->mac.portmode == PORT_10G_SERDES) {
6367 /*
6368 * NEM was unplugged, set up xcvr table
6369 * to find another xcvr in the future.
6370 */
6371 (void) nxge_xcvr_find(nxgep);
6372 }
6373 }
6374 }
6375
6376 start_link_check:
6377 (void) nxge_link_monitor(nxgep, LINK_MONITOR_START);
6378 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_check_10g_link port<%d>",
6379 portn));
6380 return (NXGE_OK);
6381
6382 fail:
6383 (void) nxge_check_link_stop(nxgep);
6384
6385 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
6386 "nxge_check_10g_link: Failed to check link port<%d>",
6387 portn));
6388 return (status);
6389 }
6390
6391
6392 /* Declare link down */
6393
6394 void
nxge_link_is_down(p_nxge_t nxgep)6395 nxge_link_is_down(p_nxge_t nxgep)
6396 {
6397 p_nxge_stats_t statsp;
6398 char link_stat_msg[64];
6399
6400 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_is_down"));
6401
6402 statsp = nxgep->statsp;
6403 (void) sprintf(link_stat_msg, "xcvr addr:0x%02x - link is down",
6404 statsp->mac_stats.xcvr_portn);
6405
6406 if (nxge_no_msg == B_FALSE) {
6407 NXGE_ERROR_MSG((nxgep, NXGE_NOTE, "%s", link_stat_msg));
6408 }
6409
6410 mac_link_update(nxgep->mach, LINK_STATE_DOWN);
6411
6412 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_is_down"));
6413 }
6414
6415 /* Declare link up */
6416
6417 void
nxge_link_is_up(p_nxge_t nxgep)6418 nxge_link_is_up(p_nxge_t nxgep)
6419 {
6420 p_nxge_stats_t statsp;
6421 char link_stat_msg[64];
6422 uint32_t val;
6423
6424 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_is_up"));
6425
6426 statsp = nxgep->statsp;
6427 (void) sprintf(link_stat_msg, "xcvr addr:0x%02x - link is up %d Mbps ",
6428 statsp->mac_stats.xcvr_portn,
6429 statsp->mac_stats.link_speed);
6430
6431 if (statsp->mac_stats.link_T4)
6432 (void) strcat(link_stat_msg, "T4");
6433 else if (statsp->mac_stats.link_duplex == 2)
6434 (void) strcat(link_stat_msg, "full duplex");
6435 else
6436 (void) strcat(link_stat_msg, "half duplex");
6437
6438
6439 /* Clean up symbol errors incurred during link transition */
6440 if ((nxgep->mac.portmode == PORT_10G_FIBER) ||
6441 (nxgep->mac.portmode == PORT_10G_COPPER) ||
6442 (nxgep->mac.portmode == PORT_10G_SERDES)) {
6443 (void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
6444 XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val);
6445 (void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
6446 XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val);
6447 }
6448
6449 /*
6450 * If the driver was plumbed without a link (therefore auto-negotiation
6451 * could not complete), the driver will detect a link up when a cable
6452 * conneting to a link partner is plugged into the port. By the time
6453 * link-up is detected, auto-negotiation should have completed (The
6454 * TN1010 tries to contact a link partner every 8~24ms). Here we re-
6455 * configure the Neptune/NIU according to the newly negotiated speed.
6456 * This is necessary only for the TN1010 basad device because only the
6457 * TN1010 supports dual speeds.
6458 */
6459 if (nxgep->mac.portmode == PORT_1G_TN1010 ||
6460 nxgep->mac.portmode == PORT_10G_TN1010) {
6461
6462 (void) nxge_set_tn1010_param(nxgep);
6463
6464 /*
6465 * nxge_xcvr_find calls nxge_get_xcvr_type (which sets
6466 * nxgep->portmode) and nxge_setup_xcvr_table (which sets
6467 * the nxgep->xcvr to the proper nxge_xcvr_table_t struct).
6468 */
6469 if (nxge_xcvr_find(nxgep) != NXGE_OK) {
6470 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
6471 "nxge_link_is_up: nxge_xcvr_find failed"));
6472 }
6473
6474 /* nxge_link_init calls nxge_xcvr_init and nxge_serdes_init */
6475 if (nxge_link_init(nxgep) != NXGE_OK) {
6476 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
6477 "nxge_link_is_up: nxge_link_init failed"));
6478 }
6479
6480 /*
6481 * nxge_mac_init calls many subroutines including
6482 * nxge_xif_init which sets XGMII or GMII mode
6483 */
6484 if (nxge_mac_init(nxgep) != NXGE_OK) {
6485 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
6486 "nxge_link_is_up: nxge_mac_init failed"));
6487 }
6488 } else {
6489 (void) nxge_xif_init(nxgep);
6490 }
6491
6492 if (nxge_no_msg == B_FALSE) {
6493 NXGE_ERROR_MSG((nxgep, NXGE_NOTE, "%s", link_stat_msg));
6494 }
6495
6496 mac_link_update(nxgep->mach, LINK_STATE_UP);
6497
6498 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_is_up"));
6499 }
6500
6501 #ifdef NXGE_DEBUG
6502 /* Dump all TN1010 Status registers */
6503 static void
nxge_dump_tn1010_status_regs(p_nxge_t nxgep)6504 nxge_dump_tn1010_status_regs(p_nxge_t nxgep)
6505 {
6506 uint16_t val;
6507
6508 nxge_mdio_read(nxgep, nxgep->xcvr_addr,
6509 TN1010_PMA_PMD_DEV_ADDR, 1, &val);
6510 cmn_err(CE_NOTE, "PMA status1 = 0x%x", val);
6511
6512 nxge_mdio_read(nxgep, nxgep->xcvr_addr,
6513 TN1010_PMA_PMD_DEV_ADDR, 8, &val);
6514 cmn_err(CE_NOTE, "PMA status2 = 0x%x", val);
6515
6516 nxge_mdio_read(nxgep, nxgep->xcvr_addr,
6517 TN1010_PMA_PMD_DEV_ADDR, 129, &val);
6518 cmn_err(CE_NOTE, "10BASET-T status = 0x%x", val);
6519
6520 nxge_mdio_read(nxgep, nxgep->xcvr_addr,
6521 TN1010_PCS_DEV_ADDR, 1, &val);
6522 cmn_err(CE_NOTE, "PCS status1 = 0x%x", val);
6523
6524 nxge_mdio_read(nxgep, nxgep->xcvr_addr,
6525 TN1010_PCS_DEV_ADDR, 8, &val);
6526 cmn_err(CE_NOTE, "PCS status2 = 0x%x", val);
6527
6528 nxge_mdio_read(nxgep, nxgep->xcvr_addr,
6529 TN1010_PCS_DEV_ADDR, 32, &val);
6530 cmn_err(CE_NOTE, "10GBASE-R status1 = 0x%x", val);
6531
6532 nxge_mdio_read(nxgep, nxgep->xcvr_addr,
6533 TN1010_PCS_DEV_ADDR, 33, &val);
6534 cmn_err(CE_NOTE, "10GBASE-R Status2 = 0x%x", val);
6535
6536 nxge_mdio_read(nxgep, nxgep->xcvr_addr,
6537 TN1010_PHYXS_DEV_ADDR, 1, &val);
6538 cmn_err(CE_NOTE, "PHYXS status1 = 0x%x", val);
6539
6540 nxge_mdio_read(nxgep, nxgep->xcvr_addr,
6541 TN1010_PHYXS_DEV_ADDR, 8, &val);
6542 cmn_err(CE_NOTE, "PHYXS status2 = 0x%x", val);
6543
6544 nxge_mdio_read(nxgep, nxgep->xcvr_addr,
6545 TN1010_PHYXS_DEV_ADDR, 24, &val);
6546 cmn_err(CE_NOTE, "XGXS Lane status = 0x%x", val);
6547
6548 nxge_mdio_read(nxgep, nxgep->xcvr_addr,
6549 TN1010_AUTONEG_DEV_ADDR, 1, &val);
6550 cmn_err(CE_NOTE, "Autoneg status = 0x%x", val);
6551
6552 nxge_mdio_read(nxgep, nxgep->xcvr_addr,
6553 TN1010_AUTONEG_DEV_ADDR, 33, &val);
6554 cmn_err(CE_NOTE, "10Gbase-T An status = 0x%x", val);
6555
6556 nxge_mdio_read(nxgep, nxgep->xcvr_addr,
6557 TN1010_VENDOR_MMD1_DEV_ADDR, 1, &val);
6558 cmn_err(CE_NOTE, "TN1010 status = 0x%x", val);
6559
6560 nxge_mdio_read(nxgep, nxgep->xcvr_addr,
6561 TN1010_VENDOR_MMD1_DEV_ADDR, 8, &val);
6562 cmn_err(CE_NOTE, "Device status = 0x%x", val);
6563
6564 nxge_mdio_read(nxgep, nxgep->xcvr_addr,
6565 TN1010_VENDOR_MMD1_DEV_ADDR, 16, &val);
6566 cmn_err(CE_NOTE, "DDR status = 0x%x", val);
6567
6568 nxge_mdio_read(nxgep, nxgep->xcvr_addr,
6569 TN1010_VENDOR_MMD1_DEV_ADDR, 17, &val);
6570 cmn_err(CE_NOTE, "DDR fault status = 0x%x", val);
6571
6572 nxge_mdio_read(nxgep, nxgep->xcvr_addr,
6573 TN1010_VENDOR_MMD1_DEV_ADDR, 11, &val);
6574 cmn_err(CE_NOTE, "Firmware Revision = 0x%x Major = 0x%x Minor = 0x%x",
6575 val, (val & 0xFF00) >> 8, val & 0x00FF);
6576 }
6577 #endif
6578
6579 /*
6580 * Calculate the bit in the multicast address filter
6581 * that selects the given * address.
6582 * Note: For GEM, the last 8-bits are used.
6583 */
6584 uint32_t
crc32_mchash(p_ether_addr_t addr)6585 crc32_mchash(p_ether_addr_t addr)
6586 {
6587 uint8_t *cp;
6588 uint32_t crc;
6589 uint32_t c;
6590 int byte;
6591 int bit;
6592
6593 cp = (uint8_t *)addr;
6594 crc = (uint32_t)0xffffffff;
6595 for (byte = 0; byte < 6; byte++) {
6596 c = (uint32_t)cp[byte];
6597 for (bit = 0; bit < 8; bit++) {
6598 if ((c & 0x1) ^ (crc & 0x1))
6599 crc = (crc >> 1)^0xedb88320;
6600 else
6601 crc = (crc >> 1);
6602 c >>= 1;
6603 }
6604 }
6605 return ((~crc) >> (32 - HASH_BITS));
6606 }
6607
6608 /* Reset serdes */
6609
6610 nxge_status_t
nxge_serdes_reset(p_nxge_t nxgep)6611 nxge_serdes_reset(p_nxge_t nxgep)
6612 {
6613 npi_handle_t handle;
6614
6615 handle = nxgep->npi_handle;
6616
6617 ESR_REG_WR(handle, ESR_RESET_REG, ESR_RESET_0 | ESR_RESET_1);
6618 drv_usecwait(500);
6619 ESR_REG_WR(handle, ESR_CONFIG_REG, 0);
6620
6621 return (NXGE_OK);
6622 }
6623
6624 /*
6625 * This function monitors link status using interrupt or polling.
6626 * It calls nxgep->xcvr.check_link, a member function of
6627 * nxge_xcvr_table_t. But nxgep->xcvr.check_link calls this
6628 * function back, that is why the check_link routine is
6629 * executed periodically.
6630 */
6631 nxge_status_t
nxge_link_monitor(p_nxge_t nxgep,link_mon_enable_t enable)6632 nxge_link_monitor(p_nxge_t nxgep, link_mon_enable_t enable)
6633 {
6634 nxge_status_t status = NXGE_OK;
6635
6636 /* If we are a guest domain driver, don't bother. */
6637 if (isLDOMguest(nxgep))
6638 return (status);
6639
6640 /*
6641 * Return immediately if this is an imaginary XMAC port.
6642 * (At least, we don't have 4-port XMAC cards yet.)
6643 */
6644 if ((nxgep->mac.portmode == PORT_10G_FIBER ||
6645 nxgep->mac.portmode == PORT_10G_COPPER ||
6646 nxgep->mac.portmode == PORT_10G_SERDES) &&
6647 (nxgep->mac.portnum > 1))
6648 return (NXGE_OK);
6649
6650 if (nxgep->statsp == NULL) {
6651 /* stats has not been allocated. */
6652 return (NXGE_OK);
6653 }
6654 /* Don't check link if we're in internal loopback mode */
6655 if (nxgep->statsp->port_stats.lb_mode >= nxge_lb_serdes10g)
6656 return (NXGE_OK);
6657
6658 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
6659 "==> nxge_link_monitor port<%d> enable=%d",
6660 nxgep->mac.portnum, enable));
6661 if (enable == LINK_MONITOR_START) {
6662 if (nxgep->mac.linkchkmode == LINKCHK_INTR) {
6663 if ((status = nxge_link_intr(nxgep, LINK_INTR_START))
6664 != NXGE_OK)
6665 goto fail;
6666 } else {
6667 timeout_id_t timerid;
6668 /*
6669 * check_link_stop means "Stop the link check", so
6670 * we return without starting the timer.
6671 */
6672 if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP)
6673 return (NXGE_OK);
6674
6675 /*
6676 * Otherwise fire the timer for the nxge to check
6677 * the link using the check_link function
6678 * of the nxge_xcvr_table and pass "nxgep" as the
6679 * argument to the check_link function.
6680 */
6681 if (nxgep->xcvr.check_link) {
6682 timerid = timeout(
6683 (fptrv_t)(nxgep->xcvr.check_link),
6684 nxgep,
6685 drv_usectohz(LINK_MONITOR_PERIOD));
6686 MUTEX_ENTER(&nxgep->poll_lock);
6687 nxgep->nxge_link_poll_timerid = timerid;
6688 MUTEX_EXIT(&nxgep->poll_lock);
6689 nxgep->link_check_count ++;
6690 } else {
6691 return (NXGE_ERROR);
6692 }
6693 }
6694 } else {
6695 if (nxgep->mac.linkchkmode == LINKCHK_INTR) {
6696 if ((status = nxge_link_intr(nxgep, LINK_INTR_STOP))
6697 != NXGE_OK)
6698 goto fail;
6699 } else {
6700 clock_t rv;
6701
6702 MUTEX_ENTER(&nxgep->poll_lock);
6703
6704 /* If <timerid> == 0, the link monitor has */
6705 /* never been started, or just now stopped. */
6706 if (nxgep->nxge_link_poll_timerid == 0) {
6707 MUTEX_EXIT(&nxgep->poll_lock);
6708 return (NXGE_OK);
6709 }
6710
6711 nxgep->poll_state = LINK_MONITOR_STOPPING;
6712 rv = cv_reltimedwait(&nxgep->poll_cv, &nxgep->poll_lock,
6713 drv_usectohz(LM_WAIT_MULTIPLIER *
6714 LINK_MONITOR_PERIOD), TR_CLOCK_TICK);
6715 if (rv == -1) {
6716 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
6717 "==> stopping port %d: "
6718 "cv_timedwait(%d) timed out",
6719 nxgep->mac.portnum, nxgep->poll_state));
6720 nxgep->poll_state = LINK_MONITOR_STOP;
6721 nxgep->nxge_link_poll_timerid = 0;
6722 }
6723
6724 MUTEX_EXIT(&nxgep->poll_lock);
6725 }
6726 }
6727 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
6728 "<== nxge_link_monitor port<%d> enable=%d",
6729 nxgep->mac.portnum, enable));
6730
6731 return (NXGE_OK);
6732 fail:
6733 return (status);
6734
6735 }
6736
6737 nxge_status_t
nxge_check_tn1010_link(p_nxge_t nxgep)6738 nxge_check_tn1010_link(p_nxge_t nxgep)
6739 {
6740 nxge_status_t status = NXGE_OK;
6741 nxge_link_state_t link_up;
6742
6743 if (nxgep->nxge_magic != NXGE_MAGIC) {
6744 /* magic is 0 if driver is not attached */
6745 return (NXGE_ERROR);
6746 }
6747
6748 /* Link has been stopped, no need to continue */
6749 if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP) {
6750 return (NXGE_OK);
6751 }
6752
6753 if (nxgep->statsp->port_stats.lb_mode > nxge_lb_ext10)
6754 goto nxge_check_tn1010_link_exit;
6755
6756 if ((status = nxge_tn1010_check(nxgep, &link_up)) != NXGE_OK)
6757 goto fail;
6758
6759 nxge_check_tn1010_link_exit:
6760 if (link_up == LINK_IS_UP)
6761 nxge_link_is_up(nxgep);
6762 else if (link_up == LINK_IS_DOWN)
6763 nxge_link_is_down(nxgep);
6764
6765 /*
6766 * nxge_link_monitor will call (nxgep->xcvr.check_link)
6767 * which could be THIS function.
6768 */
6769 (void) nxge_link_monitor(nxgep, LINK_MONITOR_START);
6770
6771 return (NXGE_OK);
6772
6773 fail:
6774 (void) nxge_link_monitor(nxgep, LINK_MONITOR_START);
6775
6776 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
6777 "nxge_check_tn1010_link: Failed to check link"));
6778 return (status);
6779 }
6780
6781
6782 /*
6783 * Fill variable "link_up" with either LINK_IS_UP or LINK_IS_DOWN.
6784 */
6785 static nxge_status_t
nxge_tn1010_check(p_nxge_t nxgep,nxge_link_state_t * link_up)6786 nxge_tn1010_check(p_nxge_t nxgep, nxge_link_state_t *link_up)
6787 {
6788 nxge_status_t status = NXGE_OK;
6789 p_nxge_stats_t statsp;
6790 uint8_t phy_port_addr, portn;
6791 uint16_t val;
6792
6793 *link_up = LINK_NO_CHANGE;
6794
6795 portn = NXGE_GET_PORT_NUM(nxgep->function_num);
6796 phy_port_addr = nxgep->nxge_hw_p->xcvr_addr[portn];
6797 statsp = nxgep->statsp;
6798
6799 /* Check if link is up */
6800 if ((status = nxge_mdio_read(nxgep, phy_port_addr,
6801 TN1010_AUTONEG_DEV_ADDR, TN1010_AUTONEG_STATUS_REG, &val))
6802 != NXGE_OK) {
6803 goto fail;
6804 }
6805 /*
6806 * nxge_link_is_up has called nxge_set_tn1010_param and set
6807 * portmode and link_speed
6808 */
6809 if (val & TN1010_AN_LINK_STAT_BIT) {
6810 if ((nxgep->link_notify &&
6811 nxgep->nxge_mac_state == NXGE_MAC_STARTED) ||
6812 nxgep->statsp->mac_stats.link_up == 0) {
6813 statsp->mac_stats.link_up = 1;
6814 statsp->mac_stats.link_duplex = 2;
6815 *link_up = LINK_IS_UP;
6816 nxgep->link_notify = B_FALSE;
6817 }
6818 } else {
6819 if ((nxgep->link_notify && nxgep->link_check_count > 3 &&
6820 nxgep->nxge_mac_state == NXGE_MAC_STARTED) ||
6821 nxgep->statsp->mac_stats.link_up == 1) {
6822 statsp->mac_stats.link_up = 0;
6823 statsp->mac_stats.link_speed = 0;
6824 statsp->mac_stats.link_duplex = 0;
6825 *link_up = LINK_IS_DOWN;
6826 nxgep->link_notify = B_FALSE;
6827 }
6828 }
6829 return (NXGE_OK);
6830
6831 fail:
6832 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
6833 "nxge_tn1010_check: Unable to check TN1010"));
6834 return (status);
6835 }
6836
6837
6838 /* Set promiscous mode */
6839
6840 nxge_status_t
nxge_set_promisc(p_nxge_t nxgep,boolean_t on)6841 nxge_set_promisc(p_nxge_t nxgep, boolean_t on)
6842 {
6843 nxge_status_t status = NXGE_OK;
6844
6845 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_set_promisc: on %d", on));
6846
6847 nxgep->filter.all_phys_cnt = ((on) ? 1 : 0);
6848
6849 RW_ENTER_WRITER(&nxgep->filter_lock);
6850
6851 if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK) {
6852 goto fail;
6853 }
6854 if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK) {
6855 goto fail;
6856 }
6857
6858 RW_EXIT(&nxgep->filter_lock);
6859
6860 if (on)
6861 nxgep->statsp->mac_stats.promisc = B_TRUE;
6862 else
6863 nxgep->statsp->mac_stats.promisc = B_FALSE;
6864
6865 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_set_promisc"));
6866
6867 return (NXGE_OK);
6868 fail:
6869 RW_EXIT(&nxgep->filter_lock);
6870 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_set_promisc: "
6871 "Unable to set promisc (%d)", on));
6872
6873 return (status);
6874 }
6875
6876 /*ARGSUSED*/
6877 uint_t
nxge_mif_intr(void * arg1,void * arg2)6878 nxge_mif_intr(void *arg1, void *arg2)
6879 {
6880 #ifdef NXGE_DEBUG
6881 p_nxge_t nxgep = (p_nxge_t)arg2;
6882 #endif
6883 #if NXGE_MIF
6884 p_nxge_ldv_t ldvp = (p_nxge_ldv_t)arg1;
6885 uint32_t status;
6886 npi_handle_t handle;
6887 uint8_t portn;
6888 p_nxge_stats_t statsp;
6889 #endif
6890
6891 #ifdef NXGE_MIF
6892 if (arg2 == NULL || (void *)ldvp->nxgep != arg2) {
6893 nxgep = ldvp->nxgep;
6894 }
6895 nxgep = ldvp->nxgep;
6896 #endif
6897 NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_mif_intr"));
6898
6899 NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mif_intr"));
6900 return (DDI_INTR_CLAIMED);
6901
6902 mif_intr_fail:
6903 NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mif_intr"));
6904 return (DDI_INTR_UNCLAIMED);
6905 }
6906
6907 /*ARGSUSED*/
6908 uint_t
nxge_mac_intr(void * arg1,void * arg2)6909 nxge_mac_intr(void *arg1, void *arg2)
6910 {
6911 p_nxge_t nxgep = (p_nxge_t)arg2;
6912 p_nxge_ldv_t ldvp = (p_nxge_ldv_t)arg1;
6913 p_nxge_ldg_t ldgp;
6914 uint32_t status;
6915 npi_handle_t handle;
6916 uint8_t portn;
6917 p_nxge_stats_t statsp;
6918 npi_status_t rs = NPI_SUCCESS;
6919
6920 if (arg2 == NULL || (void *)ldvp->nxgep != arg2) {
6921 nxgep = ldvp->nxgep;
6922 }
6923
6924 ldgp = ldvp->ldgp;
6925 NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_mac_intr: "
6926 "group %d", ldgp->ldg));
6927
6928 handle = NXGE_DEV_NPI_HANDLE(nxgep);
6929 /*
6930 * This interrupt handler is for a specific
6931 * mac port.
6932 */
6933 statsp = (p_nxge_stats_t)nxgep->statsp;
6934 portn = nxgep->mac.portnum;
6935
6936 NXGE_DEBUG_MSG((nxgep, INT_CTL,
6937 "==> nxge_mac_intr: reading mac stats: port<%d>", portn));
6938
6939 if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
6940 rs = npi_xmac_tx_get_istatus(handle, portn,
6941 (xmac_tx_iconfig_t *)&status);
6942 if (rs != NPI_SUCCESS)
6943 goto npi_fail;
6944 if (status & ICFG_XMAC_TX_ALL) {
6945 if (status & ICFG_XMAC_TX_UNDERRUN) {
6946 statsp->xmac_stats.tx_underflow_err++;
6947 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
6948 NXGE_FM_EREPORT_TXMAC_UNDERFLOW);
6949 }
6950 if (status & ICFG_XMAC_TX_MAX_PACKET_ERR) {
6951 statsp->xmac_stats.tx_maxpktsize_err++;
6952 /*
6953 * Do not send FMA ereport because this
6954 * error does not indicate HW failure.
6955 */
6956 }
6957 if (status & ICFG_XMAC_TX_OVERFLOW) {
6958 statsp->xmac_stats.tx_overflow_err++;
6959 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
6960 NXGE_FM_EREPORT_TXMAC_OVERFLOW);
6961 }
6962 if (status & ICFG_XMAC_TX_FIFO_XFR_ERR) {
6963 statsp->xmac_stats.tx_fifo_xfr_err++;
6964 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
6965 NXGE_FM_EREPORT_TXMAC_TXFIFO_XFR_ERR);
6966 }
6967 if (status & ICFG_XMAC_TX_BYTE_CNT_EXP) {
6968 statsp->xmac_stats.tx_byte_cnt +=
6969 XTXMAC_BYTE_CNT_MASK;
6970 }
6971 if (status & ICFG_XMAC_TX_FRAME_CNT_EXP) {
6972 statsp->xmac_stats.tx_frame_cnt +=
6973 XTXMAC_FRM_CNT_MASK;
6974 }
6975 }
6976
6977 rs = npi_xmac_rx_get_istatus(handle, portn,
6978 (xmac_rx_iconfig_t *)&status);
6979 if (rs != NPI_SUCCESS)
6980 goto npi_fail;
6981 if (status & ICFG_XMAC_RX_ALL) {
6982 if (status & ICFG_XMAC_RX_OVERFLOW)
6983 statsp->xmac_stats.rx_overflow_err++;
6984 if (status & ICFG_XMAC_RX_UNDERFLOW) {
6985 statsp->xmac_stats.rx_underflow_err++;
6986 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
6987 NXGE_FM_EREPORT_RXMAC_UNDERFLOW);
6988 }
6989 /*
6990 * Do not send FMA ereport for the following 3 errors
6991 * because they do not indicate HW failures.
6992 */
6993 if (status & ICFG_XMAC_RX_CRC_ERR_CNT_EXP) {
6994 statsp->xmac_stats.rx_crc_err_cnt +=
6995 XRXMAC_CRC_ER_CNT_MASK;
6996 }
6997 if (status & ICFG_XMAC_RX_LEN_ERR_CNT_EXP) {
6998 statsp->xmac_stats.rx_len_err_cnt +=
6999 MAC_LEN_ER_CNT_MASK;
7000 }
7001 if (status & ICFG_XMAC_RX_VIOL_ERR_CNT_EXP) {
7002 statsp->xmac_stats.rx_viol_err_cnt +=
7003 XRXMAC_CD_VIO_CNT_MASK;
7004 }
7005 if (status & ICFG_XMAC_RX_OCT_CNT_EXP) {
7006 statsp->xmac_stats.rx_byte_cnt +=
7007 XRXMAC_BT_CNT_MASK;
7008 }
7009 if (status & ICFG_XMAC_RX_HST_CNT1_EXP) {
7010 statsp->xmac_stats.rx_hist1_cnt +=
7011 XRXMAC_HIST_CNT1_MASK;
7012 }
7013 if (status & ICFG_XMAC_RX_HST_CNT2_EXP) {
7014 statsp->xmac_stats.rx_hist2_cnt +=
7015 XRXMAC_HIST_CNT2_MASK;
7016 }
7017 if (status & ICFG_XMAC_RX_HST_CNT3_EXP) {
7018 statsp->xmac_stats.rx_hist3_cnt +=
7019 XRXMAC_HIST_CNT3_MASK;
7020 }
7021 if (status & ICFG_XMAC_RX_HST_CNT4_EXP) {
7022 statsp->xmac_stats.rx_hist4_cnt +=
7023 XRXMAC_HIST_CNT4_MASK;
7024 }
7025 if (status & ICFG_XMAC_RX_HST_CNT5_EXP) {
7026 statsp->xmac_stats.rx_hist5_cnt +=
7027 XRXMAC_HIST_CNT5_MASK;
7028 }
7029 if (status & ICFG_XMAC_RX_HST_CNT6_EXP) {
7030 statsp->xmac_stats.rx_hist6_cnt +=
7031 XRXMAC_HIST_CNT6_MASK;
7032 }
7033 if (status & ICFG_XMAC_RX_BCAST_CNT_EXP) {
7034 statsp->xmac_stats.rx_broadcast_cnt +=
7035 XRXMAC_BC_FRM_CNT_MASK;
7036 }
7037 if (status & ICFG_XMAC_RX_MCAST_CNT_EXP) {
7038 statsp->xmac_stats.rx_mult_cnt +=
7039 XRXMAC_MC_FRM_CNT_MASK;
7040 }
7041 /*
7042 * Do not send FMA ereport for the following 3 errors
7043 * because they do not indicate HW failures.
7044 */
7045 if (status & ICFG_XMAC_RX_FRAG_CNT_EXP) {
7046 statsp->xmac_stats.rx_frag_cnt +=
7047 XRXMAC_FRAG_CNT_MASK;
7048 }
7049 if (status & ICFG_XMAC_RX_ALIGNERR_CNT_EXP) {
7050 statsp->xmac_stats.rx_frame_align_err_cnt +=
7051 XRXMAC_AL_ER_CNT_MASK;
7052 }
7053 if (status & ICFG_XMAC_RX_LINK_FLT_CNT_EXP) {
7054 statsp->xmac_stats.rx_linkfault_err_cnt +=
7055 XMAC_LINK_FLT_CNT_MASK;
7056 }
7057 if (status & ICFG_XMAC_RX_REMOTE_FLT_DET) {
7058 statsp->xmac_stats.rx_remotefault_err++;
7059 }
7060 if (status & ICFG_XMAC_RX_LOCAL_FLT_DET) {
7061 statsp->xmac_stats.rx_localfault_err++;
7062 }
7063 }
7064
7065 rs = npi_xmac_ctl_get_istatus(handle, portn,
7066 (xmac_ctl_iconfig_t *)&status);
7067 if (rs != NPI_SUCCESS)
7068 goto npi_fail;
7069 if (status & ICFG_XMAC_CTRL_ALL) {
7070 if (status & ICFG_XMAC_CTRL_PAUSE_RCVD)
7071 statsp->xmac_stats.rx_pause_cnt++;
7072 if (status & ICFG_XMAC_CTRL_PAUSE_STATE)
7073 statsp->xmac_stats.tx_pause_state++;
7074 if (status & ICFG_XMAC_CTRL_NOPAUSE_STATE)
7075 statsp->xmac_stats.tx_nopause_state++;
7076 }
7077 } else if (nxgep->mac.porttype == PORT_TYPE_BMAC) {
7078 rs = npi_bmac_tx_get_istatus(handle, portn,
7079 (bmac_tx_iconfig_t *)&status);
7080 if (rs != NPI_SUCCESS)
7081 goto npi_fail;
7082 if (status & ICFG_BMAC_TX_ALL) {
7083 if (status & ICFG_BMAC_TX_UNDERFLOW) {
7084 statsp->bmac_stats.tx_underrun_err++;
7085 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
7086 NXGE_FM_EREPORT_TXMAC_UNDERFLOW);
7087 }
7088 if (status & ICFG_BMAC_TX_MAXPKTSZ_ERR) {
7089 statsp->bmac_stats.tx_max_pkt_err++;
7090 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
7091 NXGE_FM_EREPORT_TXMAC_MAX_PKT_ERR);
7092 }
7093 if (status & ICFG_BMAC_TX_BYTE_CNT_EXP) {
7094 statsp->bmac_stats.tx_byte_cnt +=
7095 BTXMAC_BYTE_CNT_MASK;
7096 }
7097 if (status & ICFG_BMAC_TX_FRAME_CNT_EXP) {
7098 statsp->bmac_stats.tx_frame_cnt +=
7099 BTXMAC_FRM_CNT_MASK;
7100 }
7101 }
7102
7103 rs = npi_bmac_rx_get_istatus(handle, portn,
7104 (bmac_rx_iconfig_t *)&status);
7105 if (rs != NPI_SUCCESS)
7106 goto npi_fail;
7107 if (status & ICFG_BMAC_RX_ALL) {
7108 if (status & ICFG_BMAC_RX_OVERFLOW) {
7109 statsp->bmac_stats.rx_overflow_err++;
7110 }
7111 if (status & ICFG_BMAC_RX_FRAME_CNT_EXP) {
7112 statsp->bmac_stats.rx_frame_cnt +=
7113 RXMAC_FRM_CNT_MASK;
7114 }
7115 if (status & ICFG_BMAC_RX_CRC_ERR_CNT_EXP) {
7116 statsp->bmac_stats.rx_crc_err_cnt +=
7117 BMAC_CRC_ER_CNT_MASK;
7118 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
7119 NXGE_FM_EREPORT_RXMAC_CRC_ERRCNT_EXP);
7120 }
7121 if (status & ICFG_BMAC_RX_LEN_ERR_CNT_EXP) {
7122 statsp->bmac_stats.rx_len_err_cnt +=
7123 MAC_LEN_ER_CNT_MASK;
7124 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
7125 NXGE_FM_EREPORT_RXMAC_LENGTH_ERRCNT_EXP);
7126 }
7127 if (status & ICFG_BMAC_RX_VIOL_ERR_CNT_EXP)
7128 statsp->bmac_stats.rx_viol_err_cnt +=
7129 BMAC_CD_VIO_CNT_MASK;
7130 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
7131 NXGE_FM_EREPORT_RXMAC_VIOL_ERRCNT_EXP);
7132 }
7133 if (status & ICFG_BMAC_RX_BYTE_CNT_EXP) {
7134 statsp->bmac_stats.rx_byte_cnt +=
7135 BRXMAC_BYTE_CNT_MASK;
7136 }
7137 if (status & ICFG_BMAC_RX_ALIGNERR_CNT_EXP) {
7138 statsp->bmac_stats.rx_align_err_cnt +=
7139 BMAC_AL_ER_CNT_MASK;
7140 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
7141 NXGE_FM_EREPORT_RXMAC_ALIGN_ECNT_EXP);
7142 }
7143
7144 rs = npi_bmac_ctl_get_istatus(handle, portn,
7145 (bmac_ctl_iconfig_t *)&status);
7146 if (rs != NPI_SUCCESS)
7147 goto npi_fail;
7148
7149 if (status & ICFG_BMAC_CTL_ALL) {
7150 if (status & ICFG_BMAC_CTL_RCVPAUSE)
7151 statsp->bmac_stats.rx_pause_cnt++;
7152 if (status & ICFG_BMAC_CTL_INPAUSE_ST)
7153 statsp->bmac_stats.tx_pause_state++;
7154 if (status & ICFG_BMAC_CTL_INNOTPAUSE_ST)
7155 statsp->bmac_stats.tx_nopause_state++;
7156 }
7157 }
7158
7159 if (ldgp->nldvs == 1) {
7160 (void) npi_intr_ldg_mgmt_set(handle, ldgp->ldg,
7161 B_TRUE, ldgp->ldg_timer);
7162 }
7163
7164 NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mac_intr"));
7165 return (DDI_INTR_CLAIMED);
7166
7167 npi_fail:
7168 NXGE_ERROR_MSG((nxgep, INT_CTL, "<== nxge_mac_intr"));
7169 return (DDI_INTR_UNCLAIMED);
7170 }
7171
7172 nxge_status_t
nxge_check_bcm8704_link(p_nxge_t nxgep,boolean_t * link_up)7173 nxge_check_bcm8704_link(p_nxge_t nxgep, boolean_t *link_up)
7174 {
7175 uint8_t phy_port_addr;
7176 nxge_status_t status = NXGE_OK;
7177 boolean_t rx_sig_ok;
7178 boolean_t pcs_blk_lock;
7179 boolean_t link_align;
7180 uint16_t val1, val2, val3;
7181 #ifdef NXGE_DEBUG_SYMBOL_ERR
7182 uint16_t val_debug;
7183 uint32_t val;
7184 #endif
7185
7186 phy_port_addr = nxgep->statsp->mac_stats.xcvr_portn;
7187
7188 #ifdef NXGE_DEBUG_SYMBOL_ERR
7189 /* Check Device 3 Register Device 3 0xC809 */
7190 (void) nxge_mdio_read(nxgep, phy_port_addr, 0x3, 0xC809, &val_debug);
7191 if ((val_debug & ~0x200) != 0) {
7192 cmn_err(CE_NOTE, "!Port%d BCM8704 Dev3 Reg 0xc809 = 0x%x\n",
7193 nxgep->mac.portnum, val_debug);
7194 (void) nxge_mdio_read(nxgep, phy_port_addr, 0x4, 0x18,
7195 &val_debug);
7196 cmn_err(CE_NOTE, "!Port%d BCM8704 Dev4 Reg 0x18 = 0x%x\n",
7197 nxgep->mac.portnum, val_debug);
7198 }
7199
7200 (void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
7201 XPCS_REG_DESCWERR_COUNTER, &val);
7202 if (val != 0)
7203 cmn_err(CE_NOTE, "!XPCS DESCWERR = 0x%x\n", val);
7204
7205 (void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
7206 XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val);
7207 if (val != 0)
7208 cmn_err(CE_NOTE, "!XPCS SYMBOL_ERR_L0_1 = 0x%x\n", val);
7209
7210 (void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
7211 XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val);
7212 if (val != 0)
7213 cmn_err(CE_NOTE, "!XPCS SYMBOL_ERR_L2_3 = 0x%x\n", val);
7214 #endif
7215
7216 /* Check from BCM8704 if 10G link is up or down */
7217
7218 /* Check Device 1 Register 0xA bit0 */
7219 status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_PMA_PMD_DEV_ADDR,
7220 BCM8704_PMD_RECEIVE_SIG_DETECT, &val1);
7221 if (status != NXGE_OK)
7222 goto fail;
7223 rx_sig_ok = ((val1 & GLOB_PMD_RX_SIG_OK) ? B_TRUE : B_FALSE);
7224
7225 /* Check Device 3 Register 0x20 bit0 */
7226 if ((status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_PCS_DEV_ADDR,
7227 BCM8704_10GBASE_R_PCS_STATUS_REG, &val2)) != NPI_SUCCESS)
7228 goto fail;
7229 pcs_blk_lock = ((val2 & PCS_10GBASE_R_PCS_BLK_LOCK) ? B_TRUE : B_FALSE);
7230
7231 /* Check Device 4 Register 0x18 bit12 */
7232 status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR,
7233 BCM8704_PHYXS_XGXS_LANE_STATUS_REG, &val3);
7234 if (status != NXGE_OK)
7235 goto fail;
7236
7237 switch (nxgep->chip_id) {
7238 case BCM8704_CHIP_ID:
7239 link_align = (val3 == (XGXS_LANE_ALIGN_STATUS |
7240 XGXS_LANE3_SYNC | XGXS_LANE2_SYNC | XGXS_LANE1_SYNC |
7241 XGXS_LANE0_SYNC | 0x400)) ? B_TRUE : B_FALSE;
7242 break;
7243 case BCM8706_CHIP_ID:
7244 link_align = ((val3 & XGXS_LANE_ALIGN_STATUS) &&
7245 (val3 & XGXS_LANE3_SYNC) && (val3 & XGXS_LANE2_SYNC) &&
7246 (val3 & XGXS_LANE1_SYNC) && (val3 & XGXS_LANE0_SYNC)) ?
7247 B_TRUE : B_FALSE;
7248 break;
7249 default:
7250 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_check_bcm8704_link:"
7251 "Unknown chip ID [0x%x]", nxgep->chip_id));
7252 goto fail;
7253 }
7254
7255 #ifdef NXGE_DEBUG_ALIGN_ERR
7256 /* Temp workaround for link down issue */
7257 if (pcs_blk_lock == B_FALSE) {
7258 if (val2 != 0x4) {
7259 pcs_blk_lock = B_TRUE;
7260 cmn_err(CE_NOTE, "!LINK DEBUG: port%d PHY Dev3 "
7261 "Reg 0x20 = 0x%x\n", nxgep->mac.portnum, val2);
7262 }
7263 }
7264
7265 if (link_align == B_FALSE) {
7266 if (val3 != 0x140f) {
7267 link_align = B_TRUE;
7268 cmn_err(CE_NOTE, "!LINK DEBUG: port%d PHY Dev4 "
7269 "Reg 0x18 = 0x%x\n", nxgep->mac.portnum, val3);
7270 }
7271 }
7272
7273 if (rx_sig_ok == B_FALSE) {
7274 if ((val2 == 0) || (val3 == 0)) {
7275 rx_sig_ok = B_TRUE;
7276 cmn_err(CE_NOTE,
7277 "!LINK DEBUG: port %d Dev3 or Dev4 read zero\n",
7278 nxgep->mac.portnum);
7279 }
7280 }
7281 #endif
7282
7283 *link_up = ((rx_sig_ok == B_TRUE) && (pcs_blk_lock == B_TRUE) &&
7284 (link_align == B_TRUE)) ? B_TRUE : B_FALSE;
7285
7286 return (NXGE_OK);
7287 fail:
7288 return (status);
7289 }
7290
7291 static nxge_status_t
nxge_check_mrvl88x2011_link(p_nxge_t nxgep,boolean_t * link_up)7292 nxge_check_mrvl88x2011_link(p_nxge_t nxgep, boolean_t *link_up)
7293 {
7294 uint8_t phy;
7295 nxge_status_t status = NXGE_OK;
7296 boolean_t pma_status;
7297 boolean_t pcs_status;
7298 boolean_t xgxs_status;
7299 uint16_t val;
7300
7301 phy = nxgep->statsp->mac_stats.xcvr_portn;
7302
7303 MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV1_ADDR,
7304 MRVL_88X2011_10G_PMD_STAT_2, &val);
7305
7306 *link_up = B_FALSE;
7307
7308 /* Check from Marvell 88X2011 if 10G link is up or down */
7309
7310 /* Check PMA/PMD Register: 1.0001.2 == 1 */
7311 MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV1_ADDR,
7312 MRVL_88X2011_PMA_PMD_STAT_1, &val);
7313
7314 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
7315 "nxge_check_mrvl88x2011_link: pmd=0x%x", val));
7316
7317 pma_status = ((val & MRVL_88X2011_LNK_STATUS_OK) ? B_TRUE : B_FALSE);
7318
7319 /* Check PMC Register : 3.0001.2 == 1: read twice */
7320 MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV3_ADDR,
7321 MRVL_88X2011_PMA_PMD_STAT_1, &val);
7322 MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV3_ADDR,
7323 MRVL_88X2011_PMA_PMD_STAT_1, &val);
7324
7325 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
7326 "nxge_check_mrvl88x2011_link: pcs=0x%x", val));
7327
7328 pcs_status = ((val & MRVL_88X2011_LNK_STATUS_OK) ? B_TRUE : B_FALSE);
7329
7330 /* Check XGXS Register : 4.0018.[0-3,12] */
7331 MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV4_ADDR,
7332 MRVL_88X2011_10G_XGXS_LANE_STAT, &val);
7333
7334 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
7335 "nxge_check_mrvl88x2011_link: xgxs=0x%x", val));
7336
7337 xgxs_status = (val == (XGXS_LANE_ALIGN_STATUS | XGXS_LANE3_SYNC |
7338 XGXS_LANE2_SYNC | XGXS_LANE1_SYNC |
7339 XGXS_LANE0_SYNC | XGXS_PATTERN_TEST_ABILITY |
7340 XGXS_LANE_STAT_MAGIC)) ? B_TRUE : B_FALSE;
7341
7342 *link_up = (pma_status && pcs_status && xgxs_status) ?
7343 B_TRUE : B_FALSE;
7344
7345 fail:
7346
7347 if (*link_up == B_FALSE) {
7348 /* PCS OFF */
7349 nxge_mrvl88x2011_led(nxgep, MRVL_88X2011_LED_CTL_OFF);
7350 } else {
7351 /* PCS Activity */
7352 nxge_mrvl88x2011_led(nxgep, MRVL_88X2011_LED_CTL_PCS_ACT);
7353 }
7354
7355 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
7356 " <== nxge_check_mrvl88x2011_link: up=%d", *link_up));
7357
7358 return (status);
7359 }
7360
7361 static nxge_status_t
nxge_check_nlp2020_link(p_nxge_t nxgep,boolean_t * link_up)7362 nxge_check_nlp2020_link(p_nxge_t nxgep, boolean_t *link_up)
7363 {
7364 uint8_t phy;
7365 nxge_status_t status = NXGE_OK;
7366 uint16_t pmd_rx_sig, pcs_10gbr_stat1, phy_xs_ln_stat;
7367 uint8_t connector = 0;
7368
7369 phy = nxgep->statsp->mac_stats.xcvr_portn;
7370 *link_up = B_FALSE;
7371
7372 /* Check from Netlogic AEL2020 if 10G link is up or down */
7373
7374 status = nxge_mdio_read(nxgep, phy, NLP2020_PMA_PMD_ADDR,
7375 NLP2020_PMA_PMD_RX_SIG_DET_REG, &pmd_rx_sig);
7376 if (status != NXGE_OK)
7377 goto fail;
7378
7379 status = nxge_mdio_read(nxgep, phy, NLP2020_PHY_PCS_ADDR,
7380 NLP2020_PHY_PCS_10GBR_STAT1_REG, &pcs_10gbr_stat1);
7381 if (status != NXGE_OK)
7382 goto fail;
7383
7384 status = nxge_mdio_read(nxgep, phy, NLP2020_PHY_XS_ADDR,
7385 NLP2020_PHY_XS_LN_ST_REG, &phy_xs_ln_stat);
7386 if (status != NXGE_OK)
7387 goto fail;
7388
7389 if ((pmd_rx_sig & NLP2020_PMA_PMD_RX_SIG_ON) &&
7390 (pcs_10gbr_stat1 & NLP2020_PHY_PCS_10GBR_RX_LINK_UP) &&
7391 (phy_xs_ln_stat & NLP2020_PHY_XS_LN_ALIGN_SYNC))
7392 *link_up = B_TRUE;
7393 /*
7394 * If previously link was down, check the connector type as
7395 * it might have been changed.
7396 */
7397 if (nxgep->statsp->mac_stats.link_up == 0) {
7398 (void) nxge_nlp2020_i2c_read(nxgep, phy,
7399 NLP2020_XCVR_I2C_ADDR, QSFP_MSA_CONN_REG, &connector);
7400
7401 switch (connector) {
7402 case SFPP_FIBER:
7403 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
7404 "nxge_check_nlp2020_link: SFPP_FIBER"));
7405 if (nxgep->mac.portmode != PORT_10G_FIBER) {
7406 nxgep->mac.portmode = PORT_10G_FIBER;
7407 (void) nxge_nlp2020_xcvr_init(nxgep);
7408 }
7409 break;
7410 case QSFP_FIBER:
7411 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
7412 "nxge_check_nlp2020_link: QSFP_FIBER"));
7413 if (nxgep->mac.portmode != PORT_10G_FIBER) {
7414 nxgep->mac.portmode = PORT_10G_FIBER;
7415 (void) nxge_nlp2020_xcvr_init(nxgep);
7416 }
7417 break;
7418 case QSFP_COPPER_TWINAX:
7419 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
7420 "nxge_check_nlp2020_link: "
7421 "QSFP_COPPER_TWINAX/"
7422 "SFPP_COPPER_TWINAX"));
7423 if (nxgep->mac.portmode != PORT_10G_COPPER) {
7424 nxgep->mac.portmode = PORT_10G_COPPER;
7425 (void) nxge_nlp2020_xcvr_init(nxgep);
7426 } else {
7427 uint8_t len = 0;
7428 (void) nxge_nlp2020_i2c_read(nxgep, phy,
7429 NLP2020_XCVR_I2C_ADDR, QSFP_MSA_LEN_REG,
7430 &len);
7431 if (((len < 7) &&
7432 (nxgep->nlp_conn ==
7433 NXGE_NLP_CONN_COPPER_7M_ABOVE)) ||
7434 ((len >= 7) &&
7435 (nxgep->nlp_conn ==
7436 NXGE_NLP_CONN_COPPER_LT_7M))) {
7437 (void) nxge_nlp2020_xcvr_init(nxgep);
7438 }
7439 }
7440 break;
7441 default:
7442 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
7443 "nxge_check_nlp2020_link: Unknown type [0x%x] "
7444 "detected...setting to QSFP_FIBER",
7445 connector));
7446 if (nxgep->mac.portmode != PORT_10G_FIBER) {
7447 nxgep->mac.portmode = PORT_10G_FIBER;
7448 (void) nxge_nlp2020_xcvr_init(nxgep);
7449 }
7450 break;
7451 }
7452 }
7453 fail:
7454 if (*link_up == B_FALSE && nxgep->statsp->mac_stats.link_up == 1) {
7455 /* Turn link LED OFF */
7456 (void) nxge_mdio_write(nxgep, phy,
7457 NLP2020_GPIO_ADDR, NLP2020_GPIO_CTL_REG, 0xb000);
7458 (void) nxge_mdio_write(nxgep, phy,
7459 NLP2020_GPIO_ADDR, NLP2020_GPIO_PT3_CFG_REG, 0x0);
7460 } else if (*link_up == B_TRUE &&
7461 nxgep->statsp->mac_stats.link_up == 0) {
7462 /* Turn link LED ON */
7463 (void) nxge_mdio_write(nxgep, phy,
7464 NLP2020_GPIO_ADDR, NLP2020_GPIO_CTL_REG, 0xd000);
7465 (void) nxge_mdio_write(nxgep, phy,
7466 NLP2020_GPIO_ADDR, NLP2020_GPIO_PT3_CFG_REG, 0xfbff);
7467 (void) nxge_mdio_write(nxgep, phy,
7468 NLP2020_GPIO_ADDR, 0xff2a, 0x004a);
7469 }
7470
7471 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
7472 " <== nxge_check_nlp2020_link: up=%d", *link_up));
7473 return (status);
7474 }
7475
7476
7477 nxge_status_t
nxge_10g_link_led_on(p_nxge_t nxgep)7478 nxge_10g_link_led_on(p_nxge_t nxgep)
7479 {
7480 if (npi_xmac_xif_led(nxgep->npi_handle, nxgep->mac.portnum, B_TRUE)
7481 != NPI_SUCCESS)
7482 return (NXGE_ERROR);
7483 else
7484 return (NXGE_OK);
7485 }
7486
7487 nxge_status_t
nxge_10g_link_led_off(p_nxge_t nxgep)7488 nxge_10g_link_led_off(p_nxge_t nxgep)
7489 {
7490 if (npi_xmac_xif_led(nxgep->npi_handle, nxgep->mac.portnum, B_FALSE)
7491 != NPI_SUCCESS)
7492 return (NXGE_ERROR);
7493 else
7494 return (NXGE_OK);
7495 }
7496
7497 static boolean_t
nxge_hswap_phy_present(p_nxge_t nxgep,uint8_t portn)7498 nxge_hswap_phy_present(p_nxge_t nxgep, uint8_t portn)
7499 {
7500 /*
7501 * check for BCM PHY (GOA NEM)
7502 */
7503 /*
7504 * If this is the 2nd NIU port, then check 2 addresses
7505 * to take care of the Goa NEM card. Port 1 can have addr 17
7506 * (in the eval board) or 20 (in the P0 board).
7507 */
7508 if (portn == 1) {
7509 if (nxge_is_phy_present(nxgep, ALT_GOA_CLAUSE45_PORT1_ADDR,
7510 BCM8706_DEV_ID, BCM_PHY_ID_MASK)) {
7511 nxgep->xcvr_addr = ALT_GOA_CLAUSE45_PORT1_ADDR;
7512 goto found_phy;
7513 }
7514 }
7515 if (nxge_is_phy_present(nxgep, GOA_CLAUSE45_PORT_ADDR_BASE + portn,
7516 BCM8706_DEV_ID, BCM_PHY_ID_MASK)) {
7517 nxgep->xcvr_addr = GOA_CLAUSE45_PORT_ADDR_BASE + portn;
7518 goto found_phy;
7519 }
7520
7521 /*
7522 * check for NLP2020 PHY on C4 NEM
7523 */
7524 switch (portn) {
7525 case 0:
7526 if (nxge_is_phy_present(nxgep, NLP2020_CL45_PORT0_ADDR0,
7527 NLP2020_DEV_ID, NLP2020_DEV_ID_MASK)) {
7528 nxgep->xcvr_addr = NLP2020_CL45_PORT0_ADDR0;
7529 goto found_phy;
7530 } else if (nxge_is_phy_present(nxgep, NLP2020_CL45_PORT0_ADDR1,
7531 NLP2020_DEV_ID, NLP2020_DEV_ID_MASK)) {
7532 nxgep->xcvr_addr = NLP2020_CL45_PORT0_ADDR1;
7533 goto found_phy;
7534 } else if (nxge_is_phy_present(nxgep, NLP2020_CL45_PORT0_ADDR2,
7535 NLP2020_DEV_ID, NLP2020_DEV_ID_MASK)) {
7536 nxgep->xcvr_addr = NLP2020_CL45_PORT0_ADDR2;
7537 goto found_phy;
7538 } else if (nxge_is_phy_present(nxgep, NLP2020_CL45_PORT0_ADDR3,
7539 NLP2020_DEV_ID, NLP2020_DEV_ID_MASK)) {
7540 nxgep->xcvr_addr = NLP2020_CL45_PORT0_ADDR3;
7541 goto found_phy;
7542 }
7543 break;
7544
7545 case 1:
7546 if (nxge_is_phy_present(nxgep, NLP2020_CL45_PORT1_ADDR0,
7547 NLP2020_DEV_ID, NLP2020_DEV_ID_MASK)) {
7548 nxgep->xcvr_addr = NLP2020_CL45_PORT1_ADDR0;
7549 goto found_phy;
7550 } else if (nxge_is_phy_present(nxgep, NLP2020_CL45_PORT1_ADDR1,
7551 NLP2020_DEV_ID, NLP2020_DEV_ID_MASK)) {
7552 nxgep->xcvr_addr = NLP2020_CL45_PORT1_ADDR1;
7553 goto found_phy;
7554 } else if (nxge_is_phy_present(nxgep, NLP2020_CL45_PORT1_ADDR2,
7555 NLP2020_DEV_ID, NLP2020_DEV_ID_MASK)) {
7556 nxgep->xcvr_addr = NLP2020_CL45_PORT1_ADDR2;
7557 goto found_phy;
7558 } else if (nxge_is_phy_present(nxgep, NLP2020_CL45_PORT1_ADDR3,
7559 NLP2020_DEV_ID, NLP2020_DEV_ID_MASK)) {
7560 nxgep->xcvr_addr = NLP2020_CL45_PORT1_ADDR3;
7561 goto found_phy;
7562 }
7563 break;
7564 default:
7565 break;
7566 }
7567
7568 return (B_FALSE);
7569 found_phy:
7570 return (B_TRUE);
7571
7572 }
7573
7574 static boolean_t
nxge_is_phy_present(p_nxge_t nxgep,int addr,uint32_t id,uint32_t mask)7575 nxge_is_phy_present(p_nxge_t nxgep, int addr, uint32_t id, uint32_t mask)
7576 {
7577 uint32_t pma_pmd_id = 0;
7578 uint32_t pcs_id = 0;
7579 uint32_t phy_id = 0;
7580
7581 pma_pmd_id = nxge_get_cl45_pma_pmd_id(nxgep, addr);
7582 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
7583 "nxge_is_phy_present: pma_pmd_id[0x%x]", pma_pmd_id));
7584 if ((pma_pmd_id & mask) == (id & mask))
7585 goto found_phy;
7586 pcs_id = nxge_get_cl45_pcs_id(nxgep, addr);
7587 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
7588 "nxge_is_phy_present: pcs_id[0x%x]", pcs_id));
7589 if ((pcs_id & mask) == (id & mask))
7590 goto found_phy;
7591 phy_id = nxge_get_cl22_phy_id(nxgep, addr);
7592 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
7593 "nxge_is_phy_present: phy_id[0x%x]", phy_id));
7594 if ((phy_id & mask) == (id & mask))
7595 goto found_phy;
7596
7597 return (B_FALSE);
7598
7599 found_phy:
7600 return (B_TRUE);
7601 }
7602
7603 /* Check if the given id read using the given MDIO Clause is supported */
7604
7605 static boolean_t
nxge_is_supported_phy(uint32_t id,uint8_t type)7606 nxge_is_supported_phy(uint32_t id, uint8_t type)
7607 {
7608 int i;
7609 boolean_t found = B_FALSE;
7610
7611 switch (type) {
7612 case CLAUSE_45_TYPE:
7613 for (i = 0; i < NUM_CLAUSE_45_IDS; i++) {
7614 if (((nxge_supported_cl45_ids[i] & BCM_PHY_ID_MASK) ==
7615 (id & BCM_PHY_ID_MASK)) ||
7616 (TN1010_DEV_ID == (id & TN1010_DEV_ID_MASK)) ||
7617 (NLP2020_DEV_ID == (id & NLP2020_DEV_ID_MASK))) {
7618 found = B_TRUE;
7619 break;
7620 }
7621 }
7622 break;
7623 case CLAUSE_22_TYPE:
7624 for (i = 0; i < NUM_CLAUSE_22_IDS; i++) {
7625 if ((nxge_supported_cl22_ids[i] & BCM_PHY_ID_MASK) ==
7626 (id & BCM_PHY_ID_MASK)) {
7627 found = B_TRUE;
7628 break;
7629 }
7630 }
7631 break;
7632 default:
7633 break;
7634 }
7635
7636 return (found);
7637 }
7638
7639 static uint32_t
nxge_get_cl45_pma_pmd_id(p_nxge_t nxgep,int phy_port)7640 nxge_get_cl45_pma_pmd_id(p_nxge_t nxgep, int phy_port)
7641 {
7642 uint16_t val1 = 0;
7643 uint16_t val2 = 0;
7644 uint32_t pma_pmd_dev_id = 0;
7645 npi_handle_t handle = NXGE_DEV_NPI_HANDLE(nxgep);
7646
7647 MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock);
7648 (void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PMA_PMD_DEV_ADDR,
7649 NXGE_DEV_ID_REG_1, &val1);
7650 (void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PMA_PMD_DEV_ADDR,
7651 NXGE_DEV_ID_REG_2, &val2);
7652 MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
7653
7654 /* Concatenate the Device ID stored in two registers. */
7655 pma_pmd_dev_id = val1;
7656 pma_pmd_dev_id = (pma_pmd_dev_id << 16);
7657 pma_pmd_dev_id |= val2;
7658
7659 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PMA/PMD "
7660 "devid[0x%llx]", phy_port, pma_pmd_dev_id));
7661
7662 return (pma_pmd_dev_id);
7663 }
7664
7665 static uint32_t
nxge_get_cl45_pcs_id(p_nxge_t nxgep,int phy_port)7666 nxge_get_cl45_pcs_id(p_nxge_t nxgep, int phy_port)
7667 {
7668 uint16_t val1 = 0;
7669 uint16_t val2 = 0;
7670 uint32_t pcs_dev_id = 0;
7671 npi_handle_t handle = NXGE_DEV_NPI_HANDLE(nxgep);
7672
7673 MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock);
7674 (void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PCS_DEV_ADDR,
7675 NXGE_DEV_ID_REG_1, &val1);
7676 (void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PCS_DEV_ADDR,
7677 NXGE_DEV_ID_REG_2, &val2);
7678 MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
7679
7680 pcs_dev_id = val1;
7681 pcs_dev_id = (pcs_dev_id << 16);
7682 pcs_dev_id |= val2;
7683
7684 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PCS "
7685 "devid[0x%llx]", phy_port, pcs_dev_id));
7686
7687 return (pcs_dev_id);
7688 }
7689
7690 static uint32_t
nxge_get_cl22_phy_id(p_nxge_t nxgep,int phy_port)7691 nxge_get_cl22_phy_id(p_nxge_t nxgep, int phy_port)
7692 {
7693 uint16_t val1 = 0;
7694 uint16_t val2 = 0;
7695 uint32_t phy_id = 0;
7696 npi_handle_t handle = NXGE_DEV_NPI_HANDLE(nxgep);
7697 npi_status_t npi_status = NPI_SUCCESS;
7698
7699 MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock);
7700 npi_status = npi_mac_mif_mii_read(handle, phy_port, NXGE_PHY_ID_REG_1,
7701 &val1);
7702 if (npi_status != NPI_SUCCESS) {
7703 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] "
7704 "clause 22 read to reg 2 failed!!!"));
7705 goto exit;
7706 }
7707 npi_status = npi_mac_mif_mii_read(handle, phy_port, NXGE_PHY_ID_REG_2,
7708 &val2);
7709 if (npi_status != 0) {
7710 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] "
7711 "clause 22 read to reg 3 failed!!!"));
7712 goto exit;
7713 }
7714 phy_id = val1;
7715 phy_id = (phy_id << 16);
7716 phy_id |= val2;
7717
7718 exit:
7719 MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
7720 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PHY ID [0x%llx]",
7721 phy_port, phy_id));
7722
7723 return (phy_id);
7724 }
7725
7726 /*
7727 * Scan the PHY ports 0 through 31 to get the PHY ID using Clause 22 MDIO
7728 * read and the PMA/PMD device ID and the PCS device ID using Clause 45 MDIO
7729 * read. Then use the values obtained to determine the phy type of each port
7730 * and the Neptune type.
7731 *
7732 * This function sets hw_p->xcvr_addr[i] for future MDIO access and set
7733 * hw_p->niu_type for each nxge instance to figure out nxgep->mac.portmode
7734 * in case the portmode information is not available via OBP, nxge.conf,
7735 * VPD or SEEPROM.
7736 */
7737 nxge_status_t
nxge_scan_ports_phy(p_nxge_t nxgep,p_nxge_hw_list_t hw_p)7738 nxge_scan_ports_phy(p_nxge_t nxgep, p_nxge_hw_list_t hw_p)
7739 {
7740 int i, j, l;
7741 uint32_t pma_pmd_dev_id = 0;
7742 uint32_t pcs_dev_id = 0;
7743 uint32_t phy_id = 0;
7744 uint32_t port_pma_pmd_dev_id[NXGE_PORTS_NEPTUNE];
7745 uint32_t port_pcs_dev_id[NXGE_PORTS_NEPTUNE];
7746 uint32_t port_phy_id[NXGE_PORTS_NEPTUNE];
7747 uint8_t pma_pmd_dev_fd[NXGE_MAX_PHY_PORTS];
7748 uint8_t pcs_dev_fd[NXGE_MAX_PHY_PORTS];
7749 uint8_t phy_fd_arr[NXGE_MAX_PHY_PORTS];
7750 uint8_t port_fd_arr[NXGE_MAX_PHY_PORTS];
7751 uint8_t total_port_fd, total_phy_fd;
7752 uint8_t num_xaui;
7753 nxge_status_t status = NXGE_OK;
7754
7755 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_scan_ports_phy: "));
7756 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
7757 "==> nxge_scan_ports_phy: nxge niu_type[0x%x]",
7758 nxgep->niu_type));
7759
7760 if (isLDOMguest(nxgep)) {
7761 hw_p->niu_type = NIU_TYPE_NONE;
7762 hw_p->platform_type = P_NEPTUNE_NONE;
7763 return (NXGE_OK);
7764 }
7765
7766 j = l = 0;
7767 total_port_fd = total_phy_fd = 0;
7768 /*
7769 * Clause 45 and Clause 22 port/phy addresses 0 through 5 are reserved
7770 * for on chip serdes usages. "i" in the following for loop starts at 6.
7771 */
7772 for (i = NXGE_EXT_PHY_PORT_ST; i < NXGE_MAX_PHY_PORTS; i++) {
7773
7774 pma_pmd_dev_id = nxge_get_cl45_pma_pmd_id(nxgep, i);
7775
7776 if (nxge_is_supported_phy(pma_pmd_dev_id, CLAUSE_45_TYPE)) {
7777 pma_pmd_dev_fd[i] = 1;
7778 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] "
7779 "PMA/PMD dev %x found", i, pma_pmd_dev_id));
7780 if (j < NXGE_PORTS_NEPTUNE) {
7781 if ((pma_pmd_dev_id & TN1010_DEV_ID_MASK)
7782 == TN1010_DEV_ID) {
7783 port_pma_pmd_dev_id[j] = TN1010_DEV_ID;
7784 } else if ((pma_pmd_dev_id &
7785 NLP2020_DEV_ID_MASK) == NLP2020_DEV_ID) {
7786 port_pma_pmd_dev_id[j] =
7787 NLP2020_DEV_ID;
7788 } else {
7789 port_pma_pmd_dev_id[j] =
7790 pma_pmd_dev_id & BCM_PHY_ID_MASK;
7791 }
7792 port_fd_arr[j] = (uint8_t)i;
7793 j++;
7794 }
7795 } else {
7796 pma_pmd_dev_fd[i] = 0;
7797 }
7798
7799 pcs_dev_id = nxge_get_cl45_pcs_id(nxgep, i);
7800
7801 if (nxge_is_supported_phy(pcs_dev_id, CLAUSE_45_TYPE)) {
7802 pcs_dev_fd[i] = 1;
7803 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PCS "
7804 "dev %x found", i, pcs_dev_id));
7805 if (pma_pmd_dev_fd[i] == 1) {
7806 if ((pcs_dev_id & TN1010_DEV_ID_MASK)
7807 == TN1010_DEV_ID) {
7808 port_pcs_dev_id[j - 1] =
7809 TN1010_DEV_ID;
7810 } else if ((pcs_dev_id & NLP2020_DEV_ID_MASK)
7811 == NLP2020_DEV_ID) {
7812 port_pcs_dev_id[j - 1] =
7813 NLP2020_DEV_ID;
7814 } else {
7815 port_pcs_dev_id[j - 1] =
7816 pcs_dev_id &
7817 BCM_PHY_ID_MASK;
7818 }
7819 } else {
7820 if (j < NXGE_PORTS_NEPTUNE) {
7821 if ((pcs_dev_id & TN1010_DEV_ID_MASK)
7822 == TN1010_DEV_ID) {
7823 port_pcs_dev_id[j] =
7824 TN1010_DEV_ID;
7825 } else if ((pcs_dev_id &
7826 NLP2020_DEV_ID_MASK)
7827 == NLP2020_DEV_ID) {
7828 port_pcs_dev_id[j] =
7829 NLP2020_DEV_ID;
7830 } else {
7831 port_pcs_dev_id[j] =
7832 pcs_dev_id &
7833 BCM_PHY_ID_MASK;
7834 }
7835 port_fd_arr[j] = (uint8_t)i;
7836 j++;
7837 }
7838 }
7839 } else {
7840 pcs_dev_fd[i] = 0;
7841 }
7842
7843 if (pcs_dev_fd[i] || pma_pmd_dev_fd[i]) {
7844 total_port_fd ++;
7845 }
7846
7847 phy_id = nxge_get_cl22_phy_id(nxgep, i);
7848 if (nxge_is_supported_phy(phy_id, CLAUSE_22_TYPE)) {
7849 total_phy_fd ++;
7850 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PHY ID"
7851 "%x found", i, phy_id));
7852 if (l < NXGE_PORTS_NEPTUNE) {
7853 if ((phy_id & TN1010_DEV_ID_MASK)
7854 == TN1010_DEV_ID) {
7855 port_phy_id[l] = TN1010_DEV_ID;
7856 } else {
7857 port_phy_id[l]
7858 = phy_id & BCM_PHY_ID_MASK;
7859 }
7860 phy_fd_arr[l] = (uint8_t)i;
7861 l++;
7862 }
7863 }
7864 }
7865
7866 switch (total_port_fd) {
7867 case 2:
7868 switch (total_phy_fd) {
7869 case 2:
7870 /* 2 10G, 2 1G RGMII Fiber / copper */
7871 if ((((port_pcs_dev_id[0] == PHY_BCM8704_FAMILY) &&
7872 (port_pcs_dev_id[1] == PHY_BCM8704_FAMILY)) ||
7873 ((port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY) &&
7874 (port_pma_pmd_dev_id[1] == PHY_BCM8704_FAMILY))) &&
7875 ((port_phy_id[0] == PHY_BCM5482_FAMILY) &&
7876 (port_phy_id[1] == PHY_BCM5482_FAMILY))) {
7877
7878 switch (hw_p->platform_type) {
7879 case P_NEPTUNE_ROCK:
7880 hw_p->niu_type = NEPTUNE_2_10GF_2_1GC;
7881 /*
7882 * ROCK platform has assigned a lower
7883 * addr to port 1. (port 0 = 0x9 and
7884 * port 1 = 0x8).
7885 */
7886 hw_p->xcvr_addr[1] = port_fd_arr[0];
7887 hw_p->xcvr_addr[0] = port_fd_arr[1];
7888
7889 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
7890 "Rock with 2 10G, 2 1GC"));
7891 break;
7892
7893 case P_NEPTUNE_NONE:
7894 default:
7895 hw_p->platform_type =
7896 P_NEPTUNE_GENERIC;
7897 hw_p->niu_type = NEPTUNE_2_10GF_2_1GRF;
7898
7899 hw_p->xcvr_addr[0] = port_fd_arr[0];
7900 hw_p->xcvr_addr[1] = port_fd_arr[1];
7901
7902 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
7903 "ARTM card with 2 10G, 2 1GF"));
7904 break;
7905 }
7906
7907 hw_p->xcvr_addr[2] = phy_fd_arr[0];
7908 hw_p->xcvr_addr[3] = phy_fd_arr[1];
7909
7910 } else {
7911 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
7912 "Unsupported neptune type 1"));
7913 goto error_exit;
7914 }
7915 break;
7916
7917 case 1:
7918 /* TODO - 2 10G, 1 1G */
7919 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
7920 "Unsupported neptune type 2 10G, 1 1G"));
7921 goto error_exit;
7922 case 0:
7923 /*
7924 * 2 10G: 2XGF NIC, Marvell, Goa, Huron with 2 XAUI
7925 * cards, etc.
7926 */
7927 if (((port_pcs_dev_id[0] == PHY_BCM8704_FAMILY) &&
7928 (port_pcs_dev_id[1] == PHY_BCM8704_FAMILY)) ||
7929 ((port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY) &&
7930 (port_pma_pmd_dev_id[1] == PHY_BCM8704_FAMILY)) ||
7931 ((port_pcs_dev_id[0] == MARVELL_88X201X_PHY_ID) &&
7932 (port_pcs_dev_id[1] == MARVELL_88X201X_PHY_ID)) ||
7933 ((port_pma_pmd_dev_id[0] ==
7934 MARVELL_88X201X_PHY_ID) &&
7935 (port_pma_pmd_dev_id[1] ==
7936 MARVELL_88X201X_PHY_ID))) {
7937
7938 /*
7939 * Check the first phy port address against
7940 * the known phy start addresses to determine
7941 * the platform type.
7942 */
7943
7944 switch (port_fd_arr[0]) {
7945 case NEPTUNE_CLAUSE45_PORT_ADDR_BASE:
7946 /*
7947 * The Marvell case also falls into
7948 * this case as
7949 * MRVL88X2011_NEPTUNE_PORT_ADDR_BASE
7950 * == NEPTUNE_CLAUSE45_PORT_ADDR_BASE.
7951 * This is OK for the 2 10G case.
7952 */
7953 hw_p->niu_type = NEPTUNE_2_10GF;
7954 hw_p->platform_type =
7955 P_NEPTUNE_ATLAS_2PORT;
7956 break;
7957 case GOA_CLAUSE45_PORT_ADDR_BASE:
7958 if (hw_p->platform_type !=
7959 P_NEPTUNE_NIU) {
7960 hw_p->platform_type =
7961 P_NEPTUNE_GENERIC;
7962 hw_p->niu_type =
7963 NEPTUNE_2_10GF;
7964 }
7965 break;
7966 default:
7967 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
7968 "Unsupported neptune type 2 - 1"));
7969 goto error_exit;
7970 }
7971
7972 for (i = 0; i < 2; i++) {
7973 hw_p->xcvr_addr[i] = port_fd_arr[i];
7974 }
7975
7976 /* 2 10G optical Netlogic AEL2020 ports */
7977 } else if (((port_pcs_dev_id[0] == NLP2020_DEV_ID) &&
7978 (port_pcs_dev_id[1] == NLP2020_DEV_ID)) ||
7979 ((port_pma_pmd_dev_id[0] == NLP2020_DEV_ID) &&
7980 (port_pma_pmd_dev_id[1] == NLP2020_DEV_ID))) {
7981 if (hw_p->platform_type != P_NEPTUNE_NIU) {
7982 hw_p->platform_type =
7983 P_NEPTUNE_GENERIC;
7984 hw_p->niu_type =
7985 NEPTUNE_2_10GF;
7986 }
7987 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
7988 "Found 2 NL PHYs at addrs 0x%x and 0x%x",
7989 port_fd_arr[0], port_fd_arr[1]));
7990 hw_p->xcvr_addr[0] = port_fd_arr[0];
7991 hw_p->xcvr_addr[1] = port_fd_arr[1];
7992
7993 /* Both XAUI slots have copper XAUI cards */
7994 } else if ((((port_pcs_dev_id[0] & TN1010_DEV_ID_MASK)
7995 == TN1010_DEV_ID) &&
7996 ((port_pcs_dev_id[1] & TN1010_DEV_ID_MASK)
7997 == TN1010_DEV_ID)) ||
7998 (((port_pma_pmd_dev_id[0] & TN1010_DEV_ID_MASK)
7999 == TN1010_DEV_ID) &&
8000 ((port_pma_pmd_dev_id[1] & TN1010_DEV_ID_MASK)
8001 == TN1010_DEV_ID))) {
8002 hw_p->niu_type = NEPTUNE_2_TN1010;
8003 hw_p->xcvr_addr[0] = port_fd_arr[0];
8004 hw_p->xcvr_addr[1] = port_fd_arr[1];
8005
8006 /* Slot0 has fiber XAUI, slot1 has copper XAUI */
8007 } else if ((port_pcs_dev_id[0] == PHY_BCM8704_FAMILY &&
8008 (port_pcs_dev_id[1] & TN1010_DEV_ID_MASK)
8009 == TN1010_DEV_ID) ||
8010 (port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY &&
8011 (port_pma_pmd_dev_id[1] & TN1010_DEV_ID_MASK) ==
8012 TN1010_DEV_ID)) {
8013 hw_p->niu_type = NEPTUNE_1_10GF_1_TN1010;
8014 hw_p->xcvr_addr[0] = port_fd_arr[0];
8015 hw_p->xcvr_addr[1] = port_fd_arr[1];
8016
8017 /* Slot0 has copper XAUI, slot1 has fiber XAUI */
8018 } else if ((port_pcs_dev_id[1] == PHY_BCM8704_FAMILY &&
8019 (port_pcs_dev_id[0] & TN1010_DEV_ID_MASK)
8020 == TN1010_DEV_ID) ||
8021 (port_pma_pmd_dev_id[1] == PHY_BCM8704_FAMILY &&
8022 (port_pma_pmd_dev_id[0] & TN1010_DEV_ID_MASK)
8023 == TN1010_DEV_ID)) {
8024 hw_p->niu_type = NEPTUNE_1_TN1010_1_10GF;
8025 hw_p->xcvr_addr[0] = port_fd_arr[0];
8026 hw_p->xcvr_addr[1] = port_fd_arr[1];
8027
8028 } else {
8029 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
8030 "Unsupported neptune type 2"));
8031 goto error_exit;
8032 }
8033 break;
8034
8035 case 4:
8036 if (nxge_get_num_of_xaui(
8037 port_pma_pmd_dev_id, port_pcs_dev_id,
8038 port_phy_id, &num_xaui) == NXGE_ERROR) {
8039 goto error_exit;
8040 }
8041 if (num_xaui != 2)
8042 goto error_exit;
8043
8044 /*
8045 * Maramba with 2 XAUIs (either fiber or copper)
8046 *
8047 * Check the first phy port address against
8048 * the known phy start addresses to determine
8049 * the platform type.
8050 */
8051 switch (phy_fd_arr[0]) {
8052 case MARAMBA_P0_CLAUSE22_PORT_ADDR_BASE:
8053 hw_p->platform_type =
8054 P_NEPTUNE_MARAMBA_P0;
8055 break;
8056 case MARAMBA_P1_CLAUSE22_PORT_ADDR_BASE:
8057 hw_p->platform_type =
8058 P_NEPTUNE_MARAMBA_P1;
8059 break;
8060 default:
8061 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
8062 "Unknown port %d...Cannot "
8063 "determine platform type", i));
8064 goto error_exit;
8065 }
8066
8067 hw_p->xcvr_addr[0] = port_fd_arr[0];
8068 hw_p->xcvr_addr[1] = port_fd_arr[1];
8069 hw_p->xcvr_addr[2] = phy_fd_arr[2];
8070 hw_p->xcvr_addr[3] = phy_fd_arr[3];
8071
8072 /* slot0 has fiber XAUI, slot1 has Cu XAUI */
8073 if (port_pcs_dev_id[0] == PHY_BCM8704_FAMILY &&
8074 (port_pcs_dev_id[1] & TN1010_DEV_ID_MASK)
8075 == TN1010_DEV_ID) {
8076 hw_p->niu_type = NEPTUNE_1_10GF_1_TN1010_2_1GC;
8077
8078 /* slot0 has Cu XAUI, slot1 has fiber XAUI */
8079 } else if (((port_pcs_dev_id[0] & TN1010_DEV_ID_MASK)
8080 == TN1010_DEV_ID) &&
8081 port_pcs_dev_id[1] == PHY_BCM8704_FAMILY) {
8082 hw_p->niu_type = NEPTUNE_1_TN1010_1_10GF_2_1GC;
8083
8084 /* Both slots have fiber XAUI */
8085 } else if (port_pcs_dev_id[0] == PHY_BCM8704_FAMILY &&
8086 port_pcs_dev_id[1] == PHY_BCM8704_FAMILY) {
8087 hw_p->niu_type = NEPTUNE_2_10GF_2_1GC;
8088
8089 /* Both slots have copper XAUI */
8090 } else if (((port_pcs_dev_id[0] & TN1010_DEV_ID_MASK)
8091 == TN1010_DEV_ID) &&
8092 (port_pcs_dev_id[1] & TN1010_DEV_ID_MASK)
8093 == TN1010_DEV_ID) {
8094 hw_p->niu_type = NEPTUNE_2_TN1010_2_1GC;
8095
8096 } else {
8097 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
8098 "Unsupported neptune type 3"));
8099 goto error_exit;
8100 }
8101 break;
8102 default:
8103 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
8104 "Unsupported neptune type 5"));
8105 goto error_exit;
8106 }
8107 break;
8108 case 1: /* Only one clause45 port */
8109 switch (total_phy_fd) { /* Number of clause22 ports */
8110 case 3:
8111 /*
8112 * TODO 3 1G, 1 10G mode.
8113 * Differentiate between 1_1G_1_10G_2_1G and
8114 * 1_10G_3_1G
8115 */
8116 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
8117 "Unsupported neptune type 7"));
8118 goto error_exit;
8119 case 2:
8120 /*
8121 * TODO 2 1G, 1 10G mode.
8122 * Differentiate between 1_1G_1_10G_1_1G and
8123 * 1_10G_2_1G
8124 */
8125 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
8126 "Unsupported neptune type 8"));
8127 goto error_exit;
8128 case 1:
8129 /*
8130 * TODO 1 1G, 1 10G mode.
8131 * Differentiate between 1_1G_1_10G and
8132 * 1_10G_1_1G
8133 */
8134 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
8135 "Unsupported neptune type 9"));
8136 goto error_exit;
8137 case 0: /* N2 with 1 XAUI (fiber or copper) */
8138 /* Fiber XAUI */
8139 if (port_pcs_dev_id[0] == PHY_BCM8704_FAMILY ||
8140 port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY) {
8141
8142 /*
8143 * Check the first phy port address against
8144 * the known phy start addresses to determine
8145 * the platform type.
8146 */
8147
8148 switch (port_fd_arr[0]) {
8149 case N2_CLAUSE45_PORT_ADDR_BASE:
8150 case (N2_CLAUSE45_PORT_ADDR_BASE + 1):
8151 case ALT_GOA_CLAUSE45_PORT1_ADDR:
8152 /*
8153 * If hw_p->platform_type ==
8154 * P_NEPTUNE_NIU, then portmode
8155 * is already known, so there is
8156 * no need to figure out hw_p->
8157 * platform_type because
8158 * platform_type is only for
8159 * figuring out portmode.
8160 */
8161 if (hw_p->platform_type !=
8162 P_NEPTUNE_NIU) {
8163 hw_p->platform_type =
8164 P_NEPTUNE_GENERIC;
8165 hw_p->niu_type =
8166 NEPTUNE_2_10GF;
8167 }
8168 break;
8169 default:
8170 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
8171 "Unsupported neptune type 10"));
8172 goto error_exit;
8173 }
8174 /*
8175 * For GOA, which is a hot swappable PHY, the
8176 * phy address to function number mapping
8177 * should be preserved, i.e., addr 16 is
8178 * assigned to function 0 and 20 to function 1
8179 * But for Huron XAUI, the assignment should
8180 * be by function number, i.e., whichever
8181 * function number attaches should be
8182 * assigned the available PHY (this is required
8183 * primarily to support pre-production Huron
8184 * boards where function 0 is mapped to addr 17
8185 */
8186 if (port_fd_arr[0] ==
8187 ALT_GOA_CLAUSE45_PORT1_ADDR) {
8188 hw_p->xcvr_addr[1] = port_fd_arr[0];
8189 } else {
8190 hw_p->xcvr_addr[nxgep->function_num] =
8191 port_fd_arr[0];
8192 }
8193 } else if (port_pcs_dev_id[0] == NLP2020_DEV_ID ||
8194 port_pma_pmd_dev_id[0] == NLP2020_DEV_ID) {
8195 /* A 10G NLP2020 PHY in slot0 or slot1 */
8196 switch (port_fd_arr[0]) {
8197 case NLP2020_CL45_PORT0_ADDR0:
8198 case NLP2020_CL45_PORT0_ADDR1:
8199 case NLP2020_CL45_PORT0_ADDR2:
8200 case NLP2020_CL45_PORT0_ADDR3:
8201 case NLP2020_CL45_PORT1_ADDR0:
8202 case NLP2020_CL45_PORT1_ADDR1:
8203 case NLP2020_CL45_PORT1_ADDR2:
8204 case NLP2020_CL45_PORT1_ADDR3:
8205 /*
8206 * If hw_p->platform_type ==
8207 * P_NEPTUNE_NIU, then portmode
8208 * is already known, so there is
8209 * no need to figure out hw_p->
8210 * platform_type because
8211 * platform_type is only for
8212 * figuring out portmode.
8213 */
8214 if (hw_p->platform_type !=
8215 P_NEPTUNE_NIU) {
8216 hw_p->platform_type =
8217 P_NEPTUNE_GENERIC;
8218 hw_p->niu_type =
8219 NEPTUNE_2_10GF;
8220 }
8221 break;
8222 default:
8223 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
8224 "Unsupported neptune type 10-1"));
8225 goto error_exit;
8226 }
8227 switch (port_fd_arr[0]) {
8228 case NLP2020_CL45_PORT0_ADDR0:
8229 case NLP2020_CL45_PORT0_ADDR1:
8230 case NLP2020_CL45_PORT0_ADDR2:
8231 case NLP2020_CL45_PORT0_ADDR3:
8232 hw_p->xcvr_addr[0] = port_fd_arr[0];
8233 break;
8234 case NLP2020_CL45_PORT1_ADDR0:
8235 case NLP2020_CL45_PORT1_ADDR1:
8236 case NLP2020_CL45_PORT1_ADDR2:
8237 case NLP2020_CL45_PORT1_ADDR3:
8238 hw_p->xcvr_addr[1] = port_fd_arr[0];
8239 break;
8240 default:
8241 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
8242 "Unsupported neptune type 10-11"));
8243 goto error_exit;
8244 }
8245
8246 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
8247 "Found 1 NL PHYs at addr 0x%x",
8248 port_fd_arr[0]));
8249
8250 /* A 10G copper XAUI in either slot0 or slot1 */
8251 } else if ((port_pcs_dev_id[0] & TN1010_DEV_ID_MASK)
8252 == TN1010_DEV_ID ||
8253 (port_pma_pmd_dev_id[0] & TN1010_DEV_ID_MASK)
8254 == TN1010_DEV_ID) {
8255 switch (port_fd_arr[0]) {
8256 /* The XAUI is in slot0 */
8257 case N2_CLAUSE45_PORT_ADDR_BASE:
8258 hw_p->niu_type = NEPTUNE_1_TN1010;
8259 break;
8260
8261 /* The XAUI is in slot1 */
8262 case (N2_CLAUSE45_PORT_ADDR_BASE + 1):
8263 hw_p->niu_type
8264 = NEPTUNE_1_NONE_1_TN1010;
8265 break;
8266 default:
8267 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
8268 "Unsupported XAUI port address"));
8269 goto error_exit;
8270 }
8271 hw_p->xcvr_addr[nxgep->function_num]
8272 = port_fd_arr[0];
8273
8274 } else {
8275 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
8276 "Unsupported PHY type"));
8277 goto error_exit;
8278 }
8279 break;
8280 case 4: /* Maramba always have 4 clause 45 ports */
8281
8282 /* Maramba with 1 XAUI */
8283 if ((port_pcs_dev_id[0] != PHY_BCM8704_FAMILY) &&
8284 (port_pma_pmd_dev_id[0] != PHY_BCM8704_FAMILY) &&
8285 ((port_pcs_dev_id[0] & TN1010_DEV_ID_MASK)
8286 != TN1010_DEV_ID) &&
8287 ((port_pma_pmd_dev_id[0] & TN1010_DEV_ID_MASK)
8288 != TN1010_DEV_ID)) {
8289 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
8290 "Unsupported neptune type 12"));
8291 goto error_exit;
8292 }
8293
8294 /*
8295 * Check the first phy port address against
8296 * the known phy start addresses to determine
8297 * the platform type.
8298 */
8299 switch (phy_fd_arr[0]) {
8300 case MARAMBA_P0_CLAUSE22_PORT_ADDR_BASE:
8301 hw_p->platform_type =
8302 P_NEPTUNE_MARAMBA_P0;
8303 break;
8304 case MARAMBA_P1_CLAUSE22_PORT_ADDR_BASE:
8305 hw_p->platform_type =
8306 P_NEPTUNE_MARAMBA_P1;
8307 break;
8308 default:
8309 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
8310 "Unknown port %d...Cannot "
8311 "determine platform type 10 - 2",
8312 i));
8313 goto error_exit;
8314 }
8315
8316 /*
8317 * Check the clause45 address to determine
8318 * if XAUI is in port 0 or port 1.
8319 */
8320 switch (port_fd_arr[0]) {
8321 case MARAMBA_CLAUSE45_PORT_ADDR_BASE:
8322 if (port_pcs_dev_id[0]
8323 == PHY_BCM8704_FAMILY ||
8324 port_pma_pmd_dev_id[0]
8325 == PHY_BCM8704_FAMILY) {
8326 hw_p->niu_type
8327 = NEPTUNE_1_10GF_3_1GC;
8328 } else {
8329 hw_p->niu_type
8330 = NEPTUNE_1_TN1010_3_1GC;
8331 }
8332 hw_p->xcvr_addr[0] = port_fd_arr[0];
8333 for (i = 1; i < NXGE_MAX_PORTS; i++) {
8334 hw_p->xcvr_addr[i] =
8335 phy_fd_arr[i];
8336 }
8337 break;
8338 case (MARAMBA_CLAUSE45_PORT_ADDR_BASE + 1):
8339 if (port_pcs_dev_id[0]
8340 == PHY_BCM8704_FAMILY ||
8341 port_pma_pmd_dev_id[0]
8342 == PHY_BCM8704_FAMILY) {
8343 hw_p->niu_type =
8344 NEPTUNE_1_1GC_1_10GF_2_1GC;
8345 } else {
8346 hw_p->niu_type =
8347 NEPTUNE_1_1GC_1_TN1010_2_1GC;
8348 }
8349 hw_p->xcvr_addr[0] = phy_fd_arr[0];
8350 hw_p->xcvr_addr[1] = port_fd_arr[0];
8351 hw_p->xcvr_addr[2] = phy_fd_arr[2];
8352 hw_p->xcvr_addr[3] = phy_fd_arr[3];
8353 break;
8354 default:
8355 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
8356 "Unsupported neptune type 11"));
8357 goto error_exit;
8358 }
8359 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
8360 "Maramba with 1 XAUI (fiber or copper)"));
8361 break;
8362 default:
8363 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
8364 "Unsupported neptune type 13"));
8365 goto error_exit;
8366 }
8367 break;
8368 case 0: /* 4 ports Neptune based NIC */
8369 switch (total_phy_fd) {
8370 case 4:
8371 if ((port_phy_id[0] == PHY_BCM5464R_FAMILY) &&
8372 (port_phy_id[1] == PHY_BCM5464R_FAMILY) &&
8373 (port_phy_id[2] == PHY_BCM5464R_FAMILY) &&
8374 (port_phy_id[3] == PHY_BCM5464R_FAMILY)) {
8375
8376 /*
8377 * Check the first phy port address against
8378 * the known phy start addresses to determine
8379 * the platform type.
8380 */
8381 switch (phy_fd_arr[0]) {
8382 case MARAMBA_P1_CLAUSE22_PORT_ADDR_BASE:
8383 hw_p->platform_type =
8384 P_NEPTUNE_MARAMBA_P1;
8385 break;
8386 case NEPTUNE_CLAUSE22_PORT_ADDR_BASE:
8387 hw_p->platform_type =
8388 P_NEPTUNE_ATLAS_4PORT;
8389 break;
8390 default:
8391 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
8392 "Unknown port %d...Cannot "
8393 "determine platform type", i));
8394 goto error_exit;
8395 }
8396 hw_p->niu_type = NEPTUNE_4_1GC;
8397 for (i = 0; i < NXGE_MAX_PORTS; i++) {
8398 hw_p->xcvr_addr[i] = phy_fd_arr[i];
8399 }
8400 } else {
8401 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
8402 "Unsupported neptune type 14"));
8403 goto error_exit;
8404 }
8405 break;
8406 case 3:
8407 /* TODO 3 1G mode */
8408 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
8409 "Unsupported neptune type 15"));
8410 goto error_exit;
8411 case 2:
8412 /* TODO 2 1G mode */
8413 if ((port_phy_id[0] == PHY_BCM5482_FAMILY) &&
8414 (port_phy_id[1] == PHY_BCM5482_FAMILY)) {
8415 hw_p->platform_type = P_NEPTUNE_GENERIC;
8416 hw_p->niu_type = NEPTUNE_2_1GRF;
8417 hw_p->xcvr_addr[2] = phy_fd_arr[0];
8418 hw_p->xcvr_addr[3] = phy_fd_arr[1];
8419 } else {
8420 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
8421 "Unsupported neptune type 16"));
8422 goto error_exit;
8423 }
8424 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
8425 "2 RGMII Fiber ports - RTM"));
8426 break;
8427
8428 case 1:
8429 /* TODO 1 1G mode */
8430 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
8431 "Unsupported neptune type 17"));
8432 goto error_exit;
8433 default:
8434 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
8435 "Unsupported neptune type 18, total phy fd %d",
8436 total_phy_fd));
8437 goto error_exit;
8438 }
8439 break;
8440 default:
8441 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
8442 "Unsupported neptune type 19"));
8443 goto error_exit;
8444 }
8445
8446 scan_exit:
8447
8448 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_scan_ports_phy, "
8449 "niu type [0x%x]\n", hw_p->niu_type));
8450 return (status);
8451
8452 error_exit:
8453 return (NXGE_ERROR);
8454 }
8455
8456 boolean_t
nxge_is_valid_local_mac(ether_addr_st mac_addr)8457 nxge_is_valid_local_mac(ether_addr_st mac_addr)
8458 {
8459 if ((mac_addr.ether_addr_octet[0] & 0x01) ||
8460 (ether_cmp(&mac_addr, ðerbroadcastaddr) == 0) ||
8461 (ether_cmp(&mac_addr, ðerzeroaddr) == 0))
8462 return (B_FALSE);
8463 else
8464 return (B_TRUE);
8465 }
8466
8467 static void
nxge_bcm5464_link_led_off(p_nxge_t nxgep)8468 nxge_bcm5464_link_led_off(p_nxge_t nxgep) {
8469
8470 npi_status_t rs = NPI_SUCCESS;
8471 uint8_t xcvr_portn;
8472 uint8_t portn = NXGE_GET_PORT_NUM(nxgep->function_num);
8473
8474 NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_bcm5464_link_led_off"));
8475
8476 if (nxgep->nxge_hw_p->platform_type == P_NEPTUNE_MARAMBA_P1) {
8477 xcvr_portn = MARAMBA_P1_CLAUSE22_PORT_ADDR_BASE;
8478 } else if (nxgep->nxge_hw_p->platform_type == P_NEPTUNE_MARAMBA_P0) {
8479 xcvr_portn = MARAMBA_P0_CLAUSE22_PORT_ADDR_BASE;
8480 }
8481 /*
8482 * For Altas 4-1G copper, Xcvr port numbers are
8483 * swapped with ethernet port number. This is
8484 * designed for better signal integrity in routing.
8485 */
8486 switch (portn) {
8487 case 0:
8488 xcvr_portn += 3;
8489 break;
8490 case 1:
8491 xcvr_portn += 2;
8492 break;
8493 case 2:
8494 xcvr_portn += 1;
8495 break;
8496 case 3:
8497 default:
8498 break;
8499 }
8500
8501 MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock);
8502 rs = npi_mac_mif_mii_write(nxgep->npi_handle,
8503 xcvr_portn, BCM5464R_MISC, 0xb4ee);
8504 if (rs != NPI_SUCCESS) {
8505 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
8506 "<== nxge_bcm5464_link_led_off: npi_mac_mif_mii_write "
8507 "returned error 0x[%x]", rs));
8508 MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
8509 return;
8510 }
8511
8512 rs = npi_mac_mif_mii_write(nxgep->npi_handle,
8513 xcvr_portn, BCM5464R_MISC, 0xb8ee);
8514 if (rs != NPI_SUCCESS) {
8515 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
8516 "<== nxge_bcm5464_link_led_off: npi_mac_mif_mii_write "
8517 "returned error 0x[%x]", rs));
8518 }
8519
8520 MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
8521 }
8522
8523 static nxge_status_t
nxge_mii_get_link_mode(p_nxge_t nxgep)8524 nxge_mii_get_link_mode(p_nxge_t nxgep)
8525 {
8526 p_nxge_stats_t statsp;
8527 uint8_t xcvr_portn;
8528 p_mii_regs_t mii_regs;
8529 mii_mode_control_stat_t mode;
8530 int status = NXGE_OK;
8531
8532 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_get_link_mode"));
8533
8534 statsp = nxgep->statsp;
8535 xcvr_portn = statsp->mac_stats.xcvr_portn;
8536 mii_regs = NULL;
8537 mode.value = 0;
8538 mode.bits.shadow = NXGE_MII_MODE_CONTROL_REG;
8539 #if defined(__i386)
8540 if ((status = nxge_mii_write(nxgep, xcvr_portn,
8541 (uint8_t)(uint32_t)(&mii_regs->shadow),
8542 mode.value)) != NXGE_OK) {
8543 goto fail;
8544 #else
8545 if ((status = nxge_mii_write(nxgep, xcvr_portn,
8546 (uint8_t)(uint64_t)(&mii_regs->shadow),
8547 mode.value)) != NXGE_OK) {
8548 goto fail;
8549 #endif
8550 }
8551 #if defined(__i386)
8552 if ((status = nxge_mii_read(nxgep, xcvr_portn,
8553 (uint8_t)(uint32_t)(&mii_regs->shadow),
8554 &mode.value)) != NXGE_OK) {
8555 goto fail;
8556 }
8557 #else
8558 if ((status = nxge_mii_read(nxgep, xcvr_portn,
8559 (uint8_t)(uint64_t)(&mii_regs->shadow),
8560 &mode.value)) != NXGE_OK) {
8561 goto fail;
8562 }
8563 #endif
8564
8565 if (mode.bits.mode == NXGE_MODE_SELECT_FIBER) {
8566 nxgep->mac.portmode = PORT_1G_RGMII_FIBER;
8567 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
8568 "nxge_mii_get_link_mode: fiber mode"));
8569 }
8570
8571 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
8572 "nxge_mii_get_link_mode: "
8573 "(address 0x%x) port 0x%x mode value 0x%x link mode 0x%x",
8574 NXGE_MII_MODE_CONTROL_REG, xcvr_portn,
8575 mode.value, nxgep->mac.portmode));
8576
8577 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
8578 "<== nxge_mii_get_link_mode"));
8579 return (status);
8580 fail:
8581 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
8582 "<== nxge_mii_get_link_mode (failed)"));
8583 return (NXGE_ERROR);
8584 }
8585
8586 nxge_status_t
8587 nxge_mac_set_framesize(p_nxge_t nxgep)
8588 {
8589 npi_attr_t ap;
8590 uint8_t portn;
8591 npi_handle_t handle;
8592 npi_status_t rs = NPI_SUCCESS;
8593
8594 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mac_set_framesize"));
8595
8596 portn = NXGE_GET_PORT_NUM(nxgep->function_num);
8597 handle = nxgep->npi_handle;
8598
8599 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
8600 "==> nxge_mac_sec_framesize: port<%d> "
8601 "min framesize %d max framesize %d ",
8602 portn,
8603 nxgep->mac.minframesize,
8604 nxgep->mac.maxframesize));
8605
8606 SET_MAC_ATTR2(handle, ap, portn,
8607 MAC_PORT_FRAME_SIZE,
8608 nxgep->mac.minframesize,
8609 nxgep->mac.maxframesize,
8610 rs);
8611 if (rs != NPI_SUCCESS) {
8612 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
8613 "<== nxge_mac_set_framesize: failed to configure "
8614 "max/min frame size port %d", portn));
8615
8616 return (NXGE_ERROR | rs);
8617 }
8618
8619 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
8620 "<== nxge_mac_set_framesize: port<%d>", portn));
8621
8622 return (NXGE_OK);
8623 }
8624
8625 static nxge_status_t
8626 nxge_get_num_of_xaui(uint32_t *port_pma_pmd_dev_id,
8627 uint32_t *port_pcs_dev_id, uint32_t *port_phy_id, uint8_t *num_xaui)
8628 {
8629 uint8_t i;
8630
8631 for (i = 0; i < 4; i++) {
8632 if (port_phy_id[i] != PHY_BCM5464R_FAMILY)
8633 return (NXGE_ERROR);
8634 }
8635
8636 *num_xaui = 0;
8637 if ((port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY &&
8638 port_pcs_dev_id[0] == PHY_BCM8704_FAMILY) ||
8639 (((port_pma_pmd_dev_id[0] & TN1010_DEV_ID_MASK)
8640 == TN1010_DEV_ID) &&
8641 ((port_pcs_dev_id[0] & TN1010_DEV_ID_MASK)
8642 == TN1010_DEV_ID))) {
8643 (*num_xaui) ++;
8644 }
8645 if ((port_pma_pmd_dev_id[1] == PHY_BCM8704_FAMILY &&
8646 port_pcs_dev_id[1] == PHY_BCM8704_FAMILY) ||
8647 (((port_pma_pmd_dev_id[1] & TN1010_DEV_ID_MASK)
8648 == TN1010_DEV_ID) &&
8649 ((port_pcs_dev_id[1] & TN1010_DEV_ID_MASK)
8650 == TN1010_DEV_ID))) {
8651 (*num_xaui) ++;
8652 }
8653 return (NXGE_OK);
8654 }
8655
8656 /*
8657 * Instruction from Teranetics: Once you detect link is up, go
8658 * read Reg 30.1.4 for link speed: '1' for 1G and '0' for 10G. You
8659 * may want to qualify it by first checking Register 30.1.7:6 and
8660 * making sure it reads "01" (Auto-Neg Complete).
8661 *
8662 * If this function is called when the link is down or before auto-
8663 * negotiation has completed, then the speed of the PHY is not certain.
8664 * In such cases, this function returns 1G as the default speed with
8665 * NXGE_OK status instead of NXGE_ERROR. It is OK to initialize the
8666 * driver based on a default speed because this function will be called
8667 * again when the link comes up. Returning NXGE_ERROR, which may
8668 * cause brutal chain reaction in caller functions, is not necessary.
8669 */
8670 static nxge_status_t
8671 nxge_get_tn1010_speed(p_nxge_t nxgep, uint16_t *speed)
8672 {
8673 uint8_t phy_port_addr, autoneg_stat, link_up;
8674 nxge_status_t status = NXGE_OK;
8675 uint16_t val;
8676 uint8_t portn = NXGE_GET_PORT_NUM(nxgep->function_num);
8677
8678 /* Set default speed to 10G */
8679 *speed = TN1010_SPEED_10G;
8680
8681 /* Set Clause 45 */
8682 npi_mac_mif_set_indirect_mode(nxgep->npi_handle, B_TRUE);
8683
8684 phy_port_addr = nxgep->nxge_hw_p->xcvr_addr[portn];
8685
8686 /* Check Device 1 Register 0xA bit0 for link up status */
8687 status = nxge_mdio_read(nxgep, phy_port_addr,
8688 TN1010_AUTONEG_DEV_ADDR, TN1010_AUTONEG_STATUS_REG, &val);
8689 if (status != NXGE_OK)
8690 goto fail;
8691
8692 link_up = ((val & TN1010_AN_LINK_STAT_BIT)
8693 ? B_TRUE : B_FALSE);
8694 if (link_up == B_FALSE) {
8695 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
8696 "nxge_get_tn1010_speed: link is down"));
8697 goto nxge_get_tn1010_speed_exit;
8698 }
8699
8700 if ((status = nxge_mdio_read(nxgep, phy_port_addr,
8701 TN1010_VENDOR_MMD1_DEV_ADDR, TN1010_VENDOR_MMD1_STATUS_REG,
8702 &val)) != NXGE_OK) {
8703 goto fail;
8704 }
8705 autoneg_stat = (val & TN1010_VENDOR_MMD1_AN_STAT_BITS) >>
8706 TN1010_VENDOR_MMD1_AN_STAT_SHIFT;
8707
8708 /*
8709 * Return NXGE_OK even when we can not get a settled speed. In
8710 * such case, the speed reported should not be trusted but that
8711 * is OK, we will call this function periodically and will get
8712 * the correct speed after the link is up.
8713 */
8714 switch (autoneg_stat) {
8715 case TN1010_AN_IN_PROG:
8716 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
8717 "nxge_get_tn1010_speed: Auto-negotiation in progress"));
8718 break;
8719 case TN1010_AN_COMPLETE:
8720 if ((status = nxge_mdio_read(nxgep, phy_port_addr,
8721 TN1010_VENDOR_MMD1_DEV_ADDR,
8722 TN1010_VENDOR_MMD1_STATUS_REG,
8723 &val)) != NXGE_OK) {
8724 goto fail;
8725 }
8726 *speed = (val & TN1010_VENDOR_MMD1_AN_SPEED_BIT) >>
8727 TN1010_VENDOR_MMD1_AN_SPEED_SHIFT;
8728 break;
8729 case TN1010_AN_RSVD:
8730 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
8731 "nxge_get_tn1010_speed: Autoneg status undefined"));
8732 break;
8733 case TN1010_AN_FAILED:
8734 NXGE_DEBUG_MSG((nxgep, MAC_CTL,
8735 "nxge_get_tn1010_speed: Auto-negotiation failed"));
8736 break;
8737 default:
8738 break;
8739 }
8740 nxge_get_tn1010_speed_exit:
8741 return (NXGE_OK);
8742 fail:
8743 return (status);
8744 }
8745
8746
8747 /*
8748 * Teranetics TN1010 PHY chip supports both 1G and 10G modes, this function
8749 * figures out the speed of the PHY determined by the autonegotiation
8750 * process and sets the following 3 parameters,
8751 * nxgep->mac.portmode
8752 * nxgep->statsp->mac_stats.link_speed
8753 * nxgep->statsp->mac_stats.xcvr_inuse
8754 */
8755 static nxge_status_t
8756 nxge_set_tn1010_param(p_nxge_t nxgep)
8757 {
8758 uint16_t speed;
8759
8760 if (nxge_get_tn1010_speed(nxgep, &speed) != NXGE_OK) {
8761 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
8762 "nxge_set_tn1010_param: "
8763 "Failed to get TN1010 speed"));
8764 return (NXGE_ERROR);
8765 }
8766 if (speed == TN1010_SPEED_1G) {
8767 nxgep->mac.portmode = PORT_1G_TN1010;
8768 nxgep->statsp->mac_stats.link_speed = 1000;
8769 nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR;
8770 } else {
8771 nxgep->mac.portmode = PORT_10G_TN1010;
8772 nxgep->statsp->mac_stats.link_speed = 10000;
8773 nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
8774 }
8775 return (NXGE_OK);
8776 }
8777
8778 #ifdef NXGE_DEBUG
8779 static void
8780 nxge_mii_dump(p_nxge_t nxgep)
8781 {
8782 p_nxge_stats_t statsp;
8783 uint8_t xcvr_portn;
8784 p_mii_regs_t mii_regs;
8785 mii_bmcr_t bmcr;
8786 mii_bmsr_t bmsr;
8787 mii_idr1_t idr1;
8788 mii_idr2_t idr2;
8789 mii_mode_control_stat_t mode;
8790 p_nxge_param_t param_arr;
8791
8792 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "==> nxge_mii_dump"));
8793
8794 statsp = nxgep->statsp;
8795 xcvr_portn = statsp->mac_stats.xcvr_portn;
8796
8797 mii_regs = NULL;
8798
8799 #if defined(__i386)
8800 (void) nxge_mii_read(nxgep, nxgep->statsp->mac_stats.xcvr_portn,
8801 (uint8_t)(uint32_t)(&mii_regs->bmcr), &bmcr.value);
8802 #else
8803 (void) nxge_mii_read(nxgep, nxgep->statsp->mac_stats.xcvr_portn,
8804 (uint8_t)(uint64_t)(&mii_regs->bmcr), &bmcr.value);
8805 #endif
8806 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
8807 "nxge_mii_dump: bmcr (0) xcvr 0x%x value 0x%x",
8808 xcvr_portn, bmcr.value));
8809
8810 #if defined(__i386)
8811 (void) nxge_mii_read(nxgep,
8812 nxgep->statsp->mac_stats.xcvr_portn,
8813 (uint8_t)(uint32_t)(&mii_regs->bmsr), &bmsr.value);
8814 #else
8815 (void) nxge_mii_read(nxgep,
8816 nxgep->statsp->mac_stats.xcvr_portn,
8817 (uint8_t)(uint64_t)(&mii_regs->bmsr), &bmsr.value);
8818 #endif
8819 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
8820 "nxge_mii_dump: bmsr (1) xcvr 0x%x value 0x%x",
8821 xcvr_portn, bmsr.value));
8822
8823 #if defined(__i386)
8824 (void) nxge_mii_read(nxgep,
8825 nxgep->statsp->mac_stats.xcvr_portn,
8826 (uint8_t)(uint32_t)(&mii_regs->idr1), &idr1.value);
8827 #else
8828 (void) nxge_mii_read(nxgep,
8829 nxgep->statsp->mac_stats.xcvr_portn,
8830 (uint8_t)(uint64_t)(&mii_regs->idr1), &idr1.value);
8831 #endif
8832
8833
8834 #if defined(__i386)
8835 (void) nxge_mii_read(nxgep,
8836 nxgep->statsp->mac_stats.xcvr_portn,
8837 (uint8_t)(uint32_t)(&mii_regs->idr2), &idr2.value);
8838 #else
8839 (void) nxge_mii_read(nxgep,
8840 nxgep->statsp->mac_stats.xcvr_portn,
8841 (uint8_t)(uint64_t)(&mii_regs->idr2), &idr2.value);
8842 #endif
8843
8844 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
8845 "nxge_mii_dump: idr1 (2) xcvr 0x%x value 0x%x",
8846 xcvr_portn, idr1.value));
8847
8848 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
8849 "nxge_mii_dump: idr2 (3) xcvr 0x%x value 0x%x",
8850 xcvr_portn, idr2.value));
8851
8852 mode.value = 0;
8853 mode.bits.shadow = NXGE_MII_MODE_CONTROL_REG;
8854
8855 #if defined(__i386)
8856 (void) nxge_mii_write(nxgep, xcvr_portn,
8857 (uint8_t)(uint32_t)(&mii_regs->shadow), mode.value);
8858
8859 (void) nxge_mii_read(nxgep, xcvr_portn,
8860 (uint8_t)(uint32_t)(&mii_regs->shadow), &mode.value);
8861 #else
8862 (void) nxge_mii_write(nxgep, xcvr_portn,
8863 (uint8_t)(uint64_t)(&mii_regs->shadow), mode.value);
8864
8865 (void) nxge_mii_read(nxgep, xcvr_portn,
8866 (uint8_t)(uint64_t)(&mii_regs->shadow), &mode.value);
8867 #endif
8868
8869 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
8870 "nxge_mii_dump: mode control xcvr 0x%x value 0x%x",
8871 xcvr_portn, mode.value));
8872 }
8873 #endif
8874