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