/* * ipicmg.c * * This module handles PICMG extended IPMI commands. * * Change History: * 06/03/2010 ARCress - new, included in source tree * 08/15/2011 ARCress - updated with PICMG 2.3 * *---------------------------------------------------------------------- * Copyright (c) 2010 Kontron. All right reserved * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of Kontron, or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any kind. * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. * THE COPYRIGHT HOLDER AND ITS LICENSORS SHALL NOT BE LIABLE * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL THE * COPYRIGHT HOLDER OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR * DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, * EVEN IF COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. *---------------------------------------------------------------------- */ #ifdef WIN32 #include #include #include #include #include "getopt.h" #else #include #include #include #if defined(HPUX) /* getopt is defined in stdio.h */ #elif defined(MACOS) /* getopt is defined in unistd.h */ #include #else #include #endif #endif #include "ipmicmd.h" #include "ipicmg.h" /* Misc PICMG defines */ #define PICMG_EXTENSION_ATCA_MAJOR_VERSION 2 #define PICMG_EXTENSION_AMC0_MAJOR_VERSION 4 #define PICMG_EXTENSION_UTCA_MAJOR_VERSION 5 #define PICMG_EKEY_MODE_QUERY 0 #define PICMG_EKEY_MODE_PRINT_ALL 1 #define PICMG_EKEY_MODE_PRINT_ENABLED 2 #define PICMG_EKEY_MODE_PRINT_DISABLED 3 #define PICMG_EKEY_MAX_CHANNEL 16 #define PICMG_EKEY_MAX_FABRIC_CHANNEL 15 #define PICMG_EKEY_MAX_INTERFACE 3 #define PICMG_EKEY_AMC_MAX_CHANNEL 16 #define PICMG_EKEY_AMC_MAX_DEVICE 15 /* 4 bits */ /* Global data */ #ifdef METACOMMAND extern char * progver; /*from ipmiutil.c*/ static char * progname = "ipmiutil picmg"; #else static char * progver = "3.08"; static char * progname = "ipicmg"; #endif static char fdebug = 0; static char fset_mc = 0; static uint8_t g_bus = PUBLIC_BUS; static uint8_t g_sa = BMC_SA; static uint8_t g_lun = BMC_LUN; static uint8_t g_addrtype = ADDR_SMI; static uint8_t g_fruid = 0; static unsigned char PicmgExtMajorVersion; /* the LED color capabilities */ static const char* led_color_str[] = { //__attribute__((unused)) = { "reserved", "BLUE", "RED", "GREEN", "AMBER", "ORANGE", "WHITE", "reserved" }; static const char* amc_link_type_str[] = { // __attribute__((unused)) = { "RESERVED", "RESERVED1", "PCI EXPRESS", "ADVANCED SWITCHING1", "ADVANCED SWITCHING2", "ETHERNET", "RAPIDIO", "STORAGE", }; static const char* amc_link_type_ext_str[][16]= { // __attribute__((unused)) /* FRU_PICMGEXT_AMC_LINK_TYPE_RESERVED */ { "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, /* FRU_PICMGEXT_AMC_LINK_TYPE_RESERVED1 */ { "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, /* FRU_PICMGEXT_AMC_LINK_TYPE_PCI_EXPRESS */ { "Gen 1 - NSSC", "Gen 1 - SSC", "Gen 2 - NSSC", "Gen 2 - SSC", "", "", "", "", "", "", "", "", "", "", "", "" }, /* FRU_PICMGEXT_AMC_LINK_TYPE_ADVANCED_SWITCHING1 */ { "Gen 1 - NSSC", "Gen 1 - SSC", "Gen 2 - NSSC", "Gen 2 - SSC", "", "", "", "", "", "", "", "", "", "", "", "" }, /* FRU_PICMGEXT_AMC_LINK_TYPE_ADVANCED_SWITCHING2 */ { "Gen 1 - NSSC", "Gen 1 - SSC", "Gen 2 - NSSC", "Gen 2 - SSC", "", "", "", "", "", "", "", "", "", "", "", "" }, /* FRU_PICMGEXT_AMC_LINK_TYPE_ETHERNET */ { "1000BASE-BX (SerDES Gigabit)", "10GBASE-BX410 Gigabit XAUI", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, /* FRU_PICMGEXT_AMC_LINK_TYPE_RAPIDIO */ { "1.25 Gbaud transmission rate", "2.5 Gbaud transmission rate", "3.125 Gbaud transmission rate", "", "", "", "", "", "", "", "", "", "", "", "", "" }, /* FRU_PICMGEXT_AMC_LINK_TYPE_STORAGE */ { "Fibre Channel", "Serial ATA", "Serial Attached SCSI", "", "", "", "", "", "", "", "", "", "", "", "", "" } }; typedef enum picmg_bused_resource_mode { PICMG_BUSED_RESOURCE_SUMMARY, } t_picmg_bused_resource_mode ; typedef enum picmg_card_type { PICMG_CARD_TYPE_CPCI, PICMG_CARD_TYPE_ATCA, PICMG_CARD_TYPE_AMC, PICMG_CARD_TYPE_RESERVED } t_picmg_card_type ; /* This is the version of the PICMG Extenstion */ static t_picmg_card_type PicmgCardType = PICMG_CARD_TYPE_RESERVED; const struct valstr picmg_frucontrol_vals[] = { { 0, "Cold Reset" }, { 1, "Warm Reset" }, { 2, "Graceful Reboot" }, { 3, "Issue Diagnostic Interrupt" }, { 4, "Quiesce" }, { 5, NULL }, }; const struct valstr picmg_clk_family_vals[] = { { 0x00, "Unspecified" }, { 0x01, "SONET/SDH/PDH" }, { 0x02, "Reserved for PCI Express" }, { 0x03, "Reserved" }, /* from 03h to C8h */ { 0xC9, "Vendor defined clock family" }, /* from C9h to FFh */ { 0x00, NULL }, }; const struct oemvalstr picmg_clk_accuracy_vals[] = { { 0x01, 10, "PRS" }, { 0x01, 20, "STU" }, { 0x01, 30, "ST2" }, { 0x01, 40, "TNC" }, { 0x01, 50, "ST3E" }, { 0x01, 60, "ST3" }, { 0x01, 70, "SMC" }, { 0x01, 80, "ST4" }, { 0x01, 90, "DUS" }, { 0x02, 0xE0, "PCI Express Generation 2" }, { 0x02, 0xF0, "PCI Express Generation 1" }, { 0xffffff, 0x00, NULL } }; const struct oemvalstr picmg_clk_resource_vals[] = { { 0x0, 0, "On-Carrier Device 0" }, { 0x0, 1, "On-Carrier Device 1" }, { 0x1, 1, "AMC Site 1 - A1" }, { 0x1, 2, "AMC Site 1 - A2" }, { 0x1, 3, "AMC Site 1 - A3" }, { 0x1, 4, "AMC Site 1 - A4" }, { 0x1, 5, "AMC Site 1 - B1" }, { 0x1, 6, "AMC Site 1 - B2" }, { 0x1, 7, "AMC Site 1 - B3" }, { 0x1, 8, "AMC Site 1 - B4" }, { 0x2, 0, "ATCA Backplane" }, { 0xffffff, 0x00, NULL } }; const struct oemvalstr picmg_clk_id_vals[] = { { 0x0, 0, "Clock 0" }, { 0x0, 1, "Clock 1" }, { 0x0, 2, "Clock 2" }, { 0x0, 3, "Clock 3" }, { 0x0, 4, "Clock 4" }, { 0x0, 5, "Clock 5" }, { 0x0, 6, "Clock 6" }, { 0x0, 7, "Clock 7" }, { 0x0, 8, "Clock 8" }, { 0x0, 9, "Clock 9" }, { 0x0, 10, "Clock 10" }, { 0x0, 11, "Clock 11" }, { 0x0, 12, "Clock 12" }, { 0x0, 13, "Clock 13" }, { 0x0, 14, "Clock 14" }, { 0x0, 15, "Clock 15" }, { 0x1, 1, "TCLKA" }, { 0x1, 2, "TCLKB" }, { 0x1, 3, "TCLKC" }, { 0x1, 4, "TCLKD" }, { 0x1, 5, "FLCKA" }, { 0x2, 1, "CLK1A" }, { 0x2, 2, "CLK1A" }, { 0x2, 3, "CLK1A" }, { 0x2, 4, "CLK1A" }, { 0x2, 5, "CLK1A" }, { 0x2, 6, "CLK1A" }, { 0x2, 7, "CLK1A" }, { 0x2, 8, "CLK1A" }, { 0x2, 9, "CLK1A" }, { 0xffffff, 0x00, NULL } }; const struct valstr picmg_busres_id_vals[] = { { 0x0, "Metallic Test Bus pair #1" }, { 0x1, "Metallic Test Bus pair #2" }, { 0x2, "Synch clock group 1 (CLK1)" }, { 0x3, "Synch clock group 2 (CLK2)" }, { 0x4, "Synch clock group 3 (CLK3)" }, { 0x5, NULL } }; const struct valstr picmg_busres_board_cmd_vals[] = { { 0x0, "Query" }, { 0x1, "Release" }, { 0x2, "Force" }, { 0x3, "Bus Free" }, { 0x4, NULL } }; const struct valstr picmg_busres_shmc_cmd_vals[] = { { 0x0, "Request" }, { 0x1, "Relinquish" }, { 0x2, "Notify" }, { 0x3, NULL } }; const struct oemvalstr picmg_busres_board_status_vals[] = { { 0x0, 0x0, "In control" }, { 0x0, 0x1, "No control" }, { 0x1, 0x0, "Ack" }, { 0x1, 0x1, "Refused" }, { 0x1, 0x2, "No control" }, { 0x2, 0x0, "Ack" }, { 0x2, 0x1, "No control" }, { 0x3, 0x0, "Accept" }, { 0x3, 0x1, "Not Needed" }, { 0xffffff, 0x00, NULL } }; const struct oemvalstr picmg_busres_shmc_status_vals[] = { { 0x0, 0x0, "Grant" }, { 0x0, 0x1, "Busy" }, { 0x0, 0x2, "Defer" }, { 0x0, 0x3, "Deny" }, { 0x1, 0x0, "Ack" }, { 0x1, 0x1, "Error" }, { 0x2, 0x0, "Ack" }, { 0x2, 0x1, "Error" }, { 0x2, 0x2, "Deny" }, { 0xffffff, 0x00, NULL } }; void ipmi_picmg_help (void) { printf(" properties - get PICMG properties\n"); printf(" frucontrol - FRU control\n"); printf(" addrinfo - get address information\n"); printf(" activate - activate a FRU\n"); printf(" deactivate - deactivate a FRU\n"); printf(" policy get - get the FRU activation policy\n"); printf(" policy set - set the FRU activation policy\n"); printf(" portstate get - get port state \n"); printf(" portstate getdenied - get all denied[disabled] port description\n"); printf(" portstate getgranted - get all granted[enabled] port description\n"); printf(" portstate getall - get all port state description\n"); printf(" portstate set - set port state \n"); printf(" amcportstate get - get port state \n"); printf(" amcportstate set - set port state \n"); printf(" led prop - get led properties\n"); printf(" led cap - get led color capabilities\n"); printf(" led get - get led state\n"); printf(" led set - set led state\n"); printf(" power get - get power level info\n"); printf(" power set - set power level\n"); printf(" clk get - get clk state\n"); printf(" clk getdenied - get all(up to 16) denied[disabled] clock descriptions\n"); printf(" clk getgranted - get all(up to 16) granted[enabled] clock descriptions\n"); printf(" clk getall - get all(up to 16) clock descriptions\n"); printf(" clk set - set clk state\n"); printf(" busres summary - display brief bused resource status info \n"); } struct sAmcAddrMap { unsigned char ipmbLAddr; char* amcBayId; unsigned char siteNum; } amcAddrMap[] = { {0xFF, "reserved", 0}, {0x72, "A1" , 1}, {0x74, "A2" , 2}, {0x76, "A3" , 3}, {0x78, "A4" , 4}, {0x7A, "B1" , 5}, {0x7C, "B2" , 6}, {0x7E, "B3" , 7}, {0x80, "B4" , 8}, {0x82, "reserved", 0}, {0x84, "reserved", 0}, {0x86, "reserved", 0}, {0x88, "reserved", 0}, }; int ipmi_picmg_getaddr(void * intf, int argc, char ** argv) { uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv; struct ipmi_rq req; unsigned char msg_data[5]; memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_PICMG; req.msg.cmd = PICMG_GET_ADDRESS_INFO_CMD; req.msg.data = msg_data; req.msg.data_len = 2; msg_data[0] = 0; /* picmg identifier */ msg_data[1] = 0; /* default fru id */ if(argc > 0) { msg_data[1] = (uint8_t)strtoul(argv[0], NULL,0); /* FRU ID */ } rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv) { printf("Error getting address information CC: 0x%02x\n", rv); return rv; } printf("Hardware Address : 0x%02x\n", rsp[1]); printf("IPMB-0 Address : 0x%02x\n", rsp[2]); printf("FRU ID : 0x%02x\n", rsp[4]); printf("Site ID : 0x%02x\n", rsp[5]); printf("Site Type : "); switch (rsp[6]) { case PICMG_ATCA_BOARD: printf("ATCA board\n"); break; case PICMG_POWER_ENTRY: printf("Power Entry Module\n"); break; case PICMG_SHELF_FRU: printf("Shelf FRU\n"); break; case PICMG_DEDICATED_SHMC: printf("Dedicated Shelf Manager\n"); break; case PICMG_FAN_TRAY: printf("Fan Tray\n"); break; case PICMG_FAN_FILTER_TRAY: printf("Fan Filter Tray\n"); break; case PICMG_ALARM: printf("Alarm module\n"); break; case PICMG_AMC: printf("AMC"); printf(" -> IPMB-L Address: 0x%02x\n", amcAddrMap[rsp[5]].ipmbLAddr); break; case PICMG_PMC: printf("PMC\n"); break; case PICMG_RTM: printf("RTM\n"); break; default: if (rsp[6] >= 0xc0 && rsp[6] <= 0xcf) { printf("OEM\n"); } else { printf("unknown\n"); } } return 0; } int ipmi_picmg_properties(void * intf, int show ) { uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv; unsigned char PicmgExtMajorVersion; struct ipmi_rq req; unsigned char msg_data; memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_PICMG; req.msg.cmd = PICMG_GET_PICMG_PROPERTIES_CMD; req.msg.data = &msg_data; req.msg.data_len = 1; msg_data = 0; rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv) { printf("Error %d getting picmg properties\n", rv); return rv; } if( show ) { printf("PICMG identifier : 0x%02x\n", rsp[0]); printf("PICMG Ext. Version : %i.%i\n", rsp[1]&0x0f, (rsp[1]&0xf0) >> 4); printf("Max FRU Device ID : 0x%02x\n", rsp[2]); printf("FRU Device ID : 0x%02x\n", rsp[3]); } /* We cache the major extension version ... to know how to format some commands */ PicmgExtMajorVersion = rsp[1]&0x0f; if( PicmgExtMajorVersion == PICMG_CPCI_MAJOR_VERSION ) { PicmgCardType = PICMG_CARD_TYPE_CPCI; } else if( PicmgExtMajorVersion == PICMG_ATCA_MAJOR_VERSION) { PicmgCardType = PICMG_CARD_TYPE_ATCA; } else if( PicmgExtMajorVersion == PICMG_AMC_MAJOR_VERSION) { PicmgCardType = PICMG_CARD_TYPE_AMC; } return 0; } #define PICMG_FRU_DEACTIVATE (unsigned char) 0x00 #define PICMG_FRU_ACTIVATE (unsigned char) 0x01 int ipmi_picmg_fru_activation(void * intf, int argc, char ** argv, unsigned char state) { uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv; struct ipmi_rq req; struct picmg_set_fru_activation_cmd cmd; memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_PICMG; req.msg.cmd = PICMG_FRU_ACTIVATION_CMD; req.msg.data = (unsigned char*) &cmd; req.msg.data_len = 3; cmd.picmg_id = 0; /* PICMG identifier */ cmd.fru_id = atob(argv[0]); /* FRU ID */ cmd.fru_state = state; rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv) { printf("Error %d on activation/deactivation of FRU\n",rv); return rv; } if (rsp[0] != 0x00) { printf("Error, invalid response\n"); } return 0; } int ipmi_picmg_fru_activation_policy_get(void * intf, int argc, char ** argv) { uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv; struct ipmi_rq req; unsigned char msg_data[4]; memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_PICMG; req.msg.cmd = PICMG_GET_FRU_POLICY_CMD; req.msg.data = msg_data; req.msg.data_len = 2; msg_data[0] = 0; /* PICMG identifier */ msg_data[1] = atob(argv[0]); /* FRU ID */ rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv) { if (rv < 0) printf("no response\n"); else printf("returned Completion Code 0x%02x\n", rv); return rv; } printf(" %s\n", ((rsp[1] & 0x01) == 0x01) ? "activation locked" : "activation not locked"); printf(" %s\n", ((rsp[1] & 0x02) == 0x02) ? "deactivation locked" : "deactivation not locked"); return 0; } int ipmi_picmg_fru_activation_policy_set(void * intf, int argc, char ** argv) { uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv; struct ipmi_rq req; unsigned char msg_data[4]; memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_PICMG; req.msg.cmd = PICMG_SET_FRU_POLICY_CMD; req.msg.data = msg_data; req.msg.data_len = 4; msg_data[0] = 0; /* PICMG identifier */ msg_data[1] = atob(argv[0]); /* FRU ID */ msg_data[2] = atob(argv[1])& 0x03; /* FRU act policy mask */ msg_data[3] = atob(argv[2])& 0x03; /* FRU act policy set bits */ rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv) { if (rv < 0) printf("no response\n"); else printf("returned Completion Code 0x%02x\n", rv); return rv; } return 0; } #define PICMG_MAX_LINK_PER_CHANNEL 4 int ipmi_picmg_portstate_get(void * intf, int interfc, uchar channel, int mode) { uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv; struct ipmi_rq req; unsigned char msg_data[4]; struct fru_picmgext_link_desc* d; /* descriptor pointer for rec. data */ memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_PICMG; req.msg.cmd = PICMG_GET_PORT_STATE_CMD; req.msg.data = msg_data; req.msg.data_len = 2; msg_data[0] = 0x00; /* PICMG identifier */ msg_data[1] = (interfc & 0x3)<<6; /* interface */ msg_data[1] |= (channel & 0x3F); /* channel number */ rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv) { if (rv < 0) printf("no response\n"); else if( mode == PICMG_EKEY_MODE_QUERY ) printf("returned Completion Code 0x%02x\n", rv); return rv; } if (rsp_len >= 6) { int index; /* add support for more than one link per channel */ for(index=0;index (1+ (index*5))){ d = (struct fru_picmgext_link_desc *) &(rsp[1 + (index*5)]); if ( mode == PICMG_EKEY_MODE_PRINT_ALL || mode == PICMG_EKEY_MODE_QUERY || ( mode == PICMG_EKEY_MODE_PRINT_ENABLED && rsp[5 + (index*5) ] == 0x01 ) || ( mode == PICMG_EKEY_MODE_PRINT_DISABLED && rsp[5 + (index*5) ] == 0x00 ) ) { printf(" Link Grouping ID: 0x%02x\n", d->grouping); printf(" Link Type Extension: 0x%02x\n", d->ext); printf(" Link Type: 0x%02x ", d->type); if (d->type == 0 || d->type == 0xff) { printf("Reserved %d\n",d->type); } else if (d->type >= 0x06 && d->type <= 0xef) { printf("Reserved %d\n",d->type); } else if (d->type >= 0xf0 && d->type <= 0xfe) { printf("OEM GUID Definition %d\n",d->type); } else { switch (d->type) { case FRU_PICMGEXT_LINK_TYPE_BASE: printf("PICMG 3.0 Base Interface 10/100/1000\n"); break; case FRU_PICMGEXT_LINK_TYPE_FABRIC_ETHERNET: printf("PICMG 3.1 Ethernet Fabric Interface\n"); break; case FRU_PICMGEXT_LINK_TYPE_FABRIC_INFINIBAND: printf("PICMG 3.2 Infiniband Fabric Interface\n"); break; case FRU_PICMGEXT_LINK_TYPE_FABRIC_STAR: printf("PICMG 3.3 Star Fabric Interface\n"); break; case FRU_PICMGEXT_LINK_TYPE_PCIE: printf("PCI Express Fabric Interface\n"); break; default: printf("Invalid\n"); break; } } printf(" Link Designator: \n"); printf(" Port Flag: 0x%02x\n", d->desig_port); printf(" Interface: 0x%02x - ", d->desig_if); switch (d->desig_if) { case FRU_PICMGEXT_DESIGN_IF_BASE: printf("Base Interface\n"); break; case FRU_PICMGEXT_DESIGN_IF_FABRIC: printf("Fabric Interface\n"); break; case FRU_PICMGEXT_DESIGN_IF_UPDATE_CHANNEL: printf("Update Channel\n"); break; case FRU_PICMGEXT_DESIGN_IF_RESERVED: printf("Reserved\n"); break; default: printf("Invalid"); break; } printf(" Channel Number: 0x%02x\n", d->desig_channel); printf(" STATE: %s\n", ( rsp[5 +(index*5)] == 0x01) ?"enabled":"disabled"); printf("\n"); } } } } else { printf("Unexpected answer len %d, can't print result\n",rsp_len); } return 0; } int ipmi_picmg_portstate_set(void * intf, int interfc, uchar channel, uchar port, int type, int typeext, int group, int enable) { uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv; struct ipmi_rq req; unsigned char msg_data[6]; // struct fru_picmgext_link_desc* d; memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_PICMG; req.msg.cmd = PICMG_SET_PORT_STATE_CMD; req.msg.data = msg_data; req.msg.data_len = 6; msg_data[0] = 0x00; /* PICMG identifier */ msg_data[1] = (channel & 0x3f) | ((interfc & 3) << 6); msg_data[2] = (port & 0xf) | ((type & 0xf) << 4); msg_data[3] = ((type >> 4) & 0xf) | ((typeext & 0xf) << 4); msg_data[4] = group & 0xff; msg_data[5] = (unsigned char) (enable & 0x01); /* en/dis */ rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv) { if (rv < 0) printf("no response\n"); else printf("returned Completion Code 0x%02x\n", rv); return rv; } return 0; } /* AMC.0 commands */ #define PICMG_AMC_MAX_LINK_PER_CHANNEL 4 int ipmi_picmg_amc_portstate_get(void * intf,int device,uchar channel, int mode) { uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv; struct ipmi_rq req; unsigned char msg_data[4]; struct fru_picmgext_amc_link_info* d; /* descriptor pointer for rec. data */ memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_PICMG; req.msg.cmd = PICMG_AMC_GET_PORT_STATE_CMD; req.msg.data = msg_data; /* FIXME : add check for AMC or carrier device */ if(device == -1 || PicmgCardType != PICMG_CARD_TYPE_ATCA ){ req.msg.data_len = 2; /* for amc only channel */ }else{ req.msg.data_len = 3; /* for carrier channel and device */ } msg_data[0] = 0x00; /* PICMG identifier */ msg_data[1] = channel ; msg_data[2] = (uchar)device ; rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv) { if (rv < 0) printf("no response\n"); else if ( mode == PICMG_EKEY_MODE_QUERY ) printf("returned Completion Code 0x%02x\n", rv); return rv; } if (rsp_len >= 5) { int index; /* add support for more than one link per channel */ for(index=0;index (1+ (index*4))){ unsigned char type; unsigned char ext; unsigned char grouping; unsigned char port; unsigned char enabled; d = (struct fru_picmgext_amc_link_info *)&(rsp[1 + (index*4)]); /* Removed endianness check here, probably not required as we dont use bitfields */ port = d->linkInfo[0] & 0x0F; type = ((d->linkInfo[0] & 0xF0) >> 4 )|(d->linkInfo[1] & 0x0F ); ext = ((d->linkInfo[1] & 0xF0) >> 4 ); grouping = d->linkInfo[2]; enabled = rsp[4 + (index*4) ]; if ( mode == PICMG_EKEY_MODE_PRINT_ALL || mode == PICMG_EKEY_MODE_QUERY || ( mode == PICMG_EKEY_MODE_PRINT_ENABLED && enabled == 0x01 ) || ( mode == PICMG_EKEY_MODE_PRINT_DISABLED && enabled == 0x00 ) ) { if(device == -1 || PicmgCardType != PICMG_CARD_TYPE_ATCA ){ printf(" Link device : AMC\n"); }else{ printf(" Link device : 0x%02x\n", device ); } printf(" Link Grouping ID: 0x%02x\n", grouping); if (type == 0 || type == 1 ||type == 0xff) { printf(" Link Type Extension: 0x%02x\n", ext); printf(" Link Type: Reserved\n"); } else if (type >= 0xf0 && type <= 0xfe) { printf(" Link Type Extension: 0x%02x\n", ext); printf(" Link Type: OEM GUID Definition\n"); } else { if (type <= FRU_PICMGEXT_AMC_LINK_TYPE_STORAGE ) { printf(" Link Type Extension: %s\n", amc_link_type_ext_str[type][ext]); printf(" Link Type: %s\n", amc_link_type_str[type]); } else{ printf(" Link Type Extension: 0x%02x\n", ext); printf(" Link Type: undefined\n"); } } printf(" Link Designator: \n"); printf(" Channel Number: 0x%02x\n", channel); printf(" Port Flag: 0x%02x\n", port ); printf(" STATE: %s\n", ( enabled == 0x01 )?"enabled":"disabled"); printf("\n"); } } } } else { printf("ipmi_picmg_amc_portstate_get: " "Unexpected answer, can't print result\n"); } return 0; } int ipmi_picmg_amc_portstate_set(void * intf, uchar channel, uchar port, int type, int typeext, int group, int enable, int device) { uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv; struct ipmi_rq req; unsigned char msg_data[7]; memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_PICMG; req.msg.cmd = PICMG_AMC_SET_PORT_STATE_CMD; req.msg.data = msg_data; msg_data[0] = 0x00; /* PICMG identifier*/ msg_data[1] = channel; /* channel id */ msg_data[2] = port & 0xF; /* port flags */ msg_data[2] |= (type & 0x0F)<<4; /* type */ msg_data[3] = (type & 0xF0)>>4; /* type */ msg_data[3] |= (typeext & 0x0F)<<4; /* extension */ msg_data[4] = (group & 0xFF); /* group */ msg_data[5] = (enable & 0x01); /* state */ req.msg.data_len = 6; /* device id - only for carrier needed */ if (device >= 0) { msg_data[6] = (uchar)device; req.msg.data_len = 7; } rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv) { if (rv < 0) printf("no response\n"); else printf("returned Completion Code 0x%02x\n", rv); return rv; } return 0; } int ipmi_picmg_get_led_properties(void * intf, int argc, char ** argv) { uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv; struct ipmi_rq req; unsigned char msg_data[6]; memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_PICMG; req.msg.cmd = PICMG_GET_FRU_LED_PROPERTIES_CMD; req.msg.data = msg_data; req.msg.data_len = 2; msg_data[0] = 0x00; /* PICMG identifier */ msg_data[1] = atob(argv[0]); /* FRU-ID */ rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv) { if (rv < 0) printf("no response\n"); else printf("returned Completion Code 0x%02x\n", rv); return rv; } printf("General Status LED Properties: 0x%2x\n\r", rsp[1] ); printf("App. Specific LED Count: 0x%2x\n\r", rsp[2] ); return 0; } int ipmi_picmg_get_led_capabilities(void * intf, int argc, char ** argv) { int i; uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv; struct ipmi_rq req; unsigned char msg_data[6]; memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_PICMG; req.msg.cmd = PICMG_GET_LED_COLOR_CAPABILITIES_CMD; req.msg.data = msg_data; req.msg.data_len = 3; msg_data[0] = 0x00; /* PICMG identifier */ msg_data[1] = atob(argv[0]); /* FRU-ID */ msg_data[2] = atob(argv[1]); /* LED-ID */ rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv) { if (rv < 0) printf("no response\n"); else printf("returned Completion Code 0x%02x\n", rv); return rv; } printf("LED Color Capabilities: %02x", rsp[1] ); for ( i=0 ; i<8 ; i++ ) { if ( rsp[1] & (0x01 << i) ) { printf("%s, ", led_color_str[ i ]); } } printf("\n\r"); printf("Default LED Color in\n\r"); printf(" LOCAL control: %s\n\r", led_color_str[ rsp[2] ] ); printf(" OVERRIDE state: %s\n\r", led_color_str[ rsp[3] ] ); return 0; } int ipmi_picmg_get_led_state(void * intf, int argc, char ** argv) { uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv; struct ipmi_rq req; unsigned char msg_data[6]; memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_PICMG; req.msg.cmd = PICMG_GET_FRU_LED_STATE_CMD; req.msg.data = msg_data; req.msg.data_len = 3; msg_data[0] = 0x00; /* PICMG identifier */ msg_data[1] = atob(argv[0]); /* FRU-ID */ msg_data[2] = atob(argv[1]); /* LED-ID */ rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv) { if (rv < 0) printf("no response\n"); else printf("returned Completion Code 0x%02x\n", rv); return rv; } printf("LED states: %x ", rsp[1] ); if (rsp[1] == 0x1) printf("[LOCAL CONTROL]\n\r"); else if (rsp[1] == 0x2) printf("[OVERRIDE]\n\r"); else if (rsp[1] == 0x4) printf("[LAMPTEST]\n\r"); else printf("\n\r"); printf(" Local Control function: %x ", rsp[2] ); if (rsp[2] == 0x0) printf("[OFF]\n\r"); else if (rsp[2] == 0xff) printf("[ON]\n\r"); else printf("[BLINKING]\n\r"); printf(" Local Control On-Duration: %x\n\r", rsp[3] ); printf(" Local Control Color: %x [%s]\n\r", rsp[4], led_color_str[ rsp[4] ]); /* override state or lamp test */ if (rsp[1] == 0x02) { printf(" Override function: %x ", rsp[5] ); if (rsp[2] == 0x0) printf("[OFF]\n\r"); else if (rsp[2] == 0xff) printf("[ON]\n\r"); else printf("[BLINKING]\n\r"); printf(" Override On-Duration: %x\n\r", rsp[6] ); printf(" Override Color: %x [%s]\n\r", rsp[7], led_color_str[ rsp[7] ]); }else if (rsp[1] == 0x06) { printf(" Override function: %x ", rsp[5] ); if (rsp[2] == 0x0) printf("[OFF]\n\r"); else if (rsp[2] == 0xff) printf("[ON]\n\r"); else printf("[BLINKING]\n\r"); printf(" Override On-Duration: %x\n\r", rsp[6] ); printf(" Override Color: %x [%s]\n\r", rsp[7], led_color_str[ rsp[7] ]); printf(" Lamp test duration: %x\n\r", rsp[8] ); } return 0; } int ipmi_picmg_set_led_state(void * intf, int argc, char ** argv) { uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv; struct ipmi_rq req; unsigned char msg_data[6]; memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_PICMG; req.msg.cmd = PICMG_SET_FRU_LED_STATE_CMD; req.msg.data = msg_data; req.msg.data_len = 6; msg_data[0] = 0x00; /* PICMG identifier */ msg_data[1] = atob(argv[0]); /* FRU-ID */ msg_data[2] = atob(argv[1]); /* LED-ID */ msg_data[3] = atob(argv[2]); /* LED function */ msg_data[4] = atob(argv[3]); /* LED on duration */ msg_data[5] = atob(argv[4]); /* LED color */ rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv) { if (rv < 0) printf("no response\n"); else printf("returned Completion Code 0x%02x\n", rv); return rv; } return 0; } int ipmi_picmg_get_power_level(void * intf, int argc, char ** argv) { int i; uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv; struct ipmi_rq req; unsigned char msg_data[6]; memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_PICMG; req.msg.cmd = PICMG_GET_POWER_LEVEL_CMD; req.msg.data = msg_data; req.msg.data_len = 3; msg_data[0] = 0x00; /* PICMG identifier */ msg_data[1] = atob(argv[0]); /* FRU-ID */ msg_data[2] = atob(argv[1]); /* Power type */ rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv) { if (rv < 0) printf("no response\n"); else printf("returned Completion Code 0x%02x\n", rv); return rv; } printf("Dynamic Power Configuration: %s\n", (rsp[1]&0x80)==0x80?"enabled":"disabled" ); printf("Actual Power Level: %i\n", (rsp[1] & 0xf)); printf("Delay to stable Power: %i\n", rsp[2]); printf("Power Multiplier: %i\n", rsp[3]); for ( i = 1; i+3 < rsp_len ; i++ ) { printf(" Power Draw %i: %i\n", i, (rsp[i+3]) * rsp[3] / 10); } return 0; } int ipmi_picmg_set_power_level(void * intf, int argc, char ** argv) { // int i; uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv; struct ipmi_rq req; unsigned char msg_data[6]; memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_PICMG; req.msg.cmd = PICMG_SET_POWER_LEVEL_CMD; req.msg.data = msg_data; req.msg.data_len = 4; msg_data[0] = 0x00; /* PICMG identifier */ msg_data[1] = atob(argv[0]); /* FRU-ID */ msg_data[2] = atob(argv[1]); /* power level */ msg_data[3] = atob(argv[2]); /* present to desired */ rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv) { if (rv < 0) printf("no response\n"); else printf("returned Completion Code 0x%02x\n", rv); return rv; } return 0; } int ipmi_picmg_bused_resource(void * intf, t_picmg_bused_resource_mode mode) { uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv; struct ipmi_rq req; unsigned char msg_data[6]; memset(&req, 0, sizeof(req)); switch ( mode ) { case PICMG_BUSED_RESOURCE_SUMMARY: { t_picmg_busres_resource_id resource; t_picmg_busres_board_cmd_types cmd =PICMG_BUSRES_BOARD_CMD_QUERY; req.msg.netfn = IPMI_NETFN_PICMG; req.msg.cmd = PICMG_BUSED_RESOURCE_CMD; req.msg.data = msg_data; req.msg.data_len = 3; /* IF BOARD query for all resources */ for( resource=PICMG_BUSRES_METAL_TEST_BUS_1;resource<=PICMG_BUSRES_SYNC_CLOCK_GROUP_3;resource+=(t_picmg_busres_resource_id)1 ) { msg_data[0] = 0x00; /* PICMG identifier */ msg_data[1] = (unsigned char) cmd; msg_data[2] = (unsigned char) resource; rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv) { if (rv < 0) printf("bused resource control: no response\n"); else printf("bused resource control: returned Completion Code 0x%02x\n",rv); return rv; } else { printf("Resource 0x%02x '%-26s' : 0x%02x [%s] \n" , resource, val2str(resource,picmg_busres_id_vals), rsp[1], oemval2str(cmd,rsp[1], picmg_busres_board_status_vals)); } } } break; default: rv = -1; break; } return rv; } int ipmi_picmg_fru_control(void * intf, int argc, char ** argv) { uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv; struct ipmi_rq req; unsigned char msg_data[6]; memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_PICMG; req.msg.cmd = PICMG_FRU_CONTROL_CMD; req.msg.data = msg_data; req.msg.data_len = 3; msg_data[0] = 0x00; /* PICMG identifier */ msg_data[1] = atob(argv[0]); /* FRU-ID */ msg_data[2] = atob(argv[1]); /* control option */ printf("FRU Device Id: %d FRU Control Option: %s\n\r", msg_data[1], \ val2str( msg_data[2], picmg_frucontrol_vals)); rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv) { if (rv < 0) printf("frucontrol: no response\n"); else printf("frucontrol: returned Completion Code 0x%02x\n",rv); return rv; } else { printf("frucontrol: ok\n"); } return 0; } int ipmi_picmg_clk_get(void * intf, int clk_id,int clk_res,int mode) { // int i; uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv; struct ipmi_rq req; unsigned char enabled; unsigned char direction; unsigned char msg_data[6]; memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_PICMG; req.msg.cmd = PICMG_AMC_GET_CLK_STATE_CMD; req.msg.data = msg_data; msg_data[0] = 0x00; /* PICMG identifier */ msg_data[1] = clk_id; if(clk_res == -1 || PicmgCardType != PICMG_CARD_TYPE_ATCA ){ req.msg.data_len = 2; /* for amc only channel */ }else{ req.msg.data_len = 3; /* for carrier channel and device */ msg_data[2] = clk_res; } rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv) { if (rv < 0) printf("no response\n"); else printf("returned Completion Code 0x%02x\n", rv); return rv; } { enabled = (rsp[1]&0x8)!=0; direction = (rsp[1]&0x4)!=0; if ( mode == PICMG_EKEY_MODE_QUERY || mode == PICMG_EKEY_MODE_PRINT_ALL || ( mode == PICMG_EKEY_MODE_PRINT_DISABLED && enabled == 0 ) || ( mode == PICMG_EKEY_MODE_PRINT_ENABLED && enabled == 1 ) ) { if( PicmgCardType != PICMG_CARD_TYPE_AMC ) { printf("CLK resource id : %3d [ %s ]\n", clk_res , oemval2str( ((clk_res>>6)&0x03), (clk_res&0x0F), picmg_clk_resource_vals)); } else { printf("CLK resource id : N/A [ AMC Module ]\n"); clk_res = 0x40; /* Set */ } printf("CLK id : %3d [ %s ]\n", clk_id, oemval2str( ((clk_res>>6)&0x03), clk_id , picmg_clk_id_vals)); printf("CLK setting : 0x%02x\n", rsp[1]); printf(" - state: %s\n", (enabled)?"enabled":"disabled"); printf(" - direction: %s\n", (direction)?"Source":"Receiver"); printf(" - PLL ctrl: 0x%x\n", rsp[1]&0x3); if(enabled){ unsigned long freq = 0; freq = ( rsp[5] << 0 | rsp[6] << 8 | rsp[7] << 16 | rsp[8] << 24 ); printf(" - Index: %3d\n", rsp[2]); printf(" - Family: %3d [ %s ]\n", rsp[3], val2str( rsp[3], picmg_clk_family_vals)); printf(" - AccLVL: %3d [ %s ]\n", rsp[4], oemval2str(rsp[3],rsp[4],picmg_clk_accuracy_vals)); printf(" - Freq: %lu\n", freq); } } } return 0; } int ipmi_picmg_clk_set(void * intf, int argc, char ** argv) { // int i; uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv; struct ipmi_rq req; unsigned char msg_data[11]; unsigned long freq=0; memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_PICMG; req.msg.cmd = PICMG_AMC_SET_CLK_STATE_CMD; req.msg.data = msg_data; msg_data[0] = 0x00; /* PICMG identifier */ msg_data[1] = (uchar)strtoul(argv[0], NULL,0); /* clk id */ msg_data[2] = (uchar)strtoul(argv[1], NULL,0); /* clk index */ msg_data[3] = (uchar)strtoul(argv[2], NULL,0); /* setting */ msg_data[4] = (uchar)strtoul(argv[3], NULL,0); /* family */ msg_data[5] = (uchar)strtoul(argv[4], NULL,0); /* acc */ freq = strtoul(argv[5], NULL,0); msg_data[6] = (uchar)((freq >> 0)& 0xFF); /* freq */ msg_data[7] = (uchar)((freq >> 8)& 0xFF); /* freq */ msg_data[8] = (uchar)((freq >>16)& 0xFF); /* freq */ msg_data[9] = (uchar)((freq >>24)& 0xFF); /* freq */ req.msg.data_len = 10; if( PicmgCardType == PICMG_CARD_TYPE_ATCA ) { if( argc > 7) { req.msg.data_len = 11; msg_data[10] = (uchar)strtoul(argv[6], NULL,0); /* resource id */ } else { printf("missing resource id for atca board\n"); return -1; } } #if 1 printf("## ID: %d\n", msg_data[1]); printf("## index: %d\n", msg_data[2]); printf("## setting: 0x%02x\n", msg_data[3]); printf("## family: %d\n", msg_data[4]); printf("## acc: %d\n", msg_data[5]); printf("## freq: %lu\n", freq ); printf("## res: %d\n", msg_data[10]); #endif rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv) { if (rv < 0) printf("no response\n"); else printf("returned Completion Code 0x%02x\n", rv); return rv; } return 0; } #ifdef METACOMMAND int i_picmg(int argc, char **argv) #else #ifdef WIN32 int __cdecl #else int #endif main(int argc, char **argv) #endif { int rc = 0; int showProperties = 0; void *intf = NULL; int c, i; char *s1; printf("%s ver %s\n", progname,progver); while ( (c = getopt( argc, argv,"m:i:T:V:J:EYF:P:N:R:U:Z:x?")) != EOF) switch (c) { case 'm': /* specific IPMB MC, 3-byte address, e.g. "409600" */ g_bus = htoi(&optarg[0]); /*bus/channel*/ g_sa = htoi(&optarg[2]); /*device slave address*/ g_lun = htoi(&optarg[4]); /*LUN*/ g_addrtype = ADDR_IPMB; if (optarg[6] == 's') { g_addrtype = ADDR_SMI; s1 = "SMI"; } else { g_addrtype = ADDR_IPMB; s1 = "IPMB"; } fset_mc = 1; ipmi_set_mc(g_bus,g_sa,g_lun,g_addrtype); printf("Use MC at %s bus=%x sa=%x lun=%x\n", s1,g_bus,g_sa,g_lun); break; case 'i': /*specify a fru id*/ if (strncmp(optarg,"0x",2) == 0) g_fruid = htoi(&optarg[2]); else g_fruid = htoi(optarg); printf("Using FRU ID 0x%02x\n",g_fruid); break; case 'x': fdebug = 1; break; /* debug messages */ case 'N': /* nodename */ case 'U': /* remote username */ case 'P': /* remote password */ case 'R': /* remote password */ case 'E': /* get password from IPMI_PASSWORD environment var */ case 'F': /* force driver type */ case 'T': /* auth type */ case 'J': /* cipher suite */ case 'V': /* priv level */ case 'Y': /* prompt for remote password */ case 'Z': /* set local MC address */ parse_lan_options(c,optarg,fdebug); break; case '?': ipmi_picmg_help(); return ERR_USAGE; break; } for (i = 0; i < optind; i++) { argv++; argc--; } /* Get PICMG properties is called to obtain version information */ if (argc !=0 && !strncmp(argv[0], "properties", 10)) { showProperties =1; } if (argc == 0 || (!strncmp(argv[0], "help", 4))) { ipmi_picmg_help(); return ERR_USAGE; } rc = ipmi_picmg_properties(intf,showProperties); if (rc < 0) { /*cannot contact MC, so exit*/ goto do_exit; } /* address info command */ else if (!strncmp(argv[0], "addrinfo", 8)) { rc = ipmi_picmg_getaddr(intf, argc-1, &argv[1]); } else if (!strncmp(argv[0], "busres", 6)) { if (argc > 1) { if (!strncmp(argv[1], "summary", 7)) { ipmi_picmg_bused_resource(intf, PICMG_BUSED_RESOURCE_SUMMARY ); } } else { printf("usage: busres summary\n"); } } /* fru control command */ else if (!strncmp(argv[0], "frucontrol", 10)) { if (argc > 2) { rc = ipmi_picmg_fru_control(intf, argc-1, &(argv[1])); } else { printf("usage: frucontrol