~ubuntu-branches/ubuntu/intrepid/openipmi/intrepid

« back to all changes in this revision

Viewing changes to lib/sensor.c

  • Committer: Bazaar Package Importer
  • Author(s): Noèl Köthe
  • Date: 2005-07-04 21:29:17 UTC
  • Revision ID: james.westby@ubuntu.com-20050704212917-igddk5jawjmhrlay
Tags: upstream-2.0.1
Import upstream version 2.0.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * sensor.c
 
3
 *
 
4
 * MontaVista IPMI code for handling sensors
 
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
#include <string.h>
 
35
#include <stdio.h>
 
36
#include <math.h>
 
37
 
 
38
#include <OpenIPMI/ipmiif.h>
 
39
#include <OpenIPMI/ipmi_sdr.h>
 
40
#include <OpenIPMI/ipmi_msgbits.h>
 
41
#include <OpenIPMI/ipmi_err.h>
 
42
 
 
43
#include <OpenIPMI/internal/locked_list.h>
 
44
#include <OpenIPMI/internal/opq.h>
 
45
#include <OpenIPMI/internal/ipmi_int.h>
 
46
#include <OpenIPMI/internal/ipmi_sensor.h>
 
47
#include <OpenIPMI/internal/ipmi_entity.h>
 
48
#include <OpenIPMI/internal/ipmi_domain.h>
 
49
#include <OpenIPMI/internal/ipmi_mc.h>
 
50
#include <OpenIPMI/internal/ipmi_event.h>
 
51
 
 
52
struct ipmi_sensor_info_s
 
53
{
 
54
    int                      destroyed;
 
55
 
 
56
    /* Indexed by LUN and sensor # */
 
57
    ipmi_sensor_t            **(sensors_by_idx[5]);
 
58
    /* Size of above sensor array, per LUN.  This will be 0 if the
 
59
       LUN has no sensors. */
 
60
    int                      idx_size[5];
 
61
    /* In the above two, the 5th index is for non-standard sensors. */
 
62
 
 
63
    ipmi_lock_t *idx_lock;
 
64
 
 
65
    /* Total number of sensors we have in this. */
 
66
    unsigned int sensor_count;
 
67
 
 
68
    opq_t *sensor_wait_q;
 
69
    int  wait_err;
 
70
};
 
71
 
 
72
#define SENSOR_ID_LEN 32 /* 16 bytes are allowed for a sensor. */
 
73
struct ipmi_sensor_s
 
74
{
 
75
    unsigned int  usecount;
 
76
 
 
77
    ipmi_domain_t *domain; /* Domain I am in. */
 
78
 
 
79
    ipmi_mc_t     *mc; /* My owner, NOT the SMI mc (unless that
 
80
                          happens to be my direct owner). */
 
81
 
 
82
    ipmi_mc_t     *source_mc; /* If the sensor came from the main SDR,
 
83
                                 this will be NULL.  Otherwise, it
 
84
                                 will be the MC that owned the device
 
85
                                 SDR this came from. */
 
86
    int           source_idx; /* The index into the source array where
 
87
                                 this is stored.  This will be -1 if
 
88
                                 it does not have a source index (ie
 
89
                                 it's a non-standard sensor) */
 
90
    int           source_recid; /* The SDR record ID the sensor came from. */
 
91
    ipmi_sensor_t **source_array; /* This is the source array where
 
92
                                     the sensor is stored. */
 
93
 
 
94
    int           destroyed;
 
95
 
 
96
    /* After the sensor is added, it will not be reported immediately.
 
97
       Instead, it will wait until the usecount goes to zero before
 
98
       being reported.  This marks that the add report is pending */
 
99
    int add_pending;
 
100
 
 
101
    unsigned char owner;
 
102
    unsigned char channel;
 
103
    unsigned char lun;
 
104
    unsigned char num;
 
105
 
 
106
    /* For OEM sensors, the sending LUN might be different that the
 
107
       LUN we use for storage. */
 
108
    unsigned char send_lun;
 
109
 
 
110
    ipmi_entity_t *entity;
 
111
 
 
112
    unsigned char entity_id;
 
113
    unsigned char entity_instance;
 
114
 
 
115
    unsigned char entity_instance_logical : 1;
 
116
    unsigned int  sensor_init_scanning : 1;
 
117
    unsigned int  sensor_init_events : 1;
 
118
    unsigned int  sensor_init_thresholds : 1;
 
119
    unsigned int  sensor_init_hysteresis : 1;
 
120
    unsigned int  sensor_init_type : 1;
 
121
    unsigned int  sensor_init_pu_events : 1;
 
122
    unsigned int  sensor_init_pu_scanning : 1;
 
123
    unsigned int  ignore_if_no_entity : 1;
 
124
    unsigned int  supports_auto_rearm : 1;
 
125
    unsigned int  hysteresis_support : 2;
 
126
    unsigned int  threshold_access : 2;
 
127
    unsigned int  event_support : 2;
 
128
 
 
129
    unsigned int sensor_direction : 2;
 
130
 
 
131
    int          hot_swap_requester;
 
132
    unsigned int hot_swap_requester_val;
 
133
 
 
134
    unsigned char sensor_type;
 
135
 
 
136
    unsigned char event_reading_type;
 
137
 
 
138
    unsigned char mask1[16];
 
139
    unsigned char mask2[16];
 
140
    unsigned char mask3[16];
 
141
 
 
142
    unsigned int  analog_data_format : 2;
 
143
 
 
144
    unsigned int  rate_unit : 3;
 
145
 
 
146
    unsigned int  modifier_unit_use : 2;
 
147
 
 
148
    unsigned int  percentage : 1;
 
149
 
 
150
    unsigned char base_unit;
 
151
    unsigned char modifier_unit;
 
152
 
 
153
    unsigned char linearization;
 
154
 
 
155
    struct {
 
156
        int m : 10;
 
157
        unsigned int tolerance : 6;
 
158
        int b : 10;
 
159
        int r_exp : 4;
 
160
        unsigned int accuracy_exp : 2;
 
161
        int accuracy : 10;
 
162
        int b_exp : 4;
 
163
    } conv[256];
 
164
 
 
165
    unsigned int  normal_min_specified : 1;
 
166
    unsigned int  normal_max_specified : 1;
 
167
    unsigned int  nominal_reading_specified : 1;
 
168
 
 
169
    unsigned char nominal_reading;
 
170
    unsigned char normal_max;
 
171
    unsigned char normal_min;
 
172
    unsigned char sensor_max;
 
173
    unsigned char sensor_min;
 
174
    unsigned char default_thresholds[6];
 
175
    unsigned char positive_going_threshold_hysteresis;
 
176
    unsigned char negative_going_threshold_hysteresis;
 
177
 
 
178
 
 
179
    unsigned char oem1;
 
180
 
 
181
    /* Note that the ID is *not* nil terminated. */
 
182
    enum ipmi_str_type_e id_type;
 
183
    unsigned int id_len;
 
184
    char id[SENSOR_ID_LEN]; /* The ID from the device SDR. */
 
185
 
 
186
    const char *sensor_type_string;
 
187
    const char *event_reading_type_string;
 
188
    const char *rate_unit_string;
 
189
    const char *base_unit_string;
 
190
    const char *modifier_unit_string;
 
191
 
 
192
    /* A list of handlers to call when an event for the sensor comes
 
193
       in. */
 
194
    locked_list_t *handler_list;
 
195
 
 
196
    opq_t *waitq;
 
197
    ipmi_event_state_t event_state;
 
198
 
 
199
    /* Polymorphic functions. */
 
200
    ipmi_sensor_cbs_t cbs;
 
201
 
 
202
    /* OEM info */
 
203
    void                            *oem_info;
 
204
    ipmi_sensor_cleanup_oem_info_cb oem_info_cleanup_handler;
 
205
 
 
206
    ipmi_sensor_destroy_cb destroy_handler;
 
207
    void                   *destroy_handler_cb_data;
 
208
 
 
209
    /* Name we use for reporting.  We add a ' ' onto the end, thus
 
210
       the +1. */
 
211
    char name[IPMI_SENSOR_NAME_LEN+1];
 
212
 
 
213
    /* Used for temporary linking. */
 
214
    ipmi_sensor_t *tlink;
 
215
 
 
216
    /* Cruft. */
 
217
    ipmi_sensor_threshold_event_handler_nd_cb threshold_event_handler;
 
218
    ipmi_sensor_discrete_event_handler_nd_cb  discrete_event_handler;
 
219
    void                         *cb_data;
 
220
};
 
221
 
 
222
static void sensor_final_destroy(ipmi_sensor_t *sensor);
 
223
 
 
224
/***********************************************************************
 
225
 *
 
226
 * Sensor ID handling.
 
227
 *
 
228
 **********************************************************************/
 
229
 
 
230
/* Must be called with the domain entity lock held. */
 
231
int
 
232
_ipmi_sensor_get(ipmi_sensor_t *sensor)
 
233
{
 
234
    if (sensor->destroyed)
 
235
        return EINVAL;
 
236
    sensor->usecount++;
 
237
    return 0;
 
238
}
 
239
 
 
240
void
 
241
_ipmi_sensor_put(ipmi_sensor_t *sensor)
 
242
{
 
243
    ipmi_domain_t *domain = sensor->domain;
 
244
    _ipmi_domain_entity_lock(domain);
 
245
    if (sensor->usecount == 1) {
 
246
        if (sensor->add_pending) {
 
247
            sensor->add_pending = 0;
 
248
            _ipmi_domain_entity_unlock(sensor->domain);
 
249
            _ipmi_entity_call_sensor_handlers(sensor->entity,
 
250
                                              sensor, IPMI_ADDED);
 
251
            _ipmi_domain_entity_lock(sensor->domain);
 
252
        }
 
253
        if (sensor->destroyed
 
254
            && (!sensor->waitq
 
255
                || (!opq_stuff_in_progress(sensor->waitq))))
 
256
        {
 
257
            _ipmi_domain_entity_unlock(domain);
 
258
            sensor_final_destroy(sensor);
 
259
            return;
 
260
        }
 
261
    }
 
262
    sensor->usecount--;
 
263
    _ipmi_domain_entity_unlock(domain);
 
264
}
 
265
 
 
266
ipmi_sensor_id_t
 
267
ipmi_sensor_convert_to_id(ipmi_sensor_t *sensor)
 
268
{
 
269
    ipmi_sensor_id_t val;
 
270
 
 
271
    CHECK_SENSOR_LOCK(sensor);
 
272
 
 
273
    val.mcid = ipmi_mc_convert_to_id(sensor->mc);
 
274
    val.lun = sensor->lun;
 
275
    val.sensor_num = sensor->num;
 
276
 
 
277
    return val;
 
278
}
 
279
 
 
280
int
 
281
ipmi_cmp_sensor_id(ipmi_sensor_id_t id1, ipmi_sensor_id_t id2)
 
282
{
 
283
    int rv;
 
284
 
 
285
    rv = ipmi_cmp_mc_id(id1.mcid, id2.mcid);
 
286
    if (rv)
 
287
        return rv;
 
288
    if (id1.lun > id2.lun)
 
289
        return 1;
 
290
    if (id1.lun < id2.lun)
 
291
        return -1;
 
292
    if (id1.sensor_num > id2.sensor_num)
 
293
        return 1;
 
294
    if (id1.sensor_num < id2.sensor_num)
 
295
        return -1;
 
296
    return 0;
 
297
}
 
298
 
 
299
void
 
300
ipmi_sensor_id_set_invalid(ipmi_sensor_id_t *id)
 
301
{
 
302
    memset(id, 0, sizeof(*id));
 
303
}
 
304
 
 
305
int
 
306
ipmi_sensor_id_is_invalid(ipmi_sensor_id_t *id)
 
307
{
 
308
    return (id->mcid.domain_id.domain == NULL);
 
309
}
 
310
 
 
311
typedef struct mc_cb_info_s
 
312
{
 
313
    ipmi_sensor_ptr_cb handler;
 
314
    void               *cb_data;
 
315
    ipmi_sensor_id_t   id;
 
316
    int                err;
 
317
} mc_cb_info_t;
 
318
 
 
319
static void
 
320
mc_cb(ipmi_mc_t *mc, void *cb_data)
 
321
{
 
322
    mc_cb_info_t       *info = cb_data;
 
323
    ipmi_sensor_info_t *sensors;
 
324
    ipmi_domain_t      *domain = ipmi_mc_get_domain(mc);
 
325
    ipmi_sensor_t      *sensor;
 
326
    ipmi_entity_t      *entity = NULL;
 
327
    
 
328
    sensors = _ipmi_mc_get_sensors(mc);
 
329
    _ipmi_domain_entity_lock(domain);
 
330
    if (info->id.lun > 4) {
 
331
        info->err = EINVAL;
 
332
        goto out_unlock;
 
333
    }
 
334
 
 
335
    if (info->id.sensor_num >= sensors->idx_size[info->id.lun]) {
 
336
        info->err = EINVAL;
 
337
        goto out_unlock;
 
338
    }
 
339
 
 
340
    sensor = sensors->sensors_by_idx[info->id.lun][info->id.sensor_num];
 
341
    if (!sensor) {
 
342
        info->err = EINVAL;
 
343
        goto out_unlock;
 
344
    }
 
345
 
 
346
    info->err = _ipmi_entity_get(sensor->entity);
 
347
    if (info->err)
 
348
        goto out_unlock;
 
349
    entity = sensor->entity;
 
350
 
 
351
    info->err = _ipmi_sensor_get(sensor);
 
352
    if (info->err)
 
353
        goto out_unlock;
 
354
 
 
355
    _ipmi_domain_entity_unlock(domain);
 
356
 
 
357
    info->handler(sensor, info->cb_data);
 
358
 
 
359
    _ipmi_sensor_put(sensor);
 
360
    _ipmi_entity_put(entity);
 
361
    return;
 
362
 
 
363
 out_unlock:
 
364
    _ipmi_domain_entity_unlock(domain);
 
365
    if (entity)
 
366
        _ipmi_entity_put(entity);
 
367
}
 
368
 
 
369
int
 
370
ipmi_sensor_pointer_cb(ipmi_sensor_id_t   id,
 
371
                       ipmi_sensor_ptr_cb handler,
 
372
                       void               *cb_data)
 
373
{
 
374
    int          rv;
 
375
    mc_cb_info_t info;
 
376
 
 
377
    if (id.lun >= 5)
 
378
        return EINVAL;
 
379
 
 
380
    info.handler = handler;
 
381
    info.cb_data = cb_data;
 
382
    info.id = id;
 
383
    info.err = 0;
 
384
 
 
385
    rv = ipmi_mc_pointer_cb(id.mcid, mc_cb, &info);
 
386
    if (!rv)
 
387
        rv = info.err;
 
388
 
 
389
    return rv;
 
390
}
 
391
 
 
392
int
 
393
ipmi_sensor_pointer_noseq_cb(ipmi_sensor_id_t   id,
 
394
                             ipmi_sensor_ptr_cb handler,
 
395
                             void               *cb_data)
 
396
{
 
397
    int          rv;
 
398
    mc_cb_info_t info;
 
399
 
 
400
    if (id.lun >= 5)
 
401
        return EINVAL;
 
402
 
 
403
    info.handler = handler;
 
404
    info.cb_data = cb_data;
 
405
    info.id = id;
 
406
    info.err = 0;
 
407
 
 
408
    rv = ipmi_mc_pointer_noseq_cb(id.mcid, mc_cb, &info);
 
409
    if (!rv)
 
410
        rv = info.err;
 
411
 
 
412
    return rv;
 
413
}
 
414
 
 
415
typedef struct sensor_find_info_s
 
416
{
 
417
    ipmi_sensor_id_t id;
 
418
    char             *id_name;
 
419
    int              rv;
 
420
} sensor_find_info_t;
 
421
 
 
422
static void
 
423
sensor_search_cmp(ipmi_entity_t *entity, ipmi_sensor_t *sensor, void *cb_data)
 
424
{
 
425
    sensor_find_info_t *info = cb_data;
 
426
    char               id[33];
 
427
    int                rv;
 
428
 
 
429
    rv = ipmi_sensor_get_id(sensor, id, 33);
 
430
    if (rv) 
 
431
        return;
 
432
    if (strcmp(info->id_name, id) == 0) {
 
433
        info->id = ipmi_sensor_convert_to_id(sensor);
 
434
        info->rv = 0;
 
435
    }
 
436
}
 
437
 
 
438
static void
 
439
sensor_search(ipmi_entity_t *entity, void *cb_data)
 
440
{
 
441
    sensor_find_info_t *info = cb_data;
 
442
 
 
443
    ipmi_entity_iterate_sensors(entity, sensor_search_cmp, info);
 
444
}
 
445
 
 
446
int
 
447
ipmi_sensor_find_id(ipmi_domain_id_t domain_id,
 
448
                    int entity_id, int entity_instance,
 
449
                    int channel, int slave_address,
 
450
                    char *id_name,
 
451
                    ipmi_sensor_id_t *id)
 
452
{
 
453
    int                rv;
 
454
    ipmi_entity_id_t   entity;
 
455
    sensor_find_info_t info;
 
456
 
 
457
    rv = ipmi_entity_find_id(domain_id, entity_id, entity_instance,
 
458
                             channel, slave_address, &entity);
 
459
    if (rv)
 
460
        return rv;
 
461
 
 
462
    info.id_name = id_name;
 
463
    info.rv = EINVAL;
 
464
 
 
465
    rv = ipmi_entity_pointer_cb(entity, sensor_search, &info);
 
466
    if (!rv)
 
467
        rv = info.rv;
 
468
    if (!rv)
 
469
        *id = info.id;
 
470
 
 
471
    return rv;
 
472
}
 
473
 
 
474
/***********************************************************************
 
475
 *
 
476
 * Various sensor allocation/deallocation/opq/etc.
 
477
 *
 
478
 **********************************************************************/
 
479
 
 
480
static void sensor_set_name(ipmi_sensor_t *sensor);
 
481
 
 
482
static void
 
483
sensor_opq_ready2(ipmi_sensor_t *sensor, void *cb_data)
 
484
{
 
485
    ipmi_sensor_op_info_t *info = cb_data;
 
486
    if (info->__handler)
 
487
        info->__handler(sensor, 0, info->__cb_data);
 
488
}
 
489
 
 
490
static void
 
491
sensor_opq_ready(void *cb_data, int shutdown)
 
492
{
 
493
    ipmi_sensor_op_info_t *info = cb_data;
 
494
    int                   rv;
 
495
 
 
496
    if (shutdown) {
 
497
        if (info->__handler)
 
498
            info->__handler(info->__sensor, ECANCELED, info->__cb_data);
 
499
        return;
 
500
    }
 
501
 
 
502
    rv = ipmi_sensor_pointer_cb(info->__sensor_id, sensor_opq_ready2, info);
 
503
    if (rv)
 
504
        if (info->__handler)
 
505
            info->__handler(info->__sensor, rv, info->__cb_data);
 
506
}
 
507
 
 
508
int
 
509
ipmi_sensor_add_opq(ipmi_sensor_t         *sensor,
 
510
                    ipmi_sensor_op_cb     handler,
 
511
                    ipmi_sensor_op_info_t *info,
 
512
                    void                  *cb_data)
 
513
{
 
514
    if (sensor->destroyed)
 
515
        return EINVAL;
 
516
 
 
517
    info->__sensor = sensor;
 
518
    info->__sensor_id = ipmi_sensor_convert_to_id(sensor);
 
519
    info->__cb_data = cb_data;
 
520
    info->__handler = handler;
 
521
    if (!opq_new_op(sensor->waitq, sensor_opq_ready, info, 0))
 
522
        return ENOMEM;
 
523
    return 0;
 
524
}
 
525
 
 
526
static void
 
527
sensor_id_add_opq_cb(ipmi_sensor_t *sensor, void *cb_data)
 
528
{
 
529
    ipmi_sensor_op_info_t *info = cb_data;
 
530
 
 
531
    info->__sensor = sensor;
 
532
    if (!opq_new_op(sensor->waitq, sensor_opq_ready, info, 0))
 
533
        info->__err = ENOMEM;
 
534
}
 
535
 
 
536
int
 
537
ipmi_sensor_id_add_opq(ipmi_sensor_id_t      sensor_id,
 
538
                       ipmi_sensor_op_cb     handler,
 
539
                       ipmi_sensor_op_info_t *info,
 
540
                       void                  *cb_data)
 
541
{
 
542
    int rv;
 
543
 
 
544
    info->__sensor_id = sensor_id;
 
545
    info->__cb_data = cb_data;
 
546
    info->__handler = handler;
 
547
    info->__err = 0;
 
548
    rv = ipmi_sensor_pointer_cb(sensor_id, sensor_id_add_opq_cb, info);
 
549
    if (!rv)
 
550
        rv = info->__err;
 
551
    return rv;
 
552
}
 
553
 
 
554
void
 
555
ipmi_sensor_opq_done(ipmi_sensor_t *sensor)
 
556
{
 
557
    /* Protect myself from NULL sensors.  This way, it doesn't have to
 
558
       be done in each call. */
 
559
    if (!sensor)
 
560
        return;
 
561
 
 
562
    /* This gets called on ECANCELLED error cases, if the sensor is
 
563
       already we need to clear out the opq. */
 
564
    if (sensor->destroyed) {
 
565
        if (sensor->waitq) {
 
566
            opq_destroy(sensor->waitq);
 
567
            sensor->waitq = NULL;
 
568
        }
 
569
        return;
 
570
    }
 
571
 
 
572
    /* No check for the sensor lock.  It will sometimes fail at
 
573
       destruction time. */
 
574
 
 
575
    opq_op_done(sensor->waitq);
 
576
}
 
577
 
 
578
static void
 
579
sensor_rsp_handler2(ipmi_sensor_t *sensor, void *cb_data)
 
580
{
 
581
    ipmi_sensor_op_info_t *info = cb_data;
 
582
 
 
583
    if (info->__rsp_handler)
 
584
        info->__rsp_handler(sensor, 0, info->__rsp, info->__cb_data);
 
585
}
 
586
 
 
587
static void
 
588
sensor_rsp_handler(ipmi_mc_t  *mc,
 
589
                   ipmi_msg_t *rsp,
 
590
                   void       *rsp_data)
 
591
{
 
592
    ipmi_sensor_op_info_t *info = rsp_data;
 
593
    int                   rv;
 
594
    ipmi_sensor_t         *sensor = info->__sensor;
 
595
 
 
596
    if (sensor->destroyed) {
 
597
        ipmi_entity_t *entity = NULL;
 
598
 
 
599
        _ipmi_domain_entity_lock(sensor->domain);
 
600
        sensor->usecount++;
 
601
        _ipmi_domain_entity_unlock(sensor->domain);
 
602
 
 
603
        rv = _ipmi_entity_get(sensor->entity);
 
604
        if (! rv)
 
605
            entity = sensor->entity;
 
606
 
 
607
        if (info->__rsp_handler)
 
608
            info->__rsp_handler(sensor, ECANCELED, NULL, info->__cb_data);
 
609
 
 
610
        _ipmi_sensor_put(sensor);
 
611
        if (entity)
 
612
            _ipmi_entity_put(entity);
 
613
        return;
 
614
    }
 
615
 
 
616
    if (!mc) {
 
617
        if (info->__rsp_handler)
 
618
            info->__rsp_handler(sensor, ECANCELED, rsp, info->__cb_data);
 
619
        return;
 
620
    }
 
621
 
 
622
    /* Call the next stage with the lock held. */
 
623
    info->__rsp = rsp;
 
624
    rv = ipmi_sensor_pointer_cb(info->__sensor_id,
 
625
                                sensor_rsp_handler2,
 
626
                                info);
 
627
    if (rv) {
 
628
        ipmi_log(IPMI_LOG_ERR_INFO,
 
629
                 "%ssensor.c(sensor_rsp_handler):"
 
630
                 " Could not convert sensor id to a pointer",
 
631
                 MC_NAME(mc));
 
632
        if (info->__rsp_handler)
 
633
            info->__rsp_handler(sensor, rv, NULL, info->__cb_data);
 
634
    }
 
635
}
 
636
                         
 
637
int
 
638
ipmi_sensor_send_command(ipmi_sensor_t         *sensor,
 
639
                         ipmi_mc_t             *mc,
 
640
                         unsigned int          lun,
 
641
                         ipmi_msg_t            *msg,
 
642
                         ipmi_sensor_rsp_cb    handler,
 
643
                         ipmi_sensor_op_info_t *info,
 
644
                         void                  *cb_data)
 
645
{
 
646
    int rv;
 
647
 
 
648
    CHECK_MC_LOCK(mc);
 
649
    CHECK_SENSOR_LOCK(sensor);
 
650
 
 
651
    if (sensor->destroyed)
 
652
        return EINVAL;
 
653
 
 
654
    info->__sensor = sensor;
 
655
    info->__sensor_id = ipmi_sensor_convert_to_id(sensor);
 
656
    info->__cb_data = cb_data;
 
657
    info->__rsp_handler = handler;
 
658
    rv = ipmi_mc_send_command(mc, lun, msg, sensor_rsp_handler, info);
 
659
    return rv;
 
660
}
 
661
 
 
662
static int
 
663
sensor_addr_response_handler(ipmi_domain_t *domain, ipmi_msgi_t *rspi)
 
664
{
 
665
    ipmi_msg_t            *msg = &rspi->msg;
 
666
    ipmi_sensor_op_info_t *info = rspi->data1;
 
667
    int                   rv;
 
668
    ipmi_sensor_t         *sensor = info->__sensor;
 
669
 
 
670
    if (sensor->destroyed) {
 
671
        if (info->__rsp_handler)
 
672
            info->__rsp_handler(NULL, ECANCELED, NULL, info->__cb_data);
 
673
 
 
674
        _ipmi_domain_entity_lock(sensor->domain);
 
675
        sensor->usecount++;
 
676
        _ipmi_domain_entity_unlock(sensor->domain);
 
677
        _ipmi_sensor_put(sensor);
 
678
        return IPMI_MSG_ITEM_NOT_USED;
 
679
    }
 
680
 
 
681
    /* Call the next stage with the lock held. */
 
682
    info->__rsp = msg;
 
683
    rv = ipmi_sensor_pointer_cb(info->__sensor_id,
 
684
                                sensor_rsp_handler2,
 
685
                                info);
 
686
    if (rv) {
 
687
        ipmi_log(IPMI_LOG_ERR_INFO,
 
688
                 "%ssensor.c(sensor_addr_rsp_handler):"
 
689
                 " Could not convert sensor id to a pointer",
 
690
                 DOMAIN_NAME(domain));
 
691
        if (info->__rsp_handler)
 
692
            info->__rsp_handler(sensor, rv, NULL, info->__cb_data);
 
693
    }
 
694
    return IPMI_MSG_ITEM_NOT_USED;
 
695
}
 
696
 
 
697
int
 
698
ipmi_sensor_send_command_addr(ipmi_domain_t         *domain,
 
699
                              ipmi_sensor_t         *sensor,
 
700
                              ipmi_addr_t           *addr,
 
701
                              unsigned int          addr_len,
 
702
                              ipmi_msg_t            *msg,
 
703
                              ipmi_sensor_rsp_cb    handler,
 
704
                              ipmi_sensor_op_info_t *info,
 
705
                              void                  *cb_data)
 
706
{
 
707
    int rv;
 
708
 
 
709
    CHECK_SENSOR_LOCK(sensor);
 
710
    CHECK_MC_LOCK(sensor->mc);
 
711
 
 
712
    info->__sensor = sensor;
 
713
    info->__sensor_id = ipmi_sensor_convert_to_id(sensor);
 
714
    info->__cb_data = cb_data;
 
715
    info->__rsp_handler = handler;
 
716
    rv = ipmi_send_command_addr(domain, addr, addr_len,
 
717
                                msg, sensor_addr_response_handler, info, NULL);
 
718
    return rv;
 
719
}
 
720
 
 
721
int
 
722
ipmi_sensors_alloc(ipmi_mc_t *mc, ipmi_sensor_info_t **new_sensors)
 
723
{
 
724
    ipmi_sensor_info_t *sensors;
 
725
    ipmi_domain_t      *domain;
 
726
    os_handler_t       *os_hnd;
 
727
    int                i;
 
728
    int                rv;
 
729
 
 
730
    CHECK_MC_LOCK(mc);
 
731
 
 
732
    domain = ipmi_mc_get_domain(mc);
 
733
    os_hnd = ipmi_domain_get_os_hnd(domain);
 
734
 
 
735
    sensors = ipmi_mem_alloc(sizeof(*sensors));
 
736
    if (!sensors)
 
737
        return ENOMEM;
 
738
    sensors->sensor_wait_q = opq_alloc(os_hnd);
 
739
    if (! sensors->sensor_wait_q) {
 
740
        ipmi_mem_free(sensors);
 
741
        return ENOMEM;
 
742
    }
 
743
 
 
744
    rv = ipmi_create_lock_os_hnd(os_hnd, &sensors->idx_lock);
 
745
    if (rv) {
 
746
        opq_destroy(sensors->sensor_wait_q);
 
747
        ipmi_mem_free(sensors);
 
748
        return rv;
 
749
    }
 
750
 
 
751
    sensors->destroyed = 0;
 
752
    sensors->sensor_count = 0;
 
753
    for (i=0; i<5; i++) {
 
754
        sensors->sensors_by_idx[i] = NULL;
 
755
        sensors->idx_size[i] = 0;
 
756
    }
 
757
 
 
758
    *new_sensors = sensors;
 
759
    return 0;
 
760
}
 
761
 
 
762
unsigned int
 
763
ipmi_sensors_get_count(ipmi_sensor_info_t *sensors)
 
764
{
 
765
    return sensors->sensor_count;
 
766
}
 
767
 
 
768
opq_t *
 
769
_ipmi_sensors_get_waitq(ipmi_sensor_info_t *sensors)
 
770
{
 
771
    return sensors->sensor_wait_q;
 
772
}
 
773
 
 
774
int
 
775
ipmi_sensor_alloc_nonstandard(ipmi_sensor_t **new_sensor)
 
776
{
 
777
    ipmi_sensor_t *sensor;
 
778
 
 
779
    sensor = ipmi_mem_alloc(sizeof(*sensor));
 
780
    if (!sensor)
 
781
        return ENOMEM;
 
782
 
 
783
    memset(sensor, 0, sizeof(*sensor));
 
784
 
 
785
    sensor->hot_swap_requester = -1;
 
786
    sensor->usecount = 1;
 
787
 
 
788
    *new_sensor = sensor;
 
789
    return 0;
 
790
}
 
791
 
 
792
int
 
793
ipmi_sensor_add_nonstandard(ipmi_mc_t              *mc,
 
794
                            ipmi_mc_t              *source_mc,
 
795
                            ipmi_sensor_t          *sensor,
 
796
                            unsigned int           num,
 
797
                            unsigned int           send_lun,
 
798
                            ipmi_entity_t          *ent,
 
799
                            ipmi_sensor_destroy_cb destroy_handler,
 
800
                            void                   *destroy_handler_cb_data)
 
