/*
* oem_atca_fru.c
*
* FRU Multirecord decoding for ATCA multirecords.
*
* (C) 2005 MontaVista Software, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <string.h>
#include <stdio.h> /* for sprintf */
#include <OpenIPMI/internal/ipmi_fru.h>
#include <OpenIPMI/internal/ipmi_int.h>
/***********************************************************************
*
* Point-to-point connectivity record
*
**********************************************************************/
static ipmi_mr_item_layout_t p2p_cr_desc_ent_items[] = {
{ .name = "remote slot", .dtype = IPMI_FRU_DATA_INT, .settable = 1,
.start = 0, .length = 8,
.set_field = ipmi_mr_bitint_set_field, .get_field = ipmi_mr_bitint_get_field },
{ .name = "remote channel", .dtype = IPMI_FRU_DATA_INT, .settable = 1,
.start = 8, .length = 5,
.set_field = ipmi_mr_bitint_set_field, .get_field = ipmi_mr_bitint_get_field },
{ .name = "local channel ", .dtype = IPMI_FRU_DATA_INT, .settable = 1,
.start = 13, .length = 5,
.set_field = ipmi_mr_bitint_set_field, .get_field = ipmi_mr_bitint_get_field }
};
static ipmi_mr_struct_layout_t p2p_cr_desc_ent = {
.name = NULL, .length = 3,
.item_count = 3, .items = p2p_cr_desc_ent_items,
.array_count = 0, .arrays = NULL,
.cleanup = ipmi_mr_struct_cleanup
};
static ipmi_mr_item_layout_t p2p_cr_desc_items[] = {
{ .name = "channel type", .dtype = IPMI_FRU_DATA_INT, .settable = 1,
.start = 0, .length = 1,
.set_field = ipmi_mr_int_set_field, .get_field = ipmi_mr_int_get_field },
{ .name = "slot address", .dtype = IPMI_FRU_DATA_INT, .settable = 1,
.start = 1, .length = 1,
.set_field = ipmi_mr_int_set_field, .get_field = ipmi_mr_int_get_field }
};
static ipmi_mr_array_layout_t p2p_cr_desc_arys[] = {
{ .name = "channels", .has_count = 1, .min_elem_size = 3, .settable = 1,
.elem_layout = &p2p_cr_desc_ent,
.elem_check = ipmi_mr_struct_elem_check,
.elem_decode = ipmi_mr_struct_decode,
.cleanup = ipmi_mr_struct_array_cleanup,
.get_field = ipmi_mr_struct_array_get_field,
.set_field = ipmi_mr_struct_array_set_field }
};
static ipmi_mr_struct_layout_t p2p_cr_desc = {
.name = NULL, .length = 2,
.item_count = 2, .items = p2p_cr_desc_items,
.array_count = 1, .arrays = p2p_cr_desc_arys,
.cleanup = ipmi_mr_struct_cleanup
};
static ipmi_mr_item_layout_t p2p_cr_items[] = {
{ .name = "version", .dtype = IPMI_FRU_DATA_INT, .settable = 0,
.start = 0, .length = 1,
.set_field = NULL, .get_field = ipmi_mr_int_get_field }
};
static ipmi_mr_array_layout_t p2p_cr_arys[] = {
{ .name = "descriptors", .has_count = 0, .min_elem_size = 3, .settable = 1,
.elem_layout = &p2p_cr_desc,
.elem_check = ipmi_mr_struct_elem_check, .elem_decode = ipmi_mr_struct_decode,
.cleanup = ipmi_mr_struct_array_cleanup,
.get_field = ipmi_mr_struct_array_get_field,
.set_field = ipmi_mr_struct_array_set_field }
};
static ipmi_mr_struct_layout_t p2p_cr = {
.name = "Point-to-Point Connectivity Record", .length = 1,
.item_count = 1, .items = p2p_cr_items,
.array_count = 1, .arrays = p2p_cr_arys,
.cleanup = ipmi_mr_struct_cleanup
};
/***********************************************************************
*
* Address table descriptor record
*
**********************************************************************/
static ipmi_mr_item_layout_t addr_tab_ent[] = {
{ .name = "hardware address", .dtype = IPMI_FRU_DATA_INT, .settable = 1,
.start = 0, .length = 1,
.set_field = ipmi_mr_int_set_field, .get_field = ipmi_mr_int_get_field },
{ .name = "site_number", .dtype = IPMI_FRU_DATA_INT, .settable = 1,
.start = 1, .length = 1,
.set_field = ipmi_mr_int_set_field, .get_field = ipmi_mr_int_get_field },
{ .name = "site_type", .dtype = IPMI_FRU_DATA_INT, .settable = 1,
.start = 2, .length = 1,
.set_field = ipmi_mr_int_set_field, .get_field = ipmi_mr_int_get_field }
};
static ipmi_mr_struct_layout_t addr_tab_ents = {
.name = NULL, .length = 3,
.item_count = 3, .items = addr_tab_ent,
.array_count = 0, .arrays = NULL,
.cleanup = ipmi_mr_struct_cleanup
};
static ipmi_mr_item_layout_t addr_tab_items[] = {
{ .name = "version", .dtype = IPMI_FRU_DATA_INT, .settable = 0,
.start = 0, .length = 1,
.set_field = NULL, .get_field = ipmi_mr_int_get_field },
{ .name = "shelf address", .dtype = IPMI_FRU_DATA_ASCII, .settable = 1,
.start = 1, .length = 21,
.set_field = ipmi_mr_str_set_field, .get_field = ipmi_mr_str_get_field },
};
static ipmi_mr_array_layout_t addr_tab_arys[] = {
{ .name = "addresses", .has_count = 1, .min_elem_size = 3, .settable = 1,
.elem_layout = &addr_tab_ents,
.elem_check = ipmi_mr_struct_elem_check, .elem_decode = ipmi_mr_struct_decode,
.cleanup = ipmi_mr_struct_array_cleanup,
.get_field = ipmi_mr_struct_array_get_field,
.set_field = ipmi_mr_struct_array_set_field }
};
static ipmi_mr_struct_layout_t addr_tab = {
.name = "Address Table", .length = 22,
.item_count = 2, .items = addr_tab_items,
.array_count = 1, .arrays = addr_tab_arys,
.cleanup = ipmi_mr_struct_cleanup
};
/***********************************************************************
*
* Shelf power distribution record
*
**********************************************************************/
static ipmi_mr_item_layout_t pow_dist_f2f_items[] = {
{ .name = "hardware address", .dtype = IPMI_FRU_DATA_INT, .settable = 1,
.start = 0, .length = 1,
.set_field = ipmi_mr_int_set_field, .get_field = ipmi_mr_int_get_field },
{ .name = "FRU device id", .dtype = IPMI_FRU_DATA_INT, .settable = 1,
.start = 1, .length = 1,
.set_field = ipmi_mr_int_set_field, .get_field = ipmi_mr_int_get_field }
};
static ipmi_mr_struct_layout_t pow_dist_f2f = {
.name = NULL, .length = 2,
.item_count = 2, .items = pow_dist_f2f_items,
.array_count = 0, .arrays = NULL,
.cleanup = ipmi_mr_struct_cleanup
};
static ipmi_mr_item_layout_t pow_dist_maps_items[] = {
{ .name = "max extern avail current", .dtype = IPMI_FRU_DATA_FLOAT,
.settable = 1,
.start = 0, .length = 2,
.u = { .multiplier = 0.1 },
.set_field = ipmi_mr_intfloat_set_field,
.get_field = ipmi_mr_intfloat_get_field },
{ .name = "max internal current", .dtype = IPMI_FRU_DATA_FLOAT,
.settable = 1,
.start = 2, .length = 2,
.u = { .multiplier = 0.1 },
.set_field = ipmi_mr_intfloat_set_field,
.get_field = ipmi_mr_intfloat_get_field },
{ .name = "min operating voltage", .dtype = IPMI_FRU_DATA_FLOAT,
.settable = 1,
.start = 2, .length = 2,
.u = { .multiplier = 0.5 },
.set_field = ipmi_mr_intfloat_set_field,
.get_field = ipmi_mr_intfloat_get_field }
};
static ipmi_mr_array_layout_t pow_dist_maps_arys[] = {
{ .name = "feed to frus", .has_count = 1, .min_elem_size = 6,
.settable = 1,
.elem_layout = &pow_dist_f2f,
.elem_check = ipmi_mr_struct_elem_check,
.elem_decode = ipmi_mr_struct_decode,
.cleanup = ipmi_mr_struct_array_cleanup,
.get_field = ipmi_mr_struct_array_get_field,
.set_field = ipmi_mr_struct_array_set_field }
};
static ipmi_mr_struct_layout_t pow_dist_maps = {
.name = NULL, .length = 5,
.item_count = 3, .items = pow_dist_maps_items,
.array_count = 1, .arrays = pow_dist_maps_arys,
.cleanup = ipmi_mr_struct_cleanup
};
static ipmi_mr_item_layout_t pow_dist_items[] = {
{ .name = "version", .dtype = IPMI_FRU_DATA_INT, .settable = 0,
.start = 0, .length = 1,
.set_field = NULL, .get_field = ipmi_mr_int_get_field }
};
static ipmi_mr_array_layout_t pow_dist_arys[] = {
{ .name = "power feeds", .has_count = 1, .min_elem_size = 3, .settable = 1,
.elem_layout = &pow_dist_maps,
.elem_check = ipmi_mr_struct_elem_check,
.elem_decode = ipmi_mr_struct_decode,
.cleanup = ipmi_mr_struct_array_cleanup,
.get_field = ipmi_mr_struct_array_get_field,
.set_field = ipmi_mr_struct_array_set_field }
};
static ipmi_mr_struct_layout_t pow_dist = {
.name = "Shelf Power Distribution", .length = 1,
.item_count = 1, .items = pow_dist_items,
.array_count = 1, .arrays = pow_dist_arys,
.cleanup = ipmi_mr_struct_cleanup
};
/***********************************************************************
*
* Shelf activation and power management record
*
**********************************************************************/
static ipmi_mr_item_layout_t act_pm_desc[] = {
{ .name = "hardware address", .dtype = IPMI_FRU_DATA_INT, .settable = 1,
.start = 0, .length = 1,
.set_field = ipmi_mr_int_set_field, .get_field = ipmi_mr_int_get_field },
{ .name = "FRU device id", .dtype = IPMI_FRU_DATA_INT, .settable = 1,
.start = 1, .length = 1,
.set_field = ipmi_mr_int_set_field, .get_field = ipmi_mr_int_get_field },
{ .name = "max FRU power", .dtype = IPMI_FRU_DATA_INT, .settable = 1,
.start = 2, .length = 2,
.set_field = ipmi_mr_int_set_field, .get_field = ipmi_mr_int_get_field },
{ .name = "shelf manager activation", .dtype = IPMI_FRU_DATA_BOOLEAN,
.settable = 1,
.start = 38, .length = 1,
.set_field = ipmi_mr_bitint_set_field, .get_field = ipmi_mr_bitint_get_field },
{ .name = "delay before next power on", .dtype = IPMI_FRU_DATA_INT,
.settable = 1,
.start = 32, .length = 6,
.set_field = ipmi_mr_bitint_set_field, .get_field = ipmi_mr_bitint_get_field }
};
static ipmi_mr_struct_layout_t act_pm_descs = {
.name = NULL, .length = 5,
.item_count = 5, .items = act_pm_desc,
.array_count = 0, .arrays = NULL,
.cleanup = ipmi_mr_struct_cleanup
};
static ipmi_mr_item_layout_t act_pm_items[] = {
{ .name = "version", .dtype = IPMI_FRU_DATA_INT, .settable = 0,
.start = 0, .length = 1,
.set_field = NULL, .get_field = ipmi_mr_int_get_field },
{ .name = "allowance for activation readiness", .dtype = IPMI_FRU_DATA_INT,
.settable = 1,
.start = 1, .length = 1,
.set_field = ipmi_mr_int_set_field, .get_field = ipmi_mr_int_get_field }
};
static ipmi_mr_array_layout_t act_pm_arys[] = {
{ .name = "activation power descriptors", .has_count = 1, .settable = 1,
.min_elem_size = 5,
.elem_layout = &act_pm_descs,
.elem_check = ipmi_mr_struct_elem_check, .elem_decode = ipmi_mr_struct_decode,
.cleanup = ipmi_mr_struct_array_cleanup,
.get_field = ipmi_mr_struct_array_get_field,
.set_field = ipmi_mr_struct_array_set_field }
};
static ipmi_mr_struct_layout_t act_pm = {
.name = "Shelf Activation and Power Management", .length = 2,
.item_count = 1, .items = act_pm_items,
.array_count = 1, .arrays = act_pm_arys,
.cleanup = ipmi_mr_struct_cleanup
};
/***********************************************************************
*
* Shelf manager IP connection record
*
**********************************************************************/
static ipmi_mr_item_layout_t ip_conn0_items[] = {
{ .name = "version", .dtype = IPMI_FRU_DATA_INT, .settable = 0,
.start = 0, .length = 1,
.set_field = NULL, .get_field = ipmi_mr_int_get_field },
{ .name = "ip address", .dtype = IPMI_FRU_DATA_ASCII,
.settable = 1,
.start = 1, .length = 4,
.set_field = ipmi_mr_ip_set_field, .get_field = ipmi_mr_ip_get_field }
};
static ipmi_mr_struct_layout_t ip_conn0 = {
.name = "Shelf Manager IP Connection", .length = 5,
.item_count = 2, .items = ip_conn0_items,
.array_count = 0, .arrays = NULL,
.cleanup = ipmi_mr_struct_cleanup
};
static ipmi_mr_item_layout_t ip_conn1_items[] = {
{ .name = "version", .dtype = IPMI_FRU_DATA_INT, .settable = 0,
.start = 0, .length = 1,
.set_field = NULL, .get_field = ipmi_mr_int_get_field },
{ .name = "ip address", .dtype = IPMI_FRU_DATA_ASCII,
.settable = 1,
.start = 1, .length = 4,
.set_field = ipmi_mr_ip_set_field, .get_field = ipmi_mr_ip_get_field },
{ .name = "gateway address", .dtype = IPMI_FRU_DATA_ASCII,
.settable = 1,
.start = 5, .length = 4,
.set_field = ipmi_mr_ip_set_field, .get_field = ipmi_mr_ip_get_field },
{ .name = "subnet mask", .dtype = IPMI_FRU_DATA_ASCII,
.settable = 1,
.start = 9, .length = 4,
.set_field = ipmi_mr_ip_set_field, .get_field = ipmi_mr_ip_get_field }
};
static ipmi_mr_struct_layout_t ip_conn1 = {
.name = "Shelf Manager IP Connection", .length = 13,
.item_count = 4, .items = ip_conn1_items,
.array_count = 0, .arrays = NULL,
.cleanup = ipmi_mr_struct_cleanup
};
static int
atca_root_ipmi_mr_shelf_mgr_ip_conn(ipmi_fru_t *fru,
unsigned int mr_rec_num,
unsigned char *mr_data,
unsigned int mr_data_len,
const char **name,
ipmi_fru_node_t **node)
{
ipmi_mr_struct_layout_t *layout;
if (mr_data_len < 5)
return EINVAL;
switch (mr_data[4]) {
case 0: layout = &ip_conn0; break;
case 1: layout = &ip_conn1; break;
default:
return EINVAL;
}
return ipmi_mr_struct_root(fru, mr_rec_num, mr_data+4, mr_data_len-4,
layout, name, node);
}
/***********************************************************************
*
* Board point-to-point Connectivity record
*
**********************************************************************/
static ipmi_mr_item_layout_t guid_elem = {
.name = "GUID", .dtype = IPMI_FRU_DATA_BINARY, .settable = 1,
.start = 0, .length = 16,
.set_field = ipmi_mr_binary_set_field,
.get_field = ipmi_mr_binary_get_field
};
static ipmi_mr_tab_item_t link_if_tab = {
.count = 3,
.table = { "base", "fabric", "update channel" }
};
static ipmi_mr_item_layout_t link_desc[] = {
{ .name = "link grouping id", .dtype = IPMI_FRU_DATA_INT, .settable = 1,
.start = 24, .length = 8,
.set_field = ipmi_mr_bitint_set_field, .get_field = ipmi_mr_bitint_get_field },
{ .name = "link type extension", .dtype = IPMI_FRU_DATA_INT, .settable = 1,
.start = 20, .length = 4,
.set_field = ipmi_mr_bitint_set_field, .get_field = ipmi_mr_bitint_get_field },
{ .name = "link type", .dtype = IPMI_FRU_DATA_INT, .settable = 1,
.start = 12, .length = 8,
.set_field = ipmi_mr_bitint_set_field, .get_field = ipmi_mr_bitint_get_field },
{ .name = "port 3 included", .dtype = IPMI_FRU_DATA_BOOLEAN, .settable = 1,
.start = 11, .length = 1,
.set_field = ipmi_mr_bitint_set_field, .get_field = ipmi_mr_bitint_get_field },
{ .name = "port 2 included", .dtype = IPMI_FRU_DATA_BOOLEAN, .settable = 1,
.start = 10, .length = 1,
.set_field = ipmi_mr_bitint_set_field, .get_field = ipmi_mr_bitint_get_field },
{ .name = "port 1 included", .dtype = IPMI_FRU_DATA_BOOLEAN, .settable = 1,
.start = 9, .length = 1,
.set_field = ipmi_mr_bitint_set_field, .get_field = ipmi_mr_bitint_get_field },
{ .name = "port 0 included", .dtype = IPMI_FRU_DATA_BOOLEAN, .settable = 1,
.start = 8, .length = 1,
.set_field = ipmi_mr_bitint_set_field, .get_field = ipmi_mr_bitint_get_field },
{ .name = "interface", .dtype = IPMI_FRU_DATA_ASCII, .settable = 1,
.start = 6, .length = 2,
.u = { .tab_data = &link_if_tab },
.set_field = ipmi_mr_bitvaltab_set_field,
.get_field = ipmi_mr_bitvaltab_get_field,
.get_enum = ipmi_mr_bitvaltab_get_enum },
{ .name = "channel number", .dtype = IPMI_FRU_DATA_INT, .settable = 1,
.start = 0, .length = 6,
.set_field = ipmi_mr_bitint_set_field, .get_field = ipmi_mr_bitint_get_field }
};
static ipmi_mr_struct_layout_t link_descs = {
.name = NULL, .length = 4,
.item_count = 9, .items = link_desc,
.array_count = 0, .arrays = NULL,
.cleanup = ipmi_mr_struct_cleanup
};
static ipmi_mr_item_layout_t bp2p_conn_items[] = {
{ .name = "version", .dtype = IPMI_FRU_DATA_INT, .settable = 0,
.start = 0, .length = 1,
.set_field = NULL, .get_field = ipmi_mr_int_get_field }
};
static ipmi_mr_array_layout_t bp2p_conn_arys[] = {
{ .name = "OEM GUIDs", .has_count = 1, .settable = 1,
.min_elem_size = 16,
.elem_layout = &guid_elem,
.elem_check = ipmi_mr_item_elem_check,
.elem_decode = ipmi_mr_item_decode,
.cleanup = ipmi_mr_item_array_cleanup,
.get_field = ipmi_mr_item_array_get_field,
.set_field = ipmi_mr_item_array_set_field },
{ .name = "Link Descriptors", .has_count = 0,
.min_elem_size = 4,
.elem_layout = &link_descs,
.elem_check = ipmi_mr_struct_elem_check,
.elem_decode = ipmi_mr_struct_decode,
.cleanup = ipmi_mr_struct_array_cleanup,
.get_field = ipmi_mr_struct_array_get_field,
.set_field = ipmi_mr_struct_array_set_field }
};
static ipmi_mr_struct_layout_t bp2p_conn = {
.name = "Board P2P Connectivity", .length = 1,
.item_count = 1, .items = bp2p_conn_items,
.array_count = 2, .arrays = bp2p_conn_arys,
.cleanup = ipmi_mr_struct_cleanup
};
/***********************************************************************
*
* Radial IPMB-0 Link Mapping
*
**********************************************************************/
static ipmi_mr_item_layout_t ipmb_link_mapping[] = {
{ .name = "hardware address", .dtype = IPMI_FRU_DATA_INT, .settable = 1,
.start = 0, .length = 1,
.set_field = ipmi_mr_int_set_field, .get_field = ipmi_mr_int_get_field },
{ .name = "IPMB-0 link entry", .dtype = IPMI_FRU_DATA_INT, .settable = 1,
.start = 1, .length = 1,
.set_field = ipmi_mr_int_set_field, .get_field = ipmi_mr_int_get_field }
};
static ipmi_mr_struct_layout_t ipmb_link_mappings = {
.name = NULL, .length = 2,
.item_count = 2, .items = ipmb_link_mapping,
.array_count = 0, .arrays = NULL,
.cleanup = ipmi_mr_struct_cleanup
};
static ipmi_mr_tab_item_t hub_info_if_tab = {
.count = 4,
.table = { NULL, "IPMB-A only", "IPMB-B only", "IPMB-A and IPMB-B" }
};
static ipmi_mr_item_layout_t hub_desc_items[] = {
{ .name = "hardware address", .dtype = IPMI_FRU_DATA_INT, .settable = 1,
.start = 0, .length = 1,
.set_field = ipmi_mr_int_set_field, .get_field = ipmi_mr_int_get_field },
{ .name = "bus coverage", .dtype = IPMI_FRU_DATA_ASCII, .settable = 1,
.start = 8, .length = 2,
.u = { .tab_data = &hub_info_if_tab },
.set_field = ipmi_mr_bitvaltab_set_field,
.get_field = ipmi_mr_bitvaltab_get_field,
.get_enum = ipmi_mr_bitvaltab_get_enum }
};
static ipmi_mr_array_layout_t hub_desc_arys[] = {
{ .name = "IPMB-0 link mappings", .has_count = 1, .settable = 1,
.min_elem_size = 4,
.elem_layout = &ipmb_link_mappings,
.elem_check = ipmi_mr_struct_elem_check,
.elem_decode = ipmi_mr_struct_decode,
.cleanup = ipmi_mr_struct_array_cleanup,
.get_field = ipmi_mr_struct_array_get_field,
.set_field = ipmi_mr_struct_array_set_field }
};
static ipmi_mr_struct_layout_t hub_descs = {
.name = NULL, .length = 2,
.item_count = 2, .items = hub_desc_items,
.array_count = 1, .arrays = hub_desc_arys,
.cleanup = ipmi_mr_struct_cleanup
};
static ipmi_mr_item_layout_t rad_ipmb_items[] = {
{ .name = "version", .dtype = IPMI_FRU_DATA_INT, .settable = 0,
.start = 0, .length = 1,
.set_field = NULL, .get_field = ipmi_mr_int_get_field },
{ .name = "connecter definer", .dtype = IPMI_FRU_DATA_INT, .settable = 1,
.start = 1, .length = 3,
.set_field = ipmi_mr_int_set_field, .get_field = ipmi_mr_int_get_field },
{ .name = "connecter version", .dtype = IPMI_FRU_DATA_INT, .settable = 1,
.start = 4, .length = 2,
.set_field = ipmi_mr_int_set_field, .get_field = ipmi_mr_int_get_field }
};
static ipmi_mr_array_layout_t rad_ipmb_arys[] = {
{ .name = "hub descriptors", .has_count = 1, .settable = 1,
.min_elem_size = 4,
.elem_layout = &hub_descs,
.elem_check = ipmi_mr_struct_elem_check,
.elem_decode = ipmi_mr_struct_decode,
.cleanup = ipmi_mr_struct_array_cleanup,
.get_field = ipmi_mr_struct_array_get_field,
.set_field = ipmi_mr_struct_array_set_field }
};
static ipmi_mr_struct_layout_t rad_ipmb = {
.name = "Radial IPMB-0 Link Mapping", .length = 6,
.item_count = 3, .items = rad_ipmb_items,
.array_count = 1, .arrays = rad_ipmb_arys,
.cleanup = ipmi_mr_struct_cleanup
};
/***********************************************************************
*
* Shelf fan geography record
*
**********************************************************************/
static ipmi_mr_item_layout_t fan_to_frus_items[] = {
{ .name = "hardware address", .dtype = IPMI_FRU_DATA_INT, .settable = 1,
.start = 0, .length = 1,
.set_field = ipmi_mr_int_set_field, .get_field = ipmi_mr_int_get_field },
{ .name = "FRU device id", .dtype = IPMI_FRU_DATA_INT, .settable = 1,
.start = 1, .length = 1,
.set_field = ipmi_mr_int_set_field, .get_field = ipmi_mr_int_get_field },
{ .name = "site number", .dtype = IPMI_FRU_DATA_INT, .settable = 1,
.start = 2, .length = 1,
.set_field = ipmi_mr_int_set_field, .get_field = ipmi_mr_int_get_field },
{ .name = "site type", .dtype = IPMI_FRU_DATA_INT, .settable = 1,
.start = 3, .length = 1,
.set_field = ipmi_mr_int_set_field, .get_field = ipmi_mr_int_get_field }
};
static ipmi_mr_struct_layout_t fan_to_frus = {
.name = NULL, .length = 4,
.item_count = 4, .items = fan_to_frus_items,
.array_count = 0, .arrays = NULL,
.cleanup = ipmi_mr_struct_cleanup
};
static ipmi_mr_item_layout_t fan_geog_items[] = {
{ .name = "version", .dtype = IPMI_FRU_DATA_INT, .settable = 0,
.start = 0, .length = 1,
.set_field = NULL, .get_field = ipmi_mr_int_get_field }
};
static ipmi_mr_array_layout_t fan_geog_arys[] = {
{ .name = "fan to frus", .has_count = 1, .settable = 1,
.min_elem_size = 4,
.elem_layout = &fan_to_frus,
.elem_check = ipmi_mr_struct_elem_check,
.elem_decode = ipmi_mr_struct_decode,
.cleanup = ipmi_mr_struct_array_cleanup,
.get_field = ipmi_mr_struct_array_get_field,
.set_field = ipmi_mr_struct_array_set_field }
};
static ipmi_mr_struct_layout_t fan_geog = {
.name = "Shelf Fan Geography", .length = 1,
.item_count = 1, .items = fan_geog_items,
.array_count = 1, .arrays = fan_geog_arys,
.cleanup = ipmi_mr_struct_cleanup
};
/***********************************************************************
*
* Initialization code
*
**********************************************************************/
int
i_ipmi_atca_fru_get_mr_root(ipmi_fru_t *fru,
unsigned int mr_rec_num,
unsigned int manufacturer_id,
unsigned char record_type_id,
unsigned char *mr_data,
unsigned int mr_data_len,
void *cb_data,
const char **name,
ipmi_fru_node_t **node)
{
/* A record type and version number. */
if (mr_data_len < 5)
return EINVAL;
switch (mr_data[3]) {
case 4: /* backplane point-to-point connectivity record */
if (mr_data[4] != 0)
return EINVAL;
return ipmi_mr_struct_root(fru, mr_rec_num, mr_data+4, mr_data_len-4,
&p2p_cr,
name, node);
case 0x10: /* shelf address table */
if (mr_data[4] != 0)
return EINVAL;
return ipmi_mr_struct_root(fru, mr_rec_num, mr_data+4, mr_data_len-4,
&addr_tab,
name, node);
case 0x11: /* Shelf power distribution */
if (mr_data[4] != 0)
return EINVAL;
return ipmi_mr_struct_root(fru, mr_rec_num, mr_data+4, mr_data_len-4,
&pow_dist,
name, node);
case 0x12: /* Shelf activation and power mgmt */
if (mr_data[4] != 0)
return EINVAL;
return ipmi_mr_struct_root(fru, mr_rec_num, mr_data+4, mr_data_len-4,
&act_pm,
name, node);
case 0x13: /* Shelf Manager IP Connection Record */
return atca_root_ipmi_mr_shelf_mgr_ip_conn(fru, mr_rec_num,
mr_data, mr_data_len,
name, node);
case 0x14: /* Board p2p connectivity record */
if (mr_data[4] != 0)
return EINVAL;
return ipmi_mr_struct_root(fru, mr_rec_num, mr_data+4, mr_data_len-4,
&bp2p_conn,
name, node);
case 0x15: /* radial ipmb0 link mapping */
if (mr_data[4] != 0)
return EINVAL;
return ipmi_mr_struct_root(fru, mr_rec_num, mr_data+4, mr_data_len-4,
&rad_ipmb,
name, node);
case 0x1b: /* Shelf fan geography record */
if (mr_data[4] != 0)
return EINVAL;
return ipmi_mr_struct_root(fru, mr_rec_num, mr_data+4, mr_data_len-4,
&fan_geog,
name, node);
default:
return ENOSYS;
}
}