[BACK]Return to ipmi.c CVS log [TXT][DIR] Up to [local] / sys / dev

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