xref: /titanic_50/usr/src/uts/common/io/nxge/nxge_espc.c (revision 20c794b39650d115e17a15983b6b82e46238cf45)
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 2007 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 	}
257 
258 	/* If Alonso platform, replace "mif" for the last 2 ports phy-type */
259 	if ((nxgep->platform_type == P_NEPTUNE_ALONSO) &&
260 	    ((nxgep->function_num == 2) || (nxgep->function_num == 3))) {
261 		(void) strcpy(nxgep->vpd_info.phy_type, "mif");
262 	}
263 }
264 
265 static void
266 nxge_check_vpd_version(p_nxge_t nxgep)
267 {
268 	int		i, j;
269 	const char	*fcode_str = NXGE_FCODE_ID_STR;
270 	int		fcode_str_len = strlen(fcode_str);
271 	char		ver_num_str[NXGE_FCODE_VER_STR_LEN];
272 	char		*ver_num_w;
273 	char		*ver_num_f;
274 	int		ver_num_w_len = 0;
275 	int		ver_num_f_len = 0;
276 	int		ver_w = 0;
277 	int		ver_f = 0;
278 
279 	nxgep->vpd_info.ver_valid = B_FALSE;
280 	ver_num_str[0] = '\0';
281 
282 	for (i = 0; i < NXGE_VPD_VER_LEN; i++) {
283 		if (nxgep->vpd_info.ver[i] == fcode_str[0]) {
284 			if ((i + fcode_str_len + NXGE_FCODE_VER_STR_LEN) >
285 			    NXGE_VPD_VER_LEN)
286 				break;
287 			for (j = 0; j < fcode_str_len; j++, i++) {
288 				if (nxgep->vpd_info.ver[i] != fcode_str[j])
289 					break;
290 			}
291 			if (j < fcode_str_len)
292 				continue;
293 
294 			/* found the Fcode version string */
295 			for (j = 0; j < NXGE_FCODE_VER_STR_LEN; j++, i++) {
296 				ver_num_str[j] = nxgep->vpd_info.ver[i];
297 				if (ver_num_str[j] == ' ')
298 					break;
299 			}
300 			ver_num_str[j] = '\0';
301 			break;
302 		}
303 	}
304 
305 	ver_num_w = ver_num_str;
306 	for (i = 0; i < strlen(ver_num_str); i++) {
307 		if (ver_num_str[i] == '.') {
308 			ver_num_f = &ver_num_str[i + 1];
309 			ver_num_w_len = i;
310 			ver_num_f_len = strlen(ver_num_str) - (i + 1);
311 			break;
312 		}
313 	}
314 
315 	for (i = 0; i < ver_num_w_len; i++) {
316 		ver_w = (ver_w * 10) + (ver_num_w[i] - '0');
317 	}
318 
319 	for (i = 0; i < ver_num_f_len; i++) {
320 		ver_f = (ver_f * 10) + (ver_num_f[i] - '0');
321 	}
322 
323 	if ((ver_w > NXGE_VPD_VALID_VER_W) ||
324 	    (ver_w == NXGE_VPD_VALID_VER_W && ver_f >= NXGE_VPD_VALID_VER_F))
325 		nxgep->vpd_info.ver_valid = B_TRUE;
326 
327 }
328