Annotation of sys/dev/ipmi.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: ipmi.c,v 1.58 2007/05/29 06:36:56 claudio Exp $ */
2:
3: /*
4: * Copyright (c) 2005 Jordan Hargrave
5: * All rights reserved.
6: *
7: * Redistribution and use in source and binary forms, with or without
8: * modification, are permitted provided that the following conditions
9: * are met:
10: * 1. Redistributions of source code must retain the above copyright
11: * notice, this list of conditions and the following disclaimer.
12: * 2. Redistributions in binary form must reproduce the above copyright
13: * notice, this list of conditions and the following disclaimer in the
14: * documentation and/or other materials provided with the distribution.
15: *
16: * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
17: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19: * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR
20: * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26: * SUCH DAMAGE.
27: */
28:
29: #include <sys/types.h>
30: #include <sys/param.h>
31: #include <sys/systm.h>
32: #include <sys/kernel.h>
33: #include <sys/device.h>
34: #include <sys/extent.h>
35: #include <sys/timeout.h>
36: #include <sys/sensors.h>
37: #include <sys/malloc.h>
38: #include <sys/kthread.h>
39:
40: #include <machine/bus.h>
41: #include <machine/intr.h>
42: #include <machine/smbiosvar.h>
43:
44: #include <dev/isa/isareg.h>
45: #include <dev/isa/isavar.h>
46:
47: #include <dev/ipmivar.h>
48:
49: #include <uvm/uvm_extern.h>
50:
51: struct ipmi_sensor {
52: u_int8_t *i_sdr;
53: int i_num;
54: int stype;
55: int etype;
56: struct ksensor i_sensor;
57: SLIST_ENTRY(ipmi_sensor) list;
58: };
59:
60: int ipmi_nintr;
61: int ipmi_poll = 1;
62: int ipmi_enabled = 0;
63:
64: #define SENSOR_REFRESH_RATE (5 * hz)
65:
66: #define SMBIOS_TYPE_IPMI 0x26
67:
68: #define DEVNAME(s) ((s)->sc_dev.dv_xname)
69:
70: /*
71: * Format of SMBIOS IPMI Flags
72: *
73: * bit0: interrupt trigger mode (1=level, 0=edge)
74: * bit1: interrupt polarity (1=active high, 0=active low)
75: * bit2: reserved
76: * bit3: address LSB (1=odd,0=even)
77: * bit4: interrupt (1=specified, 0=not specified)
78: * bit5: reserved
79: * bit6/7: register spacing (1,4,2,err)
80: */
81: #define SMIPMI_FLAG_IRQLVL (1L << 0)
82: #define SMIPMI_FLAG_IRQEN (1L << 3)
83: #define SMIPMI_FLAG_ODDOFFSET (1L << 4)
84: #define SMIPMI_FLAG_IFSPACING(x) (((x)>>6)&0x3)
85: #define IPMI_IOSPACING_BYTE 0
86: #define IPMI_IOSPACING_WORD 2
87: #define IPMI_IOSPACING_DWORD 1
88:
89: #define IPMI_BTMSG_LEN 0
90: #define IPMI_BTMSG_NFLN 1
91: #define IPMI_BTMSG_SEQ 2
92: #define IPMI_BTMSG_CMD 3
93: #define IPMI_BTMSG_CCODE 4
94: #define IPMI_BTMSG_DATASND 4
95: #define IPMI_BTMSG_DATARCV 5
96:
97: #define IPMI_MSG_NFLN 0
98: #define IPMI_MSG_CMD 1
99: #define IPMI_MSG_CCODE 2
100: #define IPMI_MSG_DATASND 2
101: #define IPMI_MSG_DATARCV 3
102:
103: #define IPMI_SENSOR_TYPE_TEMP 0x0101
104: #define IPMI_SENSOR_TYPE_VOLT 0x0102
105: #define IPMI_SENSOR_TYPE_FAN 0x0104
106: #define IPMI_SENSOR_TYPE_INTRUSION 0x6F05
107: #define IPMI_SENSOR_TYPE_PWRSUPPLY 0x6F08
108:
109: #define IPMI_NAME_UNICODE 0x00
110: #define IPMI_NAME_BCDPLUS 0x01
111: #define IPMI_NAME_ASCII6BIT 0x02
112: #define IPMI_NAME_ASCII8BIT 0x03
113:
114: #define IPMI_ENTITY_PWRSUPPLY 0x0A
115:
116: #define IPMI_INVALID_SENSOR (1L << 5)
117:
118: #define IPMI_SDR_TYPEFULL 1
119: #define IPMI_SDR_TYPECOMPACT 2
120:
121: #define byteof(x) ((x) >> 3)
122: #define bitof(x) (1L << ((x) & 0x7))
123: #define TB(b,m) (data[2+byteof(b)] & bitof(b))
124:
125: #ifdef IPMI_DEBUG
126: int ipmi_dbg = 0;
127: #define dbg_printf(lvl, fmt...) \
128: if (ipmi_dbg >= lvl) \
129: printf(fmt);
130: #define dbg_dump(lvl, msg, len, buf) \
131: if (len && ipmi_dbg >= lvl) \
132: dumpb(msg, len, (const u_int8_t *)(buf));
133: #else
134: #define dbg_printf(lvl, fmt...)
135: #define dbg_dump(lvl, msg, len, buf)
136: #endif
137:
138: long signextend(unsigned long, int);
139:
140: SLIST_HEAD(ipmi_sensors_head, ipmi_sensor);
141: struct ipmi_sensors_head ipmi_sensor_list =
142: SLIST_HEAD_INITIALIZER(&ipmi_sensor_list);
143:
144: struct timeout ipmi_timeout;
145:
146: void dumpb(const char *, int, const u_int8_t *);
147:
148: int read_sensor(struct ipmi_softc *, struct ipmi_sensor *);
149: int add_sdr_sensor(struct ipmi_softc *, u_int8_t *);
150: int get_sdr_partial(struct ipmi_softc *, u_int16_t, u_int16_t,
151: u_int8_t, u_int8_t, void *, u_int16_t *);
152: int get_sdr(struct ipmi_softc *, u_int16_t, u_int16_t *);
153:
154: int ipmi_sendcmd(struct ipmi_softc *, int, int, int, int, int, const void*);
155: int ipmi_recvcmd(struct ipmi_softc *, int, int *, void *);
156: void ipmi_delay(struct ipmi_softc *, int);
157:
158: int ipmi_watchdog(void *, int);
159:
160: int ipmi_intr(void *);
161: int ipmi_match(struct device *, void *, void *);
162: void ipmi_attach(struct device *, struct device *, void *);
163:
164: long ipow(long, int);
165: long ipmi_convert(u_int8_t, struct sdrtype1 *, long);
166: void ipmi_sensor_name(char *, int, u_int8_t, u_int8_t *);
167:
168: /* BMC Helper Functions */
169: u_int8_t bmc_read(struct ipmi_softc *, int);
170: void bmc_write(struct ipmi_softc *, int, u_int8_t);
171: int bmc_io_wait(struct ipmi_softc *, int, u_int8_t, u_int8_t, const char *);
172: int bmc_io_wait_cold(struct ipmi_softc *, int, u_int8_t, u_int8_t,
173: const char *);
174: void _bmc_io_wait(void *);
175:
176: void *bt_buildmsg(struct ipmi_softc *, int, int, int, const void *, int *);
177: void *cmn_buildmsg(struct ipmi_softc *, int, int, int, const void *, int *);
178:
179: int getbits(u_int8_t *, int, int);
180: int ipmi_sensor_type(int, int, int);
181:
182: void ipmi_smbios_probe(struct smbios_ipmi *, struct ipmi_attach_args *);
183: void ipmi_refresh_sensors(struct ipmi_softc *sc);
184: int ipmi_map_regs(struct ipmi_softc *sc, struct ipmi_attach_args *ia);
185: void ipmi_unmap_regs(struct ipmi_softc *sc, struct ipmi_attach_args *ia);
186:
187: void *scan_sig(long, long, int, int, const void *);
188:
189: int ipmi_test_threshold(u_int8_t, u_int8_t, u_int8_t, u_int8_t);
190: int ipmi_sensor_status(struct ipmi_softc *, struct ipmi_sensor *,
191: u_int8_t *);
192:
193: int add_child_sensors(struct ipmi_softc *, u_int8_t *, int, int, int,
194: int, int, int, const char *);
195:
196: struct ipmi_if kcs_if = {
197: "KCS",
198: IPMI_IF_KCS_NREGS,
199: cmn_buildmsg,
200: kcs_sendmsg,
201: kcs_recvmsg,
202: kcs_reset,
203: kcs_probe,
204: };
205:
206: struct ipmi_if smic_if = {
207: "SMIC",
208: IPMI_IF_SMIC_NREGS,
209: cmn_buildmsg,
210: smic_sendmsg,
211: smic_recvmsg,
212: smic_reset,
213: smic_probe,
214: };
215:
216: struct ipmi_if bt_if = {
217: "BT",
218: IPMI_IF_BT_NREGS,
219: bt_buildmsg,
220: bt_sendmsg,
221: bt_recvmsg,
222: bt_reset,
223: bt_probe,
224: };
225:
226: struct ipmi_if *ipmi_get_if(int);
227:
228: struct ipmi_if *
229: ipmi_get_if(int iftype)
230: {
231: switch (iftype) {
232: case IPMI_IF_KCS:
233: return (&kcs_if);
234: case IPMI_IF_SMIC:
235: return (&smic_if);
236: case IPMI_IF_BT:
237: return (&bt_if);
238: }
239:
240: return (NULL);
241: }
242:
243: /*
244: * BMC Helper Functions
245: */
246: u_int8_t
247: bmc_read(struct ipmi_softc *sc, int offset)
248: {
249: return (bus_space_read_1(sc->sc_iot, sc->sc_ioh,
250: offset * sc->sc_if_iospacing));
251: }
252:
253: void
254: bmc_write(struct ipmi_softc *sc, int offset, u_int8_t val)
255: {
256: bus_space_write_1(sc->sc_iot, sc->sc_ioh,
257: offset * sc->sc_if_iospacing, val);
258: }
259:
260: void
261: _bmc_io_wait(void *arg)
262: {
263: struct ipmi_softc *sc = arg;
264: struct ipmi_bmc_args *a = sc->sc_iowait_args;
265:
266: *a->v = bmc_read(sc, a->offset);
267: if ((*a->v & a->mask) == a->value) {
268: sc->sc_wakeup = 0;
269: wakeup(sc);
270: return;
271: }
272:
273: if (++sc->sc_retries > sc->sc_max_retries) {
274: sc->sc_wakeup = 0;
275: wakeup(sc);
276: return;
277: }
278:
279: timeout_add(&sc->sc_timeout, 1);
280: }
281:
282: int
283: bmc_io_wait(struct ipmi_softc *sc, int offset, u_int8_t mask, u_int8_t value,
284: const char *lbl)
285: {
286: volatile u_int8_t v;
287: struct ipmi_bmc_args args;
288:
289: if (cold)
290: return (bmc_io_wait_cold(sc, offset, mask, value, lbl));
291:
292: sc->sc_retries = 0;
293: sc->sc_wakeup = 1;
294:
295: args.offset = offset;
296: args.mask = mask;
297: args.value = value;
298: args.v = &v;
299: sc->sc_iowait_args = &args;
300:
301: _bmc_io_wait(sc);
302:
303: while (sc->sc_wakeup)
304: tsleep(sc, PWAIT, lbl, 0);
305:
306: if (sc->sc_retries > sc->sc_max_retries) {
307: dbg_printf(1, "%s: bmc_io_wait fails : v=%.2x m=%.2x "
308: "b=%.2x %s\n", DEVNAME(sc), v, mask, value, lbl);
309: return (-1);
310: }
311:
312: return (v);
313: }
314:
315: int
316: bmc_io_wait_cold(struct ipmi_softc *sc, int offset, u_int8_t mask,
317: u_int8_t value, const char *lbl)
318: {
319: volatile u_int8_t v;
320: int count = 5000000; /* == 5s XXX can be shorter */
321:
322: while (count--) {
323: v = bmc_read(sc, offset);
324: if ((v & mask) == value)
325: return v;
326:
327: delay(1);
328: }
329:
330: dbg_printf(1, "%s: bmc_io_wait_cold fails : *v=%.2x m=%.2x b=%.2x %s\n",
331: DEVNAME(sc), v, mask, value, lbl);
332: return (-1);
333:
334: }
335:
336: #define NETFN_LUN(nf,ln) (((nf) << 2) | ((ln) & 0x3))
337:
338: /*
339: * BT interface
340: */
341: #define _BT_CTRL_REG 0
342: #define BT_CLR_WR_PTR (1L << 0)
343: #define BT_CLR_RD_PTR (1L << 1)
344: #define BT_HOST2BMC_ATN (1L << 2)
345: #define BT_BMC2HOST_ATN (1L << 3)
346: #define BT_EVT_ATN (1L << 4)
347: #define BT_HOST_BUSY (1L << 6)
348: #define BT_BMC_BUSY (1L << 7)
349:
350: #define BT_READY (BT_HOST_BUSY|BT_HOST2BMC_ATN|BT_BMC2HOST_ATN)
351:
352: #define _BT_DATAIN_REG 1
353: #define _BT_DATAOUT_REG 1
354:
355: #define _BT_INTMASK_REG 2
356: #define BT_IM_HIRQ_PEND (1L << 1)
357: #define BT_IM_SCI_EN (1L << 2)
358: #define BT_IM_SMI_EN (1L << 3)
359: #define BT_IM_NMI2SMI (1L << 4)
360:
361: int bt_read(struct ipmi_softc *, int);
362: int bt_write(struct ipmi_softc *, int, uint8_t);
363:
364: int
365: bt_read(struct ipmi_softc *sc, int reg)
366: {
367: return bmc_read(sc, reg);
368: }
369:
370: int
371: bt_write(struct ipmi_softc *sc, int reg, uint8_t data)
372: {
373: if (bmc_io_wait(sc, _BT_CTRL_REG, BT_BMC_BUSY, 0, "bt_write") < 0)
374: return (-1);
375:
376: bmc_write(sc, reg, data);
377: return (0);
378: }
379:
380: int
381: bt_sendmsg(struct ipmi_softc *sc, int len, const u_int8_t *data)
382: {
383: int i;
384:
385: bt_write(sc, _BT_CTRL_REG, BT_CLR_WR_PTR);
386: for (i = 0; i < len; i++)
387: bt_write(sc, _BT_DATAOUT_REG, data[i]);
388:
389: bt_write(sc, _BT_CTRL_REG, BT_HOST2BMC_ATN);
390: if (bmc_io_wait(sc, _BT_CTRL_REG, BT_HOST2BMC_ATN | BT_BMC_BUSY, 0,
391: "bt_sendwait") < 0)
392: return (-1);
393:
394: return (0);
395: }
396:
397: int
398: bt_recvmsg(struct ipmi_softc *sc, int maxlen, int *rxlen, u_int8_t *data)
399: {
400: u_int8_t len, v, i;
401:
402: if (bmc_io_wait(sc, _BT_CTRL_REG, BT_BMC2HOST_ATN, BT_BMC2HOST_ATN,
403: "bt_recvwait") < 0)
404: return (-1);
405:
406: bt_write(sc, _BT_CTRL_REG, BT_HOST_BUSY);
407: bt_write(sc, _BT_CTRL_REG, BT_BMC2HOST_ATN);
408: bt_write(sc, _BT_CTRL_REG, BT_CLR_RD_PTR);
409: len = bt_read(sc, _BT_DATAIN_REG);
410: for (i = IPMI_BTMSG_NFLN; i <= len; i++) {
411: v = bt_read(sc, _BT_DATAIN_REG);
412: if (i != IPMI_BTMSG_SEQ)
413: *(data++) = v;
414: }
415: bt_write(sc, _BT_CTRL_REG, BT_HOST_BUSY);
416: *rxlen = len - 1;
417:
418: return (0);
419: }
420:
421: int
422: bt_reset(struct ipmi_softc *sc)
423: {
424: return (-1);
425: }
426:
427: int
428: bt_probe(struct ipmi_softc *sc)
429: {
430: u_int8_t rv;
431:
432: rv = bmc_read(sc, _BT_CTRL_REG);
433: rv &= BT_HOST_BUSY;
434: rv |= BT_CLR_WR_PTR|BT_CLR_RD_PTR|BT_BMC2HOST_ATN|BT_HOST2BMC_ATN;
435: bmc_write(sc, _BT_CTRL_REG, rv);
436:
437: rv = bmc_read(sc, _BT_INTMASK_REG);
438: rv &= BT_IM_SCI_EN|BT_IM_SMI_EN|BT_IM_NMI2SMI;
439: rv |= BT_IM_HIRQ_PEND;
440: bmc_write(sc, _BT_INTMASK_REG, rv);
441:
442: #if 0
443: printf("bt_probe: %2x\n", v);
444: printf(" WR : %2x\n", v & BT_CLR_WR_PTR);
445: printf(" RD : %2x\n", v & BT_CLR_RD_PTR);
446: printf(" H2B : %2x\n", v & BT_HOST2BMC_ATN);
447: printf(" B2H : %2x\n", v & BT_BMC2HOST_ATN);
448: printf(" EVT : %2x\n", v & BT_EVT_ATN);
449: printf(" HBSY : %2x\n", v & BT_HOST_BUSY);
450: printf(" BBSY : %2x\n", v & BT_BMC_BUSY);
451: #endif
452: return (0);
453: }
454:
455: /*
456: * SMIC interface
457: */
458: #define _SMIC_DATAIN_REG 0
459: #define _SMIC_DATAOUT_REG 0
460:
461: #define _SMIC_CTRL_REG 1
462: #define SMS_CC_GET_STATUS 0x40
463: #define SMS_CC_START_TRANSFER 0x41
464: #define SMS_CC_NEXT_TRANSFER 0x42
465: #define SMS_CC_END_TRANSFER 0x43
466: #define SMS_CC_START_RECEIVE 0x44
467: #define SMS_CC_NEXT_RECEIVE 0x45
468: #define SMS_CC_END_RECEIVE 0x46
469: #define SMS_CC_TRANSFER_ABORT 0x47
470:
471: #define SMS_SC_READY 0xc0
472: #define SMS_SC_WRITE_START 0xc1
473: #define SMS_SC_WRITE_NEXT 0xc2
474: #define SMS_SC_WRITE_END 0xc3
475: #define SMS_SC_READ_START 0xc4
476: #define SMS_SC_READ_NEXT 0xc5
477: #define SMS_SC_READ_END 0xc6
478:
479: #define _SMIC_FLAG_REG 2
480: #define SMIC_BUSY (1L << 0)
481: #define SMIC_SMS_ATN (1L << 2)
482: #define SMIC_EVT_ATN (1L << 3)
483: #define SMIC_SMI (1L << 4)
484: #define SMIC_TX_DATA_RDY (1L << 6)
485: #define SMIC_RX_DATA_RDY (1L << 7)
486:
487: int smic_wait(struct ipmi_softc *, u_int8_t, u_int8_t, const char *);
488: int smic_write_cmd_data(struct ipmi_softc *, u_int8_t, const u_int8_t *);
489: int smic_read_data(struct ipmi_softc *, u_int8_t *);
490:
491: int
492: smic_wait(struct ipmi_softc *sc, u_int8_t mask, u_int8_t val, const char *lbl)
493: {
494: int v;
495:
496: /* Wait for expected flag bits */
497: v = bmc_io_wait(sc, _SMIC_FLAG_REG, mask, val, "smicwait");
498: if (v < 0)
499: return (-1);
500:
501: /* Return current status */
502: v = bmc_read(sc, _SMIC_CTRL_REG);
503: dbg_printf(99, "smic_wait = %.2x\n", v);
504: return (v);
505: }
506:
507: int
508: smic_write_cmd_data(struct ipmi_softc *sc, u_int8_t cmd, const u_int8_t *data)
509: {
510: int sts, v;
511:
512: dbg_printf(50, "smic_wcd: %.2x %.2x\n", cmd, data ? *data : -1);
513: sts = smic_wait(sc, SMIC_TX_DATA_RDY | SMIC_BUSY, SMIC_TX_DATA_RDY,
514: "smic_write_cmd_data ready");
515: if (sts < 0)
516: return (sts);
517:
518: bmc_write(sc, _SMIC_CTRL_REG, cmd);
519: if (data)
520: bmc_write(sc, _SMIC_DATAOUT_REG, *data);
521:
522: /* Toggle BUSY bit, then wait for busy bit to clear */
523: v = bmc_read(sc, _SMIC_FLAG_REG);
524: bmc_write(sc, _SMIC_FLAG_REG, v | SMIC_BUSY);
525:
526: return (smic_wait(sc, SMIC_BUSY, 0, "smic_write_cmd_data busy"));
527: }
528:
529: int
530: smic_read_data(struct ipmi_softc *sc, u_int8_t *data)
531: {
532: int sts;
533:
534: sts = smic_wait(sc, SMIC_RX_DATA_RDY | SMIC_BUSY, SMIC_RX_DATA_RDY,
535: "smic_read_data");
536: if (sts >= 0) {
537: *data = bmc_read(sc, _SMIC_DATAIN_REG);
538: dbg_printf(50, "smic_readdata: %.2x\n", *data);
539: }
540: return (sts);
541: }
542:
543: #define ErrStat(a,b) if (a) printf(b);
544:
545: int
546: smic_sendmsg(struct ipmi_softc *sc, int len, const u_int8_t *data)
547: {
548: int sts, idx;
549:
550: sts = smic_write_cmd_data(sc, SMS_CC_START_TRANSFER, &data[0]);
551: ErrStat(sts != SMS_SC_WRITE_START, "wstart");
552: for (idx = 1; idx < len - 1; idx++) {
553: sts = smic_write_cmd_data(sc, SMS_CC_NEXT_TRANSFER,
554: &data[idx]);
555: ErrStat(sts != SMS_SC_WRITE_NEXT, "write");
556: }
557: sts = smic_write_cmd_data(sc, SMS_CC_END_TRANSFER, &data[idx]);
558: if (sts != SMS_SC_WRITE_END) {
559: dbg_printf(50, "smic_sendmsg %d/%d = %.2x\n", idx, len, sts);
560: return (-1);
561: }
562:
563: return (0);
564: }
565:
566: int
567: smic_recvmsg(struct ipmi_softc *sc, int maxlen, int *len, u_int8_t *data)
568: {
569: int sts, idx;
570:
571: *len = 0;
572: sts = smic_wait(sc, SMIC_RX_DATA_RDY, SMIC_RX_DATA_RDY, "smic_recvmsg");
573: if (sts < 0)
574: return (-1);
575:
576: sts = smic_write_cmd_data(sc, SMS_CC_START_RECEIVE, NULL);
577: ErrStat(sts != SMS_SC_READ_START, "rstart");
578: for (idx = 0;; ) {
579: sts = smic_read_data(sc, &data[idx++]);
580: if (sts != SMS_SC_READ_START && sts != SMS_SC_READ_NEXT)
581: break;
582: smic_write_cmd_data(sc, SMS_CC_NEXT_RECEIVE, NULL);
583: }
584: ErrStat(sts != SMS_SC_READ_END, "rend");
585:
586: *len = idx;
587:
588: sts = smic_write_cmd_data(sc, SMS_CC_END_RECEIVE, NULL);
589: if (sts != SMS_SC_READY) {
590: dbg_printf(50, "smic_recvmsg %d/%d = %.2x\n", idx, maxlen, sts);
591: return (-1);
592: }
593:
594: return (0);
595: }
596:
597: int
598: smic_reset(struct ipmi_softc *sc)
599: {
600: return (-1);
601: }
602:
603: int
604: smic_probe(struct ipmi_softc *sc)
605: {
606: /* Flag register should not be 0xFF on a good system */
607: if (bmc_read(sc, _SMIC_FLAG_REG) == 0xFF)
608: return (-1);
609:
610: return (0);
611: }
612:
613: /*
614: * KCS interface
615: */
616: #define _KCS_DATAIN_REGISTER 0
617: #define _KCS_DATAOUT_REGISTER 0
618: #define KCS_READ_NEXT 0x68
619:
620: #define _KCS_COMMAND_REGISTER 1
621: #define KCS_GET_STATUS 0x60
622: #define KCS_WRITE_START 0x61
623: #define KCS_WRITE_END 0x62
624:
625: #define _KCS_STATUS_REGISTER 1
626: #define KCS_OBF (1L << 0)
627: #define KCS_IBF (1L << 1)
628: #define KCS_SMS_ATN (1L << 2)
629: #define KCS_CD (1L << 3)
630: #define KCS_OEM1 (1L << 4)
631: #define KCS_OEM2 (1L << 5)
632: #define KCS_STATE_MASK 0xc0
633: #define KCS_IDLE_STATE 0x00
634: #define KCS_READ_STATE 0x40
635: #define KCS_WRITE_STATE 0x80
636: #define KCS_ERROR_STATE 0xC0
637:
638: int kcs_wait(struct ipmi_softc *, u_int8_t, u_int8_t, const char *);
639: int kcs_write_cmd(struct ipmi_softc *, u_int8_t);
640: int kcs_write_data(struct ipmi_softc *, u_int8_t);
641: int kcs_read_data(struct ipmi_softc *, u_int8_t *);
642:
643: int
644: kcs_wait(struct ipmi_softc *sc, u_int8_t mask, u_int8_t value, const char *lbl)
645: {
646: int v;
647:
648: v = bmc_io_wait(sc, _KCS_STATUS_REGISTER, mask, value, lbl);
649: if (v < 0)
650: return (v);
651:
652: /* Check if output buffer full, read dummy byte */
653: if ((v & (KCS_OBF | KCS_STATE_MASK)) == (KCS_OBF | KCS_WRITE_STATE))
654: bmc_read(sc, _KCS_DATAIN_REGISTER);
655:
656: /* Check for error state */
657: if ((v & KCS_STATE_MASK) == KCS_ERROR_STATE) {
658: bmc_write(sc, _KCS_COMMAND_REGISTER, KCS_GET_STATUS);
659: while (bmc_read(sc, _KCS_STATUS_REGISTER) & KCS_IBF)
660: ;
661: printf("%s: error code: %x\n", DEVNAME(sc),
662: bmc_read(sc, _KCS_DATAIN_REGISTER));
663: }
664:
665: return (v & KCS_STATE_MASK);
666: }
667:
668: int
669: kcs_write_cmd(struct ipmi_softc *sc, u_int8_t cmd)
670: {
671: /* ASSERT: IBF and OBF are clear */
672: dbg_printf(50, "kcswritecmd: %.2x\n", cmd);
673: bmc_write(sc, _KCS_COMMAND_REGISTER, cmd);
674:
675: return (kcs_wait(sc, KCS_IBF, 0, "write_cmd"));
676: }
677:
678: int
679: kcs_write_data(struct ipmi_softc *sc, u_int8_t data)
680: {
681: /* ASSERT: IBF and OBF are clear */
682: dbg_printf(50, "kcswritedata: %.2x\n", data);
683: bmc_write(sc, _KCS_DATAOUT_REGISTER, data);
684:
685: return (kcs_wait(sc, KCS_IBF, 0, "write_data"));
686: }
687:
688: int
689: kcs_read_data(struct ipmi_softc *sc, u_int8_t * data)
690: {
691: int sts;
692:
693: sts = kcs_wait(sc, KCS_IBF | KCS_OBF, KCS_OBF, "read_data");
694: if (sts != KCS_READ_STATE)
695: return (sts);
696:
697: /* ASSERT: OBF is set read data, request next byte */
698: *data = bmc_read(sc, _KCS_DATAIN_REGISTER);
699: bmc_write(sc, _KCS_DATAOUT_REGISTER, KCS_READ_NEXT);
700:
701: dbg_printf(50, "kcsreaddata: %.2x\n", *data);
702:
703: return (sts);
704: }
705:
706: /* Exported KCS functions */
707: int
708: kcs_sendmsg(struct ipmi_softc *sc, int len, const u_int8_t * data)
709: {
710: int idx, sts;
711:
712: /* ASSERT: IBF is clear */
713: dbg_dump(50, "kcs sendmsg", len, data);
714: sts = kcs_write_cmd(sc, KCS_WRITE_START);
715: for (idx = 0; idx < len; idx++) {
716: if (idx == len - 1)
717: sts = kcs_write_cmd(sc, KCS_WRITE_END);
718:
719: if (sts != KCS_WRITE_STATE)
720: break;
721:
722: sts = kcs_write_data(sc, data[idx]);
723: }
724: if (sts != KCS_READ_STATE) {
725: dbg_printf(1, "kcs sendmsg = %d/%d <%.2x>\n", idx, len, sts);
726: dbg_dump(1, "kcs_sendmsg", len, data);
727: return (-1);
728: }
729:
730: return (0);
731: }
732:
733: int
734: kcs_recvmsg(struct ipmi_softc *sc, int maxlen, int *rxlen, u_int8_t * data)
735: {
736: int idx, sts;
737:
738: for (idx = 0; idx < maxlen; idx++) {
739: sts = kcs_read_data(sc, &data[idx]);
740: if (sts != KCS_READ_STATE)
741: break;
742: }
743: sts = kcs_wait(sc, KCS_IBF, 0, "recv");
744: *rxlen = idx;
745: if (sts != KCS_IDLE_STATE) {
746: dbg_printf(1, "kcs read = %d/%d <%.2x>\n", idx, maxlen, sts);
747: return (-1);
748: }
749:
750: dbg_dump(50, "kcs recvmsg", idx, data);
751:
752: return (0);
753: }
754:
755: int
756: kcs_reset(struct ipmi_softc *sc)
757: {
758: return (-1);
759: }
760:
761: int
762: kcs_probe(struct ipmi_softc *sc)
763: {
764: u_int8_t v;
765:
766: v = bmc_read(sc, _KCS_STATUS_REGISTER);
767: #if 0
768: printf("kcs_probe: %2x\n", v);
769: printf(" STS: %2x\n", v & KCS_STATE_MASK);
770: printf(" ATN: %2x\n", v & KCS_SMS_ATN);
771: printf(" C/D: %2x\n", v & KCS_CD);
772: printf(" IBF: %2x\n", v & KCS_IBF);
773: printf(" OBF: %2x\n", v & KCS_OBF);
774: #endif
775: return (0);
776: }
777:
778: /*
779: * IPMI code
780: */
781: #define READ_SMS_BUFFER 0x37
782: #define WRITE_I2C 0x50
783:
784: #define GET_MESSAGE_CMD 0x33
785: #define SEND_MESSAGE_CMD 0x34
786:
787: #define IPMB_CHANNEL_NUMBER 0
788:
789: #define PUBLIC_BUS 0
790:
791: #define MIN_I2C_PACKET_SIZE 3
792: #define MIN_IMB_PACKET_SIZE 7 /* one byte for cksum */
793:
794: #define MIN_BTBMC_REQ_SIZE 4
795: #define MIN_BTBMC_RSP_SIZE 5
796: #define MIN_BMC_REQ_SIZE 2
797: #define MIN_BMC_RSP_SIZE 3
798:
799: #define BMC_SA 0x20 /* BMC/ESM3 */
800: #define FPC_SA 0x22 /* front panel */
801: #define BP_SA 0xC0 /* Primary Backplane */
802: #define BP2_SA 0xC2 /* Secondary Backplane */
803: #define PBP_SA 0xC4 /* Peripheral Backplane */
804: #define DRAC_SA 0x28 /* DRAC-III */
805: #define DRAC3_SA 0x30 /* DRAC-III */
806: #define BMC_LUN 0
807: #define SMS_LUN 2
808:
809: struct ipmi_request {
810: u_int8_t rsSa;
811: u_int8_t rsLun;
812: u_int8_t netFn;
813: u_int8_t cmd;
814: u_int8_t data_len;
815: u_int8_t *data;
816: };
817:
818: struct ipmi_response {
819: u_int8_t cCode;
820: u_int8_t data_len;
821: u_int8_t *data;
822: };
823:
824: struct ipmi_bmc_request {
825: u_int8_t bmc_nfLn;
826: u_int8_t bmc_cmd;
827: u_int8_t bmc_data_len;
828: u_int8_t bmc_data[1];
829: };
830:
831: struct ipmi_bmc_response {
832: u_int8_t bmc_nfLn;
833: u_int8_t bmc_cmd;
834: u_int8_t bmc_cCode;
835: u_int8_t bmc_data_len;
836: u_int8_t bmc_data[1];
837: };
838:
839: struct cfattach ipmi_ca = {
840: sizeof(struct ipmi_softc), ipmi_match, ipmi_attach
841: };
842:
843: struct cfdriver ipmi_cd = {
844: NULL, "ipmi", DV_DULL
845: };
846:
847: /* Scan memory for signature */
848: void *
849: scan_sig(long start, long end, int skip, int len, const void *data)
850: {
851: void *va;
852:
853: while (start < end) {
854: va = ISA_HOLE_VADDR(start);
855: if (memcmp(va, data, len) == 0)
856: return (va);
857:
858: start += skip;
859: }
860:
861: return (NULL);
862: }
863:
864: void
865: dumpb(const char *lbl, int len, const u_int8_t *data)
866: {
867: int idx;
868:
869: printf("%s: ", lbl);
870: for (idx = 0; idx < len; idx++)
871: printf("%.2x ", data[idx]);
872:
873: printf("\n");
874: }
875:
876: void
877: ipmi_smbios_probe(struct smbios_ipmi *pipmi, struct ipmi_attach_args *ia)
878: {
879:
880: dbg_printf(1, "ipmi_smbios_probe: %02x %02x %02x %02x %08llx %02x "
881: "%02x\n",
882: pipmi->smipmi_if_type,
883: pipmi->smipmi_if_rev,
884: pipmi->smipmi_i2c_address,
885: pipmi->smipmi_nvram_address,
886: pipmi->smipmi_base_address,
887: pipmi->smipmi_base_flags,
888: pipmi->smipmi_irq);
889:
890: ia->iaa_if_type = pipmi->smipmi_if_type;
891: ia->iaa_if_rev = pipmi->smipmi_if_rev;
892: ia->iaa_if_irq = (pipmi->smipmi_base_flags & SMIPMI_FLAG_IRQEN) ?
893: pipmi->smipmi_irq : -1;
894: ia->iaa_if_irqlvl = (pipmi->smipmi_base_flags & SMIPMI_FLAG_IRQLVL) ?
895: IST_LEVEL : IST_EDGE;
896:
897: switch (SMIPMI_FLAG_IFSPACING(pipmi->smipmi_base_flags)) {
898: case IPMI_IOSPACING_BYTE:
899: ia->iaa_if_iospacing = 1;
900: break;
901:
902: case IPMI_IOSPACING_DWORD:
903: ia->iaa_if_iospacing = 4;
904: break;
905:
906: case IPMI_IOSPACING_WORD:
907: ia->iaa_if_iospacing = 2;
908: break;
909:
910: default:
911: ia->iaa_if_iospacing = 1;
912: printf("ipmi: unknown register spacing\n");
913: }
914:
915: /* Calculate base address (PCI BAR format) */
916: if (pipmi->smipmi_base_address & 0x1) {
917: ia->iaa_if_iotype = 'i';
918: ia->iaa_if_iobase = pipmi->smipmi_base_address & ~0x1;
919: } else {
920: ia->iaa_if_iotype = 'm';
921: ia->iaa_if_iobase = pipmi->smipmi_base_address & ~0xF;
922: }
923: if (pipmi->smipmi_base_flags & SMIPMI_FLAG_ODDOFFSET)
924: ia->iaa_if_iobase++;
925:
926: if (pipmi->smipmi_base_flags == 0x7f) {
927: /* IBM 325 eServer workaround */
928: ia->iaa_if_iospacing = 1;
929: ia->iaa_if_iobase = pipmi->smipmi_base_address;
930: ia->iaa_if_iotype = 'i';
931: return;
932: }
933: }
934:
935: /*
936: * bt_buildmsg builds an IPMI message from a nfLun, cmd, and data
937: * This is used by BT protocol
938: *
939: * Returns a buffer to an allocated message, txlen contains length
940: * of allocated message
941: */
942: void *
943: bt_buildmsg(struct ipmi_softc *sc, int nfLun, int cmd, int len,
944: const void *data, int *txlen)
945: {
946: u_int8_t *buf;
947:
948: /* Block transfer needs 4 extra bytes: length/netfn/seq/cmd + data */
949: *txlen = len + 4;
950: buf = malloc(*txlen, M_DEVBUF, M_NOWAIT|M_CANFAIL);
951: if (buf == NULL)
952: return (NULL);
953:
954: buf[IPMI_BTMSG_LEN] = len + 3;
955: buf[IPMI_BTMSG_NFLN] = nfLun;
956: buf[IPMI_BTMSG_SEQ] = sc->sc_btseq++;
957: buf[IPMI_BTMSG_CMD] = cmd;
958: if (len && data)
959: memcpy(buf + IPMI_BTMSG_DATASND, data, len);
960:
961: return (buf);
962: }
963:
964: /*
965: * cmn_buildmsg builds an IPMI message from a nfLun, cmd, and data
966: * This is used by both SMIC and KCS protocols
967: *
968: * Returns a buffer to an allocated message, txlen contains length
969: * of allocated message
970: */
971: void *
972: cmn_buildmsg(struct ipmi_softc *sc, int nfLun, int cmd, int len,
973: const void *data, int *txlen)
974: {
975: u_int8_t *buf;
976:
977: /* Common needs two extra bytes: nfLun/cmd + data */
978: *txlen = len + 2;
979: buf = malloc(*txlen, M_DEVBUF, M_NOWAIT|M_CANFAIL);
980: if (buf == NULL)
981: return (NULL);
982:
983: buf[IPMI_MSG_NFLN] = nfLun;
984: buf[IPMI_MSG_CMD] = cmd;
985: if (len && data)
986: memcpy(buf + IPMI_MSG_DATASND, data, len);
987:
988: return (buf);
989: }
990:
991: /* Send an IPMI command */
992: int
993: ipmi_sendcmd(struct ipmi_softc *sc, int rssa, int rslun, int netfn, int cmd,
994: int txlen, const void *data)
995: {
996: u_int8_t *buf;
997: int rc = -1;
998:
999: dbg_printf(50, "ipmi_sendcmd: rssa=%.2x nfln=%.2x cmd=%.2x len=%.2x\n",
1000: rssa, NETFN_LUN(netfn, rslun), cmd, txlen);
1001: dbg_dump(10, " send", txlen, data);
1002: if (rssa != BMC_SA) {
1003: #if 0
1004: buf = sc->sc_if->buildmsg(sc, NETFN_LUN(APP_NETFN, BMC_LUN),
1005: APP_SEND_MESSAGE, 7 + txlen, NULL, &txlen);
1006: pI2C->bus = (sc->if_ver == 0x09) ?
1007: PUBLIC_BUS :
1008: IPMB_CHANNEL_NUMBER;
1009:
1010: imbreq->rsSa = rssa;
1011: imbreq->nfLn = NETFN_LUN(netfn, rslun);
1012: imbreq->cSum1 = -(imbreq->rsSa + imbreq->nfLn);
1013: imbreq->rqSa = BMC_SA;
1014: imbreq->seqLn = NETFN_LUN(sc->imb_seq++, SMS_LUN);
1015: imbreq->cmd = cmd;
1016: if (txlen)
1017: memcpy(imbreq->data, data, txlen);
1018: /* Set message checksum */
1019: imbreq->data[txlen] = cksum8(&imbreq->rqSa, txlen + 3);
1020: #endif
1021: goto done;
1022: } else
1023: buf = sc->sc_if->buildmsg(sc, NETFN_LUN(netfn, rslun), cmd,
1024: txlen, data, &txlen);
1025:
1026: if (buf == NULL) {
1027: printf("%s: sendcmd malloc fails\n", DEVNAME(sc));
1028: goto done;
1029: }
1030: rc = sc->sc_if->sendmsg(sc, txlen, buf);
1031: free(buf, M_DEVBUF);
1032:
1033: ipmi_delay(sc, 5); /* give bmc chance to digest command */
1034:
1035: done:
1036: return (rc);
1037: }
1038:
1039: int
1040: ipmi_recvcmd(struct ipmi_softc *sc, int maxlen, int *rxlen, void *data)
1041: {
1042: u_int8_t *buf, rc = 0;
1043: int rawlen;
1044:
1045: /* Need three extra bytes: netfn/cmd/ccode + data */
1046: buf = malloc(maxlen + 3, M_DEVBUF, M_NOWAIT|M_CANFAIL);
1047: if (buf == NULL) {
1048: printf("%s: ipmi_recvcmd: malloc fails\n", DEVNAME(sc));
1049: return (-1);
1050: }
1051: /* Receive message from interface, copy out result data */
1052: if (sc->sc_if->recvmsg(sc, maxlen + 3, &rawlen, buf))
1053: return (-1);
1054:
1055: *rxlen = rawlen - IPMI_MSG_DATARCV;
1056: if (*rxlen > 0 && data)
1057: memcpy(data, buf + IPMI_MSG_DATARCV, *rxlen);
1058:
1059: rc = buf[IPMI_MSG_CCODE];
1060: #ifdef IPMI_DEBUG
1061: if (rc != 0)
1062: dbg_printf(1, "ipmi_recvmsg: nfln=%.2x cmd=%.2x err=%.2x\n",
1063: buf[IPMI_MSG_NFLN], buf[IPMI_MSG_CMD], buf[IPMI_MSG_CCODE]);
1064: #endif
1065:
1066: dbg_printf(50, "ipmi_recvcmd: nfln=%.2x cmd=%.2x err=%.2x len=%.2x\n",
1067: buf[IPMI_MSG_NFLN], buf[IPMI_MSG_CMD], buf[IPMI_MSG_CCODE],
1068: *rxlen);
1069: dbg_dump(10, " recv", *rxlen, data);
1070:
1071: free(buf, M_DEVBUF);
1072:
1073: ipmi_delay(sc, 5); /* give bmc chance to digest command */
1074:
1075: return (rc);
1076: }
1077:
1078: void
1079: ipmi_delay(struct ipmi_softc *sc, int period)
1080: {
1081: /* period is in 10 ms increments */
1082: if (cold)
1083: delay(period * 10000);
1084: else
1085: while (tsleep(sc, PWAIT, "ipmicmd", period) != EWOULDBLOCK);
1086: }
1087:
1088: /* Read a partial SDR entry */
1089: int
1090: get_sdr_partial(struct ipmi_softc *sc, u_int16_t recordId, u_int16_t reserveId,
1091: u_int8_t offset, u_int8_t length, void *buffer, u_int16_t *nxtRecordId)
1092: {
1093: u_int8_t cmd[8 + length];
1094: int len;
1095:
1096: ((u_int16_t *) cmd)[0] = reserveId;
1097: ((u_int16_t *) cmd)[1] = recordId;
1098: cmd[4] = offset;
1099: cmd[5] = length;
1100: if (ipmi_sendcmd(sc, BMC_SA, 0, STORAGE_NETFN, STORAGE_GET_SDR, 6,
1101: cmd)) {
1102: printf("%s: sendcmd fails\n", DEVNAME(sc));
1103: return (-1);
1104: }
1105: if (ipmi_recvcmd(sc, 8 + length, &len, cmd)) {
1106: printf("%s: getSdrPartial: recvcmd fails\n", DEVNAME(sc));
1107: return (-1);
1108: }
1109: if (nxtRecordId)
1110: *nxtRecordId = *(uint16_t *) cmd;
1111: memcpy(buffer, cmd + 2, len - 2);
1112:
1113: return (0);
1114: }
1115:
1116: int maxsdrlen = 0x10;
1117:
1118: /* Read an entire SDR; pass to add sensor */
1119: int
1120: get_sdr(struct ipmi_softc *sc, u_int16_t recid, u_int16_t *nxtrec)
1121: {
1122: u_int16_t resid = 0;
1123: int len, sdrlen, offset;
1124: u_int8_t *psdr;
1125: struct sdrhdr shdr;
1126:
1127: /* Reserve SDR */
1128: if (ipmi_sendcmd(sc, BMC_SA, 0, STORAGE_NETFN, STORAGE_RESERVE_SDR,
1129: 0, NULL)) {
1130: printf(": reserve send fails\n");
1131: return (-1);
1132: }
1133: if (ipmi_recvcmd(sc, sizeof(resid), &len, &resid)) {
1134: printf(": reserve recv fails\n");
1135: return (-1);
1136: }
1137: /* Get SDR Header */
1138: if (get_sdr_partial(sc, recid, resid, 0, sizeof shdr, &shdr, nxtrec)) {
1139: printf(": get header fails\n");
1140: return (-1);
1141: }
1142: /* Allocate space for entire SDR Length of SDR in header does not
1143: * include header length */
1144: sdrlen = sizeof(shdr) + shdr.record_length;
1145: psdr = malloc(sdrlen, M_DEVBUF, M_NOWAIT|M_CANFAIL);
1146: if (psdr == NULL)
1147: return -1;
1148:
1149: memcpy(psdr, &shdr, sizeof(shdr));
1150:
1151: /* Read SDR Data maxsdrlen bytes at a time */
1152: for (offset = sizeof(shdr); offset < sdrlen; offset += maxsdrlen) {
1153: len = sdrlen - offset;
1154: if (len > maxsdrlen)
1155: len = maxsdrlen;
1156:
1157: if (get_sdr_partial(sc, recid, resid, offset, len,
1158: psdr + offset, NULL)) {
1159: printf(": get chunk: %d,%d fails\n", offset, len);
1160: return (-1);
1161: }
1162: }
1163:
1164: /* Add SDR to sensor list, if not wanted, free buffer */
1165: if (add_sdr_sensor(sc, psdr) == 0)
1166: free(psdr, M_DEVBUF);
1167:
1168: return (0);
1169: }
1170:
1171: int
1172: getbits(u_int8_t *bytes, int bitpos, int bitlen)
1173: {
1174: int v;
1175: int mask;
1176:
1177: bitpos += bitlen - 1;
1178: for (v = 0; bitlen--;) {
1179: v <<= 1;
1180: mask = 1L << (bitpos & 7);
1181: if (bytes[bitpos >> 3] & mask)
1182: v |= 1;
1183: bitpos--;
1184: }
1185:
1186: return (v);
1187: }
1188:
1189: /* Decode IPMI sensor name */
1190: void
1191: ipmi_sensor_name(char *name, int len, u_int8_t typelen, u_int8_t *bits)
1192: {
1193: int i, slen;
1194: char bcdplus[] = "0123456789 -.:,_";
1195:
1196: slen = typelen & 0x1F;
1197: switch (typelen >> 6) {
1198: case IPMI_NAME_UNICODE:
1199: //unicode
1200: break;
1201:
1202: case IPMI_NAME_BCDPLUS:
1203: /* Characters are encoded in 4-bit BCDPLUS */
1204: if (len < slen * 2 + 1)
1205: slen = (len >> 1) - 1;
1206: for (i = 0; i < slen; i++) {
1207: *(name++) = bcdplus[bits[i] >> 4];
1208: *(name++) = bcdplus[bits[i] & 0xF];
1209: }
1210: break;
1211:
1212: case IPMI_NAME_ASCII6BIT:
1213: /* Characters are encoded in 6-bit ASCII
1214: * 0x00 - 0x3F maps to 0x20 - 0x5F */
1215: /* XXX: need to calculate max len: slen = 3/4 * len */
1216: if (len < slen + 1)
1217: slen = len - 1;
1218: for (i = 0; i < slen * 8; i += 6)
1219: *(name++) = getbits(bits, i, 6) + ' ';
1220: break;
1221:
1222: case IPMI_NAME_ASCII8BIT:
1223: /* Characters are 8-bit ascii */
1224: if (len < slen + 1)
1225: slen = len - 1;
1226: while (slen--)
1227: *(name++) = *(bits++);
1228: break;
1229: }
1230: *name = 0;
1231: }
1232:
1233: /* Calculate val * 10^exp */
1234: long
1235: ipow(long val, int exp)
1236: {
1237: while (exp > 0) {
1238: val *= 10;
1239: exp--;
1240: }
1241:
1242: while (exp < 0) {
1243: val /= 10;
1244: exp++;
1245: }
1246:
1247: return (val);
1248: }
1249:
1250: /* Sign extend a n-bit value */
1251: long
1252: signextend(unsigned long val, int bits)
1253: {
1254: long msk = (1L << (bits-1))-1;
1255:
1256: return (-(val & ~msk) | val);
1257: }
1258:
1259: /* Convert IPMI reading from sensor factors */
1260: long
1261: ipmi_convert(u_int8_t v, struct sdrtype1 *s1, long adj)
1262: {
1263: short M, B;
1264: char K1, K2;
1265: long val;
1266:
1267: /* Calculate linear reading variables */
1268: M = signextend((((short)(s1->m_tolerance & 0xC0)) << 2) + s1->m, 10);
1269: B = signextend((((short)(s1->b_accuracy & 0xC0)) << 2) + s1->b, 10);
1270: K1 = signextend(s1->rbexp & 0xF, 4);
1271: K2 = signextend(s1->rbexp >> 4, 4);
1272:
1273: /* Calculate sensor reading:
1274: * y = L((M * v + (B * 10^K1)) * 10^(K2+adj)
1275: *
1276: * This commutes out to:
1277: * y = L(M*v * 10^(K2+adj) + B * 10^(K1+K2+adj)); */
1278: val = ipow(M * v, K2 + adj) + ipow(B, K1 + K2 + adj);
1279:
1280: /* Linearization function: y = f(x) 0 : y = x 1 : y = ln(x) 2 : y =
1281: * log10(x) 3 : y = log2(x) 4 : y = e^x 5 : y = 10^x 6 : y = 2^x 7 : y
1282: * = 1/x 8 : y = x^2 9 : y = x^3 10 : y = square root(x) 11 : y = cube
1283: * root(x) */
1284: return (val);
1285: }
1286:
1287: int
1288: ipmi_test_threshold(u_int8_t v, u_int8_t valid, u_int8_t hi, u_int8_t lo)
1289: {
1290: dbg_printf(10, "thresh: %.2x %.2x %.2x %d\n", v, lo, hi,valid);
1291: return ((valid & 1 && lo != 0x00 && v <= lo) ||
1292: (valid & 8 && hi != 0xFF && v >= hi));
1293: }
1294:
1295: int
1296: ipmi_sensor_status(struct ipmi_softc *sc, struct ipmi_sensor *psensor,
1297: u_int8_t *reading)
1298: {
1299: u_int8_t data[32];
1300: struct sdrtype1 *s1 = (struct sdrtype1 *)psensor->i_sdr;
1301: int rxlen, etype;
1302:
1303: /* Get reading of sensor */
1304: switch (psensor->i_sensor.type) {
1305: case SENSOR_TEMP:
1306: psensor->i_sensor.value = ipmi_convert(reading[0], s1, 6);
1307: psensor->i_sensor.value += 273150000;
1308: break;
1309:
1310: case SENSOR_VOLTS_DC:
1311: psensor->i_sensor.value = ipmi_convert(reading[0], s1, 6);
1312: break;
1313:
1314: case SENSOR_FANRPM:
1315: psensor->i_sensor.value = ipmi_convert(reading[0], s1, 0);
1316: if (((s1->units1>>3)&0x7) == 0x3)
1317: psensor->i_sensor.value *= 60; // RPS -> RPM
1318: break;
1319: default:
1320: break;
1321: }
1322:
1323: /* Return Sensor Status */
1324: etype = (psensor->etype << 8) + psensor->stype;
1325: switch (etype) {
1326: case IPMI_SENSOR_TYPE_TEMP:
1327: case IPMI_SENSOR_TYPE_VOLT:
1328: case IPMI_SENSOR_TYPE_FAN:
1329: data[0] = psensor->i_num;
1330: if (ipmi_sendcmd(sc, s1->owner_id, s1->owner_lun,
1331: SE_NETFN, SE_GET_SENSOR_THRESHOLD, 1, data) ||
1332: ipmi_recvcmd(sc, sizeof(data), &rxlen, data))
1333: return (SENSOR_S_UNKNOWN);
1334:
1335: dbg_printf(25, "recvdata: %.2x %.2x %.2x %.2x %.2x %.2x %.2x\n",
1336: data[0], data[1], data[2], data[3], data[4], data[5],
1337: data[6]);
1338:
1339: if (ipmi_test_threshold(*reading, data[0] >> 2 ,
1340: data[6], data[3]))
1341: return (SENSOR_S_CRIT);
1342:
1343: if (ipmi_test_threshold(*reading, data[0] >> 1,
1344: data[5], data[2]))
1345: return (SENSOR_S_CRIT);
1346:
1347: if (ipmi_test_threshold(*reading, data[0] ,
1348: data[4], data[1]))
1349: return (SENSOR_S_WARN);
1350:
1351: break;
1352:
1353: case IPMI_SENSOR_TYPE_INTRUSION:
1354: psensor->i_sensor.value = (reading[2] & 1) ? 1 : 0;
1355: if (reading[2] & 0x1)
1356: return (SENSOR_S_CRIT);
1357: break;
1358:
1359: case IPMI_SENSOR_TYPE_PWRSUPPLY:
1360: /* Reading: 1 = present+powered, 0 = otherwise */
1361: psensor->i_sensor.value = (reading[2] & 1) ? 1 : 0;
1362: if (reading[2] & 0x10) {
1363: /* XXX: Need sysctl type for Power Supply types
1364: * ok: power supply installed && powered
1365: * warn: power supply installed && !powered
1366: * crit: power supply !installed
1367: */
1368: return (SENSOR_S_CRIT);
1369: }
1370: if (reading[2] & 0x08) {
1371: /* Power supply AC lost */
1372: return (SENSOR_S_WARN);
1373: }
1374: break;
1375: }
1376:
1377: return (SENSOR_S_OK);
1378: }
1379:
1380: int
1381: read_sensor(struct ipmi_softc *sc, struct ipmi_sensor *psensor)
1382: {
1383: struct sdrtype1 *s1 = (struct sdrtype1 *) psensor->i_sdr;
1384: u_int8_t data[8];
1385: int rxlen, rv = -1;
1386:
1387: if (!cold)
1388: rw_enter_write(&sc->sc_lock);
1389:
1390: memset(data, 0, sizeof(data));
1391: data[0] = psensor->i_num;
1392: if (ipmi_sendcmd(sc, s1->owner_id, s1->owner_lun, SE_NETFN,
1393: SE_GET_SENSOR_READING, 1, data))
1394: goto done;
1395:
1396: if (ipmi_recvcmd(sc, sizeof(data), &rxlen, data))
1397: goto done;
1398:
1399: dbg_printf(10, "values=%.2x %.2x %.2x %.2x %s\n",
1400: data[0],data[1],data[2],data[3], psensor->i_sensor.desc);
1401: psensor->i_sensor.flags &= ~SENSOR_FINVALID;
1402: if (data[1] & IPMI_INVALID_SENSOR) {
1403: /* Check if sensor is valid */
1404: psensor->i_sensor.flags |= SENSOR_FINVALID;
1405: }
1406: psensor->i_sensor.status = ipmi_sensor_status(sc, psensor, data);
1407: rv = 0;
1408: done:
1409: if (!cold)
1410: rw_exit_write(&sc->sc_lock);
1411: return (rv);
1412: }
1413:
1414: int
1415: ipmi_sensor_type(int type, int ext_type, int entity)
1416: {
1417: switch (ext_type << 8L | type) {
1418: case IPMI_SENSOR_TYPE_TEMP:
1419: return (SENSOR_TEMP);
1420:
1421: case IPMI_SENSOR_TYPE_VOLT:
1422: return (SENSOR_VOLTS_DC);
1423:
1424: case IPMI_SENSOR_TYPE_FAN:
1425: return (SENSOR_FANRPM);
1426:
1427: case IPMI_SENSOR_TYPE_PWRSUPPLY:
1428: if (entity == IPMI_ENTITY_PWRSUPPLY)
1429: return (SENSOR_INDICATOR);
1430: break;
1431:
1432: case IPMI_SENSOR_TYPE_INTRUSION:
1433: return (SENSOR_INDICATOR);
1434: }
1435:
1436: return (-1);
1437: }
1438:
1439: /* Add Sensor to BSD Sysctl interface */
1440: int
1441: add_sdr_sensor(struct ipmi_softc *sc, u_int8_t *psdr)
1442: {
1443: int rc;
1444: struct sdrtype1 *s1 = (struct sdrtype1 *)psdr;
1445: struct sdrtype2 *s2 = (struct sdrtype2 *)psdr;
1446: char name[64];
1447:
1448: switch (s1->sdrhdr.record_type) {
1449: case IPMI_SDR_TYPEFULL:
1450: ipmi_sensor_name(name, sizeof(name), s1->typelen, s1->name);
1451: rc = add_child_sensors(sc, psdr, 1, s1->sensor_num,
1452: s1->sensor_type, s1->event_code, 0, s1->entity_id, name);
1453: break;
1454:
1455: case IPMI_SDR_TYPECOMPACT:
1456: ipmi_sensor_name(name, sizeof(name), s2->typelen, s2->name);
1457: rc = add_child_sensors(sc, psdr, s2->share1 & 0xF,
1458: s2->sensor_num, s2->sensor_type, s2->event_code,
1459: s2->share2 & 0x7F, s2->entity_id, name);
1460: break;
1461:
1462: default:
1463: return (0);
1464: }
1465:
1466: return rc;
1467: }
1468:
1469: int
1470: add_child_sensors(struct ipmi_softc *sc, u_int8_t *psdr, int count,
1471: int sensor_num, int sensor_type, int ext_type, int sensor_base,
1472: int entity, const char *name)
1473: {
1474: int typ, idx;
1475: struct ipmi_sensor *psensor;
1476: #ifdef IPMI_DEBUG
1477: struct sdrtype1 *s1 = (struct sdrtype1 *)psdr;
1478: #endif
1479:
1480: typ = ipmi_sensor_type(sensor_type, ext_type, entity);
1481: if (typ == -1) {
1482: dbg_printf(5, "Unknown sensor type:%.2x et:%.2x sn:%.2x "
1483: "name:%s\n", sensor_type, ext_type, sensor_num, name);
1484: return 0;
1485: }
1486: for (idx = 0; idx < count; idx++) {
1487: psensor = malloc(sizeof(struct ipmi_sensor), M_DEVBUF,
1488: M_NOWAIT|M_CANFAIL);
1489: if (psensor == NULL)
1490: break;
1491:
1492: memset(psensor, 0, sizeof(struct ipmi_sensor));
1493:
1494: /* Initialize BSD Sensor info */
1495: psensor->i_sdr = psdr;
1496: psensor->i_num = sensor_num + idx;
1497: psensor->stype = sensor_type;
1498: psensor->etype = ext_type;
1499: psensor->i_sensor.type = typ;
1500: if (count > 1)
1501: snprintf(psensor->i_sensor.desc,
1502: sizeof(psensor->i_sensor.desc),
1503: "%s - %d", name, sensor_base + idx);
1504: else
1505: strlcpy(psensor->i_sensor.desc, name,
1506: sizeof(psensor->i_sensor.desc));
1507:
1508: dbg_printf(5, "add sensor:%.4x %.2x:%d ent:%.2x:%.2x %s\n",
1509: s1->sdrhdr.record_id, s1->sensor_type,
1510: typ, s1->entity_id, s1->entity_instance,
1511: psensor->i_sensor.desc);
1512: if (read_sensor(sc, psensor) == 0) {
1513: SLIST_INSERT_HEAD(&ipmi_sensor_list, psensor, list);
1514: sensor_attach(&sc->sc_sensordev, &psensor->i_sensor);
1515: dbg_printf(5, " reading: %lld [%s]\n",
1516: psensor->i_sensor.value,
1517: psensor->i_sensor.desc);
1518: }
1519: }
1520:
1521: return (1);
1522: }
1523:
1524: /* Interrupt handler */
1525: int
1526: ipmi_intr(void *arg)
1527: {
1528: struct ipmi_softc *sc = (struct ipmi_softc *)arg;
1529: int v;
1530:
1531: v = bmc_read(sc, _KCS_STATUS_REGISTER);
1532: if (v & KCS_OBF)
1533: ++ipmi_nintr;
1534:
1535: return (0);
1536: }
1537:
1538: /* Handle IPMI Timer - reread sensor values */
1539: void
1540: ipmi_refresh_sensors(struct ipmi_softc *sc)
1541: {
1542: if (!ipmi_poll)
1543: return;
1544:
1545: if (SLIST_EMPTY(&ipmi_sensor_list))
1546: return;
1547:
1548: sc->current_sensor = SLIST_NEXT(sc->current_sensor, list);
1549: if (sc->current_sensor == NULL)
1550: sc->current_sensor = SLIST_FIRST(&ipmi_sensor_list);
1551:
1552: if (read_sensor(sc, sc->current_sensor)) {
1553: dbg_printf(1, "%s: error reading: %s\n", DEVNAME(sc),
1554: sc->current_sensor->i_sensor.desc);
1555: return;
1556: }
1557: }
1558:
1559: int
1560: ipmi_map_regs(struct ipmi_softc *sc, struct ipmi_attach_args *ia)
1561: {
1562: sc->sc_if = ipmi_get_if(ia->iaa_if_type);
1563: if (sc->sc_if == NULL)
1564: return (-1);
1565:
1566: if (ia->iaa_if_iotype == 'i')
1567: sc->sc_iot = ia->iaa_iot;
1568: else
1569: sc->sc_iot = ia->iaa_memt;
1570:
1571: sc->sc_if_rev = ia->iaa_if_rev;
1572: sc->sc_if_iospacing = ia->iaa_if_iospacing;
1573: if (bus_space_map(sc->sc_iot, ia->iaa_if_iobase,
1574: sc->sc_if->nregs * sc->sc_if_iospacing,
1575: 0, &sc->sc_ioh)) {
1576: printf("%s: bus_space_map(%x %x %x 0 %p) failed\n",
1577: DEVNAME(sc),
1578: sc->sc_iot, ia->iaa_if_iobase,
1579: sc->sc_if->nregs * sc->sc_if_iospacing, &sc->sc_ioh);
1580: return (-1);
1581: }
1582: #if 0
1583: if (iaa->if_if_irq != -1)
1584: sc->ih = isa_intr_establish(-1, iaa->if_if_irq,
1585: iaa->if_irqlvl, IPL_BIO, ipmi_intr, sc, DEVNAME(sc));
1586: #endif
1587: return (0);
1588: }
1589:
1590: void
1591: ipmi_unmap_regs(struct ipmi_softc *sc, struct ipmi_attach_args *ia)
1592: {
1593: bus_space_unmap(sc->sc_iot, sc->sc_ioh,
1594: sc->sc_if->nregs * sc->sc_if_iospacing);
1595: }
1596:
1597: void
1598: ipmi_poll_thread(void *arg)
1599: {
1600: struct ipmi_thread *thread = arg;
1601: struct ipmi_softc *sc = thread->sc;
1602:
1603: while (thread->running) {
1604: ipmi_refresh_sensors(sc);
1605: tsleep(thread, PWAIT, "ipmi_poll", SENSOR_REFRESH_RATE);
1606: }
1607: free(thread, M_DEVBUF);
1608:
1609: kthread_exit(0);
1610: }
1611:
1612: void
1613: ipmi_create_thread(void *arg)
1614: {
1615: struct ipmi_softc *sc = arg;
1616:
1617: if (kthread_create(ipmi_poll_thread, sc->sc_thread, NULL,
1618: DEVNAME(sc)) != 0) {
1619: printf("%s: unable to create polling thread, ipmi disabled\n",
1620: DEVNAME(sc));
1621: return;
1622: }
1623: }
1624:
1625: int
1626: ipmi_probe(void *aux)
1627: {
1628: struct ipmi_attach_args *ia = aux;
1629: struct dmd_ipmi *pipmi;
1630: struct smbtable tbl;
1631:
1632: tbl.cookie = 0;
1633: if (smbios_find_table(SMBIOS_TYPE_IPMIDEV, &tbl))
1634: ipmi_smbios_probe(tbl.tblhdr, ia);
1635: else {
1636: pipmi = (struct dmd_ipmi *)scan_sig(0xC0000L, 0xFFFFFL, 16, 4,
1637: "IPMI");
1638: /* XXX hack to find Dell PowerEdge 8450 */
1639: if (pipmi == NULL) {
1640: /* no IPMI found */
1641: return (0);
1642: }
1643:
1644: /* we have an IPMI signature, fill in attach arg structure */
1645: ia->iaa_if_type = pipmi->dmd_if_type;
1646: ia->iaa_if_rev = pipmi->dmd_if_rev;
1647: }
1648:
1649: return (1);
1650: }
1651:
1652: int
1653: ipmi_match(struct device *parent, void *match, void *aux)
1654: {
1655: struct ipmi_softc sc;
1656: struct ipmi_attach_args *ia = aux;
1657: struct cfdata *cf = match;
1658: u_int8_t cmd[32];
1659: int len;
1660: int rv = 0;
1661:
1662: if (strcmp(ia->iaa_name, cf->cf_driver->cd_name))
1663: return (0);
1664:
1665: /* XXX local softc is wrong wrong wrong */
1666: strlcpy(sc.sc_dev.dv_xname, "ipmi0", sizeof(sc.sc_dev.dv_xname));
1667: /* Map registers */
1668: if (ipmi_map_regs(&sc, ia) == 0) {
1669: sc.sc_if->probe(&sc);
1670:
1671: /* Identify BMC device early to detect lying bios */
1672: if (ipmi_sendcmd(&sc, BMC_SA, 0, APP_NETFN, APP_GET_DEVICE_ID,
1673: 0, NULL)) {
1674: dbg_printf(1, ": unable to send get device id "
1675: "command\n");
1676: goto unmap;
1677: }
1678: if (ipmi_recvcmd(&sc, sizeof(cmd), &len, cmd)) {
1679: dbg_printf(1, ": unable to retrieve device id\n");
1680: goto unmap;
1681: }
1682:
1683: dbg_dump(1, "bmc data", len, cmd);
1684: unmap:
1685: rv = 1; /* GETID worked, we got IPMI */
1686: ipmi_unmap_regs(&sc, ia);
1687: }
1688:
1689: return (rv);
1690: }
1691:
1692: void
1693: ipmi_attach(struct device *parent, struct device *self, void *aux)
1694: {
1695: struct ipmi_softc *sc = (void *) self;
1696: struct ipmi_attach_args *ia = aux;
1697: u_int16_t rec;
1698:
1699: /* Map registers */
1700: ipmi_map_regs(sc, ia);
1701:
1702: /* Scan SDRs, add sensors */
1703: for (rec = 0; rec != 0xFFFF;) {
1704: if (get_sdr(sc, rec, &rec)) {
1705: /* IPMI may have been advertised, but it is stillborn */
1706: ipmi_unmap_regs(sc, ia);
1707: return;
1708: }
1709: }
1710:
1711: sc->sc_thread = malloc(sizeof(struct ipmi_thread), M_DEVBUF,
1712: M_NOWAIT|M_CANFAIL);
1713: if (sc->sc_thread == NULL) {
1714: printf(": unable to allocate thread\n");
1715: return;
1716: }
1717: sc->sc_thread->sc = sc;
1718: sc->sc_thread->running = 1;
1719:
1720: /* initialize sensor list for thread */
1721: if (!SLIST_EMPTY(&ipmi_sensor_list))
1722: sc->current_sensor = SLIST_FIRST(&ipmi_sensor_list);
1723:
1724: /* Setup threads */
1725: kthread_create_deferred(ipmi_create_thread, sc);
1726:
1727: strlcpy(sc->sc_sensordev.xname, sc->sc_dev.dv_xname,
1728: sizeof(sc->sc_sensordev.xname));
1729: sensordev_install(&sc->sc_sensordev);
1730:
1731: printf(": version %d.%d interface %s %sbase 0x%x/%x spacing %d",
1732: ia->iaa_if_rev >> 4, ia->iaa_if_rev & 0xF, sc->sc_if->name,
1733: ia->iaa_if_iotype == 'i' ? "io" : "mem", ia->iaa_if_iobase,
1734: ia->iaa_if_iospacing * sc->sc_if->nregs, ia->iaa_if_iospacing);
1735: if (ia->iaa_if_irq != -1)
1736: printf(" irq %d", ia->iaa_if_irq);
1737: printf("\n");
1738:
1739: /* setup flag to exclude iic */
1740: ipmi_enabled = 1;
1741:
1742: /* Setup Watchdog timer */
1743: sc->sc_wdog_period = 0;
1744: wdog_register(sc, ipmi_watchdog);
1745:
1746: /* lock around read_sensor so that no one messes with the bmc regs */
1747: rw_init(&sc->sc_lock, DEVNAME(sc));
1748:
1749: /* setup ticker */
1750: sc->sc_retries = 0;
1751: sc->sc_wakeup = 0;
1752: sc->sc_max_retries = 50; /* 50 * 1/100 = 0.5 seconds max */
1753: timeout_set(&sc->sc_timeout, _bmc_io_wait, sc);
1754: }
1755:
1756: int
1757: ipmi_watchdog(void *arg, int period)
1758: {
1759: struct ipmi_softc *sc = arg;
1760: struct ipmi_watchdog wdog;
1761: int s, rc, len;
1762:
1763: if (sc->sc_wdog_period == period) {
1764: if (period != 0) {
1765: s = splsoftclock();
1766: /* tickle the watchdog */
1767: rc = ipmi_sendcmd(sc, BMC_SA, BMC_LUN, APP_NETFN,
1768: APP_RESET_WATCHDOG, 0, NULL);
1769: rc = ipmi_recvcmd(sc, 0, &len, NULL);
1770: splx(s);
1771: }
1772: return (period);
1773: }
1774:
1775: if (period < 10 && period > 0)
1776: period = 10;
1777:
1778: s = splsoftclock();
1779: /* XXX what to do if poking wdog fails? */
1780: rc = ipmi_sendcmd(sc, BMC_SA, BMC_LUN, APP_NETFN,
1781: APP_GET_WATCHDOG_TIMER, 0, NULL);
1782: rc = ipmi_recvcmd(sc, sizeof(wdog), &len, &wdog);
1783:
1784: /* Period is 10ths/sec */
1785: wdog.wdog_timeout = htole32(period * 10);
1786: wdog.wdog_action &= ~IPMI_WDOG_MASK;
1787: wdog.wdog_action |= (period == 0) ? IPMI_WDOG_DISABLED :
1788: IPMI_WDOG_REBOOT;
1789:
1790: rc = ipmi_sendcmd(sc, BMC_SA, BMC_LUN, APP_NETFN,
1791: APP_SET_WATCHDOG_TIMER, sizeof(wdog), &wdog);
1792: rc = ipmi_recvcmd(sc, 0, &len, NULL);
1793:
1794: splx(s);
1795:
1796: sc->sc_wdog_period = period;
1797: return (period);
1798: }
CVSweb