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 2009 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
31static void nxge_check_vpd_version(p_nxge_t nxgep);
32
33void
34nxge_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
56nxge_status_t
57nxge_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
82exit:
83	NXGE_DEBUG_MSG((nxgep, CFG_CTL, "<== nxge_espc_mac_addr_get, "
84	    "status [0x%x]", status));
85
86	return (status);
87}
88
89nxge_status_t
90nxge_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
108nxge_status_t
109nxge_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
131nxge_status_t
132nxge_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
178exit:
179
180	NXGE_DEBUG_MSG((nxgep, CFG_CTL, "<== nxge_espc_phy_type_get, "
181	    "status [0x%x]", status));
182
183	return (status);
184}
185
186nxge_status_t
187nxge_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
206void
207nxge_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		nxgep->platform_type = P_NEPTUNE_GENERIC;
258		nxgep->niu_type = NEPTUNE_2_10GF;
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
277static void
278nxge_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			if (j < NXGE_FCODE_VER_STR_LEN)
313				ver_num_str[j] = '\0';
314			break;
315		}
316	}
317
318	ver_num_w = ver_num_str;
319	for (i = 0; i < strlen(ver_num_str); i++) {
320		if (ver_num_str[i] == '.') {
321			ver_num_f = &ver_num_str[i + 1];
322			ver_num_w_len = i;
323			ver_num_f_len = strlen(ver_num_str) - (i + 1);
324			break;
325		}
326	}
327
328	for (i = 0; i < ver_num_w_len; i++) {
329		ver_w = (ver_w * 10) + (ver_num_w[i] - '0');
330	}
331
332	for (i = 0; i < ver_num_f_len; i++) {
333		ver_f = (ver_f * 10) + (ver_num_f[i] - '0');
334	}
335
336	if ((ver_w > NXGE_VPD_VALID_VER_W) ||
337	    (ver_w == NXGE_VPD_VALID_VER_W && ver_f >= NXGE_VPD_VALID_VER_F))
338		nxgep->vpd_info.ver_valid = B_TRUE;
339
340}
341