144961713Sgirish /*
244961713Sgirish  * CDDL HEADER START
344961713Sgirish  *
444961713Sgirish  * The contents of this file are subject to the terms of the
544961713Sgirish  * Common Development and Distribution License (the "License").
644961713Sgirish  * You may not use this file except in compliance with the License.
744961713Sgirish  *
844961713Sgirish  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
944961713Sgirish  * or http://www.opensolaris.org/os/licensing.
1044961713Sgirish  * See the License for the specific language governing permissions
1144961713Sgirish  * and limitations under the License.
1244961713Sgirish  *
1344961713Sgirish  * When distributing Covered Code, include this CDDL HEADER in each
1444961713Sgirish  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1544961713Sgirish  * If applicable, add the following below this CDDL HEADER, with the
1644961713Sgirish  * fields enclosed by brackets "[]" replaced with your own identifying
1744961713Sgirish  * information: Portions Copyright [yyyy] [name of copyright owner]
1844961713Sgirish  *
1944961713Sgirish  * CDDL HEADER END
2044961713Sgirish  */
2144961713Sgirish /*
22*52ccf843Smisaki  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
2344961713Sgirish  * Use is subject to license terms.
2444961713Sgirish  */
2544961713Sgirish 
2644961713Sgirish #include <npi_espc.h>
2744961713Sgirish #include <nxge_espc.h>
2844961713Sgirish 
2956d930aeSspeer static int npi_vpd_read_prop(npi_handle_t handle, uint32_t ep,
3056d930aeSspeer 		const char *prop, int len, char *val);
3156d930aeSspeer 
3244961713Sgirish npi_status_t
npi_espc_pio_enable(npi_handle_t handle)3344961713Sgirish npi_espc_pio_enable(npi_handle_t handle)
3444961713Sgirish {
3544961713Sgirish 	NXGE_REG_WR64(handle, ESPC_REG_ADDR(ESPC_PIO_EN_REG), 0x1);
3644961713Sgirish 	return (NPI_SUCCESS);
3744961713Sgirish }
3844961713Sgirish 
3944961713Sgirish npi_status_t
npi_espc_pio_disable(npi_handle_t handle)4044961713Sgirish npi_espc_pio_disable(npi_handle_t handle)
4144961713Sgirish {
422bd43bc7Ssbehera 	NXGE_REG_WR64(handle, ESPC_REG_ADDR(ESPC_PIO_EN_REG), 0);
4344961713Sgirish 	return (NPI_SUCCESS);
4444961713Sgirish }
4544961713Sgirish 
4644961713Sgirish npi_status_t
npi_espc_eeprom_entry(npi_handle_t handle,io_op_t op,uint32_t addr,uint8_t * data)4744961713Sgirish npi_espc_eeprom_entry(npi_handle_t handle, io_op_t op, uint32_t addr,
4844961713Sgirish 			uint8_t *data)
4944961713Sgirish {
5044961713Sgirish 	uint64_t val = 0;
5144961713Sgirish 
5244961713Sgirish 	if ((addr & ~EPC_EEPROM_ADDR_BITS) != 0) {
5344961713Sgirish 		NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
54*52ccf843Smisaki 		    " npi_espc_eerprom_entry"
55*52ccf843Smisaki 		    " Invalid input addr <0x%x>\n",
56*52ccf843Smisaki 		    addr));
5744961713Sgirish 		return (NPI_FAILURE | NPI_ESPC_EEPROM_ADDR_INVALID);
5844961713Sgirish 	}
5944961713Sgirish 
60a3c5bd6dSspeer 	switch (op) {
61a3c5bd6dSspeer 	case OP_SET:
6244961713Sgirish 		val = EPC_WRITE_INITIATE | (addr << EPC_EEPROM_ADDR_SHIFT) |
63*52ccf843Smisaki 		    *data;
6444961713Sgirish 		NXGE_REG_WR64(handle, ESPC_REG_ADDR(ESPC_PIO_STATUS_REG), val);
6544961713Sgirish 		EPC_WAIT_RW_COMP(handle, &val, EPC_WRITE_COMPLETE);
6644961713Sgirish 		if ((val & EPC_WRITE_COMPLETE) == 0) {
6744961713Sgirish 			NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
68*52ccf843Smisaki 			    " npi_espc_eeprom_entry"
69*52ccf843Smisaki 			    " HW Error: EEPROM_WR <0x%x>\n",
70*52ccf843Smisaki 			    val));
7144961713Sgirish 			return (NPI_FAILURE | NPI_ESPC_EEPROM_WRITE_FAILED);
7244961713Sgirish 		}
73a3c5bd6dSspeer 		break;
74a3c5bd6dSspeer 	case OP_GET:
7544961713Sgirish 		val = EPC_READ_INITIATE | (addr << EPC_EEPROM_ADDR_SHIFT);
7644961713Sgirish 		NXGE_REG_WR64(handle, ESPC_REG_ADDR(ESPC_PIO_STATUS_REG), val);
7744961713Sgirish 		EPC_WAIT_RW_COMP(handle, &val, EPC_READ_COMPLETE);
7844961713Sgirish 		if ((val & EPC_READ_COMPLETE) == 0) {
7944961713Sgirish 			NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
80*52ccf843Smisaki 			    " npi_espc_eeprom_entry"
81*52ccf843Smisaki 			    " HW Error: EEPROM_RD <0x%x>",
82*52ccf843Smisaki 			    val));
8344961713Sgirish 			return (NPI_FAILURE | NPI_ESPC_EEPROM_READ_FAILED);
8444961713Sgirish 		}
8544961713Sgirish 		NXGE_REG_RD64(handle, ESPC_REG_ADDR(ESPC_PIO_STATUS_REG), &val);
8656d930aeSspeer 		/*
8756d930aeSspeer 		 * Workaround for synchronization issues - do a second PIO
8856d930aeSspeer 		 */
8956d930aeSspeer 		val = EPC_READ_INITIATE | (addr << EPC_EEPROM_ADDR_SHIFT);
9056d930aeSspeer 		NXGE_REG_WR64(handle, ESPC_REG_ADDR(ESPC_PIO_STATUS_REG), val);
9156d930aeSspeer 		EPC_WAIT_RW_COMP(handle, &val, EPC_READ_COMPLETE);
9256d930aeSspeer 		if ((val & EPC_READ_COMPLETE) == 0) {
9356d930aeSspeer 			NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
9456d930aeSspeer 			    " npi_espc_eeprom_entry HW Error: "
9556d930aeSspeer 			    "EEPROM_RD <0x%x>", val));
9656d930aeSspeer 			return (NPI_FAILURE | NPI_ESPC_EEPROM_READ_FAILED);
9756d930aeSspeer 		}
9856d930aeSspeer 		NXGE_REG_RD64(handle, ESPC_REG_ADDR(ESPC_PIO_STATUS_REG), &val);
9944961713Sgirish 		*data = val & EPC_EEPROM_DATA_MASK;
100a3c5bd6dSspeer 		break;
101a3c5bd6dSspeer 	default:
10244961713Sgirish 		NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
103*52ccf843Smisaki 		    " npi_espc_eeprom_entry"
104*52ccf843Smisaki 		    " Invalid Input addr <0x%x>\n", addr));
10544961713Sgirish 		return (NPI_FAILURE | NPI_ESPC_OPCODE_INVALID);
10644961713Sgirish 	}
10744961713Sgirish 
10844961713Sgirish 	return (NPI_SUCCESS);
10944961713Sgirish }
11044961713Sgirish 
11144961713Sgirish npi_status_t
npi_espc_mac_addr_get(npi_handle_t handle,uint8_t * data)11244961713Sgirish npi_espc_mac_addr_get(npi_handle_t handle, uint8_t *data)
11344961713Sgirish {
11444961713Sgirish 	mac_addr_0_t mac0;
11544961713Sgirish 	mac_addr_1_t mac1;
11644961713Sgirish 
11744961713Sgirish 	NXGE_REG_RD64(handle, ESPC_MAC_ADDR_0, &mac0.value);
11844961713Sgirish 	data[0] = mac0.bits.w0.byte0;
11944961713Sgirish 	data[1] = mac0.bits.w0.byte1;
12044961713Sgirish 	data[2] = mac0.bits.w0.byte2;
12144961713Sgirish 	data[3] = mac0.bits.w0.byte3;
12244961713Sgirish 
12344961713Sgirish 	NXGE_REG_RD64(handle, ESPC_MAC_ADDR_1, &mac1.value);
12444961713Sgirish 	data[4] = mac1.bits.w0.byte4;
12544961713Sgirish 	data[5] = mac1.bits.w0.byte5;
12644961713Sgirish 
12744961713Sgirish 	return (NPI_SUCCESS);
12844961713Sgirish }
12944961713Sgirish 
13044961713Sgirish npi_status_t
npi_espc_num_ports_get(npi_handle_t handle,uint8_t * data)13144961713Sgirish npi_espc_num_ports_get(npi_handle_t handle, uint8_t *data)
13244961713Sgirish {
13344961713Sgirish 	uint64_t val = 0;
13444961713Sgirish 
13544961713Sgirish 	NXGE_REG_RD64(handle, ESPC_NUM_PORTS_MACS, &val);
13644961713Sgirish 	val &= NUM_PORTS_MASK;
13744961713Sgirish 	*data = (uint8_t)val;
13844961713Sgirish 
13944961713Sgirish 	return (NPI_SUCCESS);
14044961713Sgirish }
14144961713Sgirish 
14244961713Sgirish npi_status_t
npi_espc_num_macs_get(npi_handle_t handle,uint8_t * data)14344961713Sgirish npi_espc_num_macs_get(npi_handle_t handle, uint8_t *data)
14444961713Sgirish {
14544961713Sgirish 	uint64_t val = 0;
14644961713Sgirish 
14744961713Sgirish 	NXGE_REG_RD64(handle, ESPC_NUM_PORTS_MACS, &val);
14844961713Sgirish 	val &= NUM_MAC_ADDRS_MASK;
14944961713Sgirish 	val = (val >> NUM_MAC_ADDRS_SHIFT);
15044961713Sgirish 	*data = (uint8_t)val;
15144961713Sgirish 
15244961713Sgirish 	return (NPI_SUCCESS);
15344961713Sgirish }
15444961713Sgirish 
15544961713Sgirish npi_status_t
npi_espc_model_str_get(npi_handle_t handle,char * data)15644961713Sgirish npi_espc_model_str_get(npi_handle_t handle, char *data)
15744961713Sgirish {
15844961713Sgirish 	uint64_t val = 0;
15944961713Sgirish 	uint16_t str_len;
16044961713Sgirish 	int i, j;
16144961713Sgirish 
16244961713Sgirish 	NXGE_REG_RD64(handle, ESPC_MOD_STR_LEN, &val);
16344961713Sgirish 	val &= MOD_STR_LEN_MASK;
16444961713Sgirish 	str_len = (uint8_t)val;
16544961713Sgirish 
16644961713Sgirish 	if (str_len > MAX_MOD_STR_LEN) {
16744961713Sgirish 		NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
168*52ccf843Smisaki 		    " npi_espc_model_str_get"
169*52ccf843Smisaki 		    " Model string length %d exceeds max %d\n",
170*52ccf843Smisaki 		    str_len, MAX_MOD_STR_LEN));
17144961713Sgirish 		return (NPI_FAILURE | NPI_ESPC_STR_LEN_INVALID);
17244961713Sgirish 	}
17344961713Sgirish 
17444961713Sgirish 	/*
17544961713Sgirish 	 * Might have to reverse the order depending on how the string
17644961713Sgirish 	 * is written.
17744961713Sgirish 	 */
17844961713Sgirish 	for (i = 0, j = 0; i < str_len; j++) {
17944961713Sgirish 		NXGE_REG_RD64(handle, ESPC_MOD_STR(j), &val);
18044961713Sgirish 		data[i++] = ((char *)&val)[3];
18144961713Sgirish 		data[i++] = ((char *)&val)[2];
18244961713Sgirish 		data[i++] = ((char *)&val)[1];
18344961713Sgirish 		data[i++] = ((char *)&val)[0];
18444961713Sgirish 	}
18544961713Sgirish 
18644961713Sgirish 	data[str_len] = '\0';
18744961713Sgirish 
18844961713Sgirish 	return (NPI_SUCCESS);
18944961713Sgirish }
19044961713Sgirish 
19144961713Sgirish npi_status_t
npi_espc_bd_model_str_get(npi_handle_t handle,char * data)19244961713Sgirish npi_espc_bd_model_str_get(npi_handle_t handle, char *data)
19344961713Sgirish {
19444961713Sgirish 	uint64_t val = 0;
19544961713Sgirish 	uint16_t str_len;
19644961713Sgirish 	int i, j;
19744961713Sgirish 
19844961713Sgirish 	NXGE_REG_RD64(handle, ESPC_BD_MOD_STR_LEN, &val);
19944961713Sgirish 	val &= BD_MOD_STR_LEN_MASK;
20044961713Sgirish 	str_len = (uint8_t)val;
20144961713Sgirish 
20244961713Sgirish 	if (str_len > MAX_BD_MOD_STR_LEN) {
20344961713Sgirish 		NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
204*52ccf843Smisaki 		    " npi_espc_model_str_get"
205*52ccf843Smisaki 		    " Board Model string length %d "
206*52ccf843Smisaki 		    "exceeds max %d\n",
207*52ccf843Smisaki 		    str_len, MAX_BD_MOD_STR_LEN));
20844961713Sgirish 		return (NPI_FAILURE | NPI_ESPC_STR_LEN_INVALID);
20944961713Sgirish 	}
21044961713Sgirish 
21144961713Sgirish 	/*
21244961713Sgirish 	 * Might have to reverse the order depending on how the string
21344961713Sgirish 	 * is written.
21444961713Sgirish 	 */
21544961713Sgirish 	for (i = 0, j = 0; i < str_len; j++) {
21644961713Sgirish 		NXGE_REG_RD64(handle, ESPC_BD_MOD_STR(j), &val);
21744961713Sgirish 		data[i++] = ((char *)&val)[3];
21844961713Sgirish 		data[i++] = ((char *)&val)[2];
21944961713Sgirish 		data[i++] = ((char *)&val)[1];
22044961713Sgirish 		data[i++] = ((char *)&val)[0];
22144961713Sgirish 	}
22244961713Sgirish 
22344961713Sgirish 	data[str_len] = '\0';
22444961713Sgirish 
22544961713Sgirish 	return (NPI_SUCCESS);
22644961713Sgirish }
22744961713Sgirish 
22844961713Sgirish npi_status_t
npi_espc_phy_type_get(npi_handle_t handle,uint8_t * data)22944961713Sgirish npi_espc_phy_type_get(npi_handle_t handle, uint8_t *data)
23044961713Sgirish {
23144961713Sgirish 	phy_type_t	phy;
23244961713Sgirish 
23344961713Sgirish 	NXGE_REG_RD64(handle, ESPC_PHY_TYPE, &phy.value);
23444961713Sgirish 	data[0] = phy.bits.w0.pt0_phy_type;
23544961713Sgirish 	data[1] = phy.bits.w0.pt1_phy_type;
23644961713Sgirish 	data[2] = phy.bits.w0.pt2_phy_type;
23744961713Sgirish 	data[3] = phy.bits.w0.pt3_phy_type;
23844961713Sgirish 
23944961713Sgirish 	return (NPI_SUCCESS);
24044961713Sgirish }
24144961713Sgirish 
24244961713Sgirish npi_status_t
npi_espc_port_phy_type_get(npi_handle_t handle,uint8_t * data,uint8_t portn)24344961713Sgirish npi_espc_port_phy_type_get(npi_handle_t handle, uint8_t *data, uint8_t portn)
24444961713Sgirish {
24544961713Sgirish 	phy_type_t	phy;
24644961713Sgirish 
247a3c5bd6dSspeer 	ASSERT(IS_PORT_NUM_VALID(portn));
24844961713Sgirish 
24944961713Sgirish 	NXGE_REG_RD64(handle, ESPC_PHY_TYPE, &phy.value);
25044961713Sgirish 	switch (portn) {
25144961713Sgirish 	case 0:
25244961713Sgirish 		*data = phy.bits.w0.pt0_phy_type;
25344961713Sgirish 		break;
25444961713Sgirish 	case 1:
25544961713Sgirish 		*data = phy.bits.w0.pt1_phy_type;
25644961713Sgirish 		break;
25744961713Sgirish 	case 2:
25844961713Sgirish 		*data = phy.bits.w0.pt2_phy_type;
25944961713Sgirish 		break;
26044961713Sgirish 	case 3:
26144961713Sgirish 		*data = phy.bits.w0.pt3_phy_type;
26244961713Sgirish 		break;
26344961713Sgirish 	default:
26444961713Sgirish 		NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
265*52ccf843Smisaki 		    " npi_espc_port_phy_type_get"
266*52ccf843Smisaki 		    " Invalid Input: portn <%d>",
267*52ccf843Smisaki 		    portn));
26844961713Sgirish 		return (NPI_FAILURE | NPI_ESPC_PORT_INVALID);
26944961713Sgirish 	}
27044961713Sgirish 
27144961713Sgirish 	return (NPI_SUCCESS);
27244961713Sgirish }
27344961713Sgirish 
27444961713Sgirish npi_status_t
npi_espc_max_frame_get(npi_handle_t handle,uint16_t * data)27544961713Sgirish npi_espc_max_frame_get(npi_handle_t handle, uint16_t *data)
27644961713Sgirish {
27744961713Sgirish 	uint64_t val = 0;
27844961713Sgirish 
27944961713Sgirish 	NXGE_REG_RD64(handle, ESPC_MAX_FM_SZ, &val);
28044961713Sgirish 	val &= MAX_FM_SZ_MASK;
28144961713Sgirish 	*data = (uint8_t)val;
28244961713Sgirish 
28344961713Sgirish 	return (NPI_SUCCESS);
28444961713Sgirish }
28544961713Sgirish 
28644961713Sgirish npi_status_t
npi_espc_version_get(npi_handle_t handle,uint16_t * data)28744961713Sgirish npi_espc_version_get(npi_handle_t handle, uint16_t *data)
28844961713Sgirish {
28944961713Sgirish 	uint64_t val = 0;
29044961713Sgirish 
29144961713Sgirish 	NXGE_REG_RD64(handle, ESPC_VER_IMGSZ, &val);
29244961713Sgirish 	val &= VER_NUM_MASK;
29344961713Sgirish 	*data = (uint8_t)val;
29444961713Sgirish 
29544961713Sgirish 	return (NPI_SUCCESS);
29644961713Sgirish }
29744961713Sgirish 
29844961713Sgirish npi_status_t
npi_espc_img_sz_get(npi_handle_t handle,uint16_t * data)29944961713Sgirish npi_espc_img_sz_get(npi_handle_t handle, uint16_t *data)
30044961713Sgirish {
30144961713Sgirish 	uint64_t val = 0;
30244961713Sgirish 
30344961713Sgirish 	NXGE_REG_RD64(handle, ESPC_VER_IMGSZ, &val);
30444961713Sgirish 	val &= IMG_SZ_MASK;
30544961713Sgirish 	val = val >> IMG_SZ_SHIFT;
30644961713Sgirish 	*data = (uint8_t)val;
30744961713Sgirish 
30844961713Sgirish 	return (NPI_SUCCESS);
30944961713Sgirish }
31044961713Sgirish 
31144961713Sgirish npi_status_t
npi_espc_chksum_get(npi_handle_t handle,uint8_t * data)31244961713Sgirish npi_espc_chksum_get(npi_handle_t handle, uint8_t *data)
31344961713Sgirish {
31444961713Sgirish 	uint64_t val = 0;
31544961713Sgirish 
31644961713Sgirish 	NXGE_REG_RD64(handle, ESPC_CHKSUM, &val);
31744961713Sgirish 	val &= CHKSUM_MASK;
31844961713Sgirish 	*data = (uint8_t)val;
31944961713Sgirish 
32044961713Sgirish 	return (NPI_SUCCESS);
32144961713Sgirish }
32244961713Sgirish 
32344961713Sgirish npi_status_t
npi_espc_intr_num_get(npi_handle_t handle,uint8_t * data)32444961713Sgirish npi_espc_intr_num_get(npi_handle_t handle, uint8_t *data)
32544961713Sgirish {
32644961713Sgirish 	intr_num_t	intr;
32744961713Sgirish 
32844961713Sgirish 	NXGE_REG_RD64(handle, ESPC_INTR_NUM, &intr.value);
32944961713Sgirish 	data[0] = intr.bits.w0.pt0_intr_num;
33044961713Sgirish 	data[1] = intr.bits.w0.pt1_intr_num;
33144961713Sgirish 	data[2] = intr.bits.w0.pt2_intr_num;
33244961713Sgirish 	data[3] = intr.bits.w0.pt3_intr_num;
33344961713Sgirish 
33444961713Sgirish 	return (NPI_SUCCESS);
33544961713Sgirish }
33644961713Sgirish 
33744961713Sgirish void
npi_espc_dump(npi_handle_t handle)33844961713Sgirish npi_espc_dump(npi_handle_t handle)
33944961713Sgirish {
34044961713Sgirish 	int i;
34144961713Sgirish 	uint64_t val = 0;
34244961713Sgirish 
34344961713Sgirish 	NPI_REG_DUMP_MSG((handle.function, NPI_REG_CTL,
344*52ccf843Smisaki 	    "Dumping SEEPROM registers directly:\n\n"));
34544961713Sgirish 
34644961713Sgirish 	for (i = 0; i < 23; i++) {
34744961713Sgirish 		NXGE_REG_RD64(handle, ESPC_NCR_REGN(i), &val);
34844961713Sgirish 		NPI_REG_DUMP_MSG((handle.function, NPI_REG_CTL,
349*52ccf843Smisaki 		    "reg[%d]      0x%llx\n",
350*52ccf843Smisaki 		    i, val & 0xffffffff));
35144961713Sgirish 	}
35244961713Sgirish 
35344961713Sgirish 	NPI_REG_DUMP_MSG((handle.function, NPI_REG_CTL, "\n\n"));
35444961713Sgirish }
35544961713Sgirish 
35644961713Sgirish uint32_t
npi_espc_reg_get(npi_handle_t handle,int reg_idx)35744961713Sgirish npi_espc_reg_get(npi_handle_t handle, int reg_idx)
35844961713Sgirish {
35944961713Sgirish 	uint64_t val = 0;
36044961713Sgirish 	uint32_t reg_val = 0;
36144961713Sgirish 
36244961713Sgirish 	NXGE_REG_RD64(handle, ESPC_NCR_REGN(reg_idx), &val);
36344961713Sgirish 	reg_val = val & 0xffffffff;
36444961713Sgirish 
36544961713Sgirish 	return (reg_val);
36644961713Sgirish }
36756d930aeSspeer 
vpd_rd(npi_handle_t handle,uint32_t addr)36856d930aeSspeer static inline uint8_t vpd_rd(npi_handle_t handle, uint32_t addr)
36956d930aeSspeer {
37056d930aeSspeer 	uint8_t data = 0;
37156d930aeSspeer 
37256d930aeSspeer 	if (npi_espc_eeprom_entry(handle, OP_GET, addr, &data) != NPI_SUCCESS)
37356d930aeSspeer 		data = 0;
37456d930aeSspeer 	return (data);
37556d930aeSspeer }
37656d930aeSspeer 
37756d930aeSspeer npi_status_t
npi_espc_vpd_info_get(npi_handle_t handle,p_npi_vpd_info_t vpdp,uint32_t rom_len)37856d930aeSspeer npi_espc_vpd_info_get(npi_handle_t handle, p_npi_vpd_info_t vpdp,
37956d930aeSspeer 		uint32_t rom_len)
38056d930aeSspeer {
38156d930aeSspeer 	int		i, len;
38256d930aeSspeer 	uint32_t	base = 0, kstart = 0, ep, end;
38356d930aeSspeer 	uint8_t		fd_flags = 0;
38456d930aeSspeer 
38556d930aeSspeer 	/* Fill the vpd_info struct with invalid vals */
38656d930aeSspeer 	(void) strcpy(vpdp->model, "\0");
38756d930aeSspeer 	(void) strcpy(vpdp->bd_model, "\0");
38856d930aeSspeer 	(void) strcpy(vpdp->phy_type, "\0");
38956d930aeSspeer 	(void) strcpy(vpdp->ver, "\0");
39056d930aeSspeer 	vpdp->num_macs = 0;
39156d930aeSspeer 	for (i = 0; i < ETHERADDRL; i++) {
39256d930aeSspeer 		vpdp->mac_addr[i] = 0;
39356d930aeSspeer 	}
39456d930aeSspeer 
39556d930aeSspeer 	ep = 0;
39656d930aeSspeer 	end = ep + rom_len;
39756d930aeSspeer 
39856d930aeSspeer 	/* go through the images till OBP image type is found */
39956d930aeSspeer 	while (ep < end) {
40056d930aeSspeer 		base = ep;
40156d930aeSspeer 		/* check for expansion rom header signature */
40256d930aeSspeer 		if (vpd_rd(handle, ep) != 0x55 ||
40356d930aeSspeer 		    vpd_rd(handle, ep + 1) != 0xaa) {
40456d930aeSspeer 			NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
40556d930aeSspeer 			    "npi_espc_vpd_info_get: expansion rom image "
40656d930aeSspeer 			    "not found, 0x%x [0x%x 0x%x]", ep,
40756d930aeSspeer 			    vpd_rd(handle, ep), vpd_rd(handle, ep + 1)));
40856d930aeSspeer 			goto vpd_info_err;
40956d930aeSspeer 		}
41056d930aeSspeer 		/* go to the beginning of the PCI data struct of this image */
41156d930aeSspeer 		ep = ep + 23;
41256d930aeSspeer 		ep = base + ((vpd_rd(handle, ep) << 8) |
41356d930aeSspeer 		    (vpd_rd(handle, ep + 1)));
41456d930aeSspeer 		/* check for PCI data struct signature "PCIR" */
41556d930aeSspeer 		if ((vpd_rd(handle, ep) != 0x50) ||
41656d930aeSspeer 		    (vpd_rd(handle, ep + 1) != 0x43) ||
41756d930aeSspeer 		    (vpd_rd(handle, ep + 2) != 0x49) ||
41856d930aeSspeer 		    (vpd_rd(handle, ep + 3) != 0x52)) {
41956d930aeSspeer 			NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
42056d930aeSspeer 			    "npi_espc_vpd_info_get: PCIR sig not found"));
42156d930aeSspeer 			goto vpd_info_err;
42256d930aeSspeer 		}
42356d930aeSspeer 		/* check for image type OBP */
42456d930aeSspeer 		if (vpd_rd(handle, ep + 20) != 0x01) {
42556d930aeSspeer 			/* go to the next image */
42656d930aeSspeer 			ep = base + ((vpd_rd(handle, base + 2)) * 512);
42756d930aeSspeer 			continue;
42856d930aeSspeer 		}
42956d930aeSspeer 		/* find the beginning of the VPD data */
43056d930aeSspeer 		base = base + (vpd_rd(handle, ep + 8) |
43156d930aeSspeer 		    (vpd_rd(handle, ep + 9) << 8));
43256d930aeSspeer 		break;
43356d930aeSspeer 	}
43456d930aeSspeer 
43556d930aeSspeer 	/* check first byte of identifier string tag */
43656d930aeSspeer 	if (!base || (vpd_rd(handle, base + 0) != 0x82)) {
43756d930aeSspeer 		NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
43856d930aeSspeer 		    "npi_espc_vpd_info_get: Could not find VPD!!"));
43956d930aeSspeer 		goto vpd_info_err;
44056d930aeSspeer 	}
44156d930aeSspeer 
44256d930aeSspeer 	/*
44356d930aeSspeer 	 * skip over the ID string descriptor to go to the read-only VPD
44456d930aeSspeer 	 * keywords list.
44556d930aeSspeer 	 */
44656d930aeSspeer 	i = (vpd_rd(handle, base + 1) |
44756d930aeSspeer 	    (vpd_rd(handle, base + 2) << 8)) + 3;
44856d930aeSspeer 
44956d930aeSspeer 	while (i < EXPANSION_ROM_SIZE) {
45056d930aeSspeer 		if (vpd_rd(handle, base + i) != 0x90) { /* no vpd found */
45156d930aeSspeer 			NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
45256d930aeSspeer 			    "nxge_get_vpd_info: Could not find "
45356d930aeSspeer 			    "VPD ReadOnly list!! [0x%x] %d",
45456d930aeSspeer 			    vpd_rd(handle, base + i), i));
45556d930aeSspeer 			goto vpd_info_err;
45656d930aeSspeer 		}
45756d930aeSspeer 
45856d930aeSspeer 		/* found a vpd read-only list, get its length */
45956d930aeSspeer 		len = vpd_rd(handle, base + i + 1) |
46056d930aeSspeer 		    (vpd_rd(handle, base + i + 2) << 8);
46156d930aeSspeer 
46256d930aeSspeer 		/* extract keywords */
46356d930aeSspeer 		kstart = base + i + 3;
46456d930aeSspeer 		ep = kstart;
46556d930aeSspeer 		/*
46656d930aeSspeer 		 * Each keyword field is as follows:
46756d930aeSspeer 		 * 2 bytes keyword in the form of "Zx" where x = 0,1,2....
46856d930aeSspeer 		 * 1 byte keyword data field length - klen
46956d930aeSspeer 		 * Now the actual keyword data field:
47056d930aeSspeer 		 * 	1 byte VPD property instance, 'M' / 'I'
47156d930aeSspeer 		 * 	2 bytes
47256d930aeSspeer 		 * 	1 byte VPD property data type, 'B' / 'S'
47356d930aeSspeer 		 * 	1 byte VPD property value length - n
47456d930aeSspeer 		 * 	Actual property string, length (klen - n - 5) bytes
47556d930aeSspeer 		 * 	Actual property value, length n bytes
47656d930aeSspeer 		 */
47756d930aeSspeer 		while ((ep - kstart) < len) {
47856d930aeSspeer 			int klen = vpd_rd(handle, ep + 2);
47956d930aeSspeer 			int dlen;
48056d930aeSspeer 			char type;
48156d930aeSspeer 
48256d930aeSspeer 			ep += 3;
48356d930aeSspeer 
48456d930aeSspeer 			/*
48556d930aeSspeer 			 * Look for the following properties:
48656d930aeSspeer 			 *
48756d930aeSspeer 			 * local-mac-address:
48856d930aeSspeer 			 * -- VPD Instance 'I'
48956d930aeSspeer 			 * -- VPD Type String 'B'
49056d930aeSspeer 			 * -- property string == local-mac-address
49156d930aeSspeer 			 *
49256d930aeSspeer 			 * model:
49356d930aeSspeer 			 * -- VPD Instance 'M'
49456d930aeSspeer 			 * -- VPD Type String 'S'
49556d930aeSspeer 			 * -- property string == model
49656d930aeSspeer 			 *
49756d930aeSspeer 			 * board-model:
49856d930aeSspeer 			 * -- VPD Instance 'M'
49956d930aeSspeer 			 * -- VPD Type String 'S'
50056d930aeSspeer 			 * -- property string == board-model
50156d930aeSspeer 			 *
50256d930aeSspeer 			 * num-mac-addresses:
50356d930aeSspeer 			 * -- VPD Instance 'I'
50456d930aeSspeer 			 * -- VPD Type String 'B'
50556d930aeSspeer 			 * -- property string == num-mac-addresses
50656d930aeSspeer 			 *
50756d930aeSspeer 			 * phy-type:
50856d930aeSspeer 			 * -- VPD Instance 'I'
50956d930aeSspeer 			 * -- VPD Type String 'S'
51056d930aeSspeer 			 * -- property string == phy-type
51156d930aeSspeer 			 *
51256d930aeSspeer 			 * version:
51356d930aeSspeer 			 * -- VPD Instance 'M'
51456d930aeSspeer 			 * -- VPD Type String 'S'
51556d930aeSspeer 			 * -- property string == version
51656d930aeSspeer 			 */
51756d930aeSspeer 			if (vpd_rd(handle, ep) == 'M') {
51856d930aeSspeer 				type = vpd_rd(handle, ep + 3);
51956d930aeSspeer 				if (type == 'S') {
52056d930aeSspeer 					dlen = vpd_rd(handle, ep + 4);
52156d930aeSspeer 					if (npi_vpd_read_prop(handle, ep + 5,
52256d930aeSspeer 					    "model", dlen, vpdp->model)) {
52356d930aeSspeer 						fd_flags |= FD_MODEL;
52456d930aeSspeer 						goto next;
52556d930aeSspeer 					}
52656d930aeSspeer 					if (npi_vpd_read_prop(handle, ep + 5,
52756d930aeSspeer 					    "board-model", dlen,
52856d930aeSspeer 					    vpdp->bd_model)) {
52956d930aeSspeer 						fd_flags |= FD_BD_MODEL;
53056d930aeSspeer 						goto next;
53156d930aeSspeer 					}
53256d930aeSspeer 					if (npi_vpd_read_prop(handle, ep + 5,
53356d930aeSspeer 					    "version", dlen, vpdp->ver)) {
53456d930aeSspeer 						fd_flags |= FD_FW_VERSION;
53556d930aeSspeer 						goto next;
53656d930aeSspeer 					}
53756d930aeSspeer 				}
53856d930aeSspeer 				goto next;
53956d930aeSspeer 			} else if (vpd_rd(handle, ep) == 'I') {
54056d930aeSspeer 				type = vpd_rd(handle, ep + 3);
54156d930aeSspeer 				if (type == 'B') {
54256d930aeSspeer 					dlen = vpd_rd(handle, ep + 4);
54356d930aeSspeer 					if (npi_vpd_read_prop(handle, ep + 5,
54456d930aeSspeer 					    "local-mac-address", dlen,
54556d930aeSspeer 					    (char *)(vpdp->mac_addr))) {
54656d930aeSspeer 						fd_flags |= FD_MAC_ADDR;
54756d930aeSspeer 						goto next;
54856d930aeSspeer 					}
54956d930aeSspeer 					if (npi_vpd_read_prop(handle, ep + 5,
55056d930aeSspeer 					    "num-mac-addresses", dlen,
55156d930aeSspeer 					    (char *)&(vpdp->num_macs))) {
55256d930aeSspeer 						fd_flags |= FD_NUM_MACS;
55356d930aeSspeer 					}
55456d930aeSspeer 				} else if (type == 'S') {
55556d930aeSspeer 					dlen = vpd_rd(handle, ep + 4);
55656d930aeSspeer 					if (npi_vpd_read_prop(handle, ep + 5,
55756d930aeSspeer 					    "phy-type", dlen,
55856d930aeSspeer 					    vpdp->phy_type)) {
55956d930aeSspeer 						fd_flags |= FD_PHY_TYPE;
56056d930aeSspeer 					}
56156d930aeSspeer 				}
56256d930aeSspeer 				goto next;
56356d930aeSspeer 			} else {
56456d930aeSspeer 				goto vpd_info_err;
56556d930aeSspeer 			}
56656d930aeSspeer 
56756d930aeSspeer next:
56856d930aeSspeer 			if ((fd_flags & FD_ALL) == FD_ALL)
56956d930aeSspeer 				goto vpd_success;
57056d930aeSspeer 			ep += klen;
57156d930aeSspeer 		}
57256d930aeSspeer 		i += len + 3;
57356d930aeSspeer 	}
57456d930aeSspeer 
57556d930aeSspeer vpd_success:
57656d930aeSspeer 	return (NPI_SUCCESS);
57756d930aeSspeer 
57856d930aeSspeer vpd_info_err:
57956d930aeSspeer 	return (NPI_FAILURE);
58056d930aeSspeer }
58156d930aeSspeer 
58256d930aeSspeer static int
npi_vpd_read_prop(npi_handle_t handle,uint32_t ep,const char * prop,int len,char * val)58356d930aeSspeer npi_vpd_read_prop(npi_handle_t handle, uint32_t ep, const char *prop, int len,
58456d930aeSspeer 		char *val)
58556d930aeSspeer {
58656d930aeSspeer 	int prop_len =  strlen(prop) + 1;
58756d930aeSspeer 	int i;
58856d930aeSspeer 
58956d930aeSspeer 	for (i = 0; i < prop_len; i++) {
59056d930aeSspeer 		if (vpd_rd(handle, ep + i) != prop[i])
59156d930aeSspeer 			return (0);
59256d930aeSspeer 	}
59356d930aeSspeer 
59456d930aeSspeer 	ep += prop_len;
59556d930aeSspeer 
59656d930aeSspeer 	for (i = 0; i < len; i++)
59756d930aeSspeer 		val[i] = vpd_rd(handle, ep + i);
59856d930aeSspeer 	return (1);
59956d930aeSspeer }
600