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