801
{
 
802
    ipmi_sensor_info_t *sensors = _ipmi_mc_get_sensors(mc);
 
803
    ipmi_domain_t      *domain;
 
804
    os_handler_t       *os_hnd;
 
805
    void               *link;
 
806
 
 
807
    CHECK_MC_LOCK(mc);
 
808
    CHECK_ENTITY_LOCK(ent);
 
809
 
 
810
    domain = ipmi_mc_get_domain(mc);
 
811
    os_hnd = ipmi_domain_get_os_hnd(domain);
 
812
 
 
813
    if (num >= 256)
 
814
        return EINVAL;
 
815
 
 
816
    _ipmi_domain_entity_lock(domain);
 
817
    ipmi_lock(sensors->idx_lock);
 
818
 
 
819
    if (num >= sensors->idx_size[4]) {
 
820
        ipmi_sensor_t **new_array;
 
821
        unsigned int  new_size;
 
822
        int           i;
 
823
 
 
824
        /* Allocate the array in multiples of 16 (to avoid thrashing malloc
 
825
           too much). */
 
826
        new_size = ((num / 16) * 16) + 16;
 
827
        new_array = ipmi_mem_alloc(sizeof(*new_array) * new_size);
 
828
        if (!new_array)
 
829
            return ENOMEM;
 
830
        if (sensors->sensors_by_idx[4]) {
 
831
            memcpy(new_array, sensors->sensors_by_idx[4],
 
832
                   sizeof(*new_array) * (sensors->idx_size[4]));
 
833
            ipmi_mem_free(sensors->sensors_by_idx[4]);
 
834
        }
 
835
        for (i=sensors->idx_size[4]; i<new_size; i++)
 
836
            new_array[i] = NULL;
 
837
        sensors->sensors_by_idx[4] = new_array;
 
838
        sensors->idx_size[4] = new_size;
 
839
    }
 
840
 
 
841
    sensor->waitq = opq_alloc(os_hnd);
 
842
    if (! sensor->waitq)
 
843
        return ENOMEM;
 
844
 
 
845
    sensor->handler_list = locked_list_alloc(os_hnd);
 
846
    if (! sensor->handler_list) {
 
847
        opq_destroy(sensor->waitq);
 
848
        return ENOMEM;
 
849
    }
 
850
 
 
851
    link = locked_list_alloc_entry();
 
852
    if (!link) {
 
853
        opq_destroy(sensor->waitq);
 
854
        sensor->waitq = NULL;
 
855
        locked_list_destroy(sensor->handler_list);
 
856
        sensor->handler_list = NULL;
 
857
        return ENOMEM;
 
858
    }
 
859
 
 
860
    sensor->domain = domain;
 
861
    sensor->mc = mc;
 
862
    sensor->source_mc = source_mc;
 
863
    sensor->lun = 4;
 
864
    sensor->send_lun = send_lun;
 
865
    sensor->num = num;
 
866
    sensor->source_idx = -1;
 
867
    sensor->source_array = NULL;
 
868
    if (!sensors->sensors_by_idx[4][num])
 
869
        sensors->sensor_count++;
 
870
    sensors->sensors_by_idx[4][num] = sensor;
 
871
    sensor->entity = ent;
 
872
    sensor->entity_id = ipmi_entity_get_entity_id(ent);
 
873
    sensor->entity_instance = ipmi_entity_get_entity_instance(ent);
 
874
    sensor->destroy_handler = destroy_handler;
 
875
    sensor->destroy_handler_cb_data = destroy_handler_cb_data;
 
876
    sensor_set_name(sensor);
 
877
 
 
878
    ipmi_unlock(sensors->idx_lock);
 
879
 
 
880
    _ipmi_domain_entity_unlock(domain);
 
881
 
 
882
    ipmi_entity_add_sensor(ent, sensor, link);
 
883
 
 
884
    sensor->add_pending = 1;
 
885
 
 
886
    return 0;
 
887
}
 
888
 
 
889
static void
 
890
sensor_final_destroy(ipmi_sensor_t *sensor)
 
891
{
 
892
    _ipmi_entity_get(sensor->entity);
 
893
    _ipmi_entity_call_sensor_handlers(sensor->entity, sensor, IPMI_DELETED);
 
894
 
 
895
    sensor->mc = NULL;
 
896
 
 
897
    if (sensor->destroy_handler)
 
898
        sensor->destroy_handler(sensor, sensor->destroy_handler_cb_data);
 
899
 
 
900
    if (sensor->oem_info_cleanup_handler)
 
901
        sensor->oem_info_cleanup_handler(sensor, sensor->oem_info);
 
902
 
 
903
    if (sensor->waitq)
 
904
        opq_destroy(sensor->waitq);
 
905
 
 
906
    if (sensor->handler_list)
 
907
        locked_list_destroy(sensor->handler_list);
 
908
 
 
909
    if (sensor->entity)
 
910
        ipmi_entity_remove_sensor(sensor->entity, sensor);
 
911
 
 
912
    _ipmi_entity_put(sensor->entity);
 
913
    ipmi_mem_free(sensor);
 
914
}
 
915
 
 
916
int
 
917
ipmi_sensor_destroy(ipmi_sensor_t *sensor)
 
918
{
 
919
    ipmi_sensor_info_t *sensors = _ipmi_mc_get_sensors(sensor->mc);
 
920
 
 
921
    ipmi_lock(sensors->idx_lock);
 
922
    if (sensor != sensors->sensors_by_idx[sensor->lun][sensor->num])
 
923
        return EINVAL;
 
924
 
 
925
    _ipmi_sensor_get(sensor);
 
926
 
 
927
    if (sensor->source_array)
 
928
        sensor->source_array[sensor->source_idx] = NULL;
 
929
 
 
930
    sensors->sensor_count--;
 
931
    sensors->sensors_by_idx[sensor->lun][sensor->num] = NULL;
 
932
    ipmi_unlock(sensors->idx_lock);
 
933
 
 
934
    sensor->destroyed = 1;
 
935
    _ipmi_sensor_put(sensor);
 
936
    return 0;
 
937
}
 
938
 
 
939
int
 
940
ipmi_sensors_destroy(ipmi_sensor_info_t *sensors)
 
941
{
 
942
    int i, j;
 
943
 
 
944
    if (sensors->destroyed)
 
945
        return EINVAL;
 
946
 
 
947
    sensors->destroyed = 1;
 
948
    for (i=0; i<=4; i++) {
 
949
        for (j=0; j<sensors->idx_size[i]; j++) {
 
950
            if (sensors->sensors_by_idx[i][j]) {
 
951
                ipmi_sensor_destroy(sensors->sensors_by_idx[i][j]);
 
952
            }
 
953
        }
 
954
        if (sensors->sensors_by_idx[i])
 
955
            ipmi_mem_free(sensors->sensors_by_idx[i]);
 
956
    }
 
957
    if (sensors->sensor_wait_q)
 
958
        opq_destroy(sensors->sensor_wait_q);
 
959
    if (sensors->idx_lock)
 
960
        ipmi_destroy_lock(sensors->idx_lock);
 
961
    ipmi_mem_free(sensors);
 
962
    return 0;
 
963
}
 
964
 
 
965
static void
 
966
sensor_set_name(ipmi_sensor_t *sensor)
 
967
{
 
968
    int length;
 
969
 
 
970
    length = ipmi_entity_get_name(sensor->entity, sensor->name,
 
971
                                  sizeof(sensor->name)-2);
 
972
    sensor->name[length] = '.';
 
973
    length++;
 
974
    length += snprintf(sensor->name+length, IPMI_SENSOR_NAME_LEN-length-2,
 
975
                       "%s", sensor->id);
 
976
    sensor->name[length] = ' ';
 
977
    length++;
 
978
    sensor->name[length] = '\0';
 
979
    length++;
 
980
}
 
981
 
 
982
char *
 
983
_ipmi_sensor_name(ipmi_sensor_t *sensor)
 
984
{
 
985
    return sensor->name;
 
986
}
 
987
 
 
988
int
 
989
ipmi_sensor_get_name(ipmi_sensor_t *sensor, char *name, int length)
 
990
{
 
991
    int  slen;
 
992
 
 
993
    if (length <= 0)
 
994
        return 0;
 
995
 
 
996
    /* Never changes, no lock needed. */
 
997
    slen = strlen(sensor->name);
 
998
    if (slen == 0) {
 
999
        if (name)
 
1000
            *name = '\0';
 
1001
        goto out;
 
1002
    }
 
1003
 
 
1004
    slen -= 1; /* Remove the trailing ' ' */
 
1005
    if (slen >= length)
 
1006
        slen = length - 1;
 
1007
 
 
1008
    if (name) {
 
1009
        memcpy(name, sensor->name, slen);
 
1010
        name[slen] = '\0';
 
1011
    }
 
1012
 out:
 
1013
    return slen;
 
1014
}
 
1015
 
 
1016
/***********************************************************************
 
1017
 *
 
1018
 * Sensor SDR handling
 
1019
 *
 
1020
 **********************************************************************/
 
1021
 
 
1022
static int
 
1023
get_sensors_from_sdrs(ipmi_domain_t      *domain,
 
1024
                      ipmi_mc_t          *source_mc,
 
1025
                      ipmi_sdr_info_t    *sdrs,
 
1026
                      ipmi_sensor_t      ***sensors,
 
1027
                      unsigned int       *sensor_count)
 
1028
{
 
1029
    ipmi_sdr_t    sdr;
 
1030
    unsigned int  count;
 
1031
    ipmi_sensor_t **s = NULL;
 
1032
    unsigned int  p, s_size = 0;
 
1033
    int           val;
 
1034
    int           rv;
 
1035
    int           i, j;
 
1036
    int           share_count;
 
1037
    int           id_string_mod_type;
 
1038
    int           entity_instance_incr;
 
1039
    int           id_string_modifier_offset;
 
1040
    unsigned char *str;
 
1041
 
 
1042
    
 
1043
 
 
1044
    rv = ipmi_get_sdr_count(sdrs, &count);
 
1045
    if (rv)
 
1046
        goto out_err;
 
1047
 
 
1048
    /* Get a real count on the number of sensors, since a single SDR can
 
1049
       contain multiple sensors. */
 
1050
    p = 0;
 
1051
    for (i=0; i<count; i++) {
 
1052
        int incr;
 
1053
        int lun;
 
1054
 
 
1055
        rv = ipmi_get_sdr_by_index(sdrs, i, &sdr);
 
1056
        if (rv)
 
1057
            goto out_err;
 
1058
 
 
1059
        lun = sdr.data[1] & 0x03;
 
1060
        if (sdr.type == 1) {
 
1061
            incr = 1;
 
1062
        } else if (sdr.type == 2) {
 
1063
            if (sdr.data[18] & 0x0f)
 
1064
                incr = sdr.data[18] & 0x0f;
 
1065
            else
 
1066
                incr = 1;
 
1067
        } else if (sdr.type == 3) {
 
1068
            if (sdr.data[7] & 0x0f)
 
1069
                incr = sdr.data[7] & 0x0f;
 
1070
            else
 
1071
                incr = 1;
 
1072
        } else
 
1073
            continue;
 
1074
 
 
1075
        p += incr;
 
1076
    }
 
1077
 
 
1078
    /* Setup memory to hold the sensors. */
 
1079
    s = ipmi_mem_alloc(sizeof(*s) * p);
 
1080
    if (!s) {
 
1081
        rv = ENOMEM;
 
1082
        goto out_err;
 
1083
    }
 
1084
    s_size = p;
 
1085
    memset(s, 0, sizeof(*s) * p);
 
1086
 
 
1087
    p = 0;
 
1088
    for (i=0; i<count; i++) {
 
1089
        rv = ipmi_get_sdr_by_index(sdrs, i, &sdr);
 
1090
        if (rv)
 
1091
            goto out_err;
 
1092
 
 
1093
        if ((sdr.type != 1) && (sdr.type != 2) && (sdr.type != 3))
 
1094
            continue;
 
1095
 
 
1096
        s[p] = ipmi_mem_alloc(sizeof(*s[p]));
 
1097
        if (!s[p]) {
 
1098
            rv = ENOMEM;
 
1099
            goto out_err;
 
1100
        }
 
1101
        memset(s[p], 0, sizeof(*s[p]));
 
1102
 
 
1103
        s[p]->source_recid = sdr.record_id;
 
1104
        s[p]->hot_swap_requester = -1;
 
1105
 
 
1106
        s[p]->waitq = opq_alloc(ipmi_domain_get_os_hnd(domain));
 
1107
        if (!s[p]->waitq) {
 
1108
            rv = ENOMEM;
 
1109
            goto out_err;
 
1110
        }
 
1111
 
 
1112
        s[p]->handler_list = locked_list_alloc(ipmi_domain_get_os_hnd(domain));
 
1113
        if (! s[p]->handler_list) {
 
1114
            opq_destroy(s[p]->waitq);
 
1115
            rv = ENOMEM;
 
1116
            goto out_err;
 
1117
        }
 
1118
 
 
1119
        s[p]->destroyed = 0;
 
1120
        s[p]->destroy_handler = NULL;
 
1121
 
 
1122
        rv = _ipmi_find_or_create_mc_by_slave_addr(domain,
 
1123
                                                   sdr.data[1] >> 4,
 
1124
                                                   sdr.data[0],
 
1125
                                                   &(s[p]->mc));
 
1126
        if (rv)
 
1127
            goto out_err;
 
1128
 
 
1129
        share_count = 0;
 
1130
        id_string_mod_type = 0;
 
1131
        entity_instance_incr = 0;
 
1132
        id_string_modifier_offset = 0;
 
1133
 
 
1134
        s[p]->usecount = 1;
 
1135
        s[p]->domain = domain;
 
1136
        s[p]->source_mc = source_mc;
 
1137
        s[p]->source_idx = p;
 
1138
        s[p]->source_array = s;
 
1139
        s[p]->owner = sdr.data[0];
 
1140
        s[p]->channel = sdr.data[1] >> 4;
 
1141
        s[p]->lun = sdr.data[1] & 0x03;
 
1142
        s[p]->send_lun = s[p]->lun;
 
1143
        s[p]->num = sdr.data[2];
 
1144
        s[p]->entity_id = sdr.data[3];
 
1145
        s[p]->entity_instance_logical = sdr.data[4] >> 7;
 
1146
        s[p]->entity_instance = sdr.data[4] & 0x7f;
 
1147
        if ((sdr.type == 1) || (sdr.type == 2)) {
 
1148
            s[p]->sensor_init_scanning = (sdr.data[5] >> 6) & 1;
 
1149
            s[p]->sensor_init_events = (sdr.data[5] >> 5) & 1;
 
1150
            s[p]->sensor_init_thresholds = (sdr.data[5] >> 4) & 1;
 
1151
            s[p]->sensor_init_hysteresis = (sdr.data[5] >> 3) & 1;
 
1152
            s[p]->sensor_init_type = (sdr.data[5] >> 2) & 1;
 
1153
            s[p]->sensor_init_pu_events = (sdr.data[5] >> 1) & 1;
 
1154
            s[p]->sensor_init_pu_scanning = (sdr.data[5] >> 0) & 1;
 
1155
            s[p]->ignore_if_no_entity = (sdr.data[6] >> 7) & 1;
 
1156
            s[p]->supports_auto_rearm = (sdr.data[6] >> 6) & 1 ;
 
1157
            s[p]->hysteresis_support = (sdr.data[6] >> 4) & 3;
 
1158
            s[p]->threshold_access = (sdr.data[6] >> 2) & 3;
 
1159
            s[p]->event_support = sdr.data[6] & 3;
 
1160
            s[p]->sensor_type = sdr.data[7];
 
1161
            s[p]->event_reading_type = sdr.data[8];
 
1162
 
 
1163
            val = ipmi_get_uint16(sdr.data+9);
 
1164
            for (j=0; j<16; j++) {
 
1165
                s[p]->mask1[j] = val & 1;
 
1166
                val >>= 1;
 
1167
            }
 
1168
            val = ipmi_get_uint16(sdr.data+11);
 
1169
            for (j=0; j<16; j++) {
 
1170
                s[p]->mask2[j] = val & 1;
 
1171
                val >>= 1;
 
1172
            }
 
1173
            val = ipmi_get_uint16(sdr.data+13);
 
1174
            for (j=0; j<16; j++) {
 
1175
                s[p]->mask3[j] = val & 1;
 
1176
                val >>= 1;
 
1177
            }
 
1178
 
 
1179
            s[p]->analog_data_format = (sdr.data[15] >> 6) & 3;
 
1180
            s[p]->rate_unit = (sdr.data[15] >> 3) & 7;
 
1181
            s[p]->modifier_unit_use = (sdr.data[15] >> 1) & 3;
 
1182
            s[p]->percentage = sdr.data[15] & 1;
 
1183
            s[p]->base_unit = sdr.data[16];
 
1184
            s[p]->modifier_unit = sdr.data[17];
 
1185
        }
 
1186
 
 
1187
        if (sdr.type == 1) {
 
1188
            /* A full sensor record. */
 
1189
            s[p]->linearization = sdr.data[18] & 0x7f;
 
1190
 
 
1191
            if (s[p]->linearization <= 11) {
 
1192
                for (j=0; j<256; j++) {
 
1193
                    s[p]->conv[j].m = sdr.data[19] | ((sdr.data[20] & 0xc0) << 2);
 
1194
                    s[p]->conv[j].tolerance = sdr.data[20] & 0x3f;
 
1195
                    s[p]->conv[j].b = sdr.data[21] | ((sdr.data[22] & 0xc0) << 2);
 
1196
                    s[p]->conv[j].accuracy = ((sdr.data[22] & 0x3f)
 
1197
                                             | ((sdr.data[23] & 0xf0) << 2));
 
1198
                    s[p]->conv[j].accuracy_exp = (sdr.data[23] >> 2) & 0x3;
 
1199
                    s[p]->conv[j].r_exp = (sdr.data[24] >> 4) & 0xf;
 
1200
                    s[p]->conv[j].b_exp = sdr.data[24] & 0xf;
 
1201
                }
 
1202
            }
 
1203
 
 
1204
            s[p]->sensor_direction = sdr.data[23] & 0x3;
 
1205
            s[p]->normal_min_specified = (sdr.data[25] >> 2) & 1;
 
1206
            s[p]->normal_max_specified = (sdr.data[25] >> 1) & 1;
 
1207
            s[p]->nominal_reading_specified = sdr.data[25] & 1;
 
1208
            s[p]->nominal_reading = sdr.data[26];
 
1209
            s[p]->normal_max = sdr.data[27];
 
1210
            s[p]->normal_min = sdr.data[28];
 
1211
            s[p]->sensor_max = sdr.data[29];
 
1212
            s[p]->sensor_min = sdr.data[30];
 
1213
            s[p]->default_thresholds[IPMI_UPPER_NON_RECOVERABLE]= sdr.data[31];
 
1214
            s[p]->default_thresholds[IPMI_UPPER_CRITICAL] = sdr.data[32];
 
1215
            s[p]->default_thresholds[IPMI_UPPER_NON_CRITICAL] = sdr.data[33];
 
1216
            s[p]->default_thresholds[IPMI_LOWER_NON_RECOVERABLE] = sdr.data[34];
 
1217
            s[p]->default_thresholds[IPMI_LOWER_CRITICAL] = sdr.data[35];
 
1218
            s[p]->default_thresholds[IPMI_LOWER_NON_CRITICAL] = sdr.data[36];
 
1219
            s[p]->positive_going_threshold_hysteresis = sdr.data[37];
 
1220
            s[p]->negative_going_threshold_hysteresis = sdr.data[38];
 
1221
            s[p]->oem1 = sdr.data[41];
 
1222
 
 
1223
            str = sdr.data + 42;
 
1224
            s[p]->id_len = ipmi_get_device_string(&str, sdr.length-42,
 
1225
                                                  s[p]->id, IPMI_STR_SDR_SEMANTICS, 0,
 
1226
                                                  &s[p]->id_type, SENSOR_ID_LEN);
 
1227
            if (s[p]->entity)
 
1228
                sensor_set_name(s[p]);
 
1229
        } else if (sdr.type == 2) {
 
1230
            /* FIXME - make sure this is not a threshold sensor.  The
 
1231
               question is, what do I do if it is? */
 
1232
            /* A short sensor record. */
 
1233
 
 
1234
            s[p]->sensor_direction = (sdr.data[18] >> 6) & 0x3;
 
1235
 
 
1236
            s[p]->positive_going_threshold_hysteresis = sdr.data[20];
 
1237
            s[p]->negative_going_threshold_hysteresis = sdr.data[21];
 
1238
            s[p]->oem1 = sdr.data[25];
 
1239
 
 
1240
            str = sdr.data + 26;
 
1241
            s[p]->id_len = ipmi_get_device_string(&str, sdr.length-26,
 
1242
                                                  s[p]->id, IPMI_STR_SDR_SEMANTICS, 0,
 
1243
                                                  &s[p]->id_type, SENSOR_ID_LEN);
 
1244
 
 
1245
            share_count = sdr.data[18] & 0x0f;
 
1246
            if (share_count == 0)
 
1247
                share_count = 1;
 
1248
            id_string_mod_type = (sdr.data[18] >> 4) & 0x3;
 
1249
            entity_instance_incr = (sdr.data[19] >> 7) & 0x01;
 
1250
            id_string_modifier_offset = sdr.data[19] & 0x7f;
 
1251
        } else {
 
1252
            /* Event-only sensor */
 
1253
 
 
1254
            s[p]->sensor_type = sdr.data[5];
 
1255
            s[p]->event_reading_type = sdr.data[6];
 
1256
            s[p]->oem1 = sdr.data[10];
 
1257
 
 
1258
            str = sdr.data + 11;
 
1259
            s[p]->id_len = ipmi_get_device_string(&str, sdr.length-11,
 
1260
                                                  s[p]->id, IPMI_STR_SDR_SEMANTICS, 0,
 
1261
                                                  &s[p]->id_type, SENSOR_ID_LEN);
 
1262
 
 
1263
            share_count = sdr.data[7] & 0x0f;
 
1264
            if (share_count == 0)
 
1265
                share_count = 1;
 
1266
            id_string_mod_type = (sdr.data[7] >> 4) & 0x3;
 
1267
            entity_instance_incr = (sdr.data[8] >> 7) & 0x01;
 
1268
            id_string_modifier_offset = sdr.data[8] & 0x7f;
 
1269
        }
 
1270
 
 
1271
        if (share_count) {
 
1272
            /* Duplicate the sensor records for each instance.  Go
 
1273
               backwards to avoid destroying the first one until we
 
1274
               finish the others. */
 
1275
            for (j=share_count-1; j>=0; j--) {
 
1276
                int len;
 
1277
 
 
1278
                if (j != 0) {
 
1279
                    /* The first one is already allocated, we are
 
1280
                       using it to copy to the other ones, so this is
 
1281
                       not necessary.  We still have to iterate the
 
1282
                       first one to set its string name, though. */
 
1283
                    s[p+j] = ipmi_mem_alloc(sizeof(ipmi_sensor_t));
 
1284
                    if (!s[p+j]) {
 
1285
                        rv = ENOMEM;
 
1286
                        goto out_err;
 
1287
                    }
 
1288
                    memcpy(s[p+j], s[p], sizeof(ipmi_sensor_t));
 
1289
                    
 
1290
                    /* In case of error */
 
1291
                    s[p+j]->handler_list = NULL;
 
1292
 
 
1293
                    /* For every sensor except the first, increment the usage
 
1294
                       count for the MC so that it will decrement properly.
 
1295
                       This cannot fail because we have already gotten it
 
1296
                       before. */
 
1297
                    _ipmi_find_or_create_mc_by_slave_addr(domain,
 
1298
                                                          s[p+j]->channel,
 
1299
                                                          s[p+j]->owner,
 
1300
                                                          &(s[p+j]->mc));
 
1301
 
 
1302
                    s[p+j]->waitq = opq_alloc(ipmi_domain_get_os_hnd(domain));
 
1303
                    if (!s[p+j]->waitq) {
 
1304
                        rv = ENOMEM;
 
1305
                        goto out_err;
 
1306
                    }
 
1307
 
 
1308
                    s[p+j]->handler_list
 
1309
                        = locked_list_alloc(ipmi_domain_get_os_hnd(domain));
 
1310
                    if (! s[p+j]->handler_list) {
 
1311
                        rv = ENOMEM;
 
1312
                        goto out_err;
 
1313
                    }
 
1314
 
 
1315
                    s[p+j]->num += j;
 
1316
 
 
1317
                    if (entity_instance_incr & 0x80) {
 
1318
                        s[p+j]->entity_instance += j;
 
1319
                    }
 
1320
 
 
1321
                    s[p+j]->source_idx += j;
 
1322
                }
 
1323
 
 
1324
                val = id_string_modifier_offset + j;
 
1325
                len = s[p+j]->id_len;
 
1326
                switch (id_string_mod_type) {
 
1327
                    case 0: /* Numeric */
 
1328
                        if ((val / 10) > 0) {
 
1329
                            if (len < SENSOR_ID_LEN) {
 
1330
                                s[p+j]->id[len] = (val/10) + '0';
 
1331
                                len++;
 
1332
                            }
 
1333
                        }
 
1334
                        if (len < SENSOR_ID_LEN) {
 
1335
                            s[p+j]->id[len] = (val%10) + '0';
 
1336
                            len++;
 
1337
                        }
 
1338
                        break;
 
1339
                    case 1: /* Alpha */
 
1340
                        if ((val / 26) > 0) {
 
1341
                            if (len < SENSOR_ID_LEN) {
 
1342
                                s[p+j]->id[len] = (val/26) + 'A';
 
1343
                                len++;
 
1344
                            }
 
1345
                        }
 
1346
                        if (len < SENSOR_ID_LEN) {
 
1347
                            s[p+j]->id[len] = (val%26) + 'A';
 
1348
                            len++;
 
1349
                        }
 
1350
                        break;
 
1351
                    /* FIXME - unicode handling? */
 
1352
                }
 
1353
                s[p+j]->id_len = len;
 
1354
                if (s[p+j]->entity)
 
1355
                    sensor_set_name(s[p+j]);
 
1356
            }
 
1357
 
 
1358
            p += share_count;
 
1359
        } else
 
1360
            p++;
 
1361
    }
 
1362
 
 
1363
    *sensors = s;
 
1364
    *sensor_count = s_size;
 
1365
    return 0;
 
1366
 
 
1367
 out_err:
 
1368
    if (s) {
 
1369
        for (i=0; i<s_size; i++)
 
1370
            if (s[i]) {
 
1371
                if (s[i]->mc)
 
1372
                    _ipmi_mc_put(s[i]->mc);
 
1373
                if (s[i]->waitq)
 
1374
                    opq_destroy(s[i]->waitq);
 
1375
                if (s[i]->handler_list)
 
1376
                    locked_list_destroy(s[i]->handler_list);
 
1377
                ipmi_mem_free(s[i]);
 
1378
            }
 
1379
        ipmi_mem_free(s);
 
1380
    }
 
1381
    return rv;
 
1382
}
 
1383
 
 
1384
static void
 
1385
handle_new_sensor(ipmi_domain_t *domain,
 
1386
                  ipmi_sensor_t *sensor,
 
1387
                  void          *link)
 
1388
{
 
1389
    ipmi_entity_info_t *ents;
 
1390
 
 
1391
 
 
1392
    /* Call this before the OEM call so the OEM call can replace it. */
 
1393
    sensor->cbs = ipmi_standard_sensor_cb;
 
1394
    sensor->sensor_type_string
 
1395
        = ipmi_get_sensor_type_string(sensor->sensor_type);
 
1396
    sensor->event_reading_type_string
 
1397
        = ipmi_get_event_reading_type_string(sensor->event_reading_type);
 
1398
    sensor->rate_unit_string
 
1399
        = ipmi_get_rate_unit_string(sensor->rate_unit);
 
1400
    sensor->base_unit_string
 
1401
        = ipmi_get_unit_type_string(sensor->base_unit);
 
1402
    sensor->modifier_unit_string
 
1403
        = ipmi_get_unit_type_string(sensor->modifier_unit);
 
1404
 
 
1405
    ents = ipmi_domain_get_entities(domain);
 
1406
 
 
1407
    sensor_set_name(sensor);
 
1408
 
 
1409
    if ((sensor->source_mc)
 
1410
        && (_ipmi_mc_new_sensor(sensor->source_mc, sensor->entity,
 
1411
                                sensor, link)))
 
1412
    {
 
1413
        /* Nothing to do, OEM code handled the sensor. */
 
1414
    } else {
 
1415
        ipmi_entity_add_sensor(sensor->entity, sensor, link);
 
1416
    }
 
1417
 
 
1418
    _call_new_sensor_handlers(domain, sensor);
 
1419
}
 
1420
 
 
1421
static int cmp_sensor(ipmi_sensor_t *s1,
 
1422
                      ipmi_sensor_t *s2)
 
1423
{
 
1424
    int i;
 
1425
 
 
1426
    if (s1->entity_instance_logical != s2->entity_instance_logical) return 0;
 
1427
    if (s1->sensor_init_scanning != s2->sensor_init_scanning) return 0;
 
1428
    if (s1->sensor_init_events != s2->sensor_init_events) return 0;
 
1429
    if (s1->sensor_init_thresholds != s2->sensor_init_thresholds) return 0;
 
1430
    if (s1->sensor_init_hysteresis != s2->sensor_init_hysteresis) return 0;
 
1431
    if (s1->sensor_init_type != s2->sensor_init_type) return 0;
 
1432
    if (s1->sensor_init_pu_events != s2->sensor_init_pu_events) return 0;
 
1433
    if (s1->sensor_init_pu_scanning != s2->sensor_init_pu_scanning) return 0;
 
1434
    if (s1->ignore_if_no_entity != s2->ignore_if_no_entity) return 0;
 
1435
    if (s1->supports_auto_rearm != s2->supports_auto_rearm) return 0;
 
1436
    if (s1->hysteresis_support != s2->hysteresis_support) return 0;
 
1437
    if (s1->threshold_access != s2->threshold_access) return 0;
 
1438
    if (s1->event_support != s2->event_support) return 0;
 
1439
    if (s1->sensor_type != s2->sensor_type) return 0;
 
1440
    if (s1->event_reading_type != s2->event_reading_type) return 0;
 
1441
 
 
1442
    for (i=0; i<16; i++) {
 
1443
        if (s1->mask1[i] != s2->mask1[i]) return 0;
 
1444
        if (s1->mask2[i] != s2->mask2[i]) return 0;
 
1445
        if (s1->mask3[i] != s2->mask3[i]) return 0;
 
1446
    }
 
1447
    
 
1448
    if (s1->analog_data_format != s2->analog_data_format) return 0;
 
1449
    if (s1->rate_unit != s2->rate_unit) return 0;
 
1450
    if (s1->modifier_unit_use != s2->modifier_unit_use) return 0;
 
1451
    if (s1->percentage != s2->percentage) return 0;
 
1452
    if (s1->base_unit != s2->base_unit) return 0;
 
1453
    if (s1->modifier_unit != s2->modifier_unit) return 0;
 
1454
    if (s1->linearization != s2->linearization) return 0;
 
1455
    if (s1->linearization <= 11) {
 
1456
        if (s1->conv[0].m != s2->conv[0].m) return 0;
 
1457
        if (s1->conv[0].tolerance != s2->conv[0].tolerance) return 0;
 
1458
        if (s1->conv[0].b != s2->conv[0].b) return 0;
 
1459
        if (s1->conv[0].accuracy != s2->conv[0].accuracy) return 0;
 
1460
        if (s1->conv[0].accuracy_exp != s2->conv[0].accuracy_exp) return 0;
 
1461
        if (s1->conv[0].r_exp != s2->conv[0].r_exp) return 0;
 
1462
        if (s1->conv[0].b_exp != s2->conv[0].b_exp) return 0;
 
1463
    }
 
1464
    if (s1->normal_min_specified != s2->normal_min_specified) return 0;
 
1465
    if (s1->normal_max_specified != s2->normal_max_specified) return 0;
 
1466
    if (s1->nominal_reading_specified != s2->nominal_reading_specified) return 0;
 
1467
    if (s1->nominal_reading != s2->nominal_reading) return 0;
 
1468
    if (s1->normal_max != s2->normal_max) return 0;
 
1469
    if (s1->normal_min != s2->normal_min) return 0;
 
1470
    if (s1->sensor_max != s2->sensor_max) return 0;
 
1471
    if (s1->sensor_min != s2->sensor_min) return 0;
 
1472
    for (i=0; i<6; i++) {
 
1473
        if (s1->default_thresholds[i] != s2->default_thresholds[i])
 
1474
            return 0;
 
1475
    }
 
1476
    if (s1->positive_going_threshold_hysteresis
 
1477
        != s2->positive_going_threshold_hysteresis)
 
1478
        return 0;
 
1479
    if (s1->negative_going_threshold_hysteresis
 
1480
        != s2->negative_going_threshold_hysteresis)
 
1481
        return 0;
 
1482
    if (s1->oem1 != s2->oem1) return 0;
 
1483
 
 
1484
    if (s1->id_type != s2->id_type) return 0;
 
1485
    if (s1->id_len != s2->id_len) return 0;
 
1486
    if (memcmp(s1->id, s2->id, s1->id_len) != 0) return 0;
 
1487
    
 
1488
    return 1;
 
1489
}
 
