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 * These routines in this file are used to interact with SMC driver to
31 * read and write FRUID data
41 #include <sys/types.h>
48 #include "fru_access_impl.h"
50 #define POLL_TIMEOUT 10000
51 #define FRUID_CHECK_POLL_TIMEOUT 5000
52 #define SIZE_TO_READ_WRITE 20
54 /* IPMI fru spec Storage definition version 1.0, rev 1.1 */
55 #define IPMI_COMMON_HEADER_SIZE 8
56 #define IPMI_VERSION 1
57 #define CMN_HDR_VERSION_MASK 0x0
58 #define CMN_HDR_OFFSET 0x0
59 #define BD_MFR_OFFSET 6
60 #define BD_FIELDS_SIZE 6
61 #define AREA_TERMINATION_INDICATOR 0xc1
64 #define BINARY_TYPE 0x0
65 #define BCDPLUS_TYPE 0x1
66 #define SIX_BITASCII_TYPE 0x2
67 #define UNICODE_TYPE 0x3
69 /* for ascii conversion */
70 #define ASCII_MAP 0x20
71 #define BIT_MASK1 0x3f
72 #define BIT_MASK2 0x0f
73 #define BIT_MASK3 0x03
75 #define SUN_NAME "SUN MICROSYSTEMS, INC."
76 #define SUN_JEDEC_CODE 0x3e
77 #define MANR_MAX_LENGTH 80
78 #define FRU_DATA_MAX_SIZE 100
81 #define IPMI_GET_DEVICE_ID 0x1
82 #define FRU_DEVICE_ID 0x0
83 #define READ_FRU_INVENTORY_INFO 0x10
84 #define READ_FRU_INVENTORY_DATA 0x11
85 #define WRITE_FRU_INVENTORY_DATA 0x12
87 #define TMP_BUFFER_SIZE 10
88 #define BYTE_TO_READ_SUN_CHK 5
91 uint8_t internal
; /* internal use area */
92 uint8_t chassis
; /* chassis info area */
93 uint8_t board
; /* board area */
94 uint8_t product
; /* product info area */
95 uint8_t records
; /* multirecord area */
98 extern void get_fru_data_info(int, int, format_t
*);
99 static void convert_to_ascii(uint8_t [], uint8_t [], int, int);
100 static void bcdplus_to_ascii(uint8_t [], uint8_t [], int);
101 static time_t get_utc_time(uint8_t []);
102 static uint8_t cpu_no
= 0;
105 * Routine to read FRUID information from BMC
108 get_alarm_fru_data(int offset
, int size
, void *buffer
, format_t
*format
)
114 if (buffer
== NULL
) {
119 datap
[0] = 0x7; /* bus id */
120 datap
[1] = 0xa0; /* slave address */
121 datap
[2] = size
; /* count */
122 datap
[3] = offset
>> 8; /* MSB */
123 datap
[4] = (uint8_t)offset
; /* LSB */
125 (void) smc_init_ipmi_msg(&req_pkt
, SMC_MASTER_WR_RD_I2C
,
126 FRUACCESS_MSG_ID
, 5, datap
, DEFAULT_SEQN
, format
->dest
,
127 SMC_NETFN_APP_REQ
, SMC_BMC_LUN
);
129 if (smc_send_msg(DEFAULT_FD
, &req_pkt
, &res_pkt
,
130 POLL_TIMEOUT
) != SMC_SUCCESS
) {
133 /* check the completion code */
134 if (res_pkt
.data
[7] != 0) {
138 (void) memcpy(buffer
, &(res_pkt
.data
[8]), size
);
143 * Routine to read FRUID information from other boards
146 get_fru_data(int offset
, int size
, void *buffer
, format_t
*format
)
153 if (buffer
== NULL
) {
157 /* figure out if onboard access or ipmb access */
158 if (format
->src
== format
->dest
) {
166 case 0: /* on board info (local i2c) */
168 SC_MSG_CMD(&req_pkt
) = SMC_EEPROM_READ
;
169 SC_MSG_LEN(&req_pkt
) = 4;
170 SC_MSG_ID(&req_pkt
) = FRUACCESS_MSG_ID
;
172 /* data field for request */
173 req_pkt
.data
[0] = format
->sun_device_id
; /* device id */
174 req_pkt
.data
[1] = (uint8_t)offset
; /* (LSB) */
175 req_pkt
.data
[3] = size
;
177 if (format
->format
== SUN_FORMAT
) {
178 req_pkt
.data
[2] = offset
>> 8;
180 req_pkt
.data
[2] = 0x0; /* (MSB) always 0x0 for IPMI */
183 /* make a call to smc library to send cmd */
184 if (smc_send_msg(DEFAULT_FD
, &req_pkt
, &res_pkt
,
185 POLL_TIMEOUT
) != SMC_SUCCESS
) {
189 if (SC_MSG_LEN(&res_pkt
) != size
) {
192 (void) memcpy(buffer
, res_pkt
.data
, size
);
197 /* data for request packet */
198 datap
[0] = format
->sun_device_id
; /* device id */
199 datap
[1] = (uint8_t)offset
; /* LSB */
200 datap
[3] = size
; /* bytes to read */
201 if (format
->format
== SUN_FORMAT
) {
202 datap
[2] = offset
>> 8;
204 datap
[2] = 0x0; /* (MSB) always 0x0 for IPMI */
207 (void) smc_init_ipmi_msg(&req_pkt
, READ_FRU_INVENTORY_DATA
,
208 FRUACCESS_MSG_ID
, 4, datap
, DEFAULT_SEQN
,
209 format
->dest
, SMC_NETFN_STORAGE_REQ
, format
->sun_lun
);
211 if (smc_send_msg(DEFAULT_FD
, &req_pkt
, &res_pkt
,
212 POLL_TIMEOUT
) != SMC_SUCCESS
) {
215 /* check the completion code */
216 if (res_pkt
.data
[7] != 0) {
221 if (res_pkt
.data
[8] != size
) {
225 (void) memcpy(buffer
, &(res_pkt
.data
[9]), size
);
231 * routine to read the IPMI common header field
234 read_common_header(fruid_offset_t
*offset
, format_t
*format
)
237 uint8_t data
[FRU_DATA_MAX_SIZE
];
239 ret
= get_fru_data(CMN_HDR_OFFSET
, IPMI_COMMON_HEADER_SIZE
, data
,
246 if ((data
[0] | CMN_HDR_VERSION_MASK
) != 1) {
250 offset
->internal
= data
[1] * 8;
251 offset
->chassis
= data
[2] * 8;
252 offset
->board
= data
[3] * 8;
253 offset
->product
= data
[4] * 8;
254 offset
->records
= data
[5] * 8;
260 * Read the values of each field based on FORMAT
264 read_bd_fields(uint8_t *field
, int offset
, format_t
*format
)
267 int ret
, encode_type
= 0x0, len
, length
, extra_bytes
, alloc_size
;
269 uint8_t data
[FRU_DATA_MAX_SIZE
];
271 bzero(field
, MANR_MAX_LENGTH
);
273 ret
= get_fru_data(offset
, BD_FIELDS_SIZE
, data
, format
);
278 if (data
[0] == AREA_TERMINATION_INDICATOR
) {
282 encode_type
= data
[0] >> 6;
283 len
= data
[0] & 0x3f;
288 ret
= get_fru_data(offset
+1, len
, data
, format
);
293 switch (encode_type
) {
295 case SIX_BITASCII_TYPE
:
297 length
= len
- (len
% 3);
298 extra_bytes
= len
% 3;
299 alloc_size
= ((length
/3) * 4) + extra_bytes
;
300 store
= (uint8_t *)malloc(sizeof (uint8_t) * alloc_size
);
304 convert_to_ascii(data
, store
, len
, extra_bytes
);
309 alloc_size
= len
* 2;
310 store
= (uint8_t *)malloc(sizeof (uint8_t) * alloc_size
);
315 bcdplus_to_ascii(data
, store
, len
);
324 (void) memcpy(field
, store
, alloc_size
);
330 read_board_info(uint8_t board_offset
, payload_t
*manr
, format_t
*format
)
335 uint8_t data
[FRU_DATA_MAX_SIZE
];
336 int ret
= 0, current_offset
= 0x0;
339 /* read version, length, lang code, mfg. time */
340 ret
= get_fru_data(board_offset
, BD_FIELDS_SIZE
, data
, format
);
347 if ((data
[0] | CMN_HDR_VERSION_MASK
) != 1) {
351 /* byte 2 is lang code */
352 bd_area_len
= data
[1] * 8;
353 mfg_time
[3] = data
[3];
354 mfg_time
[2] = data
[4];
355 mfg_time
[1] = data
[5];
357 time
= get_utc_time(mfg_time
);
359 /* fill the timestamp into manr */
360 (void) memcpy(manr
->timestamp
, &time
, MANR_TIME_LEN
);
362 if (bd_area_len
< BD_MFR_OFFSET
) {
365 buffer
= (uint8_t *)malloc(sizeof (uint8_t) * MANR_MAX_LENGTH
);
366 if (buffer
== NULL
) {
370 /* read the board info */
371 current_offset
+= board_offset
+ BD_MFR_OFFSET
;
372 current_offset
+= read_bd_fields(buffer
, current_offset
, format
);
374 if (strncmp(SUN_NAME
, (char *)buffer
, sizeof (SUN_NAME
)) == 0) {
375 manr
->vendor_name
[0] = 0x00;
376 manr
->vendor_name
[1] = 0x3e;
378 manr
->vendor_name
[0] = 0x00;
379 manr
->vendor_name
[1] = 0x00;
382 current_offset
+= 1; /* for length/type field */
384 current_offset
+= read_bd_fields(buffer
, current_offset
, format
);
385 current_offset
+= 1; /* for length/type field */
386 (void) memcpy(manr
->fru_short_name
, buffer
, MANR_FRUNAME_LEN
);
388 current_offset
+= read_bd_fields(buffer
, current_offset
, format
);
389 current_offset
+= 1; /* for length/type field */
390 (void) memcpy(manr
->sun_serial_no
, buffer
, MANR_SERIALNUM_LEN
);
392 current_offset
+= read_bd_fields(buffer
, current_offset
, format
);
393 current_offset
+= 1; /* for length/type field */
394 (void) memcpy(manr
->sun_part_no
, buffer
, MANR_PARTNUM_LEN
);
397 * We dont need the FRU FILE ID, so just skip the field
398 * and get the offset to read the custom MFG. info fields
400 current_offset
+= read_bd_fields(buffer
, current_offset
, format
);
401 current_offset
+= 1; /* for length/type field */
403 current_offset
+= read_bd_fields(buffer
, current_offset
, format
);
404 current_offset
+= 1; /* for length/type field */
406 /* read the custom mfg. info fields */
407 current_offset
+= read_bd_fields(buffer
, current_offset
, format
);
408 current_offset
+= 1; /* for length/type field */
409 (void) memcpy(manr
->manufacture_loc
, buffer
, MANR_MFRLOC_LEN
);
411 current_offset
+= read_bd_fields(buffer
, current_offset
, format
);
412 (void) memcpy(manr
->fru_descr
, buffer
, MANR_FRUDESCR_LEN
);
419 * Read the IPMI information from hardware and translate it into
423 get_manr(format_t
*format
, payload_t
*manr
)
426 fruid_offset_t
*offset
= NULL
;
428 offset
= (fruid_offset_t
*)malloc(sizeof (fruid_offset_t
));
429 if (offset
== NULL
) {
433 ret
= read_common_header(offset
, format
);
439 if (offset
->board
!= 0) {
440 ret
= read_board_info(offset
->board
, manr
, format
);
448 convert_to_ascii(uint8_t data
[], uint8_t store
[],
449 int length
, int extra_bytes
)
453 int i
, idx
= length
- (length
% 3);
455 for (i
= 0; ; i
+= 3) {
460 if (i
== idx
&& extra_bytes
== 0) {
464 /* get the first six bits */
465 x
= (data
[i
] & BIT_MASK1
);
469 if (i
== idx
&& extra_bytes
== 1) {
474 * get last 2 bits of first byte and first
475 * 4 bits of second byte
479 y
= (data
[i
+ 1] & BIT_MASK2
) << 2;
487 /* get last 4 bits of second byte and 2 bits of last byte */
488 x
= data
[i
+ 1] >> 4;
489 y
= (data
[i
+ 2] & BIT_MASK3
) << 4;
493 /* get last six bits of third byte */
494 store
[index
+ 3] = (data
[i
+ 2] >> 2) + ASCII_MAP
;
500 bcdplus_to_ascii(uint8_t data
[], uint8_t store
[], int len
)
510 for (i
= 0; i
< len
; i
++) {
511 (void) memcpy(&val
, &data
[i
], 1);
512 for (j
= 0; j
< 2; j
++) {
519 /* ascii conversion */
520 store
[index
++] = tmp
+ 48;
527 store
[index
++] = ' ';
530 store
[index
++] = '-';
533 store
[index
++] = '.';
536 store
[index
++] = ' ';
542 /* converts ipmi format time to UTC time (unix 32 bit timestamp) */
544 get_utc_time(uint8_t data
[])
550 (void) memcpy(&ipmi_time
, data
, 4);
552 ipmi_time
*= 60; /* convert into seconds */
554 /* get UTC time for 0:00 1/1/96 (ipmi epoch) */
569 * routine to write information to BMC
572 write_alarm_fru_data(const void *buffer
, size_t size
,
573 off_t offset
, format_t
*format
)
577 uint8_t *datap
= NULL
;
579 if (buffer
== NULL
) {
582 datap
= (uint8_t *)malloc(sizeof (uint8_t) * (size
+ 5));
587 datap
[0] = 0x7; /* bus id */
588 datap
[1] = 0xa0; /* slave address */
589 datap
[2] = 0; /* count */
590 datap
[3] = offset
>> 8; /* MSB */
591 datap
[4] = (uint8_t)offset
; /* LSB */
592 (void) memcpy((void *)&(datap
[5]), buffer
, size
);
594 /* initialize ipmi request packet */
595 (void) smc_init_ipmi_msg(&req_pkt
, SMC_MASTER_WR_RD_I2C
,
596 FRUACCESS_MSG_ID
, (5 + size
), datap
, DEFAULT_SEQN
,
597 format
->dest
, SMC_NETFN_APP_REQ
, SMC_BMC_LUN
);
600 /* send ipmi request packet */
601 if (smc_send_msg(DEFAULT_FD
, &req_pkt
, &res_pkt
,
602 POLL_TIMEOUT
) != SMC_SUCCESS
) {
605 /* check the completion code */
606 if (res_pkt
.data
[7] != 0) {
613 write_fru_data(const void *buffer
, size_t size
,
614 off_t offset
, format_t
*format
)
619 uint8_t *datap
= NULL
;
621 if (buffer
== NULL
) {
625 if (format
->src
== format
->dest
) {
633 case 0: /* on board info (local i2c) */
635 SC_MSG_CMD(&req_pkt
) = SMC_EEPROM_WRITE
;
636 SC_MSG_LEN(&req_pkt
) = 4 + size
;
637 SC_MSG_ID(&req_pkt
) = FRUACCESS_MSG_ID
;
639 /* data field for request */
640 req_pkt
.data
[0] = format
->sun_device_id
; /* device id */
641 req_pkt
.data
[1] = offset
; /* (LSB) */
642 req_pkt
.data
[3] = size
;
643 if (format
->format
== SUN_FORMAT
) {
644 req_pkt
.data
[2] = offset
>> 8;
646 req_pkt
.data
[2] = 0x0; /* (MSB) always 0x0 for IPMI */
648 (void) memcpy((void *)&(req_pkt
.data
[4]), buffer
, size
);
650 /* make a call to smc library to send cmd */
651 if (smc_send_msg(DEFAULT_FD
, &req_pkt
, &res_pkt
,
652 POLL_TIMEOUT
) != SMC_SUCCESS
) {
657 default: /* read data from remote device (ipmi) */
658 datap
= (uint8_t *)malloc(sizeof (uint8_t) * (size
+ 4));
663 datap
[0] = format
->sun_device_id
; /* device id */
664 datap
[1] = offset
; /* LSB */
665 datap
[3] = size
; /* nbytes */
666 if (format
->format
== SUN_FORMAT
) {
667 datap
[2] = offset
>> 8;
669 datap
[2] = 0x0; /* (MSB) always 0x0 for IPMI */
671 (void) memcpy((void *)&(datap
[4]), buffer
, size
);
673 (void) smc_init_ipmi_msg(&req_pkt
, WRITE_FRU_INVENTORY_DATA
,
674 FRUACCESS_MSG_ID
, (4 + size
), datap
, DEFAULT_SEQN
,
675 format
->dest
, SMC_NETFN_STORAGE_REQ
, format
->sun_lun
);
678 if (smc_send_msg(DEFAULT_FD
, &req_pkt
, &res_pkt
,
679 POLL_TIMEOUT
) != SMC_SUCCESS
) {
682 /* check the completion code */
683 if (res_pkt
.data
[7] != 0) {
687 } /* end of switch */
692 * This routine splits the data to write into smaller chunks and
693 * write it to FRUID chip using SMC drv APIs
698 pwrite_new(int fd
, const void *buffer
, size_t size
,
699 off_t offset
, format_t
*format
)
704 off_t next_offset
= 0x0;
705 off_t curr_offset
= offset
;
706 size_t bytes_to_write
= size
;
709 int (* func_ptr
)(const void *, size_t, off_t
, format_t
*);
711 if (format
->dest
== 0x20) {
712 func_ptr
= write_alarm_fru_data
;
714 func_ptr
= write_fru_data
;
717 data
= (uint8_t *)buffer
;
718 while (bytes_to_write
!= 0) {
723 if (bytes_to_write
> SIZE_TO_READ_WRITE
) {
724 bytes
= SIZE_TO_READ_WRITE
;
725 next_offset
= curr_offset
+ SIZE_TO_READ_WRITE
;
727 bytes
= bytes_to_write
;
730 bytes_to_write
= bytes_to_write
- bytes
;
731 while ((ret
!= 0) && (retry
!= 0)) {
732 ret
= (*func_ptr
)((void *)&data
[index
],
733 bytes
, curr_offset
, format
);
739 index
= index
+ bytes
;
740 curr_offset
= next_offset
;
746 * This routine reads the data in smaller chunks and
747 * sends it to upper layer(frudata plugin) in the sw stack
751 pread_new(int fd
, void *buffer
, size_t size
,
752 off_t offset
, format_t
*format
)
757 off_t next_offset
= 0x0;
758 off_t curr_offset
= offset
;
759 size_t bytes_to_read
= size
;
762 int (* func_ptr
)(int, int, void *, format_t
*);
764 if (format
->dest
== 0x20) {
765 func_ptr
= get_alarm_fru_data
;
767 func_ptr
= get_fru_data
;
770 data
= (uint8_t *)buffer
;
772 while (bytes_to_read
!= 0) {
777 if (bytes_to_read
> SIZE_TO_READ_WRITE
) {
778 bytes
= SIZE_TO_READ_WRITE
;
779 next_offset
= curr_offset
+ SIZE_TO_READ_WRITE
;
781 bytes
= bytes_to_read
;
784 bytes_to_read
= bytes_to_read
- bytes
;
786 while ((ret
!= 0) && (retry
!= 0)) {
787 ret
= (* func_ptr
)(curr_offset
, bytes
,
788 (void *) &data
[index
], format
);
794 index
= index
+ bytes
;
795 curr_offset
= next_offset
;
801 * routine to check if IPMI fruid info is available,
802 * return 0: IPMI fruid not present
803 * return 1: IPMI fruid present
806 is_ipmi_fru_data_available(int src
, int dest
)
812 /* on board access */
815 SC_MSG_CMD(&req_pkt
) = SMC_EEPROM_READ
;
816 SC_MSG_LEN(&req_pkt
) = 4;
817 SC_MSG_ID(&req_pkt
) = FRUACCESS_MSG_ID
;
819 /* data field for request */
820 req_pkt
.data
[0] = 0x0; /* eeprom number (ipmi format) */
821 req_pkt
.data
[1] = CMN_HDR_OFFSET
; /* (LSB) */
822 req_pkt
.data
[2] = 0x0; /* (MSB) always 0x0 for IPMI */
823 req_pkt
.data
[3] = IPMI_COMMON_HEADER_SIZE
;
825 /* make a call to smc library to send cmd */
826 if (smc_send_msg(DEFAULT_FD
, &req_pkt
, &res_pkt
,
827 POLL_TIMEOUT
) != SMC_SUCCESS
) {
832 if (res_pkt
.data
[0] != IPMI_VERSION
) {
840 datap
[0] = FRU_DEVICE_ID
; /* fru device id - always */
841 datap
[1] = 0x0; /* LSB */
842 datap
[2] = 0x0; /* MSB */
843 datap
[3] = 8; /* bytes to read */
845 (void) smc_init_ipmi_msg(&req_pkt
, READ_FRU_INVENTORY_DATA
,
846 FRUACCESS_MSG_ID
, 4, datap
, DEFAULT_SEQN
,
847 IPMB_ADDR(dest
), SMC_NETFN_STORAGE_REQ
, SMC_BMC_LUN
);
849 if (smc_send_msg(DEFAULT_FD
, &req_pkt
, &res_pkt
,
850 FRUID_CHECK_POLL_TIMEOUT
) != SMC_SUCCESS
) {
854 if (res_pkt
.data
[9] == IPMI_VERSION
) {
862 * routine to check if fruid info is available on BMC,
863 * return 0: fruid not present
864 * return 1: fruid present
867 is_alarm_frudata_available(format_t
*fru_format
)
870 char buffer
[TMP_BUFFER_SIZE
];
874 bzero(buffer
, sizeof (buffer
));
875 format
.src
= fru_format
->src
;
876 format
.dest
= fru_format
->dest
;
877 format
.sun_device_id
= 0x0;
878 format
.sun_lun
= 0x0;
879 format
.format
|= SUN_FORMAT
;
881 /* passing dummy fd */
882 /* for now read the first 3 bytes and check the info */
883 ret
= pread_new(fd
, (void *) buffer
, 3, STATIC_OFFSET
, &format
);
888 if (buffer
[0] != SECTION_HDR_TAG
) {
889 fru_format
->format
= NO_FRUDATA
;
893 fru_format
->format
= SUN_FORMAT
;
894 fru_format
->sun_device_id
= 0x0;
895 fru_format
->sun_lun
= 0x0;
900 * checks if the remote device intelligent device (IPMI capable) or not
901 * return 0: not ipmi capable
902 * return 1: ipmi capable
905 is_ipmi_capable(int src
, int dest
)
914 (void) smc_init_ipmi_msg(&req_pkt
, IPMI_GET_DEVICE_ID
,
915 FRUACCESS_MSG_ID
, 0, NULL
, DEFAULT_SEQN
,
916 IPMB_ADDR(dest
), SMC_NETFN_APP_REQ
, SMC_BMC_LUN
);
918 if (smc_send_msg(DEFAULT_FD
, &req_pkt
, &res_pkt
,
919 FRUID_CHECK_POLL_TIMEOUT
) != SMC_SUCCESS
) {
922 return (1); /* got response */
926 is_fru_data_available(int precedence
, int slot_no
, format_t
*fru_format
)
929 uint8_t data
[TMP_BUFFER_SIZE
];
931 fru_format
->format
= NO_FRUDATA
;
932 if (fru_format
->dest
== 0x20) { /* alarm card */
933 ret
= is_alarm_frudata_available(fru_format
);
937 if (cpu_no
== 0) { /* get the geo_addr */
942 /* initialize the request packet */
943 (void) smc_init_smc_msg(&req_pkt
,
944 SMC_GET_GEOGRAPHICAL_ADDRESS
, DEFAULT_SEQN
, size
);
945 /* make a call to smc library to send cmd */
946 if (smc_send_msg(DEFAULT_FD
, &req_pkt
, &rsp_pkt
,
947 POLL_TIMEOUT
) != SMC_SUCCESS
) {
950 if (SC_MSG_LEN(&rsp_pkt
) == 0) {
953 cpu_no
= rsp_pkt
.data
[0];
956 /* check if it is IPMI intelligent or not */
957 if (slot_no
!= cpu_no
) {
958 ret
= is_ipmi_capable(cpu_no
, slot_no
);
959 if (ret
== 0) { /* dumb I/O card */
964 /* check if ipmi frudata is present or not */
965 ret
= is_ipmi_fru_data_available(cpu_no
, slot_no
);
967 fru_format
->format
|= IPMI_FORMAT
;
968 fru_format
->sun_device_id
= 0x0;
969 fru_format
->sun_lun
= 0x0;
971 /* no need to look for sun format */
972 if (precedence
== IPMI_FORMAT
) {
973 return (fru_format
->format
);
977 /* check if sun fruid is present */
978 get_fru_data_info(cpu_no
, slot_no
, fru_format
);
979 /* check the hdr version */
980 if (fru_format
->format
& SUN_FORMAT
) {
981 ret
= pread_new(fd
, &data
, BYTE_TO_READ_SUN_CHK
,
982 STATIC_OFFSET
, fru_format
);
983 if (ret
!= BYTE_TO_READ_SUN_CHK
) {
984 fru_format
->format
= fru_format
->format
&
986 fru_format
->sun_device_id
= 0x0;
987 fru_format
->sun_lun
= 0x0;
989 if (data
[0] != SECTION_HDR_TAG
) {
990 fru_format
->format
= fru_format
->format
&
992 fru_format
->sun_device_id
= 0x0;
993 fru_format
->sun_lun
= 0x0;
996 return (fru_format
->format
);