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