1490
 
 
1491
enum entity_list_op { ENT_LIST_OLD, ENT_LIST_NEW, ENT_LIST_DUP };
 
1492
typedef struct entity_list_s
 
1493
{
 
1494
    ipmi_entity_t        *ent;
 
1495
    ipmi_sensor_t        *sensor;
 
1496
    ipmi_sensor_t        *osensor;
 
1497
    ipmi_mc_t            *mc;
 
1498
    enum entity_list_op  op;
 
1499
    struct entity_list_s *next;
 
1500
} entity_list_t;
 
1501
 
 
1502
/* Assume it has enough space for one pointer. */
 
1503
struct locked_list_entry_s
 
1504
{
 
1505
    locked_list_entry_t *next;
 
1506
};
 
1507
 
 
1508
int
 
1509
ipmi_sensor_handle_sdrs(ipmi_domain_t   *domain,
 
1510
                        ipmi_mc_t       *source_mc,
 
1511
                        ipmi_sdr_info_t *sdrs)
 
1512
{
 
1513
    int                 rv;
 
1514
    int                 i, j;
 
1515
    ipmi_sensor_t       **sdr_sensors;
 
1516
    ipmi_sensor_t       **old_sdr_sensors;
 
1517
    unsigned int        old_count;
 
1518
    unsigned int        count;
 
1519
    ipmi_entity_info_t  *ents;
 
1520
    ipmi_entity_t       *ent;
 
1521
    entity_list_t       *new_sensors = NULL;
 
1522
    entity_list_t       *del_sensors = NULL;
 
1523
    entity_list_t       *ent_item;
 
1524
    entity_list_t       *new_ent_item;
 
1525
    locked_list_entry_t *link, *links = NULL;
 
1526
    ipmi_sensor_t       **sens_tmp;
 
1527
    
 
1528
 
 
1529
    CHECK_DOMAIN_LOCK(domain);
 
1530
    if (source_mc)
 
1531
        CHECK_MC_LOCK(source_mc);
 
1532
 
 
1533
    rv = get_sensors_from_sdrs(domain, source_mc, sdrs, &sdr_sensors, &count);
 
1534
    if (rv)
 
1535
        goto out_err;
 
1536
 
 
1537
    ents = ipmi_domain_get_entities(domain);
 
1538
 
 
1539
    /* Pre-allocate all the links we will need for registering sensors
 
1540
       with the entities, and we make sure all the entities exist. */
 
1541
    for (i=0; i<count; i++) {
 
1542
        ipmi_sensor_t      *nsensor = sdr_sensors[i];
 
1543
 
 
1544
        ent = NULL;
 
1545
 
 
1546
        if (nsensor != NULL) {
 
1547
            ipmi_sensor_info_t *sensors;
 
1548
 
 
1549
            /* Make sure the entity exists for ALL sensors in the
 
1550
               new list.  This way, if a sensor has changed
 
1551
               entities, the new entity will exist. */
 
1552
            rv = ipmi_entity_add(ents,
 
1553
                                 domain,
 
1554
                                 ipmi_mc_get_channel(nsensor->mc),
 
1555
                                 ipmi_mc_get_address(nsensor->mc),
 
1556
                                 i,
 
1557
                                 nsensor->entity_id,
 
1558
                                 nsensor->entity_instance,
 
1559
                                 "",
 
1560
                                 IPMI_ASCII_STR,
 
1561
                                 0,
 
1562
                                 NULL,
 
1563
                                 NULL,
 
1564
                                 &ent);
 
1565
            if (rv)
 
1566
                goto out_err_free;
 
1567
 
 
1568
            nsensor->entity = ent;
 
1569
 
 
1570
            sensors = _ipmi_mc_get_sensors(nsensor->mc);
 
1571
 
 
1572
            ipmi_lock(sensors->idx_lock);
 
1573
            if (nsensor->num >= sensors->idx_size[nsensor->lun]) {
 
1574
                /* There's not enough room in the sensor repository
 
1575
                   for the new item, so expand the array. */
 
1576
                ipmi_sensor_t **new_by_idx;
 
1577
                unsigned int  new_size = nsensor->num+10;
 
1578
                new_by_idx = ipmi_mem_alloc(sizeof(ipmi_sensor_t *) * new_size);
 
1579
                if (!new_by_idx) {
 
1580
                    ipmi_unlock(sensors->idx_lock);
 
1581
                    rv = ENOMEM;
 
1582
                    _ipmi_entity_put(ent);
 
1583
                    goto out_err_free;
 
1584
                }
 
1585
                if (sensors->sensors_by_idx[nsensor->lun]) {
 
1586
                    memcpy(new_by_idx,
 
1587
                           sensors->sensors_by_idx[nsensor->lun],
 
1588
                           (sensors->idx_size[nsensor->lun]
 
1589
                            * sizeof(ipmi_sensor_t *)));
 
1590
                    ipmi_mem_free(sensors->sensors_by_idx[nsensor->lun]);
 
1591
                }
 
1592
                for (j=sensors->idx_size[nsensor->lun]; j<new_size; j++)
 
1593
                    new_by_idx[j] = NULL;
 
1594
                sensors->sensors_by_idx[nsensor->lun] = new_by_idx;
 
1595
                sensors->idx_size[nsensor->lun] = new_size;
 
1596
            }
 
1597
            ipmi_unlock(sensors->idx_lock);
 
1598
 
 
1599
            /* Keep track of each entity/sensor pair. */
 
1600
            new_ent_item = ipmi_mem_alloc(sizeof(*new_ent_item));
 
1601
            if (!new_ent_item) {
 
1602
                _ipmi_entity_put(ent);
 
1603
                goto out_err_free;
 
1604
            }
 
1605
            new_ent_item->ent = ent;
 
1606
            new_ent_item->sensor = nsensor;
 
1607
            new_ent_item->osensor = NULL;
 
1608
            new_ent_item->mc = nsensor->mc;
 
1609
            new_ent_item->op = ENT_LIST_OLD;
 
1610
            new_ent_item->next = new_sensors;
 
1611
            new_sensors = new_ent_item;
 
1612
 
 
1613
            /* Pre-allocate link entries for putting the sensor into
 
1614
               the entity. */
 
1615
            link = locked_list_alloc_entry();
 
1616
            if (!link)
 
1617
                goto out_err_free;
 
1618
            link->next = links;
 
1619
            links = link;
 
1620
        }
 
1621
    }
 
1622
 
 
1623
    /* Check for duplicate sensor numbers in the new sensor set. */
 
1624
    sens_tmp = ipmi_mem_alloc(256 * sizeof(ipmi_sensor_t **));
 
1625
    if (!sens_tmp) {
 
1626
        rv = ENOMEM;
 
1627
        goto out_err_free;
 
1628
    }
 
1629
    memset(sens_tmp, 0, 256 * sizeof(ipmi_sensor_t **));
 
1630
    ent_item = new_sensors;
 
1631
    while (ent_item) {
 
1632
        ipmi_sensor_t *nsensor = ent_item->sensor;
 
1633
        ipmi_sensor_t *csensor;
 
1634
 
 
1635
        if ((!ent_item->ent) || (!nsensor)) {
 
1636
            ent_item = ent_item->next;
 
1637
            continue;
 
1638
        }
 
1639
 
 
1640
        csensor = sens_tmp[nsensor->num];
 
1641
        while (csensor) {
 
1642
            if ((csensor->lun == nsensor->lun)
 
1643
                && (csensor->num == nsensor->num)
 
1644
                && (csensor->mc == nsensor->mc))
 
1645
            {
 
1646
                break;
 
1647
            }
 
1648
            csensor = csensor->tlink;
 
1649
        }
 
1650
        if (csensor) {
 
1651
            ipmi_log(IPMI_LOG_WARNING,
 
1652
                     "%ssensor.c(ipmi_sensor_handle_sdrs):"
 
1653
                     " SDR record %d has the same sensor number as record"
 
1654
                     " %d in the repository.  Ignoring second sensor."
 
1655
                     " Fix your SDRs!",
 
1656
                     SENSOR_NAME(nsensor),
 
1657
                     csensor->source_recid,
 
1658
                     nsensor->source_recid);
 
1659
            ent_item->op = ENT_LIST_DUP;
 
1660
            ent_item->osensor = NULL;
 
1661
        } else {
 
1662
            nsensor->tlink = sens_tmp[nsensor->num];
 
1663
            sens_tmp[nsensor->num] = nsensor;
 
1664
        }
 
1665
        ent_item = ent_item->next;
 
1666
    }
 
1667
    ipmi_mem_free(sens_tmp);
 
1668
 
 
1669
    _ipmi_domain_entity_lock(domain);
 
1670
 
 
1671
    _ipmi_get_sdr_sensors(domain, source_mc,
 
1672
                          &old_sdr_sensors, &old_count);
 
1673
 
 
1674
    ent_item = new_sensors;
 
1675
    while (ent_item) {
 
1676
        ipmi_sensor_t      *nsensor = ent_item->sensor;
 
1677
        ipmi_sensor_info_t *sensors;
 
1678
 
 
1679
        if ((!ent_item->ent) || (!nsensor) || (ent_item->op == ENT_LIST_DUP)) {
 
1680
            ent_item = ent_item->next;
 
1681
            continue;
 
1682
        }
 
1683
 
 
1684
        sensors = _ipmi_mc_get_sensors(nsensor->mc);
 
1685
        ipmi_lock(sensors->idx_lock);
 
1686
        if (sensors->sensors_by_idx[nsensor->lun]
 
1687
            && (nsensor->num < sensors->idx_size[nsensor->lun])
 
1688
            && sensors->sensors_by_idx[nsensor->lun][nsensor->num])
 
1689
        {
 
1690
            /* A sensor is already there. */
 
1691
            ipmi_sensor_t *osensor
 
1692
                = sensors->sensors_by_idx[nsensor->lun][nsensor->num];
 
1693
 
 
1694
            if (cmp_sensor(nsensor, osensor)) {
 
1695
                /* Since the data is the same, there is no need to get
 
1696
                   the old sensor entity or mc, since they are already
 
1697
                   gotten by the new sensor. */
 
1698
                ent_item->op = ENT_LIST_DUP;
 
1699
                ent_item->osensor = osensor;
 
1700
            } else {
 
1701
                /* We have to delete the old sensor. */
 
1702
                new_ent_item = ipmi_mem_alloc(sizeof(*new_ent_item));
 
1703
                if (!new_ent_item) {
 
1704
                    ipmi_unlock(sensors->idx_lock);
 
1705
                    rv = ENOMEM;
 
1706
                    goto out_err_free_unlock;
 
1707
                }
 
1708
                /* It's possible this can fail, but that means that
 
1709
                   the MC is currently being destroyed.  No big deal,
 
1710
                   just ignore it. */
 
1711
                new_ent_item->mc = NULL;
 
1712
                _ipmi_find_or_create_mc_by_slave_addr(domain,
 
1713
                                                      osensor->channel,
 
1714
                                                      osensor->owner,
 
1715
                                                      &new_ent_item->mc);
 
1716
                _ipmi_entity_get(osensor->entity);
 
1717
                _ipmi_sensor_get(osensor);
 
1718
                new_ent_item->ent = osensor->entity;
 
1719
                new_ent_item->sensor = osensor;
 
1720
                new_ent_item->next = del_sensors;
 
1721
                del_sensors = new_ent_item;
 
1722
                ent_item->op = ENT_LIST_NEW;
 
1723
            }
 
1724
        } else {
 
1725
            ent_item->op = ENT_LIST_NEW;
 
1726
        }
 
1727
        ipmi_unlock(sensors->idx_lock);
 
1728
 
 
1729
        ent_item = ent_item->next;
 
1730
    }
 
1731
 
 
1732
    _ipmi_domain_entity_unlock(domain);
 
1733
 
 
1734
    /* After this point, the operation cannot fail.  Nothing above
 
1735
       this actually changes anything, it just gets it ready.  Now we
 
1736
       put into place all the changes. */
 
1737
 
 
1738
    /* First delete the sensors that we are replacing. */
 
1739
    ent_item = del_sensors;
 
1740
    while (ent_item) {
 
1741
        ipmi_sensor_t *osensor = ent_item->sensor;
 
1742
 
 
1743
        if (osensor->source_array) {
 
1744
            osensor->source_array[osensor->source_idx] = NULL;
 
1745
            osensor->source_array = NULL;
 
1746
        }
 
1747
        /* Note that the actual destroy is deferred until we put the
 
1748
           sensor. */
 
1749
        ipmi_sensor_destroy(osensor);
 
1750
 
 
1751
        ent_item = ent_item->next;
 
1752
    }
 
1753
 
 
1754
    ent_item = new_sensors;
 
1755
    while (ent_item) {
 
1756
        ipmi_sensor_t      *nsensor = ent_item->sensor;
 
1757
        ipmi_sensor_t      *osensor = ent_item->osensor;
 
1758
        ipmi_sensor_info_t *sensors;
 
1759
 
 
1760
        if ((!ent_item->ent) || (!nsensor)) {
 
1761
            ent_item = ent_item->next;
 
1762
            continue;
 
1763
        }
 
1764
 
 
1765
        sensors = _ipmi_mc_get_sensors(nsensor->mc);
 
1766
        ipmi_lock(sensors->idx_lock);
 
1767
        switch (ent_item->op) {
 
1768
        case ENT_LIST_NEW:
 
1769
            sensors->sensors_by_idx[nsensor->lun][nsensor->num] = nsensor;
 
1770
            sensors->sensor_count++;
 
1771
            link = links;
 
1772
            links = link->next;
 
1773
            handle_new_sensor(domain, nsensor, link);
 
1774
            break;
 
1775
 
 
1776
        case ENT_LIST_OLD:
 
1777
            break;
 
1778
 
 
1779
        case ENT_LIST_DUP:
 
1780
            /* They compare, prefer to keep the old data. */
 
1781
            i = nsensor->source_idx;
 
1782
            opq_destroy(nsensor->waitq);
 
1783
            locked_list_destroy(nsensor->handler_list);
 
1784
            ipmi_mem_free(nsensor);
 
1785
            ent_item->sensor = NULL;
 
1786
            sdr_sensors[i] = osensor;
 
1787
            if (osensor) {
 
1788
                if (osensor->source_array)
 
1789
                    osensor->source_array[osensor->source_idx] = NULL;
 
1790
                osensor->source_idx = i;
 
1791
                osensor->source_array = sdr_sensors;
 
1792
            }
 
1793
            break;
 
1794
        }
 
1795
        ipmi_unlock(sensors->idx_lock);
 
1796
        ent_item = ent_item->next;
 
1797
    }
 
1798
 
 
1799
    _ipmi_set_sdr_sensors(domain, source_mc, sdr_sensors, count);
 
1800
 
 
1801
    if (old_sdr_sensors) {
 
1802
        for (i=0; i<old_count; i++) {
 
1803
            ipmi_sensor_t *osensor = old_sdr_sensors[i];
 
1804
            if (osensor != NULL) {
 
1805
                /* This sensor was not in the new repository, so it must
 
1806
                   have been deleted. */
 
1807
                _ipmi_sensor_get(osensor);
 
1808
                ipmi_sensor_destroy(osensor);
 
1809
            }
 
1810
        }
 
1811
    }
 
1812
 
 
1813
    if (old_sdr_sensors) {
 
1814
        for (i=0; i<old_count; i++) {
 
1815
            ipmi_sensor_t *osensor = old_sdr_sensors[i];
 
1816
            if (osensor != NULL) {
 
1817
                _ipmi_sensor_put(osensor);
 
1818
            }
 
1819
        }
 
1820
        ipmi_mem_free(old_sdr_sensors);
 
1821
    }
 
1822
 
 
1823
    /* Free up all the deleted sensors. */
 
1824
    while (del_sensors) {
 
1825
        ent_item = del_sensors;
 
1826
        del_sensors = del_sensors->next;
 
1827
        if (ent_item->sensor)
 
1828
            _ipmi_sensor_put(ent_item->sensor);
 
1829
        if (ent_item->ent)
 
1830
            _ipmi_entity_put(ent_item->ent);
 
1831
        if (ent_item->mc)
 
1832
            _ipmi_mc_put(ent_item->mc);
 
1833
        ipmi_mem_free(ent_item);
 
1834
    }
 
1835
 
 
1836
    /* Report then free up all the new sensors. */
 
1837
    while (new_sensors) {
 
1838
        ent_item = new_sensors;
 
1839
        new_sensors = new_sensors->next;
 
1840
 
 
1841
        if (ent_item->ent && ent_item->sensor)
 
1842
            ent_item->sensor->add_pending = 1;
 
1843
        if (ent_item->sensor)
 
1844
            _ipmi_sensor_put(ent_item->sensor);
 
1845
        if (ent_item->ent)
 
1846
            _ipmi_entity_put(ent_item->ent);
 
1847
        if (ent_item->mc)
 
1848
            _ipmi_mc_put(ent_item->mc);
 
1849
        ipmi_mem_free(ent_item);
 
1850
    }
 
1851
 
 
1852
 out:
 
1853
    /* Cleanup unused links. */
 
1854
    while (links) {
 
1855
        link = links;
 
1856
        links = link->next;
 
1857
        locked_list_free_entry(link);
 
1858
    }
 
1859
 
 
1860
    return rv;
 
1861
 
 
1862
 out_err:
 
1863
    /* Release all the entities, sensors, etc. */
 
1864
    while (del_sensors) {
 
1865
        ent_item = del_sensors;
 
1866
        del_sensors = del_sensors->next;
 
1867
        if (ent_item->sensor)
 
1868
            _ipmi_sensor_put(ent_item->sensor);
 
1869
        if (ent_item->ent)
 
1870
            _ipmi_entity_put(ent_item->ent);
 
1871
        if (ent_item->mc)
 
1872
            _ipmi_mc_put(ent_item->mc);
 
1873
        ipmi_mem_free(ent_item);
 
1874
    }
 
1875
    while (new_sensors) {
 
1876
        ent_item = new_sensors;
 
1877
        new_sensors = new_sensors->next;
 
1878
        if (ent_item->sensor)
 
1879
            _ipmi_sensor_put(ent_item->sensor);
 
1880
        if (ent_item->ent)
 
1881
            _ipmi_entity_put(ent_item->ent);
 
1882
        if (ent_item->mc)
 
1883
            _ipmi_mc_put(ent_item->mc);
 
1884
        ipmi_mem_free(ent_item);
 
1885
    }
 
1886
    goto out;
 
1887
 
 
1888
 out_err_free_unlock:
 
1889
    _ipmi_domain_entity_unlock(domain);
 
1890
 out_err_free:
 
1891
    /* Free up the usecounts on all the MCs we got. */
 
1892
    for (i=0; i<count; i++) {
 
1893
        ipmi_sensor_t *nsensor = sdr_sensors[i];
 
1894
 
 
1895
        if ((nsensor) && (nsensor->mc))
 
1896
            _ipmi_mc_put(nsensor->mc);
 
1897
    }
 
1898
    goto out_err;
 
1899
}
 
1900
                        
 
1901
/***********************************************************************
 
1902
 *
 
1903
 * Get/set various local information about a sensor.
 
1904
 *
 
1905
 **********************************************************************/
 
1906
 
 
1907
int
 
1908
ipmi_sensor_get_nominal_reading(ipmi_sensor_t *sensor,
 
1909
                                double *nominal_reading)
 
1910
{
 
1911
    CHECK_SENSOR_LOCK(sensor);
 
1912
 
 
1913
    if (!sensor->nominal_reading_specified)
 
1914
        return ENOSYS;
 
1915
 
 
1916
    return (ipmi_sensor_convert_from_raw(sensor,
 
1917
                                         sensor->nominal_reading,
 
1918
                                         nominal_reading));
 
1919
}
 
1920
 
 
1921
int
 
1922
ipmi_sensor_get_normal_max(ipmi_sensor_t *sensor, double *normal_max)
 
1923
{
 
1924
    CHECK_SENSOR_LOCK(sensor);
 
1925
 
 
1926
    if (!sensor->normal_max_specified)
 
1927
        return ENOSYS;
 
1928
 
 
1929
    return (ipmi_sensor_convert_from_raw(sensor,
 
1930
                                         sensor->normal_max,
 
1931
                                         normal_max));
 
1932
}
 
1933
 
 
1934
int
 
1935
ipmi_sensor_get_normal_min(ipmi_sensor_t *sensor, double *normal_min)
 
1936
{
 
1937
    CHECK_SENSOR_LOCK(sensor);
 
1938
 
 
1939
    if (!sensor->normal_min_specified)
 
1940
        return ENOSYS;
 
1941
 
 
1942
    return (ipmi_sensor_convert_from_raw(sensor,
 
1943
                                         sensor->normal_min,
 
1944
                                         normal_min));
 
1945
}
 
1946
 
 
1947
int
 
1948
ipmi_sensor_get_sensor_max(ipmi_sensor_t *sensor, double *sensor_max)
 
1949
{
 
1950
    CHECK_SENSOR_LOCK(sensor);
 
1951
 
 
1952
    return (ipmi_sensor_convert_from_raw(sensor,
 
1953
                                         sensor->sensor_max,
 
1954
                                         sensor_max));
 
1955
}
 
1956
 
 
1957
int
 
1958
ipmi_sensor_get_sensor_min(ipmi_sensor_t *sensor, double *sensor_min)
 
1959
{
 
1960
    CHECK_SENSOR_LOCK(sensor);
 
1961
 
 
1962
    return (ipmi_sensor_convert_from_raw(sensor,
 
1963
                                         sensor->sensor_min,
 
1964
                                         sensor_min));
 
1965
}
 
1966
 
 
1967
int ipmi_sensor_set_raw_default_threshold(ipmi_sensor_t *sensor,
 
1968
                                          int           threshold,
 
1969
                                          int           val)
 
1970
{
 
1971
    if ((threshold < 0) || (threshold > 5))
 
1972
        return EINVAL;
 
1973
 
 
1974
    sensor->default_thresholds[threshold] = val;
 
1975
    return 0;
 
1976
}
 
1977
 
 
1978
int ipmi_sensor_get_default_threshold_raw(ipmi_sensor_t *sensor,
 
1979
                                          int           threshold,
 
1980
                                          int           *raw)
 
1981
{
 
1982
    int rv;
 
1983
    int val;
 
1984
 
 
1985
    CHECK_SENSOR_LOCK(sensor);
 
1986
 
 
1987
    if ((threshold < 0) || (threshold > 5))
 
1988
        return EINVAL;
 
1989
 
 
1990
    rv = ipmi_sensor_threshold_settable(sensor, threshold, &val);
 
1991
    if (rv)
 
1992
        return rv;
 
1993
 
 
1994
    if (!val)
 
1995
        return ENOSYS;
 
1996
 
 
1997
    if (!ipmi_sensor_get_sensor_init_thresholds(sensor))
 
1998
        return ENOSYS;
 
1999
 
 
2000
    *raw = sensor->default_thresholds[threshold];
 
2001
    return 0;
 
2002
}
 
2003
 
 
2004
int ipmi_sensor_get_default_threshold_cooked(ipmi_sensor_t *sensor,
 
2005
                                             int           threshold,
 
2006
                                             double        *cooked)
 
2007
{
 
2008
    int rv;
 
2009
    int val;
 
2010
 
 
2011
    CHECK_SENSOR_LOCK(sensor);
 
2012
 
 
2013
    if ((threshold < 0) || (threshold > 5))
 
2014
        return EINVAL;
 
2015
 
 
2016
    rv = ipmi_sensor_threshold_settable(sensor, threshold, &val);
 
2017
    if (rv)
 
2018
        return rv;
 
2019
 
 
2020
    if (!val)
 
2021
        return ENOSYS;
 
2022
 
 
2023
    if (!ipmi_sensor_get_sensor_init_thresholds(sensor))
 
2024
        return ENOSYS;
 
2025
 
 
2026
    return (ipmi_sensor_convert_from_raw(sensor,
 
2027
                                         sensor->default_thresholds[threshold],
 
2028
                                         cooked));
 
2029
}
 
2030
 
 
2031
ipmi_mc_t *
 
2032
ipmi_sensor_get_mc(ipmi_sensor_t *sensor)
 
2033
{
 
2034
    return sensor->mc;
 
2035
}
 
2036
 
 
2037
ipmi_mc_t *
 
2038
ipmi_sensor_get_source_mc(ipmi_sensor_t *sensor)
 
2039
{
 
2040
    CHECK_SENSOR_LOCK(sensor);
 
2041
 
 
2042
    return sensor->source_mc;
 
2043
}
 
2044
 
 
2045
int
 
2046
ipmi_sensor_get_num(ipmi_sensor_t *sensor,
 
2047
                    int           *lun,
 
2048
                    int           *num)
 
2049
{
 
2050
    CHECK_SENSOR_LOCK(sensor);
 
2051
 
 
2052
    if (lun)
 
2053
        *lun = sensor->lun;
 
2054
    if (num)
 
2055
        *num = sensor->num;
 
2056
    return 0;
 
2057
}
 
2058
 
 
2059
int
 
2060
ipmi_sensor_threshold_event_supported(ipmi_sensor_t               *sensor,
 
2061
                                      enum ipmi_thresh_e          event,
 
2062
                                      enum ipmi_event_value_dir_e value_dir,
 
2063
                                      enum ipmi_event_dir_e       dir,
 
2064
                                      int                         *val)
 
2065
{
 
2066
    int idx;
 
2067
    unsigned char *mask;
 
2068
 
 
2069
    CHECK_SENSOR_LOCK(sensor);
 
2070
 
 
2071
    if (sensor->event_reading_type != IPMI_EVENT_READING_TYPE_THRESHOLD)
 
2072
        /* Not a threshold sensor, it doesn't have readings. */
 
2073
        return ENOSYS;
 
2074
    if (sensor->threshold_access == IPMI_THRESHOLD_ACCESS_SUPPORT_NONE) {
 
2075
        /* No thresholds supported. */
 
2076
        *val = 0;
 
2077
        return 0;
 
2078
    }
 
2079
 
 
2080
    if (dir == IPMI_ASSERTION)
 
2081
        mask = sensor->mask1;
 
2082
    else if (dir == IPMI_DEASSERTION)
 
2083
        mask = sensor->mask2;
 
2084
    else
 
2085
        return EINVAL;
 
2086
 
 
2087
    idx = (event * 2) + value_dir;
 
2088
    if (idx > 11)
 
2089
        return EINVAL;
 
2090
 
 
2091
    *val = mask[idx];
 
2092
    return 0;
 
2093
}
 
2094
 
 
2095
void
 
2096
ipmi_sensor_set_threshold_assertion_event_supported(
 
2097
    ipmi_sensor_t               *sensor,
 
2098
    enum ipmi_thresh_e          event,
 
2099
    enum ipmi_event_value_dir_e dir,
 
2100
    int                         val)
 
2101
{
 
2102
    int idx;
 
2103
 
 
2104
    idx = (event * 2) + dir;
 
2105
    if (idx > 11)
 
2106
        return;
 
2107
 
 
2108
    sensor->mask1[idx] = val;
 
2109
}
 
2110
 
 
2111
void
 
2112
ipmi_sensor_set_threshold_deassertion_event_supported(
 
2113
    ipmi_sensor_t               *sensor,
 
2114
    enum ipmi_thresh_e          event,
 
2115
    enum ipmi_event_value_dir_e dir,
 
2116
    int                         val)
 
2117
{
 
2118
    int idx;
 
2119
 
 
2120
    idx = (event * 2) + dir;
 
2121
    if (idx > 11)
 
2122
        return;
 
2123
 
 
2124
    sensor->mask2[idx] = val;
 
2125
}
 
2126
 
 
2127
int
 
2128
ipmi_sensor_threshold_reading_supported(ipmi_sensor_t      *sensor,
 
2129
                                        enum ipmi_thresh_e thresh,
 
2130
                                        int                *val)
 
2131
{
 
2132
    CHECK_SENSOR_LOCK(sensor);
 
2133
 
 
2134
    if (sensor->event_reading_type != IPMI_EVENT_READING_TYPE_THRESHOLD)
 
2135
        /* Not a threshold sensor, it doesn't have readings. */
 
2136
        return ENOSYS;
 
2137
 
 
2138
    switch(thresh) {
 
2139
    case IPMI_LOWER_NON_CRITICAL:
 
2140
        *val = sensor->mask1[12];
 
2141
        break;
 
2142
    case IPMI_LOWER_CRITICAL:
 
2143
        *val = sensor->mask1[13];
 
2144
        break;
 
2145
    case IPMI_LOWER_NON_RECOVERABLE:
 
2146
        *val = sensor->mask1[14];
 
2147
        break;
 
2148
    case IPMI_UPPER_NON_CRITICAL:
 
2149
        *val = sensor->mask2[12];
 
2150
        break;
 
2151
    case IPMI_UPPER_CRITICAL:
 
2152
        *val = sensor->mask2[13];
 
2153
        break;
 
2154
    case IPMI_UPPER_NON_RECOVERABLE:
 
2155
        *val = sensor->mask2[14];
 
2156
        break;
 
2157
    default:
 
2158
        return EINVAL;
 
2159
    }
 
2160
    return 0;
 
2161
}
 
2162
 
 
2163
int
 
2164
ipmi_sensor_threshold_settable(ipmi_sensor_t      *sensor,
 
2165
                               enum ipmi_thresh_e event,
 
2166
                               int                *val)
 
2167
{
 
2168
    CHECK_SENSOR_LOCK(sensor);
 
2169
 
 
2170
    if (sensor->event_reading_type != IPMI_EVENT_READING_TYPE_THRESHOLD)
 
2171
        /* Not a threshold sensor, it doesn't have readings. */
 
2172
        return ENOSYS;
 
2173
    if (sensor->threshold_access != IPMI_THRESHOLD_ACCESS_SUPPORT_SETTABLE) {
 
2174
        /* Threshold setting not supported for any thresholds. */
 
2175
        *val = 0;
 
2176
        return 0;
 
2177
    }
 
2178
 
 
2179
    if (event > IPMI_UPPER_NON_RECOVERABLE)
 
2180
        return EINVAL;
 
2181
 
 
2182
    *val = sensor->mask3[event + 8];
 
2183
    return 0;
 
2184
}
 
2185
 
 
2186
void
 
