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