xref: /openbmc/ipmitool/lib/ipmi_dcmi.c (revision 2d79e69f)
1c18ec02fSPetter Reinholdtsen /*
2c18ec02fSPetter Reinholdtsen  * Copyright (C) 2008 Intel Corporation.
3c18ec02fSPetter Reinholdtsen  * All rights reserved
4c18ec02fSPetter Reinholdtsen  *
5c18ec02fSPetter Reinholdtsen  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
6c18ec02fSPetter Reinholdtsen  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
7c18ec02fSPetter Reinholdtsen  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
8c18ec02fSPetter Reinholdtsen  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
9c18ec02fSPetter Reinholdtsen  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
10c18ec02fSPetter Reinholdtsen  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
11c18ec02fSPetter Reinholdtsen  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
12c18ec02fSPetter Reinholdtsen  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
13c18ec02fSPetter Reinholdtsen  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
14c18ec02fSPetter Reinholdtsen  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
15c18ec02fSPetter Reinholdtsen  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
16c18ec02fSPetter Reinholdtsen  *
17c18ec02fSPetter Reinholdtsen  */
18c18ec02fSPetter Reinholdtsen 
19c18ec02fSPetter Reinholdtsen /* Theory of operation
20c18ec02fSPetter Reinholdtsen  *
21c18ec02fSPetter Reinholdtsen  * DCMI is the Data Center Management Interface which is a subset of IPMI v2.0.
22c18ec02fSPetter Reinholdtsen  * DCMI incorporates the ability to locate a system with DCMI functionality,
23c18ec02fSPetter Reinholdtsen  * its available temperature sensors, and power limiting control.
24c18ec02fSPetter Reinholdtsen  *
25c18ec02fSPetter Reinholdtsen  * All of the available DCMI commands are contained in a struct with a numeric
26c18ec02fSPetter Reinholdtsen  * value and a string.  When the user specifies a command the string is
27c18ec02fSPetter Reinholdtsen  * compared to one of several structs and is then given a numeric value based
28c18ec02fSPetter Reinholdtsen  * on the matched string.  A case statement is used to select the desired
29c18ec02fSPetter Reinholdtsen  * action from the user.  If an invalid string is entered, or a string that is
30c18ec02fSPetter Reinholdtsen  * not a command option is entered, the available commands are printed to the
31c18ec02fSPetter Reinholdtsen  * screen.  This allows the strings to be changed quickly with the DCMI spec.
32c18ec02fSPetter Reinholdtsen  *
33c18ec02fSPetter Reinholdtsen  * Each called function usually executes whichever command was requested to
34c18ec02fSPetter Reinholdtsen  * keep the main() from being overly complicated.
35c18ec02fSPetter Reinholdtsen  *
36c18ec02fSPetter Reinholdtsen  * This code conforms to the 1.0 DCMI Specification
37c18ec02fSPetter Reinholdtsen  *  released by Hari Ramachandran of the Intel Corporation
38c18ec02fSPetter Reinholdtsen  */
39c18ec02fSPetter Reinholdtsen 
40c18ec02fSPetter Reinholdtsen #include <stdlib.h>
41c18ec02fSPetter Reinholdtsen #include <string.h>
42c18ec02fSPetter Reinholdtsen #include <stdio.h>
43c18ec02fSPetter Reinholdtsen #include <math.h>
44c18ec02fSPetter Reinholdtsen #include <unistd.h>
45c18ec02fSPetter Reinholdtsen #include <sys/types.h>
46c18ec02fSPetter Reinholdtsen #include <time.h>
47c18ec02fSPetter Reinholdtsen #include <netdb.h>
48c18ec02fSPetter Reinholdtsen 
49c18ec02fSPetter Reinholdtsen #include <ipmitool/ipmi_dcmi.h>
50c18ec02fSPetter Reinholdtsen #include <ipmitool/helper.h>
51c18ec02fSPetter Reinholdtsen #include <ipmitool/ipmi.h>
52c18ec02fSPetter Reinholdtsen #include <ipmitool/log.h>
53c18ec02fSPetter Reinholdtsen #include <ipmitool/ipmi_intf.h>
54c18ec02fSPetter Reinholdtsen #include <ipmitool/ipmi_strings.h>
55c18ec02fSPetter Reinholdtsen #include <ipmitool/ipmi_mc.h>
56c18ec02fSPetter Reinholdtsen #include <ipmitool/ipmi_entity.h>
57c18ec02fSPetter Reinholdtsen #include <ipmitool/ipmi_constants.h>
58c18ec02fSPetter Reinholdtsen #include <ipmitool/ipmi_sensor.h>
59c18ec02fSPetter Reinholdtsen 
60c18ec02fSPetter Reinholdtsen #include "../src/plugins/lanplus/lanplus.h"
61c18ec02fSPetter Reinholdtsen 
62c18ec02fSPetter Reinholdtsen #define IPMI_LAN_PORT       0x26f
63c18ec02fSPetter Reinholdtsen 
64c18ec02fSPetter Reinholdtsen extern int verbose;
65fd5fdc59SPat Donlin extern int csv_output;
66c18ec02fSPetter Reinholdtsen static int ipmi_print_sensor_info(struct ipmi_intf *intf, uint16_t rec_id);
67c18ec02fSPetter Reinholdtsen 
68c18ec02fSPetter Reinholdtsen /*******************************************************************************
69c18ec02fSPetter Reinholdtsen  * The structs below are the DCMI command option strings.  They are printed    *
70c18ec02fSPetter Reinholdtsen  * when the user does not issue enough options or the wrong ones.  The reason  *
71c18ec02fSPetter Reinholdtsen  * that the DMCI command strings are in a struct is so that when the           *
72c18ec02fSPetter Reinholdtsen  * specification changes, the strings can be changed quickly with out having   *
73c18ec02fSPetter Reinholdtsen  * to change a lot of the code in the main().                                  *
74c18ec02fSPetter Reinholdtsen  ******************************************************************************/
75c18ec02fSPetter Reinholdtsen 
76c18ec02fSPetter Reinholdtsen /* Main set of DCMI commands */
77c18ec02fSPetter Reinholdtsen const struct dcmi_cmd dcmi_cmd_vals[] = {
78c18ec02fSPetter Reinholdtsen 	{ 0x00, "discover", "           Used to discover supported DCMI capabilities" },
79c18ec02fSPetter Reinholdtsen 	{ 0x01, "power", "              Platform power limit command options"         },
80c18ec02fSPetter Reinholdtsen 	{ 0x02, "sensors", "            Prints the available DCMI sensors"            },
81c18ec02fSPetter Reinholdtsen 	{ 0x03, "asset_tag", "          Prints the platform's asset tag"              },
82c18ec02fSPetter Reinholdtsen 	{ 0x04, "set_asset_tag", "      Sets the platform's asset tag"                },
83c18ec02fSPetter Reinholdtsen 	{ 0x05, "get_mc_id_string", "   Get management controller ID string"          },
84c18ec02fSPetter Reinholdtsen 	{ 0x06, "set_mc_id_string", "   Set management controller ID string"          },
85c18ec02fSPetter Reinholdtsen 	{ 0x07, "thermalpolicy", "      Thermal policy get/set"                       },
86c18ec02fSPetter Reinholdtsen 	{ 0x08, "get_temp_reading", "   Get Temperature Readings"                     },
87c18ec02fSPetter Reinholdtsen 	{ 0x09, "get_conf_param", "     Get DCMI Config Parameters"                   },
88c18ec02fSPetter Reinholdtsen 	{ 0x0A, "set_conf_param", "     Set DCMI Config Parameters"                   },
89c18ec02fSPetter Reinholdtsen 	{ 0x0B, "oob_discover", "       Ping/Pong Message for DCMI Discovery"         },
90c18ec02fSPetter Reinholdtsen 	{ 0xFF, NULL, NULL                                                        }
91c18ec02fSPetter Reinholdtsen };
92c18ec02fSPetter Reinholdtsen 
93c18ec02fSPetter Reinholdtsen /* get capabilites */
94c18ec02fSPetter Reinholdtsen const struct dcmi_cmd dcmi_capable_vals[] = {
95c18ec02fSPetter Reinholdtsen 	{ 0x01, "platform", "            Lists the system capabilities" },
96c18ec02fSPetter Reinholdtsen 	{ 0x02, "mandatory_attributes", "Lists SEL, identification and"
97c18ec02fSPetter Reinholdtsen 		"temperature attributes"                                    },
98c18ec02fSPetter Reinholdtsen 	{ 0x03, "optional_attributes", " Lists power capabilities"      },
99c18ec02fSPetter Reinholdtsen 	{ 0x04, "managebility access", " Lists OOB channel information" },
100c18ec02fSPetter Reinholdtsen 	{ 0xFF, NULL, NULL                                              }
101c18ec02fSPetter Reinholdtsen };
102c18ec02fSPetter Reinholdtsen 
103c18ec02fSPetter Reinholdtsen /* platform capabilities
104c18ec02fSPetter Reinholdtsen  * Since they are actually in two bytes, we need three structs to make this
105c18ec02fSPetter Reinholdtsen  * human readable...
106c18ec02fSPetter Reinholdtsen  */
107c18ec02fSPetter Reinholdtsen const struct dcmi_cmd dcmi_mandatory_platform_capabilities[] = {
108c18ec02fSPetter Reinholdtsen 	{ 0x01, "Identification support available", "" },
109c18ec02fSPetter Reinholdtsen 	{ 0x02, "SEL logging available", ""            },
110c18ec02fSPetter Reinholdtsen 	{ 0x03, "Chassis power available", ""          },
111c18ec02fSPetter Reinholdtsen 	{ 0x04, "Temperature monitor available", ""  },
112c18ec02fSPetter Reinholdtsen 	{ 0xFF, NULL, NULL                   }
113c18ec02fSPetter Reinholdtsen };
114c18ec02fSPetter Reinholdtsen 
115c18ec02fSPetter Reinholdtsen /* optional capabilities */
116c18ec02fSPetter Reinholdtsen const struct dcmi_cmd dcmi_optional_platform_capabilities[] = {
117c18ec02fSPetter Reinholdtsen 	{ 0x01, "Power management available", ""       },
118c18ec02fSPetter Reinholdtsen 	{ 0xFF, NULL, NULL                   }
119c18ec02fSPetter Reinholdtsen };
120c18ec02fSPetter Reinholdtsen 
121c18ec02fSPetter Reinholdtsen /* access capabilties */
122c18ec02fSPetter Reinholdtsen const struct dcmi_cmd dcmi_management_access_capabilities[] = {
123c18ec02fSPetter Reinholdtsen 	{ 0x01, "In-band KCS channel available", ""               },
124c18ec02fSPetter Reinholdtsen 	{ 0x02, "Out-of-band serial TMODE available", ""          },
125c18ec02fSPetter Reinholdtsen 	{ 0x03, "Out-of-band secondary LAN channel available", "" },
126c18ec02fSPetter Reinholdtsen 	{ 0x04, "Out-of-band primary LAN channel available", ""   },
127c18ec02fSPetter Reinholdtsen 	{ 0x05, "SOL enabled", ""                       },
128c18ec02fSPetter Reinholdtsen 	{ 0x06, "VLAN capable", ""      },
129c18ec02fSPetter Reinholdtsen 	{ 0xFF, NULL, NULL                              }
130c18ec02fSPetter Reinholdtsen };
131c18ec02fSPetter Reinholdtsen 
132c18ec02fSPetter Reinholdtsen /* identification capabilities */
133c18ec02fSPetter Reinholdtsen const struct dcmi_cmd dcmi_id_capabilities_vals[] = {
134c18ec02fSPetter Reinholdtsen 	{ 0x01, "GUID", ""          },
135c18ec02fSPetter Reinholdtsen 	{ 0x02, "DHCP hostname", "" },
136c18ec02fSPetter Reinholdtsen 	{ 0x03, "Asset tag", ""    },
137c18ec02fSPetter Reinholdtsen 	{ 0xFF, NULL, NULL          }
138c18ec02fSPetter Reinholdtsen };
139c18ec02fSPetter Reinholdtsen 
140c18ec02fSPetter Reinholdtsen /* Configuration parameters*/
141c18ec02fSPetter Reinholdtsen const struct dcmi_cmd dcmi_conf_param_vals[] = {
142c18ec02fSPetter Reinholdtsen 	{ 0x01, "activate_dhcp",   "\tActivate DHCP"},
143c18ec02fSPetter Reinholdtsen 	{ 0x02, "dhcp_config",     "\tDHCP Configuration" },
144c18ec02fSPetter Reinholdtsen 	{ 0x03, "init",            "\t\tInitial timeout interval"  },
145c18ec02fSPetter Reinholdtsen 	{ 0x04, "timeout",         "\t\tServer contact timeout interval"  },
146c18ec02fSPetter Reinholdtsen 	{ 0x05, "retry",           "\t\tServer contact retry interval"  },
147c18ec02fSPetter Reinholdtsen 	{ 0xFF, NULL, NULL          }
148c18ec02fSPetter Reinholdtsen };
149c18ec02fSPetter Reinholdtsen 
150c18ec02fSPetter Reinholdtsen 
151c18ec02fSPetter Reinholdtsen /* temperature monitoring capabilities */
152c18ec02fSPetter Reinholdtsen const struct dcmi_cmd dcmi_temp_monitoring_vals[] = {
153c18ec02fSPetter Reinholdtsen 	{ 0x01, "inlet", "    Inlet air temperature sensors"  },
154c18ec02fSPetter Reinholdtsen 	{ 0x02, "cpu", "      CPU temperature sensors"        },
155c18ec02fSPetter Reinholdtsen 	{ 0x03, "baseboard", "Baseboard temperature sensors"  },
156c18ec02fSPetter Reinholdtsen 	{ 0xff, NULL, NULL                                    }
157c18ec02fSPetter Reinholdtsen };
158c18ec02fSPetter Reinholdtsen 
159c18ec02fSPetter Reinholdtsen /* These are not comands.  These are the DCMI temp sensors and their numbers
160c18ec02fSPetter Reinholdtsen  * If new sensors are added, they need to be added to this list with their
161c18ec02fSPetter Reinholdtsen  * sensor number
162c18ec02fSPetter Reinholdtsen  */
163c18ec02fSPetter Reinholdtsen const struct dcmi_cmd dcmi_discvry_snsr_vals[] = {
164c18ec02fSPetter Reinholdtsen 	{ 0x40, "Inlet", "    Inlet air temperature sensors"  },
165c18ec02fSPetter Reinholdtsen 	{ 0x41, "CPU", "      CPU temperature sensors"        },
166c18ec02fSPetter Reinholdtsen 	{ 0x42, "Baseboard", "Baseboard temperature sensors"  },
167c18ec02fSPetter Reinholdtsen 	{ 0xff, NULL, NULL                                    }
168c18ec02fSPetter Reinholdtsen };
169c18ec02fSPetter Reinholdtsen 
170c18ec02fSPetter Reinholdtsen /* Temperature Readings */
171c18ec02fSPetter Reinholdtsen const struct dcmi_cmd dcmi_temp_read_vals[] = {
172c18ec02fSPetter Reinholdtsen 	{ 0x40, "Inlet",        "Inlet air temperature(40h)         " },
173c18ec02fSPetter Reinholdtsen 	{ 0x41, "CPU",          "CPU temperature sensors(41h)       " },
174c18ec02fSPetter Reinholdtsen 	{ 0x42, "Baseboard",    "Baseboard temperature sensors(42h) " },
175c18ec02fSPetter Reinholdtsen 	{ 0xff, NULL, NULL                                    }
176c18ec02fSPetter Reinholdtsen };
177c18ec02fSPetter Reinholdtsen 
178c18ec02fSPetter Reinholdtsen /* power management/control commands */
179c18ec02fSPetter Reinholdtsen const struct dcmi_cmd dcmi_pwrmgmt_vals[] = {
180c18ec02fSPetter Reinholdtsen 	{ 0x00, "reading", "   Get power related readings from the system" },
181c18ec02fSPetter Reinholdtsen 	{ 0x01, "get_limit", " Get the configured power limits"            },
182c18ec02fSPetter Reinholdtsen 	{ 0x02, "set_limit", " Set a power limit option"                   },
183c18ec02fSPetter Reinholdtsen 	{ 0x03, "activate", "  Activate the set power limit"               },
184c18ec02fSPetter Reinholdtsen 	{ 0x04, "deactivate", "Deactivate the set power limit"             },
185c18ec02fSPetter Reinholdtsen 	{ 0xFF, NULL, NULL                                                 }
186c18ec02fSPetter Reinholdtsen };
187c18ec02fSPetter Reinholdtsen 
188c18ec02fSPetter Reinholdtsen /* set power limit commands */
189c18ec02fSPetter Reinholdtsen const struct dcmi_cmd dcmi_pwrmgmt_set_usage_vals[] = {
19042aba7ebSZdenek Styblik 	{ 0x00, "action", "    <no_action | sel_logging | power_off>" },
191c18ec02fSPetter Reinholdtsen 	{ 0x01, "limit", "     <number in Watts>" },
192c18ec02fSPetter Reinholdtsen 	{ 0x02, "correction", "<number in milliseconds>" },
193c18ec02fSPetter Reinholdtsen 	{ 0x03, "sample", "    <number in seconds>" },
194c18ec02fSPetter Reinholdtsen 	{ 0xFF, NULL, NULL }
195c18ec02fSPetter Reinholdtsen };
196c18ec02fSPetter Reinholdtsen 
19742aba7ebSZdenek Styblik /* power management/get action commands */
19842aba7ebSZdenek Styblik const struct dcmi_cmd dcmi_pwrmgmt_get_action_vals[] = {
199c18ec02fSPetter Reinholdtsen 	{ 0x00, "No Action", ""},
200c18ec02fSPetter Reinholdtsen 	{ 0x01, "Hard Power Off & Log Event to SEL", ""},
20142aba7ebSZdenek Styblik 
20242aba7ebSZdenek Styblik 	{ 0x02, "OEM reserved (02h)", ""},
20342aba7ebSZdenek Styblik 	{ 0x03, "OEM reserved (03h)", ""},
20442aba7ebSZdenek Styblik 	{ 0x04, "OEM reserved (04h)", ""},
20542aba7ebSZdenek Styblik 	{ 0x05, "OEM reserved (05h)", ""},
20642aba7ebSZdenek Styblik 	{ 0x06, "OEM reserved (06h)", ""},
20742aba7ebSZdenek Styblik 	{ 0x07, "OEM reserved (07h)", ""},
20842aba7ebSZdenek Styblik 	{ 0x08, "OEM reserved (08h)", ""},
20942aba7ebSZdenek Styblik 	{ 0x09, "OEM reserved (09h)", ""},
21042aba7ebSZdenek Styblik 	{ 0x0a, "OEM reserved (0ah)", ""},
21142aba7ebSZdenek Styblik 	{ 0x0b, "OEM reserved (0bh)", ""},
21242aba7ebSZdenek Styblik 	{ 0x0c, "OEM reserved (0ch)", ""},
21342aba7ebSZdenek Styblik 	{ 0x0d, "OEM reserved (0dh)", ""},
21442aba7ebSZdenek Styblik 	{ 0x0e, "OEM reserved (0eh)", ""},
21542aba7ebSZdenek Styblik 	{ 0x0f, "OEM reserved (0fh)", ""},
21642aba7ebSZdenek Styblik 	{ 0x10, "OEM reserved (10h)", ""},
21742aba7ebSZdenek Styblik 
218c18ec02fSPetter Reinholdtsen 	{ 0x11, "Log Event to SEL", ""},
219c18ec02fSPetter Reinholdtsen 	{ 0xFF, NULL, NULL      }
220c18ec02fSPetter Reinholdtsen };
221c18ec02fSPetter Reinholdtsen 
22242aba7ebSZdenek Styblik /* power management/set action commands */
22342aba7ebSZdenek Styblik const struct dcmi_cmd dcmi_pwrmgmt_action_vals[] = {
22442aba7ebSZdenek Styblik 	{ 0x00, "no_action",   "No Action"},
22542aba7ebSZdenek Styblik 	{ 0x01, "power_off",   "Hard Power Off & Log Event to SEL"},
22642aba7ebSZdenek Styblik 	{ 0x11, "sel_logging", "Log Event to SEL"},
22742aba7ebSZdenek Styblik 
22842aba7ebSZdenek Styblik 	{ 0x02, "oem_02", "OEM reserved (02h)"},
22942aba7ebSZdenek Styblik 	{ 0x03, "oem_03", "OEM reserved (03h)"},
23042aba7ebSZdenek Styblik 	{ 0x04, "oem_04", "OEM reserved (04h)"},
23142aba7ebSZdenek Styblik 	{ 0x05, "oem_05", "OEM reserved (05h)"},
23242aba7ebSZdenek Styblik 	{ 0x06, "oem_06", "OEM reserved (06h)"},
23342aba7ebSZdenek Styblik 	{ 0x07, "oem_07", "OEM reserved (07h)"},
23442aba7ebSZdenek Styblik 	{ 0x08, "oem_08", "OEM reserved (08h)"},
23542aba7ebSZdenek Styblik 	{ 0x09, "oem_09", "OEM reserved (09h)"},
23642aba7ebSZdenek Styblik 	{ 0x0a, "oem_0a", "OEM reserved (0ah)"},
23742aba7ebSZdenek Styblik 	{ 0x0b, "oem_0b", "OEM reserved (0bh)"},
23842aba7ebSZdenek Styblik 	{ 0x0c, "oem_0c", "OEM reserved (0ch)"},
23942aba7ebSZdenek Styblik 	{ 0x0d, "oem_0d", "OEM reserved (0dh)"},
24042aba7ebSZdenek Styblik 	{ 0x0e, "oem_0e", "OEM reserved (0eh)"},
24142aba7ebSZdenek Styblik 	{ 0x0f, "oem_0f", "OEM reserved (0fh)"},
24242aba7ebSZdenek Styblik 	{ 0x10, "oem_10", "OEM reserved (10h)"},
24342aba7ebSZdenek Styblik 
24442aba7ebSZdenek Styblik 	{ 0xFF, NULL, NULL      }
24542aba7ebSZdenek Styblik };
24642aba7ebSZdenek Styblik 
247c18ec02fSPetter Reinholdtsen /* thermal policy action commands */
248c18ec02fSPetter Reinholdtsen const struct dcmi_cmd dcmi_thermalpolicy_vals[] = {
249c18ec02fSPetter Reinholdtsen 	{ 0x00, "get", "Get thermal policy"  },
250c18ec02fSPetter Reinholdtsen 	{ 0x01, "set", "Set thermal policy"  },
251c18ec02fSPetter Reinholdtsen 	{ 0xFF, NULL, NULL      }
252c18ec02fSPetter Reinholdtsen };
253c18ec02fSPetter Reinholdtsen 
254c18ec02fSPetter Reinholdtsen /* thermal policy action commands */
255c18ec02fSPetter Reinholdtsen const struct dcmi_cmd dcmi_confparameters_vals[] = {
256c18ec02fSPetter Reinholdtsen 	{ 0x00, "get", "Get configuration parameters"  },
257c18ec02fSPetter Reinholdtsen 	{ 0x01, "set", "Set configuration parameters"  },
258c18ec02fSPetter Reinholdtsen 	{ 0xFF, NULL, NULL      }
259c18ec02fSPetter Reinholdtsen };
260c18ec02fSPetter Reinholdtsen 
261c18ec02fSPetter Reinholdtsen /* entityIDs used in thermap policy */
262c18ec02fSPetter Reinholdtsen const struct dcmi_cmd dcmi_thermalpolicy_set_parameters_vals[] = {
263c18ec02fSPetter Reinholdtsen 	{ 0x00, "volatile", "   Current Power Cycle"        },
264c18ec02fSPetter Reinholdtsen 	{ 0x01, "nonvolatile", "Set across power cycles"        },
265c18ec02fSPetter Reinholdtsen 	{ 0x01, "poweroff", "   Hard Power Off system"          },
266c18ec02fSPetter Reinholdtsen 	{ 0x00, "nopoweroff", " No 'Hard Power Off' action"         },
267c18ec02fSPetter Reinholdtsen 	{ 0x01, "sel", "        Log event to SEL"   },
268c18ec02fSPetter Reinholdtsen 	{ 0x00, "nosel", "      No 'Log event to SEL' action"   },
269c18ec02fSPetter Reinholdtsen 	{ 0x00, "disabled", "   Disabled"   },
270c18ec02fSPetter Reinholdtsen 	{ 0x00, NULL,    NULL                   }
271c18ec02fSPetter Reinholdtsen };
272c18ec02fSPetter Reinholdtsen 
273c18ec02fSPetter Reinholdtsen 
274c18ec02fSPetter Reinholdtsen /* DCMI command specific completion code results per 1.0 spec
275c18ec02fSPetter Reinholdtsen  * 80h - parameter not supported.
276c18ec02fSPetter Reinholdtsen  * 81h - attempt to set the ‘set in progress’ value (in parameter #0) when not
277c18ec02fSPetter Reinholdtsen  *       in the ‘set complete’ state. (This completion code provides a way to
278c18ec02fSPetter Reinholdtsen  *       recognize that another party has already ‘claimed’ the parameters)
279c18ec02fSPetter Reinholdtsen  * 82h - attempt to write read-only parameter
280c18ec02fSPetter Reinholdtsen  * 82h - set not supported on selected channel (e.g. channel is session-less.)
281c18ec02fSPetter Reinholdtsen  * 83h - access mode not supported
282c18ec02fSPetter Reinholdtsen  * 84h – Power Limit out of range
283c18ec02fSPetter Reinholdtsen  * 85h – Correction Time out of range
284c18ec02fSPetter Reinholdtsen  * 89h – Statistics Reporting Period out of range
285c18ec02fSPetter Reinholdtsen  */
286c18ec02fSPetter Reinholdtsen const struct valstr dcmi_ccode_vals[] = {
287c18ec02fSPetter Reinholdtsen 	{ 0x80, "Parameter not supported" },
288c18ec02fSPetter Reinholdtsen 	{ 0x81, "Something else has already claimed these parameters" },
289c18ec02fSPetter Reinholdtsen 	{ 0x82, "Not supported or failed to write a read-only parameter" },
290c18ec02fSPetter Reinholdtsen 	{ 0x83, "Access mode is not supported" },
291c18ec02fSPetter Reinholdtsen 	{ 0x84, "Power/Thermal limit out of range" },
292c18ec02fSPetter Reinholdtsen 	{ 0x85, "Correction/Exception time out of range" },
293c18ec02fSPetter Reinholdtsen 	{ 0x89, "Sample/Statistics Reporting period out of range" },
294c18ec02fSPetter Reinholdtsen 	{ 0x8A, "Power limit already active" },
295c18ec02fSPetter Reinholdtsen 	{ 0xFF, NULL }
296c18ec02fSPetter Reinholdtsen };
297c18ec02fSPetter Reinholdtsen 
298fd5fdc59SPat Donlin /*
299fd5fdc59SPat Donlin  * Start of Node Manager Operations
300fd5fdc59SPat Donlin  */
301fd5fdc59SPat Donlin 
302fd5fdc59SPat Donlin const struct dcmi_cmd dcmi_sampling_vals[] = {
303fd5fdc59SPat Donlin 	{ 0x05, "5_sec", "" },
304fd5fdc59SPat Donlin 	{ 0x0f, "15_sec", "" },
305fd5fdc59SPat Donlin 	{ 0x1E, "30_sec", "" },
306fd5fdc59SPat Donlin 	{ 0x41, "1_min", "" },
307fd5fdc59SPat Donlin 	{ 0x43, "3_min", "" },
308fd5fdc59SPat Donlin 	{ 0x47, "7_min", "" },
309fd5fdc59SPat Donlin 	{ 0x4F, "15_min", "" },
310fd5fdc59SPat Donlin 	{ 0x5E, "30_min", "" },
311fd5fdc59SPat Donlin 	{ 0x81, "1_hour", ""},
312fd5fdc59SPat Donlin 	{ 0x00, NULL, NULL },
313fd5fdc59SPat Donlin };
314fd5fdc59SPat Donlin 
315fd5fdc59SPat Donlin /* Primary Node Manager commands */
316fd5fdc59SPat Donlin const struct dcmi_cmd nm_cmd_vals[] = {
317fd5fdc59SPat Donlin 	{ 0x00, "discover", "Discover Node Manager " },
318fd5fdc59SPat Donlin 	{ 0x01, "capability", "Get Node Manager Capabilities" },
319fd5fdc59SPat Donlin 	{ 0x02, "control", "Enable/Disable Policy Control" },
320fd5fdc59SPat Donlin 	{ 0x03, "policy", "Add/Remove Policies" },
321fd5fdc59SPat Donlin 	{ 0x04, "statistics", "Get Statistics" },
322fd5fdc59SPat Donlin 	{ 0x05, "power", "Set Power Draw Range" },
323fd5fdc59SPat Donlin 	{ 0x06, "suspend", "Set/Get Policy suspend periods" },
324fd5fdc59SPat Donlin 	{ 0x07, "reset", "Reset Statistics" },
325fd5fdc59SPat Donlin 	{ 0x08, "alert", "Set/Get/Clear Alert destination" },
326fd5fdc59SPat Donlin 	{ 0x09, "threshold", "Set/Get Alert Thresholds" },
327fd5fdc59SPat Donlin 	{ 0xFF, NULL, NULL },
328fd5fdc59SPat Donlin };
329fd5fdc59SPat Donlin 
330fd5fdc59SPat Donlin const struct dcmi_cmd nm_ctl_cmds[] = {
331fd5fdc59SPat Donlin 	{ 0x01, "enable", " <control scope>" },
332fd5fdc59SPat Donlin 	{ 0x00, "disable", "<control scope>"},
333fd5fdc59SPat Donlin 	{ 0xFF, NULL, NULL },
334fd5fdc59SPat Donlin };
335fd5fdc59SPat Donlin 
336fd5fdc59SPat Donlin const struct dcmi_cmd nm_ctl_domain[] = {
337fd5fdc59SPat Donlin 	{ 0x00, "global", "" },
338fd5fdc59SPat Donlin 	{ 0x02, "per_domain", "<platform|CPU|Memory> (default is platform)" },
339fd5fdc59SPat Donlin 	{ 0x04, "per_policy", "<0-7>" },
340fd5fdc59SPat Donlin 	{ 0xFF, NULL, NULL },
341fd5fdc59SPat Donlin };
342fd5fdc59SPat Donlin 
343fd5fdc59SPat Donlin /* Node Manager Domain codes */
344fd5fdc59SPat Donlin const struct dcmi_cmd nm_domain_vals[] = {
345fd5fdc59SPat Donlin 	{ 0x00, "platform", ""  },
346fd5fdc59SPat Donlin 	{ 0x01, "CPU", ""  },
347fd5fdc59SPat Donlin 	{ 0x02, "Memory", "" },
348fd5fdc59SPat Donlin 	{ 0x03, "protection", "" },
349fd5fdc59SPat Donlin 	{ 0x04, "I/O", "" },
350fd5fdc59SPat Donlin 	{ 0xFF, NULL, NULL },
351fd5fdc59SPat Donlin };
352fd5fdc59SPat Donlin 
353fd5fdc59SPat Donlin const struct dcmi_cmd nm_version_vals[] = {
354fd5fdc59SPat Donlin 	{ 0x01, "1.0", "" },
355fd5fdc59SPat Donlin 	{ 0x02, "1.5", "" },
356fd5fdc59SPat Donlin 	{ 0x03, "2.0", "" },
357fd5fdc59SPat Donlin 	{ 0x04, "2.5", "" },
358fd5fdc59SPat Donlin 	{ 0x05, "3.0", "" },
359fd5fdc59SPat Donlin 	{ 0xFF, NULL, NULL },
360fd5fdc59SPat Donlin };
361fd5fdc59SPat Donlin 
362fd5fdc59SPat Donlin const struct dcmi_cmd nm_capability_opts[] = {
363fd5fdc59SPat Donlin 	{ 0x01, "domain", "<platform|CPU|Memory> (default is platform)" },
364fd5fdc59SPat Donlin 	{ 0x02, "inlet", "Inlet temp trigger" },
365fd5fdc59SPat Donlin 	{ 0x03, "missing", "Missing Power reading trigger" },
366fd5fdc59SPat Donlin 	{ 0x04, "reset", "Time after Host reset trigger" },
367fd5fdc59SPat Donlin 	{ 0x05, "boot", "Boot time policy" },
368fd5fdc59SPat Donlin 	{ 0xFF, NULL, NULL },
369fd5fdc59SPat Donlin };
370fd5fdc59SPat Donlin 
371fd5fdc59SPat Donlin const struct  dcmi_cmd nm_policy_type_vals[] = {
372fd5fdc59SPat Donlin 	{ 0x00, "No trigger, use Power Limit", "" },
373fd5fdc59SPat Donlin 	{ 0x01, "Inlet temp trigger", "" },
374fd5fdc59SPat Donlin 	{ 0x02, "Missing Power reading trigger", "" },
375fd5fdc59SPat Donlin 	{ 0x03, "Time after Host reset trigger", "" },
376fd5fdc59SPat Donlin 	{ 0x04, "number of cores to disable at boot time", "" },
377fd5fdc59SPat Donlin 	{ 0xFF, NULL, NULL },
378fd5fdc59SPat Donlin };
379fd5fdc59SPat Donlin 
380fd5fdc59SPat Donlin const struct dcmi_cmd nm_stats_opts[] = {
381fd5fdc59SPat Donlin 	{ 0x01, "domain", "<platform|CPU|Memory> (default is platform)" },
382fd5fdc59SPat Donlin 	{ 0x02, "policy_id", "<0-7>" },
383fd5fdc59SPat Donlin 	{ 0xFF, NULL, NULL },
384fd5fdc59SPat Donlin };
385fd5fdc59SPat Donlin 
386fd5fdc59SPat Donlin const struct dcmi_cmd nm_stats_mode[] = {
387fd5fdc59SPat Donlin 	{ 0x01, "power", "global power" },
388fd5fdc59SPat Donlin 	{ 0x02, "temps", "inlet temperature" },
389fd5fdc59SPat Donlin 	{ 0x11, "policy_power", "per policy power" },
390fd5fdc59SPat Donlin 	{ 0x12, "policy_temps", "per policy inlet temp" },
391fd5fdc59SPat Donlin 	{ 0x13, "policy_throt", "per policy throttling stats" },
392fd5fdc59SPat Donlin 	{ 0x1B, "requests", "unhandled requests" },
393fd5fdc59SPat Donlin 	{ 0x1C, "response", "response time" },
394fd5fdc59SPat Donlin 	{ 0x1D, "cpu_throttling", "CPU throttling" },
395fd5fdc59SPat Donlin 	{ 0x1E, "mem_throttling", "memory throttling" },
396fd5fdc59SPat Donlin 	{ 0x1F, "comm_fail", "host communication failures" },
397fd5fdc59SPat Donlin 	{ 0xFF, NULL, NULL },
398fd5fdc59SPat Donlin };
399fd5fdc59SPat Donlin 
400fd5fdc59SPat Donlin const struct dcmi_cmd nm_policy_action[] = {
401fd5fdc59SPat Donlin 	{ 0x00, "get", "nm policy get policy_id <0-7> [domain <platform|CPU|Memory>]" },
402fd5fdc59SPat Donlin 	{ 0x04, "add", "nm policy add policy_id <0-7> [domain <platform|CPU|Memory>] correction auto|soft|hard power <watts>|inlet <temp> trig_lim <param> stats <seconds> enable|disable" },
403fd5fdc59SPat Donlin 	{ 0x05, "remove", "nm policy remove policy_id <0-7> [domain <platform|CPU|Memory>]" },
404fd5fdc59SPat Donlin 	{ 0x06, "limiting", "nm policy limiting [domain <platform|CPU|Memory>]" },
405fd5fdc59SPat Donlin 	{ 0xFF, NULL, NULL },
406fd5fdc59SPat Donlin };
407fd5fdc59SPat Donlin const struct dcmi_cmd nm_policy_options[] = {
408fd5fdc59SPat Donlin 	{ 0x01, "enable", "" },
409fd5fdc59SPat Donlin 	{ 0x02, "disable", "" },
410fd5fdc59SPat Donlin 	{ 0x03, "domain", "" },
411fd5fdc59SPat Donlin 	{ 0x04, "inlet", "inlet air temp full limiting (SCRAM)"},
412fd5fdc59SPat Donlin 	{ 0x06, "correction", "auto, soft, hard" },
413fd5fdc59SPat Donlin 	{ 0x08, "power", "power limit in watts" },
414fd5fdc59SPat Donlin 	{ 0x09, "trig_lim", "time to send alert" },
415fd5fdc59SPat Donlin 	{ 0x0A, "stats", "moving window averaging time" },
416fd5fdc59SPat Donlin 	{ 0x0B, "policy_id", "policy number" },
417fd5fdc59SPat Donlin 	{ 0x0C, "volatile", "save policy in volatiel memory" },
418fd5fdc59SPat Donlin 	{ 0x0D, "cores_off", "at boot time, disable N cores" },
419fd5fdc59SPat Donlin 	{ 0xFF, NULL, NULL },
420fd5fdc59SPat Donlin };
421fd5fdc59SPat Donlin 
422fd5fdc59SPat Donlin /* if "trigger" command used from nm_policy_options */
423fd5fdc59SPat Donlin const struct dcmi_cmd nm_trigger[] = {
424fd5fdc59SPat Donlin 	{ 0x00, "none", "" },
425fd5fdc59SPat Donlin 	{ 0x01, "temp", "" },
426fd5fdc59SPat Donlin 	{ 0x02, "reset", "" },
427fd5fdc59SPat Donlin 	{ 0x03, "boot", "" },
428fd5fdc59SPat Donlin 	{ 0xFF, NULL, NULL },
429fd5fdc59SPat Donlin };
430fd5fdc59SPat Donlin 
431fd5fdc59SPat Donlin /* if "correction" used from nm_policy_options */
432fd5fdc59SPat Donlin const struct dcmi_cmd nm_correction[] = {
433fd5fdc59SPat Donlin 	{ 0x00, "auto", "" },
434fd5fdc59SPat Donlin 	{ 0x01, "soft", "" },
435fd5fdc59SPat Donlin 	{ 0x02, "hard", "" },
436fd5fdc59SPat Donlin 	{ 0xFF, NULL, NULL },
437fd5fdc59SPat Donlin };
438fd5fdc59SPat Donlin 
439fd5fdc59SPat Donlin /* returned codes from get policy */
440fd5fdc59SPat Donlin const struct dcmi_cmd nm_correction_vals[] = {
441fd5fdc59SPat Donlin 	{ 0x00, "no T-state use", "" },
442fd5fdc59SPat Donlin 	{ 0x01, "no T-state use", "" },
443fd5fdc59SPat Donlin 	{ 0x02, "use T-states", "" },
444fd5fdc59SPat Donlin 	{ 0xFF, NULL, NULL },
445fd5fdc59SPat Donlin };
446fd5fdc59SPat Donlin 
447fd5fdc59SPat Donlin /* if "exception" used from nm_policy_options */
448fd5fdc59SPat Donlin const struct dcmi_cmd nm_exception[] = {
449fd5fdc59SPat Donlin 	{ 0x00, "none", "" },
450fd5fdc59SPat Donlin 	{ 0x01, "alert", "" },
451fd5fdc59SPat Donlin 	{ 0x02, "shutdown", "" },
452fd5fdc59SPat Donlin 	{ 0xFF, NULL, NULL },
453fd5fdc59SPat Donlin };
454fd5fdc59SPat Donlin 
455fd5fdc59SPat Donlin const struct dcmi_cmd nm_reset_mode[] = {
456fd5fdc59SPat Donlin 	{ 0x00, "global", "" },
457fd5fdc59SPat Donlin 	{ 0x01, "per_policy", "" },
458fd5fdc59SPat Donlin 	{ 0x1B, "requests", "" },
459fd5fdc59SPat Donlin 	{ 0x1C, "response", "" },
460fd5fdc59SPat Donlin 	{ 0x1D, "throttling", "" },
461fd5fdc59SPat Donlin 	{ 0x1E, "memory", "", },
462fd5fdc59SPat Donlin 	{ 0x1F, "comm", "" },
463fd5fdc59SPat Donlin 	{ 0xFF, NULL, NULL },
464fd5fdc59SPat Donlin };
465fd5fdc59SPat Donlin 
466fd5fdc59SPat Donlin const struct dcmi_cmd nm_power_range[] = {
467fd5fdc59SPat Donlin 	{ 0x01, "domain", "domain <platform|CPU|Memory> (default is platform)" },
468fd5fdc59SPat Donlin 	{ 0x02, "min", " min <integer value>" },
469fd5fdc59SPat Donlin 	{ 0x03, "max", "max <integer value>" },
470fd5fdc59SPat Donlin 	{ 0xFF, NULL, NULL },
471fd5fdc59SPat Donlin };
472fd5fdc59SPat Donlin 
473fd5fdc59SPat Donlin const struct dcmi_cmd nm_alert_opts[] = {
474fd5fdc59SPat Donlin 	{ 0x01, "set", "nm alert set chan <chan> dest <dest> string <string>" },
475fd5fdc59SPat Donlin 	{ 0x02, "get", "nm alert get" },
476fd5fdc59SPat Donlin 	{ 0x03, "clear", "nm alert clear dest <dest>" },
477fd5fdc59SPat Donlin };
478fd5fdc59SPat Donlin 
479fd5fdc59SPat Donlin const struct dcmi_cmd nm_set_alert_param[] = {
480fd5fdc59SPat Donlin 	{ 0x01, "chan", "chan <channel>" },
481fd5fdc59SPat Donlin 	{ 0x02, "dest", "dest <destination>" },
482fd5fdc59SPat Donlin 	{ 0x03, "string", "string <string>" },
483fd5fdc59SPat Donlin };
484fd5fdc59SPat Donlin 
485fd5fdc59SPat Donlin const struct dcmi_cmd nm_thresh_cmds[] = {
486fd5fdc59SPat Donlin 	{ 0x01, "set", "nm thresh set [domain <platform|CPU|Memory>] policy_id <policy> thresh_array" },
487fd5fdc59SPat Donlin 	{ 0x02, "get", "nm thresh get [domain <platform|CPU|Memory>] policy_id <policy>" },
488fd5fdc59SPat Donlin };
489fd5fdc59SPat Donlin 
490fd5fdc59SPat Donlin const struct dcmi_cmd nm_thresh_param[] = {
491fd5fdc59SPat Donlin 	{ 0x01, "domain", "<platform|CPU|Memory> (default is platform)" },
492fd5fdc59SPat Donlin 	{ 0x02, "policy_id", "<0-7>" },
493fd5fdc59SPat Donlin 	{ 0xFF, NULL, NULL },
494fd5fdc59SPat Donlin };
495fd5fdc59SPat Donlin 
496fd5fdc59SPat Donlin const struct dcmi_cmd nm_suspend_cmds[] = {
497fd5fdc59SPat Donlin 	{ 0x01, "set", "nm suspend set [domain <platform|CPU|Memory]> policy_id <policy> <start> <stop> <pattern>" },
498fd5fdc59SPat Donlin 	{ 0x02, "get", "nm suspend get [domain <platform|CPU|Memory]> policy_id <policy>" },
499fd5fdc59SPat Donlin };
500fd5fdc59SPat Donlin 
501fd5fdc59SPat Donlin const struct valstr nm_ccode_vals[] = {
502fd5fdc59SPat Donlin 	{ 0x80, "Policy ID Invalid"},
503fd5fdc59SPat Donlin 	{ 0x81, "Domain ID Invalid"},
504fd5fdc59SPat Donlin 	{ 0x82, "Unknown policy trigger type"},
505fd5fdc59SPat Donlin 	{ 0x84, "Power Limit out of range"},
506fd5fdc59SPat Donlin 	{ 0x85, "Correction Time out of range"},
507fd5fdc59SPat Donlin 	{ 0x86, "Policy Trigger value out of range"},
508fd5fdc59SPat Donlin 	{ 0x88, "Invalid Mode"},
509fd5fdc59SPat Donlin 	{ 0x89, "Statistics Reporting Period out of range"},
510fd5fdc59SPat Donlin 	{ 0x8B, "Invalid value for Aggressive CPU correction field"},
511fd5fdc59SPat Donlin 	{ 0xA1, "No policy is currently limiting for the specified domain ID"},
512fd5fdc59SPat Donlin 	{ 0xC4, "No space available"},
513fd5fdc59SPat Donlin 	{ 0xD4, "Insufficient privledge level due wrong responder LUN"},
514fd5fdc59SPat Donlin 	{ 0xD5, "Policy exists and param unchangeable while enabled"},
515fd5fdc59SPat Donlin 	{ 0xD6, "Command subfunction disabled or unavailable"},
516fd5fdc59SPat Donlin 	{ 0xFF, NULL },
517fd5fdc59SPat Donlin };
518fd5fdc59SPat Donlin 
519fd5fdc59SPat Donlin 
520c18ec02fSPetter Reinholdtsen /* End strings */
521c18ec02fSPetter Reinholdtsen 
522c18ec02fSPetter Reinholdtsen /* This was taken from print_valstr() from helper.c.  It serves the same
523c18ec02fSPetter Reinholdtsen  * purpose but with out the extra formatting.  This function simply prints
524c18ec02fSPetter Reinholdtsen  * the dcmi_cmd struct provided.  verthorz specifies to print vertically or
525c18ec02fSPetter Reinholdtsen  * horizontally.  If the string is printed horizontally then a | will be
526c18ec02fSPetter Reinholdtsen  * printed between each instance of vs[i].str until it is NULL
527c18ec02fSPetter Reinholdtsen  *
528c18ec02fSPetter Reinholdtsen  * @vs:         value string list to print
529c18ec02fSPetter Reinholdtsen  * @title:      name of this value string list
530c18ec02fSPetter Reinholdtsen  * @loglevel:   what log level to print, -1 for stdout
531c18ec02fSPetter Reinholdtsen  * @verthorz:   printed vertically or horizontally, 0 or 1
532c18ec02fSPetter Reinholdtsen  */
533c18ec02fSPetter Reinholdtsen void
print_strs(const struct dcmi_cmd * vs,const char * title,int loglevel,int verthorz)534c18ec02fSPetter Reinholdtsen print_strs(const struct dcmi_cmd * vs, const char * title, int loglevel,
535c18ec02fSPetter Reinholdtsen 		int verthorz)
536c18ec02fSPetter Reinholdtsen {
537c18ec02fSPetter Reinholdtsen 	int i;
538c18ec02fSPetter Reinholdtsen 
539c18ec02fSPetter Reinholdtsen 	if (vs == NULL)
540c18ec02fSPetter Reinholdtsen 		return;
541c18ec02fSPetter Reinholdtsen 
542c18ec02fSPetter Reinholdtsen 	if (title != NULL) {
543c18ec02fSPetter Reinholdtsen 		if (loglevel < 0)
544c18ec02fSPetter Reinholdtsen 			printf("\n%s\n", title);
545c18ec02fSPetter Reinholdtsen 		else
546c18ec02fSPetter Reinholdtsen 			lprintf(loglevel, "\n%s", title);
547c18ec02fSPetter Reinholdtsen 	}
548c18ec02fSPetter Reinholdtsen 	for (i = 0; vs[i].str != NULL; i++) {
549c18ec02fSPetter Reinholdtsen 		if (loglevel < 0) {
550c18ec02fSPetter Reinholdtsen 			if (vs[i].val < 256)
551c18ec02fSPetter Reinholdtsen 				if (verthorz == 0)
552c18ec02fSPetter Reinholdtsen 					printf("    %s    %s\n", vs[i].str, vs[i].desc);
553c18ec02fSPetter Reinholdtsen 				else
554c18ec02fSPetter Reinholdtsen 					printf("%s", vs[i].str);
555c18ec02fSPetter Reinholdtsen 			else if (verthorz == 0)
556c18ec02fSPetter Reinholdtsen 				printf("    %s    %s\n", vs[i].str, vs[i].desc);
557c18ec02fSPetter Reinholdtsen 			else
558c18ec02fSPetter Reinholdtsen 				printf("%s", vs[i].str);
559c18ec02fSPetter Reinholdtsen 		} else {
560c18ec02fSPetter Reinholdtsen 			if (vs[i].val < 256)
561c18ec02fSPetter Reinholdtsen 				lprintf(loglevel, "    %s    %s", vs[i].str, vs[i].desc);
562c18ec02fSPetter Reinholdtsen 			else
563c18ec02fSPetter Reinholdtsen 				lprintf(loglevel, "    %s    %s", vs[i].str, vs[i].desc);
564c18ec02fSPetter Reinholdtsen 		}
565c18ec02fSPetter Reinholdtsen 		/* Check to see if this is NOT the last element in vs.str if true
566c18ec02fSPetter Reinholdtsen 		 * print the | else don't print anything.
567c18ec02fSPetter Reinholdtsen 		 */
568c18ec02fSPetter Reinholdtsen 		if ((verthorz == 1) && (vs[i+1].str != NULL))
569c18ec02fSPetter Reinholdtsen 			printf(" | ");
570c18ec02fSPetter Reinholdtsen 	}
571c18ec02fSPetter Reinholdtsen 	if (verthorz == 0) {
572c18ec02fSPetter Reinholdtsen 		if (loglevel < 0) {
573c18ec02fSPetter Reinholdtsen 			printf("\n");
574c18ec02fSPetter Reinholdtsen 		} else {
575c18ec02fSPetter Reinholdtsen 			lprintf(loglevel, "");
576c18ec02fSPetter Reinholdtsen 		}
577c18ec02fSPetter Reinholdtsen 	}
578c18ec02fSPetter Reinholdtsen }
579c18ec02fSPetter Reinholdtsen 
580c18ec02fSPetter Reinholdtsen /* This was taken from str2val() from helper.c.  It serves the same
581c18ec02fSPetter Reinholdtsen  * purpose but with the addition of a desc field from the structure.
582c18ec02fSPetter Reinholdtsen  * This function converts the str from the dcmi_cmd struct provided to the
583c18ec02fSPetter Reinholdtsen  * value associated to the compared string in the struct.
584c18ec02fSPetter Reinholdtsen  *
585c18ec02fSPetter Reinholdtsen  * @str:        string to compare against
586c18ec02fSPetter Reinholdtsen  * @vs:         dcmi_cmd structure
587c18ec02fSPetter Reinholdtsen  */
588c18ec02fSPetter Reinholdtsen uint16_t
str2val2(const char * str,const struct dcmi_cmd * vs)589c18ec02fSPetter Reinholdtsen str2val2(const char *str, const struct dcmi_cmd *vs)
590c18ec02fSPetter Reinholdtsen {
591c18ec02fSPetter Reinholdtsen 	int i;
592c18ec02fSPetter Reinholdtsen 	if (vs == NULL || str == NULL) {
593c18ec02fSPetter Reinholdtsen 		return 0;
594c18ec02fSPetter Reinholdtsen 	}
595c18ec02fSPetter Reinholdtsen 	for (i = 0; vs[i].str != NULL; i++) {
596c18ec02fSPetter Reinholdtsen 		if (strncasecmp(vs[i].str, str,
597c18ec02fSPetter Reinholdtsen 					__maxlen(str, vs[i].str)) == 0) {
598c18ec02fSPetter Reinholdtsen 			return vs[i].val;
599c18ec02fSPetter Reinholdtsen 		}
600c18ec02fSPetter Reinholdtsen 	}
601c18ec02fSPetter Reinholdtsen 	return vs[i].val;
602c18ec02fSPetter Reinholdtsen }
603c18ec02fSPetter Reinholdtsen 
604c18ec02fSPetter Reinholdtsen /* This was taken from val2str() from helper.c.  It serves the same
605c18ec02fSPetter Reinholdtsen  * purpose but with the addition of a desc field from the structure.
606c18ec02fSPetter Reinholdtsen  * This function converts the val and returns a string from the dcmi_cmd
607c18ec02fSPetter Reinholdtsen  * struct provided in the struct.
608c18ec02fSPetter Reinholdtsen  *
609c18ec02fSPetter Reinholdtsen  * @val:        value to compare against
610c18ec02fSPetter Reinholdtsen  * @vs:         dcmi_cmd structure
611c18ec02fSPetter Reinholdtsen  */
612c18ec02fSPetter Reinholdtsen const char *
val2str2(uint16_t val,const struct dcmi_cmd * vs)613c18ec02fSPetter Reinholdtsen val2str2(uint16_t val, const struct dcmi_cmd *vs)
614c18ec02fSPetter Reinholdtsen {
615c18ec02fSPetter Reinholdtsen 	static char un_str[32];
616c18ec02fSPetter Reinholdtsen 	int i;
617c18ec02fSPetter Reinholdtsen 
618c18ec02fSPetter Reinholdtsen 	if (vs == NULL)
619c18ec02fSPetter Reinholdtsen 		return NULL;
620c18ec02fSPetter Reinholdtsen 
621c18ec02fSPetter Reinholdtsen 	for (i = 0; vs[i].str != NULL; i++) {
622c18ec02fSPetter Reinholdtsen 		if (vs[i].val == val)
623c18ec02fSPetter Reinholdtsen 			return vs[i].str;
624c18ec02fSPetter Reinholdtsen 	}
625fd5fdc59SPat Donlin 	memset(un_str, 0, sizeof (un_str));
626c18ec02fSPetter Reinholdtsen 	snprintf(un_str, 32, "Unknown (0x%x)", val);
627c18ec02fSPetter Reinholdtsen 	return un_str;
628c18ec02fSPetter Reinholdtsen }
629c18ec02fSPetter Reinholdtsen 
630c18ec02fSPetter Reinholdtsen /* check the DCMI response   from the BMC
631c18ec02fSPetter Reinholdtsen  * @rsp:       Response data structure
632c18ec02fSPetter Reinholdtsen  */
633c18ec02fSPetter Reinholdtsen static int
chk_rsp(struct ipmi_rs * rsp)634c18ec02fSPetter Reinholdtsen chk_rsp(struct ipmi_rs * rsp)
635c18ec02fSPetter Reinholdtsen {
636c18ec02fSPetter Reinholdtsen 	/* if the response from the intf is NULL then the BMC is experiencing
637c18ec02fSPetter Reinholdtsen 	 * some issue and cannot complete the command
638c18ec02fSPetter Reinholdtsen 	 */
639c18ec02fSPetter Reinholdtsen 	if (rsp == NULL) {
640c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "\n    Unable to get DCMI information");
641c18ec02fSPetter Reinholdtsen 		return 1;
642c18ec02fSPetter Reinholdtsen 	}
643c18ec02fSPetter Reinholdtsen 	/* if the completion code is greater than zero there was an error.  We'll
644c18ec02fSPetter Reinholdtsen 	 * use val2str from helper.c to print the error from either the DCMI
645c18ec02fSPetter Reinholdtsen 	 * completion code struct or the generic IPMI completion_code_vals struct
646c18ec02fSPetter Reinholdtsen 	 */
647c18ec02fSPetter Reinholdtsen 	if ((rsp->ccode >= 0x80) && (rsp->ccode <= 0x8F)) {
648c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "\n    DCMI request failed because: %s (%x)",
649c18ec02fSPetter Reinholdtsen 				val2str(rsp->ccode, dcmi_ccode_vals), rsp->ccode);
650c18ec02fSPetter Reinholdtsen 		return 1;
651c18ec02fSPetter Reinholdtsen 	} else if (rsp->ccode > 0) {
652c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "\n    DCMI request failed because: %s (%x)",
653c18ec02fSPetter Reinholdtsen 				val2str(rsp->ccode, completion_code_vals), rsp->ccode);
654c18ec02fSPetter Reinholdtsen 		return 1;
655c18ec02fSPetter Reinholdtsen 	}
656c18ec02fSPetter Reinholdtsen 	/* check to make sure this is a DCMI firmware */
657c18ec02fSPetter Reinholdtsen 	if(rsp->data[0] != IPMI_DCMI) {
658c18ec02fSPetter Reinholdtsen 		printf("\n    A valid DCMI command was not returned! (%x)", rsp->data[0]);
659c18ec02fSPetter Reinholdtsen 		return 1;
660c18ec02fSPetter Reinholdtsen 	}
661c18ec02fSPetter Reinholdtsen 	return 0;
662c18ec02fSPetter Reinholdtsen }
663c18ec02fSPetter Reinholdtsen 
664fd5fdc59SPat Donlin /* check the Node Manager response from the BMC
665fd5fdc59SPat Donlin  * @rsp:       Response data structure
666fd5fdc59SPat Donlin  */
667fd5fdc59SPat Donlin static int
chk_nm_rsp(struct ipmi_rs * rsp)668fd5fdc59SPat Donlin chk_nm_rsp(struct ipmi_rs * rsp)
669fd5fdc59SPat Donlin {
670fd5fdc59SPat Donlin 	/* if the response from the intf is NULL then the BMC is experiencing
671fd5fdc59SPat Donlin 	 * some issue and cannot complete the command
672fd5fdc59SPat Donlin 	 */
673fd5fdc59SPat Donlin 	if (rsp == NULL) {
674fd5fdc59SPat Donlin 		lprintf(LOG_ERR, "\n    No reponse to NM request");
675fd5fdc59SPat Donlin 		return 1;
676fd5fdc59SPat Donlin 	}
677fd5fdc59SPat Donlin 	/* if the completion code is greater than zero there was an error.  We'll
678fd5fdc59SPat Donlin 	 * use val2str from helper.c to print the error from either the DCMI
679fd5fdc59SPat Donlin 	 * completion code struct or the generic IPMI completion_code_vals struct
680fd5fdc59SPat Donlin 	 */
681fd5fdc59SPat Donlin 	if ((rsp->ccode >= 0x80) && (rsp->ccode <= 0xD6)) {
682fd5fdc59SPat Donlin 		lprintf(LOG_ERR, "\n    NM request failed because: %s (%x)",
683fd5fdc59SPat Donlin 		val2str(rsp->ccode, nm_ccode_vals), rsp->ccode);
684fd5fdc59SPat Donlin 		return 1;
685fd5fdc59SPat Donlin 	} else if (rsp->ccode > 0) {
686fd5fdc59SPat Donlin 		lprintf(LOG_ERR, "\n    NM request failed because: %s (%x)",
687fd5fdc59SPat Donlin 			val2str(rsp->ccode, completion_code_vals), rsp->ccode);
688fd5fdc59SPat Donlin 		return 1;
689fd5fdc59SPat Donlin 	}
690fd5fdc59SPat Donlin 	/* check to make sure this is a DCMI firmware */
691fd5fdc59SPat Donlin 	if(rsp->data[0] != 0x57) {
692fd5fdc59SPat Donlin 		printf("\n    A valid NM command was not returned! (%x)", rsp->data[0]);
693fd5fdc59SPat Donlin 		return 1;
694fd5fdc59SPat Donlin 	}
695fd5fdc59SPat Donlin 	return 0;
696fd5fdc59SPat Donlin }
697fd5fdc59SPat Donlin 
698c18ec02fSPetter Reinholdtsen /* Get capabilities ipmi response
699c18ec02fSPetter Reinholdtsen  *
700c18ec02fSPetter Reinholdtsen  * This function returns the available capabilities of the platform.
701c18ec02fSPetter Reinholdtsen  * The reason it returns in the rsp struct is so that it can be used for other
702c18ec02fSPetter Reinholdtsen  * purposes.
703c18ec02fSPetter Reinholdtsen  *
704c18ec02fSPetter Reinholdtsen  * returns ipmi response structure
705c18ec02fSPetter Reinholdtsen  *
706c18ec02fSPetter Reinholdtsen  * @intf:   ipmi interface handler
707c18ec02fSPetter Reinholdtsen  * @selector: Parameter selector
708c18ec02fSPetter Reinholdtsen  */
709c18ec02fSPetter Reinholdtsen struct ipmi_rs *
ipmi_dcmi_getcapabilities(struct ipmi_intf * intf,uint8_t selector)710c18ec02fSPetter Reinholdtsen ipmi_dcmi_getcapabilities(struct ipmi_intf * intf, uint8_t selector)
711c18ec02fSPetter Reinholdtsen {
712c18ec02fSPetter Reinholdtsen 	struct ipmi_rq req; /* request data to send to the BMC */
713c18ec02fSPetter Reinholdtsen 	uint8_t msg_data[2]; /* 'raw' data to be sent to the BMC */
714c18ec02fSPetter Reinholdtsen 
715c18ec02fSPetter Reinholdtsen 	msg_data[0] = IPMI_DCMI; /* Group Extension Identification */
716c18ec02fSPetter Reinholdtsen 	msg_data[1] = selector;
717c18ec02fSPetter Reinholdtsen 
718c18ec02fSPetter Reinholdtsen 	memset(&req, 0, sizeof(req));
719c18ec02fSPetter Reinholdtsen 	req.msg.netfn = IPMI_NETFN_DCGRP; /* 0x2C per 1.0 spec */
720c18ec02fSPetter Reinholdtsen 	req.msg.cmd = IPMI_DCMI_COMPAT; /* 0x01 per 1.0 spec */
721c18ec02fSPetter Reinholdtsen 	req.msg.data = msg_data; /* 0xDC 0x01 or the msg_data above */
722c18ec02fSPetter Reinholdtsen 	req.msg.data_len = 2; /* How many times does req.msg.data need to read */
723c18ec02fSPetter Reinholdtsen 
724c18ec02fSPetter Reinholdtsen 	return intf->sendrecv(intf, &req);
725c18ec02fSPetter Reinholdtsen }
726c18ec02fSPetter Reinholdtsen /* end capabilities struct */
727c18ec02fSPetter Reinholdtsen 
728c18ec02fSPetter Reinholdtsen /* Displays capabilities from structure
729c18ec02fSPetter Reinholdtsen  * returns void
730c18ec02fSPetter Reinholdtsen  *
731c18ec02fSPetter Reinholdtsen  * @cmd:        dcmi_cmd structure
732c18ec02fSPetter Reinholdtsen  * @data_val:  holds value of what to display
733c18ec02fSPetter Reinholdtsen  */
734c18ec02fSPetter Reinholdtsen void
display_capabilities_attributes(const struct dcmi_cmd * cmd,uint8_t data_val)735c18ec02fSPetter Reinholdtsen display_capabilities_attributes(const struct dcmi_cmd *cmd, uint8_t data_val)
736c18ec02fSPetter Reinholdtsen {
737c18ec02fSPetter Reinholdtsen 	uint8_t i;
738c18ec02fSPetter Reinholdtsen 	for (i = 0x01; cmd[i-1].val != 0xFF; i++) {
739c18ec02fSPetter Reinholdtsen 		if (data_val & (1<<(i-1))) {
740c18ec02fSPetter Reinholdtsen 			printf("        %s\n", val2str2(i, cmd));
741c18ec02fSPetter Reinholdtsen 		}
742c18ec02fSPetter Reinholdtsen 	}
743c18ec02fSPetter Reinholdtsen }
744c18ec02fSPetter Reinholdtsen 
745c18ec02fSPetter Reinholdtsen static int
ipmi_dcmi_prnt_oobDiscover(struct ipmi_intf * intf)746c18ec02fSPetter Reinholdtsen ipmi_dcmi_prnt_oobDiscover(struct ipmi_intf * intf)
747c18ec02fSPetter Reinholdtsen {
748c18ec02fSPetter Reinholdtsen # ifndef IPMI_INTF_LANPLUS
749c18ec02fSPetter Reinholdtsen 	lprintf(LOG_ERR,
750c18ec02fSPetter Reinholdtsen 			"DCMI Discovery is available only when LANplus(IPMI v2.0) is enabled.");
751c18ec02fSPetter Reinholdtsen 	return (-1);
752c18ec02fSPetter Reinholdtsen # else
753*eb541367SZdenek Styblik 	struct ipmi_session_params *p;
754c18ec02fSPetter Reinholdtsen 
755c18ec02fSPetter Reinholdtsen 	if (intf->opened == 0 && intf->open != NULL) {
756c18ec02fSPetter Reinholdtsen 		if (intf->open(intf) < 0)
757c18ec02fSPetter Reinholdtsen 			return (-1);
758c18ec02fSPetter Reinholdtsen 	}
759c18ec02fSPetter Reinholdtsen 	if (intf == NULL || intf->session == NULL)
760c18ec02fSPetter Reinholdtsen 		return -1;
761c18ec02fSPetter Reinholdtsen 
762*eb541367SZdenek Styblik 	p = &intf->ssn_params;
763c18ec02fSPetter Reinholdtsen 
764*eb541367SZdenek Styblik 	if (p->port == 0)
765*eb541367SZdenek Styblik 		p->port = IPMI_LAN_PORT;
766*eb541367SZdenek Styblik 	if (p->privlvl == 0)
767*eb541367SZdenek Styblik 		p->privlvl = IPMI_SESSION_PRIV_ADMIN;
768*eb541367SZdenek Styblik 	if (p->timeout == 0)
769*eb541367SZdenek Styblik 		p->timeout = IPMI_LAN_TIMEOUT;
770*eb541367SZdenek Styblik 	if (p->retry == 0)
771*eb541367SZdenek Styblik 		p->retry = IPMI_LAN_RETRY;
772c18ec02fSPetter Reinholdtsen 
773*eb541367SZdenek Styblik 	if (p->hostname == NULL || strlen((const char *)p->hostname) == 0) {
774c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "No hostname specified!");
775c18ec02fSPetter Reinholdtsen 		return -1;
776c18ec02fSPetter Reinholdtsen 	}
777c18ec02fSPetter Reinholdtsen 
778c18ec02fSPetter Reinholdtsen 	intf->abort = 1;
779c18ec02fSPetter Reinholdtsen 	intf->session->sol_data.sequence_number = 1;
780c18ec02fSPetter Reinholdtsen 
781c18ec02fSPetter Reinholdtsen 	if (ipmi_intf_socket_connect (intf)  == -1) {
782c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "Could not open socket!");
783c18ec02fSPetter Reinholdtsen 		return -1;
784c18ec02fSPetter Reinholdtsen 	}
785c18ec02fSPetter Reinholdtsen 
786c18ec02fSPetter Reinholdtsen 	if (intf->fd < 0) {
787c18ec02fSPetter Reinholdtsen 		lperror(LOG_ERR, "Connect to %s failed",
788*eb541367SZdenek Styblik 			p->hostname);
789c18ec02fSPetter Reinholdtsen 		intf->close(intf);
790c18ec02fSPetter Reinholdtsen 		return -1;
791c18ec02fSPetter Reinholdtsen 	}
792c18ec02fSPetter Reinholdtsen 
793c18ec02fSPetter Reinholdtsen 	intf->opened = 1;
794c18ec02fSPetter Reinholdtsen 
795c18ec02fSPetter Reinholdtsen 	/* Lets ping/pong */
796c18ec02fSPetter Reinholdtsen 	return ipmiv2_lan_ping(intf);
797c18ec02fSPetter Reinholdtsen # endif
798c18ec02fSPetter Reinholdtsen }
799c18ec02fSPetter Reinholdtsen 
800c18ec02fSPetter Reinholdtsen /* This is the get DCMI Capabilities function to see what the BMC supports.
801c18ec02fSPetter Reinholdtsen  *
802c18ec02fSPetter Reinholdtsen  * returns 0 with out error -1 with any errors
803c18ec02fSPetter Reinholdtsen  *
804c18ec02fSPetter Reinholdtsen  * @intf:      ipmi interface handler
805c18ec02fSPetter Reinholdtsen  * @selector:  selection parameter
806c18ec02fSPetter Reinholdtsen  */
807c18ec02fSPetter Reinholdtsen static int
ipmi_dcmi_prnt_getcapabilities(struct ipmi_intf * intf,uint8_t selector)808c18ec02fSPetter Reinholdtsen ipmi_dcmi_prnt_getcapabilities(struct ipmi_intf * intf, uint8_t selector)
809c18ec02fSPetter Reinholdtsen {
810c18ec02fSPetter Reinholdtsen 	struct capabilities cape;
811c18ec02fSPetter Reinholdtsen 	struct ipmi_rs * rsp;
812fd5fdc59SPat Donlin 	uint8_t reply[16];
813c18ec02fSPetter Reinholdtsen 	rsp = ipmi_dcmi_getcapabilities(intf, selector);
814fd5fdc59SPat Donlin 	int j;
815c18ec02fSPetter Reinholdtsen 
816c18ec02fSPetter Reinholdtsen 	if(chk_rsp(rsp))
817c18ec02fSPetter Reinholdtsen 		return -1;
818c18ec02fSPetter Reinholdtsen 
819c18ec02fSPetter Reinholdtsen 	/* if there were no errors, the command worked! */
820c18ec02fSPetter Reinholdtsen 	memcpy(&cape, rsp->data, sizeof (cape));
821fd5fdc59SPat Donlin 	memcpy(&reply, rsp->data, sizeof (reply));
822c18ec02fSPetter Reinholdtsen 	/* check to make sure that this is a 1.0/1.1/1.5 command */
823c18ec02fSPetter Reinholdtsen 	if ((cape.conformance != IPMI_DCMI_CONFORM)
824c18ec02fSPetter Reinholdtsen 			&& (cape.conformance != IPMI_DCMI_1_1_CONFORM)
825c18ec02fSPetter Reinholdtsen 			&& (cape.conformance != IPMI_DCMI_1_5_CONFORM)) {
826c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR,
827c18ec02fSPetter Reinholdtsen 				"ERROR!  This command is not available on this platform");
828c18ec02fSPetter Reinholdtsen 		return -1;
829c18ec02fSPetter Reinholdtsen 	}
830c18ec02fSPetter Reinholdtsen 	/* check to make sure that this is a rev .01 or .02 */
831c18ec02fSPetter Reinholdtsen 	if (cape.revision != 0x01 && cape.revision != 0x02) {
832c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR,
833c18ec02fSPetter Reinholdtsen 				"ERROR!  This command is not compatible with this version");
834c18ec02fSPetter Reinholdtsen 		return -1;
835c18ec02fSPetter Reinholdtsen 	}
836c18ec02fSPetter Reinholdtsen 	/* 0x01 - platform capabilities
837c18ec02fSPetter Reinholdtsen 	 * 0x02 - Manageability Access Capabilities
838c18ec02fSPetter Reinholdtsen 	 * 0x03 - SEL Capability
839c18ec02fSPetter Reinholdtsen 	 * 0x04 - Identification Capability
840c18ec02fSPetter Reinholdtsen 	 * 0x05 - LAN Out-Of-Band Capability
841c18ec02fSPetter Reinholdtsen 	 * 0x06 - Serial Out-Of-Band TMODE Capability
842c18ec02fSPetter Reinholdtsen 	 */
843c18ec02fSPetter Reinholdtsen 	switch (selector) {
844c18ec02fSPetter Reinholdtsen 	case 0x01:
845c18ec02fSPetter Reinholdtsen 		printf("    Supported DCMI capabilities:\n");
846c18ec02fSPetter Reinholdtsen 		/* loop through each of the entries in the first byte from the
847c18ec02fSPetter Reinholdtsen 		 * struct
848c18ec02fSPetter Reinholdtsen 		 */
849c18ec02fSPetter Reinholdtsen 		printf("\n         Mandatory platform capabilties\n");
850c18ec02fSPetter Reinholdtsen 		display_capabilities_attributes(
851c18ec02fSPetter Reinholdtsen 				dcmi_mandatory_platform_capabilities, cape.data_byte1);
852c18ec02fSPetter Reinholdtsen 		/* loop through each of the entries in the second byte from the
853c18ec02fSPetter Reinholdtsen 		 * struct
854c18ec02fSPetter Reinholdtsen 		 */
855c18ec02fSPetter Reinholdtsen 		printf("\n         Optional platform capabilties\n");
856c18ec02fSPetter Reinholdtsen 		display_capabilities_attributes(
857c18ec02fSPetter Reinholdtsen 				dcmi_optional_platform_capabilities, cape.data_byte2);
858c18ec02fSPetter Reinholdtsen 		/* loop through each of the entries in the third byte from the
859c18ec02fSPetter Reinholdtsen 		 * struct
860c18ec02fSPetter Reinholdtsen 		 */
861c18ec02fSPetter Reinholdtsen 		printf("\n         Managebility access capabilties\n");
862c18ec02fSPetter Reinholdtsen 		display_capabilities_attributes(
863c18ec02fSPetter Reinholdtsen 				dcmi_management_access_capabilities, cape.data_byte3);
864c18ec02fSPetter Reinholdtsen 		break;
865c18ec02fSPetter Reinholdtsen 	case 0x02:
866c18ec02fSPetter Reinholdtsen 		printf("\n    Mandatory platform attributes:\n");
867c18ec02fSPetter Reinholdtsen 		/* byte 1 & 2 data */
868c18ec02fSPetter Reinholdtsen 		printf("\n         SEL Attributes: ");
869c18ec02fSPetter Reinholdtsen 		printf("\n               SEL automatic rollover is ");
870c18ec02fSPetter Reinholdtsen 		/* mask the 2nd byte of the data response with 10000000b or 0x80
871c18ec02fSPetter Reinholdtsen 		 * because of the endian-ness the 15th bit is in the second byte
872c18ec02fSPetter Reinholdtsen 		 */
873c18ec02fSPetter Reinholdtsen 		if ((cape.data_byte2 & 0x80))
874c18ec02fSPetter Reinholdtsen 			printf("enabled");
875c18ec02fSPetter Reinholdtsen 		else
876c18ec02fSPetter Reinholdtsen 			printf("not present");
877c18ec02fSPetter Reinholdtsen 		/* since the number of SEL entries is split across the two data
878c18ec02fSPetter Reinholdtsen 		 * bytes we will need to bit shift and append them together again
879c18ec02fSPetter Reinholdtsen 		 */
880c18ec02fSPetter Reinholdtsen 		/* cast cape.data_byte1 as 16 bits */
881c18ec02fSPetter Reinholdtsen 		uint16_t sel_entries = (uint16_t)cape.data_byte1;
882c18ec02fSPetter Reinholdtsen 		/* or sel_entries with byte 2 and shift it 8 places  */
883c18ec02fSPetter Reinholdtsen 		sel_entries |= (uint16_t)cape.data_byte2 << 8;
884c18ec02fSPetter Reinholdtsen 		printf("\n               %d SEL entries\n", sel_entries & 0xFFF);
885c18ec02fSPetter Reinholdtsen 		/* byte 3 data */
886c18ec02fSPetter Reinholdtsen 		printf("\n         Identification Attributes: \n");
887c18ec02fSPetter Reinholdtsen 		display_capabilities_attributes(
888c18ec02fSPetter Reinholdtsen 				dcmi_id_capabilities_vals, cape.data_byte3);
889c18ec02fSPetter Reinholdtsen 		/* byte 4 data */
890c18ec02fSPetter Reinholdtsen 		printf("\n         Temperature Monitoring Attributes: \n");
891c18ec02fSPetter Reinholdtsen 		display_capabilities_attributes(dcmi_temp_monitoring_vals,
892c18ec02fSPetter Reinholdtsen 				cape.data_byte4);
893c18ec02fSPetter Reinholdtsen 		break;
894c18ec02fSPetter Reinholdtsen 	case 0x03:
895c18ec02fSPetter Reinholdtsen 		printf("\n    Optional Platform Attributes: \n");
896c18ec02fSPetter Reinholdtsen 		/* Power Management */
897c18ec02fSPetter Reinholdtsen 		printf("\n         Power Management:\n");
898c18ec02fSPetter Reinholdtsen 		if (cape.data_byte1 == 0x40) {
899c18ec02fSPetter Reinholdtsen 			printf("                Slave address of device: 20h (BMC)\n" );
900c18ec02fSPetter Reinholdtsen 		} else {
901c18ec02fSPetter Reinholdtsen 			printf("                Slave address of device: %xh (8bits)"
902c18ec02fSPetter Reinholdtsen 					"(Satellite/External controller)\n",
903c18ec02fSPetter Reinholdtsen 					cape.data_byte1);
904c18ec02fSPetter Reinholdtsen 		}
905c18ec02fSPetter Reinholdtsen 		/* Controller channel number (4-7) bits */
906c18ec02fSPetter Reinholdtsen 		if ((cape.data_byte2>>4) == 0x00) {
907c18ec02fSPetter Reinholdtsen 			printf("                Channel number is 0h (Primary BMC)\n");
908c18ec02fSPetter Reinholdtsen 		} else {
909c18ec02fSPetter Reinholdtsen 			printf("                Channel number is %xh \n",
910c18ec02fSPetter Reinholdtsen 					(cape.data_byte2>>4));
911c18ec02fSPetter Reinholdtsen 		}
912c18ec02fSPetter Reinholdtsen 		/* Device revision (0-3) */
913c18ec02fSPetter Reinholdtsen 		printf("                    Device revision is %d \n",
914c18ec02fSPetter Reinholdtsen 				cape.data_byte2 &0xf);
915c18ec02fSPetter Reinholdtsen 		break;
916c18ec02fSPetter Reinholdtsen 	case 0x04:
917c18ec02fSPetter Reinholdtsen 		/* LAN */
918c18ec02fSPetter Reinholdtsen 		printf("\n    Manageability Access Attributes: \n");
919c18ec02fSPetter Reinholdtsen 		if (cape.data_byte1 == 0xFF) {
920c18ec02fSPetter Reinholdtsen 			printf("         Primary LAN channel is not available for OOB\n");
921c18ec02fSPetter Reinholdtsen 		} else {
922c18ec02fSPetter Reinholdtsen 			printf("         Primary LAN channel number: %d is available\n",
923c18ec02fSPetter Reinholdtsen 					cape.data_byte1);
924c18ec02fSPetter Reinholdtsen 		}
925c18ec02fSPetter Reinholdtsen 		if (cape.data_byte2 == 0xFF) {
926c18ec02fSPetter Reinholdtsen 			printf("         Secondary LAN channel is not available for OOB\n");
927c18ec02fSPetter Reinholdtsen 		} else {
928c18ec02fSPetter Reinholdtsen 			printf("         Secondary LAN channel number: %d is available\n",
929c18ec02fSPetter Reinholdtsen 					cape.data_byte2);
930c18ec02fSPetter Reinholdtsen 		}
931c18ec02fSPetter Reinholdtsen 		/* serial */
932c18ec02fSPetter Reinholdtsen 		if (cape.data_byte3 == 0xFF) {
933c18ec02fSPetter Reinholdtsen 			printf("         No serial channel is available\n");
934c18ec02fSPetter Reinholdtsen 		} else {
935c18ec02fSPetter Reinholdtsen 			printf("         Serial channel number: %d is available\n",
936c18ec02fSPetter Reinholdtsen 					cape.data_byte3);
937c18ec02fSPetter Reinholdtsen 		}
938c18ec02fSPetter Reinholdtsen 		break;
939fd5fdc59SPat Donlin 	case 0x05:
940fd5fdc59SPat Donlin 		/* Node Manager */
941fd5fdc59SPat Donlin 		printf("\n    Node Manager Get DCMI Capability Info: \n");
942fd5fdc59SPat Donlin 		printf("         DCMI Specification %d.%d\n", reply[1], reply[2]);
943fd5fdc59SPat Donlin 		printf("         Rolling average time period options: %d\n", reply[4]);
944fd5fdc59SPat Donlin 		printf("         Sample time options: ");
945fd5fdc59SPat Donlin 		for (j = 1; dcmi_sampling_vals[j-1].str != NULL; j++)
946fd5fdc59SPat Donlin 			printf(" %s ", val2str2(reply[4+j],dcmi_sampling_vals));
947fd5fdc59SPat Donlin 		printf("\n");
948fd5fdc59SPat Donlin 		break;
949c18ec02fSPetter Reinholdtsen 	default:
950c18ec02fSPetter Reinholdtsen 		return -1;
951c18ec02fSPetter Reinholdtsen 	}
952c18ec02fSPetter Reinholdtsen 	return 0;
953c18ec02fSPetter Reinholdtsen 	/* return intf->sendrecv(intf, &req); */
954c18ec02fSPetter Reinholdtsen }
955c18ec02fSPetter Reinholdtsen 
956c18ec02fSPetter Reinholdtsen /* This is the get asset tag command.  This checks the length of the asset tag
957c18ec02fSPetter Reinholdtsen  * with the first read, then reads n number of bytes thereafter to get the
958c18ec02fSPetter Reinholdtsen  * complete asset tag.
959c18ec02fSPetter Reinholdtsen  *
960c18ec02fSPetter Reinholdtsen  * @intf:   ipmi interface handler
961c18ec02fSPetter Reinholdtsen  * @offset: where to start reading the asset tag
962c18ec02fSPetter Reinholdtsen  * @length: how much to read
963c18ec02fSPetter Reinholdtsen  *
964c18ec02fSPetter Reinholdtsen  * returns ipmi_rs structure
965c18ec02fSPetter Reinholdtsen  */
966c18ec02fSPetter Reinholdtsen struct ipmi_rs *
ipmi_dcmi_getassettag(struct ipmi_intf * intf,uint8_t offset,uint8_t length)967c18ec02fSPetter Reinholdtsen ipmi_dcmi_getassettag(struct ipmi_intf * intf, uint8_t offset, uint8_t length)
968c18ec02fSPetter Reinholdtsen {
969c18ec02fSPetter Reinholdtsen 	struct ipmi_rq req; /* request data to send to the BMC */
970c18ec02fSPetter Reinholdtsen 	uint8_t msg_data[3]; /* 'raw' data to be sent to the BMC */
971c18ec02fSPetter Reinholdtsen 
972c18ec02fSPetter Reinholdtsen 	msg_data[0] = IPMI_DCMI; /* Group Extension Identification */
973c18ec02fSPetter Reinholdtsen 	msg_data[1] = offset; /* offset 0 */
974c18ec02fSPetter Reinholdtsen 	msg_data[2] = length; /* read one byte */
975c18ec02fSPetter Reinholdtsen 
976c18ec02fSPetter Reinholdtsen 	memset(&req, 0, sizeof(req));
977c18ec02fSPetter Reinholdtsen 	req.msg.netfn = IPMI_NETFN_DCGRP; /* 0x2C per 1.1 spec */
978c18ec02fSPetter Reinholdtsen 	req.msg.cmd = IPMI_DCMI_GETASSET; /* 0x01 per 1.1 spec */
979c18ec02fSPetter Reinholdtsen 	req.msg.data = msg_data; /* msg_data above */
980c18ec02fSPetter Reinholdtsen 	req.msg.data_len = 3; /* How many times does req.msg.data need to read */
981c18ec02fSPetter Reinholdtsen 	return intf->sendrecv(intf, &req);
982c18ec02fSPetter Reinholdtsen }
983c18ec02fSPetter Reinholdtsen 
984c18ec02fSPetter Reinholdtsen /* This is the get asset tag command.  The function first checks to see if the
985c18ec02fSPetter Reinholdtsen  * platform is capable of getting the asset tag by calling the getcapabilities
986c18ec02fSPetter Reinholdtsen  * function and checking the response.  Then it checks the length of the asset
987c18ec02fSPetter Reinholdtsen  * tag with the first read, then x number of reads thereafter to get the asset
988c18ec02fSPetter Reinholdtsen  * complete asset tag then print it.
989c18ec02fSPetter Reinholdtsen  *
990c18ec02fSPetter Reinholdtsen  * @intf:   ipmi interface handler
991c18ec02fSPetter Reinholdtsen  *
992c18ec02fSPetter Reinholdtsen  * returns 0 if no failure, -1 with a failure
993c18ec02fSPetter Reinholdtsen  */
994c18ec02fSPetter Reinholdtsen static int
ipmi_dcmi_prnt_getassettag(struct ipmi_intf * intf)995c18ec02fSPetter Reinholdtsen ipmi_dcmi_prnt_getassettag(struct ipmi_intf * intf)
996c18ec02fSPetter Reinholdtsen {
997c18ec02fSPetter Reinholdtsen 	struct ipmi_rs * rsp; /* ipmi response */
998c18ec02fSPetter Reinholdtsen 	uint8_t taglength = 0;
999c18ec02fSPetter Reinholdtsen 	uint8_t getlength = 0;
1000c18ec02fSPetter Reinholdtsen 	uint8_t offset = 0;
1001c18ec02fSPetter Reinholdtsen 	uint8_t i;
1002c18ec02fSPetter Reinholdtsen 	/* now let's get the asset tag length */
1003c18ec02fSPetter Reinholdtsen 	rsp = ipmi_dcmi_getassettag(intf, 0, 0);
1004c18ec02fSPetter Reinholdtsen 	if (chk_rsp(rsp)) {
1005c18ec02fSPetter Reinholdtsen 		return -1;
1006c18ec02fSPetter Reinholdtsen 	}
1007c18ec02fSPetter Reinholdtsen 	taglength = rsp->data[1];
1008c18ec02fSPetter Reinholdtsen 	printf("\n Asset tag: ");
1009c18ec02fSPetter Reinholdtsen 	while (taglength) {
1010c18ec02fSPetter Reinholdtsen 		getlength = taglength / DCMI_MAX_BYTE_SIZE ?
1011c18ec02fSPetter Reinholdtsen 			DCMI_MAX_BYTE_SIZE : taglength%DCMI_MAX_BYTE_SIZE;
1012c18ec02fSPetter Reinholdtsen 		rsp = ipmi_dcmi_getassettag(intf, offset, getlength);
1013c18ec02fSPetter Reinholdtsen 		/* macro has no effect here where can generate sig segv
1014c18ec02fSPetter Reinholdtsen 		 * if rsp occurs with null
1015c18ec02fSPetter Reinholdtsen 		 */
1016c18ec02fSPetter Reinholdtsen 		if (rsp != NULL) {
1017c18ec02fSPetter Reinholdtsen 			GOOD_ASSET_TAG_CCODE(rsp->ccode);
1018c18ec02fSPetter Reinholdtsen 		}
1019c18ec02fSPetter Reinholdtsen 		if (chk_rsp(rsp)) {
1020c18ec02fSPetter Reinholdtsen 			return -1;
1021c18ec02fSPetter Reinholdtsen 		}
1022c18ec02fSPetter Reinholdtsen 		for (i=0; i<getlength; i++) {
1023c18ec02fSPetter Reinholdtsen 			printf("%c", rsp->data[i+2]);
1024c18ec02fSPetter Reinholdtsen 		}
1025c18ec02fSPetter Reinholdtsen 		offset += getlength;
1026c18ec02fSPetter Reinholdtsen 		taglength -= getlength;
1027c18ec02fSPetter Reinholdtsen 	}
1028c18ec02fSPetter Reinholdtsen 	printf("\n");
1029c18ec02fSPetter Reinholdtsen 	return 0;
1030c18ec02fSPetter Reinholdtsen }
1031c18ec02fSPetter Reinholdtsen 
1032c18ec02fSPetter Reinholdtsen /* This is the set asset tag command.  This checks the length of the asset tag
1033c18ec02fSPetter Reinholdtsen  * with the first read, then reads n number of bytes thereafter to set the
1034c18ec02fSPetter Reinholdtsen  * complete asset tag.
1035c18ec02fSPetter Reinholdtsen  *
1036c18ec02fSPetter Reinholdtsen  * @intf:   ipmi interface handler
1037c18ec02fSPetter Reinholdtsen  * @offset: offset to write
1038c18ec02fSPetter Reinholdtsen  * @length: number of bytes to write (16 bytes maximum)
1039c18ec02fSPetter Reinholdtsen  * @data:   data to write
1040c18ec02fSPetter Reinholdtsen  *
1041c18ec02fSPetter Reinholdtsen  * returns ipmi_rs structure
1042c18ec02fSPetter Reinholdtsen  */
1043c18ec02fSPetter Reinholdtsen struct ipmi_rs *
ipmi_dcmi_setassettag(struct ipmi_intf * intf,uint8_t offset,uint8_t length,uint8_t * data)1044c18ec02fSPetter Reinholdtsen ipmi_dcmi_setassettag(struct ipmi_intf * intf, uint8_t offset, uint8_t length,
1045c18ec02fSPetter Reinholdtsen 		uint8_t *data)
1046c18ec02fSPetter Reinholdtsen {
1047c18ec02fSPetter Reinholdtsen 	struct ipmi_rq req; /* request data to send to the BMC */
1048c18ec02fSPetter Reinholdtsen 	uint8_t msg_data[3+length]; /* 'raw' data to be sent to the BMC */
1049c18ec02fSPetter Reinholdtsen 
1050c18ec02fSPetter Reinholdtsen 	msg_data[0] = IPMI_DCMI; /* Group Extension Identification */
1051c18ec02fSPetter Reinholdtsen 	msg_data[1] = offset; /* offset 0 */
1052c18ec02fSPetter Reinholdtsen 	msg_data[2] = length; /* read one byte */
1053c18ec02fSPetter Reinholdtsen 
1054c18ec02fSPetter Reinholdtsen 	memset(&req, 0, sizeof(req));
1055c18ec02fSPetter Reinholdtsen 	req.msg.netfn = IPMI_NETFN_DCGRP; /* 0x2C per 1.1 spec */
1056c18ec02fSPetter Reinholdtsen 	req.msg.cmd = IPMI_DCMI_SETASSET; /* 0x08 per 1.1 spec */
1057c18ec02fSPetter Reinholdtsen 	req.msg.data = msg_data; /* msg_data above */
1058c18ec02fSPetter Reinholdtsen 	/* How many times does req.msg.data need to read */
1059c18ec02fSPetter Reinholdtsen 	req.msg.data_len = length + 3;
1060c18ec02fSPetter Reinholdtsen 	memcpy(req.msg.data + 3, data, length);
1061c18ec02fSPetter Reinholdtsen 
1062c18ec02fSPetter Reinholdtsen 	return intf->sendrecv(intf, &req);
1063c18ec02fSPetter Reinholdtsen }
1064c18ec02fSPetter Reinholdtsen 
1065c18ec02fSPetter Reinholdtsen static int
ipmi_dcmi_prnt_setassettag(struct ipmi_intf * intf,uint8_t * data)1066c18ec02fSPetter Reinholdtsen ipmi_dcmi_prnt_setassettag(struct ipmi_intf * intf, uint8_t * data)
1067c18ec02fSPetter Reinholdtsen {
1068c18ec02fSPetter Reinholdtsen 	struct ipmi_rs * rsp; /* ipmi response */
1069c18ec02fSPetter Reinholdtsen 	uint8_t tmpData[DCMI_MAX_BYTE_SIZE];
1070fd5fdc59SPat Donlin 	int32_t taglength = 0;
1071c18ec02fSPetter Reinholdtsen 	uint8_t getlength = 0;
1072c18ec02fSPetter Reinholdtsen 	uint8_t offset = 0;
1073c18ec02fSPetter Reinholdtsen 	uint8_t i;
1074c18ec02fSPetter Reinholdtsen 
1075c18ec02fSPetter Reinholdtsen 	/* now let's get the asset tag length */
1076fd5fdc59SPat Donlin 	taglength = strlen((char *)data);
1077c18ec02fSPetter Reinholdtsen 	if (taglength > 64){
1078c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "\nValue is too long.");
1079c18ec02fSPetter Reinholdtsen 		return -1;
1080c18ec02fSPetter Reinholdtsen 	}
1081c18ec02fSPetter Reinholdtsen 	printf("\n Set Asset Tag: ");
1082c18ec02fSPetter Reinholdtsen 	while (taglength) {
1083c18ec02fSPetter Reinholdtsen 		getlength = taglength / DCMI_MAX_BYTE_SIZE ?
1084c18ec02fSPetter Reinholdtsen 			DCMI_MAX_BYTE_SIZE : taglength%DCMI_MAX_BYTE_SIZE;
1085c18ec02fSPetter Reinholdtsen 		memcpy(tmpData, data + offset, getlength);
1086c18ec02fSPetter Reinholdtsen 		rsp = ipmi_dcmi_setassettag(intf, offset, getlength, tmpData);
1087c18ec02fSPetter Reinholdtsen 		if (chk_rsp(rsp)) {
1088c18ec02fSPetter Reinholdtsen 			return -1;
1089c18ec02fSPetter Reinholdtsen 		}
1090c18ec02fSPetter Reinholdtsen 		for (i=0; i<getlength; i++) {
1091c18ec02fSPetter Reinholdtsen 			printf("%c", tmpData[i]);
1092c18ec02fSPetter Reinholdtsen 		}
1093c18ec02fSPetter Reinholdtsen 		offset += getlength;
1094c18ec02fSPetter Reinholdtsen 		taglength -= getlength;
1095c18ec02fSPetter Reinholdtsen 	}
1096c18ec02fSPetter Reinholdtsen 	printf("\n");
1097c18ec02fSPetter Reinholdtsen 	return 0;
1098c18ec02fSPetter Reinholdtsen }
1099c18ec02fSPetter Reinholdtsen 
1100c18ec02fSPetter Reinholdtsen /* Management Controller Identifier String is provided in order to accommodate
1101c18ec02fSPetter Reinholdtsen  * the requirement for the management controllers to identify themselves.
1102c18ec02fSPetter Reinholdtsen  *
1103c18ec02fSPetter Reinholdtsen  * @intf:   ipmi interface handler
1104c18ec02fSPetter Reinholdtsen  * @offset: offset to read
1105c18ec02fSPetter Reinholdtsen  * @length: number of bytes to read (16 bytes maximum)
1106c18ec02fSPetter Reinholdtsen  *
1107c18ec02fSPetter Reinholdtsen  * returns ipmi_rs structure
1108c18ec02fSPetter Reinholdtsen  */
1109c18ec02fSPetter Reinholdtsen struct ipmi_rs *
ipmi_dcmi_getmngctrlids(struct ipmi_intf * intf,uint8_t offset,uint8_t length)1110c18ec02fSPetter Reinholdtsen ipmi_dcmi_getmngctrlids(struct ipmi_intf * intf, uint8_t offset, uint8_t length)
1111c18ec02fSPetter Reinholdtsen {
1112c18ec02fSPetter Reinholdtsen 	struct ipmi_rq req; /* request data to send to the BMC */
1113c18ec02fSPetter Reinholdtsen 	uint8_t msg_data[3]; /* 'raw' data to be sent to the BMC */
1114c18ec02fSPetter Reinholdtsen 
1115c18ec02fSPetter Reinholdtsen 	msg_data[0] = IPMI_DCMI; /* Group Extension Identification */
1116c18ec02fSPetter Reinholdtsen 	msg_data[1] = offset; /* offset 0 */
1117c18ec02fSPetter Reinholdtsen 	msg_data[2] = length; /* read one byte */
1118c18ec02fSPetter Reinholdtsen 
1119c18ec02fSPetter Reinholdtsen 	memset(&req, 0, sizeof(req));
1120c18ec02fSPetter Reinholdtsen 	req.msg.netfn = IPMI_NETFN_DCGRP; /* 0x2C per 1.1 spec */
1121c18ec02fSPetter Reinholdtsen 	req.msg.cmd = IPMI_DCMI_GETMNGCTRLIDS; /* 0x09 per 1.1 spec */
1122c18ec02fSPetter Reinholdtsen 	req.msg.data = msg_data; /* msg_data above */
1123c18ec02fSPetter Reinholdtsen 	/* How many times does req.msg.data need to read */
1124c18ec02fSPetter Reinholdtsen 	req.msg.data_len = 3;
1125c18ec02fSPetter Reinholdtsen 	return intf->sendrecv(intf, &req);
1126c18ec02fSPetter Reinholdtsen }
1127c18ec02fSPetter Reinholdtsen 
1128c18ec02fSPetter Reinholdtsen static int
ipmi_dcmi_prnt_getmngctrlids(struct ipmi_intf * intf)1129c18ec02fSPetter Reinholdtsen ipmi_dcmi_prnt_getmngctrlids(struct ipmi_intf * intf)
1130c18ec02fSPetter Reinholdtsen {
1131c18ec02fSPetter Reinholdtsen 	struct ipmi_rs * rsp; /* ipmi response */
1132c18ec02fSPetter Reinholdtsen 	uint8_t taglength = 0;
1133c18ec02fSPetter Reinholdtsen 	uint8_t getlength = 0;
1134c18ec02fSPetter Reinholdtsen 	uint8_t offset = 0;
1135c18ec02fSPetter Reinholdtsen 	uint8_t i;
1136c18ec02fSPetter Reinholdtsen 
1137c18ec02fSPetter Reinholdtsen 	/* now let's get the asset tag length */
1138c18ec02fSPetter Reinholdtsen 	rsp = ipmi_dcmi_getmngctrlids(intf, 0, 1);
1139c18ec02fSPetter Reinholdtsen 
1140c18ec02fSPetter Reinholdtsen 	if (chk_rsp(rsp)) {
1141c18ec02fSPetter Reinholdtsen 		return -1;
1142c18ec02fSPetter Reinholdtsen 	}
1143c18ec02fSPetter Reinholdtsen 
1144c18ec02fSPetter Reinholdtsen 	taglength = rsp->data[1];
1145c18ec02fSPetter Reinholdtsen 
1146c18ec02fSPetter Reinholdtsen 	printf("\n Get Management Controller Identifier String: ");
1147c18ec02fSPetter Reinholdtsen 	while (taglength) {
1148c18ec02fSPetter Reinholdtsen 		getlength = taglength / DCMI_MAX_BYTE_SIZE ?
1149c18ec02fSPetter Reinholdtsen 			DCMI_MAX_BYTE_SIZE : taglength%DCMI_MAX_BYTE_SIZE;
1150c18ec02fSPetter Reinholdtsen 		rsp = ipmi_dcmi_getmngctrlids(intf, offset, getlength);
1151c18ec02fSPetter Reinholdtsen 
1152c18ec02fSPetter Reinholdtsen 		if (chk_rsp(rsp)) {
1153c18ec02fSPetter Reinholdtsen 			return -1;
1154c18ec02fSPetter Reinholdtsen 		}
1155c18ec02fSPetter Reinholdtsen 		for (i=0; i<getlength; i++) {
1156c18ec02fSPetter Reinholdtsen 			printf("%c", rsp->data[i+2]);
1157c18ec02fSPetter Reinholdtsen 		}
1158c18ec02fSPetter Reinholdtsen 		offset += getlength;
1159c18ec02fSPetter Reinholdtsen 		taglength -= getlength;
1160c18ec02fSPetter Reinholdtsen 	}
1161c18ec02fSPetter Reinholdtsen 	printf("\n");
1162c18ec02fSPetter Reinholdtsen 	return 0;
1163c18ec02fSPetter Reinholdtsen }
1164c18ec02fSPetter Reinholdtsen 
1165c18ec02fSPetter Reinholdtsen /* Management Controller Identifier String is provided in order to accommodate
1166c18ec02fSPetter Reinholdtsen  * the requirement for the management controllers to identify themselves.
1167c18ec02fSPetter Reinholdtsen  *
1168c18ec02fSPetter Reinholdtsen  * @intf:   ipmi interface handler
1169c18ec02fSPetter Reinholdtsen  * @offset: offset to write
1170c18ec02fSPetter Reinholdtsen  * @length: number of bytes to write (16 bytes maximum)
1171c18ec02fSPetter Reinholdtsen  * @data:   data to write
1172c18ec02fSPetter Reinholdtsen  *
1173c18ec02fSPetter Reinholdtsen  * returns ipmi_rs structure
1174c18ec02fSPetter Reinholdtsen  */
1175c18ec02fSPetter Reinholdtsen struct ipmi_rs *
ipmi_dcmi_setmngctrlids(struct ipmi_intf * intf,uint8_t offset,uint8_t length,uint8_t * data)1176c18ec02fSPetter Reinholdtsen ipmi_dcmi_setmngctrlids(struct ipmi_intf * intf, uint8_t offset, uint8_t length,
1177c18ec02fSPetter Reinholdtsen 		uint8_t *data)
1178c18ec02fSPetter Reinholdtsen {
1179c18ec02fSPetter Reinholdtsen 	struct ipmi_rq req; /* request data to send to the BMC */
1180c18ec02fSPetter Reinholdtsen 	uint8_t msg_data[3+length]; /* 'raw' data to be sent to the BMC */
1181c18ec02fSPetter Reinholdtsen 
1182c18ec02fSPetter Reinholdtsen 	msg_data[0] = IPMI_DCMI; /* Group Extension Identification */
1183c18ec02fSPetter Reinholdtsen 	msg_data[1] = offset; /* offset 0 */
1184c18ec02fSPetter Reinholdtsen 	msg_data[2] = length; /* read one byte */
1185c18ec02fSPetter Reinholdtsen 
1186c18ec02fSPetter Reinholdtsen 	memset(&req, 0, sizeof(req));
1187c18ec02fSPetter Reinholdtsen 	req.msg.netfn = IPMI_NETFN_DCGRP; /* 0x2C per 1.1 spec */
1188c18ec02fSPetter Reinholdtsen 	req.msg.cmd = IPMI_DCMI_SETMNGCTRLIDS; /* 0x0A per 1.1 spec */
1189c18ec02fSPetter Reinholdtsen 	req.msg.data = msg_data; /* msg_data above */
1190c18ec02fSPetter Reinholdtsen 	/* How many times does req.msg.data need to read */
1191c18ec02fSPetter Reinholdtsen 	req.msg.data_len = 3 + length;
1192c18ec02fSPetter Reinholdtsen 	memcpy(req.msg.data + 3, data, length);
1193c18ec02fSPetter Reinholdtsen 
1194c18ec02fSPetter Reinholdtsen 	return intf->sendrecv(intf, &req);
1195c18ec02fSPetter Reinholdtsen }
1196c18ec02fSPetter Reinholdtsen 
1197c18ec02fSPetter Reinholdtsen /* Set Asset Tag command provides ability for the management console to set the
1198c18ec02fSPetter Reinholdtsen  * asset tag as appropriate. Management controller is not responsible for the
1199c18ec02fSPetter Reinholdtsen  * data format used for the Asset Tag once modified by IPDC.
1200c18ec02fSPetter Reinholdtsen  *
1201c18ec02fSPetter Reinholdtsen  * @intf:   ipmi interface handler
1202c18ec02fSPetter Reinholdtsen  *
1203c18ec02fSPetter Reinholdtsen  * returns 0 if no failure, -1 with a failure
1204c18ec02fSPetter Reinholdtsen  */
1205c18ec02fSPetter Reinholdtsen static int
ipmi_dcmi_prnt_setmngctrlids(struct ipmi_intf * intf,uint8_t * data)1206c18ec02fSPetter Reinholdtsen ipmi_dcmi_prnt_setmngctrlids(struct ipmi_intf * intf, uint8_t * data)
1207c18ec02fSPetter Reinholdtsen {
1208c18ec02fSPetter Reinholdtsen 	struct ipmi_rs * rsp; /* ipmi response */
1209c18ec02fSPetter Reinholdtsen 	uint8_t tmpData[DCMI_MAX_BYTE_SIZE];
1210c18ec02fSPetter Reinholdtsen 	uint8_t taglength = 0;
1211c18ec02fSPetter Reinholdtsen 	uint8_t getlength = 0;
1212c18ec02fSPetter Reinholdtsen 	uint8_t offset = 0;
1213c18ec02fSPetter Reinholdtsen 	uint8_t i;
1214c18ec02fSPetter Reinholdtsen 
1215c18ec02fSPetter Reinholdtsen 	data += '\0';
1216fd5fdc59SPat Donlin 	taglength = strlen((char *)data) +1;
1217c18ec02fSPetter Reinholdtsen 
1218c18ec02fSPetter Reinholdtsen 	if (taglength > 64) {
1219c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "\nValue is too long.");
1220c18ec02fSPetter Reinholdtsen 		return -1;
1221c18ec02fSPetter Reinholdtsen 	}
1222c18ec02fSPetter Reinholdtsen 
1223c18ec02fSPetter Reinholdtsen 	printf("\n Set Management Controller Identifier String Command: ");
1224c18ec02fSPetter Reinholdtsen 	while (taglength) {
1225c18ec02fSPetter Reinholdtsen 		getlength = taglength / DCMI_MAX_BYTE_SIZE ?
1226c18ec02fSPetter Reinholdtsen 			DCMI_MAX_BYTE_SIZE : taglength%DCMI_MAX_BYTE_SIZE;
1227c18ec02fSPetter Reinholdtsen 		memcpy(tmpData, data + offset, getlength);
1228c18ec02fSPetter Reinholdtsen 		rsp = ipmi_dcmi_setmngctrlids(intf, offset, getlength, tmpData);
1229c18ec02fSPetter Reinholdtsen 		/* because after call "Set mc id string" RMCP+ will go down
1230c18ec02fSPetter Reinholdtsen 		 * we have no "rsp"
1231c18ec02fSPetter Reinholdtsen 		 */
1232c18ec02fSPetter Reinholdtsen 		if (strncmp(intf->name, "lanplus", 7)) {
1233c18ec02fSPetter Reinholdtsen 			if (chk_rsp(rsp)) {
1234c18ec02fSPetter Reinholdtsen 				return -1;
1235c18ec02fSPetter Reinholdtsen 			}
1236c18ec02fSPetter Reinholdtsen 		}
1237c18ec02fSPetter Reinholdtsen 		for (i=0; i<getlength; i++) {
1238c18ec02fSPetter Reinholdtsen 			printf("%c", tmpData[i]);
1239c18ec02fSPetter Reinholdtsen 		}
1240c18ec02fSPetter Reinholdtsen 		offset += getlength;
1241c18ec02fSPetter Reinholdtsen 		taglength -= getlength;
1242c18ec02fSPetter Reinholdtsen 	}
1243c18ec02fSPetter Reinholdtsen 	printf("\n");
1244c18ec02fSPetter Reinholdtsen 	return 0;
1245c18ec02fSPetter Reinholdtsen }
1246c18ec02fSPetter Reinholdtsen 
1247c18ec02fSPetter Reinholdtsen /* Issues a discovery command to see what sensors are available on the target.
1248c18ec02fSPetter Reinholdtsen  * system.
1249c18ec02fSPetter Reinholdtsen  *
1250c18ec02fSPetter Reinholdtsen  * @intf:   ipmi interface handler
1251c18ec02fSPetter Reinholdtsen  * @isnsr:  entity ID
1252c18ec02fSPetter Reinholdtsen  * @offset:   offset (Entity instace start)
1253c18ec02fSPetter Reinholdtsen  *
1254c18ec02fSPetter Reinholdtsen  * returns ipmi_rs structure
1255c18ec02fSPetter Reinholdtsen  */
1256c18ec02fSPetter Reinholdtsen struct ipmi_rs *
ipmi_dcmi_discvry_snsr(struct ipmi_intf * intf,uint8_t isnsr,uint8_t offset)1257c18ec02fSPetter Reinholdtsen ipmi_dcmi_discvry_snsr(struct ipmi_intf * intf, uint8_t isnsr, uint8_t offset)
1258c18ec02fSPetter Reinholdtsen {
1259c18ec02fSPetter Reinholdtsen 	struct ipmi_rq req; /* ipmi request struct */
1260c18ec02fSPetter Reinholdtsen 	uint8_t msg_data[5]; /* number of request data bytes */
1261c18ec02fSPetter Reinholdtsen 
1262c18ec02fSPetter Reinholdtsen 	msg_data[0] = IPMI_DCMI; /* Group Extension Identification */
1263c18ec02fSPetter Reinholdtsen 	msg_data[1] = 0x01; /* Senser Type = Temp (01h) */
1264c18ec02fSPetter Reinholdtsen 	msg_data[2] = isnsr; /* Sensor Number */
1265c18ec02fSPetter Reinholdtsen 	msg_data[3] = 0x00; /* Entity Instance, set to read all instances */
1266c18ec02fSPetter Reinholdtsen 	msg_data[4] = offset; /* Entity instace start */
1267c18ec02fSPetter Reinholdtsen 
1268c18ec02fSPetter Reinholdtsen 	memset(&req, 0, sizeof(req));
1269c18ec02fSPetter Reinholdtsen 	req.msg.netfn = IPMI_NETFN_DCGRP;
1270c18ec02fSPetter Reinholdtsen 	req.msg.cmd = IPMI_DCMI_GETSNSR;
1271c18ec02fSPetter Reinholdtsen 	req.msg.data = msg_data; /* Contents above */
1272c18ec02fSPetter Reinholdtsen 	req.msg.data_len = 5; /* how many times does req.msg.data need to read */
1273c18ec02fSPetter Reinholdtsen 
1274c18ec02fSPetter Reinholdtsen 	return intf->sendrecv(intf, &req);
1275c18ec02fSPetter Reinholdtsen }
1276c18ec02fSPetter Reinholdtsen 
1277c18ec02fSPetter Reinholdtsen /* DCMI sensor discovery
1278c18ec02fSPetter Reinholdtsen  * Uses the dcmi_discvry_snsr_vals struct to print its string and
1279c18ec02fSPetter Reinholdtsen  * uses the numeric values to request the sensor sdr record id.
1280c18ec02fSPetter Reinholdtsen  *
1281c18ec02fSPetter Reinholdtsen  * @intf:   ipmi interface handler
1282c18ec02fSPetter Reinholdtsen  * @isnsr:  entity ID
1283c18ec02fSPetter Reinholdtsen  * @ient:   sensor entity id
1284c18ec02fSPetter Reinholdtsen  */
1285c18ec02fSPetter Reinholdtsen static int
ipmi_dcmi_prnt_discvry_snsr(struct ipmi_intf * intf,uint8_t isnsr)1286c18ec02fSPetter Reinholdtsen ipmi_dcmi_prnt_discvry_snsr(struct ipmi_intf * intf, uint8_t isnsr)
1287c18ec02fSPetter Reinholdtsen {
1288c18ec02fSPetter Reinholdtsen 	int i = 0;
1289c18ec02fSPetter Reinholdtsen 	struct ipmi_rs * rsp; /* ipmi response */
1290c18ec02fSPetter Reinholdtsen 	uint8_t records = 0;
1291c18ec02fSPetter Reinholdtsen 	int8_t instances = 0;
1292c18ec02fSPetter Reinholdtsen 	uint8_t offset = 0;
1293c18ec02fSPetter Reinholdtsen 	uint16_t record_id = 0;
1294c18ec02fSPetter Reinholdtsen 	uint8_t id_buff[16]; /* enough for 8 record IDs */
1295c18ec02fSPetter Reinholdtsen 	rsp = ipmi_dcmi_discvry_snsr(intf, isnsr, 0);
1296c18ec02fSPetter Reinholdtsen 	if (chk_rsp(rsp)) {
1297c18ec02fSPetter Reinholdtsen 		return -1;
1298c18ec02fSPetter Reinholdtsen 	}
1299c18ec02fSPetter Reinholdtsen 	instances = rsp->data[1];
1300c18ec02fSPetter Reinholdtsen 	printf("\n%s: %d temperature sensor%s found:\n",
1301c18ec02fSPetter Reinholdtsen 			val2str2(isnsr, dcmi_discvry_snsr_vals),
1302c18ec02fSPetter Reinholdtsen 			instances,
1303c18ec02fSPetter Reinholdtsen 			(instances > 1) ? "s" : "");
1304c18ec02fSPetter Reinholdtsen 	while(instances > 0) {
1305c18ec02fSPetter Reinholdtsen 		ipmi_dcmi_discvry_snsr(intf, isnsr, offset);
1306c18ec02fSPetter Reinholdtsen 		if (chk_rsp(rsp)) {
1307c18ec02fSPetter Reinholdtsen 			return -1;
1308c18ec02fSPetter Reinholdtsen 		}
1309c18ec02fSPetter Reinholdtsen 		records = rsp->data[2];
1310c18ec02fSPetter Reinholdtsen 		/* cache the data since it may be destroyed by subsequent
1311c18ec02fSPetter Reinholdtsen 		 * ipmi_xxx calls
1312c18ec02fSPetter Reinholdtsen 		 */
1313fd5fdc59SPat Donlin 		memcpy(id_buff, &rsp->data[3], sizeof (id_buff));
1314c18ec02fSPetter Reinholdtsen 		for (i=0; i<records; i++) {
1315c18ec02fSPetter Reinholdtsen 			/* Record ID is in little endian format */
1316c18ec02fSPetter Reinholdtsen 			record_id = (id_buff[2*i + 1] << 8) + id_buff[2*i];
1317c18ec02fSPetter Reinholdtsen 			printf("Record ID 0x%04x: ", record_id);
1318c18ec02fSPetter Reinholdtsen 			ipmi_print_sensor_info(intf, record_id);
1319c18ec02fSPetter Reinholdtsen 		}
1320c18ec02fSPetter Reinholdtsen 		offset += 8;
1321c18ec02fSPetter Reinholdtsen 		instances -= records;
1322c18ec02fSPetter Reinholdtsen 	}
1323c18ec02fSPetter Reinholdtsen 	return 0;
1324c18ec02fSPetter Reinholdtsen }
1325c18ec02fSPetter Reinholdtsen /* end sensor discovery */
1326c18ec02fSPetter Reinholdtsen 
1327c18ec02fSPetter Reinholdtsen /* Power Management get power reading
1328c18ec02fSPetter Reinholdtsen  *
1329c18ec02fSPetter Reinholdtsen  * @intf:   ipmi interface handler
1330c18ec02fSPetter Reinholdtsen  */
1331c18ec02fSPetter Reinholdtsen static int
ipmi_dcmi_pwr_rd(struct ipmi_intf * intf,uint8_t sample_time)1332fd5fdc59SPat Donlin ipmi_dcmi_pwr_rd(struct ipmi_intf * intf, uint8_t sample_time)
1333c18ec02fSPetter Reinholdtsen {
1334c18ec02fSPetter Reinholdtsen 	struct ipmi_rs * rsp;
1335c18ec02fSPetter Reinholdtsen 	struct ipmi_rq req;
1336c18ec02fSPetter Reinholdtsen 	struct power_reading val;
1337c18ec02fSPetter Reinholdtsen 	struct tm tm_t;
1338c18ec02fSPetter Reinholdtsen 	time_t t;
1339c18ec02fSPetter Reinholdtsen 	uint8_t msg_data[4]; /* number of request data bytes */
1340c18ec02fSPetter Reinholdtsen 	memset(&tm_t, 0, sizeof(tm_t));
1341c18ec02fSPetter Reinholdtsen 	memset(&t, 0, sizeof(t));
1342c18ec02fSPetter Reinholdtsen 
1343c18ec02fSPetter Reinholdtsen 	msg_data[0] = IPMI_DCMI; /* Group Extension Identification */
1344fd5fdc59SPat Donlin 	if (sample_time) {
1345fd5fdc59SPat Donlin 		msg_data[1] = 0x02; /* Enhanced Power Statistics */
1346fd5fdc59SPat Donlin 		msg_data[2] = sample_time;
1347fd5fdc59SPat Donlin 	} else {
1348c18ec02fSPetter Reinholdtsen 		msg_data[1] = 0x01; /* Mode Power Status */
1349c18ec02fSPetter Reinholdtsen 		msg_data[2] = 0x00; /* reserved */
1350fd5fdc59SPat Donlin 	}
1351c18ec02fSPetter Reinholdtsen 	msg_data[3] = 0x00; /* reserved */
1352c18ec02fSPetter Reinholdtsen 
1353c18ec02fSPetter Reinholdtsen 	memset(&req, 0, sizeof(req));
1354c18ec02fSPetter Reinholdtsen 	req.msg.netfn = IPMI_NETFN_DCGRP;
1355c18ec02fSPetter Reinholdtsen 	req.msg.cmd = IPMI_DCMI_GETRED; /* Get power reading */
1356c18ec02fSPetter Reinholdtsen 	req.msg.data = msg_data; /* msg_data above */
1357c18ec02fSPetter Reinholdtsen 	req.msg.data_len = 4; /* how many times does req.msg.data need to read */
1358c18ec02fSPetter Reinholdtsen 
1359c18ec02fSPetter Reinholdtsen 	rsp = intf->sendrecv(intf, &req);
1360c18ec02fSPetter Reinholdtsen 
1361c18ec02fSPetter Reinholdtsen 	if (chk_rsp(rsp)) {
1362c18ec02fSPetter Reinholdtsen 		return -1;
1363c18ec02fSPetter Reinholdtsen 	}
1364c18ec02fSPetter Reinholdtsen 	/* rsp->data[0] is equal to response data byte 2 in spec */
1365c18ec02fSPetter Reinholdtsen 	/* printf("Group Extension Identification: %02x\n", rsp->data[0]); */
1366c18ec02fSPetter Reinholdtsen 	memcpy(&val, rsp->data, sizeof (val));
1367c18ec02fSPetter Reinholdtsen 	t = val.time_stamp;
1368c18ec02fSPetter Reinholdtsen 	gmtime_r(&t, &tm_t);
1369c18ec02fSPetter Reinholdtsen 	printf("\n");
1370c18ec02fSPetter Reinholdtsen 	printf("    Instantaneous power reading:              %8d Watts\n",
1371c18ec02fSPetter Reinholdtsen 			val.curr_pwr);
1372c18ec02fSPetter Reinholdtsen 	printf("    Minimum during sampling period:           %8d Watts\n",
1373c18ec02fSPetter Reinholdtsen 			val.min_sample);
1374c18ec02fSPetter Reinholdtsen 	printf("    Maximum during sampling period:           %8d Watts\n",
1375c18ec02fSPetter Reinholdtsen 			val.max_sample);
1376c18ec02fSPetter Reinholdtsen 	printf("    Average power reading over sample period: %8d Watts\n",
1377c18ec02fSPetter Reinholdtsen 			val.avg_pwr);
1378c18ec02fSPetter Reinholdtsen 	printf("    IPMI timestamp:                           %s",
1379c18ec02fSPetter Reinholdtsen 			asctime(&tm_t));
1380fd5fdc59SPat Donlin 	printf("    Sampling period:                          ");
1381fd5fdc59SPat Donlin 	if (sample_time)
1382fd5fdc59SPat Donlin 		printf("%s \n", val2str2(val.sample,dcmi_sampling_vals));
1383fd5fdc59SPat Donlin 	else
1384fd5fdc59SPat Donlin 		printf("%08u Seconds.\n", val.sample/1000);
1385c18ec02fSPetter Reinholdtsen 	printf("    Power reading state is:                   ");
1386c18ec02fSPetter Reinholdtsen 	/* mask the rsp->data so that we only care about bit 6 */
1387c18ec02fSPetter Reinholdtsen 	if((val.state & 0x40) == 0x40) {
1388c18ec02fSPetter Reinholdtsen 		printf("activated");
1389c18ec02fSPetter Reinholdtsen 	} else {
1390c18ec02fSPetter Reinholdtsen 		printf("deactivated");
1391c18ec02fSPetter Reinholdtsen 	}
1392c18ec02fSPetter Reinholdtsen 	printf("\n\n");
1393c18ec02fSPetter Reinholdtsen 	return 0;
1394c18ec02fSPetter Reinholdtsen }
1395c18ec02fSPetter Reinholdtsen /* end Power Management get reading */
1396c18ec02fSPetter Reinholdtsen 
1397c18ec02fSPetter Reinholdtsen 
1398c18ec02fSPetter Reinholdtsen /* This is the get thermalpolicy command.
1399c18ec02fSPetter Reinholdtsen  *
1400c18ec02fSPetter Reinholdtsen  * @intf:   ipmi interface handler
1401c18ec02fSPetter Reinholdtsen  */
1402c18ec02fSPetter Reinholdtsen int
ipmi_dcmi_getthermalpolicy(struct ipmi_intf * intf,uint8_t entityID,uint8_t entityInstance)1403c18ec02fSPetter Reinholdtsen ipmi_dcmi_getthermalpolicy(struct ipmi_intf * intf, uint8_t entityID,
1404c18ec02fSPetter Reinholdtsen 		uint8_t entityInstance)
1405c18ec02fSPetter Reinholdtsen {
1406c18ec02fSPetter Reinholdtsen 	struct ipmi_rs * rsp;
1407c18ec02fSPetter Reinholdtsen 	struct ipmi_rq req;
1408c18ec02fSPetter Reinholdtsen 	struct thermal_limit val;
1409c18ec02fSPetter Reinholdtsen 	uint8_t msg_data[3]; /* number of request data bytes */
1410c18ec02fSPetter Reinholdtsen 
1411c18ec02fSPetter Reinholdtsen 	msg_data[0] = IPMI_DCMI; /* Group Extension Identification */
1412c18ec02fSPetter Reinholdtsen 	msg_data[1] = entityID; /* Inlet Temperature DCMI ID*/
1413c18ec02fSPetter Reinholdtsen 	msg_data[2] = entityInstance; /* Entity Instance */
1414c18ec02fSPetter Reinholdtsen 
1415c18ec02fSPetter Reinholdtsen 	memset(&req, 0, sizeof(req));
1416c18ec02fSPetter Reinholdtsen 	req.msg.netfn = IPMI_NETFN_DCGRP;
1417c18ec02fSPetter Reinholdtsen 	req.msg.cmd = IPMI_DCMI_GETTERMALLIMIT; /* Get thermal policy reading */
1418c18ec02fSPetter Reinholdtsen 	req.msg.data = msg_data; /* msg_data above */
1419c18ec02fSPetter Reinholdtsen 	req.msg.data_len = 3; /* how many times does req.msg.data need to read */
1420c18ec02fSPetter Reinholdtsen 
1421c18ec02fSPetter Reinholdtsen 	rsp = intf->sendrecv(intf, &req);
1422c18ec02fSPetter Reinholdtsen 
1423c18ec02fSPetter Reinholdtsen 	if (chk_rsp(rsp)) {
1424c18ec02fSPetter Reinholdtsen 		return -1;
1425c18ec02fSPetter Reinholdtsen 	}
1426c18ec02fSPetter Reinholdtsen 	/* rsp->data[0] is equal to response data byte 2 in spec */
1427c18ec02fSPetter Reinholdtsen 	memcpy(&val, rsp->data, sizeof (val));
1428c18ec02fSPetter Reinholdtsen 	printf("\n");
1429c18ec02fSPetter Reinholdtsen 	printf("    Persistance flag is:                      %s\n",
1430c18ec02fSPetter Reinholdtsen 			((val.exceptionActions & 0x80) ? "set" : "notset"));
1431c18ec02fSPetter Reinholdtsen 	printf("    Exception Actions, taken if the Temperature Limit exceeded:\n");
1432c18ec02fSPetter Reinholdtsen 	printf("        Hard Power Off system and log event:  %s\n",
1433c18ec02fSPetter Reinholdtsen 			((val.exceptionActions & 0x40) ? "active":"inactive"));
1434c18ec02fSPetter Reinholdtsen 	printf("        Log event to SEL only:                %s\n",
1435c18ec02fSPetter Reinholdtsen 			((val.exceptionActions & 0x20) ? "active":"inactive"));
1436c18ec02fSPetter Reinholdtsen 	printf("    Temperature Limit                         %d degrees\n",
1437c18ec02fSPetter Reinholdtsen 			val.tempLimit);
1438c18ec02fSPetter Reinholdtsen 	printf("    Exception Time                            %d seconds\n",
1439c18ec02fSPetter Reinholdtsen 			val.exceptionTime);
1440c18ec02fSPetter Reinholdtsen 	printf("\n\n");
1441c18ec02fSPetter Reinholdtsen 	return 0;
1442c18ec02fSPetter Reinholdtsen }
1443c18ec02fSPetter Reinholdtsen 
1444c18ec02fSPetter Reinholdtsen /* This is the set thermalpolicy command.
1445c18ec02fSPetter Reinholdtsen  *
1446c18ec02fSPetter Reinholdtsen  * @intf:   ipmi interface handler
1447c18ec02fSPetter Reinholdtsen  */
1448c18ec02fSPetter Reinholdtsen int
ipmi_dcmi_setthermalpolicy(struct ipmi_intf * intf,uint8_t entityID,uint8_t entityInst,uint8_t persistanceFlag,uint8_t actionHardPowerOff,uint8_t actionLogToSEL,uint8_t tempLimit,uint8_t samplingTimeLSB,uint8_t samplingTimeMSB)1449c18ec02fSPetter Reinholdtsen ipmi_dcmi_setthermalpolicy(struct ipmi_intf * intf,
1450c18ec02fSPetter Reinholdtsen 		uint8_t entityID,
1451c18ec02fSPetter Reinholdtsen 		uint8_t entityInst,
1452c18ec02fSPetter Reinholdtsen 		uint8_t persistanceFlag,
1453c18ec02fSPetter Reinholdtsen 		uint8_t actionHardPowerOff,
1454c18ec02fSPetter Reinholdtsen 		uint8_t actionLogToSEL,
1455c18ec02fSPetter Reinholdtsen 		uint8_t tempLimit,
1456c18ec02fSPetter Reinholdtsen 		uint8_t samplingTimeLSB,
1457c18ec02fSPetter Reinholdtsen 		uint8_t samplingTimeMSB)
1458c18ec02fSPetter Reinholdtsen {
1459c18ec02fSPetter Reinholdtsen 	struct ipmi_rs * rsp;
1460c18ec02fSPetter Reinholdtsen 	struct ipmi_rq req;
1461c18ec02fSPetter Reinholdtsen 	uint8_t msg_data[7]; /* number of request data bytes */
1462c18ec02fSPetter Reinholdtsen 
1463c18ec02fSPetter Reinholdtsen 	msg_data[0] = IPMI_DCMI; /* Group Extension Identification */
1464c18ec02fSPetter Reinholdtsen 	msg_data[1] = entityID; /* Inlet Temperature DCMI ID*/
1465c18ec02fSPetter Reinholdtsen 	msg_data[2] = entityInst; /* Entity Instance */
1466c18ec02fSPetter Reinholdtsen 	/* persistance and actions or disabled if no actions */
1467c18ec02fSPetter Reinholdtsen 	msg_data[3] = (((persistanceFlag ? 1 : 0) << 7) |
1468c18ec02fSPetter Reinholdtsen 			((actionHardPowerOff? 1 : 0) << 6) |
1469c18ec02fSPetter Reinholdtsen 			((actionLogToSEL ? 1 : 0) << 5));
1470c18ec02fSPetter Reinholdtsen 	msg_data[4] = tempLimit;
1471c18ec02fSPetter Reinholdtsen 	msg_data[5] = samplingTimeLSB;
1472c18ec02fSPetter Reinholdtsen 	msg_data[6] = samplingTimeMSB;
1473c18ec02fSPetter Reinholdtsen 
1474c18ec02fSPetter Reinholdtsen 	memset(&req, 0, sizeof(req));
1475c18ec02fSPetter Reinholdtsen 	req.msg.netfn = IPMI_NETFN_DCGRP;
1476c18ec02fSPetter Reinholdtsen 	/* Get thermal policy reading */
1477c18ec02fSPetter Reinholdtsen 	req.msg.cmd = IPMI_DCMI_SETTERMALLIMIT;
1478c18ec02fSPetter Reinholdtsen 	req.msg.data = msg_data; /* msg_data above */
1479c18ec02fSPetter Reinholdtsen 	/* how many times does req.msg.data need to read */
1480c18ec02fSPetter Reinholdtsen 	req.msg.data_len = 7;
1481c18ec02fSPetter Reinholdtsen 
1482c18ec02fSPetter Reinholdtsen 	rsp = intf->sendrecv(intf, &req);
1483c18ec02fSPetter Reinholdtsen 	if (chk_rsp(rsp)) {
1484c18ec02fSPetter Reinholdtsen 		return -1;
1485c18ec02fSPetter Reinholdtsen 	}
1486c18ec02fSPetter Reinholdtsen 	/* rsp->data[0] is equal to response data byte 2 in spec */
1487c18ec02fSPetter Reinholdtsen 	printf("\nThermal policy %d for %0Xh entity successfully set.\n\n",
1488c18ec02fSPetter Reinholdtsen 			entityInst, entityID);
1489c18ec02fSPetter Reinholdtsen 	return 0;
1490c18ec02fSPetter Reinholdtsen }
1491c18ec02fSPetter Reinholdtsen 
1492c18ec02fSPetter Reinholdtsen /* This is Get Temperature Readings Command
1493c18ec02fSPetter Reinholdtsen  *
1494c18ec02fSPetter Reinholdtsen  * returns ipmi response structure
1495c18ec02fSPetter Reinholdtsen  *
1496c18ec02fSPetter Reinholdtsen  * @intf:   ipmi interface handler
1497c18ec02fSPetter Reinholdtsen  */
1498c18ec02fSPetter Reinholdtsen struct ipmi_rs *
ipmi_dcmi_get_temp_readings(struct ipmi_intf * intf,uint8_t entityID,uint8_t entityInst,uint8_t entityInstStart)1499c18ec02fSPetter Reinholdtsen ipmi_dcmi_get_temp_readings(struct ipmi_intf * intf,
1500c18ec02fSPetter Reinholdtsen 		uint8_t entityID,
1501c18ec02fSPetter Reinholdtsen 		uint8_t entityInst,
1502c18ec02fSPetter Reinholdtsen 		uint8_t entityInstStart)
1503c18ec02fSPetter Reinholdtsen {
1504c18ec02fSPetter Reinholdtsen 	struct ipmi_rq req;
1505c18ec02fSPetter Reinholdtsen 	uint8_t msg_data[5]; /* number of request data bytes */
1506c18ec02fSPetter Reinholdtsen 
1507c18ec02fSPetter Reinholdtsen 	msg_data[0] = IPMI_DCMI; /* Group Extension Identification */
1508c18ec02fSPetter Reinholdtsen 	msg_data[1] = 0x01; /* Sensor type */
1509c18ec02fSPetter Reinholdtsen 	msg_data[2] = entityID; /* Entity Instance */
1510c18ec02fSPetter Reinholdtsen 	msg_data[3] = entityInst;
1511c18ec02fSPetter Reinholdtsen 	msg_data[4] = entityInstStart;
1512c18ec02fSPetter Reinholdtsen 
1513c18ec02fSPetter Reinholdtsen 	memset(&req, 0, sizeof(req));
1514c18ec02fSPetter Reinholdtsen 	req.msg.netfn = IPMI_NETFN_DCGRP;
1515c18ec02fSPetter Reinholdtsen 	req.msg.cmd = IPMI_DCMI_GETTEMPRED; /* Get thermal policy reading */
1516c18ec02fSPetter Reinholdtsen 	req.msg.data = msg_data; /* msg_data above */
1517c18ec02fSPetter Reinholdtsen 	/* how many times does req.msg.data need to read */
1518c18ec02fSPetter Reinholdtsen 	req.msg.data_len = 5;
1519c18ec02fSPetter Reinholdtsen 	return intf->sendrecv(intf, &req);
1520c18ec02fSPetter Reinholdtsen }
1521c18ec02fSPetter Reinholdtsen 
1522c18ec02fSPetter Reinholdtsen static int
ipmi_dcmi_prnt_get_temp_readings(struct ipmi_intf * intf)1523c18ec02fSPetter Reinholdtsen ipmi_dcmi_prnt_get_temp_readings(struct ipmi_intf * intf)
1524c18ec02fSPetter Reinholdtsen {
1525c18ec02fSPetter Reinholdtsen 	struct ipmi_rs * rsp;
1526c18ec02fSPetter Reinholdtsen 	int i,j, tota_inst, get_inst, offset = 0;
1527c18ec02fSPetter Reinholdtsen 	/* Print sensor description */
1528c18ec02fSPetter Reinholdtsen 	printf("\n\tEntity ID\t\t\tEntity Instance\t   Temp. Readings");
1529c18ec02fSPetter Reinholdtsen 	for (i = 0; dcmi_temp_read_vals[i].str != NULL; i++) {
1530c18ec02fSPetter Reinholdtsen 		/* get all of the information about this sensor */
1531c18ec02fSPetter Reinholdtsen 		rsp = ipmi_dcmi_get_temp_readings(intf,
1532c18ec02fSPetter Reinholdtsen 				dcmi_temp_read_vals[i].val, 0, 0);
1533c18ec02fSPetter Reinholdtsen 		if (chk_rsp(rsp)) {
1534c18ec02fSPetter Reinholdtsen 			continue;
1535c18ec02fSPetter Reinholdtsen 		}
1536c18ec02fSPetter Reinholdtsen 		/* Total number of available instances for the Entity ID */
1537c18ec02fSPetter Reinholdtsen 		offset = 0;
1538c18ec02fSPetter Reinholdtsen 		tota_inst = rsp->data[1];
1539c18ec02fSPetter Reinholdtsen 		while (tota_inst > 0) {
1540c18ec02fSPetter Reinholdtsen 			get_inst = ((tota_inst / DCMI_MAX_BYTE_TEMP_READ_SIZE) ?
1541c18ec02fSPetter Reinholdtsen 					DCMI_MAX_BYTE_TEMP_READ_SIZE :
1542c18ec02fSPetter Reinholdtsen 					(tota_inst % DCMI_MAX_BYTE_TEMP_READ_SIZE));
1543c18ec02fSPetter Reinholdtsen 			rsp = ipmi_dcmi_get_temp_readings(intf,
1544c18ec02fSPetter Reinholdtsen 					dcmi_temp_read_vals[i].val, offset, 0);
1545c18ec02fSPetter Reinholdtsen 			if (chk_rsp(rsp)) {
1546c18ec02fSPetter Reinholdtsen 				continue;
1547c18ec02fSPetter Reinholdtsen 			}
1548c18ec02fSPetter Reinholdtsen 			/* Number of sets of Temperature Data in this
1549c18ec02fSPetter Reinholdtsen 			 * response (Max 8 per response)
1550c18ec02fSPetter Reinholdtsen 			 */
1551c18ec02fSPetter Reinholdtsen 			for (j=0; j < rsp->data[2]*2; j=j+2) {
1552c18ec02fSPetter Reinholdtsen 				/* Print Instance temperature info */
1553c18ec02fSPetter Reinholdtsen 				printf("\n%s",dcmi_temp_read_vals[i].desc);
1554c18ec02fSPetter Reinholdtsen 				printf("\t\t%i\t\t%c%i C", rsp->data[j+4],
1555c18ec02fSPetter Reinholdtsen 						((rsp->data[j+3]) >> 7) ?
1556c18ec02fSPetter Reinholdtsen 						'-' : '+', (rsp->data[j+3] & 127));
1557c18ec02fSPetter Reinholdtsen 			}
1558c18ec02fSPetter Reinholdtsen 			offset += get_inst;
1559c18ec02fSPetter Reinholdtsen 			tota_inst -= get_inst;
1560c18ec02fSPetter Reinholdtsen 		}
1561c18ec02fSPetter Reinholdtsen 	}
1562c18ec02fSPetter Reinholdtsen 	return 0;
1563c18ec02fSPetter Reinholdtsen }
1564c18ec02fSPetter Reinholdtsen 
1565c18ec02fSPetter Reinholdtsen /* This is Get DCMI Config Parameters Command
1566c18ec02fSPetter Reinholdtsen  *
1567c18ec02fSPetter Reinholdtsen  * returns ipmi response structure
1568c18ec02fSPetter Reinholdtsen  *
1569c18ec02fSPetter Reinholdtsen  * @intf:   ipmi interface handler
1570c18ec02fSPetter Reinholdtsen  */
1571c18ec02fSPetter Reinholdtsen struct ipmi_rs *
ipmi_dcmi_getconfparam(struct ipmi_intf * intf,int param_selector)1572c18ec02fSPetter Reinholdtsen ipmi_dcmi_getconfparam(struct ipmi_intf * intf, int param_selector)
1573c18ec02fSPetter Reinholdtsen {
1574c18ec02fSPetter Reinholdtsen 	struct ipmi_rq req;
1575c18ec02fSPetter Reinholdtsen 	uint8_t msg_data[3]; /* number of request data bytes */
1576c18ec02fSPetter Reinholdtsen 
1577c18ec02fSPetter Reinholdtsen 	msg_data[0] = IPMI_DCMI; /* Group Extension Identification */
1578c18ec02fSPetter Reinholdtsen 	msg_data[1] = param_selector; /* Parameter selector */
1579c18ec02fSPetter Reinholdtsen 	/* Set Selector. Selects a given set of parameters under a given Parameter
1580c18ec02fSPetter Reinholdtsen 	 * selector value. 00h if parameter doesn't use a Set Selector.
1581c18ec02fSPetter Reinholdtsen 	 */
1582c18ec02fSPetter Reinholdtsen 	msg_data[2] = 0x00;
1583c18ec02fSPetter Reinholdtsen 
1584c18ec02fSPetter Reinholdtsen 	memset(&req, 0, sizeof(req));
1585c18ec02fSPetter Reinholdtsen 	req.msg.netfn = IPMI_NETFN_DCGRP;
1586c18ec02fSPetter Reinholdtsen 	req.msg.cmd = IPMI_DCMI_GETCONFPARAM; /* Get DCMI Config Parameters */
1587c18ec02fSPetter Reinholdtsen 	req.msg.data = msg_data; /* Contents above */
1588c18ec02fSPetter Reinholdtsen 	/* how many times does req.msg.data need to read */
1589c18ec02fSPetter Reinholdtsen 	req.msg.data_len = 3;
1590c18ec02fSPetter Reinholdtsen 	return intf->sendrecv(intf, &req);
1591c18ec02fSPetter Reinholdtsen }
1592c18ec02fSPetter Reinholdtsen 
1593c18ec02fSPetter Reinholdtsen static int
ipmi_dcmi_prnt_getconfparam(struct ipmi_intf * intf)1594c18ec02fSPetter Reinholdtsen ipmi_dcmi_prnt_getconfparam(struct ipmi_intf * intf)
1595c18ec02fSPetter Reinholdtsen {
1596c18ec02fSPetter Reinholdtsen 	struct ipmi_rs * rsp;
1597c18ec02fSPetter Reinholdtsen 	const int dcmi_conf_params = 5;
1598c18ec02fSPetter Reinholdtsen 	int param_selector;
1599c18ec02fSPetter Reinholdtsen 	uint16_t tmp_value = 0;
1600c18ec02fSPetter Reinholdtsen 	/* We are not interested in parameter 1 which always will return 0 */
1601c18ec02fSPetter Reinholdtsen 	for (param_selector = 2 ; param_selector <= dcmi_conf_params;
1602c18ec02fSPetter Reinholdtsen 			param_selector++) {
1603c18ec02fSPetter Reinholdtsen 		rsp = ipmi_dcmi_getconfparam(intf, param_selector);
1604c18ec02fSPetter Reinholdtsen 		if (chk_rsp(rsp)) {
1605c18ec02fSPetter Reinholdtsen 			return -1;
1606c18ec02fSPetter Reinholdtsen 		}
1607c18ec02fSPetter Reinholdtsen 		/* Time to print what we have got */
1608c18ec02fSPetter Reinholdtsen 		switch(param_selector) {
1609c18ec02fSPetter Reinholdtsen 		case 2:
1610c18ec02fSPetter Reinholdtsen 			tmp_value = (rsp->data[4])& 1;
1611c18ec02fSPetter Reinholdtsen 			printf("\n\tDHCP Discovery method\t: ");
1612c18ec02fSPetter Reinholdtsen 			printf("\n\t\tManagement Controller ID String is %s",
1613c18ec02fSPetter Reinholdtsen 					tmp_value ? "enabled" : "disabled");
1614c18ec02fSPetter Reinholdtsen 			printf("\n\t\tVendor class identifier DCMI IANA and Vendor class-specific Informationa are %s",
1615c18ec02fSPetter Reinholdtsen 					((rsp->data[4])& 2) ? "enabled" : "disabled" );
1616c18ec02fSPetter Reinholdtsen 			break;
1617c18ec02fSPetter Reinholdtsen 		case 3:
1618c18ec02fSPetter Reinholdtsen 			printf("\n\tInitial timeout interval\t: %i seconds",
1619c18ec02fSPetter Reinholdtsen 					rsp->data[4]);
1620c18ec02fSPetter Reinholdtsen 			break;
1621c18ec02fSPetter Reinholdtsen 		case 4:
1622c18ec02fSPetter Reinholdtsen 			printf("\n\tServer contact timeout interval\t: %i seconds",
1623c18ec02fSPetter Reinholdtsen 					rsp->data[4] + (rsp->data[5]<<8));
1624c18ec02fSPetter Reinholdtsen 			break;
1625c18ec02fSPetter Reinholdtsen 		case 5:
1626c18ec02fSPetter Reinholdtsen 			printf("\n\tServer contact retry interval\t: %i seconds",
1627c18ec02fSPetter Reinholdtsen 					rsp->data[4] + (rsp->data[5] << 8));
1628c18ec02fSPetter Reinholdtsen 			break;
1629c18ec02fSPetter Reinholdtsen 		default:
1630c18ec02fSPetter Reinholdtsen 			printf("\n\tConfiguration Parameter not supported.");
1631c18ec02fSPetter Reinholdtsen 		}
1632c18ec02fSPetter Reinholdtsen 	}
1633c18ec02fSPetter Reinholdtsen 	return 0;
1634c18ec02fSPetter Reinholdtsen }
1635c18ec02fSPetter Reinholdtsen 
1636c18ec02fSPetter Reinholdtsen /* This is Set DCMI Config Parameters Command
1637c18ec02fSPetter Reinholdtsen  *
1638c18ec02fSPetter Reinholdtsen  * returns ipmi response structure
1639c18ec02fSPetter Reinholdtsen  *
1640c18ec02fSPetter Reinholdtsen  * @intf:   ipmi interface handler
1641c18ec02fSPetter Reinholdtsen  */
1642c18ec02fSPetter Reinholdtsen struct ipmi_rs *
ipmi_dcmi_setconfparam(struct ipmi_intf * intf,uint8_t param_selector,uint16_t value)1643c18ec02fSPetter Reinholdtsen ipmi_dcmi_setconfparam(struct ipmi_intf * intf, uint8_t param_selector,
1644c18ec02fSPetter Reinholdtsen 		uint16_t value)
1645c18ec02fSPetter Reinholdtsen {
1646c18ec02fSPetter Reinholdtsen 	struct ipmi_rq req;
1647c18ec02fSPetter Reinholdtsen 	uint8_t msg_data[5]; /* number of request data bytes */
1648c18ec02fSPetter Reinholdtsen 
1649c18ec02fSPetter Reinholdtsen 	msg_data[0] = IPMI_DCMI; /* Group Extension Identification */
1650c18ec02fSPetter Reinholdtsen 	msg_data[1] = param_selector; /* Parameter selector */
1651c18ec02fSPetter Reinholdtsen 	/* Set Selector (use 00h for parameters that only have one set). */
1652c18ec02fSPetter Reinholdtsen 	msg_data[2] = 0x00;
1653c18ec02fSPetter Reinholdtsen 
1654c18ec02fSPetter Reinholdtsen 	if (param_selector > 3) {
1655c18ec02fSPetter Reinholdtsen 		/* One bite more */
1656c18ec02fSPetter Reinholdtsen 		msg_data[3] = value & 0xFF;
1657c18ec02fSPetter Reinholdtsen 		msg_data[4] = value >> 8;
1658c18ec02fSPetter Reinholdtsen 	} else {
1659c18ec02fSPetter Reinholdtsen 		msg_data[3] = value;
1660c18ec02fSPetter Reinholdtsen 	}
1661c18ec02fSPetter Reinholdtsen 
1662c18ec02fSPetter Reinholdtsen 	memset(&req, 0, sizeof(req));
1663c18ec02fSPetter Reinholdtsen 	req.msg.netfn = IPMI_NETFN_DCGRP;
1664c18ec02fSPetter Reinholdtsen 	req.msg.cmd = IPMI_DCMI_SETCONFPARAM; /* Set DCMI Config Parameters */
1665c18ec02fSPetter Reinholdtsen 	req.msg.data = msg_data; /* Contents above */
1666c18ec02fSPetter Reinholdtsen 	if (param_selector > 3) {
1667c18ec02fSPetter Reinholdtsen 		/* One bite more */
1668c18ec02fSPetter Reinholdtsen 		/* how many times does req.msg.data need to read */
1669c18ec02fSPetter Reinholdtsen 		req.msg.data_len = 5;
1670c18ec02fSPetter Reinholdtsen 	} else {
1671c18ec02fSPetter Reinholdtsen 		/* how many times does req.msg.data need to read */
1672c18ec02fSPetter Reinholdtsen 		req.msg.data_len = 4;
1673c18ec02fSPetter Reinholdtsen 	}
1674c18ec02fSPetter Reinholdtsen 	return intf->sendrecv(intf, &req);
1675c18ec02fSPetter Reinholdtsen }
1676c18ec02fSPetter Reinholdtsen 
1677c18ec02fSPetter Reinholdtsen /*  Power Management get limit ipmi response
1678c18ec02fSPetter Reinholdtsen  *
1679c18ec02fSPetter Reinholdtsen  * This function returns the currently set power management settings as an
1680c18ec02fSPetter Reinholdtsen  * ipmi response structure.  The reason it returns in the rsp struct is so
1681c18ec02fSPetter Reinholdtsen  * that it can be used in the set limit [slimit()] function to populate
1682c18ec02fSPetter Reinholdtsen  * un-changed or un-edited values.
1683c18ec02fSPetter Reinholdtsen  *
1684c18ec02fSPetter Reinholdtsen  * returns ipmi response structure
1685c18ec02fSPetter Reinholdtsen  *
1686c18ec02fSPetter Reinholdtsen  * @intf:   ipmi interface handler
1687c18ec02fSPetter Reinholdtsen  */
ipmi_dcmi_pwr_glimit(struct ipmi_intf * intf)1688c18ec02fSPetter Reinholdtsen struct ipmi_rs * ipmi_dcmi_pwr_glimit(struct ipmi_intf * intf)
1689c18ec02fSPetter Reinholdtsen {
1690c18ec02fSPetter Reinholdtsen 	struct ipmi_rq req;
1691c18ec02fSPetter Reinholdtsen 	uint8_t msg_data[3]; /* number of request data bytes */
1692c18ec02fSPetter Reinholdtsen 
1693c18ec02fSPetter Reinholdtsen 	msg_data[0] = IPMI_DCMI; /* Group Extension Identification */
1694c18ec02fSPetter Reinholdtsen 	msg_data[1] = 0x00; /* reserved */
1695c18ec02fSPetter Reinholdtsen 	msg_data[2] = 0x00; /* reserved */
1696c18ec02fSPetter Reinholdtsen 
1697c18ec02fSPetter Reinholdtsen 	memset(&req, 0, sizeof(req));
1698c18ec02fSPetter Reinholdtsen 	req.msg.netfn = IPMI_NETFN_DCGRP;
1699c18ec02fSPetter Reinholdtsen 	req.msg.cmd = IPMI_DCMI_GETLMT; /* Get power limit */
1700c18ec02fSPetter Reinholdtsen 	req.msg.data = msg_data; /* Contents above */
1701c18ec02fSPetter Reinholdtsen 	/* how many times does req.msg.data need to read */
1702c18ec02fSPetter Reinholdtsen 	req.msg.data_len = 3;
1703c18ec02fSPetter Reinholdtsen 
1704c18ec02fSPetter Reinholdtsen 	return intf->sendrecv(intf, &req);
1705c18ec02fSPetter Reinholdtsen }
1706c18ec02fSPetter Reinholdtsen /* end Power Management get limit response */
1707c18ec02fSPetter Reinholdtsen 
1708c18ec02fSPetter Reinholdtsen /*  Power Management print the get limit command
1709c18ec02fSPetter Reinholdtsen  *
1710c18ec02fSPetter Reinholdtsen  * This function calls the get limit function that returns an ipmi response.
1711c18ec02fSPetter Reinholdtsen  *
1712c18ec02fSPetter Reinholdtsen  * returns 0 else 1 with error
1713c18ec02fSPetter Reinholdtsen  * @intf:   ipmi interface handler
1714c18ec02fSPetter Reinholdtsen  */
1715c18ec02fSPetter Reinholdtsen static int
ipmi_dcmi_pwr_prnt_glimit(struct ipmi_intf * intf)1716c18ec02fSPetter Reinholdtsen ipmi_dcmi_pwr_prnt_glimit(struct ipmi_intf * intf)
1717c18ec02fSPetter Reinholdtsen {
1718c18ec02fSPetter Reinholdtsen 	struct ipmi_rs * rsp;
1719c18ec02fSPetter Reinholdtsen 	struct power_limit val;
1720c18ec02fSPetter Reinholdtsen 	uint8_t realCc = 0xff;
1721c18ec02fSPetter Reinholdtsen 
1722c18ec02fSPetter Reinholdtsen 	rsp = ipmi_dcmi_pwr_glimit(intf);
1723c18ec02fSPetter Reinholdtsen 	/* rsp can be a null so check response before any operation
1724c18ec02fSPetter Reinholdtsen 	 * on it to avoid sig segv
1725c18ec02fSPetter Reinholdtsen 	 */
1726c18ec02fSPetter Reinholdtsen 	if (rsp != NULL) {
1727c18ec02fSPetter Reinholdtsen 		realCc = rsp->ccode;
1728c18ec02fSPetter Reinholdtsen 		GOOD_PWR_GLIMIT_CCODE(rsp->ccode);
1729c18ec02fSPetter Reinholdtsen 	}
1730c18ec02fSPetter Reinholdtsen 	if (chk_rsp(rsp)) {
1731c18ec02fSPetter Reinholdtsen 		return -1;
1732c18ec02fSPetter Reinholdtsen 	}
1733c18ec02fSPetter Reinholdtsen 	/* rsp->data[0] is equal to response data byte 2 in spec */
1734c18ec02fSPetter Reinholdtsen 	/* printf("Group Extension Identification: %02x\n", rsp->data[0]); */
1735c18ec02fSPetter Reinholdtsen 	memcpy(&val, rsp->data, sizeof (val));
1736c18ec02fSPetter Reinholdtsen 	printf("\n    Current Limit State: %s\n",
1737c18ec02fSPetter Reinholdtsen 			(realCc == 0) ?
1738c18ec02fSPetter Reinholdtsen 			"Power Limit Active" : "No Active Power Limit");
1739c18ec02fSPetter Reinholdtsen 	printf("    Exception actions:   %s\n",
174042aba7ebSZdenek Styblik 			val2str2(val.action, dcmi_pwrmgmt_get_action_vals));
1741c18ec02fSPetter Reinholdtsen 	printf("    Power Limit:         %i Watts\n", val.limit);
1742c18ec02fSPetter Reinholdtsen 	printf("    Correction time:     %i milliseconds\n", val.correction);
1743c18ec02fSPetter Reinholdtsen 	printf("    Sampling period:     %i seconds\n", val.sample);
1744c18ec02fSPetter Reinholdtsen 	printf("\n");
1745c18ec02fSPetter Reinholdtsen 	return 0;
1746c18ec02fSPetter Reinholdtsen }
1747c18ec02fSPetter Reinholdtsen /* end print get limit */
1748c18ec02fSPetter Reinholdtsen 
1749c18ec02fSPetter Reinholdtsen /*  Power Management set limit
1750c18ec02fSPetter Reinholdtsen  *
1751c18ec02fSPetter Reinholdtsen  * Undocumented bounds:
1752c18ec02fSPetter Reinholdtsen  * Power limit: 0 - 0xFFFF
1753c18ec02fSPetter Reinholdtsen  * Correction period 5750ms to 28751ms or 0x1676 to 0x704F
1754c18ec02fSPetter Reinholdtsen  * sample period: 3 sec to 65 sec and 69+
1755c18ec02fSPetter Reinholdtsen  *
1756c18ec02fSPetter Reinholdtsen  * @intf:    ipmi interface handler
1757c18ec02fSPetter Reinholdtsen  * @option:  Power option to change
1758c18ec02fSPetter Reinholdtsen  * @value:   Value of the desired change
1759c18ec02fSPetter Reinholdtsen  */
1760c18ec02fSPetter Reinholdtsen static int
ipmi_dcmi_pwr_slimit(struct ipmi_intf * intf,const char * option,const char * value)1761c18ec02fSPetter Reinholdtsen ipmi_dcmi_pwr_slimit(struct ipmi_intf * intf, const char * option,
1762c18ec02fSPetter Reinholdtsen 		const char * value)
1763c18ec02fSPetter Reinholdtsen {
1764c18ec02fSPetter Reinholdtsen 	struct ipmi_rs * rsp; /* ipmi response */
1765c18ec02fSPetter Reinholdtsen 	struct ipmi_rq req; /* ipmi request (to send) */
1766c18ec02fSPetter Reinholdtsen 	struct power_limit val;
1767c18ec02fSPetter Reinholdtsen 	uint8_t msg_data[15]; /* number of request data bytes */
1768c18ec02fSPetter Reinholdtsen 	uint32_t lvalue = 0;
1769c18ec02fSPetter Reinholdtsen 
1770c18ec02fSPetter Reinholdtsen 	rsp = ipmi_dcmi_pwr_glimit(intf); /* get the power limit settings */
1771c18ec02fSPetter Reinholdtsen # if 0
1772c18ec02fSPetter Reinholdtsen 	{
1773c18ec02fSPetter Reinholdtsen 		unsigned char counter = 0;
1774c18ec02fSPetter Reinholdtsen 		printf("DATA (%d): ", rsp->data_len);
1775c18ec02fSPetter Reinholdtsen 		for(counter = 0; counter < rsp->data_len; counter ++) {
1776c18ec02fSPetter Reinholdtsen 			printf("%02X ", rsp->data[counter]);
1777c18ec02fSPetter Reinholdtsen 		}
1778c18ec02fSPetter Reinholdtsen 		printf("\n");
1779c18ec02fSPetter Reinholdtsen 	}
1780c18ec02fSPetter Reinholdtsen # endif
1781c18ec02fSPetter Reinholdtsen 	/* rsp can be a null so check response before any operation on it to
1782c18ec02fSPetter Reinholdtsen 	 * avoid sig segv
1783c18ec02fSPetter Reinholdtsen 	 */
1784c18ec02fSPetter Reinholdtsen 	if (rsp != NULL) {
1785c18ec02fSPetter Reinholdtsen 		GOOD_PWR_GLIMIT_CCODE(rsp->ccode);
1786c18ec02fSPetter Reinholdtsen 	}
1787c18ec02fSPetter Reinholdtsen 	if (chk_rsp(rsp)) {
1788c18ec02fSPetter Reinholdtsen 		return -1;
1789c18ec02fSPetter Reinholdtsen 	}
1790c18ec02fSPetter Reinholdtsen 	memcpy(&val, rsp->data, sizeof (val));
1791c18ec02fSPetter Reinholdtsen 	/* same as above; sets the values of the val struct
1792c18ec02fSPetter Reinholdtsen 	 * DCMI group ID *
1793c18ec02fSPetter Reinholdtsen 	 * val.grp_id = rsp->data[0];
1794c18ec02fSPetter Reinholdtsen 	 * exception action *
1795c18ec02fSPetter Reinholdtsen 	 * val.action = rsp->data[3]; *
1796c18ec02fSPetter Reinholdtsen 	 *
1797c18ec02fSPetter Reinholdtsen 	 * power limit in Watts *
1798c18ec02fSPetter Reinholdtsen 	 * store 16 bits of the rsp from the 4th entity *
1799c18ec02fSPetter Reinholdtsen 	 * val.limit = *(uint16_t*)(&rsp->data[4]);
1800c18ec02fSPetter Reinholdtsen 	 * correction period in mS *
1801c18ec02fSPetter Reinholdtsen 	 * store 32 bits of the rsp from the 6th entity *
1802c18ec02fSPetter Reinholdtsen 	 * val.correction = *(uint32_t*)(&rsp->data[6]);
1803c18ec02fSPetter Reinholdtsen 	 * store 16 bits of the rsp from the 12th entity *
1804c18ec02fSPetter Reinholdtsen 	 * sample period in seconds *
1805c18ec02fSPetter Reinholdtsen 	 * val.sample = *(uint16_t*)(&rsp->data[12]);
1806c18ec02fSPetter Reinholdtsen 	 */
180742aba7ebSZdenek Styblik 	lprintf(LOG_INFO,
180842aba7ebSZdenek Styblik 			"DCMI IN  Limit=%d Correction=%d Action=%d Sample=%d\n",
180942aba7ebSZdenek Styblik 			val.limit, val.correction, val.action, val.sample);
1810c18ec02fSPetter Reinholdtsen 	switch (str2val2(option, dcmi_pwrmgmt_set_usage_vals)) {
1811c18ec02fSPetter Reinholdtsen 	case 0x00:
1812c18ec02fSPetter Reinholdtsen 		/* action */
1813c18ec02fSPetter Reinholdtsen 		switch (str2val2(value, dcmi_pwrmgmt_action_vals)) {
181442aba7ebSZdenek Styblik 		case 0x00:
181542aba7ebSZdenek Styblik 			/* no_action */
181642aba7ebSZdenek Styblik 			val.action = 0;
181742aba7ebSZdenek Styblik 			break;
1818c18ec02fSPetter Reinholdtsen 		case 0x01:
1819c18ec02fSPetter Reinholdtsen 			/* power_off */
1820c18ec02fSPetter Reinholdtsen 			val.action = 1;
1821c18ec02fSPetter Reinholdtsen 			break;
182242aba7ebSZdenek Styblik 		case 0x02:
182342aba7ebSZdenek Styblik 			/* OEM reserved action */
182442aba7ebSZdenek Styblik 			val.action = 0x02;
182542aba7ebSZdenek Styblik 			break;
182642aba7ebSZdenek Styblik 		case 0x03:
182742aba7ebSZdenek Styblik 			/* OEM reserved action */
182842aba7ebSZdenek Styblik 			val.action = 0x03;
182942aba7ebSZdenek Styblik 			break;
183042aba7ebSZdenek Styblik 		case 0x04:
183142aba7ebSZdenek Styblik 			/* OEM reserved action */
183242aba7ebSZdenek Styblik 			val.action = 0x04;
183342aba7ebSZdenek Styblik 			break;
183442aba7ebSZdenek Styblik 		case 0x05:
183542aba7ebSZdenek Styblik 			/* OEM reserved action */
183642aba7ebSZdenek Styblik 			val.action = 0x05;
183742aba7ebSZdenek Styblik 			break;
183842aba7ebSZdenek Styblik 		case 0x06:
183942aba7ebSZdenek Styblik 			/* OEM reserved action */
184042aba7ebSZdenek Styblik 			val.action = 0x06;
184142aba7ebSZdenek Styblik 			break;
184242aba7ebSZdenek Styblik 		case 0x07:
184342aba7ebSZdenek Styblik 			/* OEM reserved action */
184442aba7ebSZdenek Styblik 			val.action = 0x07;
184542aba7ebSZdenek Styblik 			break;
184642aba7ebSZdenek Styblik 		case 0x08:
184742aba7ebSZdenek Styblik 			/* OEM reserved action */
184842aba7ebSZdenek Styblik 			val.action = 0x08;
184942aba7ebSZdenek Styblik 			break;
185042aba7ebSZdenek Styblik 		case 0x09:
185142aba7ebSZdenek Styblik 			/* OEM reserved action */
185242aba7ebSZdenek Styblik 			val.action = 0x09;
185342aba7ebSZdenek Styblik 			break;
185442aba7ebSZdenek Styblik 		case 0x0a:
185542aba7ebSZdenek Styblik 			/* OEM reserved action */
185642aba7ebSZdenek Styblik 			val.action = 0x0a;
185742aba7ebSZdenek Styblik 			break;
185842aba7ebSZdenek Styblik 		case 0x0b:
185942aba7ebSZdenek Styblik 			/* OEM reserved action */
186042aba7ebSZdenek Styblik 			val.action = 0x0b;
186142aba7ebSZdenek Styblik 			break;
186242aba7ebSZdenek Styblik 		case 0x0c:
186342aba7ebSZdenek Styblik 			/* OEM reserved action */
186442aba7ebSZdenek Styblik 			val.action = 0x0c;
186542aba7ebSZdenek Styblik 			break;
186642aba7ebSZdenek Styblik 		case 0x0d:
186742aba7ebSZdenek Styblik 			/* OEM reserved action */
186842aba7ebSZdenek Styblik 			val.action = 0x0d;
186942aba7ebSZdenek Styblik 			break;
187042aba7ebSZdenek Styblik 		case 0x0e:
187142aba7ebSZdenek Styblik 			/* OEM reserved action */
187242aba7ebSZdenek Styblik 			val.action = 0x0e;
187342aba7ebSZdenek Styblik 			break;
187442aba7ebSZdenek Styblik 		case 0x0f:
187542aba7ebSZdenek Styblik 			/* OEM reserved action */
187642aba7ebSZdenek Styblik 			val.action = 0x0f;
187742aba7ebSZdenek Styblik 			break;
187842aba7ebSZdenek Styblik 		case 0x10:
187942aba7ebSZdenek Styblik 			/* OEM reserved action */
188042aba7ebSZdenek Styblik 			val.action = 0x10;
188142aba7ebSZdenek Styblik 			break;
1882c18ec02fSPetter Reinholdtsen 		case 0x11:
1883c18ec02fSPetter Reinholdtsen 			/* sel_logging*/
1884c18ec02fSPetter Reinholdtsen 			val.action = 0x11;
1885c18ec02fSPetter Reinholdtsen 			break;
1886c18ec02fSPetter Reinholdtsen 		case 0xFF:
1887c18ec02fSPetter Reinholdtsen 			/* error - not a string we knew what to do with */
188842aba7ebSZdenek Styblik 			lprintf(LOG_ERR, "Given %s '%s' is invalid.",
188942aba7ebSZdenek Styblik 					option, value);
1890c18ec02fSPetter Reinholdtsen 			return -1;
1891c18ec02fSPetter Reinholdtsen 		}
1892c18ec02fSPetter Reinholdtsen 		break;
1893c18ec02fSPetter Reinholdtsen 	case 0x01:
1894c18ec02fSPetter Reinholdtsen 		/* limit */
189542aba7ebSZdenek Styblik 		if (str2uint(value, &lvalue) != 0) {
189642aba7ebSZdenek Styblik 			lprintf(LOG_ERR, "Given %s '%s' is invalid.",
189742aba7ebSZdenek Styblik 					option, value);
189842aba7ebSZdenek Styblik 			return (-1);
189942aba7ebSZdenek Styblik 		}
1900c18ec02fSPetter Reinholdtsen 		val.limit = *(uint16_t*)(&lvalue);
1901c18ec02fSPetter Reinholdtsen 		break;
1902c18ec02fSPetter Reinholdtsen 	case 0x02:
1903c18ec02fSPetter Reinholdtsen 		/* correction */
190442aba7ebSZdenek Styblik 		if (str2uint(value, &lvalue) != 0) {
190542aba7ebSZdenek Styblik 			lprintf(LOG_ERR, "Given %s '%s' is invalid.",
190642aba7ebSZdenek Styblik 					option, value);
190742aba7ebSZdenek Styblik 			return (-1);
190842aba7ebSZdenek Styblik 		}
1909c18ec02fSPetter Reinholdtsen 		val.correction = *(uint32_t*)(&lvalue);
1910c18ec02fSPetter Reinholdtsen 		break;
1911c18ec02fSPetter Reinholdtsen 	case 0x03:
1912c18ec02fSPetter Reinholdtsen 		/* sample */
191342aba7ebSZdenek Styblik 		if (str2uint(value, &lvalue) != 0) {
191442aba7ebSZdenek Styblik 			lprintf(LOG_ERR, "Given %s '%s' is invalid.",
191542aba7ebSZdenek Styblik 					option, value);
191642aba7ebSZdenek Styblik 			return (-1);
191742aba7ebSZdenek Styblik 		}
1918c18ec02fSPetter Reinholdtsen 		val.sample = *(uint16_t*)(&lvalue);
1919c18ec02fSPetter Reinholdtsen 		break;
1920c18ec02fSPetter Reinholdtsen 	case 0xff:
1921c18ec02fSPetter Reinholdtsen 		/* no valid options */
1922c18ec02fSPetter Reinholdtsen 		return -1;
1923c18ec02fSPetter Reinholdtsen 	}
192442aba7ebSZdenek Styblik 	lprintf(LOG_INFO, "DCMI OUT Limit=%d Correction=%d Action=%d Sample=%d\n", val.limit, val.correction, val.action, val.sample);
1925c18ec02fSPetter Reinholdtsen 
1926c18ec02fSPetter Reinholdtsen 	msg_data[0] = val.grp_id; /* Group Extension Identification */
1927c18ec02fSPetter Reinholdtsen 	msg_data[1] = 0x00; /* reserved */
1928c18ec02fSPetter Reinholdtsen 	msg_data[2] = 0x00; /* reserved */
1929c18ec02fSPetter Reinholdtsen 	msg_data[3] = 0x00; /* reserved */
1930c18ec02fSPetter Reinholdtsen 	msg_data[4] = val.action; /* exception action; 0x00 disables it */
1931c18ec02fSPetter Reinholdtsen 
1932c18ec02fSPetter Reinholdtsen 	/* fill msg_data[5] with the first 16 bits of val.limit */
1933c18ec02fSPetter Reinholdtsen 	*(uint16_t*)(&msg_data[5]) = val.limit;
1934c18ec02fSPetter Reinholdtsen 	/* msg_data[5] = 0xFF;
1935c18ec02fSPetter Reinholdtsen 	 * msg_data[6] = 0xFF;
1936c18ec02fSPetter Reinholdtsen 	 */
1937c18ec02fSPetter Reinholdtsen 	/* fill msg_data[7] with the first 32 bits of val.correction */
1938c18ec02fSPetter Reinholdtsen 	*(uint32_t*)(&msg_data[7]) = val.correction;
1939c18ec02fSPetter Reinholdtsen 	/* msg_data[7] = 0x76;
1940c18ec02fSPetter Reinholdtsen 	 * msg_data[8] = 0x16;
1941c18ec02fSPetter Reinholdtsen 	 * msg_data[9] = 0x00;
1942c18ec02fSPetter Reinholdtsen 	 * msg_data[10] = 0x00;
1943c18ec02fSPetter Reinholdtsen 	 */
1944c18ec02fSPetter Reinholdtsen 	msg_data[11] = 0x00; /* reserved */
1945c18ec02fSPetter Reinholdtsen 	msg_data[12] = 0x00; /* reserved */
1946fd5fdc59SPat Donlin 	/* fill msg_data[13] with the first 16 bits of val.sample */
1947c18ec02fSPetter Reinholdtsen 	*(uint16_t*)(&msg_data[13]) = val.sample;
1948c18ec02fSPetter Reinholdtsen 	/* msg_data[13] = 0x03; */
1949c18ec02fSPetter Reinholdtsen 	memset(&req, 0, sizeof(req));
1950c18ec02fSPetter Reinholdtsen 	req.msg.netfn = IPMI_NETFN_DCGRP;
1951c18ec02fSPetter Reinholdtsen 	req.msg.cmd = IPMI_DCMI_SETLMT; /* Set power limit */
1952c18ec02fSPetter Reinholdtsen 	req.msg.data = msg_data; /* Contents above */
1953c18ec02fSPetter Reinholdtsen 	/* how many times does req.msg.data need to read */
1954c18ec02fSPetter Reinholdtsen 	req.msg.data_len = 15;
1955c18ec02fSPetter Reinholdtsen 
1956c18ec02fSPetter Reinholdtsen 	rsp = intf->sendrecv(intf, &req);
1957c18ec02fSPetter Reinholdtsen 
1958c18ec02fSPetter Reinholdtsen 	if (chk_rsp(rsp)) {
1959c18ec02fSPetter Reinholdtsen 		return -1;
1960c18ec02fSPetter Reinholdtsen 	}
1961c18ec02fSPetter Reinholdtsen 	return 0;
1962c18ec02fSPetter Reinholdtsen }
1963c18ec02fSPetter Reinholdtsen /* end Power Management set limit */
1964c18ec02fSPetter Reinholdtsen 
1965c18ec02fSPetter Reinholdtsen /*  Power Management activate deactivate
1966c18ec02fSPetter Reinholdtsen  *
1967c18ec02fSPetter Reinholdtsen  * @intf:    ipmi interface handler
1968c18ec02fSPetter Reinholdtsen  * @option:  uint8_t - 0 to deactivate or 1 to activate
1969c18ec02fSPetter Reinholdtsen  */
1970c18ec02fSPetter Reinholdtsen static int
ipmi_dcmi_pwr_actdeact(struct ipmi_intf * intf,uint8_t option)1971c18ec02fSPetter Reinholdtsen ipmi_dcmi_pwr_actdeact(struct ipmi_intf * intf, uint8_t option)
1972c18ec02fSPetter Reinholdtsen {
1973c18ec02fSPetter Reinholdtsen 	struct ipmi_rs * rsp;
1974c18ec02fSPetter Reinholdtsen 	struct ipmi_rq req;
1975c18ec02fSPetter Reinholdtsen 	uint8_t msg_data[4]; /* number of request data bytes */
1976c18ec02fSPetter Reinholdtsen 
1977c18ec02fSPetter Reinholdtsen 	msg_data[0] = IPMI_DCMI; /* Group Extension Identification */
1978c18ec02fSPetter Reinholdtsen 	msg_data[1] = option; /* 0 = Deactivate 1 = Activate */
1979c18ec02fSPetter Reinholdtsen 	msg_data[2] = 0x00; /* reserved */
1980c18ec02fSPetter Reinholdtsen 	msg_data[3] = 0x00; /* reserved */
1981c18ec02fSPetter Reinholdtsen 
1982c18ec02fSPetter Reinholdtsen 	memset(&req, 0, sizeof(req));
1983c18ec02fSPetter Reinholdtsen 	req.msg.netfn = IPMI_NETFN_DCGRP;
1984c18ec02fSPetter Reinholdtsen 	req.msg.cmd = IPMI_DCMI_PWRACT; /* Act-deactivate power limit */
1985c18ec02fSPetter Reinholdtsen 	req.msg.data = msg_data; /* Contents above */
1986c18ec02fSPetter Reinholdtsen 	req.msg.data_len = 4; /* how mant times does req.msg.data need to read */
1987c18ec02fSPetter Reinholdtsen 
1988c18ec02fSPetter Reinholdtsen 	rsp = intf->sendrecv(intf, &req);
1989c18ec02fSPetter Reinholdtsen 	if (chk_rsp(rsp)) {
1990c18ec02fSPetter Reinholdtsen 		return -1;
1991c18ec02fSPetter Reinholdtsen 	}
1992c18ec02fSPetter Reinholdtsen 	printf("\n    Power limit successfully ");
1993c18ec02fSPetter Reinholdtsen 	if (option == 0x00) {
1994c18ec02fSPetter Reinholdtsen 		printf("deactivated");
1995c18ec02fSPetter Reinholdtsen 	} else {
1996c18ec02fSPetter Reinholdtsen 		printf("activated");
1997c18ec02fSPetter Reinholdtsen 	}
1998c18ec02fSPetter Reinholdtsen 	printf("\n");
1999c18ec02fSPetter Reinholdtsen 	return 0;
2000c18ec02fSPetter Reinholdtsen }
2001c18ec02fSPetter Reinholdtsen /* end power management activate/deactivate */
2002c18ec02fSPetter Reinholdtsen 
2003fd5fdc59SPat Donlin /* Node Manager discover */
2004fd5fdc59SPat Donlin static int
_ipmi_nm_discover(struct ipmi_intf * intf,struct nm_discover * disc)2005fd5fdc59SPat Donlin _ipmi_nm_discover(struct ipmi_intf * intf, struct nm_discover *disc)
2006fd5fdc59SPat Donlin {
2007fd5fdc59SPat Donlin 	struct ipmi_rq req; /* request data to send to the BMC */
2008fd5fdc59SPat Donlin 	struct ipmi_rs *rsp;
2009fd5fdc59SPat Donlin 	uint8_t msg_data[3]; /* 'raw' data to be sent to the BMC */
2010fd5fdc59SPat Donlin 
2011fd5fdc59SPat Donlin 	msg_data[0] = 0x57;
2012fd5fdc59SPat Donlin 	msg_data[1] = 1;
2013fd5fdc59SPat Donlin 	msg_data[2] = 0;
2014fd5fdc59SPat Donlin 	memset(&req, 0, sizeof(req));
2015fd5fdc59SPat Donlin 	req.msg.netfn = IPMI_NETFN_OEM;
2016fd5fdc59SPat Donlin 	req.msg.cmd = IPMI_NM_GET_VERSION;
2017fd5fdc59SPat Donlin 	req.msg.data = msg_data;
2018fd5fdc59SPat Donlin 	req.msg.data_len = 3;
2019fd5fdc59SPat Donlin 	rsp = intf->sendrecv(intf, &req);
2020fd5fdc59SPat Donlin 	if (chk_nm_rsp(rsp)) {
2021fd5fdc59SPat Donlin 		return -1;
2022fd5fdc59SPat Donlin 	}
2023fd5fdc59SPat Donlin 	memcpy(disc, rsp->data, sizeof (struct nm_discover));
2024fd5fdc59SPat Donlin 	return 0;
2025fd5fdc59SPat Donlin }
2026fd5fdc59SPat Donlin /* Get NM capabilities
2027c18ec02fSPetter Reinholdtsen  *
2028fd5fdc59SPat Donlin  * This function returns the available capabilities of the platform.
2029fd5fdc59SPat Donlin  *
2030fd5fdc59SPat Donlin  * returns success/failure
2031fd5fdc59SPat Donlin  *
2032fd5fdc59SPat Donlin  * @intf:   ipmi interface handler
2033fd5fdc59SPat Donlin  * @caps:   fills in capability struct
2034c18ec02fSPetter Reinholdtsen  */
2035fd5fdc59SPat Donlin static int
_ipmi_nm_getcapabilities(struct ipmi_intf * intf,uint8_t domain,uint8_t trigger,struct nm_capability * caps)2036fd5fdc59SPat Donlin _ipmi_nm_getcapabilities(struct ipmi_intf * intf, uint8_t domain, uint8_t trigger, struct nm_capability *caps)
2037c18ec02fSPetter Reinholdtsen {
2038fd5fdc59SPat Donlin 	struct ipmi_rq req; /* request data to send to the BMC */
2039fd5fdc59SPat Donlin 	struct ipmi_rs *rsp;
2040fd5fdc59SPat Donlin 	uint8_t msg_data[5]; /* 'raw' data to be sent to the BMC */
2041fd5fdc59SPat Donlin 
2042fd5fdc59SPat Donlin 	msg_data[0] = 0x57;
2043fd5fdc59SPat Donlin 	msg_data[1] = 1;
2044fd5fdc59SPat Donlin 	msg_data[2] = 0;
2045fd5fdc59SPat Donlin 	msg_data[3] = domain;
2046fd5fdc59SPat Donlin 	msg_data[4] = trigger; /* power control policy or trigger */
2047fd5fdc59SPat Donlin 	memset(&req, 0, sizeof(req));
2048fd5fdc59SPat Donlin 	req.msg.netfn = IPMI_NETFN_OEM;
2049fd5fdc59SPat Donlin 	req.msg.cmd = IPMI_NM_GET_CAP;
2050fd5fdc59SPat Donlin 	req.msg.data = msg_data;
2051fd5fdc59SPat Donlin 	req.msg.data_len = 5;
2052fd5fdc59SPat Donlin 	rsp = intf->sendrecv(intf, &req);
2053fd5fdc59SPat Donlin 	if (chk_nm_rsp(rsp)) {
2054fd5fdc59SPat Donlin 		return -1;
2055fd5fdc59SPat Donlin 	}
2056fd5fdc59SPat Donlin 	memcpy(caps, rsp->data, sizeof (struct nm_capability));
2057fd5fdc59SPat Donlin 	return 0;
2058fd5fdc59SPat Donlin }
2059fd5fdc59SPat Donlin 
2060fd5fdc59SPat Donlin static int
_ipmi_nm_get_policy(struct ipmi_intf * intf,uint8_t domain,uint8_t policy_id,struct nm_get_policy * policy)2061fd5fdc59SPat Donlin _ipmi_nm_get_policy(struct ipmi_intf * intf, uint8_t domain, uint8_t policy_id, struct nm_get_policy *policy)
2062fd5fdc59SPat Donlin {
2063fd5fdc59SPat Donlin 	struct ipmi_rq req; /* request data to send to the BMC */
2064fd5fdc59SPat Donlin 	struct ipmi_rs *rsp;
2065fd5fdc59SPat Donlin 	uint8_t msg_data[5]; /* 'raw' data to be sent to the BMC */
2066fd5fdc59SPat Donlin 
2067fd5fdc59SPat Donlin 	msg_data[0] = 0x57;
2068fd5fdc59SPat Donlin 	msg_data[1] = 1;
2069fd5fdc59SPat Donlin 	msg_data[2] = 0;
2070fd5fdc59SPat Donlin 	msg_data[3] = domain;
2071fd5fdc59SPat Donlin 	msg_data[4] = policy_id;
2072fd5fdc59SPat Donlin 	memset(&req, 0, sizeof(req));
2073fd5fdc59SPat Donlin 	req.msg.netfn = IPMI_NETFN_OEM;
2074fd5fdc59SPat Donlin 	req.msg.cmd = IPMI_NM_GET_POLICY;
2075fd5fdc59SPat Donlin 	req.msg.data = msg_data;
2076fd5fdc59SPat Donlin 	req.msg.data_len = 5;
2077fd5fdc59SPat Donlin 	rsp = intf->sendrecv(intf, &req);
2078fd5fdc59SPat Donlin 	if (chk_nm_rsp(rsp)) {
2079fd5fdc59SPat Donlin 		return -1;
2080fd5fdc59SPat Donlin 	}
2081fd5fdc59SPat Donlin 	memcpy(policy, rsp->data, sizeof (struct nm_get_policy));
2082fd5fdc59SPat Donlin 	return 0;
2083fd5fdc59SPat Donlin }
2084fd5fdc59SPat Donlin static int
_ipmi_nm_set_policy(struct ipmi_intf * intf,struct nm_policy * policy)2085fd5fdc59SPat Donlin _ipmi_nm_set_policy(struct ipmi_intf * intf, struct nm_policy *policy)
2086fd5fdc59SPat Donlin {
2087fd5fdc59SPat Donlin 	struct ipmi_rq req; /* request data to send to the BMC */
2088c18ec02fSPetter Reinholdtsen 	struct ipmi_rs *rsp;
2089c18ec02fSPetter Reinholdtsen 
2090fd5fdc59SPat Donlin 	memset(&req, 0, sizeof(req));
2091fd5fdc59SPat Donlin 	req.msg.netfn = IPMI_NETFN_OEM;
2092fd5fdc59SPat Donlin 	req.msg.cmd = IPMI_NM_SET_POLICY;
2093fd5fdc59SPat Donlin 	req.msg.data = (uint8_t *)policy;
2094fd5fdc59SPat Donlin 	req.msg.data_len = sizeof(struct nm_policy);
2095fd5fdc59SPat Donlin 	policy->intel_id[0] = 0x57; policy->intel_id[1] =1; policy->intel_id[2] =0;
2096fd5fdc59SPat Donlin 	rsp = intf->sendrecv(intf, &req);
2097fd5fdc59SPat Donlin 	if (chk_nm_rsp(rsp)) {
2098c18ec02fSPetter Reinholdtsen 		return -1;
2099c18ec02fSPetter Reinholdtsen 	}
2100fd5fdc59SPat Donlin 	return 0;
2101fd5fdc59SPat Donlin }
2102fd5fdc59SPat Donlin 
2103fd5fdc59SPat Donlin static int
_ipmi_nm_policy_limiting(struct ipmi_intf * intf,uint8_t domain)2104fd5fdc59SPat Donlin _ipmi_nm_policy_limiting(struct ipmi_intf * intf, uint8_t domain)
2105fd5fdc59SPat Donlin {
2106fd5fdc59SPat Donlin 	struct ipmi_rq req; /* request data to send to the BMC */
2107fd5fdc59SPat Donlin 	struct ipmi_rs *rsp;
2108fd5fdc59SPat Donlin 	uint8_t msg_data[4]; /* 'raw' data to be sent to the BMC */
2109fd5fdc59SPat Donlin 
2110fd5fdc59SPat Donlin 	memset(&req, 0, sizeof(req));
2111fd5fdc59SPat Donlin 	req.msg.netfn = IPMI_NETFN_OEM;
2112fd5fdc59SPat Donlin 	req.msg.cmd = IPMI_NM_LIMITING;
2113fd5fdc59SPat Donlin 	msg_data[0] = 0x57;
2114fd5fdc59SPat Donlin 	msg_data[1] = 1;
2115fd5fdc59SPat Donlin 	msg_data[2] = 0;
2116fd5fdc59SPat Donlin 	msg_data[3] = domain;
2117fd5fdc59SPat Donlin 	req.msg.data = msg_data;
2118fd5fdc59SPat Donlin 	req.msg.data_len = 4;
2119fd5fdc59SPat Donlin 	rsp = intf->sendrecv(intf, &req);
2120fd5fdc59SPat Donlin 	/* check for special case error of no policy is limiting */
2121fd5fdc59SPat Donlin 	if (rsp && (rsp->ccode == 0xA1))
2122fd5fdc59SPat Donlin 		return 0x80;
2123fd5fdc59SPat Donlin 	else if (chk_nm_rsp(rsp))
2124fd5fdc59SPat Donlin 		return -1;
2125fd5fdc59SPat Donlin 	return rsp->data[0];
2126fd5fdc59SPat Donlin }
2127fd5fdc59SPat Donlin 
2128fd5fdc59SPat Donlin static int
_ipmi_nm_control(struct ipmi_intf * intf,uint8_t scope,uint8_t domain,uint8_t policy_id)2129fd5fdc59SPat Donlin _ipmi_nm_control(struct ipmi_intf * intf, uint8_t scope, uint8_t domain, uint8_t policy_id)
2130fd5fdc59SPat Donlin {
2131fd5fdc59SPat Donlin 	struct ipmi_rq req; /* request data to send to the BMC */
2132fd5fdc59SPat Donlin 	struct ipmi_rs *rsp;
2133fd5fdc59SPat Donlin 	uint8_t msg_data[6]; /* 'raw' data to be sent to the BMC */
2134fd5fdc59SPat Donlin 
2135fd5fdc59SPat Donlin 	msg_data[0] = 0x57;
2136fd5fdc59SPat Donlin 	msg_data[1] = 1;
2137fd5fdc59SPat Donlin 	msg_data[2] = 0;
2138fd5fdc59SPat Donlin 	msg_data[3] = scope;
2139fd5fdc59SPat Donlin 	msg_data[4] = domain;
2140fd5fdc59SPat Donlin 	msg_data[5] = policy_id;
2141fd5fdc59SPat Donlin 	memset(&req, 0, sizeof(req));
2142fd5fdc59SPat Donlin 	req.msg.netfn = IPMI_NETFN_OEM;
2143fd5fdc59SPat Donlin 	req.msg.cmd = IPMI_NM_POLICY_CTL;
2144fd5fdc59SPat Donlin 	req.msg.data = msg_data;
2145fd5fdc59SPat Donlin 	req.msg.data_len = 6;
2146fd5fdc59SPat Donlin 	rsp = intf->sendrecv(intf, &req);
2147fd5fdc59SPat Donlin 	if (chk_nm_rsp(rsp)) {
2148c18ec02fSPetter Reinholdtsen 		return -1;
2149c18ec02fSPetter Reinholdtsen 	}
2150fd5fdc59SPat Donlin 	return 0;
2151c18ec02fSPetter Reinholdtsen }
2152fd5fdc59SPat Donlin 
2153fd5fdc59SPat Donlin /* Get NM statistics
2154fd5fdc59SPat Donlin  *
2155fd5fdc59SPat Donlin  * This function returns the statistics
2156fd5fdc59SPat Donlin  *
2157fd5fdc59SPat Donlin  * returns success/failure
2158fd5fdc59SPat Donlin  *
2159fd5fdc59SPat Donlin  * @intf:   ipmi interface handler
2160fd5fdc59SPat Donlin  * @selector: Parameter selector
2161c18ec02fSPetter Reinholdtsen  */
2162fd5fdc59SPat Donlin static int
_ipmi_nm_statistics(struct ipmi_intf * intf,uint8_t mode,uint8_t domain,uint8_t policy_id,struct nm_statistics * caps)2163fd5fdc59SPat Donlin _ipmi_nm_statistics(struct ipmi_intf * intf, uint8_t mode, uint8_t domain, uint8_t policy_id, struct nm_statistics *caps)
2164fd5fdc59SPat Donlin {
2165fd5fdc59SPat Donlin 	struct ipmi_rq req; /* request data to send to the BMC */
2166fd5fdc59SPat Donlin 	struct ipmi_rs *rsp;
2167fd5fdc59SPat Donlin 	uint8_t msg_data[6]; /* 'raw' data to be sent to the BMC */
2168fd5fdc59SPat Donlin 
2169fd5fdc59SPat Donlin 	msg_data[0] = 0x57;
2170fd5fdc59SPat Donlin 	msg_data[1] = 1;
2171fd5fdc59SPat Donlin 	msg_data[2] = 0;
2172fd5fdc59SPat Donlin 	msg_data[3] = mode;
2173fd5fdc59SPat Donlin 	msg_data[4] = domain;
2174fd5fdc59SPat Donlin 	msg_data[5] = policy_id;
2175fd5fdc59SPat Donlin 	memset(&req, 0, sizeof(req));
2176fd5fdc59SPat Donlin 	req.msg.netfn = IPMI_NETFN_OEM;
2177fd5fdc59SPat Donlin 	req.msg.cmd = IPMI_NM_GET_STATS;
2178fd5fdc59SPat Donlin 	req.msg.data = msg_data;
2179fd5fdc59SPat Donlin 	req.msg.data_len = 6;
2180fd5fdc59SPat Donlin 	rsp = intf->sendrecv(intf, &req);
2181fd5fdc59SPat Donlin 	if (chk_nm_rsp(rsp)) {
2182fd5fdc59SPat Donlin 		return -1;
2183fd5fdc59SPat Donlin 	}
2184fd5fdc59SPat Donlin 	memcpy(caps, rsp->data, sizeof (struct nm_statistics));
2185fd5fdc59SPat Donlin 	return 0;
2186fd5fdc59SPat Donlin }
2187fd5fdc59SPat Donlin 
2188fd5fdc59SPat Donlin static int
_ipmi_nm_reset_stats(struct ipmi_intf * intf,uint8_t mode,uint8_t domain,uint8_t policy_id)2189fd5fdc59SPat Donlin _ipmi_nm_reset_stats(struct ipmi_intf * intf, uint8_t mode, uint8_t domain, uint8_t policy_id)
2190fd5fdc59SPat Donlin {
2191fd5fdc59SPat Donlin 	struct ipmi_rq req; /* request data to send to the BMC */
2192fd5fdc59SPat Donlin 	struct ipmi_rs *rsp;
2193fd5fdc59SPat Donlin 	uint8_t msg_data[6]; /* 'raw' data to be sent to the BMC */
2194fd5fdc59SPat Donlin 
2195fd5fdc59SPat Donlin 	msg_data[0] = 0x57;
2196fd5fdc59SPat Donlin 	msg_data[1] = 1;
2197fd5fdc59SPat Donlin 	msg_data[2] = 0;
2198fd5fdc59SPat Donlin 	msg_data[3] = mode;
2199fd5fdc59SPat Donlin 	msg_data[4] = domain;
2200fd5fdc59SPat Donlin 	msg_data[5] = policy_id;
2201fd5fdc59SPat Donlin 	memset(&req, 0, sizeof(req));
2202fd5fdc59SPat Donlin 	req.msg.netfn = IPMI_NETFN_OEM;
2203fd5fdc59SPat Donlin 	req.msg.cmd = IPMI_NM_RESET_STATS;
2204fd5fdc59SPat Donlin 	req.msg.data = msg_data;
2205fd5fdc59SPat Donlin 	req.msg.data_len = 6;
2206fd5fdc59SPat Donlin 	rsp = intf->sendrecv(intf, &req);
2207fd5fdc59SPat Donlin 	if (chk_nm_rsp(rsp)) {
2208fd5fdc59SPat Donlin 		return -1;
2209fd5fdc59SPat Donlin 	}
2210fd5fdc59SPat Donlin 	return 0;
2211fd5fdc59SPat Donlin }
2212fd5fdc59SPat Donlin 
2213fd5fdc59SPat Donlin static int
_nm_set_range(struct ipmi_intf * intf,uint8_t domain,uint16_t minimum,uint16_t maximum)2214fd5fdc59SPat Donlin _nm_set_range(struct ipmi_intf * intf, uint8_t domain, uint16_t minimum, uint16_t maximum)
2215fd5fdc59SPat Donlin {
2216fd5fdc59SPat Donlin 	struct ipmi_rq req; /* request data to send to the BMC */
2217fd5fdc59SPat Donlin 	struct ipmi_rs *rsp;
2218fd5fdc59SPat Donlin 	uint8_t msg_data[8]; /* 'raw' data to be sent to the BMC */
2219fd5fdc59SPat Donlin 
2220fd5fdc59SPat Donlin 	msg_data[0] = 0x57;
2221fd5fdc59SPat Donlin 	msg_data[1] = 1;
2222fd5fdc59SPat Donlin 	msg_data[2] = 0;
2223fd5fdc59SPat Donlin 	msg_data[3] = domain;
2224fd5fdc59SPat Donlin 	msg_data[4] = minimum & 0xFF;
2225fd5fdc59SPat Donlin 	msg_data[5] = minimum >> 8;
2226fd5fdc59SPat Donlin 	msg_data[6] = maximum & 0xFF;
2227fd5fdc59SPat Donlin 	msg_data[7] = maximum >> 8;
2228fd5fdc59SPat Donlin 	memset(&req, 0, sizeof(req));
2229fd5fdc59SPat Donlin 	req.msg.netfn = IPMI_NETFN_OEM;
2230fd5fdc59SPat Donlin 	req.msg.cmd = IPMI_NM_SET_POWER;
2231fd5fdc59SPat Donlin 	req.msg.data = msg_data;
2232fd5fdc59SPat Donlin 	req.msg.data_len = 8;
2233fd5fdc59SPat Donlin 	rsp = intf->sendrecv(intf, &req);
2234fd5fdc59SPat Donlin 	if (chk_nm_rsp(rsp)) {
2235fd5fdc59SPat Donlin 		return -1;
2236fd5fdc59SPat Donlin 	}
2237fd5fdc59SPat Donlin 	return 0;
2238fd5fdc59SPat Donlin }
2239fd5fdc59SPat Donlin 
2240fd5fdc59SPat Donlin static int
_ipmi_nm_get_alert(struct ipmi_intf * intf,struct nm_set_alert * alert)2241fd5fdc59SPat Donlin _ipmi_nm_get_alert(struct ipmi_intf * intf, struct nm_set_alert *alert)
2242fd5fdc59SPat Donlin {
2243fd5fdc59SPat Donlin 	struct ipmi_rq req; /* request data to send to the BMC */
2244fd5fdc59SPat Donlin 	struct ipmi_rs *rsp;
2245fd5fdc59SPat Donlin 	uint8_t msg_data[3]; /* 'raw' data to be sent to the BMC */
2246fd5fdc59SPat Donlin 
2247fd5fdc59SPat Donlin 	msg_data[0] = 0x57;
2248fd5fdc59SPat Donlin 	msg_data[1] = 1;
2249fd5fdc59SPat Donlin 	msg_data[2] = 0;
2250fd5fdc59SPat Donlin 	memset(&req, 0, sizeof(req));
2251fd5fdc59SPat Donlin 	req.msg.netfn = IPMI_NETFN_OEM;
2252fd5fdc59SPat Donlin 	req.msg.cmd = IPMI_NM_GET_ALERT_DS;
2253fd5fdc59SPat Donlin 	req.msg.data = msg_data;
2254fd5fdc59SPat Donlin 	req.msg.data_len = 3;
2255fd5fdc59SPat Donlin 	rsp = intf->sendrecv(intf, &req);
2256fd5fdc59SPat Donlin 	if (chk_nm_rsp(rsp)) {
2257fd5fdc59SPat Donlin 		return -1;
2258fd5fdc59SPat Donlin 	}
2259fd5fdc59SPat Donlin 	memcpy(alert, rsp->data, sizeof (struct nm_set_alert));
2260fd5fdc59SPat Donlin 	return 0;
2261fd5fdc59SPat Donlin }
2262fd5fdc59SPat Donlin 
2263fd5fdc59SPat Donlin static int
_ipmi_nm_set_alert(struct ipmi_intf * intf,struct nm_set_alert * alert)2264fd5fdc59SPat Donlin _ipmi_nm_set_alert(struct ipmi_intf * intf, struct nm_set_alert *alert)
2265fd5fdc59SPat Donlin {
2266fd5fdc59SPat Donlin 	struct ipmi_rq req; /* request data to send to the BMC */
2267fd5fdc59SPat Donlin 	struct ipmi_rs *rsp;
2268fd5fdc59SPat Donlin 	uint8_t msg_data[6]; /* 'raw' data to be sent to the BMC */
2269fd5fdc59SPat Donlin 
2270fd5fdc59SPat Donlin 	msg_data[0] = 0x57;
2271fd5fdc59SPat Donlin 	msg_data[1] = 1;
2272fd5fdc59SPat Donlin 	msg_data[2] = 0;
2273fd5fdc59SPat Donlin 	msg_data[3] = alert->chan;
2274fd5fdc59SPat Donlin 	msg_data[4] = alert->dest;
2275fd5fdc59SPat Donlin 	msg_data[5] = alert->string;
2276fd5fdc59SPat Donlin 	memset(&req, 0, sizeof(req));
2277fd5fdc59SPat Donlin 	req.msg.netfn = IPMI_NETFN_OEM;
2278fd5fdc59SPat Donlin 	req.msg.cmd = IPMI_NM_SET_ALERT_DS;
2279fd5fdc59SPat Donlin 	req.msg.data = msg_data;
2280fd5fdc59SPat Donlin 	req.msg.data_len = 6;
2281fd5fdc59SPat Donlin 	rsp = intf->sendrecv(intf, &req);
2282fd5fdc59SPat Donlin 	if (chk_nm_rsp(rsp)) {
2283fd5fdc59SPat Donlin 		return -1;
2284fd5fdc59SPat Donlin 	}
2285fd5fdc59SPat Donlin 	return 0;
2286fd5fdc59SPat Donlin }
2287fd5fdc59SPat Donlin 
2288fd5fdc59SPat Donlin /*
2289fd5fdc59SPat Donlin  *
2290fd5fdc59SPat Donlin  * get alert threshold values.
2291fd5fdc59SPat Donlin  *
2292fd5fdc59SPat Donlin  * the list pointer is assumed to point to an array of 16 short integers.
2293fd5fdc59SPat Donlin  * This array is filled in for valid thresholds returned.
2294fd5fdc59SPat Donlin  */
2295fd5fdc59SPat Donlin static int
_ipmi_nm_get_thresh(struct ipmi_intf * intf,uint8_t domain,uint8_t policy_id,uint16_t * list)2296fd5fdc59SPat Donlin _ipmi_nm_get_thresh(struct ipmi_intf * intf, uint8_t domain, uint8_t policy_id, uint16_t *list)
2297fd5fdc59SPat Donlin {
2298fd5fdc59SPat Donlin 	struct ipmi_rq req; /* request data to send to the BMC */
2299fd5fdc59SPat Donlin 	struct ipmi_rs *rsp;
2300fd5fdc59SPat Donlin 	uint8_t msg_data[5]; /* 'raw' data to be sent to the BMC */
2301fd5fdc59SPat Donlin 
2302fd5fdc59SPat Donlin 	msg_data[0] = 0x57;
2303fd5fdc59SPat Donlin 	msg_data[1] = 1;
2304fd5fdc59SPat Donlin 	msg_data[2] = 0;
2305fd5fdc59SPat Donlin 	msg_data[3] = domain;
2306fd5fdc59SPat Donlin 	msg_data[4] = policy_id;
2307fd5fdc59SPat Donlin 	memset(&req, 0, sizeof(req));
2308fd5fdc59SPat Donlin 	req.msg.netfn = IPMI_NETFN_OEM;
2309fd5fdc59SPat Donlin 	req.msg.cmd = IPMI_NM_GET_ALERT_TH;
2310fd5fdc59SPat Donlin 	req.msg.data = msg_data;
2311fd5fdc59SPat Donlin 	req.msg.data_len = 5;
2312fd5fdc59SPat Donlin 	rsp = intf->sendrecv(intf, &req);
2313fd5fdc59SPat Donlin 	if (chk_nm_rsp(rsp)) {
2314fd5fdc59SPat Donlin 		return -1;
2315fd5fdc59SPat Donlin 	}
2316fd5fdc59SPat Donlin 	if (rsp->data[3] > 0)
2317fd5fdc59SPat Donlin 		*list++ = (rsp->data[5] << 8) | rsp->data[4];
2318fd5fdc59SPat Donlin 	if (rsp->data[3] > 1)
2319fd5fdc59SPat Donlin 		*list++ = (rsp->data[7] << 8) | rsp->data[6];
2320fd5fdc59SPat Donlin 	if (rsp->data[3] > 2)
2321fd5fdc59SPat Donlin 		*list   = (rsp->data[9] << 8) | rsp->data[8];
2322fd5fdc59SPat Donlin 	return 0;
2323fd5fdc59SPat Donlin }
2324fd5fdc59SPat Donlin 
2325fd5fdc59SPat Donlin static int
_ipmi_nm_set_thresh(struct ipmi_intf * intf,struct nm_thresh * thresh)2326fd5fdc59SPat Donlin _ipmi_nm_set_thresh(struct ipmi_intf * intf, struct nm_thresh * thresh)
2327fd5fdc59SPat Donlin {
2328fd5fdc59SPat Donlin 	struct ipmi_rq req; /* request data to send to the BMC */
2329fd5fdc59SPat Donlin 	struct ipmi_rs *rsp;
2330fd5fdc59SPat Donlin 	uint8_t msg_data[IPMI_NM_SET_THRESH_LEN]; /* 'raw' data to be sent to the BMC */
2331fd5fdc59SPat Donlin 
2332fd5fdc59SPat Donlin 	memset(&msg_data, 0, sizeof(msg_data));
2333fd5fdc59SPat Donlin 	msg_data[0] = 0x57;
2334fd5fdc59SPat Donlin 	msg_data[1] = 1;
2335fd5fdc59SPat Donlin 	msg_data[2] = 0;
2336fd5fdc59SPat Donlin 	msg_data[3] = thresh->domain;
2337fd5fdc59SPat Donlin 	msg_data[4] = thresh->policy_id;
2338fd5fdc59SPat Donlin 	msg_data[5] = thresh->count;
2339fd5fdc59SPat Donlin 	if (thresh->count > 0) {
2340fd5fdc59SPat Donlin 		msg_data[7] = thresh->thresholds[0] >> 8;
2341fd5fdc59SPat Donlin 		msg_data[6] = thresh->thresholds[0] & 0xFF;
2342fd5fdc59SPat Donlin 	}
2343fd5fdc59SPat Donlin 	if (thresh->count > 1) {
2344fd5fdc59SPat Donlin 		msg_data[9] = thresh->thresholds[1] >> 8;
2345fd5fdc59SPat Donlin 		msg_data[8] = thresh->thresholds[1] & 0xFF;
2346fd5fdc59SPat Donlin 	}
2347fd5fdc59SPat Donlin 	if (thresh->count > 2) {
2348fd5fdc59SPat Donlin 		msg_data[11] = thresh->thresholds[2] >> 8;
2349fd5fdc59SPat Donlin 		msg_data[10] = thresh->thresholds[2] & 0xFF;
2350fd5fdc59SPat Donlin 	}
2351fd5fdc59SPat Donlin 	memset(&req, 0, sizeof(req));
2352fd5fdc59SPat Donlin 	req.msg.netfn = IPMI_NETFN_OEM;
2353fd5fdc59SPat Donlin 	req.msg.cmd = IPMI_NM_SET_ALERT_TH;
2354fd5fdc59SPat Donlin 	req.msg.data = msg_data;
2355fd5fdc59SPat Donlin 	req.msg.data_len = 6 + (thresh->count * 2);
2356fd5fdc59SPat Donlin 	rsp = intf->sendrecv(intf, &req);
2357fd5fdc59SPat Donlin 	if (chk_nm_rsp(rsp)) {
2358fd5fdc59SPat Donlin 		return -1;
2359fd5fdc59SPat Donlin 	}
2360fd5fdc59SPat Donlin 	return 0;
2361fd5fdc59SPat Donlin }
2362fd5fdc59SPat Donlin 
2363fd5fdc59SPat Donlin /*
2364fd5fdc59SPat Donlin  *
2365fd5fdc59SPat Donlin  * get suspend periods
2366fd5fdc59SPat Donlin  *
2367fd5fdc59SPat Donlin  */
2368fd5fdc59SPat Donlin static int
_ipmi_nm_get_suspend(struct ipmi_intf * intf,uint8_t domain,uint8_t policy_id,int * count,struct nm_period * periods)2369fd5fdc59SPat Donlin _ipmi_nm_get_suspend(struct ipmi_intf * intf, uint8_t domain, uint8_t policy_id, int *count, struct nm_period *periods)
2370fd5fdc59SPat Donlin {
2371fd5fdc59SPat Donlin 	struct ipmi_rq req; /* request data to send to the BMC */
2372fd5fdc59SPat Donlin 	struct ipmi_rs *rsp;
2373fd5fdc59SPat Donlin 	uint8_t msg_data[5]; /* 'raw' data to be sent to the BMC */
2374fd5fdc59SPat Donlin 	int i;
2375fd5fdc59SPat Donlin 
2376fd5fdc59SPat Donlin 	msg_data[0] = 0x57;
2377fd5fdc59SPat Donlin 	msg_data[1] = 1;
2378fd5fdc59SPat Donlin 	msg_data[2] = 0;
2379fd5fdc59SPat Donlin 	msg_data[3] = domain;
2380fd5fdc59SPat Donlin 	msg_data[4] = policy_id;
2381fd5fdc59SPat Donlin 	memset(&req, 0, sizeof(req));
2382fd5fdc59SPat Donlin 	req.msg.netfn = IPMI_NETFN_OEM;
2383fd5fdc59SPat Donlin 	req.msg.cmd = IPMI_NM_GET_SUSPEND;
2384fd5fdc59SPat Donlin 	req.msg.data = msg_data;
2385fd5fdc59SPat Donlin 	req.msg.data_len = 5;
2386fd5fdc59SPat Donlin 	rsp = intf->sendrecv(intf, &req);
2387fd5fdc59SPat Donlin 	if (chk_nm_rsp(rsp)) {
2388fd5fdc59SPat Donlin 		return -1;
2389fd5fdc59SPat Donlin 	}
2390fd5fdc59SPat Donlin 	*count = rsp->data[3];
2391fd5fdc59SPat Donlin 	for (i = 0; i < rsp->data[3]; i += 3, periods++) {
2392fd5fdc59SPat Donlin 		periods->start = rsp->data[4+i];
2393fd5fdc59SPat Donlin 		periods->stop  = rsp->data[5+i];
2394fd5fdc59SPat Donlin 		periods->repeat = rsp->data[6+i];
2395fd5fdc59SPat Donlin 	}
2396fd5fdc59SPat Donlin 	return 0;
2397fd5fdc59SPat Donlin }
2398fd5fdc59SPat Donlin 
2399fd5fdc59SPat Donlin static int
_ipmi_nm_set_suspend(struct ipmi_intf * intf,struct nm_suspend * suspend)2400fd5fdc59SPat Donlin _ipmi_nm_set_suspend(struct ipmi_intf * intf, struct nm_suspend *suspend)
2401fd5fdc59SPat Donlin {
2402fd5fdc59SPat Donlin 	struct ipmi_rq req; /* request data to send to the BMC */
2403fd5fdc59SPat Donlin 	struct ipmi_rs *rsp;
2404fd5fdc59SPat Donlin 	uint8_t msg_data[21]; /* 6 control bytes + 5 suspend periods, 3 bytes per period */
2405fd5fdc59SPat Donlin 	struct nm_period *periods;
2406fd5fdc59SPat Donlin 	int i;
2407fd5fdc59SPat Donlin 
2408fd5fdc59SPat Donlin 	msg_data[0] = 0x57;
2409fd5fdc59SPat Donlin 	msg_data[1] = 1;
2410fd5fdc59SPat Donlin 	msg_data[2] = 0;
2411fd5fdc59SPat Donlin 	msg_data[3] = suspend->domain;
2412fd5fdc59SPat Donlin         msg_data[4] = suspend->policy_id;
2413fd5fdc59SPat Donlin 	msg_data[5] = suspend->count;
2414fd5fdc59SPat Donlin 	for (i = 0, periods = &suspend->period[0]; i < (suspend->count*3); i += 3, periods++) {
2415fd5fdc59SPat Donlin 		msg_data[6+i] = periods->start;
2416fd5fdc59SPat Donlin 		msg_data[7+i] = periods->stop;
2417fd5fdc59SPat Donlin 		msg_data[8+i] = periods->repeat;
2418fd5fdc59SPat Donlin 	}
2419fd5fdc59SPat Donlin 	memset(&req, 0, sizeof(req));
2420fd5fdc59SPat Donlin 	req.msg.data_len = 6 + (suspend->count*3);
2421fd5fdc59SPat Donlin 	req.msg.netfn = IPMI_NETFN_OEM;
2422fd5fdc59SPat Donlin 	req.msg.cmd = IPMI_NM_SET_SUSPEND;
2423fd5fdc59SPat Donlin 	req.msg.data = msg_data;
2424fd5fdc59SPat Donlin         rsp = intf->sendrecv(intf, &req);
2425fd5fdc59SPat Donlin         if (chk_nm_rsp(rsp)) {
2426fd5fdc59SPat Donlin 		return -1;
2427fd5fdc59SPat Donlin 	}
2428fd5fdc59SPat Donlin 	return 0;
2429fd5fdc59SPat Donlin }
2430fd5fdc59SPat Donlin 
2431fd5fdc59SPat Donlin static int
ipmi_nm_getcapabilities(struct ipmi_intf * intf,int argc,char ** argv)2432fd5fdc59SPat Donlin ipmi_nm_getcapabilities(struct ipmi_intf * intf, int argc, char **argv)
2433fd5fdc59SPat Donlin {
2434fd5fdc59SPat Donlin 	uint8_t option;
2435fd5fdc59SPat Donlin 	uint8_t domain = 0;  /* default domain of platform */
2436fd5fdc59SPat Donlin 	uint8_t trigger = 0; /* default power policy (no trigger) */
2437fd5fdc59SPat Donlin 	struct nm_capability caps;
2438fd5fdc59SPat Donlin 
2439fd5fdc59SPat Donlin         while (--argc > 0) {
2440fd5fdc59SPat Donlin 		argv++;
2441fd5fdc59SPat Donlin 		if (argv[0] == NULL) break;
2442fd5fdc59SPat Donlin 		if ((option = str2val2(argv[0], nm_capability_opts)) == 0xFF) {
2443fd5fdc59SPat Donlin 			print_strs(nm_capability_opts, "Capability commands", LOG_ERR, 0);
2444fd5fdc59SPat Donlin 			return -1;
2445fd5fdc59SPat Donlin 		}
2446fd5fdc59SPat Donlin 		switch (option) {
2447fd5fdc59SPat Donlin 		case 0x01:   /* get domain scope */
2448fd5fdc59SPat Donlin 			if ((domain = str2val2(argv[1], nm_domain_vals)) == 0xFF) {
2449fd5fdc59SPat Donlin 				print_strs(nm_domain_vals, "Domain Scope:", LOG_ERR, 0);
2450fd5fdc59SPat Donlin 				return -1;
2451fd5fdc59SPat Donlin 			}
2452fd5fdc59SPat Donlin 			break;
2453fd5fdc59SPat Donlin 		case 0x02:  /* Inlet */
2454fd5fdc59SPat Donlin 			trigger = 1;
2455fd5fdc59SPat Donlin 			break;
2456fd5fdc59SPat Donlin 		case 0x03:  /* Missing power reading */
2457fd5fdc59SPat Donlin 			trigger = 2;
2458fd5fdc59SPat Donlin 			break;
2459fd5fdc59SPat Donlin 		case 0x04:  /* Time after host reset */
2460fd5fdc59SPat Donlin 			trigger = 3;
2461fd5fdc59SPat Donlin 			break;
2462fd5fdc59SPat Donlin 		case 0x05:  /* Boot time policy */
2463fd5fdc59SPat Donlin 			trigger = 4;
2464fd5fdc59SPat Donlin 			break;
2465fd5fdc59SPat Donlin 		default:
2466fd5fdc59SPat Donlin 			break;
2467fd5fdc59SPat Donlin 		}
2468fd5fdc59SPat Donlin 		argc--;
2469fd5fdc59SPat Donlin 		argv++;
2470fd5fdc59SPat Donlin 	}
2471fd5fdc59SPat Donlin 	trigger |= 0x10;
2472fd5fdc59SPat Donlin 	memset(&caps, 0, sizeof(caps));
2473fd5fdc59SPat Donlin 	if (_ipmi_nm_getcapabilities(intf, domain, trigger, &caps))
2474fd5fdc59SPat Donlin 		return -1;
2475fd5fdc59SPat Donlin 	if (csv_output) {
2476fd5fdc59SPat Donlin 		printf("%d,%u,%u,%u,%u,%u,%u,%s\n",
2477fd5fdc59SPat Donlin 			caps.max_settings, caps.max_value,caps.min_value,
2478fd5fdc59SPat Donlin 			caps.min_corr/1000, caps.max_corr/1000,
2479fd5fdc59SPat Donlin 			caps.min_stats, caps.max_stats,
2480fd5fdc59SPat Donlin 			val2str2(caps.scope&0xF, nm_domain_vals));
2481fd5fdc59SPat Donlin 		return 0;
2482fd5fdc59SPat Donlin 	}
2483fd5fdc59SPat Donlin 	printf("    power policies:\t\t%d\n", caps.max_settings);
2484fd5fdc59SPat Donlin 	switch (trigger&0xF) {
2485fd5fdc59SPat Donlin 	case 0:  /* power */
2486fd5fdc59SPat Donlin 		printf("    max_power\t\t%7u Watts\n    min_power\t\t%7u Watts\n",
2487fd5fdc59SPat Donlin 				caps.max_value, caps.min_value);
2488fd5fdc59SPat Donlin 		break;
2489fd5fdc59SPat Donlin 	case 1:  /* Inlet */
2490fd5fdc59SPat Donlin 		printf("    max_temp\t\t%7u C\n    min_temp\t\t%7u C\n",
2491fd5fdc59SPat Donlin 				caps.max_value, caps.min_value);
2492fd5fdc59SPat Donlin 		break;
2493fd5fdc59SPat Donlin 	case 2: /* Missing reading time */
2494fd5fdc59SPat Donlin 	case 3: /* Time after host reset */
2495fd5fdc59SPat Donlin 		printf("    max_time\t\t%7u Secs\n    min_time\t\t%7u Secs\n",
2496fd5fdc59SPat Donlin 				caps.max_value/10, caps.min_value/10);
2497fd5fdc59SPat Donlin 		break;
2498fd5fdc59SPat Donlin 	case 4: /* boot time policy does not use these values */
2499fd5fdc59SPat Donlin 	default:
2500fd5fdc59SPat Donlin 		break;
2501fd5fdc59SPat Donlin 	}
2502fd5fdc59SPat Donlin 	printf("    min_corr\t\t%7u secs\n    max_corr\t\t%7u secs\n",
2503fd5fdc59SPat Donlin 				caps.min_corr/1000, caps.max_corr/1000);
2504fd5fdc59SPat Donlin 	printf("    min_stats\t\t%7u secs\n    max_stats\t\t%7u secs\n",
2505fd5fdc59SPat Donlin 				caps.min_stats, caps.max_stats);
2506fd5fdc59SPat Donlin 	printf("    domain scope:\t%s\n", val2str2(caps.scope&0xF, nm_domain_vals));
2507fd5fdc59SPat Donlin 	return 0;
2508fd5fdc59SPat Donlin }
2509fd5fdc59SPat Donlin 
2510fd5fdc59SPat Donlin static int
ipmi_nm_get_policy(struct ipmi_intf * intf,int argc,char ** argv)2511fd5fdc59SPat Donlin ipmi_nm_get_policy(struct ipmi_intf * intf, int argc, char **argv)
2512fd5fdc59SPat Donlin {
2513fd5fdc59SPat Donlin 	uint8_t option;
2514fd5fdc59SPat Donlin 	uint8_t domain = 0; /* default domain of platform */
2515fd5fdc59SPat Donlin 	uint8_t policy_id = -1;
2516fd5fdc59SPat Donlin 	struct nm_get_policy policy;
2517fd5fdc59SPat Donlin 
2518fd5fdc59SPat Donlin 	memset(&policy, 0, sizeof(policy));
2519fd5fdc59SPat Donlin 
2520fd5fdc59SPat Donlin 	while (--argc) {
2521fd5fdc59SPat Donlin 		argv++;
2522fd5fdc59SPat Donlin 		if (argv[0] == NULL) break;
2523fd5fdc59SPat Donlin 		if ((option = str2val2(argv[0], nm_policy_options)) == 0xFF) {
2524fd5fdc59SPat Donlin 			print_strs(nm_policy_options, "Get Policy commands", LOG_ERR, 0);
2525fd5fdc59SPat Donlin 			return -1;
2526fd5fdc59SPat Donlin 		}
2527fd5fdc59SPat Donlin 		switch (option) {
2528fd5fdc59SPat Donlin 		case 0x03:   /* get domain scope */
2529fd5fdc59SPat Donlin 			if ((domain = str2val2(argv[1], nm_domain_vals)) == 0xFF) {
2530fd5fdc59SPat Donlin 				print_strs(nm_domain_vals, "Domain Scope:", LOG_ERR, 0);
2531fd5fdc59SPat Donlin 				return -1;
2532fd5fdc59SPat Donlin 			}
2533fd5fdc59SPat Donlin 			policy.domain |= domain & 0xF;
2534fd5fdc59SPat Donlin 			break;
2535fd5fdc59SPat Donlin 		case 0x0B:   /* policy id */
2536fd5fdc59SPat Donlin 			if (str2uchar(argv[1], &policy_id) < 0) {
2537fd5fdc59SPat Donlin 				lprintf(LOG_ERR,"    Policy ID must be a positive integer 0-7.\n");
2538fd5fdc59SPat Donlin 				return -1;
2539fd5fdc59SPat Donlin 			}
2540fd5fdc59SPat Donlin 			break;
2541fd5fdc59SPat Donlin 		default:
2542fd5fdc59SPat Donlin 			printf("    Unknown command 0x%x, skipping.\n", option);
2543fd5fdc59SPat Donlin 			break;
2544fd5fdc59SPat Donlin 		}
2545fd5fdc59SPat Donlin 		argc--;
2546fd5fdc59SPat Donlin 		argv++;
2547fd5fdc59SPat Donlin 	}
2548fd5fdc59SPat Donlin         if (policy_id == 0xFF) {
2549fd5fdc59SPat Donlin 		print_strs(nm_stats_opts, "Missing policy_id parameter:", LOG_ERR, 0);
2550fd5fdc59SPat Donlin                 return -1;
2551fd5fdc59SPat Donlin         }
2552fd5fdc59SPat Donlin 	if (_ipmi_nm_get_policy(intf, policy.domain, policy_id, &policy))
2553fd5fdc59SPat Donlin 		return -1;
2554fd5fdc59SPat Donlin 	if (csv_output) {
2555fd5fdc59SPat Donlin 		printf("%s,0x%x,%s,%s,%s,%u,%u,%u,%u,%s\n",
2556fd5fdc59SPat Donlin 			val2str2(policy.domain&0xF, nm_domain_vals),
2557fd5fdc59SPat Donlin 			policy.domain,
2558fd5fdc59SPat Donlin 			(policy.policy_type & 0x10) ? "power" : "nopower ",
2559fd5fdc59SPat Donlin 			val2str2(policy.policy_type & 0xF, nm_policy_type_vals),
2560fd5fdc59SPat Donlin 			val2str2(policy.policy_exception, nm_exception),
2561fd5fdc59SPat Donlin 			policy.policy_limits,
2562fd5fdc59SPat Donlin 			policy.corr_time,
2563fd5fdc59SPat Donlin 			policy.trigger_limit,
2564fd5fdc59SPat Donlin 			policy.stats_period,
2565fd5fdc59SPat Donlin 			policy.policy_type & 0x80 ? "volatile" : "non-volatile");
2566fd5fdc59SPat Donlin 		return 0;
2567fd5fdc59SPat Donlin 	}
2568fd5fdc59SPat Donlin 	printf("    Power domain:                             %s\n",
2569fd5fdc59SPat Donlin 		val2str2(policy.domain&0xF, nm_domain_vals));
2570fd5fdc59SPat Donlin 	printf("    Policy is %s %s%s%s\n",
2571fd5fdc59SPat Donlin 		policy.domain&0x10 ? "enabled" : "not enabled",
2572fd5fdc59SPat Donlin 		policy.domain&0x20 ? "per Domain " : "",
2573fd5fdc59SPat Donlin 		policy.domain&0x40 ? "Globally " : "",
2574fd5fdc59SPat Donlin 		policy.domain&0x80 ? "via DCMI api " : "");
2575fd5fdc59SPat Donlin 	printf("    Policy is %sa power control type.\n", (policy.policy_type & 0x10) ? "" : "not ");
2576fd5fdc59SPat Donlin 	printf("    Policy Trigger Type:                      %s\n",
2577fd5fdc59SPat Donlin 		val2str2(policy.policy_type & 0xF, nm_policy_type_vals));
2578fd5fdc59SPat Donlin 	printf("    Correction Aggressiveness:                %s\n",
2579fd5fdc59SPat Donlin 		val2str2((policy.policy_type>> 5) & 0x3, nm_correction_vals));
2580fd5fdc59SPat Donlin 	printf("    Policy Exception Actions:                 %s\n",
2581fd5fdc59SPat Donlin 		val2str2(policy.policy_exception, nm_exception));
2582fd5fdc59SPat Donlin 	printf("    Power Limit:                              %u Watts\n",
2583fd5fdc59SPat Donlin 		policy.policy_limits);
2584fd5fdc59SPat Donlin 	printf("    Correction Time Limit:                    %u milliseconds\n",
2585fd5fdc59SPat Donlin 		policy.corr_time);
2586fd5fdc59SPat Donlin 	printf("    Trigger Limit:                            %u units\n",
2587fd5fdc59SPat Donlin 		policy.trigger_limit);
2588fd5fdc59SPat Donlin 	printf("    Statistics Reporting Period:              %u seconds\n",
2589fd5fdc59SPat Donlin 		policy.stats_period);
2590fd5fdc59SPat Donlin 	printf("    Policy retention:                         %s\n",
2591fd5fdc59SPat Donlin 		policy.policy_type & 0x80 ? "volatile" : "non-volatile");
2592fd5fdc59SPat Donlin 	if ( (policy_id == 0) && ((policy.domain & 0xf) == 0x3) )
2593fd5fdc59SPat Donlin 		printf("    HW Prot Power domain:                     %s\n",
2594fd5fdc59SPat Donlin 			policy.policy_type & 0x80 ? "Secondary" : "Primary");
2595fd5fdc59SPat Donlin 	return 0;
2596fd5fdc59SPat Donlin }
2597fd5fdc59SPat Donlin 
2598fd5fdc59SPat Donlin static int
ipmi_nm_policy(struct ipmi_intf * intf,int argc,char ** argv)2599fd5fdc59SPat Donlin ipmi_nm_policy(struct ipmi_intf * intf, int argc, char **argv)
2600fd5fdc59SPat Donlin {
2601fd5fdc59SPat Donlin 	uint8_t action;
2602fd5fdc59SPat Donlin 	uint8_t option;
2603fd5fdc59SPat Donlin 	uint8_t correction;
2604fd5fdc59SPat Donlin 	uint8_t domain = 0; /* default domain of platform */
2605fd5fdc59SPat Donlin 	uint8_t policy_id = -1;
2606fd5fdc59SPat Donlin 	uint16_t power, period, inlet;
2607fd5fdc59SPat Donlin 	uint16_t cores;
2608fd5fdc59SPat Donlin 	uint32_t limit;
2609fd5fdc59SPat Donlin 	struct nm_policy policy;
2610fd5fdc59SPat Donlin 
2611fd5fdc59SPat Donlin 	argv++;
2612fd5fdc59SPat Donlin 	argc--;
2613fd5fdc59SPat Donlin 	if ((argv[0] == NULL) ||
2614fd5fdc59SPat Donlin 			((action = str2val2(argv[0], nm_policy_action)) == 0xFF)) {
2615fd5fdc59SPat Donlin 		print_strs(nm_policy_action, "Policy commands", LOG_ERR, 0);
2616fd5fdc59SPat Donlin 		return -1;
2617fd5fdc59SPat Donlin 	}
2618fd5fdc59SPat Donlin 	if (action == 0) /* get */
2619fd5fdc59SPat Donlin 		return (ipmi_nm_get_policy(intf, argc, argv));
2620fd5fdc59SPat Donlin 	memset(&policy, 0, sizeof(policy));
2621fd5fdc59SPat Donlin 	/*
2622fd5fdc59SPat Donlin 	 * nm policy add [domain <param>] enable|disable  policy_id <param> correction <opt> power <watts> limit <param> period <param>
2623fd5fdc59SPat Donlin 	 * nm policy remove [domain <param>]  policy_id <param>
2624fd5fdc59SPat Donlin 	 * nm policy limiting {domain <param>]
2625fd5fdc59SPat Donlin 	 */
2626fd5fdc59SPat Donlin 	while (--argc > 0) {
2627fd5fdc59SPat Donlin 		argv++;
2628fd5fdc59SPat Donlin 		if (argv[0] == NULL) break;
2629fd5fdc59SPat Donlin 		if ((option = str2val2(argv[0], nm_policy_options)) == 0xFF) {
2630fd5fdc59SPat Donlin 			print_strs(nm_policy_options, "Policy options", LOG_ERR, 0);
2631fd5fdc59SPat Donlin 			return -1;
2632fd5fdc59SPat Donlin 		}
2633fd5fdc59SPat Donlin 		switch (option) {
2634fd5fdc59SPat Donlin 		case 0x01:   /* policy enable */
2635fd5fdc59SPat Donlin 			policy.domain |= IPMI_NM_POLICY_ENABLE;
2636fd5fdc59SPat Donlin 			break;
2637fd5fdc59SPat Donlin 		case 0x02:   /* policy disable */
2638fd5fdc59SPat Donlin 			break;   /* value is initialized to zero already */
2639fd5fdc59SPat Donlin 		case 0x03:   /* get domain scope */
2640fd5fdc59SPat Donlin 			if ((domain = str2val2(argv[1], nm_domain_vals)) == 0xFF) {
2641fd5fdc59SPat Donlin 				print_strs(nm_domain_vals, "Domain Scope:", LOG_ERR, 0);
2642fd5fdc59SPat Donlin 				return -1;
2643fd5fdc59SPat Donlin 			}
2644fd5fdc59SPat Donlin 			policy.domain |= domain & 0xF;
2645fd5fdc59SPat Donlin 			break;
2646fd5fdc59SPat Donlin 		case 0x04:   /* inlet */
2647fd5fdc59SPat Donlin 			if (str2ushort(argv[1], &inlet) < 0) {
2648fd5fdc59SPat Donlin 				printf("Inlet Temp value must be 20-45.\n");
2649fd5fdc59SPat Donlin 				return -1;
2650fd5fdc59SPat Donlin 			}
2651fd5fdc59SPat Donlin 			policy.policy_type |= 1;
2652fd5fdc59SPat Donlin 			policy.policy_limits = 0;
2653fd5fdc59SPat Donlin 			policy.trigger_limit = inlet;
2654fd5fdc59SPat Donlin 			break;
2655fd5fdc59SPat Donlin 		case 0x06:   /* get correction action */
2656fd5fdc59SPat Donlin 			if (action == 0x5) break;   /* skip if this is a remove */
2657fd5fdc59SPat Donlin 			if ((correction = str2val2(argv[1], nm_correction)) == 0xFF) {
2658fd5fdc59SPat Donlin 				print_strs(nm_correction, "Correction Actions", LOG_ERR, 0);
2659fd5fdc59SPat Donlin 				return -1;
2660fd5fdc59SPat Donlin 			}
2661fd5fdc59SPat Donlin 			policy.policy_type |= (correction << 5);
2662fd5fdc59SPat Donlin 			break;
2663fd5fdc59SPat Donlin 		case 0x07:   /* not implemented */
2664fd5fdc59SPat Donlin 			break;
2665fd5fdc59SPat Donlin 		case 0x08:   /* power */
2666fd5fdc59SPat Donlin 			if (str2ushort(argv[1], &power) < 0) {
2667fd5fdc59SPat Donlin 				printf("Power limit value must be 0-500.\n");
2668fd5fdc59SPat Donlin 				return -1;
2669fd5fdc59SPat Donlin 			}
2670fd5fdc59SPat Donlin 			policy.policy_limits = power;
2671fd5fdc59SPat Donlin 			break;
2672fd5fdc59SPat Donlin 		case 0x09:   /* trigger limit */
2673fd5fdc59SPat Donlin 			if (str2uint(argv[1], &limit) < 0) {
2674fd5fdc59SPat Donlin 				printf("Trigger Limit value must be positive integer.\n");
2675fd5fdc59SPat Donlin 				return -1;
2676fd5fdc59SPat Donlin 			}
2677fd5fdc59SPat Donlin 			policy.corr_time = limit;
2678fd5fdc59SPat Donlin 			break;
2679fd5fdc59SPat Donlin 		case 0x0A:   /* statistics period */
2680fd5fdc59SPat Donlin 			if (str2ushort(argv[1], &period) < 0) {
2681fd5fdc59SPat Donlin 				printf("Statistics Reporting Period must be positive integer.\n");
2682fd5fdc59SPat Donlin 				return -1;
2683fd5fdc59SPat Donlin 			}
2684fd5fdc59SPat Donlin 			policy.stats_period = period;
2685fd5fdc59SPat Donlin 			break;
2686fd5fdc59SPat Donlin 		case 0x0B:   /* policy ID */
2687fd5fdc59SPat Donlin 			if (str2uchar(argv[1], &policy_id) < 0) {
2688fd5fdc59SPat Donlin 				printf("Policy ID must be a positive integer 0-7.\n");
2689fd5fdc59SPat Donlin 				return -1;
2690fd5fdc59SPat Donlin 			}
2691fd5fdc59SPat Donlin 			policy.policy_id = policy_id;
2692fd5fdc59SPat Donlin 			break;
2693fd5fdc59SPat Donlin 		case 0x0C:   /* volatile */
2694fd5fdc59SPat Donlin 			policy.policy_type |= 0x80;
2695fd5fdc59SPat Donlin 			break;
2696fd5fdc59SPat Donlin 		case 0x0D:   /* cores_off, number of cores to disable at boot time */
2697fd5fdc59SPat Donlin 			policy.policy_type |= 4;
2698fd5fdc59SPat Donlin 			if (str2ushort(argv[1], &cores) < 0) {
2699fd5fdc59SPat Donlin 				printf("number of cores disabled must be 1-127.\n");
2700fd5fdc59SPat Donlin 				return -1;
2701fd5fdc59SPat Donlin 			}
2702fd5fdc59SPat Donlin 			if ((cores < 1) || (cores > 127)) {
2703fd5fdc59SPat Donlin 				printf("number of cores disabled must be 1-127.\n");
2704fd5fdc59SPat Donlin 				return -1;
2705fd5fdc59SPat Donlin 			}
2706fd5fdc59SPat Donlin 			policy.policy_type |= 4;
2707fd5fdc59SPat Donlin 			policy.policy_limits = cores << 1;
2708fd5fdc59SPat Donlin 			break;
2709fd5fdc59SPat Donlin 		default:
2710fd5fdc59SPat Donlin 			break;
2711fd5fdc59SPat Donlin 		}
2712fd5fdc59SPat Donlin 		argc--;
2713fd5fdc59SPat Donlin 		argv++;
2714fd5fdc59SPat Donlin 	}
2715fd5fdc59SPat Donlin 	if (action == 0x06) { /* limiting */
2716fd5fdc59SPat Donlin 		if ((limit = _ipmi_nm_policy_limiting(intf, domain) == -1))
2717fd5fdc59SPat Donlin 			return -1;
2718fd5fdc59SPat Donlin 		printf("limit %x\n", limit);
2719fd5fdc59SPat Donlin 		return 0;
2720fd5fdc59SPat Donlin 	}
2721fd5fdc59SPat Donlin 	if (policy_id == 0xFF) {
2722fd5fdc59SPat Donlin 		print_strs(nm_stats_opts, "Missing policy_id parameter:", LOG_ERR, 0);
2723fd5fdc59SPat Donlin 		return -1;
2724fd5fdc59SPat Donlin 	}
2725fd5fdc59SPat Donlin 	if (action == 0x04)   /* add */
2726fd5fdc59SPat Donlin 		policy.policy_type |= 0x10;
2727fd5fdc59SPat Donlin 	if (_ipmi_nm_set_policy(intf, &policy))
2728fd5fdc59SPat Donlin 		return -1;
2729fd5fdc59SPat Donlin 	return 0;
2730fd5fdc59SPat Donlin }
2731fd5fdc59SPat Donlin /* end policy */
2732fd5fdc59SPat Donlin 
2733fd5fdc59SPat Donlin static int
ipmi_nm_control(struct ipmi_intf * intf,int argc,char ** argv)2734fd5fdc59SPat Donlin ipmi_nm_control(struct ipmi_intf * intf, int argc, char **argv)
2735fd5fdc59SPat Donlin {
2736fd5fdc59SPat Donlin 	uint8_t action;
2737fd5fdc59SPat Donlin 	uint8_t scope = 0;   /* default control scope of global */
2738fd5fdc59SPat Donlin 	uint8_t domain = 0;  /* default domain of platform */
2739fd5fdc59SPat Donlin 	uint8_t policy_id = -1;
2740fd5fdc59SPat Donlin 
2741fd5fdc59SPat Donlin 	argv++;
2742fd5fdc59SPat Donlin 	argc--;
2743fd5fdc59SPat Donlin 	/* nm_ctl_cmds returns 0 for disable, 1 for enable */
2744fd5fdc59SPat Donlin 	if ((argv[0] == NULL) ||
2745fd5fdc59SPat Donlin 			((action = str2val2(argv[0], nm_ctl_cmds)) == 0xFF)) {
2746fd5fdc59SPat Donlin 		print_strs(nm_ctl_cmds, "Control parameters:", LOG_ERR, 0);
2747fd5fdc59SPat Donlin 		print_strs(nm_ctl_domain, "control Scope (required):", LOG_ERR, 0);
2748fd5fdc59SPat Donlin 		return -1;
2749fd5fdc59SPat Donlin 	}
2750fd5fdc59SPat Donlin 	argv++;
2751fd5fdc59SPat Donlin 	while (--argc) {
2752fd5fdc59SPat Donlin 		/* nm_ctl_domain returns correct bit field except for action */
2753fd5fdc59SPat Donlin 		if ((argv[0] == NULL) ||
2754fd5fdc59SPat Donlin 				((scope = str2val2(argv[0], nm_ctl_domain)) == 0xFF)) {
2755fd5fdc59SPat Donlin 			print_strs(nm_ctl_domain, "Control Scope (required):", LOG_ERR, 0);
2756fd5fdc59SPat Donlin 			return -1;
2757fd5fdc59SPat Donlin 		}
2758fd5fdc59SPat Donlin 		argv++;
2759fd5fdc59SPat Donlin 		if (argv[0] == NULL) break;
2760fd5fdc59SPat Donlin 		if (scope == 0x02) { /* domain */
2761fd5fdc59SPat Donlin 			if ((domain = str2val2(argv[0], nm_domain_vals)) == 0xFF) {
2762fd5fdc59SPat Donlin 				print_strs(nm_domain_vals, "Domain Scope:", LOG_ERR, 0);
2763fd5fdc59SPat Donlin 				return -1;
2764fd5fdc59SPat Donlin 			}
2765fd5fdc59SPat Donlin 		} else if (scope == 0x04) { /* per_policy */
2766fd5fdc59SPat Donlin 
2767fd5fdc59SPat Donlin 			if (str2uchar(argv[0], &policy_id) < 0) {
2768fd5fdc59SPat Donlin 				lprintf(LOG_ERR,"Policy ID must be a positive integer.\n");
2769fd5fdc59SPat Donlin 				return -1;
2770fd5fdc59SPat Donlin 			}
2771fd5fdc59SPat Donlin 			break;
2772fd5fdc59SPat Donlin 		}
2773fd5fdc59SPat Donlin 		argc--;
2774fd5fdc59SPat Donlin 		argv++;
2775fd5fdc59SPat Donlin 	}
2776fd5fdc59SPat Donlin         if ((scope == 0x04) && (policy_id == 0xFF)) {
2777fd5fdc59SPat Donlin 		print_strs(nm_stats_opts, "Missing policy_id parameter:", LOG_ERR, 0);
2778fd5fdc59SPat Donlin 		return -1;
2779fd5fdc59SPat Donlin 	}
2780fd5fdc59SPat Donlin 	if (_ipmi_nm_control(intf, scope|(action&1), domain, policy_id) < 0 )
2781fd5fdc59SPat Donlin 		return -1;
2782fd5fdc59SPat Donlin 	return 0;
2783fd5fdc59SPat Donlin }
2784fd5fdc59SPat Donlin 
2785fd5fdc59SPat Donlin static int
ipmi_nm_get_statistics(struct ipmi_intf * intf,int argc,char ** argv)2786fd5fdc59SPat Donlin ipmi_nm_get_statistics(struct ipmi_intf * intf, int argc, char **argv)
2787fd5fdc59SPat Donlin {
2788fd5fdc59SPat Donlin 	uint8_t mode = 0;
2789fd5fdc59SPat Donlin 	uint8_t option;
2790fd5fdc59SPat Donlin 	uint8_t domain = 0;   /* default domain of platform */
2791fd5fdc59SPat Donlin 	uint8_t policy_id = -1;
2792fd5fdc59SPat Donlin 	int     policy_mode = 0;
2793fd5fdc59SPat Donlin 	int     cut;
2794fd5fdc59SPat Donlin 	char   *units = "";
2795fd5fdc59SPat Donlin 	char    datebuf[27];
2796fd5fdc59SPat Donlin 	struct nm_statistics stats;
2797fd5fdc59SPat Donlin 	struct tm tm_t;
2798fd5fdc59SPat Donlin 	time_t t;
2799fd5fdc59SPat Donlin 
2800fd5fdc59SPat Donlin 	argv++;
2801fd5fdc59SPat Donlin 	if ((argv[0] == NULL) ||
2802fd5fdc59SPat Donlin 			((mode = str2val2(argv[0], nm_stats_mode)) == 0xFF)) {
2803fd5fdc59SPat Donlin 		print_strs(nm_stats_mode, "Statistics commands", LOG_ERR, 0);
2804fd5fdc59SPat Donlin 		return -1;
2805fd5fdc59SPat Donlin 	}
2806fd5fdc59SPat Donlin 	while (--argc) {
2807fd5fdc59SPat Donlin 		argv++;
2808fd5fdc59SPat Donlin 		if (argv[0] == NULL) break;
2809fd5fdc59SPat Donlin 		if ((option = str2val2(argv[0], nm_stats_opts)) == 0xFF) {
2810fd5fdc59SPat Donlin 				print_strs(nm_stats_opts, "Control Scope options", LOG_ERR, 0);
2811fd5fdc59SPat Donlin 			return -1;
2812fd5fdc59SPat Donlin 		}
2813fd5fdc59SPat Donlin 		switch (option) {
2814fd5fdc59SPat Donlin 		case 0x01:   /* get domain scope */
2815fd5fdc59SPat Donlin 			if ((domain = str2val2(argv[1], nm_domain_vals)) == 0xFF) {
2816fd5fdc59SPat Donlin 				print_strs(nm_domain_vals, "Domain Scope:", LOG_ERR, 0);
2817fd5fdc59SPat Donlin 				return -1;
2818fd5fdc59SPat Donlin 			}
2819fd5fdc59SPat Donlin 			break;
2820fd5fdc59SPat Donlin 		case 0x02:   /* policy ID */
2821fd5fdc59SPat Donlin 			if (str2uchar(argv[1], &policy_id) < 0) {
2822fd5fdc59SPat Donlin 				lprintf(LOG_ERR,"Policy ID must be a positive integer.\n");
2823fd5fdc59SPat Donlin 				return -1;
2824fd5fdc59SPat Donlin 			}
2825fd5fdc59SPat Donlin 			break;
2826fd5fdc59SPat Donlin 		default:
2827fd5fdc59SPat Donlin 			break;
2828fd5fdc59SPat Donlin 		}
2829fd5fdc59SPat Donlin 		argc--;
2830fd5fdc59SPat Donlin 		argv++;
2831fd5fdc59SPat Donlin 	}
2832fd5fdc59SPat Donlin 
2833fd5fdc59SPat Donlin 	switch (mode) {
2834fd5fdc59SPat Donlin 	case 0x01:
2835fd5fdc59SPat Donlin 		units = "Watts";
2836c18ec02fSPetter Reinholdtsen 		break;
2837c18ec02fSPetter Reinholdtsen 	case 0x02:
2838fd5fdc59SPat Donlin 		units = "Celsius";
2839fd5fdc59SPat Donlin 		break;
2840fd5fdc59SPat Donlin 	case 0x03:
2841fd5fdc59SPat Donlin 		units = "%";
2842fd5fdc59SPat Donlin 		break;
2843fd5fdc59SPat Donlin 	case 0x11:
2844fd5fdc59SPat Donlin 	case 0x12:
2845fd5fdc59SPat Donlin 	case 0x13:
2846fd5fdc59SPat Donlin 		policy_mode = 1;
2847fd5fdc59SPat Donlin 		units = (mode == 0x11) ? "Watts" : (mode == 0x12) ? "Celsius" : " %";
2848fd5fdc59SPat Donlin 		if (policy_id == 0xFF) {
2849fd5fdc59SPat Donlin 			print_strs(nm_stats_opts, "Missing policy_id parameter:", LOG_ERR, 0);
2850c18ec02fSPetter Reinholdtsen 			return -1;
2851c18ec02fSPetter Reinholdtsen 		}
2852fd5fdc59SPat Donlin 		break;
2853fd5fdc59SPat Donlin 	default:
2854fd5fdc59SPat Donlin 		break;
2855fd5fdc59SPat Donlin 	}
2856fd5fdc59SPat Donlin 	if (_ipmi_nm_statistics(intf, mode, domain, policy_id, &stats))
2857fd5fdc59SPat Donlin 		return -1;
2858fd5fdc59SPat Donlin 	t = stats.time_stamp;
2859fd5fdc59SPat Donlin 	gmtime_r(&t, &tm_t);
2860fd5fdc59SPat Donlin 	sprintf(datebuf, "%s", asctime(&tm_t));
2861fd5fdc59SPat Donlin 	cut = strlen(datebuf) -1;
2862fd5fdc59SPat Donlin 	datebuf[cut] = 0;
2863fd5fdc59SPat Donlin 	if (csv_output) {
2864fd5fdc59SPat Donlin 		printf("%s,%s,%s,%s,%s,%d,%d,%d,%d,%s,%d\n",
2865fd5fdc59SPat Donlin 			val2str2(stats.id_state & 0xF, nm_domain_vals),
2866fd5fdc59SPat Donlin 			((stats.id_state >> 4) & 1) ? (policy_mode ? "Policy Enabled" : "Globally Enabled") : "Disabled" ,
2867fd5fdc59SPat Donlin 			((stats.id_state >> 5) & 1) ? "active" : "suspended",
2868fd5fdc59SPat Donlin 			((stats.id_state >> 6) & 1) ? "in progress" : "suspended",
2869fd5fdc59SPat Donlin 			((stats.id_state >> 7) & 1) ? "triggered" : "not triggered",
2870fd5fdc59SPat Donlin 			stats.curr_value,
2871fd5fdc59SPat Donlin 			stats.min_value,
2872fd5fdc59SPat Donlin 			stats.max_value,
2873fd5fdc59SPat Donlin 			stats.ave_value,
2874fd5fdc59SPat Donlin 			datebuf,
2875fd5fdc59SPat Donlin 			stats.stat_period);
2876fd5fdc59SPat Donlin 		return 0;
2877fd5fdc59SPat Donlin 	}
2878fd5fdc59SPat Donlin 	printf("    Power domain:                             %s\n",
2879fd5fdc59SPat Donlin 		val2str2(stats.id_state & 0xF, nm_domain_vals));
2880fd5fdc59SPat Donlin 	printf("    Policy/Global Admin state                 %s\n",
2881fd5fdc59SPat Donlin 		((stats.id_state >> 4) & 1) ? (policy_mode ? "Policy Enabled" : "Globally Enabled") : "Disabled" );
2882fd5fdc59SPat Donlin 	printf("    Policy/Global Operational state           %s\n",
2883fd5fdc59SPat Donlin 		((stats.id_state >> 5) & 1) ? "active" : "suspended");
2884fd5fdc59SPat Donlin 	printf("    Policy/Global Measurement state           %s\n",
2885fd5fdc59SPat Donlin 		((stats.id_state >> 6) & 1) ? "in progress" : "suspended");
2886fd5fdc59SPat Donlin 	printf("    Policy Activation state                   %s\n",
2887fd5fdc59SPat Donlin 		((stats.id_state >> 7) & 1) ? "triggered" : "not triggered");
2888fd5fdc59SPat Donlin 	printf("    Instantaneous reading:                    %8d %s\n",
2889fd5fdc59SPat Donlin 		stats.curr_value, units);
2890fd5fdc59SPat Donlin 	printf("    Minimum during sampling period:           %8d %s\n",
2891fd5fdc59SPat Donlin 		stats.min_value, units);
2892fd5fdc59SPat Donlin 	printf("    Maximum during sampling period:           %8d %s\n",
2893fd5fdc59SPat Donlin 		stats.max_value, units);
2894fd5fdc59SPat Donlin 	printf("    Average reading over sample period:       %8d %s\n",
2895fd5fdc59SPat Donlin 		stats.ave_value, units);
2896fd5fdc59SPat Donlin 	printf("    IPMI timestamp:                           %s\n",
2897fd5fdc59SPat Donlin 		datebuf);
2898fd5fdc59SPat Donlin 	printf("    Sampling period:                          %08d Seconds.\n", stats.stat_period);
2899fd5fdc59SPat Donlin 	printf("\n");
2900fd5fdc59SPat Donlin 	return 0;
2901fd5fdc59SPat Donlin }
2902fd5fdc59SPat Donlin 
2903fd5fdc59SPat Donlin static int
ipmi_nm_reset_statistics(struct ipmi_intf * intf,int argc,char ** argv)2904fd5fdc59SPat Donlin ipmi_nm_reset_statistics(struct ipmi_intf * intf, int argc, char **argv)
2905fd5fdc59SPat Donlin {
2906fd5fdc59SPat Donlin 	uint8_t mode;
2907fd5fdc59SPat Donlin 	uint8_t option;
2908fd5fdc59SPat Donlin 	uint8_t domain = 0;   /* default domain of platform */
2909fd5fdc59SPat Donlin 	uint8_t policy_id = -1;
2910fd5fdc59SPat Donlin 
2911fd5fdc59SPat Donlin 	argv++;
2912fd5fdc59SPat Donlin 	if ((argv[0] == NULL) ||
2913fd5fdc59SPat Donlin 			((mode = str2val2(argv[0], nm_reset_mode)) == 0xFF)) {
2914fd5fdc59SPat Donlin 		print_strs(nm_reset_mode, "Reset Statistics Modes:", LOG_ERR, 0);
2915fd5fdc59SPat Donlin 		return -1;
2916fd5fdc59SPat Donlin 	}
2917fd5fdc59SPat Donlin 	while (--argc) {
2918fd5fdc59SPat Donlin 		argv++;
2919fd5fdc59SPat Donlin 		if (argv[0] == NULL) break;
2920fd5fdc59SPat Donlin 		if ((option = str2val2(argv[0], nm_stats_opts)) == 0xFF) {
2921fd5fdc59SPat Donlin 			print_strs(nm_stats_opts, "Reset Scope options", LOG_ERR, 0);
2922fd5fdc59SPat Donlin 			return -1;
2923fd5fdc59SPat Donlin 		}
2924fd5fdc59SPat Donlin 		switch (option) {
2925fd5fdc59SPat Donlin 		case 0x01:   /* get domain scope */
2926fd5fdc59SPat Donlin 			if ((domain = str2val2(argv[1], nm_domain_vals)) == 0xFF) {
2927fd5fdc59SPat Donlin 				print_strs(nm_domain_vals, "Domain Scope:", LOG_ERR, 0);
2928fd5fdc59SPat Donlin 				return -1;
2929fd5fdc59SPat Donlin 			}
2930fd5fdc59SPat Donlin 			break;
2931fd5fdc59SPat Donlin 		case 0x02:   /* policy ID */
2932fd5fdc59SPat Donlin 			if (str2uchar(argv[1], &policy_id) < 0) {
2933fd5fdc59SPat Donlin 				lprintf(LOG_ERR,"Policy ID must be a positive integer.\n");
2934fd5fdc59SPat Donlin 				return -1;
2935fd5fdc59SPat Donlin 			}
2936fd5fdc59SPat Donlin 			break;
2937fd5fdc59SPat Donlin 		default:
2938fd5fdc59SPat Donlin 			break;
2939fd5fdc59SPat Donlin 		}
2940fd5fdc59SPat Donlin 		argc--;
2941fd5fdc59SPat Donlin 		argv++;
2942fd5fdc59SPat Donlin 	}
2943fd5fdc59SPat Donlin 	if (mode && (policy_id == 0xFF)) {
2944fd5fdc59SPat Donlin 		print_strs(nm_stats_opts, "Missing policy_id parameter:", LOG_ERR, 0);
2945fd5fdc59SPat Donlin 		return -1;
2946fd5fdc59SPat Donlin 	}
2947fd5fdc59SPat Donlin 	if (_ipmi_nm_reset_stats(intf, mode, domain, policy_id) < 0)
2948fd5fdc59SPat Donlin 		return -1;
2949fd5fdc59SPat Donlin 	return 0;
2950fd5fdc59SPat Donlin }
2951fd5fdc59SPat Donlin 
2952fd5fdc59SPat Donlin static int
ipmi_nm_set_range(struct ipmi_intf * intf,int argc,char ** argv)2953fd5fdc59SPat Donlin ipmi_nm_set_range(struct ipmi_intf * intf, int argc, char **argv)
2954fd5fdc59SPat Donlin {
2955fd5fdc59SPat Donlin 	uint8_t domain = 0;
2956fd5fdc59SPat Donlin 	uint8_t param;
2957fd5fdc59SPat Donlin 	uint16_t minimum = -1;
2958fd5fdc59SPat Donlin 	uint16_t maximum = -1;
2959fd5fdc59SPat Donlin 
2960fd5fdc59SPat Donlin 	while (--argc) {
2961fd5fdc59SPat Donlin 		argv++;
2962fd5fdc59SPat Donlin 		if (argv[0] == NULL) break;
2963fd5fdc59SPat Donlin 		if ((param = str2val2(argv[0], nm_power_range)) == 0xFF) {
2964fd5fdc59SPat Donlin 			print_strs(nm_power_range, "power range parameters:", LOG_ERR, 0);
2965fd5fdc59SPat Donlin 			return -1;
2966fd5fdc59SPat Donlin 		}
2967fd5fdc59SPat Donlin 		switch (param) {
2968fd5fdc59SPat Donlin 		case 0x01:   /* get domain scope */
2969fd5fdc59SPat Donlin 			if ((domain = str2val2(argv[1], nm_domain_vals)) == 0xFF) {
2970fd5fdc59SPat Donlin 				print_strs(nm_domain_vals, "Domain Scope:", LOG_ERR, 0);
2971fd5fdc59SPat Donlin 				return -1;
2972fd5fdc59SPat Donlin 			}
2973fd5fdc59SPat Donlin 			break;
2974fd5fdc59SPat Donlin 		case 0x02: /* min */
2975fd5fdc59SPat Donlin 			if (str2ushort(argv[1], &minimum) < 0) {
2976fd5fdc59SPat Donlin 				lprintf(LOG_ERR,"Power minimum must be a positive integer.\n");
2977fd5fdc59SPat Donlin 				return -1;
2978fd5fdc59SPat Donlin 			}
2979ce861658SPat Donlin 			break;
2980fd5fdc59SPat Donlin 		case 0x03: /* max */
2981fd5fdc59SPat Donlin 			if (str2ushort(argv[1], &maximum) < 0) {
2982fd5fdc59SPat Donlin 				lprintf(LOG_ERR,"Power maximum must be a positive integer.\n");
2983fd5fdc59SPat Donlin 				return -1;
2984fd5fdc59SPat Donlin 			}
2985fd5fdc59SPat Donlin 			break;
2986fd5fdc59SPat Donlin 		default:
2987fd5fdc59SPat Donlin 			break;
2988fd5fdc59SPat Donlin 		}
2989fd5fdc59SPat Donlin 		argc--;
2990fd5fdc59SPat Donlin 		argv++;
2991fd5fdc59SPat Donlin 	}
2992fd5fdc59SPat Donlin 	if ((minimum == 0xFFFF) || (maximum == 0xFFFF)) {
2993fd5fdc59SPat Donlin 		lprintf(LOG_ERR,"Missing parameters: nm power range min <minimum> max <maximum>.\n");
2994fd5fdc59SPat Donlin 		return -1;
2995fd5fdc59SPat Donlin 	}
2996fd5fdc59SPat Donlin 	if (_nm_set_range(intf, domain, minimum, maximum) < 0)
2997fd5fdc59SPat Donlin 		return -1;
2998fd5fdc59SPat Donlin 	return 0;
2999fd5fdc59SPat Donlin }
3000fd5fdc59SPat Donlin 
3001fd5fdc59SPat Donlin static int
ipmi_nm_get_alert(struct ipmi_intf * intf)3002fd5fdc59SPat Donlin ipmi_nm_get_alert(struct ipmi_intf * intf)
3003fd5fdc59SPat Donlin {
3004fd5fdc59SPat Donlin 	struct nm_set_alert alert;
3005fd5fdc59SPat Donlin 
3006fd5fdc59SPat Donlin 	memset(&alert, 0, sizeof(alert));
3007fd5fdc59SPat Donlin 	if (_ipmi_nm_get_alert(intf, &alert))
3008fd5fdc59SPat Donlin 		return -1;
3009fd5fdc59SPat Donlin 	if (csv_output) {
3010fd5fdc59SPat Donlin 		printf("%d,%s,0x%x,%s,0x%x\n",
3011fd5fdc59SPat Donlin 				alert.chan&0xF,
3012fd5fdc59SPat Donlin 				(alert.chan >> 7) ? "not registered" : "registered",
3013fd5fdc59SPat Donlin 				alert.dest,
3014fd5fdc59SPat Donlin 				(alert.string >> 7) ? "yes" : "no",
3015fd5fdc59SPat Donlin 				alert.string & 0x7F);
3016fd5fdc59SPat Donlin 		return 0;
3017fd5fdc59SPat Donlin 	}
3018fd5fdc59SPat Donlin 	printf("    Alert Chan:                                  %d\n",
3019fd5fdc59SPat Donlin 		alert.chan&0xF);
3020fd5fdc59SPat Donlin 	printf("    Alert Receiver:                              %s\n",
3021fd5fdc59SPat Donlin 		(alert.chan >> 7) ? "not registered" : "registered");
3022fd5fdc59SPat Donlin 	printf("    Alert Lan Destination:                       0x%x\n",
3023fd5fdc59SPat Donlin 		alert.dest);
3024fd5fdc59SPat Donlin 	printf("    Use Alert String:                            %s\n",
3025fd5fdc59SPat Donlin 		(alert.string >> 7) ? "yes" : "no");
3026fd5fdc59SPat Donlin 	printf("    Alert String Selector:                       0x%x\n",
3027fd5fdc59SPat Donlin 		alert.string & 0x7F);
3028fd5fdc59SPat Donlin 	return 0;
3029fd5fdc59SPat Donlin }
3030fd5fdc59SPat Donlin 
3031fd5fdc59SPat Donlin static int
ipmi_nm_alert(struct ipmi_intf * intf,int argc,char ** argv)3032fd5fdc59SPat Donlin ipmi_nm_alert(struct ipmi_intf * intf, int argc, char **argv)
3033fd5fdc59SPat Donlin {
3034fd5fdc59SPat Donlin 	uint8_t param;
3035fd5fdc59SPat Donlin 	uint8_t action;
3036fd5fdc59SPat Donlin 	uint8_t chan = -1;
3037fd5fdc59SPat Donlin 	uint8_t dest = -1;
3038fd5fdc59SPat Donlin 	uint8_t string = -1;
3039fd5fdc59SPat Donlin 	struct nm_set_alert alert;
3040fd5fdc59SPat Donlin 
3041fd5fdc59SPat Donlin 	argv++;
3042fd5fdc59SPat Donlin 	argc--;
3043fd5fdc59SPat Donlin 	if ((argv[0] == NULL) ||
3044fd5fdc59SPat Donlin 			((action = str2val2(argv[0], nm_alert_opts)) == 0xFF)) {
3045fd5fdc59SPat Donlin 		print_strs(nm_alert_opts, "Alert commands", LOG_ERR, 0);
3046fd5fdc59SPat Donlin 		return -1;
3047fd5fdc59SPat Donlin 	}
3048fd5fdc59SPat Donlin 	if (action == 0x02) /* get */
3049fd5fdc59SPat Donlin 		return (ipmi_nm_get_alert(intf));
3050fd5fdc59SPat Donlin 	/* set */
3051fd5fdc59SPat Donlin 	memset(&alert, 0, sizeof(alert));
3052fd5fdc59SPat Donlin 	while (--argc) {
3053fd5fdc59SPat Donlin 		argv++;
3054fd5fdc59SPat Donlin 		if (argv[0] == NULL) break;
3055fd5fdc59SPat Donlin 		if ((param = str2val2(argv[0], nm_set_alert_param)) == 0xFF) {
3056fd5fdc59SPat Donlin 			print_strs(nm_set_alert_param, "Set alert Parameters:", LOG_ERR, 0);
3057fd5fdc59SPat Donlin 			return -1;
3058fd5fdc59SPat Donlin 		}
3059fd5fdc59SPat Donlin 		switch (param) {
3060fd5fdc59SPat Donlin 		case 0x01: /* channnel */
3061fd5fdc59SPat Donlin 			if (str2uchar(argv[1], &chan) < 0) {
3062fd5fdc59SPat Donlin 				lprintf(LOG_ERR,"Alert Lan chan must be a positive integer.\n");
3063fd5fdc59SPat Donlin 				return -1;
3064fd5fdc59SPat Donlin 			}
3065fd5fdc59SPat Donlin 			if (action == 0x03)  /* Clear */
3066fd5fdc59SPat Donlin 				chan |= 0x80;   /* deactivate alert reciever */
3067fd5fdc59SPat Donlin 			break;
3068fd5fdc59SPat Donlin 		case 0x02:  /* dest */
3069fd5fdc59SPat Donlin 			if (str2uchar(argv[1], &dest) < 0) {
3070fd5fdc59SPat Donlin 				lprintf(LOG_ERR,"Alert Destination must be a positive integer.\n");
3071fd5fdc59SPat Donlin 				return -1;
3072fd5fdc59SPat Donlin 			}
3073fd5fdc59SPat Donlin 			break;
3074fd5fdc59SPat Donlin 		case 0x03:  /* string number */
3075fd5fdc59SPat Donlin 			if (str2uchar(argv[1], &string) < 0) {
3076fd5fdc59SPat Donlin 				lprintf(LOG_ERR,"Alert String # must be a positive integer.\n");
3077fd5fdc59SPat Donlin 				return -1;
3078fd5fdc59SPat Donlin 			}
3079fd5fdc59SPat Donlin 			string |= 0x80;   /* set string select flag */
3080fd5fdc59SPat Donlin 			break;
3081fd5fdc59SPat Donlin 		}
3082fd5fdc59SPat Donlin 		argc--;
3083fd5fdc59SPat Donlin 		argv++;
3084fd5fdc59SPat Donlin 	}
3085fd5fdc59SPat Donlin 	if ((chan == 0xFF) || (dest == 0xFF)) {
3086fd5fdc59SPat Donlin 		print_strs(nm_set_alert_param, "Must set alert chan and dest params.", LOG_ERR, 0);
3087fd5fdc59SPat Donlin 		return -1;
3088fd5fdc59SPat Donlin 	}
3089fd5fdc59SPat Donlin 	if (string == 0xFF) string = 0;
3090fd5fdc59SPat Donlin 	alert.chan = chan;
3091fd5fdc59SPat Donlin 	alert.dest = dest;
3092fd5fdc59SPat Donlin 	alert.string = string;
3093fd5fdc59SPat Donlin 	if (_ipmi_nm_set_alert(intf, &alert))
3094fd5fdc59SPat Donlin 		return -1;
3095fd5fdc59SPat Donlin 	return 0;
3096fd5fdc59SPat Donlin }
3097fd5fdc59SPat Donlin 
3098fd5fdc59SPat Donlin static int
ipmi_nm_get_thresh(struct ipmi_intf * intf,uint8_t domain,uint8_t policy_id)3099fd5fdc59SPat Donlin ipmi_nm_get_thresh(struct ipmi_intf *intf, uint8_t domain, uint8_t policy_id)
3100fd5fdc59SPat Donlin {
3101fd5fdc59SPat Donlin 	uint16_t list[3];
3102fd5fdc59SPat Donlin 
3103fd5fdc59SPat Donlin 	memset(list, 0, sizeof(list));
3104fd5fdc59SPat Donlin 	if (_ipmi_nm_get_thresh(intf, domain, policy_id, &list[0]))
3105fd5fdc59SPat Donlin 		return -1;
3106fd5fdc59SPat Donlin 
3107fd5fdc59SPat Donlin 	printf("    Alert Threshold domain:                   %s\n",
3108fd5fdc59SPat Donlin 			val2str2(domain, nm_domain_vals));
3109fd5fdc59SPat Donlin 	printf("    Alert Threshold Policy ID:                %d\n",
3110fd5fdc59SPat Donlin 			policy_id);
3111fd5fdc59SPat Donlin 	printf("    Alert Threshold 1:                        %d\n",
3112fd5fdc59SPat Donlin 			list[0]);
3113fd5fdc59SPat Donlin 	printf("    Alert Threshold 2:                        %d\n",
3114fd5fdc59SPat Donlin 			list[1]);
3115fd5fdc59SPat Donlin 	printf("    Alert Threshold 3:                        %d\n",
3116fd5fdc59SPat Donlin 			list[2]);
3117fd5fdc59SPat Donlin 	return 0;
3118fd5fdc59SPat Donlin }
3119fd5fdc59SPat Donlin 
3120fd5fdc59SPat Donlin static int
ipmi_nm_thresh(struct ipmi_intf * intf,int argc,char ** argv)3121fd5fdc59SPat Donlin ipmi_nm_thresh(struct ipmi_intf * intf, int argc, char **argv)
3122fd5fdc59SPat Donlin {
3123fd5fdc59SPat Donlin 	uint8_t option;
3124fd5fdc59SPat Donlin 	uint8_t action;
3125fd5fdc59SPat Donlin 	uint8_t domain = 0;   /* default domain of platform */
3126fd5fdc59SPat Donlin 	uint8_t policy_id = -1;
3127fd5fdc59SPat Donlin 	struct nm_thresh thresh;
3128fd5fdc59SPat Donlin 	int i = 0;
3129fd5fdc59SPat Donlin 
31307a854623SPat Donlin 	argv++;
31317a854623SPat Donlin 	argc--;
3132fd5fdc59SPat Donlin 	/* set or get */
3133fd5fdc59SPat Donlin 	if ((argv[0] == NULL) || (argc < 3) ||
3134fd5fdc59SPat Donlin 			((action = str2val2(argv[0], nm_thresh_cmds)) == 0xFF)) {
3135fd5fdc59SPat Donlin 		print_strs(nm_thresh_cmds, "Theshold commands", LOG_ERR, 0);
3136fd5fdc59SPat Donlin 		return -1;
3137fd5fdc59SPat Donlin 	}
3138fd5fdc59SPat Donlin 	memset(&thresh, 0, sizeof(thresh));
3139fd5fdc59SPat Donlin 	while (--argc) {
3140fd5fdc59SPat Donlin 		argv++;
3141fd5fdc59SPat Donlin 		if (argv[0] == NULL) break;
3142fd5fdc59SPat Donlin 		option = str2val2(argv[0], nm_thresh_param);
3143fd5fdc59SPat Donlin 		switch (option) {
3144fd5fdc59SPat Donlin 		case 0x01:   /* get domain scope */
3145fd5fdc59SPat Donlin 			if ((domain = str2val2(argv[1], nm_domain_vals)) == 0xFF) {
3146fd5fdc59SPat Donlin 				print_strs(nm_domain_vals, "Domain Scope:", LOG_ERR, 0);
3147fd5fdc59SPat Donlin 				return -1;
3148fd5fdc59SPat Donlin 			}
3149fd5fdc59SPat Donlin 			argc--;
3150fd5fdc59SPat Donlin 			argv++;
3151fd5fdc59SPat Donlin 			break;
3152fd5fdc59SPat Donlin 		case 0x02:   /* policy ID */
3153fd5fdc59SPat Donlin 			if (str2uchar(argv[1], &policy_id) < 0) {
3154fd5fdc59SPat Donlin 				lprintf(LOG_ERR,"Policy ID must be a positive integer.\n");
3155fd5fdc59SPat Donlin 				return -1;
3156fd5fdc59SPat Donlin 			}
3157fd5fdc59SPat Donlin 			argc--;
3158fd5fdc59SPat Donlin 			argv++;
3159fd5fdc59SPat Donlin 			break;
3160fd5fdc59SPat Donlin 		case 0xFF:
3161fd5fdc59SPat Donlin 			if (i > 2) {
3162fd5fdc59SPat Donlin 				lprintf(LOG_ERR,"Set Threshold requires 1, 2, or 3 threshold integer values.\n");
3163fd5fdc59SPat Donlin 				return -1;
3164fd5fdc59SPat Donlin 			}
3165fd5fdc59SPat Donlin 			if (str2ushort(argv[0], &thresh.thresholds[i++]) < 0) {
3166fd5fdc59SPat Donlin 				lprintf(LOG_ERR,"threshold value %d count must be a positve integer.\n", i);
3167fd5fdc59SPat Donlin 				return -1;
3168fd5fdc59SPat Donlin 			}
3169fd5fdc59SPat Donlin 		default:
3170fd5fdc59SPat Donlin 			break;
3171fd5fdc59SPat Donlin 		}
3172fd5fdc59SPat Donlin 	}
3173fd5fdc59SPat Donlin 	if (policy_id == 0xFF) {
3174fd5fdc59SPat Donlin 		print_strs(nm_stats_opts, "Missing policy_id parameter:", LOG_ERR, 0);
3175fd5fdc59SPat Donlin 		return -1;
3176fd5fdc59SPat Donlin 	}
3177fd5fdc59SPat Donlin 	if (action == 0x02) /* get */
3178fd5fdc59SPat Donlin 		return (ipmi_nm_get_thresh(intf, domain, policy_id));
3179fd5fdc59SPat Donlin 	thresh.domain = domain;
3180fd5fdc59SPat Donlin 	thresh.policy_id = policy_id;
3181fd5fdc59SPat Donlin 	thresh.count = i;
3182fd5fdc59SPat Donlin 	if (_ipmi_nm_set_thresh(intf, &thresh) < 0)
3183fd5fdc59SPat Donlin 		return -1;
3184fd5fdc59SPat Donlin 	return 0;
3185fd5fdc59SPat Donlin }
3186fd5fdc59SPat Donlin 
3187fd5fdc59SPat Donlin static inline int
click2hour(int click)3188fd5fdc59SPat Donlin click2hour(int click)
3189fd5fdc59SPat Donlin {
3190fd5fdc59SPat Donlin 	if ((click*6) < 60) return 0;
3191fd5fdc59SPat Donlin 	return ((click*6)/60);
3192fd5fdc59SPat Donlin }
3193fd5fdc59SPat Donlin 
3194fd5fdc59SPat Donlin static inline int
click2min(int click)3195fd5fdc59SPat Donlin click2min(int click)
3196fd5fdc59SPat Donlin {
3197fd5fdc59SPat Donlin 	if (!click) return 0;
3198fd5fdc59SPat Donlin 	if ((click*6) < 60) return click*6;
3199fd5fdc59SPat Donlin 	return (click*6)%60;
3200fd5fdc59SPat Donlin }
3201fd5fdc59SPat Donlin 
3202fd5fdc59SPat Donlin static int
ipmi_nm_get_suspend(struct ipmi_intf * intf,uint8_t domain,uint8_t policy_id)3203fd5fdc59SPat Donlin ipmi_nm_get_suspend(struct ipmi_intf *intf, uint8_t domain, uint8_t policy_id)
3204fd5fdc59SPat Donlin {
3205fd5fdc59SPat Donlin 	struct nm_period periods[5];
3206fd5fdc59SPat Donlin 	int i;
3207fd5fdc59SPat Donlin 	int j;
3208fd5fdc59SPat Donlin 	int count = 0;
3209fd5fdc59SPat Donlin 	const char *days[7] = {"M", "Tu", "W", "Th", "F", "Sa", "Su"};
3210fd5fdc59SPat Donlin 
3211fd5fdc59SPat Donlin 	memset(periods, 0, sizeof(periods));
3212fd5fdc59SPat Donlin 	if (_ipmi_nm_get_suspend(intf, domain, policy_id, &count, &periods[0]))
3213fd5fdc59SPat Donlin 		return -1;
3214fd5fdc59SPat Donlin 
3215fd5fdc59SPat Donlin 	printf("    Suspend Policy domain:                    %s\n",
3216fd5fdc59SPat Donlin 			val2str2(domain, nm_domain_vals));
3217fd5fdc59SPat Donlin 	printf("    Suspend Policy Policy ID:                 %d\n",
3218fd5fdc59SPat Donlin 			policy_id);
3219fd5fdc59SPat Donlin 	if (!count) {
3220fd5fdc59SPat Donlin 		printf("    No suspend Periods.\n");
3221fd5fdc59SPat Donlin 		return 0;
3222fd5fdc59SPat Donlin 	}
3223fd5fdc59SPat Donlin 	for (i = 0; i < count; i++) {
3224fd5fdc59SPat Donlin 		printf("    Suspend Period %d:                         %02d:%02d to %02d:%02d",
3225fd5fdc59SPat Donlin 			i, click2hour(periods[i].start), click2min(periods[i].start),
3226fd5fdc59SPat Donlin 			click2hour(periods[i].stop), click2min(periods[i].stop));
3227fd5fdc59SPat Donlin 		if (periods[i].repeat) printf(", ");
3228fd5fdc59SPat Donlin 		for (j = 0; j < 7; j++)
3229fd5fdc59SPat Donlin 			printf("%s",  (periods[i].repeat >> j)&1 ? days[j] : "");
3230fd5fdc59SPat Donlin 		printf("\n");
3231fd5fdc59SPat Donlin 	}
3232fd5fdc59SPat Donlin 	return 0;
3233fd5fdc59SPat Donlin }
3234fd5fdc59SPat Donlin 
3235fd5fdc59SPat Donlin static int
ipmi_nm_suspend(struct ipmi_intf * intf,int argc,char ** argv)3236fd5fdc59SPat Donlin ipmi_nm_suspend(struct ipmi_intf * intf, int argc, char **argv)
3237fd5fdc59SPat Donlin {
3238fd5fdc59SPat Donlin 	uint8_t option;
3239fd5fdc59SPat Donlin 	uint8_t action;
3240fd5fdc59SPat Donlin 	uint8_t domain = 0;   /* default domain of platform */
3241fd5fdc59SPat Donlin 	uint8_t policy_id = -1;
3242fd5fdc59SPat Donlin 	uint8_t count = 0;
3243fd5fdc59SPat Donlin 	struct nm_suspend suspend;
3244fd5fdc59SPat Donlin 	int i;
3245fd5fdc59SPat Donlin 
32467a854623SPat Donlin 	argv++;
32477a854623SPat Donlin 	argc--;
3248fd5fdc59SPat Donlin 	/* set or get */
32497a854623SPat Donlin 	if ((argv[0] == NULL) || (argc < 3) ||
32507a854623SPat Donlin 			((action = str2val2(argv[0], nm_suspend_cmds)) == 0xFF)) {
3251fd5fdc59SPat Donlin 		print_strs(nm_suspend_cmds, "Suspend commands", LOG_ERR, 0);
3252fd5fdc59SPat Donlin 		return -1;
3253fd5fdc59SPat Donlin 	}
3254fd5fdc59SPat Donlin 	memset(&suspend, 0, sizeof(suspend));
3255fd5fdc59SPat Donlin 	while (--argc > 0) {
3256fd5fdc59SPat Donlin 		argv++;
3257fd5fdc59SPat Donlin 		if (argv[0] == NULL) break;
3258fd5fdc59SPat Donlin 		option = str2val2(argv[0], nm_thresh_param);
3259fd5fdc59SPat Donlin 		switch (option) {
3260fd5fdc59SPat Donlin 		case 0x01:   /* get domain scope */
3261fd5fdc59SPat Donlin 			if ((domain = str2val2(argv[1], nm_domain_vals)) == 0xFF) {
3262fd5fdc59SPat Donlin 				print_strs(nm_domain_vals, "Domain Scope:", LOG_ERR, 0);
3263fd5fdc59SPat Donlin 				return -1;
3264fd5fdc59SPat Donlin 			}
3265fd5fdc59SPat Donlin 			argc--;
3266fd5fdc59SPat Donlin 			argv++;
3267fd5fdc59SPat Donlin 			break;
3268fd5fdc59SPat Donlin 		case 0x02:   /* policy ID */
3269fd5fdc59SPat Donlin 			if (str2uchar(argv[1], &policy_id) < 0) {
3270fd5fdc59SPat Donlin 				lprintf(LOG_ERR,"Policy ID must be a positive integer.\n");
3271fd5fdc59SPat Donlin 				return -1;
3272fd5fdc59SPat Donlin 			}
3273fd5fdc59SPat Donlin 			argc--;
3274fd5fdc59SPat Donlin 			argv++;
3275fd5fdc59SPat Donlin 			break;
3276fd5fdc59SPat Donlin                 case 0xFF:   /* process periods */
32777a854623SPat Donlin 			for (i = 0; count < IPMI_NM_SUSPEND_PERIOD_MAX; i += 3, count++) {
32787a854623SPat Donlin 				if (argc < 3) {
32797a854623SPat Donlin 					lprintf(LOG_ERR,"Error: suspend period requires a start, stop, and repeat values.\n");
3280fd5fdc59SPat Donlin 					return -1;
3281fd5fdc59SPat Donlin 				}
3282fd5fdc59SPat Donlin 				if (str2uchar(argv[i+0], &suspend.period[count].start) < 0) {
3283fd5fdc59SPat Donlin 					lprintf(LOG_ERR,"suspend start value %d must be 0-239.\n", count);
3284fd5fdc59SPat Donlin 					return -1;
3285fd5fdc59SPat Donlin 				}
3286fd5fdc59SPat Donlin 				if (str2uchar(argv[i+1], &suspend.period[count].stop) < 0) {
3287fd5fdc59SPat Donlin 					lprintf(LOG_ERR,"suspend stop value %d  must be 0-239.\n", count);
3288fd5fdc59SPat Donlin 					return -1;
3289fd5fdc59SPat Donlin 				}
3290fd5fdc59SPat Donlin 				if (str2uchar(argv[i+2], &suspend.period[count].repeat) < 0) {
3291fd5fdc59SPat Donlin 					lprintf(LOG_ERR,"suspend repeat value %d unable to convert.\n", count);
3292fd5fdc59SPat Donlin 					return -1;
3293fd5fdc59SPat Donlin 				}
3294fd5fdc59SPat Donlin 				argc -= 3;
32957a854623SPat Donlin 				if (argc <= 0)
32967a854623SPat Donlin 					break;
32977a854623SPat Donlin 			}
32987a854623SPat Donlin 			if (argc <= 0)
32997a854623SPat Donlin 				break;
3300fd5fdc59SPat Donlin 			break;
3301fd5fdc59SPat Donlin                 default:
3302fd5fdc59SPat Donlin                         break;
3303fd5fdc59SPat Donlin                 }
3304fd5fdc59SPat Donlin         }
3305fd5fdc59SPat Donlin 	if (action == 0x02) /* get */
3306fd5fdc59SPat Donlin 		return (ipmi_nm_get_suspend(intf, domain, policy_id));
3307fd5fdc59SPat Donlin 
3308fd5fdc59SPat Donlin 	suspend.domain = domain;
3309fd5fdc59SPat Donlin 	suspend.policy_id = policy_id;
3310fd5fdc59SPat Donlin 	if (_ipmi_nm_set_suspend(intf, &suspend) < 0)
3311fd5fdc59SPat Donlin 		return -1;
3312fd5fdc59SPat Donlin 	return 0;
3313fd5fdc59SPat Donlin }
3314fd5fdc59SPat Donlin /* end nm */
3315fd5fdc59SPat Donlin 
3316fd5fdc59SPat Donlin static int
ipmi_dcmi_set_limit(struct ipmi_intf * intf,int argc,char ** argv)3317fd5fdc59SPat Donlin ipmi_dcmi_set_limit(struct ipmi_intf * intf, int argc, char **argv)
3318fd5fdc59SPat Donlin {
3319fd5fdc59SPat Donlin 	int rc = 0;
3320fd5fdc59SPat Donlin 
3321c18ec02fSPetter Reinholdtsen 	if ( argc == 10) {
3322c18ec02fSPetter Reinholdtsen 		/* Let`s initialize dcmi power parameters */
3323c18ec02fSPetter Reinholdtsen 		struct ipmi_rq req;
3324c18ec02fSPetter Reinholdtsen 		uint8_t data[256];
3325c18ec02fSPetter Reinholdtsen 		uint16_t sample = 0;
3326c18ec02fSPetter Reinholdtsen 		uint16_t limit = 0;
3327c18ec02fSPetter Reinholdtsen 		uint32_t correction = 0;
3328fd5fdc59SPat Donlin 		struct ipmi_rs *rsp;
3329c18ec02fSPetter Reinholdtsen 
3330c18ec02fSPetter Reinholdtsen 		memset(data, 0, sizeof(data));
3331c18ec02fSPetter Reinholdtsen 		memset(&req, 0, sizeof(req));
3332c18ec02fSPetter Reinholdtsen 
3333c18ec02fSPetter Reinholdtsen 		req.msg.netfn = IPMI_NETFN_DCGRP;
3334c18ec02fSPetter Reinholdtsen 		req.msg.lun = 0x00;
3335c18ec02fSPetter Reinholdtsen 		req.msg.cmd = IPMI_DCMI_SETLMT; /* Set power limit */
3336c18ec02fSPetter Reinholdtsen 		req.msg.data = data; /* Contents above */
3337c18ec02fSPetter Reinholdtsen 		req.msg.data_len =  15;
3338c18ec02fSPetter Reinholdtsen 
3339c18ec02fSPetter Reinholdtsen 		data[0] = IPMI_DCMI; /* Group Extension Identification */
3340c18ec02fSPetter Reinholdtsen 		data[1] = 0x0;  /* reserved */
3341c18ec02fSPetter Reinholdtsen 		data[2] = 0x0;  /* reserved */
3342c18ec02fSPetter Reinholdtsen 		data[3] = 0x0;  /* reserved */
3343c18ec02fSPetter Reinholdtsen 
3344c18ec02fSPetter Reinholdtsen 		/* action */
3345c18ec02fSPetter Reinholdtsen 		switch (str2val2(argv[2], dcmi_pwrmgmt_action_vals)) {
334642aba7ebSZdenek Styblik 		case 0x00:
334742aba7ebSZdenek Styblik 			/* no_action */
334842aba7ebSZdenek Styblik 			data[4] = 0x00;
334942aba7ebSZdenek Styblik 			break;
3350c18ec02fSPetter Reinholdtsen 		case 0x01:
3351c18ec02fSPetter Reinholdtsen 			/* power_off */
3352c18ec02fSPetter Reinholdtsen 			data[4] = 0x01;
3353c18ec02fSPetter Reinholdtsen 			break;
3354c18ec02fSPetter Reinholdtsen 		case 0x11:
3355c18ec02fSPetter Reinholdtsen 			/* sel_logging*/
3356c18ec02fSPetter Reinholdtsen 			data[4] = 0x11;
3357c18ec02fSPetter Reinholdtsen 			break;
3358c18ec02fSPetter Reinholdtsen 		case 0xFF:
3359c18ec02fSPetter Reinholdtsen 			/* error - not a string we knew what to do with */
336042aba7ebSZdenek Styblik 			lprintf(LOG_ERR, "Given Action '%s' is invalid.",
336142aba7ebSZdenek Styblik 				argv[2]);
3362c18ec02fSPetter Reinholdtsen 			return -1;
3363c18ec02fSPetter Reinholdtsen 		}
3364c18ec02fSPetter Reinholdtsen 		/* limit */
3365c18ec02fSPetter Reinholdtsen 		if (str2ushort(argv[4], &limit) != 0) {
3366c18ec02fSPetter Reinholdtsen 			lprintf(LOG_ERR,
3367c18ec02fSPetter Reinholdtsen 				"Given Limit '%s' is invalid.",
3368c18ec02fSPetter Reinholdtsen 				argv[4]);
3369c18ec02fSPetter Reinholdtsen 			return (-1);
3370c18ec02fSPetter Reinholdtsen 		}
3371c18ec02fSPetter Reinholdtsen 		data[5] = limit >> 0;
3372c18ec02fSPetter Reinholdtsen 		data[6] = limit >> 8;
3373c18ec02fSPetter Reinholdtsen 		/* correction */
3374c18ec02fSPetter Reinholdtsen 		if (str2uint(argv[6], &correction) != 0) {
3375c18ec02fSPetter Reinholdtsen 			lprintf(LOG_ERR,
3376c18ec02fSPetter Reinholdtsen 				"Given Correction '%s' is invalid.",
3377c18ec02fSPetter Reinholdtsen 				argv[6]);
3378c18ec02fSPetter Reinholdtsen 			return (-1);
3379c18ec02fSPetter Reinholdtsen 		}
3380c18ec02fSPetter Reinholdtsen 		data[7] = correction >> 0;
3381c18ec02fSPetter Reinholdtsen 		data[8] = correction >> 8;
3382c18ec02fSPetter Reinholdtsen 		data[9] = correction >> 16;
3383c18ec02fSPetter Reinholdtsen 		data[10] = correction >> 24;
3384c18ec02fSPetter Reinholdtsen 		data[11] = 0x00;  /* reserved */
3385c18ec02fSPetter Reinholdtsen 		data[12] = 0x00;  /* reserved */
3386c18ec02fSPetter Reinholdtsen 		/* sample */
3387c18ec02fSPetter Reinholdtsen 		if (str2ushort(argv[8], &sample) != 0) {
3388c18ec02fSPetter Reinholdtsen 			lprintf(LOG_ERR,
3389c18ec02fSPetter Reinholdtsen 				"Given Sample '%s' is invalid.",
3390c18ec02fSPetter Reinholdtsen 				argv[8]);
3391c18ec02fSPetter Reinholdtsen 			return (-1);
3392c18ec02fSPetter Reinholdtsen 		}
3393c18ec02fSPetter Reinholdtsen 		data[13] = sample >> 0;
3394c18ec02fSPetter Reinholdtsen 		data[14] = sample >> 8;
3395c18ec02fSPetter Reinholdtsen 
3396c18ec02fSPetter Reinholdtsen 		rsp = intf->sendrecv(intf, &req);
3397c18ec02fSPetter Reinholdtsen 		if (chk_rsp(rsp)) {
3398c18ec02fSPetter Reinholdtsen 			return -1;
3399c18ec02fSPetter Reinholdtsen 		}
3400c18ec02fSPetter Reinholdtsen 	} else {
3401c18ec02fSPetter Reinholdtsen 		/* loop through each parameter and value until we have neither */
3402c18ec02fSPetter Reinholdtsen 		while ((argv[1] != NULL) && (argv[2] != NULL)) {
3403c18ec02fSPetter Reinholdtsen 			rc = ipmi_dcmi_pwr_slimit(intf, argv[1], argv[2]);
3404c18ec02fSPetter Reinholdtsen 			/* catch any error that the set limit function returned */
3405c18ec02fSPetter Reinholdtsen 			if (rc > 0) {
3406c18ec02fSPetter Reinholdtsen 				print_strs(dcmi_pwrmgmt_set_usage_vals,
3407fd5fdc59SPat Donlin 					"set_limit <parameter> <value>", LOG_ERR, 0);
3408c18ec02fSPetter Reinholdtsen 				return -1;
3409c18ec02fSPetter Reinholdtsen 			}
3410c18ec02fSPetter Reinholdtsen 			/* the first argument is the command and the second is the
3411c18ec02fSPetter Reinholdtsen 			* value.  Move argv two places; what is now 3 will be 1
3412c18ec02fSPetter Reinholdtsen 			*/
3413c18ec02fSPetter Reinholdtsen 			argv+=2;
3414c18ec02fSPetter Reinholdtsen 		}
3415c18ec02fSPetter Reinholdtsen 	}
3416fd5fdc59SPat Donlin 	return rc;
3417fd5fdc59SPat Donlin }
3418fd5fdc59SPat Donlin 
3419fd5fdc59SPat Donlin static int
ipmi_dcmi_parse_power(struct ipmi_intf * intf,int argc,char ** argv)3420fd5fdc59SPat Donlin ipmi_dcmi_parse_power(struct ipmi_intf * intf, int argc, char **argv)
3421fd5fdc59SPat Donlin {
3422fd5fdc59SPat Donlin 	int rc = 0;
3423fd5fdc59SPat Donlin 	uint8_t sample_time = 0;
3424fd5fdc59SPat Donlin 	/* power management */
3425fd5fdc59SPat Donlin 	switch (str2val2(argv[0], dcmi_pwrmgmt_vals)) {
3426fd5fdc59SPat Donlin 	case 0x00:
3427fd5fdc59SPat Donlin 	/* get reading */
3428fd5fdc59SPat Donlin 		if (argv[1] != NULL) {
3429fd5fdc59SPat Donlin 			if (!(sample_time = str2val2(argv[1], dcmi_sampling_vals))) {
3430fd5fdc59SPat Donlin 				print_strs(dcmi_sampling_vals,
3431fd5fdc59SPat Donlin 					"Invalid sample time. Valid times are: ",
3432fd5fdc59SPat Donlin 					LOG_ERR, 1);
3433fd5fdc59SPat Donlin 				printf("\n");
3434fd5fdc59SPat Donlin 				return -1;
3435fd5fdc59SPat Donlin 			}
3436fd5fdc59SPat Donlin 		}
3437fd5fdc59SPat Donlin 		rc = ipmi_dcmi_pwr_rd(intf, sample_time);
3438fd5fdc59SPat Donlin 		break;
3439fd5fdc59SPat Donlin 	case 0x01:
3440fd5fdc59SPat Donlin 		/* get limit */
3441fd5fdc59SPat Donlin 		/* because the get limit function is also used to
3442fd5fdc59SPat Donlin 		 * populate unchanged values for the set limit
3443fd5fdc59SPat Donlin 		 * command it returns an ipmi response structure
3444fd5fdc59SPat Donlin 		 */
3445fd5fdc59SPat Donlin 		rc = ipmi_dcmi_pwr_prnt_glimit(intf);
3446fd5fdc59SPat Donlin 		break;
3447fd5fdc59SPat Donlin 	case 0x02:
3448fd5fdc59SPat Donlin 		/* set limit */
3449fd5fdc59SPat Donlin 		if (argc < 4) {
3450fd5fdc59SPat Donlin 			print_strs(dcmi_pwrmgmt_set_usage_vals,
3451fd5fdc59SPat Donlin 				"set_limit <parameter> <value>",
3452fd5fdc59SPat Donlin 				LOG_ERR, 0);
3453fd5fdc59SPat Donlin 			return -1;
3454fd5fdc59SPat Donlin 		}
3455fd5fdc59SPat Donlin 		if (ipmi_dcmi_set_limit(intf, argc, argv) < 0)
3456fd5fdc59SPat Donlin 			return -1;
3457c18ec02fSPetter Reinholdtsen 		rc = ipmi_dcmi_pwr_prnt_glimit(intf);
3458c18ec02fSPetter Reinholdtsen 		break;
3459c18ec02fSPetter Reinholdtsen 	case 0x03:
3460c18ec02fSPetter Reinholdtsen 		/* activate */
3461c18ec02fSPetter Reinholdtsen 		rc = ipmi_dcmi_pwr_actdeact(intf, 1);
3462c18ec02fSPetter Reinholdtsen 		break;
3463c18ec02fSPetter Reinholdtsen 	case 0x04:
3464c18ec02fSPetter Reinholdtsen 		/* deactivate */
3465c18ec02fSPetter Reinholdtsen 		rc = ipmi_dcmi_pwr_actdeact(intf, 0);
3466c18ec02fSPetter Reinholdtsen 		break;
3467c18ec02fSPetter Reinholdtsen 	default:
3468c18ec02fSPetter Reinholdtsen 		/* no valid options */
3469c18ec02fSPetter Reinholdtsen 		print_strs(dcmi_pwrmgmt_vals,
3470fd5fdc59SPat Donlin 			"power <command>", LOG_ERR, 0);
3471c18ec02fSPetter Reinholdtsen 		break;
3472c18ec02fSPetter Reinholdtsen 	}
3473fd5fdc59SPat Donlin 	return rc;
3474c18ec02fSPetter Reinholdtsen }
3475fd5fdc59SPat Donlin /* end dcmi power command */
3476fd5fdc59SPat Donlin 
3477fd5fdc59SPat Donlin static int
ipmi_dcmi_thermalpolicy(struct ipmi_intf * intf,int argc,char ** argv)3478fd5fdc59SPat Donlin ipmi_dcmi_thermalpolicy(struct ipmi_intf * intf, int argc, char **argv)
3479c18ec02fSPetter Reinholdtsen {
3480fd5fdc59SPat Donlin 	int rc = 0;
3481c18ec02fSPetter Reinholdtsen 	uint8_t entityID = 0;
3482c18ec02fSPetter Reinholdtsen 	uint8_t entityInst = 0;
3483c18ec02fSPetter Reinholdtsen 	uint8_t persistanceFlag;
3484c18ec02fSPetter Reinholdtsen 	uint8_t actionHardPowerOff;
3485c18ec02fSPetter Reinholdtsen 	uint8_t actionLogToSEL;
3486c18ec02fSPetter Reinholdtsen 	uint8_t tempLimit = 0;
3487c18ec02fSPetter Reinholdtsen 	uint8_t samplingTimeLSB;
3488c18ec02fSPetter Reinholdtsen 	uint8_t samplingTimeMSB;
3489c18ec02fSPetter Reinholdtsen 	uint16_t samplingTime = 0;
3490c18ec02fSPetter Reinholdtsen 	/* Thermal policy get/set */
3491c18ec02fSPetter Reinholdtsen 	/* dcmitool dcmi thermalpolicy get */
3492c18ec02fSPetter Reinholdtsen 	switch (str2val2(argv[1], dcmi_thermalpolicy_vals)) {
3493c18ec02fSPetter Reinholdtsen 	case 0x00:
3494c18ec02fSPetter Reinholdtsen 		if (argc < 4) {
3495c18ec02fSPetter Reinholdtsen 			lprintf(LOG_NOTICE, "Get <entityID> <instanceID>");
3496c18ec02fSPetter Reinholdtsen 			return -1;
3497c18ec02fSPetter Reinholdtsen 		}
3498c18ec02fSPetter Reinholdtsen 		if (str2uchar(argv[2], &entityID) != 0) {
3499c18ec02fSPetter Reinholdtsen 			lprintf(LOG_ERR,
3500c18ec02fSPetter Reinholdtsen 					"Given Entity ID '%s' is invalid.",
3501c18ec02fSPetter Reinholdtsen 					argv[2]);
3502c18ec02fSPetter Reinholdtsen 			return (-1);
3503c18ec02fSPetter Reinholdtsen 		}
3504c18ec02fSPetter Reinholdtsen 		if (str2uchar(argv[3], &entityInst) != 0) {
3505c18ec02fSPetter Reinholdtsen 			lprintf(LOG_ERR,
3506c18ec02fSPetter Reinholdtsen 					"Given Instance ID '%s' is invalid.",
3507c18ec02fSPetter Reinholdtsen 					argv[3]);
3508c18ec02fSPetter Reinholdtsen 			return (-1);
3509c18ec02fSPetter Reinholdtsen 		}
3510c18ec02fSPetter Reinholdtsen 		rc = ipmi_dcmi_getthermalpolicy(intf,  entityID, entityInst);
3511c18ec02fSPetter Reinholdtsen 		break;
3512c18ec02fSPetter Reinholdtsen 	case 0x01:
3513c18ec02fSPetter Reinholdtsen 		if (argc < 4) {
3514c18ec02fSPetter Reinholdtsen 			lprintf(LOG_NOTICE, "Set <entityID> <instanceID>");
3515c18ec02fSPetter Reinholdtsen 			return -1;
3516c18ec02fSPetter Reinholdtsen 		} else if (argc < 9) {
3517c18ec02fSPetter Reinholdtsen 		print_strs(dcmi_thermalpolicy_set_parameters_vals,
3518c18ec02fSPetter Reinholdtsen 				"Set thermalpolicy instance parameters: "
3519c18ec02fSPetter Reinholdtsen 					"<volatile/nonvolatile/disabled> "
3520c18ec02fSPetter Reinholdtsen 					"<poweroff/nopoweroff/disabled> "
3521c18ec02fSPetter Reinholdtsen 					"<sel/nosel/disabled> <templimitByte> <exceptionTime>",
3522fd5fdc59SPat Donlin 					LOG_ERR, 0);
3523c18ec02fSPetter Reinholdtsen 			return -1;
3524c18ec02fSPetter Reinholdtsen 		}
3525c18ec02fSPetter Reinholdtsen 		if (str2uchar(argv[2], &entityID) != 0) {
3526c18ec02fSPetter Reinholdtsen 			lprintf(LOG_ERR,
3527c18ec02fSPetter Reinholdtsen 					"Given Entity ID '%s' is invalid.",
3528c18ec02fSPetter Reinholdtsen 					argv[2]);
3529c18ec02fSPetter Reinholdtsen 			return (-1);
3530c18ec02fSPetter Reinholdtsen 		}
3531c18ec02fSPetter Reinholdtsen 		if (str2uchar(argv[3], &entityInst) != 0) {
3532c18ec02fSPetter Reinholdtsen 			lprintf(LOG_ERR,
3533c18ec02fSPetter Reinholdtsen 					"Given Instance ID '%s' is invalid.",
3534c18ec02fSPetter Reinholdtsen 					argv[3]);
3535c18ec02fSPetter Reinholdtsen 			return (-1);
3536c18ec02fSPetter Reinholdtsen 		}
3537c18ec02fSPetter Reinholdtsen 		persistanceFlag = (uint8_t) str2val2(argv[4], dcmi_thermalpolicy_set_parameters_vals);
3538c18ec02fSPetter Reinholdtsen 		actionHardPowerOff = (uint8_t) str2val2(argv[5], dcmi_thermalpolicy_set_parameters_vals);
3539c18ec02fSPetter Reinholdtsen 		actionLogToSEL = (uint8_t) str2val2(argv[6], dcmi_thermalpolicy_set_parameters_vals);
3540c18ec02fSPetter Reinholdtsen 		if (str2uchar(argv[7], &tempLimit) != 0) {
3541c18ec02fSPetter Reinholdtsen 			lprintf(LOG_ERR,
3542c18ec02fSPetter Reinholdtsen 					"Given Temp Limit '%s' is invalid.",
3543c18ec02fSPetter Reinholdtsen 					argv[7]);
3544c18ec02fSPetter Reinholdtsen 			return (-1);
3545c18ec02fSPetter Reinholdtsen 		}
3546c18ec02fSPetter Reinholdtsen 		if (str2ushort(argv[8], &samplingTime) != 0) {
3547c18ec02fSPetter Reinholdtsen 			lprintf(LOG_ERR,
3548c18ec02fSPetter Reinholdtsen 					"Given Sampling Time '%s' is invalid.",
3549c18ec02fSPetter Reinholdtsen 					argv[8]);
3550c18ec02fSPetter Reinholdtsen 			return (-1);
3551c18ec02fSPetter Reinholdtsen 		}
3552c18ec02fSPetter Reinholdtsen 		samplingTimeLSB =  (samplingTime & 0xFF);
3553c18ec02fSPetter Reinholdtsen 		samplingTimeMSB = ((samplingTime & 0xFF00) >> 8);
3554c18ec02fSPetter Reinholdtsen 
3555c18ec02fSPetter Reinholdtsen 		rc = ipmi_dcmi_setthermalpolicy(intf,
3556c18ec02fSPetter Reinholdtsen 			entityID,
3557c18ec02fSPetter Reinholdtsen 			entityInst,
3558c18ec02fSPetter Reinholdtsen 			persistanceFlag,
3559c18ec02fSPetter Reinholdtsen 			actionHardPowerOff,
3560c18ec02fSPetter Reinholdtsen 			actionLogToSEL,
3561c18ec02fSPetter Reinholdtsen 			tempLimit,
3562c18ec02fSPetter Reinholdtsen 			samplingTimeLSB,
3563c18ec02fSPetter Reinholdtsen 			samplingTimeMSB);
3564c18ec02fSPetter Reinholdtsen 
3565c18ec02fSPetter Reinholdtsen 		break;
3566c18ec02fSPetter Reinholdtsen 	default:
3567c18ec02fSPetter Reinholdtsen 		print_strs(dcmi_thermalpolicy_vals,
3568c18ec02fSPetter Reinholdtsen 				"thermalpolicy <command>",
3569fd5fdc59SPat Donlin 				LOG_ERR, 0);
3570fd5fdc59SPat Donlin 		return -1;
3571fd5fdc59SPat Donlin 	}
3572fd5fdc59SPat Donlin 	return rc;
3573fd5fdc59SPat Donlin }
3574fd5fdc59SPat Donlin 
3575fd5fdc59SPat Donlin /*  main
3576fd5fdc59SPat Donlin  *
3577fd5fdc59SPat Donlin  * @intf:   dcmi interface handler
3578fd5fdc59SPat Donlin  * @argc:   argument count
3579fd5fdc59SPat Donlin  * @argv:   argument vector
3580fd5fdc59SPat Donlin  */
3581fd5fdc59SPat Donlin int
ipmi_dcmi_main(struct ipmi_intf * intf,int argc,char ** argv)3582fd5fdc59SPat Donlin ipmi_dcmi_main(struct ipmi_intf * intf, int argc, char **argv)
3583fd5fdc59SPat Donlin {
3584fd5fdc59SPat Donlin 	int rc = 0;
3585d5c2e976SZdenek Styblik 	int i;
3586fd5fdc59SPat Donlin 	struct ipmi_rs *rsp;
3587fd5fdc59SPat Donlin 
3588fd5fdc59SPat Donlin 	if ((argc == 0) || (strncmp(argv[0], "help", 4) == 0)) {
3589fd5fdc59SPat Donlin 		print_strs(dcmi_cmd_vals,
3590fd5fdc59SPat Donlin 				"Data Center Management Interface commands",
3591fd5fdc59SPat Donlin 				LOG_ERR, 0);
3592fd5fdc59SPat Donlin 		return -1;
3593fd5fdc59SPat Donlin 	}
3594fd5fdc59SPat Donlin 	/* start the cmd requested */
3595fd5fdc59SPat Donlin 	switch (str2val2(argv[0], dcmi_cmd_vals)) {
3596fd5fdc59SPat Donlin 	case 0x00:
3597fd5fdc59SPat Donlin 		/* discover capabilities*/
3598fd5fdc59SPat Donlin 		for (i = 1; dcmi_capable_vals[i-1].str != NULL; i++) {
3599fd5fdc59SPat Donlin 			if (ipmi_dcmi_prnt_getcapabilities(intf, i) < 0) {
3600fd5fdc59SPat Donlin 				lprintf(LOG_ERR,"Error discovering %s capabilities!\n",
3601fd5fdc59SPat Donlin 						val2str2(i, dcmi_capable_vals));
3602fd5fdc59SPat Donlin 				return -1;
3603fd5fdc59SPat Donlin 			}
3604fd5fdc59SPat Donlin 		}
3605fd5fdc59SPat Donlin 		break;
3606fd5fdc59SPat Donlin 	case 0x01:
3607fd5fdc59SPat Donlin 		/* power */
3608fd5fdc59SPat Donlin 		argv++;
3609fd5fdc59SPat Donlin 		if (argv[0] == NULL) {
3610fd5fdc59SPat Donlin 			print_strs(dcmi_pwrmgmt_vals, "power <command>",
3611fd5fdc59SPat Donlin 					LOG_ERR, 0);
3612fd5fdc59SPat Donlin 			return -1;
3613fd5fdc59SPat Donlin 		}
3614fd5fdc59SPat Donlin 		rc = ipmi_dcmi_parse_power(intf, argc, argv);
3615fd5fdc59SPat Donlin 		break;
3616fd5fdc59SPat Donlin 		/* end power command */
3617fd5fdc59SPat Donlin 	case 0x02:
3618fd5fdc59SPat Donlin 		/* sensor print */
3619fd5fdc59SPat Donlin 		/* Look for each item in the dcmi_discvry_snsr_vals struct
3620fd5fdc59SPat Donlin 		 * and if it exists, print the sdr record id(s) for it.
3621fd5fdc59SPat Donlin 		 * Use the val from each one as the sensor number.
3622fd5fdc59SPat Donlin 		 */
3623fd5fdc59SPat Donlin 		for (i = 0; dcmi_discvry_snsr_vals[i].str != NULL; i++) {
3624fd5fdc59SPat Donlin 			/* get all of the information about this sensor */
3625fd5fdc59SPat Donlin 			rc = ipmi_dcmi_prnt_discvry_snsr(intf,
3626fd5fdc59SPat Donlin 					dcmi_discvry_snsr_vals[i].val);
3627fd5fdc59SPat Donlin 		}
3628fd5fdc59SPat Donlin 		break;
3629fd5fdc59SPat Donlin 		/* end sensor print */
3630fd5fdc59SPat Donlin 	case 0x03:
3631fd5fdc59SPat Donlin 		/* asset tag */
3632fd5fdc59SPat Donlin 		if(ipmi_dcmi_prnt_getassettag(intf) < 0) {
3633fd5fdc59SPat Donlin 			lprintf(LOG_ERR, "Error getting asset tag!");
3634fd5fdc59SPat Donlin 			return -1;
3635fd5fdc59SPat Donlin 		}
3636fd5fdc59SPat Donlin 		break;
3637fd5fdc59SPat Donlin 		/* end asset tag */
3638fd5fdc59SPat Donlin 	case 0x04:
3639fd5fdc59SPat Donlin 	{
3640fd5fdc59SPat Donlin 		/* set asset tag */
3641fd5fdc59SPat Donlin 		if (argc == 1 ) {
3642fd5fdc59SPat Donlin 			print_strs(dcmi_cmd_vals,
3643fd5fdc59SPat Donlin 					"Data Center Management Interface commands",
3644fd5fdc59SPat Donlin 					LOG_ERR, 0);
3645fd5fdc59SPat Donlin 			return -1;
3646fd5fdc59SPat Donlin 		}
3647fd5fdc59SPat Donlin 		if (ipmi_dcmi_prnt_setassettag(intf, (uint8_t *)argv[1]) < 0) {
3648fd5fdc59SPat Donlin 			lprintf(LOG_ERR, "\nError setting asset tag!");
3649c18ec02fSPetter Reinholdtsen 			return -1;
3650c18ec02fSPetter Reinholdtsen 		}
3651c18ec02fSPetter Reinholdtsen 		break;
3652c18ec02fSPetter Reinholdtsen 	}
3653fd5fdc59SPat Donlin 	/* end set asset tag */
3654fd5fdc59SPat Donlin 	case 0x05:
3655fd5fdc59SPat Donlin 		/* get management controller identifier string */
3656fd5fdc59SPat Donlin 		if (ipmi_dcmi_prnt_getmngctrlids(intf) < 0) {
3657fd5fdc59SPat Donlin 			lprintf(LOG_ERR,
3658fd5fdc59SPat Donlin 					"Error getting management controller identifier string!");
3659fd5fdc59SPat Donlin 			return -1;
3660fd5fdc59SPat Donlin 		}
3661fd5fdc59SPat Donlin 		break;
3662fd5fdc59SPat Donlin 		/* end get management controller identifier string */
3663fd5fdc59SPat Donlin 	case 0x06:
3664fd5fdc59SPat Donlin 	{
3665fd5fdc59SPat Donlin 		/* set management controller identifier string */
3666fd5fdc59SPat Donlin 		if (argc == 1 ) {
3667fd5fdc59SPat Donlin 			print_strs(dcmi_cmd_vals,
3668fd5fdc59SPat Donlin 					"Data Center Management Interface commands",
3669fd5fdc59SPat Donlin 					LOG_ERR, 0);
3670fd5fdc59SPat Donlin 			return -1;
3671fd5fdc59SPat Donlin 		}
3672fd5fdc59SPat Donlin 		if (ipmi_dcmi_prnt_setmngctrlids(intf, (uint8_t *)argv[1]) < 0) {
3673fd5fdc59SPat Donlin 			lprintf(LOG_ERR,
3674fd5fdc59SPat Donlin 					"Error setting management controller identifier string!");
3675fd5fdc59SPat Donlin 			return -1;
3676fd5fdc59SPat Donlin 		}
3677fd5fdc59SPat Donlin 		break;
3678fd5fdc59SPat Donlin 	}
3679fd5fdc59SPat Donlin 	/* end set management controller identifier string */
3680fd5fdc59SPat Donlin 	case 0x07:
3681fd5fdc59SPat Donlin 		/* get/set thermal policy */
3682fd5fdc59SPat Donlin 		rc = ipmi_dcmi_thermalpolicy(intf, argc, argv);
3683fd5fdc59SPat Donlin 		break;
3684c18ec02fSPetter Reinholdtsen 	case 0x08:
3685c18ec02fSPetter Reinholdtsen 		if(ipmi_dcmi_prnt_get_temp_readings(intf) < 0 ) {
3686c18ec02fSPetter Reinholdtsen 			lprintf(LOG_ERR,
3687c18ec02fSPetter Reinholdtsen 					"Error get temperature readings!");
3688fd5fdc59SPat Donlin 			return -1;
3689c18ec02fSPetter Reinholdtsen 		}
3690c18ec02fSPetter Reinholdtsen 		break;
3691c18ec02fSPetter Reinholdtsen 	case 0x09:
3692c18ec02fSPetter Reinholdtsen 		if(ipmi_dcmi_prnt_getconfparam(intf) < 0 ) {
3693c18ec02fSPetter Reinholdtsen 			lprintf(LOG_ERR,
3694c18ec02fSPetter Reinholdtsen 					"Error Get DCMI Configuration Parameters!");
3695fd5fdc59SPat Donlin 			return -1;
3696c18ec02fSPetter Reinholdtsen 		};
3697c18ec02fSPetter Reinholdtsen 		break;
3698c18ec02fSPetter Reinholdtsen 	case 0x0A:
3699c18ec02fSPetter Reinholdtsen 	{
3700c18ec02fSPetter Reinholdtsen 		switch (argc) {
3701c18ec02fSPetter Reinholdtsen 		case 2:
3702c18ec02fSPetter Reinholdtsen 			if (strncmp(argv[1], "activate_dhcp", 13) != 0) {
3703c18ec02fSPetter Reinholdtsen 				print_strs( dcmi_conf_param_vals,
3704c18ec02fSPetter Reinholdtsen 						"DCMI Configuration Parameters",
3705fd5fdc59SPat Donlin 						LOG_ERR, 0);
3706c18ec02fSPetter Reinholdtsen 				return -1;
3707c18ec02fSPetter Reinholdtsen 			}
3708c18ec02fSPetter Reinholdtsen 			break;
3709c18ec02fSPetter Reinholdtsen 		default:
3710c18ec02fSPetter Reinholdtsen 			if (argc != 3 || strncmp(argv[1], "help", 4) == 0) {
3711c18ec02fSPetter Reinholdtsen 				print_strs(dcmi_conf_param_vals,
3712c18ec02fSPetter Reinholdtsen 						"DCMI Configuration Parameters",
3713fd5fdc59SPat Donlin 						LOG_ERR, 0);
3714c18ec02fSPetter Reinholdtsen 				return -1;
3715c18ec02fSPetter Reinholdtsen 			}
3716c18ec02fSPetter Reinholdtsen 		}
3717c18ec02fSPetter Reinholdtsen 		if (strncmp(argv[1], "activate_dhcp", 13) == 0) {
3718c18ec02fSPetter Reinholdtsen 			rsp = ipmi_dcmi_setconfparam(intf, 1, 1);
3719c18ec02fSPetter Reinholdtsen 		} else {
3720c18ec02fSPetter Reinholdtsen 			uint16_t tmp_val = 0;
3721c18ec02fSPetter Reinholdtsen 			if (str2ushort(argv[2], &tmp_val) != 0) {
3722c18ec02fSPetter Reinholdtsen 				lprintf(LOG_ERR,
3723c18ec02fSPetter Reinholdtsen 						"Given %s '%s' is invalid.",
3724c18ec02fSPetter Reinholdtsen 						argv[1], argv[2]);
3725c18ec02fSPetter Reinholdtsen 				return (-1);
3726c18ec02fSPetter Reinholdtsen 			}
3727c18ec02fSPetter Reinholdtsen 			rsp = ipmi_dcmi_setconfparam(intf,
3728c18ec02fSPetter Reinholdtsen 					str2val2(argv[1], dcmi_conf_param_vals),
3729c18ec02fSPetter Reinholdtsen 					tmp_val);
3730c18ec02fSPetter Reinholdtsen 		}
3731c18ec02fSPetter Reinholdtsen 		if (chk_rsp(rsp)) {
3732c18ec02fSPetter Reinholdtsen 			lprintf(LOG_ERR,
3733c18ec02fSPetter Reinholdtsen 					"Error Set DCMI Configuration Parameters!");
3734c18ec02fSPetter Reinholdtsen 		}
3735c18ec02fSPetter Reinholdtsen 		break;
3736c18ec02fSPetter Reinholdtsen 	}
3737c18ec02fSPetter Reinholdtsen 	case 0x0B:
3738c18ec02fSPetter Reinholdtsen 	{
3739c18ec02fSPetter Reinholdtsen 		if (intf->session == NULL) {
3740c18ec02fSPetter Reinholdtsen 			lprintf(LOG_ERR,
3741c18ec02fSPetter Reinholdtsen 					"\nOOB discovery is available only via RMCP interface.");
3742c18ec02fSPetter Reinholdtsen 			return -1;
3743c18ec02fSPetter Reinholdtsen 		}
3744c18ec02fSPetter Reinholdtsen 		if(ipmi_dcmi_prnt_oobDiscover(intf) < 0) {
3745c18ec02fSPetter Reinholdtsen 			lprintf(LOG_ERR, "\nOOB discovering capabilities failed.");
3746c18ec02fSPetter Reinholdtsen 			return -1;
3747c18ec02fSPetter Reinholdtsen 		}
3748c18ec02fSPetter Reinholdtsen 		break;
3749c18ec02fSPetter Reinholdtsen 	}
3750c18ec02fSPetter Reinholdtsen 	default:
3751c18ec02fSPetter Reinholdtsen 		/* couldn't detect what the user entered */
3752c18ec02fSPetter Reinholdtsen 		print_strs(dcmi_cmd_vals,
3753c18ec02fSPetter Reinholdtsen 				"Data Center Management Interface commands",
3754fd5fdc59SPat Donlin 				LOG_ERR, 0);
3755c18ec02fSPetter Reinholdtsen 		return -1;
3756c18ec02fSPetter Reinholdtsen 		break;
3757c18ec02fSPetter Reinholdtsen 	}
3758c18ec02fSPetter Reinholdtsen 	printf("\n");
3759fd5fdc59SPat Donlin 	return rc;
3760fd5fdc59SPat Donlin }
3761fd5fdc59SPat Donlin 
3762fd5fdc59SPat Donlin /*  Node Manager main
3763fd5fdc59SPat Donlin  *
3764fd5fdc59SPat Donlin  * @intf:   nm interface handler
3765fd5fdc59SPat Donlin  * @argc:   argument count
3766fd5fdc59SPat Donlin  * @argv:   argument vector
3767fd5fdc59SPat Donlin  */
3768fd5fdc59SPat Donlin int
ipmi_nm_main(struct ipmi_intf * intf,int argc,char ** argv)3769fd5fdc59SPat Donlin ipmi_nm_main(struct ipmi_intf * intf, int argc, char **argv)
3770fd5fdc59SPat Donlin {
3771fd5fdc59SPat Donlin 	struct nm_discover disc;
3772fd5fdc59SPat Donlin 
3773fd5fdc59SPat Donlin 	if ((argc == 0) || (strncmp(argv[0], "help", 4) == 0)) {
3774fd5fdc59SPat Donlin 		print_strs(nm_cmd_vals,
3775fd5fdc59SPat Donlin 			"Node Manager Interface commands",
3776fd5fdc59SPat Donlin 			LOG_ERR, 0);
3777fd5fdc59SPat Donlin 		return -1;
3778fd5fdc59SPat Donlin 	}
3779fd5fdc59SPat Donlin 
3780fd5fdc59SPat Donlin 	switch (str2val2(argv[0], nm_cmd_vals)) {
3781fd5fdc59SPat Donlin 	/* discover */
3782fd5fdc59SPat Donlin 	case 0x00:
3783fd5fdc59SPat Donlin 		if (_ipmi_nm_discover(intf, &disc))
3784fd5fdc59SPat Donlin 			return -1;
3785fd5fdc59SPat Donlin 		printf("    Node Manager Version %s\n", val2str2(disc.nm_version, nm_version_vals));
3786fd5fdc59SPat Donlin 		printf("    revision %d.%d%d  patch version %d\n", disc.major_rev,
3787fd5fdc59SPat Donlin 				disc.minor_rev>>4, disc.minor_rev&0xf, disc.patch_version);
3788fd5fdc59SPat Donlin 		break;
3789fd5fdc59SPat Donlin 	/* capability */
3790fd5fdc59SPat Donlin 	case 0x01:
3791fd5fdc59SPat Donlin 		if (ipmi_nm_getcapabilities(intf, argc, argv))
3792fd5fdc59SPat Donlin 			return -1;
3793fd5fdc59SPat Donlin 		break;
3794fd5fdc59SPat Donlin 	/*  policy control enable-disable */
3795fd5fdc59SPat Donlin 	case 0x02:
3796fd5fdc59SPat Donlin 		if (ipmi_nm_control(intf, argc, argv))
3797fd5fdc59SPat Donlin 			return -1;
3798fd5fdc59SPat Donlin 		break;
3799fd5fdc59SPat Donlin 	/* policy */
3800fd5fdc59SPat Donlin 	case 0x03:
3801fd5fdc59SPat Donlin 		if (ipmi_nm_policy(intf, argc, argv))
3802fd5fdc59SPat Donlin 			return -1;
3803fd5fdc59SPat Donlin 		break;
3804fd5fdc59SPat Donlin 	/* Get statistics */
3805fd5fdc59SPat Donlin 	case 0x04:
3806fd5fdc59SPat Donlin 		if (ipmi_nm_get_statistics(intf, argc, argv))
3807fd5fdc59SPat Donlin 			return -1;
3808fd5fdc59SPat Donlin 		break;
3809fd5fdc59SPat Donlin 	/* set power draw range */
3810fd5fdc59SPat Donlin 	case 0x05:
3811fd5fdc59SPat Donlin 		if (ipmi_nm_set_range(intf, argc, argv))
3812fd5fdc59SPat Donlin 			return -1;
3813fd5fdc59SPat Donlin 		break;
3814fd5fdc59SPat Donlin 	/* set/get suspend periods */
3815fd5fdc59SPat Donlin 	case 0x06:
3816fd5fdc59SPat Donlin 		if (ipmi_nm_suspend(intf, argc, argv))
3817fd5fdc59SPat Donlin 			return -1;
3818fd5fdc59SPat Donlin 		break;
3819fd5fdc59SPat Donlin 	/* reset statistics */
3820fd5fdc59SPat Donlin 	case 0x07:
3821fd5fdc59SPat Donlin 		if (ipmi_nm_reset_statistics(intf, argc, argv))
3822fd5fdc59SPat Donlin 			return -1;
3823fd5fdc59SPat Donlin 		break;
3824fd5fdc59SPat Donlin 	/* set/get alert destination */
3825fd5fdc59SPat Donlin 	case 0x08:
3826fd5fdc59SPat Donlin 		if (ipmi_nm_alert(intf, argc, argv))
3827fd5fdc59SPat Donlin 			return -1;
3828fd5fdc59SPat Donlin 		break;
3829fd5fdc59SPat Donlin 	/* set/get alert thresholds */
3830fd5fdc59SPat Donlin 	case 0x09:
3831fd5fdc59SPat Donlin 		if (ipmi_nm_thresh(intf, argc, argv))
3832fd5fdc59SPat Donlin 			return -1;
3833fd5fdc59SPat Donlin 		break;
3834fd5fdc59SPat Donlin 	default:
3835fd5fdc59SPat Donlin 		print_strs(nm_cmd_vals, "Node Manager Interface commands", LOG_ERR, 0);
3836fd5fdc59SPat Donlin 		break;
3837fd5fdc59SPat Donlin 	}
3838c18ec02fSPetter Reinholdtsen 	return 0;
3839c18ec02fSPetter Reinholdtsen }
3840c18ec02fSPetter Reinholdtsen 
3841c18ec02fSPetter Reinholdtsen /* Display DCMI sensor information
3842c18ec02fSPetter Reinholdtsen  * Uses the ipmi_sdr_get_next_header to read SDR header and compare to the
3843c18ec02fSPetter Reinholdtsen  * target Record ID. Then either ipmi_sensor_print_full or
3844c18ec02fSPetter Reinholdtsen  * ipmi_sensor_print_compact is called to print the data
3845c18ec02fSPetter Reinholdtsen  *
3846c18ec02fSPetter Reinholdtsen  * @intf:   ipmi interface handler
3847c18ec02fSPetter Reinholdtsen  * @rec_id: target Record ID
3848c18ec02fSPetter Reinholdtsen  */
3849c18ec02fSPetter Reinholdtsen static int
ipmi_print_sensor_info(struct ipmi_intf * intf,uint16_t rec_id)3850c18ec02fSPetter Reinholdtsen ipmi_print_sensor_info(struct ipmi_intf *intf, uint16_t rec_id)
3851c18ec02fSPetter Reinholdtsen {
3852c18ec02fSPetter Reinholdtsen 	struct sdr_get_rs *header;
3853c18ec02fSPetter Reinholdtsen 	struct ipmi_sdr_iterator *itr;
3854c18ec02fSPetter Reinholdtsen 	int rc = 0;
3855c18ec02fSPetter Reinholdtsen 	uint8_t *rec = NULL;
3856c18ec02fSPetter Reinholdtsen 
3857c18ec02fSPetter Reinholdtsen 	itr = ipmi_sdr_start(intf, 0);
3858c18ec02fSPetter Reinholdtsen 	if (itr == NULL) {
3859c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "Unable to open SDR for reading");
3860c18ec02fSPetter Reinholdtsen 		return (-1);
3861c18ec02fSPetter Reinholdtsen 	}
3862c18ec02fSPetter Reinholdtsen 
3863c18ec02fSPetter Reinholdtsen 	while ((header = ipmi_sdr_get_next_header(intf, itr)) != NULL) {
3864c18ec02fSPetter Reinholdtsen 		if (header->id == rec_id) {
3865c18ec02fSPetter Reinholdtsen 			break;
3866c18ec02fSPetter Reinholdtsen 		}
3867c18ec02fSPetter Reinholdtsen 	}
3868c18ec02fSPetter Reinholdtsen 	if (header == NULL) {
3869c18ec02fSPetter Reinholdtsen 		lprintf(LOG_DEBUG, "header == NULL");
3870c18ec02fSPetter Reinholdtsen 		ipmi_sdr_end(intf, itr);
3871c18ec02fSPetter Reinholdtsen 		return (-1);
3872c18ec02fSPetter Reinholdtsen 	}
3873c18ec02fSPetter Reinholdtsen 	/* yes, we found the SDR for this record ID, now get full record */
3874c18ec02fSPetter Reinholdtsen 	rec = ipmi_sdr_get_record(intf, header, itr);
3875c18ec02fSPetter Reinholdtsen 	if (rec == NULL) {
3876c18ec02fSPetter Reinholdtsen 		lprintf(LOG_DEBUG, "rec == NULL");
3877c18ec02fSPetter Reinholdtsen 		ipmi_sdr_end(intf, itr);
3878c18ec02fSPetter Reinholdtsen 		return (-1);
3879c18ec02fSPetter Reinholdtsen 	}
3880c18ec02fSPetter Reinholdtsen 	if ((header->type == SDR_RECORD_TYPE_FULL_SENSOR) ||
3881c18ec02fSPetter Reinholdtsen 			(header->type == SDR_RECORD_TYPE_COMPACT_SENSOR)) {
3882c18ec02fSPetter Reinholdtsen 		rc = ipmi_sdr_print_rawentry(intf, header->type,
3883c18ec02fSPetter Reinholdtsen 				rec, header->length);
3884c18ec02fSPetter Reinholdtsen 	} else {
3885c18ec02fSPetter Reinholdtsen 		rc = (-1);
3886c18ec02fSPetter Reinholdtsen 	}
3887c18ec02fSPetter Reinholdtsen 	free(rec);
3888c18ec02fSPetter Reinholdtsen 	rec = NULL;
3889c18ec02fSPetter Reinholdtsen 	ipmi_sdr_end(intf, itr);
3890c18ec02fSPetter Reinholdtsen 	return rc;
3891c18ec02fSPetter Reinholdtsen }
3892