2187
ipmi_sensor_threshold_set_settable(ipmi_sensor_t      *sensor,
 
2188
                                   enum ipmi_thresh_e event,
 
2189
                                   int                val)
 
2190
{
 
2191
    if (sensor->event_reading_type != IPMI_EVENT_READING_TYPE_THRESHOLD)
 
2192
        /* Not a threshold sensor, it doesn't have readings. */
 
2193
        return;
 
2194
 
 
2195
    if (event > IPMI_UPPER_NON_RECOVERABLE)
 
2196
        return;
 
2197
 
 
2198
    sensor->mask3[event + 8] = val;
 
2199
}
 
2200
 
 
2201
int
 
2202
ipmi_sensor_threshold_readable(ipmi_sensor_t      *sensor,
 
2203
                               enum ipmi_thresh_e event,
 
2204
                               int                *val)
 
2205
{
 
2206
    CHECK_SENSOR_LOCK(sensor);
 
2207
 
 
2208
    if (sensor->event_reading_type != IPMI_EVENT_READING_TYPE_THRESHOLD)
 
2209
        /* Not a threshold sensor, it doesn't have readings. */
 
2210
        return ENOSYS;
 
2211
    if ((sensor->threshold_access == IPMI_THRESHOLD_ACCESS_SUPPORT_NONE)
 
2212
        || (sensor->threshold_access == IPMI_THRESHOLD_ACCESS_SUPPORT_FIXED))
 
2213
    {
 
2214
        /* Threshold reading not supported for any thresholds. */
 
2215
        *val = 0;
 
2216
        return 0;
 
2217
    }
 
2218
 
 
2219
    if (event > IPMI_UPPER_NON_RECOVERABLE)
 
2220
        return EINVAL;
 
2221
 
 
2222
    *val = sensor->mask3[event];
 
2223
    return 0;
 
2224
}
 
2225
 
 
2226
void
 
2227
ipmi_sensor_threshold_set_readable(ipmi_sensor_t      *sensor,
 
2228
                                   enum ipmi_thresh_e event,
 
2229
                                   int                val)
 
2230
{
 
2231
    if (sensor->event_reading_type != IPMI_EVENT_READING_TYPE_THRESHOLD)
 
2232
        /* Not a threshold sensor, it doesn't have readings. */
 
2233
        return;
 
2234
 
 
2235
    if (event > IPMI_UPPER_NON_RECOVERABLE)
 
2236
        return;
 
2237
 
 
2238
    sensor->mask3[event] = val;
 
2239
}
 
2240
 
 
2241
int
 
2242
ipmi_sensor_discrete_event_supported(ipmi_sensor_t         *sensor,
 
2243
                                     int                   event,
 
2244
                                     enum ipmi_event_dir_e dir,
 
2245
                                     int                   *val)
 
2246
{
 
2247
    unsigned char *mask;
 
2248
 
 
2249
    CHECK_SENSOR_LOCK(sensor);
 
2250
 
 
2251
    if (sensor->event_reading_type == IPMI_EVENT_READING_TYPE_THRESHOLD)
 
2252
        /* A threshold sensor, it doesn't have events. */
 
2253
        return ENOSYS;
 
2254
 
 
2255
    if (dir == IPMI_ASSERTION)
 
2256
        mask = sensor->mask1;
 
2257
    else if (dir == IPMI_DEASSERTION)
 
2258
        mask = sensor->mask2;
 
2259
    else
 
2260
        return EINVAL;
 
2261
 
 
2262
    if (event > 14)
 
2263
        return EINVAL;
 
2264
 
 
2265
    *val = mask[event];
 
2266
    return 0;
 
2267
}
 
2268
 
 
2269
void
 
2270
ipmi_sensor_set_discrete_assertion_event_supported(ipmi_sensor_t *sensor,
 
2271
                                                   int           event,
 
2272
                                                   int           val)
 
2273
{
 
2274
    if (event > 14)
 
2275
        return;
 
2276
 
 
2277
    sensor->mask1[event] = val;
 
2278
}
 
2279
 
 
2280
void
 
2281
ipmi_sensor_set_discrete_deassertion_event_supported(ipmi_sensor_t *sensor,
 
2282
                                                     int           event,
 
2283
                                                     int           val)
 
2284
{
 
2285
    if (event > 14)
 
2286
        return;
 
2287
 
 
2288
    sensor->mask2[event] = val;
 
2289
}
 
2290
 
 
2291
int
 
2292
ipmi_sensor_discrete_event_readable(ipmi_sensor_t *sensor,
 
2293
                                    int           event,
 
2294
                                    int           *val)
 
2295
{
 
2296
    CHECK_SENSOR_LOCK(sensor);
 
2297
 
 
2298
    if (sensor->event_reading_type == IPMI_EVENT_READING_TYPE_THRESHOLD)
 
2299
        /* A threshold sensor, it doesn't have events. */
 
2300
        return ENOSYS;
 
2301
 
 
2302
    if (event > 14)
 
2303
        return EINVAL;
 
2304
 
 
2305
    *val = sensor->mask3[event];
 
2306
    return 0;
 
2307
}
 
2308
 
 
2309
void
 
2310
ipmi_sensor_discrete_set_event_readable(ipmi_sensor_t *sensor,
 
2311
                                        int           event,
 
2312
                                        int           val)
 
2313
{
 
2314
    if (sensor->event_reading_type == IPMI_EVENT_READING_TYPE_THRESHOLD)
 
2315
        /* A threshold sensor, it doesn't have events. */
 
2316
        return;
 
2317
 
 
2318
    if (event > 14)
 
2319
        return;
 
2320
 
 
2321
    sensor->mask3[event] = val;
 
2322
}
 
2323
 
 
2324
int
 
2325
ipmi_sensor_get_owner(ipmi_sensor_t *sensor)
 
2326
{
 
2327
    CHECK_SENSOR_LOCK(sensor);
 
2328
 
 
2329
    return sensor->owner;
 
2330
}
 
2331
 
 
2332
int
 
2333
ipmi_sensor_get_channel(ipmi_sensor_t *sensor)
 
2334
{
 
2335
    CHECK_SENSOR_LOCK(sensor);
 
2336
 
 
2337
    return sensor->channel;
 
2338
}
 
2339
 
 
2340
int
 
2341
ipmi_sensor_get_entity_id(ipmi_sensor_t *sensor)
 
2342
{
 
2343
    CHECK_SENSOR_LOCK(sensor);
 
2344
 
 
2345
    return sensor->entity_id;
 
2346
}
 
2347
 
 
2348
int
 
2349
ipmi_sensor_get_entity_instance(ipmi_sensor_t *sensor)
 
2350
{
 
2351
    CHECK_SENSOR_LOCK(sensor);
 
2352
 
 
2353
    return sensor->entity_instance;
 
2354
}
 
2355
 
 
2356
int
 
2357
ipmi_sensor_get_entity_instance_logical(ipmi_sensor_t *sensor)
 
2358
{
 
2359
    CHECK_SENSOR_LOCK(sensor);
 
2360
 
 
2361
    return sensor->entity_instance_logical;
 
2362
}
 
2363
 
 
2364
int
 
2365
ipmi_sensor_get_sensor_init_scanning(ipmi_sensor_t *sensor)
 
2366
{
 
2367
    CHECK_SENSOR_LOCK(sensor);
 
2368
 
 
2369
    return sensor->sensor_init_scanning;
 
2370
}
 
2371
 
 
2372
int
 
2373
ipmi_sensor_get_sensor_init_events(ipmi_sensor_t *sensor)
 
2374
{
 
2375
    CHECK_SENSOR_LOCK(sensor);
 
2376
 
 
2377
    return sensor->sensor_init_events;
 
2378
}
 
2379
 
 
2380
int
 
2381
ipmi_sensor_get_sensor_init_thresholds(ipmi_sensor_t *sensor)
 
2382
{
 
2383
    CHECK_SENSOR_LOCK(sensor);
 
2384
 
 
2385
    return sensor->sensor_init_thresholds;
 
2386
}
 
2387
 
 
2388
int
 
2389
ipmi_sensor_get_sensor_init_hysteresis(ipmi_sensor_t *sensor)
 
2390
{
 
2391
    CHECK_SENSOR_LOCK(sensor);
 
2392
 
 
2393
    return sensor->sensor_init_hysteresis;
 
2394
}
 
2395
 
 
2396
int
 
2397
ipmi_sensor_get_sensor_init_type(ipmi_sensor_t *sensor)
 
2398
{
 
2399
    CHECK_SENSOR_LOCK(sensor);
 
2400
 
 
2401
    return sensor->sensor_init_type;
 
2402
}
 
2403
 
 
2404
int
 
2405
ipmi_sensor_get_sensor_init_pu_events(ipmi_sensor_t *sensor)
 
2406
{
 
2407
    CHECK_SENSOR_LOCK(sensor);
 
2408
 
 
2409
    return sensor->sensor_init_pu_events;
 
2410
}
 
2411
 
 
2412
int
 
2413
ipmi_sensor_get_sensor_init_pu_scanning(ipmi_sensor_t *sensor)
 
2414
{
 
2415
    CHECK_SENSOR_LOCK(sensor);
 
2416
 
 
2417
    return sensor->sensor_init_pu_scanning;
 
2418
}
 
2419
 
 
2420
int
 
2421
ipmi_sensor_get_ignore_if_no_entity(ipmi_sensor_t *sensor)
 
2422
{
 
2423
    CHECK_SENSOR_LOCK(sensor);
 
2424
 
 
2425
    return sensor->ignore_if_no_entity;
 
2426
}
 
2427
 
 
2428
int
 
2429
ipmi_sensor_get_supports_auto_rearm(ipmi_sensor_t *sensor)
 
2430
{
 
2431
    CHECK_SENSOR_LOCK(sensor);
 
2432
 
 
2433
    return sensor->supports_auto_rearm;
 
2434
}
 
2435
 
 
2436
int
 
2437
ipmi_sensor_get_hysteresis_support(ipmi_sensor_t *sensor)
 
2438
{
 
2439
    CHECK_SENSOR_LOCK(sensor);
 
2440
 
 
2441
    return sensor->hysteresis_support;
 
2442
}
 
2443
 
 
2444
int
 
2445
ipmi_sensor_get_threshold_access(ipmi_sensor_t *sensor)
 
2446
{
 
2447
    CHECK_SENSOR_LOCK(sensor);
 
2448
 
 
2449
    return sensor->threshold_access;
 
2450
}
 
2451
 
 
2452
int
 
2453
ipmi_sensor_get_event_support(ipmi_sensor_t *sensor)
 
2454
{
 
2455
    CHECK_SENSOR_LOCK(sensor);
 
2456
 
 
2457
    return sensor->event_support;
 
2458
}
 
2459
 
 
2460
int
 
2461
ipmi_sensor_get_sensor_type(ipmi_sensor_t *sensor)
 
2462
{
 
2463
    CHECK_SENSOR_LOCK(sensor);
 
2464
 
 
2465
    return sensor->sensor_type;
 
2466
}
 
2467
 
 
2468
int
 
2469
ipmi_sensor_get_event_reading_type(ipmi_sensor_t *sensor)
 
2470
{
 
2471
    CHECK_SENSOR_LOCK(sensor);
 
2472
 
 
2473
    return sensor->event_reading_type;
 
2474
}
 
2475
 
 
2476
int
 
2477
ipmi_sensor_get_sensor_direction(ipmi_sensor_t *sensor)
 
2478
{
 
2479
    CHECK_SENSOR_LOCK(sensor);
 
2480
 
 
2481
    return sensor->sensor_direction;
 
2482
}
 
2483
 
 
2484
int
 
2485
ipmi_sensor_get_analog_data_format(ipmi_sensor_t *sensor)
 
2486
{
 
2487
    CHECK_SENSOR_LOCK(sensor);
 
2488
 
 
2489
    return sensor->analog_data_format;
 
2490
}
 
2491
 
 
2492
enum ipmi_rate_unit_e
 
2493
ipmi_sensor_get_rate_unit(ipmi_sensor_t *sensor)
 
2494
{
 
2495
    CHECK_SENSOR_LOCK(sensor);
 
2496
 
 
2497
    return sensor->rate_unit;
 
2498
}
 
2499
 
 
2500
enum ipmi_modifier_unit_use_e
 
2501
ipmi_sensor_get_modifier_unit_use(ipmi_sensor_t *sensor)
 
2502
{
 
2503
    CHECK_SENSOR_LOCK(sensor);
 
2504
 
 
2505
    return sensor->modifier_unit_use;
 
2506
}
 
2507
 
 
2508
int
 
2509
ipmi_sensor_get_percentage(ipmi_sensor_t *sensor)
 
2510
{
 
2511
    CHECK_SENSOR_LOCK(sensor);
 
2512
 
 
2513
    return sensor->percentage;
 
2514
}
 
2515
 
 
2516
enum ipmi_unit_type_e
 
2517
ipmi_sensor_get_base_unit(ipmi_sensor_t *sensor)
 
2518
{
 
2519
    CHECK_SENSOR_LOCK(sensor);
 
2520
 
 
2521
    return sensor->base_unit;
 
2522
}
 
2523
 
 
2524
enum ipmi_unit_type_e
 
2525
ipmi_sensor_get_modifier_unit(ipmi_sensor_t *sensor)
 
2526
{
 
2527
    CHECK_SENSOR_LOCK(sensor);
 
2528
 
 
2529
    return sensor->modifier_unit;
 
2530
}
 
2531
 
 
2532
int
 
2533
ipmi_sensor_get_linearization(ipmi_sensor_t *sensor)
 
2534
{
 
2535
    CHECK_SENSOR_LOCK(sensor);
 
2536
 
 
2537
    return sensor->linearization;
 
2538
}
 
2539
 
 
2540
int
 
2541
ipmi_sensor_get_raw_m(ipmi_sensor_t *sensor, int val)
 
2542
{
 
2543
    CHECK_SENSOR_LOCK(sensor);
 
2544
 
 
2545
    return sensor->conv[val].m;
 
2546
}
 
2547
 
 
2548
int
 
2549
ipmi_sensor_get_raw_tolerance(ipmi_sensor_t *sensor, int val)
 
2550
{
 
2551
    CHECK_SENSOR_LOCK(sensor);
 
2552
 
 
2553
    return sensor->conv[val].tolerance;
 
2554
}
 
2555
 
 
2556
int
 
2557
ipmi_sensor_get_raw_b(ipmi_sensor_t *sensor, int val)
 
2558
{
 
2559
    CHECK_SENSOR_LOCK(sensor);
 
2560
 
 
2561
    return sensor->conv[val].b;
 
2562
}
 
2563
 
 
2564
int
 
2565
ipmi_sensor_get_raw_accuracy(ipmi_sensor_t *sensor, int val)
 
2566
{
 
2567
    CHECK_SENSOR_LOCK(sensor);
 
2568
 
 
2569
    return sensor->conv[val].accuracy;
 
2570
}
 
2571
 
 
2572
int
 
2573
ipmi_sensor_get_raw_accuracy_exp(ipmi_sensor_t *sensor, int val)
 
2574
{
 
2575
    CHECK_SENSOR_LOCK(sensor);
 
2576
 
 
2577
    return sensor->conv[val].accuracy_exp;
 
2578
}
 
2579
 
 
2580
int
 
2581
ipmi_sensor_get_raw_r_exp(ipmi_sensor_t *sensor, int val)
 
2582
{
 
2583
    CHECK_SENSOR_LOCK(sensor);
 
2584
 
 
2585
    return sensor->conv[val].r_exp;
 
2586
}
 
2587
 
 
2588
int
 
2589
ipmi_sensor_get_raw_b_exp(ipmi_sensor_t *sensor, int val)
 
2590
{
 
2591
    CHECK_SENSOR_LOCK(sensor);
 
2592
 
 
2593
    return sensor->conv[val].b_exp;
 
2594
}
 
2595
 
 
2596
int
 
2597
ipmi_sensor_get_normal_min_specified(ipmi_sensor_t *sensor)
 
2598
{
 
2599
    CHECK_SENSOR_LOCK(sensor);
 
2600
 
 
2601
    return sensor->normal_min_specified;
 
2602
}
 
2603
 
 
2604
int
 
2605
ipmi_sensor_get_normal_max_specified(ipmi_sensor_t *sensor)
 
2606
{
 
2607
    CHECK_SENSOR_LOCK(sensor);
 
2608
 
 
2609
    return sensor->normal_max_specified;
 
2610
}
 
2611
 
 
2612
int
 
2613
ipmi_sensor_get_nominal_reading_specified(ipmi_sensor_t *sensor)
 
2614
{
 
2615
    CHECK_SENSOR_LOCK(sensor);
 
2616
 
 
2617
    return sensor->nominal_reading_specified;
 
2618
}
 
2619
 
 
2620
int
 
2621
ipmi_sensor_get_raw_nominal_reading(ipmi_sensor_t *sensor)
 
2622
{
 
2623
    CHECK_SENSOR_LOCK(sensor);
 
2624
 
 
2625
    return sensor->nominal_reading;
 
2626
}
 
2627
 
 
2628
int
 
2629
ipmi_sensor_get_raw_normal_max(ipmi_sensor_t *sensor)
 
2630
{
 
2631
    CHECK_SENSOR_LOCK(sensor);
 
2632
 
 
2633
    return sensor->normal_max;
 
2634
}
 
2635
 
 
2636
int
 
2637
ipmi_sensor_get_raw_normal_min(ipmi_sensor_t *sensor)
 
2638
{
 
2639
    CHECK_SENSOR_LOCK(sensor);
 
2640
 
 
2641
    return sensor->normal_min;
 
2642
}
 
2643
 
 
2644
int
 
2645
ipmi_sensor_get_raw_sensor_max(ipmi_sensor_t *sensor)
 
2646
{
 
2647
    CHECK_SENSOR_LOCK(sensor);
 
2648
 
 
2649
    return sensor->sensor_max;
 
2650
}
 
2651
 
 
2652
int
 
2653
ipmi_sensor_get_raw_sensor_min(ipmi_sensor_t *sensor)
 
2654
{
 
2655
    CHECK_SENSOR_LOCK(sensor);
 
2656
 
 
2657
    return sensor->sensor_min;
 
2658
}
 
2659
 
 
2660
int
 
2661
ipmi_sensor_get_positive_going_threshold_hysteresis(ipmi_sensor_t *sensor)
 
2662
{
 
2663
    CHECK_SENSOR_LOCK(sensor);
 
2664
 
 
2665
    return sensor->positive_going_threshold_hysteresis;
 
2666
}
 
2667
 
 
2668
int
 
2669
ipmi_sensor_get_negative_going_threshold_hysteresis(ipmi_sensor_t *sensor)
 
2670
{
 
2671
    CHECK_SENSOR_LOCK(sensor);
 
2672
 
 
2673
    return sensor->negative_going_threshold_hysteresis;
 
2674
}
 
2675
 
 
2676
int
 
2677
ipmi_sensor_get_oem1(ipmi_sensor_t *sensor)
 
2678
{
 
2679
    CHECK_SENSOR_LOCK(sensor);
 
2680
 
 
2681
    return sensor->oem1;
 
2682
}
 
2683
 
 
2684
int
 
2685
ipmi_sensor_get_id_length(ipmi_sensor_t *sensor)
 
2686
{
 
2687
    CHECK_SENSOR_LOCK(sensor);
 
2688
 
 
2689
    if (sensor->id_type == IPMI_ASCII_STR)
 
2690
        return sensor->id_len+1;
 
2691
    else
 
2692
        return sensor->id_len;
 
2693
}
 
2694
 
 
2695
enum ipmi_str_type_e
 
2696
ipmi_sensor_get_id_type(ipmi_sensor_t *sensor)
 
2697
{
 
2698
    CHECK_SENSOR_LOCK(sensor);
 
2699
 
 
2700
    return sensor->id_type;
 
2701
}
 
2702
 
 
2703
int
 
2704
ipmi_sensor_get_id(ipmi_sensor_t *sensor, char *id, int length)
 
2705
{
 
2706
    int clen;
 
2707
 
 
2708
    CHECK_SENSOR_LOCK(sensor);
 
2709
 
 
2710
    if (sensor->id_len > length)
 
2711
        clen = length;
 
2712
    else
 
2713
        clen = sensor->id_len;
 
2714
    memcpy(id, sensor->id, clen);
 
2715
 
 
2716
    if (sensor->id_type == IPMI_ASCII_STR) {
 
2717
        /* NIL terminate the ASCII string. */
 
2718
        if (clen == length)
 
2719
            clen--;
 
2720
 
 
2721
        id[clen] = '\0';
 
2722
    }
 
2723
 
 
2724
    return clen;
 
2725
}
 
2726
 
 
2727
void
 
2728
ipmi_sensor_set_owner(ipmi_sensor_t *sensor, int owner)
 
2729
{
 
2730
    sensor->owner = owner;
 
2731
}
 
2732
 
 
2733
void
 
2734
ipmi_sensor_set_channel(ipmi_sensor_t *sensor, int channel)
 
2735
{
 
2736
    sensor->channel = channel;
 
2737
}
 
2738
 
 
2739
void
 
2740
ipmi_sensor_set_entity_id(ipmi_sensor_t *sensor, int entity_id)
 
2741
{
 
2742
    sensor->entity_id = entity_id;
 
2743
}
 
2744
 
 
2745
void
 
2746
ipmi_sensor_set_entity_instance(ipmi_sensor_t *sensor, int entity_instance)
 
2747
{
 
2748
    sensor->entity_instance = entity_instance;
 
2749
}
 
2750
 
 
2751
void
 
2752
ipmi_sensor_set_entity_instance_logical(ipmi_sensor_t *sensor,
 
2753
                                        int           entity_instance_logical)
 
2754
{
 
2755
    sensor->entity_instance_logical = entity_instance_logical;
 
2756
}
 
2757
 
 
2758
void
 
2759
ipmi_sensor_set_sensor_init_scanning(ipmi_sensor_t *sensor,
 
2760
                                     int           sensor_init_scanning)
 
2761
{
 
2762
    sensor->sensor_init_scanning = sensor_init_scanning;
 
2763
}
 
2764
 
 
2765
void
 
2766
ipmi_sensor_set_sensor_init_events(ipmi_sensor_t *sensor,
 
2767
                                   int           sensor_init_events)
 
2768
{
 
2769
    sensor->sensor_init_events = sensor_init_events;
 
2770
}
 
2771
 
 
2772
void
 
2773
ipmi_sensor_set_sensor_init_thresholds(ipmi_sensor_t *sensor,
 
2774
                                       int           sensor_init_thresholds)
 
2775
{
 
2776
    sensor->sensor_init_thresholds = sensor_init_thresholds;
 
2777
}
 
2778
 
 
2779
void
 
2780
ipmi_sensor_set_sensor_init_hysteresis(ipmi_sensor_t *sensor,
 
2781
                                       int           sensor_init_hysteresis)
 
2782
{
 
2783
    sensor->sensor_init_hysteresis = sensor_init_hysteresis;
 
2784
}
 
2785
 
 
2786
void
 
2787
ipmi_sensor_set_sensor_init_type(ipmi_sensor_t *sensor, int sensor_init_type)
 
2788
{
 
2789
    sensor->sensor_init_type = sensor_init_type;
 
2790
}
 
2791
 
 
2792
void
 
2793
ipmi_sensor_set_sensor_init_pu_events(ipmi_sensor_t *sensor,
 
2794
                                      int           sensor_init_pu_events)
 
2795
{
 
2796
    sensor->sensor_init_pu_events = sensor_init_pu_events;
 
2797
}
 
2798
 
 
2799
void
 
2800
ipmi_sensor_set_sensor_init_pu_scanning(ipmi_sensor_t *sensor,
 
2801
                                        int           sensor_init_pu_scanning)
 
2802
{
 
2803
    sensor->sensor_init_pu_scanning = sensor_init_pu_scanning;
 
2804
}
 
2805
 
 
2806
void
 
2807
ipmi_sensor_set_ignore_if_no_entity(ipmi_sensor_t *sensor,
 
2808
                                    int           ignore_if_no_entity)
 
2809
{
 
2810
    sensor->ignore_if_no_entity = ignore_if_no_entity;
 
2811
}
 
2812
 
 
2813
void
 
2814
ipmi_sensor_set_supports_auto_rearm(ipmi_sensor_t *sensor, int val)
 
2815
{
 
2816
    sensor->supports_auto_rearm = val;
 
2817
}
 
2818
 
 
2819
void
 
2820
ipmi_sensor_set_hysteresis_support(ipmi_sensor_t *sensor,
 
2821
                                   int           hysteresis_support)
 
2822
{
 
2823
    sensor->hysteresis_support = hysteresis_support;
 
2824
}
 
2825
 
 
2826
void
 
2827
ipmi_sensor_set_threshold_access(ipmi_sensor_t *sensor, int threshold_access)
 
2828
{
 
2829
    sensor->threshold_access = threshold_access;
 
2830
}
 
2831
 
 
2832
void
 
2833
ipmi_sensor_set_event_support(ipmi_sensor_t *sensor, int event_support)
 
2834
{
 
2835
    sensor->event_support = event_support;
 
2836
}
 
2837
 
 
2838
void
 
2839
ipmi_sensor_set_sensor_type(ipmi_sensor_t *sensor, int sensor_type)
 
2840
{
 
2841
    sensor->sensor_type = sensor_type;
 
2842
}
 
2843
 
 
2844
void
 
2845
ipmi_sensor_set_event_reading_type(ipmi_sensor_t *sensor,
 
2846
                                   int           event_reading_type)
 
2847
{
 
2848
    sensor->event_reading_type = event_reading_type;
 
2849
}
 
2850
 
 
2851
void
 
2852
ipmi_sensor_set_direction(ipmi_sensor_t *sensor,
 
2853
                          int           direction)
 
2854
{
 
2855
    sensor->sensor_direction = direction;
 
2856
}
 
2857
 
 
2858
void
 
2859
ipmi_sensor_set_analog_data_format(ipmi_sensor_t *sensor,
 
2860
                                   int           analog_data_format)
 
2861
{
 
2862
    sensor->analog_data_format = analog_data_format;
 
2863
}
 
2864
 
 
2865
void
 
2866
ipmi_sensor_set_rate_unit(ipmi_sensor_t *sensor, int rate_unit)
 
2867
{
 
2868
    sensor->rate_unit = rate_unit;
 
2869
}
 
2870
 
 
2871
void
 
2872
ipmi_sensor_set_modifier_unit_use(ipmi_sensor_t *sensor, int modifier_unit_use)
 
2873
{
 
2874
    sensor->modifier_unit_use = modifier_unit_use;
 
2875
}
 
2876
 
 
2877
void
 
2878
ipmi_sensor_set_percentage(ipmi_sensor_t *sensor, int percentage)
 
2879
{
 
2880
    sensor->percentage = percentage;
 
2881
}
 
2882
 
 
2883
void
 
2884
ipmi_sensor_set_base_unit(ipmi_sensor_t *sensor, int base_unit)
 
2885
{
 
2886
    sensor->base_unit = base_unit;
 
2887
}
 
2888
 
 
2889
void
 
2890
ipmi_sensor_set_modifier_unit(ipmi_sensor_t *sensor, int modifier_unit)
 
2891
{
 
2892
    sensor->modifier_unit = modifier_unit;
 
2893
}
 
2894
 
 
2895
void
 
2896
ipmi_sensor_set_linearization(ipmi_sensor_t *sensor, int linearization)
 
2897
{
 
2898
    sensor->linearization = linearization;
 
2899
}
 
2900
 
 
2901
void
 
2902
ipmi_sensor_set_raw_m(ipmi_sensor_t *sensor, int idx, int val)
 
2903
{
 
2904
    sensor->conv[idx].m = val;
 
2905
}
 
2906
 
 
2907
void
 
2908
ipmi_sensor_set_raw_tolerance(ipmi_sensor_t *sensor, int idx, int val)
 
2909
{
 
2910
    sensor->conv[idx].tolerance = val;
 
2911
}
 
2912
 
 
2913
void
 
2914
ipmi_sensor_set_raw_b(ipmi_sensor_t *sensor, int idx, int val)
 
2915
{
 
2916
    sensor->conv[idx].b = val;
 
2917
}
 
2918
 
 
2919
void
 
2920
ipmi_sensor_set_raw_accuracy(ipmi_sensor_t *sensor, int idx, int val)
 
2921
{
 
2922
    sensor->conv[idx].accuracy = val;
 
2923
}
 
2924
 
 
2925
void
 
2926
ipmi_sensor_set_raw_accuracy_exp(ipmi_sensor_t *sensor, int idx, int val)
 
2927
{
 
2928
    sensor->conv[idx].accuracy_exp = val;
 
2929
}
 
2930
 
 
2931
void
 
2932
ipmi_sensor_set_raw_r_exp(ipmi_sensor_t *sensor, int idx, int val)
 
2933
{
 
2934
    sensor->conv[idx].r_exp = val;
 
2935
}
 
2936
 
 
2937
void
 
2938
ipmi_sensor_set_raw_b_exp(ipmi_sensor_t *sensor, int idx, int val)
 
2939
{
 
2940
    sensor->conv[idx].b_exp = val;
 
2941
}
 
2942
 
 
2943
void
 
2944
ipmi_sensor_set_normal_min_specified(ipmi_sensor_t *sensor,
 
2945
                                     int           normal_min_specified)
 
2946
{
 
2947
    sensor->normal_min_specified = normal_min_specified;
 
2948
}
 
2949
 
 
2950
void
 
2951
ipmi_sensor_set_normal_max_specified(ipmi_sensor_t *sensor,
 
2952
                                     int           normal_max_specified)
 
2953
{
 
2954
    sensor->normal_max_specified = normal_max_specified;
 
2955
}
 
2956
 
 
2957
void
 
2958
ipmi_sensor_set_nominal_reading_specified(
 
2959
    ipmi_sensor_t *sensor,
 
2960
    int            nominal_reading_specified)
 
2961
{
 
2962
    sensor->nominal_reading_specified = nominal_reading_specified;
 
2963
}
 
2964
 
 
2965
void
 
2966
ipmi_sensor_set_raw_nominal_reading(ipmi_sensor_t *sensor,
 
2967
                                    int           raw_nominal_reading)
 
2968
{
 
2969
    sensor->nominal_reading = raw_nominal_reading;
 
2970
}
 
2971
 
 
2972
void
 
2973
ipmi_sensor_set_raw_normal_max(ipmi_sensor_t *sensor, int raw_normal_max)
 
2974
{
 
2975
    sensor->normal_max = raw_normal_max;
 
2976
}
 
2977
 
 
2978
void
 
2979
ipmi_sensor_set_raw_normal_min(ipmi_sensor_t *sensor, int raw_normal_min)
 
2980
{
 
2981
    sensor->normal_min = raw_normal_min;
 
2982
}
 
2983
 
 
2984
void
 
2985
ipmi_sensor_set_raw_sensor_max(ipmi_sensor_t *sensor, int raw_sensor_max)
 
2986
{
 
2987
    sensor->sensor_max = raw_sensor_max;
 
2988
}
 
2989
 
 
2990
void
 
2991
ipmi_sensor_set_raw_sensor_min(ipmi_sensor_t *sensor, int raw_sensor_min)
 
2992
{
 
2993
    sensor->sensor_min = raw_sensor_min;
 
2994
}
 
2995
 
 
2996
void
 
2997
ipmi_sensor_set_positive_going_threshold_hysteresis(
 
2998
    ipmi_sensor_t *sensor,
 
2999
    int           positive_going_threshold_hysteresis)
 
