/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */
/*
 * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

#ifndef	_LIBIPMI_H
#define	_LIBIPMI_H

#pragma ident	"%Z%%M%	%I%	%E% SMI"

#include <sys/bmc_intf.h>
#include <sys/byteorder.h>
#include <sys/sysmacros.h>

/*
 * Private interfaces for communicating with attached services over IPMI.  This
 * library is designed for system software communicating with Sun-supported
 * service processors over /dev/bmc.  It is not a generic IPMI library.
 *
 * Documentation references refer to "Intelligent Platform Management Interface
 * Specification Second Generation v2.0", document revision 1.0 with Februrary
 * 15, 2006 Markup from "IPMI v2.0 Addenda, Errata, and Clarifications Revision
 * 3".
 */

#ifdef	__cplusplus
extern "C" {
#endif

typedef struct ipmi_handle ipmi_handle_t;

#pragma pack(1)

/*
 * Basic netfn definitions.  See section 5.1.
 */
#define	IPMI_NETFN_APP			BMC_NETFN_APP
#define	IPMI_NETFN_STORAGE		BMC_NETFN_STORAGE
#define	IPMI_NETFN_SE			BMC_NETFN_SE
#define	IPMI_NETFN_OEM			0x2e

/*
 * Error definitions
 */
#define	EIPMI_BASE	2000

typedef enum {
	EIPMI_NOMEM = EIPMI_BASE,	/* memory allocation failure */
	EIPMI_BMC_OPEN_FAILED,		/* failed to open /dev/bmc */
	EIPMI_BMC_PUTMSG,		/* failed to send message to /dev/bmc */
	EIPMI_BMC_GETMSG,	/* failed to read response from /dev/bmc */
	EIPMI_BMC_RESPONSE,		/* response from /dev/bmc failed */
	EIPMI_INVALID_COMMAND,		/* invalid command */
	EIPMI_COMMAND_TIMEOUT,		/* command timeout */
	EIPMI_DATA_LENGTH_EXCEEDED,	/* maximum data length exceeded */
	EIPMI_SEND_FAILED,		/* failed to send BMC request */
	EIPMI_UNSPECIFIED,		/* unspecified BMC error */
	EIPMI_UNKNOWN,			/* unknown error */
	EIPMI_BAD_RESPONSE,		/* received unexpected response */
	EIPMI_BAD_RESPONSE_LENGTH,	/* unexpected response length */
	EIPMI_INVALID_RESERVATION,	/* invalid or cancelled reservation */
	EIPMI_NOT_PRESENT,		/* requested entity not present */
	EIPMI_INVALID_REQUEST,		/* malformed request data */
	EIPMI_BUSY,			/* service processor is busy */
	EIPMI_NOSPACE,			/* service processor is out of space */
	EIPMI_UNAVAILABLE,		/* service processor is unavailable */
	EIPMI_ACCESS			/* insufficient privileges */
} ipmi_errno_t;

/*
 * Basic library functions.
 *
 * The ipmi_handle is the primary interface to the library.  The library itself
 * is not MT-safe, but it is safe within a single handle.  Multithreaded clients
 * should either open multiple handles, or otherwise synchronize access to the
 * same handle.
 *
 * There is a single command response buffer that is stored with the handle, to
 * simplify memory management in the caller.  The memory referenced by a command
 * response is only valid until the next command is issued.  The caller is
 * responsible for making a copy of the response if it is needed.
 */
extern ipmi_handle_t *ipmi_open(int *, char **);
extern void ipmi_close(ipmi_handle_t *);

extern int ipmi_errno(ipmi_handle_t *);
extern const char *ipmi_errmsg(ipmi_handle_t *);

/*
 * Raw requests.  See section 5.
 */
typedef struct ipmi_cmd {
	uint8_t		ic_netfn:6;
	uint8_t		ic_lun:2;
	uint8_t		ic_cmd;
	uint16_t	ic_dlen;
	void		*ic_data;
} ipmi_cmd_t;

extern ipmi_cmd_t *ipmi_send(ipmi_handle_t *, ipmi_cmd_t *);

/*
 * Retrieve basic information about the IPMI device.  See section 20.1 "Get
 * Device ID Command".
 */
#define	IPMI_CMD_GET_DEVICEID		0x01

typedef struct ipmi_deviceid {
	uint8_t		id_devid;
	DECL_BITFIELD3(
	    id_dev_rev		:4,
	    __reserved		:3,
	    id_dev_sdrs		:1);
	DECL_BITFIELD2(
	    id_firm_major	:7,
	    id_dev_available	:1);
	uint8_t		id_firm_minor;
	uint8_t		id_ipmi_rev;
	uint8_t		id_dev_support;
	uint8_t		id_manufacturer[3];
	uint16_t	id_product;
} ipmi_deviceid_t;

#define	IPMI_OEM_SUN		0x2a
#define	IPMI_PROD_SUN_ILOM	0x4701

ipmi_deviceid_t *ipmi_get_deviceid(ipmi_handle_t *);

#define	ipmi_devid_manufacturer(dp)		\
	((dp)->id_manufacturer[0] |		\
	((dp)->id_manufacturer[1] << 8) |	\
	((dp)->id_manufacturer[2] << 16))

const char *ipmi_firmware_version(ipmi_handle_t *);

/*
 * SEL (System Event Log) commands.  Currently the library only provides
 * commands for reading the SEL.
 */

/*
 * 31.2 Get SEL Info Command
 */
#define	IPMI_CMD_GET_SEL_INFO		0x40

typedef struct ipmi_sel_info {
	uint8_t		isel_version;
	uint16_t	isel_entries;
	uint16_t	isel_free;
	uint32_t	isel_add_ts;
	uint32_t	isel_erase_ts;
	DECL_BITFIELD6(
	    isel_supp_allocation	:1,
	    isel_supp_reserve		:1,
	    isel_supp_partial		:1,
	    isel_supp_delete		:1,
	    __reserved			:3,
	    isel_overflow		:1);
} ipmi_sel_info_t;

extern ipmi_sel_info_t *ipmi_sel_get_info(ipmi_handle_t *);
extern boolean_t ipmi_sdr_changed(ipmi_handle_t *);
extern int ipmi_sdr_refresh(ipmi_handle_t *);

/*
 * 32.1 SEL Event Records
 */
typedef struct ipmi_sel_event {
	uint16_t	isel_ev_next;
	uint16_t	isel_ev_recid;
	uint8_t		isel_ev_rectype;
	uint32_t	isel_ev_ts;
	DECL_BITFIELD2(
	    isel_ev_software	:1,
	    isel_ev_addr_or_id	:7);
	DECL_BITFIELD3(
	    isel_ev_lun		:2,
	    __reserved		:2,
	    isel_ev_channel	:4);
	uint8_t		isel_ev_rev;
	uint8_t		isel_ev_sensor_type;
	uint8_t		isel_ev_sensor_number;
	DECL_BITFIELD2(
	    isel_ev_type	:7,
	    isel_ev_dir		:1);
	uint8_t		isel_ev_data[3];
} ipmi_sel_event_t;

#define	IPMI_EV_REV15		0x04
#define	IPMI_EV_REV1		0x03

#define	IPMI_SEL_SYSTEM		0x02
#define	IPMI_SEL_OEMTS_LO	0xC0
#define	IPMI_SEL_OEMTS_HI	0xDF
#define	IPMI_SEL_OEM_LO		0xE0
#define	IPMI_SEL_OEM_HI		0xFF

#define	IPMI_EV_ASSERT		0x0
#define	IPMI_EV_DEASSERT	0x1

/*
 * 32.2 OEM SEL Record (with timestamp)
 */
typedef struct ipmi_sel_oem_ts {
	uint16_t	isel_oem_next;
	uint16_t	isel_oem_id;
	uint8_t		isel_oem_type;
	uint32_t	isel_oem_ts;
	uint8_t		isel_oem_devid[3];
	uint8_t		isel_oem_data[6];
} ipmi_sel_oem_ts_t;

/*
 * 32.3 OEM SEL Record (no timestamp)
 */
typedef struct ipmi_sel_oem {
	uint16_t	isel_oem_next;
	uint16_t	isel_oem_id;
	uint8_t		isel_oem_type;
	uint8_t		isel_oem_data[13];
} ipmi_sel_oem_t;

/*
 * 29.7 Event Data Field Formats.  Consumers can cast the data field of the
 * event record to the appropriate type depending on the sensor class.
 */

typedef struct ipmi_event_threshold {
	DECL_BITFIELD3(
	    iev_offset		:4,
	    iev_desc_byte3	:2,
	    iev_desc_byte2	:2);
	uint8_t		iev_reading;
	uint8_t		iev_threshold;
} ipmi_event_threshold_t;

#define	IPMI_EV_DESC_UNSPECIFIED	0x00
#define	IPMI_EV_DESC_TRIGGER		0x01
#define	IPMI_EV_DESC_OEM		0x02
#define	IPMI_EV_DESC_SPECIFIC		0x03

typedef struct ipmi_event_discrete {
	DECL_BITFIELD3(
	    iev_offset		:4,
	    iev_desc_byte3	:2,
	    iev_desc_byte2	:2);
	DECL_BITFIELD2(
	    iev_offset_type	:4,
	    iev_offset_severity	:4);
	uint8_t		iev_oem_code;
} ipmi_event_discrete_t;

#define	IPMI_EV_DESC_PREVSTATE		0x01
#define	IPMI_EV_DESC_SPECIFIC		0x03

typedef struct ipmi_event_oem {
	DECL_BITFIELD3(
	    iev_offset		:4,
	    iev_desc_byte3	:2,
	    iev_desc_byte2	:2);
	DECL_BITFIELD2(
	    iev_offset_type	:4,
	    iev_offset_severity	:4);
	uint8_t		iev_oem_code;
} ipmi_event_oem_t;

/*
 * Get SEL Entry Command.  See section 31.5.  We don't support partial reads, so
 * this interface is quite a bit simpler than in the spec.  We default to
 * returning event records, though the consumer should check the type field and
 * cast it to the appropriate type if it is no IPMI_SEL_SYSTEM.
 */
#define	IPMI_CMD_GET_SEL_ENTRY		0x43

extern ipmi_sel_event_t *ipmi_sel_get_entry(ipmi_handle_t *, uint16_t);

#define	IPMI_SEL_FIRST_ENTRY		0x0000
#define	IPMI_SEL_LAST_ENTRY		0xFFFF

/*
 * SEL time management.  See sections 31.10 and 31.11.
 */
#define	IPMI_CMD_GET_SEL_TIME		0x48
#define	IPMI_CMD_SET_SEL_TIME		0x49
#define	IPMI_CMD_GET_SEL_UTC_OFFSET	0x5C
#define	IPMI_CMD_SET_SEL_UTC_OFFSET	0x5D

extern int ipmi_sel_get_time(ipmi_handle_t *, uint32_t *);
extern int ipmi_sel_set_time(ipmi_handle_t *, uint32_t);
extern int ipmi_sel_get_utc_offset(ipmi_handle_t *, int *);
extern int ipmi_sel_set_utc_offset(ipmi_handle_t *, int);

/*
 * SDR (Sensor Device Record) requests.  A cache of the current SDR repository
 * is kept as part of the IPMI handle and updated when necessary.  This does the
 * work of processing the SDR names and providing an easy way to lookup
 * individual records and iterate over all records.
 */

/*
 * Get SDR Repository Info Command.  See section 33.9.
 */
#define	IPMI_CMD_GET_SDR_INFO		0x20

typedef struct ipmi_sdr_info {
	uint8_t		isi_version;
	uint16_t	isi_record_count;
	uint16_t	isi_free_space;
	uint32_t	isi_add_ts;
	uint32_t	isi_erase_ts;
	DECL_BITFIELD7(
	    isi_supp_allocation		:1,
	    isi_supp_reserve		:1,
	    isi_supp_partial		:1,
	    isi_supp_delete		:1,
	    __reserved			:1,
	    isi_modal			:2,
	    isi_overflow		:1);
} ipmi_sdr_info_t;

extern ipmi_sdr_info_t *ipmi_sdr_get_info(ipmi_handle_t *);

/*
 * Reserve repository command.  See section 33.11.
 */
#define	IPMI_CMD_RESERVE_SDR_REPOSITORY	0x22

/*
 * Get SDR command.  See section 33.12.  This command accesses the raw SDR
 * repository.  Clients can also use the lookup functions to retrieve a
 * particular SDR record by name.
 *
 * The list of possible types is indicated in the sub-chapters of section 43.
 */
typedef struct ipmi_sdr {
	uint16_t	is_id;
	uint8_t		is_version;
	uint8_t		is_type;
	uint8_t		is_length;
	uint8_t		is_record[1];
} ipmi_sdr_t;
#define	IPMI_CMD_GET_SDR		0x23

#define	IPMI_SDR_FIRST			0x0000
#define	IPMI_SDR_LAST			0xFFFF

extern ipmi_sdr_t *ipmi_sdr_get(ipmi_handle_t *, uint16_t, uint16_t *);

/*
 * Full Sensor Record.  See 43.1
 */
#define	IPMI_SDR_TYPE_FULL_SENSOR		0x01

typedef struct ipmi_sdr_full_sensor {
	/* RECORD KEY BYTES */
	uint8_t		is_fs_owner;
	DECL_BITFIELD3(
	    is_fs_sensor_lun			:2,
	    __reserved1				:2,
	    is_fs_channel			:4);
	uint8_t		is_fs_number;
	/* RECORD BODY BYTES */
	uint8_t		is_fs_entity_id;
	DECL_BITFIELD2(
	    is_fs_entity_instance		:7,
	    is_fs_entity_logical		:1);
	DECL_BITFIELD8(
	    is_fs_sensor_scanning_enabled	:1,
	    is_fs_event_generation_enabled	:1,
	    is_fs_init_sensor_type		:1,
	    is_fs_init_hysteresis		:1,
	    is_fs_init_thresholds		:1,
	    is_fs_init_events			:1,
	    is_fs_init_scanning			:1,
	    is_fs_settable			:1);
	DECL_BITFIELD5(
	    is_fs_event_support			:2,
	    is_fs_threshold_support		:2,
	    is_fs_hysteresis_support		:2,
	    is_fs_rearm_support			:1,
	    is_fs_ignore			:1);
	uint8_t		is_fs_type;
	uint8_t		is_fs_reading_type;
	uint16_t	is_fs_assert_mask;
	uint16_t	is_fs_deassert_mask;
	uint16_t	is_fs_reading_mask;
	DECL_BITFIELD4(
	    is_fs_units_isprcnt			:1,
	    is_fs_mod_unit			:2,
	    is_fs_rate_unit			:3,
	    is_fs_analog_fmt			:2);
	uint8_t		is_fs_unit2;
	uint8_t		is_fs_unit3;
	/* Linearization */
	DECL_BITFIELD2(
	    is_fs_sensor_linear_type		:7,
	    __reserved2				:1);
	/* M, Tolerance */
	uint16_t	is_fs_mtol;
	/* B, Accuracy, R exp, B exp */
	uint32_t	is_fs_bacc;
	DECL_BITFIELD4(
	    is_fs_nominal_reading_spec		:1,
	    is_fs_normal_max_spec		:1,
	    is_fs_normal_min_spec		:1,
	    __reserved3				:5);
	uint8_t	is_fs_nominal_reading;
	uint8_t	is_fs_normal_maximum;
	uint8_t	is_fs_normal_minimum;
	uint8_t	is_fs_max;
	uint8_t	is_fs_min;
	uint8_t is_fs_upper_nonrecov;
	uint8_t	is_fs_upper_critical;
	uint8_t	is_fs_upper_noncrit;
	uint8_t	is_fs_lower_nonrecov;
	uint8_t	is_fs_lower_critical;
	uint8_t	is_fs_lower_noncrit;
	uint8_t		is_fs_hysteresis_positive;
	uint8_t		is_fs_hysteresis_negative;
	uint16_t	__reserved4;
	uint8_t		is_fs_oem;
	DECL_BITFIELD3(
	    is_fs_idlen				:5,
	    __reserved5				:1,
	    is_fs_idtype			:2);
	char		is_fs_idstring[1];
} ipmi_sdr_full_sensor_t;

#define	IPMI_SDR_TYPE_COMPACT_SENSOR		0x02

/*
 * Compact Sensor Record.  See section 43.2
 */
typedef struct ipmi_sdr_compact_sensor {
	/* RECORD KEY BYTES */
	uint8_t		is_cs_owner;
	DECL_BITFIELD3(
	    is_cs_sensor_lun			:2,
	    is_cs_fru_lun			:2,
	    is_cs_channel			:4);
	uint8_t		is_cs_number;
	/* RECORD BODY BYTES */
	uint8_t		is_cs_entity_id;
	DECL_BITFIELD2(
	    is_cs_entity_instance		:7,
	    is_cs_entity_logical		:1);
	DECL_BITFIELD8(
	    is_cs_sensor_scanning_enabled	:1,
	    is_cs_event_generation_enabled	:1,
	    is_cs_init_sensor_type		:1,
	    is_cs_init_hysteresis		:1,
	    __reserved1				:1,
	    is_cs_init_events			:1,
	    is_cs_init_scanning			:1,
	    is_cs_settable			:1);
	DECL_BITFIELD5(
	    is_cs_event_support			:2,
	    is_cs_threshold_support		:2,
	    is_cs_hysteresis_support		:2,
	    is_cs_rearm_support			:1,
	    is_cs_ignore			:1);
	uint8_t		is_cs_type;
	uint8_t		is_cs_reading_type;
	uint16_t	is_cs_assert_mask;
	uint16_t	is_cs_deassert_mask;
	uint16_t	is_cs_reading_mask;
	DECL_BITFIELD4(
	    is_cs_units_isprcnt			:1,
	    is_cs_mod_unit			:2,
	    is_cs_rate_unit			:3,
	    __reserved2				:2);
	uint8_t		is_cs_unit2;
	uint8_t		is_cs_unit3;
	DECL_BITFIELD3(
	    is_cs_share_count			:4,
	    is_cs_modifier_type			:2,
	    is_cs_direction			:2);
	DECL_BITFIELD2(
	    is_cs_modifier_offset		:7,
	    is_cs_sharing			:1);
	uint8_t		is_cs_hysteresis_positive;
	uint8_t		is_cs_hysteresis_negative;
	uint16_t	__reserved3;
	uint8_t		__reserved4;
	uint8_t		is_cs_oem;
	DECL_BITFIELD3(
	    is_cs_idlen				:5,
	    __reserved5				:1,
	    is_cs_idtype			:2);
	char		is_cs_idstring[1];
} ipmi_sdr_compact_sensor_t;

/*
 * Threshold sensor masks for is_cs_assert_mask and is_cs_deassert_mask.
 */
#define	IPMI_SENSOR_RETURN_NONRECOV	0x4000
#define	IPMI_SENSOR_RETURN_CRIT		0x2000
#define	IPMI_SENSOR_RETURN_NONCRIT	0x1000

#define	IPMI_SENSOR_MASK_UPPER_NONRECOV_HI	0x0800
#define	IPMI_SENSOR_MASK_UPPER_NONRECOV_LO	0x0400
#define	IPMI_SENSOR_MASK_UPPER_CRIT_HI		0x0200
#define	IPMI_SENSOR_MASK_UPPER_CRIT_LO		0x0100
#define	IPMI_SENSOR_MASK_UPPER_NONCRIT_HI	0x0080
#define	IPMI_SENSOR_MASK_UPPER_NONCRIT_LO	0x0040
#define	IPMI_SENSOR_MASK_LOWER_NONRECOV_HI	0x0020
#define	IPMI_SENSOR_MASK_LOWER_NONRECOV_LO	0x0010
#define	IPMI_SENSOR_MASK_LOWER_CRIT_HI		0x0008
#define	IPMI_SENSOR_MASK_LOWER_CRIT_LO		0x0004
#define	IPMI_SENSOR_MASK_LOWER_NONCRIT_HI	0x0002
#define	IPMI_SENSOR_MASK_LOWER_NONCRIT_LO	0x0001

/*
 * Threshold sensor masks for is_cs_reading_mask.
 */
#define	IPMI_SENSOR_SETTABLE_UPPER_NONRECOV	0x2000
#define	IPMI_SENSOR_SETTABLE_UPPER_CRIT		0x1000
#define	IPMI_SENSOR_SETTABLE_UPPER_NONCRIT	0x0800
#define	IPMI_SENSOR_SETTABLE_LOWER_NONRECOV	0x0400
#define	IPMI_SENSOR_SETTABLE_LOWER_CRIT		0x0200
#define	IPMI_SENSOR_SETTABLE_LOWER_NONCRIT	0x0100
#define	IPMI_SENSOR_READABLE_UPPER_NONRECOV	0x0020
#define	IPMI_SENSOR_READABLE_UPPER_CRIT		0x0010
#define	IPMI_SENSOR_READABLE_UPPER_NONCRIT	0x0008
#define	IPMI_SENSOR_READABLE_LOWER_NONRECOV	0x0004
#define	IPMI_SENSOR_READABLE_LOWER_CRIT		0x0002
#define	IPMI_SENSOR_READABLE_LOWER_NONCRIT	0x0001

/*
 * Values for is_cs_reading_type.  See table 42-2.
 */
#define	IPMI_RT_THRESHOLD			0x01
#define	IPMI_RT_USAGE				0x02
#define	IPMI_RT_STATE				0x03
#define	IPMI_RT_PREDFAIL			0x04
#define	IPMI_RT_LIMIT				0x05
#define	IPMI_RT_PERFORMANCE			0x06
#define	IPMI_RT_SEVERITY			0x07
#define	IPMI_RT_PRESENT				0x08
#define	IPMI_RT_ENABLED				0x09
#define	IPMI_RT_AVAILABILITY			0x0A
#define	IPMI_RT_REDUNDANCY			0x0B
#define	IPMI_RT_ACPI				0x0C
#define	IPMI_RT_SPECIFIC			0x6F

/*
 * Bitmasks based on above reading types.  See table 42-2
 */
#define	IPMI_SR_THRESHOLD_LOWER_NONCRIT_LOW	0x0001
#define	IPMI_SR_THRESHOLD_LOWER_NONCRIT_HIGH	0x0002
#define	IPMI_SR_THRESHOLD_LOWER_CRIT_LOW	0x0004
#define	IPMI_SR_THRESHOLD_LOWER_CRIT_HIGH	0x0008
#define	IPMI_SR_THRESHOLD_LOWER_NONRECOV_LOW	0x0010
#define	IPMI_SR_THRESHOLD_LOWER_NONRECOV_HIGH	0x0020
#define	IPMI_SR_THRESHOLD_UPPER_NONCRIT_LOW	0x0040
#define	IPMI_SR_THRESHOLD_UPPER_NONCRIT_HIGH	0x0080
#define	IPMI_SR_THRESHOLD_UPPER_CRIT_LOW	0x0100
#define	IPMI_SR_THRESHOLD_UPPER_CRIT_HIGH	0x0200
#define	IPMI_SR_THRESHOLD_UPPER_NONRECOV_LOW	0x0400
#define	IPMI_SR_THRESHOLD_UPPER_NONRECOV_HIGH	0x0800

#define	IPMI_SR_USAGE_IDLE			0x0001
#define	IPMI_SR_USAGE_ACTIVE			0x0002
#define	IPMI_SR_USAGE_BUSY			0x0004

#define	IPMI_SR_STATE_DEASSERT			0x0001
#define	IPMI_SR_STATE_ASSERT			0x0002

#define	IPMI_SR_PREDFAIL_DEASSERT		0x0001
#define	IPMI_SR_PREDFAIL_ASSERT			0x0002

#define	IPMI_SR_LIMIT_NOTEXCEEDED		0x0001
#define	IPMI_SR_LIMIT_EXCEEDED			0x0002

#define	IPMI_SR_PERFORMANCE_MET			0x0001
#define	IPMI_SR_PERFORMANCE_LAGS		0x0002

#define	IPMI_SR_SEVERITY_TO_OK			0x0001
#define	IPMI_SR_SEVERITY_OK_TO_NONCRIT		0x0002
#define	IPMI_SR_SEVERITY_LESS_TO_CRIT		0x0004
#define	IPMI_SR_SEVERITY_LESS_TO_NONRECOV	0x0008
#define	IPMI_SR_SEVERITY_MORE_TO_NONCRIT	0x0010
#define	IPMI_SR_SEVERITY_NONRECOV_TO_CRIT	0x0020
#define	IPMI_SR_SEVERITY_TO_NONRECOV		0x0040
#define	IPMI_SR_SEVERITY_MONITOR		0x0080
#define	IPMI_SR_SEVERITY_INFO			0x0100

#define	IPMI_SR_PRESENT_DEASSERT		0x0001
#define	IPMI_SR_PRESENT_ASSERT			0x0002

#define	IPMI_SR_ENABLED_DEASSERT		0x0001
#define	IPMI_SR_ENABLED_ASSERT			0x0002

#define	IPMI_SR_AVAILABILITY_RUNNING		0x0001
#define	IPMI_SR_AVAILABILITY_INTEST		0x0002
#define	IPMI_SR_AVAILABILITY_POWEROFF		0x0004
#define	IPMI_SR_AVAILABILITY_ONLINE		0x0008
#define	IPMI_SR_AVAILABILITY_OFFLINE		0x0010
#define	IPMI_SR_AVAILABILITY_OFFDUTY		0x0020
#define	IPMI_SR_AVAILABILITY_DEGRADED		0x0040
#define	IPMI_SR_AVAILABILITY_POWERSAVE		0x0080
#define	IPMI_SR_AVAILABILITY_INSTALLERR		0x0100

#define	IPMI_SR_REDUNDANCY_FULL			0x0001
#define	IPMI_SR_REDUNDANCY_LOST			0x0002
#define	IPMI_SR_REDUNDANCY_DEGRADED		0x0004
#define	IPMI_SR_REDUNDANCY_NONE_MINIMAL		0x0008
#define	IPMI_SR_REDUNDANCY_NONE_REGAINED	0x0010
#define	IPMI_SR_REDUNDANCY_NONE_INSUFFFICIENT	0x0020
#define	IPMI_SR_REDUNDANCY_DEG_FROM_FULL	0x0040
#define	IPMI_SR_REDUNDANCY_DEG_FROM_NON		0x0080

#define	IPMI_SR_ACPI_DO				0x0001
#define	IPMI_SR_ACPI_D1				0x0002
#define	IPMI_SR_ACPI_D2				0x0004
#define	IPMI_SR_ACPI_D3				0x0008

/*
 * Bitmasks for sensor-specific reading type (0x6F).  See section 42.2.
 */
#define	IPMI_ST_RESERVED			0x00
#define	IPMI_ST_TEMP				0x01
#define	IPMI_ST_VOLTAGE				0x02
#define	IPMI_ST_CURRENT				0x03
#define	IPMI_ST_FAN				0x04
#define	IPMI_ST_PHYSICAL			0x05

#define	IPMI_EV_PHYSICAL_GENERAL		0x0001
#define	IPMI_EV_PHYSICAL_BAY			0x0002
#define	IPMI_EV_PHYSICAL_CARD			0x0004
#define	IPMI_EV_PHYSICAL_PROCESSOR		0x0008
#define	IPMI_EV_PHYSICAL_LAN			0x0010
#define	IPMI_EV_PHYSICAL_DOCK			0x0020
#define	IPMI_EV_PHYSICAL_FAN			0x0040

#define	IPMI_ST_PLATFORM			0x06

#define	IPMI_EV_PLATFORM_SECURE			0x0001
#define	IPMI_EV_PLATFORM_USER_PASS		0x0002
#define	IPMI_EV_PLATFORM_SETUP_PASS		0x0004
#define	IPMI_EV_PLATFORM_NETWORK_PASS		0x0008
#define	IPMI_EV_PLATFORM_OTHER_PASS		0x0010
#define	IPMI_EV_PLATFORM_OUT_OF_BAND		0x0020

#define	IPMI_ST_PROCESSOR			0x07

#define	IPMI_EV_PROCESSOR_IERR			0x0001
#define	IPMI_EV_PROCESSOR_THERMAL		0x0002
#define	IPMI_EV_PROCESSOR_FRB1			0x0004
#define	IPMI_EV_PROCESSOR_FRB2			0x0008
#define	IPMI_EV_PROCESSOR_FRB3			0x0010
#define	IPMI_EV_PROCESSOR_CONFIG		0x0020
#define	IPMI_EV_PROCESSOR_SMBIOS		0x0040
#define	IPMI_EV_PROCESSOR_PRESENT		0x0080
#define	IPMI_EV_PROCESSOR_DISABLED		0x0100
#define	IPMI_EV_PROCESSOR_TERMINATOR		0x0200
#define	IPMI_EV_PROCESSOR_THROTTLED		0x0400

#define	IPMI_ST_POWER_SUPPLY			0x08

#define	IPMI_EV_POWER_SUPPLY_PRESENT		0x0001
#define	IPMI_EV_POWER_SUPPLY_FAILURE		0x0002
#define	IPMI_EV_POWER_SUPPLY_PREDFAIL		0x0004
#define	IPMI_EV_POWER_SUPPLY_INPUT_LOST		0x0008
#define	IPMI_EV_POWER_SUPPLY_INPUT_RANGE	0x0010
#define	IPMI_EV_POWER_SUPPLY_INPUT_RANGE_PRES	0x0020
#define	IPMI_EV_POWER_SUPPLY_CONFIG_ERR		0x0040

#define	IPMI_ST_POWER_UNIT			0x09

#define	IPMI_EV_POWER_UNIT_OFF			0x0001
#define	IPMI_EV_POWER_UNIT_CYCLE		0x0002
#define	IPMI_EV_POWER_UNIT_240_DOWN		0x0004
#define	IPMI_EV_POWER_UNIT_INTERLOCK_DOWN	0x0008
#define	IPMI_EV_POWER_UNIT_AC_LOST		0x0010
#define	IPMI_EV_POWER_UNIT_SOFT_FAILURE		0x0020
#define	IPMI_EV_POWER_UNIT_FAIL			0x0040
#define	IPMI_EV_POWER_UNIT_PREDFAIL		0x0080

#define	IPMI_ST_COOLING				0x0A
#define	IPMI_ST_OTHER				0x0B
#define	IPMI_ST_MEMORY				0x0C

#define	IPMI_EV_MEMORY_CE			0x0001
#define	IPMI_EV_MEMORY_UE			0x0002
#define	IPMI_EV_MEMORY_PARITY			0x0004
#define	IPMI_EV_MEMORY_SCRUB_FAIL		0x0008
#define	IPMI_EV_MEMORY_DISABLED			0x0010
#define	IPMI_EV_MEMORY_CE_LOG_LIMIT		0x0020
#define	IPMI_EV_MEMORY_PRESENT			0x0040
#define	IPMI_EV_MEMORY_CONFIG_ERR		0x0080
#define	IPMI_EV_MEMORY_SPARE			0x0100
#define	IPMI_EV_MEMORY_THROTTLED		0x0200
#define	IPMI_EV_MEMORY_OVERTEMP			0x0400

#define	IPMI_ST_BAY				0x0D

#define	IPMI_EV_BAY_PRESENT			0x0001
#define	IPMI_EV_BAY_FAULT			0x0002
#define	IPMI_EV_BAY_PREDFAIL			0x0004
#define	IPMI_EV_BAY_SPARE			0x0008
#define	IPMI_EV_BAY_CHECK			0x0010
#define	IPMI_EV_BAY_CRITICAL			0x0020
#define	IPMI_EV_BAY_FAILED			0x0040
#define	IPMI_EV_BAY_REBUILDING			0x0080
#define	IPMI_EV_BAY_ABORTED			0x0100

#define	IPMI_ST_POST_RESIZE			0x0E
#define	IPMI_ST_FIRMWARE			0x0F

#define	IPMI_EV_FIRMWARE_ERROR			0x0001
#define	IPMI_EV_FIRMWARE_HANG			0x0002
#define	IPMI_EV_FIRMWARE_PROGRESS		0x0004

#define	IPMI_ST_EVENT_LOG			0x10

#define	IPMI_EV_EVENT_LOG_CE			0x0001
#define	IPMI_EV_EVENT_LOG_TYPE			0x0002
#define	IPMI_EV_EVENT_LOG_RESET			0x0004
#define	IPMI_EV_EVENT_LOG_ALL			0x0008
#define	IPMI_EV_EVENT_LOG_FULL			0x0010
#define	IPMI_EV_EVENT_LOG_ALMOST_FULL		0x0020

#define	IPMI_ST_WATCHDOG1			0x11

#define	IPMI_EV_WATCHDOG_BIOS_RESET		0x0001
#define	IPMI_EV_WATCHDOG_OS_RESET		0x0002
#define	IPMI_EV_WATCHDOG_OS_SHUTDOWN		0x0004
#define	IPMI_EV_WATCHDOG_OS_PWR_DOWN		0x0008
#define	IPMI_EV_WATCHDOG_OS_PWR_CYCLE		0x0010
#define	IPMI_EV_WATCHDOG_OS_NMI_DIAG		0x0020
#define	IPMI_EV_WATCHDOG_EXPIRED		0x0040
#define	IPMI_EV_WATCHDOG_PRE_TIMEOUT_INT	0x0080

#define	IPMI_ST_SYSTEM				0x12

#define	IPMI_EV_STSTEM_RECONF			0x0001
#define	IPMI_EV_STSTEM_BOOT			0x0002
#define	IPMI_EV_STSTEM_UNKNOWN_HW_FAILURE	0x0004
#define	IPMI_EV_STSTEM_AUX_LOG_UPDATED		0x0008
#define	IPMI_EV_STSTEM_PEF_ACTION		0x0010
#define	IPMI_EV_SYSTEM_TIMETAMP_CLOCKSYNC	0x0020

#define	IPMI_ST_CRITICAL			0x13

#define	IPMI_EV_CRITICAL_EXT_NMI		0x0001
#define	IPMI_EV_CRITICAL_BUS_TIMOEOUT		0x0002
#define	IPMI_EV_CRITICAL_IO_NMI			0x0004
#define	IPMI_EV_CRITICAL_SW_NMI			0x0008
#define	IPMI_EV_CRITICAL_PCI_PERR		0x0010
#define	IPMI_EV_CRITICAL_PCI_SERR		0x0020
#define	IPMI_EV_CRITICAL_EISA_FAILSAFE		0x0040
#define	IPMI_EV_CRITICAL_BUS_CE			0x0080
#define	IPMI_EV_CRITICAL_BUS_UE			0x0100
#define	IPMI_EV_CRITICAL_FATAL_NMI		0x0200
#define	IPMI_EV_CRITICAL_BUS_FATAL_ERR		0x0400
#define	IPMI_EV_CRITICAL_BUS_DEGRADED		0x0800

#define	IPMI_ST_BUTTON				0x14

#define	IPMI_EV_BUTTON_PWR			0x0001
#define	IPMI_EV_BUTTON_SLEEP			0x0002
#define	IPMI_EV_BUTTON_RESET			0x0004
#define	IPMI_EV_BUTTON_FRU_LATCH		0x0008
#define	IPMI_EV_BUTTON_FRU_SERVICE		0x0010

#define	IPMI_ST_MODULE				0x15
#define	IPMI_ST_MICROCONTROLLER			0x16
#define	IPMI_ST_CARD				0x17
#define	IPMI_ST_CHASSIS				0x18

#define	IPMI_ST_CHIPSET				0x19

#define	IPMI_EV_CHIPSET_PWR_CTL_FAIL		0x0001

#define	IPMI_ST_FRU				0x1A
#define	IPMI_ST_CABLE				0x1B

#define	IPMI_EV_CABLE_CONNECTED			0x0001
#define	IPMI_EV_CABLE_CONFIG_ERR		0x0002

#define	IPMI_ST_TERMINATOR			0x1C

#define	IPMI_ST_BOOT				0x1D

#define	IPMI_EV_BOOT_BIOS_PWR_UP		0x0001
#define	IPMI_EV_BOOT_BIOS_HARD_RESET		0x0002
#define	IPMI_EV_BOOT_BIOS_WARM_RESET		0x0004
#define	IPMI_EV_BOOT_PXE_BOOT			0x0008
#define	IPMI_EV_BOOT_DIAG_BOOT			0x0010
#define	IPMI_EV_BOOT_OS_HARD_RESET		0x0020
#define	IPMI_EV_BOOT_OS_WARM_RESET		0x0040
#define	IPMI_EV_BOOT_SYS_RESTART		0x0080

#define	IPMI_ST_BOOT_ERROR			0x1E

#define	IPMI_EV_BOOT_ERROR_NOMEDIA		0x0001
#define	IPMI_EV_BOOT_ERROR_NON_BOOTABLE_DISK	0x0002
#define	IPMI_EV_BOOT_ERROR_NO_PXE_SERVER	0x0004
#define	IPMI_EV_BOOT_ERROR_INV_BOOT_SECT	0x0008
#define	IPMI_EV_BOOT_ERROR_USR_SELECT_TIMEOUT	0x0010

#define	IPMI_ST_BOOT_OS				0x1F

#define	IPMI_EV_BOOT_OS_A_DRV_BOOT_COMPLETE	0x0001
#define	IPMI_EV_BOOT_OS_C_DRV_BOOT_COMPLETE	0x0002
#define	IPMI_EV_BOOT_OS_PXE_BOOT_COMPLETE	0x0004
#define	IPMI_EV_BOOT_OS_DIAG_BOOT_COMPLETE	0x0008
#define	IPMI_EV_BOOT_OS_CDROM_BOOT_COMPLETE	0x0010
#define	IPMI_EV_BOOT_OS_ROM_BOOT_COMPLETE	0x0020
#define	IPMI_EV_BOOT_OS_UNSPEC_BOOT_COMPLETE	0x0040

#define	IPMI_ST_OS_SHUTDOWN			0x20

#define	IPMI_EV_OS_SHUTDOWN_LOADING		0x0001
#define	IPMI_EV_OS_SHUTDOWN_CRASH		0x0002
#define	IPMI_EV_OS_STOP_GRACEFUL		0x0004
#define	IPMI_EV_OS_SHUTDOWN_GRACEFUL		0x0008
#define	IPMI_EV_OS_SHUTDOWN_PEF			0x0010
#define	IPMI_EV_OS_SHUTDOWN_BMC			0x0020

#define	IPMI_ST_SLOT				0x21

#define	IPMI_EV_SLOT_FAULT_ASSERTED		0x0001
#define	IPMI_EV_SLOT_IDENTIFY_ASSERTED		0x0002
#define	IPMI_EV_SLOT_CONNECTED			0x0004
#define	IPMI_EV_SLOT_INSTALL_READY		0x0008
#define	IPMI_EV_SLOT_REMOVE_READY		0x0010
#define	IPMI_EV_SLOT_PWR_OFF			0x0020
#define	IPMI_EV_SLOT_REMOVED			0x0040
#define	IPMI_EV_SLOT_INTERLOCK_ASSERTED		0x0080
#define	IPMI_EV_SLOT_DISABLED			0x0100
#define	IPMI_EV_SLOT_SPARE_DEVICE		0x0200

#define	IPMI_ST_ACPI				0x22

#define	IPMI_EV_ACPI_PSTATE_S0_G0		0x0001
#define	IPMI_EV_ACPI_PSTATE_S1			0x0002
#define	IPMI_EV_ACPI_PSTATE_S2			0x0004
#define	IPMI_EV_ACPI_PSTATE_S3			0x0008
#define	IPMI_EV_ACPI_PSTATE_S4			0x0010
#define	IPMI_EV_ACPI_PSTATE_S5_G2_SOFT_OFF	0x0020
#define	IPMI_EV_ACPI_PSTATE_S4_S5_SOFT_OFF	0x0040
#define	IPMI_EV_ACPI_PSATTE_G3_MECH_OFF		0x0080
#define	IPMI_EV_ACPI_PSTATE_S1_S2_S3_SLEEP	0x0100
#define	IPMI_EV_ACPI_PSTATE_G1_SLEEP		0x0200
#define	IPMI_EV_ACPI_PSTATE_S5_OVERRIDE		0x0400
#define	IPMI_EV_ACPI_PSTATE_LEGACY_ON		0x0800
#define	IPMI_EV_ACPI_PSTATE_LEGACY_OFF		0x1000
#define	IPMI_EV_ACPI_PSTATE_UNKNOWN		0x2000

#define	IPMI_ST_WATCHDOG2			0x23

#define	IPMI_EV_WATCHDOG2_EXPIRED		0x0001
#define	IPMI_EV_WATCHDOG2_HARD_RESET		0x0002
#define	IPMI_EV_WATCHDOG2_PWR_DOWN		0x0004
#define	IPMI_EV_WATCHDOG2_PWR_CYCLE		0x0008
#define	IPMI_EV_WATCHDOG2_RESERVED1		0x0010
#define	IPMI_EV_WATCHDOG2_RESERVED2		0x0020
#define	IPMI_EV_WATCHDOG2_RESERVED3		0x0040
#define	IPMI_EV_WATCHDOG2_RESERVED4		0x0080
#define	IPMI_EV_WATCHDOG2_TIMEOUT_INT		0x0100

#define	IPMI_ST_ALERT				0x24

#define	IPMI_EV_ALERT_PLAT_PAGE			0x0001
#define	IPMI_EV_ALERT_PLAT_LAN_ALERT		0x0002
#define	IPMI_EV_ALERT_PLAT_EVT_TRAP		0x0004
#define	IPMI_EV_ALERT_PLAT_SNMP_TRAP		0x0008

#define	IPMI_ST_PRESENCE			0x25

#define	IPMI_EV_PRESENCE_PRESENT		0x0001
#define	IPMI_EV_PRESENCE_ABSENT			0x0002
#define	IPMI_EV_PRESENCE_DISABLED		0x0004

#define	IPMI_ST_ASIC				0x26

#define	IPMI_ST_LAN				0x27

#define	IPMI_EV_LAN_HEARTBEAT_LOST		0x0001
#define	IPMI_EV_LAN_HEARTBEAT			0x0002

#define	IPMI_ST_HEALTH				0x28

#define	IPMI_EV_HEALTH_SENSOR_ACC_DEGRADED	0x0001
#define	IPMI_EV_HEALTH_CNTLR_ACC_DEGRADED	0x0002
#define	IPMI_EV_HEALTH_CNTLR_OFFLINE		0x0004
#define	IPMI_EV_HEALTH_CNTLR_UNAVAIL		0x0008
#define	IPMI_EV_HEALTH_SENSOR_FAILURE		0x0010
#define	IPMI_EV_HEALTH_FRU_FAILURE		0x0020

#define	IPMI_ST_BATTERY				0x29

#define	IPMI_EV_BATTERY_LOW			0x0001
#define	IPMI_EV_BATTERY_FAILED			0x0002
#define	IPMI_EV_BATTERY_PRESENCE		0x0004

#define	IPMI_ST_AUDIT				0x2A

#define	IPMI_EV_AUDIT_SESSION_ACTIVATED		0x0001
#define	IPMI_EV_AUDIT_SESSION_DEACTIVATED	0x0002

#define	IPMI_ST_VERSION				0x2B

#define	IPMI_EV_VERSION_HW_CHANGE		0x0001
#define	IPMI_EV_VERSION_SW_CHANGE		0x0002
#define	IPMI_EV_VERSION_HW_INCOMPATIBLE		0x0004
#define	IPMI_EV_VERSION_SW_INCOMPATIBLE		0x0008
#define	IPMI_EV_VERSION_HW_INVAL		0x0010
#define	IPMI_EV_VERSION_SW_INVAL		0x0020
#define	IPMI_EV_VERSION_HW_CHANGE_SUCCESS	0x0040
#define	IPMI_EV_VERSION_SW_CHANGE_SUCCESS	0x0080

#define	IPMI_ST_FRU_STATE			0x2C

#define	IPMI_EV_FRU_STATE_NOT_INSTALLED		0x0001
#define	IPMI_EV_FRU_STATE_INACTIVE		0x0002
#define	IPMI_EV_FRU_STATE_ACT_REQ		0x0004
#define	IPMI_EV_FRU_STATE_ACT_INPROGRESS	0x0008
#define	IPMI_EV_FRU_STATE_ACTIVE		0x0010
#define	IPMI_EV_FRU_STATE_DEACT_REQ		0x0020
#define	IPMI_EV_FRU_STATE_DEACT_INPROGRESS	0x0040
#define	IPMI_EV_FRU_STATE_COMM_LOST		0x0080

/*
 * Constants for unit type codes.  See Table 43-15.
 */
#define	IPMI_UNITS_UNSPECIFIED			0x00
#define	IPMI_UNITS_DEGREES_C			0x01
#define	IPMI_UNITS_DEGREES_F			0x02
#define	IPMI_UNITS_DEGREES_K			0x03
#define	IPMI_UNITS_VOLTS			0x04
#define	IPMI_UNITS_AMPS				0x05
#define	IPMI_UNITS_WATTS			0x06
#define	IPMI_UNITS_JOULES			0x07
#define	IPMI_UNITS_COULOMBS			0x08
#define	IPMI_UNITS_VA				0x09
#define	IPMI_UNITS_NITS				0x0A
#define	IPMI_UNITS_LUMEN			0x0B
#define	IPMI_UNITS_LUX				0x0C
#define	IPMI_UNITS_CANDELA			0x0D
#define	IPMI_UNITS_KPA				0x0E
#define	IPMI_UNITS_PSI				0x0F

#define	IPMI_UNITS_NEWTON			0x10
#define	IPMI_UNITS_CFM				0x11
#define	IPMI_UNITS_RPM				0x12
#define	IPMI_UNITS_HZ				0x13
#define	IPMI_UNITS_MICROSEC			0x14
#define	IPMI_UNITS_MILLISEC			0x15
#define	IPMI_UNITS_SECS				0x16
#define	IPMI_UNITS_MIN				0x17
#define	IPMI_UNITS_HOUR				0x18
#define	IPMI_UNITS_DAY				0x19
#define	IPMI_UNITS_WEEK				0x1A
#define	IPMI_UNITS_MIL				0x1B
#define	IPMI_UNITS_INCHES			0x1C
#define	IPMI_UNITS_FEET				0x1D
#define	IPMI_UNITS_CUB_INCH			0x1E
#define	IPMI_UNITS_CUB_FEET			0x1F

#define	IPMI_UNITS_MM				0x20
#define	IPMI_UNITS_CM				0x21
#define	IPMI_UNITS_METERS			0x22
#define	IPMI_UNITS_CUB_CM			0x23
#define	IPMI_UNITS_CUB_METER			0x24
#define	IPMI_UNITS_LITERS			0x25
#define	IPMI_UNITS_FLUID_OUNCE			0x26
#define	IPMI_UNITS_RADIANS			0x27
#define	IPMI_UNITS_STERADIANS			0x28
#define	IPMI_UNITS_REVOLUTIONS			0x29
#define	IPMI_UNITS_CYCLES			0x2A
#define	IPMI_UNITS_GRAVITIES			0x2B
#define	IPMI_UNITS_OUNCE			0x2C
#define	IPMI_UNITS_POUND			0x2D
#define	IPMI_UNITS_FOOT_POUND			0x2E
#define	IPMI_UNITS_OZ_INCH			0x2F

#define	IPMI_UNITS_GAUSS			0x30
#define	IPMI_UNITS_GILBERTS			0x31
#define	IPMI_UNITS_HENRY			0x32
#define	IPMI_UNITS_MILHENRY			0x33
#define	IPMI_UNITS_FARAD			0x34
#define	IPMI_UNITS_MICROFARAD			0x35
#define	IPMI_UNITS_OHMS				0x36
#define	IPMI_UNITS_SIEMENS			0x37
#define	IPMI_UNITS_MOLE				0x38
#define	IPMI_UNITS_BECQUEREL			0x39
#define	IPMI_UNITS_PPM				0x3A
/* 0x3B is reserved */
#define	IPMI_UNITS_DECIBELS			0x3C
#define	IPMI_UNITS_DBA				0x3D
#define	IPMI_UNITS_DBC				0x3E
#define	IPMI_UNITS_GRAY				0x3F

#define	IPMI_UNITS_SIEVERT			0x40
#define	IPMI_UNITS_COLOR_TEMP_K			0x41
#define	IPMI_UNITS_BIT				0x42
#define	IPMI_UNITS_KILOBIT			0x43
#define	IPMI_UNITS_MEGABIT			0x44
#define	IPMI_UNITS_GIGABIT			0x45
#define	IPMI_UNITS_BYTE				0x46
#define	IPMI_UNITS_KILOBYTE			0x47
#define	IPMI_UNITS_MEGABYTE			0x48
#define	IPMI_UNITS_GIGABYTE			0x49
#define	IPMI_UNITS_WORD				0x4A
#define	IPMI_UNITS_DWORD			0x4B
#define	IPMI_UNITS_QWORD			0x4C
#define	IPMI_UNITS_MEMLINE			0x4D
#define	IPMI_UNITS_HIT				0x4E
#define	IPMI_UNITS_MISS				0x4F

#define	IPMI_UNITS_RETRY			0x50
#define	IPMI_UNITS_RESET			0x51
#define	IPMI_UNITS_OVERFLOW			0x52
#define	IPMI_UNITS_UNDERRUN			0x53
#define	IPMI_UNITS_COLLISION			0x54
#define	IPMI_UNITS_PACKETS			0x55
#define	IPMI_UNITS_MESSAGES			0x56
#define	IPMI_UNITS_CHARACTERS			0x57
#define	IPMI_UNITS_ERROR			0x58
#define	IPMI_UNITS_CE				0x59
#define	IPMI_UNITS_UE				0x5A
#define	IPMI_UNITS_FATAL_ERROR			0x5B
#define	IPMI_UNITS_GRAMS			0x5C

/*
 * Event-Only Record.  See section 43.3.
 */

#define	IPMI_SDR_TYPE_EVENT_ONLY		0x03

typedef struct ipmi_sdr_event_only {
	/* RECORD KEY BYTES */
	uint8_t		is_eo_owner;
	DECL_BITFIELD3(
	    is_eo_sensor_lun			:2,
	    is_eo_fru_lun			:2,
	    is_eo_channel			:4);
	uint8_t		is_eo_number;
	/* RECORD BODY BYTES */
	uint8_t		is_eo_entity_id;
	DECL_BITFIELD2(
	    is_eo_entity_instance		:7,
	    is_eo_entity_logical		:1);
	uint8_t		is_eo_sensor_type;
	uint8_t		is_eo_reading_type;
	DECL_BITFIELD3(
	    is_eo_share_count			:4,
	    is_eo_modifier_type			:2,
	    is_eo_direction			:2);
	DECL_BITFIELD2(
	    is_eo_modifier_offset		:7,
	    is_eo_sharing			:1);
	uint8_t		__reserved;
	uint8_t		is_eo_oem;
	DECL_BITFIELD3(
	    is_eo_idlen				:5,
	    __reserved1				:1,
	    is_eo_idtype			:2);
	char		is_eo_idstring[1];
} ipmi_sdr_event_only_t;

/*
 * Entity Association Record.  See section 43.4.
 */

#define	IPMI_SDR_TYPE_ENTITY_ASSOCIATION	0x08

typedef struct ipmi_sdr_entity_association {
	/* RECORD KEY BYTES */
	uint8_t		is_ea_entity_id;
	uint8_t		is_ea_entity_instance;
	DECL_BITFIELD4(
	    __reserved		:5,
	    is_ea_presence	:1,
	    is_ea_record_link	:1,
	    is_ea_range		:1);
	/* RECORD BODY BYTES */
	struct {
		uint8_t		is_ea_sub_id;
		uint8_t		is_ea_sub_instance;
	} is_ea_sub[4];
} ipmi_sdr_entity_association_t;

/*
 * Device-relative Entity Association Record.  See section 43.5.
 */

#define	IPMI_SDR_TYPE_DEVICE_RELATIVE		0x09

typedef struct ipmi_sdr_device_relative {
	/* RECORD KEY BYTES */
	uint8_t		is_dr_entity_id;
	uint8_t		is_dr_entity_instance;
	DECL_BITFIELD2(
	    __reserved1			:1,
	    is_dr_slaveaddr		:7);
	DECL_BITFIELD2(
	    __reserved2			:4,
	    is_dr_channel		:4);
	DECL_BITFIELD4(
	    __reserved			:5,
	    is_dr_presence		:1,
	    is_dr_record_link		:1,
	    is_dr_range			:1);
	/* RECORD BODY BYTES */
	struct {
		DECL_BITFIELD2(
		    __reserved3		:1,
		    is_dr_sub_slaveaddr	:7);
		DECL_BITFIELD2(
		    __reserved4		:4,
		    is_dr_sub_channel	:4);
		uint8_t		is_ea_sub_id;
		uint8_t		is_ea_sub_instance;
	} is_ea_sub[4];
} ipmi_sdr_device_relative_t;

/*
 * Generic Device Locator Record.  See section 43.7.
 */

#define	IPMI_SDR_TYPE_GENERIC_LOCATOR		0x10

typedef struct ipmi_sdr_generic_locator {
	/* RECORD KEY BYTES */
	DECL_BITFIELD2(
	    __reserved1		:1,
	    is_gl_accessaddr	:7);
	DECL_BITFIELD2(
	    is_gl_channel_msb	:1,
	    is_gl_slaveaddr	:7);
	DECL_BITFIELD3(
	    is_gl_bus		:3,
	    is_gl_lun		:2,
	    is_gl_channel	:3);
	/* RECORD BODY BYTES */
	DECL_BITFIELD2(
	    is_gl_span		:3,
	    __reserved2		:5);
	uint8_t		__reserved3;
	uint8_t		is_gl_type;
	uint8_t		is_gl_modifier;
	uint8_t		is_gl_entity;
	uint8_t		is_gl_instance;
	uint8_t		is_gl_oem;
	DECL_BITFIELD3(
	    is_gl_idlen		:5,
	    __reserved4		:1,
	    is_gl_idtype	:2);
	char		is_gl_idstring[1];
} ipmi_sdr_generic_locator_t;

/*
 * FRU Device Locator Record.  See section 43.8.
 */

#define	IPMI_SDR_TYPE_FRU_LOCATOR		0x11

typedef struct ipmi_sdr_fru_locator {
	/* RECORD KEY BYTES */
	DECL_BITFIELD2(
	    __reserved1		:1,
	    is_fl_accessaddr	:7);
	union {
		struct {
			uint8_t	_is_fl_devid;
		} _logical;
		struct {
			DECL_BITFIELD2(
			    __reserved		:1,
			    _is_fl_slaveaddr	:7);
		} _nonintelligent;
	} _devid_or_slaveaddr;
	DECL_BITFIELD4(
	    is_fl_bus		:3,
	    is_fl_lun		:2,
	    __reserved2		:2,
	    is_fl_logical	:1);
	DECL_BITFIELD2(
	    __reserved3		:4,
	    is_fl_channel	:4);
	/* RECORD BODY BYTES */
	uint8_t		__reserved4;
	uint8_t		is_fl_type;
	uint8_t		is_fl_modifier;
	uint8_t		is_fl_entity;
	uint8_t		is_fl_instance;
	uint8_t		is_fl_oem;
	DECL_BITFIELD3(
	    is_fl_idlen		:5,
	    __reserved5		:1,
	    is_fl_idtype	:2);
	char		is_fl_idstring[1];
} ipmi_sdr_fru_locator_t;

#define	is_fl_devid	_devid_or_slaveaddr._logical._is_fl_devid
#define	is_fl_slaveaddr	_devid_or_slaveaddr._nonintelligent._is_fl_slaveaddr

/*
 * Management Controller Device Locator Record.  See section 43.9
 */

#define	IPMI_SDR_TYPE_MANAGEMENT_LOCATOR	0x12

typedef struct ipmi_sdr_management_locator {
	/* RECORD KEY BYTES */
	DECL_BITFIELD2(
	    __reserved1			:1,
	    is_ml_devaddr		:7);
	DECL_BITFIELD2(
	    is_ml_channel		:4,
	    __reserved2			:4);
	/* RECORD BODY BYTES */
	DECL_BITFIELD7(
	    is_ml_init_message		:2,
	    is_ml_init_log		:1,
	    is_ml_init_controller_log	:1,
	    __reserved3			:1,
	    is_ml_static		:1,
	    is_ml_acpi_device		:1,
	    is_ml_acpi_system		:1);
	DECL_BITFIELD8(
	    is_ml_supp_sensor		:1,
	    is_ml_supp_sdr		:1,
	    is_ml_supp_sel		:1,
	    is_ml_supp_fru		:1,
	    is_ml_supp_event_receiver	:1,
	    is_ml_supp_event_generator	:1,
	    is_ml_supp_bridge		:1,
	    is_ml_supp_chassis		:1);
	uint8_t		__reserved4;
	uint16_t	__reserved5;
	uint8_t		is_ml_entity_id;
	uint8_t		is_ml_entity_instance;
	uint8_t		is_ml_oem;
	DECL_BITFIELD3(
	    is_ml_idlen		:5,
	    __reserved6		:1,
	    is_ml_idtype	:2);
	char		is_ml_idstring[1];
} ipmi_sdr_management_locator_t;

#define	IPMI_MESSAGE_INIT_ENABLE		0x0
#define	IPMI_MESSAGE_INIT_DISABLE		0x1
#define	IPMI_MESSAGE_INIT_NONE			0x2

/*
 *  Management Controller Confirmation Record.  See section 43.10
 */

#define	IPMI_SDR_TYPE_MANAGEMENT_CONFIRMATION	0x13

typedef struct ipmi_sdr_management_confirmation {
	/* RECORD KEY BYTES */
	DECL_BITFIELD2(
	    __reserved1		:1,
	    is_mc_slaveaddr	:7);
	uint8_t		is_mc_deviceid;
	DECL_BITFIELD2(
	    is_mc_dev_revision	:4,
	    is_mc_channel	:4);
	/* RECORD BODY BYTES */
	DECL_BITFIELD2(
	    is_mc_major_rev	:7,
	    __reserved2		:1);
	uint8_t		is_mc_minor_rev;
	uint8_t		is_mc_impi_ver;
	uint8_t		is_mc_manufacturer[3];
	uint16_t	is_mc_product;
	uint8_t		is_mc_guid[16];
} ipmi_sdr_management_confirmation_t;

/*
 * BMC Message Channel Info Record.  See esction 43.11.
 */

#define	IPMI_SDR_TYPE_BMC_MESSAGE_CHANNEL	0x14

typedef struct ipmi_sdr_bmc_channel {
	/* RECORD BODY BYTES */
	struct {
		DECL_BITFIELD3(
		    is_bc_protocol	:4,
		    is_bc_receive_lun	:3,
		    is_bc_transmit	:1);
	} is_bc_channel[8];
	uint8_t		is_bc_interrupt_type;
	uint8_t		is_bc_buffer_type;
	uint8_t		__reserved;
} ipmi_sdr_bmc_channel_t;

/*
 * OEM Record.  See ction 43.12.
 */

#define	IPMI_SDR_TYPE_OEM			0xC0

typedef struct ipmi_sdr_oem {
	uint8_t		is_oem_manufacturer[3];
	uint8_t		is_oem_data[1];
} ipmi_sdr_oem_t;

/*
 * Iterate over the SDR repository.  This function does the work of parsing the
 * name when available, and keeping the repository in a consistent state.
 */
extern int ipmi_sdr_iter(ipmi_handle_t *,
    int (*)(ipmi_handle_t *, const char *, ipmi_sdr_t *, void *), void *);

/*
 * Lookup the given sensor type by name.  These functions automatically read in
 * and cache the complete SDR repository.
 */
extern ipmi_sdr_t *ipmi_sdr_lookup(ipmi_handle_t *, const char *);
extern ipmi_sdr_fru_locator_t *ipmi_sdr_lookup_fru(ipmi_handle_t *,
    const char *);
extern ipmi_sdr_generic_locator_t *ipmi_sdr_lookup_generic(ipmi_handle_t *,
    const char *);
extern ipmi_sdr_compact_sensor_t *ipmi_sdr_lookup_compact_sensor(
    ipmi_handle_t *, const char *);
extern ipmi_sdr_full_sensor_t *ipmi_sdr_lookup_full_sensor(
    ipmi_handle_t *, const char *);

/*
 * Entity ID codes.  See table 43.13.
 */
#define	IPMI_ET_UNSPECIFIED		0x00
#define	IPMI_ET_OTHER			0x01
#define	IPMI_ET_UNKNOWN			0x02
#define	IPMI_ET_PROCESSOR		0x03
#define	IPMI_ET_DISK			0x04
#define	IPMI_ET_PERIPHERAL		0x05
#define	IPMI_ET_MANAGEMENT_MODULE	0x06
#define	IPMI_ET_MOTHERBOARD		0x07
#define	IPMI_ET_MEMORY_MODULE		0x08
#define	IPMI_ET_PROCESSOR_MODULE	0x09
#define	IPMI_ET_PSU			0x0A
#define	IPMI_ET_CARD			0x0B
#define	IPMI_ET_FRONT_PANEL		0x0C
#define	IPMI_ET_BACK_PANEL		0x0D
#define	IPMI_ET_POWER_BOARD		0x0E
#define	IPMI_ET_BACKPLANE		0x0F
#define	IPMI_ET_EXPANSION_BOARD		0x10
#define	IPMI_ET_OTHER_BOARD		0x11
#define	IPMI_ET_PROCESSOR_BOARD		0x12
#define	IPMI_ET_POWER_DOMAIN		0x13
#define	IPMI_ET_POWER_CONVERTER		0x14
#define	IPMI_ET_POWER_MANAGEMENT	0x15
#define	IPMI_ET_BACK_CHASSIS		0x16
#define	IPMI_ET_SYSTEM_CHASSIS		0x17
#define	IPMI_ET_SUB_CHASSIS		0x18
#define	IPMI_ET_OTHER_CHASSIS		0x19
#define	IPMI_ET_DISK_BAY		0x1A
#define	IPMI_ET_PERIPHERAL_BAY		0x1B
#define	IPMI_ET_DEVICE_BAY		0x1C
#define	IPMI_ET_FAN			0x1D
#define	IPMI_ET_COOLING_DOMAIN		0x1E
#define	IPMI_ET_CABLE			0x1F
#define	IPMI_ET_MEMORY_DEVICE		0x20
#define	IPMI_ET_MANAGEMENT_SOFTWARE	0x21
#define	IPMI_ET_SYSTEM_FIRMWARE		0x22
#define	IPMI_ET_OS			0x23
#define	IPMI_ET_SYSTEM_BUS		0x24
#define	IPMI_ET_GROUP			0x25
#define	IPMI_ET_REMOTE			0x26
#define	IPMI_ET_ENVIRONMENT		0x27
#define	IPMI_ET_BATTERY			0x28
#define	IPMI_ET_BLADE			0x29
#define	IPMI_ET_SWITCH			0x2A
#define	IPMI_ET_PROCMEM_MODULE		0x2B
#define	IPMI_ET_IO_MODULE		0x2C
#define	IPMI_ET_PROCIO_MODULE		0x2D
#define	IPMI_ET_CONTROLLER_FIRMWARE	0x2E
#define	IPMI_ET_CHANNEL			0x2F
#define	IPMI_ET_PCI			0x30
#define	IPMI_ET_PCIE			0x31
#define	IPMI_ET_SCSI			0x32
#define	IPMI_ET_SATA_SAS		0x33
#define	IPMI_ET_FSB			0x34
#define	IPMI_ET_RTC			0x35

/*
 * Get Sensor Reading.  See section 35.14.
 */

#define	IPMI_CMD_GET_SENSOR_READING	0x2d

typedef struct ipmi_sensor_reading {
	uint8_t		isr_reading;
	DECL_BITFIELD4(
	    __reserved1			:5,
	    isr_state_unavailable	:1,
	    isr_scanning_enabled	:1,
	    isr_event_enabled		:1);
	uint16_t	isr_state;
} ipmi_sensor_reading_t;

#define	IPMI_SENSOR_THRESHOLD_LOWER_NONCRIT		0x0001
#define	IPMI_SENSOR_THRESHOLD_LOWER_CRIT		0x0002
#define	IPMI_SENSOR_THRESHOLD_LOWER_NONRECOV		0x0004
#define	IPMI_SENSOR_THRESHOLD_UPPER_NONCRIT		0x0008
#define	IPMI_SENSOR_THRESHOLD_UPPER_CRIT		0x0010
#define	IPMI_SENSOR_THRESHOLD_UPPER_NONRECOV		0x0020

extern ipmi_sensor_reading_t *ipmi_get_sensor_reading(ipmi_handle_t *, uint8_t);
extern int ipmi_sdr_conv_reading(ipmi_sdr_full_sensor_t *, uint8_t,
    double *);
/*
 * Set Sensor Reading.  See section 35.14.
 */
#define	IPMI_CMD_SET_SENSOR_READING	0x30

#define	IPMI_SENSOR_OP_CLEAR	0x3	/* clear '0' bits */
#define	IPMI_SENSOR_OP_SET	0x2	/* set '1' bits */
#define	IPMI_SENSOR_OP_EXACT	0x1	/* set bits exactly */

typedef struct ipmi_set_sensor_reading {
	uint8_t		iss_id;
	DECL_BITFIELD5(
	    iss_set_reading		:1,
	    __reserved			:1,
	    iss_deassrt_op		:2,
	    iss_assert_op		:2,
	    iss_data_bytes		:2);
	uint8_t		iss_sensor_reading;
	uint16_t	iss_assert_state;	/* optional */
	uint16_t	iss_deassert_state;	/* optional */
	uint8_t		iss_event_data1;	/* optional */
	uint8_t		iss_event_data2;	/* optional */
	uint8_t		iss_event_data3;	/* optional */
} ipmi_set_sensor_reading_t;

extern int ipmi_set_sensor_reading(ipmi_handle_t *,
    ipmi_set_sensor_reading_t *);

/*
 * These IPMI message id/opcodes are documented in Appendix G in the IPMI spec.
 *
 * Payloads for these two commands are described in Sections 34.1 and 34.2 of
 * the spec, respectively.
 */
#define	IPMI_CMD_GET_FRU_INV_AREA	0x10
#define	IPMI_CMD_READ_FRU_DATA		0x11

/*
 * Structs to hold the FRU Common Header and the FRU Product Info Area, as
 * described in the IPMI Platform Management FRU Information Storage
 * Definition (v1.1).
 */
typedef struct ipmi_fru_hdr
{
	uint8_t		ifh_format;
	uint8_t		ifh_int_use_off;
	uint8_t		ifh_chassis_info_off;
	uint8_t		ifh_board_info_off;
	uint8_t		ifh_product_info_off;
	uint8_t		ifh_multi_rec_off;
	uint8_t		ifh_pad;
	uint8_t		ifh_chksum;
} ipmi_fru_hdr_t;

/*
 * Because only 6 bits are used to specify the length of each field in the FRU
 * product and board info areas, the biggest string we would ever need to hold
 * would be 63 chars plus a NULL.
 */
#define	FRU_INFO_MAXLEN	64

typedef struct ipmi_fru_brd_info
{
	char	ifbi_manuf_date[3];
	char	ifbi_manuf_name[FRU_INFO_MAXLEN];
	char	ifbi_board_name[FRU_INFO_MAXLEN];
	char	ifbi_product_serial[FRU_INFO_MAXLEN];
	char	ifbi_part_number[FRU_INFO_MAXLEN];
} ipmi_fru_brd_info_t;

typedef struct ipmi_fru_prod_info
{
	char	ifpi_manuf_name[FRU_INFO_MAXLEN];
	char	ifpi_product_name[FRU_INFO_MAXLEN];
	char	ifpi_part_number[FRU_INFO_MAXLEN];
	char	ifpi_product_version[FRU_INFO_MAXLEN];
	char	ifpi_product_serial[FRU_INFO_MAXLEN];
	char	ifpi_asset_tag[FRU_INFO_MAXLEN];
} ipmi_fru_prod_info_t;

extern int ipmi_fru_read(ipmi_handle_t *, ipmi_sdr_fru_locator_t *, char **);
extern int ipmi_fru_parse_board(ipmi_handle_t *, char *, ipmi_fru_brd_info_t *);
extern int ipmi_fru_parse_product(ipmi_handle_t *, char *,
    ipmi_fru_prod_info_t *);

/*
 * Routines to convert from entity and sensors defines into text strings.
 */
void ipmi_entity_name(uint8_t, char *, size_t);
void ipmi_sensor_type_name(uint8_t, char *, size_t);
void ipmi_sensor_units_name(uint8_t, char *, size_t);
void ipmi_sensor_reading_name(uint8_t, uint8_t, char *, size_t);

/*
 * Entity management.  IPMI has a notion of 'entities', but these are not
 * directly accessible from any commands.  Instead, their existence is inferred
 * from examining the SDR repository.  Since this is rather unwieldy, and
 * iterating over entities is a common operation, libipmi provides an entity
 * abstraction that hides the implementation details.  This handles entity
 * groupings as well as SDR associations.
 */
typedef struct ipmi_entity {
	uint8_t		ie_type;
	uint8_t		ie_instance;
	uint8_t		ie_children;
	boolean_t	ie_logical;
} ipmi_entity_t;

extern int ipmi_entity_iter(ipmi_handle_t *, int (*)(ipmi_handle_t *,
    ipmi_entity_t *, void *), void *);
extern int ipmi_entity_iter_sdr(ipmi_handle_t *, ipmi_entity_t *,
    int (*)(ipmi_handle_t *, ipmi_entity_t *, const char *, ipmi_sdr_t *,
    void *), void *);
extern int ipmi_entity_iter_children(ipmi_handle_t *, ipmi_entity_t *,
    int (*)(ipmi_handle_t *, ipmi_entity_t *, void *), void *);
extern ipmi_entity_t *ipmi_entity_lookup(ipmi_handle_t *, uint8_t,
    uint8_t);
extern ipmi_entity_t *ipmi_entity_lookup_sdr(ipmi_handle_t *, const char *);
extern ipmi_entity_t *ipmi_entity_parent(ipmi_handle_t *, ipmi_entity_t *);
extern int ipmi_entity_present(ipmi_handle_t *, ipmi_entity_t *, boolean_t *);
extern int ipmi_entity_present_sdr(ipmi_handle_t *, ipmi_sdr_t *, boolean_t *);

/*
 * User management.  The raw functions are private to libipmi, and only the
 * higher level abstraction (ipmi_user_t) is exported to consumers of the
 * library.
 */

#define	IPMI_USER_PRIV_CALLBACK		0x1
#define	IPMI_USER_PRIV_USER		0x2
#define	IPMI_USER_PRIV_OPERATOR		0x3
#define	IPMI_USER_PRIV_ADMIN		0x4
#define	IPMI_USER_PRIV_OEM		0x5
#define	IPMI_USER_PRIV_NONE		0xf

typedef struct ipmi_user {
	uint8_t		iu_uid;
	char		*iu_name;
	boolean_t	iu_enabled;
	boolean_t	iu_ipmi_msg_enable;
	boolean_t	iu_link_auth_enable;
	uint8_t		iu_priv;
} ipmi_user_t;

extern int ipmi_user_iter(ipmi_handle_t *,
    int (*)(ipmi_user_t *, void *), void *);
extern ipmi_user_t *ipmi_user_lookup_name(ipmi_handle_t *, const char *);
extern ipmi_user_t *ipmi_user_lookup_id(ipmi_handle_t *, uint8_t);
extern int ipmi_user_set_password(ipmi_handle_t *, uint8_t, const char *);

/*
 * The remaining functions are private to the implementation of the Sun ILOM
 * service processor.  These function first check the manufacturer from the IPMI
 * device ID, and will return EIPMI_NOT_SUPPORTED if attempted for non-Sun
 * devices.
 */

/*
 * Sun OEM LED requests.
 */

#define	IPMI_SUNOEM_LED_MODE_OFF	0
#define	IPMI_SUNOEM_LED_MODE_ON		1
#define	IPMI_SUNOEM_LED_MODE_STANDBY	2
#define	IPMI_SUNOEM_LED_MODE_SLOW	3
#define	IPMI_SUNOEM_LED_MODE_FAST	4

/*
 * These functions take a SDR record and construct the appropriate form of the
 * above commands.
 */
extern int ipmi_sunoem_led_set(ipmi_handle_t *,
    ipmi_sdr_generic_locator_t *, uint8_t);
extern int ipmi_sunoem_led_get(ipmi_handle_t *,
    ipmi_sdr_generic_locator_t *, uint8_t *);

/*
 * Sun OEM uptime.  Note that the underlying command returns the uptime in big
 * endian form.  This wrapper automatically converts to the appropriate native
 * form.
 */

#define	IPMI_CMD_SUNOEM_UPTIME		0x08

extern int ipmi_sunoem_uptime(ipmi_handle_t *, uint32_t *, uint32_t *);

/*
 * Sun OEM FRU update.  The FRU information is managed through a generic
 * identifier, and then a type-specific data portion.  The wrapper function will
 * automatically fill in the data length field according to which type is
 * specified.
 */

#define	IPMI_CMD_SUNOEM_FRU_UPDATE	0x16

#define	IPMI_SUNOEM_FRU_DIMM	0x00
#define	IPMI_SUNOEM_FRU_CPU	0x01
#define	IPMI_SUNOEM_FRU_BIOS	0x02
#define	IPMI_SUNOEM_FRU_DISK	0x03

typedef struct ipmi_sunoem_fru {
	uint8_t				isf_type;
	uint8_t				isf_id;
	uint8_t				isf_datalen;
	union {
		struct {
			uint8_t		isf_data[128];
		} dimm;
		struct {
			uint32_t	isf_thermtrip;
			uint32_t	isf_eax;
			char		isf_product[48];
		} cpu;
		struct {
			char		isf_part[16];
			char		isf_version[16];
		} bios;
		struct {
			char		isf_manufacturer[16];
			char		isf_model[28];
			char		isf_serial[20];
			char		isf_version[8];
			char		isf_capacity[16];
		} disk;
	} isf_data;
} ipmi_sunoem_fru_t;

int ipmi_sunoem_update_fru(ipmi_handle_t *, ipmi_sunoem_fru_t *);

#pragma pack()

#ifdef	__cplusplus
}
#endif

#endif	/* _LIBIPMI_H */