xref: /onnv-gate/usr/src/uts/common/io/nxge/npi/npi_espc.c (revision 6929:a596171cbf16)
13859Sml29623 /*
23859Sml29623  * CDDL HEADER START
33859Sml29623  *
43859Sml29623  * The contents of this file are subject to the terms of the
53859Sml29623  * Common Development and Distribution License (the "License").
63859Sml29623  * You may not use this file except in compliance with the License.
73859Sml29623  *
83859Sml29623  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
93859Sml29623  * or http://www.opensolaris.org/os/licensing.
103859Sml29623  * See the License for the specific language governing permissions
113859Sml29623  * and limitations under the License.
123859Sml29623  *
133859Sml29623  * When distributing Covered Code, include this CDDL HEADER in each
143859Sml29623  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
153859Sml29623  * If applicable, add the following below this CDDL HEADER, with the
163859Sml29623  * fields enclosed by brackets "[]" replaced with your own identifying
173859Sml29623  * information: Portions Copyright [yyyy] [name of copyright owner]
183859Sml29623  *
193859Sml29623  * CDDL HEADER END
203859Sml29623  */
213859Sml29623 /*
22*6929Smisaki  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
233859Sml29623  * Use is subject to license terms.
243859Sml29623  */
253859Sml29623 
263859Sml29623 #pragma ident	"%Z%%M%	%I%	%E% SMI"
273859Sml29623 
283859Sml29623 #include <npi_espc.h>
293859Sml29623 #include <nxge_espc.h>
303859Sml29623 
314185Sspeer static int npi_vpd_read_prop(npi_handle_t handle, uint32_t ep,
324185Sspeer 		const char *prop, int len, char *val);
334185Sspeer 
343859Sml29623 npi_status_t
npi_espc_pio_enable(npi_handle_t handle)353859Sml29623 npi_espc_pio_enable(npi_handle_t handle)
363859Sml29623 {
373859Sml29623 	NXGE_REG_WR64(handle, ESPC_REG_ADDR(ESPC_PIO_EN_REG), 0x1);
383859Sml29623 	return (NPI_SUCCESS);
393859Sml29623 }
403859Sml29623 
413859Sml29623 npi_status_t
npi_espc_pio_disable(npi_handle_t handle)423859Sml29623 npi_espc_pio_disable(npi_handle_t handle)
433859Sml29623 {
444600Ssbehera 	NXGE_REG_WR64(handle, ESPC_REG_ADDR(ESPC_PIO_EN_REG), 0);
453859Sml29623 	return (NPI_SUCCESS);
463859Sml29623 }
473859Sml29623 
483859Sml29623 npi_status_t
npi_espc_eeprom_entry(npi_handle_t handle,io_op_t op,uint32_t addr,uint8_t * data)493859Sml29623 npi_espc_eeprom_entry(npi_handle_t handle, io_op_t op, uint32_t addr,
503859Sml29623 			uint8_t *data)
513859Sml29623 {
523859Sml29623 	uint64_t val = 0;
533859Sml29623 
543859Sml29623 	if ((addr & ~EPC_EEPROM_ADDR_BITS) != 0) {
553859Sml29623 		NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
56*6929Smisaki 		    " npi_espc_eerprom_entry"
57*6929Smisaki 		    " Invalid input addr <0x%x>\n",
58*6929Smisaki 		    addr));
593859Sml29623 		return (NPI_FAILURE | NPI_ESPC_EEPROM_ADDR_INVALID);
603859Sml29623 	}
613859Sml29623 
623859Sml29623 	switch (op) {
633859Sml29623 	case OP_SET:
643859Sml29623 		val = EPC_WRITE_INITIATE | (addr << EPC_EEPROM_ADDR_SHIFT) |
65*6929Smisaki 		    *data;
663859Sml29623 		NXGE_REG_WR64(handle, ESPC_REG_ADDR(ESPC_PIO_STATUS_REG), val);
673859Sml29623 		EPC_WAIT_RW_COMP(handle, &val, EPC_WRITE_COMPLETE);
683859Sml29623 		if ((val & EPC_WRITE_COMPLETE) == 0) {
693859Sml29623 			NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
70*6929Smisaki 			    " npi_espc_eeprom_entry"
71*6929Smisaki 			    " HW Error: EEPROM_WR <0x%x>\n",
72*6929Smisaki 			    val));
733859Sml29623 			return (NPI_FAILURE | NPI_ESPC_EEPROM_WRITE_FAILED);
743859Sml29623 		}
753859Sml29623 		break;
763859Sml29623 	case OP_GET:
773859Sml29623 		val = EPC_READ_INITIATE | (addr << EPC_EEPROM_ADDR_SHIFT);
783859Sml29623 		NXGE_REG_WR64(handle, ESPC_REG_ADDR(ESPC_PIO_STATUS_REG), val);
793859Sml29623 		EPC_WAIT_RW_COMP(handle, &val, EPC_READ_COMPLETE);
803859Sml29623 		if ((val & EPC_READ_COMPLETE) == 0) {
813859Sml29623 			NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
82*6929Smisaki 			    " npi_espc_eeprom_entry"
83*6929Smisaki 			    " HW Error: EEPROM_RD <0x%x>",
84*6929Smisaki 			    val));
853859Sml29623 			return (NPI_FAILURE | NPI_ESPC_EEPROM_READ_FAILED);
863859Sml29623 		}
873859Sml29623 		NXGE_REG_RD64(handle, ESPC_REG_ADDR(ESPC_PIO_STATUS_REG), &val);
884185Sspeer 		/*
894185Sspeer 		 * Workaround for synchronization issues - do a second PIO
904185Sspeer 		 */
914185Sspeer 		val = EPC_READ_INITIATE | (addr << EPC_EEPROM_ADDR_SHIFT);
924185Sspeer 		NXGE_REG_WR64(handle, ESPC_REG_ADDR(ESPC_PIO_STATUS_REG), val);
934185Sspeer 		EPC_WAIT_RW_COMP(handle, &val, EPC_READ_COMPLETE);
944185Sspeer 		if ((val & EPC_READ_COMPLETE) == 0) {
954185Sspeer 			NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
964185Sspeer 			    " npi_espc_eeprom_entry HW Error: "
974185Sspeer 			    "EEPROM_RD <0x%x>", val));
984185Sspeer 			return (NPI_FAILURE | NPI_ESPC_EEPROM_READ_FAILED);
994185Sspeer 		}
1004185Sspeer 		NXGE_REG_RD64(handle, ESPC_REG_ADDR(ESPC_PIO_STATUS_REG), &val);
1013859Sml29623 		*data = val & EPC_EEPROM_DATA_MASK;
1023859Sml29623 		break;
1033859Sml29623 	default:
1043859Sml29623 		NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
105*6929Smisaki 		    " npi_espc_eeprom_entry"
106*6929Smisaki 		    " Invalid Input addr <0x%x>\n", addr));
1073859Sml29623 		return (NPI_FAILURE | NPI_ESPC_OPCODE_INVALID);
1083859Sml29623 	}
1093859Sml29623 
1103859Sml29623 	return (NPI_SUCCESS);
1113859Sml29623 }
1123859Sml29623 
1133859Sml29623 npi_status_t
npi_espc_mac_addr_get(npi_handle_t handle,uint8_t * data)1143859Sml29623 npi_espc_mac_addr_get(npi_handle_t handle, uint8_t *data)
1153859Sml29623 {
1163859Sml29623 	mac_addr_0_t mac0;
1173859Sml29623 	mac_addr_1_t mac1;
1183859Sml29623 
1193859Sml29623 	NXGE_REG_RD64(handle, ESPC_MAC_ADDR_0, &mac0.value);
1203859Sml29623 	data[0] = mac0.bits.w0.byte0;
1213859Sml29623 	data[1] = mac0.bits.w0.byte1;
1223859Sml29623 	data[2] = mac0.bits.w0.byte2;
1233859Sml29623 	data[3] = mac0.bits.w0.byte3;
1243859Sml29623 
1253859Sml29623 	NXGE_REG_RD64(handle, ESPC_MAC_ADDR_1, &mac1.value);
1263859Sml29623 	data[4] = mac1.bits.w0.byte4;
1273859Sml29623 	data[5] = mac1.bits.w0.byte5;
1283859Sml29623 
1293859Sml29623 	return (NPI_SUCCESS);
1303859Sml29623 }
1313859Sml29623 
1323859Sml29623 npi_status_t
npi_espc_num_ports_get(npi_handle_t handle,uint8_t * data)1333859Sml29623 npi_espc_num_ports_get(npi_handle_t handle, uint8_t *data)
1343859Sml29623 {
1353859Sml29623 	uint64_t val = 0;
1363859Sml29623 
1373859Sml29623 	NXGE_REG_RD64(handle, ESPC_NUM_PORTS_MACS, &val);
1383859Sml29623 	val &= NUM_PORTS_MASK;
1393859Sml29623 	*data = (uint8_t)val;
1403859Sml29623 
1413859Sml29623 	return (NPI_SUCCESS);
1423859Sml29623 }
1433859Sml29623 
1443859Sml29623 npi_status_t
npi_espc_num_macs_get(npi_handle_t handle,uint8_t * data)1453859Sml29623 npi_espc_num_macs_get(npi_handle_t handle, uint8_t *data)
1463859Sml29623 {
1473859Sml29623 	uint64_t val = 0;
1483859Sml29623 
1493859Sml29623 	NXGE_REG_RD64(handle, ESPC_NUM_PORTS_MACS, &val);
1503859Sml29623 	val &= NUM_MAC_ADDRS_MASK;
1513859Sml29623 	val = (val >> NUM_MAC_ADDRS_SHIFT);
1523859Sml29623 	*data = (uint8_t)val;
1533859Sml29623 
1543859Sml29623 	return (NPI_SUCCESS);
1553859Sml29623 }
1563859Sml29623 
1573859Sml29623 npi_status_t
npi_espc_model_str_get(npi_handle_t handle,char * data)1583859Sml29623 npi_espc_model_str_get(npi_handle_t handle, char *data)
1593859Sml29623 {
1603859Sml29623 	uint64_t val = 0;
1613859Sml29623 	uint16_t str_len;
1623859Sml29623 	int i, j;
1633859Sml29623 
1643859Sml29623 	NXGE_REG_RD64(handle, ESPC_MOD_STR_LEN, &val);
1653859Sml29623 	val &= MOD_STR_LEN_MASK;
1663859Sml29623 	str_len = (uint8_t)val;
1673859Sml29623 
1683859Sml29623 	if (str_len > MAX_MOD_STR_LEN) {
1693859Sml29623 		NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
170*6929Smisaki 		    " npi_espc_model_str_get"
171*6929Smisaki 		    " Model string length %d exceeds max %d\n",
172*6929Smisaki 		    str_len, MAX_MOD_STR_LEN));
1733859Sml29623 		return (NPI_FAILURE | NPI_ESPC_STR_LEN_INVALID);
1743859Sml29623 	}
1753859Sml29623 
1763859Sml29623 	/*
1773859Sml29623 	 * Might have to reverse the order depending on how the string
1783859Sml29623 	 * is written.
1793859Sml29623 	 */
1803859Sml29623 	for (i = 0, j = 0; i < str_len; j++) {
1813859Sml29623 		NXGE_REG_RD64(handle, ESPC_MOD_STR(j), &val);
1823859Sml29623 		data[i++] = ((char *)&val)[3];
1833859Sml29623 		data[i++] = ((char *)&val)[2];
1843859Sml29623 		data[i++] = ((char *)&val)[1];
1853859Sml29623 		data[i++] = ((char *)&val)[0];
1863859Sml29623 	}
1873859Sml29623 
1883859Sml29623 	data[str_len] = '\0';
1893859Sml29623 
1903859Sml29623 	return (NPI_SUCCESS);
1913859Sml29623 }
1923859Sml29623 
1933859Sml29623 npi_status_t
npi_espc_bd_model_str_get(npi_handle_t handle,char * data)1943859Sml29623 npi_espc_bd_model_str_get(npi_handle_t handle, char *data)
1953859Sml29623 {
1963859Sml29623 	uint64_t val = 0;
1973859Sml29623 	uint16_t str_len;
1983859Sml29623 	int i, j;
1993859Sml29623 
2003859Sml29623 	NXGE_REG_RD64(handle, ESPC_BD_MOD_STR_LEN, &val);
2013859Sml29623 	val &= BD_MOD_STR_LEN_MASK;
2023859Sml29623 	str_len = (uint8_t)val;
2033859Sml29623 
2043859Sml29623 	if (str_len > MAX_BD_MOD_STR_LEN) {
2053859Sml29623 		NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
206*6929Smisaki 		    " npi_espc_model_str_get"
207*6929Smisaki 		    " Board Model string length %d "
208*6929Smisaki 		    "exceeds max %d\n",
209*6929Smisaki 		    str_len, MAX_BD_MOD_STR_LEN));
2103859Sml29623 		return (NPI_FAILURE | NPI_ESPC_STR_LEN_INVALID);
2113859Sml29623 	}
2123859Sml29623 
2133859Sml29623 	/*
2143859Sml29623 	 * Might have to reverse the order depending on how the string
2153859Sml29623 	 * is written.
2163859Sml29623 	 */
2173859Sml29623 	for (i = 0, j = 0; i < str_len; j++) {
2183859Sml29623 		NXGE_REG_RD64(handle, ESPC_BD_MOD_STR(j), &val);
2193859Sml29623 		data[i++] = ((char *)&val)[3];
2203859Sml29623 		data[i++] = ((char *)&val)[2];
2213859Sml29623 		data[i++] = ((char *)&val)[1];
2223859Sml29623 		data[i++] = ((char *)&val)[0];
2233859Sml29623 	}
2243859Sml29623 
2253859Sml29623 	data[str_len] = '\0';
2263859Sml29623 
2273859Sml29623 	return (NPI_SUCCESS);
2283859Sml29623 }
2293859Sml29623 
2303859Sml29623 npi_status_t
npi_espc_phy_type_get(npi_handle_t handle,uint8_t * data)2313859Sml29623 npi_espc_phy_type_get(npi_handle_t handle, uint8_t *data)
2323859Sml29623 {
2333859Sml29623 	phy_type_t	phy;
2343859Sml29623 
2353859Sml29623 	NXGE_REG_RD64(handle, ESPC_PHY_TYPE, &phy.value);
2363859Sml29623 	data[0] = phy.bits.w0.pt0_phy_type;
2373859Sml29623 	data[1] = phy.bits.w0.pt1_phy_type;
2383859Sml29623 	data[2] = phy.bits.w0.pt2_phy_type;
2393859Sml29623 	data[3] = phy.bits.w0.pt3_phy_type;
2403859Sml29623 
2413859Sml29623 	return (NPI_SUCCESS);
2423859Sml29623 }
2433859Sml29623 
2443859Sml29623 npi_status_t
npi_espc_port_phy_type_get(npi_handle_t handle,uint8_t * data,uint8_t portn)2453859Sml29623 npi_espc_port_phy_type_get(npi_handle_t handle, uint8_t *data, uint8_t portn)
2463859Sml29623 {
2473859Sml29623 	phy_type_t	phy;
2483859Sml29623 
2493859Sml29623 	ASSERT(IS_PORT_NUM_VALID(portn));
2503859Sml29623 
2513859Sml29623 	NXGE_REG_RD64(handle, ESPC_PHY_TYPE, &phy.value);
2523859Sml29623 	switch (portn) {
2533859Sml29623 	case 0:
2543859Sml29623 		*data = phy.bits.w0.pt0_phy_type;
2553859Sml29623 		break;
2563859Sml29623 	case 1:
2573859Sml29623 		*data = phy.bits.w0.pt1_phy_type;
2583859Sml29623 		break;
2593859Sml29623 	case 2:
2603859Sml29623 		*data = phy.bits.w0.pt2_phy_type;
2613859Sml29623 		break;
2623859Sml29623 	case 3:
2633859Sml29623 		*data = phy.bits.w0.pt3_phy_type;
2643859Sml29623 		break;
2653859Sml29623 	default:
2663859Sml29623 		NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
267*6929Smisaki 		    " npi_espc_port_phy_type_get"
268*6929Smisaki 		    " Invalid Input: portn <%d>",
269*6929Smisaki 		    portn));
2703859Sml29623 		return (NPI_FAILURE | NPI_ESPC_PORT_INVALID);
2713859Sml29623 	}
2723859Sml29623 
2733859Sml29623 	return (NPI_SUCCESS);
2743859Sml29623 }
2753859Sml29623 
2763859Sml29623 npi_status_t
npi_espc_max_frame_get(npi_handle_t handle,uint16_t * data)2773859Sml29623 npi_espc_max_frame_get(npi_handle_t handle, uint16_t *data)
2783859Sml29623 {
2793859Sml29623 	uint64_t val = 0;
2803859Sml29623 
2813859Sml29623 	NXGE_REG_RD64(handle, ESPC_MAX_FM_SZ, &val);
2823859Sml29623 	val &= MAX_FM_SZ_MASK;
2833859Sml29623 	*data = (uint8_t)val;
2843859Sml29623 
2853859Sml29623 	return (NPI_SUCCESS);
2863859Sml29623 }
2873859Sml29623 
2883859Sml29623 npi_status_t
npi_espc_version_get(npi_handle_t handle,uint16_t * data)2893859Sml29623 npi_espc_version_get(npi_handle_t handle, uint16_t *data)
2903859Sml29623 {
2913859Sml29623 	uint64_t val = 0;
2923859Sml29623 
2933859Sml29623 	NXGE_REG_RD64(handle, ESPC_VER_IMGSZ, &val);
2943859Sml29623 	val &= VER_NUM_MASK;
2953859Sml29623 	*data = (uint8_t)val;
2963859Sml29623 
2973859Sml29623 	return (NPI_SUCCESS);
2983859Sml29623 }
2993859Sml29623 
3003859Sml29623 npi_status_t
npi_espc_img_sz_get(npi_handle_t handle,uint16_t * data)3013859Sml29623 npi_espc_img_sz_get(npi_handle_t handle, uint16_t *data)
3023859Sml29623 {
3033859Sml29623 	uint64_t val = 0;
3043859Sml29623 
3053859Sml29623 	NXGE_REG_RD64(handle, ESPC_VER_IMGSZ, &val);
3063859Sml29623 	val &= IMG_SZ_MASK;
3073859Sml29623 	val = val >> IMG_SZ_SHIFT;
3083859Sml29623 	*data = (uint8_t)val;
3093859Sml29623 
3103859Sml29623 	return (NPI_SUCCESS);
3113859Sml29623 }
3123859Sml29623 
3133859Sml29623 npi_status_t
npi_espc_chksum_get(npi_handle_t handle,uint8_t * data)3143859Sml29623 npi_espc_chksum_get(npi_handle_t handle, uint8_t *data)
3153859Sml29623 {
3163859Sml29623 	uint64_t val = 0;
3173859Sml29623 
3183859Sml29623 	NXGE_REG_RD64(handle, ESPC_CHKSUM, &val);
3193859Sml29623 	val &= CHKSUM_MASK;
3203859Sml29623 	*data = (uint8_t)val;
3213859Sml29623 
3223859Sml29623 	return (NPI_SUCCESS);
3233859Sml29623 }
3243859Sml29623 
3253859Sml29623 npi_status_t
npi_espc_intr_num_get(npi_handle_t handle,uint8_t * data)3263859Sml29623 npi_espc_intr_num_get(npi_handle_t handle, uint8_t *data)
3273859Sml29623 {
3283859Sml29623 	intr_num_t	intr;
3293859Sml29623 
3303859Sml29623 	NXGE_REG_RD64(handle, ESPC_INTR_NUM, &intr.value);
3313859Sml29623 	data[0] = intr.bits.w0.pt0_intr_num;
3323859Sml29623 	data[1] = intr.bits.w0.pt1_intr_num;
3333859Sml29623 	data[2] = intr.bits.w0.pt2_intr_num;
3343859Sml29623 	data[3] = intr.bits.w0.pt3_intr_num;
3353859Sml29623 
3363859Sml29623 	return (NPI_SUCCESS);
3373859Sml29623 }
3383859Sml29623 
3393859Sml29623 void
npi_espc_dump(npi_handle_t handle)3403859Sml29623 npi_espc_dump(npi_handle_t handle)
3413859Sml29623 {
3423859Sml29623 	int i;
3433859Sml29623 	uint64_t val = 0;
3443859Sml29623 
3453859Sml29623 	NPI_REG_DUMP_MSG((handle.function, NPI_REG_CTL,
346*6929Smisaki 	    "Dumping SEEPROM registers directly:\n\n"));
3473859Sml29623 
3483859Sml29623 	for (i = 0; i < 23; i++) {
3493859Sml29623 		NXGE_REG_RD64(handle, ESPC_NCR_REGN(i), &val);
3503859Sml29623 		NPI_REG_DUMP_MSG((handle.function, NPI_REG_CTL,
351*6929Smisaki 		    "reg[%d]      0x%llx\n",
352*6929Smisaki 		    i, val & 0xffffffff));
3533859Sml29623 	}
3543859Sml29623 
3553859Sml29623 	NPI_REG_DUMP_MSG((handle.function, NPI_REG_CTL, "\n\n"));
3563859Sml29623 }
3573859Sml29623 
3583859Sml29623 uint32_t
npi_espc_reg_get(npi_handle_t handle,int reg_idx)3593859Sml29623 npi_espc_reg_get(npi_handle_t handle, int reg_idx)
3603859Sml29623 {
3613859Sml29623 	uint64_t val = 0;
3623859Sml29623 	uint32_t reg_val = 0;
3633859Sml29623 
3643859Sml29623 	NXGE_REG_RD64(handle, ESPC_NCR_REGN(reg_idx), &val);
3653859Sml29623 	reg_val = val & 0xffffffff;
3663859Sml29623 
3673859Sml29623 	return (reg_val);
3683859Sml29623 }
3694185Sspeer 
vpd_rd(npi_handle_t handle,uint32_t addr)3704185Sspeer static inline uint8_t vpd_rd(npi_handle_t handle, uint32_t addr)
3714185Sspeer {
3724185Sspeer 	uint8_t data = 0;
3734185Sspeer 
3744185Sspeer 	if (npi_espc_eeprom_entry(handle, OP_GET, addr, &data) != NPI_SUCCESS)
3754185Sspeer 		data = 0;
3764185Sspeer 	return (data);
3774185Sspeer }
3784185Sspeer 
3794185Sspeer npi_status_t
npi_espc_vpd_info_get(npi_handle_t handle,p_npi_vpd_info_t vpdp,uint32_t rom_len)3804185Sspeer npi_espc_vpd_info_get(npi_handle_t handle, p_npi_vpd_info_t vpdp,
3814185Sspeer 		uint32_t rom_len)
3824185Sspeer {
3834185Sspeer 	int		i, len;
3844185Sspeer 	uint32_t	base = 0, kstart = 0, ep, end;
3854185Sspeer 	uint8_t		fd_flags = 0;
3864185Sspeer 
3874185Sspeer 	/* Fill the vpd_info struct with invalid vals */
3884185Sspeer 	(void) strcpy(vpdp->model, "\0");
3894185Sspeer 	(void) strcpy(vpdp->bd_model, "\0");
3904185Sspeer 	(void) strcpy(vpdp->phy_type, "\0");
3914185Sspeer 	(void) strcpy(vpdp->ver, "\0");
3924185Sspeer 	vpdp->num_macs = 0;
3934185Sspeer 	for (i = 0; i < ETHERADDRL; i++) {
3944185Sspeer 		vpdp->mac_addr[i] = 0;
3954185Sspeer 	}
3964185Sspeer 
3974185Sspeer 	ep = 0;
3984185Sspeer 	end = ep + rom_len;
3994185Sspeer 
4004185Sspeer 	/* go through the images till OBP image type is found */
4014185Sspeer 	while (ep < end) {
4024185Sspeer 		base = ep;
4034185Sspeer 		/* check for expansion rom header signature */
4044185Sspeer 		if (vpd_rd(handle, ep) != 0x55 ||
4054185Sspeer 		    vpd_rd(handle, ep + 1) != 0xaa) {
4064185Sspeer 			NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
4074185Sspeer 			    "npi_espc_vpd_info_get: expansion rom image "
4084185Sspeer 			    "not found, 0x%x [0x%x 0x%x]", ep,
4094185Sspeer 			    vpd_rd(handle, ep), vpd_rd(handle, ep + 1)));
4104185Sspeer 			goto vpd_info_err;
4114185Sspeer 		}
4124185Sspeer 		/* go to the beginning of the PCI data struct of this image */
4134185Sspeer 		ep = ep + 23;
4144185Sspeer 		ep = base + ((vpd_rd(handle, ep) << 8) |
4154185Sspeer 		    (vpd_rd(handle, ep + 1)));
4164185Sspeer 		/* check for PCI data struct signature "PCIR" */
4174185Sspeer 		if ((vpd_rd(handle, ep) != 0x50) ||
4184185Sspeer 		    (vpd_rd(handle, ep + 1) != 0x43) ||
4194185Sspeer 		    (vpd_rd(handle, ep + 2) != 0x49) ||
4204185Sspeer 		    (vpd_rd(handle, ep + 3) != 0x52)) {
4214185Sspeer 			NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
4224185Sspeer 			    "npi_espc_vpd_info_get: PCIR sig not found"));
4234185Sspeer 			goto vpd_info_err;
4244185Sspeer 		}
4254185Sspeer 		/* check for image type OBP */
4264185Sspeer 		if (vpd_rd(handle, ep + 20) != 0x01) {
4274185Sspeer 			/* go to the next image */
4284185Sspeer 			ep = base + ((vpd_rd(handle, base + 2)) * 512);
4294185Sspeer 			continue;
4304185Sspeer 		}
4314185Sspeer 		/* find the beginning of the VPD data */
4324185Sspeer 		base = base + (vpd_rd(handle, ep + 8) |
4334185Sspeer 		    (vpd_rd(handle, ep + 9) << 8));
4344185Sspeer 		break;
4354185Sspeer 	}
4364185Sspeer 
4374185Sspeer 	/* check first byte of identifier string tag */
4384185Sspeer 	if (!base || (vpd_rd(handle, base + 0) != 0x82)) {
4394185Sspeer 		NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
4404185Sspeer 		    "npi_espc_vpd_info_get: Could not find VPD!!"));
4414185Sspeer 		goto vpd_info_err;
4424185Sspeer 	}
4434185Sspeer 
4444185Sspeer 	/*
4454185Sspeer 	 * skip over the ID string descriptor to go to the read-only VPD
4464185Sspeer 	 * keywords list.
4474185Sspeer 	 */
4484185Sspeer 	i = (vpd_rd(handle, base + 1) |
4494185Sspeer 	    (vpd_rd(handle, base + 2) << 8)) + 3;
4504185Sspeer 
4514185Sspeer 	while (i < EXPANSION_ROM_SIZE) {
4524185Sspeer 		if (vpd_rd(handle, base + i) != 0x90) { /* no vpd found */
4534185Sspeer 			NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
4544185Sspeer 			    "nxge_get_vpd_info: Could not find "
4554185Sspeer 			    "VPD ReadOnly list!! [0x%x] %d",
4564185Sspeer 			    vpd_rd(handle, base + i), i));
4574185Sspeer 			goto vpd_info_err;
4584185Sspeer 		}
4594185Sspeer 
4604185Sspeer 		/* found a vpd read-only list, get its length */
4614185Sspeer 		len = vpd_rd(handle, base + i + 1) |
4624185Sspeer 		    (vpd_rd(handle, base + i + 2) << 8);
4634185Sspeer 
4644185Sspeer 		/* extract keywords */
4654185Sspeer 		kstart = base + i + 3;
4664185Sspeer 		ep = kstart;
4674185Sspeer 		/*
4684185Sspeer 		 * Each keyword field is as follows:
4694185Sspeer 		 * 2 bytes keyword in the form of "Zx" where x = 0,1,2....
4704185Sspeer 		 * 1 byte keyword data field length - klen
4714185Sspeer 		 * Now the actual keyword data field:
4724185Sspeer 		 * 	1 byte VPD property instance, 'M' / 'I'
4734185Sspeer 		 * 	2 bytes
4744185Sspeer 		 * 	1 byte VPD property data type, 'B' / 'S'
4754185Sspeer 		 * 	1 byte VPD property value length - n
4764185Sspeer 		 * 	Actual property string, length (klen - n - 5) bytes
4774185Sspeer 		 * 	Actual property value, length n bytes
4784185Sspeer 		 */
4794185Sspeer 		while ((ep - kstart) < len) {
4804185Sspeer 			int klen = vpd_rd(handle, ep + 2);
4814185Sspeer 			int dlen;
4824185Sspeer 			char type;
4834185Sspeer 
4844185Sspeer 			ep += 3;
4854185Sspeer 
4864185Sspeer 			/*
4874185Sspeer 			 * Look for the following properties:
4884185Sspeer 			 *
4894185Sspeer 			 * local-mac-address:
4904185Sspeer 			 * -- VPD Instance 'I'
4914185Sspeer 			 * -- VPD Type String 'B'
4924185Sspeer 			 * -- property string == local-mac-address
4934185Sspeer 			 *
4944185Sspeer 			 * model:
4954185Sspeer 			 * -- VPD Instance 'M'
4964185Sspeer 			 * -- VPD Type String 'S'
4974185Sspeer 			 * -- property string == model
4984185Sspeer 			 *
4994185Sspeer 			 * board-model:
5004185Sspeer 			 * -- VPD Instance 'M'
5014185Sspeer 			 * -- VPD Type String 'S'
5024185Sspeer 			 * -- property string == board-model
5034185Sspeer 			 *
5044185Sspeer 			 * num-mac-addresses:
5054185Sspeer 			 * -- VPD Instance 'I'
5064185Sspeer 			 * -- VPD Type String 'B'
5074185Sspeer 			 * -- property string == num-mac-addresses
5084185Sspeer 			 *
5094185Sspeer 			 * phy-type:
5104185Sspeer 			 * -- VPD Instance 'I'
5114185Sspeer 			 * -- VPD Type String 'S'
5124185Sspeer 			 * -- property string == phy-type
5134185Sspeer 			 *
5144185Sspeer 			 * version:
5154185Sspeer 			 * -- VPD Instance 'M'
5164185Sspeer 			 * -- VPD Type String 'S'
5174185Sspeer 			 * -- property string == version
5184185Sspeer 			 */
5194185Sspeer 			if (vpd_rd(handle, ep) == 'M') {
5204185Sspeer 				type = vpd_rd(handle, ep + 3);
5214185Sspeer 				if (type == 'S') {
5224185Sspeer 					dlen = vpd_rd(handle, ep + 4);
5234185Sspeer 					if (npi_vpd_read_prop(handle, ep + 5,
5244185Sspeer 					    "model", dlen, vpdp->model)) {
5254185Sspeer 						fd_flags |= FD_MODEL;
5264185Sspeer 						goto next;
5274185Sspeer 					}
5284185Sspeer 					if (npi_vpd_read_prop(handle, ep + 5,
5294185Sspeer 					    "board-model", dlen,
5304185Sspeer 					    vpdp->bd_model)) {
5314185Sspeer 						fd_flags |= FD_BD_MODEL;
5324185Sspeer 						goto next;
5334185Sspeer 					}
5344185Sspeer 					if (npi_vpd_read_prop(handle, ep + 5,
5354185Sspeer 					    "version", dlen, vpdp->ver)) {
5364185Sspeer 						fd_flags |= FD_FW_VERSION;
5374185Sspeer 						goto next;
5384185Sspeer 					}
5394185Sspeer 				}
5404185Sspeer 				goto next;
5414185Sspeer 			} else if (vpd_rd(handle, ep) == 'I') {
5424185Sspeer 				type = vpd_rd(handle, ep + 3);
5434185Sspeer 				if (type == 'B') {
5444185Sspeer 					dlen = vpd_rd(handle, ep + 4);
5454185Sspeer 					if (npi_vpd_read_prop(handle, ep + 5,
5464185Sspeer 					    "local-mac-address", dlen,
5474185Sspeer 					    (char *)(vpdp->mac_addr))) {
5484185Sspeer 						fd_flags |= FD_MAC_ADDR;
5494185Sspeer 						goto next;
5504185Sspeer 					}
5514185Sspeer 					if (npi_vpd_read_prop(handle, ep + 5,
5524185Sspeer 					    "num-mac-addresses", dlen,
5534185Sspeer 					    (char *)&(vpdp->num_macs))) {
5544185Sspeer 						fd_flags |= FD_NUM_MACS;
5554185Sspeer 					}
5564185Sspeer 				} else if (type == 'S') {
5574185Sspeer 					dlen = vpd_rd(handle, ep + 4);
5584185Sspeer 					if (npi_vpd_read_prop(handle, ep + 5,
5594185Sspeer 					    "phy-type", dlen,
5604185Sspeer 					    vpdp->phy_type)) {
5614185Sspeer 						fd_flags |= FD_PHY_TYPE;
5624185Sspeer 					}
5634185Sspeer 				}
5644185Sspeer 				goto next;
5654185Sspeer 			} else {
5664185Sspeer 				goto vpd_info_err;
5674185Sspeer 			}
5684185Sspeer 
5694185Sspeer next:
5704185Sspeer 			if ((fd_flags & FD_ALL) == FD_ALL)
5714185Sspeer 				goto vpd_success;
5724185Sspeer 			ep += klen;
5734185Sspeer 		}
5744185Sspeer 		i += len + 3;
5754185Sspeer 	}
5764185Sspeer 
5774185Sspeer vpd_success:
5784185Sspeer 	return (NPI_SUCCESS);
5794185Sspeer 
5804185Sspeer vpd_info_err:
5814185Sspeer 	return (NPI_FAILURE);
5824185Sspeer }
5834185Sspeer 
5844185Sspeer static int
npi_vpd_read_prop(npi_handle_t handle,uint32_t ep,const char * prop,int len,char * val)5854185Sspeer npi_vpd_read_prop(npi_handle_t handle, uint32_t ep, const char *prop, int len,
5864185Sspeer 		char *val)
5874185Sspeer {
5884185Sspeer 	int prop_len =  strlen(prop) + 1;
5894185Sspeer 	int i;
5904185Sspeer 
5914185Sspeer 	for (i = 0; i < prop_len; i++) {
5924185Sspeer 		if (vpd_rd(handle, ep + i) != prop[i])
5934185Sspeer 			return (0);
5944185Sspeer 	}
5954185Sspeer 
5964185Sspeer 	ep += prop_len;
5974185Sspeer 
5984185Sspeer 	for (i = 0; i < len; i++)
5994185Sspeer 		val[i] = vpd_rd(handle, ep + i);
6004185Sspeer 	return (1);
6014185Sspeer }
602