1 /*
2  * ipmi_domain.h
3  *
4  * MontaVista IPMI interface for management domains
5  *
6  * Author: MontaVista Software, Inc.
7  *         Corey Minyard <minyard@mvista.com>
8  *         source@mvista.com
9  *
10  * Copyright 2002,2003 MontaVista Software Inc.
11  *
12  *  This program is free software; you can redistribute it and/or
13  *  modify it under the terms of the GNU Lesser General Public License
14  *  as published by the Free Software Foundation; either version 2 of
15  *  the License, or (at your option) any later version.
16  *
17  *
18  *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
19  *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
20  *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21  *  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
23  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
24  *  OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25  *  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
26  *  TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
27  *  USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  *
29  *  You should have received a copy of the GNU Lesser General Public
30  *  License along with this program; if not, write to the Free
31  *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
32  */
33 
34 #ifndef OPENIPMI_DOMAIN_H
35 #define OPENIPMI_DOMAIN_H
36 #include <OpenIPMI/ipmi_types.h>
37 #include <OpenIPMI/os_handler.h>
38 #include <OpenIPMI/ipmi_sdr.h>
39 #include <OpenIPMI/ipmi_addr.h>
40 #include <OpenIPMI/ipmi_fru.h>
41 
42 #include <OpenIPMI/internal/ipmi_entity.h>
43 #include <OpenIPMI/internal/ipmi_sensor.h>
44 #include <OpenIPMI/internal/ipmi_control.h>
45 
46 /* Handle validation and usecounts on domains. */
47 int i_ipmi_domain_get(ipmi_domain_t *domain);
48 void i_ipmi_domain_put(ipmi_domain_t *domain);
49 
50 /* Return the OS handler used by the mc. */
51 os_handler_t *ipmi_domain_get_os_hnd(ipmi_domain_t *domain);
52 
53 /* Return the entity info for the given domain. */
54 ipmi_entity_info_t *ipmi_domain_get_entities(ipmi_domain_t *domain);
55 
56 /* Should the BMC do a full bus scan at startup?  This is so OEM
57    code can turn this function off.  The value is a boolean. */
58 int ipmi_domain_set_full_bus_scan(ipmi_domain_t *domain, int val);
59 
60 int ipmi_domain_get_event_rcvr(ipmi_domain_t *domain);
61 
62 /* Allocate an MC in the domain.  It doesn't add it to the domain's
63    list, to allow the MC to be setup before that happens. */
64 int ipmi_create_mc(ipmi_domain_t     *domain,
65 		   const ipmi_addr_t *addr,
66 		   unsigned int      addr_len,
67 		   ipmi_mc_t         **new_mc);
68 
69 int i_ipmi_remove_mc_from_domain(ipmi_domain_t *domain, ipmi_mc_t *mc);
70 
71 /* Attempt to find the MC, and if it doesn't exist create it and
72    return it. */
73 int i_ipmi_find_or_create_mc_by_slave_addr(ipmi_domain_t *domain,
74 					   unsigned int  channel,
75 					   unsigned int  slave_addr,
76 					   ipmi_mc_t     **mc);
77 
78 /* Find the MC with the given IPMI address, or return NULL if not
79    found. */
80 ipmi_mc_t *i_ipmi_find_mc_by_addr(ipmi_domain_t     *domain,
81 				  const ipmi_addr_t *addr,
82 				  unsigned int      addr_len);
83 
84 /* Return the SDRs for the given MC, or the main set of SDRs if the MC
85    is NULL. */
86 void i_ipmi_get_sdr_sensors(ipmi_domain_t *domain,
87 			    ipmi_mc_t     *mc,
88 			    ipmi_sensor_t ***sensors,
89 			    unsigned int  *count);
90 
91 /* Set the SDRs for the given MC, or the main set of SDRs if the MC is
92    NULL. */
93 void i_ipmi_set_sdr_sensors(ipmi_domain_t *domain,
94 			    ipmi_mc_t     *mc,
95 			    ipmi_sensor_t **sensors,
96 			    unsigned int  count);
97 
98 /* Returns/set the SDRs entity info for the given MC, or the main set
99    of SDRs if the MC is NULL. */
100 void *i_ipmi_get_sdr_entities(ipmi_domain_t *domain,
101 			     ipmi_mc_t     *mc);
102 void i_ipmi_set_sdr_entities(ipmi_domain_t *domain,
103 			    ipmi_mc_t     *mc,
104 			    void          *entities);
105 
106 /* Add an MC to the list of MCs in the domain. */
107 int ipmi_add_mc_to_domain(ipmi_domain_t *domain, ipmi_mc_t *mc);
108 
109 /* Remove an MC from the list of MCs in the domain. */
110 int ipmi_remove_mc_from_domain(ipmi_domain_t *domain, ipmi_mc_t *mc);
111 
112 /* The old interfaces (for backwards compatability).  DON'T USE THESE!! */
113 struct ipmi_domain_mc_upd_s;
114 typedef struct ipmi_domain_mc_upd_s ipmi_domain_mc_upd_t
115      IPMI_TYPE_DEPRECATED;
116 int ipmi_domain_register_mc_update_handler(ipmi_domain_t         *domain,
117 					   ipmi_domain_mc_upd_cb handler,
118 					   void                  *cb_data,
119 					   struct ipmi_domain_mc_upd_s  **id)
120      IPMI_FUNC_DEPRECATED;
121 void ipmi_domain_remove_mc_update_handler(ipmi_domain_t        *domain,
122 					  struct ipmi_domain_mc_upd_s *id)
123      IPMI_FUNC_DEPRECATED;
124 
125 /* Call any OEM handlers for the given MC. */
126 int i_ipmi_domain_check_oem_handlers(ipmi_domain_t *domain, ipmi_mc_t *mc);
127 
128 /* Scan a system interface address for an MC. */
129 int ipmi_start_si_scan(ipmi_domain_t *domain,
130 		       int            si_num,
131 		       ipmi_domain_cb done_handler,
132 		       void           *cb_data);
133 
134 /* Add an IPMB address to a list of addresses to not scan.  This way,
135    if you have weak puny devices in IPMB that will break if you do
136    normal IPMB operations, you can have them be ignored. */
137 int ipmi_domain_add_ipmb_ignore(ipmi_domain_t *domain,
138 				unsigned char channel,
139 				unsigned char ipmb_addr);
140 int ipmi_domain_add_ipmb_ignore_range(ipmi_domain_t *domain,
141 				      unsigned char channel,
142 				      unsigned char first_ipmb_addr,
143 				      unsigned char last_ipmb_addr);
144 
145 /* If OEM code gets and event and it doesn't deliver it to the user,
146    it should deliver it this way, that way it can be delivered to the
147    user to be deleted. */
148 void ipmi_handle_unhandled_event(ipmi_domain_t *domain, ipmi_event_t *event);
149 
150 /* Handle a new event from something, usually from an SEL. */
151 void i_ipmi_domain_system_event_handler(ipmi_domain_t *domain,
152 				       ipmi_mc_t     *mc,
153 				       ipmi_event_t  *event);
154 
155 /* Returns the main SDR repository for the domain, or NULL if there is
156    not one. */
157 ipmi_sdr_info_t *ipmi_domain_get_main_sdrs(ipmi_domain_t *domain);
158 
159 /* Get the number of channels the domain supports. */
160 int ipmi_domain_get_num_channels(ipmi_domain_t *domain, int *val);
161 
162 /* Get information about a channel by index.  The index is not
163    necessarily the channel number, just an array index (up to the
164    number of channels).  Get the channel number from the returned
165    information. */
166 int ipmi_domain_get_channel(ipmi_domain_t    *domain,
167 			    int              index,
168 			    ipmi_chan_info_t *chan);
169 
170 /* These calls deal with OEM-type handlers for domains.  Certain
171    domains can be detected with special means (beyond just the
172    manufacturer and product id) and this allows handlers for these
173    types of domains to be registered.  At the very initial connection
174    of every domain, the handler will be called and it must detect
175    whether this is the specific type of domain or not, do any setup
176    for that domain type, and then call the done routine passed in.
177    Note that the done routine may be called later, (allowing this
178    handler to send messages and the like) but it *must* be called.
179    Note that the error value in the check_done routine should be
180    ENOSYS if the specific OEM handlers were not applicable, 0 if the
181    OEM handlers were installed, and anything else for specific
182    errors installing the OEM handlers. */
183 typedef void (*ipmi_domain_oem_check_done)(ipmi_domain_t *domain,
184 					   int           err,
185 					   void          *cb_data);
186 typedef int (*ipmi_domain_oem_check)(ipmi_domain_t              *domain,
187 				     ipmi_domain_oem_check_done done,
188 				     void                       *cb_data);
189 int ipmi_register_domain_oem_check(ipmi_domain_oem_check check,
190 				   void                  *cb_data);
191 int ipmi_deregister_domain_oem_check(ipmi_domain_oem_check check,
192 				     void                  *cb_data);
193 
194 /* Register OEM data for the domain.  Note that you can set a function
195    that will be called after all the domain messages have been flushed
196    but before anything else is destroyed.  If the OEM data or
197    destroyer is NULL, it will not be called. */
198 typedef void (*ipmi_domain_destroy_oem_data_cb)(ipmi_domain_t *domain,
199 						void          *oem_data);
200 void ipmi_domain_set_oem_data(ipmi_domain_t                   *domain,
201 			      void                            *oem_data,
202 			      ipmi_domain_destroy_oem_data_cb destroyer);
203 void *ipmi_domain_get_oem_data(ipmi_domain_t *domain);
204 
205 /* Register a call that will be done at the beginning of the domain
206    shutdown process.  Setting it to NULL will disable it. */
207 typedef void (*ipmi_domain_shutdown_cb)(ipmi_domain_t *domain);
208 void ipmi_domain_set_oem_shutdown_handler(ipmi_domain_t           *domain,
209 					  ipmi_domain_shutdown_cb handler);
210 
211 /* Used to implement special handling of FRU data for locking,
212    timestamps, etc. */
213 typedef int (*i_ipmi_domain_fru_setup_cb)(ipmi_domain_t *domain,
214 					  unsigned char is_logical,
215 					  unsigned char device_address,
216 					  unsigned char device_id,
217 					  unsigned char lun,
218 					  unsigned char private_bus,
219 					  unsigned char channel,
220 					  ipmi_fru_t    *fru,
221 					  void          *cb_data);
222 int i_ipmi_domain_fru_set_special_setup(ipmi_domain_t             *domain,
223 					i_ipmi_domain_fru_setup_cb setup,
224 					void                      *cb_data);
225 int i_ipmi_domain_fru_call_special_setup(ipmi_domain_t *domain,
226 					 unsigned char is_logical,
227 					 unsigned char device_address,
228 					 unsigned char device_id,
229 					 unsigned char lun,
230 					 unsigned char private_bus,
231 					 unsigned char channel,
232 					 ipmi_fru_t    *fru);
233 
234 /* Set the domain type for a domain. */
235 void ipmi_domain_set_type(ipmi_domain_t *domain, enum ipmi_domain_type dtype);
236 
237 /* OEM code can call this to do its own bus scanning to speed things
238    up. Must be holding the domain MC lock (i_ipmi_domain_mc_lock()) to
239    call this. */
240 void i_ipmi_start_mc_scan_one(ipmi_domain_t *domain, int chan,
241 			      int first, int last);
242 
243 /* Can be used to generate unique numbers for a domain. */
244 unsigned int ipmi_domain_get_unique_num(ipmi_domain_t *domain);
245 
246 /* Initialize the domain code, called only once at init time. */
247 int i_ipmi_domain_init(void);
248 
249 /* Clean up the global domain memory. */
250 void i_ipmi_domain_shutdown(void);
251 
252 /* Is the domain currently in shutdown? */
253 int i_ipmi_domain_in_shutdown(ipmi_domain_t *domain);
254 
255 /* Used as a refcount to know when the domain is completely
256    operational. */
257 void i_ipmi_get_domain_fully_up(ipmi_domain_t *domain, const char *name);
258 void i_ipmi_put_domain_fully_up(ipmi_domain_t *domain, const char *name);
259 
260 /* Return connections for a domain. */
261 int i_ipmi_domain_get_connection(ipmi_domain_t *domain,
262 				 int           con_num,
263 				 ipmi_con_t    **con);
264 
265 /* Option settings. */
266 int ipmi_option_SDRs(ipmi_domain_t *domain);
267 int ipmi_option_SEL(ipmi_domain_t *domain);
268 int ipmi_option_FRUs(ipmi_domain_t *domain);
269 int ipmi_option_IPMB_scan(ipmi_domain_t *domain);
270 int ipmi_option_OEM_init(ipmi_domain_t *domain);
271 int ipmi_option_set_event_rcvr(ipmi_domain_t *domain);
272 int ipmi_option_set_sel_time(ipmi_domain_t *domain);
273 int ipmi_option_activate_if_possible(ipmi_domain_t *domain);
274 int ipmi_option_local_only(ipmi_domain_t *domain);
275 int ipmi_option_use_cache(ipmi_domain_t *domain);
276 
277 void i_ipmi_option_set_local_only_if_not_specified(ipmi_domain_t *domain,
278 						   int           val);
279 
280 /*
281  * Domain attribute handling.
282  *
283  * An attribute is a string name that is registered with the domain along
284  * with a void data item.  This allows things to be attached to the domain
285  * but not directly coupled to the domain.  Names that begin with "ipmi_"
286  * belong to OpenIPMI, DON'T USE THEM.  OEM names should start with
287  * "oem_<type>_".  Other names are free for use by the application.
288  *
289  * Note that attributes are ummutable after creation and cannot be
290  * destroyed.  Destruction only happens when the domain goes away, but
291  * may be delayed to after the domain is gone due to race conditions.
292  */
293 
294 /* Attr init function.  Return the data item in the data field.  Returns
295    an error value. */
296 typedef int (*ipmi_domain_attr_init_cb)(ipmi_domain_t *domain, void *cb_data,
297 					void **data);
298 
299 /* Called when the attribute is destroyed.  Note that this may happen
300    after domain destruction, so the domain may not exist any more. */
301 typedef void (*ipmi_domain_attr_kill_cb)(void *cb_data, void *data);
302 
303 typedef struct ipmi_domain_attr_s ipmi_domain_attr_t;
304 
305 /* Find an attribute for a domain.  If the attribute is not found,
306    register the attribute.  If the registration occurs, the init()
307    function will be called (if non-null); it must return the data item
308    in the data field.  When the domain is destroyed, the destroy
309    function will be called (if not null). */
310 int ipmi_domain_register_attribute(ipmi_domain_t            *domain,
311 				   char                     *name,
312 				   ipmi_domain_attr_init_cb init,
313 				   ipmi_domain_attr_kill_cb destroy,
314 				   void                     *cb_data,
315 				   ipmi_domain_attr_t       **attr);
316 
317 /* Find an attribute in an domain.  Returns EINVAL if the name is not
318    registered.  Returns 0 on success, and the data item is
319    returned. */
320 int ipmi_domain_find_attribute(ipmi_domain_t      *domain,
321 			       char               *name,
322 			       ipmi_domain_attr_t **attr);
323 
324 /* Like the previous call, but takes a domain id. */
325 int ipmi_domain_id_find_attribute(ipmi_domain_id_t   domain_id,
326 				  char               *name,
327 				  ipmi_domain_attr_t **data);
328 
329 /* Get the data item from the attr. */
330 void *ipmi_domain_attr_get_data(ipmi_domain_attr_t *attr);
331 
332 /* Call this when you are done with the attr. */
333 void ipmi_domain_attr_put(ipmi_domain_attr_t *attr);
334 
335 /* Add/Remove a function, that is called when any new sensor is
336    added to the system and it allows OEM code to update information
337    about  it if there are domain-specific sensor types that need
338    to be adjusted.
339 */
340 typedef void (*ipmi_domain_sensor_cb)(ipmi_domain_t *domain,
341                                       ipmi_sensor_t *sensor,
342                                       void          *cb_data);
343 
344 int
345 ipmi_domain_add_new_sensor_handler(ipmi_domain_t         *domain,
346                                    ipmi_domain_sensor_cb handler,
347                                    void                  *cb_data);
348 
349 int
350 ipmi_domain_remove_new_sensor_handler(ipmi_domain_t        *domain,
351                                       ipmi_domain_sensor_cb handler,
352                                       void                *cb_data);
353 
354 int
355 i_call_new_sensor_handlers(ipmi_domain_t *domain,
356                          ipmi_sensor_t *sensor);
357 
358 
359 #endif /* OPENIPMI_DOMAIN_H */
360