3000
{
 
3001
    sensor->positive_going_threshold_hysteresis
 
3002
        = positive_going_threshold_hysteresis;
 
3003
}
 
3004
 
 
3005
void
 
3006
ipmi_sensor_set_negative_going_threshold_hysteresis(
 
3007
    ipmi_sensor_t *sensor,
 
3008
    int           negative_going_threshold_hysteresis)
 
3009
{
 
3010
    sensor->negative_going_threshold_hysteresis
 
3011
        = negative_going_threshold_hysteresis;
 
3012
}
 
3013
 
 
3014
void
 
3015
ipmi_sensor_set_oem1(ipmi_sensor_t *sensor, int oem1)
 
3016
{
 
3017
    sensor->oem1 = oem1;
 
3018
}
 
3019
 
 
3020
void
 
3021
ipmi_sensor_set_id(ipmi_sensor_t *sensor, char *id,
 
3022
                   enum ipmi_str_type_e type, int length)
 
3023
{
 
3024
    if (length > SENSOR_ID_LEN)
 
3025
        length = SENSOR_ID_LEN;
 
3026
    
 
3027
    memcpy(sensor->id, id, length);
 
3028
    sensor->id_type = type;
 
3029
    sensor->id_len = length;
 
3030
    if (sensor->entity)
 
3031
        sensor_set_name(sensor);
 
3032
}
 
3033
 
 
3034
void
 
3035
ipmi_sensor_set_oem_info(ipmi_sensor_t *sensor, void *oem_info,
 
3036
                         ipmi_sensor_cleanup_oem_info_cb cleanup_handler)
 
3037
{
 
3038
    sensor->oem_info = oem_info;
 
3039
    sensor->oem_info_cleanup_handler = cleanup_handler;
 
3040
}
 
3041
 
 
3042
void *
 
3043
ipmi_sensor_get_oem_info(ipmi_sensor_t *sensor)
 
3044
{
 
3045
    CHECK_SENSOR_LOCK(sensor);
 
3046
 
 
3047
    return sensor->oem_info;
 
3048
}
 
3049
 
 
3050
const char *
 
3051
ipmi_sensor_get_sensor_type_string(ipmi_sensor_t *sensor)
 
3052
{
 
3053
    CHECK_SENSOR_LOCK(sensor);
 
3054
 
 
3055
    return sensor->sensor_type_string;
 
3056
}
 
3057
 
 
3058
void
 
3059
ipmi_sensor_set_sensor_type_string(ipmi_sensor_t *sensor, const char *str)
 
3060
{
 
3061
    sensor->sensor_type_string = str;
 
3062
}
 
3063
 
 
3064
const char *
 
3065
ipmi_sensor_get_event_reading_type_string(ipmi_sensor_t *sensor)
 
3066
{
 
3067
    CHECK_SENSOR_LOCK(sensor);
 
3068
 
 
3069
    return sensor->event_reading_type_string;
 
3070
}
 
3071
 
 
3072
void
 
3073
ipmi_sensor_set_event_reading_type_string(ipmi_sensor_t *sensor,
 
3074
                                          const char    *str)
 
3075
{
 
3076
    sensor->event_reading_type_string = str;
 
3077
}
 
3078
 
 
3079
const char *
 
3080
ipmi_sensor_get_rate_unit_string(ipmi_sensor_t *sensor)
 
3081
{
 
3082
    CHECK_SENSOR_LOCK(sensor);
 
3083
 
 
3084
    return sensor->rate_unit_string;
 
3085
}
 
3086
 
 
3087
void
 
3088
ipmi_sensor_set_rate_unit_string(ipmi_sensor_t *sensor,
 
3089
                                 const char    *str)
 
3090
{
 
3091
    sensor->rate_unit_string = str;
 
3092
}
 
3093
 
 
3094
const char *
 
3095
ipmi_sensor_get_base_unit_string(ipmi_sensor_t *sensor)
 
3096
{
 
3097
    CHECK_SENSOR_LOCK(sensor);
 
3098
 
 
3099
    return sensor->base_unit_string;
 
3100
}
 
3101
 
 
3102
void
 
3103
ipmi_sensor_set_base_unit_string(ipmi_sensor_t *sensor, const char *str)
 
3104
{
 
3105
    sensor->base_unit_string = str;
 
3106
}
 
3107
 
 
3108
const char *
 
3109
ipmi_sensor_get_modifier_unit_string(ipmi_sensor_t *sensor)
 
3110
{
 
3111
    CHECK_SENSOR_LOCK(sensor);
 
3112
 
 
3113
    return sensor->modifier_unit_string;
 
3114
}
 
3115
 
 
3116
void
 
3117
ipmi_sensor_set_modifier_unit_string(ipmi_sensor_t *sensor, const char *str)
 
3118
{
 
3119
    sensor->modifier_unit_string = str;
 
3120
}
 
3121
 
 
3122
void
 
3123
ipmi_sensor_set_hot_swap_requester(ipmi_sensor_t *sensor,
 
3124
                                   unsigned int  offset,
 
3125
                                   unsigned int  val_when_requesting)
 
3126
{
 
3127
    sensor->hot_swap_requester = offset;
 
3128
    sensor->hot_swap_requester_val = val_when_requesting;
 
3129
}
 
3130
 
 
3131
int
 
3132
ipmi_sensor_is_hot_swap_requester(ipmi_sensor_t *sensor,
 
3133
                                  unsigned int  *offset,
 
3134
                                  unsigned int  *val_when_requesting)
 
3135
{
 
3136
    CHECK_SENSOR_LOCK(sensor);
 
3137
 
 
3138
    if (sensor->hot_swap_requester != -1) {
 
3139
        if (offset)
 
3140
            *offset = sensor->hot_swap_requester;
 
3141
        if (val_when_requesting)
 
3142
            *val_when_requesting = sensor->hot_swap_requester_val;
 
3143
        return 1;
 
3144
    }
 
3145
    return 0;
 
3146
}
 
3147
 
 
3148
ipmi_domain_t *
 
3149
ipmi_sensor_get_domain(ipmi_sensor_t *sensor)
 
3150
{
 
3151
    return sensor->domain;
 
3152
}
 
3153
 
 
3154
ipmi_entity_t *
 
3155
ipmi_sensor_get_entity(ipmi_sensor_t *sensor)
 
3156
{
 
3157
    return sensor->entity;
 
3158
}
 
3159
 
 
3160
 
 
3161
/***********************************************************************
 
3162
 *
 
3163
 * Incoming event handling for sensors.
 
3164
 *
 
3165
 **********************************************************************/
 
3166
 
 
3167
int
 
3168
ipmi_sensor_threshold_set_event_handler(
 
3169
    ipmi_sensor_t                             *sensor,
 
3170
    ipmi_sensor_threshold_event_handler_nd_cb handler,
 
3171
    void                                      *cb_data)
 
3172
{
 
3173
    CHECK_SENSOR_LOCK(sensor);
 
3174
 
 
3175
    sensor->threshold_event_handler = handler;
 
3176
    sensor->cb_data = cb_data;
 
3177
    return 0;
 
3178
}
 
3179
 
 
3180
int
 
3181
ipmi_sensor_add_threshold_event_handler(
 
3182
    ipmi_sensor_t                  *sensor,
 
3183
    ipmi_sensor_threshold_event_cb handler,
 
3184
    void                           *cb_data)
 
3185
{
 
3186
    CHECK_SENSOR_LOCK(sensor);
 
3187
 
 
3188
    if (! locked_list_add(sensor->handler_list, handler, cb_data))
 
3189
        return ENOMEM;
 
3190
 
 
3191
    return 0;
 
3192
}
 
3193
 
 
3194
int
 
3195
ipmi_sensor_remove_threshold_event_handler(
 
3196
    ipmi_sensor_t                  *sensor,
 
3197
    ipmi_sensor_threshold_event_cb handler,
 
3198
    void                           *cb_data)
 
3199
{
 
3200
    CHECK_SENSOR_LOCK(sensor);
 
3201
 
 
3202
    if (! locked_list_remove(sensor->handler_list, handler, cb_data))
 
3203
        return ENOENT;
 
3204
 
 
3205
    return 0;
 
3206
}
 
3207
 
 
3208
 
 
3209
int
 
3210
ipmi_sensor_discrete_set_event_handler(
 
3211
    ipmi_sensor_t                            *sensor,
 
3212
    ipmi_sensor_discrete_event_handler_nd_cb handler,
 
3213
    void                                     *cb_data)
 
3214
{
 
3215
    CHECK_SENSOR_LOCK(sensor);
 
3216
 
 
3217
    sensor->discrete_event_handler = handler;
 
3218
    sensor->cb_data = cb_data;
 
3219
    return 0;
 
3220
}
 
3221
 
 
3222
int
 
3223
ipmi_sensor_add_discrete_event_handler(
 
3224
    ipmi_sensor_t                 *sensor,
 
3225
    ipmi_sensor_discrete_event_cb handler,
 
3226
    void                          *cb_data)
 
3227
{
 
3228
    CHECK_SENSOR_LOCK(sensor);
 
3229
 
 
3230
    if (! locked_list_add(sensor->handler_list, handler, cb_data))
 
3231
        return ENOMEM;
 
3232
 
 
3233
    return 0;
 
3234
}
 
3235
 
 
3236
int
 
3237
ipmi_sensor_remove_discrete_event_handler(
 
3238
    ipmi_sensor_t                 *sensor,
 
3239
    ipmi_sensor_discrete_event_cb handler,
 
3240
    void                          *cb_data)
 
3241
{
 
3242
    CHECK_SENSOR_LOCK(sensor);
 
3243
 
 
3244
    if (! locked_list_remove(sensor->handler_list, handler, cb_data))
 
3245
        return ENOENT;
 
3246
 
 
3247
    return 0;
 
3248
}
 
3249
 
 
3250
typedef struct sensor_event_info_s
 
3251
{
 
3252
    ipmi_sensor_t               *sensor;
 
3253
    int                         handled;
 
3254
 
 
3255
    enum ipmi_event_dir_e       dir;
 
3256
    enum ipmi_thresh_e          threshold;
 
3257
    enum ipmi_event_value_dir_e high_low;
 
3258
    enum ipmi_value_present_e   value_present;
 
3259
    unsigned int                raw_value;
 
3260
    double                      value;
 
3261
 
 
3262
    int                         offset;
 
3263
    int                         severity;
 
3264
    int                         prev_severity;
 
3265
 
 
3266
    ipmi_event_t                *event;
 
3267
} sensor_event_info_t;
 
3268
 
 
3269
static int
 
3270
threshold_sensor_event_call_handler(void *cb_data, void *item1, void *item2)
 
3271
{
 
3272
    ipmi_sensor_threshold_event_cb handler = item1;
 
3273
    sensor_event_info_t            *info = cb_data;
 
3274
    int                            handled;
 
3275
 
 
3276
    handled = handler(info->sensor, info->dir,
 
3277
                      info->threshold,
 
3278
                      info->high_low,
 
3279
                      info->value_present,
 
3280
                      info->raw_value, info->value,
 
3281
                      item2, info->event);
 
3282
    if (handled == IPMI_EVENT_HANDLED) {
 
3283
        info->handled = handled;
 
3284
        info->event = NULL;
 
3285
    }
 
3286
    return LOCKED_LIST_ITER_CONTINUE;
 
3287
}
 
3288
 
 
3289
void
 
3290
ipmi_sensor_call_threshold_event_handlers
 
3291
(ipmi_sensor_t               *sensor,
 
3292
 enum ipmi_event_dir_e       dir,
 
3293
 enum ipmi_thresh_e          threshold,
 
3294
 enum ipmi_event_value_dir_e high_low,
 
3295
 enum ipmi_value_present_e   value_present,
 
3296
 unsigned int                raw_value,
 
3297
 double                      value,
 
3298
 ipmi_event_t                **event,
 
3299
 int                         *handled)
 
3300
{
 
3301
    sensor_event_info_t info;
 
3302
 
 
3303
    info.sensor = sensor;
 
3304
    info.dir = dir;
 
3305
    info.threshold = threshold;
 
3306
    info.high_low = high_low;
 
3307
    info.value_present = value_present;
 
3308
    info.raw_value = raw_value;
 
3309
    info.value = value;
 
3310
    info.event = *event;
 
3311
    info.handled = IPMI_EVENT_NOT_HANDLED;
 
3312
 
 
3313
    if (sensor->threshold_event_handler) {
 
3314
        sensor->threshold_event_handler(sensor, info.dir,
 
3315
                                        info.threshold,
 
3316
                                        info.high_low,
 
3317
                                        info.value_present,
 
3318
                                        info.raw_value, info.value,
 
3319
                                        sensor->cb_data, info.event);
 
3320
        if (info.event)
 
3321
            info.handled = IPMI_EVENT_HANDLED;
 
3322
        info.event = NULL;
 
3323
    }
 
3324
    locked_list_iterate(sensor->handler_list,
 
3325
                        threshold_sensor_event_call_handler, &info);
 
3326
 
 
3327
    if (handled)
 
3328
        *handled = info.handled;
 
3329
    *event = info.event;
 
3330
}
 
3331
 
 
3332
static int
 
3333
discrete_sensor_event_call_handler(void *cb_data, void *item1, void *item2)
 
3334
{
 
3335
    ipmi_sensor_discrete_event_cb handler = item1;
 
3336
    sensor_event_info_t           *info = cb_data;
 
3337
    int                           handled;
 
3338
 
 
3339
    handled = handler(info->sensor, info->dir, info->offset,
 
3340
                      info->severity,
 
3341
                      info->prev_severity,
 
3342
                      item2, info->event);
 
3343
    if (handled == IPMI_EVENT_HANDLED) {
 
3344
        info->handled = handled;
 
3345
        info->event = NULL;
 
3346
    }
 
3347
    return LOCKED_LIST_ITER_CONTINUE;
 
3348
}
 
3349
 
 
3350
void
 
3351
ipmi_sensor_call_discrete_event_handlers(ipmi_sensor_t         *sensor,
 
3352
                                         enum ipmi_event_dir_e dir,
 
3353
                                         int                   offset,
 
3354
                                         int                   severity,
 
3355
                                         int                   prev_severity,
 
3356
                                         ipmi_event_t          **event,
 
3357
                                         int                   *handled)
 
3358
{
 
3359
    sensor_event_info_t info;
 
3360
 
 
3361
    info.sensor = sensor;
 
3362
    info.dir = dir;
 
3363
    info.offset = offset;
 
3364
    info.severity = severity;
 
3365
    info.prev_severity = prev_severity;
 
3366
    info.event = *event;
 
3367
    info.handled = IPMI_EVENT_NOT_HANDLED;
 
3368
 
 
3369
    if (sensor->discrete_event_handler) {
 
3370
        sensor->discrete_event_handler(sensor, info.dir, info.offset,
 
3371
                                       info.severity,
 
3372
                                       info.prev_severity,
 
3373
                                       sensor->cb_data, info.event);
 
3374
        if (info.event)
 
3375
            info.handled = IPMI_EVENT_HANDLED;
 
3376
        info.event = NULL;
 
3377
    }
 
3378
    locked_list_iterate(sensor->handler_list,
 
3379
                        discrete_sensor_event_call_handler, &info);
 
3380
 
 
3381
    if (handled)
 
3382
        *handled = info.handled;
 
3383
    *event = info.event;
 
3384
}
 
3385
 
 
3386
int
 
3387
ipmi_sensor_event(ipmi_sensor_t *sensor, ipmi_event_t *event)
 
3388
{
 
3389
    int rv;
 
3390
    int handled;
 
3391
 
 
3392
    CHECK_SENSOR_LOCK(sensor);
 
3393
 
 
3394
    handled = 0;
 
3395
 
 
3396
    if (sensor->event_reading_type == IPMI_EVENT_READING_TYPE_THRESHOLD) {
 
3397
        enum ipmi_event_dir_e       dir;
 
3398
        enum ipmi_thresh_e          threshold;
 
3399
        enum ipmi_event_value_dir_e high_low;
 
3400
        enum ipmi_value_present_e   value_present;
 
3401
        unsigned int                raw_value;
 
3402
        double                      value;
 
3403
        unsigned char               *data;
 
3404
 
 
3405
        data = ipmi_event_get_data_ptr(event);
 
3406
        dir = data[9] >> 7;
 
3407
        threshold = (data[10] >> 1) & 0x07;
 
3408
        high_low = data[10] & 1;
 
3409
        raw_value = data[11];
 
3410
        value = 0.0;
 
3411
 
 
3412
        if ((data[10] >> 6) == 2) {
 
3413
            rv = ipmi_sensor_convert_from_raw(sensor, raw_value, &value);
 
3414
            if (!rv)
 
3415
                value_present = IPMI_RAW_VALUE_PRESENT;
 
3416
            else
 
3417
                value_present = IPMI_BOTH_VALUES_PRESENT;
 
3418
        } else {
 
3419
            value_present = IPMI_NO_VALUES_PRESENT;
 
3420
        }
 
3421
        ipmi_sensor_call_threshold_event_handlers(sensor, dir,
 
3422
                                                  threshold,
 
3423
                                                  high_low,
 
3424
                                                  value_present,
 
3425
                                                  raw_value, value,
 
3426
                                                  &event,
 
3427
                                                  &handled);
 
3428
    } else {
 
3429
        enum ipmi_event_dir_e dir;
 
3430
        int                   offset;
 
3431
        int                   severity = 0;
 
3432
        int                   prev_severity = 0;
 
3433
        unsigned char         *data;
 
3434
 
 
3435
        data = ipmi_event_get_data_ptr(event);
 
3436
        dir = data[9] >> 7;
 
3437
        offset = data[10] & 0x0f;
 
3438
        if ((data[10] >> 6) == 2) {
 
3439
            severity = data[11] >> 4;
 
3440
            prev_severity = data[11] & 0xf;
 
3441
            if (severity == 0xf)
 
3442
                severity = -1;
 
3443
            if (prev_severity == 0xf)
 
3444
                prev_severity = -1;
 
3445
        }
 
3446
 
 
3447
        ipmi_sensor_call_discrete_event_handlers(sensor, dir, offset,
 
3448
                                                 severity,
 
3449
                                                 prev_severity,
 
3450
                                                 &event,
 
3451
                                                 &handled);
 
3452
    }
 
3453
 
 
3454
    /* Make sure the caller knows if we didn't deliver the event. */
 
3455
    if (handled == IPMI_EVENT_NOT_HANDLED)
 
3456
        return EINVAL;
 
3457
    return 0;
 
3458
}
 
3459
 
 
3460
/***********************************************************************
 
3461
 *
 
3462
 * Standard sensor messaging.
 
3463
 *
 
3464
 **********************************************************************/
 
3465
 
 
3466
typedef void (*sensor_done_handler_cb)(ipmi_sensor_t *sensor,
 
3467
                                       int           err,
 
3468
                                       void          *sinfo);
 
3469
 
 
3470
static int
 
3471
sensor_done_check_rsp(ipmi_sensor_t          *sensor,
 
3472
                      int                    err,
 
3473
                      ipmi_msg_t             *rsp,
 
3474
                      unsigned int           min_length,
 
3475
                      char                   *name,
 
3476
                      sensor_done_handler_cb done,
 
3477
                      void                   *sinfo)
 
3478
{
 
3479
    if (err) {
 
3480
        ipmi_log(IPMI_LOG_ERR_INFO,
 
3481
                 "%ssensor.c(%s): Got error: %x",
 
3482
                 SENSOR_NAME(sensor), name, err);
 
3483
        done(sensor, err, sinfo);
 
3484
        return err;
 
3485
    }
 
3486
 
 
3487
    if (!sensor) {
 
3488
        /* This *should* never happen, but we check it to shake out
 
3489
           bugs. */
 
3490
        ipmi_log(IPMI_LOG_ERR_INFO,
 
3491
                 "%ssensor.c(%s): Sensor when away during operation",
 
3492
                 SENSOR_NAME(sensor), name);
 
3493
        done(sensor, ECANCELED, sinfo);
 
3494
        return ECANCELED;
 
3495
    }
 
3496
 
 
3497
    if (rsp && rsp->data[0]) {
 
3498
#if 0
 
3499
        /* This is sometimes expected. */
 
3500
        ipmi_log(IPMI_LOG_ERR_INFO,
 
3501
                 "%ssensor.c(%s): Got IPMI error in response: %x",
 
3502
                 SENSOR_NAME(sensor), name, rsp->data[0]);
 
3503
#endif
 
3504
        done(sensor, IPMI_IPMI_ERR_VAL(rsp->data[0]), sinfo);
 
3505
        return IPMI_IPMI_ERR_VAL(rsp->data[0]);
 
3506
    }
 
3507
 
 
3508
    if (rsp && (rsp->data_len < min_length)) {
 
3509
        ipmi_log(IPMI_LOG_ERR_INFO,
 
3510
                 "%ssensor.c(%s): Response was too short, got %d, expected %d",
 
3511
                 SENSOR_NAME(sensor), name, rsp->data_len, min_length);
 
3512
        done(sensor, EINVAL, sinfo);
 
3513
        return EINVAL;
 
3514
    }
 
3515
 
 
3516
    return 0;
 
3517
}
 
3518
 
 
3519
typedef struct event_enable_info_s
 
3520
{
 
3521
    ipmi_sensor_op_info_t sdata;
 
3522
    ipmi_event_state_t    state;
 
3523
    ipmi_sensor_done_cb   done;
 
3524
    void                  *cb_data;
 
3525
    int                   do_enable;
 
3526
    int                   do_disable;
 
3527
} event_enable_info_t;
 
3528
 
 
3529
static void enables_done_handler(ipmi_sensor_t *sensor,
 
3530
                                 int           err,
 
3531
                                 void          *sinfo)
 
3532
{
 
3533
    event_enable_info_t *info = sinfo;
 
3534
 
 
3535
    if (info->done)
 
3536
        info->done(sensor, err, info->cb_data);
 
3537
    ipmi_sensor_opq_done(sensor);
 
3538
    ipmi_mem_free(info);
 
3539
}
 
3540
 
 
3541
static void
 
3542
disables_set(ipmi_sensor_t *sensor,
 
3543
             int           err,
 
3544
             ipmi_msg_t    *rsp,
 
3545
             void          *cb_data)
 
3546
{
 
3547
    event_enable_info_t *info = cb_data;
 
3548
 
 
3549
    if (sensor_done_check_rsp(sensor, err, rsp, 1, "disables_set",
 
3550
                              enables_done_handler, info))
 
3551
        return;
 
3552
 
 
3553
    enables_done_handler(sensor, 0, info);
 
3554
}
 
3555
 
 
3556
static void
 
3557
enables_set(ipmi_sensor_t *sensor,
 
3558
            int           err,
 
3559
            ipmi_msg_t    *rsp,
 
3560
            void          *cb_data)
 
3561
{
 
3562
    event_enable_info_t *info = cb_data;
 
3563
    unsigned char       cmd_data[MAX_IPMI_DATA_SIZE];
 
3564
    ipmi_msg_t          cmd_msg;
 
3565
    int                 rv;
 
3566
 
 
3567
    if (sensor_done_check_rsp(sensor, err, rsp, 1, "enables_set",
 
3568
                              enables_done_handler, info))
 
3569
        return;
 
3570
 
 
3571
    if (info->do_disable) {
 
3572
        /* Enables were set, now disable all the other ones. */
 
3573
        cmd_msg.netfn = IPMI_SENSOR_EVENT_NETFN;
 
3574
        cmd_msg.cmd = IPMI_SET_SENSOR_EVENT_ENABLE_CMD;
 
3575
        cmd_msg.data_len = 6;
 
3576
        cmd_msg.data = cmd_data;
 
3577
        cmd_data[0] = sensor->num;
 
3578
        cmd_data[1] = (info->state.status & 0xc0) | (0x02 << 4);
 
3579
        cmd_data[2] = ~(info->state.__assertion_events & 0xff);
 
3580
        cmd_data[3] = ~(info->state.__assertion_events >> 8);
 
3581
        cmd_data[4] = ~(info->state.__deassertion_events & 0xff);
 
3582
        cmd_data[5] = ~(info->state.__deassertion_events >> 8);
 
3583
        rv = ipmi_sensor_send_command(sensor, sensor->mc, sensor->send_lun,
 
3584
                                      &cmd_msg, disables_set,
 
3585
                                      &(info->sdata), info);
 
3586
        if (rv) {
 
3587
            ipmi_log(IPMI_LOG_ERR_INFO,
 
3588
                     "%ssensors.c(enables_set):"
 
3589
                     " Error sending event enable command to clear events: %x",
 
3590
                     SENSOR_NAME(sensor), rv);
 
3591
            enables_done_handler(sensor, rv, info);
 
3592
        }
 
3593
    } else {
 
3594
        /* Just doing enables, we are done. */
 
3595
        enables_done_handler(sensor, 0, info);
 
3596
    }
 
3597
}
 
3598
 
 
3599
static void
 
3600
event_enable_set_start(ipmi_sensor_t *sensor, int err, void *cb_data)
 
3601
{
 
3602
    event_enable_info_t *info = cb_data;
 
3603
    unsigned char       cmd_data[MAX_IPMI_DATA_SIZE];
 
3604
    ipmi_msg_t          cmd_msg;
 
3605
    int                 event_support;
 
3606
    int                 rv;
 
3607
 
 
3608
    if (sensor_done_check_rsp(sensor, err, NULL, 0, "event_enable_set_start",
 
3609
                              enables_done_handler, info))
 
3610
        return;
 
3611
 
 
3612
    event_support = ipmi_sensor_get_event_support(sensor);
 
3613
 
 
3614
    cmd_msg.data = cmd_data;
 
3615
    cmd_msg.netfn = IPMI_SENSOR_EVENT_NETFN;
 
3616
    cmd_msg.cmd = IPMI_SET_SENSOR_EVENT_ENABLE_CMD;
 
3617
    cmd_msg.data = cmd_data;
 
3618
    cmd_data[0] = sensor->num;
 
3619
    if (event_support == IPMI_EVENT_SUPPORT_ENTIRE_SENSOR) {
 
3620
        /* We can only turn on/off the entire sensor, just pass the
 
3621
           status to the sensor. */
 
3622
        cmd_data[1] = info->state.status & 0xc0;
 
3623
        cmd_msg.data_len = 2;
 
3624
        rv = ipmi_sensor_send_command(sensor, sensor->mc, sensor->send_lun,
 
3625
                                      &cmd_msg, disables_set, &(info->sdata),
 
3626
                                      info);
 
3627
    } else if (info->do_enable) {
 
3628
        /* Start by first setting the enables, then set the disables
 
3629
           in a second operation.  We do this because enables and
 
3630
           disables cannot both be set at the same time, and it's
 
3631
           safer to first enable the new events then to disable the
 
3632
           events we want disabled.  It would be *really* nice if IPMI
 
3633
           had a way to do this in one operation, such as using 11b in
 
3634
           the request byte 2 bits 5:4 to say "set the events to
 
3635
           exactly this state". */
 
3636
        cmd_data[1] = (info->state.status & 0xc0) | (0x01 << 4);
 
3637
        cmd_data[2] = info->state.__assertion_events & 0xff;
 
3638
        cmd_data[3] = info->state.__assertion_events >> 8;
 
3639
        cmd_data[4] = info->state.__deassertion_events & 0xff;
 
3640
        cmd_data[5] = info->state.__deassertion_events >> 8;
 
3641
        cmd_msg.data_len = 6;
 
3642
        rv = ipmi_sensor_send_command(sensor, sensor->mc, sensor->send_lun,
 
3643
                                      &cmd_msg, enables_set, &(info->sdata),
 
3644
                                      info);
 
3645
    } else {
 
3646
        /* We are only doing disables. */
 
3647
        cmd_data[1] = (info->state.status & 0xc0) | (0x02 << 4);
 
3648
        cmd_data[2] = info->state.__assertion_events & 0xff;
 
3649
        cmd_data[3] = info->state.__assertion_events >> 8;
 
3650
        cmd_data[4] = info->state.__deassertion_events & 0xff;
 
3651
        cmd_data[5] = info->state.__deassertion_events >> 8;
 
3652
        cmd_msg.data_len = 6;
 
3653
        rv = ipmi_sensor_send_command(sensor, sensor->mc, sensor->send_lun,
 
3654
                                      &cmd_msg, disables_set,
 
3655
                                      &(info->sdata), info);
 
3656
    }
 
3657
    if (rv) {
 
3658
        ipmi_log(IPMI_LOG_ERR_INFO,
 
3659
                 "%ssensor.c(event_enable_set_start):"
 
3660
                 " Error sending event enable command: %x",
 
3661
                 SENSOR_NAME(sensor), rv);
 
3662
        enables_done_handler(sensor, rv, info);
 
3663
    }
 
3664
}
 
3665
 
 
3666
static int
 
3667
check_events_capability(ipmi_sensor_t      *sensor,
 
3668
                        ipmi_event_state_t *states)
 
3669
{
 
3670
    int event_support;
 
3671
 
 
3672
    event_support = ipmi_sensor_get_event_support(sensor);
 
3673
    if ((event_support == IPMI_EVENT_SUPPORT_NONE)
 
3674
        || (event_support == IPMI_EVENT_SUPPORT_GLOBAL_ENABLE))
 
3675
    {
 
3676
        /* We don't support setting events for this sensor. */
 
3677
        return EINVAL;
 
3678
    }
 
3679
 
 
3680
    if ((event_support == IPMI_EVENT_SUPPORT_ENTIRE_SENSOR)
 
3681
        && ((states->__assertion_events != 0)
 
3682
            || (states->__deassertion_events != 0)))
 
3683
    {
 
3684
        /* This sensor does not support individual event states, but
 
3685
           the user is trying to set them. */
 
3686
        return EINVAL;
 
3687
    }
 
3688
 
 
3689
    if (event_support == IPMI_EVENT_SUPPORT_PER_STATE) {
 
3690
        int i;
 
3691
        for (i=0; i<16; i++) {
 
3692
            unsigned int bit = 1 << i;
 
3693
 
 
3694
            if (((!sensor->mask1[i]) && (bit & states->__assertion_events))
 
3695
                || ((!sensor->mask2[i]) && (bit & states->__deassertion_events)))
 
3696
            {
 
3697
                /* The user is attempting to set a state that the
 
3698
                   sensor does not support. */
 
3699
                return EINVAL;
 
3700
            }
 
3701
        }
 
3702
    }
 
3703
 
 
3704
    return 0;
 
3705
}
 
3706
 
 
3707
static int
 
3708
stand_ipmi_sensor_set_event_enables(ipmi_sensor_t         *sensor,
 
3709
                                    ipmi_event_state_t    *states,
 
3710
                                    ipmi_sensor_done_cb   done,
 
3711
                                    void                  *cb_data)
 
3712
{
 
3713
    event_enable_info_t *info;
 
3714
    int                 rv;
 
3715
 
 
3716
    rv = check_events_capability(sensor, states);
 
3717
    if (rv)
 
3718
        return rv;
 
3719
 
 
3720
    info = ipmi_mem_alloc(sizeof(*info));
 
3721
    if (!info)
 
3722
        return ENOMEM;
 
3723
    info->state = *states;
 
3724
    info->done = done;
 
3725
    info->cb_data = cb_data;
 
3726
    info->do_enable = 1;
 
3727
    info->do_disable = 1;
 
3728
    rv = ipmi_sensor_add_opq(sensor, event_enable_set_start,
 
3729
                             &(info->sdata), info);
 
3730
    if (rv)
 
3731
        ipmi_mem_free(info);
 
3732
    return rv;
 
3733
}
 
3734
 
 
3735
static int
 
