LCOV - code coverage report
Current view: top level - dev - ipmi.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 812 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 64 0.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13