summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMasao Uebayashi <uebayasi@cvs.openbsd.org>2016-02-05 06:29:02 +0000
committerMasao Uebayashi <uebayasi@cvs.openbsd.org>2016-02-05 06:29:02 +0000
commit301f453b1544dd088417106b104584704927713d (patch)
treedce6673ee496ceef8e27e590f28a1df8db1f75dc
parent36c6b15245925ced646fdc8d2bf1972e10e38847 (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.c4
-rw-r--r--sys/arch/i386/i386/conf.c4
-rw-r--r--sys/dev/ipmi.c357
-rw-r--r--sys/dev/ipmi.h123
-rw-r--r--sys/dev/ipmivar.h27
-rw-r--r--sys/sys/conf.h10
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 = &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