4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #pragma ident "%Z%%M% %I% %E% SMI"
30 * Read the SDR information on a board and get the device id to
31 * read the FRUID information
35 #include <sys/types.h>
45 #include "fru_access_impl.h"
47 #define POLL_TIMEOUT 10000 /* 20 sec */
50 #define IPMI_GET_SDR_INFO 0x20
51 #define IPMI_SENSOR_NETFN 0x4
52 #define SDR_INFO_RESPONSE_SZ_MIN 10
55 #define SUN_FRU "SUN FRU SDR"
56 #define FRU_DEVICE_SDR_TYPE 0x11
57 #define IPMI_SDR_VERSION 0x51
58 #define IPMI_DATA_OFFSET 7
59 #define IPMI_GET_SDR_INFO_CMD 0x20
60 #define SDR_BUFFER_LEN_MAX 100
66 uint8_t record_id_lsb
;
67 uint8_t record_id_msb
;
73 static int get_sdr_info(int, int, uint8_t lun
);
74 static int get_sdr(sdr_info_t
*);
75 static int get_sun_sdr(int, uint8_t, uint8_t, uint8_t);
80 * static int lun_mask[4] = { 0x01, 0x02, 0x04, 0x08 };
84 * routine to read the onboard/remote device SDR information
87 get_fru_data_info(int src
, int dest
, format_t
*fru_format
)
92 dest
= IPMB_ADDR(dest
);
94 if (src
!= dest
) { /* ipmi */
96 for (i
= 0; i
< NUM_OF_LUN
; i
++) { /* for each lun */
97 ret
= get_sdr_info(src
, dest
, i
);
99 ret
= get_sun_sdr(ret
, src
, dest
, i
);
101 fru_format
->format
|= SUN_FORMAT
;
102 fru_format
->sun_device_id
= ret
;
103 fru_format
->sun_lun
= i
;
108 } else { /* on board */
109 ret
= get_sdr_info(src
, dest
, 0);
111 ret
= get_sun_sdr(ret
, src
, dest
, 0);
113 fru_format
->format
|= SUN_FORMAT
;
114 fru_format
->sun_device_id
= ret
;
115 fru_format
->sun_lun
= 0;
122 * read the onboard sdr information
125 get_onboard_sdr(sdr_info_t
*sdr
)
130 SC_MSG_CMD(&req_pkt
) = SMC_DEVICE_SDR_GET
;
131 SC_MSG_LEN(&req_pkt
) = 6;
132 SC_MSG_ID(&req_pkt
) = SEQUENCE
;
134 /* data for request packet */
135 req_pkt
.data
[0] = 0x0;
136 req_pkt
.data
[1] = 0x0;
137 req_pkt
.data
[2] = sdr
->record_id_lsb
;
138 req_pkt
.data
[3] = sdr
->record_id_msb
;
139 req_pkt
.data
[4] = sdr
->offset
;
140 req_pkt
.data
[5] = sdr
->length
;
142 if (smc_send_msg(DEFAULT_FD
, &req_pkt
, &res_pkt
,
143 POLL_TIMEOUT
) != SMC_SUCCESS
) {
147 bzero(sdr
->buffer
, SDR_BUFFER_LEN_MAX
);
148 (void) memcpy(sdr
->buffer
, res_pkt
.data
, res_pkt
.hdr
.len
);
153 * get the sdr information
156 get_sdr_info(int src
, int dest
, uint8_t lun
)
161 if (lun
>= NUM_OF_LUN
) {
165 if (src
== dest
) { /* onboard */
166 SC_MSG_CMD(&req_pkt
) = SMC_DEVICE_SDR_INFO_GET
;
167 SC_MSG_LEN(&req_pkt
) = 0;
168 SC_MSG_ID(&req_pkt
) = SEQUENCE
;
169 if (smc_send_msg(DEFAULT_FD
, &req_pkt
, &res_pkt
,
170 POLL_TIMEOUT
) != SMC_SUCCESS
) {
173 return (res_pkt
.data
[0]);
177 (void) smc_init_ipmi_msg(&req_pkt
, IPMI_GET_SDR_INFO_CMD
,
178 FRUACCESS_MSG_ID
, 0, NULL
, DEFAULT_SEQN
, dest
,
179 SMC_NETFN_SENSOR_REQ
, lun
);
181 if (smc_send_msg(DEFAULT_FD
, &req_pkt
, &res_pkt
,
182 POLL_TIMEOUT
) != SMC_SUCCESS
) {
186 /* completion code */
187 if (res_pkt
.data
[IPMI_DATA_OFFSET
] != 0) {
192 * Known bug in SMC f/w. take this out for next release
193 * if ((res_pkt.data[IPMI_DATA_OFFSET + 2] & lun_mask[lun]) != 1) {
197 return (res_pkt
.data
[IPMI_DATA_OFFSET
+ 1]);
201 get_sun_sdr(int num_records
, uint8_t src
, uint8_t dest
, uint8_t lun
)
205 char data
[SDR_BUFFER_LEN_MAX
];
206 uint8_t next_record_lsb
;
207 uint8_t next_record_msb
;
214 /* get the first record info */
215 next_record_lsb
= 0x0;
216 next_record_msb
= 0x0;
220 if (src
== dest
) { /* onboard */
221 for (i
= 0; i
< num_records
; i
++) {
222 sdr
.record_id_lsb
= next_record_lsb
;
223 sdr
.record_id_msb
= next_record_msb
;
225 if ((ret
= get_onboard_sdr(&sdr
)) < 0) {
229 next_record_lsb
= data
[0];
230 next_record_msb
= data
[1];
231 if (data
[4] != IPMI_SDR_VERSION
) {
235 if (data
[5] == FRU_DEVICE_SDR_TYPE
) {
237 sdr
.length
= strlen(SUN_FRU
);
238 if ((ret
= get_onboard_sdr(&sdr
)) < 0) {
242 /* first two bytes of response is reserv. id */
243 if (strncmp(SUN_FRU
, &data
[2],
244 strlen(SUN_FRU
)) == 0) {
248 if ((ret
= get_onboard_sdr(&sdr
)) < 0) {
259 /* traverse thru all the records until we find sun sdr */
260 for (i
= 0; i
< num_records
; i
++) {
262 sdr
.record_id_lsb
= next_record_lsb
;
263 sdr
.record_id_msb
= next_record_msb
;
265 if ((ret
= get_sdr(&sdr
)) < 0) {
269 /* completion code */
270 if (data
[IPMI_DATA_OFFSET
] != 0) {
273 next_record_lsb
= data
[IPMI_DATA_OFFSET
+ 1];
274 next_record_msb
= data
[IPMI_DATA_OFFSET
+ 2];
276 if (data
[IPMI_DATA_OFFSET
+ 5] != IPMI_SDR_VERSION
) {
280 if (data
[IPMI_DATA_OFFSET
+ 6] == FRU_DEVICE_SDR_TYPE
) {
283 sdr
.length
= strlen(SUN_FRU
);
284 if ((ret
= get_sdr(&sdr
)) < 0) {
288 /* completion code */
289 if (data
[IPMI_DATA_OFFSET
] != 0) {
293 if (strncmp(&data
[IPMI_DATA_OFFSET
+ 3],
294 SUN_FRU
, strlen(SUN_FRU
)) == 0) {
298 if ((ret
= get_sdr(&sdr
)) < 0) {
302 /* completion code */
303 if (data
[IPMI_DATA_OFFSET
] != 0) {
306 return (data
[IPMI_DATA_OFFSET
+ 9]);
314 get_sdr(sdr_info_t
*sdr
)
324 /* data for request packet */
325 datap
[0] = 0x0; /* reserved */
326 datap
[1] = 0x0; /* reserved */
327 datap
[2] = sdr
->record_id_lsb
;
328 datap
[3] = sdr
->record_id_msb
;
329 datap
[4] = sdr
->offset
;
330 datap
[5] = sdr
->length
;
332 (void) smc_init_ipmi_msg(&req_pkt
, SMC_GET_DEVICE_SDR
,
333 FRUACCESS_MSG_ID
, 6, datap
, DEFAULT_SEQN
,
334 sdr
->dest
, SMC_NETFN_SENSOR_REQ
, sdr
->lun
);
336 if (smc_send_msg(DEFAULT_FD
, &req_pkt
, &res_pkt
,
337 POLL_TIMEOUT
) != SMC_SUCCESS
) {
340 bzero(sdr
->buffer
, SDR_BUFFER_LEN_MAX
);
341 (void) memcpy(sdr
->buffer
, res_pkt
.data
, res_pkt
.hdr
.len
);