3736
stand_ipmi_sensor_enable_events(ipmi_sensor_t         *sensor,
 
3737
                                ipmi_event_state_t    *states,
 
3738
                                ipmi_sensor_done_cb   done,
 
3739
                                void                  *cb_data)
 
3740
{
 
3741
    event_enable_info_t *info;
 
3742
    int                 rv;
 
3743
 
 
3744
    rv = check_events_capability(sensor, states);
 
3745
    if (rv)
 
3746
        return rv;
 
3747
 
 
3748
    info = ipmi_mem_alloc(sizeof(*info));
 
3749
    if (!info)
 
3750
        return ENOMEM;
 
3751
    info->state = *states;
 
3752
    info->done = done;
 
3753
    info->cb_data = cb_data;
 
3754
    info->do_enable = 1;
 
3755
    info->do_disable = 0;
 
3756
    rv = ipmi_sensor_add_opq(sensor, event_enable_set_start,
 
3757
                             &(info->sdata), info);
 
3758
    if (rv)
 
3759
        ipmi_mem_free(info);
 
3760
    return rv;
 
3761
}
 
3762
 
 
3763
static int
 
3764
stand_ipmi_sensor_disable_events(ipmi_sensor_t         *sensor,
 
3765
                                 ipmi_event_state_t    *states,
 
3766
                                 ipmi_sensor_done_cb   done,
 
3767
                                 void                  *cb_data)
 
3768
{
 
3769
    event_enable_info_t *info;
 
3770
    int                 rv;
 
3771
 
 
3772
    rv = check_events_capability(sensor, states);
 
3773
    if (rv)
 
3774
        return rv;
 
3775
 
 
3776
    info = ipmi_mem_alloc(sizeof(*info));
 
3777
    if (!info)
 
3778
        return ENOMEM;
 
3779
    info->state = *states;
 
3780
    info->done = done;
 
3781
    info->cb_data = cb_data;
 
3782
    info->do_enable = 0;
 
3783
    info->do_disable = 1;
 
3784
    rv = ipmi_sensor_add_opq(sensor, event_enable_set_start,
 
3785
                             &(info->sdata), info);
 
3786
    if (rv)
 
3787
        ipmi_mem_free(info);
 
3788
    return rv;
 
3789
}
 
3790
 
 
3791
typedef struct event_enable_get_info_s
 
3792
{
 
3793
    ipmi_sensor_op_info_t        sdata;
 
3794
    ipmi_event_state_t           state;
 
3795
    ipmi_sensor_event_enables_cb done;
 
3796
    void                         *cb_data;
 
3797
} event_enable_get_info_t;
 
3798
 
 
3799
static void enables_get_done_handler(ipmi_sensor_t *sensor,
 
3800
                                     int           err,
 
3801
                                     void          *sinfo)
 
3802
{
 
3803
    event_enable_get_info_t *info = sinfo;
 
3804
 
 
3805
    if (info->done)
 
3806
        info->done(sensor, err, &info->state, info->cb_data);
 
3807
    ipmi_sensor_opq_done(sensor);
 
3808
    ipmi_mem_free(info);
 
3809
}
 
3810
 
 
3811
static void
 
3812
enables_get(ipmi_sensor_t *sensor,
 
3813
            int           err,
 
3814
            ipmi_msg_t    *rsp,
 
3815
            void          *cb_data)
 
3816
{
 
3817
    event_enable_get_info_t *info = cb_data;
 
3818
 
 
3819
    if (sensor_done_check_rsp(sensor, err, rsp, 2, "enables_get",
 
3820
                              enables_get_done_handler, info))
 
3821
        return;
 
3822
 
 
3823
    info->state.status = rsp->data[1] & 0xc0;
 
3824
    if (rsp->data_len >= 4)
 
3825
        info->state.__assertion_events = (rsp->data[2]
 
3826
                                          | (rsp->data[3] << 8));
 
3827
    if (rsp->data_len >= 6)
 
3828
        info->state.__deassertion_events = (rsp->data[4]
 
3829
                                            | (rsp->data[5] << 8));
 
3830
    enables_get_done_handler(sensor, 0, info);
 
3831
}
 
3832
 
 
3833
static void
 
3834
event_enable_get_start(ipmi_sensor_t *sensor, int err, void *cb_data)
 
3835
{
 
3836
    event_enable_get_info_t *info = cb_data;
 
3837
    unsigned char           cmd_data[MAX_IPMI_DATA_SIZE];
 
3838
    ipmi_msg_t              cmd_msg;
 
3839
    int                     rv;
 
3840
 
 
3841
    if (sensor_done_check_rsp(sensor, err, NULL, 0, "event_enable_get_start",
 
3842
                              enables_get_done_handler, info))
 
3843
        return;
 
3844
 
 
3845
    cmd_msg.data = cmd_data;
 
3846
    cmd_msg.netfn = IPMI_SENSOR_EVENT_NETFN;
 
3847
    cmd_msg.cmd = IPMI_GET_SENSOR_EVENT_ENABLE_CMD;
 
3848
    cmd_msg.data_len = 1;
 
3849
    cmd_msg.data = cmd_data;
 
3850
    cmd_data[0] = sensor->num;
 
3851
    rv = ipmi_sensor_send_command(sensor, sensor->mc, sensor->send_lun,
 
3852
                                  &cmd_msg, enables_get, &(info->sdata), info);
 
3853
    if (rv) {
 
3854
        ipmi_log(IPMI_LOG_ERR_INFO,
 
3855
                 "%ssensor.c(event_enable_get_start):"
 
3856
                 " Error sending get event enables command: %x",
 
3857
                 SENSOR_NAME(sensor), rv);
 
3858
        enables_get_done_handler(sensor, rv, info);
 
3859
    }
 
3860
}
 
3861
 
 
3862
static int
 
3863
stand_ipmi_sensor_get_event_enables(ipmi_sensor_t                *sensor,
 
3864
                                    ipmi_sensor_event_enables_cb done,
 
3865
                                    void                         *cb_data)
 
3866
{
 
3867
    event_enable_get_info_t *info;
 
3868
    int                     rv;
 
3869
 
 
3870
    info = ipmi_mem_alloc(sizeof(*info));
 
3871
    if (!info)
 
3872
        return ENOMEM;
 
3873
    memset(info, 0, sizeof(info));
 
3874
    info->done = done;
 
3875
    info->cb_data = cb_data;
 
3876
    rv = ipmi_sensor_add_opq(sensor, event_enable_get_start,
 
3877
                             &(info->sdata), info);
 
3878
    if (rv)
 
3879
        ipmi_mem_free(info);
 
3880
    return rv;
 
3881
}
 
3882
 
 
3883
typedef struct sensor_rearm_info_s
 
3884
{
 
3885
    ipmi_sensor_op_info_t sdata;
 
3886
    ipmi_event_state_t    state;
 
3887
    int                   global_enable;
 
3888
    ipmi_sensor_done_cb   done;
 
3889
    void                  *cb_data;
 
3890
} sensor_rearm_info_t;
 
3891
 
 
3892
static void sensor_rearm_done_handler(ipmi_sensor_t *sensor,
 
3893
                                      int           err,
 
3894
                                      void          *sinfo)
 
3895
{
 
3896
    sensor_rearm_info_t *info = sinfo;
 
3897
 
 
3898
    if (info->done)
 
3899
        info->done(sensor, err, info->cb_data);
 
3900
    ipmi_sensor_opq_done(sensor);
 
3901
    ipmi_mem_free(info);
 
3902
}
 
3903
 
 
3904
static void
 
3905
sensor_rearm(ipmi_sensor_t *sensor,
 
3906
             int           err,
 
3907
             ipmi_msg_t    *rsp,
 
3908
             void          *cb_data)
 
3909
{
 
3910
    sensor_rearm_info_t *info = cb_data;
 
3911
 
 
3912
    if (sensor_done_check_rsp(sensor, err, rsp, 1, "sensor_rearm",
 
3913
                              sensor_rearm_done_handler, info))
 
3914
        return;
 
3915
 
 
3916
    sensor_rearm_done_handler(sensor, 0, info);
 
3917
}
 
3918
 
 
3919
static void
 
3920
sensor_rearm_start(ipmi_sensor_t *sensor, int err, void *cb_data)
 
3921
{
 
3922
    sensor_rearm_info_t *info = cb_data;
 
3923
    unsigned char   cmd_data[MAX_IPMI_DATA_SIZE];
 
3924
    ipmi_msg_t      cmd_msg;
 
3925
    int             rv;
 
3926
 
 
3927
    if (sensor_done_check_rsp(sensor, err, NULL, 0, "sensor_rearm_start",
 
3928
                              sensor_rearm_done_handler, info))
 
3929
        return;
 
3930
 
 
3931
    cmd_msg.data = cmd_data;
 
3932
    cmd_msg.netfn = IPMI_SENSOR_EVENT_NETFN;
 
3933
    cmd_msg.cmd = IPMI_REARM_SENSOR_EVENTS_CMD;
 
3934
    if (info->global_enable) {
 
3935
        cmd_msg.data_len = 2;
 
3936
        cmd_msg.data = cmd_data;
 
3937
        cmd_data[0] = sensor->num;
 
3938
        cmd_data[1] = 0; /* Rearm all events. */
 
3939
    } else {
 
3940
        cmd_msg.data_len = 6;
 
3941
        cmd_msg.data = cmd_data;
 
3942
        cmd_data[0] = sensor->num;
 
3943
        cmd_data[1] = 0x80; /* Rearm only specific sensors. */
 
3944
        cmd_data[2] = info->state.__assertion_events & 0xff;
 
3945
        cmd_data[3] = info->state.__assertion_events >> 8;
 
3946
        cmd_data[4] = info->state.__deassertion_events & 0xff;
 
3947
        cmd_data[5] = info->state.__deassertion_events >> 8;
 
3948
    }
 
3949
    rv = ipmi_sensor_send_command(sensor, sensor->mc, sensor->send_lun,
 
3950
                                  &cmd_msg, sensor_rearm,
 
3951
                                  &(info->sdata), info);
 
3952
    if (rv) {
 
3953
        ipmi_log(IPMI_LOG_ERR_INFO,
 
3954
                 "%ssensor.c(sensor_rearm_start):"
 
3955
                 " Error sending rearm command: %x",
 
3956
                 SENSOR_NAME(sensor), rv);
 
3957
        sensor_rearm_done_handler(sensor, rv, info);
 
3958
    }
 
3959
}
 
3960
 
 
3961
static int
 
3962
stand_ipmi_sensor_rearm(ipmi_sensor_t       *sensor,
 
3963
                        int                 global_enable,
 
3964
                        ipmi_event_state_t  *state,
 
3965
                        ipmi_sensor_done_cb done,
 
3966
                        void                *cb_data)
 
3967
{
 
3968
    sensor_rearm_info_t *info;
 
3969
    int                 rv;
 
3970
    
 
3971
    if (!global_enable && !state)
 
3972
        return EINVAL;
 
3973
 
 
3974
    info = ipmi_mem_alloc(sizeof(*info));
 
3975
    if (!info)
 
3976
        return ENOMEM;
 
3977
    info->done = done;
 
3978
    info->cb_data = cb_data;
 
3979
    info->global_enable = global_enable;
 
3980
    if (state)
 
3981
        memcpy(&info->state, state, sizeof(info->state));
 
3982
    rv = ipmi_sensor_add_opq(sensor, sensor_rearm_start, &(info->sdata), info);
 
3983
    if (rv)
 
3984
        ipmi_mem_free(info);
 
3985
    return rv;
 
3986
}
 
3987
 
 
3988
typedef struct hyst_get_info_s
 
3989
{
 
3990
    ipmi_sensor_op_info_t     sdata;
 
3991
    ipmi_sensor_hysteresis_cb done;
 
3992
    void                      *cb_data;
 
3993
    unsigned int              positive;
 
3994
    unsigned int              negative;
 
3995
} hyst_get_info_t;
 
3996
 
 
3997
static void hyst_get_done_handler(ipmi_sensor_t *sensor,
 
3998
                                  int           err,
 
3999
                                  void          *sinfo)
 
4000
{
 
4001
    hyst_get_info_t *info = sinfo;
 
4002
 
 
4003
    if (info->done)
 
4004
        info->done(sensor, err, info->positive, info->negative, info->cb_data);
 
4005
    ipmi_sensor_opq_done(sensor);
 
4006
    ipmi_mem_free(info);
 
4007
}
 
4008
 
 
4009
static void
 
4010
hyst_get(ipmi_sensor_t *sensor,
 
4011
         int           err,
 
4012
         ipmi_msg_t    *rsp,
 
4013
         void          *cb_data)
 
4014
{
 
4015
    hyst_get_info_t *info = cb_data;
 
4016
 
 
4017
    if (sensor_done_check_rsp(sensor, err, rsp, 3, "hyst_get",
 
4018
                              hyst_get_done_handler, info))
 
4019
        return;
 
4020
 
 
4021
    info->positive = rsp->data[1];
 
4022
    info->negative = rsp->data[2];
 
4023
    hyst_get_done_handler(sensor, 0, info);
 
4024
}
 
4025
 
 
4026
static void
 
4027
hyst_get_start(ipmi_sensor_t *sensor, int err, void *cb_data)
 
4028
{
 
4029
    hyst_get_info_t *info = cb_data;
 
4030
    unsigned char       cmd_data[MAX_IPMI_DATA_SIZE];
 
4031
    ipmi_msg_t          cmd_msg;
 
4032
    int                 rv;
 
4033
 
 
4034
    if (sensor_done_check_rsp(sensor, err, NULL, 0, "hyst_get_start",
 
4035
                              hyst_get_done_handler, info))
 
4036
        return;
 
4037
 
 
4038
    cmd_msg.data = cmd_data;
 
4039
    cmd_msg.netfn = IPMI_SENSOR_EVENT_NETFN;
 
4040
    cmd_msg.cmd = IPMI_GET_SENSOR_HYSTERESIS_CMD;
 
4041
    cmd_msg.data_len = 2;
 
4042
    cmd_msg.data = cmd_data;
 
4043
    cmd_data[0] = sensor->num;
 
4044
    cmd_data[1] = 0xff;
 
4045
    rv = ipmi_sensor_send_command(sensor, sensor->mc, sensor->send_lun,
 
4046
                                  &cmd_msg, hyst_get, &(info->sdata), info);
 
4047
    if (rv) {
 
4048
        ipmi_log(IPMI_LOG_ERR_INFO,
 
4049
                 "%ssensor.c(hyst_get_start):"
 
4050
                 " Error sending hysteresis get command: %x",
 
4051
                 SENSOR_NAME(sensor), rv);
 
4052
        hyst_get_done_handler(sensor, rv, info);
 
4053
    }
 
4054
}
 
4055
 
 
4056
static int
 
4057
stand_ipmi_sensor_get_hysteresis(ipmi_sensor_t             *sensor,
 
4058
                                 ipmi_sensor_hysteresis_cb done,
 
4059
                                 void                      *cb_data)
 
4060
{
 
4061
    hyst_get_info_t *info;
 
4062
    int             rv;
 
4063
    
 
4064
    if (sensor->event_reading_type != IPMI_EVENT_READING_TYPE_THRESHOLD)
 
4065
        /* Not a threshold sensor, it doesn't have readings. */
 
4066
        return ENOSYS;
 
4067
 
 
4068
    if ((sensor->hysteresis_support != IPMI_HYSTERESIS_SUPPORT_READABLE)
 
4069
        && (sensor->hysteresis_support != IPMI_HYSTERESIS_SUPPORT_SETTABLE))
 
4070
        return ENOSYS;
 
4071
    
 
4072
    info = ipmi_mem_alloc(sizeof(*info));
 
4073
    if (!info)
 
4074
        return ENOMEM;
 
4075
    memset(info, 0, sizeof(*info));
 
4076
    info->done = done;
 
4077
    info->cb_data = cb_data;
 
4078
    rv = ipmi_sensor_add_opq(sensor, hyst_get_start, &(info->sdata), info);
 
4079
    if (rv)
 
4080
        ipmi_mem_free(info);
 
4081
    return rv;
 
4082
}
 
4083
 
 
4084
typedef struct hyst_set_info_s
 
4085
{
 
4086
    ipmi_sensor_op_info_t sdata;
 
4087
    unsigned int          positive, negative;
 
4088
    ipmi_sensor_done_cb   done;
 
4089
    void                  *cb_data;
 
4090
} hyst_set_info_t;
 
4091
 
 
4092
static void hyst_set_done_handler(ipmi_sensor_t *sensor,
 
4093
                                  int           err,
 
4094
                                  void          *sinfo)
 
4095
{
 
4096
    hyst_set_info_t *info = sinfo;
 
4097
 
 
4098
    if (info->done)
 
4099
        info->done(sensor, err, info->cb_data);
 
4100
    ipmi_sensor_opq_done(sensor);
 
4101
    ipmi_mem_free(info);
 
4102
}
 
4103
 
 
4104
static void
 
4105
hyst_set(ipmi_sensor_t *sensor,
 
4106
         int           err,
 
4107
         ipmi_msg_t    *rsp,
 
4108
         void          *cb_data)
 
4109
{
 
4110
    hyst_set_info_t *info = cb_data;
 
4111
 
 
4112
    if (sensor_done_check_rsp(sensor, err, rsp, 1, "hyst_set",
 
4113
                              hyst_set_done_handler, info))
 
4114
        return;
 
4115
 
 
4116
    hyst_set_done_handler(sensor, 0, info);
 
4117
}
 
4118
 
 
4119
static void
 
4120
hyst_set_start(ipmi_sensor_t *sensor, int err, void *cb_data)
 
4121
{
 
4122
    hyst_set_info_t *info = cb_data;
 
4123
    unsigned char   cmd_data[MAX_IPMI_DATA_SIZE];
 
4124
    ipmi_msg_t      cmd_msg;
 
4125
    int             rv;
 
4126
 
 
4127
    if (sensor_done_check_rsp(sensor, err, NULL, 0, "hyst_set_start",
 
4128
                              hyst_set_done_handler, info))
 
4129
        return;
 
4130
 
 
4131
    cmd_msg.data = cmd_data;
 
4132
    cmd_msg.netfn = IPMI_SENSOR_EVENT_NETFN;
 
4133
    cmd_msg.cmd = IPMI_SET_SENSOR_HYSTERESIS_CMD;
 
4134
    cmd_msg.data_len = 4;
 
4135
    cmd_msg.data = cmd_data;
 
4136
    cmd_data[0] = sensor->num;
 
4137
    cmd_data[1] = 0xff;
 
4138
    cmd_data[2] = info->positive;
 
4139
    cmd_data[3] = info->negative;
 
4140
    rv = ipmi_sensor_send_command(sensor, sensor->mc, sensor->send_lun,
 
4141
                                  &cmd_msg, hyst_set, &(info->sdata), info);
 
4142
    if (rv) {
 
4143
        ipmi_log(IPMI_LOG_ERR_INFO,
 
4144
                 "%ssensor.c(hyst_set_start):"
 
4145
                 " Error sending hysteresis set command: %x",
 
4146
                 SENSOR_NAME(sensor), rv);
 
4147
        hyst_set_done_handler(sensor, rv, info);
 
4148
    }
 
4149
}
 
4150
 
 
4151
static int
 
4152
stand_ipmi_sensor_set_hysteresis(ipmi_sensor_t       *sensor,
 
4153
                                 unsigned int        positive_hysteresis,
 
4154
                                 unsigned int        negative_hysteresis,
 
4155
                                 ipmi_sensor_done_cb done,
 
4156
                                 void                *cb_data)
 
4157
{
 
4158
    hyst_set_info_t *info;
 
4159
    int             rv;
 
4160
    
 
4161
    if (sensor->event_reading_type != IPMI_EVENT_READING_TYPE_THRESHOLD)
 
4162
        /* Not a threshold sensor, it doesn't have readings. */
 
4163
        return ENOSYS;
 
4164
 
 
4165
    if (sensor->hysteresis_support != IPMI_HYSTERESIS_SUPPORT_SETTABLE)
 
4166
        return ENOSYS;
 
4167
    
 
4168
    info = ipmi_mem_alloc(sizeof(*info));
 
4169
    if (!info)
 
4170
        return ENOMEM;
 
4171
    info->positive = positive_hysteresis;
 
4172
    info->negative = negative_hysteresis;
 
4173
    info->done = done;
 
4174
    info->cb_data = cb_data;
 
4175
    rv = ipmi_sensor_add_opq(sensor, hyst_set_start, &(info->sdata), info);
 
4176
    if (rv)
 
4177
        ipmi_mem_free(info);
 
4178
    return rv;
 
4179
}
 
4180
 
 
4181
typedef struct thresh_get_info_s
 
4182
{
 
4183
    ipmi_sensor_op_info_t     sdata;
 
4184
    ipmi_thresholds_t         th;
 
4185
    ipmi_sensor_thresholds_cb done;
 
4186
    void                      *cb_data;
 
4187
} thresh_get_info_t;
 
4188
 
 
4189
static void thresh_get_done_handler(ipmi_sensor_t *sensor,
 
4190
                                    int           err,
 
4191
                                    void          *sinfo)
 
4192
{
 
4193
    thresh_get_info_t *info = sinfo;
 
4194
 
 
4195
    if (info->done)
 
4196
        info->done(sensor, err, &info->th, info->cb_data);
 
4197
    ipmi_sensor_opq_done(sensor);
 
4198
    ipmi_mem_free(info);
 
4199
}
 
4200
 
 
4201
static void
 
4202
thresh_get(ipmi_sensor_t *sensor,
 
4203
           int           err,
 
4204
           ipmi_msg_t    *rsp,
 
4205
           void          *cb_data)
 
4206
{
 
4207
    thresh_get_info_t  *info = cb_data;
 
4208
    enum ipmi_thresh_e th;
 
4209
 
 
4210
    if (sensor_done_check_rsp(sensor, err, rsp, 8, "thresh_get",
 
4211
                              thresh_get_done_handler, info))
 
4212
        return;
 
4213
    
 
4214
    for (th=IPMI_LOWER_NON_CRITICAL; th<=IPMI_UPPER_NON_RECOVERABLE; th++) {
 
4215
        int rv;
 
4216
        if (rsp->data[1] & (1 << th)) {
 
4217
            info->th.vals[th].status = 1;
 
4218
            rv = ipmi_sensor_convert_from_raw(sensor,
 
4219
                                              rsp->data[th+2],
 
4220
                                              &(info->th.vals[th].val));
 
4221
            if (rv) {
 
4222
                ipmi_log(IPMI_LOG_ERR_INFO,
 
4223
                         "%ssensor.c(thresh_get):"
 
4224
                         " Could not convert raw threshold value: %x",
 
4225
                         SENSOR_NAME(sensor), rv);
 
4226
                thresh_get_done_handler(sensor, rv, info);
 
4227
                return;
 
4228
            }
 
4229
        } else {
 
4230
            info->th.vals[th].status = 0;
 
4231
        }
 
4232
    }
 
4233
 
 
4234
    thresh_get_done_handler(sensor, 0, info);
 
4235
}
 
4236
 
 
4237
int
 
4238
ipmi_get_default_sensor_thresholds(ipmi_sensor_t     *sensor,
 
4239
                                   ipmi_thresholds_t *th)
 
4240
{
 
4241
    enum ipmi_thresh_e thnum;
 
4242
    int                rv = 0;
 
4243
 
 
4244
    CHECK_SENSOR_LOCK(sensor);
 
4245
 
 
4246
    for (thnum = IPMI_LOWER_NON_CRITICAL;
 
4247
         thnum <= IPMI_UPPER_NON_RECOVERABLE;
 
4248
         thnum++)
 
4249
    {
 
4250
        th->vals[thnum].status = 1;
 
4251
        rv = ipmi_sensor_convert_from_raw(sensor,
 
4252
                                          sensor->default_thresholds[thnum],
 
4253
                                          &(th->vals[thnum].val));
 
4254
        if (rv)
 
4255
            goto out;
 
4256
    }
 
4257
 out:
 
4258
    return rv;
 
4259
}
 
4260
 
 
4261
static void
 
4262
thresh_get_start(ipmi_sensor_t *sensor, int err, void *cb_data)
 
4263
{
 
4264
    thresh_get_info_t *info = cb_data;
 
4265
    unsigned char     cmd_data[MAX_IPMI_DATA_SIZE];
 
4266
    ipmi_msg_t        cmd_msg;
 
4267
    int               rv;
 
4268
 
 
4269
    if (sensor_done_check_rsp(sensor, err, NULL, 0, "thresh_get_start",
 
4270
                              thresh_get_done_handler, info))
 
4271
        return;
 
4272
    
 
4273
    if (sensor->threshold_access == IPMI_THRESHOLD_ACCESS_SUPPORT_FIXED) {
 
4274
        int thnum;
 
4275
        /* Thresholds are fixed, they cannot be read. */
 
4276
        for (thnum = IPMI_LOWER_NON_CRITICAL;
 
4277
             thnum <= IPMI_UPPER_NON_RECOVERABLE;
 
4278
             thnum++)
 
4279
        {
 
4280
            info->th.vals[thnum].status = 0;
 
4281
        }
 
4282
        thresh_get_done_handler(sensor, 0, info);
 
4283
        return;
 
4284
    }
 
4285
 
 
4286
    cmd_msg.data = cmd_data;
 
4287
    cmd_msg.netfn = IPMI_SENSOR_EVENT_NETFN;
 
4288
    cmd_msg.cmd = IPMI_GET_SENSOR_THRESHOLD_CMD;
 
4289
    cmd_msg.data_len = 1;
 
4290
    cmd_msg.data = cmd_data;
 
4291
    cmd_data[0] = sensor->num;
 
4292
    rv = ipmi_sensor_send_command(sensor, sensor->mc, sensor->send_lun,
 
4293
                                  &cmd_msg, thresh_get, &(info->sdata), info);
 
4294
    if (rv) {
 
4295
        ipmi_log(IPMI_LOG_ERR_INFO,
 
4296
                 "%ssensor.c(thresh_get_start):"
 
4297
                 " Error sending threshold get command: %x",
 
4298
                 SENSOR_NAME(sensor), rv);
 
4299
        thresh_get_done_handler(sensor, rv, info);
 
4300
    }
 
4301
}
 
4302
 
 
4303
static int
 
4304
stand_ipmi_sensor_get_thresholds(ipmi_sensor_t             *sensor,
 
4305
                                 ipmi_sensor_thresholds_cb done,
 
4306
                                 void                      *cb_data)
 
4307
{
 
4308
    thresh_get_info_t *info;
 
4309
    int               rv;
 
4310
    
 
4311
    if (sensor->event_reading_type != IPMI_EVENT_READING_TYPE_THRESHOLD)
 
4312
        /* Not a threshold sensor, it doesn't have readings. */
 
4313
        return ENOSYS;
 
4314
 
 
4315
    if (sensor->threshold_access == IPMI_THRESHOLD_ACCESS_SUPPORT_NONE)
 
4316
        return ENOSYS;
 
4317
    
 
4318
    info = ipmi_mem_alloc(sizeof(*info));
 
4319
    if (!info)
 
4320
        return ENOMEM;
 
4321
    info->done = done;
 
4322
    info->cb_data = cb_data;
 
4323
    rv = ipmi_sensor_add_opq(sensor, thresh_get_start, &(info->sdata), info);
 
4324
    if (rv)
 
4325
        ipmi_mem_free(info);
 
4326
    return rv;
 
4327
}
 
4328
 
 
4329
typedef struct thresh_set_info_s
 
4330
{
 
4331
    ipmi_sensor_op_info_t sdata;
 
4332
    ipmi_thresholds_t     th;
 
4333
    ipmi_sensor_done_cb   done;
 
4334
    void                  *cb_data;
 
4335
} thresh_set_info_t;
 
4336
 
 
4337
static void thresh_set_done_handler(ipmi_sensor_t *sensor,
 
4338
                                    int           err,
 
4339
                                    void          *sinfo)
 
4340
{
 
4341
    thresh_set_info_t *info = sinfo;
 
4342
 
 
4343
    if (info->done)
 
4344
        info->done(sensor, err, info->cb_data);
 
4345
    ipmi_sensor_opq_done(sensor);
 
4346
    ipmi_mem_free(info);
 
4347
}
 
4348
 
 
4349
static void
 
4350
thresh_set(ipmi_sensor_t *sensor,
 
4351
           int           err,
 
4352
           ipmi_msg_t    *rsp,
 
4353
           void          *cb_data)
 
4354
{
 
4355
    thresh_set_info_t *info = cb_data;
 
4356
 
 
4357
    if (sensor_done_check_rsp(sensor, err, rsp, 1, "thresh_set",
 
4358
                              thresh_set_done_handler, info))
 
4359
        return;
 
4360
 
 
4361
    thresh_set_done_handler(sensor, 0, info);
 
4362
}
 
4363
 
 
4364
static void
 
4365
thresh_set_start(ipmi_sensor_t *sensor, int err, void *cb_data)
 
4366
{
 
4367
    thresh_set_info_t  *info = cb_data;
 
4368
    unsigned char      cmd_data[MAX_IPMI_DATA_SIZE];
 
4369
    ipmi_msg_t         cmd_msg;
 
4370
    int                rv;
 
4371
    enum ipmi_thresh_e th;
 
4372
 
 
4373
    if (sensor_done_check_rsp(sensor, err, NULL, 0, "thresh_set_start",
 
4374
                              thresh_set_done_handler, info))
 
4375
        return;
 
4376
 
 
4377
    cmd_msg.data = cmd_data;
 
4378
    cmd_msg.netfn = IPMI_SENSOR_EVENT_NETFN;
 
4379
    cmd_msg.cmd = IPMI_SET_SENSOR_THRESHOLD_CMD;
 
4380
    cmd_msg.data_len = 8;
 
4381
    cmd_msg.data = cmd_data;
 
4382
    cmd_data[0] = sensor->num;
 
4383
    cmd_data[1] = 0;
 
4384
    for (th=IPMI_LOWER_NON_CRITICAL; th<=IPMI_UPPER_NON_RECOVERABLE; th++) {
 
4385
        if (info->th.vals[th].status) {
 
4386
            int val;
 
4387
            cmd_data[1] |= (1 << th);
 
4388
            rv = ipmi_sensor_convert_to_raw(sensor,
 
4389
                                            ROUND_NORMAL,
 
4390
                                            info->th.vals[th].val,
 
4391
                                            &val);
 
4392
            if (rv) {
 
4393
                ipmi_log(IPMI_LOG_ERR_INFO,
 
4394
                         "%ssensor.c(thresh_set_start):"
 
4395
                         "Error converting threshold to raw: %x",
 
4396
                         SENSOR_NAME(sensor), rv);
 
4397
                thresh_set_done_handler(sensor, rv, info);
 
4398
                return;
 
4399
            }
 
4400
            cmd_data[th+2] = val;
 
4401
        }
 
4402
    }
 
4403
 
 
4404
    rv = ipmi_sensor_send_command(sensor, sensor->mc, sensor->send_lun,
 
4405
                                  &cmd_msg, thresh_set, &(info->sdata), info);
 
4406
    if (rv) {
 
4407
        ipmi_log(IPMI_LOG_ERR_INFO,
 
4408
                 "%ssensor.c(thresh_set_start):"
 
4409
                 "Error sending thresholds set command: %x",
 
4410
                 SENSOR_NAME(sensor), rv);
 
4411
        thresh_set_done_handler(sensor, rv, info);
 
4412
    }
 
4413
}
 
4414
 
 
4415
static int
 
