xref: /titanic_50/usr/src/uts/common/io/nxge/nxge_espc.c (revision 7c64d3750da7fda7e450b8f9b0b963905ded6379)
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 2008 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 
28 #include <nxge_impl.h>
29 #include <nxge_mac.h>
30 #include <npi_espc.h>
31 #include <nxge_espc.h>
32 
33 static void nxge_check_vpd_version(p_nxge_t nxgep);
34 
35 void
36 nxge_espc_get_next_mac_addr(uint8_t *st_mac, uint8_t nxt_cnt,
37 			    struct ether_addr *final_mac)
38 {
39 	uint64_t	mac[ETHERADDRL];
40 	uint64_t	mac_addr = 0;
41 	int		i, j;
42 
43 	for (i = ETHERADDRL - 1, j = 0; j < ETHERADDRL; i--, j++) {
44 		mac[j] = st_mac[i];
45 		mac_addr |= (mac[j] << (j*8));
46 	}
47 
48 	mac_addr += nxt_cnt;
49 
50 	final_mac->ether_addr_octet[0] = (mac_addr & 0xff0000000000) >> 40;
51 	final_mac->ether_addr_octet[1] = (mac_addr & 0xff00000000) >> 32;
52 	final_mac->ether_addr_octet[2] = (mac_addr & 0xff000000) >> 24;
53 	final_mac->ether_addr_octet[3] = (mac_addr & 0xff0000) >> 16;
54 	final_mac->ether_addr_octet[4] = (mac_addr & 0xff00) >> 8;
55 	final_mac->ether_addr_octet[5] = (mac_addr & 0xff);
56 }
57 
58 nxge_status_t
59 nxge_espc_mac_addrs_get(p_nxge_t nxgep)
60 {
61 	nxge_status_t	status = NXGE_OK;
62 	npi_status_t	npi_status = NPI_SUCCESS;
63 	uint8_t		port_num = nxgep->mac.portnum;
64 	npi_handle_t	handle = NXGE_DEV_NPI_HANDLE(nxgep);
65 	uint8_t		mac_addr[ETHERADDRL];
66 
67 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
68 			    "==> nxge_espc_mac_addr_get, port[%d]",
69 			    port_num));
70 
71 	npi_status = npi_espc_mac_addr_get(handle, mac_addr);
72 	if (npi_status != NPI_SUCCESS) {
73 		status = (NXGE_ERROR | npi_status);
74 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
75 				    "nxge_espc_mac_addr_get, port[%d] failed",
76 				    port_num));
77 		goto exit;
78 	}
79 
80 	nxge_espc_get_next_mac_addr(mac_addr, port_num, &nxgep->factaddr);
81 		NXGE_DEBUG_MSG((nxgep, CFG_CTL,
82 			"Got MAC Addr: %2x:%2x:%2x:%2x:%2x%:%2x%c \n",
83 			mac_addr[0], mac_addr[1],
84 			mac_addr[2], mac_addr[3],
85 			mac_addr[4], mac_addr[5]));
86 
87 exit:
88 	NXGE_DEBUG_MSG((nxgep, CFG_CTL, "<== nxge_espc_mac_addr_get, "
89 			"status [0x%x]", status));
90 
91 	return (status);
92 }
93 
94 nxge_status_t
95 nxge_espc_num_macs_get(p_nxge_t nxgep, uint8_t *nmacs)
96 {
97 	nxge_status_t   status = NXGE_OK;
98 	npi_status_t    npi_status = NPI_SUCCESS;
99 	npi_handle_t    handle = NXGE_DEV_NPI_HANDLE(nxgep);
100 	NXGE_DEBUG_MSG((nxgep, CFG_CTL, "==> nxge_espc_num_macs_get"));
101 
102 	npi_status = npi_espc_num_macs_get(handle, nmacs);
103 	if (npi_status != NPI_SUCCESS) {
104 		status = (NXGE_ERROR | npi_status);
105 	}
106 
107 	NXGE_DEBUG_MSG((nxgep, CFG_CTL, "<== nxge_espc_num_macs_get, "
108 		"status [0x%x]", status));
109 
110 	return (status);
111 }
112 
113 nxge_status_t
114 nxge_espc_num_ports_get(p_nxge_t nxgep)
115 {
116 	nxge_status_t	status = NXGE_OK;
117 	npi_status_t	npi_status = NPI_SUCCESS;
118 	npi_handle_t	handle = NXGE_DEV_NPI_HANDLE(nxgep);
119 	uint8_t		nports = 0;
120 	NXGE_DEBUG_MSG((nxgep, CFG_CTL, "==> nxge_espc_num_ports_get"));
121 
122 	npi_status = npi_espc_num_ports_get(handle, &nports);
123 	if (npi_status != NPI_SUCCESS) {
124 		status = (NXGE_ERROR | npi_status);
125 	}
126 	nxgep->nports = nports;
127 	NXGE_DEBUG_MSG((nxgep, CFG_CTL, " nxge_espc_num_ports_get "
128 			"ports [0x%x]", nports));
129 
130 	NXGE_DEBUG_MSG((nxgep, CFG_CTL, "<== nxge_espc_num_ports_get, "
131 			"status [0x%x]", status));
132 
133 	return (status);
134 }
135 
136 nxge_status_t
137 nxge_espc_phy_type_get(p_nxge_t nxgep)
138 {
139 	nxge_status_t	status = NXGE_OK;
140 	npi_status_t	npi_status = NPI_SUCCESS;
141 	npi_handle_t	handle = NXGE_DEV_NPI_HANDLE(nxgep);
142 	uint8_t		port_num = nxgep->mac.portnum;
143 	uint8_t		phy_type;
144 
145 	NXGE_DEBUG_MSG((nxgep, CFG_CTL, "==> nxge_espc_phy_type_get, port[%d]",
146 			port_num));
147 
148 	npi_status = npi_espc_port_phy_type_get(handle, &phy_type,
149 						port_num);
150 	if (npi_status != NPI_SUCCESS) {
151 		status = (NXGE_ERROR | npi_status);
152 		goto exit;
153 	}
154 
155 	switch (phy_type) {
156 	case ESC_PHY_10G_FIBER:
157 		nxgep->mac.portmode = PORT_10G_FIBER;
158 		nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
159 		break;
160 	case ESC_PHY_10G_COPPER:
161 		nxgep->mac.portmode = PORT_10G_COPPER;
162 		nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
163 		break;
164 	case ESC_PHY_1G_FIBER:
165 		nxgep->mac.portmode = PORT_1G_FIBER;
166 		nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR;
167 		break;
168 	case ESC_PHY_1G_COPPER:
169 		nxgep->mac.portmode = PORT_1G_COPPER;
170 		nxgep->statsp->mac_stats.xcvr_inuse = INT_MII_XCVR;
171 		break;
172 	case ESC_PHY_NONE:
173 		status = NXGE_ERROR;
174 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_espc_phy_type_get:"
175 				"No phy type set"));
176 		break;
177 	default:
178 		status = NXGE_ERROR;
179 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_espc_phy_type_get: "
180 				"Unknown phy type [%d]", phy_type));
181 		break;
182 	}
183 
184 exit:
185 
186 	NXGE_DEBUG_MSG((nxgep, CFG_CTL, "<== nxge_espc_phy_type_get, "
187 			"status [0x%x]", status));
188 
189 	return (status);
190 }
191 
192 nxge_status_t
193 nxge_espc_max_frame_sz_get(p_nxge_t nxgep)
194 {
195 	nxge_status_t	status = NXGE_OK;
196 	npi_status_t	npi_status = NPI_SUCCESS;
197 	npi_handle_t	handle = NXGE_DEV_NPI_HANDLE(nxgep);
198 
199 	NXGE_DEBUG_MSG((nxgep, CFG_CTL, "==> nxge_espc_max_frame_sz_get"));
200 
201 	npi_status = npi_espc_max_frame_get(handle, &nxgep->mac.maxframesize);
202 	if (npi_status != NPI_SUCCESS) {
203 		status = (NXGE_ERROR | npi_status);
204 	}
205 
206 	NXGE_DEBUG_MSG((nxgep, CFG_CTL, " nxge_espc_max_frame_sz_get, "
207 			    "status [0x%x]", status));
208 
209 	return (status);
210 }
211 
212 void
213 nxge_vpd_info_get(p_nxge_t nxgep)
214 {
215 	npi_status_t	status;
216 	npi_handle_t	handle = NXGE_DEV_NPI_HANDLE(nxgep);
217 
218 	if ((nxgep->platform_type == P_NEPTUNE_NIU) ||
219 	    (nxgep->platform_type == P_NEPTUNE_MARAMBA_P0) ||
220 	    (nxgep->platform_type == P_NEPTUNE_MARAMBA_P1)) {
221 		nxgep->vpd_info.present = B_FALSE;
222 		return;
223 	}
224 
225 	nxgep->vpd_info.present = B_TRUE;
226 	nxgep->vpd_info.ver_valid = B_FALSE;
227 
228 	MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_cfg_lock);
229 	(void) npi_espc_pio_enable(handle);
230 	status = npi_espc_vpd_info_get(handle, &nxgep->vpd_info,
231 	    NXGE_EROM_LEN);
232 	(void) npi_espc_pio_disable(handle);
233 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_cfg_lock);
234 
235 	if (status != NPI_SUCCESS)
236 		return;
237 
238 	nxge_check_vpd_version(nxgep);
239 	if (!nxgep->vpd_info.ver_valid)
240 		return;
241 
242 	/* Determine the platform type */
243 	if ((strncmp(nxgep->vpd_info.bd_model, NXGE_QGC_LP_BM_STR,
244 	    strlen(NXGE_QGC_LP_BM_STR)) == 0) ||
245 	    (strncmp(nxgep->vpd_info.bd_model, NXGE_QGC_PEM_BM_STR,
246 	    strlen(NXGE_QGC_PEM_BM_STR)) == 0)) {
247 		nxgep->platform_type = P_NEPTUNE_ATLAS_4PORT;
248 	} else if ((strncmp(nxgep->vpd_info.bd_model,
249 	    NXGE_2XGF_LP_BM_STR, strlen(NXGE_2XGF_LP_BM_STR)) == 0) ||
250 	    (strncmp(nxgep->vpd_info.bd_model, NXGE_2XGF_PEM_BM_STR,
251 	    strlen(NXGE_2XGF_PEM_BM_STR)) == 0)) {
252 		nxgep->platform_type = P_NEPTUNE_ATLAS_2PORT;
253 	} else if (strncmp(nxgep->vpd_info.bd_model,
254 	    NXGE_ALONSO_BM_STR, strlen(NXGE_ALONSO_BM_STR)) == 0) {
255 		nxgep->platform_type = P_NEPTUNE_ALONSO;
256 	} else if (strncmp(nxgep->vpd_info.bd_model,
257 	    NXGE_RFEM_BM_STR, strlen(NXGE_RFEM_BM_STR)) == 0) {
258 		nxgep->hot_swappable_phy = B_TRUE;
259 	}
260 
261 	/* If Alonso platform, replace "mif" for the last 2 ports phy-type */
262 	if ((nxgep->platform_type == P_NEPTUNE_ALONSO) &&
263 	    ((nxgep->function_num == 2) || (nxgep->function_num == 3))) {
264 		(void) strcpy(nxgep->vpd_info.phy_type, "mif");
265 	}
266 
267 	/* If ARTM card, replace "mif" for the last 2 ports phy-type */
268 	if ((strncmp(nxgep->vpd_info.bd_model,
269 	    NXGE_ARTM_BM_STR, strlen(NXGE_ARTM_BM_STR)) == 0) &&
270 	    ((nxgep->function_num == 2) || (nxgep->function_num == 3))) {
271 		NXGE_DEBUG_MSG((nxgep, NXGE_ERR_CTL,
272 		    "Replaced phy type as mif"));
273 		(void) strcpy(nxgep->vpd_info.phy_type, "mif");
274 	}
275 }
276 
277 static void
278 nxge_check_vpd_version(p_nxge_t nxgep)
279 {
280 	int		i, j;
281 	const char	*fcode_str = NXGE_FCODE_ID_STR;
282 	int		fcode_str_len = strlen(fcode_str);
283 	char		ver_num_str[NXGE_FCODE_VER_STR_LEN];
284 	char		*ver_num_w;
285 	char		*ver_num_f;
286 	int		ver_num_w_len = 0;
287 	int		ver_num_f_len = 0;
288 	int		ver_w = 0;
289 	int		ver_f = 0;
290 
291 	nxgep->vpd_info.ver_valid = B_FALSE;
292 	ver_num_str[0] = '\0';
293 
294 	for (i = 0; i < NXGE_VPD_VER_LEN; i++) {
295 		if (nxgep->vpd_info.ver[i] == fcode_str[0]) {
296 			if ((i + fcode_str_len + NXGE_FCODE_VER_STR_LEN) >
297 			    NXGE_VPD_VER_LEN)
298 				break;
299 			for (j = 0; j < fcode_str_len; j++, i++) {
300 				if (nxgep->vpd_info.ver[i] != fcode_str[j])
301 					break;
302 			}
303 			if (j < fcode_str_len)
304 				continue;
305 
306 			/* found the Fcode version string */
307 			for (j = 0; j < NXGE_FCODE_VER_STR_LEN; j++, i++) {
308 				ver_num_str[j] = nxgep->vpd_info.ver[i];
309 				if (ver_num_str[j] == ' ')
310 					break;
311 			}
312 			ver_num_str[j] = '\0';
313 			break;
314 		}
315 	}
316 
317 	ver_num_w = ver_num_str;
318 	for (i = 0; i < strlen(ver_num_str); i++) {
319 		if (ver_num_str[i] == '.') {
320 			ver_num_f = &ver_num_str[i + 1];
321 			ver_num_w_len = i;
322 			ver_num_f_len = strlen(ver_num_str) - (i + 1);
323 			break;
324 		}
325 	}
326 
327 	for (i = 0; i < ver_num_w_len; i++) {
328 		ver_w = (ver_w * 10) + (ver_num_w[i] - '0');
329 	}
330 
331 	for (i = 0; i < ver_num_f_len; i++) {
332 		ver_f = (ver_f * 10) + (ver_num_f[i] - '0');
333 	}
334 
335 	if ((ver_w > NXGE_VPD_VALID_VER_W) ||
336 	    (ver_w == NXGE_VPD_VALID_VER_W && ver_f >= NXGE_VPD_VALID_VER_F))
337 		nxgep->vpd_info.ver_valid = B_TRUE;
338 
339 }
340