8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / cmd / picl / plugins / sun4u / snowbird / lib / fruaccess / piclsdr.c
blob41efb7ee6142011cb0a4550e3f8ec50979e75d27
1 /*
2 * CDDL HEADER START
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
7 * with the License.
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]
20 * CDDL HEADER END
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
34 #include <stdio.h>
35 #include <sys/types.h>
36 #include <sys/stat.h>
37 #include <fcntl.h>
38 #include <errno.h>
39 #include <time.h>
40 #include <poll.h>
41 #include <stropts.h>
42 #include <stdarg.h>
43 #include <syslog.h>
44 #include <smclib.h>
45 #include "fru_access_impl.h"
47 #define POLL_TIMEOUT 10000 /* 20 sec */
48 #define SEQUENCE 10
50 #define IPMI_GET_SDR_INFO 0x20
51 #define IPMI_SENSOR_NETFN 0x4
52 #define SDR_INFO_RESPONSE_SZ_MIN 10
54 #define NUM_OF_LUN 4
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
62 typedef struct {
63 uint8_t src;
64 uint8_t dest;
65 uint8_t lun;
66 uint8_t record_id_lsb;
67 uint8_t record_id_msb;
68 int offset;
69 int length;
70 char *buffer;
71 } sdr_info_t;
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);
78 * bug in smc f/w
80 * static int lun_mask[4] = { 0x01, 0x02, 0x04, 0x08 };
84 * routine to read the onboard/remote device SDR information
86 void
87 get_fru_data_info(int src, int dest, format_t *fru_format)
89 int ret;
91 src = IPMB_ADDR(src);
92 dest = IPMB_ADDR(dest);
94 if (src != dest) { /* ipmi */
95 int i = 0;
96 for (i = 0; i < NUM_OF_LUN; i++) { /* for each lun */
97 ret = get_sdr_info(src, dest, i);
98 if (ret > 0) {
99 ret = get_sun_sdr(ret, src, dest, i);
100 if (ret > 0) {
101 fru_format->format |= SUN_FORMAT;
102 fru_format->sun_device_id = ret;
103 fru_format->sun_lun = i;
104 break;
108 } else { /* on board */
109 ret = get_sdr_info(src, dest, 0);
110 if (ret > 0) {
111 ret = get_sun_sdr(ret, src, dest, 0);
112 if (ret > 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
124 static int
125 get_onboard_sdr(sdr_info_t *sdr)
127 sc_reqmsg_t req_pkt;
128 sc_rspmsg_t res_pkt;
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) {
144 return (-1);
147 bzero(sdr->buffer, SDR_BUFFER_LEN_MAX);
148 (void) memcpy(sdr->buffer, res_pkt.data, res_pkt.hdr.len);
149 return (0);
153 * get the sdr information
155 static int
156 get_sdr_info(int src, int dest, uint8_t lun)
158 sc_reqmsg_t req_pkt;
159 sc_rspmsg_t res_pkt;
161 if (lun >= NUM_OF_LUN) {
162 return (-1);
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) {
171 return (-1);
173 return (res_pkt.data[0]);
176 /* ipmb access */
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) {
183 return (-1);
186 /* completion code */
187 if (res_pkt.data[IPMI_DATA_OFFSET] != 0) {
188 return (-1);
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) {
194 * return (0);
197 return (res_pkt.data[IPMI_DATA_OFFSET + 1]);
200 static int
201 get_sun_sdr(int num_records, uint8_t src, uint8_t dest, uint8_t lun)
203 int i, ret;
204 sdr_info_t sdr;
205 char data[SDR_BUFFER_LEN_MAX];
206 uint8_t next_record_lsb;
207 uint8_t next_record_msb;
209 sdr.src = src;
210 sdr.dest = dest;
211 sdr.lun = lun;
212 sdr.buffer = data;
214 /* get the first record info */
215 next_record_lsb = 0x0;
216 next_record_msb = 0x0;
217 sdr.length = 4;
218 sdr.offset = 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) {
226 return (ret);
229 next_record_lsb = data[0];
230 next_record_msb = data[1];
231 if (data[4] != IPMI_SDR_VERSION) {
232 return (-1);
235 if (data[5] == FRU_DEVICE_SDR_TYPE) {
236 sdr.offset = 0x10;
237 sdr.length = strlen(SUN_FRU);
238 if ((ret = get_onboard_sdr(&sdr)) < 0) {
239 return (ret);
242 /* first two bytes of response is reserv. id */
243 if (strncmp(SUN_FRU, &data[2],
244 strlen(SUN_FRU)) == 0) {
245 /* found sun sdr */
246 sdr.offset = 0x0;
247 sdr.length = 7;
248 if ((ret = get_onboard_sdr(&sdr)) < 0) {
249 return (ret);
251 return (data[8]);
255 return (-1);
258 /* ipmb access */
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) {
266 return (ret);
269 /* completion code */
270 if (data[IPMI_DATA_OFFSET] != 0) {
271 return (-1);
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) {
277 return (-1);
280 if (data[IPMI_DATA_OFFSET + 6] == FRU_DEVICE_SDR_TYPE) {
282 sdr.offset = 0x10;
283 sdr.length = strlen(SUN_FRU);
284 if ((ret = get_sdr(&sdr)) < 0) {
285 return (ret);
288 /* completion code */
289 if (data[IPMI_DATA_OFFSET] != 0) {
290 return (-1);
293 if (strncmp(&data[IPMI_DATA_OFFSET+ 3],
294 SUN_FRU, strlen(SUN_FRU)) == 0) {
295 /* found sun sdr */
296 sdr.offset = 0x0;
297 sdr.length = 7;
298 if ((ret = get_sdr(&sdr)) < 0) {
299 return (ret);
302 /* completion code */
303 if (data[IPMI_DATA_OFFSET] != 0) {
304 return (-1);
306 return (data[IPMI_DATA_OFFSET + 9]);
310 return (-1);
313 static int
314 get_sdr(sdr_info_t *sdr)
316 sc_reqmsg_t req_pkt;
317 sc_rspmsg_t res_pkt;
318 uint8_t datap[6];
320 if (sdr->lun > 3) {
321 return (-1);
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) {
338 return (-1);
340 bzero(sdr->buffer, SDR_BUFFER_LEN_MAX);
341 (void) memcpy(sdr->buffer, res_pkt.data, res_pkt.hdr.len);
342 return (0);