4416
stand_ipmi_sensor_set_thresholds(ipmi_sensor_t       *sensor,
 
4417
                                 ipmi_thresholds_t   *thresholds,
 
4418
                                 ipmi_sensor_done_cb done,
 
4419
                                 void                *cb_data)
 
4420
{
 
4421
    thresh_set_info_t *info;
 
4422
    int               rv;
 
4423
    
 
4424
    if (sensor->event_reading_type != IPMI_EVENT_READING_TYPE_THRESHOLD)
 
4425
        /* Not a threshold sensor, it doesn't have readings. */
 
4426
        return ENOSYS;
 
4427
 
 
4428
    if (sensor->threshold_access != IPMI_THRESHOLD_ACCESS_SUPPORT_SETTABLE)
 
4429
        return ENOSYS;
 
4430
    
 
4431
    info = ipmi_mem_alloc(sizeof(*info));
 
4432
    if (!info)
 
4433
        return ENOMEM;
 
4434
    info->th = *thresholds;
 
4435
    info->done = done;
 
4436
    info->cb_data = cb_data;
 
4437
    rv = ipmi_sensor_add_opq(sensor, thresh_set_start, &(info->sdata), info);
 
4438
    if (rv)
 
4439
        ipmi_mem_free(info);
 
4440
    return rv;
 
4441
}
 
4442
 
 
4443
typedef struct reading_get_info_s
 
4444
{
 
4445
    ipmi_sensor_op_info_t      sdata;
 
4446
    ipmi_sensor_reading_cb     done;
 
4447
    void                       *cb_data;
 
4448
    ipmi_states_t              states;
 
4449
    enum ipmi_value_present_e  value_present;
 
4450
    double                     raw_val;
 
4451
    double                     cooked_val;
 
4452
} reading_get_info_t;
 
4453
 
 
4454
static void reading_get_done_handler(ipmi_sensor_t *sensor,
 
4455
                                     int           err,
 
4456
                                     void          *sinfo)
 
4457
{
 
4458
    reading_get_info_t *info = sinfo;
 
4459
 
 
4460
    if (info->done)
 
4461
        info->done(sensor, err, info->value_present,
 
4462
                   info->raw_val, info->cooked_val, &info->states,
 
4463
                   info->cb_data);
 
4464
    ipmi_sensor_opq_done(sensor);
 
4465
    ipmi_mem_free(info);
 
4466
}
 
4467
 
 
4468
static void
 
4469
reading_get(ipmi_sensor_t *sensor,
 
4470
            int           err,
 
4471
            ipmi_msg_t    *rsp,
 
4472
            void          *rsp_data)
 
4473
{
 
4474
    reading_get_info_t        *info = rsp_data;
 
4475
    int                       rv;
 
4476
 
 
4477
    if (sensor_done_check_rsp(sensor, err, rsp, 3, "reading_get",
 
4478
                              reading_get_done_handler, info))
 
4479
        return;
 
4480
 
 
4481
    info->raw_val = rsp->data[1];
 
4482
    if (sensor->analog_data_format != IPMI_ANALOG_DATA_FORMAT_NOT_ANALOG) {
 
4483
        rv = ipmi_sensor_convert_from_raw(sensor,
 
4484
                                          info->raw_val,
 
4485
                                          &info->cooked_val);
 
4486
        if (rv)
 
4487
            info->value_present = IPMI_RAW_VALUE_PRESENT;
 
4488
        else
 
4489
            info->value_present = IPMI_BOTH_VALUES_PRESENT;
 
4490
    } else {
 
4491
        info->value_present = IPMI_NO_VALUES_PRESENT;
 
4492
    }
 
4493
 
 
4494
    info->states.__event_messages_enabled = (rsp->data[2] >> 7) & 1;
 
4495
    info->states.__sensor_scanning_enabled = (rsp->data[2] >> 6) & 1;
 
4496
    info->states.__initial_update_in_progress = (rsp->data[2] >> 5) & 1;
 
4497
    if (rsp->data_len >= 4)
 
4498
        info->states.__states = rsp->data[3];
 
4499
 
 
4500
    reading_get_done_handler(sensor, 0, info);
 
4501
}
 
4502
 
 
4503
static void
 
4504
reading_get_start(ipmi_sensor_t *sensor, int err, void *cb_data)
 
4505
{
 
4506
    reading_get_info_t *info = cb_data;
 
4507
    unsigned char      cmd_data[MAX_IPMI_DATA_SIZE];
 
4508
    ipmi_msg_t         cmd_msg;
 
4509
    int                rv;
 
4510
 
 
4511
    if (sensor_done_check_rsp(sensor, err, NULL, 0, "reading_get_start",
 
4512
                              reading_get_done_handler, info))
 
4513
        return;
 
4514
 
 
4515
    cmd_msg.data = cmd_data;
 
4516
    cmd_msg.netfn = IPMI_SENSOR_EVENT_NETFN;
 
4517
    cmd_msg.cmd = IPMI_GET_SENSOR_READING_CMD;
 
4518
    cmd_msg.data_len = 1;
 
4519
    cmd_msg.data = cmd_data;
 
4520
    cmd_data[0] = sensor->num;
 
4521
    rv = ipmi_sensor_send_command(sensor, sensor->mc, sensor->send_lun,
 
4522
                                  &cmd_msg, reading_get,
 
4523
                                  &(info->sdata), info);
 
4524
    if (rv) {
 
4525
        ipmi_log(IPMI_LOG_ERR_INFO,
 
4526
                 "%ssensor.c(reading_get_start):"
 
4527
                 "Error sending reading get command: %x",
 
4528
                 SENSOR_NAME(sensor), rv);
 
4529
        reading_get_done_handler(sensor, rv, info);
 
4530
    }
 
4531
}
 
4532
 
 
4533
static int
 
4534
stand_ipmi_sensor_get_reading(ipmi_sensor_t          *sensor,
 
4535
                              ipmi_sensor_reading_cb done,
 
4536
                              void                   *cb_data)
 
4537
{
 
4538
    reading_get_info_t *info;
 
4539
    int                rv;
 
4540
    
 
4541
    if (sensor->event_reading_type != IPMI_EVENT_READING_TYPE_THRESHOLD)
 
4542
        /* Not a threshold sensor, it doesn't have readings. */
 
4543
        return ENOSYS;
 
4544
 
 
4545
    info = ipmi_mem_alloc(sizeof(*info));
 
4546
    if (!info)
 
4547
        return ENOMEM;
 
4548
    info->done = done;
 
4549
    info->cb_data = cb_data;
 
4550
    info->value_present = IPMI_NO_VALUES_PRESENT;
 
4551
    info->raw_val = 0;
 
4552
    info->cooked_val = 0.0;
 
4553
    ipmi_init_states(&info->states);
 
4554
    rv = ipmi_sensor_add_opq(sensor, reading_get_start, &(info->sdata), info);
 
4555
    if (rv)
 
4556
        ipmi_mem_free(info);
 
4557
    return rv;
 
4558
}
 
4559
 
 
4560
 
 
4561
typedef struct states_get_info_s
 
4562
{
 
4563
    ipmi_sensor_op_info_t sdata;
 
4564
    ipmi_sensor_states_cb done;
 
4565
    void                  *cb_data;
 
4566
    ipmi_states_t         states;
 
4567
} states_get_info_t;
 
4568
 
 
4569
static void states_get_done_handler(ipmi_sensor_t *sensor,
 
4570
                                    int           err,
 
4571
                                    void          *sinfo)
 
4572
{
 
4573
    states_get_info_t *info = sinfo;
 
4574
 
 
4575
    if (info->done)
 
4576
        info->done(sensor, err, &info->states, info->cb_data);
 
4577
    ipmi_sensor_opq_done(sensor);
 
4578
    ipmi_mem_free(info);
 
4579
}
 
4580
 
 
4581
static void
 
4582
states_get(ipmi_sensor_t *sensor,
 
4583
           int           err,
 
4584
           ipmi_msg_t    *rsp,
 
4585
           void          *cb_data)
 
4586
{
 
4587
    states_get_info_t *info = cb_data;
 
4588
 
 
4589
    if (sensor_done_check_rsp(sensor, err, rsp, 3, "states_get",
 
4590
                              states_get_done_handler, info))
 
4591
        return;
 
4592
 
 
4593
    info->states.__event_messages_enabled = (rsp->data[2] >> 7) & 1;
 
4594
    info->states.__sensor_scanning_enabled = (rsp->data[2] >> 6) & 1;
 
4595
    info->states.__initial_update_in_progress = (rsp->data[2] >> 5) & 1;
 
4596
 
 
4597
    if (rsp->data_len >= 4)
 
4598
        info->states.__states |= rsp->data[3];
 
4599
    if (rsp->data_len >= 5)
 
4600
        info->states.__states |= rsp->data[4] << 8;
 
4601
 
 
4602
    states_get_done_handler(sensor, 0, info);
 
4603
}
 
4604
 
 
4605
static void
 
4606
states_get_start(ipmi_sensor_t *sensor, int err, void *cb_data)
 
4607
{
 
4608
    states_get_info_t *info = cb_data;
 
4609
    unsigned char     cmd_data[MAX_IPMI_DATA_SIZE];
 
4610
    ipmi_msg_t        cmd_msg;
 
4611
    int               rv;
 
4612
 
 
4613
    if (sensor_done_check_rsp(sensor, err, NULL, 0, "states_get_start",
 
4614
                              states_get_done_handler, info))
 
4615
        return;
 
4616
 
 
4617
    cmd_msg.data = cmd_data;
 
4618
    cmd_msg.netfn = IPMI_SENSOR_EVENT_NETFN;
 
4619
    cmd_msg.cmd = IPMI_GET_SENSOR_READING_CMD;
 
4620
    cmd_msg.data_len = 1;
 
4621
    cmd_msg.data = cmd_data;
 
4622
    cmd_data[0] = sensor->num;
 
4623
    rv = ipmi_sensor_send_command(sensor, sensor->mc, sensor->send_lun,
 
4624
                                  &cmd_msg, states_get,
 
4625
                                  &(info->sdata), info);
 
4626
    if (rv) {
 
4627
        ipmi_log(IPMI_LOG_ERR_INFO,
 
4628
                 "%sstates.c(states_get_start):"
 
4629
                 " Error sending states get command: %x",
 
4630
                 SENSOR_NAME(sensor), rv);
 
4631
        states_get_done_handler(sensor, 0, info);
 
4632
    }
 
4633
}
 
4634
 
 
4635
static int
 
4636
stand_ipmi_sensor_get_states(ipmi_sensor_t         *sensor,
 
4637
                             ipmi_sensor_states_cb done,
 
4638
                             void                  *cb_data)
 
4639
{
 
4640
    states_get_info_t *info;
 
4641
    int               rv;
 
4642
    
 
4643
    if (sensor->event_reading_type == IPMI_EVENT_READING_TYPE_THRESHOLD)
 
4644
        /* A threshold sensor, it doesn't have states. */
 
4645
        return ENOSYS;
 
4646
 
 
4647
    info = ipmi_mem_alloc(sizeof(*info));
 
4648
    if (!info)
 
4649
        return ENOMEM;
 
4650
    info->done = done;
 
4651
    info->cb_data = cb_data;
 
4652
    ipmi_init_states(&info->states);
 
4653
    rv = ipmi_sensor_add_opq(sensor, states_get_start, &(info->sdata), info);
 
4654
    if (rv)
 
4655
        ipmi_mem_free(info);
 
4656
    return rv;
 
4657
}
 
4658
 
 
4659
/***********************************************************************
 
4660
 *
 
4661
 * Various data conversion stuff.
 
4662
 *
 
4663
 **********************************************************************/
 
4664
 
 
4665
static double c_linear(double val)
 
4666
{
 
4667
    return val;
 
4668
}
 
4669
 
 
4670
static double c_log2(double val)
 
4671
{
 
4672
    return log(val) / 0.69314718 /* log(2) */;
 
4673
}
 
4674
 
 
4675
static double c_exp10(double val)
 
4676
{
 
4677
    return pow(10.0, val);
 
4678
}
 
4679
 
 
4680
static double c_exp2(double val)
 
4681
{
 
4682
    return pow(2.0, val);
 
4683
}
 
4684
 
 
4685
static double c_1_over_x(double val)
 
4686
{
 
4687
    return 1.0 / val;
 
4688
}
 
4689
 
 
4690
static double c_sqr(double val)
 
4691
{
 
4692
    return pow(val, 2.0);
 
4693
}
 
4694
 
 
4695
static double c_cube(double val)
 
4696
{
 
4697
    return pow(val, 3.0);
 
4698
}
 
4699
 
 
4700
static double c_1_over_cube(double val)
 
4701
{
 
4702
    return 1.0 / pow(val, 3.0);
 
4703
}
 
4704
 
 
4705
typedef double (*linearizer)(double val);
 
4706
static linearizer linearize[12] =
 
4707
{
 
4708
    c_linear,
 
4709
    log,
 
4710
    log10,
 
4711
    c_log2,
 
4712
    exp,
 
4713
    c_exp10,
 
4714
    c_exp2,
 
4715
    c_1_over_x,
 
4716
    c_sqr,
 
4717
    c_cube,
 
4718
    sqrt,
 
4719
    c_1_over_cube
 
4720
};
 
4721
 
 
4722
static int
 
4723
sign_extend(int m, int bits)
 
4724
{
 
4725
    if (m & (1 << (bits-1)))
 
4726
        return m | (-1 << bits);
 
4727
    else
 
4728
        return m & (~(-1 << bits));
 
4729
}
 
4730
 
 
4731
static int
 
4732
stand_ipmi_sensor_convert_from_raw(ipmi_sensor_t *sensor,
 
4733
                                   int           val,
 
4734
                                   double        *result)
 
4735
{
 
4736
    double m, b, b_exp, r_exp, fval;
 
4737
    linearizer c_func;
 
4738
 
 
4739
    if (sensor->event_reading_type != IPMI_EVENT_READING_TYPE_THRESHOLD)
 
4740
        /* Not a threshold sensor, it doesn't have readings. */
 
4741
        return ENOSYS;
 
4742
 
 
4743
    if (sensor->linearization == IPMI_LINEARIZATION_NONLINEAR)
 
4744
        c_func = c_linear;
 
4745
    else if (sensor->linearization <= 11)
 
4746
        c_func = linearize[sensor->linearization];
 
4747
    else
 
4748
        return EINVAL;
 
4749
 
 
4750
    val &= 0xff;
 
4751
 
 
4752
    m = sensor->conv[val].m;
 
4753
    b = sensor->conv[val].b;
 
4754
    r_exp = sensor->conv[val].r_exp;
 
4755
    b_exp = sensor->conv[val].b_exp;
 
4756
 
 
4757
    switch(sensor->analog_data_format) {
 
4758
        case IPMI_ANALOG_DATA_FORMAT_UNSIGNED:
 
4759
            fval = val;
 
4760
            break;
 
4761
        case IPMI_ANALOG_DATA_FORMAT_1_COMPL:
 
4762
            val = sign_extend(val, 8);
 
4763
            if (val < 0)
 
4764
                val += 1;
 
4765
            fval = val;
 
4766
            break;
 
4767
        case IPMI_ANALOG_DATA_FORMAT_2_COMPL:
 
4768
            fval = sign_extend(val, 8);
 
4769
            break;
 
4770
        default:
 
4771
            return EINVAL;
 
4772
    }
 
4773
 
 
4774
    *result = c_func(((m * fval) + (b * pow(10, b_exp))) * pow(10, r_exp));
 
4775
    return 0;
 
4776
}
 
4777
 
 
4778
static int
 
4779
stand_ipmi_sensor_convert_to_raw(ipmi_sensor_t     *sensor,
 
4780
                                 enum ipmi_round_e rounding,
 
4781
                                 double            val,
 
4782
                                 int               *result)
 
4783
{
 
4784
    double cval;
 
4785
    int    lowraw, highraw, raw, maxraw, minraw, next_raw;
 
4786
    int    rv;
 
4787
 
 
4788
    if (sensor->event_reading_type != IPMI_EVENT_READING_TYPE_THRESHOLD)
 
4789
        /* Not a threshold sensor, it doesn't have readings. */
 
4790
        return ENOSYS;
 
4791
 
 
4792
    switch(sensor->analog_data_format) {
 
4793
        case IPMI_ANALOG_DATA_FORMAT_UNSIGNED:
 
4794
            lowraw = 0;
 
4795
            highraw = 255;
 
4796
            minraw = 0;
 
4797
            maxraw = 255;
 
4798
            next_raw = 128;
 
4799
            break;
 
4800
        case IPMI_ANALOG_DATA_FORMAT_1_COMPL:
 
4801
            lowraw = -127;
 
4802
            highraw = 127;
 
4803
            minraw = -127;
 
4804
            maxraw = 127;
 
4805
            next_raw = 0;
 
4806
            break;
 
4807
        case IPMI_ANALOG_DATA_FORMAT_2_COMPL:
 
4808
            lowraw = -128;
 
4809
            highraw = 127;
 
4810
            minraw = -128;
 
4811
            maxraw = 127;
 
4812
            next_raw = 0;
 
4813
            break;
 
4814
        default:
 
4815
            return EINVAL;
 
4816
    }
 
4817
 
 
4818
    /* We do a binary search for the right value.  Yuck, but I don't
 
4819
       have a better plan that will work with non-linear sensors. */
 
4820
    do {
 
4821
        raw = next_raw;
 
4822
        rv = ipmi_sensor_convert_from_raw(sensor, raw, &cval);
 
4823
        if (rv)
 
4824
            return rv;
 
4825
 
 
4826
        if (cval < val) {
 
4827
            next_raw = ((highraw - raw) / 2) + raw;
 
4828
            lowraw = raw;
 
4829
        } else {
 
4830
            next_raw = ((raw - lowraw) / 2) + lowraw;
 
4831
            highraw = raw;
 
4832
        }
 
4833
    } while (raw != next_raw);
 
4834
 
 
4835
    /* The above loop gets us to within 1 of what it should be, we
 
4836
       have to look at rounding to make the final decision. */
 
4837
    switch (rounding)
 
4838
    {
 
4839
        case ROUND_NORMAL:
 
4840
            if (val > cval) {
 
4841
                if (raw < maxraw) {
 
4842
                    double nval;
 
4843
                    rv = ipmi_sensor_convert_from_raw(sensor, raw+1, &nval);
 
4844
                    if (rv)
 
4845
                        return rv;
 
4846
                    nval = cval + ((nval - cval) / 2.0);
 
4847
                    if (val >= nval)
 
4848
                        raw++;
 
4849
                }
 
4850
            } else {
 
4851
                if (raw > minraw) {
 
4852
                    double pval;
 
4853
                    rv = ipmi_sensor_convert_from_raw(sensor, raw-1, &pval);
 
4854
                    if (rv)
 
4855
                        return rv;
 
4856
                    pval = pval + ((cval - pval) / 2.0);
 
4857
                    if (val < pval)
 
4858
                        raw--;
 
4859
                }
 
4860
            }
 
4861
            break;
 
4862
        case ROUND_UP:
 
4863
            if ((val > cval) && (raw < maxraw)) {
 
4864
                raw++;
 
4865
            }
 
4866
            break;
 
4867
        case ROUND_DOWN:
 
4868
            if ((val < cval) && (raw > minraw)) {
 
4869
                raw--;
 
4870
            }
 
4871
            break;
 
4872
    }
 
4873
 
 
4874
    if (sensor->analog_data_format == IPMI_ANALOG_DATA_FORMAT_1_COMPL) {
 
4875
        if (raw < 0)
 
4876
            raw -= 1;
 
4877
    }
 
4878
 
 
4879
    *result = raw & 0xff;
 
4880
    return 0;
 
4881
}
 
4882
 
 
4883
static int
 
4884
stand_ipmi_sensor_get_tolerance(ipmi_sensor_t *sensor,
 
4885
                                int           val,
 
4886
                                double        *tolerance)
 
4887
{
 
4888
    double m, r_exp, fval;
 
4889
    linearizer c_func;
 
4890
 
 
4891
    if (sensor->event_reading_type != IPMI_EVENT_READING_TYPE_THRESHOLD)
 
4892
        /* Not a threshold sensor, it doesn't have readings. */
 
4893
        return ENOSYS;
 
4894
 
 
4895
    if (sensor->linearization == IPMI_LINEARIZATION_NONLINEAR)
 
4896
        c_func = c_linear;
 
4897
    else if (sensor->linearization <= 11)
 
4898
        c_func = linearize[sensor->linearization];
 
4899
    else
 
4900
        return EINVAL;
 
4901
 
 
4902
    val &= 0xff;
 
4903
 
 
4904
    m = sensor->conv[val].m;
 
4905
    r_exp = sensor->conv[val].r_exp;
 
4906
 
 
4907
    fval = sign_extend(val, 8);
 
4908
 
 
4909
    *tolerance = c_func(((m * fval) / 2.0) * pow(10, r_exp));
 
4910
    return 0;
 
4911
}
 
4912
 
 
4913
/* Returns accuracy as a percentage value. */
 
4914
static int
 
4915
stand_ipmi_sensor_get_accuracy(ipmi_sensor_t *sensor, int val, double *accuracy)
 
4916
{
 
4917
    double a, a_exp;
 
4918
 
 
4919
    if (sensor->event_reading_type != IPMI_EVENT_READING_TYPE_THRESHOLD)
 
4920
        /* Not a threshold sensor, it doesn't have readings. */
 
4921
        return ENOSYS;
 
4922
 
 
4923
    val &= 0xff;
 
4924
 
 
4925
    a = sensor->conv[val].accuracy;
 
4926
    a_exp = sensor->conv[val].r_exp;
 
4927
 
 
4928
    *accuracy = (a * pow(10, a_exp)) / 100.0;
 
4929
    return 0;
 
4930
}
 
4931
 
 
4932
static const char *
 
4933
stand_ipmi_sensor_reading_name_string(ipmi_sensor_t *sensor, int offset)
 
4934
{
 
4935
    return ipmi_get_reading_name(sensor->event_reading_type,
 
4936
                                 sensor->sensor_type,
 
4937
                                 offset);
 
4938
}
 
4939
 
 
4940
/***********************************************************************
 
4941
 *
 
4942
 * The standard callback structure
 
4943
 *
 
4944
 **********************************************************************/
 
4945
 
 
4946
const ipmi_sensor_cbs_t ipmi_standard_sensor_cb =
 
4947
{
 
4948
    .ipmi_sensor_set_event_enables = stand_ipmi_sensor_set_event_enables,
 
4949
    .ipmi_sensor_get_event_enables = stand_ipmi_sensor_get_event_enables,
 
4950
    .ipmi_sensor_enable_events     = stand_ipmi_sensor_enable_events,
 
4951
    .ipmi_sensor_disable_events    = stand_ipmi_sensor_disable_events,
 
4952
    .ipmi_sensor_rearm             = stand_ipmi_sensor_rearm,
 
4953
 
 
4954
    .ipmi_sensor_convert_from_raw  = stand_ipmi_sensor_convert_from_raw,
 
4955
    .ipmi_sensor_convert_to_raw    = stand_ipmi_sensor_convert_to_raw,
 
4956
    .ipmi_sensor_get_accuracy      = stand_ipmi_sensor_get_accuracy,
 
4957
    .ipmi_sensor_get_tolerance     = stand_ipmi_sensor_get_tolerance,
 
4958
    .ipmi_sensor_get_hysteresis    = stand_ipmi_sensor_get_hysteresis,
 
4959
    .ipmi_sensor_set_hysteresis    = stand_ipmi_sensor_set_hysteresis,
 
4960
    .ipmi_sensor_set_thresholds    = stand_ipmi_sensor_set_thresholds,
 
4961
    .ipmi_sensor_get_thresholds    = stand_ipmi_sensor_get_thresholds,
 
4962
    .ipmi_sensor_get_reading       = stand_ipmi_sensor_get_reading,
 
4963
 
 
4964
    .ipmi_sensor_get_states        = stand_ipmi_sensor_get_states,
 
4965
    .ipmi_sensor_reading_name_string = stand_ipmi_sensor_reading_name_string,
 
4966
};
 
4967
 
 
4968
void
 
4969
ipmi_sensor_get_callbacks(ipmi_sensor_t *sensor, ipmi_sensor_cbs_t *cbs)
 
4970
{
 
4971
    *cbs = sensor->cbs;
 
4972
}
 
4973
 
 
4974
void
 
4975
ipmi_sensor_set_callbacks(ipmi_sensor_t *sensor, ipmi_sensor_cbs_t *cbs)
 
4976
{
 
4977
    sensor->cbs = *cbs;
 
4978
}
 
4979
 
 
4980
/***********************************************************************
 
4981
 *
 
4982
 * Polymorphic calls to the callback handlers.
 
4983
 *
 
4984
 **********************************************************************/
 
4985
 
 
4986
int
 
4987
ipmi_sensor_set_event_enables(ipmi_sensor_t         *sensor,
 
4988
                              ipmi_event_state_t    *states,
 
4989
                              ipmi_sensor_done_cb   done,
 
4990
                              void                  *cb_data)
 
4991
{
 
4992
    if (sensor->destroyed)
 
4993
        return ECANCELED;
 
4994
      
 
4995
    CHECK_SENSOR_LOCK(sensor);
 
4996
 
 
4997
    if (!sensor->cbs.ipmi_sensor_set_event_enables)
 
4998
        return ENOSYS;
 
4999
    return sensor->cbs.ipmi_sensor_set_event_enables(sensor,
 
5000
                                                     states,
 
5001
                                                     done,
 
5002
                                                     cb_data);
 
5003
}
 
5004
 
 
5005
int
 
5006
ipmi_sensor_enable_events(ipmi_sensor_t         *sensor,
 
5007
                          ipmi_event_state_t    *states,
 
5008
                          ipmi_sensor_done_cb   done,
 
5009
                          void                  *cb_data)
 
5010
{
 
5011
    if (sensor->destroyed)
 
5012
        return ECANCELED;
 
5013
      
 
5014
    CHECK_SENSOR_LOCK(sensor);
 
5015
 
 
5016
    if (!sensor->cbs.ipmi_sensor_enable_events)
 
5017
        return ENOSYS;
 
5018
    return sensor->cbs.ipmi_sensor_enable_events(sensor,
 
5019
                                                 states,
 
5020
                                                 done,
 
5021
                                                 cb_data);
 
5022
}
 
5023
 
 
5024
int
 
5025
ipmi_sensor_disable_events(ipmi_sensor_t         *sensor,
 
5026
                           ipmi_event_state_t    *states,
 
5027
                           ipmi_sensor_done_cb   done,
 
5028
                           void                  *cb_data)
 
5029
{
 
5030
    if (sensor->destroyed)
 
5031
        return ECANCELED;
 
5032
      
 
5033
    CHECK_SENSOR_LOCK(sensor);
 
5034
 
 
5035
    if (!sensor->cbs.ipmi_sensor_disable_events)
 
5036
        return ENOSYS;
 
5037
    return sensor->cbs.ipmi_sensor_disable_events(sensor,
 
5038
                                                  states,
 
5039
                                                  done,
 
5040
                                                  cb_data);
 
5041
}
 
5042
 
 
5043
int
 
5044
ipmi_sensor_rearm(ipmi_sensor_t       *sensor,
 
5045
                  int                 global_enable,
 
5046
                  ipmi_event_state_t  *state,
 
5047
                  ipmi_sensor_done_cb done,
 
5048
                  void                *cb_data)
 
5049
{
 
5050
    if (sensor->destroyed)
 
5051
        return ECANCELED;
 
5052
      
 
5053
    CHECK_SENSOR_LOCK(sensor);
 
5054
 
 
5055
    if (!sensor->cbs.ipmi_sensor_rearm)
 
5056
        return ENOSYS;
 
5057
    return sensor->cbs.ipmi_sensor_rearm(sensor,
 
5058
                                         global_enable,
 
5059
                                         state,
 
5060
                                         done,
 
5061
                                         cb_data);
 
5062
}
 
5063
 
 
5064
int
 
5065
ipmi_sensor_get_event_enables(ipmi_sensor_t                *sensor,
 
5066
                              ipmi_sensor_event_enables_cb done,
 
5067
                              void                         *cb_data)
 
5068
{
 
5069
    if (sensor->destroyed)
 
5070
        return ECANCELED;
 
5071
      
 
5072
    CHECK_SENSOR_LOCK(sensor);
 
5073
 
 
5074
    if (!sensor->cbs.ipmi_sensor_get_event_enables)
 
5075
        return ENOSYS;
 
5076
    return sensor->cbs.ipmi_sensor_get_event_enables(sensor,
 
5077
                                                     done,
 
5078
                                                     cb_data);
 
5079
}
 
5080
 
 
5081
int
 
5082
ipmi_sensor_get_hysteresis(ipmi_sensor_t             *sensor,
 
5083
                           ipmi_sensor_hysteresis_cb done,
 
5084
                           void                      *cb_data)
 
5085
{
 
5086
    if (sensor->destroyed)
 
5087
        return ECANCELED;
 
5088
      
 
5089
    CHECK_SENSOR_LOCK(sensor);
 
5090
 
 
5091
    if (!sensor->cbs.ipmi_sensor_get_hysteresis)
 
5092
        return ENOSYS;
 
5093
    return sensor->cbs.ipmi_sensor_get_hysteresis(sensor,
 
5094
                                                  done,
 
5095
                                                  cb_data);
 
5096
}
 
5097
 
 
5098
int
 
5099
ipmi_sensor_set_hysteresis(ipmi_sensor_t       *sensor,
 
5100
                           unsigned int        positive_hysteresis,
 
5101
                           unsigned int        negative_hysteresis,
 
5102
                           ipmi_sensor_done_cb done,
 
5103
                           void                *cb_data)
 
5104
{
 
5105
    if (sensor->destroyed)
 
5106
        return ECANCELED;
 
5107
      
 
5108
    CHECK_SENSOR_LOCK(sensor);
 
5109
 
 
5110
    if (!sensor->cbs.ipmi_sensor_set_hysteresis)
 
5111
        return ENOSYS;
 
5112
    return sensor->cbs.ipmi_sensor_set_hysteresis(sensor,
 
5113
                                                  positive_hysteresis,
 
5114
                                                  negative_hysteresis,
 
5115
                                                  done,
 
5116
                                                  cb_data);
 
5117
}
 
5118
 
 
5119
int
 
5120
ipmi_sensor_get_thresholds(ipmi_sensor_t             *sensor,
 
5121
                           ipmi_sensor_thresholds_cb done,
 
5122
                           void                      *cb_data)
 
5123
{
 
5124
    if (sensor->destroyed)
 
5125
        return ECANCELED;
 
5126
      
 
5127
    CHECK_SENSOR_LOCK(sensor);
 
5128
 
 
5129
    if (!sensor->cbs.ipmi_sensor_get_thresholds)
 
5130
        return ENOSYS;
 
5131
    return sensor->cbs.ipmi_sensor_get_thresholds(sensor, done, cb_data);
 
5132
}
 
5133
 
 
5134
int
 
5135
ipmi_sensor_set_thresholds(ipmi_sensor_t       *sensor,
 
5136
                           ipmi_thresholds_t   *thresholds,
 
5137
                           ipmi_sensor_done_cb done,
 
5138
                           void                *cb_data)
 
5139
{
 
5140
    if (sensor->destroyed)
 
5141
        return ECANCELED;
 
5142
      
 
5143
    CHECK_SENSOR_LOCK(sensor);
 
5144
 
 
5145
    if (!sensor->cbs.ipmi_sensor_set_thresholds)
 
5146
        return ENOSYS;
 
5147
    return sensor->cbs.ipmi_sensor_set_thresholds(sensor, thresholds,
 
5148
                                                  done, cb_data);
 
5149
}
 
