diff options
author | Masao Uebayashi <uebayasi@cvs.openbsd.org> | 2016-02-05 06:29:02 +0000 |
---|---|---|
committer | Masao Uebayashi <uebayasi@cvs.openbsd.org> | 2016-02-05 06:29:02 +0000 |
commit | 301f453b1544dd088417106b104584704927713d (patch) | |
tree | dce6673ee496ceef8e27e590f28a1df8db1f75dc | |
parent | 36c6b15245925ced646fdc8d2bf1972e10e38847 (diff) |
Implement FreeBSD-compatible IOCTL to access BMC in ipmi(4)
Initial help & testing by jmatthew@
Code review & input by mpi@
Final review & OK by jsg@
-rw-r--r-- | sys/arch/amd64/amd64/conf.c | 4 | ||||
-rw-r--r-- | sys/arch/i386/i386/conf.c | 4 | ||||
-rw-r--r-- | sys/dev/ipmi.c | 357 | ||||
-rw-r--r-- | sys/dev/ipmi.h | 123 | ||||
-rw-r--r-- | sys/dev/ipmivar.h | 27 | ||||
-rw-r--r-- | sys/sys/conf.h | 10 |
6 files changed, 360 insertions, 165 deletions
diff --git a/sys/arch/amd64/amd64/conf.c b/sys/arch/amd64/amd64/conf.c index d69887b3061..a10a2b786cb 100644 --- a/sys/arch/amd64/amd64/conf.c +++ b/sys/arch/amd64/amd64/conf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: conf.c,v 1.55 2016/01/27 09:04:19 reyk Exp $ */ +/* $OpenBSD: conf.c,v 1.56 2016/02/05 06:29:01 uebayasi Exp $ */ /* * Copyright (c) 1994, 1995 Charles M. Hannum. All rights reserved. @@ -183,6 +183,7 @@ cdev_decl(pci); #include "pppx.h" #include "fuse.h" #include "pvbus.h" +#include "ipmi.h" struct cdevsw cdevsw[] = { @@ -294,6 +295,7 @@ struct cdevsw cdevsw[] = cdev_tun_init(NTUN,tap), /* 93: Ethernet network tunnel */ cdev_tty_init(NVIOCON,viocon), /* 94: virtio console */ cdev_pvbus_init(NPVBUS,pvbus), /* 95: pvbus(4) control interface */ + cdev_ipmi_init(NIPMI,ipmi), /* 96: ipmi */ }; int nchrdev = nitems(cdevsw); diff --git a/sys/arch/i386/i386/conf.c b/sys/arch/i386/i386/conf.c index 668e13724a5..03e2298e12c 100644 --- a/sys/arch/i386/i386/conf.c +++ b/sys/arch/i386/i386/conf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: conf.c,v 1.152 2016/01/27 09:04:19 reyk Exp $ */ +/* $OpenBSD: conf.c,v 1.153 2016/02/05 06:29:01 uebayasi Exp $ */ /* $NetBSD: conf.c,v 1.75 1996/05/03 19:40:20 christos Exp $ */ /* @@ -177,6 +177,7 @@ cdev_decl(pci); #include "pppx.h" #include "fuse.h" #include "pvbus.h" +#include "ipmi.h" struct cdevsw cdevsw[] = { @@ -288,6 +289,7 @@ struct cdevsw cdevsw[] = cdev_fuse_init(NFUSE,fuse), /* 93: fuse */ cdev_tun_init(NTUN,tap), /* 94: Ethernet network tunnel */ cdev_pvbus_init(NPVBUS,pvbus), /* 95: pvbus(4) control interface */ + cdev_ipmi_init(NIPMI,ipmi), /* 96: ipmi */ }; int nchrdev = nitems(cdevsw); diff --git a/sys/dev/ipmi.c b/sys/dev/ipmi.c index 5812388ed51..1afc935fffa 100644 --- a/sys/dev/ipmi.c +++ b/sys/dev/ipmi.c @@ -1,6 +1,7 @@ -/* $OpenBSD: ipmi.c,v 1.91 2016/01/25 06:36:47 uebayasi Exp $ */ +/* $OpenBSD: ipmi.c,v 1.92 2016/02/05 06:29:01 uebayasi Exp $ */ /* + * Copyright (c) 2015 Masao Uebayashi * Copyright (c) 2005 Jordan Hargrave * All rights reserved. * @@ -31,21 +32,21 @@ #include <sys/systm.h> #include <sys/kernel.h> #include <sys/device.h> +#include <sys/ioctl.h> #include <sys/extent.h> -#include <sys/timeout.h> #include <sys/sensors.h> #include <sys/malloc.h> #include <sys/kthread.h> #include <sys/task.h> #include <machine/bus.h> -#include <machine/intr.h> #include <machine/smbiosvar.h> #include <dev/isa/isareg.h> #include <dev/isa/isavar.h> #include <dev/ipmivar.h> +#include <dev/ipmi.h> struct ipmi_sensor { u_int8_t *i_sdr; @@ -56,7 +57,6 @@ struct ipmi_sensor { SLIST_ENTRY(ipmi_sensor) list; }; -int ipmi_nintr; int ipmi_enabled = 0; #define SENSOR_REFRESH_RATE (5 * hz) @@ -140,8 +140,6 @@ SLIST_HEAD(ipmi_sensors_head, ipmi_sensor); struct ipmi_sensors_head ipmi_sensor_list = SLIST_HEAD_INITIALIZER(ipmi_sensor_list); -struct timeout ipmi_timeout; - void dumpb(const char *, int, const u_int8_t *); int read_sensor(struct ipmi_softc *, struct ipmi_sensor *); @@ -152,7 +150,6 @@ int get_sdr(struct ipmi_softc *, u_int16_t, u_int16_t *); int ipmi_sendcmd(struct ipmi_cmd *); int ipmi_recvcmd(struct ipmi_cmd *); -void ipmi_delay(struct ipmi_softc *, int); void ipmi_cmd(struct ipmi_cmd *); void ipmi_cmd_poll(struct ipmi_cmd *); void ipmi_cmd_wait(struct ipmi_cmd *); @@ -162,10 +159,14 @@ int ipmi_watchdog(void *, int); void ipmi_watchdog_tickle(void *); void ipmi_watchdog_set(void *); -int ipmi_intr(void *); int ipmi_match(struct device *, void *, void *); void ipmi_attach(struct device *, struct device *, void *); int ipmi_activate(struct device *, int); +struct ipmi_softc *ipmilookup(dev_t dev); + +int ipmiopen(dev_t, int, int, struct proc *); +int ipmiclose(dev_t, int, int, struct proc *); +int ipmiioctl(dev_t, u_long, caddr_t, int, struct proc *); long ipow(long, int); long ipmi_convert(u_int8_t, struct sdrtype1 *, long); @@ -174,10 +175,7 @@ void ipmi_sensor_name(char *, int, u_int8_t, u_int8_t *); /* BMC Helper Functions */ u_int8_t bmc_read(struct ipmi_softc *, int); void bmc_write(struct ipmi_softc *, int, u_int8_t); -int bmc_io_wait(struct ipmi_softc *, int, u_int8_t, u_int8_t, const char *); -int bmc_io_wait_cold(struct ipmi_softc *, int, u_int8_t, u_int8_t, - const char *); -void _bmc_io_wait(void *); +int bmc_io_wait(struct ipmi_softc *, struct ipmi_iowait *); void bt_buildmsg(struct ipmi_cmd *); void cmn_buildmsg(struct ipmi_cmd *); @@ -268,83 +266,29 @@ bmc_write(struct ipmi_softc *sc, int offset, u_int8_t val) offset * sc->sc_if_iospacing, val); } -void -_bmc_io_wait(void *arg) -{ - struct ipmi_softc *sc = arg; - struct ipmi_bmc_args *a = sc->sc_iowait_args; - - *a->v = bmc_read(sc, a->offset); - if ((*a->v & a->mask) == a->value) { - sc->sc_wakeup = 0; - wakeup(sc); - return; - } - - if (++sc->sc_retries > sc->sc_max_retries) { - sc->sc_wakeup = 0; - wakeup(sc); - return; - } - - timeout_add(&sc->sc_timeout, 1); -} - int -bmc_io_wait(struct ipmi_softc *sc, int offset, u_int8_t mask, u_int8_t value, - const char *lbl) -{ - volatile u_int8_t v; - struct ipmi_bmc_args args; - - if (cold) - return (bmc_io_wait_cold(sc, offset, mask, value, lbl)); - - sc->sc_retries = 0; - sc->sc_wakeup = 1; - - args.offset = offset; - args.mask = mask; - args.value = value; - args.v = &v; - sc->sc_iowait_args = &args; - - _bmc_io_wait(sc); - - while (sc->sc_wakeup) - tsleep(sc, PWAIT, lbl, 0); - - if (sc->sc_retries > sc->sc_max_retries) { - dbg_printf(1, "%s: bmc_io_wait fails : v=%.2x m=%.2x " - "b=%.2x %s\n", DEVNAME(sc), v, mask, value, lbl); - return (-1); - } - - return (v); -} - -int -bmc_io_wait_cold(struct ipmi_softc *sc, int offset, u_int8_t mask, - u_int8_t value, const char *lbl) +bmc_io_wait(struct ipmi_softc *sc, struct ipmi_iowait *a) { volatile u_int8_t v; int count = 5000000; /* == 5s XXX can be shorter */ while (count--) { - v = bmc_read(sc, offset); - if ((v & mask) == value) + v = bmc_read(sc, a->offset); + if ((v & a->mask) == a->value) return v; delay(1); } - dbg_printf(1, "%s: bmc_io_wait_cold fails : *v=%.2x m=%.2x b=%.2x %s\n", - DEVNAME(sc), v, mask, value, lbl); + dbg_printf(1, "%s: bmc_io_wait fails : *v=%.2x m=%.2x b=%.2x %s\n", + DEVNAME(sc), v, a->mask, a->value, a->lbl); return (-1); } -#define NETFN_LUN(nf,ln) (((nf) << 2) | ((ln) & 0x3)) +#define RSSA_MASK 0xff +#define LUN_MASK 0x3 +#define NETFN_LUN(nf,ln) (((nf) << 2) | ((ln) & LUN_MASK)) /* * BT interface @@ -381,7 +325,13 @@ bt_read(struct ipmi_softc *sc, int reg) int bt_write(struct ipmi_softc *sc, int reg, uint8_t data) { - if (bmc_io_wait(sc, _BT_CTRL_REG, BT_BMC_BUSY, 0, "bt_write") < 0) + struct ipmi_iowait a; + + a.offset = _BT_CTRL_REG; + a.mask = BT_BMC_BUSY; + a.value = 0; + a.lbl = "bt_write"; + if (bmc_io_wait(sc, &a) < 0) return (-1); bmc_write(sc, reg, data); @@ -392,6 +342,7 @@ int bt_sendmsg(struct ipmi_cmd *c) { struct ipmi_softc *sc = c->c_sc; + struct ipmi_iowait a; int i; bt_write(sc, _BT_CTRL_REG, BT_CLR_WR_PTR); @@ -399,8 +350,11 @@ bt_sendmsg(struct ipmi_cmd *c) bt_write(sc, _BT_DATAOUT_REG, sc->sc_buf[i]); bt_write(sc, _BT_CTRL_REG, BT_HOST2BMC_ATN); - if (bmc_io_wait(sc, _BT_CTRL_REG, BT_HOST2BMC_ATN | BT_BMC_BUSY, 0, - "bt_sendwait") < 0) + a.offset = _BT_CTRL_REG; + a.mask = BT_HOST2BMC_ATN | BT_BMC_BUSY; + a.value = 0; + a.lbl = "bt_sendwait"; + if (bmc_io_wait(sc, &a) < 0) return (-1); return (0); @@ -410,10 +364,14 @@ int bt_recvmsg(struct ipmi_cmd *c) { struct ipmi_softc *sc = c->c_sc; + struct ipmi_iowait a; u_int8_t len, v, i, j; - if (bmc_io_wait(sc, _BT_CTRL_REG, BT_BMC2HOST_ATN, BT_BMC2HOST_ATN, - "bt_recvwait") < 0) + a.offset = _BT_CTRL_REG; + a.mask = BT_BMC2HOST_ATN; + a.value = BT_BMC2HOST_ATN; + a.lbl = "bt_recvwait"; + if (bmc_io_wait(sc, &a) < 0) return (-1); bt_write(sc, _BT_CTRL_REG, BT_HOST_BUSY); @@ -504,10 +462,15 @@ int smic_read_data(struct ipmi_softc *, u_int8_t *); int smic_wait(struct ipmi_softc *sc, u_int8_t mask, u_int8_t val, const char *lbl) { + struct ipmi_iowait a; int v; /* Wait for expected flag bits */ - v = bmc_io_wait(sc, _SMIC_FLAG_REG, mask, val, "smicwait"); + a.offset = _SMIC_FLAG_REG; + a.mask = mask; + a.value = val; + a.lbl = "smicwait"; + v = bmc_io_wait(sc, &a); if (v < 0) return (-1); @@ -658,9 +621,14 @@ int kcs_read_data(struct ipmi_softc *, u_int8_t *); int kcs_wait(struct ipmi_softc *sc, u_int8_t mask, u_int8_t value, const char *lbl) { + struct ipmi_iowait a; int v; - v = bmc_io_wait(sc, _KCS_STATUS_REGISTER, mask, value, lbl); + a.offset = _KCS_STATUS_REGISTER; + a.mask = mask; + a.value = value; + a.lbl = lbl; + v = bmc_io_wait(sc, &a); if (v < 0) return (v); @@ -781,6 +749,8 @@ kcs_probe(struct ipmi_softc *sc) u_int8_t v; v = bmc_read(sc, _KCS_STATUS_REGISTER); + if ((v & KCS_STATE_MASK) == KCS_ERROR_STATE) + return (1); #if 0 printf("kcs_probe: %2x\n", v); printf(" STS: %2x\n", v & KCS_STATE_MASK); @@ -1019,8 +989,6 @@ ipmi_sendcmd(struct ipmi_cmd *c) c->c_txlen += sc->sc_if->datasnd; rc = sc->sc_if->sendmsg(c); - ipmi_delay(sc, 5); /* give bmc chance to digest command */ - done: return (rc); } @@ -1055,23 +1023,10 @@ ipmi_recvcmd(struct ipmi_cmd *c) c->c_rxlen); dbg_dump(10, " recv", c->c_rxlen, c->c_data); - ipmi_delay(sc, 5); /* give bmc chance to digest command */ - return (rc); } void -ipmi_delay(struct ipmi_softc *sc, int period) -{ - /* period is in 10 ms increments */ - if (cold) - delay(period * 10000); - else - while (tsleep(sc, PWAIT, "ipmicmd", period) != EWOULDBLOCK) - continue; -} - -void ipmi_cmd(struct ipmi_cmd *c) { if (cold || panicstr != NULL) @@ -1085,12 +1040,10 @@ ipmi_cmd_poll(struct ipmi_cmd *c) { mtx_enter(&c->c_sc->sc_cmd_mtx); - c->c_sc->sc_cmd = c; if (ipmi_sendcmd(c)) { panic("%s: sendcmd fails", DEVNAME(c->c_sc)); } c->c_ccode = ipmi_recvcmd(c); - c->c_sc->sc_cmd = NULL; mtx_leave(&c->c_sc->sc_cmd_mtx); } @@ -1141,6 +1094,7 @@ get_sdr_partial(struct ipmi_softc *sc, u_int16_t recordId, u_int16_t reserveId, c.c_cmd = STORAGE_GET_SDR; c.c_txlen = IPMI_SET_WDOG_MAX; c.c_rxlen = 0; + c.c_data = cmd; ipmi_cmd(&c); len = c.c_rxlen; @@ -1406,9 +1360,6 @@ read_sensor(struct ipmi_softc *sc, struct ipmi_sensor *psensor) u_int8_t data[8]; int rv = -1; - if (!cold) - rw_enter_write(&sc->sc_lock); - memset(data, 0, sizeof(data)); data[0] = psensor->i_num; @@ -1432,8 +1383,6 @@ read_sensor(struct ipmi_softc *sc, struct ipmi_sensor *psensor) psensor->i_sensor.flags |= SENSOR_FINVALID; psensor->i_sensor.status = ipmi_sensor_status(sc, psensor, data); rv = 0; - if (!cold) - rw_exit_write(&sc->sc_lock); return (rv); } @@ -1544,20 +1493,6 @@ add_child_sensors(struct ipmi_softc *sc, u_int8_t *psdr, int count, return (1); } -/* Interrupt handler */ -int -ipmi_intr(void *arg) -{ - struct ipmi_softc *sc = (struct ipmi_softc *)arg; - int v; - - v = bmc_read(sc, _KCS_STATUS_REGISTER); - if (v & KCS_OBF) - ++ipmi_nintr; - - return (0); -} - /* Handle IPMI Timer - reread sensor values */ void ipmi_refresh_sensors(struct ipmi_softc *sc) @@ -1599,11 +1534,6 @@ ipmi_map_regs(struct ipmi_softc *sc, struct ipmi_attach_args *ia) sc->sc_if->nregs * sc->sc_if_iospacing, &sc->sc_ioh); return (-1); } -#if 0 - if (iaa->if_if_irq != -1) - sc->ih = isa_intr_establish(-1, iaa->if_if_irq, - iaa->if_irqlvl, IPL_BIO, ipmi_intr, sc, DEVNAME(sc)); -#endif return (0); } @@ -1694,7 +1624,7 @@ ipmi_probe(void *aux) int ipmi_match(struct device *parent, void *match, void *aux) { - struct ipmi_softc sc; + struct ipmi_softc *sc; struct ipmi_attach_args *ia = aux; struct cfdata *cf = match; u_int8_t cmd[32]; @@ -1704,16 +1634,17 @@ ipmi_match(struct device *parent, void *match, void *aux) return (0); /* XXX local softc is wrong wrong wrong */ - mtx_init(&sc.sc_cmd_mtx, IPL_NONE); - strlcpy(sc.sc_dev.dv_xname, "ipmi0", sizeof(sc.sc_dev.dv_xname)); + sc = malloc(sizeof(*sc), M_TEMP, M_NOWAIT | M_ZERO); + mtx_init(&sc->sc_cmd_mtx, IPL_NONE); + strlcpy(sc->sc_dev.dv_xname, "ipmi0", sizeof(sc->sc_dev.dv_xname)); /* Map registers */ - if (ipmi_map_regs(&sc, ia) == 0) { - sc.sc_if->probe(&sc); + if (ipmi_map_regs(sc, ia) == 0) { + sc->sc_if->probe(sc); /* Identify BMC device early to detect lying bios */ struct ipmi_cmd c; - c.c_sc = ≻ + c.c_sc = sc; c.c_rssa = BMC_SA; c.c_rslun = BMC_LUN; c.c_netfn = APP_NETFN; @@ -1726,9 +1657,11 @@ ipmi_match(struct device *parent, void *match, void *aux) dbg_dump(1, "bmc data", c.c_rxlen, cmd); rv = 1; /* GETID worked, we got IPMI */ - ipmi_unmap_regs(&sc); + ipmi_unmap_regs(sc); } + free(sc, M_TEMP, sizeof(*sc)); + return (rv); } @@ -1737,6 +1670,7 @@ ipmi_attach(struct device *parent, struct device *self, void *aux) { struct ipmi_softc *sc = (void *) self; struct ipmi_attach_args *ia = aux; + struct ipmi_cmd *c = &sc->sc_ioctl.cmd; /* Map registers */ ipmi_map_regs(sc, ia); @@ -1768,14 +1702,10 @@ ipmi_attach(struct device *parent, struct device *self, void *aux) task_set(&sc->sc_wdog_tickle_task, ipmi_watchdog_tickle, sc); wdog_register(ipmi_watchdog, sc); - /* lock around read_sensor so that no one messes with the bmc regs */ - rw_init(&sc->sc_lock, DEVNAME(sc)); - - /* setup ticker */ - sc->sc_retries = 0; - sc->sc_wakeup = 0; - sc->sc_max_retries = 50; /* 50 * 1/100 = 0.5 seconds max */ - timeout_set(&sc->sc_timeout, _bmc_io_wait, sc); + rw_init(&sc->sc_ioctl.lock, DEVNAME(sc)); + sc->sc_ioctl.req.msgid = -1; + c->c_sc = sc; + c->c_ccode = -1; sc->sc_cmd_taskq = taskq_create("ipmicmd", 1, IPL_NONE, TASKQ_MPSAFE); mtx_init(&sc->sc_cmd_mtx, IPL_NONE); @@ -1793,6 +1723,149 @@ ipmi_activate(struct device *self, int act) return (0); } +struct ipmi_softc * +ipmilookup(dev_t dev) +{ + return (struct ipmi_softc *)device_lookup(&ipmi_cd, minor(dev)); +} + +int +ipmiopen(dev_t dev, int flags, int mode, struct proc *p) +{ + struct ipmi_softc *sc = ipmilookup(dev); + + if (sc == NULL) + return (ENXIO); + return (0); +} + +int +ipmiclose(dev_t dev, int flags, int mode, struct proc *p) +{ + struct ipmi_softc *sc = ipmilookup(dev); + + if (sc == NULL) + return (ENXIO); + return (0); +} + +int +ipmiioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *proc) +{ + struct ipmi_softc *sc = ipmilookup(dev); + struct ipmi_req *req = (struct ipmi_req *)data; + struct ipmi_recv *recv = (struct ipmi_recv *)data; + struct ipmi_cmd *c = &sc->sc_ioctl.cmd; + int iv; + int len; + u_char ccode; + int rc = 0; + + if (sc == NULL) + return (ENXIO); + + rw_enter_write(&sc->sc_ioctl.lock); + + c->c_maxrxlen = sizeof(sc->sc_ioctl.buf); + c->c_data = sc->sc_ioctl.buf; + + switch (cmd) { + case IPMICTL_SEND_COMMAND: + if (req->msgid == -1) { + rc = EINVAL; + goto reset; + } + if (sc->sc_ioctl.req.msgid != -1) { + rc = EBUSY; + goto reset; + } + len = req->msg.data_len; + if (len < 0) { + rc = EINVAL; + goto reset; + } + if (len > c->c_maxrxlen) { + rc = E2BIG; + goto reset; + } + sc->sc_ioctl.req = *req; + c->c_ccode = -1; + rc = copyin(req->msg.data, c->c_data, len); + if (rc != 0) + goto reset; + KASSERT(c->c_ccode == -1); + + /* Execute a command synchronously. */ + c->c_netfn = req->msg.netfn; + c->c_cmd = req->msg.cmd; + c->c_txlen = req->msg.data_len; + c->c_rxlen = 0; + ipmi_cmd(c); + + KASSERT(c->c_ccode != -1); + break; + case IPMICTL_RECEIVE_MSG_TRUNC: + case IPMICTL_RECEIVE_MSG: + if (sc->sc_ioctl.req.msgid == -1) { + rc = EINVAL; + goto reset; + } + if (c->c_ccode == -1) { + rc = EAGAIN; + goto reset; + } + ccode = c->c_ccode & 0xff; + rc = copyout(&ccode, recv->msg.data, 1); + if (rc != 0) + goto reset; + + /* Return a command result. */ + recv->recv_type = IPMI_RESPONSE_RECV_TYPE; + recv->msgid = sc->sc_ioctl.req.msgid; + recv->msg.netfn = sc->sc_ioctl.req.msg.netfn; + recv->msg.cmd = sc->sc_ioctl.req.msg.cmd; + recv->msg.data_len = c->c_rxlen + 1; + + rc = copyout(c->c_data, recv->msg.data + 1, c->c_rxlen); + goto reset; + case IPMICTL_SET_MY_ADDRESS_CMD: + iv = *(int *)data; + if (iv < 0 || iv > RSSA_MASK) { + rc = EINVAL; + goto reset; + } + c->c_rssa = iv; + break; + case IPMICTL_GET_MY_ADDRESS_CMD: + *(int *)data = c->c_rssa; + break; + case IPMICTL_SET_MY_LUN_CMD: + iv = *(int *)data; + if (iv < 0 || iv > LUN_MASK) { + rc = EINVAL; + goto reset; + } + c->c_rslun = iv; + break; + case IPMICTL_GET_MY_LUN_CMD: + *(int *)data = c->c_rslun; + break; + case IPMICTL_SET_GETS_EVENTS_CMD: + break; + case IPMICTL_REGISTER_FOR_CMD: + case IPMICTL_UNREGISTER_FOR_CMD: + default: + break; + } +done: + rw_exit_write(&sc->sc_ioctl.lock); + return (rc); +reset: + sc->sc_ioctl.req.msgid = -1; + c->c_ccode = -1; + goto done; +} + #define MIN_PERIOD 10 int @@ -1827,11 +1900,8 @@ void ipmi_watchdog_tickle(void *arg) { struct ipmi_softc *sc = arg; - int s; struct ipmi_cmd c; - s = splsoftclock(); - c.c_sc = sc; c.c_rssa = BMC_SA; c.c_rslun = BMC_LUN; @@ -1842,8 +1912,6 @@ ipmi_watchdog_tickle(void *arg) c.c_rxlen = 0; c.c_data = NULL; ipmi_cmd(&c); - - splx(s); } void @@ -1851,11 +1919,8 @@ ipmi_watchdog_set(void *arg) { struct ipmi_softc *sc = arg; uint8_t wdog[IPMI_GET_WDOG_MAX]; - int s; struct ipmi_cmd c; - s = splsoftclock(); - c.c_sc = sc; c.c_rssa = BMC_SA; c.c_rslun = BMC_LUN; @@ -1884,6 +1949,4 @@ ipmi_watchdog_set(void *arg) c.c_rxlen = 0; c.c_data = wdog; ipmi_cmd(&c); - - splx(s); } diff --git a/sys/dev/ipmi.h b/sys/dev/ipmi.h new file mode 100644 index 00000000000..81d6aa34498 --- /dev/null +++ b/sys/dev/ipmi.h @@ -0,0 +1,123 @@ +/*- + * Copyright (c) 2006 IronPort Systems Inc. <ambrisko@ironport.com> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _IPMI_H_ +#define _IPMI_H_ + +#define IPMI_MAX_ADDR_SIZE 0x20 +#define IPMI_MAX_RX 1024 +#define IPMI_BMC_SLAVE_ADDR 0x20 /* Linux Default slave address */ +#define IPMI_BMC_CHANNEL 0x0f /* Linux BMC channel */ + +#define IPMI_BMC_SMS_LUN 0x02 + +#define IPMI_SYSTEM_INTERFACE_ADDR_TYPE 0x0c +#define IPMI_IPMB_ADDR_TYPE 0x01 +#define IPMI_IPMB_BROADCAST_ADDR_TYPE 0x41 + +#define IPMI_IOC_MAGIC 'i' +#define IPMICTL_RECEIVE_MSG_TRUNC _IOWR(IPMI_IOC_MAGIC, 11, struct ipmi_recv) +#define IPMICTL_RECEIVE_MSG _IOWR(IPMI_IOC_MAGIC, 12, struct ipmi_recv) +#define IPMICTL_SEND_COMMAND _IOW(IPMI_IOC_MAGIC, 13, struct ipmi_req) +#define IPMICTL_REGISTER_FOR_CMD _IOW(IPMI_IOC_MAGIC, 14, struct ipmi_cmdspec) +#define IPMICTL_UNREGISTER_FOR_CMD _IOW(IPMI_IOC_MAGIC, 15, struct ipmi_cmdspec) +#define IPMICTL_SET_GETS_EVENTS_CMD _IOW(IPMI_IOC_MAGIC, 16, int) +#define IPMICTL_SET_MY_ADDRESS_CMD _IOW(IPMI_IOC_MAGIC, 17, unsigned int) +#define IPMICTL_GET_MY_ADDRESS_CMD _IOR(IPMI_IOC_MAGIC, 18, unsigned int) +#define IPMICTL_SET_MY_LUN_CMD _IOW(IPMI_IOC_MAGIC, 19, unsigned int) +#define IPMICTL_GET_MY_LUN_CMD _IOR(IPMI_IOC_MAGIC, 20, unsigned int) + +#define IPMI_RESPONSE_RECV_TYPE 1 +#define IPMI_ASYNC_EVENT_RECV_TYPE 2 +#define IPMI_CMD_RECV_TYPE 3 + +#define IPMI_APP_REQUEST 0x06 +#define IPMI_GET_DEVICE_ID 0x01 +#define IPMI_CLEAR_FLAGS 0x30 +#define IPMI_GET_MSG_FLAGS 0x31 +# define IPMI_MSG_AVAILABLE 0x01 +# define IPMI_MSG_BUFFER_FULL 0x02 +# define IPMI_WDT_PRE_TIMEOUT 0x08 +#define IPMI_GET_MSG 0x33 +#define IPMI_SEND_MSG 0x34 +#define IPMI_GET_CHANNEL_INFO 0x42 +#define IPMI_RESET_WDOG 0x22 +#define IPMI_SET_WDOG 0x24 +#define IPMI_GET_WDOG 0x25 + +#define IPMI_SET_WD_TIMER_SMS_OS 0x04 +#define IPMI_SET_WD_TIMER_DONT_STOP 0x40 +#define IPMI_SET_WD_ACTION_RESET 0x01 + +struct ipmi_msg { + unsigned char netfn; + unsigned char cmd; + unsigned short data_len; + unsigned char *data; +}; + +struct ipmi_req { + unsigned char *addr; + unsigned int addr_len; + long msgid; + struct ipmi_msg msg; +}; + +struct ipmi_recv { + int recv_type; + unsigned char *addr; + unsigned int addr_len; + long msgid; + struct ipmi_msg msg; +}; + +struct ipmi_cmdspec { + unsigned char netfn; + unsigned char cmd; +}; + +struct ipmi_addr { + int addr_type; + short channel; + unsigned char data[IPMI_MAX_ADDR_SIZE]; +}; + +struct ipmi_system_interface_addr { + int addr_type; + short channel; + unsigned char lun; +}; + +struct ipmi_ipmb_addr { + int addr_type; + short channel; + unsigned char slave_addr; + unsigned char lun; +}; + +#endif /* !_IPMI_H_ */ diff --git a/sys/dev/ipmivar.h b/sys/dev/ipmivar.h index 0e2bc938129..328047943af 100644 --- a/sys/dev/ipmivar.h +++ b/sys/dev/ipmivar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ipmivar.h,v 1.27 2016/01/12 10:44:32 uebayasi Exp $ */ +/* $OpenBSD: ipmivar.h,v 1.28 2016/02/05 06:29:01 uebayasi Exp $ */ /* * Copyright (c) 2005 Jordan Hargrave @@ -30,11 +30,12 @@ #ifndef _IPMIVAR_H_ #define _IPMIVAR_H_ -#include <sys/timeout.h> #include <sys/rwlock.h> #include <sys/sensors.h> #include <sys/task.h> +#include <dev/ipmi.h> + #define IPMI_IF_KCS 1 #define IPMI_IF_SMIC 2 #define IPMI_IF_BT 3 @@ -43,17 +44,16 @@ #define IPMI_IF_SMIC_NREGS 3 #define IPMI_IF_BT_NREGS 3 -#define IPMI_MAX_RX 1024 /* XXX ipmi_linux.h */ - struct ipmi_thread; struct ipmi_softc; struct ipmi_cmd; -struct ipmi_bmc_args{ +struct ipmi_iowait { int offset; u_int8_t mask; u_int8_t value; volatile u_int8_t *v; + const char *lbl; }; struct ipmi_attach_args { @@ -111,24 +111,21 @@ struct ipmi_softc { int sc_btseq; u_int8_t sc_buf[IPMI_MAX_RX + 16]; - struct ipmi_cmd *sc_cmd; struct taskq *sc_cmd_taskq; struct mutex sc_cmd_mtx; + struct ipmi_ioctl { + struct rwlock lock; + struct ipmi_req req; + struct ipmi_cmd cmd; + uint8_t buf[IPMI_MAX_RX]; + } sc_ioctl; + int sc_wdog_period; struct task sc_wdog_tickle_task; struct ipmi_thread *sc_thread; - struct timeout sc_timeout; - int sc_max_retries; - int sc_retries; - int sc_wakeup; - - struct rwlock sc_lock; - - struct ipmi_bmc_args *sc_iowait_args; - struct ipmi_sensor *current_sensor; struct ksensordev sc_sensordev; }; diff --git a/sys/sys/conf.h b/sys/sys/conf.h index 95212cb7569..0cc79da72ab 100644 --- a/sys/sys/conf.h +++ b/sys/sys/conf.h @@ -1,4 +1,4 @@ -/* $OpenBSD: conf.h,v 1.137 2016/01/27 09:04:19 reyk Exp $ */ +/* $OpenBSD: conf.h,v 1.138 2016/02/05 06:29:01 uebayasi Exp $ */ /* $NetBSD: conf.h,v 1.33 1996/05/03 20:03:32 christos Exp $ */ /*- @@ -475,6 +475,13 @@ extern struct cdevsw cdevsw[]; #endif +/* open, close, read, write, poll, ioctl, nokqfilter */ +#define cdev_ipmi_init(c,n) { \ + dev_init(c,n,open), dev_init(c,n,close), (dev_type_read((*))) enodev, \ + (dev_type_write((*))) enodev, dev_init(c,n,ioctl), \ + (dev_type_stop((*))) enodev, 0, (dev_type_poll((*))) enodev, \ + (dev_type_mmap((*))) enodev, 0 } + /* * Line discipline switch table */ @@ -606,6 +613,7 @@ cdev_decl(gpio); cdev_decl(amdmsr); cdev_decl(fuse); cdev_decl(pvbus); +cdev_decl(ipmi); #endif |