1/* $NetBSD: ipmi.c,v 1.64 2016/07/07 06:55:40 msaitoh Exp $ */
2
3/*
4 * Copyright (c) 2006 Manuel Bouyer.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 *
26 */
27
28/*
29 * Copyright (c) 2005 Jordan Hargrave
30 * All rights reserved.
31 *
32 * Redistribution and use in source and binary forms, with or without
33 * modification, are permitted provided that the following conditions
34 * are met:
35 * 1. Redistributions of source code must retain the above copyright
36 * notice, this list of conditions and the following disclaimer.
37 * 2. Redistributions in binary form must reproduce the above copyright
38 * notice, this list of conditions and the following disclaimer in the
39 * documentation and/or other materials provided with the distribution.
40 *
41 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
42 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR
45 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51 * SUCH DAMAGE.
52 */
53
54#include <sys/cdefs.h>
55__KERNEL_RCSID(0, "$NetBSD: ipmi.c,v 1.64 2016/07/07 06:55:40 msaitoh Exp $");
56
57#include <sys/types.h>
58#include <sys/param.h>
59#include <sys/systm.h>
60#include <sys/kernel.h>
61#include <sys/device.h>
62#include <sys/extent.h>
63#include <sys/callout.h>
64#include <sys/envsys.h>
65#include <sys/malloc.h>
66#include <sys/kthread.h>
67#include <sys/bus.h>
68#include <sys/intr.h>
69
70#include <x86/smbiosvar.h>
71
72#include <dev/isa/isareg.h>
73#include <dev/isa/isavar.h>
74
75#include <x86/ipmivar.h>
76
77#include <uvm/uvm_extern.h>
78
79struct ipmi_sensor {
80 uint8_t *i_sdr;
81 int i_num;
82 int i_stype;
83 int i_etype;
84 char i_envdesc[64];
85 int i_envtype; /* envsys compatible type */
86 int i_envnum; /* envsys index */
87 sysmon_envsys_lim_t i_limits, i_deflims;
88 uint32_t i_props, i_defprops;
89 SLIST_ENTRY(ipmi_sensor) i_list;
90 int32_t i_prevval; /* feed rnd source on change */
91};
92
93int ipmi_nintr;
94int ipmi_dbg = 0;
95int ipmi_enabled = 0;
96
97#define SENSOR_REFRESH_RATE (hz / 2)
98
99#define SMBIOS_TYPE_IPMI 0x26
100
101/*
102 * Format of SMBIOS IPMI Flags
103 *
104 * bit0: interrupt trigger mode (1=level, 0=edge)
105 * bit1: interrupt polarity (1=active high, 0=active low)
106 * bit2: reserved
107 * bit3: address LSB (1=odd,0=even)
108 * bit4: interrupt (1=specified, 0=not specified)
109 * bit5: reserved
110 * bit6/7: register spacing (1,4,2,err)
111 */
112#define SMIPMI_FLAG_IRQLVL (1L << 0)
113#define SMIPMI_FLAG_IRQEN (1L << 3)
114#define SMIPMI_FLAG_ODDOFFSET (1L << 4)
115#define SMIPMI_FLAG_IFSPACING(x) (((x)>>6)&0x3)
116#define IPMI_IOSPACING_BYTE 0
117#define IPMI_IOSPACING_WORD 2
118#define IPMI_IOSPACING_DWORD 1
119
120#define IPMI_BTMSG_LEN 0
121#define IPMI_BTMSG_NFLN 1
122#define IPMI_BTMSG_SEQ 2
123#define IPMI_BTMSG_CMD 3
124#define IPMI_BTMSG_CCODE 4
125#define IPMI_BTMSG_DATASND 4
126#define IPMI_BTMSG_DATARCV 5
127
128#define IPMI_MSG_NFLN 0
129#define IPMI_MSG_CMD 1
130#define IPMI_MSG_CCODE 2
131#define IPMI_MSG_DATASND 2
132#define IPMI_MSG_DATARCV 3
133
134#define IPMI_SENSOR_TYPE_TEMP 0x0101
135#define IPMI_SENSOR_TYPE_VOLT 0x0102
136#define IPMI_SENSOR_TYPE_FAN 0x0104
137#define IPMI_SENSOR_TYPE_INTRUSION 0x6F05
138#define IPMI_SENSOR_TYPE_PWRSUPPLY 0x6F08
139
140#define IPMI_NAME_UNICODE 0x00
141#define IPMI_NAME_BCDPLUS 0x01
142#define IPMI_NAME_ASCII6BIT 0x02
143#define IPMI_NAME_ASCII8BIT 0x03
144
145#define IPMI_ENTITY_PWRSUPPLY 0x0A
146
147#define IPMI_SENSOR_SCANNING_ENABLED (1L << 6)
148#define IPMI_SENSOR_UNAVAILABLE (1L << 5)
149#define IPMI_INVALID_SENSOR_P(x) \
150 (((x) & (IPMI_SENSOR_SCANNING_ENABLED|IPMI_SENSOR_UNAVAILABLE)) \
151 != IPMI_SENSOR_SCANNING_ENABLED)
152
153#define IPMI_SDR_TYPEFULL 1
154#define IPMI_SDR_TYPECOMPACT 2
155
156#define byteof(x) ((x) >> 3)
157#define bitof(x) (1L << ((x) & 0x7))
158#define TB(b,m) (data[2+byteof(b)] & bitof(b))
159
160#define dbg_printf(lvl, fmt...) \
161 if (ipmi_dbg >= lvl) \
162 printf(fmt);
163#define dbg_dump(lvl, msg, len, buf) \
164 if (len && ipmi_dbg >= lvl) \
165 dumpb(msg, len, (const uint8_t *)(buf));
166
167long signextend(unsigned long, int);
168
169SLIST_HEAD(ipmi_sensors_head, ipmi_sensor);
170struct ipmi_sensors_head ipmi_sensor_list =
171 SLIST_HEAD_INITIALIZER(&ipmi_sensor_list);
172
173void dumpb(const char *, int, const uint8_t *);
174
175int read_sensor(struct ipmi_softc *, struct ipmi_sensor *);
176int add_sdr_sensor(struct ipmi_softc *, uint8_t *);
177int get_sdr_partial(struct ipmi_softc *, uint16_t, uint16_t,
178 uint8_t, uint8_t, void *, uint16_t *);
179int get_sdr(struct ipmi_softc *, uint16_t, uint16_t *);
180
181char *ipmi_buf_acquire(struct ipmi_softc *, size_t);
182void ipmi_buf_release(struct ipmi_softc *, char *);
183int ipmi_sendcmd(struct ipmi_softc *, int, int, int, int, int, const void*);
184int ipmi_recvcmd(struct ipmi_softc *, int, int *, void *);
185void ipmi_delay(struct ipmi_softc *, int);
186
187int ipmi_watchdog_setmode(struct sysmon_wdog *);
188int ipmi_watchdog_tickle(struct sysmon_wdog *);
189void ipmi_dotickle(struct ipmi_softc *);
190
191int ipmi_intr(void *);
192int ipmi_match(device_t, cfdata_t, void *);
193void ipmi_attach(device_t, device_t, void *);
194static int ipmi_detach(device_t, int);
195
196long ipmi_convert(uint8_t, struct sdrtype1 *, long);
197void ipmi_sensor_name(char *, int, uint8_t, uint8_t *);
198
199/* BMC Helper Functions */
200uint8_t bmc_read(struct ipmi_softc *, int);
201void bmc_write(struct ipmi_softc *, int, uint8_t);
202int bmc_io_wait(struct ipmi_softc *, int, uint8_t, uint8_t, const char *);
203int bmc_io_wait_spin(struct ipmi_softc *, int, uint8_t, uint8_t);
204int bmc_io_wait_sleep(struct ipmi_softc *, int, uint8_t, uint8_t);
205
206void *bt_buildmsg(struct ipmi_softc *, int, int, int, const void *, int *);
207void *cmn_buildmsg(struct ipmi_softc *, int, int, int, const void *, int *);
208
209int getbits(uint8_t *, int, int);
210int ipmi_sensor_type(int, int, int);
211
212void ipmi_smbios_probe(struct smbios_ipmi *, struct ipmi_attach_args *);
213void ipmi_refresh_sensors(struct ipmi_softc *);
214int ipmi_map_regs(struct ipmi_softc *, struct ipmi_attach_args *);
215void ipmi_unmap_regs(struct ipmi_softc *);
216
217void *scan_sig(long, long, int, int, const void *);
218
219int32_t ipmi_convert_sensor(uint8_t *, struct ipmi_sensor *);
220void ipmi_set_limits(struct sysmon_envsys *, envsys_data_t *,
221 sysmon_envsys_lim_t *, uint32_t *);
222void ipmi_get_limits(struct sysmon_envsys *, envsys_data_t *,
223 sysmon_envsys_lim_t *, uint32_t *);
224void ipmi_get_sensor_limits(struct ipmi_softc *, struct ipmi_sensor *,
225 sysmon_envsys_lim_t *, uint32_t *);
226int ipmi_sensor_status(struct ipmi_softc *, struct ipmi_sensor *,
227 envsys_data_t *, uint8_t *);
228
229int add_child_sensors(struct ipmi_softc *, uint8_t *, int, int, int,
230 int, int, int, const char *);
231
232bool ipmi_suspend(device_t, const pmf_qual_t *);
233
234struct ipmi_if kcs_if = {
235 "KCS",
236 IPMI_IF_KCS_NREGS,
237 cmn_buildmsg,
238 kcs_sendmsg,
239 kcs_recvmsg,
240 kcs_reset,
241 kcs_probe,
242};
243
244struct ipmi_if smic_if = {
245 "SMIC",
246 IPMI_IF_SMIC_NREGS,
247 cmn_buildmsg,
248 smic_sendmsg,
249 smic_recvmsg,
250 smic_reset,
251 smic_probe,
252};
253
254struct ipmi_if bt_if = {
255 "BT",
256 IPMI_IF_BT_NREGS,
257 bt_buildmsg,
258 bt_sendmsg,
259 bt_recvmsg,
260 bt_reset,
261 bt_probe,
262};
263
264struct ipmi_if *ipmi_get_if(int);
265
266struct ipmi_if *
267ipmi_get_if(int iftype)
268{
269 switch (iftype) {
270 case IPMI_IF_KCS:
271 return (&kcs_if);
272 case IPMI_IF_SMIC:
273 return (&smic_if);
274 case IPMI_IF_BT:
275 return (&bt_if);
276 }
277
278 return (NULL);
279}
280
281/*
282 * BMC Helper Functions
283 */
284uint8_t
285bmc_read(struct ipmi_softc *sc, int offset)
286{
287 return (bus_space_read_1(sc->sc_iot, sc->sc_ioh,
288 offset * sc->sc_if_iospacing));
289}
290
291void
292bmc_write(struct ipmi_softc *sc, int offset, uint8_t val)
293{
294 bus_space_write_1(sc->sc_iot, sc->sc_ioh,
295 offset * sc->sc_if_iospacing, val);
296}
297
298int
299bmc_io_wait_sleep(struct ipmi_softc *sc, int offset, uint8_t mask,
300 uint8_t value)
301{
302 int retries;
303 uint8_t v;
304
305 KASSERT(mutex_owned(&sc->sc_cmd_mtx));
306
307 for (retries = 0; retries < sc->sc_max_retries; retries++) {
308 v = bmc_read(sc, offset);
309 if ((v & mask) == value)
310 return v;
311 mutex_enter(&sc->sc_sleep_mtx);
312 cv_timedwait(&sc->sc_cmd_sleep, &sc->sc_sleep_mtx, 1);
313 mutex_exit(&sc->sc_sleep_mtx);
314 }
315 return -1;
316}
317
318int
319bmc_io_wait(struct ipmi_softc *sc, int offset, uint8_t mask, uint8_t value,
320 const char *lbl)
321{
322 int v;
323
324 v = bmc_io_wait_spin(sc, offset, mask, value);
325 if (cold || v != -1)
326 return v;
327
328 return bmc_io_wait_sleep(sc, offset, mask, value);
329}
330
331int
332bmc_io_wait_spin(struct ipmi_softc *sc, int offset, uint8_t mask,
333 uint8_t value)
334{
335 uint8_t v;
336 int count = cold ? 15000 : 500;
337 /* ~us */
338
339 while (count--) {
340 v = bmc_read(sc, offset);
341 if ((v & mask) == value)
342 return v;
343
344 delay(1);
345 }
346
347 return (-1);
348
349}
350
351#define NETFN_LUN(nf,ln) (((nf) << 2) | ((ln) & 0x3))
352
353/*
354 * BT interface
355 */
356#define _BT_CTRL_REG 0
357#define BT_CLR_WR_PTR (1L << 0)
358#define BT_CLR_RD_PTR (1L << 1)
359#define BT_HOST2BMC_ATN (1L << 2)
360#define BT_BMC2HOST_ATN (1L << 3)
361#define BT_EVT_ATN (1L << 4)
362#define BT_HOST_BUSY (1L << 6)
363#define BT_BMC_BUSY (1L << 7)
364
365#define BT_READY (BT_HOST_BUSY|BT_HOST2BMC_ATN|BT_BMC2HOST_ATN)
366
367#define _BT_DATAIN_REG 1
368#define _BT_DATAOUT_REG 1
369
370#define _BT_INTMASK_REG 2
371#define BT_IM_HIRQ_PEND (1L << 1)
372#define BT_IM_SCI_EN (1L << 2)
373#define BT_IM_SMI_EN (1L << 3)
374#define BT_IM_NMI2SMI (1L << 4)
375
376int bt_read(struct ipmi_softc *, int);
377int bt_write(struct ipmi_softc *, int, uint8_t);
378
379int
380bt_read(struct ipmi_softc *sc, int reg)
381{
382 return bmc_read(sc, reg);
383}
384
385int
386bt_write(struct ipmi_softc *sc, int reg, uint8_t data)
387{
388 if (bmc_io_wait(sc, _BT_CTRL_REG, BT_BMC_BUSY, 0, "bt_write") < 0)
389 return (-1);
390
391 bmc_write(sc, reg, data);
392 return (0);
393}
394
395int
396bt_sendmsg(struct ipmi_softc *sc, int len, const uint8_t *data)
397{
398 int i;
399
400 bt_write(sc, _BT_CTRL_REG, BT_CLR_WR_PTR);
401 for (i = 0; i < len; i++)
402 bt_write(sc, _BT_DATAOUT_REG, data[i]);
403
404 bt_write(sc, _BT_CTRL_REG, BT_HOST2BMC_ATN);
405 if (bmc_io_wait(sc, _BT_CTRL_REG, BT_HOST2BMC_ATN | BT_BMC_BUSY, 0,
406 "bt_sendwait") < 0)
407 return (-1);
408
409 return (0);
410}
411
412int
413bt_recvmsg(struct ipmi_softc *sc, int maxlen, int *rxlen, uint8_t *data)
414{
415 uint8_t len, v, i;
416
417 if (bmc_io_wait(sc, _BT_CTRL_REG, BT_BMC2HOST_ATN, BT_BMC2HOST_ATN,
418 "bt_recvwait") < 0)
419 return (-1);
420
421 bt_write(sc, _BT_CTRL_REG, BT_HOST_BUSY);
422 bt_write(sc, _BT_CTRL_REG, BT_BMC2HOST_ATN);
423 bt_write(sc, _BT_CTRL_REG, BT_CLR_RD_PTR);
424 len = bt_read(sc, _BT_DATAIN_REG);
425 for (i = IPMI_BTMSG_NFLN; i <= len; i++) {
426 v = bt_read(sc, _BT_DATAIN_REG);
427 if (i != IPMI_BTMSG_SEQ)
428 *(data++) = v;
429 }
430 bt_write(sc, _BT_CTRL_REG, BT_HOST_BUSY);
431 *rxlen = len - 1;
432
433 return (0);
434}
435
436int
437bt_reset(struct ipmi_softc *sc)
438{
439 return (-1);
440}
441
442int
443bt_probe(struct ipmi_softc *sc)
444{
445 uint8_t rv;
446
447 rv = bmc_read(sc, _BT_CTRL_REG);
448 rv &= BT_HOST_BUSY;
449 rv |= BT_CLR_WR_PTR|BT_CLR_RD_PTR|BT_BMC2HOST_ATN|BT_HOST2BMC_ATN;
450 bmc_write(sc, _BT_CTRL_REG, rv);
451
452 rv = bmc_read(sc, _BT_INTMASK_REG);
453 rv &= BT_IM_SCI_EN|BT_IM_SMI_EN|BT_IM_NMI2SMI;
454 rv |= BT_IM_HIRQ_PEND;
455 bmc_write(sc, _BT_INTMASK_REG, rv);
456
457#if 0
458 printf("bt_probe: %2x\n", v);
459 printf(" WR : %2x\n", v & BT_CLR_WR_PTR);
460 printf(" RD : %2x\n", v & BT_CLR_RD_PTR);
461 printf(" H2B : %2x\n", v & BT_HOST2BMC_ATN);
462 printf(" B2H : %2x\n", v & BT_BMC2HOST_ATN);
463 printf(" EVT : %2x\n", v & BT_EVT_ATN);
464 printf(" HBSY : %2x\n", v & BT_HOST_BUSY);
465 printf(" BBSY : %2x\n", v & BT_BMC_BUSY);
466#endif
467 return (0);
468}
469
470/*
471 * SMIC interface
472 */
473#define _SMIC_DATAIN_REG 0
474#define _SMIC_DATAOUT_REG 0
475
476#define _SMIC_CTRL_REG 1
477#define SMS_CC_GET_STATUS 0x40
478#define SMS_CC_START_TRANSFER 0x41
479#define SMS_CC_NEXT_TRANSFER 0x42
480#define SMS_CC_END_TRANSFER 0x43
481#define SMS_CC_START_RECEIVE 0x44
482#define SMS_CC_NEXT_RECEIVE 0x45
483#define SMS_CC_END_RECEIVE 0x46
484#define SMS_CC_TRANSFER_ABORT 0x47
485
486#define SMS_SC_READY 0xc0
487#define SMS_SC_WRITE_START 0xc1
488#define SMS_SC_WRITE_NEXT 0xc2
489#define SMS_SC_WRITE_END 0xc3
490#define SMS_SC_READ_START 0xc4
491#define SMS_SC_READ_NEXT 0xc5
492#define SMS_SC_READ_END 0xc6
493
494#define _SMIC_FLAG_REG 2
495#define SMIC_BUSY (1L << 0)
496#define SMIC_SMS_ATN (1L << 2)
497#define SMIC_EVT_ATN (1L << 3)
498#define SMIC_SMI (1L << 4)
499#define SMIC_TX_DATA_RDY (1L << 6)
500#define SMIC_RX_DATA_RDY (1L << 7)
501
502int smic_wait(struct ipmi_softc *, uint8_t, uint8_t, const char *);
503int smic_write_cmd_data(struct ipmi_softc *, uint8_t, const uint8_t *);
504int smic_read_data(struct ipmi_softc *, uint8_t *);
505
506int
507smic_wait(struct ipmi_softc *sc, uint8_t mask, uint8_t val, const char *lbl)
508{
509 int v;
510
511 /* Wait for expected flag bits */
512 v = bmc_io_wait(sc, _SMIC_FLAG_REG, mask, val, "smicwait");
513 if (v < 0)
514 return (-1);
515
516 /* Return current status */
517 v = bmc_read(sc, _SMIC_CTRL_REG);
518 dbg_printf(99, "smic_wait(%s) = %.2x\n", lbl, v);
519 return (v);
520}
521
522int
523smic_write_cmd_data(struct ipmi_softc *sc, uint8_t cmd, const uint8_t *data)
524{
525 int sts, v;
526
527 dbg_printf(50, "smic_wcd: %.2x %.2x\n", cmd, data ? *data : -1);
528 sts = smic_wait(sc, SMIC_TX_DATA_RDY | SMIC_BUSY, SMIC_TX_DATA_RDY,
529 "smic_write_cmd_data ready");
530 if (sts < 0)
531 return (sts);
532
533 bmc_write(sc, _SMIC_CTRL_REG, cmd);
534 if (data)
535 bmc_write(sc, _SMIC_DATAOUT_REG, *data);
536
537 /* Toggle BUSY bit, then wait for busy bit to clear */
538 v = bmc_read(sc, _SMIC_FLAG_REG);
539 bmc_write(sc, _SMIC_FLAG_REG, v | SMIC_BUSY);
540
541 return (smic_wait(sc, SMIC_BUSY, 0, "smic_write_cmd_data busy"));
542}
543
544int
545smic_read_data(struct ipmi_softc *sc, uint8_t *data)
546{
547 int sts;
548
549 sts = smic_wait(sc, SMIC_RX_DATA_RDY | SMIC_BUSY, SMIC_RX_DATA_RDY,
550 "smic_read_data");
551 if (sts >= 0) {
552 *data = bmc_read(sc, _SMIC_DATAIN_REG);
553 dbg_printf(50, "smic_readdata: %.2x\n", *data);
554 }
555 return (sts);
556}
557
558#define ErrStat(a,b) if (a) printf(b);
559
560int
561smic_sendmsg(struct ipmi_softc *sc, int len, const uint8_t *data)
562{
563 int sts, idx;
564
565 sts = smic_write_cmd_data(sc, SMS_CC_START_TRANSFER, &data[0]);
566 ErrStat(sts != SMS_SC_WRITE_START, "smic_sendmsg: wstart");
567 for (idx = 1; idx < len - 1; idx++) {
568 sts = smic_write_cmd_data(sc, SMS_CC_NEXT_TRANSFER,
569 &data[idx]);
570 ErrStat(sts != SMS_SC_WRITE_NEXT, "smic_sendmsg: write");
571 }
572 sts = smic_write_cmd_data(sc, SMS_CC_END_TRANSFER, &data[idx]);
573 if (sts != SMS_SC_WRITE_END) {
574 dbg_printf(50, "smic_sendmsg %d/%d = %.2x\n", idx, len, sts);
575 return (-1);
576 }
577
578 return (0);
579}
580
581int
582smic_recvmsg(struct ipmi_softc *sc, int maxlen, int *len, uint8_t *data)
583{
584 int sts, idx;
585
586 *len = 0;
587 sts = smic_wait(sc, SMIC_RX_DATA_RDY, SMIC_RX_DATA_RDY, "smic_recvmsg");
588 if (sts < 0)
589 return (-1);
590
591 sts = smic_write_cmd_data(sc, SMS_CC_START_RECEIVE, NULL);
592 ErrStat(sts != SMS_SC_READ_START, "smic_recvmsg: rstart");
593 for (idx = 0;; ) {
594 sts = smic_read_data(sc, &data[idx++]);
595 if (sts != SMS_SC_READ_START && sts != SMS_SC_READ_NEXT)
596 break;
597 smic_write_cmd_data(sc, SMS_CC_NEXT_RECEIVE, NULL);
598 }
599 ErrStat(sts != SMS_SC_READ_END, "smic_recvmsg: rend");
600
601 *len = idx;
602
603 sts = smic_write_cmd_data(sc, SMS_CC_END_RECEIVE, NULL);
604 if (sts != SMS_SC_READY) {
605 dbg_printf(50, "smic_recvmsg %d/%d = %.2x\n", idx, maxlen, sts);
606 return (-1);
607 }
608
609 return (0);
610}
611
612int
613smic_reset(struct ipmi_softc *sc)
614{
615 return (-1);
616}
617
618int
619smic_probe(struct ipmi_softc *sc)
620{
621 /* Flag register should not be 0xFF on a good system */
622 if (bmc_read(sc, _SMIC_FLAG_REG) == 0xFF)
623 return (-1);
624
625 return (0);
626}
627
628/*
629 * KCS interface
630 */
631#define _KCS_DATAIN_REGISTER 0
632#define _KCS_DATAOUT_REGISTER 0
633#define KCS_READ_NEXT 0x68
634
635#define _KCS_COMMAND_REGISTER 1
636#define KCS_GET_STATUS 0x60
637#define KCS_WRITE_START 0x61
638#define KCS_WRITE_END 0x62
639
640#define _KCS_STATUS_REGISTER 1
641#define KCS_OBF (1L << 0)
642#define KCS_IBF (1L << 1)
643#define KCS_SMS_ATN (1L << 2)
644#define KCS_CD (1L << 3)
645#define KCS_OEM1 (1L << 4)
646#define KCS_OEM2 (1L << 5)
647#define KCS_STATE_MASK 0xc0
648#define KCS_IDLE_STATE 0x00
649#define KCS_READ_STATE 0x40
650#define KCS_WRITE_STATE 0x80
651#define KCS_ERROR_STATE 0xC0
652
653int kcs_wait(struct ipmi_softc *, uint8_t, uint8_t, const char *);
654int kcs_write_cmd(struct ipmi_softc *, uint8_t);
655int kcs_write_data(struct ipmi_softc *, uint8_t);
656int kcs_read_data(struct ipmi_softc *, uint8_t *);
657
658int
659kcs_wait(struct ipmi_softc *sc, uint8_t mask, uint8_t value, const char *lbl)
660{
661 int v;
662
663 v = bmc_io_wait(sc, _KCS_STATUS_REGISTER, mask, value, lbl);
664 if (v < 0)
665 return (v);
666
667 /* Check if output buffer full, read dummy byte */
668 if ((v & (KCS_OBF | KCS_STATE_MASK)) == (KCS_OBF | KCS_WRITE_STATE))
669 bmc_read(sc, _KCS_DATAIN_REGISTER);
670
671 /* Check for error state */
672 if ((v & KCS_STATE_MASK) == KCS_ERROR_STATE) {
673 bmc_write(sc, _KCS_COMMAND_REGISTER, KCS_GET_STATUS);
674 while (bmc_read(sc, _KCS_STATUS_REGISTER) & KCS_IBF)
675 ;
676 aprint_error("ipmi: error code: %x\n",
677 bmc_read(sc, _KCS_DATAIN_REGISTER));
678 }
679
680 return (v & KCS_STATE_MASK);
681}
682
683int
684kcs_write_cmd(struct ipmi_softc *sc, uint8_t cmd)
685{
686 /* ASSERT: IBF and OBF are clear */
687 dbg_printf(50, "kcswritecmd: %.2x\n", cmd);
688 bmc_write(sc, _KCS_COMMAND_REGISTER, cmd);
689
690 return (kcs_wait(sc, KCS_IBF, 0, "write_cmd"));
691}
692
693int
694kcs_write_data(struct ipmi_softc *sc, uint8_t data)
695{
696 /* ASSERT: IBF and OBF are clear */
697 dbg_printf(50, "kcswritedata: %.2x\n", data);
698 bmc_write(sc, _KCS_DATAOUT_REGISTER, data);
699
700 return (kcs_wait(sc, KCS_IBF, 0, "write_data"));
701}
702
703int
704kcs_read_data(struct ipmi_softc *sc, uint8_t * data)
705{
706 int sts;
707
708 sts = kcs_wait(sc, KCS_IBF | KCS_OBF, KCS_OBF, "read_data");
709 if (sts != KCS_READ_STATE)
710 return (sts);
711
712 /* ASSERT: OBF is set read data, request next byte */
713 *data = bmc_read(sc, _KCS_DATAIN_REGISTER);
714 bmc_write(sc, _KCS_DATAOUT_REGISTER, KCS_READ_NEXT);
715
716 dbg_printf(50, "kcsreaddata: %.2x\n", *data);
717
718 return (sts);
719}
720
721/* Exported KCS functions */
722int
723kcs_sendmsg(struct ipmi_softc *sc, int len, const uint8_t * data)
724{
725 int idx, sts;
726
727 /* ASSERT: IBF is clear */
728 dbg_dump(50, "kcs sendmsg", len, data);
729 sts = kcs_write_cmd(sc, KCS_WRITE_START);
730 for (idx = 0; idx < len; idx++) {
731 if (idx == len - 1)
732 sts = kcs_write_cmd(sc, KCS_WRITE_END);
733
734 if (sts != KCS_WRITE_STATE)
735 break;
736
737 sts = kcs_write_data(sc, data[idx]);
738 }
739 if (sts != KCS_READ_STATE) {
740 dbg_printf(1, "kcs sendmsg = %d/%d <%.2x>\n", idx, len, sts);
741 dbg_dump(1, "kcs_sendmsg", len, data);
742 return (-1);
743 }
744
745 return (0);
746}
747
748int
749kcs_recvmsg(struct ipmi_softc *sc, int maxlen, int *rxlen, uint8_t * data)
750{
751 int idx, sts;
752
753 for (idx = 0; idx < maxlen; idx++) {
754 sts = kcs_read_data(sc, &data[idx]);
755 if (sts != KCS_READ_STATE)
756 break;
757 }
758 sts = kcs_wait(sc, KCS_IBF, 0, "recv");
759 *rxlen = idx;
760 if (sts != KCS_IDLE_STATE) {
761 dbg_printf(1, "kcs read = %d/%d <%.2x>\n", idx, maxlen, sts);
762 return (-1);
763 }
764
765 dbg_dump(50, "kcs recvmsg", idx, data);
766
767 return (0);
768}
769
770int
771kcs_reset(struct ipmi_softc *sc)
772{
773 return (-1);
774}
775
776int
777kcs_probe(struct ipmi_softc *sc)
778{
779 uint8_t v;
780
781 v = bmc_read(sc, _KCS_STATUS_REGISTER);
782#if 0
783 printf("kcs_probe: %2x\n", v);
784 printf(" STS: %2x\n", v & KCS_STATE_MASK);
785 printf(" ATN: %2x\n", v & KCS_SMS_ATN);
786 printf(" C/D: %2x\n", v & KCS_CD);
787 printf(" IBF: %2x\n", v & KCS_IBF);
788 printf(" OBF: %2x\n", v & KCS_OBF);
789#else
790 __USE(v);
791#endif
792 return (0);
793}
794
795/*
796 * IPMI code
797 */
798#define READ_SMS_BUFFER 0x37
799#define WRITE_I2C 0x50
800
801#define GET_MESSAGE_CMD 0x33
802#define SEND_MESSAGE_CMD 0x34
803
804#define IPMB_CHANNEL_NUMBER 0
805
806#define PUBLIC_BUS 0
807
808#define MIN_I2C_PACKET_SIZE 3
809#define MIN_IMB_PACKET_SIZE 7 /* one byte for cksum */
810
811#define MIN_BTBMC_REQ_SIZE 4
812#define MIN_BTBMC_RSP_SIZE 5
813#define MIN_BMC_REQ_SIZE 2
814#define MIN_BMC_RSP_SIZE 3
815
816#define BMC_SA 0x20 /* BMC/ESM3 */
817#define FPC_SA 0x22 /* front panel */
818#define BP_SA 0xC0 /* Primary Backplane */
819#define BP2_SA 0xC2 /* Secondary Backplane */
820#define PBP_SA 0xC4 /* Peripheral Backplane */
821#define DRAC_SA 0x28 /* DRAC-III */
822#define DRAC3_SA 0x30 /* DRAC-III */
823#define BMC_LUN 0
824#define SMS_LUN 2
825
826struct ipmi_request {
827 uint8_t rsSa;
828 uint8_t rsLun;
829 uint8_t netFn;
830 uint8_t cmd;
831 uint8_t data_len;
832 uint8_t *data;
833};
834
835struct ipmi_response {
836 uint8_t cCode;
837 uint8_t data_len;
838 uint8_t *data;
839};
840
841struct ipmi_bmc_request {
842 uint8_t bmc_nfLn;
843 uint8_t bmc_cmd;
844 uint8_t bmc_data_len;
845 uint8_t bmc_data[1];
846};
847
848struct ipmi_bmc_response {
849 uint8_t bmc_nfLn;
850 uint8_t bmc_cmd;
851 uint8_t bmc_cCode;
852 uint8_t bmc_data_len;
853 uint8_t bmc_data[1];
854};
855
856
857CFATTACH_DECL2_NEW(ipmi, sizeof(struct ipmi_softc),
858 ipmi_match, ipmi_attach, ipmi_detach, NULL, NULL, NULL);
859
860/* Scan memory for signature */
861void *
862scan_sig(long start, long end, int skip, int len, const void *data)
863{
864 void *va;
865
866 while (start < end) {
867 va = ISA_HOLE_VADDR(start);
868 if (memcmp(va, data, len) == 0)
869 return (va);
870
871 start += skip;
872 }
873
874 return (NULL);
875}
876
877void
878dumpb(const char *lbl, int len, const uint8_t *data)
879{
880 int idx;
881
882 printf("%s: ", lbl);
883 for (idx = 0; idx < len; idx++)
884 printf("%.2x ", data[idx]);
885
886 printf("\n");
887}
888
889void
890ipmi_smbios_probe(struct smbios_ipmi *pipmi, struct ipmi_attach_args *ia)
891{
892 const char *platform;
893
894 dbg_printf(1, "ipmi_smbios_probe: %02x %02x %02x %02x "
895 "%08" PRIx64 " %02x %02x\n",
896 pipmi->smipmi_if_type,
897 pipmi->smipmi_if_rev,
898 pipmi->smipmi_i2c_address,
899 pipmi->smipmi_nvram_address,
900 pipmi->smipmi_base_address,
901 pipmi->smipmi_base_flags,
902 pipmi->smipmi_irq);
903
904 ia->iaa_if_type = pipmi->smipmi_if_type;
905 ia->iaa_if_rev = pipmi->smipmi_if_rev;
906 ia->iaa_if_irq = (pipmi->smipmi_base_flags & SMIPMI_FLAG_IRQEN) ?
907 pipmi->smipmi_irq : -1;
908 ia->iaa_if_irqlvl = (pipmi->smipmi_base_flags & SMIPMI_FLAG_IRQLVL) ?
909 IST_LEVEL : IST_EDGE;
910
911 switch (SMIPMI_FLAG_IFSPACING(pipmi->smipmi_base_flags)) {
912 case IPMI_IOSPACING_BYTE:
913 ia->iaa_if_iospacing = 1;
914 break;
915
916 case IPMI_IOSPACING_DWORD:
917 ia->iaa_if_iospacing = 4;
918 break;
919
920 case IPMI_IOSPACING_WORD:
921 ia->iaa_if_iospacing = 2;
922 break;
923
924 default:
925 ia->iaa_if_iospacing = 1;
926 aprint_error("ipmi: unknown register spacing\n");
927 }
928
929 /* Calculate base address (PCI BAR format) */
930 if (pipmi->smipmi_base_address & 0x1) {
931 ia->iaa_if_iotype = 'i';
932 ia->iaa_if_iobase = pipmi->smipmi_base_address & ~0x1;
933 } else {
934 ia->iaa_if_iotype = 'm';
935 ia->iaa_if_iobase = pipmi->smipmi_base_address & ~0xF;
936 }
937 if (pipmi->smipmi_base_flags & SMIPMI_FLAG_ODDOFFSET)
938 ia->iaa_if_iobase++;
939
940 platform = pmf_get_platform("system-product");
941 if (platform != NULL &&
942 strcmp(platform, "ProLiant MicroServer") == 0 &&
943 pipmi->smipmi_base_address != 0) {
944 ia->iaa_if_iospacing = 1;
945 ia->iaa_if_iobase = pipmi->smipmi_base_address & ~0x7;
946 ia->iaa_if_iotype = 'i';
947 return;
948 }
949
950 if (pipmi->smipmi_base_flags == 0x7f) {
951 /* IBM 325 eServer workaround */
952 ia->iaa_if_iospacing = 1;
953 ia->iaa_if_iobase = pipmi->smipmi_base_address;
954 ia->iaa_if_iotype = 'i';
955 return;
956 }
957}
958
959/*
960 * bt_buildmsg builds an IPMI message from a nfLun, cmd, and data
961 * This is used by BT protocol
962 *
963 * Returns a buffer to an allocated message, txlen contains length
964 * of allocated message
965 */
966void *
967bt_buildmsg(struct ipmi_softc *sc, int nfLun, int cmd, int len,
968 const void *data, int *txlen)
969{
970 uint8_t *buf;
971
972 /* Block transfer needs 4 extra bytes: length/netfn/seq/cmd + data */
973 *txlen = len + 4;
974 buf = ipmi_buf_acquire(sc, *txlen);
975 if (buf == NULL)
976 return (NULL);
977
978 buf[IPMI_BTMSG_LEN] = len + 3;
979 buf[IPMI_BTMSG_NFLN] = nfLun;
980 buf[IPMI_BTMSG_SEQ] = sc->sc_btseq++;
981 buf[IPMI_BTMSG_CMD] = cmd;
982 if (len && data)
983 memcpy(buf + IPMI_BTMSG_DATASND, data, len);
984
985 return (buf);
986}
987
988/*
989 * cmn_buildmsg builds an IPMI message from a nfLun, cmd, and data
990 * This is used by both SMIC and KCS protocols
991 *
992 * Returns a buffer to an allocated message, txlen contains length
993 * of allocated message
994 */
995void *
996cmn_buildmsg(struct ipmi_softc *sc, int nfLun, int cmd, int len,
997 const void *data, int *txlen)
998{
999 uint8_t *buf;
1000
1001 /* Common needs two extra bytes: nfLun/cmd + data */
1002 *txlen = len + 2;
1003 buf = ipmi_buf_acquire(sc, *txlen);
1004 if (buf == NULL)
1005 return (NULL);
1006
1007 buf[IPMI_MSG_NFLN] = nfLun;
1008 buf[IPMI_MSG_CMD] = cmd;
1009 if (len && data)
1010 memcpy(buf + IPMI_MSG_DATASND, data, len);
1011
1012 return (buf);
1013}
1014
1015/*
1016 * ipmi_sendcmd: caller must hold sc_cmd_mtx.
1017 *
1018 * Send an IPMI command
1019 */
1020int
1021ipmi_sendcmd(struct ipmi_softc *sc, int rssa, int rslun, int netfn, int cmd,
1022 int txlen, const void *data)
1023{
1024 uint8_t *buf;
1025 int rc = -1;
1026
1027 dbg_printf(50, "ipmi_sendcmd: rssa=%.2x nfln=%.2x cmd=%.2x len=%.2x\n",
1028 rssa, NETFN_LUN(netfn, rslun), cmd, txlen);
1029 dbg_dump(10, " send", txlen, data);
1030 if (rssa != BMC_SA) {
1031#if 0
1032 buf = sc->sc_if->buildmsg(sc, NETFN_LUN(APP_NETFN, BMC_LUN),
1033 APP_SEND_MESSAGE, 7 + txlen, NULL, &txlen);
1034 pI2C->bus = (sc->if_ver == 0x09) ?
1035 PUBLIC_BUS :
1036 IPMB_CHANNEL_NUMBER;
1037
1038 imbreq->rsSa = rssa;
1039 imbreq->nfLn = NETFN_LUN(netfn, rslun);
1040 imbreq->cSum1 = -(imbreq->rsSa + imbreq->nfLn);
1041 imbreq->rqSa = BMC_SA;
1042 imbreq->seqLn = NETFN_LUN(sc->imb_seq++, SMS_LUN);
1043 imbreq->cmd = cmd;
1044 if (txlen)
1045 memcpy(imbreq->data, data, txlen);
1046 /* Set message checksum */
1047 imbreq->data[txlen] = cksum8(&imbreq->rqSa, txlen + 3);
1048#endif
1049 goto done;
1050 } else
1051 buf = sc->sc_if->buildmsg(sc, NETFN_LUN(netfn, rslun), cmd,
1052 txlen, data, &txlen);
1053
1054 if (buf == NULL) {
1055 printf("ipmi: sendcmd buffer busy\n");
1056 goto done;
1057 }
1058 rc = sc->sc_if->sendmsg(sc, txlen, buf);
1059 ipmi_buf_release(sc, buf);
1060
1061 ipmi_delay(sc, 50); /* give bmc chance to digest command */
1062
1063done:
1064 return (rc);
1065}
1066
1067void
1068ipmi_buf_release(struct ipmi_softc *sc, char *buf)
1069{
1070 KASSERT(sc->sc_buf_rsvd);
1071 KASSERT(sc->sc_buf == buf);
1072 sc->sc_buf_rsvd = false;
1073}
1074
1075char *
1076ipmi_buf_acquire(struct ipmi_softc *sc, size_t len)
1077{
1078 KASSERT(len <= sizeof(sc->sc_buf));
1079
1080 if (sc->sc_buf_rsvd || len > sizeof(sc->sc_buf))
1081 return NULL;
1082 sc->sc_buf_rsvd = true;
1083 return sc->sc_buf;
1084}
1085
1086/*
1087 * ipmi_recvcmd: caller must hold sc_cmd_mtx.
1088 */
1089int
1090ipmi_recvcmd(struct ipmi_softc *sc, int maxlen, int *rxlen, void *data)
1091{
1092 uint8_t *buf, rc = 0;
1093 int rawlen;
1094
1095 /* Need three extra bytes: netfn/cmd/ccode + data */
1096 buf = ipmi_buf_acquire(sc, maxlen + 3);
1097 if (buf == NULL) {
1098 printf("ipmi: ipmi_recvcmd: malloc fails\n");
1099 return (-1);
1100 }
1101 /* Receive message from interface, copy out result data */
1102 if (sc->sc_if->recvmsg(sc, maxlen + 3, &rawlen, buf)) {
1103 ipmi_buf_release(sc, buf);
1104 return (-1);
1105 }
1106
1107 *rxlen = rawlen - IPMI_MSG_DATARCV;
1108 if (*rxlen > 0 && data)
1109 memcpy(data, buf + IPMI_MSG_DATARCV, *rxlen);
1110
1111 if ((rc = buf[IPMI_MSG_CCODE]) != 0)
1112 dbg_printf(1, "ipmi_recvmsg: nfln=%.2x cmd=%.2x err=%.2x\n",
1113 buf[IPMI_MSG_NFLN], buf[IPMI_MSG_CMD], buf[IPMI_MSG_CCODE]);
1114
1115 dbg_printf(50, "ipmi_recvcmd: nfln=%.2x cmd=%.2x err=%.2x len=%.2x\n",
1116 buf[IPMI_MSG_NFLN], buf[IPMI_MSG_CMD], buf[IPMI_MSG_CCODE],
1117 *rxlen);
1118 dbg_dump(10, " recv", *rxlen, data);
1119
1120 ipmi_buf_release(sc, buf);
1121
1122 return (rc);
1123}
1124
1125/*
1126 * ipmi_delay: caller must hold sc_cmd_mtx.
1127 */
1128void
1129ipmi_delay(struct ipmi_softc *sc, int ms)
1130{
1131 if (cold)
1132 delay(ms * 1000);
1133 else {
1134 mutex_enter(&sc->sc_sleep_mtx);
1135 cv_timedwait(&sc->sc_cmd_sleep, &sc->sc_sleep_mtx, mstohz(ms));
1136 mutex_exit(&sc->sc_sleep_mtx);
1137 }
1138}
1139
1140/* Read a partial SDR entry */
1141int
1142get_sdr_partial(struct ipmi_softc *sc, uint16_t recordId, uint16_t reserveId,
1143 uint8_t offset, uint8_t length, void *buffer, uint16_t *nxtRecordId)
1144{
1145 uint8_t cmd[256 + 8];
1146 int len;
1147
1148 ((uint16_t *) cmd)[0] = reserveId;
1149 ((uint16_t *) cmd)[1] = recordId;
1150 cmd[4] = offset;
1151 cmd[5] = length;
1152 mutex_enter(&sc->sc_cmd_mtx);
1153 if (ipmi_sendcmd(sc, BMC_SA, 0, STORAGE_NETFN, STORAGE_GET_SDR, 6,
1154 cmd)) {
1155 mutex_exit(&sc->sc_cmd_mtx);
1156 printf("ipmi: sendcmd fails\n");
1157 return (-1);
1158 }
1159 if (ipmi_recvcmd(sc, 8 + length, &len, cmd)) {
1160 mutex_exit(&sc->sc_cmd_mtx);
1161 printf("ipmi: getSdrPartial: recvcmd fails\n");
1162 return (-1);
1163 }
1164 mutex_exit(&sc->sc_cmd_mtx);
1165 if (nxtRecordId)
1166 *nxtRecordId = *(uint16_t *) cmd;
1167 memcpy(buffer, cmd + 2, len - 2);
1168
1169 return (0);
1170}
1171
1172int maxsdrlen = 0x10;
1173
1174/* Read an entire SDR; pass to add sensor */
1175int
1176get_sdr(struct ipmi_softc *sc, uint16_t recid, uint16_t *nxtrec)
1177{
1178 uint16_t resid = 0;
1179 int len, sdrlen, offset;
1180 uint8_t *psdr;
1181 struct sdrhdr shdr;
1182
1183 mutex_enter(&sc->sc_cmd_mtx);
1184 /* Reserve SDR */
1185 if (ipmi_sendcmd(sc, BMC_SA, 0, STORAGE_NETFN, STORAGE_RESERVE_SDR,
1186 0, NULL)) {
1187 mutex_exit(&sc->sc_cmd_mtx);
1188 printf("ipmi: reserve send fails\n");
1189 return (-1);
1190 }
1191 if (ipmi_recvcmd(sc, sizeof(resid), &len, &resid)) {
1192 mutex_exit(&sc->sc_cmd_mtx);
1193 printf("ipmi: reserve recv fails\n");
1194 return (-1);
1195 }
1196 mutex_exit(&sc->sc_cmd_mtx);
1197 /* Get SDR Header */
1198 if (get_sdr_partial(sc, recid, resid, 0, sizeof shdr, &shdr, nxtrec)) {
1199 printf("ipmi: get header fails\n");
1200 return (-1);
1201 }
1202 /* Allocate space for entire SDR Length of SDR in header does not
1203 * include header length */
1204 sdrlen = sizeof(shdr) + shdr.record_length;
1205 psdr = malloc(sdrlen, M_DEVBUF, M_WAITOK|M_CANFAIL);
1206 if (psdr == NULL)
1207 return -1;
1208
1209 memcpy(psdr, &shdr, sizeof(shdr));
1210
1211 /* Read SDR Data maxsdrlen bytes at a time */
1212 for (offset = sizeof(shdr); offset < sdrlen; offset += maxsdrlen) {
1213 len = sdrlen - offset;
1214 if (len > maxsdrlen)
1215 len = maxsdrlen;
1216
1217 if (get_sdr_partial(sc, recid, resid, offset, len,
1218 psdr + offset, NULL)) {
1219 printf("ipmi: get chunk : %d,%d fails\n",
1220 offset, len);
1221 free(psdr, M_DEVBUF);
1222 return (-1);
1223 }
1224 }
1225
1226 /* Add SDR to sensor list, if not wanted, free buffer */
1227 if (add_sdr_sensor(sc, psdr) == 0)
1228 free(psdr, M_DEVBUF);
1229
1230 return (0);
1231}
1232
1233int
1234getbits(uint8_t *bytes, int bitpos, int bitlen)
1235{
1236 int v;
1237 int mask;
1238
1239 bitpos += bitlen - 1;
1240 for (v = 0; bitlen--;) {
1241 v <<= 1;
1242 mask = 1L << (bitpos & 7);
1243 if (bytes[bitpos >> 3] & mask)
1244 v |= 1;
1245 bitpos--;
1246 }
1247
1248 return (v);
1249}
1250
1251/* Decode IPMI sensor name */
1252void
1253ipmi_sensor_name(char *name, int len, uint8_t typelen, uint8_t *bits)
1254{
1255 int i, slen;
1256 char bcdplus[] = "0123456789 -.:,_";
1257
1258 slen = typelen & 0x1F;
1259 switch (typelen >> 6) {
1260 case IPMI_NAME_UNICODE:
1261 //unicode
1262 break;
1263
1264 case IPMI_NAME_BCDPLUS:
1265 /* Characters are encoded in 4-bit BCDPLUS */
1266 if (len < slen * 2 + 1)
1267 slen = (len >> 1) - 1;
1268 for (i = 0; i < slen; i++) {
1269 *(name++) = bcdplus[bits[i] >> 4];
1270 *(name++) = bcdplus[bits[i] & 0xF];
1271 }
1272 break;
1273
1274 case IPMI_NAME_ASCII6BIT:
1275 /* Characters are encoded in 6-bit ASCII
1276 * 0x00 - 0x3F maps to 0x20 - 0x5F */
1277 /* XXX: need to calculate max len: slen = 3/4 * len */
1278 if (len < slen + 1)
1279 slen = len - 1;
1280 for (i = 0; i < slen * 8; i += 6)
1281 *(name++) = getbits(bits, i, 6) + ' ';
1282 break;
1283
1284 case IPMI_NAME_ASCII8BIT:
1285 /* Characters are 8-bit ascii */
1286 if (len < slen + 1)
1287 slen = len - 1;
1288 while (slen--)
1289 *(name++) = *(bits++);
1290 break;
1291 }
1292 *name = 0;
1293}
1294
1295/* Sign extend a n-bit value */
1296long
1297signextend(unsigned long val, int bits)
1298{
1299 long msk = (1L << (bits-1))-1;
1300
1301 return (-(val & ~msk) | val);
1302}
1303
1304
1305/* fixpoint arithmetic */
1306#define FIX2INT(x) ((int64_t)((x) >> 32))
1307#define INT2FIX(x) ((int64_t)((uint64_t)(x) << 32))
1308
1309#define FIX2 0x0000000200000000ll /* 2.0 */
1310#define FIX3 0x0000000300000000ll /* 3.0 */
1311#define FIXE 0x00000002b7e15163ll /* 2.71828182845904523536 */
1312#define FIX10 0x0000000a00000000ll /* 10.0 */
1313#define FIXMONE 0xffffffff00000000ll /* -1.0 */
1314#define FIXHALF 0x0000000080000000ll /* 0.5 */
1315#define FIXTHIRD 0x0000000055555555ll /* 0.33333333333333333333 */
1316
1317#define FIX1LOG2 0x0000000171547653ll /* 1.0/log(2) */
1318#define FIX1LOGE 0x0000000100000000ll /* 1.0/log(2.71828182845904523536) */
1319#define FIX1LOG10 0x000000006F2DEC55ll /* 1.0/log(10) */
1320
1321#define FIX1E 0x000000005E2D58D9ll /* 1.0/2.71828182845904523536 */
1322
1323static int64_t fixlog_a[] = {
1324 0x0000000100000000ll /* 1.0/1.0 */,
1325 0xffffffff80000000ll /* -1.0/2.0 */,
1326 0x0000000055555555ll /* 1.0/3.0 */,
1327 0xffffffffc0000000ll /* -1.0/4.0 */,
1328 0x0000000033333333ll /* 1.0/5.0 */,
1329 0x000000002aaaaaabll /* -1.0/6.0 */,
1330 0x0000000024924925ll /* 1.0/7.0 */,
1331 0x0000000020000000ll /* -1.0/8.0 */,
1332 0x000000001c71c71cll /* 1.0/9.0 */
1333};
1334
1335static int64_t fixexp_a[] = {
1336 0x0000000100000000ll /* 1.0/1.0 */,
1337 0x0000000100000000ll /* 1.0/1.0 */,
1338 0x0000000080000000ll /* 1.0/2.0 */,
1339 0x000000002aaaaaabll /* 1.0/6.0 */,
1340 0x000000000aaaaaabll /* 1.0/24.0 */,
1341 0x0000000002222222ll /* 1.0/120.0 */,
1342 0x00000000005b05b0ll /* 1.0/720.0 */,
1343 0x00000000000d00d0ll /* 1.0/5040.0 */,
1344 0x000000000001a01all /* 1.0/40320.0 */
1345};
1346
1347static int64_t
1348fixmul(int64_t x, int64_t y)
1349{
1350 int64_t z;
1351 int64_t a,b,c,d;
1352 int neg;
1353
1354 neg = 0;
1355 if (x < 0) {
1356 x = -x;
1357 neg = !neg;
1358 }
1359 if (y < 0) {
1360 y = -y;
1361 neg = !neg;
1362 }
1363
1364 a = FIX2INT(x);
1365 b = x - INT2FIX(a);
1366 c = FIX2INT(y);
1367 d = y - INT2FIX(c);
1368
1369 z = INT2FIX(a*c) + a * d + b * c + (b/2 * d/2 >> 30);
1370
1371 return neg ? -z : z;
1372}
1373
1374static int64_t
1375poly(int64_t x0, int64_t x, int64_t a[], int n)
1376{
1377 int64_t z;
1378 int i;
1379
1380 z = fixmul(x0, a[0]);
1381 for (i=1; i<n; ++i) {
1382 x0 = fixmul(x0, x);
1383 z = fixmul(x0, a[i]) + z;
1384 }
1385 return z;
1386}
1387
1388static int64_t
1389logx(int64_t x, int64_t y)
1390{
1391 int64_t z;
1392
1393 if (x <= INT2FIX(0)) {
1394 z = INT2FIX(-99999);
1395 goto done;
1396 }
1397
1398 z = INT2FIX(0);
1399 while (x >= FIXE) {
1400 x = fixmul(x, FIX1E);
1401 z += INT2FIX(1);
1402 }
1403 while (x < INT2FIX(1)) {
1404 x = fixmul(x, FIXE);
1405 z -= INT2FIX(1);
1406 }
1407
1408 x -= INT2FIX(1);
1409 z += poly(x, x, fixlog_a, sizeof(fixlog_a)/sizeof(fixlog_a[0]));
1410 z = fixmul(z, y);
1411
1412done:
1413 return z;
1414}
1415
1416static int64_t
1417powx(int64_t x, int64_t y)
1418{
1419 int64_t k;
1420
1421 if (x == INT2FIX(0))
1422 goto done;
1423
1424 x = logx(x,y);
1425
1426 if (x < INT2FIX(0)) {
1427 x = INT2FIX(0) - x;
1428 k = -FIX2INT(x);
1429 x = INT2FIX(-k) - x;
1430 } else {
1431 k = FIX2INT(x);
1432 x = x - INT2FIX(k);
1433 }
1434
1435 x = poly(INT2FIX(1), x, fixexp_a, sizeof(fixexp_a)/sizeof(fixexp_a[0]));
1436
1437 while (k < 0) {
1438 x = fixmul(x, FIX1E);
1439 ++k;
1440 }
1441 while (k > 0) {
1442 x = fixmul(x, FIXE);
1443 --k;
1444 }
1445
1446done:
1447 return x;
1448}
1449
1450/* Convert IPMI reading from sensor factors */
1451long
1452ipmi_convert(uint8_t v, struct sdrtype1 *s1, long adj)
1453{
1454 int64_t M, B;
1455 char K1, K2;
1456 int64_t val, v1, v2, vs;
1457 int sign = (s1->units1 >> 6) & 0x3;
1458
1459 vs = (sign == 0x1 || sign == 0x2) ? (int8_t)v : v;
1460 if ((vs < 0) && (sign == 0x1))
1461 vs++;
1462
1463 /* Calculate linear reading variables */
1464 M = signextend((((short)(s1->m_tolerance & 0xC0)) << 2) + s1->m, 10);
1465 B = signextend((((short)(s1->b_accuracy & 0xC0)) << 2) + s1->b, 10);
1466 K1 = signextend(s1->rbexp & 0xF, 4);
1467 K2 = signextend(s1->rbexp >> 4, 4);
1468
1469 /* Calculate sensor reading:
1470 * y = L((M * v + (B * 10^K1)) * 10^(K2+adj)
1471 *
1472 * This commutes out to:
1473 * y = L(M*v * 10^(K2+adj) + B * 10^(K1+K2+adj)); */
1474 v1 = powx(FIX10, INT2FIX(K2 + adj));
1475 v2 = powx(FIX10, INT2FIX(K1 + K2 + adj));
1476 val = M * vs * v1 + B * v2;
1477
1478 /* Linearization function: y = f(x) 0 : y = x 1 : y = ln(x) 2 : y =
1479 * log10(x) 3 : y = log2(x) 4 : y = e^x 5 : y = 10^x 6 : y = 2^x 7 : y
1480 * = 1/x 8 : y = x^2 9 : y = x^3 10 : y = square root(x) 11 : y = cube
1481 * root(x) */
1482 switch (s1->linear & 0x7f) {
1483 case 0: break;
1484 case 1: val = logx(val,FIX1LOGE); break;
1485 case 2: val = logx(val,FIX1LOG10); break;
1486 case 3: val = logx(val,FIX1LOG2); break;
1487 case 4: val = powx(FIXE,val); break;
1488 case 5: val = powx(FIX10,val); break;
1489 case 6: val = powx(FIX2,val); break;
1490 case 7: val = powx(val,FIXMONE); break;
1491 case 8: val = powx(val,FIX2); break;
1492 case 9: val = powx(val,FIX3); break;
1493 case 10: val = powx(val,FIXHALF); break;
1494 case 11: val = powx(val,FIXTHIRD); break;
1495 }
1496
1497 return FIX2INT(val);
1498}
1499
1500int32_t
1501ipmi_convert_sensor(uint8_t *reading, struct ipmi_sensor *psensor)
1502{
1503 struct sdrtype1 *s1 = (struct sdrtype1 *)psensor->i_sdr;
1504 int32_t val;
1505
1506 switch (psensor->i_envtype) {
1507 case ENVSYS_STEMP:
1508 val = ipmi_convert(reading[0], s1, 6) + 273150000;
1509 break;
1510
1511 case ENVSYS_SVOLTS_DC:
1512 val = ipmi_convert(reading[0], s1, 6);
1513 break;
1514
1515 case ENVSYS_SFANRPM:
1516 val = ipmi_convert(reading[0], s1, 0);
1517 if (((s1->units1>>3)&0x7) == 0x3)
1518 val *= 60; /* RPS -> RPM */
1519 break;
1520 default:
1521 val = 0;
1522 break;
1523 }
1524 return val;
1525}
1526
1527void
1528ipmi_set_limits(struct sysmon_envsys *sme, envsys_data_t *edata,
1529 sysmon_envsys_lim_t *limits, uint32_t *props)
1530{
1531 struct ipmi_sensor *ipmi_s;
1532
1533 /* Find the ipmi_sensor corresponding to this edata */
1534 SLIST_FOREACH(ipmi_s, &ipmi_sensor_list, i_list) {
1535 if (ipmi_s->i_envnum == edata->sensor) {
1536 if (limits == NULL) {
1537 limits = &ipmi_s->i_deflims;
1538 props = &ipmi_s->i_defprops;
1539 }
1540 *props |= PROP_DRIVER_LIMITS;
1541 ipmi_s->i_limits = *limits;
1542 ipmi_s->i_props = *props;
1543 return;
1544 }
1545 }
1546 return;
1547}
1548
1549void
1550ipmi_get_limits(struct sysmon_envsys *sme, envsys_data_t *edata,
1551 sysmon_envsys_lim_t *limits, uint32_t *props)
1552{
1553 struct ipmi_sensor *ipmi_s;
1554 struct ipmi_softc *sc = sme->sme_cookie;
1555
1556 /* Find the ipmi_sensor corresponding to this edata */
1557 SLIST_FOREACH(ipmi_s, &ipmi_sensor_list, i_list) {
1558 if (ipmi_s->i_envnum == edata->sensor) {
1559 ipmi_get_sensor_limits(sc, ipmi_s, limits, props);
1560 ipmi_s->i_limits = *limits;
1561 ipmi_s->i_props = *props;
1562 if (ipmi_s->i_defprops == 0) {
1563 ipmi_s->i_defprops = *props;
1564 ipmi_s->i_deflims = *limits;
1565 }
1566 return;
1567 }
1568 }
1569 return;
1570}
1571
1572void
1573ipmi_get_sensor_limits(struct ipmi_softc *sc, struct ipmi_sensor *psensor,
1574 sysmon_envsys_lim_t *limits, uint32_t *props)
1575{
1576 struct sdrtype1 *s1 = (struct sdrtype1 *)psensor->i_sdr;
1577 bool failure;
1578 int rxlen;
1579 uint8_t data[32];
1580 uint32_t prop_critmax, prop_warnmax, prop_critmin, prop_warnmin;
1581 int32_t *pcritmax, *pwarnmax, *pcritmin, *pwarnmin;
1582
1583 *props &= ~(PROP_CRITMIN | PROP_CRITMAX | PROP_WARNMIN | PROP_WARNMAX);
1584 data[0] = psensor->i_num;
1585 mutex_enter(&sc->sc_cmd_mtx);
1586 failure =
1587 ipmi_sendcmd(sc, s1->owner_id, s1->owner_lun,
1588 SE_NETFN, SE_GET_SENSOR_THRESHOLD, 1, data) ||
1589 ipmi_recvcmd(sc, sizeof(data), &rxlen, data);
1590 mutex_exit(&sc->sc_cmd_mtx);
1591 if (failure)
1592 return;
1593
1594 dbg_printf(25, "recvdata: %.2x %.2x %.2x %.2x %.2x %.2x %.2x\n",
1595 data[0], data[1], data[2], data[3], data[4], data[5], data[6]);
1596
1597 switch (s1->linear & 0x7f) {
1598 case 7: /* 1/x sensor, exchange upper and lower limits */
1599 prop_critmax = PROP_CRITMIN;
1600 prop_warnmax = PROP_WARNMIN;
1601 prop_critmin = PROP_CRITMAX;
1602 prop_warnmin = PROP_WARNMAX;
1603 pcritmax = &limits->sel_critmin;
1604 pwarnmax = &limits->sel_warnmin;
1605 pcritmin = &limits->sel_critmax;
1606 pwarnmin = &limits->sel_warnmax;
1607 break;
1608 default:
1609 prop_critmax = PROP_CRITMAX;
1610 prop_warnmax = PROP_WARNMAX;
1611 prop_critmin = PROP_CRITMIN;
1612 prop_warnmin = PROP_WARNMIN;
1613 pcritmax = &limits->sel_critmax;
1614 pwarnmax = &limits->sel_warnmax;
1615 pcritmin = &limits->sel_critmin;
1616 pwarnmin = &limits->sel_warnmin;
1617 break;
1618 }
1619
1620 if (data[0] & 0x20 && data[6] != 0xff) {
1621 *pcritmax = ipmi_convert_sensor(&data[6], psensor);
1622 *props |= prop_critmax;
1623 }
1624 if (data[0] & 0x10 && data[5] != 0xff) {
1625 *pcritmax = ipmi_convert_sensor(&data[5], psensor);
1626 *props |= prop_critmax;
1627 }
1628 if (data[0] & 0x08 && data[4] != 0xff) {
1629 *pwarnmax = ipmi_convert_sensor(&data[4], psensor);
1630 *props |= prop_warnmax;
1631 }
1632 if (data[0] & 0x04 && data[3] != 0x00) {
1633 *pcritmin = ipmi_convert_sensor(&data[3], psensor);
1634 *props |= prop_critmin;
1635 }
1636 if (data[0] & 0x02 && data[2] != 0x00) {
1637 *pcritmin = ipmi_convert_sensor(&data[2], psensor);
1638 *props |= prop_critmin;
1639 }
1640 if (data[0] & 0x01 && data[1] != 0x00) {
1641 *pwarnmin = ipmi_convert_sensor(&data[1], psensor);
1642 *props |= prop_warnmin;
1643 }
1644 return;
1645}
1646
1647int
1648ipmi_sensor_status(struct ipmi_softc *sc, struct ipmi_sensor *psensor,
1649 envsys_data_t *edata, uint8_t *reading)
1650{
1651 int etype;
1652
1653 /* Get reading of sensor */
1654 edata->value_cur = ipmi_convert_sensor(reading, psensor);
1655
1656 /* Return Sensor Status */
1657 etype = (psensor->i_etype << 8) + psensor->i_stype;
1658 switch (etype) {
1659 case IPMI_SENSOR_TYPE_TEMP:
1660 case IPMI_SENSOR_TYPE_VOLT:
1661 case IPMI_SENSOR_TYPE_FAN:
1662 if (psensor->i_props & PROP_CRITMAX &&
1663 edata->value_cur > psensor->i_limits.sel_critmax)
1664 return ENVSYS_SCRITOVER;
1665
1666 if (psensor->i_props & PROP_WARNMAX &&
1667 edata->value_cur > psensor->i_limits.sel_warnmax)
1668 return ENVSYS_SWARNOVER;
1669
1670 if (psensor->i_props & PROP_WARNMIN &&
1671 edata->value_cur < psensor->i_limits.sel_warnmin)
1672 return ENVSYS_SWARNUNDER;
1673
1674 if (psensor->i_props & PROP_CRITMIN &&
1675 edata->value_cur < psensor->i_limits.sel_critmin)
1676 return ENVSYS_SCRITUNDER;
1677
1678 break;
1679
1680 case IPMI_SENSOR_TYPE_INTRUSION:
1681 edata->value_cur = (reading[2] & 1) ? 0 : 1;
1682 if (reading[2] & 0x1)
1683 return ENVSYS_SCRITICAL;
1684 break;
1685
1686 case IPMI_SENSOR_TYPE_PWRSUPPLY:
1687 /* Reading: 1 = present+powered, 0 = otherwise */
1688 edata->value_cur = (reading[2] & 1) ? 0 : 1;
1689 if (reading[2] & 0x10) {
1690 /* XXX: Need envsys type for Power Supply types
1691 * ok: power supply installed && powered
1692 * warn: power supply installed && !powered
1693 * crit: power supply !installed
1694 */
1695 return ENVSYS_SCRITICAL;
1696 }
1697 if (reading[2] & 0x08) {
1698 /* Power supply AC lost */
1699 return ENVSYS_SWARNOVER;
1700 }
1701 break;
1702 }
1703
1704 return ENVSYS_SVALID;
1705}
1706
1707int
1708read_sensor(struct ipmi_softc *sc, struct ipmi_sensor *psensor)
1709{
1710 struct sdrtype1 *s1 = (struct sdrtype1 *) psensor->i_sdr;
1711 uint8_t data[8];
1712 int rxlen;
1713 envsys_data_t *edata = &sc->sc_sensor[psensor->i_envnum];
1714
1715 memset(data, 0, sizeof(data));
1716 data[0] = psensor->i_num;
1717
1718 mutex_enter(&sc->sc_cmd_mtx);
1719 if (ipmi_sendcmd(sc, s1->owner_id, s1->owner_lun, SE_NETFN,
1720 SE_GET_SENSOR_READING, 1, data))
1721 goto err;
1722
1723 if (ipmi_recvcmd(sc, sizeof(data), &rxlen, data))
1724 goto err;
1725 mutex_exit(&sc->sc_cmd_mtx);
1726
1727 dbg_printf(10, "m=%u, m_tolerance=%u, b=%u, b_accuracy=%u, rbexp=%u, linear=%d\n",
1728 s1->m, s1->m_tolerance, s1->b, s1->b_accuracy, s1->rbexp, s1->linear);
1729 dbg_printf(10, "values=%.2x %.2x %.2x %.2x %s\n",
1730 data[0],data[1],data[2],data[3], edata->desc);
1731 if (IPMI_INVALID_SENSOR_P(data[1])) {
1732 /* Check if sensor is valid */
1733 edata->state = ENVSYS_SINVALID;
1734 } else {
1735 edata->state = ipmi_sensor_status(sc, psensor, edata, data);
1736 }
1737 return 0;
1738err:
1739 mutex_exit(&sc->sc_cmd_mtx);
1740 return -1;
1741}
1742
1743int
1744ipmi_sensor_type(int type, int ext_type, int entity)
1745{
1746 switch (ext_type << 8L | type) {
1747 case IPMI_SENSOR_TYPE_TEMP:
1748 return (ENVSYS_STEMP);
1749
1750 case IPMI_SENSOR_TYPE_VOLT:
1751 return (ENVSYS_SVOLTS_DC);
1752
1753 case IPMI_SENSOR_TYPE_FAN:
1754 return (ENVSYS_SFANRPM);
1755
1756 case IPMI_SENSOR_TYPE_PWRSUPPLY:
1757 if (entity == IPMI_ENTITY_PWRSUPPLY)
1758 return (ENVSYS_INDICATOR);
1759 break;
1760
1761 case IPMI_SENSOR_TYPE_INTRUSION:
1762 return (ENVSYS_INDICATOR);
1763 }
1764
1765 return (-1);
1766}
1767
1768/* Add Sensor to BSD Sysctl interface */
1769int
1770add_sdr_sensor(struct ipmi_softc *sc, uint8_t *psdr)
1771{
1772 int rc;
1773 struct sdrtype1 *s1 = (struct sdrtype1 *)psdr;
1774 struct sdrtype2 *s2 = (struct sdrtype2 *)psdr;
1775 char name[64];
1776
1777 switch (s1->sdrhdr.record_type) {
1778 case IPMI_SDR_TYPEFULL:
1779 ipmi_sensor_name(name, sizeof(name), s1->typelen, s1->name);
1780 rc = add_child_sensors(sc, psdr, 1, s1->sensor_num,
1781 s1->sensor_type, s1->event_code, 0, s1->entity_id, name);
1782 break;
1783
1784 case IPMI_SDR_TYPECOMPACT:
1785 ipmi_sensor_name(name, sizeof(name), s2->typelen, s2->name);
1786 rc = add_child_sensors(sc, psdr, s2->share1 & 0xF,
1787 s2->sensor_num, s2->sensor_type, s2->event_code,
1788 s2->share2 & 0x7F, s2->entity_id, name);
1789 break;
1790
1791 default:
1792 return (0);
1793 }
1794
1795 return rc;
1796}
1797
1798static int
1799ipmi_is_dupname(char *name)
1800{
1801 struct ipmi_sensor *ipmi_s;
1802
1803 SLIST_FOREACH(ipmi_s, &ipmi_sensor_list, i_list) {
1804 if (strcmp(ipmi_s->i_envdesc, name) == 0) {
1805 return 1;
1806 }
1807 }
1808 return 0;
1809}
1810
1811int
1812add_child_sensors(struct ipmi_softc *sc, uint8_t *psdr, int count,
1813 int sensor_num, int sensor_type, int ext_type, int sensor_base,
1814 int entity, const char *name)
1815{
1816 int typ, idx, dupcnt, c;
1817 char *e;
1818 struct ipmi_sensor *psensor;
1819 struct sdrtype1 *s1 = (struct sdrtype1 *)psdr;
1820
1821 typ = ipmi_sensor_type(sensor_type, ext_type, entity);
1822 if (typ == -1) {
1823 dbg_printf(5, "Unknown sensor type:%.2x et:%.2x sn:%.2x "
1824 "name:%s\n", sensor_type, ext_type, sensor_num, name);
1825 return 0;
1826 }
1827 dupcnt = 0;
1828 sc->sc_nsensors += count;
1829 for (idx = 0; idx < count; idx++) {
1830 psensor = malloc(sizeof(struct ipmi_sensor), M_DEVBUF,
1831 M_WAITOK|M_CANFAIL);
1832 if (psensor == NULL)
1833 break;
1834
1835 memset(psensor, 0, sizeof(struct ipmi_sensor));
1836
1837 /* Initialize BSD Sensor info */
1838 psensor->i_sdr = psdr;
1839 psensor->i_num = sensor_num + idx;
1840 psensor->i_stype = sensor_type;
1841 psensor->i_etype = ext_type;
1842 psensor->i_envtype = typ;
1843 if (count > 1)
1844 snprintf(psensor->i_envdesc,
1845 sizeof(psensor->i_envdesc),
1846 "%s - %d", name, sensor_base + idx);
1847 else
1848 strlcpy(psensor->i_envdesc, name,
1849 sizeof(psensor->i_envdesc));
1850
1851 /*
1852 * Check for duplicates. If there are duplicates,
1853 * make sure there is space in the name (if not,
1854 * truncate to make space) for a count (1-99) to
1855 * add to make the name unique. If we run the
1856 * counter out, just accept the duplicate (@name99)
1857 * for now.
1858 */
1859 if (ipmi_is_dupname(psensor->i_envdesc)) {
1860 if (strlen(psensor->i_envdesc) >=
1861 sizeof(psensor->i_envdesc) - 3) {
1862 e = psensor->i_envdesc +
1863 sizeof(psensor->i_envdesc) - 3;
1864 } else {
1865 e = psensor->i_envdesc +
1866 strlen(psensor->i_envdesc);
1867 }
1868 c = psensor->i_envdesc +
1869 sizeof(psensor->i_envdesc) - e;
1870 do {
1871 dupcnt++;
1872 snprintf(e, c, "%d", dupcnt);
1873 } while (dupcnt < 100 &&
1874 ipmi_is_dupname(psensor->i_envdesc));
1875 }
1876
1877 dbg_printf(5, "add sensor:%.4x %.2x:%d ent:%.2x:%.2x %s\n",
1878 s1->sdrhdr.record_id, s1->sensor_type,
1879 typ, s1->entity_id, s1->entity_instance,
1880 psensor->i_envdesc);
1881 SLIST_INSERT_HEAD(&ipmi_sensor_list, psensor, i_list);
1882 }
1883
1884 return (1);
1885}
1886
1887/* Interrupt handler */
1888int
1889ipmi_intr(void *arg)
1890{
1891 struct ipmi_softc *sc = (struct ipmi_softc *)arg;
1892 int v;
1893
1894 v = bmc_read(sc, _KCS_STATUS_REGISTER);
1895 if (v & KCS_OBF)
1896 ++ipmi_nintr;
1897
1898 return (0);
1899}
1900
1901/* Handle IPMI Timer - reread sensor values */
1902void
1903ipmi_refresh_sensors(struct ipmi_softc *sc)
1904{
1905
1906 if (SLIST_EMPTY(&ipmi_sensor_list))
1907 return;
1908
1909 sc->current_sensor = SLIST_NEXT(sc->current_sensor, i_list);
1910 if (sc->current_sensor == NULL)
1911 sc->current_sensor = SLIST_FIRST(&ipmi_sensor_list);
1912
1913 if (read_sensor(sc, sc->current_sensor)) {
1914 dbg_printf(1, "ipmi: error reading\n");
1915 }
1916}
1917
1918int
1919ipmi_map_regs(struct ipmi_softc *sc, struct ipmi_attach_args *ia)
1920{
1921 sc->sc_if = ipmi_get_if(ia->iaa_if_type);
1922 if (sc->sc_if == NULL)
1923 return (-1);
1924
1925 if (ia->iaa_if_iotype == 'i')
1926 sc->sc_iot = ia->iaa_iot;
1927 else
1928 sc->sc_iot = ia->iaa_memt;
1929
1930 sc->sc_if_rev = ia->iaa_if_rev;
1931 sc->sc_if_iospacing = ia->iaa_if_iospacing;
1932 if (bus_space_map(sc->sc_iot, ia->iaa_if_iobase,
1933 sc->sc_if->nregs * sc->sc_if_iospacing,
1934 0, &sc->sc_ioh)) {
1935 printf("ipmi: bus_space_map(..., %x, %x, 0, %p) failed\n",
1936 ia->iaa_if_iobase,
1937 sc->sc_if->nregs * sc->sc_if_iospacing, &sc->sc_ioh);
1938 return (-1);
1939 }
1940#if 0
1941 if (iaa->if_if_irq != -1)
1942 sc->ih = isa_intr_establish(-1, iaa->if_if_irq,
1943 iaa->if_irqlvl, IPL_BIO, ipmi_intr, sc,
1944 device_xname(sc->sc_dev);
1945#endif
1946 return (0);
1947}
1948
1949void
1950ipmi_unmap_regs(struct ipmi_softc *sc)
1951{
1952 bus_space_unmap(sc->sc_iot, sc->sc_ioh,
1953 sc->sc_if->nregs * sc->sc_if_iospacing);
1954}
1955
1956int
1957ipmi_probe(struct ipmi_attach_args *ia)
1958{
1959 struct dmd_ipmi *pipmi;
1960 struct smbtable tbl;
1961
1962 tbl.cookie = 0;
1963
1964 if (smbios_find_table(SMBIOS_TYPE_IPMIDEV, &tbl))
1965 ipmi_smbios_probe(tbl.tblhdr, ia);
1966 else {
1967 pipmi = (struct dmd_ipmi *)scan_sig(0xC0000L, 0xFFFFFL, 16, 4,
1968 "IPMI");
1969 /* XXX hack to find Dell PowerEdge 8450 */
1970 if (pipmi == NULL) {
1971 /* no IPMI found */
1972 return (0);
1973 }
1974
1975 /* we have an IPMI signature, fill in attach arg structure */
1976 ia->iaa_if_type = pipmi->dmd_if_type;
1977 ia->iaa_if_rev = pipmi->dmd_if_rev;
1978 }
1979
1980 return (1);
1981}
1982
1983int
1984ipmi_match(device_t parent, cfdata_t cf, void *aux)
1985{
1986 struct ipmi_softc sc;
1987 struct ipmi_attach_args *ia = aux;
1988 uint8_t cmd[32];
1989 int len;
1990 int rv = 0;
1991
1992 memset(&sc, 0, sizeof(sc));
1993
1994 /* Map registers */
1995 if (ipmi_map_regs(&sc, ia) != 0)
1996 return 0;
1997
1998 sc.sc_if->probe(&sc);
1999
2000 mutex_init(&sc.sc_cmd_mtx, MUTEX_DEFAULT, IPL_SOFTCLOCK);
2001 cv_init(&sc.sc_cmd_sleep, "ipmimtch");
2002 mutex_enter(&sc.sc_cmd_mtx);
2003 /* Identify BMC device early to detect lying bios */
2004 if (ipmi_sendcmd(&sc, BMC_SA, 0, APP_NETFN, APP_GET_DEVICE_ID,
2005 0, NULL)) {
2006 mutex_exit(&sc.sc_cmd_mtx);
2007 dbg_printf(1, ": unable to send get device id "
2008 "command\n");
2009 goto unmap;
2010 }
2011 if (ipmi_recvcmd(&sc, sizeof(cmd), &len, cmd)) {
2012 mutex_exit(&sc.sc_cmd_mtx);
2013 dbg_printf(1, ": unable to retrieve device id\n");
2014 goto unmap;
2015 }
2016 mutex_exit(&sc.sc_cmd_mtx);
2017
2018 dbg_dump(1, "bmc data", len, cmd);
2019 rv = 1; /* GETID worked, we got IPMI */
2020unmap:
2021 cv_destroy(&sc.sc_cmd_sleep);
2022 mutex_destroy(&sc.sc_cmd_mtx);
2023 ipmi_unmap_regs(&sc);
2024
2025 return rv;
2026}
2027
2028static void
2029ipmi_thread(void *cookie)
2030{
2031 device_t self = cookie;
2032 struct ipmi_softc *sc = device_private(self);
2033 struct ipmi_attach_args *ia = &sc->sc_ia;
2034 uint16_t rec;
2035 struct ipmi_sensor *ipmi_s;
2036 int i;
2037
2038 sc->sc_thread_running = true;
2039
2040 /* setup ticker */
2041 sc->sc_max_retries = hz * 90; /* 90 seconds max */
2042
2043 /* Map registers */
2044 ipmi_map_regs(sc, ia);
2045
2046 /* Scan SDRs, add sensors to list */
2047 for (rec = 0; rec != 0xFFFF;)
2048 if (get_sdr(sc, rec, &rec))
2049 break;
2050
2051 /* allocate and fill sensor arrays */
2052 sc->sc_sensor =
2053 malloc(sizeof(envsys_data_t) * sc->sc_nsensors,
2054 M_DEVBUF, M_WAITOK | M_ZERO);
2055 if (sc->sc_sensor == NULL) {
2056 aprint_error("ipmi: can't allocate envsys_data_t\n");
2057 kthread_exit(0);
2058 }
2059
2060 sc->sc_envsys = sysmon_envsys_create();
2061 sc->sc_envsys->sme_cookie = sc;
2062 sc->sc_envsys->sme_get_limits = ipmi_get_limits;
2063 sc->sc_envsys->sme_set_limits = ipmi_set_limits;
2064
2065 i = 0;
2066 SLIST_FOREACH(ipmi_s, &ipmi_sensor_list, i_list) {
2067 ipmi_s->i_props = 0;
2068 ipmi_s->i_envnum = -1;
2069 sc->sc_sensor[i].units = ipmi_s->i_envtype;
2070 sc->sc_sensor[i].state = ENVSYS_SINVALID;
2071 sc->sc_sensor[i].flags |= ENVSYS_FHAS_ENTROPY;
2072 /*
2073 * Monitor threshold limits in the sensors.
2074 */
2075 switch (sc->sc_sensor[i].units) {
2076 case ENVSYS_STEMP:
2077 case ENVSYS_SVOLTS_DC:
2078 case ENVSYS_SFANRPM:
2079 sc->sc_sensor[i].flags |= ENVSYS_FMONLIMITS;
2080 break;
2081 default:
2082 sc->sc_sensor[i].flags |= ENVSYS_FMONCRITICAL;
2083 }
2084 (void)strlcpy(sc->sc_sensor[i].desc, ipmi_s->i_envdesc,
2085 sizeof(sc->sc_sensor[i].desc));
2086 ++i;
2087
2088 if (sysmon_envsys_sensor_attach(sc->sc_envsys,
2089 &sc->sc_sensor[i-1]))
2090 continue;
2091
2092 /* get reference number from envsys */
2093 ipmi_s->i_envnum = sc->sc_sensor[i-1].sensor;
2094 }
2095
2096 sc->sc_envsys->sme_name = device_xname(sc->sc_dev);
2097 sc->sc_envsys->sme_flags = SME_DISABLE_REFRESH;
2098
2099 if (sysmon_envsys_register(sc->sc_envsys)) {
2100 aprint_error("ipmi: unable to register with sysmon\n");
2101 sysmon_envsys_destroy(sc->sc_envsys);
2102 }
2103
2104 /* initialize sensor list for thread */
2105 if (!SLIST_EMPTY(&ipmi_sensor_list))
2106 sc->current_sensor = SLIST_FIRST(&ipmi_sensor_list);
2107
2108 aprint_verbose_dev(self, "version %d.%d interface %s %sbase "
2109 "0x%x/%x spacing %d\n",
2110 ia->iaa_if_rev >> 4, ia->iaa_if_rev & 0xF, sc->sc_if->name,
2111 ia->iaa_if_iotype == 'i' ? "io" : "mem", ia->iaa_if_iobase,
2112 ia->iaa_if_iospacing * sc->sc_if->nregs, ia->iaa_if_iospacing);
2113 if (ia->iaa_if_irq != -1)
2114 aprint_verbose_dev(self, " irq %d\n", ia->iaa_if_irq);
2115
2116 /* setup flag to exclude iic */
2117 ipmi_enabled = 1;
2118
2119 /* Setup Watchdog timer */
2120 sc->sc_wdog.smw_name = device_xname(sc->sc_dev);
2121 sc->sc_wdog.smw_cookie = sc;
2122 sc->sc_wdog.smw_setmode = ipmi_watchdog_setmode;
2123 sc->sc_wdog.smw_tickle = ipmi_watchdog_tickle;
2124 sysmon_wdog_register(&sc->sc_wdog);
2125
2126 /* Set up a power handler so we can possibly sleep */
2127 if (!pmf_device_register(self, ipmi_suspend, NULL))
2128 aprint_error_dev(self, "couldn't establish a power handler\n");
2129
2130 mutex_enter(&sc->sc_poll_mtx);
2131 while (sc->sc_thread_running) {
2132 ipmi_refresh_sensors(sc);
2133 cv_timedwait(&sc->sc_poll_cv, &sc->sc_poll_mtx,
2134 SENSOR_REFRESH_RATE);
2135 if (sc->sc_tickle_due) {
2136 ipmi_dotickle(sc);
2137 sc->sc_tickle_due = false;
2138 }
2139 }
2140 mutex_exit(&sc->sc_poll_mtx);
2141 kthread_exit(0);
2142}
2143
2144void
2145ipmi_attach(device_t parent, device_t self, void *aux)
2146{
2147 struct ipmi_softc *sc = device_private(self);
2148
2149 sc->sc_ia = *(struct ipmi_attach_args *)aux;
2150 sc->sc_dev = self;
2151 aprint_naive("\n");
2152 aprint_normal("\n");
2153
2154 /* lock around read_sensor so that no one messes with the bmc regs */
2155 mutex_init(&sc->sc_cmd_mtx, MUTEX_DEFAULT, IPL_SOFTCLOCK);
2156 mutex_init(&sc->sc_sleep_mtx, MUTEX_DEFAULT, IPL_SOFTCLOCK);
2157 cv_init(&sc->sc_cmd_sleep, "ipmicmd");
2158
2159 mutex_init(&sc->sc_poll_mtx, MUTEX_DEFAULT, IPL_SOFTCLOCK);
2160 cv_init(&sc->sc_poll_cv, "ipmipoll");
2161
2162 if (kthread_create(PRI_NONE, 0, NULL, ipmi_thread, self,
2163 &sc->sc_kthread, "ipmi") != 0) {
2164 aprint_error("ipmi: unable to create thread, disabled\n");
2165 }
2166}
2167
2168static int
2169ipmi_detach(device_t self, int flags)
2170{
2171 struct ipmi_sensor *i;
2172 int rc;
2173 struct ipmi_softc *sc = device_private(self);
2174
2175 mutex_enter(&sc->sc_poll_mtx);
2176 sc->sc_thread_running = false;
2177 cv_signal(&sc->sc_poll_cv);
2178 mutex_exit(&sc->sc_poll_mtx);
2179
2180 if ((rc = sysmon_wdog_unregister(&sc->sc_wdog)) != 0) {
2181 if (rc == ERESTART)
2182 rc = EINTR;
2183 return rc;
2184 }
2185
2186 /* cancel any pending countdown */
2187 sc->sc_wdog.smw_mode &= ~WDOG_MODE_MASK;
2188 sc->sc_wdog.smw_mode |= WDOG_MODE_DISARMED;
2189 sc->sc_wdog.smw_period = WDOG_PERIOD_DEFAULT;
2190
2191 if ((rc = ipmi_watchdog_setmode(&sc->sc_wdog)) != 0)
2192 return rc;
2193
2194 ipmi_enabled = 0;
2195
2196 if (sc->sc_envsys != NULL) {
2197 /* _unregister also destroys */
2198 sysmon_envsys_unregister(sc->sc_envsys);
2199 sc->sc_envsys = NULL;
2200 }
2201
2202 while ((i = SLIST_FIRST(&ipmi_sensor_list)) != NULL) {
2203 SLIST_REMOVE_HEAD(&ipmi_sensor_list, i_list);
2204 free(i, M_DEVBUF);
2205 }
2206
2207 if (sc->sc_sensor != NULL) {
2208 free(sc->sc_sensor, M_DEVBUF);
2209 sc->sc_sensor = NULL;
2210 }
2211
2212 ipmi_unmap_regs(sc);
2213
2214 cv_destroy(&sc->sc_poll_cv);
2215 mutex_destroy(&sc->sc_poll_mtx);
2216 cv_destroy(&sc->sc_cmd_sleep);
2217 mutex_destroy(&sc->sc_sleep_mtx);
2218 mutex_destroy(&sc->sc_cmd_mtx);
2219
2220 return 0;
2221}
2222
2223int
2224ipmi_watchdog_setmode(struct sysmon_wdog *smwdog)
2225{
2226 struct ipmi_softc *sc = smwdog->smw_cookie;
2227 struct ipmi_get_watchdog gwdog;
2228 struct ipmi_set_watchdog swdog;
2229 int rc, len;
2230
2231 if (smwdog->smw_period < 10)
2232 return EINVAL;
2233 if (smwdog->smw_period == WDOG_PERIOD_DEFAULT)
2234 sc->sc_wdog.smw_period = 10;
2235 else
2236 sc->sc_wdog.smw_period = smwdog->smw_period;
2237
2238 mutex_enter(&sc->sc_cmd_mtx);
2239 /* see if we can properly task to the watchdog */
2240 rc = ipmi_sendcmd(sc, BMC_SA, BMC_LUN, APP_NETFN,
2241 APP_GET_WATCHDOG_TIMER, 0, NULL);
2242 rc = ipmi_recvcmd(sc, sizeof(gwdog), &len, &gwdog);
2243 mutex_exit(&sc->sc_cmd_mtx);
2244 if (rc) {
2245 printf("ipmi: APP_GET_WATCHDOG_TIMER returned 0x%x\n", rc);
2246 return EIO;
2247 }
2248
2249 memset(&swdog, 0, sizeof(swdog));
2250 /* Period is 10ths/sec */
2251 swdog.wdog_timeout = htole16(sc->sc_wdog.smw_period * 10);
2252 if ((smwdog->smw_mode & WDOG_MODE_MASK) == WDOG_MODE_DISARMED)
2253 swdog.wdog_action = IPMI_WDOG_ACT_DISABLED;
2254 else
2255 swdog.wdog_action = IPMI_WDOG_ACT_RESET;
2256 swdog.wdog_use = IPMI_WDOG_USE_USE_OS;
2257
2258 mutex_enter(&sc->sc_cmd_mtx);
2259 if ((rc = ipmi_sendcmd(sc, BMC_SA, BMC_LUN, APP_NETFN,
2260 APP_SET_WATCHDOG_TIMER, sizeof(swdog), &swdog)) == 0)
2261 rc = ipmi_recvcmd(sc, 0, &len, NULL);
2262 mutex_exit(&sc->sc_cmd_mtx);
2263 if (rc) {
2264 printf("ipmi: APP_SET_WATCHDOG_TIMER returned 0x%x\n", rc);
2265 return EIO;
2266 }
2267
2268 return (0);
2269}
2270
2271int
2272ipmi_watchdog_tickle(struct sysmon_wdog *smwdog)
2273{
2274 struct ipmi_softc *sc = smwdog->smw_cookie;
2275
2276 mutex_enter(&sc->sc_poll_mtx);
2277 sc->sc_tickle_due = true;
2278 cv_signal(&sc->sc_poll_cv);
2279 mutex_exit(&sc->sc_poll_mtx);
2280 return 0;
2281}
2282
2283void
2284ipmi_dotickle(struct ipmi_softc *sc)
2285{
2286 int rc, len;
2287
2288 mutex_enter(&sc->sc_cmd_mtx);
2289 /* tickle the watchdog */
2290 if ((rc = ipmi_sendcmd(sc, BMC_SA, BMC_LUN, APP_NETFN,
2291 APP_RESET_WATCHDOG, 0, NULL)) == 0)
2292 rc = ipmi_recvcmd(sc, 0, &len, NULL);
2293 mutex_exit(&sc->sc_cmd_mtx);
2294 if (rc != 0) {
2295 printf("%s: watchdog tickle returned 0x%x\n",
2296 device_xname(sc->sc_dev), rc);
2297 }
2298}
2299
2300bool
2301ipmi_suspend(device_t dev, const pmf_qual_t *qual)
2302{
2303 struct ipmi_softc *sc = device_private(dev);
2304
2305 /* Don't allow suspend if watchdog is armed */
2306 if ((sc->sc_wdog.smw_mode & WDOG_MODE_MASK) != WDOG_MODE_DISARMED)
2307 return false;
2308 return true;
2309}
2310