5150
 
 
5151
int
 
5152
ipmi_sensor_get_reading(ipmi_sensor_t          *sensor,
 
5153
                        ipmi_sensor_reading_cb done,
 
5154
                        void                   *cb_data)
 
5155
{
 
5156
    if (sensor->destroyed)
 
5157
        return ECANCELED;
 
5158
      
 
5159
    CHECK_SENSOR_LOCK(sensor);
 
5160
 
 
5161
    if (!sensor->cbs.ipmi_sensor_get_reading)
 
5162
        return ENOSYS;
 
5163
    return sensor->cbs.ipmi_sensor_get_reading(sensor, done, cb_data);
 
5164
}
 
5165
 
 
5166
int
 
5167
ipmi_sensor_get_states(ipmi_sensor_t         *sensor,
 
5168
                       ipmi_sensor_states_cb done,
 
5169
                       void                  *cb_data)
 
5170
{
 
5171
    if (sensor->destroyed)
 
5172
        return ECANCELED;
 
5173
      
 
5174
    CHECK_SENSOR_LOCK(sensor);
 
5175
 
 
5176
    if (!sensor->cbs.ipmi_sensor_get_states)
 
5177
        return ENOSYS;
 
5178
    return sensor->cbs.ipmi_sensor_get_states(sensor, done, cb_data);
 
5179
}
 
5180
 
 
5181
const char *
 
5182
ipmi_sensor_reading_name_string(ipmi_sensor_t *sensor, int offset)
 
5183
{
 
5184
    CHECK_SENSOR_LOCK(sensor);
 
5185
 
 
5186
    if (!sensor->cbs.ipmi_sensor_reading_name_string)
 
5187
        return NULL;
 
5188
    return sensor->cbs.ipmi_sensor_reading_name_string(sensor, offset);
 
5189
}
 
5190
 
 
5191
int
 
5192
ipmi_sensor_convert_from_raw(ipmi_sensor_t *sensor,
 
5193
                             int           val,
 
5194
                             double        *result)
 
5195
{
 
5196
    CHECK_SENSOR_LOCK(sensor);
 
5197
 
 
5198
    if (!sensor->cbs.ipmi_sensor_convert_from_raw)
 
5199
        return ENOSYS;
 
5200
    return sensor->cbs.ipmi_sensor_convert_from_raw(sensor, val, result);
 
5201
}
 
5202
 
 
5203
int
 
5204
ipmi_sensor_convert_to_raw(ipmi_sensor_t     *sensor,
 
5205
                           enum ipmi_round_e rounding,
 
5206
                           double            val,
 
5207
                           int               *result)
 
5208
{
 
5209
    CHECK_SENSOR_LOCK(sensor);
 
5210
 
 
5211
    if (!sensor->cbs.ipmi_sensor_convert_to_raw)
 
5212
        return ENOSYS;
 
5213
    return sensor->cbs.ipmi_sensor_convert_to_raw(sensor,
 
5214
                                                  rounding,
 
5215
                                                  val,
 
5216
                                                  result);
 
5217
}
 
5218
 
 
5219
int
 
5220
ipmi_sensor_get_tolerance(ipmi_sensor_t *sensor, int val, double *tolerance)
 
5221
{
 
5222
    CHECK_SENSOR_LOCK(sensor);
 
5223
 
 
5224
    if (!sensor->cbs.ipmi_sensor_get_tolerance)
 
5225
        return ENOSYS;
 
5226
    return sensor->cbs.ipmi_sensor_get_tolerance(sensor, val, tolerance);
 
5227
}
 
5228
 
 
5229
/* Returns accuracy as a percentage value. */
 
5230
int
 
5231
ipmi_sensor_get_accuracy(ipmi_sensor_t *sensor, int val, double *accuracy)
 
5232
{
 
5233
    CHECK_SENSOR_LOCK(sensor);
 
5234
 
 
5235
    if (!sensor->cbs.ipmi_sensor_get_accuracy)
 
5236
        return ENOSYS;
 
5237
    return sensor->cbs.ipmi_sensor_get_accuracy(sensor, val, accuracy);
 
5238
}
 
5239
 
 
5240
 
 
5241
/***********************************************************************
 
5242
 *
 
5243
 * Convenience functions that take ids.
 
5244
 *
 
5245
 **********************************************************************/
 
5246
 
 
5247
typedef struct sensor_id_events_enable_set_s
 
5248
{
 
5249
    ipmi_event_state_t    *states;
 
5250
    ipmi_sensor_done_cb   done;
 
5251
    void                  *cb_data;
 
5252
    int                   rv;
 
5253
} sensor_id_events_enable_set_t;
 
5254
 
 
5255
static void
 
5256
sensor_id_set_event_enables_cb(ipmi_sensor_t *sensor, void *cb_data)
 
5257
{
 
5258
    sensor_id_events_enable_set_t *info = cb_data;
 
5259
 
 
5260
    info->rv = ipmi_sensor_set_event_enables(sensor, info->states,
 
5261
                                             info->done, info->cb_data);
 
5262
}
 
5263
 
 
5264
int
 
5265
ipmi_sensor_id_set_event_enables(ipmi_sensor_id_t      sensor_id,
 
5266
                                 ipmi_event_state_t    *states,
 
5267
                                 ipmi_sensor_done_cb   done,
 
5268
                                 void                  *cb_data)
 
5269
{
 
5270
    sensor_id_events_enable_set_t info;
 
5271
    int                           rv;
 
5272
 
 
5273
    info.states = states;
 
5274
    info.done = done;
 
5275
    info.cb_data = cb_data;
 
5276
    rv = ipmi_sensor_pointer_cb(sensor_id, sensor_id_set_event_enables_cb,
 
5277
                                &info);
 
5278
    if (!rv)
 
5279
        rv = info.rv;
 
5280
    return rv;
 
5281
}
 
5282
 
 
5283
typedef struct sensor_id_events_enable_s
 
5284
{
 
5285
    ipmi_event_state_t    *states;
 
5286
    ipmi_sensor_done_cb   done;
 
5287
    void                  *cb_data;
 
5288
    int                   rv;
 
5289
} sensor_id_events_enable_t;
 
5290
 
 
5291
static void
 
5292
sensor_id_enable_events_cb(ipmi_sensor_t *sensor, void *cb_data)
 
5293
{
 
5294
    sensor_id_events_enable_t *info = cb_data;
 
5295
 
 
5296
    info->rv = ipmi_sensor_enable_events(sensor,
 
5297
                                         info->states,
 
5298
                                         info->done,
 
5299
                                         info->cb_data);
 
5300
}
 
5301
 
 
5302
int
 
5303
ipmi_sensor_id_enable_events(ipmi_sensor_id_t      sensor_id,
 
5304
                             ipmi_event_state_t    *states,
 
5305
                             ipmi_sensor_done_cb   done,
 
5306
                             void                  *cb_data)
 
5307
{
 
5308
    sensor_id_events_enable_t info;
 
5309
    int                       rv;
 
5310
 
 
5311
    info.states = states;
 
5312
    info.done = done;
 
5313
    info.cb_data = cb_data;
 
5314
    rv = ipmi_sensor_pointer_cb(sensor_id, sensor_id_enable_events_cb, &info);
 
5315
    if (!rv)
 
5316
        rv = info.rv;
 
5317
    return rv;
 
5318
}
 
5319
 
 
5320
typedef struct sensor_id_events_disable_s
 
5321
{
 
5322
    ipmi_event_state_t    *states;
 
5323
    ipmi_sensor_done_cb   done;
 
5324
    void                  *cb_data;
 
5325
    int                   rv;
 
5326
} sensor_id_events_disable_t;
 
5327
 
 
5328
static void
 
5329
sensor_id_disable_events_cb(ipmi_sensor_t *sensor, void *cb_data)
 
5330
{
 
5331
    sensor_id_events_disable_t *info = cb_data;
 
5332
 
 
5333
    info->rv = ipmi_sensor_disable_events(sensor,
 
5334
                                          info->states,
 
5335
                                          info->done,
 
5336
                                          info->cb_data);
 
5337
}
 
5338
 
 
5339
int
 
5340
ipmi_sensor_id_disable_events(ipmi_sensor_id_t      sensor_id,
 
5341
                              ipmi_event_state_t    *states,
 
5342
                              ipmi_sensor_done_cb   done,
 
5343
                              void                  *cb_data)
 
5344
{
 
5345
    sensor_id_events_enable_t info;
 
5346
    int                       rv;
 
5347
 
 
5348
    info.states = states;
 
5349
    info.done = done;
 
5350
    info.cb_data = cb_data;
 
5351
    rv = ipmi_sensor_pointer_cb(sensor_id, sensor_id_disable_events_cb, &info);
 
5352
    if (!rv)
 
5353
        rv = info.rv;
 
5354
    return rv;
 
5355
}
 
5356
 
 
5357
typedef struct sensor_id_events_enable_get_s
 
5358
{
 
5359
    ipmi_sensor_event_enables_cb done;
 
5360
    void                         *cb_data;
 
5361
    int                          rv;
 
5362
} sensor_id_events_enable_get_t;
 
5363
 
 
5364
static void
 
5365
sensor_id_get_event_enables_cb(ipmi_sensor_t *sensor, void *cb_data)
 
5366
{
 
5367
    sensor_id_events_enable_get_t *info = cb_data;
 
5368
 
 
5369
    info->rv = ipmi_sensor_get_event_enables(sensor,
 
5370
                                             info->done,
 
5371
                                             info->cb_data);
 
5372
}
 
5373
 
 
5374
int
 
5375
ipmi_sensor_id_get_event_enables(ipmi_sensor_id_t             sensor_id,
 
5376
                                 ipmi_sensor_event_enables_cb done,
 
5377
                                 void                         *cb_data)
 
5378
{
 
5379
    sensor_id_events_enable_get_t info;
 
5380
    int                           rv;
 
5381
 
 
5382
    info.done = done;
 
5383
    info.cb_data = cb_data;
 
5384
    rv = ipmi_sensor_pointer_cb(sensor_id, sensor_id_get_event_enables_cb,
 
5385
                                &info);
 
5386
    if (!rv)
 
5387
        rv = info.rv;
 
5388
    return rv;
 
5389
}
 
5390
 
 
5391
typedef struct sensor_id_rearm_s
 
5392
{
 
5393
    int                 global_enable;
 
5394
    ipmi_event_state_t  *state;
 
5395
    ipmi_sensor_done_cb done;
 
5396
    void                *cb_data;
 
5397
    int                 rv;
 
5398
} sensor_id_rearm_t;
 
5399
 
 
5400
static void
 
5401
sensor_id_rearm_cb(ipmi_sensor_t *sensor, void *cb_data)
 
5402
{
 
5403
    sensor_id_rearm_t *info = cb_data;
 
5404
 
 
5405
    info->rv = ipmi_sensor_rearm(sensor,
 
5406
                                 info->global_enable,
 
5407
                                 info->state,
 
5408
                                 info->done,
 
5409
                                 info->cb_data);
 
5410
}
 
5411
 
 
5412
int
 
5413
ipmi_sensor_id_rearm(ipmi_sensor_id_t    sensor_id,
 
5414
                     int                 global_enable,
 
5415
                     ipmi_event_state_t  *state,
 
5416
                     ipmi_sensor_done_cb done,
 
5417
                     void                *cb_data)
 
5418
{
 
5419
    sensor_id_rearm_t info;
 
5420
    int               rv;
 
5421
 
 
5422
    info.global_enable = global_enable;
 
5423
    info.state = state;
 
5424
    info.done = done;
 
5425
    info.cb_data = cb_data;
 
5426
    rv = ipmi_sensor_pointer_cb(sensor_id, sensor_id_rearm_cb, &info);
 
5427
    if (!rv)
 
5428
        rv = info.rv;
 
5429
    return rv;
 
5430
}
 
5431
 
 
5432
typedef struct sensor_id_get_hysteresis_s
 
5433
{
 
5434
    ipmi_sensor_hysteresis_cb done;
 
5435
    void                      *cb_data;
 
5436
    int                       rv;
 
5437
} sensor_id_get_hysteresis_t;
 
5438
 
 
5439
static void
 
5440
sensor_id_get_hysteresis_cb(ipmi_sensor_t *sensor, void *cb_data)
 
5441
{
 
5442
    sensor_id_get_hysteresis_t *info = cb_data;
 
5443
 
 
5444
    info->rv = ipmi_sensor_get_hysteresis(sensor,
 
5445
                                          info->done,
 
5446
                                          info->cb_data);
 
5447
}
 
5448
 
 
5449
int
 
5450
ipmi_sensor_id_get_hysteresis(ipmi_sensor_id_t          sensor_id,
 
5451
                              ipmi_sensor_hysteresis_cb done,
 
5452
                              void                      *cb_data)
 
5453
{
 
5454
    sensor_id_get_hysteresis_t info;
 
5455
    int                        rv;
 
5456
 
 
5457
    info.done = done;
 
5458
    info.cb_data = cb_data;
 
5459
    rv = ipmi_sensor_pointer_cb(sensor_id, sensor_id_get_hysteresis_cb, &info);
 
5460
    if (!rv)
 
5461
        rv = info.rv;
 
5462
    return rv;
 
5463
}
 
5464
 
 
5465
typedef struct sensor_id_set_hysteresis_s
 
5466
{
 
5467
    unsigned int        positive_hysteresis;
 
5468
    unsigned int        negative_hysteresis;
 
5469
    ipmi_sensor_done_cb done;
 
5470
    void                *cb_data;
 
5471
    int                 rv;
 
5472
} sensor_id_set_hysteresis_t;
 
5473
 
 
5474
static void
 
5475
sensor_id_set_hysteresis_cb(ipmi_sensor_t *sensor, void *cb_data)
 
5476
{
 
5477
    sensor_id_set_hysteresis_t *info = cb_data;
 
5478
 
 
5479
    info->rv = ipmi_sensor_set_hysteresis(sensor,
 
5480
                                          info->positive_hysteresis,
 
5481
                                          info->negative_hysteresis,
 
5482
                                          info->done,
 
5483
                                          info->cb_data);
 
5484
}
 
5485
 
 
5486
int
 
5487
ipmi_sensor_id_set_hysteresis(ipmi_sensor_id_t    sensor_id,
 
5488
                              unsigned int        positive_hysteresis,
 
5489
                              unsigned int        negative_hysteresis,
 
5490
                              ipmi_sensor_done_cb done,
 
5491
                              void                *cb_data)
 
5492
{
 
5493
    sensor_id_set_hysteresis_t info;
 
5494
    int                        rv;
 
5495
 
 
5496
    info.positive_hysteresis = positive_hysteresis;
 
5497
    info.negative_hysteresis = negative_hysteresis;
 
5498
    info.done = done;
 
5499
    info.cb_data = cb_data;
 
5500
    rv = ipmi_sensor_pointer_cb(sensor_id, sensor_id_set_hysteresis_cb, &info);
 
5501
    if (!rv)
 
5502
        rv = info.rv;
 
5503
    return rv;
 
5504
}
 
5505
 
 
5506
typedef struct sensor_id_thresholds_set_s
 
5507
{
 
5508
    ipmi_thresholds_t   *thresholds;
 
5509
    ipmi_sensor_done_cb done;
 
5510
    void                *cb_data;
 
5511
    int                 rv;
 
5512
} sensor_id_thresholds_set_t;
 
5513
 
 
5514
static void
 
5515
sensor_id_set_thresholds_cb(ipmi_sensor_t *sensor, void *cb_data)
 
5516
{
 
5517
    sensor_id_thresholds_set_t *info = cb_data;
 
5518
 
 
5519
    info->rv = ipmi_sensor_set_thresholds(sensor,
 
5520
                                          info->thresholds,
 
5521
                                          info->done,
 
5522
                                          info->cb_data);
 
5523
}
 
5524
 
 
5525
int
 
5526
ipmi_sensor_id_set_thresholds(ipmi_sensor_id_t    sensor_id,
 
5527
                              ipmi_thresholds_t   *thresholds,
 
5528
                              ipmi_sensor_done_cb done,
 
5529
                              void                *cb_data)
 
5530
{
 
5531
    sensor_id_thresholds_set_t info;
 
5532
    int               rv;
 
5533
 
 
5534
    info.thresholds = thresholds;
 
5535
    info.done = done;
 
5536
    info.cb_data = cb_data;
 
5537
    rv = ipmi_sensor_pointer_cb(sensor_id, sensor_id_set_thresholds_cb, &info);
 
5538
    if (!rv)
 
5539
        rv = info.rv;
 
5540
    return rv;
 
5541
}
 
5542
 
 
5543
typedef struct sensor_id_thresholds_get_s
 
5544
{
 
5545
    ipmi_sensor_thresholds_cb done;
 
5546
    void                      *cb_data;
 
5547
    int                       rv;
 
5548
} sensor_id_thresholds_get_t;
 
5549
 
 
5550
static void
 
5551
sensor_id_get_thresholds_cb(ipmi_sensor_t *sensor, void *cb_data)
 
5552
{
 
5553
    sensor_id_thresholds_get_t *info = cb_data;
 
5554
 
 
5555
    info->rv = ipmi_sensor_get_thresholds(sensor,
 
5556
                                          info->done,
 
5557
                                          info->cb_data);
 
5558
}
 
5559
 
 
5560
int
 
5561
ipmi_sensor_id_get_thresholds(ipmi_sensor_id_t          sensor_id,
 
5562
                              ipmi_sensor_thresholds_cb done,
 
5563
                              void                      *cb_data)
 
5564
{
 
5565
    sensor_id_thresholds_get_t info;
 
5566
    int                        rv;
 
5567
 
 
5568
    info.done = done;
 
5569
    info.cb_data = cb_data;
 
5570
    rv = ipmi_sensor_pointer_cb(sensor_id, sensor_id_get_thresholds_cb, &info);
 
5571
    if (!rv)
 
5572
        rv = info.rv;
 
5573
    return rv;
 
5574
}
 
5575
 
 
5576
typedef struct sensor_id_reading_get_s
 
5577
{
 
5578
    ipmi_sensor_reading_cb done;
 
5579
    void                   *cb_data;
 
5580
    int                    rv;
 
5581
} sensor_id_reading_get_t;
 
5582
 
 
5583
static void
 
5584
sensor_id_get_reading_cb(ipmi_sensor_t *sensor, void *cb_data)
 
5585
{
 
5586
    sensor_id_reading_get_t *info = cb_data;
 
5587
    
 
5588
    info->rv = ipmi_sensor_get_reading(sensor,
 
5589
                                       info->done,
 
5590
                                       info->cb_data);
 
5591
}
 
5592
 
 
5593
int
 
5594
ipmi_sensor_id_get_reading(ipmi_sensor_id_t       sensor_id,
 
5595
                           ipmi_sensor_reading_cb done,
 
5596
                           void                   *cb_data)
 
5597
{
 
5598
    sensor_id_reading_get_t info;
 
5599
    int                     rv;
 
5600
 
 
5601
    info.done = done;
 
5602
    info.cb_data = cb_data;
 
5603
    rv = ipmi_sensor_pointer_cb(sensor_id, sensor_id_get_reading_cb, &info);
 
5604
    if (!rv)
 
5605
        rv = info.rv;
 
5606
    return rv;
 
5607
}
 
5608
 
 
5609
typedef struct sensor_id_states_get_s
 
5610
{
 
5611
    ipmi_sensor_states_cb done;
 
5612
    void                  *cb_data;
 
5613
    int                   rv;
 
5614
} sensor_id_states_get_t;
 
5615
 
 
5616
static void
 
5617
sensor_id_get_states_cb(ipmi_sensor_t *sensor, void *cb_data)
 
5618
{
 
5619
    sensor_id_states_get_t *info = cb_data;
 
5620
 
 
5621
    info->rv = ipmi_sensor_get_states(sensor,
 
5622
                                      info->done,
 
5623
                                      info->cb_data);
 
5624
}
 
5625
 
 
5626
int
 
5627
ipmi_sensor_id_get_states(ipmi_sensor_id_t      sensor_id,
 
5628
                          ipmi_sensor_states_cb done,
 
5629
                          void                  *cb_data)
 
5630
{
 
5631
    sensor_id_states_get_t info;
 
5632
    int                    rv;
 
5633
 
 
5634
    info.done = done;
 
5635
    info.cb_data = cb_data;
 
5636
    rv = ipmi_sensor_pointer_cb(sensor_id, sensor_id_get_states_cb, &info);
 
5637
    if (!rv)
 
5638
        rv = info.rv;
 
5639
    return rv;
 
5640
}
 
5641
 
 
5642
 
 
5643
#ifdef IPMI_CHECK_LOCKS
 
5644
void
 
5645
__ipmi_check_sensor_lock(ipmi_sensor_t *sensor)
 
5646
{
 
5647
    if (!sensor)
 
5648
        return;
 
5649
 
 
5650
    if (!DEBUG_LOCKS)
 
5651
        return;
 
5652
 
 
5653
    CHECK_ENTITY_LOCK(sensor->entity);
 
5654
    CHECK_MC_LOCK(sensor->mc);
 
5655
 
 
5656
    if (sensor->usecount == 0)
 
5657
        ipmi_report_lock_error(ipmi_domain_get_os_hnd(sensor->domain),
 
5658
                               "sensor not locked when it should have been");
 
5659
}
 
5660
#endif
 
5661
 
 
5662
/***********************************************************************
 
5663
 *
 
5664
 * Cruft
 
5665
 *
 
5666
 **********************************************************************/
 
5667
 
 
5668
int
 
5669
ipmi_sensor_threshold_assertion_event_supported(
 
5670
    ipmi_sensor_t               *sensor,
 
5671
    enum ipmi_thresh_e          event,
 
5672
    enum ipmi_event_value_dir_e dir,
 
5673
    int                         *val)
 
5674
{
 
5675
    int idx;
 
5676
 
 
5677
    CHECK_SENSOR_LOCK(sensor);
 
5678
 
 
5679
    if (sensor->event_reading_type != IPMI_EVENT_READING_TYPE_THRESHOLD)
 
5680
        /* Not a threshold sensor, it doesn't have readings. */
 
5681
        return ENOSYS;
 
5682
 
 
5683
    idx = (event * 2) + dir;
 
5684
    if (idx > 11)
 
5685
        return EINVAL;
 
5686
 
 
5687
    *val = sensor->mask1[idx];
 
5688
    return 0;
 
5689
}
 
5690
 
 
5691
int
 
5692
ipmi_sensor_threshold_deassertion_event_supported(
 
5693
    ipmi_sensor_t               *sensor,
 
5694
    enum ipmi_thresh_e          event,
 
5695
    enum ipmi_event_value_dir_e dir,
 
5696
    int                         *val)
 
5697
{
 
5698
    int idx;
 
5699
 
 
5700
    CHECK_SENSOR_LOCK(sensor);
 
5701
 
 
5702
    if (sensor->event_reading_type != IPMI_EVENT_READING_TYPE_THRESHOLD)
 
5703
        /* Not a threshold sensor, it doesn't have readings. */
 
5704
        return ENOSYS;
 
5705
 
 
5706
    idx = (event * 2) + dir;
 
5707
    if (idx > 11)
 
5708
        return 0;
 
5709
 
 
5710
    *val = sensor->mask2[idx];
 
5711
    return 0;
 
5712
}
 
5713
 
 
5714
int
 
5715
ipmi_sensor_discrete_assertion_event_supported(ipmi_sensor_t *sensor,
 
5716
                                               int           event,
 
5717
                                               int           *val)
 
5718
{
 
5719
    CHECK_SENSOR_LOCK(sensor);
 
5720
 
 
5721
    if (sensor->event_reading_type == IPMI_EVENT_READING_TYPE_THRESHOLD)
 
5722
        /* A threshold sensor, it doesn't have events. */
 
5723
        return ENOSYS;
 
5724
 
 
5725
    if (event > 14)
 
5726
        return EINVAL;
 
5727
 
 
5728
    *val = sensor->mask1[event];
 
5729
    return 0;
 
5730
}
 
5731
 
 
5732
int
 
5733
ipmi_sensor_discrete_deassertion_event_supported(ipmi_sensor_t *sensor,
 
5734
                                                 int           event,
 
5735
                                                 int           *val)
 
5736
{
 
5737
    CHECK_SENSOR_LOCK(sensor);
 
5738
 
 
5739
    if (sensor->event_reading_type == IPMI_EVENT_READING_TYPE_THRESHOLD)
 
5740
        /* A threshold sensor, it doesn't have events. */
 
5741
        return ENOSYS;
 
5742
 
 
5743
    if (event > 14)
 
5744
        return EINVAL;
 
5745
 
 
5746
    *val = sensor->mask2[event];
 
5747
    return 0;
 
5748
}
 
5749
 
 
5750
int
 
5751
ipmi_sensor_events_enable_get(ipmi_sensor_t                *sensor,
 
5752
                              ipmi_sensor_event_enables_cb done,
 
5753
                              void                         *cb_data)
 
5754
{
 
5755
    return ipmi_sensor_get_event_enables(sensor, done, cb_data);
 
5756
}
 
5757
 
 
5758
int
 
5759
ipmi_sensor_events_disable(ipmi_sensor_t         *sensor,
 
5760
                           ipmi_event_state_t    *states,
 
5761
                           ipmi_sensor_done_cb   done,
 
5762
                           void                  *cb_data)
 
5763
{
 
5764
    return ipmi_sensor_disable_events(sensor, states, done, cb_data);
 
5765
}
 
5766
 
 
5767
int
 
5768
ipmi_sensor_events_enable(ipmi_sensor_t         *sensor,
 
5769
                          ipmi_event_state_t    *states,
 
5770
                          ipmi_sensor_done_cb   done,
 
5771
                          void                  *cb_data)
 
5772
{
 
5773
    return ipmi_sensor_enable_events(sensor, states, done, cb_data);
 
5774
}
 
5775
 
 
5776
int ipmi_sensor_events_enable_set(ipmi_sensor_t         *sensor,
 
5777
                                  ipmi_event_state_t    *states,
 
5778
                                  ipmi_sensor_done_cb   done,
 
5779
                                  void                  *cb_data)
 
5780
{
 
5781
    return ipmi_sensor_set_event_enables(sensor, states, done, cb_data);
 
5782
}
 
5783
 
 
5784
int
 
5785
ipmi_sensor_id_events_enable_set(ipmi_sensor_id_t      sensor_id,
 
5786
                                 ipmi_event_state_t    *states,
 
5787
                                 ipmi_sensor_done_cb   done,
 
5788
                                 void                  *cb_data)
 
5789
{
 
5790
    return ipmi_sensor_id_set_event_enables(sensor_id, states, done, cb_data);
 
5791
}
 
5792
 
 
5793
int
 
5794
ipmi_sensor_id_events_enable(ipmi_sensor_id_t      sensor_id,
 
5795
                             ipmi_event_state_t    *states,
 
5796
                             ipmi_sensor_done_cb   done,
 
5797
                             void                  *cb_data)
 
5798
{
 
5799
    return ipmi_sensor_id_enable_events(sensor_id, states, done, cb_data);
 
5800
}
 
5801
 
 
5802
int
 
5803
ipmi_sensor_id_events_disable(ipmi_sensor_id_t      sensor_id,
 
5804
                              ipmi_event_state_t    *states,
 
5805
                              ipmi_sensor_done_cb   done,
 
5806
                              void                  *cb_data)
 
5807
{
 
5808
    return ipmi_sensor_id_disable_events(sensor_id, states, done, cb_data);
 
5809
}
 
5810
 
 
5811
int
 
5812
ipmi_sensor_id_events_enable_get(ipmi_sensor_id_t             sensor_id,
 
5813
                                 ipmi_sensor_event_enables_cb done,
 
5814
                                 void                         *cb_data)
 
5815
{
 
5816
    return ipmi_sensor_id_get_event_enables(sensor_id, done, cb_data);
 
5817
}
 
5818
 
 
5819
int
 
5820
ipmi_states_get(ipmi_sensor_t         *sensor,
 
5821
                ipmi_sensor_states_cb done,
 
5822
                void                  *cb_data)
 
5823
{
 
5824
    return ipmi_sensor_get_states(sensor, done, cb_data);
 
5825
}
 
5826
 
 
5827
int
 
5828
ipmi_reading_get(ipmi_sensor_t          *sensor,
 
5829
                 ipmi_sensor_reading_cb done,
 
5830
                 void                   *cb_data)
 
5831
{
 
5832
    return ipmi_sensor_get_reading(sensor, done, cb_data);
 
5833
}
 
5834
 
 
5835
int
 
5836
ipmi_thresholds_set(ipmi_sensor_t       *sensor,
 
5837
                    ipmi_thresholds_t   *thresholds,
 
5838
                    ipmi_sensor_done_cb done,
 
5839
                    void                *cb_data)
 
5840
{
 
5841
    return ipmi_sensor_set_thresholds(sensor, thresholds, done, cb_data);
 
5842
}
 
5843
 
 
5844
int
 
5845
ipmi_thresholds_get(ipmi_sensor_t             *sensor,
 
5846
                    ipmi_sensor_thresholds_cb done,
 
5847
                    void                      *cb_data)
 
5848
{
 
5849
    return ipmi_sensor_get_thresholds(sensor, done, cb_data);
 
5850
}
 
5851
 
 
5852
int
 
5853
ipmi_sensor_id_thresholds_set(ipmi_sensor_id_t    sensor_id,
 
5854
                              ipmi_thresholds_t   *thresholds,
 
5855
                              ipmi_sensor_done_cb done,
 
5856
                              void                *cb_data)
 
5857
{
 
5858
    return ipmi_sensor_id_set_thresholds(sensor_id, thresholds, done, cb_data);
 
5859
}
 
5860
 
 
5861
int
 
5862
ipmi_sensor_id_thresholds_get(ipmi_sensor_id_t          sensor_id,
 
5863
                              ipmi_sensor_thresholds_cb done,
 
5864
                              void                      *cb_data)
 
5865
{
 
5866
    return ipmi_sensor_id_get_thresholds(sensor_id, done, cb_data);
 
5867
}
 
5868
 
 
5869
int
 
5870
ipmi_sensor_id_reading_get(ipmi_sensor_id_t       sensor_id,
 
5871
                           ipmi_sensor_reading_cb done,
 
5872
                           void                   *cb_data)
 
5873
{
 
5874
    return ipmi_sensor_id_get_reading(sensor_id, done, cb_data);
 
5875
}
 
5876
 
 
5877
int
 
5878
ipmi_sensor_id_states_get(ipmi_sensor_id_t      sensor_id,
 
5879
                          ipmi_sensor_states_cb done,
 
5880
                          void                  *cb_data)
 
5881
{
 
5882
    return ipmi_sensor_id_get_states(sensor_id, done, cb_data);
 
5883
}
 
5884
 
 
5885
int
 
5886
ipmi_discrete_event_readable(ipmi_sensor_t *sensor,
 
5887
                             int           event,
 
5888
                             int           *val)
 
5889
{
 
5890
    CHECK_SENSOR_LOCK(sensor);
 
5891
 
 
5892
    if (sensor->event_reading_type == IPMI_EVENT_READING_TYPE_THRESHOLD)
 
5893
        /* A threshold sensor, it doesn't have events. */
 
5894
        return ENOSYS;
 
5895
 
 
5896
    if (event > 14)
 
5897
        return EINVAL;
 
5898
 
 
5899
    *val = sensor->mask3[event];
 
5900
    return 0;
 
5901
}