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